Davinci之调试DSP
被卖到公司实习马上就快一年期满了。这大半年又正好赶上第二轮本命年,真是酸甜苦辣咸,一言难尽。从现在算是放假了,最后一个暑假。天亮了就回家,听说正好奥运圣火也到天津了。不过人山人海的,没什么凑热闹的兴趣。还是清清静静地给我们家小妮妮过周岁来得好,呵呵,都一年了还没怎么当过这个新舅舅呢!小的时候觉得大人们榆木脑袋得不可思议,明明我们只想要什么什么就可以开心得不行了,可他们就是不明白。现在因果循环转回来,也真的不知道该怎么对待小孩子?扯远了,言归正传,紧接着终于要回实验室发愁毕业论文的事情,公司那边的事情恐怕再不会沾手了。给好久以前的笔记系列补上一段,算是个纪念吧!据我的孤陋寡闻所知,用Davinci搞开发的,大多数都用走CE+FC那套正统大路。我们因为一直是自己摸着石头,就走上了DSPLink+CMEM这条小道。走小路的人貌似很少,这里也暂时不去讲怎么用DSPLink+CMEM来开发。总之反正不管是用的哪套东西,调试DSP程序始终都是个大难题。首先,以前的CCS+仿真器的模式,在双核下就不好使了。用仿真器就跑不起系统来,没有系统就没法调系统下的程序——鸡不下蛋、蛋不孵鸡;其次,据说系统跑起来以后,再打开CCS可以调DSP的状态。这个要求要打开DSP的锁。我没明白是怎么弄的,而且就算明白了,这法子貌似也只能调下共享内存。结论就是,“仿真器+双核”是个很难搞甚至搞不定的东西。所以我们试着回归linux的程序调试——不是gdb,而是printf。
DSP程序的printf貌似是给CCS看的,log/trace又被JTAG金屋藏娇,想改个驱动去抓贼见脏却不知道从何下手。最后只好从DSPLink的MSGQ下手了。论机制,这个原本是高速串口的设备接口,就是用来点对点传输数据的。再加上DSPLink底层的零拷贝驱动,理论上每秒10000(还是8000)次的交换效率还是挺理想的!MSGQ实现过程是,每次由远端(DSP)生成消息(alloc),传送给本地(arm)输出后释放资源(free)。如果在两端各自构造一个消息队列,在算法的每个循环中同步一次,交换双方的资源和处理结果,可以达到并行工作的效果。这里只需要实现一个dsp_printf,1个消息队列单向传输就够了。不过美中不足的是,MSGQ本身貌似不支持中断上下文。因此若用在PRD或者SWI中,就好象失败的隐式内存申请(栈,stack)被调用到,DSP程序会崩溃,反应到ARM端多半是同步函数报告一个超时错误。(对于普遍的隐式变量定义失败的情况,我只知道换作动态malloc堆资源来解决。在DSP/BIOS的tci里加大stack的值根本不管用。不知道具体原因是什么,如何解决?盼高手赐教!)
msgq_debug库使用说明
目的:解决Davinci开发平台无法输出DSP调试信息的问题
功能:利用msgq机制,令ARM代理DSP的调试信息,并输出给终端
限制1:仅适用于TI Davinci开发平台中的DSPLink程序开发
限制2:格式字段类似printf(),但总长度(包括\0)不能超过20字节
限制3:必须指定2个参数。不需要参数时可填充任意的32位值;参数不够用时可以多次调用debug_printf()
限制4:不支持字符串参数
1.文件列表
.
|-- dsp
| |-- DspBios
| | |-- COMPONENT 配置文件2
| | `-- Davinci
| | `-- ... DSP/BIOS配置文件
| |-- SOURCES 配置文件1
| |-- msgq_debug.c msgq_debug头文件
| |-- msgq_debug.h msgq_debug函数实现
| `-- ... DSP程序
|
|-- gpp
| |-- Linux
| | |-- COMPONENT 配置文件2
| | `-- ... Linux主程序
| |-- SOURCES 配置文件1
| |-- msgq_debug.c msgq_debug头文件
| |-- msgq_debug.h msgq_debug函数实现
| `-- ... DSPLink接口程序
|
`-- ... 编译脚本、说明文件等 2.API列表
DSP
Int debug_init();
Int debug_printf (Uint16 poolid, const char * fmt, Uint32 arg0, Uint32 arg1);
ARM
NORMAL_API DSP_STATUS DEBUG_Create (PoolId poolid);
3.在dsplink工程中使用msgq_debug的方法
dsp/SOURCES
SOURCES := msgq_debug.c \
dsp/DspBios/COMPONENT
原工程配置文件无需改变
dsp程序
// 说明:在第一个debug_printf()前执行一次即可
// 作用:locate remote massage queue named "DebugMSGQ"
Int debug_init();
// 说明:在任意位置向ARM传送调试信息
// 作用:allocate a new message, and put it to remote massage queue
// 举例:debug_printf(SAMPLE_POOL_ID,"DSP loop (%d)\n", i, 0);
Int debug_printf (Uint16 poolid, const char * fmt, Uint32 arg0, Uint32 arg1);
gpp/SOURCES
SOURCES := msgq_debug.c \
gpp/Linux/COMPONENT
EXP_HEADERS := msgq_debug.h \
linux/DSPLink程序
// 说明:初始化本地debug消息队列,启动接收线程
// 作用:open local massage queue named "DebugMSGQ"
create a pthread getting and printing messages in a loop
// 举例:DEBUG_Create(SAMPLE_POOL_ID);
NORMAL_API DSP_STATUS DEBUG_Create (PoolId poolid);
=============== 下面是实现的源码 ===============
---------------------------------- GPP ----------------------------------
/** ============================================================================
* @file msgq_debug.c
* ============================================================================
* Copyright (c) Muddle Liu 2008
* ============================================================================
*/
/* ----------------------------------- DSP/BIOS Link */
#include <gpptypes.h>
#include <dsplink.h>
#include <errbase.h>
#include <platform.h>
#include <msgqdefs.h>
/* ----------------------------------- Profiling */
#include <profile.h>
/* ----------------------------------- DSP/BIOS LINK API */
#include <proc.h>
#include <msgq.h>
#include <pool.h>
/* ----------------------------------- Application Header */
#include <msgq_debug.h>
#include <pthread.h>
#include <stdio.h>
#if defined (__cplusplus)
EXTERN "C" {
#endif /* defined (__cplusplus) */
//#ifdef __DEBUG
#define __D(fmt, args...) printf("DSPDEBUG: " fmt, ## args)
//#else
//#define __D(fmt, args...)
//#endif
typedef struct DebugMsg {
#define STR_LEN 20
#define ARG_NUM 2
MsgqMsgHeader header;
Char8 str[STR_LEN];
Uint32 arg[ARG_NUM];
#undef STR_LEN
#undef ARG_NUM
} debugmsg_t;
/** ============================================================================
* @const DSPLINK_BUFFER_SIZE
*
* @desc Messaging buffer used by the application.
* Note: This buffer is aligned according to the alignment expected
* by the platform.
* ============================================================================
*/
#define DEBUG_BUFFER_SIZE DSPLINK_ALIGN (sizeof(debugmsg_t), \
DSPLINK_BUF_ALIGN)
/** ============================================================================
* @const DebugMSGQ
*
* @desc Name of the Debug MSGQ on the GPP.
* ============================================================================
*/
STATIC Char8 DebugGppMsgqName [DSP_MAX_STRLEN] = "DebugMSGQ" ;
/** ============================================================================
* @name DebugGppMsgq
*
* @desc Local GPP's MSGQ Object.
* ============================================================================
*/
STATIC MsgqQueue DebugGppMsgq = (Uint32) MSGQ_INVALIDMSGQ ;
void* DEBUG_Execute (void*);
/** ============================================================================
* @func DEBUG_Create
*
* @desc This function allocates and initializes resources used by
* this application.
* ============================================================================
*/
NORMAL_API
DSP_STATUS
DEBUG_Create (PoolId poolid)
{
DSP_STATUS status = DSP_SOK;
pthread_t pid;
__D("Entered DEBUG_Create ()\n");
/*
* Open the GPP's message queue
*/
if (DSP_SUCCEEDED (status)) {
status = MSGQ_Open (DebugGppMsgqName, &DebugGppMsgq, NULL) ;
if (DSP_FAILED (status)) {
printf("MSGQ_Open () failed. Status = [0x%x]\n", (int)status);
}
}
/*
* Set the message queue that will receive any async. errors
*/
/* if (DSP_SUCCEEDED (status)) {
status = MSGQ_SetErrorHandler (DebugGppMsgq, poolid) ;
if (DSP_FAILED (status)) {
printf("MSGQ_SetErrorHandler () failed. Status = [0x%x]\n", (int)status);
}
}
*/
printf("Leaving MESSAGE_Create ()\n");
if (pthread_create(&pid, NULL, DEBUG_Execute, NULL)) {
printf("pthread_create () failed.\n");
return(DSP_EBASE);
}
return status;
}
void DEBUG_Delete (Void);
/** ============================================================================
* @func DEBUG_Execute
*
* @desc This function implements the execute phase for this application.
*
* @modif None
* ============================================================================
*/
void* DEBUG_Execute (void* arg)
{
DSP_STATUS status = DSP_SOK ;
volatile debugmsg_t *msg ;
int i;
__D("Entered DEBUG_Execute ()\n") ;
for (i = 1; DSP_SUCCEEDED(status) ||
status == DSP_ETIMEOUT || status == DSP_ENOTCOMPLETE; i++) {
status = MSGQ_Get(DebugGppMsgq, WAIT_NONE/*WAIT_FOREVER*/, (MsgqMsg *)&msg);
if (DSP_SUCCEEDED (status)) {
printf("DSP said: ");
printf((char *)msg->str, msg->arg[0], msg->arg[1]);
MSGQ_Free ((MsgqMsg)msg) ;
}
}
__D("Leaving DEBUG_Execute ()\n") ;
DEBUG_Delete();
return NULL;
}
/** ============================================================================
* @func DEBUG_Delete
*
* @desc This function releases resources allocated earlier by call to
* DEBUG_Delete ().
* During cleanup, the allocated resources are being freed
* unconditionally. Actual applications may require stricter check
* against return values for robustness.
*
* @modif None
* ============================================================================
*/
void DEBUG_Delete ()
{
DSP_STATUS status = DSP_SOK ;
DSP_STATUS tmpStatus = DSP_SOK ;
__D("Entered DEBUG_Delete ()\n") ;
/*
* Reset the error handler before deleting the MSGQ that receives
* the error messages.
*/
tmpStatus = MSGQ_SetErrorHandler (MSGQ_INVALIDMSGQ, MSGQ_INVALIDMSGQ) ;
if (DSP_SUCCEEDED (status) && DSP_FAILED (tmpStatus)) {
status = tmpStatus ;
__D("MSGQ_SetErrorHandler () failed. Status = [0x%x]\n",
(int)status) ;
}
/*
* Close the GPP's message queue
*/
tmpStatus = MSGQ_Close (DebugGppMsgq) ;
if (DSP_SUCCEEDED (status) && DSP_FAILED (tmpStatus)) {
status = tmpStatus ;
__D("MSGQ_Close () failed. Status = [0x%x]\n", (int)status) ;
}
__D("Leaving MESSAGE_Delete ()\n") ;
}
#if defined (__cplusplus)
}
#endif /* defined (__cplusplus) */
/** ============================================================================
* @file msgq_debug.h
* ============================================================================
* Copyright (c) Muddle Liu 2008
* ============================================================================
*/
#if !defined (MSGQ_DEBUG_H)
#define MSGQ_DEBUG_H
USES (gpptypes.h)
USES (errbase.h)
#if defined (__cplusplus)
EXTERN "C" {
#endif /* defined (__cplusplus) */
NORMAL_API
DSP_STATUS
DEBUG_Create (PoolId poolid);
#if defined (__cplusplus)
}
#endif /* defined (__cplusplus) */
#endif
---------------------------------- DSP ----------------------------------
/** ============================================================================
* @file msgq_debug.c
* ============================================================================
* Copyright (c) Muddle Liu 2008
* ============================================================================
*/
/* ----------------------------------- DSP/BIOS Headers */
#include <std.h>
#include <sys.h>
#include <sem.h>
#include <log.h>
#include <tsk.h>
#include <msgq.h>
#include <pool.h>
/* ----------------------------------- DSP/BIOS LINK Headers */
#include <dsplink.h>
#include <platform.h>
#include <failure.h>
/* ----------------------------------- Sample Headers */
#include <message_config.h>
#include <debug.h>
#include <msgq_debug.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#define DebugGppMsgqName "DebugMSGQ"
MSGQ_Queue DebugMsgq;
#define DEBUG_BUFFER_SIZE (DSPLINK_ALIGN (sizeof (debugmsg_t), \
DSPLINK_BUF_ALIGN))
/** ============================================================================
* @func debug_init
*
* @desc Create phase function for the TSKMESSAGE application. Initializes
* the TSKMESSAGE_TransferInfo structure with the information that will
* be used by the other phases of the application.
*
* @modif None.
* ============================================================================
*/
Int debug_init ()
{
Int status = SYS_OK ;
MSGQ_LocateAttrs syncLocateAttrs ;
/* Synchronous locate. */
status = SYS_ENOTFOUND ;
while (status == SYS_ENOTFOUND) {
syncLocateAttrs.timeout = SYS_FOREVER ;
status = MSGQ_locate (DebugGppMsgqName,
&DebugMsgq,
&syncLocateAttrs) ;
if (status == SYS_ENOTFOUND) {
TSK_sleep (1000) ;
}
}
return status ;
}
/** ============================================================================
* @func debug_printf
*
* @desc Execute phase function for the TSKMESSAGE application. Application
* receives a message, verifies the id and sends it back.
*
* @modif None.
* ============================================================================
*/
Int debug_printf (Uint16 poolid, const char * fmt, Uint32 arg0, Uint32 arg1)
{
Int status = SYS_OK ;
debugmsg_t *msg;
status = MSGQ_alloc (poolid, (MSGQ_Msg *)&msg, DEBUG_BUFFER_SIZE);
if (status != SYS_OK) {
SET_FAILURE_REASON(status);
return(status);
}
strcpy(msg->str, fmt);
msg->arg[0] = arg0;
msg->arg[1] = arg1;
status = MSGQ_put (DebugMsgq, (MSGQ_Msg)msg);
if (status != SYS_OK) {
MSGQ_free ((MSGQ_Msg)msg) ;
SET_FAILURE_REASON(status);
}
return status ;
}
/** ============================================================================
* @func debug_destory
*
* @desc Delete phase function for the TSKMESSAGE application. It deallocates
* all the resources of allocated during create phase of the
* application.
*
* @modif None.
* ============================================================================
*/
Int debug_destory ()
{
Int status = SYS_OK ;
/* Release the located message queue */
if (DebugMsgq != MSGQ_INVALIDMSGQ) {
status = MSGQ_release (DebugMsgq) ;
if (status != SYS_OK) {
SET_FAILURE_REASON (status) ;
}
}
return status ;
}
#if defined (__cplusplus)
}
#endif /* defined (__cplusplus) */
/** ============================================================================
* @file msgq_debug.h
* ============================================================================
* Copyright (c) Muddle Liu 2008
* ============================================================================
*/
#ifndef MSGQ_DEBUG_
#define MSGQ_DEBUG_
/* ----------------------------------- DSP/BIOS Headers */
#include <msgq.h>
#include <sem.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct DebugMsg {
#define STR_LEN 20
#define ARG_NUM 2
MSGQ_MsgHeader header;
Int8 str[STR_LEN];
Uint32 arg[ARG_NUM];
#undef STR_LEN
#undef ARG_NUM
} debugmsg_t;
Int debug_init ();
Int debug_printf (Uint16 poolid, const char * fmt, Uint32 arg0, Uint32 arg1);
Int debug_destory ();
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif
页:
[1]