This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MOV.b at odd address writes the even address

Other Parts Discussed in Thread: MSP430F6659

Hi everyone,


I'm using a MSP430F6659 rev A

I have defined my peripherals registers as structures with bitfields, then linked them at the correct place. It mostly works well.

/* Timer TAx Registers Type */
typedef struct {
   /* TAxCTL */
   union {
      struct {
         G_UWord_t Taifg_UW_1Bit          :1; /* Timer A counter interrupt flag */
         G_UWord_t Taie_UW_1Bit           :1; /* Timer A counter interrupt enable */
         G_UWord_t Taclr_UW_1Bit          :1; /* Timer A counter clear */
         G_UWord_t Reserved_3_UW_1Bit     :1; /* Reserved_3 */
         G_UWord_t Mc_UW_2Bit             :2; /* Timer A mode control */
         G_UWord_t Id_UW_2Bit             :2; /* Timer A clock input divider */
         G_UWord_t Tassel_UW_2Bit         :2; /* Timer A clock source select */
         G_UWord_t Reserved_10_15_UW_6Bit :6; /* Reserved_10_15 */
      } Bits;
      G_UWord_t Value;
   } Taxctl_U; /* TAxCTL */

etc. for other register words of the structure.

But as I tried to write into 2 bits of TimerA0 register, I found the microcontroller writing it one byte lower than I expected.

The c line of code is the following:

McuTimerA_G_TimerA0Regs_S.Taxctl_U.Bits.Tassel_UW_2Bit = 0b10;


It was translated by the compiler as the following assembly code, which seems right

;----------------------------------------------------------------------
; 338 | McuTimerA_G_TimerA0Regs_S.Taxctl_U.Bits.Tassel_UW_2Bit = 0b10; // SMCLK
;----------------------------------------------------------------------
        MOV.W     #252,r15              ; [] |338|
        AND.B     &McuTimerA_G_TimerA0Regs_S+1,r15 ; [] |338|
        OR.B      #2,r15                ; [] |338|
        MOV.B     r15,&McuTimerA_G_TimerA0Regs_S+1 ; [] |338| 

After some masking of the register, it corresponds to moving my '2' value to the 2nd byte of the structure at address 0x340 with a MOV.B r15,&0x341, which looks right (and rules out placement / alignment issues, as 0x341 is where I want to write my bits)

Except when I execute this assembly instruction with the memory at 0x340 previously = 0x0000, I end up with: 0x0002 instead of 0x0200.

In other words, the MOV.B r15, 0x341 seems to have executed MOV.B r15, 0x340

I find that very strange, as it seems a byte operation can be executed on an odd address (and if not, why would the compiler generate this instruction ?)


The read of the memory is done with the Lauterbach sensor tool, which shows me expected values in all registers, and when the instruction MOV.B r15, 0x341 is executed, an interrupt is trigged afterwards which corresponds to having writen the Interrupt flag bit (bit 1 of 0x340) in the timerA register.

If i do the write operation by a 16bit overwriting of all the CTL register, the result is fine and i don't have any interrupt.

So i'm pretty sure the memory is really modified at address 0x340 and not 0x341, even if I were not to trust my toolchain, or to suspect an endianess interpretation problem.

I have looked into the compiler options to see if I had somehow messed up some alignement option, thus forbidding such odd address write, but i didn't find anything of the sort, and the code is produced by the compiler...

I have no idea of how that can be happening except for a sillicon bug, so any help would be appreciated.

  • I have singled out the problem by just executing the following instructions:

    __asm("\t   BIS.B\t   #0x2,R15");
    __asm("\t   MOV.B\t   R15,&0x341");

    to the same result: memory is modified at address 0x340

  • I suggest trying to reproduce this on another debugger (and/or compiler). In this thread regarding an issue with struct alignment the source of the apparent problem was found to be an error in the Lauterbach debugger.

  • In general we also tend to discourage using bit fields for peripheral register control bits. It leads to inefficient code after compilation in both code size and execution time if you need to set or modify multiple sets of bits.

  • Thanks Robert for this very interesting piece of information.

    I read the thread carefully and a bug at debugger level is what would make the more sense.

    I'm going to have lauterbach teams look at it closely.

    As for bitfields, I agree with you Brian, this is less efficient in code execution and size. But I don't really care about efficiency in this product and maintaining code this way seems much more natural to me.
    But for my own curiosity: I would have though that the compiler would have been able to optimize it back to the same code if I affect several parts of the same bitfield in a row, is it not the case ? (it just occurs to me that these registers are volatile so probably not)

    PS: I don't use optimization anyway :)

  • Normally, the compiler could indeed optimize multiple bitfield operations into one. But not with peripherals registers.
    Peripheral registers have side-effects, so the compiler must not optimize any access to them. If the source code instructs to set a bit and then another, the compiler must compile it exactly this way: first set one bit, then set another. As setting both together, while resulting in the same final register content, may have a completely different effect on the hardware.
    Or imagine a “P1OUT|=1;P1OUT &=~1:” sequence. Optimizing it would swallow the pulse on the port.

    So the header files declare all those registers as volatile.

    For the original topic: the .B instruction will for sure access the given address. Else almost no code would run as it should :)

    However, a .W instruction on an odd address will silently ignore the LSB and access the lower even address.
    I had to learn this when working with packed (not aligned) structs and passing their pointers. (later versions of the MSPGCC compiler fixed this issue, making always byte access on packed struct members). But the problem remained for structs in a byte stream when the struct position in the stream was not aligned)

  • well, I didn't have a clear head when this happened.

    I'm only trying to write a control bit that automatically reset itself in byte 0x341, and modifies a status bit at the same place in 0x340.

    So this is completely normal and I've just been confused by the coincidence and shortsighted.


    EDIT: I'm not mad after all, there really was something wrong: the byte accesses are just not supported here

  • Well, things like this can happen.
    However, it was not completely impossible what you observed (or seemed to observe). I once had a similar problem. It happened when programming the DMA controller. The users guide was listing byte-sized registers for the trigger.
    It  turned out that the DMA controller registers are word access only, so even if I tried to write an odd byte with a MOV.B, the byte ended up in the low byte of the word below, as the DMA controller ignored the LSB of the address and took the data as a word. It wasn’t the CPU’s fault.
    This was the issue that originally brought me here almost 5 years ago. The users guide was changed then, after I discovered and reported what was going on.

  • I thought for a moment that my problem was caused by a self clearing bit in the Timer A TACTL register, but no.

    The reason is the one you gave Jens-Michael, the registers are Word access only. It is actually expressed by a table in the user manual (thanks to you it seems^^) but I didn't suspect that some memory zones could be accessed by word operations only whereas others can, especially when the instruction is documented and generated by the compiler.

    Thanks (again)

  • I can’t accept the kudos for this table. IIRC, it was always correct. The bug in my case was that the users guide explicitly listed _L and _H byte-registers for DMA where the registers were word access only.

    For the timers, there never has been a TACTL_H or TACTL_L definition.
    On 1x family, the word or byte access capability was dependant on the memory area. There was a byte-access area and a word access area, and the modules were located in the proper memory range. On 5x family, it is the module’s responsibility to provide or refuse byte access or word access on its registers (allowing mixed situations)
    Most modules that allow byte access for one register (or have registers that are only byte-sized) do also allow byte access to their word-wide registers. Also, in most cases, nobody has a reason to access these registers byte-wise. However, in the DMA module, the trigger settings for two DMA channels are in one word-sized register, and I tried to set them independently with byte access - and failed.

    In any case, the CPU is just putting the address (and data) on the memory bus and pulls the ‘read/write byte’ or ‘read/write word’ signal. If the module doesn’t support one of them, the result is what you observed.

    Similar case: make a word access to an odd memory address. The LSB will be simply ignored then, and you write to one byte less than intended, overwriting one byte unintentionally, and having the MSB ending up in the LSB of the intended destination (and its MSB untouched). The CPU won't notice that the memory has just ignored the LSB of the address. Not the CPU's fault.

  • Guillaume Sarrot said:

    EDIT: I'm not mad after all, there really was something wrong: the byte accesses are just not supported here

    I think the real cause of the problem is that the variable you use to describe the peripheral register is not defined to be "volatile". If it would, then the compiler wouldn't be allowed to access the register using a byte operation.

    Of course, if the have defined the variable to be "volatile" and this happened anyway, you have found a compiler bug. In that case, please report it! (Which tools are use using, by the way.)

        -- Anders Lindgren, IAR Systems, Author of the IAR compiler for MSP430

  • ‘volatile’ only tells the compiler that any read or write access has to happen exactly how and where it was in the source code, as it may have side-effects. It has nothing to do with word or byte access.
    The problem here was that the way the struct and bitfield was designed didn’t tell the compiler that the whole 16 bit bitfield needs to be accessed as a word instruction. So when changing a member, the compiler generated the minimum required memory access, not knowing that it won’t work on this register.
    Another reason to not use bitfields on registers. (the other one is that changing multiple members of a bitfield leads to highly ineffective code when the destination is a hardware register and the bitfield therefore is declared volatile (and has to).

  • Jens-Michael Gross said:

    ‘volatile’ only tells the compiler that any read or write access has to happen exactly how and where it was in the source code, as it may have side-effects. It has nothing to do with word or byte access.

    The C standard does not really specify what a compiler should do when performing a volatile access. However, the intention is that it the generated code should behave as much as possible as the source code describes. The obvious thing is that the number of access and the order of which the accesses occur should correspond to the source code.

    At IAR we have also interpreted this that if is a machine access is performed, we do not change the size of the access. Clearly, the case discussed in this thread would have worked out of the box using the IAR compiler, under the assumption that the peripheral register was declared "volatile".

    He have, however, decided to apply this only to accesses that corresponds to machine-words or smaller. So, if you set a specific bit in a 32 bit volatile register, only one of the 16 bit halfs of the register is accessed, but the compiler would not set the bit using a 8 bit instruction. On larger types, we ensure an access in the source code corresponds to at least an access of a part of the peripheral register. (For example, setting a bit in a 32 bit register would access one part, clearing the register would access both.)

    On an architecture like the MSP430, in my opinion, a compiler is broken if it changes 16 bit volatile accesses to 8 bit accesses, as it causes programs like the one in this thread to fail. (It would be interesting to know if the original program did use a volatile variable or not.)

        -- Anders Lindgren, IAR Systems, Author of the IAR compiler for MSP430

  • All my register definitions are of course 'volatile'.

    I think the compiler shouldn't allow itself to simplify an access to an explicitely 16bits bitfield on an architecture where some parts of the memory are not "byte-accessible".

    At the least it should be considered as an optimization that should be deactivable either by not activating optimizations or by setting the variable volatile (as it should left it untouched then)

    In any case, there should be a way to make my code work correctly with the compiler without working around the problem completely...

  • Guillaume Sarrot said:

    All my register definitions are of course 'volatile'.

    In that case I would file a bug report on CCS (which I assume you are using) to Ti. Feel free to refer to this discussion and how the IAR tools handle the situation.

        -- Anders Lindgren, IAR Systems, Author of the IAR compiler for MSP430

  • Guillaume: The compiler cannot know (and does not need to know) whether certain parts of the system are byte or word accessible. You could as well demand that the compiler will prohibit memory access to vacant memory or write operations to flash area.
    However, I agree that any access to a 16bit data type, whether a short int or a bitfield, should be done as 16 bit access when the variable is marked volatile.
    I’m not sure what happens if you have a complex struct with a union and mark the struct as volatile. Maybe the volatile qualifier (or its meaning regarding access size) is lost while unshelling the onion. I don’t know how far the volatile qualifier on a struct is propagated to all of its members. Normally, it should be propagated all the way down.
    In any case, it is the responsibility of the user to know whether a hardware register can be accessed only byte or word-wise.

     Anders: yes, volatile is just a hint that the access may have side-effects other than the variable state change (if used as lvalue) or getting a return value (if used in an expression). And IIRC, all MSP compilers take this as instruction to perform the access in the exact number and order as given, before proceeding.
    I’m not sure about the 32bit thing. There are no 32bit hardware registers, but there are some 20bit registers. Which need to be accessed with a 20bit access from/to a 32bit source/destination. (mainly the DMA address registers). Well, IAR provides intrinsics for this, but of course a simple assignment would be much nicer. It could be implemented by an attribute to the (volatile) register definition. The 20bit extension of the MSP430 core is really not compiler friendly.
    However, the main situation where a 32/64bit variable needs to be volatile is access by an ISR. Here, the compiler could/should(?) generate an atomic access (prevent interrupts) outside an ISR. Which of course makes code slower and bigger.

    Of course, a compiler shouldn’t change the access size on a volatile variable. However, the question is whether in the original code, the compiler really did/could know.

  • Jens-Michael Gross said:

    I’m not sure about the 32bit thing. There are no 32bit hardware registers, but there are some 20bit registers. Which need to be accessed with a 20bit access from/to a 32bit source/destination. (mainly the DMA address registers). Well, IAR provides intrinsics for this, but of course a simple assignment would be much nicer. It could be implemented by an attribute to the (volatile) register definition. The 20bit extension of the MSP430 core is really not compiler friendly.

    The only reason why we added the intrinsics to access 20 bit data is that normal 20 bit accesses are not available in the small data model. (The small data model uses all the goodies of the MSP430X, but assumes that registers are 16 bit wide, thus retaining all the advantages of the old MSP430 core, like reduced stack usage.)

    In the medium and large data models, you can safely access 20 bit volatile registers using normal accesses. The IAR compiler guarantees that volatile accesses will remain 20 bit.

    Jens-Michael Gross said:

    However, the main situation where a 32/64bit variable needs to be volatile is access by an ISR. Here, the compiler could/should(?) generate an atomic access (prevent interrupts) outside an ISR. Which of course makes code slower and bigger.

    I would say that that is the responsibility of the user.

    Jens-Michael Gross said:

    Of course, a compiler shouldn’t change the access size on a volatile variable. However, the question is whether in the original code, the compiler really did/could know.

    If the original poster could make a complete, yet small, example of the code I could run it through the IAR tools. If the generated code makes a 16 bit access, then it should be possible (and desirable) for CCS to do that also.

        -- Anders Lindgren, IAR Systems, Author of the IAR compiler for MSP430

  • So how does the compiler know that a register is a 20 bit register and requires access with extended instruction, or is a normal 32 bit variable that requires two 16bit operations? The second can be volatile too.

    In case of the DMA address registers, source as well as destination usually are in lower 64k and do not need large data model. But using two 16 bit operations won’t work on them.

    I agree that atomic access of 32/64bit variables could be declared as user responsibility. However, using the proper processor registers (see ou' other discussion) is user responsibility too - and there the assembler gives warnings.
    Having a counter that is changed in ISR is a common situation. And I guess only few people think of framing the access in main by disabling interrupts. (here I do not exclude myself from the list - it happened to me too, some years ago)

  • Jens-Michael Gross said:

    So how does the compiler know that a register is a 20 bit register and requires access with extended instruction, or is a normal 32 bit variable that requires two 16bit operations? The second can be volatile too.

    Pointers to __data20 memory, like "void __data20 *", is accessed using 20 bit instructions whereas larger types like "unsigned long" are accessed using multiple 16 bit instructions.

        -- Anders Lindgren, Author of the IAR compiler for MSP430

  • So there’s a special __data20 type or attribute. That’s what I wanted to know (and already suspected).

  • Jens-Michael Gross said:

    So there’s a special __data20 type or attribute. That’s what I wanted to know (and already suspected).

    Yes, in the IAR compiler, every pointer can be associated with a memory type. By default, a pointer is 20 bits in the large data model. You can use the memory type attributes __data16 and __data20 to override this.

    When it comes to volatile accesses, if a peripheral register is a pointer to __data20 memory, it is guaranteed to be accessed using a 20 bit ".A" instruction.

        -- Anders Lindgren, IAR Systems, Author of the IAR compiler for MSP430

**Attention** This is a public forum