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
SWO.cpp
00001 /* mbed SWO Library 00002 * Copyright (c) 2014, v01: WH. Ported from Segger example (www.segger.com) 00003 * v02: WH. Added Class with Stream support 00004 * 2017, v03: WH,PS. Added stream claim for stdout, proposed by Pavel Sorejs 00005 * 00006 * Simple implementation for tracing via Serial Wire Output(SWO) for Cortex-M processors. 00007 * It can be used with Host PC software such as ST-LINK Utility or Segger J-Link SWO viewer. 00008 * This sample implementation ensures that output via SWO is enabled in order to guarantee 00009 * that the application does not hang. 00010 * 00011 * Permission is hereby granted, free of charge, to any person obtaining a copy 00012 * of this software and associated documentation files (the "Software"), to deal 00013 * in the Software without restriction, including without limitation the rights 00014 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00015 * copies of the Software, and to permit persons to whom the Software is 00016 * furnished to do so, subject to the following conditions: 00017 * 00018 * The above copyright notice and this permission notice shall be included in 00019 * all copies or substantial portions of the Software. 00020 * 00021 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00022 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00023 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00024 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00025 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00026 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00027 * THE SOFTWARE. 00028 */ 00029 #include "mbed.h" 00030 #include "SWO.h" 00031 00032 // 00033 // This the Class implementation 00034 // 00035 00036 /** Create and SWO interface for debugging that supports Stream 00037 * @brief Currently works on nucleo ST-LINK using ST-Link Utility and other devices that support SWD/SWO using Segger SWO viewer 00038 */ 00039 SWO_Channel::SWO_Channel (const char *name) : Stream(name) { 00040 //May want to add initialisation stuff here 00041 } 00042 00043 00044 /** Write a single character (Stream implementation) 00045 * 00046 * @param value character to be displayed 00047 * @return value 00048 */ 00049 int SWO_Channel::_putc(int value) { 00050 00051 //Use CMSIS_core_DebugFunctions. See core_cm3.h 00052 ITM_SendChar(value); 00053 00054 return value; 00055 } 00056 00057 /** Get a single character (Stream implementation) 00058 * @return -1 Not supported 00059 */ 00060 int SWO_Channel::_getc() { 00061 return -1; 00062 } 00063 00064 /** 00065 * Claim and redirect a stream to this SWO object 00066 * Important: A name parameter must have been added when creating the SWO object. 00067 * 00068 * @param FILE *stream The stream to redirect (default = stdout) 00069 * @return true if succeeded, else false 00070 */ 00071 bool SWO_Channel::claim (FILE *stream) { 00072 if ( FileBase::getName() == NULL) { 00073 error("claim requires a name to be given in the instantiator of the SWO instance!\r\n"); 00074 } 00075 00076 //Add '/' before name: 00077 char *path = new char[strlen(FileBase::getName()) + 2]; 00078 sprintf(path, "/%s", FileBase::getName()); 00079 00080 if (freopen(path, "w", stream) == NULL) { 00081 // Failed, should not happen 00082 return false; 00083 } 00084 00085 delete(path); 00086 00087 //No buffering 00088 setvbuf(stream, NULL, _IONBF, 32); 00089 return true; 00090 } 00091 00092 00093 00094 // 00095 //This is the classic implementation 00096 // 00097 00098 /** 00099 * Defines for Cortex-M debug unit 00100 */ 00101 #define ITM_STIM_U32(n) (*(volatile unsigned int*) (0xE0000000+4*n)) // Stimulus Port n Register word access 00102 #define ITM_STIM_U8(n) (*(volatile unsigned char*)(0xE0000000+4*n)) // Stimulus Port n Register byte access 00103 //#define ITM_STIM_U32_0 (*(volatile unsigned int*)0xE0000000) // Stimulus Port 0 Register word access 00104 //#define ITM_STIM_U8_0 (*(volatile char*)0xE0000000) // Stimulus Port 0 Register byte access 00105 #define ITM_ENA (*(volatile unsigned int*)0xE0000E00) // Trace Enable Ports Register 00106 #define ITM_TCR (*(volatile unsigned int*)0xE0000E80) // Trace control register 00107 00108 #define ITM_STIM_FIFOREADY 0x00000001 // FIFO empty 00109 00110 //Stuff below is for documentation and needs further testing 00111 // It seems that the Segger SWO Viewer and the ST-Link Utility do most/all of these 00112 // initialisations on the target before starting the session. This is probably not the case 00113 // when using GDB/OpenOCD. 00114 // 00115 // 00116 #if(0) 00117 #include <libopencm3/stm32/rcc.h> 00118 #include <libopencm3/stm32/gpio.h> 00119 00120 #include <libopencm3/stm32/dbgmcu.h> 00121 #include <libopencm3/cm3/scs.h> 00122 #include <libopencm3/cm3/tpiu.h> 00123 #include <libopencm3/cm3/itm.h> 00124 00125 /** 00126 * SWO_Setup() Example 00127 * 00128 * This file is part of the libopencm3 project. 00129 * 00130 * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de> 00131 * https://github.com/1divf/libopenstm32/blob/master/examples/stm32/stm32-h103/traceswo/traceswo.c 00132 * 00133 */ 00134 void SWO_Setup(void) { 00135 /* Enable trace subsystem (we'll use ITM and TPIU) */ 00136 SCS_DEMCR |= SCS_DEMCR_TRCENA; 00137 00138 /* Use Manchester code for asynchronous transmission */ 00139 TPIU_SPPR = TPIU_SPPR_ASYNC_MANCHESTER; 00140 TPIU_ACPR = 7; 00141 00142 /* Data width is 1 byte */ 00143 TPIU_CSPSR = TPIU_CSPSR_BYTE; 00144 00145 /* Formatter and flush control */ 00146 TPIU_FFCR &= ~TPIU_FFCR_ENFCONT; 00147 00148 /* Enable TRACESWO pin for async mode */ 00149 DBGMCU_CR = DBGMCU_CR_TRACE_IOEN | DBGMCU_CR_TRACE_MODE_ASYNC; 00150 00151 /* Unlock access to ITM registers */ 00152 /* FIXME: Magic numbers... Is this Cortex-M3 generic? */ 00153 *((volatile uint32_t*)0xE0000FB0) = 0xC5ACCE55; 00154 00155 /* Enable ITM with ID = 1 */ 00156 ITM_TCR = (1 << 16) | ITM_TCR_ITMENA; 00157 /* Enable stimulus port 1 */ 00158 ITM_TER[0] = 1; 00159 } 00160 00161 /** 00162 * SWO_Setup() Example 00163 * 00164 * http://forum.segger.com/index.php?page=Thread&threadID=608 00165 * 00166 */ 00167 void SWO_Setup_1(void) { 00168 U32 SWOPrescaler; 00169 U32 SWOSpeed; 00170 00171 //<Init PLL, set CPU clock to 72 MHz> // Optional, so I do not pos it here 00172 00173 SWOSpeed = 6000000; 00174 *((volatile unsigned *)0xE000EDFC) = 0x01000000; // "Debug Exception and Monitor Control Register (DEMCR)" 00175 *((volatile unsigned *)0xE0042004) = 0x00000027; 00176 *((volatile unsigned *)0xE00400F0) = 0x00000002; // "Selected PIN Protocol Register": Select which protocol to use for trace output (2: SWO) 00177 SWOPrescaler = (72000000 / SWOSpeed) - 1; // SWOSpeed in Hz 00178 *((volatile unsigned *)0xE0040010) = SWOPrescaler; // "Async Clock Prescaler Register". Scale the baud rate of the asynchronous output 00179 *((volatile unsigned *)0xE0000FB0) = 0xC5ACCE55; // ITM Lock Access Register, C5ACCE55 enables more write access to Control Register 0xE00 :: 0xFFC 00180 *((volatile unsigned *)0xE0000E80) = 0x0001000D; // ITM Trace Control Register 00181 *((volatile unsigned *)0xE0000E40) = 0x0000000F; // ITM Trace Privilege Register 00182 *((volatile unsigned *)0xE0000E00) = 0x00000001; // ITM Trace Enable Register. Enabled tracing on stimulus ports. One bit per stimulus port. 00183 *((volatile unsigned *)0xE0001000) = 0x400003FE; // DWT_CTRL 00184 *((volatile unsigned *)0xE0040304) = 0x00000100; // Formatter and Flush Control Register 00185 } 00186 #endif 00187 00188 /** 00189 * SWO_PrintChar() 00190 * 00191 * @brief 00192 * Checks if SWO is set up. If it is not, return, 00193 * to avoid program hangs if no debugger is connected. 00194 * If it is set up, print a character to the ITM_STIM register 00195 * in order to provide data for SWO. 00196 * @param c The Character to be printed. 00197 * @notes Additional checks for device specific registers can be added. 00198 */ 00199 void SWO_PrintChar(char c) { 00200 00201 #if(1) 00202 //Use CMSIS_core_DebugFunctions. See core_cm3.h 00203 ITM_SendChar (c); 00204 00205 #else 00206 //Use Segger example. Basically same as CMSIS 00207 00208 // Check if ITM_TCR.ITMENA is set 00209 if ((ITM_TCR & 1) == 0) { 00210 return; 00211 } 00212 00213 // Check if stimulus port is enabled 00214 if ((ITM_ENA & 1) == 0) { 00215 return; 00216 } 00217 00218 // Wait until STIMx FIFO is ready, then send data 00219 // while ((ITM_STIM_U8(0) & 1) == 0); 00220 while (!(ITM_STIM_U8(0) & ITM_STIM_FIFOREADY)); 00221 ITM_STIM_U8(0) = c; 00222 00223 // while ((ITM_STIM_U32(0) & 1) == 0); 00224 // ITM_STIM_U32(0) = c; 00225 00226 #endif 00227 } 00228 00229 /** 00230 * SWO_PrintString() 00231 * 00232 * @brief Print a string via SWO. 00233 * @param *s The string to be printed. 00234 * 00235 */ 00236 void SWO_PrintString(const char *s) { 00237 00238 // Print out characters until \0 00239 while (*s) { 00240 SWO_PrintChar(*s++); 00241 } 00242 } 00243 00244 00245
Generated on Wed Jul 13 2022 12:16:26 by 1.7.2