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:
Mon Jan 19 12:57:44 2015 +0000
Revision:
0:7f4bc855cb46
Child:
2:e79a9cb05801
Tiny storage(file) system on MCU internal flash 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.

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