rp2040/example/boot2/src/flash.c

99 lines
2.4 KiB
C
Raw Normal View History

2025-04-20 22:03:15 +08:00
#include "gpio.h"
#include "ssi_reg.h"
#include "flash.h"
static void flash_cs_force_low(void)
{
io_rw_32 *reg;
/* force QSPI_CS low level as selected */
reg = (io_rw_32 *)(IO_QSPI_BASE + GPIO_QSPI_CS_CTRL_OFFSET);
*reg = GPIO_OVER_OUT_FORCE_LOW << GPIO_OVER_OUT_POS;
}
static void flash_cs_force_high(void)
{
io_rw_32 *reg;
/* force QSPI_CS high level as disselected */
reg = (io_rw_32 *)(IO_QSPI_BASE + GPIO_QSPI_CS_CTRL_OFFSET);
*reg = GPIO_OVER_OUT_FORCE_HIGH << GPIO_OVER_OUT_POS;
}
static void flash_put_get(uint8_t *tx, uint8_t *rx, uint32_t count, uint32_t rx_skip)
{
uint32_t tx_count = count;
uint32_t rx_count = count;
while (tx_count || rx_skip || rx_count) {
uint32_t tx_level = ssi_hw->txflr;
uint32_t rx_level = ssi_hw->rxflr;
if (tx_count && tx_level + rx_level < 14) {
ssi_hw->dr0 = (uint32_t) (tx ? *tx++ : 0);
--tx_count;
}
if (rx_level) {
uint8_t rxbyte = ssi_hw->dr0;
if (rx_skip) {
--rx_skip;
} else {
if (rx)
*rx++ = rxbyte;
--rx_count;
}
}
}
flash_cs_force_high();
}
static void flash_do_cmd(uint8_t cmd, uint8_t *tx, uint8_t *rx, uint32_t count)
{
flash_cs_force_low();
ssi_hw->dr0 = cmd;
flash_put_get(tx, rx, count, 1);
}
static void flash_put_cmd_addr(uint8_t cmd, uint32_t addr)
{
flash_cs_force_low();
addr |= cmd << 24;
for (int i = 0; i < 4; ++i) {
ssi_hw->dr0 = addr >> 24;
addr <<= 8;
}
}
static void flash_enable_write(void)
{
flash_do_cmd(FLASHCMD_WRITE_ENABLE, (void *)0, (void *)0, 0);
}
static void flash_wait_ready(void)
{
uint8_t stat;
do {
flash_do_cmd(FLASHCMD_READ_STATUS, (void *)0, &stat, 1);
} while (stat & 0x1);
}
void flash_erase(uint32_t addr)
{
flash_enable_write();
flash_put_cmd_addr(FLASHCMD_SECTOR_ERASE, addr);
flash_put_get((void *)0, (void *)0, 0, 4);
flash_wait_ready();
}
void flash_write(uint32_t addr, uint8_t *data)
{
flash_enable_write();
flash_put_cmd_addr(FLASHCMD_PAGE_PROGRAM, addr);
flash_put_get(data, (void *)0, FLASH_WRITE_SIZE, 4);
flash_wait_ready();
}
void flash_read(uint32_t addr, uint8_t *data, uint32_t length)
{
flash_put_cmd_addr(FLASHCMD_READ_DATA, addr);
flash_put_get((void *)0, data, length, 4);
}