DFU: add actual upload and download support
This commit is contained in:
parent
be10ca901e
commit
f2be0ee6d8
|
@ -52,12 +52,16 @@
|
||||||
#include <utility/trace.h>
|
#include <utility/trace.h>
|
||||||
#include <utility/led.h>
|
#include <utility/led.h>
|
||||||
|
|
||||||
|
#include <memories/flash/flashd.h>
|
||||||
|
|
||||||
#include <usb/device/core/USBD.h>
|
#include <usb/device/core/USBD.h>
|
||||||
#include <usb/device/core/USBDDriver.h>
|
#include <usb/device/core/USBDDriver.h>
|
||||||
#include <usb/device/dfu/dfu.h>
|
#include <usb/device/dfu/dfu.h>
|
||||||
|
|
||||||
#include "dfu_desc.h"
|
#include "dfu_desc.h"
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
* Definitions
|
* Definitions
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
@ -105,6 +109,14 @@ static volatile uint8_t isRecActive = 0;
|
||||||
/** VBus pin instance. */
|
/** VBus pin instance. */
|
||||||
static const Pin pinVbus = PIN_USB_VBUS;
|
static const Pin pinVbus = PIN_USB_VBUS;
|
||||||
|
|
||||||
|
/* this needs to be in sync with usb-strings.txt !! */
|
||||||
|
enum dfu_altif {
|
||||||
|
ALTIF_APP,
|
||||||
|
ALTIF_BOOT,
|
||||||
|
ALTIF_RAM,
|
||||||
|
ALTIF_FPGA
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles interrupts coming from PIO controllers.
|
* Handles interrupts coming from PIO controllers.
|
||||||
*/
|
*/
|
||||||
|
@ -272,27 +284,99 @@ void USBDDriverCallbacks_InterfaceSettingChanged(unsigned char interface,
|
||||||
TRACE_INFO("DFU: IfSettingChgd(if=%u, alt=%u)\n\r", interface, setting);
|
TRACE_INFO("DFU: IfSettingChgd(if=%u, alt=%u)\n\r", interface, setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int upl_first = 1;
|
#define BOOT_FLASH_SIZE (16 * 1024)
|
||||||
|
|
||||||
|
struct flash_part {
|
||||||
|
void *base_addr;
|
||||||
|
uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct flash_part flash_parts[] = {
|
||||||
|
[ALTIF_BOOT] = {
|
||||||
|
.base_addr = AT91C_IFLASH0,
|
||||||
|
.size = BOOT_FLASH_SIZE,
|
||||||
|
},
|
||||||
|
[ALTIF_APP] = {
|
||||||
|
.base_addr = (AT91C_IFLASH + BOOT_FLASH_SIZE),
|
||||||
|
.size = (AT91C_IFLASH0_SIZE - BOOT_FLASH_SIZE),
|
||||||
|
},
|
||||||
|
[ALTIF_RAM] = {
|
||||||
|
.base_addr = AT91C_IRAM,
|
||||||
|
.size = AT91C_IRAM_SIZE,
|
||||||
|
},
|
||||||
|
[ALTIF_FPGA] = {
|
||||||
|
.base_addr = AT91C_IFLASH1,
|
||||||
|
.size = AT91C_IFLASH1_SIZE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/* DFU callback */
|
/* DFU callback */
|
||||||
int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
|
int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
|
||||||
uint8_t *buf, unsigned int req_len)
|
uint8_t *buf, unsigned int req_len)
|
||||||
{
|
{
|
||||||
TRACE_INFO("DFU: handle_upload(%u, %u, %u)\n\r", altif, offset, req_len);
|
struct flash_part *part;
|
||||||
if (upl_first) {
|
void *end, *addr;
|
||||||
upl_first = 0;
|
uint32_t real_len;
|
||||||
return req_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 4;
|
TRACE_INFO("DFU: handle_upload(%u, %u, %u)\n\r", altif, offset, req_len);
|
||||||
|
|
||||||
|
if (altif > ARRAY_SIZE(flash_parts))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
part = &flash_parts[altif];
|
||||||
|
|
||||||
|
addr = part->base_addr + offset;
|
||||||
|
end = part->base_addr + part->size;
|
||||||
|
|
||||||
|
real_len = end - addr;
|
||||||
|
if (req_len < real_len)
|
||||||
|
real_len = req_len;
|
||||||
|
|
||||||
|
memcpy(buf, addr, real_len);
|
||||||
|
|
||||||
|
return real_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DFU callback */
|
/* DFU callback */
|
||||||
int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
|
int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
|
||||||
uint8_t *buf, unsigned int len)
|
uint8_t *buf, unsigned int len)
|
||||||
{
|
{
|
||||||
|
struct flash_part *part;
|
||||||
|
void *end, *addr;
|
||||||
|
int rc;
|
||||||
|
|
||||||
TRACE_INFO("DFU: handle_dnload(%u, %u, %u)\n\r", altif, offset, len);
|
TRACE_INFO("DFU: handle_dnload(%u, %u, %u)\n\r", altif, offset, len);
|
||||||
|
|
||||||
|
if (altif > ARRAY_SIZE(flash_parts))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
part = &flash_parts[altif];
|
||||||
|
|
||||||
|
addr = part->base_addr + offset;
|
||||||
|
end = part->base_addr + part->size;
|
||||||
|
|
||||||
|
if (addr + len > end) {
|
||||||
|
TRACE_ERROR("Cannot write beyond end of DFU partition %u\n\r", altif);
|
||||||
|
dfu.status = DFU_STATUS_errADDRESS;
|
||||||
|
return DFU_RET_STALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (altif) {
|
||||||
|
case ALTIF_APP:
|
||||||
|
case ALTIF_FPGA:
|
||||||
|
rc = FLASHD_Write(addr, buf, len);
|
||||||
|
if (rc != 0) {
|
||||||
|
TRACE_ERROR("Error during write of DFU partition %u\n\r", altif);
|
||||||
|
dfu.status = DFU_STATUS_errPROG;
|
||||||
|
return DFU_RET_STALL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TRACE_WARNING("Write to DFU partition %u not implemented\n\r", altif);
|
||||||
|
dfu.status = DFU_STATUS_errTARGET;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return DFU_RET_ZLP;
|
return DFU_RET_ZLP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,6 +384,9 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
|
||||||
void dfu_drv_updstatus(void)
|
void dfu_drv_updstatus(void)
|
||||||
{
|
{
|
||||||
TRACE_INFO("DFU: updstatus()\n\r");
|
TRACE_INFO("DFU: updstatus()\n\r");
|
||||||
|
|
||||||
|
if (dfu.state == DFU_STATE_dfuMANIFEST_SYNC)
|
||||||
|
dfu.state = DFU_STATE_dfuMANIFEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue