基于IMX6ULL的嵌入式Linux开发学习笔记——(4)五种不同的LED点灯方式之STM32寄存器操作类比+NXP官方SDK方式

  在之前的两章中,已经对LED的纯汇编语言和C语言两种点灯方式进行了介绍。这一章主要讲的是将NXP官方提供的头文件移植进工程中,并在此中进行调用。

参考STM32寄存器定义方法的IMX6ULL寄存器定义

首先定义各寄存器组的基地址,其中最为重要的便是

  1. CCM、CCM_ANALOG(时钟);
  2. IOMUX_SW_MUX(IO复用);
  3. IOMUX_SW_PAD(IO电气属性设置);
  4. 5组GPIO各自的寄存器设置(GPIO1~GPIO5);
/* 
 * 定义:外设寄存器组的基地址 
 */
#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)
/* 
 * 外设指针:即重定义,此后可通过外设指针直接访问各寄存器,
 * 以此实现更为简单的寄存器访问,而不需要自定义一大堆。
 * !!!这种操作很像微机里的寄存器基址变址寻址方式
 */
#define CCM					((CCM_Type *)CCM_BASE)
#define CCM_ANALOG			((CCM_ANALOG_Type *)CCM_ANALOG_BASE)
#define IOMUX_SW_MUX		((IOMUX_SW_MUX_Type *)IOMUX_SW_MUX_BASE)
#define IOMUX_SW_PAD		((IOMUX_SW_PAD_Type *)IOMUX_SW_PAD_BASE)
#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)


然后对各结构体进行定义,如下例子:

```c
/* 
 * 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 
{
...
} CCM_ANALOG_Type; 


/* 
 * IOMUX寄存器组(MUX+PAD)
 */
typedef struct 
{
...
}IOMUX_SW_MUX_Type;

typedef struct 
{
...
}IOMUX_SW_PAD_Type;


/* 
 * GPIO寄存器结构体
 */
typedef struct 
{
...
}GPIO_Type;

通过此项操作之后,之前写入寄存器方式是直接定义到寄存器的最准确的地址。

/*定义配置时钟的寄存器地址*/
#define CCM_CCGR0 *((volatile unsigned long*)0X020C4068)
CCM_CCGR1 = 0xFFFFFFFF;   

/*IOMUX寄存器地址 (配置IO复用/功能的东西)*/

#define SW_MUX_GPIO1_IO03 *((volatile unsigned int *)0X020E0068)
#define SW_PAD_GPIO1_IO03 *((volatile unsigned int *)0X020E02f4)
SW_MUX_GPIO1_IO03 =0x5;  //GPIO复用为GPIO1_IO03
SW_PAD_GPIO1_IO03 =0x10B0; //配置GPIO1_IO03的电气属性

/*GPIO1寄存器配置*/
#define GPIO1_DR          *((volatile unsigned int *)0X0209C000)
#define GPIO1_GDIR        *((volatile unsigned int *)0X0209C004)
#define GPIO1_PSR         *((volatile unsigned int *)0X0209C008)
#define GPIO1_ICR1        *((volatile unsigned int *)0X0209C00C)
#define GPIO1_ICR2        *((volatile unsigned int *)0X0209C010)
#define GPIO1_IMR         *((volatile unsigned int *)0X0209C014)
#define GPIO1_ISR         *((volatile unsigned int *)0X0209C018)
#define GPIO1_EDGE_SEL    *((volatile unsigned int *)0X0209C01C)
GPIO1_GDIR = 0x8; //设置为输出模式
GPIO1_DR   = 0x0; //默认打开LED灯

此后便是通过定义基址,然后通过外设指针重定义后,访问结构体里面的变量从而实现读写寄存器。这样的操作会使程序的复用性更高,普遍适用性更强。

#define CCM_BASE					(0X020C4000)
CCM->CCGR0 = 0xFFFFFFFF;  

#define IOMUX_SW_MUX_BASE			(0X020E0014)
#define IOMUX_SW_PAD_BASE			(0X020E0204)
IOMUX_SW_MUX->GPIO1_IO03 =0x5;  //GPIO复用为GPIO1_IO03
IOMUX_SW_PAD->GPIO1_IO03 =0x10B0; //配置GPIO1_IO03的电气属性

#define GPIO1				((GPIO_Type *)GPIO1_BASE)
GPIO1->GDIR = 0x8; //设置为输出模式
GPIO1->DR   = 0x0; //默认打开LED灯
STM32寄存器操作类比方式总结

  在这种访问寄存器的方式中,其步骤如下:

1.定义最常使用的寄存器基地址(CCM、CCM_Analog,IOMUX_SW_MUX/PAD、GPIOx)等;
2.对各基地址所对应内部的各寄存器进行定义,生成以下寄存器结构体。
CCM_Type,
CCM_Analog_Type,
IOMUX_SW_MUX_Type,
IOMUX_SW_PAD_Type,
GPIOx_Type,
3.通过外设指针设置重定义,并方便之后的结构体指针访问寄存器操作。

#define CCM					((CCM_Type *)CCM_BASE)
#define CCM_ANALOG			((CCM_ANALOG_Type *)CCM_ANALOG_BASE)
#define IOMUX_SW_MUX		((IOMUX_SW_MUX_Type *)IOMUX_SW_MUX_BASE)
#define IOMUX_SW_PAD		((IOMUX_SW_PAD_Type *)IOMUX_SW_PAD_BASE)
#define GPIOx				((GPIO_Type *)GPIOx_BASE)

4.之后通过函数调用结构体指针,即可实现寄存器读写。

CCM->CCGR0 = 0xFFFFFFFF;  //时钟设置

IOMUX_SW_MUX->GPIO1_IO03 =0x5;  //GPIO复用为GPIO1_IO03
IOMUX_SW_PAD->GPIO1_IO03 =0x10B0; //配置GPIO1_IO03的电气属性

GPIO1->GDIR = 0x8; //设置为输出模式
参考NXP官方SDK的IMX6ULL寄存器定义

  把参考STM32寄存器操作和NXP官方SDK放在一起的目的就是,两者的共同性特别强。将NXP官方SDK里的

  1. fsl_common.h (通用宏定义)
  2. fsl_iomuxc.h  (通用寄存器地址)
  3. MCIMX6Y2.h (寄存器结构体和位定义)
  4. 自定义文件 cc.h
    移植过来,即能够将所有的GPIO定义收入囊中。并且需要自定义一些类型以供后续使用。
/*
 *   cc.h:自定义一些数据类型供库文件使用
 */
#define     __I     volatile 
#define     __O     volatile 
#define     __IO    volatile

typedef   signed          char int8_t;
typedef   signed short     int int16_t;
typedef   signed           int int32_t;
typedef unsigned          char uint8_t;
typedef unsigned short     int uint16_t;
typedef unsigned           int uint32_t;
typedef unsigned long     long uint64_t;
typedef	  signed char  	 	   s8;		
typedef	  signed short 	  int  s16;
typedef	  signed int 		   s32;
typedef	  signed long long int s64;
typedef	unsigned char 		   u8;
typedef	unsigned short int     u16;
typedef	unsigned int 		   u32;
typedef	unsigned long long int u64;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

潜心修行嵌入式Linux的鼠鼠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值