mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
ce0d589384
tools/jlink.sh: fix version check and allow to skip it
337 lines
9.4 KiB
Bash
Executable File
337 lines
9.4 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# Unified Segger J-Link script for RIOT
|
|
#
|
|
# This script is supposed to be called from RIOTs build system,
|
|
# as it depends on certain environment variables.
|
|
#
|
|
# The minimum supported version of J-Link is V6.74.
|
|
#
|
|
# Global environment variables used:
|
|
# JLINK: J-Link Commander command name, default: "JLinkExe"
|
|
# JLINK_SERVER: J-Link GDB Server command name, default: "JLinkGDBServer"
|
|
# JLINK_DEVICE: Device identifier used by J-Link
|
|
# JLINK_SERIAL: Device serial used by J-Link
|
|
# JLINK_IF: Interface used by J-Link, default: "SWD"
|
|
# JLINK_SPEED: Interface clock speed to use (in kHz), default "2000"
|
|
# FLASH_ADDR: Starting address of the target's flash memory, default: "0"
|
|
# IMAGE_OFFSET: Offset from the targets flash memory, for flashing the
|
|
# image
|
|
# JLINK_PRE_FLASH: Additional J-Link commands to execute before flashing
|
|
# JLINK_POST_FLASH: Additional J-Link commands to execute after flashing
|
|
#
|
|
# The script supports the following actions:
|
|
#
|
|
# flash: flash <binfile>
|
|
#
|
|
# flash given binary format file to the target.
|
|
#
|
|
# options:
|
|
# <binfile>: path to the binary file that is flashed
|
|
#
|
|
# debug: debug <elffile>
|
|
#
|
|
# starts J-Link as GDB server in the background and
|
|
# connects to the server with the GDB client specified by
|
|
# the board (DBG environment variable)
|
|
#
|
|
# options:
|
|
# <elffile>: path to the ELF file to debug
|
|
# GDB_PORT: port opened for GDB connections
|
|
# TELNET_PORT: port opened for telnet connections
|
|
# DBG: debugger client command, default: 'gdb -q'
|
|
# TUI: if TUI!=null, the -tui option will be used
|
|
#
|
|
# debug-server: starts J-Link as GDB server, but does not connect to
|
|
# to it with any frontend. This might be useful when using
|
|
# IDEs.
|
|
#
|
|
# options:
|
|
# GDB_PORT: port opened for GDB connections
|
|
# TELNET_PORT: port opened for telnet connections
|
|
#
|
|
# reset: triggers a hardware reset of the target board
|
|
#
|
|
#
|
|
# term-rtt: opens a serial terminal using J-Link RTT (Real-Time Transfer)
|
|
#
|
|
#
|
|
# @author Hauke Peteresen <hauke.petersen@fu-berlin.de>
|
|
|
|
# Set IMAGE_OFFSET to zero by default.
|
|
: ${IMAGE_OFFSET:=0}
|
|
# Allow overwriting the reset commands.
|
|
: ${JLINK_RESET_FILE:=${RIOTTOOLS}/jlink/reset.seg}
|
|
|
|
# default GDB port
|
|
_GDB_PORT=3333
|
|
# default telnet port
|
|
_TELNET_PORT=4444
|
|
# default J-Link command names, interface and speed
|
|
_JLINK=JLinkExe
|
|
_JLINK_SERVER=JLinkGDBServer
|
|
_JLINK_IF=SWD
|
|
_JLINK_SPEED=2000
|
|
# default terminal frontend
|
|
_JLINK_TERMPROG=${RIOTTOOLS}/pyterm/pyterm
|
|
_JLINK_TERMFLAGS="-ts 19021 ${PYTERMFLAGS}"
|
|
|
|
#
|
|
# a couple of tests for certain configuration options
|
|
#
|
|
test_config() {
|
|
if [ -z "${JLINK}" ]; then
|
|
JLINK=${_JLINK}
|
|
fi
|
|
if [ -z "${JLINK_SERVER}" ]; then
|
|
JLINK_SERVER=${_JLINK_SERVER}
|
|
fi
|
|
if [ -z "${JLINK_IF}" ]; then
|
|
JLINK_IF=${_JLINK_IF}
|
|
fi
|
|
if [ -z "${JLINK_SPEED}" ]; then
|
|
JLINK_SPEED=${_JLINK_SPEED}
|
|
fi
|
|
if [ -z "${JLINK_DEVICE}" ]; then
|
|
echo "Error: No target device defined in JLINK_DEVICE env var"
|
|
exit 1
|
|
fi
|
|
if [ -z "${FLASH_ADDR}" ]; then
|
|
echo "Error: No flash address defined in FLASH_ADDR env var"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
test_binfile() {
|
|
if [ ! -f "${BINFILE}" ]; then
|
|
echo "Error: Unable to locate BINFILE"
|
|
echo " (${BINFILE})"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
test_ports() {
|
|
if [ -z "${GDB_PORT}" ]; then
|
|
GDB_PORT=${_GDB_PORT}
|
|
fi
|
|
if [ -z "${TELNET_PORT}" ]; then
|
|
TELNET_PORT=${_TELNET_PORT}
|
|
fi
|
|
}
|
|
|
|
test_elffile() {
|
|
if [ ! -f "${ELFFILE}" ]; then
|
|
echo "Error: Unable to locate ELFFILE"
|
|
echo " (${ELFFILE})"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
test_tui() {
|
|
if [ -n "${TUI}" ]; then
|
|
TUI=-tui
|
|
fi
|
|
}
|
|
|
|
test_serial() {
|
|
if [ -n "${JLINK_SERIAL}" ]; then
|
|
JLINK_SERIAL_SERVER="-select usb='${JLINK_SERIAL}'"
|
|
JLINK_SERIAL="-selectemubysn '${JLINK_SERIAL}'"
|
|
fi
|
|
}
|
|
|
|
test_dbg() {
|
|
if [ -z "${DBG}" ]; then
|
|
DBG="${GDB}"
|
|
fi
|
|
}
|
|
|
|
test_term() {
|
|
if [ -z "${JLINK_TERMPROG}" ]; then
|
|
JLINK_TERMPROG="${_JLINK_TERMPROG}"
|
|
fi
|
|
if [ -z "${JLINK_TERMFLAGS}" ]; then
|
|
JLINK_TERMFLAGS="${_JLINK_TERMFLAGS}"
|
|
fi
|
|
}
|
|
|
|
test_version() {
|
|
if [ -z "${JLINK_SKIP_VERSION}" ]; then
|
|
JLINK_MINIMUM_VERSION="6.74"
|
|
# Adding '-nogui 1' will simply return 'Unknown command line option -nogui'
|
|
# on older versions, JLINK_VERSION will still be parsed correctly.
|
|
JLINK_VERSION=$(echo q | "${JLINK}" "${JLINK_SERIAL}" -nogui 1 2> /dev/null | grep "^DLL version*" | grep -oE "[0-9]+\.[0-9]+")
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: J-Link appears not to be installed on your PATH"
|
|
exit 1
|
|
fi
|
|
|
|
"$RIOTTOOLS"/has_minimal_version/has_minimal_version.sh "$JLINK_VERSION" "$JLINK_MINIMUM_VERSION" 2> /dev/null
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: J-Link V$JLINK_MINIMUM_VERSION is required, but V${JLINK_VERSION} is installed"
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
#
|
|
# now comes the actual actions
|
|
#
|
|
do_flash() {
|
|
BINFILE=$1
|
|
test_config
|
|
test_serial
|
|
test_version
|
|
test_binfile
|
|
# clear any existing contents in burn file
|
|
/bin/echo -n "" > ${BINDIR}/burn.seg
|
|
# create temporary burn file
|
|
if [ ! -z "${JLINK_PRE_FLASH}" ]; then
|
|
printf "${JLINK_PRE_FLASH}\n" >> ${BINDIR}/burn.seg
|
|
fi
|
|
# address to flash is hex formatted, as required by JLink
|
|
ADDR_TO_FLASH=$(printf "0x%08x\n" "$((${FLASH_ADDR} + ${IMAGE_OFFSET}))")
|
|
echo "loadbin ${BINFILE} ${ADDR_TO_FLASH}" >> ${BINDIR}/burn.seg
|
|
if [ ! -z "${JLINK_POST_FLASH}" ]; then
|
|
printf "${JLINK_POST_FLASH}\n" >> ${BINDIR}/burn.seg
|
|
fi
|
|
cat ${JLINK_RESET_FILE} >> ${BINDIR}/burn.seg
|
|
# flash device
|
|
sh -c "${JLINK} ${JLINK_SERIAL} \
|
|
-nogui 1 \
|
|
-exitonerror 1 \
|
|
-device '${JLINK_DEVICE}' \
|
|
-speed '${JLINK_SPEED}' \
|
|
-if '${JLINK_IF}' \
|
|
-jtagconf -1,-1 \
|
|
-commandfile '${BINDIR}/burn.seg'"
|
|
}
|
|
|
|
do_debug() {
|
|
ELFFILE=$1
|
|
test_config
|
|
test_serial
|
|
test_version
|
|
test_elffile
|
|
test_ports
|
|
test_tui
|
|
test_dbg
|
|
# start the J-Link GDB server
|
|
sh -c "${JLINK_SERVER} ${JLINK_SERIAL_SERVER} \
|
|
-nogui \
|
|
-silent \
|
|
-device '${JLINK_DEVICE}' \
|
|
-speed '${JLINK_SPEED}' \
|
|
-if '${JLINK_IF}' \
|
|
-port '${GDB_PORT}' \
|
|
-telnetport '${TELNET_PORT}'" &
|
|
# save PID for terminating the server afterwards
|
|
DBG_PID=$?
|
|
# connect to the GDB server
|
|
${DBG} -q ${TUI} -ex "tar ext :${GDB_PORT}" ${ELFFILE}
|
|
# clean up
|
|
kill ${DBG_PID}
|
|
}
|
|
|
|
do_debugserver() {
|
|
test_config
|
|
test_serial
|
|
test_version
|
|
test_ports
|
|
# start the J-Link GDB server
|
|
sh -c "${JLINK_SERVER} ${JLINK_SERIAL_SERVER} \
|
|
-nogui \
|
|
-device '${JLINK_DEVICE}' \
|
|
-speed '${JLINK_SPEED}' \
|
|
-if '${JLINK_IF}' \
|
|
-port '${GDB_PORT}' \
|
|
-telnetport '${TELNET_PORT}'"
|
|
}
|
|
|
|
do_reset() {
|
|
test_config
|
|
test_serial
|
|
test_version
|
|
# reset the board
|
|
sh -c "${JLINK} ${JLINK_SERIAL} \
|
|
-nogui 1 \
|
|
-exitonerror 1 \
|
|
-device '${JLINK_DEVICE}' \
|
|
-speed '${JLINK_SPEED}' \
|
|
-if '${JLINK_IF}' \
|
|
-jtagconf -1,-1 \
|
|
-commandfile '${JLINK_RESET_FILE}'"
|
|
}
|
|
|
|
do_term() {
|
|
test_config
|
|
test_serial
|
|
test_version
|
|
test_term
|
|
|
|
# temporary file that save the J-Link Commander pid
|
|
JLINK_PIDFILE=$(mktemp -t "jilnk_pid.XXXXXXXXXX")
|
|
# will be called by trap
|
|
cleanup() {
|
|
if [ -f $JLINK_PIDFILE ]; then
|
|
JLINK_PID="$(cat ${JLINK_PIDFILE})"
|
|
kill ${JLINK_PID}
|
|
rm -r "${JLINK_PIDFILE}"
|
|
fi
|
|
exit 0
|
|
}
|
|
# cleanup after script terminates
|
|
trap "cleanup ${JLINK_PIDFILE}" EXIT INT
|
|
|
|
# start J-link as RTT server
|
|
sh -c "${JLINK} ${JLINK_SERIAL} \
|
|
-nogui 1 \
|
|
-exitonerror 1 \
|
|
-device '${JLINK_DEVICE}' \
|
|
-speed '${JLINK_SPEED}' \
|
|
-if '${JLINK_IF}' \
|
|
-jtagconf -1,-1 \
|
|
-commandfile '${RIOTTOOLS}/jlink/term.seg' >/dev/null & \
|
|
echo \$! > $JLINK_PIDFILE" &
|
|
sleep 1
|
|
|
|
sh -c "${JLINK_TERMPROG} ${JLINK_TERMFLAGS}"
|
|
}
|
|
|
|
#
|
|
# parameter dispatching
|
|
#
|
|
ACTION="$1"
|
|
shift # pop $1 from $@
|
|
|
|
case "${ACTION}" in
|
|
flash)
|
|
echo "### Flashing Target ###"
|
|
echo "### Flashing at base address ${FLASH_ADDR} with offset ${IMAGE_OFFSET} ###"
|
|
do_flash "$@"
|
|
;;
|
|
debug)
|
|
echo "### Starting Debugging ###"
|
|
do_debug "$@"
|
|
;;
|
|
debug-server)
|
|
echo "### Starting GDB Server ###"
|
|
do_debugserver "$@"
|
|
;;
|
|
reset)
|
|
echo "### Resetting Target ###"
|
|
do_reset "$@"
|
|
;;
|
|
term-rtt)
|
|
echo "### Starting RTT terminal ###"
|
|
do_term
|
|
;;
|
|
*)
|
|
echo "Usage: $0 {flash|debug|debug-server|reset|term-rtt}"
|
|
echo " flash <binfile>"
|
|
echo " debug <elffile>"
|
|
;;
|
|
esac
|