Using a Raspberry Pi as a remote headless J-Link Server

Here at Feabhas we tend to favour using Segger J-Link’s as our ‘go-to’ solution for target flashing and debug, as they fall into that category of tools that just work.

As part of our ongoing work around Agile and CI (Continuous Integration), we’re always interested in addressing that challenging step of automating target based test in a cost-effective manner.

The Raspberry Pi (RPi) is a ubiquitous low-cost platform for numerous tasks. One useful tasks that it can be used for is as a network-based conjugate between a client machine and a target board, where the target board is connected to the RPi via a local J-Link.

Setting up the RPi

The Segger J-Link utilities are available for ARM-based systems, which means it should work on any Raspberry Pi. However, we have, so far, only tested it on a RPi3+, but intend to try the PiZero as well.

As we are using the RPi in a headless setup we installed Raspbian Stretch Lite, connected an HDMI screen plus keyboard and booted up the Pi.

We then proceeded through the usual Pi setup

  • ensured all software was updated
  • changed the pi user password (I know many people go further and swap out pi for a different user)
  • enabled SSH (this becomes useful later when remote working from a client):
$ sudo raspi-config
--> 5 Interfacing Options  Configure connections to peripherals  
--> P2 SSH         Enable/Disable remote command line access to your Pi using SSH 

In addition, make a note of the RPi’s IP address (assuming you’re using the WiFi interface), as we’ll need that later to connect:

$ ip addr show wlan0

and make a note of the inet number (e.g. 192.168.0.XXX or similar), or use ifconfig.

Installing the J-Link utilities

Connect your J-Link via USB to the Pi and to your target board via the appropriate header. Assuming SSH was set up we can now work remotely from the client machine.

On our client machine, log in to the RPi via ssh:

 $ ssh pi@192.168.0.XXX
pi@192.168.0.XXX's password: 
Linux raspberrypi 4.19.50-v7+ #1234 SMP Thu Jun 13 11:06:37 BST 2019 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Thu Jun 20 10:27:31 2019 from 192.168.0.YYY
pi@raspberrypi:~ $ 

In the pi user home directory, download and un-tar the Segger utilities for the Pi. Then configure the udev rules as per README.txt file in the JLink_Linux_V646g_arm directory.

$ wget --post-data 'accept_license_agreement=accepted&non_emb_ctr=confirmed&submit=Download+software'
$ tar xvf JLink_Linux_arm.tgz
$ cd JLink_Linux_V646g_arm/
$ more README.txt
$ sudo cp 99-jlink.rules /etc/udev/rules.d/
$ sudo reboot

This will close the ssh connection.

Starting the RPi’s J-Link Server Software

Re-login to the RPi via ssh.

Under the directory JLink_Linux_V646g_arm there are a number of utilities. As we are running from the command line we need to invoke the application JLinkRemoteServerCLExe on the RPi:

$ ./JLink_Linux_V646g_arm/JLinkRemoteServerCLExe -Port 19020
SEGGER J-Link Remote Server V6.46g
Compiled Jun 14 2019 19:38:47

'q' to quit '?' for help

Connected to J-Link with S/N xxxxxxxxx

Waiting for client connections... 

Reading the documentation, the -Port 19020 shouldn’t be required as it’s supposedly the default port, however, at the time of writing without specifying this the client connection always fails.

Connecting the client via CLI

On the client machine, download and install the Segger J-Link Software and Documentation Pack specific for your host OS (I’m using macOS).

Once installed, simply type the following (substituting the IP address as appropriate):

$ JLinkExe ip 192.168.0.XXX
SEGGER J-Link Commander V6.46g (Compiled Jun 14 2019 19:36:04)
DLL version V6.46g, compiled Jun 14 2019 19:35:53

Connecting to J-Link via IP...O.K.
Firmware: J-Link V10 compiled Jun 14 2019 19:25:26
Hardware version: V10.10
S/N: xxxxxxxxx
License(s): FlashBP, GDB

Type "connect" to establish a target connection, '?' for help

On the RPi you should see:

Conn. 8: Client connected.
Connected to J-Link with S/N xxxxxxxxx

To disconnect the client, simply type qc at the J-Link command line and the RPi should go back to:

Waiting for client connections... 

Connecting a client debugger

If the J-Link remotely connects correctly, then it is also possible to use tools such as Segger’s Ozone to do remote target debugging. For example, in Ozone simply set the IP address of the remote RPi in the J-Link Settings under the Tools menu.

You can then download and debug an image as if the target was local to the client machine:

Remote-remote connection!

Back in February if this year (2019), Segger announced a new feature call tunnelling. This enables remote connection to a J-Link Server via the internet.

To use this utility, then on the RPi, type:

$ ./JLink_Linux_V646g_arm/JLinkRemoteServerCLExe -UseTunnel -TunnelByName <some_name> -TunnelPW <some_password>


$ ./JLink_Linux_V646g_arm/JLinkRemoteServerCLExe -UseTunnel -TunnelByName feabhas_jlink_42 -TunnelPW monkey

And before you ask, no we don’t use monkey as our password 😉

On the client connect via:

$ JLinkExe ip tunnel:feabhas_jlink_42:monkey

Full details can be found at

Note: I was unsuccessful getting this to work with Ozone


It is important to note, that for the Linux ARM utilities, Segger clearly state that the : This package comes without any support.

I have found that quite regularly once I have quit the client I am then unable to reconnect, with the following error:

$ JLinkExe ip 192.168.0.XXX
SEGGER J-Link Commander V6.46g (Compiled Jun 14 2019 19:36:04)
DLL version V6.46g, compiled Jun 14 2019 19:35:53

Connecting to J-Link via IP...FAILED: Can not connect to J-Link via TCP/IP (192.168.0.XXX, port 19020)

And the Server application still thinks the client is connected. The only option I’ve found is to type q in the RPi session which quits JLinkRemoteServerCLExe and then to restart it from the command line. This is the major reason for using SSH as it allows JLinkRemoteServerCLExe can be restarted remotely.

The same issue was persistent when using tunnelling and, obviously, having no SSH connection to the RPi it proved pretty useless (if I use our VPN to connect to the RPi it negates the benefit of tunnelling).

However, others have indicated they have had no such problems (it may be something LAN specific?).


The use of a Raspberry Pi acting as a network-connected conduit to a target board is very attractive. RPi’s are easy to source and very inexpensive. Combined with Segger’s J-Link utilities, including applications to handle GDB and SWO, then it may provide a good platform for taking many CI pipelines to their next step.

Unfortunately, the issues of failed reconnection do seem to only be happening with the Linux Arm utilities. Running the same Remote Server commands a Linux laptop proved reliable, both on the local LAN and using tunnelling.

As Raspberry Pi’s support Docker, then my next angle of attack is to see if there is a way I can run the server software in a docker container, which would allow for simpler restarts without needing the SSH connection.

For now, we’ll live with the reconnection issue and continue to use SSH, but watch this space…


Niall Cooling
Dislike (0)
Website | + posts

Co-Founder and Director of Feabhas since 1995.
Niall has been designing and programming embedded systems for over 30 years. He has worked in different sectors, including aerospace, telecomms, government and banking.
His current interest lie in IoT Security and Agile for Embedded Systems.

About Niall Cooling

Co-Founder and Director of Feabhas since 1995. Niall has been designing and programming embedded systems for over 30 years. He has worked in different sectors, including aerospace, telecomms, government and banking. His current interest lie in IoT Security and Agile for Embedded Systems.
This entry was posted in Agile, ARM, C/C++ Programming, Testing and tagged , , . Bookmark the permalink.

11 Responses to Using a Raspberry Pi as a remote headless J-Link Server

  1. mayur pawar says:

    Hi Niall,
    Thanks for your valuable guidance through this blog.
    You explained well for case of RPI as Jlink server , But how we can handle for other micro controller . The reason I'm asking this question is because I want to try automating debugging/flashing using CI for bare controller like ST/ADU ARM controller (RPI is abstracted Embedded system with all facilities & driver ) .
    My thought to implemented is invoking Jlink server on dedicated PC System ( with Board connected to Jlink debugger ) using 1 jenkins plugin called JENKINS External Resource dispatcher. In one of my Automotive project there was requirement to automate through CI (Jenkins) after developer commit code to SVN/GIT . Test Enginner will also commit Jlink script to github .

    Like (1)
    Dislike (0)
  2. Hi. What you want to do is what we're also looking to do here.
    We have an STM32F4 connect via the j-link to the RPi as a bare-metal unit.
    Thanks for the link to the External Resource dispatcher, I wasn't aware of that.
    My plan/hope is to use Docker on the RPi in conjunction with the j-link and see how I can use Jenkins to kick off a test.
    Ultimately I'd like to have a bespoke Docker image build on the fly for a particular test, incorporating python test drivers.
    I'm some way off this, but having the RPi with remote re-flashing capability is a step along the journey.
    Let me know if you get the External Resource dispatcher going, if I do I'll document it.

    Like (3)
    Dislike (0)
  3. Lieven says:

    Hello Niall,

    Thanks for your article. Did you ever get around to run the JLink tools in a docker container as you mention at the end of your article?

    Kind regards,

    Like (0)
    Dislike (0)
  4. Hi Lieven,

    No, unfortunately, I didn't, it's still on my (very long) backlog list.

    We've been very distracted over the last year developing a comprehensive QEMU simulation of our target system, so the physical world has taken a bit of a backstop.

    That said, I'm just embarking on some new work where I may look to get this working.

    What this space 😉



    Like (1)
    Dislike (0)
  5. Lieven says:

    Thanks for your reply Niall. I might be experimenting with this myself too, hence my question.

    Side note: is it expected that the comments themselves don't show up on the site? I see there are 4 responses to the article but I can't see the responses themselves?

    Best regards,

    Like (0)
    Dislike (0)
  6. Yes they should show up - not sure what's going on . Will get "web" people to take a look.

    Thanks and let me know if you get anything working

    Like (1)
    Dislike (0)
  7. Lieven says:

    Hey Niall,

    just as a follow-up: the process described on the Segger wiki just works out of the box on the Rpi.

    Best regards,

    Like (2)
    Dislike (0)
  8. RusikOk says:

    the problem disappears when using the sudo command:
    $ sudo ./JLink_Linux_V696_arm/JLinkRemoteServerCLExe -Port 19020

    Like (0)
    Dislike (0)
  9. urmilshah1 says:

    Spent some time on this step. Should have read the comments before.

    $ ./JLink_Linux_V696_arm/JLinkRemoteServerCLExe -Port 19020

    Like (0)
    Dislike (0)
  10. HCO says:

    Hey man! I know you're net target was to get this process working in at my company we just attempted to do that and it worked and didn't work. We are able to successfully use docker locally on the RPi to flash firmware on an MCU using the Pi. However, when we used Azure DevOps to construct the pipeline where we build a docker container capable of doing the same thing and letting azure handle the job, it also worked for a time and then stopped working, giving us the same issue as above. Nothing changed in our YAML file, so we are not sure what happend. For now, our solution is to run an Ubuntu VM on the Pi to emulate our local environment.

    Like (0)
    Dislike (0)
  11. Will InwZa says:

    Hi Niall,

    Thank you for the article.

    I wanted to inform you and others who might be looking to run jlink on the RPi Zero. I've tested it with the RPI Zero W v1.1 running Raspbian GNU/Linux 11 (bullseye). It seems that issues begin to arise after Segger JLink V6.82g, displaying error messages such as "Illegal instruction" or "Segmentation fault" after starting the program. After reviewing the release notes (, there's no mention of the obsolescence of armv6z (RPi Zero's CPU). If anyone else encounters the same issue as I have, I plan to report it to Segger as a bug.

    Like (1)
    Dislike (0)

Leave a Reply