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

liuxiaofei126
認證:VIP會員
所在專題目錄 查看專題
多功能控制小車
STM32定時器的來龍去脈
底層程序如何在STM32上編譯運行
從IIC實測波形入手搞懂IIC通信
實例講解(一)移位寄存器
單片機之USB 硬件和數據的四種傳輸方式
作者動態 更多
stm32知識點總結
2021-11-24 23:12
工程師單片機LED項目
2021-11-11 07:46
電容型負載對跟隨器的影響
2021-10-28 23:33
圖騰柱和互補推挽兩個“小冤家”
2021-10-22 23:15
學習單片機的捷徑
2021-10-17 23:07

底層程序如何在STM32上編譯運行

C程序是如何運行的 

STM32F0xx 系列是ARM Cortex-M0架構,地址空間32位,也就是4G Bytes的訪問范圍。數據和代碼使用同一編址,下圖是地址空間的布局:

實際上單片機用到的資源很少,地址空間大部分都沒有內容。我使用的STM32F072C8T6帶有64kB的Flash ROM, 16kB的SRAM,起始分別是 0x08000000 和 0x20000000. (由于有硬件映射功能,在0x00000000也就是最低地址,還可以訪問ROM或者RAM的內容). 單片機片上外設的寄存器,則分布在更高的地址空間。讀寫這些寄存器,在CPU看來和讀寫內存(RAM)操作是一樣的。

所以,C語言訪問設備寄存器,和訪問內存中的一個變量一樣。只要知道寄存器的地址,通過一個指針訪問就可以實現讀寫。上一貼子我的程序中引用了 RCC, GPIOA, TIM6 這三個(結構)指針,它們的值(也就是地址)以及類型(代表訪問的內容)定義在 stm32f0xx.h 這個頭文件中。因為設備寄存器太多了哇,如果每一個都定義一個指針就太煩瑣了,所以把按功能劃分定義成組,每組用一個C語言的結構類型表示,寫起來也更清晰。而寄存器里面的位描述也可以定義成一些宏,在讀程序的時候就知道是什么意思了。如果有興趣,可以把 stm32f0xx.h 文件和STM32F0的手冊對照著閱讀。

好,假設已經熟悉寄存器操作了,知道怎么配置寄存器實現想要的功能,那么就可以寫C程序讓STM32工作了。現在需要一個工具來將C程序翻譯成機器代碼——編譯器,或者是叫做工具鏈(Tool chain)。Keil MDK-ARM 或者 IAR-EWARM 開發環境都帶有各自的編譯器,不過我更偏向于用開源的GCC-ARM. 在launchpad.net上可以下載到編譯好的arm-gcc工具鏈zip包,將它解壓縮,加到PATH里面就可以直接用了,很方便(很精簡吧)。

OK,現在來編譯上面那個mini.c文件,命令行: arm-none-eabi-gcc -c -Os -mcpu=cortex-m0 -mthumb mini.c gcc的參數 -c 是表示僅編譯,-Os 是優化代碼大小,-mcpu=cortex-m0 -mthumb 是指定指令集的,因為ARM有不同的版本。對了,include的頭文件還沒弄到呢。要編譯通過需要把 stm32f0xx.h 這個文件找來。我的建議是下載ST提供的 "STM32F0x2 USB FS Device Library" 程序庫,把里面需要的頭文件等等扒出來。在 stm32f0xx.h 中還包含了另外幾個頭文件,一并弄出來放到工程目錄下。

如果編譯成功,將得到 mini.o 目標文件。可以用 arm-none-eabi-objdump -S mini.o 反匯編看看翻譯成什么代碼了。

E:\arm\test072\mini>arm-none-eabi-objdump -S mini.o

 

mini.o:     file format elf32-littlearm

 Disassembly of section .text.startup:

 00000000 <main>:

   0:   4b16            ldr     r3, [pc, #88]   ; (5c <main+0x5c>)

   2:   2280            movs    r2, #128        ; 0x80

   4:   6959            ldr     r1, [r3, #20]

   6:   0292            lsls    r2, r2, #10

   8:   430a            orrs    r2, r1

   a:   b510            push    {r4, lr}

   c:   2180            movs    r1, #128        ; 0x80

   e:   615a            str     r2, [r3, #20]

  10:   2290            movs    r2, #144        ; 0x90

  12:   0249            lsls    r1, r1, #9

  14:   05d2            lsls    r2, r2, #23

  16:   6011            str     r1, [r2, #0]

  18:   69da            ldr     r2, [r3, #28]

1a:   2110            movs    r1, #16

  1c:   430a            orrs    r2, r1

  1e:   61da            str     r2, [r3, #28]

  20:   4b0f            ldr     r3, [pc, #60]   ; (60 <main+0x60>)

  22:   4a10            ldr     r2, [pc, #64]   ; (64 <main+0x64>)

  24:   851a            strh    r2, [r3, #40]   ; 0x28

  26:   2290            movs    r2, #144        ; 0x90

  28:   32ff            adds    r2, #255        ; 0xff

  2a:   62da            str     r2, [r3, #44]   ; 0x2c

  2c:   2205            movs    r2, #5

  2e:   801a            strh    r2, [r3, #0]

  30:   4a0d            ldr     r2, [pc, #52]   ; (68 <main+0x68>)

  32:   7812            ldrb    r2, [r2, #0]

  34:   8a1c            ldrh    r4, [r3, #16]

  36:   2101            movs    r1, #1

  38:   4809            ldr     r0, [pc, #36]   ; (60 <main+0x60>)

  3a:   420c            tst     r4, r1

  3c:   d0fa            beq.n   34 <main+0x34>

  3e:   8a04            ldrh    r4, [r0, #16]

  40:   438c            bics    r4, r1

  42:   8204            strh    r4, [r0, #16]

  44:   2090            movs    r0, #144        ; 0x90

  46:   2480            movs    r4, #128        ; 0x80

  48:   05c0            lsls    r0, r0, #23

  4a:   408c            lsls    r4, r1

  4c:   2a00            cmp     r2, #0

  4e:   d102            bne.n   56 <main+0x56>

  50:   6184            str     r4, [r0, #24]

  52:   1c0a            adds    r2, r1, #0

  54:   e7ee            b.n     34 <main+0x34>

  56:   8504            strh    r4, [r0, #40]   ; 0x28

  58:   2200            movs    r2, #0

  5a:   e7eb            b.n     34 <main+0x34>

  5c:   40021000        .word   0x40021000

  60:   40001000        .word   0x40001000

  64:   0000270f        .word   0x0000270f

  68:   00000000        .word   0x00000000

如上,其實里面就一個main函數。但是 main 的入口地址還沒有確定,而且它還使用了一個static型的內存變量,地址也還沒有確定。可以用 arm-none-eabi-nm mini.o 來查看模塊里面的全局符號表:

E:\arm\test072\mini>arm-none-eabi-nm mini.o

00000000 b a.4686

00000000 T main

那么,怎么讓程序放到ROM中合適的地址,并運行呢?如果熟悉C語言編程就知道還有一步——鏈接,才能確定符號的地址。但是,到目前為止我們還沒有告訴GCC地址的布局,也就是RAM從哪里開始,代碼放在哪里。因為ARM的器件很多,這并不是統一的,所以需要提供一些信息給鏈接程序。具體地,需要一個Linker Script, 可以從軟件包中找到 STM32F072C8_FLASH.ld (或者用近似的來修改得到)

/*

*****************************************************************************

**  File        : stm32_flash.ld

*****************************************************************************

*/

 

/* Entry Point */

ENTRY(Reset_Handler)

 

/* Highest address of the user mode stack */

_estack = 0x20003FFF;    /* end of RAM */

 

/* Generate a link error if heap and stack don't fit into RAM */

_Min_Heap_Size = 0x200;      /* required amount of heap  */

_Min_Stack_Size = 0x400; /* required amount of stack */

 

/* Specify the memory areas */

MEMORY

{

FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 64K

RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 16K

}

 

/* Define output sections */

SECTIONS

{

  /* The startup code goes first into FLASH */

  .isr_vector :

  {

    . = ALIGN(4);

    KEEP(*(.isr_vector)) /* Startup code */

    . = ALIGN(4);

  } >FLASH

 

  /* The program code and other data goes into FLASH */

  .text :

  {

    . = ALIGN(4);

}

這里面 -L 參數是添加標準庫文件的搜索路徑,雖然暫時并沒有用到C標準庫里面的東西,但是Linker Script里面引用了標準庫文件。-o 指定輸出的目標文件。這么就快要得到最終的機器碼了,不過好象還缺少了什么…… arm-none-eabi-ld: warning: cannot find entry symbol Reset_Handler; defaulting to  08000000

linker給了一個警告:找不到入口地址 Reset_Handler 的值,設成了默認 0x08000000. 下面再用objdump -S反匯編看一下

E:\arm\test072\mini>arm-none-eabi-objdump -S mini.elf

 

mini.elf:     file format elf32-littlearm

 

 

Disassembly of section .text:

 

08000000 <main>:

 8000000:       4b16            ldr     r3, [pc, #88]   ; (800005c <main+0x5c>)

 8000002:       2280            movs    r2, #128        ; 0x80

 8000004:       6959            ldr     r1, [r3, #20]

 8000006:       0292            lsls    r2, r2, #10

 8000008:       430a            orrs    r2, r1

 800000a:       b510            push    {r4, lr}

 800000c:       2180            movs    r1, #128        ; 0x80

 800000e:       615a            str     r2, [r3, #20]

現在 main() 被放到ROM最開始去了,這好象是對的?如果了解ARM Cortex-M0下就知道這樣錯了,因為最開始應該是中斷向量表。我們還沒有編寫Linker Script中的 .isr_vectors 段的內容。而且,一上來初始化堆棧指針等工作都沒有做就直接運行 main() 了也不合適吧?還缺少了初始化代碼。

原來是這樣,中斷向量表在這里進行了描述,還有設置堆棧,初始化全局變量的代碼,然后跳轉到 main 執行。好了,這樣就該差不多了。這個匯編程序是GNU AS的語法,可以用 arm-none-eabi-gcc 來直接匯編 arm-none-eabi-gcc -c startup_stm32f072.s

我這個是最簡化的例子,使用最簡化的軟件工具,不過已經包含了基本的C語言框架。

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 9
收藏 8
關注 211
成為作者 賺取收益
全部留言
0/200
  • 小董 2021-04-06 19:50
    講的真好!
    回復
  • dy-blNlwnWV 2021-02-25 22:04
    期待繼續
    回復
  • lihui710884923 2021-02-25 21:54
    很好
    回復
  • keyhei66 2020-12-16 21:59
    思路清晰,受益匪淺
    回復
  • heiha88 2020-12-03 22:43
    有點太深奧了
    回復
主站蜘蛛池模板: www一起操| 日本视频免费看 | 欧美人与动牲交a免费 | 精品久久久久亚洲 | 四虎欧美 | 国产性一交一乱一伦一色一情 | 国产精品刮毛 | 国产熟女AA级毛片 | 0855午夜福利 | 第一次进丫头身体 | 神马午夜窝窝 | 国产精品美女WWW爽爽爽视频 | 国产主播一区二区三区 | 国产成网站18禁止久久影院 | 综合成人亚洲偷自拍色 | 黄色一级久久 | 午夜在线播放视频 | 岛国精品资源网站 | 中文字幕永久视频 | tube中国91xxxxx国产 | 久久亚洲sm情趣捆绑调教 | 孩交精品XXXX视频视频 | 少妇xxxxx性开放 | 国产精品久久久久久久婷婷 | 日本激情视频在线播放 | hsck成人网| 日日操狠狠操 | 正能量免费网站WWW正能量免费 | 国产伦精品一区二区三区网站 | 国产SUV精品一区二区33 | 亚洲一二三四在线 | 色97色成人| 麻豆最新国产剧情AV原创 | 久久精品欧洲 | 邻居少妇张开腿让我爽了在线观看 | 国产精品69久久久久孕妇欧美 | 四虎永久在线精品免费AV | 精品国产子伦久久久久久小说 | yw193can未满十8网站 | 成人在线小视频 | 亚洲综合无码久久精品综合 |