From 2e9f64a045b05e93e5a5584a49dbc916e20af55c Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sat, 9 Apr 2022 21:21:21 +0200 Subject: [PATCH 01/35] Add mutex interface --- include/sta/mutex.hpp | 27 +++++++++++++++++++++++++++ src/mutex.cpp | 20 ++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 include/sta/mutex.hpp create mode 100644 src/mutex.cpp diff --git a/include/sta/mutex.hpp b/include/sta/mutex.hpp new file mode 100644 index 0000000..a9869de --- /dev/null +++ b/include/sta/mutex.hpp @@ -0,0 +1,27 @@ +#ifndef STA_MUTEX_HPP +#define STA_MUTEX_HPP + + +namespace sta +{ + /** + * @brief Interface for mutex objects. + */ + class Mutex + { + public: + /** + * @brief Block until mutex has been acquired + */ + virtual void acquire() = 0; + /** + * @brief Release mutex + */ + virtual void release() = 0; + + static Mutex * ALWAYS_FREE; /**< Fake mutex that can always be acquired */ + }; +} // namespace sta + + +#endif // STA_MUTEX_HPP diff --git a/src/mutex.cpp b/src/mutex.cpp new file mode 100644 index 0000000..b861ebd --- /dev/null +++ b/src/mutex.cpp @@ -0,0 +1,20 @@ +#include + + +namespace sta +{ + /** + * @brief Dummy mutex implementation with no access control. + */ + class DummyMutex : public Mutex + { + public: + void acquire() override {} + void release() override {} + }; + + static DummyMutex dummyMutex; + + + Mutex * Mutex::ALWAYS_FREE = &dummyMutex; +} // namespace sta From 4140a07307067a55e5a7763cf4cfc7f0ebb7f14b Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sat, 9 Apr 2022 21:21:54 +0200 Subject: [PATCH 02/35] Add SPI interface --- include/sta/spi_interface.hpp | 87 +++++++++++++++++++++++++++++++++++ src/spi_interface.cpp | 21 +++++++++ 2 files changed, 108 insertions(+) create mode 100644 include/sta/spi_interface.hpp create mode 100644 src/spi_interface.cpp diff --git a/include/sta/spi_interface.hpp b/include/sta/spi_interface.hpp new file mode 100644 index 0000000..386421f --- /dev/null +++ b/include/sta/spi_interface.hpp @@ -0,0 +1,87 @@ +#ifndef STA_SPI_INTERFACE_HPP +#define STA_SPI_INTERFACE_HPP + +#include + +#include +#include + + +namespace sta +{ + /** + * @brief Interface for SPI hardware. + */ + class SpiInterface + { + public: + /** + * @param mutex Mutex object for managing shared access. Pass nullptr for no access control + */ + SpiInterface(Mutex * mutex = nullptr); + + + /** + * @brief Send single byte of data. + * + * @param value 8-bit value + */ + virtual void transfer(uint8_t value) = 0; + /** + * @brief Send data from buffer. + * + * @param buffer Source buffer + * @param size Number of bytes in buffer + */ + virtual void transfer(const uint8_t * buffer, size_t size) = 0; + + /** + * @brief Send two bytes of data. + * + * @param value 16-bit value + */ + virtual void transfer16(uint16_t value) = 0; + + /** + * @brief Send byte value repeatedly. + * + * @param value 8-bit value to repeat + * @param count Number of repetitions + */ + virtual void fill(uint8_t value, size_t count) = 0; + /** + * @brief Send 32-bit value repeatedly. + * + * @param value 32-bit value to repeat + * @param count Number of repetitions + */ + virtual void fill32(uint32_t value, size_t count) = 0; + + /** + * @brief Read incoming data to buffer. + * + * @param buffer Destination buffer + * @param size Number of bytes to read + */ + virtual void receive(uint8_t * buffer, size_t size) = 0; + + /** + * @brief Acquire usage rights to use the interface. + * + * Must be called before any I/O operations are executed. + */ + virtual void acquire(); + /** + * @brief Release usage rights for interface. + * + * Must be called after last I/O operation. + */ + virtual void release(); + + private: + Mutex * mutex_; /**< Mutex object */ + }; +} // namespace sta + + +#endif // STA_SPI_INTERFACE_HPP diff --git a/src/spi_interface.cpp b/src/spi_interface.cpp new file mode 100644 index 0000000..26a141e --- /dev/null +++ b/src/spi_interface.cpp @@ -0,0 +1,21 @@ +#include + + +namespace sta +{ + SpiInterface::SpiInterface(Mutex * mutex /* = nullptr */) + : mutex_{mutex} + {} + + void SpiInterface::acquire() + { + if (mutex_ != nullptr) + mutex_->acquire(); + } + + void SpiInterface::release() + { + if (mutex_ != nullptr) + mutex_->release(); + } +} // namespace sta From 3abe36ec810438d0bc193feb5ed1a51415fb4a94 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sat, 9 Apr 2022 21:22:14 +0200 Subject: [PATCH 03/35] Add SPI device interface --- include/sta/spi_device.hpp | 94 ++++++++++++++++++++++++++++++++++++++ src/spi_device.cpp | 56 +++++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 include/sta/spi_device.hpp create mode 100644 src/spi_device.cpp diff --git a/include/sta/spi_device.hpp b/include/sta/spi_device.hpp new file mode 100644 index 0000000..8fbbc8b --- /dev/null +++ b/include/sta/spi_device.hpp @@ -0,0 +1,94 @@ +#ifndef STA_SPI_DEVICE_HPP +#define STA_SPI_DEVICE_HPP + +#include + +#include +#include + + +namespace sta +{ + /** + * @brief Interface for SPI devices. + */ + class SpiDevice + { + public: + /** + * @param intf SPI hardware interface + */ + SpiDevice(SpiInterface * intf); + + /** + * @brief Start transmission with device. + * + * Must be called before any I/O operations. + */ + void beginTransmission(); + /** + * @brief End transmission with device. + * + * Must be called after last I/O operation. + */ + void endTransmission(); + + /** + * @brief Send single byte of data. + * + * @param value 8-bit value + */ + void transfer(uint8_t value); + /** + * @brief Send data from buffer. + * + * @param buffer Source buffer + * @param size Number of bytes in buffer + */ + void transfer(const uint8_t * buffer, size_t size); + /** + * @brief Send two bytes of data. + * + * @param value 16-bit value + */ + void transfer16(uint16_t data); + + /** + * @brief Send byte value repeatedly. + * + * @param value 8-bit value to repeat + * @param count Number of repetitions + */ + void fill(uint8_t value, size_t count); + /** + * @brief Send 32-bit value repeatedly. + * + * @param value 32-bit value to repeat + * @param count Number of repetitions + */ + void fill32(uint32_t value, size_t count); + + /** + * @brief Read incoming data to buffer. + * + * @param buffer Destination buffer + * @param size Number of bytes to read + */ + void receive(uint8_t * buffer, size_t size); + + /** + * @brief Activate device via CS pin. + */ + virtual void select() = 0; + /** + * @brief Deactivate device via CS pin. + */ + virtual void deselect() = 0; + + private: + SpiInterface * intf_; /**< SPI hardware interface */ + }; +} // namespace sta + + +#endif // STA_SPI_DEVICE_HPP diff --git a/src/spi_device.cpp b/src/spi_device.cpp new file mode 100644 index 0000000..50a961a --- /dev/null +++ b/src/spi_device.cpp @@ -0,0 +1,56 @@ +#include + + +namespace sta +{ + SpiDevice::SpiDevice(SpiInterface * intf) + : intf_{intf} + {} + + void SpiDevice::beginTransmission() + { + // Acquire SPI access and activate device + intf_->acquire(); + select(); + } + + void SpiDevice::endTransmission() + { + // Deactivate device and release SPI access + deselect(); + intf_->release(); + } + + + // Forward I/O operations to SPI interface + + void SpiDevice::transfer(uint8_t data) + { + intf_->transfer(data); + } + + void SpiDevice::transfer(const uint8_t * data, size_t size) + { + intf_->transfer(data, size); + } + + void SpiDevice::transfer16(uint16_t data) + { + intf_->transfer16(data); + } + + void SpiDevice::fill(uint8_t value, size_t count) + { + intf_->fill(value, count); + } + + void SpiDevice::fill32(uint32_t value, size_t count) + { + intf_->fill32(value, count); + } + + void SpiDevice::receive(uint8_t * buffer, size_t size) + { + intf_->receive(buffer, size); + } +} // namespace sta From d7bd511c703664b388724c61e4eea764eaaeb045 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sat, 9 Apr 2022 21:23:02 +0200 Subject: [PATCH 04/35] Add mutex implementation using std::atomic_flag --- include/sta/atomic_mutex.hpp | 25 +++++++++++++++++++++++++ src/atomic_mutex.cpp | 19 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 include/sta/atomic_mutex.hpp create mode 100644 src/atomic_mutex.cpp diff --git a/include/sta/atomic_mutex.hpp b/include/sta/atomic_mutex.hpp new file mode 100644 index 0000000..39d2cf9 --- /dev/null +++ b/include/sta/atomic_mutex.hpp @@ -0,0 +1,25 @@ +#ifndef STA_ATOMIC_MUTEX_HPP +#define STA_ATOMIC_MUTEX_HPP + +#include + +#include + + +namespace sta +{ + class AtomicMutex : public Mutex + { + public: + AtomicMutex(); + + void acquire() override; + void release() override; + + private: + std::atomic_flag lock_; + }; +} // namespace sta + + +#endif // STA_ATOMIC_MUTEX_HPP diff --git a/src/atomic_mutex.cpp b/src/atomic_mutex.cpp new file mode 100644 index 0000000..87b9be3 --- /dev/null +++ b/src/atomic_mutex.cpp @@ -0,0 +1,19 @@ +#include + + +namespace sta +{ + AtomicMutex::AtomicMutex() + : lock_{ATOMIC_FLAG_INIT} + {} + + void AtomicMutex::acquire() + { + while (lock_.test_and_set()); + } + + void AtomicMutex::release() + { + lock_.clear(); + } +} // namespace sta From 348f6cae67e4eb5719438cef951acc44bb77fa92 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sat, 9 Apr 2022 21:23:24 +0200 Subject: [PATCH 05/35] Add UART interface --- include/sta/uart.hpp | 183 ++++++++++++++++++++++++++++++++++++++++++ src/uart.cpp | 187 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 370 insertions(+) create mode 100644 include/sta/uart.hpp create mode 100644 src/uart.cpp diff --git a/include/sta/uart.hpp b/include/sta/uart.hpp new file mode 100644 index 0000000..42068fc --- /dev/null +++ b/include/sta/uart.hpp @@ -0,0 +1,183 @@ +#ifndef STA_UART_HPP +#define STA_UART_HPP + +#include +#include + + +namespace sta +{ + /** + * @brief Integer representation. + */ + enum class IntegerBase + { + DEC, /**< Decimal */ + BIN, /**< Binary */ + HEX /**< Hexadecimal */ + }; + + /** + * @brief Interface for UART. + */ + class UART + { + public: + /** + * @brief Print single character. + * + * @param c Character to print + */ + void print(char c); + /** + * @brief Print boolean value. + * + * @param b Boolean value + */ + void print(bool b); + /** + * @brief Print integer in selected base. + * + * @param num 8-bit unsigned integer + * @param base Integer base + */ + void print(uint8_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print integer in selected base. + * + * @param num 16-bit unsigned integer + * @param base Integer base + */ + void print(uint16_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print integer in selected base. + * + * @param num 32-bit unsigned integer + * @param base Integer base + */ + void print(uint32_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print integer in selected base. + * + * @param num Integer + * @param base Integer base + */ + void print(size_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print c-string. + * + * @param str Null terminated string + */ + void print(const char * str); + /** + * @brief Print string. + * + * @param str String buffer + * @parma length String length + */ + void print(const char * str, size_t length); + + + /** + * @brief Print new-line. + */ + void println(); + /** + * @brief Print single character followed by a new-line. + * + * @param c Character to print + */ + void println(char c); + /** + * @brief Print boolean value followed by a new-line. + * + * @param b Boolean value + */ + void println(bool b); + /** + * @brief Print integer in selected base followed by a new-line. + * + * @param num 8-bit unsigned integer + * @param base Integer base + */ + void println(uint8_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print integer in selected base followed by a new-line. + * + * @param num 16-bit unsigned integer + * @param base Integer base + */ + void println(uint16_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print integer in selected base followed by a new-line. + * + * @param num 32-bit unsigned integer + * @param base Integer base + */ + void println(uint32_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print integer in selected base followed by a new-line. + * + * @param num Integer + * @param base Integer base + */ + void println(size_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print c-string followed by a new-line. + * + * @param str Null terminated string + */ + void println(const char * str); + /** + * @brief Print string followed by a new-line. + * + * @param str String buffer + * @parma length String length + */ + void println(const char * str, size_t length); + + + /** + * @brief Write buffer to UART. + * + * @param buffer Source buffer + * @param size Number of bytes in buffer + */ + virtual void write(const uint8_t * buffer, size_t size) = 0; + + private: + /** + * @brief Print unsigned integer in selected base. + * + * @param value Unsigned integer value + * @param base Integer base + * @param fmt printf format string for base 10 + * @param size Size of value in bytes + */ + void printBase(uintmax_t value, IntegerBase base, const char * fmt, size_t size); + /** + * @brief Print unsigned integer in base 10. + * + * @param value Unsigned integer value + * @param fmt printf format string + */ + void printDec(uintmax_t value, const char * fmt); + /** + * @brief Print unsigned integer in base 2. + * + * @param value Unsigned integer value + * @param digits Number of digits to print + */ + void printBin(uintmax_t value, size_t digits); + /** + * @brief Print unsigned integer in base 16. + * + * @param value Unsigned integer value + * @param digits Number of digits to print + */ + void printHex(uintmax_t value, size_t digits); + }; +} // namespace sta + + +#endif // STA_UART_HPP diff --git a/src/uart.cpp b/src/uart.cpp new file mode 100644 index 0000000..660c5ed --- /dev/null +++ b/src/uart.cpp @@ -0,0 +1,187 @@ +#include + +#include +#include + + +namespace sta +{ + void UART::print(char c) + { + print(&c, 1); + } + + void UART::print(bool b) + { + print(b ? "true" : "false"); + } + + void UART::print(uint8_t num, IntegerBase base /* = IntegerBase::DEC */) + { + printBase(num, base, "%u", sizeof(num)); + } + + void UART::print(uint16_t num, IntegerBase base /* = IntegerBase::DEC */) + { + printBase(num, base, "%u", sizeof(num)); + } + + void UART::print(uint32_t num, IntegerBase base /* = IntegerBase::DEC */) + { + printBase(num, base, "%lu", sizeof(num)); + } + + void UART::print(size_t num, IntegerBase base /* = IntegerBase::DEC */) + { + printBase(num, base, "%u", sizeof(num)); + } + + void UART::print(const char * str) + { + print(str, strlen(str)); + } + + void UART::print(const char * str, size_t length) + { + write(reinterpret_cast(str), length); + } + + + void UART::println() + { + print("\r\n", 2); + } + + void UART::println(char c) + { + print(&c, 1); + println(); + } + + void UART::println(bool b) + { + print(b); + println(); + } + + void UART::println(uint8_t num, IntegerBase base /* = IntegerBase::DEC */) + { + print(num, base); + println(); + } + + void UART::println(uint16_t num, IntegerBase base /* = IntegerBase::DEC */) + { + print(num, base); + println(); + } + + void UART::println(uint32_t num, IntegerBase base /* = IntegerBase::DEC */) + { + print(num, base); + println(); + } + + void UART::println(size_t num, IntegerBase base /* = IntegerBase::DEC */) + { + print(num, base); + println(); + } + + void UART::println(const char * str) + { + println(str, strlen(str)); + } + + void UART::println(const char * str, size_t length) + { + print(str, length); + println(); + } + + + + void UART::printBase(uintmax_t num, IntegerBase base, const char * fmt, size_t size) + { + switch (base) + { + case IntegerBase::DEC: + printDec(num, fmt); + break; + + case IntegerBase::BIN: + // Digits in base 2 = size in bytes * 8 + printBin(num, size * 8); + break; + + case IntegerBase::HEX: + // Digits in base 16 = size in bytes * 2 + printHex(num, size * 2); + break; + + default: + print(""); + } + } + + void UART::printDec(uintmax_t num, const char * fmt) + { + char buffer[64]; + sprintf(buffer, fmt, num); + print(buffer); + } + + void UART::printBin(uintmax_t value, size_t digits) + { + // Need 8 digits for every byte + char buffer[sizeof(value) * 8]; + + // Check bounds + if (digits > sizeof(buffer)) + { + print(""); + return; + } + // Nothing to do + if (digits == 0) + return; + + for (size_t i = 0; i < digits; ++i) + { + // Convert bit to '0' or '1' + // First digit in buffer is MSB in value, so shift from high to low + buffer[i] = '0' + ((value >> (digits - 1 - i)) & 0x1); + } + + print(buffer, digits); + } + + void UART::printHex(uintmax_t value, size_t digits) + { + // Need 2 digits for every byte + char buffer[sizeof(value) * 2]; + + // Check bounds + if (digits > sizeof(buffer)) + { + print(""); + return; + } + // Nothing to do + if (digits == 0) + return; + + for (size_t i = 0; i < digits; ++i) + { + // Convert 4 bits to hex + // First digit in buffer is 4 MSBs in value, so shift from high to low + uint8_t hex = ((value >> ((digits - 1 - i) * 4)) & 0xF); + if (hex > 9) + buffer[i] = 'A' + (hex - 9); + else + buffer[i] = '0' + hex; + } + + print(buffer, digits); + } +} // namespace sta From a068681b31ae7d3b13dfc9cd0b62c423e59717f5 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sat, 9 Apr 2022 21:47:23 +0200 Subject: [PATCH 06/35] Add GPIO pin interface --- include/sta/gpio_pin.hpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 include/sta/gpio_pin.hpp diff --git a/include/sta/gpio_pin.hpp b/include/sta/gpio_pin.hpp new file mode 100644 index 0000000..a0cac2e --- /dev/null +++ b/include/sta/gpio_pin.hpp @@ -0,0 +1,32 @@ +#ifndef STA_GPIO_PIN_HPP +#define STA_GPIO_PIN_HPP + + +namespace sta +{ + /** + * @brief GPIO pin state + */ + enum class GpioPinState + { + LOW, + HIGH + }; + + /** + * @brief Interface for GPIO pins. + */ + class GpioPin + { + public: + /** + * @brief Set pin output state. + * + * @param state Output state + */ + virtual void setState(GpioPinState state) = 0; + }; +} // namespace sta + + +#endif // STA_GPIO_PIN_HPP From bf037b03ecb0b162439bbff77f2badc421629a6a Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sat, 9 Apr 2022 21:47:55 +0200 Subject: [PATCH 07/35] Add HAL GPIO pin implementation --- include/sta/hal/gpio_pin.hpp | 45 ++++++++++++++++++++++++++++++++++++ src/hal/gpio_pin.cpp | 19 +++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 include/sta/hal/gpio_pin.hpp create mode 100644 src/hal/gpio_pin.cpp diff --git a/include/sta/hal/gpio_pin.hpp b/include/sta/hal/gpio_pin.hpp new file mode 100644 index 0000000..a580635 --- /dev/null +++ b/include/sta/hal/gpio_pin.hpp @@ -0,0 +1,45 @@ +/** + * @brief Wrapper for HAL GPIO pins. + * + * Defined STA_HAL_GPIO_ENABLE in to enable. + */ +#ifndef STA_HAL_GPIO_PIN_HPP +#define STA_HAL_GPIO_PIN_HPP + +#include +#ifdef STA_HAL_GPIO_ENABLE + +#include + +#include + + +namespace sta +{ + /** + * @brief Container for HAL GPIO Pin objects. + */ + class HalGpioPin : public GpioPin + { + public: + HalGpioPin(GPIO_TypeDef * port, uint16_t pin); + + void setState(GpioPinState state) override; + + private: + GPIO_TypeDef * port_; /**< GPIO port */ + uint16_t pin_; /**< GPIO pin */ + }; +} + +/** + * @brief Create HalGpioPin object from pin label. + * + * @param label Pin label + */ +#define STA_HAL_GPIO_PIN(label) sta::HalGpioPin{label##_GPIO_Port, label##_Pin} + + +#endif // STA_HAL_GPIO_ENABLE + +#endif // STA_HAL_GPIO_PIN_HPP diff --git a/src/hal/gpio_pin.cpp b/src/hal/gpio_pin.cpp new file mode 100644 index 0000000..6a23c87 --- /dev/null +++ b/src/hal/gpio_pin.cpp @@ -0,0 +1,19 @@ +#include + +#ifdef STA_HAL_GPIO_ENABLE + + +namespace sta +{ + HalGpioPin::HalGpioPin(GPIO_TypeDef * port, uint16_t pin) + : port_{port}, pin_{pin} + {} + + void HalGpioPin::setState(GpioPinState state) + { + HAL_GPIO_WritePin(port_, pin_, (state == GpioPinState::LOW) ? GPIO_PIN_RESET : GPIO_PIN_SET); + } +} // namespace sta + + +#endif // STA_HAL_GPIO_ENABLE From 03ca528d91948e10cc05617122cd786026c4681e Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sat, 9 Apr 2022 21:49:04 +0200 Subject: [PATCH 08/35] Add HAL SPI implementation --- include/sta/hal/spi.hpp | 70 +++++++++++++++++++++++++++++++++++++++++ src/hal/spi.cpp | 70 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 include/sta/hal/spi.hpp create mode 100644 src/hal/spi.cpp diff --git a/include/sta/hal/spi.hpp b/include/sta/hal/spi.hpp new file mode 100644 index 0000000..a8b2afe --- /dev/null +++ b/include/sta/hal/spi.hpp @@ -0,0 +1,70 @@ +/** + * @brief Implementations for SpiInterface and SpiDevice using HAL. + * + * Define STA_HAL_SPI_ENABLE in to enable. + * Requires STA_HAL_GPIO_ENABLE. + */ +#ifndef STA_HAL_SPI_HPP +#define STA_HAL_SPI_HPP + +#include +#ifdef STA_HAL_SPI_ENABLE + +#include +#include + +#include + + +namespace sta +{ + /** + * @brief Implementation of SpiInterface using HAL. + */ + class HalSpiInterface : public SpiInterface + { + public: + /** + * @param handle SPI handle + * @param mutex Mutex object for managing access. Pass nullptr for no access control + */ + HalSpiInterface(SPI_HandleTypeDef * handle, Mutex * mutex = nullptr); + + void transfer(uint8_t value) override; + void transfer(const uint8_t * buffer, size_t size) override; + void transfer16(uint16_t value) override; + + void fill(uint8_t value, size_t count) override; + void fill32(uint32_t value, size_t count) override; + + void receive(uint8_t * buffer, size_t size) override; + + private: + SPI_HandleTypeDef * handle_; /**< SPI handle */ + }; + + + /** + * @brief Implementation of SpiDevice using HAL. + */ + class HalSpiDevice : public SpiDevice + { + public: + /** + * @param intf SPI interface + * @param csPin Device CS pin + */ + HalSpiDevice(SpiInterface * intf, HalGpioPin csPin); + + void select() override; + void deselect() override; + + private: + HalGpioPin csPin_; /**< Device CS pin */ + }; +} // namespace sta + + +#endif // STA_HAL_SPI_ENABLE + +#endif // STA_HAL_SPI_HPP diff --git a/src/hal/spi.cpp b/src/hal/spi.cpp new file mode 100644 index 0000000..48f25f1 --- /dev/null +++ b/src/hal/spi.cpp @@ -0,0 +1,70 @@ +#include + +#ifdef STA_HAL_SPI_ENABLE + + +namespace sta +{ + HalSpiInterface::HalSpiInterface(SPI_HandleTypeDef * handle, Mutex * mutex /* = nullptr */) + : SpiInterface(mutex), handle_{handle} + {} + + + void HalSpiInterface::transfer(uint8_t data) + { + HAL_SPI_Transmit(handle_, &data, 1, HAL_MAX_DELAY); + } + + void HalSpiInterface::transfer(const uint8_t * data, size_t size) + { + HAL_SPI_Transmit(handle_, const_cast(data), size, HAL_MAX_DELAY); + } + + + void HalSpiInterface::transfer16(uint16_t value) + { + HAL_SPI_Transmit(handle_, reinterpret_cast(&value), 2, HAL_MAX_DELAY); + } + + + void HalSpiInterface::fill(uint8_t value, size_t count) + { + for (size_t i = 0; i < count; ++i) + { + transfer(value); + } + } + + void HalSpiInterface::fill32(uint32_t value, size_t count) + { + for (size_t i = 0; i < count; ++i) + { + HAL_SPI_Transmit(handle_, reinterpret_cast(&value), 4, HAL_MAX_DELAY); + } + } + + + void HalSpiInterface::receive(uint8_t * data, size_t size) + { + HAL_SPI_Receive(handle_, data, size, HAL_MAX_DELAY); + } + + + + HalSpiDevice::HalSpiDevice(SpiInterface * intf, HalGpioPin csPin) + : SpiDevice(intf), csPin_{csPin} + {} + + void HalSpiDevice::select() + { + STA_HAL_GPIO_PIN_WRITE(csPin_, GPIO_PIN_RESET); + } + + void HalSpiDevice::deselect() + { + STA_HAL_GPIO_PIN_WRITE(csPin_, GPIO_PIN_SET); + } +} // namespace sta + + +#endif // STA_HAL_SPI_ENABLE From 221b455e43ca30d1376af22b2712fdb15a9ebebf Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sat, 9 Apr 2022 21:49:20 +0200 Subject: [PATCH 09/35] Add HAL UART implementation --- include/sta/hal/uart.hpp | 53 ++++++++++++++++++++++++++++++++++++++++ src/hal/uart.cpp | 32 ++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 include/sta/hal/uart.hpp create mode 100644 src/hal/uart.cpp diff --git a/include/sta/hal/uart.hpp b/include/sta/hal/uart.hpp new file mode 100644 index 0000000..b9dd65e --- /dev/null +++ b/include/sta/hal/uart.hpp @@ -0,0 +1,53 @@ +/** + * @brief Implementation for UART using HAL. + * + * Define STA_HAL_UART_ENABLE in to enable. + * + * To enable the global DebugSerial instance (example using UART1) define: + * #define STA_HAL_UART_DEBUG huart1 + */ +#ifndef STA_HAL_UART_HPP +#define STA_HAL_UART_HPP + +#include +#ifdef STA_HAL_UART_ENABLE + +#include + +#include + + +namespace sta +{ + /** + * @brief Implementation of UART for HAL. + */ + class HalUART : public UART + { + public: + /** + * @param handle UART handle + */ + HalUART(UART_HandleTypeDef * handle); + + using UART::print; + + void write(const uint8_t * buffer, size_t size) override; + + private: + UART_HandleTypeDef * handle_; /**< UART handle */ + }; + + +#ifdef STA_HAL_UART_DEBUG + /** + * @brief Global UART instance for debug output. + */ + extern HalUART DebugSerial; +#endif // STA_HAL_UART_DEBUG +} // namespace sta + + +#endif // STA_HAL_UART_ENABLE + +#endif // STA_HAL_UART_HPP diff --git a/src/hal/uart.cpp b/src/hal/uart.cpp new file mode 100644 index 0000000..9413a28 --- /dev/null +++ b/src/hal/uart.cpp @@ -0,0 +1,32 @@ +#include + +#ifdef STA_HAL_UART_ENABLE + + +namespace sta +{ + HalUART::HalUART(UART_HandleTypeDef * handle) + : handle_{handle} + {} + + + void HalUART::write(const uint8_t * buffer, size_t size) + { + HAL_UART_Transmit(handle_, const_cast(buffer), size, HAL_MAX_DELAY); + } +} // namespace sta + + +#ifdef STA_HAL_UART_DEBUG + +#include + +namespace sta +{ + HalUART DebugSerial(&STA_HAL_UART_DEBUG); +} // namespace sta + +#endif // STA_HAL_UART_DEBUG + + +#endif // STA_HAL_UART_ENABLE From 876b3c186e60be154d7d0a823594b9e10df637ff Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sat, 9 Apr 2022 21:51:08 +0200 Subject: [PATCH 10/35] Fix usage of GpioPin in HAL SPI --- src/hal/spi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hal/spi.cpp b/src/hal/spi.cpp index 48f25f1..25c3eae 100644 --- a/src/hal/spi.cpp +++ b/src/hal/spi.cpp @@ -57,12 +57,12 @@ namespace sta void HalSpiDevice::select() { - STA_HAL_GPIO_PIN_WRITE(csPin_, GPIO_PIN_RESET); + csPin_.setState(GpioPinState::LOW); } void HalSpiDevice::deselect() { - STA_HAL_GPIO_PIN_WRITE(csPin_, GPIO_PIN_SET); + csPin_.setState(GpioPinState::HIGH); } } // namespace sta From b369f340924b1ef1fa4f11fa31055d9e22c080b0 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sun, 10 Apr 2022 15:24:03 +0200 Subject: [PATCH 11/35] Add signal interface --- include/sta/signal.hpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 include/sta/signal.hpp diff --git a/include/sta/signal.hpp b/include/sta/signal.hpp new file mode 100644 index 0000000..e32a204 --- /dev/null +++ b/include/sta/signal.hpp @@ -0,0 +1,37 @@ +#ifndef STA_SIGNAL_HPP +#define STA_SIGNAL_HPP + + +namespace sta +{ + /** + * @brief Signal interface + */ + class Signal + { + public: + /** + * @brief Enter signaled state. + */ + virtual void notify() = 0; + /** + * @brief Check signal state w/o changing it. + * + * @return True if in signaled state + */ + virtual bool peek() = 0; + /** + * @brief Check signal state. + * + * @return True if in signaled state + */ + virtual bool test() = 0; + /** + * @brief Wait until signaled state is entered. + */ + virtual void wait() = 0; + }; +} // namespace sta + + +#endif // STA_SIGNAL_HPP From 46cd2417e3fb0e4a646817543bc969e15f335c26 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sun, 10 Apr 2022 15:24:22 +0200 Subject: [PATCH 12/35] Add atomic signal implementation --- include/sta/atomic_signal.hpp | 27 +++++++++++++++++++++++++++ src/atomic_signal.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 include/sta/atomic_signal.hpp create mode 100644 src/atomic_signal.cpp diff --git a/include/sta/atomic_signal.hpp b/include/sta/atomic_signal.hpp new file mode 100644 index 0000000..88dde48 --- /dev/null +++ b/include/sta/atomic_signal.hpp @@ -0,0 +1,27 @@ +#ifndef STA_ATOMIC_SIGNAL_HPP +#define STA_ATOMIC_SIGNAL_HPP + +#include + +#include + + +namespace sta +{ + class AtomicSignal : public Signal + { + public: + AtomicSignal(); + + void notify() override; + bool peek() override; + bool test() override; + void wait() override; + + private: + std::atomic signal_; + }; +} // namespace sta + + +#endif // STA_ATOMIC_SIGNAL_HPP diff --git a/src/atomic_signal.cpp b/src/atomic_signal.cpp new file mode 100644 index 0000000..280aa30 --- /dev/null +++ b/src/atomic_signal.cpp @@ -0,0 +1,29 @@ +#include + + +namespace sta +{ + AtomicSignal::AtomicSignal() + : signal_{false} + {} + + void AtomicSignal::notify() + { + signal_.store(true); + } + + bool AtomicSignal::peek() + { + return signal_.load(); + } + + bool AtomicSignal::test() + { + return signal_.exchange(false); + } + + void AtomicSignal::wait() + { + while (!signal_.exchange(false)); + } +} // namespace sta From 4bf8a31acf73ff423c8b3115a44c0384bcdcb0b4 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sun, 10 Apr 2022 20:36:46 +0200 Subject: [PATCH 13/35] Move atomic implementations --- include/sta/{atomic_mutex.hpp => atomic/mutex.hpp} | 0 include/sta/{atomic_signal.hpp => atomic/signal.hpp} | 0 src/{atomic_mutex.cpp => atomic/mutex.cpp} | 2 +- src/{atomic_signal.cpp => atomic/signal.cpp} | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename include/sta/{atomic_mutex.hpp => atomic/mutex.hpp} (100%) rename include/sta/{atomic_signal.hpp => atomic/signal.hpp} (100%) rename src/{atomic_mutex.cpp => atomic/mutex.cpp} (87%) rename src/{atomic_signal.cpp => atomic/signal.cpp} (91%) diff --git a/include/sta/atomic_mutex.hpp b/include/sta/atomic/mutex.hpp similarity index 100% rename from include/sta/atomic_mutex.hpp rename to include/sta/atomic/mutex.hpp diff --git a/include/sta/atomic_signal.hpp b/include/sta/atomic/signal.hpp similarity index 100% rename from include/sta/atomic_signal.hpp rename to include/sta/atomic/signal.hpp diff --git a/src/atomic_mutex.cpp b/src/atomic/mutex.cpp similarity index 87% rename from src/atomic_mutex.cpp rename to src/atomic/mutex.cpp index 87b9be3..7aff61a 100644 --- a/src/atomic_mutex.cpp +++ b/src/atomic/mutex.cpp @@ -1,4 +1,4 @@ -#include +#include namespace sta diff --git a/src/atomic_signal.cpp b/src/atomic/signal.cpp similarity index 91% rename from src/atomic_signal.cpp rename to src/atomic/signal.cpp index 280aa30..98b37da 100644 --- a/src/atomic_signal.cpp +++ b/src/atomic/signal.cpp @@ -1,4 +1,4 @@ -#include +#include namespace sta From 82b7e2a3df222d10a8ee2cf8613777fc31c25a03 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sun, 10 Apr 2022 20:44:44 +0200 Subject: [PATCH 14/35] Add STA_ATOMIC_ENABLE guards --- include/sta/atomic/mutex.hpp | 5 +++++ include/sta/atomic/signal.hpp | 5 +++++ src/atomic/mutex.cpp | 4 ++++ src/atomic/signal.cpp | 4 ++++ 4 files changed, 18 insertions(+) diff --git a/include/sta/atomic/mutex.hpp b/include/sta/atomic/mutex.hpp index 39d2cf9..33deb82 100644 --- a/include/sta/atomic/mutex.hpp +++ b/include/sta/atomic/mutex.hpp @@ -1,6 +1,9 @@ #ifndef STA_ATOMIC_MUTEX_HPP #define STA_ATOMIC_MUTEX_HPP +#include +#ifdef STA_ATOMIC_ENABLE + #include #include @@ -22,4 +25,6 @@ namespace sta } // namespace sta +#endif // STA_ATOMIC_ENABLE + #endif // STA_ATOMIC_MUTEX_HPP diff --git a/include/sta/atomic/signal.hpp b/include/sta/atomic/signal.hpp index 88dde48..4baa76b 100644 --- a/include/sta/atomic/signal.hpp +++ b/include/sta/atomic/signal.hpp @@ -1,6 +1,9 @@ #ifndef STA_ATOMIC_SIGNAL_HPP #define STA_ATOMIC_SIGNAL_HPP +#include +#ifdef STA_ATOMIC_ENABLE + #include #include @@ -24,4 +27,6 @@ namespace sta } // namespace sta +#endif // STA_ATOMIC_ENABLE + #endif // STA_ATOMIC_SIGNAL_HPP diff --git a/src/atomic/mutex.cpp b/src/atomic/mutex.cpp index 7aff61a..60dc82b 100644 --- a/src/atomic/mutex.cpp +++ b/src/atomic/mutex.cpp @@ -1,4 +1,5 @@ #include +#ifdef STA_ATOMIC_ENABLE namespace sta @@ -17,3 +18,6 @@ namespace sta lock_.clear(); } } // namespace sta + + +#endif // STA_ATOMIC_ENABLE diff --git a/src/atomic/signal.cpp b/src/atomic/signal.cpp index 98b37da..e33d7f6 100644 --- a/src/atomic/signal.cpp +++ b/src/atomic/signal.cpp @@ -1,4 +1,5 @@ #include +#ifdef STA_ATOMIC_ENABLE namespace sta @@ -27,3 +28,6 @@ namespace sta while (!signal_.exchange(false)); } } // namespace sta + + +#endif // STA_ATOMIC_ENABLE From 24dae3917bdf1c9f88fcda95b0663aa80d3f349a Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sun, 10 Apr 2022 20:44:58 +0200 Subject: [PATCH 15/35] Add README --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..16d217a --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Interfaces + +The intention of these interfaces is to provide an abstraction layer for commonly used +resources. Libraries using these interfaces can be reused on different platforms +by simply implementing the required interfaces for the selected platform. + +Interfaces for the following resources are provided: +* GPIO pin +* Mutex +* Signal +* SPI +* UART + + +# HAL implementations + +Implementations using the HAL are provided for the following interfaces: +* GpioPin +* SpiInterface, SpiDevice +* UART + + +# Atomic implementations + +Implementations using atomic variables are provided for the following interfaces: +* Mutex +* Signal \ No newline at end of file From f195ceebb183a30f1fa67fd212b938695a8c2ff3 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sun, 10 Apr 2022 20:45:43 +0200 Subject: [PATCH 16/35] Add configuration advice --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 16d217a..48c0a23 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,13 @@ Implementations using the HAL are provided for the following interfaces: * SpiInterface, SpiDevice * UART +To enable these implementations follow the instructions from the individual headers. + # Atomic implementations Implementations using atomic variables are provided for the following interfaces: * Mutex -* Signal \ No newline at end of file +* Signal + +To enable these implementations define `STA_ATOMIC_ENABLE` in ``. \ No newline at end of file From dea989ffacea97316ee11dfcb562338ffad3606c Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Mon, 11 Apr 2022 12:45:04 +0200 Subject: [PATCH 17/35] Add transferReceive to SPI interface --- include/sta/hal/spi.hpp | 1 + include/sta/spi_device.hpp | 10 +++++++++- include/sta/spi_interface.hpp | 10 +++++++++- src/hal/spi.cpp | 9 +++++++-- src/spi_device.cpp | 5 +++++ 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/include/sta/hal/spi.hpp b/include/sta/hal/spi.hpp index a8b2afe..22d7f53 100644 --- a/include/sta/hal/spi.hpp +++ b/include/sta/hal/spi.hpp @@ -32,6 +32,7 @@ namespace sta void transfer(uint8_t value) override; void transfer(const uint8_t * buffer, size_t size) override; + void transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) override; void transfer16(uint16_t value) override; void fill(uint8_t value, size_t count) override; diff --git a/include/sta/spi_device.hpp b/include/sta/spi_device.hpp index 8fbbc8b..f1a4833 100644 --- a/include/sta/spi_device.hpp +++ b/include/sta/spi_device.hpp @@ -43,9 +43,17 @@ namespace sta * @brief Send data from buffer. * * @param buffer Source buffer - * @param size Number of bytes in buffer + * @param size Number of bytes to transfer */ void transfer(const uint8_t * buffer, size_t size); + /** + * @brief Send and receive data simultaneously. + * + * @param txBuffer Send buffer + * @param rxBuffer Receive buffer + * @param size Number of bytes to transfer + */ + void transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size); /** * @brief Send two bytes of data. * diff --git a/include/sta/spi_interface.hpp b/include/sta/spi_interface.hpp index 386421f..8cdc4d0 100644 --- a/include/sta/spi_interface.hpp +++ b/include/sta/spi_interface.hpp @@ -31,9 +31,17 @@ namespace sta * @brief Send data from buffer. * * @param buffer Source buffer - * @param size Number of bytes in buffer + * @param size Number of bytes to transfer */ virtual void transfer(const uint8_t * buffer, size_t size) = 0; + /** + * @brief Send and receive data simultaneously. + * + * @param txBuffer Send buffer + * @param rxBuffer Receive buffer + * @param size Number of bytes to transfer + */ + virtual void transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) = 0; /** * @brief Send two bytes of data. diff --git a/src/hal/spi.cpp b/src/hal/spi.cpp index 25c3eae..0fcf150 100644 --- a/src/hal/spi.cpp +++ b/src/hal/spi.cpp @@ -15,9 +15,14 @@ namespace sta HAL_SPI_Transmit(handle_, &data, 1, HAL_MAX_DELAY); } - void HalSpiInterface::transfer(const uint8_t * data, size_t size) + void HalSpiInterface::transfer(const uint8_t * buffer, size_t size) { - HAL_SPI_Transmit(handle_, const_cast(data), size, HAL_MAX_DELAY); + HAL_SPI_Transmit(handle_, const_cast(buffer), size, HAL_MAX_DELAY); + } + + void HalSpiInterface::transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) + { + HAL_SPI_TransmitReceive(handle_, const_cast(txBuffer), rxBuffer, size, HAL_MAX_DELAY); } diff --git a/src/spi_device.cpp b/src/spi_device.cpp index 50a961a..12d2571 100644 --- a/src/spi_device.cpp +++ b/src/spi_device.cpp @@ -34,6 +34,11 @@ namespace sta intf_->transfer(data, size); } + void SpiDevice::transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) + { + intf_->transfer(txBuffer, rxBuffer, size); + } + void SpiDevice::transfer16(uint16_t data) { intf_->transfer16(data); From 981dbc68c901229062b77eeae6e0a53fc93921f5 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Mon, 11 Apr 2022 17:10:22 +0200 Subject: [PATCH 18/35] Fix incorrect hex conversion --- src/uart.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uart.cpp b/src/uart.cpp index 660c5ed..2f18412 100644 --- a/src/uart.cpp +++ b/src/uart.cpp @@ -177,7 +177,7 @@ namespace sta // First digit in buffer is 4 MSBs in value, so shift from high to low uint8_t hex = ((value >> ((digits - 1 - i) * 4)) & 0xF); if (hex > 9) - buffer[i] = 'A' + (hex - 9); + buffer[i] = 'A' + (hex - 10); else buffer[i] = '0' + hex; } From 1ccc15cc408e8a24976a5bebff0bb04862cdd0c9 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Mon, 11 Apr 2022 17:13:16 +0200 Subject: [PATCH 19/35] Add type size assertions --- src/hal/spi.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hal/spi.cpp b/src/hal/spi.cpp index 0fcf150..9411bef 100644 --- a/src/hal/spi.cpp +++ b/src/hal/spi.cpp @@ -28,6 +28,8 @@ namespace sta void HalSpiInterface::transfer16(uint16_t value) { + static_assert(sizeof(uint16_t) == 2); + HAL_SPI_Transmit(handle_, reinterpret_cast(&value), 2, HAL_MAX_DELAY); } @@ -42,6 +44,8 @@ namespace sta void HalSpiInterface::fill32(uint32_t value, size_t count) { + static_assert(sizeof(uint32_t) == 4); + for (size_t i = 0; i < count; ++i) { HAL_SPI_Transmit(handle_, reinterpret_cast(&value), 4, HAL_MAX_DELAY); From 182fbc3ac371990a2b22fac44f865c725baff88d Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Mon, 11 Apr 2022 17:13:41 +0200 Subject: [PATCH 20/35] Add error if GPIO disabled --- include/sta/hal/spi.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/sta/hal/spi.hpp b/include/sta/hal/spi.hpp index 22d7f53..7d86d5d 100644 --- a/include/sta/hal/spi.hpp +++ b/include/sta/hal/spi.hpp @@ -10,6 +10,10 @@ #include #ifdef STA_HAL_SPI_ENABLE +#ifndef STA_HAL_GPIO_ENABLE +#error "HAL GPIO required" +#endif // !STA_HAL_GPIO_ENABLE + #include #include From b50cf07ce904bc7511ddf37a32ab260422e02ea6 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Tue, 12 Apr 2022 16:07:28 +0200 Subject: [PATCH 21/35] Fix formating --- include/sta/hal/gpio_pin.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sta/hal/gpio_pin.hpp b/include/sta/hal/gpio_pin.hpp index a580635..03ea594 100644 --- a/include/sta/hal/gpio_pin.hpp +++ b/include/sta/hal/gpio_pin.hpp @@ -1,7 +1,7 @@ /** * @brief Wrapper for HAL GPIO pins. * - * Defined STA_HAL_GPIO_ENABLE in to enable. + * Define **STA_HAL_GPIO_ENABLE** in `` to enable module. */ #ifndef STA_HAL_GPIO_PIN_HPP #define STA_HAL_GPIO_PIN_HPP From 9f2c73c9abacbf1b885f1cacca00aaf664b11aab Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Tue, 12 Apr 2022 16:08:00 +0200 Subject: [PATCH 22/35] Update description and debug serial usage --- include/sta/hal/uart.hpp | 16 ++++------------ src/hal/uart.cpp | 12 +++++++++--- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/include/sta/hal/uart.hpp b/include/sta/hal/uart.hpp index b9dd65e..e8e5434 100644 --- a/include/sta/hal/uart.hpp +++ b/include/sta/hal/uart.hpp @@ -1,10 +1,10 @@ /** - * @brief Implementation for UART using HAL. + * @brief Implementation of UART using HAL. * - * Define STA_HAL_UART_ENABLE in to enable. + * Define **STA_HAL_UART_ENABLE** in `` to enable module. * - * To enable the global DebugSerial instance (example using UART1) define: - * #define STA_HAL_UART_DEBUG huart1 + * To use a HAL UART instance (e.g. UART1) for `` define: + * #define STA_HAL_UART_DEBUG_SERIAL huart1 */ #ifndef STA_HAL_UART_HPP #define STA_HAL_UART_HPP @@ -37,14 +37,6 @@ namespace sta private: UART_HandleTypeDef * handle_; /**< UART handle */ }; - - -#ifdef STA_HAL_UART_DEBUG - /** - * @brief Global UART instance for debug output. - */ - extern HalUART DebugSerial; -#endif // STA_HAL_UART_DEBUG } // namespace sta diff --git a/src/hal/uart.cpp b/src/hal/uart.cpp index 9413a28..7d3fcc6 100644 --- a/src/hal/uart.cpp +++ b/src/hal/uart.cpp @@ -17,16 +17,22 @@ namespace sta } // namespace sta -#ifdef STA_HAL_UART_DEBUG +#ifdef STA_HAL_UART_DEBUG_SERIAL + +// Get extern declaration for DebugSerial because const namespace level variables have internal linkage by default +#include #include namespace sta { - HalUART DebugSerial(&STA_HAL_UART_DEBUG); + HalUART gHalDebugSerial(&STA_HAL_UART_DEBUG_SERIAL); + + // Used by + UART * const DebugSerial = &gHalDebugSerial; } // namespace sta -#endif // STA_HAL_UART_DEBUG +#endif // STA_HAL_UART_DEBUG_SERIAL #endif // STA_HAL_UART_ENABLE From f09f580f0042ead2dd62f616afbe201e96b9dbb0 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Tue, 12 Apr 2022 16:27:55 +0200 Subject: [PATCH 23/35] Add asserts. Fix formating --- include/sta/hal/spi.hpp | 5 +++-- src/hal/gpio_pin.cpp | 6 +++++- src/hal/spi.cpp | 21 ++++++++++++++++++--- src/hal/uart.cpp | 8 +++++++- src/spi_device.cpp | 22 +++++++++++++++++++--- 5 files changed, 52 insertions(+), 10 deletions(-) diff --git a/include/sta/hal/spi.hpp b/include/sta/hal/spi.hpp index 7d86d5d..f298541 100644 --- a/include/sta/hal/spi.hpp +++ b/include/sta/hal/spi.hpp @@ -1,8 +1,9 @@ /** * @brief Implementations for SpiInterface and SpiDevice using HAL. * - * Define STA_HAL_SPI_ENABLE in to enable. - * Requires STA_HAL_GPIO_ENABLE. + * Define **STA_HAL_SPI_ENABLE** in `` to enable module. + * + * Requires **STA_HAL_GPIO_ENABLE**. */ #ifndef STA_HAL_SPI_HPP #define STA_HAL_SPI_HPP diff --git a/src/hal/gpio_pin.cpp b/src/hal/gpio_pin.cpp index 6a23c87..d8fd93e 100644 --- a/src/hal/gpio_pin.cpp +++ b/src/hal/gpio_pin.cpp @@ -2,12 +2,16 @@ #ifdef STA_HAL_GPIO_ENABLE +#include + namespace sta { HalGpioPin::HalGpioPin(GPIO_TypeDef * port, uint16_t pin) : port_{port}, pin_{pin} - {} + { + STA_ASSERT(port != nullptr); + } void HalGpioPin::setState(GpioPinState state) { diff --git a/src/hal/spi.cpp b/src/hal/spi.cpp index 9411bef..69a428e 100644 --- a/src/hal/spi.cpp +++ b/src/hal/spi.cpp @@ -2,12 +2,16 @@ #ifdef STA_HAL_SPI_ENABLE +#include + namespace sta { HalSpiInterface::HalSpiInterface(SPI_HandleTypeDef * handle, Mutex * mutex /* = nullptr */) : SpiInterface(mutex), handle_{handle} - {} + { + STA_ASSERT(handle != nullptr); + } void HalSpiInterface::transfer(uint8_t data) @@ -17,11 +21,17 @@ namespace sta void HalSpiInterface::transfer(const uint8_t * buffer, size_t size) { + STA_ASSERT(buffer != nullptr); + HAL_SPI_Transmit(handle_, const_cast(buffer), size, HAL_MAX_DELAY); } void HalSpiInterface::transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) { + STA_ASSERT(txBuffer != nullptr); + STA_ASSERT(rxBuffer != nullptr); + STA_ASSERT(size != 0); + HAL_SPI_TransmitReceive(handle_, const_cast(txBuffer), rxBuffer, size, HAL_MAX_DELAY); } @@ -36,6 +46,8 @@ namespace sta void HalSpiInterface::fill(uint8_t value, size_t count) { + STA_ASSERT(count != 0); + for (size_t i = 0; i < count; ++i) { transfer(value); @@ -45,6 +57,7 @@ namespace sta void HalSpiInterface::fill32(uint32_t value, size_t count) { static_assert(sizeof(uint32_t) == 4); + STA_ASSERT(count != 0); for (size_t i = 0; i < count; ++i) { @@ -53,9 +66,11 @@ namespace sta } - void HalSpiInterface::receive(uint8_t * data, size_t size) + void HalSpiInterface::receive(uint8_t * buffer, size_t size) { - HAL_SPI_Receive(handle_, data, size, HAL_MAX_DELAY); + STA_ASSERT(buffer != nullptr); + + HAL_SPI_Receive(handle_, buffer, size, HAL_MAX_DELAY); } diff --git a/src/hal/uart.cpp b/src/hal/uart.cpp index 7d3fcc6..d0bd319 100644 --- a/src/hal/uart.cpp +++ b/src/hal/uart.cpp @@ -2,16 +2,22 @@ #ifdef STA_HAL_UART_ENABLE +#include + namespace sta { HalUART::HalUART(UART_HandleTypeDef * handle) : handle_{handle} - {} + { + STA_ASSERT(handle != nullptr); + } void HalUART::write(const uint8_t * buffer, size_t size) { + STA_ASSERT(buffer != nullptr); + HAL_UART_Transmit(handle_, const_cast(buffer), size, HAL_MAX_DELAY); } } // namespace sta diff --git a/src/spi_device.cpp b/src/spi_device.cpp index 12d2571..701d0e3 100644 --- a/src/spi_device.cpp +++ b/src/spi_device.cpp @@ -1,11 +1,15 @@ #include +#include + namespace sta { SpiDevice::SpiDevice(SpiInterface * intf) : intf_{intf} - {} + { + STA_ASSERT(intf != nullptr); + } void SpiDevice::beginTransmission() { @@ -29,13 +33,19 @@ namespace sta intf_->transfer(data); } - void SpiDevice::transfer(const uint8_t * data, size_t size) + void SpiDevice::transfer(const uint8_t * buffer, size_t size) { - intf_->transfer(data, size); + STA_ASSERT(buffer != nullptr); + + intf_->transfer(buffer, size); } void SpiDevice::transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) { + STA_ASSERT(txBuffer != nullptr); + STA_ASSERT(rxBuffer != nullptr); + STA_ASSERT(size != 0); + intf_->transfer(txBuffer, rxBuffer, size); } @@ -46,16 +56,22 @@ namespace sta void SpiDevice::fill(uint8_t value, size_t count) { + STA_ASSERT(count != 0); + intf_->fill(value, count); } void SpiDevice::fill32(uint32_t value, size_t count) { + STA_ASSERT(count != 0); + intf_->fill32(value, count); } void SpiDevice::receive(uint8_t * buffer, size_t size) { + STA_ASSERT(buffer != nullptr); + intf_->receive(buffer, size); } } // namespace sta From ccb15a640ec5c0fc1a2c7044bcb48f372595e789 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Tue, 12 Apr 2022 16:33:10 +0200 Subject: [PATCH 24/35] Add documentation --- include/sta/atomic/mutex.hpp | 10 +++++++++- include/sta/atomic/signal.hpp | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/sta/atomic/mutex.hpp b/include/sta/atomic/mutex.hpp index 33deb82..dcab789 100644 --- a/include/sta/atomic/mutex.hpp +++ b/include/sta/atomic/mutex.hpp @@ -1,3 +1,8 @@ +/** + * @brief Atomic mutex implementation. + * + * Define **STA_ATOMIC_ENABLE** to enable module. + */ #ifndef STA_ATOMIC_MUTEX_HPP #define STA_ATOMIC_MUTEX_HPP @@ -11,6 +16,9 @@ namespace sta { + /** + * @brief Implementation of `Mutex` interface using `std::atomic_flag`. + */ class AtomicMutex : public Mutex { public: @@ -20,7 +28,7 @@ namespace sta void release() override; private: - std::atomic_flag lock_; + std::atomic_flag lock_; /**< Atomic flag used as lock */ }; } // namespace sta diff --git a/include/sta/atomic/signal.hpp b/include/sta/atomic/signal.hpp index 4baa76b..4ca8cfc 100644 --- a/include/sta/atomic/signal.hpp +++ b/include/sta/atomic/signal.hpp @@ -1,3 +1,8 @@ +/** + * @brief Atomic signal implementation. + * + * Define **STA_ATOMIC_ENABLE** to enable module. + */ #ifndef STA_ATOMIC_SIGNAL_HPP #define STA_ATOMIC_SIGNAL_HPP @@ -11,6 +16,9 @@ namespace sta { + /** + * @brief Implementation of `Signal` interface using `std::atomic`. + */ class AtomicSignal : public Signal { public: @@ -22,7 +30,7 @@ namespace sta void wait() override; private: - std::atomic signal_; + std::atomic signal_; /**< Atomic bool used as signal */ }; } // namespace sta From b2ae487b76036fba3ae23ea0401fe8fb133460ba Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Tue, 12 Apr 2022 16:38:19 +0200 Subject: [PATCH 25/35] Rework doxygen comments --- include/sta/gpio_pin.hpp | 3 +++ include/sta/hal/spi.hpp | 6 +++--- include/sta/hal/uart.hpp | 2 +- include/sta/mutex.hpp | 3 +++ include/sta/signal.hpp | 5 ++++- include/sta/spi_device.hpp | 3 +++ include/sta/spi_interface.hpp | 3 +++ include/sta/uart.hpp | 3 +++ 8 files changed, 23 insertions(+), 5 deletions(-) diff --git a/include/sta/gpio_pin.hpp b/include/sta/gpio_pin.hpp index a0cac2e..d976d4b 100644 --- a/include/sta/gpio_pin.hpp +++ b/include/sta/gpio_pin.hpp @@ -1,3 +1,6 @@ +/** + * @brief GPIO pin interface definitions. + */ #ifndef STA_GPIO_PIN_HPP #define STA_GPIO_PIN_HPP diff --git a/include/sta/hal/spi.hpp b/include/sta/hal/spi.hpp index f298541..a342f12 100644 --- a/include/sta/hal/spi.hpp +++ b/include/sta/hal/spi.hpp @@ -1,5 +1,5 @@ /** - * @brief Implementations for SpiInterface and SpiDevice using HAL. + * @brief Implementations for `SpiInterface` and `SpiDevice` using HAL. * * Define **STA_HAL_SPI_ENABLE** in `` to enable module. * @@ -24,7 +24,7 @@ namespace sta { /** - * @brief Implementation of SpiInterface using HAL. + * @brief Implementation of `SpiInterface` interface using HAL. */ class HalSpiInterface : public SpiInterface { @@ -51,7 +51,7 @@ namespace sta /** - * @brief Implementation of SpiDevice using HAL. + * @brief Implementation of `SpiDevice` interface using HAL. */ class HalSpiDevice : public SpiDevice { diff --git a/include/sta/hal/uart.hpp b/include/sta/hal/uart.hpp index e8e5434..c12c5dc 100644 --- a/include/sta/hal/uart.hpp +++ b/include/sta/hal/uart.hpp @@ -20,7 +20,7 @@ namespace sta { /** - * @brief Implementation of UART for HAL. + * @brief Implementation of `UART` interface using HAL. */ class HalUART : public UART { diff --git a/include/sta/mutex.hpp b/include/sta/mutex.hpp index a9869de..bfc04a5 100644 --- a/include/sta/mutex.hpp +++ b/include/sta/mutex.hpp @@ -1,3 +1,6 @@ +/** + * @brief Mutex interface definition. + */ #ifndef STA_MUTEX_HPP #define STA_MUTEX_HPP diff --git a/include/sta/signal.hpp b/include/sta/signal.hpp index e32a204..b38abf3 100644 --- a/include/sta/signal.hpp +++ b/include/sta/signal.hpp @@ -1,3 +1,6 @@ +/** + * @brief Signal interface definition. + */ #ifndef STA_SIGNAL_HPP #define STA_SIGNAL_HPP @@ -5,7 +8,7 @@ namespace sta { /** - * @brief Signal interface + * @brief Interface for signal objects. */ class Signal { diff --git a/include/sta/spi_device.hpp b/include/sta/spi_device.hpp index f1a4833..377beae 100644 --- a/include/sta/spi_device.hpp +++ b/include/sta/spi_device.hpp @@ -1,3 +1,6 @@ +/** + * @brief SPI interface definitions. + */ #ifndef STA_SPI_DEVICE_HPP #define STA_SPI_DEVICE_HPP diff --git a/include/sta/spi_interface.hpp b/include/sta/spi_interface.hpp index 8cdc4d0..5708b89 100644 --- a/include/sta/spi_interface.hpp +++ b/include/sta/spi_interface.hpp @@ -1,3 +1,6 @@ +/** + * @brief SPI interface definitions. + */ #ifndef STA_SPI_INTERFACE_HPP #define STA_SPI_INTERFACE_HPP diff --git a/include/sta/uart.hpp b/include/sta/uart.hpp index 42068fc..8680d09 100644 --- a/include/sta/uart.hpp +++ b/include/sta/uart.hpp @@ -1,3 +1,6 @@ +/** + * @brief UART interface definition. + */ #ifndef STA_UART_HPP #define STA_UART_HPP From ae460b69f603adc0586214084985ed3cf4b7b102 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Thu, 14 Apr 2022 15:19:44 +0200 Subject: [PATCH 26/35] Add floating-point print --- include/sta/uart.hpp | 12 ++++++++++++ src/uart.cpp | 13 +++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/sta/uart.hpp b/include/sta/uart.hpp index 8680d09..b849ea3 100644 --- a/include/sta/uart.hpp +++ b/include/sta/uart.hpp @@ -38,6 +38,12 @@ namespace sta * @param b Boolean value */ void print(bool b); + /** + * @brief Print floating point value. + * + * @param d Floating point value + */ + void print(double d); /** * @brief Print integer in selected base. * @@ -97,6 +103,12 @@ namespace sta * @param b Boolean value */ void println(bool b); + /** + * @brief Print floating point value followed by a new-line. + * + * @param d Floating point value + */ + void println(double d); /** * @brief Print integer in selected base followed by a new-line. * diff --git a/src/uart.cpp b/src/uart.cpp index 2f18412..8a744bc 100644 --- a/src/uart.cpp +++ b/src/uart.cpp @@ -16,6 +16,13 @@ namespace sta print(b ? "true" : "false"); } + void UART::print(double d) + { + char buffer[64]; + snprintf(buffer, sizeof(buffer), "%f", d); + print(buffer); + } + void UART::print(uint8_t num, IntegerBase base /* = IntegerBase::DEC */) { printBase(num, base, "%u", sizeof(num)); @@ -64,6 +71,12 @@ namespace sta println(); } + void UART::println(double d) + { + print(d); + println(); + } + void UART::println(uint8_t num, IntegerBase base /* = IntegerBase::DEC */) { print(num, base); From 3c8fce14f642d1448973d49e1dc83530d20b32c3 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Fri, 15 Apr 2022 14:55:49 +0200 Subject: [PATCH 27/35] Add SPI settings --- include/sta/spi_settings.hpp | 71 +++++++++++++++++++++++++++++++++++ src/spi_settings.cpp | 72 ++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 include/sta/spi_settings.hpp create mode 100644 src/spi_settings.cpp diff --git a/include/sta/spi_settings.hpp b/include/sta/spi_settings.hpp new file mode 100644 index 0000000..ec89f56 --- /dev/null +++ b/include/sta/spi_settings.hpp @@ -0,0 +1,71 @@ +#ifndef STA_SPI_SETTINGS_HPP +#define STA_SPI_SETTINGS_HPP + +#include + + +namespace sta +{ + enum class SpiClkPolarity + { + LOW, + HIGH + }; + + enum class SpiClkPhase + { + EDGE_1, + EDGE_2 + }; + + enum class SpiMode + { + MODE_0, + MODE_1, + MODE_2, + MODE_3 + }; + + enum class SpiDataSize + { + BIT_8, + BIT_16 + }; + + enum class SpiBitOrder + { + MSB, + LSB + }; + + enum class SpiBaudRatePrescaler + { + BRP_2, + BRP_4, + BRP_8, + BRP_16, + BRP_32, + BRP_64, + BRP_128, + BRP_256 + }; + + + struct SpiSettings + { + SpiMode mode; + SpiDataSize dataSize; + SpiBitOrder bitOrder; + + uint32_t clkSpeed; + SpiBaudRatePrescaler baudRatePrescaler; /**< Subject to change */ + }; + + + SpiClkPolarity getSpiClkPolarity(SpiMode mode); + SpiClkPhase getSpiClkPhase(SpiMode mode); + SpiMode getSpiMode(SpiClkPolarity polarity, SpiClkPhase phase); +} // namespace sta + + +#endif // STA_SPI_SETTINGS_HPP diff --git a/src/spi_settings.cpp b/src/spi_settings.cpp new file mode 100644 index 0000000..73478e7 --- /dev/null +++ b/src/spi_settings.cpp @@ -0,0 +1,72 @@ +#include + +#include +#include + + +namespace sta +{ + SpiClkPolarity getSpiClkPolarity(SpiMode mode) + { + switch (mode) + { + case SpiMode::MODE_0: + case SpiMode::MODE_1: + return SpiClkPolarity::LOW; + + case SpiMode::MODE_2: + case SpiMode::MODE_3: + return SpiClkPolarity::HIGH; + + default: + // Unreachable case + STA_ASSERT_MSG(false, "Case for SpiMode enum not handled"); + STA_UNREACHABLE(); + } + } + + SpiClkPhase getSpiClkPhase(SpiMode mode) + { + switch (mode) + { + case SpiMode::MODE_0: + case SpiMode::MODE_2: + return SpiClkPhase::EDGE_1; + + case SpiMode::MODE_1: + case SpiMode::MODE_3: + return SpiClkPhase::EDGE_2; + + default: + // Unreachable case + STA_ASSERT_MSG(false, "Case for SpiMode enum not handled"); + STA_UNREACHABLE(); + } + } + + SpiMode getSpiMode(SpiClkPolarity polarity, SpiClkPhase phase) + { + if (polarity == SpiClkPolarity::LOW) + { + if (phase == SpiClkPhase::EDGE_1) + { + return SpiMode::MODE_0; + } + else + { + return SpiMode::MODE_1; + } + } + else + { + if (phase == SpiClkPhase::EDGE_1) + { + return SpiMode::MODE_2; + } + else + { + return SpiMode::MODE_3; + } + } + } +} // namespace sta From 4504ee9c3bda7eed068372f3338ded650297f427 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Fri, 15 Apr 2022 14:57:01 +0200 Subject: [PATCH 28/35] Use new SPI settings --- include/sta/hal/spi.hpp | 1 + include/sta/spi_device.hpp | 9 +++++ include/sta/spi_interface.hpp | 16 +++++++-- src/hal/spi.cpp | 65 +++++++++++++++++++++++++++++++++-- src/spi_device.cpp | 5 +++ src/spi_interface.cpp | 9 +++-- 6 files changed, 98 insertions(+), 7 deletions(-) diff --git a/include/sta/hal/spi.hpp b/include/sta/hal/spi.hpp index a342f12..dcc6280 100644 --- a/include/sta/hal/spi.hpp +++ b/include/sta/hal/spi.hpp @@ -45,6 +45,7 @@ namespace sta void receive(uint8_t * buffer, size_t size) override; + private: SPI_HandleTypeDef * handle_; /**< SPI handle */ }; diff --git a/include/sta/spi_device.hpp b/include/sta/spi_device.hpp index 377beae..336e123 100644 --- a/include/sta/spi_device.hpp +++ b/include/sta/spi_device.hpp @@ -87,6 +87,15 @@ namespace sta */ void receive(uint8_t * buffer, size_t size); + + /** + * @brief Get SPI interface settings. + * + * @return SPI settings + */ + const SpiSettings & settings() const; + + /** * @brief Activate device via CS pin. */ diff --git a/include/sta/spi_interface.hpp b/include/sta/spi_interface.hpp index 5708b89..fea5ddd 100644 --- a/include/sta/spi_interface.hpp +++ b/include/sta/spi_interface.hpp @@ -5,6 +5,7 @@ #define STA_SPI_INTERFACE_HPP #include +#include #include #include @@ -19,9 +20,10 @@ namespace sta { public: /** + * @param settings SPI interface settings * @param mutex Mutex object for managing shared access. Pass nullptr for no access control */ - SpiInterface(Mutex * mutex = nullptr); + SpiInterface(const SpiSettings & settings, Mutex * mutex = nullptr); /** @@ -76,6 +78,15 @@ namespace sta */ virtual void receive(uint8_t * buffer, size_t size) = 0; + + /** + * @brief Get SPI interface settings. + * + * @return SPI settings + */ + const SpiSettings & settings() const; + + /** * @brief Acquire usage rights to use the interface. * @@ -90,7 +101,8 @@ namespace sta virtual void release(); private: - Mutex * mutex_; /**< Mutex object */ + SpiSettings settings_; /** SPI settings */ + Mutex * mutex_; /**< Mutex object */ }; } // namespace sta diff --git a/src/hal/spi.cpp b/src/hal/spi.cpp index 69a428e..45b2b88 100644 --- a/src/hal/spi.cpp +++ b/src/hal/spi.cpp @@ -3,12 +3,71 @@ #ifdef STA_HAL_SPI_ENABLE #include +#include namespace sta { + static SpiSettings getHalSpiSettings(SPI_HandleTypeDef * handle) + { + SpiSettings settings; + + settings.mode = getSpiMode( + (handle->Init.CLKPolarity == SPI_POLARITY_LOW) ? SpiClkPolarity::LOW : SpiClkPolarity::HIGH, + (handle->Init.CLKPhase == SPI_PHASE_1EDGE) ? SpiClkPhase::EDGE_1 : SpiClkPhase::EDGE_2 + ); + settings.dataSize = (handle->Init.DataSize == SPI_DATASIZE_8BIT) ? SpiDataSize::BIT_8 : SpiDataSize::BIT_16; + settings.bitOrder = (handle->Init.FirstBit == SPI_FIRSTBIT_MSB) ? SpiBitOrder::MSB : SpiBitOrder::LSB; + + uint32_t prescaler = 1; + switch (handle->Init.BaudRatePrescaler) + { + case SPI_BAUDRATEPRESCALER_2: + settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_2; + prescaler = 2; + break; + case SPI_BAUDRATEPRESCALER_4: + settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_4; + prescaler = 2; + break; + case SPI_BAUDRATEPRESCALER_8: + settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_8; + prescaler = 2; + break; + case SPI_BAUDRATEPRESCALER_16: + settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_16; + prescaler = 2; + break; + case SPI_BAUDRATEPRESCALER_32: + settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_32; + prescaler = 2; + break; + case SPI_BAUDRATEPRESCALER_64: + settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_64; + prescaler = 2; + break; + case SPI_BAUDRATEPRESCALER_128: + settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_128; + prescaler = 2; + break; + case SPI_BAUDRATEPRESCALER_256: + settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_256; + prescaler = 2; + break; + default: + // Unreachable case + STA_ASSERT_MSG(false, "Case for SPI_BAUDRATEPRESCALER not handled"); + STA_UNREACHABLE(); + } + + settings.clkSpeed = HAL_RCC_GetSysClockFreq() / prescaler; + + return settings; + } + + HalSpiInterface::HalSpiInterface(SPI_HandleTypeDef * handle, Mutex * mutex /* = nullptr */) - : SpiInterface(mutex), handle_{handle} + : SpiInterface(getHalSpiSettings(handle), mutex), handle_{handle} { STA_ASSERT(handle != nullptr); } @@ -38,7 +97,7 @@ namespace sta void HalSpiInterface::transfer16(uint16_t value) { - static_assert(sizeof(uint16_t) == 2); + static_assert(sizeof(uint16_t) == 2, "Unexpected uint16_t size"); HAL_SPI_Transmit(handle_, reinterpret_cast(&value), 2, HAL_MAX_DELAY); } @@ -56,7 +115,7 @@ namespace sta void HalSpiInterface::fill32(uint32_t value, size_t count) { - static_assert(sizeof(uint32_t) == 4); + static_assert(sizeof(uint32_t) == 4, "Unexpected uint32_t size"); STA_ASSERT(count != 0); for (size_t i = 0; i < count; ++i) diff --git a/src/spi_device.cpp b/src/spi_device.cpp index 701d0e3..d3130e9 100644 --- a/src/spi_device.cpp +++ b/src/spi_device.cpp @@ -74,4 +74,9 @@ namespace sta intf_->receive(buffer, size); } + + const SpiSettings & SpiDevice::settings() const + { + return intf_->settings(); + } } // namespace sta diff --git a/src/spi_interface.cpp b/src/spi_interface.cpp index 26a141e..3abcca7 100644 --- a/src/spi_interface.cpp +++ b/src/spi_interface.cpp @@ -3,10 +3,15 @@ namespace sta { - SpiInterface::SpiInterface(Mutex * mutex /* = nullptr */) - : mutex_{mutex} + SpiInterface::SpiInterface(const SpiSettings & settings, Mutex * mutex /* = nullptr */) + : settings_{settings}, mutex_{mutex} {} + const SpiSettings & SpiInterface::settings() const + { + return settings_; + } + void SpiInterface::acquire() { if (mutex_ != nullptr) From a468133c97e5c6b8d85aa8b232f17065b7bf73d4 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Tue, 19 Apr 2022 23:20:20 +0200 Subject: [PATCH 29/35] Rework SPI interfaces --- include/sta/spi_device.hpp | 31 +++++++++++-------------- include/sta/spi_interface.hpp | 43 ++++++++++++++--------------------- include/sta/spi_settings.hpp | 22 ++++++++---------- src/spi_device.cpp | 24 ++++++++----------- src/spi_interface.cpp | 9 ++------ 5 files changed, 51 insertions(+), 78 deletions(-) diff --git a/include/sta/spi_device.hpp b/include/sta/spi_device.hpp index 336e123..7e02f47 100644 --- a/include/sta/spi_device.hpp +++ b/include/sta/spi_device.hpp @@ -23,6 +23,7 @@ namespace sta */ SpiDevice(SpiInterface * intf); + /** * @brief Start transmission with device. * @@ -36,12 +37,19 @@ namespace sta */ void endTransmission(); + /** * @brief Send single byte of data. * * @param value 8-bit value */ void transfer(uint8_t value); + /** + * @brief Send two bytes of data. + * + * @param value 16-bit value + */ + void transfer16(uint16_t data); /** * @brief Send data from buffer. * @@ -58,11 +66,13 @@ namespace sta */ void transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size); /** - * @brief Send two bytes of data. + * @brief Read incoming data to buffer. * - * @param value 16-bit value + * @param buffer Destination buffer + * @param size Number of bytes to read */ - void transfer16(uint16_t data); + void receive(uint8_t * buffer, size_t size); + /** * @brief Send byte value repeatedly. @@ -71,21 +81,6 @@ namespace sta * @param count Number of repetitions */ void fill(uint8_t value, size_t count); - /** - * @brief Send 32-bit value repeatedly. - * - * @param value 32-bit value to repeat - * @param count Number of repetitions - */ - void fill32(uint32_t value, size_t count); - - /** - * @brief Read incoming data to buffer. - * - * @param buffer Destination buffer - * @param size Number of bytes to read - */ - void receive(uint8_t * buffer, size_t size); /** diff --git a/include/sta/spi_interface.hpp b/include/sta/spi_interface.hpp index fea5ddd..3c05e12 100644 --- a/include/sta/spi_interface.hpp +++ b/include/sta/spi_interface.hpp @@ -23,7 +23,7 @@ namespace sta * @param settings SPI interface settings * @param mutex Mutex object for managing shared access. Pass nullptr for no access control */ - SpiInterface(const SpiSettings & settings, Mutex * mutex = nullptr); + SpiInterface(Mutex * mutex = nullptr); /** @@ -32,6 +32,12 @@ namespace sta * @param value 8-bit value */ virtual void transfer(uint8_t value) = 0; + /** + * @brief Send two bytes of data. + * + * @param value 16-bit value + */ + virtual void transfer16(uint16_t value) = 0; /** * @brief Send data from buffer. * @@ -47,29 +53,6 @@ namespace sta * @param size Number of bytes to transfer */ virtual void transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) = 0; - - /** - * @brief Send two bytes of data. - * - * @param value 16-bit value - */ - virtual void transfer16(uint16_t value) = 0; - - /** - * @brief Send byte value repeatedly. - * - * @param value 8-bit value to repeat - * @param count Number of repetitions - */ - virtual void fill(uint8_t value, size_t count) = 0; - /** - * @brief Send 32-bit value repeatedly. - * - * @param value 32-bit value to repeat - * @param count Number of repetitions - */ - virtual void fill32(uint32_t value, size_t count) = 0; - /** * @brief Read incoming data to buffer. * @@ -79,12 +62,21 @@ namespace sta virtual void receive(uint8_t * buffer, size_t size) = 0; + /** + * @brief Send byte value repeatedly. + * + * @param value 8-bit value to repeat + * @param count Number of repetitions + */ + virtual void fill(uint8_t value, size_t count) = 0; + + /** * @brief Get SPI interface settings. * * @return SPI settings */ - const SpiSettings & settings() const; + virtual const SpiSettings & settings() const = 0; /** @@ -101,7 +93,6 @@ namespace sta virtual void release(); private: - SpiSettings settings_; /** SPI settings */ Mutex * mutex_; /**< Mutex object */ }; } // namespace sta diff --git a/include/sta/spi_settings.hpp b/include/sta/spi_settings.hpp index ec89f56..d88a428 100644 --- a/include/sta/spi_settings.hpp +++ b/include/sta/spi_settings.hpp @@ -28,8 +28,8 @@ namespace sta enum class SpiDataSize { - BIT_8, - BIT_16 + SIZE_8, + SIZE_16 }; enum class SpiBitOrder @@ -40,14 +40,14 @@ namespace sta enum class SpiBaudRatePrescaler { - BRP_2, - BRP_4, - BRP_8, - BRP_16, - BRP_32, - BRP_64, - BRP_128, - BRP_256 + DIV_2, + DIV_4, + DIV_8, + DIV_16, + DIV_32, + DIV_64, + DIV_128, + DIV_256 }; @@ -56,9 +56,7 @@ namespace sta SpiMode mode; SpiDataSize dataSize; SpiBitOrder bitOrder; - uint32_t clkSpeed; - SpiBaudRatePrescaler baudRatePrescaler; /**< Subject to change */ }; diff --git a/src/spi_device.cpp b/src/spi_device.cpp index d3130e9..4f54883 100644 --- a/src/spi_device.cpp +++ b/src/spi_device.cpp @@ -33,6 +33,11 @@ namespace sta intf_->transfer(data); } + void SpiDevice::transfer16(uint16_t data) + { + intf_->transfer16(data); + } + void SpiDevice::transfer(const uint8_t * buffer, size_t size) { STA_ASSERT(buffer != nullptr); @@ -49,9 +54,11 @@ namespace sta intf_->transfer(txBuffer, rxBuffer, size); } - void SpiDevice::transfer16(uint16_t data) + void SpiDevice::receive(uint8_t * buffer, size_t size) { - intf_->transfer16(data); + STA_ASSERT(buffer != nullptr); + + intf_->receive(buffer, size); } void SpiDevice::fill(uint8_t value, size_t count) @@ -61,19 +68,6 @@ namespace sta intf_->fill(value, count); } - void SpiDevice::fill32(uint32_t value, size_t count) - { - STA_ASSERT(count != 0); - - intf_->fill32(value, count); - } - - void SpiDevice::receive(uint8_t * buffer, size_t size) - { - STA_ASSERT(buffer != nullptr); - - intf_->receive(buffer, size); - } const SpiSettings & SpiDevice::settings() const { diff --git a/src/spi_interface.cpp b/src/spi_interface.cpp index 3abcca7..26a141e 100644 --- a/src/spi_interface.cpp +++ b/src/spi_interface.cpp @@ -3,15 +3,10 @@ namespace sta { - SpiInterface::SpiInterface(const SpiSettings & settings, Mutex * mutex /* = nullptr */) - : settings_{settings}, mutex_{mutex} + SpiInterface::SpiInterface(Mutex * mutex /* = nullptr */) + : mutex_{mutex} {} - const SpiSettings & SpiInterface::settings() const - { - return settings_; - } - void SpiInterface::acquire() { if (mutex_ != nullptr) From 3041499ce0ca0d341e531c6896990156a31c5142 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Tue, 19 Apr 2022 23:22:04 +0200 Subject: [PATCH 30/35] Implement changes to SPI interfaces --- include/sta/hal/spi.hpp | 64 +++++++++++++++++--- src/hal/spi.cpp | 127 ++++++++++++++++++++++++++-------------- 2 files changed, 140 insertions(+), 51 deletions(-) diff --git a/include/sta/hal/spi.hpp b/include/sta/hal/spi.hpp index dcc6280..7034368 100644 --- a/include/sta/hal/spi.hpp +++ b/include/sta/hal/spi.hpp @@ -23,6 +23,23 @@ namespace sta { + /** + * @brief Get peripheral clock frequency. + * + * @return Clock frequency + */ + using HalSpiPCLKFreqFn = uint32_t (*)(); + + /** + * @brief Info related to HAL SPI interface. + */ + struct HalSpiInterfaceInfo + { + SPI_HandleTypeDef * handle; /**< Interface handle */ + HalSpiPCLKFreqFn getPCLKFreq; /**< Getter for peripheral clock used by interface */ + }; + + /** * @brief Implementation of `SpiInterface` interface using HAL. */ @@ -30,24 +47,23 @@ namespace sta { public: /** - * @param handle SPI handle + * @param info SPI interface info * @param mutex Mutex object for managing access. Pass nullptr for no access control */ - HalSpiInterface(SPI_HandleTypeDef * handle, Mutex * mutex = nullptr); + HalSpiInterface(const HalSpiInterfaceInfo & info, Mutex * mutex = nullptr); void transfer(uint8_t value) override; + void transfer16(uint16_t value) override; void transfer(const uint8_t * buffer, size_t size) override; void transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) override; - void transfer16(uint16_t value) override; - - void fill(uint8_t value, size_t count) override; - void fill32(uint32_t value, size_t count) override; - void receive(uint8_t * buffer, size_t size) override; + void fill(uint8_t value, size_t count) override; + + const SpiSettings & settings() const override; private: - SPI_HandleTypeDef * handle_; /**< SPI handle */ + HalSpiInterfaceInfo info_; /**< SPI interface info */ }; @@ -72,6 +88,38 @@ namespace sta } // namespace sta + +/** + * @brief Get function returning PCLK frequency. + * + * @param n Index of peripheral clock + */ +#define STA_HAL_GET_PCLK_FREQ_FN(n) HAL_RCC_GetPCLK ## n ## Freq + +/** + * @brief Get SPI interface info struct. + * + * Check the MCUs Reference Manual RCC register documentation to see which + * peripheral clock is used. + * + * @param n Index of SPI interface (e.g. 2 for SPI2) + * @param pclk Index of peripheral clock used by SPI interface + */ +#define STA_HAL_SPI_INFO_MANUAL(n, pclk) sta::HalSpiInterfaceInfo{&hspi ## n, STA_HAL_GET_PCLK_FREQ_FN(pclk)} + +/** + * @brief Get SPI interface info struct. + * + * Requires STA_HAL_SPI_n_PCLK_IDX set to idx of PCLK used by the interface. + * + * Check the MCUs Reference Manual RCC register documentation to see which + * peripheral clock is used. + * + * @param n Index of SPI interface (e.g. 2 for SPI2) + */ +#define STA_HAL_SPI_INFO(n) STA_HAL_SPI_INFO_MANUAL(n, STA_HAL_SPI_ ## n ## _PCLK_IDX) + + #endif // STA_HAL_SPI_ENABLE #endif // STA_HAL_SPI_HPP diff --git a/src/hal/spi.cpp b/src/hal/spi.cpp index 45b2b88..708a5c2 100644 --- a/src/hal/spi.cpp +++ b/src/hal/spi.cpp @@ -3,12 +3,26 @@ #ifdef STA_HAL_SPI_ENABLE #include +#include #include +#ifdef STA_MCU_LITTLE_ENDIAN +# define STA_HAL_SPI_REVERSE_BIT_ORDER SpiBitOrder::MSB +#elif STA_MCU_BIG_ENDIAN +# define STA_HAL_SPI_REVERSE_BIT_ORDER SpiBitOrder::LSB +#else // !STA_MCU_LITTLE_ENDIAN && !STA_MCU_BIG_ENDIAN +# ifdef STA_HAL_SPI_REVERSE_BIT_ORDER +# warning "Internal STA_HAL_SPI_REVERSE_BIT_ORDER macro manually defined! Better now what you are doing!!!" +# else // !STA_HAL_SPI_REVERSE_BIT_ORDER +# error "Unknown endian-ness. Define STA_MCU_LITTLE_ENDIAN or STA_MCU_BIG_ENDIAN in " +# endif // !STA_HAL_SPI_REVERSE_BIT_ORDER +#endif // !STA_MCU_LITTLE_ENDIAN && !STA_MCU_BIG_ENDIAN + + namespace sta { - static SpiSettings getHalSpiSettings(SPI_HandleTypeDef * handle) + static SpiSettings getHalSpiSettings(SPI_HandleTypeDef * handle, uint32_t pclkFreq) { SpiSettings settings; @@ -16,43 +30,35 @@ namespace sta (handle->Init.CLKPolarity == SPI_POLARITY_LOW) ? SpiClkPolarity::LOW : SpiClkPolarity::HIGH, (handle->Init.CLKPhase == SPI_PHASE_1EDGE) ? SpiClkPhase::EDGE_1 : SpiClkPhase::EDGE_2 ); - settings.dataSize = (handle->Init.DataSize == SPI_DATASIZE_8BIT) ? SpiDataSize::BIT_8 : SpiDataSize::BIT_16; + settings.dataSize = (handle->Init.DataSize == SPI_DATASIZE_8BIT) ? SpiDataSize::SIZE_8 : SpiDataSize::SIZE_16; settings.bitOrder = (handle->Init.FirstBit == SPI_FIRSTBIT_MSB) ? SpiBitOrder::MSB : SpiBitOrder::LSB; uint32_t prescaler = 1; switch (handle->Init.BaudRatePrescaler) { case SPI_BAUDRATEPRESCALER_2: - settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_2; prescaler = 2; break; case SPI_BAUDRATEPRESCALER_4: - settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_4; - prescaler = 2; + prescaler = 4; break; case SPI_BAUDRATEPRESCALER_8: - settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_8; - prescaler = 2; + prescaler = 8; break; case SPI_BAUDRATEPRESCALER_16: - settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_16; - prescaler = 2; + prescaler = 16; break; case SPI_BAUDRATEPRESCALER_32: - settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_32; - prescaler = 2; + prescaler = 32; break; case SPI_BAUDRATEPRESCALER_64: - settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_64; - prescaler = 2; + prescaler = 64; break; case SPI_BAUDRATEPRESCALER_128: - settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_128; - prescaler = 2; + prescaler = 128; break; case SPI_BAUDRATEPRESCALER_256: - settings.baudRatePrescaler = SpiBaudRatePrescaler::BRP_256; - prescaler = 2; + prescaler = 256; break; default: // Unreachable case @@ -60,29 +66,62 @@ namespace sta STA_UNREACHABLE(); } - settings.clkSpeed = HAL_RCC_GetSysClockFreq() / prescaler; + // SPI clock speed is based of PCLK + settings.clkSpeed = pclkFreq / prescaler; return settings; } - HalSpiInterface::HalSpiInterface(SPI_HandleTypeDef * handle, Mutex * mutex /* = nullptr */) - : SpiInterface(getHalSpiSettings(handle), mutex), handle_{handle} + HalSpiInterface::HalSpiInterface(const HalSpiInterfaceInfo & info, Mutex * mutex /* = nullptr */) + : SpiInterface(mutex), info_{info} { - STA_ASSERT(handle != nullptr); + STA_ASSERT(info.handle != nullptr); + STA_ASSERT(info.getPCLKFreq != nullptr); } - void HalSpiInterface::transfer(uint8_t data) + void HalSpiInterface::transfer(uint8_t value) { - HAL_SPI_Transmit(handle_, &data, 1, HAL_MAX_DELAY); + if (settings().dataSize == SpiDataSize::SIZE_8) + { + HAL_SPI_Transmit(info_.handle, &value, 1, HAL_MAX_DELAY); + } + else + { + // Required since tx buffer is cast to uint16_t * internally + uint16_t dummy = value; + HAL_SPI_Transmit(info_.handle, reinterpret_cast(&dummy), 1, HAL_MAX_DELAY); + } + } + + void HalSpiInterface::transfer16(uint16_t value) + { + static_assert(sizeof(value) == 2, "Unexpected uint16_t size"); + + uint16_t size = 1; + + // Send as two bytes if data size is 8-bit + if (settings().dataSize == SpiDataSize::SIZE_8) + { + size = 2; + + if (settings().bitOrder == STA_HAL_SPI_REVERSE_BIT_ORDER) + { + // Reverse byte order from internal representation + value = STA_UINT16_SWAP_BYTE_ORDER(value); + } + } + + HAL_SPI_Transmit(info_.handle, reinterpret_cast(&value), size, HAL_MAX_DELAY); } void HalSpiInterface::transfer(const uint8_t * buffer, size_t size) { STA_ASSERT(buffer != nullptr); + STA_ASSERT(size != 0); - HAL_SPI_Transmit(handle_, const_cast(buffer), size, HAL_MAX_DELAY); + HAL_SPI_Transmit(info_.handle, const_cast(buffer), size, HAL_MAX_DELAY); } void HalSpiInterface::transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) @@ -91,15 +130,14 @@ namespace sta STA_ASSERT(rxBuffer != nullptr); STA_ASSERT(size != 0); - HAL_SPI_TransmitReceive(handle_, const_cast(txBuffer), rxBuffer, size, HAL_MAX_DELAY); + HAL_SPI_TransmitReceive(info_.handle, const_cast(txBuffer), rxBuffer, size, HAL_MAX_DELAY); } - - void HalSpiInterface::transfer16(uint16_t value) + void HalSpiInterface::receive(uint8_t * buffer, size_t size) { - static_assert(sizeof(uint16_t) == 2, "Unexpected uint16_t size"); + STA_ASSERT(buffer != nullptr); - HAL_SPI_Transmit(handle_, reinterpret_cast(&value), 2, HAL_MAX_DELAY); + HAL_SPI_Receive(info_.handle, buffer, size, HAL_MAX_DELAY); } @@ -107,33 +145,36 @@ namespace sta { STA_ASSERT(count != 0); - for (size_t i = 0; i < count; ++i) + if (settings().dataSize == SpiDataSize::SIZE_8) { - transfer(value); + for (size_t i = 0; i < count; ++i) + { + HAL_SPI_Transmit(info_.handle, &value, 1, HAL_MAX_DELAY); + } } - } - - void HalSpiInterface::fill32(uint32_t value, size_t count) - { - static_assert(sizeof(uint32_t) == 4, "Unexpected uint32_t size"); - STA_ASSERT(count != 0); - - for (size_t i = 0; i < count; ++i) + else { - HAL_SPI_Transmit(handle_, reinterpret_cast(&value), 4, HAL_MAX_DELAY); + // Required since tx buffer is cast to uint16_t * internally + uint16_t dummy = value; + for (size_t i = 0; i < count; ++i) + { + HAL_SPI_Transmit(info_.handle, reinterpret_cast(&dummy), 1, HAL_MAX_DELAY); + } } } - void HalSpiInterface::receive(uint8_t * buffer, size_t size) + const SpiSettings & HalSpiInterface::settings() const { - STA_ASSERT(buffer != nullptr); + // Cache settings + static SpiSettings settings = getHalSpiSettings(info_.handle, info_.getPCLKFreq()); - HAL_SPI_Receive(handle_, buffer, size, HAL_MAX_DELAY); + return settings; } + HalSpiDevice::HalSpiDevice(SpiInterface * intf, HalGpioPin csPin) : SpiDevice(intf), csPin_{csPin} {} From 9ea2513e5a52e86b72fc13c148a5cf636e83a247 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Tue, 19 Apr 2022 23:22:33 +0200 Subject: [PATCH 31/35] Add getter for HAL GPIO pin data --- include/sta/hal/gpio_pin.hpp | 4 ++++ src/hal/gpio_pin.cpp | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/sta/hal/gpio_pin.hpp b/include/sta/hal/gpio_pin.hpp index 03ea594..d4cdf9b 100644 --- a/include/sta/hal/gpio_pin.hpp +++ b/include/sta/hal/gpio_pin.hpp @@ -26,6 +26,10 @@ namespace sta void setState(GpioPinState state) override; + GPIO_TypeDef * getPort() const; + uint16_t getPin() const; + uint8_t getIndex() const; + private: GPIO_TypeDef * port_; /**< GPIO port */ uint16_t pin_; /**< GPIO pin */ diff --git a/src/hal/gpio_pin.cpp b/src/hal/gpio_pin.cpp index d8fd93e..678b936 100644 --- a/src/hal/gpio_pin.cpp +++ b/src/hal/gpio_pin.cpp @@ -17,6 +17,21 @@ namespace sta { HAL_GPIO_WritePin(port_, pin_, (state == GpioPinState::LOW) ? GPIO_PIN_RESET : GPIO_PIN_SET); } + + GPIO_TypeDef * HalGpioPin::getPort() const + { + return port_; + } + + uint16_t HalGpioPin::getPin() const + { + return pin_; + } + + uint8_t HalGpioPin::getIndex() const + { + return GPIO_GET_INDEX(port_); + } } // namespace sta From 0eac5fbf511b0343b8a6548c985baa6eb8c456f2 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Wed, 20 Apr 2022 19:25:15 +0200 Subject: [PATCH 32/35] Use malloc free printf --- src/uart.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/uart.cpp b/src/uart.cpp index 8a744bc..12bc743 100644 --- a/src/uart.cpp +++ b/src/uart.cpp @@ -1,8 +1,11 @@ #include -#include +//#include #include +// Include last so macros don't mess with other headers +#include + namespace sta { From e7d246a2e78410013421c43f669da7c31d99fcf4 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sun, 24 Apr 2022 13:43:15 +0200 Subject: [PATCH 33/35] Add HAL clock helpers --- include/sta/hal/clocks.hpp | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 include/sta/hal/clocks.hpp diff --git a/include/sta/hal/clocks.hpp b/include/sta/hal/clocks.hpp new file mode 100644 index 0000000..d29a23a --- /dev/null +++ b/include/sta/hal/clocks.hpp @@ -0,0 +1,60 @@ +/** + * @brief Helper macros for HAL clock queries. + */ +#ifndef STA_HAL_CLOCKS_HPP +#define STA_HAL_CLOCKS_HPP + +#include +#include + + +/** + * @brief Get function returning PCLK frequency. + * + * @param n Index of peripheral clock + */ +#define STA_HAL_GET_PCLK_FREQ_FN(n) HAL_RCC_GetPCLK ## n ## Freq + + +// Internal helper for macro expansion +#define _STA_HAL_GET_PCLK_FREQ_FN(n) STA_HAL_GET_PCLK_FREQ_FN(n) +// Get instance to PCLK index map macro +#define _STA_PCLK_IDX_MAP(type, idx) STA_ ## type ## _ ## idx ## _PCLK_IDX +// Get HAL handle to PCLK index map macro +#define _STA_HAL_PCLK_IDX_MAP(handle) STA_HAL_ ## handle ## _PCLK_IDX + + +/** + * @brief Get function returning frequency of PCLK used by TIM. + * + * @param n TIM index + */ +#define STA_HAL_GET_TIM_PCLK_FREQ_FN(n) _STA_HAL_GET_PCLK_FREQ_FN(_STA_PCLK_IDX_MAP(TIM, n)) +/** + * @brief Get function returning frequency of PCLK used by SPI interface. + * + * @param n SPI interface index + */ +#define STA_HAL_GET_SPI_PCLK_FREQ_FN(n) _STA_HAL_GET_PCLK_FREQ_FN(_STA_PCLK_IDX_MAP(SPI, n)) +/** + * @brief Get function returning frequency of PCLK used by I2C interface. + * + * @param n I2C interface index + */ +#define STA_HAL_GET_I2C_PCLK_FREQ_FN(n) _STA_HAL_GET_PCLK_FREQ_FN(_STA_PCLK_IDX_MAP(I2C, n)) +/** + * @brief Get function returning frequency of PCLK used by USART interface. + * + * @param n USART interface index + */ +#define STA_HAL_GET_USART_PCLK_FREQ_FN(n) _STA_HAL_GET_PCLK_FREQ_FN(_STA_PCLK_IDX_MAP(USART, n)) + +/** + * @brief Get function returning frequency of PCLK used by HAL instance. + * + * @param handle Instance handle + */ +#define STA_HAL_GET_HANDLE_PCLK_FREQ_FN(handle) _STA_HAL_GET_PCLK_FREQ_FN(_STA_HAL_PCLK_IDX_MAP(handle)) + + +#endif // STA_HAL_CLOCKS_HPP From a24aa1c5c611fe5a29e8e86a5a5d1537e3d68533 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Sun, 24 Apr 2022 13:43:44 +0200 Subject: [PATCH 34/35] Improve doxygen comments --- include/sta/atomic/mutex.hpp | 3 ++- include/sta/atomic/signal.hpp | 3 ++- include/sta/hal/gpio_pin.hpp | 6 ++--- include/sta/hal/spi.hpp | 37 +++++++------------------ include/sta/hal/uart.hpp | 10 +++---- include/sta/spi_device.hpp | 4 +-- include/sta/spi_interface.hpp | 4 +-- include/sta/spi_settings.hpp | 51 ++++++++++++++++++++++++++++++++--- include/sta/uart.hpp | 4 +-- src/uart.cpp | 7 +++-- 10 files changed, 77 insertions(+), 52 deletions(-) diff --git a/include/sta/atomic/mutex.hpp b/include/sta/atomic/mutex.hpp index dcab789..a41b89f 100644 --- a/include/sta/atomic/mutex.hpp +++ b/include/sta/atomic/mutex.hpp @@ -1,7 +1,8 @@ /** * @brief Atomic mutex implementation. * - * Define **STA_ATOMIC_ENABLE** to enable module. + * Configuration: + * STA_ATOMIC_ENABLE: Enable module */ #ifndef STA_ATOMIC_MUTEX_HPP #define STA_ATOMIC_MUTEX_HPP diff --git a/include/sta/atomic/signal.hpp b/include/sta/atomic/signal.hpp index 4ca8cfc..b84f030 100644 --- a/include/sta/atomic/signal.hpp +++ b/include/sta/atomic/signal.hpp @@ -1,7 +1,8 @@ /** * @brief Atomic signal implementation. * - * Define **STA_ATOMIC_ENABLE** to enable module. + * Configuration: + * STA_ATOMIC_ENABLE: Enable module */ #ifndef STA_ATOMIC_SIGNAL_HPP #define STA_ATOMIC_SIGNAL_HPP diff --git a/include/sta/hal/gpio_pin.hpp b/include/sta/hal/gpio_pin.hpp index d4cdf9b..08b7f9c 100644 --- a/include/sta/hal/gpio_pin.hpp +++ b/include/sta/hal/gpio_pin.hpp @@ -1,7 +1,8 @@ /** * @brief Wrapper for HAL GPIO pins. * - * Define **STA_HAL_GPIO_ENABLE** in `` to enable module. + * Configuration: + * STA_HAL_GPIO_ENABLE: Enable module */ #ifndef STA_HAL_GPIO_PIN_HPP #define STA_HAL_GPIO_PIN_HPP @@ -10,8 +11,7 @@ #ifdef STA_HAL_GPIO_ENABLE #include - -#include +#include namespace sta diff --git a/include/sta/hal/spi.hpp b/include/sta/hal/spi.hpp index 7034368..b992513 100644 --- a/include/sta/hal/spi.hpp +++ b/include/sta/hal/spi.hpp @@ -1,9 +1,10 @@ /** * @brief Implementations for `SpiInterface` and `SpiDevice` using HAL. * - * Define **STA_HAL_SPI_ENABLE** in `` to enable module. + * Configuration: + * STA_HAL_SPI_ENABLE: Enable module * - * Requires **STA_HAL_GPIO_ENABLE**. + * Requires **HAL_GPIO** module. */ #ifndef STA_HAL_SPI_HPP #define STA_HAL_SPI_HPP @@ -15,11 +16,11 @@ #error "HAL GPIO required" #endif // !STA_HAL_GPIO_ENABLE +#include #include +#include #include -#include - namespace sta { @@ -88,36 +89,18 @@ namespace sta } // namespace sta - /** - * @brief Get function returning PCLK frequency. + * @brief Get SPI interface info struct for HAL handle. * - * @param n Index of peripheral clock - */ -#define STA_HAL_GET_PCLK_FREQ_FN(n) HAL_RCC_GetPCLK ## n ## Freq - -/** - * @brief Get SPI interface info struct. + * Requires STA_HAL__PCLK_IDX to be defined for the MCU. + * MCU mappings are found in `core` -> sta/mcu/.hpp files. * * Check the MCUs Reference Manual RCC register documentation to see which * peripheral clock is used. * - * @param n Index of SPI interface (e.g. 2 for SPI2) - * @param pclk Index of peripheral clock used by SPI interface + * @param handle SPI interface handle */ -#define STA_HAL_SPI_INFO_MANUAL(n, pclk) sta::HalSpiInterfaceInfo{&hspi ## n, STA_HAL_GET_PCLK_FREQ_FN(pclk)} - -/** - * @brief Get SPI interface info struct. - * - * Requires STA_HAL_SPI_n_PCLK_IDX set to idx of PCLK used by the interface. - * - * Check the MCUs Reference Manual RCC register documentation to see which - * peripheral clock is used. - * - * @param n Index of SPI interface (e.g. 2 for SPI2) - */ -#define STA_HAL_SPI_INFO(n) STA_HAL_SPI_INFO_MANUAL(n, STA_HAL_SPI_ ## n ## _PCLK_IDX) +#define STA_HAL_SPI_INFO(handle) sta::HalSpiInterfaceInfo{&handle, STA_HAL_GET_HANDLE_PCLK_FREQ_FN(handle)} #endif // STA_HAL_SPI_ENABLE diff --git a/include/sta/hal/uart.hpp b/include/sta/hal/uart.hpp index c12c5dc..398a00e 100644 --- a/include/sta/hal/uart.hpp +++ b/include/sta/hal/uart.hpp @@ -1,10 +1,9 @@ /** * @brief Implementation of UART using HAL. * - * Define **STA_HAL_UART_ENABLE** in `` to enable module. - * - * To use a HAL UART instance (e.g. UART1) for `` define: - * #define STA_HAL_UART_DEBUG_SERIAL huart1 + * Configuration: + * STA_HAL_UART_ENABLE: Enable module + * STA_HAL_UART_DEBUG_SERIAL: Create global `sta::DebugSerial` object using this UART instance */ #ifndef STA_HAL_UART_HPP #define STA_HAL_UART_HPP @@ -12,10 +11,9 @@ #include #ifdef STA_HAL_UART_ENABLE +#include #include -#include - namespace sta { diff --git a/include/sta/spi_device.hpp b/include/sta/spi_device.hpp index 7e02f47..44253cc 100644 --- a/include/sta/spi_device.hpp +++ b/include/sta/spi_device.hpp @@ -6,8 +6,8 @@ #include -#include -#include +#include +#include namespace sta diff --git a/include/sta/spi_interface.hpp b/include/sta/spi_interface.hpp index 3c05e12..4d6ef17 100644 --- a/include/sta/spi_interface.hpp +++ b/include/sta/spi_interface.hpp @@ -7,8 +7,8 @@ #include #include -#include -#include +#include +#include namespace sta diff --git a/include/sta/spi_settings.hpp b/include/sta/spi_settings.hpp index d88a428..decec26 100644 --- a/include/sta/spi_settings.hpp +++ b/include/sta/spi_settings.hpp @@ -1,3 +1,6 @@ +/** + * @brief SPI setting types. + */ #ifndef STA_SPI_SETTINGS_HPP #define STA_SPI_SETTINGS_HPP @@ -6,18 +9,27 @@ namespace sta { + /** + * @brief SPI clock polarity. + */ enum class SpiClkPolarity { LOW, HIGH }; + /** + * @brief SPI clock phase. + */ enum class SpiClkPhase { EDGE_1, EDGE_2 }; + /** + * @brief SPI clock mode. + */ enum class SpiMode { MODE_0, @@ -26,18 +38,27 @@ namespace sta MODE_3 }; + /** + * @brief SPI data size. + */ enum class SpiDataSize { SIZE_8, SIZE_16 }; + /** + * @brief SPI bit order. + */ enum class SpiBitOrder { MSB, LSB }; + /** + * @brief Spi baud rate prescaler. + */ enum class SpiBaudRatePrescaler { DIV_2, @@ -51,17 +72,39 @@ namespace sta }; + /** + * @brief SPI settings. + */ struct SpiSettings { - SpiMode mode; - SpiDataSize dataSize; - SpiBitOrder bitOrder; - uint32_t clkSpeed; + SpiMode mode; /**< SPI clock mode */ + SpiDataSize dataSize; /**< SPI data size */ + SpiBitOrder bitOrder; /**< SPI bit order */ + uint32_t clkSpeed; /**< SPI clock speed */ }; + /** + * @brief Get SPI clock polarity from clock mode. + * + * @param mode SPI clock mode + * @return SPI clock polarity + */ SpiClkPolarity getSpiClkPolarity(SpiMode mode); + /** + * @brief Get SPI clock phase from clock mode. + * + * @param mode SPI clock mode + * @return SPI clock phase + */ SpiClkPhase getSpiClkPhase(SpiMode mode); + /** + * @brief Get SPI clock mode from clock phase and polarity. + * + * @param polarity SPI clock polarity + * @param phase SPI clock phase + * @return SPI clock mode + */ SpiMode getSpiMode(SpiClkPolarity polarity, SpiClkPhase phase); } // namespace sta diff --git a/include/sta/uart.hpp b/include/sta/uart.hpp index b849ea3..a287bd7 100644 --- a/include/sta/uart.hpp +++ b/include/sta/uart.hpp @@ -4,8 +4,8 @@ #ifndef STA_UART_HPP #define STA_UART_HPP -#include -#include +#include +#include namespace sta diff --git a/src/uart.cpp b/src/uart.cpp index 12bc743..5b5c7bb 100644 --- a/src/uart.cpp +++ b/src/uart.cpp @@ -1,10 +1,9 @@ #include -//#include +#include + #include -// Include last so macros don't mess with other headers -#include namespace sta @@ -143,7 +142,7 @@ namespace sta void UART::printDec(uintmax_t num, const char * fmt) { char buffer[64]; - sprintf(buffer, fmt, num); + snprintf(buffer, sizeof(buffer), fmt, num); print(buffer); } From 9e6595b65d9245b7d84ab5ebaef8cfc540266af0 Mon Sep 17 00:00:00 2001 From: Henrik Stickann <4376396-Mithradir@users.noreply.gitlab.com> Date: Wed, 27 Apr 2022 18:33:32 +0200 Subject: [PATCH 35/35] Fix integer formating --- src/uart.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/uart.cpp b/src/uart.cpp index 5b5c7bb..84240e7 100644 --- a/src/uart.cpp +++ b/src/uart.cpp @@ -3,6 +3,7 @@ #include #include +#include @@ -27,22 +28,22 @@ namespace sta void UART::print(uint8_t num, IntegerBase base /* = IntegerBase::DEC */) { - printBase(num, base, "%u", sizeof(num)); + printBase(num, base, "%" PRIu8, sizeof(num)); } void UART::print(uint16_t num, IntegerBase base /* = IntegerBase::DEC */) { - printBase(num, base, "%u", sizeof(num)); + printBase(num, base, "%" PRIu16, sizeof(num)); } void UART::print(uint32_t num, IntegerBase base /* = IntegerBase::DEC */) { - printBase(num, base, "%lu", sizeof(num)); + printBase(num, base, "%" PRIu32, sizeof(num)); } void UART::print(size_t num, IntegerBase base /* = IntegerBase::DEC */) { - printBase(num, base, "%u", sizeof(num)); + printBase(num, base, "%z", sizeof(num)); } void UART::print(const char * str) @@ -142,7 +143,7 @@ namespace sta void UART::printDec(uintmax_t num, const char * fmt) { char buffer[64]; - snprintf(buffer, sizeof(buffer), fmt, num); + snprintf(buffer, sizeof(buffer), fmt, static_cast(num)); print(buffer); }