doc: fix typos and inaccuracies

This commit is contained in:
Virgil Dupras 2020-09-19 09:04:18 -04:00
parent 4b1a49c8cc
commit 6d180f737a
5 changed files with 84 additions and 88 deletions

View File

@ -6,60 +6,53 @@ TODO
# Programming AVR chips
To program AVR chips, you need a device that provides the SPI protocol. The
device built in the rc2014/sdcard recipe fits the bill. Make sure you can
override the SPI clock because the system clock will be too fast for most AVR
chips, which are usually running at 1MHz. Because the SPI clock needs to be a
4th of that, a safe frequency for SPI communication would be 250kHz.
To program AVR chips, you need a device that provides the SPI
protocol. The device built in the rc2014/sdcard recipe fits the
bill. Make sure you can override the SPI clock because the sys-
tem clock will be too fast for most AVR chips, which are usually
running at 1MHz. Because the SPI clock needs to be a 4th of
that, a safe frequency for SPI communication would be 250kHz.
Because you will not be using your system clock, you'll also need to override
SPI_DELAY in your xcomp unit: the default value for this is 2 NOP, which only
works when you use the system clock.
Alternatively, you could run your whole system at 250kHz, but that's going to be
really slow.
The AVR programmer device is really simple: Wire SPI connections to proper AVR
pins as described in the MCU's datasheet. Note that this device will be the same
as the one you'll use for any modern SPI-based AVR programmer, with RESET
replacing SS.
(TODO: design a SPI relay that supports more than one device. At the time of
this writing, one has to disconnect the SD card reader before enabling the AVR
programmer)
The AVR programmer device is really simple: Wire SPI connections
to proper AVR pins as described in the MCU's datasheet. Note
that this device will be the same as the one you'll use for any
modern SPI-based AVR programmer, with RESET replacing SS.
The AVR programming code is at B690.
Before you begin programming the chip, the device must be deselected. Ensure
with "(spid)".
Before you begin programming the chip, the device must be desel-
ected. Ensure with "0 (spie)".
Then, you initiate programming mode with "asp$", and then issue your commands.
Then, you initiate programming mode with "asp$", and then issue
your commands.
Each command will verify that it's in sync, that is, that its 3rd exchange
echoes the byte that was sent in the 2nd exchange. If it doesn't, the command
aborts with "AVR err".
Each command will verify that it's in sync, that is, that its
3rd exchange echoes the byte that was sent in the 2nd exchange.
If it doesn't, the command aborts with "AVR err".
# Access fuses
You get/set they values with "aspfx@/aspfx!", x being one of "l" (low fuse),
"h" (high fuse), "e" (extended fuse).
You get/set they values with "aspfx@/aspfx!", x being one of "l"
(low fuse), "h" (high fuse), "e" (extended fuse).
# Access flash
Writing to AVR's flash is done in batch mode, page by page. To this end, the
chip has a buffer which is writable byte-by-byte.
Writing to AVR's flash is done in batch mode, page by page. To
this end, the chip has a buffer which is writable byte-by-byte.
Writing to the flash begins with a call to asperase, which erases the whole
chip. It seems possible to erase flash page-by-page through parallel
programming, but the SPI protocol doesn't expose it, we have to erase the whole
chip. Then, you write to the buffer using aspfb! and then write to a page using
aspfp!. Example to write 0x1234 to the first byte of the first page:
Writing to the flash begins with a call to asperase, which
erases the whole chip. It seems possible to erase flash page-by-
page through parallel programming, but the SPI protocol doesn't
expose it, we have to erase the whole chip. Then, you write to
the buffer using aspfb! and then write to a page using aspfp!.
Example to write 0x1234 to the first byte of the first page:
asperase 0x1234 0 aspfb! 0 aspfp!
Please note that aspfb! deals with *words*, not bytes. If, for example, you want
to hook it to A!*, make sure you use AMOVEW instead of AMOVE. You will need to
create a wrapper word around aspfb! that divides dst addr by 2 because AMOVEW
use byte-based addresses but aspfb! uses word-based ones. You also have to make
sure that A@* points to @ (or another word-based fetcher) instead of its default
value of C@.
Please note that aspfb! deals with *words*, not bytes. If, for
example, you want to hook it to A!*, make sure you use AMOVEW
instead of AMOVE. You will need to create a wrapper word around
aspfb! that divides dst addr by 2 because AMOVEW use byte-based
addresses but aspfb! uses word-based ones. You also have to make
sure that A@* points to @ (or another word-based fetcher)
instead of its default value of C@.

View File

@ -7,32 +7,32 @@ What is Collapse OS? It is a binary placed either in ROM on
in RAM by a bootloader. That binary, when executed, initializes
itself to a Forth interpreter. In most cases, that Forth
interpreter will have some access to a mass storage device,
which allows it to access Collapse OS' disk blocks and come
to this block to bootstrap itself some more.
which allows it to access Collapse OS' disk blocks and bootstrap
itself some more.
This binary can be separated in 5 distinct layers:
1. Boot code (B280)
2. Boot words (B305)
3. Core words (low) (B350)
4. Drivers
5. Core words (high)
1. Arch-specific boot code (B280 for Z80)
2. Arch-specific boot words (B305 for Z80)
3. Arch-independant core words (low) (B350)
4. Drivers, might contain arch-specific code
5. Arch-independant core words (high) (B380)
# Boot code (B280)
# Boot code
This part contains core routines that underpins Forth fundamen-
tal structures: dict navigation and search, PSP/RSP bounds
checks, word types.
tal structures: dict navigation and FIND, PSP/RSP bounds checks,
word types.
It also of course does core initialization: set RSP/PSP, HERE
CURRENT, then call BOOT.
It also contains what we call the "stable ABI" in its first
0x100 bytes. The beginning og the dict is intertwined in this
0x100 bytes. The beginning of the dict is intertwined in this
layer because EXIT, (br), (?br) and (loop) are part of the
stable ABI.
# Boot words (B305)
# Boot words
Then come the implementation of core Forth words in native
assembly. Performance is not Collapse OS' primary design goal,
@ -42,7 +42,7 @@ to implement our words in Forth.
However, some words are in this section for performance
reasons. Sometimes, the gain is too great to pass up.
# Core words (low) (B350)
# Core words (low)
Then comes the part where we begin defining words in Forth.
Core words are designed to be cross-compiled (B260), from a
@ -63,7 +63,7 @@ precisely to fit drivers in there. This way, they have access
to a pretty good vocabulary and they're also give the oppor-
tunity to provide (emit) and (key).
# Core words (high) (B350)
# Core words (high)
Then come EMIT, KEY and everything that depend on it, until
we have a full Forth interpreter. At the very end, we define
@ -82,7 +82,7 @@ new xcomp (cross compilation) unit. Let's look at its
anatomy. First, we have constants. Some of them are device-
specific, but some of them are always there. SYSVARS is the
address at which the RAM starts on the system. System variables
will go there and use 0x80 bytes. See B80.
will go there and use 0x80 bytes. See impl.txt.
HERESTART determines where... HERE is at startup. 0 means
"same as CURRENT".
@ -100,13 +100,10 @@ same way. Drivers are a bit tricker and machine specific. I
can't help you there, you'll have to use your wits.
After we've loaded the high part of the core words, we're at
the "wrapping up" part. We add what we call a "hook word" (an
empty word with a single letter name) which doesn't cost us
much and can be very useful if we need to augment the binary
with more words, and at that point we have our future boot
CURRENT, which PC yields. That is why we write it to the
LATEST field of the stable ABI: This value will be used at
boot.
the "wrapping up" part. We add what we call a "hook word", an
empty word with a single letter name. This allows us to boot
with CURRENT pointing to "source init" content rather than being
an actual wordref.
After the last word of the dictionary comes the "source init"
part. The boot sequence is designed to interpret whatever comes

View File

@ -19,7 +19,7 @@ ample, a machine with only a serial console can't.
# Block editor
The Block editor augments the built-in work LIST with words to
The Block editor augments the built-in word LIST with words to
modify the block currently being loaded. Block saving happens
automatically: Whenever you load a new block, the old block, if
changed, is saved to disk first. You can force that with FLUSH.
@ -37,6 +37,9 @@ You can insert text at the current position with "i". For exam-
ple, "i foo" inserts "foo" at cursor. Text to the right of it
is shifted right. Any content above 64 chars is lost.
Why "i" and not "I"? Because "I" is already used and we don't
want to overshadow it.
You can "put" a new line with "P". "P foo" will insert a new
line under the cursor and place "foo" on it. The last line of
the block is lost. "U" does the same thing, but on the line
@ -68,8 +71,7 @@ P xxx: put typed IBUF on selected line.
U xxx: insert typed IBUF on selected line.
F xxx: find typed FBUF in block, starting from current
position+1. If not found, don't move.
i xxx: insert typed IBUF at cursor. "i" is to avoid shadowing
core word "I".
i xxx: insert typed IBUF at cursor.
Y: Copy n characters after cursor into IBUF, n being length of
FBUF.
X ( n -- ): Delete X chars after cursor and place in IBUF.
@ -118,7 +120,8 @@ the previously opened block.
'w' moves forward by "modifier" words. 'b' moves backward.
'W' moves to end-of-word. 'B', backwards.
'I', 'F', 'Y', 'X' and 'E' invoke the corresponding command
'I', 'F', 'Y', 'X' and 'E' invoke the corresponding command from
command-based editor.
'o' inserts a blank line after the cursor. 'O', before.

View File

@ -168,33 +168,31 @@ territory, identical)
On boot, we jump to the "main" routine in B289 which does
very few things.
1. Set SP to PS_ADDR and IX to RS_ADDR
2. Sets HERE to SYSVARS+0x80.
3. Sets CURRENT to value of LATEST field in stable ABI.
1. Set SP to PS_ADDR and IX to RS_ADDR.
2. Set CURRENT to value of LATEST field in stable ABI.
3. Set HERE to HERESTART const if defined, to CURRENT other-
wise.
4. Execute the word referred to by 0x04 (BOOT) in stable ABI.
In a normal system, BOOT is in core words at B396 and does a
few things:
1. Initialize all overrides to 0.
2. Write LATEST in BOOT C< PTR ( see below )
3. Set "C<*", the word that C< calls to (boot<).
2. Write LATEST in BOOT C< PTR ( see below ).
3. Set "C<*", the word that C< calls, to (boot<).
4. Call INTERPRET which interprets boot source code until
ASCII EOT (4) is met. This usually init drivers.
ASCII EOT (4) is met. This usually initializes drivers.
5. Initialize rdln buffer, _sys entry (for EMPTY), prints
"CollapseOS" and then calls (main).
6. (main) interprets from rdln input (usually from KEY) until
EOT is met, then calls BYE.
In RAM-only environment, we will typically have a
"CURRENT @ HERE !" line during init to have HERE begin at the
end of the binary instead of RAMEND.
# Stable ABI
Across all architectures, some offset are referred to by off-
sets that don't change (well, not without some binary manipu-
lation). Here's the complete list of these references:
The Stable ABI lives at the beginning of the binary and prov-
ides a way for Collapse OS code to access values that would
otherwise be difficult to access. Here's the complete list of
these references:
04 BOOT addr 06 (uflw) addr 08 LATEST
13 (oflw) addr 2b (s) wordref 33 2>R wordref

View File

@ -24,7 +24,7 @@ a bit tight at first, having this limit saves us a non-
negligible amount of resource usage.
The reasoning behind this intentional limit is that huge
branches are generally a indicator that a logic ought to be
branches are generally an indicator that a logic ought to be
simplified. So here's one more constraint for you to help you
towards simplicity.
@ -41,9 +41,9 @@ from KEY, puts it in a buffer, then yields the buffered line,
one character at a time.
Both C< and KEY can be overridden by setting an alternate
routine at the proper RAM offset (see B80). For example, C<
overrides are used during LOAD so that input comes from
disk blocks instead of keyboard.
routine at the proper RAM offset (see impl.txt). For example,
C< overrides are used during LOAD so that input comes from disk
blocks instead of keyboard.
KEY overrides can be used to, for example, temporarily give
prompt control to a RS-232 device instead of the keyboard.
@ -108,8 +108,13 @@ try to strive towards a few goals:
1. Block 0 contains documentation discovery core keys to the
uninitiated.
2. First section (up to B100) is usage documentation.
3. B100-B200 are for runtime usage utilities
4. B200-B500 are for bootstrapping
2. B1-B4 are for a master index of blocks.
3. B5-B199 are for runtime usage utilities
4. B200-B599 are for bootstrapping
5. The rest is for recipes.
6. I'm not sure yet how I'll organize multiple arches.
Blocks are currently not organized neatly. I'm planning the
extraction of recipes into some kind of block "overlays" that
would live in the recipes subfolder so each recipe would build
its own specific blkfs which would contain only its recipe code,
starting at B600.