diff --git a/hardware0.hpp b/hardware0.hpp index 009241d..f8e7cf7 100644 --- a/hardware0.hpp +++ b/hardware0.hpp @@ -1,5 +1,4 @@ -#ifndef UART_HARDWARE_0_HPP -#define UART_HARDWARE_0_HPP +#pragma once #include @@ -82,8 +81,10 @@ constexpr int operator<<(const int &lhs, const ControlFlagsB0 &rhs) { return lhs constexpr int operator<<(const int &lhs, const ControlFlagsC0 &rhs) { return lhs << static_cast(rhs); } // clang-format on -extern void (*fnRx0IntHandler)(); -extern void (*fnDataReg0EmptyIntHandler)(); +#if defined(__AVR_ATmega328P__) +#define USART0_RX_vect USART_RX_vect +#define USART0_UDRE_vect USART_UDRE_vect +#endif #else #error "This chip is not supported" @@ -100,70 +101,56 @@ template class Hardware0 : public detail::InterruptHardware { - using detail::InterruptHardware::rxIntHandler; - - using detail::InterruptHardware::dataRegEmptyIntHandler; - - using HardwareImpl = detail::Hardware; - public: static void init() FORCE_INLINE { - detail::fnRx0IntHandler = rxIntHandler; - detail::fnDataReg0EmptyIntHandler = dataRegEmptyIntHandler; - HardwareImpl::init(); sei(); } + + private: + using HardwareImpl = detail::Hardware; + + using InterruptHardwareImpl = detail::InterruptHardware; + + // Must be friends with Uart interface to call these private handlers + template + friend class Uart; + + static void rxIntHandler() FORCE_INLINE + { + InterruptHardwareImpl::rxIntHandler(); + } + + static void dataRegEmptyIntHandler() FORCE_INLINE + { + InterruptHardwareImpl::dataRegEmptyIntHandler(); + } }; } // namespace uart -#undef FORCE_INLINE - -#endif - ////////////////////////////////////////////////////////////////////////// -#ifdef UART0_INT_VECTORS - -#include - -namespace uart { -namespace detail { - -#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega328P__) - -#if defined(__AVR_ATmega328P__) -#define USART0_RX_vect USART_RX_vect -#define USART0_UDRE_vect USART_UDRE_vect -#endif - -void (*fnRx0IntHandler)() = nullptr; -void (*fnDataReg0EmptyIntHandler)() = nullptr; - -ISR(USART0_RX_vect) -{ - if (fnRx0IntHandler) - fnRx0IntHandler(); +// Forward declare interrupt functions to allow adding them as friends +extern "C" { +void USART0_RX_vect() __attribute__((signal)); +void USART0_UDRE_vect() __attribute__((signal)); } -ISR(USART0_UDRE_vect) -{ - if (fnDataReg0EmptyIntHandler) - fnDataReg0EmptyIntHandler(); -} +// clang-format off +#define REGISTER_UART0_INT_VECTORS(uart_type) \ + ISR(USART0_RX_vect) \ + { \ + uart_type::rxIntHandler(); \ + } \ + ISR(USART0_UDRE_vect) \ + { \ + uart_type::dataRegEmptyIntHandler(); \ + } \ + struct _##uart_type {} +// clang-format on -#else -#error "This chip is not supported" -#endif - -} // namespace detail -} // namespace uart - -#undef UART0_INT_VECTORS - -#endif +#undef FORCE_INLINE diff --git a/hardware1.hpp b/hardware1.hpp index 97b2b3a..22e4c15 100644 --- a/hardware1.hpp +++ b/hardware1.hpp @@ -1,5 +1,4 @@ -#ifndef UART_HARDWARE_1_HPP -#define UART_HARDWARE_1_HPP +#pragma once #include @@ -82,9 +81,6 @@ constexpr int operator<<(const int &lhs, const ControlFlagsB1 &rhs) { return lhs constexpr int operator<<(const int &lhs, const ControlFlagsC1 &rhs) { return lhs << static_cast(rhs); } // clang-format on -extern void (*fnRx1IntHandler)(); -extern void (*fnDataReg1EmptyIntHandler)(); - #define HAS_UART1 #endif @@ -102,65 +98,59 @@ template class Hardware1 : public detail::InterruptHardware { - using detail::InterruptHardware::rxIntHandler; - - using detail::InterruptHardware::dataRegEmptyIntHandler; - - using HardwareImpl = detail::Hardware; - public: static void init() FORCE_INLINE { - detail::fnRx1IntHandler = rxIntHandler; - detail::fnDataReg1EmptyIntHandler = dataRegEmptyIntHandler; - HardwareImpl::init(); sei(); } + + private: + using HardwareImpl = detail::Hardware; + + using InterruptHardwareImpl = detail::InterruptHardware; + + // Must be friends with Uart interface to call these private handlers + template + friend class Uart; + + static void rxIntHandler() FORCE_INLINE + { + InterruptHardwareImpl::rxIntHandler(); + } + + static void dataRegEmptyIntHandler() FORCE_INLINE + { + InterruptHardwareImpl::dataRegEmptyIntHandler(); + } }; -#endif - } // namespace uart -#undef FORCE_INLINE - -#endif - ////////////////////////////////////////////////////////////////////////// -#ifdef UART1_INT_VECTORS - -#include - -namespace uart { -namespace detail { - -#if defined(__AVR_ATmega1284P__) - -void (*fnRx1IntHandler)() = nullptr; -void (*fnDataReg1EmptyIntHandler)() = nullptr; - -ISR(USART1_RX_vect) -{ - if (fnRx1IntHandler) - fnRx1IntHandler(); +// Forward declare interrupt functions to allow adding them as friends +extern "C" { +void USART1_RX_vect() __attribute__((signal)); +void USART1_UDRE_vect() __attribute__((signal)); } -ISR(USART1_UDRE_vect) -{ - if (fnDataReg1EmptyIntHandler) - fnDataReg1EmptyIntHandler(); -} +// clang-format off +#define REGISTER_UART1_INT_VECTORS(uart_type) \ + ISR(USART1_RX_vect) \ + { \ + uart_type::rxIntHandler(); \ + } \ + ISR(USART1_UDRE_vect) \ + { \ + uart_type::dataRegEmptyIntHandler(); \ + } \ + struct _##uart_type { \ + } +// clang-format off #endif -} // namespace detail -} // namespace uart - -#undef UART1_INT_VECTORS - -#endif +#undef FORCE_INLINE diff --git a/uart.hpp b/uart.hpp index f840d90..a35dcb6 100644 --- a/uart.hpp +++ b/uart.hpp @@ -5,9 +5,7 @@ #include "config.hpp" #include "software.hpp" -#undef UART0_INT_VECTORS #include "hardware0.hpp" -#undef UART1_INT_VECTORS #include "hardware1.hpp" #include "../flash/flash.hpp" @@ -356,6 +354,25 @@ class Uart { { static_assert(type::always_false_v, "Not implemented"); } + + private: + friend void ::USART0_RX_vect(); + friend void ::USART0_UDRE_vect(); + +#ifdef HAS_UART1 + friend void ::USART1_RX_vect(); + friend void ::USART1_UDRE_vect(); +#endif + + static void rxIntHandler() FORCE_INLINE + { + Driver::rxIntHandler(); + } + + static void dataRegEmptyIntHandler() FORCE_INLINE + { + Driver::dataRegEmptyIntHandler(); + } }; template >