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

posted on 2026-01-28 19:53  li5920o  阅读(11)  评论(0)    收藏  举报

导航