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.

Issue when using SysTick on Tiva TM4C123GH6PGE

Other Parts Discussed in Thread: SYSBIOS

Hi guys,

I am getting stuck when using SysTick. Here is my setting:

1
2
3
4
5
6
7
uint32_t freq = SysCtlClockGet();
printf("CPU freq: %d", freq); fflush(stdout);
 
SysTickPeriodSet(SysCtlClockGet() / 5);
//SysTickIntRegister(&SysTickIntHandler);
SysTickIntEnable();
SysTickEnable();

I got the error:

ti.sysbios.family.arm.m3.Hwi: line 1120: E_noIsr: id = 15, pc = 00008c22
Exception occurred in background thread at PC = 0x00008c22.
Core 0: Exception occurred in ThreadType_Task.
Task name: ti.sysbios.knl.Task.IdleTask, handle: 0x200071a8.
Task stack base: 0x20003860.
Task stack size: 0x800.
R0 = 0x00000090 R8 = 0xffffffff
R1 = 0x00000044 R9 = 0xffffffff
R2 = 0x00000890 R10 = 0xffffffff
R3 = 0x00000000 R11 = 0xffffffff
R4 = 0x00011d00 R12 = 0x00000020
R5 = 0x00011d00 SP(R13) = 0x20004010
R6 = 0x00000001 LR(R14) = 0x00008c19
R7 = 0x00011cf4 PC(R15) = 0x00008c22
PSR = 0x21000000
ICSR = 0x0042380f
MMFSR = 0x00
BFSR = 0x00
UFSR = 0x0000
HFSR = 0x00000000
DFSR = 0x0000000b
MMAR = 0xe000ed34
BFAR = 0xe000ed38
AFSR = 0x00000000
Terminating execution...


It seems that program could not point to ISR handler when systick interrupt occurred. The interrupt vector might not be defined.

Could you help me how to add the interrupt handler (SysTickIntHandler) into vector table in my application?

PS: I am using Tiva TM4C123GH6PGE

Thank you!

Tin Phan

  • sys/bios uses a Stellaris/Tiva timer peripheral (as opposed to sys/tick) for its system clock by default.  

    I'm not sure how to reconfigure this with XGCONF, but try manually adding the following to your sys/bios app.cfg file:

    var Timestamp = xdc.useModule('xdc.runtime.Timestamp');
    var halTimer = xdc.useModule('ti.sysbios.hal.Timer');

    var systick = xdc.useModule('ti.sysbios.family.arm.m3.Timer');
    var systickStamp = xdc.useModule('ti.sysbios.family.arm.m3.TimestampProvider');

    halTimer.TimerProxy = systick;

    Timestamp.SupportProxy = systickStamp;

    Sys/bios has configured the system clock_tick() function to be periodically called by halTimer.  The aforementioned snippets will tell halTimer to use the Cortex M3 systick module (M3 == M4 as far as systick is concerned) for its timer hardware.  I also included code to move time-stamping services to systick.  This frees up all Stellaris/Tiva timer peripherals for your app.

    With systick used as the system timer, sys/bios will install the appropriate handler for you.  Note, however, that you should NOT reconfigure the hardware directly if sys/bios is managing it.  You should use sys/bios API's for reconfiguring the timer.

    Sys/bios will know the clock rate driving systick (same as CPU core frequency).  So, to set the period of your tick you can add the following to your app.cfg:

    Clock = xdc.useModule('ti.sysbios.knl.Clock');
    Clock.tickPeriod = 1000;  // in uS

    Hope that helps!

    --Miles

  • Hi Miles,

    Thank for your help!

    I followed your suggestion to create a 1 second timer.

    My app.cfg for Clock tick:

    var Timer = xdc.useModule('ti.sysbios.family.arm.lm4.Timer');

    var Clock = xdc.useModule('ti.sysbios.knl.Clock');

    Clock.tickPeriod = 1000;

    var clock0Params = new Clock.Params();
    clock0Params.instance.name = "clock0";
    clock0Params.period = 1000;
    clock0Params.startFlag = true;
    Program.global.clock0 = Clock.create("&myClock", 10, clock0Params);

    And "myClock" function:

    Void myClock(UArg arg)
    {
          cur_epoch_time++; //Incresed every 1sec
          printf("Epoch second = %d\n", cur_epoch_time); flush(stdout);

    }

    Function "myClock" will be invoked every 1000usx1000 (Clock.tickPeriod x clock0Params.period) = 1second. Is this right? But when I check the "cur_epoch_time" value on console, there was a bit delay compare to the second of my PC clock. I dumped the CPU core freq, it is 80MHz.

    Do yu have any idea? Is there possibility that printf command caused this delay?

    I also tried with Timer:

    var Timer = xdc.useModule('ti.sysbios.family.arm.lm4.Timer');
    var timer0Params = new Timer.Params();
    timer0Params.instance.name = "timer0";
    timer0Params.period = 1000000;
    Program.global.timer0 = Timer.create(1, "&myTimer", timer0Params);

    But got the same result (delay).

    Thank you,

    Tin Phan

  • Jack Phan1 said:
    Function "myClock" will be invoked every 1000usx1000 (Clock.tickPeriod x clock0Params.period) = 1second. Is this right?

    Correct 

    Jack Phan1 said:
    Is there possibility that printf command caused this delay?

    Yes.  The reason is that the default behavior for printf() is provided by the module SysMin.  SysMin provides a buffer into which STDOUT output is placed.  When you call fflush(), the CPU is stopped and the debugger marshals the data over the JTAG.  This is a very slow process.

    Since systick is part of the CPU, when the CPU stops sys/tick stops counting.  Thus, while you're flushing your STDOUT buffer your clock is drifting.  If you rework your code so that you only do a printf() at the end of, say, a 10 second period, you'll find far less drift.

    As an interesting side note: I tried placing my printf() inside the myClock() function (as you had) and encountered a sys/bios gate exception.  I wasn't surprised since myClock() runs in the sys/bios SWI context and a fflush() in that context could cause all sorts of nasty things to happen.  I'm not sure how you got away with it.  But, in any case, be careful where you put the fflush().  I'd recommend having it in a thread context.

    When you moved from the clock to the timer you might have expected better results.  But, as it turns out, sys/bios configured the timer to stop ticking when the CPU stops.  To verify, check out TIMERx_CTL register, bits 1 and 9.  So you were affected by an analogous problem.

    Try routing your STDOUT to a UART and see if your timing doesn't improve.

    --Miles

  • Hi Miles,

    Stellaris Miles said:

    As an interesting side note: I tried placing my printf() inside the myClock() function (as you had) and encountered a sys/bios gate exception.  I wasn't surprised since myClock() runs in the sys/bios SWI context and a fflush() in that context could cause all sorts of nasty things to happen.  I'm not sure how you got away with it.  But, in any case, be careful where you put the fflush().  I'd recommend having it in a thread context.

    You are correct. It will give out the bad context error. Actually, I called printf() in my task thread.

    My thread look like:

    /* For display TimeStamp */
    Void TIME_Handler(UArg arg0, UArg arg1) {
    
    	while (TRUE) {
    		/* Display current time */
    		struct tm now_time;
    
    		timer_tick = FALSE;
    		while (!timer_tick);  //Wait for timer tick
    
    		
    		ulocaltime(cur_epoch_time, &now_time);  //Convert epoch time to GMT+7
    
    		printf("\t<GMT+7> DATE: %d/%d/%d - TIME: %d:%d:%d \n",
    				now_time.tm_mday, (1 + now_time.tm_mon), (1900 + now_time.tm_year),
    				(GMT + now_time.tm_hour), now_time.tm_min, now_time.tm_sec);
    		fflush(stdout);
    		
    	}
    }

    My timer handler:

    Void myTimer(UArg arg)
    {
    	cur_epoch_time++;	//Incresed every 1sec
    	timer_tick = TRUE;
    
    	//Timer_getFreq(timer0, &freq1);	//RESULT: 80MHz
    }
    
    

    In thread, a loop will wait for timer tick every 1sec, then display the current time. But I got the delay as describe in the previous post. And as your suggestion, I increased the timer to 10sec period, it still a bit drift.

    As you said, the fflush() make CPU stopped and caused this delay. So If I don't use printf() and flush(), the timer will tick exactly every 1second as expected,  Is this right? And if I save the time value in SD card instead of print, it wold be the right time?

    One more unclear point, If I call fflush() in one thread, the other task thread will be "paused" also due to CPU stopped?

    Thank for your help!

    Tin Phan

  • Jack Phan1 said:
    As you said, the fflush() make CPU stopped and caused this delay. So If I don't use printf() and flush(), the timer will tick exactly every 1second as expected,  Is this right? And if I save the time value in SD card instead of print, it wold be the right time?

    The printf() should be fine (more or less).  The fflush() is the real problem.  Sending the time via any channel other than JTAG should eliminate the drift.  UART, SDcard, USB device, etc. should all yield correct timing.  Usually the bugs yield significant measurable drift.  For example configuring for a 16MHz crystal when a 12 MHz crystal is in use (conspicuously off by 25% or 33%), or thinking the PLL is on when only PIOSC is in use (40 or 80 MHz vs 16MHz).  If you're seeing mS to uS drift then that would indicate a bug in the BIOS tick handling.  Also, keep in mind that if you do too much work in interrupt context (> 1 timer period of work) you will miss a tick and drift.

    Jack Phan1 said:
    One more unclear point, If I call fflush() in one thread, the other task thread will be "paused" also due to CPU stopped?

    You're stopping the whole core, not just one thread.  So, yes.

    --Miles

     

  • Thank for your clear explaination Miles!