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

kocherga_serial: update header format #26

Merged
merged 3 commits into from
Apr 4, 2024
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
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ jobs:
SONAR_SCANNER_VERSION: 4.6.1.2450
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
if: env.SONAR_TOKEN != ''
steps:
- uses: actions/checkout@v2
with:
Expand Down
106 changes: 104 additions & 2 deletions kocherga/kocherga.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,110 @@ auto getRandomByte() -> std::uint8_t;

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

namespace detail
{

static constexpr uint8_t BitsPerByte = 8U;

/// Size-optimized implementation of CRC16-CCITT
class CRC16CCITT
{
public:
static constexpr std::size_t Size = 2;

void update(const std::uint8_t b) noexcept
{
value_ ^= static_cast<std::uint16_t>(b << BitsPerByte);
// Manually unrolled because the difference in performance is drastic. Can't use table because size limitations.
value_ =
static_cast<std::uint16_t>(static_cast<std::uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ =
static_cast<std::uint16_t>(static_cast<std::uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ =
static_cast<std::uint16_t>(static_cast<std::uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ =
static_cast<std::uint16_t>(static_cast<std::uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ =
static_cast<std::uint16_t>(static_cast<std::uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ =
static_cast<std::uint16_t>(static_cast<std::uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ =
static_cast<std::uint16_t>(static_cast<std::uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ =
static_cast<std::uint16_t>(static_cast<std::uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
}

[[nodiscard]] auto get() const noexcept { return value_; }

[[nodiscard]] auto getBytes() const noexcept -> std::array<std::uint8_t, Size>
{
const auto x = get();
return {
static_cast<std::uint8_t>(x >> (BitsPerByte * 1U)),
static_cast<std::uint8_t>(x >> (BitsPerByte * 0U)),
};
}

void update(const std::size_t size, const std::uint8_t* const ptr) noexcept
{
const auto* p = ptr;
for (std::size_t s = 0; s < size; s++)
{
update(*p);
p++;
}
}

[[nodiscard]] auto isResidueCorrect() const noexcept { return value_ == Residue; }

private:
static constexpr std::uint16_t Initial = 0xFFFFU;
static constexpr std::uint16_t Poly = 0x1021U;
static constexpr std::uint16_t Top = 0x8000U;
static constexpr std::uint16_t Residue = 0x0000U;

std::uint16_t value_ = Initial;
};

/// Size-optimized implementation of CRC32-C (Castagnoli).
class CRC32C
{
public:
static constexpr std::size_t Size = 4;

void update(const std::uint8_t b) noexcept
{
value_ ^= static_cast<std::uint32_t>(b);
for (auto i = 0U; i < BitsPerByte; i++)
{
value_ = ((value_ & 1U) != 0) ? ((value_ >> 1U) ^ ReflectedPoly) : (value_ >> 1U); // NOLINT
}
}

[[nodiscard]] auto get() const noexcept { return value_ ^ Xor; }

[[nodiscard]] auto getBytes() const noexcept -> std::array<std::uint8_t, Size>
{
const auto x = get();
return {
static_cast<std::uint8_t>(x >> (BitsPerByte * 0U)),
static_cast<std::uint8_t>(x >> (BitsPerByte * 1U)),
static_cast<std::uint8_t>(x >> (BitsPerByte * 2U)),
static_cast<std::uint8_t>(x >> (BitsPerByte * 3U)),
};
}

[[nodiscard]] auto isResidueCorrect() const noexcept { return value_ == Residue; }

private:
static constexpr std::uint32_t Xor = 0xFFFF'FFFFUL;
static constexpr std::uint32_t ReflectedPoly = 0x82F6'3B78UL;
static constexpr std::uint32_t Residue = 0xB798'B438UL;

std::uint32_t value_ = Xor;
};
} // namespace detail

/// 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 @@ -307,8 +411,6 @@ class CRC64
/// Internal use only.
namespace detail
{
static constexpr auto BitsPerByte = 8U;

static constexpr std::chrono::microseconds DefaultTransferIDTimeout{2'000'000}; ///< Default taken from Specification.

/// Detects the application in the ROM, verifies its integrity, and retrieves the information about it.
Expand Down
47 changes: 1 addition & 46 deletions kocherga/kocherga_can.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,59 +234,14 @@ class TxQueue final
namespace detail
{
using kocherga::detail::BitsPerByte; // NOSONAR
using kocherga::detail::CRC16CCITT; // NOSONAR

static constexpr std::uint8_t TailByteStartOfTransfer = 0b1000'0000;
static constexpr std::uint8_t TailByteEndOfTransfer = 0b0100'0000;
static constexpr std::uint8_t TailByteToggleBit = 0b0010'0000;

static constexpr std::uint8_t MaxTransferID = 31;

class CRC16CCITT
{
public:
static constexpr std::size_t Size = 2;

void update(const std::uint8_t b) noexcept
{
value_ ^= static_cast<std::uint16_t>(static_cast<std::uint16_t>(b) << 8U);
// Manually unrolled because the difference in performance is drastic. Can't use table because size limitations.
value_ = static_cast<uint16_t>(static_cast<uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ = static_cast<uint16_t>(static_cast<uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ = static_cast<uint16_t>(static_cast<uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ = static_cast<uint16_t>(static_cast<uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ = static_cast<uint16_t>(static_cast<uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ = static_cast<uint16_t>(static_cast<uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ = static_cast<uint16_t>(static_cast<uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
value_ = static_cast<uint16_t>(static_cast<uint16_t>(value_ << 1U) ^ (((value_ & Top) != 0U) ? Poly : 0U));
}

void update(const std::size_t size, const std::uint8_t* const ptr) noexcept
{
const auto* p = ptr;
for (std::size_t s = 0; s < size; s++)
{
update(*p);
p++;
}
}

[[nodiscard]] auto get() const noexcept { return value_; }

[[nodiscard]] auto getBytes() const noexcept -> std::array<std::uint8_t, Size>
{
const auto x = get();
return {static_cast<std::uint8_t>(x >> BitsPerByte), static_cast<std::uint8_t>(x)};
}

[[nodiscard]] auto isResidueCorrect() const noexcept { return value_ == 0; }

private:
static constexpr std::uint16_t Top = 0x8000U;
static constexpr std::uint16_t Poly = 0x1021U;

std::uint16_t value_ = std::numeric_limits<std::uint16_t>::max();
};

inline auto makePseudoUniqueID(const SystemInfo::UniqueID& uid) -> std::uint64_t
{
CRC64 crc;
Expand Down
Loading