【12月原创】基于 stm32 LL 库移植 RT-Thread Nano

RT-Thread Nano 移植主要包含Kernel部分和添加控制台与Finsh 这两部分,主要参考文档中心的内容。

准备工作

STM32Cube_FW_F1_V1.6.0

开发是直接在STM32Cube_FW_F1_V1.6.0\Projects\STM32F103RB-Nucleo\Examples_LL\GPIO\GPIO_InfiniteLedToggling 这个工程上进行移植的。

RealThread.RT-Thread.3.1.3.pack

MDK移植有介绍。

Xshell-7.0.0054p.exe

Xshell 是用其中的串口工具。我还使用野火多功能调试助手,但是发现有些问题。

Kernel 移植

此部分比较简单,按照官网的文档操作即可。

  1. 在stm32f1xx_it.c 中注释掉 void PendSV_Handler(void) 和 void SysTick_Handler(void)
  2. 将原来main 中的SystemClock_Config() 移动到 void rt_hw_board_init()
void rt_hw_board_init()
{
      /* Configure the system clock to 72 MHz */
    SystemClock_Config();
    /* System Clock Update */
    SystemCoreClockUpdate();
    
    /* System Tick Configuration */
    _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);

    /* 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
}
  1. 修改原来的main
int main(void)
{
  /* Configure the system clock to 72 MHz */
//  SystemClock_Config();
  
  /* -2- Configure IO in output push-pull mode to drive external LED */
    Configure_GPIO();

    /* Toggle IO in an infinite loop */
    while (1)
    {

        LL_GPIO_TogglePin(LED2_GPIO_PORT, LED2_PIN);
        rt_thread_mdelay(500);
    
    /* Insert delay 250 ms */
//    LL_mDelay(250);
    }
}

这样基本就是可以正常闪灯了。

添加控制台与 FinSH

此部分就是移植UART的功能,主要是参考了cube 里面的usart的code。。遇到了bug,调了好久。

遇到问题及解决方法如下:

  1. UART 单步运行可输出字符串,全速运行无输出。
    此问题主要是没有等TXE 标志位置位导致。在void rt_hw_console_output(const char *str)中添加while 等TXE为Active 即可
  2. 用xshell 出现只换行没有回车的问题 ,没有输出’\r’。此问题还是因为要等TXE为Active,不等’\r’就没有输出。用野火多功能调试助手无此问题,看来野火只要’\n’即可。
    ‘\r’ 回车,回到当前行的行首,而不会换到下一行;回车符的ASCII码值为13,十六进制表示为0x0D
    ‘\n’ 换行,换到当前位置的下一行,而不会回到行首;换行符的ASCII码值为10,十六进制表示为0x0A

rt_kprintf("\n \ | /\n"); 逻辑分析仪抓到如下图:
rt_kprintf("\n \ | /\n");

不输出’\r’,xshell 会是下面的这种情况
在这里插入图片描述
野火串口助手没有此问题:
在这里插入图片描述
3. finsh 输入help,野火串口助手没有反应,xshell则没有问题。
在这里插入图片描述

问题应该是xshell 是键盘有输入,实时在传字符,而野火串口助手是一次性发送的

在这里插入图片描述

实际code 如下

需要在board.c 添加以下内容:

static uint16_t uart_init(void)
{
  /* (1) Enable GPIO clock and configures the USART pins *********************/

  /* Enable the peripheral clock of GPIO Port */
  USARTx_GPIO_CLK_ENABLE();

  /* Enable USART peripheral clock *******************************************/
  USARTx_CLK_ENABLE();

  /* Configure Tx Pin as : Alternate function, High Speed, Push pull, Pull up */
  LL_GPIO_SetPinMode(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_MODE_ALTERNATE);
  LL_GPIO_SetPinSpeed(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
  LL_GPIO_SetPinOutputType(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
  LL_GPIO_SetPinPull(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_PULL_UP);

  /* Configure Rx Pin as : Input Floating function, High Speed, Pull up */
  LL_GPIO_SetPinMode(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_MODE_FLOATING);
  LL_GPIO_SetPinSpeed(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
  LL_GPIO_SetPinPull(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_PULL_UP);

  /* (2) NVIC Configuration for USART interrupts */
  /*  - Set priority for USARTx_IRQn */
  /*  - Enable USARTx_IRQn */
  //NVIC_SetPriority(USARTx_IRQn, 0);  
  //NVIC_EnableIRQ(USARTx_IRQn);

  /* (3) Configure USART functional parameters ********************************/
  
  /* Disable USART prior modifying configuration registers */
  /* Note: Commented as corresponding to Reset value */
  // LL_USART_Disable(USARTx_INSTANCE);

  /* TX/RX direction */
  LL_USART_SetTransferDirection(USARTx_INSTANCE, LL_USART_DIRECTION_TX_RX);

  /* 8 data bit, 1 start bit, 1 stop bit, no parity */
  LL_USART_ConfigCharacter(USARTx_INSTANCE, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);

  /* No Hardware Flow control */
  /* Reset value is LL_USART_HWCONTROL_NONE */
  // LL_USART_SetHWFlowCtrl(USARTx_INSTANCE, LL_USART_HWCONTROL_NONE);

  /* Set Baudrate to 115200 using APB frequency set to 72000000/APB_Div Hz */
  /* Frequency available for USART peripheral can also be calculated through LL RCC macro */
  /* Ex :
      Periphclk = LL_RCC_GetUSARTClockFreq(Instance); or LL_RCC_GetUARTClockFreq(Instance); depending on USART/UART instance
  
      In this example, Peripheral Clock is expected to be equal to 72000000/APB_Div Hz => equal to SystemCoreClock/APB_Div
  */
  LL_USART_SetBaudRate(USARTx_INSTANCE, SystemCoreClock/APB_Div, 115200); 

  /* (4) Enable USART *********************************************************/
  LL_USART_Enable(USARTx_INSTANCE);

  /* Enable RXNE and Error interrupts */
  //LL_USART_EnableIT_RXNE(USARTx_INSTANCE);
  
  return 0;
}
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++)
    {
        while(!LL_USART_IsActiveFlag_TXE(USARTx_INSTANCE))
        {
        }
        
 
        
        if (*(str + i) == '\n')
        {
            LL_USART_TransmitData8(USARTx_INSTANCE, a);
            while(!LL_USART_IsActiveFlag_TXE(USARTx_INSTANCE))
            {
            }
        }
        LL_USART_TransmitData8(USARTx_INSTANCE, *(str + i));
    }
//    LL_USART_ClearFlag_TC(USARTx_INSTANCE); 
//    
//    while(!LL_USART_IsActiveFlag_TC(USARTx_INSTANCE))
//    {
//        __NOP();
//    }
//    LL_USART_ClearFlag_TC(USARTx_INSTANCE); 
    
    
}

char rt_hw_console_getchar(void)
{
    int ch = -1;
    
    if(LL_USART_IsActiveFlag_RXNE(USARTx_INSTANCE))
    {
        ch = LL_USART_ReceiveData8(USARTx_INSTANCE);
    }
    else
    {
        rt_thread_mdelay(10);
    }
    return ch;
}

新建 board.h

#ifndef __BOARD_H__
#define __BOARD_H__



/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_ll_bus.h"
#include "stm32f1xx_ll_rcc.h"
#include "stm32f1xx_ll_system.h"
#include "stm32f1xx_ll_utils.h"
#include "stm32f1xx_ll_gpio.h"
#include "stm32f1xx_ll_exti.h"
#include "stm32f1xx_ll_usart.h"
#include "stm32f1xx_ll_pwr.h"

/* USART1 instance is used. (TX on PA.09, RX on PA.10)
   (requires wiring USART1 TX/Rx Pins to USB to UART adapter) */
#define USARTx_INSTANCE               USART1
#define USARTx_CLK_ENABLE()           LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1)
#define USARTx_IRQn                   USART1_IRQn
#define USARTx_IRQHandler             USART1_IRQHandler

#define USARTx_GPIO_CLK_ENABLE()      LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA)   /* Enable the peripheral clock of GPIOA */
#define USARTx_TX_PIN                 LL_GPIO_PIN_9
#define USARTx_TX_GPIO_PORT           GPIOA
#define USARTx_RX_PIN                 LL_GPIO_PIN_10
#define USARTx_RX_GPIO_PORT           GPIOA
#define APB_Div 1





#endif

STM32F103是意法半导体(STMicroelectronics)生产的一款32位嵌入式微控制器,具有高性能和低功耗的特点。RT-Thread Nano是RT-Thread实时操作系统的一个轻量级版本,适用于资源受限的嵌入式系统。 在将RT-Thread Nano移植STM32F103上之前,需要先了解RT-Thread Nano的架构和STM32F103的硬件特性。 首先,需要确保RT-Thread Nano的源代码和STM32F103的开发环境已经准备好。接着,根据STM32F103的芯片手册和引脚映射表,需要对RT-Thread Nano的硬件抽象层进行适配,确保操作系统可以正确地访问外设和中断。 其次,需要根据STM32F103的内存和存储器大小来合理配置RT-Thread Nano的内存管理器和文件系统。可以根据实际需求对系统进行裁剪,移除不必要的模块和功能,以减小系统的内存占用和代码体积。 然后,需要配置STM32F103的系统时钟和中断向量表,并在启动代码中初始化硬件资源和系统任务。可以参考RT-Thread Nano的官方文档和示例代码,根据具体的硬件平台和应用需求进行相应的设置和调试。 最后,进行系统的编译、烧录和调试。可以使用STM32F103的开发工具链和调试器,对编译后的固件进行烧录和调试,确保系统能够正确地启动和运行。 总结来说,将RT-Thread Nano移植STM32F103上需要进行硬件适配、内存管理和系统配置等工作,最终通过编译、烧录和调试来验证移植的正确性。这样可以使得STM32F103可以运行使用RT-Thread Nano操作系统的应用程序,实现更灵活和可靠的嵌入式系统设计。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值