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

16F1708 HEF usage
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mvanvliet



Joined: 02 Jun 2009
Posts: 123
Location: The Netherlands

View user's profile Send private message

16F1708 HEF usage
PostPosted: Wed Jun 10, 2015 7:32 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jun 10, 2015 8:16 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jun 12, 2015 8:40 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jun 12, 2015 9:15 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jun 19, 2015 4:21 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jun 19, 2015 2:04 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Jul 13, 2015 7:38 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Jul 13, 2015 8:56 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jul 14, 2015 12:44 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jul 14, 2015 2:36 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jul 14, 2015 3:16 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jul 14, 2015 7:29 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jul 14, 2015 7:40 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jul 14, 2015 8:24 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jul 14, 2015 9:01 am     Reply with quote

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.
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 1, 2, 3  Next
Page 1 of 3

 
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