From 1c2b1d22016957bebe0a49c9069b85815f7cf936 Mon Sep 17 00:00:00 2001 From: laforge Date: Fri, 22 Sep 2006 21:29:57 +0000 Subject: - we increase the DFU size from 4k to 16k size. This is mainly due to the SAM7S128 and SAM7S256 being restricted to 16k lock region size. If we want to lock the bootloader, it has to be 16k aligned. This wastes a lot of memory, since a non-debug DFU implementation fits currently into less than 4k. But anyway, we have lots of flexibility for the future given that amount of space. - The DFU size change introduces also a change in dfu_api location to 0x103fd0 - Allow GETSTATE and GETSTATUS from runtime mode (optional in DFU spec) - Make dfu_status a .data.shared variable, since it is used from GETSTATUS which we already support in runtime mode - do some led switching while flashing via DFU - disable all non-usb/dbgu interrupts when switching to DFU mode - fix interrupt-storm problem when dbgu is used in DFU loader - add missing linker script for SAM7S128 git-svn-id: https://svn.openpcd.org:2342/trunk@218 6dc7ffe9-61d6-0310-9af1-9938baff3ed1 --- firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld | 94 +++++++++++++++++++++++++++ firmware/link/AT91SAM7S128-ROM-sam7dfu-dfu.ld | 2 +- firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld | 8 +-- firmware/link/AT91SAM7S256-ROM-sam7dfu-dfu.ld | 2 +- firmware/src/dfu/dbgu.c | 5 +- firmware/src/dfu/dfu.c | 70 +++++++++++++++----- firmware/src/dfu/dfu.h | 2 +- firmware/src/dfu/flash.c | 5 +- 8 files changed, 159 insertions(+), 29 deletions(-) create mode 100644 firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld (limited to 'firmware') diff --git a/firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld b/firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld new file mode 100644 index 0000000..0c6ac80 --- /dev/null +++ b/firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld @@ -0,0 +1,94 @@ +/* Memory Definitions */ + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00104000, LENGTH = (0x00020000 - 0x4000) + DATA (rw) : ORIGIN = 0x00200028, LENGTH = (0x00008000 - 0x28) + STACK (rw) : ORIGIN = 0x00208000, LENGTH = 0x00000000 +} + + +/* Section Definitions */ + +SECTIONS +{ + . = 0x00000000; + /* first section is .text which is used for code */ + .text 0x00104000: AT ( 0x00000000 ) { + src/start/Cstartup_app.o (.text) + * (.text) + * (.rodata*) + . = ALIGN(4); + } >FLASH + + _etext = . ; + PROVIDE (etext = .); + + /* 0x00200000 ... */ + .data 0x00200028: AT ( ADDR(.text) + SIZEOF(.text) - ADDR(.text) ) { + _data = . ; + * (.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/link/AT91SAM7S128-ROM-sam7dfu-dfu.ld b/firmware/link/AT91SAM7S128-ROM-sam7dfu-dfu.ld index dfcfff1..1c5a15f 100644 --- a/firmware/link/AT91SAM7S128-ROM-sam7dfu-dfu.ld +++ b/firmware/link/AT91SAM7S128-ROM-sam7dfu-dfu.ld @@ -49,7 +49,7 @@ SECTIONS /* dfu.functab addresses are valid as long as DFU is in flash, i.e. * only while application calls those functions. Once executing in * DFU mode, we are re-located to ram */ - .dfu.functab 0x00000fd0: AT ( ADDR(.dfu.functab) - ADDR(.text) ) { + .dfu.functab 0x00003fd0: AT ( ADDR(.dfu.functab) - ADDR(.text) ) { *(.dfu.functab) . = ALIGN(4096); } >FLASH diff --git a/firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld b/firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld index 32bd787..8f60809 100644 --- a/firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld +++ b/firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld @@ -2,8 +2,8 @@ MEMORY { - FLASH (rx) : ORIGIN = 0x00101000, LENGTH = (0x00040000 - 0x1000) - DATA (rw) : ORIGIN = 0x00200024, LENGTH = (0x00010000 - 0x24) + FLASH (rx) : ORIGIN = 0x00104000, LENGTH = (0x00040000 - 0x4000) + DATA (rw) : ORIGIN = 0x00200028, LENGTH = (0x00010000 - 0x28) STACK (rw) : ORIGIN = 0x00210000, LENGTH = 0x00000000 } @@ -14,7 +14,7 @@ SECTIONS { . = 0x00000000; /* first section is .text which is used for code */ - .text 0x00101000: AT ( 0x00000000 ) { + .text 0x00104000: AT ( 0x00000000 ) { src/start/Cstartup_app.o (.text) * (.text) * (.rodata*) @@ -25,7 +25,7 @@ SECTIONS PROVIDE (etext = .); /* 0x00200000 ... */ - .data 0x00200024: AT ( ADDR(.text) + SIZEOF(.text) - ADDR(.text) ) { + .data 0x00200028: AT ( ADDR(.text) + SIZEOF(.text) - ADDR(.text) ) { _data = . ; * (.data) . = ALIGN(4); diff --git a/firmware/link/AT91SAM7S256-ROM-sam7dfu-dfu.ld b/firmware/link/AT91SAM7S256-ROM-sam7dfu-dfu.ld index ca450a3..908f818 100644 --- a/firmware/link/AT91SAM7S256-ROM-sam7dfu-dfu.ld +++ b/firmware/link/AT91SAM7S256-ROM-sam7dfu-dfu.ld @@ -48,7 +48,7 @@ SECTIONS /* dfu.functab addresses are valid as long as DFU is in flash, i.e. * only while application calls those functions. Once executing in * DFU mode, we are re-located to ram */ - .dfu.functab 0x00010fd0: AT ( ADDR(.dfu.functab) - ADDR(.text) ) { + .dfu.functab 0x00003fd0: AT ( ADDR(.dfu.functab) - ADDR(.text) ) { *(.dfu.functab) . = ALIGN(4096); } >FLASH diff --git a/firmware/src/dfu/dbgu.c b/firmware/src/dfu/dbgu.c index 4a8d68f..367a399 100644 --- a/firmware/src/dfu/dbgu.c +++ b/firmware/src/dfu/dbgu.c @@ -65,11 +65,8 @@ void AT91F_DBGU_Init(void) /* open interrupt */ - /* FIXME: This should be HIGH_LEVEL, but somehow this triggers an - * interrupt storm. no idea why it's working in 'os' but not in 'dfu' - * */ AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS, USART_SYS_LEVEL, - AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, + AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, DBGU_irq_handler); AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS); diff --git a/firmware/src/dfu/dfu.c b/firmware/src/dfu/dfu.c index bb8d057..693f2eb 100644 --- a/firmware/src/dfu/dfu.c +++ b/firmware/src/dfu/dfu.c @@ -32,7 +32,9 @@ #include #include "../openpcd.h" -#define SAM7DFU_SIZE 0x1000 +#include + +#define SAM7DFU_SIZE 0x4000 /* If debug is enabled, we need to access debug functions from flash * and therefore have to omit flashing */ @@ -57,6 +59,12 @@ #define RET_ZLP 1 #define RET_STALL 2 +#define led1on() AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1) +#define led1off() AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1) + +#define led2on() AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2) +#define led2off() AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2) + static void __dfufunc udp_init(void) { /* Set the PLL USB Divider */ @@ -185,8 +193,8 @@ static void __dfufunc udp_ep0_send_stall(void) } -static u_int8_t status; static u_int8_t *ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE; +static __dfudata u_int8_t dfu_status; static __dfudata u_int32_t dfu_state = DFU_STATE_appIDLE; static u_int32_t pagebuf32[AT91C_IFLASH_PAGE_SIZE/4]; @@ -203,14 +211,14 @@ static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len) * DFU protocol violation */ DEBUGP("length exceeds flash page size "); dfu_state = DFU_STATE_dfuERROR; - status = DFU_STATUS_errADDRESS; + dfu_status = DFU_STATUS_errADDRESS; return RET_STALL; } if (len & 0x3) { /* reject non-four-byte-aligned writes */ DEBUGP("not four-byte-aligned length "); dfu_state = DFU_STATE_dfuERROR; - status = DFU_STATUS_errADDRESS; + dfu_status = DFU_STATUS_errADDRESS; return RET_STALL; } if (len == 0) { @@ -222,7 +230,7 @@ static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len) if (ptr + len > (u_int8_t *) AT91C_IFLASH + AT91C_IFLASH_SIZE) { DEBUGP("end of write exceeds flash end "); dfu_state = DFU_STATE_dfuERROR; - status = DFU_STATUS_errADDRESS; + dfu_status = DFU_STATUS_errADDRESS; return RET_STALL; } @@ -256,7 +264,7 @@ static __dfufunc int handle_upload(u_int16_t val, u_int16_t len) if (len > AT91C_IFLASH_PAGE_SIZE) { /* Too big */ dfu_state = DFU_STATE_dfuERROR; - status = DFU_STATUS_errADDRESS; + dfu_status = DFU_STATUS_errADDRESS; udp_ep0_send_stall(); return -EINVAL; } @@ -282,11 +290,11 @@ static __dfufunc void handle_getstatus(void) case DFU_STATE_dfuDNBUSY: if (fsr & AT91C_MC_PROGE) { DEBUGE("errPROG "); - status = DFU_STATUS_errPROG; + dfu_status = DFU_STATUS_errPROG; dfu_state = DFU_STATE_dfuERROR; } else if (fsr & AT91C_MC_LOCKE) { DEBUGE("errWRITE "); - status = DFU_STATUS_errWRITE; + dfu_status = DFU_STATUS_errWRITE; dfu_state = DFU_STATE_dfuERROR; } else if (fsr & AT91C_MC_FRDY) { DEBUGE("DNLOAD_IDLE "); @@ -302,7 +310,7 @@ static __dfufunc void handle_getstatus(void) } /* send status response */ - dstat.bStatus = status; + dstat.bStatus = dfu_status; dstat.bState = dfu_state; dstat.iString = 0; /* FIXME: set dstat.bwPollTimeout */ @@ -328,12 +336,21 @@ int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req, switch (dfu_state) { case DFU_STATE_appIDLE: - if (req != USB_REQ_DFU_DETACH) { - ret = RET_STALL; + switch (req) { + case USB_REQ_DFU_GETSTATUS: + handle_getstatus(); + break; + case USB_REQ_DFU_GETSTATE: + handle_getstate(); + break; + case USB_REQ_DFU_DETACH: + dfu_state = DFU_STATE_appDETACH; + ret = RET_ZLP; goto out; + break; + default: + ret = RET_STALL; } - dfu_state = DFU_STATE_appDETACH; - ret = RET_ZLP; break; case DFU_STATE_appDETACH: switch (req) { @@ -491,7 +508,7 @@ int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req, break; case USB_REQ_DFU_CLRSTATUS: dfu_state = DFU_STATE_dfuIDLE; - status = DFU_STATUS_OK; + dfu_status = DFU_STATUS_OK; /* no zlp? */ ret = RET_ZLP; break; @@ -768,8 +785,10 @@ static __dfufunc void dfu_udp_irq(void) { AT91PS_UDP pUDP = AT91C_BASE_UDP; AT91_REG isr = pUDP->UDP_ISR; + led1on(); if (isr & AT91C_UDP_ENDBUSRES) { + led2on(); pUDP->UDP_IER = AT91C_UDP_EPINT0; /* reset all endpoints */ pUDP->UDP_RSTEP = (unsigned int)-1; @@ -788,6 +807,9 @@ static __dfufunc void dfu_udp_irq(void) pUDP->UDP_ICR = isr; AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_UDP); + + { volatile int i; for (i=0; i< 0x3ff; i++) ; } + led1off(); } /* this is only called once before DFU mode, no __dfufunc required */ @@ -795,17 +817,35 @@ static void dfu_switch(void) { AT91PS_AIC pAic = AT91C_BASE_AIC; - DEBUGE("Switching to DFU mode "); + AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1); + AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2); + led1off(); + led2off(); + + flash_init(); + + /* disable all non-usb (and non-dbgu) interrupts */ + pAic->AIC_IDCR = ~((1 << AT91C_ID_UDP)|(1 << AT91C_ID_SYS)); pAic->AIC_SVR[AT91C_ID_UDP] = (unsigned int) &dfu_udp_irq; dfu_state = DFU_STATE_dfuIDLE; + dfu_status = DFU_STATUS_OK; } void __dfufunc dfu_main(void) { + AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1); + AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2); + led1off(); + led2off(); + AT91F_DBGU_Init(); DEBUGE("sam7dfu startup\r\n"); + AT91F_DBGU_Printk("\n\r"); + AT91F_DBGU_Printk(COMPILE_DATE " " COMPILE_BY " " COMPILE_SVNREV); + AT91F_DBGU_Printk("\n\r"); + udp_init(); dfu_state = DFU_STATE_dfuIDLE; diff --git a/firmware/src/dfu/dfu.h b/firmware/src/dfu/dfu.h index b8d48ec..4d53ce7 100644 --- a/firmware/src/dfu/dfu.h +++ b/firmware/src/dfu/dfu.h @@ -55,7 +55,7 @@ #define __dfufunc #define __dfustruct const -#define DFU_API_LOCATION ((const struct dfuapi *) 0x00100fd0) +#define DFU_API_LOCATION ((const struct dfuapi *) 0x00103fd0) struct _dfu_desc { struct usb_config_descriptor ucfg; diff --git a/firmware/src/dfu/flash.c b/firmware/src/dfu/flash.c index 4d0c9d9..0411f73 100644 --- a/firmware/src/dfu/flash.c +++ b/firmware/src/dfu/flash.c @@ -65,7 +65,6 @@ void flash_init(void) { unsigned int fmcn = AT91F_MC_EFC_ComputeFMCN(MCK); - AT91F_MC_EFC_CfgModeReg(AT91C_BASE_MC, fmcn << 16 | AT91C_MC_FWS_3FWS | - AT91C_MC_FRDY | AT91C_MC_LOCKE | - AT91C_MC_PROGE); + AT91F_MC_EFC_CfgModeReg(AT91C_BASE_MC, (fmcn&0xff) << 16 | + AT91C_MC_FWS_3FWS); } -- cgit v1.2.3