j-link edu连接到跟踪端口
通过SWO引脚发送调试信息的源码
为了通过SWO写调试消息到主机,需要一小段代码。在Github上有一个可用的完整代码的例子项目:
https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/KDS/TWR-K64F120M/TWR-K64F120M_Demo/Sources
外部工具(比如Segger RTT查看器)可以在硬件中设置SWO。我的建议是从应用程序初始化它。因为SWO跟踪输出时钟是从CPU时钟派生而来的,所以初始化函数需要这个时钟加上SWO端口号来初始化。下面是我用来初始化SWO输出的代码,默认为64k波特率:
/*!
* rief Initialize the SWO traceport for debug message printing
* param portBits Port bit mask tobe configured
* param cpuCoreFreqHz CPU core clockfrequency in Hz
*/
void SWO_Init(uint32_t portBits,uint32_t cpuCoreFreqHz) {
uint32_t SWOSpeed = 64000;/* default 64k baud rate */
uint32_t SWOPrescaler =(cpuCoreFreqHz / SWOSpeed) - 1; /* SWOSpeed in Hz, note that cpuCoreFreqHz isexpected to be match the CPU core clock */
CoreDebug->DEMCR =CoreDebug_DEMCR_TRCENA_Msk; /* enable trace in core debug */
*((volatile unsigned*)(ITM_BASE + 0x400F0)) = 0x00000002; /* "Selected PIN ProtocolRegister": Select which protocol to use for trace output (2: SWO NRZ, 1:SWO Manchester encoding) */
*((volatile unsigned*)(ITM_BASE + 0x40010)) = SWOPrescaler; /* "Async Clock PrescalerRegister". Scale the baud rate of the asynchronous output */
*((volatile unsigned*)(ITM_BASE + 0x00FB0)) = 0xC5ACCE55; /* ITM Lock Access Register, C5ACCE55enables more write access to Control Register 0xE00 :: 0xFFC */
ITM->TCR =ITM_TCR_TraceBusID_Msk | ITM_TCR_SWOENA_Msk | ITM_TCR_SYNCENA_Msk |ITM_TCR_ITMENA_Msk; /* ITM Trace Control Register */
ITM->TPR = ITM_TPR_PRIVMASK_Msk;/* ITM Trace Privilege Register */
ITM->TER = portBits; /*ITM Trace Enable Register. Enabled tracing on stimulus ports. One bit perstimulus port. */
*((volatile unsigned*)(ITM_BASE + 0x01000)) = 0x400003FE; /* DWT_CTRL */
*((volatile unsigned*)(ITM_BASE + 0x40304)) = 0x00000100; /* Formatter and Flush Control Register*/
}
在我的主应用程序中,我像这样初始化它(对于一个有24MHz核心时钟的系统):
#define CPU_CORE_FREQUENCY_HZ 120000000/* CPU core frequency in Hz */
SWO_Init(0x1,CPU_CORE_FREQUENCY_HZ);
在SWO_PrintChar()函数中完成打印:
/*!
* rief Sends a character overthe SWO channel
* param c Character to be sent
* param portNo SWO channelnumber, value in the range of 0 to 31
*/
void SWO_PrintChar(char c, uint8_t portNo) {
volatile int timeout;
/* Check if Trace ControlRegister (ITM->TCR at 0xE0000E80) is set */
if ((ITM->TCR&ITM_TCR_ITMENA_Msk) == 0){ /* check Trace Control Register if ITM trace is enabled*/
return; /* notenabled? */
}
/* Check if the requestedchannel stimulus port (ITM->TER at 0xE0000E00) is enabled */
return; /*requested port not enabled? */
}
timeout = 5000; /* arbitrarytimeout value */
while (ITM->PORT[0].u32 == 0) {
/* Wait untilSTIMx is ready, then send data */
timeout--;
if (timeout==0) {
return;/* not able to send */
}
}
ITM->PORT[0].u16 = 0x08 |(c<<8);
}
上面的代码使用了一个非常简单的超时机制:重要的一点是,如果SWO没有启用或者SWO端口没有准备好,那么应用程序就会被阻塞。
为了更方便地打印字符串,我使用以下函数:
/*!
* riefSends a string over SWO to the host
* param sString to send
* paramportNumber Port number, 0-31, use 0 for normal debug strings
*/
void SWO_PrintString(const char *s, uint8_tportNumber) {
while(*s!='