add w25q64 hardware on bearpi board

This commit is contained in:
KY-zhang-X
2022-09-29 12:07:16 +08:00
parent f93d0857aa
commit 1514f1cb9b
2 changed files with 383 additions and 0 deletions

View File

@@ -0,0 +1,343 @@
#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;
}

View File

@@ -0,0 +1,40 @@
#ifndef _W25QXX_H_
#define _W25QXX_H_
#include "main.h"
enum {
ManufactDeviceID_CMD = 0x90,
READ_STATU_REGISTER_1 = 0x05,
READ_STATU_REGISTER_2 = 0x35,
WRITE_STATU_REGISTER = 0x01,
READ_DATA_CMD = 0x03,
FAST_READ_CMD = 0x0B,
FAST_READ_DUAL_O_CMD = 0x3B,
FAST_READ_DUAL_IO_CMD = 0xBB,
FAST_READ_QUAD_O_CMD = 0x6B,
FAST_READ_QUAD_IO_CMD = 0xEB,
WRITE_ENABLE_CMD = 0x06,
WRITE_DISABLE_CMD = 0x04,
SECTOR_ERASE_CMD = 0x20,
CHIP_ERASE_CMD = 0xc7,
PAGE_PROGRAM_CMD = 0x02,
QUAD_PAGE_PROGRAM_CMD = 0x32,
BLOCK_ERASE_64KB_CMD = 0xD8,
BLOCK_ERASE_32KB_CMD = 0x52,
ERASE_SUSPEND_CMD = 0x75,
ERASE_RESUME_CMD = 0x7A,
HIGH_PERFORM_MODE_CMD = 0xA3,
ENABLE_RESET_CMD = 0x66,
RESET_DEVICE_CMD = 0x99,
};
int w25qxx_init(void);
int w25qxx_memory_mapped(void);
uint16_t w25qxx_read_deviceid(void);
int w25qxx_read(uint8_t* buffer, uint32_t start_addr, uint16_t nbytes);
int w25qxx_erase_sector(uint32_t sector_addr);
int w25qxx_erase_chip(void);
int w25qxx_page_program(uint8_t* dat, uint32_t write_addr, uint16_t nbytes);
int w25qxx_reset(void);
#endif /* _W25QXX_H_ */