diff options
Diffstat (limited to 'firmware/src/dfu')
-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 |
4 files changed, 59 insertions, 23 deletions
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); } |