Writing to Data EEPROM on 16F18877 in Assembly

50 Views Asked by At

I am trying to figure out how to write to the data EEPROM on the PIC16F18877 in Assembly. This the first time I am trying to use it and I've read through the datasheet several times (although I sometimes find Microchip's documentation to be lack/unclear) and tried Googling for solution with no luck.

My goal was to read from 0xF001, then write 0x25 to that location, and finally read it back. The initial read returns 0x0, even though the EE Data Memory window shows all locations as 0xFF, and then readback just returns 0x0 as I clear the location before readback to ensure I am reading back the data in the EEPROM and not a previous value.

I am sure I a missing something simple/obvious, but I can't seem to figure out what it is. This is the (non-working) code I came up with:

  MOVLW  01h
  MOVWF  eeprom_addr_low
  MOVLW  0F0h
  MOVWF  eeprom_addr_high
   
  ;READ EEPROM
  BANKSEL NVMADRL
  MOVLW   eeprom_addr_low
  MOVWF   NVMADRL
  MOVLW   eeprom_addr_high
  MOVWF   NVMADRH
   
  BSF     NVMCON1,6  ;NVMREGS
  BSF     NVMCON1,0  ;RD
   
  MOVF    NVMDATL,W
  MOVWF   eeprom_data_low
  MOVF    NVMDATH,W
  MOVWF   eeprom_data_high
   
  ;WRITE EEPROM
  BANKSEL NVMADRH
  MOVF    eeprom_addr_high,W
  MOVWF   NVMADRH
  MOVF    eeprom_addr_low,W
  MOVWF   NVMADRL
  BSF     NVMCON1,2     ;WREN
  BSF     NVMCON1,6     ;LWL0
   
writeLoop:
  MOVLW   025h
  MOVWF   NVMDATL
  MOVLW   00h           ;0x00
  MOVWF   NVMDATH
  MOVLW   eeprom_addr_low   ;01h
  MOVWF   NVMADRL
  MOVLW   eeprom_addr_high  ;0F0h
  MOVWF   NVMADRH
  BSF     NVMCON1,2     ;WREN
unlockSeq:
  BCF     INTCON,7      ;GIE
  MOVLW   055h
  MOVWF   NVMCON2
  MOVLW   0AAh
  MOVWF   NVMCON2
  BSF     NVMCON1,1     ;WR
  BSF     INTCON,7      ;GIE
  BCF     NVMCON1,2     ;WREN
readBack:
  MOVLW   00h
  MOVWF   NVMDATL       ;Just clearing it to confirm if the readback is working for debugging purposes
  MOVWF   NVMDATH
   
  MOVLW   eeprom_addr_low
  MOVWF   NVMADRL
  MOVLW   eeprom_addr_high
  MOVWF   NVMADRH
   
  BSF     NVMCON1,6
  BSF     NVMCON1,0
   
  MOVF    NVMDATL,W
  MOVWF   eeprom_data_low
  MOVF    NVMDATH,W
  MOVWF   eeprom_data_high

I also attempted to add a loop to wait for the read to be completed as my understand is that bit 0 of NVMCON1 will be cleared once the read is completed. However, if I add this:

waitForRead:
    BTFSC   NVMCON1,0
    GOTO    waitForRead

then it goes into an infinite loop.

Any help/guidance would be greatly appreciated as I am stuck on exactly what I am missing.

1

There are 1 best solutions below

0
Dominick On

So after playing around with it some more I was able to get the read/write/read to work with the following code:

    MOVLW   01h
    MOVWF   eeprom_addr_low
    MOVLW   0F0h
    MOVWF   eeprom_addr_high
    
    ;READ EEPROM
    BANKSEL NVMADRL
    MOVLW   eeprom_addr_low
    MOVWF   NVMADRL
    MOVLW   eeprom_addr_high
    MOVWF   NVMADRH
    
    BSF BANKMASK(NVMCON1),6   ;NVMREGS
    BSF BANKMASK(NVMCON1),0   ;RD
    
   
waitForRead:
    BTFSC   BANKMASK(NVMCON1),0
    GOTO    waitForRead
       
    BANKSEL NVMDATL
    MOVF    NVMDATL,W
    MOVWF   eeprom_data_low
    
    ;WRITE EEPROM
    BANKSEL NVMADRL
    
    MOVF    eeprom_addr_low,W
    MOVWF   NVMADRL
    MOVLW   0F0h
    MOVWF   NVMADRH

    
writeLoop:
    BANKSEL NVMDATL
    MOVLW   025h
    MOVWF   NVMDATL
    
    BANKSEL NVMADRL
    MOVLW   eeprom_addr_low ;01h
    MOVWF   NVMADRL
    MOVLW   0F0h        
    MOVWF   NVMADRH
    
    BSF     BANKMASK(NVMCON1),2     ;WREN

unlockSeq:
    MOVLW   055h
    BCF     BANKMASK(INTCON),7      ;GIE
    MOVWF   NVMCON2
    MOVLW   0AAh
    MOVWF   NVMCON2
    BSF     BANKMASK(NVMCON1),1     ;WR
    BSF     BANKMASK(INTCON),7      ;GIE
    BCF     BANKMASK(NVMCON1),2     ;WREN
waitForWrite:
    BTFSC   NVMCON1,1           ;WR
    GOTO    waitForWrite

readBack:
    MOVLW   01h
    MOVWF   eeprom_addr_low
    MOVLW   0F0h
    MOVWF   eeprom_addr_high
    
    ;READ EEPROM
    BANKSEL NVMADRL
    MOVLW   eeprom_addr_low
    MOVWF   NVMADRL
    MOVLW   0F0h
    MOVWF   NVMADRH
    
    BSF BANKMASK(NVMCON1),6   ;NVMREGS
    BSF BANKMASK(NVMCON1),0   ;RD
    
    BANKSEL NVMDATL
    MOVF    NVMDATL,W
    MOVWF   eeprom_data_low

It seems there were two issues:

  1. I wasn't waiting for the write to complete and trying to read it back to quickly.

  2. The MPLAB Simulator seems to be kind of broken. That is, sometimes I would run the code a second time (after it was working) without making any changes and the initial read from the EEPROM would return 0x0, instead of the expected 0xFF (which is the default value for all locations when starting up). Cleaning/rebuilding occasionally fixed this, but sometimes I would have to completely restart MPLAB and then immediately debug the code and it worked as expected. Curious if anyone else has run into this.