The debug scripting interface is function based and depends on certain, named functions to be defined in a Python® file. The function will then be called when the corresponding event is occurring inside Atmel Studio.
Error checking is kept at a minimum for the functions exported into the Python environment so that the time used on initialization during normal sessions are kept low. This means that there are many ways to crash Atmel Studio through this interface.
To load a Python file, place a file named debughooks.py in the Debug folder of your project, next to the ELF file, or one folder up where the project file is. It is also possible to place this file inside the Atmel Studio installation directory to make the script load for all projects.
def should_process_breakpoint(studio_interface, breakpoint_address, breakpoint_id, obj): """ Called to determine if a breakpoint should cause Atmel Studio to enter debug mode. If this function returns False, Atmel Studio will not break at the breakpoint. """ return True def has_processed_breakpoint(studio_interface, breakpoint_address, breakpoint_id, obj): """ This function is called if Atmel Studio is breaking at a breakpoint. The GUI is now in halted mode. """ pass def on_reset(studio_interface, reset_address): """ This function is called when the target is reset. The address where the reset went to is 'reset_address'. """ pass def on_eval_expr(studio_interface, expression): """ This function is called for each expression that is evaluated in Atmel Studio. This includes the watch window and other windows that show data from the target. Pass the 'expression' string through to evaluate it, or return another expression to be evaluated to override the expression. This override is not visible in the Atmel Studio GUI. """ return expression
should_process_breakpoint is undefined, breakpoints might
start to misbehave as the return value of an undefined function is in itself
undefined.In the code shown above, the main interface back into the Atmel Studio is the
studio_interface object. This object contains some
functions to show messages and do target interaction.
Print function in the
studio_interface object is used to show text in the output window
inside Atmel Studio. The function takes two arguments; the string to print and the name of
the tab in the output window. The example below prints all the evaluated expressions to the
Expressionstab.
def on_eval_expr(studio_interface, expression): studio_interface.Print("Evaluating {}".format(expression), "Expressions") return expression
Print is set to INFO, which means that
the output may be masked by Atmel Studio. To lower the threshold, go to , select Status Management, and set the
Display Threshold to INFO. The ExecStmt function in the
studio_interface object is used to execute statements in the debugger.
This can, for instance, be used to set variables. See MSDN Debugger.ExecuteStatement Method
for more information.
The WriteMemory and ReadMemory are
symmetric functions for reading and writing memory on the target. It is
important to use a System.Array[System.Byte] object to pass
the data between the script and Atmel Studio.
import System def should_process_breakpoint(studio_interface, breakpoint_address, breakpoint_id, obj): vals = System.Array[System.Byte]([1, 2, 3, 4, 5, 6, 7, 8, 9]) studio_interface.WriteMemory(data=vals, adr=0, type="eeprom") ret = studio_interface.ReadMemory(adr=0, type="eeprom", count=9) studio_interface.Print("ret == vals => {!r}".format(ret == vals), "Python") return True
CalcNumericValue is a shorthand for the
CalcValue call. It will return the numeric value of the
symbol or the provided default value if the function fails to retrieve the
value of the symbol.
def should_process_breakpoint(studio_interface, breakpoint_address, breakpoint_id, obj): a = studio_interface.CalcNumericValue("a", 0) if a == 0: studio_interface.Print("a was 0 or default", "Value scripts") else: studio_interface.Print("a = {}".format(a), "Value scripts") return True
CalcValue function is used to retrieve
information about a symbol in the scope where the target code is running. The return value
of this call is a list of information containing the address of the symbol, symbol
information, and value. The objects sent to this list contains all known information about
a symbol, but the most useful field is the last element which contains the value of the
evaluated symbol. def should_process_breakpoint(studio_interface, breakpoint_address, breakpoint_id, obj): a = studio_interface.CalcValue("a") # a now contains all information about the variable a. # It is a list with the following members: # a = [ # <Atmel.VsIde.AvrStudio.Services.TargetService.TCF.Services.ValueInfo>, # <Atmel.VsIde.AvrStudio.Services.TargetService.TCF.Services.SymbolInfo>, # <Atmel.VsIde.AvrStudio.Services.TargetService.TCF.Services.ExpressionInfo>, # '1' ] <-- This is the value of the symbol as a string, here it had the value 1 studio_interface.Print("Value of a = {}".format(a[3]), "Value Scripts") return True
CalcValue call contains objects that are either internal or
documented in the Atmel Studio SDK. Use the python dir() command to
look at the fields that are exported.