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
-
StackAddress | Start address of memory area |
StackSize | Size of memory area in Bytes |
FillPattern | Initial value of memory area, used to identify memory usage |
MagicValue | Initial 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];
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 & 0xFFFFF] %d[(StackUsage>>20) & 0xFF]%%" />
</out>
</object>
</objects>
</component_viewer>
Output
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_name | Name 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];
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 & 0xFFFFF] %d[(StackUsage>>20) & 0xFF]%%" />
</out>
</object>
</objects>
</component_viewer>
Output
__GetRegVal
__GetRegVal | Read the value of processor register from the target processor.
uint32_t __GetRegVal (char * RegisterName)
- Parameters
-
RegisterName | Pointer 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_name | ASCII 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_name | Is 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_name | ASCII 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("MyList")]"/>
<item cond="__Symbol_exists("MyTest.c/MyVar")" property="Elements of 'MyVar'" value="%d[__size_of("MyTest.c/MyVar")]"/>
</out>