/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file quadspi.c * @brief This file provides code for the configuration * of the QUADSPI instances. ****************************************************************************** * @attention * * Copyright (c) 2024 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(QSPI_HandleTypeDef *hqspi); static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout); static uint8_t QSPI_Configuration(void); static uint8_t QSPI_ResetChip(void); //QSPI_HandleTypeDef hqspi; /* 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 = 10; hqspi.Init.FifoThreshold = 4; hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; hqspi.Init.FlashSize = 25; hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_6_CYCLE; hqspi.Init.ClockMode = QSPI_CLOCK_MODE_3; 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}; if(qspiHandle->Instance==QUADSPI) { /* USER CODE BEGIN QUADSPI_MspInit 0 */ /* USER CODE END QUADSPI_MspInit 0 */ /* QUADSPI clock enable */ __HAL_RCC_QSPI_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); /**QUADSPI GPIO Configuration PF8 ------> QUADSPI_BK1_IO0 PF9 ------> QUADSPI_BK1_IO1 PF10 ------> QUADSPI_CLK PH2 ------> QUADSPI_BK2_IO0 PH3 ------> QUADSPI_BK2_IO1 PB10 ------> QUADSPI_BK1_NCS PC11 ------> QUADSPI_BK2_NCS */ 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_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_2|GPIO_PIN_3; 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(GPIOH, &GPIO_InitStruct); GPIO_InitStruct.Pin = 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(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_11; 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(GPIOC, &GPIO_InitStruct); /* QUADSPI interrupt Init */ HAL_NVIC_SetPriority(QUADSPI_IRQn, 0, 0); HAL_NVIC_EnableIRQ(QUADSPI_IRQn); /* 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 PF8 ------> QUADSPI_BK1_IO0 PF9 ------> QUADSPI_BK1_IO1 PF10 ------> QUADSPI_CLK PH2 ------> QUADSPI_BK2_IO0 PH3 ------> QUADSPI_BK2_IO1 PB10 ------> QUADSPI_BK1_NCS PC11 ------> QUADSPI_BK2_NCS */ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10); HAL_GPIO_DeInit(GPIOH, GPIO_PIN_2|GPIO_PIN_3); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10); HAL_GPIO_DeInit(GPIOC, GPIO_PIN_11); /* QUADSPI interrupt Deinit */ HAL_NVIC_DisableIRQ(QUADSPI_IRQn); /* USER CODE BEGIN QUADSPI_MspDeInit 1 */ /* USER CODE END QUADSPI_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ /* QUADSPI init function */ uint8_t CSP_QUADSPI_Init(void) { //prepare QSPI peripheral for ST-Link Utility operations if (HAL_QSPI_DeInit(&hqspi) != HAL_OK) { return HAL_ERROR; } MX_QUADSPI_Init(); if (QSPI_ResetChip() != HAL_OK) { return HAL_ERROR; } HAL_Delay(1); if (QSPI_AutoPollingMemReady(&hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE*5) != HAL_OK) { return HAL_ERROR; } if (QSPI_WriteEnable(&hqspi) != HAL_OK) { return HAL_ERROR; } if (QSPI_Configuration() != HAL_OK) { return HAL_ERROR; } return HAL_OK; } /*Erase chip function modified for S25FL256 12/16/24 JR */ uint8_t CSP_QSPI_Erase_Chip(void) { QSPI_CommandTypeDef s_command; /* Initialize the erase command */ s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; s_command.Instruction = BULK_ERASE_CMD; s_command.AddressMode = QSPI_ADDRESS_NONE; s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = QSPI_DATA_NONE; s_command.DummyCycles = 0; s_command.DdrMode = QSPI_DDR_MODE_DISABLE; s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; /* Enable write operations */ if (QSPI_WriteEnable(&hqspi) != QSPI_OK) { return QSPI_ERROR; } /* Send the command */ if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return QSPI_ERROR; } /* Configure automatic polling mode to wait for end of erase */ if (QSPI_AutoPollingMemReady(&hqspi, 60000) != QSPI_OK) { return QSPI_ERROR; } return QSPI_OK; } /*Auto polling function modified for S25FL256 12/16/24 JR */ uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout) { QSPI_CommandTypeDef s_command; QSPI_AutoPollingTypeDef s_config; /* Configure automatic polling mode to wait for memory ready */ s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; s_command.Instruction = READ_STATUS_REG1_CMD; s_command.AddressMode = QSPI_ADDRESS_NONE; s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = QSPI_DATA_1_LINE; s_command.DummyCycles = 0; s_command.DdrMode = QSPI_DDR_MODE_DISABLE; s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; s_config.Match = 0; s_config.Mask = WIP_READY; s_config.MatchMode = QSPI_MATCH_MODE_AND; s_config.StatusBytesSize = 1; s_config.Interval = 0x10; s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE*15) != HAL_OK) { return HAL_ERROR; } return HAL_OK; } /*Write Enable function modified for S25FL256 12/16/24 JR */ static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi) { QSPI_CommandTypeDef s_command; QSPI_AutoPollingTypeDef s_config; /* Enable write operations ------------------------------------------ */ s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; s_command.Instruction = WRITE_ENABLE_CMD; s_command.AddressMode = QSPI_ADDRESS_NONE; s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = QSPI_DATA_NONE; s_command.DummyCycles = 0; s_command.DdrMode = QSPI_DDR_MODE_DISABLE; s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } /* Configure automatic polling mode to wait for write enabling ---- */ s_config.Match = QSPI_SR_WREN; s_config.Mask = QSPI_SR_WREN; s_config.MatchMode = QSPI_MATCH_MODE_AND; s_config.StatusBytesSize = 1; s_config.Interval = 0x10; s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; s_command.Instruction = READ_STATUS_REG1_CMD; s_command.DataMode = QSPI_DATA_1_LINE; if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE*10) != HAL_OK) { return HAL_ERROR; } return HAL_OK; } /* Enable quad mode and set dummy cycles count */ uint8_t QSPI_Configuration(void) { QSPI_CommandTypeDef sCommand; uint8_t test_buffer[4] = { 0 }; /*read status register*/ sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; sCommand.Instruction = READ_STATUS_REG1_CMD; sCommand.AddressMode = QSPI_ADDRESS_NONE; sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; sCommand.DataMode = QSPI_DATA_1_LINE; sCommand.DummyCycles = 0; sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; sCommand.NbData = 1; if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } if (HAL_QSPI_Receive(&hqspi, test_buffer, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } /*read configuration register*/ sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; sCommand.Instruction = READ_CONFIGURATION_REG_CMD; sCommand.AddressMode = QSPI_ADDRESS_NONE; sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; sCommand.DataMode = QSPI_DATA_1_LINE; sCommand.DummyCycles = 0; sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; sCommand.NbData = 1; if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } if (HAL_QSPI_Receive(&hqspi, &(test_buffer[1]), HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } test_buffer[0] |= 0x40; /* modify buffer to enable quad mode */ test_buffer[1] |= 0xC0; /* set dummy cycles */ sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; sCommand.AddressSize = QSPI_ADDRESS_24_BITS; sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; sCommand.Instruction = WRITE_STATUS_REG_CMD; sCommand.AddressMode = QSPI_ADDRESS_NONE; sCommand.DataMode = QSPI_DATA_1_LINE; sCommand.DummyCycles = 0; sCommand.NbData = 2; if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } if (HAL_QSPI_Transmit(&hqspi, test_buffer, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { Error_Handler(); return HAL_ERROR; } return HAL_OK; } /*Erase Sector function modified for S25FL256 12/16/24 JR */ uint8_t CSP_QSPI_EraseSector(void) { QSPI_CommandTypeDef s_command; s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; s_command.Instruction = BULK_ERASE_CMD; s_command.AddressMode = QSPI_ADDRESS_NONE; s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = QSPI_DATA_NONE; s_command.DummyCycles = 0; s_command.DdrMode = QSPI_DDR_MODE_DISABLE; s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; /* Enable write operations */ if (QSPI_WriteEnable(&hqspi) != QSPI_OK) { return QSPI_ERROR; } /* Send the command */ if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } /* Configure automatic polling mode to wait for end of erase */ if (QSPI_AutoPollingMemReady(&hqspi,60000) != HAL_OK) { return QSPI_ERROR; } return QSPI_OK; } /*Write function modified for S25FL256 12/16/24 JR */ uint8_t CSP_QSPI_WriteMemory(uint8_t* buffer, uint32_t WriteAddr, uint32_t Size) { QSPI_CommandTypeDef s_command; uint32_t end_addr, current_size, current_addr; /* Calculation of the size between the write address and the end of the page */ current_size = MEMORY_PAGE_SIZE - (WriteAddr % MEMORY_PAGE_SIZE); /* Check if the size of the data is less than the remaining place in the page */ if (current_size > Size) { current_size = Size; } /* Initialize the address variables */ current_addr = WriteAddr; end_addr = WriteAddr + Size; /* Initialize the program command */ s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; s_command.Instruction = 0x12; //QUAD_IN_FAST_PROG_CMD; jjb change s_command.AddressMode = QSPI_ADDRESS_1_LINE; s_command.AddressSize = QSPI_ADDRESS_32_BITS; s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = QSPI_DATA_1_LINE;// jjb changed s_command.DummyCycles = 0; s_command.DdrMode = QSPI_DDR_MODE_DISABLE; s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; /* Perform the write page by page */ do { s_command.Address = current_addr; s_command.NbData = current_size; if (current_size == 0) { return HAL_OK; } /* Enable write operations */ if (QSPI_WriteEnable(&hqspi) != HAL_OK) { return HAL_ERROR; } /* Configure the command */ if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE*5) != HAL_OK) { return HAL_ERROR; } /* Transmission of the data */ if (HAL_QSPI_Transmit(&hqspi, buffer, HAL_QPSI_TIMEOUT_DEFAULT_VALUE*5) != HAL_OK) { return HAL_ERROR; } /* Configure automatic polling mode to wait for end of program */ if (QSPI_AutoPollingMemReady(&hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE*5) != HAL_OK) { return HAL_ERROR; } /* Update the address and size variables for next page programming */ current_addr += current_size; buffer += current_size; current_size = ((current_addr + MEMORY_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : MEMORY_PAGE_SIZE; } while (current_addr <= end_addr); return HAL_OK; } /*Memory Mapping function modified for S25FL256 12/16/24 JR */ uint8_t CSP_QSPI_EnableMemoryMappedMode(void) { QSPI_CommandTypeDef s_command; QSPI_MemoryMappedTypeDef s_mem_mapped_cfg; /* Configure the command for the read instruction */ s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; s_command.Instruction = READ_4_BYTE_ADDR_CMD; s_command.AddressMode = QSPI_ADDRESS_1_LINE; s_command.AddressSize = QSPI_ADDRESS_32_BITS; s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = QSPI_DATA_1_LINE; // QSPI_DATA_4_LINES; s_command.DummyCycles = 0; //N25Q512A_DUMMY_CYCLES_READ_QUAD; s_command.DdrMode = QSPI_DDR_MODE_DISABLE; s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; /* Configure the memory mapped mode */ s_mem_mapped_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE; s_mem_mapped_cfg.TimeOutPeriod = 0; 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; uint32_t temp = 0; /* Erasing Sequence -------------------------------------------------- */ sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; sCommand.AddressSize = QSPI_ADDRESS_24_BITS; sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; sCommand.Instruction = RESET_ENABLE_CMD; sCommand.AddressMode = QSPI_ADDRESS_NONE; sCommand.Address = 0; sCommand.DataMode = QSPI_DATA_NONE; sCommand.DummyCycles = 0; if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } for (temp = 0; temp < 0x2f; temp++) { __NOP(); } sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; sCommand.AddressSize = QSPI_ADDRESS_24_BITS; sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; sCommand.Instruction = RESET_EXECUTE_CMD; sCommand.AddressMode = QSPI_ADDRESS_NONE; sCommand.Address = 0; sCommand.DataMode = QSPI_DATA_NONE; sCommand.DummyCycles = 0; if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } return HAL_OK; } uint8_t BSP_QSPI_GetStatus(void) { QSPI_CommandTypeDef s_command; uint8_t reg; /* Initialize the read flag status register command */ s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; s_command.Instruction = READ_STATUS_REG1_CMD; s_command.AddressMode = QSPI_ADDRESS_NONE; s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = QSPI_DATA_1_LINE; s_command.DummyCycles = 0; s_command.NbData = 1; s_command.DdrMode = QSPI_DDR_MODE_DISABLE; s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; /* Configure the command */ if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return QSPI_ERROR; } /* Reception of the data */ if (HAL_QSPI_Receive(&hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return QSPI_ERROR; } /* Check the value of the registers */ if ((reg & (P_ERR | E_ERR )) != 0) { while(1); return QSPI_ERROR; } s_command.Instruction = READ_STATUS_REG2_CMD; // it has 2 SRs if (HAL_QSPI_Receive(&hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { //while (1); return QSPI_ERROR; } if ((reg & (P_SUS | E_SUS)) != 0) { // while (1); return QSPI_SUSPENDED; } s_command.Instruction = READ_STATUS_REG1_CMD; // it has 2 SRs if (HAL_QSPI_Receive(&hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { // while (1); return QSPI_ERROR; } if ((reg & WIP_READY) == 0) { return QSPI_OK; } else { return QSPI_BUSY; } } /* USER CODE END 1 */