Mercurial > public > hwos_code
diff src/external_flash.asm @ 634:4050675965ea
3.10 stable release
author | heinrichsweikamp |
---|---|
date | Tue, 28 Apr 2020 17:34:31 +0200 |
parents | 690c48db7b5b |
children | 75e90cd0c2c3 |
line wrap: on
line diff
--- a/src/external_flash.asm Thu Mar 05 15:06:14 2020 +0100 +++ b/src/external_flash.asm Tue Apr 28 17:34:31 2020 +0200 @@ -1,6 +1,6 @@ ;============================================================================= ; -; File external_flash.asm combined next generation V3.08.8 +; File external_flash.asm * combined next generation V3.09.4e ; ; External flash ; @@ -13,92 +13,121 @@ #include "wait.inc" #include "eeprom_rs232.inc" +;============================================================================= ext_flash CODE - ;============================================================================= -; increase flash address by one with wrap-around at 0x400000 to 0x000000 -incf_ext_flash_address_p1_0x40: - movlw .1 ; increase by 1 - ;bra incf_ext_flash_address0_0x40 ; continue +;----------------------------------------------------------------------------- +; increase Flash Address by one with wrap-around at 0x400000 to 0x000000 +; +ext_flash_inc_address_0x40_p1: + movlw .1 ; increment by 1 + ;bra ext_flash_inc_address_0x40_exec ; execute incrementing -; increase flash address by value in WREG with wrap-around at 0x400000 to 0x000000 - global incf_ext_flash_address0_0x40 -incf_ext_flash_address0_0x40: - clrf ext_flash_rollover_threshold ; set wrap-around threshold without destroying WREG to ... - bsf ext_flash_rollover_threshold,6 ; ... 0x40 +;----------------------------------------------------------------------------- +; increase Flash Address by Value in WREG with wrap-around at 0x400000 to 0x000000 +; + global ext_flash_inc_address_0x40_exec +ext_flash_inc_address_0x40_exec: + clrf ext_flash_address_limit ; | set wrap-around threshold to + bsf ext_flash_address_limit,6 ; | 0x40 without destroying WREG bra incf_ext_flash_address0_common ; continue with common part -; increase flash address by one with wrap-around at 0x200000 to 0x000000 -incf_ext_flash_address_p1_0x20: - movlw .1 ; increase by one - ;bra incf_ext_flash_address0_0x20 ; continue +;----------------------------------------------------------------------------- +; increase Flash Address by one with wrap-around at 0x200000 to 0x000000 +; +ext_flash_inc_address_0x20_p1: + movlw .1 ; increment by one + ;bra ext_flash_inc_address_0x20_exec ; execute incrementing -; increase flash address by value in WREG with wrap-around at 0x200000 to 0x000000 - global incf_ext_flash_address0_0x20 -incf_ext_flash_address0_0x20: - clrf ext_flash_rollover_threshold ; set wrap-around threshold without destroying WREG to ... - bsf ext_flash_rollover_threshold,5 ; ... 0x20 +;----------------------------------------------------------------------------- +; increase Flash Address by Value in WREG with wrap-around at 0x200000 to 0x000000 +; + global ext_flash_inc_address_0x20_exec +ext_flash_inc_address_0x20_exec: + clrf ext_flash_address_limit ; | set wrap-around threshold to + bsf ext_flash_address_limit,5 ; | 0x20 without destroying WREG ;bra incf_ext_flash_address0_common ; continue with common part +;----------------------------------------------------------------------------- +; common Part for Flash Address Increasing +; incf_ext_flash_address0_common: - bcf address_wrap_around ; clear wrap-around flag + bcf flash_wrap_around ; clear wrap-around flag addwf ext_flash_address+0,F ; add WREG to address:3 movlw d'0' ; ... addwfc ext_flash_address+1,F ; ... addwfc ext_flash_address+2,F ; ... - movf ext_flash_rollover_threshold,W ; get wrap-around threshold + movf ext_flash_address_limit,W ; get wrap-around threshold cpfseq ext_flash_address+2 ; at wrap-around threshold ? bra incf_ext_flash_address1 ; NO - no wrap-around needed ; clrf ext_flash_address+0 ; YES - wrap-around to 0x000000 ; clrf ext_flash_address+1 ; - ... clrf ext_flash_address+2 ; - ... - bsf address_wrap_around ; - set wrap-around flag + bsf flash_wrap_around ; - set wrap-around flag incf_ext_flash_address1: movf ext_flash_rw,W ; export current value of ext_flash_rw via WREG, too return ; done -; decrease flash length counter by value in WREG - global decf_ext_flash_length0 -decf_ext_flash_length0: - subwf ext_flash_length_counter+0,F ; decrease address by value in WREG +;----------------------------------------------------------------------------- +; add 0x001000 to Flash Address, no Check for wrap-around +; + global ext_flash_inc_address_4kB +ext_flash_inc_address_4kB: + movlw 0x10 ; add 0x10 to high byte + addwf ext_flash_address+1,F ; ... + movlw 0x00 ; propagate carry to upper byte + addwfc ext_flash_address+2,F ; ... + return ; done + + +;----------------------------------------------------------------------------- +; decrement Length Counter by 1 +; + global ext_flash_dec_length_exec +ext_flash_dec_length_exec: + movlw .1 ; decrement by 1 + subwf ext_flash_length_counter+0,F ; ... movlw d'0' ; ... subwfb ext_flash_length_counter+1,F ; ... subwfb ext_flash_length_counter+2,F ; ... return ; done -; ---------------------------------------------------------------------------- - -; global ext_flash_byte_read_plus_0x40 ; return data read in ext_flash_rw and WREG, increase address after read with wrap-around at 0x400000 -;ext_flash_byte_read_plus_0x40: -; rcall ext_flash_byte_read ; read byte into ext_flash_rw -; bra incf_ext_flash_address_p1_0x40 ; increase address with wrap-around at 0x400000 to 0x000000 (and return) - - global ext_flash_byte_read_plus_0x20 ; return data read in ext_flash_rw and WREG, increase address after read with wrap-around at 0x200000 -ext_flash_byte_read_plus_0x20: - rcall ext_flash_byte_read ; read byte into ext_flash_rw - bra incf_ext_flash_address_p1_0x20 ; increase address with roll-over at 0x200000 to 0x000000 (and return) +;----------------------------------------------------------------------------- +; read a Byte from Flash and increment Address with wrap-around at 0x20 / 0x40 +; returns in ext_flash_rw and WREG +; + global ext_flash_read_byte_0x40 +ext_flash_read_byte_0x40: + bsf flash_wrap_around ; wrap-around at 0x400000 + bra ext_flash_read_byte_common ; continue with common part + global ext_flash_read_byte_0x20 +ext_flash_read_byte_0x20: + bcf flash_wrap_around ; wrap-around at 0x200000 + ;bra ext_flash_read_byte_common ; continue with common part - global ext_flash_byte_read ; return data read in WREG and ext_flash_rw, no address change -ext_flash_byte_read: - movlw 0x03 ; set up read command - rcall shift_spi ; prepare read command +ext_flash_read_byte_common: + movlw 0x03 ; prepare read command + rcall shift_spi ; execute read command rcall ext_flash_set_address ; write 24 bit address ext_flash_address:3 via SPI rcall shift_spi ; shift the SPI to read data into WREG bsf flash_ncs ; set CS=1 - movwf ext_flash_rw ; return data read in WREG and ext_flash_rw - return ; done + movwf ext_flash_rw ; copy byte read from WREG to ext_flash_rw + btfss flash_wrap_around ; shall wrap-around at 0x40000 ? + bra ext_flash_inc_address_0x20_p1 ; NO - increment address with wrap-around at 0x200000 and return + bra ext_flash_inc_address_0x40_p1 ; YES - increment address with wrap-around at 0x200000 and return -; ---------------------------------------------------------------------------- -; read-range base functions +;----------------------------------------------------------------------------- +; Read-Range Base Functions - start reading +; global ext_flash_read_block_start ; return data read in WREG ext_flash_read_block_start: movlw 0x03 ; set up read command @@ -107,50 +136,61 @@ bra shift_spi ; shift the SPI to read data into WREG (and return) +;----------------------------------------------------------------------------- +; Read-Range Base Functions - increment Address and read a Byte, wrap-around at 0x40 +; global ext_flash_read_block_0x40 ; return data read in WREG ext_flash_read_block_0x40: - rcall incf_ext_flash_address_p1_0x40 ; increase address with wrap-around at 0x400000 - btfss address_wrap_around ; did the address wrap-around? - bra shift_spi_loop_1 ; NO - shift the SPI to read data into WREG and return - rcall ext_flash_read_block_stop ; YES - do a block-stop - bra ext_flash_read_block_start ; - do a block-start, read data into WREG and return - - - global ext_flash_read_block_0x20 ; return data read in WREG -ext_flash_read_block_0x20: - rcall incf_ext_flash_address_p1_0x20 ; increase address with wrap-around at 0x200000 - btfss address_wrap_around ; did the address wrap-around? + rcall ext_flash_inc_address_0x40_p1 ; increase address with wrap-around at 0x400000 + btfss flash_wrap_around ; did the address wrap-around? bra shift_spi_loop_1 ; NO - shift the SPI to read data into WREG and return rcall ext_flash_read_block_stop ; YES - do a block-stop bra ext_flash_read_block_start ; - do a block-start, read data into WREG and return +;----------------------------------------------------------------------------- +; Read-Range Base Functions - increment Address and read a Byte, wrap-around at 0x20 +; +; global ext_flash_read_block_0x20 ; return data read in WREG +;ext_flash_read_block_0x20: +; rcall ext_flash_inc_address_0x20_p1 ; increase address with wrap-around at 0x200000 +; btfss flash_wrap_around ; did the address wrap-around? +; bra shift_spi_loop_1 ; NO - shift the SPI to read data into WREG and return +; rcall ext_flash_read_block_stop ; YES - do a block-stop +; bra ext_flash_read_block_start ; - do a block-start, read data into WREG and return + + +;----------------------------------------------------------------------------- +; Read-Range Base Functions - terminate reading +; global ext_flash_read_block_stop ; end block operation ext_flash_read_block_stop: bsf flash_ncs ; set CS=1 return ; done + ; ---------------------------------------------------------------------------- -; read-range function, to be used through macro +; read a Range of Bytes, to be used via Macro ; global ext_flash_read_range ext_flash_read_range: movwf eeprom_loop ; load loop counter (eeprom variable used here) - rcall ext_flash_read_block_start ; read first byte from flash + rcall ext_flash_read_block_start ; read first byte from FLASH to WREG bra ext_flash_read_range_loop_start ; jump into loop ext_flash_read_range_loop: - rcall ext_flash_read_block_0x40 ; read next byte from flash + rcall shift_spi_loop_1 ; read next byte from FLASH to WREG ext_flash_read_range_loop_start: - movwf POSTINC1 ; write byte to memory + movwf POSTINC1 ; write byte from WREG to memory decfsz eeprom_loop,F ; decrement loop counter, all done? bra ext_flash_read_range_loop ; NO - continue loop bra ext_flash_read_block_stop ; YES - end reading from flash (and return) ; ---------------------------------------------------------------------------- -; write-range base functions - +; Write-Range Base Functions - for use with SST26VF Chip only! +; ext_flash_write_block_start: + movwf ext_flash_rw ; copy byte to write from WREG to ext_flash_rw bsf flash_ncs ; set CS=1 movlw 0x06 ; set up WREN command rcall shift_spi ; execute WREN command @@ -158,161 +198,182 @@ movlw 0x02 ; set up write (PP, Page-Program) command rcall shift_spi ; execute write rcall ext_flash_set_address ; write 24 bit address ext_flash_address:3 via SPI - movf ext_flash_rw,W ; get byte to write + movf ext_flash_rw,W ; get back byte to write bra shift_spi ; write the byte (and return) ext_flash_write_block: - movf ext_flash_rw,W ; get byte to write bra shift_spi_loop_1 ; shift the SPI to write data into FLASH (and return) ext_flash_write_block_stop: bra ext_flash_wait_write ; wait for completion (and return) + ; ---------------------------------------------------------------------------- -; write-range function, to be used through macro +; write a Range of Bytes, to be used via Macro ; global ext_flash_write_range ext_flash_write_range: movwf eeprom_loop ; load loop counter (eeprom variable used here) -; btfsc flash_block_write ; does the FLASH support block-write? -; bra ext_flash_write_range_block ; YES - write date via block operation -; ;bra ext_flash_write_range_seq ; NO - write data via sequential single writes + btfsc flash_block_write ; does the FLASH support block-write? + bra ext_flash_write_range_block ; YES - write data in block mode + ;bra ext_flash_write_range_seq ; NO - write data in sequential mode -ext_flash_write_range_seq: ; sequential write -ext_flash_write_range_loop_s: - movff POSTINC1,ext_flash_rw ; read byte from memory to ext_flash_rw - rcall ext_flash_byte_write ; write byte from ext_flash_rw to FLASH - rcall incf_ext_flash_address_p1_0x40 ; increase address with wrap-around at 0x400000 + ; sequential write +ext_flash_write_range_seq: + bsf flash_wait ; wait for flash writes to complete +ext_flash_write_range_seq_loop: + movf POSTINC1,W ; copy byte from memory to WREG + rcall ext_flash_byte_write_common_W ; write byte from WREG to FLASH + rcall ext_flash_inc_address_0x40_p1 ; increase address with wrap-around at 0x400000 decfsz eeprom_loop,F ; decrement loop counter, all done? - bra ext_flash_write_range_loop_s ; NO - continue loop + bra ext_flash_write_range_seq_loop ; NO - loop return ; YES - done -ext_flash_write_range_block: ; block write - movff POSTINC1,ext_flash_rw ; read first byte from memory - rcall ext_flash_write_block_start ; write first byte to FLASH + ; block write +ext_flash_write_range_block: + movf POSTINC1,W ; copy first byte from memory to WREG + rcall ext_flash_write_block_start ; copy first byte from WREG to FLASH bra ext_flash_write_range_loop_start; jump into loop -ext_flash_write_range_loop_b: - movff POSTINC1,ext_flash_rw ; read next byte from memory - rcall ext_flash_write_block ; write next byte to FLASH +ext_flash_write_range_block_loop: + movf POSTINC1,W ; copy next byte from memory to WREG + rcall ext_flash_write_block ; copy next byte from WREG to FLASH ext_flash_write_range_loop_start: decfsz eeprom_loop,F ; decrement loop counter, all done? - bra ext_flash_write_range_loop_b ; NO - continue loop - bra ext_flash_write_block_stop ; YES - end writing to flash (and return) - -; ---------------------------------------------------------------------------- - -; global write_byte_ext_flash_plus_header -; write_byte_ext_flash_plus_header: -; movwf ext_flash_rw ; store byte to write -; ; test if write is done at first byte of 4kB block, if yes delete 4kB block first -; tstfsz ext_flash_address+0 ; at 0x....00 ? -; bra write_byte_ext_flash_plus_h1 ; NO - normal write -; movf ext_flash_address+1,W ; YES - get high byte -; andlw 0x0F ; - mask lower nibble -; tstfsz WREG ; - at 0x..0...? -; bra write_byte_ext_flash_plus_h1 ; NO - normal write -; rcall ext_flash_erase_4kB ; YES - at beginning of 4kB block -> erases 4kB sector @ext_flash_address:3 -;write_byte_ext_flash_plus_h1: -; rcall ext_flash_byte_write ; write the byte in ext_flash_rw -; bra incf_ext_flash_address_p1_0x40 ; increase address with wrap-around at 0x400000 and return + bra ext_flash_write_range_block_loop; NO - loop + rcall ext_flash_write_block_stop ; YES - initiate FLASH write + clrf ext_flash_address+0 ; - advance address to start of next block + infsnz ext_flash_address+1,F ; - ... + incf ext_flash_address+2,F ; - ... + return ; - done - global write_byte_ext_flash_plus_prof -write_byte_ext_flash_plus_prof: +;----------------------------------------------------------------------------- +; write a Byte with wrap-around at 0x200000, +; erase on entering new 4kB Block, +; increment Dive Length Counter +; + global ext_flash_write_byte_0x20_incdc +ext_flash_write_byte_0x20_incdc: movwf ext_flash_rw ; store byte to write incf ext_flash_length_counter+0,F ; increase dive length counter movlw .0 ; ... addwfc ext_flash_length_counter+1,F ; ... addwfc ext_flash_length_counter+2,F ; ... - bra write_byte_ext_flash_plus_nocnt1; continue with checking for begin of new page + bra write_byte_ext_flash_plus_nocnt1; continue with checking for begin of new block - global write_byte_ext_flash_plus_nocnt -write_byte_ext_flash_plus_nocnt: +;----------------------------------------------------------------------------- +; write a Byte with wrap-around at 0x200000, +; erase on entering new 4kB Block +; + global ext_flash_write_byte_0x20 +ext_flash_write_byte_0x20: movwf ext_flash_rw ; store byte to write -write_byte_ext_flash_plus_nocnt1: ; test if write is done at first byte of 4kB block, if yes delete 4kB block first - tstfsz ext_flash_address+0 ; at 0x....00? - bra write_byte_ext_flash_plus_nodel1; NO - execute write - movf ext_flash_address+1,W ; YES - mask lower nibble - andlw 0x0F ; - ... - tstfsz WREG ; - at 0x..0...? - bra write_byte_ext_flash_plus_nodel1; NO - execute write - ; YES - at beginning of 4kB block -> erase first! - rcall ext_flash_erase_4kB ; - erases 4kB sector @ext_flash_address:3 +write_byte_ext_flash_plus_nocnt1: + ; check if at 1st byte of a 4kB block, + ; if yes the block needs to be erased + ; before new data can be written to it + tstfsz ext_flash_address+0 ; is the low byte of the address = 0x00 ? + bra write_byte_ext_flash_plus_nodel1; NO - not at 1st byte, can execute write + movf ext_flash_address+1,W ; YES - get high byte of the address + andlw 0x0F ; - keep only the lower nibble + tstfsz WREG ; - is the lower nibble = 0x0 ? + bra write_byte_ext_flash_plus_nodel1; NO - not at 1st byte, can execute write + rcall ext_flash_erase_4kB ; YES - at 1st byte, erase 4kB block bra write_byte_ext_flash_plus_nodel1; - execute write - global write_byte_ext_flash_plus_nodel -write_byte_ext_flash_plus_nodel: +;----------------------------------------------------------------------------- +; write a Byte with wrap-around at 0x200000 +; NO erase on entering new 4kB Block +; + global ext_flash_write_byte_0x20_nodel +ext_flash_write_byte_0x20_nodel: movwf ext_flash_rw ; store byte to write write_byte_ext_flash_plus_nodel1: - rcall ext_flash_byte_write ; write the byte in ext_flash_rw - bra incf_ext_flash_address_p1_0x20 ; increase address with wrap-around at 0x200000 and return + bsf flash_wait ; wait for flash write to complete + rcall ext_flash_byte_write_common_F ; write the byte in ext_flash_rw + bra ext_flash_inc_address_0x20_p1 ; increase address with wrap-around at 0x200000 and return - global write_byte_ext_flash_plus_comms ; write from WREG without wait, ~86us fixed delay due to 115200 Baud, use with caution! -write_byte_ext_flash_plus_comms: - movwf ext_flash_rw ; store byte to write +;----------------------------------------------------------------------------- +; write a Byte without Wait (used by comm mode) +; +; time budget for flash to complete a write is ~86 us at 115200 Baud on serial +; + global ext_flash_write_byte_0x40_nowait +ext_flash_write_byte_0x40_nowait: bcf flash_wait ; do not wait on flash write to complete - rcall ext_flash_byte_write_common ; write the byte in ext_flash_rw - bra incf_ext_flash_address_p1_0x40 ; increase address with wrap-around at 0x400000 and return + rcall ext_flash_byte_write_common_W ; write the byte in WREG + bra ext_flash_inc_address_0x40_p1 ; increase address with wrap-around at 0x400000 and return -ext_flash_byte_write: - bsf flash_wait ; wait for flash write to complete -ext_flash_byte_write_common: +;----------------------------------------------------------------------------- +; internal common Write Functions W: WREG -> FLASH(ext_flash_address) +; F: ext_flash_rw -> FLASH(ext_flash_address) +; +ext_flash_byte_write_common_W: + movwf ext_flash_rw ; copy byte to write from WREG to ext_flash_rw +ext_flash_byte_write_common_F: bsf flash_ncs ; set CS=1 movlw 0x06 ; set up WREN command rcall shift_spi ; execute WREN command bsf flash_ncs ; set CS=1 - movlw 0x02 ; set up write (PP, Page-Program) command + movlw 0x02 ; prepare write (PP, Page-Program) command rcall shift_spi ; execute write rcall ext_flash_set_address ; write 24 bit address ext_flash_address:3 via SPI - movf ext_flash_rw,W ; get byte to write + movf ext_flash_rw,W ; get back byte to write rcall shift_spi ; write the byte btfsc flash_wait ; shall wait on flash write to complete? bra ext_flash_wait_write ; YES - wait for completion (and return) bsf flash_ncs ; NO - set CS=1 return ; - done -; ---------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; switch off Write-Protection +; global ext_flash_disable_protection ; disable write protection ext_flash_disable_protection: ; unlock old memory - bsf flash_ncs ; CS=1 - movlw 0x50 ; EWSR command - rcall shift_spi - bsf flash_ncs ; CS=1 - movlw 0x01 ; WRSR command - rcall shift_spi - movlw b'00000000' ; new status - rcall shift_spi - bsf flash_ncs ; CS=1 + bsf flash_ncs ; set CS=1 + movlw 0x50 ; prepare EWSR command + rcall shift_spi ; execute EWSR command + bsf flash_ncs ; set CS=1 + movlw 0x01 ; prepare WRSR command + rcall shift_spi ; execute WRSR command + movlw b'00000000' ; prepare new status + rcall shift_spi ; set new status + ; unlock new memory - movlw 0x06 ; WREN command - rcall shift_spi - bsf flash_ncs ; CS=1 - movlw 0x98 ; ULBPR command - rcall shift_spi - bsf flash_ncs ; CS=1 - movlw 0x06 ; WREN command - rcall shift_spi - bsf flash_ncs ; CS=1 - movlw 0x42 ; WBPR command - rcall shift_spi + bsf flash_ncs ; set CS=1 + movlw 0x06 ; prepare WREN command + rcall shift_spi ; execute WREN command + bsf flash_ncs ; set CS=1 + movlw 0x98 ; prepare ULBPR command + rcall shift_spi ; execute ULBPR command + bsf flash_ncs ; set CS=1 + movlw 0x06 ; prepare WREN command + rcall shift_spi ; execute WREN command + bsf flash_ncs ; set CS=1 + movlw 0x42 ; prepare WBPR command + rcall shift_spi ; execute WBPR command + movlw .18 ; 18 bytes to do movwf lo ; initialize loop counter ext_flash_disable_prot_loop: movlw 0x00 ; prepare writing a zero - rcall shift_spi ; execute write + rcall shift_spi ; write a zero decfsz lo,F ; all bytes done? bra ext_flash_disable_prot_loop ; NO - loop bsf flash_ncs ; YES - set CS=1 return ; - done +;----------------------------------------------------------------------------- +; switch on Write-Protection +; global ext_flash_enable_protection ext_flash_enable_protection: ; lock old memory @@ -324,69 +385,104 @@ rcall shift_spi ; execute WRSR command movlw b'00011100' ; prepare write protection on rcall shift_spi ; execute write protection on - bsf flash_ncs ; set CS=1 + ; lock new memory -; movlw 0x06 ; WREN command -; rcall shift_spi -; bsf flash_ncs ; CS=1 -; movlw 0x8D ; LBPR command -; rcall shift_spi + bsf flash_ncs ; set CS=1 +; movlw 0x06 ; prepare WREN command +; rcall shift_spi ; execute WREN command +; bsf flash_ncs ; set CS=1 +; movlw 0x8D ; prepare LBPR command +; rcall shift_spi ; execute LBPR command ; bsf flash_ncs ; set CS=1 movlw 0x06 ; prepare WREN command rcall shift_spi ; execute WREN command bsf flash_ncs ; set CS=1 movlw 0x42 ; prepare WBPR command rcall shift_spi ; execute WBPR command + movlw .18 ; 18 bytes to do movwf lo ; initialize loop counter ext_flash_enable_prot_loop: movlw 0xFF ; prepare writing 0xFF - rcall shift_spi ; execute write + rcall shift_spi ; write a zero decfsz lo,F ; all bytes done? bra ext_flash_enable_prot_loop ; NO - loop bsf flash_ncs ; YES - set CS=1 return ; - done -; ---------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; erase complete Logbook +; global erase_complete_logbook erase_complete_logbook: - ; clear logbook data in EPROM - CLRT mpr ; prepare a 3 byte zero integer - EEPROM_II_WRITE mpr,eeprom_num_dives ; reset total number of dives - EEPROM_TT_WRITE mpr,eeprom_log_pointer ; reset pointer to begin of log data - ; erase logbook data in FLASH (0x000000 -> 0x2FFFFF -> 3 MByte -> 3145728 Bytes) - bsf flash_ncs ; CS=1 - clrf ext_flash_address+0 ; set address to 0x000000 - clrf ext_flash_address+1 ; ... - clrf ext_flash_address+2 ; ... - clrf ext_flash_rw ; write zeros -ext_flash_erase_logbook_loop: ; 256 * 12 kB = 3.145.728 bytes to do - rcall ext_flash_erase_4kB ; erase 4kB block - rcall ext_flash_add_4kB ; increase ext_flash_address:3 by 4kB - rcall ext_flash_erase_4kB ; erase 4kB block - rcall ext_flash_add_4kB ; increase ext_flash_address:3 by 4kB - rcall ext_flash_erase_4kB ; erase 4kB block - rcall ext_flash_add_4kB ; increase ext_flash_address:3 by 4kB - decfsz ext_flash_rw,F ; decrement loop counter, done? - bra ext_flash_erase_logbook_loop ; NO - loop - return ; YES - done + ; set address to 0x000000 / prepare a 3 byte zero integer + CLRT ext_flash_address + + ; clear logbook data in EPROM by writing all zeros + EEPROM_II_WRITE ext_flash_address,eeprom_num_dives ; reset the total number of dives + EEPROM_TT_WRITE ext_flash_address,eeprom_log_pointer ; reset pointer to begin of profile data + + ; erase logbook data in FLASH from 0x000000 - 0x2FFFFF = 3 MByte = 3 * 256 blocks * 4 kB/block + + clrf WREG ; erase 256 blocks per call + rcall ext_flash_erase_range ; erase 1st bunch of 256 blocks + rcall ext_flash_erase_range_loop ; erase 2nd bunch of 256 blocks + rcall ext_flash_erase_range_loop ; erase 3rd bunch of 256 blocks + return ; done - global ext_flash_erase_4kB ; erase a 4kB sector +;----------------------------------------------------------------------------- +; erase a Number of 4kB Blocks +; + global ext_flash_erase_range +ext_flash_erase_range: + movwf eeprom_loop ; initialize loop counter +ext_flash_erase_range_loop: + rcall ext_flash_erase_4kB ; erase one block + rcall ext_flash_inc_address_4kB ; increase start address by 0x1000 (4kB) + btfsc ext_flash_address+2,6 ; reached 0x400000 ? + return ; YES - reached end of address range, done anyhow + decfsz eeprom_loop,F ; NO - decrement number of blocks to do, all blocks done? + bra ext_flash_erase_range_loop ; NO - loop + return ; YES - done, back to command loop + + +;----------------------------------------------------------------------------- +; erase one 4kB Block +; + global ext_flash_erase_4kB ext_flash_erase_4kB: bsf flash_ncs ; set CS=1 movlw 0x06 ; prepare WREN command rcall shift_spi ; execute WREN command bsf flash_ncs ; set CS=1 - movlw 0x20 ; prepare sector erase command - rcall shift_spi ; execute sector erase command + movlw 0x20 ; prepare block erase command + rcall shift_spi ; execute block erase command rcall ext_flash_set_address ; write 24 bit address ext_flash_address:3 via SPI bra ext_flash_wait_write ; wait for write to complete and return -; ---------------------------------------------------------------------------- -; send address +;----------------------------------------------------------------------------- +; read JEDEC IDs +; + global ext_flash_read_jedec +ext_flash_read_jedec: + movlw 0x9F ; prepare JEDEC read command + rcall shift_spi ; execute JEDEC read command + rcall shift_spi ; shift the SPI to read the manufacturer ID into WREG + movwf lo ; store the manufacturer ID in lo + rcall shift_spi ; shift the SPI to read the device type ID into WREG + movwf hi ; store the device type ID in hi + rcall shift_spi ; shift the SPI to read the device model ID into WREG + movwf up ; store the device model ID in up + bsf flash_ncs ; set CS=1 + return ; done + + +;----------------------------------------------------------------------------- +; low level Functions - send Address +; ext_flash_set_address: movf ext_flash_address+2,W ; write 24 bit address ext_flash_address:3 via SPI rcall shift_spi ; ... @@ -395,7 +491,10 @@ movf ext_flash_address+0,W ; ... bra shift_spi ; ... and return -; wait on write operation to complete + +;----------------------------------------------------------------------------- +; low level Functions - wait for Completion of a Write Operation +; ext_flash_wait_write: bsf flash_ncs ; set CS=1 ; WAITMS d'1' ; TBE/TSE=25ms... @@ -407,16 +506,14 @@ bra ext_flash_wait_write ; YES - loop waiting return ; NO - done -; add 0x001000 to flash address -ext_flash_add_4kB: - movlw 0x10 ; add 0x10 to high byte - addwf ext_flash_address+1,F ; ... - movlw d'0' ; propagate carry to upper byte - addwfc ext_flash_address+2,F ; ... - return ; done -; shift the SPI bus for a combined write/read: WREG --->\ /---> WREG -shift_spi: ; flash chip +;----------------------------------------------------------------------------- +; low level functions - shift the SPI Bus for a combined Write/Read +; +; WREG --> write --->\ /---> read --> WREG +; flash chip +; +shift_spi: bcf flash_ncs ; set CS=0 shift_spi_loop_1: bcf SSP2STAT,WCOL ; clear flag @@ -429,4 +526,100 @@ movf SSP2BUF,W ; YES - copy received data to WREG return ; - done + + IFDEF _firmware_recovery + +;----------------------------------------------------------------------------- +; copy active Firmware to Backup Storage +; + global copy_fw_active_to_backup +copy_fw_active_to_backup: + ; erase FLASH for recovery firmware (120 kByte = 30 * 4 kByte) + rcall ext_flash_to_recovery_fw ; set ext_flash_address to 0x3C0000 + movlw .30 ; 30 blocks to do + rcall ext_flash_erase_range ; erase #WREG 4kB blocks starting at ext_flash_address + + ; copy firmware (120 kByte = 2 x 240 x 256 byte) + rcall ext_flash_to_productive_fw ; set ext_flash_address to 0x3E0000 + clrf hi ; flag in 1st round +copy_fw_active_to_backup_loop1: + movlw .240 ; load loop counter + movwf lo ; ... +copy_fw_active_to_backup_loop2: + ; read active firmware + bsf ext_flash_address+2,1 ; switch to productive firmware + lfsr FSR1,buffer ; set start address in memory + movlw low(.256) ; set size of range to read + rcall ext_flash_read_range ; execute range-read (ext_flash_address NOT incremented) + ; write to backup storage + bcf ext_flash_address+2,1 ; switch to backup storage + lfsr FSR1,buffer ; set start address in memory + movlw low(.256) ; set size of range to write + rcall ext_flash_write_range ; execute range-write (ext_flash_address GETS incremented) + ; operate loop + decfsz lo,F ; decrement loop counter, done? + bra copy_fw_active_to_backup_loop2 ; NO - continue copying + tstfsz hi ; YES - 2nd round finished? + return ; YES - done + setf hi ; NO - flag in 2nd round now + bra copy_fw_active_to_backup_loop1 ; - start 2nd round + + +;----------------------------------------------------------------------------- +; copy Backup-Firmware to Update Storage +; + global copy_fw_backup_to_active +copy_fw_backup_to_active: + ; erase FLASH for productive firmware (120 kByte = 30 * 4 kByte) + rcall ext_flash_to_productive_fw ; set ext_flash_address to 0x3E0000 + movlw .30 ; 30 blocks to do + rcall ext_flash_erase_range ; erase #WREG 4kB blocks starting at ext_flash_address + + ; copy firmware (120 kByte = 2 x 240 x 256 byte) + rcall ext_flash_to_recovery_fw ; set ext_flash_address to 0x3C0000 + clrf hi ; flag in 1st round +copy_fw_backup_to_active_loop1: + movlw .240 ; load loop counter + movwf lo ; ... +copy_fw_backup_to_active_loop2: + ; read backup firmware + bcf ext_flash_address+2,1 ; switch to backup firmware + lfsr FSR1,buffer ; set start address in memory + movlw low(.256) ; set size of range to read + rcall ext_flash_read_range ; execute range-read (ext_flash_address NOT incremented) + ; write to update storage + bsf ext_flash_address+2,1 ; switch to update storage + lfsr FSR1,buffer ; set start address in memory + movlw low(.256) ; set size of range to write + rcall ext_flash_write_range ; execute range-write (ext_flash_address GETS incremented) + ; operate loop + decfsz lo,F ; decrement loop counter, done? + bra copy_fw_backup_to_active_loop2 ; NO - continue copying + tstfsz hi ; YES - 2nd round finished? + return ; YES - done + setf hi ; NO - flag in 2nd round now + bra copy_fw_backup_to_active_loop1 ; - start 2nd round + + +;----------------------------------------------------------------------------- +; Helper Functions - point ext_flash_address to active / backup firmware storage +; +ext_flash_to_recovery_fw + movlw 0x3C ; 0x3C| + bra ext_flash_common + +ext_flash_to_productive_fw: + movlw 0x3E ; 0x3E| + ;bra ext_flash_common + +ext_flash_common: + movwf ext_flash_address+2 ; ....| + clrf ext_flash_address+1 ; ....|00| + clrf ext_flash_address+0 ; .......|00 + return + + ENDIF + +;----------------------------------------------------------------------------- + END