IAR EWARM Printf via SWO

文章來源:http://www.cnblogs.com/shangdawei/archive/2013/04/10/3011576.html


IAR編譯器使用SWO輸出調試信息設置:

Stdout and stderr of the application can be redirected to ITM stimulus port #0. 
It means that stdout/stderr messages (e.g. strings sent by printf) can be transferred 
from the target application to the C-SPY Terminal I/O window via SWD.SWO pin <JTAG.TDO pin>.



Requirements: 
Cortex-M3/M4 board; J-Link/J-Trace; 
IAR Embedded Workbench for ARM, V5.50.5 or later.

1. plus rerouting stdout/stderr messages via SWO (library low-level interface implementation, see the figure below).

2. except for enabling ITM stimulus port #0 and using it for routing data to the C-SPY Terminal I/O window.

3. Open the Terminal I/O window from the View menu. 
Start executing the application to collect Software Trace information. 
Stdout messages sent by printf( ) in the application will be displayed here via SWO Trace.

 

Semihosting技術

將應用程序中的IO請求通過一定的通道傳送到主機(host),由主機上的資源響應應用程序的IO請求,而不是像在主機上執行本地應用程序一樣,由應用程序所在的計算機響應應用程序IO請求,也就是將目標板的輸入/輸出請求從應用程序代碼傳遞到遠程運行調試器的主機的一種機制。

簡單來說,目標開發板上通常不會有輸入/輸出這些外設,開發板運行的代碼想要將結果打印出來,或者獲得用戶的輸入,可以通過請求遠程主機IO設備來實現,如:顯示器,鍵盤等。

目標開發板執行代碼中加入對輸入/輸出設備進行訪問函數,如:printf,scanf等,這些函數並不是目標開發板的庫函數,而是遠程主機交叉編譯器中帶有的庫函數,這些庫函數被編譯時,編譯成一條軟件中斷指令。

當目標開發板上電運行之後,執行到請求訪問輸入/輸出設備指令時,產生特定中斷號的軟件中斷SWI,與開發板相連的調試器會先截獲目標板SWI請求,由於開發板程序中也可能存在用戶自定義軟件中斷,爲了區分二者,調試器會根據SWI的軟中斷號來判斷是不是semihosting模式IO請求,如果是,則取出R0寄存器裏代表的具體請求號,然後使用遠程主機來響應目標板具體IO請求,而不是開發板本身去處理setmihosting請求。

semihosting僅僅是一種調試手段,它的工作原理就是利用調試器捕捉目標環境運行過程中產生SWI中斷,然後向遠程主機調試環境發送對應的調試信息。

也就是說目標開發板通過特定的軟件中斷指令,借用了遠程主機的輸入輸出設備實現IO請求的訪問。

Semihosting半主機調試模式,只能使用在開發板和調試主機通過仿真器連接的情況下,也就是說脫離了主機調試環境上述代碼不能正常運行。

目標開發板上執行的IO實際上是交給了遠程主機來處理實現,正是因爲如此,這種方式只適合在調試模式下,真正的嵌入式系統不可能依賴於主機實現IO處理的,嵌入式系統要想獨立出來實現IO請求的處理,這就需要將輸入輸出庫函數的底層相關硬件實現重定向。

新一代調試機制

使用ITM機制實現調試,實現printf與scanf, ITM是ARM在推出semihosting之後推出的新一代調試機制。ITM機制要求使用SWD方式接口,並需要連接SWO線。

 

 

 

It is only TX and not RX but most people just use printf for tracing anyways.

If you have a USB serial adapter, you can also use it as a SWO viewer, SWO is actually very similar to UART except using a much faster speed,

for example, with JLink, I can push it to 6MHz, which most USB serial adapters do not support.

The speed is incredibly important in timing critical debugging.

Remember, SWO is not just an application software printf style debugging, it is tied to ITM (instrumentation trace macrocell)

which enables software & hardware trace with timestamp. i.e it allows you to debug OS and application events.

It's not a problem to use SWO out in production code.

The SWO is separate from the debugger.

You can even run the SWO console w/o the debugger connected. 

Target 使用 SWO 的條件

  • 硬件條件:你得把芯片的SWO腳接到調試口上,按JTAG接線的話,這個默認已經接上了.
  • 代碼條件:你得把Printf的輸出函數,替換成SWO輸出函數,其實這個函數在CMSIS庫裏已經提供了,就在core_cm4.h裏面,如下:
複製代碼
/** \brief  ITM Send Character

    This function transmits a character via the ITM channel 0.
    It just returns when no debugger is connected that has booked the output.
    It is blocking when a debugger is connected, but the previous character send is not transmitted.

    \param [in]     ch  Character to transmit
    \return             Character to transmit
 */
static __INLINE uint32_t ITM_SendChar (uint32_t ch)
{
  if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk)  &&      /* Trace enabled */
      (ITM->TCR & ITM_TCR_ITMENA_Msk)                  &&      /* ITM enabled */
      (ITM->TER & (1UL << 0)        )                    )     /* ITM Port #0 enabled */
  {
    while (ITM->PORT[0].u32 == 0);
    ITM->PORT[0].u8 = (uint8_t) ch;
  }
  return (ch);
}
複製代碼

Redirecting/retargeting printf()

複製代碼
#include <stdio.h>
#include <stm32f4xx.h>
 
int fputc(int c, FILE *stream)
{
   return(ITM_SendChar(c);
}
複製代碼

SWO printf in IAR

The following steps demonstrate how to configure the SWO pin to output printf() statements in IAR.

1) Add #include to the beginning of the file where you want to write your printf statement.

2) Enable SWO Output.

The simplest way of enabling the SWO line in the EFM32 is by using the setupSWO function.

You can find this function in the energyAware Profiler, in the left pane, when you open up the program.

Once this is run, the SWO output will be enabled to the correct pin on the Development Kit or the Starter Kit.

3) Configure the project in IAR to send printf statements through SWO:

4) Write printf('Hello world'); in your code after you have enabled the SWO output.

5) Compile the code and download it to the Starter Kit/Development Kit. Enter a debug session.

6) Once you are in debug mode, you should set the correct SWO clock speed (14 MHz) in J-link->SWO Configuration...:

(The SWO output is clocked by the auxiliary HFRCO oscillator which is running at 14MHz regardless of the chosen system clock frequency.)

7) Open up View->Terminal I/O.

8) When you hit Go you should see the printf statement show up as below:

複製代碼
#ifndef LOG_LEVEL_LOWEST
#define LOG_LEVEL_LOWEST    _LOG_LEVEL_DEBUG
#endif

/**
 * Defines the default log level.
 */
#ifndef LOG_LEVEL_DEFAULT
#define LOG_LEVEL_DEFAULT   _LOG_LEVEL_INFO
#endif

#if LOG_LEVEL_LOWEST <= _LOG_LEVEL_TRACE
#define logTrace(MSG, ...)       __logLine(&_log, LOG_LEVEL_TRACE, MSG, ##__VA_ARGS__)
#else
#define logTrace(MSG, ...)
#endif

#if LOG_LEVEL_LOWEST <= _LOG_LEVEL_DEBUG
#define logDebug(MSG, ...)      __logLine(&_log, LOG_LEVEL_DEBUG, MSG, ##__VA_ARGS__)
#else
#define logDebug(MSG, ...)
#endif

#if LOG_LEVEL_LOWEST <= _LOG_LEVEL_INFO
#define logInfo(MSG, ...)       __logLine(&_log, LOG_LEVEL_INFO, MSG, ##__VA_ARGS__)
#else
#define logInfo(MSG, ...)
#endif

#if LOG_LEVEL_LOWEST <= _LOG_LEVEL_WARN
#define logWarn(MSG, ...)       __logLine(&_log, LOG_LEVEL_WARN, MSG, ##__VA_ARGS__)
#else
#define logWarn(MSG, ...)
#endif

#if LOG_LEVEL_LOWEST <= _LOG_LEVEL_ERROR
#define logError(MSG, ...)       __logLine(&_log, LOG_LEVEL_ERROR, MSG, ##__VA_ARGS__)
#else
#define logError(MSG, ...)
#endif
複製代碼
#ifdef DEBUG
   dbgPrintf(MSG, ...)     printf(MSG, ##__VA_ARGS__)
#else
   dbgPrintf(MSG, ...) 
#endif

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章