libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
sys_tick.h
1#pragma once
2
3#include "libmicroemu/internal/bus/mem_access_results.h"
4#include "libmicroemu/internal/logic/exceptions_ops.h"
5#include "libmicroemu/internal/utils/bit_manip.h"
6#include "libmicroemu/logger.h"
7#include "libmicroemu/register_details.h"
8#include "libmicroemu/types.h"
9
10namespace libmicroemu ::internal {
11
12enum class SysTickAddressMap : me_adr_t {
13 kCsr = 0xE010U,
14 kRvr = 0xE014U,
15 kCvr = 0xE018U,
16 kCalib = 0xE01CU
17};
18
19template <typename TCpuAccessor, typename TExceptionTrigger, typename TLogger = NullLogger>
20class SysTick {
21public:
22 using ExcTrig = TExceptionTrigger;
23 using MapEnum = SysTickAddressMap;
24
25 static constexpr u32 GetBeginPhysicalAddress() { return 0xE010; }
26 static constexpr u32 GetEndPhysicalAddress() { return 0xE0FF; }
27
29 public:
30 static constexpr auto kAdr = SysTickAddressMap::kCsr;
31 static constexpr bool kUseReadModifyWrite = false; // Perform read before write
32 static constexpr bool kReadOnly = false; // Disable write operation
33
34 static u32 ReadRegister(TCpuAccessor &cpua) {
35 auto ret = cpua.template ReadSpecialRegister<SpecialRegisterId::kSysTickCsr>();
36 LOG_TRACE(TLogger, "READ SYST_CSR: 0x%X", ret);
37 // clear the count flag on each read
38 auto csr_wb = ret & (~SysTickRegister::kCsrCountFlagMsk);
39 cpua.template WriteSpecialRegister<SpecialRegisterId::kSysTickCsr>(csr_wb);
40
41 return ret;
42 }
43
44 static void WriteRegister(TCpuAccessor &cpua, u32 value) {
45 auto csr_old = cpua.template ReadSpecialRegister<SpecialRegisterId::kSysTickCsr>();
46 LOG_TRACE(TLogger, "WRITE SYST_CSR: 0x%X", value);
47 if (((csr_old & SysTickRegister::kCsrEnableMsk) == 0U) &&
48 ((value & SysTickRegister::kCsrEnableMsk) != 0U)) {
49
50 auto rvr = cpua.template ReadSpecialRegister<SpecialRegisterId::kSysTickRvr>();
51 cpua.template WriteSpecialRegister<SpecialRegisterId::kSysTickCvr>(rvr);
52 LOG_DEBUG(TLogger, "Enable SysTick");
53 } else if (((csr_old & SysTickRegister::kCsrEnableMsk) != 0U) &&
54 ((value & SysTickRegister::kCsrEnableMsk) == 0U)) {
55 LOG_DEBUG(TLogger, "Disable SysTick");
56 }
57 // each write to the register clears the count flag
58 value = value & (~SysTickRegister::kCsrCountFlagMsk);
59 cpua.template WriteSpecialRegister<SpecialRegisterId::kSysTickCsr>(value);
60 }
61 };
62
64 public:
65 static constexpr auto kAdr = SysTickAddressMap::kRvr;
66 static constexpr bool kUseReadModifyWrite = true; // Perform read before write
67 static constexpr bool kReadOnly = false; // Disable write operation
68
69 static u32 ReadRegister(TCpuAccessor &cpua) {
70 auto ret = cpua.template ReadSpecialRegister<SpecialRegisterId::kSysTickRvr>();
71 LOG_TRACE(TLogger, "READ SYST_RVR: 0x%X", ret);
72 return ret;
73 }
74
75 static void WriteRegister(TCpuAccessor &cpua, u32 value) {
76 LOG_TRACE(TLogger, "WRITE SYST_RVR: 0x%X", value);
77 cpua.template WriteSpecialRegister<SpecialRegisterId::kSysTickRvr>(value);
78 }
79 };
80
82 public:
83 static constexpr auto kAdr = SysTickAddressMap::kCvr;
84 static constexpr bool kUseReadModifyWrite = false; // Perform read before write
85 static constexpr bool kReadOnly = false; // Disable write operation
86
87 static u32 ReadRegister(TCpuAccessor &cpua) {
88 auto ret = cpua.template ReadSpecialRegister<SpecialRegisterId::kSysTickCvr>();
89 LOG_TRACE(TLogger, "READ SYST_CVR: 0x%X", ret);
90 return ret;
91 }
92
93 static void WriteRegister(TCpuAccessor &cpua, u32 value) {
94 value = 0x0; // write to this register clears the count
95 LOG_TRACE(TLogger, "WRITE SYST_CVR: 0x%X", value);
96 cpua.template WriteSpecialRegister<SpecialRegisterId::kSysTickCvr>(value);
97 }
98 };
99
101 public:
102 static constexpr auto kAdr = SysTickAddressMap::kCalib;
103 static constexpr bool kUseReadModifyWrite = false; // Perform read before write
104 static constexpr bool kReadOnly = true; // Disable write operation
105
106 static u32 ReadRegister(TCpuAccessor &cpua) {
107 auto ret = cpua.template ReadSpecialRegister<SpecialRegisterId::kSysTickCalib>();
108 LOG_TRACE(TLogger, "READ SYST_CALIB: 0x%X", ret);
109 return ret;
110 }
111 };
112
113 static constexpr auto kRegisters =
114 // clang-format off
115 std::tuple<
120 >();
121 // clang-format on
122
123 static Result<void> Step(TCpuAccessor &cpua) {
124 auto csr = cpua.template ReadSpecialRegister<SpecialRegisterId::kSysTickCsr>();
125
126 if ((csr & SysTickRegister::kCsrEnableMsk) == SysTickRegister::kCsrEnableMsk) {
127 auto cvr = cpua.template ReadSpecialRegister<SpecialRegisterId::kSysTickCvr>();
128
129 if (cvr <= 1U) {
130 LOG_DEBUG(TLogger, "SysTick counted to zero");
131 auto rvr = cpua.template ReadSpecialRegister<SpecialRegisterId::kSysTickRvr>();
132 cpua.template WriteSpecialRegister<SpecialRegisterId::kSysTickCvr>(rvr);
133
134 if ((csr & SysTickRegister::kCsrTickIntMsk) == SysTickRegister::kCsrTickIntMsk) {
135 ExcTrig::SetPending(cpua, ExceptionType::kSysTick);
136 }
137 // Set the count flag ... indication that the counter has reached 0
138 csr |= SysTickRegister::kCsrCountFlagMsk;
139 cpua.template WriteSpecialRegister<SpecialRegisterId::kSysTickCsr>(csr);
140 } else {
141 cpua.template WriteSpecialRegister<SpecialRegisterId::kSysTickCvr>(cvr - 1U);
142 }
143 }
144
145 return Ok();
146 }
147
148private:
152 constexpr SysTick() = delete;
153
157 virtual ~SysTick() = delete;
158
163 SysTick(const SysTick &r_src) = delete;
164
169 SysTick &operator=(const SysTick &r_src) = delete;
170
175 SysTick(SysTick &&r_src) = delete;
176
181 SysTick &operator=(SysTick &&r_src) = delete;
182};
183
184} // namespace libmicroemu::internal
The libmicroemu namespace contains all classes and functions of the libmicroemu which are public.
Definition bkpt_flags.h:6
Definition result.h:15