Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
9 years, 2 months ago.
K64 UART Interrupt Handler calls Mutex_Acquire
Trying to debug a problem where my UART Rx handler calls uart.getc() finally leading to HardFault_Handler() getting called everytime. Attached the error state from my Keil Debugger. .
I see that uart.getc() in my ISR routine calls serial_getc() which in turn calls serial_readable() , but the disassembly shows _mutex_acquire() getting called finally leading to HardFault_handler().
Below shows the stack trace indicating how _mutex_acquire() gets called
Stack trace mbed library with this snippet
_do _fflush: 0x0000F444 E92D41F0 PUSH {r4-r8,lr} 0x0000F448 4604 MOV r4,r0 0x0000F44A F100074C ADD r7,r0,#0x4C 0x0000F44E 4638 MOV r0,r7 0x0000F450 F7FEFE0B BL.W _mutex_acquire (0x0000E06A) // -> mutex_acquire finally leads to HardFault 0x0000F454 68E0 LDR r0,[r4,#0x0C] _ZN4mbed6Stream4getcEv: 0x00013010 B510 PUSH {r4,lr} 0x00013012 4604 MOV r4,r0 0x00013014 6940 LDR r0,[r0,#0x14] 0x00013016 F7FCFA3A BL.W fflush (0x0000F48E) // --> here the above fflush got called 0x0001301A 6960 LDR r0,[r4,#0x14] 0x0001301C E8BD4010 POP {r4,lr} uint8_t byte = bt_uart.getc(); 0x0000EA08 48BC LDR r0,[pc,#752] ; @0x0000ECFC 0x0000EA0A 303C ADDS r0,r0,#0x3C 0x0000EA0C F004FB00 BL.W _ZN4mbed6Stream4getcEv (0x00013010) // --> here the above Stream4getcEv 0x0000EA10 B2C4 UXTB r4,r0
Attaching my ISR routine for reference
ISR routine snippet
void HostioUartRxIRQHandler(void) { static uint8_t isRxBufferFull = 0; if(bt_uart.readable() && (isRxBufferFull == 0)) { uint8_t byte = bt_uart.getc(); //some logic to copy above byte into global buffer } }
I am running the standard RTOS CMSIS-RTX .
Can someone help me as to why this is happening ?
Secondly it will be nice to know why calling the standard UART serial api getc() function is leading to mutex_acquire() call ? As far as I know it is not a good practice to call mutex_acquire in an ISR routine as mutex_acquire calls mutex_wait which may sleep.
- YK
1 Answer
9 years, 2 months ago.
Worse, mutex acquire will fail because it is not allowed in ISR context, which probably causes your hard fault. This is simply happening because the C stdio lib has this mutex acquire call, and mbed Serial used the stdio lib.
Solution is to switch from Serial to RawSerial. This allows for getc/putc directly via the device registers, and skips the entire stdio layer. So besides being faster it also works with interrupts + RTOS, which normal Serial does indeed not do.
thanks Erik, but then all mbed UART serial ISR routines must have faced this problem. I do not see this problem on the STM boards where when we call getc and I never used RawSerial there but the mbed Serial.
posted by 07 Sep 2015@Yogesh, All mbed UART serial IRQ routines while also using RTOS suffer from this. It might be that it only happens when regular ARM instead of uARM lib is used, but that is something I haven't read about before! If thats the case, then STM ones might not have issues, since I believe for some reason they are all set at uARM (also don't know if thats still the case).
But in principle RawSerial was specifically introduced for your use case: Serial IRQs while using RTOS.
posted by 07 Sep 2015Hi Erik, Thank you for deeper clarification on this subject. Do you also recommend RawSerial (over Serial) in case of serial IRQs without RTOS? Cheers, Miloje
posted by 08 Sep 2015thanks Erik, you are very right. RawSerial did the trick and now there is no hardfault.
posted by 08 Sep 2015@Miloje: Serial can do everything, RawSerial has limitations (you can always manually program it, but it does not have the stdio connection Serial has, as random example: printf has been implemented, but not scanf. Also you cannot redirect a stdio stream to a RawSerial). The most used stuff is there (printf/putc/getc), it works with RTOS and it is faster/lighter than regular Serial.
So up to you what your requirements are :).
posted by 08 Sep 2015