Stephen
Stephen

Reputation: 31

C Struct problem

I've been searching for some answer to this problem but can't figure it out.

I have a structure:

typedef struct  {
    BYTE  hour;      
    BYTE  minute;    
    BYTE  second;   
    BYTE  dom;     
    BYTE month;
    BYTE year;      
} t_time_date ;

And a serial port receive function:

g_curr_td.year = g_rx_buffer[3];
g_curr_td.month = g_rx_buffer[4];
g_curr_td.dom = g_rx_buffer[5];
g_curr_td.hour = g_rx_buffer[6];
g_curr_td.minute = g_rx_buffer[7];
g_curr_td.second = g_rx_buffer[8];

I have verified the g_rx_buffer is correct and contains data. If I hard code a number in to the variable it works:

g_curr_td.year = 10;  /* this works */

However, running live data it crashes and seems to be writing data somewhere else in memory. Can anyone see something wrong in my setup?

Thanks.

Upvotes: 2

Views: 250

Answers (6)

Nicolas Viennot
Nicolas Viennot

Reputation: 3969

Although I may not answer your question directly, this may help you have cleaner code:

Have a struct for the incoming data format:

typedef struct  {
    BYTE  year;      
    BYTE  month;    
    BYTE  dom;   
    BYTE  hour;     
    BYTE  minute;
    BYTE  second;      
} t_time_input_date __attribute__((packed));


// First you can make sure the data is received in its whole
assert(g_rx_length >= sizeof(t_time_input_date) + 3);

t_time_input_date *in_date = (t_time_input_date *)(g_rx_buffer+3);

g_curr_td.year = in_date->year;
g_curr_td.month = in_date->month;
g_curr_td.dom = in_date->dom;
g_curr_td.hour = in_date->hour;
g_curr_td.minute = in_date->minute;
g_curr_td.second = in_date->second;

This way your code will be cleaner, and it will help you in 3 months.

Upvotes: 1

Sam Skuce
Sam Skuce

Reputation: 1694

For debugging purposes, you can try creating a function that takes arguments for all the struct members, something like:

/* Assumes g_curr_td is a global variable. */
void FillStruct( BYTE hour, BYTE minute, BYTE second, BYTE dom, BYTE month, BYTE year )
{ 
    g_curr_td.year = year;
    g_curr_td.month = month;
    g_curr_td.dom = dom;
    g_curr_td.hour = hour;
    g_curr_td.minute = minute;
    g_curr_td.second = second;
}

Using a function like this should make the assembly code the same whether you're using values from the buffer or constant expressions. If it still crashes, it's probably something with your buffer, even though you do seem to have checked all the angles I could think of dealing with the buffer.

You can call this function as FillStruct( g_rx_buffer[3], g_rx_buffer[4], g_rx_buffer[5], g_rx_buffer[6], g_rx_buffer[7], g_rx_buffer[8] ), and if that crashes, call it as FillStruct( a, b, c, d, e, f ), where a, b, c, d, e, and f are either the original arguments or new constant arguments. Try replacing the arguments one at a time and see if it's just one particular field that's failing, or if it's any field that fails.

EDIT: Also, exactly what is your typedef or #define for the BYTE type, what compiler and OS are you using, and are you using any pragmas, e.g. to pack the structure to byte alignment?

Upvotes: 1

a1ex07
a1ex07

Reputation: 37382

What is g_rx_buffer ? If it is not an array of BYTE and not a pointer to BYTE, g_rx_buffer[3] is not the same as ((BYTE*)g_rx_buffer)[3].

Upvotes: 0

Prine
Prine

Reputation: 12538

The only error source I can see here is the access on the g_rx_buffer. Is the array from g_rx_buffer big enough?

Maybe you can loop over the g_rx_buffer and show us the content of this array.

Upvotes: 0

RMAAlmeida
RMAAlmeida

Reputation: 304

Did you have any system so sincronize data over the serial? How do you guarantee that g_rx_buffer[3] is really g_curr_td.year?

Upvotes: 0

CashCow
CashCow

Reputation: 31445

Does g_rx_buffer have at least 9 BYTEs of data?

Upvotes: 1

Related Questions