Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

FreescaleIAP/IAP.s

Committer:
mjr
Date:
2017-02-03
Revision:
76:7f5912b6340e
Parent:
60:f38da020aa13
Child:
77:0b96f6867312

File content as of revision 76:7f5912b6340e:

; FreescaleIAP assembly functions
;
; Put all code here in READWRITE memory, to ensure that it goes in RAM 
; rather than flash.  
    AREA iapexec_asm_code, CODE, READWRITE
    
;---------------------------------------------------------------------------
; iapEraseSector(FTFA_Type *FTFA, uint32_t address)
;   R0 = FTFA pointer
;   R1 = starting address

    EXPORT iapEraseSector
iapEraseSector
    ; save registers
    STMFD   R13!,{R1,R4,LR}
    
    ; Ensure that no interrupts occur while we're erasing.  This is
    ; vitally important, because the flash controller doesn't allow
    ; anyone to read from flash while an erase is in progress.  Most
    ; of the program code is in flash, which means that any interrupt
    ; would invoke flash code, causing the CPU to fetch from flash,
    ; violating the no-read-during-erase rule.  The CPU instruction
    ; fetch would fail, causing the CPU to lock up.
    CPSID I              ; interrupts off
    DMB                  ; data memory barrier
    ISB                  ; instruction synchronization barrier
    
    ; wait for any previous command to complete
    BL      iapWait
    
    ; clear any errors
    BL      iapClearErrors
    
    ; set up the command parameters
    MOVS    R4,#0
    STRB    R4,[R0,#1]   ; FTFA->FCNFG <- 0
    MOVS    R4,#9        ; command = erase sector (9)
    STRB    R4,[R0,#7]   ; FTFA->FCCOB0 <- command
    
    STRB    R1,[R0,#4]   ; FTFA->FCCOB3 <- address bits 16-23
    
    MOVS    R1,R1,LSR #8 ; address >>= 8
    STRB    R1,[R0,#5]   ; FTFA->FCCOB2 <- address bits 8-15
    
    MOVS    R1,R1,LSR #8 ; address >>= 8
    STRB    R1,[R0,#6]   ; FTFA->FCCOB1 <- address bits 0-7
    
    ; execute and wait for completion
    BL      iapExec
    BL      iapWait
    
    ; restore interrupts
    CPSIE I

    ; pop registers and return
    LDMFD   R13!,{R1,R4,PC}    

;---------------------------------------------------------------------------
; iapProgramBlock(TFA_Type *ftfa, uint32_t address, const void *src, uint32_t length)
;   R0 = FTFA pointer
;   R1 = flash address
;   R2 = source data pointer
;   R3 = data length in bytes

    EXPORT iapProgramBlock
iapProgramBlock
    ; save registers
    STMFD   R13!, {R1,R2,R3,R4,LR}
    
    ; Turn off interrupts while we're working.  Flash reading
    ; while writing doesn't seem to be forbidden the way it is
    ; while erasing (see above), but even so, each longword
    ; transfer requires writing to 10 separate registers, so
    ; there's a lot of static state involved - we don't want
    ; any other code sneaking in and changing anything on us.
    CPSID I              ; interrupts off
    DMB                  ; data memory barrier
    ISB                  ; instruction synchronization barrier
    
    ; wait for any previous command to complete
    BL      iapWait
    
    ; iterate over the data
LpLoop
    CMPS    R3,#3        ; at least one longword left (>= 4 bytes)?
    BLS     LpDone       ; no, done
    
    ; clear any errors from the previous command
    BL      iapClearErrors
    
    ; set up the command parameters
    MOVS    R4,#0
    STRB    R4,[R0,#1]   ; FTFA->FCNFG <- 0
    MOVS    R4,#6        ; command = program longword (6)
    STRB    R4,[R0,#7]   ; FTFA->FCCOB0 <- command
    
    MOVS    R4,R1        ; R4 <- current address
    STRB    R4,[R0,#4]   ; FTFA->FCCOB3 <- address bits 16-23
    
    MOVS    R4,R4,LSR #8 ; address >>= 8
    STRB    R4,[R0,#5]   ; FTFA->FCCOB2 <- address bits 8-15

    MOVS    R4,R4,LSR #8 ; address >>= 8    
    STRB    R4,[R0,#6]   ; FTFA->FCCOB1 <- address bits 0-7
    
    LDRB    R4,[R2]      ; R4 <- data[0]
    STRB    R4,[R0,#8]   ; FTFA->FCCOB7 <- data[0]
    
    LDRB    R4,[R2,#1]   ; R4 <- data[1]
    STRB    R4,[R0,#9]   ; FTFA->FCCOB6 <- data[1]
    
    LDRB    R4,[R2,#2]   ; R4 <- data[2]
    STRB    R4,[R0,#0xA] ; FTFA->FCCOB5 <- data[2]
    
    LDRB    R4,[R2,#3]   ; R4 <- data[3]
    STRB    R4,[R0,#0xB] ; FTBA->FCCOB4 <- data[3]
    
    ; execute the command
    BL      iapExec
    
    ; advance to the next longword
    ADDS    R1,R1,#4     ; flash address += 4
    ADDS    R2,R2,#4     ; source data pointer += 4
    SUBS    R3,R3,#4     ; data length -= 4
    B       LpLoop       ; back for the next iteration
    
LpDone    
    ; restore interrupts
    CPSIE I
    
    ; pop registers and return
    LDMFD   R13!, {R1,R2,R3,R4,PC}    

    
;---------------------------------------------------------------------------
; iapClearErrors(FTFA_Type *FTFA) - clear errors from previous command
;   R0 = FTFA pointer

iapClearErrors
    ; save registers
    STMFD   R13!, {R2,R3,LR}

    LDRB    R2, [R0]    ; R2 <- FTFA->FSTAT
    MOVS    R3, #0x30   ; FPVIOL (0x10) | ACCERR (0x20)
    ANDS    R2, R2, R3  ; R2 &= error bits
    BEQ     Lc0         ; if all zeros, no need to reset anything
    STRB    R2, [R0]    ; write the 1 bits back to clear the error status
Lc0
    ; restore registers and return
    LDMFD   R13!, {R2,R3,PC}    


;---------------------------------------------------------------------------
; iapWait(FTFA_Type *FTFA) - wait for command to complete
;   R0 = FTFA pointer

iapWait
    ; save registers
    STMFD   R13!, {R1,R2,LR}

    ; the CCIF bit is SET when the command completes
Lw0
    LDRB    R1, [R0]     ; R1 <- FTFA->FSTAT
    MOVS    R2, #0x80    ; CCIF (0x80)
    TSTS    R1, R2       ; test R1 & CCIF
    BEQ     Lw0          ; if zero, the command is still running

LwDone
    ; pop registers and return
    LDMFD   R13!, {R1,R2,PC}    


;---------------------------------------------------------------------------
; iapExec(FTFA_Type *FTFA)
;   R0 = FTFA pointer

iapExec
    ; save registers
    STMFD   R13!, {R1,LR}
        
    ; write the CCIF bit to launch the command
    MOVS    R1, #0x80    ; CCIF (0x80)
    STRB    R1, [R0]     ; FTFA->FSTAT = CCIF
    
    ; wait until command completed
    BL      iapWait

    ; pop registers and return
    LDMFD   R13!, {R1,PC}    
    
    END