完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
7.1 初学者重要提示。
移植前注意以下两个问题: 本章节的IDE开发环境务必是Embedded Studio 5.10及其以上版本,镜像下载地址: 准备一个简单的裸机工程,越简单越好,我们就在这个简单的工程上面移植即可: 配套模板名称:V7-3001_Base Template GUIX的移植通过以下8步完成,下面各个小节详细讲解每一步: 7.3 第1步:了解ThreadX内核模板框架设计 移植ThreadX前,我们优先了解下ThreadX内核模板程序的框图。 7.3.1 准备一个ThreadX内核工程模板 首先准备好一个简单的ThreadX工程模板,工程模板的制作在ThreadX内核教程里面有详细说明,这里的重点是教大家移植ThreadX,对应的例子名称:V7-3002_ThreadX Kernal Template。准备好的工程模板如下图所示。 7.3.2 内核框架整体把控(重要) 为了帮助大家更好的理解ThreadX内核例子模板,专门制作了一个框图,可以让大家整体把控模板设计: 下面把几个关键点逐一为大家做个说明。 7.3.3 各种头文件汇总includes.h 这个文件主要实现工程中各种头文件的汇总,大家用到的都可以将其放到这个头文件里面。其它应用源文件有调用到的,直接调用这个头文件includes.h即可。 使用这个头文件主要是方便各种头文件的管理。 /*********************************************************************************************************** 标准库**********************************************************************************************************/#include 7.3.4 TheadX配置文件tx_user.h 此文件主要用于ThreadX内核的配置,内核相关的几个宏配置基本都已经整理到这个文件里面。 /*********************************************************************************************************** 宏定义**********************************************************************************************************//* 最快速度优化需要开启的选项 : TX_MAX_PRIORITIES 32 TX_DISABLE_PREEMPTION_THRESHOLD TX_DISABLE_REDUNDANT_CLEARING TX_DISABLE_NOTIFY_CALLBACKS TX_NOT_INTERRUPTABLE TX_TIMER_PROCESS_IN_ISR TX_REACTIVATE_INLINE TX_DISABLE_STACK_FILLING TX_INLINE_THREAD_RESUME_SUSPEND 最小代码优化需要开启的选项: TX_MAX_PRIORITIES 32 TX_DISABLE_PREEMPTION_THRESHOLD TX_DISABLE_REDUNDANT_CLEARING TX_DISABLE_NOTIFY_CALLBACKS TX_NOT_INTERRUPTABLE TX_TIMER_PROCESS_IN_ISR *//* 覆盖tx_port.h 里面的宏定义 *//*#define TX_MAX_PRIORITIES 32#define TX_MINIMUM_STACK ????#define TX_THREAD_USER_EXTENSION ????#define TX_TIMER_THREAD_STACK_SIZE ????#define TX_TIMER_THREAD_PRIORITY ????*//* 确定定时器是否到期的处理,比如应用定时器,溢出时间和函数tx_thread_sleep调用等,是在系统定时器任务里面还是在定时器中断里面调用。 默认是在定时任务里面,当定义了下面函数后,将直接在定时器中断里面处理,可以去掉定时器任务所消耗资源。 *///#define TX_TIMER_PROCESS_IN_ISR/* 用于设置定时器激活是否采用内联方式,默认此功能是关闭的。如果使能后,内联方式的执行速度快,但增加代码量 *///#define TX_REACTIVATE_INLINE/* 用于设置是否关闭栈填充,默认情况下是使能的,所有任务的栈空间全部填充为0xEF,* 带有ThreadX调试组件或者运行时栈检测会用到。*///#define TX_DISABLE_STACK_FILLING/* 用于使能栈检测,默认是关闭的。此选项使能后,而TX_DISABLE_STACK_FILLING没使能时,栈填充将开启,方便栈检测 *///#define TX_ENABLE_STACK_CHECKING/* 用于设置是否关闭抢占阀值,默认是开启的。如果应用程序不需要此功能,关闭后可以降低代码需求,提升性能 *///#define TX_DISABLE_PREEMPTION_THRESHOLD/* 用于设置是否清零ThreadX全局变量,如果编译器启动代码在ThreadX运行前清除了.bss段,那么可以关闭不必要的清零 *///#define TX_DISABLE_REDUNDANT_CLEARING/* 确定是否不需要定时器组,禁止后需要用户注释掉tx_initialize_low_level文件里面tx_timer_interrupt的调用。 另外,禁止后,必须使能TX_TIMER_PROCESS_IN_ISR *//*#define TX_NO_TIMER#ifndef TX_TIMER_PROCESS_IN_ISR#define TX_TIMER_PROCESS_IN_ISR#endif*//* 用于设置是否关闭通知回调,默认是使能的。如果应用程序没有用到消息回调,关闭掉后可以减小代码,并且可以提升性能。 *///#define TX_DISABLE_NOTIFY_CALLBACKS/* 使能tx_thread_resume和tx_thread_suspend使用内联代码,优势是提升这两个函数的执行性能,劣势是增加代码量 *///#define TX_INLINE_THREAD_RESUME_SUSPEND/* 设置TreadX内核不可中断,好处是降低处理负担,并且产生的代码小。但增加锁时间 *///#define TX_NOT_INTERRUPTABLE/* 使能事件Trace,会稍微增加点代码 *///#define TX_ENABLE_EVENT_TRACE/* 使能BLOCK_POOL信息获取 *///#define TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO/* 使能BYTE_POOL信息获取 *///#define TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO/* 使能事件标志信息获取 *///#define TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO/* 使能互斥信号量信息获取 *///#define TX_MUTEX_ENABLE_PERFORMANCE_INFO/* 使能消息对象信息获取 *///#define TX_QUEUE_ENABLE_PERFORMANCE_INFO/* 使能信号量信息获取 *///#define TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO/* 使能任务信息获取 *///#define TX_THREAD_ENABLE_PERFORMANCE_INFO/* 使能定时器信息获取 *///#define TX_TIMER_ENABLE_PERFORMANCE_INFO 7.3.5 系统时钟节拍配置tx_initialize_low_level.s 这个汇编文件里面有个重要参数需要大家配置,即芯片主频和系统时钟节拍。 SYSTEM_CLOCK EQU 400000000 SYSTICK_CYCLES EQU ((SYSTEM_CLOCK / 1000) -1) 400000000是系统时钟主频,1000对应的就是系统时钟节拍,这里1000就表示1000Hz。 7.3.6 TheadX任务管理main.c ThreadX所有任务基本都在main.c里面创建,方便统一管理。如果有GUIX,FileX等组件的任务需要运行,实际运行函数会在其它源文件里面,并将这个函数extern到main.C文件里面,放到相应的任务里面执行。 另外,任务优先级,任务栈大小,任务控制块等也都放到main.C文件里面,方便管理: /*********************************************************************************************************** 任务优先级,数值越小优先级越高**********************************************************************************************************/#define APP_CFG_TASK_START_PRIO 2u#define APP_CFG_TASK_MsgPro_PRIO 3u#define APP_CFG_TASK_USER_IF_PRIO 4u#define APP_CFG_TASK_COM_PRIO 5u#define APP_CFG_TASK_STAT_PRIO 30u#define APP_CFG_TASK_IDLE_PRIO 31u/*********************************************************************************************************** 任务栈大小,单位字节**********************************************************************************************************/#define APP_CFG_TASK_START_STK_SIZE 4096u#define APP_CFG_TASK_MsgPro_STK_SIZE 4096u#define APP_CFG_TASK_COM_STK_SIZE 4096u#define APP_CFG_TASK_USER_IF_STK_SIZE 4096u#define APP_CFG_TASK_IDLE_STK_SIZE 1024u#define APP_CFG_TASK_STAT_STK_SIZE 1024u/*********************************************************************************************************** 静态全局变量**********************************************************************************************************/ static TX_THREAD AppTaskStartTCB;static uint64_t AppTaskStartStk[APP_CFG_TASK_START_STK_SIZE/8];static TX_THREAD AppTaskMsgProTCB;static uint64_t AppTaskMsgProStk[APP_CFG_TASK_MsgPro_STK_SIZE/8];static TX_THREAD AppTaskCOMTCB;static uint64_t AppTaskCOMStk[APP_CFG_TASK_COM_STK_SIZE/8];static TX_THREAD AppTaskUserIFTCB;static uint64_t AppTaskUserIFStk[APP_CFG_TASK_USER_IF_STK_SIZE/8];static TX_THREAD AppTaskIdleTCB;static uint64_t AppTaskIdleStk[APP_CFG_TASK_IDLE_STK_SIZE/8];static TX_THREAD AppTaskStatTCB;static uint64_t AppTaskStatStk[APP_CFG_TASK_STAT_STK_SIZE/8]; 7.3.7 TheadX启动任务 启动任务里面主要做了四个工作:
代码如下: /*********************************************************************************************************** 函 数 名: AppTaskStart* 功能说明: 启动任务。* 形 参: thread_input 是在创建该任务时传递的形参* 返 回 值: 无 优 先 级: 2**********************************************************************************************************/static void AppTaskStart (ULONG thread_input){ (void)thread_input; /* 先挂起定时器组 */#ifndef TX_NO_TIMER tx_thread_suspend(&_tx_timer_thread);#endif /* 优先执行任务统计 */ OSStatInit(); /* 恢复定时器组 */#ifndef TX_NO_TIMER tx_thread_resume(&_tx_timer_thread);#endif /* 内核开启后,恢复HAL里的时间基准 */ HAL_ResumeTick(); /* 外设初始化 */ bsp_Init(); /* 创建任务 */ AppTaskCreate(); /* 创建任务间通信机制 */ AppObjCreate(); while (1) { /* 需要周期性处理的程序,对应裸机工程调用的SysTick_ISR */ bsp_ProPer1ms(); tx_thread_sleep(1); }}7.3.8 HAL库时间基准stm32h7xx_hal_timebase_tim.cThreadX系统时钟节拍默认是用的滴答定时器,STM32的HAL库时间基准也是用的滴答定时器。对于这种情况,我们一般的情况下是使用其他的通用定时器替代,不过要额外的占用一点系统性能。简单的处理办法是重新下面两个函数即可,让HAL库和ThreadX都使用滴答定时器: /*********************************************************************************************************** 函 数 名: HAL_Delay* 功能说明: 重定向毫秒延迟函数。替换HAL中的函数。因为HAL中的缺省函数依赖于Systick中断,如果在USB、SD* 卡中断中有延迟函数,则会锁死。也可以通过函数HAL_NVIC_SetPriority提升Systick中断* 形 参: 无* 返 回 值: 无**********************************************************************************************************/void HAL_Delay(uint32_t Delay){ bsp_DelayMS(Delay);}HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority){ return HAL_OK;}uint32_t HAL_GetTick (void){ static uint32_t ticks = 0U; uint32_t i; if (_tx_thread_system_state == TX_INITIALIZE_IS_FINISHED) { return ((uint32_t)_tx_time_get()); } /* 如果ThreadX还没有运行,采用下面方式 */ for (i = (SystemCoreClock >> 14U); i > 0U; i--) { __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); } return ++ticks;}7.3.9 ThreadX使能硬件浮点 这个是移植的坑王,大家移植后,可以测试下多任务的FPU计算是否有异常。比如两个任务运行相同的浮点运算和刷新速度,看看两个任务的输出是否同步变化,这个测试非常重要: 那么问题来了,正确的使能姿势是什么?务必保证使能了预定义宏: 7.4 第2步:添加ThreadX库所有相关文件到裸机工程模板 了解了ThreadX内核框架后,介绍下如何将移植到裸机工程模板里面。我们这里一步到位,直接把所有相关的文件都加上,然后再介绍如何修改,方便大家移植到自己的板子上。 7.4.1 第2.1步,下载ThreadX源码包 按照第2章2.3.1小节讲解的方法下载软件包threadx-6.0.2_rel(如果软件包升级了,数字6.0.2略有不同),下面是ThreadX软件包内容: 主要用到两个文件夹: common文件夹里面是源码文件。 ports文件夹里面是移植文件。 7.4.2 第2.2步,创建ThreadX文件夹到工程模板 在工程模板创建文件夹 将2.1步的ThreadX软件包里面的所有内容复制进来,整体效果就是下面这样: 7.4.3 第2.3步,添加Port文件和源码文件到工程 将源码文件和ports文件添加到MDK的工程项目中,添加后的效果如下:
在User文件夹下添加文件tx_user.h,直接从本章节教程配套例子的User文件夹复制即可。此文件主要用于ThreadX配置。 为了方便管理,我们这里将路径ThreadXportscortex_m7gnuinc里面的tx_port.h文件也添加进来了。 7.4.5 第2.5步,添加头文件的绘制文件includes.h 在User文件夹下添加文件incudes.h,直接从本章节教程配套例子的User文件夹复制即可。此文件主要用于ThreadX的各种头文件汇总。 7.4.6 第2.6步,加HAL基准文件stm32h7xx_hal_timbase_tim.c 在Userbsp文件夹下添加文件stm32h7xx_hal_timebase_tim.c,直接从本章节教程配套例子的Userbsp文件夹复制即可。此文件主要用于为HAL库重新安排一个时间基准: 7.4.7 第2.7步,添加BSP驱动文件bsp_dwt.c 添加bsp_dwt.c文件和bsp_dwt.h文件主要是因为2.6步中的stm32h7xx_hal_timebase_tim.c文件里面的函数bsp_DelayMS要使用,此函数是基于DWT系统时钟周期计数器实现。 7.4.8 第2.8步,添加HAL库文件 相关BSP驱动关联到的HAL库文件都添加了进来,简单省事些,大家也可以把HAL库所有文件都添加进来: 7.4.9 第2.9步,添加预定义宏 C/C++文件中添加的预定义宏如下:
7.4.10 第2.10步,添加头文件路径 需要添加的路径如下: 至此,我们需要的GUIX文件都已经添加完毕。下面为大家介绍如何修改用于自己的板子。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1750 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1608 浏览 1 评论
1049 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
721 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1665 浏览 2 评论
1924浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
709浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
559浏览 3评论
583浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
544浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-18 10:18 , Processed in 1.466581 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号