C语言驱动实现

arm coretex-a的不同模式为了尽可能的保护计算机资源(cpu、内存、io等),不同的cpu架构实现了不同的权限等级,等级越高可访问的系统资源越多(包括执行一些特权指令),这是因为普通用户级别的程序代码质量不能得到完全的保障,为了更好的保护计算机资源会让用户级别的代码工作在尽可能少的访问系统资源的模式下,而像操作系统这样经过千锤百炼的程序质量有保障,cpu可以放心的把计算机资源交出来让操作系统可以随意访问。
在当前的实验中,由于我们是工作在祼机状态下的程序,可以简单的认为我们的代码与操作系统代码是一个级别的,就算代码有问题那从cpu的角度来讲我们的祼机代码也是高质量的,也就是说可以工作在高等级权限的模式下。
arm coretex-a系列处理器有以下几种工作模式:其中,svc是超级管理员模式,可以访问所有的计算机资源。
设置cpu工作模式为svccoretex-a提供了一个专门的寄存器cpsr程序状态寄存器来控制当前cpu的工作模式, cpsr的每一位的逻辑如下:
其中的低5位m[4:0]用于指定当前cpu的工作模式,具体表格如下:
m[4:0]cpu工作模式
10000 user模式
10001 fiq模式
10010 irq模式
10011 supervisor(svc)模式
10110 monitor(mon)模式
10111 abort(abt)模式
11010 hyp(hyp)模式
11011 undef(und)模式
11111 system(sys)模式
通过表格可以看出,如果要设置成svc模式,则需要将cpsr寄存器的低5位m[4:0]设置成10011
读写crsr寄存的操作指令与读取通用寄存器使用的ldr与str不要样,需要使用mrs读取cpsr的数据,msr向cpsr写入数据。
/// 将cpsr寄存器中的数据读取到r0/// 这是因为cpsr是不能使用运算符指令对其进行直接的操作的,需要使用通用寄存器mrs r0, cpsr/// 通过使用bic指令将,r0的低5位都清空,这里使用了0x1f=11111. bic指令后面的操作数掩码位的值是1表示将此位清空,否则保持不变bic r0, r0, #0x1f/// 通过orr(或)指令将r0寄存器中的低5位设置成10011orr r0, r0, #0x13/// 将r0的数据写入cprs寄存器,完成svc模式切换msr cprs, r0设置c语言运行环境c语言要工作,需要指定一个栈空间,通过指定sp指针就可以给c语言开辟一块栈空间。
coretex-a的栈是向下生长的,也就是从高地址向低地址生成(即栈顶在高地址)。i.mx6ull的ddr的起始地址是0x80000000,这里设置一个2mb的空间大小,实际上也可以设置成1mb或者512kb也是完全够用的。所以需要设置sp指针的初始位置是0x802000000.
/// 设置sp指针地址ldr sp, =0x80200000/// 跳转到c语言的main函数开始执行b main编写c语言led驱动程序1.使能ccm_ccgr1#define ccm_ccgr1 *((volatile unsigned int *)0x020c406c)ccm_ccgr1 = 0xffffffff;2.复用sw_mux_ctl_pad_gpio1_io03为gpio1_io03#define mux_ctl_pad_gpio1_io03 *((volatile unsigned int *)0x020e0068)mux_ctl_pad_gpio1_io03 = 0x5; /// 100113.配置sw_pad_ctl_pad_gpio1_io03电气属性#define sw_pad_ctl_pad_gpio1_io03 *((volatile unsigned int *)0x020e02f4)sw_pad_ctl_pad_gpio1_io03 = 0x10b04.设置gpio1_gdir的信号输出方向#define gpio01_gdir *((volatile unsigned int *)0x0209c004)gpio01_gdir = 0x08;5.led闪烁#define gpio01_dr *((volatile unsigned int *)0x0209c000)void delay_ms(volatile unsigned int n) { while (n--) { }}void delay(volatile unsigned int n) { while (n--) { delay_ms(0x7ff); }}whilte(1) { delay(500); gpio01_dr = 0x0; delay(500); gpio01_dr = 0x8;}编译代码编写makefile/// 定义目标文件变量objs := start.o main.o/// 生成ledc.bin,依赖objsledc.bin:${objs} arm-linux-gnueabihf-ld -ttext 0x87800000 -o ledc.elf $^ /// 将目标文件链接生成ledc.elf $^表示所有依赖文件的集合,使用空格分开,去重 arm-linux-gnueabihf-objcopy -o binary -s ledc.elf $@ /// 将ledc.elf生成ledc.bin, $@指目标集合,这里的目标就是上面定义的ledc.bin arm-linux-gnueabihf-objdump -d -m arm ledc.elf > ledc.dis /// 将ledc.elf反汇编成ledc.dis,主是要方便查看连接后的代码段指令是否符合预期/// 当目标文件没有时会使用如下的模式规则去生成对应的目标文件/// $@指要生成的.o文件, $<指生成.o的源文件,比如start.o:start.s, $@(start.o) $<(start.s)%.o:%.s arm-linux-gnueabihf-gcc -wall -nostdlib -c -o $@ $<%.o:%.s arm-linux-gnueabihf-gcc -wall -nostdlib -c -o $@ $< %.o:%.c arm-linux-gnueabihf-gcc -wall -nostdlib -c -o $@ $< /// 定义清楚方法clean: rm -rf *.o ledc.bin ledc.elf ledc.dis编译make clean && make编译完成之后烧写到sd卡,选择sd卡启动观察led灯闪烁

音乐ID应用Shasham已在iOS上进行了更新设计
关于华为P10/plus智能“黑科技”都体现在哪里,你了解吗
基于Dragonboard 410c开发板的USB摄像头实现移动侦测
BlueField DPUs和DOCA软件栈提供零信任安全
中国200架固定翼无人机集群试飞成功,无人机技术进一步提升
C语言驱动实现
热电偶传感器的特点及测温原理解析
什么是oauth协议
PCB制造商为何选择飞针来测试刚性柔性电路板
如何看懂汽车的“身份证”——车辆识别码
第三届中国智能建筑节即将开启,各大奖项花落谁家
赑屃:作为一名币圈的投资者到底哪些风险需要去规避?
NSA不是假5G 高通骁龙X50真5G手机选择多
5G时代的媒体离得开4K吗
Widora烧写系统的方法
日光灯长度一般有哪些_日光灯管长度尺寸标准
新唐科技M032 系列简介
大招科技:人工智能AI行业的解决方案
选择MAXQ2000微控制器和MAX1132 ADC接口的SPI时钟模式
5纳米芯片集体成了笑话?