forked from len0rd/rockbox
utils/hwstub: completely rework the protocol, drop unused features
The protocol has evolved a lot during the 2.x.y lifetime, bringing more features which later got unused. This commit removes all the unused stuff and simplifies everything: - drop the feature mask: everything is mandatory or stalled on error - remove the info request and put all static information in standard USB descriptors which are part of the configuration descriptor (and can be retrieved using the standard GetDescriptor request). - remove the USB interface, we had only one anyway - remove all endpoint descriptors - remove the exit/atexit stuff, it never worked as intended anyway - update the hwstub library and make it able to handle any device - update the tools (mostly renaming and removing of code) Change-Id: I1872bba7f4177fc3891180e8f944aab88f5bde31
This commit is contained in:
parent
6d64111b3c
commit
c17d30f204
10 changed files with 279 additions and 653 deletions
|
@ -21,13 +21,13 @@
|
|||
#ifndef __HWSTUB_PROTOCOL__
|
||||
#define __HWSTUB_PROTOCOL__
|
||||
|
||||
#define HWSTUB_CLASS 0xfe
|
||||
#define HWSTUB_CLASS 0xff
|
||||
#define HWSTUB_SUBCLASS 0xac
|
||||
#define HWSTUB_PROTOCOL 0x1d
|
||||
|
||||
#define HWSTUB_VERSION_MAJOR 2
|
||||
#define HWSTUB_VERSION_MINOR 11
|
||||
#define HWSTUB_VERSION_REV 2
|
||||
#define HWSTUB_VERSION_MAJOR 3
|
||||
#define HWSTUB_VERSION_MINOR 0
|
||||
#define HWSTUB_VERSION_REV 0
|
||||
|
||||
#define HWSTUB_USB_VID 0xfee1
|
||||
#define HWSTUB_USB_PID 0xdead
|
||||
|
@ -41,81 +41,77 @@
|
|||
*/
|
||||
|
||||
/* list of commands */
|
||||
#define HWSTUB_GET_INFO 0 /* mandatory */
|
||||
#define HWSTUB_GET_LOG 1 /* optional */
|
||||
#define HWSTUB_RW_MEM 2 /* optional */
|
||||
#define HWSTUB_CALL 3 /* optional */
|
||||
#define HWSTUB_JUMP 4 /* optional */
|
||||
#define HWSTUB_EXIT 5 /* optional */
|
||||
#define HWSTUB_ATEXIT 6 /* optional */
|
||||
#define HWSTUB_GET_LOG 0 /* optional */
|
||||
#define HWSTUB_RW_MEM 1 /* optional */
|
||||
#define HWSTUB_CALL 2 /* optional */
|
||||
#define HWSTUB_JUMP 3 /* optional */
|
||||
|
||||
/**
|
||||
* HWSTUB_GET_INFO: get some information about an aspect of the device.
|
||||
* The wIndex field of the SETUP specifies which information to get. */
|
||||
* Descriptors can be retrieve using configuration descriptor or individually
|
||||
* using the standard GetDescriptor request on the interface.
|
||||
*/
|
||||
|
||||
/* list of possible information */
|
||||
#define HWSTUB_INFO_VERSION 0 /* mandatory */
|
||||
#define HWSTUB_INFO_LAYOUT 1 /* mandatory */
|
||||
#define HWSTUB_INFO_STMP 2 /* optional */
|
||||
#define HWSTUB_INFO_FEATURES 3 /* mandatory */
|
||||
#define HWSTUB_INFO_TARGET 4 /* mandatory */
|
||||
#define HWSTUB_DT_VERSION 0x41 /* mandatory */
|
||||
#define HWSTUB_DT_LAYOUT 0x42 /* mandatory */
|
||||
#define HWSTUB_DT_TARGET 0x43 /* mandatory */
|
||||
#define HWSTUB_DT_STMP 0x44 /* optional */
|
||||
|
||||
struct usb_resp_info_version_t
|
||||
struct hwstub_version_desc_t
|
||||
{
|
||||
uint8_t major;
|
||||
uint8_t minor;
|
||||
uint8_t revision;
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
/* full version information */
|
||||
uint8_t bMajor;
|
||||
uint8_t bMinor;
|
||||
uint8_t bRevision;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct usb_resp_info_layout_t
|
||||
struct hwstub_layout_desc_t
|
||||
{
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
/* describe the range of memory used by the running code */
|
||||
uint32_t oc_code_start;
|
||||
uint32_t oc_code_size;
|
||||
uint32_t dCodeStart;
|
||||
uint32_t dCodeSize;
|
||||
/* describe the range of memory used by the stack */
|
||||
uint32_t oc_stack_start;
|
||||
uint32_t oc_stack_size;
|
||||
uint32_t dStackStart;
|
||||
uint32_t dStackSize;
|
||||
/* describe the range of memory available as a buffer */
|
||||
uint32_t oc_buffer_start;
|
||||
uint32_t oc_buffer_size;
|
||||
uint32_t dBufferStart;
|
||||
uint32_t dBufferSize;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct usb_resp_info_stmp_t
|
||||
struct hwstub_stmp_desc_t
|
||||
{
|
||||
uint16_t chipid; /* 0x3780 for STMP3780 for example */
|
||||
uint8_t rev; /* 0=TA1 on STMP3780 for example */
|
||||
uint8_t is_supported; /* 1 if the chip is supported */
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
/* Chip ID and revision */
|
||||
uint16_t wChipID; /* 0x3780 for STMP3780 for example */
|
||||
uint8_t bRevision; /* 0=TA1 on STMP3780 for example */
|
||||
uint8_t bPackage; /* 0=169BGA for example */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* list of possible features */
|
||||
#define HWSTUB_FEATURE_LOG (1 << 0)
|
||||
#define HWSTUB_FEATURE_MEM (1 << 1)
|
||||
#define HWSTUB_FEATURE_CALL (1 << 2)
|
||||
#define HWSTUB_FEATURE_JUMP (1 << 3)
|
||||
#define HWSTUB_FEATURE_EXIT (1 << 4)
|
||||
|
||||
struct usb_resp_info_features_t
|
||||
{
|
||||
uint32_t feature_mask;
|
||||
};
|
||||
|
||||
#define HWSTUB_TARGET_UNK ('U' | 'N' << 8 | 'K' << 16 | ' ' << 24)
|
||||
#define HWSTUB_TARGET_STMP ('S' | 'T' << 8 | 'M' << 16 | 'P' << 24)
|
||||
#define HWSTUB_TARGET_RK27 ('R' | 'K' << 8 | '2' << 16 | '7' << 24)
|
||||
|
||||
struct usb_resp_info_target_t
|
||||
struct hwstub_target_desc_t
|
||||
{
|
||||
uint32_t id;
|
||||
char name[60];
|
||||
};
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
/* Target ID and name */
|
||||
uint32_t dID;
|
||||
char bName[58];
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* HWSTUB_GET_LOG: only if has HWSTUB_FEATURE_LOG.
|
||||
* HWSTUB_GET_LOG:
|
||||
* The log is returned as part of the control transfer.
|
||||
*/
|
||||
|
||||
/**
|
||||
* HWSTUB_RW_MEM: only if has HWSTUB_FEATURE_MEM.
|
||||
* HWSTUB_RW_MEM:
|
||||
* The 32-bit address is split into two parts.
|
||||
* The low 16-bit are stored in wValue and the upper
|
||||
* 16-bit are stored in wIndex. Depending on the transfer direction,
|
||||
|
@ -124,30 +120,10 @@ struct usb_resp_info_target_t
|
|||
* possible, making it suitable to read/write registers. */
|
||||
|
||||
/**
|
||||
* HWSTUB_x: only if has HWSTUB_FEATURE_x where x=CALL or JUMP.
|
||||
* HWSTUB_{CALL,JUMP}:
|
||||
* The 32-bit address is split into two parts.
|
||||
* The low 16-bit are stored in wValue and the upper
|
||||
* 16-bit are stored in wIndex. Depending on the transfer direction,
|
||||
* the transfer is either a read or a write. */
|
||||
|
||||
/**
|
||||
* HWSTUB_EXIT: only if has HWSTUB_FEATURE_EXIT.
|
||||
* Stop hwstub now, performing the atexit action. Default exit action
|
||||
* is target dependent. */
|
||||
|
||||
/**
|
||||
* HWSTUB_ATEXIT: only if has HWSTUB_FEATURE_EXIT.
|
||||
* Sets the action to perform at exit. Exit happens by sending HWSTUB_EXIT
|
||||
* or on USB disconnection. The following actions are available:
|
||||
* - nop: don't do anything, wait for next connection
|
||||
* - reboot: reboot the device
|
||||
* - off: power off
|
||||
* NOTE the power off action might have to wait for USB disconnection as some
|
||||
* targets cannot power off while plugged.
|
||||
* NOTE appart from nop which is mandatory, all other methods can be
|
||||
* unavailable and thus the atexit command can fail. */
|
||||
#define HWSTUB_ATEXIT_REBOOT 0
|
||||
#define HWSTUB_ATEXIT_OFF 1
|
||||
#define HWSTUB_ATEXIT_NOP 2
|
||||
|
||||
#endif /* __HWSTUB_PROTOCOL__ */
|
||||
|
|
|
@ -19,69 +19,55 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
#include "hwstub.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/* requires then ->handle field only */
|
||||
int hwstub_probe(struct hwstub_device_t *dev)
|
||||
struct hwstub_device_t
|
||||
{
|
||||
libusb_device_handle *handle;
|
||||
int intf;
|
||||
int bulk_in;
|
||||
int bulk_out;
|
||||
int int_in;
|
||||
};
|
||||
|
||||
struct hwstub_device_t *hwstub_open(libusb_device_handle *handle)
|
||||
{
|
||||
struct hwstub_device_t *dev = malloc(sizeof(struct hwstub_device_t));
|
||||
memset(dev, 0, sizeof(struct hwstub_device_t));
|
||||
dev->handle = handle;
|
||||
libusb_device *mydev = libusb_get_device(dev->handle);
|
||||
|
||||
int config_id;
|
||||
libusb_get_configuration(dev->handle, &config_id);
|
||||
struct libusb_config_descriptor *config;
|
||||
libusb_get_active_config_descriptor(mydev, &config);
|
||||
struct libusb_device_descriptor dev_desc;
|
||||
libusb_get_device_descriptor(mydev, &dev_desc);
|
||||
if(dev_desc.bDeviceClass != HWSTUB_CLASS ||
|
||||
dev_desc.bDeviceSubClass != HWSTUB_SUBCLASS ||
|
||||
dev_desc.bDeviceProtocol != HWSTUB_PROTOCOL)
|
||||
goto Lerr;
|
||||
return dev;
|
||||
|
||||
const struct libusb_endpoint_descriptor *endp = NULL;
|
||||
int intf;
|
||||
for(intf = 0; intf < config->bNumInterfaces; intf++)
|
||||
{
|
||||
if(config->interface[intf].num_altsetting != 1)
|
||||
continue;
|
||||
const struct libusb_interface_descriptor *interface =
|
||||
&config->interface[intf].altsetting[0];
|
||||
if(interface->bNumEndpoints != 3 ||
|
||||
interface->bInterfaceClass != HWSTUB_CLASS ||
|
||||
interface->bInterfaceSubClass != HWSTUB_SUBCLASS ||
|
||||
interface->bInterfaceProtocol != HWSTUB_PROTOCOL)
|
||||
continue;
|
||||
dev->intf = intf;
|
||||
dev->bulk_in = dev->bulk_out = dev->int_in = -1;
|
||||
for(int ep = 0; ep < interface->bNumEndpoints; ep++)
|
||||
{
|
||||
endp = &interface->endpoint[ep];
|
||||
if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_INTERRUPT &&
|
||||
(endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
|
||||
dev->int_in = endp->bEndpointAddress;
|
||||
if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK &&
|
||||
(endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
|
||||
dev->bulk_in = endp->bEndpointAddress;
|
||||
if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK &&
|
||||
(endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
|
||||
dev->bulk_out = endp->bEndpointAddress;
|
||||
}
|
||||
if(dev->bulk_in == -1 || dev->bulk_out == -1 || dev->int_in == -1)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if(intf == config->bNumInterfaces)
|
||||
return 1;
|
||||
|
||||
return libusb_claim_interface(dev->handle, intf);
|
||||
Lerr:
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int hwstub_release(struct hwstub_device_t *dev)
|
||||
{
|
||||
return libusb_release_interface(dev->handle, dev->intf);
|
||||
free(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hwstub_get_info(struct hwstub_device_t *dev, uint16_t idx, void *info, size_t sz)
|
||||
int hwstub_get_desc(struct hwstub_device_t *dev, uint16_t desc, void *info, size_t sz)
|
||||
{
|
||||
return libusb_control_transfer(dev->handle,
|
||||
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
|
||||
HWSTUB_GET_INFO, 0, idx, info, sz, 1000);
|
||||
LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
|
||||
LIBUSB_REQUEST_GET_DESCRIPTOR, desc << 8, 0, info, sz, 1000);
|
||||
}
|
||||
|
||||
int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz)
|
||||
|
@ -126,50 +112,3 @@ int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr)
|
|||
LIBUSB_ENDPOINT_OUT, HWSTUB_JUMP, addr & 0xffff, addr >> 16, NULL, 0,
|
||||
1000);
|
||||
}
|
||||
|
||||
const char *hwstub_get_product_string(struct usb_resp_info_stmp_t *stmp)
|
||||
{
|
||||
switch(stmp->chipid)
|
||||
{
|
||||
case 0x3700: return "STMP 3700";
|
||||
case 0x37b0: return "STMP 3770";
|
||||
case 0x3780: return "STMP 3780 / i.MX233";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char *hwstub_get_rev_string(struct usb_resp_info_stmp_t *stmp)
|
||||
{
|
||||
switch(stmp->chipid)
|
||||
{
|
||||
case 0x37b0:
|
||||
case 0x3780:
|
||||
switch(stmp->rev)
|
||||
{
|
||||
case 0: return "TA1";
|
||||
case 1: return "TA2";
|
||||
case 2: return "TA3";
|
||||
case 3: return "TA4";
|
||||
default: return "unknown";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
int hwstub_atexit(struct hwstub_device_t *dev, int method)
|
||||
{
|
||||
return libusb_control_transfer(dev->handle,
|
||||
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
|
||||
LIBUSB_ENDPOINT_OUT, HWSTUB_ATEXIT, 0, method, NULL, 0,
|
||||
1000);
|
||||
}
|
||||
|
||||
int hwstub_exit(struct hwstub_device_t *dev)
|
||||
{
|
||||
return libusb_control_transfer(dev->handle,
|
||||
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
|
||||
LIBUSB_ENDPOINT_OUT, HWSTUB_EXIT, 0, 0, NULL, 0,
|
||||
1000);
|
||||
}
|
||||
|
|
|
@ -34,22 +34,15 @@ extern "C" {
|
|||
*
|
||||
*/
|
||||
|
||||
struct hwstub_device_t
|
||||
{
|
||||
libusb_device_handle *handle;
|
||||
int intf;
|
||||
int bulk_in;
|
||||
int bulk_out;
|
||||
int int_in;
|
||||
};
|
||||
struct hwstub_device_t;
|
||||
|
||||
/* Requires then ->handle field only. Returns 0 on success */
|
||||
int hwstub_probe(struct hwstub_device_t *dev);
|
||||
/* Returns 0 on success */
|
||||
/* Returns NULL on error */
|
||||
struct hwstub_device_t *hwstub_open(libusb_device_handle *handle);
|
||||
/* Returns 0 on success. Does *NOT* close the usb handle */
|
||||
int hwstub_release(struct hwstub_device_t *dev);
|
||||
|
||||
/* Returns number of bytes filled */
|
||||
int hwstub_get_info(struct hwstub_device_t *dev, uint16_t idx, void *info, size_t sz);
|
||||
int hwstub_get_desc(struct hwstub_device_t *dev, uint16_t desc, void *info, size_t sz);
|
||||
/* Returns number of bytes filled */
|
||||
int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz);
|
||||
/* Returns number of bytes written/read or <0 on error */
|
||||
|
@ -57,12 +50,6 @@ int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *bu
|
|||
/* Returns <0 on error */
|
||||
int hwstub_call(struct hwstub_device_t *dev, uint32_t addr);
|
||||
int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr);
|
||||
/* Returns <0 on error */
|
||||
int hwstub_atexit(struct hwstub_device_t *dev, int action);
|
||||
int hwstub_exit(struct hwstub_device_t *dev);
|
||||
|
||||
const char *hwstub_get_product_string(struct usb_resp_info_stmp_t *stmp);
|
||||
const char *hwstub_get_rev_string(struct usb_resp_info_stmp_t *stmp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
@ -51,16 +51,16 @@ static struct usb_device_descriptor __attribute__((aligned(2)))
|
|||
.bLength = sizeof(struct usb_device_descriptor),
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = USB_CLASS_PER_INTERFACE,
|
||||
.bDeviceSubClass = 0,
|
||||
.bDeviceProtocol = 0,
|
||||
.bDeviceClass = HWSTUB_CLASS,
|
||||
.bDeviceSubClass = HWSTUB_SUBCLASS,
|
||||
.bDeviceProtocol = HWSTUB_PROTOCOL,
|
||||
.bMaxPacketSize0 = 64,
|
||||
.idVendor = HWSTUB_USB_VID,
|
||||
.idProduct = HWSTUB_USB_PID,
|
||||
.bcdDevice = HWSTUB_VERSION_MAJOR << 8 | HWSTUB_VERSION_MINOR,
|
||||
.iManufacturer = 1,
|
||||
.iProduct = 2,
|
||||
.iSerialNumber = 3,
|
||||
.iSerialNumber = 0,
|
||||
.bNumConfigurations = 1
|
||||
};
|
||||
|
||||
|
@ -72,40 +72,13 @@ static struct usb_config_descriptor __attribute__((aligned(2)))
|
|||
.bLength = sizeof(struct usb_config_descriptor),
|
||||
.bDescriptorType = USB_DT_CONFIG,
|
||||
.wTotalLength = 0, /* will be filled in later */
|
||||
.bNumInterfaces = 1,
|
||||
.bNumInterfaces = 0,
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = 0,
|
||||
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
|
||||
.bMaxPower = (USB_MAX_CURRENT + 1) / 2, /* In 2mA units */
|
||||
};
|
||||
|
||||
/* main interface */
|
||||
static struct usb_interface_descriptor __attribute__((aligned(2)))
|
||||
interface_descriptor =
|
||||
{
|
||||
.bLength = sizeof(struct usb_interface_descriptor),
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 3,
|
||||
.bInterfaceClass = HWSTUB_CLASS,
|
||||
.bInterfaceSubClass = HWSTUB_SUBCLASS,
|
||||
.bInterfaceProtocol = HWSTUB_PROTOCOL,
|
||||
.iInterface = 4
|
||||
};
|
||||
|
||||
|
||||
static struct usb_endpoint_descriptor __attribute__((aligned(2)))
|
||||
endpoint_descriptor =
|
||||
{
|
||||
.bLength = sizeof(struct usb_endpoint_descriptor),
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||
.wMaxPacketSize = 0,
|
||||
.bInterval = 0
|
||||
};
|
||||
|
||||
static const struct usb_string_descriptor __attribute__((aligned(2)))
|
||||
usb_string_iManufacturer =
|
||||
{
|
||||
|
@ -117,33 +90,11 @@ static const struct usb_string_descriptor __attribute__((aligned(2)))
|
|||
static const struct usb_string_descriptor __attribute__((aligned(2)))
|
||||
usb_string_iProduct =
|
||||
{
|
||||
52,
|
||||
44,
|
||||
USB_DT_STRING,
|
||||
{'R', 'o', 'c', 'k', 'b', 'o', 'x', ' ',
|
||||
'h', 'a', 'r', 'd', 'w', 'a', 'r', 'e', ' ',
|
||||
'e', 'm', 'u', 'l', 'a', 't', 'e', 'r'}
|
||||
};
|
||||
|
||||
static struct usb_string_descriptor __attribute__((aligned(2)))
|
||||
usb_string_iSerial =
|
||||
{
|
||||
84,
|
||||
USB_DT_STRING,
|
||||
{'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
||||
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
||||
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
||||
'0', '0', '0', '0', '0', '0', '0', '0'}
|
||||
};
|
||||
|
||||
static struct usb_string_descriptor __attribute__((aligned(2)))
|
||||
usb_string_iInterface =
|
||||
{
|
||||
28,
|
||||
USB_DT_STRING,
|
||||
{'A', 'c', 'i', 'd', ' ',
|
||||
'0' + (HWSTUB_VERSION_MAJOR >> 4), '0' + (HWSTUB_VERSION_MAJOR & 0xf), '.',
|
||||
'0' + (HWSTUB_VERSION_MINOR >> 4), '0' + (HWSTUB_VERSION_MINOR & 0xf), '.',
|
||||
'0' + (HWSTUB_VERSION_REV >> 4), '0' + (HWSTUB_VERSION_REV & 0xf) }
|
||||
's', 't', 'u', 'b'}
|
||||
};
|
||||
|
||||
/* this is stringid #0: languages supported */
|
||||
|
@ -155,6 +106,24 @@ static const struct usb_string_descriptor __attribute__((aligned(2)))
|
|||
{0x0409} /* LANGID US English */
|
||||
};
|
||||
|
||||
static struct hwstub_version_desc_t __attribute__((aligned(2)))
|
||||
version_descriptor =
|
||||
{
|
||||
sizeof(struct hwstub_version_desc_t),
|
||||
HWSTUB_DT_VERSION,
|
||||
HWSTUB_VERSION_MAJOR,
|
||||
HWSTUB_VERSION_MINOR,
|
||||
HWSTUB_VERSION_REV
|
||||
};
|
||||
|
||||
static struct hwstub_layout_desc_t __attribute__((aligned(2)))
|
||||
layout_descriptor =
|
||||
{
|
||||
sizeof(struct hwstub_layout_desc_t),
|
||||
HWSTUB_DT_LAYOUT,
|
||||
0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
#define USB_NUM_STRINGS 5
|
||||
|
||||
static const struct usb_string_descriptor* const usb_strings[USB_NUM_STRINGS] =
|
||||
|
@ -162,26 +131,25 @@ static const struct usb_string_descriptor* const usb_strings[USB_NUM_STRINGS] =
|
|||
&lang_descriptor,
|
||||
&usb_string_iManufacturer,
|
||||
&usb_string_iProduct,
|
||||
&usb_string_iSerial,
|
||||
&usb_string_iInterface
|
||||
};
|
||||
|
||||
uint8_t *usb_buffer = oc_bufferstart;
|
||||
uint32_t usb_buffer_size = 0;
|
||||
|
||||
#define EP_BULK 1
|
||||
#define EP_INT 2
|
||||
|
||||
static void set_config(void)
|
||||
static void fill_layout_info(void)
|
||||
{
|
||||
usb_drv_configure_endpoint(EP_BULK, USB_ENDPOINT_XFER_BULK);
|
||||
usb_drv_configure_endpoint(EP_INT, USB_ENDPOINT_XFER_INT);
|
||||
layout_descriptor.dCodeStart = (uint32_t)oc_codestart;
|
||||
layout_descriptor.dCodeSize = oc_codesize;
|
||||
layout_descriptor.dStackStart = (uint32_t)oc_stackstart;
|
||||
layout_descriptor.dStackSize = oc_stacksize;
|
||||
layout_descriptor.dBufferStart = (uint32_t)oc_bufferstart;
|
||||
layout_descriptor.dBufferSize = oc_buffersize;
|
||||
}
|
||||
|
||||
static void handle_std_dev_desc(struct usb_ctrlrequest *req)
|
||||
{
|
||||
int size;
|
||||
const void* ptr = NULL;
|
||||
void* ptr = NULL;
|
||||
unsigned index = req->wValue & 0xff;
|
||||
|
||||
switch(req->wValue >> 8)
|
||||
|
@ -208,32 +176,22 @@ static void handle_std_dev_desc(struct usb_ctrlrequest *req)
|
|||
}
|
||||
size = sizeof(struct usb_config_descriptor);
|
||||
|
||||
/* interface */
|
||||
memcpy(usb_buffer + size, (void *)&interface_descriptor,
|
||||
sizeof(interface_descriptor));
|
||||
size += sizeof(interface_descriptor);
|
||||
/* endpoint 1: bulk out */
|
||||
endpoint_descriptor.bEndpointAddress = EP_BULK | USB_DIR_OUT;
|
||||
endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_BULK;
|
||||
endpoint_descriptor.wMaxPacketSize = 512;
|
||||
memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
|
||||
sizeof(endpoint_descriptor));
|
||||
size += sizeof(endpoint_descriptor);
|
||||
/* endpoint 2: bulk in */
|
||||
endpoint_descriptor.bEndpointAddress = EP_BULK | USB_DIR_IN;
|
||||
endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_BULK;
|
||||
endpoint_descriptor.wMaxPacketSize = 512;
|
||||
memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
|
||||
sizeof(endpoint_descriptor));
|
||||
size += sizeof(endpoint_descriptor);
|
||||
/* endpoint 3: int in */
|
||||
endpoint_descriptor.bEndpointAddress = EP_INT | USB_DIR_IN;
|
||||
endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_INT;
|
||||
endpoint_descriptor.wMaxPacketSize = 1024;
|
||||
memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
|
||||
sizeof(endpoint_descriptor));
|
||||
size += sizeof(endpoint_descriptor);
|
||||
|
||||
/* hwstub version */
|
||||
memcpy(usb_buffer + size, (void *)&version_descriptor,
|
||||
sizeof(version_descriptor));
|
||||
size += sizeof(version_descriptor);
|
||||
/* hwstub layout */
|
||||
fill_layout_info();
|
||||
memcpy(usb_buffer + size, (void *)&layout_descriptor,
|
||||
sizeof(layout_descriptor));
|
||||
size += sizeof(layout_descriptor);
|
||||
/* hwstub target */
|
||||
fill_layout_info();
|
||||
memcpy(usb_buffer + size, (void *)&target_descriptor,
|
||||
sizeof(target_descriptor));
|
||||
size += sizeof(target_descriptor);
|
||||
/* target specific descriptors */
|
||||
target_get_config_desc(usb_buffer + size, &size);
|
||||
/* fix config descriptor */
|
||||
config_descriptor.bNumInterfaces = 1;
|
||||
config_descriptor.wTotalLength = size;
|
||||
|
@ -246,12 +204,27 @@ static void handle_std_dev_desc(struct usb_ctrlrequest *req)
|
|||
if(index < USB_NUM_STRINGS)
|
||||
{
|
||||
size = usb_strings[index]->bLength;
|
||||
ptr = usb_strings[index];
|
||||
ptr = (void *)usb_strings[index];
|
||||
}
|
||||
else
|
||||
usb_drv_stall(EP_CONTROL, true, true);
|
||||
break;
|
||||
case HWSTUB_DT_VERSION:
|
||||
ptr = &version_descriptor;
|
||||
size = sizeof(version_descriptor);
|
||||
break;
|
||||
case HWSTUB_DT_LAYOUT:
|
||||
ptr = &layout_descriptor;
|
||||
size = sizeof(layout_descriptor);
|
||||
break;
|
||||
case HWSTUB_DT_TARGET:
|
||||
ptr = &target_descriptor;
|
||||
size = sizeof(target_descriptor);
|
||||
break;
|
||||
default:
|
||||
target_get_desc(req->wValue >> 8, &ptr);
|
||||
if(ptr != 0)
|
||||
size = ((struct usb_descriptor_header *)ptr)->bLength;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -280,7 +253,6 @@ static void handle_std_dev_req(struct usb_ctrlrequest *req)
|
|||
break;
|
||||
case USB_REQ_SET_CONFIGURATION:
|
||||
usb_drv_send(EP_CONTROL, NULL, 0);
|
||||
set_config();
|
||||
break;
|
||||
case USB_REQ_GET_DESCRIPTOR:
|
||||
handle_std_dev_desc(req);
|
||||
|
@ -311,67 +283,6 @@ static void handle_std_req(struct usb_ctrlrequest *req)
|
|||
}
|
||||
}
|
||||
|
||||
struct usb_resp_info_version_t g_version =
|
||||
{
|
||||
.major = HWSTUB_VERSION_MAJOR,
|
||||
.minor = HWSTUB_VERSION_MINOR,
|
||||
.revision = HWSTUB_VERSION_REV
|
||||
};
|
||||
|
||||
struct usb_resp_info_layout_t g_layout;
|
||||
|
||||
struct usb_resp_info_features_t g_features =
|
||||
{
|
||||
.feature_mask = HWSTUB_FEATURE_LOG | HWSTUB_FEATURE_MEM |
|
||||
HWSTUB_FEATURE_CALL | HWSTUB_FEATURE_JUMP
|
||||
};
|
||||
|
||||
static void fill_layout_info(void)
|
||||
{
|
||||
g_layout.oc_code_start = (uint32_t)oc_codestart;
|
||||
g_layout.oc_code_size = oc_codesize;
|
||||
g_layout.oc_stack_start = (uint32_t)oc_stackstart;
|
||||
g_layout.oc_stack_size = oc_stacksize;
|
||||
g_layout.oc_buffer_start = (uint32_t)oc_bufferstart;
|
||||
g_layout.oc_buffer_size = oc_buffersize;
|
||||
}
|
||||
|
||||
static void handle_get_info(struct usb_ctrlrequest *req)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
int size = 0;
|
||||
switch(req->wIndex)
|
||||
{
|
||||
case HWSTUB_INFO_VERSION:
|
||||
ptr = &g_version;
|
||||
size = sizeof(g_version);
|
||||
break;
|
||||
case HWSTUB_INFO_LAYOUT:
|
||||
fill_layout_info();
|
||||
ptr = &g_layout;
|
||||
size = sizeof(g_layout);
|
||||
break;
|
||||
case HWSTUB_INFO_FEATURES:
|
||||
ptr = &g_features;
|
||||
size = sizeof(g_features);
|
||||
break;
|
||||
default:
|
||||
size = target_get_info(req->wIndex, &ptr);
|
||||
if(size < 0)
|
||||
usb_drv_stall(EP_CONTROL, true, true);
|
||||
}
|
||||
|
||||
if(ptr)
|
||||
{
|
||||
int length = MIN(size, req->wLength);
|
||||
|
||||
if(ptr != usb_buffer)
|
||||
memcpy(usb_buffer, ptr, length);
|
||||
usb_drv_send(EP_CONTROL, usb_buffer, length);
|
||||
usb_drv_recv(EP_CONTROL, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_get_log(struct usb_ctrlrequest *req)
|
||||
{
|
||||
enable_logf(false);
|
||||
|
@ -421,28 +332,10 @@ static void handle_call_jump(struct usb_ctrlrequest *req)
|
|||
}
|
||||
}
|
||||
|
||||
static void handle_atexit(struct usb_ctrlrequest *req)
|
||||
{
|
||||
if(target_atexit(req->wIndex) < 0)
|
||||
usb_drv_stall(EP_CONTROL, true, true);
|
||||
else
|
||||
usb_drv_send(EP_CONTROL, NULL, 0);
|
||||
}
|
||||
|
||||
static void handle_exit(struct usb_ctrlrequest *req)
|
||||
{
|
||||
(void)req;
|
||||
usb_drv_send(EP_CONTROL, NULL, 0);
|
||||
g_exit = true;
|
||||
}
|
||||
|
||||
static void handle_class_dev_req(struct usb_ctrlrequest *req)
|
||||
{
|
||||
switch(req->bRequest)
|
||||
{
|
||||
case HWSTUB_GET_INFO:
|
||||
handle_get_info(req);
|
||||
break;
|
||||
case HWSTUB_GET_LOG:
|
||||
handle_get_log(req);
|
||||
break;
|
||||
|
@ -453,11 +346,6 @@ static void handle_class_dev_req(struct usb_ctrlrequest *req)
|
|||
case HWSTUB_JUMP:
|
||||
handle_call_jump(req);
|
||||
break;
|
||||
case HWSTUB_ATEXIT:
|
||||
handle_atexit(req);
|
||||
break;
|
||||
case HWSTUB_EXIT:
|
||||
handle_exit(req);
|
||||
break;
|
||||
default:
|
||||
usb_drv_stall(EP_CONTROL, true, true);
|
||||
|
@ -510,5 +398,4 @@ void main(uint32_t arg)
|
|||
}
|
||||
}
|
||||
usb_drv_exit();
|
||||
target_exit();
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ enum rk27xx_family_t
|
|||
};
|
||||
|
||||
static enum rk27xx_family_t g_rk27xx_family = UNKNOWN;
|
||||
static int g_atexit = HWSTUB_ATEXIT_OFF;
|
||||
|
||||
static void _enable_irq(void)
|
||||
{
|
||||
|
@ -43,23 +42,6 @@ static void _enable_irq(void)
|
|||
);
|
||||
}
|
||||
|
||||
static void power_off(void)
|
||||
{
|
||||
GPIO_PCCON &= ~(1<<0);
|
||||
while(1);
|
||||
}
|
||||
|
||||
static void rk27xx_reset(void)
|
||||
{
|
||||
/* use Watchdog to reset */
|
||||
SCU_CLKCFG &= ~CLKCFG_WDT;
|
||||
WDTLR = 1;
|
||||
WDTCON = (1<<4) | (1<<3);
|
||||
|
||||
/* Wait for reboot to kick in */
|
||||
while(1);
|
||||
}
|
||||
|
||||
/* us may be at most 2^31/200 (~10 seconds) for 200MHz max cpu freq */
|
||||
void target_udelay(int us)
|
||||
{
|
||||
|
@ -132,41 +114,22 @@ void target_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
static struct usb_resp_info_target_t g_target =
|
||||
struct hwstub_target_desc_t __attribute__((aligned(2))) target_descriptor =
|
||||
{
|
||||
.id = HWSTUB_TARGET_RK27,
|
||||
.name = "Rockchip RK27XX"
|
||||
sizeof(struct hwstub_target_desc_t),
|
||||
HWSTUB_DT_TARGET,
|
||||
HWSTUB_TARGET_RK27,
|
||||
"Rockchip RK27XX"
|
||||
};
|
||||
|
||||
int target_get_info(int info, void **buffer)
|
||||
void target_get_desc(int desc, void **buffer)
|
||||
{
|
||||
if(info == HWSTUB_INFO_TARGET)
|
||||
{
|
||||
*buffer = &g_target;
|
||||
return sizeof(g_target);
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
(void) desc;
|
||||
*buffer = NULL;
|
||||
}
|
||||
|
||||
int target_atexit(int method)
|
||||
void target_get_config_desc(void *buffer, int *size)
|
||||
{
|
||||
g_atexit = method;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void target_exit(void)
|
||||
{
|
||||
switch(g_atexit)
|
||||
{
|
||||
case HWSTUB_ATEXIT_OFF:
|
||||
power_off();
|
||||
// fallthrough in case of return
|
||||
case HWSTUB_ATEXIT_REBOOT:
|
||||
rk27xx_reset();
|
||||
// fallthrough in case of return
|
||||
case HWSTUB_ATEXIT_NOP:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
(void) buffer;
|
||||
(void) size;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "target.h"
|
||||
#include "system.h"
|
||||
#include "logf.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define __REG_SET(reg) (*((volatile uint32_t *)(® + 1)))
|
||||
#define __REG_CLR(reg) (*((volatile uint32_t *)(® + 2)))
|
||||
|
@ -50,34 +51,6 @@ enum stmp_family_t
|
|||
};
|
||||
|
||||
static enum stmp_family_t g_stmp_family = UNKNOWN;
|
||||
static int g_atexit = HWSTUB_ATEXIT_OFF;
|
||||
|
||||
/**
|
||||
*
|
||||
* Power
|
||||
*
|
||||
*/
|
||||
|
||||
#define HW_POWER_BASE 0x80044000
|
||||
|
||||
void power_off(void)
|
||||
{
|
||||
switch(g_stmp_family)
|
||||
{
|
||||
case STMP3600:
|
||||
*(volatile uint32_t *)(HW_POWER_BASE + 0xc0) = 0x3e770014;
|
||||
break;
|
||||
case STMP3700:
|
||||
case STMP3770:
|
||||
*(volatile uint32_t *)(HW_POWER_BASE + 0xe0) = 0x3e770001;
|
||||
break;
|
||||
case STMP3780:
|
||||
*(volatile uint32_t *)(HW_POWER_BASE + 0x100) = 0x3e770001;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -114,25 +87,6 @@ void power_off(void)
|
|||
#define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE (1 << 30)
|
||||
#define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE (1 << 31)
|
||||
|
||||
void clkctrl_reset(void)
|
||||
{
|
||||
switch(g_stmp_family)
|
||||
{
|
||||
case STMP3600:
|
||||
*(volatile uint32_t *)(HW_POWER_BASE + 0xc0) = 0x3e770002;
|
||||
break;
|
||||
case STMP3700:
|
||||
case STMP3770:
|
||||
*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xf0) = 0x1;
|
||||
break;
|
||||
case STMP3780:
|
||||
*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x120) = 0x1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Digctl
|
||||
|
@ -143,11 +97,18 @@ void clkctrl_reset(void)
|
|||
#define HW_DIGCTL_BASE 0x8001C000
|
||||
#define HW_DIGCTL_CTRL (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0))
|
||||
#define HW_DIGCTL_CTRL__USB_CLKGATE (1 << 2)
|
||||
#define HW_DIGCTL_CTRL__PACKAGE_SENSE_ENABLE_STMP3600 (1 << 0)
|
||||
|
||||
#define HW_DIGCTL_STATUS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x10))
|
||||
#define HW_DIGCTL_STATUS__PACKAGE_TYPE_BP 1
|
||||
#define HW_DIGCTL_STATUS__PACKAGE_TYPE_BM (7 << 1)
|
||||
#define HW_DIGCTL_STATUS__PACKAGE_TYPE_STMP3600_BP 1
|
||||
#define HW_DIGCTL_STATUS__PACKAGE_TYPE_STMP3600_BM (1 << 1)
|
||||
|
||||
/* STMP3700+ */
|
||||
#define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0))
|
||||
/* STMP3600 */
|
||||
#define HW_DIGCTL_MICROSECONDS2 (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xB0))
|
||||
#define HW_DIGCTL_MICROSECONDS_STMP3600 (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xB0))
|
||||
|
||||
#define HW_DIGCTL_CHIPID (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x310))
|
||||
#define HW_DIGCTL_CHIPID__PRODUCT_CODE_BP 16
|
||||
|
@ -177,8 +138,25 @@ void clkctrl_reset(void)
|
|||
#define HW_RTC_CTRL (*(volatile uint32_t *)(HW_RTC_BASE + 0))
|
||||
#define HW_RTC_CTRL__WATCHDOGEN (1 << 4)
|
||||
|
||||
struct hwstub_target_desc_t __attribute__((aligned(2))) target_descriptor =
|
||||
{
|
||||
sizeof(struct hwstub_target_desc_t),
|
||||
HWSTUB_DT_TARGET,
|
||||
HWSTUB_TARGET_STMP,
|
||||
"STMP3600 / STMP3700 / STMP3780 (i.MX233)"
|
||||
};
|
||||
|
||||
static struct hwstub_stmp_desc_t __attribute__((aligned(2))) stmp_descriptor =
|
||||
{
|
||||
sizeof(struct hwstub_stmp_desc_t),
|
||||
HWSTUB_DT_STMP,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
void target_init(void)
|
||||
{
|
||||
stmp_descriptor.wChipID = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE);
|
||||
stmp_descriptor.bRevision = __XTRACT(HW_DIGCTL_CHIPID, REVISION);
|
||||
/* detect family */
|
||||
uint16_t product_code = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE);
|
||||
if(product_code >= 0x3600 && product_code < 0x3700)
|
||||
|
@ -208,6 +186,7 @@ void target_init(void)
|
|||
|
||||
if(g_stmp_family == STMP3600)
|
||||
{
|
||||
stmp_descriptor.bPackage = __XTRACT(HW_DIGCTL_STATUS, PACKAGE_TYPE);
|
||||
/* CPU clock is always derived from PLL, if we switch to PLL, cpu will
|
||||
* run at 480 MHz unprepared ! That's bad so prepare to run at slow sleed
|
||||
* (1.2MHz) for a safe transition */
|
||||
|
@ -230,7 +209,13 @@ void target_init(void)
|
|||
__REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
__REG_SET(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__PACKAGE_SENSE_ENABLE_STMP3600;
|
||||
stmp_descriptor.bPackage = __XTRACT(HW_DIGCTL_STATUS, PACKAGE_TYPE_STMP3600);
|
||||
__REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__PACKAGE_SENSE_ENABLE_STMP3600;
|
||||
|
||||
__REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER;
|
||||
}
|
||||
/* enable USB PHY PLL */
|
||||
__REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS;
|
||||
/* power up USB PHY */
|
||||
|
@ -240,57 +225,24 @@ void target_init(void)
|
|||
__REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE;
|
||||
}
|
||||
|
||||
static struct usb_resp_info_stmp_t g_stmp;
|
||||
static struct usb_resp_info_target_t g_target =
|
||||
void target_get_desc(int desc, void **buffer)
|
||||
{
|
||||
.id = HWSTUB_TARGET_STMP,
|
||||
.name = "STMP3600 / STMP3700 / STMP3780 (i.MX233)"
|
||||
};
|
||||
|
||||
int target_get_info(int info, void **buffer)
|
||||
{
|
||||
if(info == HWSTUB_INFO_STMP)
|
||||
{
|
||||
g_stmp.chipid = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE);
|
||||
g_stmp.rev = __XTRACT(HW_DIGCTL_CHIPID, REVISION);
|
||||
g_stmp.is_supported = g_stmp_family != 0;
|
||||
*buffer = &g_stmp;
|
||||
return sizeof(g_stmp);
|
||||
}
|
||||
else if(info == HWSTUB_INFO_TARGET)
|
||||
{
|
||||
*buffer = &g_target;
|
||||
return sizeof(g_target);
|
||||
}
|
||||
if(desc == HWSTUB_DT_STMP)
|
||||
*buffer = &stmp_descriptor;
|
||||
else
|
||||
return -1;
|
||||
*buffer = NULL;
|
||||
}
|
||||
|
||||
int target_atexit(int method)
|
||||
void target_get_config_desc(void *buffer, int *size)
|
||||
{
|
||||
g_atexit = method;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void target_exit(void)
|
||||
{
|
||||
switch(g_atexit)
|
||||
{
|
||||
case HWSTUB_ATEXIT_OFF:
|
||||
power_off();
|
||||
// fallthrough in case of return
|
||||
case HWSTUB_ATEXIT_REBOOT:
|
||||
clkctrl_reset();
|
||||
// fallthrough in case of return
|
||||
case HWSTUB_ATEXIT_NOP:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
memcpy(buffer, &stmp_descriptor, sizeof(stmp_descriptor));
|
||||
*size += sizeof(stmp_descriptor);
|
||||
}
|
||||
|
||||
void target_udelay(int us)
|
||||
{
|
||||
volatile uint32_t *reg = g_stmp_family == STMP3600 ? &HW_DIGCTL_MICROSECONDS2 : &HW_DIGCTL_MICROSECONDS;
|
||||
volatile uint32_t *reg = g_stmp_family == STMP3600 ?
|
||||
&HW_DIGCTL_MICROSECONDS_STMP3600 : &HW_DIGCTL_MICROSECONDS;
|
||||
uint32_t cur = *reg;
|
||||
uint32_t end = cur + us;
|
||||
if(cur < end)
|
||||
|
|
|
@ -25,15 +25,16 @@
|
|||
|
||||
/* do target specific init */
|
||||
void target_init(void);
|
||||
/* exit, performing the atexit action (default is target specific) */
|
||||
void target_exit(void);
|
||||
/* get information, return actual size or -1 if error */
|
||||
int target_get_info(int info, void **buffer);
|
||||
/* set atexit action or return -1 on error */
|
||||
int target_atexit(int action);
|
||||
/* get descriptor, set buffer to NULL on error */
|
||||
void target_get_desc(int desc, void **buffer);
|
||||
/* pack all descriptors for config desc */
|
||||
void target_get_config_desc(void *buffer, int *size);
|
||||
/* Wait a very short time (us<=1000) */
|
||||
void target_udelay(int us);
|
||||
/* Wait for a short time (ms <= 1000) */
|
||||
void target_mdelay(int ms);
|
||||
|
||||
/* mandatory for all targets */
|
||||
extern struct hwstub_target_desc_t target_descriptor;
|
||||
|
||||
#endif /* __TARGET_H__ */
|
||||
|
|
|
@ -121,7 +121,7 @@ void usage(void)
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
bool quiet = false;
|
||||
struct hwstub_device_t hwdev;
|
||||
struct hwstub_device_t *hwdev;
|
||||
enum image_type_t type = IT_DETECT;
|
||||
|
||||
// parse command line
|
||||
|
@ -244,73 +244,52 @@ int main(int argc, char **argv)
|
|||
libusb_get_bus_number(mydev),
|
||||
libusb_get_device_address(mydev));
|
||||
}
|
||||
hwdev.handle = handle;
|
||||
if(hwstub_probe(&hwdev))
|
||||
hwdev = hwstub_open(handle);
|
||||
if(hwdev == NULL)
|
||||
{
|
||||
fprintf(stderr, "Cannot probe device!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get hwstub information
|
||||
struct usb_resp_info_version_t hwdev_ver;
|
||||
int ret = hwstub_get_info(&hwdev, HWSTUB_INFO_VERSION, &hwdev_ver, sizeof(hwdev_ver));
|
||||
struct hwstub_version_desc_t hwdev_ver;
|
||||
int ret = hwstub_get_desc(hwdev, HWSTUB_DT_VERSION, &hwdev_ver, sizeof(hwdev_ver));
|
||||
if(ret != sizeof(hwdev_ver))
|
||||
{
|
||||
fprintf(stderr, "Cannot get version!\n");
|
||||
goto Lerr;
|
||||
}
|
||||
if(hwdev_ver.major != HWSTUB_VERSION_MAJOR || hwdev_ver.minor < HWSTUB_VERSION_MINOR)
|
||||
if(hwdev_ver.bMajor != HWSTUB_VERSION_MAJOR || hwdev_ver.bMinor < HWSTUB_VERSION_MINOR)
|
||||
{
|
||||
printf("Warning: this tool is possibly incompatible with your device:\n");
|
||||
printf("Device version: %d.%d.%d\n", hwdev_ver.major, hwdev_ver.minor, hwdev_ver.revision);
|
||||
printf("Device version: %d.%d.%d\n", hwdev_ver.bMajor, hwdev_ver.bMinor, hwdev_ver.bRevision);
|
||||
printf("Host version: %d.%d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR, HWSTUB_VERSION_REV);
|
||||
}
|
||||
|
||||
// get features
|
||||
struct usb_resp_info_features_t hwdev_features;
|
||||
ret = hwstub_get_info(&hwdev, HWSTUB_INFO_FEATURES, &hwdev_features, sizeof(hwdev_features));
|
||||
if(ret != sizeof(hwdev_features))
|
||||
{
|
||||
fprintf(stderr, "Cannot get features: %d\n", ret);
|
||||
goto Lerr;
|
||||
}
|
||||
if(!(hwdev_features.feature_mask & HWSTUB_RW_MEM))
|
||||
{
|
||||
fprintf(stderr, "Device doesn't support R/W commands\n");
|
||||
goto Lerr;
|
||||
}
|
||||
if(!(hwdev_features.feature_mask & HWSTUB_JUMP))
|
||||
{
|
||||
fprintf(stderr, "Device doesn't support jump commands\n");
|
||||
goto Lerr;
|
||||
}
|
||||
ret = hwstub_rw_mem(&hwdev, 0, addr, buffer, size);
|
||||
ret = hwstub_rw_mem(hwdev, 0, addr, buffer, size);
|
||||
if(ret != (int)size)
|
||||
{
|
||||
fprintf(stderr, "Image write failed\n");
|
||||
goto Lerr;
|
||||
}
|
||||
hwstub_jump(&hwdev, addr);
|
||||
hwstub_jump(hwdev, addr);
|
||||
|
||||
hwstub_release(&hwdev);
|
||||
hwstub_release(hwdev);
|
||||
return 0;
|
||||
|
||||
Lerr:
|
||||
// display log if handled
|
||||
if(hwdev_features.feature_mask & HWSTUB_FEATURE_LOG)
|
||||
fprintf(stderr, "Device log:\n");
|
||||
do
|
||||
{
|
||||
fprintf(stderr, "Device log:\n");
|
||||
do
|
||||
{
|
||||
char buffer[128];
|
||||
int length = hwstub_get_log(&hwdev, buffer, sizeof(buffer) - 1);
|
||||
if(length <= 0)
|
||||
break;
|
||||
buffer[length] = 0;
|
||||
fprintf(stderr, "%s", buffer);
|
||||
}while(1);
|
||||
}
|
||||
hwstub_release(&hwdev);
|
||||
char buffer[128];
|
||||
int length = hwstub_get_log(hwdev, buffer, sizeof(buffer) - 1);
|
||||
if(length <= 0)
|
||||
break;
|
||||
buffer[length] = 0;
|
||||
fprintf(stderr, "%s", buffer);
|
||||
}while(1);
|
||||
hwstub_release(hwdev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,12 +39,11 @@
|
|||
*/
|
||||
bool g_quiet = false;
|
||||
bool g_exit = false;
|
||||
struct hwstub_device_t g_hwdev;
|
||||
struct usb_resp_info_version_t g_hwdev_ver;
|
||||
struct usb_resp_info_layout_t g_hwdev_layout;
|
||||
struct usb_resp_info_features_t g_hwdev_features;
|
||||
struct usb_resp_info_target_t g_hwdev_target;
|
||||
struct usb_resp_info_stmp_t g_hwdev_stmp;
|
||||
struct hwstub_device_t *g_hwdev;
|
||||
struct hwstub_version_desc_t g_hwdev_ver;
|
||||
struct hwstub_layout_desc_t g_hwdev_layout;
|
||||
struct hwstub_target_desc_t g_hwdev_target;
|
||||
struct hwstub_stmp_desc_t g_hwdev_stmp;
|
||||
lua_State *g_lua;
|
||||
|
||||
/**
|
||||
|
@ -144,7 +143,7 @@ typedef void (*hw_writen_fn_t)(lua_State *state, soc_addr_t addr, soc_word_t val
|
|||
soc_word_t hw_read8(lua_State *state, soc_addr_t addr)
|
||||
{
|
||||
uint8_t u;
|
||||
if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
|
||||
if(hwstub_rw_mem(g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
|
||||
luaL_error(state, "fail to read8 @ %p", addr);
|
||||
return u;
|
||||
}
|
||||
|
@ -152,7 +151,7 @@ soc_word_t hw_read8(lua_State *state, soc_addr_t addr)
|
|||
soc_word_t hw_read16(lua_State *state, soc_addr_t addr)
|
||||
{
|
||||
uint16_t u;
|
||||
if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
|
||||
if(hwstub_rw_mem(g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
|
||||
luaL_error(state, "fail to read16 @ %p", addr);
|
||||
return u;
|
||||
}
|
||||
|
@ -160,7 +159,7 @@ soc_word_t hw_read16(lua_State *state, soc_addr_t addr)
|
|||
soc_word_t hw_read32(lua_State *state, soc_addr_t addr)
|
||||
{
|
||||
uint32_t u;
|
||||
if(hwstub_rw_mem(&g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
|
||||
if(hwstub_rw_mem(g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u))
|
||||
luaL_error(state, "fail to read32 @ %p", addr);
|
||||
return u;
|
||||
}
|
||||
|
@ -168,21 +167,21 @@ soc_word_t hw_read32(lua_State *state, soc_addr_t addr)
|
|||
void hw_write8(lua_State *state, soc_addr_t addr, soc_word_t val)
|
||||
{
|
||||
uint8_t u = val;
|
||||
if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
|
||||
if(hwstub_rw_mem(g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
|
||||
luaL_error(state, "fail to write8 @ %p", addr);
|
||||
}
|
||||
|
||||
void hw_write16(lua_State *state, soc_addr_t addr, soc_word_t val)
|
||||
{
|
||||
uint16_t u = val;
|
||||
if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
|
||||
if(hwstub_rw_mem(g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
|
||||
luaL_error(state, "fail to write16 @ %p", addr);
|
||||
}
|
||||
|
||||
void hw_write32(lua_State *state, soc_addr_t addr, soc_word_t val)
|
||||
{
|
||||
uint32_t u = val;
|
||||
if(hwstub_rw_mem(&g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
|
||||
if(hwstub_rw_mem(g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u))
|
||||
luaL_error(state, "fail to write32 @ %p", addr);
|
||||
}
|
||||
|
||||
|
@ -208,34 +207,7 @@ int my_lua_writen(lua_State *state)
|
|||
|
||||
int my_lua_printlog(lua_State *state)
|
||||
{
|
||||
print_log(&g_hwdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int my_lua_atexit(lua_State *state)
|
||||
{
|
||||
int n = lua_gettop(state);
|
||||
if(n != 1)
|
||||
luaL_error(state, "atexit takes one argument");
|
||||
const char *arg = luaL_checkstring(state, 1);
|
||||
int ret = -1;
|
||||
if(strcmp(arg, "nop") == 0)
|
||||
ret = hwstub_atexit(&g_hwdev, HWSTUB_ATEXIT_NOP);
|
||||
else if(strcmp(arg, "reboot") == 0)
|
||||
ret = hwstub_atexit(&g_hwdev, HWSTUB_ATEXIT_REBOOT);
|
||||
else if(strcmp(arg, "off") == 0)
|
||||
ret = hwstub_atexit(&g_hwdev, HWSTUB_ATEXIT_OFF);
|
||||
else
|
||||
luaL_error(state, "unknown atexit method '%s'", arg);
|
||||
if(ret < 0)
|
||||
luaL_error(state, "fail to set atexit method");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int my_lua_exit(lua_State *state)
|
||||
{
|
||||
if(hwstub_exit(&g_hwdev) < 0)
|
||||
luaL_error(state, "fail to exit hwstub");
|
||||
print_log(g_hwdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -268,69 +240,60 @@ bool my_lua_import_hwstub()
|
|||
|
||||
lua_newtable(g_lua); // dev
|
||||
lua_newtable(g_lua); // version
|
||||
lua_pushinteger(g_lua, g_hwdev_ver.major);
|
||||
lua_pushinteger(g_lua, g_hwdev_ver.bMajor);
|
||||
lua_setfield(g_lua, -2, "major");
|
||||
lua_pushinteger(g_lua, g_hwdev_ver.minor);
|
||||
lua_pushinteger(g_lua, g_hwdev_ver.bMinor);
|
||||
lua_setfield(g_lua, -2, "minor");
|
||||
lua_pushinteger(g_lua, g_hwdev_ver.revision);
|
||||
lua_pushinteger(g_lua, g_hwdev_ver.bRevision);
|
||||
lua_setfield(g_lua, -2, "revision");
|
||||
lua_setfield(g_lua, -2, "version");
|
||||
|
||||
lua_newtable(g_lua); // layout
|
||||
lua_newtable(g_lua); // ocram
|
||||
lua_newtable(g_lua); // code
|
||||
lua_pushinteger(g_lua, g_hwdev_layout.oc_code_start);
|
||||
lua_pushinteger(g_lua, g_hwdev_layout.dCodeStart);
|
||||
lua_setfield(g_lua, -2, "start");
|
||||
lua_pushinteger(g_lua, g_hwdev_layout.oc_code_size);
|
||||
lua_pushinteger(g_lua, g_hwdev_layout.dCodeSize);
|
||||
lua_setfield(g_lua, -2, "size");
|
||||
lua_setfield(g_lua, -2, "code");
|
||||
lua_newtable(g_lua); // stack
|
||||
lua_pushinteger(g_lua, g_hwdev_layout.oc_stack_start);
|
||||
lua_pushinteger(g_lua, g_hwdev_layout.dStackStart);
|
||||
lua_setfield(g_lua, -2, "start");
|
||||
lua_pushinteger(g_lua, g_hwdev_layout.oc_stack_size);
|
||||
lua_pushinteger(g_lua, g_hwdev_layout.dStackSize);
|
||||
lua_setfield(g_lua, -2, "size");
|
||||
lua_setfield(g_lua, -2, "stack");
|
||||
lua_newtable(g_lua); // buffer
|
||||
lua_pushinteger(g_lua, g_hwdev_layout.oc_buffer_start);
|
||||
lua_pushinteger(g_lua, g_hwdev_layout.dBufferStart);
|
||||
lua_setfield(g_lua, -2, "start");
|
||||
lua_pushinteger(g_lua, g_hwdev_layout.oc_buffer_size);
|
||||
lua_pushinteger(g_lua, g_hwdev_layout.dBufferSize);
|
||||
lua_setfield(g_lua, -2, "size");
|
||||
lua_setfield(g_lua, -2, "buffer");
|
||||
lua_setfield(g_lua, -2, "ocram");
|
||||
lua_setfield(g_lua, -2, "layout");
|
||||
|
||||
lua_newtable(g_lua); // target
|
||||
lua_pushstring(g_lua, g_hwdev_target.name);
|
||||
lua_pushstring(g_lua, g_hwdev_target.bName);
|
||||
lua_setfield(g_lua, -2, "name");
|
||||
lua_pushinteger(g_lua, g_hwdev_target.id);
|
||||
lua_pushinteger(g_lua, g_hwdev_target.dID);
|
||||
lua_setfield(g_lua, -2, "id");
|
||||
lua_pushinteger(g_lua, HWSTUB_TARGET_UNK);
|
||||
lua_setfield(g_lua, -2, "UNK");
|
||||
lua_pushinteger(g_lua, HWSTUB_TARGET_STMP);
|
||||
lua_setfield(g_lua, -2, "STMP");
|
||||
lua_pushinteger(g_lua, HWSTUB_TARGET_RK27);
|
||||
lua_setfield(g_lua, -2, "RK27");
|
||||
lua_setfield(g_lua, -2, "target");
|
||||
|
||||
if(g_hwdev_target.id == HWSTUB_TARGET_STMP)
|
||||
if(g_hwdev_target.dID == HWSTUB_TARGET_STMP)
|
||||
{
|
||||
lua_newtable(g_lua); // stmp
|
||||
lua_pushinteger(g_lua, g_hwdev_stmp.chipid);
|
||||
lua_pushinteger(g_lua, g_hwdev_stmp.wChipID);
|
||||
lua_setfield(g_lua, -2, "chipid");
|
||||
lua_pushinteger(g_lua, g_hwdev_stmp.rev);
|
||||
lua_pushinteger(g_lua, g_hwdev_stmp.bRevision);
|
||||
lua_setfield(g_lua, -2, "rev");
|
||||
lua_pushinteger(g_lua, g_hwdev_stmp.bPackage);
|
||||
lua_setfield(g_lua, -2, "package");
|
||||
lua_setfield(g_lua, -2, "stmp");
|
||||
}
|
||||
|
||||
lua_newtable(g_lua); // features
|
||||
lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_LOG));
|
||||
lua_setfield(g_lua, -2, "log");
|
||||
lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_MEM));
|
||||
lua_setfield(g_lua, -2, "mem");
|
||||
lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_CALL));
|
||||
lua_setfield(g_lua, -2, "call");
|
||||
lua_pushboolean(g_lua, !!(g_hwdev_features.feature_mask & HWSTUB_FEATURE_JUMP));
|
||||
lua_setfield(g_lua, -2, "jump");
|
||||
lua_setfield(g_lua, -2, "features");
|
||||
|
||||
lua_pushlightuserdata(g_lua, (void *)&hw_read8);
|
||||
lua_pushcclosure(g_lua, my_lua_readn, 1);
|
||||
lua_setfield(g_lua, -2, "read8");
|
||||
|
@ -352,10 +315,6 @@ bool my_lua_import_hwstub()
|
|||
lua_setfield(g_lua, -2, "write32");
|
||||
lua_pushcclosure(g_lua, my_lua_printlog, 0);
|
||||
lua_setfield(g_lua, -2, "print_log");
|
||||
lua_pushcclosure(g_lua, my_lua_atexit, 0);
|
||||
lua_setfield(g_lua, -2, "atexit");
|
||||
lua_pushcclosure(g_lua, my_lua_exit, 0);
|
||||
lua_setfield(g_lua, -2, "exit");
|
||||
|
||||
lua_setfield(g_lua, -2, "dev");
|
||||
|
||||
|
@ -404,7 +363,7 @@ bool my_lua_import_hwstub()
|
|||
|
||||
if(lua_gettop(g_lua) != oldtop)
|
||||
{
|
||||
printf("internal error: unbalanced my_lua_import_soc");
|
||||
printf("internal error: unbalanced my_lua_import_soc\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -785,45 +744,37 @@ int main(int argc, char **argv)
|
|||
libusb_get_bus_number(mydev),
|
||||
libusb_get_device_address(mydev));
|
||||
}
|
||||
g_hwdev.handle = handle;
|
||||
if(hwstub_probe(&g_hwdev))
|
||||
g_hwdev = hwstub_open(handle);
|
||||
if(g_hwdev == NULL)
|
||||
{
|
||||
printf("Cannot probe device!\n");
|
||||
printf("Cannot open device!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get hwstub information
|
||||
int ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_VERSION, &g_hwdev_ver, sizeof(g_hwdev_ver));
|
||||
int ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_VERSION, &g_hwdev_ver, sizeof(g_hwdev_ver));
|
||||
if(ret != sizeof(g_hwdev_ver))
|
||||
{
|
||||
printf("Cannot get version!\n");
|
||||
goto Lerr;
|
||||
}
|
||||
if(g_hwdev_ver.major != HWSTUB_VERSION_MAJOR || g_hwdev_ver.minor < HWSTUB_VERSION_MINOR)
|
||||
if(g_hwdev_ver.bMajor != HWSTUB_VERSION_MAJOR || g_hwdev_ver.bMinor < HWSTUB_VERSION_MINOR)
|
||||
{
|
||||
printf("Warning: this tool is possibly incompatible with your device:\n");
|
||||
printf("Device version: %d.%d.%d\n", g_hwdev_ver.major, g_hwdev_ver.minor, g_hwdev_ver.revision);
|
||||
printf("Device version: %d.%d.%d\n", g_hwdev_ver.bMajor, g_hwdev_ver.bMinor, g_hwdev_ver.bRevision);
|
||||
printf("Host version: %d.%d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR, HWSTUB_VERSION_REV);
|
||||
}
|
||||
|
||||
// get memory layout information
|
||||
ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_LAYOUT, &g_hwdev_layout, sizeof(g_hwdev_layout));
|
||||
ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_LAYOUT, &g_hwdev_layout, sizeof(g_hwdev_layout));
|
||||
if(ret != sizeof(g_hwdev_layout))
|
||||
{
|
||||
printf("Cannot get layout: %d\n", ret);
|
||||
goto Lerr;
|
||||
}
|
||||
|
||||
// get features
|
||||
ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_FEATURES, &g_hwdev_features, sizeof(g_hwdev_features));
|
||||
if(ret != sizeof(g_hwdev_features))
|
||||
{
|
||||
printf("Cannot get features: %d\n", ret);
|
||||
goto Lerr;
|
||||
}
|
||||
|
||||
// get target
|
||||
ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_TARGET, &g_hwdev_target, sizeof(g_hwdev_target));
|
||||
ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_TARGET, &g_hwdev_target, sizeof(g_hwdev_target));
|
||||
if(ret != sizeof(g_hwdev_target))
|
||||
{
|
||||
printf("Cannot get target: %d\n", ret);
|
||||
|
@ -831,9 +782,9 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
// get STMP specific information
|
||||
if(g_hwdev_target.id == HWSTUB_TARGET_STMP)
|
||||
if(g_hwdev_target.dID == HWSTUB_TARGET_STMP)
|
||||
{
|
||||
ret = hwstub_get_info(&g_hwdev, HWSTUB_INFO_STMP, &g_hwdev_stmp, sizeof(g_hwdev_stmp));
|
||||
ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_STMP, &g_hwdev_stmp, sizeof(g_hwdev_stmp));
|
||||
if(ret != sizeof(g_hwdev_stmp))
|
||||
{
|
||||
printf("Cannot get stmp: %d\n", ret);
|
||||
|
@ -884,12 +835,9 @@ int main(int argc, char **argv)
|
|||
|
||||
Lerr:
|
||||
// display log if handled
|
||||
if(g_hwdev_features.feature_mask & HWSTUB_FEATURE_LOG)
|
||||
{
|
||||
if(!g_quiet)
|
||||
printf("Device log:\n");
|
||||
print_log(&g_hwdev);
|
||||
}
|
||||
hwstub_release(&g_hwdev);
|
||||
if(!g_quiet)
|
||||
printf("Device log:\n");
|
||||
print_log(g_hwdev);
|
||||
hwstub_release(g_hwdev);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -79,18 +79,12 @@ if not hwstub.options.quiet then
|
|||
print(" id: " .. string.format("%#x (%s)", hwstub.dev.target.id, id_str))
|
||||
print(" name: " .. hwstub.dev.target.name)
|
||||
print(" layout")
|
||||
print(" on-chip ram")
|
||||
print(" code: " .. string.format("%#x bytes @ %#x",
|
||||
hwstub.dev.layout.ocram.code.size, hwstub.dev.layout.ocram.code.start))
|
||||
print(" stack: " .. string.format("%#x bytes @ %#x",
|
||||
hwstub.dev.layout.ocram.stack.size, hwstub.dev.layout.ocram.stack.start))
|
||||
print(" buffer: " .. string.format("%#x bytes @ %#x",
|
||||
hwstub.dev.layout.ocram.buffer.size, hwstub.dev.layout.ocram.buffer.start))
|
||||
print(" features");
|
||||
print(" log: " .. tostring(hwstub.dev.features.log))
|
||||
print(" mem: " .. tostring(hwstub.dev.features.mem))
|
||||
print(" call: " .. tostring(hwstub.dev.features.call))
|
||||
print(" jump: " .. tostring(hwstub.dev.features.jump))
|
||||
print(" code: " .. string.format("%#x bytes @ %#x",
|
||||
hwstub.dev.layout.code.size, hwstub.dev.layout.code.start))
|
||||
print(" stack: " .. string.format("%#x bytes @ %#x",
|
||||
hwstub.dev.layout.stack.size, hwstub.dev.layout.stack.start))
|
||||
print(" buffer: " .. string.format("%#x bytes @ %#x",
|
||||
hwstub.dev.layout.buffer.size, hwstub.dev.layout.buffer.start))
|
||||
end
|
||||
|
||||
--
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue