|
|
View previous topic :: View next topic |
Author |
Message |
kmp84
Joined: 02 Feb 2010 Posts: 361
|
"read_program_memory()" problem |
Posted: Mon Jan 05, 2015 9:13 am |
|
|
Hi all,
I try to store some bytes in program memory, but have this problem:
Code: |
#include <16F1459.h>
//#device *=16
#use delay(int=8MHz, clock=48MHz, USB_FULL, act=USB)
//#USE RS232(DEBUGGER,rcv=PIN_C2,xmit=PIN_C2,stream=STREAM_MONITOR)
#use rs232(baud=115200, xmit=PIN_B7, rcv=PIN_B5, errors)
#fuses PROTECT
#fuses MCLR
#fuses PUT
#fuses NOWDT
#fuses BROWNOUT
#define BUFFER_SERNUM_SIZE 16 // in bytes
#define PROGRAM_MEMORY_SIZE getenv("PROGRAM_MEMORY")
#define BUFFER_SERNUM_END (PROGRAM_MEMORY_SIZE-1) //0x1FFF
#define BUFFER_SERNUM_START (PROGRAM_MEMORY_SIZE-BUFFER_SERNUM_SIZE) //0x1FEE
//#org BUFFER_SERNUM_START, BUFFER_SERNUM_END {} //Serial_number
#rom BUFFER_SERNUM_START = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
byte ram_buff[16]={255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255};
void main (void){
int8 i;
printf("\n\rPROGRAM_MEMORY_SIZE:%Lx",PROGRAM_MEMORY_SIZE);
printf("\n\rBUFFER_START:%Lx",BUFFER_SERNUM_START);
printf("\n\rBUFFER_END:%Lx",BUFFER_SERNUM_END);
printf("\n\n");
read_program_memory(BUFFER_SERNUM_START, ram_buff, BUFFER_SERNUM_SIZE);
for(i=0;i<16;i++)
{
printf("\n\r ram_buff[%u]:%Lx",i,ram_buff[i]);
}
for(;;)
{
// ...
}
}
|
and get this result :
PROGRAM_MEMORY_SIZE:2000
BUFFER_START:1ff0
BUFFER_END:1fff
ram_buff[0]:00
ram_buff[1]:00
ram_buff[2]:01
ram_buff[3]:00
ram_buff[4]:02
ram_buff[5]:00
ram_buff[6]:03
ram_buff[7]:00
ram_buff[8]:04
ram_buff[9]:00
ram_buff[10]:05
ram_buff[11]:00
ram_buff[12]:06
ram_buff[13]:00
ram_buff[14]:07
ram_buff[15]:00
CCS Compiller v.5.019
Any Idea? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19563
|
|
Posted: Mon Jan 05, 2015 9:48 am |
|
|
The ROM is organised in words. Each is 14bits long (so can't hold two 8bit values), but is accessed by the read/write functions as bytes.
The #ROM statement, writes to the _words_. So when you write '1' to the second location, and then look at this in bytes, you get:
00 //low byte of first word
00 //high 6bits of first word
01 //low byte of second word
00 //high 6 bits of second word
etc.. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Mon Jan 05, 2015 10:54 am |
|
|
Some other related issues to think about:
Put #delay and #use rs232 AFTER the fuses. Note that some delay configurations will override some fuses, and some fuses are required to get some clock settings to work.
Your comment on the value of buffer end is wrong. The code is giving you the correct value, 0x1FF0, when it runs.
Your buffer is not compatible with the ICSP debugger. When debugging live hardware, the top of memory is used for debugging code and this will give you wrong data in debug, or worse still, debug won't work at all.
EEPROM is generally a much better storage medium for settable things like serial numbers. Its writeable and erasable byte by byte whereas program memory requires blocks to be erased. Also any program memory checksum/CRC code (I have this on some/many of my projects) will need to take any data storage regions into account. Program memory has much more limited erase cycles than EEPROM, so cannot be changed as often (though a serial number isn't likely to need changing all that often...). EEPROM can also be excluded from programming on many programmers and even bootloaders if required, for example to update code while leaving calibration data/setpoints/serial numbers/identification etc. intact.
While EEPROM is my default persistent/non-volatile data storage medium, I have used program memory, but only for fault data dumps in an "black box recorder" type thing. I write a largish (1K) block from RAM to program memory on the rare occasions (hopefully never, but you never know...) when a fault is detected. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 361
|
|
Posted: Tue Jan 06, 2015 2:33 am |
|
|
Thank you for help
I've trouble with storing only one Byte in program memory . Any suggestion how to do it ?
Thanks , |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19563
|
|
Posted: Tue Jan 06, 2015 2:48 am |
|
|
You always have to store a word. However you can just read the low bytes of the words.
So you start by having to allow a word for each byte you want to store, in your space allocation. Then read as you do, but only look at the even numbered bytes.
I have to ask what you actually want to do?. Are you wanting to update these values later?. If not, then just let the compiler do it for you and use const:
const int8 ser_num[16]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
Stores this for you in the program memory.
Or look at the UserID locations in the program memory. These are four locations at 0x8000, reserved for a user ID number. They are part of the config memory. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 361
|
|
Posted: Tue Jan 06, 2015 2:57 am |
|
|
Ttelmah wrote: | You always have to store a word. However you can just read the low bytes of the words.
So you start by having to allow a word for each byte you want to store, in your space allocation. Then read as you do, but only look at the even numbered bytes.
I have to ask what you actually want to do?. Are you wanting to update these values later?. If not, then just let the compiler do it for you and use const:
const int8 ser_num[16]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
Stores this for you in the program memory.
Or look at the UserID locations in the program memory. These are four locations at 0x8000, reserved for a user ID number. They are part of the config memory. |
Hi "Ttelmah",
Because my chip (16F1459) have not EEPROM data memory , i want to sore 16 byte max ser.num + 1 byte length of ser.num changed at runtime over rs or usb interface.
Thanks, |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19563
|
|
Posted: Tue Jan 06, 2015 3:29 am |
|
|
OK. So look at what I said. You have almost done it. It is just that you have to read 32 _bytes_ to access the 16 bytes you want.
But there are some big difficulties raised by what you say. Remember that you can only erase a whole page. So you need to use 32 words of storage as a minimum, and this needs to be on a page boundary.
The +1 makes things much more difficult. Why have this?. Why not just have (for example), leading zeros in the number?. Having a fixed size makes everything easier.
So, use getenv("FLASH_ERASE_SIZE"), to get the page size that is needed for an erase. Subtract this from the PROGRAM_MEMORY_SIZE to get the start address where the data must be stored, and use this to specify the buffer size as well as int16, not byte.
So:
Code: |
#define PROGRAM_MEMORY_SIZE getenv("PROGRAM_MEMORY")
#define PAGE_SIZE getenv("FLASH_ERASE_SIZE")
#define BUFFER_SERNUM_START (PROGRAM_MEMORY_SIZE-PAGE_SIZE)
#rom BUFFER_SERNUM_START = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
int16 ram_buff[PAGE_SIZE]; //now you have a buffer for the _words_ the minimum
//size that can be erased
//The read becomes:
read_program_memory(BUFFER_SERNUM_START, ram_buff, sizeof(ram_buff));
|
Now the data will read as written, and if you write the buffer to this address, a page erase will occur, and the data can be written.
As a comment, don't enable protection while debugging. Doing so, means you won't be able to read the memory in the programmer and see if writes have worked, and will use up extra lives on the chip, since a full erase has to occur every time anything is changed. |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 361
|
|
Posted: Wed Jan 14, 2015 1:52 pm |
|
|
Strange problem : My first test board with 16f1459 in DIP socket works good. Second board with same pic (16f1459) in SO20 socket , same software and same schematics is not possible to write to program memory. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19563
|
|
Posted: Wed Jan 14, 2015 3:42 pm |
|
|
Read the errata.
Looks like you have an old (revision A2) chip in the SO20 version.
You can do the write if you switch your clock down to a slower rate, and back up after the write has completed..... |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 361
|
|
Posted: Wed Jan 14, 2015 11:43 pm |
|
|
Ttelmah wrote: | Read the errata.
Looks like you have an old (revision A2) chip in the SO20 version.
You can do the write if you switch your clock down to a slower rate, and back up after the write has completed..... |
When I test two boards with ICD U64 show the same :
Device ID : 3023
Revision : 00 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19563
|
|
Posted: Thu Jan 15, 2015 1:20 am |
|
|
It's not reading the revision properly.
The revision bytes will be 1003, 1005 or 1006.
1003, is the A2 revision. 1005, is A5, and 1006 is A6.
Look at address 8005 in the chip's configuration memory. This is where the revision word is held. 3023, is correct as the device ID (held at 8006).
Look at the erratum, and you will see the problem. On Rev A2 chips, self timed writes won't work with the internal clock at 8MHz or 16MHz (or with external clocks above 4MHz....). |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 361
|
|
Posted: Thu Jan 15, 2015 9:12 am |
|
|
Ttelmah wrote: | It's not reading the revision properly.
The revision bytes will be 1003, 1005 or 1006.
1003, is the A2 revision. 1005, is A5, and 1006 is A6.
Look at address 8005 in the chip's configuration memory. This is where the revision word is held. 3023, is correct as the device ID (held at 8006).
Look at the erratum, and you will see the problem. On Rev A2 chips, self timed writes won't work with the internal clock at 8MHz or 16MHz (or with external clocks above 4MHz....). |
How to read memory location 8005h and 8006h and print on uart? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19563
|
|
Posted: Thu Jan 15, 2015 9:15 am |
|
|
read_configuration_memory |
|
|
kmp84
Joined: 02 Feb 2010 Posts: 361
|
|
Posted: Thu Jan 15, 2015 9:42 am |
|
|
Ttelmah wrote: | read_configuration_memory |
Thanks, but CCS Compiler v.5.019 says : "Undefined identifier-- read_configuration_memory"
In "16F1459.h " missing "_bif void read_configuration_memory". |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 15, 2015 12:39 pm |
|
|
I compiled this program with vs. 5.036:
Code: |
#include <16F1459.h>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)
//===============================
void main()
{
char buffer[16];
read_configuration_memory(buffer, 16);
while(TRUE);
}
|
It created the following ASM code for read_configuration_memory():
Code: |
.................... read_configuration_memory(buffer, 16);
002B: MOVLB 03
002C: CLRF PMADRH
002D: CLRF PMADRL
002E: MOVLW buffer+-1
002F: MOVWF FSR0H
0030: MOVLW buffer+-32
0031: MOVWF FSR0L
0032: MOVLW 10
0033: MOVLB 00
0034: MOVWF @READ_CONFIGURATION_MEMORY.P2 // Number of bytes
0035: GOTO @READ_CONFIGURATION_MEMORY
|
Code: |
READ_CONFIGURATION_MEMORY:
0003: MOVLB 03
0004: BSF PMCON1.CFGS
0005: MOVLB 00
0006: MOVF @READ_CONFIGURATION_MEMORY.P2,W
0007: MOVWF @77
0008: BCF STATUS.C
0009: INCF @77,F
000A: RRF @77,F
000B: MOVLB 03
000C: BSF PMCON1.RD
000D: NOP
000E: NOP
000F: MOVF PMDATL,W
0010: MOVWF INDF0
0011: ADDFSR 01,FSR0
0012: MOVF PMDATH,W
0013: MOVWF INDF0
0014: ADDFSR 01,FSR0
0015: INCF PMADRL,F
0016: BTFSC STATUS.Z
0017: INCF PMADRH,F
0018: DECFSZ @77,F
0019: GOTO 00C
001A: BCF PMCON1.CFGS
001B: MOVLP 00
001C: MOVLB 00
001D: GOTO 036 (RETURN)
|
You could use this as a guide to make your own routine. |
|
|
|
|
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
|