• 【Embedded System】裸机接口开发


    💘ARM Embedded System,欢迎关注我的Gitee

    💦S5PV210特性

    在这里插入图片描述
      S5PV210拥有一个外部存储器接口。DRAM控制器支持LPDDR1、DDR2或LPDDR2。Flash/ROM端口支持NAND Flash、NOR Flash 、OneNAND Flash、SRAM和ROM类型外部存储器。
      为了降低系统总成本和提高整体功能,S5PV210包括许多硬件外设,如TFT24位真彩色LCD控制器、摄像头接口、MIPIDSI、CSI -2、电源管理的系统管理器、ATA接口、4个UART、24通道DMA、5个定时器、通用I/O端口、3个I2S、S/ PDIF、3个(通用)的IIC -B接口、2个HS - SPI、USB2.0、工作在高速(480 Mbit/s)的USB 2.0 OTC主机、SD主机和高速多媒体卡接口、4个PLL时钟产生器。

    💦微处理器的主要特性

      主频能达到1 GHz,工作能耗能低于30 mW,并且性能优化的消费应用要求2000 Dhrystone MIPS。( Dhrystone是测量处理器运算能力的最常见基准程序之一,常用于处理器的整型运算性能的测量。 )
      支持ARM用于超标量处理器技术增强的代码密度和性能,NEON技术用于多媒体和信号处理,Jazelle - RTC技术用于支持提前和及时的Java或其他语言编译。
      Thumb -2技术用于更高技能、能源效率和代码密度。
      TrustZone技术用于安全交易和数字版权管理。
      13级主整数流水线。

    💦ARM指令集

      大部分ARM core 提供:
      -ARM 指令集(32-bit)
      -Thumb 指令集(16-bit )
      -Cortex-A处理器
      -16位和32位Thumb-2指令集
      -16位和32位ThumbEE指令集

    ThumbEE,也就是所谓的Thumb-2EE,业界称为Jazelle RCT技术,于2005年发表,首见于 Cortex-A8 处理器。ThumbEE 提供从 Thumb-2 而来的一些扩充性,在所处的执行环境(Execution Environment)下,使得指令集能特别适用于执行阶段(Runtime)的编码产生(例如即时编译)。Thumb-2EE 是专为一些语言如 Limbo、Java、C#、Perl 和 Python,并能让即时编译器 能够输出更小的编译码却不会影响到效能。

      Jazelle cores 支持 Java bytecode

    💦处理器工作模式

      ARM 有8个基本工作模式:
      User : 非特权模式,大部分任务执行在这种模式
      FIQ : 当一个高优先级(fast) 中断产生时将会进入这种模式
      IRQ : 当一个低优先级(normal) 中断产生时将会进入这种模式
      Supervisor :当复位或软中断指令执行时将会进入这种模式
      Abort : 当存取异常时将会进入这种模式
      Undef : 当执行未定义指令时会进入这种模式
      System : 使用和User模式相同寄存器集的特权模式
      Cortex-A特有模式:
        Monitor : 是为了安全而扩展出的用于执行安全监控代码的模式;
        也是一种特权模式
    在这里插入图片描述
    在这里插入图片描述
      条件位:
        N = Negative result from ALU
        Z = Zero result from ALU
        C = ALU operation Carried out or borrow
        V = ALU operation oVerflowed
      Q 位:
        仅ARM v5TE-J架构支持
        指示饱和状态
      J 位
        仅ARM v5TE-J架构支持
        T=0;J = 1 处理器处于Jazelle状态
      也可以和其他位组合
      DNM位:Do Not Modify
      GE[3:0] 大于或等于(当执行SIMD指令时有效)
      IT[7:2] IF….THEN….指令执行状态位
      E位:大小端控制位
      A位:A=1 禁止不精确的数据异常
      中断禁止位:
        I = 1: 禁止 IRQ.
        F = 1: 禁止 FIQ
        T Bit
        T = 0;J=0; 处理器处于 ARM 状态
        T = 1;J=0 处理器处于 Thumb 状态
        T = 1;J=1 处理器处于 ThumbEE 状态
      Mode位:
      处理器模式位
        10000 User mode; 10001 FIQ mode; 10011 SVC mode;
        10111 Abort mode; 11011 Undfined mode; 11111 System mode;
        10110 Monitor mode; 10010 IRQ

    💦裸机开发环境

    💦交叉编译环境

      这里一般把进行交叉编译的主机称为宿主机,也就是普通的通用计算机,而把程序实际的运行环境称为目标机,也就是嵌入式系统环境。由于一般通用计算机拥有非常丰富的系统资源、使用方便的集成开发环境和调试工具等,而嵌入式系统的系统资源非常紧缺,没有相关的编译工具,因此,嵌入式系统的开发需要借助宿主机来编译出目标机的可执行代码。
    在这里插入图片描述
      交叉编译工具链是为了编译、链接、处理和调试跨平台体系结构的程序代码。对于交叉开发的工具链来说,在文件名称上加了一个前缀,用来区别本地的工具链。例如,arm-linux-表示是对arm的交叉编译工具链;arm-linux-gcc表示是使用gcc的编译器。除了体系结构相关的编译选项以外,其使用方法与Linux主机上的gcc相同,所以Linux编程技术对于嵌入式同样适用。不过,并不是任何一个版本拿来都能用,各种软件包往往存在版本匹配问题。例如,编译内核时需要使用arm-linux-gcc-4.3.3版本的交叉编译工具链,而使用arm-linux-gcc-3.4.1的交叉编译工具链,则会导致编译失败。
      那么gcc和arm-linux-gcc的区别是什么呢?区别就是gcc是linux下的C语言编译器,编译出来的程序在本地执行,而arm-linux-gcc用来在linux下跨平台的C语言编译器,编译出来的程序在目标机(如ARM平台)上执行,嵌入式开发应使用嵌入式交叉编译工具链。
    在这里插入图片描述

    💦交叉链接器

      链接脚本的一个主要目的是描述输入文件中的各个段(数据段,代码段,堆,栈,bss)如何被映射到输出文件中,并控制输出文件的内存排布.
      对于这个例子,假设代码应该被载入到地址0x1000处,而数据应该从0x8000000开始,如下是实现这个功能的脚本:

    SECTIONS
    {
    .=0x1000;
    .text:{*(.text)}
    .=0x8000000;
    .data:{*(.data)}
    .bss:{*(.bss)}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    💦调试方式

    💦交叉调试

      嵌入式软件经过编译和链接后即进入调试阶段,调试是软件开发过程中必不可少的一个环节,嵌入式软件开发过程中的交叉调试与通用软件开发过程中的调试方式有很大的差别。在常见软件开发中,调试器与被调试的程序往往运行在同一台计算机上,调试器是一个单独运行的进程,它通过操作系统提供的调试接口来控制被调试的进程。而在嵌入式软件开发中,调试时采用的是在宿主机和目标机之间进行的交叉调试,调试器仍然运行在宿主机的通用操作系统之上,但被调试的进程却是运行在基于特定硬件平台的嵌入式操作系统中,调试器和被调试进程通过串口或者网络进行通信,调试器可以控制、访问被调试进程,读取被调试进程的当前状态,并能够改变被调试进程的运行状态。
      嵌入式系统的交叉调试有多种方法,主要可分为软件方式和硬件方式两种。它们一般都具有如下一些典型特点。
      调试器和被调试进程运行在不同的机器上,调试器运行在PC或者工作站上(宿主机),而被调试的进程则运行在各种专业调试板上(目标机)。
      调试器通过某种通信方式(串口、并口、网络、JTAG等)控制被调试进程。
      在目标机上一般会具备某种形式的调试代理,它负责与调试器共同配合完成对目标机上运行的进程进行调试。这种调试代理可能是某些支持调试功能的硬件设备,也可能是某些专门的调试软件(如GdbServer)。

    💦软件调试

      软件方式调试主要是通过插入调试桩的方式来进行的。用调试桩方式进行调试是通过目标操作系统和调试器内分别加入某些功能模块,二者互通信息来进行调试。该方式的典型调试器有Gdb调试器。
      这个方案的实质是用软件接管目标机的全部异常处理及部分中断处理,并在其中插入调试端口通信模块,与主机的调试器进行交互。但是它只能在目标机系统初始化完毕、调试通信端口初始化完成后才能起作用,因此,一般只能用于调试运行于目标操作系统之上的应用程序,而不宜用来调试目标操作系统的内核代码及启动代码。而且,它必须改变目标操作系统,因此,也就多了一个不用于正式发布的调试版。
    在这里插入图片描述

    💦采用In-Circuit Debugger (ICD)方式进行硬件交叉调试

      JTAG是1985年指定的检测PCB和IC芯片的一个标准。1990年被修改成为IEEE的一个标准,即IEEE1149.1。JTAG标准所采用的主要技术为边界扫描技术,它的基本思想就是在靠近芯片的输入/输出引脚上增加一个移位寄存器单元。因为这些移位寄存器单元都分布在芯片的边界上(周围),所以被称为边界扫描寄存器(Boundary-Scan Register Cell)。
    当芯片处于调试状态时候,这些边界扫描寄存器可以将芯片和外围的输入/输出隔离开来。通过这些边界扫描寄存器单元,可以实现对芯片输入/输出信号的观察和控制。
      对于芯片的输入引脚,可通过与之相连的边界扫描寄存器单元把信号(数据)加载到该引脚中去;对于芯片的输出引脚,可以通过与之相连的边界扫描寄存器单元“捕获”( Capture)该引脚的输出信号。这样,边界扫描寄存器提供了一个便捷的方式用于观测和控制所需要调试的芯片。
    在这里插入图片描述

    💦裸机程序的开发流程

    💦ARM下裸机开发环境

      裸机是一种通俗的讲法,就是指ARM设备上没有任何现成的程序来支持你的开发的软件运行。它是相对设备上有在操作系统的情况运行可执行程序而言的。
      这两种程序有很大区别。在操作系统环境下,基本上跟桌面程序开发没有太多区别,而裸机程序需要自己初始化硬件环境来运行。因为必须有一小段汇编写的引导代码来初始化,并且直接操作硬件。
      裸机程序一般采用少量汇编加C语言来编译(理论上C++可以了,但比较少)。大型的程序bootloader,实时操作系统uCOS/Nclues严格讲也是裸机程序。

    💦下载文件格式

      ELF
      Linux下标准可执行结构。
      BIN
      bin文件是由ELF转化而来,专门用下载到设备。相对于ELF它有两个变化。第一BIN只有基本的text/bss/data段,没有调试信息。第二。因为bin要下载到设备的。里面各段的地址是按相应地址对齐烧录的。因为两段之间很可能补一些空间的0空间。
      ELF转换为BIN用arm-linux-objcopy 以下语句把elf_name转换成bin_name。
      arm-linux-objcopy -O binary -S elf_name bin_name
      HEX:
      HEX主要是把BIN内容转换成相应的ASCII的文本格式,并且每一行都带下载地址。

    💦实验的开发环境

      在win下开发的eclipse+yougatoo+jlink环境搭建
      一、Eclipse
      Eclipse的本身只是一个框架平台,但是众多插件的支持,使得Eclipse拥有较好的灵活性。
      二、CDT
      CDT是Eclipse用于扩展Eclipse支持C/C++开发的插件。
      三、Zylin CDT
      支持Eclipse用于嵌入式C/C++开发和远程调试的插件
      四、Yagarto
       Yagarto整合了GNU arm的交叉编译工具链,是一个跨平台的 ARM 架构开发平台,是一个 Eclipse 的插件。
      五、J-LINK GDB Server
       A JTAG GDB Debug agent run on Host
    在这里插入图片描述

    💦GPIO编程

    💦GPIO

      GPIO的英文全称为General-Purpose IO ports,也就是通用IO接口。
      许多的设备/电路只要求一位,即只要有开/关两种状态就够了。比如,控制某个LED灯亮与灭,或者通过获取某个引脚的电平属性来达到判断外围设备的状态。对这些设备/电路的控制,使用传统的串行口或并行口都不合适。所以在微控制器芯片上一般都会提供一个“通用可编程IO接口”,即GPIO。
      GPIO接口至少有两个寄存器,即“通用IO控制寄存器”与“通用IO数据寄存器”。数据寄存器的各位都直接引到芯片外部,而对这种寄存器中每一位的作用,即每一位的信号流通方向,则可以通过控制寄存器中对应位独立地加以设置。比如,可以设置某个引脚的属性为输入、输出或其他特殊功能。

    💦S5PV210的GPIO特性

      146个可中断通用控制I/O。
      32个可控外部中断。
      237个多路复用I/O口
      睡眠模式引脚状态可控(除了GPH0、GPH1、GPH2和GPH3)。

    💦GPIO分组预览

      GPA0:8 in/out port – 2xUART 带控制流
      GPA1:4 in/out port – 2xUART 不带控制流或1xUART 带控制流。
      GPB:8 in/out port – 2x SPI总线接口。
      GPC0:5 in/out port – I2S总线接口,PCM接口,AC97接口。
      GPC1:5 in/out port – I2S总线接口,SPDIF接口,LCD_FRM接口。
      GPD0:4 in/out port –PWM接口。
      GPD1:6 in/out port – 3xI2C总线接口,PWM接口,IEM接口。
      GPE0,1:13in/out port –摄像头接口。
      GPF0,1,2,3:30 in/out port – LCD 接口。
      GPG0,1,2,3:28 in/out port – 4xMMC通道。
      GPH0,1,2,3:32 in/out port –键盘,最大支持32位的睡眠可中断接口。
      GPI:低功率I2S,PCM、低功耗PDN配置(通过AUDIO_SS PDN寄存器配置)。
      GPJ0,1,2,3,4:35 in/out port–Modem IF, CAMIF, CFCON, KEYPAD, SROM ADDR[22:16]
      MP0_1,2,3: 20 in/out port – EBI信号控制 (SROM, NF, OneNAND)
      MP0_4,5,6,7: 32 in/out memory port – EBI
      MP1_0~8: 71 DRAM1 ports
      MP2_0~8: 71 DRAM2 ports
      ETC0, ETC1, ETC2, ETC4(ETC3保留): 28 in/out ETC ports - JTAG, Operating Mode, RESET, CLOCK
    在这里插入图片描述
      GPxCON、GPxDAT、GPxPUD和GPxDRV工作在普通模式,GPxPDNCON、GPxPDNPULL工作在低功耗模式。

    💦GPIO功能概括图

    在这里插入图片描述

    💦S5PV210的GPIO常用寄存器分类

      (1) 端口控制寄存器(GPA0CON-GPJ4CON)
      在S5PV210中,大多数的引脚都可复用,所以必须对每个引脚进行配置。端口控制寄存器(GPnCON)定义了每个引脚的功能。
    在这里插入图片描述
      GPC0CON控制寄存器(可读/可写 Address = 0xE0200060)

      (2) 端口数据寄存器(GPA0DAT-GPJ4DAT)
      如果端口被配置成了输出端口,可以向GPnDAT的相应位写数据。如果端口被配置成了输入端口,可以从GPnDAT的相应位读出数据。
    在这里插入图片描述
      GPC0DAT数据寄存器(可读/可写 Address = 0xE0200064)

    .text
    .global _start
    _start:
    	ldr r0, =0E0200060
    	ldr r1, [r0]
    	bic r1, r1, #0xf000
    	orr r1, r1, #0x1000
    	str r1, [r0]
    
    	ldr r0, =0xE0200064
    	ldr r1, [r0]
    	bic r1, r1, #0x8
    	orr r1, r1,  #0x8
    	str r1,  [r0]
    halt_loop:
    	b halt_loop
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    /*相关GPIO端口的功能设定*/
    /*GPC0控制寄存器*/
    #define GPC0CON (*(volatile unsigned int *)) 0xE0200060;
    /*GPC0数据寄存器*/
    #define GPC0DAT (*(volatile unsigned int *) )0xE0200064;
         void delay()
         {
              int i = 0x100000;
              while (i--);
          }
          int main(void)
          {
               int i = 0;
               GPC0CON &= ~0xff000;
               GPC0CON |= 0x11000;
               while (1)
               {
                   GPC0DAT &= ~(3 << 3);
                   GPC0DAT |= i << 3;
                   i++;
                   if (i == 16)
                       i = 0;
                       delay();
                }
           return 0;  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    #define LEDADDR (*(volatile unsigned long *) (0x2140000))
    
    LEDADDR=0x1;            
    
    • 1
    • 2
    • 3

      LEDADDR 成为一个地址在0x2140000的unsigned long类型变量。
       ( volatile unsigned long * )是C语言中的强制类型转换,它的作用是把0x2140000这个纯粹的十六进制数转换成为一个(地址)指针,其中volatile并不是必要的,它只是告诉编译器,这个值与外界环境有关,不要对它优化。
      接下来在外面又加了一个*号,就表示0x2140000内存单元中的内容了。
      外面一层括号是为了保证里面的操作不会因为运算符优先级或者其它不可预测的原因被改变而无法得到预期的结果。
      经过这个宏定义之后,LEDADDR就被可以做为一个普通的变量来操作。
      (3) 端口上拉寄存器(GPA0PULL - GPJ4PULL)
      端口上拉寄存器控制了每个端口组的上拉/下拉电阻的使能/禁止。根据对应位的0/1组组合,设置对应端口的上拉/下拉电阻功能是否使能。如果端口的上拉电阻被使能,无论在哪种状态(输入、输出、DATAn、EINTn等)下,上拉电阻都起作用。

    💦LED灯控制的电路原理图和代码分析

    💦LED接线原理图

      LED1~LED2分别与GPC0_3、GPC0_4相连,通过GPC0_3、GPC0_4引脚的高低电平来控制三极管的导通性,从而控制LED的亮灭。
    在这里插入图片描述

    💦存储器管理

      在复杂的嵌入式系统中,存储器系统的组织结构按作用可以划分为4级:寄存器、Cache、主存储器和辅助存储器。一般将寄存器、Cache、主存储器称为内存,辅助存储器称为外存。
    在这里插入图片描述

    💦S5PV210的地址映射

      ROM:EPROM、EEPROM和FLASH
      RAM:SRAM和DRAM
      SFRS:Special Function Register(特殊功能寄存器)的缩写。
      IROM: Internal ROM 内部ROM,集成在SOC上的ROM IRAM : Internal RAM 内部RAM,集成在SOC上的RAM
      SROMC_BANK0 : SROM contrler BANK0 (SROM 控制器单元0)。
      DRAM : dynamic RAM 动态RAM(电容式存储,需要不断刷新才能保存数据) SRAM : static RAM 静态RAM(具有静态存取功能,不需要刷新电路)
      SDRAM : synchronous dynamic random access memory 同步动态随机存储器
      DMZ:demilitarized zone,中文名称为“隔离区”
      FLASH:NAND和NOR,ONENAND
    在这里插入图片描述
      地址范围的大小由CPU的位数决定,这个地址范围称为虚拟地址空间
      虚拟地址可以通过MMU(内存管理单元)映射到实际物理地址
      ARM程序的组成
      此处所说的“ARM程序”是指在ARM系统中正在执行的程序,而非保存在ROM中的bin映像(image)文件,这一点清注意区别。
      一个ARM程序包含3部分:RO,RW和ZI。RO是程序中的指令和常量;RW是程序中的已初始化变量;ZI是程序中的未初始化的变量。
      由以上3点说明可以理解为:RO就是readonly,RW就是read/write,ZI就是zero。
      ARM映像文件的组成
      所谓ARM映像文件就是指烧录到ROM中的bin文件,也称为image文件。以下用Image文件来称呼它。
      Image文件包含了RO和RW数据。之所以Image文件不包含ZI数据,是因为ZI数据都是0,没必要包含,只要程序运行之前将ZI数据所在的区域一律清零即可。包含进去反而浪费存储空间。
      ARM程序的执行过程
      烧录到ROM中的image文件与实际运行时的ARM程序之间并不是完全一样的。因此就有必要了解ARM程序是如何从ROM中的image到达实际运行状态的。
      实际上,RO中的指令至少应该有这样的功能:
      1. 将RW从ROM中搬到RAM中,因为RW是变量,变量不能存在ROM中。
      2. 将ZI所在的RAM区域全部清零,因为ZI区域并不在Image中,所以需要程序根据编译器给出的ZI地址及大小来将相应得RAM区域清零。ZI中也是变量,同理:变量不能存在ROM中
      在程序运行的最初阶段,RO中的指令完成了这两项工作后C程序才能正常访问变量。否则只能运行不含变量的代码。
      嵌入式系统中通常有多种存储器,这是为了充分发挥各种存储器的特点,达到好的性价比。下面以一个包含Flash、16位RAM和32位RAM的系统为例,讲述系统的地址映射。
      在这个例子中,系统上电前,所有的程序和数据都保存在Flash中,系统上电后,异常中断和数据栈就被移到32位的RAM中,这使得异常中断处理的速度较快;RW数据以及ZI数据移到16位RAM中;其他的RO代码在Flash中运行。在系统复位时,Flash位于地址 0处,复位后开始执行的指令把Flash映射到别的非0地址段,而把RAM映射到地址0处,具体的地址映射模式如图所示。
    在这里插入图片描述

    💦S5PV210启动过程

      五个步骤
      1、iROM阶段(BL0)
      2、BL1阶段
      3、BL2阶段
      4、拷贝OS到SDRAM
      5、启动OS

    在这里插入图片描述

    iROM的功能
    1、关闭看门狗; 2、初始化icache; 3、初始化栈; 4、初始化堆; 5、初始化块设备拷贝函数; 6、初始化PLL,设置系统时钟; 7、拷贝BL1到内部的SRAM区域; 8、检查BL1的校验和; 9、检查是否是安全启动模式; 10、跳转到BL1的起始代码处。

    💦NOR型flash与NAND型flash的区别

      1) 闪存芯片读写的基本单位不同
      应用程序对NOR芯片操作以“字”为基本单位。为了方便对大容量NOR闪存的管理,通常将NOR闪存分成大小为128KB或者64KB的逻辑块,有时候块内还分成扇区。读写时需要同时指定逻辑块号和块内偏移。应用程序对NAND芯片操作是以“块”为基本单位。NAND闪存的块比较小,一般是8KB,然后每块又分成页,页的大小一般是512字节。要修改NAND芯片中一个字节,必须重写整个数据块。
      2) NOR闪存是随机存储介质,用于数据量较小的场合;NAND闪存是连续存储介质,适合存放大的数据。
      3) 由于NOR地址线和数据线分开,所以NOR芯片可以像SRAM一样连在数据线上。NOR芯片的使用也类似于通常的内存芯片,它的传输效率很高,可执行程序可以在芯片内执行( XI P, eXecute In Place),这样应用程序可以直接在flash闪存内运行,不必再把代码 读到系统RAM中。由于NOR的这个特点,嵌入式系统中经常将NOR芯片做启动芯片使用。而NAND共用地址和数据总线,需要额外联结一些控制的输入输出,所以直接将NAND芯片做启动芯片比较难。
      4) NAND闪存芯片因为共用地址和数据总线的原因,不允许对一个字节甚至一个块进行的数据清空,只能对一个固定大小的区域进行清零操作;而NOR芯片可以对字进行操作。所以在处理小数据量的I/O操作的时候的速度要快与NAND的速度。比如一块NOR芯片通 常写一个字需要10微秒,那么在32位总线上写512字节需要1280毫秒;而NAND闪存写512字节需要的时间包括:512×每字节50纳秒+10微秒的寻页时间+200微秒的片擦写时间=234微秒。
      5) NAND闪存的容量比较大。
      OneNAND结合了NAND存储密度高、写入速度快和NOR读取速度快的优点,整体性能完全超越常规的NAND和NOR。

    💦串行通信

    💦串行通信的基本概念

      1.串行通信
      串行通信是指计算机I/O设备之间数据传输的各位是按顺序依次一位接一位进行传送。通常数据在一根数据线或一对差分线上的传输。
      2.并行通信
      并行通信是指计算机与I/O设备之间通过多条传输线交换数据,数据的各位同时进行传送。
      二者比较:
      串行通信通常传输速度慢,但使用的传输设备成本低,可利用现有的通信手段和通信设备,适合于计算机的远程通信:并行通信的速度快,但使用的传输设备成本高,适合于近距离的数据传送。需要注意的是,对于一些差分串行通信总线,如RS-485、RS-422、USB等,它们的传输距离远,且抗干扰能力强,速度也比较快。

    💦数据传输格式

    💦异步串行方式的特点

      所谓异步通信,是指数据传送以字符为单位,字符与字符间的传送是完全异步的,位与位之间的传送基本上是同步的。异步串行通信的特点可以概括为:
      (1)以字符为单位传送信息。
      (2)相邻两字符间的间隔是任意长。
      (3)因为一个字符中的比特位长度有限,所以需要的接收时钟和发送时钟只要相近就可以。
      (4)异步方式特点就是:字符间异步,字符内部种位同步。

    💦异步串行方式的数据格式

      异步串行通信的数据格式如图所示,每个字符(每帧信息)由4部分组成:
    在这里插入图片描述

    💦异步串行通信中的字符传送格式

      开始前,线路处于空闲状态,送出连续“1”。传送开始时首先发一个“0”作为起始位,然后出现在通信线上的是字符的二进制编码数据。
      每个字符的数据位长可以约定为5位、6位、7位或8位,一般采用ASCII编码。后面是奇偶校验位,根据约定,用奇偶校验位将所传字符中为“1”的位数凑成奇数个或偶数个。也可以约定不要奇偶校验,这样就取消奇偶校验位。
      最后是表示停止位的“1”信号,这个停止位可以约定持续1 位、1.5 位或2 位的时间宽度。
      至此一个字符传送完毕,线路又进入空闲,持续为“1”。经过一段随机的时间后,下一个字符开始传送才又发出起始位。
      每一个数据位的宽度等于传送波特率的倒数。微机异步串行通信中,常用的波特率为110,150,300,600,1200,2400,4800,9600 等。

    💦异步串行通信的接口

    在这里插入图片描述
      9针串口引脚定义
      PC串口中的典型是RS-232及其兼容接口,串口引脚有9针和25针两类。而一般的PC使用的都是9针的接口,25针串口具有20mA电流环接口功能,用9、11、18、25针来实现。这里只介绍9针的R-232C串口引脚定义,如表所示。
    在这里插入图片描述

    💦接口的连接方式

    💦串行接口的物理层标准

      对图4几个主要信号做简要说明。
      ● 保护地:通信线两端所接设备的金属外壳通过此线相连。当通信电缆使用屏蔽线时,常利用其外皮金属屏蔽网来实现。由于各设备往往已通过电源线接通保护地,因此,通信线中不必重复接此地线。例如,使用9针插头(DB-9)的异步串行I/O接口就没有引出保护地信号。
      ● TXD/RXD:这是一对数据线,TXD称发送数据输出,RXD称接收数据输入。当两台微机以全双工方式直接通信(无MODEM方式)时,双方的这两根线应交叉连接(扭接)。
      ● SG:信号地,所有的信号都要通过信号地线构成耦合回路。通信线有以上3条(TXD、RXD 和信号地)就能工作了。其余信号主要用于双方设备通信过程中的联络(握手信号),而且有些信号仅用于和MODEM的联络。若采取微型机对微型机直接通信,且双方可直接对异步串行通信电路芯片编程,若设置成不要任何联络信号,则其他线都可不接。有时在通信线的同一端将相关信号短接以“自握手”方式满足联络要求。
      ● RTS/CTS:请求发送信号RTS是发送器输出的准备好信号。接收方准备好后送回清除发送信号 CTS后,发送数据开始进行,在同一端将这两个信号短接就意味着只要发送器准备好即可发送。
      ● DCD:载波检测(又称接收线路信号检测)。本意是MODEM检测到线路中的载波信号后,通知终端准备接收数据的信号,在没有接MODEM的情况下,也可以和RTS、CTS短接。
    相对于MODEM而言,微型机和终端机一样被称为数据终端(Data Terminal Equipment,DTE)而 MODEM 被称为数据通信装置(Data Communications Equipment,DCE),DTE和DCE之间的连接应该是按接插件芯号,同名端对应相接。此处介绍的RS-232C的信号名称及信号流向都是对DTE而言的。
      ● DTR/DSR:数据终端准备好时发DTR信号,在收到数据通信装置装备好DSR信号后,方可通信。
      ● RI:原意是在MODEM接收到电话交换机有效的拨号时,使RI有效,通知数据终端准备传送。在无MODEM时也可和DTR相接。

    💦RS-232C接线方式

    在这里插入图片描述

    💦RS-232C电平转换芯片及电路

      RS-232C规定的逻辑电平与一般微处理器、单片机的逻辑电平不同的,例如,RS-232C逻辑“1”是以-3~-15V来表示的,而单片机的逻辑“1”是以5V表示的,S5PV210的逻辑“1”是以3.3V表示的,就必须把单片机的电平(TTL、CMOS电平)转变为RS-232C电平,或者把计算机的RS-232C电平转换成单片机的TTL或CMOS电平,通信时必须对两种电平进行转换。实现电平转换的芯片可以是分立器件,也可以是专用的RS-232C电平转换芯片。下面介绍一种在嵌入式系统中应用比较广泛的MAX3232芯片。
    在这里插入图片描述

      主要特点有:
      符合所有的RS-232C规范。
      单一供电电压+5V或3.3V。
      片内电荷泵,具有升压。电压极行反转能力,
      能够产生+10 V和-10V电压V+、V-。
      低功耗,典型供电电流3mA。
      内部集成2个RS-232C驱动器。
      内部集成2个RS-232C接收器。

    💦S5PV210串口控制器的简介

      S5PV210的通用异步收发(UART)可支持4个独立的异步串行输入/输出口,每个口皆可支持中断模式及DMA模式,UART可产生一个中断或者发出一个DMA请求,来传送CPU与UART之间的数据,UART的比特率最大可达到3Mbps。每一个UART通道包含两FIFOs用于数据的收发,其中通道0的FIFO大小为256字节,通道1的FIFO大小为64字节,通道2和通道3的FIFO大小为16字节。
      特点
      4组收发通道,同时支持中断模式及 DMA操作。
      通道0、1、2及带红外通道3.
      通道0带256byte的FIFO,通道1带64byte的FIFO,通道2、3带16byte的FIFO。
      通道0、1、2支持自动控功能。
      支持握手模式的发送/接收。
    在这里插入图片描述

    💦S5PV210串口控制器概述

      UART行控制寄存器ULCONn(ULCON0,R/W,Address=0xE2900000)
      UART控制寄存器
      UCONn (UCON0,R/W,Address=0xE2900004)
      UART FIFO控制寄存器UFCONn(UFCON0,R/W,Address=0xE2900008)
      UART MODEM控制寄存器UMCONn(UMCON0,R/W,Address=0xE2900004)
      发送寄存器UTXHn和接收寄存器URXHn
      这两个寄存器存放着发送和接收的数据,在关闭FIFO的情况下只有一个字节8位数据。需要注意的是,在发生溢出错误时,接收数据必须被读出来,否则会引发下次溢出错误。
      比特率分频寄存器UBRDIVn
      用于串口比特率的设置。S5PV210引入了UDIVSLOTn,使得波特率的设置比早期处理器更加精确。下面以设置波特率为115200为目标,介绍设置方法。

    DIV_VAL=(PCLK/(bps*16)-1
            =40000000/(115200*16)-1     //PCLK由系统时钟提供,为此设定40MHz
            =21.7-1
            =20.7
    UBRDIVn=20(DIV_VAL的整数部分)。
    (UDIVSLOTn中1的数量)/16=0.7
    (UDIVSLOTn中1的数量)=11。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

      所以UDIVSLOTn的值可以为:b1110 1110 1110 1010、b0111 0111 0111 0101等等其他类似的值,根据手册中建议值则可以选择0xDDD5(1101 1101 1101 0101b)。
      串口状态寄存器UTRSTAn(UTRSTAT0,R,ADDRESS=0xE2900014)
      寄存器详细说明表所示。
    在这里插入图片描述
      串口FIFO状态寄存器UFSTATn
    在这里插入图片描述
    在这里插入图片描述

    int main()
    {
    	uart_init(115200);
    	Uart_Select(2);
    
    	printf("CVT S5PV210 Jtag Uart Test...\n");
    
    	while(1){
    		    unsigned char ch = 'a';
    
    		ch = Uart_Getch();
    		Uart_SendByte(ch);
    		if(ch == 0x0d) //ASCII 回车
    			Uart_SendByte(0x0a); //ASCII 换行
    	}
    }
    void uart_init(int baud)
    {
     //enable GPA0 pin function mode
    	GPA0.GPA0CON = 0X22;	
     //enable GPA0 pin function mode
    	GPA1.GPA1CON = 0X22;	    
     //disable  fifo
               UART2.UFCON2 = 0X00;
     //disable AFC
    	UART2.UMCON2 = 0X00;
     //data length 8 bit
    	UART2.ULCON2 = 0X03;		UART2.UCON2  = 0X305; 
    
     // Baud rate divisior register 115200
     	UART2.UBRDIV2 = 0x23; 	UART2.UDIVSLOT2 = 0X3;
    }
    char Uart_Getch(void)
    {
        if(whichUart==0)
        {
            while(!(UART0.UTRSTAT0 & 0x1)); //Receive data ready
            return UART0.URXH0;
        }
        else if(whichUart==1)
        {
            while(!(UART1.UTRSTAT1 & 0x1)); //Receive data ready
            return UART1.URXH1;
        }
        else if(whichUart==2)
        {
            while(!(UART2.UTRSTAT2 & 0x1)); //Receive data ready
            return UART2.URXH2;
        }
    }
    void Uart_SendByte(int data)
    {
        if(whichUart==0)
        {
            if(data=='\n')
            {
                while(!(UART0.UTRSTAT0 & 0x2));
    //            Delay(10);                 //because the slow response of hyper_terminal
                utxh('\r');
            }
            while(!(UART0.UTRSTAT0 & 0x2));   //Wait until THR is empty.
    //        Delay(10);
            utxh(data);
        }
    …………}
    
    char utxh(int ch){
        if(whichUart==0)
        {
        	UART0.UTXH0 = (unsigned char)(ch);
        }
    ……..}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    💦中断处理

    💦中断控制器的基本原理

      ARM内核只有两个外部中断输入信号nFIQ和nIRQ。但对于一个系统来说,中断源可达几十个。为此,在系统集成时,一般都会有一个异常控制器来处理异常信号
    在这里插入图片描述
      这时候用户程序可能存在多个IRQ/FIQ的中断处理函数。为了使从向量表开始的跳转始终能找到正确的处理函数入口,需要设置处理机制和方法。在以往的ARM芯片中采用的是使用软件来处理异常分支,因为软件可以通过读取中断控制器来获得中断源的信息,从而达到中断分支的目的。
    在这里插入图片描述
      因为软件的灵活性,可以设计出更好的流程控制方法,如图所示。
      Int_vector_table是用户自己开辟的一块存储器空间,里面按次序存放异常处理函数的地址。IRQ_Handler()从中断控制器获取中断源信息,然后再从Int vector table中的对应地址单元得到异常处理函数的入口地址,完成一次异常响应的跳转。这种方法的好处是用户程序在运行过程中,能够很方便地动态改变异常服务内容。

    💦S5PV210的中断控制器的结构

      这种类型的中断控制早已出现在了ARM芯片中,比如基于S5PV210的Cortex-A8中,以集成PL192向量中断控制器。使用向量中断的优点在于,中断优先级仲裁及中断分支的处理递交给了控制器来处理,这样从获取中断源,再到中断ISR的处理,其性能相对于软件方式的实现有很大的提高。下面是使用这种机制的详细介绍。
      S5PV210的中断控制器是由4个向量中断控制器(VIC)、ARM PrimeCell PL192 和 4个 TrustZone Interrupt Controller (TZIC)共同组成。 。可以支持93个向量IRQ中断源。其中TZIC是为TrustZone技术所准备的,ARM TrustZone® 技术是系统范围的安全方法,针对高性能计算平台上的大量应用,包括安全支付、数字版权管理 (DRM)、企业服务和基于 Web 的服务(援引官方的介绍)。TZIC提供了安全控制的nFIQ中断并且使该这类中断从传统的不安全中断VIC中屏蔽掉,从而达到应用在数据传输时的安全性和保密性。
    在这里插入图片描述
    在这里插入图片描述

    💦中断控制器的功能

      比如当【按键中断】发生的时候,处理器就将进入IRQ模式,首先要进行现场保护(硬件自动完成),然后从固定入口进入中断处理函数,中断处理函数首先判断是哪个中断组发生中断,然后直接执行该中断组对应的VICxADDR寄存器里面的函数。我们知道,一个中断组有32个中断源,为什么我们可以直接运行中断组的VICxADDR指定的函数而无需知道是具体哪个中断源触发了中断呢?这是由于中断组内的中断源在触发中断后硬件会自动把对应中断源的处理函数入口地址赋给所属组的VICxADDR,这样我们就能省去检索中断源再跳转到对应中断函数入口的时间了,当然,前提是我们要把【按键中断】的服务程序入口地址赋给某个对应的寄存器(假设是VIC0INTADDR12,所属组是VIC0组,所对应入口是VIC0INTADDR)。

    💦中断例程

    在这里插入图片描述

    💦相关寄存器

      中断状态寄存器VICnIRQSTATUS
      快中断状态寄存器VICnFIQSTATUS
      中断选择寄存器VICnINTSELECT
      中断使能寄存器VICnINTENABLE
      中断使能清除寄存器VICnINTENCLEAR
      向量地址寄存器VICnADDRESS
      向量地址寄存器组VICnVECTADD
      向量优先级寄存器VICnVECTPRIORITY
    在这里插入图片描述

    💦中断流程

      整个中断的工作分为2部分:
      第一部分是我们为中断响应而做的预备工作:
      1. 初始化中断控制器
      2. 绑定写好的isr到中断控制器
      3. 相应中断的所有条件使能
      第二部分是当硬件产生中断后如何自动执行isr:
      1. 第一步,经过异常向量表跳转入IRQ/FIQ的入口
      2. 第二步,做中断现场保护(在start.S中),然后跳入isr_handler
      3. 第三步,在isr_handler中先去搞清楚是哪个VIC中断了,然后直接去这个VIC的ADDR寄存器中取isr来执行即可。
      4. 第四步,isr执行完,中断现场恢复,直接返回继续做常规任务。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    💦中断小结

      首先是进入start.S(清bss,开中断,设置时钟,进main),然后是main(初始化串口,初始化异常向量表,初始化中断控制器,配置GPH0作为外部中断引脚,配置EXT_INT0触发下降沿中断,取消EXT_INT0的中断屏蔽,设置该外部中断源的处理函数入口,使能该中断源的中断,死循环不断打印数字)。
      当按键中断发生后,根据异常向量表,程序会自动跳转到IRQ_handle(在start.S内)处执行,IRQ_handle先进行了现场保护,然后跳转到irq_handler,irq_handler首先是遍历四个中断组,看看是哪个中断组发生了中断,然后就跳转到该中断组的中断服务程序里(前面已经说到,isr_key作为按键中断服务程序的入口已根据中断号存入VICxINTADDRn中,而发生中断的同时,硬件会将中断源的服务程序入口自动搬移到它所属的中断组的VICxINTADDR里),从而间接地运行了isr_key这个程序,在这个程序里,我们做了分析,找出了触发中断的具体按键,并通过串口打印出来。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    C++从淬体到元婴day01
    全网显示 IP 归属地,这背后的技术你知道吗?
    【JAVAEE基础学习】--文件上传&下载案例-1.0
    无惧面试,2023最新最全Java面试手册全网首次开放下载
    《我要进大厂》- Spring框架 夺命连环22问,你能坚持到第几问?(Spring高频问题)
    Flink协调器Coordinator及自定义Operator
    气象站有什么用?有哪些类型
    SpringBoot启动失败报错,spring.profiles.active:@env@中环境变量@无法识别报错_active: @env@
    Hbase底层原理简介(二)
    yolov7添加GAMAttention注意力机制,同时添加CNeB,C3C2
  • 原文地址:https://blog.csdn.net/qq_36477513/article/details/124899591