<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

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

3天內不再提示

在STM32F407單片機上使用多塊不連續空間實現堆的軟件方法介紹

麥克泰技術 ? 來源:嵌入式系統專家之聲 ? 2024-03-20 10:43 ? 次閱讀

0 引言

嵌入式系統設計中,需要根據系統的功能需求選擇相應的單片機。筆者參與開發的一款中央空調主控制板選用了意法半導體公司STM32F407 單片機,這一系列的單片機具有高集成度、高性能、嵌入式存儲器和外設,適合作為主控制板的核心單片機使用。STM32F407 主要特征如下:提供了工作頻率為 168 MHz 的 Cortex-M4 內核(具有浮點單元)的性能,在168MHz 頻率下,從 Flash 存儲器執行時,STM32F407 能夠提供 210 DMIPS/566 CoreMark 性能,并且利用意法半導體的 ART 加速器實現了 Flash 零等待狀態。DSP 指令和浮點單元擴大了產品的應用范圍。

STM32F407產品系列具有 512 KB~1MB Flash 和 192 KBSRAM,采用尺寸小至 10 mm×10mm 的 100~ 176 引腳封裝。在開發該控制板的軟件時發現,由于 STM32F407 的 SRAM 地址不連續,造成動態內存分配存在問題,不能利用全部的片內 192 KB SRAM 資源,有必要深入分析并解決。

1 EWARM 7.40C/C++編譯器的數據存儲

筆者在開發該控制板的軟件時,使用IAR公司的EWARM7.40作為 C/C++ 編譯器,該編譯器提供了靜態內存分配與動態內存分配2種不同的內存分配機制。

1.1 簡介

ARM內核可處理4GB 的連續內存,范圍從0x00000000到0xFFFF FFFF。不同類型的物理內存可以放置在上述內存范圍中。典型的應用程序同時具有只讀存儲器(ROM)和隨機存取內存(RAM)。此外,內存范圍的某些部分包含處理器控制寄存器和外圍單元。

在典型的應用程序中,數據可以通過以下3種不同的方式存儲在內存中:

(1)自動變量

除已聲明為靜態變量者外,所有函數的局部變量都存儲在寄存器或堆棧上。這些變量在函數執行時可以使用。當函數返回到其調用者時,內存空間不再有效。

(2)全局變量、模塊靜態變量和聲明為 static的局部變量

在這種情況下,內存的分配是一勞永逸的。在此語境中,“靜態”一詞表示應用程序運行時分配給此類變量的內存數量不會改變。ARM 內核有一個單一的地址空間且編譯器支持完整的內存尋址。

(3)動態分配的數據

應用程序可以在堆上分配數據,此數據一直有效,直到它被應用程序顯式地釋放回系統。對于在應用程序執行之前不知道對象數量的場合,這種類型的內存是有用的。注意:就內存量有限的系統或預期運行很久的系統而言,存在著與使用動態分配的數據相關的潛在風險。

1.2 自動變量和參數的存儲

按照 C 語言標準,函數內定義且未聲明為靜態的變 量被命名為自動變量。其中一些變量被放置在處理器寄存器中,其余的放在堆棧上。從語義的角度來看,這是等價的。與放在堆棧上的變量相比,主要區別在于訪問寄存器更快,并且需要的內存更少。自動變量只能在函數執行時存活;當函數返回時,分配在堆棧上的內存被釋放。

(1)堆棧

堆??梢园何创鎯υ诩拇嫫髦械木植孔兞亢蛥?;表達式的臨時結果;函數的返回值(在寄存器中傳遞的除外);中斷期間的處理器狀態;應在函數返回前恢復的處理器寄存器(被調用者保存的寄存器)。

堆棧是一個固定的內存塊,分為兩部分:第一部分包含為調用當前函數的函數,以及調用該函數的函數所使用而分配的內存;第二部分包含可分配的自由內存。這兩個區域之間的邊界線稱為棧頂,由一個專門的處理器寄存器——堆棧指針來表示。通過移動堆棧指針,內存被分配到堆棧上。

函數絕不應指向包含自由內存的堆棧區域。原因是,如果發生中斷,被調用的中斷函數會分配、修改,當然還有在堆棧上去分配內存。

(2)優點

堆棧的主要優點是:程序不同部分的函數可以使用相同的內存空間存儲其數據。不同于堆,堆棧永遠不會變成碎片或出現內存泄漏。

函數可以直接或間接地調用自己(遞歸函數),每個調用可以在堆棧上存儲自己的數據。

(3)潛在的問題

堆棧的工作方式使得臆想在函數返回后存儲數據變得不可能。以下函數演示了常見的編程錯誤。它返回指向變量 x 的指針,該變量在函數返回后已不存在。

int * MyFunction(){

int x;

/*在此處理一些事情*/

return &.x; /* 不正確*/

}

另一個問題是堆棧耗盡的風險。這個問題在一個函數調用另一個、被調函數繼續調用第3個函數等,每個函數使用堆棧的總和大于堆棧的大小時會發生。當大型數據對象存儲在堆棧上或使用遞歸函數時,風險更高。

1.3 堆上的動態內存

分配在堆上的對象的內存將一直存在,直到對象被顯式釋放。這種類型的內存存儲對于直到運行時才知道數據量的應用程序是非常有用的。

在 C 語言中,使用標準庫函數 malloc或相關函數 calloc 和 realloc 中的一個來分配內存,使用free 來釋放內存。

在 C++ 語言中,一個特殊的關鍵字new 分配內存和運行構造器。通過 new 分配的內存必須使用關鍵字 delete 來釋放。

設計使用堆分配對象的應用程序時必須非常仔細,因為很容易出現無法在堆上分配對象的情形。如果你的應用程序使用過多的內存,堆可能會耗盡。如果不再使用的內存未被釋放,則堆也會用完。

對于每個分配的內存塊,若干字節用于管理目的的數據是必需的。對于分配大量小塊的應用程序,此管理開銷可能很大。

還存在碎片化的問題。這意味著在堆中,一小部分自由內存被分配對象使用的內存所分隔。如果沒有一塊足夠大的自由內存給對象,即使自由內存大小的總和超過對象的大小,還是無法分配一個新的對象。不幸的是,隨著內存的分配和釋放,碎片化往往會增加?;诖?,設計長時間運行的應用程序時應盡量避免使用分配在堆上的內存。

2 問題分析與解決方案

以下介紹的程序實例在編譯器EWARM7.40、Fre-eRTOS 10.0.0 下驗證通過。

2.1 STM32F407 的片內 SRAM

STM32F407 具有192 KB 的片內 SRAM 。片內 SRAM 可以字節、半字(16位)或全字(32位)的形式訪問。讀取和寫人操作以 CPU 速度執行,等待狀態為0。片內 SRAM 最多分為兩個模塊:SRAM1 和 SRAM2 映射地址0x20000000,可以被所有 AHB 主設備存??;CCM(核心耦合存儲器)映射到地址0x10000000, 只能由 CPU 通過 D 總線存取。

STM32F407 的內存映射如圖1所示,應用程序可以使用的系統SRAM 地址為0x20000000~0x2001 FFFF(128KB),CCM地址為0x10000000~0x1000 FFFF(64 KB)。

由于兩塊內存的地址不連續,使用編譯器 EWARM 7.40時,new 運算符只能夠在一片連續的空間分配內存,無法同時使用另外一片連續的空間。換言之,堆的實現只能在128 KB 的 SRAM 內存空間內,另外1/3的片內 SRAM 被白白浪費了,這在應用程序較為復雜時是個嚴重的缺陷,必須設法解決。

5282cf46-e5cb-11ee-a297-92fbcf53809c.jpg

圖1 STM32F407 的內存映射

2.2 解決方案

由于編譯器 EWARM7.40 的局限性,堆無法在兩片不連續的內存空間實現。為了解決此問題,筆者聯想到了免費的實時操作系統 FreeRTOS, 該操作系統在2014年8月發布的 V8.1.0中提供了新的內存管理文件 heap_5.c, 允許堆跨越多個不連續的內存區域。后續版本對此功能做了優化與改進。筆者嘗試用此方案解決堆的實現問題,取得了成功。具體方法如下:

①把FreeRTOS源程序包中的heap_5.c添加到軟件工程中。

②在頭文件中定義堆的大小。

#define configTOTAL_HEAP1_SIZE((size_t)(64*1024))

//HEAP164KB

#define configTOTAL_HEAP2_SIZE((size_t)(100*1024))

//HEAP2100KB

說明:HEAP1 使用CCM 的全部 64KB;HEAP2 使用 SRAM 的100 KB, 剩余部分留給操作系統使用。此數值可根據應用程序的需求靈活調整。

③在main.c中定義兩片內存區域:

#pragmalocation=".ccmram"

uint8_tucHeapl[configTOTAL_HEAP1_SIZE];

uint8_tucHeap2[configTOTAL_HEAP2_SIZE];

constHeapRegion_txHeapRegions[]={

/*Startaddress with dummy offsets Size */

{ucHeapl,configTOTAL_HEAP1_SIZE},

{ucHeap2,configTOTAL_HEAP2_SIZE},

{NULL,0}

};

④ 在 main.c 中重載new 和delete:

void *operator new(size_t size){

void *p=0;

p=pvPortMalloc(size); //調用FreeRTOS 的內存分配函數

return p;

void operator delete(void *p){

vPortFree(p); // 調用 FreeRTOS 的內存釋放函數

經過上述改進后,應用程序可以使用的堆的大小為 164KB, 徹底擺脫了編譯器 EWARM7.40 的局限性,滿足了復雜應用程序的需求。

3 結語

本文詳細介紹了使用多塊不連續內存空間實現堆的軟件方法,以及在 STM32F407 單片機上的軟件實現方法。使用該技術可以在多塊不連續內存空間實現堆,更好 地實現了內存的動態分配。使用該軟件的控制器產品至今已在現場穩定運行18個月。



審核編輯:劉清

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

    關注

    40

    文章

    3442

    瀏覽量

    128342
  • 加速器
    +關注

    關注

    2

    文章

    759

    瀏覽量

    36655
  • Flash存儲器
    +關注

    關注

    3

    文章

    104

    瀏覽量

    25542
  • STM32F407
    +關注

    關注

    15

    文章

    187

    瀏覽量

    29056
  • 靜態變量
    +關注

    關注

    0

    文章

    13

    瀏覽量

    6623

原文標題:使用多塊不連續空間實現堆的軟件方法

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

收藏 人收藏

    評論

    相關推薦

    STM32F407 UART的使用方法介紹

    STM32開發筆記: STM32F407 UART的使用方法
    發表于 12-22 06:36

    介紹一下單片機STM32F407芯片

    主要有單片機、嵌入式linux等。其中單片機以其功能強大、性價比高,物聯網這一行業中占據了大半江山。4.1 初識STM32F407芯片本節介紹
    發表于 07-16 07:32

    STM32F407使用HAL庫延時微妙實現方法

    STM32F407 使用HAL庫延時微妙實現方法STM32CubeMX配置)作者 : 李剴出處 歡迎轉載,但也請保留上面這段聲明。 謝謝! (以上兩個鏈接...
    發表于 08-04 08:20

    介紹STM32F407的啟動模式

    單片機型號:STM32F407VGT6本文介紹STM32F407的啟動模式,也稱為BOOT模式。STM32F407可以有3種方式進行啟動,見
    發表于 08-04 06:08

    介紹STM32F407特殊引腳連接電路

    單片機型號:STM32F407VGT6本文介紹STM32F407特殊引腳連接電路,見下圖:引腳:49、73VCAP_1和VCAP_2,按照下列電路設計
    發表于 08-04 06:22

    STM32F1單片機上實現FFT

    STM32F1系列單片機上實現FFT最近需要做一臺基于stm32的示波器,測量信號參數,用單片機上
    發表于 08-05 07:41

    介紹STM32F407的GPIO應用之無源蜂鳴器

    第20章 STM32F407的GPIO應用之無源蜂鳴器本章教程為大家介紹STM32F407的GPIO應用之無源蜂鳴器,蜂鳴器也是GPIO控制的經典測試例程,可以讓大家對STM32F407
    發表于 08-10 08:21

    如何實現stm32f407單片機串口通信?

    如何實現stm32f407單片機串口通信?
    發表于 12-07 06:24

    STM32F407的RTC部分介紹

    1.下圖是STM32F407的中文參考手冊中,RTC介紹部分。因為我想實現單片機每秒自動喚醒自己一次,開始打算用鬧鐘中斷,但是每次喚醒以后都要自己設置下次喚醒的時間,簡單的
    發表于 01-10 06:14

    基于TFTP文件傳輸協議實現STM32F407局域網內遠程網絡升級

    技術大綱摘要基于TFTP文件傳輸協議,實現STM32F407局域網內遠程網絡升級。單片機與網絡IC均采用正點原子的STM32F407探索者,采用RAW LWIP例程進行移植,采用lwi
    發表于 01-12 06:29

    如何實現STM32F407板子的互相通訊?

    如何實現STM32F407板子的互相通訊?
    發表于 02-14 06:18

    介紹STM32F407 USB轉串口功能的實現

    之前的文章中介紹STM32的USB接口虛擬串口的功能?!?b class='flag-5'>STM32CubeMX之USB從機》。本篇文章在此基礎上,以STM32F407為例,介紹
    發表于 02-22 06:29

    STM32F407 UCOS III實驗

    STM32F407 UCOS III實驗,介紹基于STM32F407的UCOSIII實例,參考下
    發表于 09-22 14:08 ?80次下載

    為什么選用ST系列STM32F407單片機

    為什么選用ST系列STM32F407單片機
    發表于 11-26 14:06 ?7次下載
    為什么選用ST系列<b class='flag-5'>STM32F407</b><b class='flag-5'>單片機</b>

    STM32F407芯片介紹

    1. 文檔準備做嵌入式開發的第一步就是了解主芯片,了解STM32F407主要要關注幾個文檔:1. stm32F407芯片手冊2. stm32F407參考手冊3. Arm Cortex-M4數據手冊
    發表于 12-04 13:21 ?108次下載
    <b class='flag-5'>STM32F407</b>芯片<b class='flag-5'>介紹</b>
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>