|
|
View previous topic :: View next topic |
Author |
Message |
apakSeO
Joined: 07 Dec 2016 Posts: 60 Location: Northeast USA
|
#ROM directive difference between 16F1503 & 18F24K40 |
Posted: Wed Sep 19, 2018 4:00 pm |
|
|
CCS Compiler Version 5.073
Windows 10
On my PIC18F24K40 target device, I am initializing some data in the EEPROM. The following code works correctly on the PIC18F24K40:
Code: |
#define EEPROM_ADDR_START getenv("EEPROM_ADDRESS")
#define EEPROM_MYDATA0_ADDR EEPROM_ADDR_START
#define EEPROM_MYDATA1_ADDR EEPROM_ADDR_START + 1
#define EEPROM_MYDATA2_ADDR EEPROM_ADDR_START + 2
#define EEPROM_MYDATA3_ADDR EEPROM_ADDR_START + 3
#ROM EEPROM_ADDR_START = {10,20,30,40}
|
When I try to port this code over to my PIC16F1503 target device and compile, I am presented with the following compiler error:
Quote: | Error#126 Invalid ORG range |
...and the error points to the last closing curly brace in the source code.
For the record, it is only the last line with the #ROM directive that causes this compiler error to pop up. Any ideas on why this does not function the same between these two PICs? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 19, 2018 4:19 pm |
|
|
The 16F1503 doesn't have eeprom.
The datasheet says:
Quote: | 3.2 High-Endurance Flash
This device has a 128 byte section of high-endurance
program Flash memory (PFM) in lieu of data EEPROM.
This area is especially well suited for nonvolatile data
storage that is expected to be updated frequently over
the life of the end product. |
|
|
|
apakSeO
Joined: 07 Dec 2016 Posts: 60 Location: Northeast USA
|
|
Posted: Thu Sep 20, 2018 8:33 am |
|
|
Thanks PCM
Is there already a built in method with the CCS compiler to read/write and initialize this memory in the 16F1503?
Something like the write_eeprom() and read_eeprom() functions for PICs that do have EEPROM, but for PFM NV data that needs to be modified during run time? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Thu Sep 20, 2018 10:25 am |
|
|
Yes, and no.
Initialisation, you just use #ROM. It is just that the data has to be put at the address where the PFM is, instead of the EEPROM. However big 'caveat', remember that the program memory has each word 14bits wide. So your data layout will have to change significantly.
In use, there is a library designed to use two pages of the program memory to emulate an EEPROM (there is a big problem in that program memory has to be erased in pages, so single byte writes need to be done my using a marker and changing single words from the erased state to a used value, and then when a page is full, copying this to a second page and erasing). The driver to do all this is 'virtual_eeprom.c'.
Honestly for most applications I'd say add an external EEPROM. Much easier. However for a limited amount of data, that does not change at all frequently this driver can be used. |
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Thu Sep 20, 2018 10:50 am |
|
|
Why not use a PIC16F1825 it is pin compatible with EEPROM. I moved from the 1503 to 1825 using same board as I wanted EEPROM. |
|
|
apakSeO
Joined: 07 Dec 2016 Posts: 60 Location: Northeast USA
|
|
Posted: Thu Sep 20, 2018 12:18 pm |
|
|
Thanks Ttelmah & Alan
The first solution will get my prototypes out.
Alan's solution will make it easier in the future.
Must appreciated, yet again. |
|
|
apakSeO
Joined: 07 Dec 2016 Posts: 60 Location: Northeast USA
|
|
Posted: Thu Sep 20, 2018 3:02 pm |
|
|
I'm having a bit of trouble understanding the virtual_eeprom.c driver. I need to initialize 4 calibration constants during program upload, and then during run time, be able to modify them. Calibration constants are all 8-bit unsigned ints. I know program memory is 14-bits, so I plan to use only the lower 8 bits and mask off the rest.
The PIC16F1503 datasheet tells me the last program memory address is 0x07FF. The High-endurance flash memory which I am interested in has an address range of 0x0780 - 0x07FF
Thus I want my 1st cal constant to be stored at 0x0780
Code: |
#include <16F1503.h>
#device PIC16F1503
#fuses NOWDT,NOPROTECT,NOBROWNOUT,NOPUT
#fuses NOWRT // No write protection for program memory
#use delay(INTERNAL=2MHZ) // Set clock internally sourced, 2MHz
#use rs232(BAUD=9600,XMIT=PIN_C0,RCV=PIN_C2,TRANSMIT_BUFFER=16,BITS=8,PARITY=N,STOP=1,ERRORS,STREAM=uart1)
#include <virtual_eeprom.c>
#DEFINE VIRTUAL_EEPROM_16BIT_ADDY
#ROM 0x0780 = {0xAB}
void main(void)
{
init_virtual_eeprom();
int8 counter = 0x00; // Just a counter to see something incrementing
// on serial uart for debug
while(1)
{
int16 v_ee_data = read_virtual_eeprom(0x0780);
int8 v_ee_data_parsed = v_ee_data & 0xFF;
fputc(counter, uart1);
putc_send();
fputc(v_ee_data_parsed, uart1);
putc_send();
if(counter<0xFF) counter++;
else counter = 0;
delay_ms(500);
}
}
|
When this code is run and I check the serial stream on my scope, I always first receive the counter byte, incrementing on each loop as expected, but the following byte, v_ee_data_parsed, is always = 0xFF
What have I missed in the code above?
Is there more setup to do in virtual_eeprom.c? |
|
|
apakSeO
Joined: 07 Dec 2016 Posts: 60 Location: Northeast USA
|
|
Posted: Thu Sep 20, 2018 3:39 pm |
|
|
I believe that the values stored in program memory need to be read as 16-bit ints ( because that's the next highest up standard type in CCS ) and then masked into 8-bit values, for what I want. I made the following changes to code, and when I browse the program memory space, I see the values initialized correctly as such:
Code: |
#include <16F1503.h>
#device PIC16F1503
#fuses NOWDT,NOPROTECT,NOBROWNOUT,NOPUT
#fuses NOWRT
#use delay(INTERNAL=2MHZ) // Set clock internally sourced, 2MHz
#use rs232(BAUD=9600,XMIT=PIN_C0,RCV=PIN_C2,TRANSMIT_BUFFER=16,BITS=8,PARITY=N,STOP=1,ERRORS,STREAM=uart1)
#include <virtual_eeprom.c>
#define VIRTUAL_EEPROM_16BIT_ADDY
#ROM 0x0780 = {0xAB}
#ROM 0x0781 = {0xCD}
#ROM 0x0782 = {0xEF}
void main(void)
{
init_virtual_eeprom();
int8 counter = 0x00; // Just a counter to see something incrementing
// on serial uart for debug
while(1)
{
int16 v_ee_data16 = read_virtual_eeprom(0x0780);
int8 v_ee_data8 = v_ee_data16 & 0xFF;
fputc(counter, uart1);
putc_send();
fputc(v_ee_data8, uart1);
putc_send();
if(counter<0xFF) counter++;
else counter = 0;
delay_ms(500);
}
}
|
However, I'm still getting back a value of 0xFF for v_ee_data8, every time. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Fri Sep 21, 2018 3:01 am |
|
|
Wrong in quite a few ways...
When setting defines to control a loaded driver, the values need to be defined _before_ you load the driver.
On your chip you have a total of 128bytes of the PFM. No point in using 16bit addresses, to talk to this.
You do not talk to a memory address, but to a virtual EEPROM address. Just as if your chip had an EEPROM.
Data stored has to be formatted ready for this virtual driver.
Also in order to give a reasonable number of values, you may need to increase the number pf pages used.
So:
Code: |
#include <16F1503.h>
#device PIC16F1503
#fuses NOWDT,NOPROTECT,NOBROWNOUT,NOPUT
#fuses NOWRT
#use delay(INTERNAL=2MHZ) // Set clock internally sourced, 2MHz
#use rs232(BAUD=9600,XMIT=PIN_C0,RCV=PIN_C2,TRANSMIT_BUFFER=16,BITS=8,PARITY=N,STOP=1,ERRORS,STREAM=uart1)
//Rom has to be loaded _before_ the driver. Otherwise it reserves the page
#rom int16 0x7C0 = { 0,0xFF, 1,0xAA, 2,0x55, 3,0x11, 4,0x22, 5,0x33, 6, 0x44, 7,0x66 }
//8 secords setup in the virtual EEPROM, numbered 0 to 7
//note you store address, value, address, value etc..
//Load this before the VE driver
//Note the first page used is in the middle of the used range
#define VIRTUAL_EEPROM_8BIT_ADDY
//defines controlling the virtual EEPROM driver must be set _before_ loading
//the driver...
//Your chip only has a small area of PFM. Pointless using 16bit addressing
#define VIRTUAL_EEPROM_NUM_PAGES 4
#include "virtual_eeprom.c"
//Use " so loads the local copy of this driver
void main(void)
{
int8 v_ee_data8;
int16 test;
int8 counter; // Just a counter to see something incrementing
// on serial uart for debug
test=_VE_PAGE0_START;
test=_VE_PAGE1_START;
test=_VE_PAGE1_END;
init_virtual_eeprom();
for (counter=0; counter<0x8;counter++)
{
v_ee_data8 = read_virtual_eeprom(counter); //you read bytes from a virtual _eeprom_ address
//not the memory address. The driver returns _bytes_.
fprintf(uart1, "Count: %d\n", counter);
putc_send();
fprintf(uart1, "Val: %02x\n\r",v_ee_data8);
putc_send();
delay_ms(500);
}
}
|
This correctly displays
Count:0
Val:FF
Count:1
Val: AA
etc..
The only change, is that I have edited the virtual_eeprom driver, 'remming' out the following two lines:
//#org _VE_PAGE0_START,(_VE_PAGE0_END-1) {}
//#org _VE_PAGE1_START,(_VE_PAGE1_END-1) {}
If you don't do this, you can't #ROM data into the area reserved by the driver (it expects you to write the data using it).
Consider the option of having a predefined set of config values in a variable, and if reading address 0 (say) does not return a suitable flag, writing this to the 'EEPROM' using the driver itself. |
|
|
|
|
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
|