CMSIS_RTOS_RTX problem with timers

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
Hi,

I can't get the timer in CMSIS_RTOS_RTX to run.

Thread stack and callback size for the timers in RTX are big enough.

void timer1callback(void const *arguments) {
DIGITAL_IO_ToggleOutput(&led1);
}

osTimerDef(timer1, timer1callback);

int main(void) {
...
osTimerId id1 = osTimerCreate(osTimer(timer1), osTimerPeriodic, nullptr);
osStatus status = osTimerStart(id1, 1000);
...


I get a jump into the DefaultHandler with the last line.

Any hints?
0 Likes
15 Replies
User10215
Level 4
Level 4
First like received
Hi Holger,

just guessing here: the error might be due to id1 which you defined as a local variable. Can you check if it works when you make id1 a global variable? And can you see what the function "osTimerStart" returns? That might give a clue.

Regards,
Niclas
0 Likes
Not applicable
Hmm, why should it be a problem?
It is the same way as in the documentation:
http://www.keil.com/pack/doc/CMSIS/RTX/html/group___c_m_s_i_s___r_t_o_s___timer_mgmt.html#ga58f36b12...

I already found that using osTimerDef inside of main will fail osTimerCreate. This is due to a bug in RTX, the internal field for the timers is not initialized with { 0 } when created. osTimerDef global solves this problem.

osTimerStart seems ok (while debugging into RTX) and bails into the DefaultHandler as soon as the internal system call is done.
0 Likes
Not applicable
Still no help?

Jumped into DefaultHandler as soon as the SVC is called inside the osTimerStart.
0 Likes
User7921
Level 3
Level 3
I had similar problems when doing RTX stuff directly in main().

main() itself is a thread in this RTX, which will be deleted at the end if you don't have a while(1) in main.
If main is long and there is a task switch, then your timer var "id" is not visible to the the rest of the system, because the main thread is put to sleep.
All my RTX related vars are module static, but global. So adc.c or digital.c have there own static global RTX vars like semaphores or timer.
Did you start the OS without any errors in main() before you create the timer?

The more I work with this RTX, the more I see many disadvantages compared to other systems.
Even other stuff from the CMSIS is not coded correctly. E.g. the USIC module description talks about DMA access possibility. But there's none implemented...
And the SPI routines are very slow. I went back to the Infineon implementations.

Michael
0 Likes
Not applicable
The DAVE implementation of RTX (which I use) does not use the main thread.

osKernelStart() never returns (as expected). There is no need for a while(1). Main will not get deleted.

And for the record. Even if I do it global it fails the same way.
0 Likes
User7921
Level 3
Level 3
Create a "Initialising" thread and create the timer there. Set the stack size high enough.
Just give it a try.
When osKernelStart() does not return, is your
status = osTimerStart(id1, 1000);

before you call osKernelStart()?

My OS init looks like this, but I use the native RTX from Keil:

if (osKernelInitialize () == osOK)      // check osStatus for other possible valid values  {
if (!osKernelRunning ()) // is the kernel running ?
{
if (osKernelStart () != osOK) // start the kernel (this RTX function really does return...)
{
__breakpoint(0); // Break into the debugger
}
else
{
/*----------------------------------------------------------*/
/* System Initialisations */
/*----------------------------------------------------------*/
SytemStartupFunction(osPriorityAboveNormal); /*-------------*/
/*----------------------------------------------------------*/
}
}
else
{
__breakpoint(0); // Break into the debugger
}
}
else
{
__breakpoint(0); // Break into the debugger
}



Michael
0 Likes
Not applicable
I am close to my holiday and got no time to build an example. I will be back after easter. 🙂
Yes. osKernelStart is the last line inside main in my above code example.
And even if I define osTimerId inside or outside of main osTimerStart leads to an HardFault. The error is inside the SVC inside the RTX.

Try it with an DAVE-CE Project with CMSIS-RTX-App added. Be carefull. There will be no main thread.
0 Likes
User7921
Level 3
Level 3
This is how my SVT table looks like:

;/*----------------------------------------------------------------------------; * RL-ARM - RTX
; *----------------------------------------------------------------------------
; * Name: SVC_TABLE.S
; * Purpose: Pre-defined SVC Table for CORTEX M3
; * Rev.: V4.70
; *----------------------------------------------------------------------------
; * This code is part of the RealView Run-Time Library.
; * Copyright (c) 2004-2014 KEIL - An ARM Company. All rights reserved.
; *---------------------------------------------------------------------------*/




AREA SVC_TABLE, CODE, READONLY


EXPORT SVC_Count


SVC_Cnt EQU (SVC_End-SVC_Table)/4
SVC_Count DCD SVC_Cnt


; Import user SVC functions here.
IMPORT __SVC_1


EXPORT SVC_Table
SVC_Table
; Insert user SVC functions here. SVC 0 used by RTL Kernel.
DCD __SVC_1 ; user SVC function


SVC_End


END


/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/




Table index 0 is used by the RTX.
My function has index 1.

Did you add a function?
If so, be sure not to use index 0.

Schöne Ostern!

Michael
0 Likes
Not applicable
The DAVE-CE CMSIS-RTX port includes a complete handling of the SVC0 with the timer and other stuff integrated there. Please try this port. I got problems with this port and not with the RTX directly from Keil.
0 Likes
jferreira
Employee
Employee
10 sign-ins 5 sign-ins First like received
HI,

As stated in the CMSIS RTOS RTX manual, you need to start the timer in a thread.

#include //Declarations from DAVE Code Generation (includes SFR declaration)

osThreadId thread_id;
osTimerId timer_id;


void Timer1_Callback(void const *arg)
{
DIGITAL_IO_ToggleOutput(&LED1);
}

osTimerDef(Timer1, Timer1_Callback);


void Thread_1(void const *arg)
{
osTimerStart(timer_id, 1000);

while(1);
}
osThreadDef(Thread_1, osPriorityNormal, 1, 0);

/**

* @brief main() - Application entry point
*
* Details of function

* This routine is the application entry point. It is invoked by the device startup code. It is responsible for
* invoking the APP initialization dispatcher routine - DAVE_Init() and hosting the place-holder for user application
* code.
*/

int main(void)
{
DAVE_STATUS_t status;

status = DAVE_Init(); /* Initialization of DAVE APPs */

if(status == DAVE_STATUS_FAILURE)
{
/* Placeholder for error handler code. The while loop below can be replaced with an user error handler. */
XMC_DEBUG("DAVE APPs initialization failed\n");

while(1U)
{

}
}

thread_id = osThreadCreate(osThread(Thread_1), NULL);
timer_id = osTimerCreate(osTimer(Timer1), osTimerPeriodic, NULL);

osKernelStart();
}

Let me know if this solves your problem.

Best regards,
Jesus
0 Likes
Not applicable
Ok, I will check it after my holidays.
0 Likes
User7921
Level 3
Level 3
That's what I mentioned at the beginning.

Michael
0 Likes
Not applicable
Did you get it work? I have the feeling that DAVE stuff (module) often does not work. And when it works, it does work together with others. It is very painful.
0 Likes
Not applicable
Yes, I got it to work.
The timers must be started/initialized AFTER osKernelStart().
As you recomended I start a main_tread() directly before osKernelStart() and in main_thread() I can use the timers as expected.
0 Likes
Not applicable
I written the binding to FreeRTOS and there is not any more problem in case of simple test.
0 Likes