From adba0ce80b5665207c8527ae4c736faa644bf3fe Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 28 Feb 2017 01:02:24 +0100 Subject: [PATCH] fix g_dfu access from both DFU and runtime access We need to refer to g_dfu as a pointer from all code. In DFU mode, it gets assigned to the address of _g_dfu, which is placed by the linker script at the start of RAM. In runtime mode, the pointer is statically defined to point at the start of RAM. The linker script for the runtime (dfu environment) is adjusted to save the first 32 bytes for the _g_dfu structure. --- firmware/apps/dfu/main.c | 16 ++-- .../libchip_sam3s/source/USBD_HAL.c | 2 +- .../usb/device/dfu/dfu.h | 2 +- .../usb/device/dfu/dfu_driver.c | 89 ++++++++++--------- .../usb/device/dfu/dfu_runtime.c | 17 ++-- .../libboard/common/resources/sam3s4/dfu.ld | 4 +- 6 files changed, 67 insertions(+), 63 deletions(-) diff --git a/firmware/apps/dfu/main.c b/firmware/apps/dfu/main.c index af595ac1..5b078674 100644 --- a/firmware/apps/dfu/main.c +++ b/firmware/apps/dfu/main.c @@ -35,8 +35,8 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset, case ALTIF_RAM: addr = RAM_ADDR(offset); if (addr > IRAM_ADDR + IRAM_SIZE) { - g_dfu.state = DFU_STATE_dfuERROR; - g_dfu.status = DFU_STATUS_errADDRESS; + g_dfu->state = DFU_STATE_dfuERROR; + g_dfu->status = DFU_STATUS_errADDRESS; return DFU_RET_STALL; } memcpy((void *)addr, data, len); @@ -44,8 +44,8 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset, case ALTIF_FLASH: addr = FLASH_ADDR(offset); if (addr > IFLASH_ADDR + IFLASH_SIZE) { - g_dfu.state = DFU_STATE_dfuERROR; - g_dfu.status = DFU_STATUS_errADDRESS; + g_dfu->state = DFU_STATE_dfuERROR; + g_dfu->status = DFU_STATUS_errADDRESS; return DFU_RET_STALL; } rc = FLASHD_Write(addr, data, len); @@ -75,8 +75,8 @@ int USBDFU_handle_upload(uint8_t altif, unsigned int offset, case ALTIF_RAM: addr = RAM_ADDR(offset); if (addr > IRAM_ADDR + IRAM_SIZE) { - g_dfu.state = DFU_STATE_dfuERROR; - g_dfu.status = DFU_STATUS_errADDRESS; + g_dfu->state = DFU_STATE_dfuERROR; + g_dfu->status = DFU_STATUS_errADDRESS; return -1; } if ((uint8_t *)addr + req_len > IRAM_END) @@ -86,8 +86,8 @@ int USBDFU_handle_upload(uint8_t altif, unsigned int offset, case ALTIF_FLASH: addr = FLASH_ADDR(offset); if (addr > IFLASH_ADDR + IFLASH_SIZE) { - g_dfu.state = DFU_STATE_dfuERROR; - g_dfu.status = DFU_STATUS_errADDRESS; + g_dfu->state = DFU_STATE_dfuERROR; + g_dfu->status = DFU_STATUS_errADDRESS; return -1; } if ((uint8_t *)addr + req_len > IFLASH_END) diff --git a/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c b/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c index 7776004f..05e62e4c 100644 --- a/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c +++ b/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c @@ -1164,7 +1164,7 @@ void USBD_IrqHandler(void) TRACE_INFO_WP("EoBRes "); #if defined(BOARD_USB_DFU) && defined(dfu) - if (g_dfu.past_manifest) + if (g_dfu->past_manifest) USBDFU_SwitchToApp(); #endif diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h index 9033de66..b49cce08 100644 --- a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h +++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h @@ -98,7 +98,7 @@ struct dfudata { unsigned int total_bytes; }; -extern struct dfudata g_dfu; +extern struct dfudata *g_dfu; void set_usb_serial_str(const uint8_t *serial_usbstr); diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c index 14a8469f..5ba84c39 100644 --- a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c +++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c @@ -42,11 +42,12 @@ static USBDDriver usbdDriver; static unsigned char if_altsettings[1]; -__dfudata struct dfudata g_dfu = { +__dfudata struct dfudata _g_dfu = { .state = DFU_STATE_appIDLE, .past_manifest = 0, .total_bytes = 0, }; +struct dfudata *g_dfu = &_g_dfu; WEAK void dfu_drv_updstatus(void) { @@ -55,8 +56,8 @@ WEAK void dfu_drv_updstatus(void) /* we transition immediately from MANIFEST_SYNC to MANIFEST, * as the flash-writing is not asynchronous in this * implementation */ - if (g_dfu.state == DFU_STATE_dfuMANIFEST_SYNC) - g_dfu.state = DFU_STATE_dfuMANIFEST; + if (g_dfu->state == DFU_STATE_dfuMANIFEST_SYNC) + g_dfu->state = DFU_STATE_dfuMANIFEST; } static __dfufunc void handle_getstatus(void) @@ -67,8 +68,8 @@ static __dfufunc void handle_getstatus(void) dfu_drv_updstatus(); /* send status response */ - dstat.bStatus = g_dfu.status; - dstat.bState = g_dfu.state; + dstat.bStatus = g_dfu->status; + dstat.bState = g_dfu->state; dstat.iString = 0; /* FIXME: set dstat.bwPollTimeout */ @@ -79,9 +80,9 @@ static __dfufunc void handle_getstatus(void) static void __dfufunc handle_getstate(void) { - uint8_t u8 = g_dfu.state; + uint8_t u8 = g_dfu->state; - TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu.state); + TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu->state); USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0); } @@ -114,15 +115,15 @@ static void dnload_cb(void *arg, unsigned char status, unsigned long int transfe return; } - rc = USBDFU_handle_dnload(if_altsettings[0], g_dfu.total_bytes, dfu_buf, transferred); + rc = USBDFU_handle_dnload(if_altsettings[0], g_dfu->total_bytes, dfu_buf, transferred); switch (rc) { case DFU_RET_ZLP: - g_dfu.total_bytes += transferred; - g_dfu.state = DFU_STATE_dfuDNLOAD_IDLE; + g_dfu->total_bytes += transferred; + g_dfu->state = DFU_STATE_dfuDNLOAD_IDLE; TerminateCtrlInWithNull(0,0,0,0); break; case DFU_RET_STALL: - g_dfu.state = DFU_STATE_dfuERROR; + g_dfu->state = DFU_STATE_dfuERROR; USBD_Stall(0); break; case DFU_RET_NOTHING: @@ -137,24 +138,24 @@ static int handle_dnload(uint16_t val, uint16_t len, int first) if (len > BOARD_DFU_PAGE_SIZE) { TRACE_ERROR("DFU length exceeds flash page size\n\r"); - g_dfu.state = DFU_STATE_dfuERROR; - g_dfu.status = DFU_STATUS_errADDRESS; + g_dfu->state = DFU_STATE_dfuERROR; + g_dfu->status = DFU_STATUS_errADDRESS; return DFU_RET_STALL; } if (len & 0x03) { TRACE_ERROR("DFU length not four-byte-aligned\n\r"); - g_dfu.state = DFU_STATE_dfuERROR; - g_dfu.status = DFU_STATUS_errADDRESS; + g_dfu->state = DFU_STATE_dfuERROR; + g_dfu->status = DFU_STATUS_errADDRESS; return DFU_RET_STALL; } if (first) - g_dfu.total_bytes = 0; + g_dfu->total_bytes = 0; if (len == 0) { TRACE_DEBUG("zero-size write -> MANIFEST_SYNC\n\r"); - g_dfu.state = DFU_STATE_dfuMANIFEST_SYNC; + g_dfu->state = DFU_STATE_dfuMANIFEST_SYNC; return DFU_RET_ZLP; } @@ -180,7 +181,7 @@ static void upload_cb(void *arg, unsigned char status, unsigned long int transfe return; } - g_dfu.total_bytes += transferred; + g_dfu->total_bytes += transferred; } static int handle_upload(uint16_t val, uint16_t len, int first) @@ -188,16 +189,16 @@ static int handle_upload(uint16_t val, uint16_t len, int first) int rc; if (first) - g_dfu.total_bytes = 0; + g_dfu->total_bytes = 0; if (len > BOARD_DFU_PAGE_SIZE) { TRACE_ERROR("DFU length exceeds flash page size\n\r"); - g_dfu.state = DFU_STATE_dfuERROR; - g_dfu.status = DFU_STATUS_errADDRESS; + g_dfu->state = DFU_STATE_dfuERROR; + g_dfu->status = DFU_STATUS_errADDRESS; return DFU_RET_STALL; } - rc = USBDFU_handle_upload(if_altsettings[0], g_dfu.total_bytes, dfu_buf, len); + rc = USBDFU_handle_upload(if_altsettings[0], g_dfu->total_bytes, dfu_buf, len); if (rc < 0) { TRACE_ERROR("application handle_upload() returned %d\n\r", rc); return DFU_RET_STALL; @@ -249,7 +250,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) USBDDriver_RequestHandler(&usbdDriver, request); } - switch (g_dfu.state) { + switch (g_dfu->state) { case DFU_STATE_appIDLE: case DFU_STATE_appDETACH: TRACE_ERROR("Invalid DFU State reached in DFU mode\r\n"); @@ -259,15 +260,15 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) switch (req) { case USB_REQ_DFU_DNLOAD: if (len == 0) { - g_dfu.state = DFU_STATE_dfuERROR; + g_dfu->state = DFU_STATE_dfuERROR; ret = DFU_RET_STALL; goto out; } - g_dfu.state = DFU_STATE_dfuDNLOAD_SYNC; + g_dfu->state = DFU_STATE_dfuDNLOAD_SYNC; ret = handle_dnload(val, len, 1); break; case USB_REQ_DFU_UPLOAD: - g_dfu.state = DFU_STATE_dfuUPLOAD_IDLE; + g_dfu->state = DFU_STATE_dfuUPLOAD_IDLE; handle_upload(val, len, 1); break; case USB_REQ_DFU_ABORT: @@ -281,7 +282,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) handle_getstate(); break; default: - g_dfu.state = DFU_STATE_dfuERROR; + g_dfu->state = DFU_STATE_dfuERROR; ret = DFU_RET_STALL; goto out; break; @@ -297,7 +298,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) handle_getstate(); break; default: - g_dfu.state = DFU_STATE_dfuERROR; + g_dfu->state = DFU_STATE_dfuERROR; ret = DFU_RET_STALL; goto out; } @@ -310,7 +311,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) handle_getstatus(); break; default: - g_dfu.state = DFU_STATE_dfuERROR; + g_dfu->state = DFU_STATE_dfuERROR; ret = DFU_RET_STALL; goto out; } @@ -318,11 +319,11 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) case DFU_STATE_dfuDNLOAD_IDLE: switch (req) { case USB_REQ_DFU_DNLOAD: - g_dfu.state = DFU_STATE_dfuDNLOAD_SYNC; + g_dfu->state = DFU_STATE_dfuDNLOAD_SYNC; ret = handle_dnload(val, len, 0); break; case USB_REQ_DFU_ABORT: - g_dfu.state = DFU_STATE_dfuIDLE; + g_dfu->state = DFU_STATE_dfuIDLE; ret = DFU_RET_ZLP; break; case USB_REQ_DFU_GETSTATUS: @@ -332,7 +333,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) handle_getstate(); break; default: - g_dfu.state = DFU_STATE_dfuERROR; + g_dfu->state = DFU_STATE_dfuERROR; ret = DFU_RET_STALL; break; } @@ -346,7 +347,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) handle_getstate(); break; default: - g_dfu.state = DFU_STATE_dfuERROR; + g_dfu->state = DFU_STATE_dfuERROR; ret = DFU_RET_STALL; break; } @@ -361,16 +362,16 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) * that we've already been through MANIFST in * the global variable 'past_manifest'. */ - //g_dfu.state = DFU_STATE_dfuMANIFEST_WAIT_RST; - g_dfu.state = DFU_STATE_dfuIDLE; - g_dfu.past_manifest = 1; + //g_dfu->state = DFU_STATE_dfuMANIFEST_WAIT_RST; + g_dfu->state = DFU_STATE_dfuIDLE; + g_dfu->past_manifest = 1; handle_getstatus(); break; case USB_REQ_DFU_GETSTATE: handle_getstate(); break; default: - g_dfu.state = DFU_STATE_dfuERROR; + g_dfu->state = DFU_STATE_dfuERROR; ret = DFU_RET_STALL; break; } @@ -384,10 +385,10 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) /* state transition if less data then requested */ rc = handle_upload(val, len, 0); if (rc >= 0 && rc < len) - g_dfu.state = DFU_STATE_dfuIDLE; + g_dfu->state = DFU_STATE_dfuIDLE; break; case USB_REQ_DFU_ABORT: - g_dfu.state = DFU_STATE_dfuIDLE; + g_dfu->state = DFU_STATE_dfuIDLE; /* no zlp? */ ret = DFU_RET_ZLP; break; @@ -398,7 +399,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) handle_getstate(); break; default: - g_dfu.state = DFU_STATE_dfuERROR; + g_dfu->state = DFU_STATE_dfuERROR; ret = DFU_RET_STALL; break; } @@ -412,13 +413,13 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request) handle_getstate(); break; case USB_REQ_DFU_CLRSTATUS: - g_dfu.state = DFU_STATE_dfuIDLE; - g_dfu.status = DFU_STATUS_OK; + g_dfu->state = DFU_STATE_dfuIDLE; + g_dfu->status = DFU_STATUS_OK; /* no zlp? */ ret = DFU_RET_ZLP; break; default: - g_dfu.state = DFU_STATE_dfuERROR; + g_dfu->state = DFU_STATE_dfuERROR; ret = DFU_RET_STALL; break; } @@ -442,7 +443,7 @@ out: void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors) { /* We already start in DFU idle mode */ - g_dfu.state = DFU_STATE_dfuIDLE; + g_dfu->state = DFU_STATE_dfuIDLE; USBDDriver_Initialize(&usbdDriver, pDescriptors, if_altsettings); USBD_Init(); diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c index 3bf7aa58..ba9665ee 100644 --- a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c +++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c @@ -35,9 +35,10 @@ #include #include +struct dfudata *g_dfu = (struct dfudata *) IRAM_ADDR; + /* FIXME: this was used for a special ELF section which then got called * by DFU code and Application code, across flash partitions */ -#define __dfudata #define __dfufunc static __dfufunc void handle_getstatus(void) @@ -46,8 +47,8 @@ static __dfufunc void handle_getstatus(void) static struct dfu_status dstat; /* send status response */ - dstat.bStatus = g_dfu.status; - dstat.bState = g_dfu.state; + dstat.bStatus = g_dfu->status; + dstat.bState = g_dfu->state; dstat.iString = 0; /* FIXME: set dstat.bwPollTimeout */ @@ -58,9 +59,9 @@ static __dfufunc void handle_getstatus(void) static void __dfufunc handle_getstate(void) { - uint8_t u8 = g_dfu.state; + uint8_t u8 = g_dfu->state; - TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu.state); + TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu->state); USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0); } @@ -118,7 +119,7 @@ void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request) USBDDriver_RequestHandler(usbdDriver, request); } - switch (g_dfu.state) { + switch (g_dfu->state) { case DFU_STATE_appIDLE: switch (req) { case USB_REQ_DFU_GETSTATUS: @@ -132,7 +133,7 @@ void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request) * return. The next USB reset in this state * will then trigger DFURT_SwitchToDFU() below */ TRACE_DEBUG("\r\n====dfu_detach\n\r"); - g_dfu.state = DFU_STATE_appDETACH; + g_dfu->state = DFU_STATE_appDETACH; ret = DFU_RET_ZLP; goto out; break; @@ -149,7 +150,7 @@ void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request) handle_getstate(); break; default: - g_dfu.state = DFU_STATE_appIDLE; + g_dfu->state = DFU_STATE_appIDLE; ret = DFU_RET_STALL; goto out; break; diff --git a/firmware/libboard/common/resources/sam3s4/dfu.ld b/firmware/libboard/common/resources/sam3s4/dfu.ld index c91c4c14..e56a435a 100644 --- a/firmware/libboard/common/resources/sam3s4/dfu.ld +++ b/firmware/libboard/common/resources/sam3s4/dfu.ld @@ -38,8 +38,10 @@ SEARCH_DIR(.) /* Memory Spaces Definitions */ MEMORY { + /* reserve the first 16k (= 0x4000) for the DFU bootloader */ rom (rx) : ORIGIN = 0x00404000, LENGTH = 0x0003c000 /* flash, 256K */ - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0000c000 /* sram, 48K */ + /* reserve the first 32 (= 0x20) bytes for the _g_dfu struct */ + ram (rwx) : ORIGIN = 0x20000020, LENGTH = 0x0000bfe0 /* sram, 48K */ } /* Section Definitions */