mirror of
https://github.com/google/pebble.git
synced 2025-05-20 10:24:58 +00:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
210
waftools/openocd.py
Normal file
210
waftools/openocd.py
Normal file
|
@ -0,0 +1,210 @@
|
|||
# Copyright 2024 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import contextlib
|
||||
import pexpect
|
||||
import re
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
import waflib
|
||||
|
||||
from waflib import Logs
|
||||
|
||||
|
||||
JTAG_OPTIONS = {'olimex': 'source [find interface/ftdi/olimex-arm-usb-ocd-h.cfg]',
|
||||
'fixture': 'source [find interface/flossjtag-noeeprom.cfg]',
|
||||
'bb2': 'source waftools/openocd_bb2_ftdi.cfg',
|
||||
'bb2-legacy': 'source waftools/openocd_bb2_ft2232.cfg',
|
||||
'jtag_ftdi': 'source waftools/openocd_jtag_ftdi.cfg',
|
||||
'swd_ftdi': 'source waftools/openocd_swd_ftdi.cfg',
|
||||
'swd_jlink': 'source waftools/openocd_swd_jlink.cfg',
|
||||
'swd_stlink': 'source [find interface/stlink-v2.cfg]',
|
||||
}
|
||||
|
||||
OPENOCD_TELNET_PORT = 4444
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def daemon(ctx, cfg_file, use_swd=False):
|
||||
if _is_openocd_running():
|
||||
yield
|
||||
else:
|
||||
if use_swd:
|
||||
expect_str = "SWD IDCODE"
|
||||
else:
|
||||
expect_str = "device found"
|
||||
|
||||
proc = pexpect.spawn('openocd', ['-f', cfg_file], logfile=sys.stdout)
|
||||
# Wait for OpenOCD to connect to the board:
|
||||
result = proc.expect([expect_str, pexpect.TIMEOUT], timeout=10)
|
||||
if result == 0:
|
||||
yield
|
||||
else:
|
||||
raise Exception("Timed out connecting OpenOCD to development board...")
|
||||
proc.close()
|
||||
|
||||
|
||||
def _has_openocd(ctx):
|
||||
try:
|
||||
ctx.cmd_and_log(['which', 'openocd'], quiet=waflib.Context.BOTH)
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
def _is_openocd_running():
|
||||
import socket
|
||||
import errno
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
s.bind(('', OPENOCD_TELNET_PORT))
|
||||
s.close()
|
||||
except socket.error as e:
|
||||
s.close()
|
||||
return e[0] == errno.EADDRINUSE
|
||||
return False
|
||||
|
||||
|
||||
def run_command(ctx, cmd, ignore_fail=False, expect=[], timeout=40,
|
||||
shutdown=True, enforce_expect=False, cfg_file="openocd.cfg"):
|
||||
if _is_openocd_running():
|
||||
import telnetlib
|
||||
t = telnetlib.Telnet('', OPENOCD_TELNET_PORT)
|
||||
Logs.info("Sending commands to OpenOCD daemon:\n%s\n..." % cmd)
|
||||
t.write("%s\n" % cmd)
|
||||
for regex in expect:
|
||||
idx, match, text = t.expect([regex], timeout)
|
||||
if enforce_expect and idx == -1:
|
||||
# They'll see the full story in another window
|
||||
ctx.fatal("OpenOCD expectation '%s' unfulfilled" % regex)
|
||||
t.close()
|
||||
else:
|
||||
fail_handling = ' || true ' if ignore_fail else ''
|
||||
if shutdown:
|
||||
# append 'shutdown' to make openocd exit:
|
||||
cmd = "%s ; shutdown" % cmd
|
||||
ctx.exec_command('openocd -f %s -c "%s" 2>&1 | tee .waf.openocd.log %s' %
|
||||
(cfg_file, cmd, fail_handling), stdout=None, stderr=None)
|
||||
if enforce_expect:
|
||||
# Read the result
|
||||
with open(".waf.openocd.log", "r") as result_file:
|
||||
result = result_file.read()
|
||||
match_start = 0
|
||||
for regex in expect:
|
||||
expect_match = re.search(regex, result[match_start:])
|
||||
if not expect_match:
|
||||
ctx.fatal("OpenOCD expectation '%s' unfulfilled" % regex)
|
||||
match_start = expect_match.end()
|
||||
|
||||
|
||||
|
||||
def _get_supported_interfaces(ctx):
|
||||
if not _has_openocd(ctx):
|
||||
return []
|
||||
# Ugh, openocd exits with status 1 when not specifying an interface...
|
||||
try:
|
||||
ctx.cmd_and_log(['openocd', '-c', '"interface_list"'],
|
||||
quiet=waflib.Context.BOTH,
|
||||
output=waflib.Context.STDERR)
|
||||
except Exception as e:
|
||||
# Ugh, openocd prints the output to stderr...
|
||||
out = e.stderr
|
||||
out_lines = out.splitlines()
|
||||
interfaces = []
|
||||
for line in out_lines:
|
||||
matches = re.search("\d+: (\w+)", line)
|
||||
if matches:
|
||||
interfaces.append(matches.groups()[0])
|
||||
return interfaces
|
||||
|
||||
|
||||
def get_flavor(conf):
|
||||
""" Returns a 2-tuple (is_newer_than_0_7_0, is_pebble_flavor) """
|
||||
|
||||
try:
|
||||
version_string = conf.cmd_and_log(['openocd', '--version'],
|
||||
quiet=waflib.Context.BOTH,
|
||||
output=waflib.Context.STDERR)
|
||||
version_string = version_string.splitlines()[0]
|
||||
matches = re.search("(\d+)\.(\d+)\.(\d+)", version_string)
|
||||
version = map(int, matches.groups())
|
||||
return (version[0] >= 0 and version[1] >= 7,
|
||||
'pebble' in version_string)
|
||||
except Exception:
|
||||
Logs.error("Couldn't parse openocd version")
|
||||
return (False, False)
|
||||
|
||||
|
||||
def _get_reset_conf(conf, is_newer_than_0_7_0, should_connect_assert_srst):
|
||||
if is_newer_than_0_7_0:
|
||||
options = ['trst_and_srst', 'srst_nogate']
|
||||
if should_connect_assert_srst:
|
||||
options.append('connect_assert_srst')
|
||||
return ' '.join(options)
|
||||
else:
|
||||
return 'trst_and_srst'
|
||||
|
||||
|
||||
def write_cfg(conf):
|
||||
jtag = conf.env.JTAG
|
||||
if jtag == 'bb2':
|
||||
if 'ftdi' not in _get_supported_interfaces(conf):
|
||||
jtag = 'bb2-legacy'
|
||||
Logs.warn('OpenOCD is not compiled with --enable-ftdi, falling'
|
||||
' back to legacy ft2232 driver.')
|
||||
|
||||
if conf.env.MICRO_FAMILY == 'STM32F2':
|
||||
target = 'stm32f2x.cfg'
|
||||
elif conf.env.MICRO_FAMILY == 'STM32F4':
|
||||
target = 'stm32f4x.cfg'
|
||||
elif conf.env.MICRO_FAMILY == 'STM32F7':
|
||||
target = 'stm32f7x.cfg'
|
||||
|
||||
(is_newer_than_0_7_0, is_pebble_flavor) = get_flavor(conf)
|
||||
|
||||
reset_config = _get_reset_conf(conf, is_newer_than_0_7_0, False)
|
||||
Logs.info("reset_config: %s" % reset_config)
|
||||
|
||||
if is_pebble_flavor:
|
||||
Logs.info("openocd is Pebble flavored!")
|
||||
os_name = 'Pebble_FreeRTOS'
|
||||
else:
|
||||
os_name = 'FreeRTOS'
|
||||
|
||||
openocd_cfg = OPENOCD_CFG_TEMPLATE.substitute(jtag=JTAG_OPTIONS[jtag],
|
||||
target=target,
|
||||
reset_config=reset_config,
|
||||
os_name=os_name)
|
||||
waflib.Utils.writef('./openocd.cfg', openocd_cfg)
|
||||
|
||||
|
||||
OPENOCD_CFG_TEMPLATE = string.Template("""
|
||||
# THIS IS A GENERATED FILE: See waftools/openocd.py for details
|
||||
|
||||
${jtag}
|
||||
source [find target/${target}]
|
||||
|
||||
reset_config ${reset_config}
|
||||
|
||||
$$_TARGETNAME configure -rtos ${os_name}
|
||||
$$_TARGETNAME configure -event gdb-attach {
|
||||
echo "Halting target because GDB is attaching..."
|
||||
halt
|
||||
}
|
||||
$$_TARGETNAME configure -event gdb-detach {
|
||||
echo "Resuming target because GDB is detaching..."
|
||||
resume
|
||||
}
|
||||
""")
|
Loading…
Add table
Add a link
Reference in a new issue