mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
targets/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_qspi.c
- Committer:
- AnnaBridge
- Date:
- 2019-02-20
- Revision:
- 189:f392fc9709a3
- Parent:
- 179:b0033dcd6934
File content as of revision 189:f392fc9709a3:
/***************************************************************************//** * @file em_qspi.c * @brief QSPI Octal-SPI Flash Controller API * @version 5.3.3 ******************************************************************************* * # License * <b>Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com</b> ******************************************************************************* * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no * obligation to support this Software. Silicon Labs is providing the * Software "AS IS", with no express or implied warranties of any kind, * including, but not limited to, any implied warranties of merchantability * or fitness for any particular purpose or warranties against infringement * of any proprietary rights of a third party. * * Silicon Labs will not be liable for any consequential, incidental, or * special damages, or any other relief, or for any claim by any third party, * arising from your use of this Software. * ******************************************************************************/ #include "em_qspi.h" #if defined(QSPI_COUNT) && (QSPI_COUNT > 0) #include "em_assert.h" /***************************************************************************//** * @addtogroup emlib * @{ ******************************************************************************/ /* *INDENT-OFF* */ /***************************************************************************//** * @addtogroup QSPI * @brief QSPI Octal-SPI Controller API * @details * These QSPI functions provide basic support for using the QSPI peripheral * in the following configurations: * @li @b Direct Read/Write, used for memory mapped access to external * memory. * @li @b STIG Command, used for configuring and executing commands on the * external memory device. * * Indirect read/write, PHY configuration and Execute-In-Place (XIP) * configuration is not supported. * * The example below shows how to set up the QSPI for direct read and write * operation: * @code CMU_ClockEnable(cmuClock_GPIO, true); CMU_ClockEnable(cmuClock_QSPI0, true); QSPI_Init_TypeDef initQspi = QSPI_INIT_DEFAULT; QSPI_Init(QSPI0, &initQspi); // Configure QSPI pins GPIO_PinModeSet(EXTFLASH_PORT_CS, EXTFLASH_PIN_CS, gpioModePushPull, 0); GPIO_PinModeSet(EXTFLASH_PORT_SCLK, EXTFLASH_PIN_SCLK, gpioModePushPull, 0); GPIO_PinModeSet(EXTFLASH_PORT_DQ0, EXTFLASH_PIN_DQ0, gpioModePushPull, 0); GPIO_PinModeSet(EXTFLASH_PORT_DQ1, EXTFLASH_PIN_DQ1, gpioModePushPull, 0); GPIO_PinModeSet(EXTFLASH_PORT_DQ2, EXTFLASH_PIN_DQ2, gpioModePushPull, 0); GPIO_PinModeSet(EXTFLASH_PORT_DQ3, EXTFLASH_PIN_DQ3, gpioModePushPull, 0); // Configure QSPI routing to GPIO QSPI0->ROUTELOC0 = EXTFLASH_QSPI_LOC; QSPI0->ROUTEPEN = QSPI_ROUTEPEN_SCLKPEN | EXTFLASH_QSPI_CSPEN | QSPI_ROUTEPEN_DQ0PEN | QSPI_ROUTEPEN_DQ1PEN | QSPI_ROUTEPEN_DQ2PEN | QSPI_ROUTEPEN_DQ3PEN; // Configure direct read QSPI_ReadConfig_TypeDef readConfig = QSPI_READCONFIG_DEFAULT; readConfig.dummyCycles = 8; readConfig.opCode = 0x6B; readConfig.instTransfer = qspiTransferSingle; readConfig.addrTransfer = qspiTransferSingle; readConfig.dataTransfer = qspiTransferQuad; QSPI_ReadConfig(QSPI0, &readConfig); // Configure direct write QSPI_WriteConfig_TypeDef writeConfig = QSPI_WRITECONFIG_DEFAULT; writeConfig.dummyCycles = 0; writeConfig.opCode = 0x38; writeConfig.addrTransfer = qspiTransferQuad; writeConfig.dataTransfer = qspiTransferQuad; writeConfig.autoWEL = true; QSPI_WriteConfig(QSPI0, &writeConfig);@endcode * * To configure an external flash, commands can set up and executed using the * Software Triggered Instruction Generator (STIG) function of the QSPI, as * shown in the example below: * @code uint8_t status; QSPI_StigCmd_TypeDef stigCmd = {0}; stigCmd.cmdOpcode = EXTFLASH_OPCODE_READ_STATUS; stigCmd.readDataSize = 1; stigCmd.readBuffer = &status; QSPI_ExecStigCmd(QSPI0, &stigCmd);@endcode * @{ ******************************************************************************/ /* *INDENT-OFF* */ /******************************************************************************* ************************** GLOBAL FUNCTIONS ******************************* ******************************************************************************/ /***************************************************************************//** * @brief * Initialize QSPI. * * @param[in] qspi * Pointer to the QSPI peripheral register block. * * @param[in] init * Pointer to initialization structure used to configure QSPI. ******************************************************************************/ void QSPI_Init(QSPI_TypeDef * qspi, const QSPI_Init_TypeDef * init) { uint32_t divisor; EFM_ASSERT((init->divisor >= 2) && (init->divisor <= 32)); divisor = init->divisor / 2 - 1; qspi->CONFIG = (qspi->CONFIG & ~_QSPI_CONFIG_MSTRBAUDDIV_MASK) | (divisor << _QSPI_CONFIG_MSTRBAUDDIV_SHIFT); QSPI_Enable(qspi, init->enable); } /***************************************************************************//** * @brief * Configure Read Operations. * * @param[in] qspi * Pointer to the QSPI peripheral register block. * * @param[in] config * Pointer to configuration structure for QSPI read operations. ******************************************************************************/ void QSPI_ReadConfig(QSPI_TypeDef * qspi, const QSPI_ReadConfig_TypeDef * config) { EFM_ASSERT(config->dummyCycles < 31); QSPI_WaitForIdle(qspi); qspi->DEVINSTRRDCONFIG = (config->opCode << _QSPI_DEVINSTRRDCONFIG_RDOPCODENONXIP_SHIFT) | (config->dummyCycles << _QSPI_DEVINSTRRDCONFIG_DUMMYRDCLKCYCLES_SHIFT) | (config->addrTransfer << _QSPI_DEVINSTRRDCONFIG_ADDRXFERTYPESTDMODE_SHIFT) | (config->dataTransfer << _QSPI_DEVINSTRRDCONFIG_DATAXFERTYPEEXTMODE_SHIFT) | (config->instTransfer << _QSPI_DEVINSTRRDCONFIG_INSTRTYPE_SHIFT); } /***************************************************************************//** * @brief * Configure Write Operations. * * @param[in] qspi * Pointer to the QSPI peripheral register block. * * @param[in] config * Pointer to configuration structure for QSPI write operations. ******************************************************************************/ void QSPI_WriteConfig(QSPI_TypeDef * qspi, const QSPI_WriteConfig_TypeDef * config) { EFM_ASSERT(config->dummyCycles < 31); QSPI_WaitForIdle(qspi); qspi->DEVINSTRWRCONFIG = (config->opCode << _QSPI_DEVINSTRWRCONFIG_WROPCODE_SHIFT) | (config->dummyCycles << _QSPI_DEVINSTRWRCONFIG_DUMMYWRCLKCYCLES_SHIFT) | (config->addrTransfer << _QSPI_DEVINSTRWRCONFIG_ADDRXFERTYPESTDMODE_SHIFT) | (config->dataTransfer << _QSPI_DEVINSTRWRCONFIG_DATAXFERTYPEEXTMODE_SHIFT) | ((config->autoWEL ? 0 : 1) << _QSPI_DEVINSTRWRCONFIG_WELDIS_SHIFT); } /***************************************************************************//** * @brief * Execute a STIG command. * * @details * STIG means "software triggered instruction generator" and is used when the * application needs to access status registers, configuration registers or * perform erase functions. The STIG commands can be used to perform any * instruction that the flash device supports. * * @param[in] qspi * Pointer to the QSPI peripheral register block. * * @param[in] stigCmd * Pointer to a structure that describes the STIG command. ******************************************************************************/ void QSPI_ExecStigCmd(QSPI_TypeDef * qspi, const QSPI_StigCmd_TypeDef * stigCmd) { uint32_t i; EFM_ASSERT(stigCmd->addrSize <= 4); EFM_ASSERT(stigCmd->writeDataSize <= 8); EFM_ASSERT(stigCmd->readDataSize <= 8); EFM_ASSERT(stigCmd->dummyCycles < 32); if (stigCmd->writeDataSize) { EFM_ASSERT(stigCmd->writeBuffer); } if (stigCmd->readDataSize) { EFM_ASSERT(stigCmd->readBuffer); } QSPI_WaitForIdle(qspi); qspi->FLASHCMDCTRL = (stigCmd->cmdOpcode << _QSPI_FLASHCMDCTRL_CMDOPCODE_SHIFT) | (stigCmd->dummyCycles << _QSPI_FLASHCMDCTRL_NUMDUMMYCYCLES_SHIFT); if (stigCmd->writeDataSize) { uint32_t buffer[2] = { 0, 0 }; uint8_t * dst = (uint8_t *) buffer; uint8_t * src = stigCmd->writeBuffer; qspi->FLASHCMDCTRL |= QSPI_FLASHCMDCTRL_ENBWRITEDATA | ((stigCmd->writeDataSize - 1) << _QSPI_FLASHCMDCTRL_NUMWRDATABYTES_SHIFT); for (i = 0; i < stigCmd->writeDataSize; i++) { dst[i] = src[i]; } qspi->FLASHWRDATALOWER = buffer[0]; qspi->FLASHWRDATAUPPER = buffer[1]; } if (stigCmd->addrSize) { qspi->FLASHCMDCTRL |= QSPI_FLASHCMDCTRL_ENBCOMDADDR | ((stigCmd->addrSize - 1) << _QSPI_FLASHCMDCTRL_NUMADDRBYTES_SHIFT); qspi->FLASHCMDADDR = stigCmd->address; } if (stigCmd->modeBitEnable) { qspi->FLASHCMDCTRL |= QSPI_FLASHCMDCTRL_ENBMODEBIT; } if (stigCmd->readDataSize) { qspi->FLASHCMDCTRL |= QSPI_FLASHCMDCTRL_ENBREADDATA | ((stigCmd->readDataSize - 1) << _QSPI_FLASHCMDCTRL_NUMRDDATABYTES_SHIFT); } // Start command execution qspi->FLASHCMDCTRL |= QSPI_FLASHCMDCTRL_CMDEXEC; while (qspi->FLASHCMDCTRL & QSPI_FLASHCMDCTRL_CMDEXECSTATUS) ; // Read data if any if (stigCmd->readDataSize) { uint32_t buffer[2] = { 0, 0 }; const uint8_t * src = (const uint8_t *)buffer; uint8_t * dst = stigCmd->readBuffer; buffer[0] = qspi->FLASHRDDATALOWER; buffer[1] = qspi->FLASHRDDATAUPPER; for (i = 0; i < stigCmd->readDataSize; i++) { dst[i] = src[i]; } } } /** @} (end addtogroup QSPI) */ /** @} (end addtogroup emlib) */ #endif /* defined(QSPI_COUNT) && (QSPI_COUNT > 0) */