Hard fault when exiting stop mode with RTC alarm on STM32F051
Posted: Thu Sep 05, 2019 11:01 pm
Hi, I am trying to write a function that will enter the stop mode for a specified time and then return, but I keep getting hard faults. Can someone look what's going on there? Here is my code:
The backtrace after a crash looks like this:
And here is assemly code from where the program is crashing:
I am using gcc-arm-none-eabi-5_4-2016q3 as a compiler, and using RT-STM32F051-DISCOVERY demo from ChibiOS_19.1.3 as a template for my project, the only changes are:
in halconf.h and
in the Makefile. It is also possible to reproduce with USE_LTO = yes, just a little harder.
The problem itself is timing dependent, depending on the number of nops in two places the program can work as intended, crash with hard fault or stuck in the infinite loop in RTC_Wait
The program is also usualy works without crashing the first time after the power up, but starts chashing after reset.
Right now I am testing this on the STM32F0discovery board, but I originaly encountered the problem on a different board with STM32F051K6U6 mcu, and also tested on the third board with STM32F051C8T6
Code: Select all
#include "ch.h"
#include "hal.h"
void HardFault_Handler(void)
{
while(1)
{
}
}
volatile bool lexit=false;
void alarmcb(RTCDriver *rtcp, rtcevent_t event)
{
(void)rtcp;
(void)event;
lexit=true;
}
__attribute__((always_inline)) inline void nop(void)
{
asm volatile("nop");
}
void RTC_Wait(int tms)
{
rtcSetCallback(&RTCD1, alarmcb);
nop();
nop();
//nop();
//nop();
RTC->CR&=~RTC_CR_ALRAE; // disable Alarm A
while(!(RTC->ISR&RTC_ISR_ALRAWF));
RTC->ALRMAR=RTC_ALRMAR_MSK4|RTC_ALRMAR_MSK3|RTC_ALRMAR_MSK2|RTC_ALRMAR_MSK1; // do not use ALRMAR
int ms=RTC->SSR; // get current value from sub second register and add delta
ms-=tms; //
if(ms<0) //
ms+=1000; //
RTC->ALRMASSR=ms|RTC_ALRMASSR_MASKSS; // match all bits in sub second register
RTC->CR=RTC_CR_ALRAE|RTC_CR_ALRAIE; // enable Alarm A, enable Alarm A interrupt
PWR->CR|=(/*PWR_CR_PDDS|*/PWR_CR_LPDS|PWR_CR_CSBF|PWR_CR_CWUF); // configure stop mode
SCB->SCR|=SCB_SCR_SLEEPDEEP_Msk; //
while(1)
{
syssts_t status=osalSysGetStatusAndLockX();
if(lexit)
{
osalSysRestoreStatusX(status);
break;
}
__WFI();
nop();
//nop();
osalSysRestoreStatusX(status);
}
SCB->SCR&=~SCB_SCR_SLEEPDEEP_Msk;
stm32_clock_init();
}
int main(void)
{
DBGMCU->CR |= DBGMCU_CR_DBG_STOP; // enable debugging in stop mode
halInit();
chSysInit();
RTC_Wait(100); // enter stop mode
while(1)
{
}
}
The backtrace after a crash looks like this:
Code: Select all
#0 0x08001540 in HardFault_Handler [HardFault] () at main.c:6
#1 0x080015aa in nop () at main.c:25
#2 0x080015aa in RTC_Wait (tms=tms@entry=100) at main.c:63
#3 0x0800161a in main () at main.c:78
And here is assemly code from where the program is crashing:
Code: Select all
80015a6: bf30 wfi
80015a8: 46c0 nop ; (mov r8, r8)
80015aa: f7ff fc69 bl 8000e80 <chSysRestoreStatusX>
80015b2: 7823 ldrb r3, [r4, #0]
I am using gcc-arm-none-eabi-5_4-2016q3 as a compiler, and using RT-STM32F051-DISCOVERY demo from ChibiOS_19.1.3 as a template for my project, the only changes are:
Code: Select all
#define HAL_USE_RTC TRUE
in halconf.h and
Code: Select all
USE_LTO = no
in the Makefile. It is also possible to reproduce with USE_LTO = yes, just a little harder.
The problem itself is timing dependent, depending on the number of nops in two places the program can work as intended, crash with hard fault or stuck in the infinite loop in RTC_Wait
The program is also usualy works without crashing the first time after the power up, but starts chashing after reset.
Right now I am testing this on the STM32F0discovery board, but I originaly encountered the problem on a different board with STM32F051K6U6 mcu, and also tested on the third board with STM32F051C8T6