cancel
Showing results for 
Search instead for 
Did you mean: 

Can't disable backup domain write protection in PWR_CR1

luuuuuuu1
Associate II

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;

1 ACCEPTED SOLUTION

Accepted Solutions
20 REPLIES 20

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
Associate II

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
Associate II

The RCC_BDCR register is configured as follows:

0x030081030693W00000LykJNQAZ.png

you do need to enable the RTC APB clock (in RCC_APBENR1).

luuuuuuu1
Associate II

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;

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

Piranha
Chief II

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?

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.

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.