From 5c51df3faec292a701448bc7d79c4920b91f549b Mon Sep 17 00:00:00 2001 From: ozpv <39195175+ozpv@users.noreply.github.com> Date: Sat, 15 Aug 2026 17:29:50 -0500 Subject: Add files via git push --- Core/Src/quadspi.c | 713 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 713 insertions(+) create mode 100755 Core/Src/quadspi.c (limited to 'Core/Src/quadspi.c') diff --git a/Core/Src/quadspi.c b/Core/Src/quadspi.c new file mode 100755 index 0000000..5c3efca --- /dev/null +++ b/Core/Src/quadspi.c @@ -0,0 +1,713 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file quadspi.c + * @brief This file provides code for the configuration + * of the QUADSPI instances. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "quadspi.h" + +/* USER CODE BEGIN 0 */ +static uint8_t QSPI_WriteEnable(void); +uint8_t QSPI_AutoPollingMemReady(void); +static uint8_t QSPI_Configuration(void); +static uint8_t QSPI_ResetChip(void); + +/* USER CODE END 0 */ + +QSPI_HandleTypeDef hqspi; + +/* QUADSPI init function */ +void MX_QUADSPI_Init(void) +{ + + /* USER CODE BEGIN QUADSPI_Init 0 */ + + /* USER CODE END QUADSPI_Init 0 */ + + /* USER CODE BEGIN QUADSPI_Init 1 */ + + /* USER CODE END QUADSPI_Init 1 */ + hqspi.Instance = QUADSPI; + hqspi.Init.ClockPrescaler = 2; + hqspi.Init.FifoThreshold = 4; + hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; + hqspi.Init.FlashSize = 23; + hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_2_CYCLE; + hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0; + hqspi.Init.FlashID = QSPI_FLASH_ID_1; + hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE; + if (HAL_QSPI_Init(&hqspi) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN QUADSPI_Init 2 */ + + /* USER CODE END QUADSPI_Init 2 */ + +} + +void HAL_QSPI_MspInit(QSPI_HandleTypeDef* qspiHandle) +{ + + GPIO_InitTypeDef GPIO_InitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + if(qspiHandle->Instance==QUADSPI) + { + /* USER CODE BEGIN QUADSPI_MspInit 0 */ + + /* USER CODE END QUADSPI_MspInit 0 */ + + /** Initializes the peripherals clock + */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_QSPI; + PeriphClkInitStruct.PLL2.PLL2M = 2; + PeriphClkInitStruct.PLL2.PLL2N = 16; + PeriphClkInitStruct.PLL2.PLL2P = 2; + PeriphClkInitStruct.PLL2.PLL2Q = 2; + PeriphClkInitStruct.PLL2.PLL2R = 1; + PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3; + PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE; + PeriphClkInitStruct.PLL2.PLL2FRACN = 0; + PeriphClkInitStruct.QspiClockSelection = RCC_QSPICLKSOURCE_PLL2; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) + { + Error_Handler(); + } + + /* QUADSPI clock enable */ + __HAL_RCC_QSPI_CLK_ENABLE(); + + __HAL_RCC_GPIOF_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + /**QUADSPI GPIO Configuration + PF6 ------> QUADSPI_BK1_IO3 + PF7 ------> QUADSPI_BK1_IO2 + PF8 ------> QUADSPI_BK1_IO0 + PF9 ------> QUADSPI_BK1_IO1 + PF10 ------> QUADSPI_CLK + PG6 ------> QUADSPI_BK1_NCS + */ + GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_10; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI; + HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI; + HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_6; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI; + HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); + + /* USER CODE BEGIN QUADSPI_MspInit 1 */ + + /* USER CODE END QUADSPI_MspInit 1 */ + } +} + +void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef* qspiHandle) +{ + + if(qspiHandle->Instance==QUADSPI) + { + /* USER CODE BEGIN QUADSPI_MspDeInit 0 */ + + /* USER CODE END QUADSPI_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_QSPI_CLK_DISABLE(); + + /**QUADSPI GPIO Configuration + PF6 ------> QUADSPI_BK1_IO3 + PF7 ------> QUADSPI_BK1_IO2 + PF8 ------> QUADSPI_BK1_IO0 + PF9 ------> QUADSPI_BK1_IO1 + PF10 ------> QUADSPI_CLK + PG6 ------> QUADSPI_BK1_NCS + */ + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9 + |GPIO_PIN_10); + + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_6); + + /* USER CODE BEGIN QUADSPI_MspDeInit 1 */ + + /* USER CODE END QUADSPI_MspDeInit 1 */ + } +} + +/* USER CODE BEGIN 1 */ + +static HAL_StatusTypeDef QSPI_ReadStatusRegister(uint8_t command, uint8_t *value) +{ + QSPI_CommandTypeDef sCommand = {0}; + + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = command; + 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 HAL_ERROR; + } + + if (HAL_QSPI_Receive(&hqspi, value, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return HAL_ERROR; + } + + return HAL_OK; +} + +static HAL_StatusTypeDef QSPI_WriteStatusRegister(uint8_t command, uint8_t value) +{ + QSPI_CommandTypeDef sCommand = {0}; + + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = command; + 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 HAL_ERROR; + } + + if (HAL_QSPI_Transmit(&hqspi, + &value, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return HAL_ERROR; + } + + return HAL_OK; +} + +uint8_t CSP_QUADSPI_Init(void) +{ + hqspi.Instance = QUADSPI; + + if (HAL_QSPI_DeInit(&hqspi) != HAL_OK) { + return HAL_ERROR; + } + + MX_QUADSPI_Init(); + + if (QSPI_ResetChip() != HAL_OK) { + return HAL_ERROR; + } + + if (QSPI_AutoPollingMemReady() != HAL_OK) { + return HAL_ERROR; + } + + if (QSPI_Configuration() != HAL_OK) { + return HAL_ERROR; + } + + return HAL_OK; +} + +uint8_t CSP_QSPI_Erase_Chip(void) +{ + QSPI_CommandTypeDef sCommand = {0}; + + if (QSPI_WriteEnable() != HAL_OK) { + return HAL_ERROR; + } + + 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; + + if (HAL_QSPI_Command(&hqspi, + &sCommand, + HAL_MAX_DELAY) != HAL_OK) { + return HAL_ERROR; + } + + if (QSPI_AutoPollingMemReady() != HAL_OK) { + return HAL_ERROR; + } + + return HAL_OK; +} + +uint8_t QSPI_AutoPollingMemReady(void) +{ + QSPI_CommandTypeDef sCommand = {0}; + QSPI_AutoPollingTypeDef sConfig = {0}; + + 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; + + sConfig.Match = 0x00U; + sConfig.Mask = W25Q128_SR1_BUSY; + sConfig.MatchMode = QSPI_MATCH_MODE_AND; + sConfig.StatusBytesSize = 1; + sConfig.Interval = 0x10U; + sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + + return HAL_QSPI_AutoPolling(&hqspi, + &sCommand, + &sConfig, + HAL_MAX_DELAY); +} + +static uint8_t QSPI_WriteEnable(void) +{ + QSPI_CommandTypeDef sCommand = {0}; + QSPI_AutoPollingTypeDef sConfig = {0}; + + 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 HAL_ERROR; + } + + sConfig.Match = W25Q128_SR1_WEL; + sConfig.Mask = W25Q128_SR1_WEL; + sConfig.MatchMode = QSPI_MATCH_MODE_AND; + sConfig.StatusBytesSize = 1; + sConfig.Interval = 0x10U; + sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + + sCommand.Instruction = READ_STATUS_REG_CMD; + sCommand.DataMode = QSPI_DATA_1_LINE; + sCommand.NbData = 1; + + if (HAL_QSPI_AutoPolling(&hqspi, + &sCommand, + &sConfig, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return HAL_ERROR; + } + + return HAL_OK; +} + +uint8_t QSPI_Configuration(void) +{ + uint8_t sr1, sr2, sr3; + + if (QSPI_ReadStatusRegister(READ_STATUS_REG_CMD, &sr1) != HAL_OK) { + return HAL_ERROR; + } + + if (QSPI_ReadStatusRegister(READ_STATUS_REG2_CMD, &sr2) != HAL_OK) { + return HAL_ERROR; + } + + // quad enable + if ((sr2 & 0x02) == 0) { + if (QSPI_WriteEnable() != HAL_OK) { + return HAL_ERROR; + } + + sr2 |= 0x02; + + if (QSPI_WriteStatusRegister(WRITE_STATUS_REG2_CMD, sr2) != HAL_OK) { + return HAL_ERROR; + } + + HAL_Delay(15); + + if (QSPI_ReadStatusRegister(READ_STATUS_REG2_CMD, &sr2) != HAL_OK) { + return HAL_ERROR; + } + + if ((sr2 & 0x02) == 0) { + return HAL_ERROR; + } + } + + if (QSPI_ReadStatusRegister(READ_STATUS_REG3_CMD, &sr3) != HAL_OK) { + return HAL_ERROR; + } + + sr3 &= (uint8_t)~0x30U; + + if (QSPI_WriteEnable() != HAL_OK) { + return HAL_ERROR; + } + + if (QSPI_WriteStatusRegister(WRITE_STATUS_REG3_CMD, sr3) != HAL_OK) { + return HAL_ERROR; + } + + HAL_Delay(15); + + if (QSPI_ReadStatusRegister(READ_STATUS_REG3_CMD, &sr3) != HAL_OK) { + return HAL_ERROR; + } + + if ((sr3 & 0x30U) != 0U) { + return HAL_ERROR; + } + + return HAL_OK; +} + +uint8_t CSP_QSPI_EraseBlock(uint32_t flash_address) +{ + QSPI_CommandTypeDef sCommand = {0}; + + if (flash_address >= MEMORY_FLASH_SIZE) { + return HAL_ERROR; + } + + flash_address -= flash_address % MEMORY_BLOCK_SIZE; + + if (QSPI_WriteEnable() != HAL_OK) { + return HAL_ERROR; + } + + 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 = flash_address; + 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 HAL_ERROR; + } + + if (QSPI_AutoPollingMemReady() != HAL_OK) { + return HAL_ERROR; + } + + return HAL_OK; +} + +uint8_t CSP_QSPI_EraseSector(uint32_t EraseStartAddress, + uint32_t EraseEndAddress) +{ + QSPI_CommandTypeDef sCommand = {0}; + + if (EraseStartAddress >= MEMORY_FLASH_SIZE) { + return HAL_ERROR; + } + + if (EraseEndAddress >= MEMORY_FLASH_SIZE) { + return HAL_ERROR; + } + + EraseStartAddress -= + EraseStartAddress % MEMORY_SECTOR_SIZE; + + EraseEndAddress -= + EraseEndAddress % MEMORY_SECTOR_SIZE; + + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = SECTOR_ERASE_CMD; + sCommand.AddressMode = QSPI_ADDRESS_1_LINE; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + 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; + + while (EraseStartAddress <= EraseEndAddress) { + sCommand.Address = EraseStartAddress; + + if (QSPI_WriteEnable() != HAL_OK) { + return HAL_ERROR; + } + + if (HAL_QSPI_Command(&hqspi, + &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return HAL_ERROR; + } + + if (QSPI_AutoPollingMemReady() != HAL_OK) { + return HAL_ERROR; + } + + EraseStartAddress += MEMORY_SECTOR_SIZE; + } + + return HAL_OK; +} + +uint8_t CSP_QSPI_WriteMemory(uint8_t *buffer, + uint32_t address, + uint32_t buffer_size) +{ + QSPI_CommandTypeDef sCommand = {0}; + + uint32_t current_addr; + uint32_t end_addr; + uint32_t current_size; + + if (buffer == NULL) { + return HAL_ERROR; + } + + if (buffer_size == 0U) { + return HAL_OK; + } + + if (address >= MEMORY_FLASH_SIZE) { + return HAL_ERROR; + } + + if (buffer_size > (MEMORY_FLASH_SIZE - address)) { + return HAL_ERROR; + } + + current_addr = address; + end_addr = address + buffer_size; + + current_size = + MEMORY_PAGE_SIZE - + (current_addr % MEMORY_PAGE_SIZE); + + if (current_size > buffer_size) { + current_size = buffer_size; + } + + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = QUAD_IN_FAST_PROG_CMD; + sCommand.AddressMode = QSPI_ADDRESS_1_LINE; + 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; + + while (current_addr < end_addr) { + + sCommand.Address = current_addr; + sCommand.NbData = current_size; + + if (QSPI_WriteEnable() != HAL_OK) { + return HAL_ERROR; + } + + if (HAL_QSPI_Command(&hqspi, + &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return HAL_ERROR; + } + + if (HAL_QSPI_Transmit(&hqspi, + buffer, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return HAL_ERROR; + } + + if (QSPI_AutoPollingMemReady() != HAL_OK) { + return HAL_ERROR; + } + + buffer += current_size; + current_addr += current_size; + + if (current_addr < end_addr) { + + uint32_t remaining = end_addr - current_addr; + + current_size = MEMORY_PAGE_SIZE; + + if (current_size > remaining) { + current_size = remaining; + } + } + } + + return HAL_OK; +} + +uint8_t CSP_QSPI_EnableMemoryMappedMode(void) +{ + QSPI_CommandTypeDef s_command = {0}; + QSPI_MemoryMappedTypeDef s_mem_mapped_cfg = {0}; + + s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; + s_command.DataMode = QSPI_DATA_4_LINES; + s_command.Instruction = QUAD_IN_OUT_FAST_READ_CMD; + + s_command.AddressMode = QSPI_ADDRESS_4_LINES; + s_command.AddressSize = QSPI_ADDRESS_24_BITS; + + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; + s_command.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; + s_command.AlternateBytes = 0xF0; + + s_command.DummyCycles = 4; + + s_command.DdrMode = QSPI_DDR_MODE_DISABLE; + s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; + s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + s_mem_mapped_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE; + + if (HAL_QSPI_MemoryMapped(&hqspi, &s_command, &s_mem_mapped_cfg) != HAL_OK) { + return HAL_ERROR; + } + + return HAL_OK; +} + +uint8_t QSPI_ResetChip(void) +{ + QSPI_CommandTypeDef sCommand = {0}; + + 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; + + if (HAL_QSPI_Command(&hqspi, + &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return HAL_ERROR; + } + + sCommand.Instruction = RESET_EXECUTE_CMD; + + if (HAL_QSPI_Command(&hqspi, + &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return HAL_ERROR; + } + + HAL_Delay(1); + + return HAL_OK; +} + +uint8_t CSP_QSPI_Read(uint8_t *pData, + uint32_t ReadAddr, + uint32_t Size) +{ + QSPI_CommandTypeDef sCommand = {0}; + + if (pData == NULL) { + return HAL_ERROR; + } + + if (Size == 0U) { + return HAL_OK; + } + + if (ReadAddr >= MEMORY_FLASH_SIZE) { + return HAL_ERROR; + } + + if (Size > (MEMORY_FLASH_SIZE - ReadAddr)) { + return HAL_ERROR; + } + + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = QUAD_IN_OUT_FAST_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.AlternateBytes = 0xFFU; + sCommand.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; + + sCommand.DummyCycles = 4; + + sCommand.DataMode = QSPI_DATA_4_LINES; + sCommand.NbData = Size; + + 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 HAL_ERROR; + } + + if (HAL_QSPI_Receive(&hqspi, + pData, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return HAL_ERROR; + } + + return HAL_OK; +} + +/* USER CODE END 1 */ + -- cgit v1.2.3