embOS OS_ERR_CPU_STATE_ISR_ILLEGAL (166)

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • embOS OS_ERR_CPU_STATE_ISR_ILLEGAL (166)

    First of all, I am an IAR PowerPAC customer but they don't have a forum like this. I know that PowerPAC is a rebranded Segger product, so I appreciate your assistance.

    I am running on an STM32F103ZE.

    I just recently upgraded my RTOS from PowerPAC rev 2.21 to 2.32. I am now getting an
    OS_ERR_CPU_STATE_ISR_ILLEGAL error in an ISR that I didn't get previously. It appears the error was never trapped in the 2.21 version. So how do I get around this one. From the Segger/IAR manuals and a posting on this forum about STM32 interrupt priorities, it looks like I can no longer call OS API routines within my ISRs. In the code snippet below my ISR for the UART fires on the receipt of a character and I want to post it as a mailbox message for a task to handle. All of the OS functions now generate the OS_ERR_CPU_STATE_ISR_ILLEGAL. I am at a loss how to fix this.

    The manuals say to call another ISR using OS_CallISR. This seems ineffecient. If I have to, how do you set up this other interrupt?

    None of the code examples provided with the install for the PowerPAC utilized an ISR sending a mailbox message or any kind of event. Do you have another code example how to set this up.

    I get the feeling there is something very simple I am overlooking but I just can't see it.

    Thanks,

    Jim

    ------------------------------------------------------------------------

    Below is the configuration of the hardware ISR for the UART.

    Brainfuck Source Code

    1. /* Enable the USART3 Interrupt */
    2. NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQChannel;
    3. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    4. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    5. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    6. NVIC_Init(&NVIC_InitStructure);
    7. /* Enable the USART Receive interrupt: this interrupt is generated when the
    8. USART1 receive data register is not empty */
    9. USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
    10. -----------------------------------------------------------------------
    11. void USART3_IRQHandler(void)
    12. {
    13. char c;
    14. if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
    15. {
    16. /* Read one byte from the receive data register */
    17. c = USART_ReceiveData(USART3) & 0xFF;
    18. if (mbSerial.Id) // Make sure the mailbox is created
    19. OS_PutMailCond1(&mbSerial, &c); <====== This is where the error occurs
    20. }
    21. }
    Display All
  • Hello Jim,

    From the Segger/IAR manuals and a posting on this forum about STM32 interrupt priorities, it looks like I can no longer call OS API routines within my ISRs.

    No, that's wrong! You have to differ between "embOS interrupts" and "zero latency interrupts". You are allowed to call embOS API function from embOS interrupts but not from zero lateny interrups.

    Instead of disabling interrupts when embOS does atomic operations, the interrupt level of the CPU is set to 128. Therefore all interrupt priorities lower than 128 can still be processed. Please note, that lower priority numbers define a higher priority. All interrupts with priority level from 0 to 127 are never disabled. These interrupts are named zero latency interrupts. You must not execute any embOS function from within a zero latency interrupt function.

    C Source Code

    1. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    Please set the interrupt priority level to a value greater than 128 and it will work.

    The manuals say to call another ISR using OS_CallISR. This seems ineffecient. If I have to, how do you set up this other interrupt?

    There is no need to use OS_CallISR(), please write your interrupt functions as normal C functions and add the entry to interrupt vector table.


    Best regards,
    Til
    Please read the forum rules before posting.

    Keep in mind, this is *not* a support forum.
    Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
    Should you be entitled to support you can contact us via our support system: segger.com/ticket/

    Or you can contact us via e-mail.
  • Thank you for your prompt reply. Unfortunately I'm a little confused. Most of what you quoted came straight from the manual, so I am not getting something. What is the difference between an "embOS interrupts" and a "zero latency interrupts"? Give me an example of each. How would you classify my UART interrupt?



    Let's try another example, too. Say I have a button on my device that is hooked to an input line on the processor and can generate an interrupt. I will want that ISR to post a character to a mailbox so I can process it by a pending task. Is this an embOS interrupt or a Zero latency?



    How do you make the ISR one and not the other so I can use the RTOS API?



    You suggestion to change NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority to be a number greater than 128 didn't seem to work. When I use any value other than zero I get an error of OS_ERR_SYS_STACK as soon as I start up the RTOS.



    Once again, I really appreciate your assistance. Thank you.



    Best regards,

    Jim
  • Hello Jim,

    the difference between an embOS interrupt and a zero latency interrupt is the interrupt priority level and the usage of OS_EnterInterrupt()/OS_LeaveInterrupt() or OS_EnterNestableInterrupt()/OS_LeaveNestableInterrupt().

    Example of an embOS interrupt function:

    C Source Code

    1. void OS_COM_IsrHandler(void) {
    2. int Dummy;
    3. OS_EnterNestableInterrupt();
    4. Dummy = US_RHR;
    5. // Call embOS API functions here
    6. OS_LeaveNestableInterrupt();
    7. }
    8. void Uart_Init(void) {
    9. OS_ARM_InstallISRHandler(ISR_ID_USART, (OS_ISR_HANDLER*) OS_COM_IsrHandler);
    10. OS_ARM_ISRSetPrio(140); // Set prio > 128
    11. OS_ARM_EnableISR(ISR_ID_USART);
    12. }
    Display All


    Example of a zero latency interrupt function:

    C Source Code

    1. void OS_COM_IsrHandler(void) {
    2. int Dummy;
    3. Dummy = US_RHR;
    4. // Never call embOS API functions here
    5. }
    6. void Uart_Init(void) {
    7. OS_ARM_InstallISRHandler(ISR_ID_USART, (OS_ISR_HANDLER*) OS_COM_IsrHandler);
    8. OS_ARM_ISRSetPrio(120); // Set prio < 128
    9. OS_ARM_EnableISR(ISR_ID_USART);
    10. }
    Display All


    Please use the embOS interrupt initializing functions or the CMSIS interrupt initializing functions since I can't know what your NVIC_* functions exactly do.
    I hope that makes it more clear.

    Best regards,
    Til
    Please read the forum rules before posting.

    Keep in mind, this is *not* a support forum.
    Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
    Should you be entitled to support you can contact us via our support system: segger.com/ticket/

    Or you can contact us via e-mail.