Skip to content

Commit f2c01ce

Browse files
committed
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 <[email protected]>
1 parent b7c8ce8 commit f2c01ce

File tree

4 files changed

+47
-7
lines changed

4 files changed

+47
-7
lines changed

config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@
4747
#define BOOTLOADER_WAIT 6
4848

4949
#define USER_CODE_RAM ((u32)0x20000C00)
50+
#define RAM_END ((u32)0x20005000)
5051
#define USER_CODE_FLASH ((u32)0x08005000)
52+
#define FLASH_END ((u32)0x08020000)
5153

5254
#define VEND_ID0 0xAF
5355
#define VEND_ID1 0x1E

dfu.c

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@
3636

3737
/* DFU globals */
3838
u32 userAppAddr = USER_CODE_RAM; /* default RAM user code location */
39+
u32 userAppEnd = RAM_END;
3940
DFUStatus dfuAppStatus; /* includes state */
4041
bool userFlash = FALSE;
4142
bool dfuBusy = FALSE;
4243

4344
u8 recvBuffer[wTransferSize];
4445
u32 userFirmwareLen = 0;
4546
u16 thisBlockLen = 0;
47+
u16 uploadBlockLen = 0;
4648

4749

4850
PLOT code_copy_lock;
@@ -58,6 +60,7 @@ void dfuInit(void) {
5860
userFirmwareLen = 0;
5961
thisBlockLen = 0;;
6062
userAppAddr = USER_CODE_RAM; /* default RAM user code location */
63+
userAppEnd = RAM_END;
6164
userFlash = FALSE;
6265
code_copy_lock = WAIT;
6366
dfuBusy = FALSE;
@@ -99,6 +102,19 @@ bool dfuUpdateByRequest(void) {
99102
}
100103
} else if (pInformation->USBbRequest == DFU_UPLOAD) {
101104
dfuAppStatus.bState = dfuUPLOAD_IDLE;
105+
/* record length of first block for calculating target
106+
address from wValue in consecutive blocks */
107+
uploadBlockLen = pInformation->USBwLengths.w;
108+
thisBlockLen = uploadBlockLen; /* for this first block as well */
109+
/* calculate where the data should be copied from */
110+
userFirmwareLen = uploadBlockLen * pInformation->USBwValue;
111+
if (pInformation->Current_AlternateSetting == 1) {
112+
userAppAddr = USER_CODE_FLASH;
113+
userAppEnd = FLASH_END;
114+
} else {
115+
userAppAddr = USER_CODE_RAM;
116+
userAppEnd = RAM_END;
117+
}
102118
} else if (pInformation->USBbRequest == DFU_ABORT) {
103119
dfuAppStatus.bState = dfuIDLE;
104120
dfuAppStatus.bStatus = OK; /* are we really ok? we were just aborted */
@@ -211,9 +227,26 @@ bool dfuUpdateByRequest(void) {
211227
/* device expecting further dfu_upload requests */
212228

213229
if (pInformation->USBbRequest == DFU_UPLOAD) {
214-
/* todo, add routine to wait for last block write to finish */
215-
dfuAppStatus.bState = dfuERROR;
216-
dfuAppStatus.bStatus = errSTALLEDPKT;
230+
if (pInformation->USBwLengths.w > 0) {
231+
/* check that this is not the last possible block */
232+
userFirmwareLen = uploadBlockLen * pInformation->USBwValue;
233+
if (userAppAddr + userFirmwareLen + uploadBlockLen <= userAppEnd) {
234+
thisBlockLen = uploadBlockLen;
235+
dfuAppStatus.bState = dfuUPLOAD_IDLE;
236+
} else {
237+
/* if above comparison was just equal, thisBlockLen becomes zero
238+
next time when USBWValue has been increased by one */
239+
thisBlockLen = userAppEnd - userAppAddr - userFirmwareLen;
240+
/* check for overflow due to USBwValue out of range */
241+
if (thisBlockLen >= pInformation->USBwLengths.w) {
242+
thisBlockLen = 0;
243+
}
244+
dfuAppStatus.bState = dfuIDLE;
245+
}
246+
} else {
247+
dfuAppStatus.bState = dfuERROR;
248+
dfuAppStatus.bStatus = errNOTDONE;
249+
}
217250
} else if (pInformation->USBbRequest == DFU_ABORT) {
218251
dfuAppStatus.bState = dfuIDLE;
219252
} else if (pInformation->USBbRequest == DFU_GETSTATUS) {
@@ -313,8 +346,12 @@ u8 *dfuCopyDNLOAD(u16 length) {
313346
}
314347

315348
u8 *dfuCopyUPLOAD(u16 length) {
316-
/* not implemented here nor supported by dfu-util */
317-
return NULL;
349+
if (length == 0) {
350+
pInformation->Ctrl_Info.Usb_wLength = thisBlockLen - pInformation->Ctrl_Info.Usb_wOffset;
351+
return NULL;
352+
} else {
353+
return((u8*) userAppAddr + userFirmwareLen + pInformation->Ctrl_Info.Usb_wOffset);
354+
}
318355
}
319356

320357
void dfuCopyBufferToExec() {

usb.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ RESULT usbDataSetup(u8 request) {
297297
break;
298298
case(DFU_UPLOAD):
299299
CopyRoutine = dfuCopyUPLOAD;
300+
break;
300301
default:
301302
/* leave copy routine null */
302303
break;

usb_descriptor.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ u8 u8_usbFunctionalDescriptor[9] = {
6666
/******************** DFU Functional Descriptor********************/
6767
0x09, /*blength = 7 Bytes*/
6868
0x21, /* DFU Functional Descriptor*/
69-
0x01, /*bmAttribute, can only download for now */
69+
0x03, /*bmAttributes, bitCanDnload | bitCanUpload */
7070
0xFF, /*DetachTimeOut= 255 ms*/
7171
0x00,
7272
(wTransferSize & 0x00FF),
@@ -122,7 +122,7 @@ u8 u8_usbConfigDescriptorDFU[36] = {
122122
/******************** DFU Functional Descriptor********************/
123123
0x09, /*blength = 7 Bytes*/
124124
0x21, /* DFU Functional Descriptor*/
125-
0x01, /*bmAttribute, can only download for now */
125+
0x03, /*bmAttributes, bitCanDnload | bitCanUpload */
126126
0xFF, /*DetachTimeOut= 255 ms*/
127127
0x00,
128128
(wTransferSize & 0x00FF),

0 commit comments

Comments
 (0)