FreeRTOS移植

一、获取FreeRTOS源码和简单介绍

1、获取方式

打开FreeRTOS官网:FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensions

2、FreeRTOS源码内容介绍

二、FreeRTOS移植 (以F1内存管理实验为例)

移植步骤:

1、添加FreeRTOS源码

在基础工程的 Middlewares 文件夹中新建一个 FreeRTOS 子文件夹,如下图所示:
接着就需要将 FreeRTOS 的源代码添加到刚刚新建的 FreeRTOS 子文件中了。将 FreeRTOS
内核源码的 Source 文件夹下的所有文件(.c文件和文件夹)添加到工程的 FreeRTOS 文件夹中,如下图所示:
将portable文件夹下的多余文件删除,删除后如下图所示:

2、将文件添加到工程

在keil中新建分组如下图所示:

添加FreeRTOS源码如图所示:

3、添加头文件路径

4、添加FreeRTOSConfig.h文件

在user文件中粘贴FreeRTOSConfig.h

5、修改文件

1.sys.h

将#define SYS_SUPPORT_OS 改位1

2.usart.c文件

3.delay.c文件

(1)删除:
/* 添加公共头文件 ( ucos需要用到) */
#include "os.h"
/* 定义 g_fac_ms 变量, 表示 ms 延时的倍乘数,
* 代表每个节拍的 ms 数, (仅在使能 os 的时候,需要用到)
*/
static uint16_t g_fac_ms = 0;
/*
* 当 delay_us/delay_ms 需要支持 OS 的时候需要三个与 OS 相关的宏定义和函数来支持
* 首先是 3 个宏定义:
* delay_osrunning :用于表示 OS 当前是否正在运行,以决定是否可以使用相关函数
* delay_ostickspersec :用于表示 OS 设定的时钟节拍,
* delay_init 将根据这个参数来初始化 systick
* delay_osintnesting :用于表示 OS 中断嵌套级别,因为中断里面不可以调度,
* delay_ms 使用该参数来决定如何运行
* 然后是 3 个函数:
* delay_osschedlock :用于锁定 OS 任务调度,禁止调度
* delay_osschedunlock :用于解锁 OS 任务调度,重新开启调度
* delay_ostimedly :用于 OS 延时,可以引起任务调度.
* 
* 本例程仅作 UCOSII 和 UCOSIII 的支持,其他 OS,请自行参考着移植
*/
/* 支持 UCOSII */
#ifdef OS_CRITICAL_METHOD /* OS_CRITICAL_METHOD 定义了
 * 说明要支持 UCOSII
 */
#define delay_osrunning OSRunning /* OS 是否运行标记,0,不运行;1,在运行 */
#define delay_ostickspersec OS_TICKS_PER_SEC /* OS 时钟节拍,即每秒调度次数 */
#define delay_osintnesting OSIntNesting /* 中断嵌套级别,即中断嵌套次数 */
#endif
/* 支持 UCOSIII */
#ifdef CPU_CFG_CRITICAL_METHOD /* CPU_CFG_CRITICAL_METHOD 定义了
 * 说明要支持 UCOSIII
 */
#define delay_osrunning OSRunning /* OS 是否运行标记,0,不运行;1,在运行 */
#define delay_ostickspersec OSCfg_TickRate_Hz /* OS 时钟节拍,即每秒调度次数 */
#define delay_osintnesting OSIntNestingCtr /* 中断嵌套级别,即中断嵌套次数 */
#endif
/**
* @brief us 级延时时,关闭任务调度(防止打断 us 级延迟)
* @param 无
* @retval 无
*/
static void delay_osschedlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD /* 使用 UCOSIII */
 OS_ERR err;
 OSSchedLock(&err); /* UCOSIII 的方式,禁止调度,防止打断 us 延时 */
#else /* 否则 UCOSII */
 OSSchedLock(); /* UCOSII 的方式,禁止调度,防止打断 us 延时 */
#endif
}
/**
* @brief us 级延时时,恢复任务调度
* @param 无
* @retval 无
*/
static void delay_osschedunlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD /* 使用 UCOSIII */
 OS_ERR err;
 OSSchedUnlock(&err); /* UCOSIII 的方式,恢复调度 */
#else /* 否则 UCOSII */
 OSSchedUnlock(); /* UCOSII 的方式,恢复调度 */
#endif
}
/**
* @brief us 级延时时,恢复任务调度
* @param ticks: 延时的节拍数
* @retval 无
*/
static void delay_ostimedly(uint32_t ticks)
{
#ifdef CPU_CFG_CRITICAL_METHOD
 OS_ERR err;
 OSTimeDly(ticks, OS_OPT_TIME_PERIODIC, &err); /* UCOSIII 延时采用周期模式 */
#else
 OSTimeDly(ticks); /* UCOSII 延时 */
#endif
}
(2)添加:

(3)修改部分内容:
需要修改的 4 个函数,分别是 SysTick_Handler() delay_init() delay_us()
delay_ms(),修改后分别如下:
void SysTick_Handler(void)
{
    HAL_IncTick();
    /* OS 开始跑了,才执行正常的调度处理 */
    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
    {
        xPortSysTickHandler();
    }
}
void delay_init(uint16_t sysclk)
{
#if SYS_SUPPORT_OS                                      /* 如果需要支持OS */
    uint32_t reload;
#endif
    SysTick->CTRL = 0;
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8);
 
    g_fac_us = sysclk / 8;
#if SYS_SUPPORT_OS
    reload = sysclk / 8;
    /* 使用 configTICK_RATE_HZ 计算重装载值
    * configTICK_RATE_HZ 在 FreeRTOSConfig.h 中定义
    */
    reload *= 1000000 / configTICK_RATE_HZ;
    /* 删除不用的 g_fac_ms 相关代码 */
    SysTick->CTRL |= 1 << 1;
    SysTick->LOAD = reload;
    SysTick->CTRL |= 1 << 0;
#endif
}
void delay_us(uint32_t nus)
{
    uint32_t ticks;
    uint32_t told, tnow, tcnt = 0;
    uint32_t reload = SysTick->LOAD;        /* LOAD的值 */
    ticks = nus * g_fac_us;                 /* 需要的节拍数 */
    
/* 删除适用于 μC/OS 用于锁定任务调度器的自定义函数 */
    ticks = nus * g_fac_us;
    told = SysTick->VAL;
    while (1)
    {
        tnow = SysTick->VAL;
        if (tnow != told)
        {
            if (tnow < told)
            {
                tcnt += told - tnow;
            }
            else
            {
                tcnt += reload - tnow + told;
            }
            told = tnow;
            if (tcnt >= ticks)
            {
                break;
            }
        }
    }
/* 删除适用于 μC/OS 用于解锁任务调度器的自定义函数 */
}
void delay_ms(uint16_t nms)
{
    uint32_t i;
    
    for (i=0; i<nms; i++)
    {
        delay_us(1000);
    }
}
(4)包含头文件
/* 添加公共头文件 (FreeRTOS 需要用到) */
#include "FreeRTOS.h"
#include "task.h"

4.修改中断相关文件

6、修改工程名称

7、移除USMART

8、添加定时器驱动

9、验证

 demo.c代码:

#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO         1
#define START_TASK_STACK_SIZE   128
TaskHandle_t    start_task_handler;
void start_task( void * pvParameters );

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO         2
#define TASK1_STACK_SIZE   128
TaskHandle_t    task1_handler;
void task1( void * pvParameters );

/* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO         3
#define TASK2_STACK_SIZE   128
TaskHandle_t    task2_handler;
void task2( void * pvParameters );

/* TASK3 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK3_PRIO         4
#define TASK3_STACK_SIZE   128
TaskHandle_t    task3_handler;
void task3( void * pvParameters );
/******************************************************************************************************/


/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{    
    xTaskCreate((TaskFunction_t         )   start_task,
                (char *                 )   "start_task",
                (configSTACK_DEPTH_TYPE )   START_TASK_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   START_TASK_PRIO,
                (TaskHandle_t *         )   &start_task_handler );
    vTaskStartScheduler();
}


void start_task( void * pvParameters )
{
    taskENTER_CRITICAL();               /* 进入临界区 */
    xTaskCreate((TaskFunction_t         )   task1,
                (char *                 )   "task1",
                (configSTACK_DEPTH_TYPE )   TASK1_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   TASK1_PRIO,
                (TaskHandle_t *         )   &task1_handler );
                
    xTaskCreate((TaskFunction_t         )   task2,
                (char *                 )   "task2",
                (configSTACK_DEPTH_TYPE )   TASK2_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   TASK2_PRIO,
                (TaskHandle_t *         )   &task2_handler );
                
    xTaskCreate((TaskFunction_t         )   task3,
                (char *                 )   "task3",
                (configSTACK_DEPTH_TYPE )   TASK3_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   TASK3_PRIO,
                (TaskHandle_t *         )   &task3_handler );
    vTaskDelete(NULL);
    taskEXIT_CRITICAL();                /* 退出临界区 */
}

/* 任务一,实现LED0每500ms翻转一次 */
void task1( void * pvParameters )
{
    while(1)
    {
        printf("task1正在运行!!!\r\n");
        LED0_TOGGLE();
        vTaskDelay(1000);
    }
}

/* 任务二,实现LED1每500ms翻转一次 */
void task2( void * pvParameters )
{
    while(1)
    {
        printf("task2正在运行!!!\r\n");
        LED1_TOGGLE();
        vTaskDelay(500);
    }
}

/* 任务三,判断按键KEY0,按下KEY0删除task1 */
void task3( void * pvParameters )
{
    uint8_t key = 0;
    while(1)
    {
        printf("task3正在运行!!!\r\n");
        key = key_scan(0);
        if(key == KEY0_PRES)
        {
            if(task1_handler != NULL)
            {
                printf("删除task1任务\r\n");
                vTaskDelete(task1_handler);
                task1_handler = NULL;
            }

        }
        vTaskDelay(10);
    }
}

  • 20
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值