Linux_kernel汇编驱动06

一、ARM汇编语言(GUN-gcc编译器下)

        1、语句格式

{symbol} {instruction|directive|pseudo-instruction} {@ comment}

symbol:为符号。

在ARM汇编语言中,符号必须从一行的行头开始,并且符号中不能包含空格。

在指令和伪指令中,符号用作地址标号(label);

在一些伪操作中,符号用作变量或常量。

instruction:为指令。

在ARM汇编语言中,指令不能从一行的行头开始。

在一行语句中,指令的前面必须有空格或者符号。

directive:为伪操作。

pseudo-instruction:为伪指令。

comment:为语句的注释。

在ARM汇编语言中,注释以(@)开头。

注释结尾即为一行的结尾。

注释也可以单独占用一行。

注意:

在ARM汇编语言中,各个指令,伪指令以及伪操作的助记符必须全部用大写或小写字母,不可以在一个伪操作助记符中既有大写又有小写字母。

         2、伪指令

                ARM伪指令不属于ARM指令集中的指令。

                定义这些指令可以使ARM汇编程序设计变得更加方便。

                ARM伪指令可以像其它ARM指令一样使用。

                汇编器会自动用一条或多条ARM指令替换ARM伪指令。

                ARM的伪指令包括:ADR、ADRL、LDR、NOP

                1)ADR指令(小范围的地址读取伪指令)

语法格式:

ADR{<cond>}    register,expr

<cond>:指令执行的条件码。(可选)

register:目标寄存器。

expr:基于PC或者寄存器的地址表达式。

①当地址值不是字对齐的,其取值范围为 -255 ~ 255

②当地址值是字对齐的,其取值范围为 -1020 ~ 1020

使用说明:

该指令将基于PC的地址值或基于寄存器的地址值读取到寄存器中。

①在汇编程序处理源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或者SUB指令来实现该伪指令的功能。

②如果不能用一条指令来实现ADR伪指令的功能,编译器将报错,因为ADR伪指令中的地址基于PC或者基于寄存器的,所以ADR读取到的地址为位置无关的地址。当ADR伪指令中的地址是基于PC时,该地址与ADR伪指令必须在同一代码段中。

                2)ADRL(中等范围的地址读取伪指令)

语法格式:

ADRL{cond} register, expr

<cond>:指令执行的条件码。(可选)

register:目标寄存器。

expr:基于PC或者寄存器的地址表达式。

①当地址值不是字对齐时,其取值范围为-64KB~64KB。

②当地址值是字对齐时,其取值范围为-256KB~256KB。

使用说明:

该指令将基于PC或基于寄存器的地址值读取到寄存器中。

ADRL伪指令比ADR伪指令可以 读取更大范围的地址。

ADRL伪指令在汇编时被编译器替换成两条指令。

①在汇编编译器处理源程序时,ADRL伪指令被编译器替换成两条合适的指令,即使一条指 令可以完成该伪指令的功能,编译器也将用两条指令来替换该ADRL伪指令。

②如果不能用两条 指令来实现ADRL伪指令的功能,编译器将报告错误。

                3)LDR(大范围的地址读取伪指令)

语法格式:

LDR{cond} register, =[expr|label-expr]

<cond>:指令执行的条件码。(可选)

register:目标寄存器。

expr:32位的常量。

编译器将根据expr的取值情况,处理LDR伪指令如下:

①当expr表示的地址值没有超过MOV或MVN指令中地址的取值范围(±32M)时,

        编译器用合适的MOV或者MVN指令代替该LDR伪指令。

②当expr表示的地址值超过了MOV或MVN指令中地址的取值范围(±32M)时,

        编译器将该常数放在数据缓冲区中,同时用一条基于PC的LDR指令读取该常数。

label-expr:基于PC的地址表达式或者是外部表达式。

①当label-expr为基于PC的地址表达式时,

        编译器将label-expr表示的数值放在数据缓冲区中,

        同时用一条基于PC的LDR指令读取该数值。

②当label-expr为外部表达式或非当前段的表达式时,

        汇编编译器将在目标文件中插入连接重定位伪操作,

        这样连接器将在连接时生成该地址。

使用说明:

LDR伪指令将一个32位的常数或者一个地址值读取到寄存器中。

①当需要读取到寄存器中的数据超过了MOV及MVN指令可以操作的范围时,可以使用 LDR伪指令将该数据读取到寄存器中。

②将一个基于PC的地址值或者外部的地址值读取到寄存器中。由于这种地址值是在连接时确定的,所以这种代码不是位置无关的。同时,LDR伪指令处的PC值到数据缓冲区中的目标数据所在的地址的偏量要小于4KB。

                4)NOP(空操作伪指令)

语法格式:

NOP

NOP伪指令不影响CPSR中的条件标志位。

使用说明:

NOP伪指令在汇编时,将被替换成ARM中的空操作,用来占用CPU的调度时间。

比如,可能为MOV R0, R0等。

        3、伪操作

                告诉编译器怎么去编译指令,本身不会生成机器码,类似于C语言中的宏定义,伪操作一般都以“.”开头,类似于C语言中的“#”

.global _start               @声明全局标号

.equ DATA, 0x101        @#define DATA        0X101

.space 32                    @开辟32个字节的连续存储空间,并初始化为0

二、汇编驱动外设

        1、驱动LED灯

                1)外观

                        通过外观了解有几盏LED灯?4盏(可控)1盏(常亮)

                2)开发板原理图

                        通过开发板原理图了解LED灯连接的芯片管脚(高【灭】/ 低【亮】)

                3)芯片手册

                        通过芯片手册了解需要驱动哪些寄存器

GPIOB26

GPIOBALTFN1_26[21:20]010xC001B024配置复用功能
GPIOBOUTENB[26]10xC001B004配置输出使能
GPIOBOUT[26]00xC001B000配置输出低电平
GPIOBOUT[26]10xC001B000配置输出高电平
GPIOC11
GPIOCALTFN0_11[23:22]010xC001C024配置复用功能
GPIOCOUTENB[11]10xC001C004配置输出使能
GPIOCOUT[11]00xC001C000配置输出低电平
GPIOCOUT[11]10xC001C000配置输出高电平
GPIOC7
GPIOCALTFN0_7[15:14]010xC001C024配置复用功能
GPIOCOUTENB[7]10xC001C004配置输出使能
GPIOCOUT[7]00xC001C000配置输出低电平
GPIOCOUT[7]10xC001C000配置输出高电平
GPIOC12
GPIOCALTFN0_12[25:24]010xC001C024配置复用功能
GPIOCOUTENB[12]10xC001C004配置输出使能
GPIOCOUT[12]00xC001C000配置输出低电平
GPIOCOUT[12]10xC001C000配置输出高电平
                4)汇编代码
.text
.global _start
.arm//宏定义GPIOC12寄存器
.equ GPIOCALTFN0, 0xC001C020    //[25:24]   01
.equ GPIOCOUTENB, 0xC001C004    //[12]      1
.equ GPIOCOUT, 0xC001C000       //[12]      0/1_start://配置GPIOC12管脚的复用功能ldr r0, =GPIOCALTFN0//把地址标号放到r0寄存器中ldr r1, [r0]//将存储器地址为r0的内容加载到r1寄存器中mov r2, #0x03//把立即数0x03传送到r2寄存器中bic r1, r1, r2, lsl #24//r1 = r1 位清楚 r2 << 24mov r3, #0x01//把立即数0x01传送到r3寄存器中orr r1, r1, r3, lsl #24//r1 = r1 | r3 << 24str r1, [r0]//将寄存器r1中的内容存储到存储器地址为r0的空间中//设置为输出模式ldr r0, =GPIOCOUTENB//把地址标号放到r0寄存器中ldr r1, [r0]//将存储器地址为r0的内容加载到r1寄存器中orr r1, r1, r3, lsl #12//r1 = r1 | r3 << 12str r1, [r0]//将寄存器r1中的内容存储到存储器地址为r0的空间中loop://亮ldr r0, =GPIOCOUT//把地址标号放到r0寄存器中ldr r1, [r0]//将存储器地址为r0的内容加载到r1寄存器中bic r1, r1, r3, lsl #12//r1 = r1 位清除 r3 << 12str r1, [r0]//将寄存器r1中的内容存储到存储器地址为r0的空间中bl delay//带返回链接的跳转//灭ldr r0, =GPIOCOUT//把地址标号放到r0寄存器中ldr r1, [r0]//将存储器地址为r0的内容加载到r1寄存器中orr r1, r1, r3, lsl #12//r1 = r1 | r3 << 12str r1, [r0]//将寄存器r1中的内容存储到存储器地址为r0的空间中bl delay//带返回链接的跳转b loop//跳到loop标号delay:push {r5}ldr r5, =0x5000000
delay_loop:sub r5, r5, #1cmp r5, #0bne delay_looppop {r5}mov pc, lr.end
                5)Makefile
TARGET          := bare
BIN             := $(TARGET).bin
LD_ADDR         := 0x48000000
OBJS            := led.oCROSS_COMPILE   := arm-cortex_a9-linux-gnueabi-CC              :=$(CROSS_COMPILE)gcc
AS              :=$(CROSS_COMPILE)as
LD              :=$(CROSS_COMPILE)ld
OBJCOPY         :=$(CROSS_COMPILE)objcopy -O binaryCFLAGS += -nostartfiles
CFLAGS += -nostdlib$(BIN) : $(TARGET)$(OBJCOPY) $(TARGET) $(BIN)
$(TARGET) : $(OBJS)$(LD) -Ttext=$(LD_ADDR) $^ -o $@copy :cp $(BIN) /tftpbootclean :rm -rf $(OBJS) $(TARGET) $(BIN)

        2、按键(button)、蜂鸣器(beep)

.text
.global _start
.arm//宏
.equ GPIOAOUTENB, 0xC001A004
.equ GPIOAPAD, 0xC001A018
.equ GPIOAALTFN1, 0xC001A024
.equ GPIOA_PULLSEL, 0xC001A058
.equ GPIOA_PULLENB, 0xC001A060.equ GPIOCOUT, 0xC001C000
.equ GPIOCOUTENB, 0xC001C004
.equ GPIOCALTFN0, 0xC001C020_start://KEY0 GPIOA28 设置为复用功能0ldr r0, =GPIOAALTFN1//把地址标号放到r0寄存器中ldr r1, [r0]//将存储器地址为r0的内容加载到r1寄存器中mov r2, #0x03//将立即数0x03传输到r2寄存器中bic r1, r1, r2, lsl #24//r1 = r1 位清除 (r2 << 24)str r1, [r0]//将r1寄存器中的数据存储到存储器地址为r0的空间中//KEY0 GPIOA28 设置为输入模式ldr r0, =GPIOAOUTENB//把地址标号放到r0寄存器中ldr r1, [r0]//将存储器地址为r0的内容加载到r1寄存器中mov r3, #0x01//将立即数0x01传输到r3寄存器中bic r1, r1, r3, lsl #28//r1 = r1 位清除 (r3 << 28)str r1, [r0]//将r1寄存器中的数据存储到存储器地址为r0的空间中//KEY0 GPIOA28 设置为上拉输入ldr r0, =GPIOA_PULLSEL//把地址标号放到r0寄存器中ldr r1, [r0]//将存储器地址为r0的内容加载到r1寄存器中orr r1, r1, r3, lsl #28//r1 = r1 | r3 << 28str r1, [r0]//将r1寄存器中的数据存储到存储器地址为r0的空间中//key0 GPIOA28 上拉输入使能ldr r0, =GPIOA_PULLENB//把地址标号放到r0寄存器中ldr r1, [r0]//将存储器地址为r0的内容加载到r1寄存器中orr r1, r1, r3, lsl #28//r1 = r1 | r3 << 28str r1, [r0]//将r1寄存器中的数据存储到存储器地址为r0的空间中//beep GPIOC14 设置为复用功能1ldr r0, =GPIOCALTFN0//把地址标号放到r0寄存器中ldr r1, [r0]//将存储器地址为r0的内容加载到r1寄存器中bic r1, r1, r2, lsl #28//r1 = r1 位清除 (r2 << 28)orr r1, r1, r3, lsl #28//r1 = r1 | r3 << 28str r1, [r0]//将r1寄存器中的数据存储到存储器地址为r0的空间中//beep GPIOC14 设置为输出模式ldr r0, =GPIOCOUTENB//把地址标号放到r0寄存器中ldr r1, [r0]//将存储器地址为r0的内容加载到r1寄存器中orr r1, r1, r3, lsl #14//r1 = r1 | r3 << 14str r1, [r0]//将r1寄存器中的数据存储到存储器地址为r0的空间中bl beep_offloop:ldr r0, =GPIOAPAD//把地址标号放到r0寄存器中ldr r1, [r0]//将存储器地址为r0的内容加载到r1寄存器中ands r1, r1, r3, lsl #28//r1 = r1 & (r3 << 28)bleq beep_onblne beep_offb loopbeep_off://不响ldr r0, =GPIOCOUT//把地址标号放到r0寄存器中ldr r1, [r0]//将存储器地址为r0的内容加载到r1寄存器中bic r1, r1, r3, lsl #14//r1 = r1 位清除 (r3 << 14)str r1, [r0]//将r1寄存器中的数据存储到存储器地址为r0的空间中mov pc, lrbeep_on://响ldr r0, =GPIOCOUT//把地址标号放到r0寄存器中ldr r1, [r0]//将存储器地址为r0的内容加载到r1寄存器中orr r1, r1, r3, lsl #14//r1 = r1 | (r3 << 14)str r1, [r0]//将r1寄存器中的数据存储到存储器地址为r0的空间中mov pc, lr.end

三、ARM裸板的异常(中断)处理

        1、初始化

                1)设置中断源(产生中断的情况)

                2)设置中断控制器(屏蔽、优先级)

                3)设置CPU总开关(使能中断)

        2、执行程序

        3、产生中断

        4、CPU每执行完一条指令,都会检查有无中断/异常产生

        5、发现有中断/异常产生,开始处理,对于不同的异常,会跳去不同的地址执行程序,在这些地址上,只是一条跳转指令,跳去执行摸个函数。

        6、这些函数的任务:保存现场(各类寄存器);处理异常,调用不同的函数;恢复现场。

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

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

相关文章

基于C++实现(MFC界面)家谱管理系统

一、题目&#xff1a;家谱管理系统 二、内容&#xff1a; 2.1 概述 2.1.1 选题原因 做此题的原因是因为可以比较方便的记录家族历代成员的情况与关系&#xff0c;能很好的保存家族每一代的信息&#xff0c;而不用人工纸质的方式来存取家谱&#xff0c;更便于人们保存和使用…

爬虫练习(js逆向解密)

目标 网站地址交易列表 - 福建省公共资源交易电子公共服务平台 (fj.gov.cn) 抓取内容如下&#xff1a; 分析 查找js代码 点击下一页翻页的时候&#xff0c;查看请求返回的数据&#xff0c;发现data数据是经过加密后得到的 通过全局搜索data,发现有两千多个结果&#xff0c;一个…

AI超强语音转文本SenseVoice,本地化部署教程!

文章目录 模型介绍SenseVoice在线预览链接本地化部署VsCode 远程连接 模型介绍 SenseVoice专注于高精度多语言语音识别、情感辨识和音频事件检测 多语言识别&#xff1a; 采用超过40万小时数据训练&#xff0c;支持超过50种语言&#xff0c;识别效果上优于Whisper模型。富文本…

跨境电商代购系统中前台基本功能介绍:帮助更快的了解跨境代购业务

前台多语言&#xff1a;可支持语言有中文&#xff08;繁体&#xff09;中文&#xff08;简体&#xff09;英文等。多语言使用百度翻译引擎接口实现&#xff0c;翻译效果与百度一致&#xff1b;网站语言分为两大块&#xff1a;1.系统后台有语言包可以编辑修改网站标题以及发布文…

WPS中JS宏使用说明(持续优化...)

前言 好久没发文章了&#xff0c;今天闲来无事发篇文章找找之前的码字感觉。 正文 最近在写教案&#xff0c;发现之前的技术又可以派上用场了。就是JS&#xff0c;全称JavaScript&#xff0c;这个语言太强大了&#xff0c;我发现WPS里的宏现在默认就是JS。功能选项如下图&…

MySQL数据库安装(详细)—>Mariadb的安装(day21)

该网盘链接有效期为7天&#xff0c;有需要评论区扣我&#xff1a; 通过网盘分享的文件&#xff1a;mariadb-10.3.7-winx64.msi 链接: https://pan.baidu.com/s/1-r_w3NuP8amhIEedmTkWsQ?pwd2ua7 提取码: 2ua7 1 双击打开安装软件 本次安装的是mariaDB&#xff0c;双击打开mar…

Java运行环境的下载、安装、配置与运行

一、实验目的及要求 目的&#xff1a;掌握如何下载java JDK软件包&#xff0c;如何设置Java程序的运行环境&#xff0c;如何编写与运行Java程序&#xff0c;了解Java概貌。 要求&#xff1a; 1、安装Java JDK软件包&#xff1b; 2、练习编写简单的Java Application程序并掌握…

vscode安装使用plantuml插件

使用 VSCode 插件 如果你在 Visual Studio Code 中使用 PlantUML 插件&#xff0c;你可以按照以下步骤生成图片&#xff1a; 安装 PlantUML 插件&#xff1a; 在 VSCode 的扩展市场中搜索并安装 PlantUML 插件。 配置插件&#xff1a; 打开设置&#xff0c;确保插件配置正确。…

Node.js发票查验接口示例、识别查验接口参数返回

财务、审计等经常与发票打交道的人员常常会遇到虚假发票、错票、重复报销等一系列问题。对于会计审计、代理记账、电子商务等发票查验量多的企业来说&#xff0c;成千上万张发票如果仅依赖于人工来进行核验&#xff0c;速度慢效率低&#xff0c;准确率也没保障&#xff0c;因此…

MySQL record

更改密码&#xff1a; alter user rootlocalhost identified with mysql_native_password by ‘123456’; 注意&#xff1a; 在命令行方式下&#xff0c;每条MySQL的命令都是以分号结尾的&#xff0c;如果不加分号&#xff0c;MySQL会继续等待用户输入命令&#xff0c;直到MyS…

kube-prometheus部署

一、自定义配置(二选一&#xff0c;不建议用这个) grafana-service.yml apiVersion: v1 kind: Service metadata:name: grafananamespace: kube-monitoringlabels:app: grafanacomponent: core spec:type: NodePortports:- port: 3000nodePort: 30011selector:app: grafanaco…

uniapp 懒加载、预加载、缓存机制深度解析

uniapp 懒加载、预加载、缓存机制深度解析 文章目录 uniapp 懒加载、预加载、缓存机制深度解析一、为什么要使用uniapp的懒加载、预加载和缓存机制二、如何使用uniapp的懒加载、预加载和缓存机制1. 懒加载2. 预加载3. 缓存机制 四、扩展与高级技巧1. 结合懒加载和预加载优化页面…

链表.......

从右到左 更新尾部 typedef typedef struct ListNode { int value; struct ListNode *next;(这里不能用listnode*应为还没有定义) } ListNode; #include <stdio.h> #include <stdlib.h> // 定义链表节点结构体 struct ListNode { int value; s…

开发台球助教小程序前景分析

开发台球助教小程序的前景分析可从以下维度展开探讨&#xff1a; 市场需求的增长 台球作为一项受欢迎的休闲运动&#xff0c;其爱好者群体正在扩大。随着大众对这项运动兴趣的增加&#xff0c;寻求系统化培训的需求也愈发明显。台球助教小程序正好填补了这一市场空白&#xf…

【Hadoop|HDFS篇】HDFS的Shell操作

1. 基本语法 hadoop fs 具体命令或者hadoop dfs 具体命令。 两个是完全相同的。 2. 命令大全 hadoop fs&#xff1a; Usage: hadoop fs [generic options][-appendToFile <localsrc> ... <dst>][-cat [-ignoreCrc] <src> ...][-checksum <src> ..…

DrissionPage设置启动浏览器为edge

1.查看浏览器启动路径 在浏览器地址栏输入下面地址&#xff0c;拿到可执行文件的路径 。 edge://version/ 2.替换路径 打开DrissionPage._configs. chromium_options.py文件&#xff0c;找到def browser_path(self)这个函数&#xff0c;将返回内容替换为edge的启动路径&#x…

【网络安全】服务基础第一阶段——第十节:Windows系统管理基础---- 组策略高级应用

目录 一、组策略的基本概念 1.1 组策略的基本概念 1.1.1 组策略对象 1.2 配置 1.2.1 计算机配置&#xff08;Computer Configuration&#xff09; 1.2.2 用户配置&#xff08;User Configuration&#xff09; 1.3 作用范围 1.4 继承和优先级 1.4.1 继承&#xff08;In…

Qt:玩转QPainter序列九(文本,文本框,填充)

前言 继续承接序列八 正文 1. drawImage系列函数 绘制图像 inline void drawImage(const QPoint &p, const QImage &image); 作用: 在指定的点 p 上绘制 QImage 图像。图像的左上角将对齐到 p 点。 inline void drawImage(int x, int y, const QImage &image,…

ArkUI-状态管理-@Provide、@Consume、@Observed、@ObjectLink

ArkUI-状态管理 Provide装饰器和Consume装饰器&#xff1a;与后代组件双向同步概述观察变化框架行为Provide支持allowOverride参数 Observed装饰器和ObjectLink装饰器&#xff1a;嵌套类对象属性变化概述限制条件观察变化框架行为 Provide装饰器和Consume装饰器&#xff1a;与后…

毕业设计选题系统

一、项目概述 Hi&#xff0c;大家好&#xff0c;今天分享的项目是《毕业设计选题系统》。 毕业论文选题是大学教学管理中的重要环节&#xff0c;关系到高校的教学质量。传统的手工管理方式工作效率低下、管理繁琐&#xff0c;浪费教师和学生的时间与精力的问题。本系统以提高…