1
0
mirror of git://projects.qi-hardware.com/ben-wpan.git synced 2024-12-22 19:01:10 +02:00

atusb/fw/: DFU: support multiple sets of flash operations; support multiple alt settings

This commit is contained in:
Werner Almesberger 2014-03-24 17:18:02 -03:00
parent 8b0859486e
commit 8f2f13c30a
4 changed files with 54 additions and 28 deletions

View File

@ -1,8 +1,8 @@
/*
* fw/descr.c - USB descriptors
*
* Written 2008-2011 by Werner Almesberger
* Copyright 2008-2011 Werner Almesberger
* Written 2008-2011, 2014 by Werner Almesberger
* Copyright 2008-2011, 2014 Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -100,5 +100,5 @@ const uint8_t config_descriptor[] = {
/* Interface #1 */
DFU_ITF_DESCR(1, dfu_proto_runtime)
DFU_ITF_DESCR(1, 0, dfu_proto_runtime)
};

View File

@ -1,8 +1,8 @@
/*
* fw/flash.c - Board-specific flash functions
*
* Written 2011, 2013 by Werner Almesberger
* Copyright 2011, 2013 Werner Almesberger
* Written 2011, 2013, 2014 by Werner Almesberger
* Copyright 2011, 2013, 2014 Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -24,19 +24,19 @@
static uint32_t payload;
void flash_start(void)
static void flash_start(void)
{
payload = 0;
}
bool flash_can_write(uint16_t size)
static bool flash_can_write(uint16_t size)
{
return payload+size <= BOOT_ADDR;
}
void flash_write(const uint8_t *buf, uint16_t size)
static void flash_write(const uint8_t *buf, uint16_t size)
{
static uint8_t last;
const uint8_t *p;
@ -61,7 +61,7 @@ void flash_write(const uint8_t *buf, uint16_t size)
}
void flash_end_write(void)
static void flash_end_write(void)
{
if (payload & (SPM_PAGESIZE-1)) {
boot_page_write(payload & ~(SPM_PAGESIZE-1));
@ -71,7 +71,7 @@ void flash_end_write(void)
}
uint16_t flash_read(uint8_t *buf, uint16_t size)
static uint16_t flash_read(uint8_t *buf, uint16_t size)
{
uint16_t got = 0;
@ -83,3 +83,15 @@ uint16_t flash_read(uint8_t *buf, uint16_t size)
}
return got;
}
static struct dfu_flash_ops flash_ops = {
.start = flash_start,
.can_write = flash_can_write,
.write = flash_write,
.end_write = flash_end_write,
.read = flash_read,
};
struct dfu_flash_ops *dfu_flash_ops = &flash_ops;

View File

@ -42,6 +42,11 @@
#define error(...)
#ifndef DFU_ALT_SETTINGS
#define DFU_ALT_SETTINGS 1
#endif
const uint8_t device_descriptor[] = {
18, /* bLength */
USB_DT_DEVICE, /* bDescriptorType */
@ -67,7 +72,7 @@ const uint8_t device_descriptor[] = {
const uint8_t config_descriptor[] = {
9, /* bLength */
USB_DT_CONFIG, /* bDescriptorType */
LE(9+9), /* wTotalLength */
LE(9+9*DFU_ALT_SETTINGS), /* wTotalLength */
1, /* bNumInterfaces */
1, /* bConfigurationValue (> 0 !) */
0, /* iConfiguration */
@ -77,7 +82,13 @@ const uint8_t config_descriptor[] = {
/* Interface #0 */
DFU_ITF_DESCR(0, dfu_proto_dfu)
DFU_ITF_DESCR(0, 0, dfu_proto_dfu)
#if DFU_ALT_SETTINGS >= 1
DFU_ITF_DESCR(0, 1, dfu_proto_dfu)
#endif
#if DFU_ALT_SETTINGS >= 2
DFU_ITF_DESCR(0, 2, dfu_proto_dfu)
#endif
};
@ -92,7 +103,7 @@ static void block_write(void *user)
{
uint16_t *size = user;
flash_write(buf, *size);
dfu_flash_ops->write(buf, *size);
}
@ -100,7 +111,7 @@ static bool block_receive(uint16_t length)
{
static uint16_t size;
if (!flash_can_write(length)) {
if (!dfu_flash_ops->can_write(length)) {
dfu.state = dfuERROR;
dfu.status = errADDRESS;
return 0;
@ -125,7 +136,7 @@ static bool block_transmit(uint16_t length)
dfu.status = errUNKNOWN;
return 1;
}
got = flash_read(buf, length);
got = dfu_flash_ops->read(buf, length);
if (got < length) {
length = got;
dfu.state = dfuIDLE;
@ -152,7 +163,7 @@ static bool my_setup(const struct setup_request *setup)
debug("DFU_DNLOAD\n");
if (dfu.state == dfuIDLE) {
next_block = setup->wValue;
flash_start();
dfu_flash_ops->start();
}
else if (dfu.state != dfuDNLOAD_IDLE) {
error("bad state\n");
@ -171,7 +182,7 @@ static bool my_setup(const struct setup_request *setup)
}
if (!setup->wLength) {
debug("DONE\n");
flash_end_write();
dfu_flash_ops->end_write();
dfu.state = dfuIDLE;
did_download = 1;
return 1;
@ -184,7 +195,7 @@ static bool my_setup(const struct setup_request *setup)
debug("DFU_UPLOAD\n");
if (dfu.state == dfuIDLE) {
next_block = setup->wValue;
flash_start();
dfu_flash_ops->start();
}
else if (dfu.state != dfuUPLOAD_IDLE)
return 0;

View File

@ -1,8 +1,8 @@
/*
* boot/dfu.h - DFU protocol constants and data structures
*
* Written 2008, 2011, 2013 by Werner Almesberger
* Copyright 2008, 2011, 2013 Werner Almesberger
* Written 2008, 2011, 2013, 2014 by Werner Almesberger
* Copyright 2008, 2011, 2013, 2014 Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -86,11 +86,11 @@ struct dfu {
};
#define DFU_ITF_DESCR(itf, proto) \
#define DFU_ITF_DESCR(itf, alt, proto) \
9, /* bLength */ \
USB_DT_INTERFACE, /* bDescriptorType */ \
(itf), /* bInterfaceNumber */ \
0, /* bAlternateSetting */ \
(alt), /* bAlternateSetting */ \
0, /* bNumEndpoints */ \
0xfe, /* bInterfaceClass (application specific) */ \
0x01, /* bInterfaceSubClass (device fw upgrade) */ \
@ -98,15 +98,18 @@ struct dfu {
0, /* iInterface */
struct dfu_flash_ops {
void (*start)(void);
bool (*can_write)(uint16_t size);
void (*write)(const uint8_t *buf, uint16_t size);
void (*end_write)(void);
uint16_t (*read)(uint8_t *buf, uint16_t size);
};
extern struct dfu dfu;
extern struct dfu_flash_ops *dfu_flash_ops;
void flash_start(void);
bool flash_can_write(uint16_t size);
void flash_write(const uint8_t *buf, uint16_t size);
void flash_end_write(void);
uint16_t flash_read(uint8_t *buf, uint16_t size);
bool dfu_setup_common(const struct setup_request *setup);
bool dfu_my_descr(uint8_t type, uint8_t index, const uint8_t **reply,
uint8_t *size);