mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Add bootloader QSPI flash support.
This commit is contained in:
parent
32205dc5c4
commit
d655642847
@ -12,6 +12,7 @@
|
||||
#include "usbdev/usbd_cdc.h"
|
||||
#include "usbdev/usbd_desc.h"
|
||||
#include "omv_boardconfig.h"
|
||||
#include "qspif.h"
|
||||
|
||||
#define IDE_TIMEOUT (1000)
|
||||
#define CONFIG_TIMEOUT (2000)
|
||||
@ -52,6 +53,12 @@ int main()
|
||||
|
||||
HAL_Init();
|
||||
|
||||
#if defined(OMV_QSPIF_LAYOUT)
|
||||
if (qspif_init() != 0) {
|
||||
__fatal_error();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Init Device Library */
|
||||
USBD_Init(&USBD_Device, &VCP_Desc, 0);
|
||||
|
||||
@ -95,6 +102,11 @@ int main()
|
||||
// Deinit USB
|
||||
USBD_DeInit(&USBD_Device);
|
||||
|
||||
#if defined(OMV_QSPIF_LAYOUT)
|
||||
qspif_reset();
|
||||
qspif_deinit();
|
||||
#endif
|
||||
|
||||
// Disable IRQs
|
||||
__disable_irq(); __DSB(); __ISB();
|
||||
|
||||
|
||||
@ -46,3 +46,82 @@ void HAL_MspInit()
|
||||
HAL_GPIO_Init(OMV_BOOTLDR_LED_PORT, &GPIO_InitStructure);
|
||||
HAL_GPIO_WritePin(OMV_BOOTLDR_LED_PORT, OMV_BOOTLDR_LED_PIN, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
#if defined(OMV_QSPIF_LAYOUT)
|
||||
void HAL_QSPI_MspInit(QSPI_HandleTypeDef *hqspi)
|
||||
{
|
||||
GPIO_InitTypeDef gpio_init_structure;
|
||||
|
||||
/*##-1- Enable peripherals and GPIO Clocks #################################*/
|
||||
/* Enable the QuadSPI memory interface clock */
|
||||
QSPIF_CLK_ENABLE();
|
||||
|
||||
/* Reset the QuadSPI memory interface */
|
||||
QSPIF_FORCE_RESET();
|
||||
QSPIF_RELEASE_RESET();
|
||||
|
||||
/* Enable GPIO clocks */
|
||||
QSPIF_CLK_GPIO_CLK_ENABLE();
|
||||
QSPIF_CS_GPIO_CLK_ENABLE();
|
||||
QSPIF_D0_GPIO_CLK_ENABLE();
|
||||
QSPIF_D1_GPIO_CLK_ENABLE();
|
||||
QSPIF_D2_GPIO_CLK_ENABLE();
|
||||
QSPIF_D3_GPIO_CLK_ENABLE();
|
||||
|
||||
/*##-2- Configure peripheral GPIO ##########################################*/
|
||||
/* QSPI CLK GPIO pin configuration */
|
||||
gpio_init_structure.Pin = QSPIF_CLK_PIN;
|
||||
gpio_init_structure.Mode = GPIO_MODE_AF_PP;
|
||||
gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
gpio_init_structure.Pull = GPIO_NOPULL;
|
||||
gpio_init_structure.Alternate = QSPIF_CLK_ALT;
|
||||
HAL_GPIO_Init(QSPIF_CLK_PORT, &gpio_init_structure);
|
||||
|
||||
/* QSPI CS GPIO pin configuration */
|
||||
gpio_init_structure.Pin = QSPIF_CS_PIN;
|
||||
gpio_init_structure.Pull = GPIO_PULLUP;
|
||||
gpio_init_structure.Alternate = QSPIF_CS_ALT;
|
||||
HAL_GPIO_Init(QSPIF_CS_PORT, &gpio_init_structure);
|
||||
|
||||
/* QSPI D0 GPIO pin configuration */
|
||||
gpio_init_structure.Pin = QSPIF_D0_PIN;
|
||||
gpio_init_structure.Pull = GPIO_NOPULL;
|
||||
gpio_init_structure.Alternate = QSPIF_D0_ALT;
|
||||
HAL_GPIO_Init(QSPIF_D0_PORT, &gpio_init_structure);
|
||||
|
||||
/* QSPI D1 GPIO pin configuration */
|
||||
gpio_init_structure.Pin = QSPIF_D1_PIN;
|
||||
gpio_init_structure.Alternate = QSPIF_D1_ALT;
|
||||
HAL_GPIO_Init(QSPIF_D1_PORT, &gpio_init_structure);
|
||||
|
||||
/* QSPI D2 GPIO pin configuration */
|
||||
gpio_init_structure.Pin = QSPIF_D2_PIN;
|
||||
gpio_init_structure.Alternate = QSPIF_D2_ALT;
|
||||
HAL_GPIO_Init(QSPIF_D2_PORT, &gpio_init_structure);
|
||||
|
||||
/* QSPI D3 GPIO pin configuration */
|
||||
gpio_init_structure.Pin = QSPIF_D3_PIN;
|
||||
gpio_init_structure.Alternate = QSPIF_D3_ALT;
|
||||
HAL_GPIO_Init(QSPIF_D3_PORT, &gpio_init_structure);
|
||||
}
|
||||
|
||||
void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi)
|
||||
{
|
||||
/*##-1- Disable peripherals and GPIO Clocks ################################*/
|
||||
/* De-Configure QSPI pins */
|
||||
HAL_GPIO_DeInit(QSPIF_CLK_PORT, QSPIF_CLK_PIN);
|
||||
HAL_GPIO_DeInit(QSPIF_CS_PORT, QSPIF_CS_PIN);
|
||||
HAL_GPIO_DeInit(QSPIF_D0_PORT, QSPIF_D0_PIN);
|
||||
HAL_GPIO_DeInit(QSPIF_D1_PORT, QSPIF_D1_PIN);
|
||||
HAL_GPIO_DeInit(QSPIF_D2_PORT, QSPIF_D2_PIN);
|
||||
HAL_GPIO_DeInit(QSPIF_D3_PORT, QSPIF_D3_PIN);
|
||||
|
||||
/*##-2- Reset peripherals ##################################################*/
|
||||
/* Reset the QuadSPI memory interface */
|
||||
QSPIF_FORCE_RESET();
|
||||
QSPIF_RELEASE_RESET();
|
||||
|
||||
/* Disable the QuadSPI memory interface clock */
|
||||
QSPIF_CLK_DISABLE();
|
||||
}
|
||||
#endif // OMV_QSPIF_LAYOUT
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include "flash.h"
|
||||
#include "usbdev/usbd_cdc.h"
|
||||
#include "omv_boardconfig.h"
|
||||
#include "qspif.h"
|
||||
|
||||
#define APP_RX_DATA_SIZE (2048)
|
||||
#define APP_TX_DATA_SIZE (2048)
|
||||
@ -29,7 +30,15 @@ static volatile uint8_t vcp_connected = 0;
|
||||
static volatile uint32_t flash_buf_idx=0;
|
||||
static volatile uint8_t flash_buf[FLASH_BUF_SIZE];
|
||||
static const uint32_t flash_layout[3] = OMV_FLASH_LAYOUT;
|
||||
static const uint32_t bootloader_version = 0xABCD0002;
|
||||
#if defined(OMV_QSPIF_LAYOUT)
|
||||
#define QSPIF_BUF_SIZE QSPIF_PAGE_SIZE
|
||||
static volatile uint32_t qspif_buf_idx=0;
|
||||
static volatile uint8_t qspif_buf[QSPIF_BUF_SIZE];
|
||||
static const uint32_t qspif_layout[3] = OMV_QSPIF_LAYOUT;
|
||||
#else
|
||||
static const uint32_t qspif_layout[3] = {0, 0, 0};
|
||||
#endif
|
||||
static const uint32_t bootloader_version = 0xABCD0003;
|
||||
|
||||
/* USB handler declaration */
|
||||
extern USBD_HandleTypeDef USBD_Device;
|
||||
@ -41,14 +50,18 @@ static int8_t CDC_Itf_Control(uint8_t cmd, uint8_t* pbuf, uint16_t length);
|
||||
static int8_t CDC_Itf_Receive(uint8_t* pbuf, uint32_t *Len);
|
||||
|
||||
enum bootldr_cmd {
|
||||
BOOTLDR_START = 0xABCD0001,
|
||||
BOOTLDR_RESET = 0xABCD0002,
|
||||
BOOTLDR_ERASE = 0xABCD0004,
|
||||
BOOTLDR_WRITE = 0xABCD0008,
|
||||
BOOTLDR_FLASH = 0xABCD0010,
|
||||
BOOTLDR_START = 0xABCD0001,
|
||||
BOOTLDR_RESET = 0xABCD0002,
|
||||
BOOTLDR_FLASH_ERASE = 0xABCD0004,
|
||||
BOOTLDR_FLASH_WRITE = 0xABCD0008,
|
||||
BOOTLDR_FLASH_LAYOUT = 0xABCD0010,
|
||||
BOOTLDR_QSPIF_ERASE = 0xABCD1004,
|
||||
BOOTLDR_QSPIF_WRITE = 0xABCD1008,
|
||||
BOOTLDR_QSPIF_LAYOUT = 0xABCD1010,
|
||||
BOOTLDR_QSPIF_MEMTEST = 0xABCD1020,
|
||||
};
|
||||
|
||||
USBD_CDC_ItfTypeDef USBD_CDC_fops =
|
||||
USBD_CDC_ItfTypeDef USBD_CDC_fops =
|
||||
{
|
||||
CDC_Itf_Init,
|
||||
CDC_Itf_DeInit,
|
||||
@ -85,7 +98,7 @@ static int8_t CDC_Itf_DeInit(void)
|
||||
/**
|
||||
* @brief CDC_Itf_Control
|
||||
* Manage the CDC class requests
|
||||
* @param Cmd: Command code
|
||||
* @param Cmd: Command code
|
||||
* @param Buf: Buffer containing command data (request parameters)
|
||||
* @param Len: Number of data to be sent (in bytes)
|
||||
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
|
||||
@ -128,7 +141,7 @@ static int8_t CDC_Itf_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length)
|
||||
pbuf[3] = (uint8_t)(LineCoding.bitrate >> 24);
|
||||
pbuf[4] = LineCoding.format;
|
||||
pbuf[5] = LineCoding.paritytype;
|
||||
pbuf[6] = LineCoding.datatype;
|
||||
pbuf[6] = LineCoding.datatype;
|
||||
break;
|
||||
|
||||
case CDC_SET_CONTROL_LINE_STATE:
|
||||
@ -137,7 +150,7 @@ static int8_t CDC_Itf_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length)
|
||||
|
||||
case CDC_SEND_BREAK:
|
||||
/* Add your code here */
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -187,7 +200,7 @@ void CDC_Tx(uint8_t *buf, uint32_t len)
|
||||
|
||||
/**
|
||||
* @brief CDC_Itf_DataRx
|
||||
* Data received over USB OUT endpoint are sent over CDC interface
|
||||
* Data received over USB OUT endpoint are sent over CDC interface
|
||||
* through this function.
|
||||
* @param Buf: Buffer of data to be transmitted
|
||||
* @param Len: Number of data received (in bytes)
|
||||
@ -196,38 +209,37 @@ void CDC_Tx(uint8_t *buf, uint32_t len)
|
||||
static int8_t CDC_Itf_Receive(uint8_t *Buf, uint32_t *Len)
|
||||
{
|
||||
static volatile uint32_t flash_offset;
|
||||
#if defined(OMV_QSPIF_LAYOUT)
|
||||
static volatile uint32_t qspif_offset=0;
|
||||
#endif
|
||||
|
||||
uint32_t *cmd_buf = (uint32_t*) Buf;
|
||||
uint32_t *cmd_buf = (uint32_t*) Buf;
|
||||
uint32_t cmd = *cmd_buf++;
|
||||
|
||||
switch (cmd) {
|
||||
case BOOTLDR_START:
|
||||
flash_buf_idx = 0;
|
||||
#if defined(OMV_QSPIF_LAYOUT)
|
||||
qspif_buf_idx = 0;
|
||||
#endif
|
||||
ide_connected = 1;
|
||||
flash_offset = MAIN_APP_ADDR;
|
||||
// Send back the bootloader version.
|
||||
CDC_Tx((uint8_t *) &bootloader_version, 4);
|
||||
break;
|
||||
case BOOTLDR_FLASH:
|
||||
|
||||
case BOOTLDR_FLASH_LAYOUT:
|
||||
// Return flash layout (bootloader v2)
|
||||
CDC_Tx((uint8_t*) flash_layout, 12);
|
||||
break;
|
||||
case BOOTLDR_RESET:
|
||||
ide_connected = 0;
|
||||
if (flash_buf_idx) {
|
||||
// Pad and flush the last packet
|
||||
for (int i=flash_buf_idx; i<FLASH_BUF_SIZE; i++) {
|
||||
flash_buf[i] = 0xFF;
|
||||
}
|
||||
flash_write((uint32_t*)flash_buf, flash_offset, FLASH_BUF_SIZE);
|
||||
}
|
||||
break;
|
||||
case BOOTLDR_ERASE: {
|
||||
uint32_t sector = *cmd_buf;
|
||||
|
||||
case BOOTLDR_FLASH_ERASE: {
|
||||
uint32_t sector = *cmd_buf;
|
||||
flash_erase(sector);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case BOOTLDR_WRITE: {
|
||||
|
||||
case BOOTLDR_FLASH_WRITE: {
|
||||
uint8_t *buf = Buf + 4;
|
||||
uint32_t len = *Len - 4;
|
||||
for (int i=0; i<len; i++) {
|
||||
@ -240,6 +252,64 @@ static int8_t CDC_Itf_Receive(uint8_t *Buf, uint32_t *Len)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BOOTLDR_QSPIF_LAYOUT:
|
||||
CDC_Tx((uint8_t*) qspif_layout, 12);
|
||||
break;
|
||||
|
||||
case BOOTLDR_QSPIF_ERASE: {
|
||||
#if defined(OMV_QSPIF_LAYOUT)
|
||||
uint32_t block = *cmd_buf;
|
||||
qspif_erase_block(block * QSPIF_BLOCK_SIZE);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case BOOTLDR_QSPIF_WRITE: {
|
||||
#if defined(OMV_QSPIF_LAYOUT)
|
||||
uint8_t *buf = Buf + 4;
|
||||
uint32_t len = *Len - 4;
|
||||
for (int i=0; i<len; i++) {
|
||||
qspif_buf[qspif_buf_idx++] = buf[i];
|
||||
if (qspif_buf_idx == QSPIF_BUF_SIZE) {
|
||||
qspif_buf_idx = 0;
|
||||
qspif_write((uint8_t*) qspif_buf, qspif_offset, QSPIF_BUF_SIZE);
|
||||
qspif_offset += QSPIF_BUF_SIZE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case BOOTLDR_QSPIF_MEMTEST: {
|
||||
uint32_t qspif_test = 0;
|
||||
#if defined(OMV_QSPIF_LAYOUT)
|
||||
qspif_test = (qspif_memory_test() == 0);
|
||||
#endif
|
||||
CDC_Tx((uint8_t*) &qspif_test, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
case BOOTLDR_RESET: {
|
||||
ide_connected = 0;
|
||||
if (flash_buf_idx) {
|
||||
// Pad and flush the last packet
|
||||
for (int i=flash_buf_idx; i<FLASH_BUF_SIZE; i++) {
|
||||
flash_buf[i] = 0xFF;
|
||||
}
|
||||
flash_write((uint32_t*)flash_buf, flash_offset, FLASH_BUF_SIZE);
|
||||
}
|
||||
#if defined(OMV_QSPIF_LAYOUT)
|
||||
if (qspif_buf_idx) {
|
||||
// Pad and flush the last packet
|
||||
for (int i=qspif_buf_idx; i<QSPIF_BUF_SIZE; i++) {
|
||||
qspif_buf[i] = 0xFF;
|
||||
}
|
||||
qspif_write((uint8_t*) qspif_buf, qspif_offset, QSPIF_BUF_SIZE);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Initiate next USB packet transfer
|
||||
|
||||
@ -20,6 +20,10 @@
|
||||
// Flash FS sector, main FW sector, max sector.
|
||||
#define OMV_FLASH_LAYOUT {1, 2, 15}
|
||||
|
||||
// QSPI Flash layout for the bootloader.
|
||||
// First block, maximum block, block size in bytes.
|
||||
#define OMV_QSPIF_LAYOUT {0, 511, 64*1024}
|
||||
|
||||
#define OMV_XCLK_MCO (0U)
|
||||
#define OMV_XCLK_TIM (1U)
|
||||
|
||||
@ -247,6 +251,57 @@
|
||||
#define LEPTON_SPI_MOSI_PORT (GPIOB)
|
||||
#define LEPTON_SPI_SSEL_PORT (GPIOA)
|
||||
|
||||
// QSPI flash configuration for the bootloader.
|
||||
#define QSPIF_SIZE_BITS (25) // 2**25 == 32MBytes.
|
||||
#define QSPIF_SR_WIP_MASK (1 << 0)
|
||||
#define QSPIF_SR_WEL_MASK (1 << 1)
|
||||
#define QSPIF_READ_QUADIO_DCYC (6)
|
||||
|
||||
#define QSPIF_PAGE_SIZE (0x100) // 256 bytes pages.
|
||||
#define QSPIF_NUM_PAGES (0x20000) // 131072 pages of 256 bytes
|
||||
|
||||
#define QSPIF_SECTOR_SIZE (0x1000) // 4K bytes sectors.
|
||||
#define QSPIF_NUM_SECTORS (0x2000) // 8192 sectors of 4K bytes
|
||||
|
||||
#define QSPIF_BLOCK_SIZE (0x10000) // 64K bytes blocks.
|
||||
#define QSPIF_NUM_BLOCKS (0x200) // 512 blocks of 64K bytes
|
||||
|
||||
#define QSPIF_CLK_PIN (GPIO_PIN_10)
|
||||
#define QSPIF_CLK_PORT (GPIOF)
|
||||
#define QSPIF_CLK_ALT (GPIO_AF9_QUADSPI)
|
||||
|
||||
#define QSPIF_CS_PIN (GPIO_PIN_6)
|
||||
#define QSPIF_CS_PORT (GPIOG)
|
||||
#define QSPIF_CS_ALT (GPIO_AF10_QUADSPI)
|
||||
|
||||
#define QSPIF_D0_PIN (GPIO_PIN_8)
|
||||
#define QSPIF_D0_PORT (GPIOF)
|
||||
#define QSPIF_D0_ALT (GPIO_AF10_QUADSPI)
|
||||
|
||||
#define QSPIF_D1_PIN (GPIO_PIN_9)
|
||||
#define QSPIF_D1_PORT (GPIOF)
|
||||
#define QSPIF_D1_ALT (GPIO_AF10_QUADSPI)
|
||||
|
||||
#define QSPIF_D2_PIN (GPIO_PIN_7)
|
||||
#define QSPIF_D2_PORT (GPIOF)
|
||||
#define QSPIF_D2_ALT (GPIO_AF9_QUADSPI)
|
||||
|
||||
#define QSPIF_D3_PIN (GPIO_PIN_6)
|
||||
#define QSPIF_D3_PORT (GPIOF)
|
||||
#define QSPIF_D3_ALT (GPIO_AF9_QUADSPI)
|
||||
|
||||
#define QSPIF_CLK_ENABLE() __HAL_RCC_QSPI_CLK_ENABLE()
|
||||
#define QSPIF_CLK_DISABLE() __HAL_RCC_QSPI_CLK_DISABLE()
|
||||
#define QSPIF_FORCE_RESET() __HAL_RCC_QSPI_FORCE_RESET()
|
||||
#define QSPIF_RELEASE_RESET() __HAL_RCC_QSPI_RELEASE_RESET()
|
||||
|
||||
#define QSPIF_CLK_GPIO_CLK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE()
|
||||
#define QSPIF_CS_GPIO_CLK_ENABLE() __HAL_RCC_GPIOG_CLK_ENABLE()
|
||||
#define QSPIF_D0_GPIO_CLK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE()
|
||||
#define QSPIF_D1_GPIO_CLK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE()
|
||||
#define QSPIF_D2_GPIO_CLK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE()
|
||||
#define QSPIF_D3_GPIO_CLK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE()
|
||||
|
||||
// Enable additional GPIO banks for DRAM...
|
||||
#define ENABLE_GPIO_BANK_F
|
||||
#define ENABLE_GPIO_BANK_G
|
||||
|
||||
@ -42,6 +42,7 @@ stm32h7xx_hal_tim_ex.c\
|
||||
stm32h7xx_hal_uart.c\
|
||||
stm32h7xx_hal_usart.c\
|
||||
stm32h7xx_hal_jpeg.c\
|
||||
stm32h7xx_hal_qspi.c\
|
||||
stm32h7xx_ll_usb.c\
|
||||
stm32h7xx_ll_sdmmc.c\
|
||||
stm32h7xx_ll_fmc.c\
|
||||
|
||||
Loading…
Reference in New Issue
Block a user