TreadX移植
移植需要的文件
- GitHub\threadx-6.1.9_rel\common\inc\
- GitHub\threadx-6.1.9_rel\common\src\
- GitHub\threadx-6.1.9_rel\ports\cortex_m3\gnu\inc\
- GitHub\threadx-6.1.9_rel\ports\cortex_m3\gnu\src\
- GitHub\threadx-6.1.9_rel\ports\cortex_m3\gnu\example_build\tx_initialize_low_level.S
GitHub\threadx-6.1.9_rel\ports\cortex_m3\gnu\example_build\tx_simulator_startup.s为example定义的中断向量表,不需要,使用原先系统自带的中断向量表即可。
GitHub\threadx-6.1.9_rel\ports\cortex_m3\gnu\example_build\cortexm3_crt0.s为reset_handler函数的具体实现,不需要,使用原先系统自带的中断复位函数即可。
GitHub\threadx-6.1.9_rel\ports\cortex_m3\gnu\example_build\sample_threadx.ld为ThreadX的链接脚本,不需要,使用原先系统自带的链接脚本即可。
GitHub\threadx-6.1.9_rel\ports\cortex_m3\gnu\example_build\sample_threadx.c为TheadX的示例程序,写应用程序时,可参考此文件。
$(wildcard ThreadX/common/src/*.c) \
$(wildcard ThreadX/ports/*.c)
$(wildcard ThreadX/ports/src/*.s) \
$(wildcard ThreadX/ports/tx_initialize_low_level.s)
-IThreadX/common/inc \
-IThreadX/ports/inc
tx_initialize_low_level.S
GitHub\threadx-6.1.9_rel\ports\cortex_m3\gnu\example_build\tx_initialize_low_level.S为需要移植的底层初始化文件。
-
修改SYSTEM_CLOCK系统时钟频率,SYSTICK_CYCLES表示多少次系统时钟进行一次重载,SYSTEM_CLOCK / 100表示10ms会产生一次SysTick中断。
SYSTEM_CLOCK = 6000000 SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
配置SysTick:
@ @ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ @ MOV r0, #0xE000E000 @ Build address of NVIC registers LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] @ Setup SysTick Reload Value MOV r1, #0x7 @ Build SysTick Control Enable Value STR r1, [r0, #0x10] @ Setup SysTick Control
-
设置可用内存的起始地址
@ @ /* Set base of available memory to end of non-initialised RAM area. */ @ LDR r0, =_tx_initialize_unused_memory @ Build address of unused memory pointer LDR r1, =__RAM_segment_used_end__ @ Build first free address ADD r1, r1, #4 @ STR r1, [r0] @ Setup first unused memory pointer
*_RAM_segment_used_end_*的值要看内存的具体布局,
若为下面的内存布局,*_RAM_segment_used_end_*应该在bss尾,即:heap的起始位置???
RAM region: stack ↓ heap ↑ … bss data 若为下面的内存布局,*_RAM_segment_used_end_*应该在stack栈底,即:heap的起始位置???
RAM region: heap ↑ stack ↓ … bss data 上述这个移植点需要后续确认一下!!!
-
设置中断向量表起始地址
@ @ /* Setup Vector Table Offset Register. */ @ MOV r0, #0xE000E000 @ Build address of NVIC registers LDR r1, =_vectors @ Pickup address of vector table STR r1, [r0, #0xD08] @ Set vector table address @ @ /* Set system stack pointer from vector value. */ @ LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer LDR r1, =_vectors @ Pickup address of vector table LDR r1, [r1] @ Pickup reset stack pointer STR r1, [r0] @ Save system stack pointer
_vectors根据链接脚本按实际的修改,如:GCC下应该为g_pfnVectors。
-
在SysTick_Handler函数中添加Tick值的计数函数
@ /* System Tick timer interrupt handler */ .global __tx_SysTickHandler .global SysTick_Handler .thumb_func __tx_SysTickHandler: .thumb_func SysTick_Handler: @ VOID TimerInterruptHandler (VOID) @ { @ PUSH {r0, lr} #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY BL _tx_execution_isr_enter @ Call the ISR enter function #endif BL _tx_timer_interrupt BL HAL_IncTick #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY BL _tx_execution_isr_exit @ Call the ISR exit function #endif POP {r0, lr} BX LR @ }
ThreadX接管了SysTick_Handler后,Tick值无法增加,因为可能别的外设驱动需要系统Tick值,所以需要调用BL HAL_IncTick(即原SysTick_Handler函数里面做的事情)。
-
注释掉无用的代码
下面的代码均需注释掉:
.global __tx_SVCallHandler .global _vectors .global __tx_NMIHandler @ NMI .global __tx_BadHandler @ HardFault .global __tx_SVCallHandler @ SVCall .global __tx_DBGHandler @ Monitor @/* Define shells for each of the unused vectors. */ @ .global __tx_BadHandler .thumb_func __tx_BadHandler: B __tx_BadHandler @ /* added to catch the hardfault */ .global __tx_HardfaultHandler .thumb_func __tx_HardfaultHandler: B __tx_HardfaultHandler @ /* added to catch the SVC */ .global __tx_SVCallHandler .thumb_func __tx_SVCallHandler: B __tx_SVCallHandler @ /* NMI, DBG handlers */ .global __tx_NMIHandler .thumb_func __tx_NMIHandler: B __tx_NMIHandler .global __tx_DBGHandler .thumb_func __tx_DBGHandler: B __tx_DBGHandler
启动文件startup.s
本地startup.s为启动文件。
-
修改中断向量表中的几个向量
__tx_PendSVHandler ← PendSV_Handler __tx_SysTickHandler ← SysTick_Handler
-
注释掉原项目中的SysTick_Handler函数和PendSV_Handler函数。
mark
/* Memory mapping of Core Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
/**
\brief Structure type to access the System Timer (SysTick).
*/
typedef struct
{
__IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
__IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
__IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
__IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;
/**
\brief Structure type to access the System Control Block (SCB).
*/
typedef struct
{
__IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
__IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
__IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
__IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
__IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
__IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
__IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */
__IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
__IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
__IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
__IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
__IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
__IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
__IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
__IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
__IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
__IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
__IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
__IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
uint32_t RESERVED0[5U];
__IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
} SCB_Type;
结合tx_initialize_low_level.S可以看出,SysTick和Vector Table设置了两遍,但是由于OS启动会调用 tx_kernel_enter -> _tx_initialize_kernel_enter -> _tx_initialize_low_level,最终会调到tx_initialize_low_level.S里来,所以最终生效的还是tx_initialize_low_level.S里设置的SysTick和Vector Table。