diff options
-rw-r--r-- | firmware/Makefile | 2 | ||||
-rw-r--r-- | firmware/apps/dfu/main.c | 35 | ||||
-rw-r--r-- | firmware/apps/dfu/usb_strings.txt | 1 | ||||
-rw-r--r-- | firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c | 13 | ||||
-rw-r--r-- | firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h | 3 | ||||
-rw-r--r-- | firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c | 29 | ||||
-rw-r--r-- | firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c | 17 | ||||
-rw-r--r-- | firmware/libboard/common/include/board_common.h | 5 | ||||
-rw-r--r-- | firmware/libboard/common/source/board_cstartup_gnu.c | 7 |
9 files changed, 92 insertions, 20 deletions
diff --git a/firmware/Makefile b/firmware/Makefile index 5c7aa92..bdca6e5 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -41,7 +41,7 @@ APP ?= dfu # Defines which are the available memory targets for the SAM3S-EK board. ifeq ($(APP), dfu) -MEMORIES ?= flash +MEMORIES ?= flash dfu else MEMORIES ?= dfu endif diff --git a/firmware/apps/dfu/main.c b/firmware/apps/dfu/main.c index 5aafc7c..2e80884 100644 --- a/firmware/apps/dfu/main.c +++ b/firmware/apps/dfu/main.c @@ -26,8 +26,15 @@ #include <osmocom/core/timer.h> +/* USB alternate interface index used to identify which partition to flash */ +/** USB alternate interface index indicating RAM partition */ #define ALTIF_RAM 0 +/** USB alternate interface index indicating flash partition */ +#if defined(ENVIRONMENT_flash) #define ALTIF_FLASH 1 +#elif defined(ENVIRONMENT_dfu) +#define ALTIF_FLASH 2 +#endif unsigned int g_unique_id[4]; /* remember if the watchdog has been configured in the main loop so we can kick it in the ISR */ @@ -44,10 +51,18 @@ static const Pin pinsLeds[] = { PINS_LEDS } ; *----------------------------------------------------------------------------*/ #define RAM_ADDR(offset) (IRAM_ADDR + BOARD_DFU_RAM_SIZE + offset) +#if defined(ENVIRONMENT_flash) #define FLASH_ADDR(offset) (IFLASH_ADDR + BOARD_DFU_BOOT_SIZE + offset) +#elif defined(ENVIRONMENT_dfu) +#define FLASH_ADDR(offset) (IFLASH_ADDR + offset) +#endif -#define IFLASH_END ((uint8_t *)IFLASH_ADDR + IFLASH_SIZE) -#define IRAM_END ((uint8_t *)IRAM_ADDR + IRAM_SIZE) +#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 /* incoming call-back: Host has transferred 'len' bytes (stored at * 'data'), which we shall write to 'offset' into the partition @@ -90,7 +105,11 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset, break; case ALTIF_FLASH: addr = FLASH_ADDR(offset); +#if defined(ENVIRONMENT_flash) if (addr < IFLASH_ADDR || addr + len >= IFLASH_ADDR + IFLASH_SIZE) { +#elif defined(ENVIRONMENT_dfu) + if (addr < IFLASH_ADDR || addr + len >= IFLASH_ADDR + BOARD_DFU_BOOT_SIZE) { +#endif g_dfu->state = DFU_STATE_dfuERROR; g_dfu->status = DFU_STATUS_errADDRESS; rc = DFU_RET_STALL; @@ -281,12 +300,12 @@ extern int main(void) TRACE_INFO("DFU bootloader start reason: "); switch (USBDFU_OverrideEnterDFU()) { case 0: - /* 0 normally means that there is no override, but we are in the bootloader, - * thus the first check in board_cstartup_gnu did return something else than 0. - * this can only be g_dfu->magic which is erased when the segment are - * relocated, which happens in board_cstartup_gnu just after USBDFU_OverrideEnterDFU. - * no static variable can be used to store this case since this will also be overwritten - */ + 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; case 1: TRACE_INFO_WP("DFU switch requested by main application\n\r"); break; diff --git a/firmware/apps/dfu/usb_strings.txt b/firmware/apps/dfu/usb_strings.txt index f1c79bc..4a58cb8 100644 --- a/firmware/apps/dfu/usb_strings.txt +++ b/firmware/apps/dfu/usb_strings.txt @@ -3,3 +3,4 @@ PRODUCT_STRING DFU (Device Firmware Upgrade) RAM Flash (Application Partition) +Flash (Bootloader Partition) diff --git a/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c b/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c index ac2595c..1ebab5b 100644 --- a/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c +++ b/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c @@ -1171,12 +1171,19 @@ void USBD_IrqHandler(void) /* if we are currently in the DFU bootloader, and we are beyond * the MANIFEST stage, we shall switch to the normal * application */ - if (g_dfu->past_manifest) + if (g_dfu->past_manifest) { +#if defined(ENVIRONMENT_flash) USBDFU_SwitchToApp(); +#elif defined(ENVIRONMENT_dfu) + USBDFU_SwitchToDFU(); +#endif + } + #else /* if we are currently in the main application, and we are in - * appDETACH state, switch into the DFU bootloader */ - if (g_dfu->state == DFU_STATE_appDETACH) + * appDETACH state or past downloading, switch into the DFU bootloader. + */ + if (g_dfu->state == DFU_STATE_appDETACH || g_dfu->state == DFU_STATE_dfuMANIFEST) DFURT_SwitchToDFU(); #endif /* APPLICATION_dfu */ #endif /* BOARD_USB_DFU */ diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h index 7354696..5bd8684 100644 --- a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h +++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h @@ -124,6 +124,9 @@ void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors); /* USBD tells us to switch from DFU mode to application mode */ void USBDFU_SwitchToApp(void); +/* USBD tells us to switch from to DFU mode */ +void USBDFU_SwitchToDFU(void); + /* Return values to be used by USBDFU_handle_{dn,up}load */ #define DFU_RET_NOTHING 0 #define DFU_RET_ZLP 1 diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c index ebbe070..faebc13 100644 --- a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c +++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c @@ -19,9 +19,10 @@ enum { STR_MANUF = 1, STR_PROD, STR_CONFIG, + // strings for the first alternate interface (e.g. DFU) _STR_FIRST_ALT, // serial string - STR_SERIAL = (_STR_FIRST_ALT+BOARD_DFU_NUM_IF), + STR_SERIAL = (_STR_FIRST_ALT + BOARD_DFU_NUM_IF), // version string (on additional interface) VERSION_CONF_STR, VERSION_STR, @@ -29,6 +30,25 @@ enum { STRING_DESC_CNT, }; +/* string used to replace one of both DFU flash partition atlsettings */ +static const unsigned char usb_string_notavailable[] = { + USBStringDescriptor_LENGTH(13), + USBGenericDescriptor_STRING, + USBStringDescriptor_UNICODE('n'), + USBStringDescriptor_UNICODE('o'), + USBStringDescriptor_UNICODE('t'), + USBStringDescriptor_UNICODE(' '), + USBStringDescriptor_UNICODE('a'), + USBStringDescriptor_UNICODE('v'), + USBStringDescriptor_UNICODE('a'), + USBStringDescriptor_UNICODE('i'), + USBStringDescriptor_UNICODE('l'), + USBStringDescriptor_UNICODE('a'), + USBStringDescriptor_UNICODE('b'), + USBStringDescriptor_UNICODE('l'), + USBStringDescriptor_UNICODE('e'), +}; + /* USB string for the serial (using 128-bit device ID) */ static unsigned char usb_string_serial[] = { USBStringDescriptor_LENGTH(32), @@ -121,7 +141,7 @@ static const USBDeviceDescriptor fsDevice = { .bNumEndpoints = 0, \ .bInterfaceClass = 0xfe, \ .bInterfaceSubClass = 1, \ - .iInterface = (_STR_FIRST_ALT+ALT), \ + .iInterface = (_STR_FIRST_ALT + ALT), \ .bInterfaceProtocol = 2, \ } @@ -180,6 +200,11 @@ void set_usb_serial_str(void) for (i = 0; i < ARRAY_SIZE(usb_strings) && i < ARRAY_SIZE(usb_strings_extended); i++) { usb_strings_extended[i] = usb_strings[i]; } +#if defined(ENVIRONMENT_dfu) + usb_strings_extended[_STR_FIRST_ALT + 1] = usb_string_notavailable; +#elif defined(ENVIRONMENT_flash) + usb_strings_extended[_STR_FIRST_ALT + 2] = usb_string_notavailable; +#endif usb_strings_extended[STR_SERIAL] = usb_string_serial; usb_strings_extended[VERSION_CONF_STR] = usb_string_version_conf; usb_strings_extended[VERSION_STR] = usb_string_version; diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c index 1cca7ab..cfb9f63 100644 --- a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c +++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c @@ -43,7 +43,7 @@ static unsigned char if_altsettings[1]; /** structure containing the DFU state and magic value to know if DFU or application should be started */ __dfudata struct dfudata _g_dfu = { - .state = DFU_STATE_appIDLE, + .state = DFU_STATE_dfuIDLE, .past_manifest = 0, .total_bytes = 0, }; @@ -463,7 +463,20 @@ void USBDFU_SwitchToApp(void) /* make sure the MAGIC is not set to enter DFU again */ g_dfu->magic = 0; - printf("switching to app\r\n"); + /* disconnect from USB to ensure re-enumeration */ + USBD_Disconnect(); + + /* disable any interrupts during transition */ + __disable_irq(); + + /* Tell the hybrid to execute FTL JUMP! */ + NVIC_SystemReset(); +} + +void USBDFU_SwitchToDFU(void) +{ + /* make sure the MAGIC is not set to enter DFU again */ + g_dfu->magic = USB_DFU_MAGIC; /* disconnect from USB to ensure re-enumeration */ USBD_Disconnect(); diff --git a/firmware/libboard/common/include/board_common.h b/firmware/libboard/common/include/board_common.h index dd21e4b..7c4b908 100644 --- a/firmware/libboard/common/include/board_common.h +++ b/firmware/libboard/common/include/board_common.h @@ -112,10 +112,13 @@ #define BOARD_USB_UDP #define BOARD_USB_DFU + + #define BOARD_DFU_BOOT_SIZE (16 * 1024) #define BOARD_DFU_RAM_SIZE (2 * 1024) #define BOARD_DFU_PAGE_SIZE 512 -#define BOARD_DFU_NUM_IF 2 +/** number of DFU interfaces (used to flash specific partitions) */ +#define BOARD_DFU_NUM_IF 3 extern void board_exec_dbg_cmd(int ch); extern void board_main_top(void); diff --git a/firmware/libboard/common/source/board_cstartup_gnu.c b/firmware/libboard/common/source/board_cstartup_gnu.c index e82a2fb..d548a30 100644 --- a/firmware/libboard/common/source/board_cstartup_gnu.c +++ b/firmware/libboard/common/source/board_cstartup_gnu.c @@ -126,7 +126,7 @@ IntFunc exception_table[] = { IrqHandlerNotUsed /* 35 not used */ }; -#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu) +#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu) && defined(ENVIRONMENT_flash) #include "usb/device/dfu/dfu.h" static void BootIntoApp(void) { @@ -159,8 +159,9 @@ void ResetException( void ) LowLevelInit() ; -#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu) - if (!USBDFU_OverrideEnterDFU()) { +#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu) && defined(ENVIRONMENT_flash) + // boot application if there is not DFU override + if (!USBDFU_OverrideEnterDFU() && SCB->VTOR < IFLASH_ADDR + BOARD_DFU_BOOT_SIZE) { UART_Exit(); __disable_irq(); BootIntoApp(); |