——参考正点原子教程
内存管理
一、LINUX驱动开发
0、驱动开发知识点
1.驱动开发
1、基础知识储备
2、裸机汇编程序
- 在VSCode中创建工程文件,在 led.s 中输入如汇编代码;
- 1、编译:
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
- 注意:“运行地址”就是代码运行的时候所处的地址,这个我们在链接的时候就已经确定好了,链接起始地址为 0X87800000;
- 2、链接:
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
- 上述命令中-Ttext 就是指定链接地址,“-o”选项指定链接生成的 elf 文件名,这里我们命名为 led.elf,随后将led.elf 文件转换为.bin 文件
- 3、反汇编:
arm-linux-gnueabihf-objdump -D led.elf > led.dis
大多数情况下我们都是用 C 语言写试验例程的,有时候需要查看其汇编代码来调试代码,
因此就需要进行反汇编,一般可以将 elf 文件反汇编; - 或者以上3步写在Makefile文件中,执行make一键完成;
- 4、下载:
chmod 777 imxdownload //给予 imxdownoad 可执行权限,一次即可
./imxdownload led.bin /dev/sdd //下载到 SD 卡中, 不能烧写到/dev/sda 或 sda1 设备里面!
3、裸机C程序
(以led灯为例)
- 新建 VScode 工程,工程名字为“ledc”,新建三个文件:start.S、main.c 和 main.h。其中 start.S是汇编文件,main.c 和 main.h 是 C 语言相关文件;
- start.S类似于 STM32 中启动文件 startup_stm32f10x_hd.s 用于完成 C 语言环境搭建,只是本实验我们不考虑中断向量表,只考虑初始化 C 环境即可;
- C 语言部分有两个文件 main.c 和 main.h,main.h 里面主要是定义的寄存器地址,main.c 实现功能;
- 编译,链接:
arm-linux-gnueabihf-ld -Ttext 0X87800000 -o ledc.elf start.o main.o
- 下载:
chmod 777 imxdownload //给予 imxdownoad 可执行权限,一次即可
./imxdownload ledc.bin /dev/sdd //下载到 SD 卡中, 不能烧写到/dev/sda 或 sda1 设备里面!
- 用Makefile文件编译时可把链接地址那行用链接脚本文件代替(当需要链接的文件很多时很有用)
- 用编写好了的链接脚本文件:imx6ul.lds更改Makefile中的一行代码
arm-linux-gnueabihf-ld -Ttext 0X87800000 -o ledc.elf $^ //更改前
arm-linux-gnueabihf-ld -Timx6ul.lds -o ledc.elf $^ //更改后
4、系统移植
1、LINUX系统移植蓝图
1、移植bootloader(相当于 BIOS):U-Boot
2、移植Linux内核
3、移植根文件系统:rootfs
移植好 U-Boot(U-Boot只是bootloader程序的一种) 以后再移植 Linux 内核,移植完 Linux 内核以后Linux 还不能正常启动,还需要再移植一个根文件系统(rootfs),根文件系统里面包含了一些最常用的命令和文件。所以 U-Boot、Linux kernel 和 rootfs 这三者一起构成了一个完整的 Linux 系统,一个可以正常使用、功能完善的 Linux 系统。
Linux 系统要启动就必须需要一个 bootloader 程序,也就说芯片上电以后先运行一段bootloader程序。这段bootloader程序会先初始化DDR等外设,然后将Linux内核从flash(NAND,NOR FLASH,SD,MMC 等)拷贝到 DDR 中,最后启动 Linux 内核。
2、系统烧写
- MfgTool 工具:将 uboot、linux kernel、.dtb(设备树)和 rootfs 这四个文件烧写到板子上的 EMMC、NAND 或 QSPI Flash 等其他存储设备上,产品即可运行;
- MfgTool 其实是先通过 USB OTG 先将 uboot、kernel 和.dtb(设备树)
这是三个文件下载到开发板的 DDR 中,注意不需要下载 rootfs。就相当于直接在开发板的 DDR上启动 Linux 系统,等 Linux 系统启动以后再向 EMMC 中烧写完整的系统,包括 uboot、linux kernel、.dtb(设备树)和 rootfs;
5、驱动开发
Linux 中的三大类驱动:字符设备驱动、块设备驱动和网络设备驱动;一个设备可以
属于多种设备驱动类型。
字符设备驱动是占用篇幅最大的一类驱动,因为字符设备最多,从最简单的点灯到I2C、SPI、音频等都属于字符设备驱动的类型。块设备和网络设备驱动要比字符设备驱动复杂,就是因为其复杂所以半导体厂商一般都给我们编写好了,大多数情况下都是直接可以使用的。
应用程序运行在用户空间,而 Linux 驱动属于内核的一部分,因此驱动运行于内核空间。
应用程序使用到的函数在具体驱动程序中都有与之对应的函数,比如应用程序中调用了 open 这个函数,那么在驱动程序中也得有一个名为 open 的函数。每一个系统调用,在驱动中都有与之对应的一个驱动函数
驱动调试