一、实验
实验目的:学会使用FreeRTOS的中断管理
创建两个定时器,一个优先级为4,另一个优先级为6;注意:系统所管理的优先级范围 :5~15
现象:两个定时器每1s,打印一段字符串,当关中断时,停止打印,开中断时持续打印。
实验设计:创建两个任务:start_task、task1
2个任务的功能如下:
start_task:用于创建task1任务
task1:中断测试任务,任务中将调到用关中断和开中断函数来体现对中断的管理。
代码:
main.c
#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h"
#include "freertos_demo.h"
#include "Delay.h"
#include "sys.h"
#include "usart.h"
#include "Timer.h"
#include "delay.h"
int main(void)
{
uart_init(9600);
Timer_Init();
delay_init();
// 创建任务
FrrrRTOS_Demo();
}
freertos_demo.c
#include "FreeRTOS.h"
#include "task.h"
#include "usart.h"
#include "Timer.h"
#include "delay.h"
/******************************************************************任务配置****************************************************/
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_TASK_STACK_SIZE 64
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define TASK1_PRIO 2
//任务堆栈大小
#define TASK1_STACK_SIZE 64
//任务句柄
TaskHandle_t Task1_Handler;
//任务函数
void task1(void *pvParameters);
/******************************************************************任务函数****************************************************/
void FrrrRTOS_Demo(void)
{
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
( char* )"start_task", //任务名称
(uint16_t )START_TASK_STACK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
// 启动任务调度
vTaskStartScheduler();
}
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建LED0任务
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STACK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
// 任务1函数
void task1(void *pvParameters)
{
uint8_t task1_num = 0;
while(1)
{
if(++task1_num == 5)
{
task1_num = 0;
printf("关中断\r\n");
portDISABLE_INTERRUPTS();
delay_xms(5000); //不可以使用vTaskDelay()函数:因为此函数会在内部开启中断引起任务切换
printf("开中断\r\n");
portENABLE_INTERRUPTS();
}
vTaskDelay(1000);
}
}
Timer.c
#include "stm32f10x.h" // Device header
#include "usart.h"
void Timer_Init(void)
{
//RCC打开时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
//选择时基单元的时钟,内部时钟一般默认初始化可以写可以不写
TIM_InternalClockConfig(TIM2);
TIM_InternalClockConfig(TIM3);
//配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
//TIM_CKD_DIV1代表1分屏
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
//代表向上计数
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
//72MHZ分频7200,就是10k,10k计10000个数就是1s
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
//高级定时器才有,现在是通用定时器给0
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
//如果不加入这一句,会导致复位之后从1开始计数
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
//TIM_IT_Update代表更新中断,中断控制,用来控制某个中断能不能通往NIVC
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 15; //新版RTOS可管理的NVIC中断:11~15
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
//启动定时器
TIM_Cmd(TIM2, ENABLE);
TIM_Cmd(TIM3, ENABLE);
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
printf("优先级4\r\n");
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)
{
printf("优先级15\r\n");
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
}
二、实验现象
三、重点
开中断和关中断函数:
portDISABLE_INTERRUPTS(); //关中断
portENABLE_INTERRUPTS(); //开中断
关中断之后不能使用vTaskDelay()函数,此函数中会打开中断。(Delay函数不能使用的可以找找我的文章,有专门修改后适用于FreeRTOS操作系统的延迟函数)
FreeRTOS可管理的中断优先级,版本不一样,可管理的优先级就不一样;
是由FreeRTOSConfig.h文件里面的宏决定:
#define configKERNEL_INTERRUPT_PRIORITY 255 // 内核中断优先级(最低优先级)
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191// 允许调用 FreeRTOS API 的最高中断优先级(优先级 11)
//可管理的中断优先级:11 到 15
适用于STM32F103C8T6项目带注释完整的FreeRTOSConfig.h文件:
/*
* FreeRTOS V202212.01
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
// 如果需要支持操作系统,可以取消注释以下宏定义
//#define SYSTEM_SUPPORT_OS 1
/*-----------------------------------------------------------
* 应用程序特定的定义。
*
* 这些定义应根据您的硬件和应用程序需求进行调整。
*
* 这些参数在 FreeRTOS API 文档的“配置”部分中有详细描述,
* 文档可在 FreeRTOS.org 网站上找到。
*
* 参见 http://www.freertos.org/a00110.html
*----------------------------------------------------------*/
// 将 FreeRTOS 的中断处理函数映射到 CMSIS 标准的中断处理函数
#define xPortPendSVHandler PendSV_Handler // PendSV 中断处理函数
//#define xPortSysTickHandler SysTick_Handler // SysTick 中断处理函数(注释掉,使用自定义的 SysTick_Handler)
#define vPortSVCHandler SVC_Handler // SVC 中断处理函数
// 启用获取当前任务句柄的 API
#define INCLUDE_xTaskGetCurrentTaskHandle 1
/*-------------------------------- FreeRTOS 内核配置 --------------------------------*/
#define configUSE_PREEMPTION 1 // 启用抢占式调度
#define configUSE_IDLE_HOOK 0 // 禁用空闲任务钩子函数
#define configUSE_TICK_HOOK 0 // 禁用时钟节拍钩子函数
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 ) // CPU 时钟频率,72MHz
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) // 系统节拍频率,1000Hz(1ms 一个节拍)
#define configMAX_PRIORITIES ( 5 ) // 最大任务优先级数
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 ) // 空闲任务的最小堆栈大小
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) ) // 系统堆的总大小,17KB
#define configMAX_TASK_NAME_LEN ( 16 ) // 任务名称的最大长度
#define configUSE_TRACE_FACILITY 0 // 禁用可视化跟踪调试功能
#define configUSE_16_BIT_TICKS 0 // 使用 32 位 Tick 计数器
#define configIDLE_SHOULD_YIELD 1 // 空闲任务在有同等优先级的用户任务时主动让出 CPU
/*-------------------------------- FreeRTOS API 包含配置 --------------------------------*/
// 以下宏定义用于控制是否包含特定的 FreeRTOS API 函数
#define INCLUDE_vTaskPrioritySet 1 // 包含任务优先级设置函数
#define INCLUDE_uxTaskPriorityGet 1 // 包含获取任务优先级函数
#define INCLUDE_vTaskDelete 1 // 包含任务删除函数
#define INCLUDE_vTaskCleanUpResources 0 // 不包含任务资源清理函数
#define INCLUDE_vTaskSuspend 1 // 包含任务挂起函数
#define INCLUDE_vTaskDelayUntil 1 // 包含绝对延时函数
#define INCLUDE_vTaskDelay 1 // 包含相对延时函数
#define INCLUDE_vTaskResumeFromISR 1 // 包含从中断恢复任务函数
#define INCLUDE_xTaskGetSchedulerState 1 // 包含获取调度器状态函数
/*-------------------------------- 中断优先级配置 --------------------------------*/
/*-------------------------------- 可管理的中断优先级:11 到 15(对应 NVIC 优先级 191 到 255) --------------------------------*/
// Cortex-M3/M4 的 NVIC 中断优先级配置
#define configKERNEL_INTERRUPT_PRIORITY 255 // 内核中断优先级(最低优先级)
// configMAX_SYSCALL_INTERRUPT_PRIORITY 不能设置为 0
// 参见 http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 // 允许调用 FreeRTOS API 的最高中断优先级(优先级 11)
// STM32 库使用的中断优先级范围是 0-15,15 对应最低优先级 255
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15 // 内核中断优先级(最低优先级)
#endif /* FREERTOS_CONFIG_H */