Serial Wire Output (SWO) viewer for tracing purposes. Tested on F401 and ST-LINK Utility as well as for F103 and Segger J-Link SWO viewer.

Dependents:   WiFi_Scanner mbed_nucleo_swo DISCO-F429ZI_LCDTS_demo_richard TEST_SM_SPEED

Committer:
wim
Date:
Tue Dec 23 21:05:52 2014 +0000
Revision:
3:e5af2e131b95
Parent:
2:ef928f61a770
Child:
4:53de8ef789f3
Added Class SWO_Channel that supports Stream putc() and printf().

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wim 1:bae4cff278f6 1 /* mbed SWO Library
wim 2:ef928f61a770 2 * Copyright (c) 2014, v01: WH. Ported from Segger example (www.segger.com)
wim 3:e5af2e131b95 3 * v02: WH. Added Class with Stream support
wim 1:bae4cff278f6 4 *
wim 2:ef928f61a770 5 * Simple implementation for tracing via Serial Wire Output(SWO) for Cortex-M processors.
wim 1:bae4cff278f6 6 * It can be used with Host PC software such as ST-LINK Utility or Segger J-Link SWO viewer.
wim 1:bae4cff278f6 7 * This sample implementation ensures that output via SWO is enabled in order to guarantee
wim 1:bae4cff278f6 8 * that the application does not hang.
wim 1:bae4cff278f6 9 *
wim 1:bae4cff278f6 10 * Permission is hereby granted, free of charge, to any person obtaining a copy
wim 1:bae4cff278f6 11 * of this software and associated documentation files (the "Software"), to deal
wim 1:bae4cff278f6 12 * in the Software without restriction, including without limitation the rights
wim 1:bae4cff278f6 13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
wim 1:bae4cff278f6 14 * copies of the Software, and to permit persons to whom the Software is
wim 1:bae4cff278f6 15 * furnished to do so, subject to the following conditions:
wim 1:bae4cff278f6 16 *
wim 1:bae4cff278f6 17 * The above copyright notice and this permission notice shall be included in
wim 1:bae4cff278f6 18 * all copies or substantial portions of the Software.
wim 1:bae4cff278f6 19 *
wim 1:bae4cff278f6 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
wim 1:bae4cff278f6 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
wim 1:bae4cff278f6 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
wim 1:bae4cff278f6 23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
wim 1:bae4cff278f6 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
wim 1:bae4cff278f6 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
wim 1:bae4cff278f6 26 * THE SOFTWARE.
wim 1:bae4cff278f6 27 */
wim 2:ef928f61a770 28 #include "mbed.h"
wim 0:0fd55660fc26 29 #include "SWO.h"
wim 0:0fd55660fc26 30
wim 3:e5af2e131b95 31 //
wim 3:e5af2e131b95 32 // This the Class implementation
wim 3:e5af2e131b95 33 //
wim 3:e5af2e131b95 34
wim 3:e5af2e131b95 35 /** Create and SWO interface for debugging that supports Stream
wim 3:e5af2e131b95 36 * @brief Currently works on nucleo ST-LINK using ST-Link Utility and other devices that support SWD/SWO using Segger SWO viewer
wim 3:e5af2e131b95 37 */
wim 3:e5af2e131b95 38 SWO_Channel::SWO_Channel () {
wim 3:e5af2e131b95 39 //May want to add initialisation stuff here
wim 3:e5af2e131b95 40 }
wim 3:e5af2e131b95 41
wim 3:e5af2e131b95 42 /** Write a single character (Stream implementation)
wim 3:e5af2e131b95 43 *
wim 3:e5af2e131b95 44 * @param value character to be displayed
wim 3:e5af2e131b95 45 * @return value
wim 3:e5af2e131b95 46 */
wim 3:e5af2e131b95 47 int SWO_Channel::_putc(int value) {
wim 3:e5af2e131b95 48
wim 3:e5af2e131b95 49 //Use CMSIS_core_DebugFunctions. See core_cm3.h
wim 3:e5af2e131b95 50 ITM_SendChar(value);
wim 3:e5af2e131b95 51
wim 3:e5af2e131b95 52 return value;
wim 3:e5af2e131b95 53 }
wim 3:e5af2e131b95 54
wim 3:e5af2e131b95 55 /** Get a single character (Stream implementation)
wim 3:e5af2e131b95 56 * @return -1 Not supported
wim 3:e5af2e131b95 57 */
wim 3:e5af2e131b95 58 int SWO_Channel::_getc() {
wim 3:e5af2e131b95 59 return -1;
wim 3:e5af2e131b95 60 }
wim 3:e5af2e131b95 61
wim 3:e5af2e131b95 62
wim 3:e5af2e131b95 63 //
wim 3:e5af2e131b95 64 //This is the classic implementation
wim 3:e5af2e131b95 65 //
wim 3:e5af2e131b95 66
wim 1:bae4cff278f6 67 /**
wim 1:bae4cff278f6 68 * Defines for Cortex-M debug unit
wim 1:bae4cff278f6 69 */
wim 3:e5af2e131b95 70 #define ITM_STIM_U32(n) (*(volatile unsigned int*) (0xE0000000+4*n)) // Stimulus Port n Register word access
wim 3:e5af2e131b95 71 #define ITM_STIM_U8(n) (*(volatile unsigned char*)(0xE0000000+4*n)) // Stimulus Port n Register byte access
wim 0:0fd55660fc26 72 //#define ITM_STIM_U32_0 (*(volatile unsigned int*)0xE0000000) // Stimulus Port 0 Register word access
wim 0:0fd55660fc26 73 //#define ITM_STIM_U8_0 (*(volatile char*)0xE0000000) // Stimulus Port 0 Register byte access
wim 0:0fd55660fc26 74 #define ITM_ENA (*(volatile unsigned int*)0xE0000E00) // Trace Enable Ports Register
wim 0:0fd55660fc26 75 #define ITM_TCR (*(volatile unsigned int*)0xE0000E80) // Trace control register
wim 0:0fd55660fc26 76
wim 2:ef928f61a770 77 #define ITM_STIM_FIFOREADY 0x00000001 // FIFO empty
wim 2:ef928f61a770 78
wim 2:ef928f61a770 79 //Stuff below is for documentation and needs further testing
wim 2:ef928f61a770 80 // It seems that the Segger SWO Viewer and the ST-Link Utility do most/all of these
wim 2:ef928f61a770 81 // initialisations on the target before starting the session. This is probably not the case
wim 2:ef928f61a770 82 // when using GDB/OpenOCD.
wim 2:ef928f61a770 83 //
wim 2:ef928f61a770 84 //
wim 2:ef928f61a770 85 #if(0)
wim 2:ef928f61a770 86 #include <libopencm3/stm32/rcc.h>
wim 2:ef928f61a770 87 #include <libopencm3/stm32/gpio.h>
wim 2:ef928f61a770 88
wim 2:ef928f61a770 89 #include <libopencm3/stm32/dbgmcu.h>
wim 2:ef928f61a770 90 #include <libopencm3/cm3/scs.h>
wim 2:ef928f61a770 91 #include <libopencm3/cm3/tpiu.h>
wim 2:ef928f61a770 92 #include <libopencm3/cm3/itm.h>
wim 2:ef928f61a770 93
wim 1:bae4cff278f6 94 /**
wim 2:ef928f61a770 95 * SWO_Setup() Example
wim 1:bae4cff278f6 96 *
wim 2:ef928f61a770 97 * This file is part of the libopencm3 project.
wim 2:ef928f61a770 98 *
wim 2:ef928f61a770 99 * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
wim 2:ef928f61a770 100 * https://github.com/1divf/libopenstm32/blob/master/examples/stm32/stm32-h103/traceswo/traceswo.c
wim 2:ef928f61a770 101 *
wim 2:ef928f61a770 102 */
wim 2:ef928f61a770 103 void SWO_Setup(void) {
wim 2:ef928f61a770 104 /* Enable trace subsystem (we'll use ITM and TPIU) */
wim 2:ef928f61a770 105 SCS_DEMCR |= SCS_DEMCR_TRCENA;
wim 2:ef928f61a770 106
wim 2:ef928f61a770 107 /* Use Manchester code for asynchronous transmission */
wim 2:ef928f61a770 108 TPIU_SPPR = TPIU_SPPR_ASYNC_MANCHESTER;
wim 2:ef928f61a770 109 TPIU_ACPR = 7;
wim 2:ef928f61a770 110
wim 2:ef928f61a770 111 /* Data width is 1 byte */
wim 2:ef928f61a770 112 TPIU_CSPSR = TPIU_CSPSR_BYTE;
wim 2:ef928f61a770 113
wim 2:ef928f61a770 114 /* Formatter and flush control */
wim 2:ef928f61a770 115 TPIU_FFCR &= ~TPIU_FFCR_ENFCONT;
wim 2:ef928f61a770 116
wim 2:ef928f61a770 117 /* Enable TRACESWO pin for async mode */
wim 2:ef928f61a770 118 DBGMCU_CR = DBGMCU_CR_TRACE_IOEN | DBGMCU_CR_TRACE_MODE_ASYNC;
wim 2:ef928f61a770 119
wim 2:ef928f61a770 120 /* Unlock access to ITM registers */
wim 2:ef928f61a770 121 /* FIXME: Magic numbers... Is this Cortex-M3 generic? */
wim 2:ef928f61a770 122 *((volatile uint32_t*)0xE0000FB0) = 0xC5ACCE55;
wim 2:ef928f61a770 123
wim 2:ef928f61a770 124 /* Enable ITM with ID = 1 */
wim 2:ef928f61a770 125 ITM_TCR = (1 << 16) | ITM_TCR_ITMENA;
wim 2:ef928f61a770 126 /* Enable stimulus port 1 */
wim 2:ef928f61a770 127 ITM_TER[0] = 1;
wim 2:ef928f61a770 128 }
wim 2:ef928f61a770 129
wim 2:ef928f61a770 130 /**
wim 2:ef928f61a770 131 * SWO_Setup() Example
wim 2:ef928f61a770 132 *
wim 2:ef928f61a770 133 * http://forum.segger.com/index.php?page=Thread&threadID=608
wim 2:ef928f61a770 134 *
wim 2:ef928f61a770 135 */
wim 2:ef928f61a770 136 void SWO_Setup_1(void) {
wim 2:ef928f61a770 137 U32 SWOPrescaler;
wim 2:ef928f61a770 138 U32 SWOSpeed;
wim 2:ef928f61a770 139
wim 2:ef928f61a770 140 //<Init PLL, set CPU clock to 72 MHz> // Optional, so I do not pos it here
wim 2:ef928f61a770 141
wim 2:ef928f61a770 142 SWOSpeed = 6000000;
wim 2:ef928f61a770 143 *((volatile unsigned *)0xE000EDFC) = 0x01000000; // "Debug Exception and Monitor Control Register (DEMCR)"
wim 2:ef928f61a770 144 *((volatile unsigned *)0xE0042004) = 0x00000027;
wim 2:ef928f61a770 145 *((volatile unsigned *)0xE00400F0) = 0x00000002; // "Selected PIN Protocol Register": Select which protocol to use for trace output (2: SWO)
wim 2:ef928f61a770 146 SWOPrescaler = (72000000 / SWOSpeed) - 1; // SWOSpeed in Hz
wim 2:ef928f61a770 147 *((volatile unsigned *)0xE0040010) = SWOPrescaler; // "Async Clock Prescaler Register". Scale the baud rate of the asynchronous output
wim 2:ef928f61a770 148 *((volatile unsigned *)0xE0000FB0) = 0xC5ACCE55; // ITM Lock Access Register, C5ACCE55 enables more write access to Control Register 0xE00 :: 0xFFC
wim 2:ef928f61a770 149 *((volatile unsigned *)0xE0000E80) = 0x0001000D; // ITM Trace Control Register
wim 2:ef928f61a770 150 *((volatile unsigned *)0xE0000E40) = 0x0000000F; // ITM Trace Privilege Register
wim 2:ef928f61a770 151 *((volatile unsigned *)0xE0000E00) = 0x00000001; // ITM Trace Enable Register. Enabled tracing on stimulus ports. One bit per stimulus port.
wim 2:ef928f61a770 152 *((volatile unsigned *)0xE0001000) = 0x400003FE; // DWT_CTRL
wim 2:ef928f61a770 153 *((volatile unsigned *)0xE0040304) = 0x00000100; // Formatter and Flush Control Register
wim 2:ef928f61a770 154 }
wim 2:ef928f61a770 155 #endif
wim 2:ef928f61a770 156
wim 2:ef928f61a770 157 /**
wim 1:bae4cff278f6 158 * SWO_PrintChar()
wim 1:bae4cff278f6 159 *
wim 1:bae4cff278f6 160 * @brief
wim 1:bae4cff278f6 161 * Checks if SWO is set up. If it is not, return,
wim 1:bae4cff278f6 162 * to avoid program hangs if no debugger is connected.
wim 1:bae4cff278f6 163 * If it is set up, print a character to the ITM_STIM register
wim 1:bae4cff278f6 164 * in order to provide data for SWO.
wim 1:bae4cff278f6 165 * @param c The Character to be printed.
wim 1:bae4cff278f6 166 * @notes Additional checks for device specific registers can be added.
wim 1:bae4cff278f6 167 */
wim 1:bae4cff278f6 168 void SWO_PrintChar(char c) {
wim 0:0fd55660fc26 169
wim 2:ef928f61a770 170 #if(1)
wim 2:ef928f61a770 171 //Use CMSIS_core_DebugFunctions. See core_cm3.h
wim 2:ef928f61a770 172 ITM_SendChar (c);
wim 2:ef928f61a770 173
wim 2:ef928f61a770 174 #else
wim 2:ef928f61a770 175 //Use Segger example. Basically same as CMSIS
wim 2:ef928f61a770 176
wim 0:0fd55660fc26 177 // Check if ITM_TCR.ITMENA is set
wim 0:0fd55660fc26 178 if ((ITM_TCR & 1) == 0) {
wim 0:0fd55660fc26 179 return;
wim 0:0fd55660fc26 180 }
wim 1:bae4cff278f6 181
wim 0:0fd55660fc26 182 // Check if stimulus port is enabled
wim 0:0fd55660fc26 183 if ((ITM_ENA & 1) == 0) {
wim 0:0fd55660fc26 184 return;
wim 0:0fd55660fc26 185 }
wim 0:0fd55660fc26 186
wim 1:bae4cff278f6 187 // Wait until STIMx FIFO is ready, then send data
wim 2:ef928f61a770 188 // while ((ITM_STIM_U8(0) & 1) == 0);
wim 2:ef928f61a770 189 while (!(ITM_STIM_U8(0) & ITM_STIM_FIFOREADY));
wim 1:bae4cff278f6 190 ITM_STIM_U8(0) = c;
wim 2:ef928f61a770 191
wim 1:bae4cff278f6 192 // while ((ITM_STIM_U32(0) & 1) == 0);
wim 1:bae4cff278f6 193 // ITM_STIM_U32(0) = c;
wim 2:ef928f61a770 194
wim 2:ef928f61a770 195 #endif
wim 0:0fd55660fc26 196 }
wim 0:0fd55660fc26 197
wim 1:bae4cff278f6 198 /**
wim 1:bae4cff278f6 199 * SWO_PrintString()
wim 1:bae4cff278f6 200 *
wim 1:bae4cff278f6 201 * @brief Print a string via SWO.
wim 1:bae4cff278f6 202 * @param *s The string to be printed.
wim 1:bae4cff278f6 203 *
wim 1:bae4cff278f6 204 */
wim 0:0fd55660fc26 205 void SWO_PrintString(const char *s) {
wim 1:bae4cff278f6 206
wim 1:bae4cff278f6 207 // Print out characters until \0
wim 0:0fd55660fc26 208 while (*s) {
wim 0:0fd55660fc26 209 SWO_PrintChar(*s++);
wim 0:0fd55660fc26 210 }
wim 3:e5af2e131b95 211 }
wim 3:e5af2e131b95 212
wim 3:e5af2e131b95 213
wim 3:e5af2e131b95 214