1 /*
2 * ArmCpuMemoryAccess.cpp
3 *
4 * Implementaion for access of CPU registers.
5 *
6 * Copyright (C) 2007 - 2011 Texas Instruments Incorporated - http://www.ti.com/
7 *
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the
19 * distribution.
20 *
21 * Neither the name of Texas Instruments Incorporated nor the names of
22 * its contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include <pch.h>
39 #include "ArmCpuMemoryAccess.h"
40 #include "HalExecCommand.h"
41 #include "FetControl.h"
42 #include "WatchdogControl.h"
43 #include "IDeviceHandle.h"
44
45 using namespace TI::DLL430;
46
ArmCpuMemoryAccess(MemoryArea::Name name,IDeviceHandle * devHandle,uint32_t start,uint32_t size,uint32_t seg,uint32_t banks,bool mapped,uint8_t bits)47 ArmCpuMemoryAccess::ArmCpuMemoryAccess (MemoryArea::Name name, IDeviceHandle* devHandle,
48 uint32_t start,
49 uint32_t size,
50 uint32_t seg,
51 uint32_t banks,
52 bool mapped,
53 uint8_t bits)
54 : size(size)
55 , localCache(size, 0)
56 , devHandle(devHandle)
57 {
58 }
59
getSize() const60 size_t ArmCpuMemoryAccess::getSize() const
61 {
62 return size;
63 }
64
65
pushCache()66 void ArmCpuMemoryAccess::pushCache()
67 {
68 this->backupCache = this->localCache;
69 }
popCache()70 void ArmCpuMemoryAccess::popCache()
71 {
72 this->localCache = this->backupCache;
73 flushCache();
74 fillCache(0, 18);
75 }
76
switchContext(uint32_t pc,uint32_t sp)77 bool ArmCpuMemoryAccess::switchContext(uint32_t pc, uint32_t sp)
78 {
79 if (!write(REGISTER_SP, sp))
80 {
81 return false;
82 }
83 if (!write(REGISTER_PC, pc))
84 {
85 return false;
86 }
87 if (!write(REGISTER_XPSR, 0x01000000))
88 {
89 return false;
90 }
91 if (!write(REGISTER_LR, 0xffffffff))
92 {
93 return false;
94 }
95 return true;
96 }
97
disableInterrupts()98 bool ArmCpuMemoryAccess::disableInterrupts()
99 {
100 uint32_t specialRegister = 0x00;
101 if (!read(REGISTER_SPECIAL, &specialRegister, 1))
102 {
103 return false;
104 }
105 if (!write(REGISTER_SPECIAL, specialRegister | (1<<0) | (1<<16)))
106 {
107 return false;
108 }
109 return true;
110 }
111
read(uint32_t Register,uint32_t * buffer,size_t count)112 bool ArmCpuMemoryAccess::read(uint32_t Register, uint32_t* buffer, size_t count)
113 {
114 if (Register + count > localCache.size())
115 {
116 return false;
117 }
118 if (buffer)
119 {
120 for (size_t i = 0; i < count; ++i)
121 {
122 buffer[i] = this->localCache[Register++];
123 }
124 }
125 return true;
126 }
127
write(uint32_t Register,const uint32_t * buffer,size_t count)128 bool ArmCpuMemoryAccess::write(uint32_t Register, const uint32_t* buffer, size_t count)
129 {
130 if (Register + count > localCache.size())
131 {
132 return false;
133 }
134 while (count--)
135 {
136 this->localCache[Register++] = *(buffer++);
137 }
138 return true;
139 }
140
write(uint32_t Register,uint32_t value)141 bool ArmCpuMemoryAccess::write(uint32_t Register, uint32_t value)
142 {
143 if (Register > localCache.size())
144 return false;
145
146 this->localCache[Register] = value;
147 return true;
148 }
149
fillCache(uint32_t Register,size_t count)150 bool ArmCpuMemoryAccess::fillCache(uint32_t Register, size_t count)
151 {
152 if ((Register + count) > localCache.size())
153 {
154 return false;
155 }
156
157 HalExecElement* el = new HalExecElement(this->devHandle->checkHalId(ID_ReadAllCpuRegs));
158
159 HalExecCommand cmd;
160 cmd.elements.emplace_back(el);
161
162 if (!this->devHandle->send(cmd))
163 {
164 return false;
165 }
166
167 for (uint8_t i = 0; i < this->localCache.size(); ++i)
168 {
169 localCache[i] = cmd.elements[0]->getOutputAt32(i * 4);
170 }
171 return true;
172 }
173
flushCache()174 bool ArmCpuMemoryAccess::flushCache()
175 {
176 HalExecCommand cmd;
177 HalExecElement* el = new HalExecElement(this->devHandle->checkHalId(ID_WriteAllCpuRegs));
178
179 for (size_t i = 0; i < this->localCache.size(); i++)
180 {
181 el->appendInputData32(localCache[i]);
182 }
183
184 cmd.elements.emplace_back(el);
185
186 if (!this->devHandle->send(cmd))
187 {
188 return false;
189 }
190 return true;
191 }
192
clearCache(uint32_t Register,size_t count)193 void ArmCpuMemoryAccess::clearCache(uint32_t Register, size_t count)
194 {
195 if (Register + count > localCache.size())
196 {
197 return;
198 }
199
200 std::fill(localCache.begin(), localCache.begin() + count, 0);
201 }
202