|
|
View previous topic :: View next topic |
Author |
Message |
Jim Hearne
Joined: 22 Dec 2003 Posts: 109 Location: West Sussex, UK
|
Corruption of const data if read from main and interrupts. |
Posted: Tue Mar 11, 2008 4:06 am |
|
|
This appears to be a bug unless i'm missing something.
PCWH Ver 4.062 (also tried 4.053 and 4.069), Pic 18LF6722
I've the follow code in a timer 4 interrupt routine.
Code: |
int8 loop;
int8 bodge;
for(loop=0;loop<4;loop++) // output relay overrides
{
bodge=output_masks[loop]; // This line causes the problem
if(output_override[loop].current==OP_ON_OR) // if on override
int_copy_port_f |= bodge; // turn on output bit
else if(output_override[loop].current==OP_OFF_OR) // if off override
int_copy_port_f &= ~bodge; // turn off output bit
}
|
Where output_masks is declare as:
Code: | const int8 output_masks[4]={0b00010000,0b00100000,0b01000000,0b10000000}; |
And i have a function (not called from any ints) containing the following code:
Code: | void copystring(int8 *dest,int8 msg)
{
int32 copy_address=0;
int16 copy_temp=0;
if(msg>NUMBER_OF_STRINGS)
msg=135; // if msg is out of range then use error as msg
copy_address=STRING_ROM_ADDRESS+string_offsets[msg][nvram.language];
do
{
copy_temp = read_program_eeprom(copy_address);
copy_temp &= 0x00ff;
*dest=(int8)copy_temp;
dest++;
copy_address++;
}
while(copy_temp!=0);
}
|
With the following related declarations.
Code: | int16 string_offsets[NUMBER_OF_STRINGS][NUMBER_OF_LANGUAGES];
#define NUMBER_OF_LANGUAGES 3
#define STRING_ROM_ADDRESS 0x00010000
#ROM STRING_ROM_ADDRESS ={
// English Spanish Portuguese
" ", " ", " ", // 0 // menu and data messages
"% Post Bl'd", "% Pos Prga", "% Pós Bld", // 1
"12hr Clock", "Reloj 12hr ", "Relógio 12hr", // 2
"20mA Output", "Salida 20mA", "Saída 20mA", // 3
//////////// 178 lines here usually.
"~" //end character
}
#define NUMBER_OF_STRINGS 178 |
string_offsets[][] is filled with the address offsets of all the messages at power up in another routine but that all works fine.
The problem is that if that line of code bodge=output_masks[loop]; in the interrupt is excecuted while the do while loop is running in copystring() then the destination string is corrupted.
I can fix the problem by:
Not making output_masks[] a const.
Or by not using a loop and duplicating the code 4 times using output_masks[0]; , output_masks[1]; etc etc.
Or by disabling timer4 ints during the do while loop.
My suspicion is that it's the reads from the program memory in both sections of code thats causing the problem, especially since it's been mention on this forum before but i thought it was supposed to have been fixed by CCS disabling int's during the read operation.
My understanding of Pic assembler isn't good enough to follow whats in the .lst file but i can post the relevent sections for somebody else to look at if need be.
It's difficult to post a small demo program as the project is massive and uses a graphic LCD screen for output (no serial port available).
Many thanks for any help.
Jim |
|
|
Jim Hearne
Joined: 22 Dec 2003 Posts: 109 Location: West Sussex, UK
|
|
Posted: Tue Mar 11, 2008 4:14 am |
|
|
Associated assy code for timer 4 int.
Code: | .................... for(loop=0;loop<NUMBER_OUTPUTS;loop++) // output relay overrides
04EE6: CLRF loop
04EE8: MOVF loop,W
04EEA: SUBLW 03
04EEC: BNC 4F64
.................... {
.................... bodge=output_masks[loop];
04EEE: CLRF @03
04EF0: MOVF loop,W
04EF2: MOVFF INTCON,@@B10
04EF6: BCF INTCON.GIE/GIEH
04EF8: MOVLB 0
04EFA: CALL @const607
04EFE: MOVLB B
04F00: BTFSC @@x10.7
04F02: BSF INTCON.GIE/GIEH
04F04: MOVWF bodge
.................... if(output_override[loop].current==OP_ON_OR) // if on override
04F06: MOVF loop,W
04F08: MULLW 06
04F0A: MOVF PRODL,W
04F0C: CLRF @@x11
04F0E: MOVWF @@x10
04F10: MOVLW 03
04F12: ADDWF @@x10,W
04F14: MOVWF @01
04F16: MOVLW 00
04F18: ADDWFC @@x11,W
04F1A: MOVWF @03
04F1C: MOVF @01,W
04F1E: ADDLW output_override
04F20: MOVWF FSR0L
04F22: MOVLW output_override>>8
04F24: ADDWFC @03,W
04F26: MOVWF FSR0H
04F28: DECFSZ INDF0,W
04F2A: BRA 4F32
.................... int_copy_port_f |= bodge; // turn on output bit
04F2C: MOVF bodge,W
04F2E: IORWF int_copy_port_f,F
.................... else if(output_override[loop].current==OP_OFF_OR) // if off override
04F30: BRA 4F60
04F32: MOVF loop,W
04F34: MULLW 06
04F36: MOVF PRODL,W
04F38: CLRF @@x11
04F3A: MOVWF @@x10
04F3C: MOVLW 03
04F3E: ADDWF @@x10,W
04F40: MOVWF @01
04F42: MOVLW 00
04F44: ADDWFC @@x11,W
04F46: MOVWF @03
04F48: MOVF @01,W
04F4A: ADDLW output_override
04F4C: MOVWF FSR0L
04F4E: MOVLW output_override>>8
04F50: ADDWFC @03,W
04F52: MOVWF FSR0H
04F54: MOVF INDF0,W
04F56: SUBLW 02
04F58: BNZ 4F60
.................... int_copy_port_f &= ~bodge; // turn off output bit
04F5A: MOVF bodge,W
04F5C: XORLW FF
04F5E: ANDWF int_copy_port_f,F
.................... }
04F60: INCF loop,F
04F62: BRA 4EE8
.................... |
And for copystring:
Code: | ....................
.................... void copystring(int8 *dest,int8 msg)
.................... {
.................... int32 copy_address=0;
*
07398: MOVLB A
0739A: CLRF copy_address
0739C: CLRF copy_address+1
0739E: CLRF copy_address+2
073A0: CLRF copy_address+3
.................... int16 copy_temp=0;
073A2: CLRF copy_temp
073A4: CLRF copy_temp+1
....................
.................... if(msg>NUMBER_OF_STRINGS)
073A6: MOVF msg,W
073A8: SUBLW B3
073AA: BC 73B0
.................... msg=135; // if msg is out of range then use error as msg
073AC: MOVLW 87
073AE: MOVWF msg
073B0: CLRF 19
073B2: BTFSC INTCON.GIE/GIEH
073B4: BSF 19.7
073B6: BCF INTCON.GIE/GIEH
.................... copy_address=STRING_ROM_ADDRESS+string_offsets[msg][nvram.language-M_LANG_ENGLISH];
073B8: MOVLB B
073BA: CLRF ??65535+1
073BC: MOVFF msg,??65535
073C0: CLRF @MUL1616.P1+1
073C2: MOVLW 06
073C4: MOVWF @MUL1616.P1
073C6: MOVLB 0
073C8: CALL @MUL1616
073CC: BTFSC 19.7
073CE: BSF INTCON.GIE/GIEH
073D0: MOVFF 02,@@ADE
073D4: MOVFF 01,@@ADD
073D8: MOVLW 60
073DA: MOVLB 1
073DC: SUBWF nvram+115,W
073DE: CLRF @03
073E0: MOVWF @02
073E2: BCF STATUS.C
073E4: RLCF @02,F
073E6: RLCF @03,F
073E8: MOVF @02,W
073EA: MOVLB A
073EC: ADDWF @01,W
073EE: MOVWF @01
073F0: MOVF @@xDE,W
073F2: ADDWFC @03,F
073F4: MOVF @01,W
073F6: ADDLW string_offsets
073F8: MOVWF FSR0L
073FA: MOVLW string_offsets>>8
073FC: ADDWFC @03,W
073FE: MOVWF FSR0H
07400: MOVFF PREINC0,03
07404: MOVF POSTDEC0,F
07406: MOVFF INDF0,copy_address
0740A: MOVFF 03,copy_address+1
0740E: MOVLW 01
07410: MOVWF copy_address+2
07412: CLRF copy_address+3
....................
.................... do
.................... {
.................... copy_temp = read_program_eeprom(copy_address);
07414: MOVFF copy_address+2,TBLPTRU
07418: MOVFF copy_address+1,TBLPTRH
0741C: MOVFF copy_address,TBLPTRL
07420: TBLRD*+
07422: MOVF TABLAT,W
07424: TBLRD*
07426: MOVFF TABLAT,03
0742A: CLRF TBLPTRU
0742C: MOVWF copy_temp
0742E: MOVFF 03,copy_temp+1
.................... copy_temp &= 0x00ff;
07432: CLRF xDC
.................... *dest=(int8)copy_temp;
07434: MOVFF dest,FSR0L
07438: MOVFF dest+1,FSR0H
0743C: MOVFF copy_temp,INDF0
.................... dest++;
07440: INCF xD4,F
07442: BTFSC STATUS.Z
07444: INCF dest+1,F
.................... copy_address++;
07446: MOVLW 01
07448: ADDWF copy_address,F
0744A: BTFSC STATUS.C
0744C: INCF copy_address+1,F
0744E: BTFSC STATUS.Z
07450: INCF copy_address+2,F
07452: BTFSC STATUS.Z
07454: INCF copy_address+3,F
.................... }
.................... while(copy_temp!=0);
07456: MOVF copy_temp,F
07458: BNZ 7414
0745A: MOVF copy_temp+1,F
0745C: BNZ 7414
.................... }
0745E: MOVLB 0
07460: RETLW 00
....................
.................... | [/list] |
|
|
Ttelmah Guest
|
|
Posted: Tue Mar 11, 2008 6:05 am |
|
|
Do you know your silicon revision on the chip?.
There is a bug in these chips, on the A1 silicon revision, which results in registers being corrupted if the RETFIE 1 instruction is used in the interrupt handler. It only affects certain instructions, which array accesses in the main, use....
There is a crude 'bodge', you can use, if you are not using any high priority interrupts in your code. Simply program one 'dummy' handler, using the 'high' keyword, for an unused interrupt. Don't enable this interrupt. Then the compiler will use the RETFIE 1 instruction for this interrupt handler, and switch to using the slightly slower RETFIE ability in the normal interrupts. If this fixes the problem, then it proves where the fault is.
Best Wishes |
|
|
Jim Hearne
Joined: 22 Dec 2003 Posts: 109 Location: West Sussex, UK
|
|
Posted: Tue Mar 11, 2008 6:12 am |
|
|
Thanks for the quick reply.
How do i find out the silicon revision, there doesn't seem to be anything printed on top of the chip showing it.
I hope it's not underneath as they are all soldered.
I will try your "test" to she what happens, i'm not using any high priority interrupts.
Thanks,
Jim |
|
|
Ttelmah Guest
|
|
Posted: Tue Mar 11, 2008 6:32 am |
|
|
Read the device ID, in your programmer.
If the revision ID is '0', then it is the A1 revision.
Best Wishes |
|
|
Jim Hearne
Joined: 22 Dec 2003 Posts: 109 Location: West Sussex, UK
|
|
Posted: Tue Mar 11, 2008 6:57 am |
|
|
The Device ID reads as 13C0 so i guess it's the faulty revision.
Edit: Sorry to whoever posted about the #ORG error and then removed it.
I fixed that problem so thought i'd remove the details about it.
Jim
Last edited by Jim Hearne on Tue Mar 11, 2008 9:45 am; edited 2 times in total |
|
|
Jim Hearne
Joined: 22 Dec 2003 Posts: 109 Location: West Sussex, UK
|
|
Posted: Tue Mar 11, 2008 9:34 am |
|
|
With the dummy high Int the problem still occurs.
Any more thoughts please ?
Thanks,
Jim |
|
|
Jim Hearne
Joined: 22 Dec 2003 Posts: 109 Location: West Sussex, UK
|
|
Posted: Tue Mar 11, 2008 10:09 am |
|
|
Looking at the assy code with or without the dummy high int the compiler always seems to use RETFIE 0
Does the compiler know about the bug on the chip and work round it i wonder.
In which case my problem is something else.
Jim |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Mar 11, 2008 11:16 am |
|
|
Jim Hearne wrote: | Looking at the assy code with or without the dummy high int the compiler always seems to use RETFIE 0
Does the compiler know about the bug on the chip and work round it i wonder. | Good thinking! And yes, this is what's happening.
You can check this yourself by running chipedit.exe from the CCS directory. Select your chip and see which errata are activated for your chip. You will find the 'Don't use RETFIE 1' errata to be active. |
|
|
Ttelmah Guest
|
|
Posted: Tue Mar 11, 2008 3:30 pm |
|
|
Though it'll waste four bytes of RAM, I'd simply try declaring 'output_masks', without the const declarator, and report this as a bug.
If you want to work out what is happening, I'd be looking at the 'save' code at the start of the interrupt. It suggests one value used in the const table access code, is not being saved/restored properly.
Best Wishes |
|
|
Jim Hearne
Joined: 22 Dec 2003 Posts: 109 Location: West Sussex, UK
|
|
Posted: Wed Mar 12, 2008 3:06 am |
|
|
That might be safer.
I reported it as a bug several days ago but nothing back from CCS as yet, i expect they will sneak a fix into the next version like they usually do !
My concern is that my project uses large amounts of constant data and there could be another conflict thats not so obvious as corruption of the message strings on the display.
I guess to be safe i need to make sure there are no accesses to constant data from an interrupt.
Unfortunatly my Pic assembler isn't up to diagnosing the exact cause, i only ever look at it when theres a problem like this. I guess we get spoilt by using the compiler.
Thanks for your help,
Jim |
|
|
|
|
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
|