diff --git a/firmware/rmcs_board/CMakePresets.json b/firmware/rmcs_board/CMakePresets.json index 4f87d17..49a4653 100644 --- a/firmware/rmcs_board/CMakePresets.json +++ b/firmware/rmcs_board/CMakePresets.json @@ -1,5 +1,5 @@ { - "version": 2, + "version": 4, "configurePresets": [ { "name": "base", diff --git a/firmware/rmcs_board/src/app.cpp b/firmware/rmcs_board/src/app.cpp index cdf9d11..642bbaa 100644 --- a/firmware/rmcs_board/src/app.cpp +++ b/firmware/rmcs_board/src/app.cpp @@ -11,7 +11,7 @@ #include "firmware/rmcs_board/src/spi/bmi088/gyro.hpp" #include "firmware/rmcs_board/src/uart/uart.hpp" #include "firmware/rmcs_board/src/usb/vendor.hpp" -#include "firmware/rmcs_board/src/utility/interrupt_lock_guard.hpp" +#include "firmware/rmcs_board/src/utility/interrupt_lock.hpp" int main() { librmcs::firmware::app.init().run(); } @@ -37,6 +37,7 @@ App::App() { usb::vendor.init(); } +// Non-static to ensure instantiation // NOLINTNEXTLINE(readability-convert-member-functions-to-static) [[noreturn]] void App::run() { while (true) { diff --git a/firmware/rmcs_board/src/spi/bmi088/accel.hpp b/firmware/rmcs_board/src/spi/bmi088/accel.hpp index 897c816..bf31088 100644 --- a/firmware/rmcs_board/src/spi/bmi088/accel.hpp +++ b/firmware/rmcs_board/src/spi/bmi088/accel.hpp @@ -2,26 +2,54 @@ #include #include -#include -#include #include #include #include -#include "core/include/librmcs/data/datas.hpp" #include "core/src/protocol/serializer.hpp" #include "core/src/utility/assert.hpp" -#include "core/src/utility/immovable.hpp" +#include "firmware/rmcs_board/src/spi/bmi088/base.hpp" #include "firmware/rmcs_board/src/spi/spi.hpp" #include "firmware/rmcs_board/src/usb/vendor.hpp" #include "firmware/rmcs_board/src/utility/lazy.hpp" namespace librmcs::firmware::spi::bmi088 { +struct AccelerometerTraits { + static constexpr std::size_t kDummyBytes = 2; + + enum class RegisterAddress : uint8_t { + kAccSoftReset = 0x7E, + kAccPwrCtrl = 0x7D, + kAccPwrConf = 0x7C, + kAccSelfTest = 0x6D, + kIntMapData = 0x58, + kInt2IoCtrl = 0x54, + kInt1IoCtrl = 0x53, + kAccRange = 0x41, + kAccConf = 0x40, + kTempLsb = 0x23, + kTempMsb = 0x22, + kAccIntStat1 = 0x1D, + kSensorTime2 = 0x1A, + kSensorTime1 = 0x19, + kSensorTime0 = 0x18, + kAccZMsb = 0x17, + kAccZLsb = 0x16, + kAccYMsb = 0x15, + kAccYLsb = 0x14, + kAccXMsb = 0x13, + kAccXLsb = 0x12, + kAccStatus = 0x03, + kAccErrReg = 0x02, + kAccChipId = 0x00, + }; +}; + class Accelerometer final - : private SpiModule - , private core::utility::Immovable { + : public AccelerometerTraits + , private Bmi088Base { public: using Lazy = utility::Lazy; @@ -40,150 +68,56 @@ class Accelerometer final explicit Accelerometer( Spi::Lazy* spi, ChipSelectPin chip_select, Range range = Range::k6G, DataRate data_rate = DataRate::k1600Hz) - : SpiModule(chip_select) - , spi_(spi->init()) { + : Bmi088Base(spi, chip_select) { core::utility::assert_debug(spi_.try_lock()); - auto read_blocked = [this](RegisterAddress address) { - spi_.transmit_receive_blocked(*this, prepare_tx_buffer_read(address, 1)); - return static_cast(spi_.rx_buffer[2]); - }; - auto write_blocked = [this](RegisterAddress address, uint8_t value) { - spi_.transmit_receive_blocked(*this, prepare_tx_buffer_write(address, value)); - }; - - constexpr int max_try_time = 3; - auto read_with_confirm = [&](RegisterAddress address, uint8_t value) { - for (int i = max_try_time; i-- > 0;) { - if (read_blocked(address) == value) - return true; - board_delay_ms(1); - } - return false; - }; - auto write_with_confirm = [&](RegisterAddress address, uint8_t value) { - for (int i = max_try_time; i-- > 0;) { - write_blocked(address, value); - board_delay_ms(1); - if (read_blocked(address) == value) - return true; - } - return false; - }; - // Dummy read to switch accelerometer to SPI mode. - read_blocked(RegisterAddress::kAccChipId); + read_register(RegisterAddress::kAccChipId); board_delay_ms(1); // Reset all registers to reset value. - write_blocked(RegisterAddress::kAccSoftreset, 0xB6); + write_register(RegisterAddress::kAccSoftReset, 0xB6); board_delay_ms(1); // "Who am I" check. - core::utility::assert_always(read_with_confirm(RegisterAddress::kAccChipId, 0x1E)); + core::utility::assert_always(read_and_confirm(RegisterAddress::kAccChipId, 0x1E)); // Enable INT1 as output pin, push-pull, active-low. - core::utility::assert_always(write_with_confirm(RegisterAddress::kInt1IoCtrl, 0b00001000)); + core::utility::assert_always(write_and_confirm(RegisterAddress::kInt1IoCtrl, 0b00001000)); // Map data ready interrupt to pin INT1. - core::utility::assert_always(write_with_confirm(RegisterAddress::kIntMapData, 0b00000100)); + core::utility::assert_always(write_and_confirm(RegisterAddress::kIntMapData, 0b00000100)); // Set ODR (output data rate) = data_rate and OSR (over-sampling-ratio) = 1. - core::utility::assert_always(write_with_confirm( - RegisterAddress::kAccConf, - 0x80 | (0x02 << 4) | (static_cast(data_rate) << 0))); + core::utility::assert_always(write_and_confirm( + RegisterAddress::kAccConf, 0x80 | (0x02 << 4) | static_cast(data_rate))); // Set accelerometer range. core::utility::assert_always( - write_with_confirm(RegisterAddress::kAccRange, static_cast(range))); + write_and_confirm(RegisterAddress::kAccRange, static_cast(range))); // Switch the accelerometer into active mode. - core::utility::assert_always(write_with_confirm(RegisterAddress::kAccPwrConf, 0x00)); + core::utility::assert_always(write_and_confirm(RegisterAddress::kAccPwrConf, 0x00)); // Turn on the accelerometer. - core::utility::assert_always(write_with_confirm(RegisterAddress::kAccPwrCtrl, 0x04)); + core::utility::assert_always(write_and_confirm(RegisterAddress::kAccPwrCtrl, 0x04)); board_delay_ms(1); // Datasheet: wait >=450us after entering normal mode spi_.unlock(); } - void data_ready_callback() { read(RegisterAddress::kAccXLsb, 6); } + void data_ready_callback() { read_async(RegisterAddress::kAccXLsb, 6); } private: - enum class RegisterAddress : uint8_t { - kAccSoftreset = 0x7E, - kAccPwrCtrl = 0x7D, - kAccPwrConf = 0x7C, - kAccSelfTest = 0x6D, - kIntMapData = 0x58, - kInt2IoCtrl = 0x54, - kInt1IoCtrl = 0x53, - kAccRange = 0x41, - kAccConf = 0x40, - kTempLsb = 0x23, - kTempMsb = 0x22, - kAccIntStat1 = 0x1D, - kSensortime2 = 0x1A, - kSensortime1 = 0x19, - kSensortime0 = 0x18, - kAccZMsb = 0x17, - kAccZLsb = 0x16, - kAccYMsb = 0x15, - kAccYLsb = 0x14, - kAccXMsb = 0x13, - kAccXLsb = 0x12, - kAccStatus = 0x03, - kAccErrReg = 0x02, - kAccChipId = 0x00, - }; - - struct __attribute__((packed)) Data { - int16_t x; - int16_t y; - int16_t z; - }; - - bool write(RegisterAddress address, uint8_t value) { - if (!spi_.try_lock()) - return false; - - spi_.transmit_receive(*this, prepare_tx_buffer_write(address, value)); - return true; - } - - bool read(RegisterAddress address, size_t read_size) { - if (!spi_.try_lock()) - return false; - - spi_.transmit_receive(*this, prepare_tx_buffer_read(address, read_size)); - return true; - } - - void transmit_receive_completed_callback(size_t size) override { - core::utility::assert_debug(size == sizeof(Data) + 2); - auto& data = *std::launder(reinterpret_cast(spi_.rx_buffer + 2)); + void transmit_receive_async_callback(std::byte* rx_buffer, std::size_t size) override { + auto& data = parse_rx_data(rx_buffer, size); handle_uplink(usb::vendor->serializer(), data); spi_.unlock(); } - std::size_t prepare_tx_buffer_write(RegisterAddress address, uint8_t value) { - spi_.tx_buffer[0] = static_cast(address); - spi_.tx_buffer[1] = static_cast(value); - return 2; - } - - std::size_t prepare_tx_buffer_read(RegisterAddress address, size_t read_size) { - spi_.tx_buffer[0] = std::byte{0x80} | static_cast(address); - std::memset(&spi_.tx_buffer[1], 0, read_size + 1); - return read_size + 2; - } - static void handle_uplink(core::protocol::Serializer& serializer, Data& data) { core::utility::assert_debug( - serializer.write_imu_accelerometer( - data::AccelerometerDataView{.x = data.x, .y = data.y, .z = data.z}) + serializer.write_imu_accelerometer({.x = data.x, .y = data.y, .z = data.z}) != core::protocol::Serializer::SerializeResult::kInvalidArgument); } - - Spi& spi_; }; inline Accelerometer::Lazy accelerometer( diff --git a/firmware/rmcs_board/src/spi/bmi088/base.hpp b/firmware/rmcs_board/src/spi/bmi088/base.hpp new file mode 100644 index 0000000..2043f9e --- /dev/null +++ b/firmware/rmcs_board/src/spi/bmi088/base.hpp @@ -0,0 +1,101 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + +#include "core/src/utility/assert.hpp" +#include "firmware/rmcs_board/src/spi/spi.hpp" + +namespace librmcs::firmware::spi::bmi088 { + +template +class Bmi088Base : private SpiModule { +protected: + static constexpr std::size_t kDummyBytes = TraitsT::kDummyBytes; + static_assert(kDummyBytes >= 1); + + using RegisterAddressType = TraitsT::RegisterAddress; + static_assert( + std::is_scoped_enum_v + && std::is_same_v, uint8_t>); + + static constexpr int kMaxRetries = 3; + + struct [[gnu::packed]] Data { + int16_t x; + int16_t y; + int16_t z; + }; + + explicit Bmi088Base(Spi::Lazy* spi, ChipSelectPin chip_select_pin) + : SpiModule(chip_select_pin) + , spi_(spi->init()) {} + + uint8_t read_register(RegisterAddressType addr) { + spi_.transmit_receive(*this, prepare_tx_buffer_read(static_cast(addr), 1)); + return static_cast(spi_.rx_buffer[kDummyBytes]); + } + + void write_register(RegisterAddressType addr, uint8_t val) { + spi_.transmit_receive(*this, prepare_tx_buffer_write(static_cast(addr), val)); + } + + bool read_and_confirm(RegisterAddressType addr, uint8_t expected) { + for (int i = kMaxRetries; i-- > 0;) { + if (read_register(addr) == expected) + return true; + board_delay_ms(1); + } + return false; + } + + bool write_and_confirm(RegisterAddressType addr, uint8_t val) { + for (int i = kMaxRetries; i-- > 0;) { + write_register(addr, val); + board_delay_ms(1); + if (read_register(addr) == val) + return true; + } + return false; + } + + bool read_async(RegisterAddressType addr, std::size_t size) { + if (!spi_.try_lock()) + return false; + + spi_.transmit_receive_async( + *this, prepare_tx_buffer_read(static_cast(addr), size)); + return true; + } + + Data& parse_rx_data(std::byte* rx_buffer, std::size_t size) { + core::utility::assert_debug(size == sizeof(Data) + kDummyBytes); + return *std::launder(reinterpret_cast(rx_buffer + kDummyBytes)); + } + + Spi& spi_; + +private: + std::size_t prepare_tx_buffer_read(uint8_t addr, std::size_t read_size) { + core::utility::assert_debug(read_size + kDummyBytes <= Spi::kMaxTransferSize); + + spi_.tx_buffer[0] = static_cast(0x80 | addr); + std::memset(&spi_.tx_buffer[1], 0, read_size + kDummyBytes - 1); + return read_size + kDummyBytes; + } + + std::size_t prepare_tx_buffer_write(uint8_t addr, uint8_t val) { + static_assert(2 <= Spi::kMaxTransferSize); + + spi_.tx_buffer[0] = static_cast(addr); + spi_.tx_buffer[1] = static_cast(val); + return 2; + } +}; + +} // namespace librmcs::firmware::spi::bmi088 diff --git a/firmware/rmcs_board/src/spi/bmi088/gyro.hpp b/firmware/rmcs_board/src/spi/bmi088/gyro.hpp index 1285026..de4516c 100644 --- a/firmware/rmcs_board/src/spi/bmi088/gyro.hpp +++ b/firmware/rmcs_board/src/spi/bmi088/gyro.hpp @@ -2,26 +2,46 @@ #include #include -#include -#include #include #include #include -#include "core/include/librmcs/data/datas.hpp" #include "core/src/protocol/serializer.hpp" #include "core/src/utility/assert.hpp" -#include "core/src/utility/immovable.hpp" +#include "firmware/rmcs_board/src/spi/bmi088/base.hpp" #include "firmware/rmcs_board/src/spi/spi.hpp" #include "firmware/rmcs_board/src/usb/vendor.hpp" #include "firmware/rmcs_board/src/utility/lazy.hpp" namespace librmcs::firmware::spi::bmi088 { +struct GyroscopeTraits { + static constexpr std::size_t kDummyBytes = 1; + + enum class RegisterAddress : uint8_t { + kGyroSelfTest = 0x3C, + kInt3Int4IoMap = 0x18, + kInt3Int4IoConf = 0x16, + kGyroIntCtrl = 0x15, + kGyroSoftReset = 0x14, + kGyroLpm1 = 0x11, + kGyroBandwidth = 0x10, + kGyroRange = 0x0F, + kGyroIntStat1 = 0x0A, + kRateZMsb = 0x07, + kRateZLsb = 0x06, + kRateYMsb = 0x05, + kRateYLsb = 0x04, + kRateXMsb = 0x03, + kRateXLsb = 0x02, + kGyroChipId = 0x00, + }; +}; + class Gyroscope final - : private SpiModule - , private core::utility::Immovable { + : public GyroscopeTraits + , private Bmi088Base { public: using Lazy = utility::Lazy; @@ -46,137 +66,52 @@ class Gyroscope final explicit Gyroscope( Spi::Lazy* spi, ChipSelectPin chip_select, DataRange range = DataRange::k2000, DataRateAndBandwidth rate = DataRateAndBandwidth::k2000And230) - : SpiModule(chip_select) - , spi_(spi->init()) { + : Bmi088Base(spi, chip_select) { core::utility::assert_debug(spi_.try_lock()); - auto read_blocked = [this](RegisterAddress address) { - spi_.transmit_receive_blocked(*this, prepare_tx_buffer_read(address, 1)); - return static_cast(spi_.rx_buffer[1]); - }; - auto write_blocked = [this](RegisterAddress address, uint8_t value) { - spi_.transmit_receive_blocked(*this, prepare_tx_buffer_write(address, value)); - }; - - constexpr int max_try_time = 3; - auto read_with_confirm = [&](RegisterAddress address, uint8_t value) { - for (int i = max_try_time; i-- > 0;) { - if (read_blocked(address) == value) - return true; - board_delay_ms(1); - } - return false; - }; - auto write_with_confirm = [&](RegisterAddress address, uint8_t value) { - for (int i = max_try_time; i-- > 0;) { - write_blocked(address, value); - board_delay_ms(1); - if (read_blocked(address) == value) - return true; - } - return false; - }; - // Reset all registers to reset value. - write_blocked(RegisterAddress::kGyroSoftreset, 0xB6); + write_register(RegisterAddress::kGyroSoftReset, 0xB6); board_delay_ms(30); // "Who am I" check. - core::utility::assert_always(read_with_confirm(RegisterAddress::kGyroChipId, 0x0F)); + core::utility::assert_always(read_and_confirm(RegisterAddress::kGyroChipId, 0x0F)); // Enable the new data interrupt. - core::utility::assert_always(write_with_confirm(RegisterAddress::kGyroIntCtrl, 0x80)); + core::utility::assert_always(write_and_confirm(RegisterAddress::kGyroIntCtrl, 0x80)); // Set both INT3 and INT4 as push-pull, active-low, even though only INT3 is used. - core::utility::assert_always(write_with_confirm(RegisterAddress::kInt3Int4IoConf, 0b0000)); + core::utility::assert_always(write_and_confirm(RegisterAddress::kInt3Int4IoConf, 0b0000)); // Map data ready interrupt to INT3 pin. - core::utility::assert_always(write_with_confirm(RegisterAddress::kInt3Int4IoMap, 0x01)); + core::utility::assert_always(write_and_confirm(RegisterAddress::kInt3Int4IoMap, 0x01)); // Set ODR (output data rate, Hz) and filter bandwidth (Hz). core::utility::assert_always( - write_with_confirm(RegisterAddress::kGyroBandwidth, 0x80 | static_cast(rate))); + write_and_confirm(RegisterAddress::kGyroBandwidth, 0x80 | static_cast(rate))); // Set data range. core::utility::assert_always( - write_with_confirm(RegisterAddress::kGyroRange, static_cast(range))); + write_and_confirm(RegisterAddress::kGyroRange, static_cast(range))); // Switch the main power mode into normal mode. - core::utility::assert_always(write_with_confirm(RegisterAddress::kGyroLpM1, 0x00)); + core::utility::assert_always(write_and_confirm(RegisterAddress::kGyroLpm1, 0x00)); spi_.unlock(); } - void data_ready_callback() { read(RegisterAddress::kRateXLsb, 6); } + void data_ready_callback() { read_async(RegisterAddress::kRateXLsb, 6); } private: - enum class RegisterAddress : uint8_t { - kGyroSelfTest = 0x3C, - kInt3Int4IoMap = 0x18, - kInt3Int4IoConf = 0x16, - kGyroIntCtrl = 0x15, - kGyroSoftreset = 0x14, - kGyroLpM1 = 0x11, - kGyroBandwidth = 0x10, - kGyroRange = 0x0F, - kGyroIntStat1 = 0x0A, - kRateZMsb = 0x07, - kRateZLsb = 0x06, - kRateYMsb = 0x05, - kRateYLsb = 0x04, - kRateXMsb = 0x03, - kRateXLsb = 0x02, - kGyroChipId = 0x00, - }; - - struct __attribute__((packed)) Data { - int16_t x; - int16_t y; - int16_t z; - }; - - bool write(RegisterAddress address, uint8_t value) { - if (!spi_.try_lock()) - return false; - - spi_.transmit_receive(*this, prepare_tx_buffer_write(address, value)); - return true; - } - - bool read(RegisterAddress address, size_t read_size) { - if (!spi_.try_lock()) - return false; - - spi_.transmit_receive(*this, prepare_tx_buffer_read(address, read_size)); - return true; - } - - void transmit_receive_completed_callback(size_t size) override { - core::utility::assert_debug(size == sizeof(Data) + 1); - auto& data = *std::launder(reinterpret_cast(spi_.rx_buffer + 1)); + void transmit_receive_async_callback(std::byte* rx_buffer, std::size_t size) override { + auto& data = parse_rx_data(rx_buffer, size); handle_uplink(usb::vendor->serializer(), data); spi_.unlock(); } - std::size_t prepare_tx_buffer_write(RegisterAddress address, uint8_t value) { - spi_.tx_buffer[0] = static_cast(address); - spi_.tx_buffer[1] = static_cast(value); - return 2; - } - - std::size_t prepare_tx_buffer_read(RegisterAddress address, size_t read_size) { - spi_.tx_buffer[0] = std::byte{0x80} | static_cast(address); - std::memset(&spi_.tx_buffer[1], 0, read_size); - return read_size + 1; - } - static void handle_uplink(core::protocol::Serializer& serializer, Data& data) { core::utility::assert_debug( - serializer.write_imu_gyroscope( - data::GyroscopeDataView{.x = data.x, .y = data.y, .z = data.z}) + serializer.write_imu_gyroscope({.x = data.x, .y = data.y, .z = data.z}) != core::protocol::Serializer::SerializeResult::kInvalidArgument); } - - Spi& spi_; }; inline Gyroscope::Lazy gyroscope( diff --git a/firmware/rmcs_board/src/spi/spi.cpp b/firmware/rmcs_board/src/spi/spi.cpp index 735d2a7..f3750be 100644 --- a/firmware/rmcs_board/src/spi/spi.cpp +++ b/firmware/rmcs_board/src/spi/spi.cpp @@ -18,7 +18,7 @@ void spi2_isr() { return; if (flags & spi_end_int) - spi2->transmit_receive_completed_callback(); + spi2->transmit_receive_async_callback(); spi_clear_interrupt_status(base, flags); } diff --git a/firmware/rmcs_board/src/spi/spi.hpp b/firmware/rmcs_board/src/spi/spi.hpp index d33633d..bd199bc 100644 --- a/firmware/rmcs_board/src/spi/spi.hpp +++ b/firmware/rmcs_board/src/spi/spi.hpp @@ -40,7 +40,7 @@ class SpiModule { virtual ~SpiModule() = default; protected: - virtual void transmit_receive_completed_callback(std::size_t size) = 0; + virtual void transmit_receive_async_callback(std::byte* rx_buffer, std::size_t size) = 0; ChipSelectPin chip_select_pin_; }; @@ -94,14 +94,26 @@ class Spi : private core::utility::Immovable { Spi(Spi&&) = delete; Spi& operator=(Spi&&) = delete; - bool locking() { return locking_.test(std::memory_order::relaxed); } + bool is_locked() const { return locking_.test(std::memory_order::relaxed); } bool try_lock() { return !locking_.test_and_set(std::memory_order::relaxed); } void transmit_receive(SpiModule& module, std::size_t size) { + intc_m_disable_irq(irq_num_); + + transmit_receive_async(module, size); + while (spi_is_active(spi_base_)) + ; + + finish_transfer(); + + intc_m_enable_irq(irq_num_); + } + + void transmit_receive_async(SpiModule& module, std::size_t size) { core::utility::assert_debug(size <= kMaxTransferSize); core::utility::assert_debug_lazy( - [&]() noexcept { return locking() && !spi_is_active(spi_base_); }); + [&]() noexcept { return is_locked() && !spi_is_active(spi_base_); }); begin_transfer(module, size); @@ -119,25 +131,13 @@ class Spi : private core::utility::Immovable { } } - void transmit_receive_blocked(SpiModule& module, std::size_t size) { - intc_m_disable_irq(irq_num_); - - transmit_receive(module, size); - while (spi_is_active(spi_base_)) - ; - - finish_transfer(); - - intc_m_enable_irq(irq_num_); - } - - void transmit_receive_completed_callback() { + void transmit_receive_async_callback() { if (auto* module = finish_transfer()) - module->transmit_receive_completed_callback(tx_rx_size_); + module->transmit_receive_async_callback(rx_buffer, tx_rx_size_); } void unlock() { - core::utility::assert_debug_lazy([&]() noexcept { return locking(); }); + core::utility::assert_debug_lazy([&]() noexcept { return is_locked(); }); locking_.clear(std::memory_order::relaxed); } diff --git a/firmware/rmcs_board/src/usb/helper.hpp b/firmware/rmcs_board/src/usb/helper.hpp index 569fdf1..3cdf9df 100644 --- a/firmware/rmcs_board/src/usb/helper.hpp +++ b/firmware/rmcs_board/src/usb/helper.hpp @@ -6,4 +6,4 @@ namespace librmcs::firmware::usb { core::protocol::Serializer& get_serializer(); -} +} // namespace librmcs::firmware::usb diff --git a/firmware/rmcs_board/src/usb/interrupt_safe_buffer.hpp b/firmware/rmcs_board/src/usb/interrupt_safe_buffer.hpp index 87777e8..e75f4e6 100644 --- a/firmware/rmcs_board/src/usb/interrupt_safe_buffer.hpp +++ b/firmware/rmcs_board/src/usb/interrupt_safe_buffer.hpp @@ -20,6 +20,8 @@ class InterruptSafeBuffer final static constexpr size_t kBatchCount = 8; static_assert(std::has_single_bit(kBatchCount), "Batch count must be a power of 2"); + static constexpr size_t kMask = kBatchCount - 1; + constexpr InterruptSafeBuffer() = default; std::span allocate(size_t size) noexcept override { @@ -48,8 +50,6 @@ class InterruptSafeBuffer final } } - static constexpr size_t kMask = kBatchCount - 1; - class Batch { public: bool empty() const { return written_size_.load(std::memory_order::relaxed) == 0; } diff --git a/firmware/rmcs_board/src/utility/assert.cpp b/firmware/rmcs_board/src/utility/assert.cpp index 1dc423e..4c9f97b 100644 --- a/firmware/rmcs_board/src/utility/assert.cpp +++ b/firmware/rmcs_board/src/utility/assert.cpp @@ -4,9 +4,9 @@ namespace librmcs::core::utility { -volatile const char* assert_file = nullptr; +const char* volatile assert_file = nullptr; volatile unsigned int assert_line = 0; -volatile const char* assert_function = nullptr; +const char* volatile assert_function = nullptr; [[noreturn]] void assert_func(const std::source_location& location) { assert_file = location.file_name(); diff --git a/firmware/rmcs_board/src/utility/interrupt_lock_guard.hpp b/firmware/rmcs_board/src/utility/interrupt_lock.hpp similarity index 100% rename from firmware/rmcs_board/src/utility/interrupt_lock_guard.hpp rename to firmware/rmcs_board/src/utility/interrupt_lock.hpp diff --git a/firmware/rmcs_board/src/utility/lazy.hpp b/firmware/rmcs_board/src/utility/lazy.hpp index 9907ccd..1d596f0 100644 --- a/firmware/rmcs_board/src/utility/lazy.hpp +++ b/firmware/rmcs_board/src/utility/lazy.hpp @@ -7,7 +7,7 @@ #include #include "core/src/utility/assert.hpp" -#include "firmware/rmcs_board/src/utility/interrupt_lock_guard.hpp" +#include "firmware/rmcs_board/src/utility/interrupt_lock.hpp" namespace librmcs::firmware::utility { @@ -18,12 +18,13 @@ class Lazy { : init_status_(InitStatus::kUninitialized) , construction_arguments_{std::move(args)...} {} - constexpr ~Lazy() {} // No need to deconstruct Lazy(const Lazy&) = delete; Lazy& operator=(const Lazy&) = delete; Lazy(Lazy&&) = delete; Lazy& operator=(Lazy&&) = delete; + constexpr ~Lazy() {} // No need to deconstruct + constexpr T& init() { const InterruptLockGuard guard;