21ic问答首页 - 使用 DMA写flash后,读取数据出现错位现象
使用 DMA写flash后,读取数据出现错位现象
lslacteer2024-11-07
使用 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);
}
请各位大佬帮忙分析下。
以下为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);
}
赞0
评论
2024-11-13
赞0
评论
2024-11-13
赞0
评论
2024-11-13
赞0
评论
2024-11-13
赞0
评论
2024-11-13
赞0
评论
2024-11-13
赞0
可以调整分频系数等参数,以确保SPI时钟与DMA传输的协调性。
评论
2024-11-13
赞0
评论
2024-11-13
赞0
评论
2024-11-13
您需要登录后才可以回复 登录 | 注册