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