This second patch is the DFU_UPLOAD support (also mailed to info@).
From f2c01ce01e5dca4f0be3cf0e71bedcb888b7ac06 Mon Sep 17 00:00:00 2001
From: Tormod Volden <debian.tormod@gmail.com>
Date: Sun, 28 Oct 2012 02:24:29 +0200
Subject: [PATCH 2/2] Add DFU_UPLOAD support
The DFU_UPLOAD support allows copying the contents of the flash or RAM
memory of the Maple to the computer.
Note that we use the wValue (BlockNum in the DFU standard) to calculate
the target address. We therefore rely on the host program (for instance
dfu-util) to set (increase) wValue for each block.
This use of wValue is not mandated by the DFU standard, which only says
wValue should be incremented by the host "to provide useful context" to
the device, but this implementation allows random access of memory
locations.
On the other hand the DFU_DNLOAD code does not make use of BlockNum but
simply increases its memory pointer for each block received. Maybe this
was done because reading out wValue was broken due to endian mix-up?
Signed-off-by: Tormod Volden <debian.tormod@gmail.com>
---
Hi,
This will permit taking backups of existing flash contents, and verifying
proper flashing.
The RAM uploading can also be used for debugging: If you reset into the
bootloader, the RAM contents (above 0x20000c00) is preserved, and you
can upload it to the computer for analysis.
I have not tested it on a real Maple, only on a development board with a
port of the maple-mini bootloader.
I have noticed that dfu-util receives a pipe error on the last
libusb_control_msg() call, but the transfers seems fine nevertheless so I
am not looking into it at this time.
Best regards,
Tormod
config.h | 2 ++
dfu.c | 47 ++++++++++++++++++++++++++++++++++++++++++-----
usb.c | 1 +
usb_descriptor.c | 4 ++--
4 files changed, 47 insertions(+), 7 deletions(-)
diff --git a/config.h b/config.h
index d2d980c..def4f99 100644
--- a/config.h
+++ b/config.h
@@ -47,7 +47,9 @@
#define BOOTLOADER_WAIT 6
#define USER_CODE_RAM ((u32)0x20000C00)
+#define RAM_END ((u32)0x20005000)
#define USER_CODE_FLASH ((u32)0x08005000)
+#define FLASH_END ((u32)0x08020000)
#define VEND_ID0 0xAF
#define VEND_ID1 0x1E
diff --git a/dfu.c b/dfu.c
index cf05f3b..d5ddad1 100644
--- a/dfu.c
+++ b/dfu.c
@@ -36,6 +36,7 @@
/* DFU globals */
u32 userAppAddr = USER_CODE_RAM; /* default RAM user code location */
+u32 userAppEnd = RAM_END;
DFUStatus dfuAppStatus; /* includes state */
bool userFlash = FALSE;
bool dfuBusy = FALSE;
@@ -43,6 +44,7 @@ bool dfuBusy = FALSE;
u8 recvBuffer[wTransferSize];
u32 userFirmwareLen = 0;
u16 thisBlockLen = 0;
+u16 uploadBlockLen = 0;
PLOT code_copy_lock;
@@ -58,6 +60,7 @@ void dfuInit(void) {
userFirmwareLen = 0;
thisBlockLen = 0;;
userAppAddr = USER_CODE_RAM; /* default RAM user code location */
+ userAppEnd = RAM_END;
userFlash = FALSE;
code_copy_lock = WAIT;
dfuBusy = FALSE;
@@ -99,6 +102,19 @@ bool dfuUpdateByRequest(void) {
}
} else if (pInformation->USBbRequest == DFU_UPLOAD) {
dfuAppStatus.bState = dfuUPLOAD_IDLE;
+ /* record length of first block for calculating target
+ address from wValue in consecutive blocks */
+ uploadBlockLen = pInformation->USBwLengths.w;
+ thisBlockLen = uploadBlockLen; /* for this first block as well */
+ /* calculate where the data should be copied from */
+ userFirmwareLen = uploadBlockLen * pInformation->USBwValue;
+ if (pInformation->Current_AlternateSetting == 1) {
+ userAppAddr = USER_CODE_FLASH;
+ userAppEnd = FLASH_END;
+ } else {
+ userAppAddr = USER_CODE_RAM;
+ userAppEnd = RAM_END;
+ }
} else if (pInformation->USBbRequest == DFU_ABORT) {
dfuAppStatus.bState = dfuIDLE;
dfuAppStatus.bStatus = OK; /* are we really ok? we were just aborted */
@@ -211,9 +227,26 @@ bool dfuUpdateByRequest(void) {
/* device expecting further dfu_upload requests */
if (pInformation->USBbRequest == DFU_UPLOAD) {
- /* todo, add routine to wait for last block write to finish */
- dfuAppStatus.bState = dfuERROR;
- dfuAppStatus.bStatus = errSTALLEDPKT;
+ if (pInformation->USBwLengths.w > 0) {
+ /* check that this is not the last possible block */
+ userFirmwareLen = uploadBlockLen * pInformation->USBwValue;
+ if (userAppAddr + userFirmwareLen + uploadBlockLen <= userAppEnd) {
+ thisBlockLen = uploadBlockLen;
+ dfuAppStatus.bState = dfuUPLOAD_IDLE;
+ } else {
+ /* if above comparison was just equal, thisBlockLen becomes zero
+ next time when USBWValue has been increased by one */
+ thisBlockLen = userAppEnd - userAppAddr - userFirmwareLen;
+ /* check for overflow due to USBwValue out of range */
+ if (thisBlockLen >= pInformation->USBwLengths.w) {
+ thisBlockLen = 0;
+ }
+ dfuAppStatus.bState = dfuIDLE;
+ }
+ } else {
+ dfuAppStatus.bState = dfuERROR;
+ dfuAppStatus.bStatus = errNOTDONE;
+ }
} else if (pInformation->USBbRequest == DFU_ABORT) {
dfuAppStatus.bState = dfuIDLE;
} else if (pInformation->USBbRequest == DFU_GETSTATUS) {
@@ -313,8 +346,12 @@ u8 *dfuCopyDNLOAD(u16 length) {
}
u8 *dfuCopyUPLOAD(u16 length) {
- /* not implemented here nor supported by dfu-util */
- return NULL;
+ if (length == 0) {
+ pInformation->Ctrl_Info.Usb_wLength = thisBlockLen - pInformation->Ctrl_Info.Usb_wOffset;
+ return NULL;
+ } else {
+ return((u8*) userAppAddr + userFirmwareLen + pInformation->Ctrl_Info.Usb_wOffset);
+ }
}
void dfuCopyBufferToExec() {
diff --git a/usb.c b/usb.c
index 5a5238b..b6d2a67 100644
--- a/usb.c
+++ b/usb.c
@@ -297,6 +297,7 @@ RESULT usbDataSetup(u8 request) {
break;
case(DFU_UPLOAD):
CopyRoutine = dfuCopyUPLOAD;
+ break;
default:
/* leave copy routine null */
break;
diff --git a/usb_descriptor.c b/usb_descriptor.c
index b9fcc09..3a0c7f0 100644
--- a/usb_descriptor.c
+++ b/usb_descriptor.c
@@ -66,7 +66,7 @@ u8 u8_usbFunctionalDescriptor[9] = {
/******************** DFU Functional Descriptor********************/
0x09, /*blength = 7 Bytes*/
0x21, /* DFU Functional Descriptor*/
- 0x01, /*bmAttribute, can only download for now */
+ 0x03, /*bmAttributes, bitCanDnload | bitCanUpload */
0xFF, /*DetachTimeOut= 255 ms*/
0x00,
(wTransferSize & 0x00FF),
@@ -122,7 +122,7 @@ u8 u8_usbConfigDescriptorDFU[36] = {
/******************** DFU Functional Descriptor********************/
0x09, /*blength = 7 Bytes*/
0x21, /* DFU Functional Descriptor*/
- 0x01, /*bmAttribute, can only download for now */
+ 0x03, /*bmAttributes, bitCanDnload | bitCanUpload */
0xFF, /*DetachTimeOut= 255 ms*/
0x00,
(wTransferSize & 0x00FF),
--
1.7.9.5