|
|
View previous topic :: View next topic |
Author |
Message |
Dimi Island
Joined: 05 Mar 2021 Posts: 2 Location: Brazil
|
Flash write and read functions - 16F15323 or 324 |
Posted: Fri Mar 05, 2021 11:49 am |
|
|
Hello,
I'm using PIC16F15323 with the CCS PCM compiler version 5.075 and I would like to write and read a value from your flash saved at any address, similar to the use of an EEPROM.
I found this topic similar to my need:
https://www.ccsinfo.com/forum/viewtopic.php?t=54707
It was answered in 2006 by Ttelmah.
I made some small adaptations to the code to see if it ran on my device, but without success.
Follow my sheets:
Main.c Code: |
#include "main.h"
#include "16F15323_flash.h"
/*
#include <16f526.h>
#device ADC=8
#device *=8
#fuses INTRC,NOWDT,NOMCLR
#use delay(clock=8000000)
*/
#use rs232 (XMIT=PIN_B0, baud=9600) //simple output for debugging
/*
Ttelmah say:
Simple test program to demonstrate the internal data flash
#include "526flash.h" //code to access this memory
Now key to understand with this memory, is that when erased all the bits
are'1'. A write can change a bit from '1' to '0', but cannot change a bit from
'0' to '1'. To change a bit to '1', the row has to be erased. So if when
writing a value, a bit needs to change to '1', the page containing the byte
has to be erased first. This means all the other bytes in this page, need to
be read, and then the whole page written back.
I've 'encapsulated' this in a routine that checks which way the bits have
to change and automatically performs the read and erase if needed.
This is 'write_as_eeprom'. Notes in the include file.
*/
void main()
{
int8 temp;
SETUP_ADC(ADC_OFF);
SETUP_ADC_PORTS(NO_ANALOGS);
setup_comparator(NC_NC_NC_NC);
//Minimum test program
//This will store a byte, then read it, but then write a second byte to the
//same page, then write to this location a second time, requiring bits to
//be set, and then read the both locations and verify the erase/'auto save'
//has worked.
write_as_eeprom(0,0xAA); //write a byte
temp=read_byte_flash(0); //read it
printf("Byte at zero %2x\n\r",temp); //diagnostic
write_as_eeprom(1,0x50); //now write to address 1
//second write forcing an erase..
write_as_eeprom(1,0x55); //Needs two bits in the low nibble set to '1'
//so the page has to erase if it is to work...
temp=read_byte_flash(0); //now check if byte 0 is still OK
printf("Byte at zero %2x\n\r",temp); //diagnostic byte 0
temp=read_byte_flash(1); //and do the same for byte 1
printf("Byte at one %2x\n\r",temp); //diagnostic byte 1
while (TRUE)
{
//stop and do nothing else
}
}
|
Main.h Code: |
#include <16F15323.h>
#device ADC=10
#FUSES RSTOSC_EXT //On Power-up clock running from External Oscillator
#FUSES NOCLKOUT //I/O function on OSC2
#FUSES CKS //Clock Switching Enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES MCLR //Master Clear pin enabled
#FUSES NOPUT //No Power Up Timer
#FUSES NOLPBOR //Low-Power Brownout reset is disabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV24 //Brownout reset at 2.4V
#FUSES ZCDDIS //Zero-cross detect circuit is disabled at POR
#FUSES PPS1WAY //Allows only one reconfiguration of peripheral pins
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES WDTSW //Watch Dog Timer Postscale settable in software
#FUSES WDTWIN_SW //Watchdog Window is settable in software
#FUSES WDTCLK_SW //WDT clock source settable in software
#FUSES BBSIZ512 //Boot block size 512 bytes
#FUSES NOBOOTBLOCK
#FUSES SAF
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOWRTC //Configuration registers not write protected
#FUSES NOWRTSAF
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOPROTECT //Code not protected from reading
#device ICD=TRUE
#use delay(internal=1MHz)
|
16F15323_flash.h
Code: |
#byte EEADR=getenv("SFR:EEADR")
#byte EECON=getenv("SFR:EECON")
#byte EEDATA=getenv("SFR:EEDATA") //EE registers
#bit RD=getenv("BIT:RD")
#bit WR=getenv("BIT:WR")
#bit FREE=getenv("BIT:FREE")
#bit WREN=getenv("BIT:WREN") //EE control bits
//The 'flash data memory' on this chip behaves like a sort of hybrid between
//flash program memory, and EEPROM. The erase size if just 8bytes (so not
//a terribly large 'page', and the control only has a simple 'unlock' sequence
//Implements four routines:
// write_byte_flash(address, value) - writes 'value' to 'address'
// read_byte_flash(address) - returns the byte at 'address'
// erase_row_flash(address) - erases the eight byte row containing 'address'
// write_as_eeprom(address, value) - this is the complex one
//it reads the byte at 'address' and if bits only have to turn 'off' (1->0)
//simply writes the byte. If however any bit has to turn 'on', this cannot
//be done without erasing the page. In this case it reads the whole page
//into a RAM buffer, erases the page, changes the one byte needed, and
//writes the page back. Allows the data flash to be 'written' as if it was
//EEPROM (hence the name), and will not erase if it is not required to do so.
void write_byte_flash(unsigned int8 address, unsigned int8 value)
{
//write a single byte to an address. This does not erase, so a bit cannot
//be set to '1' by this routine.
EEADR=address; //select address
EEDATA=value; //data to write
WREN=TRUE; //trigger a write
WR=TRUE;
}
unsigned int8 read_byte_flash(unsigned int8 address)
{
//read a single byte from the flash
unsigned int8 temp;
EEADR=address; //select address
RD=TRUE; //trigger a read
temp=EEDATA;
return temp;
}
void erase_row_flash(unsigned int8 address)
{
//The erase uses the top three bits of the specified address as the page to erase
EEADR=address; //select address
FREE=TRUE;
WREN=TRUE;
WR=TRUE; //trigger the erase
}
//
void write_as_eeprom(unsigned int8 address, unsigned int8 value)
{
//this allows a single byte to be written to any address and automatically
//erases if necessary.
unsigned int8 low3; //low 3 bits of address
unsigned int8 buffer[8];
unsigned int8 temp;
low3=address&7; //index into the buffer
//Now I need to determine if the row has to be erased.
buffer[0]=read_byte_flash(address);
//Now if writing the byte would only set bits to zero, an erase is not needed
if ((value & buffer[0]) == value)
{
//Just write
write_byte_flash(address,value);
return;
}
//otherwise we need to erase the row.
//First read the row.
for (temp=0;temp<8;temp++)
{
buffer[temp]=read_byte_flash((address&0x38)+temp);
}
//Now update the byte to change
buffer[low3]=value;
//erase the row
erase_row_flash(address);
//and write back all eight bytes
for (temp=0;temp<8;temp++)
{
write_byte_flash((address&0x38)+temp, buffer[temp]);
}
}
|
Follows errors generated when compiling: Code: |
Compiling E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\main on 05-mar-21 at 14:23
*** Error 28 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 2(31,32): Expecting an identifier Bad SFR name
*** Error 12 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 3(2,6): Undefined identifier
*** Error 48 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 3(7,12): Expecting a (
*** Error 28 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 3(31,32): Expecting an identifier Bad SFR name
*** Error 48 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 4(2,6): Expecting a (
*** Error 48 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 4(7,13): Expecting a (
*** Error 28 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 4(33,34): Expecting an identifier Bad SFR name
*** Error 48 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 5(2,5): Expecting a (
*** Error 48 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 5(6,8): Expecting a (
*** Error 43 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 5(24,25): Expecting a declaration
*** Error 43 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 5(0,1): Expecting a declaration
*** Error 12 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 29(4,9): Undefined identifier EEADR
*** Error 12 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 30(4,10): Undefined identifier EEDATA
*** Error 12 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 39(4,9): Undefined identifier EEADR
*** Error 12 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 40(4,6): Undefined identifier RD
*** Error 12 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 41(9,15): Undefined identifier EEDATA
*** Error 12 "E:\Trabalho\Cursos\12 - Pic e Flash memory\CCS_simula_flash_16F15323\16F15323_flash.h" Line 48(4,9): Undefined identifier EEADR
*** Error 100 "main.c" Line 9(5,66): USE parameter value is out of range Not a number: PIN_B0
*** Error 132 "main.c" Line 40(34,38): STDOUT not defined (may be missing #USE RS232) ::
*** Error 132 "main.c" Line 46(34,38): STDOUT not defined (may be missing #USE RS232) ::
*** Error 132 "main.c" Line 48(33,37): STDOUT not defined (may be missing #USE RS232) ::
21 Errors, 0 Warnings.
Build Failed.
|
I understand that the datasheet says that access to flash memory from this pic is indirect using FSR. But how do I do that?
Could you please help me Ttelmah?
Thank you very much for your valuable help. _________________ Dimi Island
Brazil |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Fri Mar 05, 2021 12:18 pm |
|
|
Unfortunately your chip is not at all similar to the one I wrote that for.
The flash page on your chip is 64 bytes long, not 8 bytes, and the read
and write access uses different registers.
On your chip the CCS functions should work. The code you found was
specific for the rather unusual flash access on the 526.
The same potential 'trick could be used of not erasing if bits only have to
be set to zero.
You'd need to read a whole 64 byte page, change just the byte you want,
and write the whole page back.
The supplied read_program_memory and write_program_memory
functions will do the whole thing. The write needs to be done to a page
boundary, then the write will perform an erase. You need to look at
13.3.5 in the data sheet which outlines the procedure needed. |
|
|
Dimi Island
Joined: 05 Mar 2021 Posts: 2 Location: Brazil
|
|
Posted: Fri Mar 12, 2021 12:35 pm |
|
|
Thank you very much by your response.
It's work now.
I don't see the 13.3.5 only 4.0 Memory Organization.
I'm hep _________________ Dimi Island
Brazil |
|
|
|
|
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
|