Freertos代码之互斥信号量

2023-05-16

信号量用于限制对共享资源的访问和多任务之间的同步。三个信号量API函数都是宏,使用现有的队列实现。

使用例子:

typedef void * QueueHandle_t;
typedef QueueHandle_t SemaphoreHandle_t;

SemaphoreHandle_t mutex_sema;
mutex_sema = xSemaphoreCreateMutex();

 

xSemaphoreTake(mutex_sema, portMAX_DELAY);

/* 对共享资源的操作 */

xSemaphoreGive(mutex_sema);

 

代码:

/*

 * xSemaphoreCreateMutex

 */

#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )

    QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
    {
    Queue_t *pxNewQueue;
    const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;

        pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType ); // 创建队列,注意参数.
        prvInitialiseMutex( pxNewQueue );  // 初始化刚创建的普通队列为互斥体

        return pxNewQueue;
    }

    static void prvInitialiseMutex( Queue_t *pxNewQueue )
    {
        if( pxNewQueue != NULL )
        {
            /* The queue create function will set all the queue structure members
            correctly for a generic queue, but this function is creating a
            mutex.  Overwrite those members that need to be set differently -
            in particular the information required for priority inheritance. */
            /* 队列创建函数将为通用队列正确设置所有队列结构成员,但此函数正在创建互斥体。
               覆盖那些需要以不同方式设置的成员-特别是优先级继承所需的信息 */

            // #define pxMutexHolder                pcTail
            // #define uxQueueType                    pcHead

            pxNewQueue->pxMutexHolder = NULL;
            pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;

            /* In case this is a recursive mutex. */
            pxNewQueue->u.uxRecursiveCallCount = 0;

            traceCREATE_MUTEX( pxNewQueue );

            /* Start with the semaphore in the expected state. */
            /* 从处于预期状态的信号量开始 */
            ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK );
        }
        else
        {
            traceCREATE_MUTEX_FAILED();
        }
    }

 

/*

 * xSemaphoreTake

 */

#define xSemaphoreTake( xSemaphore, xBlockTime )        xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) )

BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait )
{
BaseType_t xEntryTimeSet = pdFALSE;
TimeOut_t xTimeOut;
Queue_t * const pxQueue = ( Queue_t * ) xQueue;

#if( configUSE_MUTEXES == 1 )
    BaseType_t xInheritanceOccurred = pdFALSE;
#endif

    /* Check the queue pointer is not NULL. */
    configASSERT( ( pxQueue ) );

    /* Check this really is a semaphore, in which case the item size will be
    0. 检查这是否是一个信号量,在这种情况下,项目大小将为0 */
    configASSERT( pxQueue->uxItemSize == 0 );

    /* Cannot block if the scheduler is suspended. 如果计划程序已挂起,则无法阻止 */
    #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
    {
        configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
    }
    #endif


    /* This function relaxes the coding standard somewhat to allow return
    statements within the function itself.  This is done in the interest
    of execution time efficiency. */
    /* 这个函数在一定程度上放宽了编码标准,允许函数本身内部有返回语句。这是为了提高执行时间效率 */

    for( ;; )
    {
        taskENTER_CRITICAL();
        {
            /* Semaphores are queues with an item size of 0, and where the
            number of messages in the queue is the semaphore's count value. */
            /* 信号量是项目大小为0的队列,其中队列中的消息数是信号量的计数值 */
            const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting;

            /* Is there data in the queue now?  To be running the calling task
            must be the highest priority task wanting to access the queue. */
            /* 队列中现在有数据吗?要运行调用任务,必须是要访问队列的最高优先级任务 */
            if( uxSemaphoreCount > ( UBaseType_t ) 0 )
            {
                traceQUEUE_RECEIVE( pxQueue );

                /* Semaphores are queues with a data size of zero and where the
                messages waiting is the semaphore's count.  Reduce the count. */
                /* 信号量是数据大小为零的队列,其中等待的消息是信号量的计数。减少计数 */
                pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1;

                #if ( configUSE_MUTEXES == 1 )
                {
                    if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
                    {
                        /* Record the information required to implement
                        priority inheritance should it become necessary. */
                        /* 如果有必要,记录实现优先级继承所需的信息 */
                        pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
                    }
                    else
                    {
                        mtCOVERAGE_TEST_MARKER();
                    }
                }
                #endif /* configUSE_MUTEXES */

                /* Check to see if other tasks are blocked waiting to give the
                semaphore, and if so, unblock the highest priority such task. */
                /* 检查是否有其他任务在等待发出信号量时被阻塞,如果是,请取消阻止优先级最高的任务 */
                if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
                {
                    if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
                    {
                        queueYIELD_IF_USING_PREEMPTION();
                    }
                    else
                    {
                        mtCOVERAGE_TEST_MARKER();
                    }
                }
                else
                {
                    mtCOVERAGE_TEST_MARKER();
                }

                taskEXIT_CRITICAL();
                return pdPASS;
            }
            else
            {
                if( xTicksToWait == ( TickType_t ) 0 )
                {
                    /* For inheritance to have occurred there must have been an
                    initial timeout, and an adjusted timeout cannot become 0, as
                    if it were 0 the function would have exited. */
                    /* 要使继承发生,必须有一个初始超时,并且调整后的超时不能变为0,如果它为0,函数将退出 */
                    #if( configUSE_MUTEXES == 1 )
                    {
                        configASSERT( xInheritanceOccurred == pdFALSE );
                    }
                    #endif /* configUSE_MUTEXES */

                    /* The semaphore count was 0 and no block time is specified
                    (or the block time has expired) so exit now. */
                    /* 信号量计数为0,并且未指定块时间(或块时间已过期),因此请立即退出 */
                    taskEXIT_CRITICAL();
                    traceQUEUE_RECEIVE_FAILED( pxQueue );
                    return errQUEUE_EMPTY;
                }
                else if( xEntryTimeSet == pdFALSE )
                {
                    /* The semaphore count was 0 and a block time was specified
                    so configure the timeout structure ready to block. */
                    /* 信号量计数为0,并且指定了阻塞时间,因此请配置超时结构以准备阻塞 */
                    vTaskInternalSetTimeOutState( &xTimeOut );
                    xEntryTimeSet = pdTRUE;
                }
                else
                {
                    /* Entry time was already set. */
                    /* 已设置进入时间 */
                    mtCOVERAGE_TEST_MARKER();
                }
            }
        }
        taskEXIT_CRITICAL();

        /* Interrupts and other tasks can give to and take from the semaphore
        now the critical section has been exited. */
        /* 中断和其他任务可以对信号量进行交换,现在关键部分已经退出 */

        vTaskSuspendAll();
        prvLockQueue( pxQueue );

        /* Update the timeout state to see if it has expired yet. */
        /* 更新超时状态以查看它是否已过期 */
        if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
        {
            /* A block time is specified and not expired.  If the semaphore
            count is 0 then enter the Blocked state to wait for a semaphore to
            become available.  As semaphores are implemented with queues the
            queue being empty is equivalent to the semaphore count being 0. */
            /* 块时间已指定且未过期。如果信号量计数为0,则进入阻塞状态,等待信号量变为可用。
               由于信号量是用队列实现的,因此队列为空相当于信号量计数为0 */
            if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
            {
                traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );

                #if ( configUSE_MUTEXES == 1 )
                {
                    if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
                    {
                        taskENTER_CRITICAL();
                        {
                            xInheritanceOccurred = xTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
                        }
                        taskEXIT_CRITICAL();
                    }
                    else
                    {
                        mtCOVERAGE_TEST_MARKER();
                    }
                }
                #endif

                vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
                prvUnlockQueue( pxQueue );
                if( xTaskResumeAll() == pdFALSE )
                {
                    portYIELD_WITHIN_API();
                }
                else
                {
                    mtCOVERAGE_TEST_MARKER();
                }
            }
            else
            {
                /* There was no timeout and the semaphore count was not 0, so
                attempt to take the semaphore again. */
                /* 没有超时,信号量计数不为0,因此请尝试再次获取该信号量 */
                prvUnlockQueue( pxQueue );
                ( void ) xTaskResumeAll();
            }
        }
        else
        {
            /* Timed out. */
            prvUnlockQueue( pxQueue );
            ( void ) xTaskResumeAll();

            /* If the semaphore count is 0 exit now as the timeout has
            expired.  Otherwise return to attempt to take the semaphore that is
            known to be available.  As semaphores are implemented by queues the
            queue being empty is equivalent to the semaphore count being 0. */
            /* 如果信号量计数为0,则立即退出,因为超时已过期。否则返回尝试获取已知可用的信号量。
               由于信号量是由队列实现的,因此队列为空就等于信号量计数为0 */
            if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
            {
                #if ( configUSE_MUTEXES == 1 )
                {
                    /* xInheritanceOccurred could only have be set if
                    pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to
                    test the mutex type again to check it is actually a mutex. */
                    /* 只有当pxQueue->uxQueueType==queueQUEUE_IS_MUTEX时,才能设置xinHeritanceOccurrence,
                       因此无需再次测试互斥体类型以检查它是否是互斥体 */
                    if( xInheritanceOccurred != pdFALSE )
                    {
                        taskENTER_CRITICAL();
                        {
                            UBaseType_t uxHighestWaitingPriority;

                            /* This task blocking on the mutex caused another
                            task to inherit this task's priority.  Now this task
                            has timed out the priority should be disinherited
                            again, but only as low as the next highest priority
                            task that is waiting for the same mutex. */
                            /* 互斥体上的此任务阻塞导致另一个任务继承此任务的优先级。现在这个任务已经超时了,
                               应该再次取消优先级继承,但只能低到等待同一互斥锁的下一个最高优先级任务 */
                            uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue );
                            vTaskPriorityDisinheritAfterTimeout( ( void * ) pxQueue->pxMutexHolder, uxHighestWaitingPriority );
                        }
                        taskEXIT_CRITICAL();
                    }
                }
                #endif /* configUSE_MUTEXES */

                traceQUEUE_RECEIVE_FAILED( pxQueue );
                return errQUEUE_EMPTY;
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }
        }
    }
}

/*

 * xSemaphoreGive

 */

#define xSemaphoreGive( xSemaphore )        xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )

BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition )
{
BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired;
TimeOut_t xTimeOut;
Queue_t * const pxQueue = ( Queue_t * ) xQueue;

    configASSERT( pxQueue );
    configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
    configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
    #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
    {
        configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
    }
    #endif


    /* This function relaxes the coding standard somewhat to allow return
    statements within the function itself.  This is done in the interest
    of execution time efficiency. */
    /* 这个函数在一定程度上放宽了编码标准,允许函数本身内部有返回语句。这是为了提高执行时间效率 */
    for( ;; )
    {
        taskENTER_CRITICAL();
        {
            /* Is there room on the queue now?  The running task must be the
            highest priority task wanting to access the queue.  If the head item
            in the queue is to be overwritten then it does not matter if the
            queue is full. */
            /* 现在排队还有空吗?正在运行的任务必须是要访问队列的最高优先级任务。如果要覆盖队列中的头项,那么队列是否已满并不重要 */
            if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
            {
                traceQUEUE_SEND( pxQueue );
                xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );

                #if ( configUSE_QUEUE_SETS == 1 )
                {
                    if( pxQueue->pxQueueSetContainer != NULL )
                    {
                        if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE )
                        {
                            /* The queue is a member of a queue set, and posting
                            to the queue set caused a higher priority task to
                            unblock. A context switch is required. */
                            /* 队列是队列集的成员,投递到队列集中会导致优先级较高的任务取消阻止。需要上下文切换 */
                            queueYIELD_IF_USING_PREEMPTION();
                        }
                        else
                        {
                            mtCOVERAGE_TEST_MARKER();
                        }
                    }
                    else
                    {
                        /* If there was a task waiting for data to arrive on the
                        queue then unblock it now. */
                        /* 如果有一个任务正在等待数据到达队列,请立即取消阻止它 */
                        if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
                        {
                            if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
                            {
                                /* The unblocked task has a priority higher than
                                our own so yield immediately.  Yes it is ok to
                                do this from within the critical section - the
                                kernel takes care of that. */
                                /* 解除封锁的任务比我们的任务有更高的优先级,所以立刻让步。是的,在临界区内这样做是可以的-内核负责处理这个问题 */
                                queueYIELD_IF_USING_PREEMPTION();
                            }
                            else
                            {
                                mtCOVERAGE_TEST_MARKER();
                            }
                        }
                        else if( xYieldRequired != pdFALSE )
                        {
                            /* This path is a special case that will only get
                            executed if the task was holding multiple mutexes
                            and the mutexes were given back in an order that is
                            different to that in which they were taken. */
                            /* 此路径是一种特殊情况,只有当任务持有多个互斥锁,并且互斥锁的返回顺序与它们的获取顺序不同时,才会执行该路径 */
                            queueYIELD_IF_USING_PREEMPTION();
                        }
                        else
                        {
                            mtCOVERAGE_TEST_MARKER();
                        }
                    }
                }
                #else /* configUSE_QUEUE_SETS */
                {
                    /* If there was a task waiting for data to arrive on the
                    queue then unblock it now. */
                    /* 如果有一个任务正在等待数据到达队列,请立即取消阻止它 */
                    if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
                    {
                        if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
                        {
                            /* The unblocked task has a priority higher than
                            our own so yield immediately.  Yes it is ok to do
                            this from within the critical section - the kernel
                            takes care of that. */
                            /* 解除封锁的任务比我们的任务有更高的优先级,所以立刻让步。是的,在临界区内这样做是可以的-内核负责处理这个问题 */
                            queueYIELD_IF_USING_PREEMPTION();
                        }
                        else
                        {
                            mtCOVERAGE_TEST_MARKER();
                        }
                    }
                    else if( xYieldRequired != pdFALSE )
                    {
                        /* This path is a special case that will only get
                        executed if the task was holding multiple mutexes and
                        the mutexes were given back in an order that is
                        different to that in which they were taken. */
                        /* 此路径是一种特殊情况,只有当任务持有多个互斥锁,并且互斥锁的返回顺序与它们的获取顺序不同时,才会执行该路径 */
                        queueYIELD_IF_USING_PREEMPTION();
                    }
                    else
                    {
                        mtCOVERAGE_TEST_MARKER();
                    }
                }
                #endif /* configUSE_QUEUE_SETS */

                taskEXIT_CRITICAL();
                return pdPASS;
            }
            else
            {
                if( xTicksToWait == ( TickType_t ) 0 )
                {
                    /* The queue was full and no block time is specified (or
                    the block time has expired) so leave now. */
                    /* 队列已满,未指定块时间(或块时间已过期),请立即离开 */
                    taskEXIT_CRITICAL();

                    /* Return to the original privilege level before exiting
                    the function. */
                    /* 在退出函数之前返回到原始权限级别 */
                    traceQUEUE_SEND_FAILED( pxQueue );
                    return errQUEUE_FULL;
                }
                else if( xEntryTimeSet == pdFALSE )
                {
                    /* The queue was full and a block time was specified so
                    configure the timeout structure. */
                    /* 队列已满,并且指定了块时间,因此请配置超时结构 */
                    vTaskInternalSetTimeOutState( &xTimeOut );
                    xEntryTimeSet = pdTRUE;
                }
                else
                {
                    /* Entry time was already set. */
                    /* 已设置进入时间 */
                    mtCOVERAGE_TEST_MARKER();
                }
            }
        }
        taskEXIT_CRITICAL();

        /* Interrupts and other tasks can send to and receive from the queue
        now the critical section has been exited. */
        /* 中断和其他任务可以发送到队列或从队列接收,现在关键部分已经退出 */

        vTaskSuspendAll();
        prvLockQueue( pxQueue );

        /* Update the timeout state to see if it has expired yet. */
        /* 更新超时状态以查看它是否已过期 */
        if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
        {
            if( prvIsQueueFull( pxQueue ) != pdFALSE )
            {
                traceBLOCKING_ON_QUEUE_SEND( pxQueue );
                vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );

                /* Unlocking the queue means queue events can effect the
                event list.  It is possible that interrupts occurring now
                remove this task from the event list again - but as the
                scheduler is suspended the task will go onto the pending
                ready last instead of the actual ready list. */
                /* 解锁队列意味着队列事件可以影响事件列表。现在发生的中断可能会再次将此任务从事件列表中删除-但是由于调度程序被挂起,
                   任务将转到挂起的就绪最后一个,而不是实际的就绪列表 */
                prvUnlockQueue( pxQueue );

                /* Resuming the scheduler will move tasks from the pending
                ready list into the ready list - so it is feasible that this
                task is already in a ready list before it yields - in which
                case the yield will not cause a context switch unless there
                is also a higher priority task in the pending ready list. */
                /* 恢复调度程序会将任务从挂起的就绪列表移动到就绪列表中—因此,此任务在其生成之前已经在就绪列表中是可行的—在这种情况下,
                   除非挂起的就绪列表中还有更高优先级的任务,否则产生的结果不会导致上下文切换 */
                if( xTaskResumeAll() == pdFALSE )
                {
                    portYIELD_WITHIN_API();
                }
            }
            else
            {
                /* Try again. */
                prvUnlockQueue( pxQueue );
                ( void ) xTaskResumeAll();
            }
        }
        else
        {
            /* The timeout has expired. */
            /* 超时已过期 */
            prvUnlockQueue( pxQueue );
            ( void ) xTaskResumeAll();

            traceQUEUE_SEND_FAILED( pxQueue );
            return errQUEUE_FULL;
        }
    }
}

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

Freertos代码之互斥信号量 的相关文章

  • FreeRTOS config开始的宏

    FreeRTOSConfig h系统配置文件中可以自定义 FreeRTOS h中定义默认值 configAPPLICATION ALLOCATED HEAP 默认情况下FreeRTOS的堆内存是由编译器来分配的 将宏configAPPLIC
  • 一文教你学会keil软件仿真

    仿真在我们调试代码中是非常重要的 通过仿真 我们可以快速定位到错误代码 或者错误逻辑的地方 这里我就以上一篇博客为例 教大家如何软件仿真 软件仿真不需要单片机 直接通过keil软件进行代码调试 一 打开工具 二 选择软件仿真 三 开始仿真
  • FreeRTOS系列

    本文主要介绍如何在任务或中断中向队列发送消息或者从队列中接收消息 使用STM32CubeMX将FreeRTOS移植到工程中 创建两个任务以及两个消息队列 并开启两个中断 两个任务 Keyscan Task 读取按键的键值 并将键值发送到队列
  • ZYNQ中FreeRTOS中使用定时器

    使用普通的Timer中断方式时 Timer中断可以正常运行 但是UDP通信进程无法启动 其中TimerIntrHandler是中断服务程序 打印程序运行时间与从BRAM中读取的数据 void SetupInterruptSystem XSc
  • 【FreeRTOS(三)】任务状态

    文章目录 任务状态 任务挂起 vTaskSuspend 取消任务挂起 vTaskResume 挂起任务调度器 vTaskSuspendAll 取消挂起任务调度器 xTaskResumeAll 代码示例 任务挂起 取消任务挂起 代码示例 挂起
  • FreeRTOS临界段和开关中断

    http blog sina com cn s blog 98ee3a930102wg5u html 本章教程为大家讲解两个重要的概念 FreeRTOS的临界段和开关中断 本章教程配套的例子含Cortex M3内核的STM32F103和Co
  • STM32F103移植FreeRTOS必须搞明白的系列知识---2(FreeRTOS任务优先级)

    STM32F103移植FreeRTOS必须搞明白的系列知识 1 Cortex CM3中断优先级 STM32F103移植FreeRTOS必须搞明白的系列知识 2 FreeRTOS任务优先级 STM32F103移植FreeRTOS必须搞明白的系
  • FreeRTOS,串口中断接收中使用xQueueOverwriteFromISR()函数,程序卡死在configASSERT

    原因 UART的中断优先级设置的太高 高于了configMAX SYSCALL INTERRUPT PRIORITY宏定义的安全中断等级 UART的中断等级小于等于宏定义的优先等级即可
  • stm32f103zet6移植标准库的sdio驱动

    sdio移植 st官网给的标准库有给一个用于st出的评估板的sdio外设实现 但一是文件结构有点复杂 二是相比于国内正点原子和野火的板子也有点不同 因此还是需要移植下才能使用 当然也可以直接使用正点原子或野火提供的实例 但为了熟悉下sdio
  • FreeRTOS笔记(一)简介

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

    介绍 适用于STM32F103C8的FreeRTOS STM32F103C是一种能够使用FreeRTOS的ARM Cortex M3处理器 我们直接在Arduino IDE中开始使用STM32F103C8的FreeRTOS 我们也可以使用K
  • FreeRTOS学习笔记(8)---- 软件定时器

    使用FreeRTOS软件定时器需要在文件FreeRTOSConfig h先做如下配置 1 configUSE TIMERS 使能软件定时器 2 configTIMER TASK PRIORITY 定时器任务优先级 3 configTIMER
  • FreeRTOS死机原因

    1 中断回调函数中没有使用中断级API xxFromISR 函数 xSemaphoreGiveFromISR uart busy HighterTask 正确 xSemaphoreGive uart busy 错误 2 比configMAX
  • 单片机通信数据延迟问题排查

    1 问题说明 笔者在最近的项目中 发现系统的响应延迟较高 经过排查 排除了单片机运行卡死的问题 2 原因分析 具体排查过程这里就不细致说明了 直接给出排查后原因 任务执行周期规划不合理 导致freertos队列发送接收到的命令有延迟 为了便
  • 13-FreeRTOS任务创建与删除

    任务创建和删除API函数位于文件task c中 需要包含task h头文件 task h里面包函数任务的类型函数 例如 对xTaskCreate的调用 通过指针方式 返回一个TaskHandle t 变量 然后可将该变量用vTaskDele
  • FreeRTOSConfig.h 配置优化及深入

    本篇目标 基于上一篇的移植freertos stm32f4 freertos 上 修改 FreeRTOSConfig h 文件的相关配置来优化辅助 FreeRtos 的使用 并且建立一些基本功能 信号量 消息地列等 的简单应用位于 stm3
  • FreeRTOS 配置TICK_RATE_HZ

    我使用的是带有 5 4 版 FreeRTOS 的 MSP430f5438 我有一个有趣的问题 我无法弄清楚 基本上 当我将 configTICK RATE HZ 设置为不同的值时 LED 闪烁得更快或更慢 它应该保持相同的速率 我将 con
  • 当一个任务写入变量而其他任务读取该变量时,我们是否需要信号量?

    我正在研究 freeRtos 并且我有一个名为 x 的变量 现在 每秒只有一个任务正在写入该变量 而其他任务正在读取该变量值 我需要用互斥锁来保护变量吗 如果变量为 32 位或更小 并且其值是独立的并且不与任何其他变量一起解释 则不需要互斥
  • 如何将 void* 转换为函数指针?

    我在 FreeRTOS 中使用 xTaskCreate 其第四个参数 void const 是传递给新线程调用的函数的参数 void connect to foo void const task params void on connect
  • FreeRTOS 匈牙利表示法 [重复]

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

随机推荐

  • 二重积分和雅可比行列式

    我们以二重积分为例进行说明 xff0c 首先说结论 xff1a 一 结论 若x 61 x u v y 61 y u v 存在偏导数 xff0c 则二阶雅可比行列式为 61 61 dxdy 61 J2 dudv J2的绝对值 且 其中积分区域
  • 雅可比行列式和雅可比矩阵

    接触雅可比行列式是在二重积分的变量变换中 xff0c 参见我的另一篇文章https blog csdn net xiaoyink article details 88432372 下面我们来详细说明一下雅可比行列式和雅可比矩阵 雅可比矩阵
  • jlink-v8 固件修复

    一 先说 jlink v8 v9 v10区别 v8基本价格在40左右 xff0c 芯片是atml的 xff0c 但是很多反应是掉固件和提示盗版问题 v9现在主流 xff0c 盗版价100左右 xff0c 主控芯片stm32 做的比较成熟 x
  • kubernetes学习-快速上手速查手册

    目录 使用k3s快速搭建k8s安装k8s dashboard使用Helm部署K8S资源k8s核心命令一切推倒重来资源创建方式NamespacePodDeploymentServiceIngress解决官网Ingress安装不了问题使用方式
  • 作为一个4年程序员至少需要掌握的专业技能

    一名3年工作经验的程序员应该具备的技能 xff0c 在机缘巧合之中 xff0c 看了这篇博客 感觉自己真的是很差 xff0c 一直想着会写if else 就已经是一名程序员了 xff0c 在工作之余也很少学习 于是 xff0c 自己的cod
  • C语言与C++的区别

    一 C 43 43 简介 本贾尼 斯特劳斯特鲁普 于1979年4月在贝尔实验室负责分析UNIX系统的内核的流量情况 于1979年10月开始着手开发一种新的编程语言 在C语言的基础上增加了面向对象机制 这就是C 43 43 的来历 在1983
  • 我的2011-当梦想照进现实

    我的2011年 xff0c 之所以是现在的样子 xff0c 始缘于我三年前的一个决定 离职考研 对于工作了两年的我来说 xff0c 离职考研是人生的一场博弈 我的2011年 xff0c 结束了研究生期间对三维骨骼动画渲染的相关研究 xff0
  • Dockerfile RUN 同时执行多条命令

    Dockerfile RUN 同时执行多条命令 Dokcerfile中的命令每执行一条即产生一个新的镜像 xff0c 当前命令总是在最新的镜像上执行 如下Dockerfile xff1a RUN span class hljs built
  • HC-SR04超声波模块使用记录

    文章目录 HC SR04超声波模块使用记录轮询测量方式一 模块使用中的问题二 应对方法三 注意 分时测量利用输入捕获测量利用输入捕获测量 HC SR04超声波模块使用记录 具体使用方法见HC SR04使用手册 xff0c 本文重点记录该模块
  • 【C语言冒泡排序、选择排序和快速排序】

    文章目录 前言一 冒泡排序二 选择排序三 快速排序四 代码设计与实现代码设计代码实现 调试结果冒泡排序改良 延伸思考总结 前言 本文简单介绍了C语言的冒泡排序 选择排序 快速排序 xff0c 结合本人的理解与使用做一下记录 一 冒泡排序 思
  • 平衡车制作---原理篇

    平衡车制作 原理篇 文章目录 平衡车制作 原理篇前言直立控制直观感受内部机理 速度控制方向控制总结 前言 本篇教程内容主要来自于 直立平衡车模参考设计方案 xff0c 且这里是从概念层面讲述的并没有具体的控制理论方面的内容 有了这些概念方面
  • FreeRTOS使用注意

    FreeRTOS使用注意 xff1a 中断中必须使用带FromISR结尾的API函数只有中断优先级处于FreeRTOS可管理的范围内时 xff0c 才能使用FreeRTOS提供的API函数中断中不要使用FreeRTOS提供的内存申请和释放函
  • 现代控制理论基础总结

    现代控制理论基础总结 xff08 线性部分 xff09 学习现代控制理论也有两个月的时间了 xff0c 里面涉及的基础内容和公式十分之多 xff0c 所以现在对各部分基础知识作一个总结 1 控制系统的状态表达式 在现代控制理论中 xff0c
  • 题库(关于c++的网站都盘了)大盘点(好多没盘到)

    1 keda ac 2 hydro ac 3 luogu com cn 4 cplusplus com 5 leetcode cn 6 https loj ac 7 noi cn 8 ybt ssoier cn 8088 9 learncp
  • 利用MapReduce进行二次排序--附例子

    首先先来明确几个概念 xff1a 1 分区 partition 1 xff09 分区 xff08 partition xff09 xff1a 默认采取散列值进行分区 xff0c 但此方法容易造成 数据倾斜 xff08 大部分数据分到同一个r
  • MapReduce之单表关联Join输出祖父母、孙子---(附例子)

    需求 xff1a 一个文件 xff0c 有子女和对应的父母 xff0c 要求输出 祖父母 孙子 xff0c 文件如下 xff1a 单表关联 结果 xff1a child parent grand child Tom Lucy Alice T
  • 如何把 ubuntu 16.04.7 命令行界面下的系统语言更改为中文?

    如果你的 ubuntu 16 04 7 系统在命令行下的默认语言是英文 xff0c 比如下面这样 xff1a 怎么更改才能让某些输出单词显示成中文呢 xff1f 可以修改 etc default locale 这个文件 xff0c 先看一下
  • 小程序云开发实现订阅消息

    链接 简书博主示例 xff1a https www jianshu com p d90f22dac001 官方文档 xff1a 官方文档1 文档2 云调用 使用方法demo 假如这是一个点餐系统 xff0c 想让顾客下单以后 xff0c 派
  • ue4 常见问题解答

    1 如何让客户端自动连接服务器 span style color 0000aa MyGame span span style color 000066 span span style color 000066 exe span span s
  • Freertos代码之互斥信号量

    信号量用于限制对共享资源的访问和多任务之间的同步 三个信号量API函数都是宏 xff0c 使用现有的队列实现 使用例子 typedef void QueueHandle t typedef QueueHandle t SemaphoreHa