立志最细,FreeRtos中 中断、 调度器、的屏蔽/恢复,详解!!!

#1024程序员节征文|征文#

     

                                           前言:本文参考,韦东山开发文档,连接最后

任务调度器

        任务调度器(scheduler),在FreeRtos操作系统中,主要负责多任务之间的切换,确保系统按照优先级和多任务的并发的方式去运行,任务的切换调用是任务调度器(scheduler)去负责的。

       但是这里需要注意的是, 任务调度器(scheduler),进行切换任务的基础是在,mcu的tick中断上面的如果中断停止了,也就是被屏蔽了,任务调度器(scheduler)也是没有办法进行切换任务的。

tick中断

        FreeRtos的任务调度器(scheduler)依赖的是 tick中断 来实现任务切换,如果系统停止了 tick中断,任务调度器将没有办法切换任务,这个时候调度器不会在收到定时的中断信号来检测是否需要切换任务

        FreeRtos使用的一个周期性的时钟中断,称为tick中断,这个中断通常1ms一次,在每个tick中断的时候,FreeRtos会检测当前任务的状态,决定是否要切换到另一个任务(判断优先级,任务转态)

中断、 调度器、的屏蔽/恢复

        在FreeRtos操作系统中,如有想要访问临界资源这个时候实现任务之间的互斥,除了使用互斥信号量还可以使用,中断的屏蔽在访问临界资源完成之后,这里只需要去恢复任务就可以了,操作系统是依靠单片机的硬件中断,来完成任务的切换,当中断屏蔽之后也就不能切换任务了。

        或者在FreeRtos操作系统的工程中,当某段时间只想要一个任务单独执行,不想多任务同时并发的执行,这个时候可以把任务调度器给屏蔽掉,这个时候就不能切换任务。

屏蔽/恢复函数原型

        中断/调度器的函数,是没有参数的,使用的时候直接调度就行,想要结束效果调用推出函数,函数原型如下。

/*函数在普通任务上下文使用*/
//进入调度器屏蔽中断
taskENTER_CRITICAL();
//结束调度器屏蔽中断
taskEXIT_CRITICAL();

/*函数在中断任务上下文使用*/
//进入调度器屏蔽中断
taskENTER_CRITICAL_FROM_ISR();
//结束调度器屏蔽中断
taskEXIT_CRITICAL_FROM_ISR();

屏蔽/恢复实际调用

static void DHT11Timer_Func( TimerHandle_t xTimer )
{
	int hum, temp;
	int err;
	char buff[16];
	
	/* 读取DHT11的温湿度 */
	/* 暂停调度器 */
	vTaskSuspendAll();//这里在读iic的时候不能被干扰
	err = DHT11_Read(&hum, &temp);//读出数据完成后
	/* 恢复调度器 */
	xTaskResumeAll();//这个时候才允许调度器调度任务

	if (0 == err)
	{
		/* 在OLED上显示出来 */
		sprintf(buff, "%dC,%d%%", temp, hum);
		draw_string(buff, false, 40, 0);
	}
	else
	{
		/* 在OLED上显示出来 */
		draw_string("err      ", false, 40, 0);		
	}
}
void game1_task(void *params)
{		    
	g_framebuffer = LCD_GetFrameBuffer(&g_xres, &g_yres, &g_bpp);
	draw_init();
	draw_end();
	
	buzzer_init();

	DHT11_Init();
	/* 创建定时器 */
	g_TimerDHT11 = xTimerCreate( "dht11_timer", 2000,pdTRUE,NULL,DHT11Timer_Func);
	//启动定时器
	osTimerStart(g_TimerDHT11,portMAX_DELAY);
	
	/* 创建队列,队列集,创建输入任务InputTask */
	g_xQueuePlatform = xQueueCreate(10, sizeof(struct input_data));
	g_xQueueSetInput = xQueueCreateSet(IR_QUEUE_LEN + ROTARY_QUEUE_LEN + MPU6050_QUEUE_LEN);
	
	g_xQueueIR = GetQueueIR();
	g_xQueueRotary = GetQueueRotary();
	g_xQueueMPU6050 = GetQueueMPU6050();
	
	xQueueAddToSet(g_xQueueIR, g_xQueueSetInput);
	xQueueAddToSet(g_xQueueRotary, g_xQueueSetInput);
	xQueueAddToSet(g_xQueueMPU6050, g_xQueueSetInput);
	
    xTaskCreate(MPU6050_Task, "MPU6050Task", 128, NULL, osPriorityNormal, NULL);
    xTaskCreate(InputTask, "InputTask", 128, NULL, osPriorityNormal, NULL);
    
	uptMove = UPT_MOVE_NONE;

	ball.x = g_xres / 2;
	ball.y = g_yres - 10;
        
	ball.velX = -0.5;
	ball.velY = -0.6;
//	ball.velX = -1;
//	ball.velY = -1.1;

	blocks = pvPortMalloc(BLOCK_COUNT);
	memset(blocks, 0, BLOCK_COUNT);
	
	lives = lives_origin = 3;
	score = 0;
	platformX = (g_xres / 2) - (PLATFORM_WIDTH / 2);

    xTaskCreate(platform_task, "platform_task", 128, NULL, osPriorityNormal, NULL);

    while (1)
    {
        game1_draw();
        //draw_end();
        vTaskDelay(50);
    }
}

                                                   欢迎指正,希望对你,有所帮助!!!

猜你喜欢

转载自blog.csdn.net/weixin_62292999/article/details/143140380