Linux裸机开发|C语言点灯(定义寄存器组结构体)

2023-05-16

C语言点灯

通过逐个定义寄存器地址的方法来编写外设驱动,非常的不方便。本文将介绍如何使用结构体来定义外设寄存器

1. IMX6U寄存器定义

模仿STM32的寄存器定义来编写IMX6U的寄存器定义,分三步:

  • 编写外设结构体
//将同属于一个外设的所有寄存器编写到一个结构体中
//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 	GPIO1_BASE		(0x0209C000)
  • 定义访问指针
#define 	GPIO1			((GPIO_Type *)GPIO1_BASE)

2. 硬件设计

硬件设计与汇编点灯实例相同

3. 软件设计

3.1 汇编部分
  • 创建汇编文件start.S,用来完成C语言环境搭建
/***** start.S *****/
.global _start	//全局标号
_start:
	mrs r0, cpsr			//进入SVC模式
	bic r0, r0, #0x1f		//将r0的低5位清零
	orr r0, r0, #0x13		//r0或0x13,表示使用SVC模式
	msr cpsr, r0			//将r0的数据写入到cpsr_c中
	
	ldr sp, = 0x80200000	//设置栈指针
	b main					//跳转到mian函数
3.2 C语言部分
  • 创建imx6ul.h文件,用来定义IMX6UL相关寄存器
/* 外设寄存器组的基地址 */
#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 CCGR6;
	volatile unsigned int RESERVED_3[1];
	volatile unsigned int CMEOR;	
} CCM_Type; 
/* IOMUX寄存器组 */
typedef struct{
	volatile unsigned int BOOT_MODE0;
	volatile unsigned int BOOT_MODE1;
	volatile unsigned int SNVS_TAMPER0;
	......
	......
	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 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)
  • 创建main.c文件
/*****main.c*****/
#include "imx6ul.h"
//使能I.MX6U所有外设时钟
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对应的GPIO
void led_init(void){
	/* 1、初始化IO复用 */
	IOMUX_SW_MUX->GPIO1_IO03 = 0x5;	/* 复用为GPIO1_IO03 */
	/* 2、配置GPIO1_IO03的IO属性*/
	IOMUX_SW_PAD->GPIO1_IO03 = 0X10B0;		
	/* 3、初始化GPIO */
	GPIO1->GDIR = 0X0000008;	/* GPIO1_IO03设置为输出 */
	/* 4、设置GPIO1_IO03输出低电平,打开LED0 */
	GPIO1->DR &= ~(1 << 3);
}
//打开LED灯
void led_on(void){
	GPIO1->DR &= ~(1<<3);  //将GPIO1_DR的bit3清零
}
//关闭LED灯
void led_off(void){
	GPIO1->DR |= (1<<3);	 //将GPIO1_DR的bit3置1
}
//短时间延时函数
void delay_short(volatile unsigned int n){
	while(n--){}
}
//延时函数,在396Mhz的主频下
void delay(volatile unsigned int n){
	while(n--){
		delay_short(0x7ff);
	}
}
//mian函数
int main(void){
	clk_enable();		/* 使能所有的时钟		*/
	led_init();			/* 初始化led 			*/
	while(1)			/* 死循环 				*/
	{	
		led_off();		/* 关闭LED   			*/
		delay(500);		/* 延时大约500ms 		*/
		led_on();		/* 打开LED		 		*/
		delay(500);		/* 延时大约500ms 		*/
	}
	return 0;
}

4. 下载验证

4.1 编写Makefile和链接脚本

Makefile和链接脚本与C语言点灯(逐个定义寄存器地址)实例相同

4.2 代码验证
  • 将imxdownload拷贝到工程根目录下
  • 赋予imxdownload可执行权限
chmod 777 imxdownload
  • 确定要烧写的SD卡
ls /dev/sd*   #查看当前电脑的存储文件
  • 向SD卡烧写bin文件
./imxdownload ledc.bin /dev/sdcard
  • 烧写成功后,复位开发板,若代码正常,LED0会以500ms的时间间隔亮灭
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux裸机开发|C语言点灯(定义寄存器组结构体) 的相关文章

随机推荐