991|2

270

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

【ST NUCLEO-U5A5ZJ-Q开发板测评】04 移植RT-thread Nano [复制链接]

本帖最后由 怀揣少年梦 于 2024-2-2 13:45 编辑

这一篇在STM32U5A5移植RT-Thread Nano;毕竟RT-Thread是国产操作系统,现在已经发展的比较完善了。

一、RT-Thread Nano是什么?

RT-Thread Nano 是一个极简版的硬实时内核,它是由 C 语言开发,采用面向对象的编程思维,具有良好的代码风格,是一款可裁剪的、抢占式实时多任务的 RTOS。其内存资源占用极小,功能包括任务处理、软件定时器、信号量、邮箱和实时调度等相对完整的实时操作系统特性。适用于家电、消费电子、医疗设备、工控等领域大量使用的 32 位 ARM 入门级 MCU 的场合。

它的软件框图如下:

 

二、准备工作

1、电脑安装了stm32CubeMX和STM32CubeIDE;

2、STM32U5A5ZJQ开发板;

三、移植过程

1、建立工程

1)初始化时钟

 

2)配置三个LED灯

 

3)打开cache和PWR,和之前操作一样;

4)添加RT-Thread Nano组件

 

5)安装RT-thread

 

6)启用和使能RT-Thread

  • 选中组件

 

  • 启用RT-Thread

 

  • 配置RT-Thread

 

7)RT-Thread参数配置

 

8)配置Systick时钟源为TIM1并产生工程

 

2、修改配置文件

1)修改board.c文件

  • 修改rt_hw_board_init,增加外设初始化函数,并添加相应的头文件
#include "icache.h"
#include "memorymap.h"
#include "usart.h"
#include "gpio.h"

/*......*/
/*省略code*/

void rt_hw_board_init(void)
{
    extern void SystemClock_Config(void);
    extern void SystemPower_Config(void);
    
    HAL_Init();
    SystemClock_Config();

    /* add code start*/
    SystemPower_Config();
    MX_GPIO_Init();
    MX_ICACHE_Init();
    MX_USART1_UART_Init();
    /* add code end */
    
    SystemCoreClockUpdate();
    /* 
     * 1: OS Tick Configuration
     * Enable the hardware timer and call the rt_os_tick_callback function
     * periodically with the frequency RT_TICK_PER_SECOND. 
     */
    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/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
}

 

  • 注释uart_init里面的代码,并替换Uart_Handle 为huart1
//UART_HandleTypeDef huart1;
static int uart_init(void)
{
    /* TODO: Please modify the UART port number according to your needs */
//    huart1.Instance = USART2;
//    huart1.Init.BaudRate = 115200;
//    huart1.Init.WordLength = UART_WORDLENGTH_8B;
//    huart1.Init.StopBits = UART_STOPBITS_1;
//    huart1.Init.Parity = UART_PARITY_NONE;
//    huart1.Init.Mode = UART_MODE_TX_RX;
//    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
//    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
//
//    if (HAL_UART_Init(&huart1) != HAL_OK)
//    {
//        while (1);
//    }
    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';

    __HAL_UNLOCK(&huart1);

    size = rt_strlen(str);

    for (i = 0; i < size; i++)
    {
        if (*(str + i) == '\n')
        {
            HAL_UART_Transmit(&huart1, (uint8_t *)&a, 1, 1);
        }
        HAL_UART_Transmit(&huart1, (uint8_t *)(str + i), 1, 1);
    }
}
#endif

#ifdef RT_USING_FINSH
char rt_hw_console_getchar(void)
{
    /* Note: the initial value of ch must < 0 */
    int ch = -1;

    if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)
    {
        ch = huart1.Instance->RDR & 0xff;   //这里也需要修改,默认生成的huart1.Instance->DR
    }
    else
    {
        rt_thread_mdelay(10);
    }
    return ch;
}
#endif

 

2)配置rtconfig.h

取消finsh_config的注释,启用控制台

// <h>Enable FinSH Configuration
// <c1>include shell config
//  <i> Select this choice if you using FinSH
#include "finsh_config.h"
// </c>
// </h>

3)修改启动文件startup_stm32u5a5zjtxq.s

LoopFillZerobss:
    ldr    r3, = _ebss
    cmp    r2, r3
    bcc    FillZerobss

/* Call static constructors */
    bl __libc_init_array
/* Call the application's entry point.*/
//    bl    main    /*注释这一句*/
    bl    entry   /*增加这一句;因为RT-Thread板级初始化从entry入口进行,最后初始完后就会跳转到main.c*/

4)修改链接脚本

这里主要是对比了KEIL生成的链接脚本,发现没有包含finsh_shell部分的代码段;包含后,控制台才会有效;

  /* The program code and other data into "FLASH" Rom type memory */
  .text :
  {
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))
/*RT-thread GCC Add start*/    
    /* section information for finsh shell */
    . = ALIGN(4);
    __fsymtab_start = .;
    KEEP(*(FSymTab))
    __fsymtab_end = .;
    . = ALIGN(4);
    __vsymtab_start = .;
    KEEP(*(VSymTab))
    __vsymtab_end = .;
    . = ALIGN(4);

    /* section information for initial. */
    . = ALIGN(4);
    __rt_init_start = .;
    KEEP(*(SORT(.rti_fn*)))
    __rt_init_end = .;
    . = ALIGN(4);
    /* RT-thread GCC Add end */

    _etext = .;        /* define a global symbols at end of code */
  } >FLASH

5)修改main.c

  • 注释掉HAL初始化相关函数
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 // HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
//  SystemClock_Config();

  /* Configure the System Power */
//  SystemPower_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
//  MX_GPIO_Init();
//  MX_ICACHE_Init();
//  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    thread_sample();

  /* USER CODE END 3 */
}
  • 创建两个led任务
static void led1_thread_entry(void *parameter) {
    while(1)
    {
        HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
        rt_thread_mdelay(1000);
        rt_kprintf("LD1 test\n");
    }
}

static void led2_thread_entry(void *parameter) {
    while(1) {
        HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
        rt_thread_mdelay(1000);
        rt_kprintf("LD2 test\n");
    }
}

/* 线程示例 */
int thread_sample(void)
{
    /* 创建线程1,名称是thread1,入口是thread1_entry*/
    led1_thread = rt_thread_create("led1-thread",
                            led1_thread_entry, RT_NULL,
                            THREAD_STACK_SIZE,
                            THREAD_PRIORITY, THREAD_TIMESLICE);

    /* 如果获得线程控制块,启动这个线程 */
    if (led1_thread != RT_NULL)
        rt_thread_startup(led1_thread);

    /* 初始化线程2,名称是led2_thread,入口是led2_thread_entry */
    led2_thread = rt_thread_create("led2-thread",
                                led2_thread_entry, RT_NULL,
                            THREAD_STACK_SIZE,
                            THREAD_PRIORITY, THREAD_TIMESLICE);

    /* 如果获得线程控制块,启动这个线程 */
    if (led2_thread != RT_NULL)
        rt_thread_startup(led2_thread);

    return 0;
}

/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(thread_sample, thread sample);

6)编译下载

 

7)验证

串口打印,如图

 

四、遇到的错误

1、开始生成工程之后,编译报错Error: thumb conditional instruction,如图

解决方案:修改浮点ABI

 

2、串口报错

 

重新初始化串口即可

工程:

STM32U5A5-RT-thread.zip (19.74 MB, 下载次数: 0)

参考移植链接:

https://gitee.com/YaoDecheng/rt-thread-gcc-finsh-demo

使用 CubeMX 移植 (rt-thread.org)

STM32cubeIDE F4移植RTT系统 context_gcc.s 报错_thumb conditional instruction should be in it bloc-CSDN博客

context_gcc.s:110: Error: thumb conditional instruction should be in IT block `vstmdbeq r1!,{d8-d15}_rt-thread/libcpu/context_gcc.s(110): error: thumb -CSDN博客

此帖出自stm32/stm8论坛

最新回复

好强   详情 回复 发表于 2024-2-3 15:44
点赞 关注
 

回复
举报

73

帖子

0

TA的资源

一粒金砂(中级)

沙发
 

好强

此帖出自stm32/stm8论坛

点评

网上大佬比较多,参考就会了。哈哈  详情 回复 发表于 2024-2-3 19:26
 
 

回复

270

帖子

0

TA的资源

一粒金砂(高级)

板凳
 

网上大佬比较多,参考就会了。哈哈

此帖出自stm32/stm8论坛
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表