add w25q64 hardware on bearpi board
This commit is contained in:
343
board/BearPi_STM32L431RC/BSP/Hardware/W25QXX-QSPI/w25qxx.c
Normal file
343
board/BearPi_STM32L431RC/BSP/Hardware/W25QXX-QSPI/w25qxx.c
Normal 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;
|
||||
}
|
40
board/BearPi_STM32L431RC/BSP/Hardware/W25QXX-QSPI/w25qxx.h
Normal file
40
board/BearPi_STM32L431RC/BSP/Hardware/W25QXX-QSPI/w25qxx.h
Normal 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_ */
|
Reference in New Issue
Block a user