Marco Mayer / Mbed OS Queue
Committer:
demayer
Date:
Sat Mar 28 15:28:19 2020 +0000
Revision:
0:6bf0743ece18
IMU Thread with an event-queue running parallel to handle tasks like a 5 times blinking LED. Button with interrupt detected.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
demayer 0:6bf0743ece18 1 /* mbed Microcontroller Library
demayer 0:6bf0743ece18 2 * Copyright (c) 2017 ARM Limited
demayer 0:6bf0743ece18 3 *
demayer 0:6bf0743ece18 4 * Licensed under the Apache License, Version 2.0 (the "License");
demayer 0:6bf0743ece18 5 * you may not use this file except in compliance with the License.
demayer 0:6bf0743ece18 6 * You may obtain a copy of the License at
demayer 0:6bf0743ece18 7 *
demayer 0:6bf0743ece18 8 * http://www.apache.org/licenses/LICENSE-2.0
demayer 0:6bf0743ece18 9 *
demayer 0:6bf0743ece18 10 * Unless required by applicable law or agreed to in writing, software
demayer 0:6bf0743ece18 11 * distributed under the License is distributed on an "AS IS" BASIS,
demayer 0:6bf0743ece18 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
demayer 0:6bf0743ece18 13 * See the License for the specific language governing permissions and
demayer 0:6bf0743ece18 14 * limitations under the License.
demayer 0:6bf0743ece18 15 */
demayer 0:6bf0743ece18 16
demayer 0:6bf0743ece18 17 #include "MBRBlockDevice.h"
demayer 0:6bf0743ece18 18 #include <algorithm>
demayer 0:6bf0743ece18 19
demayer 0:6bf0743ece18 20
demayer 0:6bf0743ece18 21 // On disk structures, all entries are little endian
demayer 0:6bf0743ece18 22 MBED_PACKED(struct) mbr_entry {
demayer 0:6bf0743ece18 23 uint8_t status;
demayer 0:6bf0743ece18 24 uint8_t chs_start[3];
demayer 0:6bf0743ece18 25 uint8_t type;
demayer 0:6bf0743ece18 26 uint8_t chs_stop[3];
demayer 0:6bf0743ece18 27 uint32_t lba_offset;
demayer 0:6bf0743ece18 28 uint32_t lba_size;
demayer 0:6bf0743ece18 29 };
demayer 0:6bf0743ece18 30
demayer 0:6bf0743ece18 31 MBED_PACKED(struct) mbr_table {
demayer 0:6bf0743ece18 32 struct mbr_entry entries[4];
demayer 0:6bf0743ece18 33 uint8_t signature[2];
demayer 0:6bf0743ece18 34 };
demayer 0:6bf0743ece18 35
demayer 0:6bf0743ece18 36 // Little-endian conversion, should compile to noop
demayer 0:6bf0743ece18 37 // if system is little-endian
demayer 0:6bf0743ece18 38 static inline uint32_t tole32(uint32_t a)
demayer 0:6bf0743ece18 39 {
demayer 0:6bf0743ece18 40 union {
demayer 0:6bf0743ece18 41 uint32_t u32;
demayer 0:6bf0743ece18 42 uint8_t u8[4];
demayer 0:6bf0743ece18 43 } w;
demayer 0:6bf0743ece18 44
demayer 0:6bf0743ece18 45 w.u8[0] = a >> 0;
demayer 0:6bf0743ece18 46 w.u8[1] = a >> 8;
demayer 0:6bf0743ece18 47 w.u8[2] = a >> 16;
demayer 0:6bf0743ece18 48 w.u8[3] = a >> 24;
demayer 0:6bf0743ece18 49
demayer 0:6bf0743ece18 50 return w.u32;
demayer 0:6bf0743ece18 51 }
demayer 0:6bf0743ece18 52
demayer 0:6bf0743ece18 53 static inline uint32_t fromle32(uint32_t a)
demayer 0:6bf0743ece18 54 {
demayer 0:6bf0743ece18 55 return tole32(a);
demayer 0:6bf0743ece18 56 }
demayer 0:6bf0743ece18 57
demayer 0:6bf0743ece18 58 static void tochs(uint32_t lba, uint8_t chs[3])
demayer 0:6bf0743ece18 59 {
demayer 0:6bf0743ece18 60 uint32_t sector = std::min<uint32_t>(lba, 0xfffffd)+1;
demayer 0:6bf0743ece18 61 chs[0] = (sector >> 6) & 0xff;
demayer 0:6bf0743ece18 62 chs[1] = ((sector >> 0) & 0x3f) | ((sector >> 16) & 0xc0);
demayer 0:6bf0743ece18 63 chs[2] = (sector >> 14) & 0xff;
demayer 0:6bf0743ece18 64 }
demayer 0:6bf0743ece18 65
demayer 0:6bf0743ece18 66
demayer 0:6bf0743ece18 67 // Partition after address are turned into absolute
demayer 0:6bf0743ece18 68 // addresses, assumes bd is initialized
demayer 0:6bf0743ece18 69 static int partition_absolute(
demayer 0:6bf0743ece18 70 BlockDevice *bd, int part, uint8_t type,
demayer 0:6bf0743ece18 71 bd_size_t offset, bd_size_t size)
demayer 0:6bf0743ece18 72 {
demayer 0:6bf0743ece18 73 // Allocate smallest buffer necessary to write MBR
demayer 0:6bf0743ece18 74 uint32_t buffer_size = std::max<uint32_t>(bd->get_program_size(), sizeof(struct mbr_table));
demayer 0:6bf0743ece18 75 uint8_t *buffer = new uint8_t[buffer_size];
demayer 0:6bf0743ece18 76
demayer 0:6bf0743ece18 77 // Check for existing MBR
demayer 0:6bf0743ece18 78 int err = bd->read(buffer, 512-buffer_size, buffer_size);
demayer 0:6bf0743ece18 79 if (err) {
demayer 0:6bf0743ece18 80 delete[] buffer;
demayer 0:6bf0743ece18 81 return err;
demayer 0:6bf0743ece18 82 }
demayer 0:6bf0743ece18 83
demayer 0:6bf0743ece18 84 struct mbr_table *table = reinterpret_cast<struct mbr_table*>(
demayer 0:6bf0743ece18 85 &buffer[buffer_size - sizeof(struct mbr_table)]);
demayer 0:6bf0743ece18 86 if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) {
demayer 0:6bf0743ece18 87 // Setup default values for MBR
demayer 0:6bf0743ece18 88 table->signature[0] = 0x55;
demayer 0:6bf0743ece18 89 table->signature[1] = 0xaa;
demayer 0:6bf0743ece18 90 memset(table->entries, 0, sizeof(table->entries));
demayer 0:6bf0743ece18 91 }
demayer 0:6bf0743ece18 92
demayer 0:6bf0743ece18 93 // Setup new partition
demayer 0:6bf0743ece18 94 MBED_ASSERT(part >= 1 && part <= 4);
demayer 0:6bf0743ece18 95 table->entries[part-1].status = 0x00; // inactive (not bootable)
demayer 0:6bf0743ece18 96 table->entries[part-1].type = type;
demayer 0:6bf0743ece18 97
demayer 0:6bf0743ece18 98 // lba dimensions
demayer 0:6bf0743ece18 99 uint32_t sector = std::max<uint32_t>(bd->get_erase_size(), 512);
demayer 0:6bf0743ece18 100 uint32_t lba_offset = offset / sector;
demayer 0:6bf0743ece18 101 uint32_t lba_size = size / sector;
demayer 0:6bf0743ece18 102 table->entries[part-1].lba_offset = tole32(lba_offset);
demayer 0:6bf0743ece18 103 table->entries[part-1].lba_size = tole32(lba_size);
demayer 0:6bf0743ece18 104
demayer 0:6bf0743ece18 105 // chs dimensions
demayer 0:6bf0743ece18 106 tochs(lba_offset, table->entries[part-1].chs_start);
demayer 0:6bf0743ece18 107 tochs(lba_offset+lba_size-1, table->entries[part-1].chs_stop);
demayer 0:6bf0743ece18 108
demayer 0:6bf0743ece18 109 // Write out MBR
demayer 0:6bf0743ece18 110 err = bd->erase(0, bd->get_erase_size());
demayer 0:6bf0743ece18 111 if (err) {
demayer 0:6bf0743ece18 112 delete[] buffer;
demayer 0:6bf0743ece18 113 return err;
demayer 0:6bf0743ece18 114 }
demayer 0:6bf0743ece18 115
demayer 0:6bf0743ece18 116 err = bd->program(buffer, 512-buffer_size, buffer_size);
demayer 0:6bf0743ece18 117 delete[] buffer;
demayer 0:6bf0743ece18 118 return err;
demayer 0:6bf0743ece18 119 }
demayer 0:6bf0743ece18 120
demayer 0:6bf0743ece18 121 int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type, bd_addr_t start)
demayer 0:6bf0743ece18 122 {
demayer 0:6bf0743ece18 123 int err = bd->init();
demayer 0:6bf0743ece18 124 if (err) {
demayer 0:6bf0743ece18 125 return err;
demayer 0:6bf0743ece18 126 }
demayer 0:6bf0743ece18 127
demayer 0:6bf0743ece18 128 // Calculate dimensions
demayer 0:6bf0743ece18 129 bd_size_t offset = ((int64_t)start < 0) ? -start : start;
demayer 0:6bf0743ece18 130 bd_size_t size = bd->size();
demayer 0:6bf0743ece18 131
demayer 0:6bf0743ece18 132 if (offset < 512) {
demayer 0:6bf0743ece18 133 offset += std::max<uint32_t>(bd->get_erase_size(), 512);
demayer 0:6bf0743ece18 134 }
demayer 0:6bf0743ece18 135
demayer 0:6bf0743ece18 136 size -= offset;
demayer 0:6bf0743ece18 137
demayer 0:6bf0743ece18 138 err = partition_absolute(bd, part, type, offset, size);
demayer 0:6bf0743ece18 139 if (err) {
demayer 0:6bf0743ece18 140 return err;
demayer 0:6bf0743ece18 141 }
demayer 0:6bf0743ece18 142
demayer 0:6bf0743ece18 143 err = bd->deinit();
demayer 0:6bf0743ece18 144 if (err) {
demayer 0:6bf0743ece18 145 return err;
demayer 0:6bf0743ece18 146 }
demayer 0:6bf0743ece18 147
demayer 0:6bf0743ece18 148 return 0;
demayer 0:6bf0743ece18 149 }
demayer 0:6bf0743ece18 150
demayer 0:6bf0743ece18 151 int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type,
demayer 0:6bf0743ece18 152 bd_addr_t start, bd_addr_t stop)
demayer 0:6bf0743ece18 153 {
demayer 0:6bf0743ece18 154 int err = bd->init();
demayer 0:6bf0743ece18 155 if (err) {
demayer 0:6bf0743ece18 156 return err;
demayer 0:6bf0743ece18 157 }
demayer 0:6bf0743ece18 158
demayer 0:6bf0743ece18 159 // Calculate dimensions
demayer 0:6bf0743ece18 160 bd_size_t offset = ((int64_t)start < 0) ? -start : start;
demayer 0:6bf0743ece18 161 bd_size_t size = ((int64_t)stop < 0) ? -stop : stop;
demayer 0:6bf0743ece18 162
demayer 0:6bf0743ece18 163 if (offset < 512) {
demayer 0:6bf0743ece18 164 offset += std::max<uint32_t>(bd->get_erase_size(), 512);
demayer 0:6bf0743ece18 165 }
demayer 0:6bf0743ece18 166
demayer 0:6bf0743ece18 167 size -= offset;
demayer 0:6bf0743ece18 168
demayer 0:6bf0743ece18 169 err = partition_absolute(bd, part, type, offset, size);
demayer 0:6bf0743ece18 170 if (err) {
demayer 0:6bf0743ece18 171 return err;
demayer 0:6bf0743ece18 172 }
demayer 0:6bf0743ece18 173
demayer 0:6bf0743ece18 174 err = bd->deinit();
demayer 0:6bf0743ece18 175 if (err) {
demayer 0:6bf0743ece18 176 return err;
demayer 0:6bf0743ece18 177 }
demayer 0:6bf0743ece18 178
demayer 0:6bf0743ece18 179 return 0;
demayer 0:6bf0743ece18 180 }
demayer 0:6bf0743ece18 181
demayer 0:6bf0743ece18 182 MBRBlockDevice::MBRBlockDevice(BlockDevice *bd, int part)
demayer 0:6bf0743ece18 183 : _bd(bd), _part(part)
demayer 0:6bf0743ece18 184 {
demayer 0:6bf0743ece18 185 MBED_ASSERT(_part >= 1 && _part <= 4);
demayer 0:6bf0743ece18 186 }
demayer 0:6bf0743ece18 187
demayer 0:6bf0743ece18 188 int MBRBlockDevice::init()
demayer 0:6bf0743ece18 189 {
demayer 0:6bf0743ece18 190 int err = _bd->init();
demayer 0:6bf0743ece18 191 if (err) {
demayer 0:6bf0743ece18 192 return err;
demayer 0:6bf0743ece18 193 }
demayer 0:6bf0743ece18 194
demayer 0:6bf0743ece18 195 // Allocate smallest buffer necessary to write MBR
demayer 0:6bf0743ece18 196 uint32_t buffer_size = std::max<uint32_t>(_bd->get_read_size(), sizeof(struct mbr_table));
demayer 0:6bf0743ece18 197 uint8_t *buffer = new uint8_t[buffer_size];
demayer 0:6bf0743ece18 198
demayer 0:6bf0743ece18 199 err = _bd->read(buffer, 512-buffer_size, buffer_size);
demayer 0:6bf0743ece18 200 if (err) {
demayer 0:6bf0743ece18 201 delete[] buffer;
demayer 0:6bf0743ece18 202 return err;
demayer 0:6bf0743ece18 203 }
demayer 0:6bf0743ece18 204
demayer 0:6bf0743ece18 205 // Check for valid table
demayer 0:6bf0743ece18 206 struct mbr_table *table = reinterpret_cast<struct mbr_table*>(
demayer 0:6bf0743ece18 207 &buffer[buffer_size - sizeof(struct mbr_table)]);
demayer 0:6bf0743ece18 208 if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) {
demayer 0:6bf0743ece18 209 delete[] buffer;
demayer 0:6bf0743ece18 210 return BD_ERROR_INVALID_MBR;
demayer 0:6bf0743ece18 211 }
demayer 0:6bf0743ece18 212
demayer 0:6bf0743ece18 213 // Check for valid entry
demayer 0:6bf0743ece18 214 if (table->entries[_part-1].type == 0x00) {
demayer 0:6bf0743ece18 215 delete[] buffer;
demayer 0:6bf0743ece18 216 return BD_ERROR_INVALID_PARTITION;
demayer 0:6bf0743ece18 217 }
demayer 0:6bf0743ece18 218
demayer 0:6bf0743ece18 219 // Get partition attributes
demayer 0:6bf0743ece18 220 bd_size_t sector = std::max<uint32_t>(_bd->get_erase_size(), 512);
demayer 0:6bf0743ece18 221 _type = table->entries[_part-1].type;
demayer 0:6bf0743ece18 222 _offset = fromle32(table->entries[_part-1].lba_offset) * sector;
demayer 0:6bf0743ece18 223 _size = fromle32(table->entries[_part-1].lba_size) * sector;
demayer 0:6bf0743ece18 224
demayer 0:6bf0743ece18 225 // Check that block addresses are valid
demayer 0:6bf0743ece18 226 MBED_ASSERT(_bd->is_valid_erase(_offset, _size));
demayer 0:6bf0743ece18 227
demayer 0:6bf0743ece18 228 delete[] buffer;
demayer 0:6bf0743ece18 229 return 0;
demayer 0:6bf0743ece18 230 }
demayer 0:6bf0743ece18 231
demayer 0:6bf0743ece18 232 int MBRBlockDevice::deinit()
demayer 0:6bf0743ece18 233 {
demayer 0:6bf0743ece18 234 return _bd->deinit();
demayer 0:6bf0743ece18 235 }
demayer 0:6bf0743ece18 236
demayer 0:6bf0743ece18 237 int MBRBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
demayer 0:6bf0743ece18 238 {
demayer 0:6bf0743ece18 239 MBED_ASSERT(is_valid_read(addr, size));
demayer 0:6bf0743ece18 240 return _bd->read(b, addr + _offset, size);
demayer 0:6bf0743ece18 241 }
demayer 0:6bf0743ece18 242
demayer 0:6bf0743ece18 243 int MBRBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
demayer 0:6bf0743ece18 244 {
demayer 0:6bf0743ece18 245 MBED_ASSERT(is_valid_program(addr, size));
demayer 0:6bf0743ece18 246 return _bd->program(b, addr + _offset, size);
demayer 0:6bf0743ece18 247 }
demayer 0:6bf0743ece18 248
demayer 0:6bf0743ece18 249 int MBRBlockDevice::erase(bd_addr_t addr, bd_size_t size)
demayer 0:6bf0743ece18 250 {
demayer 0:6bf0743ece18 251 MBED_ASSERT(is_valid_erase(addr, size));
demayer 0:6bf0743ece18 252 return _bd->erase(addr + _offset, size);
demayer 0:6bf0743ece18 253 }
demayer 0:6bf0743ece18 254
demayer 0:6bf0743ece18 255 bd_size_t MBRBlockDevice::get_read_size() const
demayer 0:6bf0743ece18 256 {
demayer 0:6bf0743ece18 257 return _bd->get_read_size();
demayer 0:6bf0743ece18 258 }
demayer 0:6bf0743ece18 259
demayer 0:6bf0743ece18 260 bd_size_t MBRBlockDevice::get_program_size() const
demayer 0:6bf0743ece18 261 {
demayer 0:6bf0743ece18 262 return _bd->get_program_size();
demayer 0:6bf0743ece18 263 }
demayer 0:6bf0743ece18 264
demayer 0:6bf0743ece18 265 bd_size_t MBRBlockDevice::get_erase_size() const
demayer 0:6bf0743ece18 266 {
demayer 0:6bf0743ece18 267 return _bd->get_erase_size();
demayer 0:6bf0743ece18 268 }
demayer 0:6bf0743ece18 269
demayer 0:6bf0743ece18 270 bd_size_t MBRBlockDevice::size() const
demayer 0:6bf0743ece18 271 {
demayer 0:6bf0743ece18 272 return _size;
demayer 0:6bf0743ece18 273 }
demayer 0:6bf0743ece18 274
demayer 0:6bf0743ece18 275 bd_size_t MBRBlockDevice::get_partition_start() const
demayer 0:6bf0743ece18 276 {
demayer 0:6bf0743ece18 277 return _offset;
demayer 0:6bf0743ece18 278 }
demayer 0:6bf0743ece18 279
demayer 0:6bf0743ece18 280 bd_size_t MBRBlockDevice::get_partition_stop() const
demayer 0:6bf0743ece18 281 {
demayer 0:6bf0743ece18 282 return _offset+_size;
demayer 0:6bf0743ece18 283 }
demayer 0:6bf0743ece18 284
demayer 0:6bf0743ece18 285 uint8_t MBRBlockDevice::get_partition_type() const
demayer 0:6bf0743ece18 286 {
demayer 0:6bf0743ece18 287 return _type;
demayer 0:6bf0743ece18 288 }
demayer 0:6bf0743ece18 289
demayer 0:6bf0743ece18 290 int MBRBlockDevice::get_partition_number() const
demayer 0:6bf0743ece18 291 {
demayer 0:6bf0743ece18 292 return _part;
demayer 0:6bf0743ece18 293 }