#include <stdio.h> #include <stm32h7xx.h> #include "W25Qxx.h"
QSPI_HandleTypeDef hqspi;
void W25Qxx_EnableWrite(void) { QSPI_CommandTypeDef cmd; cmd.AddressMode = QSPI_ADDRESS_NONE; cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; cmd.DataMode = QSPI_DATA_NONE; cmd.DdrMode = QSPI_DDR_MODE_DISABLE; cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; cmd.DummyCycles = 0; cmd.NbData = 0; cmd.Instruction = 0x06; cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; HAL_QSPI_Command(&hqspi, &cmd, HAL_MAX_DELAY); }
void W25Qxx_EraseSector(uint16_t sector) { QSPI_CommandTypeDef cmd; W25Qxx_EnableWrite(); cmd.Address = sector << 12; cmd.AddressMode = QSPI_ADDRESS_1_LINE; cmd.AddressSize = QSPI_ADDRESS_24_BITS; cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; cmd.DataMode = QSPI_DATA_NONE; cmd.DdrMode = QSPI_DDR_MODE_DISABLE; cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; cmd.DummyCycles = 0; cmd.NbData = 0; cmd.Instruction = 0x20; cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; HAL_QSPI_Command(&hqspi, &cmd, HAL_MAX_DELAY); while (W25Qxx_ReadStatus(1) & W25Qxx_STATUS_BUSY); }
void W25Qxx_Init(void) { uint8_t m, status; uint16_t id; GPIO_InitTypeDef gpio;
__HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_QSPI_CLK_ENABLE(); gpio.Alternate = GPIO_AF10_QUADSPI; gpio.Mode = GPIO_MODE_AF_PP; gpio.Pin = GPIO_PIN_8 | GPIO_PIN_9; gpio.Pull = GPIO_NOPULL; gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOF, &gpio); gpio.Alternate = GPIO_AF9_QUADSPI; gpio.Pin = GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_10; HAL_GPIO_Init(GPIOF, &gpio); gpio.Alternate = GPIO_AF10_QUADSPI; gpio.Pin = GPIO_PIN_6; HAL_GPIO_Init(GPIOG, &gpio); hqspi.Instance = QUADSPI; hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE; hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0; hqspi.Init.ClockPrescaler = 1; hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE; hqspi.Init.FifoThreshold = 32; hqspi.Init.FlashID = QSPI_FLASH_ID_1; hqspi.Init.FlashSize = 23; // W25Q128 (2^(23+1)=16MB) hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; HAL_QSPI_Init(&hqspi); id = W25Qxx_ReadID(&m); printf("SPI Flash: M=0x%02x, ID=0x%02x\n", m, id); id = W25Qxx_ReadJEDECID(&m); printf("SPI Flash: M=0x%02x, ID=0x%04x\n", m, id); status = W25Qxx_ReadStatus(2); if ((status & W25Qxx_STATUS2_QE) == 0) { printf("QUADSPI mode is disabled\n"); while (1); } }
void W25Qxx_ProgramPage(uint32_t addr, const void *data, int len) { QSPI_CommandTypeDef cmd; W25Qxx_EnableWrite(); cmd.Address = addr; cmd.AddressMode = QSPI_ADDRESS_1_LINE; cmd.AddressSize = QSPI_ADDRESS_24_BITS; cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; cmd.DataMode = QSPI_DATA_4_LINES; cmd.DdrMode = QSPI_DDR_MODE_DISABLE; cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; cmd.DummyCycles = 0; cmd.NbData = len; cmd.Instruction = 0x32; cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; HAL_QSPI_Command(&hqspi, &cmd, HAL_MAX_DELAY); HAL_QSPI_Transmit(&hqspi, (uint8_t *)data, HAL_MAX_DELAY); while (W25Qxx_ReadStatus(1) & W25Qxx_STATUS_BUSY); }
void W25Qxx_Read(uint32_t addr, void *data, int len) { QSPI_CommandTypeDef cmd; W25Qxx_EnableWrite(); cmd.Address = addr; cmd.AddressMode = QSPI_ADDRESS_4_LINES; cmd.AddressSize = QSPI_ADDRESS_24_BITS; cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; cmd.DataMode = QSPI_DATA_4_LINES; cmd.DdrMode = QSPI_DDR_MODE_DISABLE; cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; cmd.DummyCycles = 6; cmd.NbData = len; cmd.Instruction = 0xeb; cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; HAL_QSPI_Command(&hqspi, &cmd, HAL_MAX_DELAY); HAL_QSPI_Receive(&hqspi, data, HAL_MAX_DELAY); }
uint8_t W25Qxx_ReadID(uint8_t *pm) { uint8_t data[5]; uint8_t m, id; QSPI_CommandTypeDef cmd; cmd.AddressMode = QSPI_ADDRESS_NONE; cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; cmd.DataMode = QSPI_DATA_1_LINE; cmd.DdrMode = QSPI_DDR_MODE_DISABLE; cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; cmd.DummyCycles = 0; cmd.NbData = sizeof(data); cmd.Instruction = 0x90; cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; HAL_QSPI_Command(&hqspi, &cmd, HAL_MAX_DELAY); HAL_QSPI_Receive(&hqspi, data, HAL_MAX_DELAY); m = data[3]; if (pm != NULL) *pm = m; id = data[4]; return id; }
uint16_t W25Qxx_ReadJEDECID(uint8_t *pm) { uint8_t data[3]; uint8_t m; uint16_t id; QSPI_CommandTypeDef cmd; cmd.AddressMode = QSPI_ADDRESS_NONE; cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; cmd.DataMode = QSPI_DATA_1_LINE; cmd.DdrMode = QSPI_DDR_MODE_DISABLE; cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; cmd.DummyCycles = 0; cmd.NbData = sizeof(data); cmd.Instruction = 0x9f; cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; HAL_QSPI_Command(&hqspi, &cmd, HAL_MAX_DELAY); HAL_QSPI_Receive(&hqspi, data, HAL_MAX_DELAY); m = data[0]; if (pm != NULL) *pm = m; id = (data[1] << 8) | data[2]; return id; }
uint8_t W25Qxx_ReadStatus(int i) { const uint8_t code[] = {0x05, 0x35, 0x15}; uint8_t status; QSPI_CommandTypeDef cmd; assert_param(i >= 1 && i <= sizeof(code)); cmd.AddressMode = QSPI_ADDRESS_NONE; cmd.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; cmd.DataMode = QSPI_DATA_1_LINE; cmd.DdrMode = QSPI_DDR_MODE_DISABLE; cmd.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; cmd.DummyCycles = 0; cmd.NbData = 1; cmd.Instruction = code[i - 1]; cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; HAL_QSPI_Command(&hqspi, &cmd, HAL_MAX_DELAY); HAL_QSPI_Receive(&hqspi, &status, HAL_MAX_DELAY); return status; }
|