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);  }  | 
