344 lines
9.0 KiB
C
344 lines
9.0 KiB
C
#include "w25qxx.h"
|
|
#include "quadspi.h"
|
|
|
|
int w25qxx_init(void)
|
|
{
|
|
MX_QUADSPI_Init();
|
|
return 0;
|
|
}
|
|
|
|
int w25qxx_memory_mapped(void)
|
|
{
|
|
QSPI_CommandTypeDef cmd = {
|
|
// Instruction
|
|
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
|
.Instruction = FAST_READ_DUAL_IO_CMD,
|
|
// Address
|
|
.AddressMode = QSPI_ADDRESS_2_LINES,
|
|
.Address = 0, // NOT USED for memory-mapped mode
|
|
.AddressSize = QSPI_ADDRESS_24_BITS,
|
|
// AlternateByte
|
|
.AlternateByteMode = QSPI_ALTERNATE_BYTES_2_LINES,
|
|
.AlternateBytes = 0xF0, // M7-M0 should be set to Fxh
|
|
.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS,
|
|
// Dummy
|
|
.DummyCycles = 0,
|
|
// Data
|
|
.DataMode = QSPI_DATA_2_LINES,
|
|
.NbData = 0, // NOT USED for memory-mapped mode
|
|
// DDR
|
|
.DdrMode = QSPI_DDR_MODE_DISABLE,
|
|
};
|
|
QSPI_MemoryMappedTypeDef cfg = {
|
|
.TimeOutPeriod = 0,
|
|
.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE,
|
|
};
|
|
if (HAL_QSPI_GetState(&hqspi) != HAL_QSPI_STATE_BUSY_MEM_MAPPED) {
|
|
if (HAL_QSPI_Abort(&hqspi) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
if (HAL_QSPI_MemoryMapped(&hqspi, &cmd, &cfg) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint16_t w25qxx_read_deviceid(void)
|
|
{
|
|
uint8_t recv_buf[2] = {0};
|
|
uint16_t device_id = 0;
|
|
QSPI_CommandTypeDef cmd = {
|
|
// Instruction
|
|
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
|
.Instruction = ManufactDeviceID_CMD,
|
|
// Address
|
|
.AddressMode = QSPI_ADDRESS_1_LINE,
|
|
.Address = 0,
|
|
.AddressSize = QSPI_ADDRESS_24_BITS,
|
|
// AlternateByte
|
|
.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
|
|
// Dummy
|
|
.DummyCycles = 0,
|
|
// Data
|
|
.DataMode = QSPI_DATA_1_LINE,
|
|
.NbData = 2,
|
|
// DDR
|
|
.DdrMode = QSPI_DDR_MODE_DISABLE,
|
|
};
|
|
if (HAL_QSPI_Abort(&hqspi) != HAL_OK) {
|
|
return 0;
|
|
}
|
|
if (HAL_QSPI_Command(&hqspi, &cmd, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
|
|
return 0;
|
|
}
|
|
if (HAL_QSPI_Receive(&hqspi, recv_buf, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
|
|
return 0;
|
|
}
|
|
device_id = (recv_buf[0] << 8) | recv_buf[1];
|
|
return device_id;
|
|
}
|
|
|
|
static void w25qxx_wait_busy(void)
|
|
{
|
|
uint8_t status;
|
|
QSPI_CommandTypeDef cmd = {
|
|
// Instruction
|
|
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
|
.Instruction = READ_STATU_REGISTER_1,
|
|
// Address
|
|
.AddressMode = QSPI_ADDRESS_NONE,
|
|
// AlternateByte
|
|
.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
|
|
// Dummy
|
|
.DummyCycles = 0,
|
|
// Data
|
|
.DataMode = QSPI_DATA_1_LINE,
|
|
.NbData = 1,
|
|
// DDR
|
|
.DdrMode = QSPI_DDR_MODE_DISABLE,
|
|
};
|
|
HAL_QSPI_Command(&hqspi, &cmd, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);
|
|
do {
|
|
HAL_QSPI_Receive(&hqspi, &status, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);
|
|
} while ((status & 0x01) == 0x01);
|
|
}
|
|
|
|
int w25qxx_read(uint8_t *buffer, uint32_t start_addr, uint16_t nbytes)
|
|
{
|
|
QSPI_CommandTypeDef cmd = {
|
|
// Instruction
|
|
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
|
.Instruction = FAST_READ_DUAL_IO_CMD,
|
|
// Address
|
|
.AddressMode = QSPI_ADDRESS_2_LINES,
|
|
.Address = start_addr,
|
|
.AddressSize = QSPI_ADDRESS_24_BITS,
|
|
// AlternateByte
|
|
.AlternateByteMode = QSPI_ALTERNATE_BYTES_2_LINES,
|
|
.AlternateBytes = 0xF0, // M7-M0 should be set to Fxh
|
|
.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS,
|
|
// Dummy
|
|
.DummyCycles = 0,
|
|
// Data
|
|
.DataMode = QSPI_DATA_2_LINES,
|
|
.NbData = nbytes,
|
|
// DDR
|
|
.DdrMode = QSPI_DDR_MODE_DISABLE,
|
|
};
|
|
if (HAL_QSPI_Abort(&hqspi) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
if (HAL_QSPI_Command(&hqspi, &cmd, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
if (HAL_QSPI_Receive(&hqspi, buffer, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void w25qxx_write_enable(void)
|
|
{
|
|
QSPI_CommandTypeDef cmd = {
|
|
// Instruction
|
|
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
|
.Instruction = WRITE_ENABLE_CMD,
|
|
// Address
|
|
.AddressMode = QSPI_ADDRESS_NONE,
|
|
// AlternateByte
|
|
.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
|
|
// Dummy
|
|
.DummyCycles = 0,
|
|
// Data
|
|
.DataMode = QSPI_DATA_NONE,
|
|
// DDR
|
|
.DdrMode = QSPI_DDR_MODE_DISABLE,
|
|
};
|
|
HAL_QSPI_Command(&hqspi, &cmd, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);
|
|
// w25qxx_wait_busy();
|
|
}
|
|
|
|
static void w25qxx_write_disable(void)
|
|
{
|
|
QSPI_CommandTypeDef cmd = {
|
|
// Instruction
|
|
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
|
.Instruction = WRITE_DISABLE_CMD,
|
|
// Address
|
|
.AddressMode = QSPI_ADDRESS_NONE,
|
|
// AlternateByte
|
|
.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
|
|
// Dummy
|
|
.DummyCycles = 0,
|
|
// Data
|
|
.DataMode = QSPI_DATA_NONE,
|
|
// DDR
|
|
.DdrMode = QSPI_DDR_MODE_DISABLE,
|
|
};
|
|
HAL_QSPI_Command(&hqspi, &cmd, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);
|
|
// w25qxx_wait_busy();
|
|
}
|
|
|
|
int w25qxx_erase_sector(uint32_t sector_addr)
|
|
{
|
|
QSPI_CommandTypeDef cmd = {
|
|
// Instruction
|
|
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
|
.Instruction = SECTOR_ERASE_CMD,
|
|
// Address
|
|
.AddressMode = QSPI_ADDRESS_1_LINE,
|
|
.Address = sector_addr,
|
|
.AddressSize = QSPI_ADDRESS_24_BITS,
|
|
// AlternateByte
|
|
.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
|
|
// Dummy
|
|
.DummyCycles = 0,
|
|
// Data
|
|
.DataMode = QSPI_DATA_NONE,
|
|
// DDR
|
|
.DdrMode = QSPI_DDR_MODE_DISABLE,
|
|
};
|
|
|
|
if (HAL_QSPI_Abort(&hqspi) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
|
|
w25qxx_wait_busy();
|
|
|
|
w25qxx_write_enable();
|
|
|
|
if (HAL_QSPI_Command(&hqspi, &cmd, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
|
|
w25qxx_wait_busy();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int w25qxx_erase_chip(void)
|
|
{
|
|
QSPI_CommandTypeDef cmd = {
|
|
// Instruction
|
|
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
|
.Instruction = CHIP_ERASE_CMD,
|
|
// Address
|
|
.AddressMode = QSPI_ADDRESS_NONE,
|
|
// AlternateByte
|
|
.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
|
|
// Dummy
|
|
.DummyCycles = 0,
|
|
// Data
|
|
.DataMode = QSPI_DATA_NONE,
|
|
// DDR
|
|
.DdrMode = QSPI_DDR_MODE_DISABLE,
|
|
};
|
|
|
|
if (HAL_QSPI_Abort(&hqspi) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
|
|
w25qxx_wait_busy();
|
|
|
|
w25qxx_write_enable();
|
|
|
|
if (HAL_QSPI_Command(&hqspi, &cmd, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
|
|
w25qxx_wait_busy();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int w25qxx_page_program(uint8_t *dat, uint32_t write_addr, uint16_t nbytes)
|
|
{
|
|
QSPI_CommandTypeDef cmd = {
|
|
// Instruction
|
|
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
|
.Instruction = PAGE_PROGRAM_CMD,
|
|
// Address
|
|
.AddressMode = QSPI_ADDRESS_1_LINE,
|
|
.Address = write_addr,
|
|
.AddressSize = QSPI_ADDRESS_24_BITS,
|
|
// AlternateByte
|
|
.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
|
|
// Dummy
|
|
.DummyCycles = 0,
|
|
// Data
|
|
.DataMode = QSPI_DATA_1_LINE,
|
|
.NbData = nbytes,
|
|
// DDR
|
|
.DdrMode = QSPI_DDR_MODE_DISABLE,
|
|
};
|
|
|
|
if (HAL_QSPI_Abort(&hqspi) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
|
|
w25qxx_wait_busy();
|
|
|
|
w25qxx_write_enable();
|
|
|
|
if (HAL_QSPI_Command(&hqspi, &cmd, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
if (HAL_QSPI_Transmit(&hqspi, dat, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
|
|
w25qxx_wait_busy();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int w25qxx_reset(void)
|
|
{
|
|
QSPI_CommandTypeDef cmd1 = {
|
|
// Instruction
|
|
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
|
.Instruction = ENABLE_RESET_CMD,
|
|
// Address
|
|
.AddressMode = QSPI_ADDRESS_NONE,
|
|
// AlternateByte
|
|
.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
|
|
// Dummy
|
|
.DummyCycles = 0,
|
|
// Data
|
|
.DataMode = QSPI_DATA_NONE,
|
|
// DDR
|
|
.DdrMode = QSPI_DDR_MODE_DISABLE,
|
|
};
|
|
QSPI_CommandTypeDef cmd2 = {
|
|
// Instruction
|
|
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
|
.Instruction = RESET_DEVICE_CMD,
|
|
// Address
|
|
.AddressMode = QSPI_ADDRESS_NONE,
|
|
// AlternateByte
|
|
.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
|
|
// Dummy
|
|
.DummyCycles = 0,
|
|
// Data
|
|
.DataMode = QSPI_DATA_NONE,
|
|
// DDR
|
|
.DdrMode = QSPI_DDR_MODE_DISABLE,
|
|
};
|
|
|
|
if (HAL_QSPI_Abort(&hqspi) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
|
|
if (HAL_QSPI_Command(&hqspi, &cmd1, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
if (HAL_QSPI_Command(&hqspi, &cmd2, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
|
|
return -1;
|
|
}
|
|
|
|
w25qxx_wait_busy();
|
|
|
|
return 0;
|
|
}
|