0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【技術(shù)分享】Apollo3 SDK平臺(tái)添加支持復(fù)旦微FM25Q128 SPI Flash的方法

潤(rùn)欣科技Fortune ? 2019-03-14 13:39 ? 次閱讀


上海潤(rùn)欣科技股份有限公司創(chuàng)研社

本文詳細(xì)介紹了,如何在Apollo3 SDK v2.0平臺(tái)上增加對(duì)復(fù)旦微FM25Q128 SPI Flash支持的方法。本文將結(jié)合軟件和硬件,闡述如何通過(guò)Apollo3片上串行外設(shè)MSPI接口Quad SPI模式訪問(wèn)SPI Flash的底層驅(qū)動(dòng)代碼的實(shí)現(xiàn)步驟。

1、 什么是MSPI

MSPI,即Multi-bit SPI的縮寫,Apollo3新引入的串行外設(shè),可以支持單線SPI,Dual SPIQuad SPI,以及八線Octal SPI(可以是單個(gè)Octal設(shè)備,也可以是兩個(gè)Quad Pair組成的Octal 設(shè)備)等模式,最高速率24MHz,可以外接串行存儲(chǔ)設(shè)備,如PSRAM,SPI Nor Flash等,支持XIP片上直接運(yùn)行代碼。MPSI支持全部的4SPI CPOL/CPHA模式,即模式0-3支持DMA。支持Command Queue。2個(gè)片選,以Quad-SPI為例,MSPI最多支持兩路Quad-SPI,這兩路共用一個(gè)MSPI CLK。兩路QSPI分時(shí)操作。MSPI具體的管腳復(fù)用圖如下圖1,

pIYBAFyJ4o6ASN_iAACdRZ2ZE98973.jpg

圖1 MSPI管腳復(fù)用圖

2、 MSPI連接SPI FlashQuad SPI四線模式,如圖2

pIYBAFyJ4qeAPytNAAA5X0_h2nA803.jpg

2 MSPI采用Quad SPI接口連接外部SPI Flash器件原理圖

3、根據(jù)以上圖2所示硬件原理圖,我們需要對(duì)SDK中的BSP庫(kù)進(jìn)行相應(yīng)的修改,將MSPI使用到的相關(guān)管腳一一進(jìn)行分配和初始化,如這里用到的:

GP1 --- CE0 (片選)

GP26 --- DQ1(數(shù)據(jù)IO1, SPI DO)

GP4 --- DQ2 (數(shù)據(jù)IO2,SPI WP#)

GP22 --- DQ0 (數(shù)據(jù)IO0SPI DI)

GP24 --- CLK (時(shí)鐘信號(hào))

GP23 --- DQ3 (數(shù)據(jù)IO3SPI HOLD#)

打開(kāi)SDK v2.0目錄下的工程libam_bsp,找到文件am_bsp_pins.h,按照上面分配的管腳修改定義:

o4YBAFyJ4qSAI83dAAAoaddPYOc912.jpg

o4YBAFyJ4qyAAoEmAAAzhcLlGzc157.jpg

pIYBAFyJ4sWAG_7eAACOpnpxWZk395.jpg

再在同一工程里面找到am_bsp_pins.c文件,逐一修改以上管腳對(duì)應(yīng)的屬性結(jié)構(gòu)體,如下:

o4YBAFyJ4ruAfqnAAAA43j13LXs270.jpg

pIYBAFyJ4tWAfIwQAABSGRBvxAM164.jpg

o4YBAFyJ4syAfG-eAABtOp1fyrg823.jpg

pIYBAFyJ4uSAIn85AABrYDmY9h0857.jpg

如果不需要修改其他外設(shè)接口的管腳定義,保存文件后退出編輯模式,SDK v2.0下的示例代碼默認(rèn)包含BSPHAL庫(kù)文件進(jìn)行編譯,所以,這里需要重新將libam_bsp工程進(jìn)行重新編譯,假設(shè)我們使用Keil MDK編譯器,那么生成的庫(kù)文件為libam_bsp.lib,可以直接包含到其他的Keil MDK示例工程下進(jìn)行使用。IAR生成的庫(kù)文件為libam_bsp.a

4、了解復(fù)旦微 SPI Flash器件FM25Q128的基本特性

FM25Q128是復(fù)旦微電子生產(chǎn)的串行SPI接口Nor Flash存儲(chǔ)器,支持單線SPI, 雙線Dual SPI和四線Quad SPIQPI)模式,我們采用的是Quad SPI,即器件的QPI模式(4-4-4)。

FM25Q128的容量為128Mbit16MB),單個(gè)Sector扇區(qū)大小為4KB,支持32KB或者64KB大小的Block塊,可編程頁(yè)大小為256字節(jié)。Sector扇區(qū),Block塊大小和數(shù)量的宏定義詳見(jiàn)如下代碼:

pIYBAFyJ4vaACgB5AAAzLA10akY216.jpg

我們采用的芯片封裝和引腳定義如下圖3所示;

o4YBAFyJ4u2ABPLxAAA04I6luJ0766.jpg

3 FM25Q125芯片引腳定義圖

請(qǐng)?zhí)貏e注意管腳WP#HOLD#/RESET#DQ3)的描述

pIYBAFyJ4wWALFWOAABNQphmlqc025.jpg

出廠時(shí),QE位為0,芯片處于單線SPI模式,硬件上,芯片的Pin3WP#信號(hào),Pin7HOLD#/RESET#信號(hào),繼續(xù)了解WP#HOLD#硬件關(guān)鍵的特點(diǎn),

說(shuō)明: D:\AmbiqMicro\Apollo3\WP和HOLD腳注意事項(xiàng).png

o4YBAFyJ4wWAbDj7AABTEGzP2W8426.jpg

SPI模式下,如果WP#管腳為低,則禁止改寫Status狀態(tài)寄存器的值;當(dāng)HOLD#為低時(shí),即使芯片CS片選腳被激活,芯片仍將進(jìn)入暫停模式,SPI總線無(wú)法正常訪問(wèn)SPI Flash,包括讀取Status狀態(tài)寄存器的值,芯片相當(dāng)于進(jìn)入了復(fù)位狀態(tài)。因?yàn)樾酒鰪S默認(rèn)模式是單線SPI模式,因此,我們需要先通過(guò)Apollo3MSPI接口的單線SPI模式(1-1-1)來(lái)初始化器件,讓器件進(jìn)入QPI模式(4-4-4)后,然后再使用Quad SPI進(jìn)行訪問(wèn)SPI Flash,以實(shí)現(xiàn)利用最高的效率訪問(wèn)SPI Flash外設(shè)。SPI的不同接口類型在傳輸指令碼、地址碼、數(shù)據(jù)碼時(shí)所使用的傳輸通道數(shù)量不同,如下圖4所示:

pIYBAFyJ4x-ANTiKAAA84EAqpfY395.jpg

4 SPI不同接口類型的區(qū)別

FM25Q128上電初始化流程如下圖所示,要使能芯片的QPI模式,需要使能狀態(tài)寄存器Status Register-2中的bit1QE,然后使用0x38命令使能進(jìn)入QPI模式。退出QPI模式可以發(fā)送0xFF命令或者發(fā)送軟件復(fù)位序列0x66 + 0x99,如下圖5所示。

o4YBAFyJ4xiAZrXOAAA-8bPi8pU401.jpg

5 FM25Q125上電初始化流程

如上所述,初次上電后,Flash芯片處于單線SPI模式,WP#HOLD#管腳可能影響狀態(tài)寄存器的寫入操作,實(shí)際調(diào)試底層驅(qū)動(dòng)代碼的過(guò)程中,筆者也發(fā)現(xiàn)了這個(gè)問(wèn)題,由于HOLD#沒(méi)有外接上拉電阻,在SPI模式下Flash芯片的HOLD#腳電平不穩(wěn),導(dǎo)致讀寫狀態(tài)寄存器時(shí)而正常,時(shí)而失敗,開(kāi)發(fā)板正常,客戶的板子失敗等現(xiàn)象,調(diào)試了很長(zhǎng)時(shí)間才發(fā)現(xiàn)問(wèn)題根源在于此。我們可以將Apollo3芯片的MSPI接口配置成SPI模式,并將連接到FM25Q128DQ2(WP#)DQ3HOLD#/RESET#)的管腳GP4GP23配置成GPIO輸出,使能內(nèi)部上拉電阻,并且同時(shí)輸出高電平,讓WP#HOLD#管腳處于非激活狀態(tài)

我們先通過(guò)閱讀Datasheet來(lái)了解一下Apollo3GPIO口結(jié)構(gòu),以及內(nèi)部上拉電阻的配置。

pIYBAFyJ4zOANC7IAAB2QiZF-4Q737.jpg

pIYBAFyJ4zqALAeSAAA-y9FUHc4639.jpg

o4YBAFyJ4zOANEuTAACP7LEqSMk897.jpg

o4YBAFyJ4zuAOm9xAAAp4_3KgaI060.jpg

Apollo3的所有的GPIO都可以通過(guò)軟件來(lái)配置(PADnPULL)使能內(nèi)部上拉電阻(除了GPIO20為下拉),上拉電阻默認(rèn)狀態(tài)是禁用的。另外,包含有I2C功能的GPIO的內(nèi)部上拉電阻是可以選擇四種不同阻值的。我們用到的GP4GP23不包含I2C功能,因此不能選擇上拉電阻的阻值。經(jīng)過(guò)與AmbiqMicro原廠工程師溝通,了解到內(nèi)部通用上拉電阻的阻值大約為63KΩ,這個(gè)內(nèi)部的弱上拉足可以保證在SPI模式初始化SPI Flash時(shí),WP#HOLD#/RESET#管腳穩(wěn)定為高電平狀態(tài)。參考代碼如下:

#define AM_BSP_GPIO_GP23 23

#define AM_BSP_GPIO_GP4 4

const am_hal_gpio_pincfg_t g_AM_BSP_GPIO_GP23_HOLD =

{

.uFuncSel = AM_HAL_PIN_23_GPIO,

.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA,

.ePullup = AM_HAL_GPIO_PIN_PULLUP_WEAK,

.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL,

.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE

};

const am_hal_gpio_pincfg_t g_AM_BSP_GPIO_GP4_WP =

{

.uFuncSel = AM_HAL_PIN_4_GPIO,

.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA,

.ePullup = AM_HAL_GPIO_PIN_PULLUP_WEAK,

.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL,

.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE

};

static void ConfigGP23AsGpioOutputForPullHighHoldPin (void)

{

//

// Configure the pin as a push-pull GPIO output.

//

am_hal_gpio_pinconfig(AM_BSP_GPIO_GP23, g_AM_BSP_GPIO_GP23_HOLD);

//

// Disable the output driver, and set the output value to the high level

// state. Note that for Apollo3 GPIOs in push-pull mode, the output

// enable, normally a tri-state control, instead functions as an enable

// for Fast GPIO. Its state does not matter on previous chips, so for

// normal GPIO usage on Apollo3, it must be disabled.

//

am_hal_gpio_state_write(AM_BSP_GPIO_GP23, AM_HAL_GPIO_OUTPUT_TRISTATE_DISABLE);

am_hal_gpio_state_write(AM_BSP_GPIO_GP23, AM_HAL_GPIO_OUTPUT_SET); // pull high

}

static void ConfigGP4AsGpioOutputForPullHighWPPin (void)

{

//

// Configure the pin as a push-pull GPIO output.

//

am_hal_gpio_pinconfig(AM_BSP_GPIO_GP4, g_AM_BSP_GPIO_GP4_WP); //

// Disable the output driver, and set the output value to the high level

// state. Note that for Apollo3 GPIOs in push-pull mode, the output

// enable, normally a tri-state control, instead functions as an enable

// for Fast GPIO. Its state does not matter on previous chips, so for

// normal GPIO usage on Apollo3, it must be disabled.

//

am_hal_gpio_state_write(AM_BSP_GPIO_GP4, AM_HAL_GPIO_OUTPUT_TRISTATE_DISABLE);

am_hal_gpio_state_write(AM_BSP_GPIO_GP4, AM_HAL_GPIO_OUTPUT_SET); // pull high

}

pIYBAFyJ41WACI0NAABaNOJchtA211.jpg

代碼詳見(jiàn)SDK v2.0目錄下的示例工程mspi_quad_example,文件am_devices_mspi_flash.c。

5、 SDK v2.0示例代碼mspi_quad_example的基礎(chǔ)上添加FM25Q128的支持

am_devices_mspi_flash.h文件中增加器件型號(hào)宏定義:#define FUDAN_FM25Q128

以及器件支持的相關(guān)操作命令,ID碼以及容量宏定義

#if defined (FUDAN_FM25Q128)

//*******************************************************************

//

// Device specific identification.

//

//*******************************************************************

#define AM_DEVICES_MSPI_FLASH_ID 0x001840A1

#define AM_DEVICES_MSPI_FLASH_ID_MASK 0x00FFFFFF

//*******************************************************************

//

// Device specific definitions for flash commands

//

//*******************************************************************

#define AM_DEVICES_MSPI_FLASH_READ_STATUS_REGISTER1 0x05 // RDSR1, read STATUS_REGISTER 1

#define AM_DEVICES_MSPI_FLASH_READ_STATUS_REGISTER2 0x35 // RDSR2, read STATUS_REGISTER 2

#define AM_DEVICES_MSPI_FLASH_READ_STATUS_REGISTER3 0x15 // RDSR3, read STATUS_REGISTER 3

#define AM_DEVICES_MSPI_FLASH_WRITE_STATUS_REGISTER1 0x01 // WRSR1, write STATUS_REGISTER 1

#define AM_DEVICES_MSPI_FLASH_WRITE_STATUS_REGISTER2 0x31 // WRSR2, write STATUS_REGISTER 2

#define AM_DEVICES_MSPI_FLASH_WRITE_STATUS_REGISTER3 0x11 // WRSR3, write STATUS_REGISTER 3

#define AM_DEVICES_MSPI_FLASH_ENABLE_QPI_MODE 0x38 // EQIO, Enable QPI

#define AM_DEVICES_MSPI_FLASH_DISABLE_QPI_MODE 0xFF // Disable QPI

#define AM_DEVICES_MSPI_FLASH_ENABLE_RESET 0x66 // Enable Reset

#define AM_DEVICES_MSPI_FLASH_RESET 0x99 // Reset

#define AM_DEVICES_MSPI_FLASH_WRITE_ENABLE_VOLATILE 0x50 // Write Enable for Volatile Status Register

//*******************************************************************

//

// Device specific definitions for the Configuration register(s)

//

//*******************************************************************

#define AM_DEVICES_MSPI_CLEAR_STATUS_REGISTER1 (0x00) // the value to clear the status register-1

#define AM_DEVICES_MSPI_ENABLE_QUAD_STATUS_REGISTER2 (0xF2) // LC = 11b, dummy cycles = 4 for quad enable, 0 for spi mdode

#define AM_DEVICES_MSPI_CLEAR_STATUS_REGISTER3 (0xFC) // to clear the status register-3, the reserved bits will be bypassed

//*******************************************************************

//

// Device specific definitions for the flash size information

//

//*******************************************************************

#define AM_DEVICES_MSPI_FLASH_PAGE_SIZE 0x100 // 256 bytes, minimum program unit

#define AM_DEVICES_MSPI_FLASH_SECTOR_SIZE 0x1000 // 4K bytes

#define AM_DEVICES_MSPI_FLASH_BLOCK_SIZE 0x10000 // 64K bytes.

#define AM_DEVICES_MSPI_FLASH_MAX_SECTORS 4096 // Sectors within 3-byte address range. 4096 * 4KB = 16MB

#define AM_DEVICES_MSPI_FLASH_MAX_BLOCKS 256 // 256 * 64KB = 16MB

#endif

上電后初始化先清除SR1SR3中的相應(yīng)的狀態(tài)位和錯(cuò)誤標(biāo)志位。

說(shuō)明:狀態(tài)寄存器SR2-3中的有些位標(biāo)注為R,其為Reserved Bit,即保留位,不能被軟件改寫,建議采用先讀出SR2-3的值,再使用與或操作置位或者清除可以改寫的位,同時(shí)保留那些原有標(biāo)注R的位的值。

o4YBAFyJ406AA3FYAAB7ozmMiIY662.jpg

o4YBAFyJ41WALn2iAABa4XVTD5A085.jpg

pIYBAFyJ426AIa7gAAC_OkGu6P8829.jpg

o4YBAFyJ42eAKdOIAAA2p2KUyKA587.jpg

o4YBAFyJ426ADISRAABOFMPd8-8356.jpg

pIYBAFyJ44aAa2WGAACK7hv9JCA897.jpg

am_devices_mspi_flash.c文件中增加對(duì)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模式,各參數(shù)說(shuō)明如下:

AM_HAL_MSPI_SPI_MODE_0 配置為SPI Mode

AM_HAL_MSPI_CLK_3MHZ 配置較低的SPI速率提高穩(wěn)定性和兼容性

.ui8TurnAround = 8:芯片出廠LC默認(rèn)值為00,對(duì)應(yīng)的SPI模式下dummy cycles8

AM_HAL_MSPI_ADDR_3_BYTE 24位即3字節(jié)地址碼

AM_HAL_MSPI_INSTR_1_BYTE 1字節(jié)指令碼

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:\n\r");

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\n", (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\n", (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\n", (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:\n\r");

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\n", (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\n", (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\n", (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.\n");

// 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.\n");

//

// 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.\n");

}

am_util_stdio_printf("Get the value of STATUS REGISTER 2:\n");

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\n", (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.\n");

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.\n");

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.\n");

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.\n");

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.\n");

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.\n");

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.\n");

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.\n");

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.\n");

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.\n");

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.\n");

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.\n");

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.\n");

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.\n",(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.\n");

// 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.\n");

// 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.\n", 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的底層驅(qū)動(dòng)代碼與SDK中的MSPI外設(shè)API已經(jīng)對(duì)接完成,我們可以操作以下的API對(duì)Flash進(jìn)行擦除扇區(qū),擦除塊,擦除全片,讀,寫等測(cè)試。

//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扇區(qū)擦除。注意:實(shí)際上是調(diào)用的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內(nèi)容

uint32_t

am_devices_mspi_flash_read(uint8_t *pui8RxBuffer,

uint32_t ui32ReadAddress,

uint32_t ui32NumBytes,

bool bWaitForCompletion);

// SPI Flash寫入內(nèi)容

uint32_t

am_devices_mspi_flash_write(uint8_t *pui8TxBuffer,

uint32_t ui32WriteAddress,

uint32_t ui32NumBytes);

SPI Flash的相關(guān)API操作Demo詳見(jiàn)mspi_quad_example工程下的mspi_quad_example.c文件。注意:開(kāi)啟宏定義#define TEST_QUAD_SPI,即為測(cè)試Quad SPI模式讀寫SPI Flash;如果注釋掉該宏,則為單線SPI模式讀寫SPI FlashSPI Flash操作成功后,通過(guò)J-LinkSWO輸出log信息顯示操作結(jié)果,截圖如下:

o4YBAFyJ44eAXPtqAAB7e_gAFYU601.jpg

o4YBAFyJ44-AYoMMAABoTbs9_LY333.jpg

o4YBAFyJ45aAXv2VAABn2JuiycM846.jpg

后記:

整理一下調(diào)試過(guò)程中遇到的一些坑:

1、SDK v2.0v1.2.12啟動(dòng)代碼startup_keil.s作了改動(dòng),直接將SDK v1.2.12中調(diào)試好的驅(qū)動(dòng)代碼放到v2.0中進(jìn)行編譯,導(dǎo)致無(wú)法進(jìn)入MSPI中斷服務(wù)程序,讀取Flash內(nèi)容時(shí)卡死,原因是SDK v2.0中把MSPI中斷服務(wù)函數(shù)名稱修改了:void am_mspi0_isr(void)

o4YBAFyJ452ASpnyAABy4WCfkGc168.jpg

2、新的片子FM25Q128在初始化過(guò)程中無(wú)法正常讀取和修改狀態(tài)寄存器,這是因?yàn)樾酒J(rèn)QE=0,芯片處于單線SPI模式,Pin3WP#腳,Pin7Hold#/RESET#腳,由于Pin7電壓不穩(wěn)定,或者處于低電平狀態(tài),導(dǎo)致芯片進(jìn)入RESET狀態(tài),MSPI無(wú)法正確訪問(wèn)Flash狀態(tài)寄存器,導(dǎo)致讀寫失??!初始化為SPI后,將MCU連接到SPI FlashPin3Pin7IO設(shè)置為GPIO輸出并使能內(nèi)部上拉,輸出高電平,初始化SPI Flash操作過(guò)程中,拉高WP#HOLD#/RESET#管腳,讓Flash芯片處于非寫保護(hù)和RESET/HOLD狀態(tài)。代碼片段示例如下:

pIYBAFyJ47SAVDISAABaNYXb8gU168.jpg

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • SPI Flash
    +關(guān)注

    關(guān)注

    1

    文章

    13

    瀏覽量

    10451
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    AMEYA360:兆易創(chuàng)新推出GD25NE系列SPI NOR Flash

    兆易創(chuàng)新 今日宣布推出專為1.2V SoC應(yīng)用打造的雙電壓供電SPI NOR Flash產(chǎn)品——GD25NE系列。該系列產(chǎn)品無(wú)需借助外部升壓電路即可與下一代1.2V SoC實(shí)現(xiàn)無(wú)縫兼容,此產(chǎn)品的面世
    的頭像 發(fā)表于 03-12 16:03 ?67次閱讀

    高效電梯語(yǔ)音播報(bào):基于復(fù)旦FM33LF016的DAC音頻方案

    的商業(yè)中心,還是安靜的醫(yī)院環(huán)境,DAC都能確保語(yǔ)音播報(bào)的清晰度,讓乘客準(zhǔn)確獲取到站信息。方案特色復(fù)旦基于FM33LF016推出了一套DAC音頻輸出方案。
    的頭像 發(fā)表于 12-27 16:33 ?261次閱讀
    高效電梯語(yǔ)音播報(bào):基于<b class='flag-5'>復(fù)旦</b><b class='flag-5'>微</b><b class='flag-5'>FM</b>33LF016的DAC音頻方案

    復(fù)旦榮獲ISO26262:2018功能安全ASIL B產(chǎn)品認(rèn)證證書

    2024年10月29日,上海復(fù)旦微電子集團(tuán)股份有限公司(簡(jiǎn)稱:“復(fù)旦”)榮獲ISO26262:2018功能安全產(chǎn)品認(rèn)證證書(ASILB等級(jí))。這標(biāo)志著復(fù)旦
    的頭像 發(fā)表于 11-08 01:06 ?539次閱讀
    <b class='flag-5'>復(fù)旦</b><b class='flag-5'>微</b>榮獲ISO26262:2018功能安全ASIL B產(chǎn)品認(rèn)證證書

    昂科燒錄器支持FuDanWei復(fù)旦微電子的低功耗微控制器FM33FR024

    芯片燒錄行業(yè)領(lǐng)導(dǎo)者-昂科技術(shù)近日發(fā)布最新的燒錄軟件更新及新增支持的芯片型號(hào)列表,其中FuDanWei復(fù)旦微電子的低功耗微控制器FM33FR024已經(jīng)被昂科的通用燒錄
    的頭像 發(fā)表于 10-12 11:29 ?434次閱讀
    昂科燒錄器<b class='flag-5'>支持</b>FuDanWei<b class='flag-5'>復(fù)旦</b>微電子的低功耗微控制器<b class='flag-5'>FM</b>33FR024

    STM32CUBEMX(13)--SPI,W25Q128外部Flash移植

    128Mbit,相當(dāng)于16M字節(jié)。W25Q128可以支持 SPI 的模式 0 和模式 3,也就是 CPOL=0/CPHA=0 和CPOL
    發(fā)表于 09-30 14:41

    物聯(lián)網(wǎng)行業(yè)中Nor Flash的軟件設(shè)計(jì)分享_W25Q128的軟件設(shè)計(jì)方案

    一 概述 W25Q128是一種NOR Flash芯片,掉電后數(shù)據(jù)不丟失的特點(diǎn)。 W25Q128FV陣列被組織成65,536個(gè)可編程頁(yè)面,每個(gè)頁(yè)面256字節(jié)。每次最多可編程256字節(jié)??梢砸?6頁(yè)為
    的頭像 發(fā)表于 09-26 11:20 ?877次閱讀
    物聯(lián)網(wǎng)行業(yè)中Nor <b class='flag-5'>Flash</b>的軟件設(shè)計(jì)分享_W<b class='flag-5'>25Q128</b>的軟件設(shè)計(jì)方案

    W25Q128FV中文手冊(cè)

    W25Q128FV(128Mbit)型串行 Flash 存儲(chǔ)器面向受限于空間、引腳和功耗的系統(tǒng),提供了一種存儲(chǔ)解決方案。
    發(fā)表于 09-18 11:33 ?17次下載

    spi_flash_read接口去訪問(wèn)SPI外掛的FLASH,無(wú)法返回是怎么回事?

    (HSPI), 0x3); SET_PERI_REG_MASK(SPI_USER(HSPI), BIT(5)); 做了以上初始化后,用spi_flash_read這個(gè)接口去訪問(wèn)SPI
    發(fā)表于 07-18 06:40

    FLASH芯片從W25Q80BL換為W25Q80DV后,系統(tǒng)運(yùn)行經(jīng)常崩潰怎么解決?

    104Mhz) 3,Tpuw(Time Delay Before Write Instruction)特性不一樣,DV 的最小值為5ms,BL的最小值為1ms,這個(gè)是否會(huì)有影響。 esp官方對(duì)這款FLASH支持時(shí)如何的?有
    發(fā)表于 07-10 06:11

    ESP32外部flashspi外設(shè)沖突怎么解決?

    硬件: ESP32 ,W25Q128 SPI顯示器 庫(kù):IDF4.0.1 使用hspi掛載了外部16MB的W25Q128,并同時(shí)掛載了SPI的顯示器,使用兩不同IO口進(jìn)行分時(shí)復(fù)用。 問(wèn)
    發(fā)表于 06-25 06:19

    【GD32H757Z海棠派開(kāi)發(fā)板使用手冊(cè)】第十一講 SPI-SPI NOR FLASH讀寫實(shí)驗(yàn)

    通過(guò)本實(shí)驗(yàn)主要學(xué)習(xí)以下內(nèi)容: ?SPI簡(jiǎn)介 ?GD32H7 SPI簡(jiǎn)介 ?SPI NOR FLASH——GD25Q128ESIGR簡(jiǎn)介 ?使
    的頭像 發(fā)表于 06-04 11:42 ?1343次閱讀
    【GD32H757Z海棠派開(kāi)發(fā)板使用手冊(cè)】第十一講 <b class='flag-5'>SPI-SPI</b> NOR <b class='flag-5'>FLASH</b>讀寫實(shí)驗(yàn)

    【GD32F470紫藤派開(kāi)發(fā)板使用手冊(cè)】第十一講 SPI-SPI NOR FLASH讀寫實(shí)驗(yàn)

    通過(guò)本實(shí)驗(yàn)主要學(xué)習(xí)以下內(nèi)容: ?SPI簡(jiǎn)介 ?GD32F470 SPI簡(jiǎn)介 ?SPI NOR FLASH——GD25Q32ESIGR簡(jiǎn)介 ?
    的頭像 發(fā)表于 05-17 09:57 ?2098次閱讀
    【GD32F470紫藤派開(kāi)發(fā)板使用手冊(cè)】第十一講 <b class='flag-5'>SPI-SPI</b> NOR <b class='flag-5'>FLASH</b>讀寫實(shí)驗(yàn)

    具有雙/四SPI和QPI的串行閃存W25Q128FV數(shù)據(jù)手冊(cè)

    電子發(fā)燒友網(wǎng)站提供《具有雙/四SPI和QPI的串行閃存W25Q128FV數(shù)據(jù)手冊(cè).pdf》資料免費(fèi)下載
    發(fā)表于 04-25 17:11 ?0次下載

    STM32F746 QSPI的Flash擴(kuò)展后,添加到工程下載發(fā)現(xiàn)報(bào)錯(cuò),為什么?

    使用 W25Q128 模塊 ,使用的是雪STM32F746IGT6的開(kāi)發(fā)板,在QSPI進(jìn)行Flash擴(kuò)展了解發(fā)現(xiàn)需要做一個(gè).FLM的Flash編程算法,我找一個(gè)STM32H7的進(jìn)行修
    發(fā)表于 04-17 06:31

    全志R128 SDK HAL 模塊開(kāi)發(fā)指南——Flash Controller

    Model 0/1/2/3 可靈活配置 4 段虛擬地址區(qū)間,支持 DMA 讀寫、Nor Flash XIP 操作 最大 2?32Bytes 容量的 Nor Flash,常見(jiàn)有 64M
    發(fā)表于 03-25 10:11