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

@ -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); 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]); 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]; uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN];
char version_string[] = VERSION_STRING; char version_string[] = VERSION_STRING;
@ -61,8 +66,6 @@ typedef struct {
set_freq_params_t set_freq_params; set_freq_params_t set_freq_params;
uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN];
uint8_t switchctrl = 0; uint8_t switchctrl = 0;
void update_switches(void) 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_request_status_t usb_vendor_request_write_cpld(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
if( stage == USB_TRANSFER_STAGE_SETUP ) 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 // len is limited to 64KB 16bits no overflow can happen
cpld_jtag_program(endpoint->setup.length, endpoint->buffer); total_len = endpoint->setup.value;
usb_endpoint_schedule_ack(endpoint->in); len = endpoint->setup.length;
usb_endpoint_schedule(endpoint->out, &cpld_xsvf_buffer[write_cpld_idx], len);
return USB_REQUEST_STATUS_OK; 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; return USB_REQUEST_STATUS_OK;
} }
} }

View File

@ -31,9 +31,11 @@
/* input file shouldn't be any longer than this */ /* input file shouldn't be any longer than this */
#define MAX_XSVF_LENGTH 0x10000 #define MAX_XSVF_LENGTH 0x10000
#define PACKET_LEN 4096
uint8_t data[MAX_XSVF_LENGTH];
static struct option long_options[] = { static struct option long_options[] = {
{ "length", required_argument, 0, 'l' },
{ "xsvf", required_argument, 0, 'x' }, { "xsvf", required_argument, 0, 'x' },
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 },
}; };
@ -66,8 +68,6 @@ int parse_int(char* s, uint32_t* const value)
static void usage() static void usage()
{ {
printf("Usage:\n"); 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"); printf("\t-x <filename>: XSVF file to be written to CPLD.\n");
} }
@ -75,20 +75,19 @@ int main(int argc, char** argv)
{ {
int opt; int opt;
uint32_t length = 0; uint32_t length = 0;
uint32_t total_length = 0;
const char* path = NULL; const char* path = NULL;
hackrf_device* device = NULL; hackrf_device* device = NULL;
int result = HACKRF_SUCCESS; int result = HACKRF_SUCCESS;
int option_index = 0; int option_index = 0;
uint8_t data[MAX_XSVF_LENGTH];
FILE* fd = NULL; 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) { &option_index)) != EOF) {
switch (opt) { switch (opt) {
case 'l':
result = parse_int(optarg, &length);
break;
case 'x': case 'x':
path = optarg; path = optarg;
break; break;
@ -112,22 +111,31 @@ int main(int argc, char** argv)
return EXIT_FAILURE; 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) { if (length > MAX_XSVF_LENGTH) {
fprintf(stderr, "XSVF file too large.\n"); fprintf(stderr, "XSVF file too large.\n");
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
fd = fopen(path, "rb"); total_length = length;
if (fd == NULL) { bytes_read = fread(data, 1, total_length, fd);
fprintf(stderr, "Failed to open file: %s\n", path); if (bytes_read != total_length)
return EXIT_FAILURE; {
} fprintf(stderr, "Failed to read all bytes (read %d bytes instead of %d bytes).\n",
(int)bytes_read, total_length);
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);
fclose(fd); fclose(fd);
fd = NULL; fd = NULL;
return EXIT_FAILURE; return EXIT_FAILURE;
@ -147,17 +155,32 @@ int main(int argc, char** argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
result = hackrf_cpld_write(device, length, data); printf("LED1/2/3 blinking means CPLD program success.\nLED3/RED steady means error.\n");
if (result != HACKRF_SUCCESS) { printf("Wait message 'Write finished' or in case of LED3/RED steady, Power OFF/Disconnect the Jawbreaker.\n");
fprintf(stderr, "hackrf_cpld_write() failed: %s (%d)\n", while( length )
hackrf_error_name(result), result); {
fclose(fd); xfer_len = (length > PACKET_LEN) ? PACKET_LEN : length;
fd = NULL; result = hackrf_cpld_write(device, xfer_len, pdata, total_length);
return EXIT_FAILURE; 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); result = hackrf_close(device);
if (result != HACKRF_SUCCESS) { if( result != HACKRF_SUCCESS )
{
fprintf(stderr, "hackrf_close() failed: %s (%d)\n", fprintf(stderr, "hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result), result); hackrf_error_name(result), result);
fclose(fd); 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, 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; int result = libusb_control_transfer(
result = libusb_control_transfer(
device->usb_device, device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
HACKRF_VENDOR_REQUEST_CPLD_WRITE, HACKRF_VENDOR_REQUEST_CPLD_WRITE,
0, total_length,
0, 0,
data, data,
length, length,
0 0
); );
if (result < length) if (result < length) {
{
return HACKRF_ERROR_LIBUSB; return HACKRF_ERROR_LIBUSB;
} else { } else {
return HACKRF_SUCCESS; return HACKRF_SUCCESS;

View File

@ -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_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_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_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_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); extern ADDAPI int ADDCALL hackrf_version_string_read(hackrf_device* device, char* version, uint8_t length);