I've been using the pic24FJ64GA004 for some time, and I now want to store some data in the flash program memory.
I ran Microchip's examples for erasing and writing code and they work fine on their own, but I can't get writing to work after I have erased a block.
The code:-
Turns on an LED
Erases a block of flash
Turns off the LED
waits about a second
Turns on the LED
Loads some data into the holding registers
Writes that data into the flash
Then it flashes the LED for ever.
The code always gets to the end. If I run it as is, the block gets erased but nothing gets written. If I disable the erase, the data gets written as expected.
Here is my code. The parts in capitals are Microchip's examples.
Any ideas what I'm doing wrong?
I ran Microchip's examples for erasing and writing code and they work fine on their own, but I can't get writing to work after I have erased a block.
The code:-
Turns on an LED
Erases a block of flash
Turns off the LED
waits about a second
Turns on the LED
Loads some data into the holding registers
Writes that data into the flash
Then it flashes the LED for ever.
The code always gets to the end. If I run it as is, the block gets erased but nothing gets written. If I disable the erase, the data gets written as expected.
Here is my code. The parts in capitals are Microchip's examples.
Code:
.include "p24FJ64GA004.inc"
config __CONFIG2, IESO_OFF & FNOSC_FRC & FCKSM_CSECMD & OSCIOFNC_ON & IOL1WAY_OFF & I2C1SEL_SEC & POSCMOD_EC
config __CONFIG1, JTAGEN_OFF & GCP_OFF & GWRP_OFF & BKBUG_OFF & COE_OFF & ICS_PGx1 & FWDTEN_OFF & WINDIS_OFF & FWPSA_PR32 & WDTPS_PS32768
.text
red_led_reg = LATA
red_led = 1
bclr TRISA, #1
bset red_led_reg, #red_led
PROG_ADDR = 0x1000
; Set up NVMCON for block erase operation
MOV #0x4042, W0 ;
MOV W0, NVMCON ; Initialize NVMCON
; Init pointer to row to be ERASED
MOV #tblpage(PROG_ADDR), W0 ;
MOV W0, TBLPAG ; Initialize PM Page Boundary SFR
MOV #tbloffset(PROG_ADDR), W0 ; Initialize in-page EA[15:0] pointer
TBLWTL W0, [W0] ; Set base address of erase block
MOV #0x55, W0
MOV W0, NVMKEY ; Write the 55 key
MOV #0xAA, W1 ;
MOV W1, NVMKEY ; Write the AA key
BSET NVMCON, #WR ; Start the erase sequence
NOP ; Insert two NOPs after the erase
NOP ; command is asserted
BTSC NVMCON, #15 ; Wait for the sequence to be completed
BRA $-2 ;
bclr red_led_reg, #red_led
mov #0x100, w0
pause_loop:
repeat #0x2000
nop
dec w0, w0
bra NZ, pause_loop ;Pause for about a second.
bset red_led_reg, #red_led
setup_table_example:
; Set up NVMCON for row programming operations
MOV #0x4001, W0 ;
MOV W0, NVMCON ; Initialize NVMCON
; Set up a pointer to the first program memory location to be written
; program memory selected, and writes enabled
MOV #0x0000, W0 ;
MOV W0, TBLPAG ; Initialize PM Page Boundary SFR
MOV #0x1000, W0 ; An example program memory address
; Perform the TBLWT instructions to write the latches
mov #64, w4
clr W3 ;
program_save_loop:
;This just writes some rubbish into the buffer
MOV #0x4142, W2 ;
TBLWTL W2, [W0] ; Write PM low word into program latch
TBLWTH W3, [W0++] ; Write PM high byte into program latch
inc w3, w3
dec w4, w4
bra NZ, program_save_loop
MOV #0x55, W0
MOV W0, NVMKEY ; Write the 55 key
MOV #0xAA, W1 ;
MOV W1, NVMKEY ; Write the AA key
BSET NVMCON, #WR ; Start the erase sequence
NOP ; 2 NOPs required after setting WR
NOP ;
BTSC NVMCON, #15 ; Wait for the sequence to be completed
BRA $-2 ;
led_flash:
bclr red_led_reg, #red_led
repeat #0x2000
nop
bset red_led_reg, #red_led
repeat #0x2000
nop
bra led_flash ;stop here
.org 0xdf0
.pword 0x123456, 0x123456 ;Put something in memory so that I can see when it has been erased
.pword 0x123456, 0x123456
.pword 0x123456, 0x123456
.pword 0x123456, 0x123456
.pword 0x123456, 0x123456
.pword 0x123456, 0x123456
.pword 0x123456, 0x123456
.pword 0x123456, 0x123456
.pword 0x123456, 0x123456
.pword 0x123456, 0x123456
.pword 0x123456, 0x123456
Any ideas what I'm doing wrong?