#include "qspi_flash.h" #include "stm32u5xx.h" #include "stm32u5xx_hal.h" #include "octospi.h" /* USER CODE BEGIN 0 */ static uint8_t QSPI_WriteEnable(void); static uint8_t QSPI_AutoPollingMemReady(uint32_t Timeout); static uint8_t QSPI_Configuration(void); static uint8_t QSPI_ResetChip(void); /* USER CODE END 0 */ /* USER CODE BEGIN 1 */ /* QUADSPI init function */ uint8_t CSP_QUADSPI_Init(void) { //prepare QSPI peripheral for ST-Link Utility operations hospi2.Instance = OCTOSPI2; if (HAL_OSPI_DeInit(&hospi2) != HAL_OK) { return HAL_ERROR; } MX_OCTOSPI2_Init(); if (QSPI_ResetChip() != HAL_OK) { return HAL_ERROR; } HAL_Delay(1); if (QSPI_AutoPollingMemReady(HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } if (QSPI_WriteEnable() != HAL_OK) { return HAL_ERROR; } if (QSPI_Configuration() != HAL_OK) { return HAL_ERROR; } if (QSPI_AutoPollingMemReady(HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } return HAL_OK; } uint8_t CSP_QSPI_Erase_Chip(void) { OSPI_RegularCmdTypeDef sCommand={0}; if (QSPI_WriteEnable() != HAL_OK) { return HAL_ERROR; } /* Erasing Sequence --------------------------------- */ sCommand.Instruction = CHIP_ERASE_CMD; sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; sCommand.Address = 0; sCommand.DataMode = HAL_OSPI_ADDRESS_NONE; sCommand.DummyCycles = 0; if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } if (QSPI_AutoPollingMemReady(QUADSPI_MAX_ERASE_TIMEOUT) != HAL_OK) { return HAL_ERROR; } return HAL_OK; } static uint8_t QSPI_AutoPollingMemReady(uint32_t Timeout) { OSPI_RegularCmdTypeDef sCommand={0}; OSPI_AutoPollingTypeDef sConfig= {0}; /* Configure automatic polling mode to wait for memory ready ------ */ sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; sCommand.Instruction = READ_STATUS_REG_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.DataMode = HAL_OSPI_DATA_1_LINE; sCommand.DummyCycles = 0; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; sConfig.Match = 0x0000; sConfig.Mask = 0x0101; sConfig.MatchMode = HAL_OSPI_MATCH_MODE_AND; sConfig.Interval = 0x10; sConfig.AutomaticStop = HAL_OSPI_AUTOMATIC_STOP_ENABLE; if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } if (HAL_OSPI_AutoPolling(&hospi2, &sConfig, Timeout) != HAL_OK) { return HAL_ERROR; } return HAL_OK; } static uint8_t QSPI_WriteEnable(void) { OSPI_RegularCmdTypeDef sCommand={0}; OSPI_AutoPollingTypeDef sConfig={0}; /* Enable write operations ------------------------------------------ */ sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; sCommand.Instruction = WRITE_ENABLE_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.DataMode = HAL_OSPI_ADDRESS_NONE; sCommand.DummyCycles = 0; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } /* Configure automatic polling mode to wait for write enabling ---- */ sConfig.Match = 0x0202; sConfig.Mask = 0x0202; sConfig.MatchMode = HAL_OSPI_MATCH_MODE_AND; sConfig.Interval = 0x10; sConfig.AutomaticStop = HAL_OSPI_AUTOMATIC_STOP_ENABLE; sCommand.Instruction = READ_STATUS_REG_CMD; sCommand.DataMode = HAL_OSPI_DATA_1_LINE; if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } if (HAL_OSPI_AutoPolling(&hospi2, &sConfig, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } return HAL_OK; } /*Enable quad mode and set dummy cycles count*/ static uint8_t QSPI_Configuration(void) { OSPI_RegularCmdTypeDef sCommand={0}; uint16_t reg=0; /*enter 4 byte address*/ sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; sCommand.Instruction = ENTER_4_BYTE_ADD_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.DataMode = HAL_OSPI_ADDRESS_NONE; sCommand.DummyCycles = 0; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; sCommand.NbData = 0; if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } /*read configuration register*/ sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; sCommand.Instruction = READ_CONFIGURATION_REG_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.DataMode = HAL_OSPI_DATA_1_LINE; sCommand.DummyCycles = 0; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; sCommand.NbData = 2; if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } if (HAL_OSPI_Receive(&hospi2, (uint8_t*)(®), HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } if (QSPI_WriteEnable() != HAL_OK) { return HAL_ERROR; } /*set dummy cycles*/ MODIFY_REG(reg, 0xF0F0, ((DUMMY_CLOCK_CYCLES_READ_QUAD << 4) | (DUMMY_CLOCK_CYCLES_READ_QUAD << 12))); sCommand.Instruction = WRITE_VOL_CFG_REG_CMD; if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } if (HAL_OSPI_Transmit(&hospi2, (uint8_t*)(®), HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } return HAL_OK; } uint8_t CSP_QSPI_EraseSector(uint32_t EraseStartAddress, uint32_t EraseEndAddress) { OSPI_RegularCmdTypeDef sCommand={0}; EraseStartAddress = EraseStartAddress - EraseStartAddress % MEMORY_SECTOR_SIZE; /* Erasing Sequence -------------------------------------------------- */ sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; sCommand.Instruction = SECTOR_ERASE_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE; sCommand.DataMode = HAL_OSPI_ADDRESS_NONE; sCommand.DummyCycles = 0; while (EraseEndAddress >= EraseStartAddress) { sCommand.Address = (EraseStartAddress & 0x0FFFFFFF); if (QSPI_WriteEnable() != HAL_OK) { return HAL_ERROR; } if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } EraseStartAddress += MEMORY_SECTOR_SIZE; if (QSPI_AutoPollingMemReady(HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } } return HAL_OK; } uint8_t CSP_QSPI_WriteMemory(uint8_t* buffer, uint32_t address, uint32_t buffer_size) { OSPI_RegularCmdTypeDef sCommand={0}; uint32_t end_addr, current_size, current_addr; /* Calculation of the size between the write address and the end of the page */ current_addr = 0; while (current_addr <= address) { current_addr += MEMORY_PAGE_SIZE; } current_size = current_addr - address; /* Check if the size of the data is less than the remaining place in the page */ if (current_size > buffer_size) { current_size = buffer_size; } /* Initialize the adress variables */ current_addr = address; end_addr = address + buffer_size; sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; sCommand.Instruction = QUAD_IN_FAST_PROG_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE; sCommand.DataMode = HAL_OSPI_DATA_4_LINES; sCommand.NbData = buffer_size; sCommand.Address = address; sCommand.DummyCycles = 0; /* Perform the write page by page */ do { sCommand.Address = current_addr; sCommand.NbData = current_size; if (current_size == 0) { return HAL_OK; } /* Enable write operations */ if (QSPI_WriteEnable() != HAL_OK) { return HAL_ERROR; } /* Configure the command */ if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } /* Transmission of the data */ if (HAL_OSPI_Transmit(&hospi2, buffer, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } /* Configure automatic polling mode to wait for end of program */ if (QSPI_AutoPollingMemReady(HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != 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; } uint8_t CSP_QSPI_EnableMemoryMappedMode(void) { OSPI_RegularCmdTypeDef sCommand={0}; OSPI_MemoryMappedTypeDef sMemMappedCfg={0}; /* Enable Memory-Mapped mode-------------------------------------------------- */ sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE; sCommand.DataMode = HAL_OSPI_DATA_4_LINES; sCommand.NbData = 0; sCommand.Address = 0; sCommand.Instruction = QUAD_OUT_FAST_READ_CMD; sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ_QUAD; /* Configure the command */ if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE; if (HAL_OSPI_MemoryMapped(&hospi2, &sMemMappedCfg) != HAL_OK) { return HAL_ERROR; } return HAL_OK; } static uint8_t QSPI_ResetChip() { OSPI_RegularCmdTypeDef sCommand={0}; uint32_t temp = 0; /* Erasing Sequence -------------------------------------------------- */ sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; sCommand.AddressSize = HAL_OSPI_ADDRESS_8_BITS; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; sCommand.Instruction = RESET_ENABLE_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; sCommand.Address = 0; sCommand.DataMode = HAL_OSPI_ADDRESS_NONE; sCommand.DummyCycles = 0; if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } for (temp = 0; temp < 0x2f; temp++) { __NOP(); } sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; sCommand.Instruction = RESET_EXECUTE_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; sCommand.Address = 0; sCommand.DataMode = HAL_OSPI_ADDRESS_NONE; sCommand.DummyCycles = 0; if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } /* Erasing Sequence -------------------------------------------------- */ sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_2_LINES; sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; sCommand.Instruction = RESET_ENABLE_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; sCommand.Address = 0; sCommand.DataMode = HAL_OSPI_ADDRESS_NONE; sCommand.DummyCycles = 0; if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } for (temp = 0; temp < 0x2f; temp++) { __NOP(); } sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_2_LINES; sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; sCommand.Instruction = RESET_EXECUTE_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; sCommand.Address = 0; sCommand.DataMode = HAL_OSPI_ADDRESS_NONE; sCommand.DummyCycles = 0; if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } /* Erasing Sequence -------------------------------------------------- */ sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_4_LINES; sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; sCommand.Instruction = RESET_ENABLE_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; sCommand.Address = 0; sCommand.DataMode = HAL_OSPI_ADDRESS_NONE; sCommand.DummyCycles = 0; if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } for (temp = 0; temp < 0x2f; temp++) { __NOP(); } sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_4_LINES; sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS; sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; sCommand.Instruction = RESET_EXECUTE_CMD; sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE; sCommand.Address = 0; sCommand.DataMode = HAL_OSPI_DATA_NONE; sCommand.DummyCycles = 0; if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } return HAL_OK; } uint8_t CSP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size) { OSPI_RegularCmdTypeDef s_command={0}; /* Initialize the read command */ s_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; s_command.Instruction = 0xEB; s_command.AddressMode = HAL_OSPI_ADDRESS_4_LINES; s_command.AddressSize = HAL_OSPI_ADDRESS_24_BITS; s_command.Address = ReadAddr; s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = HAL_OSPI_DATA_4_LINES; s_command.DummyCycles = 10; s_command.NbData = Size; s_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; /* Configure the command */ if (HAL_OSPI_Command(&hospi2, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } /* Reception of the data */ if (HAL_OSPI_Receive(&hospi2, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } return HAL_OK; } /* USER CODE END 1 */