
??默認適配
注:若用戶未使能 stdio function 時,調用printf函數時,將不會有任何輸出。


??重定向至其他設備
與UART設備不同,USB設備為動態設備,因此重定向printf函數時,需要注意以下幾個關鍵步驟:
由于AWorksLP中利用posix file相關操作接口對printf函數進行適配,故在重映射端口時,需將 support libc file operations 使能,并取消默認選擇UART設備作為printf函數的適配,具體如下圖所示。

USB設備為動態設備,因此需要持續檢測設備的是否存在情況。可通過初始化一個動態設備檢測任務,對設備的是否存在情況進行周期性檢測。
while true:? ?access (device)? ?delay()
在檢測到USB設備存在時,僅需將設備與標準文件流(stdio中的stdin、stdout、stderr,且在C庫中被假定為交互設備,并約定了這些設備的文件描述符依次為0、1、2)關聯起來。故在使用時,我們僅需將描述符0、1、2與USB串口設備即可,其偽代碼如下所示。
while true:if access (device):0 = open (device)duplicate 1 to 0duplicate 2 to 0delay()
1.4 清理文件描述符
while true:? ?if access (device):? ? ? ?0 = open (device)? ? ? ?duplicate 1 to 0? ? ? ?duplicate 2 to 0? ?else:? ? ? ?close (device)? ?delay()

3.?簡單示例
static int __dynamic_stdin_fd = -1;static aw_err_t __dynamic_stdout_ret = -AW_EBADF;static aw_err_t __dynamic_stderr_ret = -AW_EBADF;aw_err_t aw_printf_redirect_dynamic_dev(void){? ?int find = -AW_ENODEV;? ?// 檢測動態設備? ?find = aw_access(AW_DYNAMIC_DEV_PATH, AW_F_OK);? ?if(find == AW_OK) {? ? ? ?// 關聯標準文件流? ? ? ?if(__dynamic_stdin_fd < 0)? ? ? ?{? ? ? ? ? ?__dynamic_stdin_fd = \? ? ? ? ? ? aw_open_at(AW_DYNAMIC_DEV_PATH,AW_O_RDWR,0,0);? ? ? ? ? ?__dynamic_stdout_ret = aw_dup2(0, 1);? ? ? ? ? ?__dynamic_stderr_ret = aw_dup2(0, 2);? ? ? ? ? ?return AW_OK;? ? ? ?}? ?}? ?else {? ? ? ?// 清理文件描述符? ? ? ?if(__dynamic_stdin_fd >= 0) {? ? ? ? ? ?aw_close(0);? ? ? ? ? ?__dynamic_stdin_fd = -1;? ? ? ?}? ? ? ?if (__dynamic_stdout_ret == AW_OK) {? ? ? ? ? ?aw_close(1);? ? ? ? ? ?__dynamic_stdout_ret = -AW_EBADF;? ? ? ?}? ? ? ?if (__dynamic_stderr_ret == AW_OK) {? ? ? ? ? ?aw_close(2);? ? ? ? ? ?__dynamic_stderr_ret = -AW_EBADF;? ? ? ?}? ?}? ?return -AW_ENODEV;}int aw_main(void){? ?int ret;? ?aw_kprintf("hello world\n");? ?printf("hello world\n");? ?while(1) {? ? ? ?ret = aw_printf_redirect_dynamic_dev();? ? ? ?if (AW_OK == ret)? ? ? ? ? ?break;? ? ? ?// 設置檢測周期? ? ? ?AW_TASK_DELAY(100);? ?}? ?aw_kprintf("hello world, ZLG\n");? ?printf("hello world, ZLG\n");? ?return 0;}


??總結
??擴展閱讀本文所演示平臺使用的是GCC編譯器,其對應C庫為NEWLIB標準庫。在AWorksLP中printf函數的底層輸出接口在AWorksLP中實現為_write_r 函數,其具體代碼實現如下所示。
__attribute__((__used__)) _ssize_t_write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes){? ?return aw_write(fd,buf,nbytes);}
需要值得注意的是,上述適配方式僅兼容NEWLIB,若是其他編譯器,其實現以及接口不盡相同,下表僅給出部分以供參考,在使用時需根據實際情況進行調整。
工具鏈 | 標準庫 | 底層接口 |
GCC | NEWLIB | _write_r |
ARMCC | ARMCLIB | _sys_write |
ARMCLANG | ARMCLIB | _sys_write |
??關聯產品
??技術交流群
更多往期文章,請點擊“?閱讀原文?”。






