|
|
View previous topic :: View next topic |
Author |
Message |
john.ma
Joined: 19 Nov 2012 Posts: 23
|
Writing to structs with variables of variable length |
Posted: Tue Feb 19, 2013 5:16 am |
|
|
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? 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
|
|
Posted: Tue Feb 19, 2013 6:22 am |
|
|
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
|
|
Posted: Tue Feb 19, 2013 6:27 am |
|
|
'&&', 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
|
|
Posted: Tue Feb 19, 2013 6:43 am |
|
|
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
|
|
Posted: Tue Feb 19, 2013 7:11 am |
|
|
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
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
|
|
Posted: Tue Feb 19, 2013 7:40 am |
|
|
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
|
|
Posted: Tue Feb 19, 2013 7:53 am |
|
|
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 |
|
|
|
|
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
|