<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > S3C2440開(kāi)發(fā)工具realview MDK4.22之庫(kù)的使用

          S3C2440開(kāi)發(fā)工具realview MDK4.22之庫(kù)的使用

          作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò) 收藏
          一。與c庫(kù)會(huì)強(qiáng)制鏈接

          如果你寫(xiě)了一個(gè)c程序,必然會(huì)和c庫(kù)鏈接,盡管你沒(méi)有直接使用c庫(kù)函數(shù)。這是因?yàn)榫幾g器為了改進(jìn)程序,可能隱含的產(chǎn)生了對(duì)c庫(kù)函數(shù)調(diào)用。

          本文引用地址:http://www.ex-cimer.com/article/201611/318141.htm

          即便你的程序沒(méi)有main()函數(shù),也只是說(shuō)c庫(kù)沒(méi)變初始化而已,一些c庫(kù)函數(shù)仍然可以使用并且編譯器可以隱含地調(diào)用這些函數(shù)。

          二。ARM的c的運(yùn)行時(shí)庫(kù)

          c標(biāo)準(zhǔn)庫(kù)由以下組成:

          ISO99標(biāo)準(zhǔn)庫(kù)定義的所有函數(shù)。

          依賴(lài)于目標(biāo)的函數(shù),用來(lái)在semihosted環(huán)境中執(zhí)行c庫(kù)函數(shù)。你可以在你的應(yīng)用程序中重定義這些函數(shù)。

          被編譯器隱含調(diào)用的函數(shù)。

          由ARM擴(kuò)展的,但是不是由ISO C定義,且包含在這個(gè)庫(kù)里的。

          c微型庫(kù)由以下組成(可以代替c標(biāo)準(zhǔn)庫(kù),它是非常適合只有小容量?jī)?nèi)存的深度嵌入式應(yīng)用):

          為了達(dá)到最小的代碼體積,已經(jīng)高度優(yōu)化的函數(shù)。

          不服從ISO C規(guī)范的函數(shù)。

          不服從1985 IEEE 754 標(biāo)準(zhǔn)

          三。c庫(kù)的特性

          c庫(kù)用標(biāo)準(zhǔn)的ARM semihosted 環(huán)境提供一些功能,不如說(shuō)輸入、輸出。該環(huán)境由ARM RVI調(diào)試單元和Real-Time Simulator Model/(RTSM)所支持的。

          你可以重新定義任何與設(shè)備相關(guān)的c庫(kù)函數(shù),寫(xiě)在自己的應(yīng)用程序中即可。這允許你裁剪c庫(kù)以應(yīng)用在自己的執(zhí)行環(huán)境中。

          也可以裁剪與設(shè)備無(wú)關(guān)的函數(shù),以適應(yīng)自己的特殊應(yīng)用要求。例如malloc簇,ctype簇,所有的locale-specific函數(shù)。

          許多c庫(kù)函數(shù)與其他函數(shù)是獨(dú)立的并且是目標(biāo)無(wú)關(guān)的,你可以簡(jiǎn)單的從庫(kù)里利用這些函數(shù)。

          c庫(kù)函數(shù)負(fù)責(zé)以下事情:

          1.創(chuàng)建一個(gè)c環(huán)境的執(zhí)行環(huán)境(創(chuàng)建棧,如果需要?jiǎng)?chuàng)建堆,初始化程序里用到的庫(kù)的部分)

          2.開(kāi)始執(zhí)行main()

          3.支持ISO C定義的函數(shù)

          4.捕獲允許錯(cuò)誤、信號(hào),根據(jù)情況終止程序或者退出程序

          四。ARM C庫(kù)的堆使用需求

          任何暗含的使用堆或者顯示調(diào)用使用堆都需要事先準(zhǔn)備好堆。

          在c標(biāo)準(zhǔn)庫(kù)里,暗含的堆使用發(fā)生在:

          1.調(diào)用庫(kù)函數(shù)fopen()并且一個(gè)I/O操作第一次使用這個(gè)fopen()所產(chǎn)生的stream

          2.傳遞命令行參數(shù)給main()函數(shù)

          分配80字節(jié)堆作為FILE結(jié)構(gòu)體的存儲(chǔ)空間。當(dāng)?shù)谝淮蜪/O操作發(fā)生,且直到這個(gè)操作產(chǎn)生,一個(gè)附加的512字節(jié)堆空間分配給與該操作相關(guān)的buffer區(qū)??梢岳胹etvbuf()重新

          定義堆大小。

          當(dāng)fclose()調(diào)用的時(shí)候,80字節(jié)未被釋放,保存在一個(gè)自由表中以備再次使用。512字節(jié)在fclose()時(shí)候被釋放了。

          聲明帶參數(shù)的main()需要256字節(jié)的堆空間。這個(gè)內(nèi)存一直未釋放,因?yàn)橐趍ain()期間有效。在microlib里,不允許聲明帶參的main(),因此這個(gè)用法僅使用于標(biāo)準(zhǔn)庫(kù)。在

          標(biāo)準(zhǔn)庫(kù)的環(huán)境里,如果存在堆,它就可以生效。

          五。c庫(kù)基于不同的build options會(huì)選擇不同的目標(biāo)集

          比如說(shuō),目標(biāo)架構(gòu),指令集(ARM,Thumb,Thumb-2);字節(jié)須(大小端);浮點(diǎn)支持(softVFP,VFP);位置無(wú)關(guān)

          六。Thumb C 庫(kù)

          當(dāng)連接器探測(cè)到以下事情發(fā)生的時(shí)候,會(huì)自動(dòng)連接Thumb C庫(kù):

          1.Thumb or Thumb-2 or --thumb選項(xiàng) or #pragma thumb

          2.在ARMv4T下,使用--apcs / interwork

          3.ARMv6-M Cortex-M1/MO

          4.ARMv7-M Cortex-M3

          七。ARM C庫(kù)和多線程

          當(dāng)你使用RTOS,ARM C庫(kù)支持多線程

          八。__user_libspace

          __user_libspace為C庫(kù)保持了靜態(tài)數(shù)據(jù)。這是一個(gè)96字節(jié),0初始化的數(shù)據(jù)塊,該塊由C庫(kù)創(chuàng)建。在C庫(kù)初始化期間可以用來(lái)當(dāng)做臨時(shí)棧。

          默認(rèn)的ARM C庫(kù)用__user_libspace區(qū)域保持以下內(nèi)容:

          1.errno,由可以設(shè)置errno的函數(shù)使用。默認(rèn),__rt_errno_addr()返回指向errno的指針。

          2.浮點(diǎn)狀態(tài)字,用于軟件浮點(diǎn)。在硬件浮點(diǎn)里,不使用。默認(rèn),__re_fp_status_addr()返回指向FP狀態(tài)字的指針。

          3.一個(gè)指向堆基址的指針,也就是__Heap_Descriptor,被所有malloc-相關(guān)的函數(shù)使用。

          4.當(dāng)前的locale設(shè)置,被像setlocale()函數(shù)使用,同時(shí)也被所有依賴(lài)于它們的其它函數(shù)使用。

          九。在一個(gè)程序中使用庫(kù)

          可以用以下方法在應(yīng)用程序使用C庫(kù):

          1.建立一個(gè)semihosting應(yīng)用,它可以在一個(gè)semihosted環(huán)境中調(diào)試,比如說(shuō)利用RV。

          2.建立一個(gè)非host的應(yīng)用,它可以嵌入到ROM中。

          3.建立一個(gè)不包含main()的應(yīng)用,且不初始化庫(kù)。該應(yīng)用具有非常有限的庫(kù)功能,除非重定義一些函數(shù)。

          十。在一個(gè)semihosting環(huán)境利用C庫(kù)

          如果你開(kāi)發(fā)一個(gè)應(yīng)用,為了調(diào)試,運(yùn)行在semihosted環(huán)境,你必須有一個(gè)執(zhí)行環(huán)境,可以支持ARM 或者 Thumb semihosting,且有足夠的存儲(chǔ)空間。

          1.用標(biāo)準(zhǔn)的半主機(jī)功能,默認(rèn)情況下,在RVI中會(huì)提供。

          2.為半主機(jī)調(diào)用執(zhí)行自己的處理過(guò)程。

          如果使用默認(rèn)的C庫(kù)的半主機(jī)功能,不必重寫(xiě)任何函數(shù)和頭文件。ARM調(diào)試代理支持半主機(jī),但是C庫(kù)所假定的內(nèi)存格局需要裁減以匹配正在調(diào)試的硬件。

          十一。使用$sub$$使用半主機(jī)和非半主機(jī)I/O功能

          例如,fputc()的實(shí)現(xiàn)是直接往UART寫(xiě),還有1個(gè)fputc()的實(shí)現(xiàn)是半主機(jī)的。可以提供這兩個(gè)版本,具體要看傳遞到函數(shù)的FILE指針的性質(zhì)。

          int $Super$fputc(int c, FILE *fp);int $Sub$fputc(int c, FILE *fp){if (fp == (FILE *)MAGIC_NUM) // where MAGIC_NUM is a special value that{                            // is different to all normal FILE * pointer// values.write_to_UART(c);return c;}else{return $Super$fputc(c, fp);}}
          可以看到根據(jù)FILE指針判斷是哪種類(lèi)型,$$super$代表正常的,$$sub$代表特殊的,一般和自己的目標(biāo)硬件相關(guān)。

          十二。以非半主機(jī)模式使用庫(kù)

          一些C庫(kù)函數(shù)使用半主機(jī)。如果不想使用的話,下列方式之一可以實(shí)現(xiàn):

          1.移除所有的半主機(jī)函數(shù)調(diào)用

          2.重定義低層函數(shù),比如fputc()。不必重定義所有的半主機(jī)函數(shù)。只是重定義在程序里需要使用到的函數(shù)。

          有些函數(shù)雖然不直接與目標(biāo)依賴(lài),但是它依賴(lài)于某些底層函數(shù),而底層函數(shù)依賴(lài)于目標(biāo)。例如,printf(),你必須重定義fputc(),如果不用得話,那就不必重定義了。

          3.以自己特別的方式實(shí)現(xiàn)所有半主機(jī)調(diào)用的一種方式。一個(gè)作為這種處理的例子是,攔截調(diào)用,將它們重指向自己的非主機(jī)實(shí)現(xiàn),也就是,具體目標(biāo)的函數(shù)。

          IMPORT __use_no_semihosting from ASM

          #pragma import(__use_no_semihosting) from C

          十三。直接的半主機(jī)依賴(lài)


          十四。間接的半主機(jī)依賴(lài)


          十五。建立一個(gè)不使用C庫(kù)的應(yīng)用程序

          如果程序中不包含main(),那么庫(kù)不會(huì)被初始化,且如下功能不可用:

          1.帶有_sys_前綴的底層stdio函數(shù)

          2.信號(hào)處理函數(shù)

          3.其它函數(shù),如atexit()

          有些函數(shù)即便庫(kù)未初始化也能使用,一些其它不可用的函數(shù)也能被使用,除非它們所依賴(lài)的庫(kù)函數(shù)被重定義。

          十六。裸機(jī)代碼

          如果你寫(xiě)一個(gè)程序,里面沒(méi)有使用庫(kù),且沒(méi)有任何環(huán)境初始化,你必須:

          1.如果用到heap的話,重定義__rt_raise()

          2.不定義main()

          3.寫(xiě)一個(gè)匯編語(yǔ)言代碼建立c語(yǔ)言運(yùn)行需要的環(huán)境,必須要跳轉(zhuǎn)到你c函數(shù)的入口

          4.提供自己的RW/ZI初始化代碼

          5.確保你的匯編代碼在你的重啟處理段

          6.用--fpu=none

          當(dāng)滿(mǎn)足這些要求,連接器用合適的C庫(kù)變體尋找任何需要編譯的函數(shù),它們是隱形調(diào)用的。

          盡管沒(méi)有main(),__user_lbspace()被自動(dòng)創(chuàng)建,占用96字節(jié)的ZI段。

          十七。定制C庫(kù)啟動(dòng)代碼且訪問(wèn)C庫(kù)函數(shù)

          應(yīng)用程序里不需要C庫(kù),如果你程序里有main(),連接器會(huì)自動(dòng)包含初始化代碼??赡艽嬖谝恍┣闆r,這是不必的。例如,一個(gè)運(yùn)行RTOS系統(tǒng)可能通過(guò)RTOS啟動(dòng)代碼

          有它自己的執(zhí)行環(huán)境配置。

          你可以創(chuàng)建一個(gè)應(yīng)用包含自己的啟動(dòng)代碼且仍然可以使用庫(kù)函數(shù)的大部分功能。你可以做下列之一的選擇:

          1.避免使用需要初始化的函數(shù)

          2.提供初始化和底層函數(shù)函數(shù)實(shí)現(xiàn)

          十八。利用C庫(kù)使用底層函數(shù)

          如果你的應(yīng)用中沒(méi)有main(),而使用庫(kù)的話,必須重定義一些在庫(kù)里的函數(shù)

          注意:如果用heap的話,__rt_raise()是必須的。

          十九。利用庫(kù)中的高層函數(shù)

          如果低層的函數(shù)被重定義了,那么高層I/O函數(shù)能被使用。高層函數(shù)是像fprintf() printf() scanf() puts()等,低層函數(shù)是那些如fputc() fgetc() 以及__backspace()函數(shù)。

          大多數(shù)格式化輸出函數(shù)也需要調(diào)用setlocale()。

          二十。利用庫(kù)中的malloc()函數(shù)

          如果在裸機(jī)C代碼中需要堆得支持,那么__init_alloc()必須要首先調(diào)用支持堆的邊界初始化,__rt_heap_extend()必須要提供,盡管返回失敗。如果沒(méi)有__rt_heap_extend()函數(shù),特定的庫(kù)功能會(huì)被包含進(jìn)去,這會(huì)導(dǎo)致裸機(jī)C代碼出現(xiàn)問(wèn)題。

          二十一。執(zhí)行環(huán)境的初始化和程序的執(zhí)行

          一個(gè)程序的入口是位于C庫(kù)里的__main,它會(huì)做如下事情:

          1.拷貝非根區(qū)代碼從它們的加載地址到運(yùn)行地址。如果任何數(shù)據(jù)段被壓縮了得話,它們也會(huì)被解壓縮。

          2.用0初始化ZI區(qū)。

          3.跳轉(zhuǎn)到__rt_entry。

          如果你不想C庫(kù)做這些事情,你可以定義自己的__main,__main里可以跳轉(zhuǎn)到__rt_entry。例如:

          IMPORT __rt_entryEXPORT __mainENTRY__mainB  __rt_entryEND

          庫(kù)函數(shù)__rt_entry像下面這樣運(yùn)行程序:

          1.建立堆和棧通過(guò)以下方式之一:調(diào)用__user_setup_srackheap(),調(diào)用__rt_stackheap_int()或加載scatter文件里的絕對(duì)地址。

          2.調(diào)用__rt_lib_init()初始化引用的庫(kù)函數(shù),初始化locale,如果必要的話,為main()建立argc和argv。

          3.調(diào)用main(),用戶(hù)級(jí)的根函數(shù)。

          4.從main()函數(shù)起,你的程序可能調(diào)用庫(kù)函數(shù)。

          5.利用main()返回的數(shù)值作為參數(shù)調(diào)用exit()函數(shù)。

          二十二。在main()里調(diào)用庫(kù)函數(shù)

          .main()是用戶(hù)級(jí)的根函數(shù)。它需要已經(jīng)初始化了的執(zhí)行環(huán)境和可以使用的輸入輸出函數(shù)。在main()里程序可能執(zhí)行下列的動(dòng)作之一,下列動(dòng)作調(diào)用了用戶(hù)定制的C庫(kù)函數(shù):

          1.擴(kuò)展堆,棧。

          2.調(diào)用庫(kù)函數(shù)。該庫(kù)函數(shù)需要調(diào)用用戶(hù)定義的函數(shù)。例如__rt_fp_status_addr() 或者clock()。

          3.調(diào)用使用locale或CTYPE的庫(kù)函數(shù)。

          4.執(zhí)行需要浮點(diǎn)單元或者浮點(diǎn)庫(kù)支持的浮點(diǎn)運(yùn)算。

          5.通過(guò)低層函數(shù)的輸入輸出函數(shù),如putc()或間接通過(guò)高層函數(shù),如fprintf()等。

          6.發(fā)起一個(gè)錯(cuò)誤或其他信號(hào),例如ferror。

          二十三。修改用于錯(cuò)誤信號(hào),錯(cuò)誤處理和程序退出的C庫(kù)修改

          所有由C庫(kù)發(fā)起的陷阱或錯(cuò)誤信號(hào)都是通過(guò)__raise()函數(shù)??梢灾囟x這個(gè)函數(shù)或者它所使用到的低層函數(shù)。

          二十四。避免使用堆和使用堆的庫(kù)函數(shù)

          IMPORT __use_no_heap from assembly language#pragma import(__use_no_heap) from C.

          二十五。在裸機(jī)C代碼里使用heap

          1.調(diào)用__init_alloc(base, top)

          2.定義函數(shù)unsigned _rt_heap_extend(unsigned size, void block)處理擴(kuò)展堆得需要。

          二十六。棧的初始化和堆界限

          可以指定棧指針,指定哪一塊區(qū)域?yàn)槎?,用以下任何一種方式:

          1.定義__initial_sp,如果需要堆, 定義__heap_base and __heap_limit

          2.用scatter文件,下列方式之一

          2.1定義ARM_LIB_STACK and ARM_LIB_STACK區(qū)

          2.2不用堆,只需ARM_LIB_STACK

          2.3定義一個(gè)ARM_LIB_STACKHEAP,此時(shí)堆棧是一體的,相向生長(zhǎng)。

          微庫(kù)僅支持上述2種方式。

          3.實(shí)現(xiàn)__user_setup_stackheap()建立棧指針和返回初始堆區(qū)域。

          4.用遺留的__user_initial_stackheap()也可以實(shí)現(xiàn)

          初始化堆指針必須指向的時(shí)8字節(jié)倍數(shù)對(duì)齊的區(qū)域。

          默認(rèn)情況下,潛在的堆棧沖突會(huì)被自動(dòng)探測(cè)到且請(qǐng)求的堆分配失敗。如果不希望自動(dòng)的沖突檢測(cè),可以通過(guò)用#pragma import __use_two_region_memory預(yù)留一小段空間。

          5.作為遺留的原因,也可以使用__rt_stackheap_init()和__rt_heap_extend()。

          二十七。C庫(kù)中對(duì)低層函數(shù)的依賴(lài)

          表中顯示了高層函數(shù)對(duì)低層函數(shù)的依賴(lài),如果定義了自己的低層函數(shù)版本,可以直接使用高層函數(shù)庫(kù)中的版本。

          fgetc()用__FILE,但是fputc()用__FILE和ferror()。

          必須提供__stdin和__stdout的定義,如果使用和它們相關(guān)的高層函數(shù)。雖然重定義了其它函數(shù),如fgetc()和fputc(),它們沒(méi)有引用任何在__stdin __stdout里的數(shù)據(jù)。

          Table key:

          1. __FILE, the file structure.

          2. __stdin, the standard input object of type__FILE.

          3. __stdout, the standard output object of type__FILE.

          4. fputc(), outputs a character to a file.

          5. ferror(), returns the error status accumulated during file I/O.

          6. fgetc(), gets a character from a file.

          7. fgetwc()

          8. fputwc()

          9. __backspace(), moves the file pointer to the previous character.

          10. __backspacewc().

          如果選擇重定義fgetc() fputc() __backspace() 要認(rèn)識(shí)到fopen和相關(guān)的函數(shù)使用ARM默認(rèn)的FILE結(jié)構(gòu)。如果重定義了__FILE,那么也必須重定義fopen()和相關(guān)的函數(shù)。

          C庫(kù)輸出函數(shù)族僅依賴(lài)fputc() ferror();C庫(kù)輸入函數(shù)族僅依賴(lài)于fgetc() __FILE __backspace()。



          二十八。重定義低層函數(shù),以便直接使用高層函數(shù)庫(kù)函數(shù)

          如果你重定義了__FILE fputc() ferror() __stdout可以使用所有的printf()函數(shù)族。

          Example 9. Retargeting printf()#include struct __FILE{int handle;/* Whatever you require here. If the only file you are using is *//* standard output using printf() for debugging, no file handling *//* is required. */};/* FILE is typedef’d in stdio.h. */FILE __stdout;int fputc(int ch, FILE *f) {/* Your implementation of fputc(). */return ch;}int ferror(FILE *f){/* Your implementation of ferror(). */return 0;}void test(void){printf("Hello worldn");}


          二十九。

          __backspace()被scanf()函數(shù)族使用。

          __backspace()必須僅在從流里讀取一個(gè)字符后調(diào)用。



          評(píng)論


          相關(guān)推薦

          技術(shù)專(zhuān)區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();