Consider the following code:
ADC_CTRL1 |= 0x2000; // start an ADC conversion (address is 0x40190000 and is defined as a short word)
Now consider this code
ADC_CTRL1 = (ADC_CTRL | 0x2000); // start an ADC conversion (address is 0x40190000 and is defined as a short word)
Is there a difference?
Assembler gives, in the two cases,
0x0000000E 0x207C40190000 movea.l #1075380224,a0 ; '@...'
0x00000014 0x08D00005 bset #5,(a0)
0x00000018 0x7000 moveq #0,d0
0x0000001A 0x303940190000 move.w 0x40190000,d0
0x00000020 0x08C0000D bset #13,d0
0x00000024 0x33C040190000 move.w d0,0x40190000
The first fails and the second works....(the reason being that the access to the register in the first case is performed as a bit set acting on the first byte in the register whereas the second manipulates the value in a data register and performs a short word destination write - presumably this register doesn't like to be addresses as a byte.)
This leads to a question as to best practice in these situations? The problem can be solved by:
a) disabling optimisation
b) ensuring that the register is declared as volatile (although the volatile declaration is not explicitly causing the register to be handled as a volatile but does avoid the use of bset directed to a single byte).
c) use CW 6.4 rather than CW 7.2 (CW6.4 tends to use ori rather than bset when setting bits)
Maybe a bit of a theoretical topic but still interesting in some way....