/* * peripherals_hal_st.hpp * * Created on: Mar 30, 2021 * Author: erki */ #ifndef PERIPHERALS_INC_PERIPHERALS_HAL_ST_HPP_ #define PERIPHERALS_INC_PERIPHERALS_HAL_ST_HPP_ #include #include "peripherals_utility.hpp" #define USE_DELAY_US namespace Peripherals { namespace Hal { namespace St { template using IsrCallbackFn = void (*)(Origin*); template IsrCallbackFn createCallback(Handler& h_in) { static Handler* h = &h_in; return +[](Origin*) { (h->*func)(); }; } struct StaticHal { static void Initialize() { #ifdef USE_DELAY_US CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; #endif } static void Delay(const std::uint32_t milliseconds) { HAL_Delay(milliseconds); } static void DelayUs(const std::uint32_t micros) { #ifdef USE_DELAY_US const std::uint32_t tick_start = DWT->CYCCNT; const std::uint32_t ticks_delay = micros * (SystemCoreClock / 1'000'000); while (DWT->CYCCNT - tick_start < ticks_delay) ; #else (void) micros; #endif } static void enableInterrupts() { __enable_irq(); } static void disableInterrupts() { __disable_irq(); } }; #ifdef HAL_GPIO_MODULE_ENABLED struct Gpio { GPIO_TypeDef* port; std::uint16_t pin; Gpio() = delete; explicit Gpio(GPIO_TypeDef* port, const std::uint16_t pin) : port(port), pin(pin) {} void Set(const bool& state) { HAL_GPIO_WritePin(port, pin, GPIO_PinState(state)); } void Toggle() { HAL_GPIO_TogglePin(port, pin); } bool Read() const { return HAL_GPIO_ReadPin(port, pin); } }; #endif// HAL_GPIO_MODULE_ENABLED template< typename T, HAL_StatusTypeDef (*transmit)( T*, std::uint8_t* data, std::uint16_t data_len, std::uint32_t timeout), HAL_StatusTypeDef (*receive)(T*, std::uint8_t* data, std::uint16_t data_len, std::uint32_t timeout)> struct SerialInterface { using underlying_handle_type = T; underlying_handle_type* handle; SerialInterface() = delete; explicit SerialInterface(underlying_handle_type* handle) : handle(handle) {} bool Transmit(std::uint8_t* data, const std::uint32_t data_len) { return transmit(handle, data, data_len, 100) == HAL_StatusTypeDef::HAL_OK; } bool Receive(std::uint8_t* data, const std::uint32_t data_len) { return receive(handle, data, data_len, 100) == HAL_StatusTypeDef::HAL_OK; } }; template struct SerialInterfaceAsync { using underlying_handle_type = T; underlying_handle_type* handle; SerialInterfaceAsync() = delete; explicit SerialInterfaceAsync(underlying_handle_type* handle) : handle(handle) {} bool Transmit(std::uint8_t* data, const std::uint32_t data_len) { return transmit(handle, data, data_len) == HAL_StatusTypeDef::HAL_OK; } bool Receive(std::uint8_t* data, const std::uint32_t data_len) { return receive(handle, data, data_len) == HAL_StatusTypeDef::HAL_OK; } }; #ifdef HAL_SPI_MODULE_ENABLED using SpiInterface = SerialInterface; struct SpiRegisters { SpiInterface handle; Gpio chip_select; SpiRegisters() = delete; explicit SpiRegisters(const SpiInterface& handle, const Gpio& chip_select) : handle(handle), chip_select(chip_select) {} void WriteRegister(std::uint8_t reg, uint8_t data) { chip_select.Set(false); handle.Transmit(®, 1); handle.Transmit(&data, 1); chip_select.Set(true); } void WriteRegisterMultibyte(std::uint8_t reg, std::uint8_t* data, const std::uint32_t len) { chip_select.Set(false); handle.Transmit(®, 1); handle.Transmit(data, len); chip_select.Set(true); } std::uint8_t ReadRegister(std::uint8_t reg, const std::uint32_t read_delay = 0) { chip_select.Set(false); handle.Transmit(®, 1); std::uint8_t output = 255; if (read_delay) StaticHal::DelayUs(read_delay); handle.Receive(&output, 1); chip_select.Set(true); return output; } void ReadRegisterMultibyte(std::uint8_t reg, std::uint8_t* data, const std::uint32_t len, const std::uint32_t read_delay = 0) { chip_select.Set(false); handle.Transmit(®, 1); if (read_delay) StaticHal::DelayUs(read_delay); handle.Receive(data, len); chip_select.Set(true); } }; #endif// HAL_SPI_MODULE_ENABLED #ifdef HAL_UART_MODULE_ENABLED using UartInterface = SerialInterface; using UartInterfaceDMA = SerialInterfaceAsync; #endif// HAL_UART_MODULE_ENABLED #ifdef HAL_TIM_MODULE_ENABLED struct PwmChannel { TIM_HandleTypeDef* handle; std::uint32_t channel; PwmChannel() = delete; explicit PwmChannel(TIM_HandleTypeDef* handle, const std::uint32_t channel) : handle(handle), channel(channel) {} void Enable() { HAL_TIM_PWM_Start(handle, channel); } void Disable() { HAL_TIM_PWM_Stop(handle, channel); } void SetCompare(const std::uint32_t compare) { __HAL_TIM_SET_COMPARE(handle, channel, compare); } std::uint32_t MaxValue() { return handle->Init.Period; } }; #endif// HAL_TIM_MODULE_ENABLED struct ItmSerialInterface { bool Transmit(std::uint8_t* data, const std::uint32_t data_len) { for (std::uint32_t i = 0; i < data_len; i++) { ITM_SendChar(char(data[i])); } return true; } }; }// namespace St }// namespace Hal }// namespace Peripherals #endif /* PERIPHERALS_INC_PERIPHERALS_HAL_ST_HPP_ */