Linux学习笔记(6)——C语言点灯程序

  1. start.s
/*
 * 文件名: start.s
 * 描述  : i.mx6u-alpha开发板启动文件, 完成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中 */

    ldr sp, =0x80200000         /* 设置栈指针 */
    b main                      /* 跳转到main函数 */
  1. 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 = .;
}
  1. main.c
在这里插入代/*
 * 文件名   : main.c 
 * 描述     : i.mx6u C语言点亮LED程序
 */

#include "main.h"

/**
 * @brief   : 使能I.MX6U所有外设时钟
 * @para    : none
 * @return  : none
 */
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;
}

/**
 * @brief   : 初始化LED对应的GPIO
 * @para    : none
 * @return  : none
 */
void gpio_led_init(void)
{
    /* 初始化IO复用, 复用为GPIO1_IO03 */
    SW_MUX_GPIO1_IO03 = 0x05;

    /* 配置GPIO1_IO03的IO属性 */
    SW_PAD_GPIO1_IO03 = 0x10B0;

    /* 初始化GPIO1_IO03设置为输出 */
    GPIO1_GDIR = 0x00000008;

    /* 设置GPIO1_IO03输出低电平, 打开LED0 */
    GPIO1_DR = 0x00;
}

/**
 * @brief   : 打开LED灯
 * @para    : none
 * @return  : none
 */
void led_on(void)
{
    /* 将GPIO1_DR的bit3清零 */
    GPIO1_DR &= ~(1 << 3);
}

/**
 * @brief   : 关闭LED灯
 * @para    : none
 * @return  : none
 */
void led_off(void)
{
    /* 将GPIO_DR的bit3置1 */
    GPIO1_DR |= (1 << 3);
}

/**
 * @brief   : 延时
 * @para    : none
 * @return  : none
 */
void delay(volatile unsigned int n)
{
    volatile unsigned int dly = 0x7FF;

    while (n--) {
        while (dly--) {
        }
        dly = 0x7FF;
    }
}

/**
 * @brief   : main函数
 * @para    : none
 * @return  : none
 */
int main(void)
{
    clk_enable();           /* 使能时钟 */
    gpio_led_init();       /* 初始化LED的GPIO引脚 */

    while(1) {     
        led_on();               /* 打开LED */
        delay(500);

        led_off();               /* 关闭LED */
        delay(500);            /* 延时约500ms */
    }

    return 0;
}
  1. Makefile
objs	:= start.o main.o

led.bin:$(objs)
	# $^是所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那这个变量会去除重复的依赖目标,只保留一份。在这里$^就是start.o main.o
	arm-linux-gnueabihf-ld	-Timx6ul.lds -o led.elf $^
	# $@表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,“$@”就是匹配于目标中模式定义的集合。在这里就是led.bin
	arm-linux-gnueabihf-objcopy -O binary -S led.elf $@
	arm-linux-gnueabihf-objdump -D -m arm led.elf > led.dis

%.o:%.s
	# $<是依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$<"将是符合模式的一系列的文件集。注意,其是一个一个取出来的, 在这里$<就是start.s文件。在这里$@就是start.o
	arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<
	
%.o:%.S
	# $<是依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$<"将是符合模式的一系列的文件集。注意,其是一个一个取出来的, 在这里$<无匹配文件。在这里$@无匹配文件
	arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<

%.o:%.c
	# $<是依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$<"将是符合模式的一系列的文件集。注意,其是一个一个取出来的, 在这里$<就是main.c文件。在这里$@就是main.o
	arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<

.PHONY clean:
	rm -rf *.o *.bin *.elf *.dis

你可能感兴趣的:(Linux)