项目需要,使用的nuc972主芯片,需要支持网络协议,就打算移植一下azure的tx,filex,netxduo,下面新记录一下tx的移植过程:
由于新唐的arm9中断处理和定时器初始化的寄存器并不同于tx官方的arm9的port,所以官方的port无法正常运行.
1.首先从github下载最新的tx代码.
git clone https://github.com/azure-rtos/threadx.git
2.创建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目录
如图:
设置DEVICE:
设置Output:
设置Include:
编译生成tx.lib文件备用,也可以直接下载工程文件并到tx根目录下:tx_lib_20231026182439.rar
以上就是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文件
此时编译项目应该没有错误
移植之前先修改sys.c文件,删除注册中断回调时的sysInitializeAIC调用
中断入口将由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 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
UND_STACK_SIZE EQU 256
ABT_STACK_SIZE EQU 256
FIQ_STACK_SIZE EQU 512 ; FIQ stack size
SVC_STACK_SIZE EQU 1024
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. */
;
TMR0_CLK EQU 0x00E4E1C0
TMR0_IRQn EQU 16
REG_TMR_TISR EQU 0xB8001060 ; Timer Interrupt Status Register
REG_AIC_BA EQU 0xB8002000 ; Interrupt Controller
REG_AIC_IPER EQU 0xB8002118 ; Interrupt priority encoding register
REG_AIC_ISNR EQU 0xB8002120 ; Interrupt source number register
REG_AIC_MDCR EQU 0xB8002138 ; Mask disable command register
REG_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
EXPORT Reset_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, [r0]
LDR r0, =REG_AIC_MDCRH
STR r1, [r0]
;--------------------------------
; 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, [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 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,[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,[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, [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! */
;
; LDR r0,=REG_AIC_IPER
; LDR r0,[r0]
; MOV r1,#0x3f
; AND r0,r1,r0,LSR #2
POP {r0}
SUB sp,sp,#8
STR r0,[sp,#4]
LDR r0,=REG_AIC_ISNR
LDR r0,[r0]
STR r0,[sp,#0]
LDR r0,[sp,#4]
CMP r0,#0
BEQ _irq_exit
LDR r0,[sp,#0]
CMP r0,#0
BEQ _irq_clear
LDR r1,=sysIrqHandlerTable
LDR r2,[sp,#4]
LDR r0,[r1,r2,LSL #2]
BLX r0
_irq_clear
MOV r0,#1
LDR r1,=REG_AIC_EOSCR
STR r0,[r1]
_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, [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
这个代码主要干以下任务:
__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,[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,[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, [r1] ; 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,[sp,#4]
LDR r0,=REG_AIC_ISNR
LDR r0,[r0]
STR r0,[sp,#0]
LDR r0,[sp,#4]
CMP r0,#0
BEQ _irq_exit
LDR r0,[sp,#0]
CMP r0,#0
BEQ _irq_clear
LDR r1,=sysIrqHandlerTable
LDR r2,[sp,#4]
LDR r0,[r1,r2,LSL #2]
BLX r0
_irq_clear
MOV r0,#1
LDR r1,=REG_AIC_EOSCR
STR r0,[r1]
_irq_exit
ADD sp,sp,#8 ; 返还临时变量占用的空间
这就是正常中断处理了,作用等同于sys.c中的sysIrqHandler函数
移植到此就完成了
4.验证
修改main.c文件
/**************************************************************************//**
* @file main.c
* @version V1.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("System clock %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
编译项目,下载测试
这里注意sysprintf并没有做可重入处理,项目中建议需要处理一下
此项目只做移植说明,并没有在目标板实测运行,另外实测的项目相对复杂,不便于讲解.
后记:
filex基于sdnand早前移植过,前后台模式下使用,没有支持os的,后面需要打开一下os再测试一下,下一步需要移植netxduo了,这个还是第一次用.
不足之处还请多多指教
离线
大佬在硬件上跑过了吗?
跑过,开了几个任务,闪灯,跑了几天.
离线
感觉这个社区不是很活跃,主要还是用他的filex,原来一个项目用emmc,试用了好多文件系统,还是filex问题比较少.就接触了一下.
离线