Merge pull request #2470 from openmv/boot_flash

bootloader: Add common flash interface.
This commit is contained in:
Ibrahim Abdelkader 2024-10-30 23:40:39 +03:00 committed by GitHub
commit 1aafff65db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 109 additions and 111 deletions

View File

@ -33,6 +33,7 @@
#include <stdint.h>
#include <string.h>
#include "omv_bootconfig.h"
#include "flash.h"
extern bool tud_dfu_detached;
@ -59,9 +60,9 @@ uint32_t tud_dfu_get_timeout_cb(uint8_t itf, uint8_t state) {
}
// Invoked when DFU_DNLOAD is received followed by DFU_GETSTATUS (state=DFU_DNBUSY).
void tud_dfu_download_cb(uint8_t itf, uint16_t block, uint8_t const *src, uint16_t size) {
void tud_dfu_download_cb(uint8_t itf, uint16_t block, uint8_t const *buf, uint16_t size) {
const partition_t *p = &OMV_BOOT_PARTITIONS[itf];
uint8_t *dst = (uint8_t *) (p->start + (block * CFG_TUD_DFU_XFER_BUFSIZE));
uint32_t addr = p->start + (block * CFG_TUD_DFU_XFER_BUFSIZE);
// Check if partition is writable.
if (p->rdonly) {
@ -73,11 +74,11 @@ void tud_dfu_download_cb(uint8_t itf, uint16_t block, uint8_t const *src, uint16
port_mpu_protect(p, false);
}
if ((uint32_t) dst + size > p->limit) {
if (addr + size > p->limit) {
return tud_dfu_finish_flashing(DFU_STATUS_ERR_ADDRESS);
}
if (port_flash_write(p->type, (uint32_t) dst, src, size) == 0) {
if (flash_write(p->type, addr, buf, size) == 0) {
tud_dfu_finish_flashing(DFU_STATUS_OK);
} else {
tud_dfu_finish_flashing(DFU_STATUS_ERR_WRITE);
@ -92,23 +93,22 @@ void tud_dfu_manifest_cb(uint8_t itf) {
}
// Invoked when DFU_UPLOAD request is received.
uint16_t tud_dfu_upload_cb(uint8_t itf, uint16_t block, uint8_t *dst, uint16_t size) {
uint16_t tud_dfu_upload_cb(uint8_t itf, uint16_t block, uint8_t *buf, uint16_t size) {
const partition_t *p = &OMV_BOOT_PARTITIONS[itf];
uint8_t *src = (uint8_t *) (p->start + (block * CFG_TUD_DFU_XFER_BUFSIZE));
uint32_t addr = p->start + (block * CFG_TUD_DFU_XFER_BUFSIZE);
if ((uint32_t) src + size > p->limit) {
if (addr + size > p->limit) {
// Respond with a short frame to indicate EOF to the host.
size = 4;
memset(dst, 0, size);
} else if (port_flash_read(p->type, (uint32_t) src, dst, size) != 0) {
memset(buf, 0, size);
tud_dfu_finish_flashing(DFU_STATUS_OK);
} else if (flash_read(p->type, addr, buf, size) != 0) {
size = 0;
tud_dfu_finish_flashing(DFU_STATUS_ERR_FILE);
} else {
tud_dfu_finish_flashing(DFU_STATUS_OK);
}
if (size) {
tud_dfu_finish_flashing(DFU_STATUS_OK);
} else {
tud_dfu_finish_flashing(DFU_STATUS_ERR_FILE);
}
tud_dfu_detached = false;
return size;
}

View File

@ -28,13 +28,42 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* STM32 Flash driver.
* Bootloader flash interface.
*/
#ifndef __STM32_FLASH_H__
#define __STM32_FLASH_H__
#ifndef __BOOT_FLASH_H__
#define __BOOT_FLASH_H__
int axi_flash_read(uint32_t addr, uint8_t *buf, size_t size);
int axi_flash_write(uint32_t addr, const uint8_t *buf, size_t size);
int spi_flash_deinit();
int spi_flash_read(uint32_t addr, uint8_t *buf, uint32_t size);
int spi_flash_write(uint32_t addr, const uint8_t *buf, uint32_t size);
int spi_flash_deinit();
#endif //__STM32_FLASH_H__
static inline int flash_read(uint32_t ptype, uint32_t addr, uint8_t *buf, uint32_t size) {
#if OMV_BOOT_AXI_FLASH_ENABLE
if (ptype == PTYPE_AXI_FLASH) {
return axi_flash_read(addr, buf, size);
}
#endif
#if OMV_BOOT_SPI_FLASH_ENABLE
if (ptype == PTYPE_SPI_FLASH) {
return spi_flash_read(addr, buf, size);
}
#endif
return -1;
}
static inline int flash_write(uint32_t ptype, uint32_t addr, const uint8_t *buf, uint32_t size) {
#if OMV_BOOT_AXI_FLASH_ENABLE
if (ptype == PTYPE_AXI_FLASH) {
return axi_flash_write(addr, buf, size);
}
#endif
#if OMV_BOOT_SPI_FLASH_ENABLE
if (ptype == PTYPE_SPI_FLASH) {
return spi_flash_write(addr, buf, size);
}
#endif
return -1;
}
#endif //__BOOT_FLASH_H__

View File

@ -35,7 +35,6 @@
#include "omv_boardconfig.h"
#include "omv_bootconfig.h"
#include "stm32_flash.h"
#if OMV_BOOT_AXI_FLASH_ENABLE

View File

@ -36,7 +36,7 @@
#include STM32_HAL_H
#include "omv_boardconfig.h"
#include "omv_bootconfig.h"
#include "stm32_flash.h"
#include "flash.h"
#ifdef USE_USB_FS
#define USB_IRQ_Handler OTG_FS_IRQHandler
@ -226,34 +226,6 @@ void port_led_blink(uint32_t interval_ms) {
start_ms += interval_ms;
}
int port_flash_read(uint32_t ptype, uint32_t addr, uint8_t *buf, uint32_t size) {
#if OMV_BOOT_AXI_FLASH_ENABLE
if (ptype == PTYPE_AXI_FLASH) {
return axi_flash_read(addr, buf, size);
}
#endif
#if OMV_BOOT_SPI_FLASH_ENABLE
if (ptype == PTYPE_SPI_FLASH) {
return spi_flash_read(addr, buf, size);
}
#endif
return -1;
}
int port_flash_write(uint32_t ptype, uint32_t addr, const uint8_t *buf, uint32_t size) {
#if OMV_BOOT_AXI_FLASH_ENABLE
if (ptype == PTYPE_AXI_FLASH) {
return axi_flash_write(addr, buf, size);
}
#endif
#if OMV_BOOT_SPI_FLASH_ENABLE
if (ptype == PTYPE_SPI_FLASH) {
return spi_flash_write(addr, buf, size);
}
#endif
return -1;
}
void __attribute__((noreturn)) __fatal_error() {
while (1) {
port_led_blink(50);

View File

@ -34,7 +34,6 @@
#include STM32_HAL_H
#include "omv_boardconfig.h"
#include "omv_bootconfig.h"
#include "stm32_flash.h"
#if OMV_BOOT_QSPI_FLASH_SIZE
@ -291,50 +290,6 @@ static int qspi_flash_erase_block(uint32_t addr) {
return 0;
}
int __attribute__((optimize("O0"))) qspi_flash_memory_test() {
uint8_t buf[QSPI_PAGE_SIZE];
uint8_t pat[QSPI_PAGE_SIZE];
uint32_t n_pages = OMV_BOOT_QSPI_FLASH_SIZE / QSPI_PAGE_SIZE;
uint32_t n_blocks = OMV_BOOT_QSPI_FLASH_SIZE / QSPI_BLOCK_SIZE;
if (qspi.Instance == NULL || qspi_flash_init() != 0) {
return -1;
}
for (int i = 0; i < QSPI_PAGE_SIZE; i++) {
pat[i] = ((i % 2) == 0) ? 0xaa : 0x55;
}
for (uint32_t i = 0, addr = 0; i < n_blocks; i++, addr += QSPI_BLOCK_SIZE) {
if (qspi_flash_erase_block(addr) != 0) {
return -2;
}
}
for (uint32_t i = 0, addr = 0; i < n_pages; i++, addr += QSPI_PAGE_SIZE) {
if (spi_flash_write(addr, pat, QSPI_PAGE_SIZE) != 0) {
return -3;
}
}
for (uint32_t i = 0, addr = 0; i < n_pages; i++, addr += QSPI_PAGE_SIZE) {
memset(buf, 0, QSPI_PAGE_SIZE);
if (spi_flash_read(addr, buf, QSPI_PAGE_SIZE) != 0) {
return -4;
}
if (memcmp(buf, pat, QSPI_PAGE_SIZE) != 0) {
return -5;
}
}
if (qspi_flash_erase_chip() != 0) {
return -6;
}
return 0;
}
static int qspi_flash_read_page(uint32_t addr, uint8_t *buf, uint32_t size) {
QSPI_CommandTypeDef command = {
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
@ -415,6 +370,66 @@ static int qspi_flash_write_page(uint32_t addr, const uint8_t *buf, uint32_t siz
return 0;
}
int __attribute__((optimize("O0"))) qspi_flash_memory_test() {
uint8_t buf[QSPI_PAGE_SIZE];
uint8_t pat[QSPI_PAGE_SIZE];
uint32_t n_pages = OMV_BOOT_QSPI_FLASH_SIZE / QSPI_PAGE_SIZE;
uint32_t n_blocks = OMV_BOOT_QSPI_FLASH_SIZE / QSPI_BLOCK_SIZE;
if (qspi.Instance == NULL || qspi_flash_init() != 0) {
return -1;
}
for (int i = 0; i < QSPI_PAGE_SIZE; i++) {
pat[i] = ((i % 2) == 0) ? 0xaa : 0x55;
}
for (uint32_t i = 0, addr = 0; i < n_blocks; i++, addr += QSPI_BLOCK_SIZE) {
if (qspi_flash_erase_block(addr) != 0) {
return -2;
}
}
for (uint32_t i = 0, addr = 0; i < n_pages; i++, addr += QSPI_PAGE_SIZE) {
if (qspi_flash_write_page(addr, pat, QSPI_PAGE_SIZE) != 0) {
return -3;
}
}
for (uint32_t i = 0, addr = 0; i < n_pages; i++, addr += QSPI_PAGE_SIZE) {
memset(buf, 0, QSPI_PAGE_SIZE);
if (qspi_flash_read_page(addr, buf, QSPI_PAGE_SIZE) != 0) {
return -4;
}
if (memcmp(buf, pat, QSPI_PAGE_SIZE) != 0) {
return -5;
}
}
if (qspi_flash_erase_chip() != 0) {
return -6;
}
return 0;
}
int spi_flash_deinit() {
if (qspi.Instance != NULL) {
HAL_QSPI_DeInit(&qspi);
qspi.Instance = NULL;
}
// Reset QSPI.
__HAL_RCC_QSPI_FORCE_RESET();
__HAL_RCC_QSPI_RELEASE_RESET();
// Disable QSPI clock.
__HAL_RCC_QSPI_CLK_DISABLE();
memset(&qspi, 0, sizeof(QSPI_HandleTypeDef));
return 0;
}
int spi_flash_read(uint32_t addr, uint8_t *buf, uint32_t size) {
for (size_t i = 0; i < size / QSPI_PAGE_SIZE; i++) {
if (qspi_flash_read_page(addr, buf, QSPI_PAGE_SIZE) != 0) {
@ -455,21 +470,4 @@ int spi_flash_write(uint32_t addr, const uint8_t *buf, uint32_t size) {
}
return 0;
}
int spi_flash_deinit() {
if (qspi.Instance != NULL) {
HAL_QSPI_DeInit(&qspi);
qspi.Instance = NULL;
}
// Reset QSPI.
__HAL_RCC_QSPI_FORCE_RESET();
__HAL_RCC_QSPI_RELEASE_RESET();
// Disable QSPI clock.
__HAL_RCC_QSPI_CLK_DISABLE();
memset(&qspi, 0, sizeof(QSPI_HandleTypeDef));
return 0;
}
#endif // OMV_BOOT_QSPI_FLASH_SIZE