davideisinger.com

My personal website
Log | Files | Refs | README

bogdanthegeek-github-io-p0gyop.txt (10169B)


      1 [1]
      2 BogdanTheGeek's Blog
      3 
      4   • Menu ▾
      5      6       □ [2]About
      7       □ [3]Insights
      8       □ [4]Projects
      9       □ [5]Thoughts
     10 
     11   • [6]About
     12   • [7]Insights
     13   • [8]Projects
     14   • [9]Thoughts
     15 
     16 [10]Hosting a WebSite on a Disposable Vape
     17 
     18 2025-09-13Bogdan Ionescu6 min read (1266 words)[11]source [12]report issue
     19 #[13]programming  #[14]arm  #[15]tools  #[16]electronics  Hosting a WebSite on
     20 a Disposable Vape
     21 
     22 Preface[17]#
     23 
     24 This article is NOT served from a web server running on a disposable vape. If
     25 you want to see the real deal, click [18]here. The content is otherwise
     26 identical.
     27 
     28 Background[19]#
     29 
     30 For a couple of years now, I have been collecting disposable vapes from friends
     31 and family. Initially, I only salvaged the batteries for “future” projects
     32 (It’s not hoarding, I promise), but recently, disposable vapes have gotten more
     33 advanced. I wouldn’t want to be the lawyer who one day will have to argue how a
     34 device with USB C and a rechargeable battery can be classified as “disposable”.
     35 Thankfully, I don’t plan on pursuing law anytime soon.
     36 
     37 Last year, I was tearing apart some of these fancier pacifiers for adults when
     38 I noticed something that caught my eye, instead of the expected black blob of
     39 goo hiding some ASIC (Application Specific Integrated Circuit) I see a little
     40 integrated circuit inscribed “PUYA”. I don’t blame you if this name doesn’t
     41 excite you as much it does me, most people have never heard of them. They are
     42 most well known for their flash chips, but I first came across them after
     43 reading Jay Carlson’s blog post about [20]the cheapest flash microcontroller
     44 you can buy. They are quite capable little ARM Cortex-M0+ micros.
     45 
     46 Over the past year I have collected quite a few of these PY32 based vapes, all
     47 of them from different models of vape from the same manufacturer. It’s not my
     48 place to do free advertising for big tobacco, so I won’t mention the brand I
     49 got it from, but if anyone who worked on designing them reads this, thanks for
     50 labeling the debug pins!
     51 
     52 What are we working with[21]#
     53 
     54 The chip is marked PUYA C642F15, which wasn’t very helpful. I was pretty sure
     55 it was a PY32F002A, but after poking around with [22]pyOCD, I noticed that the
     56 flash was 24k and we have 3k of RAM. The extra flash meant that it was more
     57 likely a PY32F002B, which is actually a very different chip.^[23]1
     58 
     59 So here are the specs of a microcontroller so bad, it’s basically disposable:
     60 
     61   • 24MHz Coretex M0+
     62   • 24KiB of Flash Storage
     63   • 3KiB of Static RAM
     64   • a few peripherals, none of which we will use.
     65 
     66 You may look at those specs and think that it’s not much to work with. I don’t
     67 blame you, a 10y old phone can barely load google, and this is about 100x
     68 slower. I on the other hand see a blazingly fast web server.
     69 
     70 Getting online[24]#
     71 
     72 The idea of hosting a web server on a vape didn’t come to me instantly. In
     73 fact, I have been playing around with them for a while, but after writing my
     74 post on [25]semihosting, the penny dropped.
     75 
     76 If you don’t feel like reading that article, semihosting is basically syscalls
     77 for embedded ARM microcontrollers. You throw some values/pointers into some
     78 registers and call a breakpoint instruction. An attached debugger interprets
     79 the values in the registers and performs certain actions. Most people just use
     80 this to get some logs printed from the microcontroller, but they are actually
     81 bi-directional.
     82 
     83 If you are older than me, you might remember a time before Wi-Fi and Ethernet,
     84 the dark ages, when you had to use dial-up modems to get online. You might also
     85 know that the ghosts of those modems still linger all around us. Almost all USB
     86 serial devices actually emulate those modems: a 56k modem is just 57600 baud
     87 serial device. Data between some of these modems was transmitted using a
     88 protocol called SLIP (Serial Line Internet Protocol).^[26]2
     89 
     90 This may not come as a surprise, but Linux (and with some tweaking even macOS)
     91 supports SLIP. The slattach utility can make any /dev/tty* send and receive IP
     92 packets. All we have to do is put the data down the wire in the right format
     93 and provide a virtual tty. This is actually easier than you might imagine,
     94 pyOCD can forward all semihosting through a telnet port. Then, we use socat to
     95 link that port to a virtual tty:
     96 
     97 pyocd gdb -S -O semihost_console_type=telnet -T $(PORT) $(PYOCDFLAGS) &
     98 socat PTY,link=$(TTY),raw,echo=0 TCP:localhost:$(PORT),nodelay &
     99 sudo slattach -L -p slip -s 115200 $(TTY) &
    100 sudo ip addr add 192.168.190.1 peer 192.168.190.2/24 dev sl0
    101 sudo ip link set mtu 1500 up dev sl0
    102 
    103 Ok, so we have a “modem”, but that’s hardly a web server. To actually talk TCP/
    104 IP, we need an IP stack. There are many choices, but I went with [27]uIP
    105 because it’s pretty small, doesn’t require an RTOS, and it’s easy to port to
    106 other platforms. It also, helpfully, comes with a very minimal HTTP server
    107 example.
    108 
    109 After porting the SLIP code to use semihosting, I had a working web server&
    110 mldr;half of the time. As with most highly optimised libraries, uIP was
    111 designed for 8 and 16-bit machines, which rarely have memory alignment
    112 requirements. On ARM however, if you dereference a u16 *, you better hope that
    113 address is even, or you’ll get an exception. The uip_chksum assumed u16
    114 alignment, but the script that creates the filesystem didn’t. I actually
    115 decided to modify a bit the structure of the filesystem to make it a bit more
    116 portable. This was my first time working with perl and I have to say, it’s
    117 quite well suited to this kind of task.
    118 
    119 Blazingly fast[28]#
    120 
    121 So how fast is a web server running on a disposable microcontroller. Well,
    122 initially, not very fast. Pings took ~1.5s with 50% packet loss and a simple
    123 page took over 20s to load. That’s so bad, it’s actually funny, and I kind of
    124 wanted to leave it there.
    125 
    126 However, the problem was actually between the seat and the steering wheel the
    127 whole time. The first implementation read and wrote a single character at a
    128 time, which had a massive overhead associated with it. I previously benchmarked
    129 semihosting on this device, and I was getting ~20KiB/s, but uIP’s SLIP
    130 implementation was designed for very low memory devices, so it was serialising
    131 the data byte by byte. We have a whopping 3kiB of RAM to play with, so I added
    132 a ring buffer to cache reads from the host and feed them into the SLIP poll
    133 function. I also split writes in batches to allow for escaping.
    134 
    135 Now this is what I call blazingly fast! Pings now take 20ms, no packet loss and
    136 a full page loads in about 160ms. This was using almost all of the RAM, but I
    137 could also dial down the sizes of the buffer to have more than enough headroom
    138 to run other tasks. The project repo has everything set to a nice balance
    139 latency and RAM usage:
    140 
    141 Memory region         Used Size  Region Size  %age Used
    142            FLASH:        5116 B        24 KB     20.82%
    143              RAM:        1380 B         3 KB     44.92%
    144 
    145 For this blog however, I paid for none of the RAM, so I’ll use all of the RAM.
    146 
    147 As you may have noticed, we have just under 20kiB (80%) of storage space. That
    148 may not be enough to ship all of React, but as you can see, it’s more than
    149 enough to host this entire blog post. And this is not just a static page
    150 server, you can run any server-side code you want, if you know C that is.
    151 
    152 Just for fun, I added a json api endpoint to get the number of requests to the
    153 main page (since the last crash) and the unique ID of the microcontroller.
    154 
    155 Resources[29]#
    156 
    157   • [30]Code for this project
    158 
    159 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    160 
    161  1. While getting things together for this post, I came across [31]this project
    162     that correctly identified these MCUs as PY32C642, which are pretty much
    163     identical to the 002B. [32]↩︎
    164 
    165  2. Later modems used PPP (Point-to-Point Protocol) [33]↩︎
    166 
    167 © 2025 Bogdan Ionescu
    168 
    169 References:
    170 
    171 [1] https://bogdanthegeek.github.io/blog/
    172 [2] https://bogdanthegeek.github.io/blog/about
    173 [3] https://bogdanthegeek.github.io/blog/insights
    174 [4] https://bogdanthegeek.github.io/blog/projects
    175 [5] https://bogdanthegeek.github.io/blog/thoughts
    176 [6] https://bogdanthegeek.github.io/blog/about
    177 [7] https://bogdanthegeek.github.io/blog/insights
    178 [8] https://bogdanthegeek.github.io/blog/projects
    179 [9] https://bogdanthegeek.github.io/blog/thoughts
    180 [10] https://bogdanthegeek.github.io/blog/projects/vapeserver/
    181 [11] https://github.com/BogdanTheGeek/blog/tree/main/content/projects/vapeserver.md
    182 [12] https://github.com/BogdanTheGeek/blog/issues/new?template=corrections.md&title=[Correction]:%20Hosting%20a%20WebSite%20on%20a%20Disposable%20Vape
    183 [13] https://bogdanthegeek.github.io/blog/tags/programming/
    184 [14] https://bogdanthegeek.github.io/blog/tags/arm/
    185 [15] https://bogdanthegeek.github.io/blog/tags/tools/
    186 [16] https://bogdanthegeek.github.io/blog/tags/electronics/
    187 [17] https://bogdanthegeek.github.io/blog/projects/vapeserver/#preface
    188 [18] http://ewaste.fka.wtf/
    189 [19] https://bogdanthegeek.github.io/blog/projects/vapeserver/#background
    190 [20] https://jaycarlson.net/2023/02/04/the-cheapest-flash-microcontroller-you-can-buy-is-actually-an-arm-cortex-m0/
    191 [21] https://bogdanthegeek.github.io/blog/projects/vapeserver/#what-are-we-working-with
    192 [22] http://pyocd.io/
    193 [23] https://bogdanthegeek.github.io/blog/projects/vapeserver/#fn:1
    194 [24] https://bogdanthegeek.github.io/blog/projects/vapeserver/#getting-online
    195 [25] https://bogdanthegeek.github.io/blog/insights/jlink-rtt-for-the-masses/
    196 [26] https://bogdanthegeek.github.io/blog/projects/vapeserver/#fn:2
    197 [27] https://github.com/adamdunkels/uip/tree/uip-0-9
    198 [28] https://bogdanthegeek.github.io/blog/projects/vapeserver/#blazingly-fast
    199 [29] https://bogdanthegeek.github.io/blog/projects/vapeserver/#resources
    200 [30] https://github.com/BogdanTheGeek/semihost-ip
    201 [31] https://github.com/grahamwhaley/py32c642_vape
    202 [32] https://bogdanthegeek.github.io/blog/projects/vapeserver/#fnref:1
    203 [33] https://bogdanthegeek.github.io/blog/projects/vapeserver/#fnref:2