模仿STM32驱动开发格式知识点:
类似于STM32工程文件中的部分头文件,设置好所有需要用到的寄存器地址,定义结构体变量,通过结构体指针访问寄存器,从而实现控制效果。
这里截取文档中的头文件的部分代码:
/*
* 外设寄存器组的基地址
*/
#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;
/*
* 外设指针
*/
#define CCM ((CCM_Type *)CCM_BASE)
//结构体指针指向CCM——BASE,CCM可以控制寄存器了
注意:这里只截取了CCM寄存器和它的结构体指针的定义。
CCM寄存器的基地址也就是结构体中CCR寄存器的地址。(看手册)
所以在main.c的代码中:
void led_init(void)
{
/* 1、初始化IO复用 */
IOMUX_SW_MUX->GPIO1_IO03 = 0X5; /* 复用为GPIO1_IO03 */
IOMUX_SW_PAD->GPIO1_IO03 = 0X10B0;
/* 3、初始化GPIO */
GPIO1->GDIR = 0X0000008; /* GPIO1_IO03设置为输出 */
/* 4、设置GPIO1_IO03输出低电平,打开LED0 */
GPIO1->DR &= ~(1 << 3);
}
初始化IO复用为GPIO引脚的代码和下面初始化GPIO的代码就是利用结构体指针控制寄存器。
SDK移植包知识点:
在观看视频的时候,up主因为直接复制官方的包,修改很多错误,所以直接引用正点原子代码例程中的文件会减少错误。
类似于STM32开发的库函数,HAL库的感觉,个人感觉这是在梳理STM32学习时候封装好的那些内容的底层,是怎么一步一步写上来的,对理解工程的整理框架有很好的帮助作用。
三个文件:fsl_common.h、fsl_iomuxc.h、MCIMX6YH2.h
对于目前的我来说理解几万行的代码显然不可能,所以记录自己认为重要的点。
我们看main.c文件中:
void led_init(void)
{
/* 1、初始化IO复用
这个就是MUX的那个函数设置,设置IO为GPIO。
下面的那个就是PAD的函数设置,设置电气属性
*/
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0); /* 复用为GPIO1_IO0 */
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0X10B0);
/* 3、初始化GPIO,设置GPIO1_IO03设置为输出 */
GPIO1->GDIR |= (1 << 3);
/* 4、设置GPIO1_IO03输出低电平,打开LED0 */
GPIO1->DR &= ~(1 << 3);
}
两个新函数,你可以感觉出一个是设置IO复用为GPIO,一个是GPIO初始化。所以找到他们的声明:
static inline void IOMUXC_SetPinMux(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t inputOnfield)
{
*((volatile uint32_t *)muxRegister) =
IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(muxMode) | IOMUXC_SW_MUX_CTL_PAD_SION(inputOnfield);
if (inputRegister)
{
*((volatile uint32_t *)inputRegister) = IOMUXC_SELECT_INPUT_DAISY(inputDaisy);
}
}
static inline void IOMUXC_SetPinConfig(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t configValue)
{
if (configRegister)
{
*((volatile uint32_t *)configRegister) = configValue;
}
}
这里就是对寄存器的类似于封装,举个例子,我们找出文件中定义寄存器的define代码。
#define IOMUXC_GPIO1_IO03_GPIO1_IO03 0x020E0068U, 0x5U, 0x00000000U, 0x0U, 0x020E02F4U
后面四个数就对应上面函数中的前四个参数,最后一个参数区分两个函数(需要慢慢理解,我也讲不出来,朦胧的懂了,也许没懂。)
标签:MX6U,GPIO1,int,unsigned,STM32,volatile,CCM,uint32,SDK From: https://www.cnblogs.com/cjl520/p/16852854.html