目录

嵌入式-ARM4

嵌入式 - ARM4

裸机实现LED闪烁

一、启动代码

1. 异常向量表配置

https://i-blog.csdnimg.cn/direct/0bc9b6d4e0f645b2a76188ab3e8adbc4.png

1. .global

        汇编器指令,全局定义标签_start,作为汇编程序的默认起点

2. 配置标签

        配置标签时可以前置加_ ,以便和普通标签或系统标签做区分

3. 异常向量表

        ARM架构规定异常向量表位置固定,配置对应位置的异常向量

2. start函数

https://i-blog.csdnimg.cn/direct/fa4f40a49c824bae93b06958ba7b64a2.png

1. 操作CPSR寄存器 搭建运行环境

https://i-blog.csdnimg.cn/direct/6fd258f41fe44833a4dbc02c9ef1f4c0.png

1. 配置irq模式

用于处理中断,确保各个部分的独立性

1. mrs 指令使cpsr寄存器 备份到r0中

2. 修改模式为irq模式
                先通过bic指令对后五位清零,便于后续修改模式
                手册Label - ARM processor 查询模式代码,通过orr指令进行修改配置

3. 打开终端I位
                通过bic指令对第 I 位置1,打开中断,确保程序能响应中断
                注:整个程序中断只用配置一次,后续修改 sys 模式时不用再次配置

**4.**msr指令将 r0 值 返回置 cpsr ,确保模式转换

2. 配置sys模式

可以使C语言执行,空间大

1. mrs 指令使cpsr寄存器 备份到r0中

2. 修改模式为sys模式
                sys模式代码为11111,可以省略清零准备步骤

3. 不用再次配置中断响应

**4.**msr指令将 r0 值 返回置 cpsr ,确保模式转换

2. CPS指令 搭建运行环境

https://i-blog.csdnimg.cn/direct/1e55040b20ec4df38d5027e836100479.png

1. 关闭中断

        防止初始化过程被中断打断,确保原子操作

2. cps

手册376 CPS指令专用操作cpsr寄存器

配置中断:        CPS {, #}

配置模式:        CPS #

        CPS用于ARMv6v7架构,keil默认目标为ARMv5架构无法编译通过,可以使用操作CPSR寄存器的方式

3.分配空间

        硬件ROM(加载域)的起始物理地址为0x8000 0000
        为 irq 模式0x12分配 32M = 32 * 1024 * 1024 = 0200 0000 大小的空间,即0x8200 0000
        为 sys 模式0x1F再分配 32M大小的空间,即 0x8400 0000

3. 开启实现目的程序

https://i-blog.csdnimg.cn/direct/fb0436ccf5034caaa9fc902c3d60522e.png

二、LED灯配置

1. led_init

https://i-blog.csdnimg.cn/direct/ae671decd4654347bdea3c4f08198c8e.png

1.​​ 功能复用配置

GPIO引脚初始化

        手册C32 - IOMUXV Memory Map… - IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 p1571
        引脚的功能复用(MUX)

https://i-blog.csdnimg.cn/direct/aa275bfc5d41474d8a5f998c26f0756d.png


    // IO复用功能配置
    // 手册C32 - IOMUXV Memory Map... 
    // - IOMUXV Memory Map... - IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 p1571
    ldr r0, =0x020E0068
    ldr r1, =0x05                   // 0101 ALT5-GPIO1_IO03
    str r1, [r0]     
  1. 加载IOMUX控制寄存器地址
            Address:20E_0000h base + 68h offset = 0x20E 0068

  2. 将引脚功能从默认模式切换为GPIO
            模式GPIO_IO03 gpio1模式代码为 0101 = 0x05

  3. str指令将配置写回寄存器
            将 r1 存放的内容存放在 r0 存放的地址内
            即将0x05 模式存放在控制寄存器的地址,实现引脚初始化

2.​ ​电气特性配置

设置引脚的驱动能力、上下拉等电气参数

GPIO引脚初始化

        手册C32 - IOMUXV Memory Map… - IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 p1793
        引脚的​​电气特性​(PAD),滞回器、上拉/下拉电阻、开漏/推挽输出

https://i-blog.csdnimg.cn/direct/728221f675e84748a6a56573a6a346a0.png


    // 引脚电气特性配置
    // 手册C32 - IOMUXV Memory Map... 
    // - IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 p1793
    ldr r0, =0x020E02F4
    ldr r1, =0x10B0                 
    str r1, [r0]      
  1. 加载PAD控制寄存器地址
            Address:20E_0000h base + 2F4h offset = 0x20E 02F4

  2. 配置电气参数(驱动强度、压摆率、上下拉、开漏/推挽)
            配置为0x10B0 = 0001 0000 1011 0000
            对应部分参数为:12位  :    1:使能上拉
                                         7-6位:  10:中速100MHZ
                                         5-3位:110:中等驱动强度        ……

  3. str指令将配置写回寄存器
            将 r1 存放的内容存放在 r0 存放的地址内
            即将0x10B0 模式存放在PAD寄存器的地址,实现电气配置

3. ​方向配置

        将引脚设置为输出模式
        手册C28(外设) - GPIOx - GDIR

https://i-blog.csdnimg.cn/direct/0b9b4a2362a143d28c1f172324289c28.png


    // 引脚方向
    // 手册C28(外设) - GPIOx - GDIR
    ldr r0, =0x0209C004             
    ldr r1, [r0] 
    orr r1, r1, #(1 << 3)
    str r1, [r0]  
  1. 加载GPIO1的GDIR(方向控制寄存器)地址
            Address:Base address + 4h offset

  2. 设置输出模式
            将GPIO_IO03设为输出,即通过orr指令将第三位置1

  3. str指令将配置写回寄存器
            将 r1 存放的内容存放在 r0 存放的地址内
            即将结果返回寄存器地址,实现配置输出模式

2. led_on

        手册C28(外设) - GPIOx - DR

https://i-blog.csdnimg.cn/direct/789a302ac2bf4f55b39013a10c956fb1.png

https://i-blog.csdnimg.cn/direct/0874bdb98e634a48a24d897138e714d7.png

通过bic指令将GPIO_IO03位清零,通过硬件电气特征,此时LED点亮

3. led_off

https://i-blog.csdnimg.cn/direct/500710e7eb2a4baab3e5acdbf62eb36e.png

通过orr指令将GPIO_IO03位置1,通过硬件电气特征,此时LED熄灭

4. led_delay

https://i-blog.csdnimg.cn/direct/bee704daba224ebf890a5a7e85546184.png

        通过执行一个​​空循环​消耗CPU时间,实现​软件延时​​

三、编译与测试

1. 编译步骤

1. arm-linux-gnueabihf-gcc 只汇编不链接

arm-linux-gnueabihf-gcc -c start.S -o start.o -g

        -o         只编译不链接
        -g         保留编译信息

2. arm-linux-gnueabihf-ld 链接代码到特定地址

        (得到可执行,可连接程序 linux executable linkable file)

arm-linux-gnueabihf-ld -Ttext 0x87800000 start.o -o start.elf

        Ttext         指定代码段加载地址
        -o              输出ELF格式可执行文件

3. arm-linux-gnueabihf-objcopy 格式转换

arm-linux-gnueabihf-objcopy -O binary -S -g start.elf start.bin

        -O binary                输出二进制格式
        -S                           去除符号表
        -g                            去除调试信息

4. arm-linux-gnueabihf-objdump 反汇编(可省略)

arm-linux-gnueabihf-objdump -D start.elf  > start.dis

-D                 反汇编所有段

5. imxdownload 烧写程序到SD卡

./imxdownload start.bin /dev/sdb

        插入SD卡后选择连接到虚拟机Ubuntu       
        使用 chmod +777 imxdownload 命令赋予 imxdownload 权限
        通过 ls/imxdownload /dev/sdb 命令查看dev
        刚插入SD卡就执行命令可能会出错,现象为少烧写速率以M为单位,此时需要重启虚拟机

6. 将SD卡插入板子观察现象

        注:
                修改板子工作模式为SD模式
                插入SD卡时不要上电

BOOT工作模式:

https://i-blog.csdnimg.cn/direct/eec940d9811b4ce0a95d24c8a5595ec3.png

https://i-blog.csdnimg.cn/direct/0c138ff3a9a34798af7c2fe8466126fd.png

2. Makefile

https://i-blog.csdnimg.cn/direct/2767515198f24e6f8d0a0ca23858ab4a.png