logo

drewdevault.com

[mirror] blog and personal website of Drew DeVault git clone https://hacktivis.me/git/mirror/drewdevault.com.git

KnightOS-was-interesting.md (4648B)


  1. ---
  2. date: 2020-01-27
  3. title: KnightOS was an interesting operating system
  4. layout: post
  5. tags: [knightos]
  6. ---
  7. [KnightOS](https://knightos.org) is an operating system I started writing about
  8. 10 years ago, for Texas Instruments line of z80 calculators — the TI-73,
  9. TI-83+, TI-84+, and similar calculators are supported. It still gets the rare
  10. improvements, but these days myself and most of the major contributors are just
  11. left with starry eyed empty promises to themselves that one day they'll do one
  12. of those big refactorings we've been planning... for 4 or 5 years now.
  13. Still, it was a really interesting operating system which was working under some
  14. challenging constraints, and overcame them to offer a rather nice Unix-like
  15. environment, with a filesystem, preemptive multiprocessing *and* multithreading,
  16. assembly and C programming environments, and more. The entire system was written
  17. in handwritten z80 assembly, almost 50,000 lines of it, on a compiler toolchain
  18. we built from scratch.
  19. There was only 64 KiB of usable RAM. The kernel stored *all* of its state in
  20. 1024 bytes of statically allocated RAM. Many subsystems used overlapping parts
  21. of this memory, which was carefully planned for to avoid conflicts. The
  22. userspace memory allocator used a simple linked list for tracking allocations,
  23. to minimize the overhead of each allocation and maximize the usable space for
  24. userspace programs. There was no MMU in the sense that we have on modern
  25. computers, so any program could freely overwrite any other programs. In fact,
  26. the "userspace" task switching GUI would read the kernel's process table
  27. directly to make a list of running programs.
  28. The non-volatile storage was NOR Flash, which presents some interesting
  29. constraints. In the worst case we only had 512 KiB of storage, and even in the
  30. best case just 4MiB (this for a device released in 2013). This space was shared
  31. with the kernel, whose core code was less than 4KiB, and including high-address
  32. subsystems still clocked in at less than 16KiB. Due to the constraints of NOR
  33. Flash, a custom filesystem was designed which did all daily operations by only
  34. *resetting* bits in the underlying storage. In order to *set* any bits, we had
  35. to set the entire 64 KiB sector to 1. Overhead was also kept to a bare minimum
  36. here to maximize storage space available to users.
  37. Writing to Flash storage also renders it unreadable while the operation is in
  38. progress. The kernel normally executes directly from Flash, resident at the
  39. bottom of the memory. Therefore, in order to modify Flash, the kernel's Flash
  40. driver copies part of itself to RAM, jumps to it, and then jumps back after the
  41. operation is complete. Recall that all of the kernel's memory is statically
  42. allocated, and there's not much of it — we used only 128 bytes for the
  43. code which runs in RAM, and it's shared with some other stuff that we had to
  44. plan around. In order to meet these constraints, we employ *self modifying code*
  45. — the Flash driver copies some of itself into RAM, then pre-computes some
  46. information and *modifies* that machine code in-place before jumping to it.
  47. We also had some basic networking support. The calculator has a 2.5mm jack,
  48. similar to headphone jacks — if you had a 3.5mm adapter, we had a music
  49. player which would play MIDI or WAV files. The kernel had direct control of the
  50. voltages on the ring and tip, and had to bitbang them directly in software[^1].
  51. Based on this we built some basic networking support, which supported
  52. calculator-to-calculator and calculator-to-PC information exchange. Later models
  53. had a mini-USB controller (which, funnily enough, can also be bitbanged in
  54. software), but we never ended up writing a driver for it.
  55. [^1]: Newer hardware revisions had some support hardware which was capable of transferring a single byte without software intervention.
  56. The KnightOS kernel also includes some code which is the first time I ever wrote
  57. ["here be dragons"](https://github.com/KnightOS/kernel/blob/e257f54e021ee743306a2a4a5a152860728fb3f8/src/00/restarts.asm#L129-L130)
  58. into a comment, and I don't think I've topped it since.
  59. Despite these constraints, KnightOS is completely booted up to a useful
  60. Unix-like (with a graphical interface) faster than you can lift your finger off
  61. of the power button. The battery could last the entire semester, if you're
  62. lucky. Can the device you're reading this on claim the same?[^2]
  63. [^2]: The device I'm writing this blog post with is 3500&times; faster than my calculator, has 262,144&times; more RAM, and 2.1×10<sup>6</sup> times more storage space.
  64. <video controls src="https://yukari.sr.ht/knightos.webm"></video>