• 第27章_瑞萨MCU零基础入门系列教程之freeRTOS实验


    本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id=728461040949

    配套资料获取:https://renesas-docs.100ask.net

    瑞萨MCU零基础入门系列教程汇总https://blog.csdn.net/qq_35181236/article/details/132779862


    第27章 freeRTOS实验

    本章目标

    • 学会使用RASC创建一个基于freertos的工程;
    • 学会使用RASC创建freertos任务,体验RTOS的多任务调度;

    27.1 创建基于FreeRTOS的工程

    使用RASC工具创建基于freertos的MDK工程非常的简单快捷,在前文创建MDK工程《3.5.1 使用RASC创建MDK工程》的最后一步那里,在“RTOS Selection”中选“FreeRTOS(v10.4.6+fsp.4.3.0)”即可,如下图所示:

    接下来会默认勾选“FreeRTOS-Minimal-Static Allocation”:

    到这一步后直接点击下方的“Finish”即可创建一个带有FreeRTOS的RA6M5 MDK工程了。

    27.2 FreeRTOS初体验

    27.2.1 新建线程

    在RASC中新建线程非常简单,在其配置界面的“Stacks”中右侧界面的“Threads”处点击“New Thread”,即可新建一个FreeRTOS的线程,也就是任务,如下图所示:

    上图中已经添加了两个线程“log_thread”和“led_thread”。

    27.2.2 添加堆分配算法模块

    添加完线程之后还需要添加堆分配算法,FreeRTOS支持5种堆算法:heap1~heap5。本实验选择的是heap4,首先选中任意一个FreeRTOS线程,比如“led_thread”,然后点击配置界面的“New
    Stack”,找到“RTOS”后选择要使用的算法即可,如下图所示:

    FreeRTOS中,只能选择一种堆算法。虽然上图里是在“led_thread”中为它选择了某个堆算法,但是这个堆算法不是“属于”某个线程,而是属于整个FreeRTOS的。你不能在另一线程里选择另一种堆算法。

    27.2.3 配置FreeRTOS通用参数

    要使用FreeRTOS,需要配置内核相关的许多参数,比如时钟基准,时钟频率,任务栈大小,分配内存时使用静态分配还是动态分配等等,这些参数在FSP种点击任意一个FreeRTOS线程即可看到关于内核的通用参数配置,然后根据自己的实际需求进行设置:

    1. Common-General

    在此处设置RTOS内核运行的时钟频率、任务最大优先级等参数,如下图所示:

    1. Common-Memory Allocation

    在此处设置内存分配相关的参数,比如是否支持静态内存分配、堆的大小,如下图所示:

    1. 其它通用参数

    还有很多参数,比如是否支持任务通知、互斥量等等,FreeRTOS是一个可以高度定制的内核,要想弄清楚这些参数,需要对它比较熟悉。

    27.2.4 配置线程参数

    对于某个线程,需要设置它的名称、栈大小、优先级等参数,如下图所示:

    27.2.5 驱动程序

    本实验使用的是串口和LED的驱动程序,请读者自行移植。

    27.2.6 线程程序

    1. LED线程

    在LED的线程入口函数中,本实验先对LED设备进行初始化,然后每隔300ms改变一次LED的状态以实现闪烁效果,代码如下:

    #include "led_thread.h"
    #include "drv_gpio.h"
    #include "hal_data.h"
    /* LedThread entry function */
    /* pvParameters contains TaskHandle_t */
    void led_thread_entry(void * pvParameters)
    {
        FSP_PARAMETER_NOT_USED(pvParameters);
    
        /* TODO: add your own code here */
        struct IODev *pLedDev = IOGetDecvice("UserLed");
        if(NULL != pLedDev)
            pLedDev->Init(pLedDev);
        bool state = false;
        while(1)
        {
            pLedDev->Write(pLedDev, state);
            state = !state;
            vTaskDelay(300);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    需要注意的是这里使用的是RTOS内核的延时函数,它让当前线程进入阻塞状态,让出处理器资源。

    1. 串口打印线程

    在串口打印线程的入口函数中,首先初始化了串口,然后每隔100ms计数一次并打印出来,代码如下:

    #include "log_thread.h"
    #include "drv_uart.h"
    #include "hal_data.h"
    #include 
    /* LogThread entry function */
    /* pvParameters contains TaskHandle_t */
    void log_thread_entry(void * pvParameters)
    {
        FSP_PARAMETER_NOT_USED(pvParameters);
    
        /* TODO: add your own code here */
        
        UARTDrvInit();
        
        uint32_t count = 0;
        while(1)
        {
            printf("\r\nLog: %d\r\n", count++);
            vTaskDelay(100);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    27.2.7 FreeRTOS启动分析

    FreeRTOS的启动过程,看main函数即可。创建2个线程后,启动调度器。代码如下:

    int main(void)
    {
        g_fsp_common_thread_count = 0;
        g_fsp_common_initialized = false;
    
        /* Create semaphore to make sure common init is done before threads start running. */
        g_fsp_common_initialized_semaphore =
        #if configSUPPORT_STATIC_ALLOCATION
        xSemaphoreCreateCountingStatic(
        #else
        xSemaphoreCreateCounting(
        #endif
            256,
            1
            #if configSUPPORT_STATIC_ALLOCATION
            , &g_fsp_common_initialized_semaphore_memory
            #endif
        );
    
        if (NULL == g_fsp_common_initialized_semaphore) {
            rtos_startup_err_callback(g_fsp_common_initialized_semaphore, 0);
        }
    
        /* Init RTOS tasks. */
        led_thread_create();
        log_thread_create();
    
        /* Start the scheduler. */
        vTaskStartScheduler();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 第07~22行:创建了一个计数型信号量;
    • 第25~26行:创建线程;
    • 第29行:开启FreeRTOS的调度器,如果开启成功则不会走到30行的“return 0”;

    对于RASC创建的FreeRTOS工程,它不会调用hal_entry()函数。

    27.2.8 测试结果

    将编译出来的二进制可执行文件烧录到板子上运行,可以观察到LED在闪烁,而且串口在打印如下图这样的信息:


    本章完
  • 相关阅读:
    【UCIe】UCIe 数据完整性
    TypeScript-04基础知识之类型操纵、类
    idea类和方法配置注释模板
    基于Genio 700 (MT8390)芯片的AR智能眼镜方案
    springcloud之项目实战环境准备
    【Linux】多进程编程
    lwIP - A Lightweight TCP/IP stack
    STL-reverse_iterator 反向迭代器
    Linux C应用编程-5-线程
    LeetCode刷题复盘笔记——46. 全排列(一文搞懂回溯解决全排列问题上篇)
  • 原文地址:https://blog.csdn.net/qq_35181236/article/details/132866586