Enabling performance and debug tracing on i.MX RT1060 EVK using SWO back-channel

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Enabling performance and debug tracing on i.MX RT1060 EVK using SWO back-channel

1,653 Views
ssnider
Contributor III

Following on from the post on enabling faster flashing which discusses how to enable the advanced LPC-Link2 JTAG debugger features on the i.MX RT1060 EVK board I was inspired to explore how we could make good use of this with Storyboard applications.

 

There are a few resources and references that you may find useful:

https://www.nxp.com/docs/en/user-guide/LPCXpresso_IDE_SWO_Trace.pdf

https://www.nxp.com/docs/en/quick-reference-guide/MCUXpresso_IDE_SWO_Trace.pdf

 

For additional tips and instructions on developing Storyboard GUI applications for NXP processors visit Crank Software’s Help Center via this link.

 

 

Configuring the SWO hardware

The first thing that needs to be done is to bring the SWO pin to the outside world and make this available to the onboard JTAG adapter. This requires a change to the pin MUX configuration for the single wire debug function [Pad G13] on the RT1060 device.

You can do this using one of two options:

Option 1: Using the MCUXpresso Pins configuration tool and then use the update option to insert the code automatically as follows:

* TEXT BELOW IS USED AS SETTING FOR TOOLS ****************************

CopiedFunction:

- options: {}

- pin_list:

- pinItem: {pin_num: G13, peripheral: ARM, signal: arm_trace_swo, pin_signal: GPIO_AD_B0_10, pull_up_down_config: Pull_Down_100K_Ohm, pull_keeper_select: Keeper,pull_keeper_enable: Disable, open_drain: Disable, speed: MHZ_200, drive_strength: R0_7}

 

* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS ***********

 

ssnider_0-1631802571802.png

 

 

 

Option 2: Manually insert the code below into the BOARD_InitPins() function within the pin_mux.c file to set the pin MUX and route the SWO TRACE function to the pin:

IOMUXC_SetPinMux(

IOMUXC_GPIO_AD_B0_10_ARM_TRACE_SWO,     /* GPIO_AD_B0_10 is configured as ARM_TRACE_SWO */    0U);                                    /* Software Input On Field: Input Path is determined by functionality */    

IOMUXC_SetPinConfig(

IOMUXC_GPIO_AD_B0_10_ARM_TRACE_SWO,     /* GPIO_AD_B0_10 PAD functional properties : */    0xF9U);                                 /* Slew Rate Field: Fast Slew Rate                                                 Drive Strength Field: R0/7                                                 Speed Field: max(200MHz)                                                 Open Drain Enable Field: Open Drain Disabled                                                 Pull / Keep Enable Field: Pull/Keeper Disabled                                                 Pull / Keep Select Field: Keeper                                                 Pull Up / Down Config. Field: 100K Ohm Pull Down                                                 Hyst. Enable Field: Hysteresis Disabled */

 

Next the TRACE clock settings must be checked and or modified in clock_config.c within function BOARD_BootClockRUN() to be the following:

/* Set TRACE_PODF. */

CLOCK_SetDiv(kCLOCK_TraceDiv, 0);

/* Set Trace clock source. */

CLOCK_SetMux(kCLOCK_TraceMux, 3);   

 

Finally the TRACE clock must be enabled on boot so insert the following in main() after BOARD_BootClockRUN():

// Enable SWO TRACE clock

*((uint32_t *)(0x400E0600)) = (1 << 11); /* enable TPIU clock */

CLOCK_EnableClock(kCLOCK_Trace);

 

 

Adding SWO tracing utility functions

Once the hardware is configured, we can now make use of the SWO pin to act as a JTAG back-channel for trace output instead of the much slower UART method. The utility functions enable you to send strings out of the SWO debug channel that can be read using the SWO ITM Console.

SWO.h:

/*

 * SWO.h

 *

 *  Created on: 27 Mar 2020

 */

 

#ifndef SWO_H_

#define SWO_H_

 

void SWO_PrintChar  (char c);

void SWO_PrintString(const char *s); 

 

#endif /* SWO_H_ */

 

SWO.c:

/*

 * SWO.c

 *

 *  Created on: 27 Mar 2020

 */

#include "SWO.h" /*******************************************************************************

 * Code

******************************************************************************/ 

 

/*********************************************************************  *

* Defines for Cortex-M debug unit

*/

/*********************************************************************   *

*       Defines for Cortex-M debug unit

*/

#define ITM_STIM_U32 (*(volatile unsigned int*)0xE0000000)    // Stimulus Port Register word access

#define ITM_STIM_U8  (*(volatile         char*)0xE0000000)    // Stimulus Port Register byte access

#define ITM_ENA      (*(volatile unsigned int*)0xE0000E00)    // Trace Enable Ports Register

#define ITM_TCR      (*(volatile unsigned int*)0xE0000E80)    // Trace control register

/**********************************************************************

*       SWO_PrintChar()

*

* Function description

*   Checks if SWO is set up. If it is not, return,

*    to avoid program hangs if no debugger is connected.

*   If it is set up, print a character to the ITM_STIM register

*    in order to provide data for SWO.

* Parameters

*   c:    The Character to be printed.

* Notes

*   Additional checks for device specific registers can be added.

*/

void SWO_PrintChar(char c) {

  volatile int timeout;

  //

  // Check if ITM_TCR.ITMENA is set

  //

  if ((ITM_TCR & 1) == 0) {

    return;

  }

  //

  // Check if stimulus port is enabled

  //

  if ((ITM_ENA & 1) == 0) {

    return;

  }

  //

  // Wait until STIMx is ready,

  // then send data

  //

  timeout = 5000; /* arbitrary timeout value */

  while ((ITM_STIM_U8 & 1) == 0)

  {

        /* Wait until STIMx is ready, then send data */

        timeout--;

        if (timeout==0) {

                return; /* not able to send */

        }

  }

  ITM_STIM_U8 = c;

}

 

/**********************************************************************

*       SWO_PrintString()

*

* Function description

*   Print a string via SWO.

*

*/

void SWO_PrintString(const char *s) {

  //

  // Print out character per character

  //

  while (*s) {

    SWO_PrintChar(*s++);

  }

}

 

To test the SWO output with your application include the SWO.h header file in your source and call the utility function to emit some sample trace output:

:

#include "board.h"

#include "peripherals.h"

#include "SWO.h"

:

SWO_PrintString("Hello world from SWO!");

 

Build the application and flash this to the board. When the board starts-up and halts with a breakpoint on main() then move on to the next step.

 

Configuring MCUXpresso for SWO ITM Console trace output

With MCUXpresso the Analysis menu gives access to the advanced trace windows for the IDE:

ssnider_1-1631802571851.png

 

 

 

First the SWO Trace Config needs to be configured to detect the link speed and add the ITM Console.  You may need to detect the SWO link by clicking Change -> Detect :

 

ssnider_2-1631802571890.png

 

 

If you select the SWO ITM Console and start the ITM Trace, then allow the debugger to run then you should see the trace output appear:

ssnider_3-1631802571913.png

 

 

Note you can stop and start the SWO trace without impacting the performance of the target application. You can even capture and save the ITM Trace Console contents to a file.

Similarly, if you are using J-Link with IAR then the i.MX RT1060 setup below can be used to emit the SWO trace data in real time and be viewed through the Terminal IO window and also logged to the local file ITM.log.

Note the default CPU clock speed of 528MHz.

 

J-Link -> SWO Configuration:

ssnider_4-1631802572005.png

 

Using SWO Tracing for Storyboard Performance logging:

Now that the SWO back-channel is proven we can reconfigure the project to use the SWO as the default route for the STDOUT and STDERR pipes so that application printf() content will appear out of on SWO ITM Console.

With NEWLIB this can be achieved by re-implementing the _write() and re-entrant _write_r() library functions.  Inserting the code snippet below will override the default library behavior:

#ifdef __NEWLIB__

/* For GCC compiler revise _write() and _write_r() functions for printf functionality

 * which enables the output from STDOUT and STDERR */

int _write(int file, char *ptr, int len)

{

    int i;

        file = file;

        //

        // Print out character per character

       //

    for( i=0; i < len; i++) {

        SWO_PrintChar( ptr[i] );

    }

    return len;

}

_ssize_t _write_r (struct _reent *reent, int fd, const void *ptr, size_t len)

{

        portENTER_CRITICAL();

        _write(fd, ptr,len);

        portEXIT_CRITICAL();

        return (_ssize_t)len;

}

#endif

 

Now it will be possible to enable performance tracing from a Storyboard application which emits PERF data to STDOUT and now have this streamed out of the SWO ITM Console:

Void

sbengine_main_task(void *arg) {

         char *args[20];

         int n = 0;

 

         // args[n++] = "screen_mgr";

         // args[n++] = "fps";

 

        args[n++] = "logger";

        args[n++] = "perf=1";

 

ssnider_5-1631802572055.png

 

 

The same can be done for Storyboard debug output by elevating the trace verbosity:

static void

run_storyboard_app(const char *bundle, int flags, char * const *options, int option_count) {

        app = gr_application_create_args(bundle, flags, options, option_count);

        if(!app) {

                return;

         }

         // Sets the application logging verbosity. For more logging verbosities, refer to gre.h.gr_application_debug(app, GR_DEBUG_CMD_VERBOSITY, GR_LOG_EVENT2 );//GR_LOG_ERROR);

 

 

ssnider_6-1631802572192.png

 

Issues:

 

There is a slight issue with MCUXpresso where the trace line output gets truncated every 100ms or so which will need some investigation as to the cause.

 

Labels (1)
0 Kudos
Reply
1 Reply

1,638 Views
gusarambula
NXP TechSupport
NXP TechSupport

Hello Ssnider,

Thank you for contributing to the communities with this post. I’m sure it will help other community users!

Regards,
Gustavo

0 Kudos
Reply