
/**
 ******************************************************************************
 *                                                                            *
 * @file        MG32_IEC60730_CPU_Reg_GCC.S                               *
 *                                                                            *
 * @brief       Check MCU full register state.                                *
 *                                                                            *
 * @par         Project                                                       *
 *              MG32                                                      *
 * @version     V1.00                                                         *
 * @date        2022/11/19 16:00                                              *
 * @note        Copyright (c) 2022 MegaWin Technology Co., Ltd.               *
 *              All rights reserved.                                          *
 ******************************************************************************
 */


  .syntax unified
  .cpu cortex-m0
  .fpu softvfp
  .thumb

  .global IEC60730_CPURegister_StartUp
  .global IEC60730_CPURegister_RunTime
      
  .section .text.IEC60730_CPURegister_StartUp
  .weak IEC60730_CPURegister_StartUp
  .type IEC60730_CPURegister_StartUp, %function
    
  // Reference to the FailSafe routine to be executed in case of non-recoverable
  // failure (FailSafePOR)

  // C variables for control flow monitoring (CtrlFlowCnt, CtrlFlowCntInv)

conAA: .word  0xAAAAAAAA          // sds
con55: .word  0x55555555          // ssd
con80: .word  0x80000000          // ssd
conA8: .word  0xAAAAAAA8          // ssd
con54: .word  0x55555554          // ssd
     
/**
 *******************************************************************************
 * 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)
 ********************************************************************************
 */

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

    .end

/**
 ******************************************************************************
 * 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                        *
 ******************************************************************************
 */

  .section .text.IEC60730_CPURegister_RunTime
  .weak IEC60730_CPURegister_RunTime
  .type IEC60730_CPURegister_RunTime, %function
    
    
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


    .end
/******************* (C) COPYRIGHT 2022 Megawin ************ END OF FILE *****/


