stm32/mboot: Update LED0 state from systick handler.

Updating the LED0 state from systick handler ensures LED0 is always
consistent with its flash rate regardless of other processing going on in
either interrupts or main.  This improves the visible stability of the
bootloader, rather than LED0 flashing somewhat randomly at times.

This commit also changes the LED0 flash rate depending on the current state
of DFU, giving slightly more visual feedback on what the device is doing.
This commit is contained in:
Andrew Leech 2020-03-05 15:38:29 +11:00 committed by Damien George
parent 38ccb4c643
commit 9dd470b768
1 changed files with 70 additions and 48 deletions

View File

@ -416,6 +416,19 @@ void mp_hal_pin_config_speed(uint32_t port_pin, uint32_t speed) {
#define LED3 MICROPY_HW_LED4
#endif
// For flashing states: bit 0 is "active", bit 1 is "inactive", bits 2-6 are flash rate.
typedef enum {
LED0_STATE_OFF = 0,
LED0_STATE_ON = 1,
LED0_STATE_SLOW_FLASH = (20 << 2) | 1,
LED0_STATE_FAST_FLASH = (2 << 2) | 1,
LED0_STATE_SLOW_INVERTED_FLASH = (20 << 2) | 2,
} led0_state_t;
static led0_state_t led0_cur_state = LED0_STATE_OFF;
static uint32_t led0_ms_interval = 0;
static int led0_toggle_count = 0;
MP_WEAK void led_init(void) {
mp_hal_pin_output(LED0);
mp_hal_pin_output(LED1);
@ -425,6 +438,7 @@ MP_WEAK void led_init(void) {
#ifdef LED3
mp_hal_pin_output(LED3);
#endif
led0_cur_state = LED0_STATE_OFF;
}
MP_WEAK void led_state(int led, int val) {
@ -449,6 +463,24 @@ void led_state_all(unsigned int mask) {
#endif
}
void led0_state(led0_state_t state) {
led0_cur_state = state;
if (state == LED0_STATE_OFF || state == LED0_STATE_ON) {
led_state(LED0, state);
}
}
void led0_update() {
if (led0_cur_state != LED0_STATE_OFF && systick_ms - led0_ms_interval > 50) {
uint8_t rate = (led0_cur_state >> 2) & 0x1f;
led0_ms_interval += 50;
if (++led0_toggle_count >= rate) {
led0_toggle_count = 0;
}
led_state(LED0, (led0_cur_state & (led0_toggle_count == 0 ? 1 : 2)));
}
}
/******************************************************************************/
// USR BUTTON
@ -688,68 +720,72 @@ static int spiflash_page_erase(mp_spiflash_t *spif, uint32_t addr, uint32_t n_bl
#endif
int do_page_erase(uint32_t addr, uint32_t *next_addr) {
led_state(LED0, 1);
int ret = -1;
led0_state(LED0_STATE_ON);
#if defined(MBOOT_SPIFLASH_ADDR)
if (MBOOT_SPIFLASH_ADDR <= addr && addr < MBOOT_SPIFLASH_ADDR + MBOOT_SPIFLASH_BYTE_SIZE) {
*next_addr = addr + MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE * MP_SPIFLASH_ERASE_BLOCK_SIZE;
return spiflash_page_erase(MBOOT_SPIFLASH_SPIFLASH,
ret = spiflash_page_erase(MBOOT_SPIFLASH_SPIFLASH,
addr - MBOOT_SPIFLASH_ADDR, MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE);
}
} else
#endif
#if defined(MBOOT_SPIFLASH2_ADDR)
if (MBOOT_SPIFLASH2_ADDR <= addr && addr < MBOOT_SPIFLASH2_ADDR + MBOOT_SPIFLASH2_BYTE_SIZE) {
*next_addr = addr + MBOOT_SPIFLASH2_ERASE_BLOCKS_PER_PAGE * MP_SPIFLASH_ERASE_BLOCK_SIZE;
return spiflash_page_erase(MBOOT_SPIFLASH2_SPIFLASH,
ret = spiflash_page_erase(MBOOT_SPIFLASH2_SPIFLASH,
addr - MBOOT_SPIFLASH2_ADDR, MBOOT_SPIFLASH2_ERASE_BLOCKS_PER_PAGE);
}
} else
#endif
{
ret = flash_page_erase(addr, next_addr);
}
return flash_page_erase(addr, next_addr);
led0_state((ret == 0) ? LED0_STATE_SLOW_FLASH : LED0_STATE_SLOW_INVERTED_FLASH);
return ret;
}
void do_read(uint32_t addr, int len, uint8_t *buf) {
led0_state(LED0_STATE_FAST_FLASH);
#if defined(MBOOT_SPIFLASH_ADDR)
if (MBOOT_SPIFLASH_ADDR <= addr && addr < MBOOT_SPIFLASH_ADDR + MBOOT_SPIFLASH_BYTE_SIZE) {
mp_spiflash_read(MBOOT_SPIFLASH_SPIFLASH, addr - MBOOT_SPIFLASH_ADDR, len, buf);
return;
}
} else
#endif
#if defined(MBOOT_SPIFLASH2_ADDR)
if (MBOOT_SPIFLASH2_ADDR <= addr && addr < MBOOT_SPIFLASH2_ADDR + MBOOT_SPIFLASH2_BYTE_SIZE) {
mp_spiflash_read(MBOOT_SPIFLASH2_SPIFLASH, addr - MBOOT_SPIFLASH2_ADDR, len, buf);
return;
}
} else
#endif
// Other addresses, just read directly from memory
memcpy(buf, (void*)addr, len);
{
// Other addresses, just read directly from memory
memcpy(buf, (void*)addr, len);
}
led0_state(LED0_STATE_SLOW_FLASH);
}
int do_write(uint32_t addr, const uint8_t *src8, size_t len) {
static uint32_t led_tog = 0;
led_state(LED0, (led_tog++) & 4);
int ret = -1;
led0_state(LED0_STATE_FAST_FLASH);
#if defined(MBOOT_SPIFLASH_ADDR)
if (MBOOT_SPIFLASH_ADDR <= addr && addr < MBOOT_SPIFLASH_ADDR + MBOOT_SPIFLASH_BYTE_SIZE) {
return mp_spiflash_write(MBOOT_SPIFLASH_SPIFLASH, addr - MBOOT_SPIFLASH_ADDR, len, src8);
}
ret = mp_spiflash_write(MBOOT_SPIFLASH_SPIFLASH, addr - MBOOT_SPIFLASH_ADDR, len, src8);
} else
#endif
#if defined(MBOOT_SPIFLASH2_ADDR)
if (MBOOT_SPIFLASH2_ADDR <= addr && addr < MBOOT_SPIFLASH2_ADDR + MBOOT_SPIFLASH2_BYTE_SIZE) {
return mp_spiflash_write(MBOOT_SPIFLASH2_SPIFLASH, addr - MBOOT_SPIFLASH2_ADDR, len, src8);
}
ret = mp_spiflash_write(MBOOT_SPIFLASH2_SPIFLASH, addr - MBOOT_SPIFLASH2_ADDR, len, src8);
} else
#endif
if (flash_is_valid_addr(addr)) {
return flash_write(addr, src8, len);
ret = flash_write(addr, src8, len);
} else {
dfu_context.status = DFU_STATUS_ERROR_ADDRESS;
dfu_context.error = MBOOT_ERROR_STR_INVALID_ADDRESS_IDX;
}
dfu_context.status = DFU_STATUS_ERROR_ADDRESS;
dfu_context.error = MBOOT_ERROR_STR_INVALID_ADDRESS_IDX;
return -1;
led0_state((ret == 0) ? LED0_STATE_SLOW_FLASH : LED0_STATE_SLOW_INVERTED_FLASH);
return ret;
}
/******************************************************************************/
@ -1518,11 +1554,8 @@ enter_bootloader:
#endif
led_state_all(0);
led0_state(LED0_STATE_SLOW_FLASH);
#if USE_USB_POLLING
uint32_t ss = systick_ms;
int ss2 = -1;
#endif
#if MBOOT_USB_RESET_ON_DISCONNECT
bool has_connected = false;
#endif
@ -1541,23 +1574,8 @@ enter_bootloader:
if (!pyb_usbdd.tx_pending) {
dfu_process();
}
#endif
#if USE_USB_POLLING
//__WFI(); // slows it down way too much; might work with 10x faster systick
if (systick_ms - ss > 50) {
ss += 50;
ss2 = (ss2 + 1) % 20;
switch (ss2) {
case 0: led_state(LED0, 1); break;
case 1: led_state(LED0, 0); break;
}
}
#else
led_state(LED0, 1);
mp_hal_delay_ms(50);
led_state(LED0, 0);
mp_hal_delay_ms(950);
#else // !USE_USB_POLLING
__WFI();
#endif
#if MBOOT_USB_RESET_ON_DISCONNECT
@ -1608,6 +1626,10 @@ void SysTick_Handler(void) {
// the COUNTFLAG bit, which makes the logic in mp_hal_ticks_us
// work properly.
SysTick->CTRL;
// Update the LED0 state from here to ensure it's consistent regardless of
// other processing going on in interrupts or main.
led0_update();
}
#if defined(MBOOT_I2C_SCL)