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.

Pointer uint16_t

Hi all,
please could someone explain me next behavior on msp430 (code bellow). I expected tha value in var_unit should be 0x3412, but it is 0x1200.
I know all msp430 are little endian and therefore this byte order, but I am pointing to byte with value 0x12 and second byte should be 0x34.
Please help me with this elentar issue. Thank in advce for replay. David

#include "stdint.h" 
unsigned char buffer[6] = {0x00,0x12,0x34,0x56,0x78,0x90}; 
int main(void) { 
volatile unsigned int var_uint = *((unsigned int *)&buffer[1]); 
       //value in var_int is 0x1200 return 0; 
}

  • I little bit searched about it and found that this behaviour occurs only when the the variable is placed on odd address. So how to cast unsigned char pointer to unsigned int pointer in case of odd address?

  • The problem is not the cast itself, but the actual memory access. The MSP430 cannot access 2-byte words at odd addresses, so the CPU just ignores the lowest bit of word addresses.
    Your code has to manually construct the value from the two bytes.
  • Ladislav Machan1 said:
    So how to cast unsigned char pointer to unsigned int pointer in case of odd address?

     Hi as pointed, MSP430 is a 16 bit processor and memory access is not so efficient on byte access. Memory is read as two word and special bus adapter is on peripheral area. MSP is not efficient when work on byte value and is more faster on word access.

  • Thank you for replays. I understand, but in my case I am not able affect placing in memory (it is buffer for bus) . So waht do you recommand? This one wokrs for me:

    unsigned char temp[2]; //compiler manages placing on even address
    memcpy(temp,&buffer[1],2);
    unsigned int finalVariable = *((unsigned int*)temp);   

    Cleverer manners are welcomed. :)

  • There is no guarantee that every compiler will align temp correctly; the array would work without alignment, and (a future version of) your compiler might remove the alignment to save space.

    The following code is simpler, and is guaranteed to work with any compiler, and on any architecture:

    uint16_t finalVariable;
    memcpy(&finalVariable, &buffer[1], 2);
  • using memcpy, as it is a function call, is surely not the most efficient way.
    I use macros for this, as I too get data form a data stream and cannot be sure that multi-byte values are word-aligned in memory.

    #define READ_INT(address) (((unsigned char *)(void*)address)[0]|(((int)((unsigned char *)(void*)address)[1])<<8))
    It reads the int value at the given address, whether it is an address value or a pointer to anything.
  • But why not defining the array ‘buffer[]’ immediately as 16-bit integer, then there is no problem at all?
  • Leo Bosch said:
    But why not defining the array ‘buffer[]’ immediately as 16-bit integer, then there is no problem at all?

     Hi Leo I was reading what it is asking for Ladislav, this cannot solve issue and access is more worst to other element are ok too.

     I was thinking about unions record but I see no way to access a word on odd addresses on 16Bit processors. 68K series from 020 to higher where provided with a good mechanism to address a similar request but a memory move and bit move where on instruction set.

     On MSP I am need think more but I fear no simple or elegant solution can exists. Forever odd address access even with bit 0 masked out.

  • Ladislav Machan1 said:
    Cleverer manners are welcomed. :)

     Hi Ladislav, I thinked some time, no clever solution than JMG or a function same as JMG macro where you pass byte pointer to element of array returning value of integer.

  • There are several ways to align the data.
  •  Hi Leo, so you can have packed or aligned to even address, this was on old architectures like mainframes but never you can access bytes from odd addresses, as I wrote I only remember 68K architecture where memory was accessed as 8 16 24 or 32bit, this was unique processor I liked a lot, also memory was configurable in size so hardware was informing of its size. Software counterpart was for byte access at every possible address bus conrtoller was minimizing accesses...

     MSP430 is a word machine, forever read a word only on even addresses so whichever alignment you can apply to data how can you access a word variable at odd address?

     I am curious about alternate solution than macro for speed or function for space.

     

  • A byte can be read from any address, odd or even. But Ladislay wants to read a 16-bit integer, this can only from an even address, in this case Ladislay must organize it so that his ‘buffer’ array starts at an even address.
  • Leo Bosch said:
    this can only from an even address, in this case Ladislay must organize it so that his ‘buffer’ array starts at an even address

     Sorry to point to Leo, I fear this is what you didn't grasped from Ladislav request:

     Bytes are stored to a packed  character array on contiguous storage.
     This array need also be read as word value from any byte address.

     It can be correctly read from even pointer addresses

     If fail if pointer odd address is applied to read a word value.

     ...

     So on my point of view don't care if byte array is even or odd aligned, the element of vector is in odd addresses fails due MSP is a WORD based machine and forever ignore LSB address on bus.

     Internal are to be confirmed from silicon designer and are not known by us, if you check the MCU dagram only a 16bit data bus is present and in series 5xx 6xx also 8 bit bus adapter is no more present extendind architecture to pure full word machine. I think this is the same for MSP432 too where 32bit bus is splitted in some way as upper and lower word.

     MSP is contrary to old good 68K syncronous, so no async communication about hardware on the fly can be applied. Also instruction and buss accesses complete in just one clock cycles so controller too has no time to do double access on single word bus.

  • Roberto Romano said:

    Sorry to point to Leo, I fear this is what you didn't grasped from Ladislav request:

     Bytes are stored to a packed  character array on contiguous storage.
     This array need also be read as word value from any byte address.

    Roberto, I didn’t (and still) grasp this from Ladislav request, but if this is the case then Jens-Michael’s solution is the best.

    Otherwise, if the buffered data comes for example from a 8-bit communication stream and containing values -8, 16, 32 or more bits- then this is the way I handle this. You also can see here how MSP handles 8 and 16-bit data as well as on even or odd addresses.

    // These 6 byte's of variables will cost 6 bytes of RAM space
    typedef struct myStructA {
    	unsigned int	Value1;
    	unsigned char	Value2;
    	unsigned char	Value3;
    	unsigned int	Value4;
    } myStructA;
    
    typedef union myUnionA {
    	myStructA		Values;
    	unsigned char	Buffer[6];	// Buffer corresponds with Structure values.
    } myUnionA;
    
    // These 6 byte's of variables will cost 8 bytes of RAM space
    typedef struct myStructB {
    	unsigned char	Value1;
    	unsigned int	Value2;
    	unsigned char	Value3;
    	unsigned int	Value4;
    } myStructB;
    
    typedef union myUnionB {
    	myStructB		Values;
    	unsigned char	Buffer[6];	// Buffer does NOT corresponds with Structure values.
    } myUnionB;
    
    typedef struct myStructC {
    	unsigned char	Value1;
    	unsigned char	Value2;
    	unsigned char	Value3;
    } myStructC;
    
    typedef union myUnionC {
    	myStructC		Values;
    	unsigned char	Buffer[3];	// Buffer corresponds with Structure values.
    } myUnionC;
    
    
    // Contains 16-bit, Aligned to even address
    myStructA	sA1;
    myStructB	sB1;
    myUnionA	uA1;
    myUnionB	uB1;
    
    // Contains only 8-bit, Not aligned, odd address possible
    myStructC	sC1;
    myStructC	sC2;
    myUnionC	uC1;
    myUnionC	uC2;
    
    /**********************************************************
     output                                  attributes/
    section   page    origin      length       input sections
    --------  ----  ----------  ----------   ----------------
    .bss       0    00000200    00000028     UNINITIALIZED
                      00000200    00000008     (.common:sB1)
                      00000208    00000008     (.common:uB1)
                      00000210    00000006     (.common:sA1)
                      00000216    00000006     (.common:uA1)
                      0000021c    00000003     (.common:sC1)
                      0000021f    00000003     (.common:sC2)
                      00000222    00000003     (.common:uC1)
                      00000225    00000003     (.common:uC2)
    
    ***********************************************************/
    
    main:
    ;* --------------------------------------------------------------------------*
            MOV.W     #23168,&WDTCTL+0      ; [] |78| 
     
    ;	Not Optimized! All other CCS options are Default.
    ;
    ;	Moving Words & Bytes, at even address:
            MOV.W     #1,&sA1+0             ; [] |84| 
            MOV.B     #2,&sB1+0             ; [] |85| 
            MOV.B     #3,&sC1+0             ; [] |86| 
            MOV.B     #4,&uA1+0             ; [] |87| 
            MOV.W     #5,&uA1+4             ; [] |88| 
            MOV.B     #6,&uB1+0             ; [] |89| 
            MOV.W     #7,&uB1+2             ; [] |90| 
            MOV.B     #8,&uC1+0             ; [] |91| 
    ;
    ;	Moving Bytes, at odd address:
            MOV.B     #9,&uC2+0             ; [] |94| 
            MOV.B     #10,&sC2+0            ; [] |95| 
     
    ;	-------------------------------
     
            RET       ; [] 
            ; [] 
    ;*****************************************************************************
    

  • As I said, I had the same problem in my projects: I get incoming data packets on a stream. These packets contain data structures of varying size, consisting of bytes, words, dwords or byte arrays, depending on package type. So a word can end-up at any even or odd address in the receive buffer. Sure I could copy the structures, once identified, over to an aligned storage from the stream, but this would just waste space and time.
    using macros that take the struct member address based on struct address and member offset, and composing it with byte reads, whether the resulting position is an odd or even address, is the simplest way and works straight.
    in fact, the latest version of MSPGCC3 did implement it this way automatically, if the structure definitions did have the packed attribute. If I hadn't stated with an older MSPGCC, I hadn't ever needed these macros at all.
    However, it only works for structures with packed attribute. Not for individual values cast at a buffer.

**Attention** This is a public forum