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.

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?

UserRevisionLine numberNew 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