Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
国产MCU移植
复旦微
【国产MCU移植】移植RT-Thread到国产芯片FM33LC026
发布于 2021-09-06 16:09:34 浏览:2807
订阅该版
[tocm] ### 摘要 因为项目需要,使用了复旦微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。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/e9c2f7e7118f5da7a5c3a306c706c413.png.webp) Stm32的libraries一起挪到新工程目录下。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/1acbbb85599078e8b5c128b3a5b3a52f.png.webp) 只搞了keil5的工程,其它没用的删掉。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/0eaa06825010356fc8807d5aefda12b5.png.webp) 修改keil5工程。 项目工程是工具通过template模板生成的,所以,修改型号只需要修改template.uvprojx就可以了。 打开template.uvprojx 修改芯片型号为FM33LC02X,其余大部分会根据选择的芯片自动修改。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/b271390c55de838ef7578e1e4acfe7c4.png) 再进入linker,分散加载文件修改一下。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/7f8b69a4e065be0fbeada3f45a4bf3f5.png) template模板修改完成,接下来需要用模板生成工程,由于工程是STM32拷贝出来的,一些相对路径等会有变化,脚本会有问题,先进行一下修改。 修改fm33lc026文件夹下SConstruct文件,文本文档打开,这里路径改为如图的路径。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/1268e3d9ea193017b62962908a8bce66.png.webp) 修改fm33lc026文件夹下Kconfig文件,修改如下。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/348d0e595d55852133412de9a2dd8cc4.png) 修改好了,通过env工具,menuconfig,啊哈,报错了。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/c8723ec575223790d98c1749f94fe2ab.png.webp) 根据报错信息,还需要修改board/Kconfig下libraries的路径。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/592baffed9d9738212000ed2fc4fe194.png) 修改完成,menuconfig打开,现在还是原来工程的配置,接下来还需要继续修改,退出,生成一下keil5工程,打开工程,各配置正常,文件路径都可以找到,工程搭建完毕。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/d5b5ad2147aa627c0344e418accfd7d0.png) ### 添加复旦微官方库 接下来,添加复旦微FM33LC0XX的官方库函数到路径下。 需要替换掉原本STM32的官方HAL库。 STM32的库函数和驱动文件都在`\libraries`文件夹下,也就是刚才我们复制到工程内的文件夹。 我们只需要进入`\libraries`文件夹下,把官方库函数文件夹添加进来,通过修改脚本,让它自己添加就OK了。 打开`\libraries`文件夹,先看一下文件结构。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/8519e6c65f602919e1db3085ea23bb9e.png) 把STM32的HAL库全部删掉,找到官方的FM33LC0xx_FL_Driver库,复制一份进来。同时FM33LC0XX内核相关文件也复制进来。新的目录结构如下,驱动文件留着,低层驱动需要套接到内核驱动层,在原本STM32的修改就可以了。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/5d2ad5e23a1e0b52fc7854a52e3aab21.png) 修改Kconfig ![image.png](https://oss-club.rt-thread.org/uploads/20210906/55f07246971a4c794985d067797bfd1c.png) 进入接下来的文件夹,继续修改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目录下。打开。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/fc110d11defe88169cd99261b081520c.png.webp) 改为如下: ![image.png](https://oss-club.rt-thread.org/uploads/20210906/458ec235bdf33c36e6f55df81e943764.png.webp) 进入HAL_Drivers文件夹下。 因为我只适配了串口驱动,删掉没用的文件。删完如下图。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/0d71f775a8a5699d93c8aa6c2baf0400.png) Config文件夹下 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/f636a473e4eeb7baad9c904b7ef4fe0c.png) 修改SConscript,都是根据宏定义添加drv_XXX.c到工程。 Emmmm,算了,不修改了,以后添加驱动还要加回来,顶多生成的工程找不到相应的drv_.c,基本没啥影响。 使用env生成一下工程,报错了,根据报错信息,找到报错的位置。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/59fe7bafb1f4651fc924ba68a32cf7fd.png.webp) 打开报错的文件,官方库路径在这一步修改过,需要重新修改。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/f692f1694a89a1a54b0f1e7231d17e44.png.webp) 重新生成工程,成功,打开工程,库文件也添加成功。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/3701456cbc2e80f1a3ebd55a1b0f611d.png) ### 板级初始化 相关库函数已经添加成功,接下来,要让单片机运行起来,并且进入系统。 启动流程可以看[RT_Thread官方文档](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-nano/nano-port-principle/an0044-nano-port-principle)。这里借用一张图。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/7e69a374ee048be3a7b24842117e5f8e.png) 要修改的有,.s启动文件,rt_hw_board_init()函数内相关的内容。 添加完官方库文件后,打开keil5工程,会发现.s启动文件还是STM32F072的,这里,我们要修改一下。 打开board文件夹,打开SConscript,修改启动文件路径,修改如下。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/2e7f9ec25e5ce6b986f8d54b77ae44f5.png.webp) 还有一个Kconfig文件,和启动无关,顺路也修改一下。里面主要是menuconfig里单片机设备等的配置菜单,修改成我们需要的。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/6ed652f3c9c4cb4daae721b301694f68.png.webp) 进入工程board文件夹,删掉STM32的CubeMX文件夹。 删掉linker_scripts分散加载文件(分散加载相关在最前面已经配置了,如果需要分散加载文件,推荐不删,把文件内容改成FM33LC0XX的即可)。 OK.. 进入env,打开menuconfig,发现串口图形化配置已经OK了。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/d290cff7660a785675230cb9c07d0d35.png.webp) 退出menuconfig,生成工程,打开工程,发现所有文件都添加完毕,接下来要修改代码了。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/5b9ed6f9b8c309b6580855c39cfdee09.png) 进行rt_hw_board_init()内相关的函数的修改。 直接上改好的吧,具体相关的自行查看源码,代码现已经合并到RT_Thread主分支。 打开drv_common.c,修改相关。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/5c2e97a1a34a107b927a87ef36301412.png.webp) 打开board.c ![image.png](https://oss-club.rt-thread.org/uploads/20210906/079d753ddb4e9edb166d1480c3f7024f.png) 板级初始化这部分就完成了。工程这部分编译还是会报错,因为串口驱动相关的代码还是STM32的。关于驱动部分的对接,在接下来的部分。 ### 对接串口驱动 关于设备,可以参考[官方设备文档](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/device/device) 继续引用一张图。 ![image.png](https://oss-club.rt-thread.org/uploads/20210906/b5a627aeaa1f369fc351ba3d8c181c14.png) 对应到工程: ![image.png](https://oss-club.rt-thread.org/uploads/20210906/a98412db2aee980a4fbb89d87472a69a.png.webp) 简单来讲,就是写一个套接层,把官方的库函数套接到RT_Thread的设备管理层内。只需要修改设备驱动框架层,对应到工程就是keil5里Drivers里相关的代码。 打开Drivers分组,找到我们要修改的串口部分程序,分别为drv_usart.c,drv_usart.h,uart_config.h。同时,关于串口引脚的初始化,模仿STM32的bsp包,单独拿了出来,放到了board.c里。 首先是drv_usart.h文件,定义了串口配置结构体和串口设备结构体,删掉原来STM32的,修改成如下: 串口配置结构体,一些需要单独进行配置的部分单拉出来。 ```c /* config class */ struct _uart_config { const char *name; void *InitTypeDef; IRQn_Type irq_type; uint32_t clockSrc; }; ``` 串口结构体,通用的,不需要修改的部分。 ```c /* 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里的宏定义进行配置。 ```c enum { #ifdef BSP_USING_UART0 UART0_INDEX, #endif #ifdef BSP_USING_UART1 UART1_INDEX, #endif #ifdef BSP_USING_UART4 UART4_INDEX, #endif #ifdef BSP_USING_UART5 UART5_INDEX, #endif #ifdef BSP_USING_LPUART0 LPUART0_INDEX, #endif #ifdef BSP_USING_LPUART1 LPUART1_INDEX, #endif }; static struct _uart_config uart_config[] = { #ifdef BSP_USING_UART0 UART0_CONFIG, #endif #ifdef BSP_USING_UART1 UART1_CONFIG, #endif #ifdef BSP_USING_UART4 UART4_CONFIG, #endif #ifdef BSP_USING_UART5 UART5_CONFIG, #endif #ifdef BSP_USING_LPUART0 LPUART0_CONFIG, #endif #ifdef BSP_USING_LPUART1 LPUART1_CONFIG, #endif }; ``` 串口的操作方法函数,这里不详细列出,需要把这几个结构体里函数修改完成。 ```c static const struct rt_uart_ops _uart_ops = { .configure = uart_configure, .control = uart_control, .putc = uart_putc, .getc = uart_getc, .dma_transmit = 0 }; ``` 串口的注册函数,将串口设备注册到设备管理层。 ```c 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里包含,给串口配置结构体赋值,需要填入对应的串口中断向量地址等: ```c #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里放入了串口引脚初始化,和其他一些关于硬件底层的配置。 ```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函数里点灯 ```c 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); } } ``` 完毕。 ## 总结 没有总结,第一次写技术文档,欢迎大家学习交流。
7
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
jiao96
这家伙很懒,什么也没写!
文章
1
回答
6
被采纳
0
关注TA
发私信
相关文章
1
官方有没有移植到STC32的计划
2
哪些国产MCU移植了rtthread
3
Studio何时能支持其他国产IC
4
rtthread studio增加APM32国产芯片支持
5
有没有做过cw32的rtthread的移植啊
6
RT-Thread 对 STM32 支持的很好,哪款国产芯片支持的最好呀?
7
如何让RT thread适配一款新的芯片?
8
我想学习怎么移植rtt,需要怎么学习,有什么好的学习路线吗
9
请教复旦微芯片fm33lc046的drv_spi.c 问题
10
kconfig下添加spi为什么没有引脚设置
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
8
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部