blob: e760eaf43614c4c2c8a689dae08af94b9f3da774 [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,
36 modules=None,
37
38 # serial settings
39 serial_port='/dev/ttyS0',
40 baudrate=115200,
41
42 # VExpress MicroSD mount point
43 vemsd_mount=None,
44
45 # supported: dtr, reboottxt
46 hard_reset_method=None,
47 # supported: uefi, uefi-shell, u-boot, bootmon
48 bootloader=None,
49 # supported: vemsd
50 flash_method='vemsd',
51
52 image=None,
53 fdt=None,
54 initrd=None,
55 bootargs=None,
56
57 uefi_entry=None, # only used if bootloader is "uefi"
58 ready_timeout=60,
59 ):
60 super(VersatileExpressPlatform, self).__init__(name,
61 core_names,
62 core_clusters,
63 big_core,
64 modules)
65 self.serial_port = serial_port
66 self.baudrate = baudrate
67 self.vemsd_mount = vemsd_mount
68 self.image = image
69 self.fdt = fdt
70 self.initrd = initrd
71 self.bootargs = bootargs
72 self.uefi_entry = uefi_entry
73 self.ready_timeout = ready_timeout
74 self.bootloader = None
75 self.hard_reset_method = None
76 self._set_bootloader(bootloader)
77 self._set_hard_reset_method(hard_reset_method)
78 self._set_flash_method(flash_method)
79
80 def init_target_connection(self, target):
81 if target.os == 'android':
82 self._init_android_target(target)
83 else:
84 self._init_linux_target(target)
85
86 def _init_android_target(self, target):
87 if target.connection_settings.get('device') is None:
88 addr = self._get_target_ip_address(target)
89 target.connection_settings['device'] = addr + ':5555'
90
91 def _init_linux_target(self, target):
92 if target.connection_settings.get('host') is None:
93 addr = self._get_target_ip_address(target)
94 target.connection_settings['host'] = addr
95
96 def _get_target_ip_address(self, target):
97 with open_serial_connection(port=self.serial_port,
98 baudrate=self.baudrate,
99 timeout=30,
100 init_dtr=0) as tty:
101 tty.sendline('')
102 self.logger.debug('Waiting for the Android shell prompt.')
103 tty.expect(target.shell_prompt)
104
105 self.logger.debug('Waiting for IP address...')
106 wait_start_time = time.time()
107 while True:
108 tty.sendline('ip addr list eth0')
109 time.sleep(1)
110 try:
111 tty.expect(r'inet ([1-9]\d*.\d+.\d+.\d+)', timeout=10)
112 return tty.match.group(1)
113 except pexpect.TIMEOUT:
114 pass # We have our own timeout -- see below.
115 if (time.time() - wait_start_time) > self.ready_timeout:
116 raise TargetError('Could not acquire IP address.')
117
118 def _set_hard_reset_method(self, hard_reset_method):
119 if hard_reset_method == 'dtr':
120 self.modules.append({'vexpress-dtr': {'port': self.serial_port,
121 'baudrate': self.baudrate,
122 }})
123 elif hard_reset_method == 'reboottxt':
124 self.modules.append({'vexpress-reboottxt': {'port': self.serial_port,
125 'baudrate': self.baudrate,
126 'path': self.vemsd_mount,
127 }})
128 else:
129 ValueError('Invalid hard_reset_method: {}'.format(hard_reset_method))
130
131 def _set_bootloader(self, bootloader):
132 self.bootloader = bootloader
133 if self.bootloader == 'uefi':
134 self.modules.append({'vexpress-uefi': {'port': self.serial_port,
135 'baudrate': self.baudrate,
136 'image': self.image,
137 'fdt': self.fdt,
138 'initrd': self.initrd,
139 'bootargs': self.bootargs,
140 }})
141 elif self.bootloader == 'uefi-shell':
142 self.modules.append({'vexpress-uefi-shell': {'port': self.serial_port,
143 'baudrate': self.baudrate,
144 'image': self.image,
145 'bootargs': self.bootargs,
146 }})
147 elif self.bootloader == 'u-boot':
Sergei Trofimova1e991c2015-12-15 16:17:08 +0000148 uboot_env = None
149 if self.bootargs:
150 uboot_env = {'bootargs': self.bootargs}
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100151 self.modules.append({'vexpress-u-boot': {'port': self.serial_port,
152 'baudrate': self.baudrate,
Sergei Trofimova1e991c2015-12-15 16:17:08 +0000153 'env': uboot_env,
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100154 }})
155 elif self.bootloader == 'bootmon':
156 self.modules.append({'vexpress-bootmon': {'port': self.serial_port,
157 'baudrate': self.baudrate,
158 'image': self.image,
159 'fdt': self.fdt,
160 'initrd': self.initrd,
161 'bootargs': self.bootargs,
162 }})
163 else:
164 ValueError('Invalid hard_reset_method: {}'.format(bootloader))
165
166 def _set_flash_method(self, flash_method):
167 if flash_method == 'vemsd':
168 self.modules.append({'vexpress-vemsd': {'vemsd_mount': self.vemsd_mount}})
169 else:
170 ValueError('Invalid flash_method: {}'.format(flash_method))
171
172
173class Juno(VersatileExpressPlatform):
174
175 def __init__(self,
176 vemsd_mount='/media/JUNO',
177 baudrate=115200,
178 bootloader='u-boot',
179 hard_reset_method='dtr',
180 **kwargs
181 ):
182 super(Juno, self).__init__('juno',
183 vemsd_mount=vemsd_mount,
184 baudrate=baudrate,
185 bootloader=bootloader,
186 hard_reset_method=hard_reset_method,
187 **kwargs)
188
189
190class TC2(VersatileExpressPlatform):
191
192 def __init__(self,
193 vemsd_mount='/media/VEMSD',
194 baudrate=38400,
195 bootloader='bootmon',
196 hard_reset_method='reboottxt',
197 **kwargs
198 ):
199 super(TC2, self).__init__('tc2',
200 vemsd_mount=vemsd_mount,
201 baudrate=baudrate,
202 bootloader=bootloader,
203 hard_reset_method=hard_reset_method,
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100204 **kwargs)
205
206
207class JunoEnergyInstrument(Instrument):
208
209 binname = 'readenergy'
Chris Redpath09915102015-12-12 21:46:59 +0000210 mode = CONTINUOUS | INSTANTANEOUS
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100211
212 _channels = [
213 InstrumentChannel('sys_curr', 'sys', 'current'),
214 InstrumentChannel('a57_curr', 'a57', 'current'),
215 InstrumentChannel('a53_curr', 'a53', 'current'),
216 InstrumentChannel('gpu_curr', 'gpu', 'current'),
217 InstrumentChannel('sys_volt', 'sys', 'voltage'),
218 InstrumentChannel('a57_volt', 'a57', 'voltage'),
219 InstrumentChannel('a53_volt', 'a53', 'voltage'),
220 InstrumentChannel('gpu_volt', 'gpu', 'voltage'),
221 InstrumentChannel('sys_pow', 'sys', 'power'),
222 InstrumentChannel('a57_pow', 'a57', 'power'),
223 InstrumentChannel('a53_pow', 'a53', 'power'),
224 InstrumentChannel('gpu_pow', 'gpu', 'power'),
225 InstrumentChannel('sys_cenr', 'sys', 'energy'),
226 InstrumentChannel('a57_cenr', 'a57', 'energy'),
227 InstrumentChannel('a53_cenr', 'a53', 'energy'),
228 InstrumentChannel('gpu_cenr', 'gpu', 'energy'),
229 ]
230
231 def __init__(self, target):
232 super(JunoEnergyInstrument, self).__init__(target)
233 self.on_target_file = None
234 self.command = None
235 self.binary = self.target.bin(self.binname)
236 for chan in self._channels:
237 self.channels[chan.name] = chan
238 self.on_target_file = self.target.tempfile('energy', '.csv')
Brendan Jackman49b547a2017-04-26 15:07:05 +0100239 self.sample_rate_hz = 10 # DEFAULT_PERIOD is 100[ms] in readenergy.c
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100240 self.command = '{} -o {}'.format(self.binary, self.on_target_file)
Chris Redpath09915102015-12-12 21:46:59 +0000241 self.command2 = '{}'.format(self.binary)
Sergei Trofimov4e6afe92015-10-09 09:30:04 +0100242
243 def setup(self):
244 self.binary = self.target.install(os.path.join(PACKAGE_BIN_DIRECTORY,
245 self.target.abi, self.binname))
246
247 def reset(self, sites=None, kinds=None):
248 super(JunoEnergyInstrument, self).reset(sites, kinds)
249 self.target.killall(self.binname, as_root=True)
250
251 def start(self):
252 self.target.kick_off(self.command, as_root=True)
253
254 def stop(self):
255 self.target.killall(self.binname, signal='TERM', as_root=True)
256
257 def get_data(self, output_file):
258 temp_file = tempfile.mktemp()
259 self.target.pull(self.on_target_file, temp_file)
260 self.target.remove(self.on_target_file)
261
262 with open(temp_file, 'rb') as fh:
263 reader = csv.reader(fh)
264 headings = reader.next()
265
266 # Figure out which columns from the collected csv we actually want
267 select_columns = []
268 for chan in self.active_channels:
269 try:
270 select_columns.append(headings.index(chan.name))
271 except ValueError:
272 raise HostError('Channel "{}" is not in {}'.format(chan.name, temp_file))
273
274 with open(output_file, 'wb') as wfh:
275 write_headings = ['{}_{}'.format(c.site, c.kind)
276 for c in self.active_channels]
277 writer = csv.writer(wfh)
278 writer.writerow(write_headings)
279 for row in reader:
280 write_row = [row[c] for c in select_columns]
281 writer.writerow(write_row)
282
283 return MeasurementsCsv(output_file, self.active_channels)
284
Chris Redpath09915102015-12-12 21:46:59 +0000285 def take_measurement(self):
286 result = []
287 output = self.target.execute(self.command2).split()
288 reader=csv.reader(output)
289 headings=reader.next()
290 values = reader.next()
291 for chan in self.active_channels:
292 value = values[headings.index(chan.name)]
293 result.append(Measurement(value, chan))
Chris Redpath09915102015-12-12 21:46:59 +0000294 return result
295