国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

嵌入式系統(tǒng)上的簡(jiǎn)易printf

發(fā)布時(shí)間:2009-11-27 19:09    發(fā)布者:linux_Ultra
關(guān)鍵詞: printf , 嵌入式系統(tǒng)
嵌入式系統(tǒng)上的簡(jiǎn)易printf
windstorm on 2008-12-30,17:02 1,097 views Comments (3)
此文針對(duì)嵌入式軟件的業(yè)余初學(xué)者,高手請(qǐng)自行路過(guò)打醬油。
嵌入式中,調(diào)試手段通常有兩種,一是遠(yuǎn)程gdb,一是直接printf。如果是調(diào)試自己玩的小板子,用gdb有點(diǎn)大張旗鼓了,大多數(shù)情況下printf就可以搞定。不過(guò)printf的問(wèn)題是stdiolib的size太大,稍微有點(diǎn)程序,加上幾個(gè)常用的庫(kù),比如stdio和string,超過(guò)16k甚至32k(已經(jīng)大于一些低端芯片的flash容量了)是很正常的事情,而且通常比較慢,程序越多,越麻煩。道理很簡(jiǎn)單,標(biāo)準(zhǔn)C語(yǔ)言庫(kù)的規(guī)范中,Printf()必須處理大量的數(shù)據(jù)格式,包括字符串、字符、(各種長(zhǎng)度的有符號(hào)和無(wú)符號(hào))數(shù)字,以及浮點(diǎn)值。而且格式字符串還要包括用于更改文本對(duì)齊、基數(shù)、間距、字段寬度和精度的調(diào)節(jié)器和指示器。符合這個(gè)規(guī)范的代碼必然會(huì)是冗長(zhǎng)和繁重的。一些嵌入式系統(tǒng)庫(kù)倒是提供了一些之針對(duì)整數(shù)的printf,但還是有問(wèn)題,首先是還是太大,其次是你沒(méi)有自己的調(diào)整權(quán)限。
其實(shí)printf也就是IO的調(diào)用包裝而已,我們完全可以自己寫(xiě)一個(gè)簡(jiǎn)易版本的printf滿足自己的需要,并隨時(shí)根據(jù)需要裁剪。具體來(lái)說(shuō),printf在這里要起的作用就是將調(diào)試字符串從嵌入式目標(biāo)空閑的串口壓出,并在運(yùn)行于宿主工作站的終端模擬器上顯示結(jié)果。下面就簡(jiǎn)單介紹一下,如何來(lái)自己寫(xiě)一個(gè)簡(jiǎn)易printf函數(shù)。


要寫(xiě)printf,首先要知道什么是可變參數(shù)傳遞,我們來(lái)看看標(biāo)準(zhǔn)庫(kù)里面,是如何定義可變參數(shù)實(shí)現(xiàn)的:

#define _AUPBND (sizeof (acpi_native_int) - 1)
#define _ADNBND (sizeof (acpi_native_int) - 1)
#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T,_AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap) (void) 0
#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) +(_bnd(A,_AUPBND))))
關(guān)于可變參數(shù)的原理,網(wǎng)上有一些文章,總結(jié)來(lái)說(shuō),就是我們可以通過(guò)Intel80×86機(jī)器的對(duì)齊特性來(lái)獲得所有的參數(shù),因?yàn)樵贗ntel80×86機(jī)器上,每個(gè)變量的地址都要是sizeof(int)的倍數(shù),這樣能提升CPU運(yùn)行的效率。也就是說(shuō),所有參數(shù)的首地址都要是4的倍數(shù),就算你是char型的,那浪費(fèi)3個(gè)byte也要安排你占第四個(gè)坑。
好,由于C語(yǔ)言傳遞參數(shù)時(shí)是用push指令從右到左將參數(shù)逐個(gè)壓棧,因此我們通過(guò)棧指針跳4n格來(lái)訪問(wèn)第n個(gè)參數(shù),不要忘了,參數(shù)的地址都是字對(duì)齊的。這里,我們用#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) &(~(bnd)))來(lái)計(jì)算類型為X的參數(shù)在棧中占據(jù)的字對(duì)齊后的字節(jié)數(shù)。bnd是sizeof (acpi_native_int) –1,acpi_native_unit在32位機(jī)的定義是:
typedef u32 acpi_native_uint;
所以( ~(bnd))就是0xfffffffc 。 因此,_bnd(X,bnd) 宏在32位機(jī)下就是
  ( (sizeof(X) + 3)&0xfffffffc )
很明顯,其作用是–倘若sizeof(X)不是4的整數(shù)倍,將其變?yōu)?的整數(shù)倍。
va_start(ap,A) 負(fù)責(zé)初始化參數(shù)指針ap,將函數(shù)參數(shù)A右邊第一個(gè)參數(shù)的地址賦給ap,這個(gè)第一個(gè)參數(shù)通常就是printf里面的”%x%d%f%d”。
va_arg(ap,T) 可以獲得ap指向參數(shù)的值,并使ap指向下一個(gè)參數(shù),T用來(lái)指明當(dāng)前參數(shù)類型。
在這里,上述代碼還是麻煩,而且sizeof我們也不能直接用,所以我們不如干脆直接寫(xiě)一個(gè)不那么麻煩而有針對(duì)性的可變參數(shù)操作定義:
#define sizeof(x) ((char *)(&x+1) - (char *)(&x))
#define va_start(ap,v)  ( ap = (char *)&v + sizeof(v) )
#define va_arg(ap,t)    ( *(t *)((ap += sizeof(t)) - sizeof(t)) )
#define va_end(ap)      ( ap = (char *)0 )
有了這幾個(gè)定義,print函數(shù)就好寫(xiě)了,為了節(jié)省空間,這個(gè)簡(jiǎn)單的print()只支持“%s”,“%d”和”%c”格式的分類符,暫時(shí)不需要其他功能,比如格式對(duì)齊之類的,當(dāng)然,可以根據(jù)自己的需要擴(kuò)展這個(gè)函數(shù)。
int print( const char *fmt, ... )
{
  const char *s;
  char c;
  int d;
  va_list ap;
  va_start(ap, fmt);
  while( *fmt != '\0' )
  {
    if( *fmt != '%' )
    {
      uart_putc(*fmt++);
      continue;
    }
    switch(*++fmt)
    {
      case 's':
      {
        s = va_arg(ap, const char *);
        uart_puts(s);
        break;
      }
      case 'd':
      {
        d = va_arg(ap, int);
        uart_putints(d, 10);
        break;
      }
      case 'c':
      {
        c = va_arg(ap, char);
        uart_putc(c);
        break;
      }
      default:
        uart_putc(*fmt);
    }
    fmt++;
  }
  va_end(ap);
  return 1;
}
這里面有一些函數(shù),uart_putc是串口驅(qū)動(dòng)程序,給串口送東西的,uart_puts是簡(jiǎn)單的多重putc包裝。uart_putints則需要做一些atoi的轉(zhuǎn)換,一個(gè)比較簡(jiǎn)單但是有效的atoi程序宏定義如下:
#define ATOI(X, result) \
do{ \
char *lptr = X; \
result = 0; \
while (1) \
{ \
if ((*lptr >= '0') && (*lptr <= '9')) \
{ \
result *= 10; \
result += *lptr - '0'; \
lptr++; \
} \
else \
{ \
break; \
} \
} \
}while(0)
本文地址:http://m.qingdxww.cn/thread-5878-1-1.html     【打印本頁(yè)】

本站部分文章為轉(zhuǎn)載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀點(diǎn)和對(duì)其真實(shí)性負(fù)責(zé);文章版權(quán)歸原作者及原出處所有,如涉及作品內(nèi)容、版權(quán)和其它問(wèn)題,我們將根據(jù)著作權(quán)人的要求,第一時(shí)間更正或刪除。
您需要登錄后才可以發(fā)表評(píng)論 登錄 | 立即注冊(cè)

廠商推薦

  • Microchip視頻專區(qū)
  • Dev Tool Bits——使用MPLAB® Discover瀏覽資源
  • Dev Tool Bits——使用條件軟件斷點(diǎn)宏來(lái)節(jié)省時(shí)間和空間
  • Dev Tool Bits——使用DVRT協(xié)議查看項(xiàng)目中的數(shù)據(jù)
  • Dev Tool Bits——使用MPLAB® Data Visualizer進(jìn)行功率監(jiān)視
  • 貿(mào)澤電子(Mouser)專區(qū)

相關(guān)視頻

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權(quán)所有   京ICP備16069177號(hào) | 京公網(wǎng)安備11010502021702
快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 4438色| 欧美高清milf在线播放 | 肉与灵电视剧在线观看 | 国产毛片在线看 | 99热国产这里只有精品9九 | 久久五月婷 | 99精品视频免费在线观看 | 黑人巨大精品欧美一区二区区 | 日韩不卡一区二区 | 激情综合久久 | 青青草91在线 | 成人黄色一级片 | 国产日韩欧美亚洲青青草原 | 99热播在线观看 | 青青草a| 精品久久久久久久一区二区伦理 | 欧美日韩精品国产一区在线 | 国产美女69视频免费观看 | 俄罗斯丰满护士乱 | 香蕉视频在线免费 | 向日葵app在线观看 向日葵app看片视频在线观看 | 欧美精品导航 | 中文字幕日韩精品一区口 | 欧美三及 | 日日干夜夜拍 | 四虎影视色费永久在线观看 | 4虎影视国产在线观看精品 4虎成人 | 欧美大片在线观看完整版 | 成年人黄视频在线观看 | 向日葵视频免费在线观看 | 岛国大片在线免费观看 | 99视频免费在线观看 | 性生生活三级视频观看 | 99视频网站| 羞羞视频免费网站 | 国产福利一区二区精品免费 | 中文岛国精品亚洲一区 | 四虎在线免费 | 精品一久久香蕉国产线看观看下 | 91视频观看 | 在线观看色网站 |