硬汉嵌入式论坛

 找回密码
 立即注册
12
返回列表 发新帖
楼主: rcsn0601
收起左侧

[ThreadX全家桶] threadx移植到新唐ARM9 nuc977失败。

  [复制链接]

0

主题

6

回帖

6

积分

新手上路

积分
6
发表于 2025-8-23 15:48:03 | 显示全部楼层
这么多年后,有人搞定了吗
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
发表于 2025-8-23 15:57:14 | 显示全部楼层
tx_initialize_low_level.s
[Asm] 纯文本查看 复制代码
;/**************************************************************************/
;/*                                                                        */
;/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
;/*                                                                        */
;/*       This software is licensed under the Microsoft Software License   */
;/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
;/*       found in the LICENSE file at [url]https://aka.ms/AzureRTOS_EULA[/url]       */
;/*       and in the root directory of this software.                      */
;/*                                                                        */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/**                                                                       */ 
;/** ThreadX Component                                                     */ 
;/**                                                                       */
;/**   Initialize                                                          */
;/**                                                                       */
;/**************************************************************************/
;/**************************************************************************/
;
;
;#define TX_SOURCE_CODE
;
;
;/* Include necessary system files.  */
;
;#include "tx_api.h"
;#include "tx_initialize.h"
;#include "tx_thread.h"
;#include "tx_timer.h"
;
;
SVC_MODE        DEFINE  0xD3                    ; Disable irq,fiq SVC mode
IRQ_MODE        DEFINE  0xD2                    ; Disable irq,fiq IRQ mode
FIQ_MODE        DEFINE  0xD1                    ; Disable irq,fiq FIQ mode
SYS_MODE        DEFINE  0xDF                    ; Disable irq,fiq SYS mode
REG_AIC_IPER_L  DEFINE  0x01C20410              ;0x01C20400+0x10
REG_AIC_IPER_H  DEFINE  0x01C20414              ;0x01C20400+0x10
TIMER_IRQ_STA   DEFINE  0x01C20C04              ;0x01C20C00+0x04
;
;

    EXTERN      _tx_thread_system_stack_ptr
    EXTERN      _tx_initialize_unused_memory
    EXTERN      _tx_thread_context_save
;    EXTERN      _tx_thread_vectored_context_save
    EXTERN      _tx_thread_context_restore
#ifdef TX_ENABLE_FIQ_SUPPORT
    EXTERN      _tx_thread_fiq_context_save
    EXTERN      _tx_thread_fiq_context_restore
#endif
#ifdef TX_ENABLE_IRQ_NESTING
    EXTERN      _tx_thread_irq_nesting_start
    EXTERN      _tx_thread_irq_nesting_end
#endif
#ifdef TX_ENABLE_FIQ_NESTING
    EXTERN      _tx_thread_fiq_nesting_start
    EXTERN      _tx_thread_fiq_nesting_end
#endif
    EXTERN      _tx_timer_interrupt
    EXTERN      ?cstartup
    EXTERN      _tx_build_options
    EXTERN      _tx_version_id
    EXTERN      IRQ_Handler1
    EXTERN      IRQ_Handler2
    EXTERN      print_flag
    EXTERN      Iid_L
    EXTERN      Iid_H
    EXTERN      __vector
;
;
;
;/* Define the FREE_MEM segment that will specify where free memory is 
;   defined.  This must also be located in at the end of other RAM segments
;   in the linker control file.  The value of this segment is what is passed
;   to tx_application_define.  */
;
    RSEG    FREE_MEM:DATA
    PUBLIC  __tx_free_memory_start
__tx_free_memory_start
    DS32    4
;
;
;
;
;/**************************************************************************/ 
;/*                                                                        */ 
;/*  FUNCTION                                               RELEASE        */ 
;/*                                                                        */ 
;/*    _tx_initialize_low_level                             ARM9/IAR       */ 
;/*                                                           6.0.1        */
;/*  AUTHOR                                                                */
;/*                                                                        */
;/*    William E. Lamie, Microsoft Corporation                             */
;/*                                                                        */
;/*  DESCRIPTION                                                           */
;/*                                                                        */ 
;/*    This function is responsible for any low-level processor            */ 
;/*    initialization, including setting up interrupt vectors, setting     */ 
;/*    up a periodic timer interrupt source, saving the system stack       */ 
;/*    pointer for use in ISR processing later, and finding the first      */ 
;/*    available RAM memory address for tx_application_define.             */ 
;/*                                                                        */ 
;/*  INPUT                                                                 */ 
;/*                                                                        */ 
;/*    None                                                                */ 
;/*                                                                        */ 
;/*  OUTPUT                                                                */ 
;/*                                                                        */ 
;/*    None                                                                */ 
;/*                                                                        */ 
;/*  CALLS                                                                 */ 
;/*                                                                        */ 
;/*    None                                                                */ 
;/*                                                                        */ 
;/*  CALLED BY                                                             */ 
;/*                                                                        */ 
;/*    _tx_initialize_kernel_enter           ThreadX entry function        */ 
;/*                                                                        */ 
;/*  RELEASE HISTORY                                                       */ 
;/*                                                                        */ 
;/*    DATE              NAME                      DESCRIPTION             */
;/*                                                                        */
;/*  06-30-2020     William E. Lamie         Initial Version 6.0.1         */
;/*                                                                        */
;/**************************************************************************/
;VOID   _tx_initialize_low_level(VOID)
;{
    RSEG    .text:CODE:NOROOT(2)
    CODE32
    PUBLIC  _tx_initialize_low_level
_tx_initialize_low_level
;
;    /****** NOTE ****** The IAR 4.11a and above releases call main in SYS mode.  */
;
;    /* Remember the stack pointer, link register, and switch to SVC mode.  */
;
    MOV     r0, sp                              ; Remember the SP
    MOV     r1, lr                              ; Remember the LR
    MOV     r3, #SVC_MODE                       ; Build SVC mode CPSR
    MSR     CPSR_cxsf, r3                       ; Switch to SVC mode
    MOV     sp, r0                              ; Inherit the stack pointer setup by cstartup
    MOV     lr, r1                              ; Inherit the link register

;
;    /* Pickup the start of free memory.  */
;
    LDR     r0, =__tx_free_memory_start         ; Get end of non-initialized RAM area
;
;    /* Save the system stack pointer.  */
;    _tx_thread_system_stack_ptr = (VOID_PTR) (sp);

;    /* Save the first available memory address.  */
;    _tx_initialize_unused_memory =  (VOID_PTR) FREE_MEM;
;
    
    LDR     r2, =_tx_initialize_unused_memory   ; Pickup unused memory ptr address
    STR     r0, [r2, #0]                        ; Save first free memory address

;                      
;    /* Setup Timer for periodic interrupts.  */
;
;    /* Done, return to caller.  */
;
#ifdef TX_THUMB
    BX      lr                                  ; Return to caller
#else
    MOV     pc, lr                              ; Return to caller
#endif
;}
;
;/* Define shells for each of the interrupt vectors.  */
;
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_undefined
__tx_undefined
    B       __tx_undefined                      ; Undefined handler
;
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_swi_interrupt
__tx_swi_interrupt
    B       __tx_swi_interrupt                  ; Software interrupt handler
;
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_prefetch_handler
__tx_prefetch_handler
    B       __tx_prefetch_handler               ; Prefetch exception handler
;
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_abort_handler
__tx_abort_handler
    B       __tx_abort_handler                  ; Abort exception handler
;
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_reserved_handler
__tx_reserved_handler
    B       __tx_reserved_handler               ; Reserved exception handler
;
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_irq_handler
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_irq_processing_return

__tx_irq_handler
    B      _tx_thread_context_save
__tx_irq_processing_return
    ;Check for time0 interrupts on the ARMulator*/
    LDR     r0,=REG_AIC_IPER_H
    LDR     r0,[r0]
    LDR     r1,=Iid_H
    STR     r0,[r1] ;store hight 32 bit
    LDR     r1,=Iid_L
    LDR     r0,=REG_AIC_IPER_L
    LDR     r0,[r0]
    STR     r0,[r1] ;store low 32 bit
    MOV     r1,#1
    LSL     r1,r1,#0x0D ;IRQ_Timer0 is 0x0D
    ADD     r0,r0,r1
    CMP     r0,#0
    BEQ     IRQ_Handler1;_tx_not_timer_interrupt
    BIC     r0,r0,r1 
    LDR     r1,=REG_AIC_IPER_L
    STR     r0,[r1]
    ;clear time0 bit
    LDR     r0,=TIMER_IRQ_STA
    LDR     r1,[r0]
    ORR     r1,r1,#1;time0
    STR     r1,[r0]
    ;BL      print_flag
    

#ifdef TX_ENABLE_IRQ_NESTING
    BL      _tx_thread_irq_nesting_start
#endif
    BL      _tx_timer_interrupt                 ; Timer interrupt handler

#ifdef TX_ENABLE_IRQ_NESTING
    BL      _tx_thread_irq_nesting_end
#endif

    B       _tx_thread_context_restore
;
;
;    /* This is an example of a vectored IRQ handler.  */
;
;    RSEG    .text:CODE:NOROOT(2)
;    PUBLIC  __tx_example_vectored_irq_handler
;__tx_example_vectored_irq_handler
;
;    /* Jump to context save to save system context.  */
;    STMDB   sp!, {r0-r3}                    ; Save some scratch registers
;    MRS     r0, SPSR                        ; Pickup saved SPSR
;    SUB     lr, lr, #4                      ; Adjust point of interrupt 
;    STMDB   sp!, {r0, r10, r12, lr}         ; Store other registers
;    BL      _tx_thread_vectored_context_save
;
;    /* At this point execution is still in the IRQ mode.  The CPSR, point of
;       interrupt, and all C scratch registers are available for use.  In 
;       addition, IRQ interrupts may be re-enabled - with certain restrictions -
;       if nested IRQ interrupts are desired.  Interrupts may be re-enabled over
;       small code sequences where lr is saved before enabling interrupts and 
;       restored after interrupts are again disabled.  */
;
;    /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start 
;       from IRQ mode with interrupts disabled.  This routine switches to the
;       system mode and returns with IRQ interrupts enabled.  
;       
;       NOTE:  It is very important to ensure all IRQ interrupts are cleared 
;       prior to enabling nested IRQ interrupts.  */
;#ifdef TX_ENABLE_IRQ_NESTING
;    BL      _tx_thread_irq_nesting_start
;#endif
;
;    /* Application IRQ handler is called here!  */
;
;    /* If interrupt nesting was started earlier, the end of interrupt nesting
;       service must be called before returning to _tx_thread_context_restore.  
;       This routine returns in processing in IRQ mode with interrupts disabled.  */
;#ifdef TX_ENABLE_IRQ_NESTING
;    BL      _tx_thread_irq_nesting_end
;#endif
;
;    /* Jump to context restore to restore system context.  */
;    B       _tx_thread_context_restore
;
;
#ifdef TX_ENABLE_FIQ_SUPPORT
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_fiq_handler
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_fiq_processing_return
__tx_fiq_handler
;
;    /* Jump to fiq context save to save system context.  */
    B       _tx_thread_fiq_context_save
__tx_fiq_processing_return
;
;    /* At this point execution is still in the FIQ mode.  The CPSR, point of
;       interrupt, and all C scratch registers are available for use.  */
;
;    /* Interrupt nesting is allowed after calling _tx_thread_fiq_nesting_start 
;       from FIQ mode with interrupts disabled.  This routine switches to the
;       system mode and returns with FIQ interrupts enabled. 
;
;       NOTE:  It is very important to ensure all FIQ interrupts are cleared 
;       prior to enabling nested FIQ interrupts.  */
#ifdef TX_ENABLE_FIQ_NESTING
    BL      _tx_thread_fiq_nesting_start
#endif
;
;    /* Application FIQ handlers can be called here!  */
;
;    /* If interrupt nesting was started earlier, the end of interrupt nesting
;       service must be called before returning to _tx_thread_fiq_context_restore.  */
#ifdef TX_ENABLE_FIQ_NESTING
    BL      _tx_thread_fiq_nesting_end
#endif
;
;    /* Jump to fiq context restore to restore system context.  */
    B       _tx_thread_fiq_context_restore
;
;
#else
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_fiq_handler
__tx_fiq_handler
    B       __tx_fiq_handler                    ; FIQ interrupt handler
#endif
;
;
BUILD_OPTIONS
    DC32    _tx_build_options                   ; Reference to ensure it comes in
VERSION_ID
    DC32    _tx_version_id                      ; Reference to ensure it comes in
    END


cstartup.s
[C] 纯文本查看 复制代码
            MODULE ?cstartup
            SECTION CSTACK    :DATA:NOROOT(3)
            SECTION SVC_STACK :DATA:NOROOT(3)
            SECTION IRQ_STACK :DATA:NOROOT(3)
            SECTION FIQ_STACK :DATA:NOROOT(3)
            SECTION UND_STACK :DATA:NOROOT(3)
            SECTION ABT_STACK :DATA:NOROOT(3)
            SECTION HEAP      :DATA:NOROOT(3)

            SECTION .intvec:CODE:NOROOT(2)

            PUBLIC __vector
            PUBLIC __iar_program_start

__vector:
        LDR     PC, Reset_Addr
        LDR     PC, Undefined_Addr
        LDR     PC, SWI_Addr
        LDR     PC, Prefetch_Addr
        LDR     PC, Abort_Addr
        NOP                             ; Reserved vector
        LDR     PC, IRQ_Addr
        LDR     PC, FIQ_Addr

Reset_Addr:      DCD     __iar_program_start
Undefined_Addr:  DCD     Undefined_Handler
SWI_Addr:        DCD     SWI_Handler
Prefetch_Addr:   DCD     Prefetch_Handler
Abort_Addr:      DCD     Abort_Handler
                 DCD		0
IRQ_Addr:        DCD     IRQ_Handler
FIQ_Addr:        DCD     FIQ_Handler

            SECTION .text:CODE:NOROOT(2)
            EXTERN main
            EXTERN  ?main
            EXTERN BSP_Init
            EXTERN IRQ_Handler1
            REQUIRE __vector
            PUBLIC IRQ_Handler2
        
__iar_program_start:        
?cstartup:

MODE_USR  DEFINE        0x10
MODE_FIQ  DEFINE        0x11
MODE_IRQ  DEFINE        0x12
MODE_SVC  DEFINE        0x13
MODE_ABT  DEFINE        0x17
MODE_UND  DEFINE        0x1B
MODE_SYS  DEFINE        0x1F
MODEMASK  DEFINE        0x1F
NOINT     DEFINE        0xC0

    ;--------------------------------
    ; Initial Stack Pointer register
    ;--------------------------------
    ;INIT_STACK
    MRS     R0, CPSR

    BIC     r0, r0, #MODEMASK
    ORR     r1, r0, #MODE_UND
    ;ORR     r1, r1, #NOINT
    MSR     CPSR_c, R1            ; Undef mode
    LDR     SP, =SFE(UND_STACK)

    BIC     r0, r0, #MODEMASK
    ORR     r1, r0, #MODE_ABT
    ;ORR     r1, r1, #NOINT
    MSR     CPSR_c,R1             ; Abort mode
    LDR     SP, =SFE(ABT_STACK)

    BIC     r0, r0, #MODEMASK
    ORR     r1, r0, #MODE_IRQ
    ;ORR     r1, r1, #NOINT
    MSR     CPSR_c,R1             ; IRQ mode
    LDR     SP, =SFE(IRQ_STACK)

    BIC     r0, r0, #MODEMASK
    ORR     r1, r0, #MODE_FIQ
    ;ORR     r1, r1, #NOINT
    MSR     CPSR_c,R1             ; FIQ mode
    LDR     SP, =SFE(FIQ_STACK)

    BIC      R0,R0,#MODEMASK
    ORR      R1,R0,#MODE_SYS
    ;ORR      r1, r0, #NOINT
    MSR      CPSR_c,R1              ; SYS/User mode
    LDR      SP, =SFE(CSTACK)

    BIC      R0,R0,#MODEMASK
    ORR      R1,R0,#MODE_SVC
    ;ORR      r1, r1, #NOINT
    MSR      CPSR_c,R1             ; SVC mode
    LDR      SP, =SFE(SVC_STACK)

    ;------------------------------------------------------
    ; Set the normal exception vector of CP15 control bit
    ;------------------------------------------------------
    MRC p15, 0, r0 , c1, c0     ; r0 := cp15 register 1
    bic r0, r0, #0x2000         ; Clear bit13 in r1 =0低端向量表 =1高端向量表
    MCR p15, 0, r0 , c1, c0     ; cp15 register 1 := r0

    ldr r0, = __vector
    mrc p15, 0, r2, c1, c0, 0	 ;读出CP15
    ands r2, r2, #(1 << 13)    ;取13位判断
    ldreq r1, =0x00000000      ;值=0  Z=1相等
    ldrne r1, =0xFFFF0000			 ;值!=0 Z=0 不相等
    ;从R0地址复制16个数据到R1
    ldmia r0!, {r2-r8, r10}
    stmia r1!, {r2-r8, r10}
    ldmia r0!, {r2-r8, r10}
    stmia r1!, {r2-r8, r10}

    BL      BSP_Init
    B       main
    B       ?main
; ************************
; Exception Handlers
; ************************

; The following dummy handlers do not do anything useful in this example.
; They are set up here for completeness.
  EXTERN SWI_Handler1
  EXTERN FIQ_Handler1
  EXTERN __tx_irq_handler
  EXTERN print_flag

Undefined_Handler
    B       print_flag;Undefined_Handler
SWI_Handler
    B 	    SWI_Handler1 
Prefetch_Handler
    B       print_flag;Prefetch_Handler
Abort_Handler
    B       print_flag;Abort_Handler
	NOP
IRQ_Handler
    B       __tx_irq_handler;IRQ_Handler2 ;
FIQ_Handler
    B       FIQ_Handler1	
	
;    PUBLIC  __tx_irq_processing_return
    EXTERN      _tx_thread_context_save
    EXTERN      _tx_thread_context_restore
#ifdef TX_ENABLE_IRQ_NESTING
    EXTERN      _tx_thread_irq_nesting_start
    EXTERN      _tx_thread_irq_nesting_end
#endif


IRQ_Handler2
    LDR SP,=SFE(IRQ_STACK)
    sub sp, sp, #72
    stmia sp, {r0 - r12}
    add r8, sp, #60
    stmdb r8, {sp, lr}^
    nop
    str lr, [r8, #0]
    mrs r6, spsr
    str r6, [r8, #4]
    str r0, [r8, #8]
    mov r0, sp
    bl IRQ_Handler1
    ldmia sp, {r0 - lr}^
    mov r0, r0
    ldr lr, [sp, #60]
    add sp, sp, #72
    subs pc, lr, #4

    END


以上代码tick中断工作正常,_tx_timer_system_clock 正常执行。在主函数中加入tx_kernel_enter()函数后_tx_timer_system_clock 加到15000后就停止变化了,没有tx_kernel_enter(),_tx_timer_system_clock 可以一直正常工作。

有几个问题:
1.主函数中加入tx_kernel_enter(),心跳变量15000就停止了;
2.线程不工作;
3.我看在arm9的demo中 _tx_thread_system_stack_ptr变量没有用,不知道有没有关系;
4.在‘tx_initialize_low_level.s’文件中看到一行 /****** NOTE ****** The IAR 4.11a and above releases call main in SYS mode.  */,目前已经工作在了SVC模式,不知道还需不需要特殊处理
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
发表于 2025-8-25 16:10:15 | 显示全部楼层
Sam_wang 发表于 2025-8-23 15:57
tx_initialize_low_level.s
[Asm] 纯文本查看 复制代码
;/************************************************* ...[/quote]

接上问题:
在`_tx_thread_schedule`函数中加了打印函数,确定了一去不复返的位置,
在159行:LDMNEIA sp!, {r0-r12, lr, pc}^
[mw_shl_code=asm,true]    LDMIA   sp!, {r0, r1}                       ; Pickup the stack type and saved CPSR
    CMP     r0, #0                              ; Check for synchronous context switch
    MSRNE   SPSR_cxsf, r1                       ; Setup SPSR for return
    LDMNEIA sp!, {r0-r12, lr, pc}^              ; Return to point of thread interrupt
    LDMIA   sp!, {r4-r11, lr}                   ; Return to thread synchronously
    MSR     CPSR_cxsf, r1                       ; Recover CPSR


希望路过高手给分析分析
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
发表于 2025-8-26 12:02:53 | 显示全部楼层
Sam_wang 发表于 2025-8-25 16:10
接上问题:
在`_tx_thread_schedule`函数中加了打印函数,确定了一去不复返的位置,
在159行:LDMNEIA  ...

再记录一个新的疑点:
在arm9上,boot 将代码从Flash转移到DDR上,偏移地址在0x80080000,会不会存在系统汇编部分操作了地址小于0x80080000的部分,而导致系统异常的
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
发表于 2025-9-1 08:22:39 | 显示全部楼层
Sam_wang 发表于 2025-8-26 12:02
再记录一个新的疑点:
在arm9上,boot 将代码从Flash转移到DDR上,偏移地址在0x80080000,会不会存在系 ...

继续跟进,欢迎大神来讨论:
再看ThreadX源码时发现,AC5与IAR的启动代码有很大的差别,其中AC5中直接将中断向量表放在了tx_initialize_low_level.s 文件中,而且在原来放复位函数的地方,直接跳转到了main函数,在IAR中先执行cstartup.s,再执行tx_initialize_low_level.s ,再cstartup.s中配置栈、中断向量表以及复位函数,二者的中断处理也不太一样,以下是源码:
AC5:
[Asm] 纯文本查看 复制代码
;/***************************************************************************
; * Copyright (c) 2024 Microsoft Corporation 
; * 
; * This program and the accompanying materials are made available under the
; * terms of the MIT License which is available at
; * [url]https://opensource.org/licenses/MIT.[/url]
; * 
; * SPDX-License-Identifier: MIT
; **************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/**                                                                       */ 
;/** ThreadX Component                                                     */ 
;/**                                                                       */
;/**   Initialize                                                          */
;/**                                                                       */
;/**************************************************************************/
;/**************************************************************************/
;
;
;#define TX_SOURCE_CODE
;
;
;/* Include necessary system files.  */
;
;#include "tx_api.h"
;#include "tx_initialize.h"
;#include "tx_thread.h"
;#include "tx_timer.h"
;
;
SVC_MODE        EQU     0xD3                    ; Disable IRQ/FIQ SVC mode
IRQ_MODE        EQU     0xD2                    ; Disable IRQ/FIQ IRQ mode
FIQ_MODE        EQU     0xD1                    ; Disable IRQ/FIQ FIQ mode
SYS_MODE        EQU     0xDF                    ; Disable IRQ/FIQ SYS mode
HEAP_SIZE       EQU     4096                    ; Heap size
FIQ_STACK_SIZE  EQU     512                     ; FIQ stack size
SYS_STACK_SIZE  EQU     1024                    ; SYS stack size (used for nested interrupts)
IRQ_STACK_SIZE  EQU     1024                    ; IRQ stack size
;
;
;/* ARM9 ARMulator Timer and Interrupt controller information.  This depends on 
;   the ARMulator's Interrupt Controller and Timer being enabled in the default.ami.
;   In addition, the addresses must match those specified in the peripherals.ami file.
;   Please refer to section 2.10 and 4.16 of the Debug Target Guide, version 1.2.  */
;
IRQStatus       EQU     0x0a000000              ; IRQ Status Register
IRQRawStatus    EQU     0x0a000004              ; IRQ Raw Status Register
IRQEnable       EQU     0x0a000008              ; IRQ Enable Set Register
IRQEnableClear  EQU     0x0a00000C              ; IRQ Enable Clear Register
IRQSoft         EQU     0x0a000010              ; IRQ Soft 
FIQStatus       EQU     0x0a000100              ; FIQ Status Register
FIQRawStatus    EQU     0x0a000104              ; FIQ Raw Status Register
FIQEnable       EQU     0x0a000108              ; FIQ Enable Set Register
FIQEnableClear  EQU     0x0a00010C              ; FIQ Enable Clear Register

TIMER1_BIT      EQU     0x00000010              ; IRQ/FIQ Timer1 bit
TIMER2_BIT      EQU     0x00000020              ; IRQ/FIQ Timer2 bit

Timer1Load      EQU     0x0a800000              ; Timer1 Load Register
Timer1Value     EQU     0x0a800004              ; Timer1 Value Register
Timer1Control   EQU     0x0a800008              ; Timer1 Control Register
Timer1Clear     EQU     0x0a80000C              ; Timer1 Clear Register

Timer1Mode      EQU     0x000000C0              ; Timer1 Control Value, Timer enable, periodic, no prescaler
Timer1Period    EQU     0x0000FFFF              ; Timer1 count-down period, maximum value

Timer2Load      EQU     0x0a800020              ; Timer2 Load Register
Timer2Value     EQU     0x0a800024              ; Timer2 Value Register
Timer2Control   EQU     0x0a800028              ; Timer2 Control Register
Timer2Clear     EQU     0x0a80002C              ; Timer2 Clear Register
;
;
    IMPORT      _tx_thread_system_stack_ptr
    IMPORT      _tx_initialize_unused_memory
    IMPORT      _tx_thread_context_save
    IMPORT      _tx_thread_context_restore
    IF  :DEF:TX_ENABLE_FIQ_SUPPORT
    IMPORT      _tx_thread_fiq_context_save
    IMPORT      _tx_thread_fiq_context_restore
    ENDIF
    IF  :DEF:TX_ENABLE_IRQ_NESTING
    IMPORT      _tx_thread_irq_nesting_start
    IMPORT      _tx_thread_irq_nesting_end
    ENDIF
    IF  :DEF:TX_ENABLE_FIQ_NESTING
    IMPORT      _tx_thread_fiq_nesting_start
    IMPORT      _tx_thread_fiq_nesting_end
    ENDIF
    IMPORT      _tx_timer_interrupt
    IMPORT      __main
    IMPORT      _tx_version_id
    IMPORT      _tx_build_options
    IMPORT      |Image$$ZI$$Limit|
;
;
        AREA  Init, CODE, READONLY
;
;/* Define the ARM9 vector area.  This should be located or copied to 0.  */
;
    EXPORT  __vectors
__vectors
    LDR     pc,=__main                          ; Reset goes to startup function
    LDR     pc,=__tx_undefined                  ; Undefined handler
    LDR     pc,=__tx_swi_interrupt              ; Software interrupt handler
    LDR     pc,=__tx_prefetch_handler           ; Prefetch exception handler
    LDR     pc,=__tx_abort_handler              ; Abort exception handler
    LDR     pc,=__tx_reserved_handler           ; Reserved exception handler
    LDR     pc,=__tx_irq_handler                ; IRQ interrupt handler
    LDR     pc,=__tx_fiq_handler                ; FIQ interrupt handler
;
;
        AREA ||.text||, CODE, READONLY
;/**************************************************************************/ 
;/*                                                                        */ 
;/*  FUNCTION                                               RELEASE        */ 
;/*                                                                        */ 
;/*    _tx_initialize_low_level                             ARM9/AC5       */ 
;/*                                                           6.1          */
;/*  AUTHOR                                                                */
;/*                                                                        */
;/*    William E. Lamie, Microsoft Corporation                             */
;/*                                                                        */
;/*  DESCRIPTION                                                           */
;/*                                                                        */ 
;/*    This function is responsible for any low-level processor            */ 
;/*    initialization, including setting up interrupt vectors, setting     */ 
;/*    up a periodic timer interrupt source, saving the system stack       */ 
;/*    pointer for use in ISR processing later, and finding the first      */ 
;/*    available RAM memory address for tx_application_define.             */ 
;/*                                                                        */ 
;/*  INPUT                                                                 */ 
;/*                                                                        */ 
;/*    None                                                                */ 
;/*                                                                        */ 
;/*  OUTPUT                                                                */ 
;/*                                                                        */ 
;/*    None                                                                */ 
;/*                                                                        */ 
;/*  CALLS                                                                 */ 
;/*                                                                        */ 
;/*    None                                                                */ 
;/*                                                                        */ 
;/*  CALLED BY                                                             */ 
;/*                                                                        */ 
;/*    _tx_initialize_kernel_enter           ThreadX entry function        */ 
;/*                                                                        */ 
;/*  RELEASE HISTORY                                                       */ 
;/*                                                                        */ 
;/*    DATE              NAME                      DESCRIPTION             */
;/*                                                                        */
;/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
;/*                                                                        */
;/**************************************************************************/
;VOID   _tx_initialize_low_level(VOID)
;{
    EXPORT  _tx_initialize_low_level
_tx_initialize_low_level
;
;
;    /****** NOTE ****** We must be in SVC MODE at this point.  Some monitors
;       enter this routine in USER mode and require a software interrupt to
;       change into SVC mode.  */
;
    LDR     r1, =|Image$$ZI$$Limit|             ; Get end of non-initialized RAM area
    LDR     r2, =HEAP_SIZE                      ; Pickup the heap size
    ADD     r1, r2, r1                          ; Setup heap limit
    ADD     r1, r1, #4                          ; Setup stack limit
;
    IF :DEF:TX_ENABLE_IRQ_NESTING
;    /* Setup the system mode stack for nested interrupt support  */
    LDR     r2, =SYS_STACK_SIZE                 ; Pickup stack size
    MOV     r3, #SYS_MODE                       ; Build SYS mode CPSR
    MSR     CPSR_cxsf, r3                       ; Enter SYS mode
    ADD     r1, r1, r2                          ; Calculate start of SYS stack
    BIC     r1, r1, #7                          ; Ensure 8-byte alignment
    MOV     sp, r1                              ; Setup SYS stack pointer
    ENDIF
;
    LDR     r2, =FIQ_STACK_SIZE                 ; Pickup stack size
    MOV     r0, #FIQ_MODE                       ; Build FIQ mode CPSR
    MSR     CPSR_c, r0                          ; Enter FIQ mode
    ADD     r1, r1, r2                          ; Calculate start of FIQ stack
    BIC     r1, r1, #7                          ; Ensure 8-byte alignment
    MOV     sp, r1                              ; Setup FIQ stack pointer
    MOV     sl, #0                              ; Clear sl
    MOV     fp, #0                              ; Clear fp
    LDR     r2, =IRQ_STACK_SIZE                 ; Pickup IRQ (system stack size)
    MOV     r0, #IRQ_MODE                       ; Build IRQ mode CPSR
    MSR     CPSR_c, r0                          ; Enter IRQ mode
    ADD     r1, r1, r2                          ; Calculate start of IRQ stack
    BIC     r1, r1, #7                          ; Ensure 8-byte alignment
    MOV     sp, r1                              ; Setup IRQ stack pointer
    MOV     r0, #SVC_MODE                       ; Build SVC mode CPSR
    MSR     CPSR_c, r0                          ; Enter SVC mode
    LDR     r3, =_tx_thread_system_stack_ptr    ; Pickup stack pointer
    STR     r1, [r3, #0]                        ; Save the system stack
;
;    /* Save the system stack pointer.  */
;    _tx_thread_system_stack_ptr = (VOID_PTR) (sp);
;
    LDR     r1, =_tx_thread_system_stack_ptr    ; Pickup address of system stack ptr
    LDR     r0, [r1, #0]                        ; Pickup system stack 
    ADD     r0, r0, #4                          ; Increment to next free word
;
;    /* Save the first available memory address.  */
;    _tx_initialize_unused_memory =  (VOID_PTR) |Image$$ZI$$Limit| + HEAP + [SYS_STACK] + FIQ_STACK + IRQ_STACK;
;
    LDR     r2, =_tx_initialize_unused_memory   ; Pickup unused memory ptr address
    STR     r0, [r2, #0]                        ; Save first free memory address
;
;    /* Setup Timer for periodic interrupts.  */
;
;    /* Setup ARMulator Timer1 for periodic interrupts.  */
;
    LDR     r0,=IRQEnable                       ; Build address of IRQ enable register
    LDR     r1,=TIMER1_BIT                      ; Build value of Timer1 IRQ enable
    STR     r1,[r0]                             ; Enable IRQ interrupts for Timer1

    LDR     r0,=Timer1Load                      ; Build address of Timer1 load register
    LDR     r1,=Timer1Period                    ; Build Timer1 periodic value
    STR     r1,[r0]                             ; Set Timer1 load value

    LDR     r0,=Timer1Control                   ; Build address of Timer1 control register
    LDR     r1,=Timer1Mode                      ; Build Timer1 control value
    STR     r1,[r0]                             ; Enable Timer1
;
;    /* Done, return to caller.  */
;
    IF  {INTER} = {TRUE}
    BX      lr                                  ; Return to caller
    ELSE
    MOV     pc, lr                              ; Return to caller
    ENDIF
;}
;
;
;/* Define initial heap/stack routine for the ARM RealView (and ADS) startup code.  This
;   routine will set the initial stack to use the ThreadX IRQ & FIQ & 
;   (optionally SYS) stack areas.  */
;
    EXPORT  __user_initial_stackheap
__user_initial_stackheap
    LDR     r0, =|Image$$ZI$$Limit|             ; Get end of non-initialized RAM area
    LDR     r2, =HEAP_SIZE                      ; Pickup the heap size
    ADD     r2, r2, r0                          ; Setup heap limit
    ADD     r3, r2, #4                          ; Setup stack limit
    MOV     r1, r3                              ; Setup start of stack
    IF :DEF:TX_ENABLE_IRQ_NESTING
    LDR     r12, =SYS_STACK_SIZE                ; Pickup IRQ system stack
    ADD     r1, r1, r12                         ; Setup the return system stack
    BIC     r1, r1, #7                          ; Ensure 8-byte alignment
    ENDIF
    LDR     r12, =FIQ_STACK_SIZE                ; Pickup FIQ stack size
    ADD     r1, r1, r12                         ; Setup the return system stack
    BIC     r1, r1, #7                          ; Ensure 8-byte alignment
    LDR     r12, =IRQ_STACK_SIZE                ; Pickup IRQ system stack
    ADD     r1, r1, r12                         ; Setup the return system stack
    BIC     r1, r1, #7                          ; Ensure 8-byte alignment
    IF  {INTER} = {TRUE}
    BX      lr                                  ; Return to caller
    ELSE
    MOV     pc, lr                              ; Return to caller
    ENDIF
;
;
;/* Define shells for each of the interrupt vectors.  */
;
    EXPORT  __tx_undefined
__tx_undefined
    B       __tx_undefined                      ; Undefined handler
;
    EXPORT  __tx_swi_interrupt
__tx_swi_interrupt
    B       __tx_swi_interrupt                  ; Software interrupt handler
;
    EXPORT  __tx_prefetch_handler
__tx_prefetch_handler
    B       __tx_prefetch_handler               ; Prefetch exception handler
;
    EXPORT  __tx_abort_handler
__tx_abort_handler
    B       __tx_abort_handler                  ; Abort exception handler
;
    EXPORT  __tx_reserved_handler
__tx_reserved_handler
    B       __tx_reserved_handler               ; Reserved exception handler
;
;
    EXPORT  __tx_irq_handler
    EXPORT  __tx_irq_processing_return      
__tx_irq_handler
;
;    /* Jump to context save to save system context.  */
    B       _tx_thread_context_save
__tx_irq_processing_return
;
;    /* At this point execution is still in the IRQ mode.  The CPSR, point of
;       interrupt, and all C scratch registers are available for use.  In 
;       addition, IRQ interrupts may be re-enabled - with certain restrictions -
;       if nested IRQ interrupts are desired.  Interrupts may be re-enabled over
;       small code sequences where lr is saved before enabling interrupts and 
;       restored after interrupts are again disabled.  */
;
;
;    /* Check for Timer1 interrupts on the ARMulator.  */

    LDR     r1,=IRQStatus                       ; Pickup address of IRQStatus register
    LDR     r2, [r1]                            ; Read IRQStatus 
    LDR     r0,=TIMER1_BIT                      ; Pickup Timer1 interrupt present bit
    AND     r2, r2, r0                          ; Is this a timer interrupt?
    CMP     r2, r0                              ; 
    BNE     _tx_not_timer_interrupt             ; If 0, not a timer interrupt

    LDR     r1,=Timer1Clear                     ; Build address of Timer1 clear register
    MOV     r0,#0                               ; 
    STR     r0, [r1]                            ; Clear timer 0 interrupt

    BL      _tx_timer_interrupt                 ; Timer interrupt handler
_tx_not_timer_interrupt
;
;    /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start 
;       from IRQ mode with interrupts disabled.  This routine switches to the
;       system mode and returns with IRQ interrupts enabled.  
;       
;       NOTE:  It is very important to ensure all IRQ interrupts are cleared 
;       prior to enabling nested IRQ interrupts.  */
    IF :DEF:TX_ENABLE_IRQ_NESTING
    BL      _tx_thread_irq_nesting_start
    ENDIF
;
;
;    /* Application IRQ handlers can be called here!  */
;
;    /* If interrupt nesting was started earlier, the end of interrupt nesting
;       service must be called before returning to _tx_thread_context_restore.  
;       This routine returns in processing in IRQ mode with interrupts disabled.  */
    IF :DEF:TX_ENABLE_IRQ_NESTING
    BL      _tx_thread_irq_nesting_end
    ENDIF
;
;    /* Jump to context restore to restore system context.  */
    B       _tx_thread_context_restore
;
;
;    /* This is an example of a vectored IRQ handler.  */
;
    EXPORT  __tx_example_vectored_irq_handler
__tx_example_vectored_irq_handler
;
;
;    /* Save initial context and call context save to prepare for 
;       vectored ISR execution.  */
;
;    STMDB   sp!, {r0-r3}                        ; Save some scratch registers
;    MRS     r0, SPSR                            ; Pickup saved SPSR
;    SUB     lr, lr, #4                          ; Adjust point of interrupt 
;    STMDB   sp!, {r0, r10, r12, lr}             ; Store other scratch registers
;    BL      _tx_thread_vectored_context_save    ; Vectored context save
;
;    /* At this point execution is still in the IRQ mode.  The CPSR, point of
;       interrupt, and all C scratch registers are available for use.  In 
;       addition, IRQ interrupts may be re-enabled - with certain restrictions -
;       if nested IRQ interrupts are desired.  Interrupts may be re-enabled over
;       small code sequences where lr is saved before enabling interrupts and 
;       restored after interrupts are again disabled.  */
;
;
;    /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start 
;       from IRQ mode with interrupts disabled.  This routine switches to the
;       system mode and returns with IRQ interrupts enabled.  
;       
;       NOTE:  It is very important to ensure all IRQ interrupts are cleared 
;       prior to enabling nested IRQ interrupts.  */
;    IF :DEF:TX_ENABLE_IRQ_NESTING
;    BL      _tx_thread_irq_nesting_start
;    ENDIF
;
;    /* Application IRQ handlers can be called here!  */
;
;    /* If interrupt nesting was started earlier, the end of interrupt nesting
;       service must be called before returning to _tx_thread_context_restore.  
;       This routine returns in processing in IRQ mode with interrupts disabled.  */
;    IF :DEF:TX_ENABLE_IRQ_NESTING
;    BL      _tx_thread_irq_nesting_end
;    ENDIF
;
;    /* Jump to context restore to restore system context.  */
;    B       _tx_thread_context_restore
;
;
    IF  :DEF:TX_ENABLE_FIQ_SUPPORT
    EXPORT  __tx_fiq_handler
    EXPORT  __tx_fiq_processing_return
__tx_fiq_handler
;
;    /* Jump to fiq context save to save system context.  */
    B       _tx_thread_fiq_context_save
__tx_fiq_processing_return
;
;    /* At this point execution is still in the FIQ mode.  The CPSR, point of
;       interrupt, and all C scratch registers are available for use.  */
;
;    /* Interrupt nesting is allowed after calling _tx_thread_fiq_nesting_start 
;       from FIQ mode with interrupts disabled.  This routine switches to the
;       system mode and returns with FIQ interrupts enabled. 
;
;       NOTE:  It is very important to ensure all FIQ interrupts are cleared 
;       prior to enabling nested FIQ interrupts.  */
    IF  :DEF:TX_ENABLE_FIQ_NESTING
    BL      _tx_thread_fiq_nesting_start
    ENDIF
;
;    /* Application FIQ handlers can be called here!  */
;
;    /* If interrupt nesting was started earlier, the end of interrupt nesting
;       service must be called before returning to _tx_thread_fiq_context_restore.  */
    IF  :DEF:TX_ENABLE_FIQ_NESTING
    BL      _tx_thread_fiq_nesting_end
    ENDIF
;
;    /* Jump to fiq context restore to restore system context.  */
    B       _tx_thread_fiq_context_restore
;
;
    ELSE
    EXPORT  __tx_fiq_handler
__tx_fiq_handler
    B       __tx_fiq_handler                    ; FIQ interrupt handler
    ENDIF
;
;    /* Reference build options and version ID to ensure they come in.  */
;
    LDR     r2, =_tx_build_options              ; Pickup build options variable address
    LDR     r0, [r2, #0]                        ; Pickup build options content
    LDR     r2, =_tx_version_id                 ; Pickup version ID variable address
    LDR     r0, [r2, #0]                        ; Pickup version ID content
;
;
    END


IAR:
[Asm] 纯文本查看 复制代码
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Part one of the system initialization code, 
;; contains low-level
;; initialization.
;;
;; Copyright 2007 IAR Systems. All rights reserved.
;;
;; $Revision: 14520 $
;;

        MODULE  ?cstartup

        ;; Forward declaration of sections.
        SECTION IRQ_STACK:DATA:NOROOT(3)
        SECTION FIQ_STACK:DATA:NOROOT(3)
        SECTION CSTACK:DATA:NOROOT(3)

;
; The module in this file are included in the libraries, and may be
; replaced by any user-defined modules that define the PUBLIC symbol
; __iar_program_start or a user defined start symbol.
;
; To override the cstartup defined in the library, simply add your
; modified version to the workbench project.

        SECTION .intvec:CODE:NOROOT(2)

        PUBLIC  __vector
        PUBLIC  __vector_0x14
        PUBLIC  __iar_program_start
        EXTERN  __tx_undefined
        EXTERN  __tx_swi_interrupt
        EXTERN  __tx_prefetch_handler
        EXTERN  __tx_abort_handler
        EXTERN  __tx_irq_handler
        EXTERN  __tx_fiq_handler

        ARM
__vector:
        ; All default exception handlers (except reset) are
        ; defined as weak symbol definitions.
        ; If a handler is defined by the application it will take precedence.
        LDR     PC,Reset_Addr           ; Reset
        LDR     PC,Undefined_Addr       ; Undefined instructions
        LDR     PC,SWI_Addr             ; Software interrupt (SWI/SVC)
        LDR     PC,Prefetch_Addr        ; Prefetch abort
        LDR     PC,Abort_Addr           ; Data abort
__vector_0x14:
        DCD     0                       ; RESERVED
        LDR     PC,IRQ_Addr             ; IRQ
        LDR     PC,FIQ_Addr             ; FIQ

Reset_Addr:     DCD   __iar_program_start
Undefined_Addr: DCD   __tx_undefined
SWI_Addr:       DCD   __tx_swi_interrupt
Prefetch_Addr:  DCD   __tx_prefetch_handler
Abort_Addr:     DCD   __tx_abort_handler
IRQ_Addr:       DCD   __tx_irq_handler
FIQ_Addr:       DCD   __tx_fiq_handler

; --------------------------------------------------
; ?cstartup -- low-level system initialization code.
;
; After a reser execution starts here, the mode is ARM, supervisor
; with interrupts disabled.
;



        SECTION .text:CODE:NOROOT(2)

;        PUBLIC  ?cstartup        
        EXTERN  ?main
        REQUIRE __vector

        ARM        
        
__iar_program_start:        
?cstartup:

;
; Add initialization needed before setup of stackpointers here.
;

;
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
;


; --------------------
; Mode, correspords to bits 0-5 in CPSR

MODE_MSK DEFINE 0x1F            ; Bit mask for mode bits in CPSR

USR_MODE DEFINE 0x10            ; User mode
FIQ_MODE DEFINE 0x11            ; Fast Interrupt Request mode
IRQ_MODE DEFINE 0x12            ; Interrupt Request mode
SVC_MODE DEFINE 0x13            ; Supervisor mode
ABT_MODE DEFINE 0x17            ; Abort mode
UND_MODE DEFINE 0x1B            ; Undefined Instruction mode
SYS_MODE DEFINE 0x1F            ; System mode


        MRS     r0, cpsr                ; Original PSR value

        ;; Set up the interrupt stack pointer.

        BIC     r0, r0, #MODE_MSK       ; Clear the mode bits
        ORR     r0, r0, #IRQ_MODE       ; Set IRQ mode bits
        MSR     cpsr_c, r0              ; Change the mode
        LDR     sp, =SFE(IRQ_STACK)     ; End of IRQ_STACK

        ;; Set up the fast interrupt stack pointer.

        BIC     r0, r0, #MODE_MSK       ; Clear the mode bits
        ORR     r0, r0, #FIQ_MODE       ; Set FIR mode bits
        MSR     cpsr_c, r0              ; Change the mode
        LDR     sp, =SFE(FIQ_STACK)     ; End of FIQ_STACK

        ;; Set up the normal stack pointer.

        BIC     r0 ,r0, #MODE_MSK       ; Clear the mode bits
        ORR     r0 ,r0, #SYS_MODE       ; Set System mode bits
        MSR     cpsr_c, r0              ; Change the mode
        LDR     sp, =SFE(CSTACK)        ; End of CSTACK

#ifdef __ARMVFP__
        ;; Enable the VFP coprocessor.

        MOV     r0, #0x40000000         ; Set EN bit in VFP
        FMXR    fpexc, r0               ; FPEXC, clear others.

;
; Disable underflow exceptions by setting flush to zero mode.
; For full IEEE 754 underflow compliance this code should be removed
; and the appropriate exception handler installed.
;

        MOV     r0, #0x01000000         ; Set FZ bit in VFP
        FMXR    fpscr, r0               ; FPSCR, clear others.
#endif

;
; Add more initialization here
;

; Continue to ?main for C-level initialization.

        B       ?main

        END



;/***************************************************************************
; * Copyright (c) 2024 Microsoft Corporation 
; * 
; * This program and the accompanying materials are made available under the
; * terms of the MIT License which is available at
; * [url]https://opensource.org/licenses/MIT.[/url]
; * 
; * SPDX-License-Identifier: MIT
; **************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/**                                                                       */ 
;/** ThreadX Component                                                     */ 
;/**                                                                       */
;/**   Initialize                                                          */
;/**                                                                       */
;/**************************************************************************/
;/**************************************************************************/
;
;
;#define TX_SOURCE_CODE
;
;
;/* Include necessary system files.  */
;
;#include "tx_api.h"
;#include "tx_initialize.h"
;#include "tx_thread.h"
;#include "tx_timer.h"
;
;
SVC_MODE        DEFINE  0xD3                    ; Disable irq,fiq SVC mode
IRQ_MODE        DEFINE  0xD2                    ; Disable irq,fiq IRQ mode
FIQ_MODE        DEFINE  0xD1                    ; Disable irq,fiq FIQ mode
SYS_MODE        DEFINE  0xDF                    ; Disable irq,fiq SYS mode
;
;

    EXTERN      _tx_thread_system_stack_ptr
    EXTERN      _tx_initialize_unused_memory
    EXTERN      _tx_thread_context_save
;    EXTERN      _tx_thread_vectored_context_save
    EXTERN      _tx_thread_context_restore
#ifdef TX_ENABLE_FIQ_SUPPORT
    EXTERN      _tx_thread_fiq_context_save
    EXTERN      _tx_thread_fiq_context_restore
#endif
#ifdef TX_ENABLE_IRQ_NESTING
    EXTERN      _tx_thread_irq_nesting_start
    EXTERN      _tx_thread_irq_nesting_end
#endif
#ifdef TX_ENABLE_FIQ_NESTING
    EXTERN      _tx_thread_fiq_nesting_start
    EXTERN      _tx_thread_fiq_nesting_end
#endif
    EXTERN      _tx_timer_interrupt
    EXTERN      ?cstartup
    EXTERN      _tx_build_options
    EXTERN      _tx_version_id
;
;
;
;/* Define the FREE_MEM segment that will specify where free memory is 
;   defined.  This must also be located in at the end of other RAM segments
;   in the linker control file.  The value of this segment is what is passed
;   to tx_application_define.  */
;
    RSEG    FREE_MEM:DATA
    PUBLIC  __tx_free_memory_start
__tx_free_memory_start
    DS32    4
;
;
;
;
;/**************************************************************************/ 
;/*                                                                        */ 
;/*  FUNCTION                                               RELEASE        */ 
;/*                                                                        */ 
;/*    _tx_initialize_low_level                            ARM11/IAR       */ 
;/*                                                            6.1         */ 
;/*  AUTHOR                                                                */ 
;/*                                                                        */ 
;/*    William E. Lamie, Microsoft Corporation                             */ 
;/*                                                                        */ 
;/*  DESCRIPTION                                                           */ 
;/*                                                                        */ 
;/*    This function is responsible for any low-level processor            */ 
;/*    initialization, including setting up interrupt vectors, setting     */ 
;/*    up a periodic timer interrupt source, saving the system stack       */ 
;/*    pointer for use in ISR processing later, and finding the first      */ 
;/*    available RAM memory address for tx_application_define.             */ 
;/*                                                                        */ 
;/*  INPUT                                                                 */ 
;/*                                                                        */ 
;/*    None                                                                */ 
;/*                                                                        */ 
;/*  OUTPUT                                                                */ 
;/*                                                                        */ 
;/*    None                                                                */ 
;/*                                                                        */ 
;/*  CALLS                                                                 */ 
;/*                                                                        */ 
;/*    None                                                                */ 
;/*                                                                        */ 
;/*  CALLED BY                                                             */ 
;/*                                                                        */ 
;/*    _tx_initialize_kernel_enter           ThreadX entry function        */ 
;/*                                                                        */ 
;/*  RELEASE HISTORY                                                       */ 
;/*                                                                        */ 
;/*    DATE              NAME                      DESCRIPTION             */ 
;/*                                                                        */ 
;/*  09-30-2020     William E. Lamie         Initial Version 6.1           */ 
;/*                                                                        */ 
;/**************************************************************************/ 
;VOID   _tx_initialize_low_level(VOID)
;{
    RSEG    .text:CODE:NOROOT(2)
    CODE32
    PUBLIC  _tx_initialize_low_level
_tx_initialize_low_level
;
;    /****** NOTE ****** The IAR 4.11a and above releases call main in SYS mode.  */
;
;    /* Remember the stack pointer, link register, and switch to SVC mode.  */
;
    MOV     r0, sp                              ; Remember the SP
    MOV     r1, lr                              ; Remember the LR
    MOV     r3, #SVC_MODE                       ; Build SVC mode CPSR
    MSR     CPSR_cxsf, r3                       ; Switch to SVC mode
    MOV     sp, r0                              ; Inherit the stack pointer setup by cstartup
    MOV     lr, r1                              ; Inherit the link register
;
;    /* Pickup the start of free memory.  */
;
    LDR     r0, =__tx_free_memory_start         ; Get end of non-initialized RAM area
;
;    /* Save the system stack pointer.  */
;    _tx_thread_system_stack_ptr = (VOID_PTR) (sp);
;
;    /* Save the first available memory address.  */
;    _tx_initialize_unused_memory =  (VOID_PTR) FREE_MEM;
;
    LDR     r2, =_tx_initialize_unused_memory   ; Pickup unused memory ptr address
    STR     r0, [r2, #0]                        ; Save first free memory address
;                      
;    /* Setup Timer for periodic interrupts.  */
;
;    /* Done, return to caller.  */
;
#ifdef TX_THUMB
    BX      lr                                  ; Return to caller
#else
    MOV     pc, lr                              ; Return to caller
#endif
;}
;
;/* Define shells for each of the interrupt vectors.  */
;
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_undefined
__tx_undefined
    B       __tx_undefined                      ; Undefined handler
;
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_swi_interrupt
__tx_swi_interrupt
    B       __tx_swi_interrupt                  ; Software interrupt handler
;
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_prefetch_handler
__tx_prefetch_handler
    B       __tx_prefetch_handler               ; Prefetch exception handler
;
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_abort_handler
__tx_abort_handler
    B       __tx_abort_handler                  ; Abort exception handler
;
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_reserved_handler
__tx_reserved_handler
    B       __tx_reserved_handler               ; Reserved exception handler
;
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_irq_handler
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_irq_processing_return      
__tx_irq_handler
;
;    /* Jump to context save to save system context.  */
    B       _tx_thread_context_save
__tx_irq_processing_return
;
;    /* At this point execution is still in the IRQ mode.  The CPSR, point of
;       interrupt, and all C scratch registers are available for use.  In 
;       addition, IRQ interrupts may be re-enabled - with certain restrictions -
;       if nested IRQ interrupts are desired.  Interrupts may be re-enabled over
;       small code sequences where lr is saved before enabling interrupts and 
;       restored after interrupts are again disabled.  */
;
;    /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start 
;       from IRQ mode with interrupts disabled.  This routine switches to the
;       system mode and returns with IRQ interrupts enabled.  
;       
;       NOTE:  It is very important to ensure all IRQ interrupts are cleared 
;       prior to enabling nested IRQ interrupts.  */
#ifdef TX_ENABLE_IRQ_NESTING
    BL      _tx_thread_irq_nesting_start
#endif
;
;    /* For debug purpose, execute the timer interrupt processing here.  In
;       a real system, some kind of status indication would have to be checked
;       before the timer interrupt handler could be called.  */
;
    BL      _tx_timer_interrupt                 ; Timer interrupt handler
;
;    /* Application IRQ handlers can be called here!  */
;
;    /* If interrupt nesting was started earlier, the end of interrupt nesting
;       service must be called before returning to _tx_thread_context_restore.  
;       This routine returns in processing in IRQ mode with interrupts disabled.  */
#ifdef TX_ENABLE_IRQ_NESTING
    BL      _tx_thread_irq_nesting_end
#endif
;
;    /* Jump to context restore to restore system context.  */
    B       _tx_thread_context_restore
;
;
;    /* This is an example of a vectored IRQ handler.  */
;
;    RSEG    .text:CODE:NOROOT(2)
;    PUBLIC  __tx_example_vectored_irq_handler
;__tx_example_vectored_irq_handler
;
;    /* Jump to context save to save system context.  */
;    STMDB   sp!, {r0-r3}                    ; Save some scratch registers
;    MRS     r0, SPSR                        ; Pickup saved SPSR
;    SUB     lr, lr, #4                      ; Adjust point of interrupt 
;    STMDB   sp!, {r0, r10, r12, lr}         ; Store other registers
;    BL      _tx_thread_vectored_context_save
;
;    /* At this point execution is still in the IRQ mode.  The CPSR, point of
;       interrupt, and all C scratch registers are available for use.  In 
;       addition, IRQ interrupts may be re-enabled - with certain restrictions -
;       if nested IRQ interrupts are desired.  Interrupts may be re-enabled over
;       small code sequences where lr is saved before enabling interrupts and 
;       restored after interrupts are again disabled.  */
;
;    /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start 
;       from IRQ mode with interrupts disabled.  This routine switches to the
;       system mode and returns with IRQ interrupts enabled.  
;       
;       NOTE:  It is very important to ensure all IRQ interrupts are cleared 
;       prior to enabling nested IRQ interrupts.  */
;#ifdef TX_ENABLE_IRQ_NESTING
;    BL      _tx_thread_irq_nesting_start
;#endif
;
;    /* Application IRQ handler is called here!  */
;
;    /* If interrupt nesting was started earlier, the end of interrupt nesting
;       service must be called before returning to _tx_thread_context_restore.  
;       This routine returns in processing in IRQ mode with interrupts disabled.  */
;#ifdef TX_ENABLE_IRQ_NESTING
;    BL      _tx_thread_irq_nesting_end
;#endif
;
;    /* Jump to context restore to restore system context.  */
;    B       _tx_thread_context_restore
;
;
#ifdef TX_ENABLE_FIQ_SUPPORT
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_fiq_handler
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_fiq_processing_return
__tx_fiq_handler
;
;    /* Jump to fiq context save to save system context.  */
    B       _tx_thread_fiq_context_save
__tx_fiq_processing_return
;
;    /* At this point execution is still in the FIQ mode.  The CPSR, point of
;       interrupt, and all C scratch registers are available for use.  */
;
;    /* Interrupt nesting is allowed after calling _tx_thread_fiq_nesting_start 
;       from FIQ mode with interrupts disabled.  This routine switches to the
;       system mode and returns with FIQ interrupts enabled. 
;
;       NOTE:  It is very important to ensure all FIQ interrupts are cleared 
;       prior to enabling nested FIQ interrupts.  */
#ifdef TX_ENABLE_FIQ_NESTING
    BL      _tx_thread_fiq_nesting_start
#endif
;
;    /* Application FIQ handlers can be called here!  */
;
;    /* If interrupt nesting was started earlier, the end of interrupt nesting
;       service must be called before returning to _tx_thread_fiq_context_restore.  */
#ifdef TX_ENABLE_FIQ_NESTING
    BL      _tx_thread_fiq_nesting_end
#endif
;
;    /* Jump to fiq context restore to restore system context.  */
    B       _tx_thread_fiq_context_restore
;
;
#else
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  __tx_fiq_handler
__tx_fiq_handler
    B       __tx_fiq_handler                    ; FIQ interrupt handler
#endif
;
;
BUILD_OPTIONS
    DC32    _tx_build_options                   ; Reference to ensure it comes in
VERSION_ID
    DC32    _tx_version_id                      ; Reference to ensure it comes in
    END

回复

使用道具 举报

2

主题

71

回帖

77

积分

初级会员

积分
77
发表于 2025-9-2 16:35:56 | 显示全部楼层
Sam_wang 发表于 2025-9-1 08:22
继续跟进,欢迎大神来讨论:
再看ThreadX源码时发现,AC5与IAR的启动代码有很大的差别,其中AC5中直接将 ...

38楼的这个可以用么?
NUC972下threadx移植
https://forum.anfulai.cn/forum.p ... 2&fromuid=39090
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
发表于 2025-9-3 09:09:23 | 显示全部楼层
sup999 发表于 2025-9-2 16:35
38楼的这个可以用么?
NUC972下threadx移植
https://forum.anfulai.cn/forum.p ... 2&fromuid=39090

KEIL 下没尝试,用同样的方法在IAR环境下任务不执行
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-9-26 18:47 , Processed in 0.053438 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表