Linux裸机开发|汇编点灯及启动方式介绍

一、汇编点灯

1. IMX6U IO介绍

IMX6ULL的IO分为两类:SNVS域和通用,这两类IO本质上是一样的。以IOMUXC_SW_MUC_CTL_PAD_GPIO1_IO01为例:后面的GPIO1_IO01就是GPIO命名
Linux裸机开发|汇编点灯及启动方式介绍_第1张图片

1.1 IO复用

SW_MUX_CTL寄存器是用来配置IO复用功能的

Linux裸机开发|汇编点灯及启动方式介绍_第2张图片

  • MUX_MODE(bit0~bit3):用来设置GPIO1_IO00的复用功能
1.2 IO配置

SW_PAD_CTL寄存器是用来配置IO口参数的

Linux裸机开发|汇编点灯及启动方式介绍_第3张图片

  • HYS:使能或禁止迟滞比较器
  • PUS:设置上下拉电阻
  • PUE:设置IO使用上下拉还是状态保持器(IO作为输入)
  • PKE:使能或禁止上下拉/状态保持器功能
  • ODE:使能或禁止开路输出(IO作为输出)
  • SPEED:设置IO速度(IO作为输出)
  • DSE:设置IO的驱动能力(IO作为输出)
  • SRE:设置压摆率
1.3 GPIO配置

上面两种类型的寄存器是配置IO的,不是GPIO,GPIO是IO口众多复用功能中的一种。如果我们要使用GPIO来点灯或作为按键输入功能,在将IO复用为GPIO之后,还需要对GPIO的功能进行配置

GPIO结构图如下示
Linux裸机开发|汇编点灯及启动方式介绍_第4张图片
由上图可以看出使用GPIO功能,除了配置IO复用和IO属性寄存器外,还需要设置DRGDIRPSRICR1ICR2EDGE_SELIMRISR这八个寄存器

  • GPIOx_DR 数据寄存器:一个GPIO组最大只有32个IO,DR寄存器中的每一个位对应一个GPIO
    Linux裸机开发|汇编点灯及启动方式介绍_第5张图片

当设置为输出模式,向指定的位写入数据,相应的IO就会输出相应的高低电平
当设置为输入模式,比如GPIO1_IO00引脚接地的话,GPIO1.DR的bit0就是0

  • GPIOx_GDIR 方向寄存器:设置IO的工作方向是输入还是输出,每个位对应一个IO
    Linux裸机开发|汇编点灯及启动方式介绍_第6张图片

若要设置GPIO1_IO00为输入,则GPIO1.GDIR = 0;反之GPIO1.GDIR = 1

  • GPIOx_PSR 状态寄存器:一个位对应一个GPIO,用于获取对应的GPIO的状态(高低电平)
    Linux裸机开发|汇编点灯及启动方式介绍_第7张图片

功能类似于输入状态下的DR寄存器

  • GPIOx_ICR1GPIOx_ICR2 中断控制寄存器:每两位对应一个GPIO
    Linux裸机开发|汇编点灯及启动方式介绍_第8张图片

例如设置GPIO1_IO15为上升沿触发中断,则GPIO1.ICR1 = 2 << 30

  • GPIOx_EDGE_SEL
    Linux裸机开发|汇编点灯及启动方式介绍_第9张图片

  • GPIOx_IMR 中断屏蔽寄存器:一个位对应一个GPIO,用于控制GPIO的中断使能和禁止
    Linux裸机开发|汇编点灯及启动方式介绍_第10张图片

例如要使能GPIO1_IO00的中断,则GPIO1.MIR = 1

  • GPIOx_ISR 中断状态寄存器:一个位对应一个GPIO,只要某个GPIO的中断发生,ISR中相应的位会被置1
    Linux裸机开发|汇编点灯及启动方式介绍_第11张图片

可通过读取ISR寄存器来判断GPIO中断是否发生,这些位相当于中断标志位
处理完中断后,必须清除中断标志位

1.4 时钟使能

IMX6U的每个外设的时钟都可以独立的使能或禁止,这样可以关闭掉不使用的外设时钟,起到省电的目的。CCM有CCM_CCGR0~CCM_CCGR6这7个外设时钟使能寄存器,这7个寄存器控制着IMX6U的所有外设时钟开关

以CCM_CCGR0为例,其结构体如下图示:
Linux裸机开发|汇编点灯及启动方式介绍_第12张图片
CCM_CCGR0是个32位寄存器,每2位控制一个外设时钟,两个位就有四种操作方式
Linux裸机开发|汇编点灯及启动方式介绍_第13张图片

例如打开GPIO2的外设时钟,设置CCM_CCGR0 = 3<<30 即可

1.5 GPIO的使用步骤

IMX6U的IO最为GPIO使用,需要进行以下几个步骤:

  • 使能GPIO对应的时钟
  • 配置SW_MUX_CTL寄存器,设置对应的IO复用功能
  • 配置SW_PAD_CTL寄存器,设置相关的IO参数
  • 若复用为GPIO功能,则需要设置输入/输出、是否使用中断以及默认输出电平等

2. 硬件设计

LED0的原理图如下示:
Linux裸机开发|汇编点灯及启动方式介绍_第14张图片

开发板LED0接到了GPIO_3上,且上拉到3.3V上,因此GPIO输出高电平时,LED0不会被点亮,输出低电平时,LED0被点亮

3. 软件设计

要使用GPIO1_IO03,需按如下步骤进行配置

使能GPIO时钟
设置复用功能
配置IO参数
设置GPIO
/***汇编文件led.s***/
.global _start  /* 全局标号 */

/*_start函数,程序从此函数开始执行 */
_start:
	/* 1、使能所有时钟 */
	ldr r0, =0X020C4068 	/* CCGR0 */
	ldr r1, =0XFFFFFFFF  
	str r1, [r0]		
	
	ldr r0, =0X020C406C  	/* CCGR1 */
	str r1, [r0]

	ldr r0, =0X020C4070  	/* CCGR2 */
	str r1, [r0]
	
	ldr r0, =0X020C4074  	/* CCGR3 */
	str r1, [r0]
	
	ldr r0, =0X020C4078  	/* CCGR4 */
	str r1, [r0]
	
	ldr r0, =0X020C407C  	/* CCGR5 */
	str r1, [r0]
	
	ldr r0, =0X020C4080  	/* CCGR6 */
	str r1, [r0]
	/* 2、设置GPIO1_IO03复用为GPIO1_IO03 */
	ldr r0, =0X020E0068	/* 将寄存器SW_MUX_GPIO1_IO03_BASE加载到r0中 */
	ldr r1, =0X5		/* 设置寄存器SW_MUX_GPIO1_IO03_BASE的MUX_MODE为5 */
	str r1,[r0]

	/* 3、配置GPIO1_IO03的IO属性	*/
    ldr r0, =0X020E02F4	/*寄存器SW_PAD_GPIO1_IO03_BASE */
    ldr r1, =0X10B0
    str r1,[r0]

	/* 4、设置GPIO1_IO03为输出 */
    ldr r0, =0X0209C004	/*寄存器GPIO1_GDIR */
    ldr r1, =0X0000008		
    str r1,[r0]

	/* 5、打开LED0,设置GPIO1_IO03输出低电平 */
	ldr r0, =0X0209C000	/*寄存器GPIO1_DR */
    ldr r1, =0		
    str r1,[r0]
/* loop死循环 */
loop:
	b loop 				

4. 下载验证

4.1 代码编译
  • arm-linux-gnueabihf-gcc 编译文件
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
//-g 产生调试信息
//-c 编译源文件,但是不链接
//-o 指定编译产生的文件名字
  • arm-linux-gnueabihf-ld 链接文件
arm-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf
//-Ttext 指定链接地址
//-o	 指定链接生成的elf文件名
//用于将.o文件链接到一个指定的链接位置
  • arm-linux-gnueabihf-objcopy 格式转换
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
//-O 指定输出格式,binary表示以二进制格式输出
//-S 不要复制源文件中的重定位和符号信息
//-g 不复制源文件中的调试信息
//用于将.elf文件转换为.bin文件
  • arm-linux-gnueabihf-objdump 反汇编
arm-linux-gnueabihf-objdump -D led.elf > led.dis
//-D 表示反汇编所有的段
//用于将.elf文件反汇编,并生成.dis文件

使用makefile方式进行编译

led.bin:led.s
	arm-linux-gnueabihf-gcc -g -c led.s -o led.o
	arm-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf
	arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
	arm-linux-gnueabihf-objdump -D led.elf > led.dis
clean:
	rm -rf *.o led.bin led.elf led.dis
4.2 代码烧写
  • 将imxdownload(正点原子编写的用来将编译出来的.bin文件烧写到SD卡的软件)拷贝到工程根目录下
  • 赋予imxdownload可执行权限
chmod 777 imxdownload
  • 确定要烧写的SD卡
ls /dev/sd*   #查看当前电脑的存储文件
  • 向SD卡烧写bin文件
./imxdownload led.bin /dev/sdcard
//烧写完成后会生成一个load.imx文件
//该文件是imxdownload在.bin文件前面添加一些数据后生成的
//最终烧写到SD卡里面的就是这个文件
4.3 代码验证

代码烧写到SD卡后,将SD卡插到开发板卡槽中,设置拨码开关为SD卡启动,启动后如果代码运行正常的话LED0会被点亮

二、启动方式介绍

1. 启动方式

正点原子阿尔法开发板的拨码开关如下图所示,不同的拨码位置表示不同的启动方式:
Linux裸机开发|汇编点灯及启动方式介绍_第15张图片

  • 01xxxxxx 串行下载,可通过USB烧写镜像文件

  • 10000010 SD卡启动

  • 10100110 EMMC启动

  • 10001001 NAND FLASH启动

2. 镜像烧写

IMX6U不能直接烧写编译生成的BIN文件,需要在BIN文件前面添加一些头信息构成最终可烧写文件,该文件组成如下:

  • IVT(Image Vector Table):图像矢量表,包含一系列的地址信息,这些地址信息在ROM中按固定的地址存放

IVT包含了镜像程序的入口点、指向DCD的指针和一些其他用途的指针。IVT要求laod.imx在烧写的时候放到指定的位置,不同的启动设备位置不同,整个位置都是相对于存储设备的起始地址的偏移

  • Boot Data:启动数据,包含镜像要拷贝到哪个地址,拷贝的大小是多少等

Boot Data包含了整个load.imx的起始地址、镜像大小等

  • DCD(Device Configuration Data):设备配置信息,重点是DDR3的初始化配置

芯片复位后所有的寄存器都会复位为默认值,但往往这些值不是我们需要的值,并且有的外设必须要在使用之前初始化(比如时钟、初始化DDR等)。DCD就是寄存器地址和对应的配置集合,Boot ROM会使用这个集合来初始化相应的寄存器

  • 用户代码可执行文件,bin文件

因此使用 imxdownload 将编译出来的.bin文件烧写到SD卡里的load.imx文件,其实就是 IVT + Boot data + DCD + .bin 组成的

你可能感兴趣的:(Linux裸机开发,linux,物联网,IMX6U)