痞子衡嵌入式:ARM Cortex-M文件那些事(1)- 源文件(.c/.h/.s)

发布者:skyhcg最新更新时间:2019-12-20 来源: eefocus关键字:ARM  Cortex-M文件  源文件 手机看文章 扫描二维码
随时随地手机看文章

  众所周知,嵌入式开发属于偏底层的开发,主要编程语言是C和汇编。所以本文要讲的source文件主要指的就是c文件和汇编文件。


  尽管在平常开发中,我们都只会关注自己创建的.c/.h/.s源文件,但实际上我们不知不觉中也跟很多不是我们创建的源文件在打交道,那么问题来了,一个完整的嵌入式工程(以基于ARM Cortex-M控制器的工程为例)到底会包含哪些source文件呢?


  现在就到了痞子衡的show time了,痞子衡将这些文件按来源分为五类十种,下面痞子衡按类别逐一分析这些文件:


第一类:Provided by Committee

  第一类文件由C标准委员会提供,该类文件伴随着标准的发布而逐渐壮大。该类文件主要就是一种,即C标准库。


1. C standard Library

  大家都知道C语言是有标准的,常见的C标准有ANSI C(C89)、C99、C11,而C标准函数库(C Standard library)就是所有符合C标准的头文件的集合,以及常用的函数库实现程序。C标准库由Committee制订发布,通常会被包含在IDE里。列举一些常见文件和函数如下,是不是觉得似曾相识?


/* 常用文件 */ assert.h,stdio.h,stddef.h,stdint.h,string.h ...

/* 常用定义 */ bool,NULL,uint8_t,uint16_t,uint32_t...

/* 常用函数 */ assert(),printf(),memset(),memcpy()...


第二类:Provided by IDE(Compiler)

  第二类文件由IDE提供,C语言是编译型语言,需要编译器将C程序汇编成机器码,所有便有了一些跟编译器特性相关的函数库。


2. Compiler Library

  我们在开发嵌入式应用时需要借助集成开发环境(IDE),常见的IDE有GCC(GNUC),Keil MDK(ARMCC),IAR EWARM(ICCARM),这些IDE都有配套的C编译器,这些编译器是各有特色的,为了充分展示各编译器特色,配套的函数库便应运而生。


  编译器函数库是因IDE而异的,此处仅讲一个例子以供参考,需要了解更多需查看各IDE手册。


  以IAR EWARM里的DLib_Product_string.h文件为例,该文件中重定义了memcpy的实现:


#define _DLIB_STRING_SKIP_INLINE_MEMCPY

#pragma inline=forced_no_body

__EFF_NENR1NW2R1 __ATTRIBUTES void * memcpy(void * _D, const void * _S, size_t _N)

{

  __aeabi_memcpy(_D, _S, _N);

  return _D;

}


第三类:Provided by ARM

  第三类文件由ARM提供,嵌入式程序的执行靠的是控制器内核(此处指的内核便是ARM内核),ARM公司在设计内核时,提供了一些内核模块的接口,开发者可以通过这些接口访问内核资源,CMSIS header里就是这些内核模块资源的接口。


3. CMSIS header

  完整的CMSIS header目录应该是下面这个样子,而必须要关注的只有CMSISInclude下面的core_cmx.h文件


CMSIS

     Core      

     DAP            /* ARM debugger实现 */

     Driver         /* ARM统一的常用外设driver API */

     DSP_Lib        /* ARM优化实现的DSP Lib */

     Include        /* ARM内核资源接口 */

            arm_xx.h

            cmsis_xx.h

            core_cmx.h

     Lib            /* ARM优化实现的标准Lib */

     Pack

     RTOS           /* ARM推出的RTOS- RTX */

     RTOS2

     SVD

     Utilities

  core_cmx.h文件里定义了内核资源接口,里面最常用的三大模块是SCB,SysTick,NVIC,一个嵌入式开发的老手看到这些模块应该要向痞子衡挥手示意,来,让痞子衡看见你们的双手~~~


第四类:Provided by Chip Producer

  第四类文件是由ARM芯片生产商提供,我们在选型一个ARM芯片时,除了看ARM内核类型外,还得看芯片内部外设资源,是这些外设导致了ARM芯片差异,于是便有了各大ARM厂商争奇斗艳,比如NXP(Freescale), ST, Microchip(Atmel),ARM厂商赋予了ARM芯片各种外设资源,同时也会提供这些外设资源的接口。该类别下文件有四种:


4. device.h:芯片头文件,主要包含中断号定义(xx_IRQn)、外设模块类型定义(xx_Type) 、外设基地址定义(xx_BASE)。


/////////////////////////////////////////////////////

// 中断号定义

typedef enum IRQn {

  NotAvail_IRQn                = -128,

  /* Core interrupts */

  NonMaskableInt_IRQn          = -14,

  HardFault_IRQn               = -13,

  ...

  SysTick_IRQn                 = -1,

  /* Device specific interrupts */

  WDT0_IRQn                = 0,

  ...

} IRQn_Type;

////////////////////////////////////////////////////

// 外设寄存器定义

typedef struct {

  __IO uint32_t MOD;

  ...

  __IO uint32_t WINDOW;

} WWDT_Type;

#define WWDT_WINDOW_WINDOW_MASK       (0xFFFFFFU)

#define WWDT_WINDOW_WINDOW_SHIFT      (0U)

#define WWDT_WINDOW_WINDOW(x)         (((uint32_t)(((uint32_t)(x)) << WWDT_WINDOW_WINDOW_SHIFT)) & WWDT_WINDOW_WINDOW_MASK)

////////////////////////////////////////////////////

// 外设基地址定义

#define WWDT0_BASE                    (0x5000E000u)


5. startup_device.s:芯片中断向量表文件,主要包含中断向量表定义(DCD xx_Handler) ,以及各中断服务程序的弱定义(PUBWEAK)。 Note:该文件因编译器而异。


;;基于IAR的startup_device.s文件

        MODULE  ?cstartup

        ;; Forward declaration of sections.

        SECTION CSTACK:DATA:NOROOT(3)

        SECTION .intvec:CODE:NOROOT(2)

        PUBLIC  __vector_table

        PUBLIC  __Vectors_End

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; 中断向量表定义

        DATA

__vector_table

        DCD     sfe(CSTACK)

        DCD     Reset_Handler

        DCD     NMI_Handler

        DCD     HardFault_Handler

        ...

        DCD     SysTick_Handler

        ; External Interrupts

        DCD     WDT0_IRQHandler

        ...

__Vectors_End

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; 中断服务程序弱定义

        THUMB

        PUBWEAK WDT0_IRQHandler

        PUBWEAK WDT0_DriverIRQHandler

        SECTION .text:CODE:REORDER:NOROOT(2)

WDT0_IRQHandler

        LDR     R0, =WDT0_DriverIRQHandler

        BX      R0

WDT0_DriverIRQHandler

        B .

        END


6. system_device.c/h:芯片系统初始化文件,主要包含全局变量SystemCoreClock定义(提供芯片内核默认工作频率)、SystemInit()函数定义(完成最基本的系统初始化,比如WDOG初始化,RAM使能等,这部分因芯片设计而异)。


7. device SDK Library:官方提供的芯片外设SDK driver包文件,有了这个SDK包可以直接使用片内外设设计自己的应用,而不需要查看芯片手册里的外设模块寄存器去重写外设驱动。当然并不是每个厂商都有完善的SDK包,这取决于各厂商对软件服务的重视程度。


// 来自于NXP SDK的WWDT driver API

void WWDT_GetDefaultConfig(wwdt_config_t *config);

void WWDT_Init(WWDT_Type *base, const wwdt_config_t *config);

void WWDT_Deinit(WWDT_Type *base);

void WWDT_ClearStatusFlags(WWDT_Type *base, uint32_t mask);

void WWDT_Refresh(WWDT_Type *base);


第五类:Created by Developer

  第五类文件是开发者自己创建,用于实现开发者自己的嵌入式应用,分为应用系统启动文件,应用系统初始化文件,应用文件。其中应用系统启动和初始化文件属于main函数之前的文件,一般可以通用,大部分开发者并不关心其具体内容,但是了解其过程可以加深对嵌入式系统结构的理解。


8. reset.s: 应用系统复位启动文件,了解ARM原理的都知道,image前8个字节数据分别是芯片上电的初始SP, PC,其中PC指向的便是本文件里的Reset_Handler,这是芯片执行的第一个函数入口,该函数主要用于完成应用系统初始化工作,包含应用中断向量表重定向、调用芯片系统初始化、ARM系统寄存器rx清零、初始化应用程序各数据段、初始化ARM系统中断、跳转main函数。


// 一段经典的startup code

        SECTION .noinit : CODE

        THUMB

        import SystemInit

        import init_data_bss

        import main

        import CSTACK$$Limit

        import init_interrupts

        EXTERN __vector_table

        REQUIRE __vector_table

#define SCB_BASE            (0xE000ED00)

#define SCB_VTOR_OFFSET     (0x00000008)

        PUBLIC  Reset_Handler

        EXPORT  Reset_Handler

Reset_Handler

        // Mask interrupts

        cpsid   i

        // Set VTOR register in SCB first thing we do.

        ldr     r0,=__vector_table

        ldr     r1,=SCB_BASE

        str     r0,[r1, #SCB_VTOR_OFFSET]

        // Init the rest of the registers

        ldr     r2,=0

        ldr     r3,=0

        ldr     r4,=0

        ldr     r5,=0

        ldr     r6,=0

        ldr     r7,=0

        mov     r8,r7

        mov     r9,r7

        mov     r10,r7

        mov     r11,r7

        mov     r12,r7

        // Initialize the stack pointer

        ldr     r0,=CSTACK$$Limit

        mov     r13,r0

        // Call the CMSIS system init routine

        ldr     r0,=SystemInit

        blx     r0

        // Init .data and .bss sections

        ldr     r0,=init_data_bss

        blx     r0

        // Init interrupts

        ldr     r0,=init_interrupts

        blx     r0

        // Unmask interrupts

        cpsie   i

        // Set argc and argv to NULL before calling main().

        ldr     r0,=0

        ldr     r1,=0

        ldr     r2,=main

        blx     r2

__done

        B       __done

        END


9. startup.c:应用系统初始化文件,该文件里主要包含两个初始化函数,init_data_bss()、 init_interrupts(),data, bss段数据的初始化是为了保证嵌入式系统中所有全局变量能有一个开发者指定的初值。由于data,bss段的位置是在链接阶段确定的,所以此处需要配合linker文件才能找到正确的data,bss位置,linker文件是因IDE而异的,所有本文件要想做到通用,必须增加各IDE条件编译,此处仅以IAR下的实现为例:


//基于IAR的startup.c文件

#if (defined(__ICCARM__))

#pragma section = ".intvec"

#pragma section = ".data"

#pragma section = ".data_init"

#pragma section = ".bss"

#pragma section = "CodeRelocate"

#pragma section = "CodeRelocateRam"

#endif

void init_data_bss(void)

{

#if defined(__ICCARM__)

    uint8_t *data_ram, *data_rom, *data_rom_end;

    uint8_t *bss_start, *bss_end;

    uint8_t *code_relocate_ram, *code_relocate, *code_relocate_end;

    uint32_t n;

// 初始化data段 .data section (initialized data section)

    data_ram = __section_begin(".data");

[1] [2]
关键字:ARM  Cortex-M文件  源文件 引用地址:痞子衡嵌入式:ARM Cortex-M文件那些事(1)- 源文件(.c/.h/.s)

上一篇:痞子衡嵌入式:ARM Cortex-M文件那些事(0)- 文件关联
下一篇:痞子衡嵌入式:ARM Cortex-M文件那些事(2)- 链接文件(.icf)

推荐阅读最新更新时间:2024-11-12 15:45

别意外!ARM芯片未来将运行在PC上
近日,高通对外正式宣布称,自家是目前唯一一家与ARM达成协议,获得推出可运行 Windows系统芯片的授权许可。不过,ARM高管近日澄清称,ARM并没有阻止授权芯片厂商开发可运行x86系统的芯片,而且法律上也没有限制。 ARM 坦承,在去年被日本软银收购之后,就已经置顶了“所有计算设备”范畴的规划,以扩大公司的业务范围。因此,ARM芯片未来出现在PC上并不是意外。 过去微软在尝试Windows RT失败之后,没有正式宣布放弃,所以选择了高通作为合作伙伴,通过在ARM芯片的基础上开发模拟器,达到运行传统x86应用程序的目的。虽然现在还不清楚x86系统能够真正利用ARM芯片的哪些优势,但是在200美元PC这个价位上,高通显然对英特尔形
[嵌入式]
ARM——体系架构
1.ARM简介 ARM是Advanced RISC Machines的缩写,它是一家微处理器行业的知名企业,该企业设计了大量高性能、廉价、耗能低的RISC (精简指令集)处理器。公司的特点是只设计芯片,而不生产。它将技术授权给世界上许多著名的半导体、软件和OEM厂商,并提供服务。 1.1 ARM(Advanced RISC Machines)的几种含义: 1、ARM是一种RISC MPU/MCU的体系结构,如同x86架构是一种CISC体系结构一样。另外,还有MIPS架构、PowerPC架构等等。 2、ARM是Advanced RISC Machine Limited公司的简称。 3、ARM是Advanced R
[单片机]
<font color='red'>ARM</font>——体系架构
赛普拉斯宣布支持Arm平台安全架构(PSA)的Trusted Firmware-M
赛普拉斯超低功耗双核PSoC®6 MCU提供PSA定义的最高级别保护。 先进嵌入式解决方案的领导者赛普拉斯半导体公司(纳斯达克代码:CY)近日宣布,推出基于PSoC®6 MCU的支持Arm®平台安全架构(PSA)Trusted Firmware-M的参考实例,是符合PSA标准的最高级别保护能力的解决方案。通过利用PSA全套威胁模型、安全分析、硬件和固件架构规范以及Trusted Firmware-M设计参考,物联网(IoT)设计人员可以快速、轻松地使用PSoC 6 MCU实现安全设计。 Arm物联网设备IP业务部副总裁兼总经理Paul Williamson表示:“互联设备正在快速发展,为了真正实现这些技术所带来的效益,安全
[网络通信]
基于ARM的等精度测频在机组转速测控中的应用
  电力系统的频率反映了发电机组发出的有功功率与负荷所需有功功率的平衡情况。高精度和高可靠性的频率测量对整个电力系统的稳定运行有着至关重要的作用,机组在开停机过程中,频率变化范围比较大,变化速度比较快,传统的测频方法由于固有的缺陷,难以很好解决这一问题。等精度测量方法的测量精度不随被测脉冲的频率高低变化而改变,只与标准计数器有关,可以使测量精度大大提高,并且闸门时间可变,可快速反应频率的变化。   1 传统测量方法的原理及误差分析   传统测量方法有2种,一种是测频法(M 法),是对被测信号在闸门时间(T—Nfo,N 个基准信号脉冲的时间)内的脉 内,对于任意的f不能保证在T时间内正好有M 个T ,因此会产生最大
[单片机]
基于<font color='red'>ARM</font>的等精度测频在机组转速测控中的应用
Azure ARM (7) ARM Template - 使用Visual Studio编辑
  之前介绍的ARM Template,都是使用文本编辑器来编辑JSON文件的。   文本讲介绍如何使用Visual Studio,编辑JSON Template。   本文使用Visual Studio 2015 with Update 3进行编辑,安装了Azure SDK 2.9。   如果读者使用的是Visual Studio 2013和Azure SDK 2.9,大部门的界面是和笔者的截图类似。笔者强烈建议安装最新的Visual Studio和Azure SDK。   前提:   1.安装Visual Studio 2015 with Update 3   2.安装Azure SDK 2.9   
[单片机]
Azure <font color='red'>ARM</font> (7) <font color='red'>ARM</font> Template - 使用Visual Studio编辑
基于ARM9的媒体播放器的设计方案
1 引言   计算机多媒体技术和网络技术飞速发展使得基于流媒体的多媒体应用也被运用在多种领域,特别是网络可视电话、远程监控、视频点播领域。伴随着计算机多媒体压缩技术的成熟和网络传输技术的发展,开发实时可靠、多功能、数字化、操作简单的基于计算机网络通讯技术和多媒体应用的网络化流媒体播放器已成为计算机、通信、消费电子产品领域(3C 产业-Computer、Communication、Consumer Electronics)技术发展的主要方向之一。   2 系统硬件设计   本文使用TQ2440 开发板作为硬件平台。   S3C2440AL 是控制核心,负责控制所有辅助设备。存储器采用SDRAM 和Flash 两种类型,能满足系统
[电源管理]
基于<font color='red'>ARM</font>9的媒体播放器的设计方案
arm linux 内核 startkenal 的问题
arm linux 内核 start_kenal 的问题我费解了很久 还是不解:: 在include\linux\Cupmask.h中有如下定义 typedef struct { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t; extern cpumask_t _unused_cpumask_arg_; #define cpu_set(cpu, dst) __cpu_set((cpu), &(dst)) static inline void __cpu_set(int cpu, volatile cpumask_t *dstp) { set_bit(cpu, dstp- bits); }
[单片机]
Arm中国自主研发“周易”平台,让AI无处不在
随着新技术的成熟,新型的先进应用将来自5G、人工智能(AI)和物联网(IoT)的融合,这种融合将创造出一个智能互联的全新未来,对所有个人、行业、社会和经济产生积极影响。Arm预计到2035年将有1万亿的物联网设备,在这些设备上实现本地人工智能,是人工智能应用的必然趋势。而要做到这一点,必须进一步降低人工智能的算力成本。 为此,Arm中国自主研发了“周易”平台这样一个适配性强、开放通用的人工智能平台,其主要包括软件框架Tengine和全新的硬件处理器——人工智能处理单元(AIPU),其中Tengine软件框架针对边缘设备的推理做了深度优化和实现。周易平台也支持Arm CPU、Mali GPU以及第三方硬件,专注于边缘推理,能够提
[物联网]
<font color='red'>Arm</font>中国自主研发“周易”平台,让AI无处不在
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved