嵌入式开发基础二

来源:互联网 发布:西部数码 域名管理 编辑:程序博客网 时间:2024/05/28 11:50
1.嵌入式产品
  手机
2.嵌入式定义
  iphone和低端的诺基亚
3.嵌入式系统的组成部分
  硬件:
      依赖用户需求
      三大件:CPU,内存,闪存
      外围设备:USB口(可以有),串口(必须有),网口(可以有),SD,摄像头,声卡,各种sensors
  软件:
      依赖硬件和用户需求
      嵌入式linux软件包括:bootloader,kernel,rootfs
4.嵌入式linux系统开发的基本模式
  左手PC机:
具备:串口,网口,USB口,linux系统,linux系统还要安装tftp网络服务
  右手开发板:
具备:串口,网口,USB口
        串口:用于双方通信
        网口:主要用于下载
        USB口:主要用于下载
5.嵌入式linux系统软件部署
   嵌入式linux软件组成部分:
  bootloader(BIOS),选在u-boot(属于bootloader一种)
  linux内核(kernel)
  根文件系统(rootfs)
  5.1.bootloader部署
  1.获取要部署的bootloader二进制镜像文件(u-boot.bin)
  2.明确这个软件部署的位置
    一般部署在nand,0地址处,启动方式要以nand启动
    也可以部署在SD卡,在SD卡的512字节以后,要以SD卡
  3.部署的过程
    可以利用USB下载
    可以利用SD下载
    可以利用网络下载
    dnw 20008000 
    或者
    tftp 20008000 u-boot.bin
    nand erase 0 100000
    nand write 20008000
    总结:不管是哪种烧写方法,前提是要运行一个u-boot
  4.网络下载部署的注意事项
    1.保证PC的linux系统安装和启动tftp网络服务
      tftp(简单的文件传输服务)
      sudo apt-get install tftpd-hpa
    2.保证设置好一个共享目录
      /tftpboot
      将来开发板客户端就可以从虚拟机的tftpboot目录下载
    3.保证启动tftp服务
      sudo /etc/init.d/tftpd-hpa restart
    4.利用开发板u-boot的相关tftp命令来部署软件
      tftp 20008000 led.bin      
      go 20008000
      nand erase 0 100000
      nand write 20008000 0 100000
      print
      setenv 
      saveenv
      ping:tftp下载之前一定要记得先ping!
      ping不需要tftp服务!
    5.此时此刻,开发板运行的程序仅仅是u-boot
      还没有运行linux系统,说明以前UC的代码此时此刻不能在开发板上运行起来!
      此时此刻的软件都是裸板程序
    6.裸板程序:
      在无操作系统下运行的软件,它们可以直接对硬件进行访问操作,不许要以文件的形式来访问硬件设备
      在linux系统下必须以文件的形式访问硬件设备!
6.ARM裸板程序的开发
  6.1.明确:
在无操作系统的状态下,软件访问硬件是"直接"访问
  6.2.明确:
在ARM架构下,CPU访问外设都是以地址(指针)的形式访问,如果要访问某个外设,一定要搞清楚外设的基地址,例如TPAD的内存的基地址0x20000000
例如,现在向内存地址0x20000000写入0x55
//int a = 100; //仅仅告诉编译器,从内存某个位置分配4字节的内存,&a就是这块内存的首地址
unsigned long *p = (unsigned long *)0x20000000;
*p = 0x55;
  6.3.明确:
对于S5PV210,32位处理器,CPU寻址的硬件地址范围:
        0x00000000~0xFFFFFFFF;
  6.4.明确:
      “外设”:CPU核以外的任何硬件逻辑单元都是外设
       不仅仅包括肉眼能看到的硬件,还包括处理器内部集成的硬件逻辑单元
  6.5.初识S5PV210处理器
  明确:S5PV210处理器的硬件特性都是在datasheet(芯片手册)--S5PV210_UM_REV1.1.pdf  
        resource/datasheet/S5PV210_UM_REV1.1.pdf
        工作频率:1GHz
        内部集成的外设:
        GPIO控制器
        RTC控制器
        USB控制器
        SD控制器
        NAND控制器
        ...
   6.6.初识TPAD开发板的硬件原理图
核心板的原理图:
CW210_CORE_LHGZ.pdf(融汇光泽)
CW210_CORE_TARENA.pdf(Tarena)
底板的原理图:
CW210-Peripherial.pdf
由硬件工程师提供!
   6.7.外设地址的确定
       对于CPU内部集成的外设,外设的基地址看芯片手册即可
       对于CPU外部的外设,不仅仅要看CPU的芯片手册还要看原理图,以DM9000网卡为例:
       通过原理图和芯片手册发现DM9000网卡的基地址就是0x88000000
       切记:如果不清楚,一定咨询硬件工程师       
7.面试题:谈谈ARM处理器如何某个外设?
  以TPAD的两个LED灯的操作为例
  案例目的:掌握裸板程序中,CPU如何访问某个外设
  具体实施步骤:
  7.1.明确用户的需求
      实现一个流水灯(亮灭亮灭...)
  7.2.明确两个LED的硬件操作特性
  宏观看:大致看LED灯在开发板的位置
 利用万用表测试LED的电源和底是否连接正确
  细微看:看原理图,看LED在原理图的硬件连接方式
  先看底板原理,找到LED灯硬件位置
  7.3.通过原理图获取LED的硬件操作特性
      第一个LED的开关由CPU的GPC1_3来决定
      第二个LED的开关由CPU的GPC1_4来决定
      GPC1_3/4输出高电平,灯亮
      GPC1_3/4输出低电平,灯灭
      问:GPC1_3/4的名如何起?
  7.4.S5PV210的IO(input/output)管脚的特性
      S5PV210的IO管脚由简称GPIO(通用输入和输出)
      S5PV210包括237个复用GPIO
      “复用”:一个GPIO既可以做输入口,又可以做输出口
                又可以做别的功能的IO口
      同一时刻只能有一个功能!
      S5PV210并且把这些GPIO进行分组:A,B,C...等
      一堆GPIO:
     A组
A0组
   包括8个GPIO
A1组
   包括4个GPIO
     B组
     C组
C0组:5个
 GPC0_0,GPC0_1,GPC0_2,...
C1组:5个      
     ... GPC1_0,GPC1_1,GPC1_2,GPC1_3,GPC1_4


      问:现在研究的问题是由原先的两个LED转变成研究两个GPIO管脚(GPC1_3,GPC1_4),CPU如何操作这两个管脚呢?
      答:CPU通过操作GPIO控制器来间接操作IO的状态
      切记:CPU访问某个GPIO都是通过访问GPIO控制器这个硬件逻辑单元间接访问GPIO
      切记:GPIO控制器对于CPU核就是一个外设!
      切记:就需要明确这个GPIO控制器外设的地址,这个地址只需查看CPU的芯片手册即可
   7.5.GPIO控制器的硬件操作方法
   0."寄存器":像内存一样的硬件,能够存储数据
   1.GPIO控制器的操作都是通过一堆的GPIO的寄存器来进行
     访问操作,例如:
     GPC1_3,GPC1_4对应的寄存器有:
     GPC1CON
     GPC1DAT
     GPC1PUD
     ...
   2.明确:GPIO对应寄存器的基地址
     寄存器名称       物理地址
     GPC1CON      0xE0200080
     GPC1DAT      0xE0200084
     GPC1PUD      0xE0200088
     例如:向GPC1CON寄存器写0x55
     *((volatile unsigned long *)0xE0200080) = 0x55;
     切记:
对于嵌入式软件开发,硬件的访问一定要加volatile
   3.总结:
     CPU访问某个GPIO,是通过访问对应的寄存器来进行
   4.以GPC1_3,GPC1_4对应的寄存器为例(P141)
     GPC1CON特点:
GPC1组的配置寄存器,用于配置GPIO的工作模式
可以配置为输入或者输出或者中断或者别的或者保留
对于LED应该配置为输出口
基地址0xE0200080
         可读,可写
         有效位数为20bit位
GPC1_3对应的bit位为:BIT[12:15]
         GPC1_4对应的bit位为:BIT[16:19]
4bit对应一个GPIO
    GPC1DAT特点:
数据寄存器,用于保存GPIO的状态(高/低电平)
例如:如果作为输出口,如果寄存器对应的bit的值为1,表示这个GPIO将输出高电平,否则低电平
基地址0xE0200084
可读,可写
有效的位数为5位
         GPC1_3对应的bit位为:BIT[3]
GPC1_4对应的bit位为:BIT[4]
         例如:
BIT[3] = 1,GPC1_3输出高电平
         BIT[4] = 0,GPC1_4输出低电平
    GPC1PUD[n]特点:
n表示对应的GPIO编号(0,1,2,3,4)
上/下拉电阻配置寄存器
基地址0xE0200088
        可读,可写
  有效的位数为10
GPC1_3对应的bit位为:BIT[6:7]
GPC1_4对应的bit位为:BIT[8:9]
例如:
BIT[6:7] = 00:禁止上下拉电阻功能
BIT[6:7] = 01:使能下拉电阻功能
        BIT[6:7] = 10:使能上拉电阻功能
...
    "上拉电阻":如果GPIO连接一个上拉电阻,会让GPIO的状态默认设置为高电平
    "下拉电阻":
    "GPIO悬空":不外接任何设备或者即使连接了某个外设
也不确定GPIO的状态到底是高还是低
    "默认":CPU不操作,外设也操作GPIO,此时上/下拉电阻操作,设置为高或者低
   7.6.编写裸板代码(无操作系统)
   裸板程序的主要功能实现流水灯
   编码实施步骤:
   PC虚拟机中执行:
   1.将/opt/目录的用户和组改为tarena用户和tarena组
     sudo chown tarena /opt -R
     sudo chgrp tarena /opt -R
   2.创建ARM裸板代码的存放目录
     mkdir /opt/arm/day03/1.0 -p
     cd /opt/arm/day03/1.0 
   3.vim led.c
     硬件寄存器的操作原则:
     1.只能修改对应的BIT位,其余位不能乱改
     2.先读取寄存器数据,
     3.修改读取的数据
     4.修改完毕再写回
     保存退出
   4.交叉编译led.c
     "交叉编译":在PC机上编译源码,源码运行在ARM平台上
     此时不能用gcc编译器编译,gcc针对于X86架构
   5.虚拟机中添加设置交叉编译器(arm-linux-gcc)的环境变量,arm-linux-gcc针对于ARM架构
   6.获取交叉编译器
     ftp://ARM/resource.rar/arm gcc编译器/
    arm-2009q3.tar.bz2  
     拷贝到虚拟机的/opt/目录下
     cp arm-2009q3.tar.bz2 /opt
     cd /opt
     tar -xvf arm-2009q3.tar.bz2
     rm arm-2009q3.tar.bz2
     sudo vim /etc/environment //在环境变量中添加交叉编译器的命令支持     
     PATH="/opt/arm-2009q3/bin:...
     也就是在PATH中添加/opt/arm-2009q3/bin的路径
     将来在终端中直接输入arm-linux-gcc即可使用!
     保存退出
     重启虚拟机
     重启以后验证交叉编译器是否能正常使用:
     arm-linux-gcc -v //查看编译器的版本是否为4.4.1
   7.交叉编译led.c
     cd /opt/arm/day03/1.0
     arm-linux-gcc -nostdlib -c led.c -o led.o
     arm-linux-ld -nostartfiles -nostdlib 
       -Ttext=0x20008000 -eled_test led.o -o led.elf
     arm-linux-objcopy -O binary led.elf led.bin
     cp led.bin /tftpboot
   8.进入开发板的u-boot命令行模式,执行:
     tftp 20008000 led.bin
     go 20008000
   9.有些同学的板子的GPIO不是GPC1_3/GPC1_4(Tarena)
     而是GPC0_3/GPC0_4(融慧广泽)
  10.添加GPC1_4(LED2)的开关操作
  11.温习arm-linux-gcc或者gcc编译的过程
     预处理->汇编->编译->链接
     以交叉编译led.c为例:
     1.预处理
       cd /opt/arm/day03/1.0
       arm-linux-gcc -E led.c -o led.i
       生成预处理文件led.i
     2.汇编
       arm-linux-gcc -nostdlib -S led.i -o led.s
       生成汇编文件led.s
     3.编译(不连接标准C库)
       arm-linux-as led.s -o led.o
     4.连接
      明确一般应用程序的main函数都是标准C库的启动代码来调用! 
      明确:程序一般包括代码段,数据段,BSS段
      ELF文件格式:
ELF文件头
原始二进制代码
ELF文件尾
      arm-linux-ld -nostartfiles -nostdlib 
       -Ttext=0x20008000 -eled_test led.o -o led.elf
      -nostartfiles:链接时不需要添加启动文件
      -nostdlib:链接时不需要链接标准库  
      -Ttext=0x20008000:指定代码段的起始地址为0x20008000(内存地址)
      -eled_test:指定程序的入口为led_test,仅仅是消除一个警告而已,没有实质意义
      -o led.elf:最终生成一个ELF格式的文件
      注意:ELF格式的文件只能在linux系统下运行
   不能再裸板上运行,需要获取其中的原始二进制文件信息
     5.如果是裸板,需要对ELF进行处理获取最终的二进制文件
       arm-linux-objcopy -O binary led.elf led.bin
       cp led.bin /tftpboot
       开发板测试          
     6.注意:
     arm-linux-gcc -nostdlib -c led.c -o led.o
     等价于1+2+3三个步骤
    问:为什么不能将delay定义放在led_test的前面
    答:
    正常情况(delay函数定义在led_test后面):
    arm-linux-gcc -nostdlib -c led.c -o led.o
    arm-linux-ld -nostartfiles -nostdlib 
       -Ttext=0x20008000 -eled_test led.o -o led.elf
    反汇编led.elf:
    arm-linux-objdump -D led.elf > led.dis
    vim led.dis
    Disassembly of section .text: //表示代码段的开始
    20008000 <led_test>: 
  //led_test函数的地址0x20008000
    起始地址         机器码(CPU)  汇编指令(人)
    20008000:       e92d4800 等价 push  {    fp, lr}
    异常情况(delay函数定义放在led_test前面):
    arm-linux-gcc -nostdlib -c led.c -o led.o
    arm-linux-ld -nostartfiles -nostdlib 
       -Ttext=0x20008000 -eled_test led.o -o led.elf
    反汇编led.elf:
    arm-linux-objdump -D led.elf > led.dis
    vim led.dis

    Disassembly of section .text: //表示代码段的开始   

蜂鸣器提示:

    1.明确用户的需求:响~不响
    2.了解蜂鸣器的硬件工作特性
      查看底板原理图和芯片手册
      注意:要连接号电源的跳帽
    3.XpwmTOUT1是CPU的某个管脚
    4.在底板原理图上搜索XpwmTOUT1,找到插座位J1D
    5.打开核心板的原理图CW210_CORE_TARENA.pdf
    6.在核心板原理图上搜索J1D
    7.在核心板原理图上搜索XpwmTOUT1,会搜索一下信息:
      XpwmTOUT1/GPD0_1:表名这个GPIO是复用的
      即可用于XpwmTOUT1也可以用于普通的输入和输入(GPD0_1)
    8.GPD0_1输出高电平,蜂鸣器响,否则不响








原创粉丝点击