Skip to main content
luuuuuuu1
Associate
April 22, 2022
Solved

Can't disable backup domain write protection in PWR_CR1

Hey there,

I'm trying to access STM32G071's backup register TAMP_BKP0R, PWR_CR1 is set successfully, however I can't store anything in the backup register.

enum backup_reg{foo0, foo1, foo2, LOW_POWER_RESET};

      RCC_APBENR1 |= RCC_APBENR1_PWREN_MASK;

      /* Disabling backup domain write protection */

      PWR_CR1 |= PWR_CR1_DBP_MASK;

      /* RTC clock enable */

      RCC_BDCR |= RCC_BDCR_RTCSEL_MASK;

      RCC_BDCR|= RCC_BDCR_RTCEN_MASK;

      TAMP_BKP0R = LOW_POWER_RESET;

This topic has been closed for replies.
waclawek.jan
waclawek.janBest answer
Super User
April 22, 2022

20 replies

waclawek.jan
Super User
April 22, 2022

You probably don't need to enable the RTC kernel clock (in RCC_BDCR), but you do need to enable the RTC APB clock (in RCC_APBENR1).

By not using the CMSIS-mandated header, you run into risk that the symbols you've defined yourself may be defined incorrectly.

Read out and check/post content of relevant registers.

JW

luuuuuuu1
luuuuuuu1Author
Associate
April 22, 2022

First and foremost thanks for replying so quickly!!

Yes I've figured that out by now, I'm using the following configuration now:

The clock I've chosen for RTC (LSE) is up and running, yet the register is still locked...

enum backup_reg{foo0, foo1, foo2, LOW_POWER_RESET};

      RCC_APBENR1 |= RCC_APBENR1_PWREN_MASK + RCC_APBENR1_RTCAPBEN;

      /* Disabling backup domain write protection */

      PWR_CR1 |= PWR_CR1_DBP_MASK;

      RCC_BDCR |= RCC_BDCR_LSEON_MASK;

      RCC_BDCR |= RCC_BDCR_LSCOEN_MASK;

      RCC_BDCR |= RCC_BDCR_LSCOSEL_MASK;

      RCC_BDCR |= 0x100U;

      RCC_BDCR |= RCC_BDCR_RTCEN_MASK;

      /* After disabling backup domain write protection, write access to backup registers is granted */

      TAMP_BKP0R = LOW_POWER_RESET;

luuuuuuu1
luuuuuuu1Author
Associate
April 22, 2022

The RCC_BDCR register is configured as follows:

0x030081030693W00000LykJNQAZ.png

waclawek.jan
waclawek.janBest answer
Super User
April 22, 2022
luuuuuuu1
luuuuuuu1Author
Associate
April 22, 2022

Do you have an idea why my backup register gets erased after power loss? I thought the backup register was reset proof.

Piranha
Principal III
April 22, 2022

Reset and power loss is not the same thing. Backup registers can do the same as RTC - keep the values during reset, standby, shutdown and optionally can be powered by VBAT while all other power is removed.

And, by the way, generic RAM also is not impacted by a reset. It's your startup code that clears and initializes portions of it.

luuuuuuu1
luuuuuuu1Author
Associate
April 22, 2022

RCC_APBENR1 |= RCC_APBENR1_PWREN_MASK + RCC_APBENR1_RTCAPBEN;

Oh god.. I've used the bit position instead of the mask.

Thanks so much!

RCC_APBENR1 |= RCC_APBENR1_RTCAPBEN_MASK;

Piranha
Principal III
April 22, 2022

The code is still flawed, because it doesn't respect the RM0444 section 5.2.17:

The enable bit has a synchronization mechanism to create a glitch-free clock for the peripheral. After the enable bit is set, there is a 2-clock-cycle delay before the clock be active, which the software must take into account.

And because PWR peripheral is located on APB bus, which have synchronization buffers, but it's configuration impacts peripherals on other buses, to be sure the write is completed one has to do a dummy read:

PWR->CR1 |= PWR_CR1_DBP;
PWR->CR1;

> Oh god.. I've used the bit position instead of the mask.

Do not use + operator on bit masks, use | instead. It's safer in exactly such situations as this one. In case of | wrong value will corrupt only some bits, but in case of + all bits can be corrupted.

As you are not the only one... What's the point of not using the CMSIS defined register structures and bitfields and redefining an "improved" ones? And how do you deal with multiple instances of the same peripheral type? Are you defining an individual constants like GPIOA_ODR, GPIOB_ODR, GPIOC_ODR and so on?

luuuuuuu1
luuuuuuu1Author
Associate
April 22, 2022

Unfortunately, I'm trapped in a framework and not supposed to use CMSIS..

Thanks, I've implemented a dummy read for synchronization.

Do you have an idea why my backup register gets erased after power loss? I thought the backup register was reset proof.

Piranha
Principal III
April 22, 2022

CMSIS is an abbreviation of many things, of which everyone imagines something of it, but doesn't care to clarify which part exactly they mean. Those, who forbid it, probably meant CMSIS-Driver, CMSIS-RTOS etc.:

https://www.keil.com/pack/doc/CMSIS/General/html/index.html

Or maybe you (or your managers) misunderstood and took ST's Cube/HAL/LL broken bloatware for being "CMSIS", which, of course, it isn't?

CMSIS-Core peripheral and register definition files are harmless and usage of peripheral structures is much more flexible:

https://github.com/STMicroelectronics/STM32CubeG0/blob/master/Drivers/CMSIS/Device/ST/STM32G0xx/Include/stm32g071xx.h

waclawek.jan
Super User
April 23, 2022

> CMSIS is an abbreviation of many things

Exactly. CMSIS was (is?) ARM's not-that-well-thought-through attempt to bring everything you need for programming Cortex-M under a single title, ultimately resulting only in more confusion. That's why I am talking about "CMSIS-mandated device header" when referring to https://github.com/STMicroelectronics/STM32CubeG0/blob/master/Drivers/CMSIS/Device/ST/STM32G0xx/Include/stm32g071xx.h which is basically the only STM32-specific thing you need from CMSIS and from Cube (you also need the core Cortex-M headers from https://github.com/STMicroelectronics/STM32CubeG0/tree/master/Drivers/CMSIS/Core/Include - obviously, not all of them are relevant to your particular STM32/Cortex-M0+, it's just that ST simply copypastes the whole bunch from ARM).

> Do you have an idea why my backup register gets erased after power loss? I thought the backup register was reset proof.

How is VBAT connected in your hardware? How do you set BOR in Option bytes?

A good practice is also to clear DBP immediately after backup-domain access.

JW

Piranha
Principal III
April 23, 2022

By the way, I strongly recommend taking the Cortex-M headers directly from ARM CMSIS 5 master tree:

https://github.com/ARM-software/CMSIS_5/tree/master/CMSIS/Core/Include

The reason is ST is shipping years old versions (June 2018) despite very important critical fixes having been done only few months later (Oct 2018). It's the ST's "testing" process that ensures that old and buggy software versions are still used years after having been fixed by the original developers. The result of a policy, where formal testing is more important than analytical skills and actual understanding of code...

waclawek.jan
Super User
April 23, 2022

> I strongly recommend taking the Cortex-M headers directly

Generally, I tend to agree.

But, for purposes to this thread: this particular issue is Cortex-M7-specific, not related to Cortex-M0+.

(Also, I'd say, the original problem was more of insufficient documentation than anything else: would there be a concise description of the CM7 L1-cache by ARM in form of appnote; and would those function's description said out explicitly, that address and size have to be cache-line-granularity-aligned, there would be no need for that "fix", which btw. is performance-pessimal. Would there be any need for fix, asserts should've been used preferentially in this case.)

JW

waclawek.jan
Super User
April 25, 2022

> RCC_BDCR |= 0x100U;

I am not sure what are you trying to achieve by this.

Make sure some of the symbols you use to write into RCC_BDCR does not contain also the RCC_BDCR.BDRST bit. Single-step in disasm to see what exactly gets written into RCC_BDCR.

Do you observe (using debugger) the registers loss before the above code is called?

Write a simple test code manipulating only the backup register, without any other "framework" whatsoever. Still problems?

Also, tell us about your hardware - in particular, how is VBAT connected?

JW

luuuuuuu1
luuuuuuu1Author
Associate
April 25, 2022

To my knowledge, we use VDD to apply 3V3 and have no backup battery. We wanted to use the backup registers to store power loss flags, BOR is default.

waclawek.jan
Super User
April 25, 2022

There is no magic which would preserve backup registers content, if you don't have any power source for them.

JW

luuuuuuu1
luuuuuuu1Author
Associate
April 25, 2022

Well, I feared that. Thanks for your efforts, nevertheless!

LW