blob: 936efde46f2154579f6af810eff5d503198b3550 [file] [log] [blame]
// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include "teensy_flash/teensy_flash.h"
#include <algorithm>
#include "pw_kvs/alignment.h"
#include "pw_log/log.h"
#ifdef __x86_64__
#error x86 is not supported!
#endif // __x86_64__
extern "C" {
// Requires running the following command after installing the arduino core:
//
// sed -i -e 's/^static void flash_/void flash_/'
// third_party/pigweed/third_party/arduino/cores/teensy/hardware/teensy/avr/cores/teensy4/eeprom.c
extern void flash_write(void* addr, const void* data, uint32_t len);
extern void flash_erase_sector(void* addr);
}
namespace sample {
// Erase num_sectors starting at a given address.
pw::Status TeensyFlashMemory::Erase(Address address, size_t num_sectors) {
// Erase each sector, one at a time.
for (size_t i = 0; i < num_sectors; i++) {
void* sector_address = (void*)(address + (i * sector_size_bytes()));
// Requires running the following command after installing the arduino core:
//
// sed -i -e 's/^static void flash_/void flash_/'
// third_party/pigweed/third_party/arduino/cores/teensy/hardware/teensy/avr/cores/teensy4/eeprom.c
flash_erase_sector(sector_address); // See sed comment above
}
return pw::OkStatus();
}
// Reads bytes from flash into buffer.
pw::StatusWithSize TeensyFlashMemory::Read(Address address,
std::span<std::byte> output) {
memcpy(output.data(), (void*)((size_t)address), output.size_bytes());
return pw::StatusWithSize(output.size_bytes());
}
// Writes bytes to flash.
pw::StatusWithSize TeensyFlashMemory::Write(Address address,
std::span<const std::byte> data) {
std::span<const std::byte> write_data = data;
// Writing using flash_write is done by upto page size chunks. Each call to
// flash_write needs to fit in a page.
while (write_data.size_bytes() > 0) {
size_t bytes_remaining_in_page =
(size_t)(pw::AlignUp(address, kWritePageSize) - address);
if (bytes_remaining_in_page == 0) {
bytes_remaining_in_page = kWritePageSize;
}
size_t chunk_size =
std::min(bytes_remaining_in_page, write_data.size_bytes());
// Requires running the following command after installing the arduino core:
//
// sed -i -e 's/^static void flash_/void flash_/'
// third_party/pigweed/third_party/arduino/cores/teensy/hardware/teensy/avr/cores/teensy4/eeprom.c
flash_write((void*)(address),
write_data.data(),
chunk_size); // See sed comment above
write_data = write_data.subspan(chunk_size);
address += chunk_size;
}
return pw::StatusWithSize(data.size_bytes());
}
} // namespace sample