[ag-automation] linux-2.6.26.8-rt16 clock_nanosleep + setting time

Mehlan, Markus Markus.Mehlan at ritter.info
Mon Oct 5 12:15:40 CEST 2009


Hello,

I have the following problem on a MPC5200b customer board:

In a cyclic task the watchdog timer is triggered every 200ms. If the
watchdog timer isn't triggered for more than 1 second, the processor
makes a reboot. This is the normal workings.

I start the application, the timeout is set to 10 seconds and every
200ms
I can see a new line on the console. Then I set the time with "date
100509152009"
a few times on a scond console. The effect is that the output on the
first console freezes
and if I check the time with "date", the time doesn't progress during
the "freeze time". 
After the "freeze time" the time makes a jump of several seconds.

If the watchdog timeout is set to 1 second, this strange behavior causes
a reboot.
I've tested this behavior with linux-2.6.24.7-rt11 and 2.6.26.8-rt16.

Has someone an idea?

With friendly regards,
Markus Mehlan


---------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <time.h>
#include <sys/time.h>
#include <linux/watchdog.h>
#include <pthread.h>
#include <sys/mman.h>

#define CTRL_TASK_PRIORITY		5
#define USEC_PER_SEC   1000000
#define NSEC_PER_SEC   1000000000

#ifndef max
#define max(a, b)	((a > b) ? a : b)
#endif


#define WATCHDOG_DEVICE_PATH     "/dev/watchdog"

static int fd_drv_wdg;

static void tsnorm(struct timespec *ts)
{
	while (ts->tv_nsec >= NSEC_PER_SEC)
	{
		ts->tv_nsec -= NSEC_PER_SEC;
		ts->tv_sec++;       
	}
}

double SysGetHighResTime(char bDummy)
{
  struct timespec now;
  clock_gettime (CLOCK_REALTIME, &now);   
  return (double) now.tv_sec*1000000 +  now.tv_nsec/1000;
}

/* 
 * Starte watchdog-Timer und setze Timeout
 * Parameter: int timeout[ms]
 */
int el392WatchdogSetTimeout(int timeout)
{
	double t1;
	unsigned long us;
	time_t time1;
	struct tm *time2;
	
	fd_drv_wdg = open(WATCHDOG_DEVICE_PATH, O_RDWR);
    if (fd_drv_wdg < 0) {
    	printf("el392WatchdogSetTimeout() Error while openeing %s\n",
WATCHDOG_DEVICE_PATH);
    	return -1;
    }
	
	if (ioctl(fd_drv_wdg, WDIOC_SETTIMEOUT, &timeout)) {
		printf("el392WatchdogSetTimeout() Error
ioctl->WDIOC_SETTIMEOUT: %s\n", WATCHDOG_DEVICE_PATH);
   		close(fd_drv_wdg);
   		return -2;
	}

	return 0;	
}

int el392WatchdogPing(void)
{	
    if (fd_drv_wdg < 0) {
    	printf("el392WatchdogPing() Error while openeing %s\n",
WATCHDOG_DEVICE_PATH);
    	return -1;
    }

	if (ioctl(fd_drv_wdg, WDIOC_KEEPALIVE)) {
		printf("el392WatchdogPing() Error
ioctl->WDIOC_KEEPALIVE: %s\n", WATCHDOG_DEVICE_PATH);
       	//close(fd_drv_wdg);
       	return -2;
	}

	return 0;	
}


void *PingTask()
{
	static unsigned long ulHwWdgTime = 0;			
	struct itimerspec timer;
	struct itimerspec timer2;
	int i;
	unsigned long ulInterval = 1000; // = 1ms
	
	if(clock_gettime(CLOCK_MONOTONIC, &timer.it_value) < 0)
	{
		perror("TimerTask: clock_gettime() failed\n");
		//return -1;
	}
	
	el392WatchdogSetTimeout(1000);
	
	timer.it_interval.tv_nsec = ulInterval % USEC_PER_SEC;
	timer.it_interval.tv_nsec *= 1000;
	timer.it_interval.tv_sec = ulInterval / USEC_PER_SEC;
	printf("timer.it_value.tv_nsec:%lu timer.it_value.tv_sec:%lu\n",

			timer.it_value.tv_nsec, timer.it_value.tv_sec);
	printf("timer.it_interval.tv_nsec:%lu
timer.it_interval.tv_sec:%lu\n", 
			timer.it_interval.tv_nsec,
timer.it_interval.tv_sec);
	
	while(1) {
		timer.it_value.tv_sec += timer.it_interval.tv_sec;
		timer.it_value.tv_nsec += timer.it_interval.tv_nsec;
		tsnorm(&timer.it_value);
		
		if (ulHwWdgTime == 0)
		{
			el392WatchdogPing();
			
			ulHwWdgTime = 200; // 200ms
					
			clock_gettime(CLOCK_MONOTONIC,
&timer2.it_value);
			printf("ulHwWdgTime:%lu timer.v.nsec:%lu
timer.v.sec:%lu timer2.v.nsec:%lu timer2.v.sec:%lu\n", 
				ulHwWdgTime, timer.it_value.tv_nsec,
timer.it_value.tv_sec,
				             timer2.it_value.tv_nsec,
timer2.it_value.tv_sec);
		}	
		ulHwWdgTime--;
		
		if (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
&timer.it_value, NULL))
			printf("-F-ulHwWdgTime:%lu
timer.it_value.tv_nsec:%lu timer.it_value.tv_sec:%lu\n", 
			ulHwWdgTime, timer.it_value.tv_nsec,
timer.it_value.tv_sec);
	}	

}


int main(int argc, char **argv)
{
	pthread_attr_t attr;
	pthread_t	threadHandle;
	void *thread_result;
	struct sched_param sched_param;
  	int res;
  	unsigned char byPriority = CTRL_TASK_PRIORITY;
	  
    pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	   
 	if (pthread_create(&threadHandle, &attr, PingTask, NULL) != 0)
    {	
    	printf("Fehler pthread_create\n");
    	if (fd_drv_wdg)	
    		close(fd_drv_wdg);
    	return -3;
    }
    
	sched_param.sched_priority =
max(0,sched_get_priority_max(SCHED_FIFO) - (int)byPriority);
	if ((res=pthread_setschedparam
((pthread_t)threadHandle,SCHED_FIFO,&sched_param)))
	{
		printf("SysTaskSetPriority->pthread_setschedparam()
failed:%s\n",strerror(res));
		if (fd_drv_wdg)	
			close(fd_drv_wdg);
		return -4;
	}
  	pthread_attr_destroy(&attr);
  	  	
  	printf("Ende\n");
  	getchar();
	
	if (fd_drv_wdg)				
		close(fd_drv_wdg);
	return 0;
}



Sitz der Gesellschaft: Oberhausen
Handelsregister Amtsgericht Duisburg HRB-Nr. 17168 UST ID-Nr. DE 814009849
Geschaftsfuehrer: Manfred A. Wagner und Dr. Uwe Baader




More information about the ag-automation mailing list