View previous topic :: View next topic |
Author |
Message |
2xhp
Joined: 14 Jan 2019 Posts: 39
|
erase_program_memory on dsPIC33 and delay between |
Posted: Fri Apr 16, 2021 4:37 pm |
|
|
I'm trying to do a bulk erase of a chunk of memory on a dsPIC33EV256GM104. I've found that if I do successive erases without a delay, the chip resets. I'm staying far away from the config words.
Code: | for(i=0; i<total_erase_blocks; i++) {
erase_program_memory(current_erase_location);
current_erase_location+=erase_block_size;
delay_us(1);
} |
Compiler version: 5.103
With the delay shown in the above code, it works fine. Without it, problems.
Hopefully I'm calculating the incrementing correctly - erase_block_size is set as such:
Code: | erase_block_size = (getenv("FLASH_ERASE_SIZE")) >> 1; |
Admittedly, I've had a hard time wrapping my head around the dsPIC memory layout with phantom bytes and such. With FLASH_ERASE_SIZE of 2,048 as being reported by the chip, I would have thought to use that for what I incremented the memory location by to do the erasing. But in the help file for erase_program_memory, there is this example:
Code: | erase_program_memory(address); // erase block of memory from 0x2000
// to 0x2400 for a PIC24HJ/FJ /33FJ
//device, or erase 0x2000 to 0x2040
//for a dsPIC30F chip |
This says that 1,024 bytes will be erased with FLASH_ERASE_SIZE of 1,536 which the dsPIC I'm using states it has (unless you read out from what the compiler reports, then it says 2,048). Very confusing! This is why I'm dividing the flash erase size given down so it is 1,024.
Anyways, the main question is on why the delay is needed to prevent problems when erasing. Thanks in advance. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 16, 2021 5:47 pm |
|
|
The first thing I'd look at is decoupling and bulk capacitors near the
PIC. Are they on all the required pins ? Is there enough bulk
capacitance to handle erasing the chip ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sat Apr 17, 2021 12:15 am |
|
|
Remember that program memory on the DsPIC has three usable bytes
per 32bit word.
1536 bytes of program memory, is 512 instructions, which occupies
2048 actual 'locations', of which only 1536 are actually implemented.
Quote: |
00 01 02 NN
03 04 05 NN
06 07 08 NN
|
Where 'NN' is a not existent byte.
So here, 3 instructions is 9 usable bytes, but 12 actual addresses.
The CCS report is of that actual address range involved.
The smallest 'page' that can be erased is 512 instructions, containing
1536 physically implemented memory bytes, but using an address range
of 2048 bytes.
By dividing by 2, you are performing two erases per page. Each erase uses
up a 'life' on this page, so you will kill the chip in half the time that would
otherwise happen....
It is possible the repeated erases without delay, is triggering the ECC
erratum that can occur for flash operations on this chip. |
|
|
2xhp
Joined: 14 Jan 2019 Posts: 39
|
|
Posted: Sat Apr 17, 2021 5:44 pm |
|
|
Ttelmah wrote: |
By dividing by 2, you are performing two erases per page. Each erase uses
up a 'life' on this page, so you will kill the chip in half the time that would
otherwise happen....
It is possible the repeated erases without delay, is triggering the ECC
erratum that can occur for flash operations on this chip. |
Thank you for the detailed explanation.
So is the help file example I referenced, i.e.:
Code: | erase_program_memory(address); // erase block of memory from 0x2000
// to 0x2400 for a PIC24HJ/FJ /33FJ
//device, or erase 0x2000 to 0x2040
//for a dsPIC30F chip |
... incorrect?
This is what it says for the chips it's referencing:
Erases FLASH_ERASE_SIZE bytes to 0xFFFF in program memory.
FLASH_ERASE_SIZE varies depending on the part.
Family FLASH_ERASE_SIZE
dsPIC30F 32 instructions (96 bytes)
dsPIC33FJ 512 instructions (1536 bytes)
PIC24FJ 512 instructions (1536 bytes)
PIC24HJ 512 instructions (1536 bytes)
It seems like the example should have said that:
Code: | erase_program_memory(0x2000) |
... would erase from 0x2000 to 0x2800 (2,048 address bytes) for the 512 instruction PICs. |
|
|
2xhp
Joined: 14 Jan 2019 Posts: 39
|
|
Posted: Sat Apr 17, 2021 8:30 pm |
|
|
I discovered looking in the virtual_eeprom.c driver file where it looks like the FLASH_ERASE_SIZE is being divided by 2 for PCD devices:
Code: | #if defined(__PCH__)
#define _VE_BPA 1
#else
#define _VE_BPA 2
#endif
#if defined(VIRTUAL_EEPROM_DOUBLE_SPACE)
#define VIRTUAL_EEPROM_NUM_PAGES 2
#endif
#ifndef VIRTUAL_EEPROM_NUM_PAGES
#define VIRTUAL_EEPROM_NUM_PAGES 1
#endif
#define _VE_PAGE_BYTES (getenv("FLASH_ERASE_SIZE")*VIRTUAL_EEPROM_NUM_PAGES)
#ifdef VIRTUAL_EEPROM_START_ADDR
#if ((VIRTUAL_EEPROM_START_ADDR % (getenv("FLASH_ERASE_SIZE")/_VE_BPA)) != 0)
#error Virtual EEPROM Start Address must be on a flash erase boundary
#endif
#if ((VIRTUAL_EEPROM_START_ADDR + (2*(_VE_PAGE_BYTES/_VE_BPA))) > getenv("PROGRAM_MEMORY"))
#error Virtual EEPROM Start Address to high, memory overruns program memory size
#endif
#define _VE_FLASH_SIZE_INSTRUCTIONS (VIRTUAL_EEPROM_START_ADDR + (2*(_VE_PAGE_BYTES/_VE_BPA)))
#else
#if ((getenv("PROGRAM_MEMORY") % (getenv("FLASH_ERASE_SIZE")/_VE_BPA)) != 0)
//go back one page, because this page is being used for config bits
#define _VE_FLASH_SIZE_INSTRUCTIONS (getenv("PROGRAM_MEMORY") - (getenv("PROGRAM_MEMORY") % (getenv("FLASH_ERASE_SIZE")/_VE_BPA)))
#else
#define _VE_FLASH_SIZE_INSTRUCTIONS getenv("PROGRAM_MEMORY")
#endif
#endif |
This makes me wonder if indeed the flash erase size is in increments of 0x400 address locations for chips reporting FLASH_ERASE_SIZE of 0x800 (2,048) bytes? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sun Apr 18, 2021 9:58 am |
|
|
The erase code uses a 16bit address. If you look at the data sheet, you
cannot erase on a byte boundary, on on 16 bit addresses. Hence the byte
address is divided by 2 to give a 16bit address.
I think the manual makes it very plain that the actual erase size is
completely device specific. |
|
|
2xhp
Joined: 14 Jan 2019 Posts: 39
|
|
Posted: Mon Apr 19, 2021 10:41 am |
|
|
Ttelmah wrote: | The erase code uses a 16bit address. If you look at the data sheet, you
cannot erase on a byte boundary, on on 16 bit addresses. Hence the byte
address is divided by 2 to give a 16bit address.
I think the manual makes it very plain that the actual erase size is
completely device specific. |
I'm probably explaining the situation poorly. Right now, my main question is related to your statement:
Ttelmah wrote: | By dividing by 2, you are performing two erases per page. Each erase uses
up a 'life' on this page, so you will kill the chip in half the time that would
otherwise happen.... |
This boils down more specifically to this question: for this PIC (dsPIC33EV256GM104) with a erase block size of 1,536, as I erase program memory, should I be incrementing the address by 1,024 (0x400) or 2,048 (0x800)?
I ran a test where I filled a section of memory from 0x15000 to 0x1A000 with some recognizable data (essentially something other than 0xFF). I then did erase_program_memory starting at 0x15000 and incrementing the address by 0x800:
Code: |
erase_address_location = 0x15000;
for(i=0;i<3;i++) {
erase_program_memory(erase_address_location);
erase_address_location+=0x800;
delay_ms(1);
} |
It erases from 0x15000 to 0x15400.
The data I filled memory with is present from 0x15400 to 0x15800.
It erases from 0x15800 to 0x15C00.
The data I filled memory with is present from 0x15C00 to 0x16000.
It erases from 0x16000 to 0x16400.
The data I filled memory with is present from 0x16400 to 0x1A000.
*************************
My summary from this test is that I must increment the address by 0x400 (FLASH_ERASE_SIZE / 2) over the space to be deleted or I will only erase half of the intended space. This seems to line up with the virtual_eeprom.c code and testing I have done with it.
I certainly welcome any correction that might be needed in case I've somehow missed something. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 19, 2021 11:38 am |
|
|
The CCS manual has the following example code:
Code: |
// Erase a block of memory from 0x2000 to 0x2400
// for a PIC24HJ/FJ /33FJ device.
int32 address = 0x2000;
erase_program_memory(address);
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Wed Apr 21, 2021 12:29 am |
|
|
OK. Did an experiment.
The answer here is that the data sheet is wrong. Unfortunately, the CCS
value returned by getenv("FLASH_ERASE_SIZE"), is based on the data
sheet value, so this also is wrong.
When you trigger a block erase on the chip, it erases 256 instructions,
not 512 instructions (at least in the MPLAB simulator).
Now it may be that it is the simulator that has the problem.
Have you tried in an actual chip?.
This is why you are seeing the confusing behaviour.
I did a simple one instruction marker every 256 bytes:
Code: |
#ROM 0x1000 = {0}
#rom 0x1100 = {0}
#rom 0x1200 = {0}
#rom 0x1300 = {0}
#rom 0x1400 = {0}
#ROM 0x1500 = {0}
#rom 0x1600 = {0}
#rom 0x1700 = {0}
#rom 0x1800 = {0}
#ROM 0x1900 = {0}
#rom 0x1A00 = {0}
#rom 0x1B00 = {0}
#rom 0x1C00 = {0}
#rom 0x1D00 = {0}
#rom 0x1E00 = {0}
#rom 0x1F00 = {0}
#rom 0x2000 = {0}
#rom 0x2100 = {0}
#rom 0x2200 = {0}
#rom 0x2300 = {0}
#rom 0x2400 = {0}
#ROM 0x2500 = {0}
#rom 0x2600 = {0}
#rom 0x2700 = {0}
#rom 0x2800 = {0}
#ROM 0x2900 = {0}
|
Then did a single erase at address 0x1000
The result was that the first marker that was not erased was at 0x1400.
So the erase has done 256 instructions, not the 512 the data sheet says. |
|
|
2xhp
Joined: 14 Jan 2019 Posts: 39
|
|
Posted: Wed Apr 21, 2021 12:52 am |
|
|
Ttelmah wrote: | OK. Did an experiment.
Have you tried in an actual chip?.
|
Yes, the tests above were all with an actual chip using MPLAB X IPE v5.30 with a PICKIT4 to read out the chip after I ran the tests.
Ttelmah wrote: |
Then did a single erase at address 0x1000
The result was that the first marker that was not erased was at 0x1400.
So the erase has done 256 instructions, not the 512 the data sheet says. |
Sounds like that matches what I saw - that the erase clears 0x400 of memory. |
|
|
|