FreeRTOS学习笔记-基于stm32(3)中断管理

一、什么是中断

        通俗点讲就是让CPU停止当前在做的事,转而去做更紧急的事。

二、中断优先级分组

        这个紧急的事也有一个等级之分,优先级越高越先执行。stm32使用中断优先配置寄存器的高4位,共16级的中断优先等级。

        stm32的中断优先等级可以分为抢占优先级和子优先级。抢占优先级高的中断可以打断正在执行的抢占优先级低的中断;当抢占优先级相同时,子优先级高的优先执行。

eg:抢占优先级2,子优先级1的中断可以打断抢占优先级3,子优先级0的中断;但抢占优先级2,子优先级1的中断不能打断抢占优先级2,子优先级2的中断;虽然前者子优先级高于后者,但子优先级不能打断其他中断

三、特征

        1、低于configMAX_SYSCALL_INTERRUPT_PRIORITY(一般默认设置为5)优先级的中断才允许调用FreeRTOS的API函数(带有“FromISR后缀的函数”);

        2、将所有优先级位指定为抢占优先级位,方便管理;

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 

        3、中断优先级越小越优先,任务优先级越大越优先;

四、FreeRTOS中断相关寄存器

        FreeRTOS 中,通过 SHPR3 寄存器,将 PendSV 和 Systick 中断优先级被设置为最低,因为要保证系统任务的切换不会阻塞系统其他中断的响应

1、FreeRTOS关闭中断:

        FreeRTOS 中,通过 BASEPRI 寄存器,屏蔽优先级低于某一阈值的中断。

eg:BASEPRI 寄存器设置为0x50,表示中断优先级在5~15内的均被屏蔽,0~4的正常执行。(因为中断寄存器使用的是8位寄存器的高4位)也就是关闭FreeRTOS的中断  。

portDISABLE_INTERRUPTS();       //关闭中断

         经过此函数的一层层回调,会发现最终此函数还是对寄存器 basepri 写入0x50来关闭中断;

#define portDISABLE_INTERRUPTS()				vPortRaiseBASEPRI()

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			15                      //中断最低优先级
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	5                       //系统可管理的最高中断优先级
#define configKERNEL_INTERRUPT_PRIORITY 		( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) 
//此处对5进行左移4位,正是因为控制中断的寄存器高4位有效

static portFORCE_INLINE void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;

	__asm
	{
		/* Set BASEPRI to the max syscall priority to effect a critical
		section. */
		msr basepri, ulNewBASEPRI //将0x50写入寄存器basepri
		dsb
		isb
	}
}

2、FreeRTOS开启中断:

        将 BASEPRI 寄存器值设置为0时,则不关闭任何中断。

portENABLE_INTERRUPTS();        //开启中断

        此处就比较简单了,与关闭中断函数类似,直接对中断寄存器 basepri 写0。

#define portENABLE_INTERRUPTS()					vPortSetBASEPRI( 0 )

static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
{
	__asm
	{
		/* Barrier instructions are not used as this function is only used to
		lower the BASEPRI value. */
		msr basepri, ulBASEPRI
	}
}

 五、中断管理例程

        创建函数与上一章说的类似,此处只展示 task1 代码:

注意:此处延时函数使用的是 delay_xms(); 而不是delay_ms(); 或 vTaskDelay(); 因为FreeRTOS提供的 vTaskDelay() 内部会调用到 vPortSetBASEPRI( 0 ) ,就是上面开启中断所调用的内部函数。也就是说 vTaskDelay() 会调用到开中断函数,而 delay_ms() 内部则是调用的 vTaskDelay() 函数所以如果调用 vTaskDelay() 函数会提前开启中断,从而得不到正确的实验现象。

void task1( void * pvParameters )
{
    uint8_t task1_num=0;
    while(1)
    {
        if(++task1_num==5)
        {
            printf("关中断!!!\r\n");
            portDISABLE_INTERRUPTS();       //关闭中断
            delay_xms(5000);
            printf("开中断!!!!!!\r\n");
            portENABLE_INTERRUPTS();        //开启中断
        }
        vTaskDelay(1000);
    }
}

        定时器部分,为了验证FreeRTOS的中断管理函数仅对5~15的优先级有效,所以 TIM3 的优先级为4,TIM5 的优先级为6;

void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
	
	//定时器TIM3初始化
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;  //先占优先级4级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIMx					 
}

//通用定时器5中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器5!
void TIM5_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //时钟使能
	
	//定时器TIM3初始化
	TIM_TimeBaseStructure.TIM_Period = arr; 					//设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; 					//设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 	//设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
	TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); 			//根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE ); 					//使能指定的TIM5中断,允许更新中断

	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;  			//TIM5中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6;  	//先占优先级6级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  		//从优先级0级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 			//IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  							//初始化NVIC寄存器

	TIM_Cmd(TIM5, ENABLE);  									//使能TIM5					 
}

        中断服务函数

//定时器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);  //清除中断标志位
}

        由于FreeRTOS的中断管理函数仅对5~15的优先级有效,所以关闭中断后,TIM3会正常工作。

        实验现象:

        至于关中断时候输出的乱码,我个人觉得可能是抢占同一个串口导致的。

                                 

  • 22
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: FreeRTOS是一个开源的实时操作系统内核,为嵌入式设备提供了实时多任务处理、优先级管理和多线程等功能,非常适合一些资源有限的嵌入式设备进行开发。CANopen则是一种通信协议,可以用于各种嵌入式系统中的控制和数据传输,通常用于工业控制和自动化领域。 STM32F407则是意法半导体生产的一款Cortex-M4内核的微控制器,具有高性能、低功耗、高集成度等特点,非常适合应用于需要高要求的嵌入式设备中。而将这三者结合起来,可以实现很多嵌入式应用的功能,提高设备 控制的精度和可靠性。 具体而言,使用FreeRTOS可以使得STM32F407实现多任务处理,并在任务之间进行调度管理,提高系统的运行效率。CANopen则可以方便地实现各种设备之间的通信,实现控制指令和数据传输功能。在整个开发过程中,通过FreeRTOS和CANopen的结合,可以快速开发出高效、可靠的嵌入式系统。 ### 回答2: FreeRTOS是一个免费的实时操作系统内核,可用于大量基于嵌入式系统的微控制器的开发。CanOpen是针对CAN总线的一个通信协议,它能够实现不同的设备之间的通讯。而STM32F407是由ST推出的基于ARM Cortex-M4微控制器的产品系列之一。 在使用STM32F407进行嵌入式系统的开发时,FreeRTOS和CanOpen是非常有用的工具。FreeRTOS可以提供实时多任务支持,从而可以在单个系统中运行多个任务,并减少系统的复杂性。而CanOpen可实现在CAN总线上的设备之间的通信,从而实现大规模设备的控制和监控。 在使用这些工具时,需要注意一些配置和设置,以确保系统和设备的正常运行。例如,需要在STM32F407上启用CAN总线功能和FreeRTOS支持,这需要了解其软件开发工具,如Keil和IAR等。同时,在设备之间设置正确的CanOpen节点ID,使其互相识别并进行通信。 总之,对于使用STM32F407进行嵌入式系统开发的人员来说,FreeRTOS和CanOpen是非常有用的工具。它们可以帮助优化系统性能,提高设备之间的互操作性,从而实现更好的系统控制和管理

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值