├── README.md ├── examples ├── demo │ └── demo.ino ├── eraseChip │ └── eraseChip.ino └── memoryMappedMode │ └── memoryMappedMode.ino ├── keywords.txt ├── library.properties └── src ├── MX25R6435F.cpp ├── MX25R6435F.h ├── mx25r6435f_desc.h ├── mx25r6435f_driver.c └── mx25r6435f_driver.h /README.md: -------------------------------------------------------------------------------- 1 | # MX25R6435F 2 | 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. 3 | 4 | ## API 5 | 6 | The library provides the following API: 7 | 8 | * `begin()` 9 | * `end()` 10 | * `write()` 11 | * `read()` 12 | * `mapped()` 13 | * `erase()` 14 | * `eraseChip()` 15 | * `eraseSector()` 16 | * `suspendErase()` 17 | * `resumeErase()` 18 | * `sleep()` 19 | * `wakeup()` 20 | * `status()` 21 | * `info()` 22 | * `length()` 23 | 24 | Since library version 2.0.0, xSPI pins can be defined at sketch level, using: 25 | 26 | * To redefine the default one before call of `begin()`: 27 | 28 | * `setDx(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3)` 29 | * `setDx(PinName data0, PinName data1, PinName data2, PinName data3)` 30 | * `setSSEL(uint32_t ssel)` 31 | * `setSSEL(PinName ssel)` 32 | * `setSCLK(uint32_t sclk)` 33 | * `setSCLK(PinName sclk)` 34 | 35 | *Code snippet:* 36 | ```C++ 37 | MX25R6435F.setDx(PE12, PE13, PE14, PE15); // using pin number 38 | MX25R6435F.setSCLK(PE10); 39 | MX25R6435F.setSSEL(PE_11); // using PinName 40 | MX25R6435F.begin(); 41 | ``` 42 | 43 | * or using the `begin()` method: 44 | 45 | * `MX25R6435FClass(uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3, uint8_t clk, uint8_t ssel)` 46 | 47 | *Code snippet:* 48 | ```C++ 49 | MX25R6435F.begin(PE12, PE13, PE14, PE15, PE10, PE11); 50 | ``` 51 | 52 | * 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)): 53 | 54 | * `MX25R6435F_D0` 55 | * `MX25R6435F_D1` 56 | * `MX25R6435F_D2` 57 | * `MX25R6435F_D3` 58 | * `MX25R6435F_SCLK` 59 | * `MX25R6435F_SSEL` 60 | 61 | ## Examples 62 | 63 | 3 sketches provide basic examples to show how to use the library API: 64 | * `demo.ino` uses basic read/write functions. 65 | * `eraseChip.ino` erases all data present in the memory. 66 | * `memoryMappedMode.ino` shows how to use the mapped mode. 67 | 68 | ## Documentation 69 | 70 | You can find the source files at 71 | https://github.com/stm32duino/MX25R6435F 72 | 73 | The MX25R6435F datasheet is available at 74 | http://www.mxic.com.tw/Lists/Datasheet/Attachments/6270/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.4.pdf 75 | -------------------------------------------------------------------------------- /examples/demo/demo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * demo 3 | * 4 | * This sketch show how to use the mx25r6435f driver. 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #define BUFFER_SIZE ((uint32_t)0x0100) 11 | #define WRITE_READ_ADDR ((uint32_t)0x0050) 12 | 13 | uint8_t aTxBuffer[BUFFER_SIZE]; 14 | uint8_t aRxBuffer[BUFFER_SIZE]; 15 | 16 | static void Fill_Buffer (uint8_t *pBuffer, uint32_t uwBufferLength, uint32_t uwOffset); 17 | static uint8_t Buffercmp (uint8_t* pBuffer1, uint8_t* pBuffer2, uint32_t BufferLength); 18 | 19 | void setup() { 20 | Serial.begin(9600); 21 | } 22 | 23 | void loop() { 24 | uint8_t status; 25 | 26 | Serial.println("*****************************************************************"); 27 | Serial.println("*********************** Memory Test *****************************"); 28 | Serial.println("*****************************************************************"); 29 | 30 | MX25R6435F.end(); 31 | 32 | /*##-1- Configure the device ##########################################*/ 33 | /* Device configuration */ 34 | MX25R6435F.begin(); 35 | status = MX25R6435F.status(); 36 | 37 | if ((status == MEMORY_ERROR) || (status == MEMORY_SUSPENDED) || (status == MEMORY_BUSY)) 38 | { 39 | Serial.println("Init : FAILED, Test Aborted"); 40 | } 41 | else 42 | { 43 | Serial.println("Init : OK"); 44 | 45 | /*##-2- Read & check the info #######################################*/ 46 | if( (MX25R6435F.info(MEMORY_SIZE) != 0x800000) || 47 | (MX25R6435F.info(MEMORY_SECTOR_SIZE) != 0x1000) || 48 | (MX25R6435F.info(MEMORY_PAGE_SIZE) != 0x100) || 49 | (MX25R6435F.info(MEMORY_SECTOR_NUMBER) != 2048) || 50 | (MX25R6435F.info(MEMORY_PAGE_NUMBER) != 32768)) 51 | { 52 | Serial.println("GET INFO : FAILED, Test Aborted"); 53 | } 54 | else 55 | { 56 | Serial.println("GET INFO : OK"); 57 | 58 | /*##-3- Erase memory ################################################*/ 59 | if(MX25R6435F.erase(WRITE_READ_ADDR) != MEMORY_OK) 60 | { 61 | Serial.println("ERASE : FAILED, Test Aborted"); 62 | } 63 | else 64 | { 65 | Serial.println("ERASE : OK"); 66 | 67 | /*##-4- memory read/write access #################################*/ 68 | /* Fill the buffer to write */ 69 | Fill_Buffer(aTxBuffer, BUFFER_SIZE, 0xD20F); 70 | 71 | /* Write data to the QSPI memory */ 72 | if(MX25R6435F.write(aTxBuffer, WRITE_READ_ADDR, BUFFER_SIZE) == 0) 73 | { 74 | Serial.println("WRITE : FAILED, Test Aborted"); 75 | } 76 | else 77 | { 78 | Serial.println("WRITE : OK"); 79 | 80 | /* Read back data from the QSPI memory */ 81 | MX25R6435F.read(aRxBuffer, WRITE_READ_ADDR, BUFFER_SIZE); 82 | 83 | /*##-5- Checking data integrity ############################################*/ 84 | if(Buffercmp(aRxBuffer, aTxBuffer, BUFFER_SIZE) > 0) 85 | { 86 | Serial.println("COMPARE : FAILED, Test Aborted"); 87 | } 88 | else 89 | { 90 | Serial.println("Test : OK"); 91 | } 92 | } 93 | } 94 | } 95 | } 96 | 97 | // Enables the deep power mode 98 | MX25R6435F.sleep(); 99 | delay(5000); 100 | MX25R6435F.wakeup(); 101 | } 102 | 103 | static void Fill_Buffer(uint8_t *pBuffer, uint32_t uwBufferLenght, uint32_t uwOffset) 104 | { 105 | uint32_t tmpIndex = 0; 106 | 107 | /* Put in global buffer different values */ 108 | for (tmpIndex = 0; tmpIndex < uwBufferLenght; tmpIndex++ ) 109 | { 110 | pBuffer[tmpIndex] = tmpIndex + uwOffset; 111 | } 112 | } 113 | 114 | static uint8_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint32_t BufferLength) 115 | { 116 | while (BufferLength--) 117 | { 118 | if (*pBuffer1 != *pBuffer2) 119 | { 120 | return 1; 121 | } 122 | 123 | pBuffer1++; 124 | pBuffer2++; 125 | } 126 | 127 | return 0; 128 | } 129 | -------------------------------------------------------------------------------- /examples/eraseChip/eraseChip.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * eraseChip 3 | * 4 | * Sets all of the bytes of the memory to the default value (0xFF). 5 | * Could take until 240 seconds to erase all the memory (worst conditions). 6 | * 7 | */ 8 | 9 | #include 10 | 11 | void setup() { 12 | // initialize the LED pin as an output. 13 | pinMode(LED_BUILTIN, OUTPUT); 14 | 15 | // initialize the MX25R6435F flash memory 16 | MX25R6435F.begin(); 17 | 18 | // erase all the memory: set byte to 0xFF 19 | MX25R6435F.eraseChip(); 20 | 21 | // turn the LED on when we're done 22 | digitalWrite(LED_BUILTIN, HIGH); 23 | } 24 | 25 | void loop() { 26 | /** Empty loop. **/ 27 | } 28 | -------------------------------------------------------------------------------- /examples/memoryMappedMode/memoryMappedMode.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * memoryMappedMode 3 | * 4 | * This sketch show how to use the mx25r6435f driver and the memory mapped mode. 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #define BUFFER_SIZE ((uint32_t)0x0100) 11 | #define WRITE_READ_ADDR ((uint32_t)0x0050) 12 | 13 | uint8_t aTxBuffer[BUFFER_SIZE]; 14 | uint8_t aRxBuffer[BUFFER_SIZE]; 15 | 16 | static void Fill_Buffer (uint8_t *pBuffer, uint32_t uwBufferLength, uint32_t uwOffset); 17 | 18 | void setup() { 19 | Serial.begin(9600); 20 | } 21 | 22 | void loop() { 23 | /* QSPI info structure */ 24 | uint8_t status, read_status = 0; 25 | uint16_t index = 0; 26 | uint8_t *mem_addr; 27 | 28 | Serial.println("*****************************************************************"); 29 | Serial.println("********************* Memory mapped Test ************************"); 30 | Serial.println("*****************************************************************"); 31 | 32 | MX25R6435F.end(); 33 | 34 | /*##-1- Configure the device ##########################################*/ 35 | /* Device configuration */ 36 | MX25R6435F.begin(); 37 | status = MX25R6435F.status(); 38 | 39 | if ((status == MEMORY_ERROR) || (status == MEMORY_SUSPENDED) || (status == MEMORY_BUSY)) 40 | { 41 | Serial.println("Init : FAILED, Test Aborted"); 42 | } 43 | else 44 | { 45 | Serial.println("Init : OK"); 46 | 47 | /*##-2- Read & check the info #######################################*/ 48 | if( (MX25R6435F.info(MEMORY_SIZE) != 0x800000) || 49 | (MX25R6435F.info(MEMORY_SECTOR_SIZE) != 0x1000) || 50 | (MX25R6435F.info(MEMORY_PAGE_SIZE) != 0x100) || 51 | (MX25R6435F.info(MEMORY_SECTOR_NUMBER) != 2048) || 52 | (MX25R6435F.info(MEMORY_PAGE_NUMBER) != 32768)) 53 | { 54 | Serial.println("GET INFO : FAILED, Test Aborted"); 55 | } 56 | else 57 | { 58 | Serial.println("GET INFO : OK"); 59 | 60 | /*##-3- Erase memory ################################################*/ 61 | if(MX25R6435F.erase(WRITE_READ_ADDR) != MEMORY_OK) 62 | { 63 | Serial.println("ERASE : FAILED, Test Aborted"); 64 | } 65 | else 66 | { 67 | Serial.println("ERASE : OK"); 68 | 69 | /*##-4- memory read/write access #################################*/ 70 | /* Fill the buffer to write */ 71 | Fill_Buffer(aTxBuffer, BUFFER_SIZE, 0xD20F); 72 | 73 | for(uint32_t i = 0; i < 1; i++) 74 | { 75 | if(MX25R6435F.write(aTxBuffer, (i * 0x100), BUFFER_SIZE) != BUFFER_SIZE) 76 | { 77 | Serial.println("WRITE : FAILED, Test Aborted"); 78 | } 79 | } 80 | 81 | /* Read back data from the QSPI memory */ 82 | mem_addr = MX25R6435F.mapped(); 83 | 84 | if(mem_addr != NULL) { 85 | for(uint32_t i = 0; i < 1; i++) 86 | { 87 | mem_addr += (i * 0x100); 88 | for (index = 0; index < BUFFER_SIZE; index++) 89 | { 90 | if (*mem_addr != aTxBuffer[index]) 91 | { 92 | read_status++; 93 | Serial.println(read_status); 94 | } 95 | mem_addr++; 96 | } 97 | } 98 | 99 | 100 | if(read_status != 0) 101 | { 102 | Serial.println("READ : FAILED"); 103 | Serial.println("Test Aborted"); 104 | } 105 | else 106 | { 107 | Serial.println("READ : OK"); 108 | Serial.println("Test : OK"); 109 | 110 | } 111 | } else { 112 | Serial.println("MAPPED MODE : FAILED"); 113 | Serial.println("Test Aborted"); 114 | } 115 | } 116 | } 117 | } 118 | 119 | delay(5000); 120 | } 121 | 122 | static void Fill_Buffer(uint8_t *pBuffer, uint32_t uwBufferLenght, uint32_t uwOffset) 123 | { 124 | uint32_t tmpIndex = 0; 125 | 126 | /* Put in global buffer different values */ 127 | for (tmpIndex = 0; tmpIndex < uwBufferLenght; tmpIndex++ ) 128 | { 129 | pBuffer[tmpIndex] = tmpIndex + uwOffset; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map MX25R6435F 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | MX25R6435F KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | begin KEYWORD2 15 | end KEYWORD2 16 | write KEYWORD2 17 | read KEYWORD2 18 | mapped KEYWORD2 19 | erase KEYWORD2 20 | eraseSector KEYWORD2 21 | eraseChip KEYWORD2 22 | suspendErase KEYWORD2 23 | resumeErase KEYWORD2 24 | sleep KEYWORD2 25 | wakeup KEYWORD2 26 | status KEYWORD2 27 | info KEYWORD2 28 | length KEYWORD2 29 | setDx KEYWORD2 30 | setSCLK KEYWORD2 31 | setSSEL KEYWORD2 32 | 33 | ####################################### 34 | # Constants (LITERAL1) 35 | ####################################### 36 | MEMORY_SIZE LITERAL1 37 | MEMORY_SECTOR_SIZE LITERAL1 38 | MEMORY_SECTOR_NUMBER LITERAL1 39 | MEMORY_PAGE_SIZE LITERAL1 40 | MEMORY_PAGE_NUMBER LITERAL1 41 | MEMORY_OK LITERAL1 42 | MEMORY_ERROR LITERAL1 43 | MEMORY_BUSY LITERAL1 44 | MEMORY_NOT_SUPPORTED LITERAL1 45 | MEMORY_SUSPENDED LITERAL1 46 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=STM32duino MX25R6435F 2 | version=2.0.0 3 | author=stm32duino 4 | maintainer=stm32duino 5 | sentence=Quad-SPI NOR Flash memory library. 6 | paragraph=This library provides Arduino support for the 64-Mbit Quad-SPI NOR Flash memory MX25R6435F connected to the Quad-SPI or Octo-SPI interfaces of a STM32 board. 7 | category=Data Storage 8 | url=https://github.com/stm32duino/MX25R6435F 9 | architectures=stm32 10 | -------------------------------------------------------------------------------- /src/MX25R6435F.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file MX25R6435F.c 4 | * @author WI6LABS 5 | * @version V1.0.0 6 | * @date 19-July-2017 7 | * @brief MX25R6435F library for STM32 Arduino 8 | * 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

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

14 | * 15 | * This software component is licensed by ST under BSD 3-Clause license, 16 | * the "License"; You may not use this file except in compliance with the 17 | * License. You may obtain a copy of the License at: 18 | * opensource.org/licenses/BSD-3-Clause 19 | * 20 | ****************************************************************************** 21 | */ 22 | 23 | #include "MX25R6435F.h" 24 | 25 | MX25R6435FClass MX25R6435F; 26 | 27 | MX25R6435FClass::MX25R6435FClass(): initDone(0) 28 | { 29 | } 30 | 31 | void MX25R6435FClass::begin(uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3, uint8_t sclk, uint8_t ssel) 32 | { 33 | _qspi.pin_d0 = digitalPinToPinName(data0); 34 | _qspi.pin_d1 = digitalPinToPinName(data1); 35 | _qspi.pin_d2 = digitalPinToPinName(data2); 36 | _qspi.pin_d3 = digitalPinToPinName(data3); 37 | _qspi.pin_sclk = digitalPinToPinName(sclk); 38 | _qspi.pin_ssel = digitalPinToPinName(ssel); 39 | 40 | if (BSP_QSPI_Init(&_qspi) == MEMORY_OK) { 41 | initDone = 1; 42 | } 43 | } 44 | 45 | void MX25R6435FClass::end(void) 46 | { 47 | BSP_QSPI_DeInit(&_qspi); 48 | initDone = 0; 49 | } 50 | 51 | uint32_t MX25R6435FClass::write(uint8_t data, uint32_t addr) 52 | { 53 | return write(&data, addr, 1); 54 | } 55 | 56 | uint32_t MX25R6435FClass::write(uint8_t *pData, uint32_t addr, uint32_t size) 57 | { 58 | if ((pData == NULL) || (initDone == 0)) { 59 | return 0; 60 | } 61 | 62 | if (BSP_QSPI_Write(&_qspi, pData, addr, size) != MEMORY_OK) { 63 | return 0; 64 | } 65 | 66 | return size; 67 | } 68 | 69 | uint8_t MX25R6435FClass::read(uint32_t addr) 70 | { 71 | uint8_t data; 72 | 73 | read(&data, addr, 1); 74 | 75 | return data; 76 | } 77 | 78 | void MX25R6435FClass::read(uint8_t *pData, uint32_t addr, uint32_t size) 79 | { 80 | if ((pData != NULL) && (initDone == 1)) { 81 | BSP_QSPI_Read(&_qspi, pData, addr, size); 82 | } 83 | } 84 | 85 | uint8_t *MX25R6435FClass::mapped(void) 86 | { 87 | if (BSP_QSPI_EnableMemoryMappedMode(&_qspi) != MEMORY_OK) { 88 | return NULL; 89 | } 90 | 91 | return (uint8_t *)MEMORY_MAPPED_ADDRESS; 92 | } 93 | 94 | uint8_t MX25R6435FClass::erase(uint32_t addr) 95 | { 96 | if (initDone == 0) { 97 | return MEMORY_ERROR; 98 | } 99 | 100 | return BSP_QSPI_Erase_Block(&_qspi, addr); 101 | } 102 | 103 | uint8_t MX25R6435FClass::eraseChip(void) 104 | { 105 | if (initDone == 0) { 106 | return MEMORY_ERROR; 107 | } 108 | 109 | return BSP_QSPI_Erase_Chip(&_qspi); 110 | } 111 | 112 | uint8_t MX25R6435FClass::eraseSector(uint32_t sector) 113 | { 114 | if (initDone == 0) { 115 | return MEMORY_ERROR; 116 | } 117 | 118 | return BSP_QSPI_Erase_Sector(&_qspi, sector); 119 | } 120 | 121 | uint8_t MX25R6435FClass::suspendErase(void) 122 | { 123 | if (initDone == 0) { 124 | return MEMORY_ERROR; 125 | } 126 | 127 | return BSP_QSPI_SuspendErase(&_qspi); 128 | } 129 | 130 | uint8_t MX25R6435FClass::resumeErase(void) 131 | { 132 | if (initDone == 0) { 133 | return MEMORY_ERROR; 134 | } 135 | 136 | return BSP_QSPI_ResumeErase(&_qspi); 137 | } 138 | 139 | uint8_t MX25R6435FClass::sleep(void) 140 | { 141 | if (initDone == 0) { 142 | return MEMORY_ERROR; 143 | } 144 | 145 | return BSP_QSPI_EnterDeepPowerDown(&_qspi); 146 | } 147 | 148 | uint8_t MX25R6435FClass::wakeup(void) 149 | { 150 | if (initDone == 0) { 151 | return MEMORY_ERROR; 152 | } 153 | 154 | return BSP_QSPI_LeaveDeepPowerDown(&_qspi); 155 | } 156 | 157 | uint8_t MX25R6435FClass::status(void) 158 | { 159 | return BSP_QSPI_GetStatus(&_qspi); 160 | } 161 | 162 | uint32_t MX25R6435FClass::info(memory_info_t info) 163 | { 164 | uint32_t res; 165 | QSPI_Info pInfo; 166 | 167 | BSP_QSPI_GetInfo(&pInfo); 168 | 169 | switch (info) { 170 | case MEMORY_SIZE: 171 | res = pInfo.FlashSize; 172 | break; 173 | 174 | case MEMORY_SECTOR_SIZE: 175 | res = pInfo.EraseSectorSize; 176 | break; 177 | 178 | case MEMORY_SECTOR_NUMBER: 179 | res = pInfo.EraseSectorsNumber; 180 | break; 181 | 182 | case MEMORY_PAGE_SIZE: 183 | res = pInfo.ProgPageSize; 184 | break; 185 | 186 | case MEMORY_PAGE_NUMBER: 187 | res = pInfo.ProgPagesNumber; 188 | break; 189 | 190 | default: 191 | res = 0; 192 | break; 193 | } 194 | 195 | return res; 196 | } 197 | 198 | uint32_t MX25R6435FClass::length(void) 199 | { 200 | return info(MEMORY_SIZE); 201 | } 202 | -------------------------------------------------------------------------------- /src/MX25R6435F.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file MX25R6435F.h 4 | * @brief MX25R6435F library for STM32 Arduino 5 | * 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | #ifndef _MX25R6435F_H_ 21 | #define _MX25R6435F_H_ 22 | 23 | #include "Arduino.h" 24 | #include "mx25r6435f_driver.h" 25 | 26 | /* 27 | * For backward compatibility define the xSPI pins used by: 28 | * B-L475E-IOT01A and B-L4S5I-IOT01A 29 | */ 30 | #ifndef MX25R6435F_D0 31 | #define MX25R6435F_D0 PE12 32 | #endif 33 | #ifndef MX25R6435F_D1 34 | #define MX25R6435F_D1 PE13 35 | #endif 36 | #ifndef MX25R6435F_D2 37 | #define MX25R6435F_D2 PE14 38 | #endif 39 | #ifndef MX25R6435F_D3 40 | #define MX25R6435F_D3 PE15 41 | #endif 42 | #ifndef MX25R6435F_SCLK 43 | #define MX25R6435F_SCLK PE10 44 | #endif 45 | #ifndef MX25R6435F_SSEL 46 | #define MX25R6435F_SSEL PE11 47 | #endif 48 | 49 | /* Memory configuration paremeters */ 50 | typedef enum { 51 | MEMORY_SIZE, 52 | MEMORY_SECTOR_SIZE, 53 | MEMORY_SECTOR_NUMBER, 54 | MEMORY_PAGE_SIZE, 55 | MEMORY_PAGE_NUMBER 56 | } memory_info_t; 57 | 58 | /* Memory Error codes */ 59 | #define MEMORY_OK QSPI_OK 60 | #define MEMORY_ERROR QSPI_ERROR 61 | #define MEMORY_BUSY QSPI_BUSY 62 | #define MEMORY_NOT_SUPPORTED QSPI_NOT_SUPPORTED 63 | #define MEMORY_SUSPENDED QSPI_SUSPENDED 64 | 65 | /* Base address of the memory in mapped mode */ 66 | #define MEMORY_MAPPED_ADDRESS ((uint32_t)0x90000000) 67 | 68 | class MX25R6435FClass { 69 | public: 70 | MX25R6435FClass(); 71 | 72 | // setDx/SCLK/SSEL have to be called before begin() 73 | void setDx(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3) 74 | { 75 | _qspi.pin_d0 = digitalPinToPinName(data0); 76 | _qspi.pin_d1 = digitalPinToPinName(data1); 77 | _qspi.pin_d2 = digitalPinToPinName(data2); 78 | _qspi.pin_d3 = digitalPinToPinName(data3); 79 | }; 80 | void setSCLK(uint32_t sclk) 81 | { 82 | _qspi.pin_sclk = digitalPinToPinName(sclk); 83 | }; 84 | void setSSEL(uint32_t ssel) 85 | { 86 | _qspi.pin_ssel = digitalPinToPinName(ssel); 87 | }; 88 | 89 | void setDx(PinName data0, PinName data1, PinName data2, PinName data3) 90 | { 91 | _qspi.pin_d0 = (data0); 92 | _qspi.pin_d1 = (data1); 93 | _qspi.pin_d2 = (data2); 94 | _qspi.pin_d3 = (data3); 95 | }; 96 | void setSCLK(PinName sclk) 97 | { 98 | _qspi.pin_sclk = (sclk); 99 | }; 100 | void setSSEL(PinName ssel) 101 | { 102 | _qspi.pin_ssel = (ssel); 103 | }; 104 | 105 | /* Initializes the memory interface. */ 106 | 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); 107 | 108 | /* De-Initializes the memory interface. */ 109 | void end(void); 110 | 111 | /** 112 | * @brief Writes one byte to the memory. 113 | * @param data : data to be written 114 | * @param addr : Write start address 115 | * @retval number of data written. 0 indicates a failure. 116 | */ 117 | uint32_t write(uint8_t data, uint32_t addr); 118 | 119 | /** 120 | * @brief Writes an amount of data to the memory. 121 | * @param pData : Pointer to data to be written 122 | * @param addr : Write start address 123 | * @param size : Size of data to write 124 | * @retval number of data written. 0 indicates a failure. 125 | */ 126 | uint32_t write(uint8_t *pData, uint32_t addr, uint32_t size); 127 | 128 | /** 129 | * @brief Reads one byte from the memory. 130 | * @param addr : Read start address 131 | * @retval data read 132 | */ 133 | uint8_t read(uint32_t addr); 134 | 135 | /** 136 | * @brief Reads an amount of data from the memory. 137 | * @param pData : Pointer to data to be read 138 | * @param addr : Read start address 139 | * @param size : Size of data to read 140 | */ 141 | void read(uint8_t *pData, uint32_t addr, uint32_t size); 142 | 143 | /** 144 | * @brief Configure the memory in mapped mode 145 | * @retval pointer to the memory 146 | */ 147 | uint8_t *mapped(void); 148 | 149 | /** 150 | * @brief Erases the specified block of the memory. 151 | * @param addr : Block address to erase 152 | * @retval memory status 153 | */ 154 | uint8_t erase(uint32_t addr); 155 | 156 | /** 157 | * @brief Erases the entire memory. 158 | * @retval memory status 159 | */ 160 | uint8_t eraseChip(void); 161 | 162 | /** 163 | * @brief Erases the specified sector of the memory. 164 | * @param sector : Sector address to erase 165 | * @retval memory status 166 | * @note This function is non blocking meaning that sector erase 167 | * operation is started but not completed when the function 168 | * returns. Application has to call BSP_QSPI_GetStatus() 169 | * to know when the device is available again (i.e. erase operation 170 | * completed). 171 | */ 172 | uint8_t eraseSector(uint32_t sector); 173 | 174 | /** 175 | * @brief This function suspends an ongoing eraseSector command. 176 | * @retval memory status 177 | */ 178 | uint8_t suspendErase(void); 179 | 180 | /** 181 | * @brief This function resumes a paused eraseSector command. 182 | * @retval memory status 183 | */ 184 | uint8_t resumeErase(void); 185 | 186 | /** 187 | * @brief This function enter the memory in deep power down mode. 188 | * @retval memory status 189 | */ 190 | uint8_t sleep(void); 191 | 192 | /** 193 | * @brief This function leave the memory from deep power down mode. 194 | * @retval memory status 195 | */ 196 | uint8_t wakeup(void); 197 | 198 | /* Reads current status of the memory.*/ 199 | uint8_t status(void); 200 | 201 | /** 202 | * @brief Return the configuration of the memory. 203 | * @param info : value to read. This parameter should be a value of 204 | * memory_info_t. 205 | * @retval configuration value read 206 | */ 207 | uint32_t info(memory_info_t info); 208 | 209 | /* Return the total size of the memory */ 210 | uint32_t length(void); 211 | 212 | private: 213 | uint8_t initDone; 214 | QSPI_t _qspi; 215 | }; 216 | 217 | extern MX25R6435FClass MX25R6435F; 218 | 219 | #endif /* _MX25R6435F_H_ */ 220 | -------------------------------------------------------------------------------- /src/mx25r6435f_desc.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file mx25r6435f.h 4 | * @brief This file contains all the description of the MX25R6435F QSPI memory. 5 | ****************************************************************************** 6 | * @attention 7 | * 8 | *

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

10 | * 11 | * This software component is licensed by ST under BSD 3-Clause license, 12 | * the "License"; You may not use this file except in compliance with the 13 | * License. You may obtain a copy of the License at: 14 | * opensource.org/licenses/BSD-3-Clause 15 | * 16 | ****************************************************************************** 17 | */ 18 | 19 | /* Define to prevent recursive inclusion -------------------------------------*/ 20 | #ifndef __MX25R6435F_H 21 | #define __MX25R6435F_H 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | /* Includes ------------------------------------------------------------------*/ 28 | 29 | /** 30 | * @brief MX25R6435F Configuration 31 | */ 32 | #define MX25R6435F_FLASH_SIZE 0x800000 /* 64 MBits => 8MBytes */ 33 | #define MX25R6435F_BLOCK_SIZE 0x10000 /* 128 blocks of 64KBytes */ 34 | #define MX25R6435F_SUBBLOCK_SIZE 0x8000 /* 256 blocks of 32KBytes */ 35 | #define MX25R6435F_SECTOR_SIZE 0x1000 /* 2048 sectors of 4kBytes */ 36 | #define MX25R6435F_PAGE_SIZE 0x100 /* 32768 pages of 256 bytes */ 37 | 38 | #define MX25R6435F_DUMMY_CYCLES_READ 8 39 | #define MX25R6435F_DUMMY_CYCLES_READ_DUAL 4 40 | #define MX25R6435F_DUMMY_CYCLES_READ_QUAD 4 41 | #define MX25R6435F_DUMMY_CYCLES_2READ 2 42 | #define MX25R6435F_DUMMY_CYCLES_4READ 4 43 | 44 | #define MX25R6435F_ALT_BYTES_PE_MODE 0xA5 45 | #define MX25R6435F_ALT_BYTES_NO_PE_MODE 0xAA 46 | 47 | #define MX25R6435F_CHIP_ERASE_MAX_TIME 240000 48 | #define MX25R6435F_BLOCK_ERASE_MAX_TIME 3500 49 | #define MX25R6435F_SUBBLOCK_ERASE_MAX_TIME 3000 50 | #define MX25R6435F_SECTOR_ERASE_MAX_TIME 240 51 | 52 | /** 53 | * @brief MX25R6435F Commands 54 | */ 55 | /* Read Operations */ 56 | #define READ_CMD 0x03 57 | #define FAST_READ_CMD 0x0B 58 | #define DUAL_OUT_READ_CMD 0x3B 59 | #define DUAL_INOUT_READ_CMD 0xBB 60 | #define QUAD_OUT_READ_CMD 0x6B 61 | #define QUAD_INOUT_READ_CMD 0xEB 62 | 63 | /* Program Operations */ 64 | #define PAGE_PROG_CMD 0x02 65 | #define QUAD_PAGE_PROG_CMD 0x38 66 | 67 | /* Erase Operations */ 68 | #define SECTOR_ERASE_CMD 0x20 69 | #define SUBBLOCK_ERASE_CMD 0x52 70 | #define BLOCK_ERASE_CMD 0xD8 71 | #define CHIP_ERASE_CMD 0x60 72 | #define CHIP_ERASE_CMD_2 0xC7 73 | 74 | #define PROG_ERASE_RESUME_CMD 0x7A 75 | #define PROG_ERASE_RESUME_CMD_2 0x30 76 | #define PROG_ERASE_SUSPEND_CMD 0x75 77 | #define PROG_ERASE_SUSPEND_CMD_2 0xB0 78 | 79 | /* Identification Operations */ 80 | #define READ_ID_CMD 0x9F 81 | #define READ_ELECTRONIC_ID_CMD 0xAB 82 | #define READ_ELEC_MANUFACTURER_DEVICE_ID_CMD 0x90 83 | #define READ_SERIAL_FLASH_DISCO_PARAM_CMD 0x5A 84 | 85 | /* Write Operations */ 86 | #define WRITE_ENABLE_CMD 0x06 87 | #define WRITE_DISABLE_CMD 0x04 88 | 89 | /* Register Operations */ 90 | #define READ_STATUS_REG_CMD 0x05 91 | #define READ_CFG_REG_CMD 0x15 92 | #define WRITE_STATUS_CFG_REG_CMD 0x01 93 | 94 | #define READ_SEC_REG_CMD 0x2B 95 | #define WRITE_SEC_REG_CMD 0x2F 96 | 97 | /* Power Down Operations */ 98 | #define DEEP_POWER_DOWN_CMD 0xB9 99 | 100 | /* Burst Operations */ 101 | #define SET_BURST_LENGTH_CMD 0xC0 102 | 103 | /* One-Time Programmable Operations */ 104 | #define ENTER_SECURED_OTP_CMD 0xB1 105 | #define EXIT_SECURED_OTP_CMD 0xC1 106 | 107 | /* No Operation */ 108 | #define NO_OPERATION_CMD 0x00 109 | 110 | /* Reset Operations */ 111 | #define RESET_ENABLE_CMD 0x66 112 | #define RESET_MEMORY_CMD 0x99 113 | #define RELEASE_READ_ENHANCED_CMD 0xFF 114 | 115 | /** 116 | * @brief MX25R6435F Registers 117 | */ 118 | /* Status Register */ 119 | #define MX25R6435F_SR_WIP ((uint8_t)0x01) /*!< Write in progress */ 120 | #define MX25R6435F_SR_WEL ((uint8_t)0x02) /*!< Write enable latch */ 121 | #define MX25R6435F_SR_BP ((uint8_t)0x3C) /*!< Block protect */ 122 | #define MX25R6435F_SR_QE ((uint8_t)0x40) /*!< Quad enable */ 123 | #define MX25R6435F_SR_SRWD ((uint8_t)0x80) /*!< Status register write disable */ 124 | 125 | /* Configuration Register 1 */ 126 | #define MX25R6435F_CR1_TB ((uint8_t)0x08) /*!< Top / bottom */ 127 | 128 | /* Configuration Register 2 */ 129 | #define MX25R6435F_CR2_LH_SWITCH ((uint8_t)0x02) /*!< Low power / high performance switch */ 130 | 131 | /* Security Register */ 132 | #define MX25R6435F_SECR_SOI ((uint8_t)0x01) /*!< Secured OTP indicator */ 133 | #define MX25R6435F_SECR_LDSO ((uint8_t)0x02) /*!< Lock-down secured OTP */ 134 | #define MX25R6435F_SECR_PSB ((uint8_t)0x04) /*!< Program suspend bit */ 135 | #define MX25R6435F_SECR_ESB ((uint8_t)0x08) /*!< Erase suspend bit */ 136 | #define MX25R6435F_SECR_P_FAIL ((uint8_t)0x20) /*!< Program fail flag */ 137 | #define MX25R6435F_SECR_E_FAIL ((uint8_t)0x40) /*!< Erase fail flag */ 138 | 139 | #ifdef __cplusplus 140 | } 141 | #endif 142 | 143 | #endif /* __MX25R6435F_H */ 144 | 145 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 146 | -------------------------------------------------------------------------------- /src/mx25r6435f_driver.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file mx25r6435f_driver.c 4 | * @brief This file includes a standard driver for the MX25R6435F QSPI 5 | * memory. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | /* Includes ------------------------------------------------------------------*/ 25 | #include "core_debug.h" 26 | #include "mx25r6435f_driver.h" 27 | 28 | /* Private constants --------------------------------------------------------*/ 29 | #define QSPI_QUAD_DISABLE 0x0 30 | #define QSPI_QUAD_ENABLE 0x1 31 | 32 | #define QSPI_HIGH_PERF_DISABLE 0x0 33 | #define QSPI_HIGH_PERF_ENABLE 0x1 34 | 35 | /* Private functions ---------------------------------------------------------*/ 36 | static uint8_t QSPI_ResetMemory(XSPI_HandleTypeDef *hxspi); 37 | static uint8_t QSPI_WriteEnable(XSPI_HandleTypeDef *hxspi); 38 | static uint8_t QSPI_AutoPollingMemReady(XSPI_HandleTypeDef *hxspi, uint32_t Timeout); 39 | static uint8_t QSPI_QuadMode(XSPI_HandleTypeDef *hxspi, uint8_t Operation); 40 | static uint8_t QSPI_HighPerfMode(XSPI_HandleTypeDef *hxspi, uint8_t Operation); 41 | static uint8_t qspi_setClockPrescaler(void); 42 | 43 | /* Exported functions ---------------------------------------------------------*/ 44 | /** 45 | * @brief Select a prescaler to have a clock frequency lower than the maximum. 46 | * The MX25R6435F supports a maximum frequency of 80MHz. 47 | * QSPI clock is connected to AHB bus clock. 48 | * @retval Clock prescaler. 0 means error. 49 | */ 50 | static uint8_t qspi_setClockPrescaler(void) 51 | { 52 | uint8_t i; 53 | 54 | for (i = 1; i < 255; i++) { 55 | if ((HAL_RCC_GetHCLKFreq() / i) <= 80000000) { 56 | return i; 57 | } 58 | } 59 | 60 | return 0; 61 | } 62 | 63 | /** 64 | * @brief Initializes the QSPI interface. 65 | * @param obj : pointer to QSPI_t structure 66 | * @retval QSPI memory status 67 | */ 68 | uint8_t BSP_QSPI_Init(QSPI_t *obj) 69 | { 70 | if (obj == NULL) { 71 | return QSPI_ERROR; 72 | } 73 | XSPI_HandleTypeDef *handle = &(obj->handle); 74 | 75 | /* Determine the XSPI to use */ 76 | XSPI_TypeDef *xspi_d0 = pinmap_peripheral(obj->pin_d0, PinMap_XSPI_DATA0); 77 | XSPI_TypeDef *xspi_d1 = pinmap_peripheral(obj->pin_d1, PinMap_XSPI_DATA1); 78 | XSPI_TypeDef *xspi_d2 = pinmap_peripheral(obj->pin_d2, PinMap_XSPI_DATA2); 79 | XSPI_TypeDef *xspi_d3 = pinmap_peripheral(obj->pin_d3, PinMap_XSPI_DATA3); 80 | 81 | XSPI_TypeDef *xspi_sclk = pinmap_peripheral(obj->pin_sclk, PinMap_XSPI_SCLK); 82 | XSPI_TypeDef *xspi_ssel = pinmap_peripheral(obj->pin_ssel, PinMap_XSPI_SSEL); 83 | 84 | /* Pins Dx/SSEL/SCLK must not be NP. */ 85 | if (xspi_d0 == NP || xspi_d1 == NP || xspi_d2 == NP || xspi_sclk == NP || xspi_ssel == NP) { 86 | core_debug("ERROR: at least one QSPI pin has no peripheral\n"); 87 | return QSPI_ERROR; 88 | } 89 | 90 | XSPI_TypeDef *spi_d01 = pinmap_merge_peripheral(xspi_d0, xspi_d1); 91 | XSPI_TypeDef *spi_d23 = pinmap_merge_peripheral(xspi_d2, xspi_d3); 92 | XSPI_TypeDef *spi_dx = pinmap_merge_peripheral(spi_d01, spi_d23); 93 | XSPI_TypeDef *spi_sxxx = pinmap_merge_peripheral(xspi_sclk, xspi_ssel); 94 | 95 | obj->qspi = pinmap_merge_peripheral(spi_dx, spi_sxxx); 96 | 97 | /* Are all pins connected to the same SPI instance? */ 98 | if (obj->qspi == NP) { 99 | core_debug("ERROR: QSPI pins mismatch\n"); 100 | return QSPI_ERROR; 101 | } 102 | 103 | handle->Instance = obj->qspi; 104 | 105 | /* Call the DeInit function to reset the driver */ 106 | if (HAL_XSPI_DeInit(handle) != HAL_OK) { 107 | return QSPI_ERROR; 108 | } 109 | 110 | /* System level initialization */ 111 | BSP_QSPI_MspInit(obj); 112 | 113 | #ifdef OCTOSPI 114 | /* OSPI initialization */ 115 | handle->Init.FifoThreshold = 4; 116 | handle->Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE; 117 | handle->Init.MemoryType = HAL_OSPI_MEMTYPE_MACRONIX; 118 | handle->Init.DeviceSize = POSITION_VAL(MX25R6435F_FLASH_SIZE); 119 | handle->Init.ChipSelectHighTime = 1; 120 | handle->Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE; 121 | handle->Init.ClockMode = HAL_OSPI_CLOCK_MODE_0; 122 | handle->Init.ClockPrescaler = 4; /* QSPI clock = 110MHz / ClockPrescaler = 27.5 MHz */ 123 | handle->Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE; 124 | handle->Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE; 125 | handle->Init.ChipSelectBoundary = 0; 126 | handle->Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_USED; 127 | #else /* OCTOSPI */ 128 | /* QSPI initialization */ 129 | /* High performance mode clock is limited to 80 MHz */ 130 | handle->Init.ClockPrescaler = qspi_setClockPrescaler() + 1; /* QSPI clock = systemCoreClock / (ClockPrescaler+1) */ 131 | handle->Init.FifoThreshold = 4; 132 | handle->Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE; 133 | handle->Init.FlashSize = POSITION_VAL(MX25R6435F_FLASH_SIZE) - 1; 134 | handle->Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE; 135 | handle->Init.ClockMode = QSPI_CLOCK_MODE_0; 136 | #endif 137 | 138 | if (HAL_XSPI_Init(handle) != HAL_OK) { 139 | return QSPI_ERROR; 140 | } 141 | 142 | /* QSPI memory reset */ 143 | if (QSPI_ResetMemory(handle) != QSPI_OK) { 144 | return QSPI_NOT_SUPPORTED; 145 | } 146 | 147 | /* QSPI quad enable */ 148 | if (QSPI_QuadMode(handle, QSPI_QUAD_ENABLE) != QSPI_OK) { 149 | return QSPI_ERROR; 150 | } 151 | 152 | /* High performance mode enable */ 153 | if (QSPI_HighPerfMode(handle, QSPI_HIGH_PERF_ENABLE) != QSPI_OK) { 154 | return QSPI_ERROR; 155 | } 156 | 157 | /* Re-configure the clock for the high performance mode */ 158 | /* High performance mode clock is limited to 80 MHz */ 159 | handle->Init.ClockPrescaler = qspi_setClockPrescaler(); /* QSPI clock = systemCoreClock / (ClockPrescaler+1) */ 160 | 161 | if (HAL_XSPI_Init(handle) != HAL_OK) { 162 | return QSPI_ERROR; 163 | } 164 | 165 | if (HAL_XSPI_Init(handle) != HAL_OK) { 166 | return QSPI_ERROR; 167 | } 168 | 169 | return QSPI_OK; 170 | } 171 | 172 | /** 173 | * @brief De-Initializes the QSPI interface. 174 | * @param obj : pointer to QSPI_t structure 175 | * @retval QSPI memory status 176 | */ 177 | uint8_t BSP_QSPI_DeInit(QSPI_t *obj) 178 | { 179 | XSPI_HandleTypeDef *handle = &(obj->handle); 180 | 181 | /* Call the DeInit function to reset the driver */ 182 | if (HAL_XSPI_DeInit(handle) != HAL_OK) { 183 | return QSPI_ERROR; 184 | } 185 | 186 | /* System level De-initialization */ 187 | BSP_QSPI_MspDeInit(obj); 188 | 189 | return QSPI_OK; 190 | } 191 | 192 | /** 193 | * @brief Reads an amount of data from the QSPI memory. 194 | * @param obj : pointer to QSPI_t structure 195 | * @param pData : Pointer to data to be read 196 | * @param ReadAddr : Read start address 197 | * @param Size : Size of data to read 198 | * @retval QSPI memory status 199 | */ 200 | uint8_t BSP_QSPI_Read(QSPI_t *obj, uint8_t *pData, uint32_t ReadAddr, uint32_t Size) 201 | { 202 | XSPI_HandleTypeDef *handle = &(obj->handle); 203 | #ifdef OCTOSPI 204 | OSPI_RegularCmdTypeDef sCommand; 205 | 206 | /* Initialize the read command */ 207 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 208 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 209 | sCommand.Instruction = QUAD_INOUT_READ_CMD; 210 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 211 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 212 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 213 | sCommand.Address = ReadAddr; 214 | sCommand.AddressMode = HAL_OSPI_ADDRESS_4_LINES; 215 | sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; 216 | sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; 217 | sCommand.AlternateBytes = MX25R6435F_ALT_BYTES_NO_PE_MODE; 218 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_4_LINES; 219 | sCommand.AlternateBytesSize = HAL_OSPI_ALTERNATE_BYTES_8_BITS; 220 | sCommand.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; 221 | sCommand.DataMode = HAL_OSPI_DATA_4_LINES; 222 | sCommand.NbData = Size; 223 | sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; 224 | sCommand.DummyCycles = MX25R6435F_DUMMY_CYCLES_READ_QUAD; 225 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 226 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 227 | 228 | #else /* OCTOSPI */ 229 | QSPI_CommandTypeDef sCommand; 230 | 231 | /* Initialize the read command */ 232 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 233 | sCommand.Instruction = QUAD_INOUT_READ_CMD; 234 | sCommand.AddressMode = QSPI_ADDRESS_4_LINES; 235 | sCommand.AddressSize = QSPI_ADDRESS_24_BITS; 236 | sCommand.Address = ReadAddr; 237 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; 238 | sCommand.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; 239 | sCommand.AlternateBytes = MX25R6435F_ALT_BYTES_NO_PE_MODE; 240 | sCommand.DataMode = QSPI_DATA_4_LINES; 241 | sCommand.DummyCycles = MX25R6435F_DUMMY_CYCLES_READ_QUAD; 242 | sCommand.NbData = Size; 243 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 244 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 245 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 246 | #endif /* OCTOSPI */ 247 | 248 | /* Configure the command */ 249 | if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 250 | return QSPI_ERROR; 251 | } 252 | 253 | /* Reception of the data */ 254 | if (HAL_XSPI_Receive(handle, pData, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 255 | return QSPI_ERROR; 256 | } 257 | 258 | return QSPI_OK; 259 | } 260 | 261 | /** 262 | * @brief Writes an amount of data to the QSPI memory. 263 | * @param obj : pointer to QSPI_t structure 264 | * @param pData : Pointer to data to be written 265 | * @param WriteAddr : Write start address 266 | * @param Size : Size of data to write 267 | * @retval QSPI memory status 268 | */ 269 | uint8_t BSP_QSPI_Write(QSPI_t *obj, uint8_t *pData, uint32_t WriteAddr, uint32_t Size) 270 | { 271 | XSPI_HandleTypeDef *handle = &(obj->handle); 272 | uint32_t end_addr, current_size, current_addr; 273 | 274 | /* Calculation of the size between the write address and the end of the page */ 275 | current_size = MX25R6435F_PAGE_SIZE - (WriteAddr % MX25R6435F_PAGE_SIZE); 276 | 277 | /* Check if the size of the data is less than the remaining place in the page */ 278 | if (current_size > Size) { 279 | current_size = Size; 280 | } 281 | 282 | /* Initialize the adress variables */ 283 | current_addr = WriteAddr; 284 | end_addr = WriteAddr + Size; 285 | 286 | #ifdef OCTOSPI 287 | OSPI_RegularCmdTypeDef sCommand; 288 | 289 | /* Initialize the program command */ 290 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 291 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 292 | sCommand.Instruction = QUAD_PAGE_PROG_CMD; 293 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 294 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 295 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 296 | sCommand.AddressMode = HAL_OSPI_ADDRESS_4_LINES; 297 | sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; 298 | sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; 299 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 300 | sCommand.DataMode = HAL_OSPI_DATA_4_LINES; 301 | sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; 302 | sCommand.DummyCycles = 0; 303 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 304 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 305 | #else /* OCTOSPI */ 306 | QSPI_CommandTypeDef sCommand; 307 | 308 | /* Initialize the program command */ 309 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 310 | sCommand.Instruction = QUAD_PAGE_PROG_CMD; 311 | sCommand.AddressMode = QSPI_ADDRESS_4_LINES; 312 | sCommand.AddressSize = QSPI_ADDRESS_24_BITS; 313 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 314 | sCommand.DataMode = QSPI_DATA_4_LINES; 315 | sCommand.DummyCycles = 0; 316 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 317 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 318 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 319 | #endif /* OCTOSPI */ 320 | 321 | /* Perform the write page by page */ 322 | do { 323 | sCommand.Address = current_addr; 324 | sCommand.NbData = current_size; 325 | 326 | /* Enable write operations */ 327 | if (QSPI_WriteEnable(handle) != QSPI_OK) { 328 | return QSPI_ERROR; 329 | } 330 | 331 | /* Configure the command */ 332 | if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 333 | return QSPI_ERROR; 334 | } 335 | 336 | /* Transmission of the data */ 337 | if (HAL_XSPI_Transmit(handle, pData, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 338 | return QSPI_ERROR; 339 | } 340 | 341 | /* Configure automatic polling mode to wait for end of program */ 342 | if (QSPI_AutoPollingMemReady(handle, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) { 343 | return QSPI_ERROR; 344 | } 345 | 346 | /* Update the address and size variables for next page programming */ 347 | current_addr += current_size; 348 | pData += current_size; 349 | current_size = ((current_addr + MX25R6435F_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : MX25R6435F_PAGE_SIZE; 350 | } while (current_addr < end_addr); 351 | 352 | return QSPI_OK; 353 | } 354 | 355 | /** 356 | * @brief Erases the specified block of the QSPI memory. 357 | * @param obj : pointer to QSPI_t structure 358 | * @param BlockAddress : Block address to erase 359 | * @retval QSPI memory status 360 | */ 361 | uint8_t BSP_QSPI_Erase_Block(QSPI_t *obj, uint32_t BlockAddress) 362 | { 363 | XSPI_HandleTypeDef *handle = &(obj->handle); 364 | #ifdef OCTOSPI 365 | OSPI_RegularCmdTypeDef sCommand; 366 | 367 | /* Initialize the erase command */ 368 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 369 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 370 | sCommand.Instruction = BLOCK_ERASE_CMD; 371 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 372 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 373 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 374 | sCommand.Address = BlockAddress; 375 | sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE; 376 | sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; 377 | sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; 378 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 379 | sCommand.DataMode = HAL_OSPI_DATA_NONE; 380 | sCommand.DummyCycles = 0; 381 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 382 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 383 | #else /* OCTOSPI */ 384 | QSPI_CommandTypeDef sCommand; 385 | 386 | /* Initialize the erase command */ 387 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 388 | sCommand.Instruction = BLOCK_ERASE_CMD; 389 | sCommand.AddressMode = QSPI_ADDRESS_1_LINE; 390 | sCommand.AddressSize = QSPI_ADDRESS_24_BITS; 391 | sCommand.Address = BlockAddress; 392 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 393 | sCommand.DataMode = QSPI_DATA_NONE; 394 | sCommand.DummyCycles = 0; 395 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 396 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 397 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 398 | #endif /* OCTOSPI */ 399 | 400 | /* Enable write operations */ 401 | if (QSPI_WriteEnable(handle) != QSPI_OK) { 402 | return QSPI_ERROR; 403 | } 404 | 405 | /* Send the command */ 406 | if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 407 | return QSPI_ERROR; 408 | } 409 | 410 | /* Configure automatic polling mode to wait for end of erase */ 411 | if (QSPI_AutoPollingMemReady(handle, MX25R6435F_BLOCK_ERASE_MAX_TIME) != QSPI_OK) { 412 | return QSPI_ERROR; 413 | } 414 | return QSPI_OK; 415 | } 416 | 417 | /** 418 | * @brief Erases the specified sector of the QSPI memory. 419 | * @param obj : pointer to QSPI_t structure 420 | * @param Sector : Sector address to erase (0 to 255) 421 | * @retval QSPI memory status 422 | * @note This function is non blocking meaning that sector erase 423 | * operation is started but not completed when the function 424 | * returns. Application has to call BSP_QSPI_GetStatus() 425 | * to know when the device is available again (i.e. erase operation 426 | * completed). 427 | */ 428 | uint8_t BSP_QSPI_Erase_Sector(QSPI_t *obj, uint32_t Sector) 429 | { 430 | XSPI_HandleTypeDef *handle = &(obj->handle); 431 | 432 | if (Sector >= (uint32_t)(MX25R6435F_FLASH_SIZE / MX25R6435F_SECTOR_SIZE)) { 433 | return QSPI_ERROR; 434 | } 435 | 436 | #ifdef OCTOSPI 437 | OSPI_RegularCmdTypeDef sCommand; 438 | 439 | /* Initialize the erase command */ 440 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 441 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 442 | sCommand.Instruction = SECTOR_ERASE_CMD; 443 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 444 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 445 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 446 | sCommand.Address = (Sector * MX25R6435F_SECTOR_SIZE); 447 | sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE; 448 | sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; 449 | sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; 450 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 451 | sCommand.DataMode = HAL_OSPI_DATA_NONE; 452 | sCommand.DummyCycles = 0; 453 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 454 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 455 | #else /* OCTOSPI */ 456 | QSPI_CommandTypeDef sCommand; 457 | 458 | /* Initialize the erase command */ 459 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 460 | sCommand.Instruction = SECTOR_ERASE_CMD; 461 | sCommand.AddressMode = QSPI_ADDRESS_1_LINE; 462 | sCommand.AddressSize = QSPI_ADDRESS_24_BITS; 463 | sCommand.Address = (Sector * MX25R6435F_SECTOR_SIZE); 464 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 465 | sCommand.DataMode = QSPI_DATA_NONE; 466 | sCommand.DummyCycles = 0; 467 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 468 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 469 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 470 | #endif /* OCTOSPI */ 471 | 472 | /* Enable write operations */ 473 | if (QSPI_WriteEnable(handle) != QSPI_OK) { 474 | return QSPI_ERROR; 475 | } 476 | 477 | /* Send the command */ 478 | if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 479 | return QSPI_ERROR; 480 | } 481 | 482 | return QSPI_OK; 483 | } 484 | 485 | /** 486 | * @brief Erases the entire QSPI memory. 487 | * @param obj : pointer to QSPI_t structure 488 | * @retval QSPI memory status 489 | */ 490 | uint8_t BSP_QSPI_Erase_Chip(QSPI_t *obj) 491 | { 492 | XSPI_HandleTypeDef *handle = &(obj->handle); 493 | 494 | #ifdef OCTOSPI 495 | OSPI_RegularCmdTypeDef sCommand; 496 | 497 | /* Initialize the erase command */ 498 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 499 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 500 | sCommand.Instruction = CHIP_ERASE_CMD; 501 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 502 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 503 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 504 | sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; 505 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 506 | sCommand.DataMode = HAL_OSPI_DATA_NONE; 507 | sCommand.DummyCycles = 0; 508 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 509 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 510 | #else /* OCTOSPI */ 511 | QSPI_CommandTypeDef sCommand; 512 | 513 | /* Initialize the erase command */ 514 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 515 | sCommand.Instruction = CHIP_ERASE_CMD; 516 | sCommand.AddressMode = QSPI_ADDRESS_NONE; 517 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 518 | sCommand.DataMode = QSPI_DATA_NONE; 519 | sCommand.DummyCycles = 0; 520 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 521 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 522 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 523 | #endif /* OCTOSPI */ 524 | 525 | /* Enable write operations */ 526 | if (QSPI_WriteEnable(handle) != QSPI_OK) { 527 | return QSPI_ERROR; 528 | } 529 | 530 | /* Send the command */ 531 | if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 532 | return QSPI_ERROR; 533 | } 534 | 535 | /* Configure automatic polling mode to wait for end of erase */ 536 | if (QSPI_AutoPollingMemReady(handle, MX25R6435F_CHIP_ERASE_MAX_TIME) != QSPI_OK) { 537 | return QSPI_ERROR; 538 | } 539 | 540 | return QSPI_OK; 541 | } 542 | 543 | /** 544 | * @brief Reads current status of the QSPI memory. 545 | * @param obj : pointer to QSPI_t structure 546 | * @retval QSPI memory status 547 | */ 548 | uint8_t BSP_QSPI_GetStatus(QSPI_t *obj) 549 | { 550 | XSPI_HandleTypeDef *handle = &(obj->handle); 551 | uint8_t reg; 552 | #ifdef OCTOSPI 553 | OSPI_RegularCmdTypeDef sCommand; 554 | 555 | /* Initialize the read security register command */ 556 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 557 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 558 | sCommand.Instruction = READ_SEC_REG_CMD; 559 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 560 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 561 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 562 | sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; 563 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 564 | sCommand.DataMode = HAL_OSPI_DATA_1_LINE; 565 | sCommand.NbData = 1; 566 | sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; 567 | sCommand.DummyCycles = 0; 568 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 569 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 570 | #else /* OCTOSPI */ 571 | QSPI_CommandTypeDef sCommand; 572 | 573 | /* Initialize the read security register command */ 574 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 575 | sCommand.Instruction = READ_SEC_REG_CMD; 576 | sCommand.AddressMode = QSPI_ADDRESS_NONE; 577 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 578 | sCommand.DataMode = QSPI_DATA_1_LINE; 579 | sCommand.DummyCycles = 0; 580 | sCommand.NbData = 1; 581 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 582 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 583 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 584 | #endif /* OCTOSPI */ 585 | 586 | /* Configure the command */ 587 | if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 588 | return QSPI_ERROR; 589 | } 590 | 591 | /* Reception of the data */ 592 | if (HAL_XSPI_Receive(handle, ®, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 593 | return QSPI_ERROR; 594 | } 595 | 596 | /* Check the value of the register */ 597 | if ((reg & (MX25R6435F_SECR_P_FAIL | MX25R6435F_SECR_E_FAIL)) != 0) { 598 | return QSPI_ERROR; 599 | } else if ((reg & (MX25R6435F_SECR_PSB | MX25R6435F_SECR_ESB)) != 0) { 600 | return QSPI_SUSPENDED; 601 | } 602 | 603 | /* Initialize the read status register command */ 604 | sCommand.Instruction = READ_STATUS_REG_CMD; 605 | 606 | /* Configure the command */ 607 | if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 608 | return QSPI_ERROR; 609 | } 610 | 611 | /* Reception of the data */ 612 | if (HAL_XSPI_Receive(handle, ®, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 613 | return QSPI_ERROR; 614 | } 615 | 616 | /* Check the value of the register */ 617 | if ((reg & MX25R6435F_SR_WIP) != 0) { 618 | return QSPI_BUSY; 619 | } else { 620 | return QSPI_OK; 621 | } 622 | } 623 | 624 | /** 625 | * @brief Return the configuration of the QSPI memory. 626 | * @param pInfo : pointer on the configuration structure 627 | * @retval QSPI memory status 628 | */ 629 | uint8_t BSP_QSPI_GetInfo(QSPI_Info *pInfo) 630 | { 631 | /* Configure the structure with the memory configuration */ 632 | pInfo->FlashSize = MX25R6435F_FLASH_SIZE; 633 | pInfo->EraseSectorSize = MX25R6435F_SECTOR_SIZE; 634 | pInfo->EraseSectorsNumber = (MX25R6435F_FLASH_SIZE / MX25R6435F_SECTOR_SIZE); 635 | pInfo->ProgPageSize = MX25R6435F_PAGE_SIZE; 636 | pInfo->ProgPagesNumber = (MX25R6435F_FLASH_SIZE / MX25R6435F_PAGE_SIZE); 637 | 638 | return QSPI_OK; 639 | } 640 | 641 | /** 642 | * @brief Configure the QSPI in memory-mapped mode 643 | * @param obj : pointer to QSPI_t structure 644 | * @retval QSPI memory status 645 | */ 646 | uint8_t BSP_QSPI_EnableMemoryMappedMode(QSPI_t *obj) 647 | { 648 | XSPI_HandleTypeDef *handle = &(obj->handle); 649 | 650 | #ifdef OCTOSPI 651 | OSPI_RegularCmdTypeDef sCommand; 652 | OSPI_MemoryMappedTypeDef sMemMappedCfg; 653 | 654 | /* Configure the command for the read instruction */ 655 | sCommand.OperationType = HAL_OSPI_OPTYPE_READ_CFG; 656 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 657 | sCommand.Instruction = QUAD_INOUT_READ_CMD; 658 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 659 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 660 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 661 | sCommand.AddressMode = HAL_OSPI_ADDRESS_4_LINES; 662 | sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; 663 | sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; 664 | sCommand.AlternateBytes = MX25R6435F_ALT_BYTES_NO_PE_MODE; 665 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_4_LINES; 666 | sCommand.AlternateBytesSize = HAL_OSPI_ALTERNATE_BYTES_8_BITS; 667 | sCommand.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; 668 | sCommand.DataMode = HAL_OSPI_DATA_4_LINES; 669 | sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; 670 | sCommand.DummyCycles = MX25R6435F_DUMMY_CYCLES_READ_QUAD; 671 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 672 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 673 | 674 | /* Configure the command */ 675 | if (HAL_OSPI_Command(handle, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 676 | return QSPI_ERROR; 677 | } 678 | 679 | /* Configure the command for the program instruction */ 680 | sCommand.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG; 681 | sCommand.Instruction = QUAD_PAGE_PROG_CMD; 682 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 683 | sCommand.DummyCycles = 0; 684 | 685 | /* Configure the command */ 686 | if (HAL_OSPI_Command(handle, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 687 | return QSPI_ERROR; 688 | } 689 | 690 | /* Configure the memory mapped mode */ 691 | sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE; 692 | 693 | if (HAL_OSPI_MemoryMapped(handle, &sMemMappedCfg) != HAL_OK) { 694 | return QSPI_ERROR; 695 | } 696 | #else /* OCTOSPI */ 697 | QSPI_CommandTypeDef sCommand; 698 | QSPI_MemoryMappedTypeDef sMemMappedCfg; 699 | 700 | /* Configure the command for the read instruction */ 701 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 702 | sCommand.Instruction = QUAD_INOUT_READ_CMD; 703 | sCommand.AddressMode = QSPI_ADDRESS_4_LINES; 704 | sCommand.AddressSize = QSPI_ADDRESS_24_BITS; 705 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; 706 | sCommand.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; 707 | sCommand.AlternateBytes = MX25R6435F_ALT_BYTES_NO_PE_MODE; 708 | sCommand.DataMode = QSPI_DATA_4_LINES; 709 | sCommand.DummyCycles = MX25R6435F_DUMMY_CYCLES_READ_QUAD; 710 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 711 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 712 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 713 | 714 | /* Configure the memory mapped mode */ 715 | sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE; 716 | 717 | if (HAL_QSPI_MemoryMapped(handle, &sCommand, &sMemMappedCfg) != HAL_OK) { 718 | return QSPI_ERROR; 719 | } 720 | #endif /* OCTOSPI */ 721 | 722 | return QSPI_OK; 723 | } 724 | 725 | /** 726 | * @brief This function suspends an ongoing erase command. 727 | * @param obj : pointer to QSPI_t structure 728 | * @retval QSPI memory status 729 | */ 730 | uint8_t BSP_QSPI_SuspendErase(QSPI_t *obj) 731 | { 732 | XSPI_HandleTypeDef *handle = &(obj->handle); 733 | 734 | /* Check whether the device is busy (erase operation is 735 | in progress). 736 | */ 737 | if (BSP_QSPI_GetStatus(obj) == QSPI_BUSY) { 738 | #ifdef OCTOSPI 739 | OSPI_RegularCmdTypeDef sCommand; 740 | 741 | /* Initialize the suspend command */ 742 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 743 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 744 | sCommand.Instruction = PROG_ERASE_SUSPEND_CMD; 745 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 746 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 747 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 748 | sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; 749 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 750 | sCommand.DataMode = HAL_OSPI_DATA_NONE; 751 | sCommand.DummyCycles = 0; 752 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 753 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 754 | #else /* OCTOSPI */ 755 | QSPI_CommandTypeDef sCommand; 756 | 757 | /* Initialize the erase command */ 758 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 759 | sCommand.Instruction = PROG_ERASE_SUSPEND_CMD; 760 | sCommand.AddressMode = QSPI_ADDRESS_NONE; 761 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 762 | sCommand.DataMode = QSPI_DATA_NONE; 763 | sCommand.DummyCycles = 0; 764 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 765 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 766 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 767 | #endif /* OCTOSPI */ 768 | /* Send the command */ 769 | if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 770 | return QSPI_ERROR; 771 | } 772 | 773 | if (BSP_QSPI_GetStatus(obj) == QSPI_SUSPENDED) { 774 | return QSPI_OK; 775 | } 776 | 777 | return QSPI_ERROR; 778 | } 779 | 780 | return QSPI_OK; 781 | } 782 | 783 | /** 784 | * @brief This function resumes a paused erase command. 785 | * @param obj : pointer to QSPI_t structure 786 | * @retval QSPI memory status 787 | */ 788 | uint8_t BSP_QSPI_ResumeErase(QSPI_t *obj) 789 | { 790 | XSPI_HandleTypeDef *handle = &(obj->handle); 791 | 792 | /* Check whether the device is in suspended state */ 793 | if (BSP_QSPI_GetStatus(obj) == QSPI_SUSPENDED) { 794 | #ifdef OCTOSPI 795 | OSPI_RegularCmdTypeDef sCommand; 796 | 797 | /* Initialize the resume command */ 798 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 799 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 800 | sCommand.Instruction = PROG_ERASE_RESUME_CMD; 801 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 802 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 803 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 804 | sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; 805 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 806 | sCommand.DataMode = HAL_OSPI_DATA_NONE; 807 | sCommand.DummyCycles = 0; 808 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 809 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 810 | #else /* OCTOSPI */ 811 | QSPI_CommandTypeDef sCommand; 812 | 813 | /* Initialize the erase command */ 814 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 815 | sCommand.Instruction = PROG_ERASE_RESUME_CMD; 816 | sCommand.AddressMode = QSPI_ADDRESS_NONE; 817 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 818 | sCommand.DataMode = QSPI_DATA_NONE; 819 | sCommand.DummyCycles = 0; 820 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 821 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 822 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 823 | #endif /* OCTOSPI */ 824 | /* Send the command */ 825 | if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 826 | return QSPI_ERROR; 827 | } 828 | /* 829 | When this command is executed, the status register write in progress bit is set to 1, and 830 | the flag status register program erase controller bit is set to 0. This command is ignored 831 | if the device is not in a suspended state. 832 | */ 833 | 834 | if (BSP_QSPI_GetStatus(obj) == QSPI_BUSY) { 835 | return QSPI_OK; 836 | } 837 | 838 | return QSPI_ERROR; 839 | } 840 | 841 | return QSPI_OK; 842 | } 843 | 844 | /** 845 | * @brief This function enter the QSPI memory in deep power down mode. 846 | * @param obj : pointer to QSPI_t structure 847 | * @retval QSPI memory status 848 | */ 849 | uint8_t BSP_QSPI_EnterDeepPowerDown(QSPI_t *obj) 850 | { 851 | XSPI_HandleTypeDef *handle = &(obj->handle); 852 | 853 | #ifdef OCTOSPI 854 | OSPI_RegularCmdTypeDef sCommand; 855 | 856 | /* Initialize the deep power down command */ 857 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 858 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 859 | sCommand.Instruction = DEEP_POWER_DOWN_CMD; 860 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 861 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 862 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 863 | sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; 864 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 865 | sCommand.DataMode = HAL_OSPI_DATA_NONE; 866 | sCommand.DummyCycles = 0; 867 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 868 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 869 | #else /* OCTOSPI */ 870 | QSPI_CommandTypeDef sCommand; 871 | 872 | /* Initialize the deep power down command */ 873 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 874 | sCommand.Instruction = DEEP_POWER_DOWN_CMD; 875 | sCommand.AddressMode = QSPI_ADDRESS_NONE; 876 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 877 | sCommand.DataMode = QSPI_DATA_NONE; 878 | sCommand.DummyCycles = 0; 879 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 880 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 881 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 882 | #endif /* OCTOSPI */ 883 | 884 | /* Send the command */ 885 | if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 886 | return QSPI_ERROR; 887 | } 888 | 889 | /* --- Memory takes 10us max to enter deep power down --- */ 890 | /* --- At least 30us should be respected before leaving deep power down --- */ 891 | 892 | return QSPI_OK; 893 | } 894 | 895 | /** 896 | * @brief This function leave the QSPI memory from deep power down mode. 897 | * @param obj : pointer to QSPI_t structure 898 | * @retval QSPI memory status 899 | */ 900 | uint8_t BSP_QSPI_LeaveDeepPowerDown(QSPI_t *obj) 901 | { 902 | XSPI_HandleTypeDef *handle = &(obj->handle); 903 | 904 | #ifdef OCTOSPI 905 | OSPI_RegularCmdTypeDef sCommand; 906 | 907 | /* Initialize the erase command */ 908 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 909 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 910 | sCommand.Instruction = NO_OPERATION_CMD; 911 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 912 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 913 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 914 | sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; 915 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 916 | sCommand.DataMode = HAL_OSPI_DATA_NONE; 917 | sCommand.DummyCycles = 0; 918 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 919 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 920 | #else /* OCTOSPI */ 921 | QSPI_CommandTypeDef sCommand; 922 | 923 | /* Initialize the erase command */ 924 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 925 | sCommand.Instruction = NO_OPERATION_CMD; 926 | sCommand.AddressMode = QSPI_ADDRESS_NONE; 927 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 928 | sCommand.DataMode = QSPI_DATA_NONE; 929 | sCommand.DummyCycles = 0; 930 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 931 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 932 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 933 | #endif /* OCTOSPI */ 934 | 935 | /* Send the command */ 936 | if (HAL_XSPI_Command(handle, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 937 | return QSPI_ERROR; 938 | } 939 | 940 | /* --- A NOP command is sent to the memory, as the nCS should be low for at least 20 ns --- */ 941 | /* --- Memory takes 35us min to leave deep power down --- */ 942 | 943 | return QSPI_OK; 944 | } 945 | 946 | /** 947 | * @brief Initializes the QSPI MSP. 948 | * @param obj : pointer to QSPI_t structure 949 | * @retval None 950 | */ 951 | __weak void BSP_QSPI_MspInit(QSPI_t *obj) 952 | { 953 | #ifdef OCTOSPI 954 | 955 | /* Enable the OctoSPI memory interface clock */ 956 | /* Reset the OctoSPI memory interface */ 957 | #if defined(OCTOSPI1) 958 | if (obj->qspi == OCTOSPI1) { 959 | __HAL_RCC_OSPI1_CLK_ENABLE(); 960 | 961 | __HAL_RCC_OSPI1_FORCE_RESET(); 962 | __HAL_RCC_OSPI1_RELEASE_RESET(); 963 | } 964 | #endif 965 | #if defined(OCTOSPI2) 966 | if (obj->qspi == OCTOSPI2) { 967 | __HAL_RCC_OSPI2_CLK_ENABLE(); 968 | 969 | __HAL_RCC_OSPI2_FORCE_RESET(); 970 | __HAL_RCC_OSPI2_RELEASE_RESET(); 971 | } 972 | #endif 973 | #else /* OCTOSPI */ 974 | /* Enable the QuadSPI memory interface clock */ 975 | __HAL_RCC_QSPI_CLK_ENABLE(); 976 | 977 | /* Reset the QuadSPI memory interface */ 978 | __HAL_RCC_QSPI_FORCE_RESET(); 979 | __HAL_RCC_QSPI_RELEASE_RESET(); 980 | #endif /* OCTOSPI */ 981 | 982 | /* Configure QSPI GPIO pins */ 983 | pinmap_pinout(obj->pin_d0, PinMap_XSPI_DATA0); 984 | pinmap_pinout(obj->pin_d1, PinMap_XSPI_DATA1); 985 | pinmap_pinout(obj->pin_d2, PinMap_XSPI_DATA2); 986 | pinmap_pinout(obj->pin_d3, PinMap_XSPI_DATA3); 987 | pinmap_pinout(obj->pin_sclk, PinMap_XSPI_SCLK); 988 | pinmap_pinout(obj->pin_ssel, PinMap_XSPI_SSEL); 989 | } 990 | 991 | /** 992 | * @brief De-Initializes the QSPI MSP. 993 | * @param obj : pointer to QSPI_t structure 994 | * @retval None 995 | */ 996 | __weak void BSP_QSPI_MspDeInit(QSPI_t *obj) 997 | { 998 | /* QSPI CLK, CS, D0-D3 GPIO pins de-configuration */ 999 | 1000 | HAL_GPIO_DeInit((GPIO_TypeDef *)STM_PORT(obj->pin_d0), STM_GPIO_PIN(obj->pin_d0)); 1001 | HAL_GPIO_DeInit((GPIO_TypeDef *)STM_PORT(obj->pin_d1), STM_GPIO_PIN(obj->pin_d1)); 1002 | HAL_GPIO_DeInit((GPIO_TypeDef *)STM_PORT(obj->pin_d2), STM_GPIO_PIN(obj->pin_d2)); 1003 | HAL_GPIO_DeInit((GPIO_TypeDef *)STM_PORT(obj->pin_d3), STM_GPIO_PIN(obj->pin_d3)); 1004 | HAL_GPIO_DeInit((GPIO_TypeDef *)STM_PORT(obj->pin_sclk), STM_GPIO_PIN(obj->pin_sclk)); 1005 | HAL_GPIO_DeInit((GPIO_TypeDef *)STM_PORT(obj->pin_ssel), STM_GPIO_PIN(obj->pin_ssel)); 1006 | 1007 | #ifdef OCTOSPI 1008 | #if defined(OCTOSPI1) 1009 | /* Reset the OctoSPI memory interface */ 1010 | /* Disable the OctoSPI memory interface clock */ 1011 | if (obj->qspi == OCTOSPI1) { 1012 | __HAL_RCC_OSPI1_FORCE_RESET(); 1013 | __HAL_RCC_OSPI1_RELEASE_RESET(); 1014 | 1015 | __HAL_RCC_OSPI1_CLK_DISABLE(); 1016 | } 1017 | #endif 1018 | #if defined(OCTOSPI2) 1019 | if (obj->qspi == OCTOSPI2) { 1020 | __HAL_RCC_OSPI2_FORCE_RESET(); 1021 | __HAL_RCC_OSPI2_RELEASE_RESET(); 1022 | 1023 | __HAL_RCC_OSPI2_CLK_DISABLE(); 1024 | } 1025 | #endif 1026 | #else /* OCTOSPI */ 1027 | /* Reset the QuadSPI memory interface */ 1028 | __HAL_RCC_QSPI_FORCE_RESET(); 1029 | __HAL_RCC_QSPI_RELEASE_RESET(); 1030 | 1031 | /* Disable the QuadSPI memory interface clock */ 1032 | __HAL_RCC_QSPI_CLK_DISABLE(); 1033 | #endif /* OCTOSPI */ 1034 | } 1035 | 1036 | /** 1037 | * @brief This function reset the QSPI memory. 1038 | * @param hxspi : QSPI handle 1039 | * @retval None 1040 | */ 1041 | static uint8_t QSPI_ResetMemory(XSPI_HandleTypeDef *hxspi) 1042 | { 1043 | #ifdef OCTOSPI 1044 | OSPI_RegularCmdTypeDef sCommand; 1045 | 1046 | /* Initialize the reset enable command */ 1047 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 1048 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 1049 | sCommand.Instruction = RESET_ENABLE_CMD; 1050 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 1051 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 1052 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 1053 | sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; 1054 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 1055 | sCommand.DataMode = HAL_OSPI_DATA_NONE; 1056 | sCommand.DummyCycles = 0; 1057 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 1058 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 1059 | #else /* OCTOSPI */ 1060 | QSPI_CommandTypeDef sCommand; 1061 | 1062 | /* Initialize the reset enable command */ 1063 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 1064 | sCommand.Instruction = RESET_ENABLE_CMD; 1065 | sCommand.AddressMode = QSPI_ADDRESS_NONE; 1066 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 1067 | sCommand.DataMode = QSPI_DATA_NONE; 1068 | sCommand.DummyCycles = 0; 1069 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 1070 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 1071 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 1072 | #endif /* OCTOSPI */ 1073 | 1074 | /* Send the command */ 1075 | if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1076 | return QSPI_ERROR; 1077 | } 1078 | 1079 | /* Send the reset memory command */ 1080 | sCommand.Instruction = RESET_MEMORY_CMD; 1081 | if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1082 | return QSPI_ERROR; 1083 | } 1084 | 1085 | /* Configure automatic polling mode to wait the memory is ready */ 1086 | if (QSPI_AutoPollingMemReady(hxspi, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) { 1087 | return QSPI_ERROR; 1088 | } 1089 | 1090 | return QSPI_OK; 1091 | } 1092 | 1093 | /** 1094 | * @brief This function send a Write Enable and wait it is effective. 1095 | * @param hxspi : QSPI handle 1096 | * @retval None 1097 | */ 1098 | static uint8_t QSPI_WriteEnable(XSPI_HandleTypeDef *hxspi) 1099 | { 1100 | #ifdef OCTOSPI 1101 | OSPI_RegularCmdTypeDef sCommand; 1102 | OSPI_AutoPollingTypeDef sConfig; 1103 | 1104 | /* Enable write operations */ 1105 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 1106 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 1107 | sCommand.Instruction = WRITE_ENABLE_CMD; 1108 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 1109 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 1110 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 1111 | sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; 1112 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 1113 | sCommand.DataMode = HAL_OSPI_DATA_NONE; 1114 | sCommand.DummyCycles = 0; 1115 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 1116 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 1117 | 1118 | if (HAL_OSPI_Command(hxspi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1119 | return QSPI_ERROR; 1120 | } 1121 | 1122 | /* Configure automatic polling mode to wait for write enabling */ 1123 | sConfig.Match = MX25R6435F_SR_WEL; 1124 | sConfig.Mask = MX25R6435F_SR_WEL; 1125 | sConfig.MatchMode = HAL_OSPI_MATCH_MODE_AND; 1126 | sConfig.Interval = 0x10; 1127 | sConfig.AutomaticStop = HAL_OSPI_AUTOMATIC_STOP_ENABLE; 1128 | 1129 | sCommand.Instruction = READ_STATUS_REG_CMD; 1130 | sCommand.DataMode = HAL_OSPI_DATA_1_LINE; 1131 | sCommand.NbData = 1; 1132 | sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; 1133 | 1134 | if (HAL_OSPI_Command(hxspi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1135 | return QSPI_ERROR; 1136 | } 1137 | 1138 | if (HAL_OSPI_AutoPolling(hxspi, &sConfig, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1139 | return QSPI_ERROR; 1140 | } 1141 | #else /* OCTOSPI */ 1142 | QSPI_CommandTypeDef sCommand; 1143 | QSPI_AutoPollingTypeDef sConfig; 1144 | 1145 | /* Enable write operations */ 1146 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 1147 | sCommand.Instruction = WRITE_ENABLE_CMD; 1148 | sCommand.AddressMode = QSPI_ADDRESS_NONE; 1149 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 1150 | sCommand.DataMode = QSPI_DATA_NONE; 1151 | sCommand.DummyCycles = 0; 1152 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 1153 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 1154 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 1155 | 1156 | if (HAL_QSPI_Command(hxspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1157 | return QSPI_ERROR; 1158 | } 1159 | 1160 | /* Configure automatic polling mode to wait for write enabling */ 1161 | sConfig.Match = MX25R6435F_SR_WEL; 1162 | sConfig.Mask = MX25R6435F_SR_WEL; 1163 | sConfig.MatchMode = QSPI_MATCH_MODE_AND; 1164 | sConfig.StatusBytesSize = 1; 1165 | sConfig.Interval = 0x10; 1166 | sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 1167 | 1168 | sCommand.Instruction = READ_STATUS_REG_CMD; 1169 | sCommand.DataMode = QSPI_DATA_1_LINE; 1170 | 1171 | if (HAL_QSPI_AutoPolling(hxspi, &sCommand, &sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1172 | return QSPI_ERROR; 1173 | } 1174 | #endif /* OCTOSPI */ 1175 | 1176 | return QSPI_OK; 1177 | } 1178 | 1179 | /** 1180 | * @brief This function read the SR of the memory and wait the EOP. 1181 | * @param hxspi : QSPI handle 1182 | * @param Timeout : Timeout for auto-polling 1183 | * @retval None 1184 | */ 1185 | static uint8_t QSPI_AutoPollingMemReady(XSPI_HandleTypeDef *hxspi, uint32_t Timeout) 1186 | { 1187 | #ifdef OCTOSPI 1188 | OSPI_RegularCmdTypeDef sCommand; 1189 | OSPI_AutoPollingTypeDef sConfig; 1190 | 1191 | /* Configure automatic polling mode to wait for memory ready */ 1192 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 1193 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 1194 | sCommand.Instruction = READ_STATUS_REG_CMD; 1195 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 1196 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 1197 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 1198 | sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; 1199 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 1200 | sCommand.DataMode = HAL_OSPI_DATA_1_LINE; 1201 | sCommand.NbData = 1; 1202 | sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; 1203 | sCommand.DummyCycles = 0; 1204 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 1205 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 1206 | 1207 | sConfig.Match = 0; 1208 | sConfig.Mask = MX25R6435F_SR_WIP; 1209 | sConfig.MatchMode = HAL_OSPI_MATCH_MODE_AND; 1210 | sConfig.Interval = 0x10; 1211 | sConfig.AutomaticStop = HAL_OSPI_AUTOMATIC_STOP_ENABLE; 1212 | 1213 | if (HAL_OSPI_Command(hxspi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1214 | return QSPI_ERROR; 1215 | } 1216 | 1217 | if (HAL_OSPI_AutoPolling(hxspi, &sConfig, Timeout) != HAL_OK) { 1218 | return QSPI_ERROR; 1219 | } 1220 | #else /* OCTOSPI */ 1221 | QSPI_CommandTypeDef sCommand; 1222 | QSPI_AutoPollingTypeDef sConfig; 1223 | 1224 | /* Configure automatic polling mode to wait for memory ready */ 1225 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 1226 | sCommand.Instruction = READ_STATUS_REG_CMD; 1227 | sCommand.AddressMode = QSPI_ADDRESS_NONE; 1228 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 1229 | sCommand.DataMode = QSPI_DATA_1_LINE; 1230 | sCommand.DummyCycles = 0; 1231 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 1232 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 1233 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 1234 | 1235 | sConfig.Match = 0; 1236 | sConfig.Mask = MX25R6435F_SR_WIP; 1237 | sConfig.MatchMode = QSPI_MATCH_MODE_AND; 1238 | sConfig.StatusBytesSize = 1; 1239 | sConfig.Interval = 0x10; 1240 | sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; 1241 | 1242 | if (HAL_QSPI_AutoPolling(hxspi, &sCommand, &sConfig, Timeout) != HAL_OK) { 1243 | return QSPI_ERROR; 1244 | } 1245 | #endif /* OCTOSPI */ 1246 | 1247 | return QSPI_OK; 1248 | } 1249 | 1250 | /** 1251 | * @brief This function enables/disables the Quad mode of the memory. 1252 | * @param hxspi : QSPI handle 1253 | * @param Operation : QSPI_QUAD_ENABLE or QSPI_QUAD_DISABLE mode 1254 | * @retval None 1255 | */ 1256 | static uint8_t QSPI_QuadMode(XSPI_HandleTypeDef *hxspi, uint8_t Operation) 1257 | { 1258 | uint8_t reg; 1259 | #ifdef OCTOSPI 1260 | OSPI_RegularCmdTypeDef sCommand; 1261 | 1262 | /* Read status register */ 1263 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 1264 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 1265 | sCommand.Instruction = READ_STATUS_REG_CMD; 1266 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 1267 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 1268 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 1269 | sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; 1270 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 1271 | sCommand.DataMode = HAL_OSPI_DATA_1_LINE; 1272 | sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; 1273 | sCommand.DummyCycles = 0; 1274 | sCommand.NbData = 1; 1275 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 1276 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 1277 | #else /* OCTOSPI */ 1278 | QSPI_CommandTypeDef sCommand; 1279 | 1280 | /* Read status register */ 1281 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 1282 | sCommand.Instruction = READ_STATUS_REG_CMD; 1283 | sCommand.AddressMode = QSPI_ADDRESS_NONE; 1284 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 1285 | sCommand.DataMode = QSPI_DATA_1_LINE; 1286 | sCommand.DummyCycles = 0; 1287 | sCommand.NbData = 1; 1288 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 1289 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 1290 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 1291 | #endif /* OCTOSPI */ 1292 | 1293 | if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1294 | return QSPI_ERROR; 1295 | } 1296 | 1297 | if (HAL_XSPI_Receive(hxspi, ®, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1298 | return QSPI_ERROR; 1299 | } 1300 | 1301 | /* Enable write operations */ 1302 | if (QSPI_WriteEnable(hxspi) != QSPI_OK) { 1303 | return QSPI_ERROR; 1304 | } 1305 | 1306 | /* Activate/deactivate the Quad mode */ 1307 | if (Operation == QSPI_QUAD_ENABLE) { 1308 | SET_BIT(reg, MX25R6435F_SR_QE); 1309 | } else { 1310 | CLEAR_BIT(reg, MX25R6435F_SR_QE); 1311 | } 1312 | 1313 | sCommand.Instruction = WRITE_STATUS_CFG_REG_CMD; 1314 | 1315 | if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1316 | return QSPI_ERROR; 1317 | } 1318 | 1319 | if (HAL_XSPI_Transmit(hxspi, ®, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1320 | return QSPI_ERROR; 1321 | } 1322 | 1323 | /* Wait that memory is ready */ 1324 | if (QSPI_AutoPollingMemReady(hxspi, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) { 1325 | return QSPI_ERROR; 1326 | } 1327 | 1328 | /* Check the configuration has been correctly done */ 1329 | sCommand.Instruction = READ_STATUS_REG_CMD; 1330 | 1331 | if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1332 | return QSPI_ERROR; 1333 | } 1334 | 1335 | if (HAL_XSPI_Receive(hxspi, ®, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1336 | return QSPI_ERROR; 1337 | } 1338 | 1339 | if ((((reg & MX25R6435F_SR_QE) == 0) && (Operation == QSPI_QUAD_ENABLE)) || 1340 | (((reg & MX25R6435F_SR_QE) != 0) && (Operation == QSPI_QUAD_DISABLE))) { 1341 | return QSPI_ERROR; 1342 | } 1343 | 1344 | return QSPI_OK; 1345 | } 1346 | 1347 | /** 1348 | * @brief This function enables/disables the high performance mode of the memory. 1349 | * @param hxspi : QSPI handle 1350 | * @param Operation : QSPI_HIGH_PERF_ENABLE or QSPI_HIGH_PERF_DISABLE high performance mode 1351 | * @retval None 1352 | */ 1353 | static uint8_t QSPI_HighPerfMode(XSPI_HandleTypeDef *hxspi, uint8_t Operation) 1354 | { 1355 | uint8_t reg[3]; 1356 | #ifdef OCTOSPI 1357 | OSPI_RegularCmdTypeDef sCommand; 1358 | 1359 | /* Read status register */ 1360 | sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; 1361 | sCommand.FlashId = HAL_OSPI_FLASH_ID_1; 1362 | sCommand.Instruction = READ_STATUS_REG_CMD; 1363 | sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; 1364 | sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; 1365 | sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; 1366 | sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; 1367 | sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; 1368 | sCommand.DataMode = HAL_OSPI_DATA_1_LINE; 1369 | sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; 1370 | sCommand.DummyCycles = 0; 1371 | sCommand.NbData = 1; 1372 | sCommand.DQSMode = HAL_OSPI_DQS_DISABLE; 1373 | sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; 1374 | #else /* OCTOSPI */ 1375 | QSPI_CommandTypeDef sCommand; 1376 | 1377 | /* Read status register */ 1378 | sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; 1379 | sCommand.Instruction = READ_STATUS_REG_CMD; 1380 | sCommand.AddressMode = QSPI_ADDRESS_NONE; 1381 | sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 1382 | sCommand.DataMode = QSPI_DATA_1_LINE; 1383 | sCommand.DummyCycles = 0; 1384 | sCommand.NbData = 1; 1385 | sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; 1386 | sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; 1387 | sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; 1388 | #endif /* OCTOSPI */ 1389 | 1390 | if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1391 | return QSPI_ERROR; 1392 | } 1393 | 1394 | if (HAL_XSPI_Receive(hxspi, &(reg[0]), HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1395 | return QSPI_ERROR; 1396 | } 1397 | 1398 | /* Read configuration registers */ 1399 | sCommand.Instruction = READ_CFG_REG_CMD; 1400 | sCommand.NbData = 2; 1401 | 1402 | if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1403 | return QSPI_ERROR; 1404 | } 1405 | 1406 | if (HAL_XSPI_Receive(hxspi, &(reg[1]), HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1407 | return QSPI_ERROR; 1408 | } 1409 | 1410 | /* Enable write operations */ 1411 | if (QSPI_WriteEnable(hxspi) != QSPI_OK) { 1412 | return QSPI_ERROR; 1413 | } 1414 | 1415 | /* Activate/deactivate the Quad mode */ 1416 | if (Operation == QSPI_HIGH_PERF_ENABLE) { 1417 | SET_BIT(reg[2], MX25R6435F_CR2_LH_SWITCH); 1418 | } else { 1419 | CLEAR_BIT(reg[2], MX25R6435F_CR2_LH_SWITCH); 1420 | } 1421 | 1422 | sCommand.Instruction = WRITE_STATUS_CFG_REG_CMD; 1423 | sCommand.NbData = 3; 1424 | 1425 | if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1426 | return QSPI_ERROR; 1427 | } 1428 | 1429 | if (HAL_XSPI_Transmit(hxspi, &(reg[0]), HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1430 | return QSPI_ERROR; 1431 | } 1432 | 1433 | /* Wait that memory is ready */ 1434 | if (QSPI_AutoPollingMemReady(hxspi, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) { 1435 | return QSPI_ERROR; 1436 | } 1437 | 1438 | /* Check the configuration has been correctly done */ 1439 | sCommand.Instruction = READ_CFG_REG_CMD; 1440 | sCommand.NbData = 2; 1441 | 1442 | if (HAL_XSPI_Command(hxspi, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1443 | return QSPI_ERROR; 1444 | } 1445 | 1446 | if (HAL_XSPI_Receive(hxspi, &(reg[0]), HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { 1447 | return QSPI_ERROR; 1448 | } 1449 | 1450 | if ((((reg[1] & MX25R6435F_CR2_LH_SWITCH) == 0) && (Operation == QSPI_HIGH_PERF_ENABLE)) || 1451 | (((reg[1] & MX25R6435F_CR2_LH_SWITCH) != 0) && (Operation == QSPI_HIGH_PERF_DISABLE))) { 1452 | return QSPI_ERROR; 1453 | } 1454 | 1455 | return QSPI_OK; 1456 | } 1457 | 1458 | #ifdef __cplusplus 1459 | } 1460 | #endif 1461 | 1462 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 1463 | -------------------------------------------------------------------------------- /src/mx25r6435f_driver.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file mx25r6435f_driver.h 4 | * @brief This file contains the common defines and functions prototypes for 5 | * the mx25r6435f_driver.c driver. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

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

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /* Define to prevent recursive inclusion -------------------------------------*/ 21 | #ifndef _MX25R6435F_DRIVER_H 22 | #define _MX25R6435F_DRIVER_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* Includes ------------------------------------------------------------------*/ 29 | #include "stm32_def.h" 30 | #include "PeripheralPins.h" 31 | #include "mx25r6435f_desc.h" 32 | 33 | /* Exported constants --------------------------------------------------------*/ 34 | #if defined(OCTOSPI1) || defined(OCTOSPI2) 35 | #define OCTOSPI 36 | #define XSPI_HandleTypeDef OSPI_HandleTypeDef 37 | #define XSPI_TypeDef OCTOSPI_TypeDef 38 | #define PinMap_XSPI_DATA0 PinMap_OCTOSPI_DATA0 39 | #define PinMap_XSPI_DATA1 PinMap_OCTOSPI_DATA1 40 | #define PinMap_XSPI_DATA2 PinMap_OCTOSPI_DATA2 41 | #define PinMap_XSPI_DATA3 PinMap_OCTOSPI_DATA3 42 | #define PinMap_XSPI_SCLK PinMap_OCTOSPI_SCLK 43 | #define PinMap_XSPI_SSEL PinMap_OCTOSPI_SSEL 44 | #define HAL_XSPI_Init HAL_OSPI_Init 45 | #define HAL_XSPI_DeInit HAL_OSPI_DeInit 46 | #define HAL_XSPI_TIMEOUT_DEFAULT_VALUE HAL_OSPI_TIMEOUT_DEFAULT_VALUE 47 | #define HAL_XSPI_Command HAL_OSPI_Command 48 | #define HAL_XSPI_Transmit HAL_OSPI_Transmit 49 | #define HAL_XSPI_Receive HAL_OSPI_Receive 50 | #elif defined(QUADSPI) 51 | #define XSPI_HandleTypeDef QSPI_HandleTypeDef 52 | #define XSPI_TypeDef QUADSPI_TypeDef 53 | 54 | #if defined(STM32_CORE_VERSION) && (STM32_CORE_VERSION > 0x01090000) 55 | #define PinMap_XSPI_DATA0 PinMap_QUADSPI_DATA0 56 | #define PinMap_XSPI_DATA1 PinMap_QUADSPI_DATA1 57 | #define PinMap_XSPI_DATA2 PinMap_QUADSPI_DATA2 58 | #define PinMap_XSPI_DATA3 PinMap_QUADSPI_DATA3 59 | #define PinMap_XSPI_SCLK PinMap_QUADSPI_SCLK 60 | #define PinMap_XSPI_SSEL PinMap_QUADSPI_SSEL 61 | #else 62 | #define PinMap_XSPI_DATA0 PinMap_QUADSPI 63 | #define PinMap_XSPI_DATA1 PinMap_QUADSPI 64 | #define PinMap_XSPI_DATA2 PinMap_QUADSPI 65 | #define PinMap_XSPI_DATA3 PinMap_QUADSPI 66 | #define PinMap_XSPI_SCLK PinMap_QUADSPI 67 | #define PinMap_XSPI_SSEL PinMap_QUADSPI 68 | #endif 69 | #define HAL_XSPI_Init HAL_QSPI_Init 70 | #define HAL_XSPI_DeInit HAL_QSPI_DeInit 71 | #define HAL_XSPI_TIMEOUT_DEFAULT_VALUE HAL_QPSI_TIMEOUT_DEFAULT_VALUE 72 | #define HAL_XSPI_Command HAL_QSPI_Command 73 | #define HAL_XSPI_Transmit HAL_QSPI_Transmit 74 | #define HAL_XSPI_Receive HAL_QSPI_Receive 75 | #else 76 | #error "QSPI feature not available. MX25R6435F library compilation failed." 77 | #endif /* OCTOSPIx */ 78 | 79 | /* QSPI Error codes */ 80 | #define QSPI_OK ((uint8_t)0x00) 81 | #define QSPI_ERROR ((uint8_t)0x01) 82 | #define QSPI_BUSY ((uint8_t)0x02) 83 | #define QSPI_NOT_SUPPORTED ((uint8_t)0x04) 84 | #define QSPI_SUSPENDED ((uint8_t)0x08) 85 | 86 | /* Exported types ------------------------------------------------------------*/ 87 | /* QSPI Info */ 88 | typedef struct { 89 | uint32_t FlashSize; /*!< Size of the flash */ 90 | uint32_t EraseSectorSize; /*!< Size of sectors for the erase operation */ 91 | uint32_t EraseSectorsNumber; /*!< Number of sectors for the erase operation */ 92 | uint32_t ProgPageSize; /*!< Size of pages for the program operation */ 93 | uint32_t ProgPagesNumber; /*!< Number of pages for the program operation */ 94 | } QSPI_Info; 95 | 96 | 97 | typedef struct { 98 | XSPI_HandleTypeDef handle; 99 | XSPI_TypeDef *qspi; 100 | PinName pin_d0; 101 | PinName pin_d1; 102 | PinName pin_d2; 103 | PinName pin_d3; 104 | PinName pin_sclk; 105 | PinName pin_ssel; 106 | } QSPI_t; 107 | 108 | /* Exported functions --------------------------------------------------------*/ 109 | uint8_t BSP_QSPI_Init(QSPI_t *obj); 110 | uint8_t BSP_QSPI_DeInit(QSPI_t *obj); 111 | uint8_t BSP_QSPI_Read(QSPI_t *obj, uint8_t *pData, uint32_t ReadAddr, uint32_t Size); 112 | uint8_t BSP_QSPI_Write(QSPI_t *obj, uint8_t *pData, uint32_t WriteAddr, uint32_t Size); 113 | uint8_t BSP_QSPI_Erase_Block(QSPI_t *obj, uint32_t BlockAddress); 114 | uint8_t BSP_QSPI_Erase_Sector(QSPI_t *obj, uint32_t Sector); 115 | uint8_t BSP_QSPI_Erase_Chip(QSPI_t *obj); 116 | uint8_t BSP_QSPI_GetStatus(QSPI_t *obj); 117 | uint8_t BSP_QSPI_GetInfo(QSPI_Info *pInfo); 118 | uint8_t BSP_QSPI_EnableMemoryMappedMode(QSPI_t *obj); 119 | uint8_t BSP_QSPI_SuspendErase(QSPI_t *obj); 120 | uint8_t BSP_QSPI_ResumeErase(QSPI_t *obj); 121 | uint8_t BSP_QSPI_EnterDeepPowerDown(QSPI_t *obj); 122 | uint8_t BSP_QSPI_LeaveDeepPowerDown(QSPI_t *obj); 123 | 124 | void BSP_QSPI_MspInit(QSPI_t *obj); 125 | void BSP_QSPI_MspDeInit(QSPI_t *obj); 126 | 127 | #ifdef __cplusplus 128 | } 129 | #endif 130 | 131 | #endif /* _MX25R6435F_DRIVER_H */ 132 | 133 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 134 | --------------------------------------------------------------------------------