715 lines
21 KiB
C
715 lines
21 KiB
C
/*----------------------------------------------------------------------------
|
||
* Copyright (c) Fenda Technologies Co., Ltd. 2020. All rights reserved.
|
||
*
|
||
* Description: flash drv_mx25u51245g.c
|
||
*
|
||
* Author: saimen
|
||
*
|
||
* Create: 2021-04-27
|
||
*--------------------------------------------------------------------------*/
|
||
|
||
#include <stdbool.h>
|
||
#include <stdint.h>
|
||
#include <string.h>
|
||
|
||
#include "am_mcu_apollo.h"
|
||
#include "am_bsp.h"
|
||
#include "am_util_stdio.h"
|
||
#include "am_util_delay.h"
|
||
#include "am_util.h"
|
||
|
||
#include "config_hw.h"
|
||
#include "drv_mspi.h"
|
||
#include "drv_mx25u51245g.h"
|
||
#include "user_flash_ate.h"
|
||
#include "debug_print.h"
|
||
|
||
|
||
#define mx25u512_mspi_module 1
|
||
|
||
//#define ENABLE_MX25U512_LOG
|
||
|
||
#ifdef ENABLE_MX25U512_LOG
|
||
#define mx25u512_debug_print(...) am_util_stdio_printf(__VA_ARGS__)
|
||
#else
|
||
#define mx25u512_debug_print(...)
|
||
#endif
|
||
|
||
|
||
/***************************************************************************************************/
|
||
|
||
static volatile bool bDMAComplete = true;
|
||
|
||
static uint32_t g_mx25u512_mspi_buff[32] = {0};
|
||
static uint32_t g_mx25u512_mspi_dma_buf[256] = {0};
|
||
|
||
static mx25u512_info_t mx25u512_info = {0};
|
||
|
||
static const am_hal_mspi_dev_config_t mx25u512_serial_mspi_config =
|
||
{
|
||
.eSpiMode = AM_HAL_MSPI_SPI_MODE_0,
|
||
.eClockFreq = AM_HAL_MSPI_CLK_48MHZ, //AM_HAL_MSPI_CLK_8MHZ
|
||
.ui8TurnAround = 8,
|
||
.eAddrCfg = AM_HAL_MSPI_ADDR_4_BYTE,
|
||
.eInstrCfg = AM_HAL_MSPI_INSTR_1_BYTE,
|
||
.eDeviceConfig = AM_HAL_MSPI_FLASH_SERIAL_CE0,
|
||
//.bSeparateIO = true,
|
||
.bSendInstr = true,
|
||
.bSendAddr = true,
|
||
.bTurnaround = true,
|
||
|
||
#if !defined(AM_PART_APOLLO4)
|
||
.ui32TCBSize = 0,
|
||
.pTCB = NULL,
|
||
.scramblingStartAddr = 0,
|
||
.scramblingEndAddr = 0,
|
||
#endif
|
||
};
|
||
|
||
static const am_hal_mspi_dev_config_t mx25u512_quad_mspi_config =
|
||
{
|
||
.eSpiMode = AM_HAL_MSPI_SPI_MODE_0,
|
||
.eClockFreq = AM_HAL_MSPI_CLK_48MHZ,
|
||
.ui8TurnAround = 6,
|
||
.eAddrCfg = AM_HAL_MSPI_ADDR_4_BYTE,
|
||
.eInstrCfg = AM_HAL_MSPI_INSTR_1_BYTE,
|
||
.eDeviceConfig = AM_HAL_MSPI_FLASH_QUAD_CE0,
|
||
//.bSeparateIO = false,
|
||
.bSendInstr = true,
|
||
.bSendAddr = true,
|
||
.bTurnaround = true,
|
||
#if defined(AM_PART_APOLLO4)
|
||
.ui16ReadInstr = 0xEC,
|
||
.ui16WriteInstr = 0x02,
|
||
#else
|
||
.ui8ReadInstr = 0xEC,
|
||
.ui8WriteInstr = 0x02,
|
||
#endif
|
||
|
||
#if !defined(AM_PART_APOLLO4)
|
||
.ui32TCBSize = (sizeof(g_mx25u512_mspi_dma_buf) / sizeof(g_mx25u512_mspi_dma_buf[0])),
|
||
.pTCB = g_mx25u512_mspi_dma_buf,
|
||
.scramblingStartAddr = 0,
|
||
.scramblingEndAddr = 0,
|
||
#endif
|
||
.ui16DMATimeLimit = 0,
|
||
.eDMABoundary = AM_HAL_MSPI_BOUNDARY_NONE,
|
||
};
|
||
|
||
#if defined(AM_PART_APOLLO4)
|
||
static const am_hal_mspi_config_t mx25u512_quad_mspi_tcb_config =
|
||
{
|
||
.ui32TCBSize = (sizeof(g_mx25u512_mspi_dma_buf) / sizeof(g_mx25u512_mspi_dma_buf[0])),
|
||
.pTCB = g_mx25u512_mspi_dma_buf,
|
||
};
|
||
#endif
|
||
|
||
|
||
void mx25u512_dma_delay(uint32_t count)
|
||
{
|
||
#if defined(AM_PART_APOLLO4)
|
||
am_util_delay_us(count);
|
||
#else
|
||
am_hal_flash_delay(FLASH_CYCLES_US(count));
|
||
#endif
|
||
}
|
||
|
||
void mx25u512_read_write_cb(void *cb_context, uint32_t status)
|
||
{
|
||
uint8_t* Complete = (uint8_t *)cb_context;
|
||
|
||
if (status == AM_HAL_STATUS_SUCCESS)
|
||
{
|
||
*Complete = true;
|
||
}
|
||
|
||
mx25u512_debug_print("mx25u512 dma cb done %d\r\n", status);
|
||
if(mx25u512_info.transfer_cb)
|
||
{
|
||
mx25u512_info.transfer_cb(cb_context, status);
|
||
}
|
||
}
|
||
|
||
uint32_t mx25u512_enter_deep_power_down(void)
|
||
{
|
||
// drv_mspi_t *p_mspi_dev = &g_mspi_dev[mx25u512_mspi_module];
|
||
uint32_t status = AM_HAL_STATUS_SUCCESS;
|
||
|
||
status = mspi_write_cmd(mx25u512_mspi_module, ENTER_DEEP_POWER_DOWN_CMD, NULL, 0);
|
||
// 因影响lcd驱动的mspi功能,暂时屏蔽
|
||
//am_hal_mspi_power_control(p_mspi_dev->pHandle, AM_HAL_SYSCTRL_DEEPSLEEP, true);
|
||
//am_util_delay_ms(10);
|
||
mx25u512_debug_print("mx25u512 enter deep power down >>>>> \n");
|
||
|
||
return status;
|
||
}
|
||
|
||
uint32_t mx25u512_exit_deep_power_down(void)
|
||
{
|
||
drv_mspi_t *p_mspi_dev = &g_mspi_dev[mx25u512_mspi_module];
|
||
uint32_t status = AM_HAL_STATUS_SUCCESS;
|
||
|
||
am_hal_mspi_initialize(mx25u512_mspi_module, &p_mspi_dev->pHandle);
|
||
// 因影响lcd驱动的mspi功能,暂时屏蔽
|
||
//am_hal_mspi_power_control(p_mspi_dev->pHandle, AM_HAL_SYSCTRL_WAKE, true);
|
||
|
||
memcpy(&p_mspi_dev->hal_config, &mx25u512_quad_mspi_config, sizeof(am_hal_mspi_dev_config_t));
|
||
#if defined(AM_PART_APOLLO4)
|
||
memcpy(&p_mspi_dev->tcb_config, &mx25u512_quad_mspi_tcb_config, sizeof(am_hal_mspi_config_t));
|
||
#endif
|
||
status = mspi_mode_switch(mx25u512_mspi_module);
|
||
if (AM_HAL_STATUS_SUCCESS != status)
|
||
{
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
|
||
/* NVIC_EnableIRQ(mspi_interrupts[mx25u512_mspi_module]);
|
||
|
||
am_hal_interrupt_master_enable(); */
|
||
|
||
status = mspi_write_cmd(mx25u512_mspi_module, RELEASE_DEEP_POWER_DOWN_CMD, NULL, 0);
|
||
am_util_delay_ms(10);
|
||
|
||
mx25u512_debug_print("mx25u512 release from deep power down >>>>> \n");
|
||
|
||
return status;
|
||
}
|
||
|
||
uint32_t mx25u512_read_status_reg(uint8_t *pdata)
|
||
{
|
||
uint32_t status = mspi_read_cmd(mx25u512_mspi_module, READ_STATUS_REG_CMD, (uint32_t *)pdata, 1);
|
||
return status;
|
||
}
|
||
|
||
uint32_t mx25u512_set_4byte_mode(void)
|
||
{
|
||
uint32_t status = mspi_write_cmd(mx25u512_mspi_module, ENTER_4_BYTES_CMD, g_mx25u512_mspi_buff, 0);
|
||
return status;
|
||
}
|
||
|
||
uint32_t mx25u512_read_chip_id(uint32_t *chip_id)
|
||
{
|
||
uint32_t temp_id = 0;
|
||
uint32_t status = mspi_read_cmd(mx25u512_mspi_module, QREAD_ID_CMD, &temp_id, 3);
|
||
*chip_id = ((temp_id & 0xff) << 16) | ((temp_id & 0xff00)) | ((temp_id & 0xff0000) >> 16);
|
||
return status;
|
||
}
|
||
|
||
uint32_t mx25u512_reset(void)
|
||
{
|
||
uint32_t status = AM_HAL_STATUS_SUCCESS;
|
||
|
||
status = mspi_write_cmd(mx25u512_mspi_module, ENABLE_RESET, g_mx25u512_mspi_buff, 0);
|
||
if(status != AM_HAL_STATUS_SUCCESS)
|
||
{
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
|
||
status = mspi_write_cmd(mx25u512_mspi_module, RESET_DEV, g_mx25u512_mspi_buff, 0);
|
||
if(status != AM_HAL_STATUS_SUCCESS)
|
||
{
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
|
||
return AM_HAL_STATUS_SUCCESS;
|
||
}
|
||
|
||
uint32_t mx25u512_qspi_mode_init(void)
|
||
{
|
||
drv_mspi_t *p_mspi_dev = &g_mspi_dev[mx25u512_mspi_module];
|
||
uint32_t status = AM_HAL_STATUS_SUCCESS;
|
||
uint32_t reg_05 = 0;
|
||
uint32_t reg_15 = 0x2740;
|
||
|
||
mspi_write_cmd(mx25u512_mspi_module, WRITE_ENABLE_CMD, ®_05, 0);
|
||
mspi_write_cmd(mx25u512_mspi_module, WRITE_STATUS_CONF_REG_CMD, ®_15, 2);
|
||
mspi_write_cmd(mx25u512_mspi_module, WRITE_DISABLE_CMD, ®_05, 0);
|
||
|
||
mspi_write_cmd(mx25u512_mspi_module, ENTER_4_BYTES_CMD, g_mx25u512_mspi_buff, 0);
|
||
mspi_write_cmd(mx25u512_mspi_module, ENTER_QPI_MODE_CMD, g_mx25u512_mspi_buff, 0);
|
||
|
||
memset(&p_mspi_dev->hal_config, 0x0, sizeof(am_hal_mspi_dev_config_t));
|
||
memcpy(&p_mspi_dev->hal_config, &mx25u512_quad_mspi_config, sizeof(am_hal_mspi_dev_config_t));
|
||
#if defined(AM_PART_APOLLO4)
|
||
memcpy(&p_mspi_dev->tcb_config, &mx25u512_quad_mspi_tcb_config, sizeof(am_hal_mspi_config_t));
|
||
#endif
|
||
status = mspi_mode_switch(mx25u512_mspi_module);
|
||
if (AM_HAL_STATUS_SUCCESS != status)
|
||
{
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
|
||
return AM_HAL_STATUS_SUCCESS;
|
||
}
|
||
|
||
uint32_t mx25u512_bus_init(void)
|
||
{
|
||
drv_mspi_t *p_mspi_dev = &g_mspi_dev[mx25u512_mspi_module];
|
||
|
||
p_mspi_dev->module = mx25u512_mspi_module;
|
||
|
||
memset(&p_mspi_dev->hal_config, 0x0, sizeof(am_hal_mspi_dev_config_t));
|
||
memcpy(&p_mspi_dev->hal_config, &mx25u512_serial_mspi_config, sizeof(am_hal_mspi_dev_config_t));
|
||
#if defined(AM_PART_APOLLO4)
|
||
memcpy(&p_mspi_dev->tcb_config, &mx25u512_quad_mspi_tcb_config, sizeof(am_hal_mspi_config_t));
|
||
#endif
|
||
if (AM_HAL_STATUS_SUCCESS != mspi_open(mx25u512_mspi_module))
|
||
{
|
||
mx25u512_debug_print("Error - mx25u512 mspi_open failed.\n");
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
|
||
if (AM_HAL_STATUS_SUCCESS != mx25u512_reset())
|
||
{
|
||
mx25u512_debug_print("Error - mx25u512 reset failed.\n");
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
//am_util_delay_ms(100);
|
||
|
||
mx25u512_qspi_mode_init();
|
||
|
||
NVIC_EnableIRQ(mspi_interrupts[mx25u512_mspi_module]);
|
||
|
||
am_hal_interrupt_master_enable();
|
||
|
||
//
|
||
// Return the status.
|
||
//
|
||
return AM_HAL_STATUS_SUCCESS;
|
||
}
|
||
|
||
uint32_t mx25u512_buse_deinit(void)
|
||
{
|
||
if (AM_HAL_STATUS_SUCCESS != mspi_close(mx25u512_mspi_module))
|
||
{
|
||
mx25u512_debug_print("Error - mx25u512 mspi_close failed.\n");
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
|
||
return AM_HAL_STATUS_SUCCESS;
|
||
}
|
||
|
||
uint32_t mx25u512_erase_sector(uint32_t u32SectorAddr)
|
||
{
|
||
uint32_t status = AM_HAL_STATUS_SUCCESS;
|
||
uint32_t reg_status = 0;
|
||
bool complete = false;
|
||
|
||
mx25u512_debug_print("flash_erase: 0x%x\r\n", u32SectorAddr);
|
||
mspi_write_cmd(mx25u512_mspi_module, WRITE_ENABLE_CMD, NULL, 0);
|
||
mspi_write(mx25u512_mspi_module, 0x20, true, u32SectorAddr, false, NULL, 0);
|
||
|
||
for (uint32_t i = MX25U51245G_MSPI_TIMEOUT; i > 0; i--)
|
||
{
|
||
mspi_read_cmd(mx25u512_mspi_module, READ_STATUS_REG_CMD, ®_status, 1);
|
||
//mx25u512_debug_print("erase ---read reg 1 is %x\n", reg_status);
|
||
complete = reg_status & 0x01 ? false : true;
|
||
if (complete)
|
||
{
|
||
break;
|
||
}
|
||
am_util_delay_us(10);
|
||
}
|
||
|
||
status = mspi_write_cmd(mx25u512_mspi_module, WRITE_DISABLE_CMD, g_mx25u512_mspi_buff, 0);
|
||
if (AM_HAL_STATUS_SUCCESS != status)
|
||
{
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
uint32_t mx25u512_dma_read(uint32_t addr, uint8_t *pdata, uint32_t bytes)
|
||
{
|
||
uint32_t status = AM_HAL_STATUS_SUCCESS;
|
||
|
||
bDMAComplete = false;
|
||
mx25u512_debug_print("flash_read: 0x%x 0x%x %d\r\n", addr,pdata,bytes);
|
||
status = mspi_read_DMA(mx25u512_mspi_module, addr, (uint32_t *)pdata, bytes, mx25u512_read_write_cb, (void *)&bDMAComplete);
|
||
//mx25u512_debug_print("mx25u512 mspi_read_DMA bDMAComplete: %d, status: %d\n", bDMAComplete, status);
|
||
if (AM_HAL_STATUS_SUCCESS != status)
|
||
{
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
|
||
// Wait for DMA Complete or Timeout
|
||
for (uint32_t i = MX25U51245G_MSPI_TIMEOUT; i > 0; i--)
|
||
//for (uint32_t i = (MX25U51245G_MSPI_TIMEOUT/10); i > 0; i--)
|
||
{
|
||
if (bDMAComplete)
|
||
{
|
||
break;
|
||
}
|
||
//
|
||
// Call the BOOTROM cycle function to delay for about 1 microsecond.
|
||
//
|
||
//am_util_delay_us(10);
|
||
mx25u512_dma_delay(1);
|
||
}
|
||
|
||
// Check the status.
|
||
if (!bDMAComplete)
|
||
{
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
|
||
return AM_HAL_STATUS_SUCCESS;
|
||
}
|
||
|
||
//与mx25u512_dma_read相比,不带延迟等待
|
||
uint32_t mx25u512_dma_read_ex(uint32_t addr, uint8_t *pdata, uint32_t bytes)
|
||
{
|
||
uint32_t status = AM_HAL_STATUS_SUCCESS;
|
||
|
||
bDMAComplete = false;
|
||
mx25u512_debug_print("flash_read: 0x%x 0x%x %d\r\n", addr,pdata,bytes);
|
||
status = mspi_read_DMA(mx25u512_mspi_module, addr, (uint32_t *)pdata, bytes, mx25u512_read_write_cb, (void *)&bDMAComplete);
|
||
//mx25u512_debug_print("mx25u512 mspi_read_DMA bDMAComplete: %d, status: %d\n", bDMAComplete, status);
|
||
if (AM_HAL_STATUS_SUCCESS != status)
|
||
{
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
|
||
return AM_HAL_STATUS_SUCCESS;
|
||
}
|
||
|
||
uint32_t mx25u512_dma_write(uint32_t addr, uint8_t *pdata, uint32_t bytes)
|
||
{
|
||
uint32_t status = AM_HAL_STATUS_SUCCESS;
|
||
uint32_t curre_write_bytes = 0;
|
||
uint32_t remaind_bytes = 0;
|
||
|
||
while (bytes > 0)
|
||
{
|
||
status = mspi_write_cmd(mx25u512_mspi_module, WRITE_ENABLE_CMD, NULL, 0);
|
||
if (AM_HAL_STATUS_SUCCESS != status)
|
||
{
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
|
||
remaind_bytes = addr % MX25U51245G_PAGE_SIZE;
|
||
if (remaind_bytes != 0)
|
||
{
|
||
remaind_bytes = MX25U51245G_PAGE_SIZE - remaind_bytes;
|
||
if (bytes >= remaind_bytes)
|
||
{
|
||
curre_write_bytes = remaind_bytes;
|
||
}
|
||
else
|
||
{
|
||
curre_write_bytes = bytes;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (bytes >= MX25U51245G_PAGE_SIZE)
|
||
{
|
||
curre_write_bytes = MX25U51245G_PAGE_SIZE;
|
||
}
|
||
else
|
||
{
|
||
curre_write_bytes = bytes;
|
||
}
|
||
}
|
||
|
||
bDMAComplete = false;
|
||
status = mspi_write_DMA(mx25u512_mspi_module, addr, (uint32_t *)pdata, curre_write_bytes, mx25u512_read_write_cb, (void *)&bDMAComplete);
|
||
//mx25u512_debug_print("mx25u512 mspi_write_DMA bDMAComplete: %d, status: %d\n", bDMAComplete, status);
|
||
if (AM_HAL_STATUS_SUCCESS != status)
|
||
{
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
|
||
addr += curre_write_bytes;
|
||
pdata += curre_write_bytes;
|
||
bytes -= curre_write_bytes;
|
||
|
||
// Wait for DMA Complete or Timeout
|
||
for (uint32_t i = MX25U51245G_MSPI_TIMEOUT; i > 0; i--)
|
||
{
|
||
if (bDMAComplete)
|
||
{
|
||
break;
|
||
}
|
||
//
|
||
// Call the BOOTROM cycle function to delay for about 1 microsecond.
|
||
//
|
||
mx25u512_dma_delay(1);
|
||
}
|
||
|
||
// Check the status.
|
||
if (!bDMAComplete)
|
||
{
|
||
//
|
||
// Send the command sequence to disable writing.
|
||
//
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
else
|
||
{
|
||
mx25u512_wait_ready(0, MX25U51245G_MSPI_TIMEOUT);
|
||
//
|
||
// Send the command sequence to disable writing.
|
||
//
|
||
status = mspi_write_cmd(mx25u512_mspi_module, WRITE_DISABLE_CMD, g_mx25u512_mspi_buff, 0);
|
||
if (AM_HAL_STATUS_SUCCESS != status)
|
||
{
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
}
|
||
}
|
||
//mx25u512_debug_print("write ------------------------ status is %d\n", status);
|
||
|
||
return status;
|
||
}
|
||
|
||
void mx25u512_wait_ready(uint32_t delay_cs,uint32_t time_out)
|
||
{
|
||
bool complete = false;
|
||
uint32_t reg_status = 0;
|
||
uint32_t i = 0, time_step = 10;
|
||
|
||
if(delay_cs)
|
||
{
|
||
time_step = 1000;
|
||
}
|
||
i = time_out/time_step;
|
||
for (; i > 0; i--)
|
||
{
|
||
mspi_read_cmd(mx25u512_mspi_module, READ_STATUS_REG_CMD, ®_status, 1);
|
||
//mx25u512_debug_print("write ---read reg1 is %x\n", reg_status);
|
||
complete = reg_status & 0x01 ? false : true;
|
||
if (complete)
|
||
{
|
||
break;
|
||
}
|
||
if(delay_cs)
|
||
{
|
||
mx25u512_info.delay_ms(1);
|
||
}
|
||
else
|
||
{
|
||
am_util_delay_us(10);
|
||
}
|
||
}
|
||
}
|
||
|
||
//read write config
|
||
void drv_mx25u512_open(void)
|
||
{
|
||
mx25u512_info.lock();
|
||
ext_flash_power_on();
|
||
am_util_delay_ms(10);
|
||
mx25u512_bus_init();
|
||
mx25u512_info.status = true;
|
||
mx25u512_info.unlock();
|
||
}
|
||
|
||
void drv_mx25u512_close(void)
|
||
{
|
||
mx25u512_info.lock();
|
||
mx25u512_buse_deinit();
|
||
ext_flash_power_off();
|
||
mx25u512_info.status = false;
|
||
mx25u512_info.unlock();
|
||
}
|
||
|
||
void drv_mx25u512_info_init(void* delay_ms,void* lock,void* unlock,void* transfer_cb)
|
||
{
|
||
mx25u512_info.transfer_cb = transfer_cb;
|
||
mx25u512_info.lock = lock;
|
||
mx25u512_info.unlock = unlock;
|
||
mx25u512_info.delay_ms = delay_ms;
|
||
}
|
||
|
||
void drv_mx25u512_enter_power_down(void)
|
||
{
|
||
mx25u512_info.lock();
|
||
mx25u512_enter_deep_power_down();
|
||
mx25u512_info.unlock();
|
||
}
|
||
|
||
void drv_mx25u512_release_power_down(void)
|
||
{
|
||
mx25u512_info.lock();
|
||
mx25u512_exit_deep_power_down();
|
||
mx25u512_info.unlock();
|
||
}
|
||
|
||
uint32_t drv_mx25u512_read_id(void)
|
||
{
|
||
uint32_t temp_id = 0;
|
||
mx25u512_info.lock();
|
||
mx25u512_read_chip_id(&temp_id);
|
||
mx25u512_info.unlock();
|
||
return temp_id;
|
||
}
|
||
|
||
uint32_t drv_mx25u512_read_status(void)
|
||
{
|
||
return mx25u512_info.status;
|
||
}
|
||
|
||
extern uint32_t user_mspi_status_get(uint32_t module);
|
||
//read,write,erase flash
|
||
uint32_t drv_mx25u512_chip_erase(void)
|
||
{
|
||
uint32_t status;
|
||
|
||
mx25u512_info.lock();
|
||
while(user_mspi_status_get(mx25u512_mspi_module))
|
||
{
|
||
mx25u512_info.delay_ms(1);
|
||
}
|
||
status = mspi_write_cmd(mx25u512_mspi_module, WRITE_ENABLE_CMD, NULL, 0);
|
||
if(status == AM_HAL_STATUS_SUCCESS)
|
||
{
|
||
status = mspi_write(mx25u512_mspi_module, CHIP_ERASE_CMD, false, NULL, false, NULL, 0);
|
||
}
|
||
mx25u512_wait_ready(1,MX25U51245G_MSPI_CHIP_ERASE_TIMEOUT);
|
||
if(status == AM_HAL_STATUS_SUCCESS)
|
||
{
|
||
status = mspi_write_cmd(mx25u512_mspi_module, WRITE_DISABLE_CMD, g_mx25u512_mspi_buff, 0);
|
||
}
|
||
mx25u512_info.unlock();
|
||
|
||
return status;
|
||
}
|
||
|
||
uint32_t drv_mx25u512_sector_erase(uint32_t addr)
|
||
{
|
||
uint32_t status;
|
||
mx25u512_info.lock();
|
||
while(user_mspi_status_get(mx25u512_mspi_module))
|
||
{
|
||
mx25u512_info.delay_ms(1);
|
||
}
|
||
status = mx25u512_erase_sector(addr);
|
||
mx25u512_info.unlock();
|
||
return status;
|
||
}
|
||
|
||
uint32_t drv_mx25u512_smart_erase(uint32_t begin_addr,uint32_t end_addr)
|
||
{
|
||
uint32_t status;
|
||
uint32_t index_sector,begin_sector,end_sector;
|
||
|
||
if(begin_sector>end_sector || begin_addr>=MX25U51245G_TOTAL_SIZE || end_addr>=MX25U51245G_TOTAL_SIZE)
|
||
{
|
||
return AM_HAL_STATUS_FAIL;
|
||
}
|
||
|
||
mx25u512_info.lock();
|
||
while(user_mspi_status_get(mx25u512_mspi_module))
|
||
{
|
||
mx25u512_info.delay_ms(1);
|
||
}
|
||
status = mspi_write_cmd(mx25u512_mspi_module, WRITE_ENABLE_CMD, NULL, 0);
|
||
index_sector = begin_sector;
|
||
while(end_sector>=index_sector)
|
||
{
|
||
if(index_sector%16==0)
|
||
{
|
||
if(end_sector-index_sector>=16)
|
||
{
|
||
status = mspi_write(mx25u512_mspi_module, BLOCK_ERASE_CMD, true, (index_sector<<12), false, NULL, 0);
|
||
mx25u512_wait_ready(1,MX25U51245G_MSPI_TIMEOUT);
|
||
index_sector += 16;
|
||
}
|
||
else
|
||
{
|
||
status = mspi_write(mx25u512_mspi_module, SECTOR_ERASE_CMD, true, (index_sector<<12), false, NULL, 0);
|
||
mx25u512_wait_ready(1,MX25U51245G_MSPI_TIMEOUT);
|
||
index_sector++;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
status = mspi_write(mx25u512_mspi_module, SECTOR_ERASE_CMD, true, (index_sector<<12), false, NULL, 0);
|
||
mx25u512_wait_ready(1,MX25U51245G_MSPI_TIMEOUT);
|
||
index_sector++;
|
||
}
|
||
}
|
||
status = mspi_write_cmd(mx25u512_mspi_module, WRITE_DISABLE_CMD, g_mx25u512_mspi_buff, 0);
|
||
mx25u512_info.unlock();
|
||
|
||
return status;
|
||
}
|
||
|
||
uint32_t drv_mx25u512_read_nonblocking(uint8_t *pdata,uint32_t addr,uint32_t readlen)
|
||
{
|
||
uint32_t status;
|
||
mx25u512_info.lock();
|
||
while(user_mspi_status_get(mx25u512_mspi_module))
|
||
{
|
||
mx25u512_info.delay_ms(1);
|
||
}
|
||
status = mx25u512_dma_read(addr, pdata, readlen);
|
||
mx25u512_info.unlock();
|
||
return status;
|
||
}
|
||
|
||
//与drv_mx25u512_read_nonblocking相比,不带延迟等待
|
||
uint32_t drv_mx25u512_read_nonblocking_ex(uint8_t *pdata,uint32_t addr,uint32_t readlen)
|
||
{
|
||
uint32_t status;
|
||
mx25u512_info.lock();
|
||
#if 0
|
||
status = mx25u512_dma_read_ex(addr, pdata, readlen);
|
||
#else
|
||
bDMAComplete = false;
|
||
mx25u512_debug_print("flash_read: 0x%x 0x%x %d\r\n", addr, pdata, readlen);
|
||
#if 0
|
||
status = mspi_read_DMA(mx25u512_mspi_module, addr, (uint32_t *)pdata, readlen, mx25u512_read_write_cb, (void *)&bDMAComplete);
|
||
#else
|
||
drv_mspi_t *p_mspi_dev = &g_mspi_dev[mx25u512_mspi_module];
|
||
am_hal_mspi_dma_transfer_t Transaction = {0};
|
||
|
||
//
|
||
// Create the transaction.
|
||
//
|
||
Transaction.eDirection = AM_HAL_MSPI_RX;
|
||
Transaction.ui32DeviceAddress = addr;
|
||
// Clear the CQ stimulus.
|
||
// Transaction.ui32PauseCondition = 0;
|
||
Transaction.ui32SRAMAddress = (uint32_t)pdata;
|
||
// Clear the post-processing
|
||
// Transaction.ui32StatusSetClr = 0;
|
||
Transaction.ui32TransferCount = readlen;
|
||
Transaction.ui8Priority = 1;
|
||
|
||
status = am_hal_mspi_nonblocking_transfer(p_mspi_dev->pHandle, &Transaction, AM_HAL_MSPI_TRANS_DMA,
|
||
mx25u512_read_write_cb,
|
||
(void *)&bDMAComplete);
|
||
#endif
|
||
#endif
|
||
mx25u512_info.unlock();
|
||
return status;
|
||
}
|
||
|
||
uint32_t drv_mx25u512_write_nonblocking(uint8_t *pdata,uint32_t addr,uint32_t writelen)
|
||
{
|
||
uint32_t status;
|
||
mx25u512_info.lock();
|
||
while(user_mspi_status_get(mx25u512_mspi_module))
|
||
{
|
||
mx25u512_info.delay_ms(1);
|
||
}
|
||
status = mx25u512_dma_write(addr, pdata, writelen);
|
||
mx25u512_info.unlock();
|
||
return status;
|
||
}
|
||
|
||
void drv_mx25u512_maped(void)
|
||
{
|
||
drv_mspi_t *p_mspi_dev = &g_mspi_dev[mx25u512_mspi_module];
|
||
uint32_t status;
|
||
status = am_hal_mspi_control(p_mspi_dev->pHandle, AM_HAL_MSPI_REQ_XIP_EN, NULL);
|
||
if(AM_HAL_STATUS_SUCCESS != status) {
|
||
mx25u512_debug_print("Failed to put the MSPI mx25u512 into XIP mode! ret:%d\r\n", ui32Status);
|
||
return;
|
||
}
|
||
}
|
||
|