cancel
Showing results for 
Search instead for 
Did you mean: 

STM32Cube USB middleware & Keil CMSIS RTOS RTX Causing HardFault - 'INVPC'

markdunstan9
Associate II
Posted on October 13, 2015 at 12:53

I have found that sometimes a HardFault occurs upon startup of my firmware. The specific fault is ''INVPC''. After doing some searching, there are multiple causes of this and I think, in my case, it is due to:

''4) ICI/IT bit invalid for current instruction.  This can happen when a multiple-load/store instruction gets interrupted and, during the interrupt handler, the stacked PC is modified.  When the interrupt return takes place, the non-zero ICI bit is applied to an instruction that do not use ICI bits.  The same problem can also happen due to corruption of stacked PSR.''

This is because after trying to debug the issue, it seems to always be triggered when the USB OTG FS interrupt is interrupting the osThreadYield functon of the RTOS right when the RTOS is doing an 'STM' instruction ('multiple-store') - which I think matches the above description. This fault (so far) has only occured in the first second after startup and using a USB Analyzer I have found that it occurs right before starting the first 'Bulk or Interrupt Transfer'. It also only occurs every 5-20 startups, making it very annoying to debug... 

My current (rough) solution is to disable the USB interrupt right before calling osThreadYield and enable it right after this again, but there are other issues in doing this (my current RTOS structure means most tasks are in a 'waiting' state for the majority of the time, resulting in the USB interrupt rarely being enabled) and I don't think this is the best solution , more of a sloppy work-around. It would be better (at least for my case) if the USB interrupt was disabled in a lower level function of the osTheadYield so that it gets enabled earlier, but I don't want to start digging into the Keil CMSIS RTOS RTX...

Is there something that I have missed, regarding USB and RTOS configuration etc to stop this? or is there another better / simpler solution?

Thanks in advance.         

6 REPLIES 6
Posted on October 13, 2015 at 14:34

If it's the stack corruption side of the equation, double check you have adequate stack allocations for the task(s)

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
markdunstan9
Associate II
Posted on October 13, 2015 at 18:06

Thanks for the advice clive.

I tried increasing the thread stack sizes (OS_STKSIZE & OS_MAINSTKSIZE) and doubling the stack size (to 0x0800) but it still had the same issue.

I am also using stack overflow checking (from the RTOS), but this has never occured. Finally I checked that in Keil's System and Thread Viewer that the maximum stack usage of any stack was always < 5% both when the HardFault occured and on a reset when it didn't occur.

FYI: I'm using the STM32F407VE

markdunstan9
Associate II
Posted on October 20, 2015 at 10:31

The area I'm questioning the most is the interrupt priorities. I've been playing around with PriorityGrouping being 4 bits for preemption (which is what the STM32Cube's HAL_Init() sets it to) or 2 bits preemption and 2 bits sub-priority.

The interrupt priorities I'm questioning are particularly the PendSV, SysTick, SVCall and the USB OTG FS IRQ. The first 3 are set by the CMSIS RTOS RTX (PendSV = SysTick = lowest priority, SVCall = almost the lowest). My other interrupts (2 timers) are higher than these but I have up until now set the USB OTG interrupt to be the lowest (= PendSV & SysTick) or at least lower than SVCall - which is resulting in the 'INVPC' HardFault every 5-20 startups (before the 'Bulk or Interrupt Transfer' according to my USB Analyzer). 

I have now found that if I make the USB interrupt priority higher (lower number) or equal to the SVCall interrupt priority, the HardFaut occurs every startup (still the same 'Bulk or Interrupt Transfer' according to the USB Analyzer) but the Keil Fault Reports window just says it was escalated to a HardFault with no Memory Manage Fault, Bus Faults or Usage Faults checked (ie not 'INVPC'... but maybe I shouldn't focus on this aspect...)

Has anyone had any issues like this? Could someone give me some guidance on what should be the right interrupt priority settings?

Currently the CMSIS RTOS sets the PendSV = SysTick = Lowest and SVCall = low (but not lowest). I have seen many forum threads mention that the PendSV priority should be the same as the SVCall priority (but the RTOS has set these itself).    

markdunstan9
Associate II
Posted on October 20, 2015 at 11:01

Further debugging info:

When USB OTG IRQ priority is higher or equal to the SVCall priority (when it gets the HardFault on every startup), it occurs at a different piece of code. It occurs in RTX_CM_Lib.h at:

/*--------------------------- _mutex_acquire --------------------------------*/

__attribute__((used)) void _mutex_acquire (OS_ID *mutex) {

  /* Acquire a system mutex, lock stdlib resources. */

  if (os_running) {

    /* RTX running, acquire a mutex. */

    mutex_wait (*mutex);  /* HARD FAULT OCCURS HERE */

  }

}

The assembly/C hybrid shows:

   230:     mutex_wait (*mutex); 

   231:   } 

0x08008CDC 6800      LDR           r0,[r0,#0x00]

0x08008CDE F64F71FF  MOVW          r1,#0xFFFF

0x08008CE2 F8DFC02C  LDR.W         r12,[pc,#44]  ; @0x08008D12

0x08008CE4 C02C     STM   r0!,{r2-r3,r5}

0x08008CE6 DF00      SVC           0x00

   232: } 

 Also, 'mutex_wait (*mutex)' is only called when the USB is connected. Connecting later after other startup functions means the function call / HardFault still occurs later and without connection this function is not called and no HardFault occurs. It looks like there are 2 HardFaults occuring in 2 different areas (1 if I set the USB priority higher than SVCall - which is what I think it should be, and one when it is a lower priority). This one looks (hopefully) easier to debug than the original one found.

markdunstan9
Associate II
Posted on October 20, 2015 at 14:23

This seems to be the problem I'm having (when the USB int priority is higher than SVCall):

https://developer.mbed.org/questions/60778/K64-UART-Interrupt-Handler-calls-Mutex_A/

Except in my case it's the USB interrupt handler and I don't want (or think I should have) to change to another USB middleware. This handler must somehow be calling mutex_acquire which calls mutex_wait and a HardFault is triggered as the mutex_wait is called inside the USB interrupt handler. So I need to work out where / how the USB handler is calling mutex_wait (a search doesn't show any results) and how to stop it from calling this or work around this...

Has anyone had this problem? I suppose everyone using the Keil CMSIS RTOS RTX and the STM32Cube USB Middleware should have the same issue. 

markdunstan9
Associate II
Posted on October 28, 2015 at 10:28

According to:

http://www.keil.com/support/man/docs/rlarm/rlarm_ar_hints_cortex.htm

I should be setting the USB IRQ priority higher than the SVCall interrupt as the lowest 2 priorities should be reserved for SVCall, PendSV and SysTick. Meaning the consistent HardFault (due to a mutex_acquire/wait function call) is the one I should focus on fixing. 

Once again, has anyone successfully implemented the STM32 Cube HAL USB Middleware with an RTOS without HardFaults occuring?

As I'm guessing that everyone using the middleware + (CMSIS) RTOS RTX or probably other RTOSs should have the same issue... I'm hoping of course that i've made a mistake so that I don't have to port the code to another middleware.