mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Merge pull request #2470 from openmv/boot_flash
bootloader: Add common flash interface.
This commit is contained in:
commit
1aafff65db
@ -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;
|
||||
}
|
||||
|
||||
@ -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__
|
||||
@ -35,7 +35,6 @@
|
||||
|
||||
#include "omv_boardconfig.h"
|
||||
#include "omv_bootconfig.h"
|
||||
#include "stm32_flash.h"
|
||||
|
||||
#if OMV_BOOT_AXI_FLASH_ENABLE
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user