CC1110 的DMA 采用16bit字模式,源为SFR时会出现高低字节反序的BUG,而源为SRAM时则正常
CC1110 的DMA 采用16bit字模式,源为SFR时会出现高低字节反序,而源为SRAM时则正常
本身想利用 DMA 高速读取ADC,满64次后再进行ADPCM压缩。
ADC结果寄存器是小端排列符合IAR EW8051小端要求,刚刚好
却发现 使用 DMA_WORDSIZE_WORD 16bit字模式时 ,ADC结果在目标SRAM会出现高低字节反序,需要自己手动反序才能进行ADPCM运算 ,晕死。
如果改成字节模式,那就每次只能读2个字节(1次ADC结果),用DMA的意义跟0差不多。
寄存器测试, 结果是高低字节反序
#define X_ADCL XREG( 0xDFBA )
#define X_ADCH XREG( 0xDFBB )
#define X_RNDL XREG( 0xDFBC )
#define X_RNDH XREG( 0xDFBD )
#define X_U0DBUF XREG( 0xDFC1 )
#define X_U0BAUD XREG( 0xDFC2 )
SRCADDR 指向 0xDFBA(X_ADCL) 那么 SRAM_BUF的结果是 ADCH1,ADCL1 ADCH2,ADCL2
SRCADDR 指向 0xDFBB(X_ADCH) 那么 SRAM_BUF的结果是 RNDL, ADCH1, RNDL, ADCH2
SRCADDR 指向 0xDFBC(X_RNDL) 那么 SRAM_BUF的结果是 RNDH, RNDL, RNDH, RNDL
// 对应 CC2540协议栈
SRCADDR 指向 0xDFBC(X_U0DBUF) 那么 SRAM_BUF的结果是 U0BAUD,U0DBUF, U0BAUD,U0DBUF,
===================
SRAM测试 ,结果是不改变字节顺序
SRAM_SRC 数据是 0x11,0x22
SRCADDR 指向 SRAM_SRC 那么 SRAM_BUF的结果 是 0x11,0x22, 0x11,0x22
===========================================
我能找到官方的唯一一个 ADC DMA例子,却是字节模式, 每次只能读取1次结果的DMA (wtf?)
adc_cont_dma_seq.c // SWRC117 - cc1110_cc2510_Basic Software_Examples
里面的设置是
DMA_WORDSIZE_BYTE , 字节模式
LEN=2 , ADC结果是16bit,所以是2字节
DMA_SRCINC_1 源地址每次+1
DMA_DESTINC_1 目标地址每次+1
DMA_TMODE_BLOCK 每次传输1块(就是前面的2字节)
5个DMA通道对应5个ADC通道,只能读一次结果, 再启动就重复刷新目标缓冲区。
简直就是没卵用啊
===============================
网上唯一关于 DMA_WORDSIZE_WORD 的讨论就是 CC2540协议栈高速串口通信解决(UART的DMA方式)
官方代码 是同时读取 X_U0DBUF 和 X_U0BAUD (字模式,源地址指向X_U0DBUF )
#define X_U0DBUF XREG( 0xDFC1 )
#define X_U0BAUD XREG( 0xDFC2 )
例子中 U0BAUD = 0xD8
外部发送的数据是 0x01,0x02,0x03,0x04
而SRAM_BUF的排列却是 0xD8,0x01,0xD8,0x02,0xD8,0x03,0xD8,0x04
很明显是 源高地址U0BAUD的值 却被传输到 目标的低地址 上
===============================
有其他用户使用过字模式的DMA传输么?
能否确认 TI 8051核的DMA存在这个特殊BUG?
(翻了好多CC11xx CC24xx CC25xx 的规格书都找不到相关描述 ,网上也找不到16bit DMA的应用 )
迟点再看看DMA写入寄存器是否存在相同的反序现象
@AZ
DMA 16bit字写入的情况一样, 目标为SFR高低字节反序, 目标为SRAM则正常
一个有趣的组合是 源和目标都是SFR,那么反转再反转还是正确字节序
既然是BUG,只好变通了
128个ADC数据采样
2个数组缓存,3次DMA操作
一个是ADC的DMA缓存数组 Buff_1[256], 这个数据会循环刷新,不建议直接取用。
一个是处理用的缓存数组 Buff_2[257],多留1个字节或字
实际数据类型是 16bit x 128,但用 8bit x 256 格式好描述
第1次DMA 就是 ADC触发的,2Bx128次 Buff_1[]获得字节反序的数据
Buff_1[]的数据排列是 1H,1L,2H,2L (大端格式 KEIL C51使用)
第二次 DMA 是 &Buff_1[0] --->&Buff_2[1](目标地址首地址地址偏移1B) , 256Bytes
Buff_2[] 的数据排列是 x,1H,1L,2H,2L
第三次 DMA 是搬移Buff_2[]单数地址的数据往前2字节的位置, 利用了DMA有每次传输后地址+2的能力。 共128Bytes
[2]-->[0],[4]->[2],,,[128]->[126]
Buff_2[] 的数据排列是 1L,1H,2L,2H, (小端格式 ,IAR EW8051使用 ,也跟寄存器序一样)
******
为了让处理数组拿到正确字节序的数据,还需要第3次DMA ,IO测量这2/3次DMA总耗时 20us多吧,
等于多了一次消耗10us不到的DMA操作,也是可以接受的
==============================================
不过到了后来
我发现在ADPCM压缩/解压程序里面做技巧,也可以完成字节序反转,不花费额外指令和时间。 唉