I.MX6U点亮第一个LED灯
一、编写源码
创建~/imx6ull/project/ledc/
文件存放工程代码
mkdir ledc
-
创建start.S汇编启动文件
touch start.S
编写启动文件
/**************************************************************************** 文件名 : start.s 描述 : 开发板启动文件,完成C环境初始化, C环境初始化完成以后跳转到C代码。 ****************************************************************************/ .global _start /* 全局标号 */ /* * 描述: _start函数,程序从此函数开始执行,此函数主要功能是设置C * 运行环境。 */ _start: /* 进入SVC模式 */ mrs r0, cpsr bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */ orr r0, r0, #0x13 /* r0或上0x13,表示使用SVC模式 */ msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中 */ /* 设置栈指针, * 注意:IMX6UL的堆栈是向下增长的! * 堆栈指针地址一定要是4字节地址对齐的!!! * DDR范围:0X80000000~0X9FFFFFFF */ ldr sp,=0X80200000 /* 设置用户模式下的栈首地址为0X80200000,大小为2MB*/ b main /* 跳转到main函数 */
-
然后创建LED驱动文件
touch led.c
编写LED驱动文件
/************************************************************** 文件名 : led.c 描述 : C语言点灯 使用C语言来点亮开发板上的LED灯,学习和掌握如何用C语言来 完成对I.MX6U处理器的GPIO初始化和控制。 **************************************************************/ #include "led.h" /* * @description : 使能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; } /* * @description : 初始化LED对应的GPIO */ void led_init(void) { /* 1、初始化IO复用 */ SW_MUX_GPIO1_IO03 = 0x5; /* 复用为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 低转换率 */ SW_PAD_GPIO1_IO03 = 0X10B0; /* 3、初始化GPIO */ GPIO1_GDIR = 0X0000008; /* GPIO1_IO03设置为输出 */ /* 4、设置GPIO1_IO03输出低电平,打开LED0 */ GPIO1_DR = 0X0; } /* * @description : 打开LED灯 */ void led_on(void) { /* * 将GPIO1_DR的bit3清零 */ GPIO1_DR &= ~(1<<3); } /* * @description : 关闭LED灯 */ void led_off(void) { /* * 将GPIO1_DR的bit3置1 */ GPIO1_DR |= (1<<3); } /* * @description : 短时间延时函数 * @param - n : 要延时循环次数(空操作循环次数,模式延时) * @return : 无 */ void delay_short(volatile unsigned int n) { while(n--){} } /* * @description : 延时函数,在396Mhz的主频下 * 延时时间大约为1ms * @param - n : 要延时的ms数 * @return : 无 */ void delay(volatile unsigned int n) { while(n--) { delay_short(0x7ff); } }
相对应的,创建头文件
touch led.h
编写头文件
#ifndef __LED_H #define __LED_H /* * 时钟GPIO1_IO03相关寄存器地址定义。 */ /* * CCM相关寄存器地址 */ #define CCM_CCGR0 *((volatile unsigned int *)0X020C4068) #define CCM_CCGR1 *((volatile unsigned int *)0X020C406C) #define CCM_CCGR2 *((volatile unsigned int *)0X020C4070) #define CCM_CCGR3 *((volatile unsigned int *)0X020C4074) #define CCM_CCGR4 *((volatile unsigned int *)0X020C4078) #define CCM_CCGR5 *((volatile unsigned int *)0X020C407C) #define CCM_CCGR6 *((volatile unsigned int *)0X020C4080) /* * IOMUX相关寄存器地址 */ #define SW_MUX_GPIO1_IO03 *((volatile unsigned int *)0X020E0068) #define SW_PAD_GPIO1_IO03 *((volatile unsigned int *)0X020E02F4) /* * GPIO1相关寄存器地址 */ #define GPIO1_DR *((volatile unsigned int *)0X0209C000) #define GPIO1_GDIR *((volatile unsigned int *)0X0209C004) #define GPIO1_PSR *((volatile unsigned int *)0X0209C008) #define GPIO1_ICR1 *((volatile unsigned int *)0X0209C00C) #define GPIO1_ICR2 *((volatile unsigned int *)0X0209C010) #define GPIO1_IMR *((volatile unsigned int *)0X0209C014) #define GPIO1_ISR *((volatile unsigned int *)0X0209C018) #define GPIO1_EDGE_SEL *((volatile unsigned int *)0X0209C01C) void clk_enable(void); //使能I.MX6U所有外设时钟 void led_init(void); //初始化LED对应的GPIO void led_on(void); //打开LED灯 void led_off(void); //关闭LED灯 void delay(volatile unsigned int n);//ms级延时函数,在396Mhz的主频下,延时时间大约为1ms #endif
-
然后编写主程序
touch main.c
#include "led.h" int main(void) { clk_enable(); /* 时钟使能 */ led_init(); /* 初始化led */ while(1) /* 死循环 */ { led_off(); /* 关闭LED */ delay(500); /* 延时大约500ms */ led_on(); /* 打开LED */ delay(500); /* 延时大约500ms */ } return 0; }
-
然后编写连接脚本文件
touch imx6ul.lds
SECTIONS{ . = 0X87800000; .text : { start.o main.o *(.text) } .rodata ALIGN(4) : {*(.rodata*)} .data ALIGN(4) : { *(.data) } __bss_start = .; .bss ALIGN(4) : { *(.bss) *(COMMON) } __bss_end = .; }
-
然后编写Makefile文件
touch Makefile
objs := start.o main.o ledc.bin:$(objs) arm-linux-gnueabihf-ld -Timx6ul.lds -o ledc.elf $^ arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@ arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis %.o:%.s arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $< %.o:%.S arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $< %.o:%.c arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $< clean: rm -rf *.o ledc.bin ledc.elf ledc.dis
二、生成工程
代码编写完成后,使用make
命令对工程进行编译链接
可以看到,生成了ledc.bin
三、烧录工程
将imxdownload
文件复制到工程目录下
并修改其权限chmod 777 imxdownload
然后使用ls /dev/sd*
命令找到sd卡
通过插入SD卡前后的对比,可以看到我们要使用的SD卡为sdb
然后用imxdownlord将ledc.bin烧写到sd卡中
./imxdownload ledc.bin /dev/sdb
烧写后可看到
要注意其烧写速度,如果烧写速度大于几十MB/s,那么就是烧写失败了,可以尝试重启Ubuntu系统。
另外可以看到,烧写完后再当前目录下会生成一个load.imx
的文件,这个文件是软件imxdownlord根据NXP官方启动方式,再ledc.bin文件前面添加了一些数据头生成的,最终写到SD卡里的也是这个load.imx文件。
四、开发板启动
将SD卡插到开发板的SD卡槽中,并设置拨码开关为SD卡启动
然后上电可以看到LED闪烁