完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
μCOS-III系统移植--STM32F1为例
1.1 获取μC/OS源码 选择对应的(相近的)MCU型号;比如我需要移植μC/OS-III到STM32F103C8T6,那么我就去下载STM32F107对应的源代码。见下图: 注:在 Micrium 官网下载需要账号登陆,并且下载速度很慢,所以可以到处找找资源。 1.2 建立裸机工程(库函数版) 建立如下工程目录: CORE目录下:存放的是一些有关该CPU的内核文件和启动文件。F1系列就是core_cm3.c、core_cm3.h、startup_stmewf10x_hd.s。(.s启动文件需要结合自己的硬件进行容量选择; 再F4系列里面不在有core_cm4.c文件,但还是会有一些内核相关文件) FWLib目录下:就是存放该工程的标准函数库包了。直接复制 STM32F10x_FWLib 里面的文件到相关目录即可。 HARDWARE目录下:存放一些自己写的硬件模块文件。比如led.c、led.h、oled.c、oled.h…… SYSTEM目录下:存放一些有关系统方面的文件。具体的可以查看正点原子的《STM32F4开发指南–库函数版本》里面的第五章。 USER目录下:main.c 、stm32f10x.h、stm32f10x_conf.h、stm32f10x_it.h、stm32f10x_it.h、system_stm32f10x.c、system_stm32f10x.h 注:一般我们还会建立OBJ文件夹没用来存储工程编译的输出文件。有些还有建立专门的DOC文件夹用来说明工程相关内容。 目录建好以后就需要建立工程了,在工程里面建立相应的工作组,添加相应的文件以及头文件地址等等。具体的步骤再仔细查阅相关资料。建好后如下图: 1.3 在裸机工程文件里建立μC/OS文件夹 在裸机工程文件下面建立UCOSIII文件夹,并新建如下目录: 将下载好的源码解压后会在Software文件下面发现四个文件夹: EvalBoards:评估(开发)板相关文件;主要是配置底层和系统,我们会提取部分有效文件。 uC-CPU:CPU相关文件;我们使用ST标准外设库配置一些模块,不更改该文件夹下文件。 uC-LIB:这个是Micrium官方的库,初学者这里也不更改。 uCOS-III:这个文件夹才是关键,我们移植的内容基本上就是这里的文件。 所以我们一次来看看我们新建文件下面具体都存放了些什么文件: uC_CPU:就是我们解压后的 μC_CPU 文件夹,我们直接将里面所有的内容复制过去就可以了。 uC_LIB:这个文件夹和上面的一样,直接复制解压后的 μC_LIB 文件夹里面的内容即可。 UCOS_BSP:这个文件夹就不同了,这个文件夹我峨嵋你只需要存放 bsp.c 和 bsp.h 两个文件夹即可。这两个文件在 SoftwareEvalBoardsMicriumuC-Eval-STM32F107BSP 目录下面。 uCOS_CONFIG:存放一些配置文件,复制 SoftwareEvalBoardsMicriumuC- Eval-STM32F107uCOS-III 目录下的这些文件。不要 app.c 是因为这个文件就类似于 我们裸机工程里面的 main.c 文件,在新的工程中,我们仍然使用 main.c 作为主题程序的接入口;至于 stm32f10x_conf.h 我们之前在裸机工程里面就有 所以这里就不用了。如下图: 注:app.c 我们使用 main.c 代替后,也可以不要 app_cfg.h 文件的。这是一个对所有 APP(任务)进行配置的文件,可以保留在需要的时候进行修改引用。 uCOS-III:直接复制解压后的 μCOS-III 文件夹内容即可。 注:取名字的时候不要使用中文 和特殊字符,比如 μ 就不要用,最好用 u 代替。因为MDK不能正确识别。如果修改了文件夹名,那么该文件夹下的所有文件都需要重新加载。 总结:我们自己建立了 5 个文件夹,其中有 3个(μC_CPU、μC_LIB、μCOS-III)文件夹是直接复制的原来的解压后的文件,而其余 两个 (UCOS_BSP、UCOS_CONFIG)文件里面的内容都是从 SoftwareEvalBoardsMicriumuC-Eval-STM32F107 的两个文件夹中进行提取的。 1.4 在裸机工程里面添加工程组及相应的文件 在裸机工程里面添加如下的工程组: 在UCOSIII_CONFIG 工程组下面添加 工程文件夹 UCOSIIIUCOS_CONFIG 文件夹下面的文件,如图: 同理,工程组UCOSIII_BSP、UCOSIII_CPU、UCOSIII_LIB 分别对应工程文件夹下面的UCOSIIIUCOS_BSP、UCOSIIIuC-CPU、UCOSIIIuC-LIB 并分别添加对应的文件。具体分别见下图: 最后的两个工程组分别对应 工程文件夹 UCOSIIIuCOS-III 下面的 PORT 和 CORE 文件夹,并添加如下图内容: 注:如果在对应的文件下面没有找到所需的文件,那就在该文件夹下面的子文件夹里面去寻找,根据不同的平台,选择对应的文件。比如我们使用的是KEIL,那么,对应的文件就在 RealView 文件夹下面。 注:对于一些 .h 头文件是否要直接添加的在对应工程组的问题,这里我们没有去深究。只是简单的理解为,如果在工程组里面添加了 .h 文件 那么这个 .h 文件就会直接显示在工程组下面的文件按列表中,而不是隐藏在 .c 文件下面。我常用的做法是,如果这个 .h 文件有对应的(同名的) .c 文件 那么就不直接添加在工程组中,其它时候则相反。 注:使用系统时,还需要在SYSTEM工作组中添加delay.c、sys.c、usart.c文件,这几个文件中delay.c文件是必须的,而其余文件则根据使用要求进行选择,一般都是需要的。 1.5 对部分文件进行修改 a、修改 os_cpu_a.s 或者 startup_stm32f10x_hd.s 文件 注:这两个文件直选哟修改其中一个即可,建议修改 os_cpu_a.s。 os_cpu_a.s文件:它和 startup_stm32f10x_hd.s 都应该属于启动文件,只需要将它们关联起来 即可。修改如下图所示的地方: 注:使用 “;” 注释掉第 41行,添加第42行。 注释掉第 139行,添加第 140行;注释掉第 143行,添加第 144行。 注释掉第 154行,添加第 155行。 或者修改startup_stm32f10x_hd.s文件: 修改如下图所示部分即可: 注:如果不清楚可以查看 《野火]uCOS-III内核实现与应用开发实战指南——基于STM32》第256页的内容。 b、修改 stm32f10x_it.c 和 stm32f10x_it.h文件 stm32f10x_it.c文件:这是一个中断相关函数的文件,如果在其他地方没有定义有关的中断函数声明,那么中断函数默认的入口函数就在这里。因为它们上面修改了启动文件,并且在使用系统的时候,不能出现重复定义,所以这里我们也需要去注释掉 两个 相关的函数。如下图: 同样的,stm32f10x_it.h文件也熬做出相应的修改: c、修改bsp.c 和 bsp.h 文件 bsp.c文件:bsp 就是板级相关的文件,也就是对应开发板的文件,而 μC/OS-III 源码的 bsp 肯定是 与我们的板子不一样,所以就需要进行修改,而且以后我们的板级外设都在 bsp.c 文件进行初始化。 在不考虑板级相关的情况下,bsp.c文件只需要保留与 时间戳相关的 3个 函数 以及一些与之相关的预定义即可。详细情况如下图: 只需要上面部分的内容即可,其余部分均可删除或者注释掉。 bsp.h文件:也只需要保留它最基本的内容即可。如下图: 注:这一部分原来是 stm32f10x_lib.h 后来者部分改成了stm32f10x_conf.h d、修改 includes.h 文件 includes.h文件:这个是系统相关的头文件,有点类似于 stm32f10x.h 文件。这个主要还是修改之前的一个问题,就是将 stm32f10x_lib.h 修改为 stm32f10x_conf.h 如下图所示: e、修改 lib_cfg.h 文件 lib_cfg.h文件:中有这样一个定义: 表示把堆的空间设置为27KB,但是我使用的stm32f103c8t6的RAM总共才20K。所以我们需要修改它为合适的值,一般我们改为如下: 这一部分需要在使用内存管理 lib_mem.c 时才会被使用到,如果不使用也可以不管,不过还是建议先改一下。 到上面 移植算是结束了。 1.6 写一个简单的DEMO进行编译测试 //μCOS 系统使用 #include “misc.h” #include “includes.h” //SYSTEM 使用 #include “delay.h” #include “sys.h” #include “usart.h” #include 《stdio.h》 //功能模块 #include “led.h” //其它 #include 《string.h》 //任务初始化控制块 OS_TCB app_task_tcb_init; void app_task_init(void *parg); CPU_STK app_task_stk_init[512]; //任务堆栈,大小为512字,也就是2048字节 2K //任务串口控制块 OS_TCB app_task_tcb_usart; void app_task_usart(void *parg); CPU_STK app_task_stk_usart[512]; //任务堆栈,大小为512字,也就是2048字节 2K //任务led控制块 OS_TCB app_task_tcb_led; void app_task_led(void *parg); CPU_STK app_task_stk_led[512]; //任务堆栈,大小为512字,也就是2048字节 2K OS_MUTEX g_mutex_printf; //互斥量的对象 //用户对串口发送的数据进行完整性的保护 //如果不使能串口接收,那么下面的就不需要 OS_Q g_queue_usart1; //消息队列的对象 //用于处理串口接收到消息 //调试用代码 = 1 就开启调试 #define DEBUG_PRINTF_EN 1 void dgb_printf_safe(const char *format, 。..) { #if DEBUG_PRINTF_EN OS_ERR err; va_list args; va_start(args, format); OSMutexPend(&g_mutex_printf,0,OS_OPT_PEND_BLOCKING,NULL,&err); vprintf(format, args); OSMutexPost(&g_mutex_printf,OS_OPT_POST_NONE,&err); va_end(args); #else (void)0; #endif } int main ( void ) { OS_ERR err; systick_init(); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置 usart_init(115200); OSInit(&err); //创建任务 OSTaskCreate( &app_task_tcb_init, //任务控制块,等同于线程id “app_task_init”, //任务的名字,名字可以自定义的 app_task_init, //任务函数,等同于线程函数 0, //传递参数,等同于线程的传递参数 7, //任务的优先级6 app_task_stk_init, //任务堆栈基地址 512/10, //任务堆栈深度限位,用到这个位置,任务不能再继续使用 512, //任务堆栈大小 0, //禁止任务消息队列 0, //默认是抢占式内核 0, //不需要补充用户存储区 OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR, //开启堆栈检测与清空任务堆栈 &err //返回的错误码 ); OSStart(&err); printf(“never run.。..。..rn”); //启动OSStart之后 这一句永远不会执行 while(1); } void app_task_init(void *parg) { OS_ERR err; dgb_printf_safe(“task init is create okrn”); //模块初始化 led_init(); //创建互斥量 OSMutexCreate(&g_mutex_printf, “g_mutex_printf”, &err); //创建消息队列,用于处理串口1数据 OSQCreate(&g_queue_usart1, “g_queue_usart1”, 16, &err); //创建任务1 OSTaskCreate( (OS_TCB *)&app_task_tcb_usart, //任务控制块,等同于线程id (CPU_CHAR *)“app_task_usart”, //任务的名字,名字可以自定义的 (OS_TASK_PTR)app_task_usart, //任务函数,等同于线程函数 (void *)0, //传递参数,等同于线程的传递参数 (OS_PRIO)6, //任务的优先级6 前面的0123都被系统使用了 (CPU_STK *)app_task_stk_usart, //任务堆栈基地址 (CPU_STK_SIZE)512/10, //任务堆栈深度限位,用到这个位置,任务不能再继续使用 %10的空间给任务堆栈检测函数使用,任务实用为%90 (CPU_STK_SIZE)512, //任务堆栈大小 (OS_MSG_QTY)0, //禁止任务消息队列 (OS_TICK)0, //默认时间片长度 (void *)0, //不需要补充用户存储区 (OS_OPT)OS_OPT_TASK_NONE, //没有任何选项 &err //返回的错误码 ); //创建任务2 OSTaskCreate( (OS_TCB *)&app_task_tcb_led, //任务控制块 (CPU_CHAR *)“app_task_led”, //任务的名字 (OS_TASK_PTR)app_task_led, //任务函数 (void *)0, //传递参数 (OS_PRIO)6, //任务的优先级7 (CPU_STK *)app_task_stk_led, //任务堆栈基地址 (CPU_STK_SIZE)512/10, //任务堆栈深度限位,用到这个位置,任务不能再继续使用 (CPU_STK_SIZE)512, //任务堆栈大小 (OS_MSG_QTY)0, //禁止任务消息队列 (OS_TICK)0, //默认时间片长度 (void *)0, //不需要补充用户存储区 (OS_OPT)OS_OPT_TASK_NONE, //没有任何选项 &err //返回的错误码 ); //删除自身任务,进入休眠态 OSTaskDel(NULL, &err); } void app_task_usart(void *parg) { OS_ERR err; uint8_t *pmsg=NULL; OS_MSG_SIZE msg_size; uint16_t i; dgb_printf_safe(“task1 is create okrn”); while(1) { //等待消息队列 pmsg=OSQPend(&g_queue_usart1, 0, OS_OPT_PEND_BLOCKING, &msg_size, NULL, &err); if(err != OS_ERR_NONE) { dgb_printf_safe(“[app_task_usart1][OSQPend]Error Code = %drn”, err); continue; } //正确接收到消息 if(pmsg && msg_size) { OSMutexPend(&g_mutex_printf, 0, OS_OPT_PEND_BLOCKING, NULL, &err); for(i=0; i《msg_size; i++) { printf(“%c”, pmsg[i]); } printf(“n”); OSMutexPost(&g_mutex_printf, OS_OPT_POST_NONE, &err); } memset(pmsg, 0, msg_size); } } void app_task_led(void *parg) { dgb_printf_safe(“task2 is create okrn”); while(1) { PBout(2) = 1; delay_ms(1000); PBout(2) = 0; delay_ms(1000); } } 注:关于测试程序,不仅仅需要上面的主程序,还需要对应的 SYSTEM文件夹 对应的3个文件。这里我们就不再一一赘述了。 如果有不对的地方、需要调整的地方或者好的建议,欢迎留言,我看到的话我会及早的处理。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1828 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1640 浏览 1 评论
1109 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
742 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1698 浏览 2 评论
1954浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
762浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
590浏览 3评论
608浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
575浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-1 14:32 , Processed in 0.567700 second(s), Total 42, Slave 37 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号