forked from PAWPAW-Mirror/lib_xua
First commit
This commit is contained in:
188
module_dfu/src/dfu.h
Normal file
188
module_dfu/src/dfu.h
Normal file
@@ -0,0 +1,188 @@
|
||||
#ifndef DFU_VENDOR_ID
|
||||
#define DFU_VENDOR_ID 0x20B1
|
||||
#endif
|
||||
|
||||
//#ifndef DFU_PRODUCT_ID
|
||||
//#define DFU_PRODUCT_ID 0x0003
|
||||
//#error DFU_PRODUCT_ID not defined!
|
||||
//#endif
|
||||
|
||||
#ifndef PID_DFU
|
||||
#error PID_DFU not defined!
|
||||
#endif
|
||||
|
||||
#ifndef DFU_BCD_DEVICE
|
||||
#warning DFU_BCD_DEVICE NOT DEFINED
|
||||
#define DFU_BCD_DEVICE 0x0000
|
||||
#endif
|
||||
|
||||
#ifndef DFU_SERIAL_STR_INDEX
|
||||
#error DFU_SERIAL_STR_INDEX NOT DEFINED!
|
||||
//#define DFU_SERIAL_STR_INDEX 0x00
|
||||
#endif
|
||||
|
||||
#ifndef DFU_PRODUCT_INDEX
|
||||
#error DFU_PROFUCT_INDEX NOT DEFINED!
|
||||
//#define DFU_PRODUCT_INDEX 0x1
|
||||
#endif
|
||||
|
||||
#ifndef DFU_MANUFACTURER_INDEX
|
||||
#error DFU_MANUFACTURING_INDEX NOT DEFINED!
|
||||
//#define DFU_MANUFACTURER_INDEX 0x2
|
||||
#endif
|
||||
|
||||
unsigned char DFUdevDesc[] = {
|
||||
18, /* 0 bLength : Size of descriptor in Bytes (18 Bytes) */
|
||||
1, /* 1 bdescriptorType */
|
||||
0, /* 2 bcdUSB */
|
||||
2, /* 3 bcdUSB */
|
||||
0x00, /* 4 bDeviceClass: See interface */
|
||||
0x00, /* 5 bDeviceSubClass: See interface */
|
||||
0, /* 6 bDeviceProtocol: See interface */
|
||||
64, /* 7 bMaxPacketSize */
|
||||
(DFU_VENDOR_ID & 0xFF), /* 8 idVendor */
|
||||
(DFU_VENDOR_ID >> 8), /* 9 idVendor */
|
||||
(PID_DFU & 0xFF), /* 10 idProduct */
|
||||
(PID_DFU >> 8), /* 11 idProduct */
|
||||
(DFU_BCD_DEVICE & 0xFF), /* 12 bcdDevice : Device release number */
|
||||
(DFU_BCD_DEVICE >> 8), /* 13 bcdDevice : Device release number */
|
||||
DFU_MANUFACTURER_INDEX, /* 14 iManufacturer : Index of manufacturer string */
|
||||
DFU_PRODUCT_INDEX, /* 15 iProduct : Index of product string descriptor */
|
||||
DFU_SERIAL_STR_INDEX, /* 16 iSerialNumber : Index of serial number decriptor */
|
||||
0x01 /* 17 bNumConfigurations : Number of possible configs */
|
||||
};
|
||||
|
||||
unsigned char DFUcfgDesc[] = {
|
||||
/* Standard USB device descriptor */
|
||||
0x09, /* 0 bLength */
|
||||
CONFIGURATION, /* 1 bDescriptorType */
|
||||
0x1b, /* 2 wTotalLength */
|
||||
0x00, /* 3 wTotalLength */
|
||||
1, /* 4 bNumInterface: Number of interfaces*/
|
||||
0x01, /* 5 bConfigurationValue */
|
||||
0x00, /* 6 iConfiguration */
|
||||
0xC0, /* 7 bmAttributes */
|
||||
0x32, /* 8 bMaxPower */
|
||||
|
||||
/* Standard DFU class interface descriptor */
|
||||
0x09, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */
|
||||
0x04, /* 1 bDescriptorType : INTERFACE descriptor. (field size 1 bytes) */
|
||||
0x00, /* 2 bInterfaceNumber : Index of this interface. (field size 1 bytes) */
|
||||
0x00, /* 3 bAlternateSetting : Index of this setting. (field size 1 bytes) */
|
||||
0x00, /* 4 bNumEndpoints : 0 endpoints. (field size 1 bytes) */
|
||||
0xFE, /* 5 bInterfaceClass : AUDIO. (field size 1 bytes) */
|
||||
0x01, /* 6 bInterfaceSubclass : AUDIO_CONTROL. (field size 1 bytes) */
|
||||
0x02, /* 7 bInterfaceProtocol : Unused. (field size 1 bytes) */
|
||||
0x00, /* 8 iInterface : Unused. (field size 1 bytes) */
|
||||
|
||||
#if 0
|
||||
/* DFU 1.0 Standard DFU class functional descriptor */
|
||||
0x07,
|
||||
0x21,
|
||||
0x07,
|
||||
0xFA,
|
||||
0x00,
|
||||
0x40,
|
||||
0x00
|
||||
#else
|
||||
/* DFU 1.1 Run-Time DFU Functional Descriptor */
|
||||
0x09, /* 0 Size */
|
||||
0x21, /* 1 bDescriptorType : DFU FUNCTIONAL */
|
||||
0x07, /* 2 bmAttributes */
|
||||
0xFA, /* 3 wDetachTimeOut */
|
||||
0x00, /* 4 wDetachTimeOut */
|
||||
0x40, /* 5 wTransferSize */
|
||||
0x00, /* 6 wTransferSize */
|
||||
0x10, /* 7 bcdDFUVersion */
|
||||
0x01, /* 7 bcdDFUVersion */
|
||||
#endif
|
||||
|
||||
|
||||
};
|
||||
|
||||
unsigned char DFUoSpeedCfgDesc[] =
|
||||
{
|
||||
/* Standard USB device descriptor */
|
||||
0x09, /* 0 bLength */
|
||||
OTHER_SPEED_CONFIGURATION, /* 1 bDescriptorType */
|
||||
0x1b, /* 2 wTotalLength */
|
||||
0x00, /* 3 wTotalLength */
|
||||
1, /* 4 bNumInterface: Number of interfaces*/
|
||||
0x01, /* 5 bConfigurationValue */
|
||||
0x00, /* 6 iConfiguration */
|
||||
0xC0, /* 7 bmAttributes */
|
||||
0x32, /* 8 bMaxPower */
|
||||
|
||||
/* Standard DFU class interface descriptor */
|
||||
0x09, /* 0 bLength : Size of this descriptor, in bytes. (field size 1 bytes) */
|
||||
0x04, /* 1 bDescriptorType : INTERFACE descriptor. (field size 1 bytes) */
|
||||
0x00, /* 2 bInterfaceNumber : Index of this interface. (field size 1 bytes) */
|
||||
0x00, /* 3 bAlternateSetting : Index of this setting. (field size 1 bytes) */
|
||||
0x00, /* 4 bNumEndpoints : 0 endpoints. (field size 1 bytes) */
|
||||
0xFE, /* 5 bInterfaceClass : AUDIO. (field size 1 bytes) */
|
||||
0x01, /* 6 bInterfaceSubclass : AUDIO_CONTROL. (field size 1 bytes) */
|
||||
0x02, /* 7 bInterfaceProtocol : Unused. (field size 1 bytes) */
|
||||
0x00, /* 8 iInterface : Unused. (field size 1 bytes) */
|
||||
|
||||
/* DFU 1.1 Run-Time DFU Functional Descriptor */
|
||||
0x09, /* 0 Size */
|
||||
0x21, /* 1 bDescriptorType : DFU FUNCTIONAL */
|
||||
0x07, /* 2 bmAttributes */
|
||||
0xFA, /* 3 wDetachTimeOut */
|
||||
0x00, /* 4 wDetachTimeOut */
|
||||
0x40, /* 5 wTransferSize */
|
||||
0x00, /* 6 wTransferSize */
|
||||
0x10, /* 7 bcdDFUVersion */
|
||||
0x01, /* 7 bcdDFUVersion */
|
||||
};
|
||||
|
||||
unsigned char DFUdevQualDesc[] =
|
||||
{
|
||||
10, /* 0 bLength : Size of descriptor in Bytes (18 Bytes) */
|
||||
DEVICE_QUALIFIER, /* 1 bdescriptorType */
|
||||
0, /* 2 bcdUSB */
|
||||
2, /* 3 bcdUSB */
|
||||
0xfe, /* 4 bDeviceClass */
|
||||
1, /* 5 bDeviceSubClass */
|
||||
0, /* 6 bDeviceProtocol */
|
||||
64, /* 7 bMaxPacketSize */
|
||||
0x01, /* 8 bNumConfigurations : Number of possible configs */ \
|
||||
0x00 /* 9 bReserved (must be zero) */ \
|
||||
};
|
||||
|
||||
int DFUReportResetState(chanend ?c_user_cmd);
|
||||
int DFUDeviceRequests(XUD_ep c_ep0_out, XUD_ep &?ep0_in, SetupPacket &sp, chanend ?c_user_cmd, unsigned int altInterface, unsigned int user_reset);
|
||||
|
||||
// Overload the USB user command handler if present
|
||||
extern unsigned int flash_programmer(unsigned int cmd, unsigned int request_data[16]);
|
||||
void user_cmd_handler(unsigned int cmd, chanend ?c_user_cmd) {
|
||||
|
||||
if (!isnull(c_user_cmd)) {
|
||||
unsigned int request_data_len = 0;
|
||||
unsigned int request_data[16];
|
||||
unsigned int return_data_len = 0;
|
||||
int i = 0;
|
||||
|
||||
// Read request data length
|
||||
request_data_len = inuint(c_user_cmd);
|
||||
|
||||
// Read request data
|
||||
for (i = 0; i < request_data_len; i++) {
|
||||
request_data[i] = inuint(c_user_cmd);
|
||||
}
|
||||
|
||||
return_data_len = flash_programmer(cmd, request_data);
|
||||
|
||||
outuint(c_user_cmd, return_data_len);
|
||||
|
||||
if (return_data_len) {
|
||||
for (i = 0; i < return_data_len/4; i++) {
|
||||
outuint(c_user_cmd, request_data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
460
module_dfu/src/dfu.xc
Normal file
460
module_dfu/src/dfu.xc
Normal file
@@ -0,0 +1,460 @@
|
||||
#include <xs1.h>
|
||||
#include <platform.h>
|
||||
#include <print.h>
|
||||
|
||||
#include "xud.h"
|
||||
#ifdef ARCH_G
|
||||
#include "XUD_USB_Defines.h"
|
||||
#else
|
||||
#include "usb.h"
|
||||
#endif
|
||||
|
||||
#include "dfu_types.h"
|
||||
#include "flash_programmer.h"
|
||||
|
||||
static int DFU_state = STATE_APP_IDLE;
|
||||
static int DFU_status = DFU_OK;
|
||||
static timer DFUTimer;
|
||||
static unsigned int DFUTimerStart = 0;
|
||||
static unsigned int DFUResetTimeout = 100000000; // 1 second default
|
||||
static int DFU_flash_connected = 0;
|
||||
|
||||
static unsigned int subPagesLeft = 0;
|
||||
|
||||
extern int DFU_reset_override;
|
||||
|
||||
void temp() {
|
||||
asm(".linkset DFU_reset_override, _edp.bss");
|
||||
asm(".globl DFU_reset_override");
|
||||
}
|
||||
|
||||
static int DFU_OpenFlash(chanend ?c_user_cmd)
|
||||
{
|
||||
if (!DFU_flash_connected)
|
||||
{
|
||||
unsigned int cmd_data[16];
|
||||
HandleUserDeviceRequest(FLASH_CMD_INIT, 1, 0, cmd_data, c_user_cmd);
|
||||
DFU_flash_connected = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DFU_CloseFlash(chanend ?c_user_cmd) {
|
||||
if (DFU_flash_connected) {
|
||||
unsigned int cmd_data[16];
|
||||
HandleUserDeviceRequest(FLASH_CMD_DEINIT, 1, 0, cmd_data, c_user_cmd);
|
||||
DFU_flash_connected = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DFU_Detach(unsigned int timeout, chanend ?c_user_cmd) {
|
||||
if (DFU_state == STATE_APP_IDLE) {
|
||||
|
||||
DFU_state = STATE_APP_DETACH;
|
||||
|
||||
DFU_OpenFlash(c_user_cmd);
|
||||
|
||||
// Setup DFU timeout value
|
||||
DFUResetTimeout = timeout * 100000;
|
||||
|
||||
// Start DFU reset timer
|
||||
DFUTimer :> DFUTimerStart;
|
||||
} else {
|
||||
DFU_state = STATE_DFU_ERROR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DFU_Dnload(unsigned int request_len, unsigned int block_num, unsigned int request_data[16], chanend ?c_user_cmd) {
|
||||
unsigned int fromDfuIdle = 0;
|
||||
|
||||
// Get DFU packets here, sequence is
|
||||
// DFU_DOWNLOAD -> DFU_DOWNLOAD_SYNC
|
||||
// GET_STATUS -> DFU_DOWNLOAD_SYNC (flash busy) || DFU_DOWNLOAD_IDLE
|
||||
// REPEAT UNTIL DFU_DOWNLOAD with 0 length -> DFU_MANIFEST_SYNC
|
||||
|
||||
DFU_OpenFlash(c_user_cmd);
|
||||
|
||||
switch (DFU_state) {
|
||||
case STATE_DFU_IDLE:
|
||||
case STATE_DFU_DOWNLOAD_IDLE:
|
||||
break;
|
||||
default:
|
||||
DFU_state = STATE_DFU_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((DFU_state == STATE_DFU_IDLE) && (request_len == 0)) {
|
||||
DFU_state = STATE_DFU_ERROR;
|
||||
return 0;
|
||||
} else if (DFU_state == STATE_DFU_IDLE) {
|
||||
fromDfuIdle = 1;
|
||||
} else {
|
||||
fromDfuIdle = 0;
|
||||
}
|
||||
|
||||
if (request_len == 0) {
|
||||
// Host signalling complete download
|
||||
int i = 0;
|
||||
unsigned int cmd_data[16];
|
||||
if (subPagesLeft) {
|
||||
unsigned int subPagePad[16] = {0};
|
||||
for (i = 0; i < subPagesLeft; i++) {
|
||||
HandleUserDeviceRequest(FLASH_CMD_WRITE_PAGE_DATA, 1, 64, subPagePad, c_user_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
cmd_data[0] = 2; // Terminate write
|
||||
HandleUserDeviceRequest(FLASH_CMD_WRITE_PAGE, 1, 4, cmd_data, c_user_cmd);
|
||||
|
||||
DFU_state = STATE_DFU_MANIFEST_SYNC;
|
||||
} else {
|
||||
unsigned int i = 0;
|
||||
unsigned int flash_cmd = 0;
|
||||
unsigned int flash_page_index = 0;
|
||||
unsigned int cmd_data[16];
|
||||
|
||||
if (fromDfuIdle)
|
||||
{
|
||||
unsigned s = 0;
|
||||
|
||||
#if 0
|
||||
/* Flash lib does erase on add image */
|
||||
// Erase flash on first block
|
||||
HandleUserDeviceRequest(FLASH_CMD_ERASE_ALL, 1, 0, cmd_data, c_user_cmd);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Delay should not be required. Erase now blocking call */
|
||||
DFUTimer :> s;
|
||||
DFUTimer when timerafter(s + 25000000) :> s; // Wait for flash erase
|
||||
#endif
|
||||
}
|
||||
|
||||
// Program firmware, STATE_DFU_DOWNLOAD_BUSY not currently used
|
||||
|
||||
if (!(block_num % 4)) {
|
||||
cmd_data[0] = !fromDfuIdle; // 0 for first page, 1 for other pages.
|
||||
HandleUserDeviceRequest(FLASH_CMD_WRITE_PAGE, 1, 4, cmd_data, c_user_cmd);
|
||||
subPagesLeft = 4;
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
cmd_data[i] = request_data[i];
|
||||
}
|
||||
|
||||
HandleUserDeviceRequest(FLASH_CMD_WRITE_PAGE_DATA, 1, 64, cmd_data, c_user_cmd);
|
||||
subPagesLeft--;
|
||||
|
||||
DFU_state = STATE_DFU_DOWNLOAD_SYNC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int DFU_Upload(unsigned int request_len, unsigned int block_num, unsigned int request_data[16], chanend ?c_user_cmd) {
|
||||
unsigned int cmd_data[16];
|
||||
unsigned int firstRead = 0;
|
||||
|
||||
// Start at flash address 0
|
||||
// Keep reading flash pages until read_page returns 1 (address out of range)
|
||||
// Return terminating upload packet at this point
|
||||
|
||||
DFU_OpenFlash(c_user_cmd);
|
||||
|
||||
switch (DFU_state) {
|
||||
case STATE_DFU_IDLE:
|
||||
case STATE_DFU_UPLOAD_IDLE:
|
||||
break;
|
||||
default:
|
||||
DFU_state = STATE_DFU_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//printintln(request_len);
|
||||
|
||||
if ((DFU_state == STATE_DFU_IDLE) && (request_len == 0)) {
|
||||
DFU_state = STATE_DFU_ERROR;
|
||||
return 0;
|
||||
} else if (DFU_state == STATE_DFU_IDLE) {
|
||||
firstRead = 1;
|
||||
subPagesLeft = 0;
|
||||
}
|
||||
|
||||
if (!subPagesLeft) {
|
||||
cmd_data[0] = !firstRead;
|
||||
|
||||
// Read page
|
||||
HandleUserDeviceRequest(FLASH_CMD_READ_PAGE, 0, 4, cmd_data, c_user_cmd);
|
||||
subPagesLeft = 4;
|
||||
|
||||
// If address out of range, terminate!
|
||||
if (cmd_data[0] == 1) {
|
||||
subPagesLeft = 0;
|
||||
// Back to idle state, upload complete
|
||||
DFU_state = STATE_DFU_IDLE;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Read page data
|
||||
HandleUserDeviceRequest(FLASH_CMD_READ_PAGE_DATA, 0, 0, request_data, c_user_cmd);
|
||||
|
||||
subPagesLeft--;
|
||||
|
||||
DFU_state = STATE_DFU_UPLOAD_IDLE;
|
||||
|
||||
return 64;
|
||||
}
|
||||
|
||||
static int DFU_GetStatus(unsigned int request_len, unsigned int request_data[16], chanend ?c_user_cmd) {
|
||||
unsigned int timeout = 0;
|
||||
|
||||
request_data[0] = timeout << 8 | (unsigned char)DFU_status;
|
||||
|
||||
switch (DFU_state) {
|
||||
case STATE_DFU_MANIFEST:
|
||||
case STATE_DFU_MANIFEST_WAIT_RESET:
|
||||
DFU_state = STATE_DFU_ERROR;
|
||||
break;
|
||||
case STATE_DFU_DOWNLOAD_BUSY:
|
||||
// If download completes -> DFU_DOWNLOAD_SYNC
|
||||
// Currently all transactions are synchronous so no busy state
|
||||
break;
|
||||
case STATE_DFU_DOWNLOAD_SYNC:
|
||||
DFU_state = STATE_DFU_DOWNLOAD_IDLE;
|
||||
break;
|
||||
case STATE_DFU_MANIFEST_SYNC:
|
||||
// Check if complete here
|
||||
DFU_state = STATE_DFU_IDLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
request_data[1] = DFU_state;
|
||||
|
||||
return 6;
|
||||
}
|
||||
|
||||
static int DFU_ClrStatus(void) {
|
||||
if (DFU_state == STATE_DFU_ERROR) {
|
||||
DFU_state = STATE_DFU_IDLE;
|
||||
} else {
|
||||
DFU_state = STATE_DFU_ERROR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DFU_GetState(unsigned int request_len, unsigned int request_data[16], chanend ?c_user_cmd) {
|
||||
|
||||
request_data[0] = DFU_state;
|
||||
|
||||
switch (DFU_state) {
|
||||
case STATE_DFU_DOWNLOAD_BUSY:
|
||||
case STATE_DFU_MANIFEST:
|
||||
case STATE_DFU_MANIFEST_WAIT_RESET:
|
||||
DFU_state = STATE_DFU_ERROR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int DFU_Abort(void) {
|
||||
DFU_state = STATE_DFU_IDLE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Tell the DFU state machine that a USB reset has occured
|
||||
int DFUReportResetState(chanend ?c_user_cmd) {
|
||||
unsigned int inDFU = 0;
|
||||
unsigned int currentTime = 0;
|
||||
|
||||
if (DFU_reset_override == 0x11042011) {
|
||||
unsigned int cmd_data[16];
|
||||
inDFU = 1;
|
||||
DFU_state = STATE_DFU_IDLE;
|
||||
return inDFU;
|
||||
}
|
||||
|
||||
switch(DFU_state) {
|
||||
case STATE_APP_DETACH:
|
||||
case STATE_DFU_IDLE:
|
||||
DFU_state = STATE_DFU_IDLE;
|
||||
|
||||
DFUTimer :> currentTime;
|
||||
if (currentTime - DFUTimerStart > DFUResetTimeout) {
|
||||
DFU_state = STATE_APP_IDLE;
|
||||
//printintln(currentTime - DFUTimerStart);
|
||||
//printintln(DFUResetTimeout);
|
||||
inDFU = 0;
|
||||
} else {
|
||||
inDFU = 1;
|
||||
}
|
||||
break;
|
||||
case STATE_APP_IDLE:
|
||||
case STATE_DFU_DOWNLOAD_SYNC:
|
||||
case STATE_DFU_DOWNLOAD_BUSY:
|
||||
case STATE_DFU_DOWNLOAD_IDLE:
|
||||
case STATE_DFU_MANIFEST_SYNC:
|
||||
case STATE_DFU_MANIFEST:
|
||||
case STATE_DFU_MANIFEST_WAIT_RESET:
|
||||
case STATE_DFU_UPLOAD_IDLE:
|
||||
case STATE_DFU_ERROR:
|
||||
inDFU = 0;
|
||||
DFU_state = STATE_APP_IDLE;
|
||||
break;
|
||||
default:
|
||||
DFU_state = STATE_DFU_ERROR;
|
||||
inDFU = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!inDFU) {
|
||||
DFU_CloseFlash(c_user_cmd);
|
||||
}
|
||||
|
||||
return inDFU;
|
||||
}
|
||||
|
||||
int XMOS_DFU_RevertFactory(chanend ?c_user_cmd) {
|
||||
unsigned int cmd_data[16];
|
||||
unsigned s = 0;
|
||||
|
||||
DFU_OpenFlash(c_user_cmd);
|
||||
|
||||
HandleUserDeviceRequest(FLASH_CMD_ERASE_ALL, 1, 0, cmd_data, c_user_cmd);
|
||||
|
||||
DFUTimer :> s;
|
||||
DFUTimer when timerafter(s + 25000000) :> s; // Wait for flash erase
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XMOS_DFU_SelectImage(unsigned int index, chanend ?c_user_cmd) {
|
||||
|
||||
// Select the image index for firmware update
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int XMOS_DFU_SaveState()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XMOS_DFU_LoadState()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DFUDeviceRequests(XUD_ep ep0_out, XUD_ep &?ep0_in, SetupPacket &sp, chanend ?c_user_cmd, unsigned int altInterface, unsigned int user_reset) {
|
||||
unsigned int return_data_len = 0;
|
||||
unsigned int data_buffer_len = 0;
|
||||
unsigned int data_buffer[17];
|
||||
unsigned int reset_device_after_ack = 0;
|
||||
|
||||
if(sp.bmRequestType.Direction == BM_REQTYPE_DIRECTION_OUT)
|
||||
{ // Host to device
|
||||
if (sp.wLength)
|
||||
#ifdef ARCH_G
|
||||
data_buffer_len = XUD_GetBuffer_(ep0_out, 0, (data_buffer, unsigned char[]));
|
||||
#else
|
||||
data_buffer_len = XUD_GetBuffer(ep0_out, (data_buffer, unsigned char[]));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Map Standard DFU commands onto device level firmware upgrade mechanism
|
||||
switch (sp.bRequest) {
|
||||
case DFU_DETACH:
|
||||
return_data_len = DFU_Detach(sp.wValue, c_user_cmd);
|
||||
break;
|
||||
case DFU_DNLOAD:
|
||||
return_data_len = DFU_Dnload(sp.wLength, sp.wValue, data_buffer, c_user_cmd);
|
||||
break;
|
||||
case DFU_UPLOAD:
|
||||
return_data_len = DFU_Upload(sp.wLength, sp.wValue, data_buffer, c_user_cmd);
|
||||
break;
|
||||
case DFU_GETSTATUS:
|
||||
return_data_len = DFU_GetStatus(sp.wLength, data_buffer, c_user_cmd);
|
||||
break;
|
||||
case DFU_CLRSTATUS:
|
||||
return_data_len = DFU_ClrStatus();
|
||||
break;
|
||||
case DFU_GETSTATE:
|
||||
return_data_len = DFU_GetState(sp.wLength, data_buffer, c_user_cmd);
|
||||
break;
|
||||
case DFU_ABORT:
|
||||
return_data_len = DFU_Abort();
|
||||
break;
|
||||
/* XMOS Custom DFU requests */
|
||||
case XMOS_DFU_RESETDEVICE:
|
||||
reset_device_after_ack = 1;
|
||||
return_data_len = 0;
|
||||
break;
|
||||
case XMOS_DFU_REVERTFACTORY:
|
||||
return_data_len = XMOS_DFU_RevertFactory(c_user_cmd);
|
||||
break;
|
||||
case XMOS_DFU_RESETINTODFU:
|
||||
reset_device_after_ack = 1;
|
||||
DFU_reset_override = 0x11042011;
|
||||
return_data_len = 0;
|
||||
break;
|
||||
case XMOS_DFU_RESETFROMDFU:
|
||||
reset_device_after_ack = 1;
|
||||
DFU_reset_override = 0;
|
||||
return_data_len = 0;
|
||||
break;
|
||||
case XMOS_DFU_SELECTIMAGE:
|
||||
return_data_len = XMOS_DFU_SelectImage(sp.wValue, c_user_cmd);
|
||||
break;
|
||||
case XMOS_DFU_SAVESTATE:
|
||||
/* Save passed state to flash */
|
||||
return_data_len = XMOS_DFU_SaveState();
|
||||
break;
|
||||
case XMOS_DFU_RESTORESTATE:
|
||||
/* Restore saved state from flash */
|
||||
return_data_len = XMOS_DFU_LoadState();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (sp.bmRequestType.Direction == BM_REQTYPE_DIRECTION_IN && sp.wLength != 0) { // Device to host
|
||||
#ifdef ARCH_G
|
||||
XUD_DoGetRequest(ep0_out, 0, (data_buffer, unsigned char[]), return_data_len, return_data_len);
|
||||
#else
|
||||
XUD_DoGetRequest(ep0_out, ep0_in, (data_buffer, unsigned char[]), return_data_len, return_data_len);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef ARCH_G
|
||||
XUD_DoSetRequestStatus(ep0_out, 0);
|
||||
#else
|
||||
XUD_DoSetRequestStatus(ep0_in, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
// If device reset requested, handle after command acknowledgement
|
||||
if (reset_device_after_ack)
|
||||
{
|
||||
if (!user_reset)
|
||||
{
|
||||
unsigned int cmd_data[16];
|
||||
HandleUserDeviceRequest(FLASH_CMD_REBOOT, 1, 0, cmd_data, c_user_cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
48
module_dfu/src/dfu_types.h
Normal file
48
module_dfu/src/dfu_types.h
Normal file
@@ -0,0 +1,48 @@
|
||||
// Default Command requests (from Spec)
|
||||
#define DFU_DETACH 0
|
||||
#define DFU_DNLOAD 1
|
||||
#define DFU_UPLOAD 2
|
||||
#define DFU_GETSTATUS 3
|
||||
#define DFU_CLRSTATUS 4
|
||||
#define DFU_GETSTATE 5
|
||||
#define DFU_ABORT 6
|
||||
|
||||
// XMOS Alternate Setting Command Requests
|
||||
#define XMOS_DFU_RESETDEVICE 0xf0
|
||||
#define XMOS_DFU_REVERTFACTORY 0xf1
|
||||
#define XMOS_DFU_RESETINTODFU 0xf2
|
||||
#define XMOS_DFU_RESETFROMDFU 0xf3
|
||||
#define XMOS_DFU_SELECTIMAGE 0xf4
|
||||
#define XMOS_DFU_SAVESTATE 0xf5
|
||||
#define XMOS_DFU_RESTORESTATE 0xf6
|
||||
|
||||
// DFU States
|
||||
#define STATE_APP_IDLE 0x00
|
||||
#define STATE_APP_DETACH 0x01
|
||||
#define STATE_DFU_IDLE 0x02
|
||||
#define STATE_DFU_DOWNLOAD_SYNC 0x03
|
||||
#define STATE_DFU_DOWNLOAD_BUSY 0x04
|
||||
#define STATE_DFU_DOWNLOAD_IDLE 0x05
|
||||
#define STATE_DFU_MANIFEST_SYNC 0x06
|
||||
#define STATE_DFU_MANIFEST 0x07
|
||||
#define STATE_DFU_MANIFEST_WAIT_RESET 0x08
|
||||
#define STATE_DFU_UPLOAD_IDLE 0x09
|
||||
#define STATE_DFU_ERROR 0x0a
|
||||
|
||||
// DFU error conditions
|
||||
#define DFU_OK 0x00 // No error condition is present.
|
||||
#define DFU_errTARGET 0x01 // File is not targeted for use by this device.
|
||||
#define DFU_errFILE 0x02 // File is for this device but fails some vendor-specific verification test.
|
||||
#define DFU_errWRITE 0x03 // Device is unable to write memory.
|
||||
#define DFU_errERASE 0x04 // Memory erase function failed.
|
||||
#define DFU_errCHECK_ERASED 0x05 // Memory erase check failed.
|
||||
#define DFU_errPROG 0x06 // Program memory function failed.
|
||||
#define DFU_errVERIFY 0x07 // Programmed memory failed verification.
|
||||
#define DFU_errADDRESS 0x08 // Cannot program memory due to received address that is out of range.
|
||||
#define DFU_errNOTDONE 0x09 // Received DFU_DNLOAD with wLength = 0, but device does not think it has all of the data yet.
|
||||
#define DFU_errFIRMWARE 0x0A // Devices firmware is corrupt. It cannot return to run-time (non-DFU) operations
|
||||
#define DFU_errVENDOR 0x0B // iString indicates a vendor-specific error.
|
||||
#define DFU_errUSBR 0x0C // Device detected unexpected USB reset signaling.
|
||||
#define DFU_errPOR 0x0D // Device detected unexpected power on reset.
|
||||
#define DFU_errUNKNOWN 0x0E // Something went wrong, but the device does not know what it was
|
||||
#define DFU_errSTALLEDPKT 0x0F // Device stalled an unexpected request.
|
||||
218
module_dfu/src/flash_interface.c
Executable file
218
module_dfu/src/flash_interface.c
Executable file
@@ -0,0 +1,218 @@
|
||||
#include <xs1.h>
|
||||
#include <flash.h>
|
||||
#include <flashlib.h>
|
||||
#include <print.h>
|
||||
#include <string.h>
|
||||
#include <xclib.h>
|
||||
|
||||
#ifndef FLASH_MAX_UPGRADE_SIZE
|
||||
#ifdef ARCH_G
|
||||
#define FLASH_MAX_UPGRADE_SIZE 128 * 1024 // 128K default
|
||||
#else
|
||||
//#define FLASH_MAX_UPGRADE_SIZE 64 * 1024 // 64K default
|
||||
#define FLASH_MAX_UPGRADE_SIZE 128 * 1024 // 64K default
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define FLASH_ERROR() do { printstr("Error: line: "); printintln(__LINE__); __builtin_trap(); } while(0)
|
||||
#else
|
||||
#define FLASH_ERROR() do {} while(0)
|
||||
#endif
|
||||
|
||||
static int flash_device_open = 0;
|
||||
static fl_BootImageInfo factory_image;
|
||||
static fl_BootImageInfo upgrade_image;
|
||||
|
||||
static int upgrade_image_valid = 0;
|
||||
static int current_flash_subpage_index = 0;
|
||||
static unsigned char current_flash_page_data[256];
|
||||
|
||||
int flash_cmd_enable_ports() __attribute__ ((weak));
|
||||
int flash_cmd_enable_ports() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_cmd_disable_ports() __attribute__ ((weak));
|
||||
int flash_cmd_disable_ports() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_cmd_init(void) {
|
||||
fl_BootImageInfo image;
|
||||
|
||||
if (!flash_device_open) {
|
||||
if (flash_cmd_enable_ports());
|
||||
flash_device_open = 1;
|
||||
}
|
||||
|
||||
if (!flash_device_open)
|
||||
return 0;
|
||||
|
||||
// Disable flash protection
|
||||
fl_setProtection(0);
|
||||
|
||||
if (fl_getFactoryImage(&image) != 0) {
|
||||
return 0;
|
||||
}
|
||||
factory_image = image;
|
||||
|
||||
if (fl_getNextBootImage(&image) == 0) {
|
||||
upgrade_image_valid = 1;
|
||||
upgrade_image = image;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_cmd_deinit(void) {
|
||||
if (!flash_device_open)
|
||||
return 0;
|
||||
|
||||
flash_cmd_disable_ports();
|
||||
flash_device_open = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_cmd_read_page(unsigned char *data) {
|
||||
if (!upgrade_image_valid) {
|
||||
*(unsigned int *)data = 1;
|
||||
return 4;
|
||||
}
|
||||
if (*(unsigned int *)data == 0) {
|
||||
fl_startImageRead(&upgrade_image);
|
||||
}
|
||||
current_flash_subpage_index = 0;
|
||||
if (fl_readImageRead(current_flash_page_data) == 0) {
|
||||
*(unsigned int *)data = 0;
|
||||
} else {
|
||||
*(unsigned int *)data = 1;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
int flash_cmd_read_page_data(unsigned char *data) {
|
||||
unsigned char *page_data_ptr = ¤t_flash_page_data[current_flash_subpage_index * 64];
|
||||
memcpy(data, page_data_ptr, 64);
|
||||
|
||||
current_flash_subpage_index++;
|
||||
|
||||
return 64;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int roundUpToSectorBoundary(unsigned address)
|
||||
{
|
||||
unsigned curAddress = 0;
|
||||
unsigned numSectors = fl_getNumSectors();
|
||||
unsigned i;
|
||||
for (i = 0; i < numSectors; i++) {
|
||||
curAddress += fl_getSectorSize(i);
|
||||
if (curAddress >= address)
|
||||
return curAddress;
|
||||
}
|
||||
return address;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void begin_write()
|
||||
{
|
||||
int result;
|
||||
// TODO this will take a long time. To minimise the amount of time spent
|
||||
// paused on this operation it would be preferable to move to this to a
|
||||
// seperate command, e.g. start_write.
|
||||
do {
|
||||
result = fl_startImageAdd(&factory_image, FLASH_MAX_UPGRADE_SIZE, 0);
|
||||
} while (result > 0);
|
||||
if (result < 0)
|
||||
FLASH_ERROR();
|
||||
}
|
||||
|
||||
static int pages_written = 0;
|
||||
|
||||
int flash_cmd_write_page(unsigned char *data) {
|
||||
unsigned int flag = *(unsigned int *)data;
|
||||
//printstr("flash_cmd_write_page(");
|
||||
//printint(flag);
|
||||
//printstr(")\n");
|
||||
|
||||
if (upgrade_image_valid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (flag) {
|
||||
case 0:
|
||||
// First page.
|
||||
begin_write();
|
||||
pages_written = 0;
|
||||
// fallthrough
|
||||
case 1:
|
||||
// Do nothing.
|
||||
break;
|
||||
case 2:
|
||||
// Termination.
|
||||
if (fl_endWriteImage() != 0)
|
||||
FLASH_ERROR();
|
||||
// Sanity check
|
||||
fl_BootImageInfo image = factory_image;
|
||||
if (fl_getNextBootImage(&image) != 0)
|
||||
FLASH_ERROR();
|
||||
break;
|
||||
}
|
||||
current_flash_subpage_index = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isAllOnes(unsigned char page[256])
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (page[i] != 0xff)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flash_cmd_write_page_data(unsigned char *data) {
|
||||
unsigned char *page_data_ptr = ¤t_flash_page_data[current_flash_subpage_index * 64];
|
||||
//printstr("flash_cmd_write_page_data()\n");
|
||||
|
||||
if (upgrade_image_valid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (current_flash_subpage_index >= 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(page_data_ptr, data, 64);
|
||||
|
||||
current_flash_subpage_index++;
|
||||
|
||||
if (current_flash_subpage_index == 4) {
|
||||
if (isAllOnes(data))
|
||||
FLASH_ERROR();
|
||||
if (fl_writeImagePage(current_flash_page_data) != 0)
|
||||
FLASH_ERROR();
|
||||
pages_written++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_cmd_erase_all(void) {
|
||||
if (upgrade_image_valid) {
|
||||
if (fl_deleteImage(&upgrade_image) != 0)
|
||||
FLASH_ERROR();
|
||||
upgrade_image_valid = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flash_cmd_reboot(void) {
|
||||
unsigned int pllVal;
|
||||
read_sswitch_reg(0, 6, &pllVal);
|
||||
write_sswitch_reg(0, 6, pllVal);
|
||||
return 0;
|
||||
}
|
||||
33
module_dfu/src/flash_interface.h
Executable file
33
module_dfu/src/flash_interface.h
Executable file
@@ -0,0 +1,33 @@
|
||||
#ifndef _flash_interface_h_
|
||||
#define _flash_interface_h_
|
||||
|
||||
int flash_cmd_init(void);
|
||||
/**
|
||||
* Prepare to write a page of a new upgrade image.
|
||||
* The first word of data should be set to 0 if it is the first page,
|
||||
* 1 for all other pages and 2 to terminate the write (no further data is sent).
|
||||
*/
|
||||
int flash_cmd_write_page(unsigned char []);
|
||||
/**
|
||||
* Provide upgrade image data. flash_cmd_write_page() must be called previously.
|
||||
* Once a page of data has been provided it is written to the device.
|
||||
*/
|
||||
int flash_cmd_write_page_data(unsigned char []);
|
||||
/**
|
||||
* Read a page of data from the upgrade image.
|
||||
* If the first word of data is 0 the page is read from the start of the
|
||||
* upgrade image, otherwise the next page in the image will be read.
|
||||
* On return the first word of data is written with 1 if there is nothing to
|
||||
* read and 0 otherwise.
|
||||
*/
|
||||
int flash_cmd_read_page(unsigned char []);
|
||||
/**
|
||||
* Get data previously read by flash_cmd_read_page().
|
||||
*/
|
||||
int flash_cmd_read_page_data(unsigned char []);
|
||||
int flash_cmd_erase_all(void);
|
||||
int flash_cmd_reboot(void);
|
||||
int flash_cmd_init(void);
|
||||
int flash_cmd_deinit(void);
|
||||
|
||||
#endif /*_flash_interface_h_*/
|
||||
14
module_dfu/src/flash_programmer.h
Executable file
14
module_dfu/src/flash_programmer.h
Executable file
@@ -0,0 +1,14 @@
|
||||
#define FLASH_CMD_WRITE_PAGE 0xf1
|
||||
#define FLASH_CMD_READ_PAGE 0xf2
|
||||
#define FLASH_CMD_WRITE_PAGE_DATA 0xf3
|
||||
#define FLASH_CMD_READ_PAGE_DATA 0xf4
|
||||
#define FLASH_CMD_ERASE_ALL 0xf5
|
||||
#define FLASH_CMD_REBOOT 0xf6
|
||||
#define FLASH_CMD_INIT 0xf7
|
||||
#define FLASH_CMD_DEINIT 0xf8
|
||||
|
||||
unsigned int flash_programmer(unsigned int cmd, unsigned int request_data[16]);
|
||||
int HandleUserDeviceRequest(unsigned int cmd, unsigned int to_device,
|
||||
unsigned int request_size, unsigned int request_data[16],
|
||||
chanend ?c_user_cmd);
|
||||
|
||||
82
module_dfu/src/flash_programmer.xc
Executable file
82
module_dfu/src/flash_programmer.xc
Executable file
@@ -0,0 +1,82 @@
|
||||
#include <xs1.h>
|
||||
#include <print.h>
|
||||
#include "flash_interface.h"
|
||||
#include "flash_programmer.h"
|
||||
|
||||
unsigned int flash_programmer(unsigned int cmd, unsigned int request_data[16]) {
|
||||
unsigned int return_data_len = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case FLASH_CMD_WRITE_PAGE:
|
||||
return_data_len = flash_cmd_write_page((request_data, unsigned char[64]));
|
||||
break;
|
||||
|
||||
case FLASH_CMD_READ_PAGE:
|
||||
return_data_len = flash_cmd_read_page((request_data, unsigned char[64]));
|
||||
break;
|
||||
|
||||
case FLASH_CMD_WRITE_PAGE_DATA:
|
||||
return_data_len = flash_cmd_write_page_data((request_data, unsigned char[64]));
|
||||
break;
|
||||
|
||||
case FLASH_CMD_READ_PAGE_DATA:
|
||||
return_data_len = flash_cmd_read_page_data((request_data, unsigned char[64]));
|
||||
break;
|
||||
|
||||
case FLASH_CMD_ERASE_ALL:
|
||||
return_data_len = flash_cmd_erase_all();
|
||||
break;
|
||||
|
||||
case FLASH_CMD_REBOOT:
|
||||
return_data_len = flash_cmd_reboot();
|
||||
break;
|
||||
|
||||
case FLASH_CMD_INIT:
|
||||
return_data_len = flash_cmd_init();
|
||||
break;
|
||||
|
||||
case FLASH_CMD_DEINIT:
|
||||
return_data_len = flash_cmd_deinit();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return return_data_len;
|
||||
}
|
||||
|
||||
int HandleUserDeviceRequest(unsigned int cmd, unsigned int to_device,
|
||||
unsigned int request_size, unsigned int request_data[16],
|
||||
chanend ?c_user_cmd) {
|
||||
|
||||
unsigned int return_data_len = 0;
|
||||
|
||||
if (isnull(c_user_cmd)) {
|
||||
return_data_len = flash_programmer(cmd, request_data);
|
||||
} else {
|
||||
int i = 0;
|
||||
|
||||
outuint(c_user_cmd, cmd);
|
||||
outuint(c_user_cmd, request_size/4);
|
||||
|
||||
if (request_size) {
|
||||
// Send request data to user cmd handler
|
||||
for (i = 0; i < request_size/4; i++) {
|
||||
outuint(c_user_cmd, request_data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return_data_len = inuint(c_user_cmd);
|
||||
|
||||
if (return_data_len) {
|
||||
// Get response data from user cmd handler
|
||||
for (i = 0; i < return_data_len/4; i++) {
|
||||
request_data[i] = inuint(c_user_cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return return_data_len;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user