硬件开发2-ARM裸机开发2-I.MX6ULL-main点灯

一、利用main函数调用外设接口 - led

1、配置好启动文件:start.S;

  1. 其内部包含(按顺序记录):
    1. 配置异常向量表,并封装跳转异常向量表情况的函数
    2. 模式切换与栈指针初始化
      1. 切换到IRQ模式并设置其栈指针
      2. 切回SYS/USER模式并设置其栈指针
    3. 调b main

2、main函数

  1. 封装寄存器地址封装、灯初始化、灯亮、灯暗、灯延时的函数
  2. 在main函数内部调用函数接口                       
关键字:volatile:

        防止被修饰的变量会被 “意外修改”,禁止编译器对该变量进行优化

3、编译:

//定义交叉编译工具链的前缀和工具

COPLITE=arm-linux-gnueabihf-

CC=$(COPLITE)gcc

LD=$(COPLITE)ld

OBJCOPY=$(COPLITE)objcopy

OBJDUMP=$(COPLITE)objdump

//列出目标与依赖文件target

OBJS=start.o main.o

TARGET=led

//.S(汇编)和.c(C语言)文件编译为.o目标文件(后者源文件,前者目标文件)
%.o : %.S

    $(CC) -c -g $^ -o $@        //$^表示:所有依赖文件(%.S %.c)   $@表示:目标文件(%.o)

%.o : %.c

    $(CC) -c -g $^ -o $@

//链接->二进制文本->反汇编
$(TARGET).bin:$(OBJS)

    $(LD) -Ttext 0x87800000 $(OBJS) -o $(TARGET).elf

    $(OBJCOPY) -O binary -S -g $(TARGET).elf $(TARGET).bin

    $(OBJDUMP) -D $(TARGET).elf > $(TARGET).dis


clean:

    rm $(OBJS) $(TARGET).elf $(TARGET).bin $(TARGET).dis -f

load:

    ./imxdownload $(TARGET).bin /dev/sdb

4、小点:

  • sp寄存器
    • 概念:
      • ARM架构中,SP寄存器(Stack Pointer,栈指针寄存器):是用于管理函数调用、中断处理等场景中栈操作的核心寄存器;
      • 有效RAM范围内(如0x80000000~0x90000000)
    • 功能:   
      • SP寄存器指向当前栈顶的内存地址,能够动态进行处理压栈和弹栈
      • 属于满减栈,保存函数调用的返回地址、局部变量、中断现场信息等

5、代码实现:

start.S

main.c

makefile

6、优化1.0 - 配置时钟

改动:在main.c中配置了时钟寄存器

7、优化2.0 - 添加硬件寄存器定义和驱动库文件

改动:在main.c中,添加硬件寄存器定义和驱动库文件,

(1)GPIO方向寄存器

  • ARM架构中,GPIO方向寄存器(GDIR)的每个bit控制一个引脚(bit3对应GPIO1_IO03)。
  • |= (1 << 3) 将bit3置1,配置为输出模式,符合硬件要求的原子性位操作(避免影响其他引脚)

(2)GPIO1->DR 位操作注释:

开漏/推挽输出:
DR寄存器bit3直接驱动引脚电平:

  • DR &= ~(1 << 3) 输出低电平(LED点亮,假设共阳极接法)

  • DR |= (1 << 3) 输出高电平(LED熄灭)

8、优化3.0 将功能性函数分离

改动:将有关led的函数封装,放入 led.c led.h

9、makefile

    二、唤醒蜂鸣器

    操作类似:进行优化,进行了BSP工程管理

    1、BSP工程管理

        1.project :存放必要程序


        2.imx6ull :存放NXP提供的i.mx6ull头文件

        3.bsp :存放硬件外设相关功能模块

        4.Makefile: 需要遍目录

    如下图所示

    2、链接脚本(.lds)

    (1)概要

            使用BSP进行工程管理时,makefile就要升级了,同时也需要写一个链接脚本,保证插电启动时,首先运行的是start.S。

            明确链接器:代码段、数据段、BSS 段的存放地址和顺序(为 I.MX6ULL 启动做准备)

            start.S(启动代码)放在最前面,且需初始化BSS段(未初始化全局变量清 0)

    (2)规则
    1)内存布局定义核心结构

    链接脚本的核心是SECTIONS命令块,用于定义程序各段在内存中的布局:

    SECTIONS {
        /* 各段定义 */
    }
    
    2)关键要素分类说明
    - 定位计数器与起始地址
    • . = 0x87800000;
      • 使用定位计数器(.)设置起始链接地址
      • 示例中设置为I.MX6ULL的SD启动地址
      • 后续段将从这个地址开始依次排列
    - 代码段(.text)处理
    .text : {
        obj/start.o      /* 必须首先放置启动文件 */
        *(.text)        /* 收集所有目标文件的.text段 */
    }
    
    • 确保启动代码(start.o)位于最前
    • 通配符*(.text)收集所有.text段
    - 数据段组织
    段类型语法示例作用对齐要求
    只读数据段.rodata ALIGN(4) : {*(.rodata*)}存放常量数据(如字符串)4字节对齐
    已初始化数据.data ALIGN(4) : {*(.data)}存放已初始化全局/静态变量4字节对齐
    未初始化数据.bss ALIGN(4) : {*(.bss)}存放未初始化全局/静态变量4字节对齐
    - BSS段特殊处理
    __bss_start = .;     /* 定义BSS起始符号 */
    .bss ALIGN(4) : {
        *(.bss)          /* 标准BSS段 */
        *(COMMON)        /* 公共块数据 */
    }
    __bss_end = .;       /* 定义BSS结束符号 */
    
    • 需要显式定义起止符号供启动代码使用
    • 必须包含COMMON段
    • 通常需要4字节对齐
    - 对齐控制
    • ALIGN(4)指令确保段起始地址4字节对齐
    • 对齐操作对32位处理器至关重要
    • 可防止内存访问越界和性能下降
    3)完整要素流程图
    SECTIONS
    │
    ├─ 定位计数器设置(.=0x87800000)
    │
    ├─ .text段
    │   ├─ 强制包含start.o
    │   └─ 收集所有.text段
    │
    ├─ .rodata段(ALIGN4)
    │
    ├─ .data段(ALIGN4)
    │
    ├─ BSS段处理
    │   ├─ __bss_start标记
    │   ├─ .bss段(ALIGN4)
    │   │   ├─ 标准.bss
    │   │   └─ COMMON块
    │   └─ __bss_end标记
    4)代码示例解释

    3、代码实现

    start.S

    imx6ull.lds

    beep.c  beep.h

    main.c

    makefile

    评论
    成就一亿技术人!
    拼手气红包6.0元
    还能输入1000个字符
     
    红包 添加红包
    表情包 插入表情
     条评论被折叠 查看
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值