本文由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相关推荐

  1. 正点原子delay函数移植到rt thread操作系统(HAL库)

    正点原子教程中涉及到的操作系统只涉及了UCOS的教程,其中例程的system文件夹中的delay.c函数只是适配了UCOS. 下面将delay.c函数移植到rt thread中,使用的bsp是rt t ...

  2. 【国产MCU移植】移植RT-Thread到国产芯片HC32L196

    大家好我是惊觉.是的,失踪人口回来了.最近参加了rt-thread的国产MCU移植活动,移植rt-thread到华大的HC32L196.rtt论坛中已有许多介绍移植到各种平台的文章,详细讲述移植步骤, ...

  3. stm32移植到国产MCU雅特力AT32

    第一章 STM32移植AT32 概述 前言 雅特力科技于2016年在重庆成立的国产MCU品牌,全系列产品采用55nm先进工艺主打M4内核的高性能32位单片机,目前正式发布的有AT32F403.AT32 ...

  4. RT Thread Free Modbus移植问题整理

    RT Thread Free Modbus移植问题整理 问题描述: 在读写寄存器中,写数据正常,只能读1个寄存器的值,多个值会异常. 在移植过程中发现串口(或RS485)数据接收长度异常. 一.环境描 ...

  5. STM32的国产替代,盘点下我知道的国产MCU

    电子元件涨价和缺货是多少嵌入式工程师的痛,一年内上游厂家晶圆产能告急能有数十次之多.而MCU更是重灾区,且不说国内有超75%的市场都是被国外产品占据,就是本国内的代理和供应商也是漫天要价,而交期更是长 ...

  6. 文末赠书《GD32 MCU原理及固件库开发指南》5本 | 国产MCU中GD32系列有望成为未来32位MCU的主流

    学习优秀博文([guo产MCU移植]手把手教你使用RT-Thread制作GD32系列BSP)有感 一篇优秀的博文是什么样的?它有什么规律可循吗?优秀的guo产32位单片机处理器是否真的能成功替换掉st ...

  7. MCU不再“芯慌慌”,国产新品Air101帮你忙

    "全球缺芯,最缺是MCU!"这两年在疫情.政治因素等复杂背景交织下,MCU价格呈几十倍甚至几百倍上涨之势,如同翻着筋斗云:纵然舍得大价钱,漫漫交期也让人心慌慌.更别提开发切换之难, ...

  8. 客户回访|国产MCU测试解决方案 助力中国“芯”智造

    半导体技术持续更新迭代,MCU也在与时俱进,为了更好地迎接市场未来趋势,国产MCU厂商积极布局各系列MCU产品线,开始逐渐在特定细分领域实现突破.随着应用场景的进化升级,MCU 中包含越来越多的功能模 ...

  9. 灵动微MM32SPIN360C获选2020年度国产MCU评选

    由芯师爷主办.深福保集团冠名的"2020硬核中国芯"活动中,灵动微电子获选2020年度国产MCU评选. 企业介绍 灵动微电子是中国本土领先的通用32位MCU产品及解决方案供应商.公 ...

最新文章

  1. 函数-函数进阶-装饰器流程分析
  2. 基于GNS3的ssl配置
  3. screw (螺丝钉) ~ 简洁好用的数据库表结构文档生成工具
  4. 如何使用VS2017将客户端库添加到ASP.NET CORE 2.2(简单方法)
  5. golang 单协程和多协程的性能测试
  6. vc6.0 debug 比 release 快??_全网稀缺的快应用开源项目熊宝儿歌故事QuickApp
  7. android 圆角图片 imageview,【android 图片圆角设定】CustomImageView简单一览
  8. SAP UI5 应用开发教程之六十一 - 在 SAP UI5 应用里绘制甘特图 Gantt Chart 试读版
  9. 手机 android.downloader病毒,Android手机出现史上最强木马 感染后无法删除
  10. 营销公众号该如何运营大纲
  11. 微信小程序---简约音乐播放器
  12. 中英文常用标点符号统一清洗为英文格式
  13. 武林传奇之七剑下天山java游戏开发商_拓展训练项目之七剑下天山
  14. 金立Android版本,金立amigo为国内首个安卓5.0手机操作系统
  15. log(一)——MDC入门
  16. 第二章 聚合数据模型
  17. Pulling is not possible because you have unmerged files.
  18. 浅谈 ext2 文件系统的特点、优缺点以及使用场景
  19. 远程计算机桌面登录拒绝访问,win7远程界面显示拒绝访问
  20. 使用RTOS系统如何选取大容量存储芯片NAND FLASH

热门文章

  1. xshell远程连接服务
  2. SpringBoot 部署: 项目打包 手动部署到阿里云服务器上
  3. java 一元 二元 三元_一元、二元和三元关系
  4. 物联网IoT平台 设备影子服务 业务流程
  5. vue 3D地球 转动
  6. 【技术篇】详解,网络穿透,P2P,打洞的核心原理丨NAT,穿透的原理丨实现网络穿透
  7. Cannot resolve the collation conflict between “SQL_Latin1_General_CP1_CI_AS“ and “Latin1_General_CI_
  8. 论文浅尝 - ESWC2020 | YAGO 4: A Reason-able Knowledge Base
  9. java word标签替换_用java替换word文档模板中的变量
  10. 开源办公开发平台新应用——办公用品管理功能上线!