Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make C library overhead configurable #12

Merged
merged 7 commits into from
Oct 23, 2021
Merged
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
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,81 @@ This is a stripped-down example; the full API documentation is available in the

The integration test application available under `/tests/integration/bootloader/` may also be a good reference.

#### Configuring Kochergá

##### Random number generation

Kochergá needs a source of random numbers regardless of the transport used.
You need to provide a definition of `kocherga::getRandomByte() -> std::uint8_t` for the library to build successfully.
You can use this implementation based on `std::rand()`:

```c++
#include <cstdlib>

auto kocherga::getRandomByte() -> std::uint8_t
{
return static_cast<std::uint8_t>(std::rand() * std::numeric_limits<std::uint8_t>::max() / RAND_MAX);
}

int main()
{
std::srand(GET_ENTROPY());
// bootloader implementation below
return 0;
}
```

An alternative is to use a generator from C++ standard library:

```c++
#include <random>

auto kocherga::getRandomByte() -> std::uint8_t
{
static std::mt19937 rd{GET_ENTROPY()};
return static_cast<std::uint8_t>(rd() * std::numeric_limits<std::uint8_t>::max() / std::mt19937::max());
}
```

In both cases beware that you need to initialize the psudorandom sequence with `GET_ENTROPY()`.
This function should retrieve a sufficiently random or unique value (such as the number of seconds since epoch).
Look for more information in the respective documentation of both `std::srand` and `std::mt19937`.

##### Providing custom assert macros

Kochergá uses the `assert` macro from the stadard C library to check its invariants.
If this is undesireable in your project, you can redefine the following macros.
You can do this before including Kochergá or globally in your build system.

```c++
#define KOCHERGA_ASSERT(x) some_other_assert(x, ...);
#include <kocherga.hpp>
```

You can disable all internal assertions like this:

```c++
#define KOCHERGA_ASSERT(x) (void)(x);
#include <kocherga.hpp>
```

##### Compatibility with environments with missing operator delete

Kocherga does not require heap but some toolchains may refuse to link the code if operator delete is not available.
If your environment does not define `operator delete`, you can provide a custom definition in your code like this:

```c++
void operator delete(void*) noexcept { std::abort(); }
```

This is needed as Kochergá uses virtual destructors, code generation for which includes
an `operator delete` even if deleting an object through pointer to its base class is
not used in your entire application.

#### ROM interface

The ROM backend abstracts the specifics of reading and writing your ROM (usually this is the on-chip flash memory).
Be sure to avoid overwriting the bootloader while modifying the ROM.

```c++
class MyROMBackend final : public kocherga::IROMBackend
Expand Down
14 changes: 14 additions & 0 deletions kocherga/kocherga.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
#define KOCHERGA_VERSION_MAJOR 0 // NOLINT NOSONAR
#define KOCHERGA_VERSION_MINOR 2 // NOLINT NOSONAR

#ifndef KOCHERGA_ASSERT
# include <cassert>
# define KOCHERGA_ASSERT(x) assert(x) // NOLINT NOSONAR
// This assert is a global configuration point and, sadly,
// the macro is the most efficient way.
#endif

namespace kocherga
{
/// Semantic version number pair: major then minor.
Expand Down Expand Up @@ -226,6 +233,11 @@ class IROMBackend

// --------------------------------------------------------------------------------------------------------------------

/// This function is used in drivers to generate
auto getRandomByte() -> uint8_t;

// --------------------------------------------------------------------------------------------------------------------

/// This is used to verify integrity of the application and other data.
/// Note that the firmware CRC verification is a computationally expensive process that needs to be completed
/// in a limited time interval, which should be minimized. This class has been carefully manually optimized to
Expand Down Expand Up @@ -1022,6 +1034,8 @@ class Bootloader : public detail::IController
{}

/// Nodes shall be registered using this method after the instance is constructed.
/// Lifetime of the nodes is managed outside of the Bootloader class.
/// Bootloader does NOT manage lifetimes of nodes.
/// The return value is true on success, false if there are too many nodes already or this node is already
/// registered (no effect in this case).
[[nodiscard]] auto addNode(INode* const node) -> bool { return presentation_.addNode(node); }
Expand Down
Loading