《使用CCS进行DSP编程(四)--CCS编程入门.pdf》由会员分享,可在线阅读,更多相关《使用CCS进行DSP编程(四)--CCS编程入门.pdf(13页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、使用使用 CCS 进行进行 DSP 编程(四)编程(四)实现实现 Host 和和 DSP 通信通信 pacificxu 首先对题目进行一下解释,之所以取这个名字,是为了与前面三篇文章相对应,连成一个系列,这里不仅仅涉及使用 CCS 进行 DSP 编程,主机端的程序便是用 Visual C+实现的。通信包括许多手段:中断、mailbox、直接数据传输等等,这里并不一一列举。现在讨论实现 Host 和 DSP 通信。假定读者对 CCS 的使用已经比较了解,并有了一定的 CCS 编程经验。如果读者还不太了解,请参阅使用 CCS 进行 DSP编程(一)CCS 编程入门、使用 CCS 进行 DSP 编程
2、(二)实现 FFT、使用 CCS 进行 DSP 编程(三)实现 DMA 和 Interrupt及其他 CCS 的学习文档。下面用闻亭公司的 C6xP 板硬件和闻亭公司的 PCI 仿真器为例,来实现 Host和 DSP 通信。对于C6Xpa 板同样有效。闻亭公司的 C6xP 板是一款具有 PCI 接口的高速信号处理 EVM 板,接口芯片是 AMCC 的 S5933,兼容 PCI Local Bus Revision 2.1 协议。PCI 接口比较适合用来进行 Host 和 DSP 的高速大数据量数据交换。主机通过 HPI 接口可直接访问DSP 的所有存储空间,允许主机初始化 DSP,可以从主机加
3、载程序。前面几篇文章所讲的都是从 JTAG 接口加载程序,这样比较适合于程序的开发调试,对于实际的系统来说,大部分都是系统自己从 EEPROM 或 Flash 加载,现在我们可以从主机通过应用程序来加载,基于此,许多耗时的算法 PC 机不能实时完成的可以由 DSP 来完成。这个过程可以这样来描述:PC 机执行应用程序,加载算法到 DSP 端,并将需要处理的数据传送到 DSP,DSP 计算完成后将数据传回 PC,整个过程由 PC来控制启动、工作、完成,使用起来比较方便。当然,DSP 算法还需要首先用仿真器通过 JTAG 接口调试好才行。接下来看看实现这个功能的一个典型系统框图:在这个框图里,我简
4、化了主机 PC 执行程序的其他部分,突出了与 DSP 进行通信有关的内容。对任何一个系统,复位状态必须是确定的,这样才有一个确定的前提,对硬件电路如此,对于软件编程也是如此。因为这里的关于主机与 DSP 通信是针对确定物理硬件的(闻亭公司C6Xp 板和C6Xpa 板),编程是建立在对应的支持库上的,未使用闻亭公司C6Xp 板或C6Xpa 板的读者可能对一些地方不太理解,但原理性的地方应该是一致的。对于 PCI 插卡与操作系统的关系,我不做过多的说明。闻亭公司C6Xp 板和 C6Xpa 板可以看作标准的 PCI 插卡,“驱动级”有两个文件支持,evm6x.vxd(对于 NT4.0 是 evm6x
5、.sys)和 evm6x.dll,我们所关心的是 evm6x.dll,它提供了类似于 WIN32 的 API 一样的函数接口,用户可以直接在 Visual C+和 C+Builder 下调用。在应用程序中,需要包含头文件 evm6xdll.h,在这个头文件中,包含了对以下函数的定义:读者可以对比较感兴趣的函数比较感兴趣的函数做进一步的了解,这些函数的参数和使用方法在TI 的文档(spru308.pdf)中有详细的说明,我就不一一说明。顺便说一下,如果读者同时有几块类似的 PCI 插卡,可以通过使用不同的板卡索引分别对不同的板卡进行操作:对第一块卡,board_index 为 0,第二块卡,bo
6、ard_index 为 1,对每一块确定的卡都有相应的操作句柄对应,相互之间互相不影响。在 DSP 端的 CCS 编程中,同样会用到相关的头文件:board.h 和 pci.h,以及相关的运行时库为 drv6x.lib。其中与主机交换信息的函数列表如下:现在,对我们要使用的硬件和软件资源都已经有了一定的了解,可以开锅造饭了。对 DSP 端的程序,读者可以根据自己的需要来编写,我直接采用 Chest Nut先生的程序来做例子,大家使用时可别忘了饮水思源啊%(&$%&(:_:其中引用的头文件 gather.h 源文件如下:程序中首先对使用的硬件进行初始化,接下来进行死循环,DSP 端一直读主机发送
7、的消息,读到后,将 0 x02000000 开始的 1024 个空间用 1 来填充。然后向主机发送消息,继续循环。同步和异步消息的收发有些不同,罗列如下:#include?int pci_message_send(unsigned int message);此程序发送一个 32bit 的 message,如果它不能立即放入 mailbox,返回错误,message 未被发送。Return:returns OK or ERROR,可能出错条件包括:外发信息邮箱不空或 HINT 未 clear Note:此函数检测邮箱 empty/full flags 和 HINT bit,如果邮箱 1 为空且
8、HINT is clear,信息被放入邮箱 1,并把 HINT bit 置 1。?int pci_message_async_send(unsigned int message,int wait_for_ack,pci_msg_callback*p_callback)此函数执行发送信息操作,立即返回,操作结束会调用 callback。Parameters:-message is the 32bit value to be sent to the host-wait_for_ack determines when the operation is considered complete and
9、the callback function is called.-p_callback is the funciton pointer for the callback routine Return:-returns OK or ERROR,possible error conditions include:another send in progress Notes:-this function uses interrupts internally,it does not poll-if wait_for_ack is TRUE then callback is not called unt
10、il the message has been read by the host,if it is FALSE then callback is called as soon as the message is placed into the mailbox?int pci_message_sync_send(unsigned int message,int wait_for_ack)此函数发送 32bit message 到主机,操作完成后才返回。Parameters:-message is the 32bit value to be sent to the host -wait_for_a
11、ck determines when the operation is considered complete and the callback function is called.Return:-returns OK or ERROR,possible error conditions include:another send in progress Notes:-this function implemented by calling pci_message_async_send()and waiting internally for the operation to complete.
12、-if wait_for_ack is TRUE then the operation is not complete until the message has been read by the host,if it is FALSE then the operation is complete as soon as the message is placed into the mailbox?int pci_message_retrieve(unsigned int*p_message)此函数接主机发送的信息,如果信息不存在,返回 ERROR。Parameters:-p_message i
13、s the location to store the 32bit value sent by the host Return:-returns OK or ERROR,possible error conditions include:incoming message mailbox not full Notes:-this function checks mailbox empty/full flags then if mailbox 1 is full the message is read from the mailbox 1 register?int pci_message_asyn
14、c_retrieve(unsigned int*p_message,pci_msg_callback*p_callback)此程序执行异步信息接收操作,立即返回。操作结束时调用 callback 函数。Parameters:-p_message is the location to store the 32bit value sent by the host -p_callback is the funciton pointer for the callback routine Return:-returns OK or ERROR,possible error conditions incl
15、ude:another retrieve in progress Notes:-this function uses interrupts internally,it does not poll?int pci_message_sync_retrieve(unsigned int*p_message)此程序接收主机发送的 32bit message,直到完成操作后才返回。Parameters:-p_message is the location to store the 32bit value sent by the host Return:-returns OK or ERROR,possi
16、ble error conditions include:another retrieve in progress Notes:-此函数通过调用 pci_message_async_retrieve()并 waiting internaly for the operation to complete 读者可以根据自己的实际情况选择同步或异步消息发送或接收。对于主机端的程序,读者可以采用喜欢的方式来编程,但需要包括以下的内容:主机作了初始化后,可以加载程序到 DSP 运行,将这时主机可以向 DSP 发送消息,并等待 DSP 返回消息,一切工作完成后,别忘了关闭 HPI 及 Evm 板。如果读者觉
17、得这样主机(PC)有点浪费,可以单独开一个 Thread,来进行消息的收发。下面是一个主机向 DSP 写数据并发送消息的子程序:当然读者会使用自己的函数名称来实现这些功能,更不需要在 main()里实现这些功能了。用户加载自己的 DSP 程序时,只要将其中的文件名换成自己的文件名即可:其他的初始化步骤搬过来用就行了。好了,不再罗嗦了。六祖曰:“迷时师度,悟时自度”。大家要学会“自度”,“遇事反求诸己”,这样才能快速提高。本人水平如此,也只能点到为止了。题后话:题后话:本来写到这里就觉得差不多了,又有人来问:“我的程序在 CCS 下运行正常,在主机端加载后怎么不正常?”,理由是往 DSP 的某一
18、空间写某一确定数,主机来读取,得不到预期的结果。我们来看一下程序是怎么写的(举此例,并无他意):我们首先需要弄明白,下面的函数到底是什么意思。具体一点:那么,“halted state”和“releases the DSP from the halted state”到底怎么理解呢?我们从主机往 DSP 载入程序后,DSP 并不自动运行程序,需要一个启动信号,把它从“halted”状态唤醒,evm6x_unreset_dsp()这个函数完成的就是这个工作,那么它在程序中的位置也就清楚了,“米放到锅里,过了好久了,怎么还没熟?”,“哦,没有开电源!嘻”。到此,上面的问题也就不言自明了。本来想强调一下,又觉得没有这个必要了。大家都是明白人。