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