DSP

纯新手DSP编程--5.30--任务的通信和同步

2019-07-13 09:41发布

DSP/BIOS中提供的用于线程之间协调的管理模块 1 MBX邮箱管理模块    MBX模块使用一组函数通过邮箱对象的句柄管理邮箱的访问。    通常MBX_pend函数来等待信箱的信息。这个函数可以带一个超时参数,以控制允许任务等待的时间。若参数设为SYS_FOREVER,则会引起调用的任务无限期地等待邮箱里的信息。如果超时值为0,则MBX_pend函数立即返回。其返回值给出了邮箱是否存有信息。    函数MBX_post用来给信箱发送信息,如果有任务在等待该信箱的信息,该任务会变为就绪状态,同时MBX_post函数会根据优先级产生任务切换。如果没有任务处在等待状态或者邮箱尚有空间,函数MBX_post会简单的将信息存储在邮箱中并返回。   两个任务线程可以通过邮箱来交换数据。 邮箱大小的单位是:字

(1)MBX_Handle mbx = MBX_create(Uns msgsize, Uns mbxlength, MBX_Attrs * attrs)

  信息大小、邮箱长度、目前邮箱参数没有定义(保留),此函数将调用MEM_alloc函数创建邮箱数据结构

  struct MBX_Attrs{

   int segid; // default is 0

  }

(2)void MBX_delete(MBX_Handle mbx)

  删除指定邮箱,调用MEM_free释放存储空间

(3)bool status = MBX_pend(MBX_Handle mbx, Ptr msg, Uns timeout)

  msg是存放邮箱信息的指针,如果等待时间大于timeout则返回。如果邮箱中有信息,此函数将复制第一条信息到msg所指的存储空间,返回TRUE,否则函数挂起当前任务,直到超时或调用MBX_post函数。

  如果timeout取SYS_FOREVER,当前任务会一直挂起,直到MBX_post被调用,若timeout为0,直接返回。

(4)bool status = MBX_post(MBX_Handle mbx, Ptr msg, Uns timeout)

  此函数在将信息写入邮箱之前,需要检查邮箱是否有容纳新信息的空间,若有,写入并返回。调用函数时,若有更高优先级的任务就绪,或者邮箱已满且timeout不为0,则任务切换。

  同理,如果timeout取SYS_FOREVER,当前任务会一直挂起,直到MBX_pend被调用,若timeout为0,直接返回。
2 SEM旗语管理模块    SEM旗语模块使用一组函数通过旗语对象的句柄来管理旗语的使用。    DSP/BIOS提供的旗语实际上是信号量旗语,该旗语管理模块通过对旗语的计数来完成任务线程的同步和互相作用。    SEM_post与MBX_post类似。不同的是,若没有任务在等待旗语,则该函数简单对旗语计数器加1,返回。        旗语是DSP/BIOS内核定义的数据结构,用于任务线程之间的通信,同步以及访问共享数据,当一个任务线程在等待旗语信号时,它将暂停执行,并产生任务切换。只有当其他任务发送旗语信号后,该线程任务将转变为就绪状态,等待执行。     (1)int count = SEM_count(SEM_Handle sem)

  返回sem制定的旗语计数器的当前值

(2)int count = SEM_create(int count, SEM_Attrs * attrs)

  传入初始的旗语信号量计数值和属性参数(目前无定义,保留)成功则返回对象句柄,否则返回NULL

(3)void SEM_delete(SEM_Handle sem)

  删除指定的旗语,并且调用MEM_free函数释放空间

(4)void SEM_ipost(SEM_Handle sem)

  使得处于等待旗语的任务由阻塞状态(Blocked)变为就绪状态(Ready).如果没有等待旗语的任务,函数仅仅对信号旗语计数器加1并返回。

  此函数类似于SEM_post函数,一般地在SWI或者HWI中使用SEM_ipost函数,在任务线程中使用SEM_post函数。

(5)void SEM_new(SEM_Handle sem, int count)

  初始化指定旗语对象的计数器,只能用于静态创建的旗语计数器进行初始化,调此函数不发生任务切换。

(6)bool status = SEM_pend(SEM_Handle sem, Uns timeout)

  如果旗语计数器大于0,此函数对旗语减1返回TRUE,否则会暂停当前任务的运行,直到该函数的旗语达到。

  在timeout时间之后,暂停的任务会变为就绪,若timeout等于SYS_FOREVER,则必须有SEM_post函数才能取消。

  若超时,函数返回FALSE。若旗语计数器为0,而超时参数不为0,则任务切换

(7)void SEM_post(SEM_Handle sem)

  类似于SEM_ipost函数。

(8)void SEM_reset(SEM_Handle sem, int count)

  复位旗语计数器并重新开始计数,调此函数不发生任务切换。   3 QUE队列管理模块

概述:QUE模块通过队列句柄的访问来管理一系列队列操作函数。

   每个队列包含0个或者多个有序的元素项,其中每个元素项都是一个结构体变量。

   它的第一个成员是类型为QUE_Elem的变量,该结构体成员用作内部指针。

(1)QUE_Handle queue = QUE_create(QUE_Attrs * attrs)

  队列属性参数目前保留。成功返回新队列对象句柄,失败返回NULL。

(2)void QUE_delete(QUE_Handle queue)

  删除队列

(3)Ptr elem = QUE_dequeue(QUE_Handle queue)

  删除队列最前面的元素项并返回该项的指针,此指针是一个指向结构体的指针,该结构第一个成员必须是

  QUE_Elem类型的成员。

  注意:多任务共享队列时:使用QUE_get函数,此函数取元素时禁止中断。

(4)bool empty = QUE_empty(QUE_Handle queue)

  判定队列是否为空

(5)void QUE_enqueue(QUE_Handle queue, Ptr elem)

  在队尾插入一个元素项,参数elem是一个指向结构体的指针。

  注意:多任务共享队列时:使用QUE_put函数,此函数取元素时禁止中断。

(6)void * elem = QUE_get(QUE_Handle queue)

  如果队列不为空,则此函数删除最前面元素项,并返回指向其的指针,如果队列为空,返回此队列本身。

  判定队列是否为空的方法:

  if( (QUE_Handle)(elem = QUE_get(q))!=q )//队列非空

(7)QUE_Elem * elem = QUE_head(QUE_Handle queue)

  返回一个指向队列中最靠前元素的指针,队列为空,返回此队列本身。

(8)void QUE_insert(Ptr qelem, Ptr elem)

  在原队列的qelem前面插入新元素项elem,多任务共享队列时,此函数应和一些避免冲突的函数配合使用。

(9)void QUE_new(QUE_Handle queue)

  初始化指定的队列对象,使队列变空。

  当使用变量说明方法静态创建队列时,初始化此队列。若队列原来为空,其元素不被处理,而是遗弃。

(10)Ptr elem = QUE_next(Ptr qelem)

  返回元素qelem的下一个元素项的指针,多任务共享队列时,此函数应和一些避免冲突的函数配合使用。

(11)Ptr elem = QUE_prev(Ptr qelem)

  返回元素qelem的前一个元素项的指针,多任务共享队列时,此函数应和一些避免冲突的函数配合使用。

(12)void QUE_put(QUE_Handle queue, void * elem)

  在队尾添加元素项,自动禁止中断

(13)void QUE_remove(Ptr qelem)

  删除队列中的元素项,由于队列是双向链表,所以不要删除头结点。   任务之间的共享资源与同步