问题
I am using MPLAB C18 compiler with PIC18F87J11 and I am trying to save some values to flash memory, using inline assembly, which is a combination of C and assembly code.
It looks like I can write and read to flash memory correctly, but as soon as I power cycle my PIC and then attempt to read what I previous saved from a specific address, I don't get the same value. I am saving 0x09
to 0xB22A
address. Like I said, if I save the value then read it immediately, everything comes up correctly, but upon resetting the PIC I get 0x00
.
Am I not saving permanently to flash memory or what is really happening here?
This is my code:
Erase memory row
_asm
MOVLW 0x00
MOVWF TBLPTRU,BANKED
MOVLW 0xB2
MOVWF TBLPTRH,BANKED
MOVLW 0x2A
MOVWF TBLPTRL,BANKED
_endasm
EECON1bits.FREE = 1;
INTCONbits.GIE = 0;
_asm
MOVLW 0x55
MOVWF EECON2,BANKED
MOVLW 0xAA
MOVWF EECON2,BANKED
_endasm
EECON1bits.WR = 1;
INTCONbits.GIE = 1;
Write to flash memory
_asm
MOVLW 0x00
MOVWF TBLPTRU,BANKED
MOVLW 0xB2
MOVWF TBLPTRH,BANKED
MOVLW 0x2A
MOVWF TBLPTRL,BANKED
MOVLW 0x09
MOVWF TABLAT,BANKED
TBLWTPOSTINC
MOVLW 0x09
MOVWF TABLAT,BANKED
TBLWT
_endasm
EECON1bits.WPROG = 1;
EECON1bits.WREN = 1;
INTCONbits.GIE = 0;
_asm
MOVLW 0x55
MOVWF EECON2,BANKED
MOVLW 0xAA
MOVWF EECON2,BANKED
_endasm
EECON1bits.WR = 1;
INTCONbits.GIE = 1;
EECON1bits.WPROG = 0;
EECON1bits.WREN = 0;
Read from flash memeory
_asm
MOVLW 0x00
MOVWF TBLPTRU,BANKED
MOVLW 0xB2
MOVWF TBLPTRH,BANKED
MOVLW 0x2A
MOVWF TBLPTRL,BANKED
READ_WORD:
TBLRDPOSTINC
MOVF TABLAT, 0,BANKED
MOVWF WORD_EVEN,ACCESS
TBLRDPOSTINC
MOVF TABLAT, 0,BANKED
MOVWF WORD_ODD,ACCESS
_endasm
printf("\r\n");
PrintChar(WORD_EVEN);
printf("\r\n");
PrintChar(WORD_ODD);
The original code can be found in the datasheet on chapter 6, but remember I had to modify it a little bit to be able to use it with C. I am not sure what the difference is between ACCESS
and BANKED
as I suspect they might be related to the problem.
回答1:
It looks like you arrived at the solution already: the problem is in using BANKED
.
EECON2
and the like are Special Function Registers (SFRs) that reside in bank 15. The fastest way to access them is to use ACCESS
, which ignores the bank register in computing the address.
It looks like in the assembly language you are using, ACCESS
means 0 and BANKED
means 1. One of these values is required in the movwf
instruction. The datasheet uses the actual numbers in its examples, instead of symbolic constants.
The datasheet also explains the how the RAM is banked.
Basically, there is as register that holds 4 bits representing banks 0 to 15. This number gets prepended to the 8 bit number given to the instruction, to give all 12 bits. This allows faster execution. To store in the correct location, you need to set this register to the correct bank first.
Two of the banks, 0 and 15, are mapped to the General Purpose registers and Special Function Registers as well. Since these are used most often, the fast way to get to them is to use a flag in the instruction to ignore the bank register in computing the address, and go straight to the GPR or SFR you want.
Your problem is that you were setting the flag to use a different bank of memory from where the register reside.
来源:https://stackoverflow.com/questions/18179070/how-to-write-to-flash-memory-using-inline-assembly