diff options
-rw-r--r-- | firmware/link/AT91SAM7S128-ROM-sam7dfu-app.ld | 94 | ||||
-rw-r--r-- | firmware/link/AT91SAM7S128-ROM-sam7dfu-dfu.ld | 2 | ||||
-rw-r--r-- | firmware/link/AT91SAM7S256-ROM-sam7dfu-app.ld | 8 | ||||
-rw-r--r-- | firmware/link/AT91SAM7S256-ROM-sam7dfu-dfu.ld | 2 | ||||
-rw-r--r-- | firmware/src/dfu/dbgu.c | 5 | ||||
-rw-r--r-- | firmware/src/dfu/dfu.c | 70 | ||||
-rw-r--r-- | firmware/src/dfu/dfu.h | 2 | ||||
-rw-r--r-- | firmware/src/dfu/flash.c | 5 |
8 files changed, 159 insertions, 29 deletions
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 <os/pcd_enumerate.h> #include "../openpcd.h" -#define SAM7DFU_SIZE 0x1000 +#include <compile.h> + +#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); } |