【linux-IMX6ULL配置GPIO通用流程-以及时钟配置】

目录

  • 1. GPIO模式控制流程
    • 1.1 LED、蜂鸣器、按键
    • 1.2 GPIO控制流程
  • 2. 标准库的简要分析及实现:
    • 2.1 问题引入:
    • 2.2 代码实现:
  • 3. 时钟配置总结:
    • 3.1 时钟树概要:
    • 3.2 IMX6ULL时钟概要及时钟树:
    • 3.3 IMX6ULL时钟配置代码:

1. GPIO模式控制流程

1.1 LED、蜂鸣器、按键

  这些功能的实现都是利用了引脚的GPIO模式,通过GPIO模式进行引脚配置输出或者输入,进而实现LED、蜂鸣器、按键,的功能

1.2 GPIO控制流程

  核心配置思路如下:引脚X->寄存器A->寄存器A1->寄存器B(伪寄存器)

  • 引脚X:顾名思义,看得见,摸得着的物理引脚,一个引脚可以配置成多个模式,X可取范围是1-32,因为这个芯片是32位的,一个寄存器最多能控制32个引脚的输入和输出;
  • 寄存器A:例如对于引脚X,那么我如何把这个引脚配置成我想要的模式呢?例如配置成GPIO模式,答案就是通过寄存器A,也就是IOMUXC_SW_MUX_CTL_PAD_GPIO1_X寄存器,每个引脚都有对应的寄存器A,通过配置寄存器A来确定GPIO的工作模式
  • 寄存器A1:A和A1是一一映射的,一个引脚确定了模式,下一步就是配置电气属性,因此寄存器A1就是配置电气属性的,例如确定了GPIO的工作模式,下一步就是配置这个引脚的电气属性:就是通过寄存器A1来配置的,在数据手册中也叫:IOMUXC_SW_PAD_CTL_PAD_GPIO1_X
  • 寄存器B:引脚确定了模式和电器属性,那么下一步就是确定这个模式下如何进行工作,例如上面确定了GPIO(通用输入输出模式)那么下一步就是配置寄存器B(GPIO寄存器)进行输入或者输出、上下拉、保持、速度等功能的配置
  • 思路如下图:

2. 标准库的简要分析及实现:

2.1 问题引入:

  仔细观察一下,对于以下数据手册中引脚的寄存器地址分布,是不是每个引脚之间的寄存器地址都差4。所以知道了GPIO1_DR的地址后,剩下的寄存器地址我们都可以推出来,因此可以把这一类的寄存器放在一个结构体中,因为结构体存储数据是可以按照等字节连续存储,如何把结构体中的第一个值的地址宏定义一下,那么结构体中的其他寄存器的地址自动获得
在这里插入图片描述

2.2 代码实现:

 &emsp注意,代码把地址强制转换成了结构体指针,因为物理硬件地址不会发生变化,在一些底层的硬件编程中,需要直接访问特定的硬件寄存器。通过将寄存器的地址定义为一个结构体指针,可以方便地进行访问和操作。

//定义结构体中的首地址,那么结构体中的其他寄存器的地址自动获得
#define GPIO1_BASE                  (0x0209C000)
#define GPIO2_BASE                  (0x020A0000)
#define GPIO3_BASE                  (0x020A4000)
#define GPIO4_BASE                  (0x020A8000)
#define GPIO5_BASE                  (0x020AC000)


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;  
}GPIO_Type;

#define GPIO1				((GPIO_Type *)GPIO1_BASE)//注意,这里把地址强制转换成了结构体指针,
                                                      //因为物理硬件地址不会发生变化
//在一些底层的硬件编程中,需要直接访问特定的硬件寄存器。
//通过将寄存器的地址定义为一个结构体指针,可以方便地进行访问和操作。
#define GPIO2				((GPIO_Type *)GPIO2_BASE)
#define GPIO3				((GPIO_Type *)GPIO3_BASE)
#define GPIO4				((GPIO_Type *)GPIO4_BASE)
#define GPIO5				((GPIO_Type *)GPIO5_BASE)

  以上就是一个简单的标准库的实现,其实可以把整个模块都按照这样的形式写出来,例如,IO口寄存器,GPIO,USART,CLOCK,等等

3. 时钟配置总结:

3.1 时钟树概要:

  对于每款MCU都有专有的时钟路线,但是这些芯片有共同点,那就是时钟树,时钟树的根就是外部的晶振,通过对外部晶振的倍频和分频可以得到几大主干道,也就是时钟树的枝干,而通过这些枝干在进行分频和倍频可以得到各个外设需要的时钟。

3.2 IMX6ULL时钟概要及时钟树:

  IMX6ULL大体上有7个PLL和8个PFD时钟总线,其余的大都是从这些时钟总线上分频得到的;其中PLL1作为ARM内核的时钟总线,是要首先进行初始化的,初始化过程中注意点ARM时钟切换频率时要先进行时钟的转接,换好后再把系统时钟接回来;配置ARM时钟时主要参考图如下:
在这里插入图片描述
  配置其他时钟主要参考是时钟树,IMX6ULL时钟树部分截图:注意时钟树中黄色的是寄存器对选择器的配置,红色的是寄存器对分频器的的控制,分频过程中注意不要直接清零,清零代表不分频,可能时钟频率会超出下线的承受范围导致板子卡死,注意有的分频过后要进行握手检测,也就是握手换频率不用关时钟,关时钟换频率不用握手;
在这里插入图片描述

3.3 IMX6ULL时钟配置代码:

#include "bsp_clk.h"
/*使能外设时钟*/
void clk_enable(void)
{
    CCM->CCGR0 = 0xFFFFFFFF;
    CCM->CCGR1 = 0xFFFFFFFF;
    CCM->CCGR2 = 0xFFFFFFFF;
    CCM->CCGR3 = 0xFFFFFFFF;
    CCM->CCGR4 = 0xFFFFFFFF;
    CCM->CCGR5 = 0xFFFFFFFF;
    CCM->CCGR6 = 0xFFFFFFFF;
}

/*初始化时钟*/
void imx6u_clkinit(void)
{
    unsigned int reg=0;
    /*初始化6u的主频为528MHz*/
    if((((CCM->CCSR)>>2) & 0x1)==0)  /*当前时钟使用的是pll1_main_clk,也就是pll1,要进行时钟切换*/
    {
        CCM->CCSR &= ~(1<<8);/*设置step_clk=osc_clk=24MHz*/
        CCM->CCSR |= (1<<2);/*pll1_main_clk=step_clk=24MHz*/
    }
    /*系统时钟切换已经设置好了,下一步就是设置PLL1=1056MHz,根据公式设置DIV_SELECT这八位为88,且使能*/
    CCM_ANALOG->PLL_ARM = ((1<<13)|((88<<0) & 0x7f));
    CCM->CACRR = 1;/*设置二分频*/
    /*现在设置好了时钟,下一步就是把时钟切换回来*/
    CCM->CCSR &= ~(1<<2);/*把这一位PLL1_SW_CLK_SEL清零就行,切换回来了,设置pll1_main_clk=1056MHz*/
    /*二位选择器,通过PLL1_SW_CLK_SEL=0/1来进行选择时钟频率*/

    /*设置PL2的4路PFD*/
    reg=CCM_ANALOG->PFD_528;
    reg &=~(0x3f3f3f3f);
    reg |=(32<<24);             /*初始化PLL2_PFD3=297MHz,利用公式的得到:*/
    reg |=(24<<16);             /*初始化PLL2_PFD2=396MHz,利用公式的得到:*/
    reg |=(16<<8);              /*初始化PLL2_PFD1=594MHz,利用公式的得到:*/
    reg |=(27<<0);              /*初始化PLL2_PFD0=352MHz,利用公式的得到:*/
    CCM_ANALOG->PFD_528=reg;    /*设置完毕*/

     /*设置PL3的4路PFD*/
    reg=0;
    reg=CCM_ANALOG->PFD_480;
    reg &=~(0x3f3f3f3f);
    reg |=(19<<24);              /*初始化PLL3_PFD3=454.7MHz,利用公式的得到:*/
    reg |=(17<<16);              /*初始化PLL3_PFD2=508.2MHz,利用公式的得到:*/
    reg |=(16<<8);               /*初始化PLL3_PFD1=540MHz,利用公式的得到:*/
    reg |=(12<<0);               /*初始化PLL3_PFD0=720MHz,利用公式的得到:*/
    CCM_ANALOG->PFD_480=reg;     /*设置完毕*/

    /*设置AHB_CLK_ROOT=132MHZ*/
    CCM->CBCMR &= ~(3<<18);
    CCM->CBCMR |= (1<<18);//四路选择器选择时钟PLL2_PFD2,即设置:PRE_PERIPH_CLK_SEL=400M(396Mhz)
    /*设置第二个选择器,通过CBCDR寄存器进行设置*/
    CCM->CBCDR &= ~(1<<25);
    while (CCM->CDHIPR & (1<<5));  /*等待握手信号*/

    reg=0;
    reg= CCM->CBCDR;
    reg &= ~(7<<10);  //先清零,这里不能直接先 CCM->CBCDR &= ~(7<<10)清零,因为清零直接变成1分频,超过了132Mhz,直接死机
    reg |= (2<<10);   //在赋值3分频
    CCM->CBCDR=reg;
    while((CCM->CDHIPR >> 1) & (0x1));/*等待握手信号*/

   /*设置IPG_CLK_ROOT=66MHz*/
   /*通过设置CBCDR寄存器的IPG_PODF位实现*/
   reg=0;
   reg = CCM->CBCDR;
   reg &= ~(3<<8);
   reg |= (1<<8);
   CCM->CBCDR=reg; /*设置完毕*/


   /*设置PERCLK_CLK_ROOT时钟为66Mhz*/
   /*设置CSCMR1寄存器的PERCLK_CLK_SEL位为0(第六位),两路选择器选择进入66MHz*/
   CCM->CSCMR1 &= ~(1<<6); /*时钟源已经选择了IPG,可以对照着时钟树进行了解*/
   /*分频器不分频*/
   CCM->CSCMR1 &= ~(0x3f << 0);/*设置完毕,1分频,66MHZ*/


}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[C/C++] -- 代理模式

代理模式是一种结构型设计模式&#xff0c;允许一个对象&#xff08;代理&#xff09;控制另一个对象的访问。代理对象通常充当客户端和实际目标对象之间的中间人&#xff0c;从而控制对目标对象的访问&#xff0c;可以在访问前后进行一些额外的处理。 代理模式的优点包括&…

Python通过定义类实现增删改查(期末考试)

python高级编程期末测试 别看我挣的少&#xff0c;但是我省的多&#xff0c;昨天法拉利又省下两百多万。 一、通过创建自己类来实现增删改查 我们已经利用模型实现单表的增删改查了 现在 我们不想使用模型来操作数据库 我们可以自己定义模型 那么 如何通过自己创建的类实现增…

商标注册证下证的前后时间的注意!

近日下了6个商标注册证&#xff0c;商标初审公告是3个月时间&#xff0c;如果没人提出异议&#xff0c;公告结束后1个月内基本上都可以拿到商标注册证电子版&#xff0c;没有纸制版的&#xff0c;凡是邮寄到付签收纸制商标注册证的基本都是骗。 对商标提出异议的主体平常会在公…

2024年03月 C/C++(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 第1题&#xff1a;满足条件的数的累加2 现有n个整数&#xff0c;将其中个位数为k的数进行累加求和 输入 第一行一个整数n。第二行n个非负整数&#xff0c;以空格分割&#xff0c;每个数不大于100000。第三行一个整数k。 …

uniapp——列表分享当前话题(一个页面多个分享)

案例 分享的时候弹出对应的标题和默认第一张图片 代码 <view v-for"(item,index) in list" :key"index"><button open-type"share" :id"index" click.stop"()>{}"><image src"/static/images/cir…

多客陪玩系统源码APP小程序H5陪玩开发伴游源码游戏陪玩平台源码陪玩平台开发约单源码线下陪玩接单平台app小程序H5源码游戏陪玩app小程序H5开发

出售成品陪玩app小程序H5源码&#xff0c;免费搭建部署和售后服务&#xff0c;并提供源码二开、定制开发等相关服务。 一、陪玩app源码的功能介绍 1、语音聊天: 陪玩app小程序H5源码用户随时创建语音聊天室&#xff0c;实现多用户上麦功能&#xff0c;提高互动聊天体验。 2、游…

Apache SeaTunnel 4月回顾:明星贡献者与技术突破

各位热爱 SeaTunnel 的小伙伴们&#xff0c;SeaTunnel 社区 4 月份月报来啦&#xff01;这里将记录 SeaTunnel 社区每月的重要更新&#xff0c;欢迎关注&#xff01; 月度 Merge 之星 感谢以下小伙伴 4 月为 Apache SeaTunnel 做的精彩贡献&#xff08;排名不分先后&#xff…

02-单片机商业项目编程,从零搭建低功耗系统设计

一、本文内容 上一节《01-单片机商业项目编程&#xff0c;从零搭建低功耗系统设计-CSDN博客》已经对事件驱动原理有个基本了解&#xff0c;本节主要就是如何将事件写的更规范&#xff0c;而不是用t_flag这样的标记&#xff0c;写多了可读性也不强&#xff1b;本节结尾总结将提出…

蓝牙 | 软件:Git管理高通的ChipCode项目

哈喽大家好&#xff0c;最近发现大家在高通chipcode网站上下载不了代码&#xff0c;小编一直使用git的方式获取新版本代码&#xff0c;没有遇到什么阻碍。于是小编到新主机上尝试下载代码的压缩包和git代码&#xff0c;都遇到了问题。由于压缩包是高通自己处理卡住了&#xff0…

【Mac】LiveWallpaper(超高清4K动态壁纸) 安装教程

软件介绍 今天给大家介绍的一款软件叫Live Wallpaper & Themes 4K Pro&#xff0c;这是一款超高清4K动态壁纸应用程序。 Live Wallpaper & Themes 4K Pro是一款提供高品质动态壁纸和主题的应用程序。以下是它的一些主要特点和功能&#xff1a; 1.高清和4K动态壁纸&a…

Shell变成规范与变量

目录 1. Shell脚本 1.1 Shell脚本概述 1.2 Shell的作用 1.3 Shell脚本的构成 2. 重定向与管道操作 2.1 交互式硬件设备 ​ 2.2 重定向操作 3. shell变量 3.1 自定义变量 3.2 变量的作用范围​编辑 3.3 整数变量的运算 4. 环境变量 4.1 特殊的Shell变量 4.2 只读变…

二总线,替代传统485总线通讯,主动上报方案简易实现方法

二总线通信设计专栏 《二总线&#xff0c;替代传统485总线通讯&#xff0c;选型及应用-CSDN博客》《二总线&#xff0c;替代传统485总线通讯&#xff0c;低成本直流载波方案实现及原理-CSDN博客》《二总线&#xff0c;替代传统485总线通讯&#xff0c;调试避坑指南之最大的电流…

基于springboot+mybatis+vue的项目实战之前端

步骤&#xff1a; 1、项目准备&#xff1a;新建项目&#xff0c;并删除自带demo程序&#xff0c;修改application.properties. 2、使用Apifox准备好json数据的mock地址 3、编写基于vue的静态页面 4、运行 整个的目录结构如下&#xff1a; 0、项目准备 新建项目&#xff0…

G 2024-05-09 开源项目日报Top10

根据Github Trendings的统计,今日(2024-05-09统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目6C++项目2TypeScript项目2Jupyter Notebook项目1Lua项目1JavaScript项目1Dify.AI: 开源的LLM应用程序开发平台 创建周期:299 天开发…

22 内核开发-宏内核,微内核探秘

22 内核开发-宏内核&#xff0c;微内核探秘 目录 22 内核开发-宏内核&#xff0c;微内核探秘 1.宏内核 2.宏内核优点 3.宏内核缺点 4.为什么选择宏内核 5.微内核 6.微内核优缺点 7.总结 今天看书&#xff0c;看到一个知识点&#xff1a; 《深入linux内核架构》第7章…

ffmpeg ubuntu18.04编译报错fcntl64

fcntl&#xff0c;fcntl64均是系统的api提供的文件操作&#xff0c;fcntl64本来是用来解决操作大文件的问题&#xff0c;后面fcntl本身已经解决了这个问题&#xff0c;fcntl64就被舍弃了 系统环境信息&#xff1a; ubuntu 18.04 root# cat /etc/issue Ubuntu 18.04.6 LTS \n…

java数据结构之数组系统了解

1.数组介绍 数组就是一个存储数据的容器&#xff0c;容器的长度固定、存储元素的数据类型固定。 跟变量加以区分&#xff1a;变量也可以存储数据&#xff0c;但是只能存一个值。当要存的数据比较多的时候&#xff0c;用变量就不方便了。我们就可以使用数组来存储。 1.1数组…

部分设计模式概述

单例模式 工厂模式 适配器模式 模板方法模式 策略模式 责任链 观察者模式&#xff08;又叫发布订阅模式&#xff09;