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****/