搜索

[方案相关] 【华大测评】 HC32F460移植RT-Thread Nano

[复制链接]
926|2
 楼主 | 2020-9-20 17:58 | 显示全部楼层 |阅读模式
本帖最后由 Liyj336 于 2020-9-20 17:58 编辑

这一次测评我将一步步分享RT-Thread Nano移植到HC32F460的过程。主要分三步讲解工程建立、RT-Thread移植、添加UART控制台和Finsh。
一、工程建立

1、首先我们需要建立程序工程文件,下面的工程我是在HC32F460官方例程基础上建立的。在一个总的工程文件夹下面,建立以下工程文件夹。红色划线部分文件夹可以先忽略。(可以按照自己习惯建立工程)
工程目录2.jpg
BSP:打算存放MCU外部外设部分程序。
documents:从官方例程中复制过来,存放HC32F460官方库使用说明。
driver:从官方例程复制过来,存放HC32F460的驱动库。
mcu:从官方例程复制过来,MDK工程需要里面的文件。保留下面两个文件夹就行
mcu.JPG
MDK:存放MDK工程文件。我从例程icg_hrc_osc_hw_startup复制过来的,该例程跟Systick有关。
MDK.JPG
source:从官方移植过来的,存放main.c和其他一些程序文件。

2、打开MDK目录下的icg_hrc_osc_hw_startup工程。从新加入project下的文件。忽略打叉或者划线的文件,从刚建立的工程中加入以下文件。

MDK工程无RTT1.jpg

3、新建led.c和led.h文件放入到BSP下的src和inc文件夹内,并把led.c文件加入到MDK工程中。
led.c代码如下,只是一个简单的点灯代码,用来验证程序。

  1. #include <led.h>

  2. void LED_Init(void)
  3. {
  4.     /**************************************************************************/
  5.    
  6.     stc_port_init_t stcPortInit;

  7.     /* configure structure initialization */
  8.     MEM_ZERO_STRUCT(stcPortInit);

  9.     /* LED0 Port/Pin initialization */
  10.     LED0_OFF();
  11.     stcPortInit.enPinMode = Pin_Mode_Out;
  12.     PORT_Init(LED0_PORT, LED0_PIN, &stcPortInit);
  13. }
复制代码
led.h
  1. #ifndef        __LED_H
  2. #define        __LED_H

  3. #include "hc32_ddl.h"

  4. /*******************************************************************************
  5. * Local type definitions ('typedef')
  6. ******************************************************************************/

  7. /*******************************************************************************
  8. * Local pre-processor symbols/macros ('#define')
  9. ******************************************************************************/
  10. /* LED0 Port/Pin definition */
  11. #define LED0_PORT                       (PortE)
  12. #define LED0_PIN                        (Pin06)

  13. #define LED0_ON()                       (PORT_SetBits(LED0_PORT, LED0_PIN))
  14. #define LED0_OFF()                      (PORT_ResetBits(LED0_PORT, LED0_PIN))
  15. #define LED0_TOGGLE()                   (PORT_Toggle(LED0_PORT, LED0_PIN))


  16. void LED_Init(void);

  17. #endif        /*__LED_H*/
复制代码

4、接下来修改HDSC_HC32F46x.SFR文件路径,如下图红框内,其实我也不知道这个文件有什么作用。

设置截图1.jpg

然后从新加入头文件路径。
头文件.JPG


二、RT-Thread Nano移植

1、首先需要获取RT-Thread Nano源码,RT-Thread Nano是一个精简版的RT-Thread,去除很多板子的BSP和很多功能组件,组件上只保留了Finsh,当然RTOS的核心功能会保留着。RT-Thread Nano源码下载地址:https://www.rt-thread.org/page/download.html,目前最新版为V3.1.3。

获取到的RT-Thread文件夹目录如下。
RTT源码文件夹.JPG
2、在工程文件夹下,加入RT-thread文件夹,并在下RT-thread文件夹下加入Include、Port、Source文件夹,存放RT-thread所需文件。

工程目录1.JPG

RTT-MDK文件夹内容.JPG

3、将路径RT-Thread/3.1.3/include文件夹下的内容复制到新建的工程目录下的RT-thread/Include文件夹
将路径RT-Thread/3.1.3/components/finsh文件夹复制到新建的RT-thread/Include文件夹




4、将路径RT-Thread/3.1.3/source文件夹下面的 rtconfig.h和board.c文件复制到到工程目录下的source文件夹。
RTT-source.JPG
5、将路径RT-Thread/3.1.3/libcpu/arm/cortex-m3文件夹下面的 rtconfig.h和board.c文件复制到到工程目录下的port文件夹。
RTT-Port.JPG

6、打开hc32f46x_interrupts.c把SysTick_Handler、PendSV_Handler、HardFault_Handler这三个中断函数注释掉,要不然编译会出现重定义错误。

中断注释.JPG

7、修改RT-thread配置文件rtconfig.h头文件进行RTT的配置。里面是通过修改宏来实现的,可以根据实际情况进行修改。这里我不进行该文件修改,直接使用。rtconfig.h文件一些配置宏如下所示。

rtconfig.JPG

8、在 MDK source 目录下新建一个 board.h 头文件,用来包含HC32F460固件驱动库和BSP 相关的头文件。
source分2.jpg
board.h代码如下
  1. #ifndef __BOARD_H
  2. #define __BOARD_H

  3. #include "hc32_ddl.h"
  4. #include "led.h"
  5. #include "uart.h"

  6. void rt_hw_board_init(void);
  7. void SysTick_Handler(void);

  8. #endif    /*__BOARD_H*/
复制代码
9、修改board.c文件。board.c里面主要完成RT-thread的初始化,并对外设硬件完成初始化。
  1. /*
  2. * Copyright (c) 2006-2019, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date           Author       Notes
  8. * 2017-07-24     Tanek        the first version
  9. * 2018-11-12     Ernest Chen  modify copyright
  10. */

  11. #include <board.h>
  12. #include <stdint.h>
  13. #include <rthw.h>
  14. #include <rtthread.h>

  15. static void SysTick_Init(void);

  16. #if 0
  17. #define _SCB_BASE       (0xE000E010UL)
  18. #define _SYSTICK_CTRL   (*(rt_uint32_t *)(_SCB_BASE + 0x0))
  19. #define _SYSTICK_LOAD   (*(rt_uint32_t *)(_SCB_BASE + 0x4))
  20. #define _SYSTICK_VAL    (*(rt_uint32_t *)(_SCB_BASE + 0x8))
  21. #define _SYSTICK_CALIB  (*(rt_uint32_t *)(_SCB_BASE + 0xC))
  22. #define _SYSTICK_PRI    (*(rt_uint8_t  *)(0xE000ED23UL))

  23. // Updates the variable SystemCoreClock and must be called
  24. // whenever the core clock is changed during program execution.
  25. extern void SystemCoreClockUpdate(void);

  26. // Holds the system core clock, which is the system clock
  27. // frequency supplied to the SysTick timer and the processor
  28. // core clock.
  29. extern uint32_t SystemCoreClock;

  30. static uint32_t _SysTick_Config(rt_uint32_t ticks)
  31. {
  32.     if ((ticks - 1) > 0xFFFFFF)
  33.     {
  34.         return 1;
  35.     }
  36.    
  37.     _SYSTICK_LOAD = ticks - 1;
  38.     _SYSTICK_PRI = 0xFF;
  39.     _SYSTICK_VAL  = 0;
  40.     _SYSTICK_CTRL = 0x07;  
  41.    
  42.     return 0;
  43. }

  44. #endif

  45. #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
  46. #define RT_HEAP_SIZE 1024
  47. static uint32_t rt_heap[RT_HEAP_SIZE];     // heap default size: 4K(1024 * 4)
  48. RT_WEAK void *rt_heap_begin_get(void)
  49. {
  50.     return rt_heap;
  51. }

  52. RT_WEAK void *rt_heap_end_get(void)
  53. {
  54.     return rt_heap + RT_HEAP_SIZE;
  55. }
  56. #endif

  57. /**
  58. * This function will initial your board.
  59. */
  60. void rt_hw_board_init()
  61. {
  62.     /* System Clock Update */
  63.     //SystemCoreClockUpdate();
  64.    
  65.     /* System Tick Configuration */
  66.    // _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);

  67.     /* Call components board initial (use INIT_BOARD_EXPORT()) */
  68.       CLK_SetSysClkSource(ClkSysSrcHRC);                        //设置时钟源
  69.    
  70.       SysTick_Init();                                                         //Systick时钟初始化
  71.       
  72.      LED_Init();                                                               //外设LED初始化
  73.      LED0_ON();
  74.   
  75. #ifdef RT_USING_COMPONENTS_INIT
  76.     rt_components_board_init();
  77. #endif

  78. #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
  79.     rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
  80. #endif
  81. }

  82. void SysTick_Handler(void)
  83. {
  84.     /* enter interrupt */
  85.     rt_interrupt_enter();

  86.     rt_tick_increase();

  87.     /* leave interrupt */
  88.     rt_interrupt_leave();
  89. }

  90. static void SysTick_Init(void)
  91. {
  92.     stc_clk_freq_t stcClkFreq;

  93.     /* configure structure initialization */
  94.     MEM_ZERO_STRUCT(stcClkFreq);

  95.     /* Config 1 sec trigger interrupt*/
  96.     CLK_GetClockFreq(&stcClkFreq);
  97.     SysTick_Config(stcClkFreq.sysclkFreq/RT_TICK_PER_SECOND);
  98. }
复制代码

10、到这里RT_thread移植已经完成了,我们还是写个点灯程序测试一下。修改main.c函数

  1. #include "hc32_ddl.h"
  2. #include "led.h"
  3. #include "board.h"
  4. #include "rtthread.h"


  5. /*定义线程控制块*/
  6. static struct rt_thread led1_thread;

  7. /*定义线程空栈时要求RT_ALIGN_SIZE个字节对齐*/
  8. ALIGN(RT_ALIGN_SIZE)

  9. /*定义线程栈*/
  10. static rt_uint8_t rt_led1_thread_stack[1024];

  11. /*函数声明*/
  12. static void led1_thread_entry(void * parameter);


  13. /*******************************************************************************
  14. ** \brief  main function for ICG HRC function
  15. **
  16. ** \param [in]  None
  17. **
  18. ** \retval int32_t Return value, if needed
  19. **
  20. ******************************************************************************/
  21. int32_t main(void)
  22. {
  23.     rt_thread_init(&led1_thread,
  24.                                 "led1",
  25.                                 led1_thread_entry,
  26.                                 RT_NULL,
  27.                                 &rt_led1_thread_stack,
  28.                                 sizeof(rt_led1_thread_stack),
  29.                                 3,
  30.                                 20);
  31.     rt_thread_startup(&led1_thread);

  32. }

  33. static void led1_thread_entry(void * parameter)
  34. {
  35.     while(1)
  36.     {
  37.         LED0_ON();
  38.         rt_thread_delay(500);
  39.         LED0_OFF();
  40.         rt_thread_delay(500);
  41.     }   
  42. }
复制代码

11、好了,编译下载可以看看LED灯正常闪烁。


三、添加UART控制台和Finsh组件
在 RT-Thread Nano 上添加 UART 控制台打印功能后,就可以在代码中使用 RT-Thread 提供的打印函数 rt_kprintf() 进行信息打印。Finsh组件是 RT-Thread 的命令行组件(shell),提供一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。
1、在MDK工程中增加RTT_Component目录,并在目录下添加RT-thread/Include/finsh目录下的cmd.c、msh.c、shell.c文件
RTT组件.JPG

2、在MDK工程source目录下增加uart.c和uart.h文件。
source分组.JPG

3、uart.c包含对uart的初始化和对rt_hw_console_output、rt_hw_console_getchar函数的实现。uart.c代码如下:

  1. #include <uart.h>
  2. #include "rtthread.h"

  3. void Uart_Init(void)
  4. {
  5.       uint16_t u16RxData;
  6.     en_result_t enRet = Ok;
  7.     uint32_t u32Fcg1Periph = PWC_FCG1_PERIPH_USART1 | PWC_FCG1_PERIPH_USART2 | \
  8.                              PWC_FCG1_PERIPH_USART3 | PWC_FCG1_PERIPH_USART4;
  9.     const stc_usart_uart_init_t stcInitCfg = {
  10.         UsartIntClkCkNoOutput,
  11.         UsartClkDiv_1,
  12.         UsartDataBits8,
  13.         UsartDataLsbFirst,
  14.         UsartOneStopBit,
  15.         UsartParityNone,
  16.         UsartSamleBit8,
  17.         UsartStartBitFallEdge,
  18.         UsartRtsEnable,
  19.     };

  20.     /* Enable peripheral clock */
  21.     PWC_Fcg1PeriphClockCmd(u32Fcg1Periph, Enable);

  22.     /* Initialize USART IO */
  23.     PORT_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_FUNC, Disable);
  24.     PORT_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_FUNC, Disable);

  25.     /* Initialize UART */
  26.    USART_UART_Init(USART_CH, &stcInitCfg);

  27.     /* Set baudrate */
  28.    USART_SetBaudrate(USART_CH, USART_BAUDRATE);

  29.     /*Enable RX && TX function*/
  30.     USART_FuncCmd(USART_CH, UsartRx, Enable);
  31.     USART_FuncCmd(USART_CH, UsartTx, Enable);
  32. }
  33. INIT_BOARD_EXPORT(Uart_Init);

  34. void rt_hw_console_output(const char *str)
  35. {
  36.         rt_size_t i = 0, size = 0;
  37.         char a = '\r';
  38.         size = rt_strlen(str);
  39.         for (i = 0; i < size; i++)
  40.             {
  41.                 if (*(str + i) == '\n')
  42.                 {
  43.                     while (Reset == USART_GetStatus(USART_CH, UsartTxEmpty))  /* Warit Tx data register empty */
  44.           {
  45.           }
  46.                     USART_SendData(USART_CH,(uint16_t)a);
  47.                 }
  48.                 while (Reset == USART_GetStatus(USART_CH, UsartTxEmpty))  /* Warit Tx data register empty */
  49.         {
  50.         }
  51.                 USART_SendData(USART_CH,(*(str + i)));
  52.             }
  53. }

  54. char rt_hw_console_getchar(void)
  55. {
  56.         int ch = -1;
  57.             if (Set == USART_GetStatus(USART_CH, UsartRxNoEmpty))
  58.             {
  59.                     ch = USART_RecData(USART_CH);
  60.             }

  61.         return ch;
  62. }
复制代码

uart.h主要对uart.c内定义的函数进行声明。uart.h代码如下:
  1. #ifndef        __UART_H
  2. #define        __UART_H

  3. #include "hc32_ddl.h"

  4. /*******************************************************************************
  5. * Local pre-processor symbols/macros ('#define')
  6. ******************************************************************************/
  7. /* USART channel definition */
  8. #define USART_CH                        (M4_USART3)

  9. /* USART baudrate definition */
  10. #define USART_BAUDRATE                  (115200ul)

  11. /* USART RX Port/Pin definition */
  12. #define USART_RX_PORT                   (PortE)
  13. #define USART_RX_PIN                    (Pin04)
  14. #define USART_RX_FUNC                   (Func_Usart3_Rx)

  15. /* USART TX Port/Pin definition */
  16. #define USART_TX_PORT                   (PortE)
  17. #define USART_TX_PIN                    (Pin05)
  18. #define USART_TX_FUNC                   (Func_Usart3_Tx)


  19. void Uart_Init(void);
  20. void rt_hw_console_output(const char *str);
  21. char rt_hw_console_getchar(void);

  22. #endif        /*__UART_H*/
复制代码
4、串口初始化函数Uart_Init()加入到board.c文件中。Uart_Init()需要在 board.c中的 rt_hw_board_init() 函数中调用。注意不要忘了board.h需要包含uart.h头文件。
  1. void 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.     /* Call components board initial (use INIT_BOARD_EXPORT()) */
  9.       CLK_SetSysClkSource(ClkSysSrcHRC);
  10.    
  11.       SysTick_Init();
  12.       
  13.      LED_Init();
  14.      LED0_ON();
  15.      Uart_Init();                      串口初始化
  16.       //LED0_OFF();
  17.     // while(1);
  18.    
  19. #ifdef RT_USING_COMPONENTS_INIT
  20.     rt_components_board_init();
  21. #endif

  22. #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
  23.     rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
  24. #e
复制代码

5、修改RT-thread配置文件rtconfig.h,在文件中加入使用Finsh组件的宏。
  1. /* RT-Thread config file */

  2. #ifndef __RTTHREAD_CFG_H__
  3. #define __RTTHREAD_CFG_H__

  4. #if defined(__CC_ARM) || defined(__CLANG_ARM)
  5. #include "RTE_Components.h"

  6. #if defined(RTE_USING_FINSH)
  7. #define RT_USING_FINSH
  8. #endif //RTE_USING_FINSH

  9. #endif //(__CC_ARM) || (__CLANG_ARM)

  10. #define RT_USING_FINSH                                               //使用Finsh组件

  11. // <<< Use Configuration Wizard in Context Menu >>>
  12. // <h>Basic Configuration
  13. // <o>Maximal level of thread priority <8-256>
  14. // <i>Default: 32
  15. #define RT_THREAD_PRIORITY_MAX 8
  16. // <o>OS tick per second
  17. // <i>Default: 1000 (1ms)
  18. #define RT_TICK_PER_SECOND 1000
复制代码
6、main.c不需重新修改上一章中main函数就行,编译下载验证。
复位开发板,看到输出一下信息。
RTT_打印.JPG
输入help,输出命令列表。
help.JPG
输入list_thread,输出线程执行情况。
list.JPG
最后,RT-thread和uart控制台和Finsh组件功能增加完毕。

这一次的HC32H460开发板RT-thread Nano移植分享就结束了。有什么写得不对的地方,欢迎各位评论回复,大家一起交流。

@21小跑堂



使用特权

评论回复
| 2020-9-20 18:41 | 显示全部楼层
谢谢分享【HC32F460移植RT-Thread Nano】

使用特权

评论回复
| 2020-9-21 20:21 | 显示全部楼层
很好的操作

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表