EFM32jg之FreeRTOS(3)-中断、任务相关

本文详细介绍了在EFM32JG微控制器上移植FreeRTOS时的中断管理和任务创建。内容涵盖了NVIC中断配置、临界区保护、任务创建的动态与静态方式、任务挂起与恢复的操作,以及任务控制块和堆栈管理。强调了在中断管理中正确设置优先级和使用临界区保护的重要性,同时提供了静态任务创建的步骤和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@EFM32JG移植FreeRTOS

1、中断管理

Cotex-M3 和 M4 的 NVIC 最多支持 240 个 IRQ(中断请求)、 1 个不可屏蔽中断(NMI)、 1 个Systick(滴答定时器)定时器中断和多个系统异常。

1)由于EFM32JG1B200F128GM48有三位来表达优先级,如下,所以优先级组最多分为四组
在这里插入图片描述
2)三个极其重要的寄存器

  • PRIMASK
    用于禁止除 NMI 和 HardFalut 外的所有异常和中断,汇编编程的时候可以使用 CPS(修改处理器状态)指令修改 PRIMASK 寄存器的数值

CPSIE I; //清除 PRIMASK(使能中断)
CPSID I; //设置 PRIMASK(禁止中断)

  • FAULTMASK
    可以连 HardFault 都屏蔽掉,使用方法和 PRIMASK 类似, FAULTMASK 会在退出时自动清零

CPSIE F ;清除 FAULTMASK
CPSID F ;设置 FAULTMASK

  • BASEPRI
    可以关闭低于某个阈值的中断,高于这个阈值的中断就不会被关闭

MOV R0, #0X60
MSR BASEPRI, R0

3)开关中断—管理比优先级configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY低的中断
函数如下:作用为向BASEPRI写入值,实现开启关闭中断

#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)

4)临界段代码保护–保护必须完整运行,不能被打断的代码;临界区代码一定要精简!

  • 任务级

#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()

  • 中断级

#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)

4)若要使用使用临界区保护,在中断管理时,尽量不要给中断优先级分组,否则当 BASEPRI设置的任务管理优先级过高,可能导致退出临界区也不再进入中断。

不可用:NVIC_SetPriorityGrouping(5);

2、任务创建

1)如果是动态创建,那么在此任务被删除以后此任务之前申请的堆栈和控制块内存会在空闲任务中被释放掉,因此当调用函数 vTaskDelete()删除任务以后必须给空闲任务一定的运行时间。
2)只有那些由内核分配给任务的内存才会在任务被删除以后自动的释放掉,用户分配给任务的内存需要用户自行释放掉
3)创建任务需要在临界区中,创建完退出临界区。

静态创建任务

之前创建任务时宏定义为打开configSUPPORT_STATIC_ALLOCATION
这就表示虽然动态创建的任务,但是对于空闲任务和软时钟任务是静态创建的,所有才出现了错误,对EFM32jg之FreeRTOS(2)中提前创建了空闲任务和软时钟任务的分配。
在这里插入图片描述
所以静态创建第一步
1、改宏使能静态创建方法,编写空闲和软时钟任务
在这里插入图片描述
2、编写测试代码
注:以下宏定义必须为全局变量,否则运行不成功
TaskHandle_t StartTask_Handler; //创建成功返回句柄
StackType_t StartTaskStack[START_STK_SIZE]; //任务堆栈
StaticTask_t StartTaskTCB; //任务控制块

  StartTask_Handler = xTaskCreateStatic(	(TaskFunction_t	) 	start_task,         ///任务函数
  										(const char *	) 	"start_task",		///任务名称
										(uint32_t 		)	START_STK_SIZE,     ///任务堆栈大小
										(void *			) 	NULL,	            ///传递给任务函数的参数
										(UBaseType_t	) 	START_TASK_PRIO,    ///任务优先级
										(StackType_t *	)	StartTaskStack,     ///任务堆栈
										(StaticTask_t * ) 	&StartTaskTCB );

3、任务挂起和恢复

1、挂起和删除的本质区别是保存堆栈和变量.。
2、若使用函数 vTaskDelay()可使任务进入阻塞态,知道延时周期完成。任务在等待队列、信号量、事件组、通知或互斥信号量的时候也会进入阻塞态。当进行任务切换时,可以使用 vTaskDelay()进行。
3、优先级数字越低表示任务的优先级越低, 0 的优先级最低, configMAX_PRIORITIES-1 的优先级最高。空闲任务的优先级最低,为 0。任务切换时,会将优先级任务最高的就绪态任务运行。

4、任务控制块

FreeRTOS 的每个任务都有一些属性需要存储, FreeRTOS 把这些属性集合到一起用一个结构体来表示, 这个结构体叫做任务控制块: TCB_t,在使用函数 xTaskCreate()创建任务的时候就会自动的给每个任务分配一个任务控制块。

任务控制块又叫任务句柄,包含创建任务的所有状态,说成任务的身份证最为合适,想删除,直接删除身份证就可以了。

5、任务堆栈

FreeRTOS 之所以能正确的恢复一个任务的运行就是因为有任务堆栈在保驾护航,任务调度器在进行任务切换的时候会将当前任务的现场(CPU寄存器值等)保存在此任务的任务堆栈中,等到此任务下次运行的时候就会先用堆栈中保存的值来恢复现场,恢复现场以后任务就会接着从上次中断的地方开始运行。

其中需要注意的点是:任务的实际堆栈大小我们所定义的 4 倍,因为它是uint32_t的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值