Merge io_interfaces repo into helpers

This commit is contained in:
Henrik Stickann
2022-05-02 13:20:25 +02:00
24 changed files with 1726 additions and 4 deletions

View File

@@ -0,0 +1,39 @@
/**
* @brief Atomic mutex implementation.
*
* Configuration:
* STA_ATOMIC_ENABLE: Enable module
*/
#ifndef STA_ATOMIC_MUTEX_HPP
#define STA_ATOMIC_MUTEX_HPP
#include <sta/config.hpp>
#ifdef STA_ATOMIC_ENABLE
#include <sta/mutex.hpp>
#include <atomic>
namespace sta
{
/**
* @brief Implementation of `Mutex` interface using `std::atomic_flag`.
*/
class AtomicMutex : public Mutex
{
public:
AtomicMutex();
void acquire() override;
void release() override;
private:
std::atomic_flag lock_; /**< Atomic flag used as lock */
};
} // namespace sta
#endif // STA_ATOMIC_ENABLE
#endif // STA_ATOMIC_MUTEX_HPP

View File

@@ -0,0 +1,41 @@
/**
* @brief Atomic signal implementation.
*
* Configuration:
* STA_ATOMIC_ENABLE: Enable module
*/
#ifndef STA_ATOMIC_SIGNAL_HPP
#define STA_ATOMIC_SIGNAL_HPP
#include <sta/config.hpp>
#ifdef STA_ATOMIC_ENABLE
#include <sta/signal.hpp>
#include <atomic>
namespace sta
{
/**
* @brief Implementation of `Signal` interface using `std::atomic`.
*/
class AtomicSignal : public Signal
{
public:
AtomicSignal();
void notify() override;
bool peek() override;
bool test() override;
void wait() override;
private:
std::atomic<bool> signal_; /**< Atomic bool used as signal */
};
} // namespace sta
#endif // STA_ATOMIC_ENABLE
#endif // STA_ATOMIC_SIGNAL_HPP

35
include/sta/gpio_pin.hpp Normal file
View File

@@ -0,0 +1,35 @@
/**
* @brief GPIO pin interface definitions.
*/
#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

View File

@@ -0,0 +1,60 @@
/**
* @brief Helper macros for HAL clock queries.
*/
#ifndef STA_HAL_CLOCKS_HPP
#define STA_HAL_CLOCKS_HPP
#include <sta/config.hpp>
#include <sta/hal.hpp>
/**
* @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

View File

@@ -0,0 +1,49 @@
/**
* @brief Wrapper for HAL GPIO pins.
*
* Configuration:
* STA_HAL_GPIO_ENABLE: Enable module
*/
#ifndef STA_HAL_GPIO_PIN_HPP
#define STA_HAL_GPIO_PIN_HPP
#include <sta/config.hpp>
#ifdef STA_HAL_GPIO_ENABLE
#include <sta/gpio_pin.hpp>
#include <sta/hal.hpp>
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;
GPIO_TypeDef * getPort() const;
uint16_t getPin() const;
uint8_t getIndex() const;
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

108
include/sta/hal/spi.hpp Normal file
View File

@@ -0,0 +1,108 @@
/**
* @brief Implementations for `SpiInterface` and `SpiDevice` using HAL.
*
* Configuration:
* STA_HAL_SPI_ENABLE: Enable module
*
* Requires **HAL_GPIO** module.
*/
#ifndef STA_HAL_SPI_HPP
#define STA_HAL_SPI_HPP
#include <sta/config.hpp>
#ifdef STA_HAL_SPI_ENABLE
#ifndef STA_HAL_GPIO_ENABLE
#error "HAL GPIO required"
#endif // !STA_HAL_GPIO_ENABLE
#include <sta/hal.hpp>
#include <sta/spi_device.hpp>
#include <sta/hal/clocks.hpp>
#include <sta/hal/gpio_pin.hpp>
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.
*/
class HalSpiInterface : public SpiInterface
{
public:
/**
* @param info SPI interface info
* @param mutex Mutex object for managing access. Pass nullptr for no access control
*/
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 receive(uint8_t * buffer, size_t size) override;
void fill(uint8_t value, size_t count) override;
const SpiSettings & settings() const override;
private:
HalSpiInterfaceInfo info_; /**< SPI interface info */
};
/**
* @brief Implementation of `SpiDevice` interface 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
/**
* @brief Get SPI interface info struct for HAL handle.
*
* Requires STA_HAL_<handle>_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 handle SPI interface handle
*/
#define STA_HAL_SPI_INFO(handle) sta::HalSpiInterfaceInfo{&handle, STA_HAL_GET_HANDLE_PCLK_FREQ_FN(handle)}
#endif // STA_HAL_SPI_ENABLE
#endif // STA_HAL_SPI_HPP

43
include/sta/hal/uart.hpp Normal file
View File

@@ -0,0 +1,43 @@
/**
* @brief Implementation of UART using HAL.
*
* 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
#include <sta/config.hpp>
#ifdef STA_HAL_UART_ENABLE
#include <sta/hal.hpp>
#include <sta/uart.hpp>
namespace sta
{
/**
* @brief Implementation of `UART` interface using 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 */
};
} // namespace sta
#endif // STA_HAL_UART_ENABLE
#endif // STA_HAL_UART_HPP

30
include/sta/mutex.hpp Normal file
View File

@@ -0,0 +1,30 @@
/**
* @brief Mutex interface definition.
*/
#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

40
include/sta/signal.hpp Normal file
View File

@@ -0,0 +1,40 @@
/**
* @brief Signal interface definition.
*/
#ifndef STA_SIGNAL_HPP
#define STA_SIGNAL_HPP
namespace sta
{
/**
* @brief Interface for signal objects.
*/
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

109
include/sta/spi_device.hpp Normal file
View File

@@ -0,0 +1,109 @@
/**
* @brief SPI interface definitions.
*/
#ifndef STA_SPI_DEVICE_HPP
#define STA_SPI_DEVICE_HPP
#include <sta/spi_interface.hpp>
#include <cstdint>
#include <cstddef>
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 two bytes of data.
*
* @param value 16-bit value
*/
void transfer16(uint16_t data);
/**
* @brief Send data from buffer.
*
* @param buffer Source 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 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 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 Get SPI interface settings.
*
* @return SPI settings
*/
const SpiSettings & settings() const;
/**
* @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

View File

@@ -0,0 +1,101 @@
/**
* @brief SPI interface definitions.
*/
#ifndef STA_SPI_INTERFACE_HPP
#define STA_SPI_INTERFACE_HPP
#include <sta/mutex.hpp>
#include <sta/spi_settings.hpp>
#include <cstdint>
#include <cstddef>
namespace sta
{
/**
* @brief Interface for SPI hardware.
*/
class SpiInterface
{
public:
/**
* @param settings SPI interface settings
* @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 two bytes of data.
*
* @param value 16-bit value
*/
virtual void transfer16(uint16_t value) = 0;
/**
* @brief Send data from buffer.
*
* @param buffer Source 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 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 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
*/
virtual const SpiSettings & settings() const = 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

View File

@@ -0,0 +1,112 @@
/**
* @brief SPI setting types.
*/
#ifndef STA_SPI_SETTINGS_HPP
#define STA_SPI_SETTINGS_HPP
#include <cstdint>
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,
MODE_1,
MODE_2,
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,
DIV_4,
DIV_8,
DIV_16,
DIV_32,
DIV_64,
DIV_128,
DIV_256
};
/**
* @brief SPI settings.
*/
struct SpiSettings
{
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
#endif // STA_SPI_SETTINGS_HPP

198
include/sta/uart.hpp Normal file
View File

@@ -0,0 +1,198 @@
/**
* @brief UART interface definition.
*/
#ifndef STA_UART_HPP
#define STA_UART_HPP
#include <cstddef>
#include <cstdint>
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 floating point value.
*
* @param d Floating point value
*/
void print(double d);
/**
* @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 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.
*
* @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