This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

LPC2368 UART register sizes in lpc23xx.h file?

I have a question about the lpc23xx.h file version 1.04

I was wondering why some of the UART registers were defined as unsigned long, when they appear to only be 8 bits (unsigned char)?
For example, the RBR, THR, DLL, DLM, FCR, LCR, LSR, SCR and TER registers for all the UARTS.
Is there a reason for this, or was this just a cut and paste typo?

  • It's not a typo.

    LPC23xx is an 32-bit ARM device and using 32-bit registers generates the best code. This is the reason why UART registers are defined as unsigned long.

  • That's what I thought at first, but I'm not so sure...
    For example:

    recData is unsigned char, REC_DATA (U0RBR) is unsigned long

      305:         recData = (unsigned char)REC_DATA;
    0x00000500  E5900000  LDR       R0,[R0]
    0x00000504  E20060FF  AND       R6,R0,#0x000000FF
    

    recData is unsigned char, REC_DATA (U0RBR) is unsigned char

       305:         recData = REC_DATA;
    0x00000500  E5D06000  LDRB      R6,[R0]
    

  • The second case generates only one instruction (no cast is required) and this is the best way to use it (when REC_DATA is unsigned long).

  • I think you might be confused...
    In the first case (when REC_DATA is unsigned long) the compiler generates two instructions whether or not I use the cast (the cast is assumed by the compiler since I'm loading an unsigned long into an unsigned char variable).
    In the second case, I changed the definition of REC_DATA(U0RBR) from unsigned long to unsigned char which matches the variable I was using. This allowed the compiler to only use one (LDRB- load register byte value) instruction which is obviously more efficient (speed wise).
    If I left the REC_DATA(U0RBR) definition as unsigned long and used a variable that was an unsigned long, i would be back down to one (LDR - load 32 bit word from memory) instruction, but this would be less efficient memory wise (just wasted 3 bytes).
    So, back to my original question, why keep the 8 bit UART registers defined as unsigned long?

  • I think you might be confused...
    Not really, I have just overlooked that in the second case unsigned char was used.

    If I left the REC_DATA(U0RBR) definition as unsigned long and used a variable that was an unsigned long, i would be back down to one (LDR - load 32 bit word from memory) instruction, but this would be less efficient memory wise (just wasted 3 bytes).
    Not always true regarding memory usage. When variables are local they are located in registers (or stack) and since they are 32-bit anyway there is no real wasted memory.

    So, back to my original question, why keep the 8 bit UART registers defined as unsigned long?
    Since 32-bit is native size it should generate more efficient code but as you have tried out this is not always the case. So using 8-bit definitions might be better.

  • It is quite common that the developer selects the int or unsigned int data types. So it isn't an unreasonable assumption that the SFR can be accessed with 32-bit accesses. The chip designer have designed the chip to allow such accesses.

    Anyway: The most general solution is to define two sets of definitions to access these registers, just as the GPIO ports has 8-bit, 16-bit and 32-bit access methods.