FreeRTOS在TM4C单片机上的移植: TM4C中断系统介绍与FreeRTOS中断管理

上一篇文章我们讨论了FreeRTOS任务相关的内容, 接下来让我们探索一下TM4C的中断系统及FreeRTOS的中断管理.

中断在TM4C中的实现

在FreeRTOS中, 实时性和中断的处理都十分重要. 为了保证系统的实时性, 如某些外设初始化时不被打断, FreeRTOS提供了一系列函数来满足中断管理的要求.
由于TM4C单片机为Cortex-M内核, 故其中断的实现方式与STM32单片机十分相似, 故具体原理不详细讲解.
在这里插入图片描述

根据官方的芯片数据手册, Tiva C/E系列单片机设计只实现了三位优先级, 故根据这种设置, 可能的优先级为高0x00, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0低共八位.
在官方库中, 可通过 IntPriorityGroupingSet(uint32_t ui32Bits) 函数实现优先级分组的更改. 如, ui32Bits值为2时, 系统具有四位抢占优先级, 两位子优先级. 具体如下表所示:
在这里插入图片描述
若要在TM4C单片机中实现中断功能, 需有一下几步设置(以PF4按键中断为例):

  • #define USER_INT0 0x00
    #define USER_INT1 0x20
    #define USER_INT2 0x40
    #define USER_INT3 0x60
    #define USER_INT4 0x80
    #define USER_INT5 0xA0
    //中断优先级定义
  • IntPriorityGroupingSet(3);
    //设置中断优先级分组
  • IntMasterEnable();
    //向处理器请求开启总中断开关
  • IntPrioritySet(INT_GPIOF_TM4C123, USER_INT5);
    //设置GPIO F口中断优先级为5(无法按位设置中断优先级)
  • GPIOIntRegister(GPIO_PORTF_BASE, KEYIRQHandler);
    //注册GPIO中断函数
  • GPIOIntEnable(GPIO_PORTF_BASE, GPIO_PIN_4);
    //使能PF4中断
  • IntEnable(INT_GPIOF);
    //开启GPIO F口中断

注意: 对于设置中断优先级分组 IntPriorityGroupingSet() 函数, 传参值仅1, 2, 3有效, 对于高于3的值, 系统会默认处理为3, 及8位抢占优先级.

FreeRTOS的中断管理

FreeRTOS对于中断没有特别的处理程序, 但提供一些特性和系统API函数方便用户可以简单地实现和维护中断管理.
需要注意的是, 任意一个最低优先级的中断都比最高优先级的任务权限更高, 故在FreeRTOS中, 我们对于不能被打断的代码有临界段保护的功能. 对于临界段保护, FreeRTOS有一下几个相关函数

    #define portDISABLE_INTERRUPTS()                  vPortRaiseBASEPRI()
    #define portENABLE_INTERRUPTS()                   vPortSetBASEPRI( 0 )
    #define portENTER_CRITICAL()                      vPortEnterCritical()
    #define portEXIT_CRITICAL()                       vPortExitCritical()
    #define portSET_INTERRUPT_MASK_FROM_ISR()         ulPortRaiseBASEPRI()
    #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vPortSetBASEPRI( x )

这几个函数的具体操作就是改变BASEPRI的值, 来实现中断的开关, 从而实现临界段的保护, 通常情况下, 用 portENTER_CRITICAL() 和 portEXIT_CRITICAL() 两个函数框住想要保护的代码即可实现有关功能.
然而, FreeRTOS并不能通过这些函数暂停一切中断. 我们可以设置configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY参数来免于某些中断被FreeRTOS打断. 当中断优先级高于此参数时(即数值上低于此值), 该中断便是免于FreeRTOS管理的.
当然, FreeRTOS中中断管理远不止这些, 大家可以看这篇文章FreeRTOS 从入门到精通9–探讨中断管理来深入了解.

实验探索

我们下面通过一个简单的实验来探索FreeRTOS的中断特性.

中断函数

void KEYIRQHandler(void)
{
    uint32_t s=GPIOIntStatus(GPIO_PORTF_BASE, true);
	if((s&GPIO_PIN_4)==GPIO_PIN_4)
	{
		if(TactKey2FLAG==true)
		{
			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);
			TactKey2FLAG=false;
		}	
		else
		{
			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0);
			TactKey2FLAG=true;
			portDISABLE_INTERRUPTS(); 
		}
	}
	GPIOIntClear(GPIO_PORTF_BASE, GPIO_INT_PIN_4);	
}

恢复任务

void task3_task(void *pvParameters)
{
	bool print_flag1 = 0, print_flag2 = 0;
	while (1)
	{
		if (TactKey2 == 0 && print_flag2 == 0)
		{
			print_flag1 = 0;
			printf("resuming interrupt\n\n");
			print_flag2 = 1;
			portENABLE_INTERRUPTS();
		}
	}
}

当我们按下按键SW1(PF4)时, 系统将会进入该中断函数. 当我们按第一次时, 会发现板载LED灯亮. 按第二次时, LED灯熄灭, 同时被portDISABLE_INTERRUPTS()函数关闭中断. 在此之后, 再按下按键, 我们会发现LED不会再次翻转, 说明FreeRTOS的中断管理体系已经将该中断屏蔽.

当我们通过恢复任务(按下SW2)调用portENABLE_INTERRUPTS()函数后, 按下SW1, LED灯会再次亮起.

当我们改变configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY值至更高优先级后, 重新编译烧录程序, 我们会发现持续按下SW1小灯会持续翻转状态, 说明中断并未被FreeRTOS屏蔽.

工程文件

TM4C中断系统介绍与FreeRTOS中断管理

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值