CC2540 UART数据失真分析
来源:互联网 发布:音频频谱分析软件 编辑:程序博客网 时间:2024/05/19 05:33
学习蓝牙有一段时间了,最近整理一下,有部分是参考,进击的菜鸟的博文,请大家多多指教。
如果只是简单的实现串口的数值传递,可以很简单的实现,直接引用TI的串口函数就可以。但是TI的串口有很多问题,不知道在他们设计时,是否注意到这些缺陷。首先
由于OSAL并不是一个实时的系统(其实并不是系统),且效率并不高,如果需要传输比较大的数据量,会出血性丢字节的现象。在采用中断获取串口数据时,分析原因就是OSAL时不时的要进入临界区,从而关闭所有中断,影响了接口的接收。如果你使用DAM做接收,当数据量大时,由于OSAL采用轮询的方式处理DAM,在大数据传输过程中也会出现数据失真。即便是将缓冲区HAL_UART_DMA_RX_MAX调大,也解决不了问题。在审查程序的过程中发现了这几处问题,如果不加修改当传输数据比较大时,也会失真。
1)POWER_SAVING
工程默认是低功耗模式,所以要在设置中将POWER_SAVING前面打差号(xPOWER_SAVING);
2) // Enable clock divide on halt停止时钟
// This reduces active current while radio is active and CC254x MCU
// is halted//如果不修改,会自动切换频率,倒是DMA数据失真
HCI_EXT_ClkDivOnHaltCmd( HCI_EXT_ENABLE_CLK_DIVIDE_ON_HALT );
TI程序默认是MCU空闲时降低主频来降低功耗,但是在用DAM进行串口数据传输时,会影响到DMA控制器搬数据,导致数据失真,所以要把此处设置成HCI_EXT_DISABLE_CLK_DIVIDE_ON_HALT。
3)当数据量比较打是,参照{进击的菜鸟的博文}如下:
在HalDmaInit和HalUARTInitDMA中基本是做DMA相关寄存器的配置,在HalUARTInitDMA中可以看到一处设置
HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_WORD );
这条语句有点诡异,我看到这儿的时候立马就注意到了,因为串口是一个字节一个字节传的,为何SIZE要设置为WORD,也就是两个字节,其上有一串注释
/* The trick is to cfg DMA to xfer 2 bytes for every 1 byte of Rx.
* The byte after the Rx Data Buffer is the Baud Cfg Register,
* which always has a known value. So init Rx buffer to inverse of that
* known value. DMA word xfer will flip the bytes, so every valid Rx byte
* in the Rx buffer will be preceded by a DMA_PAD char equal to the
* Baud Cfg Register value.
*/
在这儿,OSAL用了一个小技巧,因为串口数据接收的缓冲寄存器后面接的是波特率寄存器,见手册U0BUF的地址为0x70C1,而0x70C2正好是波特率寄存器U0BAUD,所以,DMA取一个字,也就是两个字节,会取出一个U0BAUD和U0BUF。取出U0BAUD来有何用?其实目的很简单——OSAL每次轮训,在DMA接收到数据后,将DMA目标缓冲中“有效”的数据取出来,并反馈给应用层,然后将多出来的、取自U0BAUD的字节,取反,这样就能分辨出DMA有没有接收到新的字节,因为已经处理过的数据有部分被取反了,也就不等于U0BAUD寄存器中的值了
举例说明,如果uart接收到的数据为,0x01,0x02,0x03,0x04,那么在DMA缓冲区里存的数据(115200波特率下)将会是:0xD8,0x01,0xD8,0x02,0xD8,0x03,0xD8,0x04,这样0xD8实际就是用来做标记的,处理过后给他设置为别的值,那就知道哪些是处理过,哪些没处理过了~~
而HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE_REPEATED );表明DMA是循环执行的,不用关心何时重启DMA
所以要做的修改为:
1.在Hal_ProcessPoll中注释掉HalUARTPoll();不让OSAL去轮询它
2.自己写一个处理DMA缓冲的函数,自己去分析dmaCfg.rxBuf中的内容
整理好以后重新烧到CC2540里面测试,一切OK,不停地发送了几万个字节没有一个字节丢了的。
- CC2540 UART数据失真分析
- Cc2540 协议栈UART实验
- Cc2540 协议栈UART实验
- 示波器分析UART串口数据
- 示波器分析UART串口数据
- CC2540的HAL层UART学习笔记
- CC2540 内存结构分析
- 从tty到uart层,分析uart数据流程(一)
- 从tty到uart层,分析uart数据流程(二)
- 通过波形分析方法调试UART数据收发
- UART设备驱动分析
- UART分析与设计
- UART软件设计与分析
- linux tty ----uart 分析
- uart驱动分析
- UART驱动分析
- UART分析与设计
- UART时序分析
- C语言——逗号表达式
- 剑指Offer-20-顺时针打印矩阵
- Apache与Tomcat的联系和区别
- 四维矩阵、四维数组
- 《懒人Shell脚本》之一——遍历文件并格式化输出文件
- CC2540 UART数据失真分析
- Communication System
- Android 之 Retrofit 入门介绍
- 牛顿迭代解立方根
- Java与Mysql开发中的特殊字符(包括Emoji)
- 基于模板匹配的数字识别
- Maven五种scope含义的说明
- 高级UIKit-04(NSUserDefaults、NSKeyedArchiver、对象归档方法) - 回读(IOS)
- js模块化编程