| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- #include "spi_mem_worker_i.h"
- #include "spi_mem_chip.h"
- #include "spi_mem_tools.h"
- #include "../../spi_mem_files.h"
- static void spi_mem_worker_chip_detect_process(SPIMemWorker* worker);
- static void spi_mem_worker_read_process(SPIMemWorker* worker);
- static void spi_mem_worker_verify_process(SPIMemWorker* worker);
- static void spi_mem_worker_erase_process(SPIMemWorker* worker);
- static void spi_mem_worker_write_process(SPIMemWorker* worker);
- const SPIMemWorkerModeType spi_mem_worker_modes[] = {
- [SPIMemWorkerModeIdle] = {.process = NULL},
- [SPIMemWorkerModeChipDetect] = {.process = spi_mem_worker_chip_detect_process},
- [SPIMemWorkerModeRead] = {.process = spi_mem_worker_read_process},
- [SPIMemWorkerModeVerify] = {.process = spi_mem_worker_verify_process},
- [SPIMemWorkerModeErase] = {.process = spi_mem_worker_erase_process},
- [SPIMemWorkerModeWrite] = {.process = spi_mem_worker_write_process}};
- static void spi_mem_worker_run_callback(SPIMemWorker* worker, SPIMemCustomEventWorker event) {
- if(worker->callback) {
- worker->callback(worker->cb_ctx, event);
- }
- }
- static bool spi_mem_worker_await_chip_busy(SPIMemWorker* worker) {
- while(true) {
- furi_delay_tick(10); // to give some time to OS
- if(spi_mem_worker_check_for_stop(worker)) return true;
- SPIMemChipStatus chip_status = spi_mem_tools_get_chip_status(worker->chip_info);
- if(chip_status == SPIMemChipStatusError) return false;
- if(chip_status == SPIMemChipStatusBusy) continue;
- return true;
- }
- }
- static size_t spi_mem_worker_modes_get_total_size(SPIMemWorker* worker) {
- size_t chip_size = spi_mem_chip_get_size(worker->chip_info);
- size_t file_size = spi_mem_file_get_size(worker->cb_ctx);
- size_t total_size = chip_size;
- if(chip_size > file_size) total_size = file_size;
- return total_size;
- }
- // ChipDetect
- static void spi_mem_worker_chip_detect_process(SPIMemWorker* worker) {
- SPIMemCustomEventWorker event;
- while(!spi_mem_tools_read_chip_info(worker->chip_info)) {
- furi_delay_tick(10); // to give some time to OS
- if(spi_mem_worker_check_for_stop(worker)) return;
- }
- if(spi_mem_chip_find_all(worker->chip_info, *worker->found_chips)) {
- event = SPIMemCustomEventWorkerChipIdentified;
- } else {
- event = SPIMemCustomEventWorkerChipUnknown;
- }
- spi_mem_worker_run_callback(worker, event);
- }
- // Read
- static bool spi_mem_worker_read(SPIMemWorker* worker, SPIMemCustomEventWorker* event) {
- uint8_t data_buffer[SPI_MEM_FILE_BUFFER_SIZE];
- size_t chip_size = spi_mem_chip_get_size(worker->chip_info);
- size_t offset = 0;
- bool success = true;
- while(true) {
- furi_delay_tick(10); // to give some time to OS
- size_t block_size = SPI_MEM_FILE_BUFFER_SIZE;
- if(spi_mem_worker_check_for_stop(worker)) break;
- if(offset >= chip_size) break;
- if((offset + block_size) > chip_size) block_size = chip_size - offset;
- if(!spi_mem_tools_read_block(worker->chip_info, offset, data_buffer, block_size)) {
- *event = SPIMemCustomEventWorkerChipFail;
- success = false;
- break;
- }
- if(!spi_mem_file_write_block(worker->cb_ctx, data_buffer, block_size)) {
- success = false;
- break;
- }
- offset += block_size;
- spi_mem_worker_run_callback(worker, SPIMemCustomEventWorkerBlockReaded);
- }
- if(success) *event = SPIMemCustomEventWorkerDone;
- return success;
- }
- static void spi_mem_worker_read_process(SPIMemWorker* worker) {
- SPIMemCustomEventWorker event = SPIMemCustomEventWorkerFileFail;
- do {
- if(!spi_mem_worker_await_chip_busy(worker)) break;
- if(!spi_mem_file_create_open(worker->cb_ctx)) break;
- if(!spi_mem_worker_read(worker, &event)) break;
- } while(0);
- spi_mem_file_close(worker->cb_ctx);
- spi_mem_worker_run_callback(worker, event);
- }
- // Verify
- static bool
- spi_mem_worker_verify(SPIMemWorker* worker, size_t total_size, SPIMemCustomEventWorker* event) {
- uint8_t data_buffer_chip[SPI_MEM_FILE_BUFFER_SIZE];
- uint8_t data_buffer_file[SPI_MEM_FILE_BUFFER_SIZE];
- size_t offset = 0;
- bool success = true;
- while(true) {
- furi_delay_tick(10); // to give some time to OS
- size_t block_size = SPI_MEM_FILE_BUFFER_SIZE;
- if(spi_mem_worker_check_for_stop(worker)) break;
- if(offset >= total_size) break;
- if((offset + block_size) > total_size) block_size = total_size - offset;
- if(!spi_mem_tools_read_block(worker->chip_info, offset, data_buffer_chip, block_size)) {
- *event = SPIMemCustomEventWorkerChipFail;
- success = false;
- break;
- }
- if(!spi_mem_file_read_block(worker->cb_ctx, data_buffer_file, block_size)) {
- success = false;
- break;
- }
- if(memcmp(data_buffer_chip, data_buffer_file, block_size) != 0) {
- *event = SPIMemCustomEventWorkerVerifyFail;
- success = false;
- break;
- }
- offset += block_size;
- spi_mem_worker_run_callback(worker, SPIMemCustomEventWorkerBlockReaded);
- }
- if(success) *event = SPIMemCustomEventWorkerDone;
- return success;
- }
- static void spi_mem_worker_verify_process(SPIMemWorker* worker) {
- SPIMemCustomEventWorker event = SPIMemCustomEventWorkerFileFail;
- size_t total_size = spi_mem_worker_modes_get_total_size(worker);
- do {
- if(!spi_mem_worker_await_chip_busy(worker)) break;
- if(!spi_mem_file_open(worker->cb_ctx)) break;
- if(!spi_mem_worker_verify(worker, total_size, &event)) break;
- } while(0);
- spi_mem_file_close(worker->cb_ctx);
- spi_mem_worker_run_callback(worker, event);
- }
- // Erase
- static void spi_mem_worker_erase_process(SPIMemWorker* worker) {
- SPIMemCustomEventWorker event = SPIMemCustomEventWorkerChipFail;
- do {
- if(!spi_mem_worker_await_chip_busy(worker)) break;
- if(!spi_mem_tools_erase_chip(worker->chip_info)) break;
- if(!spi_mem_worker_await_chip_busy(worker)) break;
- event = SPIMemCustomEventWorkerDone;
- } while(0);
- spi_mem_worker_run_callback(worker, event);
- }
- // Write
- static bool spi_mem_worker_write_block_by_page(
- SPIMemWorker* worker,
- size_t offset,
- uint8_t* data,
- size_t block_size,
- size_t page_size) {
- for(size_t i = 0; i < block_size; i += page_size) {
- if(!spi_mem_worker_await_chip_busy(worker)) return false;
- if(!spi_mem_tools_write_bytes(worker->chip_info, offset, data, page_size)) return false;
- offset += page_size;
- data += page_size;
- }
- return true;
- }
- static bool
- spi_mem_worker_write(SPIMemWorker* worker, size_t total_size, SPIMemCustomEventWorker* event) {
- bool success = true;
- uint8_t data_buffer[SPI_MEM_FILE_BUFFER_SIZE];
- size_t page_size = spi_mem_chip_get_page_size(worker->chip_info);
- size_t offset = 0;
- while(true) {
- furi_delay_tick(10); // to give some time to OS
- size_t block_size = SPI_MEM_FILE_BUFFER_SIZE;
- if(spi_mem_worker_check_for_stop(worker)) break;
- if(offset >= total_size) break;
- if((offset + block_size) > total_size) block_size = total_size - offset;
- if(!spi_mem_file_read_block(worker->cb_ctx, data_buffer, block_size)) {
- *event = SPIMemCustomEventWorkerFileFail;
- success = false;
- break;
- }
- if(!spi_mem_worker_write_block_by_page(
- worker, offset, data_buffer, block_size, page_size)) {
- success = false;
- break;
- }
- offset += block_size;
- spi_mem_worker_run_callback(worker, SPIMemCustomEventWorkerBlockReaded);
- }
- return success;
- }
- static void spi_mem_worker_write_process(SPIMemWorker* worker) {
- SPIMemCustomEventWorker event = SPIMemCustomEventWorkerChipFail;
- size_t total_size =
- spi_mem_worker_modes_get_total_size(worker); // need to be executed before opening file
- do {
- if(!spi_mem_file_open(worker->cb_ctx)) break;
- if(!spi_mem_worker_await_chip_busy(worker)) break;
- if(!spi_mem_worker_write(worker, total_size, &event)) break;
- if(!spi_mem_worker_await_chip_busy(worker)) break;
- event = SPIMemCustomEventWorkerDone;
- } while(0);
- spi_mem_file_close(worker->cb_ctx);
- spi_mem_worker_run_callback(worker, event);
- }
|