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

嵌入式学习 day47 LED

一、搭建环境

        (1)切换到irq模式

mrs r0,cpsr

bic r0,r0,#(0x1f << 0)

bic r0,r0,#(1 << 7)

orr r0,r0,#(0x12 << 0)

msr cpsr,r0

ldr sp,=0x82000000

        (2)切换到system模式

mrs r0,cpsr

orr r0,r0,#(0x1f << 0)

msr cpsr,r0

ldr sp,=0x84000000

注:cps #<code>:可切换到相应模式

    cpsid i

    cps #0x12

    ldr sp, =0x82000000

    cps #0x1F

    ldr sp, =0x84000000

    cpsie i

二、步骤
        1、查看原理图

        2、步骤

        (1)打开时钟门:查手册CCM,把CCM_CCGR0-CCM_CCGR6的位全部置1

enable_clock:

    ldr r0, =0x020C4068

    mov r1, #0xFFFFFFFF

    str r1, [r0]

    ldr r0, =0x020C406C

    str r1, [r0]  

   

    ldr r0, =0x020C4070

    str r1, [r0]  

   

    ldr r0, =0x020C4074

    str r1, [r0]          

    ldr r0, =0x020C4078

    str r1, [r0]  

    ldr r0, =0x020C407C

    str r1, [r0]          

    ldr r0, =0x020C4080

    str r1, [r0]

    bx lr

        (2)设置复用模式

   ldr r0, =0x020E0068

    mov r1, #0x05

    str r1, [r0]

        (3)调电器属性

  ldr r0, =0x020E02F4

    ldr r1, =0x10B0

    str r1, [r0]

        (4)配置GPIO

 ldr r0, =0x0209C004

    mov r1, #0

    orr r1, r1, #(1 << 3)

    str r1, [r0]

三、代码

        控制led灯的亮灭

.global _start

_start:

    ldr pc, =_reset_handler

    ldr pc, =_undefined_handler

    ldr pc, =_svc_handler

    ldr pc, =_prefetch_handler

    ldr pc, =_data_abort_handler

    ldr pc, =_not_user_handler

    ldr pc, =_irq_handler

    ldr pc, =_fiq_handler  

_undefined_handler:

    ldr pc, =_undefined_handler

_svc_handler:

    ldr pc, =_svc_handler

_prefetch_handler:

    ldr pc, =_prefetch_handler

 _data_abort_handler:

    ldr pc, =_data_abort_handler  

_not_user_handler:

    ldr pc, =_not_user_handler

 _irq_handler:

    ldr pc, =_irq_handler

_fiq_handler:

    ldr pc, =_fiq_handler    

_reset_handler:

    cpsid i

    cps #0x12

    ldr sp, =0x82000000

    cps #0x1F

    ldr sp, =0x84000000

    cpsie i

    bl enable_clock

    bl init_led

    b finished

led_on:

    ldr r0, =0x0209C000

    ldr r1, [r0]

    bic r1, r1, #(1 << 3)

    str r1, [r0]

    bx lr

led_off:

    ldr r0, =0x0209C000

    ldr r1, [r0]

    orr r1, r1, #(1 << 3)

    str r1, [r0]

    bx lr  

asm_delay:

    ldr r0, =0x7FFFF

loop:

    sub r0, r0, #1

    cmp r0, #0

    bgt loop

    bx lr

init_led:

    ldr r0, =0x020E0068

    mov r1, #0x05

    str r1, [r0]

    ldr r0, =0x020E02F4

    ldr r1, =0x10B0

    str r1, [r0]

    ldr r0, =0x0209C004

    mov r1, #0

    orr r1, r1, #(1 << 3)

    str r1, [r0]

    bx lr

enable_clock:

    ldr r0, =0x020C4068

    mov r1, #0xFFFFFFFF

    str r1, [r0]

    ldr r0, =0x020C406C

    str r1, [r0]  

   

    ldr r0, =0x020C4070

    str r1, [r0]  

   

    ldr r0, =0x020C4074

    str r1, [r0]          

    ldr r0, =0x020C4078

    str r1, [r0]  

    ldr r0, =0x020C407C

    str r1, [r0]          

    ldr r0, =0x020C4080

    str r1, [r0]

    bx lr


finished:

    bl led_on

    bl asm_delay

    bl led_off

    bl asm_delay

    b finished    

四、编译
        1、交叉编译环境

        与Keil下不同,Keil下是不存在I.MX这个器件的。飞思卡尔现在属于NXP,之前的飞思卡尔被NXP收购了。但是在LMX推出的时候,还没有完成这个收购。我们需要在Ubuntu(PC)下编译出I.MX(ARM)可以运行的程序,这种编译环境称为交叉编译环境。使用的编译工具称为交叉工具链,总结一下
就是:
1)它肯定是一个 GCC 编译器;
2)这个 GCC 编译器是运行在 X86 架构的 PC 上的;
3)这个GCC 编译器是编译ARM架构代码的,也就是编译出来的可执行文件是在ARM芯片上运行的。

        2、交叉编译环境的搭建

        使用FileZillaClient将交叉工具链压缩文件gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-
gnueabihf.tar.xz上传到Ubuntu的家自录下,并创建自录/usr/local/arm。将压缩文件拷贝到这个新建的文件夹下并解压缩。
sudo mkdir /usr/local/arm
sudo cp gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz /usr/local/arm/ -f
sudo tar -vxf gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz
到目前我们已经按照好了交叉编译工具链的必要文件,,由于我们使用的Ubuntu之前安装过更古老版本的交叉工真链,我们必须先把原来那个屏蔽掉。方法是打开家目录下的.bashrc文件,找到exportPATH=$PATH:/home/linux/tools/opt/FriendlyARM/toolschain/4.4.3/bin并删除这一行。再将我们新安装的工具链启用起来,方法是:
sudo vi /etc/profile
·        在文件末尾添加export PATH=$PATH:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin
重启Ubuntu,输入arm-linux-gnueabihf-gcc-V,能看到4.9.4字样,说明新工具链安装成功。

注:ftp工具:

      接下来的工作我们经常要把文件从Windows拷贝到Ubuntu去,这里我们使用一个称为FileZilla
Client的工真。它是一个Windows系统下免费的ftp工真,但是需要手动配置Ubuntu的ftp服务。步骤如下:
1) sudo apt-get install vsftpd ;
2)下载完成后用Vl 命令打开/etc/vsftpd.conf;
3)找到local_enable=YES write_enable=YES确保这两行之前没有 #;
4)最后重启ftp服务,sudo /etc/init.d/vsftpd restart 。
首先使用FileZilla_Client填入Ubuntu的IP地址、用户名和密码,端口可不填。之后就可以方便地在Windows和Ubuntu之间进行互传文件了。接下来就可以把之前写号的ledasm.s文件上传到Ubuntu上了,这里强烈建议各位为每个实验创建独立的文件夹,例如在Ubuntu下的家目录中创建一个IMX文件夹,从Windows上传的led.s提前放入一个Led_asm文件夹中,之后将该文件夹整体上传到Ubuntu。  

        3、编译流程

        (1) 使用arm-linux-gnueabihf-gcc编译文件
有了工具链,就可以编译我们led_asm.s文件了,命令为:

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


其中“-g”选项是产生调试信息,GDB 能够使用这些调试信息进行代码调试。“-c”选项是编译源
文件,但是不链接。“-o”选项是指定编译产生的文件名字,这里我们指定  start.s 编译完成以后的文件名字为 start.o。执行上述命令以后就会编译生成一个 start.o 文件。
(2)使用arm-linux-gnueabihf-ld 链接文件
上面的led.o 文件并不是我们可以下载到开发板中运行的文件,一个工程中所有的  C文件和汇编文件都会编译生成一个对应的.o 文件,我们需要将这.o 文件链接起来组合成可执行文件。确定了链接地址以后就可以使用 arm-linux-gnueabihf-ld 来将前面编译出来的 led.o 文件链接到 
0X87800000 这个地址,使用如下命令:

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


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

        ①链接:我们使用的Keil是一种IDE,这种集成开发环境其实组合了编译和链接为一体,不需要手动操作。

        ②存储地址:就是可执行文件存储在哪里,可执行文件的存储地址可以随意选择。

        ③运行地址:就是代码运行的时候所处的地址,这个我们在链接的时候就已经确定好了,代码要运行,那就必须处于运行地址处,否则代码肯定运行出错

        比如:I.MX6U 支持 SD 卡、EMMC、NAND 启动,因此代码可以存储到 SD 卡、EMMC 或者 NAND 中,但是要运行的话就必须将代码从 SD 卡、EMMC 或者NAND 中拷贝到其运行地址(链接地址)处。

        注:“存储地址”和“运行地址”可能是一样的,比如STM32 的存储起始地址和运行起始地址都是0X08000000。

        (3)用arm-linux-gnueabihf-objcopy 格式转换 

         led.elf 文件也不是我们最终烧写到 SD 卡中的可执行文件,我们要烧写的.bin 文件,因此还需要将 led.elf 文件转换为.bin 文件,这里我们就需要用到 arm-linux-gnueabihf-objcopy 这个工具
了。 arm-linux-gnueabihf-objcopy 更像一个格式转换工具,我们需要用它将  start.elf 文件转换为
start.bin 文件,命令如下:

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

上述命令中,“-O”选项指定以什么格式输出,后面的“binary”表示以二进制格式输出,选项“-S”表示不要复制源文件中的重定位信息和符号信息,“-g”表示不复制源文件中的调试信息。上述命令执行完成以后,就会在工程目录下多一个 start.bin 文件。至此我们终于等到了想要的东西—start.bin 文件。

        (4)使用arm-linux-gnueabihf-objdump 反汇编

        大多数情况下我们都是用  C 语言写试验例程的,有时候需要查看其汇编代码来调试代码,因此就需要进行反汇编,当然这个工作目前对于我们不是必须的。一般来说可以将 elf 文件反汇编,比如如下命令:

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

上述代码中的“-D”选项表示反汇编所有的段,反汇编完成以后就会在当前目录下出现一个名为  led.dis 文件。我们可以打开这个文件,查看其中的内容可以发现这里面都是汇编代码。注意通过  led.dis 这个反汇编文件可以明显的看出我们的代码已经链接到了以 0X87800000 为起始地址的区域。

注:Makefile:

COMPILER = arm-linux-gnueabihf-

CC = $(COMPILER)gcc

LD = $(COMPILER)ld

OBJCOPY = $(COMPILER)objcopy

OBJDUMP = $(COMPILER)objdump

start.bin:start.S

    $(CC) -g -c start.S -o start.o

    $(LD) -Ttext 0x87800000 start.o -ostart.elf

    $(OBJCOPY) -O binary -S -g start.elf start.bin

    $(OBJDUMP) -D start.elf > start.dis

clean:

    rm start.elf start.o start.bin start.dis -f

        4、烧写程序

      (1)原因:我们学习 STM32 等其他的单片机的时候,编译完代码以后可以直接通过 Keil下载到内部的 flash中。但是 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 中。

        (2)步骤:

        ①首先将工具拷贝到工程目录下并添加运行权限。之后准备一张新的  SD(TF)卡,确保  SD 卡里面没有有用的数据,因为我们在烧写代码的时候可能会格式化  SD 卡。

        ②Ubuntu 下所有的设备文件都在目录“/dev”里面,所以插上  SD 卡以后也会出现在“/dev”里面,其中存储设备都是以“/dev/sd”开头的。我们要先看一下不插 SD 卡的时候电脑都有哪些存储设备,以防插入 SD 卡以后分不清谁是谁。输入如下所示命令:ls /dev/sd* 。例如我这里看到的结果是/dev/sda  /dev/sda1  /dev/sda2  /dev/sda3 四个文件,分别代表Ubuntu下的磁盘和三个分区。使用读卡器将 SD 卡插到电脑,一定要确保 SD 卡是挂载到了 Ubuntu 系统中,而不是  Windows下。

        ③再次使用上述命令,我这里看到的是/dev/sda  /dev/sda1  /dev/sda2 /dev/sda3  /dev/sdb   /dev/sdb1 多出的两个文件就是sd卡及其分区了。

        ④我们要做的就是把led.bin文件烧写到sd卡里去。使用命令./imxdownload led.bin /dev/sdb 。注意千万不能写成./imxdownload led.bin/dev/sda,sda是系统磁盘,会造成Ubuntu损坏的!

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

注:烧写的最后一行会显示烧写大小、用时和速度,比如 led.bin 烧写到 SD 卡中的大小是 3.2KB,用时 0.0160821s,烧写速度是 201KB/s,注意这个烧写速度,如果这个烧写速度在几百 KB/s 以下那么就是正常烧写。如果这个烧写速度大于几十 MB/s、甚至几百 MB/s 那么肯定是烧写失败了。解决方法就是重新插拔 SD 卡,一般出现这种情况,重新插拔 SD 卡基本没啥用,只有重启Ubuntu。

        5、运行程序

        代码已经烧写到了 SD 卡中了,接下来就是将 SD 卡插到开发板的 SD 卡槽中,然后设置拨
码开关为 SD 卡启动,拨码开关设置如图。之后打开电源,可以看到用户Led已经被点亮。

http://www.dtcms.com/a/322196.html

相关文章:

  • ctfshow_萌新web9-web15-----rce
  • AJAX与axios框架
  • Vuex 数据共享
  • v-model双向绑定指令
  • Overleaf单栏双栏排版技巧
  • MWORKS 2025b:里程碑升级,Sysblock全栈替代,开启AI4MWORKS智能工程
  • F I R S T Q U A R T E R 2 0 2 5 - - M a y 2 2 2 0 2 5
  • 什么是Serverless(无服务器架构)
  • 数据结构---二叉树(概念、特点、分类、特性、读取顺序、例题)、gdb调试指令、时间复杂度(概念、大O符号法、分类)
  • Qwen Agent 入门介绍与简单使用示例
  • 基于STM32单片机的OneNet物联网环境检测系统
  • Vue 路由跳转
  • Vue3生命周期
  • ZK首次连接失败,第二次连接成功的问题解决方案
  • AI入门学习--如何对RAG测试
  • Flutter开发 Switch、SwitchListTile的基本使用
  • 嵌入式LINUX—————系统编程
  • Javascript中的一些常见设计模式
  • 小程序中使用echarts(2025/8/8)
  • 最近看到的提示词相关内容汇总
  • Document Picture-in-Picture API拥抱全新浮窗体验[参考:window.open]
  • K-Means 聚类
  • 液体泄漏识别误报率↓76%:陌讯多模态融合算法实战解析
  • 94、【OS】【Nuttx】【构建】cmake 配置介绍
  • 【Linux】Linux增删改查命令大全(附频率评级)
  • 批量将NC格式数据转换为TIF格式:解决转换后图像颠倒、镜像、翻转等问题
  • 深度剖析主流AI大模型的编程语言与架构选择:行业实践与技术细节解读
  • Uipath Studio中爬取网页信息
  • 安装CST时,报错问题处理
  • 几个概率分布在机器学习应用示例