韦东山stdio裸机程序分析

本文介绍韦东山裸机程序中GCC的移植过程,包括如何配置Makefile、分析ctype函数、使用__attribute__宏及gcclib.h中的类型定义等内容。

韦东山裸机程序

GCC中文手册

 

源代码和GCC中文手册可自由下载

缘由:首先单纯的uart驱动,没有什么难度,配置2440寄存器即可实现。

stdio程序移植libc库,实现printf  scanf sscanf 等函数,利用串口获取十进制数,转换成十六进制。

功能较简单,但是对于libc库的移植较复杂,其中还涉及gnu assemble语法等等,因此比较感兴趣,想总结一下。

1. 首先是顶层Makefile。

其中一句:

  INCLUDEDIR  := $(shell pwd)/include
  CFLAGS      := -Wall -O2
  CPPFLAGS    := -nostdinc -I$(INCLUDEDIR)

参考gcc中文手册 -nostdinc:

不要在标准系统目录中寻找头文件.只搜索`-I'选项指定的目录(以及当前目录,如果合适).
结合使用`-nostdinc'和`-I-'选项,你可以把包含文件搜索限制在显式指定的目录.

-I$(INCLUDEDIR)

指定当前目录下的include目录为头文件的搜索目录。

2. 查看lib目录下的Makefile

libc.a: $(objs)
    ${AR} -r -o $@ $^

这里用到了AR命令,AR为arm-linux-ar, 关于ar命令有篇文章讲的较细致可以参考:关于静态链接库 

也可以参考 arm-linux-ar --help

ar作用是生成静态库

-r 表示:replace existing or insert new file(s) into the archive, 替换归档库中已存在的文件或插入新的文件。

-o:preserve original dates ,保留原来的日期。

 

3. Ctype分析

 我看了半天,大致明白了Ctype的作用,其实就是分析一个字符是什么类型的

#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
#define isupper(c)    ((__ismask(c)&(_U)) != 0)
 

这里以isupper来举例,isupper顾名思义,判断字符是否为大写。假设字符为大写字母'A' ,则

isupper('A')  => ((__ismask(‘A’)&(_U)) != 0) => (_ctype[65] & _U != 0 ) , 查看_ctype[65] 值为 _U|_X ,则 (_U|_X) & _U  ,结果为true。

ctype.h 提供了 两个函数: __tolower __toupper ,支持大小写字母转换。

 

4. __attribute__

有关__attribute__有篇文章较详细:Using GNU C __attribute__

另外还有一份 :The GNU C Reference Manual

继续拓展 attribute,

 

/* like printf() but to standard error only */
extern void eprintf(const char *format, ...)
	__attribute__((format(printf, 1, 2)));  /* 1=format 2=params */extern void eprintf(const char *format, ...)
	__attribute__((format(printf, 1, 2)));  /* 1=format 2=params */

这里1 代表指定传入函数的第1个参数是格式化字符串, 2 代表指定从函数的第几个参数开始按上述规则进行检查。开始我也没理解文档中英文的含义。参见这篇博客:__attribute__ 详解 

 

5.  gcclib.h

 

/* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
/* I Molton     29/07/01 */

#define BITS_PER_UNIT  8
#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)

typedef unsigned int UQItype    __attribute__ ((mode (QI)));
typedef          int SItype     __attribute__ ((mode (SI)));
typedef unsigned int USItype    __attribute__ ((mode (SI)));
typedef          int DItype     __attribute__ ((mode (DI)));
typedef          int word_type 	__attribute__ ((mode (__word__)));
typedef unsigned int UDItype    __attribute__ ((mode (DI)));

#ifdef __ARMEB__
  struct DIstruct {SItype high, low;};
#else
  struct DIstruct {SItype low, high;};
#endif

typedef union
{
  struct DIstruct s;
  DItype ll;
} DIunion;

 

参考mode的定义:

mode (mode)

This attribute specifies the data type for the declaration--whichevertype corresponds to the modemode. This in effect lets yourequest an integer or floating point type according to its width.

结合上述说明,

typedef unsigned int UQItype    __attribute__ ((mode (QI)));

定义了一个新的类型 UQItype, mode属性用来标识它的位宽。QI的定义参见下面两篇文章:

Machine Modes

Using vector instructions through built-in functions

              具体代码一目了然。

6.  va_start va_arg va_end 的使用 参见文章:  va_start和va_end使用详解

(待续)

1.1 课程内容嵌入式软件工程师的学习路线一般是:单片机、RTOS、Linux。当你掌握单片机开发后,如果要进一步提升编程水平,建议学习RTOS(Real Time Operating System,实时操作系统)。有很多优秀的RTOS,比如FreeRTOS、RT-Thread、UCOS等等。FreeRTOS使用范围最广泛,RT-Thread生态丰富,UCOS是收费的并且很少使用了。对于初学者,建议先学习FreeRTOS。只要学会了任意一款RTOS,肯定就会使用其他RTOS了。我们在2022年已经推出了“FreeRTOS快速入门”课程。为何还要重新制作“FreeRTOS入门与工程实践”?“FreeRTOS快速入门”只是讲解FreeRTOS的各类API的理论、用法、示例,这些实验是基于Keil自带的STM32F103模拟器。没有使用更多的硬件模块、不能体现工作中的实际场景。在“FreeRTOS入门与工程实践”,将引入更多的硬件模块,并展示实际工程示例中的用法。另外,基于RTOS的程序一般都比较复杂,涉及的源文件非常多,在工作中一般都基于“面向对象”的思想来写程序。所以,本课程会涉及如下内容:讲解FreeRTOS的常用API:理论、用法选择合适的硬件模块,展示这些API的实例实现合适的小项目,展示工作中的编程方法1.2 讲课方式对于每一个实验,我们会精心设计:要解决什么问题;然后讲解FreeRTOS提供的解决方法。讲解FreeRTOS的API及内部原理(不深入讲解内部源码,只是进行原理性介绍)讲解实验过程使用的模块的接口函数(只讲使用,不讲内部实现,模块的源码实现单独开课讲解)讲解原理时,配合着文档、现场画图进行讲解,跟学校老师写黑板一样最后现场从0编写程序并调试一切都是现场操作,绝对不会照着PPT念,绝对不会照着现成的代码讲解。只有现场从0操作,学员才能身临其境地学习,跟着教程:碰到问题、解决问题。1.3 硬件平台本课程基于DshanMCU-103开发套件进行开发,它由3部分组成:STM32F103C8T6的最小系统板、扩展底板、各类模块。如下图所示:  上述硬件再加一个ST-Link即可学完本课程所有内容。主板DshanMCU-103是基于STM32F103C8T6的最小系统板。之所以选择最小系统板,而不是把所有模块都放在一个整体的电路板上,目的如下:低成本尝试:嵌入式软件开发并不一定适合你,可以购买最小系统板进行体验、及时放弃按需购买:用到再买,讲究一个性价比 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值