SPI Flash: add function to clear SPI flash status register

This commit is contained in:
Dominic Spill
2017-11-06 10:42:19 -07:00
parent f20763419f
commit c416fa1294
8 changed files with 105 additions and 16 deletions

View File

@ -38,6 +38,7 @@
#define W25Q80BV_FAST_READ 0x0b #define W25Q80BV_FAST_READ 0x0b
#define W25Q80BV_WRITE_ENABLE 0x06 #define W25Q80BV_WRITE_ENABLE 0x06
#define W25Q80BV_CHIP_ERASE 0xC7 #define W25Q80BV_CHIP_ERASE 0xC7
#define W25Q80BV_WRITE_STATUS 0x01
#define W25Q80BV_READ_STATUS1 0x05 #define W25Q80BV_READ_STATUS1 0x05
#define W25Q80BV_READ_STATUS2 0x35 #define W25Q80BV_READ_STATUS2 0x35
#define W25Q80BV_PAGE_PROGRAM 0x02 #define W25Q80BV_PAGE_PROGRAM 0x02
@ -76,17 +77,6 @@ uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv)
return data[1]; return data[1];
} }
void w25q80bv_get_full_status(w25q80bv_driver_t* const drv, uint8_t* data)
{
uint8_t cmd[] = { W25Q80BV_READ_STATUS1, 0xFF };
spi_bus_transfer(drv->bus, cmd, ARRAY_SIZE(cmd));
data[0] = cmd[1];
cmd[0] =W25Q80BV_READ_STATUS2;
cmd[1] = 0xFF;
spi_bus_transfer(drv->bus, cmd, ARRAY_SIZE(cmd));
data[1] = cmd[1];
}
/* Release power down / Device ID */ /* Release power down / Device ID */
uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv) uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv)
{ {
@ -237,3 +227,22 @@ void w25q80bv_read(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, ui
spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers)); spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers));
} }
void w25q80bv_clear_status(w25q80bv_driver_t* const drv)
{
w25q80bv_write_enable(drv);
w25q80bv_wait_while_busy(drv);
uint8_t data[] = { W25Q80BV_WRITE_STATUS, 0x00, 0x00 };
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
}
void w25q80bv_get_full_status(w25q80bv_driver_t* const drv, uint8_t* data)
{
uint8_t cmd[] = { W25Q80BV_READ_STATUS1, 0xFF };
spi_bus_transfer(drv->bus, cmd, ARRAY_SIZE(cmd));
data[0] = cmd[1];
cmd[0] =W25Q80BV_READ_STATUS2;
cmd[1] = 0xFF;
spi_bus_transfer(drv->bus, cmd, ARRAY_SIZE(cmd));
data[1] = cmd[1];
}

View File

@ -59,5 +59,6 @@ void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len,
uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv); 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); void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* unique_id);
void w25q80bv_read(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* const data); void w25q80bv_read(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* const data);
void w25q80bv_clear_status(w25q80bv_driver_t* const drv);
#endif//__W25Q80BV_H__ #endif//__W25Q80BV_H__

View File

@ -90,7 +90,8 @@ static const usb_request_handler_fn vendor_request_handler[] = {
usb_vendor_request_set_hw_sync_mode, usb_vendor_request_set_hw_sync_mode,
usb_vendor_request_reset, usb_vendor_request_reset,
usb_vendor_request_operacake_set_ranges, usb_vendor_request_operacake_set_ranges,
usb_vendor_request_spiflash_status usb_vendor_request_spiflash_status,
usb_vendor_request_spiflash_clear_status
}; };
static const uint32_t vendor_request_handler_count = static const uint32_t vendor_request_handler_count =

View File

@ -136,3 +136,13 @@ usb_request_status_t usb_vendor_request_spiflash_status(
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
} }
usb_request_status_t usb_vendor_request_spiflash_clear_status(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
{
if (stage == USB_TRANSFER_STAGE_SETUP) {
w25q80bv_clear_status(&spi_flash);
usb_transfer_schedule_ack(endpoint->in);
}
return USB_REQUEST_STATUS_OK;
}

View File

@ -34,5 +34,7 @@ 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);
usb_request_status_t usb_vendor_request_spiflash_status( usb_request_status_t usb_vendor_request_spiflash_status(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_spiflash_clear_status(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
#endif /* end of include guard: __USB_API_SPIFLASH_H__ */ #endif /* end of include guard: __USB_API_SPIFLASH_H__ */

View File

@ -54,6 +54,7 @@ static struct option long_options[] = {
{ "device", required_argument, 0, 'd' }, { "device", required_argument, 0, 'd' },
{ "reset", no_argument, 0, 'R' }, { "reset", no_argument, 0, 'R' },
{ "status", no_argument, 0, 's' }, { "status", no_argument, 0, 's' },
{ "clear", no_argument, 0, 'c' },
{ "verbose", no_argument, 0, 'v' }, { "verbose", no_argument, 0, 'v' },
{ "help", no_argument, 0, 'h' }, { "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 },
@ -97,6 +98,7 @@ static void usage()
printf("\t-w, --write <filename>: Write data from file.\n"); printf("\t-w, --write <filename>: Write data from file.\n");
printf("\t-d, --device <serialnumber>: Serial number of device, if multiple devices\n"); printf("\t-d, --device <serialnumber>: Serial number of device, if multiple devices\n");
printf("\t-s, --status: Read SPI flash status registers before other operations.\n"); printf("\t-s, --status: Read SPI flash status registers before other operations.\n");
printf("\t-c, --clear: Clear SPI flash status registers before other operations.\n");
printf("\t-R, --reset: Reset HackRF after other operations.\n"); printf("\t-R, --reset: Reset HackRF after other operations.\n");
printf("\t-v, --verbose: Verbose output.\n"); printf("\t-v, --verbose: Verbose output.\n");
} }
@ -122,9 +124,10 @@ int main(int argc, char** argv)
bool verbose = false; bool verbose = false;
bool reset = false; bool reset = false;
bool read_status = false; bool read_status = false;
bool clear_status = false;
uint16_t usb_api; uint16_t usb_api;
while ((opt = getopt_long(argc, argv, "a:l:r:w:d:svRh?", long_options, while ((opt = getopt_long(argc, argv, "a:l:r:w:d:scvRh?", long_options,
&option_index)) != EOF) { &option_index)) != EOF) {
switch (opt) { switch (opt) {
case 'a': case 'a':
@ -153,6 +156,10 @@ int main(int argc, char** argv)
read_status = true; read_status = true;
break; break;
case 'c':
clear_status = true;
break;
case 'v': case 'v':
verbose = true; verbose = true;
break; break;
@ -186,7 +193,7 @@ int main(int argc, char** argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if(!(write || read || reset || read_status)) { if(!(write || read || reset || read_status || clear_status)) {
fprintf(stderr, "Specify either read, write, or reset option.\n"); fprintf(stderr, "Specify either read, write, or reset option.\n");
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
@ -249,8 +256,39 @@ int main(int argc, char** argv)
} }
if(read_status) { if(read_status) {
hackrf_spiflash_status(device, status); result = hackrf_spiflash_status(device, status);
printf("Status: 0x%02x %02x\n", status[0], status[1]); if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_spiflash_status() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
if(!verbose) {
printf("Status: 0x%02x %02x\n", status[0], status[1]);
} else {
printf("SRP0\t%x\nSEC\t%x\nTB\t%x\nBP\t%x\nWEL\t%x\nBusy\t%x\n",
(status[0] & 0x80) >> 7,
(status[0] & 0x40) >> 6,
(status[0] & 0x20) >> 5,
(status[0] & 0x1C) >> 2,
(status[0] & 0x02) >> 1,
status[0] & 0x01);
printf("SUS\t%x\nCMP\t%x\nLB\t%x\nRes\t%x\nQE\t%x\nSRP1\t%x\n",
(status[1] & 0x80) >> 7,
(status[1] & 0x40) >> 6,
(status[1] & 0x38) >> 3,
(status[1] & 0x04) >> 2,
(status[1] & 0x02) >> 1,
status[1] & 0x01);
}
}
if(clear_status) {
result = hackrf_spiflash_clear_status(device);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_spiflash_clear_status() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
} }
if(read) { if(read) {

View File

@ -80,6 +80,7 @@ typedef enum {
HACKRF_VENDOR_REQUEST_RESET = 30, HACKRF_VENDOR_REQUEST_RESET = 30,
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_RANGES = 31, HACKRF_VENDOR_REQUEST_OPERACAKE_SET_RANGES = 31,
HACKRF_VENDOR_REQUEST_SPIFLASH_STATUS = 32, HACKRF_VENDOR_REQUEST_SPIFLASH_STATUS = 32,
HACKRF_VENDOR_REQUEST_SPIFLASH_CLEAR_STATUS = 33,
} hackrf_vendor_request; } hackrf_vendor_request;
#define USB_CONFIG_STANDARD 0x1 #define USB_CONFIG_STANDARD 0x1
@ -989,6 +990,30 @@ int ADDCALL hackrf_spiflash_status(hackrf_device* device, uint8_t* data)
} }
} }
int ADDCALL hackrf_spiflash_clear_status(hackrf_device* device)
{
USB_API_REQUIRED(device, 0x0103)
int result;
result = libusb_control_transfer(
device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
HACKRF_VENDOR_REQUEST_SPIFLASH_CLEAR_STATUS,
0,
0,
NULL,
0,
0
);
if( result != 0 )
{
last_libusb_error = result;
return HACKRF_ERROR_LIBUSB;
} else {
return HACKRF_SUCCESS;
}
}
int ADDCALL hackrf_cpld_write(hackrf_device* device, int ADDCALL hackrf_cpld_write(hackrf_device* device,
unsigned char* const data, const unsigned int total_length) unsigned char* const data, const unsigned int total_length)
{ {
@ -2017,6 +2042,7 @@ int ADDCALL hackrf_set_operacake_ranges(hackrf_device* device, uint8_t* ranges,
return HACKRF_SUCCESS; return HACKRF_SUCCESS;
} }
} }
#ifdef __cplusplus #ifdef __cplusplus
} // __cplusplus defined. } // __cplusplus defined.
#endif #endif

View File

@ -177,6 +177,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_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_spiflash_status(hackrf_device* device, uint8_t* data); extern ADDAPI int ADDCALL hackrf_spiflash_status(hackrf_device* device, uint8_t* data);
extern ADDAPI int ADDCALL hackrf_spiflash_clear_status(hackrf_device* device);
/* device will need to be reset after hackrf_cpld_write */ /* device will need to be reset after hackrf_cpld_write */
extern ADDAPI int ADDCALL hackrf_cpld_write(hackrf_device* device, extern ADDAPI int ADDCALL hackrf_cpld_write(hackrf_device* device,
unsigned char* const data, const unsigned int total_length); unsigned char* const data, const unsigned int total_length);