Line data Source code
1 : // --------------------------------------------------------------------------- 2 : // USB EPROM/Flash Programmer 3 : // 4 : // Copyright (2022) Robson Martins 5 : // 6 : // This work is licensed under a Creative Commons Attribution-NonCommercial- 7 : // ShareAlike 4.0 International License. 8 : // --------------------------------------------------------------------------- 9 : /** 10 : * @ingroup Firmware 11 : * @file hal/flash.cpp 12 : * @brief Implementation of the Pico Flash Class. 13 : * 14 : * @author Robson Martins (https://www.robsonmartins.com) 15 : */ 16 : // --------------------------------------------------------------------------- 17 : 18 : #include "hal/flash.hpp" 19 : 20 : #include <cstring> 21 : 22 : #include "hardware/flash.h" 23 : #include "hardware/sync.h" 24 : #include "pico/multicore.h" 25 : 26 : // --------------------------------------------------------------------------- 27 : 28 3 : void Flash::write(const uint8_t *data, size_t len) { 29 3 : size_t tmpLen = pageSize_(len); 30 3 : size_t eraseLen = sectorSize_(tmpLen); 31 3 : size_t offset = offset_(eraseLen); 32 1539 : uint8_t *tmpBuf = new uint8_t[tmpLen](); 33 3 : std::memcpy(tmpBuf, data, len); 34 3 : write_(tmpBuf, offset, tmpLen); 35 3 : delete[] tmpBuf; 36 3 : } 37 : 38 44 : void Flash::read(uint8_t *data, size_t len) { 39 44 : size_t tmpLen = pageSize_(len); 40 44 : size_t eraseLen = sectorSize_(tmpLen); 41 44 : size_t offset = offset_(eraseLen); 42 12844 : uint8_t *tmpBuf = new uint8_t[tmpLen](); 43 44 : read_(tmpBuf, offset, tmpLen); 44 44 : std::memcpy(data, tmpBuf, len); 45 44 : delete[] tmpBuf; 46 44 : } 47 : 48 3 : bool Flash::verify(const uint8_t *data, size_t len) { 49 3 : size_t tmpLen = pageSize_(len); 50 3 : size_t eraseLen = sectorSize_(tmpLen); 51 3 : size_t offset = offset_(eraseLen); 52 2051 : uint8_t *tmpBuf = new uint8_t[tmpLen](); 53 3 : std::memcpy(tmpBuf, data, len); 54 3 : bool result = verify_(tmpBuf, offset, len); 55 3 : delete[] tmpBuf; 56 3 : return result; 57 : } 58 : 59 3 : void Flash::write_(const uint8_t *buf, size_t offset, size_t len) { 60 3 : if (!buf || !len || offset + len > PICO_FLASH_SIZE_BYTES) { 61 0 : return; 62 : } 63 3 : size_t eraseLen = sectorSize_(len); 64 3 : if (offset + eraseLen > PICO_FLASH_SIZE_BYTES) { 65 0 : return; 66 : } 67 3 : multicore_reset_core1(); 68 3 : uint32_t ints = save_and_disable_interrupts(); 69 3 : flash_range_erase(offset, eraseLen); 70 3 : flash_range_program(offset, buf, len); 71 3 : restore_interrupts(ints); 72 : } 73 : 74 46 : void Flash::read_(uint8_t *buf, size_t offset, size_t len) { 75 46 : if (!buf || !len || offset + len > PICO_FLASH_SIZE_BYTES) { 76 0 : return; 77 : } 78 : const uint8_t *pFlash = 79 46 : reinterpret_cast<const uint8_t *>(XIP_BASE + offset); 80 46 : std::memcpy(buf, pFlash, len); 81 : } 82 : 83 3 : bool Flash::verify_(const uint8_t *buf, size_t offset, size_t len) { 84 3 : if (!buf || !len || offset + len > PICO_FLASH_SIZE_BYTES) { 85 1 : return false; 86 : } 87 2050 : uint8_t *tmp = new uint8_t[len](); 88 2 : read_(tmp, offset, len); 89 2 : bool result = !std::memcmp(tmp, buf, len); 90 2 : delete[] tmp; 91 2 : return result; 92 : } 93 : 94 50 : size_t Flash::pageSize_(size_t len) { 95 50 : return (len + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE * FLASH_PAGE_SIZE; 96 : } 97 : 98 53 : size_t Flash::sectorSize_(size_t len) { 99 53 : return (len + FLASH_SECTOR_SIZE - 1) / FLASH_SECTOR_SIZE * 100 53 : FLASH_SECTOR_SIZE; 101 : } 102 : 103 50 : size_t Flash::offset_(size_t len) { 104 50 : return PICO_FLASH_SIZE_BYTES - len; 105 : }