|
|
View previous topic :: View next topic |
Author |
Message |
GregReadUK
Joined: 24 Jan 2011 Posts: 6 Location: Kent, UK
|
Issues with structures on 24F and v4.118 |
Posted: Mon Jan 24, 2011 6:31 am |
|
|
Hi Folks,
I am encountering an issue with structures on a PIC24F and v4.118 of compiler (Pretty sure I saw this with a few earlier compiler versions too).
Simple code is below, I initialise structure then call a function which modifies a couple of the members.
Why is structure.a32var getting set to 0 when I subtract 1 from structure.b32var?
Interestingly if reverse the order of the structure member variables to
Code: |
typedef struct
{
unsigned int32 a32var;
unsigned int32 b32var;
} MYSTRUCT;
|
the code seems to work, but I suspect if I have more structure variables after b32var they would be getting written over instead.
Any advice welcomed.
Thanks,
Greg
Expected results:
DEVICE:PIC24FJ64GA004
COMPILER VERSION:4.118
MyStruct:500 999
MyStruct:123 998
Actual results:
DEVICE:PIC24FJ64GA004
COMPILER VERSION:4.118
MyStruct:500 999
MyStruct:0 998
Simplfied Code (24F on v4.118 compiler):
Code: |
#include <24FJ64GA004.h>
#device *=16
#fuses NOWDT
#fuses ICSP1
#fuses NOWRT
#fuses NOPROTECT
#fuses NOJTAG
#fuses NOCKSFSM // NO FAIL SAFE CLOCK MONITOR
#fuses OSCIO // OSC 2 IS A GENERAL PURPOSE INPUT
#fuses NOIESO // THIS CAUSES IT TO BOOT OFF THE INTERNAL CRYSTAL IF EXTERNAL FAILED
//#fuses IESO
#fuses HS // USE EXTERNAL HIGH SPEED OSCILLATOR
#fuses PR // RUN OSCILLATOR AT HS OSCILLATOR SPEED
// #use delay(clock=22118400)
#use delay(clock=25M)
// I2C definition for clock
//#USE I2C(MASTER, I2C1, FORCE_HW, RESTART_WDT)
#USE I2C(MASTER, SCL=PIN_B6, SDA=PIN_B5, RESTART_WDT)
#use rs232(baud=115200,parity=N,bits=8,errors,XMIT=PIN_B8,RCV=PIN_B13)
void Debug_putc(BYTE Data)
{
putc(Data);
}
typedef struct
{
unsigned int32 b32var;
unsigned int32 a32var;
} MYSTRUCT;
void a(MYSTRUCT *pStruct)
{
pStruct->a32var = 123;
pStruct->b32var -= 1;
}
void main()
{
MYSTRUCT myStruct;
memset(&myStruct, 0, sizeof(MYSTRUCT));
// Initialise structure
myStruct.a32var = 500;
myStruct.b32var = 999;
printf(Debug_putc, "DEVICE:%s\r\n", getenv("DEVICE"));
printf(Debug_putc, "COMPILER VERSION:%s\r\n", getenv("VERSION_STRING"));
// dump contents of structure
printf(Debug_putc, "MyStruct:%lu %lu\r\n", myStruct.a32var, myStruct.b32var);
// Call simple function that modifies contents of stucture
a(&myStruct);
// dump contents of structure -- why is a32var now 0?
printf(Debug_putc, "MyStruct:%lu %lu\r\n", myStruct.a32var, myStruct.b32var);
} |
|
|
|
GregReadUK
Joined: 24 Jan 2011 Posts: 6 Location: Kent, UK
|
|
Posted: Mon Jan 24, 2011 6:35 am |
|
|
This issue may be related to the -= operation on the structure member.
Changing to the code below makes it work as expected.
void a(MYSTRUCT *pStruct)
{
pStruct->a32var = 123;
pStruct->b32var = pStruct->b32var - 1;
}
Is the original code incorrect or is this a compiler issue?
All advice appreciated,
thanks,
Greg |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Mon Jan 24, 2011 8:22 am |
|
|
It's a bug, newly introduced in V4.108 or V4.109. It's caused by incrementing an address erroneously twice, in 003F0 and 003F4. Instead of writing the carryover to the highword of b32var, it's written to a32var.
It's a typical PCD arithmetic bug, they come and go, although the product is slowly improving. I fear, the only chance for CCS to get rid of it, besides of better considering compiler changes, is to implement automated test suites that must be run before a new version is released. Of course, new detected bugs have to be added to the test collection. There are several commercial products availiable, also the GCC test suites most likely would have revealed many of the bugs found during the last years.
Code: | 39: void a(MYSTRUCT *pStruct)
40: {
003D4 781F85 mov.w 0x000a,[0x001e++]
41: pStruct->a32var = 123;
003D6 200040 mov.w #0x4,0x0000
003D8 B40808 add.w 0x0808,0x0000
003DA 780280 mov.w 0x0000,0x000a
003DC 2007B4 mov.w #0x7b,0x0008
003DE 980284 mov.w 0x0008,[0x000a+0]
003E0 200004 mov.w #0x0,0x0008
003E2 980294 mov.w 0x0008,[0x000a+2]
42: pStruct->b32var -= 1;
003E4 200000 mov.w #0x0,0x0000
003E6 B40808 add.w 0x0808,0x0000
003E8 780280 mov.w 0x0000,0x000a
003EA 780215 mov.w [0x000a],0x0008
003EC 520061 sub.w 0x0008,#1,0x0000
003EE 780A80 mov.w 0x0000,[0x000a]
003F0 780255 mov.w [++0x000a],0x0008 // now pointing to b32var.H
003F2 5A0060 subb.w 0x0008,#0,0x0000
003F4 980290 mov.w 0x0000,[0x000a+2] // data moved to a32var.L
43: }
003F6 7802CF mov.w [--0x001e],0x000a
003F8 060000 return |
|
|
|
GregReadUK
Joined: 24 Jan 2011 Posts: 6 Location: Kent, UK
|
|
Posted: Mon Jan 24, 2011 8:33 am |
|
|
Many thanks for the detailed clarification. I can work around it for now by not using -=.
I agree that once test cases are known, automated test tools definitely help to ensure higher quality consistency in functionality. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Mon Jan 24, 2011 10:48 am |
|
|
Yes, unfortunately the lack of just about any testing, is one of the biggest 'gripes' about CCS....
As a comment, I would add #case, and get rid of *=16 to your setups. *=16, is not used/needed on any chip after the PIC18 family, and you are using the same name for a typedef, and an actual variable, distinguished only by case, and if you want to do this, I would switch the compiler to use case significance.
Best Wishes |
|
|
GregReadUK
Joined: 24 Jan 2011 Posts: 6 Location: Kent, UK
|
|
Posted: Mon Jan 24, 2011 11:04 am |
|
|
Thanks for the tips, *= 16 and #case.
Variable name co-incidence was a happy accident I hadn't even noticed. |
|
|
|
|
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
|