From 460ece8365600e1a8fdb124c2f68de6aabf1fa62 Mon Sep 17 00:00:00 2001 From: laforge Date: Sat, 23 Sep 2006 14:49:43 +0000 Subject: - Implement runtime DFU switching and reset-after-update. This means we can now reflash without any buttons or replugging of the device git-svn-id: https://svn.openpcd.org:2342/trunk@222 6dc7ffe9-61d6-0310-9af1-9938baff3ed1 --- firmware/src/dfu/dfu.c | 34 +++++++++++++++++----------------- firmware/src/start/Cstartup.S | 24 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 17 deletions(-) (limited to 'firmware') diff --git a/firmware/src/dfu/dfu.c b/firmware/src/dfu/dfu.c index 7e7c575..56f7ef0 100644 --- a/firmware/src/dfu/dfu.c +++ b/firmware/src/dfu/dfu.c @@ -195,7 +195,7 @@ static void __dfufunc udp_ep0_send_stall(void) 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; +__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) @@ -376,9 +376,9 @@ int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req, ret = RET_STALL; goto out; } + dfu_state = DFU_STATE_dfuDNLOAD_SYNC; ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE; ret = handle_dnload(val, len); - dfu_state = DFU_STATE_dfuDNLOAD_SYNC; break; case USB_REQ_DFU_UPLOAD: ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE; @@ -433,8 +433,8 @@ int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req, case DFU_STATE_dfuDNLOAD_IDLE: switch (req) { case USB_REQ_DFU_DNLOAD: - ret = handle_dnload(val, len); dfu_state = DFU_STATE_dfuDNLOAD_SYNC; + ret = handle_dnload(val, len); break; case USB_REQ_DFU_ABORT: dfu_state = DFU_STATE_dfuIDLE; @@ -798,6 +798,14 @@ static __dfufunc void dfu_udp_irq(void) /* Configure endpoint 0 */ pUDP->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); cur_config = 0; + + if (dfu_state == DFU_STATE_dfuMANIFEST_WAIT_RST || + dfu_state == DFU_STATE_dfuMANIFEST) { + AT91F_RSTSoftReset(AT91C_BASE_RSTC, AT91C_RSTC_PROCRST| + AT91C_RSTC_PERRST| + AT91C_RSTC_EXTRST); + } + } if (isr & AT91C_UDP_EPINT0) @@ -817,22 +825,14 @@ static void dfu_switch(void) AT91PS_AIC pAic = AT91C_BASE_AIC; DEBUGE("\r\nsam7dfu: switching to DFU mode\r\n"); - 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)); + dfu_state = DFU_STATE_appDETACH; + AT91F_RSTSoftReset(AT91C_BASE_RSTC, AT91C_RSTC_PROCRST| + AT91C_RSTC_PERRST|AT91C_RSTC_EXTRST); - pAic->AIC_SVR[AT91C_ID_UDP] = (unsigned int) &dfu_udp_irq; - dfu_state = DFU_STATE_dfuIDLE; - dfu_status = DFU_STATUS_OK; - //AT91F_DBGU_Printk("You may now start the DFU up/download process\r\n"); - AT91F_DBGU_Printk("\r\nTHIS DOES NOT WORK YET, " - " PLEASE PUSH THE BUTTON WHILE POWERING UP\r\n"); + /* We should never reach here, but anyway avoid returning to the + * caller since he doesn't expect us to do so */ + while (1) ; } void __dfufunc dfu_main(void) diff --git a/firmware/src/start/Cstartup.S b/firmware/src/start/Cstartup.S index a750039..990dbcb 100644 --- a/firmware/src/start/Cstartup.S +++ b/firmware/src/start/Cstartup.S @@ -35,8 +35,12 @@ //*- 1.1 01/Apr/05 JPP : save SPSR //*-----------------------------------------------------------------------------*/ +/* Enable DFU by press of hardware POI_BOOTLDR switch */ #define CONFIG_DFU_SWITCH +/* Enable DFU by magic value in RAM and software reset */ +#define CONFIG_DFU_MAGIC + //#define DEBUG_LL #ifdef DEBUG_LL @@ -301,6 +305,12 @@ InitReset: .EQU I_BIT, 0x80 .EQU F_BIT, 0x40 + +#define AT91C_RSTC_RSR 0xFFFFFD04 +#define AT91C_RSTC_RSTTYP_SOFTWARE (0x03 << 8) +#define DFU_STATE_appDETACH 1 + + /*------------------------------------------------------------------------------ //*- Setup the stack for each mode //*-------------------------------*/ @@ -319,6 +329,20 @@ InitReset: msr CPSR_c, #ARM_MODE_SVC mov r13, r0 /* Init stack Sup */ +#ifdef CONFIG_DFU_MAGIC + ldr r1, =AT91C_RSTC_RSR + ldr r2, [r1] + #and r2, r2, AT91C_RSTC_RSTTYP + tst r2, #AT91C_RSTC_RSTTYP_SOFTWARE + beq dfu_magic_end + + ldr r1, =dfu_state + ldr r2, [r1] + cmp r2, #DFU_STATE_appDETACH + beq _reloc_dfu +dfu_magic_end: +#endif + # Relocate DFU .data.shared section (Copy from ROM to RAM) LDR R1, =_etext LDR R2, =_data_shared -- cgit v1.2.3