flyaqiao 发表于 2023-10-26 19:45:33

NUC972下threadx移植

本帖最后由 flyaqiao 于 2023-10-26 19:46 编辑

项目需要,使用的nuc972主芯片,需要支持网络协议,就打算移植一下azure的tx,filex,netxduo,下面新记录一下tx的移植过程:
由于新唐的arm9中断处理和定时器初始化的寄存器并不同于tx官方的arm9的port,所以官方的port无法正常运行.1.首先从github下载最新的tx代码.
git clone https://github.com/azure-rtos/threadx.git2.创建tx的keil工程,nuc972官方没有提供iar工程,所以这里都使用keil,编译成lib的形式.
项目结构:
共三个目录:将tx的common/src目录下的所有文件添加到src目录
将tx的common/inc目录下的所有文件添加到inc目录
将tx的ports/arm9/ac5/inc目录下的所有文件添加到inc目录(其实就一个tx_port.h)
将tx的ports/arm9/ac5/src目录下的所有文件添加到port目录
如图:
https://whycan.com/files/members/12991/%E5%B7%A5%E7%A8%8B%E7%BB%93%E6%9E%84.png
设置DEVICE:
https://whycan.com/files/members/12991/%E5%B7%A5%E7%A8%8BDEV.png
设置Output:
https://whycan.com/files/members/12991/%E5%B7%A5%E7%A8%8BLIB.png
设置Include:
https://whycan.com/files/members/12991/%E5%B7%A5%E7%A8%8BINC.png
编译生成tx.lib文件备用,也可以直接下载工程文件并到tx根目录下:tx_lib_20231026182439.rar
https://whycan.com/files/members/12991/%E5%B7%A5%E7%A8%8B%E6%96%87%E4%BB%B6.png
以上就是tx库的生成过程3.打开新唐官方Non-OS BSP中的hello工程
将刚才生成的tx.lib放到hello目录下
将ports/arm9/ac5/example_build下的tx_initialize_low_level.s放到hello目录下,移植的主要工作就是修改这个文件,这里先放上我移植好的文件
tx_initialize_low_level_20231026183734.rar
打开工程加入刚才的两个文件,并在项目中排除startup_NUC970.s文件
https://whycan.com/files/members/12991/hello-2.pnghttps://whycan.com/files/members/12991/hello-1.png
此时编译项目应该没有错误
移植之前先修改sys.c文件,删除注册中断回调时的sysInitializeAIC调用
https://whycan.com/files/members/12991/hello-3.png
中断入口将由tx_initialize_low_level.s中的__tx_irq_handler接管,所以不能再动态修改中断入口;/**************************************************************************/;/*                                                                        */;/*       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 https://aka.ms/AzureRTOS_EULA       */;/*       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      EQU   0xD3               ; Disable IRQ/FIQ SVC modeIRQ_MODE      EQU   0xD2               ; Disable IRQ/FIQ IRQ modeFIQ_MODE      EQU   0xD1               ; Disable IRQ/FIQ FIQ modeSYS_MODE      EQU   0xDF               ; Disable IRQ/FIQ SYS modeHEAP_SIZE       EQU   4096               ; Heap sizeUND_STACK_SIZEEQU   256ABT_STACK_SIZEEQU   256FIQ_STACK_SIZEEQU   512                  ; FIQ stack sizeSVC_STACK_SIZEEQU   1024SYS_STACK_SIZEEQU   1024               ; SYS stack size (used for nested interrupts)IRQ_STACK_SIZEEQU   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.*/;TMR0_CLK      EQU   0x00E4E1C0TMR0_IRQn       EQU   16REG_TMR_TISR    EQU   0xB8001060; Timer Interrupt Status RegisterREG_AIC_BA      EQU   0xB8002000; Interrupt ControllerREG_AIC_IPER    EQU   0xB8002118; Interrupt priority encoding registerREG_AIC_ISNR    EQU   0xB8002120; Interrupt source number registerREG_AIC_MDCR    EQU   0xB8002138; Mask disable command registerREG_AIC_MDCRH   EQU   0xB800213C; Mask disable command register (High)REG_AIC_EOSCR   EQU   0xB8002150;;    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      sysIrqHandlerTable    IMPORT      sysSetTimerReferenceClock    IMPORT      sysStartTimer    IMPORT      sysGetSdramSizebyMB    IMPORT      |Image$$RW_RAM1$$ZI$$Limit|;    AREA NUC_INIT, CODE, READONLY;;/* Define the ARM9 vector area.This should be located or copied to 0.*/;    ENTRY    EXPORTReset_Go    EXPORT__vectors__vectors    B       Reset_Go    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;;Reset_Go    ; Disable Interrupt in case code is load by ICE while other firmware is executing    LDR    r0, =REG_AIC_MDCR    LDR    r1, =0xFFFFFFFF    STR    r1,     LDR    r0, =REG_AIC_MDCRH    STR    r1,     ;--------------------------------    ; Initial Stack Pointer register    ;--------------------------------    ;INIT_STACK    LDR   r1, =|Image$$RW_RAM1$$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;    /* 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_c, 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    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    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    LDR   r2, =SVC_STACK_SIZE               ; Pickup SVC (SVC stack size)    MOV   r0, #SVC_MODE                     ; Build SVC mode CPSR    MSR   CPSR_c, r0                        ; Enter SVC mode    ADD   r1, r1, r2                        ; Calculate start of SVC stack    BIC   r1, r1, #7                        ; Ensure 8-byte alignment    MOV   sp, r1                              ; Setup SVC stack pointe    ;------------------------------------------------------    ; 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    MCR p15, 0, r0 , c1, c0   ; cp15 register 1 := r0    IMPORT__main    ;-----------------------------    ;   enter the C code    ;-----------------------------    B   __main    AREA ||.text||, CODE, READONLY;/**************************************************************************/ ;/*                                                                        */ ;/*FUNCTION                                             RELEASE      */ ;/*                                                                        */ ;/*    _tx_initialize_low_level                           ARM9/AC5       */ ;/*                                                         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);{    EXPORT_tx_initialize_low_level_tx_initialize_low_level    PRESERVE8;;;    /****** 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   r2, =SVC_STACK_SIZE               ; Pickup SVC    MOV   r0, #SVC_MODE                     ; Build SVC mode CPSR    MSR   CPSR_c, r0                        ; Enter SVC mode    MOV   r1, sp    ADD   r1, r1, r2                        ; Calculate start of SVC stack    LDR   r3, =_tx_thread_system_stack_ptr    ; Pickup stack pointer    STR   r1,                         ; 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,                         ; 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 + + FIQ_STACK + IRQ_STACK;;    LDR   r2, =_tx_initialize_unused_memory   ; Pickup unused memory ptr address    STR   r0,                         ; Save first free memory address;;    /* Setup Timer for periodic interrupts.*/;;    /* Setup ARMulator Timer0 for periodic interrupts.*/    PUSH    {lr}                              ; Save ISR lr    LDR   r1,=TMR0_CLK    MOV   r0,#0    BL      sysSetTimerReferenceClock    MOV   r2,#1                               ; PERIODIC_MODE    MOV   r1,#0x64                            ; TX_TIMER_TICKS_PER_SECOND    MOV   r0,#0                               ; TIMER0    BL      sysStartTimer    POP   {lr}                              ; Recover ISR lr;    /* 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 Timer0 interrupts on the ARMulator.*/    LDR   r0,=REG_AIC_IPER    LDR   r0,    MOV   r1,#0x3f    AND   r0,r1,r0,LSR #2    PUSH    {r0}    LDR   r2,=TMR0_IRQn                     ; Pickup Timer0 interrupt present bit    CMP   r2, r0                              ;   BNE   _tx_not_timer_interrupt             ; If 0, not a timer interrupt    LDR   r0,=REG_TMR_TISR    LDR   r0,    AND   r0,r0,#1    CMP   r0,#0    BEQ   _tx_not_timer_interrupt    LDR   r1,=REG_TMR_TISR                  ; Build address of Timer0 clear register    MOV   r0,#1                               ;   STR   r0,                             ; 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!*/;; LDR   r0,=REG_AIC_IPER; LDR   r0,; MOV   r1,#0x3f; AND   r0,r1,r0,LSR #2    POP   {r0}    SUB   sp,sp,#8    STR   r0,    LDR   r0,=REG_AIC_ISNR    LDR   r0,    STR   r0,    LDR   r0,    CMP   r0,#0    BEQ   _irq_exit    LDR   r0,    CMP   r0,#0    BEQ   _irq_clear    LDR   r1,=sysIrqHandlerTable    LDR   r2,    LDR   r0,    BLX   r0_irq_clear    MOV   r0,#1    LDR   r1,=REG_AIC_EOSCR    STR   r0,_irq_exit    ADD      sp,sp,#8;    /* 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,                         ; Pickup build options content    LDR   r2, =_tx_version_id               ; Pickup version ID variable address    LDR   r0,                         ; Pickup version ID content;;    END
这个代码主要干以下任务:
__vectors初始化中断向量表
Reset_Go程序入口,初始化AIC和堆栈,并跳转main函数
_tx_initialize_low_level是tx_kernel_enter调用,用来初始化timer0做为OS的tick定时器,并初始化_tx_thread_system_stack_ptr和_tx_initialize_unused_memory
后的就是中断处理函数,主要是__tx_irq_handler    LDR   r0,=REG_AIC_IPER    LDR   r0,    MOV   r1,#0x3f    AND   r0,r1,r0,LSR #2    PUSH    {r0}    LDR   r2,=TMR0_IRQn                     ; Pickup Timer0 interrupt present bit    CMP   r2, r0                              ;   BNE   _tx_not_timer_interrupt             ; If 0, not a timer interrupt    LDR   r0,=REG_TMR_TISR    LDR   r0,    AND   r0,r0,#1    CMP   r0,#0    BEQ   _tx_not_timer_interrupt    LDR   r1,=REG_TMR_TISR                  ; Build address of Timer0 clear register    MOV   r0,#1                               ;   STR   r0,                             ; Clear timer 0 interrupt    BL      _tx_timer_interrupt               ; Timer interrupt handler
这段代码检查是不是Timer0定时器中断,如果是则调用_tx_timer_interrupt,否则跳转到_tx_not_timer_interrupt执行正常中断处理
这里的PUSH    {r0}注意,由于REG_AIC_IPER只能读取一次,这里压栈保存,方便后面正常中断处理使用    POP   {r0}                        ; 弹出前面压入的中断号    SUB   sp,sp,#8                  ; 在栈中为临时变量留出空间    STR   r0,    LDR   r0,=REG_AIC_ISNR    LDR   r0,    STR   r0,    LDR   r0,    CMP   r0,#0    BEQ   _irq_exit    LDR   r0,    CMP   r0,#0    BEQ   _irq_clear    LDR   r1,=sysIrqHandlerTable    LDR   r2,    LDR   r0,    BLX   r0_irq_clear    MOV   r0,#1    LDR   r1,=REG_AIC_EOSCR    STR   r0,_irq_exit    ADD      sp,sp,#8   ; 返还临时变量占用的空间
这就是正常中断处理了,作用等同于sys.c中的sysIrqHandler函数
移植到此就完成了
4.验证
修改main.c文件/**************************************************************************//** * @file   main.c * @versionV1.00 * $Date: 15/05/07 5:38p $ * @brief    NUC970 Driver Sample Code * * @note * Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved. ******************************************************************************/#include "nuc970.h"#include "sys.h"#include "tx_api.h"#define DEMO_STACK_SIZE         (1024 * 32)#define DEMO_BYTE_POOL_SIZE   (1024 * 1024)TX_THREAD               thread_0;TX_THREAD               thread_1;TX_THREAD               thread_2;TX_BYTE_POOL            byte_pool_0;TX_EVENT_FLAGS_GROUP    event_flags_0;UINT thread_0_counter = 0;/* Define what the initial system looks like.*/void thread_0_entry(ULONG thread_input){UINT status;/* This thread simply sits in while-forever-sleep loop.*/while (1) {    /* Increment the thread counter.*/    thread_0_counter++;    /* Sleep for 10 ticks.*/    if (thread_0_counter & 1)      tx_thread_sleep(TX_TIMER_TICKS_PER_SECOND / 10);    else      tx_thread_sleep(TX_TIMER_TICKS_PER_SECOND);    /* Set event flag 0 to wakeup thread 5.*/    status =tx_event_flags_set(&event_flags_0, 0x1, TX_OR);    /* Check status.*/    if (status != TX_SUCCESS)      break;}}void thread_1_entry(ULONG thread_input){UINT    status;ULONG   actual_flags;/* This thread simply waits for an event in a forever loop.*/while (1) {    /* Wait for event flag 0.*/    status =tx_event_flags_get(&event_flags_0, 0x1, TX_OR_CLEAR,                                 &actual_flags, TX_WAIT_FOREVER);    /* Check status.*/    if ((status != TX_SUCCESS) || (actual_flags != 0x1))      break;    sysprintf("%s\r\n", __func__);}}void thread_2_entry(ULONG thread_input){/* This thread simply sits in while-forever-sleep loop.*/while (1) {    tx_thread_sleep(TX_TIMER_TICKS_PER_SECOND);    sysprintf("%d\r\n", thread_0_counter);}}/*-----------------------------------------------------------------------------*/int main(void){    sysDisableCache();    sysFlushCache(I_D_CACHE);    sysEnableCache(CACHE_WRITE_BACK);    sysInitializeUART();    sysprintf("\n\n Hello NUC970 !!!\n");    sysprintf("APLL    clock %d MHz\n", sysGetClock(SYS_APLL));    sysprintf("UPLL    clock %d MHz\n", sysGetClock(SYS_UPLL));    sysprintf("CPU   clock %d MHz\n", sysGetClock(SYS_CPU));    sysprintf("Systemclock %d MHz\n", sysGetClock(SYS_SYSTEM));    sysprintf("HCLK1   clock %d MHz\n", sysGetClock(SYS_HCLK1));    sysprintf("HCLK234 clock %d MHz\n", sysGetClock(SYS_HCLK234));    sysprintf("PCLK    clock %d MHz\n", sysGetClock(SYS_PCLK));    tx_kernel_enter();    return 0;}void tx_application_define(void *first_unused_memory){CHAR    *pointer = TX_NULL;/* Create a byte memory pool from which to allocate the thread stacks.*/tx_byte_pool_create(&byte_pool_0, "byte pool 0", first_unused_memory, DEMO_BYTE_POOL_SIZE);/* Put system definition stuff in here, e.g. thread creates and other assorted   create information.*//* Allocate the stack for thread 0.*/tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);/* Create the main thread.*/tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,                   pointer, DEMO_STACK_SIZE,                   1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);/* Allocate the stack for thread 1.*/tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);/* Create thread 1.This thread simply pends on an event flag which will be set   by thread_0.*/tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0,                   pointer, DEMO_STACK_SIZE,                   4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);/* Allocate the stack for thread 2.*/tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);tx_thread_create(&thread_2, "thread 2", thread_2_entry, 0,                   pointer, DEMO_STACK_SIZE,                   5, 5, TX_NO_TIME_SLICE, TX_AUTO_START);tx_event_flags_create(&event_flags_0, "event flags 0");}
创建三个任务,和一个事件任务0和任务2通过事件通知,任务1打印任务0中的记数
设置项目引用,包含tx的common/inc和port/arm9/ac5/inc
https://whycan.com/files/members/12991/hello-4.png
编译项目,下载测试
这里注意sysprintf并没有做可重入处理,项目中建议需要处理一下
此项目只做移植说明,并没有在目标板实测运行,另外实测的项目相对复杂,不便于讲解.后记:
filex基于sdnand早前移植过,前后台模式下使用,没有支持os的,后面需要打开一下os再测试一下,下一步需要移植netxduo了,这个还是第一次用.
不足之处还请多多指教

eric2013 发表于 2023-10-26 20:44:55

谢谢楼主分享{:8:}

萌军总司令 发表于 2023-11-6 23:03:24

在 哇酷 刚看到大佬的帖子,很好很强大,也很暴力啊

ayuanshop 发表于 2023-11-8 00:05:13

好棒~~~另,,可否将文中提到的附件传到这边呢,,,挖坑那边积分太羞涩了,,,,下载不了。。。谢谢您~
页: [1]
查看完整版本: NUC972下threadx移植