Files
TencentOS-tiny/board/BearPi_STM32L431RC/BSP/Hardware/W25QXX-QSPI/w25qxx.c
2022-09-29 12:07:16 +08:00

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;
}