|
|
View previous topic :: View next topic |
Author |
Message |
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
16F1708 HEF usage |
Posted: Wed Jun 10, 2015 7:32 am |
|
|
I've some questions about the HEF of a 16F1708:
Where can I find the start address of the HEF?
edit: I think I found it in the datasheet 0F80h - 0FFFh
Do I have to use the write_program_memory or can I also use the write_eeprom_memory function?
CCS: 5.026 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Wed Jun 10, 2015 8:16 am |
|
|
You have to use write_program_memory, and (key thing) have to remember that everything on the program memory is done in pages. To change a single byte, you have to read the entire page, change just the byte you want, and write the whole page back. 32 instruction words (64 bytes) needing to be stored...
A search here will find some threads about this.
The data sheet couldn't be much clearer on where it is. Look at table 3-1.
However there is then another caveat.
The memory on these is 14bits wide. The HEF, is only the low 8bits of each instruction word. So 32 bytes out of each 64 written. |
|
|
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Fri Jun 12, 2015 8:40 am |
|
|
How do I have to write 47 decimal to the first address of the HEF?
I've tried this:
write_program_memory(0x0F80, 47, 2);
But that's not the way to use this function...can anyone help me? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Fri Jun 12, 2015 9:15 am |
|
|
Code: |
int16 val=47;
write_program_memory(0x0F80, &val, 2);
|
The second value needs to be a _pointer_ to the RAM containing the value to be written. |
|
|
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Fri Jun 19, 2015 4:21 am |
|
|
How many bytes is one page for the 16F1708? 64?
If I have 4 bytes to change, is it correct that I've one read_program_memory function and I put the results in a string, change the bytes I want and do one write_program_memory? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Fri Jun 19, 2015 2:04 pm |
|
|
Not a string, no.
A 'string', is an array of characters terminated by a '\0'.
You need to use 4 * int16 values, and remember that each (for this), can only hold numbers up to 16383.
Code: |
int16 configs[4]={1,2,3,4};
write_program_memory(0x0F80, configs, 8);
|
Remember in C, the name of an array, is the pointer to it, so the '&' is not needed here. |
|
|
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Mon Jul 13, 2015 7:38 am |
|
|
The limit of 16383 is not a problem because I want to save 8 bit integers.
I've tried something with the code you suggested, but it isn't working as I have written it.
Code: |
int16 configs[4]={150,17,230,104};
int I_cal = 100;
int I_0A = 100;
int I_16A = 100;
int komma_8 = 100;
configs[0] = I_cal;
configs[1] = I_0A;
configs[2] = I_16A;
configs[3] = komma_8;
write_program_memory(0x0F80, configs, 8);
|
In this case I see 2x 255, 1x 150 and 1x 0. Is it not possible to do it like I did? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Mon Jul 13, 2015 8:56 am |
|
|
1) How are you testing this?.
2) You need to protect the area, or the compiler may put things there - particularly constants.
3) Compiler version?. Still 5.026?.
There is a fault in some compiler versions with the automatic erase code not working. If this is the case for yours, you need to do this yourself (I haven't checked if .026 needs this):
Code: |
#byte PMADRH=getenv("SFR:PMADRH")
#byte PMADRL=getenv("SFR:PMADRL")
#bit CFGS=getenv("BIT:CFGS")
#bit WREN=getenv("BIT:WREN")
#bit FREE=getenv("BIT:FREE")
#BIT WR=getenv("BIT:WR")
#byte PMCON2=getenv("SFR:PMCON2")
void erase_program_eeprom(int16 address)
{
disable_interrupts(GLOBAL);
PMADRL=make8(address,0);
PMADRH=make8(address,1);
CFGS=FALSE;
FREE=TRUE;
WREN=TRUE;
PMCON2=0x55;
PMCON2=0xAA;
WR=TRUE;
delay_cycles(1);
delay_cycles(1);
enable_interrupts(GLOBAL);
}
|
|
|
|
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Tue Jul 14, 2015 12:44 am |
|
|
For testing I've this code which I send to the computer with RS232.
Code: |
read_program_memory(0x0F80, configs, 8);
I_cal = configs[0];
I_0A = configs[1];
I_16A = configs[2];
komma_8 = configs[3];
printf("%u",I_0A); putc(' ');
printf("%u",I_cal); putc(' ');
printf("%u",I_16A); putc(' ');
printf("%u",komma_8); putc(' ');
|
The compiler version is still 5.026.
I'm going to look at the ASM to check of the automatic erase is working (if I can recognize this with my very little knowlegde about ASM).
edit: this is the ASM code of the write_program_memory function (I think the original erase should be inside this function if 5.026 doesn't have this bug?).
Code: |
.................... write_program_memory(0x0F80, configs, 8);
01B2: MOVLW 0F
01B3: MOVLB 03
01B4: MOVWF 12
01B5: MOVLW 80
01B6: MOVWF 11
01B7: MOVLW 20
01B8: MOVWF 05
01B9: MOVLW 36
01BA: MOVWF 04
01BB: MOVLW 08
01BC: MOVLB 00
01BD: MOVWF 5C
|
Or do I always have to perform an erase_program_memory/eeprom before a write_program_memory function? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Tue Jul 14, 2015 2:36 am |
|
|
That is not the write_program_memory function.
That is just the 'setup' to load the registers required before calling the function.... |
|
|
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Tue Jul 14, 2015 3:16 am |
|
|
That's all the ASM which is under the write_program_memory function.
This is the read_program_memory:
Code: |
.................... read_program_memory(0x0F80, configs, 8);
047D: MOVLW 0F
047E: MOVLB 03
047F: MOVWF 12
0480: MOVLW 80
0481: MOVWF 11
0482: MOVLW 20
0483: MOVWF 05
0484: MOVLW 36
0485: MOVWF 04
0486: MOVLW 08
0487: MOVLB 00
0488: MOVWF 5C
0489: GOTO 05A
.................... I_cal = 100;
01A5: MOVLW 64
01A6: MOVWF 2E
.................... I_0A = 100;
01A7: MOVWF 2F
.................... I_16A = 100;
01A8: MOVWF 30
.................... komma_8 = 100;
01A9: MOVWF 45
....................
.................... configs[0] = I_cal;
01AA: MOVF 2E,W
01AB: MOVWF 56
.................... configs[1] = I_0A;
01AC: MOVF 2F,W
01AD: MOVWF 57
.................... configs[2] = I_16A;
01AE: MOVF 30,W
01AF: MOVWF 58
.................... configs[3] = komma_8;
01B0: MOVF 45,W
01B1: MOVWF 59
|
Where can I find the code to see of the erase function bug is in this version of the compiler? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Tue Jul 14, 2015 7:29 am |
|
|
Again, no it isn't.....
The read_program_memory function is at 0x5A. It again loads the registers _first_ then goes to the function. |
|
|
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Tue Jul 14, 2015 7:40 am |
|
|
Aah I get it...I've missed the GOTO.
This is at 5A:
Code: | 005A: MOVF 5C,W
005B: MOVWF 77
005C: BCF 03.0
005D: INCF 77,F
005E: RRF 77,F
005F: MOVLB 03
0060: BSF 15.0
0061: NOP
0062: NOP
0063: MOVF 13,W
0064: MOVWF 00
0065: INCF 04,F
0066: MOVF 14,W
0067: MOVWF 00
0068: INCF 04,F
0069: INCF 11,F
006A: BTFSC 03.2
006B: INCF 12,F
006C: DECFSZ 77,F
006D: GOTO 060
006E: MOVLP 00
006F: MOVLB 00
0070: GOTO 48A (RETURN)
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Tue Jul 14, 2015 8:24 am |
|
|
OK. Have looked in my archives, and have 5.025. Confirm this does not erase the page, or write correctly. Very likely that 5.026 won't either.
So have written (slightly cruder than the CCS version) replacement functions.
Also note I don't copy the variables around but leave them in the memory block that can be directly written/read.
Have included basically your test code, but modified the values so one can see they are different.
Also note you swap the order of the first and second values in the print.
Code: |
//Suitable header here
//Register and bit definitions
#byte PMADRH=getenv("SFR:PMADRH")
#byte PMADRL=getenv("SFR:PMADRL")
#byte PMDATH=getenv("SFR:PMDATH")
#byte PMDATL=getenv("SFR:PMDATL")
#bit CFGS=getenv("BIT:CFGS")
#bit WREN=getenv("BIT:WREN")
#bit FREE=getenv("BIT:FREE")
#bit LWLO=getenv("BIT:LWLO")
#BIT WR=getenv("BIT:WR")
#byte PMCON2=getenv("SFR:PMCON2")
#define HEF 0xF80
void my_erase_program_eeprom(int16 address)
{
//erases the page at the selected address
disable_interrupts(GLOBAL);
CFGS=FALSE;
PMADRL=make8(address,0);
PMADRH=make8(address,1);
CFGS=FALSE;
FREE=TRUE;
WREN=TRUE;
PMCON2=0x55;
PMCON2=0xAA;
WR=TRUE;
delay_cycles(1);
delay_cycles(1);
WREN=FALSE;
enable_interrupts(GLOBAL);
}
void my_write_program_memory(int16 address, int16 *data, int8 ctr)
{
//Beware - this does not erase a page for you, and will not handle
//a write that goes beyond the end of a page. Only works to
//write ctr bytes, to the program memory starting at address
int8 count;
disable_interrupts(GLOBAL);
WREN=TRUE;
CFGS=FALSE;
LWLO=TRUE; //load latches only
PMADRL=make8(address,0);
PMADRH=make8(address,1);
for (count=0;count<((ctr/2)-1);count++)
{
PMDATL=make8(data[count],0);
PMDATH=make8(data[count],1);
PMCON2=0x55;
PMCON2=0xAA;
WR=TRUE;
delay_cycles(1);
delay_cycles(1);
PMADRL++;
}
LWLO=FALSE;
PMDATL=make8(data[count],0);
PMDATH=make8(data[count],1); //last word
PMCON2=0x55;
PMCON2=0xAA;
WR=TRUE;
delay_cycles(1);
delay_cycles(1);
WREN=FALSE;
enable_interrupts(GLOBAL);
}
//memory layout definitions
struct twobytes
{
int8 l;
int8 h;
};
union prog_mem
{
int16 word;
struct twobytes b;
};
#ROM int16 HEF={0,0,0,0} //ensures the compiler will not accidentally
//put something else here.
void main(void) //crude demo program
{
struct
{
union prog_mem I_cal;
union prog_mem I_0A;
union prog_mem I_16A;
union prog_mem komma_B;
} values;
values.I_cal.b.l = 100;
values.I_0A.b.l = 101;
values.I_16A.b.l = 102;
values.komma_B.b.l = 103; //so they are different
//erase the page
my_erase_program_eeprom(HEF);
//write the values
my_write_program_memory(HEF, &values, 8);
//and read them back - CCS read works fine
read_program_memory(HEF,&values,8);
printf("%u ",values.I_0A.b.l);
printf("%u ",values.I_cal.b.l);
printf("%u ",values.I_16A.b.l);
printf("%u ",values.komma_B.b.l);
while(1)
{
delay_cycles(1);
}
}
|
|
|
|
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Tue Jul 14, 2015 9:01 am |
|
|
Thank you for your effort. I will check your program and will let you know tomorrow of it works.
It will also be time to get an new 1 year maintenance...this kind of bugs aren't nice to have. |
|
|
|
|
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
|