ARM(IMX6U)裸机模仿STM32驱动开发实验(定义外设结构体)

参考:Linux之ARM(IMX6U)裸机模仿STM32驱动开发格式
作者:一只青木呀
发布时间: 2020-08-15 12:11:56
网址:https://blog.csdn.net/weixin_45309916/article/details/108019447

目录

  • 0.外设结构体抽象思路
  • 1.模仿STM32寄存器的定义
    • 1.1、STM32寄存器定义方式
    • 1.2、I.MX6U寄存器定义步骤
      • 1.编写外设结构体
      • 2.定义 IO 复用寄存器组的基地址
      • 3.定义访问指针
  • 2.硬件原理分析,和之前的硬件资源一样
  • 3.实验程序编写
    • 1.imx6ul.h
    • 2.main.c
    • 3.start.s
  • 4.编译下载验证
    • 1.编写链接脚本
    • 2.编写Makefile脚本
    • 3.编译下载

0.外设结构体抽象思路

之前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 中输入如下代码:

要去imx6ul参考手册找到这些寄存器的地址,比如下面的CCM寄存器。 这里是引用
在这里插入图片描述

/* * 外设寄存器组的基地址 */
#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;volatile unsigned int LCD_DATA19;volatile unsigned int LCD_DATA20;volatile unsigned int LCD_DATA21;volatile unsigned int LCD_DATA22;volatile unsigned int LCD_DATA23;volatile unsigned int NAND_RE_B;volatile unsigned int NAND_WE_B;volatile unsigned int NAND_DATA00;volatile unsigned int NAND_DATA01;volatile unsigned int NAND_DATA02;volatile unsigned int NAND_DATA03;volatile unsigned int NAND_DATA04;volatile unsigned int NAND_DATA05;volatile unsigned int NAND_DATA06;volatile unsigned int NAND_DATA07;volatile unsigned int NAND_ALE;volatile unsigned int NAND_WP_B;volatile unsigned int NAND_READY_B;volatile unsigned int NAND_CE0_B;volatile unsigned int NAND_CE1_B;volatile unsigned int NAND_CLE;volatile unsigned int NAND_DQS;volatile unsigned int SD1_CMD;volatile unsigned int SD1_CLK;volatile unsigned int SD1_DATA0;volatile unsigned int SD1_DATA1;volatile unsigned int SD1_DATA2;volatile unsigned int SD1_DATA3;volatile unsigned int CSI_MCLK;volatile unsigned int CSI_PIXCLK;volatile unsigned int CSI_VSYNC;volatile unsigned int CSI_HSYNC;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;
}IOMUX_SW_MUX_Type;typedef struct 
{volatile unsigned int DRAM_ADDR00;volatile unsigned int DRAM_ADDR01;volatile unsigned int DRAM_ADDR02;volatile unsigned int DRAM_ADDR03;volatile unsigned int DRAM_ADDR04;volatile unsigned int DRAM_ADDR05;volatile unsigned int DRAM_ADDR06;volatile unsigned int DRAM_ADDR07;volatile unsigned int DRAM_ADDR08;volatile unsigned int DRAM_ADDR09;volatile unsigned int DRAM_ADDR10;volatile unsigned int DRAM_ADDR11;volatile unsigned int DRAM_ADDR12;volatile unsigned int DRAM_ADDR13;volatile unsigned int DRAM_ADDR14;volatile unsigned int DRAM_ADDR15;volatile unsigned int DRAM_DQM0;volatile unsigned int DRAM_DQM1;volatile unsigned int DRAM_RAS_B;volatile unsigned int DRAM_CAS_B;volatile unsigned int DRAM_CS0_B;volatile unsigned int DRAM_CS1_B;volatile unsigned int DRAM_SDWE_B;volatile unsigned int DRAM_ODT0;volatile unsigned int DRAM_ODT1;volatile unsigned int DRAM_SDBA0;volatile unsigned int DRAM_SDBA1;volatile unsigned int DRAM_SDBA2;volatile unsigned int DRAM_SDCKE0;volatile unsigned int DRAM_SDCKE1;volatile unsigned int DRAM_SDCLK0_P;volatile unsigned int DRAM_SDQS0_P;volatile unsigned int DRAM_SDQS1_P;volatile unsigned int DRAM_RESET;volatile unsigned int TEST_MODE;volatile unsigned int POR_B;volatile unsigned int ONOFF;volatile unsigned int SNVS_PMIC_ON_REQ;volatile unsigned int CCM_PMIC_STBY_REQ;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;volatile unsigned int LCD_DATA19;volatile unsigned int LCD_DATA20;volatile unsigned int LCD_DATA21;volatile unsigned int LCD_DATA22;volatile unsigned int LCD_DATA23;volatile unsigned int NAND_RE_B;volatile unsigned int NAND_WE_B;volatile unsigned int NAND_DATA00;volatile unsigned int NAND_DATA01;volatile unsigned int NAND_DATA02;volatile unsigned int NAND_DATA03;volatile unsigned int NAND_DATA04;volatile unsigned int NAND_DATA05;volatile unsigned int NAND_DATA06;volatile unsigned int NAND_DATA07;volatile unsigned int NAND_ALE;volatile unsigned int NAND_WP_B;volatile unsigned int NAND_READY_B;volatile unsigned int NAND_CE0_B;volatile unsigned int NAND_CE1_B;volatile unsigned int NAND_CLE;volatile unsigned int NAND_DQS;volatile unsigned int SD1_CMD;volatile unsigned int SD1_CLK;volatile unsigned int SD1_DATA0;volatile unsigned int SD1_DATA1;volatile unsigned int SD1_DATA2;volatile unsigned int SD1_DATA3;volatile unsigned int CSI_MCLK;volatile unsigned int CSI_PIXCLK;volatile unsigned int CSI_VSYNC;volatile unsigned int CSI_HSYNC;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;volatile unsigned int GRP_ADDDS;volatile unsigned int GRP_DDRMODE_CTL;volatile unsigned int GRP_B0DS;volatile unsigned int GRP_DDRPK;volatile unsigned int GRP_CTLDS;volatile unsigned int GRP_B1DS;volatile unsigned int GRP_DDRHYS;volatile unsigned int GRP_DDRPKE;volatile unsigned int GRP_DDRMODE;volatile unsigned int GRP_DDR_TYPE;
}IOMUX_SW_PAD_Type;/* * GPIO寄存器结构体*/
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 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)

在编写寄存器组结构体的时候注意寄存器的地址是否连续,有些外设的寄存器地址可能不是连续的,会有一些保留地址,因此我们需要在结构体中留出这些保留的寄存器

比如 CCM 的CCGR6 寄存器地址为 0X020C4080,而寄存器 CMEOR 的地址为 0X020C4088。按照地址顺序递增的原理,寄存器 CMEOR 的地址应该是 0X020C4084,但是实际上 CMEOR 的地址是0X020C4088,相当于中间跳过了 0X020C4088-0X020C4080=8 个字节,如果寄存器地址连续的话应该只差 4 个字节(32 位),但是现在差了 8 个字节,所以需要在寄存器 CCGR6 和 CMEOR直接加入一个保留寄存器,这就是第 47 行 RESERVED_3[1]的来源。如果不添加保留为来占位的话就会导致寄存器地址错位!

这里是引用

2.main.c

#include "imx6ul.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;}/*初始化LED灯*/
void led_init(void)
{IOMUX_SW_MUX->GPIO1_IO03=0x5; /*1.复用为GPIO1--IO03 *//* 2、配置 GPIO1_IO03 的 IO 属性*bit 16:0 HYS 关闭*bit [15:14]: 00 默认下拉*bit [13]: 0 kepper 功能*bit [12]: 1 pull/keeper 使能*bit [11]: 0 关闭开路输出*bit [7:6]: 10 速度 100Mhz*bit [5:3]: 110 R0/6 驱动能力*bit [0]: 0 低转换率*/IOMUX_SW_PAD->GPIO1_IO03=0x10B0;/*设置GPIO__IO03电器属性*//* 3、初始化 GPIO */GPIO1->GDIR=0x8;//设置为输出/* 4、设置 GPIO1_IO03 输出低电平,打开 LED0 */GPIO1->DR=0x0;}
/*短延时*/
void delay_short(volatile unsigned int n)
{while(n--){}}
/** 延时  一次循环大概是1ms 在主频396MHz* n:延时ms数
*/
void delay(volatile unsigned int n)
{while (n--){delay_short(0x7ff);}}
/*打开LED灯*/
void  led_on(void)
{GPIO1->DR&= ~(1<<3); //bit3清零}
/*关闭LED灯*/
void led_off(void )
{GPIO1->DR |= (1<<3);  //bit3置1
}
int main() 
{clk_enable();  //使能外设时钟led_init(); //初始化LEDwhile(1){led_off();  delay(500);led_on();delay(500);}return 0;
}

3.start.s

.global _start
.global _bss_start     /*相当于C语言定义宏  注意是一个杠 下面是两个杠*/
_bss_start:.word __bss_start  /*相当于C语言里面的变量,.word表示在这里放了一个变量,__bss_start就是这个变量的标签,类似变量名*/
.global _bss_end
_bss_end:.word __bss_end_start:/*设置处理器进入SVC模式 */mrs r0,cpsr      /*读取cpsr到r0 */bic r0,r0,#0x1f  /*清除cpsr的bit4--0 */orr r0,r0,#0x13  /*使用SVC模式 */msr cpsr,r0      /*将r0写入到cpsr中去 *//*清除bss段  bss段是定义但是没有初始化的变量,最好全部清零*/ldr r0, _bss_startldr r1, _bss_endmov r2, #0bss_loop:       /*循环 清除BSS段 */stmia r0!, {r2}/*移步指令 写数据0 地址自动加1*/cmp r0, r1     /*比较指令*/ble bss_loop   /*如果r0地址小于等于r1,跳转继续清除bss段*//*设置SP指针 */ldr sp,=0x80200000b main /*跳转到C语言main函数 */  

4.编译下载验证

1.编写链接脚本

将代码段、数据段等链接到指定的地址中去

SECTIONS
{. = 0x87800000;.text :{start.o*(.text)}.rodata ALIGN(4) : {*(.rodata*)}.data ALIGN(4) : {*(.data)}__bss_start = .;.bss ALIGN(4) : { *(.bss) *(COMMON)}__bss_end = .;
}

2.编写Makefile脚本

objs 	:= start.o main.o //类似于定义变量,后面就不用输入那么多的字母
gcc 	:=arm-linux-gnueabihf-gcc
ld		:=arm-linux-gnueabihf-ld
objcopy :=arm-linux-gnueabihf-objcopy
objdump :=arm-linux-gnueabihf-objdumpledc.bin : $(objs)$(ld) -Timx6ul.lds -o ledc.elf $^$(objcopy) -O binary -S ledc.elf $@$(objdump) -D -m arm ledc.elf > ledc.dis%.o : %.s$(gcc) -Wall -nostdlib -c -O2 -o $@ $<%.o : %.c$(gcc) -Wall -nostdlib -c -O2 -o $@ $<clean:rm -rf *.o ledc.elf ledc.bin ledc.dis

3.编译下载

使用 Make 命令编译代码,编译成功以后使用软件 imxdownload 将编译完成的 ledc.bin 文件下载到 SD 卡中,命令如下:

chmod 777 imxdownload //给予 imxdownload 可执行权限,一次即可./imxdownload ledc.bin /dev/sdd //烧写到 SD 卡中

烧写成功以后将 SD 卡插到开发板的 SD 卡槽中,然后复位开发板,如果代码运行正常的话 LED0 就会以 500ms 的时间间隔亮灭。

具体过程请参考前几篇博文

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

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

相关文章

ARM(IMX6U)裸机官方SDK包使用

参考&#xff1a;Linux之ARM&#xff08;IMX6U&#xff09;裸机C语言LED驱动实验–驱动编写,编译 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-08-11 11:20:17 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/107930284 目录1、I.MX6ULL 官…

Leaflet中添加的不同图层样式图标

如上图&#xff0c;具体问题请查看对应html页引用的basemaps的css样式。 如下图是本项目引用的css样式&#xff1a; .basemap img { width: 48px; border: 2px solid #FFF; margin: 0 2px; /*border-radius: 40px;*/ box-shadow: 0 1px 5px rgba(0,0,0,0.65)} 当css样式中的bor…

ARM(IMX6U)BSP工程文件管理(分文件编程)

参考&#xff1a;Linux之ARM&#xff08;IMX6U&#xff09;BSP工程管理实验 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-08-15 23:41:37 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/108028093 目录1、工程管理简介1.1、创建bsp、imx6…

php图片视频,PHP中使用php5-ffmpeg撷取视频图片实例

前几天在玩 FFmpeg 的时后&#xff0c;突然发现 Ubuntu 上多了 php5-ffmpeg 这个扩充套件&#xff0c;就想来玩玩看&#xff0c;看好不好用&#xff0c;有两个结论&#xff1a;读取影片取决于 FFmpeg 的支援性&#xff0c;如果想要什么格式都支援的话&#xff0c;建议自己重新编…

ARM(IMX6U)裸机C语言蜂鸣器驱动实验(BSP+SDK)

参考&#xff1a;Linux之ARM&#xff08;IMX6U&#xff09;裸机C语言蜂鸣器驱动实验–驱动编写,编译 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-08-16 14:47:23 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/108032168 目录1、有源蜂鸣…

java金字塔的流程图,R中的金字塔图

Plotrix可能更容易&#xff0c;但可以反汇编ggplot图表&#xff0c;并将它们排列为金字塔图 . 使用 eipi10的数据(谢谢)&#xff0c;并调整drawing-pyramid-plot-using-r-and-ggplot2中的代码&#xff0c;我为"males"&#xff0c;"females"和"country…

ARM(IMX6U)裸机按键输入实验(BSP+SDK、GPIO输入与输出、按键消抖)

参考&#xff1a;Linux之ARM&#xff08;IMX6U&#xff09;裸机按键输入实验&#xff08;GPIO的输出与输入&#xff09; 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-08-17 21:43:37 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/108057…

php 提取正文算法,PHP生成文章摘要算法_栈

之前网上复制了一个摘要算法&#xff0c;一直使用正常。最近写的一篇前500字里含有超链接&#xff0c;就导致摘要生成有误&#xff0c;从而影响了前端样式。所以后面打算自己写&#xff0c;想起大学编译原理匹配表达式的大致思想&#xff0c;就决定采用栈的思想试试。实现目标&…

设计模式 之 《组合模式》

GOOD&#xff1a;整体和部分可以被一致对待&#xff08;如WORD中复制一个文字、一段文字、一篇文章都是一样的操作&#xff09; #ifndef __COMPOSITE_MODEL__ #define __COMPOSITE_MODEL__ #include <iostream> #include <string> #include <vector> using n…

ARM(IMX6U)裸机主频和时钟

参考&#xff1a;Linux之ARM&#xff08;IMX6U&#xff09;裸机主频和时钟配置 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-08-28 10:39:17 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/108237599 目录1、I.MX6U 时钟系统详解系统时钟…

关联矩阵古林法的matlab代码,[转载][原创]灰色关联分析及Matlab程序实现

灰色系统理论由我国著名学者邓聚龙教授于1982提出。灰色关联分析是灰色系统理论的一个分支&#xff0c;应用灰色关联分析方法对受多种因素影响的事物和现象从整体观念出发进行综合评价是一个被广为接受的方法。一、灰色关联分析法的建模过程灰色关联分析法的基本思想是根据各比…

C语言排序(桶排序,冒泡排序,选择排序,插入排序,快速排序)

参考&#xff1a;C语言五大排序&#xff08;桶排序&#xff0c;冒泡排序&#xff0c;选择排序&#xff0c;插入排序&#xff0c;快速排序&#xff09;动态演示 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-09-09 20:18:43 网址&#xff1a;https://blog.csdn.net/we…

FIFO分枝_限界算法

问题&#xff1a; 检索4-皇后问题的状态空间树如下图的基本过程。&#xff08;4-皇后问题解空间的树结构&#xff0c;结点按深度优先检索编号&#xff09; 如果按序扩展这些结点&#xff0c;则下一个E-结点就是结点2。扩展结点2后生成结点3&#xff0c;8和13。利用限界函数(同行…

智能家居APP使用指南

参考&#xff1a;智能家居APP使用指南 作者&#xff1a;图触靓 发布时间&#xff1a; 2021-04-14 14:11:40 网址&#xff1a;https://blog.csdn.net/bhbhhyg/article/details/115694774 目录一、如何修改IP&#xff0c;端口号&#xff0c;以及发送的指令二、如何增加或者删除一…

python zlib字符串压缩

2019独角兽企业重金招聘Python工程师标准>>> 在做网络程序时,可以对字符串进行压缩来节省带宽 项目中用到 {"compress": <压缩标记>, "result":[[设备类型.设备ID, 设备名称, 单位ID, 设备功能], ...]} 只做了简单的压缩解压缩,也没crc3…

linux做一个客户端与WemosD1作为服务器的无线通信(局域网通信)

参考&#xff1a;linux做一个客户端与WemosD1作为服务器的无线通信&#xff08;局域网通信&#xff09; 作者&#xff1a;枕上 发布时间&#xff1a;2021-07-19 23:33:44 网址&#xff1a;https://blog.csdn.net/jinchi_boke/article/details/118916896?utm_sourceapp&app…

C语言学习书籍推荐《C语言程序设计 现代方法(第2版)》下载

下载地址&#xff1a;点我 C语言仍然是计算机领域的通用语言之一&#xff0c;但现在的C语言已经和当初的时候大不相同了。本书主要的一个目的就是通过一种“现代方法”来介绍C语言&#xff0c;书中强调标准C&#xff0c;强调软件工程&#xff0c;不再强调“手工优化”。这一版中…

wemosD1_WIFI模块 与 arduino

参考&#xff1a;wemosD1_WIFI模块 与 arduino 作者&#xff1a;枕上 发布时间&#xff1a;2021-07-19 21:49:55 网址&#xff1a;https://blog.csdn.net/jinchi_boke/article/details/118915142 目录作为设备接入wifi&#xff08;STA模式&#xff09;架设Wemos为ftp服务器ardu…

本机在合成图片经常提示内存不足

转载于:https://www.cnblogs.com/niyl/p/9988614.html

tp5 php7 报500,记一次TP单元测试报500错误的问题

记一次TP单元测试报500错误的问题一直听说好的单元测试能提高代码质量&#xff0c;昨天终于在下定决心弄懂单元测试&#xff0c;但第一步就把我干趴下了&#xff0c;我的问题在下面开始都没有什么问题&#xff0c;tp5单元测试的手册就那一点&#xff0c;通过看云上一位仁兄写的…