0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言驱动实现

汽车电子技术 来源:程序猿搬砖 作者:程序猿搬砖 2023-03-02 16:28 次阅读

ARM Coretex-A的不同模式

为了尽可能的保护计算机资源(CPU、内存、IO等),不同的CPU架构实现了不同的权限等级,等级越高可访问的系统资源越多(包括执行一些特权指令),这是因为普通用户级别的程序代码质量不能得到完全的保障,为了更好的保护计算机资源会让用户级别的代码工作在尽可能少的访问系统资源的模式下,而像操作系统这样经过千锤百炼的程序质量有保障,CPU可以放心的把计算机资源交出来让操作系统可以随意访问。

在当前的实验中,由于我们是工作在祼机状态下的程序,可以简单的认为我们的代码与操作系统代码是一个级别的,就算代码有问题那从CPU的角度来讲我们的祼机代码也是高质量的,也就是说可以工作在高等级权限的模式下。

ARM Coretex-A系列处理器有以下几种工作模式:图片其中,SVC是超级管理员模式,可以访问所有的计算机资源。

设置CPU工作模式为SVC

Coretex-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寄存的操作指令与读取通用寄存器使用的ldrstr不要样,需要使用mrs读取CPSR的数据,msrCPSR写入数据。

/// 将cpsr寄存器中的数据读取到r0
/// 这是因为cpsr是不能使用运算符指令对其进行直接的操作的,需要使用通用寄存器
mrs r0, cpsr
/// 通过使用bic指令将,r0的低5位都清空,这里使用了0x1f=11111. bic指令后面的操作数掩码位的值是1表示将此位清空,否则保持不变
bic r0, r0, #0x1f
/// 通过orr(或)指令将r0寄存器中的低5位设置成10011
orr r0, r0, #0x13
/// 将r0的数据写入cprs寄存器,完成svc模式切换
msr cprs, r0

设置C语言运行环境

C语言要工作,需要指定一个栈空间,通过指定sp指针就可以给C语言开辟一块栈空间。

Coretex-A的栈是向下生长的,也就是从高地址向低地址生成(即栈顶在高地址)。I.MX6ULLDDR的起始地址是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; /// 10011
  • 3.配置SW_PAD_CTL_PAD_GPIO1_IO03电气属性
#define SW_PAD_CTL_PAD_GPIO1_IO03 *((volatile unsigned int *)0x020E02F4)
SW_PAD_CTL_PAD_GPIO1_IO03 = 0x10B0
  • 4.设置GPIO1_GDIR的信号输出方向
#define GPIO01_GDIR *((volatile unsigned int *)0x0209C004)
GPIO01_GDIR = 0x08;
#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,依赖objs
ledc.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灯闪烁

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10496

    浏览量

    207085
  • 计算机
    +关注

    关注

    19

    文章

    6696

    浏览量

    85080
  • 操作系统
    +关注

    关注

    37

    文章

    6337

    浏览量

    122031
收藏 人收藏

    评论

    相关推荐

    C语言在信号处理中的设计与实现

    C语言在信号处理中的设计与实现
    发表于 08-15 18:43

    CRC算法和c语言实现

    CRC算法和c语言实现
    发表于 08-20 19:21

    基于C语言的数字PID控制算法及实现

    基于C语言的数字PID控制算法及实现
    发表于 06-13 11:45

    TLC5941 C语言驱动

    哪位有TLC5941的C语言驱动程序,是否可以提供参考,谢谢!
    发表于 09-13 14:10

    如何实现C语言播放音乐

    实现C语言播放音乐的方法
    发表于 12-28 06:18

    C语言怎么实现高效编程?

    C语言怎么实现高效编程?
    发表于 04-28 06:14

    如何用C语言实现面向对象编程

    1 用C语言实现面向对象编程GOF的《设计模式》一书的副标题叫做“可复用面向对象软件的基础”,从标题就能看出面向对象是设计模式基本思想。由于C语言并不是面向对象的
    发表于 07-12 07:24

    基于Proteus和C语言实现

    基于Proteus和C语言实现一共四个题目,有没有人愿意尝试一下?
    发表于 07-14 06:20

    如何使用C语言实现模糊PID控制?

    如何使用C语言实现模糊PID控制?
    发表于 09-24 08:54

    C语言怎么实现输入输出日期?

    C语言怎么实现输入输出日期?
    发表于 10-18 07:49

    C语言实现常用排序算法是什么?

    C语言实现常用排序算法是什么?
    发表于 10-19 06:41

    怎么实现c语言循环链表?

    怎么实现c语言循环链表?
    发表于 10-19 06:07

    为什么又说Linux驱动不是C语言

    说到Linux驱动,尤其是嵌入式Linux驱动,大家可能会望而却步,因为入门太难!很多书上或课程基本是这样的:一上来给我们展示一大堆高深莫测的代码,感觉是C语言,又感觉不是
    发表于 11-05 07:13

    C语言如何实现Hmacsha1的加密?

    C语言如何实现Hmacsha1的加密?
    发表于 12-02 06:18

    经典C语言接口与实现:创建可重用软件的技术

    C语言接口与实现(创建可重用软件的技术)概念清晰、内容新颖、实例详尽,是一本有关设计、实现和有效使用C
    发表于 09-25 06:42