您的位置 首页 厂商

S3C2440开发工具realview MDK4.22之库的运用

一。与c库会强制链接如果你写了一个c程序,必然会和c库链接,尽管你没有直接使用c库函数。这是因为编译器为了改进程序,可能隐含的产生了对…

一。与c库会强制链接

假如你写了一个c程序,必然会和c库链接,尽管你没有直接运用c库函数。这是由于编译器为了改善程序,或许隐含的产生了对c库函数调用。

即使你的程序没有main()函数,也仅仅说c库没变初始化罢了,一些c库函数依然能够运用而且编译器能够隐含地调用这些函数。

二。ARM的c的运转时库

c规范库由以下组成:

ISO99规范库界说的一切函数。

依靠于方针的函数,用来在semihosted环境中碑文c库函数。你能够在你的运用程序中重界说这些函数。

被编译器隐含调用的函数。

由ARM扩展的,可是不是由ISO C界说,且包括在这个库里的。

c微型库由以下组成(能够替代c规范库,它是十分适宜只要小容量内存的深度嵌入式运用):

为了到达最小的代码体积,现已高度优化的函数。

不服从ISO C规范的函数。

不服从1985 IEEE 754 规范

三。c库的特性

c库用规范的ARM semihosted 环境供给一些功用,不如说输入、输出。该环境由ARM RVI调试单元和Real-Time Simulator Model/(RTSM)所支撑的。

你能够从头界说任何与设备相关的c库函数,写在自己的运用程序中即可。这答应你裁剪c库以运用在自己的碑文环境中。

也能够裁剪与设备无关的函数,以习惯自己的特别运用要求。例如malloc簇,ctype簇,一切的locale-specific函数。

许多c库函数与其他函数是独立的而且是方针无关的,你能够简略的从库里运用这些函数。

c库函数担任以下工作:

1.创立一个c环境的碑文环境(创立栈,假如需求创立堆,初始化程序里用到的库的部分)

2.开端碑文main()

3.支撑ISO C界说的函数

4.捕获答应过错、信号,依据状况停止程序或许退出程序

四。ARM C库的堆运用需求

任何暗含的运用堆或许显现调用运用堆都需求事前准备好堆。

在c规范库里,暗含的堆运用产生在:

1.调用库函数fopen()而且一个I/O操作第一次运用这个fopen()所产生的stream

2.传递命令行参数给main()函数

分配80字节堆作为FILE结构体的存储空间。当第一次I/O操作产生,且直到这个操作产生,一个附加的512字节堆空间分配给与该操作相关的buffer区。能够运用setvbuf()从头

界说堆巨细。

当fclose()调用的时分,80字节未被开释,保存在一个自在表中以备再次运用。512字节在fclose()时分被开释了。

声明带参数的main()需求256字节的堆空间。这个内存一向未开释,由于要在main()期间有用。在microlib里,不答应声明带参的main(),因而这个用法仅运用于规范库。在

规范库的环境里,假如存在堆,它就能够收效。

五。c库依据不同的build options会挑选不同的方针集

比方说,方针架构,指令集(ARM,Thumb,Thumb-2);字节须(巨细端);浮点支撑(softVFP,VFP);方位无关

六。Thumb C 库

当衔接器探测到以下工作产生的时分,会主动衔接Thumb C库:

1.Thumb or Thumb-2 or –thumb选项 or #pragma thumb

2.在ARMv4T下,运用–apcs / interwork

3.ARMv6-M Cortex-M1/MO

4.ARMv7-M Cortex-M3

七。ARM C库和多线程

当你运用RTOS,ARM C库支撑多线程

八。__user_libspace

__user_libspace为C库坚持了静态数据。这是一个96字节,0初始化的数据块,该块由C库创立。在C库初始化期间能够用来作为暂时栈。

默许的ARM C库用__user_libspace区域坚持以下内容:

1.errno,由能够设置errno的函数运用。默许,__rt_errno_addr()回来指向errno的指针。

2.浮点状态字,用于软件浮点。在硬件浮点里,不运用。默许,__re_fp_status_addr()回来指向FP状态字的指针。

3.一个指向堆基址的指针,也便是__Heap_Descriptor,被一切malloc-相关的函数运用。

4.当时的locale设置,被像setlocale()函数运用,一起也被一切依靠于它们的其它函数运用。

九。在一个程序中运用库

能够用以下办法在运用程序运用C库:

1.树立一个semihosting运用,它能够在一个semihosted环境中调试,比方说运用RV。

2.树立一个非host的运用,它能够嵌入到ROM中。

3.树立一个不包括main()的运用,且不初始化库。该运用具有十分有限的库功用,除非重界说一些函数。

十。在一个semihosting环境运用C库

假如你开发一个运用,为了调试,运转在semihosted环境,你有必要有一个碑文环境,能够支撑ARM 或许 Thumb semihosting,且有分量的存储空间。

1.用规范的半主机功用,默许状况下,在RVI中会供给。

2.为半主机调用碑文自己的处理进程。

假如运用默许的C库的半主机功用,不必重写任何函数和头文件。ARM调试署理支撑半主机,可是C库所假定的内存格式需求削减以匹配正在调试的硬件。

十一。运用$sub$$运用半主机和非半主机I/O功用

例如,fputc()的完成是直接往UART写,还有1个fputc()的完成是半主机的。能够供给这两个版别,详细要看传递到函数的FILE指针的性质。

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);}}

能够看到依据FILE指针判别是哪种类型,$$super$代表正常的,$$sub$代表特别的,一般和自己的方针硬件相关。

十二。以非半主机形式运用库

一些C库函数运用半主机。假如不想运用的话,下列方法之一能够完成:

1.移除一切的半主机函数调用

2.重界说低层函数,比方fputc()。不必重界说一切的半主机函数。仅仅重界说在程序里需求运用到的函数。

有些函数尽管不直接与方针依靠,可是它依靠于某些底层函数,而底层函数依靠于方针。例如,printf(),你有必要重界说fputc(),假如不必得话,那就不必重界说了。

3.以自己特别的方法完成一切半主机调用的一种方法。一个作为这种处理的比如是,阻拦调用,将它们重指向自己的非主机完成,也便是,详细方针的函数。

IMPORT __use_no_semihosting from ASM

#pragma import(__use_no_semihosting) from C

十三。直接的半主机依靠

十四。直接的半主机依靠

十五。树立一个不运用C库的运用程序

假如程序中不包括main(),那么库不会被初始化,且如下功用不可用:

1.带有_sys_前缀的底层stdio函数

2.信号处理函数

3.其它函数,如atexit()

有些函数即使库未初始化也能运用,一些其它不可用的函数也能被运用,除非它们所依靠的库函数被重界说。

十六。裸机代码

假如你写一个程序,晒干没有运用库,且没有任何环境初始化,你有必要:

1.假如用到heap的话,重界说__rt_raise()

2.不界说main()

3.写一个汇编言语代码树立c言语运转需求的环境,有必要要跳转到你c函数的进口

4.供给自己的RW/ZI初始化代码

5.保证你的汇编代码在你的重启处理段

6.用–fpu=none

当分量这些要求,衔接器用适宜的C库变体寻觅任何需求编译的函数,它们是隐形调用的。

尽管没有main(),__user_lbspace()被主动创立,占用96字节的ZI段。

十七。定制C库发动代码且拜访C库函数

运用程序里不需求C库,假如你程序里有main(),衔接器会主动包括初始化代码。或许存在一些状况,这是不必的。例如,一个运转RTOS体系或许经过RTOS发动代码

有它自己的碑文环境装备。

你能够创立一个运用包括自己的发动代码且依然能够运用库函数的大部分功用。你能够做下列之一的挑选:

1.防止运用需求初始化的函数

2.供给初始化和底层函数函数完成

十八。运用C库运用底层函数

假如你的运用中没有main(),而运用库的话,有必要重界说一些在库里的函数

留意:假如用heap的话,__rt_raise()是有必要的。

十九。运用库中的高层函数

假如低层的函数被重界说了,那么高层I/O函数能被运用。高层函数是像fprintf() printf() scanf() puts()等,低层函数是那些如fputc() fgetc() 以及__backspace()函数。

大多数格式化输出函数也需求调用setlocale()。

二十。运用库中的malloc()函数

假如在裸机C代码中需求堆得支撑,那么__init_alloc()有必要要首要调用支撑堆的鸿沟初始化,__rt_heap_extend()有必要要供给,尽管回来失利。假如没有__rt_heap_extend()函数,特定的库功用会被包括进去,这会导致裸机C代码出现问题。

二十一。碑文环境的初始化和程序的碑文

一个程序的进口是坐落C库里的__main,它会做如下工作:

1.劳动非根区代码从它们的加载地址到运转地址。假如任何数据段被紧缩了得话,它们也会被解紧缩。

2.用0初始化ZI区。

3.跳转到__rt_entry。

假如你不想C库做这些工作,你能够界说自己的__main,__main里能够跳转到__rt_entry。例如:

IMPORT __rt_entryEXPORT __mainENTRY__mainB  __rt_entryEND

库函数__rt_entry像下面这样运转程序:

1.树立堆和栈经过以下方法之一:调用__user_setup_srackheap(),调用__rt_stackheap_int()或加载scatter文件里的肯定地址。

2.调用__rt_lib_init()初始化引证的库函数,初始化locale,假如必要的话,为main()树立argc和argv。

3.调用main(),用户级的根函数。

4.从main()函数起,你的程序或许调用库函数。

5.运用main()回来的数值作为参数调用exit()函数。

二十二。在main()里调用库函数

.main()是用户级的根函数。它需求现已初始化了的碑文环境和能够运用的输入输出函数。在main()里程序或许碑文下列的动作之一,下列动作调用了用户定制的C库函数:

1.扩展堆,栈。

2.调用库函数。该库函数需求调用用户界说的函数。例如__rt_fp_status_addr() 或许clock()。

3.调用运用locale或CTYPE的库函数。

4.碑文需求浮点单元或许浮点库支撑的浮点运算。

5.经过低层函数的输入输出函数,如putc()或直接经过高层函数,如fprintf()等。

6.建议一个过错或其他信号,例如ferror。

二十三。修正用于过错信号,过错处理和程序退出的C库修正

一切由C库建议的圈套或过错信号都是经过__raise()函数。能够重界说这个函数或许它所运用到的低层函数。

二十四。防止运用堆和运用堆的库函数

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

二十五。在裸机C代码里运用heap

1.调用__init_alloc(base, top)

2.界说函数unsigned _rt_heap_extend(unsigned size, void block)处理扩展堆得需求。

二十六。栈的初始化和堆边界

能够指定栈指针,指定哪一块区域为堆,用以下任何一种方法:

1.界说__initial_sp,假如需求堆, 界说__heap_base and __heap_limit

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

2.1界说ARM_LIB_STACK and ARM_LIB_STACK区

2.2不必堆,只需ARM_LIB_STACK

2.3界说一个ARM_LIB_STACKHEAP,此刻仓库是一体的,相向成长。

微库仅支撑上述2种方法。

3.完成__user_setup_stackheap()树立栈指针和回来初始堆区域。

4.用留传的__user_initial_stackheap()也能够完成

初始化堆指针有必要指向的时8字节倍数对齐的区域。

默许状况下,潜在的仓库抵触会被主动探测到且恳求的堆分配失利。假如不期望主动的抵触检测,能够经过用#pragma import __use_two_region_memory预留一小段空间。

5.作为留传的原因,也能够运用__rt_stackheap_init()和__rt_heap_extend()。

二十七。C库中对低层函数的依靠

表中显现了高层函数对低层函数的依靠,假如界说了自己的低层函数版别,能够直接运用高层函数库中的版别。

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

有必要供给__stdin和__stdout的界说,假如运用和它们相关的高层函数。尽管重界说了其它函数,如fgetc()和fputc(),它们没有引证任安在__stdin __stdout里的数据。

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() 要认识到fopen和相关的函数运用ARM默许的FILE结构。假如重界说了__FILE,那么也有必要重界说fopen()和相关的函数。

C库输出函数族仅依靠fputc() ferror();C库输入函数族仅依靠于fgetc() __FILE __backspace()。

二十八。重界说低层函数,以便直接运用高层函数库函数

假如你重界说了__FILE fputc() ferror() __stdout能够运用一切的printf()函数族。

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 world\n");}

二十九。

__backspace()被scanf()函数族运用。

__backspace()有必要仅在从流里读取一个字符后调用。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/changshang/264959.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部