搜索
bottom↓
回复: 10

STM32H743 单字节DMA发送问题,这个是否算芯片Bug?

[复制链接]

出100入113汤圆

发表于 2019-10-26 10:35:59 | 显示全部楼层 |阅读模式
本帖最后由 saccapanna 于 2019-10-26 11:06 编辑

    I/D-Cache 都已经关闭。 main.c 主要功能,从 USART4 接收数据,然后原封不动返回相同数据。多字节 DMA 发送没有任何问题。 但是当 USART4 接收到一个字节时,把单个字节写入到 USART4 发送缓冲区,然后启动 DMA 数据传输,而 DMA 实际传输的是以前缓冲区的值,而不是新写入的值。 单字节写入后,延迟 10us,或者打断点等待一下,再启动 DMA 传输也没有问题。 这个问题我分析了好久,实在没有找到软件的问题,后来解决方法如下,在启动DMA前做一下判断,如果长度为1,写4次缓冲…… 这个算不算芯片的 Bug ?


     if( usart4_tx_dma_len == 1 ) {                                             // -- 如果是单字节发送,DMA会出问题
            temp = usart4_tx_buff[usart4_tx_sp];                            // -- 数据重写四次,问题解决了,重写三次都不行!!!
            usart4_tx_buff[usart4_tx_sp] = temp;                            //
            usart4_tx_buff[usart4_tx_sp] = temp;                            //
            usart4_tx_buff[usart4_tx_sp] = temp;                            //
            usart4_tx_buff[usart4_tx_sp] = temp;                            //
      }                                                                                      //



整个测试过程大概如下:
main()
{
     ……
    sub_usart4_init( 9600, 0 );                                    // 串口初始化
    while (1) {                                                           //
        i = sub_usart4_get_receive_buff_len();              // 从 USART4 接收数据,然后原封不动发送相同数据。
        if( i != 0 ) {                                                     //
        sub_usart4_read_receive_buff( test_buff, i );      // -- 如果 i==1,也就是从串口接收一个字节,
        sub_usart4_write_send_buff( test_buff, i );         // -- 单字节写入触发DMA传输,这个函数 DMA 传输出问题
    }                                                                        //
}


//==============================================================================================================
// 函数名称:sub_usart4_write_send_buff
// 函数功能:写数据到 usart4 发射缓冲区
//                 DMA1_Stream4:USART4_RX(63) --->    DMAMUX1_Channel_04  --->    DMA1_Stream4_Request
//                 DMA1_Stream5:USART4_TX(64) --->    DMAMUX1_Channel_05  --->    DMA1_Stream5_Request
// 入口参数:data:数据指针,length:数据长度
// 出口参数:BOOL_FALSE:数据太长,将导致缓冲区溢出,写入失败
//                 BOOL_TRUE:写入成功
// 程序版本:1.0
// 编写日期:2019-05-05
// 程序作者:
// 修改次数:
// 修改作者:
// 修改日期:
// 修改内容:
// 版本升级:
//==============================================================================================================
BOOLEAN sub_usart4_write_send_buff( const INT8U * data, INT16U length )
{
    INT16U  i;                                                                   //
    INT16U  usart4_tx_len;                                                //
   
    if( length > USART4_TX_BUFF ) {                                  // 检测写入数据长度
        return BOOL_FALSE;                                                //
    }                                                                                //
   
    ENTER_CRITICAL();                                                     //
    usart4_tx_len = usart4_tx_buff_len + length;                 //
    EXIT_CRITICAL();                                                        //
    if( usart4_tx_len > USART4_TX_BUFF ) {                       // 数据太长,写入失败
        return BOOL_FALSE;                                                //
    }                                                                                //

    for( i=0; i<length; i++ ) {                                            // 写数据到缓冲区
        usart4_tx_buff[usart4_tx_ep] = data;                     //
        usart4_tx_ep++;                                                     //
        if( usart4_tx_ep >= USART4_TX_BUFF ){                   //
            usart4_tx_ep = 0;                                                //
        }                                                                            //
    }                                                                                //
   
//  sub_system_raw_delay_10us(1);                                  // 如果使用延迟,DMA发送数据没有任何问题。
//  __asm("NOP");                                                           // 如果断点打在这里,然后再F5全速跑,DMA发送也没问题。
//  __asm("NOP");                                                           // 但是如果这里不延迟,不打断点,单字节启动DMA,
//  __asm("NOP");                                                           // DMA传输的数据,是之前 usart4_tx_buff 中的数据。
//  __asm("NOP");                                                           // 也就是说,新的数据没有真正的写入到 usart4_tx_buff 中。
//  __asm("NOP");                                                           //
//  __asm("NOP");                                                           // 说明:为了便于测试观看,buff 大小都只设置到了 16 字节。
//  __asm("NOP");                                                           //
//  __asm("NOP");                                                           //
   
    ENTER_CRITICAL();                                                                                        //
    usart4_tx_buff_len += length;                                                                    // 缓冲区长度增加
    if( ((DMA1_Stream5->CR) & DMA_SxCR_EN) == 0 ) {                                 // 开启 DMA 数据传输
        DMA1_Stream5->CR        = 0x00000000;                                              //
        DMA1_Stream5->FCR       = 0x00000000;                                                // -- 使用直接模式
        DMA1_Stream5->PAR       = (INT32U)(&(USART4->TDR));                     // -- 设置 外设 地址
        DMA1_Stream5->M0AR      = (INT32U)( usart4_tx_buff+usart4_tx_sp );  // -- 设置 Memory 地址
        if( usart4_tx_ep > usart4_tx_sp ) {                                                       //
            usart4_tx_dma_len = usart4_tx_ep - usart4_tx_sp;                            //
        }                                                                                                       //
        else {                                                                                                //
            usart4_tx_dma_len = USART4_TX_BUFF - usart4_tx_sp;                    //
        }                                                                                                       //
        DMA1_Stream5->NDTR      = usart4_tx_dma_len;                                 // -- 设置传输长度
        
    //  if( usart4_tx_dma_len == 1 ) {                                          // -- 如果是单字节发送,DMA会出问题
    //      temp = usart4_tx_buff[usart4_tx_sp];                            // -- 数据重写四次,问题解决了,重写三次都不行!!
    //      usart4_tx_buff[usart4_tx_sp] = temp;                            //
    //      usart4_tx_buff[usart4_tx_sp] = temp;                            //
    //      usart4_tx_buff[usart4_tx_sp] = temp;                            //
    //      usart4_tx_buff[usart4_tx_sp] = temp;                            //
    //  }                                                                                     //
        
        DMAMUX1_Channel5->CCR   = 64;                                                       // -- 选择触发信号
        DMA1_Stream5->CR       |= DMA_SxCR_MINC | DMA_SxCR_DIR_0;         // -- Memory 自增,01: Memory-to-peripheral,DMA优先级为低。
        DMA1->HIFCR             = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5;     // -- 清除传输完毕标识
        DMA1_Stream5->CR       |= DMA_SxCR_TCIE;                                       // -- 开启传输完毕中断
        DMA1_Stream5->CR       |= DMA_SxCR_EN;                                          // -- 启动 DMA 传输
        USART4->CR3            |= USART_CR3_DMAT;                                        //
    }                                                                                                            //
    EXIT_CRITICAL();                                                                                    //
    return BOOL_TRUE;                                                                                 //
}                                                                                                                //



测试工程文件:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2019-10-26 10:51:53 来自手机 | 显示全部楼层
是不是dma配置有问题,比如fifo,长度等

出0入0汤圆

发表于 2019-10-26 10:56:10 | 显示全部楼层
STM32H743 什么价格,750不是一样吗,据说可以白用2M

出100入113汤圆

 楼主| 发表于 2019-10-26 10:57:32 | 显示全部楼层
cht-rtos 发表于 2019-10-26 10:51
是不是dma配置有问题,比如fifo,长度等

不是的,多字节传输没有问题。 单字节传输,多写几次 buff 也没有问题。

我重新修改了一下问题说明,后来把这个测试工程发给代理了,然后代理没有回复我,我用奇葩的方法把问题解决了。

出100入113汤圆

 楼主| 发表于 2019-10-26 10:59:02 | 显示全部楼层
dreambox 发表于 2019-10-26 10:56
STM32H743 什么价格,750不是一样吗,据说可以白用2M


我们没用 H743,当时手里只有 H743 的板子,所以用 H743 做的评估,最后实际用的是 H750。H750价格还可以二十多点人民币。

出0入0汤圆

发表于 2019-10-26 15:12:55 | 显示全部楼层
saccapanna 发表于 2019-10-26 10:59
我们没用 H743,当时手里只有 H743 的板子,所以用 H743 做的评估,最后实际用的是 H750。H750价格还可以 ...

750这么便宜吗? 有渠道共享下不?

出100入113汤圆

 楼主| 发表于 2019-10-26 15:14:21 | 显示全部楼层
wusuowei1985 发表于 2019-10-26 15:12
750这么便宜吗? 有渠道共享下不?

直接找代理啊……我们是采购跟代理直接拿的。

出0入0汤圆

发表于 2019-10-27 16:14:22 | 显示全部楼层
saccapanna 发表于 2019-10-26 15:14
直接找代理啊……我们是采购跟代理直接拿的。

多少脚的啊?

出0入0汤圆

发表于 2019-10-27 22:23:06 | 显示全部楼层
官方历程跑没问题就不是芯片的问题了,很简单

出100入113汤圆

 楼主| 发表于 2019-10-28 08:54:05 | 显示全部楼层

没用 FMC 总线,100脚的。STM32H750VBT6

出100入113汤圆

 楼主| 发表于 2019-10-28 08:56:57 | 显示全部楼层
nongxiaoming 发表于 2019-10-27 22:23
官方历程跑没问题就不是芯片的问题了,很简单

没有跑过官方例程,不知道官方例程哪里有下载。你是说 CubeMX 自动生成的驱动,可以配置 DMA 传输吗?我写的这个库已经很好用了,完全不用收发中断,只使用DMA中断就好,在高速时占用MCU时间很少。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 11:09

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表