打印

【分享】+DSP/BIOS的基础应用一例

[复制链接]
3526|28
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
msblast|  楼主 | 2013-12-25 13:41 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 msblast 于 2013-12-25 14:55 编辑

本例中使用到的BIOS的组件有BUF,QUE,MBX,PRD,TSK等,现在将这过程与大家分享。

一、新建一个优先级最高的task,如下图


二、软件通用定时器
因为在软件运行过程中,有很多地方需要用到定时。所以写了一个软件定时器,方便使用。

在BIOS中配置,如下图



每一个定时器实例都给分配了内存空间,这是通过BIOS的内存池来实现的,如下图

CtmrCreate/CtmrRelease就是基于这个内存池来实现的


通用定时器的CtmrStart/CtmrStop是通过队列的入列和出列来实现的,也是用的BIOS的队列机制,如下图

队列的数据存储空间也是基于BIOS的BUF组件实现的,如下图


代码实现如下

/*Ctmr.h*/
#ifndef __CTMR_H__
#define __CTMR_H__
#include <std.h>

#include <log.h>
#include <mem.h>
#include <que.h>
#include <sys.h>
#include <tsk.h>

typedef void (*fxn_ptr)(void);
typedef void (*fxn_tmr_cb)(void *cb);

typedef struct _Ctmr {
      Int32 tmrcnt;
      Int32 delay;
      Int32 exe_times;
      Int32 execnt;
      void *params;
      fxn_tmr_cb cb;
      Uint8 bSync;
} CtmrObj;
typedef struct _CtmrQ_Obj {
      QUE_Elem    elem;
      CtmrObj     *ct;
} CtmrQ_Obj, *CtmrQ;

#define CTMR_BASIC_TICK (10)
#define CTMR_EXE_FOR_EVER (0)

Uint32 CtmrCreate(Int32 dly, Int32 exe_times, void *params, fxn_tmr_cb cb);
void CtmrRelease(Uint32 nHdlr);
void CtmrStart(Uint32 nHdlr);
void CtmrStop(Uint32 nHdlr);
void CtmrExeCB(Uint32 nHdlr);

#endif

/*Ctmr.c*/
#include <std.h>
#include <tsk.h>
#include <stdio.h>
#include "timer.h"
#include "c6x.h"

#include "ctrl_task.h"
#include "ctmr.h"
#include "xxxcfg.h"
/*xxxcfg.h由配置工具自动生成*/


/*CtmrCreate给一个新创建的定时器实例分配内存并进行初始化,然后返回内存地址,如果分配不到内存则返回0*/
Uint32 CtmrCreate(Int32 dly, Int32 exe_times, void *params, fxn_tmr_cb cb) {
    Uint32 nHdlr = 0;
    CtmrObj *hTmr = 0;
    do {
          hTmr = (CtmrObj *)BUF_alloc(&Ctmr);
          if(!hTmr) {
                break;
          }
          if(!dly) {
                dly = CTMR_BASIC_TICK;
          }
          dly = ((dly+(CTMR_BASIC_TICK-1))/CTMR_BASIC_TICK)*CTMR_BASIC_TICK;
          hTmr->cb = cb;
          hTmr->delay = dly;
          hTmr->tmrcnt = 0;
          hTmr->exe_times = exe_times;
          hTmr->execnt = 0;
          hTmr->params = params;
          hTmr->bSync = 0;
          nHdlr = (Uint32)hTmr;
    }while(0);
    return nHdlr;
}
/*CtmrRelease释放给定时器实例分配的内存,在这之前先关闭定时器,这主要是防止使用的人忘记停止定时器*/
void CtmrRelease(Uint32 nHdlr) {
    CtmrObj *hTmr = (CtmrObj *)nHdlr;
    if(hTmr) {
        CtmrStop((Uint32)hTmr);
        BUF_free(&Ctmr, (void *)hTmr);
    }
}
/*CtmrStart启动一个定时器,将定时器实例加入队列;如果这个定时器实例之前已在队列中则先移出队列*/
void CtmrStart(Uint32 nHdlr) {
    Uns oldCSR;
    CtmrObj *hTmr = (CtmrObj *)nHdlr;
    CtmrQ ctqelem = 0;
    QUE_Elem *qelem = QUE_head(&CtmrQue);
    if(hTmr) {
        while (qelem != &CtmrQue) {
           if(((CtmrQ)qelem)->ct == hTmr) {
            break;
           }
           qelem = QUE_next(qelem);
        }
        if (qelem != &CtmrQue) {
            oldCSR = HWI_disable();
               QUE_remove(qelem);
               HWI_restore(oldCSR);
               BUF_free(&CtmrQueBuf, (void *)qelem);
        }
        ctqelem = (CtmrQ)BUF_alloc(&CtmrQueBuf);
        if(ctqelem) {
            hTmr->tmrcnt = 0;
            hTmr->execnt = 0;
            hTmr->bSync = 0;
            ctqelem->ct = hTmr;
            oldCSR = HWI_disable();
            QUE_put(&CtmrQue, ctqelem);
            HWI_restore(oldCSR);
        }
    }
}
/*CtmrStop将定时器实例移出队列,并释放为队列分配的内存*/
void CtmrStop(Uint32 nHdlr) {
    Uns oldCSR;
    CtmrObj *hTmr = (CtmrObj *)nHdlr;
    QUE_Elem *qelem = QUE_head(&CtmrQue);
    if(hTmr) {
        while (qelem != &CtmrQue) {
           if(((CtmrQ)qelem)->ct == hTmr) {
            break;
           }
           qelem = QUE_next(qelem);
        }
        
        if (qelem != &CtmrQue) {
        oldCSR = HWI_disable();
           QUE_remove(qelem);
           HWI_restore(oldCSR);
           BUF_free(&CtmrQueBuf, (void *)qelem);
        }
    }
}

/*CtmrExeCB执行CtmrCreate注册的回调函数*/
void CtmrExeCB(Uint32 nHdlr) {
    CtmrObj *hTmr = (CtmrObj *)nHdlr;
    if(hTmr) {
        if(hTmr->cb) {
            hTmr->cb(hTmr);
        }
    }
}
/*CtmrExe在prd_tmr中周期执行*/
void CtmrExe(void) {
    MsgObj      msg;
    CtmrObj *hTmr = 0;
    QUE_Elem *qelem = QUE_head(&CtmrQue);
    while (qelem != &CtmrQue) {
       hTmr = ((CtmrQ)qelem)->ct;
       if(hTmr) {
        if(hTmr->bSync) {
            hTmr->tmrcnt++;
            if((hTmr->tmrcnt*CTMR_BASIC_TICK) == hTmr->delay) {
                msg.id = EVT_IND_CTMR_EXE_CB;
                msg.val = (Uint32)hTmr;
                MBX_post(&CtrlEvt, &msg, 0);
                hTmr->tmrcnt = 0;
                if(hTmr->exe_times != VTIMER_EXE_FOR_EVER) {
                    hTmr->execnt++;
                    if(hTmr->execnt == hTmr->exe_times) {
                        msg.id = EVT_IND_CTMR_EXE_POST_CB;
                        msg.val = (Uint32)hTmr;
                        MBX_post(&CtrlEvt, &msg, 0);
                    }
                }
            }
        }
        else {
            hTmr->bSync = 1;
        }
       }
       qelem = QUE_next(qelem);
    }
}
void prd_tmr() {
  CtmrExe();
}
通用定时器的使用,遵守以下步骤

1.CtmrCreate,创建一个定时器实例
2.CtmrStart,启动定时器实例
3.CtmrStop,停止定时器实例,定时器实例仍然存在,没有销毁
4.CtmrRelease,销毁定时器实例

三、使用mailbox实现事件驱动架构

事件驱动的架使得代码看起来更清晰明了,基于BIOS的MBX和BUF实现的,如下


代码实现如下

/*Ctrl_task.h*/
#ifndef __CTRL_TASK_H__
#define __CTRL_TASK_H__
#include<stdlib.h>
#include "ctmr.h"
.
.
.

typedef struct MsgObj {
    Uint32 id;             /* event id */
    Uint32        val;            /* message value , address of content*/
} MsgObj, *Msg;

enum {
    .
    .
    .
    ,EVT_IND_CTMR_EXE_CB
    ,EVT_IND_CTMR_EXE_POST_CB
    .
    .
    .
    ,EVT_NUM
};
.
.
.
#endif
/*Ctrl_task.c*/

#include <std.h>
#include <c6x.h>
#include "pal_os.h"
#include "psputils.h"
#include "ctrl_task.h"
#include "xxxcfg.h"
/*xxxcfg.h由配置工具自动生成*/
.
.
.
void Task_Ctrl(){
  MsgObj      msg;
  Uint32 Evtid;
  .
  .
  .
  do {
    if (MBX_pend(&CtrlEvt, &msg, SYS_FOREVER)) {
      Evtid = msg.id;
      switch(Evtid) {
        .
        .
        .
        case EVT_IND_CTMR_EXE_CB:
          CtmrExeCB((Uint32) msg.val);
          break;
        case EVT_IND_CTMR_EXE_POST_CB:
          CtmrStop((Uint32)msg.val);
          break;
        default:break;
      }
    }
  }while(1);
}

四、一些体会和建议
掌握通过通用定时器和事件驱动框架,可以很方便的扩展和衍生出很多的功能。


有些问题是在实践过程中才逐步暴露出来的,一段成熟的代码需要一个不断完善的过程。


有细心的童鞋会发现我没有用malloc/free和MEM_alloc/MEM_free,而是用了BUF_alloc/BUF_free 。如果你没有经过我的提醒就意识到了这个问题,我会很高兴看到同道。是的,BIOS HWI中不允许调用malloc/free和MEM_alloc/MEM_free。另外,就算是在TSK中也不要过于频繁的调用malloc/free和MEM_alloc/MEM_free。这是我的体会,也是建议。
你也可以来补充。









评分
参与人数 1威望 +3 收起 理由
zhangmangui + 3 很给力!

相关帖子

沙发
zhangmangui| | 2013-12-25 14:40 | 只看该作者
顶  楼主多多分享这方面的东西

使用特权

评论回复
板凳
msblast|  楼主 | 2013-12-26 11:12 | 只看该作者
zhangmangui 发表于 2013-12-25 14:40
顶  楼主多多分享这方面的东西

多谢支持:lol
希望TI论坛以后多搞点活动啊

用过多家的平台之后,个人最喜欢的就是TI的了。

使用特权

评论回复
地板
zhangmangui| | 2013-12-26 11:30 | 只看该作者
msblast 发表于 2013-12-26 11:12
多谢支持
希望TI论坛以后多搞点活动啊

只要兄弟们多多支持   我一定会争取的

使用特权

评论回复
5
拿起书本| | 2013-12-26 15:37 | 只看该作者
正在学习掌握TMS320C6000系列芯片软件编程中,进来取经来了,受益了,顶起来。

使用特权

评论回复
6
zhangmangui| | 2013-12-26 17:51 | 只看该作者
拿起书本 发表于 2013-12-26 15:37
正在学习掌握TMS320C6000系列芯片软件编程中,进来取经来了,受益了,顶起来。 ...

好好学习   6000系列的问题还望你多多帮忙解答~

使用特权

评论回复
7
陌路绝途| | 2013-12-26 20:48 | 只看该作者

使用特权

评论回复
8
zhangjin_comeon| | 2013-12-27 21:51 | 只看该作者
很充实的分享

使用特权

评论回复
9
msblast|  楼主 | 2013-12-28 12:31 | 只看该作者
拿起书本 发表于 2013-12-26 15:37
正在学习掌握TMS320C6000系列芯片软件编程中,进来取经来了,受益了,顶起来。 ...

谢谢你的肯定。

使用特权

评论回复
10
MyMary| | 2013-12-28 21:20 | 只看该作者
顶  感觉不错

使用特权

评论回复
11
waitingf| | 2013-12-28 21:39 | 只看该作者
希望楼主多分享一些呀

使用特权

评论回复
12
someonewho| | 2013-12-28 23:20 | 只看该作者
学习了 多谢

使用特权

评论回复
13
justbybing| | 2013-12-28 23:28 | 只看该作者
适合初学者 很不错

使用特权

评论回复
14
specialfrin| | 2013-12-29 18:16 | 只看该作者
学习一下 哈哈

使用特权

评论回复
15
someontime| | 2013-12-29 18:52 | 只看该作者
学习啦 不错

使用特权

评论回复
16
haidixibahe| | 2013-12-29 18:57 | 只看该作者
学会了 多谢楼主

使用特权

评论回复
17
chao11yue| | 2013-12-29 19:35 | 只看该作者
不错的分享 楼主分享辛苦了哈

使用特权

评论回复
18
engtafanzhuan| | 2013-12-29 19:54 | 只看该作者
想知道代码能直接用吗

使用特权

评论回复
19
xichengmadia| | 2013-12-29 20:51 | 只看该作者
一步一步讲解的好详细啊

使用特权

评论回复
20
huigoushang| | 2013-12-29 22:09 | 只看该作者
学习了 非常有价值的资料

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

770

帖子

7

粉丝