嵌入式 - ARM4

裸机实现LED闪烁

一、启动代码

1. 异常向量表配置

1. .global

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

2. 配置标签

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

3. 异常向量表

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

2. start函数

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

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指令 搭建运行环境

1. 关闭中断

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

2. cps

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

配置中断:        CPS<effect> <iflags>{, #<mode>}

配置模式:        CPS #<mode>

        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. 开启实现目的程序

二、LED灯配置

1. led_init

1.​​ 功能复用配置

GPIO引脚初始化

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

    // IO复用功能配置// 手册C32 - IOMUXV Memory Map... // - IOMUXV Memory Map... - IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 p1571ldr r0, =0x020E0068ldr r1, =0x05                   // 0101 ALT5-GPIO1_IO03str 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),滞回器、上拉/下拉电阻、开漏/推挽输出

    // 引脚电气特性配置// 手册C32 - IOMUXV Memory Map... // - IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 p1793ldr r0, =0x020E02F4ldr 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

    // 引脚方向// 手册C28(外设) - GPIOx - GDIRldr 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

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

3. led_off

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

4. led_delay

        通过执行一个​​空循环​消耗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工作模式:

2. Makefile

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/96137.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/96137.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《C++ 108好库》之2 多线程库thread,mutex,condition_variable,this_thread

《C 108好库》之之2 多线程库thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_thread《C 108好库》之2 多线程库thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_threadstd::thread类​​互斥量&#xff08;Mutex&#xff09;…

Android系统框架知识系列(二十):专题延伸:JVM vs ART/Dalvik - Android运行时演进深度解析

​关键词​&#xff1a;运行时优化、AOT编译、JIT编译、内存管理、电池效率、性能分析一、Android运行时演进背景1. 移动环境的特殊挑战Android运行时环境的演进源于移动设备的独特限制&#xff1a;​移动设备约束条件​&#xff1a;​有限的内存资源​&#xff1a;早期设备仅1…

ubuntu 22 安装轻量级桌面Xfce并使用xrdp远程桌面连接

1.安装Xfce:sudo apt install xubuntu-desktop -y2.安装xrdp:sudo apt install xrdp -y3.配置xrdp&#xff0c;nano /etc/xrdp/xrdp.ini:[Globals] ... port3389 ; 远程连接端口&#xff0c;默认是3389&#xff0c;可以改成自己喜欢的端口... ; ; Session types ;; Some sess…

【Flask】测试平台开发,数据看板开发-第二十一篇

概述&#xff1a;在前面我们已经实现了我们的产品创建管理&#xff0c;应用管理管理&#xff0c;需求提测管理但是每周提测了多少需求&#xff0c;创建了哪些产品&#xff0c;我们是不是看着不是很直观&#xff0c;接下来我们就需要开发一个数据看板功能&#xff0c;实现能够看…

我是程序员,不是程序猿:请别把我当猴耍——拒绝被低估,用专业赢得尊重

摘要 本文旨在深度剖析“程序员”与“程序猿”一字之差背后所反映的职业尊严与身份认同问题。我们生活在一个技术驱动的时代&#xff0c;但对技术创造者的认知却常常被“程序猿”、“码农”等标签简单化、甚至矮化。本文将从正名开始&#xff0c;辨析“程序员”的专业内涵&…

C++中vector删除操作的安全隐患与最佳实践

std::vector 是C标准模板库&#xff08;STL&#xff09;中最常用的动态数组容器&#xff0c;提供了高效的随机访问和动态扩容能力。然而&#xff0c;其删除操作如果使用不当&#xff0c;会引入严重的安全隐患&#xff0c;包括未定义行为、内存泄漏和数据竞争等问题。本文将深入…

Unix/Linux 系统中的 `writev` 系统调用

<摘要> 本文对 Unix/Linux 系统中的 writev 系统调用进行了全面深入的解析。内容涵盖了其产生的背景&#xff08;从传统 write 的局限性到分散/聚集 I/O 概念的引入&#xff09;、核心概念&#xff08;如 struct iovec、系统调用流程&#xff09;。重点剖析了其设计意图&…

深入理解 Android targetSdkVersion:从 Google Play 政策到依赖冲突

深入理解 Android targetSdkVersion&#xff1a;从 Google Play 政策到依赖冲突 作为 Android 开发者&#xff0c;你很可能在 Android Studio 中见过这条提示&#xff1a;Google Play requires that apps target API level 33 or higher。它像一个尽职的提醒者&#xff0c;时常…

灰匣(GrayBox)1.0.0 发布【提升系统权限APP】

灰匣是一个提升系统权限的工具&#xff0c;可以配合Root、三方软件&#xff08;Shizuku&#xff09;以及【设备管理员】&#xff08;设备所有者&#xff09;实现一些高级功能及底层接口&#xff0c;可以自动隔离&#xff08;冻结/禁用&#xff09;不必要的应用&#xff0c;如某…

PAT 1104 Sum of Number Segments

这一题的大意就是找一个数组中的所有子数组&#xff0c;它们的累加和为多少&#xff0c; 题目上给出的数据范围是O(n^5)那么只能遍历一次&#xff0c;不能用暴力的方法求出。 看到这一题我有两个思路&#xff1a; 1.试图用双指针和滑动窗口来把O&#xff08;n^2)的时间复杂度降…

[万字长文]AJAX入门-常用请求方法和数据提交、HTTP协议-报文、接口文档、案例实战

本系列可作为前端学习系列的笔记&#xff0c;代码的运行环境是在VS code中&#xff0c;小编会将代码复制下来&#xff0c;大家复制下来就可以练习了&#xff0c;方便大家学习。 HTML、CSS、JavaScript系列文章 已经收录在前端专栏&#xff0c;有需要的宝宝们可以点击前端专栏查…

Codesy中的UDP发送信息

Codesy UDP通讯 概述 CAA Net Base Services UDP通讯的建立 发送UDP 状态控制 效果 概述 Codesys中默认安装的通讯支持很多,不安装其他的软件也可以实现TCP通讯。但是,在使用UDP通讯时,因为我们的PLC有两个网卡,一般我们把第一个网口做编程和HMI用,把的个网口做外部通讯,…

神经网络之深入理解偏置

&#x1f50d; 1. 表达能力&#xff1a;无偏模型不能表示全体函数族 ✔ 有偏线性变换&#xff1a; yWxb&#xff08;仿射变换&#xff09; y Wx b \quad \text{&#xff08;仿射变换&#xff09;} yWxb&#xff08;仿射变换&#xff09; 能表示任意线性函数 平移是仿射空间的…

小白必看:AI智能体零基础搭建全攻略!

写在前面&#xff1a;别怕&#xff0c;真的不需要技术背景&#xff01; 你是不是经常听到"AI智能体"、"大模型"这些高大上的词&#xff0c;总觉得那是技术大牛的专利&#xff1f;别担心&#xff0c;这篇教程就是为你准备的&#xff01;我们将用最通俗的语…

React state在setInterval里未获取最新值的问题

目录 一、问题描述 二、解决方案 方案一&#xff0c;使用函数式更新 方案二&#xff0c;使用 useRef 保存最新值 一、问题描述 在 React 中&#xff0c;当在 setInterval或setTimeout 中使用 setState 时&#xff0c;经常会遇到状态不是最新值的问题。这是因为闭包导致的&a…

x86 架构 Docker 镜像迁移至 ARM 环境的详细指南

目录 一、问题背景与分析 二、解决步骤 &#xff08;一&#xff09;检查 docker-compose 版本 &#xff08;二&#xff09;升级 docker-compose 1. 对于 Linux 系统 2. 对于 Windows 系统 &#xff08;三&#xff09;验证升级 &#xff08;四&#xff09;重新运行 dock…

零代码部署工业数据平台:TRAE + TDengine IDMP 实践

对于编程初学者来说&#xff0c;软件开发流程中的开发环境配置、安装异常或报错往往需要花费大量时间查阅资料和反复试错&#xff0c;才能正常安装和启动某些软件工具。现在&#xff0c;在 TRAE 的帮助下&#xff0c;即使完全没有接触过编程&#xff0c;也能通过自然语言直接表…

史上最全Flink面试题(完整版)

1、简单介绍一下 FlinkFlink 是一个框架和分布式处理引擎&#xff0c;用于对无界和有界数据流进行有状态计算。并且 Flink 提供了数据分布、容错机制以及资源管理等核心功能。Flink提供了诸多高抽象层的API以便用户编写分布式任务&#xff1a;DataSet API&#xff0c; 对静态数…

C# .NET中使用log4Net日志框架指南

C# .NET中使用log4Net日志框架指南 log4Net是Apache基金会开发的一款高效、灵活的日志记录框架&#xff0c;广泛应用于.NET生态系统中。它支持多种日志输出目标&#xff08;如文件、数据库、控制台&#xff09;&#xff0c;并提供细粒度的日志级别控制&#xff0c;帮助开发者监…

每日算法刷题Day68:9.10:leetcode 最短路6道题,用时2h30min

一. 单源最短路&#xff1a;Dijkstra 算法 1.套路 1.Dijkstra 算法介绍 (1)定义 g[i][j] 表示节点 i 到节点 j 这条边的边权。如果没有 i 到 j 的边&#xff0c;则 g[i][j]∞。 (2)定义 dis[i] 表示起点 k 到节点 i 的最短路长度&#xff0c;一开始 dis[k]0&#xff0c;其余 …