RISC OS Open

RISC OS  OPEN


A fast and easily customised operating system for devices using ARM processor cores.

Documentation: DebugTools Module API Specification

Contents


CLI Commands

*Where [<address>]

Output information about the specified address (or that of the last abort).

Uses SWI DebugTools_Where.

Examples:
*Where
*Where 0240DD84

*Vectors

List the contents of the software vectors.

Uses SWI DebugTools_Vectors.

Examples:
*Vectors
*Vectors 2E
*Vectors IrqV

*Tickers

List the contents of the Kernel's CallAfter and CallEvery list.

Uses SWI DebugTools_Tickers.

Examples:
*Tickers

*IRQDevices

List the contents of the Kernel device vectors.

Uses SWI DebugTools_IRQDevices.

Examples:
*IRQDevices

*X <CLI command>

Execute the specified *command and place any error into the X$Error system variable (if it is currently unset). Do not return the error.

No equivalent SWI call.

Examples:
*X Pin Boot:Choices 180 154
*X Wipe rm ~cfr~v

*Canonical <sys var> <file spec>

Canonicalise the specified filename and place the result in a system variable.

No equivalent SWI call.

Examples:
*Canonical Root$Dir Boot:^
*Canonical My$Scrap Waste:Basket.12Mar2003.Scrap

*IRQInfo [0 | 1]

This command can be used to both activate and deactivate the IRQ timing mechanism, and to output a table of statistics.

    Parameter: Function:
    None Output a table of statistics (see below)
    0 Deactivate the timing mechanism (off by default)
    1 Activate the timing mechanism
    2+ Reserved - do not use

If the parameter "1" is passed when the timing mechanism is already active, this command will not do anything. If the parameter "0" is passed when the timing mechanism is already inactive, this command will not do anything.

When no parameter is passed, this command will check to see if the timing mechanism is active. If not, it will activate it. If active, this command outputs a table of information on the number of times in the last second that each device driver for each IRQ device number was entered. It also shows the percentage of CPU use for each device driver.

Does not need to use SWI DebugTools_IRQInfo.

Examples:
*IRQInfo 1

*UnknownIRQs

Output a dump of our count of how many times we have seen each device pass along IrqV since the last call to this *command. Reset all counters to zero after reading them.

Does not need to use SWI DebugTools_UnknownIRQs.

Examples:
*UnknownIRQs

*RMDie

When a module cannot be killed, it is usually because the module finalisation code is returning an error. This *command will attempt to replace the finalisation code offset in the specified module's header with zero and then kill the module. Faulty ROM modules clearly cannot be killed using this method because their module header is in read-only memory.

WARNING: removing the module finalisation code and then killing the module can lead to system instability due to the fact that any system resources claimed by the module (i.e. CallBacks, Events, Vectors, RMA, etc) are not freed. This *command is aimed for use during module development only.

Does not use any DebugTools SWI calls.

Examples:
*RMDie FrontEnd

*RMRemove

This command is similar to the *RMDie command, but it does not attempt to kill the specified module. It will reset all module header words in the specified module to zero, apart from the module title string and module help string. Faulty ROM modules clearly cannot be killed using this method because their module header is in read-only memory.

The module is left in the module chain so that any system resources claimed by that module can continue to operate as expected.

The module will have its title and help strings replaced with a string of the form "Dead<num>", where num is an eight-digit hexadecimal number, incremented after each call to *RMRemove. As the module is given a new title string, it can be killed with *RMKill later. It also allows that module to be re-loaded.

Note: if the module is killed, it will leak an additional 16 bytes of RMA used to store the new title and help string. This is likely to be of minor impact when compared to the other system resources leaked by removing the module's finalisation code! Refer to the warning for *RMDie.

Does not use any DebugTools SWI calls.

Examples:
*RMRemove FrontEnd

*pushd [<directory>]

As with the UNIX command of the same name, this command push the currently selected directory (CSD) onto a stack and then set the specified directory (if any) as the CSD.

Does not use any DebugTools SWI calls.

Examples:
*pushd Boot:Choices.Boot.Tasks

*popd

As with the UNIX command of the same name, this command will change the currently selected directory (CSD) to the top one off the directory stack (if any). This directory will be removed from the stack.

Does not use any DebugTools SWI calls.

Examples:
*popd

*pwd

As with the UNIX command of the same name, this command outputs the (canonicalised) currently selected directory (CSD) to all active output streams.

Does not use any DebugTools SWI calls.

Examples:
*pwd

*EvalHex <expression>

Evaluate the specified expression and output the result as either a string (if that is the type) or as eight-digit hexadecimal (if the result is an integer).

Does not use any DebugTools SWI calls.

Examples:
*EvalHex &00FFFF00 AND (&01F00000 + &CD0)

*EvalBin <expression>

Evaluate the specified expression and output the result as either a string (if that is the type) or as 32 bit binary (if the result is an integer).

Does not use any DebugTools SWI calls.

Examples:
*EvalBin 2_10001011 EOR (2_11100111 + 53730)

Software Interrupts

SWI DebugTools_AddressInfo (0x554C0)

Given an address, try to sensibly interpret the context of that address. It returns values in R0-R3 to indicate information about the specified address.

A list of the current area types and return values are:

    A mapped-out page
      R0 = 0
      R1 = R1 on entry rounded-down to nearest page boundary
      R2 = offset of R1 on entry from page boundary
      R3 = 0
    A module
      R0 = 1
      R1 = base address of module
      R2 = offset of R1 on entry from module base
      R3 = pointer to module title string
    A module's workspace
      R0 = 2
      R1 = base address of module workspace
      R2 = offset of R1 on entry from workspace base
      R3 = pointer to module title string
    A dynamic area
      R0 = 3
      R1 = base address of dynamic area
      R2 = offset of R1 on entry from area base
      R3 = pointer to dynamic area name string
    A mapped-out page in a dynamic area
      R0 = 4
      R1 = base address of dynamic area
      R2 = offset of R1 on entry from area base
      R3 = pointer to dynamic area name string
    Zero page
      R0 = 5
      R1 = as R1 on entry
      R2 = 0
      R3 = 0
    The Kernel
      R0 = 6
      R1 = ROM base address
      R2 = offset of R1 on entry from ROM base
      R3 = 0
    The ROM space
      R0 = 7
      R1 = as R1 on entry
      R2 = 0
      R3 = 0
    The application slot
      R0 = 8
      R1 = &8000
      R2 = offset of R1 on entry from &8000
      R3 = 0
    Any other location
      R0 = 9
      R1 = as R1 on entry
      R2 = 0
      R3 = 0
In...
    R0 = flags word (zero)
    R1 = address to check
Out...
    R0 = area type code (or pointer to error block)
    R1 = base address of area
    R2 = offset of R1 on entry into area
    R3 = additional area info (depends upon R0 on exit)
    R4-R9 = preserved
    V flag = set if R0 is a pointer to an error block

SWI DebugTools_Where (0x554C1)

Given an address (or the address of the last abort), output an analysis of where that address is (using the AddressInfo SWI).

In...
    R0 = flags word
    bit 0 0 - R1 contains address to inspect
    1 - Inspect address of the last exception
    bits 1-31 - should be zero
    R1 = address to check (if R0:0 is clear on entry)
Out...
    R0 = corrupted (or pointer to error block)
    R1-R9 = preserved
    V flag = set if R0 is a pointer to an error block

SWI DebugTools_Vectors (0x554C2)

Output information on the claimants of each of the software vectors in a human-readable format.

In...
    R0 = flags word
    bit 0 0 - list contents of all vectors
    1 - list contents of vector number in R1
    bits 1-31 - should be zero
    R1 = vector number to enumerate (if R0:0 set on entry)
Out...
    R0 = corrupted (or pointer to error block)
    R1-R9 = preserved
    V flag = set if R0 is a pointer to an error block

SWI DebugTools_Tickers (0x554C3)

Enumerate all of the currently pending CallAfters and CallEverys in a human-readable format.

In...
    R0 = flags word (zero)
Out...
    R0 = corrupted (or pointer to error block)
    R1-R9 = preserved
    V flag = set if R0 is a pointer to an error block

SWI DebugTools_IRQDevices (0x554C4)

Output the contents of the Kernel's device driver vector in a human-readable format. This may not be available on early Kernels.

In...
    R0 = flags word (zero)
Out...
    R0 = preserved (or pointer to error block)
    R1-R9 = preserved
    V flag = set if R0 is a pointer to an error block

SWI DebugTools_IRQInfo (0x554C5)

Return a pointer to a table of information about the current device drivers installed on the Kernel's device vector. This is a copy of the table which is maintained by the patch code on the Kernel's interrupt despatch code.

The table is refreshed once every second. The format is:

    Bytes: Contents:
    0-3 IRQ 0 - number of 2 MHz cycles consumed by driver
    4-7 IRQ 0 - number of times driver was called
    8-11 IRQ 1 - number of 2 MHz cycles...
    12-15 IRQ 1 - number of times...
    ... ...
    128-131 IRQs above 15 - number of 2 MHz cycles...
    132-135 IRQs above 15 - number of times...

Note: calls to this SWI will return zero in R0 if the IRQ timing mechanism has not yet been activated with a call to *IRQInfo. Timing information will only be updated once a second, so calls within the first 99 cs after activating the timing mechanism will return a table filled with zeros.

In...
    R0 = flags word (zero)
Out...
    R0 = pointer to table of IRQ information or zero if none is available
    R1 = size of the table (bytes)
    R2-R9 = preserved
    V flag = set if R0 is a pointer to an error block

SWI DebugTools_UnknownIRQs (0x554C6)

Return a pointer to a table of information hit counts for each device number from our code sat on IrqV. The table is reset to zero after each call to *UnknownIRQs.

    Bytes: Contents:
    0-3 Counter for IRQ device 0
    4-7 Counter for IRQ device 1
    ... ...
    124-127 Counter for IRQ device 31
In...
    R0 = flags word (zero)
Out...
    R0 = pointer to table or zero if none is available
    R1 = size of the table (bytes)
    R2-R9 = preserved
    V flag = set if R0 is a pointer to an error block

SWI DebugTools_ClaimOSSWI (0x554C7)

This SWI call allows the specified code to be added onto a vector of code to call whenever the specified OS SWI call is made. SWI DebugTools_ClaimOSSWI will add the code specified in R1 to the head of the vector for the OS SWI specified in R0. It will remove all other claimants on the vector with identical values of both R1 and R2 on entry to this SWI.

The value passed in R2 to this SWI will be passed into the claimant's code in R12 whenever the claimant is entered - it is the claimant's private word. Other registers are defined below. Note: the claimant is the code which resides on a particular OS SWI vector, the caller is the code which issued the OS SWI.

See the notes section for more information.

In...
    R0 = OS SWI number (flags in top 8 bits - should be zero)
    R1 = pointer to code to add
    R2 = value to be passed in R12 to code
Out...
    R0 = corrupted (or pointer to error block)
    R1-R9 = preserved
    V flag = set if R0 is a pointer to an error block

SWI DebugTools_AddToOSSWI (0x554C8)

This SWI behaves in much the same way as DebugTools_ClaimOSSWI, except that any previous claimants on the vector are preserved, even if they were added with identical values of R1 and R2.

See the notes section for more information.

In...
    R0 = OS SWI number (flags in top 8 bits - should be zero)
    R1 = pointer to code to add
    R2 = value to be passed in R12 to code
Out...
    R0 = corrupted (or pointer to error block)
    R1-R9 = preserved
    V flag = set if R0 is a pointer to an error block

SWI DebugTools_ReleaseOSSWI (0x554C9)

This SWI will remove the first (head first, tail last) instance of a claimant from the specified OS SWI vector, which was added with identical values in R1 and R2.

If no match is found, the error "Bad OS SWI release" will be returned. If an attempt is made to remove the Kernel (tail) claimant from any vector, the error "You cannot release the Kernel claimant" will be returned.

See the notes section for more information.

In...
    R0 = OS SWI number (flags in top 8 bits - should be zero)
    R1 = pointer to code to remove
    R2 = value passed in R2 when added
Out...
    R0 = corrupted (or pointer to error block)
    R1-R9 = preserved
    V flag = set if R0 is a pointer to an error block

Notes

The following are additional notes concerning the usage of the DebugTools SWIs ClaimOSSWI, AddToOSSWI and ReleaseOSSWI.

On entry to the claimant's code:
    R0-R9 = as for the claimed SWI
    R10 = copy of the caller's CPSR
    R11 = SWI number
    R12 = private word (as passed in R2 to ClaimOSSWI)
    R13 = full-descending supervisor stack pointer
    R14 = address to return to for passing-on the SWI call
    CPSR_f = undefined
    CPSR_c = ARM mode, SVC26 or SVC32, IRQs/FIQs as for caller

The Kernel (i.e. the original claimant of the SWI) will always be at the tail of the vector. Thus, a claimant may wish to either modify the registers before passing the SWI call on to the Kernel, or it may wish to claim the SWI call to stop it from being passed-on to the Kernel.

To pass-on the OS SWI call on exit from the claimant's code, use:

    MOV PC,LR and not MOVS PC,LR

To claim the OS SWI call on exit from the claimant's code, use:

    LDMFD R13!,{PC} and not LDMFD R13!,{PC}^

If you want to return an error to the caller, you must set R0 to be a pointer to the error block as normal and set the V bit in R10, not R14. This is because the CPSR is restored from the value in R10 before the SWI returns to the caller.

The exit conditions for passing-on and claiming an OS SWI call are described below.

On exit from the claimant's code (passing-on the call):
    R0-R9 = may be modified for next claimant
    R10 = may be modified for next claimant
    R11 = must be preserved
    R12 = may be corrupted
    R13 = must be preserved
    R14 = may be corrupted
    CPSR_f = may be corrupted
    CPSR_c = must be preserved
On exit from the claimant's code (claiming the call):
    R0-R9 = may be modified
    R10 = full CPSR to assert on return to caller
    R11 = may be corrupted
    R12 = may be corrupted
    R13 = R13 on entry +4 (pulled LR to claim)
    R14 = may be corrupted
    CPSR_f = may be corrupted
    CPSR_c = must be preserved

When you claim, add to or release an OS SWI using the DebugTools SWIs, there are some additional constraints that you should be aware of:

  1. You cannot claim SWI "OS_WriteC" on RISC OS 4 and above Kernels due to an optimisation in the Kernel's OS SWI despatch code which means that this SWI is not despatched via the despatch table.

  2. You can only claim the first 256 OS SWIs (see above note). This means that SWIs from "OS_WriteI+0" cannot be claimed using DebugTools.

  3. Do not claim, release or add to OS SWI vectors from an IRQ handling routine. To do so may produce unpredictable results.

  4. When the DebugTools module is killed, it will remove all of the OS SWI vectors forcibly. Any software using the DebugTools module should make no assumptions that the DebugTools module is still present when attempting to remove SWI vector claimants (i.e. check for the "SWI name not known" error - 486).

  5. You should take care when claimant code modifies the values in R0-R9, as this will be changing the documented behaviour of the OS SWI.

SAR, 12th Jun 2001
   .