PDA

View Full Version : WRITECODE and BLOCKSIZE on 18F26J50



proximo
- 20th June 2011, 15:30
Hello!

I'm currently using this PIC because it holds the RTCC; unfortunatly it seems that it's not possible to have a device with two serial ports, the RTCC and an EEPROM at the same time, so I have to use the code flash in order to store my permanent data.
After reading some post, in particular this one:
http://www.picbasic.co.uk/forum/showthread.php?t=14655&highlight=writecode
I discovered that it's not possible to write only 1 word at time using PBP-level commands and the assembly should be use (the mcu datasheet tells that 2bytes writings are allowed on this device).
By the way, I found out that it's possible to write ONLY 2 bytes on the flash, with a single WRITECODE operation (I mean, without 64 cycles-wide FOR NEXT loops) by changing the BLOCKSIZE statement inside the .INC file from 64 to 2:
BLOCK_SIZE EQU 2
I would like to know what I'm going to compromise doing that. For now, everything seems to work fine, but I'm afraid some memory management or what else can be made mulfunctionig :confused:. Can you please help me?
Thank you very much

proximo
- 21st June 2011, 16:22
Or maybe I can rewrite the question this way:

What does the BLOCK_SIZE statement inside the .INC file do? What does it configure?

Thank you!

Darrel Taylor
- 21st June 2011, 20:50
Changing BLOCK_SIZE to 2 will not work.
In order to write 1 word at a time, the WPROG bit must be set in EECON1, and WRITECODE does not set that bit.

For example, using the following code it tries to write 100 BYTEs to Flash. At each word location it writes the address of that word. The results were read back with a U2 programmer.
The image on the left is with BLOCK_SIZE = 64. Only 64 out of the 100 BYTEs actually gets written. This is the normal operation of WRITECODE.

The image on the right is with BLOCK_SIZE = 2.
It was still writing 64 bytes at a time, but it was doing it for every 2 bytes.
The holding registers don't get cleared, and the data gets really messed up.
It ends up writing 128 bytes with BAD Data.

5678

; Bad program -- do not use --
;
FlashAddr VAR WORD
Idx VAR WORD
Wvar VAR WORD
;----[Get address of Flash Data Area]-------------------------------------------
;
ASM
CHK?RP _FlashAddr
movlw low(_FlashData)
movwf _FlashAddr
movlw high(_FlashData)
movwf _FlashAddr + 1
ENDASM
;
;----[The Main Program]---------------------------------------------------------
FOR Idx = FlashAddr to FlashAddr+100 STEP 2
Wvar = Idx
WRITECODE Idx, Wvar
NEXT Idx
STOP
;
;----[This is where the Data will be saved in Flash]----------------------------
@ org $+1023 & 0FC00h ; align to 1KB boundary
FlashData:


As stated in the other thread, you can use the assembly language routine in the datasheet.
Or, here's an adaptation that allows you to write 1 WORD at a time.
You can see in this image that it writes the correct data.

5679

Pause 100
FlashAddr VAR WORD
Idx VAR WORD
Wvar VAR WORD
;
;----[Get address of Flash Data Area]-------------------------------------------
ASM
CHK?RP _FlashAddr
movlw low(_FlashData)
movwf _FlashAddr
movlw high(_FlashData)
movwf _FlashAddr + 1
ENDASM
;
;----[The Main Program]---------------------------------------------------------
FOR Idx = FlashAddr to FlashAddr+100 STEP 2
Wvar = Idx
GOSUB WRITEWORD
NEXT Idx
;
STOP
;
;-------------------------------------------------------------------------------
WRITEWORD:
TBLPTRU = 0 ; Load TBLPTR with the base address
TBLPTRH = Idx.HighByte
TBLPTRL = Idx.LowByte ; The TBLPTR must be loaded with an even address
TABLAT = Wvar.LowByte ; LSB of word to be written
@ TBLWT*+
TABLAT = Wvar.highByte ; MSB of word to be written
@ TBLWT* ; The last table write must not increment the table
ASM
; PROGRAM_MEMORY
BSF EECON1, WPROG ; enable single word write
BSF EECON1, WREN ; enable write to memory
MOVE?TT INTCON,GIE, R0,0 ; save state of GIE
BCF INTCON,GIE ; disable interrupts
MOVLW 0x55
MOVWF EECON2 ; write 0x55
MOVLW 0xAA
MOVWF EECON2 ; write 0xAA
BSF EECON1, WR ; start program (CPU stall)
MOVE?TT R0,0, INTCON,GIE ; restore GIE state
BCF EECON1, WPROG ; disable single word write
BCF EECON1, WREN ; disable write to memory
ENDASM
RETURN
;
;----[This is where the Data will be saved in Flash]----------------------------
@ org $+1023 & 0FC00h ; align to 1KB boundary
FlashData:


Keep in mind that you still have to erase 1kB at a time.
That's why you want to "Align" the data with a 1k boundary.

proximo
- 22nd June 2011, 11:16
Hi Darrel, thank you very much for your reply!
I tried your sub and of course it works, perfectly!
By the way, before you replied, I tried a small program (with block size = 2) and it seemed to work for the first 64 bytes under a cycle of 256, not from the 65th to the end;
So, the solution for my thread is definitely the assembly, however I'm posting the code and the result:


CONTAW VAR WORD
ERASECODE $3000 '1k from $3000 will be erased
FOR CONTAW=0 TO 255 STEP 2 'writes 256 bytes, 1 word for address
WRITECODE $3000+CONTAW,CONTAW 'On each address, wrties a word containing the cycle index
NEXT CONTAW



Thank you again!