cancel
Showing results for 
Search instead for 
Did you mean: 

Subject: When are you allowed to change regs using |= and &= and when are you not?

re.wolff9
Senior
Posted on March 22, 2016 at 12:36

DEAR ST: 

Participating in your forum, helping other people is ''enjoyable'' as long as the technology does not get in the way. So if I have something to say, I want to post it. What absolutely pisses me off is that I go through the trouble of writing a reply trying to help you and your customer. I get an error message about ''no such file'' and then a link offering to help troubleshoot  windows sharepoint servics. Well.... I don't have any windows sharepoint services that need debugging. 

----------------------------------------------------------------------------------------------

The tmp = ... construct is ''dangerous''. You have to be sure that there won't be an interrupt that modifies the register and that  occurs between the tmp =... and the ... = tmp.

If an interrupt does occur, it will modify the peripheral register while the interrupted program continues to have the old value stored in the ''tmp'' variable (probably in some CPU register). The modified version based on the OLD value is written back a few instructions later. 

Two options: either disable interrupts for the operation, or KNOW that your code does not modify this register in any interrupt. 

The bad part is, that the other option is effectively the same. The CPU cannot perform the OR operation in memory so it has to load the peripheral register into a CPU-register, perform the operation and write it back. 

The annoying thing is, that IF this goes wrong, the bugs are hard to find, as they only trigger very seldomly. 

From: arnold_w

Posted: Tuesday, March 22, 2016 10:12 AM

Subject: When are you allowed to change regs using |= and &= and when are you not?

I have recently reversed-engineer some HAL source code and I see that sometimes a temporary variable is used to manipulate a register, for example

uint32_t tmp = 0;

tmp = hdma->Instance->CR;

tmp |=  hdma->Init.MemBurst | hdma->Init.PeriphBurst;

hdma->Instance->CR = tmp;

At other times, the register is changed directly, for exaple:

#define __HAL_SPI_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |=  SPI_CR1_SPE)

What is the rule here?

1 REPLY 1
Posted on March 22, 2016 at 13:22

In the load-store model used here, all operations occur through a 'tmp' it is just less obvious. So same issue with interrupts exists. A number of registers have write specific behaviour for just this reason. Ie TIM-SR

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