CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Writing to structs with variables of variable length

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
john.ma



Joined: 19 Nov 2012
Posts: 23

View user's profile Send private message

Writing to structs with variables of variable length
PostPosted: Tue Feb 19, 2013 5:16 am     Reply with quote

Hi Everyone,

Summary: PIC keeps restarting trying to write to a structure variable of 3 bits

I'm writing data to a structure as below:

Code:

struct Bx15_IRIGAnatomy {
   // frame 1
   int ref       : 1;
   int seconds0_3    : 4;
   int marker1      : 1;
   int seconds4_6   : 3;
   int position1   : 1;
   // frame 2   
   int minutes0_3    : 4;
        ... and so on
};

union DataBuffer {
   int8 SPI[bufferSize];
   int1 signalData[8*bufferSize];
   struct Bx15_IRIGAnatomy IRIG;
} SignalData[buffers]; // dual-buffer setup

 


The data I'm using comes from another structure called GPStime. I'm essentially just converting output formats....

Code:

   fprintf(debugUART,"Sec\n\r");
   // seconds - 7bits
   SignalData[bufferSelect].IRIG.seconds0_3 = GPStime.sec; // 4 bits
   
   fprintf(debugUART,"Sec1\n\r");
   SignalData[bufferSelect].IRIG.seconds4_6 = (GPStime.sec >> 4)  && 0x07; // 3bits
   
   fprintf(debugUART,"Min\n\r");


When I observe the serial output it gets to Sec1 and the PIC restarts, thus Im doing something wrong with SignalData[bufferSelect].IRIG.seconds4_6 = (GPStime.sec >> 4)

Perhaps this is a data misalignment or is my expression wrong? Confused It simulates fine which makes it a bit more difficult to debug.

PIC 24F16KA102
PCD 4.139

Thanks everyone,
John
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Feb 19, 2013 6:22 am     Reply with quote

WDT enabled ?
Without seeing a complete but small, compilable program it's impossible to say exactly why the PIC is restarting.
'works fine in simulation'...hmm..if Proteus, get rid of it..full of bugs,errors,faulty DRCs,etc.

'hard code' data into those variables and see what happens.If it still restarts then you KNOW the problem is NOT 'data misalignment...'.
ie:.

GPStime.sec=0x07;

SignalData[bufferSelect].IRIG.seconds0_3 = GPStime.sec; // 4 bits



hth
jay
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Tue Feb 19, 2013 6:27 am     Reply with quote

'&&', as in '(GPStime.sec >> 4) && 0x07' is the boolean (logical) and. In C the bitwise and, which is what you need, is, of course, '&'. That should not cause any memory alignment issues, and so is probably not the cause of your problem.

RF Developer
john.ma



Joined: 19 Nov 2012
Posts: 23

View user's profile Send private message

PostPosted: Tue Feb 19, 2013 6:43 am     Reply with quote

Sorry about that, the fuses are...

Code:

#include <24F16KA102.h>

#fuses NODEBUG      // Debug Mode. 1.11   NODEBUG   No Debug mode for ICD
#fuses FRC_PLL      // Crystal HS, 4xPLL -- FRC_PS : Internal OSC (8MHz) with postscaler (PS set automatically in #use delay)
#fuses NOIESO       // No 2-speed Start Up
#fuses NOPROTECT    // No Memory Protection
#fuses NOWDT        // No WatchDog Timer

#use delay(clock=32M, internal=8M)

// GPS interface on U1RX/RF2 and U1TX/RF3
#use rs232(UART1, STREAM=gpsUART, baud=9600, bits=8)
// Serial out interface on U2RX/RF4 and U2TX/RF5
#use rs232(UART2, STREAM=debugUART, baud=9600, bits=8)


This setup works fine in other programs. if I take the 'conversion' lines out the PIC is happy and continues until the end in hardware...
I dont use Proteus due to its anomalies, I used MPLAB SIM.

As for the &&, good point, silly me I applied the changes but it didn't solve the reset problem.

I did what temtronic said and put in a few values manually:

Code:

int InsertGPSTimeToIRIG(int bufferSelect)
{
   fprintf(debugUART,"Sec\n\r");
   // seconds - 7bits
   SignalData[bufferSelect].IRIG.seconds0_3 = GPStime.sec;
   
   fprintf(debugUART,"Sec1\n\r");
   SignalData[bufferSelect].IRIG.seconds4_6 = 0b010; //(GPStime.sec >> 4) & 0x07;
   
   fprintf(debugUART,"Min\n\r");
   // minutes - 7bits
   SignalData[bufferSelect].IRIG.minutes0_3 = GPStime.min;
   SignalData[bufferSelect].IRIG.minutes4_6 = 0x1111; //(GPStime.min >> 4) & 0x07;

   fprintf(debugUART,"Hour\n\r");
   // hours - 6bits
   SignalData[bufferSelect].IRIG.hours0_3 = (int8)GPStime.hour;
   SignalData[bufferSelect].IRIG.hours4_5 = (int8)(GPStime.hour >> 4) & 0x03;

   fprintf(debugUART,"Year\n\r");   
   // years - 8bits
   SignalData[bufferSelect].IRIG.year0_3 = (int8)GPStime.year;
   SignalData[bufferSelect].IRIG.year4_7 = (int8)(GPStime.year >> 4);
      
   // signal state - estimated or tracked
   SignalData[bufferSelect].IRIG.state = 0b11; // valid
   
   // error magnitude
   
   return 0;
}


So I simulated this and got:

CORE-E0002: Trap due to misaligned data word access, occurred from instruction at 0x000642
CORE-E0004: Trap due to unimplemented FLASH memory access, occurred from instruction at 0x000642

And interestingly it doesnt matter if there are the correct number of bits or not. I think it may have something to do with the nature of structs.
I read this in the PCD compiler manual:
Struct Rules:
- Fields 16 bits and up are aligned to a even byte boundry. Some Bits may be unused.
- No Field will span from an odd byte to an even byte unless the field width is a multiple of 16 bits.

Hm, is there a work around for this? The bit structure is a standard, not something I can change unless I implement it differently...

Regards,
John
john.ma



Joined: 19 Nov 2012
Posts: 23

View user's profile Send private message

PostPosted: Tue Feb 19, 2013 7:11 am     Reply with quote

Cut as much out as I could from the program:

For anyone who is interested, IRIG is a military & industrial timestamp
http://www.meinberg.de/german/info/irig.htm - they have nice diagrams Smile

Code:

#include <24F16KA102.h>

#fuses NODEBUG      // Debug Mode. 1.11   NODEBUG   No Debug mode for ICD
#fuses FRC_PLL      // Crystal HS, 4xPLL -- FRC_PS : Internal OSC (8MHz) with postscaler (PS set automatically in #use delay)
#fuses NOIESO       // No 2-speed Start Up
#fuses NOPROTECT    // No Memory Protection
#fuses NOWDT        // No WatchDog Timer

#use delay(clock=32M, internal=8M)

// GPS interface on U1RX/RF2 and U1TX/RF3
#use rs232(UART1, STREAM=gpsUART, baud=9600, bits=8)
// Serial out interface on U2RX/RF4 and U2TX/RF5
#use rs232(UART2, STREAM=debugUART, baud=9600, bits=8)

// SPI sends in packets of 8bits, thus sent data must be rounded up to nearest multiple of 8

#define bufferSize 13 // dont change
#define buffers 2 // dual buffer setup: one to write, one to read - alternate

int activeBuffer = 0;

struct GPSDateTimeStruct
{
   int8 hour; //hhmmss
   int8 min;
   int8 sec;
   int8 day; //ddmmyy
   int8 month;
   int8 year;
} GPStime;

// complies with B[0,2]-1-5
struct Bx15_IRIGAnatomy {
   // frame 1
   int ref       : 1;
   int seconds0_3    : 4;
   int marker1      : 1;
   int seconds4_6   : 3;
   int position1   : 1;
   // frame 2   
   int minutes0_3    : 4;
   int marker2    : 1;
   int minutes4_6   : 3;
   int empty2      : 1;
   int position2    : 1;
   // frame 3
   int hours0_3    : 4;
   int marker3    : 1;
   int hours4_5    : 2;
   int empty3       : 2;
   int position3    : 1;
   // frame 4
   int days0_3    : 4;
   int marker4    : 1;
   int days4_7    : 4;
   int position4    : 1;
   // frame 5
   int days8_9    : 2;
   int empty5_1   : 6; // CORE-E0002: Trap due to misaligned data word access, occurred from instruction
   int empty5_2   : 1; // No Field will span from an odd byte to an even byte unless the field width is a multiple of 16 bits
   int position5    : 1;
   // frame 6
   int year0_3    : 4;
   int marker6      : 1;
   int year4_7      : 4;
   int position6    : 1;
   // frame 7 - Control Function Field
   int state       : 2;
   int error0_6   : 7;
   int position7    : 1;
   // frame 8
   int error7_15   : 9;
   int position8    : 1;
   // frame 9 - Straight Binary Seconds : not used
   int empty9       : 9;
   int position9    : 1;
   // frame 10
   int empty10_1    : 6; // struct vars cant occupy multiple bytes
   int empty10_2   : 3;
   int position10    : 1;
};

union DataBuffer {
   int8 SPI[bufferSize];
   int1 signalData[8*bufferSize];
   struct Bx15_IRIGAnatomy IRIG;
} SignalData[buffers]; // dual-buffer setup


int ResetIRIGBuffers(void)
{
   int i;
   
   for( i=0; i<buffers; i++)
   {
      // reset everything to zero
      memset(&SignalData[i], 0, sizeof(SignalData[i]));

      SignalData[i].IRIG.ref = 1;
         
      SignalData[i].IRIG.position1  = 1;
      SignalData[i].IRIG.position2  = 1;
      SignalData[i].IRIG.position3  = 1;
      SignalData[i].IRIG.position4  = 1;
      SignalData[i].IRIG.position5  = 1;
      SignalData[i].IRIG.position6  = 1;
      SignalData[i].IRIG.position7  = 1;
      SignalData[i].IRIG.position8  = 1;
      SignalData[i].IRIG.position9  = 1;
      SignalData[i].IRIG.position10 = 1;
   }
   
   return 0;
}

int InsertGPSTimeToIRIG(int bufferSelect)
{
   fprintf(debugUART,"Sec\n\r");
   // seconds - 7bits
   SignalData[bufferSelect].IRIG.seconds0_3 = GPStime.sec;
   
   fprintf(debugUART,"Sec1\n\r");
   SignalData[bufferSelect].IRIG.seconds4_6 = 0b010; //(GPStime.sec >> 4) & 0x07;
   
   fprintf(debugUART,"Min\n\r");
   // minutes - 7bits
   SignalData[bufferSelect].IRIG.minutes0_3 = GPStime.min;
   SignalData[bufferSelect].IRIG.minutes4_6 = 0x111; //(GPStime.min >> 4) & 0x07;

   fprintf(debugUART,"Hour\n\r");
   // hours - 6bits
   SignalData[bufferSelect].IRIG.hours0_3 = (int8)GPStime.hour;
   SignalData[bufferSelect].IRIG.hours4_5 = (int8)(GPStime.hour >> 4) & 0x03;

   fprintf(debugUART,"Year\n\r");   
   // years - 8bits
   SignalData[bufferSelect].IRIG.year0_3 = (int8)GPStime.year;
   SignalData[bufferSelect].IRIG.year4_7 = (int8)(GPStime.year >> 4);
      
   // signal state - estimated or tracked
   SignalData[bufferSelect].IRIG.state = 0b11; // valid
   
   // error magnitude
   
   return 0;
}

void main()
{   
   int returnValue, i;

   // *** 1.1 Reset Signal Buffers
   ResetIRIGBuffers();
   
   InsertGPSTimeToIRIG(activeBuffer); // Potentially an issue
   
   fprintf(debugUART,"Done.\n\r");
   while(1);
}



I got these errors


CORE-E0002: Trap due to misaligned data word access, occurred from instruction at 0x0003fc
CORE-E0002: Trap due to misaligned data word access, occurred from instruction at 0x0003fc
CORE-E0004: Trap due to unimplemented FLASH memory access, occurred from instruction at 0x0003fc
CORE-E0004: Trap due to unimplemented FLASH memory access, occurred from instruction at 0x0003fc
CORE-E0004: Trap due to unimplemented FLASH memory access, occurred from instruction at 0x0003fe
CORE-E0002: Trap due to misaligned data word access, occurred from instruction at 0x000400
CORE-E0002: Trap due to misaligned data word access, occurred from instruction at 0x000400
jeremiah



Joined: 20 Jul 2010
Posts: 1345

View user's profile Send private message

PostPosted: Tue Feb 19, 2013 7:40 am     Reply with quote

I think your issue comes from using bit sizes that are not aligned to 8bit/16bit boundaries. I forget offhand if the PIC24 actually requires 8 bit boundaries, but I think it is 16bit boundary, so you need to make sure your struct variable sizes add up to 16bit values (16,32, 48, 64, etc) at the boundaries.

As an example:

Code:

struct{
   int var1 : 1;  //sum=1
   int var2 : 3;  //sum=4
   int var3 : 4;  //sum=8
   int var4 : 5;  //sum=13
   int var5 : 3;  //sum=16  GOOD!
} test;


vs

Code:

struct{
   int var1 : 1;  //sum=1
   int var2 : 3;  //sum=4
   int var3 : 4;  //sum=8
   int var4 : 5;  //sum=13
   int var5 : 4;  //sum=17  BAD!
} test;


If you need fillers, you can also do something like this:
Code:

struct{
   int var1 : 1;  //sum=1
   int var2 : 3;  //sum=4
   int var3 : 4;  //sum=8
   int var4 : 5;  //sum=13
   int      : 3;   //sum=16 GOOD!
   int var5 : 4;  //sum=20
} test;
john.ma



Joined: 19 Nov 2012
Posts: 23

View user's profile Send private message

PostPosted: Tue Feb 19, 2013 7:53 am     Reply with quote

Thanking you Jeremiah,

In a nutshell I wont be able to use a struct to model the packet as shown in the diagram below?


As an alternative I was thinking of using an array to store the bit count from the start to the individual fields, e.g. minutes0_3 = 11 bits, minutes4_6 = 16 and so on... however, that's not as elegant as the first solution as it entails counting all the time.

Doesn't seem to be a quick way without additional functions to read data in/out :/

Thanks everyone,
John
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group