打印
[牛人杂谈]

CMSIS的结构

[复制链接]
2150|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
643757107|  楼主 | 2016-10-31 21:51 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
ARM 公司于 2008 年 11 月 12 日发布了 ARM Cortex-M 微控制器软件接口标准(CMSIS:Cortex Microcontroller
Software Interface Standard)。CMSIS 是独立于供应商的 Cortex-M 微控制器系列硬件抽象层,为芯片厂商和中间件供应
商提供了连续的、简单的微控制器软件接口,简化了软件复用,降低了 Cortex-M0/M3/M4 上操作系统的移植难度,并缩短了新入门
的微控制器开发者的学习时间和新产品的上市时间。
根据近期的调查研究,软件开发已经被嵌入式行业公认为最主要的开发成本。图4.1.1 为近年来软件开发与硬件开发成本对比图。
因此,ARM 与 Atmel、IAR、Keil、hami-nary Micro、Micrium、NXP、SEGGER 和 ST 等诸多芯片和软件厂商合作,将所有 Cortex
芯片厂商产品的软件接口标准化,制定了 CMSIS 标准。此举意在降低软件开发成本,尤其针对新设备项目开发,或者将已有软件移
植到其他芯片厂商提供的基于 Cortex 微控制器的微控制器的情况。有了该标准,芯片厂商就能够将他们的资源专注于产品外设特性
的差异化,并且消除对微控制器进行编程时需要维持的不同的、互相不兼容的标准的需求,从而达到降低开发成本的目的。
CMSIS  标准的软件架构
如图 所示,基于 CMSIS 标准的软件架构主要分为以下 4 层:用户应用层、操作系统及中间件接口层、CMSIS 层、硬件
寄存器层。其中 CMSIS 层起着承上启下的作用:一方面该层对硬件寄存器层进行统一实现,屏蔽了不同厂商对 Cortex-M 系列微控
制器核内外设寄存器的不同定义;另一方面又向上层的操作系统及中间件接口层和应用层提供接口,简化了应用程序开发难度,使开
发人员能够在完全透明的情况下进行应用程序开发。也正是如此,CMSIS 层的实现相对复杂。



沙发
643757107|  楼主 | 2016-10-31 21:52 | 只看该作者
CMSIS 层主要分为 3 部分:
① 核内外设访问层(CPAL:Core Peripheral Access Layer):由 ARM 负责实现。包括对寄存器地址的定义,对核寄存器、
NVIC、调试子系统的访问接口定义以及对特殊用途寄存器的访问接口(如 CONTROL 和 xPSR)定义。由于对特殊寄存器的访问以内联
方式定义,所以 ARM 针对不同的编译器统一用__INLINE 来屏蔽差异。该层定义的接口函数均是可重入的。
② 中间件访问层(MWAL:Middleware Access Layer):由 arm 负责实现,但芯片厂商需要针对所生产的设备特性对该层进行
更新。该层主要负责定义一些中间件访问的 API 函数,例如为 TCP/IP 协议栈、SD/MMC、USB 协议以及实时操作系统的访问与调
试提供标准软件接口。该层在 1.1 标准中尚未实现。
③ 设备外设访问层(DPAL:Device Peripheral Acess Layer):由芯片厂商负责实现。该层的实现与 CPAL 类似,负责对硬
件寄存器地址以及外设访问接口进行定义。该层可调用 CPAL 层提供的接口函数,同时根据设备特性对异常向量表进行扩展,以处理
相应外设的中断请求。
对一个 Cortex-M 微控制系统而言,CMSIS 通过以上三个部分实现了:
  定义了访问外设寄存器和异常向量的通用方法;
  定义了核内外设的寄存器名称和核异常向量的名称;
  为 RTOS 核定义了与设备独立的接口,包括 Debug 通道。
这样芯片厂商就能专注于对其产品的外设特性进行差异化,并且消除他们对微控制器进行编程时需要维持的不同的、互相不兼容
的标准需求,以达到低成本开发的目的。

使用特权

评论回复
板凳
643757107|  楼主 | 2016-10-31 21:53 | 只看该作者

CMSIS  文件的规范
  基本规范
  CMSIS 的 C 代码遵照 MISRA 2004 规则。
  使用标准 ANSI C 头文件<stdint.h>中定义的标准数据类型。
  由#define 定义的包含表达式的常数必须用括号括起来。
  变量和参数必须有完全的数据类型。
  CPAL 层的函数必须是可重入的。
  CPAL 层的函数不能有阻塞代码,也就是说等待、 查询等循环必须在其他的软件层中。

  定义每个异常/中断的:
  每个异常处理函数的后缀是_Handler,每个中断处理器函数的后缀是_IRQHandler。
  默认的异常中断处理器函数(弱定义)包含一个无限循环。
  用#define 将中断号定义为后缀为_IRQn 的名称。
  推荐规范
  定义通用寄存器、外设寄存器和 CPU 指令名称时使用大写。
  定义外设访问函数、中断函数名称时首字母大写。
  对于某个外设相应的函数,一般用该外设名称作为其前缀。
  按照 Doxygen 规范撰写函数的注释,注释使用 C90 风格(/* 注释 */) 或者 C++风格(// 注释),函数的注释应包含
以下内容:
  一行函数简介。
  参数的详细解释。
  返回值的详细解释。
  函数功能的详细描述。

使用特权

评论回复
地板
643757107|  楼主 | 2016-10-31 21:56 | 只看该作者
文件结构
CMSIS 的文件结构如图 4.2.1 所示(以 NuMiro M451 为例)。其中 stdint.h 包括对 8 位、16 位、32 位等类型指示符
的定义,主要用来屏蔽不同编译器之前的差异。core_cm4.h 中包括 Cortex-M4 核的全局变量声明和定义,并定义一些静态功能函
数。M451Series.h 定义了与特定芯片厂商相关的寄存器以及各中断异常号,并可定制 Cortex-M4 核中的特殊设备, 如 MCU、中
断优先级位数以及寄存器定义。 虽然 CMSIS 提供的文件很多,但在应用程序中只需包含.h。

  数据类型及 I/O  类型限定符
HAL 层使用标准 ANSI C 头文件 stdint.h 定义的数据类型。 I/O 类型限定符用于指定外设寄存器的访问限制,定义如表
4.1.1 所列。
表 4.2.1 I/O 类型限定符


使用特权

评论回复
5
643757107|  楼主 | 2016-10-31 21:58 | 只看该作者
  CMSIS  版本号
CMSIS 标准有多个版本号, 对于 ARM Cortex-M4 处理器, 在 core_cm4.h 中定义所用 CMSIS的版本,如程序清单4.2.1。
程序清单 4.2.1 CMSIS 版本号
#define __CM4_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */
#define __CM4_CMSIS_VERSION_SUB (0x01) /*!< [15:0] CMSIS HAL sub version */
#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16) | \__CM4_CMSIS_VERSION_SUB)

  CMSIS  内核
对于 ARM Cortex-M4 处理器,在头文件 core_cm4.h 中定义,如程序清单 4.2.2。
程序清单 4.2.2 确认当前 Cortex-M 内核
#define __CORTEX_M (0x04) /*!< Cortex-M Core */
  工具链
CMSIS 支持目前嵌入式开发的三大主流工具链,即 ARM ReakView(armcc)、IAR EWARM(iccarm)以及 GNU 工具链(gcc)。
通过在 core_cm4.h 中的如下定义,来屏蔽一些编译器内置关键字的差异,如程序清单 4.2.3。
程序清单 4.2.3 CMSIS 支持的工具链
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#define __STATIC_INLINE static __inline
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for IAR Compiler */
#define __INLINE inline /*!< inline keyword for IAR Compiler */
#define __STATIC_INLINE static inline
#elif defined ( __TMS470__ )
#define __ASM __asm /*!< asm keyword for TI CCS Compiler */
#define __STATIC_INLINE static inline
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#define __STATIC_INLINE static inline
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#define __STATIC_INLINE static inline
#endif
这样,CPAL 中的功能函数就可以被定义成静态内联类型(static inline),实现编译优化。

使用特权

评论回复
6
643757107|  楼主 | 2016-10-31 22:00 | 只看该作者
  中断异常
CMSIS 对异常和中断标识符、中断处理函数名以及中断向量异常号都有严格的要求。异常和中断标识符需加后缀_IRQn,系统
异常向量号必须为负值,而设备的中断向量号是从 0 开始递增,具体的定义在 M451Series.h 文件,如下所示(以 M451 微控制器系
列为例):
程序清单 4.2.4 M451 的中断异常
typedef enum IRQn
{
/****** Cortex-M4 Processor Exceptions Numbers ******/
NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
MemoryManagement_IRQn = -12, /*!< 4 Memory Management Interrupt */
BusFault_IRQn = -11, /*!< 5 Bus Fault Interrupt */
UsageFault_IRQn = -10, /*!< 6 Usage Fault Interrupt */
SVCall_IRQn = -5, /*!< 11 SV Call Interrupt */
DebugMonitor_IRQn = -4, /*!< 12 Debug Monitor Interrupt */
PendSV_IRQn = -2, /*!< 14 Pend SV Interrupt */
SysTick_IRQn = -1, /*!< 15 System Tick Interrupt */
/****** M451 Specific Interrupt Numbers *****/
BOD_IRQn = 0, /*!< Brown Out detection Interrupt */
IRC_IRQn = 1, /*!< Internal RC Interrupt */
PWRWU_IRQn = 2, /*!< Power Down Wake Up Interrupt */
RAMPE_IRQn = 3, /*!< SRAM parity check failed Interrupt */
CKFAIL_IRQn = 4, /*!< Clock failed Interrupt */
RTC_IRQn = 6, /*!< Real Time Clock Interrupt */
TAMPER_IRQn = 7, /*!< Tamper detection Interrupt */
WDT_IRQn = 8, /*!< Watchdog Timer Interrupt */
WWDT_IRQn = 9, /*!< Window Watchdog Timer Interrupt */
EINT0_IRQn = 10, /*!< External Input 0 Interrupt */
EINT1_IRQn = 11, /*!< External Input 1 Interrupt */
EINT2_IRQn = 12, /*!< External Input 2 Interrupt */
EINT3_IRQn = 13, /*!< External Input 3 Interrupt */
EINT4_IRQn = 14, /*!< External Input 4 Interrupt */
EINT5_IRQn = 15, /*!< External Input 5 Interrupt */
GPA_IRQn = 16, /*!< GPIO Port A Interrupt */
GPB_IRQn = 17, /*!< GPIO Port B Interrupt */
GPC_IRQn = 18, /*!< GPIO Port C Interrupt */
GPD_IRQn = 19, /*!< GPIO Port D Interrupt */
GPE_IRQn = 20, /*!< GPIO Port E Interrupt */
GPF_IRQn = 21, /*!< GPIO Port F Interrupt */
SPI0_IRQn = 22, /*!< SPI0 Interrupt */
SPI1_IRQn = 23, /*!< SPI1 Interrupt */
BRAKE0_IRQn = 24, /*!< BRAKE0 Interrupt */
PWM0P0_IRQn = 25, /*!< PWM0P0 Interrupt */
PWM0P1_IRQn = 26, /*!< PWM0P1 Interrupt */
PWM0P2_IRQn = 27, /*!< PWM0P2 Interrupt */
BRAKE1_IRQn = 28, /*!< BRAKE1 Interrupt */
PWM1P0_IRQn = 29, /*!< PWM1P0 Interrupt */
PWM1P1_IRQn = 30, /*!< PWM1P1 Interrupt */
PWM1P2_IRQn = 31, /*!< PWM1P2 Interrupt */
TMR0_IRQn = 32, /*!< Timer 0 Interrupt */
TMR1_IRQn = 33, /*!< Timer 1 Interrupt */
TMR2_IRQn = 34, /*!< Timer 2 Interrupt */
TMR3_IRQn = 35, /*!< Timer 3 Interrupt */
UART0_IRQn = 36, /*!< UART 0 Interrupt */
UART1_IRQn = 37, /*!< UART 1 Interrupt */
I2C0_IRQn = 38, /*!< I2C 0 Interrupt */
I2C1_IRQn = 39, /*!< I2C 1 Interrupt */
PDMA_IRQn = 40, /*!< Peripheral DMA Interrupt */
DAC_IRQn = 41, /*!< DAC Interrupt */
ADC00_IRQn = 42, /*!< ADC0 Source 0 Interrupt */
ADC01_IRQn = 43, /*!< ADC0 Source 1 Interrupt */
ACMP01_IRQn = 44, /*!< Analog Comparator 0 and 1 Interrupt */
ADC02_IRQn = 46, /*!< ADC0 Source 2 Interrupt */
ADC03_IRQn = 47, /*!< ADC0 Source 3 Interrupt */
UART2_IRQn = 48, /*!< UART2 Interrupt */
UART3_IRQn = 49, /*!< UART3 Interrupt */
SPI2_IRQn = 51, /*!< SPI2 Interrupt */
USBD_IRQn = 53, /*!< USB device Interrupt */
USBH_IRQn = 54, /*!< USB host Interrupt */
USBOTG_IRQn = 55, /*!< USB OTG Interrupt */
CAN0_IRQn = 56, /*!< CAN0 Interrupt */
SC0_IRQn = 58, /*!< Smart Card 0 Interrupt */
TK_IRQn = 63 /*!< Touch Key Interrupt */
} IRQn_Type;
CMSIS 对系统异常处理函数以及普通的中断处理函数名的定义也有所不同。系统异常处理函数名需加后缀“_Handler”,而普
通中断处理函数名则加后缀“_IRQHandler”。这些异常中断处理函数被定义为 weak 属性, 以便在其他的文件中重新实现时不出现
重复定义的错误。这些处理函数的地址用来填充中断异常向量表,并在启动代码中给以声明,例如:BOD_IRQHandler、
WDT_IRQHandler、TMR0_IRQHandler、UART0_IRQHandler 等。


使用特权

评论回复
7
643757107|  楼主 | 2016-10-31 22:01 | 只看该作者
  安全机制
在嵌入式软件开发过程中,代码的安全性和健壮性一直是开发人员所关注的,因此 CMSIS 在这方面也作出了努力,所有的 CMSIS
代码都基于 MISRA-C2004(Motor Industry Software Reliability Association forthe C programming language)
标准。MIRSA-C 2004 制定了一系列安全机制用来保证驱动层软件的安全性,是嵌入式行业都应遵循的标准。对于不符合 MISRA 标
准的,编译器会提示错误或警告,这主要取决于开发者所使用的工具链。

使用特权

评论回复
8
gejigeji521| | 2016-10-31 23:56 | 只看该作者
都是这些工作才让开发不会太复杂的,现场越来越偏向软件了

使用特权

评论回复
9
643757107|  楼主 | 2016-11-13 12:36 | 只看该作者
现在的ARM内核单片机开发都离不开这个CMSIS了。

使用特权

评论回复
10
玛尼玛尼哄| | 2016-11-13 23:17 | 只看该作者
要搞清楚层与层之间是怎么做,怎么用。

使用特权

评论回复
11
捉虫天师| | 2016-11-14 11:24 | 只看该作者
看了好多ARM的都是用这个,研究研究。

使用特权

评论回复
12
643757107|  楼主 | 2016-11-14 16:50 | 只看该作者
EFM32的也用了这个,不过他们搞的elib很酷。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

215

主题

3873

帖子

11

粉丝