DFU: add actual upload and download support

This commit is contained in:
Harald Welte 2012-01-08 13:04:30 +01:00
parent be10ca901e
commit f2be0ee6d8
1 changed files with 94 additions and 7 deletions

View File

@ -52,12 +52,16 @@
#include <utility/trace.h>
#include <utility/led.h>
#include <memories/flash/flashd.h>
#include <usb/device/core/USBD.h>
#include <usb/device/core/USBDDriver.h>
#include <usb/device/dfu/dfu.h>
#include "dfu_desc.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
/*----------------------------------------------------------------------------
* Definitions
*----------------------------------------------------------------------------*/
@ -105,6 +109,14 @@ static volatile uint8_t isRecActive = 0;
/** VBus pin instance. */
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.
*/
@ -272,27 +284,99 @@ void USBDDriverCallbacks_InterfaceSettingChanged(unsigned char interface,
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 */
int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
uint8_t *buf, unsigned int req_len)
{
TRACE_INFO("DFU: handle_upload(%u, %u, %u)\n\r", altif, offset, req_len);
if (upl_first) {
upl_first = 0;
return req_len;
}
struct flash_part *part;
void *end, *addr;
uint32_t real_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 */
int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
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);
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;
}
@ -300,6 +384,9 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
void dfu_drv_updstatus(void)
{
TRACE_INFO("DFU: updstatus()\n\r");
if (dfu.state == DFU_STATE_dfuMANIFEST_SYNC)
dfu.state = DFU_STATE_dfuMANIFEST;
}
/*----------------------------------------------------------------------------