Apollo3 SDK平台添加支持复旦微FM25Q128 SPI Flash的方法
说明:状态寄存器SR2-3中的有些位标注为R,其为Reserved Bit,即保留位,不能被软件改写,建议采用先读出SR2-3的值,再使用与或操作置位或者清除可以改写的位,同时保留那些原有标注R的位的值。
am_devices_mspi_flash.c文件中增加对FM25Q128支持的初始化代码:
SPI接口初始化宏定义:
// Configure the MSPI for Serial operation during initialization
am_hal_mspi_dev_config_t SerialCE0MSPIConfig = // MSPI SERIAL CE0(SPI mode)
{
.eSpiMode = AM_HAL_MSPI_SPI_MODE_0,
.eClockFreq = AM_HAL_MSPI_CLK_3MHZ, // lower speed rate for more stable initialization operation
#if defined(MICRON_N25Q256A)
.ui8TurnAround = 3,
#elif defined (CYPRESS_S25FS064S)
.ui8TurnAround = 3,
#elif defined (MACRONIX_MX25U12835F)
.ui8TurnAround = 8,
#elif defined (FUDAN_FM25Q128)
.ui8TurnAround = 8, // The dummy clocks is 8 under SPI mode by default. will update automatically
#endif
.eAddrCfg = AM_HAL_MSPI_ADDR_3_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_FLASH_FAST_READ,
.ui8WriteInstr = AM_DEVICES_MSPI_FLASH_PAGE_PROGRAM,
.ui32TCBSize = 0,
.pTCB = NULL,
.scramblingStartAddr = 0,
.scramblingEndAddr = 0,
};
上电后,选择将MSPI配置为CE0,单线SPI模式,各参数说明如下:
AM_HAL_MSPI_SPI_MODE_0: 配置为SPI Mode
AM_HAL_MSPI_CLK_3MHZ: 配置较低的SPI速率提高稳定性和兼容性
.ui8TurnAround = 8:芯片出厂LC默认值为00,对应的SPI模式下dummy cycles为8
AM_HAL_MSPI_ADDR_3_BYTE: 24位即3字节地址码
AM_HAL_MSPI_INSTR_1_BYTE: 1字节指令码
AM_HAL_MSPI_FLASH_SERIAL_CE0:单线SPI模式,片选通道CE0
FM25Q128初始化代码如下:
//*******************************************************************
//
// FUDAN FM25Q128 Support
// Added by Roger
//
//*******************************************************************
#if defined (FUDAN_FM25Q128)
//
// Device specific initialization function.
//
uint32_t am_device_init_flash(am_hal_mspi_dev_config_t *psMSPISettings)
{
uint32_t ui32Status = AM_HAL_STATUS_SUCCESS;
// workaround for the HOLD# pin bug
// When read the SPI Flash device at the first time powered-on, the device will present as SPI mode
// If the WP# or Hold# pin is tied directly to a low level (such as, connect to the ground) during standard SPI
// or Dual SPI operation, the QE bit should never be set to a 1.
// Pull the WP# and HOLD# pin of SPI Flash as a high level to prevent hold state
ConfigGP23AsGpioOutputForPullHighHoldPin(); // added by Roger
ConfigGP4AsGpioOutputForPullHighWPPin(); // added by Roger
#if 1
//
// Reset the Fudan FM25Q128. using the existing api
//
if (AM_HAL_STATUS_SUCCESS != am_devices_mspi_flash_reset())
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
// software reset code
#else
ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_ENABLE_RESET, false, 0, g_PIOBuffer, 0); // Enable reset
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_RESET, false, 0, g_PIOBuffer, 0); // Reset
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
#endif
am_util_delay_us(1000); // for stable concern, delay 1000us after software reset
g_ui32SR1 = 0;
g_ui32SR2 = 0;
g_ui32SR3 = 0;
am_util_stdio_printf("Dump out the STATUS REGISTER 1 - 3 before configurating:");
ui32Status = am_device_command_read(AM_DEVICES_MSPI_FLASH_READ_STATUS_REGISTER1, false, 0, (uint32_t *)&g_ui32SR1, 1);
am_util_stdio_printf("STATUS REGISTER 1 is 0x%02X", (uint8_t)g_ui32SR1);
ui32Status = am_device_command_read(AM_DEVICES_MSPI_FLASH_READ_STATUS_REGISTER2, false, 0, (uint32_t *)&g_ui32SR2, 1);
am_util_stdio_printf("STATUS REGISTER 2 is 0x%02X", (uint8_t)g_ui32SR2);
ui32Status = am_device_command_read(AM_DEVICES_MSPI_FLASH_READ_STATUS_REGISTER3, false, 0, (uint32_t *)&g_ui32SR3, 1);
am_util_stdio_printf("STATUS REGISTER 3 is 0x%02X", (uint8_t)g_ui32SR3);
//
// Enable writing to the Status/Configuration register.
//
ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_WRITE_ENABLE, false, 0, g_PIOBuffer, 0); // Non-Volatile
//ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_WRITE_ENABLE_VOLATILE, false, 0, g_PIOBuffer, 0); // Volatile
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
//
// Configure the Fudan FM25Q128 Status Register-1.
//
g_PIOBuffer[0] = AM_DEVICES_MSPI_CLEAR_STATUS_REGISTER1 ; // Write status register + Data (0x00) --> Clear
ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_WRITE_STATUS_REGISTER1, false, 0, g_PIOBuffer, 1); // SR1
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
//
// Enable writing to the Status/Configuration register.
//
//ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_WRITE_ENABLE, false, 0, g_PIOBuffer, 0); // Non-Volatile
ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_WRITE_ENABLE_VOLATILE, false, 0, g_PIOBuffer, 0); // Volatile
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
//
// Configure the Fudan FM25Q128 Status Register-3.
//
g_PIOBuffer[0] = g_ui32SR3 & ~AM_DEVICES_MSPI_CLEAR_STATUS_REGISTER3;
ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_WRITE_STATUS_REGISTER3, false, 0, g_PIOBuffer, 1);
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
// SPI mode does not need to config the QE bit, move the QE setting to the quad SPI initial code
#if 0
//
// Enable writing to the Status/Configuration register.
//ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_WRITE_ENABLE, false, 0, g_PIOBuffer, 0); // Non-Volatile
//ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_WRITE_ENABLE_VOLATILE, false, 0, g_PIOBuffer, 0); // Volatile
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
//
// Configure the Fudan FM25Q128 Status Register-2.
//
g_PIOBuffer[0]=(uint8_t)g_ui32SR2|
AM_DEVICES_MSPI_ENABLE_QUAD_STATUS_REGISTER2;
// Setting LC and Enable QE(QUAD ENABLE)
ui32Status=am_device_command_write(AM_DEVICES_MSPI_FLASH_WRITE_STATUS_REGISTER2, false, 0, g_PIOBuffer, 1);
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
#endif
am_util_stdio_printf("Dump out the STATUS REGISTER 1 & 3 after having been overwritten:");
g_ui32SR1 = 0;
g_ui32SR2 = 0;
g_ui32SR3 = 0;
ui32Status= am_device_command_read(AM_DEVICES_MSPI_FLASH_READ_STATUS_REGISTER1, false, 0, (uint32_t *)&g_ui32SR1, 1);
am_util_stdio_printf("STATUS REGISTER 1 is 0x%02X", (uint8_t)g_ui32SR1);
ui32Status= am_device_command_read(AM_DEVICES_MSPI_FLASH_READ_STATUS_REGISTER2, false, 0, (uint32_t *)&g_ui32SR2, 1);
am_util_stdio_printf("STATUS REGISTER 2 is 0x%02X", (uint8_t)g_ui32SR2);
ui32Status= am_device_command_read(AM_DEVICES_MSPI_FLASH_READ_STATUS_REGISTER3, false, 0, (uint32_t *)&g_ui32SR3, 1);
am_util_stdio_printf("STATUS REGISTER 3 is 0x%02X", (uint8_t)g_ui32SR3);
switch (psMSPISettings->eDeviceConfig)
{
case AM_HAL_MSPI_FLASH_SERIAL_CE0:
case AM_HAL_MSPI_FLASH_SERIAL_CE1:
// Nothing to do. Device defaults to SPI mode for initializing SPI flash device. Disable QPI mode
ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_DISABLE_QPI_MODE, false, 0, g_PIOBuffer, 0); // Disable QPI, return to SPI
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
break;
case AM_HAL_MSPI_FLASH_DUAL_CE0:
case AM_HAL_MSPI_FLASH_DUAL_CE1:
// Device does not support Dual mode.
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
//break;
case AM_HAL_MSPI_FLASH_QUAD_CE0:
case AM_HAL_MSPI_FLASH_QUAD_CE1:
case AM_HAL_MSPI_FLASH_QUADPAIRED:
case AM_HAL_MSPI_FLASH_QUADPAIRED_SERIAL:
am_util_stdio_printf("Check the QE bit in STATUS REGISTER 2.");
// check the QE bit in SR2
if ( ((uint8_t)g_ui32SR2 & (1<<1)) == 0)
{
am_util_stdio_printf("Config the STATUS REGISTER 2 for Quad SPI mode.");
//
// Enable writing to the Status/Configuration register.
//
ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_WRITE_ENABLE, false, 0, g_PIOBuffer, 0); // Non-Volatile
//ui32Status=am_device_command_write(AM_DEVICES_MSPI_FLASH_WRITE_ENABLE_VOLATILE, false, 0, g_PIOBuffer, 0); // Volatile
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
//
// Configure the Fudan FM25Q128 Status Register-2.
//
g_PIOBuffer[0]=(uint8_t)g_ui32SR2| AM_DEVICES_MSPI_ENABLE_QUAD_STATUS_REGISTER2;
// default LC Setting and Enable QE(QUAD ENABLE)
ui32Status=am_device_command_write(AM_DEVICES_MSPI_FLASH_WRITE_STATUS_REGISTER2, false, 0, g_PIOBuffer, 1);
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
}
else
{
am_util_stdio_printf("QE bit in the STATUS REGISTER 2 has already been enabled.");
}
am_util_stdio_printf("Get the value of STATUS REGISTER 2:");
ui32Status= am_device_command_read(AM_DEVICES_MSPI_FLASH_READ_STATUS_REGISTER2, false, 0, (uint32_t *)&g_ui32SR2, 1);
am_util_stdio_printf("STATUS REGISTER 2 is 0x%02X", (uint8_t)g_ui32SR2);
ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_ENABLE_QPI_MODE, false, 0, g_PIOBuffer, 0); // Enable QPI
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
break;
case AM_HAL_MSPI_FLASH_OCTAL_CE0:
case AM_HAL_MSPI_FLASH_OCTAL_CE1:
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
//break;
}
return AM_DEVICES_MSPI_FLASH_STATUS_SUCCESS;
}
//
// Device specific de-initialization function.
//
uint32_t am_device_deinit_flash(am_hal_mspi_dev_config_t *psMSPISettings)
{
uint32_t ui32Status;
//
// Reset the Fudan FM25Q128
//
ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_ENABLE_RESET, false, 0, g_PIOBuffer, 0); // Enable reset
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
ui32Status=am_device_command_write(AM_DEVICES_MSPI_FLASH_RESET,false, 0, g_PIOBuffer, 0); // Reset
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
// added by Roger
am_util_delay_us(1000); // delay 1000us after software reset
//
// Configure the Fudan FM25Q128 Device mode.
//
ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_WRITE_ENABLE, false, 0, g_PIOBuffer, 0);
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
switch (psMSPISettings->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_DUAL_CE0:
case AM_HAL_MSPI_FLASH_DUAL_CE1:
// Device does not support Dual mode.
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
//break;
case AM_HAL_MSPI_FLASH_QUAD_CE0:
case AM_HAL_MSPI_FLASH_QUAD_CE1:
case AM_HAL_MSPI_FLASH_QUADPAIRED:
case AM_HAL_MSPI_FLASH_QUADPAIRED_SERIAL:
ui32Status = am_device_command_write(AM_DEVICES_MSPI_FLASH_DISABLE_QPI_MODE, false, 0, g_PIOBuffer, 0);
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
break;
case AM_HAL_MSPI_FLASH_OCTAL_CE0:
case AM_HAL_MSPI_FLASH_OCTAL_CE1:
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
//break;
}
return AM_DEVICES_MSPI_FLASH_STATUS_SUCCESS;
}
#endif
uint32_t
am_devices_mspi_flash_init(am_hal_mspi_dev_config_t *psMSPISettings, void **pHandle)
{
uint32_t ui32Status;
//
// Enable fault detection.
//
#if AM_APOLLO3_MCUCTRL
am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_FAULT_CAPTURE_ENABLE, 0);
#else
am_hal_mcuctrl_fault_capture_enable();
#endif
//
// Configure the MSPI for Serial or Quad-Paired Serial operation during initialization.
//
switch (psMSPISettings->eDeviceConfig)
{
case AM_HAL_MSPI_FLASH_SERIAL_CE0:
// Select CE0 SPI mode
case AM_HAL_MSPI_FLASH_DUAL_CE0:
case AM_HAL_MSPI_FLASH_QUAD_CE0:
// Select CE0 Quad mode
case AM_HAL_MSPI_FLASH_OCTAL_CE0:
g_psMSPISettings = SerialCE0MSPIConfig; // Configure the MSPI for Serial operation during initialization
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_initialize(AM_DEVICES_MSPI_FLASH_MSPI_INSTANCE, &g_pMSPIHandle))
{
am_util_stdio_printf("Error - Failed to initialize MSPI.");
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_power_control(g_pMSPIHandle, AM_HAL_SYSCTRL_WAKE, false))
{
am_util_stdio_printf("Error - Failed to power on MSPI.");
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_device_configure(g_pMSPIHandle, &SerialCE0MSPIConfig))
{
am_util_stdio_printf("Error - Failed to configure MSPI.");
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_enable(g_pMSPIHandle))
{
am_util_stdio_printf("Error - Failed to enable MSPI.");
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
am_bsp_mspi_pins_enable(SerialCE0MSPIConfig.eDeviceConfig); // Set up the MSPI pins for CE0
break;
case AM_HAL_MSPI_FLASH_SERIAL_CE1:
case AM_HAL_MSPI_FLASH_DUAL_CE1:
case AM_HAL_MSPI_FLASH_QUAD_CE1:
case AM_HAL_MSPI_FLASH_OCTAL_CE1:
g_psMSPISettings = SerialCE1MSPIConfig;
if(AM_HAL_STATUS_SUCCESS!=am_hal_mspi_initialize(AM_DEVICES_MSPI_FLASH_MSPI_INSTANCE, &g_pMSPIHandle))
{
am_util_stdio_printf("Error - Failed to initialize MSPI.");
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
if(AM_HAL_STATUS_SUCCESS!=am_hal_mspi_power_control(g_pMSPIHandle, AM_HAL_SYSCTRL_WAKE, false))
{
am_util_stdio_printf("Error - Failed to power on MSPI.");
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
if(AM_HAL_STATUS_SUCCESS!=am_hal_mspi_device_configure(g_pMSPIHandle,&SerialCE1MSPIConfig))
{
am_util_stdio_printf("Error - Failed to configure MSPI.");
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_enable(g_pMSPIHandle))
{
am_util_stdio_printf("Error - Failed to enable MSPI.");
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
am_bsp_mspi_pins_enable(SerialCE1MSPIConfig.eDeviceConfig); // Set up the MSPI pins for CE1
break;
case AM_HAL_MSPI_FLASH_QUADPAIRED:
g_psMSPISettings = QuadPairedSerialMSPIConfig;
if(AM_HAL_STATUS_SUCCESS!=am_hal_mspi_initialize(AM_DEVICES_MSPI_FLASH_MSPI_INSTANCE, &g_pMSPIHandle))
{
am_util_stdio_printf("Error - Failed to initialize MSPI.");
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
if(AM_HAL_STATUS_SUCCESS!=am_hal_mspi_power_control(g_pMSPIHandle, AM_HAL_SYSCTRL_WAKE, false))
{
am_util_stdio_printf("Error - Failed to power on MSPI.");
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
if(AM_HAL_STATUS_SUCCESS!=am_hal_mspi_device_configure(g_pMSPIHandle, &QuadPairedSerialMSPIConfig))
{
am_util_stdio_printf("Error - Failed to configure MSPI.");
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
if (AM_HAL_STATUS_SUCCESS != am_hal_mspi_enable(g_pMSPIHandle))
{
am_util_stdio_printf("Error - Failed to enable MSPI.");
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
am_bsp_mspi_pins_enable(QuadPairedSerialMSPIConfig.eDeviceConfig); // Set up the MSPI pins
break;
case AM_HAL_MSPI_FLASH_QUADPAIRED_SERIAL:
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
//break;
}
if (AM_HAL_STATUS_SUCCESS != am_devices_mspi_flash_reset()) // software reset the external flash device
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
// added by Roger
am_util_delay_us(1000); // for stable concern, delay 1000us after software reset
//
// Device specific MSPI Flash initialization.
// Added by Roger
//
ui32Status = am_device_init_flash(psMSPISettings);
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
am_util_stdio_printf("Error - Failed to initial device specific MSPI Flash.");
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
//
// Initialize the MSPI settings for the SPI FLASH.
//
g_psMSPISettings = *psMSPISettings;
// Disable MSPI before re-configuring it
ui32Status = am_hal_mspi_disable(g_pMSPIHandle);
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
// added by Roger
#if defined (FUDAN_FM25Q128)
am_util_stdio_printf("Status Register 2 is 0x%02X.",(uint8_t)g_ui32SR2);
if((g_psMSPISettings.eDeviceConfig==AM_HAL_MSPI_FLASH_QUAD_CE0) || (g_psMSPISettings.eDeviceConfig == AM_HAL_MSPI_FLASH_QUAD_CE1))
{
am_util_stdio_printf("MSPI operation with Quad SPI mode.");
// added by Roger, for updating the dummy clocks according to the LC setting under QPI mode
switch (((uint8_t)g_ui32SR2 & 0xC0) >> 6)
{
case 0: // LC = 00
g_psMSPISettings.ui8TurnAround = 6;
break;
case 1: // LC = 01
g_psMSPISettings.ui8TurnAround = 8;
break;
case 2: // LC = 10
g_psMSPISettings.ui8TurnAround = 10;
break;
case 3: // LC = 11
g_psMSPISettings.ui8TurnAround = 4;
break;
default:
g_psMSPISettings.ui8TurnAround = 6;
break;
}
}
if ((g_psMSPISettings.eDeviceConfig == AM_HAL_MSPI_FLASH_SERIAL_CE0) || (g_psMSPISettings.eDeviceConfig == AM_HAL_MSPI_FLASH_SERIAL_CE1))
{
am_util_stdio_printf("MSPI operation with SPI mode.");
// added by Roger, for updating the dummy clocks according to the LC setting under SPI mode
switch (((uint8_t)g_ui32SR2 & 0xC0) >>6)
{
case 0: // LC = 00
case 1: // LC = 01
case 2: // LC = 10
g_psMSPISettings.ui8TurnAround = 8;
break;
case 3: // LC = 11
g_psMSPISettings.ui8TurnAround = 0;
break;
default:
g_psMSPISettings.ui8TurnAround = 8;
break;
}
}
am_util_stdio_printf("g_psMSPISettings.ui8TurnAround=0x%02X.", g_psMSPISettings.ui8TurnAround);
#endif
//
// Re-Configure the MSPI for the requested operation mode.
//
//ui32Status = am_hal_mspi_device_configure(g_pMSPIHandle, psMSPISettings);
ui32Status = am_hal_mspi_device_configure(g_pMSPIHandle, &g_psMSPISettings); // modified by Roger
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
// Re-Enable MSPI
ui32Status = am_hal_mspi_enable(g_pMSPIHandle);
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
//
// Configure the MSPI pins.
//
am_bsp_mspi_pins_enable(g_psMSPISettings.eDeviceConfig); // Set up the MSPI pins
//
// Enable MSPI interrupts.
//
#if MSPI_USE_CQ
ui32Status = am_hal_mspi_interrupt_clear(g_pMSPIHandle, AM_HAL_MSPI_INT_CQUPD | AM_HAL_MSPI_INT_ERR );
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
ui32Status = am_hal_mspi_interrupt_enable(g_pMSPIHandle, AM_HAL_MSPI_INT_CQUPD | AM_HAL_MSPI_INT_ERR );
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
#else
ui32Status=am_hal_mspi_interrupt_clear(g_pMSPIHandle,AM_HAL_MSPI_INT_ERR | AM_HAL_MSPI_INT_DMACMP | AM_HAL_MSPI_INT_CMDCMP );
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
ui32Status = am_hal_mspi_interrupt_enable(g_pMSPIHandle, AM_HAL_MSPI_INT_ERR | AM_HAL_MSPI_INT_DMACMP | AM_HAL_MSPI_INT_CMDCMP );
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return AM_DEVICES_MSPI_FLASH_STATUS_ERROR;
}
#endif
#if AM_CMSIS_REGS
NVIC_EnableIRQ(MSPI_IRQn);
#else // AM_CMSIS_REGS
am_hal_interrupt_enable(AM_HAL_INTERRUPT_MSPI);
#endif // AM_CMSIS_REGS
am_hal_interrupt_master_enable();
//
// Return the handle.
//
*pHandle = g_pMSPIHandle;
//
// Return the status.
//
return AM_DEVICES_MSPI_FLASH_STATUS_SUCCESS;
}
至此,FM25Q128的底层驱动代码与SDK中的MSPI外设API已经对接完成,我们可以操作以下的API对Flash进行擦除扇区,擦除块,擦除全片,读,写等测试。
//SPI Flash初始化
uint32_t
am_devices_mspi_flash_init(am_hal_mspi_dev_config_t *psMSPISettings, void **pHandle);
// 获取SPI Flash的器件ID码
uint32_t
am_devices_mspi_flash_id(void);
// SPI Flash扇区擦除。注意:实际上是调用的Block块擦除命令0xD8,擦除单位为64KB
uint32_t
am_devices_mspi_flash_sector_erase(uint32_t ui32SectorAddress);
// SPI Flash全片擦除
uint32_t am_devices_mspi_flash_mass_erase(void);
// 读取SPI Flash内容
uint32_t
am_devices_mspi_flash_read(uint8_t *pui8RxBuffer,
uint32_t ui32ReadAddress,
uint32_t ui32NumBytes,
bool bWaitForCompletion);
// SPI Flash写入内容
uint32_t
am_devices_mspi_flash_write(uint8_t *pui8TxBuffer,
uint32_t ui32WriteAddress,
uint32_t ui32NumBytes);
图片新闻
技术文库
最新活动更多
-
即日-12.26立即报名>>> 【在线会议】村田用于AR/VR设计开发解决方案
-
1月8日火热报名中>> Allegro助力汽车电气化和底盘解决方案优化在线研讨会
-
1月9日立即预约>>> 【直播】ADI电能计量方案:新一代直流表、EV充电器和S级电能表
-
即日-1.14火热报名中>> OFweek2025中国智造CIO在线峰会
-
即日-1.20限时下载>>> 爱德克(IDEC)设备及工业现场安全解决方案
-
即日-1.24立即参与>>> 【限时免费】安森美:Treo 平台带来出色的精密模拟
推荐专题
发表评论
请输入评论内容...
请输入评论/评论长度6~500个字
暂无评论
暂无评论