mirror of
git://projects.qi-hardware.com/ben-wpan.git
synced 2024-12-23 19:52:04 +02:00
atusb/fw/usb/: adapted DFU engine to current stack and abstracted Flash ops
- dfu.c: updated includes - dfu.c (device_descriptor): renamed USB IDs from USB_VENDOR/PRODUCT to DFU_USB_VENDOR/PRODUCT to allow differentiation - dfu.c: changed all __bit to "int" - dfu.c: removed all __xdata and __reentrant - dfu.c: changed "ep0" to "eps[0]" - dfu.c (payload, flash_erase_page, flash_write_byte, block_write, block_receive, block_transmit, my_setup): abstracted Flash interface and removed target-specific operations - dfu.h: added prototypes for target-specific Flash operations - dfu,c (my_setup, my_descr): removed SDCC-specific hacks - dfu.c (my_reset): commented out - did we actually use this ?
This commit is contained in:
parent
fb2204ad84
commit
f91738c306
@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* boot/dfu.c - DFU protocol engine
|
* boot/dfu.c - DFU protocol engine
|
||||||
*
|
*
|
||||||
* Written 2008-2010 by Werner Almesberger
|
* Written 2008-2011 by Werner Almesberger
|
||||||
* Copyright 2008-2010 Werner Almesberger
|
* Copyright 2008-2011 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
|
||||||
@ -27,20 +27,18 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "regs.h"
|
|
||||||
#include "uart.h"
|
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "dfu.h"
|
#include "dfu.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "../board.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef NULL
|
#ifndef NULL
|
||||||
#define NULL 0
|
#define NULL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define debug(...)
|
||||||
#define PAYLOAD_END (PAYLOAD_START+PAYLOAD_SIZE)
|
#define error(...)
|
||||||
|
|
||||||
|
|
||||||
const uint8_t device_descriptor[] = {
|
const uint8_t device_descriptor[] = {
|
||||||
@ -51,8 +49,8 @@ const uint8_t device_descriptor[] = {
|
|||||||
0x00, /* bDeviceSubClass (per interface) */
|
0x00, /* bDeviceSubClass (per interface) */
|
||||||
0x00, /* bDeviceProtocol (per interface) */
|
0x00, /* bDeviceProtocol (per interface) */
|
||||||
EP0_SIZE, /* bMaxPacketSize */
|
EP0_SIZE, /* bMaxPacketSize */
|
||||||
LE(USB_VENDOR), /* idVendor */
|
LE(DFU_USB_VENDOR), /* idVendor */
|
||||||
LE(USB_PRODUCT), /* idProduct */
|
LE(DFU_USB_PRODUCT), /* idProduct */
|
||||||
LE(0x0001), /* bcdDevice */
|
LE(0x0001), /* bcdDevice */
|
||||||
0, /* iManufacturer */
|
0, /* iManufacturer */
|
||||||
0, /* iProduct */
|
0, /* iProduct */
|
||||||
@ -105,55 +103,25 @@ struct dfu dfu = {
|
|||||||
|
|
||||||
|
|
||||||
static uint16_t next_block = 0;
|
static uint16_t next_block = 0;
|
||||||
static uint16_t payload;
|
static int did_download;
|
||||||
static __bit did_download;
|
|
||||||
|
|
||||||
|
|
||||||
static __xdata uint8_t buf[EP0_SIZE];
|
static uint8_t buf[EP0_SIZE];
|
||||||
|
|
||||||
|
|
||||||
static void flash_erase_page(uint16_t addr)
|
|
||||||
{
|
|
||||||
FLKEY = 0xa5;
|
|
||||||
FLKEY = 0xf1;
|
|
||||||
PSCTL |= PSEE;
|
|
||||||
PSCTL |= PSWE;
|
|
||||||
*(__xdata uint8_t *) addr = 0;
|
|
||||||
PSCTL &= ~PSWE;
|
|
||||||
PSCTL &= ~PSEE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void flash_write_byte(uint16_t addr, uint8_t value)
|
|
||||||
{
|
|
||||||
FLKEY = 0xa5;
|
|
||||||
FLKEY = 0xf1;
|
|
||||||
PSCTL |= PSWE;
|
|
||||||
PSCTL &= ~PSEE;
|
|
||||||
*(__xdata uint8_t *) addr = value;
|
|
||||||
PSCTL &= ~PSWE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void block_write(void *user)
|
static void block_write(void *user)
|
||||||
{
|
{
|
||||||
uint16_t *size = user;
|
uint16_t *size = user;
|
||||||
uint8_t *p;
|
|
||||||
|
|
||||||
for (p = buf; p != buf+*size; p++) {
|
flash_write(buf, *size);
|
||||||
if (!(payload & 511))
|
|
||||||
flash_erase_page(payload);
|
|
||||||
flash_write_byte(payload, *p);
|
|
||||||
payload++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static __bit block_receive(uint16_t length)
|
static int block_receive(uint16_t length)
|
||||||
{
|
{
|
||||||
static uint16_t size;
|
static uint16_t size;
|
||||||
|
|
||||||
if (payload < PAYLOAD_START || payload+length > PAYLOAD_END) {
|
if (!flash_can_write(length)) {
|
||||||
dfu.state = dfuERROR;
|
dfu.state = dfuERROR;
|
||||||
dfu.status = errADDRESS;
|
dfu.status = errADDRESS;
|
||||||
return 0;
|
return 0;
|
||||||
@ -164,39 +132,33 @@ static __bit block_receive(uint16_t length)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size = length;
|
size = length;
|
||||||
usb_recv(&ep0, buf, size, block_write, &size);
|
usb_recv(&eps[0], buf, size, block_write, &size);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static __bit block_transmit(uint16_t length)
|
static int block_transmit(uint16_t length)
|
||||||
{
|
{
|
||||||
uint16_t left;
|
uint16_t got;
|
||||||
|
|
||||||
if (payload < PAYLOAD_START || payload > PAYLOAD_END) {
|
|
||||||
dfu.state = dfuERROR;
|
|
||||||
dfu.status = errADDRESS;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (length > EP0_SIZE) {
|
if (length > EP0_SIZE) {
|
||||||
dfu.state = dfuERROR;
|
dfu.state = dfuERROR;
|
||||||
dfu.status = errUNKNOWN;
|
dfu.status = errUNKNOWN;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
left = PAYLOAD_END-payload;
|
got = flash_read(buf, length);
|
||||||
if (left < length) {
|
if (got < length) {
|
||||||
length = left;
|
length = got;
|
||||||
dfu.state = dfuIDLE;
|
dfu.state = dfuIDLE;
|
||||||
}
|
}
|
||||||
usb_send(&ep0, (__code uint8_t *) payload, length, NULL, NULL);
|
usb_send(&eps[0], buf, length, NULL, NULL);
|
||||||
payload += length;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static __bit my_setup(struct setup_request *setup) __reentrant
|
static int my_setup(const struct setup_request *setup)
|
||||||
{
|
{
|
||||||
__bit ok;
|
int ok;
|
||||||
|
|
||||||
switch (setup->bmRequestType | setup->bRequest << 8) {
|
switch (setup->bmRequestType | setup->bRequest << 8) {
|
||||||
case DFU_TO_DEV(DFU_DETACH):
|
case DFU_TO_DEV(DFU_DETACH):
|
||||||
@ -211,7 +173,7 @@ static __bit my_setup(struct setup_request *setup) __reentrant
|
|||||||
debug("DFU_DNLOAD\n");
|
debug("DFU_DNLOAD\n");
|
||||||
if (dfu.state == dfuIDLE) {
|
if (dfu.state == dfuIDLE) {
|
||||||
next_block = setup->wValue;
|
next_block = setup->wValue;
|
||||||
payload = PAYLOAD_START;
|
flash_start();
|
||||||
}
|
}
|
||||||
else if (dfu.state != dfuDNLOAD_IDLE) {
|
else if (dfu.state != dfuDNLOAD_IDLE) {
|
||||||
error("bad state\n");
|
error("bad state\n");
|
||||||
@ -242,7 +204,7 @@ static __bit my_setup(struct setup_request *setup) __reentrant
|
|||||||
debug("DFU_UPLOAD\n");
|
debug("DFU_UPLOAD\n");
|
||||||
if (dfu.state == dfuIDLE) {
|
if (dfu.state == dfuIDLE) {
|
||||||
next_block = setup->wValue;
|
next_block = setup->wValue;
|
||||||
payload = PAYLOAD_START;
|
flash_start();
|
||||||
}
|
}
|
||||||
else if (dfu.state != dfuUPLOAD_IDLE)
|
else if (dfu.state != dfuUPLOAD_IDLE)
|
||||||
return 0;
|
return 0;
|
||||||
@ -266,7 +228,7 @@ static __bit my_setup(struct setup_request *setup) __reentrant
|
|||||||
return ok;
|
return ok;
|
||||||
case DFU_FROM_DEV(DFU_GETSTATUS):
|
case DFU_FROM_DEV(DFU_GETSTATUS):
|
||||||
debug("DFU_GETSTATUS\n");
|
debug("DFU_GETSTATUS\n");
|
||||||
usb_send(&ep0, (uint8_t *) &dfu, sizeof(dfu), NULL, NULL);
|
usb_send(&eps[0], (uint8_t *) &dfu, sizeof(dfu), NULL, NULL);
|
||||||
return 1;
|
return 1;
|
||||||
case DFU_TO_DEV(DFU_CLRSTATUS):
|
case DFU_TO_DEV(DFU_CLRSTATUS):
|
||||||
debug("DFU_CLRSTATUS\n");
|
debug("DFU_CLRSTATUS\n");
|
||||||
@ -275,7 +237,7 @@ static __bit my_setup(struct setup_request *setup) __reentrant
|
|||||||
return 1;
|
return 1;
|
||||||
case DFU_FROM_DEV(DFU_GETSTATE):
|
case DFU_FROM_DEV(DFU_GETSTATE):
|
||||||
debug("DFU_GETSTATE\n");
|
debug("DFU_GETSTATE\n");
|
||||||
usb_send(&ep0, &dfu.state, 1, NULL, NULL);
|
usb_send(&eps[0], &dfu.state, 1, NULL, NULL);
|
||||||
return 1;
|
return 1;
|
||||||
case DFU_TO_DEV(DFU_ABORT):
|
case DFU_TO_DEV(DFU_ABORT):
|
||||||
debug("DFU_ABORT\n");
|
debug("DFU_ABORT\n");
|
||||||
@ -283,29 +245,16 @@ static __bit my_setup(struct setup_request *setup) __reentrant
|
|||||||
dfu.status = OK;
|
dfu.status = OK;
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
#ifdef CONFIG_PRINTK
|
error("DFU rt %x, rq%x ?\n",
|
||||||
printk("DFU rt %x, rq%x ?\n",
|
|
||||||
setup->bmRequestType, setup->bRequest);
|
setup->bmRequestType, setup->bRequest);
|
||||||
#else
|
|
||||||
/*
|
|
||||||
* @@@ SDCC 2.7.0 ends up OR'in setup->bmRequestType with
|
|
||||||
* setup->bRequest unshifted if we don't use at least one of
|
|
||||||
* them here.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
static volatile uint8_t foo;
|
|
||||||
foo = setup->bRequest;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static __bit my_descr(uint8_t type, uint8_t index, const uint8_t **reply,
|
static int my_descr(uint8_t type, uint8_t index, const uint8_t **reply,
|
||||||
uint8_t *size) __reentrant
|
uint8_t *size)
|
||||||
{
|
{
|
||||||
index; /* suppress warning */
|
|
||||||
if (type != DFU_DT_FUNCTIONAL)
|
if (type != DFU_DT_FUNCTIONAL)
|
||||||
return 0;
|
return 0;
|
||||||
*reply = functional_descriptor;
|
*reply = functional_descriptor;
|
||||||
@ -314,7 +263,8 @@ static __bit my_descr(uint8_t type, uint8_t index, const uint8_t **reply,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void my_reset(void) __reentrant
|
#if 0
|
||||||
|
static void my_reset(void)
|
||||||
{
|
{
|
||||||
/* @@@ not nice -- think about where this should go */
|
/* @@@ not nice -- think about where this should go */
|
||||||
extern void run_payload(void);
|
extern void run_payload(void);
|
||||||
@ -322,11 +272,12 @@ static void my_reset(void) __reentrant
|
|||||||
if (did_download)
|
if (did_download)
|
||||||
run_payload();
|
run_payload();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void dfu_init(void)
|
void dfu_init(void)
|
||||||
{
|
{
|
||||||
user_setup = my_setup;
|
user_setup = my_setup;
|
||||||
user_get_descriptor = my_descr;
|
user_get_descriptor = my_descr;
|
||||||
user_reset = my_reset;
|
// user_reset = my_reset;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* boot/dfu.h - DFU protocol constants and data structures
|
* boot/dfu.h - DFU protocol constants and data structures
|
||||||
*
|
*
|
||||||
* Written 2008 by Werner Almesberger
|
* Written 2008, 2011 by Werner Almesberger
|
||||||
* Copyright 2008 Werner Almesberger
|
* Copyright 2008, 2011 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
|
||||||
@ -81,6 +81,12 @@ struct dfu {
|
|||||||
extern struct dfu dfu;
|
extern struct dfu dfu;
|
||||||
|
|
||||||
|
|
||||||
|
void flash_start(void);
|
||||||
|
int flash_can_write(uint16_t size);
|
||||||
|
void flash_write(const uint8_t *buf, uint16_t size);
|
||||||
|
uint16_t flash_read(uint8_t *buf, uint16_t size);
|
||||||
|
|
||||||
|
|
||||||
void dfu_init(void);
|
void dfu_init(void);
|
||||||
|
|
||||||
#endif /* !DFU_H */
|
#endif /* !DFU_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user