spi dma 双缓冲区读取flash内容(匹配i2s)
https://chuna2.787528.xyz/li5920o/p/19335935
在此音频调试基础上进行flash的读取
app_flash.c
#include "app_flash.h"
#include "GD25Q64F_SPI_Driver.h"
#include "spi_demo.h"
#include "app_i2s.h"
#include "crc_demo.h"
flash_handle_t flash_control = {
.uflash_Dummy_data = {0x00}
#ifdef FLASH_RWTEST
,
.crc_bt = {
.uflash_test_rdata = {0} // 注意:这里只初始化第一个元素为0
}
#endif
};
flash_state_t audio1_flash_state = {
.flash_init_magic = FLASH_INIT_MAGIC};
/**
* @brief: flash read data
* @param None
* @param None
* @retval : None
*/
void flash_read_data(uint32_t address, uint8_t *updata, uint32_t Length)
{
if (updata == NULL || Length == 0)
return;
/*只读*/
/*cs使能*/
GD25Q64_FLASH_CS_Low(); /*cs irq 拉高*/
/*发送写page命令*/
SPI_Send_ReceiveByte(CMD_FAST_READ);
/*发送地址byte*/
SPI_Send_ReceiveByte((address & 0xFF0000) >> 16);
/*发送地址byte*/
SPI_Send_ReceiveByte((address & 0xFF00) >> 8);
/*发送地址byte*/
SPI_Send_ReceiveByte(address & 0xFF);
/*发送地址byte*/
SPI_Send_ReceiveByte(FLASH_DUMMY_BYTE & 0xFF);
// uint8_t temp = SPI2_SFR->BUFR;
/*start dma*/
/*rx*/
DMA0_SFR->CTLR6 &= ~((uint32_t)0xFFFF << 16);
DMA0_SFR->CTLR6 |= (((uint32_t)(Length)) << 16);
DMA0_SFR->MADDR6 = (uint32_t)(updata);
/*tx 空数据启动时钟*/
DMA0_SFR->CTLR5 &= ~((uint32_t)0xFFFF << 16);
DMA0_SFR->CTLR5 |= (((uint32_t)(Length)) << 16);
DMA0_SFR->MADDR5 = (uint32_t)(flash_control.uflash_Dummy_data);
/*enable dma*/
// SPI2_SFR->CTLR &=~(1 << 0);
SPI_Send_ReceiveByte(FLASH_DUMMY_BYTE & 0xFF);
// DMA_Oneshot_Enable(DMA0_SFR , DMA_CHANNEL_6 ,TRUE);
// DMA_Oneshot_Enable(DMA0_SFR , DMA_CHANNEL_5 ,TRUE);
DMA0_SFR->CTLR6 |= 1;
DMA0_SFR->CTLR5 |= 1;
// DMA_Oneshot_Enable(DMA0_SFR , DMA_CHANNEL_6 ,TRUE);
// DMA_Oneshot_Enable(DMA0_SFR , DMA_CHANNEL_5 ,TRUE);
// SPI2_SFR->CTLR |= 1 << 0;
}
/**
* @brief: 检查是否已经擦除
* @param None
* @param None
* @retval : None
*/
uint8_t flash_is_initialized(void)
{
uint32_t magic;
gd25q_read(FLASH_INIT_FLAG, (uint8_t *)&magic, 4);
if (magic == FLASH_INIT_MAGIC)
return 1;
else
return 0;
}
/**
* @brief: 检查 块 是否已经擦除
* @param None
* @param None
* @retval : None
*/
uint8_t flash_chunk_initialized(flash_state_t *flash_state, uint32_t address)
{
uint32_t magic;
gd25q_read(address, (uint8_t *)&magic, 4);
if (magic == FLASH_INIT_MAGIC)
return 1;
else
return 0;
}
/**
* @brief: init(全片擦除 写flag)
* @param None
* @param None
* @retval : None
*/
void flash_initialize(void)
{
if (!flash_is_initialized())
{
gd25q_chip_erase(); /*全片擦除*/
/*write init flag*/
flash_WriteData(FLASH_INIT_ADDR, (uint8_t *)&audio1_flash_state.flash_init_magic, 4);
}
}
/**
* @brief: 写入音频数据
* @param None
* @param None
* @retval : 0 ? 1 write finish
*/
uint8_t Audio_Load_Write(flash_state_t *flash_state, const data_t *audio_data, uint32_t address, uint32_t Length)
{
if (audio_data == NULL || Length == 0)
return 0;
flash_state->flash_init_magic = FLASH_INIT_MAGIC;
flash_state->flash_data_address[0] = address;
flash_state->flash_data_address[1] = address + Length;
flash_state->DATA_Length = Length - 4;
uint32_t uflash_Flag_Address = flash_state->flash_data_address[0] + FLASH_CHUNK_SIZE - FLASH_PAGE_SIZE;
if (!flash_chunk_initialized(flash_state, uflash_Flag_Address))
{
gd25q_block_erase_64k(flash_state->flash_data_address[0]); /*块 擦除*/
/*write audio*/
flash_WriteData(flash_state->flash_data_address[0], (uint8_t *)audio_data, Length);
/*write init flag*/
flash_WriteData(uflash_Flag_Address, (uint8_t *)flash_state, sizeof(*flash_state));
return 1;
}
return 0;
}
/**
* @brief: 验证某音频数据完整性
* @param None
* @param None
* @retval : 1 正确 0 err
*/
uint8_t FlashVerify(uint32_t AddRess, uint8_t *VerifyFifo, uint8_t *VerifyFlag)
{
if (VerifyFifo == NULL)
return 0;
uint32_t flashmagic = 0, flash_address = 0, _Length = 0;
uint32_t SectionNum = 0;
uint16_t Remainder = 0;
uint32_t crc32 = 0, CrcAudio = 0;
uint32_t FlChunkFlag = 0;
switch (AddRess)
{
case FLASH_CHUNK_ADDR0:
FlChunkFlag = FLASH_CHUNK_FLAG0;
break;
case FLASH_CHUNK_ADDR1:
FlChunkFlag = FLASH_CHUNK_FLAG1;
break;
case FLASH_CHUNK_ADDR2:
FlChunkFlag = FLASH_CHUNK_FLAG2;
break;
case FLASH_CHUNK_ADDR3:
FlChunkFlag = FLASH_CHUNK_FLAG3;
break;
case FLASH_CHUNK_ADDR4:
FlChunkFlag = FLASH_CHUNK_FLAG4;
break;
case FLASH_CHUNK_ADDR5:
FlChunkFlag = FLASH_CHUNK_FLAG5;
break;
default:
return 0;
}
gd25q_read(FlChunkFlag, VerifyFlag, 16);
flashmagic |= ((VerifyFlag[3] << 24) //
| (VerifyFlag[2] << 16) //
| (VerifyFlag[1] << 8) //
| (VerifyFlag[0]));
flash_address |= ((VerifyFlag[11] << 24) //
| (VerifyFlag[10] << 16) //
| (VerifyFlag[9] << 8) //
| (VerifyFlag[8]));
_Length |= ((VerifyFlag[15] << 24) //
| (VerifyFlag[14] << 16) //
| (VerifyFlag[13] << 8) //
| (VerifyFlag[12]));
SectionNum = _Length / FLASH_READ_SIZE;
Remainder = _Length % FLASH_READ_SIZE;
while (SectionNum)
{
gd25q_read(AddRess, VerifyFifo, FLASH_READ_SIZE);
CRC32_CalcBlock((uint8_t const *)VerifyFifo, FLASH_READ_SIZE);
AddRess += FLASH_READ_SIZE;
SectionNum--;
}
if (!Remainder)
{
}
else
{
gd25q_read(AddRess, VerifyFifo, Remainder);
CRC32_CalcBlock((uint8_t const *)VerifyFifo, Remainder);
AddRess += Remainder;
}
gd25q_read(AddRess, VerifyFlag, 4);
CrcAudio |= ((VerifyFlag[3] << 24) //
| (VerifyFlag[2] << 16) //
| (VerifyFlag[1] << 8) //
| (VerifyFlag[0]));
crc32 = CRC_GET_RESULT();
// CRC_Reset();
if (crc32 == CrcAudio)
{
return 1;
}
else
{
return 0;
}
}
/**
* @brief: 验证ALL音频数据完整性
* @param None
* @param None
* @retval : None
*/
void AllFlashAudioVerify()
{
// uint8_t FlashVerify(uint32_t AddRess, uint8_t *VerifyFifo ,uint8_t *VerifyFlag);
}
/**
* @brief: powerful function
* @param None
* @param None
* @retval : None
*/
void FlashFunction(const data_t *audio_data, uint32_t Length)
{
if (1 == Audio_Load_Write(&audio1_flash_state, audio_data, FLASH_CHUNK_ADDR0, Length))
{
}
if(FlashVerify(FLASH_CHUNK_ADDR0, player.dma_buffer ,flash_control.ucrc_flag))
{
}
}
#ifdef FLASH_RWTEST
/**
* @brief: read
* @param None
* @param None
* @retval : None
*/
uint8_t flash_test_read()
{
uint32_t flashmagic = 0, flash_address = 0, _Length = 0;
uint32_t SectionNum = 0;
uint16_t Remainder = 0;
uint32_t AddRess = FLASH_CHUNK_ADDR0;
uint32_t crc32 = 0;
uint32_t CrcAudio = 0;
// flash_read_data(FLASH_CHUNK_FLAG0, flash_control.ucrc_flag, 17);
gd25q_read(FLASH_CHUNK_FLAG0, flash_control.ucrc_flag, 16);
flashmagic |= ((flash_control.ucrc_flag[3] << 24) //
| (flash_control.ucrc_flag[2] << 16) //
| (flash_control.ucrc_flag[1] << 8) //
| (flash_control.ucrc_flag[0]));
// flashmagic = ((flash_control.ucrc_flag[8] << 24) //
// | (flash_control.ucrc_flag[7] << 16) //
// | (flash_control.ucrc_flag[6] << 8) //
// | (flash_control.ucrc_flag[5]));
flash_address |= ((flash_control.ucrc_flag[11] << 24) //
| (flash_control.ucrc_flag[10] << 16) //
| (flash_control.ucrc_flag[9] << 8) //
| (flash_control.ucrc_flag[8]));
_Length |= ((flash_control.ucrc_flag[15] << 24) //
| (flash_control.ucrc_flag[14] << 16) //
| (flash_control.ucrc_flag[13] << 8) //
| (flash_control.ucrc_flag[12]));
SectionNum = _Length / FLASH_READ_SIZE;
Remainder = _Length % FLASH_READ_SIZE;
while (SectionNum)
{
// flash_read_data(FLASH_CHUNK_ADDR0, flash_control.crc_bt.uflash_test_rdata, 2049);
gd25q_read(AddRess, flash_control.crc_bt.uflash_test_rdata, FLASH_READ_SIZE);
CRC32_CalcBlock((uint8_t const *)(&flash_control.crc_bt.uflash_test_rdata[0]), FLASH_READ_SIZE);
AddRess += FLASH_READ_SIZE;
SectionNum--;
}
if (!Remainder)
{
}
else
{
gd25q_read(AddRess, flash_control.crc_bt.uflash_test_rdata, Remainder);
CRC32_CalcBlock((uint8_t const *)(&flash_control.crc_bt.uflash_test_rdata[0]), Remainder);
AddRess += Remainder;
}
gd25q_read(AddRess, flash_control.ucrc_flag, 4);
CrcAudio |= ((flash_control.ucrc_flag[3] << 24) //
| (flash_control.ucrc_flag[2] << 16) //
| (flash_control.ucrc_flag[1] << 8) //
| (flash_control.ucrc_flag[0]));
crc32 = CRC_GET_RESULT();
if (crc32 == CrcAudio)
{
return 1;
}
else
{
return 0;
}
}
/**
* @brief: Test
* @param None
* @param None
* @retval : None
*/
void Flash_Test_Function(const data_t *audio_data, uint32_t Length)
{
// flash_initialize();
// flash_test_read();
if(FlashVerify(FLASH_CHUNK_ADDR0, flash_control.crc_bt.uflash_test_rdata ,flash_control.ucrc_flag))
{
Length = 0;
}
// flash_read_data(FLASH_CHUNK_FLAG0, flash_control.ucrc_flag, 17);
// if (1 == Audio_Load_Write(&audio1_flash_state, audio_data, FLASH_CHUNK_ADDR0, Length))
// {
//
// }
}
#endif
/**
* @brief: flash write irq
* @param None
* @param None
* @retval : None
*/
void Flash_TxCallback(void)
{
if (DMA_Get_Finish_Transfer_INT_Flag(DMA0_SFR, DMA_CHANNEL_5))
{
/* Clear interrupt flag */
DMA_Clear_INT_Flag(DMA0_SFR, DMA_CHANNEL_5, DMA_INT_FINISH_TRANSFER);
/* Enable next transmit */
}
}
/**
* @brief: flash write half irq
* @param None
* @param None
* @retval : None
*/
void Flash_TxHalfCallback(void)
{
if (DMA_Get_Half_Transfer_INT_Flag(DMA0_SFR, DMA_CHANNEL_5))
{
/* Clear interrupt flag */
DMA_Clear_INT_Flag(DMA0_SFR, DMA_CHANNEL_5, DMA_INT_HALF_TRANSFER);
/* Enable next transmit */
}
}
/**
* @brief: flash read irq
* @param None
* @param None
* @retval : None
*/
void Flash_RxCallback(void)
{
if (DMA_Get_Finish_Transfer_INT_Flag(DMA0_SFR, DMA_CHANNEL_6))
{
/* Clear interrupt flag */
DMA_Clear_INT_Flag(DMA0_SFR, DMA_CHANNEL_6, DMA_INT_FINISH_TRANSFER);
/* Enable next transmit */
GD25Q64_FLASH_CS_High();
}
}
/**
* @brief: flash read half irq
* @param None
* @param None
* @retval : None
*/
void Flash_RxHalfCallback(void)
{
if (DMA_Get_Half_Transfer_INT_Flag(DMA0_SFR, DMA_CHANNEL_6))
{
/* Clear interrupt flag */
DMA_Clear_INT_Flag(DMA0_SFR, DMA_CHANNEL_6, DMA_INT_HALF_TRANSFER);
/* Enable next transmit */
}
}
app_flash.h
#ifndef __APP_FLASH_
#define __APP_FLASH_
#include "GD25Q64F_SPI_Driver.h"
#include "app_i2s.h"
#include "stdint.h"
//#define FLASH_RWTEST
#define FLASH_INIT_ADDR 0x00000000
#define FLASH_INIT_MAGIC 0xA5A55A5A
#define FLASH_INIT_FLAG FLASH_INIT_ADDR + FLASH_CHUNK_SIZE - FLASH_PAGE_SIZE
/*chunk address */
#define FLASH_CHUNK_ADDR0 FLASH_INIT_ADDR
#define FLASH_CHUNK_ADDR1 FLASH_CHUNK_ADDR0 + FLASH_CHUNK_SIZE
#define FLASH_CHUNK_ADDR2 FLASH_CHUNK_ADDR1 + FLASH_CHUNK_SIZE
#define FLASH_CHUNK_ADDR3 FLASH_CHUNK_ADDR2 + FLASH_CHUNK_SIZE
#define FLASH_CHUNK_ADDR4 FLASH_CHUNK_ADDR3 + FLASH_CHUNK_SIZE
#define FLASH_CHUNK_ADDR5 FLASH_CHUNK_ADDR4 + FLASH_CHUNK_SIZE
/*chunk flag address */
#define FLASH_CHUNK_FLAG0 FLASH_INIT_FLAG
#define FLASH_CHUNK_FLAG1 FLASH_CHUNK_FLAG0 + FLASH_CHUNK_SIZE
#define FLASH_CHUNK_FLAG2 FLASH_CHUNK_FLAG1 + FLASH_CHUNK_SIZE
#define FLASH_CHUNK_FLAG3 FLASH_CHUNK_FLAG2 + FLASH_CHUNK_SIZE
#define FLASH_CHUNK_FLAG4 FLASH_CHUNK_FLAG3 + FLASH_CHUNK_SIZE
#define FLASH_CHUNK_FLAG5 FLASH_CHUNK_FLAG4 + FLASH_CHUNK_SIZE
typedef struct
{
uint8_t uflash_Dummy_data[1]; /*Dummy_data*/
#ifdef FLASH_RWTEST
union
{
uint8_t uflash_test_rdata[2048]; /*test data*/
uint32_t uFlashData[512];
} crc_bt;
#endif
uint8_t ucrc_flag[17];
} flash_handle_t;
typedef struct
{
uint32_t flash_init_magic; /*是否全片擦除*/
uint32_t flash_data_address[2]; /*数据 起始 结束地址*/
uint32_t DATA_Length; /*数据长度*/
} flash_state_t;
typedef union
{
uint8_t u8data[4];
uint32_t u32Data;
} byteAlign_t;
extern flash_handle_t flash_control;
extern flash_state_t audio1_flash_state;
/**
* @brief: powerful function
* @param None
* @param None
* @retval : None
*/
void FlashFunction(const data_t *audio_data, uint32_t Length);
#ifdef FLASH_RWTEST
/**
* @brief: Test
* @param None
* @param None
* @retval : None
*/
void Flash_Test_Function(const data_t *audio_data, uint32_t Length);
#endif
/**
* @brief: flash read data
* @param None
* @param None
* @retval : None
*/
void flash_read_data(uint32_t address, uint8_t *updata, uint32_t Length);
/**
* @brief: flash write irq
* @param None
* @param None
* @retval : None
*/
void Flash_TxCallback(void);
/**
* @brief: flash write half irq
* @param None
* @param None
* @retval : None
*/
void Flash_TxHalfCallback(void);
/**
* @brief: flash read irq
* @param None
* @param None
* @retval : None
*/
void Flash_RxCallback(void);
/**
* @brief: flash read half irq
* @param None
* @param None
* @retval : None
*/
void Flash_RxHalfCallback(void);
#endif
浙公网安备 33010602011771号