2006/02/02 14:20:22
DavidP5
I am trying to write to flash/program memory.
 
I have been looking at Trampas Sterns code as posted in this forum. His code is
for the p18f8680 but I am working with a p18f452. His code uses a register
called EEADRH (which is defined in p18f8680.h) but the p18f452 does not define
this register. In the p18F452.asm file there is the following definition:
EEADR               RES 1     ; 0xFA9
                       RES 1
It appears to me that the second byte (0xFAA?) is the byte corresponding to the
p18f8680 EEADRH register, but for some reason it is not named. I am new to
microcontroller programming and I'm not used to all this low-level stuff so I'm
not sure how best to modify Trampas's code to make it work for the p18f452.
My initial thought is to simply change the start of his EEpromPut function from:
 
void EEpromPut(UWORD addr, BYTE data)
{
  UWORDbytes temp;
  temp.data=addr;    //could use cast instead
  EEADRH = temp.high;
  EEADR = temp.low;
  ...
to:
 
void EEpromPut(UWORD addr, BYTE data)
{
  EEADR = addr;
  ...
 
Is this correct?
 
2006/02/02 14:41:22
DavidP5
Further to my last post, and thanks to Kalpak for pointing out that Trampas's code is
for writing to EEPROM, not flash memory. Can I modify his code to write to
flash by simply changing the EEPGD bit as follows?
 
His code:
void EEpromPut(UWORD addr, BYTE data)
{
  ....
  EECON1bits.EEPGD = 0;
  ....
 
Change to:
void EEpromPut(UWORD addr, BYTE data)
{
  ....
  EECON1bits.EEPGD = 1;
  ....
 
Thanks, David.

2006/02/02 17:55:04
DavidP5
It appears that the answer to my most recent question is NO.
So please don't bother to point this out.
 
2006/02/02 21:08:28
DavidP5
I'm still trying to find out how to write C code to write to program memory.
I'm not getting very far with this.
I wrote the following program based on code posted by Sekhar:
 
#include <p18F452.h>
rom unsigned char* startblock = 0x5000; // any number divisible by 64
rom unsigned char* buf; // temporary rom pointer
unsigned char mem[64] = "test"; // data holding buffer
void WriteDataToMemory(int block_no) {
  unsigned char i;
  TBLPTR = (unsigned int)(startblock + block_no * 64);
  buf = (rom unsigned char*)TBLPTR;
  EECON1bits.EEPGD = 1; // erase sequence
  EECON1bits.WREN = 1;
  EECON1bits.FREE = 1;
  INTCONbits.GIE = 0;
  EECON2 = 0x55;
  EECON2 = 0xaa;
  EECON1bits.WR = 1;
  Nop();
  INTCONbits.GIE = 1;
  EECON1bits.WREN = 0;
  for(i = 0;i < 64;i++){
    buf = mem;
    if(((i + 1) % 8) == 0){
      EECON1bits.EEPGD = 1; // write sequence for every 8 bytes
      EECON1bits.WREN = 1;
      INTCONbits.GIE = 0;
      EECON2 = 0x55;
      EECON2 = 0xaa;
      EECON1bits.WR = 1;
      Nop();
      INTCONbits.GIE = 1;
      EECON1bits.WREN = 0;
    }
  }
}
void main(void) {
  WriteDataToMemory(0);
  while(1);
}
I expected the string "test" to show up at 0x5000 in program memory after
running the program, but it didn't. I was not completely surprised by this
because this code does not seem to correspond to the guidelines given in the
datasheet (where are the holding registers getting filled?). The only other C
code that I found in this thread is an excerpt from a bootloader and it does not
make any sense to me at all.
Does anyone have any easily understandable and well-documented code that I could
use/modify to write a string to flash memory (please)?
Regards, David.

2006/02/02 21:20:00
kalpak
Add this to the beginning of your code and check

EECON1bits.EEPGS = 1

This is for selecting the flash
2006/02/03 12:29:17
DavidP5
ORIGINAL: kalpak

Add this to the beginning of your code and check

EECON1bits.EEPGS = 1

This is for selecting the flash

 
There is no EECON1bits.EEPGS. I presume you mean EEPGD, which I have set to 1 already.
2006/02/03 12:42:54
kalpak
A typo, try:

EECON1bits.CFGS=0;


Still a typo, it should be:

EECON1bits.CFGS=1;
2006/02/03 13:21:13
DavidP5
ORIGINAL: kalpak

A typo, try:

EECON1bits.CFGS=0;


 
Thanks, I have added that line, which I had overlooked previously. But it still doesn't write to flash memory. I can't see where the program is telling the processor which data to put into flash. The datasheet says that one must load the 8 holding registers with the data to be written for each 8-byte write, but this code does not seem to do that. The only line in the writing sequence code that might be indicating what to write is:
    buf = mem;
which I have altered to:
    buf = (rom unsigned char*) mem;
to suppress a compiler warning. But what on earth is "buf = mem" supposed to be doing? It seems to me that this line should be replaced with code to load the holding registers.
In the datasheet there is some assembly code that does this:
PROGRAM_LOOP
  MOVLW 8           ; number of bytes in holding register
  MOVWF COUNTER
WRITE_WORD_TO_HREGS
  MOVF POSTINC0, W  ; get low byte of buffer data
  MOVWF TABLAT      ; present data to table latch
  TBLWT+*           ; write data, perform a short write
                    ; to internal TBLWT holding register.
  DECFSZ COUNTER    ; loop until buffers are full
  BRA WRITE_WORD_TO_HREGS
but I'm not clear how to do this in C.
2006/02/04 15:51:08
DavidP5
This is my latest attempt at writing a block of ram to flash:
 
#include <p18F452.h>
void memcpyram2flash(unsigned addr, char * mem) {
 unsigned char i;
 TBLPTR = addr;
 //TBLPTR <<= 6;  // erasure uses TBLPTR bits [21:6] to point to program memory address
 // erase row of 64 bytes starting at TBLTPTR address
 EECON1bits.EEPGD = 1;
 EECON1bits.WREN = 1;
 EECON1bits.FREE = 1;
 EECON1bits.CFGS = 0;
 INTCONbits.GIE = 0;
 EECON2 = 0x55;
 EECON2 = 0xaa;
 EECON1bits.WR = 1;
 Nop();
 INTCONbits.GIE = 1;
 EECON1bits.WREN = 0;
 //TBLPTR >>= 3; // TBLWT uses [21:3] to point to memory address, [2:0] identifies
        // each of the eight holding registers
 for(i = 0;i < 64;i++){
  TABLAT = mem;    // put a char into the table latch register
  _asm
   TBLWTPOSTINC     // write to holding register and post-increment TBLPTR
  _endasm
  if(((i + 1) % 8) == 0){ // after each 8-byte write to holding registers...
   EECON1bits.EEPGD = 1; // ...write the holding registers to flash
   EECON1bits.WREN = 1;
   EECON1bits.CFGS = 0;
   EECON1bits.FREE = 0;
   INTCONbits.GIE = 0;
   EECON2 = 0x55;
   EECON2 = 0xaa;
   EECON1bits.WR = 1;
   Nop();
   INTCONbits.GIE = 1;
   EECON1bits.WREN = 0;
  }
 }
}
 
void main(void) {
 // write test string to address 0x5000 in program memory
 char mem[64] = "test"; // string to be copied to flash
 memcpyram2flash(0x5000, mem);
 while(1);
}
 
It still doesn't seem to work. I'm not sure how to interpret the information in the datasheet about the various bits of the TBLPTR that are used for reading, erasing and writing so I experimented with shifting the bits around, but that did not help so I have commented those lines out.
 
Any suggestions please?
2006/02/04 19:35:13
kalpak
Please see my typo above, the CFGS bit selects EERPOM or flash. It should be:

EECON1bits.CFGS=1;

 
© 2021 APG vNext Commercial Version 4.5

Use My Existing Forum Account