FreeRTOS学习之路,以STM32F103C8T6为实验MCU(2-2:中断)

学习之路主要为FreeRTOS操作系统在STM32F103(STM32F103C8T6)上的运用,采用的是标准库编程的方式,使用的IDE为KEIL5。

注意!!!本学习之路可以通过购买STM32最小系统板以及部分配件的方式进行学习,也可以通过Proteus仿真的方式进行学习。

后续文章会同时发表在个人博客(jason1016.club)、CSDN;

视频会发布在bilibili(UID:399951374)

一、中断与FreeRTOS的关系

中断与FreeRTOS任务体系是共存的,通常我们把正常工作执行的工作放在任务,某个紧急工作触发或者需要单片机加急去做的工作放在中断。

操作系统和中断其实没有那么玄乎。中断就是中断,OS起到的作用只是管理中断运行不允许,起到一个调控作用。与任务无关,中断就是中断嘛。

二、FreeRTOS对中断的屏蔽(关闭)

在许多应用中,需要暂时屏蔽所有的中断一执行一些对时序要求严格的任务。

我们可以通过配置下列三个寄存器屏蔽中断

  1. PRIMASK 用于禁止除复位、 NMI 和 HardFalut 外的所有异常和中断
  2. FAULTMASK 比 PRIMASK 更狠,它可以连 HardFault 都屏蔽掉
  3. BASEPRI 寄存器相对柔和,只屏蔽优先级低于某一个阈值的中断(下面就引出我们中断保留的概念)

三、中断保留

但是我们有时候会觉得,一关就全关了,太傻了是不是,所以我们要对OS关闭的中断设置一个阈值,让它不会全部关掉,保留一些重要的中断是不是。

对于STM32而言,中断优先级一共16个。

FreeRTOS是建立在正常裸机系统上的,所以裸机自己的中断是全部保留的。

那我觉得有些裸机中断不允许被OS控制怎么办,所以我们设置了一个OS中断阈值优先级寄存器。

意思就是得保留部分裸机中断级别,让FreeRTOS不参与进这部分级别中断的的开发。所以我们设计一个中断宏的阈值,高于此中断阈值的中断优先级不能被FreeRTOS操控。

大家可以自由设置,这里我设置为了 5。也就是高于 5 的优先级(优先级数小于 5)不归 FreeRTOS 管理!

configMAX_SYSCALL_INTERRUPT_PRIORITY==5

四、开关中断

我们这里用配置BASEPRI 寄存器的方法控制中断的开关

关闭中断:vPortRaiseBASEPRI() 原理就是向BASEPRI寄存器写入上述configMAX_SYSCALL_INTERRUPT_PRIORITY的值,关闭阈值以下优先级的中断

开启中断:vPortSetBASEPRI(0)

portDISABLE_INTERRUPTS()    //关闭中断(关闭MAX阈值中断优先级之后的中断)
portENABLE_INTERRUPTS()     //开启中断

五、临界段保护

上面也讲到了OS可以对中断进行屏蔽,这是针对某些不能被中断打断的重要任务嘛。那我们统一将那些进行需要屏蔽中断来保护运行的代码称为临界段;那我们开启屏蔽就叫临界段保护。

临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段,比如有的外设的初始化需要严格的时序,初始化过程中不能被打断。

通常由两个函数组成,一个是临界段进入,一个是临界段退出

taskENTER_CRITICAL();  //临界段进入
taskEXIT_CRITICAL();   //临界段退出

代码:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"
#include "sys.h"
#include "interrupt.h"


#define START_TASK_PRIO 1 //任务优先级
#define START_STK_SIZE 256 //任务堆栈大小
TaskHandle_t StartTask_Handler; //任务句柄
void start_task(void *pvParameters); //任务函数
#define INTERRUPT_TASK_PRIO 2 //任务优先级
#define INTERRUPT_STK_SIZE 256 //任务堆栈大小
TaskHandle_t INTERRUPTTask_Handler; //任务句柄
void interrupt_task(void *p_arg); //任务函数


int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组 4
delay_init(); //延时函数初始化
uart_init(115200); //初始化串口
LED_Init(); //初始化 LED
TIM3_Int_Init(10000-1,7200-1); //初始化定时器 3,定时器周期 1S
TIM5_Int_Init(10000-1,7200-1); //初始化定时器 5,定时器周期 1S
//创建开始任务
 xTaskCreate((TaskFunction_t )start_task, //任务函数
 (const char* )"start_task", //任务名称
 (uint16_t )START_STK_SIZE, //任务堆栈大小
 (void* )NULL, //传递给任务函数的参数
 (UBaseType_t )START_TASK_PRIO, //任务优先级
 (TaskHandle_t* )&StartTask_Handler); //任务句柄 
 vTaskStartScheduler(); //开启任务调度
}

//开始任务任务函数
void start_task(void *pvParameters)
{
 taskENTER_CRITICAL(); //进入临界区
 //创建中断测试任务
 xTaskCreate((TaskFunction_t )interrupt_task, //任务函数 (1)
 (const char* )"interrupt_task", //任务名称
 (uint16_t )INTERRUPT_STK_SIZE, //任务堆栈大小
 (void* )NULL, //传递给任务函数的参数
 (UBaseType_t )INTERRUPT_TASK_PRIO, //任务优先级
 (TaskHandle_t* )&INTERRUPTTask_Handler); //任务句柄
vTaskDelete(StartTask_Handler); //删除开始任务
 taskEXIT_CRITICAL(); //退出临界区
}

//中断测试任务函数
void interrupt_task(void *pvParameters)
{
static u32 total_num=0;
 while(1)
 {
total_num+=1;
if(total_num==5) 
{
printf("关闭中断.............\r\n");
portDISABLE_INTERRUPTS(); //关闭中断 (3)
delay_xms(5000); //延时 5s (4)
printf("打开中断.............\r\n"); //打开中断
portENABLE_INTERRUPTS();
}
 LED0=~LED0;
 vTaskDelay(1000);
 }
}



//定时器 3 中断服务函数
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
{
printf("TIM3 输出.......\r\n");
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
}
//定时器 5 中断服务函数
void TIM4_IRQHandler(void)
{
if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET) //溢出中断
{
printf("TIM4 输出.......\r\n");
}
TIM_ClearITPendingBit(TIM4,TIM_IT_Update); //清除中断标志位
}

本文为作者独立编写,本BLOG上所有的原创文章未经本人许可,不得用于商业用途及传统媒体。网络媒体转载请注明出处,否则属于侵权行为。  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JASON丶LI

作者码力不足了,卑微的求个打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值