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.

Reading and Writing to Memory Registers

Other Parts Discussed in Thread: MSP430F5636

I'm familiar with writing code that uses pointers with direct memory access to read and write to a register, but the symbolic constants provided by MSP430 header files allow you to write to a register without using pointers. Only symbols are needed. For example, if I want to enable interrupts for Timer A, I could just write  TACTL = TACTL | TAIE or TACTL |= TAIE.

What if I wanted to read the bits in the TACTL register or read the TAIE bit in the register. Can I still use these symbolic contants. If I can, what would the line of code look like?

  • Hi Thomas,

    You can read and write registers represented as symbolic names just as you do for the normal variables:

    unsigned short regValue;
    unsigned short regNewValue = 0x0001;

    regValue = TA0CTL;
    TA0CTL = regNewValue;

    However, you can not read or write separate bits using symbolic names for the bits:

    unsigned char bitValue;
    unsigned char bitNewValue = 0x0001;

    bitValue = TAIE; // Compiles, but does not make sense. Always = 0x0002
    TAIE = bitNewValue; // Can not do that; Compilation error.

    These are just bit masks used to extract or set/reset particular bit in a register. For example, TAIE is defined as

    (0x0002u) in corresponding h/w .h file, masking off all bits except bit 1.

    If you want to read particular bit:

    bitValue = TA0CTL & TAIE; // Read bit 1, masking off all other bits in TA0CTL register

    If you want to set/reset bit:

    TA0CTL |= TAIE; // Set bit 1 in TA0CTL register
    TA0CTL &= (~TAIE); // Reset bit 1 in TA0CTL register

  • Serge:

    Thanks for your help. I thought that's how it worked, and I actually wrote some code just like yours, but my code didn't work. My declarations were local, so after changing them to global, it all worked.

    However, the symbol TA0CTL is a mystery to me. What is it? I know it symbolizes a register, but is it a macro, a data type, or what. When I tried watching it during a debug session, the watch window can't find the indentifier TA0CTL, so it doesn't know its data type nor its address. I even tried tracing its declarations through several header files, but it's inner working seem to be hidden inside a linker file. Do you have any idea what it is?

  • Hi Thomas,

    TA0CTL is one of the registers defined for Timer TA0. Not every MSP430 member has Timer TA0 implemented in hardware, in this case this symbol is not defined. Some may have only one Timer A, in this case symbol TACTL is defined instead of TA0CTL.

    In any case, all these symbols are defined in msp430fXXXX.h file.

    For example, let’s take TA0CTL in MSP430F5636 device. It has multi-stage definition in msp430f5636.h file:

    #define DEFW(name, address) __no_init volatile unsigned short name @ address;
    #define TA0CTL_ (0x0340u) /* Timer0_A5 Control */
    DEFW( TA0CTL , TA0CTL_)

    When pre-processor processes these lines, it outputs the next declaration to C compiler:

    __no_init volatile unsigned short TA0CTL @ 0x0340;


    This declares variable with name TA0CTL at fixed address of 0x0340. This kind of declarations is not part of a standard C language, but instead part of extensions for embedded systems programming. These extensions are normally enabled by default (under the IAR - Language conformance - Standard with IAR extensions).

    That was for IAR toolchain. CCS utilises little bit different approach. TA0CTL definition is spread across several files:

    lnk_msp430f5636.cmd
    msp430f5636.cmd
    msp430f5636.h

    Basically in this case your guess that “…it's inner working seem to be hidden inside a linker file” is absolutely right. C compiler used in CCS does not use feature to place register variable on specified address in C code like IAR does (‘@ address’ extension), so it utilises defining register variables as “extern” ones with actual address assignment to them at link time according to content of msp430fXXXX.cmd file. Well, fair enough.

    All other register symbols are defined in similar way as TA0CTL described above.

    Serge

  • You can think of TA0CTL as if there would be a line like

    volatile unsigned char TA0CTL;
    in your code. And that’s actually how the header files provide the registers: they declare global variables with these names. However, the linker later knows that these variables need to be linked to specific memory locations rather than being placed sequentially in ram.

    On the other side, the bit definitions like TAIE are just defined tokens (macros). The precompiler will replace their occurrences by their fixed value (e.g. “0x01”)
    That’s why “TAIE = newValue” will throw an error: the compiler will instead see “0x01 = newValue”.

**Attention** This is a public forum