How to flash program memory?

Status
Not open for further replies.

Matteo Martinelli

Newbie level 6
Joined
Jan 10, 2014
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
77
Hi guys,
I need to flash program memory, actually I use this function for write/read EEPROM:

Write And Read:
Code:
unsigned short Eeprom_ReadWord(unsigned short addressHi, unsigned short  pushAddress) {
   unsigned short ushResult;
   register int eedata_addr; 
   register int eedata_val; 
   
   TBLPAG = addressHi; // __builtin_tblpage()
   eedata_addr = (unsigned short)pushAddress; // __builtin_tbloffset()
   __asm__("TBLRDL [%[addr]], %[val]" : [val]"=r"(eedata_val) : [addr]"r"(eedata_addr)); 
  
   ushResult = eedata_val; 
   return (ushResult);
}
void Eeprom_WriteWord(unsigned short addressHi, unsigned short pushAddress, unsigned short ushValue) {
   
   TBLPAG = addressHi;
   NVMADRU = addressHi; // Write address of word to be erased into NVMADRU, NVMADR registers.
   NVMADR = (unsigned short)pushAddress;
   NVMCON = ERASE_WORD; // Setup NVMCON register to erase one EEPROM word.
   
   //PROTECT_CODE_FROM_INTERRUPTS_START // Disable interrupts while the KEY sequence is written
      NVMKEY = 0x55; // Write the KEY sequence step1
      NVMKEY = 0xAA; // step2
      NVMCONbits.WR = 1; // Start the erase cycle
   //PROTECT_CODE_FROM_INTERRUPTS_STOP // Enable interrupts
   
   while (NVMCONbits.WR == 1); // wait for the EEPROM
   
   NVMCON = WRITE_WORD; // Setup NVMCON register to write one EEPROM word. 
   {
      register int eedata_addr; 
      register int eedata_val; 
      
      eedata_addr = (unsigned short)pushAddress; // write low word of address
      eedata_val = ushValue; // write data
      
      __asm__ volatile ("TBLWTL %[val], [%[addr]]" : [val]"+r"(eedata_val) : [addr]"r"(eedata_addr));
   }
   
   //PROTECT_CODE_FROM_INTERRUPTS_START // Disable interrupts while the KEY sequence is written
      NVMKEY = 0x55; // Write the KEY sequence step1
      NVMKEY = 0xAA; // step2
      NVMCONbits.WR = 1; // Start the erase cycle
   //PROTECT_CODE_FROM_INTERRUPTS_STOP // Enable interrupts
   
   while (NVMCONbits.WR == 1); // wait for the word to be written
   
   // no proper watchdog protection in the 2 while loops
   // no proper check if bytes are written correctly by re-reading them
}

And I use that functions as below
Code:
value = Eeprom_ReadWord(0x0000, 0x0002);
Eeprom_WriteWord(0x007F, 0xFC00, 0x0001);

I don't know how I can write in Program memory because OPCODE is formed by 8 byte and Eeprom_WriteWord allow to write only 4 byte.
Eeprom_ReadWord is the same of write.

Thank you everybody.
 

I don't know how I can write in Program memory because OPCODE is formed by 8 byte and Eeprom_WriteWord allow to write only 4 byte.
Neither correct. EEPROM write is in word (16 bit) entities. Flash programming is performed 32 instruction words (24 Bit each) at once. dsPIC33 and PIC24 also supports programming of single instruction words.

Everything is well explained in the dsPIC family reference manual, Section 5. Flash and EEPROM Programming and respective data sheets.
 
If I want to store only 1 OPCODE, for example:
I would write 000100 at address 000000.

Can I, or not?

- - - Updated - - -

I am trying to write in PM. I found this .asm library in AN1094 (Bootloader UART)

Code:
_LoadAddr:	;W0=NVMADRU,W1=NVMADR - no return values
	mov	W0,NVMADRU
	mov	W1,NVMADR
	
	return
	
;***************************************************************		
_WriteMem:	;W0=NVMCON - no return values
	mov	W0,NVMCON
	mov	#0x55,W0	;Unlock sequence - interrupts need to be off
	mov	W0,NVMKEY
	mov	#0xAA,W0
	mov	W0,NVMKEY
	bset NVMCON,#WR
	nop				;Required
	nop
1:	btsc NVMCON,#WR	;Wait for write end
	bra 1b
	
	return
	
;***************************************************************	
_WriteLatch: ;W0=TBLPAG,W1=Wn,W2=WordHi,W3=WordLo - no return values
	mov	W0,TBLPAG	
	tblwtl W3,[W1]
	tblwth W2,[W1]
	
	return
	
;***************************************************************	
_ReadLatch: ;W0=TBLPAG,W1=Wn - data in W1:W0
	mov	W0,TBLPAG	
	tblrdl [W1],W0
	tblrdh [W1],W1
	
	return


;***************************************************************

In main.c I typed:
Code:
#define PM_ROW_SIZE 32
#define CM_ROW_SIZE 7
#define CONFIG_WORD_SIZE 1

#define PM_ROW_ERASE 		0x4041
#define PM_ROW_WRITE 		0x4001
#define EE_ROW_ERASE 		0x4045
#define EE_ROW_WRITE 		0x4005
#define CONFIG_WORD_WRITE	0X4008

char Buffer[PM_ROW_SIZE*3 + 1];
	int    Size;
  	uReg32 SourceAddr;
	UWord32 Opcode;

	SourceAddr.Val[0] = 0;
	SourceAddr.Val[1] = 0;
	SourceAddr.Val[2] = 0;
	for(Size = 0; Size < PM_ROW_SIZE*3; Size++)
	{
		Buffer[Size] = Size;
	}
	SourceAddr.Word.HW = 0x0000;
	SourceAddr.Word.LW = 0x0000;
	LoadAddr(SourceAddr.Word.HW,SourceAddr.Word.LW);
	
	WriteMem(PM_ROW_ERASE);				/*Erase  page  */
	WritePM(Buffer, SourceAddr);		/*program page */

Why doesn't it work? When I run, why does target halt?
I don't know how to verify the correct writing.

Thanks.
 

Firstly, I can't recognize that the code follows the programming sequence specified in the dsPIC family reference manual under 5.4.2.1 Flash Program Memory Programming Algorithm. E.g. TBLPAG is never set.

Secondly, which flash memory range do you want to modify. Are you sure that your code isn't executing in the same area?

To change a single instruction, you need to copy the full row from flash to RAM, modify the content, erase and reprogram the row.
 

First of all, thanks for interesting.

I'm developing a bootloader therefore I write each line of .hex file.
I don't know what address I'll write, simply, I read every line, take address, take byte and write that.

Can I overwrite ALL firmware, or not?
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…