OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4635|回复: 2

阿尔法Linux开发板----Linux学习笔记二:裸机开发篇

[复制链接]

23

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
365
金钱
365
注册时间
2018-3-21
在线时间
64 小时
发表于 2020-8-27 19:04:43 | 显示全部楼层 |阅读模式
本帖最后由 随风飘动 于 2020-9-7 20:43 编辑

经过上一轮的学习,安装教程基本熟悉了第一篇的内容,接下来开始进入正轨,裸机的开发,计划一个半月时间看能不能基本学完
2020-08-27----------2020-10-01暂定这个时间


2020-08-27:wsqxfx

一、开发环境的搭建
1、文件互传FTP
1.1开启Ubuntu下的FTP服务:sudo apt-get install vsftpd,安装完了之后打开;sudo vi /etc/vsftpd.conf;打开之后将local_enable=YES,write_enable=Yes打开,如果有注释的话,去掉#。我的就有注释的,去掉之后保存。
图片1.png
保存之后重启:sudo  /etc/init.d/vsftpd restart
最后我自己查了一下安装成功没:vsftpd -v
图片2.png

1.2 windowsFTP客户端安装:FileZilla
这个安装的时间超级长,不知道什么原因一直让我在等待它。左盟主提供的软件包等了十几分钟按照都不行,不等了,我自己去官网下载了,教程上也提供了。下载的可执行包
Ubuntu作为FTP的服务器,FileZilla作为FTP的客户端,客户端需要连接到服务器上
按照左盟主的教程按照即可,修改的IP地址,ifcongfig查看一下即可,最终字符设置为UTF8就可以了,按照过程没有什么问题
2、UbuntuNFS(网络文件系统)和SSHsecure shell protocol)也是传数据,包括对数据的加密等操作)服务开启
   2.1 安装NFS服务,,之后创建文件夹nfs,以后可以在开发板上通过网络文件系统来访问nfs文件夹,首先配置nfs, sudo vi /etc/exports,然后添加你的nfs文件夹所在的位置
图片3.png
然后重启:sudo /etc/init.d/nfs-kernel-server restart

  2.2 SSH服务开启:开启之后可以在Windows下使用终端软件登录到Ubuntu,例如secure-CRT.secure shell protocol.
安装:sudo apt-get install openssh-server
Ssh的配置文件在/etc/ssh/sshd_config

3Ubuntu交叉编译工具链安装
交叉编译器:在一个架构上编译另一个架构的代码,我们是在X86架构的PC上要编译ARM架构的代码,所以就需要可以编译arm架构代码的gcc编译器。
安装的时候需要根据自己的系统去选择安装包,通过fileZilla复制到服务器上,最后解压,按照教程走没啥问题,我遇到的问题还是自己不小心,最后设置路径的时候一定不要打错了,不然总是提示找不到安装的交叉编译器:export PATH=$PATH:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin
我就是因为把USR---USER所以有问题,还是要仔细。
4sourceinsight安装:我以前常用,跳过
5VSCode安装:我以前也常用,主要是安装Linux下的vscode.插件介绍的真好,风格好看
64.6等待晚上回家去看了,emmmmmmmm


2020.8.31号:wsqxfx
1、secureCRT安装之后破解码破解不了,网上的用不了稍后处理
2、开发板的介绍我自己看了,就不写进去了
重点:
1、ARM汇编基础:对于大部分cortex-A系列的芯片,芯片上电以后C语言的环境还没准备好,所以第一行程序肯定是汇编,至于写多少汇编,看到哪一步能把C语言环境准备好,


2、GNU汇编语法:GNU汇编语法适用于所有的架构,并不是ARM独享的,GNU汇编由一系列的语句组成,每行一条语句,每条语句有三个可选部分,如下:
Labelinstruction@comment
Label:标号,表示地址的位置,有些指令前面可能有标号,可以通过标号得到指令的地址,标号也可以表示数据的地址,任何以“:”结尾的标识符都会被识别为一个标号。
Instruction:指令,也就是 汇编指令或者伪指令
Comment:注释内容 @// /**/意义一样
例如 add(标号):MOVS R0,#0x12(指令) @R0设置为0x12(注释)
注意!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ARM中的指令,伪指令,伪操作,寄存器名等可以全部使用大写,也可以全部使用小写,不能大小混写。

3、用户可以使用.section伪操作来定义一个段,汇编系统预定义了一些段名:
   .text代码段 .data初始化的数据段 .bss未初始化的数据段 .rodata只读的数据段
   汇编程序的默认入口标号是start
   .global _start
   _start:
        Ldr r0,=0x12 @r0=0x12
   .global是伪操作,将_start设置为全局标号,常见的伪操作有
   .byte  定义单字节数据:.byte 0x12
   .short 定义双字节数据:.byte 0x1212
   .long  定义四字节数据:.byte 0x12123434
   .equ  赋值语句  .equ num,0x12
   .align 数据字节对齐 .align 4 表示4字节对齐
   .end  便是源文件结束
   .global 定义一个全局符号,格式 .global symbol  .global _start
   上面这些就是最基本的伪操作了

4、GNU汇编支持函数,函数格式如下,返回语句不是必须的
   函数名:
          函数体
          返回语句 bx xx
例子:中断服务函数
//未定义终端
Undefined_Handler:
      LDR R0,=Undefined_Handler
      bx R0
//SVC中断
SVC_Handler:
  LDR R0,=SVC_Handler
  bx R0
//预取终止函数
PrefAbort_Handler:
     LDR R0,=PrefAbort_Handler
bx R0

5、常用汇编指令(暂时学习到7.2.4
1、处理器内部数据传输指令
   处理器最多的事情就是在处理器内部来回的传递数据,常见的操作:
1、将数据从一个寄存器传递到另一个寄存器 MOV R0,R1
2、将数据从一个寄存器传递到特殊寄存器,如CPSR SPSR寄存器
   MRS R0,CPSR
   MSR CPSR,R1 R1里面的数据复制到特殊寄存器CPSR
3、将立即数传递到寄存器
   MOV R1,#0X12 @R1=0X12   
2、存储器访问指令
      ARM不能直接访问存储器,比如RAM中的数据,I.MX6UL中的寄存器就是RAM类型的,我们用汇编来配置I.MX6UL的寄存器的时候需要解除存储器访问指令,一般先将要配置的值写入到RX寄存器中,然后借助存储器访问指令将RX中的数据写入到I.MX寄存器中,读取的过程就是相反的。常用的存储器访问指令有两种:LDR STR
  LDR: LDR RX,[RN,#offset] 从存储器RN+offset的位置读取数据存放到RX
  STR: STR RX,[RN,#offset]  RX中的数据存储到RN+offset的位置上

2.1LDR主要是把存储器上的数据加载到寄存器中,LDR也可以将一个立即数加载到寄存器RX中,LDR加载立即数是“=”,不是“#”。
LDR R0,=0X0209C004@将寄存器地址加载R0中,即R0=0X0209C004
LDR R1,[R0]@读取R0地址的数据保存到R1

2.2STR将数据写入到寄存器中。
LDR R0,=0X0209C004@将寄存器地址加载R0
LDR R1,=0X20002000@将想写入的值加载到R1
STR R1,[R0]@R1的值写到R0地址中


3、入栈和出栈指令
   3.1、通常我们会在A函数中调用B函数,当B函数执行完以后再回到A函数继续执行,要想在调回A函数的时候还能够正常运行,就必须在跳到B函数之前将当前处理器状态保存起来,(就是保存R0~R15这些寄存器),当B函数执行完之后再恢复这些寄存器的值即可,保护寄存器需要入栈,恢复寄存器需要出栈,利用当前的栈指针SP来生成地址,处理器的堆栈是向下增长的。
   3.2PUSH<R0~R3,R12>@R0~R3,R12压栈
        PUSH<LR>@LR入栈
        出栈的就是从栈顶出栈,也就是常说的先进后出,
        POP<LR>
        POP<R0~R3,R12>
   3.3PUSH STMFD SP!
        POP LDMFD SP!
        这上面是PUSHPOP的另外一种写法,所以入栈和出栈的操作还可以写成:
       STMFD SP!,{R0~R3,R12}  @R0~R3,R12压栈
       STMFD SP!,{LR}@LR入栈
      LDMFD SP!,{LR}@LR出栈
      LDMFD SP!,{R0~R3,R12}@出栈R0~R3,R12

      STMFD !SP  STMSTR的变化,STR只能存储一个数据,STM存储存储多个
                 FD :FULL descending 满递减的意思
                 SP:栈指针

1、跳转指令
   4.1B指令:这是最简单的跳转指令,B指令会将PC寄存器的值设置为跳转目标地址,一旦执行B指令,ARM处理器就会立即跳转到指定的目标地址。如果要调用的函数不会再返回到原来执行处,那就可以用B指令。最典型的就是汇编初始化C运行环境,然后跳转到C文件的main函数中运行。
   4.2BL指令相比B指令,在跳转之前会在寄存器LR中保存当前PC寄存器值,所以可以通过将LR寄存器的值重新加载到PC中集训从跳转之前的代码运行。跟入栈出栈配合,上面学习的知识
   BBL指令的区别,B是执行了之后就不会回到最初的地方了。
2、算数运算指令
   ADD:加法  ADC:带进位的加法
   SUB:减法   SBC: 带借位的减法
      MUL:乘法
      UDIV:无符号除法
      SDIV:有符号除法
3、逻辑运算指令
   AND:&  按位与
   ORR:|   按位或
   BIC:  BIC Rd,Rn         Rd=Rd&(~Rn) 位清除
   ORN:  ORN Rd,Rn,Rm    Rd=Rn|(Rm)  按位或非?????---是不是写错了
   EOR:   EOR Rd,Rn       Rd=Rd^RN  按位异或
图片4.png
是不是文档写错了,后续查一下,应该是写错了吧。

2020-09-02:wsqxfx

学习的方式:第一遍:先看这一章的内容,了解概念问题,第二遍:摘录我认为比较重要的内容做笔记;第三遍:实际上机操作。一个章节大概这样就学习了三遍,基本内容就掌握了。
汇编LED实验总结
1、I.MX6UIo作为GPIO使用,我们需要以下几步
1.1、使能GPIO对应的时钟------18
1.2、设置IOMUXC_SW_MUX_CTR_PAD_XX_XX,设置IO的复用功能,使其复用为GPIO功能-----30
1.3、设置寄存器IOMUXC_SW_PAD_CTR_PAD_XX_XX,设置IO的上下拉、速度等--30
1.4、配置GPIO,设置为输入/输出,是否使能中断,默认输出电平等---26
认真阅读这些寄存器代表的含义,其实也不难

2、汇编程序的编写,这个编写其实也不难,左盟主的教程给的很详细,基本上就是往指定的地址里写进指定的参数。重要的是学习方法
为了编译在ARM开发板上运行的led.o文件,使用了如下命令
2.1.arm-linux-gnueabihf-gcc -g -c led.s -o led.o  -g:调试信息 -c:只编译不链接 -o:指定编译产生的 名字
2.2.arm-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf -Ttext:指定链接的地址 -o:指定链接生成的文件名
2.3.arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin  -O:指定以什么格式输出,到此处我们得到了最终要的led.bin文件,
2.4.arm-linux-gnueabihf-objdump -D led.elf > led.dis  -D:表示反汇编所有的段,led.dis就是汇编文件

3、建立Makefile文件:避免每次都重复编译
代码内容如下
图片5.png
通过make make clean 命令编译、清理工程
4、代码的烧写
学习STM32的时候,编译完的代码可以直接通过MDKIAR下载到内部flash中。I.MX6U虽然内部有96KROM,但是这96KNXP自己用的,不向用户开放。所以相当于I.MX没有内部flash,我们的代码需要地方存放。为此,I.MX6U支持从外置的存储介质中启动,所以我们可以将代码烧写到存储介质中,这些介质中,除了SD卡外,其他一般都是焊接到板子上的,我们没法直接烧写,SD卡是移动的,可以将SD卡插到电脑上,在电脑上将.bin文件烧录到SD卡中,然后插到板子上。量产的时候不可能放到SD卡中,一般存放在其他介质中,比如NOR FLASH NAND FLASH QSPI FLASH .
前面编译的.bin文件不能直接复制到SD卡中,编译出来的可执行文件是怎么存放到SD卡中,存放的位置是什么,这个NXP是有详细规定的,我们必须按照NXP的规定来将代码烧写到SD卡中。否则代码是绝对运行不起来的。
左盟主用的是正点原子编写的软件 将编译出来的.bin文件烧写到SD卡中,软件叫imxdownload,我暂时就用他的,后面搞清楚是按照什么规则的。 -----今晚暂定学习到这里
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

23

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
365
金钱
365
注册时间
2018-3-21
在线时间
64 小时
 楼主| 发表于 2020-8-31 19:31:06 | 显示全部楼层
8.31号:wsqxfx
1、secureCRT安装之后破解码破解不了,网上的用不了稍后处理
2、开发板的介绍我自己看了,就不写进去了
重点:
1、ARM汇编基础:对于大部分cortex-A系列的芯片,芯片上电以后C语言的环境还没准备好,所以第一行程序肯定是汇编,至于写多少汇编,看到哪一步能把C语言环境准备好,


2、GNU汇编语法:GNU汇编语法适用于所有的架构,并不是ARM独享的,GNU汇编由一系列的语句组成,每行一条语句,每条语句有三个可选部分,如下:
Label:instruction@comment
Label:标号,表示地址的位置,有些指令前面可能有标号,可以通过标号得到指令的地址,标号也可以表示数据的地址,任何以“:”结尾的标识符都会被识别为一个标号。
Instruction:指令,也就是 汇编指令或者伪指令
Comment:注释内容 @跟// /**/意义一样
例如 add(标号):MOVS R0,#0x12(指令) @将R0设置为0x12(注释)
注意!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ARM中的指令,伪指令,伪操作,寄存器名等可以全部使用大写,也可以全部使用小写,不能大小混写。

3、用户可以使用.section伪操作来定义一个段,汇编系统预定义了一些段名:
   .text代码段 .data初始化的数据段 .bss未初始化的数据段 .rodata只读的数据段
   汇编程序的默认入口标号是start,
   .global _start
   _start:
        Ldr r0,=0x12 @r0=0x12
   .global是伪操作,将_start设置为全局标号,常见的伪操作有
   .byte  定义单字节数据:.byte 0x12
   .short 定义双字节数据:.byte 0x1212
   .long  定义四字节数据:.byte 0x12123434
   .equ  赋值语句  .equ num,0x12
   .align 数据字节对齐 .align 4 表示4字节对齐
   .end  便是源文件结束
   .global 定义一个全局符号,格式 .global symbol  .global _start
   上面这些就是最基本的伪操作了

4、GNU汇编支持函数,函数格式如下,返回语句不是必须的
   函数名:
          函数体
          返回语句 bx xx
例子:中断服务函数
//未定义终端
Undefined_Handler:
      LDR R0,=Undefined_Handler
      bx R0
//SVC中断
SVC_Handler:
  LDR R0,=SVC_Handler
  bx R0
//预取终止函数
PrefAbort_Handler:
     LDR R0,=PrefAbort_Handler
bx R0

5、常用汇编指令(暂时学习到7.2.4)
1、处理器内部数据传输指令
   处理器最多的事情就是在处理器内部来回的传递数据,常见的操作:
1、将数据从一个寄存器传递到另一个寄存器 MOV R0,R1
2、将数据从一个寄存器传递到特殊寄存器,如CPSR SPSR寄存器
   MRS R0,CPSR
   MSR CPSR,R1 将R1里面的数据复制到特殊寄存器CPSR中
3、将立即数传递到寄存器
   MOV R1,#0X12 @R1=0X12   
2、存储器访问指令
      ARM不能直接访问存储器,比如RAM中的数据,I.MX6UL中的寄存器就是RAM类型的,我们用汇编来配置I.MX6UL的寄存器的时候需要解除存储器访问指令,一般先将要配置的值写入到RX寄存器中,然后借助存储器访问指令将RX中的数据写入到I.MX寄存器中,读取的过程就是相反的。常用的存储器访问指令有两种:LDR STR。
  LDR: LDR RX,[RN,#offset] 从存储器RN+offset的位置读取数据存放到RX中
  STR: STR RX,[RN,#offset]  将RX中的数据存储到RN+offset的位置上
  
2.1、LDR主要是把存储器上的数据加载到寄存器中,LDR也可以将一个立即数加载到寄存器RX中,LDR加载立即数是“=”,不是“#”。
LDR R0,=0X0209C004@将寄存器地址加载R0中,即R0=0X0209C004
LDR R1,[R0]@读取R0地址的数据保存到R1中

2.2、STR将数据写入到寄存器中。
LDR R0,=0X0209C004@将寄存器地址加载R0中
LDR R1,=0X20002000@将想写入的值加载到R1中
STR R1,[R0]@将R1的值写到R0地址中


3、入栈和出栈指令
   3.1、通常我们会在A函数中调用B函数,当B函数执行完以后再回到A函数继续执行,要想在调回A函数的时候还能够正常运行,就必须在跳到B函数之前将当前处理器状态保存起来,(就是保存R0~R15这些寄存器),当B函数执行完之后再恢复这些寄存器的值即可,保护寄存器需要入栈,恢复寄存器需要出栈,利用当前的栈指针SP来生成地址,处理器的堆栈是向下增长的。
   3.2、PUSH<R0~R3,R12>@将R0~R3,R12压栈
        PUSH<LR>@LR入栈
        出栈的就是从栈顶出栈,也就是常说的先进后出,
        POP<LR>
        POP<R0~R3,R12>
   3.3、PUSH STMFD SP!
        POP LDMFD SP!
        这上面是PUSH和POP的另外一种写法,所以入栈和出栈的操作还可以写成:
       STMFD SP!,{R0~R3,R12}  @将R0~R3,R12压栈
       STMFD SP!,{LR}@LR入栈
      LDMFD SP!,{LR}@LR出栈
      LDMFD SP!,{R0~R3,R12}@出栈R0~R3,R12

      STMFD !SP  STM是STR的变化,STR只能存储一个数据,STM存储存储多个
                 FD :FULL descending 满递减的意思
                 SP:栈指针
4、跳转指令
5、算数运算指令
6、逻辑运算指令
回复 支持 反对

使用道具 举报

2

主题

474

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6087
金钱
6087
注册时间
2018-6-27
在线时间
524 小时
发表于 2020-9-4 12:30:15 | 显示全部楼层
学习学习,学习学习。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-26 04:08

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表