MCPcopy Index your code
hub / github.com/BogdanTheGeek/semihost-ip

github.com/BogdanTheGeek/semihost-ip @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
165 symbols 257 edges 25 files 104 documented · 63%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

You can find my blog post about this project here: https://bogdanthegeek.github.io/blog/projects/vapeserver/

The vape is hosted here: http://ewaste.fka.wtf/

And if it's down: https://web.archive.org/web/20250914222638/http://ewaste.fka.wtf/

Running a web server over SWD

After playing around with semihosting on a little py32 microcontroller I found in a disposable vape, I realised that pyocd can forward the semihosting stdout/stdin to a TCP port.

Considering that all of the internet used to be run over serial modems, once you can send and receive data to a device, you can talk TCP/IP.

This is where using UART would have actually made things easier, but I wanted to see if I could do it over SWD. Most modem drivers expect to see a serial device(/dev/ttyACM0 or similar), but we can make any unix socket look like a serial device using socat:

socat PTY,link=/home/me/customTTY,raw,echo=0 TCP:localhost:$(PORT),nodelay

[!WARNING] Linux developers love to make things difficult. If you are on Linux, the virtual tty device needs to be a full root path like /home/user/tty or /tmp/tty. Relative paths don't work. The path also needs to be writable by your user.

Now we have a /home/me/customTTY device that we can use as a serial device. This is also a good trick if you prefer to use something like picocom or minicom to interact with serial devices.

Ok, so we have a serial device, how do we run TCP/IP over it? We need a network layer because we are not running over Ethernet or WiFi. The simples protocol I have come across is SLIP (Serial Line Internet Protocol). It is less performant than PPP, but it's very simple to set up, and as a bonus, the IP stack I am using (uIP) has SLIP support built in.

For the TCP/IP stack, I used uIP v9.0 as it is pretty popular and easy to port as well as being very small and having good examples. I used the picosoc-uip project as a reference for how to set up a minimal web server. My only change was to optimise the SLIP serialisation just a little bit to reduce the semihosting overhead.

And that's it! You can now ping 192.168.190.2 or curl http://192.168.190.2:80 to see the web server running on the microcontroller.

Performance can be pretty good at the expense of RAM usage. I got pings to be as low as 30ms, and loading a simple web page took about 150ms.

The default settings however conserve a bit more RAM, and the ping times are around 70ms, and loading a web page takes about 400ms:

Memory region         Used Size  Region Size  %age Used
           FLASH:        8632 B        24 KB     35.12%
             RAM:        1496 B         3 KB     48.70%

Throughput is pretty acceptable for a microcontroller over SWD. I got it as high as 10KiB/s with larger web pages.

Requirements

  • Any arm microcontroller supported by pyocd (I used a py32f002b)
  • socat
  • pyocd >= 0.39.0
  • perl (for the makefsimage script)
  • net-tools (for slattach on linux)

Usage

In separate terminals, run the following commands:

make flash serve
make tty
make slip

Acknowledgements

Core symbols most depended-on inside this repo

uip_add_rcv_nxt
called by 10
lib/uip/uip.c
slipdev_char_put
called by 8
src/main.c
htons
called by 7
lib/uip/uip.c
read
called by 5
src/main.c
fs_open
called by 4
lib/uip/fs.c
SEMIHOST_SysCall
called by 4
src/semihost.h
uip_chksum
called by 3
lib/uip/uip_arch.c
uip_ipchksum
called by 3
lib/uip/uip_arch.c

Shape

Function 129
Class 36

Languages

C65%
C++35%

Modules by API surface

src/system.h37 symbols
src/system.c28 symbols
tools/slip-macos/slip.c19 symbols
lib/uip/uip_arp.c15 symbols
lib/uip/uip.c12 symbols
src/main.c10 symbols
src/gpio.h7 symbols
lib/uip/httpd.c6 symbols
lib/uip/fs.c6 symbols
lib/uip/uip_arch.c4 symbols
lib/uip/fsdata.h4 symbols
src/log.c3 symbols

For agents

$ claude mcp add semihost-ip \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page