打印

使用 DMA写flash后,读取数据出现错位现象

[复制链接]
1684|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lslacteer|  楼主 | 2024-11-7 18:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
     使用 DMA写flash后,读取数据出现错位现象,读到的buffer 的第一节总为0,从第二字节开始才是正常数据。只能在24bit地址发送完后,再发一个DUMMY_BYTE(无效字节),才能bufferr接收数据。       一但调“dma_channel_enable(DMA1, DMA_CH3)这个使能”后就出现上述现象。每次读取数据时都要先发一个DUMMY_BYTE才能正确接收。若上电不调“dma_channel_enable(DMA1, DMA_CH3)“接收都是正常的。使用的MCU是GD32F470VIT6,SPI FLAH是GD25Q40C.
请各位大佬帮忙分析下。
以下为SPI代码
DMA配置
void dma_init(uint8_t *data_buffer, uint32_t data_length)
{
    dma_single_data_parameter_struct dma_init_struct;
       
        rcu_periph_clock_enable(RCU_DMA1);
   //DMA发送


    dma_deinit(DMA1, DMA_CH3);

    // DMA初始化参数设置
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPH;
       
    dma_init_struct.memory0_addr = (uint32_t)data_buffer;
       
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
       
       
          dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI0);
       
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
       
    dma_init_struct.periph_memory_width = DMA_MEMORY_WIDTH_8BIT;
       
    dma_init_struct.number = data_length;

    dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_DISABLE;
               
    dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
               
          dma_single_data_mode_init(DMA1, DMA_CH3,  &dma_init_struct);
       
          dma_channel_subperipheral_select(DMA1, DMA_CH3, DMA_SUBPERI3);

    // 使能DMA中断通道
   nvic_irq_enable(DMA1_Channel3_IRQn, 0, 0);
    // 配置DMA中断使能位
         //dma_circulation_disable(DMA1, DMA_CH3);
         dma_interrupt_enable(DMA1, DMA_CH3, DMA_CHXCTL_FTFIE);
         
         
          

}


DMA发送
int8_t spi_dma_data_send(uint8_t* pbuffer, uint32_t write_addr, uint16_t num_byte_to_write)
{
       
       
          /* enable the write access to the flash */
    spi_flash_write_enable();

    /* select the flash: chip select low */
    SPI_FLASH_CS_LOW();
       
           /* send "write to memory" instruction */
       
         
          spi_flash_send_byte(WRITE);

    /* send read_addr high nibble address byte to read from */
    spi_flash_send_byte((write_addr & 0xFF0000) >> 16);
    /* send read_addr medium nibble address byte to read from */
    spi_flash_send_byte((write_addr& 0xFF00) >> 8);
    /* send read_addr low nibble address byte to read from */
    spi_flash_send_byte(write_addr & 0xFF);

               
               
                dma_channel_disable(DMA1, DMA_CH3);
               
          spi_dma_disable(SPI0,SPI_DMA_TRANSMIT);
       
          dma_memory_address_config(DMA1, DMA_CH3, DMA_MEMORY_0, (uint32_t)(pbuffer));

          dma_transfer_number_config(DMA1, DMA_CH3, num_byte_to_write);
               
                spi_dma_enable(SPI0,SPI_DMA_TRANSMIT);
               
          dma_channel_enable(DMA1, DMA_CH3);
               
          return 0;
       
       
}

DMA接收
int8_t spi_dma_data_recv(uint8_t* pbuffer, uint32_t read_addr, uint16_t num_byte_to_write)
{
         uint8_t dumyy_byte = 0xA5;
       
       
       
          //spi_flash_wait_for_write_end();
       
       
           /* select the flash: chip slect low */
   SPI_FLASH_CS_LOW();

    /* send "read from memory " instruction */
   spi_flash_send_byte(READ);
          

    /* send read_addr high nibble address byte to read from */
    spi_flash_send_byte((read_addr & 0xFF0000) >> 16);
    /* send read_addr medium nibble address byte to read from */
    spi_flash_send_byte((read_addr& 0xFF00) >> 8);
    /* send read_addr low nibble address byte to read from */
    spi_flash_send_byte(read_addr & 0xFF);
       
          spi_flash_send_byte(0xA5); //为应对错位,多加的一个DUMMY_BYTE
       
       
          dma_channel_disable(DMA1, DMA_CH3);
          dma_channel_disable(DMA1, DMA_CH2);
       
          spi_dma_disable(SPI0,SPI_DMA_TRANSMIT);
          spi_dma_disable(SPI0,SPI_DMA_RECEIVE);

          dma_memory_address_config(DMA1, DMA_CH3, DMA_MEMORY_0, (uint32_t)(&dumyy_byte));  //设置发送无效字节
       
          dma_periph_width_config(DMA1, DMA_CH3, DMA_MEMORY_INCREASE_DISABLE);//取消地址自动增长
       
          dma_transfer_number_config(DMA1, DMA_CH3, num_byte_to_write);//设置产生时钟脉冲个数
               

               
               
               
                dma_memory_address_config(DMA1, DMA_CH2, DMA_MEMORY_0, (uint32_t)pbuffer);//设置接收数据位
               
                dma_transfer_number_config(DMA1, DMA_CH2, num_byte_to_write);//设置产生时钟脉冲个数
               
       
                /* enable DMA channel */
                spi_dma_enable(SPI0,SPI_DMA_TRANSMIT);  //SPI使能DMA发送功能
                spi_dma_enable(SPI0,SPI_DMA_RECEIVE);
               
               
                /* enable DMA channel */
                dma_channel_enable(DMA1, DMA_CH2);  //使能DMA接收
          dma_channel_enable(DMA1, DMA_CH3);  //使能DMA发送
          
                 /* while there is data to be written on the flash */


       
}


spi初始化
void spi_flash_init(void)
{
    spi_parameter_struct spi_init_struct;

    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_SPI0);

    /* SPI0_CLK(PB3), SPI0_MISO(PB4), SPI0_MOSI(PB5) GPIO pin configuration */
    gpio_af_set(GPIOB, GPIO_AF_5, GPIO_PIN_3|GPIO_PIN_4| GPIO_PIN_5);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3|GPIO_PIN_4| GPIO_PIN_5);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO_PIN_3|GPIO_PIN_4| GPIO_PIN_5);

    /* SPI0_CS(PE2) GPIO pin configuration */
          rcu_periph_clock_enable(RCU_GPIOE);
    gpio_mode_set(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_2);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);

    /* chip select invalid */
    SPI_FLASH_CS_HIGH();

    /* SPI0 parameter config */
    spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;
    spi_init_struct.device_mode          = SPI_MASTER;
    spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;
    spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
    spi_init_struct.nss                  = SPI_NSS_SOFT;
    spi_init_struct.prescale             = SPI_PSC_32;
    spi_init_struct.endian               = SPI_ENDIAN_MSB;
    spi_init(SPI0, &spi_init_struct);


    /* enable SPI0 */
    spi_enable(SPI0);
}


使用特权

评论回复
沙发
wyadqwld| | 2024-11-13 09:54 | 只看该作者
我也是这样的lz解决了吗

使用特权

评论回复
板凳
两只袜子| | 2024-11-13 10:34 | 只看该作者
可能是DMA配置错误

使用特权

评论回复
地板
elephant00| | 2024-11-13 10:35 | 只看该作者
使用的MCU或SPI flash芯片可能存在硬件缺陷或兼容性问题。

使用特权

评论回复
5
jcky001| | 2024-11-13 11:00 | 只看该作者
DMA的传输数量或地址设置可能不正确,导致数据未能完整或准确地写入flash。

使用特权

评论回复
6
cr315| | 2024-11-13 12:23 | 只看该作者
SPI时钟频率与DMA的传输速度不匹配,可能导致数据在传输过程中出现错位。

使用特权

评论回复
7
laocuo1142| | 2024-11-13 13:59 | 只看该作者
固件或驱动程序中的bug可能导致DMA传输异常。

使用特权

评论回复
8
flycamelaaa| | 2024-11-13 16:00 | 只看该作者
检查DMA的传输方向、数据宽度、传输模式等配置与SPI传输的要求是否相匹配。

使用特权

评论回复
9
powerantone| | 2024-11-13 16:59 | 只看该作者
检查DMA的传输数量、地址等设置,确保数据能够完整且准确地写入flash。

使用特权

评论回复
10
stormwind123| | 2024-11-13 17:26 | 只看该作者
尝试调整SPI的时钟频率,以匹配DMA的传输速度。
可以调整分频系数等参数,以确保SPI时钟与DMA传输的协调性。

使用特权

评论回复
11
probedog| | 2024-11-13 20:00 | 只看该作者
检查MCU和SPI flash芯片的硬件连接看看有没有损坏或接触不良的情况。

使用特权

评论回复
12
classroom| | 2024-11-13 20:00 | 只看该作者
如果可能,尝试使用其他MCU或SPI flash芯片进行测试,以排除硬件兼容性问题。

使用特权

评论回复
13
duo点| | 2024-11-13 21:00 | 只看该作者
固件和驱动程序更新至最新版本

使用特权

评论回复
14
onlycook| | 2024-11-13 21:46 | 只看该作者
优化固件中的DMA传输逻辑,确保数据传输的稳定性和准确性。

使用特权

评论回复
15
七毛钱| | 2024-11-13 22:00 | 只看该作者
可以在DMA传输的末尾添加一个无效字节(DUMMY_BYTE),以解决数据错位的问题。

使用特权

评论回复
16
内政奇才| | 2024-11-13 23:00 | 只看该作者
可以尝试重新初始化SPI和DMA模块。关闭SPI和DMA,重新配置其相关寄存器,并重新启动它们。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

2

帖子

0

粉丝