View previous topic :: View next topic |
Author |
Message |
pmaggi
Joined: 05 Jun 2013 Posts: 10
|
Errors writing to program memory in 16f1825 |
Posted: Sun Apr 27, 2014 3:25 pm |
|
|
Hi, I'm trying to make some kind of loader but I'm having problems writting into program memory.
First, I load the data in an array (dato_ld)
Code: | addr=make16(dato_ld[0],dato_ld[1]);
addr=addr/2;
cuenta=dato_ld[2];
if(cuenta!=0){
for(x=0;x<cuenta;x++)
buffer[x]=dato_ld[x+3];
write_program_memory(addr, buffer, cuenta);
} |
In dato_ld[0] and [1] I have the address where to write the data
In dato_ld[2] I have how many bytes to write
And from dato_ld[3] to the end I have the data itself
When there is no pre loaded data in the destination, I can record without any trouble, however if there is any kind of data, it records garbage.
This PIC does not need to erase program memory before writing to it, at least CCS doesn't allow to use erase_program_eeprom instruction, so I'm stuck here.
Any suggestion of what I am doing wrong? I'm using CCS 4.120.
Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 27, 2014 6:21 pm |
|
|
Quote: | This PIC does not need to erase program memory before writing to it |
The 16F1826 data sheet says this:
Quote: | 11.3.3 WRITING TO FLASH PROGRAM MEMORY
Before writing to program memory, the word(s) to be
written must be erased or previously unwritten. |
Quote: |
I'm using CCS 4.120.
At least CCS doesn't allow to use erase_program_eeprom instruction
|
That function compiles without errors with vs. 5.025. See the program below:
Code: |
#include <16F1826.h>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)
//======================
void main()
{
int16 addr = 0x400;
erase_program_eeprom(addr);
} |
Before writing to program memory, the word(s) to be
written must be erased or previously unwritten. |
|
|
pmaggi
Joined: 05 Jun 2013 Posts: 10
|
|
Posted: Sun Apr 27, 2014 7:03 pm |
|
|
Thanks, I will upgrade the compiler and try it. |
|
|
pmaggi
Joined: 05 Jun 2013 Posts: 10
|
|
Posted: Sun Apr 27, 2014 7:38 pm |
|
|
I tryed your code and it compile without any problem, but if I specify a 16f1825 instead of a 16f1826 it fails and says
*** Error 112 "prueba.c" Line 10(1,1): Function used but not defined: ... erase_program_eeprom 618 SCR=937
The 16f1825 data sheets also says that the memory has to be erased before writing to it but for some reason CCS fails to compile...
Try your code using a 16f1825... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 27, 2014 7:44 pm |
|
|
You're right. Somehow I accidentally read your post as 16F1826.
I will look into this further and try to come up with a work-around if possible. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Mon Apr 28, 2014 12:30 am |
|
|
Before going on, lets ask a question. Why?....
These chips have EEPROM, and this is much easier to use than program memory. Why not use this?.
On these chips the flash row is 32 words.
Remember that the program memory is 14bits wide. So you can't write a pair of bytes like 0xFFFF to a word, only the low 14bits will be stored. Your code is going to need to be aware of the limitations this brings....
Aaah. I see later you refer to a loader, which should then be OK, aand makes sense. The write_program_memory function is meant to erase _automatically_, but only when you write to the first byte of a row. If you are writing to addresses that don't align to the rows, then it'd behave as you see, or if the erase doesn't work on your compiler. Haven't got 4.120 handy.
Within these limitations, if CCS on your compiler version is not handling an erase, it should be 'doable' with:
Code: |
#define delay_2 delay_cycles(1);delay_cycles(1) //used to ensure two NOP's
#byte EEADRH=getenv("SFR:EEADRH")
#byte EEADRL=getenv("SFR:EEADRL")
#byte EECON2=getenv("SFR:EECON2")
#bit CFGS=getenv("BIT:CFGS")
#bit WREN=getenv("BIT:WREN")
#bit FREE=getenv("BIT:FREE")
#bit EEPGD=getenv("BIT:EEPGD")
void erase_page(int16 address)
{
//Mask address to the low word - 64 byte mask
address&=0xFFC0;
EEADRL=make8(address,0);
EEADRL=MAKE8(address,1); //load address
EEPGD=TRUE;
CFGS=FALSE;
FREE=TRUE;
WREN=TRUE;
EECON2=0x55;
EECON2=0xAA; //unlock
WR=TRUE; //trigger erase
delay_2; //two NOP's
WREN=FALSE;
}
|
Now, I've not tested this (it was bodged out of some other code I had for a chip where the erase was not working), but structurally looks right (assuming 4.120 knows the bit names). Remember GIE needs to be off before this is called.
Best Wishes |
|
|
pmaggi
Joined: 05 Jun 2013 Posts: 10
|
|
Posted: Mon Apr 28, 2014 6:00 am |
|
|
Thanks, I will try this approach.
The loader is for a smart switch controlled trough RF. What I am trying to implement is a way of changing the firmware trough RF without having to take it apart.
Everything is working fine except for the writing to program memory |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Mon Apr 28, 2014 8:00 am |
|
|
Strategic important thing to be aware of. Just how long the flash memory takes to do things. It takes 2.5mSec (worst case) to perform a block write/erase. During this time the processor completely stops. You need to ensure the serial stops when data is being written. Also to change one byte in a row, you have to read the entire row, modify the one byte in RAM, erase the row, and write the whole row back. |
|
|
pmaggi
Joined: 05 Jun 2013 Posts: 10
|
|
Posted: Mon Apr 28, 2014 8:12 am |
|
|
Thanks, I just send 16 data bytes at a time, and don't send more until receiving the acknowledge from the pic. That part works ok, I'm able to write quite long pieces of code in free zones of memory without any problem. |
|
|
|