zoukankan      html  css  js  c++  java
  • 【ARM】arm系列知识框架

    【ARM编程模型】


     硬件: 电路原理图
     软件: 体系结构, 指令集, 寄存器组

    【ARM编程技术】


     汇编/C语言 编译, 链接, 烧写和调试
     windows: MDK
     linux  : gcc

    【ARM接口编程】


     电路原理图
     datasheet ------> 裸机程序(不带操作系统,直接操作硬件)
     中断技术
     初始化程序
     


     

    【 ARM基础知识】


     1. 冯·诺依曼结构特点:
          采用二进制表示数据和程序
          事先存储程序
          利用控制流来驱动程序
          五大部件
     
     2. CPU = CU + ALU
            CPU: 解释并执行指令的功能部件
            CU: 译码并发出各种控制信号
            ALU: 运算

     3. 常见存储器
          RAM: (掉电丢失数据)
          SRAM: 静态 96KB 
          DRAM: 动态(SDRAM, DDRII(256MB))

          ROM: (掉电不丢失数据)
             PROM
             EPROM
             E2PROM
             BIOS

          flash:
             norflash : 2MB  有地址线, 片上执行(CPU可以直接访问), 读数据速度快, 存储启动程序
             nandflash: 256MB 无地址线, 不片上执行, 存储大数据量数据

     

    【ARM体系结构】


    1. ARM : advanced RISC machine
        含义: 
              公司
              技术
              微处理器

    2.编程模型
        1)数据和指令类型: 
            ARM处理器支持: 8bit, 16bit, 32bit数据
            Thumb指令集, ARM指令集
           
           半字对齐: 被2整除 [0]=0
           字对齐 : 被4整除  [1:0]=00

        例子:
        运行地址    机器码    机器码符号化
        0x00000000  E3A00001  MOV  R0,#0x00000001

        2)处理器工作模式
            ARM处理器一般支持 7 种基本工作模式
            不同的工作模式对应着不同的寄存器
       
            特殊寄存器: R13(SP), R14(LR), R15(PC), CPSR, SPSR

            程序指针PC (r15): 程序执行到哪里(地址), PC指针指到哪里(地址)


    3. 异常处理过程
        产生:(硬件过程)
            1. CPSR ---> SPSR_mode
            2. 设置CPSR
                CPSR[5]  = 0  处理器处于ARM状态
                CPSR[4:0]=mode  异常工作模式
                CPSR[7:6]=11  根据实际情况

           3. 返回地址--->LR_mode
           4. PC ---> 异常向量表入口地址
           5. 保护现场(堆栈)


        退出:(软件过程)
           1. SPSR_mode ---> CPSR
           2. LR_mode----> PC 
           3. 恢复现场(堆栈)

        注意: 异常产生,退出时,ARM处理器必须处于ARM工作状态


    【指令集】


     1. RISC: 精简指令集系统
       特点:
           机器码是固定长度
           指令规整简单
           单周期执行, 容易流水线机制
           大量寄存器
           访问存储设备: 加载,存储, 交换

     2. ARM指令格式
          操作码  +  目标寄存器  + OP1 + OP2....
          |---助记符
          |---条件码

     3. 第二操作数寻址方式
          立即数寻址:  mov r1, #1
          寄存器寻址:  mov r0, r1
          移位寻址  :  mov r0, r1, lsl #2
          寄存器间接:  ldr r0, [r1]
          基址寻址  :  ldr r0, [r1, #2]
          多寄存器  :  ldmia r0!, {r0-r7}
          堆栈寻址  :  stmfd sp!, {r0-r12, lr}
          相对寻址  :  b label


    【系统设计】


     1. SOC概念:
       system on chip
      
       ARM芯片 = ARM内核 +  片内存储器  + 片内各种电路
       S5PC100   cortex-A8    SRAM...   各种控制器

     2. 指令流水线
       在编译器中, 黄色箭头指向的地址  =  执行PC  = R15(PC)

       ARM态: 
           PC值 = 当前执行指令PC + 8 
         (取指PC)

       Thumb态: 
           PC值 = 当前执行指令PC + 4 
         (取指PC)
        
       例如:
        add pc, pc, #4  ; PC  = PC + 4
              ; R15 = 取指PC + 4
     
     3. ARM920T = ARM9TDMI + I/D cache + MMU + cp14 + cp15


    【ARM指令集】

    1. 条件执行及标志位
      cmp: 功能相当于减法运算,不保存结果, 但影响标志位
     
       条件码: 16条, AL

    2. 分支指令
       B : 相当于C语言goto label, 不带返回地址
       BL: 相当于C语言函数调用, 处理器自动保存下一条指令的返回地址 ---> LR


       跳转范围 = 偏移量(机器码低24位) * 4 + 当前PC值(取指PC)
                = 0x1 * 4 + (0x8+8)
                = 0x14


       例子:
         0x00000008  EB000001  BL        0x00000014


      长跳转:
      ldr pc, =label

      注意: B,BL指令是位置无关指令


    3. 数据处理指令
       注意: 上述指令只能对寄存器操作,不能针对存储器

       ADD SUB AND EOR ORR
       CMN CMP TST TEQ BIC

    4. 桶型移位器
      逻辑移位: lsl  lsr
      算术移位: asr
      循环移位: ror  左移 = 32 - 右移

    5. 立即数
      第二个操作数有12位:
       低8位: 常数
       高4位: 移位次数---> 循环右移 * 2

       如何判断常数是否是合法立即数?
      1. 利用编译器
        例如:
         0x00000004  E3A014FF  MOV       R1,#0xFF000000
            低8位: 0xff
            高4位: 4 * 2 = 8(循环右移8位) 


      2. 规则
       1. 找出8位常数
         第一个"1"和最后一个"1",  最短距离不能超出8位
      
       2. 常数能否循环右移偶数位


    6. 装载32 bit常数
      伪指令: 不会生成一一对应的机器码

      ldr r0, =const
         const: 符合立即数  mov r0, #const
         const: 不符合立即数 ldr r0, [pc, #offset]
       

    7. 单寄存器数据传送
      ldr: 读 源寄存器在后, 目标寄存器在前
      str: 写 源寄存器在前, 目标寄存器在后

      前索引: LDR r0,[r1,#8]   后索引: LDR, R0,[R1],#8

    8. 块数据传送
      ldm: 读 源寄存器在后, 目标寄存器在前
      stm: 写 源寄存器在后, 目标寄存器在前

      操作多寄存器访问:
       1. 低编号的寄存器对应着低地址数据
       2. 读取存储设备数据分别存放在寄存器参数列表中
       3. 指针向上/下移动

    9. 堆栈

      1)堆栈指针移动方向:
        向上: 写入数据(压栈), 指针递增
        向下: 读取数据(出栈), 指针递减
     
      2) 满堆栈: 堆栈指针指向最后入栈的有效数据的位置
         空堆栈: 堆栈指针指向等待下一个入栈的数据的空位置
     

      STMFD (压栈)
      LDMFD (出栈)

      注意: 运行C语言main函数之前,必须确保堆栈空间已经设置好了!!!

      异常处理退出过程: 软件过程中
        1. SPSR--->CPSR
        2. LR  --->PC
        3. 恢复现场

      例如:
        保护现场:  stmfd sp!, {r0-r12, lr}
      
        恢复现场:  ldmfd sp!, {r0-r12, pc}^
          
          解释: 堆栈列表中, 如果有"PC"和"^"同时存在, 表示处理器自动将SPSR_mode ---> CPSR, LR_mode--->PC

    10. SWP软交换
       作用: 原子操作, 不可被外部因素打断.
        唯一一条原子操作的访存指令

    11. 软件中断 (SWI)
        格式:
        swi 软中断号

        swi是一种用户自定义指令,当执行到swi指令时, 跳转到异常向量表0x8入口地址, 自动切换到SVC工作模式

    12. PSR 传送指令
        msr/mrs  设置CPSR/SPSR指令

     


    【异常处理过程】

    1、产生:(硬件过程)
       1. CPSR ---> SPSR_mode
       2. 设置CPSR
         CPSR[5]  = 0  处理器处于ARM状态
         CPSR[4:0]=mode  异常工作模式
         CPSR[7:6]=11  根据实际情况

       3. 返回地址--->LR_mode
       4. PC ---> 异常向量表入口地址
       
       5. 保护现场(堆栈)


    2、退出:(软件过程)
       1. SPSR_mode ---> CPSR
       2. LR_mode----> PC 
       3. 恢复现场(堆栈)

      注意: 异常产生,退出时,ARM处理器必须处于ARM工作状态

    【异常返回地址】


      前提: 在异常产生的时候内核设置 LR_mode = PC - 4


    【搭建linux下ARM开发环境】


     1. 将arm-none-eabi-4.2.2.tgz拷贝到ubuntu /usr/local目录,然后解压
     2. 将解压之后生成arm目录,改变权限
     3. 将交叉开发工具链的路径: /usr/local/arm/4.2.2-eabi/usr/bin 
        添加到 /etc/environment
     4. 更新工具链路径
       source /etc/environment


    arm_project工程有:
      start.S uart.c serial.c
      1. 将源文件编译生成 *.o文件   gcc
      2. 将*.o文件链接生成*.elf文件  ld
      3. 将*.elf文件转换生成*.bin文件  objcopy
      4. 将*.elf文件反汇编生成*.dis文件 objdump

     


    【系统时钟】


     1. 各种不同的外围设置需要的工作频率:
          CPU: 667MHZ
          内存: 200MHZ
          串口: 115200bps
          ...
          ...
     
     2. 设置不同的外围设备需要的工作频率:
          如何设置不同的工作频率?
              12MHZ ---> 667MHZ工作频率   倍频
              最高工作频率---> 各种不同的设备  分频
      
          PLL锁相环

     3. 查看用户手册
          S5PC100通过3个域管理不同外围设备需要的工作频率:
          D0:  ARMCLK, HCLK, PCLK
          D1:  HCLK, PCLK
          D2:  HCLK, PCLK

     4. PLL工作原理
          1. 设置PLL使能信号
          2. 设置PLL LOCKTIME
          3. 设置Fin和Fout之间参数
          4. 设置比例关系:
             D0: ARMCLK:HCLK:PCLK = 1:4:8
             D1:     MPLLCLK:PCLK = 1:4

     5. 系统时钟寄存器
          1. A/M/E/HPLL_MASK:  LOCKTIME = 0xe10
          2. A/M/E/HPLL_CON :  PLL使能信号, 设置输出工作频率的参数
          3. CLK_SRC0~3     :  选择时钟源, CLK_SRC0 = 0x1111
          4. CLK_DIV0~4    :  分频比例关系


     6. 编写驱动系统时钟流程:
          1. 设置LOCKTIME
          2. 设置分频比例关系
          3. 使能PLL信号,设置输出工作频率的参数
             FOUT = MDIV X FIN / (PDIV X 2^SDIV) 
          4. 选择时钟源为输出

     


     

    【中断控制器】


    中断处理过程流程:
      1. 建立异常向量表
      2. 关闭看门狗, 初始化系统时钟
      3. 设置堆栈空间: IRQ_stack system_stack
      4. 开CPSR[I]=0
      5. 跳转C语言main函数
      6. 正常程序
      7. 中断初始化
           1) 设置K1(GPH0_1/EINT1)引脚功能为: 中断输入 GPH0CON[7:4] = 0010      WKUP_INT[1] 
           2) 设置K1(GPH0_1/EINT1)触发方式为: 下降沿触发 WKUP_INT0_7_CON[6:4]=010  Falling edge triggered 
       
           3)  WKUP_INT0_7_MASK &= ~(0x1<<1);
              VIC0INTENABLE |= (0x1<<1);
               VIC0VECTADDR1 = (unsigned long)int_key1; //ISR函数入口地址

      8. 产生IRQ信号:
           保护现场
           调用ISR:
             ((void (*)(void))VIC0ADDRESS)();  //强制将VIC0ADDRESS转换成函数指针
         LED亮
         清中断: 
           VIC0ADDRESS = 0;
           WKUP_INT0_7_PEND = (0x1<<1);
        恢复现场
        调整返回地址

     


    【串口控制器】


     1. 使用uart需要设置:
          波特率
          数据位
          奇偶校验位
          停止位
          流控

     2. uart寄存器
          ULCONn:  设置uart传输格式 8N1

          UCONn :  选择时钟源, 传输方式
          UTRSTATn: 检测uart发送/接收状态
          UTXHn/URXHn:发送/接收数据
          UBRDIVn/UDIVSLOTn: 波特率
              DIV_VAL = (PCLK / (bps x 16 ) ) −1 
                      = (66.75mhz/(115200*16)) - 1
                      = 35.2

              UBRDIVn = 35
              UDIVSLOT0 = 3

     3. 编写uart 程序流程:
          1. 设置GPA0_0,1引脚功能: GPA0CON[3:0] = 0010 UART_0_RXD  GPA0CON[7:4] = 0010 UART_0_TXD 

          2. 设置系统时钟
          3. 初始化uart:
                 波特率
                 数据位
                 奇偶校验位
                 停止位
                 流控

    4、串口出现乱码原因
          硬件: 串口线型号

          软件: 系统时钟,波特率,串口程序

    【PWM timer】


     1. PWM timer操作原理
          参考网络解释

     2. timer寄存器
          TCFG0: 一级预分频值

          TCFG1: 二级5路分频值  Timer Input Clock Frequency = PCLK / ( {prescaler value + 1} ) / {divider value} 
                                                            = 66.75MHZ / 250 / 8
                                                            = 33.375KHZ
                                                            = 0.03ms

          TCON: 启动/停止, 装载方式
          TCNTBn: 计数值
          TCMPBn: 比较(控制高电平)

     3. 编写驱动PWM timer程序流程:
          1. 设置GPD1/pwmtout1引脚功能: GPDCON[7:4] = 0010  TOUT_1

          2. 初始化系统时钟
          3. 初始化pwm timer1:
               设置一级预分频值
               设置二级5路分频值
               设置计数值
               设置比较值
               启动timer1(手动装载, 自动)

     


    【nand控制器】


     查看用户手册
     查看nandflash芯片手册
     查看电路原理图
     结合分析
     编写程序

     1.nandflash内部结构
          1个nand器件 = 2048块

                  1块 = 64页
                  1页 = (2048 + 64)B
                2048B: 代表main区,存放正常数据
                  64B: 代表spare区(OOB区), 存放EDC/ECC校验码

          读写nandflash以 页 为单位
          擦出nandflash以 块 为单位

     2. nand容量
          256MB:

          二进制  28bit  表示
          寻址: 
          发 5 次地址

     3. nand寻址
          以 页 为单位

         A0~A11 : 列地址(页内地址) 
          A12~A28: 行地址(页地址)

     4. nandflash操作步骤
          发命令:   复位: 0xff  读: 0x00 0x30

          发地址:   连续发5次地址(发2次列地址, 发3次行地址) 
          检测nandflash: 
          读写:
     
     5. nand寄存器
          NFCONF:  选择时钟, 设置时序时间

          NFCONT:  使能nand控制器, 片选nandflash芯片
          NFCMMD:  命令
          NFADDR:  地址
          NFDATA:  数据
          NFSTAT:  检测nandflash状态


     6. 编写nandflash驱动程序流程
          1. nand初始化

               1.1 设置GPK0_2,3引脚功能: GPK0CON[11:8]=0011 NFCSn[0]  GPK0CON[15:12]=0011 NFCSn[1]
               1.2 选择时钟源, 设置时序时间
               1.3 使能nand控制器
               1.4 nandflash复位:
                      片选nandflash芯片
                      发出复位命令: 0xff
                      检测nand状态
                      取消nandflash片选

          2. 从nandflash拷贝数据到内存中
               2.1 定义目标地址ddr_start, 源地址nand_start, 数据大小len
               2.2 片选nandflash芯片
               2.3 循环读取数据到内存中
                    for(i=nand_start; i<(nand_start+len); i+=2048)  //页地址
                    {
                         发地址准备命令: 0x00
                         连续发5次地址(发2次列地址, 发3次行地址) 
                         发数据准备命令: 0x30
                         检测nand状态

                         for(j=0;j<2048;j++) //页内地址
                         {
         
                         }
                    }
      
          3. 取消nandflash片选

     


    【A/D转换器】


     1. A/D概念:
          将电信号(模拟信号)转换为数字量(数字信号,二进制)

     2. A/D转换原理
          采样---> 量化 ----> 编码

     3. A/D编码位数: 12位
           Vmax = 3.3V

           Vmin = 0  V

     4. A/D转换公式
          采样值 = (4096/3.3V) * 采样电压 (4096 = 2 ^ 12,12个输出)

     5. ADC操作方法:
          选择输入通道: 采样通道[5:0] 触摸通道[9:6]

          ADC初始化

     6. ADC寄存器
          ADCCON:  设置输出编码位数, 检测adc转换状态, 设置预分频值, 启动读

          ADCDAT0: 采样值
          ADCMUX:  输入通道选择 ADCMUX = 0000  AIN0

     7. 编写ADC驱动程序流程:
          1. 设置系统时钟

          2. 初始化ADC
               选择输入通道
               设置输出编码位数, 检测adc转换状态, 设置预分频值, 启动读
               读取采样值


    【I2C控制器】


     1. I2C寄存器
          I2CCONn: 使能ACK信号, 选择时钟源, 使能传输方式
          I2CSTATn: 设置主机发送/接收模式, 启动/停止, 使能输出, ACK信号能否被接收
          I2CDSn:  发送/接收数据

     

     2. 编写I2C驱动程序流程:(根据LM75时序图)
          设置GPD3,4引脚功能:  GPDCON[15:12] = 0010  I2C0_SDA  GPDCON[19:16] = 0010   I2C0_SCL

          第一阶段:
               1. 装载LM75地址: 0x90

               2. 设置主机发送模式, 使能ACK信号能被接收, 使能数据输出, 设置开始条件
               3. 使能ACK信号, 选择时钟源, 使能传输方式
               4. 等待

               5. 配置LM75模式: 温度模式 0x0
               6. 使能ACK信号, 选择时钟源, 使能传输方式

          第二阶段:
               1. 装载LM75地址: 0x90

               2. 设置主机接收模式, 使能ACK信号能被接收, 使能数据输出, 设置开始条件
               3. 使能ACK信号, 选择时钟源, 使能传输方式
               4. 等待

               5. 使能ACK信号能被接收, 接收第一个字节数据(温度整数部分)
               6. 关闭ACK信号被接收  , 接收第二个字节数据(温度小数部分)
               7. 设置停止条件

     

    @成鹏致远 | 2013-08-30

  • 相关阅读:
    ffmpeg h264编码 extradata 为空
    MySQL主从复制报错一致性问题解决
    MySQL 子查询优化案例
    RAC+单节点搭建DG
    总结搭建Oracle11g DG踩的坑
    解决开机自动调用脚本失败的问题
    MySQL版本升级之5.6到5.7
    MySQL 通过semi join 优化子查询
    MySQL 配置文件中忘配置default-character-set引发的乱码问题
    MySQL5.6下使用xtrabackup部分备份恢复到MySQL5.7
  • 原文地址:https://www.cnblogs.com/lcw/p/3762899.html
Copyright © 2011-2022 走看看