понедельник, 13 ноября 2023 г.

Set stack in system and irq mode in cortex a15

Code Composer Studio v. 11.1.0.00011 Windows

1. Build Tool: ti-cgt-arm_20.2.7.LTS

Перед main загружается из файла
C:\ti\ccs1110\ccs\tools\compiler\ti-cgt-arm_20.2.7.LTS\lib\src\boot_non_cortex_m.asm
asm-функция _c_int00 на строчке 180 (32 BIT STATE BOOT ROUTINE).

Файл boot_non_cortex_m.asm надо немного отредактировать, чтобы при старте cortex a15 процессор не падал в hard fault.

;****************************************************************************
;* BOOT.ASM
;*
;* THIS IS THE INITAL BOOT ROUTINE FOR TMS470 C++ PROGRAMS.
;* IT MUST BE LINKED AND LOADED WITH ALL C++ PROGRAMS.
;*
;* THIS MODULE PERFORMS THE FOLLOWING ACTIONS:
;*   1) ALLOCATES THE STACK AND INITIALIZES THE STACK POINTER
;*   2) CALLS AUTO-INITIALIZATION ROUTINE
;*   3) CALLS THE FUNCTION MAIN TO START THE C++ PROGRAM
;*   4) CALLS THE STANDARD EXIT ROUTINE
;*
;* THIS MODULE DEFINES THE FOLLOWING GLOBAL SYMBOLS:
;*   1) __stack     STACK MEMORY AREA
;*   2) _c_int00    BOOT ROUTINE
;*
;****************************************************************************
.armfunc _c_int00

;****************************************************************************
;*  32 BIT STATE BOOT ROUTINE                                               *
;****************************************************************************

    .global __stack
;***************************************************************
;* DEFINE THE USER MODE STACK (DEFAULT SIZE IS 512)
;***************************************************************
__stack:.usect  ".stack", 0, 4

    .global _c_int00
;***************************************************************
;* FUNCTION DEF: _c_int00
;***************************************************************
_c_int00: .asmfunc stack_usage(0)

    ; Invalidate and Enable Branch Prediction
    MOV     r0, #0
    MCR     p15, #0, r0, c7, c5, #6
    ISB
    MRC     p15, #0, r0, c1, c0, #0
    ORR     r0, r0, #0x00000800
    MCR     p15, #0, r0, c1, c0, #0

    .if __TI_NEON_SUPPORT__ | __TI_VFP_SUPPORT__

        ;
        ; Enable Neon/VFP Co-Processor
        ;
MRC p15, #0, r1, c1, c0, #2        ; r1 = Access Control Register
ORR r1, r1, #(0xf << 20)           ; enable full access for p10,11
MCR p15, #0, r1, c1, c0, #2        ; Access Control Register = r1
MOV r1, #0
MCR p15, #0, r1, c7, c5, #4        ; flush prefetch buffer
MOV r0,#0x40000000
FMXR FPEXC, r0                     ; Set Neon/VFP Enable bit
        ;*------------------------------------------------------
        ;* SETUP PRIVILEGED AND USER MODE ACCESS TO COPROCESSORS
        ;* 10 AND 11, REQUIRED TO ENABLE NEON/VFP
        ;* COPROCESSOR ACCESS CONTROL REG
        ;* BITS [23:22] - CP11, [21:20] - CP10
        ;* SET TO 0b11 TO ENABLE USER AND PRIV MODE ACCESS
        ;*------------------------------------------------------
        ;MRC      p15,#0x0,r0,c1,c0,#2
        ;MOV      r3,#0xf00000
        ;ORR      r0,r0,r3
        ;MCR      p15,#0x0,r0,c1,c0,#2

        ;*------------------------------------------------------
        ; SET THE EN BIT, FPEXC[30] TO ENABLE NEON AND VFP
        ;*------------------------------------------------------
        ;MOV      r0,#0x40000000
        ;FMXR     FPEXC,r0
.endif

    ;*------------------------------------------------------
    ;* SET TO USER MODE
    ;*------------------------------------------------------
    ;
    ; Change to user mode. It allows for a stack smaller than 64kB.
    ;
    ;MRS     r0, cpsr
    ;BIC     r0, r0, #0x1F  ; CLEAR MODES
    ;ORR     r0, r0, #0x10  ; SET USER MODE
    ;MSR     cpsr_pf, r0

    ;*------------------------------------------------------
    ;* INITIALIZE THE USER MODE STACK
    ;*------------------------------------------------------
    ;.if __TI_AVOID_EMBEDDED_CONSTANTS
    ;    MOVW    sp, __STACK_END
    ;    MOVT    sp, __STACK_END
    ;.else
    ;LDR     sp, c_STACK_END
    ;.endif

    ;
    ; The stack for all the modes (Abort, FIQ, etc.) is set by
    ; the runtime support library.
    ;
    BIC   r0, r0, #0x1F ; system mode

    ORR   r0, r0, #0x12 ; IRQ mode
    MSR   cpsr_cf, r0
LDR   r13, c_IRQ_STACK_END

    ORR   r0, r0, #0x1F ; system mode
    MSR   cpsr_cf, r0
LDR   r13, c_SYSTEM_STACK_END

    ;*------------------------------------------------------
;* Call the __mpu_init hook function.
    ;*------------------------------------------------------
    BL      __mpu_init

    ;*------------------------------------------------------
    ;* Perform all the required initializations when
    ;* _system_pre_init() returns non-zero:
    ;*   - Process BINIT Table
    ;*   - Perform C auto initialization
    ;*   - Call global constructors
    ;*------------------------------------------------------
    BL      _system_pre_init
    CMP     R0, #0
    BEQ     bypass_auto_init
    BL      __TI_auto_init
bypass_auto_init:

    ;*------------------------------------------------------
    ;* CALL APPLICATION
    ;*------------------------------------------------------
    BL      _args_main

    ;*------------------------------------------------------
    ;* IF APPLICATION DIDN'T CALL EXIT, CALL EXIT(1)
    ;*------------------------------------------------------
    MOV     R0, #1
    BL      exit

    ;*------------------------------------------------------
    ;* DONE, LOOP FOREVER
    ;*------------------------------------------------------
L1:     B       L1
    .endasmfunc

;***************************************************************
;* CONSTANTS USED BY THIS MODULE
;***************************************************************
    ;.if !__TI_AVOID_EMBEDDED_CONSTANTS
c_SYSTEM_STACK_END    .long    __STACK_END
c_IRQ_STACK_END       .long    __STACK_END - 0x400
    ;.endif

;******************************************************
;* UNDEFINED REFERENCES                               *
;******************************************************
.global __STACK_END
        .global _system_pre_init
        .global __TI_auto_init
.global _args_main
.global exit
.global __mpu_init

.end

Links:

2. Build tool: Linaro GNU v7.2.1. Файл в сконструированном мастером проекте startup_ARMCA15.S.

@******************************************************************************
@
@ startup_ARMCA15.S - Init code routine for Cortex A15 cores and Linaro baremetal
@


@****************************** Global Symbols*******************************
.global Entry
.global __stack
.global __bss_start__
.global __bss_end__
.global start_boot


@************************ Internal Definitions ******************************
@
@ to set the mode bits in CPSR for different modes
@
.set MODE_USR, 0x10
.set MODE_FIQ, 0x11
.set MODE_IRQ, 0x12
.set MODE_SVC, 0x13
.set MODE_ABT, 0x17
.set MODE_UND, 0x1B
.set MODE_SYS, 0x1F


.equ I_F_BIT, 0xC0


@**************************** Code Section ***********************************
.text


@
@ This code is assembled for ARM instructions
@
.code 32


@******************************************************************************
@
@******************************************************************************
@
@ The reset handler sets up the stack pointers for all the modes. The FIQ and
@ IRQ shall be disabled during this. Then clears the BSS section, enters the
@ main function.


Entry:




@ Invalidate and Enable Branch Prediction
MOV r0, #0
MCR p15, #0, r0, c7, c5, #6
ISB
MRC p15, #0, r0, c1, c0, #0
ORR r0, r0, #0x00000800
MCR p15, #0, r0, c1, c0, #0


.if __ARM_PCS_VFP == 1


@
@ Enable Neon/VFP Co-Processor
@
MRC p15, #0, r1, c1, c0, #2 @ r1 = Access Control Register
ORR r1, r1, #(0xf << 20) @ enable full access for p10,11
MCR p15, #0, r1, c1, c0, #2 @ Access Control Register = r1
MOV r1, #0
MCR p15, #0, r1, c7, c5, #4 @ flush prefetch buffer
MOV r0,#0x40000000
FMXR FPEXC, r0 @ Set Neon/VFP Enable bit


.endif


MRS r0, cpsr
ORR r0, r0, #192
MSR cpsr, r0
@
@ The stack for all the modes (Abort, FIQ, etc.) is set by
@ the runtime support library.
@
BIC r0, r0, #0x1F


ORR r0, r0, #0x12
MSR cpsr_cf, r0
LDR r13, = __StackMp


ORR r0, r0, #0x1F
MSR cpsr_cf, r0
LDR r13, = __StackTop
@
@ Set up the Vector Base Address Regsiter
@
LDR r0, = __isr_vector
MCR p15, 0, r0, c12, c0, 0 @ Write VBAR Register

.if USERMODE == 1
@
@ Change to user mode. It allows for a stack smaller than 64kB.
@
MSR cpsr_c, #MODE_USR|I_F_BIT @ change to user mode
.endif


@
@ The BSS section is cleared by the runtime support library
@


@
@ Enter the main function.
@ The symbol _start is the entry point for the runtime support library
@


Enter_BootLoader:
LDR r10, = _start @ Get the address of _start
MOV lr,pc @ Dummy return
BX r10 @ Branch to main
SUB pc, pc, #0x08 @ looping


@
@ Set the Stack space here
@
.section .stack
.align 4
.globl __StackBase
.globl __StackLimit
__StackLimit:
@ .space 0x400 @ the stack size is set by the linker script
.size __StackLimit, . - __StackLimit
__StackBase:
.size __StackBase, . - __StackBase


@
@ Set the Heap space here
@
.section .heap
.align 4
.globl __HeapBase
.globl __HeapLimit
__HeapBase:
@ .space 0x400 @ the heap size is set by the linker script
.size __HeapBase, . - __HeapBase
__HeapLimit:
.size __HeapLimit, . - __HeapLimit

@
@ Set the Interrupt vector table here
@


.section .isr_vector
.align 4
.globl __isr_vector
__isr_vector:
LDR pc, [pc,#24] @ 0x00 Reset
LDR pc, = UndefInstHandler @ 0x04 Undefined instruction
LDR pc, = SVC_Handler @ 0x08 Supervisor
LDR pc, = AbortHandler @ 0x0C Prefetch abort
LDR pc, = AbortHandler @ 0x10 Data abort
LDR pc, = AbortHandler @ 0x14 not used
LDR pc, = IRQHandler @ 0x18 IRQ
LDR pc, = FIQHandler @ 0x1C FIQ


.long Entry
.long 0
.long SVC_Handler
.long 0
.long 0
.long 0
.long 0
.long 0


@
@ End of the file
@
.end


https://community.arm.com/support-forums/f/keil-forum/26293/understanding-pc-r15-register-arm7

Stack:
1) Устройство Стека для Intel386 https://habr.com/ru/articles/675522/
3) Как защититься от переполнения стека (на Cortex M)? https://habr.com/ru/articles/425071/
4) Как работает stack trace на ARM https://habr.com/ru/companies/embox/articles/424365/
5) Одна маленькая загадка про Cortex-M https://habr.com/ru/articles/224101/

Interrupts:
1) Что необходимо знать, чтобы написать свою Embedded RTOS (часть 1) https://habr.com/ru/articles/598693/
2) Тайны пингвина: как работают исключения и прерывания в Linux? https://habr.com/ru/companies/timeweb/articles/780082/
3) Динамическое управление прерываниями в ARM https://habr.com/ru/articles/275351/
4) Прерывания в конвейеризированных процессорах https://habr.com/ru/articles/188002/