 |
 |
View previous topic :: View next topic |
Author |
Message |
levdev
Joined: 19 May 2010 Posts: 36 Location: UK
|
|
Posted: Wed Jan 11, 2012 12:30 pm |
|
|
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
|
|
Posted: Wed Jan 11, 2012 2:51 pm |
|
|
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
|
|
Posted: Thu Jan 12, 2012 11:43 am |
|
|
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
|
|
Posted: Thu Jan 12, 2012 3:03 pm |
|
|
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
|
|
Posted: Thu Jan 12, 2012 3:18 pm |
|
|
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
|
|
Posted: Thu Jan 12, 2012 4:44 pm |
|
|
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
|
|
Posted: Fri Jan 13, 2012 8:50 am |
|
|
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.
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
If you feel like reading this post has been a waste of time, imagine how I feel  |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19730
|
|
Posted: Fri Jan 13, 2012 9:00 am |
|
|
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
|
|
Posted: Fri Jan 13, 2012 9:01 am |
|
|
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. |
|
 |
|
|
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
|