💾 Archived View for gemini.sensorstation.co › ~winduptoy › project.x.log.gmi captured on 2023-07-10 at 13:24:17. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-06-14)

➡️ Next capture (2023-07-22)

🚧 View Differences

-=-=-=-=-=-=-

project x

I'm finally at the point in my life and career where I can set down the typical grind work and pursue something really unique, something that really pushes my limits and creativity, something that when I look at even now I think "there's no way I'll ever be smart enough to pull that off." I currently struggle to see a future for myself with much fulfillment if I were to follow a safer career path.

2023-07-07

began manually testing words in the debugger from the beginning.

issue 1: gdb is unaware of the assembly source for any section that isn't text. adding the "x" flag (executable) to the section definition (e.g. `.section .dictionary "ax"`) makes gdb aware of the source when stepping through the debugger.

issue 2: naming symbols in the linker script with a dot (or matching the name of a section) cause them to have the incorrect value. maybe because it uses the end of the section as the value.

/* WRONG */
.data : ALIGN(4) {
	.data = .;
	*(.data*)
	.data_end = .;
} > SRAM AT> FLASH

`.data` has the expected value when running `objdump -x`, but I think that it's getting overridden by the section name.

/* RIGHT */
.data : ALIGN(4) {
	_data = .;
	*(.data*)
	_data_end = .;
} > SRAM AT> FLASH

`_data` has the expected value.

issue 3: modifying a symbol across multiple translation units is causing issues. it seems that the linker can't take a symbol for the end of the dictionary in the core TU and allow a secondary TU to build off it and move the dictionary head pointer further. i solved this by creating a "unity build" where the platform assembly entrypoint just includes the core content.

2023-07-05

finished initial pass of DOES>.

tried to start manually testing everything in the debugger, but ran into an issue where the chip would reset immediately and just mount over USB to accept a new firmware image. spent a while trying to track that down, thinking it was something to do with the OpenOCD/gdb setup. turns out I had an output section in my ELF file that was not marked as "ALLOC" (gnu assembler `.section name, "a"`) and therefore the linker allowed another section to overlap at the same address. this was the bootloader section, so it was just producing garbage.

ran into the next issue where symbols didn't have the expected value. in the linker script:

/* WRONG */
.data : ALIGN(4) {
	.data = .;
	*(.data*)
	.data_end = .;
	.data_len = SIZEOF(.data);
} > SRAM AT> FLASH

.data_len has a value equal to .data_end (???). the solution turned out to be moving it outside of the section block:

/* RIGHT */
.data : ALIGN(4) {
	.data = .;
	*(.data*)
	.data_end = .;
} > SRAM AT> FLASH
.data_len = SIZEOF(.data);

2023-07-04

started implementation of DOES>.

2023-07-03

implemented /MOD.

2023-06-30

implemented NUMBER.

2023-06-27

took a little time off to make a little money. started hacking again today. made good progress on INTERPRET and getting to the point to start compiling words. next step is to start copying inline code or branching to regular words, then write a number/digit interpreter.

2023-06-20

implemented CREATE.

2023-06-19

finished WORD and implemented FIND.

2023-06-16

started implementing WORD. thinking about linker organization and how to get static forth code burned to flash and then executed on boot.

when running objdump I see that some sections aren't incrementing the VMA. I had to add the "a" attribute (allocatable). would be nice if there was a way to do this in the linker script rather than the assembly.

2023-06-15

wrote copy routines, more cleanup. broke open the stage 2 bootloader to see how it worked.

2023-06-14

received my hardware today. set up OpenOCD and got it talking to the debugger after a few hiccups. spent a lot of time getting burned by another Thumb™ crash when the LSB is not set.

.section .text
.global myfunc

// ---- HERE! ---------
// The assembler doesn't set the LSB when referencing this
// label without this directive
.type myfunc, %function
// --------------------
myfunc:
	movs r0, 42
	...

tried loading a PC-relative value and then jumping over that value (when not using static pools) to discover that PC is current instruction + 4 when word-aligned and current instruction + 6 otherwise (Thumb).

2023-06-12

started thinking about how to encode pushing literal values onto the stack.

tried the following simulators to execute armv6m instructions with no luck. they either fail to compile or vomit on the assembly I throw at them. I've tried everything on Google/GitHub and I'm stunned that I can't get any of them to work. makes me wonder why ARM doesn't supply an official simulator; maybe to sell more hardware dev kits.

at the end of the day I just gave up and ordered some hardware. luckily the RP2040 and Pico Debug Probe are cheap.

2023-06-09

validated bl instruction encoding (33 instructions!) using cemu. not beautiful but it got the job done. implemented encoding of 32-bit literals into dictionary definitions (loading forward in memory, pushing to stack, and then jumping over the literal).

2023-06-08

started implementation of offset-to-bl-instruction encoding. investigating a faster-simpler armv6-m emulator that supports Thumb 2.

2023-06-07

working on moving to a subroutine threaded forth. inlining code into a definition is straightforward, but encoding a call to each subroutine seems to be tricky because with Thumb instructions you can't just put a 32-bit address down and jump to it. You can either `ldr` it from a static pool somewhere (slow), mash one together with a bunch of `mov`s and shifting (lame), or `bl` to a PC-relative address. opting for the latter, ARM's encoding scheme is a lot more complicated than just [opcode][offset]! so while trying to decipher this with a test case, I ran a disassembly on an object file with `objdump -D`. after tedious bit manipulation and head scratching, I realized that the offset in a `bl` instruction is meaningless until after it's linked. wasted a few hours on that one. all good now though: the PC is assumed to be AFTER the 32-bit `bl` instruction.

2023-06-06

refamiliarized myself with the JonesForth code. decided to move to a subroutine threaded forth after reading Brad Rodriguez's "Making Forth."

2023-06-05

just finished reading Starting Forth and Thinking Forth.

I spent the last few days documenting the memory layout I expect the system to have and the interaction among the core forth systems (dictionary, scheduler). I think this will help me pick a target for what to work on next rather than just opening the text editor and making a guess every day.

I used Richard Hipp's awesome pikchr tool to create inline diagrams.

previous work

april 2023

I spent a few weeks getting the Unicorn emulator up and running in a python environment. the python version is easy to install with pip, but has slower than expected execution. I suspect there's a high cost of crossing the C/Python barrier to run memory callbacks.

july 2022

I experimented and built the core of JonesForth, translating from x86 to ARM as I went. it accepts input over UART, although waiting in a busy loop so it's not pretty. things I learned during this period: