分类 嵌入式开发 下的文章

交叉编译器 gnueabi、none-eabi、arm-eabi、gnueabihf、gnueabi 的区别

命名规则 交叉编译工具链的命名规则为:arch-vendor-os-(gnu)eabi arch - 体系架构,如 ARM,MIPS vendor - 工具链提供商 os - 目标操作系统 eabi - 嵌入式应用二进制接口(Embedded Application Binary Interface) 根据对操作系统的支持与否,ARM GCC 可分为支持和不支持操作系统,如: arm-none-eabi:这个是没有操作系统的,自然不可能支持那些跟操作系统关系密切的函数,比如 fork。它使用的是 newlib 这个专用于嵌入式系统的 C 库。 arm-none-linux-eabi:用于 Linux 的,使用 Glibc 命名实例 1. arm-none-eabi-gcc (ARM architecture,no vendor,not target an operating system,complies with the ARM EABI) 用于编译 ARM 架构的裸机系统(包括 ARM Linux 的 boot、kernel,不适用编译 Linux 应用 Application),一般适合 ARM7、Cortex-M 和 Cortex-R 内核的芯片使用,所以不支持那些跟操作系统关系密切的函数,比如 fork,他使用的是 newlib 这个专用于嵌入式系统的 C 库。 2. arm-none-linux-gnueabi-gcc (ARM architecture, no vendor, creates binaries that run on the Linux operating system, and uses the GNU EABI) 主要用于基于 ARM 架构的 Linux 系统,可用于编译 ARM 架构的 u-boot、Linux 内核、Linux 应用等。arm-none-linux-gnueabi 基于GCC,使用 Glibc 库,经过 Codesourcery 公司优化过推出的编译器。arm-none-linux-gnueabi-xxx 交叉编译工具的浮点运算非常优秀。一般 ARM9、ARM11、Cortex-A 内核,带有 Linux 操作系统的会用到。 3. arm-eabi-gcc Android ARM 编译器。 4. armcc ARM 公司推出的编译工具,功能和 arm-none-eabi 类似,可以编译裸机程序(u-boot、kernel),但是不能编译 Linux 应用程序。armcc 一般和 ARM 开发工具一起,Keil MDK、ADS、RVDS 和 DS-5 中的编译器都是 armcc,所以 armcc 编译器都是收费的。 5. arm-none-uclinuxeabi-gcc 和 arm-none-symbianelf-gcc arm-none-uclinuxeabi 用于 uCLinux,使用 Glibc。 arm-none-symbianelf 用于 Symbian,没用过,不知道 C 库是什么 。 ABI 和 EABI ABI:二进制应用程序接口(Application Binary Interface (ABI) for the ARM Architecture)。在计算机中,应用二进制接口描述了应用程序(或者其他类型)和操作系统之间或其他应用程序的低级接口。 EABI:嵌入式 ABI。嵌入式应用二进制接口指定了文件格式、数据类型、寄存器使用、堆积组织优化和在一个嵌入式软件中的参数的标准约定。开发者使用自己的汇编语言也可以使用 EABI 作为与兼容的编译器生成的汇编语言的接口。 两者主要区别是,ABI 是计算机上的,EABI 是嵌入式平台上(如 ARM,MIPS 等)。 arm-linux-gnueabi-gcc 与 arm-linux-gnueabihf-gcc 两个交叉编译器分别适用于 armel 和 armhf 两个不同的架构,armel 和 armhf 这两种架构在对待浮点运算采取了不同的策略(有 FPU 的 ARM 才能支持这两种浮点运算策略)。 其实这两个交叉编译器只不过是 gcc 的选项 -mfloat-abi 的默认值不同。gcc 的选项 -mfloat-abi 有三种值 soft、softfp、hard(其中后两者都要求 ARM 里有 FPU 浮点运算单元,soft 与后两者是兼容的,但 softfp 和 hard 两种模式互不兼容): soft: 不用 FPU 进行浮点计算,即使有 FPU 浮点运算单元也不用,而是使用软件模式。 softfp: armel 架构(对应的编译器为 arm-linux-gnueabi-gcc)采用的默认值,用 FPU 计算,但是传参数用普通寄存器传,这样中断的时候,只需要保存普通寄存器,中断负荷小,但是参数需要转换成浮点的再计算。 hard: armhf 架构(对应的编译器 arm-linux-gnueabihf-gcc)采用的默认值,用 FPU 计算,传参数也用 FPU 中的浮点寄存器传,省去了转换,性能最好,但是中断负荷高。 把以下测试使用的 C 文件内容保存成 mfloat.c: #include <stdio.h> int main(void) { double a, b, c; a = 23.543; b = 323.234; c = b / a; printf("the 13/2 = %f\n", c); printf("hello world !\n"); return 0; } 1、使用 arm-linux-gnueabihf-gcc 编译,使用 -v 选项以获取更详细的信息: # arm-linux-gnueabihf-gcc mfloat.c -v ... COLLECT_GCC_OPTIONS='-v' '-mfloat-abi=hard' '-mtls-dialect=gnu' '-mthumb' '-mlibarch=armv7-a+fp' '-march=armv7-a+fp' '-dumpdir' 'a.' 可看出使用了 hard 硬件浮点模式。 2、使用 arm-linux-gnueabi-gcc 编译: # arm-linux-gnueabi-gcc -v mfloat.c -mfloat-abi=softfp ... COLLECT_GCC_OPTIONS='-v' '-mfloat-abi=softfp' '-mtls-dialect=gnu' '-marm' '-mlibarch=armv5t' '-march=armv5t' '-dumpdir' 'a.' 可看出使用 softfp 模式。 我测试用的 GCC 版本是 11.4.0,arm-linux-gnueabihf-gcc 只支持 -mfloat-abi=hard,而 arm-linux-gnueabi-gcc 则支持 -mfloat-abi=soft 与 -mfloat-abi=softfp 两种模...

实现复位后不清零单片机内部 SRAM 的方法

通常情况下单片机复位后会自动清零 SRAM 中的一些变量,本文以 ARM 单片机为例来说一说如何实现不清零。 在默认情况下,定义一个未初始化的数组: uint8_t hardfault_info[256]; 它会被分配到ZI段中去。什么是ZI段? ZI(.bss) 即 zero-initialized ,它是在代码中未作初始化的需要在运行时被初始化为零的变量的集合。类似地还有 XO(execute-only )、RO(read-only,.text)只读的常量、RW(read-write,.data)在编译时被初始化了的可读写变...

9G25 使用 Buildroot 创建 rootfs

tar -jxvf buildroot-2017.02.tar.bz2 make at91sam9g20dfc_defconfig make menuconfig Target options ---> Enable VFP extension support Build options ---> Mirrors and Download locations ---> 修改几处源为国内的源,以加快下载速度 │ │ () Primary download site │ │ │ │ (http://sources.buildroot.net) Backup download site │ │ │ │ (http://mirrors.ustc.edu.cn/kernel.org) Kernel.org mirror │ │ │ │ (http://mirrors.ustc.edu.cn/gnu) GNU Software mirror │ │ │ │ (http://rocks.moonscript.org) LuaRocks mirror │ │ │ │ (http://mirrors.ustc.edu.cn/CPAN) CPAN mirror (Perl packages) 工具链配置 Toolchain ---> Toolchain type (Buildroot toolchain) (buildroot) custom toolchain vendor name C library (glibc) Kernel Headers (Linux 3.2.x kernel headers) 版本至少与实际使用的内核的版本一样老才可以,否则启动的时候会提示: FATAL: kernel too old Kernel panic - not syncing: Attempted to kill init! exitcode=0x00007f00 查看 busybox 支持的 Linux 版本:file busybox | grep Linux glibc version (2.23) Binutils Version (binutils 2.26.1) GCC compiler Version (gcc 5.x) Enable C++ support 注:在使用 Buildroot 自己编译的 toolchian 之前我使用过 gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabi 作为外部 Toolchain,但是遇到了问题,编译的 rootfs 在启动的时候报错: Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004 网上说问题可能是 Kernel 与 rootfs 在编译的时候没有同时开启 EABI,但我检查(readelf -hA vmlinux busybox)的结果是都开启了。会不会是浮点数的问题?配置的都是 soft float,也没问题。最后发现是 rootfs 指令集用的是 ARMv7-a,而 CPU 是 AT91SAM9G25(ARM926EJ-S(ARM9)),支持的指令集是 ARMv5t。单 buildroot 中没找到向外部 GCC 传递 CFLAGS(-march=armv5t)的配置,于是放弃使用外部工具链。 System configuration ---> /dev management (Dynamic using devtmpfs + eudev) 不选 Run a getty (login prompt) after boot (具体行为后续再 inittab 中改) (eth0) Network interface to configure through DHCP Kernel ---> 不选择编译 Kernel Target packages ---> Show packages that are also provided by busybox Shell and utilities ---> bash Debugging, profiling and benchmark ---> gdb Compressors and decompressors ---> bzip2 gzip Networking applications ---> pppd Bootloaders ---> 不选 如果需要额外配置 busybox,使用:make busybox-menuconfig ,这里使用默认配置 编译系统: make -j4 会在 dl 文件夹放置下载到的源码,在 output/image 中生成 rootfs.tar mkdir rootfs sudo tar -xvf rootfs.tar -C rootfs 添加 10_usbkey.rules 到 /etc/udev/rules.d /etc/profile export LD_LIBRARY_PATH=/qtlib /etc/inittab ttyS0::respawn:/bin/login -f root /etc/init.d/S10udev 修改 udevadm trigger --type=devices --action=add 为 udevadm trigger --type=devices 创建 /qtlib 把 QT 的部分动态库库放进去。 将 linux-ppp-scripts_v1.2 的文件放到相应的位置 sudo ./mkubifsimage rootfs/ ubifs.img 发现的问题: 在启动初始化时,执行 init.d/S10udev 中的 udevadm trigger --type=devices --action=add 时,会出现错误信息: UBI error: ubi_open_volume: cannot open device 0, volume 0, error -16 (估计是操作 /dev/mtd8 时出现的错误,因为 cat /dev/mtd8 时会出现同样的错误信息) cat /proc/mtd dev: size erasesize name mtd0: 00040000 00020000 "bootstrap" mtd1: 00080000 00020000 "uboot" mtd2: 00040000 00020000 "env" mtd3: 00040000 00020000 "env_redundant" mtd4: 00040000 00020000 "spare" mtd5: 00080000 00020000 "dtb" mtd6: 00600000 00020000 "kernel" mtd7: 0f800000 00020000 "rootfs" mtd8: 0eb68000 0001f000 "rootfs" 为什么会有两个 rootfs 呢?mtd8 是怎么来的,留待以后研究。 暂时的解决对策是: 去掉此行中的 --action=a...

把 qt 库加入 rootfs 并制作 UBIFS 镜像

解压 rootfs: sudo tar -zxvf rootfs.tar.gz -C rootfs 添加 10_usbkey.rules到 /etc/udev/rules.d(自动挂载,非必须) 编辑 /etc/profile,加入: export LD_LIBRARY_PATH=/qtlib 编辑 /etc/inittab,加入: ttyO0::respawn:/bin/login -f root 实现自动登陆(非必要) 创建 /qtlib 把 QT 的部分动态库库放进去。 制作镜像: sudo ./mkfs.ubifs -F -r rootfs -m 2048 -e 126976 -c 1866 -o ubifs.img ./ubinize -o ubi.img -m 2048 -p 128KiB -s 2048 -O 2048 ubinize-256M.cf...

Intel HEX

Intel HEX 是一种用 ASCII 文本表达二进制文件信息的文件格式,对于我们玩嵌入式的人来说并不陌生。本文有两个目的: 阐明 Intel HEX 的文件格式; 用 C 语言解析和生成 HEX 文件。 文件格式 Intel HEX 是以记录( record )为单位的,文件的每行存放一条记录。记录的基本格式为...

树莓派——初装

简介 树莓派( Raspberry Pi )是一块 ARM 开发板,由埃本·阿普顿( Eben Epton )发布,现托管在 Raspberry Pi 基金会( https://www.raspberrypi.org/ )。基金会以提升学校计算机科学及相关学科的教育,让计算机变得有趣为宗旨。这块只有信用卡大小的卡片式电脑开放了 GPIO、USB、以太网、影音输出等接口,本身没有存储设备,但留有一个 MicroSD 卡座,用于系统和数据的存储。正因为如此开放的设计和低廉的价格,已在电子和编程爱好者圈内风靡。是我们电子 DIY 或产品快速原型设计的一个好平...

当色彩照进现实——RGB LED 驱动及控制(2)

控制 LED 的上位机可以是 PC,也可以是 Smart Mobile、Pad 。可以使用 Windows 系统,也可以使用 Linux、Android 系统。考虑到跨平台的便利性和语言之间的关联性,我选用了 Python + PyQt 的搭配。既能利用 Python 的良好的跨平台能力和便捷的编程,又能在界面库上向 C++ Qt 靠...