前言
本学习笔记仅自己学习过程中的记录,可交流学习,但请勿恶语相加。
NXP的i.MX 6ULL系列芯片是一款基于ARM Cortex A7内核的低功耗高性能且低成本的应用处理器,下面是imx6ull处理器的内部功能框图:
主要特性如下:
- ARM Cortex-A7内核可达900 MHz, 128 KB L2缓存。
- 并行24bit RGB LCD接口,可以支持1366*768分辨率。
- 8/10/16位 并行摄像头传感器接口(CSI)。
- 2个MMC 4.5/SD 3.0/SDIO 接口。
- 2个USB 2.0 OTG, HS/FS, Device or Host with PHY。
- 音频接口3x I2S/SAI, S/PDIF Tx/Rx。 2个IEEE802.3标准10/100Mbps以太网接口。
- 多达8个UART接口。
- 2个12-bit ADC最高支持10个输入通道,支持电阻触摸屏(4/5线)。
- 安全模块: TRNG, Crypto Engine(AES with DPA, TDES/SHA/RSA), Secure Boot。
官方链接
学习Linux之前先了解一下裸机编程,有助于后期对Linux驱动的理解,进行混合编程。
过程
下载手册:参考手册
学过STM32的人应该都知道,STM32的IO初始化的几个步骤:
- 使能GPIO时钟
- 设置GPIO复用为GPIO
- 设置GPIO属性
- 设置GPIO电平
而i.MX6ULL大概也是这么个步骤:
- 使能GPIO时钟:CCGR0~CCGR6这七个寄存器控制i.MX6ULL所有的外设时钟,具体设置哪个需要看参考手册,我这里是要控制gpio5_03,为了图方便,直接全设置使能。
- 设置IO复用:我的板子中LED连接的是SNVS_TAMPER3,到参考手册中找这个引脚的相关寄存器:IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3,注意,前面这一串里的MUX就是复用的意思,注意地址和使用的位。
- 设置GPIO属性,包括压摆率、速度、驱动能力、开漏、上下拉等。到参考手册中找到相应的寄存器:IOMUXC_SNVS_SW_PAD_CTL_PAD_SNVS_TAMPER3,这个和上面那个差不多,就只有高亮的部分有所区别。
- 配置GPIO功能,设置输入输出,找到GPIOx_GDIR寄存器,那个x就是GPIO号,比如我这儿是GPIO5,就是GPIO5_GDIR,每bit对应1个IO,我这里是GPIO5_IO03,所以是bit3,设置为1时为输出,此时GPIO的电平和GPIOx_DR寄存器的值一致
写代码
.text
.global _start
_start:
/**配置时钟*/
ldr r0, =020C4068H @CCM_CCGR0
ldr r1, =FFFFFFFFH
str r1, [r0] @将R1中的内容写入R0的地址
ldr r0, =020C406CH @CCM_CCGR1
str r1, [r0]
ldr r0, =020C4070H @CCM_CCGR2
str r1, [r0]
ldr r0, =020c4074H @CCM_CCGR3
str r1, [r0]
ldr r0, =020c4078H @CCM_CCGR4
str r1, [r0]
ldr r0, =020c407CH @CCM_CCGR5
str r1, [r0]
ldr r0, =020c4080H @CCM_CCGR6
str r1, [r0]
/**设置IO复用*/
ldr r0, =2290014H @配置GPIO5_IO03为GPIO,IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3
ldr r1, =5H
str r1, [r0]
/**配置电气属性,寄存器IOMUXC_SNVS_SW_PAD_CTL_PAD_SNVS_TAMPER3
* bit0:0低速率
* bit5:3: 110 R0/6驱动能力
* bit7:6: 10 100MHz
* bit11: 0关闭开漏输出
* bit12: 1使能pull/kepper
* bit13: 0kepper
* bit15:14: 00 100K下拉
* bit16: 0关闭HYS
*/
ldr r0, =2290058H
ldr r1, =10B0H
str r1, [r0]
/**设置GPIO 输入/输出*/
ldr r0, =20AC004H @设置GPIO5_GDIR
ldr r1, =8H
str r1, [r0]
/**打开LED,设置GPIO5_DR*/
ldr r0, =20AC000H @设置GPIO5_DR
ldr r1, =0H
str r1, [r0]
loop:
b loop
编译
- 使用arm-linux-gnueabihf-gcc工具编译,将.c .s编译为.o
- 将所有.o链接为.elf文件
- 将.elf文件编译为.bin文件
arm-linux-gnueabihf-gcc -g -c leds.s -o leds.o
gcc命令:参数-g产生调试信息,-c编译源文件,-o自定义目标文件
链接:链接就是将所有的.o链接到一起,并且链接到指定位置,本次实验需要指定起始地址。
对于i.MX6ULL来说,链接起始地址应该指向RAM地址。RAM分为内部RAM和外部RAM(DDR),i.MX6ULL的内部RAM地址范围0x00900000~0x0091FFFF ,对于外部DDR来说,起始地址都为0x80000000,我们使用Uboot使用的地址0x87800000作为起始地址。
要使用DDR,必须初始化DDR,对于i.MX来说bin不能直接运行,需要添加一个头部信息,这个头部信息包含了DDR的初始化参数,i.MX系列SOC内部boot ROM会从外置存储中读取头部信息,然后初始化DDR,并且将bin文件拷贝到指定位置。
bin文件的运行地址需要和链接地址一致。
arm-linux-gnueabihf-ld -Ttext 0x87800000 leds.o -o leds.elf
arm-linux-gnueabihf-objcopy -O binary -S -g leds.elf leds.bin
烧写
我这里使用正点原子的imxdownload程序烧录,指令为:
./imxdownload leds.bin /dev/sdc
偷懒
使用Makefile进行批处理
本记录记录于正点原子学习过程中。