Merge pull request #48 from TitanMKD/master

Fixed libhackrf, hackrf_cpldjtag (host) & usb_performance (firmware)
This commit is contained in:
Michael Ossmann
2013-05-11 16:55:59 -07:00
4 changed files with 118 additions and 46 deletions

View File

@ -51,6 +51,11 @@ static const uint32_t usb_bulk_buffer_mask = 32768 - 1;
usb_transfer_descriptor_t usb_td_bulk[2] ATTR_ALIGNED(64);
const uint_fast8_t usb_td_bulk_count = sizeof(usb_td_bulk) / sizeof(usb_td_bulk[0]);
/* TODO remove this big buffer and use streaming for CPLD */
#define CPLD_XSVF_MAX_LEN (65536)
uint8_t cpld_xsvf_buffer[CPLD_XSVF_MAX_LEN];
uint16_t write_cpld_idx = 0;
uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN];
char version_string[] = VERSION_STRING;
@ -61,8 +66,6 @@ typedef struct {
set_freq_params_t set_freq_params;
uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN];
uint8_t switchctrl = 0;
void update_switches(void)
@ -586,15 +589,62 @@ usb_request_status_t usb_vendor_request_read_spiflash(
usb_request_status_t usb_vendor_request_write_cpld(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
if( stage == USB_TRANSFER_STAGE_SETUP )
const usb_transfer_stage_t stage)
{
int error, i;
uint16_t total_len;
uint16_t len;
#define WAIT_LOOP_DELAY (6000000)
#define ALL_LEDS (PIN_LED1|PIN_LED2|PIN_LED3)
if (stage == USB_TRANSFER_STAGE_SETUP)
{
// len is limited to 64KB 16bits no overflow can happen
total_len = endpoint->setup.value;
len = endpoint->setup.length;
usb_endpoint_schedule(endpoint->out, &cpld_xsvf_buffer[write_cpld_idx], len);
return USB_REQUEST_STATUS_OK;
} else if (stage == USB_TRANSFER_STAGE_DATA)
{
// len is limited to 64KB 16bits no overflow can happen
total_len = endpoint->setup.value;
len = endpoint->setup.length;
write_cpld_idx = write_cpld_idx + len;
// Check if all bytes received and write CPLD
if(write_cpld_idx == total_len)
{
write_cpld_idx = 0;
error = cpld_jtag_program(total_len, &cpld_xsvf_buffer[write_cpld_idx]);
// TO FIX ACK shall be not delayed so much as cpld prog can take up to 5s.
if(error == 0)
{
usb_endpoint_schedule_ack(endpoint->in);
/* blink LED1, LED2, and LED3 on success */
while (1)
{
gpio_set(PORT_LED1_3, ALL_LEDS); /* LEDs on */
for (i = 0; i < WAIT_LOOP_DELAY; i++) /* Wait a bit. */
__asm__("nop");
gpio_clear(PORT_LED1_3, ALL_LEDS); /* LEDs off */
for (i = 0; i < WAIT_LOOP_DELAY; i++) /* Wait a bit. */
__asm__("nop");
}
return USB_REQUEST_STATUS_OK;
}else
{
/* LED3 (Red) steady on error */
gpio_set(PORT_LED1_3, PIN_LED3); /* LEDs on */
while (1);
return USB_REQUEST_STATUS_STALL;
}
}else
{
//FIXME endpoint->buffer can't be used like this
cpld_jtag_program(endpoint->setup.length, endpoint->buffer);
usb_endpoint_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK;
} else {
}
} else
{
return USB_REQUEST_STATUS_OK;
}
}

View File

@ -31,9 +31,11 @@
/* input file shouldn't be any longer than this */
#define MAX_XSVF_LENGTH 0x10000
#define PACKET_LEN 4096
uint8_t data[MAX_XSVF_LENGTH];
static struct option long_options[] = {
{ "length", required_argument, 0, 'l' },
{ "xsvf", required_argument, 0, 'x' },
{ 0, 0, 0, 0 },
};
@ -66,8 +68,6 @@ int parse_int(char* s, uint32_t* const value)
static void usage()
{
printf("Usage:\n");
//FIXME length should be automatic
printf("\t-l, --length <n>: length of XSVF file (default: 0)\n");
printf("\t-x <filename>: XSVF file to be written to CPLD.\n");
}
@ -75,20 +75,19 @@ int main(int argc, char** argv)
{
int opt;
uint32_t length = 0;
uint32_t total_length = 0;
const char* path = NULL;
hackrf_device* device = NULL;
int result = HACKRF_SUCCESS;
int option_index = 0;
uint8_t data[MAX_XSVF_LENGTH];
FILE* fd = NULL;
ssize_t bytes_read;
uint16_t xfer_len = 0;
uint8_t* pdata = &data[0];
while ((opt = getopt_long(argc, argv, "l:x:", long_options,
while ((opt = getopt_long(argc, argv, "x:", long_options,
&option_index)) != EOF) {
switch (opt) {
case 'l':
result = parse_int(optarg, &length);
break;
case 'x':
path = optarg;
break;
@ -112,22 +111,31 @@ int main(int argc, char** argv)
return EXIT_FAILURE;
}
fd = fopen(path, "rb");
if (fd == NULL)
{
fprintf(stderr, "Failed to open file: %s\n", path);
return EXIT_FAILURE;
}
/* Get size of the file */
fseek(fd, 0, SEEK_END); /* Not really portable but work on major OS Linux/Win32 */
length = ftell(fd);
/* Move to start */
rewind(fd);
printf("File size %d bytes.\n", length);
if (length > MAX_XSVF_LENGTH) {
fprintf(stderr, "XSVF file too large.\n");
usage();
return EXIT_FAILURE;
}
fd = fopen(path, "rb");
if (fd == NULL) {
fprintf(stderr, "Failed to open file: %s\n", path);
return EXIT_FAILURE;
}
const ssize_t bytes_read = fread(data, 1, length, fd);
if (bytes_read != length) {
fprintf(stderr, "Failed read file (read %d bytes).\n",
(int)bytes_read);
total_length = length;
bytes_read = fread(data, 1, total_length, fd);
if (bytes_read != total_length)
{
fprintf(stderr, "Failed to read all bytes (read %d bytes instead of %d bytes).\n",
(int)bytes_read, total_length);
fclose(fd);
fd = NULL;
return EXIT_FAILURE;
@ -147,17 +155,32 @@ int main(int argc, char** argv)
return EXIT_FAILURE;
}
result = hackrf_cpld_write(device, length, data);
if (result != HACKRF_SUCCESS) {
printf("LED1/2/3 blinking means CPLD program success.\nLED3/RED steady means error.\n");
printf("Wait message 'Write finished' or in case of LED3/RED steady, Power OFF/Disconnect the Jawbreaker.\n");
while( length )
{
xfer_len = (length > PACKET_LEN) ? PACKET_LEN : length;
result = hackrf_cpld_write(device, xfer_len, pdata, total_length);
if (result != HACKRF_SUCCESS)
{
fprintf(stderr, "hackrf_cpld_write() failed: %s (%d)\n",
hackrf_error_name(result), result);
fclose(fd);
fd = NULL;
return EXIT_FAILURE;
}
pdata += xfer_len;
length -= xfer_len;
printf("hackrf_cpld_write() Writing %d bytes, remaining %d bytes.\n",
xfer_len, length);
}
printf("Write finished.\n");
printf("Please Power OFF/Disconnect the Jawbreaker.\n");
fflush(stdout);
result = hackrf_close(device);
if (result != HACKRF_SUCCESS) {
if( result != HACKRF_SUCCESS )
{
fprintf(stderr, "hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result), result);
fclose(fd);

View File

@ -634,22 +634,20 @@ int ADDCALL hackrf_spiflash_read(hackrf_device* device, const uint32_t address,
}
int ADDCALL hackrf_cpld_write(hackrf_device* device, const uint16_t length,
unsigned char* const data)
unsigned char* const data, const uint16_t total_length)
{
int result;
result = libusb_control_transfer(
int result = libusb_control_transfer(
device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
HACKRF_VENDOR_REQUEST_CPLD_WRITE,
0,
total_length,
0,
data,
length,
0
);
if (result < length)
{
if (result < length) {
return HACKRF_ERROR_LIBUSB;
} else {
return HACKRF_SUCCESS;

View File

@ -122,7 +122,8 @@ extern ADDAPI int ADDCALL hackrf_spiflash_erase(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_spiflash_write(hackrf_device* device, const uint32_t address, const uint16_t length, unsigned char* const data);
extern ADDAPI int ADDCALL hackrf_spiflash_read(hackrf_device* device, const uint32_t address, const uint16_t length, unsigned char* data);
extern ADDAPI int ADDCALL hackrf_cpld_write(hackrf_device* device, const uint16_t length, unsigned char* const data);
extern ADDAPI int ADDCALL hackrf_cpld_write(hackrf_device* device, const uint16_t length,
unsigned char* const data, const uint16_t total_length);
extern ADDAPI int ADDCALL hackrf_board_id_read(hackrf_device* device, uint8_t* value);
extern ADDAPI int ADDCALL hackrf_version_string_read(hackrf_device* device, char* version, uint8_t length);