Shop OBEX P1 Docs P2 Docs Learn Events
P2 ROM Monitor/Debugger (rev 1 & rev 2 silicon) — Parallax Forums

P2 ROM Monitor/Debugger (rev 1 & rev 2 silicon)

Cluso99Cluso99 Posts: 18,069
edited 2021-08-04 12:59 in Propeller 2
P2 Monitor/Debugger
The Monitor/Debugger is loaded into the top 16KB of HUB RAM from the internal serial ROM by the booter software. The Monitor/Debugger code occupies HUB $FCA78-$FD025 inclusive (1454 bytes).
The Monitor/Debugger, along with TAQOZ and the autobaud booter, are all resident in HUB after power-up. Only an external serial terminal connected to Pins 63(in) and 62(out) is necessary to invoke the Monitor/Debugger or TAQOZ.
The Monitor/Debugger can be entered directly from power-up via the two character Serial autobaud sequence “> “ followed by Ctl-D. The Monitor/Debugger uses the serial connection via P63(in) and P62(out). The Monitor/Debugger supports the following commands at the input prompt…
---------------------------------------------------------------------------------------------
LMM DEBUGGER - SUPPORTED COMMANDS (Rev 1 & 2 silicon)
---------------------------------------------------------------------------------------------
xxxxxx : xx xx xx xx ... <cr>  DOWNLOAD:  to   cog/lut/hub {addr1} following {byte(s)}
xxxxxx - [xxxxxx] [L] <cr>     MEM LIST:  from cog/lut/hub {addr1} to < {addr2}  L=longs
xxxxxx G <cr>                  GOTO:      to   cog/lut/hub {addr1}
Q <cr>                         QUIT:      Quit Rom Monitor and return to the User Program
                                             {addr} is on the stack
Lfilename.xxx<cr>              LOAD:      Load file from SD   (8.3 filename)
                                             returns "=" on success, "!" on failure
Rfilename.xxx<cr>              RUN:       Run  file from SD   (8.3 filename)
                                             returns "!" on failure
<esc><cr>                      TAQOZ:     goto TAQOZ
<cr>                                      will repeat last MEM LIST command
---------------------------------------------------------------------------------------------
Note: COG/LUT addresses are 3 digits or less and <$3FF, otherwise hub address is presumed. 
To list a low Hub address below $400, use a leading zero. (When calling from a user program use $1x_xxxx as only the lower 20 address bits are used)

Calling the Monitor/Debugger from User Programs
The Monitor/Debugger is callable from a users’ program.
The Monitor/Debugger Routines are also callable from a users’ program.
COG & HUB RAM Usage by the Debugger/Monitor
The Monitor/Debugger uses COG RAM $1E0-$1EF for variables.
The Receive String routines use HUB RAM $FC000-$FC04F as the input buffer unless lmm_bufad is initialised to point to a different HUB RAM address. Note: This buffer overwrites the booter code!

Below is a list of Routines that may be called by a user’s program…
--------------------------------------------------------------------------------------------
LMM DEBUGGER - Routines callable from users' programs
--------------------------------------------------------------------------------------------
_SerialInit   = $fcab8 'Serial Initialise     (lmm_x & lmm_bufad must be set first)
_HubTxCR      = $fcae4 'Sends <cr><lf>        (overwrites lmm_x)
_HubTxRev     = $fcaec 'Sends lmm_x with bytes reversed
_HubTx        = $fcaf0 'Sends lmm_x           (can be up to 4 bytes)
_HubHexRev    = $fcb24 'Sends lmm_x with bytes reversed as Hex char(s) as defined in lmm_f
_HubHex8      = $fcb28 'Sends lmm_x as Hex char(s) after setting lmm_f as 8 hex chars
_HubHex       = $fcb2c 'Sends lmm_x as Hex char(s) as defined in lmm_f
_HubTxStrVer  = $fcb9c 'Sends hub $0 terminated string at lmm_p address 
                           after setting lmm_p=##_str_vers
_HubTxString  = $fcba4 'Sends hub $0 terminated string at lmm_p address
_HubListA2H   = $fcbc4 'List/Dump line(s) from lmm_p address to lmm_p2 address 
                           after setting lmm_f=#_LIST+_ADDR2 
_HubList      = $fcbc8 'List/Dump line(s) from lmm_p address to lmm_p2 address 
                           according to lmm_f
_HubRx        = $fcb10 'Recv char into lmm_x
_HubRxStrMon  = $fccc4 'Recv string into hub address pointed to by lmm_bufad after setting 
                           prompt=lmm_x=#"*" & params=lmm_f=#_RXSTRING+_ECHO_+_PROMPT
_HubRxString  = $fcccc 'Recv string into hub address pointed to by lmm_p/lmm_bufad 
                           according to params in lmm_f
_HubMonitor   = $fcd78 'Calls the Monitor; uses lmm_bufad as the input buffer address
_RdLongCogHub = $fcf34 'read cog/lut/hub long from lmm_p address into lmm_x, then lmm_p++
_str_vers     = $fd014 'locn of the monitors hub string, $0 terminated
--------------------------------------------------------------------------------------------
  _HUBROM     = $FC000 'ROM $FC000
  _HUBBUF     = $FC000 'use as RxString buffer    (overwrites Booter)
  _HUBBUFSIZE = 80     'default size for _HUBBUF  (can be 128)
--------------------------------------------------------------------------------------------

Below is a list of the COG RAM variables and their usage…
--------------------------------------------------------------------------------------------
LMM DEBUGGER - COG VARIABLES $1E0-$1EF
-------[ LMM parameters, etc ]--------------------------------------------------------------
lmm_x     = $1e0 'parameter passed to/from LMM routine (typically a value)
lmm_f     = $1e1 'parameter passed to      LMM routine (function options; returns unchanged)
lmm_p     = $1e2 'parameter passed to/from LMM routine (typically a hub/cog ptr/addr)
lmm_p2    = $1e3 'parameter passed to/from LMM routine (typically a 2nd hub/cog address)
lmm_c     = $1e4 'parameter passed to/from LMM routine (typically a count)
-------[ LMM additional workareas ]-------------------------------------------
lmm_w     = $1e5 'workarea (never saved - short term use between calls, except _HubTx)
lmm_tx    = $1e6 '_HubTx
lmm_hx    = $1e7 '_HubHex/_HubString
lmm_hx2   = $1e8 '_HubHex
lmm_hc    = $1e9 '  "
lmm_lx    = $1ea '_HubList
lmm_lf    = $1eb '  "
lmm_lp    = $1ec '  "
lmm_lp2   = $1ed '  "
lmm_lc    = $1ee '  "
lmm_bufad = $1ef '_HubRxString
--------------------------------------------------------------------------------------------

The following are values passed in lmm_f for HEX, LIST and RXSTRING calls…
--------------------------------------------------------------------------------------------
LMM DEBUGGER - lmm_f CALL Modes...(b4..b0 are modifier options)
--------------------------------------------------------------------------------------------
_HEX_     = 2 << 5   ' hex...
  _REV_    = 1 << 4  '   - reverse byte order
  _SP      = 1 << 3  '   - space between hex output pairs
 '_DIGITS  = 7..0    ' no. of digits to display where 0 is 8 digits
_LIST     = 3 << 5   ' LIST memory line (1/4 longs) from cog/hub
  _ADDR2   = 1 << 4  '  1= use lmm_p2 as to-address
  _LONG_   = 1 << 1  '  1=display longs xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
_RXSTRING = 5 << 5   ' RXSTRING...
  _ECHO_   = 1 << 4  '    - echo char
  _PROMPT  = 1 << 3  '    - prompt (lmm_x)
  _ADDR    = 1 << 2  '    - addr of string buffer supplied
  _NOLF    = 1 << 1  '    - strip <lf>
--------------------------------------------------------------------------------------------

Note: The use of the lmm_ prefix is a carry over from when I first wrote the Monitor/Debugger way back in 2013. This was intended for the original P2 design which did not support HUBEXEC. So I used the LMM model as originally defined by Bill Henning. LMM stands for Large Memory Model, where a tiny routine in COG fetches each instruction from HUB and executes it in COG.

Comments

  • Cluso99Cluso99 Posts: 18,069
    edited 2019-10-21 08:48
    Monitor/Debugger - COG Variables (for use in your program(s) as res or equ
    ''============[ 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
    
    -OR-
    ''============[ COG VARIABLES $1E0-$1EF - MONITOR]=============================
    ''-------[ LMM parameters, etc ]-----------------------------------------------
      lmm_x         = $1e0          ' parameter passed to/from LMM routine (typically a value)
      lmm_f         = $1e1          ' parameter passed to      LMM routine (function options; returns unchanged)
      lmm_p         = $1e2          ' parameter passed to/from LMM routine (typically a hub/cog ptr/addr)
      lmm_p2        = $1e3          ' parameter passed to/from LMM routine (typically a 2nd hub/cog address)
      lmm_c         = $1e4          ' parameter passed to/from LMM routine (typically a count)
    ''-------[ LMM additional workareas ]------------------------------------------
      lmm_w         = $1e5          ' workarea (never saved - short term use between calls, except _HubTx)
      lmm_tx        = $1e6          ' _HubTx
      lmm_hx        = $1e7          ' _HubHex/_HubString
      lmm_hx2       = $1e8          ' _HubHex
      lmm_hc        = $1e9          '   "
      lmm_lx        = $1ea          ' _HubList
      lmm_lf        = $1eb          '   "
      lmm_lp        = $1ec          '   "
      lmm_lp2       = $1ed          '   "
      lmm_lc        = $1ee          '   "
      lmm_bufad     = $1ef          ' _HubRxString
    '' +--------------------------------------------------------------------------+
    '' ASCII equates
    '' +--------------------------------------------------------------------------+
      _CLS_         = $0C     
      _BS_          = $08
      _LF_          = $0A
      _CR_          = $0D
      _TAQOZ_       = $1B           ' <esc>   goto TAQOZ
    '' +--------------------------------------------------------------------------+
    
  • Cluso99Cluso99 Posts: 18,069
    Code examples to go here
  • Cluso99Cluso99 Posts: 18,069
    The first post has been updated with a description of the Monitor/Debugger.
  • evanhevanh Posts: 15,912
    Thanks Cluso. Add it to your sticky links.
  • I was wondering how to enter the monitor, all this time. So, in short, right at boot:
    - [>][ ][Esc] to enter TAQOZ
    - [>][ ][Ctrl + D] to enter P2 Monitor

    Thanks, Cluso! It worked.

    Kind regards, Samuel Lourenço
  • Cluso99,
    Please point me to an example of a call to _SerialInit and a description of the contents of lmm_x for that call. I plan to use _SerialInit, _HubTx, and _HubRx from Spin. Any suggestion or "gotcha"s.
    Mike
  • Cluso99Cluso99 Posts: 18,069
    Mike Green wrote: »
    Cluso99,
    Please point me to an example of a call to _SerialInit and a description of the contents of lmm_x for that call. I plan to use _SerialInit, _HubTx, and _HubRx from Spin. Any suggestion or "gotcha"s.
    Mike
    I posted an example over on this thread
    forums.parallax.com/discussion/comment/1494072/#Comment_1494072
    BUT then started getting weird results. Turns out spin2 uses the registers (lmm_x etc) that the ROM code uses :(
  • Cluso99Cluso99 Posts: 18,069
    Here is how you can call the ROM Monitor (Serial) from Spin2.
    Warning: The ROM Monitor uses registers $1E0-$1EF which is also used by Spin2. Therefore, it is suggested you call the ROM Monitor/Debugger as a one-way event ie do not return to your spin2 code from the monitor

    Once in the monitor, the usual monitor features are available eg examine/modify cog/lut/hub memory.
    CON
      _BAUD         = 115_200
      _bitper       = (_clkfreq / _BAUD) << 16 + 7                  ' 115200 baud, 8 bits
    
    PUB xyz()
        .....
        REG[$1EF] := $FC000                                 ' locn of hub buffer for serial routine
        REG[$1E0] := _bitper                                ' sets serial baud
        CALL($FCAB8)                                        ' ROM: _SerialInit
        CALL($FCB9C)                                        ' ROM: _HubTxStrVer (not necessary)
        CALL($fcd78)                                        ' ROM: _HubMonitor
    
  • Cluso99 wrote: »
    Here is how you can call the ROM Monitor (Serial) from Spin2.
    Warning: The ROM Monitor uses registers $1E0-$1EF which is also used by Spin2. Therefore, it is suggested you call the ROM Monitor/Debugger as a one-way event ie do not return to your spin2 code from the monitor

    Once in the monitor, the usual monitor features are available eg examine/modify cog/lut/hub memory.
    CON
      _BAUD         = 115_200
      _bitper       = (_clkfreq / _BAUD) << 16 + 7                  ' 115200 baud, 8 bits
    
    PUB xyz()
        .....
        REG[$1EF] := $FC000                                 ' locn of hub buffer for serial routine
        REG[$1E0] := _bitper                                ' sets serial baud
        CALL($FCAB8)                                        ' ROM: _SerialInit
        CALL($FCB9C)                                        ' ROM: _HubTxStrVer (not necessary)
        CALL($fcd78)                                        ' ROM: _HubMonitor
    

    Putting this together with what Chip suggested, couldn't you copy $1E0-$1EF to a buffer somewhere before calling the ROM Monitor/Debugger, and then return to a stub that copies the saved content back to $1E0-$1EF before returning to Spin2?

    Perhaps a 16 word buffer declared in HUBRAM with a SETQ WRLONG combo to save and a SETQ RDLONG combo to restore.
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-04-20 08:25
    @AJL,
    Have to get something working first!

    I had embarked on using the Tx and TxString etc, but something was slightly messing up the results whereupon Chip said they were used by spin2. Been trying ever since to get something working reliably.
  • Cluso99 wrote: »
    @AJL,
    Have to get something working first!

    I had embarked on using the Tx and TxString etc, but something was slightly messing up the results whereupon Chip said they were used by spin2. Been trying ever since to get something working reliably.

    Ok. I was thinking that if you were to save the contentious range before monitor and debugger calls and restore them after that there'd be nothing else to do, but there's possibly something I'm missing.

    I'm reminded of the zero page use under ProDOS on the Apple II, where we have to do the same thing to avoid ProDOS stomping on our zero page variables.
  • Cluso99Cluso99 Posts: 18,069
    There are about 20 different calls to the monitor so saving the registers is not a solution.

    The monitor not only provides an interactive monitor, it also includes serial routines for outputting characters, string, hex, crlf, dumping cog/lut/hub, reading an input character or string, together with an optional prompt character. The dump has options for reversing and bytes or longs, and includes ascii output on the line.
    The input also accepts a saved dump (download) to input to cog/lut/hub too.
  • Cluso99 wrote: »
    There are about 20 different calls to the monitor so saving the registers is not a solution.

    The monitor not only provides an interactive monitor, it also includes serial routines for outputting characters, string, hex, crlf, dumping cog/lut/hub, reading an input character or string, together with an optional prompt character. The dump has options for reversing and bytes or longs, and includes ascii output on the line.
    The input also accepts a saved dump (download) to input to cog/lut/hub too.

    All while still running Spin2 code? Impressive.

    I'm offering an alternative to the solution of having to load a modified version of the ROM routines.

    If you need to save the state of these variables between monitor calls then you need two buffers: One to hold Spin2's variables during each call, and one to hold the monitor's variables between calls. Then the code to call and return involves 8 extra instructions (probably inline pasm2):
    SETQ #$F
     WRLONG Spinstore, #$1E0
     SETQ #$F
     RDLONG Monstore, #$1E0
     CALL(Entry)
     ...
     SETQ #$F
     WRLONG Monstore, #$1E0
     SETQ #$F
     RDLONG Spinstore, #$1E0
    

    Of course, if there are 8 spare longs available in the Spin2 memory footprint then building this into Spin2 would be more elegant. But then I seem to recall @cgracey saying something about the top 16k being wiped for debug. If so, I hope there's an opt-out for that or all of your work here will be for nothing.

  • Cluso99Cluso99 Posts: 18,069
    edited 2020-04-20 11:58
    I need to get the monitor hubexec code working again, even if it eventually needs to move.

    Also I have to get the SD code working again, and include write too. It’s actually done but I’ve been waiting for spin2 to get the full FAT32 file interface done.

    I am heavily reliant of having my monitor (debugger) working as I can check code operation along the way. It’s so easy to just display a register or hub value, or dump a piece of memory.

    The calls to the monitor are extremely simple. Just load 1-5 registers and a call into hub.
    lmm_x is the data register
    lmm_f is an optional function register that selects options for the specific call
    lmm_p and lmm_p2 are address registers (when required)
    lmm_c is an optional count register (not sure if it is still used as some features were removed due to the rom size limits)

    The ROM monitor can locate and load and optionally run a binary file from the SD card but the re-loaded monitor probably will not support these routines. They will be part of my full OS.
  • Cluso99Cluso99 Posts: 18,069
    Here is the Serial/Monitor code working from spin2
    OBJ
        mon : "RamMonitor"  ' "RamMonitor.spin2"
    
    PUB go()
    
        WAITMS(5000)                                        ' 5s  (delay to get PST running)      
    
    ' move the code to replace the ROM Monitor code using new lmm registers at $120-$12F
        LONGMOVE(mon.SerialInit, @_SerialInit, (@_hub_blob_end - @_SerialInit)/4)
    
        REG[mon.bufad]  := mon.BUF                          ' locn of hub buffer for serial routine $FC000-
        REG[mon.x]      := _bitper                          ' sets serial baud
        CALL(mon.SerialInit)                                ' initialise serial monitor
    
        CALL(mon.TxStrVer)                                  ' print Monitor Version string
    
        REG[mon.x]      := $31323334                        ' print "4321"
        CALL(mon.Tx)
    
        REG[mon.x]      := $31323334                        ' print "1234"
        CALL(mon.TxRev)
    
        CALL(mon.TxCR)                                      ' print crlf
    
        REG[mon.p]      := $01A00                           '
        REG[mon.p2]     := $01B00                           '
        CALL(mon.TxList)                                    ' print list hub $01A00-$01B00
    
        REG[mon.p]      := $000                             '
        REG[mon.p2]     := $020                             '
        CALL(mon.TxList)                                    ' print list cog $000-$020
    
        CALL(mon.TxStrVer)                                  ' print Monitor Version string
        CALL(mon.monitor)                                   ' RAM: _HubMonitor
    
    
        repeat
            PINTOGGLE(LED_p2eval)
            WAITMS(1000)                                    ' 1s        
    
    and the output to PST
    P2-Monitor V1.4m
    43211234
    01A00: 3D3D3D3D 3D3D3D3D 3D3D3D3D 3D3D3D3D  '================'
    01A10: 3D3D3D3D 3D3D3D3D 3D3D3D3D 3D3D3D3D  '================'
    01A20: 3D3D3D3D 3D3D3D3D 3D3D3D3D 3D3D3D3D  '================'
    01A30: 3D3D3D3D 3D3D3D3D 3D3D3D3D 3D3D3D3D  '================'
    01A40: 3D3D3D3D 3D3D3D3D 3D3D3D3D 3D3D3D3D  '================'
    01A50: 3D3D3D3D 3D3D3D3D 3D3D3D3D 3D3D3D3D  '================'
    01A60: 3D3D3D3D 3D3D3D3D 3D3D3D3D 3D3D3D3D  '================'
    01A70: 3D3D3D3D 3D3D3D3D 3D3D3D3D 3D3D3D3D  '================'
    01A80: 3D3D3D3D 3D3D3D3D 3D3D3D3D 3D3D3D3D  '================'
    01A90: 3D3D3D3D 3D3D3D3D 3D3D3D3D 3D3D3D3D  '================'
    01AA0: 3D3D3D3D 3D3D3D3D 3D3D3D3D 3D3D3D3D  '================'
    01AB0: 3D3D3D3D 3D3D3D3D 3D3D3D3D 3D3D3D3D  '================'
    01AC0: FF800000 FC0CF83E FC16403E FD647C41  '.......>..@>.d|A'
    01AD0: FF800000 FC0C7C3F FC16403F FD647E41  '......|?..@?.d~A'
    01AE0: F606400D FC26403E FD7C002D FF068500  '..@..&@>.|.-....'
    01AF0: F6064000 F9FE401B F6024B20 FD747C40  '..@...@...K .t|@'
      000: F603AC10 F603AE11 FDA00CCC FD641E28  '.............d.('
      004: FC6C0000 FD601E28 FC68000D FD640228  '.l...`.(.h...d.('
      008: FC60180E FD601C28 FF000006 FCEC4150  '.`...`.(......AP'
      00C: 00000FF8 002020F0 000020F8 00000101  '.....  ... .....'
      010: 014D28FB 11B3DC40 E0082728 806587D1  '.M(....@..'(.e..'
      014: 047A150C 0CF80CB4 0D9C0D00 0DBC0DB4  '.z..............'
      018: 0E040DE0 0E380E04 0E340E38 0E300E34  '.....8...4.8.0.4'
      01C: 0F200E30 0F680F28 0FB00F68 00000FC4  '. .0.h.(...h....'
    P2-Monitor V1.4m
    *
    

    I am having trouble with the hex routines so no examples yet.
    And I have to hard-code this due to a deficiency IMHO in Chip's compiler but Chip disagrees :(
    '_HubTxStrVer  mov       lmm_p,  ##_str_vers             ' send version string, $00 terminated
    '_HubTxStrVer  mov       lmm_p,  ##@_str_vers             ' send version string, $00 terminated
    _HubTxStrVer  mov       lmm_p,  ##$FD014                ' send version string, $00 terminated hub$fd014
    
  • Cluso99Cluso99 Posts: 18,069
    Here is the fully working RAM Monitor/Debugger replacement for the ROM Monitor/Debugger :sunglasses:

    The monitor code is contained within a pasm object and the register/calls/parameters are contained in another object.
    The demo file gives simple examples of some of the calls available.
    If you call the monitor from spin2, then typing "Q<cr>" at the "*" monitor prompt will return you to the spin code.

    This code may also be called from pasm code. I'll need to provide a new example for that.

    Serial Monitor calling examples
    OBJ
        mon : "RamMonitorEqu"           ' "RamMonitorEqu.spin2"     register & call equates
        cod : "RamMonitorCode"          ' "RamMonitorCode.spin2"    pasm code to be relocated
    
    PUB go()
    
        WAITMS(5000)                                        ' 5s  (delay to get PST running)      
    
        ' move the code to replace the ROM Monitor code using new lmm registers at $120-$12F
        cod.start()                 ' LONGMOVE(mon.SerialInit, @_SerialInit, (@_hub_blob_end - @_SerialInit)/4)
    
        REG[mon.bufad]  := mon.BUF                          ' locn of hub buffer for serial routine $FC000-
        REG[mon.x]      := _bitper                          ' sets serial baud
        CALL(mon.SerialInit)                                ' initialise serial monitor
    
        CALL(mon.TxStrVer)                                  ' print Monitor Version string
    
        REG[mon.x]      := "H"
        CALL(mon.Tx)                                        ' print "H" (prints lowest byte first)
        REG[mon.x]      := "i"
        CALL(mon.Tx)                                        ' print "i" (prints lowest byte first)
        CALL(mon.TxCR)                                      ' print crlf
    
        REG[mon.x]      := "H" + ("i" <<8)
        CALL(mon.Tx)                                        ' print "Hi" (prints lowest byte first)
        CALL(mon.TxCR)                                      ' print crlf
    
    
        REG[mon.x]      := $31323334
        CALL(mon.Tx)                                        ' print "4321" (prints lowest byte first)
    
        REG[mon.x]      := $31323334
        CALL(mon.TxRev)                                     ' print "4321" (prints highest byte first)
    
        CALL(mon.TxCR)                                      ' print crlf
    
        REG[mon.p]      := $01A00                           '
        REG[mon.p2]     := $01B00                           '
        CALL(mon.TxListA2)                                  ' print list hub $01A00-$01B00 (f=List+Addr2)
    
        REG[mon.p]      := $000                             '
        REG[mon.p2]     := $020                             '
        CALL(mon.TxListA2)                                  ' print list cog $000-$020 (f=List+Addr2)
    
        CALL(mon.TxStrVer)                                  ' print Monitor Version string
        CALL(mon.monitor)                                   ' call the Monitor (Q<cr> returns)
    
    
        repeat
            PINTOGGLE(LED_p2eval)
            WAITMS(500)                                    ' 0.5s        
    
    PST output from above examples
    P2-Monitor V1.4
    Hi
    Hi
    43211234
    01A00: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
    01A10: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
    01A20: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
    01A30: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
    01A40: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
    01A50: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
    01A60: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
    01A70: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
    01A80: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
    01A90: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00   '................'
    01AA0: 00 00 00 00  00 00 00 00  00 00 00 00  44 81 03 F0   '............D...'
    01AB0: F8 0F 00 00  7C 16 00 00  A0 16 00 00  00 00 00 00   '....|...........'
    01AC0: 1A 10 00 00  00 00 00 00  B8 CA 0F 00  E8 10 00 00   '................'
    01AD0: 70 05 00 00  00 00 00 00  B8 CA 0F 00  F8 10 00 00   'p...............'
    01AE0: 70 05 00 00  EC 7C BB B9  0A E0 A4 2D  8A 3A FA A1   'p....|.....-.:..'
    01AF0: 07 95 34 04  09 3E 02 0E  53 CA 27 FC  F4 D2 72 FE   '..4..>..S.'...r.'
      000: 10 AC 03 F6  11 AE 03 F6  CC 0C A0 FD  28 1E 64 FD   '............(.d.'
      004: 00 00 6C FC  28 1E 60 FD  0D 00 68 FC  28 02 64 FD   '..l.(.`...h.(.d.'
      008: 0E 18 60 FC  28 1C 60 FD  06 00 00 FF  50 41 EC FC   '..`.(.`.....PA..'
      00C: F8 0F 00 00  7C 16 40 00  8C 16 00 00  03 01 00 00   '....|.@.........'
      010: FB 28 4D 01  40 DC B3 11  28 27 08 E0  D1 87 65 80   '.(M.@...('....e.'
      014: 0C 15 7A 04  B4 0C F8 0C  00 0D 9C 0D  B4 0D BC 0D   '..z.............'
      018: E0 0D 04 0E  04 0E 38 0E  38 0E 34 0E  34 0E 30 0E   '......8.8.4.4.0.'
      01C: 30 0E 20 0F  28 0F 68 0F  68 0F B0 0F  C4 0F 00 00   '0. .(.h.h.......'
    P2-Monitor V1.4
    *q
    
  • Cluso99Cluso99 Posts: 18,069
    There are a couple of "tricks" when using the List call routine...

    The calls mon.TxListA2 and mon.TxListF...
    * use the mon.TxListA2 call if you want the default address range and hex display (register mon.f is set by the routine)
    * set mon.f to the bit options to control the format and then use the mon.TXListF call

    From the call...
    * any address < $200 will be cog
    * any address < $400 but >= $200 will be lut
    * otherwise it will be hub
    But..
    * an address > $1_0000 will be $00000 in hub
    Note: both mon.p and mon.p2 must have this address $1_xxxxx set, otherwise only a single line will be displayed.

    From the monitor...
    * any address with 3 or less digits and < $200 will be cog
    * any address with 3 or less digits and < $400 but >= $200 will be lut
    * any address with more than 3 digits or >= $400 will be hub
    * a <cr> will display the next list block

    So, all of cog/lut/hub can be displayed (and it can be input ie changed too).
  • hinvhinv Posts: 1,255
    I just found the ROM monitor. It's pretty neat. Those lmm calls remind me of sys calls on the Commodore64 to do stuff. So what cog is actually executing the monitor? How does one get to the RAM monitor, which seems to be at rev V1.4m vs the ROM monitor on mine is V1.3?
  • Cluso99Cluso99 Posts: 18,069
    edited 2021-01-13 02:12
    The ROM Monitor runs from whatever cog calls the routine(s). The hubexec routines are re-entrant and can actually be called by any cog, even simultaneously although you have to be careful about intermixing the serial bytes. This is because the smartpins apply to all cogs.

    The use of the lmm prefix is because I wrote this back in 2013 before the P2 had hubexec so it was running in lmm mode back then. This was even before P2-HOT.

    V1.4 is the ROM code compiled for soft-loading and uses different cog registers so it can be used with spin code.
  • Hello,

    Syntax is not clear to me. I am just only trying the mem listing ('L') command and it fails. I don't know what I am doing wrong.

    Please, can someone provide examples of ROM Monitor download, listing and 'G' GOTO?
    Is it possible to download a simple Blink_LED program and run/execute ('G') that code?

    Thank you !

      Cold start
    -------------------------------------------------------------------------------
      Parallax P2  .:.:--TAQOZ--:.:.  V1.1--v33h         190219-1900
    -------------------------------------------------------------------------------
    TAQOZ#  ---  ok
    TAQOZ#  ---  ok
    TAQOZ#  ---  ok
    P2-MONITOR V1.3
    *
    ?
    *
    ?
    *0 - 10 L
    ?
    *L
    !
    *L 0 - 10
    !
    *000000 - 000010 L
    ?
    *$000000 - $000010 L
    ?
    * 1000 - 1100 L
    ?
    * 1000 - [1100] L
    ?
    * 00100 - [001100] L
    ?
    * 00100 00200 L
    ?
    * $000010 L
    ?
    *$001000 L
    ?
    *
    
  • Cluso99Cluso99 Posts: 18,069
    edited 2021-04-26 03:49

    @Ramon said:
    Hello,

    Syntax is not clear to me. I am just only trying the mem listing ('L') command and it fails. I don't know what I am doing wrong.

    Please, can someone provide examples of ROM Monitor download, listing and 'G' GOTO?
    Is it possible to download a simple Blink_LED program and run/execute ('G') that code?

    Thank you !

      Cold start
    -------------------------------------------------------------------------------
      Parallax P2  .:.:--TAQOZ--:.:.  V1.1--v33h         190219-1900
    -------------------------------------------------------------------------------
    TAQOZ#  ---  ok
    TAQOZ#  ---  ok
    TAQOZ#  ---  ok
    P2-MONITOR V1.3
    *
    ?
    *
    ?
    *0 - 10 L
    ?
    *L
    !
    *L 0 - 10
    !
    *000000 - 000010 L
    ?
    *$000000 - $000010 L
    ?
    * 1000 - 1100 L
    ?
    * 1000 - [1100] L
    ?
    * 00100 - [001100] L
    ?
    * 00100 00200 L
    ?
    * $000010 L
    ?
    *$001000 L
    ?
    *
    

    You don't need/use the L command. It's likely an old writeup as I changed the code and missed the doc update.
    For dumping cog ram valid addresses are 0-1EF
    0-100
    For dumping lut ram valid addresses are 200-3FF
    200-280
    For dumping hub ram
    400-480
    For dumping lower hub ram, use this trick
    100000-100100
    only 5 digits are recognised.
    This also works when you are interactive (because you can call the monitor from your program) as the interactive version knows how many digits you entered
    00000-00100

    As for loading and running a binary file located on an SD card, you can do it but these days we have the tools so it's much easier to just download and run a binary (compiled program) wiht pnut, proptool or flexprop & loadp2.

    The G command relies on you entering some code into memory and then jumping to it with the G command.

    All commands follow the addresses.

    The ? response is because the command could not be interpreted.
    The [ and ] are enclosing optional parameters and the [ and ] should not be included in the command.

    Sorry I don;t have time for a better explanation as I'm at work.

Sign In or Register to comment.