cancel
Showing results for 
Search instead for 
Did you mean: 

WFI() issue using Nucleo STM32G031K8 and uVision.

DRH
Associate III

Hi together,

I’m trying to start a new project using STM32G031. The final decision of the MCU isn’t made yet and therefore I’m currently testing the possibilities with the Nucleo STM32G031K8 board. I’m using the onboards USB debug interface. 

I start a new Keil uVision project and everything work as expected until I add WFI() at the end of my main loop. After adding it, I start a debug session and everything is fine. But after leaving this first debug session and trying to start it second one again, I got the error message “Invalid ROM table�?.

From that point it’s not possible to debug or even flash the MCU using uVision. I have to copy a hex file (strange that it’s the same source) using the storage bootloader and after that it’s possible to start a new debug session. Unfortunately with the same result, that after leaving it and trying to debug again, I got this error message.

I’m checked all ideas and tips I found here, check different “Connect and Reset Options�? because this looks to solve the “Invalid ROM table�? error for some other users, but had no success.

All programs and interfaces are updated to the current version. Currently I’m reading about DBGMCU_CR register options but I’m not using standby or stop mode so I don’t think this will change the situation. At the moment, this register is in init state.

A second strange thing is, that the same situation occurs if I use an example software provided by ST. If I use

STM32Cube_FW_G0_V1.4.0\Projects\NUCLEO-G031K8\Examples_LL\PWR\PWR_EnterStandbyMode

and delete “ LL_LPM_EnableDeepSleep();�? in line 273, I got the same result.

Maybe there is a clock or interrupt issue. Currently I’m using HSI.

Does anybody have an idea or hint where to start? Sure, I can try to switch off WFI() in debug mode, but this is only a quick & dirty fix.

I’m happy about any idea. Thank you so much. 

1 ACCEPTED SOLUTION

Accepted Solutions
DRH
Associate III

Hi all,

to anybody that have the same issue. It looks like I missed to switch on the DBGMCU clock....

LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DBGMCU);

I have to make further investigation but this seems to have been the issue. Please excuse that it looks like there was a second issue behind my eyes.

View solution in original post

19 REPLIES 19
MM..1
Chief III

As first one cit def

Note

WFI is intended for power saving only. When writing software assume

that WFI might behave as a NOP operation.

Maybe you have more info , but i never use WFI in code. Real setup for WFI is only call power f. This result to assembly wfi.

example

while {

...

HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

...

}

or simmilar SLEEPMode.

DRH
Associate III

Thank you for your response. That's exactly why I use WFI(). The firmware is working interrupt triggered (by hardware or periodic timer) and I use WFI() at the end of my main loop to stop the core until the next interrupt triggers. I do this in different programs, e.g. for the STM32F3xx, and it works pretty well.

Please let me know if you see any issue with this idea. Maybe WFI() is really the wrong option to safe energy without entering Stop or Standby mode?

For the STM32F3, debugging works very good. But with the Nucleo STM32G032 including the integrated usb-debugger, I have to use NOP() instead, at least for debugging...

DRH
Associate III

...I think it's not important, but I'm using the LL library.

Doing things that turn off parts of the chip is not helpful to external logic trying to communicate with it.

Alter the behaviour to permit debugging, or check DBGMCU related settings/options.​

To 'debug' low power and realtime critical code consider non-invasive methods where telemetry and flow information are output to a terminal.​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Thank's. Mmh, it's working with the STM32F3xx pretty well, but maybe you are right. The difference may also be the debug hardware. With the STM32F3 I'm using a Segger programmer, but if I remember right, the bigger Nucleo provides the same possibilities...

Are you familiar with the STM32G031 MCU. I checked different DBGMCU options (actually there are only two bits, one Standby and one Stop) but don't see any effect. Do you know that DBGMCU change WFI() behavior as well? I don't find that information in the reference manual.

You can read more here interrupt - arm sleep mode entry and exit differences WFE, WFI - Stack Overflow

and here is writed too all cortex have this managed differently, then you need ...

I mean M4 can call this LL WFI an debug it. And as you can see M0+ dont. I mean when you need it as you write option to safe energy 

calling WFI() dont do any safe energy.

Use LL SLEEP or STOP mode.

DRH
Associate III

I'm confused. The reference manual said (40.9.1) "To enter low-power mode, the instruction WFI or WFE must be executed.". My understanding is, that the periphery is working but the core is stopped in sleep mode until the next task is necessary. This section said that debugging is possible in sleep mode as well.

Table 28 (Section 4.3.4) said, that for entry sleep mode, WFI is necessary? Again section 4.3.3. explains this low-power mode.

What do I understand wrong?

I'm referring on the reference manual RM0444 Rev 5.

?? Realy exist only __WFI() , this underscored functions is usable only for combine with asm and registers direct control.

Normal save energy >

void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
{
 800a220:	b480      	push	{r7}
 800a222:	b083      	sub	sp, #12
 800a224:	af00      	add	r7, sp, #0
 800a226:	6078      	str	r0, [r7, #4]
 800a228:	460b      	mov	r3, r1
 800a22a:	70fb      	strb	r3, [r7, #3]
  /* Check the parameters */
  assert_param(IS_PWR_REGULATOR(Regulator));
  assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
  
  /* Select the regulator state in Stop mode: Set PDDS and LPDS bits according to PWR_Regulator value */
  MODIFY_REG(PWR->CR, (PWR_CR_PDDS | PWR_CR_LPDS), Regulator);
 800a22c:	4b10      	ldr	r3, [pc, #64]	; (800a270 <HAL_PWR_EnterSTOPMode+0x50>)
 800a22e:	681b      	ldr	r3, [r3, #0]
 800a230:	f023 0203 	bic.w	r2, r3, #3
 800a234:	490e      	ldr	r1, [pc, #56]	; (800a270 <HAL_PWR_EnterSTOPMode+0x50>)
 800a236:	687b      	ldr	r3, [r7, #4]
 800a238:	4313      	orrs	r3, r2
 800a23a:	600b      	str	r3, [r1, #0]
  
  /* Set SLEEPDEEP bit of Cortex System Control Register */
  SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
 800a23c:	4b0d      	ldr	r3, [pc, #52]	; (800a274 <HAL_PWR_EnterSTOPMode+0x54>)
 800a23e:	691b      	ldr	r3, [r3, #16]
 800a240:	4a0c      	ldr	r2, [pc, #48]	; (800a274 <HAL_PWR_EnterSTOPMode+0x54>)
 800a242:	f043 0304 	orr.w	r3, r3, #4
 800a246:	6113      	str	r3, [r2, #16]
  
  /* Select Stop mode entry --------------------------------------------------*/
  if(STOPEntry == PWR_STOPENTRY_WFI)
 800a248:	78fb      	ldrb	r3, [r7, #3]
 800a24a:	2b01      	cmp	r3, #1
 800a24c:	d101      	bne.n	800a252 <HAL_PWR_EnterSTOPMode+0x32>
  {   
    /* Request Wait For Interrupt */
    __WFI();
 800a24e:	bf30      	wfi
 800a250:	e002      	b.n	800a258 <HAL_PWR_EnterSTOPMode+0x38>
  }
  else
  {
    /* Request Wait For Event */
    __SEV();
 800a252:	bf40      	sev
    __WFE();
 800a254:	bf20      	wfe
    __WFE();
 800a256:	bf20      	wfe
  }
  /* Reset SLEEPDEEP bit of Cortex System Control Register */
  CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));  
 800a258:	4b06      	ldr	r3, [pc, #24]	; (800a274 <HAL_PWR_EnterSTOPMode+0x54>)
 800a25a:	691b      	ldr	r3, [r3, #16]
 800a25c:	4a05      	ldr	r2, [pc, #20]	; (800a274 <HAL_PWR_EnterSTOPMode+0x54>)
 800a25e:	f023 0304 	bic.w	r3, r3, #4
 800a262:	6113      	str	r3, [r2, #16]
}

as you can see __ is part of this HAL. Your LL have other call functions for SLEEP or STOP mode , then use it and will see.

DRH
Associate III

I'm new with the G031 but I don't know and also find this "other call functions" for sleep mode.

There is no sleep mode example, but the standby mode example provided with the ST software package calls:

void EnterStandbyMode(void)
{
  /* Turn-off LED */
  /* Note: LED state at this step depends on blinking state at the instant of user button is pressed. */
  LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_6);
   
  /* Enable pull up on wakeup pin */
  /* Note: Setting not mandatory but recommended to avoid wake-up pin floating */
  LL_PWR_EnableGPIOPullUp(LL_PWR_GPIO_A, LL_PWR_GPIO_BIT_0);
  
  /* Enable pull-up and pull-down configuration */
  LL_PWR_EnablePUPDCfg();
  
  /* Set wakeup pin polarity */
  LL_PWR_SetWakeUpPinPolarityLow(LL_PWR_WAKEUP_PIN1);
 
  /* Enable wakeup pin */
  LL_PWR_EnableWakeUpPin(LL_PWR_WAKEUP_PIN1);
  
  /* As default LL_PWR_WAKEUP_PIN1 state is high level, need to clear all wake up Flag again */
  LL_PWR_ClearFlag_WU();
 
  /** Request to enter Standby mode
    * Following procedure describe in STM32G0xx Reference Manual
    * See PWR part, section Low-power modes, Standby mode
    */
  /* Set Standby mode when CPU enters deepsleep */
  LL_PWR_SetPowerMode(LL_PWR_MODE_STANDBY);
  
  /* Set SLEEPDEEP bit of Cortex System Control Register */
  LL_LPM_EnableDeepSleep();
  
  /* This option is used to ensure that store operations are completed */
#if defined ( __CC_ARM)
  __force_stores();
#endif
  /* Request Wait For Interrupt */
  __WFI();
}