1576 lines
55 KiB
C
1576 lines
55 KiB
C
//*****************************************************************************
|
|
//
|
|
//! @file am_devices_mspi_atxp032.c
|
|
//!
|
|
//! @brief General Multibit SPI Flash driver.
|
|
//
|
|
//*****************************************************************************
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Copyright (c) 2020, Ambiq Micro
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are met:
|
|
//
|
|
// 1. Redistributions of source code must retain the above copyright notice,
|
|
// this list of conditions and the following disclaimer.
|
|
//
|
|
// 2. Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
//
|
|
// 3. Neither the name of the copyright holder nor the names of its
|
|
// contributors may be used to endorse or promote products derived from this
|
|
// software without specific prior written permission.
|
|
//
|
|
// Third party software included in this distribution is subject to the
|
|
// additional license terms as defined in the /docs/licenses directory.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
|
//
|
|
//*****************************************************************************
|
|
|
|
#include "am_mcu_apollo.h"
|
|
#include "am_devices_mspi_atxp032.h"
|
|
#include "am_util_stdio.h"
|
|
#include "am_bsp.h"
|
|
#include "am_util_delay.h"
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Global variables.
|
|
//
|
|
//*****************************************************************************
|
|
#define AM_DEVICES_MSPI_ATXP032_TIMEOUT 1000000
|
|
#define AM_DEVICES_MSPI_ATXP032_ERASE_TIMEOUT 1000000
|
|
|
|
typedef struct
|
|
{
|
|
uint32_t ui32Module;
|
|
void *pMspiHandle;
|
|
am_hal_mspi_dev_config_t stSetting;
|
|
bool bOccupied;
|
|
} am_devices_mspi_atxp032_t;
|
|
|
|
am_devices_mspi_atxp032_t gAmAtxp032[AM_DEVICES_MSPI_ATXP032_MAX_DEVICE_NUM];
|
|
|
|
am_hal_mspi_dev_config_t MSPI_ATXP032_Serial_CE0_MSPIConfig =
|
|
{
|
|
.eSpiMode = AM_HAL_MSPI_SPI_MODE_0,
|
|
.eClockFreq = AM_HAL_MSPI_CLK_24MHZ,
|
|
.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,
|
|
.ui8ReadInstr = AM_DEVICES_MSPI_ATXP032_FAST_READ,
|
|
.ui8WriteInstr = AM_DEVICES_MSPI_ATXP032_PAGE_PROGRAM,
|
|
#if defined(AM_PART_APOLLO3P)
|
|
.ui8WriteLatency = 0,
|
|
.bEnWriteLatency = false,
|
|
.bEmulateDDR = false,
|
|
.ui16DMATimeLimit = 0,
|
|
.eDMABoundary = AM_HAL_MSPI_BOUNDARY_NONE,
|
|
#endif
|
|
.ui32TCBSize = 0,
|
|
.pTCB = NULL,
|
|
.scramblingStartAddr = 0,
|
|
.scramblingEndAddr = 0,
|
|
};
|
|
|
|
am_hal_mspi_dev_config_t MSPI_ATXP032_Serial_CE1_MSPIConfig =
|
|
{
|
|
.eSpiMode = AM_HAL_MSPI_SPI_MODE_0,
|
|
.eClockFreq = AM_HAL_MSPI_CLK_24MHZ,
|
|
.ui8TurnAround = 8,
|
|
.eAddrCfg = AM_HAL_MSPI_ADDR_4_BYTE,
|
|
.eInstrCfg = AM_HAL_MSPI_INSTR_1_BYTE,
|
|
.eDeviceConfig = AM_HAL_MSPI_FLASH_SERIAL_CE1,
|
|
.bSeparateIO = true,
|
|
.bSendInstr = true,
|
|
.bSendAddr = true,
|
|
.bTurnaround = true,
|
|
.ui8ReadInstr = AM_DEVICES_MSPI_ATXP032_FAST_READ,
|
|
.ui8WriteInstr = AM_DEVICES_MSPI_ATXP032_PAGE_PROGRAM,
|
|
#if defined(AM_PART_APOLLO3P)
|
|
.ui8WriteLatency = 0,
|
|
.bEnWriteLatency = false,
|
|
.bEmulateDDR = false,
|
|
.ui16DMATimeLimit = 0,
|
|
.eDMABoundary = AM_HAL_MSPI_BOUNDARY_NONE,
|
|
#endif
|
|
.ui32TCBSize = 0,
|
|
.pTCB = NULL,
|
|
.scramblingStartAddr = 0,
|
|
.scramblingEndAddr = 0,
|
|
};
|
|
|
|
am_hal_mspi_dev_config_t MSPI_ATXP032_Quad_CE0_MSPIConfig =
|
|
{
|
|
.eSpiMode = AM_HAL_MSPI_SPI_MODE_0,
|
|
.eClockFreq = AM_HAL_MSPI_CLK_24MHZ,
|
|
.ui8TurnAround = 8,
|
|
.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,
|
|
.ui8ReadInstr = AM_DEVICES_MSPI_ATXP032_FAST_READ,
|
|
.ui8WriteInstr = AM_DEVICES_MSPI_ATXP032_PAGE_PROGRAM,
|
|
#if defined(AM_PART_APOLLO3P)
|
|
.ui8WriteLatency = 0,
|
|
.bEnWriteLatency = false,
|
|
.bEmulateDDR = false,
|
|
.ui16DMATimeLimit = 0,
|
|
.eDMABoundary = AM_HAL_MSPI_BOUNDARY_NONE,
|
|
#endif
|
|
.ui32TCBSize = 0,
|
|
.pTCB = NULL,
|
|
.scramblingStartAddr = 0,
|
|
.scramblingEndAddr = 0,
|
|
};
|
|
|
|
am_hal_mspi_dev_config_t MSPI_ATXP032_Quad_CE1_MSPIConfig =
|
|
{
|
|
.eSpiMode = AM_HAL_MSPI_SPI_MODE_0,
|
|
.eClockFreq = AM_HAL_MSPI_CLK_24MHZ,
|
|
.ui8TurnAround = 8,
|
|
.eAddrCfg = AM_HAL_MSPI_ADDR_4_BYTE,
|
|
.eInstrCfg = AM_HAL_MSPI_INSTR_1_BYTE,
|
|
.eDeviceConfig = AM_HAL_MSPI_FLASH_QUAD_CE1,
|
|
.bSeparateIO = false,
|
|
.bSendInstr = true,
|
|
.bSendAddr = true,
|
|
.bTurnaround = true,
|
|
.ui8ReadInstr = AM_DEVICES_MSPI_ATXP032_FAST_READ,
|
|
.ui8WriteInstr = AM_DEVICES_MSPI_ATXP032_PAGE_PROGRAM,
|
|
#if defined(AM_PART_APOLLO3P)
|
|
.ui8WriteLatency = 0,
|
|
.bEnWriteLatency = false,
|
|
.bEmulateDDR = false,
|
|
.ui16DMATimeLimit = 0,
|
|
.eDMABoundary = AM_HAL_MSPI_BOUNDARY_NONE,
|
|
#endif
|
|
.ui32TCBSize = 0,
|
|
.pTCB = NULL,
|
|
.scramblingStartAddr = 0,
|
|
.scramblingEndAddr = 0,
|
|
};
|
|
|
|
am_hal_mspi_dev_config_t MSPI_ATXP032_Octal_CE0_MSPIConfig =
|
|
{
|
|
.eSpiMode = AM_HAL_MSPI_SPI_MODE_0,
|
|
.eClockFreq = AM_HAL_MSPI_CLK_24MHZ,
|
|
.ui8TurnAround = 8,
|
|
.eAddrCfg = AM_HAL_MSPI_ADDR_4_BYTE,
|
|
.eInstrCfg = AM_HAL_MSPI_INSTR_1_BYTE,
|
|
.eDeviceConfig = AM_HAL_MSPI_FLASH_OCTAL_CE0,
|
|
.bSeparateIO = false,
|
|
.bSendInstr = true,
|
|
.bSendAddr = true,
|
|
.bTurnaround = true,
|
|
.ui8ReadInstr = AM_DEVICES_MSPI_ATXP032_FAST_READ,
|
|
.ui8WriteInstr = AM_DEVICES_MSPI_ATXP032_PAGE_PROGRAM,
|
|
#if defined(AM_PART_APOLLO3P)
|
|
.ui8WriteLatency = 0,
|
|
.bEnWriteLatency = false,
|
|
.bEmulateDDR = false,
|
|
.ui16DMATimeLimit = 0,
|
|
.eDMABoundary = AM_HAL_MSPI_BOUNDARY_NONE,
|
|
#endif
|
|
.ui32TCBSize = 0,
|
|
.pTCB = NULL,
|
|
.scramblingStartAddr = 0,
|
|
.scramblingEndAddr = 0,
|
|
};
|
|
|
|
am_hal_mspi_dev_config_t MSPI_ATXP032_Octal_CE1_MSPIConfig =
|
|
{
|
|
.eSpiMode = AM_HAL_MSPI_SPI_MODE_0,
|
|
.eClockFreq = AM_HAL_MSPI_CLK_24MHZ,
|
|
.ui8TurnAround = 8,
|
|
.eAddrCfg = AM_HAL_MSPI_ADDR_4_BYTE,
|
|
.eInstrCfg = AM_HAL_MSPI_INSTR_1_BYTE,
|
|
.eDeviceConfig = AM_HAL_MSPI_FLASH_OCTAL_CE1,
|
|
.bSeparateIO = false,
|
|
.bSendInstr = true,
|
|
.bSendAddr = true,
|
|
.bTurnaround = true,
|
|
.ui8ReadInstr = AM_DEVICES_MSPI_ATXP032_FAST_READ,
|
|
.ui8WriteInstr = AM_DEVICES_MSPI_ATXP032_PAGE_PROGRAM,
|
|
#if defined(AM_PART_APOLLO3P)
|
|
.ui8WriteLatency = 0,
|
|
.bEnWriteLatency = false,
|
|
.bEmulateDDR = false,
|
|
.ui16DMATimeLimit = 0,
|
|
.eDMABoundary = AM_HAL_MSPI_BOUNDARY_NONE,
|
|
#endif
|
|
.ui32TCBSize = 0,
|
|
.pTCB = NULL,
|
|
.scramblingStartAddr = 0,
|
|
.scramblingEndAddr = 0,
|
|
};
|
|
|
|
struct
|
|
{
|
|
am_hal_mspi_device_e eHalDeviceEnum;
|
|
am_hal_mspi_dev_config_t *psDevConfig;
|
|
}g_ATXP032_DevConfig[] =
|
|
{
|
|
{AM_HAL_MSPI_FLASH_SERIAL_CE0, &MSPI_ATXP032_Serial_CE0_MSPIConfig},
|
|
{AM_HAL_MSPI_FLASH_SERIAL_CE1, &MSPI_ATXP032_Serial_CE1_MSPIConfig},
|
|
{AM_HAL_MSPI_FLASH_QUAD_CE0, &MSPI_ATXP032_Quad_CE0_MSPIConfig},
|
|
{AM_HAL_MSPI_FLASH_QUAD_CE1, &MSPI_ATXP032_Quad_CE1_MSPIConfig},
|
|
{AM_HAL_MSPI_FLASH_OCTAL_CE0, &MSPI_ATXP032_Octal_CE0_MSPIConfig},
|
|
{AM_HAL_MSPI_FLASH_OCTAL_CE1, &MSPI_ATXP032_Octal_CE1_MSPIConfig},
|
|
};
|
|
|
|
//
|
|
// Forward declarations.
|
|
//
|
|
static uint32_t am_devices_mspi_atxp032_command_write(void *pHandle,
|
|
uint8_t ui8Instr,
|
|
bool bSendAddr,
|
|
uint32_t ui32Addr,
|
|
uint32_t *pData,
|
|
uint32_t ui32NumBytes);
|
|
static uint32_t am_devices_mspi_atxp032_command_read(void *pHandle,
|
|
uint8_t ui8Instr,
|
|
bool bSendAddr,
|
|
uint32_t ui32Addr,
|
|
uint32_t *pData,
|
|
uint32_t ui32NumBytes);
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Adesto ATXP032 Support
|
|
//
|
|
//*****************************************************************************
|
|
//
|
|
// Device specific initialization function.
|
|
//
|
|
static uint32_t
|
|
am_device_init_flash(void *pHandle)
|
|
{
|
|
uint32_t ui32PIOBuffer[32] = {0};
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
|
|
//
|
|
// Set the Dummy Cycles in Status/Control register 3 to 8.
|
|
//
|
|
am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_MSPI_ATXP032_WRITE_ENABLE, false, 0, ui32PIOBuffer, 0);
|
|
ui32PIOBuffer[0] = 0x00000003;
|
|
am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_ATXP032_WRITE_STATUS_CTRL, false, 0, ui32PIOBuffer, 2);
|
|
|
|
//
|
|
// Configure the ATXP032 mode based on the MSPI configuration.
|
|
//
|
|
am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_MSPI_ATXP032_WRITE_ENABLE, false, 0, ui32PIOBuffer, 0);
|
|
|
|
switch ( pFlash->stSetting.eDeviceConfig )
|
|
{
|
|
case AM_HAL_MSPI_FLASH_SERIAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_SERIAL_CE1:
|
|
am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_ATXP032_RETURN_TO_SPI_MODE, false, 0, ui32PIOBuffer, 0);
|
|
break;
|
|
case AM_HAL_MSPI_FLASH_DUAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_DUAL_CE1:
|
|
case AM_HAL_MSPI_FLASH_QUADPAIRED:
|
|
case AM_HAL_MSPI_FLASH_QUADPAIRED_SERIAL:
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
case AM_HAL_MSPI_FLASH_QUAD_CE0:
|
|
case AM_HAL_MSPI_FLASH_QUAD_CE1:
|
|
am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_ATXP032_ENTER_QUAD_MODE, false, 0, ui32PIOBuffer, 0);
|
|
break;
|
|
case AM_HAL_MSPI_FLASH_OCTAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_OCTAL_CE1:
|
|
am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_ATXP032_ENTER_OCTAL_MODE, false, 0, ui32PIOBuffer, 0);
|
|
break;
|
|
}
|
|
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Device specific de-initialization function.
|
|
//
|
|
static uint32_t
|
|
am_device_deinit_flash(void *pHandle)
|
|
{
|
|
uint32_t ui32Status;
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
uint32_t ui32PIOBuffer[32] = {0};
|
|
|
|
//
|
|
// Configure the Adesto ATXP032 Device mode.
|
|
//
|
|
switch (pFlash->stSetting.eDeviceConfig)
|
|
{
|
|
case AM_HAL_MSPI_FLASH_SERIAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_SERIAL_CE1:
|
|
// Nothing to do. Device defaults to SPI mode.
|
|
break;
|
|
case AM_HAL_MSPI_FLASH_QUAD_CE0:
|
|
case AM_HAL_MSPI_FLASH_QUAD_CE1:
|
|
case AM_HAL_MSPI_FLASH_OCTAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_OCTAL_CE1:
|
|
ui32Status = am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_ATXP032_RETURN_TO_SPI_MODE, false, 0, ui32PIOBuffer, 0);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
break;
|
|
case AM_HAL_MSPI_FLASH_DUAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_DUAL_CE1:
|
|
case AM_HAL_MSPI_FLASH_QUADPAIRED:
|
|
case AM_HAL_MSPI_FLASH_QUADPAIRED_SERIAL:
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
//break;
|
|
}
|
|
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Generic Command Write function.
|
|
//
|
|
//*****************************************************************************
|
|
static uint32_t
|
|
am_devices_mspi_atxp032_command_write(void *pHandle, uint8_t ui8Instr, bool bSendAddr,
|
|
uint32_t ui32Addr, uint32_t *pData,
|
|
uint32_t ui32NumBytes)
|
|
{
|
|
uint32_t ui32Status;
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
am_hal_mspi_pio_transfer_t stMSPIFlashPIOTransaction = {0};
|
|
|
|
// Create the individual write transaction.
|
|
stMSPIFlashPIOTransaction.ui32NumBytes = ui32NumBytes;
|
|
stMSPIFlashPIOTransaction.eDirection = AM_HAL_MSPI_TX;
|
|
stMSPIFlashPIOTransaction.bSendAddr = bSendAddr;
|
|
stMSPIFlashPIOTransaction.ui32DeviceAddr = ui32Addr;
|
|
stMSPIFlashPIOTransaction.bSendInstr = true;
|
|
stMSPIFlashPIOTransaction.ui16DeviceInstr = ui8Instr;
|
|
stMSPIFlashPIOTransaction.bTurnaround = false;
|
|
#if 0 // A3DS-25 Deprecate MSPI CONT
|
|
stMSPIFlashPIOTransaction.bContinue = false;
|
|
#endif // A3DS-25
|
|
if (AM_HAL_MSPI_FLASH_QUADPAIRED == pFlash->stSetting.eDeviceConfig)
|
|
{
|
|
stMSPIFlashPIOTransaction.bQuadCmd = true;
|
|
}
|
|
else
|
|
{
|
|
stMSPIFlashPIOTransaction.bQuadCmd = false;
|
|
}
|
|
stMSPIFlashPIOTransaction.pui32Buffer = pData;
|
|
|
|
// Execute the transction over MSPI.
|
|
ui32Status = am_hal_mspi_blocking_transfer(pFlash->pMspiHandle, &stMSPIFlashPIOTransaction,
|
|
AM_DEVICES_MSPI_ATXP032_TIMEOUT);
|
|
|
|
return ui32Status;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Generic Command Read function.
|
|
//
|
|
//*****************************************************************************
|
|
static uint32_t
|
|
am_devices_mspi_atxp032_command_read(void *pHandle, uint8_t ui8Instr, bool bSendAddr,
|
|
uint32_t ui32Addr, uint32_t *pData,
|
|
uint32_t ui32NumBytes)
|
|
{
|
|
uint32_t ui32Status;
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
am_hal_mspi_pio_transfer_t stMSPIFlashPIOTransaction = {0};
|
|
|
|
// Create the individual write transaction.
|
|
stMSPIFlashPIOTransaction.eDirection = AM_HAL_MSPI_RX;
|
|
stMSPIFlashPIOTransaction.bSendAddr = bSendAddr;
|
|
stMSPIFlashPIOTransaction.ui32DeviceAddr = ui32Addr;
|
|
stMSPIFlashPIOTransaction.bSendInstr = true;
|
|
stMSPIFlashPIOTransaction.ui16DeviceInstr = ui8Instr;
|
|
stMSPIFlashPIOTransaction.bTurnaround = false;
|
|
#if 0 // A3DS-25 Deprecate MSPI CONT
|
|
stMSPIFlashPIOTransaction.bContinue = false;
|
|
#endif // A3DS-25
|
|
if (AM_HAL_MSPI_FLASH_QUADPAIRED == pFlash->stSetting.eDeviceConfig)
|
|
{
|
|
stMSPIFlashPIOTransaction.ui32NumBytes = ui32NumBytes * 2;
|
|
stMSPIFlashPIOTransaction.bQuadCmd = true;
|
|
}
|
|
else
|
|
{
|
|
stMSPIFlashPIOTransaction.ui32NumBytes = ui32NumBytes;
|
|
stMSPIFlashPIOTransaction.bQuadCmd = false;
|
|
}
|
|
stMSPIFlashPIOTransaction.pui32Buffer = pData;
|
|
|
|
// Execute the transction over MSPI.
|
|
ui32Status = am_hal_mspi_blocking_transfer(pFlash->pMspiHandle, &stMSPIFlashPIOTransaction,
|
|
AM_DEVICES_MSPI_ATXP032_TIMEOUT);
|
|
|
|
return ui32Status;
|
|
}
|
|
|
|
static void
|
|
pfnMSPI_ATXP032_Callback(void *pCallbackCtxt, uint32_t status)
|
|
{
|
|
// Set the DMA complete flag.
|
|
*(volatile bool *)pCallbackCtxt = true;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Initialize the mspi_flash driver.
|
|
//!
|
|
//! @param psIOMSettings - IOM device structure describing the target spiflash.
|
|
//! @param pfnWriteFunc - Function to use for spi writes.
|
|
//! @param pfnReadFunc - Function to use for spi reads.
|
|
//!
|
|
//! This function should be called before any other am_devices_spiflash
|
|
//! functions. It is used to set tell the other functions how to communicate
|
|
//! with the external spiflash hardware.
|
|
//!
|
|
//! The \e pfnWriteFunc and \e pfnReadFunc variables may be used to provide
|
|
//! alternate implementations of SPI write and read functions respectively. If
|
|
//! they are left set to 0, the default functions am_hal_iom_spi_write() and
|
|
//! am_hal_iom_spi_read() will be used.
|
|
//!
|
|
//! @return None.
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_init(uint32_t ui32Module, am_devices_mspi_atxp032_config_t *psMSPISettings, void **ppHandle, void **ppMspiHandle)
|
|
{
|
|
uint32_t ui32Status;
|
|
am_hal_mspi_dev_config_t *psConfig = g_ATXP032_DevConfig[0].psDevConfig;
|
|
void *pMspiHandle;
|
|
uint32_t ui32Index = 0;
|
|
|
|
if ((ui32Module > AM_REG_MSPI_NUM_MODULES) || (psMSPISettings == NULL))
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
// Allocate a vacant device handle
|
|
for ( ui32Index = 0; ui32Index < AM_DEVICES_MSPI_ATXP032_MAX_DEVICE_NUM; ui32Index++ )
|
|
{
|
|
if ( gAmAtxp032[ui32Index].bOccupied == false )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if ( ui32Index == AM_DEVICES_MSPI_ATXP032_MAX_DEVICE_NUM )
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
for ( uint32_t i = 0; i < (sizeof(g_ATXP032_DevConfig) / sizeof(g_ATXP032_DevConfig[0])); i++ )
|
|
{
|
|
if ( psMSPISettings->eDeviceConfig == g_ATXP032_DevConfig[i].eHalDeviceEnum )
|
|
{
|
|
psConfig = g_ATXP032_DevConfig[i].psDevConfig;
|
|
psConfig->eClockFreq = psMSPISettings->eClockFreq;
|
|
psConfig->pTCB = psMSPISettings->pNBTxnBuf;
|
|
psConfig->ui32TCBSize = psMSPISettings->ui32NBTxnBufLength;
|
|
psConfig->scramblingStartAddr = psMSPISettings->ui32ScramblingStartAddr;
|
|
psConfig->scramblingEndAddr = psMSPISettings->ui32ScramblingEndAddr;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Enable fault detection.
|
|
//
|
|
#if AM_APOLLO3_MCUCTRL
|
|
am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_FAULT_CAPTURE_ENABLE, 0);
|
|
#else // AM_APOLLO3_MCUCTRL
|
|
am_hal_mcuctrl_fault_capture_enable();
|
|
#endif // AM_APOLLO3_MCUCTRL
|
|
|
|
//
|
|
// Configure the MSPI for Serial or Quad-Paired Serial operation during initialization.
|
|
//
|
|
switch (psConfig->eDeviceConfig)
|
|
{
|
|
case AM_HAL_MSPI_FLASH_SERIAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_QUAD_CE0:
|
|
case AM_HAL_MSPI_FLASH_OCTAL_CE0:
|
|
gAmAtxp032[ui32Index].stSetting = MSPI_ATXP032_Serial_CE0_MSPIConfig;
|
|
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_initialize(ui32Module, &pMspiHandle))
|
|
{
|
|
am_util_stdio_printf("Error - Failed to initialize MSPI.\n");
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_power_control(pMspiHandle, AM_HAL_SYSCTRL_WAKE, false))
|
|
{
|
|
am_util_stdio_printf("Error - Failed to power on MSPI.\n");
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_device_configure(pMspiHandle, &MSPI_ATXP032_Serial_CE0_MSPIConfig))
|
|
{
|
|
am_util_stdio_printf("Error - Failed to configure MSPI.\n");
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_enable(pMspiHandle))
|
|
{
|
|
am_util_stdio_printf("Error - Failed to enable MSPI.\n");
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
am_bsp_mspi_pins_enable(ui32Module, MSPI_ATXP032_Serial_CE0_MSPIConfig.eDeviceConfig);
|
|
break;
|
|
case AM_HAL_MSPI_FLASH_SERIAL_CE1:
|
|
case AM_HAL_MSPI_FLASH_QUAD_CE1:
|
|
case AM_HAL_MSPI_FLASH_OCTAL_CE1:
|
|
gAmAtxp032[ui32Index].stSetting = MSPI_ATXP032_Serial_CE1_MSPIConfig;
|
|
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_initialize(ui32Module, &pMspiHandle))
|
|
{
|
|
am_util_stdio_printf("Error - Failed to initialize MSPI.\n");
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_power_control(pMspiHandle, AM_HAL_SYSCTRL_WAKE, false))
|
|
{
|
|
am_util_stdio_printf("Error - Failed to power on MSPI.\n");
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_device_configure(pMspiHandle, &MSPI_ATXP032_Serial_CE1_MSPIConfig))
|
|
{
|
|
am_util_stdio_printf("Error - Failed to configure MSPI.\n");
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_enable(pMspiHandle))
|
|
{
|
|
am_util_stdio_printf("Error - Failed to enable MSPI.\n");
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
am_bsp_mspi_pins_enable(ui32Module, MSPI_ATXP032_Serial_CE1_MSPIConfig.eDeviceConfig);
|
|
break;
|
|
case AM_HAL_MSPI_FLASH_DUAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_DUAL_CE1:
|
|
case AM_HAL_MSPI_FLASH_QUADPAIRED:
|
|
case AM_HAL_MSPI_FLASH_QUADPAIRED_SERIAL:
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
//break;
|
|
}
|
|
|
|
gAmAtxp032[ui32Index].pMspiHandle = pMspiHandle;
|
|
gAmAtxp032[ui32Index].ui32Module = ui32Module;
|
|
|
|
if (AM_HAL_STATUS_SUCCESS != am_devices_mspi_atxp032_reset((void*)&gAmAtxp032[ui32Index]))
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
gAmAtxp032[ui32Index].stSetting = *psConfig;
|
|
|
|
//
|
|
// Device specific MSPI Flash initialization.
|
|
//
|
|
ui32Status = am_device_init_flash((void*)&gAmAtxp032[ui32Index]);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
// Disable MSPI defore re-configuring it
|
|
ui32Status = am_hal_mspi_disable(pMspiHandle);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
//
|
|
// Re-Configure the MSPI for the requested operation mode.
|
|
//
|
|
ui32Status = am_hal_mspi_device_configure(pMspiHandle, psConfig);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
// Re-Enable MSPI
|
|
ui32Status = am_hal_mspi_enable(pMspiHandle);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Configure the MSPI pins.
|
|
//
|
|
am_bsp_mspi_pins_enable(ui32Module, psConfig->eDeviceConfig);
|
|
|
|
//
|
|
// Enable MSPI interrupts.
|
|
//
|
|
|
|
ui32Status = am_hal_mspi_interrupt_clear(pMspiHandle, AM_HAL_MSPI_INT_CQUPD | AM_HAL_MSPI_INT_ERR );
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
ui32Status = am_hal_mspi_interrupt_enable(pMspiHandle, AM_HAL_MSPI_INT_CQUPD | AM_HAL_MSPI_INT_ERR );
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Return the handle.
|
|
//
|
|
gAmAtxp032[ui32Index].bOccupied = true;
|
|
*ppMspiHandle = pMspiHandle;
|
|
*ppHandle = (void *)&gAmAtxp032[ui32Index];
|
|
|
|
//
|
|
// Return the status.
|
|
//
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief De-Initialization the mspi_flash driver.
|
|
//!
|
|
//! @param psIOMSettings - IOM device structure describing the target spiflash.
|
|
//! @param pfnWriteFunc - Function to use for spi writes.
|
|
//! @param pfnReadFunc - Function to use for spi reads.
|
|
//!
|
|
//! This function should be called before any other am_devices_spiflash
|
|
//! functions. It is used to set tell the other functions how to communicate
|
|
//! with the external spiflash hardware.
|
|
//!
|
|
//! The \e pfnWriteFunc and \e pfnReadFunc variables may be used to provide
|
|
//! alternate implementations of SPI write and read functions respectively. If
|
|
//! they are left set to 0, the default functions am_hal_iom_spi_write() and
|
|
//! am_hal_iom_spi_read() will be used.
|
|
//!
|
|
//! @return None.
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_deinit(void *pHandle)
|
|
{
|
|
uint32_t ui32Status;
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
|
|
//
|
|
// Device specific MSPI Flash de-initialization.
|
|
//
|
|
ui32Status = am_device_deinit_flash(pHandle);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
if (AM_HAL_STATUS_SUCCESS != am_devices_mspi_atxp032_reset(pHandle))
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Disable and clear the interrupts to start with.
|
|
//
|
|
ui32Status = am_hal_mspi_interrupt_disable(pFlash->pMspiHandle, 0xFFFFFFFF);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
ui32Status = am_hal_mspi_interrupt_clear(pFlash->pMspiHandle, 0xFFFFFFFF);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Disable the MSPI instance.
|
|
//
|
|
ui32Status = am_hal_mspi_disable(pFlash->pMspiHandle);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_power_control(pFlash->pMspiHandle, AM_HAL_SYSCTRL_DEEPSLEEP, false))
|
|
{
|
|
am_util_stdio_printf("Error - Failed to power on MSPI.\n");
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Deinitialize the MSPI instance.
|
|
//
|
|
ui32Status = am_hal_mspi_deinitialize(pFlash->pMspiHandle);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
// Free this device handle
|
|
pFlash->bOccupied = false;
|
|
|
|
//
|
|
// Clear the Flash Caching.
|
|
//
|
|
#if AM_CMSIS_REGS
|
|
CACHECTRL->CACHECFG = 0;
|
|
#else // AM_CMSIS_REGS
|
|
AM_REG(CACHECTRL, CACHECFG) = 0;
|
|
#endif // AM_CMSIS_REGS
|
|
|
|
//
|
|
// Return the status.
|
|
//
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Reads the current status of the external flash
|
|
//!
|
|
//! @param ui32DeviceNumber - Device number of the external flash
|
|
//!
|
|
//! This function reads the device ID register of the external flash, and returns
|
|
//! the result as an 32-bit unsigned integer value.
|
|
//!
|
|
//! @return 32-bit status
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_reset(void *pHandle)
|
|
{
|
|
uint32_t ui32PIOBuffer[32] = {0};
|
|
|
|
//
|
|
// Return the device to SPI mode.
|
|
//
|
|
if (AM_HAL_STATUS_SUCCESS != am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_ATXP032_RETURN_TO_SPI_MODE, false, 0, ui32PIOBuffer, 0))
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Reads the ID of the external flash and returns the value.
|
|
//!
|
|
//! @param pDeviceID - Pointer to the return buffer for the Device ID.
|
|
//!
|
|
//! This function reads the device ID register of the external flash, and returns
|
|
//! the result as an 32-bit unsigned integer value.
|
|
//!
|
|
//! @return 32-bit status
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_id(void *pHandle)
|
|
{
|
|
uint32_t ui32Status;
|
|
uint32_t ui32DeviceID;
|
|
|
|
//
|
|
// Send the command sequence to read the Device ID and return status.
|
|
//
|
|
uint8_t ui8Response[11];
|
|
ui32Status = am_devices_mspi_atxp032_command_read(pHandle, AM_DEVICES_MSPI_ATXP032_READ_ID, false, 0, (uint32_t *)&ui8Response[0], 11);
|
|
ui32DeviceID = (ui8Response[7] << 16) | (ui8Response[8] << 8) | ui8Response[9];
|
|
if ( ((ui32DeviceID & AM_DEVICES_MSPI_ATXP032_ID_MASK) == AM_DEVICES_MSPI_ATXP032_ID) &&
|
|
(AM_HAL_STATUS_SUCCESS == ui32Status) )
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Reads the current status of the external flash
|
|
//!
|
|
//! This function reads the status register of the external flash, and returns
|
|
//! the result as an 8-bit unsigned integer value. The processor will block
|
|
//! during the data transfer process, but will return as soon as the status
|
|
//! register had been read.
|
|
//!
|
|
//! Macro definitions for interpreting the contents of the status register are
|
|
//! included in the header file.
|
|
//!
|
|
//! @return 8-bit status register contents
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_status(void *pHandle, uint32_t *pStatus)
|
|
{
|
|
uint32_t ui32Status;
|
|
|
|
//
|
|
// Send the command sequence to read the device status.
|
|
//
|
|
ui32Status = am_devices_mspi_atxp032_command_read(pHandle, AM_DEVICES_MSPI_ATXP032_READ_STATUS, false, 0, pStatus, 1);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
uint32_t
|
|
am_devices_mspi_atxp032_read_adv(void *pHandle, uint8_t *pui8RxBuffer,
|
|
uint32_t ui32ReadAddress,
|
|
uint32_t ui32NumBytes,
|
|
uint32_t ui32PauseCondition,
|
|
uint32_t ui32StatusSetClr,
|
|
am_hal_mspi_callback_t pfnCallback,
|
|
void *pCallbackCtxt)
|
|
{
|
|
am_hal_mspi_dma_transfer_t Transaction;
|
|
uint32_t ui32Status;
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
|
|
// Set the DMA priority
|
|
Transaction.ui8Priority = 1;
|
|
|
|
// Set the transfer direction to RX (Read)
|
|
Transaction.eDirection = AM_HAL_MSPI_RX;
|
|
|
|
// Set the transfer count in bytes.
|
|
Transaction.ui32TransferCount = ui32NumBytes;
|
|
|
|
// Set the address to read data from.
|
|
Transaction.ui32DeviceAddress = ui32ReadAddress;
|
|
|
|
// Set the target SRAM buffer address.
|
|
Transaction.ui32SRAMAddress = (uint32_t)pui8RxBuffer;
|
|
|
|
// Clear the CQ stimulus.
|
|
Transaction.ui32PauseCondition = ui32PauseCondition;
|
|
// Clear the post-processing
|
|
Transaction.ui32StatusSetClr = ui32StatusSetClr;
|
|
|
|
// Check the transaction status.
|
|
ui32Status = am_hal_mspi_nonblocking_transfer(pFlash->pMspiHandle, &Transaction,
|
|
AM_HAL_MSPI_TRANS_DMA, pfnCallback, pCallbackCtxt);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Return the status.
|
|
//
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Reads the contents of the external flash into a buffer.
|
|
//!
|
|
//! @param pui8RxBuffer - Buffer to store the received data from the flash
|
|
//! @param ui32ReadAddress - Address of desired data in external flash
|
|
//! @param ui32NumBytes - Number of bytes to read from external flash
|
|
//!
|
|
//! This function reads the external flash at the provided address and stores
|
|
//! the received data into the provided buffer location. This function will
|
|
//! only store ui32NumBytes worth of data.
|
|
//
|
|
//! @return 32-bit status
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_read(void *pHandle, uint8_t *pui8RxBuffer,
|
|
uint32_t ui32ReadAddress,
|
|
uint32_t ui32NumBytes,
|
|
bool bWaitForCompletion)
|
|
{
|
|
am_hal_mspi_dma_transfer_t Transaction;
|
|
uint32_t ui32Status;
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
|
|
// Set the DMA priority
|
|
Transaction.ui8Priority = 1;
|
|
|
|
// Set the transfer direction to RX (Read)
|
|
Transaction.eDirection = AM_HAL_MSPI_RX;
|
|
|
|
// Set the transfer count in bytes.
|
|
Transaction.ui32TransferCount = ui32NumBytes;
|
|
|
|
// Set the address to read data from.
|
|
Transaction.ui32DeviceAddress = ui32ReadAddress;
|
|
|
|
// Set the target SRAM buffer address.
|
|
Transaction.ui32SRAMAddress = (uint32_t)pui8RxBuffer;
|
|
|
|
// Clear the CQ stimulus.
|
|
Transaction.ui32PauseCondition = 0;
|
|
// Clear the post-processing
|
|
Transaction.ui32StatusSetClr = 0;
|
|
|
|
if (bWaitForCompletion)
|
|
{
|
|
// Start the transaction.
|
|
volatile bool bDMAComplete = false;
|
|
ui32Status = am_hal_mspi_nonblocking_transfer(pFlash->pMspiHandle, &Transaction, AM_HAL_MSPI_TRANS_DMA, pfnMSPI_ATXP032_Callback, (void *)&bDMAComplete);
|
|
|
|
// Check the transaction status.
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
// Wait for DMA Complete or Timeout
|
|
for (uint32_t i = 0; i < AM_DEVICES_MSPI_ATXP032_TIMEOUT; i++)
|
|
{
|
|
if (bDMAComplete)
|
|
{
|
|
break;
|
|
}
|
|
//
|
|
// Call the BOOTROM cycle function to delay for about 1 microsecond.
|
|
//
|
|
am_hal_flash_delay( FLASH_CYCLES_US(1) );
|
|
}
|
|
|
|
// Check the status.
|
|
if (!bDMAComplete)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Check the transaction status.
|
|
ui32Status = am_hal_mspi_nonblocking_transfer(pFlash->pMspiHandle, &Transaction,
|
|
AM_HAL_MSPI_TRANS_DMA, NULL, NULL);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Return the status.
|
|
//
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Reads the contents of the external flash into a buffer.
|
|
//!
|
|
//! @param pui8RxBuffer - Buffer to store the received data from the flash
|
|
//! @param ui32ReadAddress - Address of desired data in external flash
|
|
//! @param ui32NumBytes - Number of bytes to read from external flash
|
|
//!
|
|
//! This function reads the external flash at the provided address and stores
|
|
//! the received data into the provided buffer location. This function will
|
|
//! only store ui32NumBytes worth of data.
|
|
//
|
|
//! @return 32-bit status
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_read_hiprio(void *pHandle, uint8_t *pui8RxBuffer,
|
|
uint32_t ui32ReadAddress,
|
|
uint32_t ui32NumBytes,
|
|
bool bWaitForCompletion)
|
|
{
|
|
am_hal_mspi_dma_transfer_t Transaction;
|
|
uint32_t ui32Status;
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
|
|
// Set the DMA priority
|
|
Transaction.ui8Priority = 1;
|
|
|
|
// Set the transfer direction to RX (Read)
|
|
Transaction.eDirection = AM_HAL_MSPI_RX;
|
|
|
|
// Set the transfer count in bytes.
|
|
Transaction.ui32TransferCount = ui32NumBytes;
|
|
|
|
// Set the address to read data from.
|
|
Transaction.ui32DeviceAddress = ui32ReadAddress;
|
|
|
|
// Set the target SRAM buffer address.
|
|
Transaction.ui32SRAMAddress = (uint32_t)pui8RxBuffer;
|
|
|
|
// Clear the CQ stimulus.
|
|
Transaction.ui32PauseCondition = 0;
|
|
// Clear the post-processing
|
|
Transaction.ui32StatusSetClr = 0;
|
|
|
|
if (bWaitForCompletion)
|
|
{
|
|
// Start the transaction.
|
|
volatile bool bDMAComplete = false;
|
|
ui32Status = am_hal_mspi_highprio_transfer(pFlash->pMspiHandle, &Transaction, AM_HAL_MSPI_TRANS_DMA, pfnMSPI_ATXP032_Callback, (void*)&bDMAComplete);
|
|
|
|
// Check the transaction status.
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
// Wait for DMA Complete or Timeout
|
|
for (uint32_t i = 0; i < AM_DEVICES_MSPI_ATXP032_TIMEOUT; i++)
|
|
{
|
|
if (bDMAComplete)
|
|
{
|
|
break;
|
|
}
|
|
//
|
|
// Call the BOOTROM cycle function to delay for about 1 microsecond.
|
|
//
|
|
am_hal_flash_delay( FLASH_CYCLES_US(1) );
|
|
}
|
|
|
|
// Check the status.
|
|
if (!bDMAComplete)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Check the transaction status.
|
|
ui32Status = am_hal_mspi_highprio_transfer(pFlash->pMspiHandle, &Transaction,
|
|
AM_HAL_MSPI_TRANS_DMA, NULL, NULL);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Return the status.
|
|
//
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Programs the given range of flash addresses.
|
|
//!
|
|
//! @param ui32DeviceNumber - Device number of the external flash
|
|
//! @param pui8TxBuffer - Buffer to write the external flash data from
|
|
//! @param ui32WriteAddress - Address to write to in the external flash
|
|
//! @param ui32NumBytes - Number of bytes to write to the external flash
|
|
//!
|
|
//! This function uses the data in the provided pui8TxBuffer and copies it to
|
|
//! the external flash at the address given by ui32WriteAddress. It will copy
|
|
//! exactly ui32NumBytes of data from the original pui8TxBuffer pointer. The
|
|
//! user is responsible for ensuring that they do not overflow the target flash
|
|
//! memory or underflow the pui8TxBuffer array
|
|
//
|
|
//! @return 32-bit status
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_write(void *pHandle, uint8_t *pui8TxBuffer,
|
|
uint32_t ui32WriteAddress,
|
|
uint32_t ui32NumBytes,
|
|
bool bWaitForCompletion)
|
|
{
|
|
am_hal_mspi_dma_transfer_t Transaction;
|
|
bool bWriteComplete = false;
|
|
uint32_t ui32BytesLeft = ui32NumBytes;
|
|
uint32_t ui32PageAddress = ui32WriteAddress;
|
|
uint32_t ui32BufferAddress = (uint32_t)pui8TxBuffer;
|
|
uint32_t ui32Status;
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
uint32_t ui32PIOBuffer[32] = {0};
|
|
|
|
while (ui32BytesLeft > 0)
|
|
{
|
|
//
|
|
// Send the command sequence to enable writing.
|
|
//
|
|
ui32Status = am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_MSPI_ATXP032_WRITE_ENABLE, false, 0, ui32PIOBuffer, 0);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
// Set the DMA priority
|
|
Transaction.ui8Priority = 1;
|
|
|
|
// Set the transfer direction to TX (Write)
|
|
Transaction.eDirection = AM_HAL_MSPI_TX;
|
|
|
|
if (ui32BytesLeft > AM_DEVICES_MSPI_ATXP032_PAGE_SIZE)
|
|
{
|
|
// Set the transfer count in bytes.
|
|
Transaction.ui32TransferCount = AM_DEVICES_MSPI_ATXP032_PAGE_SIZE;
|
|
ui32BytesLeft -= AM_DEVICES_MSPI_ATXP032_PAGE_SIZE;
|
|
}
|
|
else
|
|
{
|
|
// Set the transfer count in bytes.
|
|
Transaction.ui32TransferCount = ui32BytesLeft;
|
|
ui32BytesLeft = 0;
|
|
}
|
|
|
|
// Set the address configuration for the read
|
|
// Transaction.eAddrCfg = AM_HAL_MSPI_ADDR_3_BYTE;
|
|
|
|
// Transaction.eAddrExtSize = AM_HAL_MSPI_ADDR_EXT_0_BYTE;
|
|
// Transaction.ui8AddrExtValue = 0;
|
|
|
|
// Set the address to read data to.
|
|
Transaction.ui32DeviceAddress = ui32PageAddress;
|
|
ui32PageAddress += AM_DEVICES_MSPI_ATXP032_PAGE_SIZE;
|
|
|
|
// Set the source SRAM buffer address.
|
|
Transaction.ui32SRAMAddress = ui32BufferAddress;
|
|
ui32BufferAddress += AM_DEVICES_MSPI_ATXP032_PAGE_SIZE;
|
|
|
|
// Clear the CQ stimulus.
|
|
Transaction.ui32PauseCondition = 0;
|
|
// Clear the post-processing
|
|
Transaction.ui32StatusSetClr = 0;
|
|
|
|
// Start the transaction.
|
|
volatile bool bDMAComplete = false;
|
|
ui32Status = am_hal_mspi_nonblocking_transfer(pFlash->pMspiHandle, &Transaction, AM_HAL_MSPI_TRANS_DMA, pfnMSPI_ATXP032_Callback, (void*)&bDMAComplete);
|
|
|
|
// Check the transaction status.
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
// Wait for DMA Complete or Timeout
|
|
for (uint32_t i = 0; i < AM_DEVICES_MSPI_ATXP032_TIMEOUT; i++)
|
|
{
|
|
if (bDMAComplete)
|
|
{
|
|
break;
|
|
}
|
|
//
|
|
// Call the BOOTROM cycle function to delay for about 1 microsecond.
|
|
//
|
|
am_hal_flash_delay( FLASH_CYCLES_US(1) );
|
|
}
|
|
|
|
// Check the status.
|
|
if (!bDMAComplete)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Wait for the Write In Progress to indicate the erase is complete.
|
|
//
|
|
for (uint32_t i = 0; i < AM_DEVICES_MSPI_ATXP032_TIMEOUT; i++)
|
|
{
|
|
// ATXP032 has different number of bytes for each speed of status read.
|
|
switch ( pFlash->stSetting.eDeviceConfig )
|
|
{
|
|
case AM_HAL_MSPI_FLASH_SERIAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_SERIAL_CE1:
|
|
am_devices_mspi_atxp032_command_read(pHandle, AM_DEVICES_MSPI_ATXP032_READ_STATUS, false, 0, ui32PIOBuffer, 2);
|
|
bWriteComplete = (0 == (ui32PIOBuffer[0] & AM_DEVICES_ATXP032_WIP));
|
|
break;
|
|
case AM_HAL_MSPI_FLASH_QUAD_CE0:
|
|
case AM_HAL_MSPI_FLASH_QUAD_CE1:
|
|
am_devices_mspi_atxp032_command_read(pHandle, AM_DEVICES_MSPI_ATXP032_READ_STATUS, false, 0, ui32PIOBuffer, 4);
|
|
bWriteComplete = (0 == ((ui32PIOBuffer[0] >> 16) & AM_DEVICES_ATXP032_WIP));
|
|
break;
|
|
case AM_HAL_MSPI_FLASH_OCTAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_OCTAL_CE1:
|
|
am_devices_mspi_atxp032_command_read(pHandle, AM_DEVICES_MSPI_ATXP032_READ_STATUS, false, 0, ui32PIOBuffer, 6);
|
|
bWriteComplete = (0 == (ui32PIOBuffer[1] & AM_DEVICES_ATXP032_WIP));
|
|
break;
|
|
case AM_HAL_MSPI_FLASH_DUAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_DUAL_CE1:
|
|
case AM_HAL_MSPI_FLASH_QUADPAIRED:
|
|
case AM_HAL_MSPI_FLASH_QUADPAIRED_SERIAL:
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
am_util_delay_us(100);
|
|
if (bWriteComplete)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Send the command sequence to disable writing.
|
|
//
|
|
ui32Status = am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_MSPI_ATXP032_WRITE_DISABLE, false, 0, ui32PIOBuffer, 0);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Return the status.
|
|
//
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Erases the entire contents of the external flash
|
|
//!
|
|
//! @param ui32DeviceNumber - Device number of the external flash
|
|
//!
|
|
//! This function uses the "Bulk Erase" instruction to erase the entire
|
|
//! contents of the external flash.
|
|
//
|
|
//! @return 32-bit status
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_mass_erase(void *pHandle)
|
|
{
|
|
bool bEraseComplete = false;
|
|
uint32_t ui32Status;
|
|
//am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
uint32_t ui32PIOBuffer[32] = {0};
|
|
|
|
//
|
|
// Send the command sequence to enable writing.
|
|
//
|
|
ui32Status = am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_MSPI_ATXP032_WRITE_ENABLE, false, 0, ui32PIOBuffer, 0);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Send the command sequence to do the mass erase.
|
|
//
|
|
ui32Status = am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_MSPI_ATXP032_BULK_ERASE, false, 0, ui32PIOBuffer, 0);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
//
|
|
// Wait for the Write In Progress to indicate the erase is complete.
|
|
//
|
|
for (uint32_t i = 0; i < AM_DEVICES_MSPI_ATXP032_ERASE_TIMEOUT; i++)
|
|
{
|
|
ui32PIOBuffer[0] = 0;
|
|
am_devices_mspi_atxp032_command_read(pHandle, AM_DEVICES_MSPI_ATXP032_READ_STATUS, false, 0, ui32PIOBuffer, 1);
|
|
bEraseComplete = (0 == (ui32PIOBuffer[0] & AM_DEVICES_MSPI_ATXP032_WIP));
|
|
if (bEraseComplete)
|
|
{
|
|
break;
|
|
}
|
|
am_util_delay_ms(10);
|
|
}
|
|
|
|
//
|
|
// Check the status.
|
|
//
|
|
if (!bEraseComplete)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Send the command sequence to disable writing.
|
|
//
|
|
ui32Status = am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_MSPI_ATXP032_WRITE_DISABLE, false, 0, ui32PIOBuffer, 0);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Return the status.
|
|
//
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Erases the contents of a single sector of flash
|
|
//!
|
|
//! @param ui32DeviceNumber - Device number of the external flash
|
|
//! @param ui32SectorAddress - Address to erase in the external flash
|
|
//!
|
|
//! This function erases a single sector of the external flash as specified by
|
|
//! ui32EraseAddress. The entire sector where ui32EraseAddress will
|
|
//! be erased.
|
|
//
|
|
//! @return 32-bit status
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_sector_erase(void *pHandle, uint32_t ui32SectorAddress)
|
|
{
|
|
bool bEraseComplete = false;
|
|
uint32_t ui32Status;
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
uint32_t ui32PIOBuffer[32] = {0};
|
|
|
|
//
|
|
// Send the command sequence to enable writing.
|
|
//
|
|
ui32Status = am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_MSPI_ATXP032_WRITE_ENABLE, false, 0, ui32PIOBuffer, 0);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Send the command to remove protection from the sector.
|
|
//
|
|
ui32Status = am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_ATXP032_UNPROTECT_SECTOR, true, ui32SectorAddress, ui32PIOBuffer, 0);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Send the command sequence to enable writing.
|
|
//
|
|
ui32Status = am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_MSPI_ATXP032_WRITE_ENABLE, false, 0, ui32PIOBuffer, 0);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Send the command sequence to do the sector erase.
|
|
//
|
|
ui32Status = am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_MSPI_ATXP032_SECTOR_ERASE, true, ui32SectorAddress, ui32PIOBuffer, 0);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Wait for the Write In Progress to indicate the erase is complete.
|
|
//
|
|
for (uint32_t i = 0; i < AM_DEVICES_MSPI_ATXP032_ERASE_TIMEOUT; i++)
|
|
{
|
|
// ATXP032 has different number of bytes for each speed of status read.
|
|
switch ( pFlash->stSetting.eDeviceConfig )
|
|
{
|
|
case AM_HAL_MSPI_FLASH_SERIAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_SERIAL_CE1:
|
|
am_devices_mspi_atxp032_command_read(pHandle, AM_DEVICES_MSPI_ATXP032_READ_STATUS, false, 0, ui32PIOBuffer, 2);
|
|
bEraseComplete = (0 == (ui32PIOBuffer[0] & AM_DEVICES_ATXP032_WIP));
|
|
break;
|
|
case AM_HAL_MSPI_FLASH_QUAD_CE0:
|
|
case AM_HAL_MSPI_FLASH_QUAD_CE1:
|
|
am_devices_mspi_atxp032_command_read(pHandle, AM_DEVICES_MSPI_ATXP032_READ_STATUS, false, 0, ui32PIOBuffer, 4);
|
|
bEraseComplete = (0 == ((ui32PIOBuffer[0] >> 16) & AM_DEVICES_ATXP032_WIP));
|
|
break;
|
|
case AM_HAL_MSPI_FLASH_OCTAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_OCTAL_CE1:
|
|
am_devices_mspi_atxp032_command_read(pHandle, AM_DEVICES_MSPI_ATXP032_READ_STATUS, false, 0, ui32PIOBuffer, 6);
|
|
bEraseComplete = (0 == (ui32PIOBuffer[1] & AM_DEVICES_ATXP032_WIP));
|
|
break;
|
|
case AM_HAL_MSPI_FLASH_DUAL_CE0:
|
|
case AM_HAL_MSPI_FLASH_DUAL_CE1:
|
|
case AM_HAL_MSPI_FLASH_QUADPAIRED:
|
|
case AM_HAL_MSPI_FLASH_QUADPAIRED_SERIAL:
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
if (bEraseComplete)
|
|
{
|
|
break;
|
|
}
|
|
am_util_delay_ms(10);
|
|
}
|
|
|
|
//
|
|
// Check the status.
|
|
//
|
|
if (!bEraseComplete)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Send the command sequence to disable writing.
|
|
//
|
|
ui32Status = am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_MSPI_ATXP032_WRITE_DISABLE, false, 0, ui32PIOBuffer, 0);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
//
|
|
// Return the status.
|
|
//
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Sets up the MSPI and external FLASH into XIP mode.
|
|
//!
|
|
//! This function sets the external psram device and the MSPI into XIP mode.
|
|
//
|
|
//! @return 32-bit status
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_enable_xip(void *pHandle)
|
|
{
|
|
uint32_t ui32Status;
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
|
|
//
|
|
// Enable XIP on the MSPI.
|
|
//
|
|
ui32Status = am_hal_mspi_control(pFlash->pMspiHandle, AM_HAL_MSPI_REQ_XIP_EN, NULL);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
#if !MSPI_USE_CQ
|
|
// Disable the DMA interrupts.
|
|
ui32Status = am_hal_mspi_interrupt_disable(pFlash->pMspiHandle,
|
|
AM_HAL_MSPI_INT_DMAERR |
|
|
AM_HAL_MSPI_INT_DMACMP );
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
#endif
|
|
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Removes the MSPI and external FLASH from XIP mode.
|
|
//!
|
|
//! This function removes the external device and the MSPI from XIP mode.
|
|
//
|
|
//! @return 32-bit status
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_disable_xip(void *pHandle)
|
|
{
|
|
uint32_t ui32Status;
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
uint32_t ui32PIOBuffer[32] = {0};
|
|
|
|
//
|
|
// Send the command to enable writing.
|
|
//
|
|
ui32Status = am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_MSPI_ATXP032_WRITE_ENABLE, false, 0, ui32PIOBuffer, 0);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Disable XIP on the MSPI.
|
|
//
|
|
ui32Status = am_hal_mspi_control(pFlash->pMspiHandle, AM_HAL_MSPI_REQ_XIP_DIS, NULL);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Sets up the MSPI and external FLASH into scrambling mode.
|
|
//!
|
|
//! This function sets the external psram device and the MSPI into scrambling mode.
|
|
//
|
|
//! @return 32-bit status
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_enable_scrambling(void *pHandle)
|
|
{
|
|
uint32_t ui32Status;
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
|
|
//
|
|
// Enable scrambling on the MSPI.
|
|
//
|
|
ui32Status = am_hal_mspi_control(pFlash->pMspiHandle, AM_HAL_MSPI_REQ_SCRAMB_EN, NULL);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Removes the MSPI and external FLASH from scrambling mode.
|
|
//!
|
|
//! This function removes the external device and the MSPI from scrambling mode.
|
|
//
|
|
//! @return 32-bit status
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_devices_mspi_atxp032_disable_scrambling(void *pHandle)
|
|
{
|
|
uint32_t ui32Status;
|
|
am_devices_mspi_atxp032_t *pFlash = (am_devices_mspi_atxp032_t *)pHandle;
|
|
uint32_t ui32PIOBuffer[32] = {0};
|
|
|
|
//
|
|
// Send the command to enable writing.
|
|
//
|
|
ui32Status = am_devices_mspi_atxp032_command_write(pHandle, AM_DEVICES_MSPI_ATXP032_WRITE_ENABLE, false, 0, ui32PIOBuffer, 0);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
//
|
|
// Disable Scrambling on the MSPI.
|
|
//
|
|
ui32Status = am_hal_mspi_control(pFlash->pMspiHandle, AM_HAL_MSPI_REQ_SCRAMB_DIS, NULL);
|
|
if (AM_HAL_STATUS_SUCCESS != ui32Status)
|
|
{
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_ERROR;
|
|
}
|
|
|
|
return AM_DEVICES_MSPI_ATXP032_STATUS_SUCCESS;
|
|
}
|
|
|