|
|
View previous topic :: View next topic |
Author |
Message |
lsimaster
Joined: 19 Mar 2009 Posts: 25
|
18F87J11 Family Flash Read/Write/Erase |
Posted: Thu Mar 19, 2009 3:38 pm |
|
|
I am working on a new product design using the 18F66J11 from this product family. The part has no eeprom so I am trying to use the flash for this purpose. I have PCWH 4.65.4.13.
Something is different about this part because none of the CCS built in functions such as erase_program_eeprom(), etc will work. I have copied the example code from the part data sheet directly into the program and run some test routines to find that the memory is not affected. I did this but preseting some values as constants, tried to erase this block of memory, and then tested the values. In all cases, my code or built-in functions, the values are not affected.
Does anyone have experience with this product family? I tried contacting Microchip but find that the support staff have been mostly layed off so nothing there.
To test I created the following block in memory. This part has a minimum erase block size of 1024 and the write block is either 2 or 64 bytes. The memory resets to 0xff so I can test ee_dat[] before and after erase to see if an erase has ocurred. I am doing this after normal operations were not successful.
Code: | #ORG 0x0400,0x0800 {} //set aside 1024 and use ee_dat as dummy variable to read
#ORG 0x0400
const long ee_dat[32] = {810,0xffff,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0};
The erase function is:
//function will erase 1024 bytes started at the reference address
void setp_erase()
{
bit_clear(INTCON,7); //disable global ints
TBLPTRU = 0x00; //the addr is 0x000400
TBLPTRH = 0x04;
TBLPTRL = 0x00;
EECON1 = 0b00010100; //set wren and free bits
EECON2 = 0x55;
EECON2 = 0xaa;
bit_set(EECON1,1); //start the erase
bit_set(INTCON,7);
setpbuf_full = 0;
} |
|
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu Mar 19, 2009 4:01 pm |
|
|
In Microchip's example, WREN and FREE are set individually. Don't know if the difference matters, but you may want to start with the originally suggested sequence. |
|
|
lsimaster
Joined: 19 Mar 2009 Posts: 25
|
I have tried that |
Posted: Fri Mar 20, 2009 7:52 am |
|
|
I have been trying to resolve this problem for about a week so have tried every twist I can think of including your suggestion, which is what I did on the first cut. The code I posted was the latest attempt after numerous other versions. I started with the built in functions and moved toward what I posted. Mostly I avoid the built in functions because I find by the time I sort out what it takes to make them work I could have written 10 on my own. I'm really wishing I had put a serial eeprom on the board but didn't based on the part data sheet. Normally I just churn these programs out but I also normally avoid using new parts. Lesson learned on this one. It looked good on paper.
For future reference, when using the Flash as an eeprom surrogate, you have to figure out the segment boundaries relative to the part erase size. I originally chose a lower address but this stepped on some dedicated locations in lower memory and bombed the program. 000400h is the beginning of the second 1K partition. The part data sheet is deficient in explaining how to use this feature and I suppose my problems are related to something not said.
Unfortunately my newest MachX went up in smoke this morning so I'm out of commission until I get a replacement. I have another MachX and 3 ICD-U's but none of them want to work with the drivers I am using. This is another issue for another thread. I'm not sure what that is about but is has been a common problem over time. The MachX that smoked this morning was just replaced because it lost its USB ID. Serenity now. |
|
|
Ttelmah Guest
|
|
Posted: Fri Mar 20, 2009 11:25 am |
|
|
How are you testing this?.
Be aware that these operations are not supported in the emulator for example.
Also, your code will fail, if you try to read the block. In CCS, if you put a 'const' array in memory, it has the program to read it, 'in front' of the data itself. The erase will destroy this program...
You need to use something like:
Code: |
#include "C:\Program Files\PICC\USBtest\eetest.h"
#ROM 0x400 = {810,0xffff,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0}
int16 address16;
#byte address16=0xFF6
#byte page=0xFF8
#byte EECON1=0xFA6
#byte EECON2=0xFA7
#bit FREE=EECON1.4
#bit WREN=EECON1.2
#bit WR=EECON1.1
union accesspart {
int16 words[2];
int32 lword;
};
void clear_page(union accesspart address) {
address16=address.words[0];
page=address.words[1];
WREN=TRUE;
FREE=TRUE;
disable_interrupts(GLOBAL);
EECON2=0x55;
EECON2=0xAA;
WR=TRUE;
enable_interrupts(GLOBAL);
}
void main()
{
rom int16* ptr;
int16 val;
ptr=0x400;
val=*ptr;
printf("Initial value %ld \n\r",val);
clear_page(0x400);
val=*ptr;
printf("Second value %ld \n\r",val);
while(TRUE);
}
|
Whether ROM pointers will work for you, will depend on the compiler version. This is _not_ the number you are quoting. Look at the top line of the listing file. It'll be in the format 4.xxx.
Best Wishes |
|
|
lsimaster
Joined: 19 Mar 2009 Posts: 25
|
18F87J11 Family Flash Read/Write/Erase |
Posted: Fri Mar 20, 2009 1:06 pm |
|
|
Thanks for your significant input. My method of testing has been to read the first three array positions and display the results on a display that is part of the product. Doing this I can tell whether the values are changed. The #Rom method is another way to put the test values in place but given that the read was not working I was looking for a construct that would provide a literal pointer to the location. I have a lookup table constructed the same way and that works well so decided to use what I know works. If an erase takes out anything I would be quite happy. Unfortunatelly I still read the values put in place. BTW I have tried direct asm code straight from the Microchip data sheet with similar results. This leads me to believe there is some subtle issue with this part that I have missed. The part is new so there isn't a lot of info available.
The code I posted is just test code other than the one #org to preserve the 1K block. The array was added so I would have a known value to check against after things didn't work. In the original I am writing and reading bytes against an offset to a pointer and there is no ee_dat[].
CCS came back with some test code and the primary difference is the use of symbolic addresses that are type defined to 32 bit. My original used a literal 24bit (ie 0x000400) and I'm thinking this could be part of the problem. It doesn't explain why the posted code doesn't do an erase.
I'll have a new programmer here on Monday and will test yours and the CCS suggestions and report back. I learned today that the other MACHX and three ICD-U40's I have will not work with this part. This leaves me with no ICSP capability until Monday. Then I'm sending all the other stuff back to CCS for ugrading.
Many thanks for the suggestions. I was running out of ideas. |
|
|
lsimaster
Joined: 19 Mar 2009 Posts: 25
|
18F87J11 Family Flash Read/Write/Erase |
Posted: Mon Mar 23, 2009 1:49 pm |
|
|
I got some sample code via CCS tech support and have sorted through my difficulty. My replacement MACHX also arrived this morning. When it rains it pours.
erase_program_eeprom is designed to erase memory from the specified address to 0xffff so is not useful if doing eeprom emulation like I am. This was most of the problem. I was doing an erase before write and wiping out the entire code.
My erase code that was posted earlier works if the free bit set is done before the wren bit set. I was doing them in the same operation and that does not work. I have now tested the corrected version and have confirmed that it works as I have described.
As far as I can tell write_program_eeprom does not support a one word write although the family I am working with does have word write in addition to 64 byte write. This and erase functions are geared toward boot loader apps and not eeprom emulation as far as I can tell from the scant documentation.
read_program_eeprom works well for reading a word. I don't think it would read a single byte but this is OK. bytes would have to be done every other address anyway because you can't write just one byte.
All the above can easily be written in CCS C with the exception of the TBLRD and TBLWT ops which have no equivalent C extension. |
|
|
lsimaster
Joined: 19 Mar 2009 Posts: 25
|
18F87J11 Family Flash Read/Write/Erase |
Posted: Wed Mar 25, 2009 4:08 pm |
|
|
I thought I had worked through this issue but not to be. After another few days of fighting with it I have determined that the problem is with the erase.
When I do an erase other parts of the program are corrupted despite a #ORG that protects 1K of memory and the erase is addressed to the start of the ORG'd memory.
I have copied the code for this directly from the Microchip data sheet and have compared it to a sample program provided by CCS. I have tried every nuance of change I can think of. If anyone has an idea on this I would appreciate the help. My other choice is to use the Real Time Clock memory or redesign the board to add a serial eeprom, which is the best idea for the long run.
The symptom of the crash is that the A/D int stops and that drives the rest of the code operation. The first statement of the A/D interrupt function is directly after the ORG'd section.
I'm thinking that this is the result of something I'm not considering like a stack problem or something that causes the interrupt to get lost so it doesn't return to the correct place. The A/D int is running all the time reading temperature probes for a thermostat. The setpoint save is called from a function which in turn calls the erase function below. I've tried all the obvious stuff. Any ideas are greatly appreciated.
Code: | //The erase block size for this processor is 1024 bytes
//This org reserves that block to avoid inadvertent erase of code
#define start_addr 0x0400
#org start_addr,start_addr + 1024 {}
//function will erase 1024 bytes started at the reference address
void setp_erase()
{
TBLPTRU = 0x00; //the addr is 0x000400
TBLPTRH = 0x04;
TBLPTRL = 0x00;
bit_set(EECON1,4); //set free bit
bit_clear(INTCON,7); //disable ints
bit_set(EECON1,2); //set wren bit
EECON2 = 0x55;
EECON2 = 0xaa;
bit_set(EECON1,1); //start the erase
bit_clear(EECON1,4);
bit_clear(EECON1,2);
bit_set(INTCON,7);
setpbuf_full = 0;
setp_cnt = 0;
} |
|
|
|
lsimaster
Joined: 19 Mar 2009 Posts: 25
|
18F87J11 Family Flash Read/Write/Erase |
Posted: Thu Mar 26, 2009 7:59 am |
|
|
I resolved the problem by disabling ints before the call to the flash write routine. Previously they were disabled inside the routine. Apparently I was getting a stack overflow due to going three layers deep with two ints running. |
|
|
|
|
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
|