Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 21 additions & 11 deletions app/commands.hh
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,19 @@ struct VerifyFile : public Commands<T> {
}

if (!page) {
std::println("Program page {:#x} failed.", addr);
std::println("Read page {:#x} failed.", addr);
return 0;
}

uint32_t chunck = std::min(remainder, std::size_t{flash::PageSize});
uint32_t chunk = std::min(remainder, std::size_t{flash::PageSize});
std::span<uint8_t> data(*page);
if (chunck < data.size()) {
data = data.subspan(0, chunck);
if (chunk < data.size()) {
data = data.subspan(0, chunk);
}
flash_hasher.process(data.begin(), data.end());

addr += chunck;
remainder -= chunck;
addr += chunk;
remainder -= chunk;
progress_bar.update(file_size - remainder);
}

Expand All @@ -188,9 +188,15 @@ struct LoadFile : public Commands<T> {
std::string& filename;
bool quad;
bool bootstrap;
bool skip_erase;
LoadFile(flash::Generic<T> f, std::string& filename, std::size_t addr = 0, bool bootstrap = false,
bool quad = false)
: Commands<T>(f), filename(filename), start_addr(addr), quad(quad), bootstrap(bootstrap) {}
bool skip_erase = false, bool quad = false)
: Commands<T>(f),
filename(filename),
start_addr(addr),
quad(quad),
bootstrap(bootstrap),
skip_erase(skip_erase) {}

int run() override {
if ((this->start_addr % flash::SectorSize) != 0) {
Expand Down Expand Up @@ -235,8 +241,9 @@ struct LoadFile : public Commands<T> {
std::span<uint8_t> data(buffer);
auto progress_bar = ProgressBar(buffer.size(), 50, "Loading").with_throughput();
size_t addr = start_addr;
this->flash.write_enable();
while (data.size() > 0) {
if ((addr % flash::SectorSize) == 0) {
if (!skip_erase && (addr % flash::SectorSize) == 0) {
auto erased = addr4b ? this->flash.template erase<4, flash::Opcode::SectorErase4b>(addr)
: this->flash.erase(addr);
if (!erased) {
Expand All @@ -245,13 +252,15 @@ struct LoadFile : public Commands<T> {
}
}

this->flash.wait_not_busy();
std::optional<bool> res;
if (addr4b) {
res = this->flash.template single_page_program<4>(addr, data.first<flash::PageSize>());
res = this->flash.template single_page_program_non_blocking<4>(
addr, data.first<flash::PageSize>());
} else if (quad) {
res = this->flash.quad_page_program(addr, data.first<flash::PageSize>());
} else {
res = this->flash.single_page_program(addr, data.first<flash::PageSize>());
res = this->flash.single_page_program_non_blocking(addr, data.first<flash::PageSize>());
}

if (!res) {
Expand All @@ -263,6 +272,7 @@ struct LoadFile : public Commands<T> {
data = data.subspan(std::min(data.size(), std::size_t{flash::PageSize}));
progress_bar.update(buffer.size() - data.size());
}
this->flash.write_enable(false);
Comment thread
engdoreis marked this conversation as resolved.

if (bootstrap) {
this->flash.reset();
Expand Down
17 changes: 11 additions & 6 deletions app/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -223,14 +223,19 @@ int main(int argc, char* argv[]) {
.default_value(std::size_t{0})
.scan<'x', std::size_t>();
bootstrap_cmd->add_argument("--quad").help("Use qSPI").default_value(false).implicit_value(true);
bootstrap_cmd->add_argument("--skip-erase")
.help("Don't issue erase commands")
.default_value(false)
.implicit_value(true);
program.add_subparser(*bootstrap_cmd);
commands["bootstrap"] = [&]() -> int {
auto pid = program.get<uint16_t>("--pid");
auto filename = bootstrap_cmd->get<std::string>("filename");
auto addr = bootstrap_cmd->get<std::size_t>("--addr");
auto quad = bootstrap_cmd->get<bool>("--quad");
auto spih = handle_flash_command(bootstrap_cmd, pid);
commands::LoadFile(flash::Generic(*spih), filename, addr, true, quad).run();
auto pid = program.get<uint16_t>("--pid");
auto filename = bootstrap_cmd->get<std::string>("filename");
auto addr = bootstrap_cmd->get<std::size_t>("--addr");
auto quad = bootstrap_cmd->get<bool>("--quad");
auto skip_erase = bootstrap_cmd->get<bool>("--skip-erase");
auto spih = handle_flash_command(bootstrap_cmd, pid);
commands::LoadFile(flash::Generic(*spih), filename, addr, true, skip_erase, quad).run();

spih->close();
return 0;
Expand Down
10 changes: 8 additions & 2 deletions lib/flash/flash.hh
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ class Generic {
}

template <size_t ADDR_SIZE = 3>
Option<bool> single_page_program(uint32_t address, std::span<uint8_t, 256> data) {
Option<bool> single_page_program_non_blocking(uint32_t address, std::span<uint8_t, 256> data) {
static_assert(ADDR_SIZE == 3 || ADDR_SIZE == 4, "Only 3 or 4 byte addresses supported");

Opcode op;
Expand All @@ -259,7 +259,6 @@ class Generic {
} else {
op = Opcode::PageProgram4b;
}
write_enable();

std::array<uint8_t, 256 + 1 + ADDR_SIZE> cmd = {op};
for (size_t i = 0; i < ADDR_SIZE; ++i) {
Expand All @@ -271,6 +270,13 @@ class Generic {

std::ranges::copy(data, slice.begin());
TRY_OPT(spih.transfer(cmd, std::span<uint8_t>()));
return true;
}

template <size_t ADDR_SIZE = 3>
Option<bool> single_page_program(uint32_t address, std::span<uint8_t, 256> data) {
write_enable();
single_page_program_non_blocking(address, data);
wait_not_busy();
return write_enable(false);
}
Expand Down
29 changes: 14 additions & 15 deletions lib/ftdi/spi_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -204,25 +204,24 @@ bool SpiHost::set_clock(size_t clock) {
std::cerr << std::format("failed to update the clock:{}\n", res);
return false;
}
return true;
}

} else {
const size_t baseClk = 60000000;
for (auto div : clocks) {
if ((baseClk >> div) <= clock) {
clk_div = div;
break;
}
const size_t baseClk = 60000000;
for (auto div : clocks) {
if ((baseClk >> div) <= clock) {
clk_div = div;
break;
}
}

FT4222_STATUS status;
status = FT4222_SPIMaster_Init(handle, SPI_IO_SINGLE, clk_div, CLK_IDLE_LOW, CLK_LEADING,
SLAVE_SELECT(0));
if (FT4222_OK != status) {
std::cerr << std::format("failed to update the clock:{}\n", status);
return false;
}
FT4222_STATUS status;
status = FT4222_SPIMaster_Init(handle, SPI_IO_SINGLE, clk_div, CLK_IDLE_LOW, CLK_LEADING,
SLAVE_SELECT(0));
if (FT4222_OK != status) {
std::cerr << std::format("failed to update the clock:{}\n", status);
return false;
}
return true;
}

static std::optional<SpiHost> new_ft4222(DeviceInfo& device) {
Expand Down
2 changes: 1 addition & 1 deletion lib/visuals/progressbar.hh
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ struct ProgressBar {
std::string tp_str = "";
if (tp) {
tp->total(progress);
tp_str = tp->render();
tp_str = tp->render(false);
}

std::print("\r\033[32m{} [", label);
Expand Down
38 changes: 31 additions & 7 deletions lib/visuals/throughput.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#pragma once
#include <chrono>
#include <cmath>
#include <print>

struct Throughput {
Expand All @@ -16,14 +17,14 @@ struct Throughput {
progress = 0;
}

Throughput& add(size_t transfered) {
progress += transfered;
Throughput& add(size_t transferred) {
progress += transferred;
elapsed = std::chrono::high_resolution_clock::now();
return *this;
}

Throughput& total(size_t transfered) {
progress = transfered;
Throughput& total(size_t transferred) {
progress = transferred;
elapsed = std::chrono::high_resolution_clock::now();
return *this;
}
Expand All @@ -37,15 +38,15 @@ struct Throughput {
if (short_fmt) {
return std::format("{}", human_size(throughput, "bps"));
}
return std::format("Transfered {} in {}s, {}", human_size(mb, "b"), seconds,
return std::format("{} in {}, {}", human_size(mb, "b"), human_time(seconds),
human_size(throughput, "b/s"));
}

void show() { std::println("{}", render()); }
void show(bool short_fmt = true) { std::println("{}", render(short_fmt)); }

private:
std::string human_size(float num, const char* suffix = "B") {
std::array<std::string, 6> units{"", "ki", "Mi", "Gi", "Ti", "Pi"};
constexpr std::array<std::string_view, 6> units{"", "ki", "Mi", "Gi", "Ti", "Pi"};
for (auto unit : units) {
if (abs(num) < 1024) {
return std::format("{:.1f} {}{}", num, unit, suffix);
Expand All @@ -54,4 +55,27 @@ struct Throughput {
}
return "";
}

std::string human_time(float seconds) {
if (seconds <= 0.0f) {
return "0";
}

constexpr std::array<std::string_view, 3> units{"s", "m", "h"};
std::string result;
auto num = static_cast<int>(std::round(seconds));

for (size_t i = 0; i < units.size(); ++i) {
int part = (i < static_cast<int>(units.size()) - 1) ? num % 60 : num;
if (part != 0) {
result = std::format("{}{}", part, units[i]) + result;
Comment thread
AlexJones0 marked this conversation as resolved.
}
num /= 60;
if (num == 0) {
break;
}
}

return result;
}
};
Loading