历史上的今天
返回首页

历史上的今天

今天是:2024年10月29日(星期二)

正在发生

2021年10月29日 | Linux之ARM(IMX6U)裸机模仿STM32驱动开发格式

2021-10-29 来源:eefocus

模仿 STM32 驱动开发格式实验

C 语言编写 LED 灯驱动的时候,每个寄存器的地址我们都需要写宏定义,使用起来非常的不方便。我们在学习 STM32 的时候,可以使用“GPIOB->ODR”这种方式来给GPIOB 的寄存器 ODR 赋值,因为在 STM32 中同属于一个外设的所有寄存器地址基本是相邻的(有些会有保留寄存器)。因此我们可以借助 C 语言里面的结构体成员地址递增的特点来将某个外设的所有寄存器写入到一个结构体里面,然后定义一个结构体指针指向这个外设的寄存器基地址,这样我们就可以通过这个结构体指针来访问这个外设的所有寄存器。同理, I.MX6U 也可以使用这种方法来定义外设寄存器,本次我们就模仿 STM32 里面的寄存器定义方式来编写I.MX6U 的驱动


1.模仿STM32寄存器的定义

1.1、STM32寄存器定义简介

为了开发方便, ST 官方为 STM32F103 编写了一个叫做 stm32f10x.h 的文件,在这个文件里面定义了 STM32F103 所有外设寄存器,我们可以使用其定义的寄存器来进行开发,比如我们可以用如下代码来初始化一个 GPIO:


GPIOE->CRL&=0XFF0FFFFF;


GPIOE->CRL|=0X00300000; //PE5 推挽输出


GPIOE->ODR|=1<<5; //PE5 输出高


上述代码是初始化 STM32 的 PE5 这个 GPIO 为推挽输出,需要配置的就是 GPIOE 的寄存器 CRL 和 ODR, “GPIOE”的定义:


#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)


可以看出“GPIOE”是个宏定义,是一个指向地址 GPIOE_BASE 的结构体指针,结构体为GPIO_TypeDef, GPIO_TypeDef 和 GPIOE_BASE 的定义如下:


typedef struct

{

__IO uint32_t CRL;

__IO uint32_t CRH;

__IO uint32_t IDR;

__IO uint32_t ODR;

__IO uint32_t BSRR;

__IO uint32_t BRR;

__IO uint32_t LCKR;

} GPIO_TypeDef;



#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800)

#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)

#define PERIPH_BASE ((uint32_t)0x40000000)


上述定义中 GPIO_TypeDef 是个结构体,结构体里面的成员变量有 CRL、 CRH、 IDR、 ODR、BSRR、 BRR 和 LCKR,这些都是 GPIO 的寄存器,每个成员变量都是 32 位(4 字节),这些寄存器在结构体中的位置都是按照其地址值从小到大排序的。GPIOE_BASE 就是 GPIOE 的基地址,其为:



GPIOE_BASE=APB2PERIPH_BASE+0x1800

  = PERIPH_BASE + 0x10000 + 0x1800

  =0x40000000 + 0x10000 + 0x1800

  =0x40011800


GPIOE_BASE 的基地址为 0x40011800,宏 GPIOE 指向这个地址,因此 GPIOE 的寄存器CRL 的地址就是 0X40011800,寄存器 CRH 的地址就是 0X40011800+4=0X40011804,其他寄存器地址以此类推。我们要操作 GPIOE 的 ODR 寄存器的话就可以通过“GPIOE->ODR”来实现,这个方法是借助了结构体成员地址连续递增的原理。


了解了 STM32 的寄存器定义以后,我们就可以参考其原理来编写 I.MX6U 的外设寄存器定义了。 NXP 官方并没有为 I.MX6UL 编写类似 stm32f10x.h 这样的文件, NXP 只为 I.MX6ULL提供了类似 stm32f10x.h 这样的文件,名为 MCIMX6Y2.h,但是 I.MX6UL 和 I.MX6ULL 几乎一模一样,所以文件 MCIMX6Y2.h 可以用在 I.MX6UL 上。


1.2、I.MX6U寄存器定义

参考 STM32 的官方文件来编写 I.MX6U 的寄存器定义,比如 IO 复用寄存器组“IOMUX_SW_MUX_CTL_PAD_XX”,步骤如下:


1.编写外设结构体

/*

* IOMUX 寄存器组

*/

 typedef struct

 {

  volatile unsigned int BOOT_MODE0;

volatile unsigned int BOOT_MODE1;

volatile unsigned int SNVS_TAMPER0;

volatile unsigned int SNVS_TAMPER1;

………

  volatile unsigned int CSI_DATA00;

volatile unsigned int CSI_DATA01;

  volatile unsigned int CSI_DATA02;

volatile unsigned int CSI_DATA03;

volatile unsigned int CSI_DATA04;

  volatile unsigned int CSI_DATA05;

volatile unsigned int CSI_DATA06;

volatile unsigned int CSI_DATA07;

/* 为了缩短代码,其余 IO 复用寄存器省略 */

115}IOMUX_SW_MUX_Tpye;


上述结构体 IOMUX_SW_MUX_Type 就是 IO 复用寄存器组,成员变量是每个 IO 对应的复用寄存器,每个寄存器的地址是 32 位,每个成员都使用“volatile”进行了修饰,目的是防止编译器优化。


2.定义 IO 复用寄存器组的基地址

根据结构体 IOMUX_SW_MUX_Type 的定义,其第一个成员变量为 BOOT_MODE0,也就是 BOOT_MODE0 这个 IO 的 IO 复用寄存器,查找 I.MX6U 的参考手册可以得知其地址为0X020E0014,所以 IO 复用寄存器组的基地址就是 0X020E0014,定义如下:


#define IOMUX_SW_MUX_BASE (0X020E0014)


3.定义访问指针

访问指针定义如下:


#define IOMUX_SW_MUX ((IOMUX_SW_MUX_Type *)IOMUX_SW_MUX_BASE)


通过上面三步我们就可以通过“IOMUX_SW_MUX->GPIO1_IO03”来访问 GPIO1_IO03 的IO 复用寄存器了。同样的,其他的外设寄存器都可以通过这三步来定义


2.硬件原理分析,和之前的硬件资源一样

3.实验程序编写

创建 VSCode 工程,工作区名字为“ledc_stm32”,新建三个文件: start.s、 main.c 和 imx6ul.h。

其中 start.s 是汇编文件, main.c和 imx6ul.h 是 C 文件,


1. imx6ul.h

文件 imx6ul.h 用来存放外设寄存器定义,在 imx6ul.h 中输入如下代码:


/* 

 * 外设寄存器组的基地址 

 */

#define CCM_BASE (0X020C4000)

#define CCM_ANALOG_BASE (0X020C8000)

#define IOMUX_SW_MUX_BASE (0X020E0014)

#define IOMUX_SW_PAD_BASE (0X020E0204)

#define GPIO1_BASE                  (0x0209C000)

#define GPIO2_BASE                  (0x020A0000)

#define GPIO3_BASE                  (0x020A4000)

#define GPIO4_BASE                  (0x020A8000)

#define GPIO5_BASE                  (0x020AC000)


/* 

 * CCM寄存器结构体定义,分为CCM和CCM_ANALOG 

 */

typedef struct 

{

volatile unsigned int CCR;

volatile unsigned int CCDR;

volatile unsigned int CSR;

volatile unsigned int CCSR;

volatile unsigned int CACRR;

volatile unsigned int CBCDR;

volatile unsigned int CBCMR;

volatile unsigned int CSCMR1;

volatile unsigned int CSCMR2;

volatile unsigned int CSCDR1;

volatile unsigned int CS1CDR;

volatile unsigned int CS2CDR;

volatile unsigned int CDCDR;

volatile unsigned int CHSCCDR;

volatile unsigned int CSCDR2;

volatile unsigned int CSCDR3;

volatile unsigned int RESERVED_1[2];

volatile unsigned int CDHIPR;  

volatile unsigned int RESERVED_2[2];

volatile unsigned int CLPCR;

volatile unsigned int CISR;

volatile unsigned int CIMR;

volatile unsigned int CCOSR;

volatile unsigned int CGPR;

volatile unsigned int CCGR0;

volatile unsigned int CCGR1;

volatile unsigned int CCGR2;

volatile unsigned int CCGR3;

volatile unsigned int CCGR4;

volatile unsigned int CCGR5;

volatile unsigned int CCGR6;

volatile unsigned int RESERVED_3[1];

volatile unsigned int CMEOR;

} CCM_Type; 


typedef struct 

{

volatile unsigned int PLL_ARM;

volatile unsigned int PLL_ARM_SET;

volatile unsigned int PLL_ARM_CLR;

volatile unsigned int PLL_ARM_TOG;

volatile unsigned int PLL_USB1;

volatile unsigned int PLL_USB1_SET;

volatile unsigned int PLL_USB1_CLR;

volatile unsigned int PLL_USB1_TOG;

volatile unsigned int PLL_USB2;

volatile unsigned int PLL_USB2_SET;

volatile unsigned int PLL_USB2_CLR;

volatile unsigned int PLL_USB2_TOG;

volatile unsigned int PLL_SYS;

volatile unsigned int PLL_SYS_SET;

volatile unsigned int PLL_SYS_CLR;

volatile unsigned int PLL_SYS_TOG;

volatile unsigned int PLL_SYS_SS;

volatile unsigned int RESERVED_1[3];

volatile unsigned int PLL_SYS_NUM;

volatile unsigned int RESERVED_2[3];

volatile unsigned int PLL_SYS_DENOM; 

volatile unsigned int RESERVED_3[3];

volatile unsigned int PLL_AUDIO;

volatile unsigned int PLL_AUDIO_SET;

volatile unsigned int PLL_AUDIO_CLR;

volatile unsigned int PLL_AUDIO_TOG;

volatile unsigned int PLL_AUDIO_DENOM;

volatile unsigned int RESERVED_4[3];

volatile unsigned int PLL_VIDEO;

volatile unsigned int PLL_VIDEO_SET;

volatile unsigned int PLL_VIDEO_CLR;

volatile unsigned int PLL_VIDEO_TOG;

volatile unsigned int PLL_VIDEO_NUM;

volatile unsigned int RESERVED_5[3];

volatile unsigned int PLL_VIDEO_DENOM;

volatile unsigned int RESERVED_6[7];

volatile unsigned int PLL_ENET;

volatile unsigned int PLL_ENET_SET;

volatile unsigned int PLL_ENET_CLR;

volatile unsigned int PLL_ENET_TOG;

volatile unsigned int PFD_480;

volatile unsigned int PFD_480_SET;

volatile unsigned int PFD_480_CLR;

volatile unsigned int PFD_480_TOG;

volatile unsigned int PFD_528;

volatile unsigned int PFD_528_SET;

volatile unsigned int PFD_528_CLR;

volatile unsigned int PFD_528_TOG;

volatile unsigned int RESERVED_7[16];

volatile unsigned int MISC0;

volatile unsigned int MISC0_SET;

volatile unsigned int MISC0_CLR;

volatile unsigned int MISC0_TOG;

volatile unsigned int MISC1;

volatile unsigned int MISC1_SET;

volatile unsigned int MISC1_CLR;

volatile unsigned int MISC1_TOG;

volatile unsigned int MISC2;

volatile unsigned int MISC2_SET;

volatile unsigned int MISC2_CLR;

volatile unsigned int MISC2_TOG;

} CCM_ANALOG_Type; 


/* 

 * IOMUX寄存器组

 */

typedef struct 

{

volatile unsigned int BOOT_MODE0;

volatile unsigned int BOOT_MODE1;

volatile unsigned int SNVS_TAMPER0;

volatile unsigned int SNVS_TAMPER1;

volatile unsigned int SNVS_TAMPER2;

volatile unsigned int SNVS_TAMPER3;

volatile unsigned int SNVS_TAMPER4;

volatile unsigned int SNVS_TAMPER5;

volatile unsigned int SNVS_TAMPER6;

volatile unsigned int SNVS_TAMPER7;

volatile unsigned int SNVS_TAMPER8;

volatile unsigned int SNVS_TAMPER9;

volatile unsigned int JTAG_MOD;

volatile unsigned int JTAG_TMS;

volatile unsigned int JTAG_TDO;

volatile unsigned int JTAG_TDI;

volatile unsigned int JTAG_TCK;

volatile unsigned int JTAG_TRST_B;

volatile unsigned int GPIO1_IO00;

volatile unsigned int GPIO1_IO01;

volatile unsigned int GPIO1_IO02;

volatile unsigned int GPIO1_IO03;

volatile unsigned int GPIO1_IO04;

volatile unsigned int GPIO1_IO05;

volatile unsigned int GPIO1_IO06;

volatile unsigned int GPIO1_IO07;

volatile unsigned int GPIO1_IO08;

volatile unsigned int GPIO1_IO09;

volatile unsigned int UART1_TX_DATA;

volatile unsigned int UART1_RX_DATA;

volatile unsigned int UART1_CTS_B;

volatile unsigned int UART1_RTS_B;

volatile unsigned int UART2_TX_DATA;

volatile unsigned int UART2_RX_DATA;

volatile unsigned int UART2_CTS_B;

volatile unsigned int UART2_RTS_B;

volatile unsigned int UART3_TX_DATA;

volatile unsigned int UART3_RX_DATA;

volatile unsigned int UART3_CTS_B;

volatile unsigned int UART3_RTS_B;

volatile unsigned int UART4_TX_DATA;

volatile unsigned int UART4_RX_DATA;

volatile unsigned int UART5_TX_DATA;

volatile unsigned int UART5_RX_DATA;

volatile unsigned int ENET1_RX_DATA0;

volatile unsigned int ENET1_RX_DATA1;

volatile unsigned int ENET1_RX_EN;

volatile unsigned int ENET1_TX_DATA0;

volatile unsigned int ENET1_TX_DATA1;

volatile unsigned int ENET1_TX_EN;

volatile unsigned int ENET1_TX_CLK;

volatile unsigned int ENET1_RX_ER;

volatile unsigned int ENET2_RX_DATA0;

volatile unsigned int ENET2_RX_DATA1;

volatile unsigned int ENET2_RX_EN;

volatile unsigned int ENET2_TX_DATA0;

volatile unsigned int ENET2_TX_DATA1;

volatile unsigned int ENET2_TX_EN;

volatile unsigned int ENET2_TX_CLK;

volatile unsigned int ENET2_RX_ER;

volatile unsigned int LCD_CLK;

volatile unsigned int LCD_ENABLE;

volatile unsigned int LCD_HSYNC;

volatile unsigned int LCD_VSYNC;

volatile unsigned int LCD_RESET;

volatile unsigned int LCD_DATA00;

volatile unsigned int LCD_DATA01;

volatile unsigned int LCD_DATA02;

volatile unsigned int LCD_DATA03;

volatile unsigned int LCD_DATA04;

volatile unsigned int LCD_DATA05;

volatile unsigned int LCD_DATA06;

volatile unsigned int LCD_DATA07;

volatile unsigned int LCD_DATA08;

volatile unsigned int LCD_DATA09;

volatile unsigned int LCD_DATA10;

volatile unsigned int LCD_DATA11;

volatile unsigned int LCD_DATA12;

volatile unsigned int LCD_DATA13;

volatile unsigned int LCD_DATA14;

volatile unsigned int LCD_DATA15;

volatile unsigned int LCD_DATA16;

volatile unsigned int LCD_DATA17;

volatile unsigned int LCD_DATA18;

推荐阅读

史海拾趣

Esc Electronics Corp公司的发展小趣事

在市场竞争日益激烈的背景下,Esc意识到品质管理的重要性。公司投入大量资源用于提升产品质量和服务水平,通过严格的质量控制和客户反馈机制,不断优化产品设计和生产流程。同时,Esc还积极塑造品牌形象,通过参加行业展会、发布新品广告等方式,提升品牌知名度和美誉度。这些努力使得Esc在消费者心中树立了高品质、可信赖的形象。

CNC Tech公司的发展小趣事

为了进一步扩大市场份额和影响力,CNC Tech公司积极实施全球化战略。公司通过参加国际展会、设立海外分支机构等方式,加强与全球客户的交流与合作。同时,CNC Tech还积极引进国际先进的技术和管理经验,不断提升自身的竞争力。在全球化战略的推动下,CNC Tech的产品和服务逐渐打入国际市场,赢得了全球客户的认可和信赖。

e2v technologies公司的发展小趣事

在医疗领域,e2v也积极发挥其作用。公司针对放射治疗系统提供了价格合理、易于运输和安装的国内制造设备,支持中国各地医院和诊所的放射治疗工作。这些设备不仅提高了放射治疗的效果和效率,也为患者带来了更好的治疗体验。

Honeywell公司的发展小趣事

背景:近年来,随着全球对可持续发展和数字化转型的重视,霍尼韦尔积极调整战略方向。

发展:公司加大了在可持续技术和数字化转型领域的投入,推出了一系列创新的产品和解决方案。例如,在能源转型领域,霍尼韦尔与多家中国合作伙伴共同推动可持续航空燃料生产基地的建设;在智慧建筑领域,与腾讯云合作打造联合解决方案等。

关键事件:这些举措不仅体现了霍尼韦尔对可持续发展的承诺和责任担当,也展示了公司在数字化转型方面的前瞻性和创新能力。同时,这些合作也进一步巩固了霍尼韦尔在全球电子行业的领先地位。

富之光(Fujicon)公司的发展小趣事

自成立以来,富致科技始终秉持创新精神,不断投入研发,引进美国最新的PPTC技术,并结合海内外技术专家的智慧,成功开发出多款高性能的自复式保险丝产品。这些产品凭借其出色的安全性能、稳定性和可靠性,迅速在市场上获得了认可。同时,富致科技积极拓展国内外市场,与众多知名企业和行业伙伴建立了长期稳定的合作关系,进一步巩固了其在PPTC保险丝领域的领先地位。

顺芯(Everest-semi)公司的发展小趣事

随着技术的不断进步,顺芯公司意识到只有不断创新才能在激烈的市场竞争中立于不败之地。因此,公司加大了在研发方面的投入,积极引进高端人才,并与国内外知名高校和研究机构建立了合作关系。在XXXX年,顺芯公司成功研发出了一款具有自主知识产权的高性能数模混合芯片,填补了国内市场的空白,并获得了多项专利。

问答坊 | AI 解惑

ucos/2经典中文教程

我做毕业论文时导师给我的,很好的哦,跟大家分享一下.…

查看全部问答>

发现同一个贴子里多个附件下载的问题

最近在论坛里发现很多帖子的资源包含多个附件,而这些附件都是一个文件分成多个的,下载时会连续扣调芯币,这样的话论坛中大部分人几乎无法负担。 这种情况,建议论坛能不能改一下,在一个帖子里的附件下载只扣一次芯币,其他附件就不用扣了。…

查看全部问答>

挂了六科 但电子竞赛多次得奖~~

本帖最后由 paulhyde 于 2014-9-15 09:47 编辑 请大家帮帮忙。 现在很迷茫,大四了要找工作了。 由于兴趣的缘故,导致挂科6门,但是在校内、省级和全国大学生电子竞赛多次得奖,请问大家我该如何找工作啊? 我的专业是机电。  …

查看全部问答>

opc开发是遇到一个问题,请大家帮帮,在此先谢谢了

Set Server = New OPCServer ’生成OPC对象,     Servers = Server.GetOPCServers(\"\") Server.Connect sServerName, \"\" ’连接OPC服务器     Server.OPCGroups.DefaultGroupUpdateRate = 800’设定组的刷新速率   ...…

查看全部问答>

CC2530+2591收发的问题

自己基于basicRF写的代码,加PA后不能接受,关闭PA就能就收到数据,PA部分的代码也是参考basicRF写的,就是三个引脚不一样,我用的是P1.2,P1.3,P1.4三个引脚,请教这里的高手,还需要修改哪些地方或注意哪些地方呢,现在反正是只要一打开PA两个板 ...…

查看全部问答>

5天学会Protel99SE图文教程下载

虽然这个是老古董了,因为看到,还有朋友再使用和学习protel 99,这份资料不错,相信能给初学者带来帮助。 …

查看全部问答>

《单片机与计算机串口通信实践》

串口通信的第一种实现方案:半双工通信方式;这适用于:下位机需要等待上位机的回复之后,方可继续发送下一个数据包的应用场合。在大多数的串口书籍中,串口通信的具体实现均是采用的该方案;但功能太简化、代码不细致。在本书中,全面考虑了菜单 ...…

查看全部问答>

关于nokia5110显示屏的参数设定

本帖最后由 jameswangsynnex 于 2015-3-3 19:56 编辑 刚刚做了下实验,看看调整供电电压对nokia5110液晶显示屏的影响 这个显示屏由于比较便宜,又是点阵的,所以用的比较多,我虽然老早就用了,但是一直有点疑问放在心上,就是其参数设定问题 1 ...…

查看全部问答>

提问+DCH010505D模块工作发热问题

本帖最后由 dontium 于 2015-1-23 11:41 编辑 DCH010505D是TI的电源模块,datasheet上说明是输入5V,输出+-5V的隔离模块。 为什么按datasheet接线,输入的是USB的5V,实测大概有4.9V,输出接近+-10V了? 而且带负载会很热(负载不大,大概有几十 ...…

查看全部问答>

免费送空usb转TTL空PCB

免费赠送USB转TTL空PCB,每人最多5片,如果真的有需要,可以多送。 不包邮的,亲! http://item.taobao.com/item.htm?spm=686.1000925.1000774.13.qirb5N&id=36643840227 …

查看全部问答>