/** * @fn spi_flash_erase * @brief Erase from data from SPI flash * @param[IN] u32Offset * Address to write to at the SPI flash * @param[IN] u32Sz * Data size * @return Status of execution * @note Data size is limited by the SPI flash size only */ sint8 spi_flash_erase(uint32 u32Offset, uint32 u32Sz) { uint32 i = 0; sint8 ret = M2M_SUCCESS; uint8 tmp = 0; #ifdef PROFILING uint32 t; t = GetTickCount(); #endif M2M_PRINT("\r\n>Start erasing...\r\n"); for(i = u32Offset; i < (u32Sz +u32Offset); i += (16*FLASH_PAGE_SZ)) { ret += spi_flash_write_enable(); ret += spi_flash_read_status_reg(&tmp); ret += spi_flash_sector_erase(i + 10); ret += spi_flash_read_status_reg(&tmp); do { if(ret != M2M_SUCCESS) goto ERR; ret += spi_flash_read_status_reg(&tmp); }while(tmp & 0x01); } M2M_PRINT("Done\r\n"); #ifdef PROFILING M2M_PRINT("#Erase time = %f sec\n", (GetTickCount()-t)/1000.0); #endif ERR: return ret; }
/** * @fn spi_flash_pp * @brief Program data of size less than a page (256 bytes) at the SPI flash * @param[IN] u32Offset * Address to write to at the SPI flash * @param[IN] pu8Buf * Pointer to data buffer * @param[IN] u32Sz * Data size * @return Status of execution */ static sint8 spi_flash_pp(uint32 u32Offset, uint8 *pu8Buf, uint16 u16Sz) { sint8 ret = M2M_SUCCESS; uint8 tmp; spi_flash_write_enable(); /* use shared packet memory as temp mem */ ret += nm_write_block(HOST_SHARE_MEM_BASE, pu8Buf, u16Sz); ret += spi_flash_page_program(HOST_SHARE_MEM_BASE, u32Offset, u16Sz); ret += spi_flash_read_status_reg(&tmp); do { if(ret != M2M_SUCCESS) goto ERR; ret += spi_flash_read_status_reg(&tmp); }while(tmp & 0x01); ret += spi_flash_write_disable(); ERR: return ret; }
/** **************************************************************************************** * @brief Wait till flash is ready for next action * @return Success : ERR_OK * Failure : ERR_TIMEOUT **************************************************************************************** */ int8_t spi_flash_wait_till_ready (void) { uint32_t statusReadCount; for (statusReadCount = 0; statusReadCount < MAX_READY_WAIT_COUNT; statusReadCount++) { if ((spi_flash_read_status_reg() & STATUS_BUSY) == 0) return ERR_OK; } return ERR_TIMEOUT; }
/** **************************************************************************************** * @brief Selects the memory protection configuration * @param[in] SPI_flash_memory_protection_setting * @return error code or success (ERR_OK) **************************************************************************************** */ int32_t spi_flash_configure_memory_protection(uint8_t spi_flash_memory_protection_setting) { if (spi_flash_detected_device == 0) return ERR_UNKNOWN_FLASH_VENDOR; // cannot configure memory protection for an unknown device if (spi_flash_set_write_enable() != ERR_OK) // send [Write Enable] instruction return ERR_TIMEOUT; return spi_flash_write_status_reg((spi_flash_read_status_reg() & (~spi_flash_detected_device->memory_protection_bitmask)) |\ ((spi_flash_memory_protection_setting)&(spi_flash_detected_device->memory_protection_bitmask))); }
/** **************************************************************************************** * @brief Issue a Write Disable Command * @return error code or success (ERR_OK) **************************************************************************************** */ int8_t spi_flash_set_write_disable(void) { uint32_t commandSendCount; uint32_t statusReadCount; uint8_t status; if (spi_flash_wait_till_ready() == ERR_OK) { spi_set_bitmode(SPI_MODE_8BIT); // set SPI bitmode to 8-bit for (commandSendCount = 0; commandSendCount < MAX_COMMAND_SEND_COUNT; commandSendCount++) { spi_transaction(WRITE_DISABLE); // send instruction for (statusReadCount = 0; statusReadCount < MAX_READY_WAIT_COUNT; statusReadCount++) { status = spi_flash_read_status_reg(); if ( ((status & STATUS_BUSY) == 0) && ((status & STATUS_WEL) == 0) ) return ERR_OK; } } } return ERR_TIMEOUT; }