Chinaunix首页 | 论坛 | 博客
  • 博客访问: 405405
  • 博文数量: 53
  • 博客积分: 1910
  • 博客等级: 中尉
  • 技术积分: 1130
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-10 14:56
文章分类

全部博文(53)

文章存档

2013年(1)

2012年(17)

2011年(33)

2010年(2)

分类: 嵌入式

2011-09-28 09:08:25

cortex-m3 是一款非常强大的单片机,和arm A系列(应用处理器)的确有很大的区别

但是还是很多相似之处,毕竟都是arm的东西

下面是阅读CM3权威指南的一些摘要:


1. P25 两个级别(user,svc),2个运行模式(handler,thread),3种组合(user没有handler mode)
       handler ,thread 的区别可能就是(4)中的自动压栈

                             特权      |       用户
       ———————————————————————
       异常(exp,irq)处理    handler    |       错误
       ———————————————————————
       主应用的代码         线程       |       用户

       注意mode 切换图
                    
                            [特权handler mode]
                            /  ^         \   ^  
                           /  /           \   \
                          /  /      (异常返回) (触发异常)
                (异常返回)  (触发异常)      \    \
                        /   /                \    \________________
                       /   /                  \_____________       | 
                      /   /                                 |      |
                     V   /                                  V      |
   复位---> [特权级thread mode]----(修改CONTROL REG)--->(用户级thread mode)
                                                                                
        CM3:
        handler mode (注意总是 MSP!)
        thread mode, 可以使用  MSP
        thread mode, 也可以使用PSP,通过control reg 设置
 
        注意和ARM9 ARM A系统等比较
        它们在各异常(Abort,Undefine,IRQ,FIQ),User,Supervisor 都有自己的SP(R13)
        移值时注意这个巨大差异!!!
         

2. P27 内存的分布

3. P30 异常名称介绍,[-1]----[-3] 3个固定优先级,NMI[-2] 的作用不错
   P43  11-SVCCall, 15-SysTick 可以关注下

4. P32 进入异常服务例程,自动压栈 R0-R3,R12,LR(R14),PSR,PC(R15)

5. P36 栈指针分MSP(SP_main), PSP(SP_process)  ,push,pop 指令根据CONTROL[1](P40],自动判断当前那个SP
       如果有特殊要求可以通过MRS/MSR 来指定访问

6. P38 注意读PC 时,当前支流+4 ,和 arm9上 (PC+8)有区别,
        pc 奇数这句表示必须在thumb2 下

7. P39 特殊功能寄存器 MRS/MSR 读/写
       PSR 分:
       APSR 应用程序PSR    (N,Z,C,V,Q)[31-27]
       IPSR 中断号PSR      (Exception Number) [8-0] 
                       (如果是thread,那么值为0,因为没有0号异常)
       EPSR 执行PSR        (ICI/IT)[26:25] ,(T)[34],(ICI/IT)[15:10]

8. P39. 异常(中断) 控制register
       PRIMASK       开关中断
       FAULTMASK     开关异常
       BASEPRI       优先级

9. P40 快速开关中断异常
       CPSID I   ;PRIMASK=1 关
       CPSIE I   ;       =0 开

       CPSID F   ;FAULTMASK 关
       CPSIE F 

10. P40 CONTROL register
        CONTROL[1]   0---MSP (reset default) (handler mode 必须为0)
        CONTROL[1]   1---PSP

        CONTROL[0]   1---svc mode
        CONTROL[0]   0---user mode

11. P41 复位后为  thread mode + svc mode
        thread mode + svc mode 对系统空间阻止访问,MRS/MSR 也禁用,否则fault
        注意user ,svc mode 的切换  (control[0] + user 发生异常(+SVCall)

12. P43 异常相量表
    P109  ,16 个异常,240 IRQ

13. P46 使用满递减栈,双栈(svc,user),用于带kernel的 user ,kernel 切换很好

14. P47 奇特的复位过程,可以看下
         1. 从0x0地址取MSP
         2. 从0x4地址取PC的值,这个值是复位向量,LSB 必须为1,然后从这个地址所
            对应的地址处取值
            [reset] -->[0x0(MSP)][0x4(复位向量)]----->[Reset Vector] !
                       (0x0--开始是MSP,然后接下拉是向量表!!!)
                       (向量表中都是32bit 地址,比如0x4放的就是reset 执行指令位置)
           P148 图3.18

15. P50 指令后缀使用:
        S 更新APSR中标志   EQ,NE,LT,GT 等等
        等只有B(跳转)指令才能任意用,其他指令引入IF-THEN 块,在这个块中才可以加后缀

16. P51 注意thumb 语法和thumb 2 以及arm 的区别 ,在UAL 下thumb2 和arm 基本相似
        但也可以用thumb 语法明确 16bit 指令
        或者通过 .N(16bit)  .W(32bit) 来指定 16bit ,32bit

17. P59 自增自减,根据指令宽度, LDMIA Rd! ,{register list} 读后Rd 自增16bit
                           LDMIA.W RD! ,{register list} 读后Rd 自增32bit

18. P69 BX reg, 指令中reg 中最低位必须为1 (LSB=1) ,因为CM3 只在Thumb 中允许,否则fault
        而BLX reg arm ,thumb 都支持,根据LSB=1 thumb LSB=0 arm

19. P71 大多数16bit 算术逻辑指令,直接更新标志位 ,除 ADD.N Rd,Rn,Rm
        32bit 需要S 后缀来控制

20. P72 barrier 指令
        DMB --- 数据访问指令等前面数据访问指令完成才执行
        DSB --- 任何指令等前面数据访问指令完成才执行
                 (比如建立完所有向量后追加1条DSB P168)
        ISB --- 任何指令等前面指令完成才执行 
        依次往下表现barrier 更严格

21. P73 带符号 饱和运算指令  SSAT.W Rd #imm5,Rn,{,shift}
        不带符号饱和运算指令

22. P75 MRS/MSR   除APSR 可以在user级访问,其他必须特权级

23. P76 IF-THEN(IT)里最多有4条支流
        IT       ; 围起1条
        IT       ; 围起2条
        IT       ; 围起3条
        IT       ; 围起4条 
          =>为  T(then),E(else)
        IT指令的意义:
          当执行到跳转指令时,需要清洗流水线,处理器必须从跳转地址重新取指,
          IT可以改善一些小跳转!!!

24. P76 比较跳转CBZ ,   CBNZ , ,但范围很小只有0-126
        并且不会更新标志位

25. P80 跳转表指令TBB ,TBH

26. P84 CM3 存储映射
        0x0-------------------------------------------------------------------------4G
        |512M(代码)|512M(片上SRAM)|512M(片上设备)|512M(片外SRAM)|512M(片外设备)|512M|
                                                                               /    |
                                             ----------------------------------     |
                                             |内部私有外设总线|外部私有外设总线|其他|
                                            0xE0000000       0xE0040000    0xE0100000       

27. P85 CM3 存储器访问属性
        Bufferable, Cacheable,Executable,Sharable

28. P88 位带操作, 0bit --- 0x0(位带别名区偏移)  1bit ---- 0x4
         操作 位带区 bit2
           无别名                   使用别名
        LDR R0,=0x20000000        LDR R0,=0x22000008
        LDR R1,[R0]               MOV R1,#1
        ORR.W R1, #0x4
        STR R1,[R0]               STR R1,[R0]
        注意位带别名地址必须对齐到字, 位带别名操作原子的

29. P94 对齐的地址传输:
        LDR/STR, LDM/STM, PUSH/POP, LDREX/STREX,位带别名操作

30. P96 LDREX/STREX 实现mutex 的原理
        LDREX后,处理器会在内部标记出一段地址(范围可定义),后续执行到STR/STREX,
        只要其存储地址落在标记范围内,就会清除此标记,
        下一个STREX 执行先检查有没有做过标记和范围,否则驳回STREX

31. P113 子优先级至少1bit,所以抢占优先级最多7bit,这就造成了128级抢占情况
    P112  AIRCR(中断及复位控制寄存器) 0xE000_ED00
          其中[10:8]PRIGROUP 设置优先分组
             比如写5,表示从第5bit 处分,前面2bit表示抢占优先级(P171)
             一般3级:
                  3bit =>0x00,0x20,0x40,0x60,0x80,0xA0,0xC0,0xE0
                     这8个值有效

32. P116 向量表偏移寄存器(VTOR:0xE000_ED08)
          向量数对齐到2的整次幂,比如 32irq+16except=48 =>64 个
          然后64*4 =256,那么按0x100 对起的偏移量
       
         (P170 向量表移动的sample!)

33. P117 当某中断的服务例程开始执行时,就称此中断进入了active 状态,并且其悬起位
         会被硬件自动清除 ,一般ISR  执行完成,才能对新请求响应,所以软件在ISR中
     清除中断请求


34. P121 总线fault 状态寄存器(BFSR) 0xE000ED29

35. P122  MemManage fault 的原因:
          NVIC 中寄存器:
             MFSR(指出导致MemManage fault 的原因)
                DACCVIOL bit --- 数据访问违例
                DACCVIOL bit --- 取指访问违例
             MMAR---可读出引发此fault 的地址
          在不带mmu 的操作系统中,这个东西具体发挥什么先进功能???

        
36. P122 用法fault必须被使能才能正常响应,使能位是NVIC的系统handler控制及状态register
         的USGFAULTENA,
         总线fault 和 MemManage fault 则不需要enable   
         用法fault 的原因可以查 UFSR(用法fault状态寄存器) 0xE000_ED2A

37. P124 硬fault状态寄存器 0xE000_ED2C
          发生的三种情况: 调试, 其他fault 上访,取向量(异常处理时对向量表读取)

         注意各fault服务例程在处理后要清FSRs状态寄存器


38. P125 如果分kernel user,那么user svc 进入kernel,如果user 使用PSP ,那么
         kernel 访问PSP (MRS Rn,PSP) 找到user 的栈指针,然后分析LR

39. P127 关于PSVC的应用!!!
         OS在某中断活跃时尝试切入,线程模式,将触发use fault

40. P129 除软件中断寄存器外,所有中断控制及状态寄存器只能在特权级下访问


41. P130 enable disable 中断:(写1有效)
         SETENA0---SETENA7  0xE000_E100---E11C
         CLRENA0-7          0xE000_E180---E19C
         可以参考P168的sample! (REG addr offset = (N/32)*4)
        

42. P131 中断pending :
         SETPEND0-7 (写1悬起)   0xE000_E200---E21C
         CLRPEND0-7 (写1解悬)   0xE000_E280---E29C

43. P131 中断优先级寄存器 (8bit可分为高底两段,分别为抢占优先级和亚优先级)
         PRI_0---239 (每个8bit)(0xE000_E400-E4EF)
         及系统异常优先级寄存器(0xE000_ED18-ED23)

44. P132 中断活动状态 只读,处理器执行了ISR第1条指令后set1,
          直到ISR返回时才硬件清0
         ACTIVE0---7 (0xE000_E300---E31C)

45. P133 PRIMASK disable NMI,硬fault 之外所有异常(将当前优先级改为0)
         关中断  MOV R0,#1
                 MSR PRIMASK,R0  
                 或者     CPSID i

         开中断  MOV R0,#0
                 MSR PRIMASK,R0  
                 或者     CPSIE i

         FAULTMASK 连硬fault 也disable (将当前优先级改为-1)
         但注意异常退出时自动清0!

         BASEPRI 寄存器 用于mask 低于某优先级的中断
         BASEPRI_MAX 只能越设越高(只能扩大mask 范围)
         用户态不能访问BASEPRI
         根据优先级位数判断mask值是否有效
              3bit =>0x00,0x20,0x40,0x60,0x80,0xA0,0xC0,0xE0
                     这8个值有效
         通过动态计算的方法在P167

46. P134 系统handler控制及状态寄存器SHCSR(0xE000_ED24)
         使用这部分寄存器请小心
         一般在: 系统调用过程中执行上下文切换
                 使用软件模拟为定义指令功能

47. P135 中断控制及状态寄存器ICSR (0xE000_ED04)
         VCETPENDING   悬起的最高优先级的ISR的编号
         RETTOBAE   ???
         VECTACTIVE    当前活动的ISR编号
    P137 中断系统设置过程示例


48. P137 软件触发中断寄存器STIR(0xE000_EF00)
         写入8,则悬起IRQ #8
   (P170)  软件中断的使用说明 (P137通过软件触发某 IRQ n)
           1. 设置NVIC  USERSETMPEND位
           2. 写0xE000EF000后必须执行DSB(数据同步隔离)
      3. 该IRQ n必须使能
      4. 如果只是为了系统调用尽量用SVC 指令


49. P138  SysTick 控制及状态寄存器(0xE000_E010)
          SysTick reload寄存器(0xE000_E014)
          SysTick 当前数值寄存器(0xE000_E010)
          SysTick 校准数值寄存器(0xE000_E010)
          注意当处理器在调试时被halt,SytTick也暂停运行!

50. P141 响应异常的3个动作(!!!):
          1.入栈
             xPSR,PC,LR,R12,R3-R0
             当前上PSP 就压PSP,否则压MSP,进入服务例程一直使用MSP
    P142 如果栈有双字对齐,如果不对齐,先空4字节,然后压栈

          2.取向量
          3.更新寄存器

51. P143 异常返回(!!!)及指令
         BX LR (EXC_RETURN)
         POP {...,PC}
         LDR/LDM =>PC

         1.出栈, 2.更新NVIC
         (同级异常不可重入)


52. P144 咬尾中断(硬件处理)
         当处理器响应异常时,有发生异常,前次异常push的,仍旧对下次异常有效
    P145 晚到中断的方式基本同上, 省去一个pop,push


53. P147 异常返回值
         LR=
           0xFFFF_FFF1 返回handler mode (注意总是MSP!)
           0xFFFF_FFF9 返回thread mode,并使用MSP
           0xFFFF_FFFD 返回thread mode,并使用PSP
         正真的LR ,已经在主程被打断前自动入栈了,(LR=>EXC_RETURN,只是指出在那个SP!!!)
         0xFFFF_FFF1所指主程其实就是被抢占的服务例程

54. P148 质量LDM/STM 的中止和继续(xPSR开出若干ICI 位)


55. P148 异常响应时的faults
        1.入栈 => 总线fault BFSR bit4 STKERR
                  存储fault MFSR bit4 MSTKERR

        2.出栈 => 总线fault BFSR bit3 UNSTKERR
                  存储fault MFSR bit3 UNMSTKERR
 
        3.取向量 => 硬fault HFSR bit VECTTBL


        4. 无效返回 =>use fault  => UFSR bit2 INVPC ,bit1 INVSTATE
                 (if disabled then hard fault)

56.  P152.   在使用C开发时建议开启CM3的双字对齐
         #define NVIC_CCR ((volatile unsigned long *)(0xE000ED14))
         *NVIC_CCR = *NVIC_CCR |0x200;  //set STKALIGN
          

57.  P155 一个串口输出程序
     P160 使用mutex 实现信号量访问
           LDREX R2,[R1]
           ...
           STREX R2,R0, [R1]
           CMP R2,#0   => R2 == 0 那么就表示成功
     P161 使用位带实现互斥锁操作 (P88=> 位带别名操作原子的)
     P163 使用位段提取与查表跳转

58.  P165 主堆栈安全容量计算方法
          每个中断都可以嵌套,对于每1级至少需要8字(32字节),附加考虑ISR局部变量的大小量
         
          进程堆栈处了满足本进程所有函数调用的最大需求量外,好要保留8字,用于容纳第1级
          中断时被保护的寄存器(然后进入主栈)

59.  P167     RBIT R2,R1, 反转R1,并LSB对齐    R1=0xE0 =>R2=0x07
     (P55表)  CLZ  R1,R2  计算前导0个数       R1=0x07 =>R2=0x5  
 

60.  P169  一个ISR 汇编的主结构 (注意R4-R11要自己保护, 其他8个自动保护P141)
            PUSH {R4-R11,LR} ... POP {R4-R11,PC} 浪费了1字LR再压栈1次
            PUSH {R4-R11}  ... POP {R4-R11},BX LR 更节约

           
61.  P171 一个比较完整的中断处理例程
           其中SetupIrqHandler 负责建立向量表中断服务例程入口地址,所以向量表
           必须移动到RAM中,否则无法动态设置!!!

62.  P173 SVC使用:
            1.SVC 提供1个8位立即数
            2.SVC框架:
               svc_handler
                   TST   LR, #4     ;测试EXC_RETURN的bit2
                   ITE   EQ         ; 如果为0,下面包括2条指令 (P76)
                   MRSEQ R0,MSP     ; 如果==0 则使用MSP
                   MRSNE R0,PSP     ; 否则使用PSP
                   LDR   R1,[R0,#24] ;从栈中读取PC值 (+24见P142表9.1)
                                     ;注意自动压栈8个reg,
                                     ;总是8字对齐的所以不用考虑
                   LDRB  R0,[R1,#-2] ;从立既数取系统调用号
                                     ; P54表4.5 SVC 是16bit 指令
                   ;准备系统调用func,这需要适当调整入栈的PC及LR(EXC_RETRUN),
                                     来进入OS内部
                   BX LR              ;借异常返回形式,进入OS 内部,call sysfunc
                                      ;可使用TBB/TBH查表跳转加速
                                      ;返回user的情况如何处理 ???

63. P173 一个具体的SVC 例程
                   (也可以放在Rx,linuxEABI-R7) 但注意咬尾+晚到情况(P176)!!!
         P178 一个gcc 内联汇编的svc 代码

64. P180 一个MPU系统的布局
       __________________________________________________________
       |用户数据  | 用户栈     |   特权数据    |     特权栈     |
       ----------------------------------------------------------
        (user 级访问)          ^         (supervisor级访问)     ^
                              PSP                              MSP

65. P180 一个简单OS的init 和返回user级的过程
         (这里叫user级,不叫user空间,因为没有MMU)
         1. OS init
         2. 建立PSP,并创建任务的堆栈(PC,xPSR)
         3. 把EXC_RETURN 改为0xFFFFFFFD 返回 (P147)

66. P181 一个使用Systick及PendSV(优先级最低异常)来实现轮转调度和上下文切换的例子
          1. user程序#1 ===> 响应 Systick 异常后进入OS
          2.                 OS 执行系统管理
          3.                 OS 悬起PendSV以便从systick
                                异常返回后执行调度和switch context
          4.                 从systick返回如果无其他异常或中断则进入
                                PendSV ,这时通过PSP 保存user#1程序
                                堆栈帧,再把PSP 指向user#2程序的堆栈帧
                                修改EXC_RETURN,(#2堆栈帧pop2psp)并且返回  

67. P182  非基级thread mode的使用
          可以在服务例程中切换到thread mode,这样如果中断服务例程是用户程序的1部分
          ,可能需要让它在thread mode 下执行,以现在访问特权级下的资源
           比如:
               redirect_handler
                    PUSH  {LR}
                    SVC   #0)         ;通过系统服务,由特权级进入user级
                    (BL    User_IRQ_Handler )
                    (SVC   #1         ;执行完中断处理后,回特权级
                    POS   {PC}       ;本次中断返回
               上面带括号中的指令,包括SVC #0 返回部分,和SVC #1的进入部分
               ,都是在PSP+thread mode 下运行,理解这部分有助手动调栈的了解
 
               * 所以第1次调整PSP,是为了SVC0返回用,否则svc0不知道返回那里
                 因为SVC0是在PSP上返回,所以将SVC0的MSP上内容cpy过来

               * 第2次调整为了SVC1的返回,因为SVC1压栈在PSP,返回在MSP
                 所以,先将PSP上+0x18的内容读出(pop pc指令地址),然后
                 修改MSP上原来SVC0压入的LR(+0x18),然后PSP东西抛弃
                 然后Bx LR,返回到SVC1下面那条指令

               * 一般情况下异常是在Handler+MSP下,但是通过
                 1. 对PSP中已经压入的IPSR清0
                 2. 然后NVIC中配置和控制寄存器CCR的NONBASETHRDENA位设置
                 3. 最后修改EXC_RETURN,并BX LR返回,就可以返回到PSP+thread
                   特殊的一半在handler+MSP一半在thread+PSP
                 
                
           需要手动调栈具体见P183-184:
               主要就是 SVC #0 时特权级IRQ栈(MSP)上的内容到PSP上,
               然后进入user thread,注意进入user thread要清0,IPSR
                            而这步必须在特权级下做!!!

68. P185  1. 消灭存储器等待周期的方法 ???
          2. 中断向量尽量放代码区,防止取向量与入栈抢总线
          3. 限制非对齐访问

           一些汇编的技巧:
                1.使用带偏移的LDR/STR,可以省去地址增减等计算
                2. 上下文相关的变量放到一起,这样就可以创造使用LDM/STM
                   连续地址的数据传送
                3. 当遇到很小if then ,可以使用(ITxxx),最多包括4条
                4. 尽量使用thumb-2 指令
                5. 多用CM3新指令

69. P186   锁定图12.5

70. P191  消除systick 异常两次悬起,通过在异常处理中除能systick,并清除
              NVIC的Systick 悬起位(0xE000ED04)

71. P192  系统控制寄存器(0xE000_ED10)
            bit 4  SEVONPEND 
            bit 2  SLEEPDEEP    当进入睡眠mode时,使能外部的SLEEPDEEP
                                信号,以允许停止系统时钟
      bit 1  SLEEPONEXT

            图13.2进入睡眠模式的序列
      
       WFI(WaitForInterrupt)             WFE(WaitForEvent)
                      |                                |
                      |                                |             
                      | (清除事件锁存器) 事件锁存器!=1 |
                      <-------------------------<------|
                      |                            事件锁存器==1                          
       SLEEPDEEP!=1)  | (SLEEPDEEP==1)                 |
                |---------------|                      V                
                |               |                 (清除事件锁存器)
             V            V               (然后执行下条指令)
        进入普通睡眠(idle)   进入深度睡眠(suspend)  
        SLEEPING信号为高   SLEEPING和SLEEPDEEP都为高
    SLEEPDEEP为低!

72. P193 唤醒小节:  
    P194  SleepOnExit 自动睡眠功能演示


73. P194 多机通信功能 (有机会再看)


74. P202 CM3共支持8个regions,允许把每个region进1步划分为更小的 子region
          次外还允许启用1个背景region(即没有MPU时的全部地址空间)

75. P204 PRIVDEFENA =1 允许特权级访问背景region (图14.1)
         注意有个列外: 不管MPU如何限制,响应异常是的取向量操作,以及对系统分区(E000_xxxx)
         的访问不受影响


76. P205 1. MPURNR (MPU region 号) 0xE000ED98
         2. MPURBAR (基地址)       0xE000ED9c
               [31:N] N >=16   ADDR
               [4]             valid
               [3:0]           那个region
         3. MPURASR   (属性及容量) 0xE000EDA0

         当region 不够用,如果是特权级就放到背景region中
         
总之这款arm 单片机就其单片机的角色,的确强大,特别是MPU,user级特权级等概念一看就是跑RTOS的好材料,但是感觉象ucos这样简单的RTOS 不是很合适,但比较强大的也不行,比如linux,主要是因为MMU,虽然都有支持linux 的cortex m3的patch ,但没有了MMU,也没发挥出强大os的特性,不过也没见过那款单片机带MMU的,所以个人认为cortex m3 应该有一款自己特定的os ,才能最大发挥他的特点

 

 

 

 

 

 

 


       

 

 

 

 

 

        


        

 

 

      

 

 

 

 

 

 

 

 


 

 
阅读(7095) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~