![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
ftoffolon
Joined: 01 Jul 2016 Posts: 8
|
write_configuration_memory() compilation error |
Posted: Tue Jul 12, 2016 6:49 am |
|
|
Hi,
I've have to write on user ID area a checksum code for bootloading reason. Normally in my previous PIC18 and PIC16 designs I use write_program_eeprom API and it works as expected. Now I'm approaching a project with PIC16F18325 and it doesn't works. I've seen documentation and I've found new APIs for accessing that area :
write_configuration_memory() and read_configuration_memory().
read_configuration_memory works as expected but with write_configuration_memory, compiler raise an error that I don't understand. Below the compiler's output with error and a simple example with the API.
ERROR ->
>>> Warning 240 "test_ccs.c" Line 19(35,36): Pointer types do not match
*** Error 102 "test_ccs.c" Line 19(35,36): Expect comma
1 Errors, 1 Warnings.
Build Failed.
<-
Code: |
#include <16f18325.h>
void main(void){
unsigned char buffer[8];
int i = 0;
buffer[0] = 0x08;
buffer[1] = 0xF0;
buffer[2] = 0x0D;
buffer[3] = 0xF0;
buffer[4] = 0x0D;
buffer[5] = 0xF0;
buffer[6] = 0x08;
buffer[7] = 0xF0;
write_configuration_memory(buffer,8);
while (1) {
i++;
}
}
|
Thanks for any support
Fabio |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Tue Jul 12, 2016 7:04 am |
|
|
Look at the data sheet.
Look at table 10-3.
What does the column 'write access' say about the configuration words?....
Because it cannot work, the compiler is 'hiccuping', and thinking you mean to use an offset, and so should have the third parameter.... |
|
![](templates/subSilver/images/spacer.gif) |
ftoffolon
Joined: 01 Jul 2016 Posts: 8
|
|
Posted: Tue Jul 12, 2016 8:36 am |
|
|
My device table says that I can also write on user id area (0x8000-0x8003).
I've also tried to put optional 1st parameter to zero, so no offset 'cause the user id area is on 1st address of configuration memory, but another error comes from compiler :
Code: |
#include <16f18325.h>
void main(void){
unsigned char buffer[8];
int i = 0;
buffer[0] = 0x08;
buffer[1] = 0xF0;
buffer[2] = 0x0D;
buffer[3] = 0xF0;
buffer[4] = 0x0D;
buffer[5] = 0xF0;
buffer[6] = 0x08;
buffer[7] = 0xF0;
write_configuration_memory(0,buffer,8);
while (1) {
i++;
}
}
|
ERROR ->
>>> Warning 203 "test_ccs.c" Line 17(1,1): Condition always TRUE
*** Error 112 "test_ccs.c" Line 15(1,1): Function used but not defined: ... write_configuration_memory 893 SCR=1391
1 Errors, 1 Warnings.
Build Failed.
<-
I'm using CCS 5.061
Thanks |
|
![](templates/subSilver/images/spacer.gif) |
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Tue Jul 12, 2016 9:37 am |
|
|
The manual entry for write_configuration_memory() says:
Quote: | On all PIC18 Family of chips, the configuration memory is readable and writable. This functionality is not available on the PIC16 Family of devices. |
Your device is a PIC16, therefore does not have writable configuration memory, and thus no write_configuration_memory() function is provided by CCS for that device.
Also, if your device was a PIC18, you must never write to 0x8007 and beyond as your code does, or tries to. This area is the fuses, and writing to them is not going to end well. Even bootloaders, which might try, generally don't, or should not under normal operation. Bootloaders should always have the same fuses as the code they are intended to load. |
|
![](templates/subSilver/images/spacer.gif) |
ftoffolon
Joined: 01 Jul 2016 Posts: 8
|
|
Posted: Tue Jul 12, 2016 10:34 am |
|
|
Sorry RF_Developer but on compiler (rel. 5.061) documentation of write_configuration_memory() says that, on Enhanced16, I can use it for User ID memory, and microcontroller datasheet says it's writable.
See CCS manual extract :
->
write_configuration_memory( )
Syntax:
write_configuration_memory ([offset], dataptr,count)
Parameters:
dataptr: pointer to one or more bytes
count: a 8 bit integer
offset is an optional parameter specifying the offset into configuration memory to start writing to, offset defaults to zero if not used.
Returns:
undefined
Function:
For PIC18 devices-Erases all fuses and writes count bytes from the dataptr to the configuration memory.
For Enhanced16 devices - erases and write User ID memory.
Availability:
All PIC18 Flash and Enhanced16 devices
<-
Regards |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9170 Location: Greensville,Ontario
|
|
Posted: Tue Jul 12, 2016 11:08 am |
|
|
I downloaded the datasheet for that PIC and all I can find is ...
Program Flash memory consists of 8192 14-bit words
as user memory, with additional words for user ID
information, Configuration Words, and interrupt
vectors. Program Flash memory provides storage
locations for:
• User program instructions
• User defined data
Program Flash memory data can be read and/or written
to through:
• CPU instruction fetch (read-only)
• FSR/INDF indirect access (read-only)
Please note (read-only) !!
So I'm assuming that you cannot 'actively' write to memory, unlike other PICs.
Others will know for sure but usually Microchip will 'promote' any feature like R/W mem. Now there may be a 'family' memeber of that PIC that does have the feature.
You have to remmeber just because the compiler has a function that works on some PICS you need to confirm by reading read datasheet which these days is 400-500 pages long !
Jay |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Tue Jul 12, 2016 1:51 pm |
|
|
If you look at the table I referred to, the main memory is writeable, but the configuration area isn't. The ID should be, but I'm not sure how.
I'd have to sit down and write a routine to do it. Problem is that the standard write will try to erase a page, and the configuration memory is in the same page, and not writeable!......
Duh. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Wed Jul 13, 2016 1:03 am |
|
|
I have to ask. Why not put the checksum in the EEPROM?.
This is much easier memory to use. Byte wide, and can be written and erased byte by byte. Even if you are using the EEPROM for other things, you could reserve (say) the last four bytes of this for a checksum.
Alternatively, the standard way, is just to have the last couple of words in the main memory, containing a value to make the whole of memory 'sum' to a particular constant.
CCS have omitted the write_configuration_memory function, since there are only 4*14bits that can actually be written using it. If you must go this way, then ask them to add it, or write your own. |
|
![](templates/subSilver/images/spacer.gif) |
ftoffolon
Joined: 01 Jul 2016 Posts: 8
|
|
Posted: Wed Jul 13, 2016 1:55 am |
|
|
Hi,
to temtronic :
on PIC16F18325 datasheet (last release), after row FSR/INDF indirect access (read-only) you find :
. NVMREG access (Section 10.4 “NVMREG Access")
that explain how to write to flash and also to user id area.
And on table 10-3 it's explicitly indicate that user id area (0x8000-0x8003) is writtable. I know that datasheet has a lot of pages but I'm tring to read all of these, at least all of these involved on my program.
to Ttelmah:
of course write access to eeprom is easy but I've chosen, as in many PIC16 and PIC18 project (also PIC16F1825, very similar to PIC16F18325) to use user id, to storage my bootloadable program checksum, for safety reason, to put on a region not involved to my normal program. On PIC16F1825, where I've used CCS 4.132 at that time, I've seen that write_program_memory() api doesn't works (unlike on PIC16F19xx) and write_configuration_memory() was available only for PIC18, so I've written a procedure on my own, following datasheet assembly indication, to do the job and it works, so it's possible to write on user id. On CCS 5.061 I've noticed that write_configuration_memory() is availabe also for Enhanced16 and I hoped that CCS has covered that gap on there apis. Maybe there is some jobs to do on CCS side?
Regards and thanks for your response on my issue
Fabio |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Wed Jul 13, 2016 2:27 am |
|
|
Just worth adding, that the code example MicroChip, gives for writing to the User ID on this chip, doesn't work....
Probably explains why CCS have omitted it.
Then Table 10-2, disagrees with MicroChip's own comment in Table 10-3. If you look this shows for NVM access, for the User ID, config etc., 'READ', not 'READ WRITE'.....
Nothing listed yet in the errata about this. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Wed Jul 13, 2016 3:31 am |
|
|
OK. Looking at the data sheet, the code given to supposedly access the ID, is the code to access program memory, not the ID....
Copying from a couple of other chips with the ID access, it looks as if this should be close to what is needed:
Code: |
#BYTE NVMADRL = getenv("SFR:NVMADRL")
#BYTE NVMADRH = getenv("SFR:NVMADRH")
#BYTE NVMDATL = getenv("SFR:NVMDATL")
#BYTE NVMDATH = getenv("SFR:NVMDATH")
#BYTE NVMCON1 = getenv("SFR:NVMCON1")
#BYTE NVMCON2 = getenv("SFR:NVMCON2")
#bit NVRD=NVMCON1.0
#bit NVWR=NVMCON1.1
#bit WREN=NVMCON1.2
#bit FREE=NVMCON1.4
#bit LWLO=NVMCON1.5
#bit NVMREGS=NVMCON1.6
void write_ID(int8 * buffer)
{
int1 GIE;
int8 ctr;
//designed just to write the 8 bytes of the User ID
//sequence needs to begin with GIE disabled, and UNLOCK
GIE=interrupt_enabled(GLOBAL); //remember if interrupts are enabled
disable_interrupts(GLOBAL);
NVMREGS=TRUE; //access the special registers
LWLO=1; //latch data
WREN=TRUE;
NVMADRL=0;
NVMADRH=0; //User ID is at address 0..3
for (ctr=0;ctr<4;ctr++)
{
NVMDATL=*(buffer++);
NVMDATH=*(buffer++); //latch the 14bits of data
NVMCON2=0x55;
NVMCON2=0xAA; //unlock
NVWR=TRUE; //set write bit
//delays supposedly not needed
if (ctr==2)
LWLO=0; //write will trigger on the next pass
NVMADRL++; //next address
}
NVWR=FALSE;
NVMREGS=FALSE;
if (GIE)
enable_interrupts(GLOBAL);
}
|
Can't test this today, but it looks close, if the chip does allow access.... |
|
![](templates/subSilver/images/spacer.gif) |
ftoffolon
Joined: 01 Jul 2016 Posts: 8
|
|
Posted: Thu Jul 14, 2016 3:45 am |
|
|
Thank you very much Ttelmah,
this week I'm fully involved into other project but next one I'll try your example.
Regards |
|
![](templates/subSilver/images/spacer.gif) |
ftoffolon
Joined: 01 Jul 2016 Posts: 8
|
|
Posted: Fri Jul 22, 2016 5:29 am |
|
|
Hi Ttelmah,
Finally I've found time to test your procedure. Unfortunately has no success. I've checked an old porject I've done with PIC16F1825, where I've implemented my proceudre to write User ID area. I've translated it with new registry names of PIC16F18325 (they are almost the same, only with different names) and it works !
Now I can write to user ID area.
Here's the procedure:
Code: |
#pragma byte EECON1 = getenv("SFR:NVMCON1")
#pragma byte EECON2 = getenv("SFR:NVMCON2")
#pragma byte EEDATL = getenv("SFR:NVMDATL")
#pragma byte EEDATH = getenv("SFR:NVMDATH")
#pragma byte EEADRL = getenv("SFR:NVMADRL")
#pragma byte EEADRH = getenv("SFR:NVMADRH")
#define EEPG 0x80
#define CFGS 0x40
#define LWLO 0x20
#define FREE 0x10
#define WRERR 0x08
#define WREN 0x04
#define WR 0x02
#define RD 0x01
#define __Nop() \
#asm nop #endasm
void write_user_id(uint_16 u16data)
{
uint_16 u16_tmp;
uint_8 i;
// erase
EEADRH = 0x80;
EEADRL = 0x00;
EECON1 |= CFGS;
EECON1 |= EEPG;
EECON1 |= FREE;
EECON1 |= WREN;
EECON2 = 0x55;
EECON2 = 0xAA;
EECON1 |= WR;
__Nop();
__Nop();
EECON1 &= ~WREN;
// write
EEADRH = 0x80;
EEADRL = 0x00;
EECON1 |= CFGS;
EECON1 |= EEPG;
EECON1 &= ~FREE;
EECON1 |= WREN;
EECON1 |= LWLO;
for (i = 0;i <= 3;i++)
{
u16_tmp = (u16data & (0xF000 >> (i*4)));
u16_tmp >>= (12 - (i*4));
u16_tmp <<= 8;
u16_tmp &= 0x0F00;
u16_tmp |= 0x00F0;
EEDATL = make8(u16_tmp,1);
EEDATH = make8(u16_tmp,0);
if (i == 3)
{
EECON1 &= ~LWLO;
}
EECON2 = 0x55;
EECON2 = 0xAA;
EECON1 |= WR;
__Nop();
__Nop();
EEADRL++;
}
EECON1 &= ~WREN;
} |
Best regards |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Fri Jul 22, 2016 5:59 am |
|
|
Well done.
You can do the nop with:
Code: |
#define __Nop() delay_cycles(1)
|
The data sheet says that you have to use address 0, with NVMREGS set to true (which is what I coded). However you are using address 0x8000.
It suggests the whole data sheet about this bit is wrong (look at the other errors we already found), so instead use the sheet/routine for a similar chip, to get it working....
Ouch...
Even more annoying, this means the standard CCS code to write to the program memory would work, if it allowed you to use address 0x8000 (which it won't). |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|