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

Constant array returns wrong value with variable index value
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
levdev



Joined: 19 May 2010
Posts: 36
Location: UK

View user's profile Send private message

PostPosted: Wed Jan 11, 2012 12:30 pm     Reply with quote

Your array will be 2048 bytes, which will just cross the boundary. Are you sure the last few variables are returned correctly?
levdev



Joined: 19 May 2010
Posts: 36
Location: UK

View user's profile Send private message

PostPosted: Wed Jan 11, 2012 2:51 pm     Reply with quote

OK, two strange things related to this issue. Take the following program:

Code:
#include <18F26K22.h>

#ROM 0x07F0 = {1000,1001,1002,1003,0xFFFF,0xFFFF,0xFFFF,0xFFFF}
#ROM 0x0800 = {1000,1001,1002,1003,0xFFFF,0xFFFF,0xFFFF,0xFFFF}

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES PUT                      //Power Up Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES noPROTECT                  //Code protected from reads
#FUSES noCPB
#FUSES EBTR
#FUSES NODEBUG

#use delay(clock=16Mhz)
#use rs232(uart1,baud=38400,bits=8,parity=N,stop=1,errors)

void Initialise_uC()
{
   setup_oscillator(OSC_16MHZ|OSC_INTRC|OSC_PLL_OFF);
   setup_wdt(WDT_OFF);
   setup_timer_0(T0_OFF);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
}

void main()
{
   int16 RETVAL;
   Initialise_uC();
   while(1)
   {
      read_program_memory(0x07F0,&RETVAL,2);
      printf("A=%lu\r",RETVAL);
      read_program_memory(0x0800,&RETVAL,2);
      printf("B=%lu\r",RETVAL);
   }
}

This should load the same data into ROM address starting 0x07F0 and then again at 0x0800. Checking the hex listing shows this is so.

Strange thing 1 : Why does
Code:
read_program_memory(0x0800,&RETVAL,2);
return a zero value (same is true for 0x0802, 0x0804 etc..).

Strange thing 2 : To test these values were being written to the device I read back the program memory and compared it to the original hex file. The segment of code at address 0x0800 is different. In the source file it reads :
Code:
:10 0800 00 E803 E903 EA03 EB03 FFFF FFFF FFFF FFFF 3E

and in the device file it reads
Code:
:10 0800 00 0003 E903 EA03 EB03 FFFF FFFF FFFF FFFF 26

You can see the first word is changed from 0xE803 to 0x0003. For clarity, 0xE803 with the bytes reversed is 0x03E8 which is the first element of the array (decimal 1000). So why is the device hex file different to the source file?

And can anyone help put this jigsaw together to reach an answer whereby I can just access the data in my array?
levdev



Joined: 19 May 2010
Posts: 36
Location: UK

View user's profile Send private message

PostPosted: Thu Jan 12, 2012 11:43 am     Reply with quote

Well I've found a workable solution to this problem which is posted below. I don't know if the original problem is compiler version specific, or device specific, but I'm surprised no one else here has had this problem before with constant arrays in ROM. The solution involves declaring the array using #ROM so the base address can be guaranteed, and using an assembly function to do the lookup. Accessing a constant array over 2Kb directly using the array index, or using read_program_memory doesn't seem to work. I did investigate the complied code for both to see why, but couldn't figure it out, and then realised even if I did figure it out, I can't change it anyway, so wrote the assembly function. A complete test program is shown below:

Code:
#include <18F26K22.h>
#DEVICE ICD=true
#DEFINE BASE_ADDR 0x0800   //Set this address to the location in ROM for the start of the array.  Should be an even number
#ROM BASE_ADDR = {-1000,1001,1002,1003,1004,1005,1006,1007}

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES PUT                      //Power Up Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOPROTECT                //Code protected from reads
#FUSES NOCPB                    //
#FUSES EBTR                     //
#FUSES DEBUG                  //Disables ICD debug mode

#USE delay(clock=16Mhz)
#USE rs232(uart1,baud=38400,bits=8,parity=N,stop=1,errors)

#DEFINE  TABLAT      0x0FF5
#DEFINE  TBLPTRL     0x0FF6
#DEFINE  TBLPTRH     0x0FF7
#DEFINE  TBLPTRU     0x0FF8

void Initialise_uC()
{
   setup_oscillator(OSC_16MHZ|OSC_INTRC|OSC_PLL_OFF);
   setup_wdt(WDT_OFF);
   setup_timer_0(T0_OFF);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
}

signed int16 get_cal_data(int16 ARRAY_INDEX)
{
   signed int16 CAL_DATA;
   int LSB,MSB;
   ARRAY_INDEX = (ARRAY_INDEX<<1) + BASE_ADDR;
   LSB = ARRAY_INDEX;
   MSB = ARRAY_INDEX>>8;
   #ASM
   CLRF     TBLPTRU
   MOVF     MSB,0
   MOVWF    TBLPTRH
   MOVF     LSB,0
   MOVWF    TBLPTRL
   TBLRD*+
   MOVF     TABLAT,W
   MOVWF    LSB
   TBLRD*+
   MOVF     TABLAT,W
   MOVWF    MSB
   #ENDASM
   CAL_DATA = (signed int16)make16(MSB,LSB);
   return(CAL_DATA);
}

void main()
{
   signed int16 RETVAL;
   int16 a;
   Initialise_uC();
   while (1)
   {
      for(a=0;a<8;a++)
      {
         RETVAL=get_cal_data(a);
         printf("a=%lu\tCD=%ld\r",a,RETVAL);
         delay_ms(50);
      }
   }
}


Any comments welcome, I'm interested in particular to know if anyone else has faced this problem.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Thu Jan 12, 2012 3:03 pm     Reply with quote

OK i'll bite ;-))

Quote:

Locations after the 0x800 page boundary (where you might expect a problem).


I don't expect trouble anywhere in program memory ;-))

SO what is a PAGE boundary in 18F program memory ??

The data sheet was singularly un informing on that.

Sure i know about DATA ram pages - but i thought program flash was a contiguous address space on 18F parts -
where do i find out about a specific location being trouble ?

What issue about program memory am i not getting here ?

something unique to THIS part - or all parts?
temtronic



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

View user's profile Send private message

PostPosted: Thu Jan 12, 2012 3:18 pm     Reply with quote

Ok silly question....

What does MPLAB say are the contents of the PIC at those memory locations ?

Reason ? You've got two chances of 'program error'. Either the data isn't getting stored right or the program doesn't read it correctly.
levdev



Joined: 19 May 2010
Posts: 36
Location: UK

View user's profile Send private message

PostPosted: Thu Jan 12, 2012 4:44 pm     Reply with quote

The program memory is correct in both the source file and on the device. I have checked both. The new function I wrote confirms that because it reads the correct values. The problem I'm sure is with the code compiled by the CCS compiler to read the values.

There are no page boundaries in ROM on the PIC18526K22 it is a continuous space from 0x0000 to 0xFFFF. The program counter is 21bit which can address 2Mb, I'm not sure why, probably for compatability issues. I would be interested to know if anyone can confirm the problem on another device in this family.

Just to confirm the problem is not to do with the size of the array as I previously said, just the location of the data in ROM. Any data located after 0x0800 does not read back properly when accessed as an array with a variable index, or using the read_program_memory command.

I happy for now that I've got a solution, just a shame such a simple thing can waste so much time.
levdev



Joined: 19 May 2010
Posts: 36
Location: UK

View user's profile Send private message

PostPosted: Fri Jan 13, 2012 8:50 am     Reply with quote

OK, last post on the subject. I've actually found the root cause and it's so simple I must be stupid not to have found it earlier.

Code:
#FUSES EBTR


protects the memory from table reads. This stops the array from looking up its values, and read_program_memory from doing it's thing. Seemingly only for ROM address space 0x0800 onwards. Replace with

Code:
#FUSES NOEBTR


If you feel like reading this post has been a waste of time, imagine how I feel Smile
Ttelmah



Joined: 11 Mar 2010
Posts: 19730

View user's profile Send private message

PostPosted: Fri Jan 13, 2012 9:00 am     Reply with quote

Agreed about 'page boundaries' as such, but there are maths boundaries. The array code goes wrong at present, if you access an array that crosses the 0xffff to 10000 boundary (where a different byte has to be transferred to the upper address). Historically it commonly went wrong with accesses that crossed 256byte areas. The access is through three separate registers, and updating carries through all of them does give problems.

The 'joke' is that your chip is behaving differently from most others regarding EBTR. On most chips if EBTR is enabled, table accesses won't work at all.
On your's EBTRB controls the bottom 2048bytes, then EBTR controls the area above this. However what is odd is that the first two bytes above the 2K boundary, actually seem to transfer OK....

Best Wishes
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri Jan 13, 2012 9:01 am     Reply with quote

Not to feel bad - I never noticed that you had EBTR as a fuse.

for me
I have a LONG list of NOxx fuses in all my inits.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
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