Tiny storage(file) system on MCU internal flash memory for Nucleo F4xx. The purpose of SOFBlock class is to provide a way to write data on flash memory in the same way of file handling class in the file system.
Dependents: storage_on_flash_demo mbed_controller_demo mbed-os-example-blinky-2
March 26, 2015
Seeed Arch Max platform which is based on STM32-F407 is supported.
SOF_block.cpp@3:2bb58064d0a2, 2015-03-25 (annotated)
- Committer:
- hillkim7
- Date:
- Wed Mar 25 05:46:25 2015 +0000
- Revision:
- 3:2bb58064d0a2
- Parent:
- 2:e79a9cb05801
Fix comment.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
hillkim7 | 0:7f4bc855cb46 | 1 | /* |
hillkim7 | 0:7f4bc855cb46 | 2 | * @file SOF_block.cpp |
hillkim7 | 0:7f4bc855cb46 | 3 | * |
hillkim7 | 0:7f4bc855cb46 | 4 | * @brief MTD device handling of STM32 internal flash memory. |
hillkim7 | 0:7f4bc855cb46 | 5 | * |
hillkim7 | 0:7f4bc855cb46 | 6 | * |
hillkim7 | 0:7f4bc855cb46 | 7 | * History: |
hillkim7 | 0:7f4bc855cb46 | 8 | */ |
hillkim7 | 0:7f4bc855cb46 | 9 | |
hillkim7 | 0:7f4bc855cb46 | 10 | #include <stdio.h> |
hillkim7 | 0:7f4bc855cb46 | 11 | #include <assert.h> |
hillkim7 | 0:7f4bc855cb46 | 12 | #include "SOF_dev.h" |
hillkim7 | 0:7f4bc855cb46 | 13 | #include <string.h> |
hillkim7 | 0:7f4bc855cb46 | 14 | |
hillkim7 | 0:7f4bc855cb46 | 15 | #define LOCAL_DEBUG 0 // turn on local debug |
hillkim7 | 0:7f4bc855cb46 | 16 | |
hillkim7 | 0:7f4bc855cb46 | 17 | #define DCRLF "\r\n" |
hillkim7 | 0:7f4bc855cb46 | 18 | |
hillkim7 | 0:7f4bc855cb46 | 19 | #if LOCAL_DEBUG |
hillkim7 | 0:7f4bc855cb46 | 20 | #define DPRINTF printf |
hillkim7 | 0:7f4bc855cb46 | 21 | #define EPRINTF printf |
hillkim7 | 0:7f4bc855cb46 | 22 | #define DUMP_BLOCK dump_block |
hillkim7 | 0:7f4bc855cb46 | 23 | #define DASSERT assert |
hillkim7 | 0:7f4bc855cb46 | 24 | #else |
hillkim7 | 0:7f4bc855cb46 | 25 | #define DPRINTF(...) |
hillkim7 | 0:7f4bc855cb46 | 26 | #define EPRINTF(...) |
hillkim7 | 0:7f4bc855cb46 | 27 | #define DUMP_BLOCK(...) |
hillkim7 | 0:7f4bc855cb46 | 28 | #define DASSERT(...) |
hillkim7 | 0:7f4bc855cb46 | 29 | #endif |
hillkim7 | 0:7f4bc855cb46 | 30 | |
hillkim7 | 0:7f4bc855cb46 | 31 | static uint16_t checksum(const uint8_t* data, int count); |
hillkim7 | 0:7f4bc855cb46 | 32 | |
hillkim7 | 0:7f4bc855cb46 | 33 | #define SYNC_MARK_BYTE_IN_LEN 0x07 // signature mark for upper byte in the storage_len |
hillkim7 | 0:7f4bc855cb46 | 34 | |
hillkim7 | 0:7f4bc855cb46 | 35 | #define RESERVED_BLOCK_INFO_SIZE sizeof(BlockInfo_t) |
hillkim7 | 0:7f4bc855cb46 | 36 | |
hillkim7 | 2:e79a9cb05801 | 37 | typedef struct { |
hillkim7 | 2:e79a9cb05801 | 38 | uint16_t for_storage; |
hillkim7 | 2:e79a9cb05801 | 39 | uint16_t for_info; |
hillkim7 | 0:7f4bc855cb46 | 40 | } BlockChecksum_t; |
hillkim7 | 0:7f4bc855cb46 | 41 | |
hillkim7 | 2:e79a9cb05801 | 42 | typedef struct { |
hillkim7 | 2:e79a9cb05801 | 43 | BlockChecksum_t csum; |
hillkim7 | 2:e79a9cb05801 | 44 | uint32_t storage_len; |
hillkim7 | 0:7f4bc855cb46 | 45 | } BlockInfo_t; |
hillkim7 | 0:7f4bc855cb46 | 46 | |
hillkim7 | 2:e79a9cb05801 | 47 | typedef struct { |
hillkim7 | 2:e79a9cb05801 | 48 | uint32_t begin_offset; |
hillkim7 | 2:e79a9cb05801 | 49 | uint32_t len; |
hillkim7 | 2:e79a9cb05801 | 50 | uint16_t storage_csum; |
hillkim7 | 0:7f4bc855cb46 | 51 | } StorageInfo_t; |
hillkim7 | 0:7f4bc855cb46 | 52 | |
hillkim7 | 0:7f4bc855cb46 | 53 | class SOF_BlockHandle |
hillkim7 | 0:7f4bc855cb46 | 54 | { |
hillkim7 | 0:7f4bc855cb46 | 55 | public: |
hillkim7 | 2:e79a9cb05801 | 56 | SOF_BlockHandle() |
hillkim7 | 2:e79a9cb05801 | 57 | : write_mode_(false) |
hillkim7 | 2:e79a9cb05801 | 58 | , cur_pos_(0) |
hillkim7 | 2:e79a9cb05801 | 59 | , hdev_(SOF_INVALID_HANDLE) |
hillkim7 | 2:e79a9cb05801 | 60 | , storage_max_offset_(0) |
hillkim7 | 2:e79a9cb05801 | 61 | , storage_begin_offset_(0) |
hillkim7 | 2:e79a9cb05801 | 62 | , storage_end_offset_(0) { |
hillkim7 | 2:e79a9cb05801 | 63 | } |
hillkim7 | 0:7f4bc855cb46 | 64 | |
hillkim7 | 2:e79a9cb05801 | 65 | bool is_writable() const { |
hillkim7 | 2:e79a9cb05801 | 66 | return write_mode_; |
hillkim7 | 2:e79a9cb05801 | 67 | } |
hillkim7 | 0:7f4bc855cb46 | 68 | |
hillkim7 | 2:e79a9cb05801 | 69 | uint32_t total_physical_block_size() const { |
hillkim7 | 2:e79a9cb05801 | 70 | return SOF_dev_info(hdev_)->sec_size; |
hillkim7 | 2:e79a9cb05801 | 71 | } |
hillkim7 | 0:7f4bc855cb46 | 72 | |
hillkim7 | 0:7f4bc855cb46 | 73 | public: |
hillkim7 | 2:e79a9cb05801 | 74 | bool write_mode_; |
hillkim7 | 2:e79a9cb05801 | 75 | size_t cur_pos_; |
hillkim7 | 2:e79a9cb05801 | 76 | SOF_DevHandle_t hdev_; |
hillkim7 | 2:e79a9cb05801 | 77 | uint32_t storage_max_offset_; |
hillkim7 | 2:e79a9cb05801 | 78 | uint32_t storage_begin_offset_; |
hillkim7 | 2:e79a9cb05801 | 79 | uint32_t storage_end_offset_; |
hillkim7 | 0:7f4bc855cb46 | 80 | }; |
hillkim7 | 0:7f4bc855cb46 | 81 | |
hillkim7 | 0:7f4bc855cb46 | 82 | |
hillkim7 | 0:7f4bc855cb46 | 83 | static bool get_block_info(const SOF_BlockHandle_t handle, size_t seq, BlockInfo_t *info, uint32_t *loc_offset) |
hillkim7 | 0:7f4bc855cb46 | 84 | { |
hillkim7 | 2:e79a9cb05801 | 85 | uint32_t check_pos = ((seq+1) * sizeof(BlockInfo_t)); |
hillkim7 | 2:e79a9cb05801 | 86 | uint32_t info_pos; |
hillkim7 | 0:7f4bc855cb46 | 87 | |
hillkim7 | 2:e79a9cb05801 | 88 | DASSERT(check_pos < handle->total_physical_block_size()); |
hillkim7 | 2:e79a9cb05801 | 89 | if (check_pos >= handle->total_physical_block_size()) |
hillkim7 | 2:e79a9cb05801 | 90 | return false; |
hillkim7 | 0:7f4bc855cb46 | 91 | |
hillkim7 | 2:e79a9cb05801 | 92 | *loc_offset = info_pos = handle->total_physical_block_size() - check_pos; |
hillkim7 | 0:7f4bc855cb46 | 93 | |
hillkim7 | 2:e79a9cb05801 | 94 | // checksum in the first word |
hillkim7 | 2:e79a9cb05801 | 95 | *((uint32_t*)&info->csum) = SOF_dev_read_word(handle->hdev_, info_pos); |
hillkim7 | 2:e79a9cb05801 | 96 | // storage len in the next word |
hillkim7 | 2:e79a9cb05801 | 97 | info->storage_len = SOF_dev_read_word(handle->hdev_, info_pos + 4); |
hillkim7 | 0:7f4bc855cb46 | 98 | |
hillkim7 | 2:e79a9cb05801 | 99 | return true; |
hillkim7 | 0:7f4bc855cb46 | 100 | } |
hillkim7 | 0:7f4bc855cb46 | 101 | |
hillkim7 | 0:7f4bc855cb46 | 102 | static bool is_empty_block_info(BlockInfo_t *info) |
hillkim7 | 0:7f4bc855cb46 | 103 | { |
hillkim7 | 2:e79a9cb05801 | 104 | uint8_t *p = (uint8_t*)info; |
hillkim7 | 0:7f4bc855cb46 | 105 | |
hillkim7 | 2:e79a9cb05801 | 106 | for (size_t i = 0; i < sizeof(BlockInfo_t); ++i) |
hillkim7 | 2:e79a9cb05801 | 107 | if (p[i] != SOF_ERASED_BYTE_VALUE) |
hillkim7 | 2:e79a9cb05801 | 108 | return false; |
hillkim7 | 0:7f4bc855cb46 | 109 | |
hillkim7 | 2:e79a9cb05801 | 110 | return true; |
hillkim7 | 0:7f4bc855cb46 | 111 | } |
hillkim7 | 0:7f4bc855cb46 | 112 | |
hillkim7 | 0:7f4bc855cb46 | 113 | static bool is_valid_block_info(BlockInfo_t *info) |
hillkim7 | 0:7f4bc855cb46 | 114 | { |
hillkim7 | 2:e79a9cb05801 | 115 | uint16_t csum = checksum((uint8_t*)&info->storage_len, 4); |
hillkim7 | 0:7f4bc855cb46 | 116 | |
hillkim7 | 2:e79a9cb05801 | 117 | if (SYNC_MARK_BYTE_IN_LEN != (info->storage_len >> 24)) { |
hillkim7 | 2:e79a9cb05801 | 118 | EPRINTF("no sync mark in storage_len=%#x"DCRLF,info->storage_len); |
hillkim7 | 2:e79a9cb05801 | 119 | return false; |
hillkim7 | 2:e79a9cb05801 | 120 | } |
hillkim7 | 0:7f4bc855cb46 | 121 | |
hillkim7 | 2:e79a9cb05801 | 122 | if (csum != info->csum.for_info) { |
hillkim7 | 2:e79a9cb05801 | 123 | EPRINTF("CSUM mismatch %#x %#x"DCRLF,csum, info->csum.for_info); |
hillkim7 | 2:e79a9cb05801 | 124 | return false; |
hillkim7 | 2:e79a9cb05801 | 125 | } |
hillkim7 | 0:7f4bc855cb46 | 126 | |
hillkim7 | 2:e79a9cb05801 | 127 | return true; |
hillkim7 | 0:7f4bc855cb46 | 128 | } |
hillkim7 | 0:7f4bc855cb46 | 129 | |
hillkim7 | 0:7f4bc855cb46 | 130 | static bool get_empty_info_location(const SOF_BlockHandle_t handle, uint32_t *loc_offset) |
hillkim7 | 0:7f4bc855cb46 | 131 | { |
hillkim7 | 2:e79a9cb05801 | 132 | BlockInfo_t info; |
hillkim7 | 2:e79a9cb05801 | 133 | uint32_t pos; |
hillkim7 | 0:7f4bc855cb46 | 134 | |
hillkim7 | 2:e79a9cb05801 | 135 | for (size_t seq = 0; get_block_info(handle, seq, &info, &pos); ++seq) { |
hillkim7 | 2:e79a9cb05801 | 136 | //DPRINTF("[%u] len=%#x pos=%u"DCRLF,seq, info.storage_len, pos); |
hillkim7 | 2:e79a9cb05801 | 137 | if (is_empty_block_info(&info)) { |
hillkim7 | 2:e79a9cb05801 | 138 | *loc_offset = pos; |
hillkim7 | 2:e79a9cb05801 | 139 | return true; |
hillkim7 | 2:e79a9cb05801 | 140 | } |
hillkim7 | 2:e79a9cb05801 | 141 | } |
hillkim7 | 0:7f4bc855cb46 | 142 | |
hillkim7 | 2:e79a9cb05801 | 143 | return false; |
hillkim7 | 0:7f4bc855cb46 | 144 | } |
hillkim7 | 0:7f4bc855cb46 | 145 | |
hillkim7 | 0:7f4bc855cb46 | 146 | static SOF_Error_t probe_active_storage_info(const SOF_BlockHandle_t handle, StorageInfo_t *storage_info) |
hillkim7 | 0:7f4bc855cb46 | 147 | { |
hillkim7 | 2:e79a9cb05801 | 148 | BlockInfo_t info, last_info; |
hillkim7 | 2:e79a9cb05801 | 149 | uint32_t pos; |
hillkim7 | 2:e79a9cb05801 | 150 | uint32_t storage_len_sum = 0; |
hillkim7 | 2:e79a9cb05801 | 151 | |
hillkim7 | 2:e79a9cb05801 | 152 | for (size_t seq = 0; get_block_info(handle, seq, &info, &pos); ++seq) { |
hillkim7 | 2:e79a9cb05801 | 153 | if (is_empty_block_info(&info)) { |
hillkim7 | 2:e79a9cb05801 | 154 | if (seq == 0) |
hillkim7 | 2:e79a9cb05801 | 155 | return kSOF_ErrNoInfo; |
hillkim7 | 2:e79a9cb05801 | 156 | break; |
hillkim7 | 2:e79a9cb05801 | 157 | } |
hillkim7 | 2:e79a9cb05801 | 158 | if (!is_valid_block_info(&info)) { |
hillkim7 | 2:e79a9cb05801 | 159 | if (storage_info->begin_offset + storage_info->len == pos) { |
hillkim7 | 2:e79a9cb05801 | 160 | DPRINTF("data is full: %u"DCRLF,storage_info->begin_offset + storage_info->len); |
hillkim7 | 2:e79a9cb05801 | 161 | break; |
hillkim7 | 2:e79a9cb05801 | 162 | } |
hillkim7 | 0:7f4bc855cb46 | 163 | |
hillkim7 | 2:e79a9cb05801 | 164 | EPRINTF("invalid block at %u"DCRLF,pos); |
hillkim7 | 2:e79a9cb05801 | 165 | return kSOF_ErrBadBlock; |
hillkim7 | 2:e79a9cb05801 | 166 | } |
hillkim7 | 2:e79a9cb05801 | 167 | |
hillkim7 | 2:e79a9cb05801 | 168 | storage_len_sum += info.storage_len & 0x00FFFFFF; |
hillkim7 | 2:e79a9cb05801 | 169 | last_info = info; |
hillkim7 | 2:e79a9cb05801 | 170 | } |
hillkim7 | 0:7f4bc855cb46 | 171 | |
hillkim7 | 2:e79a9cb05801 | 172 | uint32_t storage_len = last_info.storage_len & 0x00FFFFFF; |
hillkim7 | 0:7f4bc855cb46 | 173 | |
hillkim7 | 2:e79a9cb05801 | 174 | storage_info->begin_offset = storage_len_sum - storage_len; |
hillkim7 | 2:e79a9cb05801 | 175 | storage_info->len = storage_len; |
hillkim7 | 2:e79a9cb05801 | 176 | storage_info->storage_csum = last_info.csum.for_storage; |
hillkim7 | 0:7f4bc855cb46 | 177 | |
hillkim7 | 2:e79a9cb05801 | 178 | return kSOF_ErrNone; |
hillkim7 | 0:7f4bc855cb46 | 179 | } |
hillkim7 | 0:7f4bc855cb46 | 180 | |
hillkim7 | 0:7f4bc855cb46 | 181 | |
hillkim7 | 0:7f4bc855cb46 | 182 | #if LOCAL_DEBUG |
hillkim7 | 0:7f4bc855cb46 | 183 | static void dump_block(SOF_BlockHandle_t handle) |
hillkim7 | 0:7f4bc855cb46 | 184 | { |
hillkim7 | 2:e79a9cb05801 | 185 | DPRINTF("sector(%u)"DCRLF, SOF_dev_info(handle->hdev_)->sec_no); |
hillkim7 | 2:e79a9cb05801 | 186 | DPRINTF(" offset =%u"DCRLF, handle->cur_pos_); |
hillkim7 | 2:e79a9cb05801 | 187 | DPRINTF(" writemode =%d"DCRLF, handle->write_mode_); |
hillkim7 | 2:e79a9cb05801 | 188 | DPRINTF(" storage_max_offset =%u"DCRLF, handle->storage_max_offset_); |
hillkim7 | 2:e79a9cb05801 | 189 | DPRINTF(" storage_begin_offset =%u"DCRLF, handle->storage_begin_offset_); |
hillkim7 | 2:e79a9cb05801 | 190 | DPRINTF(" storage_end_offset =%u"DCRLF, handle->storage_end_offset_); |
hillkim7 | 2:e79a9cb05801 | 191 | DPRINTF(" free=%u total=%u"DCRLF,SOF_block_get_free_size(handle), handle->total_physical_block_size()); |
hillkim7 | 0:7f4bc855cb46 | 192 | } |
hillkim7 | 0:7f4bc855cb46 | 193 | #endif |
hillkim7 | 0:7f4bc855cb46 | 194 | |
hillkim7 | 0:7f4bc855cb46 | 195 | size_t SOF_block_get_free_size(SOF_BlockHandle_t handle) |
hillkim7 | 0:7f4bc855cb46 | 196 | { |
hillkim7 | 2:e79a9cb05801 | 197 | DASSERT(handle != NULL); |
hillkim7 | 2:e79a9cb05801 | 198 | if (handle->storage_end_offset_ <= handle->storage_max_offset_-RESERVED_BLOCK_INFO_SIZE) |
hillkim7 | 2:e79a9cb05801 | 199 | return (handle->storage_max_offset_- RESERVED_BLOCK_INFO_SIZE) - handle->storage_end_offset_; |
hillkim7 | 2:e79a9cb05801 | 200 | else { |
hillkim7 | 2:e79a9cb05801 | 201 | return 0; |
hillkim7 | 2:e79a9cb05801 | 202 | } |
hillkim7 | 0:7f4bc855cb46 | 203 | } |
hillkim7 | 0:7f4bc855cb46 | 204 | |
hillkim7 | 0:7f4bc855cb46 | 205 | uint32_t SOF_block_storage_size(SOF_BlockHandle_t handle) |
hillkim7 | 0:7f4bc855cb46 | 206 | { |
hillkim7 | 2:e79a9cb05801 | 207 | DASSERT(handle != NULL); |
hillkim7 | 2:e79a9cb05801 | 208 | return handle->storage_end_offset_ - handle->storage_begin_offset_; |
hillkim7 | 0:7f4bc855cb46 | 209 | } |
hillkim7 | 0:7f4bc855cb46 | 210 | |
hillkim7 | 0:7f4bc855cb46 | 211 | static uint16_t checksum(const uint8_t* data, int count) |
hillkim7 | 0:7f4bc855cb46 | 212 | { |
hillkim7 | 2:e79a9cb05801 | 213 | // Fletcher's checksum algorithm |
hillkim7 | 2:e79a9cb05801 | 214 | uint16_t sum1 = 0; |
hillkim7 | 2:e79a9cb05801 | 215 | uint16_t sum2 = 0; |
hillkim7 | 2:e79a9cb05801 | 216 | int index; |
hillkim7 | 0:7f4bc855cb46 | 217 | |
hillkim7 | 2:e79a9cb05801 | 218 | for( index = 0; index < count; ++index ) { |
hillkim7 | 2:e79a9cb05801 | 219 | sum1 = (sum1 + data[index]) % 255; |
hillkim7 | 2:e79a9cb05801 | 220 | sum2 = (sum2 + sum1) % 255; |
hillkim7 | 2:e79a9cb05801 | 221 | } |
hillkim7 | 0:7f4bc855cb46 | 222 | |
hillkim7 | 2:e79a9cb05801 | 223 | return (sum2 << 8) | sum1; |
hillkim7 | 0:7f4bc855cb46 | 224 | } |
hillkim7 | 0:7f4bc855cb46 | 225 | |
hillkim7 | 0:7f4bc855cb46 | 226 | static uint16_t compute_storage_checksum(SOF_BlockHandle_t handle) |
hillkim7 | 0:7f4bc855cb46 | 227 | { |
hillkim7 | 2:e79a9cb05801 | 228 | uint8_t *addr = SOF_dev_get_hw_addr(handle->hdev_); |
hillkim7 | 0:7f4bc855cb46 | 229 | |
hillkim7 | 2:e79a9cb05801 | 230 | return checksum(addr+handle->storage_begin_offset_, SOF_block_storage_size(handle)); |
hillkim7 | 0:7f4bc855cb46 | 231 | } |
hillkim7 | 0:7f4bc855cb46 | 232 | |
hillkim7 | 0:7f4bc855cb46 | 233 | static bool write_storage_info(SOF_BlockHandle_t handle) |
hillkim7 | 0:7f4bc855cb46 | 234 | { |
hillkim7 | 2:e79a9cb05801 | 235 | BlockInfo_t cs; |
hillkim7 | 0:7f4bc855cb46 | 236 | |
hillkim7 | 2:e79a9cb05801 | 237 | cs.storage_len = (SYNC_MARK_BYTE_IN_LEN << 24) | SOF_block_storage_size(handle); |
hillkim7 | 2:e79a9cb05801 | 238 | cs.csum.for_info = checksum((uint8_t*)&cs.storage_len, 4); |
hillkim7 | 2:e79a9cb05801 | 239 | cs.csum.for_storage = compute_storage_checksum(handle); |
hillkim7 | 0:7f4bc855cb46 | 240 | |
hillkim7 | 2:e79a9cb05801 | 241 | DPRINTF("write %#x at %#x"DCRLF,*((uint32_t*)&cs.csum), handle->storage_max_offset_); |
hillkim7 | 2:e79a9cb05801 | 242 | if (SOF_dev_write_word(handle->hdev_, handle->storage_max_offset_, *((uint32_t*)&cs.csum)) < 0) |
hillkim7 | 2:e79a9cb05801 | 243 | return false; |
hillkim7 | 0:7f4bc855cb46 | 244 | |
hillkim7 | 2:e79a9cb05801 | 245 | if (SOF_dev_write_word(handle->hdev_, handle->storage_max_offset_+4, *((uint32_t*)&cs.storage_len)) < 0) |
hillkim7 | 2:e79a9cb05801 | 246 | return false; |
hillkim7 | 2:e79a9cb05801 | 247 | |
hillkim7 | 2:e79a9cb05801 | 248 | return true; |
hillkim7 | 0:7f4bc855cb46 | 249 | } |
hillkim7 | 0:7f4bc855cb46 | 250 | |
hillkim7 | 0:7f4bc855cb46 | 251 | static bool create_empty_storage(SOF_DevHandle_t hdev, uint8_t sector_index) |
hillkim7 | 0:7f4bc855cb46 | 252 | { |
hillkim7 | 2:e79a9cb05801 | 253 | SOF_BlockHandle handle_data; |
hillkim7 | 2:e79a9cb05801 | 254 | |
hillkim7 | 2:e79a9cb05801 | 255 | handle_data.hdev_ = hdev; |
hillkim7 | 2:e79a9cb05801 | 256 | |
hillkim7 | 2:e79a9cb05801 | 257 | uint32_t info_begin_offset; |
hillkim7 | 0:7f4bc855cb46 | 258 | |
hillkim7 | 2:e79a9cb05801 | 259 | if (!get_empty_info_location(&handle_data, &info_begin_offset)) { |
hillkim7 | 2:e79a9cb05801 | 260 | EPRINTF("no info"DCRLF); |
hillkim7 | 2:e79a9cb05801 | 261 | SOF_block_close(&handle_data); |
hillkim7 | 2:e79a9cb05801 | 262 | return false; |
hillkim7 | 2:e79a9cb05801 | 263 | } |
hillkim7 | 0:7f4bc855cb46 | 264 | |
hillkim7 | 2:e79a9cb05801 | 265 | handle_data.storage_max_offset_ = info_begin_offset; |
hillkim7 | 2:e79a9cb05801 | 266 | handle_data.storage_begin_offset_ = 0; |
hillkim7 | 2:e79a9cb05801 | 267 | handle_data.storage_end_offset_ = handle_data.storage_begin_offset_; |
hillkim7 | 2:e79a9cb05801 | 268 | handle_data.cur_pos_ = handle_data.storage_begin_offset_; |
hillkim7 | 0:7f4bc855cb46 | 269 | |
hillkim7 | 2:e79a9cb05801 | 270 | DPRINTF("storage created: begin=%d end=%d free=%d"DCRLF, |
hillkim7 | 2:e79a9cb05801 | 271 | handle_data.storage_begin_offset_, handle_data.storage_end_offset_, SOF_block_get_free_size(&handle_data)); |
hillkim7 | 0:7f4bc855cb46 | 272 | |
hillkim7 | 2:e79a9cb05801 | 273 | write_storage_info(&handle_data); |
hillkim7 | 0:7f4bc855cb46 | 274 | |
hillkim7 | 2:e79a9cb05801 | 275 | return true; |
hillkim7 | 0:7f4bc855cb46 | 276 | } |
hillkim7 | 0:7f4bc855cb46 | 277 | |
hillkim7 | 0:7f4bc855cb46 | 278 | |
hillkim7 | 0:7f4bc855cb46 | 279 | bool SOF_block_format(uint8_t sector_index) |
hillkim7 | 0:7f4bc855cb46 | 280 | { |
hillkim7 | 2:e79a9cb05801 | 281 | if (!SOF_dev_is_valid_sector(sector_index)) { |
hillkim7 | 2:e79a9cb05801 | 282 | DPRINTF("invalid sector_index=%d"DCRLF, sector_index); |
hillkim7 | 2:e79a9cb05801 | 283 | return false; |
hillkim7 | 2:e79a9cb05801 | 284 | } |
hillkim7 | 0:7f4bc855cb46 | 285 | |
hillkim7 | 2:e79a9cb05801 | 286 | SOF_DevHandle_t hdev = SOF_dev_open(sector_index); |
hillkim7 | 0:7f4bc855cb46 | 287 | |
hillkim7 | 2:e79a9cb05801 | 288 | if (hdev == SOF_INVALID_HANDLE) { |
hillkim7 | 2:e79a9cb05801 | 289 | DPRINTF("SOF_dev_open(%d) failed"DCRLF, sector_index); |
hillkim7 | 2:e79a9cb05801 | 290 | return false; |
hillkim7 | 2:e79a9cb05801 | 291 | } |
hillkim7 | 0:7f4bc855cb46 | 292 | |
hillkim7 | 2:e79a9cb05801 | 293 | DPRINTF("Flash erase %d"DCRLF, sector_index); |
hillkim7 | 2:e79a9cb05801 | 294 | SOF_dev_erase(hdev); |
hillkim7 | 2:e79a9cb05801 | 295 | create_empty_storage(hdev, sector_index); |
hillkim7 | 2:e79a9cb05801 | 296 | SOF_dev_close(hdev); |
hillkim7 | 0:7f4bc855cb46 | 297 | |
hillkim7 | 2:e79a9cb05801 | 298 | return true; |
hillkim7 | 0:7f4bc855cb46 | 299 | } |
hillkim7 | 0:7f4bc855cb46 | 300 | |
hillkim7 | 0:7f4bc855cb46 | 301 | SOF_BlockHandle_t SOF_block_open_storage(uint8_t sector_index, SOF_Error_t *err) |
hillkim7 | 0:7f4bc855cb46 | 302 | { |
hillkim7 | 2:e79a9cb05801 | 303 | if (!SOF_dev_is_valid_sector(sector_index)) { |
hillkim7 | 2:e79a9cb05801 | 304 | DPRINTF("invalid sector_index=%d"DCRLF, sector_index); |
hillkim7 | 2:e79a9cb05801 | 305 | return false; |
hillkim7 | 2:e79a9cb05801 | 306 | } |
hillkim7 | 0:7f4bc855cb46 | 307 | |
hillkim7 | 2:e79a9cb05801 | 308 | SOF_DevHandle_t hdev = SOF_dev_open(sector_index); |
hillkim7 | 0:7f4bc855cb46 | 309 | |
hillkim7 | 2:e79a9cb05801 | 310 | if (hdev == SOF_INVALID_HANDLE) { |
hillkim7 | 2:e79a9cb05801 | 311 | DPRINTF("SOF_dev_open(%d) failed"DCRLF, sector_index); |
hillkim7 | 2:e79a9cb05801 | 312 | return false; |
hillkim7 | 2:e79a9cb05801 | 313 | } |
hillkim7 | 0:7f4bc855cb46 | 314 | |
hillkim7 | 2:e79a9cb05801 | 315 | SOF_BlockHandle_t handle = new SOF_BlockHandle(); |
hillkim7 | 0:7f4bc855cb46 | 316 | |
hillkim7 | 2:e79a9cb05801 | 317 | handle->hdev_ = hdev; |
hillkim7 | 0:7f4bc855cb46 | 318 | |
hillkim7 | 2:e79a9cb05801 | 319 | StorageInfo_t storage_info; |
hillkim7 | 0:7f4bc855cb46 | 320 | |
hillkim7 | 2:e79a9cb05801 | 321 | if ((*err=probe_active_storage_info(handle, &storage_info)) != kSOF_ErrNone) { |
hillkim7 | 2:e79a9cb05801 | 322 | delete handle; |
hillkim7 | 2:e79a9cb05801 | 323 | return NULL; |
hillkim7 | 2:e79a9cb05801 | 324 | } |
hillkim7 | 0:7f4bc855cb46 | 325 | |
hillkim7 | 2:e79a9cb05801 | 326 | uint32_t info_begin_offset; |
hillkim7 | 0:7f4bc855cb46 | 327 | |
hillkim7 | 2:e79a9cb05801 | 328 | if (!get_empty_info_location(handle, &info_begin_offset)) { |
hillkim7 | 2:e79a9cb05801 | 329 | *err = kSOF_ErrBadBlock; |
hillkim7 | 2:e79a9cb05801 | 330 | delete handle; |
hillkim7 | 2:e79a9cb05801 | 331 | return NULL; |
hillkim7 | 2:e79a9cb05801 | 332 | } |
hillkim7 | 0:7f4bc855cb46 | 333 | |
hillkim7 | 2:e79a9cb05801 | 334 | // set max offset that storage grows. |
hillkim7 | 2:e79a9cb05801 | 335 | handle->storage_max_offset_ = info_begin_offset; |
hillkim7 | 0:7f4bc855cb46 | 336 | |
hillkim7 | 2:e79a9cb05801 | 337 | handle->storage_begin_offset_ = storage_info.begin_offset; |
hillkim7 | 2:e79a9cb05801 | 338 | handle->storage_end_offset_ = storage_info.begin_offset + storage_info.len; |
hillkim7 | 0:7f4bc855cb46 | 339 | |
hillkim7 | 2:e79a9cb05801 | 340 | handle->cur_pos_ = handle->storage_begin_offset_; |
hillkim7 | 0:7f4bc855cb46 | 341 | |
hillkim7 | 2:e79a9cb05801 | 342 | DPRINTF("open for read: begin=%d end=%d len=%d free=%d"DCRLF, |
hillkim7 | 2:e79a9cb05801 | 343 | handle->storage_begin_offset_, handle->storage_end_offset_, storage_info.len, |
hillkim7 | 2:e79a9cb05801 | 344 | SOF_block_get_free_size(handle)); |
hillkim7 | 2:e79a9cb05801 | 345 | if (compute_storage_checksum(handle) != storage_info.storage_csum) { |
hillkim7 | 2:e79a9cb05801 | 346 | EPRINTF("checksum error %#x != %#x"DCRLF, compute_storage_checksum(handle), storage_info.storage_csum); |
hillkim7 | 2:e79a9cb05801 | 347 | *err = kSOF_ErrDataCurrupted; |
hillkim7 | 2:e79a9cb05801 | 348 | delete handle; |
hillkim7 | 2:e79a9cb05801 | 349 | return NULL; |
hillkim7 | 2:e79a9cb05801 | 350 | } |
hillkim7 | 0:7f4bc855cb46 | 351 | |
hillkim7 | 2:e79a9cb05801 | 352 | DUMP_BLOCK(handle); |
hillkim7 | 2:e79a9cb05801 | 353 | *err = kSOF_ErrNone; |
hillkim7 | 0:7f4bc855cb46 | 354 | |
hillkim7 | 2:e79a9cb05801 | 355 | return handle; |
hillkim7 | 0:7f4bc855cb46 | 356 | } |
hillkim7 | 0:7f4bc855cb46 | 357 | |
hillkim7 | 0:7f4bc855cb46 | 358 | SOF_BlockHandle_t SOF_block_create_storage(uint8_t sector_index, SOF_Error_t *err) |
hillkim7 | 0:7f4bc855cb46 | 359 | { |
hillkim7 | 2:e79a9cb05801 | 360 | if (!SOF_dev_is_valid_sector(sector_index)) { |
hillkim7 | 2:e79a9cb05801 | 361 | DPRINTF("invalid sector_index=%d"DCRLF, sector_index); |
hillkim7 | 2:e79a9cb05801 | 362 | return false; |
hillkim7 | 2:e79a9cb05801 | 363 | } |
hillkim7 | 0:7f4bc855cb46 | 364 | |
hillkim7 | 2:e79a9cb05801 | 365 | SOF_DevHandle_t hdev = SOF_dev_open(sector_index); |
hillkim7 | 0:7f4bc855cb46 | 366 | |
hillkim7 | 2:e79a9cb05801 | 367 | if (hdev == SOF_INVALID_HANDLE) { |
hillkim7 | 2:e79a9cb05801 | 368 | DPRINTF("SOF_dev_open(%d) failed"DCRLF, sector_index); |
hillkim7 | 2:e79a9cb05801 | 369 | return false; |
hillkim7 | 2:e79a9cb05801 | 370 | } |
hillkim7 | 0:7f4bc855cb46 | 371 | |
hillkim7 | 2:e79a9cb05801 | 372 | SOF_BlockHandle_t handle = new SOF_BlockHandle(); |
hillkim7 | 0:7f4bc855cb46 | 373 | |
hillkim7 | 2:e79a9cb05801 | 374 | handle->hdev_ = hdev; |
hillkim7 | 0:7f4bc855cb46 | 375 | |
hillkim7 | 2:e79a9cb05801 | 376 | StorageInfo_t storage_info; |
hillkim7 | 0:7f4bc855cb46 | 377 | |
hillkim7 | 2:e79a9cb05801 | 378 | if ((*err=probe_active_storage_info(handle, &storage_info)) != kSOF_ErrNone) { |
hillkim7 | 2:e79a9cb05801 | 379 | delete handle; |
hillkim7 | 2:e79a9cb05801 | 380 | return NULL; |
hillkim7 | 2:e79a9cb05801 | 381 | } |
hillkim7 | 0:7f4bc855cb46 | 382 | |
hillkim7 | 2:e79a9cb05801 | 383 | uint32_t info_begin_offset; |
hillkim7 | 0:7f4bc855cb46 | 384 | |
hillkim7 | 2:e79a9cb05801 | 385 | if (!get_empty_info_location(handle, &info_begin_offset)) { |
hillkim7 | 2:e79a9cb05801 | 386 | *err = kSOF_ErrBadBlock; |
hillkim7 | 2:e79a9cb05801 | 387 | delete handle; |
hillkim7 | 2:e79a9cb05801 | 388 | return NULL; |
hillkim7 | 2:e79a9cb05801 | 389 | } |
hillkim7 | 0:7f4bc855cb46 | 390 | |
hillkim7 | 2:e79a9cb05801 | 391 | // set max offset that storage grows. |
hillkim7 | 2:e79a9cb05801 | 392 | handle->storage_max_offset_ = info_begin_offset; |
hillkim7 | 0:7f4bc855cb46 | 393 | |
hillkim7 | 2:e79a9cb05801 | 394 | // writing position is just after previous storage |
hillkim7 | 2:e79a9cb05801 | 395 | handle->storage_begin_offset_ = storage_info.begin_offset + storage_info.len; |
hillkim7 | 2:e79a9cb05801 | 396 | handle->storage_end_offset_ = handle->storage_begin_offset_; |
hillkim7 | 0:7f4bc855cb46 | 397 | |
hillkim7 | 2:e79a9cb05801 | 398 | handle->cur_pos_ = handle->storage_begin_offset_; |
hillkim7 | 2:e79a9cb05801 | 399 | handle->write_mode_ = true; |
hillkim7 | 2:e79a9cb05801 | 400 | DPRINTF("open for write: begin=%d end=%d free=%d"DCRLF, |
hillkim7 | 2:e79a9cb05801 | 401 | handle->storage_begin_offset_, handle->storage_end_offset_, SOF_block_get_free_size(handle)); |
hillkim7 | 0:7f4bc855cb46 | 402 | |
hillkim7 | 2:e79a9cb05801 | 403 | DUMP_BLOCK(handle); |
hillkim7 | 2:e79a9cb05801 | 404 | *err = kSOF_ErrNone; |
hillkim7 | 0:7f4bc855cb46 | 405 | |
hillkim7 | 2:e79a9cb05801 | 406 | return handle; |
hillkim7 | 0:7f4bc855cb46 | 407 | } |
hillkim7 | 0:7f4bc855cb46 | 408 | |
hillkim7 | 0:7f4bc855cb46 | 409 | bool SOF_block_close(SOF_BlockHandle_t handle) |
hillkim7 | 0:7f4bc855cb46 | 410 | { |
hillkim7 | 2:e79a9cb05801 | 411 | bool r = true; |
hillkim7 | 0:7f4bc855cb46 | 412 | |
hillkim7 | 2:e79a9cb05801 | 413 | DASSERT(handle != NULL); |
hillkim7 | 2:e79a9cb05801 | 414 | if (handle->write_mode_) |
hillkim7 | 2:e79a9cb05801 | 415 | r = (bool)write_storage_info(handle); |
hillkim7 | 2:e79a9cb05801 | 416 | SOF_dev_close(handle->hdev_); |
hillkim7 | 2:e79a9cb05801 | 417 | delete handle; |
hillkim7 | 0:7f4bc855cb46 | 418 | |
hillkim7 | 2:e79a9cb05801 | 419 | return r; |
hillkim7 | 0:7f4bc855cb46 | 420 | } |
hillkim7 | 0:7f4bc855cb46 | 421 | |
hillkim7 | 0:7f4bc855cb46 | 422 | uint8_t *SOF_block_base_addr(SOF_BlockHandle_t handle) |
hillkim7 | 0:7f4bc855cb46 | 423 | { |
hillkim7 | 2:e79a9cb05801 | 424 | DASSERT(handle != NULL); |
hillkim7 | 2:e79a9cb05801 | 425 | return SOF_dev_get_hw_addr(handle->hdev_) + handle->cur_pos_; |
hillkim7 | 0:7f4bc855cb46 | 426 | } |
hillkim7 | 0:7f4bc855cb46 | 427 | |
hillkim7 | 0:7f4bc855cb46 | 428 | bool SOF_block_putc(SOF_BlockHandle_t handle, uint8_t c) |
hillkim7 | 0:7f4bc855cb46 | 429 | { |
hillkim7 | 2:e79a9cb05801 | 430 | DASSERT(handle != NULL); |
hillkim7 | 2:e79a9cb05801 | 431 | DASSERT(handle->is_writable()); |
hillkim7 | 0:7f4bc855cb46 | 432 | |
hillkim7 | 2:e79a9cb05801 | 433 | if (SOF_block_get_free_size(handle) == 0) { |
hillkim7 | 2:e79a9cb05801 | 434 | DPRINTF("no free space"DCRLF); |
hillkim7 | 2:e79a9cb05801 | 435 | DUMP_BLOCK(handle); |
hillkim7 | 0:7f4bc855cb46 | 436 | |
hillkim7 | 2:e79a9cb05801 | 437 | return false; |
hillkim7 | 2:e79a9cb05801 | 438 | } |
hillkim7 | 0:7f4bc855cb46 | 439 | |
hillkim7 | 2:e79a9cb05801 | 440 | bool b = SOF_dev_write_byte(handle->hdev_, handle->cur_pos_, c) != -1; |
hillkim7 | 2:e79a9cb05801 | 441 | if (b) { |
hillkim7 | 2:e79a9cb05801 | 442 | handle->cur_pos_++; |
hillkim7 | 2:e79a9cb05801 | 443 | handle->storage_end_offset_++; |
hillkim7 | 2:e79a9cb05801 | 444 | } |
hillkim7 | 0:7f4bc855cb46 | 445 | |
hillkim7 | 2:e79a9cb05801 | 446 | return b; |
hillkim7 | 0:7f4bc855cb46 | 447 | } |
hillkim7 | 0:7f4bc855cb46 | 448 | |
hillkim7 | 0:7f4bc855cb46 | 449 | size_t SOF_block_write(SOF_BlockHandle_t handle, const uint8_t *p, size_t p_size) |
hillkim7 | 0:7f4bc855cb46 | 450 | { |
hillkim7 | 2:e79a9cb05801 | 451 | size_t i; |
hillkim7 | 0:7f4bc855cb46 | 452 | |
hillkim7 | 2:e79a9cb05801 | 453 | for (i = 0; i < p_size; ++i) |
hillkim7 | 2:e79a9cb05801 | 454 | if (SOF_block_putc(handle, *p++) != true) |
hillkim7 | 2:e79a9cb05801 | 455 | return i; |
hillkim7 | 0:7f4bc855cb46 | 456 | |
hillkim7 | 2:e79a9cb05801 | 457 | return i; |
hillkim7 | 0:7f4bc855cb46 | 458 | } |
hillkim7 | 0:7f4bc855cb46 | 459 | |
hillkim7 | 0:7f4bc855cb46 | 460 | bool SOF_block_getc(SOF_BlockHandle_t handle, uint8_t *c) |
hillkim7 | 0:7f4bc855cb46 | 461 | { |
hillkim7 | 2:e79a9cb05801 | 462 | DASSERT(handle != NULL); |
hillkim7 | 2:e79a9cb05801 | 463 | DASSERT(handle->is_writable()); |
hillkim7 | 2:e79a9cb05801 | 464 | |
hillkim7 | 2:e79a9cb05801 | 465 | if (handle->cur_pos_ >= handle->storage_end_offset_) { |
hillkim7 | 2:e79a9cb05801 | 466 | DPRINTF("end of data\n"DCRLF); |
hillkim7 | 2:e79a9cb05801 | 467 | DUMP_BLOCK(handle); |
hillkim7 | 0:7f4bc855cb46 | 468 | |
hillkim7 | 2:e79a9cb05801 | 469 | return false; |
hillkim7 | 2:e79a9cb05801 | 470 | } |
hillkim7 | 0:7f4bc855cb46 | 471 | |
hillkim7 | 2:e79a9cb05801 | 472 | *c = SOF_dev_read_byte(handle->hdev_, handle->cur_pos_++); |
hillkim7 | 0:7f4bc855cb46 | 473 | |
hillkim7 | 2:e79a9cb05801 | 474 | return true; |
hillkim7 | 0:7f4bc855cb46 | 475 | } |
hillkim7 | 0:7f4bc855cb46 | 476 | |
hillkim7 | 0:7f4bc855cb46 | 477 | size_t SOF_block_read(SOF_BlockHandle_t handle, uint8_t *p, size_t p_size) |
hillkim7 | 0:7f4bc855cb46 | 478 | { |
hillkim7 | 2:e79a9cb05801 | 479 | size_t i; |
hillkim7 | 0:7f4bc855cb46 | 480 | |
hillkim7 | 2:e79a9cb05801 | 481 | for (i = 0; i < p_size; ++i) |
hillkim7 | 2:e79a9cb05801 | 482 | if (!SOF_block_getc(handle, p++)) |
hillkim7 | 2:e79a9cb05801 | 483 | break; |
hillkim7 | 0:7f4bc855cb46 | 484 | |
hillkim7 | 2:e79a9cb05801 | 485 | return i; |
hillkim7 | 0:7f4bc855cb46 | 486 | } |
hillkim7 | 0:7f4bc855cb46 | 487 | |
hillkim7 | 0:7f4bc855cb46 | 488 | SOF_Error_t SOF_block_get_statics(uint8_t sector_index, SOF_Statics_t *stat) |
hillkim7 | 0:7f4bc855cb46 | 489 | { |
hillkim7 | 2:e79a9cb05801 | 490 | if (!SOF_dev_is_valid_sector(sector_index)) { |
hillkim7 | 2:e79a9cb05801 | 491 | DPRINTF("invalid sector_index=%d"DCRLF, sector_index); |
hillkim7 | 2:e79a9cb05801 | 492 | return kSOF_ErrParam; |
hillkim7 | 2:e79a9cb05801 | 493 | } |
hillkim7 | 0:7f4bc855cb46 | 494 | |
hillkim7 | 2:e79a9cb05801 | 495 | SOF_Error_t err; |
hillkim7 | 2:e79a9cb05801 | 496 | SOF_BlockHandle_t hblk = SOF_block_open_storage(sector_index, &err); |
hillkim7 | 0:7f4bc855cb46 | 497 | |
hillkim7 | 2:e79a9cb05801 | 498 | if (hblk == NULL) { |
hillkim7 | 2:e79a9cb05801 | 499 | DPRINTF("SOF_block_open_storage(%d) failed"DCRLF, sector_index); |
hillkim7 | 2:e79a9cb05801 | 500 | return err; |
hillkim7 | 2:e79a9cb05801 | 501 | } |
hillkim7 | 0:7f4bc855cb46 | 502 | |
hillkim7 | 2:e79a9cb05801 | 503 | stat->data_addr = SOF_block_base_addr(hblk); |
hillkim7 | 2:e79a9cb05801 | 504 | stat->data_size = SOF_block_storage_size(hblk); |
hillkim7 | 2:e79a9cb05801 | 505 | stat->free_size = SOF_block_get_free_size(hblk); |
hillkim7 | 0:7f4bc855cb46 | 506 | |
hillkim7 | 2:e79a9cb05801 | 507 | SOF_block_close(hblk); |
hillkim7 | 0:7f4bc855cb46 | 508 | |
hillkim7 | 2:e79a9cb05801 | 509 | return kSOF_ErrNone; |
hillkim7 | 0:7f4bc855cb46 | 510 | } |
hillkim7 | 0:7f4bc855cb46 | 511 | |
hillkim7 | 0:7f4bc855cb46 | 512 | const SOF_SectorSpec_t *SOF_block_get_info(uint8_t sector_index) |
hillkim7 | 0:7f4bc855cb46 | 513 | { |
hillkim7 | 2:e79a9cb05801 | 514 | if (!SOF_dev_is_valid_sector(sector_index)) { |
hillkim7 | 2:e79a9cb05801 | 515 | DPRINTF("invalid sector_index=%d"DCRLF, sector_index); |
hillkim7 | 2:e79a9cb05801 | 516 | return NULL; |
hillkim7 | 2:e79a9cb05801 | 517 | } |
hillkim7 | 0:7f4bc855cb46 | 518 | |
hillkim7 | 2:e79a9cb05801 | 519 | return SOF_dev_info_by_index(sector_index); |
hillkim7 | 0:7f4bc855cb46 | 520 | } |
hillkim7 | 0:7f4bc855cb46 | 521 | |
hillkim7 | 2:e79a9cb05801 | 522 |