P2-ROM: Booter, Serial, Flash, SD card, Monitor and TAQOZ features and operation
Cluso99
Posts: 18,069
Final ROM code has been sent to OnSemi.
See the end posts for updates until I get time to edit these documents. In particular, note the List command uses "-" (dash) now and not "L".
P2 Vers "A" (internally 135k/136a)
TAQOZ documentation is here TAQOZ
Booter
This is the ROM boot code that runs when the P2 first boots, or is reset.
Boot Sequence
The SERIAL boot code has a number of features for downloading etc. These will be covered at a later time.
SERIAL has an "autobaud" feature which is invoked by the two character sequence "> ".
Once autobaud has established the baud rate, the user may enter TAQOZ or the Monitor...
<esc> (escape character $1B) will invoke TAQOZ
<Ctl-D> (eot character $04) will invoke the Monitor
You may switch between TAQOZ to the Monitor with <Ctl-D> and the Monitor to TAQOZ with <esc> followed by <cr> (escape $1B followed by carriage return $0D)
SD Boot
The SD boot will check for valid P2 Boot Data on the MBR sector (sector 0), and if not found it will try the VOL sector (provided the SD Card is in FAT32 format).
1. Valid Boot Data is "Prop" at offset $17C on the MBR/VOL sector...
The sector (512 bytes) will be read into Hub $0 and then copied into COG $0, followed by a JMP $020 in COG. Only code in sector byte offset $080-$17F is considered vaild but this program may know that other areas are also valid.
2. Valid Boot Data is "ProP" at offset $17C on the MBR/VOL sector...
The long at offset $174 is used as the sector start address, and the long at $178 is used as the filesize (in bytes) with a maximum of 512B-16KB = 496KB for the data to be loaded. This will then be treated as if a valid boot file on FAT32 were found and the files data loaded accordingly (see next step).
These two methods also cover the case where the SD Card is not formatted as FAT32 (eg exFAT). The boot sector(s) MBR and/or VOL must be specifically written with a program such as HxD on Windows 10.
If valid boot code is not found, and the SD Card is in FAT32 format, then the root directory is searched for file "_BOOT_P2.BIX", and if not found then the root directory is searched for file "_BOOT_P2.BIY" (upper case is required). If the file is found, then the files data is loaded into HUB $0 for the files size with a maximum of 512KB-16KB = 496KB. Once loaded into HUB, the first 496 longs will be copied to COG $0 and then a JMP #$0 will be executed.
Note: The files data must be in contiguous sectors.
MONITOR
The Monitor commands are covered in more detail in the following post(s).
See the end posts for updates until I get time to edit these documents. In particular, note the List command uses "-" (dash) now and not "L".
P2 Vers "A" (internally 135k/136a)
TAQOZ documentation is here TAQOZ
Booter
This is the ROM boot code that runs when the P2 first boots, or is reset.
Boot Sequence
SERIAL +-------------------------- P63 | RX P62 | TX +-------------------------- | FLASH SD +-------------------------- P61 | CSn CLK P60 | CLK CSn P59 | DI DI MOSI P58 | DO DO MISO ------------------------------------------------------------------- P61 P60 P59 P58 Sequence... (up=pullup, dn=pulldown) ------------------------------------------------------------------- x x up x 1. SERIAL up x x x 2. FLASH If Flash fails, goes to SERIAL x up x x 3. SD If SD fails/code missing, COGSTOP x x x x 4. SERIAL If 10s?? timeout, COGSTOP -------------------------------------------------------------------SERIAL Boot
The SERIAL boot code has a number of features for downloading etc. These will be covered at a later time.
SERIAL has an "autobaud" feature which is invoked by the two character sequence "> ".
Once autobaud has established the baud rate, the user may enter TAQOZ or the Monitor...
<esc> (escape character $1B) will invoke TAQOZ
<Ctl-D> (eot character $04) will invoke the Monitor
You may switch between TAQOZ to the Monitor with <Ctl-D> and the Monitor to TAQOZ with <esc> followed by <cr> (escape $1B followed by carriage return $0D)
SD Boot
The SD boot will check for valid P2 Boot Data on the MBR sector (sector 0), and if not found it will try the VOL sector (provided the SD Card is in FAT32 format).
1. Valid Boot Data is "Prop" at offset $17C on the MBR/VOL sector...
The sector (512 bytes) will be read into Hub $0 and then copied into COG $0, followed by a JMP $020 in COG. Only code in sector byte offset $080-$17F is considered vaild but this program may know that other areas are also valid.
2. Valid Boot Data is "ProP" at offset $17C on the MBR/VOL sector...
The long at offset $174 is used as the sector start address, and the long at $178 is used as the filesize (in bytes) with a maximum of 512B-16KB = 496KB for the data to be loaded. This will then be treated as if a valid boot file on FAT32 were found and the files data loaded accordingly (see next step).
These two methods also cover the case where the SD Card is not formatted as FAT32 (eg exFAT). The boot sector(s) MBR and/or VOL must be specifically written with a program such as HxD on Windows 10.
If valid boot code is not found, and the SD Card is in FAT32 format, then the root directory is searched for file "_BOOT_P2.BIX", and if not found then the root directory is searched for file "_BOOT_P2.BIY" (upper case is required). If the file is found, then the files data is loaded into HUB $0 for the files size with a maximum of 512KB-16KB = 496KB. Once loaded into HUB, the first 496 longs will be copied to COG $0 and then a JMP #$0 will be executed.
Note: The files data must be in contiguous sectors.
MONITOR
The Monitor commands are covered in more detail in the following post(s).
''----------------------------------------------------------------------------------------------- '' LMM DEBUGGER - SUPPORTED COMMANDS ''----------------------------------------------------------------------------------------------- '' xxxxxx - xx xx xx xx ... <cr> DOWNLOAD: to cog/lut/hub {addr1} following {byte(s)} '' xxxxxx [.yyyyyy] L <cr> LIST: from cog/lut/hub {addr1} to < {addr2} '' xxxxxx G <cr> GOTO: to cog/lut/hub {addr1} '' Q <cr> QUIT: Quit Rom Monitor and return to the User Program '' Rfilename.ext<cr> RUN: Run file from SD '' <esc><cr> TAQOZ: goto TAQOZ ''-----------------------------------------------------------------------------------------------
Comments
The Monitor has a series of commands that can be issued from a terminal program connected to the serial pins P62 and P63. The Monitor contains a number of "callable" routines that may also be called from a users program.
Commands are not case sensitive. The Monitor will always issue <cr><lf>. For PST, in Prefs... Function uncheck (10) = Line Feed. The Monitor uses a hub buffer of 80 characters starting at $0_2000. This may be changed if the user program calls the Monitor or its' commands.
List command
xxxxx . yyyyy L <cr> (spaces may be omitted)
The "xxxxx" is the "list from address". If the address is <$400 and <4 characters then a COG/LUT address is assumed, otherwise a HUB address is assumed. So for Hub $0 enter 0000 or 00000.
The "." and "yyyyy" represents the "list to address" and is optional. Rather than enter say 1FF, enter 200 and the list will stop at 1FF.
Here is an example
Download command
xxxxx - aa bb cc dd '....' <cr> (some spacing is critical to interpretation, others optional
The "xxxxx - " is the "download to address". If the address is <$400 and <4 characters then a COG/LUT address is assumed, otherwise a HUB address is assumed. So for Hub $0 enter 0000 or 00000. The "-" is required, but the spaces before and after are optional.
The "aa bb cc dd" (with spaces) are hex bytes to be stored in COG/LUT/HUB. Note the spaces define that bytes and will be loaded in sequence into COG/LUT/HUB. If "aabbccdd" (without spaces) then they would be stored as a long into COG/LUT/HUB (reversed to little endian). As an example try "000- 11 22 33 44 55667788 <cr>" and then list with "000L<cr>" or "L<cr>".
The " '...' " is ignored. Note: If ascii follows the bytes it is essential that they be escaped by the single quote character!
The Download format is designed to use the same format as output by the Monitor and by pnut using Ctl_M. I have asked Chip to change pnut to escape/enclose the ascii text within single quotes.
Goto command
xxxxx G <cr> (spaces may be omitted)
The "xxxxx" is the "go to address". If the address is <$400 then a COG/LUT address is assumed, otherwise a HUB address is assumed. A "JUMP" to this address is executed. Note Hub addresses $00000-$003FF are invalid as code cannot execute (hubexec) in the lower 4KB of HUB RAM.
Note: If "FC000 G <cr>" is entered, then this is a special case (the Booter start address) and is handled by executing a COGINIT #0, ##$FC000.
Run file command
R <filename> <cr> (where <filename> is a filename in the format 8.3 as used in FAT32
The <filename> is searched for in the root directory of a FAT32 formatted Sd card. If the SD card does not exist (no pullup on P60), or the card is not formatted correctly, or the file is not found, then the Monitor will display "!" and reissue the prompt "*" character. Note in some circumstances the timeout may take up to 10 seconds, depending on the type of failure.
Note: The filenames searched in the SD Booter are, in order of the search, "_BOOT_P2.BIX" and "_BOOT_P2.BIY" and are case sensitive (ie use capitals).
Quit command
Q <cr> (spaces may be omitted)
The Quit command is designed to return to a user calling program. When run from the SERIAL booter or from TAQOZ, the Monitor will recall itself.
To call routines in the Monitor (ie like a ROM BIOS), the Monitor Routines all run as hubexec in HUB ROM space.The following resources are required...
Internal Stack
The internal 8 deep stack is used. The user will be using 1 level in the CALL #@xxxx instruction.
COG $1E0..$1EF are required for the Monitor's Variables
The caller will utilise lmm_x..lmm_c to pass/receive variables
HUB RX Buffer
A hub buffer in HUB RAM of length 80 characters is required to receive the character string with _HubRxString and/or _HubMonitor. The default is HUB $02000 and can be changed by the user by setting lmm_bufad and using a different call. If you don't use the receiver, then this buffer is not required.
AFAIK no other user resources are used.
The "callable routines" are described in the following post(s).
Constant definitions required for supporting the Monitor calls are...
Note: Where multiple CALL entry points are provided, the top call will fall into the next call which will fall into the next, and so on. This routine is required to be run before using any of the Monitor Routines. It sets up the Serial UART ready for use.
Three alternate entry points are provided. They permit the user to use the default Hub Buffer (re receiving serial strings) and the default baud (rate) which will is preset to 115,200 baud at 200MHz. You will most likely need to provide the baud setting.
This routine will CALL the _HubRxStrMon routine, which will use the default _HubBuf hub buffer at $0_2000. To provide your own hub buffer, set lmm_bufad to your hub buffer address before calling this routine.
Note: Where multiple CALL entry points are provided, the top call will fall into the next call which will fall into the next, and so on. Load lmm_x with the char(s) you wish to transmit, and call _HubTx.
Note that you may send up to 4 characters in lmm_x. The lowest byte is sent first, then shifted out. If lmm_x then is all zeros the call returns. Otherwise another byte is sent and the process repeated. To send a $00 byte, set lmm_x=$0. Only one $00 byte will be sent.
The additional calls allow for auto-setting lmm_x to cr+lf, and for reversing the lmm_x value.
These calls display (output) the long in lmm_x in HEX format. The main call _HubHex requires a function (options) parameter to be passed in lmm_f. The additional calls negate this requirement by providing common calls for 8 digits and reverse. The reverse parameter is useful for little/big endian differences.
The Hub String must be zero (NULL) terminated. Upon return, lmm_p will point to the byte following the zero/null, permitting another call to display another following string.
These calls display a list (dump) of COG/LUT/HUB RAM/ROM. Each line displays 16 sets of Hex Bytes followed by the ASCII equivalent (bytes <$20 or >$7E are displayed as "."). An entry call _HubListA2H is provided for the most common call, which provides a from address in lmm_p and a to address in lmm_p2, a heading. This saves the caller from setting lmm_f. When this routine(s) return, lmm_f will have +_HDG turned off.
Note: For the List function to determine the difference from $000..$3FF for COG/LUT or HUB, a trick is used by the caller to fool the list code to force Hub $000..$3FF. This is done by making both lmm_p and lmm_p2 addresses >1MB. The easiest way for this is to set b20=1 on both lmm_p and lmm_p2 since this bit is ignored in addresses.
Note: Where multiple CALL entry points are provided, the top call will fall into the next call which will fall into the next, and so on. This call waits for a character to be received, and returns it in lmm_x.
This call receives a string of up to 78 characters. Backspace is supported to edit the buffer. A carriage return (enter) is required to terminate the operators entry, and the routine will terminate the string with a $00 (NULL). The routine can echo received characters back to the operator using the +_ECHO_ option in lmm_f. Line feed can be stripped from the input string using +_NOLF option, but note that if +_ECHO_ is in use, a carriage return echoed will be followed by a line feed. The routine(s) require a buffer of 80 bytes in Hub RAM. The user may set lmm_p with option lmm_f=+_ADDR to use an alternate hub address. The default is _HUBBUF which has been defined in ROM to be $0_2000. The alternate entry point provides for a prompt "*" to be sent prior to reading the string, but note this will use the default Hub Buffer! To override, set lmm_bufad before calling.
This routine is used by the Monitor to decode the input buffer to obtain the next hex address from the hub buffer.
COG $1C0..$1DF are required for SD Variables
The routine below may be called by a user program. It is also an example of how a user may call the routines directly. Below is the actual code that the above routine executes. Note: the user must have preset fname[3] in COG to the filename in 8+3 format without the "." This routine above takes an 11 character (8+3) filename passed in fname, fname+1 and fname+2 (space filled without ".") in cog memory, and
1. Initialises the SD Card
2. Reads the MBR/VOL/FSI/FAT
3. Searches the FAT32 root directory for a filename passed in fname/fname+1/fname+2, and if found
4. Reads the file's data for the file's length to a maximum of 512KB-16KB = 496KB, and
5. Copies the lower 496 longs to COG $0, and then executes a JMP #$0
If the card is not present, or the card did not initialise, or the file is not found, then this routine will return to the calling program.
This routine above continues the SD setup, reading and validation the MBR, VOL, FSI and FAT sectors. If the calling program set skiploading = #1 then P2 Boot Code on sectors MBR/VOL will not be checked or loaded. If skiploading = #0 and the P2 Boot Code is present on MBR or VOL, then it will be loaded and executed. See above post(s) for further information. A return of "Z indicates success and "NZ" indicates failure. Remember, a successful load of SD Boot Code will not return here.
This routine above takes a filename in COG registers fname[3] and searches the FAT32 directory for the 8+3 filename entry. If found, the start sector and filesize (bytes) is set ready to load/run. A"Z" will be returned if the file is found, otherwise "NZ"is returned.
This routine above loads and runs a <filename> previously located using the native sector and file size. It will return "NZ" only on an error.
That would allow to not just run programs, but also load data-files like tables, screen-images or other blocks into the HUB.
Is there maybe space and time to add 'writeFile' with HUB address and length?
great Job,
Mike
There is no writeFile capability and there is no space for it. In reality, there isn't any real support for FAT32.
I have thought about putting write sector back in but I don't think there is enough space for it.
In reality though, since code can be loaded, support routines for FAT32 including writeFILE can easily be added to upper Hub RAM.
This is what I also said to Peter when he was trying to squeeze full SD support into TAQOZ.
I know it's not in ROM which would be nicer.
Of course, with SD booting, a new TAQOZ (with more features) can be loaded, and we can overwrite that area in ROM with the remainder to support FAT32 files, and lots more.
What would be nicer is if we could pass TAQOZ commands (a 1 liner) to execute. It's probably possible. Peter?
The readFILE routine can read from a given sector for any length (trimmed to 496KB max) into any given hub address.
The low level bit-bash SPI routine supports writing, so it's not difficult to add writing a sector(s).
EDIT: This should be as simple as changing Cluso's SD booter so that after it loads the MBR and sees that it's TAQOZ bytecode, it sets a flag and then jumps to TAQOZ. When TAQOZ starts, it would check this flag and run the loaded MBR if it's set, and otherwise doing what it normally does on start if it's not set.
TAQOZ uses wordcode which is more efficient than bytecode for larger programs as 16-bits can address more memory directly and also encode jumps and short literals.
However, these wordcodes are meant to be run from a TAQOZ resident in the the first 64k since it needs to be extensible and new code, even temporary one-liners need to go into hub memory somewhere.
I don't agree with the rationale of limiting everything to the MBR simply because of a rare exception as SD cards preformatted with FAT32 have several MBs free before the start of the FAT32 partition. As for cards above 32GB that are preformatted in exFat I would simply reformat them to FAT32 thank you very much.
Be aware though that simply formatting cards in most OS's results in no free space before the FAT32 partition so you need to use a proper SD card format utility that takes into account how SD cards should be handled.
I guess not. And the SD loader loads from HUB 0 to whatever, overwriting the space needed by TAQPZ.
Can one boot from serial, flash or sd, leaving space for TAQOZ at the beginning of the HUB and then call a ROM routine to copy and start TAQOZ just using one or two COGs?
I still would like to have a co-existence between my code in some COGs and TAQOZ in some other COGs.
Or can TAQOZ use Cluso99s debugger to load a file and stay alive?
So does TAQOZ need to start all COGs and if so why?
Mike
Since you can load code from the SD (or Flash or Serial), you have control of the P2 to with what you like. The code that gets loaded can copy itself to somewhere else, or load more/new code to anywhere, and run whatever. It's all just code. The routines in ROM are there to help, but whether you use them or not is up to you.
What the ROM TAQOZ & Monitor provide, is a way to play with P2 by just using serial and without even downloading anything. As an addition to this, at least the Monitor and SD provide call-able routines to enhance a users program by providing a BIOS-like set of routines.
If you have an SD, then it's more likely that you will download a better version of TAQOZ with more feature that couldn't be squeezed into the ROM.
could you some how separate the R command into
load to start address
and
run from address?
so one could load different blocks of HUB memory from file within the debugger without starting anything?
and then start some address in HUBEXEC?
Mike
1. You can use search_dir routine to locate the file and its first sector and length
2. You can give the read sector routine a sector address and a hub address, and then call the routine to read the sector.
You will have to cater for the length in your code, which is just a simple counter.
3. You can then either jump directly or use the monitor to do a G command.
Having said all that, you can basically do what you want. You will just have to set some registers with the values, and then run some routines. But the Monitor doesn't have a CALL, only a GOTO
Postedit:
Provided it fits, next version will use a call instead of a jump for "G".
Command changes
"-" --> ":" after address for listing/downloading memory
"." --> "-" for memory listing range {addr} - {addr2} M [L]
"L" & "LM" --> "M" & "ML" for Memory Long
<cr> alone on line will continue last Memory list command
R<filename> --> L<filename> for Load filename, don't run (returns "=" if loaded ok, else "!")
X<filename> --> R<filename> for Load & Run filename (returns "!" if error)
TAQOZ also uses ":" after address for dumping memory
The list memory no longer uses "L" or "M" as the list/memory identifier, but uses the "-" to trigger the list memory function. So these are valid (<cr> omitted for simplicity)...
-
xxx-
xxxxx-
xxxxx-yyyyy
Appending "L" uses "L"ong format.
xxx is a cog/lut start address if < 4 hex digits, else Hub
yyyyy is an optional end address (Hub determined by start address)
Any subsequent <cr> only commands will continue listing, repeating the list command with incremented addresses. So
000-0080L
will list cog $000-$07F.
<cr> will list cog $080-$0FF, and so on.
Remember, all these Commands can be called (CALL) from your user program. If you call the Monitor, then return using the "Q" command. If you call a routine directly (eg List) then after it's done the routine will RET to your user program.
I've attached the boot file which works with Flash removed. Just rename to suit but it runs the earlier version of TAQOZ in 32k of RAM which boots straight up at 115200 baud at 80MHz.
Actually it would be nice to have a boot text file that holds the name of the file to actually use for booting. So the SD booter reads this file first and determines which file to load and to where or how etc. _BOOT_P2.TXT could then be edited very easily plus it could have a description and clock frequency and so on in there. Is it too late to consider this?
I can jump to the SD boot code if SPI fails and there's a pull-up on P60. This means, though, that there won't be a chance to download to SPI flash unless either the SD card is removed or a pull-up is placed on P59.
Yes, we could call it 'config.sys' just for example or 'autoexec.fth'.
Running a short Forth or debugger? script to set up clock-speed, pin-modes and then start something.
Mike
Wait! Cluso's booter will jump back to my code on failure, so we WILL have a chance for serial if SD boot fails. All is good. The faster Cluso's booter resolves whether or not it has a valid image, the better.
But the way it is now is that if I do have boot Flash and boot SD (that is on the boot pins) but I'm not using Flash for booting then it will not boot SD if I am using it for booting. Anyway, I'm making other test jigs to investigate all this as a fast reliable and predictable end-mode boot is in my best interest. It seems this stuff is only being tested for bench use but it has to be production grade and serial boot doesn't come into it once it is off the test bench out in service.