|
|
View previous topic :: View next topic |
Author |
Message |
rodrigo_cirilo
Joined: 31 Mar 2019 Posts: 43 Location: Sao paulo/Brazil
|
10F322 and HEF (virtual eeprom) |
Posted: Sun Mar 31, 2019 7:02 pm |
|
|
Hello dear friends.
I humbly ask you for help on an issue.
I have to write 6 bytes (int8 values) and I do not know how to proceed with this question. I found some examples here in this forum, I tried but I did not understand.
This is a value that will be read every time the system is turned on, and sometimes new value will be written to the addresses.
I ask for help with an example code to record and read 1 byte.
Thank you very much in advance!! |
|
|
Jerson
Joined: 31 Jul 2009 Posts: 125 Location: Bombay, India
|
|
Posted: Sun Mar 31, 2019 10:20 pm |
|
|
Since the device does not have a dedicated EEPROM area, I think you will need to look at functions that can read / write flash area. _________________ Regards
Jerson Fernandes |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Mon Apr 01, 2019 12:29 am |
|
|
Forget about using it like virtual EEPROM.
Your chip has an erase block size of 16words. So you need to think
of organising everything you want to save, into a block of RAM that
fits this size. Remember only 14bits in each word, so if you need 16bit
values, you need to use two words to hold each value etc..
If you only need to save a couple of values, read these using
read_program_memory. You then have to write the entire block you
want to save as one operation using write_program_memory, to
a boundary multiple of the erase size.
So write (for instance) to address 0x1E0, and this will erase and write
automatically.
Your chip _does not have HEF_. So there is no 'better' place to put this.
Seriously, given the size of RAM buffer needed, the lack of HEF, and
the amount of code that will be needed, it is honestly better to think in
terms of using another chip if you need EEPROM. The 'virtual EEPROM'
driver, would use a huge amount of your code space, so you really need
to be using the DIY approach, but this is going to be quite laborious... |
|
|
rodrigo_cirilo
Joined: 31 Mar 2019 Posts: 43 Location: Sao paulo/Brazil
|
|
Posted: Mon Apr 01, 2019 4:59 am |
|
|
Ttelmah wrote: | Forget about using it like virtual EEPROM.
Your chip has an erase block size of 16words. So you need to think
of organising everything you want to save, into a block of RAM that
fits this size. Remember only 14bits in each word, so if you need 16bit
values, you need to use two words to hold each value etc..
If you only need to save a couple of values, read these using
read_program_memory. You then have to write the entire block you
want to save as one operation using write_program_memory, to
a boundary multiple of the erase size.
So write (for instance) to address 0x1E0, and this will erase and write
automatically.
Your chip _does not have HEF_. So there is no 'better' place to put this.
Seriously, given the size of RAM buffer needed, the lack of HEF, and
the amount of code that will be needed, it is honestly better to think in
terms of using another chip if you need EEPROM. The 'virtual EEPROM'
driver, would use a huge amount of your code space, so you really need
to be using the DIY approach, but this is going to be quite laborious... |
Yes, I want to write 8-bit values, for example, 100, 101 and 102, and then write 200, 201, and 202 having only 6 8-bit values to be written. I do not quite understand this issue of organizing pages or blocks of memory, so I count on your precious help.
For the little that I understood, if I write the first 3 values, when I write the other 3 I should read before or 3 first and then write it all over again, is that it?
Below is your code that compiles correctly here, but I can not understand, the many settings that I do not know.
Code: | #include <10F322.h>
#FUSES NOWDT
#FUSES NOBROWNOUT
#FUSES NOLVP
#use delay(internal=4000000)
#define ADDRESS_TO_USE_FOR_STORAGE 0x1F8 //This is the high endurance flash - 0xF8 for 10F320
#define BYTES_TO_USE 8 //Key is that the high endurance flash is 8 * bytes only low bytes in word only
#ROM int16 ADDRESS_TO_USE_FOR_STORAGE = {1,2,3,4,5,6,7} //Preload the HEF
//studying the assembler suggest the supplied memory write/erase functions still won't work.
//rewrite trimmed versions of these....
int8 buffer[BYTES_TO_USE]; //buffer for HEF
#byte PMADRH=getenv("SFR:PMADRH")
#byte PMADRL=getenv("SFR:PMADRL")
#bit CFGS=getenv("BIT:CFGS")
#bit WREN=getenv("BIT:WREN")
#bit LWLO=getenv("BIT:LWLO")
#bit FREE=getenv("BIT:FREE")
#byte PMDATL=getenv("SFR:PMDATL")
#byte PMDATH=getenv("SFR:PMDATH")
#byte PMCON2=getenv("SFR:PMCON2")
#bit WR=getenv("BIT:WR")
#bit RD=getenv("BIT:WR")
//#byte FSR0=getenv("SFR:INDF0")
#define delay_2() delay_cycles(1);delay_cycles(1) //two nops
#bit GIE=getenv("BIT:GIE")
#define UNLOCK() PMCON2=0x55; PMCON2=0xAA; WR=TRUE; delay_2() //chip unlock sequence
#define select_address(add) CFGS=FALSE;PMADRL=make8(add,0);PMADRH=make8(add,1) //load address
void erase_row(int16 address) //erases the row containing 'address'.
{
disable_interrupts(GLOBAL); //ensure interrupts are off
select_address(address & 0x1F0); //select page
FREE=TRUE;
WREN=TRUE;
UNLOCK(); //Perfrom the actual erase
WREN=FALSE;
enable_interrupts(GLOBAL);
}
void write_block(int8 *ram, int8 ctr, int16 address)
{
//function to replace non working write
//Warnings....
//Writes 'ctr' bytes to the _low_ byte only of the memory block starting at 'address'
//Must fit inside a row. No testing done to ensure this (keep space small...)
disable_interrupts(GLOBAL); //ensure interrupts are off
select_address(address);
LWLO=TRUE;
WREN=TRUE;
FREE=FALSE;
//Now need to load the latches
do
{
PMDATH=0;
PMDATL=*ram;
ram++; //next byte
if (--ctr==0) break;
UNLOCK();
PMADRL++; //Next word
}
while (TRUE);
//Now all but last latch loaded
LWLO=FALSE; //switch to physical write
UNLOCK(); //and write the data
WREN=FALSE;
enable_interrupts(GLOBAL);
}
void save_HEF(void) //copies the 8 HEF bytes to RAM buffer
{
int16 address;
//now read the max 8 HEF bytes
for (address=0;address<BYTES_TO_USE;address++)
{
buffer[address]=read_program_eeprom(address+ADDRESS_TO_USE_FOR_STORAGE);
}
}
void write_HEF(void)
{
//Uses my replacement functions to write the 8 HEF bytes to ROM
erase_row(ADDRESS_TO_USE_FOR_STORAGE); //erase entire row
write_block(buffer,8,ADDRESS_TO_USE_FOR_STORAGE); //write the 8 HEF bytes
}
void main()
{
while(TRUE)
{
save_HEF();
//Now buffer contains the bytes from the HEF
//Now modify, and try writing.
buffer[2]=34;
buffer[4]=56;
buffer[7]=78;
write_HEF();
do {
}
while (TRUE); //stop here, don't want to write more than once...
}
} |
Please help me. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Mon Apr 01, 2019 5:16 am |
|
|
I looked at the datasheet and it does say it has HEF,though not how to access it. I did find a ref to HEF being the last 128 bytes of memory. Perhaps there's a separate 'application note' or other document on how to use it ?
I do have PIC10F322 samples on order as it seems it might be a GREAT 'glue' PIC.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Mon Apr 01, 2019 6:20 am |
|
|
That's interesting. I looked at my data sheet and no mention of HEF.
Suggests they have updated the chip and added this. In which case
you need to be sure your chip is recent.
On the current sheet, the HEF, is address 0x180 to 0x1FF.
So you need to choose a 32byte boundary in this area. So
0x180 0x1A0, 0x1C0, or 0x1E0.
A write to the page boundary erases the whole page.
Now you can change any bit from a 1, to a 0, without erasing.
So you can write to a single word and change it provided this is what
you want to do. However as soon as you need to change a bit from
0 to 1, this can only be done be erasing the whole page, which then implies
writing the whole page back. You need a buffer that is twice the size
of the number of bytes you want to store. So if you need 6 bytes, then
use a twelve byte buffer. Read the twelve bytes from the ROM, change the
ones you want, and write the whole block back to the page boundary.
You need to use even bytes in the buffer to have 8bits available (the
odd bytes will only store 6 bits each).
Code: | byte buffer[12];
read_program_memory(0x1E0, buffer, 12);
| Would read a 12byte buffer from the flash.
Code: | write_program_memory(0x1E0, buffer, 12); | Would write the same buffer back.
buffer[0], buffer[2], buffer[4] etc., would contain the bytes you could use.
Add
Code: | #ORG 0x1E0, 0x1FF {} |
Before your code, to stop the compiler putting anything into this area. |
|
|
rodrigo_cirilo
Joined: 31 Mar 2019 Posts: 43 Location: Sao paulo/Brazil
|
|
Posted: Mon Apr 01, 2019 7:17 am |
|
|
Ttelmah wrote: | That's interesting. I looked at my data sheet and no mention of HEF.
Suggests they have updated the chip and added this. In which case
you need to be sure your chip is recent.
On the current sheet, the HEF, is address 0x180 to 0x1FF.
So you need to choose a 32byte boundary in this area. So
0x180 0x1A0, 0x1C0, or 0x1E0.
A write to the page boundary erases the whole page.
Now you can change any bit from a 1, to a 0, without erasing.
So you can write to a single word and change it provided this is what
you want to do. However as soon as you need to change a bit from
0 to 1, this can only be done be erasing the whole page, which then implies
writing the whole page back. You need a buffer that is twice the size
of the number of bytes you want to store. So if you need 6 bytes, then
use a twelve byte buffer. Read the twelve bytes from the ROM, change the
ones you want, and write the whole block back to the page boundary.
You need to use even bytes in the buffer to have 8bits available (the
odd bytes will only store 6 bits each).
byte buffer[12];
read_program_memory(0x1E0, buffer, 12);
Would read a 12byte buffer from the flash.
write_program_memory(0x1E0, buffer, 12);
Would write the same buffer back.
buffer[0], buffer[2], buffer[4] etc., would contain the bytes you could use.
Add
#ORG 0x1E0, 0x1FF {}
Before your code, to stop the compiler putting anything into this area. |
Thank you very much for the guidance.
I analyzed your first code and I understood a small part.
I saw that you have to write directly in memory with the command:
Code: | #ROM int16 ADDRESS_TO_USE_FOR_STORAGE = {1,2,3,4,5,6,7} |
So soon after you read all the data and change only those below
Code: |
buffer [2] = 15;
buffer [4] = 56;
buffer [7] = 78;
write_HEF ();
|
Could you help me to simplify your example code?
Is really necessary all this part:
Code: |
#byte PMADRH = getenv ("SFR: PMADRH")
#byte PMADRL = getenv ("SFR: PMADRL")
#bit CFGS = getenv ("BIT: CFGS")
#bit WREN = getenv ("BIT: WREN")
#bit LWLO = getenv ("BIT: LWLO")
#bit FREE = getenv ("BIT: FREE")
#byte PMDATL = getenv ("SFR: PMDATL")
#byte PMDATH = getenv ("SFR: PMDATH")
#byte PMCON2 = getenv ("SFR: PMCON2")
#bit WR = getenv ("BIT: WR")
#bit RD = getenv ("BIT: WR")
|
|
|
|
rodrigo_cirilo
Joined: 31 Mar 2019 Posts: 43 Location: Sao paulo/Brazil
|
|
Posted: Mon Apr 01, 2019 11:42 am |
|
|
I think I can handle this.
I'm simulating proteus and it's working.
Look what I did.
Code: |
#include <10F322.h>
#FUSES NOWDT
#FUSES NOBROWNOUT
#FUSES NOLVP
#use delay(internal=4000000)
#define ADDRESS_TO_USE_FOR_STORAGE 0x1F8 //This is the high endurance flash - 0xF8 for 10F320
#define BYTES_TO_USE 8 //Key is that the high endurance flash is 8 * bytes only low bytes in word only
//#ROM int16 ADDRESS_TO_USE_FOR_STORAGE = {1,2,3,4,5,6,7} //Preload the HEF
//studying the assembler suggest the supplied memory write/erase functions still won't work.
//rewrite trimmed versions of these....
int8 buffer[BYTES_TO_USE]; //buffer for HEF
#byte PMADRH=getenv("SFR:PMADRH")
#byte PMADRL=getenv("SFR:PMADRL")
#bit CFGS=getenv("BIT:CFGS")
#bit WREN=getenv("BIT:WREN")
#bit LWLO=getenv("BIT:LWLO")
#bit FREE=getenv("BIT:FREE")
#byte PMDATL=getenv("SFR:PMDATL")
#byte PMDATH=getenv("SFR:PMDATH")
#byte PMCON2=getenv("SFR:PMCON2")
#bit WR=getenv("BIT:WR")
#bit RD=getenv("BIT:WR")
//#byte FSR0=getenv("SFR:INDF0")
#define delay_2() delay_cycles(1);delay_cycles(1) //two nops
#bit GIE=getenv("BIT:GIE")
#define UNLOCK() PMCON2=0x55; PMCON2=0xAA; WR=TRUE; delay_2() //chip unlock sequence
#define select_address(add) CFGS=FALSE;PMADRL=make8(add,0);PMADRH=make8(add,1) //load address
void erase_row(int16 address) //erases the row containing 'address'.
{
disable_interrupts(GLOBAL); //ensure interrupts are off
select_address(address & 0x1F0); //select page
FREE=TRUE;
WREN=TRUE;
UNLOCK(); //Perfrom the actual erase
WREN=FALSE;
enable_interrupts(GLOBAL);
}
void write_block(int8 *ram, int8 ctr, int16 address)
{
//function to replace non working write
//Warnings....
//Writes 'ctr' bytes to the _low_ byte only of the memory block starting at 'address'
//Must fit inside a row. No testing done to ensure this (keep space small...)
disable_interrupts(GLOBAL); //ensure interrupts are off
select_address(address);
LWLO=TRUE;
WREN=TRUE;
FREE=FALSE;
//Now need to load the latches
do
{
PMDATH=0;
PMDATL=*ram;
ram++; //next byte
if (--ctr==0) break;
UNLOCK();
PMADRL++; //Next word
}
while (TRUE);
//Now all but last latch loaded
LWLO=FALSE; //switch to physical write
UNLOCK(); //and write the data
WREN=FALSE;
enable_interrupts(GLOBAL);
}
void save_HEF(void) //copies the 8 HEF bytes to RAM buffer
{
int16 address;
//now read the max 8 HEF bytes
for (address=0;address<BYTES_TO_USE;address++)
{
buffer[address]=read_program_eeprom(address+ADDRESS_TO_USE_FOR_STORAGE);
}
}
void write_HEF(void)
{
//Uses my replacement functions to write the 8 HEF bytes to ROM
erase_row(ADDRESS_TO_USE_FOR_STORAGE); //erase entire row
write_block(buffer,8,ADDRESS_TO_USE_FOR_STORAGE); //write the 8 HEF bytes
}
void main()
{
while(TRUE)
{
if(input(pin_a0))
{
buffer[1]=1;
buffer[2]=2;
buffer[3]=3;
buffer[7]=255;
write_HEF();
}
if(input(pin_a1))
{
buffer[4]=4;
buffer[5]=5;
buffer[6]=6;
buffer[7]=255;
write_HEF();
}
/* do {
}
while (TRUE); //stop here, don't want to write more than once...
*/
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Mon Apr 01, 2019 11:54 am |
|
|
The code you have written is all already there. That is what the
program_memory functions in the compiler do. You have a read,
write and erase function. The write will automatically erase if you talk
to the first byte of an erase page.
You don't need to go DIY. |
|
|
|
|
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
|