2018-07-08 11:21:16 +00:00
|
|
|
/* SIMtrace 2 firmware USB DFU bootloader
|
|
|
|
*
|
|
|
|
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
|
2019-02-07 16:52:08 +00:00
|
|
|
* (C) 2018-2019 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
|
2018-07-08 11:21:16 +00:00
|
|
|
*
|
|
|
|
* 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, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
2017-02-27 19:31:09 +00:00
|
|
|
#include "board.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "usb/device/dfu/dfu.h"
|
|
|
|
#include "usb/common/dfu/usb_dfu.h"
|
|
|
|
#include "manifest.h"
|
2018-08-06 15:57:20 +00:00
|
|
|
#include "USBD_HAL.h"
|
2017-02-27 19:31:09 +00:00
|
|
|
|
2017-03-06 21:47:06 +00:00
|
|
|
#include <osmocom/core/timer.h>
|
|
|
|
|
DFU: add DFU application
this adds the DFU as application, allowing to flash the bootloader.
a USB DFU alternative is added to flash the bootloader partition.
when the DFU is started as bootloader, the partition/alternative
to flash the bootloader is marked as "not available", and
ineffective.
the same happens for the application partition when DFU is started
as application.
this distinction is make at compile time, not at runtime, because
of size restrictions (the bootloader was already close to the
16 kB limit).
*_dfu_flash.bin should not be mixed with *_dfu_dfu.bin.
*_dfu_dfu.bin should be flashed as application using the already
existing DFU bootloader.
once this images is started (as application), the *_dfu_flash.bin
should be flashed as bootloader using the DFU application.
once the DFU bootloader has been flashed, soft resetting
(not re-powering) will cause the bootloader to start, allowing to
flash the application with a normal image (e.g. not DFU),
replacing the DFU application.
this switch to DFU only happens after downloading (e.g. flashing).
it is planned to have the DFU application erase itself after
flashing, but this is currently not implemented.
Change-Id: Ic273bb593a7669111b0219fe301d7897419167c8
2019-12-11 16:04:21 +00:00
|
|
|
/* USB alternate interface index used to identify which partition to flash */
|
|
|
|
/** USB alternate interface index indicating RAM partition */
|
2017-02-27 23:21:45 +00:00
|
|
|
#define ALTIF_RAM 0
|
DFU: add DFU application
this adds the DFU as application, allowing to flash the bootloader.
a USB DFU alternative is added to flash the bootloader partition.
when the DFU is started as bootloader, the partition/alternative
to flash the bootloader is marked as "not available", and
ineffective.
the same happens for the application partition when DFU is started
as application.
this distinction is make at compile time, not at runtime, because
of size restrictions (the bootloader was already close to the
16 kB limit).
*_dfu_flash.bin should not be mixed with *_dfu_dfu.bin.
*_dfu_dfu.bin should be flashed as application using the already
existing DFU bootloader.
once this images is started (as application), the *_dfu_flash.bin
should be flashed as bootloader using the DFU application.
once the DFU bootloader has been flashed, soft resetting
(not re-powering) will cause the bootloader to start, allowing to
flash the application with a normal image (e.g. not DFU),
replacing the DFU application.
this switch to DFU only happens after downloading (e.g. flashing).
it is planned to have the DFU application erase itself after
flashing, but this is currently not implemented.
Change-Id: Ic273bb593a7669111b0219fe301d7897419167c8
2019-12-11 16:04:21 +00:00
|
|
|
/** USB alternate interface index indicating flash partition */
|
|
|
|
#if defined(ENVIRONMENT_flash)
|
2017-02-27 23:21:45 +00:00
|
|
|
#define ALTIF_FLASH 1
|
DFU: add DFU application
this adds the DFU as application, allowing to flash the bootloader.
a USB DFU alternative is added to flash the bootloader partition.
when the DFU is started as bootloader, the partition/alternative
to flash the bootloader is marked as "not available", and
ineffective.
the same happens for the application partition when DFU is started
as application.
this distinction is make at compile time, not at runtime, because
of size restrictions (the bootloader was already close to the
16 kB limit).
*_dfu_flash.bin should not be mixed with *_dfu_dfu.bin.
*_dfu_dfu.bin should be flashed as application using the already
existing DFU bootloader.
once this images is started (as application), the *_dfu_flash.bin
should be flashed as bootloader using the DFU application.
once the DFU bootloader has been flashed, soft resetting
(not re-powering) will cause the bootloader to start, allowing to
flash the application with a normal image (e.g. not DFU),
replacing the DFU application.
this switch to DFU only happens after downloading (e.g. flashing).
it is planned to have the DFU application erase itself after
flashing, but this is currently not implemented.
Change-Id: Ic273bb593a7669111b0219fe301d7897419167c8
2019-12-11 16:04:21 +00:00
|
|
|
#elif defined(ENVIRONMENT_dfu)
|
|
|
|
#define ALTIF_FLASH 2
|
|
|
|
#endif
|
2017-02-27 23:21:45 +00:00
|
|
|
|
2017-02-27 19:31:09 +00:00
|
|
|
unsigned int g_unique_id[4];
|
2018-06-17 20:36:44 +00:00
|
|
|
/* remember if the watchdog has been configured in the main loop so we can kick it in the ISR */
|
|
|
|
static bool watchdog_configured = false;
|
2017-02-27 19:31:09 +00:00
|
|
|
|
2018-06-27 14:27:41 +00:00
|
|
|
/* There is not enough space in the 16 KiB DFU bootloader to include led.h functions */
|
|
|
|
#ifdef PINS_LEDS
|
|
|
|
/** LED pin configurations */
|
|
|
|
static const Pin pinsLeds[] = { PINS_LEDS } ;
|
|
|
|
#endif
|
|
|
|
|
2017-02-27 19:31:09 +00:00
|
|
|
/*----------------------------------------------------------------------------
|
|
|
|
* Callbacks
|
|
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
|
2017-02-27 23:21:45 +00:00
|
|
|
#define RAM_ADDR(offset) (IRAM_ADDR + BOARD_DFU_RAM_SIZE + offset)
|
DFU: add DFU application
this adds the DFU as application, allowing to flash the bootloader.
a USB DFU alternative is added to flash the bootloader partition.
when the DFU is started as bootloader, the partition/alternative
to flash the bootloader is marked as "not available", and
ineffective.
the same happens for the application partition when DFU is started
as application.
this distinction is make at compile time, not at runtime, because
of size restrictions (the bootloader was already close to the
16 kB limit).
*_dfu_flash.bin should not be mixed with *_dfu_dfu.bin.
*_dfu_dfu.bin should be flashed as application using the already
existing DFU bootloader.
once this images is started (as application), the *_dfu_flash.bin
should be flashed as bootloader using the DFU application.
once the DFU bootloader has been flashed, soft resetting
(not re-powering) will cause the bootloader to start, allowing to
flash the application with a normal image (e.g. not DFU),
replacing the DFU application.
this switch to DFU only happens after downloading (e.g. flashing).
it is planned to have the DFU application erase itself after
flashing, but this is currently not implemented.
Change-Id: Ic273bb593a7669111b0219fe301d7897419167c8
2019-12-11 16:04:21 +00:00
|
|
|
#if defined(ENVIRONMENT_flash)
|
2017-02-27 23:21:45 +00:00
|
|
|
#define FLASH_ADDR(offset) (IFLASH_ADDR + BOARD_DFU_BOOT_SIZE + offset)
|
DFU: add DFU application
this adds the DFU as application, allowing to flash the bootloader.
a USB DFU alternative is added to flash the bootloader partition.
when the DFU is started as bootloader, the partition/alternative
to flash the bootloader is marked as "not available", and
ineffective.
the same happens for the application partition when DFU is started
as application.
this distinction is make at compile time, not at runtime, because
of size restrictions (the bootloader was already close to the
16 kB limit).
*_dfu_flash.bin should not be mixed with *_dfu_dfu.bin.
*_dfu_dfu.bin should be flashed as application using the already
existing DFU bootloader.
once this images is started (as application), the *_dfu_flash.bin
should be flashed as bootloader using the DFU application.
once the DFU bootloader has been flashed, soft resetting
(not re-powering) will cause the bootloader to start, allowing to
flash the application with a normal image (e.g. not DFU),
replacing the DFU application.
this switch to DFU only happens after downloading (e.g. flashing).
it is planned to have the DFU application erase itself after
flashing, but this is currently not implemented.
Change-Id: Ic273bb593a7669111b0219fe301d7897419167c8
2019-12-11 16:04:21 +00:00
|
|
|
#elif defined(ENVIRONMENT_dfu)
|
|
|
|
#define FLASH_ADDR(offset) (IFLASH_ADDR + offset)
|
|
|
|
#endif
|
2017-02-27 23:21:45 +00:00
|
|
|
|
DFU: add DFU application
this adds the DFU as application, allowing to flash the bootloader.
a USB DFU alternative is added to flash the bootloader partition.
when the DFU is started as bootloader, the partition/alternative
to flash the bootloader is marked as "not available", and
ineffective.
the same happens for the application partition when DFU is started
as application.
this distinction is make at compile time, not at runtime, because
of size restrictions (the bootloader was already close to the
16 kB limit).
*_dfu_flash.bin should not be mixed with *_dfu_dfu.bin.
*_dfu_dfu.bin should be flashed as application using the already
existing DFU bootloader.
once this images is started (as application), the *_dfu_flash.bin
should be flashed as bootloader using the DFU application.
once the DFU bootloader has been flashed, soft resetting
(not re-powering) will cause the bootloader to start, allowing to
flash the application with a normal image (e.g. not DFU),
replacing the DFU application.
this switch to DFU only happens after downloading (e.g. flashing).
it is planned to have the DFU application erase itself after
flashing, but this is currently not implemented.
Change-Id: Ic273bb593a7669111b0219fe301d7897419167c8
2019-12-11 16:04:21 +00:00
|
|
|
#define IRAM_END ((uint8_t *)IRAM_ADDR + IRAM_SIZE)
|
|
|
|
#if defined(ENVIRONMENT_flash)
|
|
|
|
#define IFLASH_END ((uint8_t *)IFLASH_ADDR + IFLASH_SIZE)
|
|
|
|
#elif defined(ENVIRONMENT_dfu)
|
|
|
|
#define IFLASH_END ((uint8_t *)IFLASH_ADDR + BOARD_DFU_BOOT_SIZE)
|
|
|
|
#endif
|
2017-02-27 23:21:45 +00:00
|
|
|
|
2018-06-01 09:02:49 +00:00
|
|
|
/* incoming call-back: Host has transferred 'len' bytes (stored at
|
2017-02-27 23:21:45 +00:00
|
|
|
* 'data'), which we shall write to 'offset' into the partition
|
2018-06-01 09:02:49 +00:00
|
|
|
* associated with 'altif'. Guaranted to be less than
|
2017-02-27 23:21:45 +00:00
|
|
|
* BOARD_DFU_PAGE_SIZE */
|
|
|
|
int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
|
|
|
|
uint8_t *data, unsigned int len)
|
2017-02-27 19:31:09 +00:00
|
|
|
{
|
2017-02-27 23:21:45 +00:00
|
|
|
uint32_t addr;
|
2018-06-29 19:07:41 +00:00
|
|
|
unsigned int i;
|
2017-02-27 23:21:45 +00:00
|
|
|
int rc;
|
2018-06-01 09:02:49 +00:00
|
|
|
/* address of the last allocated variable on the stack */
|
|
|
|
uint32_t stack_addr = (uint32_t)&rc;
|
2018-06-17 20:36:44 +00:00
|
|
|
/* kick the dog to have enough time to flash */
|
|
|
|
if (watchdog_configured) {
|
|
|
|
WDT_Restart(WDT);
|
|
|
|
}
|
2017-02-27 23:21:45 +00:00
|
|
|
|
2019-02-07 16:55:24 +00:00
|
|
|
#if TRACE_LEVEL >= TRACE_LEVEL_INFO
|
|
|
|
TRACE_INFO("dnload(altif=%u, offset=%u, len=%u)\n\r", altif, offset, len);
|
|
|
|
#else
|
|
|
|
printf("DL off=%u\n\r", offset);
|
|
|
|
#endif
|
2017-02-27 23:21:45 +00:00
|
|
|
|
2018-06-27 14:27:41 +00:00
|
|
|
#ifdef PINS_LEDS
|
|
|
|
PIO_Clear(&pinsLeds[LED_NUM_RED]);
|
|
|
|
#endif
|
|
|
|
|
2017-02-27 23:21:45 +00:00
|
|
|
switch (altif) {
|
|
|
|
case ALTIF_RAM:
|
|
|
|
addr = RAM_ADDR(offset);
|
2018-06-17 20:33:29 +00:00
|
|
|
if (addr < IRAM_ADDR || addr + len >= IRAM_ADDR + IRAM_SIZE || addr + len >= stack_addr) {
|
2017-02-28 00:02:24 +00:00
|
|
|
g_dfu->state = DFU_STATE_dfuERROR;
|
|
|
|
g_dfu->status = DFU_STATUS_errADDRESS;
|
2018-06-27 14:27:41 +00:00
|
|
|
rc = DFU_RET_STALL;
|
|
|
|
break;
|
2017-02-27 23:21:45 +00:00
|
|
|
}
|
|
|
|
memcpy((void *)addr, data, len);
|
2018-06-27 14:27:41 +00:00
|
|
|
rc = DFU_RET_ZLP;
|
|
|
|
break;
|
2017-02-27 23:21:45 +00:00
|
|
|
case ALTIF_FLASH:
|
|
|
|
addr = FLASH_ADDR(offset);
|
DFU: add DFU application
this adds the DFU as application, allowing to flash the bootloader.
a USB DFU alternative is added to flash the bootloader partition.
when the DFU is started as bootloader, the partition/alternative
to flash the bootloader is marked as "not available", and
ineffective.
the same happens for the application partition when DFU is started
as application.
this distinction is make at compile time, not at runtime, because
of size restrictions (the bootloader was already close to the
16 kB limit).
*_dfu_flash.bin should not be mixed with *_dfu_dfu.bin.
*_dfu_dfu.bin should be flashed as application using the already
existing DFU bootloader.
once this images is started (as application), the *_dfu_flash.bin
should be flashed as bootloader using the DFU application.
once the DFU bootloader has been flashed, soft resetting
(not re-powering) will cause the bootloader to start, allowing to
flash the application with a normal image (e.g. not DFU),
replacing the DFU application.
this switch to DFU only happens after downloading (e.g. flashing).
it is planned to have the DFU application erase itself after
flashing, but this is currently not implemented.
Change-Id: Ic273bb593a7669111b0219fe301d7897419167c8
2019-12-11 16:04:21 +00:00
|
|
|
#if defined(ENVIRONMENT_flash)
|
2018-06-17 20:33:29 +00:00
|
|
|
if (addr < IFLASH_ADDR || addr + len >= IFLASH_ADDR + IFLASH_SIZE) {
|
DFU: add DFU application
this adds the DFU as application, allowing to flash the bootloader.
a USB DFU alternative is added to flash the bootloader partition.
when the DFU is started as bootloader, the partition/alternative
to flash the bootloader is marked as "not available", and
ineffective.
the same happens for the application partition when DFU is started
as application.
this distinction is make at compile time, not at runtime, because
of size restrictions (the bootloader was already close to the
16 kB limit).
*_dfu_flash.bin should not be mixed with *_dfu_dfu.bin.
*_dfu_dfu.bin should be flashed as application using the already
existing DFU bootloader.
once this images is started (as application), the *_dfu_flash.bin
should be flashed as bootloader using the DFU application.
once the DFU bootloader has been flashed, soft resetting
(not re-powering) will cause the bootloader to start, allowing to
flash the application with a normal image (e.g. not DFU),
replacing the DFU application.
this switch to DFU only happens after downloading (e.g. flashing).
it is planned to have the DFU application erase itself after
flashing, but this is currently not implemented.
Change-Id: Ic273bb593a7669111b0219fe301d7897419167c8
2019-12-11 16:04:21 +00:00
|
|
|
#elif defined(ENVIRONMENT_dfu)
|
|
|
|
if (addr < IFLASH_ADDR || addr + len >= IFLASH_ADDR + BOARD_DFU_BOOT_SIZE) {
|
|
|
|
#endif
|
2017-02-28 00:02:24 +00:00
|
|
|
g_dfu->state = DFU_STATE_dfuERROR;
|
|
|
|
g_dfu->status = DFU_STATUS_errADDRESS;
|
2018-06-27 14:27:41 +00:00
|
|
|
rc = DFU_RET_STALL;
|
|
|
|
break;
|
2017-02-27 23:21:45 +00:00
|
|
|
}
|
2018-06-17 20:33:29 +00:00
|
|
|
rc = FLASHD_Unlock(addr, addr + len, 0, 0);
|
|
|
|
if (rc != 0) {
|
|
|
|
TRACE_ERROR("DFU download flash unlock failed\n\r");
|
2018-06-27 14:27:41 +00:00
|
|
|
rc = DFU_RET_STALL;
|
|
|
|
break;
|
2018-06-17 20:33:29 +00:00
|
|
|
}
|
2017-02-27 23:21:45 +00:00
|
|
|
rc = FLASHD_Write(addr, data, len);
|
|
|
|
if (rc != 0) {
|
2018-06-17 20:33:29 +00:00
|
|
|
TRACE_ERROR("DFU download flash erase failed\n\r");
|
2018-06-27 14:27:41 +00:00
|
|
|
rc = DFU_RET_STALL;
|
|
|
|
break;
|
2018-06-17 20:33:29 +00:00
|
|
|
}
|
2018-06-29 19:07:41 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
2018-06-17 20:33:29 +00:00
|
|
|
if (((uint8_t*)addr)[i]!=data[i]) {
|
|
|
|
TRACE_ERROR("DFU download flash data written not correct\n\r");
|
2018-06-27 14:27:41 +00:00
|
|
|
rc = DFU_RET_STALL;
|
|
|
|
break;
|
2018-06-17 20:33:29 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-27 14:27:41 +00:00
|
|
|
rc = DFU_RET_ZLP;
|
|
|
|
break;
|
2017-02-27 23:21:45 +00:00
|
|
|
default:
|
|
|
|
TRACE_ERROR("DFU download for unknown AltIf %d\n\r", altif);
|
2018-06-27 14:27:41 +00:00
|
|
|
rc = DFU_RET_STALL;
|
|
|
|
break;
|
2017-02-27 23:21:45 +00:00
|
|
|
}
|
2018-06-27 14:27:41 +00:00
|
|
|
|
|
|
|
#ifdef PINS_LEDS
|
|
|
|
PIO_Set(&pinsLeds[LED_NUM_RED]);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return rc;
|
2017-02-27 19:31:09 +00:00
|
|
|
}
|
2017-02-27 23:21:45 +00:00
|
|
|
|
|
|
|
/* incoming call-back: Host has requested to read back 'req_len' bytes
|
|
|
|
* starting from 'offset' of the firmware * associated with partition
|
|
|
|
* 'altif' */
|
|
|
|
int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
|
|
|
|
uint8_t *data, unsigned int req_len)
|
|
|
|
{
|
|
|
|
uint32_t addr;
|
|
|
|
|
|
|
|
printf("upload(altif=%u, offset=%u, len=%u)", altif, offset, req_len);
|
|
|
|
|
|
|
|
switch (altif) {
|
|
|
|
case ALTIF_RAM:
|
|
|
|
addr = RAM_ADDR(offset);
|
|
|
|
if (addr > IRAM_ADDR + IRAM_SIZE) {
|
2017-02-28 00:02:24 +00:00
|
|
|
g_dfu->state = DFU_STATE_dfuERROR;
|
|
|
|
g_dfu->status = DFU_STATUS_errADDRESS;
|
2017-02-27 23:21:45 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if ((uint8_t *)addr + req_len > IRAM_END)
|
|
|
|
req_len = IRAM_END - (uint8_t *)addr;
|
|
|
|
memcpy(data, (void *)addr, req_len);
|
|
|
|
break;
|
|
|
|
case ALTIF_FLASH:
|
|
|
|
addr = FLASH_ADDR(offset);
|
|
|
|
if (addr > IFLASH_ADDR + IFLASH_SIZE) {
|
2017-02-28 00:02:24 +00:00
|
|
|
g_dfu->state = DFU_STATE_dfuERROR;
|
|
|
|
g_dfu->status = DFU_STATUS_errADDRESS;
|
2017-02-27 23:21:45 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if ((uint8_t *)addr + req_len > IFLASH_END)
|
|
|
|
req_len = IFLASH_END - (uint8_t *)addr;
|
|
|
|
memcpy(data, (void *)addr, req_len);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
TRACE_ERROR("DFU upload for unknown AltIf %d\n\r", altif);
|
|
|
|
/* FIXME: set error codes */
|
|
|
|
return -1;
|
|
|
|
}
|
2017-03-03 00:33:24 +00:00
|
|
|
printf("=%u\n\r", req_len);
|
2017-02-27 23:21:45 +00:00
|
|
|
return req_len;
|
|
|
|
}
|
|
|
|
|
2017-11-28 21:15:56 +00:00
|
|
|
/* can be overridden by board specific code, e.g. by pushbutton */
|
|
|
|
WEAK int board_override_enter_dfu(void)
|
2017-03-04 18:17:27 +00:00
|
|
|
{
|
2017-11-28 21:15:56 +00:00
|
|
|
return 0;
|
2017-03-04 18:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* using this function we can determine if we should enter DFU mode
|
|
|
|
* during boot, or if we should proceed towards the application/runtime */
|
|
|
|
int USBDFU_OverrideEnterDFU(void)
|
|
|
|
{
|
|
|
|
uint32_t *app_part = (uint32_t *)FLASH_ADDR(0);
|
2018-07-07 13:22:16 +00:00
|
|
|
/* at the first call we are before the text segment has been relocated,
|
|
|
|
* so g_dfu is not initialized yet */
|
|
|
|
g_dfu = &_g_dfu;
|
|
|
|
if (USB_DFU_MAGIC == g_dfu->magic) {
|
|
|
|
return 1;
|
|
|
|
}
|
2017-03-04 18:17:27 +00:00
|
|
|
|
|
|
|
/* If the loopback jumper is set, we enter DFU mode */
|
2018-07-07 13:22:16 +00:00
|
|
|
if (board_override_enter_dfu()) {
|
|
|
|
return 2;
|
|
|
|
}
|
2017-03-04 18:17:27 +00:00
|
|
|
|
|
|
|
/* if the first word of the application partition doesn't look
|
|
|
|
* like a stack pointer (i.e. point to RAM), enter DFU mode */
|
2018-07-07 13:22:16 +00:00
|
|
|
if ((app_part[0] < IRAM_ADDR) || ((uint8_t *)app_part[0] > IRAM_END)) {
|
|
|
|
return 3;
|
|
|
|
}
|
2017-03-04 18:17:27 +00:00
|
|
|
|
|
|
|
/* if the second word of the application partition doesn't look
|
|
|
|
* like a function from flash (reset vector), enter DFU mode */
|
|
|
|
if (((uint32_t *)app_part[1] < app_part) ||
|
2018-07-07 13:22:16 +00:00
|
|
|
((uint8_t *)app_part[1] > IFLASH_END)) {
|
|
|
|
return 4;
|
|
|
|
}
|
2017-03-04 18:17:27 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2017-02-27 19:31:09 +00:00
|
|
|
|
|
|
|
/* returns '1' in case we should break any endless loop */
|
|
|
|
static void check_exec_dbg_cmd(void)
|
|
|
|
{
|
|
|
|
int ch;
|
|
|
|
|
|
|
|
if (!UART_IsRxReady())
|
|
|
|
return;
|
|
|
|
|
|
|
|
ch = UART_GetChar();
|
|
|
|
|
|
|
|
//board_exec_dbg_cmd(ch);
|
|
|
|
}
|
|
|
|
|
2020-08-16 13:51:14 +00:00
|
|
|
/* print a horizontal line of '=' characters; Doing this in a loop vs. using a 'const'
|
|
|
|
* string saves us ~60 bytes of executable size (matters particularly for DFU loader) */
|
|
|
|
static void print_line(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < 78; i++)
|
|
|
|
fputc('=', stdout);
|
|
|
|
fputc('\n', stdout);
|
|
|
|
fputc('\r', stdout);
|
|
|
|
}
|
|
|
|
|
2017-02-27 19:31:09 +00:00
|
|
|
/*------------------------------------------------------------------------------
|
|
|
|
* Main
|
|
|
|
*------------------------------------------------------------------------------*/
|
|
|
|
#define MAX_USB_ITER BOARD_MCK/72 // This should be around a second
|
|
|
|
extern int main(void)
|
|
|
|
{
|
|
|
|
uint8_t isUsbConnected = 0;
|
|
|
|
unsigned int i = 0;
|
2017-03-06 20:51:55 +00:00
|
|
|
uint32_t reset_cause = (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos;
|
2017-02-27 19:31:09 +00:00
|
|
|
|
2018-06-17 20:36:44 +00:00
|
|
|
/* Enable watchdog for 2000ms, with no window */
|
2017-03-03 18:01:53 +00:00
|
|
|
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
|
2018-06-17 20:36:44 +00:00
|
|
|
(WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
|
|
|
|
watchdog_configured = true;
|
2017-02-27 19:31:09 +00:00
|
|
|
|
2018-06-27 14:27:41 +00:00
|
|
|
#ifdef PINS_LEDS
|
|
|
|
/* Configure LED */
|
2021-10-20 17:35:30 +00:00
|
|
|
PIO_Configure(pinsLeds, PIO_LISTSIZE(pinsLeds));
|
2018-06-27 14:27:41 +00:00
|
|
|
PIO_Set(&pinsLeds[LED_NUM_RED]);
|
|
|
|
PIO_Clear(&pinsLeds[LED_NUM_GREEN]);
|
|
|
|
#endif
|
|
|
|
|
2017-02-27 19:31:09 +00:00
|
|
|
EEFC_ReadUniqueID(g_unique_id);
|
|
|
|
|
2020-08-16 13:51:14 +00:00
|
|
|
printf("\n\r\n\r");
|
|
|
|
print_line();
|
|
|
|
printf("DFU bootloader %s for board %s\n\r"
|
|
|
|
"(C) 2010-2017 by Harald Welte, 2018-2019 by Kevin Redon\n\r",
|
2017-02-27 19:31:09 +00:00
|
|
|
manifest_revision, manifest_board);
|
2020-08-16 13:51:14 +00:00
|
|
|
print_line();
|
2017-02-27 19:31:09 +00:00
|
|
|
|
2019-12-11 15:44:02 +00:00
|
|
|
#if (TRACE_LEVEL >= TRACE_LEVEL_INFO)
|
|
|
|
TRACE_INFO("Chip ID: 0x%08lx (Ext 0x%08lx)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
|
2017-03-03 00:33:24 +00:00
|
|
|
TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r",
|
2017-02-27 19:31:09 +00:00
|
|
|
g_unique_id[0], g_unique_id[1],
|
|
|
|
g_unique_id[2], g_unique_id[3]);
|
2019-12-11 15:44:02 +00:00
|
|
|
static const char* reset_causes[] = {
|
|
|
|
"general reset (first power-up reset)",
|
|
|
|
"backup reset (return from backup mode)",
|
|
|
|
"watchdog reset (watchdog fault occurred)",
|
|
|
|
"software reset (processor reset required by the software)",
|
|
|
|
"user reset (NRST pin detected low)",
|
|
|
|
};
|
|
|
|
if (reset_cause < ARRAY_SIZE(reset_causes)) {
|
|
|
|
TRACE_INFO("Reset Cause: %s\n\r", reset_causes[reset_cause]);
|
|
|
|
} else {
|
|
|
|
TRACE_INFO("Reset Cause: 0x%lx\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos);
|
|
|
|
}
|
|
|
|
#endif
|
2017-03-06 20:51:55 +00:00
|
|
|
|
2018-07-07 13:22:16 +00:00
|
|
|
#if (TRACE_LEVEL >= TRACE_LEVEL_INFO)
|
|
|
|
/* Find out why we are in the DFU bootloader, and not the main application */
|
|
|
|
TRACE_INFO("DFU bootloader start reason: ");
|
|
|
|
switch (USBDFU_OverrideEnterDFU()) {
|
|
|
|
case 0:
|
DFU: add DFU application
this adds the DFU as application, allowing to flash the bootloader.
a USB DFU alternative is added to flash the bootloader partition.
when the DFU is started as bootloader, the partition/alternative
to flash the bootloader is marked as "not available", and
ineffective.
the same happens for the application partition when DFU is started
as application.
this distinction is make at compile time, not at runtime, because
of size restrictions (the bootloader was already close to the
16 kB limit).
*_dfu_flash.bin should not be mixed with *_dfu_dfu.bin.
*_dfu_dfu.bin should be flashed as application using the already
existing DFU bootloader.
once this images is started (as application), the *_dfu_flash.bin
should be flashed as bootloader using the DFU application.
once the DFU bootloader has been flashed, soft resetting
(not re-powering) will cause the bootloader to start, allowing to
flash the application with a normal image (e.g. not DFU),
replacing the DFU application.
this switch to DFU only happens after downloading (e.g. flashing).
it is planned to have the DFU application erase itself after
flashing, but this is currently not implemented.
Change-Id: Ic273bb593a7669111b0219fe301d7897419167c8
2019-12-11 16:04:21 +00:00
|
|
|
if (SCB->VTOR < IFLASH_ADDR + BOARD_DFU_BOOT_SIZE) {
|
|
|
|
TRACE_INFO_WP("unknown\n\r");
|
|
|
|
} else {
|
|
|
|
TRACE_INFO_WP("DFU is the main application\n\r");
|
|
|
|
}
|
|
|
|
break;
|
2018-07-07 13:22:16 +00:00
|
|
|
case 1:
|
|
|
|
TRACE_INFO_WP("DFU switch requested by main application\n\r");
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
TRACE_INFO_WP("bootloader forced (button pressed or jumper set)\n\r");
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
TRACE_INFO_WP("stack pointer (first application word) does no point in RAM\n\r");
|
|
|
|
break;
|
|
|
|
case 4: // the is no reason
|
|
|
|
TRACE_INFO_WP("reset vector (second application word) does no point in flash\n\r");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
TRACE_INFO_WP("unknown\n\r");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-03-06 20:51:55 +00:00
|
|
|
/* clear g_dfu on power-up reset */
|
|
|
|
if (reset_cause == 0)
|
|
|
|
memset(g_dfu, 0, sizeof(*g_dfu));
|
2017-02-27 19:31:09 +00:00
|
|
|
|
2017-03-03 00:52:34 +00:00
|
|
|
board_main_top();
|
2017-02-27 19:31:09 +00:00
|
|
|
|
2017-03-03 00:33:24 +00:00
|
|
|
TRACE_INFO("USB init...\n\r");
|
2018-06-17 20:31:21 +00:00
|
|
|
/* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */
|
2019-12-03 14:29:33 +00:00
|
|
|
USBD_Disconnect();
|
|
|
|
mdelay(50);
|
2017-02-27 19:31:09 +00:00
|
|
|
USBDFU_Initialize(&dfu_descriptors);
|
|
|
|
|
|
|
|
while (USBD_GetState() < USBD_STATE_CONFIGURED) {
|
2017-03-03 18:01:53 +00:00
|
|
|
WDT_Restart(WDT);
|
2017-02-27 19:31:09 +00:00
|
|
|
check_exec_dbg_cmd();
|
2017-02-27 23:21:45 +00:00
|
|
|
#if 1
|
2017-02-27 19:31:09 +00:00
|
|
|
if (i >= MAX_USB_ITER * 3) {
|
2019-12-03 14:36:58 +00:00
|
|
|
TRACE_ERROR("Resetting board (USB could not be configured)\n\r");
|
|
|
|
g_dfu->magic = USB_DFU_MAGIC; // start the bootloader after reboot
|
2017-03-03 00:51:43 +00:00
|
|
|
USBD_Disconnect();
|
2017-02-27 19:31:09 +00:00
|
|
|
NVIC_SystemReset();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
2018-06-17 20:33:29 +00:00
|
|
|
/* Initialize the flash to be able to write it, using the IAP ROM code */
|
2017-03-02 22:18:40 +00:00
|
|
|
FLASHD_Initialize(BOARD_MCK, 1);
|
2018-06-17 20:33:29 +00:00
|
|
|
|
2017-03-03 00:33:24 +00:00
|
|
|
TRACE_INFO("entering main loop...\n\r");
|
2017-02-27 19:31:09 +00:00
|
|
|
while (1) {
|
2017-03-03 18:01:53 +00:00
|
|
|
WDT_Restart(WDT);
|
2017-02-27 19:31:09 +00:00
|
|
|
#if TRACE_LEVEL >= TRACE_LEVEL_DEBUG
|
|
|
|
const char rotor[] = { '-', '\\', '|', '/' };
|
|
|
|
putchar('\b');
|
|
|
|
putchar(rotor[i++ % ARRAY_SIZE(rotor)]);
|
|
|
|
#endif
|
|
|
|
check_exec_dbg_cmd();
|
2017-03-06 21:47:06 +00:00
|
|
|
#if 0
|
|
|
|
osmo_timers_prepare();
|
|
|
|
osmo_timers_update();
|
|
|
|
#endif
|
2017-02-27 19:31:09 +00:00
|
|
|
|
|
|
|
if (USBD_GetState() < USBD_STATE_CONFIGURED) {
|
|
|
|
|
|
|
|
if (isUsbConnected) {
|
|
|
|
isUsbConnected = 0;
|
|
|
|
}
|
|
|
|
} else if (isUsbConnected == 0) {
|
2017-03-03 00:33:24 +00:00
|
|
|
TRACE_INFO("USB is now configured\n\r");
|
2017-02-27 19:31:09 +00:00
|
|
|
|
|
|
|
isUsbConnected = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|