
  THUMB
  REQUIRE8
  PRESERVE8

  AREA |.text|, CODE, READONLY, ALIGN=2

  ; Reference to the FailSafe routine to be executed in case of non-recoverable
  ; failure
  IMPORT FailSafePOR

    ; C variables for control flow monitoring
  IMPORT CtrlFlowCnt
  IMPORT CtrlFlowCntInv

;*******************************************************************************
; Function Name  : IEC60730_CPURegister_StartUp
; Description    : Full Cortex-M0 CPU test at start-up
;                  Note: when possible, BRANCH are 16-bit only (depending on
;                  relative offset to final BL instruction)
; Input          : None.
; Output         : Branch directly to a Fail Safe routine in case of failure
; Return         : TEST_SUCCESSFULL (=1)
; WARNING        : all registers destroyed when exiting this function (including
;                  preserved registers R4 to R11) and excluding stack point R13)
;*******************************************************************************/
conAA       DCD     0xAAAAAAAA
con55       DCD     0x55555555
con80       DCD     0x80000000
conA8       DCD     0xAAAAAAA8
con54       DCD     0x55555554

  EXPORT conAA
  EXPORT con55

IEC60730_CPURegister_StartUp PROC
    EXPORT IEC60730_CPURegister_StartUp

    PUSH {R4-R6}              ; Safe critical registers

    MOVS R0, #0x00            ;
    UXTB R0,R0
    ADDS R0,#0                ; Set Z(ero) Flag
    BNE CPUStartUpTestFail    ; Fails if Z clear
    BMI CPUStartUpTestFail    ; Fails if N is set
    SUBS R0,#1                ; Set N(egative) Flag
    BPL CPUStartUpTestFail           ; Fails if N clear
    ADDS R0,#2                ; Set C(arry) Flag and do not set Z
    BCC CPUStartUpTestFail    ; Fails if C clear
    BEQ CPUStartUpTestFail    ; Fails if Z is set
    BMI CPUStartUpTestFail    ; Fails if N is set

    LDR R0,=con80             ; Prepares Overflow test
    LDR R0,[R0]
    ADDS R0, R0, R0           ; Set V(overflow) Flag
    BVC CPUStartUpTestFail    ; Fails if V clear

    ; This is for control flow test (ENTRY point)
    LDR R0,=CtrlFlowCnt
    ; Assumes R1 OK; If not, error will be detected by R1 test and Ctrl flow test later on
    LDR R1,[R0]
    ADDS R1,R1,#0x3           ; CtrlFlowCnt += OxO3
    STR R1,[R0]

    ; Register R1
    LDR R0, =conAA
    LDR R1,[R0]
    LDR R0,[R0]
    CMP R0,R1
    BNE CPUStartUpTestFail
    LDR R0, =con55
    LDR R1,[R0]
    LDR R0,[R0]
    CMP R0,R1
    BNE CPUStartUpTestFail
    MOVS R1, #0x1             ; For ramp test

    ; Register R2
    LDR R0, =conAA
    LDR R2,[R0]
    LDR R0,[R0]
    CMP R0,R2
    BNE CPUStartUpTestFail
    LDR R0, =con55
    LDR R2,[R0]
    LDR R0,[R0]
    CMP R0,R2
    BNE CPUStartUpTestFail
    MOVS R2, #0x2             ; For ramp test

    ; Register R3
    LDR R0, =conAA
    LDR R3,[R0]
    LDR R0,[R0]
    CMP R0,R3
    BNE CPUStartUpTestFail
    LDR R0, =con55
    LDR R3,[R0]
    LDR R0,[R0]
    CMP R0,R3
    BNE CPUStartUpTestFail
    MOVS R3, #0x3             ; For ramp test

    ; Register R4
    LDR R0, =conAA
    LDR R4,[R0]
    LDR R0,[R0]
    CMP R0,R4
    BNE CPUStartUpTestFail
    LDR R0, =con55
    LDR R4,[R0]
    LDR R0,[R0]
    CMP R0,R4
    BNE CPUStartUpTestFail
    MOVS R4, #0x4             ; For ramp test

    ; Register R5
    LDR R0, =conAA
    LDR R5,[R0]
    LDR R0,[R0]
    CMP R0,R5
    BNE CPUStartUpTestFail
    LDR R0, =con55
    LDR R5,[R0]
    LDR R0,[R0]
    CMP R0,R5
    BNE CPUStartUpTestFail
    MOVS R5, #0x5             ; For ramp test

    ; Register R6
    LDR R0, =conAA
    LDR R6,[R0]
    LDR R0,[R0]
    CMP R0,R6
    BNE CPUStartUpTestFail
    LDR R0, =con55
    LDR R6,[R0]
    LDR R0,[R0]
    CMP R0,R6
    BNE CPUStartUpTestFail
    MOVS R6, #0x6             ; For ramp test

    ; Register R7
    LDR R0, =conAA
    LDR R7,[R0]
    LDR R0,[R0]
    CMP R0,R7
    BNE CPUStartUpTestFail
    LDR R0, =con55
    LDR R7,[R0]
    LDR R0,[R0]
    CMP R0,R7
    BNE CPUStartUpTestFail
    MOVS R7, #0x7             ; For ramp test

    ; Register R8
    LDR R0, =conAA
    LDR R0,[R0]
    MOV R8,R0
    CMP R0,R8
    BNE CPUStartUpTestFail
    LDR R0, =con55
    LDR R0,[R0]
    MOV R8,R0
    CMP R0,R8
    BNE CPUStartUpTestFail
    MOVS R0, #0x08            ; For ramp test
    MOV R8,R0

    BAL CPUStartUpTstCont

CPUStartUpTestFail
    BLAL FailSafePOR

CPUStartUpTstCont
    ; Register R9
    LDR R0, =conAA
    LDR R0,[R0]
    MOV R9,R0
    CMP R0,R9
    BNE CPUStartUpTestFail
    LDR R0, =con55
    LDR R0,[R0]
    MOV R9,R0
    CMP R0,R9
    BNE CPUStartUpTestFail
    MOVS R0, #0x09            ; For ramp test
    MOV R9,R0

    ; Register R10
    LDR R0, =conAA
    LDR R0,[R0]
    MOV R10,R0
    CMP R0,R10
    BNE CPUStartUpTestFail
    LDR R0, =con55
    LDR R0,[R0]
    MOV R10,R0
    CMP R0,R10
    BNE CPUStartUpTestFail
    MOVS R0, #0x0A            ; For ramp test
    MOV R10,R0

    ; Register R11
    LDR R0, =conAA
    LDR R0,[R0]
    MOV R11,R0
    CMP R0,R11
    BNE CPUStartUpTestFail
    LDR R0, =con55
    LDR R0,[R0]
    MOV R11,R0
    CMP R0,R11
    BNE CPUStartUpTestFail
    MOVS R0, #0x0B            ; For ramp test
    MOV R11,R0

    ; Register R12
    LDR R0, =conAA
    LDR R0,[R0]
    MOV R12,R0
    CMP R0,R12
    BNE CPUStartUpTestFail
    LDR R0, =con55
    LDR R0,[R0]
    MOV R12,R0
    CMP R0,R12
    BNE CPUStartUpTestFail
    MOVS R0, #0x0C            ; For ramp test
    MOV R12,R0
    LDR R0, =CPUStartUpTstCont

    ; Ramp pattern verification	(R0 is not tested)
    CMP R1, #0x01
    BNE CPUStartUpTestFail
    CMP R2, #0x02
    BNE CPUStartUpTestFail
    CMP R3, #0x03
    BNE CPUStartUpTestFail
    CMP R4, #0x04
    BNE CPUStartUpTestFail
    CMP R5, #0x05
    BNE CPUStartUpTestFail
    CMP R6, #0x06
    BNE CPUStartUpTestFail
    CMP R7, #0x07
    BNE CPUStartUpTestFail
    MOVS R0, #0x08
    CMP R0,R8
    BNE CPUStartUpTestFail
    MOVS R0, #0x09
    CMP R0,R9
    BNE CPUStartUpTestFail
    MOVS R0, #0x0A
    CMP R0,R10
    BNE CPUStartUpTestFail
    MOVS R0, #0x0B
    CMP R0,R11
    BNE CPUStartUpTestFail
    MOVS R0, #0x0C
    CMP R0,R12
    BNE CPUStartUpTestFail

    ; Process Stack pointer (banked Register R13)
    MRS R0,PSP          ; Save process stack value
    LDR R1, =conA8      ; Test is different (PSP is word aligned, 2 LSB cleared)
    LDR R1,[R1]
    MSR PSP,R1          ; load process stack value
    MRS R2,PSP          ; Get back process stack value
    CMP R2,R1           ; Verify value
    BNE CPUStartUpTestFail
    LDR R1, =con54      ; Test is different (PSP is word aligned, 2 LSB cleared)
    LDR R1,[R1]
    MSR PSP,R1          ; load process stack value
    MRS R2,PSP          ; Get back process stack value
    CMP R2,R1           ; Verify value
    BNE CPUStartUpTestFail
    MSR PSP, R0         ; Restore process stack value

    ; Stack pointer (Register R13)
    MRS R0,MSP          ; Save stack pointer value
    LDR R1, =conA8      ; Test is different (SP is word aligned, 2 LSB cleared)
    LDR R1,[R1]
    MSR MSP,R1          ; load SP value
    MRS R2,MSP          ; Get back SP value
    CMP R2,R1           ; Verify value
    BNE CPUStartUpTestFail
    LDR R1, =con54
    LDR R1,[R1]         ; load SP value
    MSR MSP,R1          ; Get back SP value
    MRS R2,MSP          ; Verify value
    CMP R2,R1
    BNE CPUStartUpTestFail
    MSR MSP,R0          ; Restore stack pointer value

    ; Link register R14	cannot be tested an error should be detected by	Ctrl flow test later

    ; Control flow test (EXIT point)
    LDR R0,=CtrlFlowCntInv
    LDR R1,[R0]
    SUBS R1,R1,#0x3	    ; CtrlFlowCntInv -= OxO3
    STR R1,[R0]

    POP {R4-R6}         ; Restore critical registers

    ; If next instruction is not executed, R0 will hold a value different from 0
    MOVS R0, #0x0       ; CPUTEST_SUCCESS
    BX LR               ; return to the caller

    ALIGN

    ENDP



;*******************************************************************************
; Function Name  : IEC60730_RunTimeCPUTest
; Description    : Cortex-M0 CPU test during run-time
;                  Note: when possible, BRANCH are 16-bit only (depending on
;                  relative offset to final BL instruction)
; Input          : None.
; Output         : Branch directly to a Fail Safe routine in case of failure
; Return         : CPUTEST_SUCCESS (=1) if test is ok
;*******************************************************************************/

IEC60730_CPURegister_RunTime PROC
    EXPORT IEC60730_CPURegister_RunTime

    PUSH {R4-R7}            ; Safe registers

    ; This is for control flow test (ENTRY point)
    LDR R0,=CtrlFlowCnt
    ; Assumes R1 OK; If not, error will be detected by R1 test and Ctrl flow test later on
    LDR R1,[R0]
    ADDS R1,R1,#0x3         ; CtrlFlowCnt += OxO3
    STR R1,[R0]

    ; Register R1
    LDR R0, =conAA
    LDR R1,[R0]
    LDR R0,[R0]
    CMP R0,R1
    BNE CPURunTimeTestFail
    LDR R0, =con55
    LDR R1,[R0]
    LDR R0,[R0]
    CMP R0,R1
    BNE CPURunTimeTestFail
    MOVS R1, #0x1           ; For ramp test

    ; Register R2
    LDR R0, =conAA
    LDR R2,[R0]
    LDR R0,[R0]
    CMP R0,R2
    BNE CPURunTimeTestFail
    LDR R0, =con55
    LDR R2,[R0]
    LDR R0,[R0]
    CMP R0,R2
    BNE CPURunTimeTestFail
    MOVS R2, #0x2           ; For ramp test

    ; Register R3
    LDR R0, =conAA
    LDR R3,[R0]
    LDR R0,[R0]
    CMP R0,R3
    BNE CPURunTimeTestFail
    LDR R0, =con55
    LDR R3,[R0]
    LDR R0,[R0]
    CMP R0,R3
    BNE CPURunTimeTestFail
    MOVS R3, #0x3           ; For ramp test

    ; Register R4
    LDR R0, =conAA
    LDR R4,[R0]
    LDR R0,[R0]
    CMP R0,R4
    BNE CPURunTimeTestFail
    LDR R0, =con55
    LDR R4,[R0]
    LDR R0,[R0]
    CMP R0,R4
    BNE CPURunTimeTestFail
    MOVS R4, #0x4           ; For ramp test

    ; Register R5
    LDR R0, =conAA
    LDR R5,[R0]
    LDR R0,[R0]
    CMP R0,R5
    BNE CPURunTimeTestFail
    LDR R0, =con55
    LDR R5,[R0]
    LDR R0,[R0]
    CMP R0,R5
    BNE CPURunTimeTestFail
    MOVS R5, #0x5           ; For ramp test

    ; Register R6
    LDR R0, =conAA
    LDR R6,[R0]
    LDR R0,[R0]
    CMP R0,R6
    BNE CPURunTimeTestFail
    LDR R0, =con55
    LDR R6,[R0]
    LDR R0,[R0]
    CMP R0,R6
    BNE CPURunTimeTestFail
    MOVS R6, #0x6           ; For ramp test

    ; Register R7
    LDR R0, =conAA
    LDR R7,[R0]
    LDR R0,[R0]
    CMP R0,R7
    BNE CPURunTimeTestFail
    LDR R0, =con55
    LDR R7,[R0]
    LDR R0,[R0]
    CMP R0,R7
    BNE CPURunTimeTestFail
    MOVS R7, #0x7           ; For ramp test

    ; Register R8
    LDR R0, =conAA
    LDR R0,[R0]
    MOV R8,R0
    CMP R0,R8
    BNE CPURunTimeTestFail
    LDR R0, =con55
    LDR R0,[R0]
    MOV R8,R0
    CMP R0,R8
    BNE CPURunTimeTestFail
    MOVS R0, #0x08          ; For ramp test
    MOV R8,R0

    BAL CPURunTimeTstCont

CPURunTimeTestFail
    BLAL FailSafePOR

CPURunTimeTstCont
    ; Register R9
    LDR R0, =conAA
    LDR R0,[R0]
    MOV R9,R0
    CMP R0,R9
    BNE CPURunTimeTestFail
    LDR R0, =con55
    LDR R0,[R0]
    MOV R9,R0
    CMP R0,R9
    BNE CPURunTimeTestFail
    MOVS R0, #0x09            ; For ramp test
    MOV R9,R0

    ; Register R10
    LDR R0, =conAA
    LDR R0,[R0]
    MOV R10,R0
    CMP R0,R10
    BNE CPURunTimeTestFail
    LDR R0, =con55
    LDR R0,[R0]
    MOV R10,R0
    CMP R0,R10
    BNE CPURunTimeTestFail
    MOVS R0, #0x0A            ; For ramp test
    MOV R10,R0

    ; Register R11
    LDR R0, =conAA
    LDR R0,[R0]
    MOV R11,R0
    CMP R0,R11
    BNE CPURunTimeTestFail
    LDR R0, =con55
    LDR R0,[R0]
    MOV R11,R0
    CMP R0,R11
    BNE CPURunTimeTestFail
    MOVS R0, #0x0B            ; For ramp test
    MOV R11,R0

    ; Register R12
    LDR R0, =conAA
    LDR R0,[R0]
    MOV R12,R0
    CMP R0,R12
    BNE CPURunTimeTestFail
    LDR R0, =con55
    LDR R0,[R0]
    MOV R12,R0
    CMP R0,R12
    BNE CPURunTimeTestFail
    MOVS R0, #0x0C            ; For ramp test
    MOV R12,R0
    LDR R0, =CPUStartUpTstCont

    ; Link register R14	cannot be tested an error should be detected by	Ctrl flow test later

    ; Ramp pattern verification	(R0 is not tested)
    CMP R1, #0x01
    BNE CPURunTimeTestFail
    CMP R2, #0x02
    BNE CPURunTimeTestFail
    CMP R3, #0x03
    BNE CPURunTimeTestFail
    CMP R4, #0x04
    BNE CPURunTimeTestFail
    CMP R5, #0x05
    BNE CPURunTimeTestFail
    CMP R6, #0x06
    BNE CPURunTimeTestFail
    CMP R7, #0x07
    BNE CPURunTimeTestFail
    MOVS R0, #0x08
    CMP R0,R8
    BNE CPURunTimeTestFail
    MOVS R0, #0x09
    CMP R0,R9
    BNE CPURunTimeTestFail
    MOVS R0, #0x0A
    CMP R0,R10
    BNE CPURunTimeTestFail
    MOVS R0, #0x0B
    CMP R0,R11
    BNE CPURunTimeTestFail
    MOVS R0, #0x0C
    CMP R0,R12
    BNE CPURunTimeTestFail

    ; Control flow test (EXIT point)
    LDR R0,=CtrlFlowCntInv
    LDR R1,[R0]
    SUBS R1,R1,#0x3     ; CtrlFlowCntInv -= OxO3
    STR R1,[R0]

    POP {R4-R7}         ; Restore registers

    MOVS R0, #0x0       ; CPUTEST_SUCCESS
    BX LR               ; return to the caller
    ENDP                ; routine (unrecoverable fault)

    END
/******************* (C) COPYRIGHT 2018 Megawin ************ END OF FILE *****/


