16 static_assert(has_kRegisters_v<TPeripheral>,
"TPeripheral must have kRegisters");
17 static_assert(std::is_const_v<
decltype(TPeripheral::kRegisters)>,
18 "kRegisters must be a constant");
20 using MapEnum =
typename TPeripheral::MapEnum;
22 static constexpr u32 GetBeginPhysicalAddress() {
return TPeripheral::GetBeginPhysicalAddress(); }
23 static constexpr u32 GetEndPhysicalAddress() {
return TPeripheral::GetEndPhysicalAddress(); }
25 static constexpr auto kRegisters = TPeripheral::kRegisters;
27 template <
typename T>
static ReadResult<T> ReadRegister(TCpuAccessor &cpua, me_adr_t padr) {
28 return ReadRegisterRecursive<T, decltype(kRegisters)>(padr, cpua);
32 static WriteResult<T> WriteRegister(TCpuAccessor &cpua, me_adr_t padr, T value) {
33 return WriteRegisterRecursive<T, decltype(kRegisters)>(padr, cpua, value);
37 template <
typename T,
typename Registers, std::
size_t Index = 0U>
38 static ReadResult<T> ReadRegisterRecursive(
const u32 &padr, TCpuAccessor &cpua) {
39 if constexpr (Index < std::tuple_size_v<Registers>) {
40 using TypeRegAccess = std::tuple_element_t<Index, Registers>;
42 auto constexpr pstart_adr =
static_cast<me_adr_t
>(TypeRegAccess::kAdr);
43 auto constexpr pend_adr =
static_cast<me_adr_t
>(pstart_adr +
sizeof(u32) - 1U);
44 if (padr >= pstart_adr && padr <= pend_adr) {
46 const auto read_32 = TypeRegAccess::ReadRegister(cpua);
47 const me_adr_t start_byte = padr - pstart_adr;
49 LOG_TRACE(TLogger,
"READ: padr = 0x%X, width = %u, value = 0x%X", padr,
sizeof(T), read_t);
53 return ReadRegisterRecursive<T, Registers, Index + 1U>(padr, cpua);
60 typename TRegAccess,
typename T,
61 typename std::enable_if_t<!TRegAccess::kReadOnly && !TRegAccess::kUseReadModifyWrite, T> = 0>
62 static WriteResult<T> PerformWrite(
const u32 &padr, TCpuAccessor &cpua, T value) {
63 u32 write_value{0x0U};
64 if constexpr (std::is_same_v<T, u32>) {
67 me_adr_t start_byte = padr -
static_cast<me_adr_t
>(TRegAccess::kAdr);
71 LOG_TRACE(TLogger,
"WRITE (No read): padr = 0x%X, width = %u, value = 0x%X", padr,
sizeof(T),
74 TRegAccess::WriteRegister(cpua, write_value);
80 typename TRegAccess,
typename T,
81 typename std::enable_if_t<!TRegAccess::kReadOnly && TRegAccess::kUseReadModifyWrite, T> = 0>
82 static WriteResult<T> PerformWrite(
const u32 &padr, TCpuAccessor &cpua, T value) {
83 u32 write_value{0x0U};
85 if constexpr (std::is_same_v<T, u32>) {
88 me_adr_t start_byte = padr -
static_cast<me_adr_t
>(TRegAccess::kAdr);
91 const auto read_32 = TRegAccess::ReadRegister(cpua);
95 LOG_TRACE(TLogger,
"WRITE: padr = 0x%X, width = %u, value = 0x%X", padr,
sizeof(T),
98 TRegAccess::WriteRegister(cpua, write_value);
104 typename TRegAccess,
typename T,
105 typename std::enable_if_t<TRegAccess::kReadOnly && !TRegAccess::kUseReadModifyWrite, T> = 0>
106 static WriteResult<T> PerformWrite(
const u32 &padr, TCpuAccessor &cpua, T value) {
107 static_cast<void>(padr);
108 static_cast<void>(cpua);
109 static_cast<void>(value);
113 template <
typename T,
typename Registers, std::
size_t Index = 0U>
114 static WriteResult<T> WriteRegisterRecursive(
const u32 &padr, TCpuAccessor &cpua, T value) {
115 if constexpr (Index < std::tuple_size_v<Registers>) {
116 using TypeRegAccess = std::tuple_element_t<Index, Registers>;
118 auto constexpr pstart_adr =
static_cast<me_adr_t
>(TypeRegAccess::kAdr);
119 auto constexpr pend_adr =
static_cast<me_adr_t
>(pstart_adr +
sizeof(u32) - 1U);
121 if (padr >= pstart_adr && padr <= pend_adr) {
122 return PerformWrite<TypeRegAccess, T>(padr, cpua, value);
124 return WriteRegisterRecursive<T, Registers, Index + 1U>(padr, cpua, value);
135 using ExcTrig = TExceptionTrigger;
171 static constexpr bool kReadOnly =
false;
177 template <
typename T,
typename First,
typename... Rest>
178 static ReadResult<T> ReadRegisters(TCpuAccessor &cpua,
const u32 &padr) {
181 if (padr >= Type::GetBeginPhysicalAddress() && padr <= Type::GetEndPhysicalAddress()) {
182 const auto read_32 = Type::template ReadRegister<T>(cpua, padr);
185 return ReadRegisters<T, Rest...>(cpua, padr);
189 template <
typename T>
static ReadResult<T> ReadRegisters(TCpuAccessor &cpua,
const u32 &padr) {
190 static_cast<void>(cpua);
191 static_cast<void>(padr);
198 template <
typename T,
typename First,
typename... Rest>
199 static WriteResult<T> WriteRegisters(TCpuAccessor &cpua,
const u32 &padr,
const T &value) {
200 using Type = MemMapAccessPoint<TCpuAccessor, First, TLogger>;
202 if (padr >= Type::GetBeginPhysicalAddress() && padr <= Type::GetEndPhysicalAddress()) {
203 const auto write_32 = Type::template WriteRegister<T>(cpua, padr, value);
206 return WriteRegisters<T, Rest...>(cpua, padr, value);
210 template <
typename T>
211 static WriteResult<T> WriteRegisters(TCpuAccessor &cpua,
const u32 &padr,
const T &value) {
212 static_cast<void>(cpua);
213 static_cast<void>(padr);
214 static_cast<void>(value);
215 return WriteResult<T>{WriteStatusCode::kWriteNotAllowed};
221 template <
typename T> ReadResult<T> Read(TCpuAccessor &cpua, me_adr_t vadr)
const {
224 std::is_same<T, u32>::value ||
225 std::is_same<T, u16>::value ||
226 std::is_same<T, u8>::value,
227 "Read only allows u32, u16 and u8");
230 const me_adr_t padr = ConvertToPhysicalAdr(vadr);
231 assert(IsPAdrInRange(padr) ==
true);
232 auto read_res = ReadRegisters<T, TPeripherals...>(cpua, padr);
233 return ReadResult<T>{
static_cast<T
>(read_res.content), read_res.status_code};
236 template <
typename T>
237 WriteResult<T> Write(TCpuAccessor &cpua, me_adr_t vadr,
const T &value)
const {
240 std::is_same<T, u32>::value ||
241 std::is_same<T, u16>::value ||
242 std::is_same<T, u8>::value,
243 "Write only allows u32, u16 and u8 types");
246 const me_adr_t padr = ConvertToPhysicalAdr(vadr);
247 assert(IsPAdrInRange(padr) ==
true);
249 auto write_res = WriteRegisters<T, TPeripherals...>(cpua, padr, value);
251 return WriteResult<T>{write_res.status_code};
254 bool IsVAdrInRange(me_adr_t vadr)
const {
255 const me_adr_t padr = ConvertToPhysicalAdr(vadr);
256 if (IsPAdrInRange(padr) ==
false) {
263 me_adr_t ConvertToPhysicalAdr(me_adr_t vadr)
const {
return vadr - VadrOffset; }
264 bool IsPAdrInRange(me_adr_t padr)
const {
return padr < VadrRange; }