Added Ref Count

pull/7774/head
Offir Kochalsky 2018-08-16 18:45:48 +03:00
parent ed83b8e4c1
commit 4cd9132db8
2 changed files with 203 additions and 182 deletions

View File

@ -100,7 +100,7 @@ static unsigned int local_math_power(int base, int exp);
//*********************** //***********************
SPIFBlockDevice::SPIFBlockDevice( SPIFBlockDevice::SPIFBlockDevice(
PinName mosi, PinName miso, PinName sclk, PinName csel, int freq) PinName mosi, PinName miso, PinName sclk, PinName csel, int freq)
: _spi(mosi, miso, sclk), _cs(csel), _device_size_bytes(0), _is_initialized(false) : _spi(mosi, miso, sclk), _cs(csel), _device_size_bytes(0), _is_initialized(false), _init_ref_count(0)
{ {
_address_size = SPIF_ADDR_SIZE_3_BYTES; _address_size = SPIF_ADDR_SIZE_3_BYTES;
// Initial SFDP read tables are read with 8 dummy cycles // Initial SFDP read tables are read with 8 dummy cycles
@ -117,7 +117,7 @@ SPIFBlockDevice::SPIFBlockDevice(
tr_error("ERROR: SPI Set Frequency Failed"); tr_error("ERROR: SPI Set Frequency Failed");
} }
_cs = 1; _cs = 1;
} }
int SPIFBlockDevice::init() int SPIFBlockDevice::init()
@ -132,7 +132,14 @@ int SPIFBlockDevice::init()
spif_bd_error spi_status = SPIF_BD_ERROR_OK; spif_bd_error spi_status = SPIF_BD_ERROR_OK;
_mutex->lock(); _mutex->lock();
if (_is_initialized == true) {
if (!_is_initialized) {
_init_ref_count = 0;
}
_init_ref_count++;
if (_init_ref_count != 1) {
goto exit_point; goto exit_point;
} }
@ -214,18 +221,29 @@ exit_point:
int SPIFBlockDevice::deinit() int SPIFBlockDevice::deinit()
{ {
spif_bd_error status = SPIF_BD_ERROR_OK;
_mutex->lock(); _mutex->lock();
if (_is_initialized == false) {
_mutex->unlock(); if (!_is_initialized) {
return SPIF_BD_ERROR_OK; _init_ref_count = 0;
goto exit_point;
}
_init_ref_count--;
if (_init_ref_count) {
goto exit_point;
} }
// Disable Device for Writing // Disable Device for Writing
spif_bd_error status = _spi_send_general_command(SPIF_WRDI, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0); status = _spi_send_general_command(SPIF_WRDI, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
if (status != SPIF_BD_ERROR_OK) { if (status != SPIF_BD_ERROR_OK) {
tr_error("ERROR: Write Disable failed"); tr_error("ERROR: Write Disable failed");
} }
_is_initialized = false; _is_initialized = false;
exit_point:
_mutex->unlock(); _mutex->unlock();
return status; return status;
@ -251,52 +269,51 @@ int SPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
_mutex->unlock(); _mutex->unlock();
return status; return status;
} }
int SPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) int SPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
{ {
if (!_is_initialized) { if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR; return BD_ERROR_DEVICE_ERROR;
} }
bool program_failed = false; bool program_failed = false;
int status = SPIF_BD_ERROR_OK; int status = SPIF_BD_ERROR_OK;
uint32_t offset = 0; uint32_t offset = 0;
uint32_t chunk = 0; uint32_t chunk = 0;
tr_debug("DEBUG: program - Buff: 0x%x, addr: %llu, size: %llu", buffer, addr, size); tr_debug("DEBUG: program - Buff: 0x%x, addr: %llu, size: %llu", buffer, addr, size);
while (size > 0) { while (size > 0) {
// Write on _page_size_bytes boundaries (Default 256 bytes a page) // Write on _page_size_bytes boundaries (Default 256 bytes a page)
offset = addr % _page_size_bytes; offset = addr % _page_size_bytes;
chunk = (offset + size < _page_size_bytes) ? size : (_page_size_bytes - offset); chunk = (offset + size < _page_size_bytes) ? size : (_page_size_bytes - offset);
_mutex->lock(); _mutex->lock();
//Send WREN //Send WREN
if (_set_write_enable() != 0) { if (_set_write_enable() != 0) {
tr_error("ERROR: Write Enabe failed\n"); tr_error("ERROR: Write Enabe failed\n");
program_failed = true; program_failed = true;
status = SPIF_BD_ERROR_WREN_FAILED; status = SPIF_BD_ERROR_WREN_FAILED;
goto exit_point; goto exit_point;
} }
_spi_send_program_command(_prog_instruction, buffer, addr, chunk); _spi_send_program_command(_prog_instruction, buffer, addr, chunk);
buffer = static_cast<const uint8_t *>(buffer) + chunk; buffer = static_cast<const uint8_t *>(buffer) + chunk;
addr += chunk; addr += chunk;
size -= chunk; size -= chunk;
if ( false == _is_mem_ready()) { if ( false == _is_mem_ready()) {
tr_error("ERROR: Device not ready after write, failed\n"); tr_error("ERROR: Device not ready after write, failed\n");
program_failed = true; program_failed = true;
status = SPIF_BD_ERROR_READY_FAILED; status = SPIF_BD_ERROR_READY_FAILED;
goto exit_point; goto exit_point;
} }
_mutex->unlock(); _mutex->unlock();
} }
exit_point: exit_point:
if (program_failed) { if (program_failed) {
@ -445,116 +462,117 @@ int SPIFBlockDevice::get_erase_value() const
/***************************************************/ /***************************************************/
spif_bd_error SPIFBlockDevice::_spi_set_frequency(int freq) spif_bd_error SPIFBlockDevice::_spi_set_frequency(int freq)
{ {
_spi.frequency(freq); _spi.frequency(freq);
return SPIF_BD_ERROR_OK; return SPIF_BD_ERROR_OK;
} }
spif_bd_error SPIFBlockDevice::_spi_send_read_command(int read_inst, uint8_t *buffer, bd_addr_t addr, bd_size_t size) spif_bd_error SPIFBlockDevice::_spi_send_read_command(int read_inst, uint8_t *buffer, bd_addr_t addr, bd_size_t size)
{ {
uint32_t dummy_bytes = _dummy_and_mode_cycles / 8; uint32_t dummy_bytes = _dummy_and_mode_cycles / 8;
int dummy_byte = 0; int dummy_byte = 0;
// csel must go low for the entire command (Inst, Address and Data) // csel must go low for the entire command (Inst, Address and Data)
_cs = 0; _cs = 0;
// Write 1 byte Instruction // Write 1 byte Instruction
_spi.write(read_inst); _spi.write(read_inst);
// Write Address (can be either 3 or 4 bytes long) // Write Address (can be either 3 or 4 bytes long)
for (int address_shift = ((_address_size-1) * 8); address_shift >= 0; address_shift -= 8) { for (int address_shift = ((_address_size - 1) * 8); address_shift >= 0; address_shift -= 8) {
_spi.write((addr >> address_shift) & 0xFF); _spi.write((addr >> address_shift) & 0xFF);
} }
// Write Dummy Cycles Bytes // Write Dummy Cycles Bytes
for (uint32_t i = 0; i < dummy_bytes; i++) { for (uint32_t i = 0; i < dummy_bytes; i++) {
_spi.write(dummy_byte); _spi.write(dummy_byte);
} }
// Read Data // Read Data
for (bd_size_t i = 0; i < size; i++) { for (bd_size_t i = 0; i < size; i++) {
buffer[i] = _spi.write(0); buffer[i] = _spi.write(0);
} }
// csel back to high // csel back to high
_cs = 1; _cs = 1;
return SPIF_BD_ERROR_OK; return SPIF_BD_ERROR_OK;
} }
spif_bd_error SPIFBlockDevice::_spi_send_program_command(int prog_inst, const void *buffer, bd_addr_t addr, bd_size_t size) spif_bd_error SPIFBlockDevice::_spi_send_program_command(int prog_inst, const void *buffer, bd_addr_t addr,
bd_size_t size)
{ {
// Send Program (write) command to device driver // Send Program (write) command to device driver
uint32_t dummy_bytes = _dummy_and_mode_cycles / 8; uint32_t dummy_bytes = _dummy_and_mode_cycles / 8;
int dummy_byte = 0; int dummy_byte = 0;
uint8_t *data = (uint8_t *)buffer; uint8_t *data = (uint8_t *)buffer;
// csel must go low for the entire command (Inst, Address and Data) // csel must go low for the entire command (Inst, Address and Data)
_cs = 0; _cs = 0;
// Write 1 byte Instruction // Write 1 byte Instruction
_spi.write(prog_inst); _spi.write(prog_inst);
// Write Address (can be either 3 or 4 bytes long) // Write Address (can be either 3 or 4 bytes long)
for (int address_shift = ((_address_size-1) * 8); address_shift >= 0; address_shift -= 8) { for (int address_shift = ((_address_size - 1) * 8); address_shift >= 0; address_shift -= 8) {
_spi.write((addr >> address_shift) & 0xFF); _spi.write((addr >> address_shift) & 0xFF);
} }
// Write Dummy Cycles Bytes // Write Dummy Cycles Bytes
for (uint32_t i = 0; i < dummy_bytes; i++) { for (uint32_t i = 0; i < dummy_bytes; i++) {
_spi.write(dummy_byte); _spi.write(dummy_byte);
} }
// Write Data // Write Data
for (bd_size_t i = 0; i < size; i++) { for (bd_size_t i = 0; i < size; i++) {
_spi.write(data[i]); _spi.write(data[i]);
} }
// csel back to high // csel back to high
_cs = 1; _cs = 1;
return SPIF_BD_ERROR_OK; return SPIF_BD_ERROR_OK;
} }
spif_bd_error SPIFBlockDevice::_spi_send_erase_command(int erase_inst, bd_addr_t addr, bd_size_t size) spif_bd_error SPIFBlockDevice::_spi_send_erase_command(int erase_inst, bd_addr_t addr, bd_size_t size)
{ {
tr_info("INFO: Erase Inst: 0x%xh, addr: %llu, size: %llu", erase_inst, addr, size); tr_info("INFO: Erase Inst: 0x%xh, addr: %llu, size: %llu", erase_inst, addr, size);
addr = (((int)addr) & 0x00FFF000); addr = (((int)addr) & 0x00FFF000);
_spi_send_general_command(erase_inst, addr, NULL, 0, NULL, 0); _spi_send_general_command(erase_inst, addr, NULL, 0, NULL, 0);
return SPIF_BD_ERROR_OK; return SPIF_BD_ERROR_OK;
} }
spif_bd_error SPIFBlockDevice::_spi_send_general_command(int instruction, bd_addr_t addr, char *tx_buffer, spif_bd_error SPIFBlockDevice::_spi_send_general_command(int instruction, bd_addr_t addr, char *tx_buffer,
size_t tx_length, char *rx_buffer, size_t rx_length) size_t tx_length, char *rx_buffer, size_t rx_length)
{ {
// Send a general command Instruction to driver // Send a general command Instruction to driver
uint32_t dummy_bytes = _dummy_and_mode_cycles / 8; uint32_t dummy_bytes = _dummy_and_mode_cycles / 8;
uint8_t dummy_byte = 0x00; uint8_t dummy_byte = 0x00;
// csel must go low for the entire command (Inst, Address and Data) // csel must go low for the entire command (Inst, Address and Data)
_cs = 0; _cs = 0;
// Write 1 byte Instruction // Write 1 byte Instruction
_spi.write(instruction); _spi.write(instruction);
// Reading SPI Bus registers does not require Flash Address // Reading SPI Bus registers does not require Flash Address
if (addr != SPI_NO_ADDRESS_COMMAND) { if (addr != SPI_NO_ADDRESS_COMMAND) {
// Write Address (can be either 3 or 4 bytes long) // Write Address (can be either 3 or 4 bytes long)
for (int address_shift = ((_address_size-1) * 8); address_shift >= 0; address_shift -= 8) { for (int address_shift = ((_address_size - 1) * 8); address_shift >= 0; address_shift -= 8) {
_spi.write((addr >> address_shift) & 0xFF); _spi.write((addr >> address_shift) & 0xFF);
} }
// Write Dummy Cycles Bytes // Write Dummy Cycles Bytes
for (uint32_t i = 0; i < dummy_bytes; i++) { for (uint32_t i = 0; i < dummy_bytes; i++) {
_spi.write(dummy_byte); _spi.write(dummy_byte);
} }
} }
// Read/Write Data // Read/Write Data
_spi.write(tx_buffer, (int)tx_length, rx_buffer, (int)rx_length); _spi.write(tx_buffer, (int)tx_length, rx_buffer, (int)rx_length);
// csel back to high // csel back to high
_cs = 1; _cs = 1;
return SPIF_BD_ERROR_OK; return SPIF_BD_ERROR_OK;
} }
/*********************************************************/ /*********************************************************/
@ -654,7 +672,8 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, si
_page_size_bytes = _sfdp_detect_page_size(param_table, basic_table_size); _page_size_bytes = _sfdp_detect_page_size(param_table, basic_table_size);
// Detect and Set Erase Types // Detect and Set Erase Types
_sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _erase4k_inst, _erase_type_inst_arr, _erase_type_size_arr); _sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _erase4k_inst, _erase_type_inst_arr,
_erase_type_size_arr);
_erase_instruction = _erase4k_inst; _erase_instruction = _erase4k_inst;
// Detect and Set fastest Bus mode (default 1-1-1) // Detect and Set fastest Bus mode (default 1-1-1)
@ -673,8 +692,8 @@ int SPIFBlockDevice::_sfdp_parse_sfdp_headers(uint32_t& basic_table_addr, size_t
// Set 1-1-1 bus mode for SFDP header parsing // Set 1-1-1 bus mode for SFDP header parsing
// Initial SFDP read tables are read with 8 dummy cycles // Initial SFDP read tables are read with 8 dummy cycles
_read_dummy_and_mode_cycles = 8; _read_dummy_and_mode_cycles = 8;
_dummy_and_mode_cycles = 8; _dummy_and_mode_cycles = 8;
spif_bd_error status = _spi_send_read_command(SPIF_SFDP, sfdp_header, addr /*address*/, data_length); spif_bd_error status = _spi_send_read_command(SPIF_SFDP, sfdp_header, addr /*address*/, data_length);
if (status != SPIF_BD_ERROR_OK) { if (status != SPIF_BD_ERROR_OK) {
@ -737,21 +756,21 @@ int SPIFBlockDevice::_sfdp_parse_sfdp_headers(uint32_t& basic_table_addr, size_t
unsigned int SPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size) unsigned int SPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size)
{ {
unsigned int page_size = SPIF_DEFAULT_PAGE_SIZE; unsigned int page_size = SPIF_DEFAULT_PAGE_SIZE;
if (basic_param_table_size > SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE) { if (basic_param_table_size > SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE) {
// Page Size is specified by 4 Bits (N), calculated by 2^N // Page Size is specified by 4 Bits (N), calculated by 2^N
int page_to_power_size = ( (int)basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4; int page_to_power_size = ( (int)basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4;
page_size = local_math_power(2, page_to_power_size); page_size = local_math_power(2, page_to_power_size);
tr_debug("DEBUG: Detected Page Size: %d", page_size); tr_debug("DEBUG: Detected Page Size: %d", page_size);
} } else {
else { tr_debug("DEBUG: Using Default Page Size: %d", page_size);
tr_debug("DEBUG: Using Default Page Size: %d", page_size); }
}
return page_size; return page_size;
} }
int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size, int& erase4k_inst, int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size,
int& erase4k_inst,
int *erase_type_inst_arr, unsigned int *erase_type_size_arr) int *erase_type_inst_arr, unsigned int *erase_type_size_arr)
{ {
erase4k_inst = 0xff; erase4k_inst = 0xff;
@ -762,39 +781,39 @@ int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param
erase4k_inst = basic_param_table_ptr[SPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE]; erase4k_inst = basic_param_table_ptr[SPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE];
if (basic_param_table_size > SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE) { if (basic_param_table_size > SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE) {
// Loop Erase Types 1-4 // Loop Erase Types 1-4
for (int i_ind = 0; i_ind < 4; i_ind++) { for (int i_ind = 0; i_ind < 4; i_ind++) {
erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type
erase_type_size_arr[i_ind] = local_math_power(2, erase_type_size_arr[i_ind] = local_math_power(2,
basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N
tr_info("DEBUG: Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), erase_type_inst_arr[i_ind], tr_info("DEBUG: Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), erase_type_inst_arr[i_ind],
erase_type_size_arr[i_ind]); erase_type_size_arr[i_ind]);
if (erase_type_size_arr[i_ind] > 1) { if (erase_type_size_arr[i_ind] > 1) {
// if size==1 type is not supported // if size==1 type is not supported
erase_type_inst_arr[i_ind] = basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind]; erase_type_inst_arr[i_ind] = basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind];
if ((erase_type_size_arr[i_ind] < _min_common_erase_size) || (_min_common_erase_size == 0) ) { if ((erase_type_size_arr[i_ind] < _min_common_erase_size) || (_min_common_erase_size == 0) ) {
//Set default minimal common erase for singal region //Set default minimal common erase for singal region
_min_common_erase_size = erase_type_size_arr[i_ind]; _min_common_erase_size = erase_type_size_arr[i_ind];
} }
// SFDP standard requires 4K Erase type to exist and its instruction to be identical to legacy field erase instruction // SFDP standard requires 4K Erase type to exist and its instruction to be identical to legacy field erase instruction
if (erase_type_size_arr[i_ind] == 4096) { if (erase_type_size_arr[i_ind] == 4096) {
found_4Kerase_type = true; found_4Kerase_type = true;
if (erase4k_inst != erase_type_inst_arr[i_ind]) { if (erase4k_inst != erase_type_inst_arr[i_ind]) {
//Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table
erase4k_inst = erase_type_inst_arr[i_ind]; erase4k_inst = erase_type_inst_arr[i_ind];
tr_warning("WARNING: _detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K"); tr_warning("WARNING: _detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K");
} }
} }
_region_erase_types_bitfield[0] |= bitfield; // If there's no region map, set region "0" types bitfield as defualt; _region_erase_types_bitfield[0] |= bitfield; // If there's no region map, set region "0" types bitfield as defualt;
} }
tr_info("INFO: Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), erase_type_inst_arr[i_ind], tr_info("INFO: Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), erase_type_inst_arr[i_ind],
erase_type_size_arr[i_ind]); erase_type_size_arr[i_ind]);
bitfield = bitfield << 1; bitfield = bitfield << 1;
} }
} }
if (false == found_4Kerase_type) { if (false == found_4Kerase_type) {
@ -803,24 +822,25 @@ int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param
return 0; return 0;
} }
int SPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int& read_inst) int SPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size,
int& read_inst)
{ {
do { do {
// TBD - SPIF Dual Read Modes Require SPI driver support // TBD - SPIF Dual Read Modes Require SPI driver support
/* /*
uint8_t examined_byte; uint8_t examined_byte;
if (basic_param_table_size > SPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE) { if (basic_param_table_size > SPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE) {
examined_byte = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE]; examined_byte = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE];
if (examined_byte & 0x01) { if (examined_byte & 0x01) {
// Fast Read 2-2-2 Supported // Fast Read 2-2-2 Supported
read_inst = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE]; read_inst = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE];
_read_dummy_and_mode_cycles = (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] >> 5) _read_dummy_and_mode_cycles = (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] >> 5)
+ (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] & 0x1F); + (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] & 0x1F);
tr_info("\nDEBUG: Read Bus Mode set to 2-2-2, Instruction: 0x%xh", read_inst); tr_info("\nDEBUG: Read Bus Mode set to 2-2-2, Instruction: 0x%xh", read_inst);
break; break;
} }
} }
examined_byte = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE]; examined_byte = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE];
if (examined_byte & 0x20) { if (examined_byte & 0x20) {
@ -839,8 +859,8 @@ int SPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_
tr_debug("\nDEBUG: Read Bus Mode set to 1-1-2, Instruction: 0x%xh", _read_instruction); tr_debug("\nDEBUG: Read Bus Mode set to 1-1-2, Instruction: 0x%xh", _read_instruction);
break; break;
} }
*/ */
_read_dummy_and_mode_cycles = 0; _read_dummy_and_mode_cycles = 0;
tr_debug("\nDEBUG: Read Bus Mode set to 1-1-1, Instruction: 0x%xh", read_inst); tr_debug("\nDEBUG: Read Bus Mode set to 1-1-1, Instruction: 0x%xh", read_inst);
} while (false); } while (false);
@ -855,7 +875,7 @@ int SPIFBlockDevice::_reset_flash_mem()
tr_info("INFO: _reset_flash_mem:\n"); tr_info("INFO: _reset_flash_mem:\n");
//Read the Status Register from device //Read the Status Register from device
if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RDSR, SPI_NO_ADDRESS_COMMAND, NULL, 0, status_value, 1) ) { if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RDSR, SPI_NO_ADDRESS_COMMAND, NULL, 0, status_value, 1) ) {
// store received values in status_value // store received values in status_value
tr_debug("DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_value[0]); tr_debug("DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_value[0]);
} else { } else {
tr_debug("ERROR: Reading Status Register failed\n"); tr_debug("ERROR: Reading Status Register failed\n");
@ -865,7 +885,7 @@ int SPIFBlockDevice::_reset_flash_mem()
if (0 == status) { if (0 == status) {
//Send Reset Enable //Send Reset Enable
if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RSTEN, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0) ) { if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RSTEN, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0) ) {
// store received values in status_value // store received values in status_value
tr_debug("DEBUG: Sending RSTEN Success\n"); tr_debug("DEBUG: Sending RSTEN Success\n");
} else { } else {
tr_error("ERROR: Sending RSTEN failed\n"); tr_error("ERROR: Sending RSTEN failed\n");
@ -875,7 +895,7 @@ int SPIFBlockDevice::_reset_flash_mem()
if (0 == status) { if (0 == status) {
//Send Reset //Send Reset
if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RST, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0)) { if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RST, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0)) {
// store received values in status_value // store received values in status_value
tr_debug("DEBUG: Sending RST Success\n"); tr_debug("DEBUG: Sending RST Success\n");
} else { } else {
tr_error("ERROR: Sending RST failed\n"); tr_error("ERROR: Sending RST failed\n");

View File

@ -37,37 +37,37 @@ enum spif_bd_error {
#define SPIF_MAX_REGIONS 10 #define SPIF_MAX_REGIONS 10
#define MAX_NUM_OF_ERASE_TYPES 4 #define MAX_NUM_OF_ERASE_TYPES 4
/** BlockDevice for SFDP based flash devices over SPI bus /** BlockDevice for SFDP based flash devices over SPI bus
* *
* @code * @code
* // Here's an example using SPI flash device on K82F target * // Here's an example using SPI flash device on K82F target
* #include "mbed.h" * #include "mbed.h"
* #include "SPIFBlockDevice.h" * #include "SPIFBlockDevice.h"
* *
* // Create flash device on SPI bus with PTE5 as chip select * // Create flash device on SPI bus with PTE5 as chip select
* SPIFBlockDevice spif(PTE2, PTE4, PTE1, PTE5); * SPIFBlockDevice spif(PTE2, PTE4, PTE1, PTE5);
* *
* int main() { * int main() {
* printf("spif test\n"); * printf("spif test\n");
* *
* // Initialize the SPI flash device and print the memory layout * // Initialize the SPI flash device and print the memory layout
* spif.init(); * spif.init();
* printf("spif size: %llu\n", spif.size()); * printf("spif size: %llu\n", spif.size());
* printf("spif read size: %llu\n", spif.get_read_size()); * printf("spif read size: %llu\n", spif.get_read_size());
* printf("spif program size: %llu\n", spif.get_program_size()); * printf("spif program size: %llu\n", spif.get_program_size());
* printf("spif erase size: %llu\n", spif.get_erase_size()); * printf("spif erase size: %llu\n", spif.get_erase_size());
* *
* // Write "Hello World!" to the first block * // Write "Hello World!" to the first block
* char *buffer = (char*)malloc(spif.get_erase_size()); * char *buffer = (char*)malloc(spif.get_erase_size());
* sprintf(buffer, "Hello World!\n"); * sprintf(buffer, "Hello World!\n");
* spif.erase(0, spif.get_erase_size()); * spif.erase(0, spif.get_erase_size());
* spif.program(buffer, 0, spif.get_erase_size()); * spif.program(buffer, 0, spif.get_erase_size());
* *
* // Read back what was stored * // Read back what was stored
* spif.read(buffer, 0, spif.get_erase_size()); * spif.read(buffer, 0, spif.get_erase_size());
* printf("%s", buffer); * printf("%s", buffer);
* *
* // Deinitialize the device * // Deinitialize the device
* spif.deinit(); * spif.deinit();
* } * }
@ -83,7 +83,7 @@ public:
* @param csel SPI chip select pin * @param csel SPI chip select pin
* @param freq Clock speed of the SPI bus (defaults to 40MHz) * @param freq Clock speed of the SPI bus (defaults to 40MHz)
*/ */
SPIFBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName csel, int freq=40000000); SPIFBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName csel, int freq = 40000000);
/** Initialize a block device /** Initialize a block device
* *
@ -185,7 +185,7 @@ public:
* @return Size of the underlying device in bytes * @return Size of the underlying device in bytes
*/ */
virtual bd_size_t size() const; virtual bd_size_t size() const;
private: private:
// Internal functions // Internal functions
@ -210,7 +210,8 @@ private:
unsigned int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size); unsigned int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size);
// Detect all supported erase types // Detect all supported erase types
int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size, int& erase4k_inst, int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size,
int& erase4k_inst,
int *erase_type_inst_arr, unsigned int *erase_type_size_arr); int *erase_type_inst_arr, unsigned int *erase_type_size_arr);
/***********************/ /***********************/
@ -238,7 +239,7 @@ private:
// Send Generic command_transfer command to Driver // Send Generic command_transfer command to Driver
spif_bd_error _spi_send_general_command(int instruction, bd_addr_t addr, char *tx_buffer, spif_bd_error _spi_send_general_command(int instruction, bd_addr_t addr, char *tx_buffer,
size_t tx_length, char *rx_buffer, size_t rx_length); size_t tx_length, char *rx_buffer, size_t rx_length);
// Send set_frequency command to Driver // Send set_frequency command to Driver
spif_bd_error _spi_set_frequency(int freq); spif_bd_error _spi_set_frequency(int freq);
@ -289,7 +290,7 @@ private:
unsigned int _read_dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Read Bus Mode unsigned int _read_dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Read Bus Mode
unsigned int _write_dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Write Bus Mode unsigned int _write_dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Write Bus Mode
unsigned int _dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Current Bus Mode unsigned int _dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Current Bus Mode
uint32_t _init_ref_count;
bool _is_initialized; bool _is_initialized;
}; };