乐趣区

关于程序员:国产MCU移植HC32F460基于Keil-MDK-移植-RTThread-Nano

软件

依据厂家 demo 从新新建工程,工程中蕴含了 gpio、usart。
硬件:
gpio

/ GREEN_LED Port/Pin definition /

define GREEN_LED_PORT (PortE)

define GREEN_LED_PIN (Pin00)

/ RED_LED Port/Pin definition /

define RED_LED_PORT (PortE)

define RED_LED_PIN (Pin01)

usart4

/ USART RX Port/Pin definition /

define USART_RX_PORT (PortC)

define USART_RX_PIN (Pin07)

define USART_RX_FUNC (Func_Usart4_Rx)

/ USART TX Port/Pin definition /

define USART_TX_PORT (PortC)

define USART_TX_PIN (Pin06)

define USART_TX_FUNC (Func_Usart4_Tx)

增加 RT-Thread Nano 到工程

在 Manage Rum-Time Environment 内关上 RTOS 栏,勾选 kernal,点击 OK 后就将 RT-Thread 内核退出到工程中了。

适配 RT-Thread Nano
中断与异样解决

须要删除工程里中断服务例程文件 hc32f460_interrupts.c 中异样处理函数 HardFault_Handler() 和悬挂处理函数 PendSV_Handler(),这两个函数已由 RT-Thread 实现,防止在编译时产生反复定义。


零碎时钟配置

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

void SysTick_Handler(void)
{
rt_os_tick_callback();
}

void rt_hw_board_init(void)函数中调用零碎时钟

SysClkConfig();    // 零碎时钟初始化
SysTick_Init(RT_TICK_PER_SECOND);   //OS Tick 频率配置

void SysClkConfig(void)所在文件 system_hc32f460.c

void SysClkConfig(void)
{

stc_clk_sysclk_cfg_t    stcSysClkCfg;  // 零碎时钟
stc_clk_xtal_cfg_t      stcXtalCfg;    // 晶振配置
stc_clk_mpll_cfg_t      stcMpllCfg;    //PLL
    stc_sram_config_t           stcSramConfig;

MEM_ZERO_STRUCT(stcSysClkCfg);
MEM_ZERO_STRUCT(stcXtalCfg);
MEM_ZERO_STRUCT(stcMpllCfg);

/* Set bus clk div.    分频 */
stcSysClkCfg.enHclkDiv  = ClkSysclkDiv1;  // 100MHz  
stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;  // 50MHz
stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;  // 100MHz
stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;  // 50MHz
stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;  // 25MHz
stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;  // 25MHz
stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;  // 50MHz
CLK_SysClkConfig(&stcSysClkCfg);// 时钟分频

/* Switch system clock source to MPLL. */
/* Use Xtal as MPLL source. */
stcXtalCfg.enMode        = ClkXtalModeOsc;//XTAL 模式抉择位 
stcXtalCfg.enDrv         = ClkXtalLowDrv;/*XTAL 驱动能力抉择   
stcXtalCfg.enFastStartup = Enable;/*XTAL 超高速驱动容许  
CLK_XtalConfig(&stcXtalCfg);//CMU XTAL  配置寄存器
CLK_XtalCmd(Enable);// 开启 CMU XTAL  
while(Set != CLK_GetFlagStatus(ClkFlagXTALRdy))
{;}

/* MPLL config. */
stcMpllCfg.pllmDiv = 1ul;//MPLL 输出时钟分频系数
stcMpllCfg.plln    =50ul;//MPLL 倍频系数
stcMpllCfg.PllpDiv = 4ul;
stcMpllCfg.PllqDiv = 4ul;
stcMpllCfg.PllrDiv = 4ul;
CLK_SetPllSource(ClkPllSrcXTAL);// 时钟源抉择  XTAL
CLK_MpllConfig(&stcMpllCfg);//CMU MPLL 时钟分频配置
    
/* flash read wait cycle setting */
EFM_Unlock();
EFM_SetLatency(5ul);
EFM_Lock();
    
/* sram init include read/write wait cycle setting */
stcSramConfig.u8SramIdx = Sram12Idx | Sram3Idx | SramHsIdx | SramRetIdx;
stcSramConfig.enSramRC = SramCycle2;
stcSramConfig.enSramWC = SramCycle2;
stcSramConfig.enSramEccMode = EccMode3;
stcSramConfig.enSramEccOp = SramNmi;
stcSramConfig.enSramPyOp = SramNmi;
SRAM_Init(&stcSramConfig);        

/* Enable MPLL. */
CLK_MpllCmd(Enable);// 用于开始进行 MPLL。0:MPLL 动作开始 1:MPLL 进行

/* Wait MPLL ready. */
while(Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
{;}
/* Switch system clock source to MPLL. */
CLK_SetSysClkSource(CLKSysSrcMPLL);//CMU  零碎时钟源切换寄存器

}

en_result_t SysTick_Init(uint32_t u32Freq)所在文件 hc32f460_utility.c

__WEAKDEF en_result_t SysTick_Init(uint32_t u32Freq)
{

en_result_t enRet = Error;

if ((0UL != u32Freq) && (u32Freq <= 1000UL))
{
    m_u32TickStep = 1000UL / u32Freq;
    /* Configure the SysTick interrupt */
    if (0UL == SysTick_Config(SystemCoreClock / u32Freq))
    {enRet = Ok;}
}

return enRet;

}

内存堆初始化

零碎内存堆的初始化在 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() 将被调用,如下所示:


编写第一个利用
1. 应用 rt_thread_mdelay() 函数

移植 RT-Thread Nano 之前跑马灯应用厂家库函数

移植 RT-Thread Nano 之后跑马灯应用

2. 建设线程


在 Nano 上增加 UART 控制台

在 RT-Thread Nano 上增加 UART 控制台打印性能后,就能够在代码中应用 RT-Thread 提供的打印函数 rt_kprintf() 进行信息打印,从而获取自定义的打印信息,不便定位代码 bug 或者获取零碎以后运行状态等。实现控制台打印(须要确认 rtconfig.h 中已使能 RT_USING_CONSOLE 宏定义),须要实现根本的硬件初始化,以及对接一个零碎输入字符的函数。
实现串口初始化

rtconfig.h 中 Configuration Wizard->Console Configuration 开启 RT_USING_CONSOLE

usart.c

int rt_Usart_Init(void)
{

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 = {
    UsartIntClkCkOutput,
    UsartClkDiv_1,
    UsartDataBits8,
    UsartDataLsbFirst,
    UsartOneStopBit,
    UsartParityNone,
    UsartSampleBit8,
    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 */
while(Ok != USART_UART_Init(USART_CH, &stcInitCfg));
/* Set baudrate */
while(Ok !=  USART_SetBaudrate(USART_CH, USART_BAUDRATE));
/*Enable RX && RX  function*/
USART_FuncCmd(USART_CH, UsartRx, Enable);
USART_FuncCmd(USART_CH, UsartTx, Enable);
    return 0;

}
INIT_BOARD_EXPORT(rt_Usart_Init);

实现 rt_hw_console_output

usart.c

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)));
    }

}

RT_WEAK 润饰函数 board.c 中 rt_hw_console_output(const char *str),不然会报重定义。

RT_WEAK void rt_hw_console_output(const char *str)
{
//#error “TODO 3: Output the string ‘str’ through the uart.”
}

验证后果


在 Nano 上增加 FinSH 组件(实现命令输出)
增加 FinSH 组件

点击 Manage Run-Environment,勾选 shell,这将主动把 FinSH 组件的源码到工程

微信截图_20210812180550.png

rtconfig.h 中 Configuration Wizard->Console Configuration 开启 RT_USING_CONSOLE


实现 rt_hw_console_getchar(void)函数

usart.c

char rt_hw_console_getchar(void)
{

int ch = -1;

if (Set == USART_GetStatus(USART_CH, UsartRxNoEmpty))
{ch = USART_RecData(USART_CH);
}
return ch;

}

验证后果


HC32F460 移植 RT-Thread Nano 完结

近来芯片缺货大幕拉开,掀起新一轮国产代替浪潮。RT-Thread 发动一场国产 MCU 移植奉献流动,邀请开发者们加入!
流动详情:国潮崛起!RT-Thread 国产 MCU 移植奉献流动开启!

退出移动版