再读 ucosII源码(邵贝贝):任务之间的通讯与同步--邮箱

2023-05-16

邮箱简介:

邮箱是µC/OS-II中另一种通讯机制,它可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量。
该指针指向一个包含了特定“消息”的数据结构。为了在µC/OS-II中使用邮箱,必须将OS_CFG.H中的OS_MBOX_EN常数置为1。
使用邮箱之前,必须先建立该邮箱。
该操作可以通过调用OSMboxCreate()函数来完成,并且要指定指针的初始值。
一般情况下,这个初始值是NULL,但也可以初始化一个邮箱,使其在最开始就包含一条消息。
如果使用邮箱的目的是用来通知一个事件的发生(发送一条消息),那么就要初始化该邮箱为NULL,因为在开始时,事件还没有发生。
如果用户用邮箱来共享某些资源,那么就要初始化该邮箱为一个非NULL的指针。在这种情况下,邮箱被当成一个二值信号量使用
µC/OS-II提供了5种对邮箱的操作:OSMboxCreate(),OSMboxPend(),OSMboxPost(),OSMboxAccept()和OSMboxQuery()函数。图 F6.6描述了任务、中断服务子程序和邮箱之间的关系,这里用符号“I”表示邮箱。邮箱包含的内容是一个指向一条消息的指针。一个邮箱只能包含一个这样的指针(邮箱为满时),或者一个指向NULL的指针(邮箱为空时)。从图 F6.6可以看出,任务或者中断服务子程序可以调用函数OSMboxPost()或OSMboxAccept(),但是只有任务可以调用函数OSMboxPend()和OSMboxQuery()。
这里写图片描述

建立一个邮箱,OSMboxCreate()

程序清单 L6.14是OSMboxCreate()函数的源代码,基本上和函数OSSemCreate()相似。不同之处在于事件控制块的类型被设置成OS_EVENT_TYPE_MBOX[L6.14(1)],以及使用.OSEventPtr域来容纳消息指针,而不是使用.OSEventCnt域[L6.14(2)]。
OSMboxCreate()函数的返回值是一个指向事件控制块的指针[L6.14(3)]。这个指针在调用函数OSMboxPend(),OSMboxPost(),OSMboxAccept()和OSMboxQuery()时使用。因此,该指针可以看作是对应邮箱的句柄。
值得注意的是,如果系统中已经没有事件控制块可用,函数OSMboxCreate()将返回一个NULL指针。
邮箱一旦建立,是不能被删除的。比如,如果有任务正在等待一个邮箱的信息,这时删除该邮箱,将有可能产生灾难性的后果。
程序清单 L6.14 建立一个邮箱

OS_EVENT *OSMboxCreate (void *msg)
{
    OS_EVENT *pevent;


    OS_ENTER_CRITICAL();
    pevent = OSEventFreeList;
    if (OSEventFreeList != (OS_EVENT *)0) {
        OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
    }
    OS_EXIT_CRITICAL();
    if (pevent != (OS_EVENT *)0) {
        pevent->OSEventType = OS_EVENT_TYPE_MBOX;                       (1)
        pevent->OSEventPtr  = msg;                                     (2)
        OSEventWaitListInit(pevent);
    }
    return (pevent);                                                     (3)
}

等待一个邮箱中的消息,OSMboxPend()

程序清单 L6.15是OSMboxPend()函数的源代码。
同样,它和OSSemPend()也很相似,因此,在这里只讲述其中的不同之处。
OSMboxPend()首先检查该事件控制块是由OSMboxCreate()函数建立的[L6.15(1)]。
当.OSEventPtr域是一个非NULL的指针时,说明该邮箱中有可用的消息[L6.15(2)]。这种情况下,OSMboxPend()函数将该域的值复制到局部变量msg中,然后将.OSEventPtr置为NULL[L6.15(3)]。这正是我们所期望的,也是执行OSMboxPend()函数最快的路径。
如果此时邮箱中没有消息是可用的(.OSEventPtr域是NULL指针),OSMboxPend()函数检查它的调用者是否是中断服务子程序[L6.15(4)]。象OSSemPend()函数一样,不能在中断服务子程序中调用OSMboxPend(),因为中断服务子程序是不能等待的。这里的代码同样是为了以防万一。但是,如果邮箱中有可用的消息,即使从中断服务子程序中调用OSMboxPend()函数,也一样是成功的。

如果邮箱中没有可用的消息,OSMboxPend()的调用任务就被挂起,直到邮箱中有了消息或者等待超时[L6.15(5)]。

当有其它的任务向该邮箱发送了消息后(或者等待时间超时),这时,该任务再一次成为最高优先级任务,OSSched()返回。
这时,OSMboxPend()函数要检查是否有消息被放到该任务的任务控制块中[L6.15(6)]。如果有,那么该次函数调用成功,对应的消息被返回到调用函数。
程序清单 L6.15 等待一个邮箱中的消息

void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
    void  *msg;

    OS_ENTER_CRITICAL();
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {                  (1)
        OS_EXIT_CRITICAL();
        *err = OS_ERR_EVENT_TYPE;
        return ((void *)0);
    }
    msg = pevent->OSEventPtr;
    if (msg != (void *)0) {                                        (2)
        pevent->OSEventPtr = (void *)0;                            (3)
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
    } else if (OSIntNesting > 0) {                                  (4)
        OS_EXIT_CRITICAL();
        *err = OS_ERR_PEND_ISR;
    } else {
        OSTCBCur->OSTCBStat |= OS_STAT_MBOX;                          (5)
        OSTCBCur->OSTCBDly   = timeout;
        OSEventTaskWait(pevent);
        OS_EXIT_CRITICAL();
        OSSched();
        OS_ENTER_CRITICAL();
        if ((msg = OSTCBCur->OSTCBMsg) != (void *)0) {              (6)
            OSTCBCur->OSTCBMsg      = (void *)0;
            OSTCBCur->OSTCBStat     = OS_STAT_RDY;
            OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
            OS_EXIT_CRITICAL();
            *err                    = OS_NO_ERR;
        } else if (OSTCBCur->OSTCBStat & OS_STAT_MBOX) {              (7)
            OSEventTO(pevent);                                      (8)
            OS_EXIT_CRITICAL();
            msg                     = (void *)0;                      (9)
            *err                    = OS_TIMEOUT;
        } else {
            msg                     = pevent->OSEventPtr;           (10)
            pevent->OSEventPtr      = (void *)0;                            (11)
            OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;                 (12)
            OS_EXIT_CRITICAL();
            *err                    = OS_NO_ERR;
        }
    }
    return (msg);
}

在OSMboxPend()函数中,通过检查任务控制块中的.OSTCBStat域中的OS_STAT_MBOX位,可以知道是否等待超时。如果该域被置1,说明任务等待已经超时[L6.15(7)]。这时,通过调用函数OSEventTo()可以将任务从邮箱的等待列表中删除[L6.15(8)]。
因为此时邮箱中没有消息,所以返回的指针是NULL[L6.15(9)]。
如果OS_STAT_MBOX位没有被置1,说明所等待的消息已经被发出。OSMboxPend()的调用函数得到指向消息的指针[L6.15(10)]。此后,OSMboxPend()函数通过将邮箱事件控制块的.OSEventPtr域置为NULL清空该邮箱,并且要将任务任务控制块中指向邮箱事件控制块的指针删除[L6.15(12)]。

发送一个消息到邮箱中,OSMboxPost()

程序清单 L6.16是OSMboxPost()函数的源代码。
检查了事件控制块是否是一个邮箱后[L6.16(1)],
OSMboxPost()函数还要检查是否有任务在等待该邮箱中的消息[L6.16(2)]。
如果事件控制块中的OSEventGrp域包含非零值,就暗示着有任务在等待该消息。
这时,调用OSEventTaskRdy()将其中的最高优先级任务从等待列表中删除[见6.02节,使一个任务进入就绪状态,OSEventTaskRdy()][L6.16(3)],加入系统的就绪任务列表中,准备运行。
然后,调用OSSched()函数[L6.16(4)],检查刚刚取出的任务是否是系统中最高优先级的就绪任务。
如果是,执行任务切换[仅当OSMboxPost()函数是由任务调用时],该任务得以执行。
如果该任务不是最高优先级的任务,OSSched()返回,OSMboxPost()的调用函数继续执行。
如果没有任何任务等待该消息,指向消息的指针就被保存到邮箱中[L6.16(6)](假设此时邮箱中的指针是NULL的[L6.16(5)])。这样,下一个调用OSMboxPend()函数的任务就可以立刻得到该消息了。
注意,如果OSMboxPost()函数是从中断服务子程序中调用的,那么,这时并不发生上下文的切换。如果需要,中断服务子程序引起的上下文切换只发生在中断嵌套的最外层中断服务子程序对OSIntExit()函数的调用时(见3.09节,µC/OS-II中的中断)。

程序清单 L6.16 向邮箱中发送一条消息

INT8U OSMboxPost (OS_EVENT *pevent, void *msg)
{
    OS_ENTER_CRITICAL();
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {                 (1)
        OS_EXIT_CRITICAL();
        return (OS_ERR_EVENT_TYPE);
    }
    if (pevent->OSEventGrp) {                                       (2)
        OSEventTaskRdy(pevent, msg, OS_STAT_MBOX);                 (3)
        OS_EXIT_CRITICAL();
        OSSched();                                                 (4)
        return (OS_NO_ERR);
    } else {
        if (pevent->OSEventPtr != (void *)0) {                     (5)
            OS_EXIT_CRITICAL();
            return (OS_MBOX_FULL);
        } else {
            pevent->OSEventPtr = msg;                               (6)
            OS_EXIT_CRITICAL();
            return (OS_NO_ERR);
        }
    }
}

无等待地从邮箱中得到一个消息, OSMboxAccept()

应用程序也可以以无等待的方式从邮箱中得到消息。
这可以通过程序清单 L6.17中的OSMboxAccept()函数来实现。
OSMboxAccept()函数开始也是检查事件控制块是否是由OSMboxCreate()函数建立的 [L6.17(1)]。
接着,它得到邮箱中的当前内容[L6.17(2)],
并判断是否有消息是可用的[L6.17(3)]。
如果邮箱中有消息,就把邮箱清空[L6.17(4)],而邮箱中原来指向消息的指针被返回给OSMboxAccept()的调用函数[L6.17(5)]。
OSMboxAccept()函数的调用函数必须检查该返回值是否为NULL。
如果该值是NULL,说明邮箱是空的,没有可用的消息。
如果该值是非NULL值,说明邮箱中有消息可用,而且该调用函数已经得到了该消息。
中断服务子程序在试图得到一个消息时,应该使用OSMboxAccept()函数,而不能使用OSMboxPend()函数。
OSMboxAccept()函数的另一个用途是,用户可以用它来清空一个邮箱中现有的内容。

程序清单 L6.17 无等待地从邮箱中得到消息

void *OSMboxAccept (OS_EVENT *pevent)
{
    void  *msg;


    OS_ENTER_CRITICAL();
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {             (1)
        OS_EXIT_CRITICAL();
        return ((void *)0);
    }
    msg = pevent->OSEventPtr;                                   (2)
    if (msg != (void *)0) {                                   (3)
        pevent->OSEventPtr = (void *)0;                       (4)
    }
    OS_EXIT_CRITICAL();
    return (msg);                                               (5)
}

查询一个邮箱的状态, OSMboxQuery()

OSMboxQuery()函数使应用程序可以随时查询一个邮箱的当前状态。
程序清单 L6.18是该函数的源代码。
它需要两个参数:
一个是指向邮箱的指针pevent。该指针是在建立该邮箱时,由OSMboxCreate()函数返回的;
另一个是指向用来保存有关邮箱的信息的OS_MBOX_DATA(见uCOS_II.H)数据结构的指针pdata。
在调用OSMboxQuery()函数之前,必须先定义该结构变量(OS_MBOX_DATA),用来保存有关邮箱的信息。
之所以定义一个新的数据结构,是因为这里关心的只是和特定邮箱有关的内容,而非整个OS_EVENT数据结构的内容。后者还包含了另外两个域(.OSEventCnt和.OSEventType),而OS_MBOX_DATA只包含邮箱中的消息指针(.OSMsg)和该邮箱现有的等待任务列表(.OSEventTbl[]和.OSEventGrp)。
和前面的所以函数一样,该函数也是先检查事件控制是否是邮箱[L6.18(1)]。然后,将邮箱中的等待任务列表[L6.18(2)]和邮箱中的消息[L6.18(3)]从OS_EVENT数据结构复制到OS_MBOX_DATA数据结构。
程序清单 L6.18 查询邮箱的状态

INT8U OSMboxQuery (OS_EVENT *pevent, OS_MBOX_DATA *pdata)
{
    INT8U  i;
    INT8U *psrc;
    INT8U *pdest;

    OS_ENTER_CRITICAL();
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {             (1)
        OS_EXIT_CRITICAL();
        return (OS_ERR_EVENT_TYPE);
    }
    pdata->OSEventGrp = pevent->OSEventGrp;                   (2)
    psrc              = &pevent->OSEventTbl[0];
    pdest             = &pdata->OSEventTbl[0];
    for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {
        *pdest++ = *psrc++;
    }
    pdata->OSMsg      = pevent->OSEventPtr;                   (3)
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);
}

使用:

用邮箱作二值信号量

一个邮箱可以被用作二值的信号量。
首先,在初始化时,将邮箱设置为一个非零的指针(如 void *1)。
这样,一个任务可以调用OSMboxPend()函数来请求一个信号量,
然后通过调用OSMboxPost()函数来释放一个信号量。
程序清单 L6.19说明了这个过程是如何工作的。
如果用户只需要二值信号量和邮箱,这样做可以节省代码空间。这时可以将OS_SEM_EN设置为0,只使用邮箱就可以了。
程序清单 L6.19 使用邮箱作为二值信号量:

OS_EVENT *MboxSem;


void Task1 (void *pdata)
{
    INT8U err;

    for (;;) {
        OSMboxPend(MboxSem, 0, &err);   /* 获得对资源的访问权  */
        .
        .    /* 任务获得信号量,对资源进行访问  */
        .
        OSMboxPost(MboxSem, (void*)1);  /* 释放对资源的访问权 */
    }
}

用邮箱实现延时,而不使用OSTimeDly()

邮箱的等待超时功能可以被用来模仿OSTimeDly()函数的延时,如程序清单 L6.20所示。
如果在指定的时间段TIMEOUT内,没有消息到来,Task1()函数将继续执行。
这和OSTimeDly(TIMEOUT)功能很相似。
但是,如果Task2()在指定的时间结束之前,向该邮箱发送了一个“哑”消息,Task1()就会提前开始继续执行。
这和调用OSTimeDlyResume()函数的功能是一样的。注意,这里忽略了对返回的消息的检查,因为此时关心的不是得到了什么样的消息。
程序清单 L6.20 使用邮箱实现延时

OS_EVENT *MboxTimeDly;


void Task1 (void *pdata)
{
    INT8U err;


    for (;;) {
        OSMboxPend(MboxTimeDly, TIMEOUT, &err);   /* 延时该任务 */
        .
        .    /* 延时结束后执行的代码  */
        .
    }
}


void Task2 (void *pdata)
{
    INT8U err;


    for (;;) {
        OSMboxPost(MboxTimeDly, (void *)1);       /* 取消任务1的延时 */
        .
        .
    }
}

疑问:

1、在调用OSMboxCreate()函数之前,必须先定义该结构变量(OS_MBOX_DATA),用来保存有关邮箱的信息。

显然,没什么必然关系。是该书的笔误,应该如下:
在调用OSMboxQuery()函数之前,必须先定义该结构变量(OS_MBOX_DATA),用来保存有关邮箱的信息。

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

再读 ucosII源码(邵贝贝):任务之间的通讯与同步--邮箱 的相关文章

  • UCOSII中的任务切换原理介绍

    1 多任务的引入 之所以引入多任务 xff0c 主要在于提高程序运行的效率 多任务的过程 xff0c 能够有效地发挥交换式任务的运作效率 类似的 xff0c 由于一个任务里面也有瓶颈的地方 xff0c 为了把瓶颈的地方抠出来 xff0c 让
  • UCOSII学习---五、任务通信之信号量

    一 xff1a 信号量的理解 xff1a 信号量的本质是数据操作锁 xff0c 它本身不具有数据交换的功能 xff0c 而是通过控制其他的通信资源 xff08 文件 xff0c 外部设备 xff09 来实现进程间通信 xff0c 它本身只是
  • stm32 ucosii消息队列 串口_UC/OSII消息队列、信号量集和软件定时器

    UCOSII消息队列 信号量集和软件定时器简介 上一章 xff0c 我们介绍了信号量和邮箱的使用 xff0c 本章我们介绍比较复杂消息队列 信号量集以及软件定时器的使用 消息队列 使用消息队列可以在任务之间传递多条消息 消息队列由三个部分组
  • ucosii使用

    当需要同时跑多个任务的时候裸机显然不能很好的完成使命 xff0c 这个时候我们可以给单片机上系统 xff0c 创建多任务 xff0c 完成复杂逻辑 一 首先移植uocii在我们的板上 xff0c 根据mcu型号移植ucosii xff0c
  • UCOSII-信号量与信号量集

    文章目录 一 前言1 任务间的同步2 事件 二 信号量1 信号与信号量介绍2 信号量常用函数3 信号量使用流程 xff08 互斥信号量和信号量两种 xff09 4 互斥型信号量使用5 使用一般信号量做任务同步 三 信号量集 事件标志组 1
  • UCOSII-消息邮箱与消息队列

    文章目录 一 事件控制块及事件处理函数1 等待任务列表2 事件控制块的结构3 操作事件控制块的函数4 空事件控制块列表 二 消息邮箱1 消息邮箱介绍2 消息邮箱操作步骤 三 消息队列1 消息指针数组2 队列控制块3 消息队列的操作流程 四
  • STM32上使用UCOSII--消息队列和信号量集

    有关UCOS任务的介绍 xff1a STM32上使用UCOSII 任务 有关UCOS信号量和邮箱的介绍 xff1a STM32上使用UCOSII 信号量和邮箱 一 消息队列 使用消息队列可以在任务之间传递多条消息 消息队列由三个部分组成 x
  • ucosii消息队列学习

    近期在学习ucosii的内容使用的平台为STM32F103C8T6最小系统板 今日关于消息队列的使用遇到了一些问题 基本情况 xff1a 移植代码为正点原子ucosiii消息队列 信号量集和软件定时器例程 主要新建两个任务post task
  • UCOSII 消息队列、信号量集、软件定时器

    1 消息队列 xff1a 作用 xff1a 在任务之间传递多条信息 组成 xff1a 事件控制块 消息队列 消息 消息队列数据结构 队列控制块的结构定义 xff1a typedef struct os q struct os q OSQPt
  • Ucosii消息邮箱使用

    设置任务优先级 define LED TASK Prio 6 define LED1 TASK Prio 5 用到的UCOSII函数 消息邮箱创建函数 xff1a OS EVENT OSMboxCreate void msg 请求消息邮箱函
  • ucosii消息队列使用

    ucosii消息队列简介 ucosii的消息队列源码定义在os q c文件 xff1b 接口全部声明在ucos ii h xff0c 总共有如下接口 xff1a span class token keyword void span span
  • rtthrea-ucosii-freertos三系统学习总结

    三系统基本功能对比 RT thread ucosii freertos 任务调度 抢占式 时间片式 xff08 多级队列位图调度 xff09 抢占式 xff08 纯位图调度 xff09 抢占式 时间片式 xff08 遍历列表调度 xff09
  • UCOSII 使用笔记

    UCOS使用总结 1 UCOS 是抢占式系统 xff0c 换句话来说 xff0c 优先级高的能够被准时执行 xff0c 优先级低的很容易被高优先级抢占 xff0c 导致执行任务延迟 2 UCOS一般为64个优先级 xff0c 有些可以到25
  • 从零开始学习UCOSII操作系统7--信号量

    从零开始学习UCOSII操作系统7 信号量 参考博客 xff1a 64 http blog csdn net gatiemehttps blog csdn net gatieme article details 21071379 前言 xf
  • 从零开始学习UCOSII操作系统15--总结篇

    从零开始学习UCOSII操作系统15 总结篇 前言 xff1a 在大学的时候 xff0c 我们班级上面都有很多人觉得学习UCOSII 包括UCOSIII 是没什么厉害的 xff0c 因为很多人都喜欢去学习Linux操作系统 xff0c 但是
  • ucosII 信号量使用总结(举例讲解)

    概述 信号量用于 xff1a 1 控制共享资源的使用权 xff08 满足互斥条件 xff09 2 标志某时间的发生 3 使2个任务的行为同步 OSSemCreate 赋初值 OSSemCreate INT16U cnt xff0c cnt为
  • UCOSII 信号量和信号量集实例

    代码来自于书本光盘 嵌入式操作系统UCOSII原理及应用 实例1信号量 include 34 includes h 34 define TASK STK SIZE 512 任务堆栈长度 OS STK StartTaskStk TASK ST
  • UCOSII里面为什么调用OS_ENTER_CRITICAL()或OS_EXIT_CRITICAL()会出错,出错信息为:undeclared identifier `cpu_sr‘

    可以观察到OSTickISR Init 函数内部调用了OS ENTER CRITICAL 和OS EXIT CRITICAL 并且 1 该OSTickISR Init 函数所在的 C文件包含了includes h文件 include inc
  • stm32 ucos/ii移植,程序执行到OSStart()内部的OSStartHighRdy()语句时跑飞问题解决方法之一

    stm32 ucos ii移植 程序执行到OSStart 内部的OSStartHighRdy 语句时跑飞问题解决办法之一 网络上的一些解决办法 stm32程序遇到OSStartHang的问题解决方法总结 但并不适合我遇到的情况 我的情况是已
  • os_mutex.c(全)

    无等待地获取互斥型信号量 OSMutexAccept OS EVENT pevent INT8U perr 创建互斥型信号量OS EVENT OSMutexCreate INT8U prio INT8U perr 删除信号量OS EVENT

随机推荐

  • git中submodule子模块的添加、使用和删除

    背景 项目中经常使用别人维护的模块 xff0c 在git中使用子模块的功能能够大大提高开发效率 使用子模块后 xff0c 不必负责子模块的维护 xff0c 只需要在必要的时候同步更新子模块即可 本文主要讲解子模块相关的基础命令 xff0c
  • ros下package中CMakelists的编写

    目录 一 package自动生成的Cmakelists1 指定cmake版本2 项目名字3 寻找构建所需依赖包4 启用python模块依赖5 Message Service Action 生成文件6 启动 message services
  • STM32跳至硬件错误中断(HardFault_Handle) 原因及参考解决方法

    一 HardFault Handle引起的原因 1 遇到错误问题是数据类型不对 xff0c 导致该步骤永远不能执行到 xff0c 跳至硬件错误中断 xff1b 所以硬件中断可尝试查找数据类型错误 2 堆栈设置错误也会跳至hardwarefa
  • 时间与日期插件 -- laydate 使用方法(摘自官网)

    简单例子 xff1a function var start 61 elem 39 start 39 选择ID为START的input format 39 YYYY MM DD hh mm ss 39 自动生成的时间格式 min laydat
  • nginx部署vue项目(包括一个nginx部署多个vue项目)

    部署准备 vue项目打包 首先打开public下的index目录 xff0c 修改后台的URL地址 xff0c 如下图所示 xff1a 使用CMD xff0c 打开命令行程序 进入项目根目录 执行命令 xff1a npm run build
  • 雅可比(Jacobian)矩阵

    在向量分析中 雅可比矩阵是一阶偏导数以一定方式排列成的矩阵 其行列式称为雅可比行列式 还有 在代数几何中 代数曲线的雅可比量表示雅可比簇 xff1a 伴随该曲线的一个代数群 曲线可以嵌入其中 它们全部都以数学家卡尔 雅可比 Carl Jac
  • 粒子滤波方法入门

    例子滤波方法入门 xff1a 分析典型非线性系统数学模型 主要内容 xff1a 1 非线性数学模型 2 用粒子滤波的MATLAB程序简介 1 非线性数学模型 2 用粒子滤波的MATLAB程序简介 function output args 6
  • 关于VIO中IMU预积分的讲解

    Why VIO 转自 xff1a https zhehangt github io 2019 03 23 SLAM Basic VIOInit 首先我们先简单回顾一下为什么要做VIO xff0c 以及为什么要做VIO初始化 我们知道单目相机
  • 线程互斥量死锁,与sleep没有关联

    文章目录 死锁问题死锁原因产生死锁的几个常见场景死锁产生的四个必要条件 61 61 仅供参考互斥条件占有和等待条件不可抢占条件环路等待条件 pthread mutex lock 线程互斥量死锁 与sleep没有关联 项目上 定位死锁原因 无
  • linux下,应用程序中的全局变量与so库中的全局变量名冲突,怎么办?

    文章目录 Wl Bsymbolic 动态库与应用 如果存在同名全局变量 会如何 实现了一个动态库 xff0c 封装了一些方法 然后基于这个动态库 xff0c 实现了一个应用程序 应用程序中含有全局变量A xff0c 动态库中也含有全局变量A
  • 内存管理:分页,分段,段页结合

    内存管理 xff1a 分页 xff0c 分段 xff0c 段页结合
  • STM32 SPI 收发数据 ---规则 + 问题解析

    规则 xff1a 1 xff09 高速同步串行口 3 xff5e 4线接口 xff08 CS xff0c CLK xff0c MOSI xff0c MISO xff09 xff0c 收发独立 可同步进行 2 xff09 SPI分为主从模式
  • gazebo: ROS Control的仿真教程

    gazebo 43 ROS control 1 预备知识2 数据流3 实现动态避障的环境构建 本文主要介绍如何为仿真机器人做控制器的仿真 通过仿真控制器 xff0c 控制机器人的对应关节 1 预备知识 关于gazebo中机器人的仿真 xff
  • NuttX实时操作系统

    NuttX 是一个实时操作系统 RTOS xff0c 其重点遵从特定的标准并且尽量小型化 可伸缩良好且可适应从8位到32位单片机环境 xff0c Nuttx主要遵循的标准是 Posix和ANSI标准 其他的一些来自于Unix或者其他常规的实
  • STM32 CAN 配置、收发结构定义 留存...

    分布式系统项目需要 xff0c 这次弄个CAN总线来布局 xff0c 仅见CAN的冰山一角 本次使用扩展帧模式 STM32 对CAN的定义 库 CAN结构体定义 说明 xff1a 寄存器映射 xff1a typedef span class
  • cortex-M3 的SVC、PendSV异常,与操作系统(ucos实时系统)

    文章目录 SVC和PendSVSVC xff1a PendSV xff1a 操作系统 xff0c 上下文切换 实例 xff1a ucos 关于 PendSV 异常的应用 上下文切换时机 怎样满足实时性 xff1a 中断 异常处理通用模板 x
  • STM32+IAP方案 实现网络升级应用固件

    关注了这个概念有些日子了 xff0c 这段时间总算有机会实战 61 61 网络升级应用固件 xff0c 这里记录下遇到的问题 xff0c 及解决方案 原理与网上流传的串口作为传输手段 一致 xff1b 不同之处 xff0c 无非我这里使用了
  • IAR版本不兼容导致无法正常打开工程文件--解决方法

    嵌入式开发 学习过程中 xff0c 难免需要借鉴别人的工程 xff0c 但是开发环境的匹配始终是个问题 61 61 版本不匹配 无法正常的打开工程文件 一般官方标配的开发环境包括 xff1a MDKIAR 这里描述IAR环境下 xff0c
  • STM32中GPIO的8种工作模式

    概念解释 xff1a 复用功能 xff1a 即片内外设 xff0c 包括UART SPI CAN I2C等等 xff0c 开启这些外设的功能 xff0c 就是使用了系统的复用功能 复用功能有两种 xff1a 没有重映像 重映像 xff08
  • 再读 ucosII源码(邵贝贝):任务之间的通讯与同步--邮箱

    邮箱简介 xff1a 邮箱是 C OS II中另一种通讯机制 xff0c 它可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量 该指针指向一个包含了特定 消息 的数据结构 为了在 C OS II中使用邮箱 xff0c 必须将O