IMX6ULL裸机学习(5)— 编写C语言程序点亮LED
一、前言
使用c语言时,要用到的一个很重要的就是栈,所以我们要在汇编中就设置好栈;
二、编写汇编代码
编写start.s如下所示:
.text /* .text段保存代码,是只读和可执行的,后面的指令都属于.text段。 */
.global _start /* .global表示_start是一个全局符号,会在链接器链接时用到 */
_start: /* 标签_start,汇编程序的默认入口是_start */
/* 1、设置栈 */
ldr sp, =(0x80000000+0x100000) /* 设置栈顶地址 */
/* 2、跳转到led函数 */
bl led
/* 3、原地循环 */
b .
三、编写C文件
新建led.c
文件,编写代码如下所示
int delay(int ndelay)
{
volatile int n = ndelay;
while(n--);
return 0;
}
int led(void)
{
volatile unsigned int *pReg;
/* 1、设置 GPIO1_IO03 复用为 GPIO1_IO03 */
pReg = (unsigned int *)(0x020e0000 + 0x68);
*pReg |= (0x05);
/* 2、设置GPIO1_IO03 为输出引脚 */
pReg = (unsigned int *)(0x0209c000 + 0x04);
*pReg |= (1<<3);
pReg = (unsigned int *)(0x0209c000);
while (1)
{
/* 3、设置GPIO1_IO03输出1 */
*pReg |= (1<<3);
delay(1000000);
/* 4、设置GPIO1_IO03输出0 */
*pReg &= ~(1<<3);
delay(1000000);
}
}
四、修改Makefile
修改Makefile如下,
PREFIX=arm-linux-gnueabihf-
CC=$(PREFIX)gcc
LD=$(PREFIX)ld
AR=$(PREFIX)ar
OBJCOPY=$(PREFIX)objcopy
OBJDUMP=$(PREFIX)objdump
led.img : start.s led.c
$(CC) -nostdlib -c -g start.s -o start.o
$(CC) -nostdlib -c -g led.c -o led.o
$(LD) -g start.o led.o -Ttext 0X80100000 -o led.elf
$(OBJCOPY) led.elf -O binary -S led.bin
$(OBJDUMP) -D -m arm led.elf > led.dis
mkimage -T imximage -n ./tools/imximage.cfg.cfgtmp -e 0x80100000 -d led.bin led.imx
dd if=/dev/zero of=1k.bin bs=1024 count=1
cat 1k.bin led.imx > led.img
clean:
rm -rf *.o led.bin led.elf led.dis led.imx led.img
使用make执行后如下
编译烧录后可以看到LED闪烁
五、优化
修改led.c
文件如下所示
int delay(int ndelay)
{
volatile int n = ndelay;
while(n--);
return 0;
}
int led_init(void)
{
volatile unsigned int *pReg;
/* 1、设置 GPIO1_IO03 复用为 GPIO1_IO03 */
pReg = (unsigned int *)(0x020e0000 + 0x68);
*pReg |= (0x05);
/* 2、设置GPIO1_IO03 为输出引脚 */
pReg = (unsigned int *)(0x0209c000 + 0x04);
*pReg |= (1<<3);
}
void led_on(void)
{
volatile unsigned int *pReg;
pReg = (unsigned int *)(0x0209c000);
*pReg &= ~(1<<3); /* 设置GPIO1_IO03输出0 */
}
void led_off(void)
{
volatile unsigned int *pReg;
pReg = (unsigned int *)(0x0209c000);
*pReg |= (1<<3); /* 设置GPIO1_IO03输出1 */
}
新建led.h
文件如下
#ifndef __LED_H
#define __LED_H
int delay(int ndelay);
int led_init(void);
void led_on(void);
void led_off(void);
#endif
新建main.c
如下所示
#include "led.h"
int main(void)
{
led_init();
while(1)
{
led_on();
delay(1000000);
led_off();
delay(1000000);
}
}
修改Makefile
如下所示
PREFIX=arm-linux-gnueabihf-
CC=$(PREFIX)gcc
LD=$(PREFIX)ld
AR=$(PREFIX)ar
OBJCOPY=$(PREFIX)objcopy
OBJDUMP=$(PREFIX)objdump
led.img : start.s led.c main.c
$(CC) -nostdlib -c -g start.s -o start.o
$(CC) -nostdlib -c -g led.c -o led.o
$(CC) -nostdlib -c -g main.c -o main.o
$(LD) -g start.o led.o main.o -Ttext 0X80100000 -o led.elf
$(OBJCOPY) led.elf -O binary -S led.bin
$(OBJDUMP) -D -m arm led.elf > led.dis
mkimage -T imximage -n ./tools/imximage.cfg.cfgtmp -e 0x80100000 -d led.bin led.imx
dd if=/dev/zero of=1k.bin bs=1024 count=1
cat 1k.bin led.imx > led.img
clean:
rm -rf *.o led.bin led.elf led.dis led.imx led.img
修改start.s
如下所示
.text /* .text段保存代码,是只读和可执行的,后面的指令都属于.text段。 */
.global _start /* .global表示_start是一个全局符号,会在链接器链接时用到 */
_start: /* 标签_start,汇编程序的默认入口是_start */
/* 1、设置栈 */
ldr sp, =(0x80000000+0x100000) /* 设置栈顶地址 */
/* 2、跳转到led函数 */
bl main
/* 3、原地循环 */
b .
然后编译链接烧录,可以看到led闪烁
六、附录
上一篇:IMX6ULL裸机学习(4)— 编写汇编程序点亮LED
下一篇:IMX6ULL裸机学习(6)— 编写uart串口打印程序
代码存放:https://gitee.com/william_william/imx6ull_noos/tree/master/01_led