Event Recorder  Version 1.0.1
MDK Debugger Views for Status and Event Information
 All Files Functions Macros Groups Pages
Built-in Functions

Read CPU register value

The SCVD interpreter has the following built-in functions for calculation of stack memory usage, access to CPU registers and application program symbols.

Function Name Description
__CalcMemUsed Provide memory usage information for stack area in user application program.
__FindSymbol Get address value of a symbol in user application program.
__GetRegVal Read the value of processor register from the target processor.
__Offset_of Get offset of type member defined with the typedef.
__size_of Number of elements of an array defined by a symbol in user application.
__Symbol_exists Check if a specific symbol exists in the user application program.

 


__CalcMemUsed

Provide memory usage information for stack area in user application program.

uint32_t __CalcMemUsed (uint32_t StackAddress, uint32_t StackSize, uint32_t FillPattern, uint32_t MagicValue)
Parameters
StackAddressStart address of memory area
StackSizeSize of memory area in Bytes
FillPatternInitial value of memory area, used to identify memory usage
MagicValueInitial value at end of memory area, used to identify memory (stack) overflow
Returns
A packed 32-bit integer value that indicates memory usage in bytes, in percent, and memory overflow:
  • Bit 0..19 Used memory in Bytes (how many bytes of FillPattern are overwritten)
  • Bit 20..28 Used memory in percent (how many percent of FillPattern are overwritten)
  • Bit 31 Memory overflow (MagicValue is overwritten)

The function provides information about the memory usage of a stack area and is typically applied to calculate the utilization of RTOS thread stacks. It assumes that the memory has been filled with a pattern value. Optionally there might be a value (called magic value) at the start of the memory that is used to detect stack overflows.

Example 1

C source file

uint32_t tstack[200/4]; // 200 bytes stack space
void StackTest (void) {
uint32_t i;
memset (tstack, 0x8A, sizeof (tstack));
tstack[0] = 0xE25A2EA5;
for (i=(200/4)-1; i >= 10; i--) {
tstack[i] = i;
}
}

*.SCVD file

<?xml version="1.0" encoding="utf-8"?>
<component_viewer schemaVersion="0.1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="Component_Viewer.xsd">
<component name="MyExample" version="1.0.0"/> <!-- name and version of the component -->
<objects>
<object name="MyProgram">
<var name="StackStart" type="int32_t" value="0" />
<var name="StackSize" type="int32_t" value="0" />
<var name="StackUsage" type="int32_t" value="0" />
<calc>
StackStart = __FindSymbol ("tstack");
StackSize = __size_of ("tstack") * 4;
StackUsage = __CalcMemUsed (StackStart, StackSize, 0x8A8A8A8A, 0xE25A2EA5);
</calc>
<out name="MyProgram">
<item alert="(StackUsage >> 31)"
property="tstack @%x[StackStart] size=%x[StackSize]"
value="Usage %x[StackUsage &amp; 0xFFFFF] %d[(StackUsage>>20) &amp; 0xFF]%%" />
</out>
</object>
</objects>
</component_viewer>

Output

CalcMemUsed.png

Example 2

Typical usage with an RTOS thread control block.

<component_viewer...>
<typedefs>
<!-- Task/Thread Control Block, debugger reads 52 bytes -->
<typedef name="Thread_CB" info="RTOS Task Control Block" size="52">
:
<member name="Stack" type="uint32_t" offset="44" info="Pointer to Task Stack memory block"/>
:
<!-- Helper variables for Stack-usage calculation -->
<var name="StackSize" type="uint32_t" />
<var name="StkUse" type="uint32_t" />
<var name="BytesUsed" type="uint32_t" />
<var name="Percentage" type="uint32_t" />
<var name="StkOverflow" type="int32_t" />
<var name="ShowStackInfo" type="int32_t" />
</typedef>
</typedefs>
</objects>
<object name="Threads">
<readlist name="TCB" type="*Thread_CB" symbol="os_TCB" based="1" count="10" init="1" />
<!-- Stack Usage Calculation when watermark check is enabled (ShowStackInfo) -->
<calc cond="TCB[i].ShowStackInfo && ((i != (TCB._count - 1)) && ((stackinfo >> 28) & 0x01))" >
StkUse = __CalcMemUsed (TCB[i].Stack, TCB[i].StackSize, 0xCCCCCCCC, 0xE25A2EA5);
TCB[i].StkOverflow = (StkUse & 0x80000000) ? 1 : 0;
TCB[i].StkUse &= ~0x80000000;
TCB[i].BytesUsed = (StkUse & 0xFFFFF);
TCB[i].Percentage = (StkUse >> 20) & 0xFF;
</calc>
</object>
</objects>
</component_viewer>

 


__FindSymbol

Get address value of a symbol in the user application program.

int32_t __FindSymbol (symbol_name)
Parameters
symbol_nameName of a symbol (examples: "main", "os_active_TCB", ...).
Returns
address value Address of the symbol.

The function searches for a symbol and returns the address value of the symbol in the user application.

Note
If the symbol cannot be found, then an error in the Component Viewer is displayed.

C source file

uint32_t tstack[200/4]; // 200 bytes stack space
void StackTest (void) {
uint32_t i;
memset (tstack, 0x8A, sizeof (tstack));
tstack[0] = 0xE25A2EA5;
for (i=(200/4)-1; i >= 10; i--) {
tstack[i] = i;
}
}

*.SCVD file

<?xml version="1.0" encoding="utf-8"?>
<component_viewer schemaVersion="0.1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="Component_Viewer.xsd">
<component name="MyExample" version="1.0.0"/> <!-- name and version of the component -->
<objects>
<object name="MyProgram">
<var name="StackStart" type="int32_t" value="0" />
<var name="StackSize" type="int32_t" value="0" />
<var name="StackUsage" type="int32_t" value="0" />
<calc>
StackStart = __FindSymbol ("tstack");
StackSize = __size_of ("tstack") * 4;
StackUsage = __CalcMemUsed (StackStart, StackSize, 0x8A8A8A8A, 0xE25A2EA5);
</calc>
<out name="MyProgram">
<item alert="(StackUsage >> 31)"
property="tstack @%x[StackStart] size=%x[StackSize]"
value="Usage %x[StackUsage &amp; 0xFFFFF] %d[(StackUsage>>20) &amp; 0xFF]%%" />
</out>
</object>
</objects>
</component_viewer>

Output

CalcMemUsed.png

 


__GetRegVal

__GetRegVal | Read the value of processor register from the target processor.

uint32_t __GetRegVal (char * RegisterName)
Parameters
RegisterNamePointer to the name of a CPU register: "PSP", "MSP", ....
Returns
Value of the CPU register

The function reads the value of a CPU register.


__Symbol_exists

int32_t __Symbol_exists (symbol_name)

Search for symbol

Parameters
symbol_nameASCII string of a symbol in user application.
Returns
  • 1 for true - symbol present in user application
  • 0 for false - symbol not found

The function searches for a debug symbol in the loaded user application.

and returns 1 when the symbol was found, otherwise 0 for false.  


__Offset_of

uint32_t __Offset_of (typedef_mem_name)

Get offset of type member

Parameters
typedef_mem_nameIs the member name of a specified type and has the form typedef_name:typedef_member_name.
Returns
The offset value of the specified typedef member.

The function returns the offset value of the specified typedef member.

Example:

__Offset_of (Thread_CB:Task_ID)

__size_of

int32_t __size_of (symbol_name)

Number of elements of an array defined by a symbol in user application

Parameters
symbol_nameASCII string of a symbol in user application.
Returns
number of elements of an array defined in user application

The function searches for a debug symbol in the loaded user application. If the symbol is found it returns the number of elements of an array that is addressed by this symbol. If the symbol is not found, an error message is displayed.

Example:

User application code (file MyTest.c):

struct {
unsigned char c0;
unsigned char c1;
unsigned int i;
} MyList [20];
static int MyVar[10];

The following statements in the SCVD file output the number of elements of each variable. For 'MyList' the value is 20. The value 20 for 'MyVar' is only displayed when the variable exists.

<out name="MyTest">
<item property="Elements of 'MyList'" value="%d[__size_of(&quot;MyList&quot;)]"/>
<item cond="__Symbol_exists(&quot;MyTest.c/MyVar&quot;)" property="Elements of 'MyVar'" value="%d[__size_of(&quot;MyTest.c/MyVar&quot;)]"/>
</out>