blob: 7d3ced2550888f0cda997c633464206cc06df890 [file] [log] [blame]
Sergei Trofimov4e6afe92015-10-09 09:30:04 +01001# Copyright 2015 ARM Limited
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15from __future__ import division
16import os
17import tempfile
18import csv
19import time
20import pexpect
21
22from devlib.platform import Platform
Chris Redpath09915102015-12-12 21:46:59 +000023from devlib.instrument import Instrument, InstrumentChannel, MeasurementsCsv, Measurement, CONTINUOUS, INSTANTANEOUS
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010024from devlib.exception import TargetError, HostError
25from devlib.host import PACKAGE_BIN_DIRECTORY
26from devlib.utils.serial_port import open_serial_connection
27
28
29class VersatileExpressPlatform(Platform):
30
31 def __init__(self, name, # pylint: disable=too-many-locals
32
33 core_names=None,
34 core_clusters=None,
35 big_core=None,
Sergei Trofimova01418b2017-10-11 17:08:24 +010036 model=None,
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010037 modules=None,
38
39 # serial settings
40 serial_port='/dev/ttyS0',
41 baudrate=115200,
42
43 # VExpress MicroSD mount point
44 vemsd_mount=None,
45
46 # supported: dtr, reboottxt
47 hard_reset_method=None,
48 # supported: uefi, uefi-shell, u-boot, bootmon
49 bootloader=None,
50 # supported: vemsd
51 flash_method='vemsd',
52
53 image=None,
54 fdt=None,
55 initrd=None,
56 bootargs=None,
57
58 uefi_entry=None, # only used if bootloader is "uefi"
59 ready_timeout=60,
60 ):
61 super(VersatileExpressPlatform, self).__init__(name,
62 core_names,
63 core_clusters,
64 big_core,
Sergei Trofimova01418b2017-10-11 17:08:24 +010065 model,
Sergei Trofimov4e6afe92015-10-09 09:30:04 +010066 modules)
67 self.serial_port = serial_port
68 self.baudrate = baudrate
69 self.vemsd_mount = vemsd_mount
70 self.image = image
71 self.fdt = fdt
72 self.initrd = initrd
73 self.bootargs = bootargs
74 self.uefi_entry = uefi_entry
75 self.ready_timeout = ready_timeout
76 self.bootloader = None
77 self.hard_reset_method = None
78 self._set_bootloader(bootloader)
79 self._set_hard_reset_method(hard_reset_method)
80 self._set_flash_method(flash_method)
81
82 def init_target_connection(self, target):
83 if target.os == 'android':
84 self._init_android_target(target)
85 else:
86 self._init_linux_target(target)
87
88 def _init_android_target(self, target):
89 if target.connection_settings.get('device') is None:
90 addr = self._get_target_ip_address(target)
91 target.connection_settings['device'] = addr + ':5555'
92
93 def _init_linux_target(self, target):
94 if target.connection_settings.get('host') is None:
95 addr = self._get_target_ip_address(target)
96 target.connection_settings['host'] = addr
97
98 def _get_target_ip_address(self, target):
99 with open_serial_connection(port=self.serial_port,
100 baudrate=self.baudrate,
101 timeout=30,
102 init_dtr=0) as tty:
103 tty.sendline('')
104 self.logger.debug('Waiting for the Android shell prompt.')
105 tty.expect(target.shell_prompt)
106
107 self.logger.debug('Waiting for IP address...')
108 wait_start_time = time.time()
109 while True:
110 tty.sendline('ip addr list eth0')
111 time.sleep(1)
112 try:
113 tty.expect(r'inet ([1-9]\d*.\d+.\d+.\d+)', timeout=10)
114 return tty.match.group(1)
115 except pexpect.TIMEOUT:
116 pass # We have our own timeout -- see below.
117 if (time.time() - wait_start_time) > self.ready_timeout:
118 raise TargetError('Could not acquire IP address.')
119
120 def _set_hard_reset_method(self, hard_reset_method):
121 if hard_reset_method == 'dtr':
122 self.modules.append({'vexpress-dtr': {'port': self.serial_port,
123 'baudrate': self.baudrate,
124 }})
125 elif hard_reset_method == 'reboottxt':
126 self.modules.append({'vexpress-reboottxt': {'port': self.serial_port,
127 'baudrate': self.baudrate,
128 'path': self.vemsd_mount,
129 }})
130 else:
131 ValueError('Invalid hard_reset_method: {}'.format(hard_reset_method))
132
133 def _set_bootloader(self, bootloader):
134 self.bootloader = bootloader
135 if self.bootloader == 'uefi':
136 self.modules.append({'vexpress-uefi': {'port': self.serial_port,
137 'baudrate': self.baudrate,
138 'image': self.image,
139 'fdt': self.fdt,
140 'initrd': self.initrd,
141 'bootargs': self.bootargs,
142 }})
143 elif self.bootloader == 'uefi-shell':
144 self.modules.append({'vexpress-uefi-shell': {'port': self.serial_port,
145 'baudrate': self.baudrate,
146 'image': self.image,
147 'bootargs': self.bootargs,
148 }})
149 elif self.bootloader == 'u-boot':
Sergei Trofimova1e991c2015-12-15 16:17:08 +0000150 uboot_env = None
151 if self.bootargs:
152 uboot_env = {'bootargs': self.bootargs}
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100153 self.modules.append({'vexpress-u-boot': {'port': self.serial_port,
154 'baudrate': self.baudrate,
Sergei Trofimova1e991c2015-12-15 16:17:08 +0000155 'env': uboot_env,
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100156 }})
157 elif self.bootloader == 'bootmon':
158 self.modules.append({'vexpress-bootmon': {'port': self.serial_port,
159 'baudrate': self.baudrate,
160 'image': self.image,
161 'fdt': self.fdt,
162 'initrd': self.initrd,
163 'bootargs': self.bootargs,
164 }})
165 else:
166 ValueError('Invalid hard_reset_method: {}'.format(bootloader))
167
168 def _set_flash_method(self, flash_method):
169 if flash_method == 'vemsd':
170 self.modules.append({'vexpress-vemsd': {'vemsd_mount': self.vemsd_mount}})
171 else:
172 ValueError('Invalid flash_method: {}'.format(flash_method))
173
174
175class Juno(VersatileExpressPlatform):
176
177 def __init__(self,
178 vemsd_mount='/media/JUNO',
179 baudrate=115200,
180 bootloader='u-boot',
181 hard_reset_method='dtr',
182 **kwargs
183 ):
184 super(Juno, self).__init__('juno',
185 vemsd_mount=vemsd_mount,
186 baudrate=baudrate,
187 bootloader=bootloader,
188 hard_reset_method=hard_reset_method,
189 **kwargs)
190
191
192class TC2(VersatileExpressPlatform):
193
194 def __init__(self,
195 vemsd_mount='/media/VEMSD',
196 baudrate=38400,
197 bootloader='bootmon',
198 hard_reset_method='reboottxt',
199 **kwargs
200 ):
201 super(TC2, self).__init__('tc2',
202 vemsd_mount=vemsd_mount,
203 baudrate=baudrate,
204 bootloader=bootloader,
205 hard_reset_method=hard_reset_method,
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100206 **kwargs)
207
208
209class JunoEnergyInstrument(Instrument):
210
211 binname = 'readenergy'
Chris Redpath09915102015-12-12 21:46:59 +0000212 mode = CONTINUOUS | INSTANTANEOUS
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100213
214 _channels = [
Sergei Trofimov9192deb2017-08-31 17:38:33 +0100215 InstrumentChannel('sys', 'current'),
216 InstrumentChannel('a57', 'current'),
217 InstrumentChannel('a53', 'current'),
218 InstrumentChannel('gpu', 'current'),
219 InstrumentChannel('sys', 'voltage'),
220 InstrumentChannel('a57', 'voltage'),
221 InstrumentChannel('a53', 'voltage'),
222 InstrumentChannel('gpu', 'voltage'),
223 InstrumentChannel('sys', 'power'),
224 InstrumentChannel('a57', 'power'),
225 InstrumentChannel('a53', 'power'),
226 InstrumentChannel('gpu', 'power'),
227 InstrumentChannel('sys', 'energy'),
228 InstrumentChannel('a57', 'energy'),
229 InstrumentChannel('a53', 'energy'),
230 InstrumentChannel('gpu', 'energy'),
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100231 ]
232
233 def __init__(self, target):
234 super(JunoEnergyInstrument, self).__init__(target)
235 self.on_target_file = None
236 self.command = None
237 self.binary = self.target.bin(self.binname)
238 for chan in self._channels:
239 self.channels[chan.name] = chan
240 self.on_target_file = self.target.tempfile('energy', '.csv')
Brendan Jackman49b547a2017-04-26 15:07:05 +0100241 self.sample_rate_hz = 10 # DEFAULT_PERIOD is 100[ms] in readenergy.c
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100242 self.command = '{} -o {}'.format(self.binary, self.on_target_file)
Chris Redpath09915102015-12-12 21:46:59 +0000243 self.command2 = '{}'.format(self.binary)
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100244
245 def setup(self):
246 self.binary = self.target.install(os.path.join(PACKAGE_BIN_DIRECTORY,
247 self.target.abi, self.binname))
248
249 def reset(self, sites=None, kinds=None):
250 super(JunoEnergyInstrument, self).reset(sites, kinds)
251 self.target.killall(self.binname, as_root=True)
252
253 def start(self):
254 self.target.kick_off(self.command, as_root=True)
255
256 def stop(self):
257 self.target.killall(self.binname, signal='TERM', as_root=True)
258
259 def get_data(self, output_file):
260 temp_file = tempfile.mktemp()
261 self.target.pull(self.on_target_file, temp_file)
262 self.target.remove(self.on_target_file)
263
264 with open(temp_file, 'rb') as fh:
265 reader = csv.reader(fh)
266 headings = reader.next()
267
268 # Figure out which columns from the collected csv we actually want
269 select_columns = []
270 for chan in self.active_channels:
271 try:
272 select_columns.append(headings.index(chan.name))
273 except ValueError:
274 raise HostError('Channel "{}" is not in {}'.format(chan.name, temp_file))
275
276 with open(output_file, 'wb') as wfh:
277 write_headings = ['{}_{}'.format(c.site, c.kind)
278 for c in self.active_channels]
279 writer = csv.writer(wfh)
280 writer.writerow(write_headings)
281 for row in reader:
282 write_row = [row[c] for c in select_columns]
283 writer.writerow(write_row)
284
285 return MeasurementsCsv(output_file, self.active_channels)
286
Chris Redpath09915102015-12-12 21:46:59 +0000287 def take_measurement(self):
288 result = []
289 output = self.target.execute(self.command2).split()
290 reader=csv.reader(output)
291 headings=reader.next()
292 values = reader.next()
293 for chan in self.active_channels:
294 value = values[headings.index(chan.name)]
295 result.append(Measurement(value, chan))
Chris Redpath09915102015-12-12 21:46:59 +0000296 return result
297