【国民技术低功耗系列N32L43x测评】2、RT-Thread移植+LED演示
本帖最后由 emmnn 于 2022-7-7 11:16 编辑# 前言
在把官方提供的DEMO工程跑起来后,就可以考虑OS的移植了。恰好在官方提供的资料文档中有看到RT-Thread的应用笔记,轻车熟路,就决定移植RT-Thread。
# 一、准备工作
关于RT-Thread,官方提供了三种版本类型。分别为标准版本,Nano版本以及Smart版本。
这里我选择的是Nano版本,版本号为3.1.5,可到官网下载,下载地址如下:
(https://www.rt-thread.org/document/site/?f#/ "RT-Thread获取地址")
# 二、移植RT-Thread
我们先将整个RT-Thread源码copy到我们的裸机工程目录下。
将rt-thread\libcpu\arm\cortex-m4下context_rvds.S和cpuport.c添加到rtt/port中
将rt-thread\src 所有.c文件添加到rtt/source中
添加finsh组件,将rt-thread\components\finsh 所有.c文件添加到finsh下
最后再将bsp文件夹下board.c和rtconfig.h添加到USER中
# 三、时钟配置
添加完RT-Thread的源码后,我们还需要配置下系统时钟,用于提供RTOS任务调度所需要的时钟信号。关于时钟配置这块,跟其他厂家的MCU基本大同小异。
具体的配置方法,在官方提供的例程中也有代码演示,配合用户手册理解即可。例程路径如下:
N32L43xxx_V1.1.0\6-软件开发套件(Software Development Kit)\Nationstech.N32L43x_Library.1.1.0\projects\n32l43x_EVAL\examples\RCC\RCC_ClockConfig
这里我使用的是外部晶振源(HSE)提供的时钟信号,经过MCU内部PLL倍频后,再分频产生的时钟信号SysTick提供给RTOS用于任务调度使用。
在board.c中配置时钟如下:
```c
/*
* Copyright (c) 2006-2019, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-07-24 Tanek the first version
* 2018-11-12 Ernest Chenmodify copyright
*/
#include <stdint.h>
#include <rtthread.h>
#include "header.h"
static void sysTick_Init(void);
static void SysClkConfig(void);
/**
* @briefSelects PLL clock as System clock source and configure HCLK, PCLK2
* and PCLK1 prescalers.
*/
static void SetSysClockToPLL(uint32_t freq, uint8_t src)
{
uint32_t pllsrcclk;
uint32_t pllsrc;
uint32_t pllmul;
uint32_t plldiv = RCC_PLLDIVCLK_DISABLE;
uint32_t latency;
uint32_t pclk1div, pclk2div;
uint32_t msi_ready_flag = RESET;
ErrorStatus HSIStartUpStatus;
ErrorStatus HSEStartUpStatus;
if (HSE_VALUE != 8000000)
{
/* HSE_VALUE == 8000000 is needed in this project! */
while (1);
}
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration
* -----------------------------*/
if ((src == SYSCLK_PLLSRC_HSI) || (src == SYSCLK_PLLSRC_HSIDIV2)
|| (src == SYSCLK_PLLSRC_HSI_PLLDIV2) || (src == SYSCLK_PLLSRC_HSIDIV2_PLLDIV2))
{
/* Enable HSI */
RCC_ConfigHsi(RCC_HSI_ENABLE);
/* Wait till HSI is ready */
HSIStartUpStatus = RCC_WaitHsiStable();
if (HSIStartUpStatus != SUCCESS)
{
/* If HSI fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this
error */
/* Go to infinite loop */
while (1);
}
if ((src == SYSCLK_PLLSRC_HSIDIV2) || (src == SYSCLK_PLLSRC_HSIDIV2_PLLDIV2))
{
pllsrc = RCC_PLL_HSI_PRE_DIV2;
pllsrcclk = HSI_VALUE/2;
if(src == SYSCLK_PLLSRC_HSIDIV2_PLLDIV2)
{
plldiv = RCC_PLLDIVCLK_ENABLE;
pllsrcclk = HSI_VALUE/4;
}
} else if ((src == SYSCLK_PLLSRC_HSI) || (src == SYSCLK_PLLSRC_HSI_PLLDIV2))
{
pllsrc = RCC_PLL_HSI_PRE_DIV1;
pllsrcclk = HSI_VALUE;
if(src == SYSCLK_PLLSRC_HSI_PLLDIV2)
{
plldiv = RCC_PLLDIVCLK_ENABLE;
pllsrcclk = HSI_VALUE/2;
}
}
} else if ((src == SYSCLK_PLLSRC_HSE) || (src == SYSCLK_PLLSRC_HSEDIV2)
|| (src == SYSCLK_PLLSRC_HSE_PLLDIV2) || (src == SYSCLK_PLLSRC_HSEDIV2_PLLDIV2))
{
/* Enable HSE */
RCC_ConfigHse(RCC_HSE_ENABLE);
/* Wait till HSE is ready */
HSEStartUpStatus = RCC_WaitHseStable();
if (HSEStartUpStatus != SUCCESS)
{
/* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this
error */
/* Go to infinite loop */
while (1);
}
if ((src == SYSCLK_PLLSRC_HSEDIV2) || (src == SYSCLK_PLLSRC_HSEDIV2_PLLDIV2))
{
pllsrc = RCC_PLL_SRC_HSE_DIV2;
pllsrcclk = HSE_VALUE/2;
if(src == SYSCLK_PLLSRC_HSEDIV2_PLLDIV2)
{
plldiv = RCC_PLLDIVCLK_ENABLE;
pllsrcclk = HSE_VALUE/4;
}
} else if ((src == SYSCLK_PLLSRC_HSE) || (src == SYSCLK_PLLSRC_HSE_PLLDIV2))
{
pllsrc = RCC_PLL_SRC_HSE_DIV1;
pllsrcclk = HSE_VALUE;
if(src == SYSCLK_PLLSRC_HSE_PLLDIV2)
{
plldiv = RCC_PLLDIVCLK_ENABLE;
pllsrcclk = HSE_VALUE/2;
}
}
}
latency = (freq/32000000);
if(freq > 54000000)
{
pclk1div = RCC_HCLK_DIV4;
pclk2div = RCC_HCLK_DIV2;
}
else
{
if(freq > 27000000)
{
pclk1div = RCC_HCLK_DIV2;
pclk2div = RCC_HCLK_DIV1;
}
else
{
pclk1div = RCC_HCLK_DIV1;
pclk2div = RCC_HCLK_DIV1;
}
}
if(((freq % pllsrcclk) == 0) && ((freq / pllsrcclk) >= 2) && ((freq / pllsrcclk) <= 32))
{
pllmul = (freq / pllsrcclk);
if(pllmul <= 16)
{
pllmul = ((pllmul - 2) << 18);
}
else
{
pllmul = (((pllmul - 17) << 18) | (1 << 27));
}
}
else
{
/* Cannot make a PLL multiply factor to freq. */
PRO_LOG(LOG_WARN, "Cannot make a PLL multiply factor to freq..\n");
while(1);
}
/* Cheak if MSI is Ready */
if(RESET == RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_MSIRD))
{
/* Enable MSI and Config Clock */
RCC_ConfigMsi(RCC_MSI_ENABLE, RCC_MSI_RANGE_4M);
/* Waits for MSI start-up */
while(SUCCESS != RCC_WaitMsiStable());
msi_ready_flag = SET;
}
/* Select MSI as system clock source */
RCC_ConfigSysclk(RCC_SYSCLK_SRC_MSI);
FLASH_SetLatency(latency);
/* HCLK = SYSCLK */
RCC_ConfigHclk(RCC_SYSCLK_DIV1);
/* PCLK2 = HCLK */
RCC_ConfigPclk2(pclk2div);
/* PCLK1 = HCLK */
RCC_ConfigPclk1(pclk1div);
/* Disable PLL */
RCC_EnablePll(DISABLE);
RCC_ConfigPll(pllsrc, pllmul, plldiv);
/* Enable PLL */
RCC_EnablePll(ENABLE);
/* Wait till PLL is ready */
while (RCC_GetFlagStatus(RCC_CTRL_FLAG_PLLRDF) == RESET);
/* Select PLL as system clock source */
RCC_ConfigSysclk(RCC_SYSCLK_SRC_PLLCLK);
/* Wait till PLL is used as system clock source */
while (RCC_GetSysclkSrc() != 0x0C);
if(msi_ready_flag == SET)
{
/* MSI oscillator OFF */
RCC_ConfigMsi(RCC_MSI_DISABLE, RCC_MSI_RANGE_4M);
}
}
static void SysClkConfig(void)
{
SetSysClockToPLL(108000000, SYSCLK_PLLSRC_HSEDIV2);
}
#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
#define RT_HEAP_SIZE 4096
static uint32_t rt_heap; // heap default size: 4K(1024 * 4)
RT_WEAK void *rt_heap_begin_get(void)
{
return rt_heap;
}
RT_WEAK void *rt_heap_end_get(void)
{
return rt_heap + RT_HEAP_SIZE;
}
#endif
/**
* This function will initial your board.
*/
void rt_hw_board_init()
{
/* Call components board initial (use INIT_BOARD_EXPORT()) */
SysClkConfig();
sysTick_Init();
/* Call components board initial (use INIT_BOARD_EXPORT()) */
#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());
#endif
/* shell usart init */
Usart_Init();
}
void SysTick_Handler(void)
{
/* enter interrupt */
rt_interrupt_enter();
rt_tick_increase();
/* leave interrupt */
rt_interrupt_leave();
}
static void sysTick_Init(void)
{
RCC_ClocksType RCC_ClockFreq;
RCC_GetClocksFreqValue(&RCC_ClockFreq);
SysTick_Config(RCC_ClockFreq.SysclkFreq/RT_TICK_PER_SECOND);
}
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')
{
USART_SendData(USARTx, a);
while (RESET == USART_GetFlagStatus(USARTx, USART_FLAG_TXC))
{
;
}
}
USART_SendData(USARTx, *(str + i));
while (RESET == USART_GetFlagStatus(USARTx, USART_FLAG_TXC))
{
;
}
}
}
char rt_hw_console_getchar(void)
{
int ch = -1;
if (SET == USART_GetFlagStatus(USARTx, USART_FLAG_RXDNE))
{
ch = USART_ReceiveData(USARTx);
}
else
{
if(SET == USART_GetFlagStatus(USARTx, USART_FLAG_OREF))
{
USART_ClrFlag(USARTx, USART_FLAG_OREF);
}
rt_thread_mdelay(10);
}
return ch;
}
```
此外,我们需要把n32l43x_it.c文件中的HardFault_Handler,SysTick_Handler注释或删除掉,在移植RT-Thread后这两个中断会被RT-Thread接管。
#四、任务演示
关于RT-Thread的任务运行,这里用板载的LED做演示。相关代码如下:
```c
static struct rt_thread led_thread;
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t rt_led_thread_stack;
static void led_thread_entry(void * para);
static rt_uint8_t led_thread_priority = 6;
static void MainInit(void)
{
/* LED Init */
LedInit();
}
/**
* @briefMain program
*/
int main(void)
{
PRO_LOG(LOG_DEBUG, "entry %s. \r\n", __func__);
MainInit();
/* main thread */
rt_thread_init(&led_thread,
"led_thread",
led_thread_entry,
RT_NULL,
&rt_led_thread_stack,
sizeof(rt_led_thread_stack),
led_thread_priority,
1000);
rt_thread_startup(&led_thread);
}
static void led_thread_entry(void * para)
{
PRO_LOG(LOG_DEBUG, "Entry %s. \r\n", __func__);
while(1)
{
LedToggle(0);
LedToggle(1);
LedToggle(2);
rt_thread_delay(1000);
}
}
```
关于LED驱动的部分,就是很简单的GPIO操作,官方例程也有代码可供参考,这里就不再详细说明。
编译烧录,我们可以看到板载的三个LED以1s的频率闪烁,串口助手查看,finsh组件也能正常使用。
#附件
工程源码如下:
attach://620135.7z 这个块子rt-thread studio没有支持吗? lugl4313820 发表于 2022-7-7 13:53
这个块子rt-thread studio没有支持吗?
<p>这个没留意</p>
<p>很多人都喜欢用rt-thread,这个人系统大概有多大?</p>
秦天qintian0303 发表于 2022-7-10 08:59
很多人都喜欢用rt-thread,这个人系统大概有多大?
<p>有三种版本的,跑大部分32位mcu是没什么问题的,具体的可以到他们官网了解下</p>
页:
[1]