99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

痞子衡
認證:普通會員
所在專題目錄 查看專題
從文件角度看Cortex-M開發(1) - 源文件
從文件角度看Cortex-M開發(2) - 鏈接文件
從文件角度看Cortex-M開發(3) - 工程文件
從文件角度看Cortex-M開發(4) - 可重定向文件
從文件角度看Cortex-M開發(5) - 映射文件
從文件角度看Cortex-M開發(6) - 可執行文件
作者動態 更多
一種多MCU分時復用Flash啟動的創新方法(下)
2星期前
一種多MCU分時復用Flash啟動的創新方法(上)
3星期前
RT10xx系列UART SDP能設置多高波特率?
06-06 09:51
有時候MCU片內合封Flash就是個黑盒子!
05-15 13:52
有人說高性能MCU片內合封Flash不可靠?
05-13 14:33

從文件角度看Cortex-M開發(1) - 源文件

大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家講的是嵌入式開發里的source文件。

眾所周知,嵌入式開發屬于偏底層的開發,主要編程語言是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目錄應該是下面這個樣子,而必須要關注的只有\CMSIS\Include下面的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");
    data_rom = __section_begin(".data_init");
    data_rom_end = __section_end(".data_init");
    n = data_rom_end - data_rom;
    if (data_ram != data_rom)
    {
        while (n--)
        {
            *data_ram++ = *data_rom++;
        }
    }
// 初始化bss段 .bss section (zero-initialized data)
    bss_start = __section_begin(".bss");
    bss_end = __section_end(".bss");
    n = bss_end - bss_start;
    while (n--)
    {
        *bss_start++ = 0;
    }
// 初始化CodeRelocate段 (執行在RAM中的函數(由IAR指定的__ramfunc修飾的函數)).
    code_relocate_ram = __section_begin("CodeRelocateRam");
    code_relocate = __section_begin("CodeRelocate");
    code_relocate_end = __section_end("CodeRelocate");
    n = code_relocate_end - code_relocate;
    while (n--)
    {
        *code_relocate_ram++ = *code_relocate++;
    }
#endif
}
void init_interrupts(void)
{
    NVIC_ClearEnabledIRQs();
    NVIC_ClearAllPendingIRQs();
}

10. application.c/h:應用文件,此處便是主函數以及各功能函數的集合了,嵌入式老司機們,請開始你的表演~~~

void taskn(void)
{
    // Your task code
}
int main(void)
{
    printf("hello world\r\n");
    taskn();
    ...
    return 0;
}

至此,嵌入式開發里的各種來源的source文件痞子衡便介紹完畢了,掌聲在哪里~~~

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 4
收藏 4
關注 41
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧
主站蜘蛛池模板: 国产精品人妻无码久久久郑州天气网 | 小尤奈无码视频 | 女人与牲口性恔配视频免费 | 日日碰狠狠丁香久燥 | 午夜网站在线观看 | 国产欧美一区二区三区久久人妖 | 日韩av一区二区三区四区 | 操大爷影院 | 国产成人无精品久久久久国语 | 国产福利萌白酱在线观看视频 | 精品人妻中文字幕有码在线 | 99视频播放 | 国产剧情AV麻豆香蕉精品 | 亚洲人成网站在线观看妞妞网 | 婷婷成人基地 | 996热re视频精品视频这里 | 天天操天天碰视频 | 一区二区三区四区日韩 | 欧美人与禽猛交乱配视频 | 性欧美乱妇com喷浆水多 | 久久久国产精品萌白酱免费 | 精品无码一区二区的天堂 | 亚洲另类色区欧美日韩图片 | 亚洲国产精品乱码一区二区三区 | 高清视频在线观看免费播放 | 国产免费一区二区在线a片视频 | 五月丁香 | 一区二区在线播放视频 | 国产丝袜美女一区二区三区 | 国产尤物av尤物在线观看 | 日韩成人精品一区二区三区 | 伦理片一级片 | 精品国产乱码久久久久久浪潮 | 三区四区乱码不卡 | 二区免费 | 亚洲国产精品久久久久日本竹山梨 | 久久精品国产欧美 | 精品国产伦一区二区三区 | 玩弄人妻奶水无码av在线 | 国产精品久久久久久久久久了 | 亚洲精品无码久久久久AV老牛 |