【国产MCU移植】移植RT-Thread到国产芯片FM33LC026
本文由RT-Thread论坛用户@jiao96 原创发布:https://club.rt-thread.org/ask/article/3020.html
摘要
因为项目需要,使用了复旦微FM33LC026单片机,移植了RT_Thread系统。正好赶上rt官方的【国产MCU移植】活动,顺路参与一下。
芯片参数:
硬件 | 描述 |
---|---|
CPU | Cortex-M0 |
主频 | 64MHz |
SRAM | 24KB |
Flash | 128KB |
移植主要步骤:
1.工程搭建
2.添加复旦微官方库
3.板级初始化
4.对接串口驱动
开发工具:
Keil5、Env工具、Scons
工程搭建
芯片为ARM Cortex M0内核,可以用M0内核的其它BSP修改一个出来。
因为平时使用STM32比较多,同时rt官方适配的较好,所以使用了stm32f072-st-nucleo进行修改。
将stm32f072-st-nucleo复制到bsp目录下,改名为fm33lc026。
Stm32的libraries一起挪到新工程目录下。
只搞了keil5的工程,其它没用的删掉。
修改keil5工程。
项目工程是工具通过template模板生成的,所以,修改型号只需要修改template.uvprojx就可以了。
打开template.uvprojx
修改芯片型号为FM33LC02X,其余大部分会根据选择的芯片自动修改。
再进入linker,分散加载文件修改一下。
template模板修改完成,接下来需要用模板生成工程,由于工程是STM32拷贝出来的,一些相对路径等会有变化,脚本会有问题,先进行一下修改。
修改fm33lc026文件夹下SConstruct文件,文本文档打开,这里路径改为如图的路径。
修改fm33lc026文件夹下Kconfig文件,修改如下。
修改好了,通过env工具,menuconfig,啊哈,报错了。
根据报错信息,还需要修改board/Kconfig下libraries的路径。
修改完成,menuconfig打开,现在还是原来工程的配置,接下来还需要继续修改,退出,生成一下keil5工程,打开工程,各配置正常,文件路径都可以找到,工程搭建完毕。
添加复旦微官方库
接下来,添加复旦微FM33LC0XX的官方库函数到路径下。
需要替换掉原本STM32的官方HAL库。
STM32的库函数和驱动文件都在\libraries文件夹下,也就是刚才我们复制到工程内的文件夹。
我们只需要进入\libraries文件夹下,把官方库函数文件夹添加进来,通过修改脚本,让它自己添加就OK了。
打开\libraries文件夹,先看一下文件结构。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2OHYyQCx-1631071758745)(https://oss-club.rt-thread.org/uploads/20210906/8519e6c65f602919e1db3085ea23bb9e.png)]
把STM32的HAL库全部删掉,找到官方的FM33LC0xx_FL_Driver库,复制一份进来。同时FM33LC0XX内核相关文件也复制进来。新的目录结构如下,驱动文件留着,低层驱动需要套接到内核驱动层,在原本STM32的修改就可以了。
修改Kconfig
进入接下来的文件夹,继续修改Kconfig。
FM内的文件是board里Kconfig配置的,而且只用到了.s启动文件,下一节进行配置。
先进入FM33LC0xx_FL_Driver文件夹。
FM33LC0xx_FL_Driver对应STM32_HAL库,复制一份STM32_HAL的SConscript到FM33LC0xx_FL_Driver目录下,进行修改。
复制bsp\stm32\libraries\STM32F0xx_HAL内的SConscript到FM33LC0xx_FL_Driver目录下。打开。
改为如下:
进入HAL_Drivers文件夹下。
因为我只适配了串口驱动,删掉没用的文件。删完如下图。
Config文件夹下
修改SConscript,都是根据宏定义添加drv_XXX.c到工程。
Emmmm,算了,不修改了,以后添加驱动还要加回来,顶多生成的工程找不到相应的drv_.c,基本没啥影响。
使用env生成一下工程,报错了,根据报错信息,找到报错的位置。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xVZaPI6j-1631071758753)(https://oss-club.rt-thread.org/uploads/20210906/59fe7bafb1f4651fc924ba68a32cf7fd.png.webp)]
打开报错的文件,官方库路径在这一步修改过,需要重新修改。
重新生成工程,成功,打开工程,库文件也添加成功。
板级初始化
相关库函数已经添加成功,接下来,要让单片机运行起来,并且进入系统。
启动流程可以看RT_Thread官方文档。这里借用一张图。
要修改的有,.s启动文件,rt_hw_board_init()函数内相关的内容。
添加完官方库文件后,打开keil5工程,会发现.s启动文件还是STM32F072的,这里,我们要修改一下。
打开board文件夹,打开SConscript,修改启动文件路径,修改如下。
还有一个Kconfig文件,和启动无关,顺路也修改一下。里面主要是menuconfig里单片机设备等的配置菜单,修改成我们需要的。
进入工程board文件夹,删掉STM32的CubeMX文件夹。
删掉linker_scripts分散加载文件(分散加载相关在最前面已经配置了,如果需要分散加载文件,推荐不删,把文件内容改成FM33LC0XX的即可)。
OK…
进入env,打开menuconfig,发现串口图形化配置已经OK了。
退出menuconfig,生成工程,打开工程,发现所有文件都添加完毕,接下来要修改代码了。
进行rt_hw_board_init()内相关的函数的修改。
直接上改好的吧,具体相关的自行查看源码,代码现已经合并到RT_Thread主分支。
打开drv_common.c,修改相关。
打开board.c
板级初始化这部分就完成了。工程这部分编译还是会报错,因为串口驱动相关的代码还是STM32的。关于驱动部分的对接,在接下来的部分。
对接串口驱动
关于设备,可以参考官方设备文档
继续引用一张图。
对应到工程:
简单来讲,就是写一个套接层,把官方的库函数套接到RT_Thread的设备管理层内。只需要修改设备驱动框架层,对应到工程就是keil5里Drivers里相关的代码。
打开Drivers分组,找到我们要修改的串口部分程序,分别为drv_usart.c,drv_usart.h,uart_config.h。同时,关于串口引脚的初始化,模仿STM32的bsp包,单独拿了出来,放到了board.c里。
首先是drv_usart.h文件,定义了串口配置结构体和串口设备结构体,删掉原来STM32的,修改成如下:
串口配置结构体,一些需要单独进行配置的部分单拉出来。
/* config class */
struct _uart_config
{const char *name;void *InitTypeDef;IRQn_Type irq_type;uint32_t clockSrc;
};
串口结构体,通用的,不需要修改的部分。
/* uart dirver class */
struct _uart
{FL_UART_InitTypeDef handle;struct _uart_config *config;rt_uint16_t uart_dma_flag;struct rt_serial_device serial;
};
drv_usart.c文件里,定义了串口实例,串口的操作方法函数,串口的注册函数。修改如下:
串口实例,根据rtconfig.h里的宏定义进行配置。
enum
{
#ifdef BSP_USING_UART0UART0_INDEX,
#endif
#ifdef BSP_USING_UART1UART1_INDEX,
#endif
#ifdef BSP_USING_UART4UART4_INDEX,
#endif
#ifdef BSP_USING_UART5UART5_INDEX,
#endif
#ifdef BSP_USING_LPUART0LPUART0_INDEX,
#endif
#ifdef BSP_USING_LPUART1LPUART1_INDEX,
#endif
};static struct _uart_config uart_config[] =
{
#ifdef BSP_USING_UART0UART0_CONFIG,
#endif
#ifdef BSP_USING_UART1UART1_CONFIG,
#endif
#ifdef BSP_USING_UART4UART4_CONFIG,
#endif
#ifdef BSP_USING_UART5UART5_CONFIG,
#endif
#ifdef BSP_USING_LPUART0LPUART0_CONFIG,
#endif
#ifdef BSP_USING_LPUART1LPUART1_CONFIG,
#endif
};
串口的操作方法函数,这里不详细列出,需要把这几个结构体里函数修改完成。
static const struct rt_uart_ops _uart_ops =
{.configure = uart_configure,.control = uart_control,.putc = uart_putc,.getc = uart_getc,.dma_transmit = 0
};
串口的注册函数,将串口设备注册到设备管理层。
int rt_hw_usart_init(void)
{rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct _uart);struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;rt_err_t result = 0;for (int i = 0; i < obj_num; i++){/* init UART object */uart_obj[i].config = &uart_config[i];uart_obj[i].serial.ops = &_uart_ops;uart_obj[i].serial.config = config;/* register UART device */result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name,RT_DEVICE_FLAG_RDWR| RT_DEVICE_FLAG_INT_RX| RT_DEVICE_FLAG_INT_TX| uart_obj[i].uart_dma_flag, NULL);RT_ASSERT(result == RT_EOK);}return result;
}
uart_config.h文件,在drv_config.h里包含,给串口配置结构体赋值,需要填入对应的串口中断向量地址等:
#if defined(BSP_USING_UART0)
#ifndef UART0_CONFIG
#define UART0_CONFIG \{ \.name = "uart0", \.InitTypeDef = UART0, \.irq_type = UART0_IRQn, \.clockSrc = FL_RCC_UART0_CLK_SOURCE_APB1CLK, \}
#endif /* UART0_CONFIG */
#endif /* BSP_USING_UART0 */#if defined(BSP_USING_UART1)
#ifndef UART1_CONFIG
#define UART1_CONFIG \{ \.name = "uart1", \.InitTypeDef = UART1, \.irq_type = UART1_IRQn, \.clockSrc = FL_RCC_UART1_CLK_SOURCE_APB1CLK, \}
#endif /* UART1_CONFIG */
#endif /* BSP_USING_UART1 */
board.c里放入了串口引脚初始化,和其他一些关于硬件底层的配置。
FL_ErrorStatus FL_UART_GPIO_Init(UART_Type *UARTx)
{FL_ErrorStatus status = FL_FAIL;FL_GPIO_InitTypeDef GPIO_InitStruct;if (UARTx == UART0){GPIO_InitStruct.pin = FL_GPIO_PIN_13;GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;GPIO_InitStruct.pull = FL_DISABLE;GPIO_InitStruct.remapPin = FL_DISABLE;status = FL_GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.pin = FL_GPIO_PIN_14;GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;GPIO_InitStruct.pull = FL_DISABLE;GPIO_InitStruct.remapPin = FL_DISABLE;status = FL_GPIO_Init(GPIOA, &GPIO_InitStruct);}else if (UARTx == UART1){GPIO_InitStruct.pin = FL_GPIO_PIN_13;GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;GPIO_InitStruct.pull = FL_DISABLE;GPIO_InitStruct.remapPin = FL_DISABLE;status = FL_GPIO_Init(GPIOB, &GPIO_InitStruct);GPIO_InitStruct.pin = FL_GPIO_PIN_14;GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;GPIO_InitStruct.pull = FL_DISABLE;GPIO_InitStruct.remapPin = FL_DISABLE;status = FL_GPIO_Init(GPIOB, &GPIO_InitStruct);}else if (UARTx == UART4){GPIO_InitStruct.pin = FL_GPIO_PIN_0;GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;GPIO_InitStruct.pull = FL_DISABLE;GPIO_InitStruct.remapPin = FL_DISABLE;status = FL_GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.pin = FL_GPIO_PIN_1;GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;GPIO_InitStruct.pull = FL_DISABLE;GPIO_InitStruct.remapPin = FL_DISABLE;status = FL_GPIO_Init(GPIOA, &GPIO_InitStruct);}return status;
}
修改完毕,配置好串口到控制台,编译下载,正常使用。
点灯
最后在main函数里点灯
int main(void)
{FL_GPIO_InitTypeDef GPIO_InitStruct = {0};FL_GPIO_SetOutputPin(GPIOD, FL_GPIO_PIN_4);GPIO_InitStruct.pin = FL_GPIO_PIN_4;GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;GPIO_InitStruct.pull = FL_DISABLE;FL_GPIO_Init(GPIOD, &GPIO_InitStruct);while (1){FL_GPIO_SetOutputPin(GPIOD, FL_GPIO_PIN_4);rt_thread_mdelay(500);FL_GPIO_ResetOutputPin(GPIOD, FL_GPIO_PIN_4);rt_thread_mdelay(500);}}
完毕。
总结
没有总结,第一次写技术文档,欢迎大家学习交流。
近来芯片缺货大幕拉开,掀起新一轮国产替代浪潮。RT-Thread发起一场国产MCU移植贡献活动,邀请开发者们参加!
活动详情:国潮崛起!RT-Thread国产MCU移植贡献活动开启!
【国产MCU移植】移植RT-Thread到国产芯片FM33LC026相关推荐
- 正点原子delay函数移植到rt thread操作系统(HAL库)
正点原子教程中涉及到的操作系统只涉及了UCOS的教程,其中例程的system文件夹中的delay.c函数只是适配了UCOS. 下面将delay.c函数移植到rt thread中,使用的bsp是rt t ...
- 【国产MCU移植】移植RT-Thread到国产芯片HC32L196
大家好我是惊觉.是的,失踪人口回来了.最近参加了rt-thread的国产MCU移植活动,移植rt-thread到华大的HC32L196.rtt论坛中已有许多介绍移植到各种平台的文章,详细讲述移植步骤, ...
- stm32移植到国产MCU雅特力AT32
第一章 STM32移植AT32 概述 前言 雅特力科技于2016年在重庆成立的国产MCU品牌,全系列产品采用55nm先进工艺主打M4内核的高性能32位单片机,目前正式发布的有AT32F403.AT32 ...
- RT Thread Free Modbus移植问题整理
RT Thread Free Modbus移植问题整理 问题描述: 在读写寄存器中,写数据正常,只能读1个寄存器的值,多个值会异常. 在移植过程中发现串口(或RS485)数据接收长度异常. 一.环境描 ...
- STM32的国产替代,盘点下我知道的国产MCU
电子元件涨价和缺货是多少嵌入式工程师的痛,一年内上游厂家晶圆产能告急能有数十次之多.而MCU更是重灾区,且不说国内有超75%的市场都是被国外产品占据,就是本国内的代理和供应商也是漫天要价,而交期更是长 ...
- 文末赠书《GD32 MCU原理及固件库开发指南》5本 | 国产MCU中GD32系列有望成为未来32位MCU的主流
学习优秀博文([guo产MCU移植]手把手教你使用RT-Thread制作GD32系列BSP)有感 一篇优秀的博文是什么样的?它有什么规律可循吗?优秀的guo产32位单片机处理器是否真的能成功替换掉st ...
- MCU不再“芯慌慌”,国产新品Air101帮你忙
"全球缺芯,最缺是MCU!"这两年在疫情.政治因素等复杂背景交织下,MCU价格呈几十倍甚至几百倍上涨之势,如同翻着筋斗云:纵然舍得大价钱,漫漫交期也让人心慌慌.更别提开发切换之难, ...
- 客户回访|国产MCU测试解决方案 助力中国“芯”智造
半导体技术持续更新迭代,MCU也在与时俱进,为了更好地迎接市场未来趋势,国产MCU厂商积极布局各系列MCU产品线,开始逐渐在特定细分领域实现突破.随着应用场景的进化升级,MCU 中包含越来越多的功能模 ...
- 灵动微MM32SPIN360C获选2020年度国产MCU评选
由芯师爷主办.深福保集团冠名的"2020硬核中国芯"活动中,灵动微电子获选2020年度国产MCU评选. 企业介绍 灵动微电子是中国本土领先的通用32位MCU产品及解决方案供应商.公 ...
最新文章
- 函数-函数进阶-装饰器流程分析
- 基于GNS3的ssl配置
- screw (螺丝钉) ~ 简洁好用的数据库表结构文档生成工具
- 如何使用VS2017将客户端库添加到ASP.NET CORE 2.2(简单方法)
- golang 单协程和多协程的性能测试
- vc6.0 debug 比 release 快??_全网稀缺的快应用开源项目熊宝儿歌故事QuickApp
- android 圆角图片 imageview,【android 图片圆角设定】CustomImageView简单一览
- SAP UI5 应用开发教程之六十一 - 在 SAP UI5 应用里绘制甘特图 Gantt Chart 试读版
- 手机 android.downloader病毒,Android手机出现史上最强木马 感染后无法删除
- 营销公众号该如何运营大纲
- 微信小程序---简约音乐播放器
- 中英文常用标点符号统一清洗为英文格式
- 武林传奇之七剑下天山java游戏开发商_拓展训练项目之七剑下天山
- 金立Android版本,金立amigo为国内首个安卓5.0手机操作系统
- log(一)——MDC入门
- 第二章 聚合数据模型
- Pulling is not possible because you have unmerged files.
- 浅谈 ext2 文件系统的特点、优缺点以及使用场景
- 远程计算机桌面登录拒绝访问,win7远程界面显示拒绝访问
- 使用RTOS系统如何选取大容量存储芯片NAND FLASH
热门文章
- xshell远程连接服务
- SpringBoot 部署: 项目打包 手动部署到阿里云服务器上
- java 一元 二元 三元_一元、二元和三元关系
- 物联网IoT平台 设备影子服务 业务流程
- vue 3D地球 转动
- 【技术篇】详解,网络穿透,P2P,打洞的核心原理丨NAT,穿透的原理丨实现网络穿透
- Cannot resolve the collation conflict between “SQL_Latin1_General_CP1_CI_AS“ and “Latin1_General_CI_
- 论文浅尝 - ESWC2020 | YAGO 4: A Reason-able Knowledge Base
- java word标签替换_用java替换word文档模板中的变量
- 开源办公开发平台新应用——办公用品管理功能上线!