From 7639ef0e3ec27f8f6630d64eb8467a9d38b579ad Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 16:49:03 -0800 Subject: [PATCH] W25Q80BV: De-singleton the driver. --- firmware/common/hackrf_core.c | 2 + firmware/common/hackrf_core.h | 2 + firmware/common/rom_iap.c | 4 +- firmware/common/w25q80bv.c | 102 ++++++++++++------------- firmware/common/w25q80bv.h | 12 +-- firmware/common/w25q80bv_drv.c | 13 ++-- firmware/common/w25q80bv_drv.h | 12 ++- firmware/hackrf_usb/usb_api_spiflash.c | 10 ++- 8 files changed, 86 insertions(+), 71 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index db5029ad..93bf8512 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -39,6 +39,8 @@ max2837_driver_t max2837; rffc5071_driver_t rffc5072; +w25q80bv_driver_t spi_flash; + void delay(uint32_t duration) { uint32_t i; diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index afa3379d..35fa1225 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -34,6 +34,7 @@ extern "C" #include "max2837_drv.h" #include "rffc5071_drv.h" +#include "w25q80bv_drv.h" /* hardware identification number */ #define BOARD_ID_JELLYBEAN 0 @@ -354,6 +355,7 @@ typedef enum { void delay(uint32_t duration); extern max2837_driver_t max2837; extern rffc5071_driver_t rffc5072; +extern w25q80bv_driver_t spi_flash; void cpu_clock_init(void); void cpu_clock_pll1_low_speed(void); diff --git a/firmware/common/rom_iap.c b/firmware/common/rom_iap.c index f7a4420c..4a92494c 100644 --- a/firmware/common/rom_iap.c +++ b/firmware/common/rom_iap.c @@ -77,7 +77,7 @@ isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res) Alternative way to retrieve Part Id on MCU with no IAP Read Serial No => Read Unique ID in SPIFI (only compatible with W25Q80BV */ - w25q80bv_setup(); + w25q80bv_setup(&spi_flash); switch(iap_cmd_res->cmd_param.command_code) { @@ -92,7 +92,7 @@ isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res) /* Only 64bits used */ iap_cmd_res->status_res.iap_result[0] = 0; iap_cmd_res->status_res.iap_result[1] = 0; - w25q80bv_get_unique_id( (w25q80bv_unique_id_t*)&iap_cmd_res->status_res.iap_result[2] ); + w25q80bv_get_unique_id(&spi_flash, (w25q80bv_unique_id_t*)&iap_cmd_res->status_res.iap_result[2] ); iap_cmd_res->status_res.status_ret = CMD_SUCCESS; break; diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index fc440e6f..a325b464 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -36,105 +36,105 @@ * SSP0_SSEL is controlled by GPIO in order to handle various transfer lengths. */ -void w25q80bv_setup(void) +void w25q80bv_setup(w25q80bv_driver_t* const drv) { uint8_t device_id; - w25q80bv_spi_init(); + w25q80bv_spi_init(drv); device_id = 0; while(device_id != W25Q80BV_DEVICE_ID_RES) { - device_id = w25q80bv_get_device_id(); + device_id = w25q80bv_get_device_id(drv); } } -uint8_t w25q80bv_get_status(void) +uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv) { uint8_t value; - w25q80bv_spi_select(); - w25q80bv_spi_transfer(W25Q80BV_READ_STATUS1); - value = w25q80bv_spi_transfer(0xFF); - w25q80bv_spi_unselect(); + w25q80bv_spi_select(drv); + w25q80bv_spi_transfer(drv, W25Q80BV_READ_STATUS1); + value = w25q80bv_spi_transfer(drv, 0xFF); + w25q80bv_spi_unselect(drv); return value; } /* Release power down / Device ID */ -uint8_t w25q80bv_get_device_id(void) +uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv) { uint8_t value; - w25q80bv_spi_select(); - w25q80bv_spi_transfer(W25Q80BV_DEVICE_ID); + w25q80bv_spi_select(drv); + w25q80bv_spi_transfer(drv, W25Q80BV_DEVICE_ID); /* Read 3 dummy bytes */ - value = w25q80bv_spi_transfer(0xFF); - value = w25q80bv_spi_transfer(0xFF); - value = w25q80bv_spi_transfer(0xFF); + value = w25q80bv_spi_transfer(drv, 0xFF); + value = w25q80bv_spi_transfer(drv, 0xFF); + value = w25q80bv_spi_transfer(drv, 0xFF); /* Read Device ID shall return 0x13 for W25Q80BV */ - value = w25q80bv_spi_transfer(0xFF); + value = w25q80bv_spi_transfer(drv, 0xFF); - w25q80bv_spi_unselect(); + w25q80bv_spi_unselect(drv); return value; } -void w25q80bv_get_unique_id(w25q80bv_unique_id_t* unique_id) +void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* unique_id) { int i; uint8_t value; - w25q80bv_spi_select(); - w25q80bv_spi_transfer(W25Q80BV_UNIQUE_ID); + w25q80bv_spi_select(drv); + w25q80bv_spi_transfer(drv, W25Q80BV_UNIQUE_ID); /* Read 4 dummy bytes */ for(i=0; i<4; i++) - value = w25q80bv_spi_transfer(0xFF); + value = w25q80bv_spi_transfer(drv, 0xFF); /* Read Unique ID 64bits (8*8) */ for(i=0; i<8; i++) { - value = w25q80bv_spi_transfer(0xFF); + value = w25q80bv_spi_transfer(drv, 0xFF); unique_id->id_8b[i] = value; } - w25q80bv_spi_unselect(); + w25q80bv_spi_unselect(drv); } -void w25q80bv_wait_while_busy(void) +void w25q80bv_wait_while_busy(w25q80bv_driver_t* const drv) { - while (w25q80bv_get_status() & W25Q80BV_STATUS_BUSY); + while (w25q80bv_get_status(drv) & W25Q80BV_STATUS_BUSY); } -void w25q80bv_write_enable(void) +void w25q80bv_write_enable(w25q80bv_driver_t* const drv) { - w25q80bv_wait_while_busy(); - w25q80bv_spi_select(); - w25q80bv_spi_transfer(W25Q80BV_WRITE_ENABLE); - w25q80bv_spi_unselect(); + w25q80bv_wait_while_busy(drv); + w25q80bv_spi_select(drv); + w25q80bv_spi_transfer(drv, W25Q80BV_WRITE_ENABLE); + w25q80bv_spi_unselect(drv); } -void w25q80bv_chip_erase(void) +void w25q80bv_chip_erase(w25q80bv_driver_t* const drv) { uint8_t device_id; device_id = 0; while(device_id != W25Q80BV_DEVICE_ID_RES) { - device_id = w25q80bv_get_device_id(); + device_id = w25q80bv_get_device_id(drv); } - w25q80bv_write_enable(); - w25q80bv_wait_while_busy(); - w25q80bv_spi_select(); - w25q80bv_spi_transfer(W25Q80BV_CHIP_ERASE); - w25q80bv_spi_unselect(); + w25q80bv_write_enable(drv); + w25q80bv_wait_while_busy(drv); + w25q80bv_spi_select(drv); + w25q80bv_spi_transfer(drv, W25Q80BV_CHIP_ERASE); + w25q80bv_spi_unselect(drv); } /* write up a 256 byte page or partial page */ -void w25q80bv_page_program(const uint32_t addr, const uint16_t len, const uint8_t* data) +void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t addr, const uint16_t len, const uint8_t* data) { int i; @@ -146,21 +146,21 @@ void w25q80bv_page_program(const uint32_t addr, const uint16_t len, const uint8_ if (addr > (W25Q80BV_NUM_BYTES - len)) return; - w25q80bv_write_enable(); - w25q80bv_wait_while_busy(); + w25q80bv_write_enable(drv); + w25q80bv_wait_while_busy(drv); - w25q80bv_spi_select(); - w25q80bv_spi_transfer(W25Q80BV_PAGE_PROGRAM); - w25q80bv_spi_transfer((addr & 0xFF0000) >> 16); - w25q80bv_spi_transfer((addr & 0xFF00) >> 8); - w25q80bv_spi_transfer(addr & 0xFF); + w25q80bv_spi_select(drv); + w25q80bv_spi_transfer(drv, W25Q80BV_PAGE_PROGRAM); + w25q80bv_spi_transfer(drv, (addr & 0xFF0000) >> 16); + w25q80bv_spi_transfer(drv, (addr & 0xFF00) >> 8); + w25q80bv_spi_transfer(drv, addr & 0xFF); for (i = 0; i < len; i++) - w25q80bv_spi_transfer(data[i]); - w25q80bv_spi_unselect(); + w25q80bv_spi_transfer(drv, data[i]); + w25q80bv_spi_unselect(drv); } /* write an arbitrary number of bytes */ -void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data) +void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, const uint8_t* data) { uint16_t first_block_len; uint8_t device_id; @@ -168,7 +168,7 @@ void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data) device_id = 0; while(device_id != W25Q80BV_DEVICE_ID_RES) { - device_id = w25q80bv_get_device_id(); + device_id = w25q80bv_get_device_id(drv); } /* do nothing if we would overflow the flash */ @@ -181,7 +181,7 @@ void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data) if (len < first_block_len) first_block_len = len; if (first_block_len) { - w25q80bv_page_program(addr, first_block_len, data); + w25q80bv_page_program(drv, addr, first_block_len, data); addr += first_block_len; data += first_block_len; len -= first_block_len; @@ -189,7 +189,7 @@ void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data) /* one page at a time on boundaries */ while (len >= W25Q80BV_PAGE_LEN) { - w25q80bv_page_program(addr, W25Q80BV_PAGE_LEN, data); + w25q80bv_page_program(drv, addr, W25Q80BV_PAGE_LEN, data); addr += W25Q80BV_PAGE_LEN; data += W25Q80BV_PAGE_LEN; len -= W25Q80BV_PAGE_LEN; @@ -197,6 +197,6 @@ void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data) /* handle end not at page boundary */ if (len) { - w25q80bv_page_program(addr, len, data); + w25q80bv_page_program(drv, addr, len, data); } } diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index 49a72334..d58802d2 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -24,6 +24,8 @@ #ifndef __W25Q80BV_H__ #define __W25Q80BV_H__ +#include "w25q80bv_drv.h" + #define W25Q80BV_PAGE_LEN 256U #define W25Q80BV_NUM_PAGES 4096U #define W25Q80BV_NUM_BYTES 1048576U @@ -47,10 +49,10 @@ typedef union uint8_t id_8b[8]; /* 8*8bits 64bits Unique ID */ } w25q80bv_unique_id_t; -void w25q80bv_setup(void); -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_setup(w25q80bv_driver_t* const drv); +void w25q80bv_chip_erase(w25q80bv_driver_t* const drv); +void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, const uint8_t* data); +uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv); +void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* unique_id); #endif//__W25Q80BV_H__ diff --git a/firmware/common/w25q80bv_drv.c b/firmware/common/w25q80bv_drv.c index 3ba1952a..3639f391 100644 --- a/firmware/common/w25q80bv_drv.c +++ b/firmware/common/w25q80bv_drv.c @@ -30,7 +30,7 @@ #include #include -void w25q80bv_spi_init(void) { +void w25q80bv_spi_init(w25q80bv_driver_t* const drv) { const uint8_t serial_clock_rate = 2; const uint8_t clock_prescale_rate = 2; @@ -57,7 +57,7 @@ void w25q80bv_spi_init(void) { /* drive SSEL, HOLD, and WP pins high */ gpio_set(PORT_FLASH, (PIN_FLASH_HOLD | PIN_FLASH_WP)); - w25q80bv_spi_unselect(); + w25q80bv_spi_unselect(drv); /* Set GPIO pins as outputs. */ GPIO1_DIR |= (PIN_FLASH_HOLD | PIN_FLASH_WP); @@ -75,14 +75,17 @@ void w25q80bv_spi_init(void) { SSP_SLAVE_OUT_ENABLE); } -void w25q80bv_spi_select(void) { +void w25q80bv_spi_select(w25q80bv_driver_t* const drv) { + (void)drv; gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); } -void w25q80bv_spi_unselect(void) { +void w25q80bv_spi_unselect(w25q80bv_driver_t* const drv) { + (void)drv; gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); } -uint16_t w25q80bv_spi_transfer(const uint16_t tx_data) { +uint16_t w25q80bv_spi_transfer(w25q80bv_driver_t* const drv, const uint16_t tx_data) { + (void)drv; return ssp_transfer(SSP0_NUM, tx_data); } diff --git a/firmware/common/w25q80bv_drv.h b/firmware/common/w25q80bv_drv.h index 459fb5ed..2d7e843e 100644 --- a/firmware/common/w25q80bv_drv.h +++ b/firmware/common/w25q80bv_drv.h @@ -26,10 +26,14 @@ #include -void w25q80bv_spi_init(void); +typedef struct { + /* Empty for now */ +} w25q80bv_driver_t; -void w25q80bv_spi_select(void); -uint16_t w25q80bv_spi_transfer(const uint16_t tx_data); -void w25q80bv_spi_unselect(void); +void w25q80bv_spi_init(w25q80bv_driver_t* const drv); + +void w25q80bv_spi_select(w25q80bv_driver_t* const drv); +uint16_t w25q80bv_spi_transfer(w25q80bv_driver_t* const drv, const uint16_t tx_data); +void w25q80bv_spi_unselect(w25q80bv_driver_t* const drv); #endif//__W25Q80BV_DRV_H__ diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index 93c12065..97b1771b 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -26,6 +26,8 @@ #include +#include + #include uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN]; @@ -36,9 +38,9 @@ usb_request_status_t usb_vendor_request_erase_spiflash( //FIXME This should refuse to run if executing from SPI flash. if (stage == USB_TRANSFER_STAGE_SETUP) { - w25q80bv_setup(); + w25q80bv_setup(&spi_flash); /* only chip erase is implemented */ - w25q80bv_chip_erase(); + w25q80bv_chip_erase(&spi_flash); usb_transfer_schedule_ack(endpoint->in); //FIXME probably should undo w25q80bv_setup() } @@ -62,7 +64,7 @@ usb_request_status_t usb_vendor_request_write_spiflash( } else { usb_transfer_schedule_block(endpoint->out, &spiflash_buffer[0], len, NULL, NULL); - w25q80bv_setup(); + w25q80bv_setup(&spi_flash); return USB_REQUEST_STATUS_OK; } } else if (stage == USB_TRANSFER_STAGE_DATA) { @@ -73,7 +75,7 @@ usb_request_status_t usb_vendor_request_write_spiflash( || ((addr + len) > W25Q80BV_NUM_BYTES)) { return USB_REQUEST_STATUS_STALL; } else { - w25q80bv_program(addr, len, &spiflash_buffer[0]); + w25q80bv_program(&spi_flash, addr, len, &spiflash_buffer[0]); usb_transfer_schedule_ack(endpoint->in); //FIXME probably should undo w25q80bv_setup() return USB_REQUEST_STATUS_OK;