FreeRTOS源码分析与应用开发08:任务通知

2023-05-16

目录

1. 概述

1.1 任务通知概念

1.2 任务通知控制结构

2. 发送任务通知

2.1 任务级发送

2.2 中断级发送

2.2.1 xTaskNotifyFromISR函数

2.2.2 vTaskNotifyGiveFromISR函数

3. 获取任务通知

3.1 ulTaskNotifyTake函数

3.2 xTaskNotifyWait函数

4. 任务通知使用场景

4.1 模拟二值信号量

4.2 模拟计数信号量

4.3 模拟消息邮箱

4.4 模拟事件标志组


1. 概述

1.1 任务通知概念

① FreeRTOS从v8.2.0版本开始新增任务通知功能

② 任务通知功能可以在一些场合中替代二值信号量、计数信号量、消息队列和事件标志组,且性能更好(函数调用更少),RAM占用更少(无需新建内核对象)

可以将任务通知机制理解为一种轻量级任务间通信的实现方式

③ 凡事皆有利弊,任务通知机制也有如下限制,

a. 只能有一个任务接收通知消息(之所以叫任务通知,就是只能向指定的任务发送消息)

b. 只有等待通知的任务可以被阻塞,发送通知的任务不会因为发送失败而阻塞(作为比较,消息队列的发送任务也可以设置延时阻塞)

1.2 任务通知控制结构

任务通知作为一种轻量级任务间通信机制,无需新建内核对象,而是在TCB中新增字段,

typedef struct tskTaskControlBlock
{
    // 其他字段

    #if( configUSE_TASK_NOTIFICATIONS == 1 )
        // 任务通知值
        volatile uint32_t ulNotifiedValue;
        // 任务通知状态
        volatile uint8_t ucNotifyState;
    #endif
} tskTCB;

说明1:任务通知值ulNotifiedValue

通过对任务通知值的不同使用方法,实现对二值信号量、计数信号量、消息队列和事件标志组的模拟

说明2:任务通知状态ucNotifyState

任务通知状态共有如下3种,定义在tasks.c中,

/* Values that can be assigned to the ucNotifyState member of the TCB. */
// 任务没有在等待通知
// 任务初始化之后的默认值
// 任务在成功获取通知后也设置为该值
#define taskNOT_WAITING_NOTIFICATION	( ( uint8_t ) 0 )

// 任务在等待通知
// 任务在设置为该状态后,将进入阻塞状态
#define taskWAITING_NOTIFICATION		( ( uint8_t ) 1 )

// 任务接收到通知,但尚未处理
// 由通知的发送者设置接收任务进入该状态
#define taskNOTIFICATION_RECEIVED		( ( uint8_t ) 2 )

说明3:对任务通知值 & 任务通知状态的使用,均需要通过临界段进行保护

2. 发送任务通知

2.1 任务级发送

// xTaskNotify:任务级通用任务通知发送函数
#define xTaskNotify( xTaskToNotify, ulValue, eAction ) \
xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL )

// xTaskNotifyAndQuery:任务级返回之前任务通知值的通用任务通知发送函数
#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, \
pulPreviousNotifyValue ) \
xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), \
( pulPreviousNotifyValue ) )

// xTaskNotifyGive:任务级专门用于模拟信号量的任务通知发送函数
#define xTaskNotifyGive( xTaskToNotify ) \
xTaskGenericNotify( ( xTaskToNotify ), ( 0 ), eIncrement, NULL )

可见任务级发送函数都是对xTaskGenericNotify函数的封装,下面就分析该函数,

// xTaskToNotify:要通知的任务
// ulValue:任务通知值
// eAction:任务通知值更新方式,为一个枚举值
// pulPreviousNotificationValue:用于保存通知前的任务通知值
BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, 
uint32_t ulValue, eNotifyAction eAction, 
uint32_t *pulPreviousNotificationValue )
{
    TCB_t * pxTCB;
    BaseType_t xReturn = pdPASS;
    uint8_t ucOriginalNotifyState;

    configASSERT( xTaskToNotify );
    pxTCB = ( TCB_t * ) xTaskToNotify;

    // 进入临界段
    taskENTER_CRITICAL();
    {
        // 保存通知前的任务通知值
        if( pulPreviousNotificationValue != NULL )
        {
            *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
        }

        // 取出当前任务通知状态,是为了后续判断任务通知状态
        ucOriginalNotifyState = pxTCB->ucNotifyState;

        // 将任务通知状态设置为接收到通知消息
        pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;

        // 处理不同的任务通知值更新方式
        switch( eAction )
        {
        // 位或设置任务通知值
        // 可用于模拟事件标志组
        case eSetBits:
            pxTCB->ulNotifiedValue |= ulValue;
            break;

        // 任务通知值递增
        // 可用于模拟二值信号量 & 计数信号量
        case eIncrement:
            ( pxTCB->ulNotifiedValue )++;
            break;

        // 覆盖设置任务通知值
        // 可用于模拟长度为1的消息队列,且为覆盖模式
        case eSetValueWithOverwrite:
            pxTCB->ulNotifiedValue = ulValue;
            break;

        // 不覆盖设置任务通知值
        // 如果之前的任务通知尚未被处理,则此次设置失败
        case eSetValueWithoutOverwrite:
            if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
            {
                pxTCB->ulNotifiedValue = ulValue;
            }
            else
            {
                // 只有这一种情况会返回pfFAIL
                xReturn = pdFAIL;
            }
            break;

        // 不操作任务通知值
        case eNoAction:
            break;
        }

        // 如果要通知的任务处于阻塞状态,则将其唤醒
        if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
        {
            // 任务状态列表项目前处于延时列表或阻塞列表
            ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
            prvAddTaskToReadyList( pxTCB );
            
            // 由于被唤醒的任务在等待任务通知,所以任务事件列表项应该为空,
            // 即不应该在等待其他内核对象
            configASSERT( listLIST_ITEM_CONTAINER(
            &( pxTCB->xEventListItem ) ) == NULL );

            #if( configUSE_TICKLESS_IDLE != 0 )
            {
                // tickless模式下,尽快更新下一任务解锁时间
                prvResetNextTaskUnblockTime();
            }
            #endif

            if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
            {
                // 如果被唤醒的任务优先级更高,则触发任务调度
                taskYIELD_IF_USING_PREEMPTION();
            }
        }
    }
    taskEXIT_CRITICAL();

    return xReturn;
}

说明1:从xTaskGenericNotify函数的实现可见,任务通知机制的函数调用关系更简单,也不需要遍历等待列表(因为已有明确的唤醒对象),因此效率更高

说明2:任务通知既可以实现基于条件的通知,也可以实现基于资源的通知

2.2 中断级发送

2.2.1 xTaskNotifyFromISR函数

// xTaskNotifyFromISR:中断级通用任务通知发送函数
#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, \
pxHigherPriorityTaskWoken ) \
xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), \
( eAction ), NULL, ( pxHigherPriorityTaskWoken ) )

// xTaskNotifyAndQueryFromISR:中断级返回之前任务通知值的通用任务通知发送函数
#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction,\
 pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) \
 xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), \
 ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) )

中断级通用发送函数都是对xTaskGenericNotifyFromISR函数的封装,

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

    configASSERT( xTaskToNotify );

    // 判断当前中断的有效性,是否在FreeRTOS管理之下
    portASSERT_IF_INTERRUPT_PRIORITY_INVALID();

    pxTCB = ( TCB_t * ) xTaskToNotify;

    // 进入临界段
    uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
    {
        if( pulPreviousNotificationValue != NULL )
        {
            *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
        }

        ucOriginalNotifyState = pxTCB->ucNotifyState;
        pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;

        switch( eAction )
        {
        case eSetBits:
            pxTCB->ulNotifiedValue |= ulValue;
            break;

        case eIncrement:
            ( pxTCB->ulNotifiedValue )++;
            break;

        case eSetValueWithOverwrite:
            pxTCB->ulNotifiedValue = ulValue;
            break;

        case eSetValueWithoutOverwrite:
            if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
            {
                pxTCB->ulNotifiedValue = ulValue;
            }
            else
            {
                // 也只有这一种情况返回pdFAIL
                xReturn = pdFAIL;
            }
            break;

        case eNoAction:
            break;
        }

        // 至此的处理,中断级与任务级都是相同的
        // 差别在于唤醒阻塞任务
        if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
        {
            configASSERT( listLIST_ITEM_CONTAINER(
            &( pxTCB->xEventListItem ) ) == NULL );

            if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
            {
                ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
                prvAddTaskToReadyList( pxTCB );
            }
            else
            {
                // 唤醒任务时,如果调度器被挂起,
                // 则将任务事件列表项加入挂起解除就绪列表
                vListInsertEnd( &( xPendingReadyList ),
                &( pxTCB->xEventListItem ) );
            }

            if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
            {
                // 如果被唤醒的任务优先级更高,则通过出参带出
                if( pxHigherPriorityTaskWoken != NULL )
                {
                    *pxHigherPriorityTaskWoken = pdTRUE;
                }
                else
                {
                    // 为防止用户忽略该出参,通过xYieldPending进行标识
                    // 这样在SysTick中断中,就可以触发任务调度
                    // 这里就充分体现了RTOS的实时性
                    xYieldPending = pdTRUE;
                }
            }
        }
    }
    portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );

    return xReturn;
}

2.2.2 vTaskNotifyGiveFromISR函数

void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
BaseType_t *pxHigherPriorityTaskWoken )
{
    TCB_t * pxTCB;
	uint8_t ucOriginalNotifyState;
	UBaseType_t uxSavedInterruptStatus;

    configASSERT( xTaskToNotify );

    portASSERT_IF_INTERRUPT_PRIORITY_INVALID();

    pxTCB = ( TCB_t * ) xTaskToNotify;

    uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
    {
        ucOriginalNotifyState = pxTCB->ucNotifyState;
        pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;

        // 递增任务通知值
        ( pxTCB->ulNotifiedValue )++;

        if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
        {
            configASSERT( listLIST_ITEM_CONTAINER(
            &( pxTCB->xEventListItem ) ) == NULL );

            if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
            {
                ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
                prvAddTaskToReadyList( pxTCB );
            }
            else
            {
                vListInsertEnd( &( xPendingReadyList ),
                &( pxTCB->xEventListItem ) );
            }

            if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
            {
                if( pxHigherPriorityTaskWoken != NULL )
                {
                    *pxHigherPriorityTaskWoken = pdTRUE;
                }
                else
                {
                    xYieldPending = pdTRUE;
                }
            }
        }
    }
    portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
}

是不是看了这个函数也很难理解FreeRTOS的处理方式,只是实现为无返回值,其实有返回值又能怎样呢 ? 猜想是一个历史遗留问题

3. 获取任务通知

说明:获取任务通知只有任务级,没有中断级

3.1 ulTaskNotifyTake函数

ulTaskNotifyTask函数专门用于模拟信号量的任务通知获取函数

// xClearCountOnExit:指定任务通知值消费方式
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit,
TickType_t xTicksToWait )
{
    uint32_t ulReturn;

    taskENTER_CRITICAL();
    {
        // 任务通知值为0,说明无有效"信号量"
        // 如果设置了等待时间,则进入延时阻塞状态
        // 如果通知值不为0,说明有有效"信号量"
        // 则直接进入消费信号量的处理环节
        if( pxCurrentTCB->ulNotifiedValue == 0UL )
        {
            // 设置任务通知状态为等待通知
            pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;

            if( xTicksToWait > ( TickType_t ) 0 )
            {
                prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
                portYIELD_WITHIN_API();
            }
        }
    }
    // 如果上文进入了延时阻塞状态,并触发了任务调度
    // 在此处退出临界段之后,就会进行任务切换
    taskEXIT_CRITICAL();

    taskENTER_CRITICAL();
    {
        // 返回值为消费之前的任务通知值
        ulReturn = pxCurrentTCB->ulNotifiedValue;

        // 如果有"信号量",则根据设置消费任务通知值
        if( ulReturn != 0UL )
        {
            if( xClearCountOnExit != pdFALSE )
            {
                // 将任务通知值清零
                // 用于模拟二值信号量
                pxCurrentTCB->ulNotifiedValue = 0UL;
            }
            else
            {
                // 将任务通知值减1
                // 用于模拟计数信号量
                pxCurrentTCB->ulNotifiedValue = ulReturn - 1;
            }
        }

        // 设置任务通知状态为任务没有在等待通知
        pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
    }
    taskEXIT_CRITICAL();

    return ulReturn;
}

3.2 xTaskNotifyWait函数

xTaskNotifyWait函数为通用任务通知获取函数

// ulBitsToClearOnEntry:进入函数时要清除的任务通知值比特位
// ulBitsToClearOnExit:退出函数时要清除的任务通知值比特位
// pulNotificationValue:保存消费前的任务通知值
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry,
uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue,
TickType_t xTicksToWait )
{
    BaseType_t xReturn;

    taskENTER_CRITICAL();
    {
        // 如果任务尚未接收到通知,且设置了等待时间
        // 则任务进入延时阻塞状态
        if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
        {
            pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;

            pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;

            if( xTicksToWait > ( TickType_t ) 0 )
            {
                prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
                portYIELD_WITHIN_API();
            }
        }
    }
    taskEXIT_CRITICAL();

    taskENTER_CRITICAL();
    {
        // 返回消费前的任务通知值
        if( pulNotificationValue != NULL )
        {
            *pulNotificationValue = pxCurrentTCB->ulNotifiedValue;
        }

        // xReturn返回的是是否接收到通知消息
        if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION )
        {
            xReturn = pdFALSE;
        }
        else
        {
            // 根据设置,消费任务通知值
            pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit;
            xReturn = pdTRUE;
        }

        pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
    }
    taskEXIT_CRITICAL();

    return xReturn;
}

说明:xTaskNotifyWait函数可以用于模拟消息队列和事件标志组

4. 任务通知使用场景

4.1 模拟二值信号量

// 获取二值信号量
u32 NotifyValue = 0;
NotifyValue = ulTaskNotifyTake(pdTRUE, timeToWait);
if (NotifyValue > 0)
{
    // 说明获取到的信号量,而不是等待超时
}

// 释放二值信号量
xTaskNotifyGive 或 vTaskNotifyGiveFromISR

说明1:使用任务通知模拟二值信号量的语义与真实的二值信号量是一致的,虽然释放信号量的一端可以多次释放,但是消费信号量的任务会将任务通知值清零,因此只会处理一次

而真实的二值信号量,则是多次释放会失败,因为消息队列的长度只有1

说明2:虽然使用通用任务通知函数也能模拟二值信号量,但是系统提供了模拟函数,为啥不直接使用呢

从获取信号量的操作分析,调用xTaskNotifyWait函数实现二值信号量的语义反而比较麻烦,不如直接调用ulTaskNotifyTask函数

而使用xTaskNotifyWait函数还无法实现计数信号量的语义

4.2 模拟计数信号量

// 获取计数信号量
// 只会将任务通知值减1
u32 NotifyValue = 0;
NotifyValue = ulTaskNotifyTake(pdFALSE, timeToWait);
if (NotifyValue > 0)
{
    // 说明获取到的信号量,而不是等待超时
}

// 释放计数信号量
xTaskNotifyGive 或 vTaskNotifyGiveFromISR

说明:使用任务通知模拟计数信号量,没有真实信号量的最大值限制(使用上限为uint32_t类型最大值)

4.3 模拟消息邮箱

任务通知也可以用来向任务发送数据,相较于消息队列,使用任务通知向任务发送消息有如下限制,

① 只能发送32位的数据值(也就是任务通知值)

② 消息被保存为任务的任务通知值,而且一次只能保存一个任务通知值,相当于队列长度为1,所以被称作消息邮箱(而非消息队列)

// 等待消息
BaseType_t err = pdFALSE;

err = xTaskNptifyWait((uint32_t)0x00, // 进入函数时,不清除任务通知值比特位
(uint32_t)0xFFFFFFFF, // 退出函数时,清除任务通知值所有比特位
(uint32_t *)&notifyValue, // 保存接收到的消息值
(TickType_t)timeToWait); // 阻塞时间
if (err == pdTRUE)
{
    // 说明接收到任务通知
}

// 发送消息
BaseType_t err = pdFALSE;
err = xTaskNotify((TaskHandle_t)handle, // 要通知的任务句柄
(uint32_t)value, // 任务通知值
eSetValueWithOverWrite); // 覆写方式,也可以使用非覆写方式
if (err == pfFAIL)
{
    // 说明任务通知失败
}

4.4 模拟事件标志组

当任务通知用作事件标志组时,任务通知值就相当于事件组,任务通知值的每个bit用作事件标志位

#define EVENT_0 (1 << 0)
#define EVENT_1 (1 << 1)

// 设置事件标志位
xTaskNotify((TaskHandle_t)handle,
(uint32_t)EVENT_0,
eSetBits);

xTaskNotify((TaskHandle_t)handle,
(uint32_t)EVENT_0,
eSetBits);

// 等待事件标志
BaseType_t err = pdFALSE;

err = xTaskNotifyWait((uint32_t)0x00, // 进入函数时,不清除任务通知值比特位
(uint32_t)0xFFFFFFFF, // 退出函数时,清除任务通知值所有比特位
(uint32_t *)&notifyValue, // 保存接收到的消息值
(TickType_t)timeToWait); // 阻塞时间
if (err == pdTRUE)
{
    // 说明接收到事件
    // 此时要判断发生的是哪些事件
}

说明:在使用任务通知模拟事件标志组时,功能相对较弱,不能设置"逻辑与" & "逻辑或"类型的等待,而是需要用户自行处理事件发生后的逻辑

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS源码分析与应用开发08:任务通知 的相关文章

  • 详解FreeRTOS中的软件定时器

    软件定时器用于让某个任务定时执行 或者周期性执行 比如设定某个时间后执行某个函数 或者每隔一段时间执行某个函数 由软件定时器执行的函数称为软件定时器的回调函数 参考资料 Mastering the FreeRTOS Real Time Ke
  • FreeRTOS例程4-串口DMA收发不定长数据

    FreeRTOS例程4 串口DMA收发不定长数据 知乎 zhihu com
  • 基于HAL库的FREERTOS----------二.任务API函数

    任务API函数览概 CUBEMX对 做了API的封装 很多 的函数没有封装到位 可以用原函数调用 任务API函数分别介绍 1 uxTaskPriorityGet 此函数用来获取指定任务的优先级 要使用此函数的话宏 INCLUDE uxTas
  • FreeRTOS学习笔记 6 - 互斥量

    目录 1 创建 2 获取 3 释放 4 测试 FreeRTOS不支持调度方式的设置 所以下面2个宏定义可以随意设置值 define RTOS IPC FLAG FIFO 0x00 define RTOS IPC FLAG PRIO 0x01
  • 【FreeRTOS开发问题】FreeRTOS内存溢出

    FreeRTOS内存溢出 如下图所示 FreeRTOS编译完成后可以看到 系统提示无法分配内存到堆 Objects Template axf Error L6406E No space in execution regions with A
  • 【FreeRTOS】队列的使用

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • FreeRTOS学习笔记<中断>

    中断概念 Cortex M的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽中断 NMI 1个Systick 滴答定时器 定时器中断和多个系统异常 Cortex M处理器有多个用于管中断和异常的可编程寄存器 这些寄存器大多数都在 NV
  • FreeRTOS ------- 任务(task)

    在学习RTOS的时候 个人觉得带着问题去学习 会了解到更多 1 什么是任务 在FreeRTOS中 每个执行线程都被称为 任务 每个任务都是在自己权限范围内的一个小程序 其具有程序入口每个任务都是在自己权限范围内的一个小程序 其具有程序入口通
  • FreeRTOS记录(九、一个裸机工程转FreeRTOS的实例)

    记录一下一个实际项目由裸机程序改成FreeRTOS 以前产品的平台还是C8051单片机上面的程序 硬件平台改成了STM32L051 同时使用STM32CubeMX生成的工程 使用FreeRTOS系统 EEPROM数据存储读取函数修改更新 2
  • 【FreeRTOS(三)】任务状态

    文章目录 任务状态 任务挂起 vTaskSuspend 取消任务挂起 vTaskResume 挂起任务调度器 vTaskSuspendAll 取消挂起任务调度器 xTaskResumeAll 代码示例 任务挂起 取消任务挂起 代码示例 挂起
  • STM32F103移植FreeRTOS必须搞明白的系列知识---2(FreeRTOS任务优先级)

    STM32F103移植FreeRTOS必须搞明白的系列知识 1 Cortex CM3中断优先级 STM32F103移植FreeRTOS必须搞明白的系列知识 2 FreeRTOS任务优先级 STM32F103移植FreeRTOS必须搞明白的系
  • FreeRTOS学习(三)开关中断

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 背景知识 Cotex M3的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽 NMI 1个Systick 滴答定时器 Cortex M处理
  • FreeRTOS笔记(一)简介

    这个笔记主要依据韦东山freertos快速入门系列记录 感谢韦东山老师的总结 什么是实时操作系统 操作系统是一个控制程序 负责协调分配计算资源和内存资源给不同的应用程序使用 并防止系统出现故障 操作系统通过一个调度算法和内存管理算法尽可能把
  • 基于STM32的FreeRTOS学习之中断测试实验(五)

    记录一下 方便以后翻阅 本章内容是接着上一章节进行的实际演练 1 实验目的 FreeRTOS可以屏蔽优先级低于configMAX SYSCALL INTERRUPT PRIORITY的中断 不会屏蔽高于其的中断 本次实验就是验证这个说法 本
  • FreeRTOS学习笔记(8)---- 软件定时器

    使用FreeRTOS软件定时器需要在文件FreeRTOSConfig h先做如下配置 1 configUSE TIMERS 使能软件定时器 2 configTIMER TASK PRIORITY 定时器任务优先级 3 configTIMER
  • FreeRTOSConfig.h 配置优化及深入

    本篇目标 基于上一篇的移植freertos stm32f4 freertos 上 修改 FreeRTOSConfig h 文件的相关配置来优化辅助 FreeRtos 的使用 并且建立一些基本功能 信号量 消息地列等 的简单应用位于 stm3
  • 当一个任务写入变量而其他任务读取该变量时,我们是否需要信号量?

    我正在研究 freeRtos 并且我有一个名为 x 的变量 现在 每秒只有一个任务正在写入该变量 而其他任务正在读取该变量值 我需要用互斥锁来保护变量吗 如果变量为 32 位或更小 并且其值是独立的并且不与任何其他变量一起解释 则不需要互斥
  • FreeRTOS 匈牙利表示法 [重复]

    这个问题在这里已经有答案了 我是 RTOS 和 C 编程的新手 而且我仍在习惯 C 的良好实践 因此 我打开了一个使用 FreeRTOS 的项目 我注意到操作系统文件使用匈牙利表示法 我知道一点符号 但面临一些新的 标准 FreeRTOS
  • 有可用的 FreeRTOS 解释语言库吗?

    我在一家公司工作 该公司使用 FreeRTOS 为多个设备创建固件 最近 我们对新功能的要求已经超出了我们固件工程师的工作能力 但我们现在也无力雇用任何新人 即使进行微小的更改 也需要固件人员在非常低的级别上进行修改 我一直在为 FreeR
  • GNU Arm Cortex m4 上的 C++ 异常处理程序与 freertos

    2016 年 12 月更新现在还有一个关于此行为的最小示例 https community nxp com message 862676 https community nxp com message 862676 我正在使用带有 free

随机推荐

  • cmake(8):install命令详解

    1 说明 之前的示例中有提到使用cmake的install命令来自动安装库和头文件 xff0c 但是只是使用到了install命令很基础很少的部分 xff0c 其实该命令作用十分丰富 xff0c 本篇文档用于说明该命令的详细使用方法 2 i
  • cmake(9):包含指定目录的头文件

    1 说明 在编译程序时 xff0c 如果需要用到外部的头文件 xff0c 而该头文件又没有被添加到系统默认的路径中 xff08 如 xff1a usr include xff0c usr local include和 usr lib gcc
  • cmake(10):使用cmake编译linux驱动或内核模块

    1 说明 这篇笔记用于说明如何使用cmake构建Linux驱动 xff0c 这样可以方便地将driver和app作为一个整体统一构建 2 示例 首先来看一个代码示例 xff0c 为了简化起见 xff0c 我直接在驱动目录下进行构建而没有作为
  • Boost(1):Boost库简介及安装

    1 Boost库介绍 Boost是一个功能强大 构造精巧 跨平台 开源并且完全免费的C 43 43 程序库 xff0c 在1998年由Beman G Dawes发起倡议并建立 使用了许多现代C 43 43 编程技术 xff0c 内容涵盖字符
  • Ubuntu:与Windows共享文件夹

    1 说明 我个人更喜欢在windows下编辑代码或文档 xff0c 而运行环境又经常在Linux环境下进行 xff0c 那么Windows和Linux之间的协作就显得很有必要了 通常有两种方式来实现两个系统之间的文件共享 xff1a 在Li
  • C语言处理参数的 getopt() 函数

    前言 C语言程序主要通过 main 函数的参数来传递命令行参数 xff1a 默认传递命令行参数 int main int argc char argv 其中 argc 表示参数个数 xff08 包含程序本身 xff09 xff0c argv
  • SPD5详解

    SPD介绍 SPD xff08 serial presence detect xff09 xff0c 即串行存在检测 xff0c 是DIMM的相关描述信息 在每根内存条上 xff0c 都有一份SPD数据 xff0c 这份数据保存在一个可擦写
  • 基于CentOS更新 glibc - 解决 `GLIBC_2.29‘ not found

    说明 在一个 CentOS Stream8 上安装或运行某些程序时 xff0c 报 96 GLIBC 2 29 39 not found xff0c 因为系统自带的 glibc 库版本只到 glibc 2 28 strings usr li
  • FreeRTOS源码分析与应用开发05:信号量

    目录 1 信号量概述 1 1 信号量概念 1 2 4种信号量 1 2 1 二值信号量 1 2 2 计数信号量 1 2 3 互斥信号量 1 2 4 递归互斥信号量 1 3 信号量相关控制结构 1 3 1 队列结构 1 3 2 任务结构 2 二
  • FreeRTOS Task switch

    vTaskSwitchContext中看pxCurrentTCB traceTASK SWITCHED OUT 切出 taskSELECT HIGHEST PRIORITY TASK traceTASK SWITCHED IN 切入新的ta
  • 嵌入式常见总线分类总结

    任何一个微处理器都要与一定数量的部件和外围设备连接 xff0c 但如果将各部件和每一种外围设备都分别用一组线路与CPU直接连接 xff0c 那么连线将会错综复杂 xff0c 甚至难以实现 为了简化硬件电路设计 简化系统结构 xff0c 常用
  • linux压测工具stress和stress-ng下载

    1 下载 2020 5 16实测以下地址能下载 stress https fossies org linux privat stress 1 0 4 tar gz stress ng https aur tuna tsinghua edu
  • 设备树Device Tree详解

    原文 xff1a https www cnblogs com aaronLinux p 5496559 html 目录 1 设备树 xff08 Device Tree xff09 基本概念及作用 2 设备树的组成和使用 2 1 DTS和DT
  • 十六进制与ascii码互转 C语言实现

    十六进制与ascii码互转 C语言实现 1 ascii转16进制 func char to hex desc convert ascii to 16 hex input ascii return hex unsigned char char
  • Android 11.0 支持exFAT文件系统

    Android 11 0 支持exFAT文件系统 U盘常见文件系统类型有FAT32 NTFS exFAT xff0c Android默认支持FAT32 一般也有NTFS类型编译选项 xff0c 但是exFAT由于版权或者其他原因 xff0c
  • repo sync遇到warning: project ‘repo‘ branch ‘stable‘ is not signed

    warning project 39 repo 39 branch 39 stable 39 is not signed This can happen on Linux and Mac I 39 ve personally experie
  • C语言单链表基本操作总结

    C语言单链表基本操作 本文是参考他人实现的C语言单链表 xff0c 对多篇博文整理的结果 xff0c 仅作为学习笔记 文末有参考出处 1 单链表定义 链表是通过一组任意的存储单元来存储线性表中的数据元素 xff0c 这些存储单元可以是连续的
  • 开源项目-类似58同城的项目启动

    已经进入编程这行已经3年 xff0c 最近想做一个自己的开源项目 xff0c 最后选来选去 xff0c 选中了类似58同城的功能的项目作为开始 下面是一些列的工作 xff0c 里面会体系我是怎样把这个项目做出来 xff0c 包括思路 技术
  • CMakeLists完整解析(一)

    CMakeLists完整解析 xff08 一 xff09 首先 xff0c 我们先通过介绍一下相关的核心概念来引入CMakeLists 1 gcc make和cmake gcc xff08 GNU Compiler Collection x
  • FreeRTOS源码分析与应用开发08:任务通知

    目录 1 概述 1 1 任务通知概念 1 2 任务通知控制结构 2 发送任务通知 2 1 任务级发送 2 2 中断级发送 2 2 1 xTaskNotifyFromISR函数 2 2 2 vTaskNotifyGiveFromISR函数 3