复数乘法指令

  TI的编译器提供的一些内联函数中可以直接调用复数乘法的汇编指令(CMPYSP,只有C66x DSP支持),完成复数乘法运算。

  src1和src2是连续的两个32位寄存器组成的register pair,dst是由四个连续的32位寄存器组成的register quadruplets。这里只是做了乘法运算。

  然后用DADDSP指令可以对上面的结果中的实数部分和虚数部分分别求和,即可实现复数乘法。

(a+bi)(c+di)=ac−bd+(ad+bc)i\left( {a + b{\rm{i} } } \right)\left( {c + d{\rm{i} } } \right) = ac - bd + \left( {ad + bc} \right){\rm{i} }(a+bi)(c+di)=ac−bd+(ad+bc)i

  另外编译器也提供了一种快速实现复共轭乘法的方式,即p×q∗p\times q^*p×q∗。乘数中需要求复共轭的数qqq放在src1寄存器对中作为a+bia+b\rm{i}a+bi,另一个乘数ppp放在src2寄存器对中,依次完成CMPYSP和DSUBSP即可得到p×q∗p\times q^*p×q∗的结果。

(a−bi)(c+di)=ac+bd+(ad−bc)i\left( {a - b{\rm{i} } } \right)\left( {c + d{\rm{i} } } \right) = ac + bd + \left( {ad - bc} \right){\rm{i} }(a−bi)(c+di)=ac+bd+(ad−bc)i

  总结起来就是用_complex_conjugate_mpysp(m1, m2)这个函数的时候,第一个参数m1是那个取复共轭的复数。
  另外,从运算效率上考虑,如果一个复数在存储器中的存放方式与它在寄存器中的存放方式相同,那么就可以只用一条LDDW指令就从存储器中将一个64bit表示的复数直接load到寄存器中。可以看到寄存器中实部是存在高32位而虚部是存在低32位,所以建议存储器中也按照这样的方式存放(而一般FFT支持的复数格式是实部在低地址,虚部在高地址,是相反的,需要注意!)

Cache映射方式

  Cache的映射方式包括直接映射,全相联映射和组相联映射,后者是前两者相结合的产物。C6678的L1P Cache采用的是直接映射,存储器中的code在L1P Cache中只有唯一确定的位置。
  C6678的L1D Cache采用的是两路组相联映射(two-way set associative cache),一个set里面有两个line frame,存储器中的数据映射到固定的set,但可以是任意的line frame。

  C6678的cache line frame是64字节,所以地址中的Offset字段固定为6bits。一个set是128字节,如果L1D的Cache大小为4kB,那么L1D Cache可以分为32个set,所以Set字段为5bits,剩下的就是Tag字段21bits。

  当L1D Cache设置为32kB时,set的数量也就变为了原来的8倍,因此Set字段需要8bits,相应的Tag字段减少为18bits。

TI Data Type

  调试过程中经常需要预先往存储器中加载数据,可以通过Memory Browser窗口里的Load Memory实现。

  需要加载的数据预先存在在一个“xxx.dat”文件里,按照TI Data的格式进行存放,在加载的时候CCS就会根据文件头的信息把数据加载到指定的位置。

  帧头的数都是十六进制表示的!可以在CCS的Help->Help Comtents里搜索“data format”找到相关的介绍。

  数据格式“9”表示一种比较新的数据格式说明方式,具体数据格式由最后一个数决定。数据个数就是数据的行数,因为一行一个数据。具体数据格式如下表:

具体数据格式(十六进制) 含义
0 64bit Hex TI-style
1 64bit Hex C-style (带0x前缀)
2 64bit Floating Point
3 Exponential Float (指数表示的浮点数)
4 32bit Hex TI-style
5 32bit Hex C-style
6 32bit Signed Int
7 32bit Unsigned Int
8 32bit Binary
9 32bit Floating Point
A 32bit Exponential Float
B 16bit Hex TI-style
C 16bit Hex C-style
D 16bit Signed Int
E 16bit Unsigned Int
F 16bit Binary
10 8bit Hex TI-style
11 8bit Hex C-style
12 8bit Signed Int
13 8bit Unsigned Int
14 8bit Binary
15 Character
16 Packed Char

QDMA的使用

  有时候需要手动启动DMA并且随时需要对PaRAM进行修改,而不是等待外部事件触发,那么就可以用QDMA来实现。QDMA能够在写完PaRAM时就启动DMA传输。实际应用过程中可以有这几点需要考虑:

  1. 硬件初始化
  2. 中断服务函数
  3. 启动传输

  下面是C6678上用于实现矩阵转置的一个类。三个成员函数分别对应我提到的三点要考虑的地方。

#ifndef CTSPSMANAGER_H
#define CTSPSMANAGER_H#include <csl_edma3.h>#define TPSP_PARAM_NUM  (10)
#define TSPS_QDMA_CHANNEL (0)
#define TSPS_TCC_CODE (8)
#define TSPS_SYSEVT_EDMA3R0 (38)
#define TSPS_REGION CSL_EDMA3_REGION_0class CTspsManager
{private:CSL_Edma3Handle m_hEdma;CSL_Edma3Obj m_Obj;Bool m_bInitDone;int m_nCicId;public:CTspsManager();~CTspsManager();int HwInit(int coreId);void startTranspose(void *restrict pSrc, void *restrict pDst, int nSrcWidth, int nSrcHeight, size_t nUnit);void ClearInterruptFlag();
};#endif

  硬件初始化过程中,因为要配置中断,所以不同的核需要设置对应的片上中断控制器(CIC)。QDMA通道绑定队列与PaRAM,使能通道。同时也需要使能PaRAM中TCC code对应的DMA通道,和这个DMA通道的中断使能。清中断的时候需要清系统中断和EMDA的中断挂号寄存器。

int CTspsManager::HwInit(int coreId)
{CSL_Status status;CSL_Edma3HwSetup hwSetup;UInt nChannel;CSL_Edma3HwDmaChannelSetup hwDmaSetup[] =   CSL_EDMA3_DMACHANNELSETUP_DEFAULT;CSL_Edma3HwQdmaChannelSetup hwQdmaSetup[] = CSL_EDMA3_QDMACHANNELSETUP_DEFAULT;if(coreId < 0 || coreId > 7)return -1;if(m_bInitDone)return 0;m_hEdma = CSL_edma3Open(&m_Obj, CSL_EDMA3CC_0, NULL, &status);assert(m_hEdma != NULL);//--------------------- Hardware Setup --------------------------// DMA setuphwDmaSetup[TSPS_TCC_CODE].paramNum = TPSP_PARAM_NUM;hwDmaSetup[TSPS_TCC_CODE].que = CSL_EDMA3_QUE_0;hwSetup.dmaChaSetup = hwDmaSetup;// end of DMA setup// QDMA setuphwQdmaSetup[TSPS_QDMA_CHANNEL].paramNum = TPSP_PARAM_NUM;hwQdmaSetup[TSPS_QDMA_CHANNEL].que = CSL_EDMA3_QUE_0;hwQdmaSetup[TSPS_QDMA_CHANNEL].triggerWord = CSL_EDMA3_TRIGWORD_DEFAULT;hwSetup.qdmaChaSetup = hwQdmaSetup;// end of QDMA setupCSL_edma3HwSetup(m_hEdma, &hwSetup);
//--------------------- end of Hardware Setup --------------------------//--------------------- Queue Priority Setup --------------------------CSL_edma3SetEventQueuePriority(m_hEdma, CSL_EDMA3_QUE_0,    CSL_EDMA3_QUE_PRI_0);CSL_edma3SetEventQueuePriority(m_hEdma, CSL_EDMA3_QUE_1,    CSL_EDMA3_QUE_PRI_1);CSL_edma3SetEventQueuePriority(m_hEdma, CSL_EDMA3_QUE_2,    CSL_EDMA3_QUE_PRI_2);CSL_edma3SetEventQueuePriority(m_hEdma, CSL_EDMA3_QUE_3, CSL_EDMA3_QUE_PRI_3);
//--------------------- end of Queue Priority Setup --------------------------CSL_edma3QdmaRegionAccessDisable(m_hEdma, TSPS_REGION, 0xF);CSL_edma3QdmaRegionAccessEnable(m_hEdma, TSPS_REGION, 1 << TSPS_QDMA_CHANNEL);CSL_edma3DmaRegionAccessDisable(m_hEdma, TSPS_REGION, 0xFFFFFFFF, 0xFFFFFFFF);CSL_edma3DmaRegionAccessEnable(m_hEdma, TSPS_REGION, 1 << TSPS_TCC_CODE, 0);CSL_edma3InterruptLoEnable(m_hEdma, TSPS_REGION, 1 << TSPS_TCC_CODE);//--------------------- end of Region Access Setup --------------------------CSL_edma3QDMAChannelEnable(m_hEdma, TSPS_REGION, TSPS_QDMA_CHANNEL);CSL_edma3ClearDMAChannelEvent(m_hEdma, TSPS_REGION, TSPS_TCC_CODE);CSL_edma3DMAChannelEnable(m_hEdma, TSPS_REGION, TSPS_TCC_CODE);// CIC0 is used to connect EMDA finish interrupt to CPUm_nCicId = (coreId < 4) ? 0 : 1;nChannel = coreId % 4 * 11 + 33; // attach to host interrupt ID 22CpIntc_clearSysInt(m_nCicId, TSPS_SYSEVT_EDMA3R0);CpIntc_enableSysInt(m_nCicId, TSPS_SYSEVT_EDMA3R0);CpIntc_mapSysIntToHostInt(m_nCicId, TSPS_SYSEVT_EDMA3R0, nChannel);CpIntc_enableHostInt(m_nCicId, nChannel);CpIntc_enableAllHostInts(m_nCicId);return 0;
}void CTspsManager::startTranspose(void *restrict pSrc, void *restrict pDst, int nSrcWidth, int nSrcHeight, size_t nUnit)
{CSL_Status status;CSL_Edma3ParamSetup paramSetup;CSL_Edma3ParamHandle hParam;Cache_wb(pSrc, nSrcWidth * nSrcHeight * nUnit, Cache_Type_ALLD, TRUE);hParam = CSL_edma3GetParamHandle(m_hEdma, TPSP_PARAM_NUM, &status);paramSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_EN, \CSL_EDMA3_TCCH_DIS, \CSL_EDMA3_ITCINT_DIS, \CSL_EDMA3_TCINT_EN, \TSPS_TCC_CODE, \CSL_EDMA3_TCC_NORMAL,\CSL_EDMA3_FIFOWIDTH_NONE, \CSL_EDMA3_STATIC_DIS, \CSL_EDMA3_SYNC_AB, \CSL_EDMA3_ADDRMODE_INCR, \CSL_EDMA3_ADDRMODE_INCR);paramSetup.srcAddr = (uint32_t)pSrc;paramSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(nUnit, nSrcHeight); // (acnt, bcnt)paramSetup.dstAddr = (uint32_t)pDst;paramSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(nSrcWidth * nUnit,  nUnit); // (src, dst)paramSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAK  (CSL_EDMA3_LINK_NULL, 0);paramSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(nUnit, nSrcHeight * nUnit); // (src, dst)paramSetup.cCnt = nSrcWidth;CSL_edma3ParamSetup(hParam, &paramSetup);
}void CTspsManager::ClearInterruptFlag()
{CSL_edma3ClearLoPendingInterrupts(m_hEdma, TSPS_REGION, 1 << TSPS_TCC_CODE);CpIntc_clearSysInt(m_nCicId, TSPS_SYSEVT_EDMA3R0);
}

参考资料

  • SPRU187U-TMS320C6000 Optimizing Compiler v7.4
  • SPRUGH7-TMS320C66x DSP CPU and Instruction Set Reference Guide

近期C6000 DSP开发小结相关推荐

  1. 近期H5项目开发小结

    前言:2016差不多又过了半啦,最近参与了公司好几个h5项目(严格来说,也只能算是推广页面活动).主要是新品牌的推广需要,当然也有给公司以前老客户做的案例.今天主要总结下为新品牌开发的2个h5推广:就 ...

  2. 广州创龙TMS320C6748 DSP开发板免费申请试用

    2019独角兽企业重金招聘Python工程师标准>>> 1.广州创龙TMS320C6748 DSP开发板免费申请试用,历史上例程最丰富的C6000 DSP开发板,不容错过. 申请链接 ...

  3. 免费DSP开发板,你想要吗?

    1.广州创龙TMS320C6748 DSP开发板免费申请试用,历史上例程最丰富的C6000 DSP开发板,不容错过. 申请链接:http://bbs.elecfans.com/try_Tronlong ...

  4. 广州创龙TMS320C6748 DSP 开发板免费申请试用

    2019独角兽企业重金招聘Python工程师标准>>> 1.广州创龙TMS320C6748 DSP开发板免费申请试用,历史上例程最丰富的C6000 DSP开发板,不容错过. 申请链接 ...

  5. 近期Java高级开发岗面试总结

    原文出处:公众号:编程大道 作者:walking 近期Java高级开发岗面试总结 哈喽大家好,我是walking,这是我的公众号:编程大道. 很久没和大家见面了,文章更新的速度略有延后.这个公众号断断 ...

  6. DSP开发板选择问题

    这两天看了国内各个厂家的DSP开发板,总结一下,希望给同样需要的人一点经验和总结. 因为我是做通信系统,所以需要TI公司的C6000系列处理器. 目前C6000系列性能最强的是C66X系列,该系列的C ...

  7. C6678多核DSP开发——hello world

    C6678多核DSP开发--hello world 本篇学习笔记主要记录在C6678实验板上实现打印"hello world"信息功能,主要目的是熟悉CCS开发环境和硬件调试过程. ...

  8. C6000 DSP技术深度探索-图像处理算法仿真到硬件实现踩过的那些坑

    C6000 DSP技术深度探索-图像处理算法仿真到硬件实现踩过的那些坑 写在前面 图像处理算法-仿真篇 DSP硬件移植篇-挖坑篇 DSP硬件移植篇-坑的种类 写在前面 时间如白马过隙,今天登录CSDN ...

  9. Android 即时通讯开发小结(二)

    <Android 即时通讯开发小结>基于IM Andriod 开发的各种常见问题,结合网易云信即时通讯技术的实践,对 IM 开发做一个全面的总结. 相关推荐阅读:. Android即时通讯 ...

最新文章

  1. Coins POJ - 1742(多重背包+是否装满问题)
  2. 使用无锁的方式和有锁的方式的程序性能对比
  3. extjs官网+extjs官网案例
  4. Spark History Server配置及其启动
  5. shell_exec() php 执行shell脚本
  6. 携程第二场预赛 1003:位图像素的颜色(水题,判断点是否在矩形内)
  7. ScheduledThreadPoolExecutor之scheduleWithFixedDelay和scheduleAtFixedRate的区别
  8. 数据库设计工具-----PD
  9. 小米研发类Kindle电子阅读器
  10. 小程序源码:最新掌上题库微信小程序源码下载,修复登录接口,支持在线考试,自定义导入考题
  11. java rgb565转rgb888_RGB565 与 RGB888的相互转换 | 学步园
  12. FME 函数(Transformer)功能简介
  13. deepin显卡驱动管理器在哪_deepin显卡设置
  14. qsnctf queen wp
  15. 解决Chrome无法显示本地的.vtt字幕文件 (如何让本地HTML运行在Server上)
  16. 使用五数概括法来确定数据集中的孤立点
  17. 普通运维人员就是秋后的蚂蚱!
  18. 数据分析应学习逻辑思维及分析方法
  19. 截至2012年5月23日19点58分支持CUDA的NVIDIA的GPU列表(Geforce)
  20. 关于SQL Server 无法连接到服务器,远程过程调用失败,网络配置无项目

热门文章

  1. 201314这日子太难得了,送祝福吧!
  2. 怎样关闭tp-link无线路由器防火墙
  3. 日常填坑 ——linux服务器,mongodb吃内存,导致服务器缓慢
  4. 驼峰 下划线 String
  5. 域名信息dns服务器,DNS服务器简介
  6. 大学里“最后悔”排行榜!你有没有中?
  7. java正则表达式小括号的作用是啥_正则表达式小括号的作用
  8. matlab 显著性差异检验,假设检验及matlab实现(2)
  9. Windows下Boost库的安装与使用
  10. 牛客练习赛23----托米的位运算