Merge branch 'master' of https://github.com/mossmann/hackrf
This commit is contained in:
@ -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)
|
||||
{
|
||||
//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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user