From dda0896d875ec2d33b6de94df818a2f94526272b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 30 Jul 2011 00:34:59 +0200 Subject: use gcc/ld flags -ffunction-sections and --gc-sections This will discard unused functions from the resulting binary --- firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld | 10 +++++----- firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld | 10 +++++----- firmware/link/AT91SAM7S64-ROM-sam7dfu-app.ld | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) (limited to 'firmware/link') diff --git a/firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld b/firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld index ebac6d4..7db540e 100644 --- a/firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld +++ b/firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld @@ -16,8 +16,8 @@ SECTIONS . = 0x00000000; /* first section is .text which is used for code */ .text 0x00104000: AT ( 0x00000000 ) { - src/start/Cstartup_app.o (.text) - * (.text) + src/start/Cstartup_app.o (.text*) + * (.text*) * (.rodata*) . = ALIGN(4); } >FLASH @@ -28,8 +28,8 @@ SECTIONS /* 0x00200000 ... */ .data 0x00200028: AT ( ADDR(.text) + SIZEOF(.text) - ADDR(.text) ) { _data = . ; - * (.fastrun) - * (.data) + * (.fastrun*) + * (.data*) . = ALIGN(4); } >DATA @@ -40,7 +40,7 @@ SECTIONS .bss : { __bss_start = . ; __bss_start__ = . ; - *(.bss) + *(.bss*) *(COMMON) } >DATA diff --git a/firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld b/firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld index 85bf7b8..7ec2089 100644 --- a/firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld +++ b/firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld @@ -16,8 +16,8 @@ SECTIONS . = 0x00000000; /* first section is .text which is used for code */ .text 0x00104000: AT ( 0x00000000 ) { - src/start/Cstartup_app.o (.text) - * (.text) + src/start/Cstartup_app.o (.text*) + * (.text*) * (.rodata*) . = ALIGN(4); } >FLASH @@ -28,8 +28,8 @@ SECTIONS /* 0x00200000 ... */ .data 0x00200028: AT ( ADDR(.text) + SIZEOF(.text) - ADDR(.text) ) { _data = . ; - * (.fastrun) - * (.data) + * (.fastrun*) + * (.data*) . = ALIGN(4); } >DATA @@ -40,7 +40,7 @@ SECTIONS .bss : { __bss_start = . ; __bss_start__ = . ; - *(.bss) + *(.bss*) *(COMMON) } >DATA diff --git a/firmware/link/AT91SAM7S64-ROM-sam7dfu-app.ld b/firmware/link/AT91SAM7S64-ROM-sam7dfu-app.ld index de24dd8..d45f691 100644 --- a/firmware/link/AT91SAM7S64-ROM-sam7dfu-app.ld +++ b/firmware/link/AT91SAM7S64-ROM-sam7dfu-app.ld @@ -16,8 +16,8 @@ SECTIONS . = 0x00000000; /* first section is .text which is used for code */ .text 0x00104000: AT ( 0x00000000 ) { - src/start/Cstartup_app.o (.text) - * (.text) + src/start/Cstartup_app.o (.text*) + * (.text*) * (.rodata*) . = ALIGN(4); } >FLASH @@ -28,8 +28,8 @@ SECTIONS /* 0x00200000 ... */ .data 0x00200028: AT ( ADDR(.text) + SIZEOF(.text) - ADDR(.text) ) { _data = . ; - * (.fastrun) - * (.data) + * (.fastrun*) + * (.data*) . = ALIGN(4); } >DATA @@ -40,7 +40,7 @@ SECTIONS .bss : { __bss_start = . ; __bss_start__ = . ; - *(.bss) + *(.bss*) *(COMMON) } >DATA -- cgit v1.2.3 From 5a8cd9feca7d0d09aee736ff804be4967828aefd Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 30 Jul 2011 00:37:04 +0200 Subject: add new RUN_FROM_RAM run-mode for direct DFU-to-RAM support --- firmware/Makefile | 4 +- firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld | 94 +++++++++++++++++++++++++++ firmware/src/os/req_ctx.c | 2 +- firmware/src/start/Cstartup_app.S | 2 + 4 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld (limited to 'firmware/link') diff --git a/firmware/Makefile b/firmware/Makefile index b085c33..68ff85f 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -49,7 +49,7 @@ USE_THUMB_MODE = NO #USE_THUMB_MODE = YES ## Create ROM-Image (final) -RUN_MODE=RUN_FROM_ROM +RUN_MODE:=RUN_FROM_ROM ## Create RAM-Image (debugging) - not used in this example #RUN_MODE=RUN_FROM_RAM @@ -319,7 +319,7 @@ LDFLAGS += -Wl,--gc-sections -Wl,--entry=_startup # Set Linker-Script Depending On Selected Memory and Controller ifeq ($(RUN_MODE),RUN_FROM_RAM) -LDFLAGS +=-T$(PATH_TO_LINKSCRIPTS)$(SUBMDL)-RAM.ld +LDFLAGS +=-T$(PATH_TO_LINKSCRIPTS)$(SUBMDL)-RAM$(IMGTYPE).ld else LDFLAGS +=-T$(PATH_TO_LINKSCRIPTS)$(SUBMDL)-ROM$(IMGTYPE).ld endif diff --git a/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld b/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld new file mode 100644 index 0000000..674ee00 --- /dev/null +++ b/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld @@ -0,0 +1,94 @@ +/* Memory Definitions */ + +MEMORY +{ + /* reserve 16K DFU area on top of flash */ + /* FLASH (rx) : ORIGIN = 0x00104000, LENGTH = (0x00020000 - 0x4000 - 0x400) */ + /* reserve 1k DFU area on top of RAM */ + DATA (rw) : ORIGIN = 0x00200400, LENGTH = (0x00008000 - 0x400) + STACK (rw) : ORIGIN = 0x00208000, LENGTH = 0x00000000 +} + + +/* Section Definitions */ + +SECTIONS +{ + . = 0x00000000; + /* first section is .text which is used for code */ + .text 0x00200400: AT ( 0x00000000 ) { + src/start/Cstartup_app.o (.text) + * (.text) + * (.rodata*) + . = ALIGN(4); + + _etext = . ; + PROVIDE (etext = .); + + _data = . ; + * (.fastrun) + * (.data) + . = ALIGN(4); + } >DATA + + _edata = . ; + PROVIDE (edata = .); + + /* .bss section which is used for uninitialized data */ + .bss : { + __bss_start = . ; + __bss_start__ = . ; + *(.bss) + *(COMMON) + } >DATA + + . = ALIGN(4); + __bss_end__ = . ; + __bss_end__ = . ; + + PROVIDE (main = .); + + _end = . ; + + . = ALIGN(4); + .int_data : { + *(.internal_ram_top) + } >STACK + + PROVIDE (end = .); + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + +} diff --git a/firmware/src/os/req_ctx.c b/firmware/src/os/req_ctx.c index 0e4816e..cc8d57b 100644 --- a/firmware/src/os/req_ctx.c +++ b/firmware/src/os/req_ctx.c @@ -28,7 +28,7 @@ /* FIXME: locking, FIFO order processing */ -#ifdef __AT91SAM7S64__ +#if defined(__AT91SAM7S64__) || defined(RUN_FROM_RAM) #define NUM_RCTX_SMALL 16 #define NUM_RCTX_LARGE 1 #else diff --git a/firmware/src/start/Cstartup_app.S b/firmware/src/start/Cstartup_app.S index 448cc93..197be66 100644 --- a/firmware/src/start/Cstartup_app.S +++ b/firmware/src/start/Cstartup_app.S @@ -79,6 +79,7 @@ .global _startup .func _startup _startup: +#ifndef RUN_FROM_RAM /* Relocate .data section (copy from Flash to RAM) */ ldr r1, =_etext ldr r2, =_data @@ -87,6 +88,7 @@ loop_r: cmp r2, r3 ldrlo r0, [r1], #4 strlo r0, [r2], #4 blo loop_r +#endif /* Clear .bss section (Zero init) */ mov r0, #0 -- cgit v1.2.3 From 58d958e60c429bd7a2b2d114a4f7a86a65bdacef Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 30 Jul 2011 02:56:36 +0200 Subject: DFU: Support re-flashing of DFU via DFU As we re-locate the entire sam7dfu program into RAM, we don't need to execute from flash and can thus re-program the DFU partition via the DFU protocol itself (alternate setting '1'). We also implement downloading executable code into RAM using alternate setting '2'. The latter part is not properly executed yet. --- firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld | 4 +- firmware/src/dfu/dfu.c | 148 +++++++++++++++++++++++--- 2 files changed, 134 insertions(+), 18 deletions(-) (limited to 'firmware/link') diff --git a/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld b/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld index 674ee00..ad02776 100644 --- a/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld +++ b/firmware/link/AT91SAM7S128-RAM-sam7dfu-app.ld @@ -5,7 +5,7 @@ MEMORY /* reserve 16K DFU area on top of flash */ /* FLASH (rx) : ORIGIN = 0x00104000, LENGTH = (0x00020000 - 0x4000 - 0x400) */ /* reserve 1k DFU area on top of RAM */ - DATA (rw) : ORIGIN = 0x00200400, LENGTH = (0x00008000 - 0x400) + DATA (rw) : ORIGIN = 0x00202000, LENGTH = (0x00008000 - 0x2000) STACK (rw) : ORIGIN = 0x00208000, LENGTH = 0x00000000 } @@ -16,7 +16,7 @@ SECTIONS { . = 0x00000000; /* first section is .text which is used for code */ - .text 0x00200400: AT ( 0x00000000 ) { + .text 0x00202000: AT ( 0x00000000 ) { src/start/Cstartup_app.o (.text) * (.text) * (.rodata*) diff --git a/firmware/src/dfu/dfu.c b/firmware/src/dfu/dfu.c index 6a2f59c..f65b00d 100644 --- a/firmware/src/dfu/dfu.c +++ b/firmware/src/dfu/dfu.c @@ -1,5 +1,5 @@ /* USB Device Firmware Update Implementation for OpenPCD - * (C) 2006 by Harald Welte + * (C) 2006-2011 by Harald Welte * * This ought to be compliant to the USB DFU Spec 1.0 as available from * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf @@ -37,6 +37,7 @@ #include #define SAM7DFU_SIZE 0x4000 +#define SAM7DFU_RAM_SIZE 0x2000 /* If debug is enabled, we need to access debug functions from flash * and therefore have to omit flashing */ @@ -70,6 +71,8 @@ #define led2off() AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2) static int past_manifest = 0; +static u_int16_t usb_if_nr = 0; +static u_int16_t usb_if_alt_nr = 0; static void __dfufunc udp_init(void) { @@ -212,14 +215,37 @@ static void __dfufunc udp_ep0_send_stall(void) } -static u_int8_t *ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE; +static int first_download = 1; +static u_int8_t *ptr, *ptr_max; static __dfudata u_int8_t dfu_status; __dfudata u_int32_t dfu_state = DFU_STATE_appIDLE; static u_int32_t pagebuf32[AT91C_IFLASH_PAGE_SIZE/4]; -static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len) +static void chk_first_dnload_set_ptr(void) +{ + if (!first_download) + return; + + switch (usb_if_alt_nr) { + case 0: + ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE; + ptr_max = AT91C_IFLASH + AT91C_IFLASH_SIZE - ENVIRONMENT_SIZE; + break; + case 1: + ptr = (u_int8_t *) AT91C_IFLASH; + ptr_max = AT91C_IFLASH + SAM7DFU_SIZE; + break; + case 2: + ptr = (u_int8_t *) AT91C_ISRAM + SAM7DFU_RAM_SIZE; + ptr_max = AT91C_ISRAM + AT91C_ISRAM_SIZE; + break; + } + first_download = 0; +} + +static int __dfufunc handle_dnload_flash(u_int16_t val, u_int16_t len) { - volatile u_int32_t *p = (volatile u_int32_t *)ptr; + volatile u_int32_t *p; u_int8_t *pagebuf = (u_int8_t *) pagebuf32; int i; @@ -240,13 +266,20 @@ static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len) dfu_status = DFU_STATUS_errADDRESS; return RET_STALL; } + chk_first_dnload_set_ptr(); + p = (volatile u_int32_t *)ptr; + if (len == 0) { DEBUGP("zero-size write -> MANIFEST_SYNC "); - flash_page(p); + if (((unsigned long)p % AT91C_IFLASH_PAGE_SIZE) != 0) + flash_page(p); dfu_state = DFU_STATE_dfuMANIFEST_SYNC; + first_download = 1; return RET_ZLP; } - if (ptr + len >= (u_int8_t *) AT91C_IFLASH + AT91C_IFLASH_SIZE - ENVIRONMENT_SIZE ) { + + /* check if we would exceed end of memory */ + if (ptr + len > ptr_max) { DEBUGP("end of write exceeds flash end "); dfu_state = DFU_STATE_dfuERROR; dfu_status = DFU_STATUS_errADDRESS; @@ -258,10 +291,10 @@ static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len) DEBUGR(hexdump(pagebuf, len)); - /* we can only access the write buffer with correctly aligned - * 32bit writes ! */ #ifndef DEBUG_DFU_NOFLASH DEBUGP("copying "); + /* we can only access the write buffer with correctly aligned + * 32bit writes ! */ for (i = 0; i < len/4; i++) { *p++ = pagebuf32[i]; /* If we have filled a page buffer, flash it */ @@ -276,6 +309,56 @@ static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len) return RET_ZLP; } +static int __dfufunc handle_dnload_ram(u_int16_t val, u_int16_t len) +{ + DEBUGE("download "); + + if (len > AT91C_IFLASH_PAGE_SIZE) { + /* Too big. Not that we'd really care, but it's a + * DFU protocol violation */ + DEBUGP("length exceeds flash page size "); + dfu_state = DFU_STATE_dfuERROR; + dfu_status = DFU_STATUS_errADDRESS; + return RET_STALL; + } + chk_first_dnload_set_ptr(); + + if (len == 0) { + DEBUGP("zero-size write -> MANIFEST_SYNC "); + dfu_state = DFU_STATE_dfuMANIFEST_SYNC; + first_download = 1; + return RET_ZLP; + } + + /* check if we would exceed end of memory */ + if (ptr + len >= ptr_max) { + DEBUGP("end of write exceeds RAM end "); + dfu_state = DFU_STATE_dfuERROR; + dfu_status = DFU_STATUS_errADDRESS; + return RET_STALL; + } + + /* drectly copy into RAM */ + DEBUGP("try_to_recv=%u ", len); + udp_ep0_recv_data(ptr, len); + + DEBUGR(hexdump(ptr, len)); + + ptr += len; + + return RET_ZLP; +} + +static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len) +{ + switch (usb_if_alt_nr) { + case 2: + return handle_dnload_ram(val, len); + default: + return handle_dnload_flash(val, len); + } +} + #define AT91C_IFLASH_END ((u_int8_t *)AT91C_IFLASH + AT91C_IFLASH_SIZE) static __dfufunc int handle_upload(u_int16_t val, u_int16_t len) { @@ -287,9 +370,12 @@ static __dfufunc int handle_upload(u_int16_t val, u_int16_t len) udp_ep0_send_stall(); return -EINVAL; } + chk_first_dnload_set_ptr(); - if (ptr + len > AT91C_IFLASH_END) + if (ptr + len > AT91C_IFLASH_END) { len = AT91C_IFLASH_END - (u_int8_t *)ptr; + first_download = 1; + } udp_ep0_send_data((char *)ptr, len); ptr+= len; @@ -606,7 +692,7 @@ __dfustruct const struct _dfu_desc dfu_cfg_descriptor = { .bLength = USB_DT_CONFIG_SIZE, .bDescriptorType = USB_DT_CONFIG, .wTotalLength = USB_DT_CONFIG_SIZE + - 2* USB_DT_INTERFACE_SIZE + + 3* USB_DT_INTERFACE_SIZE + USB_DT_DFU_SIZE, .bNumInterfaces = 1, .bConfigurationValue = 1, @@ -648,6 +734,21 @@ __dfustruct const struct _dfu_desc dfu_cfg_descriptor = { .iInterface = 0, #endif }, + .uif[2] = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0x00, + .bAlternateSetting = 0x02, + .bNumEndpoints = 0x00, + .bInterfaceClass = 0xfe, + .bInterfaceSubClass = 0x01, + .bInterfaceProtocol = 0x02, +#ifdef CONFIG_USB_STRING + .iInterface = 6, +#else + .iInterface = 0, +#endif + }, .func_dfu = DFU_FUNC_DESC, }; @@ -831,9 +932,11 @@ static __dfufunc void dfu_udp_ep0_handler(void) udp_ep0_send_stall(); break; case STD_SET_INTERFACE: - DEBUGE("SET INTERFACE "); - /* FIXME: store the interface number somewhere, once + DEBUGE("SET INTERFACE(if=%d, alt=%d) ", wIndex, wValue); + /* store the interface number somewhere, once * we need to support DFU flashing DFU */ + usb_if_alt_nr = wValue; + usb_if_nr = wIndex; udp_ep0_send_zlp(); break; default: @@ -849,6 +952,8 @@ static __dfufunc void dfu_udp_ep0_handler(void) DEBUGE("\r\n"); } +const void (*ram_app_entry)(void) = AT91C_ISRAM + SAM7DFU_RAM_SIZE; + /* minimal USB IRQ handler in DFU mode */ static __dfufunc void dfu_udp_irq(void) { @@ -871,10 +976,21 @@ static __dfufunc void dfu_udp_irq(void) if (dfu_state == DFU_STATE_dfuMANIFEST_WAIT_RST || dfu_state == DFU_STATE_dfuMANIFEST || past_manifest) { - /* reset back into the main application */ - AT91F_RSTSoftReset(AT91C_BASE_RSTC, AT91C_RSTC_PROCRST| - AT91C_RSTC_PERRST| - AT91C_RSTC_EXTRST); + AT91F_DBGU_Printk("sam7dfu: switching to APP mode\r\n"); + switch (usb_if_alt_nr) { + case 2: + /* jump into RAM */ + DEBUGP("JUMP TO RAM ENTRY %p\r\n", ram_app_entry); + ram_app_entry(); + break; + default: + /* reset back into the main application */ + AT91F_RSTSoftReset(AT91C_BASE_RSTC, + AT91C_RSTC_PROCRST| + AT91C_RSTC_PERRST| + AT91C_RSTC_EXTRST); + break; + } } } -- cgit v1.2.3