2

I'm trying to test a communication between my LPC4370 cortex-m4 micro (LPC Link2 eval board) and my computer, using the VCOM exaple provided with LPCOpen. I simply want to sent data from matlab, copy them in a int32_t array and send them back to host.

Here's what I tried. From Matlab:

fwrite(serial_object,raw_data,'int32');

For the C part, I summarize with only relevant code:

#define RAW_SIZE      1024
unsigned char uint8_t;
typedef int int32_t;

// My Buffer
__DATA(RAM) int32_t buffer_rt_s[RAW_SIZE] = {0};

// VCOM-UART rx buffer
static uint8_t g_rxBuff[4*RAW_SIZE];

int i;

int main()
{
  vcom_bread((uint8_t*)&g_rxBuff[0], 4*RAW_SIZE);

    for(i=0; i < RAW_SIZE; i=i+1)
    {
     buffer_rt_s[i]=(int32_t*)(&g_rxBuff[0]+i*4);
    }
    vcom_write((uint8_t*)&buffer_rt_s[0], 4*RAW_SIZE);
}

What I'm trying to do here

for(i=0; i < RAW_SIZE; i=i+1)
{
buffer_rt_s[i]=(int32_t*)(&g_rxBuff[0]+i*4);
}

is to access the receving buffer advancing by 4 bytes at each iteration. So I ask for the address

(&g_rxBuff[0]+i*4)

And then for the content at that location, specifying I want a 32 bit number (i.e. 4 bytes):

(int32_t*)

Results form Matlab plot. To me it seems a lot like I'm reading the addresses of the receiving buffer instead of the content. Notice that I already used the vcom functions with matlab, and I know for sure that they are working.

Any help would be appreciated. Andrea

a_bet
  • 370
  • 3
  • 14
  • Please don't post C code on image. Please [edit] and attach code as text. – user694733 Apr 24 '19 at 10:36
  • I want to make sure I understand: you want to take every 4 bytes in `g_rxBuff` and treat them like a little endian 32 bit signed integer, then copy to `buffer_rt_s`? – Lev M. Apr 24 '19 at 10:44
  • I hope now the question is more clear. @Lev M. Yeah that's the Idea. It's just a test to be sure I can manipulate those numbers properly. – a_bet Apr 24 '19 at 10:51

2 Answers2

0

There's lots of different problems here.

  • Any data protocol sent over UART or other data communication will have something referred to as "network endianess". This is the MS/LS byte order used by the communication protocol. By tradition, this is almost always big endian.

    Your PC is almost certainly little endian. Cortex M4 support both big and little but typically default to little endian. This is the case with LPC4370.

    You need to sort out exactly how bytes are stored in memory and in the protocol before doing anything else.

  • g_rxBuff is not necessarily allocated on an even address, nor is the received protocol necessarily allocating integers on even addresses. Meaning that accessing it's contents through an int32_t may lead to misaligned access.

  • Accessing a uint8_t array through a int32_t pointer access is always a strict aliasing violation bug. (You can do the other way around, as a special case.) See What is the strict aliasing rule?

To avoid the latter two problems, you can either allocate memory at specific addresses and then hardcopy all memory with memcpy. Or alternatively, use some uniontricks:

typedef union
{
  uint8_t u8 [4];
  int32_t i32;
} i32_t;
Lundin
  • 195,001
  • 40
  • 254
  • 396
0

So, I post here the solution that worked for me, after following @Lundin hints. Here's my union declaration: this ensures for the data to be 4-bytes aligned.

#define RAW_SIZE      64

/* my nt32 buff */
__DATA(RAM) int32_t buffer_rt_s[RAW_SIZE] = {0};

union Buffer {
    uint8_t g_rxBuff[4*RAW_SIZE];
    int32_t g_rxBuff32[RAW_SIZE];
};

And here's my usage of the LPCOpen USB Driver

/* Union init */
Buffer b;

/* read on byte at a time*/
vcom_bread(&(b.g_rxBuff[0]), 4*RAW_SIZE);

/* do something with the data */

buffer_rt_s[i]=b.g_rxBuff32[i];

/* write - note that this cast is legal */
vcom_write((uint8_t*)&buffer_rt_s[0], 4*RAW_SIZE);

I hope this can help others in using this kind of drivers:)

a_bet
  • 370
  • 3
  • 14