python复数运算 相量_CM3权威指南CnR2 阅读笔记

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 ,才能最大发挥他的特点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值