|
|
View previous topic :: View next topic |
Author |
Message |
amarquez
Joined: 24 Jun 2009 Posts: 11
|
write_program_memory PIC10F322 |
Posted: Mon Jul 30, 2012 4:27 am |
|
|
Hello everyone!
I need to save two bytes, I am using the functions read / write_program_memory (), since, the PIC10F322 has no eeprom.
I can not write to program memory
Can anyone help me?
Code: |
#include <10F322.h>
#device adc=8
#FUSES WDT_SW //Watch Dog Timer by Software
#FUSES INTRC //Internal RC Osc
#FUSES BROWNOUT //brownout reset
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOPROTECT
#FUSES PUT
#FUSES NOWRT
#use delay(clock=4M)
#use rs232(baud=300,parity=N,rcv=PIN_A3,bits=8,stop=1)
#org 0x01FA, 0x01FB {}
#define ADD_OFFSET 0x1FA
#define ADD_FREQ 0x01FB
int offset=16;
int freq=155;
void main(){
setup_adc_ports(sAN0);
setup_adc(ADC_CLOCK_DIV_8);
set_tris_a(0b1101);
setup_wdt(WDT_OFF);
write_program_memory(ADD_OFFSET,offset,2);//OFFSET
while(TRUE){
Vin=read_adc(ADC_START_AND_READ);
if ((Vin >=105)&&(Vin <=230)){
offset=read_program_memory(ADD_OFFSET,offset,2);
if(Vin <=125){
offset=offset-28;
}else{
offset=((offset*26)/100)-4;
write_program_memory(ADD_OFFSET,offset,2);//OFFSET
}
}else{
offset=0;
}
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Mon Jul 30, 2012 5:03 am |
|
|
First key thing, is that flash memory, unlike EEPROM, does not have individual byte erase connections. Erases have to be in _pages_. Pages on this chip, are 16bytes. The write_program memory function, will erase the page automatically, _if_ (and only if) you write to the first location in a page.
So, your reserved area, needs to start on a page boundary, and the area should be 16 locations long.
Second problem then is that the program memory, is organised as 14bit words, written to as two 8bit bytes. So you can only write a full byte to every other location in the memory. The extra two bits are lost, when you write to the intermediate locations. You'll need to split your value to write, into two 8bit values are write these to even locations in the memory.
Then, the address used for the function, is the _byte_ address, but the memory is organised as words. You need to double the word address to get the byte address.
Code: |
#org 0x01F0, 0x01FF {} //Make this a page
#define ADD_OFFSET 0x1F0*2
#define ADD_FREQ 0x01F2*2 //Byte addresses
void write_int16_to_progmem(int16 address, int16 val) {
int8 buffer[4];
buffer[0]=make8(val,0); //first byte
buffer[1]=buffer[3]=0; //6bit locations
buffer[2]=make8(val,1); //second byte
write_program_memory(address,buffer,4);
}
int16 get_int16_from_progmem(int16 address) {
int8 buffer[4];
read_program_memory(address,buffer,4);
return(make16(buffer[2],buffer[0]));
}
|
This shows how to write and read a 16bit value from the program memory on these chips (Ugh....).
The whole page is erased, when you write to the first location in the page. So you need to save the second value before doing this, if you don't want to lose it. Also to change the second value, you have to retrieve the first value, then write it back (which erases the page), then write the second value....
What you show, would kill the chip very quickly. Neither EEPROM, or flash is suitable for things that are changed at all often. You are writing every time round the loop. About once every 3mSec. That will kill the chip in about 8 hours....
Best Wishes |
|
|
amarquez
Joined: 24 Jun 2009 Posts: 11
|
|
Posted: Mon Jul 30, 2012 5:37 am |
|
|
I've been testing the code and I can not write to program memory. Continuing with the same problem. |
|
|
amarquez
Joined: 24 Jun 2009 Posts: 11
|
|
Posted: Tue Jul 31, 2012 12:18 am |
|
|
I tested it on different areas of free memory in the execution of the function 'write_program_memory( address, dataptr, count )', the pic10F322 not work.
Could be a bad implementation of the function for this PIC? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Tue Jul 31, 2012 12:46 am |
|
|
Yes, it could.
Very new PIC.
One thing though, are you delaying at the start of your code, before you call these functions?. This is required (errata 1). There must be at least 100uSec delay after power on, before trying to write to the flash.
Best Wishes |
|
|
amarquez
Joined: 24 Jun 2009 Posts: 11
|
|
Posted: Tue Jul 31, 2012 1:14 am |
|
|
I have introduced a delay before writing to the flash, and locks in the execution of writing. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Tue Jul 31, 2012 2:31 am |
|
|
Are you sure, or could it be the delay?. There have been a _lot_ of problems with delays on the 10F/12F chips not working as they should on various compiler versions....
I'd guess though that the unlock sequence is not working right, in which case you either need to dismantle the assembler, and see if you can spot the error, go DIY, or log a problem with CCS.
Best Wishes |
|
|
amarquez
Joined: 24 Jun 2009 Posts: 11
|
|
Posted: Wed Aug 01, 2012 4:46 am |
|
|
The problem is not the delays.
I'm trying to assembler. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Wed Aug 01, 2012 7:15 am |
|
|
OK. It is just on these chips there have been reported problems with certain delays causing completely spurious results....
You are aware that code _will_ stall for 2mSec while any write/erase operation takes place, and that interrupts _must_ be disabled before these are called?.
Best Wishes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 01, 2012 5:46 pm |
|
|
There are bugs in the flash memory read/write routines. Are you sure
you want to do this ? Because if you type in the routines from the 10F322
data sheet, you might use a considerable portion of the Flash memory
that is available. These are small PICs, with only 512 words of Flash.
I wrote a little program to test reading a word from Flash. If you are
just playing around, I don't think it's worth the effort to finish all the
routines. Or at least, it may not be worth my effort.
But the following program does work. It displays "1234" on the TeraTerm
window on my PC. I have pin A2 connected to a Max232 chip, which
then connects to the PC with a cable. This was tested with vs. 4.135.
There also appear to be some problems with printf displaying control
characters and strings. I just used putc() to do the CR and LF chars.
Code: |
#include <10F322.H>
#fuses INTRC,NOWDT,BROWNOUT,PUT,MCLR
#use delay(clock=4M)
#use rs232(baud=9600, xmit=PIN_A2)
#define FLASH_ADDR 0x1F0 // Use last 16 words of flash for testing
// Initialize the test area in flash to all 0's when
// the PIC is programmed.
#rom FLASH_ADDR = {0x1234,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
#byte PMADRL = 0x20
#byte PMADRH = 0x21
#byte PMDATL = 0x22
#byte PMDATH = 0x23
#byte PMCON1 = 0x24
#byte PMCON2 = 0x25
#bit RD = PMCON1.0
#bit WR = PMCON1.1
#bit CFGS = PMCON1.7
int16 read_program_word(int16 addr)
{
int16 retval;
PMADRL = addr;
PMADRH = addr >> 8;
CFGS = 0;
RD = 1;
#asm nop #endasm
#asm nop #endasm
retval = make16(PMDATH, PMDATL);
return(retval);
}
//====================================
void main(void)
{
int16 result;
result = read_program_word(FLASH_ADDR);
printf("%lx ", result);
putc(0x0d);
putc(0x0a);
while(1);
} |
|
|
|
amarquez
Joined: 24 Jun 2009 Posts: 11
|
|
Posted: Thu Aug 02, 2012 5:09 am |
|
|
I appreciate the effort. I'm not playing.
I understand that the PIC10F322 is new and may have errors of routines, I need to work with it.
CFGS PMCON registry is bit 6? ('# bit CFGS = PMCON1.7')
You could check me erase and write routines?
I think the erase routine is correct, but I can not write to the flash.
Thank you. Code: |
#byte PMADRL = 0x20
#byte PMADRH = 0x21
#byte PMDATL = 0x22
#byte PMDATH = 0x23
#byte PMCON1 = 0x24
#byte PMCON2 = 0x25
#byte INTCON = 0x0B
#bit RD = PMCON1.0
#bit WR = PMCON1.1
#bit WREN = PMCON1.2
#bit WRERR = PMCON1.3
#bit FREE = PMCON1.4
#bit LWLO = PMCON1.5
#bit CFGS = PMCON1.6
#bit GIE = INTCON.7
void erase_program_word(int16 addr)
{
GIE = 0;
PMADRL = addr;
PMADRH = addr >> 8;
CFGS = 0;
FREE = 1;
WREN = 1;
//unlock sequence
PMCON2 = 0x55;
PMCON2 = 0xAA;
WR = 1;
#asm nop #endasm
#asm nop #endasm
WREN = 0;
GIE = 1;
}
void write_program_word(int16 addr, int16 data)
{
GIE = 0;
PMADRL = addr;
PMADRH = addr >> 8;
CFGS = 0;
FREE = 0;
LWLO = 1;
WREN = 1;
PMDATL = data;
PMDATH = data >> 8;
//unlock sequence
PMCON2 = 0x55;
PMCON2 = 0xAA;
WR = 1;
#asm nop #endasm
#asm nop #endasms
LWLO = 0;
WREN = 0;
GIE = 1;
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 02, 2012 12:32 pm |
|
|
You're right about the CFGS bit. That was a mistake. It is bit 6.
It worked because it defaults to 0. |
|
|
amarquez
Joined: 24 Jun 2009 Posts: 11
|
|
Posted: Thu Aug 09, 2012 1:06 am |
|
|
Routine does not work "write_program_word(int16 addr, int16 data)"
Can anyone help me? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9269 Location: Greensville,Ontario
|
|
Posted: Thu Aug 09, 2012 4:50 am |
|
|
I don't have or use that PIC but..
generally speaking...
It'd help if you told us what doesn't work.Is the correct data not at the correct address?Is only the lower byte correct,but at the wrong address?Is anything right or is it all wrong? What address/data should you have and what did you get?
Is the data/address correct when reading the PIC using say ,MPLAB, but your display program shows 'errors'?
There's a LOT of combinations..and without knowing what you have vs. what you expect it's nearly impossible to help.
This is assuming the PIC and the rest of your program is running right.
You've probably made a lot of changes since the op so maybe show us all of your new code.
hth
jay |
|
|
amarquez
Joined: 24 Jun 2009 Posts: 11
|
|
Posted: Wed Aug 22, 2012 4:31 am |
|
|
The problem is in LWLO bit of the PMCON1 register. Clear the LWLO bit before unlock sequence.
Code: | void write_program_word(int16 addr, int16 data)
{
GIE = 0;
PMADRL = addr;
PMADRH = addr >> 8;
CFGS = 0;
FREE = 0;
LWLO = 1;
WREN = 1;
PMDATL = data;
PMDATH = data >> 8;
LWLO = 0;
//unlock sequence
PMCON2 = 0x55;
PMCON2 = 0xAA;
WR = 1;
#asm nop #endasm
#asm nop #endasms
WREN = 0;
GIE = 1;
} |
|
|
|
|
|
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
|