4.4 【案例实战】微处理器的两种编程方式
案例实战演示微处理的裸机编程和移植Linux系统编程。源代码可以通过扫描封底二维码获取。
对于嵌入式微处理器,根据项目的复杂程度以及任务数量,可以分为带操作系统编程和裸机编程。其中裸机编程主要通过操作微处理器的寄存器达到项目需求的效果,比较典型的就是传统的单片机编程方式;带有操作系统的微处理器编程方式比较简单,工程师只需要关注代码如何实现的逻辑功能,其中微处理的寄存器被封装成库函数,提供给工程师调用。在任务调度方面,工程师只需要将任务的调度逻辑实现就可以。下面通过两个具体的案例帮助大家理解。
4.4.1 微处理器裸机系统的GPIO操作
微处理器的裸机编程其实就是单片机编程。现在使用比较多的是STM32系列单片机,这个系列的单片机就属于裸机编程(带有操作系统的除外)。STM32系列单片机在国内比较流行是因为它的配套环境,首先是多种IDE支持STM32系列单片机,其次就是STM32官方提供标准库函数和HAL库,大大简化了STM32开发复杂度。这一章采用i.MX6ull微处理器用裸机方式实现GPIO操作,大家会发现,没有库函数、没有集成开发环境、没有操作系统以后,裸机开发的工作量非常大。
在4.3.2小节中,介绍了ARM处理器的7种工作模式。对于这款i.MX6ull微处理器来说,它的内核是ARM Cortex-A7,因此裸机编程的默认工作模式是SVC。第一步需要设置这个微处理器的SVC工作模式,具体操作如下。
Step 1 新建一个设置SVC模式的汇编文件,i.MX6ull没有提供官方的启动文件,因此需要自己动手写,如图4-8所示。
图4-8 设置处理器的SVC模式
Step 2 配置微处理器的寄存器并使能时钟,如图4-9所示。
图4-9 配置寄存器操作
Step 3 编写操作GPIO的主函数,控制LED灯灭500ms然后亮500ms,周而复始,如图4-10所示。
图4-10 主函数
Step 4 配置文件和主函数写好后,编写Makefile文件,如图4-11所示。
图4-11 Makefile文件
Step 5 执行make指令,如图4-12所示。
图4-12 执行make指令
Step 6 插入SD卡,然后选择连接到虚拟机,如图4-13所示。
Step 7 SD卡连接到虚拟机以后就能够将生成的led.bin文件直接复制到SD卡中,如图4-14所示。
图4-13 SD卡连接虚拟机
图4-14 将ledc.bin文件拷贝到SD卡中
Step 8 将SD卡插上板卡,上电效果如图4-15和图4-16所示。
图4-15 红色LED灯灭500ms
图4-16 红色LED灯亮500ms
4.4.2 微处理器移植Linux系统的GPIO操作
读者如果没有单片机的编程经验,对于4.4.1小节的裸机编程会感到非常复杂,因为微处理器的裸机编程,首先要求工程师要对芯片技术参数非常清楚,最低要掌握常用的寄存器。但是如果在移植好的Linux系统里编程就显得比较轻松了,这里选择第1章介绍过的树莓派开源硬件。本章案例就是采用树莓派来操作其自身的GPIO,为了给读者展示效果,专门在GPIO上接了一个LED灯,通过灯的亮灭更能体现效果。
Step 1使用树莓派通过C语言的方式操作GPIO,需要下载安装树莓派的C语言的支持库wiringPi库。然后使用命令gpio readall来查看树莓派的型号和GPIO的分布,如图4-17所示。
图4-17 安装wiringPi库并查看GPIO
Step 2 在安装完wiringPi库并查看GPIO口以后,选择GPIO. 27引脚,然后在树莓派的目录里新建一个led.c文件,新建命令为touch led.c,接着使用vim led.c打开并编写下述程序代码。
Step 3 使用交叉编译工具(后面章节会介绍)编译led.c文件,编译的时候一定要关联wiringPi库,否则编译器会报错。这里使用的命令是:gcc-o led-lwiringPi led.c。最后使用目标文件./led使其执行,如图4-18所示。
图4-18 LED灯的状态信息
Step 4 可以看到LED灯会以一秒的时间间隔周期闪烁,并闪烁10次,效果如图4-19和图4-20所示。
图4-19 LED灯灭
图4-20 LED灯亮
通过对比两个案例实战的GPIO操作,很明显在系统上编程更有效率。对于系统上的编程,只需要配置相应的支持库,不需要关心微处理器的底层寄存器。但是裸机编程不单单要写主函数,还需要对底层的寄存器进行配置,工作量比较大。