Files
2016-10-07 23:44:50 +02:00

226 lines
8.0 KiB
ArmAsm

#include <avr/io.h>
#include "Memory.h"
#define NVM_CMD_NO_OPERATION_gc (0x00<<0)
#define NVM_CMD_READ_USER_SIG_ROW_gc (0x01<<0)
#define NVM_CMD_READ_CALIB_ROW_gc (0x02<<0)
#define NVM_CMD_READ_EEPROM_gc (0x06<<0)
#define NVM_CMD_READ_FUSES_gc (0x07<<0)
#define NVM_CMD_WRITE_LOCK_BITS_gc (0x08<<0)
#define NVM_CMD_ERASE_USER_SIG_ROW_gc (0x18<<0)
#define NVM_CMD_WRITE_USER_SIG_ROW_gc (0x1A<<0)
#define NVM_CMD_ERASE_APP_gc (0x20<<0)
#define NVM_CMD_ERASE_APP_PAGE_gc (0x22<<0)
#define NVM_CMD_LOAD_FLASH_BUFFER_gc (0x23<<0)
#define NVM_CMD_WRITE_APP_PAGE_gc (0x24<<0)
#define NVM_CMD_ERASE_WRITE_APP_PAGE_gc (0x25<<0)
#define NVM_CMD_ERASE_FLASH_BUFFER_gc (0x26<<0)
#define NVM_CMD_ERASE_BOOT_PAGE_gc (0x2A<<0)
#define NVM_CMD_WRITE_BOOT_PAGE_gc (0x2C<<0)
#define NVM_CMD_ERASE_WRITE_BOOT_PAGE_gc (0x2D<<0)
#define NVM_CMD_ERASE_EEPROM_gc (0x30<<0)
#define NVM_CMD_ERASE_EEPROM_PAGE_gc (0x32<<0)
#define NVM_CMD_LOAD_EEPROM_BUFFER_gc (0x33<<0)
#define NVM_CMD_WRITE_EEPROM_PAGE_gc (0x34<<0)
#define NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc (0x35<<0)
#define NVM_CMD_ERASE_EEPROM_BUFFER_gc (0x36<<0)
#define NVM_CMD_APP_CRC_gc (0x38<<0)
#define NVM_CMD_BOOT_CRC_gc (0x39<<0)
#define NVM_CMD_FLASH_RANGE_CRC_gc (0x3A<<0)
#define CCP_SPM_gc (0x9D<<0)
#define CCP_IOREG_gc (0xD8<<0)
/* FlashCommonSPM needs to reside in boot loader section */
#define SPM_HELPER_ADDR_REF (BOOT_SECTION_START + BOOT_SECTION_SIZE - 32)
#ifdef SPM_HELPER_ADDR
/* If enabled by makefile, we can check the hardcoded address from makefile
* against avr/io.h and generate an error on mismatch */
#if ((SPM_HELPER_ADDR - SPM_HELPER_ADDR_REF) != 0)
#error SPM helper function addresses from Makefile and avr/io.h do not match!
#endif
#endif
/* The following assembly code is taken from Atmels sp_driver.S in AVR1316 */
; This routine reads a word from flash given by the address in
; R25:R24:R23:R22.
;
; Input:
; R25:R24:R23:R22.
;
; Returns:
; R25:R24 - Read word.
.section .text
.global FlashReadWord
FlashReadWord:
in r19, RAMPZ ; Save RAMPZ.
out RAMPZ, r24 ; Load RAMPZ with the MSB of the address.
movw ZL, r22 ; Move the low bytes to the Z pointer
elpm r24, Z+ ; Extended load byte from address pointed to by Z.
elpm r25, Z ; Extended load byte from address pointed to by Z.
out RAMPZ, r19 ; Restore RAMPZ register.
ret
; This routine erases the page at address R25:R24:R23:R22 in the application
; section. The address can point anywhere inside the page.
;
; Input:
; R25:R24:R23:R22 - Byte address into Flash page.
;
; Returns:
; Nothing.
.section .text
.global FlashEraseApplicationPage
FlashEraseApplicationPage:
in r19, RAMPZ ; Save RAMPZ, which is restored in FlashCommonSPM.
out RAMPZ, r24 ; Load RAMPZ with the MSB of the address.
movw r24, r22 ; Move low bytes for ZH:ZL to R25:R24
ldi r20, NVM_CMD_ERASE_APP_PAGE_gc ; Prepare NVM command in R20.
jmp FlashCommonSPM ; Jump to common SPM code.
; This routine writes the word from R23:R22 into the Flash page buffer at
; address R25:R24.
;
; Input:
; R25:R24 - Byte address into Flash page.
; R23:R22 - Word to write.
;
; Returns:
; Nothing.
.section .text
.global FlashLoadFlashWord
FlashLoadFlashWord:
in r19, RAMPZ ; Save RAMPZ, which is restored in FlashCommonSPM.
movw r0, r22 ; Prepare flash word in R1:R0.
ldi r20, NVM_CMD_LOAD_FLASH_BUFFER_gc ; Prepare NVM command in R20.
jmp FlashCommonSPM ; Jump to common SPM code.
; This routine erases first and then writes the page buffer to the
; Flash page at address R25:R24:R23:R22 in the application section. The address
; can point anywhere inside the page.
;
; Input:
; R25:R24:R23:R22 - Byte address into Flash page.
;
; Returns:
; Nothing.
.section .text
.global FlashEraseWriteApplicationPage
FlashEraseWriteApplicationPage:
in r19, RAMPZ ; Save RAMPZ, which is restored in FlashCommonSPM.
out RAMPZ, r24 ; Load RAMPZ with the MSB of the address.
movw r24, r22 ; Move low bytes of address to ZH:ZL from R23:R22
ldi r20, NVM_CMD_ERASE_WRITE_APP_PAGE_gc ; Prepare NVM command in R20.
jmp FlashCommonSPM ; Jump to common SPM code.
; This routine flushes the Flash page buffer.
;
; Input:
; Nothing.
;
; Returns:
; Nothing.
.section .text
.global FlashEraseFlashBuffer
FlashEraseFlashBuffer:
in r19, RAMPZ ; Save RAMPZ, which is restored in FlashCommonSPM.
ldi r20, NVM_CMD_ERASE_FLASH_BUFFER_gc ; Prepare NVM command in R20.
;jmp FlashCommonSPM ; Jump to common SPM code.
jmp FlashCommonCMD
; This routine wait for the SPM to finish and clears the command register.
;
; Note that this routine is blocking, and will halt any execution until the SPM
; is finished.
;
; Input:
; Nothing.
;
; Returns:
; Nothing.
.section .text
.global FlashWaitForSPM
FlashWaitForSPM:
lds r18, NVM_STATUS ; Load the NVM Status register.
sbrc r18, NVM_NVMBUSY_bp ; Check if bit is cleared.
rjmp FlashWaitForSPM ; Repeat check if bit is not cleared.
clr r18
sts NVM_CMD, r18 ; Clear up command register to NO_OPERATION.
ret
; This routine is called by several other routines, and contains common code
; for executing an NVM command, including the return statement itself.
;
; If the operation (NVM command) requires the NVM Address registers to be
; prepared, this must be done before jumping to this routine.
;
; Note that R25:R24:R23:R22 is used for returning results, even if the
; C-domain calling function only expects a single byte or even void.
;
; Input:
; R20 - NVM Command code.
;
; Returns:
; R25:R24:R23:R22 - 32-bit result from NVM operation.
.section .text
FlashCommonCMD:
sts NVM_CMD, r20 ; Load command into NVM Command register.
ldi r18, CCP_IOREG_gc ; Prepare Protect IO-register signature in R18.
ldi r19, NVM_CMDEX_bm ; Prepare bitmask for setting NVM Command Execute bit into R19.
sts CCP, r18 ; Enable IO-register operation (this disables interrupts for 4 cycles).
sts NVM_CTRLA, r19 ; Load bitmask into NVM Control Register A, which executes the command.
lds r22, NVM_DATA0 ; Load NVM Data Register 0 into R22.
lds r23, NVM_DATA1 ; Load NVM Data Register 1 into R23.
lds r24, NVM_DATA2 ; Load NVM Data Register 2 into R24.
clr r25 ; Clear R25 in order to return a clean 32-bit value.
ret
; This routine is called by several other routines, and contains common code
; for executing an LPM command, including the return statement itself.
;
; Note that R24 is used for returning results, even if the
; C-domain calling function expects a void.
;
; Input:
; R25:R24 - Low bytes of Z pointer.
; R20 - NVM Command code.
;
; Returns:
; R24 - Result from LPM operation.
.section .text
FlashCommonLPM:
movw ZL, r24 ; Load index into Z.
sts NVM_CMD, r20 ; Load prepared command into NVM Command register.
lpm r24,Z
ret
; This routine is called by several other routines, and contains common code
; for executing an SPM command, including the return statement itself.
;
; If the operation (SPM command) requires the R1:R0 registers to be
; prepared, this must be done before jumping to this routine.
;
; Input:
; R1:R0 - Optional input to SPM command.
; R25:R24 - Low bytes of Z pointer.
; R20 - NVM Command code.
;
; Returns:
; Nothing.
.section .spmhelper
FlashCommonSPM:
movw ZL, r24 ; Load R25:R24 into Z.
sts NVM_CMD, r20 ; Load prepared command into NVM Command register.
ldi r18, CCP_SPM_gc ; Prepare Protect SPM signature in R18
sts CCP, r18 ; Enable SPM operation (this disables interrupts for 4 cycles).
spm ; Self-program.
clr r1 ; Clear R1 for GCC _zero_reg_ to function properly.
out RAMPZ, r19 ; Restore RAMPZ register.
ret
/* Reserve memory for data */
.section .flashdata
.align 1
.skip MEMORY_SIZE, MEMORY_INIT_VALUE