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 support@ccsinfo.com

Corruption of const data if read from main and interrupts.

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Jim Hearne



Joined: 22 Dec 2003
Posts: 109
Location: West Sussex, UK

View user's profile Send private message Send e-mail Visit poster's website

Corruption of const data if read from main and interrupts.
PostPosted: Tue Mar 11, 2008 4:06 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Mar 11, 2008 4:14 am     Reply with quote

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







PostPosted: Tue Mar 11, 2008 6:05 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Mar 11, 2008 6:12 am     Reply with quote

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







PostPosted: Tue Mar 11, 2008 6:32 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Mar 11, 2008 6:57 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Mar 11, 2008 9:34 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Mar 11, 2008 10:09 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Mar 11, 2008 11:16 am     Reply with quote

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







PostPosted: Tue Mar 11, 2008 3:30 pm     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Mar 12, 2008 3:06 am     Reply with quote

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
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