diff --git a/README.md b/README.md index b882c37..563d82f 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,69 @@ # MX25R6435F -Arduino library to support the Quad-SPI NOR Flash memory MX25R6435F +Arduino library to support the Quad-SPI NOR Flash memory MX25R6435F using the Quad SPI flash memories interface. Since library version 2.0.0 and [STM32 core](https://github.com/stm32duino/Arduino_Core_STM32) version 2.0.0 the OctoSPI Flash memories interface can also be used. ## API The library provides the following API: -* begin() -* end() -* write() -* read() -* mapped() -* erase() -* eraseChip() -* eraseSector() -* suspendErase() -* resumeErase() -* sleep() -* wakeup() -* status() -* info() -* length() +* `begin()` +* `end()` +* `write()` +* `read()` +* `mapped()` +* `erase()` +* `eraseChip()` +* `eraseSector()` +* `suspendErase()` +* `resumeErase()` +* `sleep()` +* `wakeup()` +* `status()` +* `info()` +* `length()` + +Since library version 2.0.0, xSPI pins can be defined at sketch level, using: + +* To redefine the default one before call of `begin()`: + + * `setDx(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3)` + * `setDx(PinName data0, PinName data1, PinName data2, PinName data3)` + * `setSSEL(uint32_t ssel)` + * `setSSEL(PinName ssel)` + * `setSCLK(uint32_t sclk)` + * `setSCLK(PinName sclk)` + + *Code snippet:* +```C++ + MX25R6435F.setDx(PE12, PE13, PE14, PE15); // using pin number + MX25R6435F.setSCLK(PE10); + MX25R6435F.setSSEL(PE_11); // using PinName + MX25R6435F.begin(); +``` + +* or using the `begin()` method: + + * `MX25R6435FClass(uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3, uint8_t clk, uint8_t ssel)` + + *Code snippet:* +```C++ + MX25R6435F.begin(PE12, PE13, PE14, PE15, PE10, PE11); +``` + +* or by redefining the default pins definition (using [build_opt.h](https://github.com/stm32duino/wiki/wiki/Customize-build-options-using-build_opt.h) or [hal_conf_extra.h](https://github.com/stm32duino/wiki/wiki/HAL-configuration#customize-hal-or-variant-definition)): + + * `MX25R6435F_D0` + * `MX25R6435F_D1` + * `MX25R6435F_D2` + * `MX25R6435F_D3` + * `MX25R6435F_SCLK` + * `MX25R6435F_SSEL` ## Examples -3 sketches provide basic examples to show how to use the library API. -demo.ino uses basic read/write functions. -eraseChip.ino erases all data present in the memory. -memoryMappedMode.ino shows how to use the mapped mode. +3 sketches provide basic examples to show how to use the library API: +* `demo.ino` uses basic read/write functions. +* `eraseChip.ino` erases all data present in the memory. +* `memoryMappedMode.ino` shows how to use the mapped mode. ## Documentation diff --git a/keywords.txt b/keywords.txt index 9472dfa..67bee68 100644 --- a/keywords.txt +++ b/keywords.txt @@ -26,6 +26,9 @@ wakeup KEYWORD2 status KEYWORD2 info KEYWORD2 length KEYWORD2 +setDx KEYWORD2 +setSCLK KEYWORD2 +setSSEL KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/src/MX25R6435F.cpp b/src/MX25R6435F.cpp index 02e2948..0d22a20 100644 --- a/src/MX25R6435F.cpp +++ b/src/MX25R6435F.cpp @@ -9,29 +9,13 @@ ****************************************************************************** * @attention * - *

© COPYRIGHT(c) 2017 STMicroelectronics

+ *

© Copyright (c) 2020 STMicroelectronics. + * 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 STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * 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 software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ @@ -42,18 +26,25 @@ MX25R6435FClass MX25R6435F; MX25R6435FClass::MX25R6435FClass(): initDone(0) { - } -void MX25R6435FClass::begin(void) +void MX25R6435FClass::begin(uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3, uint8_t sclk, uint8_t ssel) { - if(BSP_QSPI_Init() == MEMORY_OK) + _qspi.pin_d0 = digitalPinToPinName(data0); + _qspi.pin_d1 = digitalPinToPinName(data1); + _qspi.pin_d2 = digitalPinToPinName(data2); + _qspi.pin_d3 = digitalPinToPinName(data3); + _qspi.pin_sclk = digitalPinToPinName(sclk); + _qspi.pin_ssel = digitalPinToPinName(ssel); + + if (BSP_QSPI_Init(&_qspi) == MEMORY_OK) { initDone = 1; + } } void MX25R6435FClass::end(void) { - BSP_QSPI_DeInit(); + BSP_QSPI_DeInit(&_qspi); initDone = 0; } @@ -64,11 +55,13 @@ uint32_t MX25R6435FClass::write(uint8_t data, uint32_t addr) uint32_t MX25R6435FClass::write(uint8_t *pData, uint32_t addr, uint32_t size) { - if((pData == NULL) || (initDone == 0)) + if ((pData == NULL) || (initDone == 0)) { return 0; + } - if(BSP_QSPI_Write(pData, addr, size) != MEMORY_OK) + if (BSP_QSPI_Write(&_qspi, pData, addr, size) != MEMORY_OK) { return 0; + } return size; } @@ -84,77 +77,86 @@ uint8_t MX25R6435FClass::read(uint32_t addr) void MX25R6435FClass::read(uint8_t *pData, uint32_t addr, uint32_t size) { - if((pData != NULL) && (initDone == 1)) - BSP_QSPI_Read(pData, addr, size); + if ((pData != NULL) && (initDone == 1)) { + BSP_QSPI_Read(&_qspi, pData, addr, size); + } } uint8_t *MX25R6435FClass::mapped(void) { - if(BSP_QSPI_EnableMemoryMappedMode() != MEMORY_OK) + if (BSP_QSPI_EnableMemoryMappedMode(&_qspi) != MEMORY_OK) { return NULL; + } return (uint8_t *)MEMORY_MAPPED_ADDRESS; } uint8_t MX25R6435FClass::erase(uint32_t addr) { - if(initDone == 0) + if (initDone == 0) { return MEMORY_ERROR; + } - return BSP_QSPI_Erase_Block(addr); + return BSP_QSPI_Erase_Block(&_qspi, addr); } uint8_t MX25R6435FClass::eraseChip(void) { - if(initDone == 0) + if (initDone == 0) { return MEMORY_ERROR; + } - return BSP_QSPI_Erase_Chip(); + return BSP_QSPI_Erase_Chip(&_qspi); } uint8_t MX25R6435FClass::eraseSector(uint32_t sector) { - if(initDone == 0) + if (initDone == 0) { return MEMORY_ERROR; + } - return BSP_QSPI_Erase_Sector(sector); + return BSP_QSPI_Erase_Sector(&_qspi, sector); } uint8_t MX25R6435FClass::suspendErase(void) { - if(initDone == 0) + if (initDone == 0) { return MEMORY_ERROR; + } - return BSP_QSPI_SuspendErase(); + return BSP_QSPI_SuspendErase(&_qspi); } uint8_t MX25R6435FClass::resumeErase(void) { - if(initDone == 0) + if (initDone == 0) { return MEMORY_ERROR; + } - return BSP_QSPI_ResumeErase(); + return BSP_QSPI_ResumeErase(&_qspi); } uint8_t MX25R6435FClass::sleep(void) { - if(initDone == 0) + if (initDone == 0) { return MEMORY_ERROR; + } - return BSP_QSPI_EnterDeepPowerDown(); + return BSP_QSPI_EnterDeepPowerDown(&_qspi); } uint8_t MX25R6435FClass::wakeup(void) { - if(initDone == 0) + if (initDone == 0) { return MEMORY_ERROR; + } - return BSP_QSPI_LeaveDeepPowerDown(); + return BSP_QSPI_LeaveDeepPowerDown(&_qspi); } uint8_t MX25R6435FClass::status(void) { - return BSP_QSPI_GetStatus(); + return BSP_QSPI_GetStatus(&_qspi); } uint32_t MX25R6435FClass::info(memory_info_t info) @@ -164,30 +166,30 @@ uint32_t MX25R6435FClass::info(memory_info_t info) BSP_QSPI_GetInfo(&pInfo); - switch(info){ + switch (info) { case MEMORY_SIZE: res = pInfo.FlashSize; - break; + break; case MEMORY_SECTOR_SIZE: res = pInfo.EraseSectorSize; - break; + break; case MEMORY_SECTOR_NUMBER: res = pInfo.EraseSectorsNumber; - break; + break; case MEMORY_PAGE_SIZE: res = pInfo.ProgPageSize; - break; + break; case MEMORY_PAGE_NUMBER: res = pInfo.ProgPagesNumber; - break; + break; default: res = 0; - break; + break; } return res; diff --git a/src/MX25R6435F.h b/src/MX25R6435F.h index 1386210..940b1c3 100644 --- a/src/MX25R6435F.h +++ b/src/MX25R6435F.h @@ -1,37 +1,18 @@ /** ****************************************************************************** * @file MX25R6435F.h - * @author WI6LABS - * @version V1.0.0 - * @date 19-July-2017 * @brief MX25R6435F library for STM32 Arduino * ****************************************************************************** * @attention * - *

© COPYRIGHT(c) 2017 STMicroelectronics

+ *

© Copyright (c) 2020 STMicroelectronics. + * 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 STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * 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 software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ @@ -39,8 +20,32 @@ #ifndef _MX25R6435F_H_ #define _MX25R6435F_H_ +#include "Arduino.h" #include "mx25r6435f_driver.h" +/* + * For backward compatibility define the xSPI pins used by: + * B-L475E-IOT01A and B-L4S5I-IOT01A + */ +#ifndef MX25R6435F_D0 + #define MX25R6435F_D0 PE12 +#endif +#ifndef MX25R6435F_D1 + #define MX25R6435F_D1 PE13 +#endif +#ifndef MX25R6435F_D2 + #define MX25R6435F_D2 PE14 +#endif +#ifndef MX25R6435F_D3 + #define MX25R6435F_D3 PE15 +#endif +#ifndef MX25R6435F_SCLK + #define MX25R6435F_SCLK PE10 +#endif +#ifndef MX25R6435F_SSEL + #define MX25R6435F_SSEL PE11 +#endif + /* Memory configuration paremeters */ typedef enum { MEMORY_SIZE, @@ -60,13 +65,45 @@ typedef enum { /* Base address of the memory in mapped mode */ #define MEMORY_MAPPED_ADDRESS ((uint32_t)0x90000000) -class MX25R6435FClass -{ +class MX25R6435FClass { public: MX25R6435FClass(); + // setDx/SCLK/SSEL have to be called before begin() + void setDx(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3) + { + _qspi.pin_d0 = digitalPinToPinName(data0); + _qspi.pin_d1 = digitalPinToPinName(data1); + _qspi.pin_d2 = digitalPinToPinName(data2); + _qspi.pin_d3 = digitalPinToPinName(data3); + }; + void setSCLK(uint32_t sclk) + { + _qspi.pin_sclk = digitalPinToPinName(sclk); + }; + void setSSEL(uint32_t ssel) + { + _qspi.pin_ssel = digitalPinToPinName(ssel); + }; + + void setDx(PinName data0, PinName data1, PinName data2, PinName data3) + { + _qspi.pin_d0 = (data0); + _qspi.pin_d1 = (data1); + _qspi.pin_d2 = (data2); + _qspi.pin_d3 = (data3); + }; + void setSCLK(PinName sclk) + { + _qspi.pin_sclk = (sclk); + }; + void setSSEL(PinName ssel) + { + _qspi.pin_ssel = (ssel); + }; + /* Initializes the memory interface. */ - void begin(void); + void begin(uint8_t data0 = MX25R6435F_D0, uint8_t data1 = MX25R6435F_D1, uint8_t data2 = MX25R6435F_D2, uint8_t data3 = MX25R6435F_D3, uint8_t sclk = MX25R6435F_SCLK, uint8_t ssel = MX25R6435F_SSEL); /* De-Initializes the memory interface. */ void end(void); @@ -174,6 +211,7 @@ class MX25R6435FClass private: uint8_t initDone; + QSPI_t _qspi; }; extern MX25R6435FClass MX25R6435F; diff --git a/src/mx25r6435f_desc.h b/src/mx25r6435f_desc.h index ccdc384..76a869d 100644 --- a/src/mx25r6435f_desc.h +++ b/src/mx25r6435f_desc.h @@ -1,211 +1,145 @@ -/** - ****************************************************************************** - * @file mx25r6435f.h - * @author MCD Application Team - * @version V1.0.0 - * @date 17-February-2017 - * @brief This file contains all the description of the MX25R6435F QSPI memory. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2017 STMicroelectronics

- * - * 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 STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * 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. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __MX25R6435F_H -#define __MX25R6435F_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ - -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup Components - * @{ - */ - -/** @addtogroup mx25r6435f - * @{ - */ - -/** @defgroup MX25R6435F_Exported_Types - * @{ - */ - -/** - * @} - */ - -/** @defgroup MX25R6435F_Exported_Constants - * @{ - */ - -/** - * @brief MX25R6435F Configuration - */ -#define MX25R6435F_FLASH_SIZE 0x800000 /* 64 MBits => 8MBytes */ -#define MX25R6435F_BLOCK_SIZE 0x10000 /* 128 blocks of 64KBytes */ -#define MX25R6435F_SUBBLOCK_SIZE 0x8000 /* 256 blocks of 32KBytes */ -#define MX25R6435F_SECTOR_SIZE 0x1000 /* 2048 sectors of 4kBytes */ -#define MX25R6435F_PAGE_SIZE 0x100 /* 32768 pages of 256 bytes */ - -#define MX25R6435F_DUMMY_CYCLES_READ 8 -#define MX25R6435F_DUMMY_CYCLES_READ_DUAL 4 -#define MX25R6435F_DUMMY_CYCLES_READ_QUAD 4 -#define MX25R6435F_DUMMY_CYCLES_2READ 2 -#define MX25R6435F_DUMMY_CYCLES_4READ 4 - -#define MX25R6435F_ALT_BYTES_PE_MODE 0xA5 -#define MX25R6435F_ALT_BYTES_NO_PE_MODE 0xAA - -#define MX25R6435F_CHIP_ERASE_MAX_TIME 240000 -#define MX25R6435F_BLOCK_ERASE_MAX_TIME 3500 -#define MX25R6435F_SUBBLOCK_ERASE_MAX_TIME 3000 -#define MX25R6435F_SECTOR_ERASE_MAX_TIME 240 - -/** - * @brief MX25R6435F Commands - */ -/* Read Operations */ -#define READ_CMD 0x03 -#define FAST_READ_CMD 0x0B -#define DUAL_OUT_READ_CMD 0x3B -#define DUAL_INOUT_READ_CMD 0xBB -#define QUAD_OUT_READ_CMD 0x6B -#define QUAD_INOUT_READ_CMD 0xEB - -/* Program Operations */ -#define PAGE_PROG_CMD 0x02 -#define QUAD_PAGE_PROG_CMD 0x38 - -/* Erase Operations */ -#define SECTOR_ERASE_CMD 0x20 -#define SUBBLOCK_ERASE_CMD 0x52 -#define BLOCK_ERASE_CMD 0xD8 -#define CHIP_ERASE_CMD 0x60 -#define CHIP_ERASE_CMD_2 0xC7 - -#define PROG_ERASE_RESUME_CMD 0x7A -#define PROG_ERASE_RESUME_CMD_2 0x30 -#define PROG_ERASE_SUSPEND_CMD 0x75 -#define PROG_ERASE_SUSPEND_CMD_2 0xB0 - -/* Identification Operations */ -#define READ_ID_CMD 0x9F -#define READ_ELECTRONIC_ID_CMD 0xAB -#define READ_ELEC_MANUFACTURER_DEVICE_ID_CMD 0x90 -#define READ_SERIAL_FLASH_DISCO_PARAM_CMD 0x5A - -/* Write Operations */ -#define WRITE_ENABLE_CMD 0x06 -#define WRITE_DISABLE_CMD 0x04 - -/* Register Operations */ -#define READ_STATUS_REG_CMD 0x05 -#define READ_CFG_REG_CMD 0x15 -#define WRITE_STATUS_CFG_REG_CMD 0x01 - -#define READ_SEC_REG_CMD 0x2B -#define WRITE_SEC_REG_CMD 0x2F - -/* Power Down Operations */ -#define DEEP_POWER_DOWN_CMD 0xB9 - -/* Burst Operations */ -#define SET_BURST_LENGTH_CMD 0xC0 - -/* One-Time Programmable Operations */ -#define ENTER_SECURED_OTP_CMD 0xB1 -#define EXIT_SECURED_OTP_CMD 0xC1 - -/* No Operation */ -#define NO_OPERATION_CMD 0x00 - -/* Reset Operations */ -#define RESET_ENABLE_CMD 0x66 -#define RESET_MEMORY_CMD 0x99 -#define RELEASE_READ_ENHANCED_CMD 0xFF - -/** - * @brief MX25R6435F Registers - */ -/* Status Register */ -#define MX25R6435F_SR_WIP ((uint8_t)0x01) /*!< Write in progress */ -#define MX25R6435F_SR_WEL ((uint8_t)0x02) /*!< Write enable latch */ -#define MX25R6435F_SR_BP ((uint8_t)0x3C) /*!< Block protect */ -#define MX25R6435F_SR_QE ((uint8_t)0x40) /*!< Quad enable */ -#define MX25R6435F_SR_SRWD ((uint8_t)0x80) /*!< Status register write disable */ - -/* Configuration Register 1 */ -#define MX25R6435F_CR1_TB ((uint8_t)0x08) /*!< Top / bottom */ - -/* Configuration Register 2 */ -#define MX25R6435F_CR2_LH_SWITCH ((uint8_t)0x02) /*!< Low power / high performance switch */ - -/* Security Register */ -#define MX25R6435F_SECR_SOI ((uint8_t)0x01) /*!< Secured OTP indicator */ -#define MX25R6435F_SECR_LDSO ((uint8_t)0x02) /*!< Lock-down secured OTP */ -#define MX25R6435F_SECR_PSB ((uint8_t)0x04) /*!< Program suspend bit */ -#define MX25R6435F_SECR_ESB ((uint8_t)0x08) /*!< Erase suspend bit */ -#define MX25R6435F_SECR_P_FAIL ((uint8_t)0x20) /*!< Program fail flag */ -#define MX25R6435F_SECR_E_FAIL ((uint8_t)0x40) /*!< Erase fail flag */ - -/** - * @} - */ - -/** @defgroup MX25R6435F_Exported_Functions - * @{ - */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __MX25R6435F_H */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/** + ****************************************************************************** + * @file mx25r6435f.h + * @brief This file contains all the description of the MX25R6435F QSPI memory. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MX25R6435F_H +#define __MX25R6435F_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ + +/** + * @brief MX25R6435F Configuration + */ +#define MX25R6435F_FLASH_SIZE 0x800000 /* 64 MBits => 8MBytes */ +#define MX25R6435F_BLOCK_SIZE 0x10000 /* 128 blocks of 64KBytes */ +#define MX25R6435F_SUBBLOCK_SIZE 0x8000 /* 256 blocks of 32KBytes */ +#define MX25R6435F_SECTOR_SIZE 0x1000 /* 2048 sectors of 4kBytes */ +#define MX25R6435F_PAGE_SIZE 0x100 /* 32768 pages of 256 bytes */ + +#define MX25R6435F_DUMMY_CYCLES_READ 8 +#define MX25R6435F_DUMMY_CYCLES_READ_DUAL 4 +#define MX25R6435F_DUMMY_CYCLES_READ_QUAD 4 +#define MX25R6435F_DUMMY_CYCLES_2READ 2 +#define MX25R6435F_DUMMY_CYCLES_4READ 4 + +#define MX25R6435F_ALT_BYTES_PE_MODE 0xA5 +#define MX25R6435F_ALT_BYTES_NO_PE_MODE 0xAA + +#define MX25R6435F_CHIP_ERASE_MAX_TIME 240000 +#define MX25R6435F_BLOCK_ERASE_MAX_TIME 3500 +#define MX25R6435F_SUBBLOCK_ERASE_MAX_TIME 3000 +#define MX25R6435F_SECTOR_ERASE_MAX_TIME 240 + +/** + * @brief MX25R6435F Commands + */ +/* Read Operations */ +#define READ_CMD 0x03 +#define FAST_READ_CMD 0x0B +#define DUAL_OUT_READ_CMD 0x3B +#define DUAL_INOUT_READ_CMD 0xBB +#define QUAD_OUT_READ_CMD 0x6B +#define QUAD_INOUT_READ_CMD 0xEB + +/* Program Operations */ +#define PAGE_PROG_CMD 0x02 +#define QUAD_PAGE_PROG_CMD 0x38 + +/* Erase Operations */ +#define SECTOR_ERASE_CMD 0x20 +#define SUBBLOCK_ERASE_CMD 0x52 +#define BLOCK_ERASE_CMD 0xD8 +#define CHIP_ERASE_CMD 0x60 +#define CHIP_ERASE_CMD_2 0xC7 + +#define PROG_ERASE_RESUME_CMD 0x7A +#define PROG_ERASE_RESUME_CMD_2 0x30 +#define PROG_ERASE_SUSPEND_CMD 0x75 +#define PROG_ERASE_SUSPEND_CMD_2 0xB0 + +/* Identification Operations */ +#define READ_ID_CMD 0x9F +#define READ_ELECTRONIC_ID_CMD 0xAB +#define READ_ELEC_MANUFACTURER_DEVICE_ID_CMD 0x90 +#define READ_SERIAL_FLASH_DISCO_PARAM_CMD 0x5A + +/* Write Operations */ +#define WRITE_ENABLE_CMD 0x06 +#define WRITE_DISABLE_CMD 0x04 + +/* Register Operations */ +#define READ_STATUS_REG_CMD 0x05 +#define READ_CFG_REG_CMD 0x15 +#define WRITE_STATUS_CFG_REG_CMD 0x01 + +#define READ_SEC_REG_CMD 0x2B +#define WRITE_SEC_REG_CMD 0x2F + +/* Power Down Operations */ +#define DEEP_POWER_DOWN_CMD 0xB9 + +/* Burst Operations */ +#define SET_BURST_LENGTH_CMD 0xC0 + +/* One-Time Programmable Operations */ +#define ENTER_SECURED_OTP_CMD 0xB1 +#define EXIT_SECURED_OTP_CMD 0xC1 + +/* No Operation */ +#define NO_OPERATION_CMD 0x00 + +/* Reset Operations */ +#define RESET_ENABLE_CMD 0x66 +#define RESET_MEMORY_CMD 0x99 +#define RELEASE_READ_ENHANCED_CMD 0xFF + +/** + * @brief MX25R6435F Registers + */ +/* Status Register */ +#define MX25R6435F_SR_WIP ((uint8_t)0x01) /*!< Write in progress */ +#define MX25R6435F_SR_WEL ((uint8_t)0x02) /*!< Write enable latch */ +#define MX25R6435F_SR_BP ((uint8_t)0x3C) /*!< Block protect */ +#define MX25R6435F_SR_QE ((uint8_t)0x40) /*!< Quad enable */ +#define MX25R6435F_SR_SRWD ((uint8_t)0x80) /*!< Status register write disable */ + +/* Configuration Register 1 */ +#define MX25R6435F_CR1_TB ((uint8_t)0x08) /*!< Top / bottom */ + +/* Configuration Register 2 */ +#define MX25R6435F_CR2_LH_SWITCH ((uint8_t)0x02) /*!< Low power / high performance switch */ + +/* Security Register */ +#define MX25R6435F_SECR_SOI ((uint8_t)0x01) /*!< Secured OTP indicator */ +#define MX25R6435F_SECR_LDSO ((uint8_t)0x02) /*!< Lock-down secured OTP */ +#define MX25R6435F_SECR_PSB ((uint8_t)0x04) /*!< Program suspend bit */ +#define MX25R6435F_SECR_ESB ((uint8_t)0x08) /*!< Erase suspend bit */ +#define MX25R6435F_SECR_P_FAIL ((uint8_t)0x20) /*!< Program fail flag */ +#define MX25R6435F_SECR_E_FAIL ((uint8_t)0x40) /*!< Erase fail flag */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MX25R6435F_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/mx25r6435f_driver.c b/src/mx25r6435f_driver.c index e083e6a..0398342 100644 --- a/src/mx25r6435f_driver.c +++ b/src/mx25r6435f_driver.c @@ -1,1170 +1,1462 @@ -/** - ****************************************************************************** - * @file mx25r6435f_driver.c - * @author MCD Application Team - * @version V1.1.0 - * @date 21-April-2017 - * @brief This file includes a standard driver for the MX25R6435F QSPI - * memory. - @verbatim - ============================================================================== - ##### How to use this driver ##### - ============================================================================== - [..] - (#) This driver is used to drive the MX25R6435F QSPI external - memory mounted on STM32L475E IOT01 board. - - (#) This driver need a specific component driver (MX25R6435F) to be included with. - - (#) Initialization steps: - (++) Initialize the QPSI external memory using the BSP_QSPI_Init() function. This - function includes the MSP layer hardware resources initialization and the - QSPI interface with the external memory. The BSP_QSPI_DeInit() can be used - to deactivate the QSPI interface. - - (#) QSPI memory operations - (++) QSPI memory can be accessed with read/write operations once it is - initialized. - Read/write operation can be performed with AHB access using the functions - BSP_QSPI_Read()/BSP_QSPI_Write(). - (++) The function to the QSPI memory in memory-mapped mode is possible after - the call of the function BSP_QSPI_EnableMemoryMappedMode(). - (++) The function BSP_QSPI_GetInfo() returns the configuration of the QSPI memory. - (see the QSPI memory data sheet) - (++) Perform erase block operation using the function BSP_QSPI_Erase_Block() and by - specifying the block address. You can perform an erase operation of the whole - chip by calling the function BSP_QSPI_Erase_Chip(). - (++) The function BSP_QSPI_GetStatus() returns the current status of the QSPI memory. - (see the QSPI memory data sheet) - (++) Perform erase sector operation using the function BSP_QSPI_Erase_Sector() - which is not blocking. So the function BSP_QSPI_GetStatus() should be used - to check if the memory is busy, and the functions BSP_QSPI_SuspendErase()/ - BSP_QSPI_ResumeErase() can be used to perform other operations during the - sector erase. - (++) Deep power down of the QSPI memory is managed with the call of the functions - BSP_QSPI_EnterDeepPowerDown()/BSP_QSPI_LeaveDeepPowerDown() - @endverbatim - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2017 STMicroelectronics

- * - * 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 STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * 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. - * - ****************************************************************************** - */ - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "mx25r6435f_driver.h" -#include "PeripheralPins.h" - -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup STM32L475E_IOT01 - * @{ - */ - -/** @defgroup STM32L475E_IOT01_QSPI QSPI - * @{ - */ - -/* Private constants --------------------------------------------------------*/ -/** @defgroup STM32L475E_IOT01_QSPI_Private_Constants QSPI Private Constants - * @{ - */ -#define QSPI_QUAD_DISABLE 0x0 -#define QSPI_QUAD_ENABLE 0x1 - -#define QSPI_HIGH_PERF_DISABLE 0x0 -#define QSPI_HIGH_PERF_ENABLE 0x1 -/** - * @} - */ -/* Private variables ---------------------------------------------------------*/ - -/** @defgroup STM32L475E_IOT01_QSPI_Private_Variables QSPI Private Variables - * @{ - */ -QSPI_HandleTypeDef QSPIHandle; - -/** - * @} - */ - - -/* Private functions ---------------------------------------------------------*/ - -/** @defgroup STM32L475E_IOT01_QSPI_Private_Functions QSPI Private Functions - * @{ - */ -static uint8_t QSPI_ResetMemory (QSPI_HandleTypeDef *hqspi); -static uint8_t QSPI_WriteEnable (QSPI_HandleTypeDef *hqspi); -static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout); -static uint8_t QSPI_QuadMode (QSPI_HandleTypeDef *hqspi, uint8_t Operation); -static uint8_t QSPI_HighPerfMode (QSPI_HandleTypeDef *hqspi, uint8_t Operation); -static uint8_t qspi_setClockPrescaler (void); - -/** - * @} - */ - -/* Exported functions ---------------------------------------------------------*/ - -/** @addtogroup STM32L475E_IOT01_QSPI_Exported_Functions - * @{ - */ - -/** - * @brief Select a prescaler to have a clock frequency lower than the maximum. - * The MX25R6435F supports a maximum frequency of 80MHz. - * QSPI clock is connected to AHB bus clock. - * @retval Clock prescaler. 0 means error. - */ -static uint8_t qspi_setClockPrescaler(void) { - uint8_t i; - - for(i = 1; i < 255; i++) { - if((HAL_RCC_GetHCLKFreq() / i) <= 80000000) - return i; - } - - return 0; -} - -/** - * @brief Initializes the QSPI interface. - * @retval QSPI memory status - */ -uint8_t BSP_QSPI_Init(void) -{ - QSPIHandle.Instance = QUADSPI; - - /* Call the DeInit function to reset the driver */ - if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK) - { - return QSPI_ERROR; - } - - /* System level initialization */ - BSP_QSPI_MspInit(); - - /* QSPI initialization */ - /* High performance mode clock is limited to 80 MHz */ - QSPIHandle.Init.ClockPrescaler = qspi_setClockPrescaler() + 1; /* QSPI clock = systemCoreClock / (ClockPrescaler+1) */ - QSPIHandle.Init.FifoThreshold = 4; - QSPIHandle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE; - QSPIHandle.Init.FlashSize = POSITION_VAL(MX25R6435F_FLASH_SIZE) - 1; - QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE; - QSPIHandle.Init.ClockMode = QSPI_CLOCK_MODE_0; - - if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK) - { - return QSPI_ERROR; - } - - /* QSPI memory reset */ - if (QSPI_ResetMemory(&QSPIHandle) != QSPI_OK) - { - return QSPI_NOT_SUPPORTED; - } - - /* QSPI quad enable */ - if (QSPI_QuadMode(&QSPIHandle, QSPI_QUAD_ENABLE) != QSPI_OK) - { - return QSPI_ERROR; - } - - /* High performance mode enable */ - if (QSPI_HighPerfMode(&QSPIHandle, QSPI_HIGH_PERF_ENABLE) != QSPI_OK) - { - return QSPI_ERROR; - } - - /* Re-configure the clock for the high performance mode */ - /* High performance mode clock is limited to 80 MHz */ - QSPIHandle.Init.ClockPrescaler = qspi_setClockPrescaler(); /* QSPI clock = systemCoreClock / (ClockPrescaler+1) */ - - if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK) - { - return QSPI_ERROR; - } - - return QSPI_OK; -} - -/** - * @brief De-Initializes the QSPI interface. - * @retval QSPI memory status - */ -uint8_t BSP_QSPI_DeInit(void) -{ - QSPIHandle.Instance = QUADSPI; - - /* Call the DeInit function to reset the driver */ - if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK) - { - return QSPI_ERROR; - } - - /* System level De-initialization */ - BSP_QSPI_MspDeInit(); - - return QSPI_OK; -} - -/** - * @brief Reads an amount of data from the QSPI memory. - * @param pData : Pointer to data to be read - * @param ReadAddr : Read start address - * @param Size : Size of data to read - * @retval QSPI memory status - */ -uint8_t BSP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size) -{ - QSPI_CommandTypeDef sCommand; - - /* Initialize the read command */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = QUAD_INOUT_READ_CMD; - sCommand.AddressMode = QSPI_ADDRESS_4_LINES; - sCommand.AddressSize = QSPI_ADDRESS_24_BITS; - sCommand.Address = ReadAddr; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; - sCommand.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; - sCommand.AlternateBytes = MX25R6435F_ALT_BYTES_NO_PE_MODE; - sCommand.DataMode = QSPI_DATA_4_LINES; - sCommand.DummyCycles = MX25R6435F_DUMMY_CYCLES_READ_QUAD; - sCommand.NbData = Size; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - /* Configure the command */ - if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Reception of the data */ - if (HAL_QSPI_Receive(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - return QSPI_OK; -} - -/** - * @brief Writes an amount of data to the QSPI memory. - * @param pData : Pointer to data to be written - * @param WriteAddr : Write start address - * @param Size : Size of data to write - * @retval QSPI memory status - */ -uint8_t BSP_QSPI_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size) -{ - QSPI_CommandTypeDef sCommand; - uint32_t end_addr, current_size, current_addr; - - /* Calculation of the size between the write address and the end of the page */ - current_size = MX25R6435F_PAGE_SIZE - (WriteAddr % MX25R6435F_PAGE_SIZE); - - /* Check if the size of the data is less than the remaining place in the page */ - if (current_size > Size) - { - current_size = Size; - } - - /* Initialize the adress variables */ - current_addr = WriteAddr; - end_addr = WriteAddr + Size; - - /* Initialize the program command */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = QUAD_PAGE_PROG_CMD; - sCommand.AddressMode = QSPI_ADDRESS_4_LINES; - sCommand.AddressSize = QSPI_ADDRESS_24_BITS; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_4_LINES; - sCommand.DummyCycles = 0; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - /* Perform the write page by page */ - do - { - sCommand.Address = current_addr; - sCommand.NbData = current_size; - - /* Enable write operations */ - if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) - { - return QSPI_ERROR; - } - - /* Configure the command */ - if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Transmission of the data */ - if (HAL_QSPI_Transmit(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Configure automatic polling mode to wait for end of program */ - if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) - { - return QSPI_ERROR; - } - - /* Update the address and size variables for next page programming */ - current_addr += current_size; - pData += current_size; - current_size = ((current_addr + MX25R6435F_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : MX25R6435F_PAGE_SIZE; - } while (current_addr < end_addr); - - return QSPI_OK; -} - -/** - * @brief Erases the specified block of the QSPI memory. - * @param BlockAddress : Block address to erase - * @retval QSPI memory status - */ -uint8_t BSP_QSPI_Erase_Block(uint32_t BlockAddress) -{ - QSPI_CommandTypeDef sCommand; - - /* Initialize the erase command */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = BLOCK_ERASE_CMD; - sCommand.AddressMode = QSPI_ADDRESS_1_LINE; - sCommand.AddressSize = QSPI_ADDRESS_24_BITS; - sCommand.Address = BlockAddress; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_NONE; - sCommand.DummyCycles = 0; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - /* Enable write operations */ - if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) - { - return QSPI_ERROR; - } - - /* Send the command */ - if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Configure automatic polling mode to wait for end of erase */ - if (QSPI_AutoPollingMemReady(&QSPIHandle, MX25R6435F_BLOCK_ERASE_MAX_TIME) != QSPI_OK) - { - return QSPI_ERROR; - } - - return QSPI_OK; -} - -/** - * @brief Erases the specified sector of the QSPI memory. - * @param Sector : Sector address to erase (0 to 255) - * @retval QSPI memory status - * @note This function is non blocking meaning that sector erase - * operation is started but not completed when the function - * returns. Application has to call BSP_QSPI_GetStatus() - * to know when the device is available again (i.e. erase operation - * completed). - */ -uint8_t BSP_QSPI_Erase_Sector(uint32_t Sector) -{ - QSPI_CommandTypeDef sCommand; - - if (Sector >= (uint32_t)(MX25R6435F_FLASH_SIZE/MX25R6435F_SECTOR_SIZE)) - { - return QSPI_ERROR; - } - - /* Initialize the erase command */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = SECTOR_ERASE_CMD; - sCommand.AddressMode = QSPI_ADDRESS_1_LINE; - sCommand.AddressSize = QSPI_ADDRESS_24_BITS; - sCommand.Address = (Sector * MX25R6435F_SECTOR_SIZE); - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_NONE; - sCommand.DummyCycles = 0; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - /* Enable write operations */ - if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) - { - return QSPI_ERROR; - } - - /* Send the command */ - if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - return QSPI_OK; -} - -/** - * @brief Erases the entire QSPI memory. - * @retval QSPI memory status - */ -uint8_t BSP_QSPI_Erase_Chip(void) -{ - QSPI_CommandTypeDef sCommand; - - /* Initialize the erase command */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = CHIP_ERASE_CMD; - sCommand.AddressMode = QSPI_ADDRESS_NONE; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_NONE; - sCommand.DummyCycles = 0; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - /* Enable write operations */ - if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) - { - return QSPI_ERROR; - } - - /* Send the command */ - if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Configure automatic polling mode to wait for end of erase */ - if (QSPI_AutoPollingMemReady(&QSPIHandle, MX25R6435F_CHIP_ERASE_MAX_TIME) != QSPI_OK) - { - return QSPI_ERROR; - } - - return QSPI_OK; -} - -/** - * @brief Reads current status of the QSPI memory. - * @retval QSPI memory status - */ -uint8_t BSP_QSPI_GetStatus(void) -{ - QSPI_CommandTypeDef sCommand; - uint8_t reg; - - /* Initialize the read security register command */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = READ_SEC_REG_CMD; - sCommand.AddressMode = QSPI_ADDRESS_NONE; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_1_LINE; - sCommand.DummyCycles = 0; - sCommand.NbData = 1; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - /* Configure the command */ - if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Reception of the data */ - if (HAL_QSPI_Receive(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Check the value of the register */ - if ((reg & (MX25R6435F_SECR_P_FAIL | MX25R6435F_SECR_E_FAIL)) != 0) - { - return QSPI_ERROR; - } - else if ((reg & (MX25R6435F_SECR_PSB | MX25R6435F_SECR_ESB)) != 0) - { - return QSPI_SUSPENDED; - } - - /* Initialize the read status register command */ - sCommand.Instruction = READ_STATUS_REG_CMD; - - /* Configure the command */ - if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Reception of the data */ - if (HAL_QSPI_Receive(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Check the value of the register */ - if ((reg & MX25R6435F_SR_WIP) != 0) - { - return QSPI_BUSY; - } - else - { - return QSPI_OK; - } -} - -/** - * @brief Return the configuration of the QSPI memory. - * @param pInfo : pointer on the configuration structure - * @retval QSPI memory status - */ -uint8_t BSP_QSPI_GetInfo(QSPI_Info* pInfo) -{ - /* Configure the structure with the memory configuration */ - pInfo->FlashSize = MX25R6435F_FLASH_SIZE; - pInfo->EraseSectorSize = MX25R6435F_SECTOR_SIZE; - pInfo->EraseSectorsNumber = (MX25R6435F_FLASH_SIZE/MX25R6435F_SECTOR_SIZE); - pInfo->ProgPageSize = MX25R6435F_PAGE_SIZE; - pInfo->ProgPagesNumber = (MX25R6435F_FLASH_SIZE/MX25R6435F_PAGE_SIZE); - - return QSPI_OK; -} - -/** - * @brief Configure the QSPI in memory-mapped mode - * @retval QSPI memory status - */ -uint8_t BSP_QSPI_EnableMemoryMappedMode(void) -{ - QSPI_CommandTypeDef sCommand; - QSPI_MemoryMappedTypeDef sMemMappedCfg; - - /* Configure the command for the read instruction */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = QUAD_INOUT_READ_CMD; - sCommand.AddressMode = QSPI_ADDRESS_4_LINES; - sCommand.AddressSize = QSPI_ADDRESS_24_BITS; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; - sCommand.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; - sCommand.AlternateBytes = MX25R6435F_ALT_BYTES_NO_PE_MODE; - sCommand.DataMode = QSPI_DATA_4_LINES; - sCommand.DummyCycles = MX25R6435F_DUMMY_CYCLES_READ_QUAD; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - /* Configure the memory mapped mode */ - sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE; - - if (HAL_QSPI_MemoryMapped(&QSPIHandle, &sCommand, &sMemMappedCfg) != HAL_OK) - { - return QSPI_ERROR; - } - - return QSPI_OK; -} - -/** - * @brief This function suspends an ongoing erase command. - * @retval QSPI memory status - */ -uint8_t BSP_QSPI_SuspendErase(void) -{ - QSPI_CommandTypeDef sCommand; - - /* Check whether the device is busy (erase operation is - in progress). - */ - if (BSP_QSPI_GetStatus() == QSPI_BUSY) - { - /* Initialize the erase command */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = PROG_ERASE_SUSPEND_CMD; - sCommand.AddressMode = QSPI_ADDRESS_NONE; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_NONE; - sCommand.DummyCycles = 0; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - /* Send the command */ - if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - if (BSP_QSPI_GetStatus() == QSPI_SUSPENDED) - { - return QSPI_OK; - } - - return QSPI_ERROR; - } - - return QSPI_OK; -} - -/** - * @brief This function resumes a paused erase command. - * @retval QSPI memory status - */ -uint8_t BSP_QSPI_ResumeErase(void) -{ - QSPI_CommandTypeDef sCommand; - - /* Check whether the device is in suspended state */ - if (BSP_QSPI_GetStatus() == QSPI_SUSPENDED) - { - /* Initialize the erase command */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = PROG_ERASE_RESUME_CMD; - sCommand.AddressMode = QSPI_ADDRESS_NONE; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_NONE; - sCommand.DummyCycles = 0; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - /* Send the command */ - if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* - When this command is executed, the status register write in progress bit is set to 1, and - the flag status register program erase controller bit is set to 0. This command is ignored - if the device is not in a suspended state. - */ - - if (BSP_QSPI_GetStatus() == QSPI_BUSY) - { - return QSPI_OK; - } - - return QSPI_ERROR; - } - - return QSPI_OK; -} - -/** - * @brief This function enter the QSPI memory in deep power down mode. - * @retval QSPI memory status - */ -uint8_t BSP_QSPI_EnterDeepPowerDown(void) -{ - QSPI_CommandTypeDef sCommand; - - /* Initialize the deep power down command */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = DEEP_POWER_DOWN_CMD; - sCommand.AddressMode = QSPI_ADDRESS_NONE; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_NONE; - sCommand.DummyCycles = 0; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - /* Send the command */ - if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* --- Memory takes 10us max to enter deep power down --- */ - /* --- At least 30us should be respected before leaving deep power down --- */ - - return QSPI_OK; -} - -/** - * @brief This function leave the QSPI memory from deep power down mode. - * @retval QSPI memory status - */ -uint8_t BSP_QSPI_LeaveDeepPowerDown(void) -{ - QSPI_CommandTypeDef sCommand; - - /* Initialize the erase command */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = NO_OPERATION_CMD; - sCommand.AddressMode = QSPI_ADDRESS_NONE; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_NONE; - sCommand.DummyCycles = 0; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - /* Send the command */ - if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* --- A NOP command is sent to the memory, as the nCS should be low for at least 20 ns --- */ - /* --- Memory takes 35us min to leave deep power down --- */ - - return QSPI_OK; -} - -/** - * @brief Initializes the QSPI MSP. - * @retval None - */ -__weak void BSP_QSPI_MspInit(void) -{ - GPIO_InitTypeDef GPIO_InitStruct; - GPIO_TypeDef *port; - uint8_t idx = 0; - PinName pin; - - /* Enable the QuadSPI memory interface clock */ - __HAL_RCC_QSPI_CLK_ENABLE(); - - /* Reset the QuadSPI memory interface */ - __HAL_RCC_QSPI_FORCE_RESET(); - __HAL_RCC_QSPI_RELEASE_RESET(); - - /* QSPI CLK, CS, D0, D1, D2 and D3 GPIO pins configuration */ - pin = PinMap_QUADSPI[idx].pin; - while(pin != NC) - { - /* Enable GPIO clocks */ - port = set_GPIO_Port_Clock(STM_PORT(pin)); - - /* Pin configuration */ - GPIO_InitStruct.Pin = STM_GPIO_PIN(pin); - GPIO_InitStruct.Mode = STM_PIN_MODE(pinmap_function(pin, PinMap_QUADSPI)); - GPIO_InitStruct.Pull = STM_PIN_PUPD(pinmap_function(pin, PinMap_QUADSPI)); - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.Alternate = STM_PIN_AFNUM(pinmap_function(pin, PinMap_QUADSPI)); - HAL_GPIO_Init(port, &GPIO_InitStruct); - - pin = PinMap_QUADSPI[idx++].pin; - } -} - -/** - * @brief De-Initializes the QSPI MSP. - * @retval None - */ -__weak void BSP_QSPI_MspDeInit(void) -{ - GPIO_InitTypeDef GPIO_InitStruct; - GPIO_TypeDef *port; - uint8_t idx = 0; - PinName pin; - - /* QSPI CLK, CS, D0-D3 GPIO pins de-configuration */ - pin = PinMap_QUADSPI[idx].pin; - while(pin != NC) - { - port = get_GPIO_Port(STM_PORT(pin)); - GPIO_InitStruct.Pin = STM_GPIO_PIN(pin); - HAL_GPIO_DeInit(port, GPIO_InitStruct.Pin); - - pin = PinMap_QUADSPI[idx++].pin; - } - - /* Reset the QuadSPI memory interface */ - __HAL_RCC_QSPI_FORCE_RESET(); - __HAL_RCC_QSPI_RELEASE_RESET(); - - /* Disable the QuadSPI memory interface clock */ - __HAL_RCC_QSPI_CLK_DISABLE(); -} - -/** - * @} - */ - -/** @addtogroup STM32L475E_IOT01_QSPI_Private_Functions - * @{ - */ - -/** - * @brief This function reset the QSPI memory. - * @param hqspi : QSPI handle - * @retval None - */ -static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi) -{ - QSPI_CommandTypeDef sCommand; - - /* Initialize the reset enable command */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = RESET_ENABLE_CMD; - sCommand.AddressMode = QSPI_ADDRESS_NONE; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_NONE; - sCommand.DummyCycles = 0; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - /* Send the command */ - if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Send the reset memory command */ - sCommand.Instruction = RESET_MEMORY_CMD; - if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Configure automatic polling mode to wait the memory is ready */ - if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) - { - return QSPI_ERROR; - } - - return QSPI_OK; -} - -/** - * @brief This function send a Write Enable and wait it is effective. - * @param hqspi : QSPI handle - * @retval None - */ -static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi) -{ - QSPI_CommandTypeDef sCommand; - QSPI_AutoPollingTypeDef sConfig; - - /* Enable write operations */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = WRITE_ENABLE_CMD; - sCommand.AddressMode = QSPI_ADDRESS_NONE; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_NONE; - sCommand.DummyCycles = 0; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Configure automatic polling mode to wait for write enabling */ - sConfig.Match = MX25R6435F_SR_WEL; - sConfig.Mask = MX25R6435F_SR_WEL; - sConfig.MatchMode = QSPI_MATCH_MODE_AND; - sConfig.StatusBytesSize = 1; - sConfig.Interval = 0x10; - sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; - - sCommand.Instruction = READ_STATUS_REG_CMD; - sCommand.DataMode = QSPI_DATA_1_LINE; - - if (HAL_QSPI_AutoPolling(hqspi, &sCommand, &sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - return QSPI_OK; -} - -/** - * @brief This function read the SR of the memory and wait the EOP. - * @param hqspi : QSPI handle - * @param Timeout : Timeout for auto-polling - * @retval None - */ -static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout) -{ - QSPI_CommandTypeDef sCommand; - QSPI_AutoPollingTypeDef sConfig; - - /* Configure automatic polling mode to wait for memory ready */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = READ_STATUS_REG_CMD; - sCommand.AddressMode = QSPI_ADDRESS_NONE; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_1_LINE; - sCommand.DummyCycles = 0; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - sConfig.Match = 0; - sConfig.Mask = MX25R6435F_SR_WIP; - sConfig.MatchMode = QSPI_MATCH_MODE_AND; - sConfig.StatusBytesSize = 1; - sConfig.Interval = 0x10; - sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; - - if (HAL_QSPI_AutoPolling(hqspi, &sCommand, &sConfig, Timeout) != HAL_OK) - { - return QSPI_ERROR; - } - - return QSPI_OK; -} - -/** - * @brief This function enables/disables the Quad mode of the memory. - * @param hqspi : QSPI handle - * @param Operation : QSPI_QUAD_ENABLE or QSPI_QUAD_DISABLE mode - * @retval None - */ -static uint8_t QSPI_QuadMode(QSPI_HandleTypeDef *hqspi, uint8_t Operation) -{ - QSPI_CommandTypeDef sCommand; - uint8_t reg; - - /* Read status register */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = READ_STATUS_REG_CMD; - sCommand.AddressMode = QSPI_ADDRESS_NONE; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_1_LINE; - sCommand.DummyCycles = 0; - sCommand.NbData = 1; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - if (HAL_QSPI_Receive(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Enable write operations */ - if (QSPI_WriteEnable(hqspi) != QSPI_OK) - { - return QSPI_ERROR; - } - - /* Activate/deactivate the Quad mode */ - if (Operation == QSPI_QUAD_ENABLE) - { - SET_BIT(reg, MX25R6435F_SR_QE); - } - else - { - CLEAR_BIT(reg, MX25R6435F_SR_QE); - } - - sCommand.Instruction = WRITE_STATUS_CFG_REG_CMD; - - if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - if (HAL_QSPI_Transmit(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Wait that memory is ready */ - if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) - { - return QSPI_ERROR; - } - - /* Check the configuration has been correctly done */ - sCommand.Instruction = READ_STATUS_REG_CMD; - - if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - if (HAL_QSPI_Receive(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - if ((((reg & MX25R6435F_SR_QE) == 0) && (Operation == QSPI_QUAD_ENABLE)) || - (((reg & MX25R6435F_SR_QE) != 0) && (Operation == QSPI_QUAD_DISABLE))) - { - return QSPI_ERROR; - } - - return QSPI_OK; -} - -/** - * @brief This function enables/disables the high performance mode of the memory. - * @param hqspi : QSPI handle - * @param Operation : QSPI_HIGH_PERF_ENABLE or QSPI_HIGH_PERF_DISABLE high performance mode - * @retval None - */ -static uint8_t QSPI_HighPerfMode(QSPI_HandleTypeDef *hqspi, uint8_t Operation) -{ - QSPI_CommandTypeDef sCommand; - uint8_t reg[3]; - - /* Read status register */ - sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; - sCommand.Instruction = READ_STATUS_REG_CMD; - sCommand.AddressMode = QSPI_ADDRESS_NONE; - sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - sCommand.DataMode = QSPI_DATA_1_LINE; - sCommand.DummyCycles = 0; - sCommand.NbData = 1; - sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; - sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; - sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; - - if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - if (HAL_QSPI_Receive(hqspi, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Read configuration registers */ - sCommand.Instruction = READ_CFG_REG_CMD; - sCommand.NbData = 2; - - if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - if (HAL_QSPI_Receive(hqspi, &(reg[1]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Enable write operations */ - if (QSPI_WriteEnable(hqspi) != QSPI_OK) - { - return QSPI_ERROR; - } - - /* Activate/deactivate the Quad mode */ - if (Operation == QSPI_HIGH_PERF_ENABLE) - { - SET_BIT(reg[2], MX25R6435F_CR2_LH_SWITCH); - } - else - { - CLEAR_BIT(reg[2], MX25R6435F_CR2_LH_SWITCH); - } - - sCommand.Instruction = WRITE_STATUS_CFG_REG_CMD; - sCommand.NbData = 3; - - if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - if (HAL_QSPI_Transmit(hqspi, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - /* Wait that memory is ready */ - if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) - { - return QSPI_ERROR; - } - - /* Check the configuration has been correctly done */ - sCommand.Instruction = READ_CFG_REG_CMD; - sCommand.NbData = 2; - - if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - if (HAL_QSPI_Receive(hqspi, &(reg[0]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - { - return QSPI_ERROR; - } - - if ((((reg[1] & MX25R6435F_CR2_LH_SWITCH) == 0) && (Operation == QSPI_HIGH_PERF_ENABLE)) || - (((reg[1] & MX25R6435F_CR2_LH_SWITCH) != 0) && (Operation == QSPI_HIGH_PERF_DISABLE))) - { - return QSPI_ERROR; - } - - return QSPI_OK; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/** + ****************************************************************************** + * @file mx25r6435f_driver.c + * @brief This file includes a standard driver for the MX25R6435F QSPI + * memory. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "core_debug.h" +#include "mx25r6435f_driver.h" + +/* Private constants --------------------------------------------------------*/ +#define QSPI_QUAD_DISABLE 0x0 +#define QSPI_QUAD_ENABLE 0x1 + +#define QSPI_HIGH_PERF_DISABLE 0x0 +#define QSPI_HIGH_PERF_ENABLE 0x1 + +/* Private functions ---------------------------------------------------------*/ +static uint8_t QSPI_ResetMemory(XSPI_HandleTypeDef *hxspi); +static uint8_t QSPI_WriteEnable(XSPI_HandleTypeDef *hxspi); +static uint8_t QSPI_AutoPollingMemReady(XSPI_HandleTypeDef *hxspi, uint32_t Timeout); +static uint8_t QSPI_QuadMode(XSPI_HandleTypeDef *hxspi, uint8_t Operation); +static uint8_t QSPI_HighPerfMode(XSPI_HandleTypeDef *hxspi, uint8_t Operation); +static uint8_t qspi_setClockPrescaler(void); + +/* Exported functions ---------------------------------------------------------*/ +/** + * @brief Select a prescaler to have a clock frequency lower than the maximum. + * The MX25R6435F supports a maximum frequency of 80MHz. + * QSPI clock is connected to AHB bus clock. + * @retval Clock prescaler. 0 means error. + */ +static uint8_t qspi_setClockPrescaler(void) +{ + uint8_t i; + + for (i = 1; i < 255; i++) { + if ((HAL_RCC_GetHCLKFreq() / i) <= 80000000) { + return i; + } + } + + return 0; +} + +/** + * @brief Initializes the QSPI interface. + * @param obj : pointer to QSPI_t structure + * @retval QSPI memory status + */ +uint8_t BSP_QSPI_Init(QSPI_t *obj) +{ + if (obj == NULL) { + return QSPI_ERROR; + } + XSPI_HandleTypeDef *handle = &(obj->handle); + + /* Determine the XSPI to use */ + XSPI_TypeDef *xspi_d0 = pinmap_peripheral(obj->pin_d0, PinMap_XSPI_DATA0); + XSPI_TypeDef *xspi_d1 = pinmap_peripheral(obj->pin_d1, PinMap_XSPI_DATA1); + XSPI_TypeDef *xspi_d2 = pinmap_peripheral(obj->pin_d2, PinMap_XSPI_DATA2); + XSPI_TypeDef *xspi_d3 = pinmap_peripheral(obj->pin_d3, PinMap_XSPI_DATA3); + + XSPI_TypeDef *xspi_sclk = pinmap_peripheral(obj->pin_sclk, PinMap_XSPI_SCLK); + XSPI_TypeDef *xspi_ssel = pinmap_peripheral(obj->pin_ssel, PinMap_XSPI_SSEL); + + /* Pins Dx/SSEL/SCLK must not be NP. */ + if (xspi_d0 == NP || xspi_d1 == NP || xspi_d2 == NP || xspi_sclk == NP || xspi_ssel == NP) { + core_debug("ERROR: at least one QSPI pin has no peripheral\n"); + return QSPI_ERROR; + } + + XSPI_TypeDef *spi_d01 = pinmap_merge_peripheral(xspi_d0, xspi_d1); + XSPI_TypeDef *spi_d23 = pinmap_merge_peripheral(xspi_d2, xspi_d3); + XSPI_TypeDef *spi_dx = pinmap_merge_peripheral(spi_d01, spi_d23); + XSPI_TypeDef *spi_sxxx = pinmap_merge_peripheral(xspi_sclk, xspi_ssel); + + obj->qspi = pinmap_merge_peripheral(spi_dx, spi_sxxx); + + /* Are all pins connected to the same SPI instance? */ + if (obj->qspi == NP) { + core_debug("ERROR: QSPI pins mismatch\n"); + return QSPI_ERROR; + } + + handle->Instance = obj->qspi; + + /* Call the DeInit function to reset the driver */ + if (HAL_XSPI_DeInit(handle) != HAL_OK) { + return QSPI_ERROR; + } + + /* System level initialization */ + BSP_QSPI_MspInit(obj); + +#ifdef OCTOSPI + /* OSPI initialization */ + handle->Init.FifoThreshold = 4; + handle->Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE; + handle->Init.MemoryType = HAL_OSPI_MEMTYPE_MACRONIX; + handle->Init.DeviceSize = POSITION_VAL(MX25R6435F_FLASH_SIZE); + handle->Init.ChipSelectHighTime = 1; + handle->Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE; + handle->Init.ClockMode = HAL_OSPI_CLOCK_MODE_0; + handle->Init.ClockPrescaler = 4; /* QSPI clock = 110MHz / ClockPrescaler = 27.5 MHz */ + handle->Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE; + handle->Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE; + handle->Init.ChipSelectBoundary = 0; + handle->Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_USED; +#else /* OCTOSPI */ + /* QSPI initialization */ + /* High performance mode clock is limited to 80 MHz */ + handle->Init.ClockPrescaler = qspi_setClockPrescaler() + 1; /* QSPI clock = systemCoreClock / (ClockPrescaler+1) */ + handle->Init.FifoThreshold = 4; + handle->Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE; + handle->Init.FlashSize = POSITION_VAL(MX25R6435F_FLASH_SIZE) - 1; + handle->Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE; + handle->Init.ClockMode = QSPI_CLOCK_MODE_0; +#endif + + if (HAL_XSPI_Init(handle) != HAL_OK) { + return QSPI_ERROR; + } + + /* QSPI memory reset */ + if (QSPI_ResetMemory(handle) != QSPI_OK) { + return QSPI_NOT_SUPPORTED; + } + + /* QSPI quad enable */ + if (QSPI_QuadMode(handle, QSPI_QUAD_ENABLE) != QSPI_OK) { + return QSPI_ERROR; + } + + /* High performance mode enable */ + if (QSPI_HighPerfMode(handle, QSPI_HIGH_PERF_ENABLE) != QSPI_OK) { + return QSPI_ERROR; + } + + /* Re-configure the clock for the high performance mode */ + /* High performance mode clock is limited to 80 MHz */ + handle->Init.ClockPrescaler = qspi_setClockPrescaler(); /* QSPI clock = systemCoreClock / (ClockPrescaler+1) */ + + if (HAL_XSPI_Init(handle) != HAL_OK) { + return QSPI_ERROR; + } + + if (HAL_XSPI_Init(handle) != HAL_OK) { + return QSPI_ERROR; + } + + return QSPI_OK; +} + +/** + * @brief De-Initializes the QSPI interface. + * @param obj : pointer to QSPI_t structure + * @retval QSPI memory status + */ +uint8_t BSP_QSPI_DeInit(QSPI_t *obj) +{ + XSPI_HandleTypeDef *handle = &(obj->handle); + + /* Call the DeInit function to reset the driver */ + if (HAL_XSPI_DeInit(handle) != HAL_OK) { + return QSPI_ERROR; + } + + /* System level De-initialization */ + BSP_QSPI_MspDeInit(obj); + + return QSPI_OK; +} + +/** + * @brief Reads an amount of data from the QSPI memory. + * @param obj : pointer to QSPI_t structure + * @param pData : Pointer to data to be read + * @param ReadAddr : Read start address + * @param Size : Size of data to read + * @retval QSPI memory status + */ +uint8_t BSP_QSPI_Read(QSPI_t *obj, uint8_t *pData, uint32_t ReadAddr, uint32_t Size) +{ + XSPI_HandleTypeDef *handle = &(obj->handle); +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + + /* Initialize the read command */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = QUAD_INOUT_READ_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.Address = ReadAddr; + sCommand.AddressMode = HAL_OSPI_ADDRESS_4_LINES; + sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; + sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; + sCommand.AlternateBytes = MX25R6435F_ALT_BYTES_NO_PE_MODE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_4_LINES; + sCommand.AlternateBytesSize = HAL_OSPI_ALTERNATE_BYTES_8_BITS; + sCommand.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; + sCommand.DataMode = HAL_OSPI_DATA_4_LINES; + sCommand.NbData = Size; + sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; + sCommand.DummyCycles = MX25R6435F_DUMMY_CYCLES_READ_QUAD; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; + +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + + /* Initialize the read command */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = QUAD_INOUT_READ_CMD; + sCommand.AddressMode = QSPI_ADDRESS_4_LINES; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.Address = ReadAddr; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; + sCommand.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; + sCommand.AlternateBytes = MX25R6435F_ALT_BYTES_NO_PE_MODE; + sCommand.DataMode = QSPI_DATA_4_LINES; + sCommand.DummyCycles = MX25R6435F_DUMMY_CYCLES_READ_QUAD; + sCommand.NbData = Size; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +#endif /* OCTOSPI */ + + /* Configure the command */ + if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Reception of the data */ + if (HAL_XSPI_Receive(handle, pData, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + return QSPI_OK; +} + +/** + * @brief Writes an amount of data to the QSPI memory. + * @param obj : pointer to QSPI_t structure + * @param pData : Pointer to data to be written + * @param WriteAddr : Write start address + * @param Size : Size of data to write + * @retval QSPI memory status + */ +uint8_t BSP_QSPI_Write(QSPI_t *obj, uint8_t *pData, uint32_t WriteAddr, uint32_t Size) +{ + XSPI_HandleTypeDef *handle = &(obj->handle); + uint32_t end_addr, current_size, current_addr; + + /* Calculation of the size between the write address and the end of the page */ + current_size = MX25R6435F_PAGE_SIZE - (WriteAddr % MX25R6435F_PAGE_SIZE); + + /* Check if the size of the data is less than the remaining place in the page */ + if (current_size > Size) { + current_size = Size; + } + + /* Initialize the adress variables */ + current_addr = WriteAddr; + end_addr = WriteAddr + Size; + +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + + /* Initialize the program command */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = QUAD_PAGE_PROG_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.AddressMode = HAL_OSPI_ADDRESS_4_LINES; + sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; + sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_4_LINES; + sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; + sCommand.DummyCycles = 0; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + + /* Initialize the program command */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = QUAD_PAGE_PROG_CMD; + sCommand.AddressMode = QSPI_ADDRESS_4_LINES; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_4_LINES; + sCommand.DummyCycles = 0; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +#endif /* OCTOSPI */ + + /* Perform the write page by page */ + do { + sCommand.Address = current_addr; + sCommand.NbData = current_size; + + /* Enable write operations */ + if (QSPI_WriteEnable(handle) != QSPI_OK) { + return QSPI_ERROR; + } + + /* Configure the command */ + if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Transmission of the data */ + if (HAL_XSPI_Transmit(handle, pData, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Configure automatic polling mode to wait for end of program */ + if (QSPI_AutoPollingMemReady(handle, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) { + return QSPI_ERROR; + } + + /* Update the address and size variables for next page programming */ + current_addr += current_size; + pData += current_size; + current_size = ((current_addr + MX25R6435F_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : MX25R6435F_PAGE_SIZE; + } while (current_addr < end_addr); + + return QSPI_OK; +} + +/** + * @brief Erases the specified block of the QSPI memory. + * @param obj : pointer to QSPI_t structure + * @param BlockAddress : Block address to erase + * @retval QSPI memory status + */ +uint8_t BSP_QSPI_Erase_Block(QSPI_t *obj, uint32_t BlockAddress) +{ + XSPI_HandleTypeDef *handle = &(obj->handle); +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + + /* Initialize the erase command */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = BLOCK_ERASE_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.Address = BlockAddress; + sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE; + sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; + sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + + /* Initialize the erase command */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = BLOCK_ERASE_CMD; + sCommand.AddressMode = QSPI_ADDRESS_1_LINE; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.Address = BlockAddress; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +#endif /* OCTOSPI */ + + /* Enable write operations */ + if (QSPI_WriteEnable(handle) != QSPI_OK) { + return QSPI_ERROR; + } + + /* Send the command */ + if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Configure automatic polling mode to wait for end of erase */ + if (QSPI_AutoPollingMemReady(handle, MX25R6435F_BLOCK_ERASE_MAX_TIME) != QSPI_OK) { + return QSPI_ERROR; + } + return QSPI_OK; +} + +/** + * @brief Erases the specified sector of the QSPI memory. + * @param obj : pointer to QSPI_t structure + * @param Sector : Sector address to erase (0 to 255) + * @retval QSPI memory status + * @note This function is non blocking meaning that sector erase + * operation is started but not completed when the function + * returns. Application has to call BSP_QSPI_GetStatus() + * to know when the device is available again (i.e. erase operation + * completed). + */ +uint8_t BSP_QSPI_Erase_Sector(QSPI_t *obj, uint32_t Sector) +{ + XSPI_HandleTypeDef *handle = &(obj->handle); + + if (Sector >= (uint32_t)(MX25R6435F_FLASH_SIZE / MX25R6435F_SECTOR_SIZE)) { + return QSPI_ERROR; + } + +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + + /* Initialize the erase command */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = SECTOR_ERASE_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.Address = (Sector * MX25R6435F_SECTOR_SIZE); + sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE; + sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; + sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + + /* Initialize the erase command */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = SECTOR_ERASE_CMD; + sCommand.AddressMode = QSPI_ADDRESS_1_LINE; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.Address = (Sector * MX25R6435F_SECTOR_SIZE); + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +#endif /* OCTOSPI */ + + /* Enable write operations */ + if (QSPI_WriteEnable(handle) != QSPI_OK) { + return QSPI_ERROR; + } + + /* Send the command */ + if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + return QSPI_OK; +} + +/** + * @brief Erases the entire QSPI memory. + * @param obj : pointer to QSPI_t structure + * @retval QSPI memory status + */ +uint8_t BSP_QSPI_Erase_Chip(QSPI_t *obj) +{ + XSPI_HandleTypeDef *handle = &(obj->handle); + +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + + /* Initialize the erase command */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = CHIP_ERASE_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + + /* Initialize the erase command */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = CHIP_ERASE_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +#endif /* OCTOSPI */ + + /* Enable write operations */ + if (QSPI_WriteEnable(handle) != QSPI_OK) { + return QSPI_ERROR; + } + + /* Send the command */ + if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Configure automatic polling mode to wait for end of erase */ + if (QSPI_AutoPollingMemReady(handle, MX25R6435F_CHIP_ERASE_MAX_TIME) != QSPI_OK) { + return QSPI_ERROR; + } + + return QSPI_OK; +} + +/** + * @brief Reads current status of the QSPI memory. + * @param obj : pointer to QSPI_t structure + * @retval QSPI memory status + */ +uint8_t BSP_QSPI_GetStatus(QSPI_t *obj) +{ + XSPI_HandleTypeDef *handle = &(obj->handle); + uint8_t reg; +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + + /* Initialize the read security register command */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = READ_SEC_REG_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_1_LINE; + sCommand.NbData = 1; + sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; + sCommand.DummyCycles = 0; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + + /* Initialize the read security register command */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = READ_SEC_REG_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_1_LINE; + sCommand.DummyCycles = 0; + sCommand.NbData = 1; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +#endif /* OCTOSPI */ + + /* Configure the command */ + if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Reception of the data */ + if (HAL_XSPI_Receive(handle, ®, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Check the value of the register */ + if ((reg & (MX25R6435F_SECR_P_FAIL | MX25R6435F_SECR_E_FAIL)) != 0) { + return QSPI_ERROR; + } else if ((reg & (MX25R6435F_SECR_PSB | MX25R6435F_SECR_ESB)) != 0) { + return QSPI_SUSPENDED; + } + + /* Initialize the read status register command */ + sCommand.Instruction = READ_STATUS_REG_CMD; + + /* Configure the command */ + if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Reception of the data */ + if (HAL_XSPI_Receive(handle, ®, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Check the value of the register */ + if ((reg & MX25R6435F_SR_WIP) != 0) { + return QSPI_BUSY; + } else { + return QSPI_OK; + } +} + +/** + * @brief Return the configuration of the QSPI memory. + * @param pInfo : pointer on the configuration structure + * @retval QSPI memory status + */ +uint8_t BSP_QSPI_GetInfo(QSPI_Info *pInfo) +{ + /* Configure the structure with the memory configuration */ + pInfo->FlashSize = MX25R6435F_FLASH_SIZE; + pInfo->EraseSectorSize = MX25R6435F_SECTOR_SIZE; + pInfo->EraseSectorsNumber = (MX25R6435F_FLASH_SIZE / MX25R6435F_SECTOR_SIZE); + pInfo->ProgPageSize = MX25R6435F_PAGE_SIZE; + pInfo->ProgPagesNumber = (MX25R6435F_FLASH_SIZE / MX25R6435F_PAGE_SIZE); + + return QSPI_OK; +} + +/** + * @brief Configure the QSPI in memory-mapped mode + * @param obj : pointer to QSPI_t structure + * @retval QSPI memory status + */ +uint8_t BSP_QSPI_EnableMemoryMappedMode(QSPI_t *obj) +{ + XSPI_HandleTypeDef *handle = &(obj->handle); + +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + OSPI_MemoryMappedTypeDef sMemMappedCfg; + + /* Configure the command for the read instruction */ + sCommand.OperationType = HAL_OSPI_OPTYPE_READ_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = QUAD_INOUT_READ_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.AddressMode = HAL_OSPI_ADDRESS_4_LINES; + sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; + sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; + sCommand.AlternateBytes = MX25R6435F_ALT_BYTES_NO_PE_MODE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_4_LINES; + sCommand.AlternateBytesSize = HAL_OSPI_ALTERNATE_BYTES_8_BITS; + sCommand.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; + sCommand.DataMode = HAL_OSPI_DATA_4_LINES; + sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; + sCommand.DummyCycles = MX25R6435F_DUMMY_CYCLES_READ_QUAD; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; + + /* Configure the command */ + if (HAL_OSPI_Command(handle, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Configure the command for the program instruction */ + sCommand.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG; + sCommand.Instruction = QUAD_PAGE_PROG_CMD; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DummyCycles = 0; + + /* Configure the command */ + if (HAL_OSPI_Command(handle, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Configure the memory mapped mode */ + sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE; + + if (HAL_OSPI_MemoryMapped(handle, &sMemMappedCfg) != HAL_OK) { + return QSPI_ERROR; + } +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + QSPI_MemoryMappedTypeDef sMemMappedCfg; + + /* Configure the command for the read instruction */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = QUAD_INOUT_READ_CMD; + sCommand.AddressMode = QSPI_ADDRESS_4_LINES; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; + sCommand.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; + sCommand.AlternateBytes = MX25R6435F_ALT_BYTES_NO_PE_MODE; + sCommand.DataMode = QSPI_DATA_4_LINES; + sCommand.DummyCycles = MX25R6435F_DUMMY_CYCLES_READ_QUAD; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + /* Configure the memory mapped mode */ + sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE; + + if (HAL_QSPI_MemoryMapped(handle, &sCommand, &sMemMappedCfg) != HAL_OK) { + return QSPI_ERROR; + } +#endif /* OCTOSPI */ + + return QSPI_OK; +} + +/** + * @brief This function suspends an ongoing erase command. + * @param obj : pointer to QSPI_t structure + * @retval QSPI memory status + */ +uint8_t BSP_QSPI_SuspendErase(QSPI_t *obj) +{ + XSPI_HandleTypeDef *handle = &(obj->handle); + + /* Check whether the device is busy (erase operation is + in progress). + */ + if (BSP_QSPI_GetStatus(obj) == QSPI_BUSY) { +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + + /* Initialize the suspend command */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = PROG_ERASE_SUSPEND_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + + /* Initialize the erase command */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = PROG_ERASE_SUSPEND_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +#endif /* OCTOSPI */ + /* Send the command */ + if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + if (BSP_QSPI_GetStatus(obj) == QSPI_SUSPENDED) { + return QSPI_OK; + } + + return QSPI_ERROR; + } + + return QSPI_OK; +} + +/** + * @brief This function resumes a paused erase command. + * @param obj : pointer to QSPI_t structure + * @retval QSPI memory status + */ +uint8_t BSP_QSPI_ResumeErase(QSPI_t *obj) +{ + XSPI_HandleTypeDef *handle = &(obj->handle); + + /* Check whether the device is in suspended state */ + if (BSP_QSPI_GetStatus(obj) == QSPI_SUSPENDED) { +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + + /* Initialize the resume command */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = PROG_ERASE_RESUME_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + + /* Initialize the erase command */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = PROG_ERASE_RESUME_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +#endif /* OCTOSPI */ + /* Send the command */ + if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + /* + When this command is executed, the status register write in progress bit is set to 1, and + the flag status register program erase controller bit is set to 0. This command is ignored + if the device is not in a suspended state. + */ + + if (BSP_QSPI_GetStatus(obj) == QSPI_BUSY) { + return QSPI_OK; + } + + return QSPI_ERROR; + } + + return QSPI_OK; +} + +/** + * @brief This function enter the QSPI memory in deep power down mode. + * @param obj : pointer to QSPI_t structure + * @retval QSPI memory status + */ +uint8_t BSP_QSPI_EnterDeepPowerDown(QSPI_t *obj) +{ + XSPI_HandleTypeDef *handle = &(obj->handle); + +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + + /* Initialize the deep power down command */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = DEEP_POWER_DOWN_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + + /* Initialize the deep power down command */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = DEEP_POWER_DOWN_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +#endif /* OCTOSPI */ + + /* Send the command */ + if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* --- Memory takes 10us max to enter deep power down --- */ + /* --- At least 30us should be respected before leaving deep power down --- */ + + return QSPI_OK; +} + +/** + * @brief This function leave the QSPI memory from deep power down mode. + * @param obj : pointer to QSPI_t structure + * @retval QSPI memory status + */ +uint8_t BSP_QSPI_LeaveDeepPowerDown(QSPI_t *obj) +{ + XSPI_HandleTypeDef *handle = &(obj->handle); + +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + + /* Initialize the erase command */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = NO_OPERATION_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + + /* Initialize the erase command */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = NO_OPERATION_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +#endif /* OCTOSPI */ + + /* Send the command */ + if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* --- A NOP command is sent to the memory, as the nCS should be low for at least 20 ns --- */ + /* --- Memory takes 35us min to leave deep power down --- */ + + return QSPI_OK; +} + +/** + * @brief Initializes the QSPI MSP. + * @param obj : pointer to QSPI_t structure + * @retval None + */ +__weak void BSP_QSPI_MspInit(QSPI_t *obj) +{ +#ifdef OCTOSPI + + /* Enable the OctoSPI memory interface clock */ + /* Reset the OctoSPI memory interface */ +#if defined(OCTOSPI1) + if (obj->qspi == OCTOSPI1) { + __HAL_RCC_OSPI1_CLK_ENABLE(); + + __HAL_RCC_OSPI1_FORCE_RESET(); + __HAL_RCC_OSPI1_RELEASE_RESET(); + } +#endif +#if defined(OCTOSPI2) + if (obj->qspi == OCTOSPI2) { + __HAL_RCC_OSPI2_CLK_ENABLE(); + + __HAL_RCC_OSPI2_FORCE_RESET(); + __HAL_RCC_OSPI2_RELEASE_RESET(); + } +#endif +#else /* OCTOSPI */ + /* Enable the QuadSPI memory interface clock */ + __HAL_RCC_QSPI_CLK_ENABLE(); + + /* Reset the QuadSPI memory interface */ + __HAL_RCC_QSPI_FORCE_RESET(); + __HAL_RCC_QSPI_RELEASE_RESET(); +#endif /* OCTOSPI */ + + /* Configure QSPI GPIO pins */ + pinmap_pinout(obj->pin_d0, PinMap_XSPI_DATA0); + pinmap_pinout(obj->pin_d1, PinMap_XSPI_DATA1); + pinmap_pinout(obj->pin_d2, PinMap_XSPI_DATA2); + pinmap_pinout(obj->pin_d3, PinMap_XSPI_DATA3); + pinmap_pinout(obj->pin_sclk, PinMap_XSPI_SCLK); + pinmap_pinout(obj->pin_ssel, PinMap_XSPI_SSEL); +} + +/** + * @brief De-Initializes the QSPI MSP. + * @param obj : pointer to QSPI_t structure + * @retval None + */ +__weak void BSP_QSPI_MspDeInit(QSPI_t *obj) +{ + /* QSPI CLK, CS, D0-D3 GPIO pins de-configuration */ + + HAL_GPIO_DeInit((GPIO_TypeDef *)STM_PORT(obj->pin_d0), STM_GPIO_PIN(obj->pin_d0)); + HAL_GPIO_DeInit((GPIO_TypeDef *)STM_PORT(obj->pin_d1), STM_GPIO_PIN(obj->pin_d1)); + HAL_GPIO_DeInit((GPIO_TypeDef *)STM_PORT(obj->pin_d2), STM_GPIO_PIN(obj->pin_d2)); + HAL_GPIO_DeInit((GPIO_TypeDef *)STM_PORT(obj->pin_d3), STM_GPIO_PIN(obj->pin_d3)); + HAL_GPIO_DeInit((GPIO_TypeDef *)STM_PORT(obj->pin_sclk), STM_GPIO_PIN(obj->pin_sclk)); + HAL_GPIO_DeInit((GPIO_TypeDef *)STM_PORT(obj->pin_ssel), STM_GPIO_PIN(obj->pin_ssel)); + +#ifdef OCTOSPI +#if defined(OCTOSPI1) + /* Reset the OctoSPI memory interface */ + /* Disable the OctoSPI memory interface clock */ + if (obj->qspi == OCTOSPI1) { + __HAL_RCC_OSPI1_FORCE_RESET(); + __HAL_RCC_OSPI1_RELEASE_RESET(); + + __HAL_RCC_OSPI1_CLK_DISABLE(); + } +#endif +#if defined(OCTOSPI2) + if (obj->qspi == OCTOSPI2) { + __HAL_RCC_OSPI2_FORCE_RESET(); + __HAL_RCC_OSPI2_RELEASE_RESET(); + + __HAL_RCC_OSPI2_CLK_DISABLE(); + } +#endif +#else /* OCTOSPI */ + /* Reset the QuadSPI memory interface */ + __HAL_RCC_QSPI_FORCE_RESET(); + __HAL_RCC_QSPI_RELEASE_RESET(); + + /* Disable the QuadSPI memory interface clock */ + __HAL_RCC_QSPI_CLK_DISABLE(); +#endif /* OCTOSPI */ +} + +/** + * @brief This function reset the QSPI memory. + * @param hxspi : QSPI handle + * @retval None + */ +static uint8_t QSPI_ResetMemory(XSPI_HandleTypeDef *hxspi) +{ +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + + /* Initialize the reset enable command */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = RESET_ENABLE_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + + /* Initialize the reset enable command */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = RESET_ENABLE_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +#endif /* OCTOSPI */ + + /* Send the command */ + if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Send the reset memory command */ + sCommand.Instruction = RESET_MEMORY_CMD; + if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Configure automatic polling mode to wait the memory is ready */ + if (QSPI_AutoPollingMemReady(hxspi, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) { + return QSPI_ERROR; + } + + return QSPI_OK; +} + +/** + * @brief This function send a Write Enable and wait it is effective. + * @param hxspi : QSPI handle + * @retval None + */ +static uint8_t QSPI_WriteEnable(XSPI_HandleTypeDef *hxspi) +{ +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + OSPI_AutoPollingTypeDef sConfig; + + /* Enable write operations */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = WRITE_ENABLE_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; + + if (HAL_OSPI_Command(hxspi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Configure automatic polling mode to wait for write enabling */ + sConfig.Match = MX25R6435F_SR_WEL; + sConfig.Mask = MX25R6435F_SR_WEL; + sConfig.MatchMode = HAL_OSPI_MATCH_MODE_AND; + sConfig.Interval = 0x10; + sConfig.AutomaticStop = HAL_OSPI_AUTOMATIC_STOP_ENABLE; + + sCommand.Instruction = READ_STATUS_REG_CMD; + sCommand.DataMode = HAL_OSPI_DATA_1_LINE; + sCommand.NbData = 1; + sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; + + if (HAL_OSPI_Command(hxspi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + if (HAL_OSPI_AutoPolling(hxspi, &sConfig, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + QSPI_AutoPollingTypeDef sConfig; + + /* Enable write operations */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = WRITE_ENABLE_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + if (HAL_QSPI_Command(hxspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Configure automatic polling mode to wait for write enabling */ + sConfig.Match = MX25R6435F_SR_WEL; + sConfig.Mask = MX25R6435F_SR_WEL; + sConfig.MatchMode = QSPI_MATCH_MODE_AND; + sConfig.StatusBytesSize = 1; + sConfig.Interval = 0x10; + sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + + sCommand.Instruction = READ_STATUS_REG_CMD; + sCommand.DataMode = QSPI_DATA_1_LINE; + + if (HAL_QSPI_AutoPolling(hxspi, &sCommand, &sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } +#endif /* OCTOSPI */ + + return QSPI_OK; +} + +/** + * @brief This function read the SR of the memory and wait the EOP. + * @param hxspi : QSPI handle + * @param Timeout : Timeout for auto-polling + * @retval None + */ +static uint8_t QSPI_AutoPollingMemReady(XSPI_HandleTypeDef *hxspi, uint32_t Timeout) +{ +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + OSPI_AutoPollingTypeDef sConfig; + + /* Configure automatic polling mode to wait for memory ready */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = READ_STATUS_REG_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_1_LINE; + sCommand.NbData = 1; + sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; + sCommand.DummyCycles = 0; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; + + sConfig.Match = 0; + sConfig.Mask = MX25R6435F_SR_WIP; + sConfig.MatchMode = HAL_OSPI_MATCH_MODE_AND; + sConfig.Interval = 0x10; + sConfig.AutomaticStop = HAL_OSPI_AUTOMATIC_STOP_ENABLE; + + if (HAL_OSPI_Command(hxspi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + if (HAL_OSPI_AutoPolling(hxspi, &sConfig, Timeout) != HAL_OK) { + return QSPI_ERROR; + } +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + QSPI_AutoPollingTypeDef sConfig; + + /* Configure automatic polling mode to wait for memory ready */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = READ_STATUS_REG_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_1_LINE; + sCommand.DummyCycles = 0; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + sConfig.Match = 0; + sConfig.Mask = MX25R6435F_SR_WIP; + sConfig.MatchMode = QSPI_MATCH_MODE_AND; + sConfig.StatusBytesSize = 1; + sConfig.Interval = 0x10; + sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + + if (HAL_QSPI_AutoPolling(hxspi, &sCommand, &sConfig, Timeout) != HAL_OK) { + return QSPI_ERROR; + } +#endif /* OCTOSPI */ + + return QSPI_OK; +} + +/** + * @brief This function enables/disables the Quad mode of the memory. + * @param hxspi : QSPI handle + * @param Operation : QSPI_QUAD_ENABLE or QSPI_QUAD_DISABLE mode + * @retval None + */ +static uint8_t QSPI_QuadMode(XSPI_HandleTypeDef *hxspi, uint8_t Operation) +{ + uint8_t reg; +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + + /* Read status register */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = READ_STATUS_REG_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_1_LINE; + sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; + sCommand.DummyCycles = 0; + sCommand.NbData = 1; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + + /* Read status register */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = READ_STATUS_REG_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_1_LINE; + sCommand.DummyCycles = 0; + sCommand.NbData = 1; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +#endif /* OCTOSPI */ + + if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + if (HAL_XSPI_Receive(hxspi, ®, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Enable write operations */ + if (QSPI_WriteEnable(hxspi) != QSPI_OK) { + return QSPI_ERROR; + } + + /* Activate/deactivate the Quad mode */ + if (Operation == QSPI_QUAD_ENABLE) { + SET_BIT(reg, MX25R6435F_SR_QE); + } else { + CLEAR_BIT(reg, MX25R6435F_SR_QE); + } + + sCommand.Instruction = WRITE_STATUS_CFG_REG_CMD; + + if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + if (HAL_XSPI_Transmit(hxspi, ®, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Wait that memory is ready */ + if (QSPI_AutoPollingMemReady(hxspi, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) { + return QSPI_ERROR; + } + + /* Check the configuration has been correctly done */ + sCommand.Instruction = READ_STATUS_REG_CMD; + + if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + if (HAL_XSPI_Receive(hxspi, ®, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + if ((((reg & MX25R6435F_SR_QE) == 0) && (Operation == QSPI_QUAD_ENABLE)) || + (((reg & MX25R6435F_SR_QE) != 0) && (Operation == QSPI_QUAD_DISABLE))) { + return QSPI_ERROR; + } + + return QSPI_OK; +} + +/** + * @brief This function enables/disables the high performance mode of the memory. + * @param hxspi : QSPI handle + * @param Operation : QSPI_HIGH_PERF_ENABLE or QSPI_HIGH_PERF_DISABLE high performance mode + * @retval None + */ +static uint8_t QSPI_HighPerfMode(XSPI_HandleTypeDef *hxspi, uint8_t Operation) +{ + uint8_t reg[3]; +#ifdef OCTOSPI + OSPI_RegularCmdTypeDef sCommand; + + /* Read status register */ + sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; + sCommand.FlashId = HAL_OSPI_FLASH_ID_1; + sCommand.Instruction = READ_STATUS_REG_CMD; + sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; + sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; + sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; + sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = HAL_OSPI_DATA_1_LINE; + sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; + sCommand.DummyCycles = 0; + sCommand.NbData = 1; + sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; + sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +#else /* OCTOSPI */ + QSPI_CommandTypeDef sCommand; + + /* Read status register */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = READ_STATUS_REG_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_1_LINE; + sCommand.DummyCycles = 0; + sCommand.NbData = 1; + sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; + sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +#endif /* OCTOSPI */ + + if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + if (HAL_XSPI_Receive(hxspi, &(reg[0]), HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Read configuration registers */ + sCommand.Instruction = READ_CFG_REG_CMD; + sCommand.NbData = 2; + + if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + if (HAL_XSPI_Receive(hxspi, &(reg[1]), HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Enable write operations */ + if (QSPI_WriteEnable(hxspi) != QSPI_OK) { + return QSPI_ERROR; + } + + /* Activate/deactivate the Quad mode */ + if (Operation == QSPI_HIGH_PERF_ENABLE) { + SET_BIT(reg[2], MX25R6435F_CR2_LH_SWITCH); + } else { + CLEAR_BIT(reg[2], MX25R6435F_CR2_LH_SWITCH); + } + + sCommand.Instruction = WRITE_STATUS_CFG_REG_CMD; + sCommand.NbData = 3; + + if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + if (HAL_XSPI_Transmit(hxspi, &(reg[0]), HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + /* Wait that memory is ready */ + if (QSPI_AutoPollingMemReady(hxspi, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) { + return QSPI_ERROR; + } + + /* Check the configuration has been correctly done */ + sCommand.Instruction = READ_CFG_REG_CMD; + sCommand.NbData = 2; + + if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + if (HAL_XSPI_Receive(hxspi, &(reg[0]), HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return QSPI_ERROR; + } + + if ((((reg[1] & MX25R6435F_CR2_LH_SWITCH) == 0) && (Operation == QSPI_HIGH_PERF_ENABLE)) || + (((reg[1] & MX25R6435F_CR2_LH_SWITCH) != 0) && (Operation == QSPI_HIGH_PERF_DISABLE))) { + return QSPI_ERROR; + } + + return QSPI_OK; +} + +#ifdef __cplusplus +} +#endif + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/mx25r6435f_driver.h b/src/mx25r6435f_driver.h index 8a16c9d..83e1d3e 100644 --- a/src/mx25r6435f_driver.h +++ b/src/mx25r6435f_driver.h @@ -1,143 +1,133 @@ -/** - ****************************************************************************** - * @file mx25r6435f_driver.h - * @author MCD Application Team - * @version V1.1.0 - * @date 21-April-2017 - * @brief This file contains the common defines and functions prototypes for - * the mx25r6435f_driver.c driver. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2017 STMicroelectronics

- * - * 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 STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * 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. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef _MX25R6435F_DRIVER_H -#define _MX25R6435F_DRIVER_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "stm32_def.h" -#include "mx25r6435f_desc.h" - -/* Checks if QSPI available */ -#ifndef QUADSPI -#error "QSPI not available. MX25R6435F library compilation failed." -#endif - -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup STM32L475E_IOT01 - * @{ - */ - -/** @addtogroup STM32L475E_IOT01_QSPI - * @{ - */ - -/* Exported constants --------------------------------------------------------*/ -/** @defgroup STM32L475E_IOT01_QSPI_Exported_Constants QSPI Exported Constants - * @{ - */ -/* QSPI Error codes */ -#define QSPI_OK ((uint8_t)0x00) -#define QSPI_ERROR ((uint8_t)0x01) -#define QSPI_BUSY ((uint8_t)0x02) -#define QSPI_NOT_SUPPORTED ((uint8_t)0x04) -#define QSPI_SUSPENDED ((uint8_t)0x08) - -/** - * @} - */ - -/* Exported types ------------------------------------------------------------*/ -/** @defgroup STM32L475E_IOT01_QSPI_Exported_Types QSPI Exported Types - * @{ - */ -/* QSPI Info */ -typedef struct { - uint32_t FlashSize; /*!< Size of the flash */ - uint32_t EraseSectorSize; /*!< Size of sectors for the erase operation */ - uint32_t EraseSectorsNumber; /*!< Number of sectors for the erase operation */ - uint32_t ProgPageSize; /*!< Size of pages for the program operation */ - uint32_t ProgPagesNumber; /*!< Number of pages for the program operation */ -} QSPI_Info; - -/** - * @} - */ - -/* Exported functions --------------------------------------------------------*/ -/** @defgroup STM32L475E_IOT01_QSPI_Exported_Functions QSPI Exported Functions - * @{ - */ -uint8_t BSP_QSPI_Init (void); -uint8_t BSP_QSPI_DeInit (void); -uint8_t BSP_QSPI_Read (uint8_t* pData, uint32_t ReadAddr, uint32_t Size); -uint8_t BSP_QSPI_Write (uint8_t* pData, uint32_t WriteAddr, uint32_t Size); -uint8_t BSP_QSPI_Erase_Block (uint32_t BlockAddress); -uint8_t BSP_QSPI_Erase_Sector (uint32_t Sector); -uint8_t BSP_QSPI_Erase_Chip (void); -uint8_t BSP_QSPI_GetStatus (void); -uint8_t BSP_QSPI_GetInfo (QSPI_Info* pInfo); -uint8_t BSP_QSPI_EnableMemoryMappedMode(void); -uint8_t BSP_QSPI_SuspendErase (void); -uint8_t BSP_QSPI_ResumeErase (void); -uint8_t BSP_QSPI_EnterDeepPowerDown (void); -uint8_t BSP_QSPI_LeaveDeepPowerDown (void); - -void BSP_QSPI_MspInit(void); -void BSP_QSPI_MspDeInit(void); -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* _MX25R6435F_DRIVER_H */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/** + ****************************************************************************** + * @file mx25r6435f_driver.h + * @brief This file contains the common defines and functions prototypes for + * the mx25r6435f_driver.c driver. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef _MX25R6435F_DRIVER_H +#define _MX25R6435F_DRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32_def.h" +#include "PeripheralPins.h" +#include "mx25r6435f_desc.h" + +/* Exported constants --------------------------------------------------------*/ +#if defined(OCTOSPI1) || defined(OCTOSPI2) +#define OCTOSPI +#define XSPI_HandleTypeDef OSPI_HandleTypeDef +#define XSPI_TypeDef OCTOSPI_TypeDef +#define PinMap_XSPI_DATA0 PinMap_OCTOSPI_DATA0 +#define PinMap_XSPI_DATA1 PinMap_OCTOSPI_DATA1 +#define PinMap_XSPI_DATA2 PinMap_OCTOSPI_DATA2 +#define PinMap_XSPI_DATA3 PinMap_OCTOSPI_DATA3 +#define PinMap_XSPI_SCLK PinMap_OCTOSPI_SCLK +#define PinMap_XSPI_SSEL PinMap_OCTOSPI_SSEL +#define HAL_XSPI_Init HAL_OSPI_Init +#define HAL_XSPI_DeInit HAL_OSPI_DeInit +#define HAL_XSPI_TIMEOUT_DEFAULT_VALUE HAL_OSPI_TIMEOUT_DEFAULT_VALUE +#define HAL_XSPI_Command HAL_OSPI_Command +#define HAL_XSPI_Transmit HAL_OSPI_Transmit +#define HAL_XSPI_Receive HAL_OSPI_Receive +#elif defined(QUADSPI) +#define XSPI_HandleTypeDef QSPI_HandleTypeDef +#define XSPI_TypeDef QUADSPI_TypeDef + +#if defined(STM32_CORE_VERSION) && (STM32_CORE_VERSION > 0x01090000) +#define PinMap_XSPI_DATA0 PinMap_QUADSPI_DATA0 +#define PinMap_XSPI_DATA1 PinMap_QUADSPI_DATA1 +#define PinMap_XSPI_DATA2 PinMap_QUADSPI_DATA2 +#define PinMap_XSPI_DATA3 PinMap_QUADSPI_DATA3 +#define PinMap_XSPI_SCLK PinMap_QUADSPI_SCLK +#define PinMap_XSPI_SSEL PinMap_QUADSPI_SSEL +#else +#define PinMap_XSPI_DATA0 PinMap_QUADSPI +#define PinMap_XSPI_DATA1 PinMap_QUADSPI +#define PinMap_XSPI_DATA2 PinMap_QUADSPI +#define PinMap_XSPI_DATA3 PinMap_QUADSPI +#define PinMap_XSPI_SCLK PinMap_QUADSPI +#define PinMap_XSPI_SSEL PinMap_QUADSPI +#endif +#define HAL_XSPI_Init HAL_QSPI_Init +#define HAL_XSPI_DeInit HAL_QSPI_DeInit +#define HAL_XSPI_TIMEOUT_DEFAULT_VALUE HAL_QPSI_TIMEOUT_DEFAULT_VALUE +#define HAL_XSPI_Command HAL_QSPI_Command +#define HAL_XSPI_Transmit HAL_QSPI_Transmit +#define HAL_XSPI_Receive HAL_QSPI_Receive +#else +#error "QSPI feature not available. MX25R6435F library compilation failed." +#endif /* OCTOSPIx */ + +/* QSPI Error codes */ +#define QSPI_OK ((uint8_t)0x00) +#define QSPI_ERROR ((uint8_t)0x01) +#define QSPI_BUSY ((uint8_t)0x02) +#define QSPI_NOT_SUPPORTED ((uint8_t)0x04) +#define QSPI_SUSPENDED ((uint8_t)0x08) + +/* Exported types ------------------------------------------------------------*/ +/* QSPI Info */ +typedef struct { + uint32_t FlashSize; /*!< Size of the flash */ + uint32_t EraseSectorSize; /*!< Size of sectors for the erase operation */ + uint32_t EraseSectorsNumber; /*!< Number of sectors for the erase operation */ + uint32_t ProgPageSize; /*!< Size of pages for the program operation */ + uint32_t ProgPagesNumber; /*!< Number of pages for the program operation */ +} QSPI_Info; + + +typedef struct { + XSPI_HandleTypeDef handle; + XSPI_TypeDef *qspi; + PinName pin_d0; + PinName pin_d1; + PinName pin_d2; + PinName pin_d3; + PinName pin_sclk; + PinName pin_ssel; +} QSPI_t; + +/* Exported functions --------------------------------------------------------*/ +uint8_t BSP_QSPI_Init(QSPI_t *obj); +uint8_t BSP_QSPI_DeInit(QSPI_t *obj); +uint8_t BSP_QSPI_Read(QSPI_t *obj, uint8_t *pData, uint32_t ReadAddr, uint32_t Size); +uint8_t BSP_QSPI_Write(QSPI_t *obj, uint8_t *pData, uint32_t WriteAddr, uint32_t Size); +uint8_t BSP_QSPI_Erase_Block(QSPI_t *obj, uint32_t BlockAddress); +uint8_t BSP_QSPI_Erase_Sector(QSPI_t *obj, uint32_t Sector); +uint8_t BSP_QSPI_Erase_Chip(QSPI_t *obj); +uint8_t BSP_QSPI_GetStatus(QSPI_t *obj); +uint8_t BSP_QSPI_GetInfo(QSPI_Info *pInfo); +uint8_t BSP_QSPI_EnableMemoryMappedMode(QSPI_t *obj); +uint8_t BSP_QSPI_SuspendErase(QSPI_t *obj); +uint8_t BSP_QSPI_ResumeErase(QSPI_t *obj); +uint8_t BSP_QSPI_EnterDeepPowerDown(QSPI_t *obj); +uint8_t BSP_QSPI_LeaveDeepPowerDown(QSPI_t *obj); + +void BSP_QSPI_MspInit(QSPI_t *obj); +void BSP_QSPI_MspDeInit(QSPI_t *obj); + +#ifdef __cplusplus +} +#endif + +#endif /* _MX25R6435F_DRIVER_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/