0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何在在HK32F030MF4P6上移植RT-Thread Nano

Linux阅码场 来源:RT-Thread物联网操作系统 作者:RT-Thread物联网操作 2021-08-02 17:59 次阅读

这是一个航顺 HK32F030 的 RT-Thread Nano 移植示例,记录了在 Keil 裸机工程的基础上进行 RT-Thread Nano 移植的全过程。在按文档中心的指导进行移植的过程中基本没有遇到问题,只是由于 HK32F030 的RAM 较小,无法启用 FinSH。移植工程已经分享在Gitee RT-Thread-Nano-HK32F030。

开源地址:https://gitee.com/CraztTnspt/rt-thread-nano-hk32-f030

(请复制至外部浏览器打开)

硬件信息

MCU: 航顺 HK32F030MF4P6 , RAM: 2KB, ROM:16KB

开发板:hk32f030 - 立创EDA (https://lceda.cn/whj4674672/hk32f030)由 @whj467467222 设计

参考文档

RT-Thread Nano 简介与下载(https://docs.rt-thread.org/#/rt-thread-version/rt-thread-nano/an0038-nano-introduction)

0.准备移植

在移植 RT-Thread Nano 之前,需要准备一个能正常运行的裸机工程。航顺的库文件包 HK32F030Mxx_Library_V1.1.4.7z 中提供了 HK32F030 的标准库、启动文件等,还有一个裸机工程模板,整理后得到这里移植使用的裸机工程。

编译后烧录,看到LED闪烁,裸机程序正常运行。实测可以使用Jlink 或 CMSIS-DAP 烧录调试,而使用 ST-Link 无法识别到 HK32F030。

之后就可以开始 RT-Thread Nano 的移植了。

1.Nano Pack 安装

Nano Pack 可以在 Keil MDK IDE 内进行安装,也可以手动安装。这里选择手动安装Pack,从官网下载安装文件:RT-Thread Nano 离线安装包,下载结束后双击文件进行安装。

然后将 RT-Thread Nano 添加到工程中。点击 Manage Run-Time Environment

在 Manage Rum-Time Environment 内打开 RTOS 栏,勾选 kernal,点击 OK 后就将 RT-Thread 内核加入到工程中了。

现在能在 Keil 的 Project 栏看到 RTOS,展开后可以看到 RT-Thread Nano 的文件已经加入了工程。

2.适配 RT-Thread Nano

中断与异常处理

RT-Thread 会接管异常处理函数 HardFault_Handler() 和悬挂处理函数 PendSV_Handler(),这两个函数已由 RT-Thread 实现,所以需要删除工程里中断服务例程文件 Drivers/hk32f030m_it.c 中的这两个函数,避免在编译时产生重复定义。如果此时对工程进行编译,没有出现函数重复定义的错误,则不用做修改。

系统时钟配置

现在需要在 RTOS/board.c 中实现 系统时钟配置(为 MCU、外设提供工作时钟)与 os tick 的配置 (为操作系统提供心跳 / 节拍)。

1void rt_hw_board_init()

2{

3 /* System Clock Update */ 4 SystemCoreClockUpdate();

5 6 /* System Tick Configuration */ 7 _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);

8 9 /* Call components board initial (use INIT_BOARD_EXPORT()) */10#ifdef RT_USING_COMPONENTS_INIT11 rt_components_board_init();

12#endif1314#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)15 rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());

16#endif17}

上面的代码中,SystemCoreClockUpdate() 对系统时钟进行更新,_SysTick_Config() 配置了 OS Tick。此处 OS Tick 使用滴答定时器 systick 实现,需要在 board.c 中实现 SysTick_Handler() 中断服务例程,调用 RT-Thread 提供的 rt_tick_increase() ,如下:

1void SysTick_Handler(void)

2{

3 /* enter interrupt */ 4 rt_interrupt_enter();

5 6 rt_tick_increase();

7 8 /* leave interrupt */ 9 rt_interrupt_leave();

10}

由于 SysTick_Handler() 中断服务例程由用户在 board.c 中重新实现,作为系统 OS Tick,所以还需要删除工程里中原本已经实现的 SysTick_Handler() ,避免在编译时产生重复定义。如果此时对工程进行编译,没有出现函数重复定义的错误,则不用做修改。

内存堆初始化

系统内存堆的初始化在 board.c 中的 rt_hw_board_init() 函数中完成,内存堆功能是否使用取决于宏 RT_USING_HEAP 是否开启,RT-Thread Nano 默认不开启内存堆功能,这样可以保持一个较小的体积,不用为内存堆开辟空间。开启系统 heap 将可以使用动态内存功能,如使用 rt_malloc、rt_free 以及各种系统动态创建对象的 API。若需要使用系统内存堆功能,则打开 RT_USING_HEAP 宏定义即可,此时内存堆初始化函数 rt_system_heap_init() 将被调用。

3.编写第一个应用

移植好 RT-Thread Nano 之后,则可以开始编写第一个应用代码验证移植结果。此时 main() 函数就转变成 RT-Thread 操作系统的一个线程,现在可以在 main() 函数中实现第一个应用:板载 LED 指示灯闪烁。

首先在文件首部增加 RT-Thread 的相关头文件 《rtthread.h》 。

在 main() 函数中(也就是在 main 线程中)实现 LED 闪烁代码:初始化 LED 引脚、在循环中点亮 / 熄灭 LED。

将延时函数替换为 RT-Thread 提供的延时函数 rt_thread_mdelay()。该函数会发起系统调度,切换到其他线程运行,体现了线程的实时性。

此时可以看到 LED 闪烁,虽然现象与裸机程序一致,但 RT-Thread 已经在 HK32F030 上成功运行。

使用 RTOS 造成固件变大后,通过CMSIS-DAP 烧录程序可能出现失败现象

将 CMSIS-DAP 的 SW 调试速度调低为 500kHz 后烧录成功

4.移植控制台 FinSH

由于 RAM 的大小有限,这里 FinSH 的移植未能完成

在 Nano 上添加 UART 控制台

在 RT-Thread Nano 上添加 UART 控制台打印功能后,就可以在代码中使用 RT-Thread 提供的打印函数 rt_kprintf() 进行信息打印,从而获取自定义的打印信息,方便定位代码 bug 或者获取系统当前运行状态等。实现控制台打印(需要确认 rtconfig.h 中已使能 RT_USING_CONSOLE 宏定义),需要完成基本的硬件初始化,以及对接一个系统输出字符的函数,本小节将详细说明。

实现串口初始化

使用串口对接控制台的打印,首先需要初始化串口,如引脚、波特率等。 uart_init() 需要在 board.c 中的 rt_hw_board_init() 函数中调用。

1static int uart_init(void);

示例代码:如下是基于 HK32 库的 HK32F030 串口初始化程序,参考航顺例程编写。实现了串口的发送并配置了串口中断接收。

1#define USART1_TX_PORT GPIOA 2#define USART1_TX_PIN GPIO_Pin_3 3#define USART1_TX_IO_CLK_EN() RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE) 4 5#define USART1_RX_PORT GPIOD 6#define USART1_RX_PIN GPIO_Pin_6 7#define USART1_RX_IO_CLK_EN() RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE) 8 9static void USART_GPIO_Configurature(void);

10static void USART_NVIC_Configurature(void);

11static int uart_init(void);

1213static int uart_init(void)

14{

15 USART_InitTypeDef m_usart;

1617 USART_GPIO_Configurature();

1819 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

20 m_usart.USART_BaudRate = 115200;

21 m_usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

22 m_usart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

23 m_usart.USART_Parity = USART_Parity_No;

24 m_usart.USART_StopBits = USART_StopBits_1;

25 m_usart.USART_WordLength = USART_WordLength_8b;

26 USART_Init(USART1, &m_usart);

27 USART_Cmd(USART1, ENABLE);

2829 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

3031 USART_NVIC_Configurature();

3233 return 0;

34}

35//INIT_BOARD_EXPORT(uart_init);3637static void USART_GPIO_Configurature(void)

38{

39 GPIO_InitTypeDef m_gpio;

4041 USART1_TX_IO_CLK_EN();

42 USART1_RX_IO_CLK_EN();

4344 m_gpio.GPIO_Mode = GPIO_Mode_AF;

45 m_gpio.GPIO_OType = GPIO_OType_PP;

46 m_gpio.GPIO_Pin = USART1_TX_PIN;

47 m_gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;

48 m_gpio.GPIO_Speed = GPIO_Speed_10MHz;

49 GPIO_Init(USART1_TX_PORT, &m_gpio);

50 GPIO_PinAFConfig(USART1_TX_PORT,GPIO_PinSource3,GPIO_AF_1);

5152 m_gpio.GPIO_Pin = USART1_RX_PIN;

53 GPIO_Init(USART1_RX_PORT, &m_gpio);

54 GPIO_PinAFConfig(USART1_RX_PORT,GPIO_PinSource6,GPIO_AF_1);

55}

56static void USART_NVIC_Configurature(void)

57{

58 NVIC_SetPriority(USART1_IRQn,0);

59 NVIC_EnableIRQ(USART1_IRQn);

60}

实现 rt_hw_console_output

实现 finsh 组件输出一个字符,即实现 uart 输出一个字符:

注:注意:RT-Thread 系统中已有的打印均以 结尾,而并非 ,所以在字符输出时,需要在输出 之前输出 ,完成回车与换行,否则系统打印出来的信息将只有换行。

示例代码:如下是基于HK32 库实现的串口驱动对接 rt_hw_console_output()

1void USART1_SendByte(uint8_t ch)

2{

3 while((USART1-》ISR & USART_ISR_TXE) == 0);

4 USART1-》TDR = ch;

5}

6void rt_hw_console_output(const char *str)

7{

8 rt_size_t i = 0, size = 0;

9 char a = ‘

’;

1011 size = rt_strlen(str);

12 for (i = 0; i 《 size; i++)

13 {

14 if (*(str + i) == ‘

’)

15 {

16 USART1_SendByte((uint8_t)a);

17 }

18 USART1_SendByte(*(str + i));

19 }

20}

将对应代码加入 board.c ,编译并烧录后,可以看到终端(或串口助手中输出的rtt logo):

932133e0-e032-11eb-9e57-12bb97331649.png

至此就可以使用 rt_kprintf() 打印调试信息了。

在 Nano 上添加 FinSH 组件

RT-Thread FinSH 是 RT-Thread 的命令行组件(shell),提供一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。它可以使用串口 / 以太网 / USB 等与 PC 机进行通信。这里使用串口方式,在 Nano 上实现 FinSH 功能。

Keil 添加 FinSH 源码

打开 Manage Run-Environment。

勾选 shell 然后点击OK,将 FinSH 组件的源码到工程。

这时看到 RTOS Group 中加入了以下 FinSH 文件。

实现 rt_hw_console_getchar()

要实现 FinSH 组件功能(既可以打印也能输入命令进行调试),需要在 board.c 中对接控制台输入函数,实现字符输入:

rt_hw_console_getchar():控制台获取一个字符,即在该函数中实现 uart 获取字符,可以使用查询方式获取(注意不要死等,在未获取到字符时,需要让出 CPU),也可以使用中断方式获取。

示例代码:(未实现)

1char rt_hw_console_getchar(void)

2{

3 int ch = -1;

4 // 接收一个字符5 。。.

6 return ch;

7}

加入 FinSH 后 RAM 空间不足

这时编译会出现报错:

939ee5ba-e032-11eb-9e57-12bb97331649.png

看编译输出应该是存储空间不足,超出RAM大小154 Bytes,尝试将编译器优化等级调高至 Level2 ,但仍会报错。

然后尝试在 rtconfig.h 中调小 RT_CONSOLEBUF_SIZE 与 FINSH_THREAD_STACK_SIZE ,编译成功。可以看此时的内存占用:Program Size: Code=9458 RO-data=922 RW-data=144 ZI-data=1832 ,ROM占用为 Code+RO+RW=10524 Byte,RAM 占用为 RW+ZI=1976 Byte,RAM即将耗尽。同时因为调小了线程运行栈,程序运行时会产生 hard fault,因此不再考虑将 finsh 移植至nano上。

为了正常使用,应当关闭 FinSH 组件,在RTE_Components.h中注释 RTE_USING_FINSH,此时程序大小为:Program Size: Code=5756 RO-data=572 RW-data=120 ZI-data=1264 ,ROM占用为 Code+RO+RW=6448 Byte,RAM 占用为 RW+ZI=1384 Byte,剩余空间较为充裕。也可以通过在 Manage Run-Environment 中关闭 shell,移除 FinSH 组件。

至此,在 HK32F030MF4P6 上的 RT-Thread Nano 移植工作就完成了。

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • RT-Thread
    +关注

    关注

    31

    文章

    1285

    浏览量

    40095

原文标题:【国产MCU系列】在 HK32F030 上移植 RT-Thread Nano

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    HK32F030MF4P6最小系统板原理图及PCB文件

    方便验证 HK32F030MF4P6 性能的最小系统板原理图和PCB文件,所有IO都有引出,适合需要验证单片机性能但不想要画板的小伙伴。原理图:PCB 预览:注意:因为IO口都是直接引出,请不要将其接到超过额定电压承受范围的电路上!
    发表于 12-23 18:00 0次下载

    RT-ThreadCAN实践

    开箱测试RT-Thread官方已完成了对英飞凌XMC7200EVK的移植,通过shell可以看到做好了uart3的console。本文将介绍如何进行RT-ThreadCan移植。接下来
    的头像 发表于 11-13 01:03 1150次阅读
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>上</b>CAN实践

    何在RT-thread studio的裸机例程移植freertos?

    何在RT-thread studio的裸机例程移植freertos
    发表于 09-13 06:32

    RT-Thread 新里程碑达成——GitHub Star 破万!

    RT-Thread实时操作系统开源项目在GitHub的star数量突破一万!截止发文,RT-Thread作为实时操作系统在业界Star数量排名第一!仓库地址:https://github.com
    的头像 发表于 07-04 08:35 472次阅读
    <b class='flag-5'>RT-Thread</b> 新里程碑达成——GitHub Star 破万!

    lvgl移植RT-Thread Nano后进入硬件错误中断的原因?

    使用的是RT-Thread Nano的最新版,第一次移植,不知道是不是因为这个lvgl只能移植到标准版里? 尝试过给lvgl的线程分配更大的栈,但是依旧会卡死在硬件错误中断里。但只要把
    发表于 07-04 07:40

    66日杭州站RT-Thread线下workshop,探索RT-Thread混合部署新模式!

    66日下午我们将在杭州举办RT-Thread混合部署线下workshop,在瑞芯微RK3568平台实现同时运行RT-Thread和lin
    的头像 发表于 05-28 08:35 442次阅读
    <b class='flag-5'>6</b>月<b class='flag-5'>6</b>日杭州站<b class='flag-5'>RT-Thread</b>线下workshop,探索<b class='flag-5'>RT-Thread</b>混合部署新模式!

    RT-Thread混合部署Workshop北京站来啦!

    4月25日,下午我们将在北京举办RT-Thread混合部署线下workshop,在瑞芯微RK3568平台实现同时运行RT-Thread和linux,本次workshop邀请到
    的头像 发表于 04-19 08:34 437次阅读
    <b class='flag-5'>RT-Thread</b>混合部署Workshop北京站来啦!

    4月25日北京站RT-Thread线下workshop,探索RT-Thread混合部署新模式

    4月25日,下午我们将在北京举办RT-Thread混合部署线下workshop,在瑞芯微RK3568平台实现同时运行RT-Thread和linux,本次workshop邀请到
    的头像 发表于 04-16 08:35 417次阅读
    <b class='flag-5'>4</b>月25日北京站<b class='flag-5'>RT-Thread</b>线下workshop,探索<b class='flag-5'>RT-Thread</b>混合部署新模式

    4月10日-深圳-workshop】RT-Thread带你探索混合部署新模式

    4月10日我们将在深圳福田举办RT-Thread混合部署线下workshop,在瑞芯微RK3568平台实现同时运行RT-Thread和linux,本次workshop邀请到
    的头像 发表于 04-04 08:34 340次阅读
    【<b class='flag-5'>4</b>月10日-深圳-workshop】<b class='flag-5'>RT-Thread</b>带你探索混合部署新模式

    4月10日深圳场RT-Thread线下workshop,探索RT-Thread混合部署新模式!

    4月10日我们将在深圳福田举办RT-Thread混合部署线下workshop,在瑞芯微RK3568平台实现同时运行RT-Thread和linux,本次workshop邀请到
    的头像 发表于 03-27 11:36 817次阅读
    <b class='flag-5'>4</b>月10日深圳场<b class='flag-5'>RT-Thread</b>线下workshop,探索<b class='flag-5'>RT-Thread</b>混合部署新模式!

    4月10日深圳场RT-Thread线下workshop,探索RT-Thread混合部署新模式!

    4月10日我们将在深圳福田举办RT-Thread混合部署线下workshop,在瑞芯微RK3568平台实现同时运行RT-Thread和linux,本次workshop邀请到
    的头像 发表于 03-27 08:34 528次阅读
    <b class='flag-5'>4</b>月10日深圳场<b class='flag-5'>RT-Thread</b>线下workshop,探索<b class='flag-5'>RT-Thread</b>混合部署新模式!

    何在STM32F407移植lwip?

    如题,使用rt-thread操作系统,在STM32F407如何移植lwip,下载了最新的rt-thread代码,不知如何入手。 谁能帮
    发表于 03-05 08:32

    基于CubeMX的RT-thread Nano可以添加microros这样的软件包吗?

    最近使用rt-thread配置一个ROS2,但是是用CubeMX联合Clion做的,CubeMX使用的是RT-thread nano包, 请问这个环境可以添加像microros这样的软件包吗?谢谢。
    发表于 03-01 06:00

    何在PSoC62 Evaluation kit开发板运行RT-Thread呢?

    本文主要介绍如何在PSoC62 Evaluation kit开发板运行RT-Thread,如何连接CYW43012 WiFi蓝牙模组,以及如何进行WiFi联网、网络延迟、网络带宽测试。
    的头像 发表于 02-27 10:49 1011次阅读
    如<b class='flag-5'>何在</b>PSoC62 Evaluation kit开发板<b class='flag-5'>上</b>运行<b class='flag-5'>RT-Thread</b>呢?

    移植RT-THREAD在stm32开发板,使用rt_kprintf不能正常打印的原因是什么?怎么解决?

    开发环境: STM32CubeMX 用于生成代码; STM32CubeIDE用于调试代码; 移植过程: 使用STM32CubeMX来移植RT-Thread;移植成功了;(操作LED
    发表于 02-20 06:24