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;

20 REPLIES 20

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

> 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

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...

> 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

Receive buffers indeed will typically be aligned, but transmit buffers are often arbitrary. That would require calculating aligned address and size in every location of application/driver code, where the particular cache management function is called. Given that the performance hit is only a single bitwise AND and a single ADD operation, it's not worth the trouble. Actually in some cases it could turn out to be even better performing because the smaller code will more likely fit in cache. A cache miss costs much more than 2 clock cycles.

I agree that cache and it's management should be explained better by ARM. And by ST also... Why isn't the contents of this article integrated in AN4839?

Yes but...

I write successfully to the backup register and enable the backup domain write protection afterwards.

PWR->CR1 &= ~PWR_CR1_DBP;

However, my backup register does not store the values during reset or shutdown.

My startup code does not clear the write protection flag.

There has to be some configuration missing, right?

/* Power interface clock enable */
RCC_APBENR1 |= RCC_APBENR1_PWREN_MASK;
RCC_APBENR1_PWREN;
			
/* RTC APB clock enable */
RCC_APBENR1 |= RCC_APBENR1_RTCAPBEN_MASK;
RCC_APBENR1_RTCAPBEN;
 
/* Disabling backup domain write protection */
PWR_CR1 |= PWR_CR1_DBP_MASK;
 
/* Disable erase on tamper */
TAMP_CR2 |= TAMP_CR2_TAMP1MSK_MASK;
TAMP_CR2 |= TAMP_CR2_TAMP2MSK_MASK;
TAMP_CR2 |= TAMP_CR2_TAMP1TRG_MASK;
TAMP_CR2 |= TAMP_CR2_TAMP2TRG_MASK;
 
/* LSE oscillator enable */
RCC_BDCR |= RCC_BDCR_LSEON_MASK;
RCC_BDCR_LSEON_MASK;
 
RCC_BDCR |= RCC_BDCR_LSCOEN_MASK;
RCC_BDCR |= RCC_BDCR_LSCOSEL_MASK;
RCC_BDCR |= 0x100U;	
 
/* RTC clock enable */		
RCC_BDCR |= RCC_BDCR_RTCEN_MASK;	
 
/* After disabling backup domain write protection, write access to backup registers is granted */
TAMP_BKP0R = LOW_POWER_RESET;
 
/* Enabling backup domain write protection */
PWR_CR1 &= ~PWR_CR1_DBP_MASK;

 This code is called once, and writes to the backup register. I've disabled all "delete" options on tamper events and set write protection afterwards. In the reference manual I found the following:

RM0444 section 31.3.4:

The backup registers are also erased when the readout protection of the flash is changed

from level 1 to level 0.

Might this be the reason that the backup data gets erased?

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

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.

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

JW