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

Multidimension array problem

Hi,
Trying to set up a multi dimensional array to act as a circular buffer.
Will copy 8 databytes into the array and increment a write_counter.
Then in different module when it comes around to service the buffer it processes each entry until the read_counter == the write counter.
My code is below;

PRL.c code

#define CMD_RXBUFFER_SIZE 10 //how many entries in my buffer
#define CMD_RXBUFFER_WIDTH 8 //ie 8 bytes wide
.
.
unsigned char cmd_rxbuffer[CMD_RXBUFFER_SIZE][CMD_RXBUFFER_WIDTH];	//ie from 0-->49 deep, 8 wide
unsigned char rxbuff_write = 0;
unsigned char rxbuff_read = 0;
.
.
//then in a function:
rxbuff_write = rxbuff_write + 1; //add 1 to current write counter
if (rxbuff_write==CMD_RXBUFFER_SIZE) //dont try to allocate data to a non existent array entry
   {
   rxbuff_write=0;
   }

memcpy(&(cmd_rxbuffer[rxbuff_write][0]),&DLL_Rx_Buffer.databytes[1],7); //copy the received data to the next available buffer


then in my next file TRL.c i want to read out the data from the new buffer

extern unsigned char cmd_rxbuffer[CMD_RXBUFFER_SIZE][CMD_RXBUFFER_WIDTH];
extern unsigned char rxbuff_read;
extern unsigned char rxbuff_write;

unsigned char TestData;
.
.
.
//then in a function:
while (rxbuff_read != rxbuff_write)
 {
 rxbuff_read = rxbuff_read + 1;
 if (rxbuff_read == CMD_RXBUFFER_SIZE)		{rxbuff_read=0;}

 TestData = cmd_rxbuffer[rxbuff_read][0];

TestData always equals 0.

NOW the CONFUSING BIT!
if I was to replace the rxbuff_write and rxbuff_read with a numerical value (eg 3) then it works, and TestData equals my data.
if i assign
rxbuff_write=3;
then it also doesn't work.
I have outputted the values of the read and write variables at each stage and they are equal to what I expect them to be, and loop around when I expect. And since I can manually assign the number into the first array index, eg:
memcpy(&(cmd_rxbuffer[3][0]),&DLL_Rx_Buffer.databytes[1],7);
THIS WORKS!
but:
memcpy(&(cmd_rxbuffer[rxbuff_write][0]),&DLL_Rx_Buffer.databytes[1],7);
DOES NOT???

Im totally confused why this wouldn't work. Does anyone have any idea?

Thanks for any help in advance,
Kind Regards,

Peter

Parents
  • You reduced your example a little too much for very precise advice to be possible. The only hunch I have is that your two source files may not have the same idea what your array's dimensions are, because they don't use a single source that defines it.

    1) There should never be a need to write 'extern' inside a .c file. Such things belong into header files, where they can be maintained centrally for all modules that may have to access them.

    2) Same for #define's of constants that influence types, like your array dimensions, and for type definitions themselves.

    I.e. you should have a file PRL.h that contains all the "extern" declarations for PRL.h and the array dimension #defines. As to the problematic behaviour itself, I suspect you'll have to look into the generated code to see what it actually does.

    Another likely reason would be concurrency/reentrancy. Are the two function snippets you showed, by any chance, executed in different context, e.g. one in the main code and the other in an interrupt handler?

Reply
  • You reduced your example a little too much for very precise advice to be possible. The only hunch I have is that your two source files may not have the same idea what your array's dimensions are, because they don't use a single source that defines it.

    1) There should never be a need to write 'extern' inside a .c file. Such things belong into header files, where they can be maintained centrally for all modules that may have to access them.

    2) Same for #define's of constants that influence types, like your array dimensions, and for type definitions themselves.

    I.e. you should have a file PRL.h that contains all the "extern" declarations for PRL.h and the array dimension #defines. As to the problematic behaviour itself, I suspect you'll have to look into the generated code to see what it actually does.

    Another likely reason would be concurrency/reentrancy. Are the two function snippets you showed, by any chance, executed in different context, e.g. one in the main code and the other in an interrupt handler?

Children
  • Hi,
    Thanks for your reply.

    My #defines are actually in a .h file and the declarations are in corresponding .h files too. But I was trying to make it easier to see.

    But your point about concurrency/reentrancy is true...
    I first assign the data into the array during an interrupt service routine (when data arrives).
    then, when my main (while forever loop) gets chance it tries to service each of the array entries.

    I was able to find a work around using the following code:
    In PRL.c:

    for (x=0;x<=5;x++)	//ie copy bits 1-->7 into 0-->6
        {cmd_rxbuffer[rxbuff_write][x]=DLL_Rx_Buffer.databytes[x + 1];}
    

    and then in the TRL.c:
    for(i=0;i<=5;i++){Command_Response.Parameters[i] = cmd_rxbuffer[rxbuff_read][i+1];}
    

    All my declarations etc remained as they were in my previous thread.
    The for loops worked. Guess something strange with memcpy.

    Anyway, if anyone knows why original didnt work then id still like to know why for future reference!

    thanks for your advice,

    kind regards,
    peter

  • for (x=0;x<=5;x++)      //ie copy bits 1-->7 into 0-->6
    {cmd_rxbuffer[rxbuff_write][x]=DLL_Rx_Buffer.databytes[x + 1];}

    That comment doesn't match what the code actually does --- it's off by one. The code only actually copies 6 entries of the array [1..6]--> [0..5], not 7

    The memcpy() call copied 7 entries. Maybe that is your problem, after all?

  • Are you using an 8051 variant with dual data pointers? If so, memcpy() would make use of both pointers, while your main code would not. Are both pointers being preserved on the stack during your interrupt?