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,不停地发送了几万个字节没有一个字节丢了的。

1 0
原创粉丝点击