From 7c98d3e14bb68686acfdf67b6642a7012c7dd4da Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 28 Aug 2015 12:48:05 -0700 Subject: [PATCH 1/3] Add W25Q80BV function to fast-read from device. --- firmware/common/w25q80bv.c | 22 ++++++++++++++++++++++ firmware/common/w25q80bv.h | 3 +++ 2 files changed, 25 insertions(+) diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index 2b391d9d..f49ffe3f 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -243,3 +243,25 @@ void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data) w25q80bv_page_program(addr, len, data); } } + +void w25q80bv_read(uint32_t addr, uint32_t len, uint8_t* const data) +{ + uint32_t i; + + /* do nothing if we would overflow the flash */ + if ((len > W25Q80BV_NUM_BYTES) || (addr > W25Q80BV_NUM_BYTES) + || ((addr + len) > W25Q80BV_NUM_BYTES)) + return; + + w25q80bv_wait_while_busy(); + + gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); + ssp_transfer(SSP0_NUM, W25Q80BV_FAST_READ); + ssp_transfer(SSP0_NUM, (addr >> 16) & 0xFF); + ssp_transfer(SSP0_NUM, (addr >> 8) & 0xFF); + ssp_transfer(SSP0_NUM, (addr >> 0) & 0xFF); + ssp_transfer(SSP0_NUM, 0xFF); + for (i = 0; i < len; i++) + data[i] = ssp_transfer(SSP0_NUM, 0xFF); + gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); +} diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index b11a466a..5eda749d 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -27,6 +27,8 @@ #define W25Q80BV_NUM_PAGES 4096U #define W25Q80BV_NUM_BYTES 1048576U +#define W25Q80BV_READ_DATA 0x03 +#define W25Q80BV_FAST_READ 0x0b #define W25Q80BV_WRITE_ENABLE 0x06 #define W25Q80BV_CHIP_ERASE 0xC7 #define W25Q80BV_READ_STATUS1 0x05 @@ -51,5 +53,6 @@ void w25q80bv_chip_erase(void); void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data); uint8_t w25q80bv_get_device_id(void); void w25q80bv_get_unique_id(w25q80bv_unique_id_t* unique_id); +void w25q80bv_read(uint32_t addr, uint32_t len, uint8_t* const data); #endif//__W25Q80BV_H__ From a4e447cb9ef8bc7f8435cf24f96c6323df6077d4 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 28 Aug 2015 12:49:34 -0700 Subject: [PATCH 2/3] Use W25Q80BV read function to retrieve SPI flash contents. --- firmware/hackrf_usb/usb_api_spiflash.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index 93c12065..e8791a8f 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -86,10 +86,8 @@ usb_request_status_t usb_vendor_request_write_spiflash( usb_request_status_t usb_vendor_request_read_spiflash( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { - uint32_t i; uint32_t addr; uint16_t len; - uint8_t* u8_addr_pt; if (stage == USB_TRANSFER_STAGE_SETUP) { @@ -99,12 +97,8 @@ usb_request_status_t usb_vendor_request_read_spiflash( || ((addr + len) > W25Q80BV_NUM_BYTES)) { return USB_REQUEST_STATUS_STALL; } else { - /* TODO flush SPIFI "cache" before to read the SPIFI memory */ - u8_addr_pt = (uint8_t*)(addr + SPIFI_DATA_UNCACHED_BASE); - for(i=0; iin, &spiflash_buffer[0], len, NULL, NULL); return USB_REQUEST_STATUS_OK; From 2022cc6351709175319353b8e027a5a10ed8956e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 28 Aug 2015 13:03:40 -0700 Subject: [PATCH 3/3] Only perform W25Q80BV setup once, at startup. hackrf_usb firmware does not run from SPI flash once the ROM bootloader is done. Simplify assumptions by initializing SPI flash once, early. Do not initialize it every 256 bytes that are read from or written to the device. --- firmware/hackrf_usb/hackrf_usb.c | 4 ++++ firmware/hackrf_usb/usb_api_spiflash.c | 9 --------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index c5ccb6ad..5f793966 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -47,6 +47,7 @@ #include "sgpio_isr.h" #include "usb_bulk_buffer.h" #include "si5351c.h" +#include "w25q80bv.h" static volatile transceiver_mode_t _transceiver_mode = TRANSCEIVER_MODE_OFF; @@ -224,6 +225,9 @@ int main(void) { #endif cpu_clock_init(); + /* Code is not running from SPI flash, initialize for flash read/write over USB */ + w25q80bv_setup(); + usb_set_descriptor_by_serial_number(); usb_set_configuration_changed_cb(usb_configuration_changed); diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index e8791a8f..96072394 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -33,14 +33,10 @@ uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN]; 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_transfer_schedule_ack(endpoint->in); - //FIXME probably should undo w25q80bv_setup() } return USB_REQUEST_STATUS_OK; } @@ -51,8 +47,6 @@ usb_request_status_t usb_vendor_request_write_spiflash( 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; @@ -62,7 +56,6 @@ usb_request_status_t usb_vendor_request_write_spiflash( } else { usb_transfer_schedule_block(endpoint->out, &spiflash_buffer[0], len, NULL, NULL); - w25q80bv_setup(); return USB_REQUEST_STATUS_OK; } } else if (stage == USB_TRANSFER_STAGE_DATA) { @@ -75,7 +68,6 @@ usb_request_status_t usb_vendor_request_write_spiflash( } else { w25q80bv_program(addr, len, &spiflash_buffer[0]); usb_transfer_schedule_ack(endpoint->in); - //FIXME probably should undo w25q80bv_setup() return USB_REQUEST_STATUS_OK; } } else { @@ -97,7 +89,6 @@ usb_request_status_t usb_vendor_request_read_spiflash( || ((addr + len) > W25Q80BV_NUM_BYTES)) { return USB_REQUEST_STATUS_STALL; } else { - w25q80bv_setup(); w25q80bv_read(addr, len, &spiflash_buffer[0]); usb_transfer_schedule_block(endpoint->in, &spiflash_buffer[0], len, NULL, NULL);