主要注意点在(2.dma触发spi传输函数)部分。如下图加入这个后就稳定了。
1.初始化代码
void spi4_dma_config(void)
{
dma_single_data_parameter_struct dma_init_struct;
/* configure SPI4 transmit dma */
dma_deinit(DMA1, DMA_CH4);
dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI4);
dma_init_struct.memory0_addr = NULL;
dma_init_struct.direction = DMA_MEMORY_TO_PERIPH;
dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
dma_init_struct.priority = DMA_PRIORITY_LOW;
dma_init_struct.number = 0;
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_DISABLE;
dma_single_data_mode_init(DMA1, DMA_CH4, &dma_init_struct);
dma_channel_subperipheral_select(DMA1, DMA_CH4, DMA_SUBPERI2);
/* configure SPI4 receive dma */
dma_deinit(DMA1, DMA_CH3);
dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI4);
dma_init_struct.memory0_addr = NULL;
dma_init_struct.direction = DMA_PERIPH_TO_MEMORY;
dma_init_struct.priority = DMA_PRIORITY_HIGH;
dma_single_data_mode_init(DMA1, DMA_CH3, &dma_init_struct);
dma_channel_subperipheral_select(DMA1, DMA_CH3, DMA_SUBPERI2);
spi_dma_enable(SPI4, SPI_DMA_TRANSMIT);
spi_dma_enable(SPI4, SPI_DMA_RECEIVE);
}
void spi_flash_init(void)
{
rcu_periph_clock_enable(RCU_SPI4);
rcu_periph_clock_enable(RCU_DMA1);
spi4_dma_config();
spi_parameter_struct spi_init_struct;
/* chip select invalid */
SPI_FLASH_CS_HIGH();
/* SPI5 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_2;
spi_init_struct.endian = SPI_ENDIAN_MSB;
spi_init(SPI4, &spi_init_struct);
/* enable SPI5 */
spi_enable(SPI4);
}
2.dma触发spi传输函数
static int spi4_DMA_transition(uint32_t write_mem_addr,uint32_t read_mem_addr,uint32_t buf_size)
{
if(buf_size==0)
return -1;
int time=SPI_DMA_TIME_OUT,errorCode=0;//0xffffffff;
dma_channel_disable(DMA1, DMA_CH4);//发送
dma_channel_disable(DMA1, DMA_CH3);//接收
//delet 对比FAE给出的需要删除的
dma_flag_clear(DMA1, DMA_CH3,DMA_FLAG_FTF);
dma_flag_clear(DMA1, DMA_CH4,DMA_FLAG_FTF);
//add 对比FAE给出的需要添加的
// dma_memory_address_generation_config(DMA1, DMA_CH4,DMA_MEMORY_INCREASE_DISABLE);
// dma_memory_address_generation_config(DMA1, DMA_CH3,DMA_MEMORY_INCREASE_ENABLE);
dma_memory_address_config(DMA1, DMA_CH4,DMA_MEMORY_0, write_mem_addr);
dma_memory_address_config(DMA1, DMA_CH3, DMA_MEMORY_0,read_mem_addr);
dma_transfer_number_config (DMA1, DMA_CH4, buf_size);
dma_transfer_number_config (DMA1, DMA_CH3, buf_size);
dma_channel_enable(DMA1, DMA_CH4);
dma_channel_enable(DMA1, DMA_CH3);
//add
/* DMA channel enable */
spi_dma_enable(SPI4, SPI_DMA_RECEIVE);
spi_dma_enable(SPI4, SPI_DMA_TRANSMIT);//1.配置完成先开启一次
time=SPI_DMA_TIME_OUT;
while(!dma_flag_get(DMA1,DMA_CH4, DMA_FLAG_FTF)) {//send
__NOP();
if(time)
time--;
else
{
errorCode|=1;
break;
}
}
time=SPI_DMA_TIME_OUT;
while(!dma_flag_get(DMA1,DMA_CH3, DMA_FLAG_FTF)) {//rec
__NOP();
if(time)
time--;
else
{
errorCode|=2;
break;
}
}
if(waitOverBusyDelay(SPI_DMA_TIME_OUT))
errorCode|=4;
//add
/* SPI DMA disable */
spi_dma_disable(SPI4, SPI_DMA_TRANSMIT);//2.传输完成再关闭,,,这两条不加入有中断就可能导致传输异常
spi_dma_disable(SPI4, SPI_DMA_RECEIVE);
// /* clear DMA channel flag */
// dma_flag_clear(DMA1, DMA_CH3,DMA_FLAG_FTF);
// dma_flag_clear(DMA1, DMA_CH4,DMA_FLAG_FTF);
return errorCode;
}
3.对外封装例如flash读取
void spi_flash_buffer_read(uint8_t* pbuffer, uint32_t read_addr, uint32_t num_byte_to_read)
{
SPI_FLASH_CS_LOW();
if(norFlashUseDma)
{
uint32_t packLen=32768;//max 65535
uint32_t group=num_byte_to_read/packLen,remain=num_byte_to_read%packLen,g=0,errorCode=0,reLen=0;
uint8_t buf[4]={0};
buf[0]=READ;
buf[1]=(read_addr & 0xFF0000) >> 16;
buf[2]=(read_addr & 0xFF00) >> 8;
buf[3]=read_addr & 0xFF;
errorCode=spi4_DMA_transition((uint32_t)buf,(uint32_t)DMA_CHMADDR_RESET_VALUE,4);
while(errorCode)
{
//------方案1-重发此包-------
errorCode=spi4_DMA_transition((uint32_t)buf,(uint32_t)DMA_CHMADDR_RESET_VALUE,4);
//-----方案2-接着走-------
// reLen=getDmaRemainLen(DMA1);//还剩下的长度
// reLen=4-reLen;//未发送的长度
// errorCode=spi4_DMA_transition((uint32_t)(buf+reLen),(uint32_t)DMA_CHMADDR_RESET_VALUE,reLen);
}
for(g=0;g<group;g++)
{
errorCode=spi4_DMA_transition((uint32_t)DMA_CHMADDR_RESET_VALUE,(uint32_t)(pbuffer+(g*packLen)),packLen);
while(errorCode)
{
//------方案1-重发此包-------
errorCode=spi4_DMA_transition((uint32_t)DMA_CHMADDR_RESET_VALUE,(uint32_t)(pbuffer+(g*packLen)),packLen);
//-----方案2-接着走-------
// reLen=getDmaRemainLen(DMA1);
// reLen=65535-reLen;
// errorCode=spi4_DMA_transition((uint32_t)DMA_CHMADDR_RESET_VALUE,(uint32_t)(buf+(g*65535)+reLen),reLen);
}
}
if(remain)
{
errorCode=spi4_DMA_transition((uint32_t)DMA_CHMADDR_RESET_VALUE,(uint32_t)(pbuffer+(g*packLen)),remain);
while(errorCode)
{
//------方案1-重发此包-------
errorCode=spi4_DMA_transition((uint32_t)DMA_CHMADDR_RESET_VALUE,(uint32_t)(pbuffer+(g*packLen)),remain);
//-----方案2-接着走-------
// reLen=getDmaRemainLen(DMA1);
// reLen=remain-reLen;
// errorCode=spi4_DMA_transition((uint32_t)DMA_CHMADDR_RESET_VALUE,(uint32_t)(buf+(g*65535)+reLen),reLen);
}
}
}else
{
if((read_addr>=FLASH_IMAGE_START_ADDR)&&(read_addr<FLASH_IMAGE_START_ADDR+FLASH_PIC_TEXT_SIZE))
{
norFlashUseDma=norFlashUseDma;
}
/* 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);
/* while there is data to be read */
while(num_byte_to_read--){
/* read a byte from the flash */
*pbuffer = spi_flash_send_byte(DUMMY_BYTE);
/* point to the next location where the byte read will be saved */
pbuffer++;
}
}
SPI_FLASH_CS_HIGH();
}