IMX6Ull学习笔记1:汇编点亮LED灯

第1章 点亮LED的步骤

  1. 配置时钟(CCM寄存器配置时钟);

  2. 设置引脚复用功能( GPIO1_I003 PIN的复用为GPIO**);**

  3. 配置GPIO的电气属性(包括摆率,速度,驱动能力,开漏,上下拉等等);

  4. 配置GPIO功能,设置输入输出模式;

  5. 设置GPIO的数据寄存器;

第2章 汇编基础

汇编代码的入口都是

.global _start

start:

指令集
.global 是一个伪目标

-start 是汇编代码的入口函数

start 真正的函数区

imx6ull是Cortex-A内核

  • 读指令
cpp 复制代码
ldr 目的, 源
ldr R0, =0x40002010   @将外设寄存器的地址读取到内核寄存器,0x40002010外设寄存器地址,R0内核寄存器
ldr R1, =0x40002014   @将外设寄存器的地址读取到内核寄存器
ldr R2, [R0]          @读取外设寄存器0x40002010中的数据到R2
  • 写指令
cpp 复制代码
ldr R0, =0x40002010   @将外设寄存器的地址读取到内核寄存器
ldr R1, =0x40002014   @将外设寄存器的地址读取到内核寄存器
STR R1, [R0]          @将R1中的数据写入到R0保存的地址中去

第3章 代码实战

leds.s

cpp 复制代码
.global _start @全局标号

_start:
    /*使能所有外设时钟 */
    LDR R0 , =0x020c4068  @CCGR0   --》这是汇编的注释格式
    LDR R1 , =0xffffffff  @要想CCGR0写入的数据
    STR R1 , [R0]         @将R1的值写入到R0中
    
    LDR R0 , =0x020c406c  @CCGR1
    STR R1 ,[R0]

    LDR R0 , =0x020c4070  @CCGR1
    STR R1 ,[R0]

    LDR R0 , =0x020c4074  @CCGR1
    STR R1 ,[R0]

    LDR R0 , =0x020c4078  @CCGR1
    STR R1 ,[R0]

    LDR R0 , =0x020c407c  @CCGR1
    STR R1 ,[R0]

    LDR R0 , =0x020c4080  @CCGR1
    STR R1 ,[R0]

    /*配置 GPIO_I003  PIN的复用为GPIO
    * IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 0101 =5
    * IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03寄存器的地址为0x020E_0068
    */
    LDR R0 , =0x020E0068  @IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03
    LDR R1 , =0x5          @要写入的数据
    STR R1 , [R0]          @将5写入IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03

    /*配置 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03的电器属性
    * IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03的地址时0x020E_02F4
    * bit0 :    0 低速率
    * bit5-3:   110 R0/6  驱动能力
    * bit7-6:   10 100MHz速度
    * bit11:    0 关闭开路输出
    * bit12:    1 使能pull/keeper
    * bit15-14: 00 100K下拉
    * bit16:    0 关闭hys    
    * 向寄存器IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03写入 0x10b0
    */

    LDR R0 , = 0x020E02F4
    LDR R1 , = 0x10b0
    STR R1 ,[R0]

    /*设置GPIO功能
     *设置GPIO1_GDIR寄存器  设置GPIO1_GPIO03为输出
     *寄存器GPIO_GDIR的地址是  0x0209C004
     * 设置GPIO1_GDIR寄存器bit3为1也就是GPIO1_GPIO03为输出
     */
    LDR R0 , = 0x0209C004
    LDR R1 , = 0x8
    STR R1 ,[R0]

    /*打开LED,也就是设置GPIO1_GPIO03为0 
     *GPIO1_DR 寄存器地址为0x0209C000
    */

    LDR R0 , = 0x0209C000
    LDR R1 , =0
    STR R1 ,[R0]

loop:       @ 给一个死循环 让CPU只执行这些已知的指令
    b loop  @ b 是跳转的意思

第4章 编译过程

  • 汇编编译为目标文件
bash 复制代码
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
  • 将所有目标文件链接在一起,并且指定链接地址

arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o lex.o led2.o -o led.elf

bash 复制代码
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf

这条命令的主要作用是将led.o目标文件链接成一个可执行文件led.elf;

这意味着:当你在嵌入式系统中加载并执行led.elf时,代码会从0x87800000地址开始执行。

  • 格式转换,将.elf转换成bin文件
cpp 复制代码
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
  • 对elf 文件进行反汇编

大多数情况下我们都是用 C 语言写试验例程的,有时候需要查看其汇编代码来调试代码,因此就需要进行反汇编,一般可以将 elf 文件反汇编,比如如下命令:

cpp 复制代码
arm-linux-gnueabihf-objdump -D led.elf > led.dis

特别注意:

1. 链接过程中指定了代码段的起始地址(0X87800000),该地址是片外RAM(DDR)的地址,而不是片上Flash的地址;因为IMX6ull的片上flash不给用,片上RAM的地址128Kb较小,所以直接指定代码段的起始地址为片外DDR上的0X87800000地址作为代码段的起始地址。

2.链接起始地址是0X87800000,并且该地址是DDR的地址。由此可知需要使用DDR,所以在使用之前需要初始化DDR。 因此在在bin文件头部添加一段初始化DDR的初始化参数。

3. I.MX系列SOC内部bootrom会从SD卡,EMMC 等外置存储中读取头部信息,然后初始化 DDR,并且将 bin 文件拷贝到指定的地方。

第5章 烧录

使用正点原子的软件,添加头信息。并且烧录SD卡;

bash 复制代码
led.bin:leds.s
	@arm-linux-gnueabihf-gcc -g -c leds.s -o led.o					# 将汇编文件转换为目标文件
	@arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf		# 将目标文件链接到指定位置,并且输出为unix下的可执行文件
	@arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin		# 将可执行文件转换为二进制文件
	@arm-linux-gnueabihf-objdump -D led.elf > led.dis				# 将可执行文件转换为反汇编文件

# 生将正点原子提供的源码文件利用gcc编译成可以将二进制文件下载到SD卡的软件
run:
	gcc imxdownload.c -o  imxdownload

# 利用下载软件将二进制文件下载到SD卡
download:
	./imxdownload led.bin /dev/sdb

# 清理指定文件
clean:
	rm -rf *.o led.bin led.elf led.dis imxdownload load.imx
  • imxdownload.h
cpp 复制代码
#ifndef _IMXDOWNLOAD_H
#define _IMXDOWNLOAD_H
/* IMX6U IVT DCD表信息  暂时定义为1K Bytes,此表是读取的u-boot.imx前1K Bytes
 * imx6_ivedcd_table[9]是指明代码长度的,本应该根据实际的代码长度来修改
 * 这里为了方便,就直接定义为2M Bytes,即
 */

const int imx6_512mb_ivtdcd_table[256] = {
        0X402000D1,0X87800000,0X00000000,0X877FF42C,0X877FF420,0X877FF400,0X00000000,0X00000000,
        0X877FF000,0X00200000,0X00000000,0X40E801D2,0X04E401CC,0X68400C02,0XFFFFFFFF,0X6C400C02,
        0XFFFFFFFF,0X70400C02,0XFFFFFFFF,0X74400C02,0XFFFFFFFF,0X78400C02,0XFFFFFFFF,0X7C400C02,
        0XFFFFFFFF,0X80400C02,0XFFFFFFFF,0XB4040E02,0X00000C00,0XAC040E02,0X00000000,0X7C020E02,
        0X30000000,0X50020E02,0X30000000,0X4C020E02,0X30000000,0X90040E02,0X30000000,0X88020E02,
        0X30000C00,0X70020E02,0X00000000,0X60020E02,0X30000000,0X64020E02,0X30000000,0XA0040E02,
        0X30000000,0X94040E02,0X00000200,0X80020E02,0X30000000,0X84020E02,0X30000000,0XB0040E02,
        0X00000200,0X98040E02,0X30000000,0XA4040E02,0X30000000,0X44020E02,0X30000000,0X48020E02,
        0X30000000,0X1C001B02,0X00800000,0X00081B02,0X030039A1,0X0C081B02,0X0B000300,0X3C081B02,
        0X44014801,0X48081B02,0X302C4040,0X50081B02,0X343E4040,0X1C081B02,0X33333333,0X20081B02,
        0X33333333,0X2C081B02,0X333333F3,0X30081B02,0X333333F3,0XC0081B02,0X09409400,0XB8081B02,
        0X00080000,0X04001B02,0X2D000200,0X08001B02,0X3030331B,0X0C001B02,0XF3526B67,0X10001B02,
        0X630B6DB6,0X14001B02,0XDB00FF01,0X18001B02,0X40172000,0X1C001B02,0X00800000,0X2C001B02,
        0XD2260000,0X30001B02,0X23106B00,0X40001B02,0X4F000000,0X00001B02,0X00001884,0X90081B02,
        0X00004000,0X1C001B02,0X32800002,0X1C001B02,0X33800000,0X1C001B02,0X31800400,0X1C001B02,
        0X30802015,0X1C001B02,0X40800004,0X20001B02,0X00080000,0X18081B02,0X27020000,0X04001B02,
        0X2D550200,0X04041B02,0X06100100,0X1C001B02,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000
};

const int imx6_256mb_ivtdcd_table[256] = {
        0X402000D1,0X87800000,0X00000000,0X877FF42C,0X877FF420,0X877FF400,0X00000000,0X00000000,
        0X877FF000,0X00076000,0X00000000,0X40E801D2,0X04E401CC,0X68400C02,0XFFFFFFFF,0X6C400C02,
        0XFFFFFFFF,0X70400C02,0XFFFFFFFF,0X74400C02,0XFFFFFFFF,0X78400C02,0XFFFFFFFF,0X7C400C02,
        0XFFFFFFFF,0X80400C02,0XFFFFFFFF,0XB4040E02,0X00000C00,0XAC040E02,0X00000000,0X7C020E02,
        0X30000000,0X50020E02,0X30000000,0X4C020E02,0X30000000,0X90040E02,0X30000000,0X88020E02,
        0X30000C00,0X70020E02,0X00000000,0X60020E02,0X30000000,0X64020E02,0X30000000,0XA0040E02,
        0X30000000,0X94040E02,0X00000200,0X80020E02,0X30000000,0X84020E02,0X30000000,0XB0040E02,
        0X00000200,0X98040E02,0X30000000,0XA4040E02,0X30000000,0X44020E02,0X30000000,0X48020E02,
        0X30000000,0X1C001B02,0X00800000,0X00081B02,0X030039A1,0X0C081B02,0X04000000,0X3C081B02,
        0X3C013C01,0X48081B02,0X38324040,0X50081B02,0X28304040,0X1C081B02,0X33333333,0X20081B02,
        0X33333333,0X2C081B02,0X333333F3,0X30081B02,0X333333F3,0XC0081B02,0X09409400,0XB8081B02,
        0X00080000,0X04001B02,0X2D000200,0X08001B02,0X3030331B,0X0C001B02,0XF352433F,0X10001B02,
        0X630B6DB6,0X14001B02,0XDB00FF01,0X18001B02,0X40172000,0X1C001B02,0X00800000,0X2C001B02,
        0XD2260000,0X30001B02,0X23104300,0X40001B02,0X47000000,0X00001B02,0X00001883,0X90081B02,
        0X00004000,0X1C001B02,0X32800002,0X1C001B02,0X33800000,0X1C001B02,0X31800400,0X1C001B02,
        0X30802015,0X1C001B02,0X40800004,0X20001B02,0X00080000,0X18081B02,0X27020000,0X04001B02,
        0X2D550200,0X04041B02,0X06100100,0X1C001B02,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
        0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,0X00000000,
};

#endif
  • imxdownload.c
bash 复制代码
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "imxdownload.h"

#define SHELLCMD_LEN	(200)
#define BIN_OFFSET		(3072)

/* 此宏指明是否打印u-boot.imx的IVT DCD表信息,不同的开发板其IVT和DCD
 * 表的数据是不同的,因此需要获取所使用的开发板的IVT和DCD表信息,最
 * 简单的方法就是读取开发板配套资料里面的u-boot.imx的前1KB数据,理论上
 * 应该读取3KB的数据,但是表信息远远没有3K这么多,因此读1KB即可
 */
#define PRINT_TAB		0
/*
 * 介绍: 此软件是针对NXP的IMX6U系列芯片的,软件用来烧写bin文件到SD卡里面,
 *        本软件会自动添加IVT、DCD等信息到原始的bin文件里面,主要用于裸机和uboot的烧写。
 * 使用方法: 1、编译好原始的二进制bin文件,如,u-boot.bin等,并将编译好的.bin文件和本
 *             软件放置到同一个目录下!!!!
 *        	2、执行命令sudo ./imxdownload <soucre_bin> <sd_device>
 *             如烧写u-boot.bin到/dev/sdd中即可使用如下所示命令:
 *             sudo ./imxdownload u-boot.bin /dev/sdd
 */

/*
 * 输出一些信息
 */
void message_print(void)
{
    printf("I.MX6ULL bin download software\r\n");
    printf("Edit by:zuozhongkai\r\n");
    printf("Date:2019/6/10\r\n");
    printf("Version:V1.1\r\n");
    printf("log:V1.0 initial version,just support 512MB DDR3\r\n");
    printf("    V1.1 and support 256MB DDR3\r\n");
}

int main(int argc, char *argv[])
{
    FILE *fp;
    unsigned char *buf;
    unsigned char *cmdbuf;
    int nbytes, filelen;
    int i = 0, j = 0;
    int ddrsize = 0; /* 0为512MB,1为256MB,2为128MB...... */

    message_print();

    if((argc != 3) && (argc != 4)){
        printf("Error Usage! Reference Below:\r\n");
        printf("sudo ./%s <-512m or -256m> <source_bin> <sd_device>\r\n", argv[0]);
        return -1;
    }

    /* 查找参数,获取DDR容量 */
    for(i = 0; i < argc; i++)
    {
        char *param = argv[i];
        if(param[0] != '-')
            continue;
        if(strcmp(param, "-256m") == 0) 		/* 256MB */
            ddrsize = 1;
        else if(strcmp(param, "-512m") == 0)	/* 512MB */
            ddrsize = 0;
    }
    if(argc == 3)	/* 三个参数,也就是不输入DDR容量的话默认为512MB */
        ddrsize = 0;

    /* 打开bin文件 */
    fp = fopen(argv[1], "rb"); /* 以二进制只读方式打开bin文件 */
    if(fp == NULL){
        printf("Can't Open file %s\r\n", argv[1]);
        return -1;
    }

    /* 获取bin文件长度 */
    fseek(fp, 0L, SEEK_END);
    filelen = ftell(fp);
    fseek(fp, 0L, SEEK_SET);
    printf("file %s size = %dBytes\r\n", argv[1], filelen);

    /* 读取bin文件到缓冲区buf中 */
    buf = malloc(filelen + BIN_OFFSET);
    if(buf == NULL){
        printf("Mem Malloc Failed!\r\n");
        fclose(fp);
        return -1;
    }
    memset(buf, 0, filelen + BIN_OFFSET); /* 清零 */
    /* 读取bin源码文件 */
    fread(buf + BIN_OFFSET, 1, filelen, fp);

    /* 关闭文件 */
    fclose(fp);

#if PRINT_TAB
    printf("IVT DCD Table:\r\n");
	for(i = 0; i < 1024/32; i++){
		for(j = 0; j < 8; j++)
		{
			printf("0X%08X,",*(int *)(buf + BIN_OFFSET + (((i * 8) + j) * 4)));
		}
		printf("\r\n");
	}
	free(buf);
	return 0;
#endif

    /* 添加IVT DCD等表信息到bin文件里面 */
    if(ddrsize == 0) {		/* 512MB */
        printf("Board DDR SIZE: 512MB\r\n");
        memcpy(buf, imx6_512mb_ivtdcd_table, sizeof(imx6_512mb_ivtdcd_table));
    }
    else if (ddrsize == 1) {	/* 256MB */
        printf("Board DDR SIZE: 256MB\r\n");
        memcpy(buf, imx6_256mb_ivtdcd_table, sizeof(imx6_256mb_ivtdcd_table));
    }

    /* 现在我们已经在buf中构建好了可以用于下载的bin文件,将buf中的数据保存到
     * 到一个文件中,文件命名为load.imx
     */
    printf("Delete Old load.imx\r\n");
    system("rm -rf load.imx");		/* 先删除旧的load.imx文件	*/

    printf("Create New load.imx\r\n");
    system("touch load.imx");		/* 创建新的load.imx文件		*/
    fp = fopen("load.imx", "wb");	/* 打开laod.imx				*/
    if(fp == NULL){
        printf("Cant't Open load.imx!!!\r\n");
        free(buf);
        return -1;
    }
    nbytes = fwrite(buf, 1, filelen + BIN_OFFSET, fp);
    if(nbytes != (filelen + BIN_OFFSET)){
        printf("File Write Error!\r\n");
        free(buf);
        fclose(fp);
        return -1;
    }
    free(buf);
    fclose(fp);

    /* 构建烧写的shell命令 */
    cmdbuf = malloc(SHELLCMD_LEN);
    sprintf(cmdbuf, "sudo dd iflag=dsync oflag=dsync if=load.imx of=%s bs=512 seek=2",argv[2]);
    printf("Download load.imx to %s  ......\r\n", argv[2]);

    /* 执行上面的shell命令 */
    system(cmdbuf);
    free(cmdbuf);
    return 0;
}
相关推荐
知识分享小能手1 小时前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
汇能感知3 小时前
摄像头模块在运动相机中的特殊应用
经验分享·笔记·科技
阿巴Jun4 小时前
【数学】线性代数知识点总结
笔记·线性代数·矩阵
茯苓gao4 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾4 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
DKPT5 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习
aaaweiaaaaaa5 小时前
HTML和CSS学习
前端·css·学习·html
ST.J5 小时前
前端笔记2025
前端·javascript·css·vue.js·笔记
Suckerbin5 小时前
LAMPSecurity: CTF5靶场渗透
笔记·安全·web安全·网络安全
看海天一色听风起雨落6 小时前
Python学习之装饰器
开发语言·python·学习