Added external spi flash driver. (#15419)
parent
00cc64638c
commit
71c0b97bce
@ -0,0 +1,24 @@ |
|||||||
|
# FLASH Driver Configuration :id=flash-driver-configuration |
||||||
|
|
||||||
|
The FLASH driver can be swapped out depending on the needs of the keyboard, or whether extra hardware is present. |
||||||
|
|
||||||
|
Driver | Description |
||||||
|
-----------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
||||||
|
`FLASH_DRIVER = spi` | Supports writing to almost all NOR Flash chips. See the driver section below. |
||||||
|
|
||||||
|
|
||||||
|
## SPI FLASH Driver Configuration :id=spi-flash-driver-configuration |
||||||
|
|
||||||
|
Currently QMK supports almost all NOR Flash chips over SPI. As such, requires a working spi_master driver configuration. You can override the driver configuration via your config.h: |
||||||
|
|
||||||
|
`config.h` override | Description | Default Value |
||||||
|
-----------------------------------------------|--------------------------------------------------------------------------------------|----------------- |
||||||
|
`#define EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN` | SPI Slave select pin in order to inform that the FLASH is currently being addressed | _none_ |
||||||
|
`#define EXTERNAL_FLASH_SPI_CLOCK_DIVISOR` | Clock divisor used to divide the peripheral clock to derive the SPI frequency | `8` |
||||||
|
`#define EXTERNAL_FLASH_PAGE_SIZE` | The Page size of the FLASH in bytes, as specified in the datasheet | `256` |
||||||
|
`#define EXTERNAL_FLASH_SECTOR_SIZE` | The sector size of the FLASH in bytes, as specified in the datasheet | `(4 * 1024)` |
||||||
|
`#define EXTERNAL_FLASH_BLOCK_SIZE` | The block size of the FLASH in bytes, as specified in the datasheet | `(64 * 1024)` |
||||||
|
`#define EXTERNAL_FLASH_SIZE` | The total size of the FLASH in bytes, as specified in the datasheet | `(512 * 1024)` |
||||||
|
`#define EXTERNAL_FLASH_ADDRESS_SIZE` | The Flash address size in bytes, as specified in datasheet | `3` |
||||||
|
|
||||||
|
!> All the above default configurations are based on MX25L4006E NOR Flash. |
@ -0,0 +1,372 @@ |
|||||||
|
/*
|
||||||
|
Copyright (C) 2021 Westberry Technology (ChangZhou) Corp., Ltd |
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify |
||||||
|
it under the terms of the GNU General Public License as published by |
||||||
|
the Free Software Foundation, either version 2 of the License, or |
||||||
|
(at your option) any later version. |
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, |
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
GNU General Public License for more details. |
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License |
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/ |
||||||
|
|
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
#include "util.h" |
||||||
|
#include "wait.h" |
||||||
|
#include "debug.h" |
||||||
|
#include "timer.h" |
||||||
|
#include "flash_spi.h" |
||||||
|
#include "spi_master.h" |
||||||
|
|
||||||
|
/*
|
||||||
|
The time-out time of spi flash transmission. |
||||||
|
*/ |
||||||
|
#ifndef EXTERNAL_FLASH_SPI_TIMEOUT |
||||||
|
# define EXTERNAL_FLASH_SPI_TIMEOUT 1000 |
||||||
|
#endif |
||||||
|
|
||||||
|
/* ID comands */ |
||||||
|
#define FLASH_CMD_RDID 0x9F /* RDID (Read Identification) */ |
||||||
|
#define FLASH_CMD_RES 0xAB /* RES (Read Electronic ID) */ |
||||||
|
#define FLASH_CMD_REMS 0x90 /* REMS (Read Electronic & Device ID) */ |
||||||
|
|
||||||
|
/* register comands */ |
||||||
|
#define FLASH_CMD_WRSR 0x01 /* WRSR (Write Status register) */ |
||||||
|
#define FLASH_CMD_RDSR 0x05 /* RDSR (Read Status register) */ |
||||||
|
|
||||||
|
/* READ comands */ |
||||||
|
#define FLASH_CMD_READ 0x03 /* READ (1 x I/O) */ |
||||||
|
#define FLASH_CMD_FASTREAD 0x0B /* FAST READ (Fast read data) */ |
||||||
|
#define FLASH_CMD_DREAD 0x3B /* DREAD (1In/2 Out fast read) */ |
||||||
|
|
||||||
|
/* Program comands */ |
||||||
|
#define FLASH_CMD_WREN 0x06 /* WREN (Write Enable) */ |
||||||
|
#define FLASH_CMD_WRDI 0x04 /* WRDI (Write Disable) */ |
||||||
|
#define FLASH_CMD_PP 0x02 /* PP (page program) */ |
||||||
|
|
||||||
|
/* Erase comands */ |
||||||
|
#define FLASH_CMD_SE 0x20 /* SE (Sector Erase) */ |
||||||
|
#define FLASH_CMD_BE 0xD8 /* BE (Block Erase) */ |
||||||
|
#define FLASH_CMD_CE 0x60 /* CE (Chip Erase) hex code: 60 or C7 */ |
||||||
|
|
||||||
|
/* Mode setting comands */ |
||||||
|
#define FLASH_CMD_DP 0xB9 /* DP (Deep Power Down) */ |
||||||
|
#define FLASH_CMD_RDP 0xAB /* RDP (Release form Deep Power Down) */ |
||||||
|
|
||||||
|
/* Status register */ |
||||||
|
#define FLASH_FLAG_WIP 0x01 /* Write in progress bit */ |
||||||
|
#define FLASH_FLAG_WEL 0x02 /* Write enable latch bit */ |
||||||
|
|
||||||
|
// #define DEBUG_FLASH_SPI_OUTPUT
|
||||||
|
|
||||||
|
static bool spi_flash_start(void) { return spi_start(EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN, EXTERNAL_FLASH_SPI_LSBFIRST, EXTERNAL_FLASH_SPI_MODE, EXTERNAL_FLASH_SPI_CLOCK_DIVISOR); } |
||||||
|
|
||||||
|
static flash_status_t spi_flash_wait_while_busy(void) { |
||||||
|
uint32_t deadline = timer_read32() + EXTERNAL_FLASH_SPI_TIMEOUT; |
||||||
|
flash_status_t response = FLASH_STATUS_SUCCESS; |
||||||
|
uint8_t retval; |
||||||
|
|
||||||
|
do { |
||||||
|
bool res = spi_flash_start(); |
||||||
|
if (!res) { |
||||||
|
dprint("Failed to start SPI! [spi flash wait while busy]\n"); |
||||||
|
return FLASH_STATUS_ERROR; |
||||||
|
} |
||||||
|
|
||||||
|
spi_write(FLASH_CMD_RDSR); |
||||||
|
|
||||||
|
retval = (uint8_t)spi_read(); |
||||||
|
|
||||||
|
spi_stop(); |
||||||
|
|
||||||
|
if (timer_read32() >= deadline) { |
||||||
|
response = FLASH_STATUS_TIMEOUT; |
||||||
|
break; |
||||||
|
} |
||||||
|
} while (retval & FLASH_FLAG_WIP); |
||||||
|
|
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
static flash_status_t spi_flash_write_enable(void) { |
||||||
|
bool res = spi_flash_start(); |
||||||
|
if (!res) { |
||||||
|
dprint("Failed to start SPI! [spi flash write enable]\n"); |
||||||
|
return FLASH_STATUS_ERROR; |
||||||
|
} |
||||||
|
|
||||||
|
spi_write(FLASH_CMD_WREN); |
||||||
|
|
||||||
|
spi_stop(); |
||||||
|
|
||||||
|
return FLASH_STATUS_SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
static flash_status_t spi_flash_write_disable(void) { |
||||||
|
bool res = spi_flash_start(); |
||||||
|
if (!res) { |
||||||
|
dprint("Failed to start SPI! [spi flash write disable]\n"); |
||||||
|
return FLASH_STATUS_ERROR; |
||||||
|
} |
||||||
|
|
||||||
|
spi_write(FLASH_CMD_WRDI); |
||||||
|
|
||||||
|
spi_stop(); |
||||||
|
|
||||||
|
return FLASH_STATUS_SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
/* This function is used for read transfer, write transfer and erase transfer. */ |
||||||
|
static flash_status_t spi_flash_transaction(uint8_t cmd, uint32_t addr, uint8_t *data, size_t len) { |
||||||
|
flash_status_t response = FLASH_STATUS_SUCCESS; |
||||||
|
uint8_t buffer[EXTERNAL_FLASH_ADDRESS_SIZE + 1]; |
||||||
|
|
||||||
|
buffer[0] = cmd; |
||||||
|
for (int i = 0; i < EXTERNAL_FLASH_ADDRESS_SIZE; ++i) { |
||||||
|
buffer[EXTERNAL_FLASH_ADDRESS_SIZE - i] = addr & 0xFF; |
||||||
|
addr >>= 8; |
||||||
|
} |
||||||
|
|
||||||
|
bool res = spi_flash_start(); |
||||||
|
if (!res) { |
||||||
|
dprint("Failed to start SPI! [spi flash transmit]\n"); |
||||||
|
return FLASH_STATUS_ERROR; |
||||||
|
} |
||||||
|
|
||||||
|
response = spi_transmit(buffer, sizeof(buffer)); |
||||||
|
|
||||||
|
if ((!response) && (data != NULL)) { |
||||||
|
switch (cmd) { |
||||||
|
case FLASH_CMD_READ: |
||||||
|
response = spi_receive(data, len); |
||||||
|
break; |
||||||
|
case FLASH_CMD_PP: |
||||||
|
response = spi_transmit(data, len); |
||||||
|
break; |
||||||
|
default: |
||||||
|
response = FLASH_STATUS_ERROR; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
spi_stop(); |
||||||
|
|
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
void flash_init(void) { spi_init(); } |
||||||
|
|
||||||
|
flash_status_t flash_erase_chip(void) { |
||||||
|
flash_status_t response = FLASH_STATUS_SUCCESS; |
||||||
|
|
||||||
|
/* Wait for the write-in-progress bit to be cleared. */ |
||||||
|
response = spi_flash_wait_while_busy(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to check WIP flag! [spi flash erase chip]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
/* Enable writes. */ |
||||||
|
response = spi_flash_write_enable(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to write-enable! [spi flash erase chip]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
/* Erase Chip. */ |
||||||
|
bool res = spi_flash_start(); |
||||||
|
if (!res) { |
||||||
|
dprint("Failed to start SPI! [spi flash erase chip]\n"); |
||||||
|
return FLASH_STATUS_ERROR; |
||||||
|
} |
||||||
|
spi_write(FLASH_CMD_CE); |
||||||
|
spi_stop(); |
||||||
|
|
||||||
|
/* Wait for the write-in-progress bit to be cleared.*/ |
||||||
|
response = spi_flash_wait_while_busy(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to check WIP flag! [spi flash erase chip]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
flash_status_t flash_erase_sector(uint32_t addr) { |
||||||
|
flash_status_t response = FLASH_STATUS_SUCCESS; |
||||||
|
|
||||||
|
/* Check that the address exceeds the limit. */ |
||||||
|
if ((addr + (EXTERNAL_FLASH_SECTOR_SIZE)) >= (EXTERNAL_FLASH_SIZE) || ((addr % (EXTERNAL_FLASH_SECTOR_SIZE)) != 0)) { |
||||||
|
dprintf("Flash erase sector address over limit! [addr:0x%x]\n", (uint32_t)addr); |
||||||
|
return FLASH_STATUS_ERROR; |
||||||
|
} |
||||||
|
|
||||||
|
/* Wait for the write-in-progress bit to be cleared. */ |
||||||
|
response = spi_flash_wait_while_busy(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to check WIP flag! [spi flash erase sector]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
/* Enable writes. */ |
||||||
|
response = spi_flash_write_enable(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to write-enable! [spi flash erase sector]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
/* Erase Sector. */ |
||||||
|
response = spi_flash_transaction(FLASH_CMD_SE, addr, NULL, 0); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to erase sector! [spi flash erase sector]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
/* Wait for the write-in-progress bit to be cleared.*/ |
||||||
|
response = spi_flash_wait_while_busy(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to check WIP flag! [spi flash erase sector]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
flash_status_t flash_erase_block(uint32_t addr) { |
||||||
|
flash_status_t response = FLASH_STATUS_SUCCESS; |
||||||
|
|
||||||
|
/* Check that the address exceeds the limit. */ |
||||||
|
if ((addr + (EXTERNAL_FLASH_BLOCK_SIZE)) >= (EXTERNAL_FLASH_SIZE) || ((addr % (EXTERNAL_FLASH_BLOCK_SIZE)) != 0)) { |
||||||
|
dprintf("Flash erase block address over limit! [addr:0x%x]\n", (uint32_t)addr); |
||||||
|
return FLASH_STATUS_ERROR; |
||||||
|
} |
||||||
|
|
||||||
|
/* Wait for the write-in-progress bit to be cleared. */ |
||||||
|
response = spi_flash_wait_while_busy(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to check WIP flag! [spi flash erase block]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
/* Enable writes. */ |
||||||
|
response = spi_flash_write_enable(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to write-enable! [spi flash erase block]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
/* Erase Block. */ |
||||||
|
response = spi_flash_transaction(FLASH_CMD_BE, addr, NULL, 0); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to erase block! [spi flash erase block]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
/* Wait for the write-in-progress bit to be cleared.*/ |
||||||
|
response = spi_flash_wait_while_busy(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to check WIP flag! [spi flash erase block]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
flash_status_t flash_read_block(uint32_t addr, void *buf, size_t len) { |
||||||
|
flash_status_t response = FLASH_STATUS_SUCCESS; |
||||||
|
uint8_t * read_buf = (uint8_t *)buf; |
||||||
|
|
||||||
|
/* Wait for the write-in-progress bit to be cleared. */ |
||||||
|
response = spi_flash_wait_while_busy(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to check WIP flag! [spi flash read block]\n"); |
||||||
|
memset(read_buf, 0, len); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
/* Perform read. */ |
||||||
|
response = spi_flash_transaction(FLASH_CMD_READ, addr, read_buf, len); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to read block! [spi flash read block]\n"); |
||||||
|
memset(read_buf, 0, len); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
#if defined(CONSOLE_ENABLE) && defined(DEBUG_FLASH_SPI_OUTPUT) |
||||||
|
dprintf("[SPI FLASH R] 0x%08lX: ", addr); |
||||||
|
for (size_t i = 0; i < len; ++i) { |
||||||
|
dprintf(" %02X", (int)(((uint8_t *)read_buf)[i])); |
||||||
|
} |
||||||
|
dprintf("\n"); |
||||||
|
#endif // DEBUG_FLASH_SPI_OUTPUT
|
||||||
|
|
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
flash_status_t flash_write_block(uint32_t addr, const void *buf, size_t len) { |
||||||
|
flash_status_t response = FLASH_STATUS_SUCCESS; |
||||||
|
uint8_t * write_buf = (uint8_t *)buf; |
||||||
|
|
||||||
|
while (len > 0) { |
||||||
|
uint32_t page_offset = addr % EXTERNAL_FLASH_PAGE_SIZE; |
||||||
|
size_t write_length = EXTERNAL_FLASH_PAGE_SIZE - page_offset; |
||||||
|
if (write_length > len) { |
||||||
|
write_length = len; |
||||||
|
} |
||||||
|
|
||||||
|
/* Wait for the write-in-progress bit to be cleared. */ |
||||||
|
response = spi_flash_wait_while_busy(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to check WIP flag! [spi flash write block]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
/* Enable writes. */ |
||||||
|
response = spi_flash_write_enable(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to write-enable! [spi flash write block]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
#if defined(CONSOLE_ENABLE) && defined(DEBUG_FLASH_SPI_OUTPUT) |
||||||
|
dprintf("[SPI FLASH W] 0x%08lX: ", addr); |
||||||
|
for (size_t i = 0; i < write_length; i++) { |
||||||
|
dprintf(" %02X", (int)(uint8_t)(write_buf[i])); |
||||||
|
} |
||||||
|
dprintf("\n"); |
||||||
|
#endif // DEBUG_FLASH_SPI_OUTPUT
|
||||||
|
|
||||||
|
/* Perform the write. */ |
||||||
|
response = spi_flash_transaction(FLASH_CMD_PP, addr, write_buf, write_length); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to write block! [spi flash write block]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
write_buf += write_length; |
||||||
|
addr += write_length; |
||||||
|
len -= write_length; |
||||||
|
} |
||||||
|
|
||||||
|
/* Wait for the write-in-progress bit to be cleared. */ |
||||||
|
response = spi_flash_wait_while_busy(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to check WIP flag! [spi flash write block]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
/* Disable writes. */ |
||||||
|
response = spi_flash_write_disable(); |
||||||
|
if (response != FLASH_STATUS_SUCCESS) { |
||||||
|
dprint("Failed to write-disable! [spi flash write block]\n"); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
return response; |
||||||
|
} |
@ -0,0 +1,136 @@ |
|||||||
|
/*
|
||||||
|
Copyright (C) 2021 Westberry Technology (ChangZhou) Corp., Ltd |
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify |
||||||
|
it under the terms of the GNU General Public License as published by |
||||||
|
the Free Software Foundation, either version 2 of the License, or |
||||||
|
(at your option) any later version. |
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, |
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
GNU General Public License for more details. |
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License |
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/ |
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
/* All the following default configurations are based on MX25L4006E Nor FLASH. */ |
||||||
|
|
||||||
|
/*
|
||||||
|
The slave select pin of the FLASH. |
||||||
|
This needs to be a normal GPIO pin_t value, such as B14. |
||||||
|
*/ |
||||||
|
#ifndef EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN |
||||||
|
# error "No chip select pin defined -- missing EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN" |
||||||
|
#endif |
||||||
|
|
||||||
|
/*
|
||||||
|
The clock divisor for SPI to ensure that the MCU is within the |
||||||
|
specifications of the FLASH chip. Generally this will be PCLK divided by |
||||||
|
the intended divisor -- check your clock settings and the datasheet of |
||||||
|
your FLASH. |
||||||
|
*/ |
||||||
|
#ifndef EXTERNAL_FLASH_SPI_CLOCK_DIVISOR |
||||||
|
# ifdef __AVR__ |
||||||
|
# define EXTERNAL_FLASH_SPI_CLOCK_DIVISOR 4 |
||||||
|
# else |
||||||
|
# define EXTERNAL_FLASH_SPI_CLOCK_DIVISOR 8 |
||||||
|
# endif |
||||||
|
#endif |
||||||
|
|
||||||
|
/*
|
||||||
|
The SPI mode to communicate with the FLASH. |
||||||
|
*/ |
||||||
|
#ifndef EXTERNAL_FLASH_SPI_MODE |
||||||
|
# define EXTERNAL_FLASH_SPI_MODE 0 |
||||||
|
#endif |
||||||
|
|
||||||
|
/*
|
||||||
|
Whether or not the SPI communication between the MCU and FLASH should be |
||||||
|
LSB-first. |
||||||
|
*/ |
||||||
|
#ifndef EXTERNAL_FLASH_SPI_LSBFIRST |
||||||
|
# define EXTERNAL_FLASH_SPI_LSBFIRST false |
||||||
|
#endif |
||||||
|
|
||||||
|
/*
|
||||||
|
The Flash address size in bytes, as specified in datasheet. |
||||||
|
*/ |
||||||
|
#ifndef EXTERNAL_FLASH_ADDRESS_SIZE |
||||||
|
# define EXTERNAL_FLASH_ADDRESS_SIZE 3 |
||||||
|
#endif |
||||||
|
|
||||||
|
/*
|
||||||
|
The page size of the FLASH in bytes, as specified in the datasheet. |
||||||
|
*/ |
||||||
|
#ifndef EXTERNAL_FLASH_PAGE_SIZE |
||||||
|
# define EXTERNAL_FLASH_PAGE_SIZE 256 |
||||||
|
#endif |
||||||
|
|
||||||
|
/*
|
||||||
|
The sector size of the FLASH in bytes, as specified in the datasheet. |
||||||
|
*/ |
||||||
|
#ifndef EXTERNAL_FLASH_SECTOR_SIZE |
||||||
|
# define EXTERNAL_FLASH_SECTOR_SIZE (4 * 1024) |
||||||
|
#endif |
||||||
|
|
||||||
|
/*
|
||||||
|
The block size of the FLASH in bytes, as specified in the datasheet. |
||||||
|
*/ |
||||||
|
#ifndef EXTERNAL_FLASH_BLOCK_SIZE |
||||||
|
# define EXTERNAL_FLASH_BLOCK_SIZE (64 * 1024) |
||||||
|
#endif |
||||||
|
|
||||||
|
/*
|
||||||
|
The total size of the FLASH in bytes, as specified in the datasheet. |
||||||
|
*/ |
||||||
|
#ifndef EXTERNAL_FLASH_SIZE |
||||||
|
# define EXTERNAL_FLASH_SIZE (512 * 1024) |
||||||
|
#endif |
||||||
|
|
||||||
|
/*
|
||||||
|
The block count of the FLASH, calculated by total FLASH size and block size. |
||||||
|
*/ |
||||||
|
#define EXTERNAL_FLASH_BLOCK_COUNT ((EXTERNAL_FLASH_SIZE) / (EXTERNAL_FLASH_BLOCK_SIZE)) |
||||||
|
|
||||||
|
/*
|
||||||
|
The sector count of the FLASH, calculated by total FLASH size and sector size. |
||||||
|
*/ |
||||||
|
#define EXTERNAL_FLASH_SECTOR_COUNT ((EXTERNAL_FLASH_SIZE) / (EXTERNAL_FLASH_SECTOR_SIZE)) |
||||||
|
|
||||||
|
/*
|
||||||
|
The page count of the FLASH, calculated by total FLASH size and page size. |
||||||
|
*/ |
||||||
|
#define EXTERNAL_FLASH_PAGE_COUNT ((EXTERNAL_FLASH_SIZE) / (EXTERNAL_FLASH_PAGE_SIZE)) |
||||||
|
|
||||||
|
typedef int16_t flash_status_t; |
||||||
|
|
||||||
|
#define FLASH_STATUS_SUCCESS (0) |
||||||
|
#define FLASH_STATUS_ERROR (-1) |
||||||
|
#define FLASH_STATUS_TIMEOUT (-2) |
||||||
|
#define FLASH_STATUS_BAD_ADDRESS (-3) |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
void flash_init(void); |
||||||
|
|
||||||
|
flash_status_t flash_erase_chip(void); |
||||||
|
|
||||||
|
flash_status_t flash_erase_block(uint32_t addr); |
||||||
|
|
||||||
|
flash_status_t flash_erase_sector(uint32_t addr); |
||||||
|
|
||||||
|
flash_status_t flash_read_block(uint32_t addr, void *buf, size_t len); |
||||||
|
|
||||||
|
flash_status_t flash_write_block(uint32_t addr, const void *buf, size_t len); |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} |
||||||
|
#endif |
Loading…
Reference in new issue