2025-09-04 11:00:00
It's been almost two years since I posted the "Collecting pins" post! It's time I shared an update.
Somewhere along the way I decided to get more organized and started a spreadsheet to track all the details about my pin collection (has this crossed the line to the unhealthy hobby territory yet?). The main thing I wanted to have was a clear history of the collection: when, where and how was each pin added to the collection. And after spending a lot of time filling in the blanks, today I can finally share it!
So here it is, my current pin collection, with 128 pins and filling up two and a half display cases, summarized in three images and a table:
No. | Name | When | Where | How |
---|---|---|---|---|
1 | Poring — Ragnarok Online | 2022-12-01 | Online | Purchase |
2 | Poporing — Ragnarok Online | 2022-12-01 | Online | Purchase |
3 | /Gg Emote — Ragnarok Online | 2022-12-16 | Online | Purchase |
4 | Deviruchi — Ragnarok Online | 2022-12-16 | Online | Purchase |
5 | Fairy Bottle — Zelda | 2022-12-16 | Online | Purchase |
6 | Eevee — Pokémon | 2022-12-21 | Online | Purchase |
7 | L — Death Note | 2023-02-08 | Geek store in Antwerp, Belgium | Purchase |
8 | Phantom Of The Opera | 2023-02-13 | Phantom of the Opera show at Majestic Theatre in NYC | Purchase |
9 | Van Gogh's The Starry Night | 2023-03-11 | MoMA in NYC | Purchase |
10 | King — Katamari Damacy | 2023-03-23 | Fangamer stand at PAX East 23 | Purchase |
11 | Prince & Katamari — Katamari Damacy | 2023-03-23 | Fangamer stand at PAX East 23 | Purchase |
12 | Annoying Dog — Undertale | 2023-03-23 | Fangamer stand at PAX East 23 | Purchase |
13 | Flowey — Undertale | 2023-03-23 | Fangamer stand at PAX East 23 | Purchase |
14 | Sans — Undertale | 2023-03-23 | Fangamer stand at PAX East 23 | Purchase |
15 | Frisk — Undertale | 2023-03-23 | Fangamer stand at PAX East 23 | Purchase |
16 | Papyrus — Undertale | 2023-03-23 | Fangamer stand at PAX East 23 | Purchase |
17 | Toriel — Undertale | 2023-03-23 | Fangamer stand at PAX East 23 | Purchase |
18 | Undyne — Undertale | 2023-03-23 | Fangamer stand at PAX East 23 | Purchase |
19 | Mercy Button — Undertale | 2023-03-23 | Fangamer stand at PAX East 23 | Purchase |
20 | Fight Button — Undertale | 2023-03-23 | Fangamer stand at PAX East 23 | Purchase |
21 | Junimo Package — Stardew Valley | 2023-03-23 | Fangamer stand at PAX East 23 | Purchase |
22 | ? Block — Super Mario Bros. | 2023-03-23 | PAX merch stand at PAX East 23 | Purchase |
23 | Mario — Super Mario Bros. | 2023-03-23 | PAX merch stand at PAX East 23 | Purchase |
24 | East 2023 Logo | 2023-03-23 | PAX merch stand at PAX East 23 | Purchase |
25 | PAX East VHS | 2023-03-23 | PAX merch stand at PAX East 23 | Purchase |
26 | Babaa — Neopets | 2023-03-24 | Geekify stand at PAX East 23 | Purchase |
27 | Wraith Paintbrush — Neopets | 2023-03-24 | Geekify stand at PAX East 23 | Purchase |
28 | Strawberry Fields Forever Paintbrush — Neopets | 2023-03-24 | Geekify stand at PAX East 23 | Purchase |
29 | Raz — Psychonauts | 2023-03-24..26 | Trading hall at PAX East 23 | Gift |
30 | Kerbal Space Program | 2023-03-24..26 | Trading hall at PAX East 23 | Gift |
31 | Atlas And P-Body — Portal 2 | 2023-03-24..26 | Trading hall at PAX East 23 | Trade |
32 | Diamond Ore Block — Minecraft | 2023-03-24..26 | Trading hall at PAX East 23 | Trade |
33 | Mae — Night In The Woods | 2023-03-24..26 | Finji stand at PAX East 23 | Purchase |
34 | Green Flame — Acquisitions Inc. | 2023-03-24..26 | Acquisitions Incorporated stand at PAX East 23 | Purchase |
35 | Psychokinetic Raz — Psychonauts 2 | 2023-03-24..26 | Fangamer stand at PAX East 23 | Purchase |
36 | Goose — Kickstarter | 2023-03-24..26 | Kickstarter stand at PAX East 23 | Reward |
37 | PAX Gold Mixtape | 2023-03-24..26 | Carnival wheel at Pinny Arcade booth at PAX East 23 | Reward |
38 | Portuguese Tile | 2023-05-06..07 | Portugal (Porto?) | Purchase |
39 | Software Freedom Conservancy's Logo | 2023-05-08..11 | Collabora Meetup in Portugal | Gift (from Padovan) |
40 | Collabora's Logo | 2023-05-08..11 | Collabora Meetup in Portugal | Gift (from Guy) |
41 | +Finely-Crafted Dwarven Pin+ — Dwarf Fortress | 2023-05-20 | Online | Purchase |
42 | Fairly Oddparents | 2023-06-06 | Online | Purchase |
43 | Loto | 2023-11-09..11 | Home in NYC | Gift (from Tony) |
44 | Ecuador | 2023-11-09..11 | Home in NYC | Gift (from Tony) |
45 | Los Andes | 2023-11-09..11 | Home in NYC | Gift (from Tony) |
46 | Canada Wilderness | 2023-11-09..11 | CN Tower in Toronto / Home in NYC | Gift (from Tony) |
47 | Paranaguá Train | 2023-11-09..11 | Home in NYC | Gift (from Tony) |
48 | Wonderville Arcade Machine | 2023-11-10 | Wonderville in NYC | Purchase |
49 | Mask — Mr. Robot | 2023-11-15 | Online | Purchase |
50 | Squidward At Work — Spongebob Squarepants | 2023-12-01 | Home in NYC | Gift (from Mom) |
51 | Penguin | 2023-12-01 | Home in NYC | Gift (from Mom) |
52 | Outback @ | 2023-12-03 (originally ~2010) | Home in São Paulo | Gift (from Mom) |
53 | Outback Steakhouse Sign | 2023-12-03 (originally ~2010) | Home in São Paulo | Gift (from Mom) |
54 | Paper Boat | 2023-12-09..15 | Cruise to northeast of Brazil | Purchase |
55 | Magic The Gathering Card Back | 2023-12-15..2024-01-27 | SoGo Plaza Shopping in São Paulo | Purchase |
56 | Odish — Pokémon | 2023-12-15..2024-01-27 | SoGo Plaza Shopping in São Paulo | Purchase |
57 | This Is Fine (First Panel) | 2024-05-29 | Online | Purchase |
58 | All Hail The Glow Cloud — Welcome to Night Vale | 2024-05-29 | Online | Purchase |
59 | Spelcheck | 2024-05-29 | Online | Purchase |
60 | Donut | 2024-06-01..2024-08-01 | Gift shop at Bryant Park | Purchase |
61 | Schroeder — Peanuts | 2024-06-01..2024-08-01 | Newtown HQ store in NYC | Purchase |
62 | New York Pidgeon | 2024-06-01..2024-08-01 | Newtown HQ store in NYC | Purchase |
63 | New York Sewer | 2024-06-01..2024-08-01 | Newtown HQ store in NYC | Purchase |
64 | Groundon — Pokémon | 2024-06-01..2024-08-01 | Say Cheese store in NYC | Purchase |
65 | Pikachu — Pokémon | 2024-06-01..2024-08-01 | Say Cheese store in NYC | Purchase |
66 | MTA Logo | 2024-08-16 | New York Transit Museum | Purchase |
67 | Dollyinho | 2024-09-21 | Vienna, Austria | Gift (from Tony) |
68 | Imagination! — Spongebob Squarepants | 2024-10-17 | Zen Monkey Studios stand at New York Comic Con 2024 | Purchase |
69 | Mr. Krabs' World's Smallest Violin — Spongebob Squarepants | 2024-10-17 | Zen Monkey Studios stand at New York Comic Con 2024 | Purchase |
70 | Nail in Head Patrick — Spongebob Squarepants | 2024-10-17 | Zen Monkey Studios stand at New York Comic Con 2024 | Purchase |
71 | Shocked Patrick — Spongebob Squarepants | 2024-10-17 | Zen Monkey Studios stand at New York Comic Con 2024 | Purchase |
72 | Speedy Sonic — Classic Sonic The Hedgehog | 2024-10-17 | Zen Monkey Studios stand at New York Comic Con 2024 | Purchase |
73 | Pizza Slurpin' Gir — Invader Zim | 2024-10-17 | Zen Monkey Studios stand at New York Comic Con 2024 | Purchase |
74 | Aang On Air Scooter — Avatar: The Last Airbender | 2024-10-17 | Zen Monkey Studios stand at New York Comic Con 2024 | Purchase |
75 | Mr. Incredible — The Incredibles | 2024-10-17 | Disney pin trading event at New York Comic Con 2024 | Trade |
76 | Woody, Buzz Lightyear & Jessie — Toy Story | 2024-10-17 | Pins stand at New York Comic Con 2024 | Purchase |
77 | Randall Boggs with Scream Canister — Monsters Inc. | 2024-10-17 | Pins stand at New York Comic Con 2024 | Purchase |
78 | The One Ring — The Lord of the Rings | 2024-10-17 | Pins stand at New York Comic Con 2024 | Purchase |
79 | Pacman | 2024-10-17 | Pins stand at New York Comic Con 2024 | Purchase |
80 | Chicken Little | 2024-10-17 | Pins stand at New York Comic Con 2024 | Purchase |
81 | Warp Star Kirby | 2024-10-17 | Pins stand at New York Comic Con 2024 | Purchase |
82 | Kirby | 2024-10-17 | Pins stand at New York Comic Con 2024 | Purchase |
83 | Coraline | 2024-10-17 | Spooksieboo stand at New York Comic Con 2024 | Purchase |
84 | BFF Frog | 2024-10-17 | NYCC merch stand at New York Comic Con 2024 | Purchase |
85 | BFF Rat | 2024-10-17 | NYCC merch stand at New York Comic Con 2024 | Purchase |
86 | NYCC | 2024-10-17 | NYCC merch stand at New York Comic Con 2024 | Purchase |
87 | Ouroboros — Fullmetal Alchemist | 2024-10-26 | Online | Purchase |
88 | Greg — Over The Garden Wall | 2024-10-28 | Online | Purchase |
89 | Spectacle Logo | 2024-11-02 | Spectacle Theater in NYC | Purchase |
90 | Crash Bandicoot | 2024-12-10 | Uber ride headed to trampoline park in São Paulo | Gift (from Marianna) |
91 | Black Cat In Bucket | 2024-12-10 | Uber ride headed to trampoline park in São Paulo | Gift (from Marianna) |
92 | Zé Gotinha | 2025-01-12 | Tony’s home | Gift (from Tony) |
93 | Tudor Rose | 2025-01-18 | Tony’s home | Gift (from Tony) |
94 | Irmão Do Jorel | 2025-01-20 | Santa Hell store in Galeria do Rock in São Paulo | Purchase |
95 | Coco Mágico — Irmão do Jorel | 2025-01-20 | Santa Hell store in Galeria do Rock in São Paulo | Purchase |
96 | Mônica 1963 — Turma da Mônica | 2025-01-20 | Santa Hell store in Galeria do Rock in São Paulo | Purchase |
97 | Sansão — Turma da Mônica | 2025-01-20 | Santa Hell store in Galeria do Rock in São Paulo | Purchase |
98 | Ratinho — Castelo Rá Tim Bum | 2025-01-20 | Santa Hell store in Galeria do Rock in São Paulo | Purchase |
99 | Senta Que Lá Vem História — Castelo Rá Tim Bum | 2025-01-20 | Santa Hell store in Galeria do Rock in São Paulo | Purchase |
100 | Minhocão | 2025-01-20 | Santa Hell store in Galeria do Rock in São Paulo | Purchase |
101 | Liberdade | 2025-01-20 | Santa Hell store in Galeria do Rock in São Paulo | Purchase |
102 | Cavaquinho | 2025-01-20 | Santa Hell store in Galeria do Rock in São Paulo | Purchase |
103 | São Jorge | 2025-01-20 | Santa Hell store in Galeria do Rock in São Paulo | Purchase |
104 | Capivara | 2025-01-20 | Santa Hell store in Galeria do Rock in São Paulo | Purchase |
105 | Piso de Caquinho | 2025-01-20 | Santa Hell store in Galeria do Rock in São Paulo | Purchase |
106 | Lucky Cat | 2025-01-30 | Online | Purchase |
107 | Andorinha | 2025-01-30 | Online | Purchase |
108 | Fliperama | 2025-01-30 | Online | Purchase |
109 | Metrô SP | 2025-01-30 | Online | Purchase |
110 | Rua Augusta | 2025-01-30 | Online | Purchase |
111 | Bandeira Brasil | 2025-01-30 | Online | Purchase |
112 | Tv Cultura | 2025-02-02 | Street fair close to Av. Paulista in São Paulo | Purchase |
113 | Globo | 2025-02-02 | Street fair close to Av. Paulista in São Paulo | Purchase |
114 | Linux Conectiva | 2025-02-02 | Street fair close to Av. Paulista in São Paulo | Purchase |
115 | Windows 2000 | 2025-02-02 | Street fair close to Av. Paulista in São Paulo | Purchase |
116 | ABNT | 2025-02-02 | Street fair close to Av. Paulista in São Paulo | Purchase |
117 | Daft Punk | 2025-03-18 | Online | Purchase |
118 | Chrono Trigger | 2025-03-27 | Online | Purchase |
119 | Plumbob — The Sims | 2025-03-28 | Online | Purchase |
120 | Cardcaptor Sealing Key — Cardcaptor Sakura | 2025-03-28 | Online | Purchase |
121 | Triforce — Zelda | 2025-03-28 | Online | Purchase |
122 | Akatsuki — Naruto | 2025-03-28 | Online | Purchase |
123 | Klonoa | 2025-03-28 | Online | Purchase |
124 | Love From Wilmot — Wilmot’s Warehouse | 2025-04-26 | Online | Purchase |
125 | Usual June | 2025-04-26 | Online | Purchase |
126 | Hope Hammer — Godspeed You! Black Emperor | 2025-06-27 | Godspeed You Black Emperor show at District Music Hall in Norwalk, CT | Purchase |
127 | Javascript | 2025-08-07 | Astoria Tech Meetup meeting | Gift (from Tea) |
128 | Gomez — FEZ | 2025-08-09 | Long Island Retro Gaming Expo at Cradle of Aviation Museum | Purchase |
[*] The Collabora's Logo pin is not in the display since it's magnetic, but you can see it in the previous blog post.
The full spreadsheet wouldn't fit comfortably in this page, so the table above contains only the main columns. You can download the full spreadsheet from the link below which also includes the pin's authenticity, maker and additional comments:
2025-08-31 11:00:00
Just two days ago I went to an immersive theatrical experience called Viola's Room. It started in a girl's bedroom with dim lighting and a few beds made on the floor as in a sleepover. On the headphones, a beautiful song started playing. The moment was so magical it's hard to describe. I felt like a kid again for a second. And I knew I'd always remember this moment in the future (dès vu). If you have the chance to go, I deeply recommend it.
Anyway, the song that was playing, as I later found out, is my song of the month for August:
2025-08-12 11:00:00
Today I want to try starting something new. Every month I'll share one song that stood out to me throughout the month.
For this first one, even though it's already midway through August, I still really feel the need to share this song that has marked my days throughout July and even June. Many of my strolls around the city on sunny days have been accompanied by it, making it the hymn for this Summer to me.
Without further ado, my song of the month for July is:
2025-05-04 11:00:00
I've recently updated the blog's theme and I felt I should make a post not only to document the reason but also to archive pictures of the blog before and after the change for the future.
When I created this blog, I chose nikhil-theme as the theme because I found it minimalist and pretty. (Even prettier after I switched the fonts to be the same as the ones in the https://www.thirtythreeforty.net/ blog)
However, quite some time later as I was looking into the theme's template HTML files, I was surprised to discover that this very simple theme contained JavaScript. I tried loading the page with JavaScript removed and found that it was only required to get the hamburger menu to expand on mobile devices. That didn't sit well with me. A simple blog like this shouldn't require any JavaScript at all. And I found it even more annoying that it was only required because of one single feature.
At the time I had already been making other changes to the blog and was not looking forward to completely switching the theme, so this thought stayed in the back of my mind until recently, when I finally decided to do something about it.
In order to decide on the new theme for the blog, I started by looking through pelican-themes (the same place where I originally discovered nikhil-theme) but only found one or two themes that didn't use any JavaScript and they didn't really appeal to me.
Eventually I remembered about the seirdy.one blog. That's a blog I follow which has excellent write-ups, and there's a whole page about the design standards that the website adheres to. The standards focus on minimalism, compatibility and accessibility, which are all qualities that I would like for my blog, so I decided to adopt Seirdy's theme for my blog.
Looking through seirdy blog's source code I noticed it uses the Hugo static site generator whereas my blog uses pelican, so adapting this theme wouldn't be just a simple copy-paste.
Ideally I'd have gone through Seirdy's HTML templates and understood them all so I could adapt them to my HTML Jinja2 templates for pelican, but I honestly didn't have all that energy in me. So I went for the lazy solution: I copied over the CSS files and tweaked my templates until the website looked good enough. This means I'm probably not following many of Seirdy's standards, but at least the website is leaner, without any JS (and even external CSS), which was the main goal.
The resulting source code change can be seen in this commit (and also this and this for follow up fixes).
As for the resulting changes on the website itself, the pictures below show different pages before and after the theme change, respectively.
Home page:
A blog post:
Tags:
About:
I won't lie, I already feel nostalgic and a bit sad to see the old theme go, but I believe making the website more minimalist is worth it.
One thing lost in this transition was syntax highlighting for code snippets. I assume it's intentionally avoided by Seirdy due to accessibility concerns, but I should confirm that at some point and if it's not the case then consider adding it back.
Even though there are still a few details left to iron out, I'm quite happy with the change and particularly relieved there's no more JavaScript running when seeing this blog.
2024-11-16 11:00:00
Last year, on the "Collecting pins" post, I mentioned that I usually wear my pins on a beanie, but was still looking for a good alternative for the warmer months.
After thinking more about it, I realized a necklace would be the way to go. It doesn't depend on any specific piece of clothing and it's pretty visible, not only to others but also to myself.
I started researching for pin necklaces and found a few different solutions for the pin-to-necklace converter:
The guide is great, but I don't feel rubber pin backs are safe enough. And neither the plastic nor the leather converters looked good in my opinion. But the locking pin back one seemed perfect! So I ordered one right away.
Actually, I ordered two. The reason is that some pins have two posts, side-by-side, so two pin backs would be needed to keep those pins correctly oriented on the necklace (see pictures at the end). By buying two necklaces I could transfer the converter from one of them over and have a necklace with two converters, allowing me to wear any pin in my collection.
Once the necklace arrived and I started using it, I quickly realized there was a big problem with it though: the pin kept getting turned around! That totally beats the purpose of the necklace. I concluded the problem was the chain, which needed to be switched for something stiff, like a leather cord. I settled on this braided leather necklace (the 20inch in length and 3mm in diameter variant): https://www.amazon.com/Flexible-Braided-Leather-Necklace-Pendants/dp/B095W7J7D7
Once that arrived, I took two pliers, two jump rings (since the original ones wouldn't close around this broader necklace) and used them to put the two pin back converters on the new necklace. And it worked perfectly, no more pins getting turned around! I also liked the way it looked much better, the chain was too shiny and thin for my taste.
On top of that, since the jump rings I used are much broader than the necklace, it's super easy to get the pin back converters in and out of it. That way, when I'm wearing a pin that only uses one back, I take the other out so it's not dangling and making noise.
Finally, here are the pictures of the end result:
One-post pin:
Two-posts pin:
Pins being worn:
The only issue is that the one-post pins, like the Dwarf Fortress one above, always rest tilted to one side. I don't think there's a way to avoid that on a necklace though. In any case, that's a minor issue and I am incredibly happy with the result. I've been wearing pins everyday since!
2024-07-31 11:00:00
In the "CardOS: Writing an OS for the Cardputer" post I shared about the OS that I'm writing for the Cardputer and that the next step was to move away from the Arduino toolchain. It took me two months but I finally did it. The end product was this commit but I'd like to go over the process to get there in this post.
I started by running the Arduino commands to build and flash with verbose output enabled and saving that output for reference. This way I could see what exactly Arduino was doing and understand the steps needed to get from a source to a binary flashed to the chip's memory.
I then got to doing the obvious needed changes to convert from Arduino to C: I
renamed the single source of the project from cardOS.ino
to cardOS.c
,
changed the setup
and loop
functions into a main
function, and
changed the compilation step in my Makefile to rather than calling Arduino, call
the ESP32 C cross-compiler (xtensa-esp32s3-elf-gcc
), which had been
installed on my machine by Arduino and whose path I learned from Arduino's
output.
Next I ran the compilation, and fixed each of the errors that were thrown by the
compiler. Namely I had to add a few includes, function prototypes, change the
way a couple variables were defined and pass the -fno-builtin
flag to the
compiler so it would allow me to define my own stdlib functions. With that, I
had an ELF file and needed to figure out how to do the flashing.
From looking through Arduino's output, I learned that esptool.py
was the
command used to convert the ELF file into a binary, and then called again to
flash the binary into the chip. Besides the application code, there were other
things being flashed: a bootloader and a partition table. In order to keep
things simple, I did a quick test to verify whether I could ignore them for now
(that is, assume they were already flashed before): I tweaked the OS code and
used the Arduino toolchain to build and flash just that and the tweak showed up
on the Cardputer, so the answer was yes.
With that in mind, I updated the Makefile to call esptool.py
to convert the
ELF generated by the compiler and then flash it to the board. At this point I
had the whole procedure to get from the source to the flashed binary on the
board figured out (or so I thought), so I ran it with make upload
. But it
did not work, the screen on the cardputer just wouldn't turn on.
I realized assuming all the code would just work in the new setup was too
optimistic and decided to simplify the test as much as possible: I changed the
code in main
to simply drive the GPIO1 pin high and connected an LED to that
pin. But even then, the LED didn't turn on.
This is where I got stuck for a while. The issue was clearly somewhere in the application binary. My two main theories were that either the binary itself was malformed, or I was missing some initialization code, since Arduino included a bunch of extra files during compilation.
Hoping the issue was in the binary itself, since identifying missing initialization code from Arduino could take a while, I started investigating it.
I used readelf
to see the contents of both my ELF and the one generated by
Arduino and compared them. The biggest change in the header was this:
Mine:
Entry point address: 0x40017d
Arduino's:
Entry point address: 0x40376778
Arduino's ELF had much more code in it, so I expected its address to be higher, but this was too much of a difference. It looked like some base address was intentionally set to something different.
I looked up the meaning of the "Entry point address" in an ELF and confirmed that this is the address where execution starts from. So getting it wrong could definitely make my code not work at all.
Looking further through the ELF's content:
Mine:
Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000000 0x00400000 0x00400000 0x0183c 0x0183c R E 0x1000 LOAD 0x00183c 0x0040283c 0x0040283c 0x001a1 0x0075c RW 0x1000 Section to Segment mapping: Segment Sections... 00 .text .rodata .eh_frame 01 .ctors .dtors .data .bss
Arduino's:
Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x001020 0x3c000020 0x3c000020 0x2a678 0x2a678 RW 0x1000 LOAD 0x02c000 0x3fc88000 0x3fc88000 0x0c018 0x0d8a8 RW 0x1000 LOAD 0x039000 0x40374000 0x40374000 0x0ca97 0x0ca98 RWE 0x1000 LOAD 0x046020 0x42000020 0x42000020 0x1f347 0x1f347 R E 0x1000 LOAD 0x000000 0x50000000 0x50000000 0x00000 0x00010 RW 0x1000 Section to Segment mapping: Segment Sections... 00 .flash_rodata_dummy .flash.appdesc .flash.rodata 01 .dram0.dummy .dram0.data .dram0.bss 02 .iram0.vectors .iram0.text .iram0.data 03 .flash.text 04 .rtc_noinit
After reading up online about ELF program headers and sections this started making sense.
Looking at the program headers on the Arduino ELF, there is indeed an address
very close to the entry point address: 0x40374000
on segment 2. That is the
base address I was suspecting. The code that starts executing then must be in
the iram0.text
section, since sections with text
in the name represent
code, and that one is mapped to segment 2. The questions that come to mind are:
To answer the first question, I went looking in the ESP32-S3 manual. Figure
4-1 shows a diagram with how each memory range is mapped. The starting address
of the segment used for the entry point code in Arduino, 0x40374000
, is
inside the range 0x40370000 - 0x403dffff
which is shown as mapped to SRAM
through an instruction bus which totally makes sense!
But reading on, Table 4-1 further breaks down the memory regions and names
the region containing 0x40374000
as "Internal SRAM0". In its description, it
is mentioned the first 16KB of the space can be reserved as a cache for instructions
stored in the flash memory. If we do the math, that means the usable instruction
memory starts at... 0x40374000
, exactly the address that was used for the
code segment in Arduino's ELF! So that explains where this address came from.
To sum up, the problem I uncovered is that the ELF file I was generating had the code assigned to addresses that do not map to a memory region that can be accessed by the ESP32's processor to fetch instructions (ie accessible through an instruction bus) and therefore it couldn't be executed.
What was left was to answer the second question: How do I set the right address in my ELF file?
This was a big gap in my knowledge, I had no idea. But looking through Arduino's
output, I saw that the compiler was being passed some .ld
files through a
-T
parameter. Inside one of them called memory.ld
I found addresses
being defined! The -T
flag entry in the compiler's manual page revealed these
files were linker scripts, so I knew what I needed to learn about next.
I found this wonderful blog post about linker scripts that taught me
everything I needed to know. With that information I was able to write my linker
script to assign the right addresses to each ELF section: Not only for the code
(.text
), but also for the zero-initialized variables (.bss
) and other
variables (.data
), whose addresses I figured out similarly by referencing
the manual and the Arduino ELF. A few additional sections also had to be
assigned to get rid of linker errors.
As you might have noticed from the ELF contents, Arduino has two code sections,
iram0.text
and flash.text
, while I only have one, .text
. For that
reason, I decided to assign my .text
section to flash since it has much more
space. However, there was still no sign of life from the cardputer. Since I
noticed that my code was small enough to fit entirely inside the SRAM, and
Arduino's code started from SRAM, I decided to try that, and it worked!!
The ESP-IDF's application startup flow documentation describes what the second-stage bootloader (which is the one I'm relying on from Arduino) does and does not, and it mentions that it is the application's duty to finish setting up the flash MMU. That is probably why using the flash address for the code didn't work and why Arduino splits the code between an SRAM and a flash part. So at some point I will need to set up access to flash, but for now SRAM was enough.
Now that I had at least an LED turning on, I changed the code back to full operation, that is, initializing the display, rendering the shell and reading the keyboard.
The screen started getting cleared as usual but stopped midway. I removed the screen clearing routine temporarily and the shell prompt was written to the screen. I could type in, but after a short interval my position would go back to the intial one. I realized that the Cardputer was getting reset after a precise interval.
I remembered from the application startup flow documentation that the bootloader enabled the watchdog. And since now the application code was fully provided by me, I had to take care of it myself: either keep feeding the watchdog or disable it.
I chose to disable the watchdog for simplicity (as always), and after referencing the watchdog section in the ESP32-S3 manual and adding a few register writes to the code, it was done: the system no longer crashed. This allowed the shell to stay on screen but it was garbled:
Again, remembering from the application startup flow page, the application
code (me!) was responsible for initializing the .bss
section to zero. Since
the .bss
section contains the zero-initialized variables, if I don't
initialize it, those variables will contain trash, which is what I was seeing
here.
I didn't know how to do this the proper way, but I could definitely do it the dirty way, that is, manually listing all global variables in a function and zeroing them out 🙈. Which I did and it worked! (Note: I have figured out how to do it properly since and I did it in this commit)
Finally I had a working OS without needing Arduino to build! And that's the full story behind the "Move from Arduino to generic C build flow" commit.
There was still one difference from before the move though, it was much slower. That's because, for the last time referring back to the application startup flow page, the application is supposed to set the CPU clock frequency to the desired value. The default frequency is quite slow, but the startup code implicitly embedded by Arduino would set it to a higher value. I fixed that in a follow up commit.
With the move away from Arduino done, I was finally able to work on some much needed improvements.
The first thing I did was to split the monolithic source file into several different files in this commit. I was really looking forward to this and it felt great to finally do it 😌. Now the code is much more organized, it's easier to find things and to focus on a single component.
I also enabled all the main compiler warnings in this commit, including warning about implicit fallthrough in case switches, which would have saved me some minutes investigating a bug early in this project.
This was another great step for the project. I had a lot of fun and learned so much from it.
The next big thing to tackle is implementing SDcard read and write, and a file system. It will likely be a while before I get that done and come back with an update on the blog. Feel free to check the repository for the latest updates in the meantime if you're curious!