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
    +关注

    关注

    32

    文章

    1540

    浏览量

    44267

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

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

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    RISC-V单片机快速入门02,移植RT_Thread Nano系统

    。 (2)在基础工程中添加 RT-Thread Nano 源码,添加相应的文件路径。 (3)适配 Nano,主要从 中断、时钟、内存、应用 这几个方面进行适配,实现移植。 (
    发表于 11-10 07:23

    FlashDB移植rt-thread nano,运行时控制台无输出怎么解决?

    rt-thread标准版和HAL裸机版,移植非常成功,换成nano 3.15版,就出现控制台无输出,也无法输入,调试时进入死循环,如图所示 ,关闭hook也不行,请求指点。谢谢! 上传测试代码,用的是
    发表于 10-11 09:34

    移植最新版的rt-thread nano时程序进入到entry就报错,为什么?

    我在移植最新版的rt-thread nano时发现程序只要一进去entry函数就直接跳到一个死循环里,我使用的编译器是armgcc10.2版本。然而我移植旧版的
    发表于 10-09 07:17

    如何移植rt-thread到野火imx6ull开发板

    求助如何将rt-thread移植到野火imx6ull(coretex-A7)开发板,官方的bsp中没有imx6ull
    发表于 09-29 06:25

    使用RT-Thread studio 开发RT-Thread Nano项目的时候 串口的驱动是要自己写吗?

    刚入坑。使用RT-Thread studio 开发RT-Thread 标准板项目的时候直接使用里边的串口uart_dev=rt_device_find(“uart5”);然后操作设备,在开发R
    发表于 09-26 08:14

    CubeMX移植RT-Thread 3.1.5文件重复怎么解决?

    CubeMX6.7.0内移植RT-Thread Nano3.1.5文件重复,主要是两个部分 1、 和 两个地方重复rtconfig.h 2、shell相关的文件也会重复 和 请问下各位有没有办法可以解决这个问题的?
    发表于 09-24 07:11

    何在RT-Thread创建一个GD32F470工程?

    何在RT-Thread创建一个GD32F470工程
    发表于 09-23 06:09

    RT-Thread Nano移植后动态创建线程创建不了怎么解决?

    RT-Thread Nano 移植后动态创建线程创建不了,静态可以.直接烧录DEMO也一样,将RT_USING_HEAP开起来,使用动态创建就创建不起来,
    发表于 09-19 06:28

    恩智浦MCU教程 基于MCUXpresso和FRDM-MCXA346的RT-Thread Nano移植

    本篇还是以移植RT-Thread Nano到MCUXpresso IDE为主,移植的代码可以在nxpic.org.cn论坛搜索到。
    的头像 发表于 08-21 09:49 6226次阅读
    恩智浦MCU教程 基于MCUXpresso和FRDM-MCXA346的<b class='flag-5'>RT-Thread</b> <b class='flag-5'>Nano</b><b class='flag-5'>移植</b>

    如何移植 RT-Thread Nano 并创建 2 个线程?

    基于 BSP 中的 GPIO_OutputInput 演示,展示了如何移植 RT-Thread Nano 并创建 2 个线程。
    发表于 08-19 07:45

    RT-Thread Nano硬核移植指南:手把手实现VGLite图形驱动适配 | 技术集结

    VGLite是NXP提供的轻量级2D图形API,本文将手把手带你实现VGLite图形驱动适配RT-Thread。文章分为、下两篇,将手把手教您移植。上篇对RT-ThreadNano内
    的头像 发表于 07-17 14:40 3039次阅读
    <b class='flag-5'>RT-Thread</b> <b class='flag-5'>Nano</b>硬核<b class='flag-5'>移植</b>指南:手把手实现VGLite图形驱动适配 | 技术集结

    RT-Thread Nano移植后动态创建线程创建不了怎么处理?

    RT-Thread Nano移植后动态创建线程创建不了,静态可以.直接烧录DEMO也一样,将RT_USING_HEAP开起来,使用动态创建就创建不起来,
    发表于 06-11 06:36

    移植最新版的rt-thread nano时发现程序只要一进去entry函数就直接跳到一个死循环里,为什么?

    我在移植最新版的rt-thread nano时发现程序只要一进去entry函数就直接跳到一个死循环里,我使用的编译器是armgcc10.2版本。然而我移植旧版的
    发表于 04-01 07:04

    如何将RT-Thread移植到NXP MCUXPressoIDE

    RT-Thread默认支持的IDE只有IAR 和 Keil, 那如何将RT-Thread移植到NXP MCUXPressoIDE呢?本文内容比较简单但稍有琐碎,希望对有需要的小伙伴有
    的头像 发表于 02-13 10:37 2431次阅读
    如何将<b class='flag-5'>RT-Thread</b><b class='flag-5'>移植</b>到NXP MCUXPressoIDE<b class='flag-5'>上</b>

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

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