zoukankan      html  css  js  c++  java
  • 【DSP开发】mailbox的使用

    在DSP项目开发中,我用mailbox实现了进程间的通信,通过接收网络控制进程发来的mailbox,实现了云台的控制,其中需要学习的地方有两点:一是mailbox通信机制的学习,二是DSP时间管理机制,这里先学习一下mailbox的相关知识。

        MBX模型为mailbox提供了一系列函数支持,比如MBX_pend 和 MBX_post。而mailbox可以用来在同一块处理器上运行的进程相互通信。mailbox是同步通信机制,而且mailbox在传递之前就已经确定了大小,这样可以保证成堆的信息接踵而来的时候不会超出系统的处理能力。我们网络监控系统的mailbox初始化的时候mailbox每条信息容量的上限为500字节,长度为12,也就是可以存储12条信息。

        MBX_create和MBX_delete顾名思义就是分别用来创建和销毁mailbox的。当然你也可以静态的创建mailbox。静态创建对内存的分配方面有好处,而动态创建在于灵活,但是DSP的内存分配策略据说不是很好,我也有所体会了。当然,别人德州器械久负盛名的TI芯片族,我是没资格说三道四了。在我们组的工程中,每个进程都静态配置了mailbox的创建,这样的话,在task的源码中就不会看到MBX_create函数以及调用这个函数的函数了。这个配置文件写在.tci文件中,在最终的.tcf文件中调用,在板子启动时读取这份tcf文件,便在程序启动的最初将它们初始化完毕,以后程序的工作就是用它们了。

    DSP中的Mailbox的学习

    bios.MBX.create("mbx_alarm");

    bios.MBX.instance("mbx_alarm").messageSize = 500;

    bios.MBX.instance("mbx_alarm").length = 12;

     

        下面是MBX_create和MBX_delete的函数参数的介绍。没办法,这不是linux,它们的函数原型恐怕无法得知了。(这两天看UNIX网络编程,感觉还是开源来的爽快,大师们编的程序真是漂亮)。

    MBX_Handle MBX_create(msgsize, mbxlength, attrs)

    Uns msgsize;

    Uns mbxlength;

    MBX_Attrs *attrs;

     

    Void MBX_delete(mbx)

    MBX_Handle mbx;

    MBX_pend这个函数用来读取mailbox里的信息。如果邮箱是空的,或是说没有有效的信息,MBX_pend会阻塞。这种状况下呢,timeout参数可以让进程在此等待到超时结束,或是完全不等(设为0,唉,真的是一个信息都接不到啊,还是不要设为0,推荐2),呵呵。

    Bool MBX_pend(mbx, msg, timeout)

    MBX_Handle mbx;

    Void *msg;

    Uns timeout; /* return after this many */

    /* system clock ticks */

    这里要注意的是,DSP时间单位不是秒,而是system clock ticks,下一次我会研究比较一下linux和dsp时间机制的不同。

    相对的,MBX_post是用来发送信息的。如果mailbox是满的话,(在我的工程中,就是待发出的信息量大于12)MBX_post会阻塞。在这种情况下,timeout参数会让进程等待到超时结束,或是不等。等不来的话呢,返回0,就说明什么也没发出去咧,返回1呢,就是发送成功了啦。

    下面是MBX_post的源码:

     

    Bool MBX_post(mbx, msg, timeout)

    MBX_Handle mbx;

    Void *msg;

    Uns timeout; /* return after this many */

    /* system clock ticks */

     

    值得一提的是,我和实验室的一个MM一起调试云台的时候,我在客户端狂点云台按钮,她在服务器端比较郁闷的发现大多数MBX_post都会返回0,就是发送不成功。可以设想,如果超时时间设长一点的话,可能会保证收到消息的绝对处理,但不能保证收到消息的实时处理。对于监控系统这样对实时性要求很高的固件来说,我认为还是丢弃一部分比较好。但丢弃带来的问题就是,可能命令执行不连续,对云台控制质量保证不了,这需要我们进一步对云台控制的进程进行优化和调度,保证信息的及时稳定的传递。

     

    下面奉上DSP的代码,讲的就是两个进程通信,多个人发邮件,一个人收邮件,结果也附带奉上:

         /*

    * ======== mbxtest.c ========

    * Use a MBX mailbox to send messages from multiple writer()

    * tasks to a single reader() task.

    * The mailbox, reader task, and 3 writer tasks are created

    * by the Configuration Tool.

    *

    * This example is similar to semtest.c. The major differences

    * are:

    * - MBX is used in place of QUE and SEM.

    * - the ‘elem’ field is removed from MsgObj.

    * - reader() task is *not* higher priority than writer task.

    * - reader() looks at return value of MBX_pend() for timeout

    */

    #include

    #include

    #include

    #include

    #define NUMMSGS 3 /* number of messages */

    #define TIMEOUT 10

    typedef struct MsgObj {

    Int id; /* writer task id */

    Char val; /* message value */

    } MsgObj, *Msg;

    /* Mailbox created with Config Tool */

    extern MBX_Obj mbx;

    /* "trace" Log created with Config Tool */

    extern LOG_Obj trace;

    Void reader(Void);

    Void writer(Int id);

    /*

    * ======== main ========

    */

    Void main()

    {

    /* Does nothing */

    }

    /*

    * ======== reader ========

    */

    Void reader(Void)

    {

    MsgObj msg;

    Int i;

    for (i=0; ;i++) {

    /* wait for mailbox to be posted by writer() */

    if (MBX_pend(&mbx, &msg, TIMEOUT) == 0) {

    LOG_printf(&trace, "timeout expired for MBX_pend()");

    break;

    }

    /* print value */

    LOG_printf(&trace, "read ’%c’ from (%d).", msg.val, msg.id);

    }

    LOG_printf(&trace, "reader done.");

    }

    /*

    * ======== writer ========

    */

    Void writer(Int id)

    {

    MsgObj msg;

    Int i;

    for (i=0; i < NUMMSGS; i++) {

    /* fill in value */

    msg.id = id;

    msg.val = i % NUMMSGS + (Int)(‘a’);

    LOG_printf(&trace, "(%d) writing ‘%c’ ...", id,

    (Int)msg.val);

    /* enqueue message */

    MBX_post(&mbx, &msg, TIMEOUT);

    /* what happens if you call TSK_yield() here? */

    /* TSK_yield(); */

    }

    LOG_printf(&trace, "writer (%d) done.", id);

    }

    运行结果:

    DSP中的Mailbox的学习

    以后要在做项目的同时认真总结,查漏补缺,争取每天都能进步!

  • 相关阅读:
    023 使用@Value注解完成配置信息的注入
    022 使用@Bean的属性完成初始化和销毁的指定
    021 使用@Import注解完成Bean的注册
    020 使用@Conditional注解完成条件注入
    019 使用@Lazy完成懒加载
    018 使用@Scope完成bean的作用域的声明
    017 包扫描器和标记注解
    016 @Configuration和@Bean
    015 spel
    vs2010编辑器中找不到System.Web.Extensions.dll
  • 原文地址:https://www.cnblogs.com/huty/p/8518500.html
Copyright © 2011-2022 走看看