当前位置: 首页 > article >正文

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内核

  • 读指令

ldr 目的, 源
ldr R0, =0x40002010   @将外设寄存器的地址读取到内核寄存器,0x40002010外设寄存器地址,R0内核寄存器
ldr R1, =0x40002014   @将外设寄存器的地址读取到内核寄存器
ldr R2, [R0]          @读取外设寄存器0x40002010中的数据到R2
  • 写指令

ldr R0, =0x40002010   @将外设寄存器的地址读取到内核寄存器
ldr R1, =0x40002014   @将外设寄存器的地址读取到内核寄存器
STR R1, [R0]          @将R1中的数据写入到R0保存的地址中去

第3章 代码实战

leds.s

.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章 编译过程

  • 汇编编译为目标文件
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

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

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

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

  • 格式转换,将.elf转换成bin文件

arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
  • 对elf 文件进行反汇编

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

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卡;

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
#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
#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;
}


http://www.kler.cn/a/568959.html

相关文章:

  • 【智能音频新风尚】智能音频眼镜+FPC,打造极致听觉享受!【新立电子】
  • python多线程之Event机制笔记
  • Qt 中 **QGraphicsView** 框架的总结
  • openssl下aes128算法gcm模式加解密运算实例
  • 基于java,SpringBoot和Vue流浪动物救助领养管理系统设计
  • Qt中应用程序框架的体系说明 及应用程序类QApplication类深度解析与应用分析
  • ZK Rollup
  • JMeter 不同协议测试最佳实践汇总
  • 深入讨论C语言的可能抽象:部分对设计模式的思考
  • Maven 与持续集成(CI)/ 持续部署(CD)(一)
  • 小红的字母游戏(A组)
  • Rust~Pin的new
  • 【git】【rebase】git修改提交信息的几种方法
  • 【AI Coding】Windsurf:【Prompt】全局规则与项目规则「可直接使用」
  • 如何在 ArcGIS Pro 中将SHP转为KML:详细步骤与操作指南
  • 基于互联网协议的诊断通信(DoIP)
  • 《HarmonyOS Next × ArkTS框架:从AI模型压缩到智能家居控制的端侧开发指南》
  • 对rust中的from和into的理解
  • Android 应用开发中,证书、签名和加固简述
  • 加入二极管的NE555 PWM 电路