From 0997bdf28c6cb866ab28d36b03335d401cd0d6be Mon Sep 17 00:00:00 2001 From: John Doe Date: Mon, 26 Jan 2015 02:40:55 +0100 Subject: [PATCH] Implement 16-bit registers which use AtomicGuards to protect 16-bit register access --- include/yalla/avr/iomm.hpp | 6 +- include/yalla/avr/register.hpp | 86 +++++++++++++++++++++++-- include/yalla/device/atmega8/avr/io.hpp | 6 ++ 3 files changed, 90 insertions(+), 8 deletions(-) diff --git a/include/yalla/avr/iomm.hpp b/include/yalla/avr/iomm.hpp index 1672381..90460a5 100644 --- a/include/yalla/avr/iomm.hpp +++ b/include/yalla/avr/iomm.hpp @@ -39,11 +39,11 @@ namespace yalla /** * A static pointer that provides read and write access to the I/O Memory Space. * + * When reading or writing types with size greater than 1 byte interrupts have + * to be disabled to guarantee atomic access. + * * @tparam T type that is used for read and write access * @tparam addr the address this pointer points to (absolute memory address) - * - * TODO for types larger than 1 byte interrupts need to be disabled on each - * write and read access. */ template class IOMMPtr diff --git a/include/yalla/avr/register.hpp b/include/yalla/avr/register.hpp index 00fd5ec..1dc80f2 100644 --- a/include/yalla/avr/register.hpp +++ b/include/yalla/avr/register.hpp @@ -33,6 +33,8 @@ #include #include +#include +#include namespace yalla { @@ -46,20 +48,94 @@ namespace yalla * @tparam addr Address of the register. */ template -struct DataRegister : public IOMMPtr -{}; +class DataRegister : public IOMMPtr +{ +private: + /// Alias for the IOMMPtr + using Ptr = IOMMPtr; + +public: + /** + * Write a 8-bit integer to the register. + * + * @param v value to be written + */ + static INLINE void write(uint8_t v) { Ptr::write(v); } + + /** + * Read a 8-bit integer from the register. + * + * @return value read from register + */ + static INLINE uint8_t read() { return Ptr::read(); } +}; /** * Simple wrapper for a IOMMPtr. Represents a 16-bit io data register. * - * In contrast to a Register a DataRegister is represented only by a 16-bit value + * In contrast to a Register a DataRegister16 is represented only by a 16-bit value * and is not a set of individual bits. * * @tparam addr Address of the register. */ template -struct DataRegister16 : public IOMMPtr -{}; +class DataRegister16 +{ +private: + /// Alias for the IOMMPtr + using Ptr = IOMMPtr; + +public: + /** + * Write a 16-bit integer to the register. + * + * This method always disables interrupts and restores status of the interrupt + * flag after the write operation is performed. If interrupts are always + * disabeled when this method is called, write_unsafe(uint8_t) can be used for + * more efficient write access. + * + * @param v value to be written + */ + static INLINE void write(uint8_t v) + { + auto guard = AtomicGuard(); + Ptr::write(v); + } + + /** + * Read a 16-bit integer from the register. + * + * This method always disables interrupts and restores status of the interrupt + * flag after the read operation is performed. If interrupts are always + * disabeled when this method is called, read_unsafe() can be used for + * more efficient read access. + * + * @return value read from register + */ + static INLINE uint8_t read() + { + auto guard = AtomicGuard(); + return Ptr::read(); + } + + /** + * Directly write a 16-bit integer to the register. + * + * Interrupts must be disabled when this method is called! + * + * @param v value to be written + */ + static INLINE void write_unsafe(uint8_t v) { Ptr::write(v); } + + /** + * Directly read a 16-bit integer from the register. + * + * Interrupts must be disabled when this method is called! + * + * @return value read from register + */ + static INLINE uint8_t read_unsafe() { return Ptr::read(); } +}; /** * Represents a 8-bit io register that is assembled from 8 individual bits. diff --git a/include/yalla/device/atmega8/avr/io.hpp b/include/yalla/device/atmega8/avr/io.hpp index 9f0d39d..f2b9f47 100644 --- a/include/yalla/device/atmega8/avr/io.hpp +++ b/include/yalla/device/atmega8/avr/io.hpp @@ -149,6 +149,12 @@ using PORTC2 = PORTC::Bit2; using PORTC1 = PORTC::Bit1; using PORTC0 = PORTC::Bit0; +// ... TODO + +using ADCH = DataRegister<0x25>; +using ADCL = DataRegister<0x24>; +using ADC = DataRegister16<0x24>; +// ... TODO } // namespace lunacy