色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

挑戰用一百個字節寫一個閃爍燈程序

麥克泰技術 ? 來源:麥克泰技術 ? 作者:麥克泰技術 ? 2023-05-16 15:59 ? 次閱讀

# 作者:Roff Segger,麥克泰技術測試、翻譯和編寫

我們使用SEGGER公司的Embedded Studio開發環境進行測試:在一個Cortex-M微控制器上,看看需要使用多少Flash存儲器才能夠完成一個LED燈的閃爍?

目標:

· 使用少于100個字節的程序完成一個閃爍應用

· 使用人眼容易看到的切換頻率(即1-5Hz范圍)

· 主程序用C/C++語言編寫

· 使用方便得到的硬件

· 不使用或禁用工具鏈的運行時系統初始化

本文將大致介紹我們要使用的每一個字節和每一條指令。這是一個了解系統啟動時到底發生了什么,即在到達main()函數之前“底層”發生什么的好途徑。

簡而言之:使用Embedded Studio開發環境可以在使用不到100字節的程序內完成這個工作。

01硬件

我們使用的硬件是一塊STM32跟蹤參考板。它非常簡單,只有一個STM32F407微控制器、3個LED、一個調試/跟蹤接口和一個USB供電端口

4f44b80a-f0c9-11ed-90ce-dac502259ad0.jpg

每個J-Trace仿真器交付中包含該開發板,然而,在這里,我僅僅使用常規的J-Link功能下載和調試程序。用戶也可以選擇任何帶LED的硬件測試。

02生成項目

非常簡單,打開Embedded Studio開發環境,從菜單中選擇File -> New Project,選擇第一個選項,創建可執行文件。

4f6b8fb6-f0c9-11ed-90ce-dac502259ad0.png

根據提示,選擇使用默認值,單擊next幾次后,我最終得到了一個小項目,如下面的Project Explorer窗口中所示。

4f9a400e-f0c9-11ed-90ce-dac502259ad0.png

選擇Build->Build Mini或按F7構建我們的程序。

Debug -> Go或F5啟動調試器。

我們現在沒有連接硬件,所以Embedded Studio要求我們使用內置模擬器。

4fb7ddb2-f0c9-11ed-90ce-dac502259ad0.png

點擊Yes或點擊Enter啟動模擬器。

調試器停在main()函數處,這是一個標準的 “Hello world”應用程序。

4fd6ff44-f0c9-11ed-90ce-dac502259ad0.png

現在,為了實現最小的應用程序,我們將其簡化為一個基本上是空的循環。

int main(void) {
 int i; 
 
 do {
  i++;
 } while (1);
5000f498-f0c9-11ed-90ce-dac502259ad0.png

結果只占用了158字節的Flash。這已經非常不錯了,但是在添加實際LED閃爍功能之前,我需要了解內存的占用,以及如何使我的程序最小化。

為了做到這一點,我可以查看Memory Usage Window、鏈接器映射文件、生成的ELF文件,或者簡單地查看Project Explorer。

從Project Explorer窗口可以知道,這個可執行文件由3個源程序文件構成,以及它們使用了多少Code + RO空間。請注意,這些是編譯器生成對像的數值。對于最終的可執行文件,鏈接器可以消除未使用的功能,或者在必要時添加一些結合層代碼(從Flash跳到RAM或從Thumb指令跳到ARM指令)和填充(如:保證4字節對齊)。

另一個使用Flash存儲器的地方,可能是從庫中鏈接進來的代碼,例如:C運行時庫。然而,我們的小項目并沒有使用庫函數,因此我們不必考慮庫代碼的空間占用。

502279e2-f0c9-11ed-90ce-dac502259ad0.png

而且,Project Explorer展示了每個源文件的內存使用情況(2、128和24字節)和項目可執行文件總的內存使用情況:158字節。這和我們在Output窗口中看到的數值相同。

03理解項目結構

這三個文件的用途?我們的應用程序只是一個簡單的main()函數。為什么我還需要另外兩個文件呢?

main.c – 應用程序。

C ortex_M_Startup.s – CPU相關代碼,包含中斷向量表。

SEGGER_THUMB_Startup.s – 應用編程人員不需要修改的代碼。

讓我們更詳細地了解它們,以揭開大家都想知道的謎團:啟動代碼是如何工作的?

有了這些知識,讓我們看看如何縮小我們的應用程序。

04main.c

main.c包含我們的應用,一個最簡單的main()函數。

我們的編譯器足夠智能。它可以看出這個程序什么都不做,并將其優化為只使用一條指令或兩個字節代碼的空循環。

我怎么知道的?我們可以看看main.o,這是編譯器產生的輸出。在Project Explorer中,右鍵單擊main.c->Show Disassembly,或者展開它,雙擊Output files中的main.o。它揭示了主程序只有一個分支。

5045cfc8-f0c9-11ed-90ce-dac502259ad0.png

這是我們的主應用程序。我們已經沒有辦法再簡化它了。

05Cortex_M_Startup.s

Cortex_M_Startup.s包含了應用程序在Cortex-M硬件上執行所需要的CPU相關代碼。它包含中斷向量表和上電或復位時執行的函數:Reset_Handler。

此文件使用了大部分Flash空間。讓我們仔細看看它產生了什么。

Cortex_M_Startup.o顯示其包含中斷向量表 .vectors段及默認的異常處理程序實現。

section .vectors
<_vectors>
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
00000000 .word 0x00000000
 
section .init.NMI_Handler

E7FE b 0x00000000
 
section .init.MemManage_Handler

E7FE b 0x00000000
 
section .init.BusFault_Handler

E7FE b 0x00000000
 
section .init.UsageFault_Handler

E7FE b 0x00000000
 
section .init.SVC_Handler

E7FE b 0x00000000
 
section .init.DebugMon_Handler

E7FE b 0x00000000
 
section .init.PendSV_Handler

E7FE b 0x00000000
 
section .init.SysTick_Handler

E7FE b 0x00000000
 
section .init.Reset_Handler

F7FFFFFE bl 0x00000000
F7FFBFFE b.w 0x00000004
 
section .init.HardFault_Handler

4908 ldr r1,
680A ldr r2, [r1]
2A00 cmp r2, #0

D4FE bmi 0x00000006
F01E0F04 tst lr, #4
BF0C ite eq
F3EF8008 mrseq r0, msp
F3EF8009 mrsne r0, psp
F0424200 orr r2, r2, #0x80000000
600A str r2, [r1]
6981 ldr r1, [r0, #24]
3102 adds r1, #2
6181 str r1, [r0, #24]
4770 bx lr
E000ED2C .word 0xE000ED2C

這就是罪魁禍首。

ARM內核定義了向量表中的前16個表項,然后是設備外部中斷的表項。該文件提供了一個有16個表項(或64個字節)的向量表。這些條目僅用于該表。

在應用程序中,我們沒有處理任何故障或中斷,實際上我們只需要Reset_Handler,這是復位立即執行的代碼。我們還需要向量表中的第一個表項,它在復位時完成堆棧指針(SP)的初始化。

因此,我們刪除所有不必要的表項,將此表刪減為兩個表項,同時將消除默認的異常處理程序。

我們重新生成應用程序。不錯!現在應用減少為42個字節。

5061ec3a-f0c9-11ed-90ce-dac502259ad0.png5083fc58-f0c9-11ed-90ce-dac502259ad0.png

讓我們看看輸出的elf文件的內容。

從0x0000 0000開始的8個字節:向量表,包含初始化SP和指向Reset_Handler的指針。

從0x0000 001E 開始的8個字節: Reset_Handler,兩條4字節指令。鏈接器插入的一條nop指令,代替SystemInit的調用(在應用程序中不存在),以及一個跳轉到_start的指令。

從0x0000 0008開始的20字節:SEGGER_THUMB_Startup.s的通用運行時初始化,它執行鏈接器生成的對來自SEGGER_init_table的初始化函數的調用,然后,調用main,如果main返回,則停在exit循環中。

從0x0000 0028開始4字節:鏈接器生成了SEGGER_init_table,

其中包含需要在main之前調用的初始化函數。它可能包含段初始化(復制初始化的數據)、段填充(用于0初始化的靜態變量或堆棧的預填充)、堆初始化或全局C++對象的構造函數調用。這些都沒有在我們的應用程序中使用。

最后一條(唯一)指令是跳到運行時初始化的末尾,調用main函數。

加上從0x00000026開始的為對齊SEGGER_int_table的 2個字節的填充,總共是42個字節。

50a46984-f0c9-11ed-90ce-dac502259ad0.png50c193f6-f0c9-11ed-90ce-dac502259ad0.png

因為應用中沒有使用SystemInit功能,所以我們可以刪除bl SystemInit語句,并用nop取代,以節省4個字節,并減少到38+2=40個字節。

我們的應用程序已經是盡可能小了。下面我們開始添加閃爍代碼!

06添加閃爍代碼

我們編寫了一些用于初始化和控制參考板上LED的代碼和一個簡單的延遲函數。

有了這些代碼,我們就可以創建帶有閃爍功能的主應用程序了,如下所示:

/****************************************
*
* main()
*
* Function description
* Application entry point.
*/
int main(void) {
  _InitLED();
  for (;;) {
   _SetLED();
  _Delay(NUM_DELAY_LOOPS);
  _ClrLED();
  _Delay(NUM_DELAY_LOOPS);
  }
}

完整的源代碼工程可以訪問(可點擊“閱讀原文”):https://blog.segger.com/wp-content/uploads/2020/08/Blinky_Mini.zip

讓我們重新構建并檢查輸出。

成功了!應用程序的大小只有96個字節(需要使用release模式構建,使用debug模式代碼體積會比較大)。

它真的可以運行嗎?讓我們試一試。我們將電路板連接到J-Link,并將J-Link連接到我們的計算機。按F5鍵運行它。就像這個項目開始時一樣,調試會話開始并運行到main函數,只是這次是在實際硬件而非模擬器上。當我們再次點擊F5繼續執行時,我們可以看到開發板上的LED0在閃爍。

07小結

C語言寫的閃爍程序確實可以放在不到100字節的程序(或者更準確地說是只讀)存儲器中。

啟動代碼不需要那么復雜。它只是完成了硬件的初始化(SystemInit的用途)和運行時系統的初始化。

運行時系統初始化由Embedded Studio和SEGGER鏈接器負責。它確保只包含必要的代碼,以使生成的可執行文件盡可能小。

SEGGER鏈接器還能夠包括特定的初始化,例如:在需要的時候,完成堆的初始化和調用構造函數。這些功能是由鏈接器中的腳本控制。

initialize by symbol __SEGGER_init_heap { block heap }; // Init the heap if there is one
initialize by symbol __SEGGER_init_ctors { block ctors }; // Call constructors for globalobjects which need

SEGGER鏈接器生成的啟動代碼非常小,并且易于理解。聯合高效的SEGGER編譯器與模塊化的運行庫和主機端輸出printf()函數,我們就可以傲視群雄了。

看看電腦上簡單的“Hello World”程序的大小,也許我們還應該提供一個可以在電腦上生成相同小程序的SEGGER Studio。

你程序還能更精簡嗎?用你的工具鏈試試,挑戰用100字節寫一個閃爍程序!我相信,在同樣的硬件上,這將是很難被擊敗的。

08這個項目的代碼還能更緊湊嗎?

令人驚訝的答案是:是的。

首先:一些微控制器具有切換寄存器,這允許將循環切割為_ToggleLED() / Delay()。

還有,初始化內容需要的代碼量各不相同,在其他硬件上可能會更小。

但是即使在相同的硬件上,我們也可以進一步減小程序大小。

我們可以將_start放入向量表中,這樣程序就可以在通用啟動代碼中開始執行,從而節省了4字節的跳轉空間。

我們可以刪除exit() 和2字節的分支,因為我們知道main()程序中永遠不會返回。

因為我只想要不到100個字節的程序,所以,讓我們到此為止吧。

祝大家編碼快樂!

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 微控制器
    +關注

    關注

    48

    文章

    7542

    瀏覽量

    151318
  • led燈
    +關注

    關注

    22

    文章

    1592

    瀏覽量

    107953
  • 存儲器
    +關注

    關注

    38

    文章

    7484

    瀏覽量

    163766
  • usb
    usb
    +關注

    關注

    60

    文章

    7938

    瀏覽量

    264486
  • STM32
    +關注

    關注

    2270

    文章

    10896

    瀏覽量

    355752

原文標題:挑戰用一百個字節寫一個閃爍燈程序!

文章出處:【微信號:麥克泰技術,微信公眾號:麥克泰技術】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    proteus仿真MCS-51的一百個例子(2)

    proteus仿真MCS-51的一百個例子(2)
    發表于 07-28 10:19 ?35次下載
    proteus仿真MCS-51的<b class='flag-5'>一百個</b>例子(2)

    proteus仿真MCS-51的一百個例子(3)

    proteus仿真MCS-51的一百個例子(3)
    發表于 07-28 10:22 ?64次下載
    proteus仿真MCS-51的<b class='flag-5'>一百個</b>例子(3)

    proteus仿真MCS-51的一百個例子

    proteus仿真MCS-51的一百個例子
    發表于 07-28 10:27 ?191次下載
    proteus仿真MCS-51的<b class='flag-5'>一百個</b>例子

    示波器基礎知識一百個問答

    示波器基礎知識一百個問答:1. 對已設計完成的產品,如何用示波器經行檢測分析其可靠性?答:示波器早已成為檢測電子線路最有效的工具之,通過觀察線路關鍵節點的
    發表于 08-21 22:23 ?0次下載

    一個字節到24c02中(源程序)

    一個字節到24c02中(源程序) 24c02是非揮發eeprom存儲器器件,采用的IIC總線技術。24c02在許多試驗中都有出現。
    發表于 08-11 19:17 ?2923次閱讀

    UART 發送數據丟失最后一個字節

    STM32 UART 發送數據丟失最后一個字節
    發表于 12-04 15:10 ?0次下載

    不同頻率閃爍1LED

    6-不同頻率閃爍1LED---51單片機源代碼 keil直接打開
    發表于 06-15 18:17 ?2次下載

    1602與51一個字母_源代碼

    1602與51一個字母_源代碼,感興趣的可以看看。
    發表于 07-19 16:55 ?2次下載

    示波器基礎知識一百個問答

    電路教程相關知識的資料,關于示波器基礎知識一百個問答
    發表于 10-10 14:34 ?0次下載

    Proteus的51單片機仿真和程序一百個實例說明

    本文檔的主要內容詳細介紹的是Proteus的51單片機仿真和程序一百個實例說明。
    發表于 01-07 08:00 ?90次下載
    Proteus的51單片機仿真和<b class='flag-5'>程序</b>的<b class='flag-5'>一百個</b>實例說明

    使用51單片機進行EEPROM AT24c02存儲讀取一個字節程序免費下載

    本文檔的主要內容詳細介紹的是使用51單片機進行EEPROM AT24c02存儲讀取一個字節程序資料免費下載。
    發表于 06-10 17:48 ?9次下載
    使用51單片機進行EEPROM AT24c02存儲讀取<b class='flag-5'>一個字節</b>的<b class='flag-5'>程序</b>免費下載

    淺談STM32串口通信()基本介紹和一個字節傳輸的實現

    文章目錄0 傳輸引腳1 傳輸一個字節1.1 發送一個字節1.2 接收一個字節2 代碼2.1 配置2.2 發送一個字節2.3 接收一個字節0
    發表于 12-24 18:51 ?14次下載
    淺談STM32串口通信(<b class='flag-5'>一</b>)基本介紹和<b class='flag-5'>一個字節</b>傳輸的實現

    編寫閃爍LED代碼

    電子發燒友網站提供《編寫閃爍LED代碼.zip》資料免費下載
    發表于 10-24 10:55 ?2次下載
    編寫<b class='flag-5'>一</b><b class='flag-5'>個</b><b class='flag-5'>閃爍</b>LED<b class='flag-5'>燈</b>代碼

    exe程序

    圖形界面可以嘗試下 tkinter ,可以寫出來圖形程序,以下 Python3 作為示
    的頭像 發表于 03-03 15:00 ?1013次閱讀
    <b class='flag-5'>寫</b><b class='flag-5'>一</b><b class='flag-5'>個</b>exe<b class='flag-5'>程序</b>

    UART發送數據丟失最后一個字節

    電子發燒友網站提供《UART發送數據丟失最后一個字節.pdf》資料免費下載
    發表于 08-01 17:57 ?1次下載
    UART發送數據丟失最后<b class='flag-5'>一個字節</b>
    主站蜘蛛池模板: 亚洲A片不卡无码久久尤物| 诱咪youmiss| 第七色男人天堂| 琪琪热热色原日韩在线| 极品少妇高潮啪啪AV无码吴梦梦| 日日夜夜天天操| 初中XXXXXL| 日本亚洲精品色婷婷在线影院| 欧美一级久久久久久久大| 99视频精品全部免费 在线| 簧片免费观看| 伊人久久网国产伊人| 黄色三级视频网站| 网红主播 国产精品 开放90后| 超碰免费视频公开97| 涩涩涩涩爱网站| 99爱在线观看| 豆奶视频在线高清观看| 欧美日韩免费播放一区二区| 99精品视频免费在线观看| 蜜芽tv在线观看免费网站| 中文视频在线观看| 国产伊人自拍| 亚洲裸舞 hd| 黄色a一级视频| 永久免费的污视频网站| 欧美xxxxxbb| 宝贝好紧好爽再搔一点试視頻 | 久久这里只精品国产99re66| 亚洲视频在线观看不卡| 久久久久国产| 爆操日本美女| 性盈盈剧场| 久久青草影院| 成人中文字幕在线| 亚洲 日韩 在线 国产 视频| 国产亚洲精品视频在线网| 亚洲午夜无码久久久久蜜臀av| 久久久久琪琪精品色| 2022久久精品国产色蜜蜜麻豆| 男人扒开添女人屁股|