Stores data on the flash memory of stm32f4xx

Dependents:   DISCO-F429ZI_LCDTS_demo_richard

Fork of storage_on_flash by henning l

Committer:
pierrebizouard
Date:
Fri Mar 16 15:50:04 2018 +0000
Revision:
1:801ddc4634a5
Parent:
0:4cb438b58dc2
added support for 429ZI up to bank 11

Who changed what in which revision?

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