ARM(IMX6U)裸机汇编LED驱动实验——驱动编写、编译链接起始地址、烧写bin文件到SD卡中并运行

2023-11-16

参考:Linux之ARM(IMX6U)裸机汇编LED驱动实验–驱动编写
作者:一只青木呀
发布时间: 2020-08-07 09:13:48
网址:https://blog.csdn.net/weixin_45309916/article/details/107851318

参考:Linux之ARM(IMX6U)裸机汇编LED驱动实验–编译驱动
作者:一只青木呀
发布时间: 2020-08-07 10:26:44
网址:https://blog.csdn.net/weixin_45309916/article/details/107855668

参考:Linux之ARM(IMX6U)裸机汇编LED驱动实验–烧写bin文件到SD卡中并运行
作者:一只青木呀
发布时间: 2020-08-08 18:29:16
网址:https://blog.csdn.net/weixin_45309916/article/details/107883289

目录

1. 程序编写

在这里插入图片描述

硬件电路图(找到LED0)

在这里插入图片描述

①、使能时钟

使能时钟。CCGR0–CCGR6这七个寄存器控制着I.MX6ULL所有外设时钟的使能,为了简单,设置CCGR0–CCGR6这七个寄存器全部为0xFFFFFFFF,相当于使能所有的外设时钟(前面汇编章节讲过了,这里的寄存器不是内部寄存器,而是RAM里面的寄存器。CPU不能直接访问RAM,所以通过汇编指令LDR、STR指令进行读写操作RAM里面的寄存器

汇编使能所有的外设时钟:
在这里插入图片描述

CCGR0:
在这里插入图片描述
CCGR1:
在这里插入图片描述
CCGR2:
在这里插入图片描述
CCGR3:
在这里插入图片描述

CCGR4:
在这里插入图片描述
CCGR5:
在这里插入图片描述
CCGR6:
在这里插入图片描述

②、配置 GPIO1_I003 PIN的复用为GPIO

将IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03寄存器的bit3-0,设置为0101,这样GPIO_IO03就复用为GPIO
在这里插入图片描述
汇编实现:
在这里插入图片描述

③、配置 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03的电器属性

设置寄存器 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03的电器属性,包括摆率,速度,驱动能力,开漏,上下拉等等
在这里插入图片描述
在这里插入图片描述

上表中寄存器每一位的功能作用:
bit0: 压摆率
bit2-1: 保留的,没有用
bit5-3: 驱动能力,数值越大,驱动能力越强
bit7-6: 速度
bit10-8: 保留的,没有用
bit11:开路输出(打开、关闭)
bit12:使能上拉还是保持
bit15-14:上下拉阻值

汇编代码实现:
在这里插入图片描述

用计算器计算二进制转十六进制的计算方法:
在这里插入图片描述

④、配置GPIO功能,设置输入输出模式

设置GPIO1_GDIR寄存器bit3为1(GPIO1_IO03和LED灯连接),也就是设置为输出模式
在这里插入图片描述
在这里插入图片描述
汇编实现:
在这里插入图片描述

⑤、设置GPIO_DR寄存器的bit3,1表示输出高电平,0表示输出低电平

在这里插入图片描述

在这里插入图片描述
汇编实现:
在这里插入图片描述

整个汇编代码(.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 是跳转的意思


2. 程序编译

交叉编译器的准备

我们是要编译出在 ARM 开发板上运行的可执行文件,所以要使用交叉编译器 arm-linux-gnueabihf-gcc 来编译。

交叉编译链的安装参考另外一篇博文:交叉编译链的安装

代码编译过程

本试验就一个 leds.s 源文件,所以编译比较简单。

在这里插入图片描述
在这里插入图片描述

1.把 .s 文件编译成 .o文件

在这里插入图片描述

arm-linux-gnueabihf-gcc -g -c led.s -o led.o

在这里插入图片描述

其中“-g”选项是产生调试信息,GDB 能够使用这些调试信息进行代码调试。“-c”选项是编译源文件,但是不链接。“-o”选项是指定编译产生的文件名字,这里我们指定 led.s 编译完成以后的文件名字为 leds.o。执行上述命令以后就会编译生成一个 leds.o 文件

2.把 .o文件链接成.elf格式的可执行文件(链接起始地址)

arm-linux-gnueabihf-ld 用来将众多的.o 文件链接到一个指定的位置(起始地址)。

我们在学习SMT32 的时候基本就没有听过“链接”这个词,我们一般用MDK(即keil软件) 编写好代码,然后点击“编译”,MDK 或者IAR 就会自动帮我们编译好整个工程,最后再点击“下载”就可以将代码下载到开发板中。这是因为链接这个操作MDK 或者IAR 已经帮你做好了,后面我就以MDK 为例给大家讲解。大家可以打开一个STM32 的工程,然后编译一下,肯定能找到很多.o 文件,如图所示:
在这里插入图片描述
图中的这些.o 文件肯定会被MDK 链接到某个地址去,如果使用MDK 开发STM32
的话肯定对下图所示界面很熟悉:
在这里插入图片描述
图中左侧的IROM1 我们都知道是设置STM32 芯片的x和大小的,右边的IRAM1 是设置STM32 芯片的RAM 起始地址和大小的。其中0X08000000 就是STM32 内部ROM (flash)的起始地址,编译出来的指令肯定是要从0X08000000 这个地址开始存放的。对于STM32 来说0X08000000 就是它的链接地址,图中的这些.o 文件就是这个链接地址开始依次存放,最终生成一个可以下载的hex 或者bin 文件,我们可以打开.map 文件查看一下这些文件的链接地址,在MDK 下打开一个工程的.map 文件方法如下图所示:
在这里插入图片描述
图中的.map 文件就详细的描述了各个.o 文件都是链接到了什么地址,如下图
所示:
在这里插入图片描述
从图中就可以看出STM32 的各个.o 文件所处的位置,起始位置是0X08000000。由此可以得知,我们用MDK 开发STM32 的时候也是有链接的,只是这些工作MDK 都帮我们全部做好了,我们不用关心而已。但是我们在Linux 下用交叉编译器开发ARM 的是时候就需要自己处理这些了。

代码要运行,那就必须处于运行地址处,否则代码肯定运行出错。比如 I.MX6U 支持 SD 卡、EMMC、NAND 启动,因此代码可以存储到 SD 卡、EMMC 或者 NAND 中,但是要运行的话就必须将代码从 SD 卡、EMMC 或者NAND 中拷贝到其运行地址(链接地址)处,“存储地址”和“运行地址”可以一样。

裸机例程都是烧写到 SD 卡中,上电以后 I.MX6U 的内部 boot rom 程序会将可执行文件拷贝到链接地址处,这个链接地址可以在 I.MX6U 的内部 128KB RAM 中(0X900000~0X91FFFF),也可以在外部的 DDR中。

我们把链接地址都放在 DDR中(因为内部RAM太小了),链接起始地址为 0X87800000I.MX6U-ALPHA 开发板的DDR 容量有两种:512MB 和256MB,起始地址都为 0X80000000,只不过 512MB 的终止地址为 0X9FFFFFFF,而 256MB 容量的终止地址为 0X8FFFFFFF之所以选择 0X87800000 这个地址是因为后面要讲的 Uboot 其链接地址就是 0X87800000,这样我们统一使0X87800000 这个链接地址,不容易记混

链接起始地址就是代码运行的起始地址,有的时候也是保存代码的起始地址。

要使用DDR,必须要初始化DDR,对于I.MX来说bin文件不能直接运行,需要添加一个头部,这个头部信息包含了DDR的初始化参数,I.MX系列SOC内部boot room会从SD卡,EMMC等外置存储中读取头部信息,然后初始化DDR,并且将bin文件拷贝到指定的地方。
Bin的运行地址一定要和链接起始地址一致。位置无关代码除外。

确定了链接地址以后就可以使用 arm-linux-gnueabihf-ld 来将前面编译出来的 led.o 文件链接到 0X87800000 这个地址,使用如下命令:


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

上述命令中 -Ttext 就是指定链接地址,“-o”选项指定链接生成的 elf 文件名,这里我们命名为 led.elf。上述命令执行完以后就会在工程目录下多一个 led.elf 文件

在这里插入图片描述

led.elf 文件也不是我们最终烧写到 SD 卡中的可执行文件,还需要将 led.elf 文件转换为.bin 文件,这里我们就需要用到 arm-linux-gnueabihf-objcopy 这个工具了。

3.arm-linux-gnueabihf-objcopy 格式转换将.elf转换成bin文件

arm-linux-gnueabihf-objcopy 更像一个格式转换工具,我们需要用它将 led.elf 文件转换为led.bin 文件,命令如下:

arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin

上述命令中,“-O”选项指定以什么格式输出,后面的“binary”表示以二进制格式输出,选项“-S”表示不要复制源文件中的重定位信息和符号信息,“-g”表示不复制源文件中的调试信息。上述命令执行完成以后,工程目录如图

在这里插入图片描述
至此我们终于等到了想要的东西-— led.bin文件。

4.arm-linux-gnueabihf-objdump (对elf 文件进行)反汇编

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

arm-linux-gnueabihf-objdump -D led.elf > led.dis

上述代码中的“-D”选项表示反汇编所有的段,反汇编完成以后就会在当前目录下出现一个名为 led.dis 文件
在这里插入图片描述
在这里插入图片描述
可以看出 led.dis 里面是汇编代码,而且还可以看到内存分配情况。在0X87800000 处就是全局标号_start,也就是程序开始的地方。通过 led.dis 这个反汇编文件可以明显的看出到我们的代码已经链接到了以 0X87800000 为起始地址的区域。

5.整理成makefile文件

上面的这些命令一条条的敲太麻烦啦!而且这些代码有问题的话还要回去一直改代码来回编译很麻烦。我们可以把它整理成一个Makefile文件,一次性完成。

是用“touch”命令在工程根目录下创建一个名为“Makefile”的文件,如图
在这里插入图片描述
创建好 Makefile 文件以后就需要根据 Makefile 语法编写 Makefile 文件了:

led.bin:led.s
	arm-linux-gnueabihf-gcc -g -c led.s -o led.o
	arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
	arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
	arm-linux-gnueabihf-objdump -D led.elf > led.dis
clean:
	rm -rf *.o led.bin led.elf led.dis

注意: Makefile 命令前一定要是tab键形成的四个空格

led.bin是目标
led.s是依赖的文件
clean清理生成的所有文件

创建好 Makefile 以后我们就只需要执行一次“make”命令即可完成编译
在这里插入图片描述

3. 烧写bin文件到SD卡中并运行

STM32烧写到内部FLASH。
6ULL支持SD卡、EMMC、NAND、NOR、SPI FLASH等启动。裸机例程选择烧写到SD卡里面。

I.MX6U 虽然内部有 96K 的 ROM,但是这 96K 的 ROM 是 NXP自己用的,不向用户开放。所以相当于说 I.MX6U 是没有内部 flash 的,但是我们的代码得有地方存放啊,为此,I.MX6U 支持从外置的 NOR Flash、NAND Flash、SD/EMMC、SPI NOR Flash和 QSPI Flash 这些存储介质中启动,所以我们可以将代码烧写到这些存储介质中中。在这些存储介质中,除了 SD 卡以外,其他的一般都是焊接到了板子上的,我们没法直接烧写。但是 SD卡是活动的,是可以从板子上插拔的,我们可以将 SD 卡插到电脑上,在电脑上使用软件将.bin文件烧写到 SD 卡中,然后再插到板子上就可以了。其他的几种存储介质是我们量产的时候用到的,量产的时候代码就不可能放到 SD 卡里面了,毕竟 SD 是活动的,不牢固,而其他的都是焊接到板子上的,很牢固。

因此,我们在调试裸机和 Uboot 的时候是将代码下载到 SD 中,因为方便嘛,当调试完成以后量产的时候要将裸机或者 Uboot 烧写到 SPI NOR Flash、EMMC、NAND 等这些存储介质中的。


那么,如何将我们前面编译出来的 led.bin 烧写到 SD 卡中呢?肯定有人会认为直接复制led.bin 到 SD 卡中不就行了,错!编译出来的可执行文件是怎么存放到 SD 中的,存放的位置是什么?这个 NXP 是有详细规定的!我们必须按照 NXP 的规定来将代码烧写到 SD 卡中,否则代码是绝对运行不起来的。

而且对于I.MX而言,不能直接烧写bin文件,比如要先在bin文件前面添加头部(下一讲会讲到)。而完成这个工作,需要使用正点原子提供的imxdownload软件。

1.烧写的工具

正点原子提供的imxdownload源代码

在这里插入图片描述
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;	
}

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

2.将 imxdownload 放在工程目录下(led.bin同一个文件夹下)

在这里插入图片描述

3.imxdownload 可执行权限

chmod   777  imxdownload

在这里插入图片描述

4.确定要烧写的 SD 卡。

准备一张新的 SD(TF)卡,确保 SD 卡里面没有数据,因为我们在烧写代码的时候可能会格式化 SD 卡!!!

Ubuntu 下所有的设备文件都在目录“/dev”里面,所以插上 SD 卡以后也会出现在“/dev”里面,其中存储设备都是以“/dev/sd”开头的。我们要先看一下不插 SD 卡的时候电脑都有哪些存储设备,以防插入 SD 卡以后分不清谁是谁。输入如下所示命令:

ls  /dev/sd*

在这里插入图片描述
从图中可以看到当前电脑有/dev/sda、/dev/sda1

使用读卡器将 SD 卡插到电脑,一定要确保 SD 卡是挂载到了 Ubuntu 系统中,而不是 Windows下。SD 卡挂载到电脑以后,VMware 桌面会出现boot图标(Ubuntu18.04)

在这里插入图片描述
再次查看:

ls  /dev/sd*

在这里插入图片描述
这里我们的Ubuntu多出了两个dev/sdb和/dev/sdb1,/dev/sdb 是我的 SD 卡,/dev/sdb1 是 SD 卡的第一个分区,我们把bin文件烧写到/dev/sdb1里面

确定好SD 卡以后我们就可以使用软件 imxdownload 向 SD 卡烧写 led.bin 文件了。

5.向 SD 卡烧写 bin 文件

使用 imxdownload 向 SD 卡烧写 led.bin 文件,命令格式如下:

./imxdownload <.bin file> <SD Card>

其中.bin 就是要烧写的.bin 文件,SD Card 就是你要烧写的 SD 卡,比如我的电脑使用如下命令烧写 led.bin 到/dev/sdb1 中:

./imxdownload leds.bin /dev/sdb1

在这里插入图片描述
烧写的最后一行会显示烧写大小、用时和速度,比如 led.bin 烧写到 SD 卡中的大小是 3.2KB,用时 0.0160821s,烧写速度是 201KB/s。注意这个烧写速度,如果这个烧写速度在几百 KB/s 以下那么就是正常烧写。

如果这个烧写速度大于几十 MB/s、甚至几百 MB/s 那么肯定是烧写失败了!

解决方法就是重新插拔 SD 卡,一般出现这种情况,重新插拔 SD 卡基本没啥用,只有重启Ubuntu,至于原因,我也不清楚。

烧写完成以后会在当前工程目录下生成一个 load.imx 的文件,如图
在这里插入图片描述
load.imx 这个文件就是软件 imxdownload 根据 NXP 官方启动方式介绍的内容,在 leds.bin 文件前面添加了一些数据头以后生成的最终烧写到 SD 卡里面的就是这个 load.imx 文件,而非leds.bin

6.代码验证

代码已经烧写到了 SD 卡中了,接下来就是将 SD 卡插到开发板的 SD 卡槽中,然后设置拨码开关为 SD 卡启动,拨码开关设置如图:
在这里插入图片描述
设置好以后按一下开发板的复位键,如果代码运行正常的话 LED0 就会被点亮,如图:
在这里插入图片描述
LED0 被正常点亮,可能 LED0 之前会有一点微亮,那是因为 I.MX6U的 IO 默认电平可能让 LED0 导通了,但是 IO 的默认配置内部可能有很大的电阻,所以电流就很小,导致 LED0 微亮。但是我们自己编写代码、配置好 IO 以后就不会有这个问题,LED0 就很亮了。

其他

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ARM(IMX6U)裸机汇编LED驱动实验——驱动编写、编译链接起始地址、烧写bin文件到SD卡中并运行 的相关文章

  • ARM 汇编不能同时使用立即值和 ADDS/ADCS

    我目前正在尝试使用汇编来加速 Cortex M0 Freescale KL25Z 上的一些 C 函数 我遇到这个最小测试程序的问题 syntax unified cpu cortex m0 text global test code 16
  • ARM 汇编 SOS 中的 64 位除法

    我正在计算 16 个 64 位数字相加的平均值 我认为我已经正确完成了所有加法 但现在我需要弄清楚如何将 64 位数字除以 16 但我被困住了 任何帮助都会非常感谢你 到目前为止 这是我的代码 tableSize EQU 16 sum EQ
  • 如何在 ARM 架构上从 RAM 运行代码

    我正在对 ARM Cortex R4 进行编程 并且有一些二进制文件 我想从 TCRAM 执行它们 只是为了看看性能的提升是否足够好 我知道我必须编写一个函数来将二进制文件复制到 RAM 这可以通过链接器脚本来完成 并且知道二进制文件的大小
  • STM32F0、ST-link v2、OpenOCD 0.9.0:打开失败

    我在用着发射台 http www ti com ww en launchpad about htmlgcc arm none eabi 4 9 2015q2 为 STM32F0 进行编译 现在我想使用该集合中的 arm none eabi
  • HAL_Delay() 陷入无限循环

    我被 HAL Delay 函数困住了 当我调用此函数 HAL Delay 时 控制陷入无限循环 在寻找问题的过程中 我发现了这个 http www openstm32 org forumthread2145 threadId2146 htt
  • ARM 汇编分支到寄存器或内存内部的地址

    我想知道在 ARM 汇编中我可以使用哪条指令分支到存储在某个内存地址中的地址或标签 例如 我们可以使用B LABEL来跳转到LABEL 但现在目的地只能在运行时知道 并且它存储在某个已知的内存位置 是否有类似 B 地址 的东西 Thanks
  • 使用 ARM NEON 内在函数添加 alpha 和排列

    我正在开发一个 iOS 应用程序 需要相当快地将图像从 RGB gt BGRA 转换 如果可能的话 我想使用 NEON 内在函数 有没有比简单分配组件更快的方法 void neonPermuteRGBtoBGRA unsigned char
  • 手臂“版本”之间的差异? (仅限 ARMv7)

    基本上我想知道ARMv7l和ARMv7之间的区别hl 我有一个带有armv7l的arm处理器 并且有很多armv7的rpmhl 我完全不知道我必须搜索什么才能获得相关信息 这个 后缀 叫什么 还有其他类型吗 他们的做法有何不同 我假设它指示
  • 用于 RHEL 的 gdb-multiarch

    我正在尝试寻找方法来运行gdb 多架构RHEL 中的命令 我已经安装了用于 ARM 处理的 QEMU 模拟器 我想安装GDB进行调试 我能够安装GDB 多体系结构在 Ubuntu 中运行命令成功 sudo apt get GDB multi
  • RAM 存储二进制数和汇编语言的冒泡排序

    我必须使用 ARM v7 执行一个例程 在 RAM 内存中存储 10 个二进制数 然后使用冒泡排序对这些数字从高到低进行排序 我应该如何开始 func bubbleSortAscendingU32 ldr r3 r0 4 mov r1 9
  • 将 GCC 内联汇编与采用立即值的指令结合使用

    问题 我正在为 ARM Cortex M3 处理器开发定制操作系统 为了与我的内核交互 用户线程必须生成 SuperVisor Call SVC 指令 以前称为 SWI 用于软件中断 该指令在ARM ARM中的定义是 这意味着该指令需要即时
  • 为 ARM 交叉编译 zlib

    我尝试为arm poky linux gnueabi交叉编译zlib 但启动 make 时出现错误 zlib 1 2 11 AR HOST ar CC HOST gcc RANLIB HOST ranlib configure prefix
  • 如何在 Android 设备上运行 VS Code [重复]

    这个问题在这里已经有答案了 我有 Galaxy Tab S6 它具有替代笔记本电脑的很酷的功能 例如连接鼠标和键盘 但不幸的是它运行 Android 操作系统 并且没有很多开发应用程序可用于 Android 所以我想是否有一个选项可以在至少
  • 交叉编译 Qt 4.7 时出现“非法指令”

    我已经在这个问题上苦苦挣扎了一个多星期了 但仍然找不到解决方案 我正在尝试为 ARM 设备交叉编译 Qt 4 7 嵌入式开源版本 构建过程本身可以顺利完成 但生成的二进制文件似乎包含处理器无法理解的指令 构建主机是 i386 上的 Debi
  • 有没有办法在 Xcode 4 中为 ARM 而不是 Thumb 进行编译?

    如果有很多浮点运算正在进行 Apple 建议针对 ARM 进行编译 而不是针对拇指进行编译 我的整个应用程序几乎是一个大型浮点运算 iOS 应用程序开发工作流程指南中是这样说的 iOS 设备支持两种指令集 ARM 和 Thumb Xcode
  • 在linux x86平台上学习ARM所需的工具[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有一个 x86 linux 机器 在阅读一些关于 ARM 的各种信息时 我很好奇 现在我想花一些时间学
  • 基于 Windows 8 ARM 的平板电脑上的 VB6

    随着 Windows 8 将支持 VB6 我的问题是 Microsoft 是否在任何地方表示 是或否 VB6 应用程序将在基于 ARM 的平板电脑上运行 如果没有 是否有任何 ARM 模拟器 以便我们可以在 Windows 8 ARM 平板
  • DS-5:什么是 FVP、RTSM、基础模型、AEM 模型、快速模型、CADI?

    DS 5 模拟器使用了很多术语 如 FVP RTSM 快速模型 基础模型 AEM 模型 CADI Arm的文档中提供的解释不是很清楚 这些术语的含义是什么 作为 DS 5 的最终用户我应该关心哪些术语 Model 软件模拟的行业术语 就 A
  • arm-linux-gnueabi 编译器选项

    我在用 ARM Linux gnueabi gcc在 Linux 中为 ARM 处理器编译 C 程序 但是 我不确定它编译的默认 ARM 模式是什么 例如 对于 C 代码 test c unsigned int main return 0x
  • 架构armv7的重复符号

    尝试在我现有的应用程序中使用 Layar SDK 时出现以下错误 我该如何解决这个问题 Ld Users pnawale Library Developer Xcode DerivedData hub afxxzaqisdfliwbzxbi

随机推荐

  • 【设计模式】23种设计模式之七大原则

    设计模式 23种设计模式之七大原则 什么是设计模式的原则 1 单一职责原则 基本介绍 案例分析 注意事项 2 接口隔离原则 基本介绍 案例分析 代码实现 3 依赖倒转原则 基本介绍 案例分析 依赖传递的三种方式 注意事项 4 里氏替换原则
  • spdlog使用示例

    Copyright c 2015 Gabi Melman Distributed under the MIT License http opensource org licenses MIT spdlog usage example 参考文
  • tensorflow 默认图和自定义图

    graph1 TF Graph with graph1 as default 在这个代码块里使用的是新创建的graph1 d TF constant 10 11 12 13 dtype TF int32 此时默认的graph 就是graph
  • OSI七层模型、TCP/IP四层模型(超详细!!!!!)

    OSI七层模型 七层模型 亦称OSI Open System Interconnection 参考模型是国际标准化组织 ISO 制定的一个用于计算机或通信系统间互联的标准体系 一般称为OSI参考模型或七层模型 它是一个七层的 抽象的模型体
  • cuda,nvidia-driver ,cudnn下载地址及版本对应

    1 cuda CUDA Toolkit 11 5 Downloads NVIDIA Developer 右下角可下载先前版本 2 nvidia driver https www nvidia cn Download index aspx l
  • 主数据管理系统(MDM)调研总结!!!

    文章目录 一 引言 1 1 主数据背景 1 2 主数据定义 1 3 主数据管理 1 3 1 什么是主数据管理系统 1 3 2 主数据管理的两体系一工具 1 3 3 主数据管理的挑战 1 4 主数据与其它数据的关系 1 4 1 主数据与元数据
  • Mybatis知识总结(三):Crud的实现,Mybatis的参数和输出及配置文件

    一 知识复习 1 1 自定义流程再分析 1 2 mybatis 环境搭建步骤 第一步 创建 maven 工程 第二步 导入maven坐标 第三步 编写必要代码 实体类和持久层接口 第四步 编写 SqlMapConfig xml 第五步 编写
  • 【EDA Tools】Spyglass 检查 Verilog 和 SystemVerilog 混合语言及 Lint 检查

    目录 写在前面 读入设计 发现问题并解决 Lint 检查 写在前面 Spyglass可以用于检查混合设计中的语言互操作性和一致性问题 对于设计中包含多种硬件描述语言的情况 Spyglass 能够识别并解析其中的模块及其互连 并对其进行验证
  • 前端要懂的色域知识

    前端也要面对 五彩斑斓的红 这种世纪难题了吗 rgb 255 0 0 真的是红色吗 现在有个 CSS 色值 rgb 255 0 0 请问一下各位 在网页上展示的是什么颜色 各位可能不用思考就马上能够脱口而出 红色 But 各位有没有想过 这
  • 【Redis从入门到进阶】第 2 讲:Jedis 的快速掌握

    本文已收录于专栏 Redis从入门到进阶 专栏前言 本专栏开启 目的在于帮助大家更好的掌握学习Redis 同时也是为了记录我自己学习Redis的过程 将会从基础的数据类型开始记录 直到一些更多的应用 如缓存击穿还有分布式锁等 希望大家有问题
  • Unity接入腾讯广告/腾讯联盟/优量汇SDK操作步骤——源码+图文效果详情

    Unity接入腾讯广告 腾讯联盟 优量汇SDK操作步骤 源码 图文效果详情 前言 一 下载SDK 二 官网注册相关项目信息 1 新建媒体 2 新建广告位 三 更改代码 1 更改初始化SDK的代码 2 更改对应的ID 总结 版权声明 前言 最
  • k8s部署springboot

    前言 首先以SpringBoot应用为例介绍一下k8s的部署步骤 1 从代码仓库下载代码 比如GitLab 2 接着是进行打包 比如使用Maven 3 编写Dockerfile文件 把步骤2产生的包制作成镜像 4 上传步骤3的镜像到远程仓库
  • Ubuntu系统在终端中重启与关机

    如果你想保持当前用户的登录而并且使用root用户执行命令 可以输入 su root 即可 输入蜜码 可以运行 shutdown 命令 重启命令 1 reboot 2 shutdown r now 立刻重启 root用户使用 3 shutdo
  • Oracle 按创建时间排序,如果创建时间为空,将记录放置在最后

    oracle处理方式 在oracle中字段为空值时 被认为为最大 可通过 nulls last 将空值放到最后 语法 select from 表名 order by 排序字段 desc nulls last 实战 select from u
  • win10操作系统瘦身之微信减肥法

    很多人发现 win 10的系统盘空间一直在减少 甚至到跳出空间不足红色警告 但是又不知道哪里出问题 系统盘的容量到底被什么给吃了 所以今天就说说系统瘦身中 很管用的一个方法 减少微信的历史记录法 首先看下微信软件某个目录的空间占用情况 图1
  • 给自己的逆向工程阶段性学习感想总结

    想到哪写哪 逆向工程的学习比起近似的pwn来说 还是没那么吃基础的 不过基础知识和能力的牢固程度还是近乎决定了一个re手的上限 自己在这方面还是欠缺了不少 目前最吃亏的一个方面是代码分析能力 或者说算法能力 或者说正向能力 发现在做中难题的
  • Unity3D:角色拾取技术

    工程包下载 Unity3D虚拟现实开发之角色拾取 这个是成品图 角色拾取的原理是 由摄像机与屏幕上鼠标点击的位置确定一条射线 由此射线射向3D世界 最先和此射线相交的物体就是被选中的物体 然后对该物体的操控编写对应的代码即可 具体代码如下
  • 【python基础知识】21.高效偷懒的正确打开方式-毕业篇

    文章目录 前言 明确项目目标 分析过程 拆解项目 逐步执行 代码实现 版本1 0 输入表头 确定模版数据 阶段2 获取 复用模版数据 阶段3 0 写入csv文件 结语 前言 光阴似箭 日月如梭 不知不觉我们来到了Python基础语法课的最后
  • springboot项目启动报错:java.io.EOFException: null

    springboot项目启动时报 java io EOFException null异常 但是不影响功能 可能原因是由于tomcat上次非正常关闭时有一些活动session被持久化 表现为一些临时文件 在重启时 tomcat尝试去恢复这些s
  • ARM(IMX6U)裸机汇编LED驱动实验——驱动编写、编译链接起始地址、烧写bin文件到SD卡中并运行

    参考 Linux之ARM IMX6U 裸机汇编LED驱动实验 驱动编写 作者 一只青木呀 发布时间 2020 08 07 09 13 48 网址 https blog csdn net weixin 45309916 article det