在STM32中,厂家通常提供好了start_up.s文件来完成芯片的上电配置,C语言运行环境初始化。而MPU厂商不一般不会提供。
使用MPU外设的基本步骤:
- 需要使用汇编来初始化SOC 外设;
- 需要使用汇编初始化DDR内存(i.MX6ull不需要);
- 设置SP指针,一般是指向DDR内存中的地址,为C语言提供运行环境。
点亮LED(使用GPIO)基本步骤:
使能时钟: CCGR0-CCGR7寄存器控制所有外设的时钟使能。
配置IO复用寄存器:IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03;将Bit[3:0]设置为0101。
配置电气属性:上下拉,压摆率,速度,开漏推挽,驱动能力…需要配置(IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00)寄存器
配置GPIO属性:输入或输出等:GPIO direction register (GPIOx_GDIR)寄存器bit置1,配置为输出模式。GPIO data register (GPIOx_DR)bit3写入0或1,使其输出高低电平。
汇编代码编写:
汇编的基本语法:
label:
instruction @comment
label代表标号也是程序的地址,instruction 是具体指令操作,comment是注释内容。
add:
MOVS R0,#0x12 @给R0寄存器赋值0x12
汇编程序的默认入口是_start:相当于C中的main()函数,也可以在链接脚本中使用ENTRY手动指定程序入口点。
在程序中ARM内核可以直接读写R0-R15通用寄存器,但无法直接读写RAM中的数据,需要使用LDR,STR指令,
举例:读写0x20000000地址的数据:
LDR R0,=0x20000000 @把32bit地址数据0x20000000加载到R0寄存器中
LDR R1,[R0] @读取0x20000000地址的数据保存在R1寄存器中
LDR R1,=0xAAAA5555 @把数据0xAAAA5555加载到R1寄存器中
STR R1,[R0] @把0xAAAA5555保存到0x20000000地址中
编写代码点亮一个LED灯:
根据原理图,LED0阴极连接到I.MX6ULL芯片的GPIO3管脚,要点亮LED,则需要GPIO3推挽输出低电平。
.global _start @.global是伪操作,表示_start是一个全局标号,类似C语言中的全局变量
_start:
LDR R0, =0x20c4068 @CCGR0的寄存器地址
LDR R1, =0xffffffff
STR R1, [R0] @CCGR0寄存器写入0xffffffff
LDR R0, = 0X020C406C
STR R1, [R0] @CCGR1寄存器写入0xffffffff
LDR R0, = 0X020C4070
STR R1, [R0] @CCGR2寄存器写入0xffffffff
LDR R0, = 0X020C4074
STR R1, [R0] @CCGR3寄存器写入0xffffffff
LDR R0, = 0X020C4078
STR R1, [R0] @CCGR4寄存器写入0xffffffff
LDR R0, = 0X020C407C
STR R1, [R0] @CCGR5寄存器写入0xffffffff
LDR R0, = 0X020C4080
STR R1, [R0] @CCGR6寄存器写入0xffffffff
@完成时钟使能
@设置GPIO3的复用功能
LDR R0, = 0X020E0068 @IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03寄存器的地址
LDR R1, = 0X5
STR R1, [R0] @ALT5 — Select mux mode: ALT5 mux port: GPIO1_IO03 of instance: gpio1
@配置电气属性
LDR R0, = 0X020E02F4 @IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03寄存器的地址
@BIT0->0 设置低压摆速率
@BIT[5:3]->110 设置R0/6的驱动能力
@BIT[7:6]->10 设置100MHz速度
@BIT11->0 关闭开漏输出
@BIT12->1 使能pull/kepper
@BIT[15:14]->00 设置100k下拉
@BIT16->0 关闭HYS
LDR R1, = 0X10B0
STR R1, [R0]
@设置GPIO的GDIR寄存器和DR寄存器
LDR R0, = 0X0209C004 @GDIR寄存器的地址
LDR R1, = 0X8
STR R1, [R0] @GDIR寄存器bit3配置为1
LDR R0, =0X0209C000 @DR寄存器地址
LDR R1, =0
STR R1, [R0]
loop:
b loop @让程序进入循环
编译链接转换:
程序的编译步骤一般为: .c .s源代码编译为.o;.o链接为.elf可执行文件。对上述代码进行编译链接:
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
接下来将.o文件链接为elf可执行程序,注意:在链接时,需要指定链接的起始地址,链接的起始地址就是代码运行的起始地址。
对于MPU,一般要将链接起始地址指向RAM空间(内部RAM和外部DDR内存空间皆可)。若要使用外部DDR空间,则需要添加头部,IMX6ULL芯片根据头部中的信息初始化DDR存储器。
IMX6ULL在上电后会运行芯片内部的Boot ROM程序,从SD卡,EMMC等外部设备读取头部信息,再进行DDR初始化。之后再将bin文件拷贝到指定地址。
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
其中-Ttext参数指定的是链接地址。
将.elf转换为.bin文件:
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
烧写运行
将.bin文件烧录到SD卡而不是拷贝到SD卡,烧录过程中,程序被写入到SD卡的绝对地址上。此外还需要借助imxdownload工具添加头部。
将工具拷贝到工程目录下,发现只有RW权限,没有'X'执行权限,因此需要输入:
chmod 777 imxdownload
插入一张16GB SD卡,使用lsblk命令可知SD卡的设备名称是sdb,由于linux中存储设备都是以“/dev/sd”开头的,也可以使用ls /dev/sd*命令查找。
使用 imxdownload 向 SD 卡烧写 led.bin 文件,命令格式为:
./imxdownload <.bin file> <SD Card>
此处的指令为:
./imxdownload led.bin /dev/sdb
将开发板配置为SD卡启动:
插入SD卡,上电启动:
Comments | NOTHING
Warning: Undefined variable $return_smiles in /www/wwwroot/ogisosetsuna/wp-content/themes/Sakura/functions.php on line 1096