点击下方阅读原文可访问文中超链接
写在前面
准备移植
开始移植
- 首先更改时钟频率及给滴答定时器设置的重装载值
SYSTEM_CLOCK EQU SYSTICK_CYCLES EQU ((SYSTEM_CLOCK / 1000) -1)
- 删掉堆栈大小定义代码段(冲突)
- 删掉向量表的定义(冲突)
- 删掉Reset_Handler代码段(冲突)
- 删掉__user_initial_stackheap代码段(冲突)
- 删掉__tx_BadHandler代码段(没用)
- 删掉__tx_SVCallHandler代码段(没用)
- 删掉__tx_IntHandler代码段(没用)
- 删掉__tx_NMIHandler代码段(没用)
- 删掉__tx_DBGHandler代码段(没用)
IMPORT __Vectors
再次编译提示PendSV_Handler重复定义,但是却未提示SysTick_Handler重复定义,从以往移植其它rtos的经验来看,基本上都是使用滴答定时器作为系统心跳,我们暂且继续往下看

屏蔽掉stm32f4xx_it.c文件中的PendSV_Handler函数,threadx需要用来进行上下文切换。
再次编译提示tx_application_define未定义,这个是在threadx系统启动的时候会自动调用,我们如果需要创建任务或者信号量等资源的话都是在这个函数里面完成,参考实现可仿照sample_threadx.c文件。

在main函数中添加头文件并且添加此函数的实体
#include "tx_api.h" VOID tx_application_define(VOID *first_unused_memory) {
/*暂时留空*/ }
这个问题解决后再次编译又报了几个错,也是未定义,猜测这几个符号是编译完代码后在某个中间文件生成的,在链接的时候这里再获取其值,因为keil编译完程序生成的map文件有类似的符号。

经过搜索,发现只有ImageZILimit有用(这里$显示不出来),其它都没有使用,从官方提供的其它移植的例程得知这里是用户可用内存(运行环境需要的除外,比如C运行环境的堆栈)的起始地址,设置为__initial_sp,同样的需要在前面IMPORT这个符号,__initial_sp有点特殊,需要勾选keil选项中的Use MicroLIB选项,不然的话提示找不到这个符号的定义,这是从启动文件得知的。
;* ; User Stack and Heap initialization ;* IF :DEF:__MICROLIB EXPORT __initial_sp EXPORT __heap_base EXPORT __heap_limit ELSE IMPORT __use_two_region_memory EXPORT __user_initial_stackheap ...
现在已经编译成功了,但是你会发现系统跑不起来,这就是前面为什么说SysTick_Handler这个函数没有报重复定义的错,因为系统的心跳还没有提供,看下PendSV_Handler是怎么实现的。
; /* Generic context switching PendSV handler. */ ; EXPORT __tx_PendSVHandler EXPORT PendSV_Handler __tx_PendSVHandler PendSV_Handler
这里将两个标号写在一起,也就是相当于一个函数的两个名字,实际上是同一个东西,模仿一下,添加SysTick_Handler,然后屏蔽掉stm32f4xx_it.c文件中的SysTick_Handler函数。
EXPORT __tx_SysTickHandler EXPORT SysTick_Handler __tx_SysTickHandler SysTick_Handler
编译成功,现在移植已经就大功告成了,添加两个线程测试下(参考sample_threadx.c文件)
void thread_0_entry(ULONG thread_input) {
/* This thread simply sits in while-forever-sleep loop. */ while(1) {
PRINTF("thread 0 is running..\r\n"); tx_thread_sleep(1000); } } void thread_1_entry(ULONG thread_input) {
/* This thread simply sends messages to a queue shared by thread 2. */ while(1) {
PRINTF("thread 1 is running..\r\n"); tx_thread_sleep(500); } }
验证
/*略*/ HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TickPriority ,0U); /*新版BUG,这里参考stm32f4xx_hal.c文件的HAL_InitTick函数*/ uwTickPrio = TickPriority; /* Enable the TIM6 global Interrupt */ HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); /*略*/
/*略*/ HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TickPriority ,0U); /*0x0f优先级已被threadx系统使用*/ TickPriority -= 1; /*新版BUG,这里参考stm32f4xx_hal.c文件的HAL_InitTick函数*/ uwTickPrio = TickPriority; /* Enable the TIM6 global Interrupt */ HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); /*略*/
最后一点
欢迎扫码关注我的微信公众号

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/220434.html原文链接:https://javaforall.net
