本帖最后由 Liyj336 于 2020-11-28 09:28 编辑
这一次测评我将一步步分享RT-Thread Nano移植到HC32F460的过程。主要分三步讲解工程建立、RT-Thread移植、添加UART控制台和Finsh。
一、工程建立
1、首先我们需要建立程序工程文件,下面的工程我是在HC32F460官方例程基础上建立的。在一个总的工程文件夹下面,建立以下工程文件夹。红色划线部分文件夹可以先忽略。(可以按照自己习惯建立工程)
BSP:打算存放MCU外部外设部分程序。
documents:从官方例程中复制过来,存放HC32F460官方库使用说明。
driver:从官方例程复制过来,存放HC32F460的驱动库。
mcu:从官方例程复制过来,MDK工程需要里面的文件。保留下面两个文件夹就行
MDK:存放MDK工程文件。我从例程icg_hrc_osc_hw_startup复制过来的,该例程跟Systick有关。
source:从官方移植过来的,存放main.c和其他一些程序文件。 2、打开MDK目录下的icg_hrc_osc_hw_startup工程。从新加入project下的文件。忽略打叉或者划线的文件,从刚建立的工程中加入以下文件。
3、新建led.c和led.h文件放入到BSP下的src和inc文件夹内,并把led.c文件加入到MDK工程中。
led.c代码如下,只是一个简单的点灯代码,用来验证程序。
- #include <led.h>
- void LED_Init(void)
- {
- /**************************************************************************/
-
- stc_port_init_t stcPortInit;
- /* configure structure initialization */
- MEM_ZERO_STRUCT(stcPortInit);
- /* LED0 Port/Pin initialization */
- LED0_OFF();
- stcPortInit.enPinMode = Pin_Mode_Out;
- PORT_Init(LED0_PORT, LED0_PIN, &stcPortInit);
- }
led.h
- #ifndef __LED_H
- #define __LED_H
- #include "hc32_ddl.h"
- /*******************************************************************************
- * Local type definitions ('typedef')
- ******************************************************************************/
- /*******************************************************************************
- * Local pre-processor symbols/macros ('#define')
- ******************************************************************************/
- /* LED0 Port/Pin definition */
- #define LED0_PORT (PortE)
- #define LED0_PIN (Pin06)
- #define LED0_ON() (PORT_SetBits(LED0_PORT, LED0_PIN))
- #define LED0_OFF() (PORT_ResetBits(LED0_PORT, LED0_PIN))
- #define LED0_TOGGLE() (PORT_Toggle(LED0_PORT, LED0_PIN))
- void LED_Init(void);
- #endif /*__LED_H*/
4、接下来修改HDSC_HC32F46x.SFR文件路径,如下图红框内,其实我也不知道这个文件有什么作用。
然后从新加入头文件路径。
二、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文件夹目录如下。
2、在工程文件夹下,加入RT-thread文件夹,并在下RT-thread文件夹下加入Include、Port、Source文件夹,存放RT-thread所需文件。
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文件夹。
5、将路径RT-Thread/3.1.3/libcpu/arm/cortex-m3文件夹下面的 rtconfig.h和board.c文件复制到到工程目录下的port文件夹。
6、打开hc32f46x_interrupts.c把SysTick_Handler、PendSV_Handler、HardFault_Handler这三个中断函数注释掉,要不然编译会出现重定义错误。
7、修改RT-thread配置文件rtconfig.h头文件进行RTT的配置。里面是通过修改宏来实现的,可以根据实际情况进行修改。这里我不进行该文件修改,直接使用。rtconfig.h文件一些配置宏如下所示。
8、在 MDK source 目录下新建一个 board.h 头文件,用来包含HC32F460固件驱动库和BSP 相关的头文件。
board.h代码如下- #ifndef __BOARD_H
- #define __BOARD_H
- #include "hc32_ddl.h"
- #include "led.h"
- #include "uart.h"
- void rt_hw_board_init(void);
- void SysTick_Handler(void);
- #endif /*__BOARD_H*/
9、修改board.c文件。board.c里面主要完成RT-thread的初始化,并对外设硬件完成初始化。
10、到这里RT_thread移植已经完成了,我们还是写个点灯程序测试一下。修改main.c函数
- #include "hc32_ddl.h"
- #include "led.h"
- #include "board.h"
- #include "rtthread.h"
- /*定义线程控制块*/
- static struct rt_thread led1_thread;
- /*定义线程空栈时要求RT_ALIGN_SIZE个字节对齐*/
- ALIGN(RT_ALIGN_SIZE)
- /*定义线程栈*/
- static rt_uint8_t rt_led1_thread_stack[1024];
- /*函数声明*/
- static void led1_thread_entry(void * parameter);
- /*******************************************************************************
- ** \brief main function for ICG HRC function
- **
- ** \param [in] None
- **
- ** \retval int32_t Return value, if needed
- **
- ******************************************************************************/
- int32_t main(void)
- {
- rt_thread_init(&led1_thread,
- "led1",
- led1_thread_entry,
- RT_NULL,
- &rt_led1_thread_stack,
- sizeof(rt_led1_thread_stack),
- 3,
- 20);
- rt_thread_startup(&led1_thread);
- }
- static void led1_thread_entry(void * parameter)
- {
- while(1)
- {
- LED0_ON();
- rt_thread_delay(500);
- LED0_OFF();
- rt_thread_delay(500);
- }
- }
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文件
2、在MDK工程source目录下增加uart.c和uart.h文件。
3、uart.c包含对uart的初始化和对rt_hw_console_output、rt_hw_console_getchar函数的实现。uart.c代码如下:
- #include <uart.h>
- #include "rtthread.h"
- void Uart_Init(void)
- {
- uint16_t u16RxData;
- en_result_t enRet = Ok;
- uint32_t u32Fcg1Periph = PWC_FCG1_PERIPH_USART1 | PWC_FCG1_PERIPH_USART2 | \
- PWC_FCG1_PERIPH_USART3 | PWC_FCG1_PERIPH_USART4;
- const stc_usart_uart_init_t stcInitCfg = {
- UsartIntClkCkNoOutput,
- UsartClkDiv_1,
- UsartDataBits8,
- UsartDataLsbFirst,
- UsartOneStopBit,
- UsartParityNone,
- UsartSamleBit8,
- UsartStartBitFallEdge,
- UsartRtsEnable,
- };
- /* Enable peripheral clock */
- PWC_Fcg1PeriphClockCmd(u32Fcg1Periph, Enable);
- /* Initialize USART IO */
- PORT_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_FUNC, Disable);
- PORT_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_FUNC, Disable);
- /* Initialize UART */
- USART_UART_Init(USART_CH, &stcInitCfg);
- /* Set baudrate */
- USART_SetBaudrate(USART_CH, USART_BAUDRATE);
- /*Enable RX && TX function*/
- USART_FuncCmd(USART_CH, UsartRx, Enable);
- USART_FuncCmd(USART_CH, UsartTx, Enable);
- }
- INIT_BOARD_EXPORT(Uart_Init);
- void rt_hw_console_output(const char *str)
- {
- rt_size_t i = 0, size = 0;
- char a = '\r';
- size = rt_strlen(str);
- for (i = 0; i < size; i++)
- {
- if (*(str + i) == '\n')
- {
- while (Reset == USART_GetStatus(USART_CH, UsartTxEmpty)) /* Warit Tx data register empty */
- {
- }
- USART_SendData(USART_CH,(uint16_t)a);
- }
- while (Reset == USART_GetStatus(USART_CH, UsartTxEmpty)) /* Warit Tx data register empty */
- {
- }
- USART_SendData(USART_CH,(*(str + i)));
- }
- }
- char rt_hw_console_getchar(void)
- {
- int ch = -1;
- if (Set == USART_GetStatus(USART_CH, UsartRxNoEmpty))
- {
- ch = USART_RecData(USART_CH);
- }
- return ch;
- }
uart.h主要对uart.c内定义的函数进行声明。uart.h代码如下:
- #ifndef __UART_H
- #define __UART_H
- #include "hc32_ddl.h"
- /*******************************************************************************
- * Local pre-processor symbols/macros ('#define')
- ******************************************************************************/
- /* USART channel definition */
- #define USART_CH (M4_USART3)
- /* USART baudrate definition */
- #define USART_BAUDRATE (115200ul)
- /* USART RX Port/Pin definition */
- #define USART_RX_PORT (PortE)
- #define USART_RX_PIN (Pin04)
- #define USART_RX_FUNC (Func_Usart3_Rx)
- /* USART TX Port/Pin definition */
- #define USART_TX_PORT (PortE)
- #define USART_TX_PIN (Pin05)
- #define USART_TX_FUNC (Func_Usart3_Tx)
- void Uart_Init(void);
- void rt_hw_console_output(const char *str);
- char rt_hw_console_getchar(void);
- #endif /*__UART_H*/
4、串口初始化函数Uart_Init()加入到board.c文件中。Uart_Init()需要在 board.c中的 rt_hw_board_init() 函数中调用。注意不要忘了board.h需要包含uart.h头文件。
- void rt_hw_board_init()
- {
- /* System Clock Update */
- //SystemCoreClockUpdate();
-
- /* System Tick Configuration */
- // _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
- /* Call components board initial (use INIT_BOARD_EXPORT()) */
- CLK_SetSysClkSource(ClkSysSrcHRC);
-
- SysTick_Init();
-
- LED_Init();
- LED0_ON();
- Uart_Init(); 串口初始化
- //LED0_OFF();
- // while(1);
-
- #ifdef RT_USING_COMPONENTS_INIT
- rt_components_board_init();
- #endif
- #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
- rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
- #e
5、修改RT-thread配置文件rtconfig.h,在文件中加入使用Finsh组件的宏。- /* RT-Thread config file */
- #ifndef __RTTHREAD_CFG_H__
- #define __RTTHREAD_CFG_H__
- #if defined(__CC_ARM) || defined(__CLANG_ARM)
- #include "RTE_Components.h"
- #if defined(RTE_USING_FINSH)
- #define RT_USING_FINSH
- #endif //RTE_USING_FINSH
- #endif //(__CC_ARM) || (__CLANG_ARM)
- #define RT_USING_FINSH //使用Finsh组件
- // <<< Use Configuration Wizard in Context Menu >>>
- // <h>Basic Configuration
- // <o>Maximal level of thread priority <8-256>
- // <i>Default: 32
- #define RT_THREAD_PRIORITY_MAX 8
- // <o>OS tick per second
- // <i>Default: 1000 (1ms)
- #define RT_TICK_PER_SECOND 1000
6、main.c不需重新修改上一章中main函数就行,编译下载验证。
复位开发板,看到输出一下信息。
输入help,输出命令列表。
输入list_thread,输出线程执行情况。
最后,RT-thread和uart控制台和Finsh组件功能增加完毕。
这一次的HC32H460开发板RT-thread Nano移植分享就结束了。有什么写得不对的地方,欢迎各位评论回复,大家一起交流。
@21小跑堂
代码地址:https://gitee.com/Liyj_336/hc32_rtt.git
|