Shop OBEX P1 Docs P2 Docs Learn Events
P2-ROM: Booter, Serial, Flash, SD card, Monitor and TAQOZ features and operation — Parallax Forums

P2-ROM: Booter, Serial, Flash, SD card, Monitor and TAQOZ features and operation

Cluso99Cluso99 Posts: 18,066
edited 2018-05-29 16:29 in Propeller 2
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
       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
''-----------------------------------------------------------------------------------------------

«134

Comments

  • Cluso99Cluso99 Posts: 18,066
    edited 2018-05-17 05:27
    MONITOR

    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
    *000.010L
     addr-  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
    ------------------------------------------------------
      000- 00 08 80 FF 3F 00 0C FC 32 B6 06 F6 1F 04 DC FC  '....?...2.......'
      004- 40 7E 74 FD 01 B8 A6 F0 1F B8 26 F4 00 B8 62 FD  '@~t.......&...b.'
      008- FA B7 6E FB 3F 00 0C FC 28 B2 64 FD E0 07 00 FF  '..n.?...(.d.....'
      00C- 3C 01 06 FB 29 58 65 FD E1 07 00 FF A4 20 04 FB  '<...)Xe...... ..'
    

    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.
  • Cluso99Cluso99 Posts: 18,066
    edited 2018-05-17 08:57
    Reserved for calling the monitor commands from a user program...

    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
    ''============[ COG VARIABLES - MONITOR]========================================
                    org     $1E0              ' place the variables in cog $1E0-$1EF
    ''-------[ LMM parameters, etc ]------------------------------------------------
    lmm_x           res     1       ' parameter passed to/from LMM routine (typically a value)
    lmm_f           res     1       ' parameter passed to      LMM routine (function options; returns unchanged)
    lmm_p           res     1       ' parameter passed to/from LMM routine (typically a hub/cog ptr/addr)
    lmm_p2          res     1       ' parameter passed to/from LMM routine (typically a 2nd hub/cog address)
    lmm_c           res     1       ' parameter passed to/from LMM routine (typically a count)
    ''-------[ LMM additional workareas ]-------------------------------------------
    lmm_w           res     1       ' workarea (never saved - short term use between calls, except _HubTx)
    lmm_tx          res     1       ' _HubTx
    lmm_hx          res     1       ' _HubHex/_HubString
    lmm_hx2         res     1       ' _HubHex
    lmm_hc          res     1       '   "
    lmm_lx          res     1       ' _HubList
    lmm_lf          res     1       '   "
    lmm_lp          res     1       '   "
    lmm_lp2         res     1       '   "
    lmm_lc          res     1       '   "
    lmm_bufad       res     1       ' _HubRxString
                    fit     $1F0
    ''=======[ ^^^^^ End of COG 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...
    ''-----------------------------------------------------------------------------------------------
    ''              LMM DEBUGGER - CALL Modes...(not all modes supported)
    ''-----------------------------------------------------------------------------------------------
      _MODE         = $F << 5                       ' mode bits defining the call b8..b5 (b4..b0 are modifier options)
      _SHIFT        = 5                             ' shr # to extract mode bits
      _HEX_         = 2 << 5                        ' hex...
        _REV_               = 1 << 4                '   - reverse byte order
        _SP                 = 1 << 3                '   - space between hex output pairs
       '_DIGITS             = 7..0 where 8->0       '   - no. of digits to display
      _LIST         = 3 << 5                        ' LIST memory line (1/4 longs) from cog/hub
        _ADDR2              = 1 << 4                ' 1= use lmm_p2 as to-address
        _HDG                = 1 << 2                ' 1=display heading for opcode format
      _TXSTRING     = 4 << 5                        ' tx string (nul terminated) from hub
      _RXSTRING     = 5 << 5                        ' rx string
        _ECHO_              = 1 << 4                '    - echo char
        _PROMPT             = 1 << 3                '    - prompt (lmm_x)
        _ADDR               = 1 << 2                '    - addr of string buffer supplied
        _NOLF               = 1 << 1                '    - strip <lf>
      _MONITOR      = 7 << 5                        ' goto rom monitor
    '------------------------------------------------------------------------------------------------
    
  • Cluso99Cluso99 Posts: 18,066
    edited 2018-05-17 08:00
    User "CALLABLE" Monitor Routines

    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.
    ''-------[ Serial Routines (uses SmartPins) ]---------------------------------- <--- serial initialise --->
    ''_SerialInit
    '' On Entry:
    ''      lmm_x     = _bitper                             ' tx & rx bit period + #(bits-1)
    ''      lmm_bufad = 'bufad'                             ' hubbuf addr for use by _HubRxString
    '' Call Format:
    ''            CALL      #@_SerialAddr                   ' use default _HUBBUF   < call: serial initilise> 
    ''            CALL      #@_SerialBaud                   ' use default _bitper   < call: serial initilise> 
    ''            CALL      #@_SerialInit                   ' provide addr & baud   < call: serial initilise>
    '' On Return:
    ''      lmm_x = #CR                                     ' (changed)
    ''--------------------------------------------------------------------------------------------------
    
    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.
    ''-------[ Monitor: DebugMonitor]---------------------------------------------- <--- monitor/debug --->
    ''_HubMonitor
    ''      lmm_bufad = 'bufad'                             ' hubbuf addr for use by _HubRxString
    '' Call Format:                                         '
    ''            CALL      #@_HubMonitor                   '                       < call: monitor/debug>
    ''--------------------------------------------------------------------------------------------------
    
    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.
  • Cluso99Cluso99 Posts: 18,066
    edited 2018-05-17 08:02
    User "CALLABLE" Monitor Routines - Transmit (output)

    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.
    ''-------[ Display Char(s) ]--------------------------------------------------- <--- display char(s) --->
    ''_HubTx                                                '
    '' On Entry:
    ''      lmm_x = char(s)                                 ' char(s): up to 4 chars; B0 first; <nul> terminates
    ''                                                      '            if =$0, tx one <nul>
    '' Call Format:
    ''            CALL      #@_HubTxCR                      ' preloads cr+lf        < call: display char(s)>
    ''            CALL      #@_HubTxRev                     ' reverses lmm_x        < call: display char(s)>
    ''            CALL      #@_HubTx                        '                       < call: display char(s)>
    '' On Return:
    ''      lmm_x = -same-                                  ' char(s):  (unchanged)
    ''--------------------------------------------------------------------------------------------------
    
    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.
    ''-------[ Display Hex ]------------------------------------------------------- <--- display hex --->
    ''_HubHex                                               '
    '' On Entry:
    ''      lmm_f = _HEX_ [+options]                        ' mode:  #_HEX_[+_REV_][+_SP][+_ndigits]
    ''                                                      '        'n' digits = 7..0 where 0 = 8 digits
    ''      lmm_x = char(s)                                 ' char(s):
    '' Call Format:
    ''            CALL      #@_HubHexRev                    ' reverse lmm_x         < call: display hex >
    ''            CALL      #@_HubHex8                      ' hex 8 digits          < call: display hex >
    ''            CALL      #@_HubHex                       '                       < call: display hex >
    '' On Return:
    ''      lmm_f = -same-                                  ' mode:     (unchanged)
    ''      lmm_x = -same-                                  ' char(s):  (unchanged)
    ''--------------------------------------------------------------------------------------------------
    
    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.
    ''-------[ Display String, <nul> terminated ]---------------------------------- <--- display string --->
    ''_HubTxString                                          '
    '' On Entry:
    ''      lmm_p = 'addr'                                  ' addr:   string (hub ptr)
    '' Call Format:
    ''            CALL      #@_HubTxStrVer                  ' display version       < call: display string>
    ''            CALL      #@_HubTxString                  '                       < call: display string>
    '' On Return:
    ''      lmm_p = 'addr' (next string)                    ' addr:   (hub ptr to next string)
    ''--------------------------------------------------------------------------------------------------
    
    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.
    ''-------[ LIST a line ]------------------------------------------------------- <--- LIST a line --->
    ''_HubList
    '' On Entry:
    ''      lmm_f   = #_LIST [+options]                     ' mode:         _LIST[+_ADDR2][+_HDG]
    ''      lmm_p   = 'addr'        (from)                  ' addr:    from cog addr / hub ptr
    ''      lmm_p2  = 'addr2'       (to)    (optional)      ' addr2:   to   cog addr / hub ptr (if _ADDR2 specified)
    '' Call Format:
    ''             CALL     #@_HubListA2H                    ' _LIST+_ADDR2+_HDG     < call: LIST a line >
    ''             CALL     #@_HubList                       '                       < call: LIST a line >
    '' On Return:
    ''      lmm_f   = same except _HDG off                  ' mode:    same except _HDG will be off
    ''      lmm_p   = addr++        (from)                  ' addr:    next from cog addr / hub ptr
    ''      lmm_p2  = addr2++/same  (to)                    ' addr2:   next to addr -OR- unchanged
    ''---------------------------------------------------------------------------------------------------
    
    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.

  • Cluso99Cluso99 Posts: 18,066
    edited 2018-05-17 08:03
    User "CALLABLE" Monitor Routines - Receive (input)

    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.
    ''-------[ Rx: Receive a char ]------------------------------------------------ <--- receive char --->
    ''_HubRx
    '' On Entry:
    ''      lmm_x = -anything-                              ' value:
    '' Call Format:
    ''             CALL     #@_HubRx                        '                       < call: receive char>
    '' On Return:
    ''      lmm_x = char                                    ' char:   input char
    ''--------------------------------------------------------------------------------------------------
    _HubRx                                                  '                       <--- receive char --->
    .recv           testp   #rx_pin                 wc      ' char ready?
            if_nc   jmp     #.recv                          '
                    rdpin   lmm_x,            #rx_pin       ' recv byte (bits31:24) from rx pin
                    shr     lmm_x,            #24           ' shift rx bits
                  RET                               wcz     '                       <--- return to calling routine --->
    '---------------------------------------------------------------------------------------------------
    
    This call waits for a character to be received, and returns it in lmm_x.
    ''-------[ Receive String ]---------------------------------------------------- <--- receive string --->
    ''_HubRxString
    '' On Entry:
    ''      lmm_f = #_RXSTRING [+options]                   ' mode:   #_RXSTRING[+_ECHO_][+_PROMPT][+_ADDR][+_NOLF]
    ''      lmm_x = char(s)                 (optional)      ' prompt: char(s)
    ''      lmm_p = 'bufad'                 (optional)      ' addr:   input string (hub ptr)
    ''      lmm_bufad = 'bufad'             (default)       ' addr:   input string (hub ptr)
    '' Call Format:
    ''            CALL      #@_HubRxStrMon                  ' presets lmm_x & lmm_f < call: receive string >
    ''            CALL      #@_HubRxString                  '                       < call: receive string >
    '' On Return:
    ''      lmm_f = -same-                                  ' mode:   (unchanged)
    ''      lmm_x = -same-                                  '
    ''      lmm_p = 'addr'                                  ' addr:   input string (hub ptr)
    ''      lmm_c = 'count'                                 ' count:  char(s) entered (incl <cr>, excl <nul>)
    ''--------------------------------------------------------------------------------------------------
    
    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.
  • Cluso99Cluso99 Posts: 18,066
    edited 2018-05-17 08:18
    User "CALLABLE" Monitor Routines - Miscellaneous
    ''-------[ Read Cog/Lut/Hub Long ]--------------------------------------------- <--- read: cog/lut/hub long --->
    ''_RdLongCogHub
    '' On Entry:
    ''      lmm_x   = -anything-                            ' 'long':
    ''      lmm_p   = 'addr'                                ' 'addr':  cog/lut addr / hub ptr
    '' Call Format:
    ''              CALL    #@_RdLongCogHub                 '                       < call: read cog/lut/hub long >
    '' On Return:
    ''      lmm_x   = 'long'                                ' 'long':  read from cog/hub
    ''      lmm_p   = 'addr++'                              ' 'addr++' cog/lut addr++ / hub ptr++
    '---------------------------------------------------------------------------------------------------
    
    This routine returns a long from the address in lmm_p, with lmm_p correctly incremented. For lower hub addresses, set b20=1 for hub addresses.
    ''-------[ Parse hex input ]--------------------------------------------------- <--- parse hex input --->
    ''_ParseHex
    '' On Entry:
    ''      lmm_x   = -anything-/'hex'                      ' 'hex':   ---/prev hex value
    ''      lmm_c   = -anything-/'count'                    ' 'count': ---/prev count
    ''      lmm_p   = 'addr'                                ' 'addr':  ptr to string (hub)
    ''      lmm_w   = -anything-                            '
    '' Call Format:
    ''             CALL     #@_ParseHex                     '                       < call: parse hex >
    '' On Return:
    ''      lmm_x   = 'hex'                                 ' 'hex':   hex value
    ''      lmm_c   = 'count'                               ' 'count': of hex digits
    ''      lmm_p   = 'addr++'                              ' 'addr':  ptr past next non-hex char
    ''      lmm_w   = 'ucase'                               ' 'ucase': next non-hex char in ucase
    ''--------------------------------------------------------------------------------------------------
    
    This routine is used by the Monitor to decode the input buffer to obtain the next hex address from the hub buffer.
  • Cluso99Cluso99 Posts: 18,066
    edited 2018-05-17 09:14
    User "CALLABLE" SD Routines

    COG $1C0..$1DF are required for SD Variables
    ''============[ COG VARIABLES - SD BOOT]========================================
                    org     $1C0              ' place the variables in cog $1C0-$1DF
    
    cmdout          res     1                       ' The 8b CMDxx | $40
    cmdpar          res     1                       ' The 32b parameters
    cmdcrc          res     1                       ' The 8b CRC (must be valid for CMD0 & CMD8)
    cmdpar2         res     1                       ' SDV1=$0, SDV2=$40000000
    cmdtype         res     1                       ' reply is R1=1, R3=3, R7=7, else 0
    reply           res     1                       ' R1 reply (moved to replyR1 when R3/R7 32b reply here)
    replyR1         res     1                       ' R1 reply (8b saved when R3/R7 32b reply follows)
    dataout         res     1                       ' 8/32 bit data being shifted out
    bytescnt        res     1                       ' #bytes to send/recv
    bitscnt         res     1                       ' #bits to be shifted in/out
    ctr1            res     1
    starttime       res     1
    duration        res     1
    skiploading     res     1
                                                    '\ 1=SDV1, 2=SDV2(byte address), 3=SDHC/SDV2(block address)
    blocksh         res     1                       '/ block shift 0/9 bits
    
    vol_begin       res     1 '$0000_2000           ' Ptn0: first sector of PTN
    fsi_begin       res     1 '$0000_2001           ' Ptn0:       sector of file system info
    fat_begin       res     1 '$0000_3122           ' Ptn0: first sector of FAT table
    dir_begin       res     1' $0000_4000           ' Ptn0: first sector of DATA is DIR table
    dat_begin       res     1 '$0000_4580 $0000_54C0' Ptn0: first sector of file's DATA
    ptn_size        res     1 '$0008_0000           '       file-size 32KB = 64<<9 sectors
    
    _bufad          res     1
    _blocknr        res     1
    _sectors        res     1
    _entries        res     1
    bufad           res     1                       ' ptr sector buffer
    blocknr         res     1                       ' sector#
    fname           res     3                       ' 8+3+1
    _unused         res     2
                    fit     $1E0
    
  • Cluso99Cluso99 Posts: 18,066
    edited 2018-05-17 10:47
    User "CALLABLE" SD Routines
    The routine below may be called by a user program. It is also an example of how a user may call the routines directly.
    ''-------[ SD: Initialise/Locate/Load/Run a file from SD ]--------------------- <--- SD: init/locate/load/run a file --->
    '' On Entry:
    ''      fname[3]:       filename[11] 8+3 without "." 
    '' Call Format:
    ''              CALL    #@_Run_SDfile                   '                       < call: init/locate/load/run a file >
    '' On Return:
    ''      "NZ" if error, else does not return
    ''------------------------------------------------------------------------------
    
    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 "."
    _Run_SDfile     call    #@_SDcard_Init                  ' initialise & read CSD/CID
                    mov     skiploading,      #1            ' do not load MBR/VOL code
            if_e    call    #@readMBR                       ' read MBR/VOL/FSI/FAT
            if_e    call    #@search_dir                    ' search dir for <fname>
            if_e    call    #@readFILE                      ' read/load/run the file
                    RET                           ' failed: return to Caller
    
    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.

  • Cluso99Cluso99 Posts: 18,066
    edited 2018-05-17 10:31
    User "CALLABLE" SD Routines
    ''-------[ SD Card Initialisation ]-------------------------------------------- <--- SD initialisation --->
    '' On Entry:
    '' Call Format:
    ''              CALL    #@_SDcard_Init                  '                       < call: sd initialise >
    '' On Return:
    ''      hub $0   = CSD[16] + CID[16]                    ' csd/cid data
    ''      Returns  "Z" if ok, "NZ" if error
    ''------------------------------------------------------------------------------
    
    This routine above initialises the card and reads the CSD and CID registers into hub $0[32]. It will return "Z" if successful, else "NZ".
    ''-------[ SD: Read MBR/VBR/FSI/FAT ]------------------------------------------ <--- SD: read mbr/vol/fsi/fat --->
    '' On Entry:
    ''      skiploading:    #0 = load/run boot code if found on MBR/VOL
    ''                      #1 = do not load/run boot code on MBR/VOL
    '' Call Format:
    ''              CALL    #@readMBR                       '                       < call: read mbr/vol/fsi/fat >
    '' On Return:
    ''      DOES NOT RETURN if skiploading = #0 and code found on MBR/VOL
    ''      Returns: "Z" if ok, "NZ" if error
    ''------------------------------------------------------------------------------
    
    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.
    ''-------[ SD: Search Root Directory ]----------------------------------------- <--- SD: search root directory --->
    '' On Entry:
    ''      fname[3]:       filename[11] 8+3 without "." 
    '' Call Format:
    ''              CALL    #@search_dir                    '                       < call: search root directory >
    '' On Return:
    ''      Returns:  dat_begin = first native sector of file's data
    ''                _sectors  = file size in bytes
    ''                "Z" if file located and set to load, else "NZ" if error
    ''------------------------------------------------------------------------------
    
    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.
    ''-------[ SD: Read File ]----------------------------------------------------- <--- SD: load/run file --->
    '' On Entry:
    ''      dat_begin = first native sector of file's data
    ''      _sectors  = file size in bytes
    '' Call Format:
    ''              CALL    #@readFILE                      '                       < call: load/run file >
    '' On Return:
    ''      "NZ" if error, else does not return
    ''------------------------------------------------------------------------------
    
    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.
  • Thanks for the docs on both TAQOZ and your monitor!
  • msrobotsmsrobots Posts: 3,701
    edited 2018-05-17 16:03
    It would be very nice if the 'readFile' routine had a parameter to provide a HUB address to load to and a 'skipRun' Flag for just loading a file, but not running it.

    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
  • Cluso99Cluso99 Posts: 18,066
    msrobots wrote: »
    It would be very nice if the 'readFile' routine had a parameter to provide a HUB address to load to and a 'skipRun' Flag for just loading a file, but not running it.

    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
    Actually you can override where the readFile data will go.
    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?
  • Cluso99Cluso99 Posts: 18,066
    It is possible to read any SD sector into anywhere in hub by setting these values in the cog variables and calling the lower level SD Routine(s) (which I haven't described). The various sector addresses of the FAT table, etc are available in those cog variables.
    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).
  • The monitor looks very nice. I think that having this (and TAQOZ) in ROM will make developing for P2 a lot easier!
  • ElectrodudeElectrodude Posts: 1,614
    edited 2018-05-18 02:57
    Is there any way to automatically load and run TAQOZ bytecode out of the MBR? Since bytecode is denser than PASM, this would allow more to be done with the limited space in the MBR.

    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.
  • Is there any way to automatically load and run TAQOZ bytecode out of the MBR? Since bytecode is denser than PASM, this would allow more to be done with the limited space in the MBR.

    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.


    467 x 124 - 7K
  • msrobotsmsrobots Posts: 3,701
    edited 2018-05-18 03:36
    Does TAQOZ look for a start-script on the SD while booting?

    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
  • Cluso99Cluso99 Posts: 18,066
    msrobots,
    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.
  • Cluso99Cluso99 Posts: 18,066
    edited 2018-05-21 06:12
    Here is a list of entry-points in ROM (FPGA v32f v138PJB) for many of the Monitor & SD Routines..
    CON
      _Start_SDcard    = $fc558    
      _Run_SDfile      = $fc570    
      _SDcard_Init     = $fc588    
      readMBR          = $fc6b4    
      readFILE         = $fc84c    
      search_dir       = $fc890    
      _reset_booter    = $fca58    
      _Start_Monitor   = $fca68    
      _Enter_Monitor   = $fca6c    
      _Redo_Monitor    = $fca7c    
      _SerialAddr      = $fca88    
      _SerialBaud      = $fca90    
      _SerialInit      = $fca98    
      _HubTxCR         = $fcac4    
      _HubTxRev        = $fcacc    
      _HubTx           = $fcad0    
      _HubRx           = $fcaf0    
      _HubHexRev       = $fcb04    
      _HubHex8         = $fcb08    
      _HubHex          = $fcb0c    
      _HubTxStrVer     = $fcb7c    
      _HubTxString     = $fcb84    
      _HubListA2H      = $fcba4    
      _HubList         = $fcba8    
      _RdLongCogHub    = $fccb0    
      _HubRxStrMon     = $fcce4    
      _HubRxString     = $fccec    
      _HubMonitor      = $fcd98    
      _Download        = $fceac    
      _ParseHex        = $fcf3c    
    
  • Clusso99,

    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
  • Cluso99Cluso99 Posts: 18,066
    edited 2018-05-21 08:32
    You will need to do a small piece of your own code to...

    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".
  • Cluso99Cluso99 Posts: 18,066
    edited 2018-05-24 03:06
    A few changes to the above. I will edit later.

    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

  • Cluso99Cluso99 Posts: 18,066
    Changed commands again...
    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.
  • If I leave my Flash plugged-in and a boot file on the SD card I find it won't boot the SD even though there isn't anything on the Flash. Evem when I go to TAQOZ and execute a "SFERASE" to erase the whole chip back to $FFs and hit the reset it still doesn't boot automatically. Only after I have removed the Flash does the SD boot on reset.

    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?
  • cgraceycgracey Posts: 14,131
    edited 2018-05-27 23:44
    If I leave my Flash plugged-in and a boot file on the SD card I find it won't boot the SD even though there isn't anything on the Flash. Evem when I go to TAQOZ and execute a "SFERASE" to erase the whole chip back to $FFs and hit the reset it still doesn't boot automatically. Only after I have removed the Flash does the SD boot on reset.

    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.
  • ...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?

    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

  • cgraceycgracey Posts: 14,131
    cgracey wrote: »
    If I leave my Flash plugged-in and a boot file on the SD card I find it won't boot the SD even though there isn't anything on the Flash. Evem when I go to TAQOZ and execute a "SFERASE" to erase the whole chip back to $FFs and hit the reset it still doesn't boot automatically. Only after I have removed the Flash does the SD boot on reset.

    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.

    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.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2018-05-28 03:26
    cgracey wrote: »
    cgracey wrote: »
    If I leave my Flash plugged-in and a boot file on the SD card I find it won't boot the SD even though there isn't anything on the Flash. Evem when I go to TAQOZ and execute a "SFERASE" to erase the whole chip back to $FFs and hit the reset it still doesn't boot automatically. Only after I have removed the Flash does the SD boot on reset.

    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.

    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.

  • cgraceycgracey Posts: 14,131
    Peter, I just sent you a slightly modified version of my booter which now checks for SD card on SPI flash failure, giving SD a chance when SPI is present without boot code. It takes just two more instructions.
  • Ok, thanks Chip. I've hooked up a buffer chip to my breakout to buffer the SD signals since the LA appears as a pull-down otherwise and checking some odd SD boot signals. But I will load your code into my include folder since is now so easy to assemble them together from individual files.
Sign In or Register to comment.