This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SYSBIOS Timer and/or Clock jitter issue

Other Parts Discussed in Thread: SYSBIOS, AM3359

Hi everyone,

I am using the AM3359 with sysbios 1.1.0.6 . I need a loop every 1ms to make the motion control. I have tried with a clock module and a timing module and I get a big problem. Sometimes this is random , I measure the time the program is not in the function clock / timer to measure jitter and I get more than a second before the function is again call. I suppose to have 1ms outside the function ... The program can work very well until this error, for us, this timer is very critical and we need to minimize jitter to 0. Another thing I do not understand the timer unit has the highest priority in the system and it seems to be preempted by I do not know what.

thanks for helping me.

Eric

Log with the clock module below. The time outside of clock is "t = ..."

t = 0.001008s ,ival1 = 0, ival2 = -0
t = 0.001005s ,ival1 = 0, ival2 = -0
t = 0.001006s ,ival1 = 0, ival2 = -0
t = 0.001006s ,ival1 = 0, ival2 = -0
t = 0.001006s ,ival1 = 0, ival2 = -0
t = 1.030123s ,ival1 = 0, ival2 = -0
t = 0.000929s ,ival1 = 0, ival2 = -0

Log with the timermodule below. The time ouside of clock is "t = ..."

t = 0.000999s ,ival1 = 0, ival2 = -0
t = 0.000999s ,ival1 = 0, ival2 = -0
t = 0.000999s ,ival1 = 0, ival2 = -0
t = 0.000999s ,ival1 = 0, ival2 = -0
t = 0.000999s ,ival1 = 0, ival2 = -0
t = 0.000999s ,ival1 = 0, ival2 = -0
t = 1.244850s ,ival1 = 0, ival2 = -0
t = 0.000951s ,ival1 = 0, ival2 = -0

  • Hi Eric,

    Can you provide a sample application that demonstrates this? Also which version of SYS/BIOS are you using 1.1.06 does not make sense. It should be 6.xx.xx.xx.

    Todd

  • Hi Todd,

    Sorry for my mistakes.

    SYS/BIOS : 6.42.02.29

    Ind SDK : 1.1.0.6

    NDK : 2.24.03.35

    Below is the code :

    void createAxisService(void)
    {
    	// Init Error
    	Error_Block eb;
    	Error_init(&eb);
    
    #ifndef USE_TIMER
    	Clock_Params clockParams;
    	Clock_Params_init(&clockParams);
    	clockParams.period = OS_TICKS_IN_MILLI_SEC;	// every 1 ms
    	clockParams.startFlag = false;	// do not start immediately
    	hAxisService = Clock_create((Clock_FuncPtr) AxisService, 4* OS_TICKS_IN_MILLI_SEC, &clockParams, &eb);
    	if (hAxisService == NULL)
    	{
    		System_abort("Clock0 create failed");
    	}
    #else
    	// Setup timer clock
    	DMTimer6ModuleClkConfig();
    
    	/*Timer setup init*/
    	Timer_Params timerParams;
    	Timer_Params_init(&timerParams);
    
    	/*This is irrelevant since timeout value is received from the supervisor*/
    	timerParams.period 		= 1000;
    	timerParams.periodType	= Timer_PeriodType_MICROSECS;
    	//timerParams.arg = 1;
    	/*24 Mhz, care must be taken to ensure that this value
    	 * is modified if the source clock frequency is modified */
    	timerParams.extFreq.lo 	= 24000000;
    	timerParams.extFreq.hi 	= 0;
    	timerParams.startMode 	= Timer_StartMode_USER;
    
    	timerParams.instance->name = "AxisService";
    
    	uint8_t timerNum = 6-2; // Timer ID is 0 to 5, corresponding to timer 2 to 7
    	hAxisService = Timer_create(timerNum, AxisService, &timerParams,  &eb); /* DMTIMER6 */
    
    	if (hAxisService == NULL) {
    	 System_abort("Timer create failed");
    	}
    #endif
    }
    
    Void AxisService(UArg arg0)
    {
    	sStatus sStatus;
    	sCommande cmd_NC;
    
            // save the timer of a cycle loop
    	cmd_NC.arguments[0] = (float)Timer7Get();
    	Timer7Reset();
    
    
    	// RX & TX data structure
    	MotionDataStruct MotionDataRx[NUMAXIS], MotionDataTx[NUMAXIS];
    
    	// If we are waiting for a new trajectory element, go to check it in the mailbox
    	if(endOfTraj == true)
    	{
    		if(!Mailbox_pend(mbTrajElem_NC, &TrajElem_NC, BIOS_NO_WAIT))
    		{
    			// No more traj ? send the last command
    			RTCURawRequest(rtcuTx, rtcuRx);
    
                            // Send timer information to the uart queue to debug
    			cmd_NC.arguments[1] = (float)Timer7Get();
    			cmd_NC.arguments[2] = (float)MotionDataRx[1].ival1;
    			cmd_NC.arguments[3] = (float)MotionDataRx[1].ival2;
    			saveCmdMbox_NC(&cmd_NC,BIOS_NO_WAIT);
    
    			// finish here
    			return;
    		}
    		// starting a new trajectory
    		polyTn = 0.0;
    		polyIndex = 0;
    		endOfTraj = false;
    	}
    
    
    
    	// Send the command with TX data and get motion data
    	RTCURawRequest(rtcuTx, rtcuRx);
    
    
    // Send timer information to the uart queue to debug
    	cmd_NC.arguments[1] = (float)Timer7Get();  // save the time inside the service loop
    	cmd_NC.arguments[2] = (float)MotionDataRx[1].ival1;
    	cmd_NC.arguments[3] = (float)MotionDataRx[1].ival2;
    	saveCmdMbox_NC(&cmd_NC,BIOS_NO_WAIT);
    }

     

  • A couple things...

    1. I'm assuming you are starting the Clock or Timer somewhere else.

    2. What are the Timer7Get and Timer7Reset functions doing? Is this a different timer that you are using as a stopwatch. Is this managed by the kernel or by you? Could this timer be wrapping and giving incorrect information?

    3. Does the 1 second delay pattern repeat?

    4. Did you disable interrupts any place and could the duration that interrupts are disabled possibly be causing this?

    Todd

  • 1. Yes I start the clock or the timer when I know peripheral are initialized

    2. The Timer7Get and Timer7Reset are function to put the dmtimer 7 to zero and get the value. I use dmtimer 6 to calculate de delay. There is no interrupt, it is use un free run.

    void InitTimer7(void)
    {
    	DMTimer7ModuleClkConfig();
    	DMTimerPreScalerClkDisable(SOC_DMTIMER_7_REGS);
    	DMTimerReset(SOC_DMTIMER_7_REGS);
    	DMTimerCounterSet(SOC_DMTIMER_7_REGS, 0);
    	DMTimerModeConfigure(SOC_DMTIMER_7_REGS, DMTIMER_ONESHOT_NOCMP_ENABLE);
    //	DMTimerReloadSet(SOC_DMTIMER_7_REGS, 0xffffffff);
    //	DMTimerIntDisable(SOC_DMTIMER_7_REGS, DMTIMER_INT_OVF_EN_FLAG);
    //	DMTimerIntStatusClear(SOC_DMTIMER_7_REGS, DMTIMER_INT_OVF_EN_FLAG);
    	DMTimerEnable(SOC_DMTIMER_7_REGS);
    }
    
    uint32_t Timer7Get (void)
    {
    	return (DMTimerCounterGet(SOC_DMTIMER_7_REGS));
    }
    
    void Timer7Reset (void)
    {
    	DMTimerCounterSet(SOC_DMTIMER_7_REGS, 0);// reset counter value
    }

    3. I don't know if the delay pattern is repeated because I entering in fatal error with my peripherals connected  to, so all system stop.

    4. In no case I disable interrupt or swi or task. All the system is sync by semaphore for task management.

  • Let's focus on the Timer case. Your createAxisService function is going to be ran in the context of the interrupt. Can you add another Timer7Get at the end of createAxisService and do the math to make sure that it is not taking more time than you expect.

    Can you look in ROV to see what other interrupts are present in the system and post a snapshot of it (Hwi->Detailed in ROV). Also, select BIOS->Scan for errors... to make sure nothing fishy is going on.

    I'm assuming that no other code is calling Timer7Get, Timer7Reset or playing with the DMTimer7.


  • I don't understand about the timer7 question. The "createAxisService" is called only once. The "AxisService" is called periodically by the timer each 1ms. What is important is the service must be call with a minimum of jitter between 2 service. The time between the create and the service isn't important.

    Here is the ROV HWI screenshot:

    For the ROV Scan BIOS, there is nothing wrong.

    For the call of Timer7 get and reset, yes, indeed they are called only in the service loop.

    Regards.

  • My bad... I meant adding another Timer7Get at the end of "AxisService" and confirm the "AxisService" function is running as quickly as you expect it to (e.g. < 1ms). If this takes a long time to run, the next one will be delayed. Can you show the ROV for the timers also?

  • Hi Todd,

    Log : (t I+o = time between two calls of clock, t I = time of execution of the axisservice)

    t i+o = 0.001006s ,t  i = 0.000005s, ival1 = 0, ival2 = 0

    When I my program stuck, "t i+o" is more than 1 seconde and "t  i" is keeping the same value (approx. 5us).

    I took screenshot when I test with a clock(swi) instead of timer(hwi):

    clock :

    timer :

  • Hi Todd

    I look in the Hwi and I can find something weird.

    The problem is I don't have a Hwi in the compiler task and I when look in the Swi, there is a mention of compiler task too... This task wait a mailbox without doing anything else. Why a Hwi is created ?

    thanks

  • That looks pretty strange. Do the names change at some point? Your earlier snapshot of the Hwi module shows something very different.
  • Hi Todd,

    Finally ! I found the problem this morning. I use the NDK without XCONF because I have to manage IP configuration and other options. I never have this problem before because I never test the sysbios with critical timing. I solve by removing two line the in the NDK_stackThread initialization function. I was calling XCONF functions who configure IP in DHCP and after that, I was initialized the IP in static mode... I don't know the behavior inside the NDK, but since I remove these line the system is running without issue.

    Thanks for helping me.

    Eric

    Void NDK_stackThread(UArg arg0, UArg arg1)
    {
    	Clock_Params clockParams;
    	int rc;
    
    	/* Create the NDK heart beat */
    	Clock_Params_init(&clockParams);
    	clockParams.startFlag = TRUE;
    	clockParams.period = 100; /*Period set to 100 as we have 1000microsec tick period*/
    	Clock_create(&llTimerTick, clockParams.period, &clockParams, NULL);
    
    	/* THIS MUST BE THE ABSOLUTE FIRST THING DONE IN AN APPLICATION!! */
    	rc = NC_SystemOpen(NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT);
    	if (rc)
    	{
    		System_printf("NC_SystemOpen Failed (%d)\n",rc);
    		BIOS_exit(0);
    	}
    
    	/* Create and build the system configuration from scratch. */
    	hCfg = CfgNew();
    	if (hCfg != NULL)
    	{
    
    		/* add the ip module configuration settings. */
    		//ti_ndk_config_ip_init(hCfg);
    
    		/* add the Tcp module configuration settings. */
    		//ti_ndk_config_tcp_init(hCfg);
    
    	    // TCP Keep Interval (1 second)
    	    //   This is the time between TCP KEEP probes
    //		rc = 10;
    //	    CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_TCPKEEPINTVL,
    //	                 CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&rc, 0 );
    
    		/*
    		 *  Boot the system using this configuration
    		 *
    		 *  We keep booting until the function returns 0. This allows
    		 *  us to have a "reboot" command.
    		 */
    		do
    		{
    
    			/* The NC_NetStart() function does not return until
    			 * the stack session has terminated. */
    			rc = NC_NetStart(hCfg, Global_NetworkOpenHook, Global_NetworkCloseHook, Global_NetworkIPAddrHook);
    
    		} while (rc > 0);
    
    		/* Delete Configuration */
    		CfgFree(hCfg);
    	}
    	else
    	{
    		/* Close the OS */
    		NC_SystemClose();
    		System_flush();
    	}
    }