【GD32307E-START】RT-Thread移植测试

news2024/11/27 10:27:27

【GD32307E-START】RT-Thread移植测试

1. 软硬件平台

  1. GD32F307E-START Board开发板
  2. MDK-ARM Keil
  3. GCC Makefile

2. 物联网RTOS—RT-Thread

  1. RT-Thread

RT-Thread诞生于2006年,是一款以开源、中立、社区化发展起来的物联网操作系统。 RT-Thread主要采用 C 语言编写,浅显易懂,且具有方便移植的特性(可快速移植到多种主流 MCU 及模组芯片上)。RT-Thread把面向对象的设计方法应用到实时系统设计中,使得代码风格优雅、架构清晰、系统模块化并且可裁剪性非常好。RT-Thread完整版,通过在线的软件包管理工具,配合系统配置工具实现直观快速的模块化裁剪,并且可以无缝地导入丰富的软件功能包,从而实现复杂功能。

下图是 RT-Thread 的软件框图:

在这里插入图片描述

  1. RT-Thread Nano

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

下图是 RT-Thread Nano 的软件框图,包含支持的 CPU 架构与内核源码,还有可拆卸的 FinSH 组件:
在这里插入图片描述

支持架构:ARM:Cortex M0/ M3/ M4/ M7 等、RISC-V 及其他。

功能:线程管理、线程间同步与通信、时钟管理、中断管理、内存管理。

RT-Thread Nano的特点
  1. 下载简单

    RT-Thread Nano 以软件包的方式集成在 Keil MDK 与 CubeMX 中,可以直接在软件中下载 Nano 软件包获取源码,获取方式详见 基于 Keil MDK 移植 RT-Thread Nano 与 基于 CubeMX 移植 RT-Thread Nano 。同时也提供 下载 Nano 源码压缩包 的途径,方便在其他开发环境移植 RT-Thread Nano,如 基于 IAR 移植 RT-Thread Nano。

  2. 代码简单
    与RT-Thread 完整版不同的是,Nano 不含 Scons 构建系统,不需要 Kconfig 以及 Env 配置工具,也去除了完整版特有的 device 框架和组件,仅是一个纯净的内核。

  3. 移植简单
    由于 Nano 的极简特性,使 Nano 的移植过程变得极为简单。添加 Nano 源码到工程,就已完成 90% 的移植工作。

  4. 易裁剪:Nano 的配置文件为 rtconfig.h,该文件中列出了内核中的所有宏定义,有些默认没有打开,如需使用,打开即可。

  5. 易添加 FinSH 组件:FinSH 组件 可以很方便的在 Nano 上进行移植,而不再依赖 device 框架,只需要对接两个必要的函数即可完成 FinSH 移植。

  6. 资源占用小:对 RAM 与 ROM 的开销非常小,在支持 semaphore 和 mailbox 特性,并运行两个线程 (main 线程 + idle 线程) 情况下,ROM 和 RAM 依然保持着极小的尺寸,RAM 占用约 1K 左右,ROM 占用 4K 左右。

移植过程

  1. RT-Thread Nano 内核移植

    RT-Thread Nano移植较为简单,参考官方教程。我这里里面可能有少步骤的,大体也差不多。其实我实际对接内核就改了一个SystemClock_Config()函数的实现,其他的基本上没有太大变化,然后就是一些宏定义的打开,特别是你需要使用FINSH组件的时候。

官方移植教程 基于 Keil MDK 移植 RT-Thread Nano

官方移植教程 在 RT-Thread Nano 上添加控制台与 FinSH

  1. 在之前的工程模板基础上,添加RT-Thread Nano代码文件。在keil里面添加文件即可。

在这里插入图片描述

componentsFinsh
include头文件
libcpuCortex M0/ M3/ M4/ M7/RISC-V
src内核源代码(重点)

在这里插入图片描述

  1. 需要注意是,RT-Thread/port里面需要选择与芯片匹配的文件,GD32F307E-START Board是Cortex-M4内核的芯片,选择添加相关文件。Cortex-M 芯片内核移植文件如下:

在这里插入图片描述

  1. RT-Thread 会接管异常处理函数 HardFault_Handler() 和悬挂处理函数 PendSV_Handler(),这两个函数已由 RT-Thread 实现,所以需要删除工程里中断服务例程文件中的这两个函数,避免在编译时产生重复定义。如果此时对工程进行编译,没有出现函数重复定义的错误,则不用做修改。因此在我们的工程里面需要把gd32f30x_it.c文件中的HardFault_Handler、PendSV_Handler、SysTick_Handler函数注释掉。

在这里插入图片描述
4. 添加board.c rtconfig.h文件,这两个文件非常重要。重点需要修改这两个文件。

  修改rt_hw_board_init,SystemClock_Config();你可以main函数里的systick_config();注释掉

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 由于 SysTick_Handler() 中断服务例程由用户在 board.c 中重新实现,做了系统 OS Tick,所以还需要删除工程里中原本已经实现的 SysTick_Handler() ,避免在编译时产生重复定义。如果此时对工程进行编译,没有出现函数重复定义的错误,则不用做修改。

    在这里插入图片描述

  2. 系统内存堆的初始化
    系统内存堆的初始化在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() 将被调用.
    初始化内存堆需要堆的起始地址与结束地址这两个参数,系统中默认使用数组作为 heap,并获取了 heap 的起始地址与结束地址,该数组大小可手动更改.
    在这里插入图片描述
    在这里插入图片描述

注意:开启 heap 动态内存功能后,heap 默认值较小,在使用的时候需要改大,否则可能会有申请内存失败或者创建线程失败的情况,修改方法有以下两种:

  • 可以直接修改数组中定义的 RT_HEAP_SIZE 的大小,至少大于各个动态申请内存大小之和,但要小于芯片 RAM 总大小。
  • 也可以参考 《RT-Thread Nano 移植原理》——实现动态内存堆 章节进行修改,使用 RAM ZI 段结尾处作为 HEAP 的起始地址,使用 RAM 的结尾地址作为 HEAP 的结尾地址,这是 heap 能设置的最大值的方法。
  1. 编写主程序代码

    创建一个线程,同时支持串口打印

    
    #include "gd32f30x.h"
    #include "systick.h"
    #include <stdio.h>
    #include <rtthread.h>
    #include "bsp_led.h"
    
    
    /* retarget the C library printf function to the USART */
    int fputc(int ch, FILE *f)
    {
        usart_data_transmit(USART0 , (uint8_t)ch);
        while(RESET == usart_flag_get(USART0 , USART_FLAG_TBE));
        return ch;
    }
    
    /*****************************************************************************
      * @brief  This function
      * @param  None
      * @retval None
      */
    void bsp_uart_init(void)
    {
    	
        /* enable GPIO clock */
        rcu_periph_clock_enable(RCU_GPIOB);
    		
        /* enable AF clock */
    	rcu_periph_clock_enable(RCU_AF);
    
        /* enable USART clock */
        rcu_periph_clock_enable(RCU_USART0);
    
        /* connect port to USARTx_Tx */
        gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
    
        /* connect port to USARTx_Rx */
        gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
        
    	/* USART0 remap configure */
    	  gpio_pin_remap_config(GPIO_USART0_REMAP,ENABLE);
    		
        /* USART configure */
        usart_deinit(USART0);
    		
        usart_baudrate_set(USART0, 115200U);
    		
        usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    		
        usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
    		
        usart_enable(USART0);	
    	
    }
    
    
    /* 定义线程控制块 */
    static rt_thread_t led_thread = RT_NULL;
    
    /*
    *************************************************************************
    *                             线程定义
    *************************************************************************
    */
     
    static void led_thread_entry(void* parameter)
    {	
    	while (1)
    	{
    
            gpio_bit_set(GPIOC,GPIO_PIN_6);
            rt_thread_delay(500);   /* 延时500个tick */
            rt_kprintf("led_thread running,LED1_ON\r\n");
            
            gpio_bit_reset(GPIOC,GPIO_PIN_6);    
            rt_thread_delay(500);   /* 延时500个tick */		 		
            rt_kprintf("led_thread running,LED1_OFF\r\n"); 
    
    
            rt_kprintf("led_thread running,LED2_ON\r\n");     
            rt_thread_delay(500);   /* 延时500个tick */
            
            rt_kprintf("led_thread running,LED2_OFF\r\n");
            rt_thread_delay(500);   /* 延时500个tick */
            
    	
    	}
    }
    
    /*
    *************************************************************************
    *                             函数声明
    *************************************************************************
    */
    static void led_thread_entry(void* parameter);
    
    void Hardware_Init(void)
    {
    
        SystemInit (); 
       	//systick_config();
        bsp_uart_init();
    
        HW_LED_Init();  
        
    }
    
    int main(void)
    {
    	Hardware_Init();
        printf("SystemInit [ok] \r\n");
        printf("systick_config[ok] \r\n");
        printf("bsp_uart_init [ok] \r\n");
        printf("Hardware_Init [ok] \r\n");
        printf("LED_Init [ok] \r\n");
        printf("GD32307E-START Board Testing \r\n");
    
       led_thread =                          /* 线程控制块指针 */
        rt_thread_create( "led",              /* 线程名字 */
                          led_thread_entry,   /* 线程入口函数 */
                          RT_NULL,             /* 线程入口函数参数 */
                          512,                 /* 线程栈大小 */
                          3,                   /* 线程的优先级 */
                          20);                 /* 线程时间片 */
                       
        /* 启动线程,开启调度 */
       if (led_thread != RT_NULL)
            rt_thread_startup(led_thread);
        else
            return -1;
        
    }
    
    

    需要注意的是,用于finish打印,实现rt_ktprintf() 此函数可以在kservies.c中实现

    如果需要使用Finsh组件,需要添加相关的代码文件,并且添加rt_hw_console_getchar()代码实现

    //用于finish打印,实现rt_ktprintf()
    //此函数可以在kservies.c中实现
    void rt_hw_console_output(const char *str)
    {
    //    printf(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_data_transmit(USART0,a);
                         while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
                    }
                    usart_data_transmit(USART0, *(str+i));
                    while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
            }
     
    }
    
    //用于finish输入
    char rt_hw_console_getchar(void)
    {
          int ch =-1;
         
          if( usart_flag_get(USART0,USART_FLAG_RBNE) != RESET)
            {
               ch  =   (uint8_t)usart_data_receive(USART0);
               
     
            }
          else{
                if ( usart_flag_get(USART0,USART_FLAG_ORERR) != RESET)
                {
                    usart_flag_clear(USART0, USART_FLAG_RBNE);
                    //rt_thread_mdelay(10);
                }
     
          }
          
          return ch;
    }
    
    

测试效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

其实gcc的工程 我也进行了实验,但是虽然能下载程序了,但是不能进入内核出现错误,后面有时间再看看吧,有时间继续实践里面的各个example,完成rt-thread的学习。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
同样的问题,有时间看看这个能不能修改成功
GD32 RT_Thread Nano —UNALIGNED 非对齐访问出错
https://blog.csdn.net/qq_34442618/article/details/122586131?

  1. RT-Thread 完整版测试

    在RT-Thread的官方仓库里面有这个板子的bsp,但是我进行了下载程序,不是这个程序的效果。后面有时间再看看吧。

    https://gitee.com/rtthread/rt-thread/tree/master/bsp/gd32/arm/gd32307e-start

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1257311.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RH2288H V3服务器使用ISO安装系统

1.配置和服务器相同网段地址&#xff0c;RH2288H V3服务器bmc管理网口默认IP是192.168.2.100/24&#xff0c;默认用户root&#xff0c;默认Huawei12#$&#xff0c;网线连接BMC口&#xff0c;登录。默认密码可以在开机时按del键进入配置页面修改 2.配置raid&#xff0c;生产环境…

SpringCloud 微服务全栈体系(十八)

第十一章 分布式搜索引擎 elasticsearch 八、RestClient 查询文档 文档的查询同样适用 RestHighLevelClient 对象&#xff0c;基本步骤包括&#xff1a; 准备 Request 对象准备请求参数发起请求解析响应 1. 快速入门 以 match_all 查询为例 1.1 发起查询请求 代码解读&…

基于Java SSM框架+Vue实现药品销售进销存网站项目【项目源码+论文说明】

基于java的SSM框架Vue实现药品销售进销存网站演示 摘要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于药品管理系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了…

岂曰无衣 汉家衣裳再现锦绣美景

——福州第五届1122汉服节出行盛大开幕11月25日下午&#xff0c;闽江之心海丝广场&#xff0c;一场盛大的汉服文化节——福州第五届1122汉服节出行活动在这里隆重开幕。这个被誉为“穿在身上的历史”的传统文化&#xff0c;在这片古老而神秘的土地上焕发出新的生机与活力。据了…

Win10电脑用U盘重装系统的步骤

在Win10电脑中&#xff0c;用户遇到了无法解决的系统问题&#xff0c;用户这时候就可以考虑重装Win10系统&#xff0c;这样即可轻松解决问题&#xff0c;从而满足自己的操作需求。接下来小编给大家详细介绍关于Win10电脑中用U盘重装系统的教程步骤。 准备工作 1. 一台正常联网可…

group by

引入 日常开发中&#xff0c;我们经常会使用到group by。你是否知道group by的工作原理呢&#xff1f;group by和having有什么区别呢&#xff1f;group by的优化思路是怎样的呢&#xff1f;使用group by有哪些需要注意的问题呢&#xff1f; 使用group by的简单例子group by 工…

火力发电厂电气一次部分初步设计(论文+图纸)

1 原始资料 设计电厂为中型是凝汽式发电厂&#xff0c;共4台发电机组&#xff0c;2台75MW机组&#xff0c;2台50MW机组&#xff0c;总的装机容量为250MW&#xff0c;占系统容量的比例为&#xff1a; 250/(3500250)100%6.7%<15%&#xff0c;未超过电力系统的检修备用容量和…

深入理解JMM以及并发三大特性(2)

书接上文 文章目录 (1)CPU高速缓存(2)缓冲一致性(3)总线仲裁机制(4)总线窥探(Bus Snooping) 前面介绍到实现可见性&#xff0c;底层常用的一种方案是使用内存屏障&#xff0c;而内存屏障在汇编层面又是使用lock前缀指令来实现的&#xff0c;所以这里来介绍一下lock前缀指令。 …

skywalking 简单操作文档

1.1. 基础概念 1.1.1. 概述 SkyWalking是 apache基金会下面的一个开源 APM项目&#xff0c;为微服务架构和云原生架构系统设计。它通过探针自动收集所需的指标&#xff0c;并进行分布式追踪。通过这些调用链路以及指标&#xff0c;Skywalking APM会感知应用间关系和服务间关系…

酷开科技 | 酷开系统,让你与家人共度美好时光!

在日渐繁忙的生活中&#xff0c;我们常常会忽略和家人朋友的相处时光&#xff0c;有时候&#xff0c;我们亟需一种休闲方式&#xff0c;让家庭成员能够围坐在一起&#xff0c;享受无忧无虑的温馨和欢笑。酷开科技&#xff0c;致力于为消费者提供舒适的产品和服务内容&#xff0…

Windows11系统如何将此电脑和回收站图标放置在桌面上?

Windows11系统如何将此电脑和回收站图标放置在桌面上&#xff1f; 如下图所示&#xff0c;点击“开始”图标&#xff0c;&#xff0c;找到“设置”&#xff0c; 如下图所示&#xff0c;进入设置后&#xff0c;找到个性化—主题&#xff0c; 如下图所示&#xff0c;在个性化—主…

免费分享一套基于springboot的餐饮美食分享平台系统,挺漂亮的

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的基于springboot的餐饮美食分享平台系统&#xff0c;分享下哈。 项目视频演示 【免费】基于springboot的餐饮美食分享平台 Java毕业设计_哔哩哔哩_bilibili【免费】基于springboot的餐饮美食分享平台 Java毕…

校园导游程序及通信线路设计(结尾附着总源码)

校园导游程序及通信线路设计 摘  要 新生或来访客人刚到校园&#xff0c;对校园的环境不熟悉。就需要一个导游介绍景点&#xff0c;推荐到下一个景点的最佳路径等。随着科技的发展&#xff0c;社会的进步&#xff0c;人们对便捷的追求也越来越高。为了减少人力和时间。针对对…

VMWare虚拟机ubuntu克隆打不开

ubuntu克隆打不开 复制的存有ubuntu克隆的文件夹&#xff0c;导入vmware打不开 说找不到这个文件&#xff0c;那就到目录把它的删掉 的删掉 换000001.vmdk后缀的

好用的基于layui的免费开源后台模版layuimini

发现一个好用的后台模版 基于layui的免费开源后台模版layuimini layuimini - 基于Layui的后台管理系统前端模板 easyadmin开源项目 EasyAdmin是基于ThinkPHP6.0Layui的快速开发的后台管理系统。 演示站点 演示地址&#xff1a;跳转提示&#xff08;账号&#xff1a;admin&a…

C++学习之路(六)C++ 实现简单的工具箱系统命令行应用 - 示例代码拆分讲解

简单的工具箱系统示例介绍: 这个示例展示了一个简单的工具箱框架&#xff0c;它涉及了几个关键概念和知识点&#xff1a; 面向对象编程 (OOP)&#xff1a;使用了类和继承的概念。Tool 是一个纯虚类&#xff0c;CalculatorTool 和 FileReaderTool 是其派生类。 多态&#xff1…

JavaScript WebApi(二) 详解

监听事件 介绍 事件监听是一种用于在特定条件下执行代码的编程技术。在Web开发中&#xff0c;事件监听器可以用于捕获和响应用户与页面交互的各种操作&#xff0c;如点击、滚动、输入等。 事件监听的基本原理是&#xff0c;通过在特定元素上注册事件监听器&#xff0c;当事件…

Elastic Search的RestFul API入门:初识mapping

本节课旨在探讨Elasticsearch中Mapping的使用。在Elasticsearch中&#xff0c;Mapping是定义索引中字段&#xff08;Field&#xff09;的数据类型和属性的过程。它为Elasticsearch提供了一种途径&#xff0c;以解析和处理文档中的各个字段&#xff0c;以便在搜索、排序和聚合等…

【开源】基于Vue和SpringBoot的个人健康管理系统

项目编号&#xff1a; S 040 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S040&#xff0c;文末获取源码。} 项目编号&#xff1a;S040&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 健康档案模块2.2 体检档案模块2.3 健…

前端入门(三)Vue生命周期、组件原理、脚手架、插槽插件、存储、组件事件、动画、跨域与代理

文章目录 Vue生命周期Vue 组件化编程 - .vue文件非单文件组件组件的注意点组件嵌套Vue实例对象和VueComponent实例对象Js对象原型与原型链Vue与VueComponent的重要内置关系 应用单文件组件构建 Vue脚手架 - vue.cli项目文件结构组件相关高级属性引用名 - ref数据接入 - props混…