3757|6

35

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【GD32L233C-START评测】2、rtthread + finsh 组件的移植 [复制链接]

本帖最后由 emmnn 于 2022-1-29 11:10 编辑

前言

    距离上次发帖也有两个多星期的时间了,这两天刚回到家,休息了两天,又想起了评测的事,就拿出板子继续玩了。目前还没完全确定要使用这块板子做什么东西,但是为了方便后续的开发及调试工作,就决定先把操作系统移植上去。今天断断续续整了一天(在家里没办法完全静下心来),终于移植好并成功运行了点灯的demo(最终演示效果如下)。


看完了演示视频,下面就开始介绍rtthread的移植过程吧。


一、RT-Thread简介

    RT-Thread,一款开源的嵌入式实时操作系统,作为一款优秀的国产操作系统,因其有着可裁剪,内存资源占用小,被广泛地应用在家电,消费电子等领域。关于RT-Thread的介绍这里不再多讲,感兴趣的可以去看他们的官方文档(RT-Thread)。RT-Thread共分为三个版本,分别为标准,nano和smart版本,今天主要介绍的是RT-Thread Nano的移植(RT-Thread下载地址),目前该版本官方更新维护到3.1.5,移植也是以这个版本为准。

    下载完成后,我们可以得到一个压缩包,解压后,目录结构如下:

 


二、RT-Thread移植

    介绍完RT-Thread,接下来就可以开始移植工作了。首先先把内核源码和CPU移植文件添加到我们的项目工程中。

     这里需要注意的一点是,因为GD32L233C基于Cortex-M23,所以libcpu我们需要选择对应的文件添加。

      将srclibcpu这两个文件中的相关内容添加到我们的工程后,接下来我们需要将板级配置文件board.crtconfig.h这两个文件也添加到工程中去。

 

    这里因为GD32E230k这款芯片跟GD32L233C同属Cortex-M23,因此我们选择到对应目录下将这两个文件拷贝到工程中。

    最后,为了方便后续开发调试,这里选择将finsh组件也移植上去(没这个需求的朋友可以跳过此处)。

    同样也是将components/finsh路径下的.c文件添加到工程中 ,最后添加后的工程文件如下:

       

    还有比较重要的一步,添加头文件路径。

    内核源码文件都添加后,基本工作也都完成了,接下来我们需要修改配置文件board.c和rtconfig.h,使OS能够适配我们的开发板。

    rtconfig.h文件配置如下(关于这个配置文件的介绍,注释讲的挺详细的,这里就不罗嗦了,看不懂的自行百度了):

/* RT-Thread config file */

#ifndef __RTTHREAD_CFG_H__
#define __RTTHREAD_CFG_H__

// <<< Use Configuration Wizard in Context Menu >>>

// <h>Basic Configuration
// <o>Maximal level of thread priority <8-256>
//  <i>Default: 32
#define RT_THREAD_PRIORITY_MAX  32
// <o>OS tick per second
//  <i>Default: 1000   (1ms)
#define RT_TICK_PER_SECOND  1000
// <o>Alignment size for CPU architecture data access
//  <i>Default: 4
#define RT_ALIGN_SIZE   4
// <o>the max length of object name<2-16>
//  <i>Default: 8
#define RT_NAME_MAX    16
// <c1>Using RT-Thread components initialization
//  <i>Using RT-Thread components initialization
#define RT_USING_COMPONENTS_INIT
// </c>

#define RT_USING_USER_MAIN

// <o>the stack size of main thread<1-4086>
//  <i>Default: 512
#define RT_MAIN_THREAD_STACK_SIZE     1024

// </h>

// <h>Debug Configuration
// <c1>enable kernel debug configuration
//  <i>Default: enable kernel debug configuration
//#define RT_DEBUG
// </c>
// <o>enable components initialization debug configuration<0-1>
//  <i>Default: 0
#define RT_DEBUG_INIT 0
// <c1>thread stack over flow detect
//  <i> Diable Thread stack over flow detect
//#define RT_USING_OVERFLOW_CHECK
// </c>
// </h>

// <h>Hook Configuration
// <c1>using hook
//  <i>using hook
//#define RT_USING_HOOK
// </c>
// <c1>using idle hook
//  <i>using idle hook
//#define RT_USING_IDLE_HOOK
// </c>
// </h>

// <e>Software timers Configuration
// <i> Enables user timers
#define RT_USING_TIMER_SOFT         0
#if RT_USING_TIMER_SOFT == 0
    #undef RT_USING_TIMER_SOFT
#endif
// <o>The priority level of timer thread <0-31>
//  <i>Default: 4
#define RT_TIMER_THREAD_PRIO        4
// <o>The stack size of timer thread <0-8192>
//  <i>Default: 512
#define RT_TIMER_THREAD_STACK_SIZE  512
// </e>

// <h>IPC(Inter-process communication) Configuration
// <c1>Using Semaphore
//  <i>Using Semaphore
#define RT_USING_SEMAPHORE
// </c>
// <c1>Using Mutex
//  <i>Using Mutex
//#define RT_USING_MUTEX
// </c>
// <c1>Using Event
//  <i>Using Event
//#define RT_USING_EVENT
// </c>
// <c1>Using MailBox
//  <i>Using MailBox
#define RT_USING_MAILBOX
// </c>
// <c1>Using Message Queue
//  <i>Using Message Queue
//#define RT_USING_MESSAGEQUEUE
// </c>
// </h>

// <h>Memory Management Configuration
// <c1>Dynamic Heap Management
//  <i>Dynamic Heap Management
//#define RT_USING_HEAP
// </c>
// <c1>using small memory
//  <i>using small memory
#define RT_USING_SMALL_MEM
// </c>
// <c1>using tiny size of memory
//  <i>using tiny size of memory
//#define RT_USING_TINY_SIZE
// </c>
// </h>

// <h>Console Configuration
// <c1>Using console
//  <i>Using console
#define RT_USING_CONSOLE

// </c>
// <o>the buffer size of console <1-1024>
//  <i>the buffer size of console
//  <i>Default: 128  (128Byte)
#define RT_CONSOLEBUF_SIZE          128
// </h>

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

// <h>Device Configuration
// <c1>using device framework
//  <i>using device framework
//#define RT_USING_DEVICE
// </c>
// </h>

// <<< end of configuration section >>>

#endif

    board.c,这个文件主要是用来配置系统时钟以及OS_TICK(也就是系统心跳)的,一些外设的初始化工作也可以丢到这里面来做。

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2009-01-05     Bernard      first implementation
 */
#include <stdint.h>
#include <rthw.h>
#include <rtthread.h>
#include "gd32l23x.h"
#include "usart.h"

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
void Error_Handler(void)
{
    /* USER CODE BEGIN Error_Handler */
    /* User can add his own implementation to report the HAL error return state */
    while (1)
    {
    }
    /* USER CODE END Error_Handler */
}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{
    /* setup systick timer for 1000Hz interrupts */
    if(SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND)) {
        /* capture error */
        while(1) {
        }
    }
    /* configure the systick handler priority */
    NVIC_SetPriority(SysTick_IRQn, 0x00U);
    
    #if 0
    SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
    NVIC_SetPriority(SysTick_IRQn, 0);
    #endif
}

/**
 * This is the timer interrupt service routine.
 *
 */
void SysTick_Handler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();

    rt_tick_increase();

    /* leave interrupt */
    rt_interrupt_leave();
}

/**
 * This function will initial GD32 board.
 */
void rt_hw_board_init(void)
{
    #if 0       //TODO:中断向量表,后续新增bootloader功能,在这里更改
    /* NVIC Configuration */
#define NVIC_VTOR_MASK              0x3FFFFF80
#ifdef  VECT_TAB_RAM
    /* Set the Vector Table base location at 0x10000000 */
    SCB->VTOR  = (0x10000000 & NVIC_VTOR_MASK);
#else  /* VECT_TAB_FLASH  */
    /* Set the Vector Table base location at 0x08000000 */
    SCB->VTOR  = (0x08000000 & NVIC_VTOR_MASK);
#endif
    #endif

    SystemClock_Config();

#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    rt_system_heap_init((void*)HEAP_BEGIN, (void*)HEAP_END);
#endif

    usartInit(DEBUG_COM_PER, DEBUG_COM_BAUD);
}

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')
        {
            usart_data_transmit(DEBUG_COM_PER, (uint32_t )a);
            while((usart_flag_get(DEBUG_COM_PER, USART_FLAG_TC) == RESET));
        }
        usart_data_transmit(DEBUG_COM_PER, (uint32_t)*(str + i));
        while((usart_flag_get(DEBUG_COM_PER, USART_FLAG_TC) == RESET));
    }
}

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

    if (usart_flag_get(DEBUG_COM_PER, USART_FLAG_RBNE) != RESET)
    {
        ch = usart_data_receive(DEBUG_COM_PER);
    }
    else
    {
        rt_thread_mdelay(10);
    }
    return ch;
}

    其中,rt_hw_console_outputrt_hw_console_getchar这两个函数,分别用来做系统的串口输出处理和tshell 指令输入的获取的,SystemClock_Config则是系统时钟初始化。


    到这里,我们可以先尝试编译下工程,会看到有报错问题。

     这几个重复定义的,我们直接注释掉即可,因为这几个中断以及被RT-Thread接管了,一般情况下不用再去理会。

    再次编译,正常情况下是不会再报错了。最后就是写个demo验证下移植的成果。

static struct rt_thread led_thread;
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t rt_led_thread_stack[512];
static void led_thread_entry(void * para);
static rt_uint8_t led_thread_priority = 5;


/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void)
{
//    PRO_LOG(LOG_DEBUG, "Entry %s. \r\n", __func__);
    led_init();
 	/* led thread */
	rt_thread_init(&led_thread,
					"led_thread",
					led_thread_entry,
					RT_NULL,
					&rt_led_thread_stack,
					sizeof(rt_led_thread_stack),
					led_thread_priority,
					1000);
	rt_thread_startup(&led_thread);
}
static void led_thread_entry(void * para)
{
    PRO_LOG(LOG_DEBUG, "Entry %s. \r\n", __func__);
    while(1)
    {
        LED1_TOGGLE();
        LED2_TOGGLE();
        rt_thread_delay(1000);
    }
}

    这里的演示结果就是开头的视频,再打开串口看看

     Finsh组件也能正常使用。


总结

    至此,RT-Thread的移植工作已完成(工程源码见附件),后续有时间再分享其他内容给大家。如果所发内容有什么错误或者大家有什么其他的见解,也欢迎大家在评论区指出,谢谢!

此帖出自GD32 MCU论坛

最新回复

没看见工程文件呢  详情 回复 发表于 2022-5-23 10:50
点赞 关注
 

回复
举报

35

帖子

1

TA的资源

一粒金砂(中级)

沙发
 

附件超过15M好像就不行了,源码直接上传到资源文件中去了,目前还在审核中,需要的可以到我的主页中去下载

此帖出自GD32 MCU论坛
 
 
 

回复

7063

帖子

11

TA的资源

版主

板凳
 

可以用.7z的压缩包来压缩,我原先这是这样,原来用zip的15M,用7z的8M就行了!希望对你有帮助。

此帖出自GD32 MCU论坛

点评

好的,谢谢  详情 回复 发表于 2022-2-7 10:57
 
 
 

回复

35

帖子

1

TA的资源

一粒金砂(中级)

4
 
lugl4313820 发表于 2022-2-6 08:53 可以用.7z的压缩包来压缩,我原先这是这样,原来用zip的15M,用7z的8M就行了!希望对你有帮助。

好的,谢谢

此帖出自GD32 MCU论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

5
 

没看见工程文件呢

此帖出自GD32 MCU论坛

点评

在我的下载中心有工程文件  详情 回复 发表于 2022-5-24 14:18
我看下什么情况  详情 回复 发表于 2022-5-24 14:13
 
 
 

回复

35

帖子

1

TA的资源

一粒金砂(中级)

6
 
Sky浅梦 发表于 2022-5-23 10:50 没看见工程文件呢

我看下什么情况

此帖出自GD32 MCU论坛
 
 
 

回复

35

帖子

1

TA的资源

一粒金砂(中级)

7
 
Sky浅梦 发表于 2022-5-23 10:50 没看见工程文件呢

在我的下载中心有工程文件

此帖出自GD32 MCU论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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

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

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

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