[GD32L233C-START 评测] 【GD32L233C-START评测】4. 移植RT-Thread到GD32L233

hehung   2022-1-19 22:04 楼主

上一篇帖子尝试了移植FreeRTOSGD32L233C并移植成功是实现了两个LED点灯任务:https://bbs.eeworld.com.cn/thread-1192482-1-1.html#pid3118101

本文将尝试使用国产的嵌入式实时操作系统RT-Thread,相比较于FreeRTOSRT-Thread还是有很多有点的,比如果有Fish命令行界面,国产开源免费,Nano版本代码量极小,移植起来非常简单(比freeRTOS移植还简单)等,本文将讲解如何将RT-Thread Nano移植到GD32L233C

本文参考资料:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-nano/nano-port-keil/an0039-nano-port-keil

注:本文基于KEIL编译器,IAR编译器可以参考文档:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-nano/nano-port-iar/an0040-nano-port-iar

 

一、获取RT-Thread基于KEIL的离线安装包

地址:https://www.rt-thread.org/download/mdk/RealThread.RT-Thread.3.1.5.pack

下载之后双击安装即可。

 

二、添加RT-Thread Nano到工程

  1. 打开我们自己的工程,在我的GD32L233C的第二篇帖子中,讲解了如何创建一个全新的工程,本文将会在上一篇创建的工程的基础上添加RT-Thread OS,观看上一篇帖子请移步:https://bbs.eeworld.com.cn/thread-1192155-1-1.html
  2. 点击 Manage Run-Time Environment,展开RTOS,勾上kernel

1.png  

 

  1. 点击OK,我们可以看到KEIL已经自动为我们添加了Cortex-M23相关的内核源码,这点还是很方便,很人性化的,不用我们在手动修改了 2.png
  2. 查看官方的文档堆各个文件都有具体的描述:

3.png

 

三、修改文件适配Rt-Thread

我们需要修改HardFault_Handler()  PendSV_Handler(),这两个文件是由RT-Thread实现的,所以我们工程里面原来的这两个函数都需要删除掉,屏蔽掉这两个函数的申明和定义:

4.png 5.png

 

四、修改系统时钟

RT-Thread已经为我们写好了时钟节拍函数rt_os_tick_callback(), board.c文件中,我们只需要将这个函数放置到SysTick_Handler()中即可,注意需要删除SysTick_Handler()中的原有内容。

6.png  

删除rt_hw_board_init()函数中的#error信息,这个函数在board.c文件中,其目的是提醒用户移植的时候不要忘了心跳节拍的移植,这点还是很人性化的,免得移植了半天发现不工作。

7.png  

五、修改时钟节拍

RT-Thread为我们提供的配置文件的时钟节拍是1000,也就是1ms,如果你想要修改心跳节拍,可以在rtconfig.h中修改这个宏RT_TICK_PER_SECOND,目前是1000,如果想修改节拍为10ms,则修改该值为10000,修改的时候最好不要直接修改rtconfig.h这个文件,因为KEIL提供了配置界面修改,在配置界面修改安全可靠。

9.png  

六、创建线程测试移植是否成功

经过了上面的步骤,我们的移植已经算是完成了,接下来就是写程序验证了,像上一篇帖子一样,我们写两个LED动作的线程,LED1 100ms闪烁一次,LED2 500ms闪烁一次来做对比,别忘了修改LED灯的引脚,上一篇帖子已经说明白了,引脚不对,需要我们自己修改,如下:

8.png  

main.c中写两个线程,如下:

#include "gd32l23x.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "gd32l233r_eval.h"
#include <rtthread.h>


static rt_thread_t led1_thr = RT_NULL;
static rt_thread_t led2_thr = RT_NULL;

static void thread_led1_entry(void *parameter);
static void thread_led2_entry(void *parameter);

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/

int main(void)
{
    /* configure systick */
    systick_config();
    /* initilize the LEDs, USART and key */
    gd_eval_led_init(LED1);
    gd_eval_led_init(LED2);

	  led1_thr = rt_thread_create( "led1",     /*线程名字*/                    
                                  thread_led1_entry,/*线程入口函数*/
                                  RT_NULL,/*线程入口函数参数*/
                                  256,    /*线程栈大小*/
                                  4 ,    /*线程优先级*/
                                  20);   /*线程时间片*/
		led2_thr = rt_thread_create( "led2",     /*线程名字*/                    
																	thread_led2_entry,/*线程入口函数*/
																	RT_NULL,/*线程入口函数参数*/
																	256,    /*线程栈大小*/
																	3 ,    /*线程优先级*/
																	20);   /*线程时间片*/
    
    rt_thread_startup (led1_thr);
	  rt_thread_startup (led2_thr);

    while(1) 
	  {
			  rt_thread_mdelay(100);
    }
}

static void thread_led1_entry(void *parameter)
{
    while (1)
    {
				gd_eval_led_toggle(LED1);
        rt_thread_mdelay(100);
    }
}

static void thread_led2_entry(void *parameter)
{
    while (1)
    {
        gd_eval_led_toggle(LED2);
        rt_thread_mdelay(500);
    }
}

 

编译成功下载,发现程序并不运行,这是为什么呢?

通过堆问题的查找,发现是main函数线程的堆栈空间分配的太小了,因为相比较于其他嵌入式系统,RT-Threadmain函数也做为了一个线程,我们在main函数中创建线程需要较大的空间,而RT-Thread给的默认配置的main线程的堆栈空间为256,修改为512即可

90.png  

再次编译下载,成功,后期可以使用RT-Thread来开发多线程任务了。

 

七、演示

1642600868345.gif

 

八、源码

GD32L233C_Prj_RTT_220119.zip (820.68 KB)
(下载次数: 32, 2022-1-19 22:03 上传)

有需要的小伙伴可以参考哦

 

如果本文有遗漏之处或者是错误之处,还请指正,谢谢

本帖最后由 hehung 于 2022-1-19 22:05 编辑

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复