From 418680aed25649072e8cb6b21efc23b18a8a245a Mon Sep 17 00:00:00 2001 From: TitanMKD Date: Thu, 9 May 2013 00:29:42 +0200 Subject: [PATCH] Fixed libhackrf, hackrf_cpldjtag (host) & usb_performance (firmware) to update CPLD through USB. Use latest CPLD bitstream with following command line: hackrf_cpldjtag.exe -x hackrf\hardware\jellybean\sgpio_if\default.xsvf --- firmware/usb_performance/usb_performance.c | 68 +++++++++++++++--- host/libhackrf/examples/hackrf_cpldjtag.c | 81 ++++++++++++++-------- host/libhackrf/src/hackrf.c | 10 ++- host/libhackrf/src/hackrf.h | 5 +- 4 files changed, 118 insertions(+), 46 deletions(-) diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 3162d315..fbba364e 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -50,6 +50,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) { - //FIXME endpoint->buffer can't be used like this - cpld_jtag_program(endpoint->setup.length, endpoint->buffer); - usb_endpoint_schedule_ack(endpoint->in); + // 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 { + } 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 + { + usb_endpoint_schedule_ack(endpoint->in); + return USB_REQUEST_STATUS_OK; + } + } else + { return USB_REQUEST_STATUS_OK; } } diff --git a/host/libhackrf/examples/hackrf_cpldjtag.c b/host/libhackrf/examples/hackrf_cpldjtag.c index d81c62fb..da4293e0 100644 --- a/host/libhackrf/examples/hackrf_cpldjtag.c +++ b/host/libhackrf/examples/hackrf_cpldjtag.c @@ -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 : length of XSVF file (default: 0)\n"); printf("\t-x : 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) { - fprintf(stderr, "hackrf_cpld_write() failed: %s (%d)\n", - hackrf_error_name(result), result); - fclose(fd); - fd = NULL; - return EXIT_FAILURE; + 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); diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 8f340c1d..610ad301 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -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; diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index a5ae7ea7..64320d7c 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -121,9 +121,10 @@ extern ADDAPI int ADDCALL hackrf_rffc5071_write(hackrf_device* device, uint8_t r 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);