2.5.34. TAPOp_RunBufferedMacro

Run a predefined macro using variable parameter information from the Multi-ICE server macro buffer and then reading out any results.


#include “tapmacro.h”

extern TAPOp_Error TAPOp_RunBufferedMacro(unsigned8 connectId, unsigned8 macroNo, unsigned8 bufferNo, int *lineno_error, int *loopno_error, void *resultValues, int *resultSize, int nTimes, unsigned8 deselect);



Connection ID, as returned by TAPOp_OpenConnection.


The number of the macro to run, local to this connection.


The number of the buffer that contains the variable data block. This must be 0 or 1 and the data must have been loaded before this call.


The macro line number that caused the error. This is valid when TAPOp_RunBufferedMacro returns an error:

  • 0 indicates that the call to TAPOp_RunBufferedMacro failed, for example, an undefined macro number was specified.

  • 1,2,3... indicate failure on statement 1, 2, or 3 of the macro.


Macro loop number that caused the error. This is only valid if TAPOp_RunBufferedMacro returns an error. For example, if a macro call has nTimes = 4 and it fails on the third time the macro is run, loopno_error is three.


A block of data into which the results of the functions called by this macro are placed. This is allocated by the caller.


On entry, this indicates the maximum amount of data that can fit in resultValues. On exit, the actual amount of data in resultValues is returned.


The number of times the macro is run (parameters are read and results are written cumulatively from or to the data arrays).


If 0, the connection to this TAP controller remains selected. This excludes access to this TAP controller from other Multi-ICE server connections. Otherwise, the connection is deselected, giving other connections a chance to perform operations.


The function returns:


No error.


Connection could not be made.


The connectId was not recognized.


The RPC connection was lost while processing this request.


Parameters were missing during either the macro define or execution.


Any other errors that the components of the macro can return.


The call attempts to select the connection. If this cannot be done (for example, because another TAP controller is being accessed), the call fails with a TAPOp_UnableToSelect error.

This function is very similar to TAPOp_RunMacro except that the variable data is not passed alongside the call. Instead, the variable data is written into one of the two available buffers in the Multi-ICE server using TAPOp_FillMacroBuffer. This is useful because:

  • TAPOp_FillMacroBuffer cannot return the error TAPOp_UnableToSelect, so under normal circumstances it does not fail. This means that the variable data for a TAPOp_RunMacro call does not have to be resent if the server is busy. With large variable data blocks the time to transfer the variable data dominates the communication time, and so avoiding resending the data improves performance on multi-processor systems, where the server often returns TAPOp_UnableToSelect.

  • There are cases, for example filling memory with a pattern, when the variable data in a macro is actually fixed for a few successive calls. Writing this data to a buffer and running the macro a number of times avoids sending it over the network and so improves performance.

  • Because there are two buffers, a multi-threaded client can be loading one buffer while running a macro from the other. This overlap of the data transfer and execute portions of the TAPOp_RunMacro calls improves performance and ensures that the interface between client and server is fully utilized. This is particularly important on relatively slow interfaces such as 10Mbps Ethernet.

Like TAPOp_RunMacro, this call returns TAPOp_UnableToSelect when the server is busy.


This example shows a function that writes a register bank back to the processor (remember that ARM processor register numbers are processor mode dependent). The function does this by:

  1. Formatting the data using the parameter macros.

  2. Sending the formatted data to the server macro buffer.

  3. Running the macro identified by the constant WRITE_ALL_REGS. The macro must have been defined elsewhere in the client.

The instructions that cause the data to end up in processor registers are hidden inside the macro itself, and a routine that wrote to target memory could look very similar.

#define WRITE_ALL_REGS 20
TAPOp_Error defineMacros(void)
    ... define macro WRITE_ALL_REGS
TAPOp_Error WriteRegisters(unsigned32 reg[])
    unsigned8 resultvalues[1];
    int lnerr, looperr, resultsize;
    int i;
    // adjust PC to account for the macro's instructions
    reg[15] -= 1 * 4;
    // Format the data to write
    for (i = 0; i < 16; i++)
    // Send the data to the server
    TAPCheck(TAPOp_FillMacroBuffer(connectId, 0, Values, ValPtr);
    // Call the macro...
    resultsize = 0;
    TAPCheck(TAPOp_RunBufferedMacro(connectId, WRITE_ALL_REGS, 0, &lnerr, 
                                   &looperr, &resultvalues, &resultsize, 1, 0));  
    return TAPOp_NoError;

See also

This TAPOp API function provides similar or related functionality:

Copyright © 1998-2002 ARM Limited. All rights reserved.ARM DUI 0154B