Thursday, November 23rd 2017, 11:57am UTC+1

You are not logged in.

  • Login
  • Register

Dear visitor, welcome to SEGGER Forum. If this is your first visit here, please read the Help. It explains how this page works. You must be registered before you can use all the page's features. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

jimp

Beginner

Date of registration: Apr 27th 2011

Posts: 3

1

Thursday, April 28th 2011, 6:21pm

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.

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* Enable the USART3 Interrupt */ 
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQChannel; 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
NVIC_Init(&NVIC_InitStructure); 

/* Enable the USART Receive interrupt: this interrupt is generated when the 
USART1 receive data register is not empty */ 
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); 

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


void USART3_IRQHandler(void) 
{ 
char c; 
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) 
{ 
/* Read one byte from the receive data register */ 
c = USART_ReceiveData(USART3) & 0xFF; 
if (mbSerial.Id) // Make sure the mailbox is created 
OS_PutMailCond1(&mbSerial, &c); <====== This is where the error occurs 
} 
}

SEGGER - Til

Super Moderator

Date of registration: Nov 14th 2007

Posts: 261

2

Thursday, April 28th 2011, 6:37pm

Hello Jim,

Quoted

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/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.

Quoted

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

jimp

Beginner

Date of registration: Apr 27th 2011

Posts: 3

3

Friday, April 29th 2011, 1:20am

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

SEGGER - Til

Super Moderator

Date of registration: Nov 14th 2007

Posts: 261

4

Friday, April 29th 2011, 9:11am

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/C++ Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
void OS_COM_IsrHandler(void) {
  int Dummy;
  OS_EnterNestableInterrupt();
  Dummy = US_RHR;     
  // Call embOS API functions here
  OS_LeaveNestableInterrupt();
}

void Uart_Init(void) {
  OS_ARM_InstallISRHandler(ISR_ID_USART, (OS_ISR_HANDLER*) OS_COM_IsrHandler);
  OS_ARM_ISRSetPrio(140);                      // Set prio > 128
  OS_ARM_EnableISR(ISR_ID_USART);
}


Example of a zero latency interrupt function:

C/C++ Source code

1
2
3
4
5
6
7
8
9
10
11
void OS_COM_IsrHandler(void) {
  int Dummy;
  Dummy = US_RHR;     
  // Never call embOS API functions here
}

void Uart_Init(void) {
  OS_ARM_InstallISRHandler(ISR_ID_USART, (OS_ISR_HANDLER*) OS_COM_IsrHandler);
  OS_ARM_ISRSetPrio(120);                      // Set prio < 128
  OS_ARM_EnableISR(ISR_ID_USART);
}


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

jimp

Beginner

Date of registration: Apr 27th 2011

Posts: 3

5

Wednesday, May 4th 2011, 11:28pm

Til,



Thank you for the example. I was able to get things working.



Best regards,

Jim