第五章 嵌入式系统概述
嵌入式系统的基本概念
嵌入式系统概念:
应用为中心,以计算机技术为基础,软件硬件可裁剪,适应系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统
主流的CPU架构:ARM,MIPS,PowerPC,X86/atom
开源架构:RISC-V, OpenPower
硬件层次:
软件层次:
(一) Bootloader
在PC机中,引导加载程序由BIOS和位于硬盘的主引导记录MBR中的OS Boot Loader一起完成。嵌入式系统中,通常没有BIOS那样的固件程序,因此整个系统的加载启动任务完全由bootloader完成。bootloader的主要作用是
- 初始化硬件设备
- 建立内存空间的映射图
- 完成内核的加载,为内核设置启动参数
(二) 串口通信
RS232-C是通用异步串行接口中最常用的标准。Linux系统用minicom软件实现串口通信按照引脚进行连接以后可以进入嵌入式系统的引导界面,主要需要配置网络和本机地址,烧入内核和文件系统。详见实验1。
(三) 图形用户接口——Framebuffer(重点)
显示屏的整个显示区域,在系统内会有一段存储空间与之对应,通过改变该存储空间的内容达到改变显示信息的目的,该存储空间称为Frame Buffer。显示屏上的每一个点都与Frame Buffer里的某一位置相对应。FB通常从内存空间分配所得,并且由连续的字节空间所组成。屏幕的显示操作通常是从左到右逐点像素扫描,从上到下逐行扫描,直到扫到右下角,而FB里面的数据按照地址递增的顺序被提取,所以屏幕同一行相邻的两像素映射到FB中是相邻的,每行最末元素与下一行首像素页式连续的。左上角对应FB的第一单元空间,右下角为FB的最后一单元空间。
如果要在屏幕某一点显示某种颜色,则必须给出相应的RGB值。
-
24位:8R+8G+8B
红色表示为
1111 1111 0000 0000 0000 0000
-
16位:5R+6G+5B
红色表示为
1111 1000 0000 0000
则只需要
1111 1111 0000 0000 0000 0000 & 1111 1000 0000 0000
以字节为单位的Frame Buffer的大小和界面的宽、高和每个像素所需要的bit数有关,即
Frame Buffer Size = W × H × Bit_Per_Pixel 8 \text{Frame Buffer Size} = \frac{W \times H \times \text{Bit\_Per\_Pixel}}{8} Frame Buffer Size=8W×H×Bit_Per_Pixel
Linux中一切皆文件,Frame Buffer的设备是/dev/fb
。我们可以使用ioctl
方法获取屏幕的尺寸信息、像素信息等。可以使用mmap
函数将屏幕映射到FB中。
看一个样例。
void initset(void)
{
int fd;
int screensize = 0;
fd = open("/dev/fb0", O_RDWR);
ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);//获取色位和分辨率信息
printf("Initializing screen parameters.\n");
printf("bits_per_pixel:%d\n",vinfo.bits_per_pixel);
printf("xres:%d\n",vinfo.xres);
printf("yres:%d\n",vinfo.yres);
screensize = vinfo.bits_per_pixel * vinfo.xres * vinfo.yres / 8;//获取屏幕大小
printf("screensize:%d\n", screensize);
addr = (unsigned char *)mmap(0, screensize,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);//建立映射,返回首地址
}
void clear(void)
{
printf("Clearing screen.\n");
bzero(addr, vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8);。//清空屏幕
}
下面的代码演示了如何在 ( x , y ) (x,y) (x,y)处画一个红点
offset = (y * vinfo.xres + x) * vinfo.bits_per_pixel / 8;
color = (Red << 11) | (Green << 5) * 0x07E0 | (Blue & 0x1F);//将24位压缩成16位
*(unsigned char *)(addr + offset + 0) = color & 0xFF;//设置为红色
*(unsigned char *)(addr + offset + 1) = (color >> 8) & 0xFF;
(四) 静态编译和动态编译
-
静态编译
静态链接库在程序链接的时候被加入可执行文件,是以
*.a
为结尾的二进制文件。制作静态链接库时,先将现有代码生成目标文件,然后使用ar
命令将目标文件打包成一个静态链接库。gcc -c math.c #不链接生成目标文件 ar rcs libmath.a math.o #生成名为libmath的静态链接库 gcc -o main main.c -lmath #链接libmath.a静态库,生成可执行文件main ./main #可执行文件可以单独运行
ar
命令用于将多个文件打包成一个备份文件,参数r
用来替换库中已有的目标文件或加入新的目标文件,参数c
表示创建一个库,不管库是否存在都创建,参数s
用来创建目标文件索引 -
动态编译
在程序运行时被加载,使用动态链接库可以使得可执行文件更小、便于程序的模块化和更新以及提高有效内存使用效率,文件后缀是
*.so
。要制作动态链接库,首先在编译阶段要利用-fPIC
生成位置无关代码(Position-Independent code),这样可以使得产生的代码没有绝对位置,代码可以被加载器加载到内存的任意位置。然后利用生成的目标文件在链接阶段使用-shared
生成可动态加载的库。为了使得程序运行的时候可以找到动态函数库,需要将链接库放在标准库目录/usr/lib
下,或者在运行时设置环境变量。arm-linux-gcc -c lcd.c #不链接生成目标文件 gcc -shared -fPIC -o liblcd.so lcd.o #生成可动态加载动态库 gcc -o main main.c -L. -llcd #链接动态库,当main函数运行时会动态的加载链接库
(五) 嵌入式文件系统
嵌入式Linux应用中,主要存储设备位RAM和ROM,常用的基于存储设备的文件系统类型包括:jffs2;ysffs;cramfs;romfs;ramdisk;ramfs/tmpfs。
Linux的虚拟文件系统支持三种类型的文件
- 基于磁盘、光盘及U盘等非易失性存储介质的文件系统,如FAT,NTFS,Ext等
- 通过网络协议实现的远程网络的文件系统,如NFS等
- 特殊文件系统
习题
- 系统功能调用mmap()的作用是将内核空间地址映射到用户空间
- 作为Linux启动的内核映像和根文件系统映像RAM Disk常采用压缩格式。压缩的目的是节省DRAM空间
- 同分时操作系统相比,实时操作系统注重行为的可预测性
- 针对嵌入式系统中的FLASH存储设备,文件系统通常会采用JFFS2/YAFFS2
- 使用八段共阳数码管实现简单的数字显示功能时,点亮数码管的条件是公共端接地,通过锁存器驱动显示字形。(输入缓存器,输出锁存器)
- BusyBox的init启动进程需要读取/
etc/initab
文件 strip
可以去除代码中的调试信息
**
- 使用八段共阳数码管实现简单的数字显示功能时,点亮数码管的条件是公共端接地,通过锁存器驱动显示字形。(输入缓存器,输出锁存器)
- BusyBox的init启动进程需要读取/
etc/initab
文件 strip
可以去除代码中的调试信息