FreeRTOS(六)----中断配置

      FreeRTOSConfig.h前部分是一些CPU、调度算法等配置,后部分是中断配置。在FreeRTOSConfig.h中,能够知道config前缀宏的映射内容,下面是部分的注释:

#define configUSE_PREEMPTION            1                               //0-协程调度,1-抢占式调度
#define configUSE_IDLE_HOOK             0                               //0-除能空闲任务的钩子函数,1-使能
#define configUSE_TICK_HOOK             0                               //0-除能时间片钩子函数,1-使能
#define configCPU_CLOCK_HZ              ( SystemCoreClock )             //设置CPU频率
#define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )         //设置滴答计时器的中断频率,为HZ/1000=1ms
#define configMAX_PRIORITIES            ( 5 )                           //任务优先级是0~(configMAX_PRIORITIES-1)
#define configMINIMAL_STACK_SIZE        ( ( unsigned short ) 130 )      //设置空闲任务的堆栈大小,单位是字(4字节)
#define configTOTAL_HEAP_SIZE           ( ( size_t ) ( 75 * 1024 ) )    //设置系统总堆栈大小
#define configMAX_TASK_NAME_LEN         ( 10 )                          //设置任务名最大长度
#define configUSE_TRACE_FACILITY        1                               //0-除能可视化跟踪调试,1-使能
#define configUSE_16_BIT_TICKS          0                               //节拍计时器变量范围,0-16位,1-32位
#define configIDLE_SHOULD_YIELD         1                               //0-空闲任务不会让出CPU给同等优先级的任务,1-会让出CPU
#define configUSE_MUTEXES               1                               //0-除能互斥信号量,1-使能
#define configQUEUE_REGISTRY_SIZE       8                               //0-除能内核调试中查看队列和信号量数量,>0-可以注册的数量
#define configCHECK_FOR_STACK_OVERFLOW  0                               //0-除能堆栈溢出检测,1-使能
#define configUSE_RECURSIVE_MUTEXES     1                               //0-除能递归互斥信号量,1-使能
#define configUSE_MALLOC_FAILED_HOOK    0                               //0-除能malloc失败时调用的钩子函数,1-使能
#define configUSE_APPLICATION_TASK_TAG  0                               //0-除能一些应用程序钩子函数,1-使能
#define configUSE_COUNTING_SEMAPHORES   1                               //0-除能计数信号量,1-使能
#define configGENERATE_RUN_TIME_STATS   0                               //0-除能时间统计功能,1-使能

……

//硬件相关的中断位数
#ifdef __NVIC_PRIO_BITS
    /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
    #define configPRIO_BITS             __NVIC_PRIO_BITS
#else
    #define configPRIO_BITS             4        /* 15 priority levels */           
#endif

//最低优先级,一般与configPRIO_BITS对应,2^configPRIO_BITS-1
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY         0xf                         

//可管理的最大优先级(设置STM的BASEPRI寄存器)
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    5                           

//真正的中断优先级,用于设置滴答中断等等的优先级
#define configKERNEL_INTERRUPT_PRIORITY         ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

//真正的中断优先级,最大可以使用FreeRTOS-API的中断优先级
#define configMAX_SYSCALL_INTERRUPT_PRIORITY    ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

     

前部分的内容是硬件能运行的基本配置,而后部分的中断配置是实时嵌入式系统的需求配置,中断配置内存如下:

中断优先级数量的寄存器位数:(STM32F4)4位,16个优先级

最低优先级:2^4-1=15

FreeRTOS可管理的最大优先级:设置为5,意味着优先级>=5的优先级不被FreeRTOS控制

 

为了测试 --> 可管理的最大优先级为5,也就优先级<5的中断不归FreeRTOS管理,逻辑图如下:

定时器使用通用定时器3和4,两者都是定时1s,定时器3的优先级是4,定时器5的优先级是5,前者可以被FreeRTOS管理,后者超过了FreeRTOS管理的优先级、

 

//timer.c

void TIM3_Int_Init(u16 arr,u16 psc)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  ///使能TIM3时钟
	
	TIM_TimeBaseInitStructure.TIM_Period = arr; 	//自动重装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  //定时器分频
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
	
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断
	TIM_Cmd(TIM3,ENABLE); //使能定时器3
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x04; //抢占优先级4
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x00; //子优先级0
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

void TIM5_Int_Init(u16 arr,u16 psc)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);	//使能TIM5时钟
	
	TIM_TimeBaseInitStructure.TIM_Period = arr; 		//自动重装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  		//定时器分频
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	
	TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);	//初始化TIM5
	
	TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE); 			//允许定时器5更新中断
	TIM_Cmd(TIM5,ENABLE); 								//使能定时器5
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn; 		//定时器5中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x05; 	//抢占优先级5
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x00; 		//子优先级0
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

//定时器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 TIM5_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET) //溢出中断
	{
		printf("TIM5输出.......\r\n");
	}
	TIM_ClearITPendingBit(TIM5,TIM_IT_Update);  //清除中断标志位
}
//main.c

TIM3_Int_Init(10000-1,8400-1);		//初始化定时器3,定时器周期1S
TIM5_Int_Init(10000-1,8400-1);		//初始化定时器5,定时器周期1S

//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    //创建中断测试任务
    xTaskCreate((TaskFunction_t )interrupt_task,  			//任务函数
                (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();				//关闭中断
			delay_xms(5000);						//延时5s
			printf("打开中断.............\r\n");	//打开中断
			portENABLE_INTERRUPTS();
		}
        LED0=~LED0;
        vTaskDelay(1000);
    }
}  

 

测试结果:

以上可知:

  1. 一开始没有关闭中断,所以TIM3和TIM5都正常运行,红框显示部分
  2. 当任务interrupt_task()运行了5次以后就关闭了中断,此时由于TIM5的中断优先级为5,等于configMAX_SYSCALL_INITERRUPT_PRIORITY,因此TIM5被关闭;但是TIM3的中断优先级高于configMAX_SYSCALL_INITERRUPT_PRIORITY,不会被关闭,所以TIM3正常运行,绿框显示部分
  3. 中断关闭5s后,调用函数portENABLE_INTERRUPTS()重新打开中断,且TIM5恢复运行,蓝框显示部分

 

Tist:

  • FreeRTOSConfig.h前部分是一些CPU、调度算法等配置,后部分是中断配置
  • FreeRTOSConfig.h的中断配置使得FreeRTOS系统可以理会和不理会某些中断
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值