Introduction
This article discusses how to measure the performance of your applications using two methods:
- GPIO - Use the GPIO class to toggle pins on your board and hook these into a oscilloscope in order to visualize specific TouchGFX events.
- MCU Instrumentation - Read out current cpu-cycles using Cortex-M specific MCU instrumentation.
GPIO
The touchgfx::GPIO
class, compiled for all target applications, contains methods to set, clear, toggle and get the state of a GPIO pin. An implementation must be provided for these static members; Even if it is simply empty and does nothing. While the TouchGFX core might not be available to you, our code is instrumented to make calls into this GPIO implementation when it performs certain functions to help developers track down performance and timing issues. The following types are toggled throughout TouchGFX:
VSYNC_FREQ
is typically toggled from the HAL component of an MCURENDER_TIME
defines the time it takes to render a frame. It goes high when TouchGFX starts processing a frame, and low once all drawing has completed.FRAME_RATE
toggles every time a framebuffer swap occurs, so this pin gives you the achieved frame rate.MCU_ACTIVE
is toggled from the idle task hook in the touchgfx::OSWrappers class for an OS package as soon as the idle task is scheduled
Perform measurements with an oscilloscope by toggling the GPIO pins of choice in your implementation of the GPIO class. You can gain inspiration from existing GPIO implementations for various boards found under the touchgfx/board
folder.
MCU Instrumentation
The class touchgfx::MCUInstrumentation
provides an interface for reading out CPU-cycles in an effort to, for instance, calculate general MCU-load caused by an application. The following items are required in order to enable HAL to perform MCU load calculations:
Configure OS to set MCU active when Idle Task is switched out during rescheduling. Configure HAL with a concrete instance of MCUInstrumentation for a particular processor (For Cortex-M: touchgfx::CortexMMCUInstrumentation located under platform/core/arm/cortex-m
)
HAL
The following code snippet from a BoardConfiguration shows how to configure HAL to use MCU instrumentation.
...
CortexMMCUInstrumentation mcuInstr;
void touchgfx_init()
{
HAL& hal = touchgfx_generic_init<STM32F4HAL>(dma, display, tc, 480, 272, 0, 0);
hal.setFrameBufferStartAddress((uint16_t*)frameBuf0);
mcuInstr.init();
//Set MCU instrumentation and Load calculation
hal.setMCUInstrumentation(&mcuInstr);
hal.enableMCULoadCalculation(true);
}
OS
The following snippet shows how OSWrappers.cpp
(Specific for each Operating System supported by TouchGFX), through a task hook, is able to indicate when the MCU is active and when it is Idle. We use the FreeRTOS methodvTaskSetApplicationTaskTag
to callback function and assign our function pointer IdleTaskHook
as the task tag parameter.
static portBASE_TYPE IdleTaskHook(void* p)
{
if ((int)p) //idle task sched out
{
touchgfx::HAL::getInstance()->setMCUActive(true);
}
else //idle task sched in
{
touchgfx::HAL::getInstance()->setMCUActive(false);
}
return pdTRUE;
}
// FreeRTOS specific handlers
extern "C"
{
void vApplicationStackOverflowHook( xTaskHandle xTask,
signed portCHAR *pcTaskName )
{
while(1);
}
void vApplicationMallocFailedHook( xTaskHandle xTask,
signed portCHAR *pcTaskName )
{
while(1);
}
void vApplicationIdleHook( void )
{
vTaskSetApplicationTaskTag( NULL, IdleTaskHook );
while(1)
{
}
}
Enabling the Idle-hook is an explicit setting found in FreeRTOSConfig.h
for a specific application. The following snippet was taken from app/demo/touchgfx_demo2014/platform/os/FreeRTOSConfig.h
:
#define configUSE_IDLE_HOOK 1
//The following define configuration is required to call the idle hook when a task is switched out.
#define traceTASK_SWITCHED_OUT() xTaskCallApplicationTaskHook( pxCurrentTCB, (void*)1 )
#define traceTASK_SWITCHED_IN() xTaskCallApplicationTaskHook( pxCurrent