【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
【ARM】arm系列知识框架的更多相关文章
- ARM汇编程序基本知识
		
ARM汇编程序基本知识 1.汇编程序的基本组成 ARM汇编语言程序中,程序是以程序段为单位组织代码的.段是相对独立的指令或者代码序列,拥有特定的名称.段的种类有代码段.数据段和通用段,代 码段的内容为 ...
 - 一点理解之 CmBacktrace: ARM Cortex-M 系列 MCU 错误追踪库
		
@2019-02-14 [小记] CmBacktrace: ARM Cortex-M 系列 MCU 错误追踪库,用来将单片机故障状态寄存器值翻译出来输出至终端上以便排错 CmBacktrace: AR ...
 - ARM的体系结构与编程系列博客——ARM处理器系列介绍
		
ARM处理器系列介绍 现在到了3月,过年过得过于舒服了.系列博客也停更了近半月,我果然是个慢(lan)性(gui)子,那么趁着到校的第一天晚上,就写一篇博客来继续我的系列博客了!众所周知,ARM处理器 ...
 - 【基于Android的ARM汇编语言系列】之三:ARM汇编语言程序结构
		
作者:郭嘉 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells github:https://github.com/AllenWell [ ...
 - ARM v7-A 系列CPU的MMU隐射分析
		
ARM v7-A 系列CPU的MMU隐射分析 摘要:ARM v7-A系列的CPU加入了很多扩展,如多核处理器扩展.大物理地址扩展.TrustZone扩展.虚拟化扩展.若支持大的物理地址,则必须支持多核 ...
 - ARM v8-A 系列CPU的MMU隐射分析
		
ARM v8-A 系列CPU的MMU隐射分析 摘要:V8-A系列CPU有ELX,X为0~3等4个异常级别,又有AArch64和AArch32两种执行状态,异常级别可以决定执行状态,而对应着执行状态,M ...
 - ARM版本系列及家族成员梳理
		
ARM公司简介 ARM是Advanced RISC Machines的缩写,它是一家微处理器行业的知名企业,该企业设计了大量高性能.廉价.耗能低的RISC (精简指令集)处理器. 1985年第一个AR ...
 - 【基于Android的ARM汇编语言系列】之五:ARM指令集与Thumb指令集
		
作者:郭嘉 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells github:https://github.com/AllenWell [ ...
 - ARM处理器基础知识
		
1.ARM处理器的寄存器,ARM与Thumb状态,7中运行模式 http://blog.chinaunix.net/uid-28458801-id-3494646.html 2.ARM的7种工作模式. ...
 
随机推荐
- DSP 知识点
			
1:自定义数据段 #pragma DATA_SECTION(symbol,".section") Int32 symbol[LENGTH]; 2:前几天遇到一个问题.dsp在执行某 ...
 - go语言爬虫 - TapTap用户都喜欢些什么游戏
			
前面的废话 说到爬虫,首先想到的当然是python~ 它在机器学习.爬虫数据分析领域可谓是如日中天,十分热门.但我最近在学习go语言,所以就用go写了 TapTap社区 这是一个高品质的游戏分享社区, ...
 - RabbitMQ 初学及其深入学习推荐的一些文章
			
记录一下学习RabbitMQ过程中,收获比较大的一些文章: 什么都别说,先把这6个Demo 玩一遍 https://www.rabbitmq.com/getstarted.html 大佬1号 http ...
 - 进程描述和控制(os 笔记二)
			
进程描述和控制  计算机最初的主要任务之一就是高效的自动化我们的工作,完成用户交付的任务.而这种任务在计算机中的表示就是一个个的进程.从上一篇文章中描述的计算机的发展历史我们能发现,无论是单道批处理 ...
 - 洛谷.T21778.过年(线段树 扫描线)
			
题目链接或者这吧.. 被数据坑了 /* 操作按左端点排个序 依次进行即可 不是很懂 为什么不写Build 而在Add时改mp[rt]=p 会WA(too short on line 251..) 找到 ...
 - 关于Gevent的使用指北
			
关于Gevent的使用指北 只是看了入门指南,和一个翻译文档.写一下个人读书心得. 其实看完之后,第一个反映就是asyncio这个系统库,感觉gevent现在所做的一些事情是与asyncio很像的,但 ...
 - AngularJS中处理多个promise
			
在使用AngularJS中处理promise的时候,有时会碰到需要处理多个promise的情况. 最简单的处理就是每个promise都then.如下: var app = angular.module ...
 - 关于“UI线程”
			
http://www.cppblog.com/Streamlet/archive/2013/05/05/199999.html 缘起 这是一篇找喷的文章. 由于一些历史原因和人际渊源,周围同事谈论一些 ...
 - web架构延变
			
在现代的软件系统中,几乎所有的系统都使用到了数据库,不论是关系型数据,例如MySql.SQLite.Oracle.SQLServer等,还是非关系性数据,例如mongoDB.redis等.本文已web ...
 - Convolutional Neural Networks: Application
			
Andrew Ng deeplearning courese-4:Convolutional Neural Network Convolutional Neural Networks: Step by ...