【裸机驱动LED】使用汇编代码驱动LED(四)—— 驱动格式开发篇

news2024/11/26 9:35:46

上一篇使用C语言代码来驱动LED,之前我们是手动设置的每一个寄存器的地址,但是这样的效率太低,而且很麻烦。此时我们注意到同属于 GPIO_CCGRx 这一类的寄存器地址,他们之间都相差 4 个字节。

我们要利用这一特性,将之前的代码改为标准的驱动格式。


目录

一、start.s 汇编文件

二、结构体内存对齐规则

三、register.h 文件

完整 register.h

四、led.c 文件

1、引用方法

2、完整代码


一、start.s 汇编文件

这里就不再赘述,详情可以参考:C 代码驱动LED

二、结构体内存对齐规则

这里建议先了解结构体内存对齐规则的前两点:结构体内存对齐规则

以下面这个结构体为例:

typedef struct
{
    volatile uint32_t CCGR0;
    volatile uint32_t CCGR1;
    volatile uint32_t CCGR2;
    volatile uint32_t CCGR3;
    volatile uint32_t CCGR4;
    volatile uint32_t CCGR5;
    volatile uint32_t CCGR6;
} CCM_CCGR_Type;

结构体对齐规则第一点:第一个成员要放在与结构体起始位置偏移量为0的位置。CCGR0 占4个字节,保存在相对于结构体起始位置偏移量为 0 的位置。

结构体对齐规则第二点:第二个成员要放在偏移量为“ 对齐数的整数倍 ” 的位置。Linux环境下,对齐数 = 变量自身所占空间大小。

CCGR1占4个字节,保存的位置是在偏移量为 4 的整数倍的位置。首先看偏移量为 0,已经保存了CCGR0;然后再看偏移量为 4,还是空的,CCGR1 就可以保存在这个位置。

由此我们可以发现一个规律,因为每个寄存器的地址固定是 4 个字节,只要我们给定结构体的起始位置,里面的寄存器会自动分配地址,而且分配的地址正好就跟我们手动赋值的效果一样(这是刚好利用了结构体对齐规则的特性)。

注意:如果中间存在地址断开的情况,需要手动占位,或者单独给寄存器地址声明为宏

三、register.h 文件

时钟相关结构体

定义一个结构体,这个结构体包含与时钟相关的寄存器,结构体重命名为 CCM_CCGR_Type

typedef struct
{
    volatile uint32_t CCGR0;
    volatile uint32_t CCGR1;
    volatile uint32_t CCGR2;
    volatile uint32_t CCGR3;
    volatile uint32_t CCGR4;
    volatile uint32_t CCGR5;
    volatile uint32_t CCGR6;
} CCM_CCGR_Type;

CCGR0 的地址为 0x20C4068,这也将作为结构体的起始地址,那要如何把这个地址当做是结构体地址呢?强制转化为 CCM_CCGR_Type* 类型,指针类型会告诉编译器,这个地址占了多大空间。

比如 char* 表示告诉指针,这个地址指向的内容占了一个字节;CCM_CCGR_Type* 表示这个地址指向的内容占了 28 个字节。访问结构体中的成员时,便是由起始地址向后访问。

#define CCM_CCGR            ((CCM_CCGR_Type*)0x20C4068)

后面我们只需要使用 CCM_CCGR 便可以访问结构体成员了。

IOMUX 相关寄存器地址

和上面定义CCGR结构体一样,每个地址都强制类型转换成对应的结构体指针类型。

我们会发现 IO_MUX 的地址并不连续,除非自己补上IO_MUX 其他无关寄存器。实际上IOMUX包含了其他很多寄存器,只不过驱动LED不需要那么多寄存器。为了和其他地方统一,这里依然封装成结构体的形式。

typedef struct
{
    volatile unsigned int GPIO1_IO03;
} IOMUX_SW_MUX_Type;

typedef struct
{
    volatile unsigned int GPIO1_IO03;
} IOMUX_SW_PAD_Type;

// 注意: 这里定义的是一个结构体指针,不需要解引用
#define IOMUX_SW_MUX        ((IOMUX_SW_MUX_Type*)0x020E0068)          // 设置IO复用
#define IOMUX_SW_PAD        ((IOMUX_SW_PAD_Type*)0x020E02F4)          // 设置电气属性

 

GPIO1 相关寄存器地址

和上面定义 CCGR 结构体一样,每个地址都强制类型转换成对应的结构体指针类型。

除了GPIO1外,还有GPIO2、GPIO3,这里仅列举出GPIO1的

typedef struct
{
    volatile unsigned int DR;
    volatile unsigned int GDIR;
    volatile unsigned int PSR;
    volatile unsigned int ICR1;
    volatile unsigned int ICR2;
    volatile unsigned int IMR;
    volatile unsigned int ISR;
    volatile unsigned int EDGE_SEL;
} GPIO1_Type;

// 注意: 这里定义的是一个结构体指针,不需要解引用
#define GPIO1        ((GPIO1_Type*)0x209C000)                  // GPIO1_Type 结构体地址(寄存器GPIO1_DR的地址)

完整 register.h

#ifndef _register_h
#define _register_h

typedef unsigned int uint32_t;
typedef struct
{
    volatile uint32_t CCGR0;
    volatile uint32_t CCGR1;
    volatile uint32_t CCGR2;
    volatile uint32_t CCGR3;
    volatile uint32_t CCGR4;
    volatile uint32_t CCGR5;
    volatile uint32_t CCGR6;
} CCM_CCGR_Type;

typedef struct
{
    volatile unsigned int GPIO1_IO03;
} IOMUX_SW_MUX_Type;

typedef struct
{
    volatile unsigned int GPIO1_IO03;
} IOMUX_SW_PAD_Type;

typedef struct
{
    volatile unsigned int DR;
    volatile unsigned int GDIR;
    volatile unsigned int PSR;
    volatile unsigned int ICR1;
    volatile unsigned int ICR2;
    volatile unsigned int IMR;
    volatile unsigned int ISR;
    volatile unsigned int EDGE_SEL;
} GPIO1_Type;

#define CCM_CCGR            ((CCM_CCGR_Type*)0x20C4068)               // CCM_CCGR 结构体地址(寄存器 CCGR0 的地址) 
#define IOMUX_SW_MUX        ((IOMUX_SW_MUX_Type*)0x020E0068)          // 设置IO复用
#define IOMUX_SW_PAD        ((IOMUX_SW_PAD_Type*)0x020E02F4)          // 设置电气属性
#define GPIO1               ((GPIO1_Type*)0x209C000)                  // GPIO1_Type 结构体地址(寄存器GPIO1_DR的地址)

#endif

四、led.c 文件

1、引用方法

以访问时钟寄存器 CCGR0 为例,我们在register.h 的最后定义了宏,这个宏可以看做是结构体指针,我们直接使用宏来调用内部成员。

// CCM_CCGR 是在 register.h 里定义的宏
// CCGR0 是结构体 CCM_CCGR_Type 的成员
CCM_CCGR->CCGR0 = 0xffffffff;

2、完整代码

#include "register.h"

void clk_enable();                      // 时钟源初始化
void led_init();                        // 设置IO复用为GPIO、初始化GPIO
void delay_short(unsigned int n);       // 短时延时
void delay(unsigned int n);             // 延时
void led_on();                          // 点灯
void led_off();                         // 熄灯

int main(void)
{
    /* 1、初始化时钟源 */
    clk_enable();

    /* 2、初始化LED */
    led_init();

    while (1)
    {
        led_on();
        delay(500);

        led_off();
        delay(500);
    }

    return 0;
}

void clk_enable()
{
    CCM_CCGR->CCGR0 = 0xffffffff;
    CCM_CCGR->CCGR1 = 0xffffffff;
    CCM_CCGR->CCGR2 = 0xffffffff;
    CCM_CCGR->CCGR3 = 0xffffffff;
    CCM_CCGR->CCGR4 = 0xffffffff;
    CCM_CCGR->CCGR5 = 0xffffffff;
    CCM_CCGR->CCGR6 = 0xffffffff;
}

void led_init()
{
    /* 1、设置GPIO复用 */
    IOMUX_SW_MUX->GPIO1_IO03 = 0x5;

    /* 2、设置GPIO电气属性 */
    IOMUX_SW_PAD->GPIO1_IO03 = 0x10B0;

    /* 3、GPIO 设为输出 */
    GPIO1->GDIR = 0x00000008;
}

void delay(unsigned int n)
{
    while (n--)
    {
        delay_short(0x7ff);
    }
}

void delay_short(unsigned int n)
{
    while(n--) {}
}

void led_on()
{
    GPIO1->DR &= (~0x08);
}

void led_off()
{
    GPIO1->DR |= 0x08;
}

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

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

相关文章

SciencePub学术 | 【CCF推荐】计算机决策类重点SCIEI征稿中

SciencePub学术 刊源推荐: 【CCF推荐】计算机决策类重点SCI&EI征稿中!信息如下,录满为止: 一、期刊概况: CCF推荐|计算机决策类重点SCI&EI 【期刊简介】IF:3.5-4.0,JCR2区,中科院3/4区…

OpenCV 数据类型及赋值取值

在之前的博客 OpenCV 32F 与 8U Mat数据类型相互转换(C版) 已经提到,OpenCV Mat 类型及对应编号,如下表: 其中C1~C4为通道数,经常使用的数据类型对应如下表所示: 其中: FLT_MAX 3.402823466e38 FLT_MIN …

从亿点点失误,到一点点失误,我是如何做的【工作失误怎么办】

前言 只要我们还在做事,或者说还活着,就没有不犯错的时候。作为一名前端搬砖工,哪怕工作中再仔细小心,也免不了一些失误。 那这是不是说,失误很正常,改了就是嘛? 这么说好像没错。作为失误本…

[Java基础]面向对象-内存解析

因为内存解析篇幅较长,我们单独拿出来讲解。 我们知道,方法执行,其实就对内存的操作,但具体是如何进行的呢?下面我们以生成“圆”为例,从内存的角度解析程序执行过程。 /** * 圆 **/ public class Circle…

5年测试面试要20K,面试三个问题把我打发走了···

都说金三银四,金九银十跳槽涨薪季,我是着急忙慌的准备简历——5年软件测试经验,可独立测试大型产品项目,熟悉项目测试流程…薪资要求?5年测试经验起码能要个20K吧。 我加班肝了一页半简历,投出去一周&…

22种不同的社交媒体内容类型(2023年指南)

您是否觉得自己的社交媒体帖子陷入了无休止的循环?您是否已经无话可说并且感到厌烦了?看起来你没有得到任何牵引力吗? 别担心 — 这些感觉在营销人员和小企业主中很常见。今天,我们将探索社交媒体内容的世界,并为您提…

React-Router 5.0 制作导航栏+页面参数传递

React使用路由 使用React构建SPA应用(单页面应用),要想实现页面间的跳转,首先想到的就是使用路由。在React中,常用的有两个包可以实现这个需求,那就是react-router和react-router-dom。本文主要针对react-router-dom进行说明。 …

麒麟V10服务器 安装samba 软件,并且实现远程连接(压缩包形式)

目录 1 安装包2 实现3 如何查看安装的sambd 的版本4 使用 1 安装包 百度网盘 链接: https://pan.baidu.com/s/1l6HDAGE4_Itj-cp7XtpUNg 提取码: 100w 复制这段内容后打开百度网盘手机App,操作更方便哦2 实现 以下是在Linux系统中使用压缩包方式安装Samba服务的步…

angular框架-通过依赖注入方式挂载loading以实现任意地方一行代码调用全局loading

前言 本文主要阐述关于在angular项目中,loading的常见的使用方式,以及如何全局挂载loading,实现一行代码控制loading开,一行代码控制loading关闭。 正文 首先在angular中增加loading,主要就是组件级和全局挂载&…

Python+appium自动化测试-调用服务器接口

当前很多APP登录都需要绑定手机号,但当我们需要足够多的模拟新用户的注册登录时,无法提供大量的手机号来测试,所以可以让服务器给出一个清除账号的接口,在写自动化脚本的时候可以调用这个接口,保证能够使用一个账号进行…

pycharm的基本使用

废话文学 本人记录笔记始终遵循“能动手绝不动脑,能动脑绝不动手”的基本原则。不会的操作,跟着笔记干就完事了,还动啥脑袋?留着脑细胞刷抖音擦边小姐姐他不香吗? 什么是IDE IDE即【集成开发环境】,Inte…

【Algorithm】Java刷题中要熟练使用的容器Api、Stream流、Lambda表达式

Java刷题中要熟练使用的Stream流、Lambda表达式、容器Api 1.Stream流1.概述2.分类3.具体用法流的常用创建方法 2.Lambda表达式函数式接口Lambda书写语法方法引用 3.各类Api 1.Stream流 1.概述 Stream Api是「集合操作」的一种简化表达形式。其特点是惰性求值,流在…

maven repositories更新失败

在项目的pom文件中添加以下配置 <repositories><repository><id>alimaven</id><name>Maven Aliyun Mirror</name><url>http://maven.aliyun.com/nexus/content/repositories/central/</url><releases><enabled>tr…

视频批量剪辑软件开发源码+SaaS

工具能力 API 描述 上传素材接口 开发者可通过本接口将使用素材上传至抖音服务器。 上传临时素材接口 上传临时素材接口。 获取素材列表接口 获取素材列表接口。 删除素材接口 删除素材接口。 小程序接口能力 获取小程序接口能力。 模拟webhook事件 模拟webhook事…

基于Python的接口自动化-HTTP接口基本组成和网页构成

目录 引言 1、HTTP简介 2、HTTP原理和网页基础 2.1、 HTTP基本原理 2.2、 HTTP请求过程 2.3、 网页构成 【自动化测试工程师学习路线】 引言 在我们进行接口测试时&#xff0c;了解HTTP接口的基本组成和网页构成是非常重要的。 而Python作为一门功能强大、易学易用的编程…

亚马逊美国站 解压神器减压小玩具CPC认证

解压玩具又称减压玩具Relaxing toys&#xff0c;包括挤压、摔砸、揉捏、旋转等多种类型&#xff0c;主要供成年人使用&#xff0c;帮助释放压力。 当提到解压玩具时&#xff0c;通常指的是一类旨在缓解压力、放松心情的小型玩具。以下是几种常见的解压玩具及其简要介绍&#x…

一键开启GPT 平行时空模式

不知道大家日常使用GPT的时候&#xff0c;在一次会话中是如何完成同类任务的对话的? 简单点来说&#xff0c;假设你已经完成了角色设定&#xff0c;比如你设定GPT是一名文案编辑&#xff0c;那么接下来你会多次给它提交稿件让它进行编辑&#xff0c;那么在多次提交的时候&…

基于jsp+mysql+Spring+mybatis+VUE的SpringBoot电影院会员积分管理系统

运行环境: 最好是java jdk 1.8&#xff0c;我在这个平台上运行的。其他版本理论上也可以。 IDE环境&#xff1a; Eclipse,Myeclipse,IDEA或者Spring Tool Suite都可以&#xff0c;如果编译器的版本太低&#xff0c;需要升级下编译器&#xff0c;不要弄太低的版本 tomcat服务器环…

【剑指offer专项突破版】数组篇——“C“

文章目录 前言一 . 排序数组中两个数字的和题目分析思路分析法①代码——双指针法②代码——二分查找 二. 数组中和为 0 的三个数题目分析问题转换代码 三. 和大于等于 target 的最短子数组题目分析思路分析代码 四. 乘积小于 K 的子数组题目分析思路分析代码 五. 和为 k 的子数…

2023 年前端 Web 发展趋势

虽然就个人观点&#xff0c;我觉得 Web 开发在最近几年都没什么进展&#xff08;2016 年至 2021 年&#xff09;&#xff0c;但在刚刚过去的 2022 年中确实又出现了一些新的技术。在本文中&#xff0c;我想跟大家聊聊自己看到的最新 Web 开发的发展趋势。相信这波浪潮会继续激发…