1
0
mirror of git://projects.qi-hardware.com/ben-wpan.git synced 2024-11-22 07:25:19 +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 * fw/descr.c - USB descriptors
* *
* Written 2008-2011 by Werner Almesberger * Written 2008-2011, 2014 by Werner Almesberger
* Copyright 2008-2011 Werner Almesberger * Copyright 2008-2011, 2014 Werner Almesberger
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -100,5 +100,5 @@ const uint8_t config_descriptor[] = {
/* Interface #1 */ /* 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 * fw/flash.c - Board-specific flash functions
* *
* Written 2011, 2013 by Werner Almesberger * Written 2011, 2013, 2014 by Werner Almesberger
* Copyright 2011, 2013 Werner Almesberger * Copyright 2011, 2013, 2014 Werner Almesberger
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -24,19 +24,19 @@
static uint32_t payload; static uint32_t payload;
void flash_start(void) static void flash_start(void)
{ {
payload = 0; payload = 0;
} }
bool flash_can_write(uint16_t size) static bool flash_can_write(uint16_t size)
{ {
return payload+size <= BOOT_ADDR; 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; static uint8_t last;
const uint8_t *p; 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)) { if (payload & (SPM_PAGESIZE-1)) {
boot_page_write(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; uint16_t got = 0;
@ -83,3 +83,15 @@ uint16_t flash_read(uint8_t *buf, uint16_t size)
} }
return got; 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(...) #define error(...)
#ifndef DFU_ALT_SETTINGS
#define DFU_ALT_SETTINGS 1
#endif
const uint8_t device_descriptor[] = { const uint8_t device_descriptor[] = {
18, /* bLength */ 18, /* bLength */
USB_DT_DEVICE, /* bDescriptorType */ USB_DT_DEVICE, /* bDescriptorType */
@ -67,7 +72,7 @@ const uint8_t device_descriptor[] = {
const uint8_t config_descriptor[] = { const uint8_t config_descriptor[] = {
9, /* bLength */ 9, /* bLength */
USB_DT_CONFIG, /* bDescriptorType */ USB_DT_CONFIG, /* bDescriptorType */
LE(9+9), /* wTotalLength */ LE(9+9*DFU_ALT_SETTINGS), /* wTotalLength */
1, /* bNumInterfaces */ 1, /* bNumInterfaces */
1, /* bConfigurationValue (> 0 !) */ 1, /* bConfigurationValue (> 0 !) */
0, /* iConfiguration */ 0, /* iConfiguration */
@ -77,7 +82,13 @@ const uint8_t config_descriptor[] = {
/* Interface #0 */ /* 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; 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; static uint16_t size;
if (!flash_can_write(length)) { if (!dfu_flash_ops->can_write(length)) {
dfu.state = dfuERROR; dfu.state = dfuERROR;
dfu.status = errADDRESS; dfu.status = errADDRESS;
return 0; return 0;
@ -125,7 +136,7 @@ static bool block_transmit(uint16_t length)
dfu.status = errUNKNOWN; dfu.status = errUNKNOWN;
return 1; return 1;
} }
got = flash_read(buf, length); got = dfu_flash_ops->read(buf, length);
if (got < length) { if (got < length) {
length = got; length = got;
dfu.state = dfuIDLE; dfu.state = dfuIDLE;
@ -152,7 +163,7 @@ static bool my_setup(const struct setup_request *setup)
debug("DFU_DNLOAD\n"); debug("DFU_DNLOAD\n");
if (dfu.state == dfuIDLE) { if (dfu.state == dfuIDLE) {
next_block = setup->wValue; next_block = setup->wValue;
flash_start(); dfu_flash_ops->start();
} }
else if (dfu.state != dfuDNLOAD_IDLE) { else if (dfu.state != dfuDNLOAD_IDLE) {
error("bad state\n"); error("bad state\n");
@ -171,7 +182,7 @@ static bool my_setup(const struct setup_request *setup)
} }
if (!setup->wLength) { if (!setup->wLength) {
debug("DONE\n"); debug("DONE\n");
flash_end_write(); dfu_flash_ops->end_write();
dfu.state = dfuIDLE; dfu.state = dfuIDLE;
did_download = 1; did_download = 1;
return 1; return 1;
@ -184,7 +195,7 @@ static bool my_setup(const struct setup_request *setup)
debug("DFU_UPLOAD\n"); debug("DFU_UPLOAD\n");
if (dfu.state == dfuIDLE) { if (dfu.state == dfuIDLE) {
next_block = setup->wValue; next_block = setup->wValue;
flash_start(); dfu_flash_ops->start();
} }
else if (dfu.state != dfuUPLOAD_IDLE) else if (dfu.state != dfuUPLOAD_IDLE)
return 0; return 0;

View File

@ -1,8 +1,8 @@
/* /*
* boot/dfu.h - DFU protocol constants and data structures * boot/dfu.h - DFU protocol constants and data structures
* *
* Written 2008, 2011, 2013 by Werner Almesberger * Written 2008, 2011, 2013, 2014 by Werner Almesberger
* Copyright 2008, 2011, 2013 Werner Almesberger * Copyright 2008, 2011, 2013, 2014 Werner Almesberger
* *
* This program is free software; you can redistribute it and/or modify * 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 * 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 */ \ 9, /* bLength */ \
USB_DT_INTERFACE, /* bDescriptorType */ \ USB_DT_INTERFACE, /* bDescriptorType */ \
(itf), /* bInterfaceNumber */ \ (itf), /* bInterfaceNumber */ \
0, /* bAlternateSetting */ \ (alt), /* bAlternateSetting */ \
0, /* bNumEndpoints */ \ 0, /* bNumEndpoints */ \
0xfe, /* bInterfaceClass (application specific) */ \ 0xfe, /* bInterfaceClass (application specific) */ \
0x01, /* bInterfaceSubClass (device fw upgrade) */ \ 0x01, /* bInterfaceSubClass (device fw upgrade) */ \
@ -98,15 +98,18 @@ struct dfu {
0, /* iInterface */ 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 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_setup_common(const struct setup_request *setup);
bool dfu_my_descr(uint8_t type, uint8_t index, const uint8_t **reply, bool dfu_my_descr(uint8_t type, uint8_t index, const uint8_t **reply,
uint8_t *size); uint8_t *size);