FreeRTOS-任务通知详解

这篇具有很好参考价值的文章主要介绍了FreeRTOS-任务通知详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

✅作者简介:嵌入式入坑者,与大家一起加油,希望文章能够帮助各位!!!!
📃个人主页:@rivencode的个人主页
🔥系列专栏:玩转FreeRTOS
💬保持学习、保持热爱、认真分享、一起进步!!!

前言

FreeRTOS越学越简单,前面已经把真实的队列、信号量、事件组全部学完,现在学个任务通知去模拟这些东西,真的都学会了,模拟的还不会嘛,所以我们的本文的重点主要有两点:1.搞明白任务通知的三个状态(实现任务通知的关键),2.明白任务通知的优缺点,以及任务通知模拟出来的队列、信号量、事件组与真实的有何区别。

一、任务通知的简介

说是任务通知,倒不如说通知任务,所谓任务通知核心就是一个32位的无符号整数和一个8位的通知状态,而这两玩意就在任务控制块中,则所谓通知任务就是一个任务或者中断改写另外一个任务中的32位的无符号整数,只不过改写这个整数的方式可以有所不同(1.可以让这个整数加1: 模拟信号量 2. 设置该整数的指定的某些位:模拟事件组 3.直接选择覆盖或者不覆盖写入: 模拟消息队列)。

  • 1.任务的通知状态:任务通知有三种状态

未等待通知状态:就是任务的初始状态

等待通知状态:当任务在没有通知的时候接收通知时(也就是任务没有接收到通知的时候调用了接收通知的函数,则此时必定接收不到通知,把该任务标记为等待通知状态(去等别的任务发给我通知),任务进入阻塞态),这样做的用处是什么呢? 答:当另外一个任务发通知给该任务时,此时发现任务处于等待通知的状态,然后就可以即可把该任务唤醒。

等待接收通知状态:当有其他任务向任务发送通知,但任务还未接收这一通知的这段期间内(当其他任务给该任务发了通知,但是该任务还没有接收,则将该任务标记为等待接收通知状态),这样做的用处就是当该任务调用了接收通知的函数,发现自身的状态为等待接收通知状态,则不用进入阻塞,直接接收通知值。

为什么要搞一个这样的通知状态?
答:
1.为了判断任务是否接收到了通知
2.不需要一个链表来挂载因等不到通知而阻塞任务,可以直接将任务挂入阻塞链表,因为当调用发送通知函数去唤醒该任务时只需要判断它是否处于等待通知状态(因等待通知进入阻塞)。
像队列它有一个当前消息个数的变量可以知道队列中是否有消息,像信号量0就是没消息

那为什么任务通知不能以通知值是否为0判断是否有消息呢?
确实模拟信号量确实是怎么做的,但是如果是模拟队列的话,就不能怎么搞了,因为我发送一个0,0也算是数据,所以需要一个

如果现在还搞不懂这三个状态什么意思,没关系看后面的源码就懂了。

  • 2.任务通知的优缺点:

(1).任务通知的优点
按照FreeRTOS官方的说法使用任务通知比通过队列、事件标志组或信号量通信方式解除阻塞的任务要快 45%,并且更加省 RAM 内存空间,因为像队列、信号量、事件组这些通信方式使用前必须先创建,拿队列来说如下图所示,申请内存的时候至少需要下图这么多变量,而任务通知是任务结构体中自带的一个32位的无符号整数,一个8位的通知状态变量,一共就5个字节。
FreeRTOS-任务通知详解
使用任务通知不需要创建,因为当创建任务的时候就已经默认创建了这两个变量,任务控制块中的两个变量如下图所示,当然这里是一个数组(为了方便以后扩展),但是数组的元素个数默认为1。
FreeRTOS-任务通知详解
(2).任务通知的缺点
虽然说任务通知可以模拟这么多通信方式,但是肯定有限制、有缺点,不然还要这些队列、信号量、事件组干嘛。
1.不能发送通知到中断
原因很简单,任务通知、任务通知,人家通知的是任务,是修改任务控制块中那个32位无符号整数的值,中断并没有任务控制块这一说,但为什么队列、信号量、事件组这些就可以呢,说到底人家创建了一个独立的队列、信号量、事件组结构体当然谁都可以访问里面的内容,但是可以在中断中发送通知给其他任务,这个是没毛病的。
2.不能发送通知给多个任务
任务通知只能指定发送给某一个任务而不能广播,而队列、信号量、事件组任何中断和任务都能访问,不过很少出现多个任务或中断接收同一个通讯对象的情况

3.发送通知的任务不能进入阻塞
只有等待通知的任务可以被阻塞,发送通知的任务,在任何情况下都不会因为发送失败而进入阻塞态,像队列:写队列当队列满的时候,可以进入阻塞态

4.通知值只有一个32位的无符号的整形
加粗样式不像队列,可以缓存多个任意类型的数据,而任务通知只有一个消息,而且只能作用一次(接收到通知值等待通知的任务才能被唤醒)

接下来就开始分析任务通知有关函数的源码,其中会穿插着讲解用任务通知模拟出来的队列、信号量、事件组与真实的有何区别。

二、任务通知源码分析

任务通知的创建就不用说了,任务被创建时则就便有了任务通知,而且FreeRTOS默认任务通知是开启的。

1.发送通知函数xTaskGenericNotify

FreeRTOS定义了三个发送通知的函数,其实他们都是宏定义最终调用的是xTaskGenericNotify(),只不过他们的传入的参数有所区别,这都是FreeRTOS的老套路了,所以我们先分析完xTaskGenericNotify()函数的实现,再谈谈这三个函数应用上有何区别。
FreeRTOS-任务通知详解
1.xTaskGenericNotify()函数原型:
FreeRTOS-任务通知详解

  • 函数参数:
    1.xTaskToNotify:传入接收任务通知的任务控制块
    2.uxIndexToNotify:任务的指定通知(任务通知相关数组下标,默认为0,使用数组第一个元素当做通知)
    FreeRTOS-任务通知详解
    3.ulValue:要写入的通知值
    4.eAction:通知的方式(模拟信号量,消息队列、事件组中方式),可取的值如下所示
    FreeRTOS-任务通知详解
    第一个取值:只起通知作用也是有用的,至少可以唤醒,因未等待到通知而阻塞的任务。

5.pulPreviousNotificationValue:用于获取发送通知前的通知值

  • 函数返回值
    pdPASS 任务通知发送成功
    pdFAIL 任务通知发送失败

2.TaskGenericNotify()源码分析:

#if ( configUSE_TASK_NOTIFICATIONS == 1 )

    BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
                                   UBaseType_t uxIndexToNotify,
                                   uint32_t ulValue,
                                   eNotifyAction eAction,
                                   uint32_t * pulPreviousNotificationValue )
    {
        TCB_t * pxTCB;
        BaseType_t xReturn = pdPASS;
        uint8_t ucOriginalNotifyState;

        configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
        configASSERT( xTaskToNotify );
        pxTCB = xTaskToNotify;

        taskENTER_CRITICAL();
        {
            /* 判断是否需要通知前的通知值 */
            if( pulPreviousNotificationValue != NULL )
            {
               /* 获取发送通知前的通知值 */
                *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
            } 
			/* 记录发送通知前的任务通知状态 */
            ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
            /* 将要接收的通知的任务的状态设置为等待接收通知状态 */
            pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;

            switch( eAction )
            {
               /* 模拟事件组:将通知值的某些位置一 */
                case eSetBits:
                    pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
                    break;
               /* 模拟计数型信号量:将通知值的某些位置一 */
                case eIncrement:
                    ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
                    break;
               /* 模拟队列:覆写通知值 */
                case eSetValueWithOverwrite:
                    pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
                    break;
				/* 模拟队列:(不覆盖)写通知值 */
                case eSetValueWithoutOverwrite:
                    /* 如果任务状态不处于等待接收状态,说明通知值已被读走,
                       可以写入*/
                    if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
                    {
                        pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
                    }
                    else
                    {
                        /* 通知值未被读走,不能覆写 */
                        xReturn = pdFAIL;
                    }

                    break;

                case eNoAction:

                    /* 只将任务标记为等待接收通知状态
                       并不修改通知值 */
                    break;

                default:

                    /* Should not get here if all enums are handled.
                     * Artificially force an assert by testing a value the
                     * compiler can't assume is const. */
                    configASSERT( xTickCount == ( TickType_t ) 0 );

                    break;
            }

            traceTASK_NOTIFY( uxIndexToNotify );

            /* 如果在此之前,任务因等待任务通知而被阻塞(该任务为等待通知状态),则现在解除阻塞 */
            if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
            {
                /* 将任务从所在任务状态列表(延时列表)中移除 */
                listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
				/* 将任务添加到就绪任务列表中 */
                prvAddTaskToReadyList( pxTCB );

                /* 该任务不应在事件列表中 */
                configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );

                #if ( configUSE_TICKLESS_IDLE != 0 )
                    {
                        /* 更新下一个解除阻塞的任务 */
                        prvResetNextTaskUnblockTime();
                    }
                #endif
				/* 有任务解除阻塞后,就应该判断是否需要进行任务切换 */
                if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
                {
					/* 悬起 PendSV中断,准备进行任务切换 */
                    taskYIELD_IF_USING_PREEMPTION();
                }
                else
                {
                    mtCOVERAGE_TEST_MARKER();
                }
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }
        }
        taskEXIT_CRITICAL();

        return xReturn;
    }

#endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/

FreeRTOS-任务通知详解
源码解析:
1.如果传入的pulPreviousNotificationValue不为NULL(就是一个32位变量的地址),则代表需要获取发送通知前的通知值。
FreeRTOS-任务通知详解
2.这里解释一下为什么要将任务的通知状态改为等待接收通知状态
首先要明白一点我们改的是要接收通知的任务通知的状态,则当调用接收通知函数时,判断一下任务的通知状态是不是等待接收通知状态如果是那说明有通知已经发送过来了。

FreeRTOS-任务通知详解
3.解释一下框中的内容
不能覆写:代表已经有通知值,说明前面已经调用过一次发送通知函数xTaskGenericNotify,将任务的通知状态改为等待接收通知,如果再一次调用xTaskGenericNotify去发送通知,发送这次的任务通知状态已经不等于等待接收通知了,说明通知值被取走(其中调用过接收通知函数,会将任务的状态改写,讲接收通知函数你就知道了)。
FreeRTOS-任务通知详解
4.如果任务为等待通知状态,说明该任务在此之前已经调用过接收通知函数(如果没有通知,会将任务的通知状态改写成等待通知状态,并进入阻塞态),此时我正好发送通知过去,就需要唤醒该任务去取通知值。
FreeRTOS-任务通知详解
当然光看一个发送通知函数,可能还是不太理解这些通知状态,所以一定是要发送/接收通知函数配合起来看,才能连贯起来,就豁然开朗。

函数 xTaskNotify():
此函数用于往指定任务发送任务通知,通知方式可以自由指定,并且不获取发送任务通知前任务通知的通知值。
函数 xTaskNotifyAndQuery():
此函数用于往指定任务发送任务通知,通知方式可以自由指定,并且获取发送任务通知前任务通知的通知值。

函数 xTaskNotifyGive():
此函数用于往指定任务发送任务通知,通知方式为将通知值加 1,并且不获取发送任务通知前任务通知的通知值(用于二值/计数型信号量)

FreeRTOS-任务通知详解
当然中断也可以向某任务发送通知值,函数跟上面的差不多,只不过多了中断保护。

2.接收任务通知 ulTaskNotifyTake()

ulTaskNotifyTake()函数其实是一个宏真正调用的是ulTaskGenericNotifyTake()函数,该函数就是专门服务与模拟二值信号量/计数型信号量的。
FreeRTOS-任务通知详解
1.ulTaskNotifyTake()函数原型
FreeRTOS-任务通知详解

  • 函数参数

1.uxIndexToWaitOn :任务的指定通知(任务通知相关数组下标)
2.xClearCountOnExit: 在成功接收通知后,将通知值清零或减 1(分别对应二值信号量,计数型信号量)
3.xTicksToWait: 阻塞等待任务通知值的最大时间

  • 函数返回值
    0:接收失败
    非 0: 接收成功,返回任务通知的通知值(当前计数值)

2.ulTaskNotifyTake()函数源码

#if ( configUSE_TASK_NOTIFICATIONS == 1 )

    uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait,
                                      BaseType_t xClearCountOnExit,
                                      TickType_t xTicksToWait )
    {
        uint32_t ulReturn;

        configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );

        taskENTER_CRITICAL();
        {
            /* 通知值为0代表没有接收到通知 */
            if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL )
            {
                /* 将任务通知的状态设置为等待通知状态 */
                pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;

			    /* 如果设置了等待时间 */
                if( xTicksToWait > ( TickType_t ) 0 )
                {
                    /* 将当前任务添加到阻塞态任务列表 */
                    prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
                    traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait );

                    /* 悬起 PendSV中断 准备进行任务切换 */
                    portYIELD_WITHIN_API();
                }
                else
                {
                    mtCOVERAGE_TEST_MARKER();
                }
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }
        }
        taskEXIT_CRITICAL();

		/* 任务如果进入阻塞,在这段时间里,任务可能被
		   发送通知的函数唤醒,唤醒则继续往下执行 */

        taskENTER_CRITICAL();
        {
           /* 代码执行到这里有三种情况
            1.一直没有接收到通知,任务阻塞超时被唤醒。
            2.一进该函数通知值就不等于0,说明有通知,任务也不需要阻塞。
            3.任务因没通知而阻塞,但是在该任务阻塞期间
             有其他任务向该任务发送了通知,并唤醒该任务。*/
            
            traceTASK_NOTIFY_TAKE( uxIndexToWait );
			/* 再次获取任务通知的通知值,如果等于0说明接收通知失败*/
            ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];

            if( ulReturn != 0UL )
            {
                /* 接收通知成功
                xClearCountOnExit == pdTRUE  通知值清0 : 二值信号量
                xClearCountOnExit == pdFALSE 通知值减一 :计数信号量*/
                if( xClearCountOnExit != pdFALSE )
                {
                    pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = 0UL;
                }
                else
                {
                    pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1;
                }
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }	
			/* 不论接收通知成功或者失败,都将任务通知的状态标记为未等待通知状态 */
            pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
        }
        taskEXIT_CRITICAL();

        return ulReturn;
    }

#endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/

FreeRTOS-任务通知详解
源码分析:
1.如果任务没有通知的情况下,调用了接收通知函数,则将任务通知状态设置为等待通知状态,这样等调用发送通知函数的时候,就方便去唤醒该任务(有通知了,唤醒该任务去接收通知做后续处理)。
FreeRTOS-任务通知详解
2.下图也印证了上面发送通知函数的是否可以覆写的问题
FreeRTOS-任务通知详解
用任务通知模拟的二值或者计数型信号量与真实的有何区别?
真实的计数型信号量可以指定初始值,且有最大值,而模拟的初始值为0且不能设置最大值。

自己对比一下:
FreeRTOS信号量详解

3.接收任务通知函数xTaskNotifyWait()

该函数一般用来模拟队列或者事件组的接收,该函数可以在等待前和成功等待到任务通知后清除通知指定位,与消息队列不同的是在任务等待超时后任务通仍然可以获取通知值。但假设用该函数获取了一次通知值,但是没有清除通知值,等下次又调用该函数时会直接进入阻塞(因为判断是否有通知不是取决于通知是否不等于0(当然模拟信号量的确实以是否为0作为是否有通知的标准),而是别的任务发送通知到该任务)。

当然xTaskNotifyWait()函数只是一个宏,真正调用的是xTaskGenericNotifyWait()函数.

FreeRTOS-任务通知详解
1.xTaskGenericNotifyWait()函数原型:
FreeRTOS-任务通知详解

  • 函数参数
    1.uxIndexToWaitOn :任务的指定通知(任务通知相关数组下标)
    2.ulBitesToClearOnEntry: 等待前指定清零的任务通知通知值比特位
    3.ulBitesToClearOnExit :成功等待后指定清零的任务通知通知值比特位
    4.pulNotificationValue :要获取的通知值(队列消息或者事件组)
    5.xTicksToWait :阻塞等待任务通知值的最大时间

  • 函数返回值
    pdTRUE:等待任务通知成功
    pdFALSE:等待任务通知失败

xTaskGenericNotifyWait()函数源码:

/*-----------------------------------------------------------*/

#if ( configUSE_TASK_NOTIFICATIONS == 1 )

    BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait,
                                       uint32_t ulBitsToClearOnEntry,
                                       uint32_t ulBitsToClearOnExit,
                                       uint32_t * pulNotificationValue,
                                       TickType_t xTicksToWait )
    {
        BaseType_t xReturn;
        /* 不能数组越界 */
        configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );

        taskENTER_CRITICAL();
        {
            /* 若不为等待接收通知状态,说明其他任务没有发送通知给该任务
               如果设置了超时时间,则任务需要进入阻塞态 */
            if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
            {
                /* 等待通知前清除任务通知值中的位,因为通知任务或中断可能会设置位。 这可用于将值清除为零。 */
                pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry;

				/* 设置任务通知的状态为等待通知状态 */
                pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
                /* 如果允许阻塞 */
                if( xTicksToWait > ( TickType_t ) 0 )
                {
                
				    /* 设置任务通知的状态为等待通知状态 */
                    prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
                    traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait );

                    /* 悬起 PendSv中断,准备进行任务切换*/
                    portYIELD_WITHIN_API();
                }
                else
                {
                    mtCOVERAGE_TEST_MARKER();
                }
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }
        }
        taskEXIT_CRITICAL();

		/* 如果该任务被阻塞了,解除阻塞后继续从这往下执行 */ 
		 
        taskENTER_CRITICAL();
        {
            traceTASK_NOTIFY_WAIT( uxIndexToWait );
            /* 当代码执行到这里可能是以下三种情况:
               1.前面的判断不成立,一进来就有通知任务不需要进入阻塞 
               2.前面的判断成立,任务进入阻塞,但是有其他任务向该任务发送
               通知并将该任务唤醒 
               3.前面的判断处理,任务进入阻塞,但是阻塞超时                 任务被迫唤醒       
            */
               
            if( pulNotificationValue != NULL )
            {
                /* 输出当前通知值,该值可能已更改,也可能未更改
                   未更改说明是任务是超时被唤醒的此时虽然能获取通知值
                   但是通知值是上次的,其实是获取通知值失败的 */
                *pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];
            }

            /*如果设置了 ucNotifyValue,则任务从未进入阻止状态
            (因为通知已挂起)或任务由于通知被唤醒。 
            否则,任务由于超时而解除阻止 */
            
            /* 如果任务通知的状态还不等于等待接收通知状态的话
            说明任务还是没有接收到通知任务只不过是超时被唤醒*/
            if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
            {
                /* A notification was not received. */
                xReturn = pdFALSE;
            }
            else
            {
				/* 在成功接收到通知后将通知值的指定比特位清零 */
                pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnExit;
                xReturn = pdTRUE;1
            }
            /* 不论接收通知成功或者失败都将任务通知的状态标记为未等待通知状态*/
            pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
        }
        taskEXIT_CRITICAL();

        return xReturn;
    }

#endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/

FreeRTOS-任务通知详解
源码我就分析了,直接看代码注释,一定要接收/发送两个通知函数一起分析,这样理解起来轻松多了,然后再对比一下ulTaskNotifyTake()与xTaskNotifyWait函数有何区别,其实他们最大的区别就是服务对象不一样,前者为模拟信号量服务,后着为队列,事件组服务。

1.模拟的队列与真实的队列有何区别?
(1).真实的队列可以容纳多个数据而且数据大小可以指定,而任务通知只有一个数据(32位的无符号整数)
(2).真实的队列,写队列时可以阻塞,任务通知则不能

与事件组的区别:
其实你真正看懂源码,区别显而易见,留给你们的作业,哈哈哈哈哈哈哈
事件组详解

三.总结

发现学通了,都是有套路的,FreeRTOS全程都是一个风格,还怕研究不透嘛,只需将源码学透,接下来应用就是熟练度的问题了。文章来源地址https://www.toymoban.com/news/detail-458207.html

到了这里,关于FreeRTOS-任务通知详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 详解FreeRTOS:FreeRTOS任务管理程序设计思路(基础篇—9)

    目录 1、中断服务函数 2、任务 3、空闲任务 4、任务的执行时间 作为一位RTOS程序开发者,要对自己设计的嵌入式系统要了如指掌,任务的优先级信息,任务与中断的处理,任务的运行时间、逻辑、状态等都要知道,才能设计出好的系统,所以,在设计的时候需要根据需求制定

    2024年02月13日
    浏览(40)
  • 定时任务报警通知解决方案详解

    定时任务是每个业务常见的需求,比如每分钟扫描超时支付的订单,每小时清理一次数据库历史数据,每天统计前一天的数据并生成报表等等。 随着微服务和云计算的兴起,定时任务技术也是发展迅速,不仅能做单机的定时任务,而且在分布式系统下应用也很广泛,成为了业

    2024年02月02日
    浏览(35)
  • FreeRTOS任务调度与任务切换 | FreeRTOS八

    目录 说明: 一、任务调度器 1.1、开启任务调度器函数 1.2、任务调度器实现步骤 1.3、xPortStartScheduler()函数 二、启动一个任务 2.1、prvStartFirstTask()函数 2.2、vPortSVCHandler()函数 三、任务切换 3.1、任务切换触发途径 3.2、PendSV中断触发任务切换步骤 关于内容: 1)以下内容多为概

    2023年04月15日
    浏览(35)
  • 【Freertos基础入门】freertos任务的优先级

    本系列基于 stm32 系列单片机来使用freerots 任务管理是实时操作系统(RTOS)的核心功能之一,它允许开发者以并发的方式组织和管理多个任务。FreeRTOS 是一个流行的开源RTOS,它提供了强大的任务管理功能,让开发者能够轻松创建和控制任务。本文将介绍 FreeRTOS 的任务管理功能

    2024年02月13日
    浏览(35)
  • FreeRTOS任务的挂起和恢复 | FreeRTOS四

    目录 说明: 一、任务挂起与恢复 1.1、什么是任务挂起 1.2、任务挂起函数 1.3、什么是任务恢复 1.4、任务恢复函数 1.5、什么是中断任务恢复函数 1.6、中断任务恢复函数 二、任务挂起与恢复实例代码(任务中) 2.1、主要代码 2.2、结果 三、任务挂起与恢复实例代码(中断中)

    2024年02月16日
    浏览(38)
  • 【学习FreeRTOS】第5章——FreeRTOS任务挂起与恢复

    vTaskSuspend() ——挂起任务(类似暂停,可恢复,但删除任务,无法恢复) vTaskResume() ——恢复被挂起的任务 xTaskResumeFromISR()—— 在中断中恢复被挂起的任务 形参:待挂起任务句柄 此函数用于挂起任务,使用时需将宏 INCLUDE_vTaskSuspend 配置为 1。 无论优先级如何,被挂起的任务

    2024年02月13日
    浏览(42)
  • FreeRTOS教程2 任务管理

    正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) Keil µVision5 IDE(MDK-Arm) 野火DAP仿真器 XCOM V2.6串口助手 一个滑动变阻器 逻辑分析仪nanoDLA 本文主要学习FreeRTOS任务管理的相关知识, 包括FreeRTOS创建/删除任务、任务状态、任务优先级、延时函数、空闲任务和任务

    2024年03月12日
    浏览(44)
  • Freertos 任务调度

    文章目录 前言 一、任务调度 二、任务优先级 三、任务状态           用51单片机或者stm32进行裸机开发时, 一般都是在 main 函 数里面用 while(1) 做一个大循 环来完成所有的处理。而Freertos是一个抢占式的实时多任务操作系统,可以并发处理各个任务。   Freertos支持三种任

    2024年02月15日
    浏览(38)
  • FreeRTOS的任务堆栈

    一、 FreeRTOS的任务堆栈 在FreeRTOS中,每个任务都有自己的堆栈。堆栈是用来存储任务运行时临时变量、函数返回地址等数据的一段内存空间。堆栈的大小是通过xTaskCreate()函数的参数指定的,通常情况下需要根据任务所需的局部变量的大小及递归调用深度来合理设置。 FreeRTO

    2024年02月14日
    浏览(40)
  • FreeRTOS_任务切换

    目录 1. RendSV 异常 2. FreeRTOS 任务切换场合 2.1 执行系统调用 2.2 系统滴答定时器(SysTick)中断 3. PendSV 中断服务函数 4. 查找下一个要运行的任务 4.1 通用方法 4.2 硬件方法 5. FreeRTOS 的时间片调度 6. 时间片调度实验 6.1 实验程序         RTOS 系统的核心是任务管理,而任务管理的

    2024年02月12日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包