diff --git a/firmware/common/Makefile_inc.mk b/firmware/common/Makefile_inc.mk index 3221411a..4b51f8fa 100644 --- a/firmware/common/Makefile_inc.mk +++ b/firmware/common/Makefile_inc.mk @@ -34,12 +34,15 @@ HACKRF_OPTS = -D$(BOARD) # comment to disable RF transmission HACKRF_OPTS += -DTX_ENABLE +# automatic git version when working out of git +VERSION_STRING ?= -D'VERSION_STRING="git-$(shell git log -n 1 --format=%h)"' +HACKRF_OPTS += $(VERSION_STRING) + LDSCRIPT ?= ../common/LPC4330_M4.ld LIBOPENCM3 ?= /usr/local/arm-none-eabi PREFIX ?= arm-none-eabi -#PREFIX ?= arm-elf CC = $(PREFIX)-gcc LD = $(PREFIX)-gcc OBJCOPY = $(PREFIX)-objcopy @@ -51,7 +54,6 @@ CFLAGS += -std=c99 -Os -g3 -Wall -Wextra -I$(LIBOPENCM3)/include -I../common \ -fno-common -mcpu=cortex-m4 -mthumb -MD \ -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ $(HACKRF_OPTS) -#LDSCRIPT ?= $(BINARY).ld LDFLAGS += -L$(TOOLCHAIN_DIR)/lib/armv7e-m/fpu \ -L../common \ -L$(LIBOPENCM3)/lib -L$(LIBOPENCM3)/lib/lpc43xx \ diff --git a/firmware/common/cpld_jtag.c b/firmware/common/cpld_jtag.c index 02ce588a..ddeb13d9 100644 --- a/firmware/common/cpld_jtag.c +++ b/firmware/common/cpld_jtag.c @@ -57,12 +57,16 @@ void cpld_jtag_release(void) { GPIO_DIR(PORT_CPLD_TDI) &= ~PIN_CPLD_TDI; } -void cpld_jtag_program(const uint32_t len, unsigned char* const data) { +/* return 0 if success else return error code see xsvfExecute() */ +int cpld_jtag_program(const uint32_t len, unsigned char* const data) { + int error; cpld_jtag_setup(); xsvf_data = data; xsvf_len = len; - xsvfExecute(); + error = xsvfExecute(); cpld_jtag_release(); + + return error; } /* this gets called by the XAPP058 code */ diff --git a/firmware/common/cpld_jtag.h b/firmware/common/cpld_jtag.h index f6de2c97..ed42d782 100644 --- a/firmware/common/cpld_jtag.h +++ b/firmware/common/cpld_jtag.h @@ -25,7 +25,8 @@ #include void cpld_jtag_release(void); -void cpld_jtag_program(const uint32_t len, unsigned char* const data); +/* return 0 if success else return error code see xsvfExecute() see micro.h */ +int cpld_jtag_program(const uint32_t len, unsigned char* const data); unsigned char cpld_jtag_get_next_byte(void); #endif//__CPLD_JTAG_H__ diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 1a0ffad5..71f017da 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -239,8 +239,9 @@ extern "C" /* TODO add other Pins */ typedef enum { - TRANSCEIVER_MODE_RX, - TRANSCEIVER_MODE_TX, + TRANSCEIVER_MODE_OFF = 0, + TRANSCEIVER_MODE_RX = 1, + TRANSCEIVER_MODE_TX = 2 } transceiver_mode_t; void delay(uint32_t duration); diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 725e04e6..62edaa52 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -222,6 +222,7 @@ void max2837_start(void) set_MAX2837_EN_SPI(1); max2837_regs_commit(); #if !defined TEST + gpio_clear(PORT_XCVR_ENABLE, (PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE)); gpio_set(PORT_XCVR_ENABLE, PIN_XCVR_ENABLE); #endif } @@ -234,6 +235,7 @@ void max2837_tx(void) set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_TxLPF); max2837_regs_commit(); + gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE); gpio_set(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE); #endif } @@ -246,6 +248,7 @@ void max2837_rx(void) max2837_regs_commit(); #if !defined TEST + gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE); gpio_set(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE); #endif } diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 590bbfb1..5e2e9a19 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -160,7 +160,7 @@ void serial_delay(void) { uint32_t i; - for (i = 0; i < 1000; i++) + for (i = 0; i < 2; i++) __asm__("nop"); } diff --git a/firmware/common/xapp058/ports.c b/firmware/common/xapp058/ports.c index bb34c550..3c7c6e44 100644 --- a/firmware/common/xapp058/ports.c +++ b/firmware/common/xapp058/ports.c @@ -22,6 +22,28 @@ //static int g_iTMS = 0; /* For xapp058_example .exe */ //static int g_iTDI = 0; /* For xapp058_example .exe */ +void delay_jtag(uint32_t duration) +{ + #define DIVISOR (1024) + #define MIN_NOP (8) + + uint32_t i; + uint32_t delay_nop; + + /* @204Mhz duration of about 400ns for delay_nop=20 */ + if(duration < DIVISOR) + { + delay_nop = MIN_NOP; + }else + { + delay_nop = (duration / DIVISOR) + MIN_NOP; + } + + for (i = 0; i < delay_nop; i++) + __asm__("nop"); +} + + #ifdef WIN95PP #include "conio.h" @@ -127,7 +149,7 @@ void setPort(short p,short val) } /* conservative delay */ - delay(20000); + delay_jtag(20000); } @@ -135,9 +157,9 @@ void setPort(short p,short val) void pulseClock() { setPort(TCK,0); /* set the TCK port to low */ - delay(200); + delay_jtag(200); setPort(TCK,1); /* set the TCK port to high */ - delay(200); + delay_jtag(200); } @@ -169,7 +191,7 @@ unsigned char readTDOBit() /* You must return the current value of the JTAG TDO signal. */ //return( (unsigned char) 0 ); - delay(2000); + delay_jtag(2000); return CPLD_TDO_STATE; } diff --git a/firmware/cpldjtagprog/cpldjtagprog.c b/firmware/cpldjtagprog/cpldjtagprog.c index 06144c25..507f2370 100644 --- a/firmware/cpldjtagprog/cpldjtagprog.c +++ b/firmware/cpldjtagprog/cpldjtagprog.c @@ -26,26 +26,45 @@ #include "cpld_jtag.h" #include "sgpio_if_xsvf.h" +#define WAIT_LOOP_DELAY (6000000) + +#define ALL_LEDS (PIN_LED1|PIN_LED2|PIN_LED3) + int main(void) { int i; - + int error; + int LED; + pin_setup(); /* Set 1V8 */ gpio_set(PORT_EN1V8, PIN_EN1V8); + cpu_clock_init(); + /* program test bitstream to CPLD */ - cpld_jtag_program(sgpio_if_xsvf_len, &sgpio_if_xsvf[0]); + error = cpld_jtag_program(sgpio_if_xsvf_len, &sgpio_if_xsvf[0]); - /* blink LED1 and LED3 */ - while (1) + if(error == 0) { - gpio_set(PORT_LED1_3, (PIN_LED1|PIN_LED3)); /* LEDs on */ - for (i = 0; i < 2000000; i++) /* Wait a bit. */ + /* blink only LED1 (Green) on success */ + LED = PIN_LED1; + }else + { + /* blink LED3 (Red) on error */ + LED = PIN_LED3; + } + + gpio_clear(PORT_LED1_3, ALL_LEDS); /* All LEDs off */ + + while (1) + { + gpio_set(PORT_LED1_3, LED); /* LEDs on */ + for (i = 0; i < WAIT_LOOP_DELAY; i++) /* Wait a bit. */ __asm__("nop"); - gpio_clear(PORT_LED1_3, (PIN_LED1|PIN_LED3)); /* LED off */ - for (i = 0; i < 2000000; i++) /* Wait a bit. */ + gpio_clear(PORT_LED1_3, LED); /* LED off */ + for (i = 0; i < WAIT_LOOP_DELAY; i++) /* Wait a bit. */ __asm__("nop"); } diff --git a/firmware/cpldjtagprog_rom_to_ram/Makefile b/firmware/cpldjtagprog_rom_to_ram/Makefile new file mode 100644 index 00000000..e3a80e16 --- /dev/null +++ b/firmware/cpldjtagprog_rom_to_ram/Makefile @@ -0,0 +1,36 @@ +# Hey Emacs, this is a -*- makefile -*- +# +# Copyright 2012 Michael Ossmann +# Copyright 2012 Jared Boone +# +# This file is part of HackRF. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +BINARY = cpldjtagprog_rom_to_ram + +SRC = $(BINARY).c \ + ../common/hackrf_core.c \ + ../common/si5351c.c \ + ../common/max2837.c \ + ../common/cpld_jtag.c \ + ../common/xapp058/lenval.c \ + ../common/xapp058/micro.c \ + ../common/xapp058/ports.c + +LDSCRIPT = ../common/LPC4330_M4_rom_to_ram.ld +include ../common/Makefile_inc.mk diff --git a/firmware/cpldjtagprog_rom_to_ram/README b/firmware/cpldjtagprog_rom_to_ram/README new file mode 100644 index 00000000..82388a2c --- /dev/null +++ b/firmware/cpldjtagprog_rom_to_ram/README @@ -0,0 +1 @@ +This is a test program for CPLD JTAG programming. diff --git a/firmware/cpldjtagprog_rom_to_ram/cpldjtagprog_rom_to_ram.c b/firmware/cpldjtagprog_rom_to_ram/cpldjtagprog_rom_to_ram.c new file mode 100644 index 00000000..5cc9456c --- /dev/null +++ b/firmware/cpldjtagprog_rom_to_ram/cpldjtagprog_rom_to_ram.c @@ -0,0 +1,72 @@ +/* + * Copyright 2010 - 2013 Michael Ossmann + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include "hackrf_core.h" +#include "cpld_jtag.h" +#include "../cpldjtagprog/sgpio_if_xsvf.h" + +#define WAIT_LOOP_DELAY (6000000) + +#define ALL_LEDS (PIN_LED1|PIN_LED2|PIN_LED3) + +int main(void) +{ + int i; + int error; + int LED; + + pin_setup(); + + /* Set 1V8 */ + gpio_set(PORT_EN1V8, PIN_EN1V8); + + cpu_clock_init(); + + /* program test bitstream to CPLD */ + error = cpld_jtag_program(sgpio_if_xsvf_len, &sgpio_if_xsvf[0]); + + if(error == 0) + { + /* blink only LED1 (Green) on success */ + LED = PIN_LED1; + }else + { + /* blink LED3 (Red) on error */ + LED = PIN_LED3; + } + + gpio_clear(PORT_LED1_3, ALL_LEDS); /* All LEDs off */ + + while (1) + { + gpio_set(PORT_LED1_3, LED); /* LEDs on */ + for (i = 0; i < WAIT_LOOP_DELAY; i++) /* Wait a bit. */ + __asm__("nop"); + gpio_clear(PORT_LED1_3, LED); /* LED off */ + for (i = 0; i < WAIT_LOOP_DELAY; i++) /* Wait a bit. */ + __asm__("nop"); + } + + return 0; +} diff --git a/firmware/usb_performance/Makefile_rom_to_ram b/firmware/usb_performance/Makefile_rom_to_ram new file mode 100644 index 00000000..0ec7bb8e --- /dev/null +++ b/firmware/usb_performance/Makefile_rom_to_ram @@ -0,0 +1,44 @@ +# Hey Emacs, this is a -*- makefile -*- +# +# Copyright 2012 Jared Boone +# +# This file is part of HackRF. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +BINARY = usb_performance_rom_to_ram + +SRC = usb_performance.c \ + usb.c \ + usb_request.c \ + usb_standard_request.c \ + usb_descriptor.c \ + ../common/fault_handler.c \ + ../common/hackrf_core.c \ + ../common/sgpio.c \ + ../common/si5351c.c \ + ../common/max2837.c \ + ../common/max5864.c \ + ../common/rffc5071.c \ + ../common/w25q80bv.c \ + ../common/cpld_jtag.c \ + ../common/xapp058/lenval.c \ + ../common/xapp058/micro.c \ + ../common/xapp058/ports.c + +LDSCRIPT = ../common/LPC4330_M4_rom_to_ram.ld +include ../common/Makefile_inc.mk diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 9956dbb2..2bb56aaa 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -41,7 +41,7 @@ #include "usb_descriptor.h" #include "usb_standard_request.h" -static volatile transceiver_mode_t transceiver_mode = TRANSCEIVER_MODE_RX; +static volatile transceiver_mode_t transceiver_mode = TRANSCEIVER_MODE_OFF; uint8_t* const usb_bulk_buffer = (uint8_t*)0x20004000; static volatile uint32_t usb_bulk_buffer_offset = 0; @@ -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]); +uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN]; +char version_string[] = VERSION_STRING; + +uint8_t switchctrl = 0; + static void usb_init_buffers_bulk() { usb_td_bulk[0].next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; usb_td_bulk[0].total_bytes @@ -179,14 +184,23 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) { if( transceiver_mode == TRANSCEIVER_MODE_RX ) { gpio_clear(PORT_LED1_3, PIN_LED3); + gpio_set(PORT_LED1_3, PIN_LED2); usb_endpoint_init(&usb_endpoint_bulk_in); + max2837_start(); max2837_rx(); - } else { + } else if (transceiver_mode == TRANSCEIVER_MODE_TX) { + gpio_clear(PORT_LED1_3, PIN_LED2); gpio_set(PORT_LED1_3, PIN_LED3); usb_endpoint_init(&usb_endpoint_bulk_out); + max2837_start(); max2837_tx(); + } else { + gpio_clear(PORT_LED1_3, PIN_LED2); + gpio_clear(PORT_LED1_3, PIN_LED3); + max2837_stop(); + return; } sgpio_configure(transceiver_mode, true); @@ -204,16 +218,12 @@ usb_request_status_t usb_vendor_request_set_transceiver_mode( ) { if( stage == USB_TRANSFER_STAGE_SETUP ) { switch( endpoint->setup.value ) { - case 1: - set_transceiver_mode(TRANSCEIVER_MODE_RX); + case TRANSCEIVER_MODE_OFF: + case TRANSCEIVER_MODE_RX: + case TRANSCEIVER_MODE_TX: + set_transceiver_mode(endpoint->setup.value); usb_endpoint_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; - - case 2: - set_transceiver_mode(TRANSCEIVER_MODE_TX); - usb_endpoint_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; - default: return USB_REQUEST_STATUS_STALL; } @@ -367,44 +377,68 @@ usb_request_status_t usb_vendor_request_read_rffc5071( } } +usb_request_status_t usb_vendor_request_erase_spiflash( + usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) +{ + //FIXME This should refuse to run if executing from SPI flash. + + if (stage == USB_TRANSFER_STAGE_SETUP) { + w25q80bv_setup(); + /* only chip erase is implemented */ + w25q80bv_chip_erase(); + usb_endpoint_schedule_ack(endpoint->in); + //FIXME probably should undo w25q80bv_setup() + } + return USB_REQUEST_STATUS_OK; +} + usb_request_status_t usb_vendor_request_write_spiflash( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { - static uint32_t addr; - static uint16_t len; - static uint8_t spiflash_buffer[0xffff]; + uint32_t addr = 0; + uint16_t len = 0; + + //FIXME This should refuse to run if executing from SPI flash. if (stage == USB_TRANSFER_STAGE_SETUP) { addr = (endpoint->setup.value << 16) | endpoint->setup.index; len = endpoint->setup.length; - if ((len > W25Q80BV_NUM_BYTES) || (addr > W25Q80BV_NUM_BYTES) + if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES) || ((addr + len) > W25Q80BV_NUM_BYTES)) { return USB_REQUEST_STATUS_STALL; } else { usb_endpoint_schedule(endpoint->out, &spiflash_buffer[0], len); + w25q80bv_setup(); return USB_REQUEST_STATUS_OK; } } else if (stage == USB_TRANSFER_STAGE_DATA) { - //FIXME still trying to make this work + addr = (endpoint->setup.value << 16) | endpoint->setup.index; + len = endpoint->setup.length; + /* This check is redundant but makes me feel better. */ + if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES) + || ((addr + len) > W25Q80BV_NUM_BYTES)) { + return USB_REQUEST_STATUS_STALL; + } else { w25q80bv_program(addr, len, &spiflash_buffer[0]); usb_endpoint_schedule_ack(endpoint->in); + //FIXME probably should undo w25q80bv_setup() return USB_REQUEST_STATUS_OK; + } } else { return USB_REQUEST_STATUS_OK; } } usb_request_status_t usb_vendor_request_read_spiflash( - usb_endpoint_t* const endpoint, - const usb_transfer_stage_t stage -) { + usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) +{ uint32_t addr; uint16_t len; - if( stage == USB_TRANSFER_STAGE_SETUP ) - { + + if (stage == USB_TRANSFER_STAGE_SETUP) { addr = (endpoint->setup.value << 16) | endpoint->setup.index; len = endpoint->setup.length; - if ((len > W25Q80BV_NUM_BYTES) || (addr > W25Q80BV_NUM_BYTES) + if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES) || ((addr + len) > W25Q80BV_NUM_BYTES)) { return USB_REQUEST_STATUS_STALL; } else { @@ -440,7 +474,19 @@ usb_request_status_t usb_vendor_request_read_board_id( endpoint->buffer[0] = BOARD_ID; usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1); usb_endpoint_schedule_ack(endpoint->out); - return USB_REQUEST_STATUS_OK; + } + return USB_REQUEST_STATUS_OK; +} + +usb_request_status_t usb_vendor_request_read_version_string( + usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) +{ + uint8_t length; + + if (stage == USB_TRANSFER_STAGE_SETUP) { + length = (uint8_t)strlen(version_string); + usb_endpoint_schedule(endpoint->in, version_string, length); + usb_endpoint_schedule_ack(endpoint->out); } return USB_REQUEST_STATUS_OK; } @@ -456,10 +502,12 @@ static const usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_set_baseband_filter_bandwidth, usb_vendor_request_write_rffc5071, usb_vendor_request_read_rffc5071, + usb_vendor_request_erase_spiflash, usb_vendor_request_write_spiflash, usb_vendor_request_read_spiflash, usb_vendor_request_write_cpld, - usb_vendor_request_read_board_id + usb_vendor_request_read_board_id, + usb_vendor_request_read_version_string }; static const uint32_t vendor_request_handler_count = @@ -589,7 +637,6 @@ void sgpio_irqhandler() { int main(void) { const uint32_t ifreq = 2600000000U; - uint8_t switchctrl = 0; pin_setup(); enable_1v8_power(); @@ -612,19 +659,16 @@ int main(void) { ssp1_set_mode_max2837(); max2837_setup(); + max2837_set_frequency(ifreq); rffc5071_setup(); - + #ifdef JAWBREAKER switchctrl = SWITCHCTRL_AMP_BYPASS; #endif rffc5071_rx(switchctrl); rffc5071_set_frequency(1700, 0); // 2600 MHz IF - 1700 MHz LO = 900 MHz RF - max2837_set_frequency(ifreq); - max2837_start(); - max2837_rx(); - while(true) { // Wait until buffer 0 is transmitted/received. while( usb_bulk_buffer_offset < 16384 ); diff --git a/host/libhackrf/examples/hackrf_info.c b/host/libhackrf/examples/hackrf_info.c index aeacfce4..387a83ef 100644 --- a/host/libhackrf/examples/hackrf_info.c +++ b/host/libhackrf/examples/hackrf_info.c @@ -31,6 +31,7 @@ int main(int argc, char** argv) hackrf_device* device = NULL; int result = HACKRF_SUCCESS; uint8_t board_id = BOARD_ID_INVALID; + char version[255 + 1]; result = hackrf_init(); if (result != HACKRF_SUCCESS) { @@ -58,6 +59,15 @@ int main(int argc, char** argv) printf("Board ID Number: %d (%s)\n", board_id, hackrf_board_id_name(board_id)); + result = hackrf_version_string_read(device, &version[0], 255); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_version_string_read() failed: %s (%d)\n", + hackrf_error_name(result), result); + return EXIT_FAILURE; + } + + printf("Firmware Version: %s\n", version); + result = hackrf_close(device); if (result != HACKRF_SUCCESS) { fprintf(stderr, "hackrf_close() failed: %s (%d)\n", diff --git a/host/libhackrf/examples/hackrf_spiflash.c b/host/libhackrf/examples/hackrf_spiflash.c index d32124c0..4f0749b1 100644 --- a/host/libhackrf/examples/hackrf_spiflash.c +++ b/host/libhackrf/examples/hackrf_spiflash.c @@ -80,11 +80,13 @@ int main(int argc, char** argv) int opt; uint32_t address = 0; uint32_t length = 0; + uint16_t xfer_len = 0; const char* path = NULL; hackrf_device* device = NULL; int result = HACKRF_SUCCESS; int option_index = 0; uint8_t data[MAX_LENGTH]; + uint8_t* pdata = &data[0]; FILE* fd = NULL; bool read = false; bool write = false; @@ -133,6 +135,12 @@ int main(int argc, char** argv) return EXIT_FAILURE; } + if (length == 0) { + fprintf(stderr, "Requested transfer of zero bytes.\n"); + usage(); + return EXIT_FAILURE; + } + if ((length > MAX_LENGTH) || (address > MAX_LENGTH) || ((address + length) > MAX_LENGTH)) { fprintf(stderr, "Request exceeds size of flash memory.\n"); @@ -197,14 +205,30 @@ int main(int argc, char** argv) fd = NULL; return EXIT_FAILURE; } - result = hackrf_spiflash_write(device, address, length, data); + printf("Erasing SPI flash.\n"); + result = hackrf_spiflash_erase(device); if (result != HACKRF_SUCCESS) { - fprintf(stderr, "hackrf_spiflash_write() failed: %s (%d)\n", + fprintf(stderr, "hackrf_spiflash_erase() failed: %s (%d)\n", hackrf_error_name(result), result); fclose(fd); fd = NULL; return EXIT_FAILURE; } + while (length) { + xfer_len = (length > 256) ? 256 : length; + printf("Writing %d bytes at 0x%06x.\n", xfer_len, address); + result = hackrf_spiflash_write(device, address, xfer_len, pdata); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_spiflash_write() failed: %s (%d)\n", + hackrf_error_name(result), result); + fclose(fd); + fd = NULL; + return EXIT_FAILURE; + } + address += xfer_len; + pdata += xfer_len; + length -= xfer_len; + } } result = hackrf_close(device); diff --git a/host/libhackrf/examples/hackrf_transfer.c b/host/libhackrf/examples/hackrf_transfer.c index 2f099d6d..dd3dc1f1 100644 --- a/host/libhackrf/examples/hackrf_transfer.c +++ b/host/libhackrf/examples/hackrf_transfer.c @@ -47,8 +47,9 @@ #endif typedef enum { - TRANSCEIVER_MODE_RX, - TRANSCEIVER_MODE_TX, + TRANSCEIVER_MODE_OFF = 0, + TRANSCEIVER_MODE_RX = 1, + TRANSCEIVER_MODE_TX = 2 } transceiver_mode_t; static transceiver_mode_t transceiver_mode = TRANSCEIVER_MODE_RX; diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 716f9baa..a5e7872c 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -39,13 +39,16 @@ typedef enum { HACKRF_VENDOR_REQUEST_BASEBAND_FILTER_BANDWIDTH_SET = 7, HACKRF_VENDOR_REQUEST_RFFC5071_WRITE = 8, HACKRF_VENDOR_REQUEST_RFFC5071_READ = 9, - HACKRF_VENDOR_REQUEST_SPIFLASH_WRITE = 10, - HACKRF_VENDOR_REQUEST_SPIFLASH_READ = 11, - HACKRF_VENDOR_REQUEST_CPLD_WRITE = 12, - HACKRF_VENDOR_REQUEST_BOARD_ID_READ = 13 + HACKRF_VENDOR_REQUEST_SPIFLASH_ERASE = 10, + HACKRF_VENDOR_REQUEST_SPIFLASH_WRITE = 11, + HACKRF_VENDOR_REQUEST_SPIFLASH_READ = 12, + HACKRF_VENDOR_REQUEST_CPLD_WRITE = 13, + HACKRF_VENDOR_REQUEST_BOARD_ID_READ = 14, + HACKRF_VENDOR_REQUEST_VERSION_STRING_READ = 15 } hackrf_vendor_request; typedef enum { + HACKRF_TRANSCEIVER_MODE_OFF = 0, HACKRF_TRANSCEIVER_MODE_RECEIVE = 1, HACKRF_TRANSCEIVER_MODE_TRANSMIT = 2, } hackrf_transceiver_mode; @@ -435,6 +438,25 @@ int hackrf_rffc5071_write(hackrf_device* device, uint8_t register_number, uint16 } } +int hackrf_spiflash_erase(hackrf_device* device) { + int result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_SPIFLASH_ERASE, + 0, + 0, + NULL, + 0, + 0 + ); + + if (result != 0) { + return HACKRF_ERROR_LIBUSB; + } else { + return HACKRF_SUCCESS; + } +} + int hackrf_spiflash_write(hackrf_device* device, const uint32_t address, const uint16_t length, unsigned char* const data) { @@ -453,7 +475,7 @@ int hackrf_spiflash_write(hackrf_device* device, const uint32_t address, 0 ); - if( result != 0 ) { + if (result < length) { return HACKRF_ERROR_LIBUSB; } else { return HACKRF_SUCCESS; @@ -478,7 +500,7 @@ int hackrf_spiflash_read(hackrf_device* device, const uint32_t address, 0 ); - if( result < 2 ) { + if (result < length) { return HACKRF_ERROR_LIBUSB; } else { return HACKRF_SUCCESS; @@ -499,7 +521,7 @@ int hackrf_cpld_write(hackrf_device* device, const uint16_t length, 0 ); - if( result != 0 ) { + if (result < length) { return HACKRF_ERROR_LIBUSB; } else { return HACKRF_SUCCESS; @@ -525,6 +547,28 @@ int hackrf_board_id_read(hackrf_device* device, uint8_t* value) { } } +int hackrf_version_string_read(hackrf_device* device, char* version, + uint8_t length) +{ + int result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_VERSION_STRING_READ, + 0, + 0, + (unsigned char*)version, + length, + 0 + ); + + if (result < 0) { + return HACKRF_ERROR_LIBUSB; + } else { + version[result] = '\0'; + return HACKRF_SUCCESS; + } +} + static void* transfer_threadproc(void* arg) { hackrf_device* device = (hackrf_device*)arg; @@ -619,7 +663,12 @@ int hackrf_start_rx(hackrf_device* device, hackrf_sample_block_cb_fn callback) { } int hackrf_stop_rx(hackrf_device* device) { - return kill_transfer_thread(device); + int result1, result2; + result1 = kill_transfer_thread(device); + result2 = hackrf_set_transceiver_mode(device, HACKRF_TRANSCEIVER_MODE_OFF); + if (result2 != HACKRF_SUCCESS) + return result2; + return result1; } int hackrf_start_tx(hackrf_device* device, hackrf_sample_block_cb_fn callback) { @@ -632,7 +681,12 @@ int hackrf_start_tx(hackrf_device* device, hackrf_sample_block_cb_fn callback) { } int hackrf_stop_tx(hackrf_device* device) { - return kill_transfer_thread(device); + int result1, result2; + result1 = kill_transfer_thread(device); + result2 = hackrf_set_transceiver_mode(device, HACKRF_TRANSCEIVER_MODE_OFF); + if (result2 != HACKRF_SUCCESS) + return result2; + return result1; } int hackrf_close(hackrf_device* device) { diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index 712b4fce..67f18e1b 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -80,6 +80,7 @@ int hackrf_baseband_filter_bandwidth_set(hackrf_device* device, const uint32_t b int hackrf_rffc5071_read(hackrf_device* device, uint8_t register_number, uint16_t* value); int hackrf_rffc5071_write(hackrf_device* device, uint8_t register_number, uint16_t value); +int hackrf_spiflash_erase(hackrf_device* device); int hackrf_spiflash_write(hackrf_device* device, const uint32_t address, const uint16_t length, unsigned char* const data); int hackrf_spiflash_read(hackrf_device* device, const uint32_t address, @@ -89,6 +90,8 @@ int hackrf_cpld_write(hackrf_device* device, const uint16_t length, unsigned char* const data); int hackrf_board_id_read(hackrf_device* device, uint8_t* value); +int hackrf_version_string_read(hackrf_device* device, char* version, + uint8_t length); const char* hackrf_error_name(enum hackrf_error errcode); const char* hackrf_board_id_name(enum hackrf_board_id board_id);