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