Structure Array Missing Values

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Structure Array Missing Values

Jump to solution
1,314 Views
rayhall
Contributor V

Hello,

I am not sure this is the correct place to post this.

I am using the S12XE and when I transfer the values in a structure to a PC program I find many of the frame[4]  values are 0x00.

The structure uses a array of structures. Here is the structure,

-----------  File  cal.h  ------------------

typedef struct CanBusSettings {
       uint8_t startChar; // $ Start character
         uint8_t PacketHi;
       uint8_t PacketLo;
         uint8_t PacketID;
         uint8_t freq;
         uint8_t busEnabled;
         uint8_t readCanData;
         uint16_t readID;
         struct FrameSettings {
              uint8_t enabled;
             uint8_t rate;
             uint16_t id;
            uint8_t byteOrder;
            uint8_t data[8];
         }frame[4];             
       uint16_t crcCnt;
}CAN_Bus;

-----------  File cal.c -----------------

CAN_Bus can  = {
    
        0x24,    // $ Start character
        0x10,    // Packet Size Hi
        0x00,    // Packet Size Lo
        0x08,    // Packet ID
        0x01,    // Freq       500 kbit
        0x01,    // busEnabled
        0x01,    // readCanData
        0x0064,  // readID 100
        
        0x00,    // frame 0 enabled
        0x03,    // frame 0 rate
        0x03E8,  // frame 0 id (1000)
        0x00,    // frame  0 byte order
        {1,0,0,0,0,0,0,0}, // frame 0 data
        0x00,    // frame 1 enabled
        0x03,    // frame 1 rate
        0x03E9,  //frame 1 id (1001)
        0x00,    // frame 1 byte order
        {0,1,0,0,0,0,0,0}, // frame 1 data        
        0x00,    // frame 2 enabled
        0x03,    // frame 2 rate
        0x03EA,  // frame 2 id (1002)
        0x00,    // frame 2 byte order
        {0,0,1,0,0,0,0,0}, // frame 2 data        
        0x00,    // frame 3 enabled
        0x03,    // frame 3 rate
        0x03EB,   // frame 3 id (1003)
        0x00,    // frame 3 byte order
        {0,0,0,1,0,0,0,0}, // frame 3 data  
                          
        0,       // crcCnt
        
};

The frame[4] struct will only have the values for frame[0]; The rest are 0x00;

I have included my test program. I am not capable of using the debugger to see if the values are in memory. This is why I need help to show the problem is not CodeWarrior or the S12XE memory.

Ray.

Labels (1)
0 Kudos
1 Solution
1,046 Views
kef2
Senior Contributor IV

HI,

your struct initializer doesn't match your struct. Missing curly brackets around struct array initializer part, also missing brackets around struct array struct-element. Only first array element gets initialized.

CAN_Bus can  = {
   
     0x24,    // $ Start character
     0x10,    // Packet Size Hi
     0x00,    // Packet Size Lo
     0x08,    // Packet ID
     0x01,    // Freq       500 kbit
     0x01,    // busEnabled
     0x01,    // readCanData
     0x0064,  // readID 100
    
     {
       {     
      0x00,    // frame 0 enabled
      0x03,    // frame 0 rate
      0x03E8,  // frame 0 id (1000)
      0x00,    // frame  0 byte order
      {1,0,0,0,0,0,0,0}, // frame 0 data
      },
      {
      0x00,    // frame 1 enabled
      0x03,    // frame 1 rate
      0x03E9,  //frame 1 id (1001)
      0x00,    // frame 1 byte order
      {0,1,0,0,0,0,0,0}, // frame 1 data
      },
      {
      0x00,    // frame 2 enabled
      0x03,    // frame 2 rate
      0x03EA,  // frame 2 id (1002)
      0x00,    // frame 2 byte order
      {0,0,1,0,0,0,0,0}, // frame 2 data
      },
      {
      0x00,    // frame 3 enabled
      0x03,    // frame 3 rate
      0x03EB,   // frame 3 id (1003)
      0x00,    // frame 3 byte order
      {0,0,0,1,0,0,0,0}, // frame 3 data 
      }
                 ,
     },
     0,       // crcCnt
};

Calculations are correct.

Edward

View solution in original post

10 Replies
1,045 Views
kef2
Senior Contributor IV

Hi Ray,

I tried with different and much more modern C99 compiler for different architecture, no warning either. Remove array of structs member and both start complaining about extra data. Yet another C compiler oddity.

Edward

0 Kudos
1,045 Views
kef2
Senior Contributor IV

Hi,

Structs are not portable. Different architectures and compilers have different struct paddings and alignments. More than that, PC is little endian while S12X is big endian. If you send and receive struct as binary, as is, then no wonder PC sees it differently.

Your attachment is virtually blank, no code which sends struct to PC.

Edward

0 Kudos
1,045 Views
rayhall
Contributor V

Hello Edward,

I know I have to swap bytes on any 16 bit values the PC software receives.

I did not include anything other then the structure as I wanted help to see if the values are correct in the S12x memory.


When I change the structure (see code below) so their is no array of struct,  the data the PC receives is correct. Based on this I presume the S12x compiler/linker does not like array of struct.

typedef struct CanBusSettings {
       uint8_t startChar; // $ Start character
         uint8_t PacketHi;
       uint8_t PacketLo;
         uint8_t PacketID;
         uint8_t freq;
         uint8_t busEnabled;
         uint8_t readCanData;
         uint16_t readID;
       
         uint8_t enabled_frame1;
         uint8_t rate_frame1;
        uint16_t id_frame1;
        uint8_t byteOrder_frame1;
        uint8_t data[8]_frame1;


       uint8_t enabled_frame2;
         uint8_t rate_frame2;
        uint16_t id_frame2;
        uint8_t byteOrder_frame2;
        uint8_t data[8]_frame2;

         uint8_t enabled_frame3;
         uint8_t rate_frame3;
        uint16_t id_frame3;
        uint8_t byteOrder_frame3;
        uint8_t data[8]_frame3

;

        uint8_t enabled_frame4;
         uint8_t rate_frame4;
        uint16_t id_frame4;
        uint8_t byteOrder_frame4;
        uint8_t data[8]_frame4;        


       uint16_t crcCnt;
}CAN_Bus;

0 Kudos
1,046 Views
kef2
Senior Contributor IV

Hi,

No, your assumptions are wrong. There's no compiler, in which you could assume packed struct without any padding or alignment. Changing optimization settings alignment can be switched on/off to achieve better optimization. Again, you can't  send struct as is to different architecture and assume correct operation. Struct doesn't guarantee memory layout, it guarantees only proper storage of specific struct members within the project while all source files accessing the same struct are compiled with same compiler settings.

Try using offsetof() macro from stddef.h on both, S12X and PC. On S12X, default settings:

typedef struct CanBusSettings {
       uint8_t startChar; // $ Start character
         uint8_t PacketHi;
       uint8_t PacketLo;
         uint8_t PacketID;
         uint8_t freq;
         uint8_t busEnabled;
         uint8_t readCanData;
         uint16_t readID;
         struct FrameSettings {
              uint8_t enabled;
             uint8_t rate;
             uint16_t id;
            uint8_t byteOrder;
            uint8_t data[8];
         }frame[4];             
       uint16_t crcCnt;
}CAN_Bus;

#include <stddef.h>

volatile int bs[10];

...

{

  bs[0] = offsetof(CAN_Bus, frame); /*9*/
  bs[1] = offsetof(CAN_Bus, frame[0].byteOrder); /*13*/
  bs[2] = offsetof(CAN_Bus, frame[1]);           /*22*/
  bs[4] = offsetof(CAN_Bus, frame[1].byteOrder); /*26*/

}

filed offsets in comments are consistent with unaligned and packed struct, members order in struct unchanged. You can disassemble C source to see field offsets:

06:    bs[0] = offsetof(CAN_Bus, frame); /*9*/
  0000 c609         [1]     LDAB  #9  <----------------
  0002 87           [1]     CLRA 
  0003 7c0000       [3]     STD   bs
  107:    bs[1] = offsetof(CAN_Bus, frame[0].byteOrder); /*13*/
  0006 c60d         [1]     LDAB  #13 <---------------
  0008 7c0000       [3]     STD   bs:2
  108:    bs[2] = offsetof(CAN_Bus, frame[1]);
  000b c616         [1]     LDAB  #22 <---------------
  000d 7c0000       [3]     STD   bs:4
  109:    bs[4] = offsetof(CAN_Bus, frame[1].byteOrder); /*13*/
  0010 c61a         [1]     LDAB  #26 <---------------
  0012 7c0000       [3]     STD   bs:8
  11

On PC you probably will see different offsets, which is perfectly notmal.

Edward

0 Kudos
1,046 Views
rayhall
Contributor V

Hello Edward,

I understand that different micros and PC operating systems store data in memory in different ways.

The problem is I am only looking at the memory in the S12X and data values are missing. Here is the proof. I have attached a new version of my test program that calculates the checksum of the structure. I store the checksum value in the variable "cs"

I have included a screen shot of the debugger showing the calculated value is 65134.

(65535 - 65134) = 401

The problem is this is wrong. When I add up the values manually I get 1125.

Below shows the point where the count 401 occurs. This is exactly what I found when the data was sent to the PC. Only the first part (frame[0]) had values.

CAN_Bus can  = {
   
        0x24,    // $ Start character
        0x10,    // Packet Size Hi
        0x00,    // Packet Size Lo
        0x08,    // Packet ID
        0x01,    // Freq       500 kbit
        0x01,    // busEnabled
        0x01,    // readCanData
        0x0064,  // readID 100
        
        0x00,    // frame 0 enabled
        0x03,    // frame 0 rate
        0x03E8,  // frame 0 id (1000)
        0x00,    // frame  0 byte order
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  Count 401  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        {1,0,0,0,0,0,0,0}, // frame 0 data
        0x00,    // frame 1 enabled
        0x03,    // frame 1 rate
        0x03E9,  //frame 1 id (1001)
        0x00,    // frame 1 byte order
        {0,1,0,0,0,0,0,0}, // frame 1 data        
        0x00,    // frame 2 enabled
        0x03,    // frame 2 rate
        0x03EA,  // frame 2 id (1002)
        0x00,    // frame 2 byte order
        {0,0,1,0,0,0,0,0}, // frame 2 data        
        0x00,    // frame 3 enabled
        0x03,    // frame 3 rate
        0x03EB,   // frame 3 id (1003)
        0x00,    // frame 3 byte order
        {0,0,0,1,0,0,0,0}, // frame 3 data  
                          
        0,       // crcCnt

  // ^^^^^^^^^^^^^^^^^^^^^^^ Count  1125  ^^^^^^^^^^^^^^^^^^^^^^^^^^ 

};

0 Kudos
1,046 Views
kef2
Senior Contributor IV

I don't see where's your proof and what's wrong. Everything seems well. Which calculation is wrong? What and where do you see and what do you expect? 401 is wong? It's good.

Edward

0 Kudos
1,046 Views
rayhall
Contributor V

Edward,

Here is a screen shot of the debugger after I changed the code to just add up the values. It gives 402 which is wrong....

0 Kudos
1,047 Views
kef2
Senior Contributor IV

HI,

your struct initializer doesn't match your struct. Missing curly brackets around struct array initializer part, also missing brackets around struct array struct-element. Only first array element gets initialized.

CAN_Bus can  = {
   
     0x24,    // $ Start character
     0x10,    // Packet Size Hi
     0x00,    // Packet Size Lo
     0x08,    // Packet ID
     0x01,    // Freq       500 kbit
     0x01,    // busEnabled
     0x01,    // readCanData
     0x0064,  // readID 100
    
     {
       {     
      0x00,    // frame 0 enabled
      0x03,    // frame 0 rate
      0x03E8,  // frame 0 id (1000)
      0x00,    // frame  0 byte order
      {1,0,0,0,0,0,0,0}, // frame 0 data
      },
      {
      0x00,    // frame 1 enabled
      0x03,    // frame 1 rate
      0x03E9,  //frame 1 id (1001)
      0x00,    // frame 1 byte order
      {0,1,0,0,0,0,0,0}, // frame 1 data
      },
      {
      0x00,    // frame 2 enabled
      0x03,    // frame 2 rate
      0x03EA,  // frame 2 id (1002)
      0x00,    // frame 2 byte order
      {0,0,1,0,0,0,0,0}, // frame 2 data
      },
      {
      0x00,    // frame 3 enabled
      0x03,    // frame 3 rate
      0x03EB,   // frame 3 id (1003)
      0x00,    // frame 3 byte order
      {0,0,0,1,0,0,0,0}, // frame 3 data 
      }
                 ,
     },
     0,       // crcCnt
};

Calculations are correct.

Edward

1,046 Views
rayhall
Contributor V

Edward,

I would have thought the compiler would have given an error or warning.

Took a long time to get to this point, but if that is going to fix the problem then I am happy.

Thank you.

0 Kudos
1,046 Views
rayhall
Contributor V

Edward,

When the 8 bit values in the struct are added up the debugger gives a value of 65134. You must have not looked at how the checksum id calculated. It adds up all the 8 bit values and then substracts them form 65535. This gives a value of 65134. To find out what the count was you reverce the calculation by substracting the checksum value from 65535 and this gives you 401. This is wrong as when you manualy add up the values you get 1125.

II will change the checksum function so it just adds up the values. It will be a few hours before I can get to do this for you. If you want to do it yourself with my code change all the main.c code to this,

uint16_t CalculateStruct(uint8_t *StructurePointer, uint16_t pkt);


void main(void) {
  /* put your own code here */
 
  uint16_t cs;
 
  cs = CalculateStruct((uint8_t *)&can, sizeof(can));
 


    EnableInterrupts;


  for(;;) {
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}


//------------------ Calculate Struct  --------------------------

uint16_t CalculateStruct(uint8_t *StructurePointer, uint16_t pkt)
{
    uint16_t x;
    uint16_t cnt;

    pkt = pkt - 0x0002;
    cnt = 0;

    for (x = 0 ; x < pkt ; x++) {
        cnt = cnt + StructurePointer[x];
    }

    return(cnt);
}

0 Kudos