CMSIS是Cortex微控制器软件接口标准(CortexMicroController Software Interface Standard)的缩写,这个是ARM定制的一个用于Cortex-M系列的一个标准,主要是为了提供通用api接口来访问内核和一些片上外设,提高代码的可移植性。
CMSIS有三个层:核内外设访问层CorePeripheral Access Layer(CPAL),中间件访问层Middleware Access Layer(MWAL),设备访问层(DevicePeripheral Access Layer)。
CPAL用于访问内核的寄存器和组件,如NVIC,调试系统等。该层是由ARM实现的。
MWAL用于对中间件的访问,现在该层还未实现。(也不知道所谓的中间件是什么东西)。
DPAL用于定义一些硬件寄存器的地址和一些外设访问函数,由芯片制造商实现。
CPAL层的实现就是Core_cm3.c文件,DPAL层的实现就是system_stm32f10x.c文件(似乎还应该加上外设的函数库)。
接下来就来了解一下Core_cm3.c里面有什么东东:
首先是汇编关键字__ASM和__INLINE的宏定义,支持不同的编译器。由于使用的是Keil,所以就只看第一种,__CC_ARM。
这里面的函数调用都只符合ARM过程调用标准的,如R0到R3用作参数和返回值传递,这也是这里面唯一用到的。
此外,在Keil中使用了__asm关键字后,编译器不会为函数增加返回指令,所以需要自己编写返回命令,也就是每个函数后面的 bx lr。
1. __ASM uint32_t__get_PSP(void):获取进程堆栈指针PSP。
2. __ASM void__set_PSP(uint32_t topOfProcStack):设置PSP。
3. __ASM uint32_t__get_MSP(void):获取主堆栈指针MSP。
4. __ASM void__set_MSP(uint32_t mainStackPointer):设置MSP。
5. __ASM uint32_t__REV16(uint16_t value):反转半字中字节顺序,如0xABCD反转后得到0xCDAB。
6. __ASM int32_t__REVSH(int16_t value):反转字节顺序,并做符号拓展。就是在__REV16函数得到的结果上再进行一次符号拓展。这两个函数主要是方便进行大小端的切换。
7. __ASM void__CLREX(void):清除由LDREX指令造成的互斥锁。LDREX和STREX是Cortex用来实现互斥访问,保护临界资源的指令,LDREX执行后,只有离它最近的一条存储指令(STR,STREX)才能执行,其他的存储指令都会被驳回,而CLREX就是用于清除互斥访问状态的标记。
8. __ASMuint32_t __get_BASEPRI(void):获取BASEPRI寄存器的值,优先级号高于该寄存器的中断都会被屏蔽(优先级号越大,优先级越低),为零时不屏蔽任何中断。
9. __ASM void__set_BASEPRI(uint32_t basePri):设置BASEPRI的值。
10. __ASM uint32_t__get_PRIMASK(void):PRIMASK是一个只有一位的寄存器,置位时屏蔽绝大部分的异常中断,只剩下NMI和HardFault可以响应。
11. __ASM void __set_PRIMASK(uint32_tpriMask):设置PRIMASK的值。
12. __ASM uint32_t __get_FAULTMASK(void):FAULTMASK也是一个只有一位的寄存器,为1时只有NMI才能响应,其他异常与中断全部被屏蔽。
13. __ASM void __set_FAULTMASK(uint32_tfaultMask):设置FAULTMASK的值。
14. __ASM uint32_t__get_CONTROL(void):获取CONTROL的值。寄存器CONTROL只有两位。CONTROL[0]选择特权级别,0为特权级,1为敌用户级。CONTROL[1]用于选择堆栈指针,0为MSP,1为PSP。
15. __ASM void __set_CONTROL(uint32_tcontrol):设置CONTROL寄存器的值。
BASEPRI,PRIMASK,FAULTMASK,CONTROL都只能在特权模式下被修改。
还有两个文件,一个是Core_cmFunc.h 和 Core_cmInstr.h 这两个文件是干嘛的,第一个文件是不同编译器下的一些系统级的汇编函数,第二个文件是不同编译器下的指令,我猜Keil公司这样做是为了兼容不同的编译器做设计的。把这两个头文件在Core_cm3.h头文件里注释掉也是可以的。说明这两个头文件对于keil开发环境是不需要的。
最后剩下Core_cm3.h文件了,这个文件是内核文件,就是定义了一些Cortex-M3的寄存器和一些函数,包括NVIC,MPU,SCB,SysTick,Debug寄存器。
最近在看LPC17XX系列的东东,发现这个文章说得有一些不对(上面是复制别人的),我用的是MDK4.14版本的开发环境。
说说我对这几个文件的理解:
第一个:core_cm3.c是定义了一些兼容各个开发环境的一些内嵌汇编函数,都是关于M3内核寄存器操作的函数。其实这个函数在工程中根本没有使用到,用的是Core_cmFunc.h的汇编函数,因为Core_cmFunc.h里的函数和core_cm3.c差不多是一样的。不信自己建一个工程,调试一下就知道不是进去core_cm3.c,而是去Core_cmFunc.h执行的。所以core_cm3.h包含了Core_cmFunc.h 和 Core_cmInstr.h头文件。
第二个:core_cm3.h定义了兼容各种编译器的关于debug和NVIC的一些函数,这些函数在中断设置中是很好用的。其中还有系统节拍器函数。我觉得core_cm3.h和core_cm3.c是一点关系都没有的,虽然他们同名。担不是头文件和源文件的关系。当然这个文件一开头还有内核寄存器的定义。下面才能用操作内核寄存器。
第三个:Core_cmInstr.h定义了很多内核指令的函数,这个应该不常用,先不管。
第四个:Core_cmFunc.h和core_cm3.c是非常相似的,大多数函数连函数名都一样的,不知道为什么要这样做,实际用函数是在Core_cmFunc.h里的函数,甚至把core_cm3.c从工程里删除,都没有问题的。但是屏蔽core_cm3.h里的Core_cmFunc.h 和 Core_cmInstr.h,就不行了。说明这个core_cm3.c是没什么用的,起码在Keil开发环境下是没用的。
暂时研究到这里,后面开始实践咯,就是使用几个文件中的各种函数试试。
上面是转载的,经过测试,上面说的不完全对,在老版本的core_cm3.c文件中,是有调用的很多汇编指令的,但是新版的文件就入上面所说的实际情况,core_cm3.c和core_cm3.h不相关,所以这个也是挺奇怪的。
上一篇:lp17xx的iap的向量表区别
下一篇:Linux定时器的使用
推荐阅读最新更新时间:2024-11-21 11:20
设计资源 培训 开发板 精华推荐
- 伺服电机控制方案
- 使用 Alpha and Omega Semiconductor 的 AOZ1960DI 的参考设计
- 用于基本配置的 ADR366A、3.3V 低功耗、低噪声电压基准的典型应用
- DC2491A,基于 LT3045EDD 20V、500mA、超低噪声、超高 PSRR RF LDO 稳压器的演示板
- 用于开/关控制应用的 AM2G-2407SH30Z 7.2V 2 瓦 DC-DC 转换器的典型应用
- 使用 ON Semiconductor 的 LM431SAI 的参考设计
- NCP1423、400mA 同步整流 PFM 升压 DC-DC 转换器的典型应用,具有真正截止和环形抑制器
- 基于树莓派单片机实现超低成本的双光纤网卡100BASE-FX(软硬件开源)
- PSoC1 - 使用 CY3210 套件的 32.768-kHz 外部晶体振荡器应用电路
- ZSR1000GTA 10 伏正电流调节器的典型应用