1
0
mirror of https://github.com/sendyne/cppreg.git synced 2025-05-09 23:24:05 +00:00
cppreg/register/Memory.h
Nicolas Clauvelin c1081a114e Code maintenance
* Revise and simplify most enable_if statements in the project.
* Update code style in all files.
* Update copyright year.
* Add a dedicated Memory.h header with the memory device implementation.
* Update documentation.
* CMake cleanup.
2019-04-24 17:00:57 -04:00

107 lines
2.9 KiB
C++

//! Memory device implementation.
/**
* @file Memory.h
* @author Nicolas Clauvelin (nclauvelin@sendyne.com)
* @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved.
*/
#ifndef CPPREG_DEV_MEMORY_H
#define CPPREG_DEV_MEMORY_H
#include "Traits.h"
#include <array>
namespace cppreg {
//! Register pack base implementation.
/**
* @tparam base_address Pack base address.
* @tparam pack_byte_size Pack size in bytes.
*/
template <Address base_address, std::uint32_t pack_byte_size>
struct RegisterPack {
//! Base address.
constexpr static const Address pack_base = base_address;
//! Pack size in bytes.
constexpr static const std::uint32_t size_in_bytes = pack_byte_size;
};
//! Memory device.
/**
* @tparam mem_address Address of the memory device.
* @tparam mem_byte_size Memory device size in bytes.
*/
template <Address mem_address, std::size_t mem_byte_size>
struct MemoryDevice {
//! Storage type.
using memory_storage = std::array<volatile std::uint8_t, mem_byte_size>;
//! Memory device storage.
static memory_storage& _mem_storage;
//! Accessor.
template <RegBitSize reg_size, std::size_t byte_offset>
static const volatile typename TypeTraits<reg_size>::type& ro_memory() {
// Check alignment.
static_assert(
internals::is_aligned<mem_address + byte_offset,
std::alignment_of<typename TypeTraits<
reg_size>::type>::value>::value,
"MemoryDevice:: ro request not aligned");
return *(reinterpret_cast<const volatile
typename TypeTraits<reg_size>::type*>(
&_mem_storage[byte_offset]));
}
//! Modifier.
template <RegBitSize reg_size, std::size_t byte_offset>
static volatile typename TypeTraits<reg_size>::type& rw_memory() {
// Check alignment.
static_assert(
internals::is_aligned<mem_address + byte_offset,
std::alignment_of<typename TypeTraits<
reg_size>::type>::value>::value,
"MemoryDevice:: rw request not aligned");
return *(
reinterpret_cast<volatile typename TypeTraits<reg_size>::type*>(
&_mem_storage[byte_offset]));
}
};
//! Static reference definition.
template <Address a, std::size_t s>
typename MemoryDevice<a, s>::memory_storage& MemoryDevice<a, s>::_mem_storage =
*(reinterpret_cast<typename MemoryDevice<a, s>::memory_storage*>(a));
//! Register memory device for register pack.
/**
*
* @tparam pack_address Register pack address.
* @tparam n_bytes Register pack size in bytes.
*/
template <typename RegisterPack>
struct RegisterMemoryDevice {
using mem_device =
MemoryDevice<RegisterPack::pack_base, RegisterPack::size_in_bytes>;
};
} // namespace cppreg
#endif // CPPREG_DEV_MEMORY_H