FreeRTOS动态任务的创建与删除(尚硅谷学习笔记)

 文件下载的官网地址:FreeRTOS™ - FreeRTOS™

 Source文件夹下7个.c文件全部移植过来

  • port.c文件:里面的内容是由 FreeRTOS 官方的技术人员为 Cortex-M3 内核的处理器写的接口文件,里面核心的上下文切换代码是由汇编语言编写而成,对技术员的要求比较高,我们只是使用的话只需拷贝过来用即可。
  • portmacro.h文件:port.c文件对应的头文件,主要是一些数据类型和宏定义。

如果需要其他内核的自己寻找到RVDS下对应的port.c和portmacro.h文件

 MemMang 文件夹下存放的是跟内存管理相关的,总共有五个 heap 文件以及一个 readme 说明文件。一般只用heap_4c

 FreeRTOSConfig.h 文件是 FreeRTOS 的工程配置文件,因为 FreeRTOS 是可以裁剪的 实时操作内核,应用于不同的处理器平台,用户可以通过修改这个 FreeRTOS 内核的配置 头文件来裁剪 FreeRTOS 的功能,我们把它拷贝一份放在FreeRTOS这个文件夹下面(路径随意,只要能添加其路径就好)。

将这些文件添加到一个文件夹下,并在VScode中添加路径(我的是FreeRTOS,方便后面快速移植)

注意:HAL本身和FreeRTOS都默认依赖SysTick,可能出现卡死的问题。

为了保险起见,可以考虑在SYS选择HAL时钟源的时候换成其他的,并且中断优先级设为较高,比如1。

 在stm32f1xx_it.c中添加两个头文件

 在stm32f1xx_it.c中注释两个函数void SVC_Handler(void)和void PendSV_Handler(void)

 在stm32f1xx_it.c中声明并在void SysTick_Handler(void)编写滴答定时器

    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
    {
        xPortSysTickHandler();
    }

在FreeRTOSConfig.h文件添加三个宏

#define xPortPendSVHandler  PendSV_Handler
#define vPortSVCHandler     SVC_Handler
#define INCLUDE_xTaskGetSchedulerState   1

freertos_demo.c文件

/*
 * @Author: random
 * @Date: 2025-05-10 01:23:40
 * @Last Modified by: random
 * @Last Modified time: Do not Edit
 */
#include "freertos_demo.h"
/* freertos相关的头文件,必须的 */
#include "FreeRTOS.h"
#include "task.h"
/* 需要用到的其他头文件 */
#include "fun.h"

/* 启动任务的配置 */
#define START_TASK_STACK 128
#define START_TASK_PRIORITY 1
TaskHandle_t start_task_handle;
void start_task(void *pvParameters);

/* 任务1的配置 */
#define TASK1_STACK 128
#define TASK1_PRIORITY 2
TaskHandle_t task1_handle;
void task1(void *pvParameters);

/* 任务2的配置 */
#define TASK2_STACK 128
#define TASK2_PRIORITY 3
TaskHandle_t task2_handle;
void task2(void *pvParameters);

/* 任务3的配置 */
#define TASK3_STACK 128
#define TASK3_PRIORITY 4
TaskHandle_t task3_handle;
void task3(void *pvParameters);

/**
 * @description: 启动FreeRTOS
 * @return {*}
 */
void freertos_start(void)
{
    /* 1.创建一个启动任务 */
    xTaskCreate((TaskFunction_t)start_task,               // 任务函数的地址
                (char *)"start_task",                     // 任务名字符串
                (configSTACK_DEPTH_TYPE)START_TASK_STACK, // 任务栈大小,默认最小128,单位4字节
                (void *)NULL,                             // 传递给任务的参数
                (UBaseType_t)START_TASK_PRIORITY,         // 任务的优先级
                (TaskHandle_t *)&start_task_handle);      // 任务句柄的地址

    /* 2.启动调度器:会自动创建空闲任务 */
    vTaskStartScheduler();
}

/**
 * @description: 启动任务:用来创建其他Task
 * @param {void} *pvParameters
 * @return {*}
 */
void start_task(void *pvParameters)
{
    /* 进入临界区:保护临界区里的代码不会被打断 */
    taskENTER_CRITICAL();

    /* 创建3个任务 */
    xTaskCreate((TaskFunction_t)task1,
                (char *)"task1",
                (configSTACK_DEPTH_TYPE)TASK1_STACK,
                (void *)NULL,
                (UBaseType_t)TASK1_PRIORITY,
                (TaskHandle_t *)&task1_handle);
    xTaskCreate((TaskFunction_t)task2,
                (char *)"task2",
                (configSTACK_DEPTH_TYPE)TASK2_STACK,
                (void *)NULL,
                (UBaseType_t)TASK2_PRIORITY,
                (TaskHandle_t *)&task2_handle);
    xTaskCreate((TaskFunction_t)task3,
                (char *)"task3",
                (configSTACK_DEPTH_TYPE)TASK3_STACK,
                (void *)NULL,
                (UBaseType_t)TASK3_PRIORITY,
                (TaskHandle_t *)&task3_handle);
    /* 启动任务只需要执行一次即可,用完就删除自己 */
    vTaskDelete(NULL);

    /* 退出临界区 */
    taskEXIT_CRITICAL();
}

/**
 * @description: 任务一:实现LED1每500ms闪烁一次
 * @param {void} *pvParameters
 * @return {*}
 */
void task1(void *pvParameters)
{

    while (1)
    {
        printf("task1 is running\r\n");
        led_n(1, 1);
        vTaskDelay(500);
        led_n(1, 0);
        vTaskDelay(500);
    }
}

/**
 * @description: 任务二:实现LED2每500ms闪烁一次
 * @param {void} *pvParameters
 * @return {*}
 */
void task2(void *pvParameters)
{
    while (1)
    {
        printf("task2 is running\r\n");
        led_n(8, 1);
        vTaskDelay(500);
        led_n(8, 0);
        vTaskDelay(500);
    }
}

/**
 * @description: 任务三:判断按键KEY1是否按下,按下则删掉task1
 * @param {void} *pvParameters
 * @return {*}
 */
extern volatile uint8_t j;
extern volatile uint8_t key_number;
void task3(void *pvParameters)
{
    while (1)
    {
        printf("task3 is running\r\n");
        if (key_number == 1)
        {
            /* 判断是否已经删过,避免重复执行删除 */
            if (task1_handle != NULL)
            {
                /* key1按下了,删除task1 */
                printf("task1 is delete\r\n");
                vTaskDelete(task1_handle);
                task1_handle = NULL;
            }
            key_number = 0;
        }
        vTaskDelay(500);
        // HAL_Delay(500); //这种delay不会让任务进入阻塞态,不会让出cpu使用权
    }
}

freertos_demo.h文件

/*
 * @Author: random
 * @Date: 2025-05-10 01:23:57
 * @Last Modified by: random
 * @Last Modified time: Do not Edit
 */

#ifndef __FREERTOS_DEMO_H
#define __FREERTOS_DEMO_H

void freertos_start(void);

#endif

 main.c文件

添加头文件

#include "freertos_demo.h"

printf重定向

int fputc(int ch,FILE *f)
{
  HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,HAL_MAX_DELAY);
  return ch;
}

  /* 开启按键定时器TIM3 */
  HAL_TIM_Base_Start_IT(&htim3);
  /* 启动FreeRTOS */
  freertos_start();
  /* 注意:在进入freertos后面的代码,没机会执行 */

我写的hal库工程原本写好了串口封装和定时器按键封装(此处就不在写了)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值