环境
- 系统:Windows 10
- SDK:simplelink_cc13x2_26x2_sdk_4_30_00_54
- IDE:Code Composer Studio, Version: 10.1.1.00004
- 例程:simple_peripheral_oad_offchip_CC26X2R1_LAUNCHXL_tirtos_ccs (已删除不必要的代码,请看:删除simple_peripheral_oad_offchip工程多余的代码)
原因
问:为什么要使用 System_printf ?
答:因为Display每次打印都会换行。
1. 移除 Display
2. 配置打印UART
3. 更改配置文件
- 启用TI-RTOS的打印;
- 重定向 myUserPutch(char ch)函数;
- 实现 myUserFlush() 刷新函数。
/*
* The System.SupportProxy defines a low-level implementation of System
* functions such as System_printf(), System_flush(), etc.
*
* Pick one pair:
* - SysMin
* This module maintains an internal configurable circular buffer that
* stores the output until System_flush() is called.
* The size of the circular buffer is set via SysMin.bufSize.
* - SysCallback
* SysCallback allows for user-defined implementations for System APIs.
* The SysCallback support proxy has a smaller code footprint and can be
* used to supply custom System_printf services.
* The default SysCallback functions point to stub functions. See the
* SysCallback module's documentation.
*/
//var SysMin = xdc.useModule('xdc.runtime.SysMin');
//SysMin.bufSize = 768;
//System.SupportProxy = SysMin;
var SysCallback = xdc.useModule('xdc.runtime.SysCallback');
System.SupportProxy = SysCallback;
//SysCallback.abortFxn = "&myUserAbort";
//SysCallback.exitFxn = "&myUserExit";
SysCallback.flushFxn = "&myUserFlush";
SysCallback.putchFxn = "&myUserPutch";
//SysCallback.readyFxn = "&myUserReady";
//var Idle = xdc.useModule('ti.sysbios.knl.Idle');
//Idle.addFunc('&myUserFlush');
4. 代码
4.1. C文件
#include "user/debug/debug.h"
/*********************************************************************
* CONSTANTS
*/
#define UART_PRINTF_BUF_LEN 128
/*********************************************************************
* LOCAL VARIABLES
*/
static uint8_t uartPrintf_outArray[UART_PRINTF_BUF_LEN];
static uint16_t uartPrintf_head = 0;
static uint16_t uartPrintf_tail = 0;
static UART_Handle hUart = NULL;
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn DebugPrintf_init
*
* @brief Initializes the putchar hooks with the handle to the UART.
*
* @param handle - UART driver handle to an initialized and opened UART.
*
* @return None.
*/
void DebugPrintf_init(UART_Handle handle)
{
hUart = handle;
}
/*********************************************************************
* SYSTEM HOOK FUNCTIONS
*/
/*********************************************************************
* @fn myUserPutch
*
* @brief User supplied PutChar function.
* typedef Void (*SysCallback_PutchFxn)(Char);
*
* This function is called whenever the System module needs
* to output a character.
*
* This implementation fills a very basic ring-buffer, and relies
* on another function to flush this buffer out to UART.
*
* Requires SysCallback to be the system provider module.
* Initialized via SysCallback.putchFxn = "&myUserPutch"; in the
* TI-RTOS configuration script.
*
* @param ch - Character
*
* @return None.
*
* @post ::uartPrintf_head is incremented by one with wrap at UART_PRINTF_BUF_LEN
* if there is room.
*/
void myUserPutch(char ch)
{
// uartPrintf_tail should never catch up with uartPrintf_head. Discard in-between bytes.
if ( (uartPrintf_head + 1) % UART_PRINTF_BUF_LEN == uartPrintf_tail )
return;
uartPrintf_outArray[uartPrintf_head] = ch;
uartPrintf_head++;
if (uartPrintf_head >= UART_PRINTF_BUF_LEN)
uartPrintf_head = 0;
}
/*********************************************************************
* @fn myUserFlush
*
* @brief Printf-buffer flush function
*
* In this implementation it is intended to be called by the
* Idle task when nothing else is running.
*
* This is achieved by setting up the Idle task in the TI-RTOS
* configuration script like so:
*
* var SysCallback = xdc.useModule('xdc.runtime.SysCallback');
* System.SupportProxy = SysCallback;
* SysCallback.flushFxn = "&myUserFlush";
*
* @param None. Relies on global state.
*
* @return None.
*
* @post ::uartPrintf_tail is incremented to where uartPrintf_head
* was at the time the function was called.
*/
void myUserFlush(void)
{
// Abort in case UART hasn't been initialized.
if (NULL == hUart)
return;
// Lock head position to avoid race conditions
uint16_t curHead = uartPrintf_head;
// Find out how much data must be output, and how to output it.
bool needWrap = curHead < uartPrintf_tail;
uint16_t outLen = needWrap?(UART_PRINTF_BUF_LEN-uartPrintf_tail+curHead):(curHead-uartPrintf_tail);
if (outLen)
{
if (needWrap)
{
UART_write(hUart, &uartPrintf_outArray[uartPrintf_tail], UART_PRINTF_BUF_LEN - uartPrintf_tail);
UART_write(hUart, uartPrintf_outArray, curHead);
}
else
{
UART_write(hUart, &uartPrintf_outArray[uartPrintf_tail], outLen);
}
}
uartPrintf_tail = curHead;
}
4.2. 头文件
#ifndef USER_DEBUG_DEBUG_H_
#define USER_DEBUG_DEBUG_H_
#include <stdint.h>
#include <stdbool.h>
#include <ti/display/Display.h>
#include <xdc/runtime/System.h>
#include <ti/drivers/UART.h>
extern Display_Handle dispHandle;
extern void DebugPrintf_init(UART_Handle handle);
extern void myUserFlush(void);
/*
* Display module will output "\n" every times
*
*/
#if !defined(Display_DISABLE_ALL) || (!Display_DISABLE_ALL)
#define Debug(fmt, ...) Display_printf(dispHandle, 0, 0, fmt, ##__VA_ARGS__)
#else
#define DEBUG_NEW_LINE "\r\n"
#define Debug(fmt, ...) do{System_printf(fmt, ##__VA_ARGS__);myUserFlush();}while(0)
#define Debugln(fmt, ...) do{System_printf(fmt, ##__VA_ARGS__);System_printf(DEBUG_NEW_LINE);myUserFlush();}while(0)
#define DebugHex(buf, len) do{for(uint8_t _z = 0; _z < len; _z++)\
{System_printf("%02x ", buf[_z]);} \
System_printf(DEBUG_NEW_LINE);\
myUserFlush();}\
while(0)
# undef Display_init
# undef Display_open
# undef Display_Params_init
# undef Display_clear
# undef Display_clearLines
# undef Display_printf
# undef Display_print0
# undef Display_print1
# undef Display_print2
# undef Display_print3
# undef Display_print4
# undef Display_print5
# undef Display_vprintf
# undef Display_getType
# undef Display_control
# undef Display_close
# define Display_init()
# define Display_open(id, params) NULL
# define Display_Params_init(params)
# define Display_clear(handle)
# define Display_clearLines(handle, fromLine, toLine)
# define Display_printf(handle, line, col, fmt, ...) Debugln(fmt, ##__VA_ARGS__);
# define Display_print0(handle, line, col, fmt) Debugln(fmt)
# define Display_print1(handle, line, col, fmt, a0) Debugln(fmt, a0)
# define Display_print2(handle, line, col, fmt, a0, a1) Debugln(fmt, a0, a1)
# define Display_print3(handle, line, col, fmt, a0, a1, a2) Debugln(fmt, a0, a1, a2)
# define Display_print4(handle, line, col, fmt, a0, a1, a2, a3) Debugln(fmt, a0, a1, a2, a3)
# define Display_print5(handle, line, col, fmt, a0, a1, a2, a3, a4) Debugln(fmt, a0, a1, a2, a3, a4)
# define Display_vprintf(handle, line, col, fmt, va) Debugln(fmt, va)
# define Display_getType(handle) Display_Type_INVALID
# define Display_control(handle, cmd, arg) (DISPLAY_STATUS_UNDEFINEDCMD)
# define Display_close(handle)
#endif
#endif /* USER_DEBUG_DEBUG_H_ */
5. 刷新方法
- 即时刷新
调用 System_printf() 后调用 myUserFlush()。
var SysCallback = xdc.useModule('xdc.runtime.SysCallback');
System.SupportProxy = SysCallback;
//SysCallback.abortFxn = "&myUserAbort";
//SysCallback.exitFxn = "&myUserExit";
SysCallback.flushFxn = "&myUserFlush";
SysCallback.putchFxn = "&myUserPutch";
//SysCallback.readyFxn = "&myUserReady";
//var Idle = xdc.useModule('ti.sysbios.knl.Idle');
//Idle.addFunc('&myUserFlush');
#define DEBUG_NEW_LINE "\r\n"
#define Debug(fmt, ...) do{System_printf(fmt, ##__VA_ARGS__);myUserFlush();}while(0)
#define Debugln(fmt, ...) do{System_printf(fmt, ##__VA_ARGS__);System_printf(DEBUG_NEW_LINE);myUserFlush();}while(0)
#define DebugHex(buf, len) do{for(uint8_t _z = 0; _z < len; _z++)\
{System_printf("%02x ", buf[_z]);} \
System_printf(DEBUG_NEW_LINE);\
myUserFlush();}\
while(0)
- 空闲刷新
空闲刷新是使用 Idle 任务在睡眠前调用myUserFlush()进行刷新。
var SysCallback = xdc.useModule('xdc.runtime.SysCallback');
System.SupportProxy = SysCallback;
//SysCallback.abortFxn = "&myUserAbort";
//SysCallback.exitFxn = "&myUserExit";
SysCallback.flushFxn = "&myUserFlush";
SysCallback.putchFxn = "&myUserPutch";
//SysCallback.readyFxn = "&myUserReady";
var Idle = xdc.useModule('ti.sysbios.knl.Idle');
Idle.addFunc('&myUserFlush');
#define DEBUG_NEW_LINE "\r\n"
#define Debug(fmt, ...) do{System_printf(fmt, ##__VA_ARGS__);}while(0)
#define Debugln(fmt, ...) do{System_printf(fmt, ##__VA_ARGS__);System_printf(DEBUG_NEW_LINE);}while(0)
#define DebugHex(buf, len) do{for(uint8_t _z = 0; _z < len; _z++)\
{System_printf("%02x ", buf[_z]);} \
System_printf(DEBUG_NEW_LINE);\
while(0)