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

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

3天內不再提示

在STM32F407單片機上使用多塊不連續(xù)空間實現(xiàn)堆的軟件方法介紹

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

0 引言

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

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

1 EWARM 7.40C/C++編譯器的數(shù)據(jù)存儲

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

1.1 簡介

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

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

(1)自動變量

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

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

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

(3)動態(tài)分配的數(shù)據(jù)

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

1.2 自動變量和參數(shù)的存儲

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

(1)堆棧

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

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

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

(2)優(yōu)點

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

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

(3)潛在的問題

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

int * MyFunction(){

int x;

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

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

}

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

1.3 堆上的動態(tài)內存

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

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

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

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

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

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

2 問題分析與解決方案

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

2.1 STM32F407 的片內 SRAM

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

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

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

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

圖1 STM32F407 的內存映射

2.2 解決方案

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

①把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, 剩余部分留給操作系統(tǒng)使用。此數(shù)值可根據(jù)應用程序的需求靈活調整。

③在main.c中定義兩片內存區(qū)域:

#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 的內存分配函數(shù)

return p;

void operator delete(void *p){

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

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

3 結語

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



審核編輯:劉清

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

    關注

    40

    文章

    3519

    瀏覽量

    128798
  • 加速器
    +關注

    關注

    2

    文章

    785

    瀏覽量

    37139
  • Flash存儲器
    +關注

    關注

    3

    文章

    104

    瀏覽量

    25631
  • STM32F407
    +關注

    關注

    15

    文章

    187

    瀏覽量

    29201
  • 靜態(tài)變量

    關注

    0

    文章

    13

    瀏覽量

    6635

原文標題:使用多塊不連續(xù)空間實現(xiàn)堆的軟件方法

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

收藏 人收藏

    評論

    相關推薦

    STM32F407 串口配置步驟

    介紹STM32F407串口配置步驟,完成串口的數(shù)據(jù)發(fā)送與接收、實現(xiàn)中斷接收,支持printf重定向。
    的頭像 發(fā)表于 07-06 14:29 ?2517次閱讀
    <b class='flag-5'>STM32F407</b> 串口配置步驟

    STM32F407 位帶配置步驟

    介紹STM32F407位帶操作方法,設置寄存器的偏移量,實現(xiàn)按GPIO口指定位進行讀寫操作,方便編程。
    的頭像 發(fā)表于 07-06 14:30 ?1027次閱讀
    <b class='flag-5'>STM32F407</b> 位帶配置步驟

    STM32F407 基本定時器使用

    介紹STM32F407基本定時器的配置方法,分別介紹輪詢方式、中斷方式使用定時器完成定時。
    的頭像 發(fā)表于 07-06 14:32 ?2839次閱讀
    <b class='flag-5'>STM32F407</b> 基本定時器使用

    介紹一下單片機STM32F407芯片

    主要有單片機、嵌入式linux等。其中單片機以其功能強大、性價比高,物聯(lián)網(wǎng)這一行業(yè)中占據(jù)了大半江山。4.1 初識STM32F407芯片本節(jié)介紹
    發(fā)表于 07-16 07:32

    如何實現(xiàn)stm32f407單片機串口通信?

    如何實現(xiàn)stm32f407單片機串口通信?
    發(fā)表于 12-07 06:24

    STM32F407模板

    STM32F407模板,感興趣可以看看。
    發(fā)表于 07-25 18:52 ?129次下載

    STM32F407 UCOS III實驗

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

    如何實現(xiàn)STM32F407單片機的ADC轉換

    ADC轉換是把外面輸入到引腳的電壓值轉換成數(shù)字信號,單片機里面有一個模擬至數(shù)字的轉換模塊,我們可以控制它采集引腳的電壓,stm32F407可以利用void ADC_SoftwareStartConv(ADC_TypeDef* ADCx)這個函數(shù)來控制轉換。
    發(fā)表于 12-26 15:08 ?2.6w次閱讀
    如何<b class='flag-5'>實現(xiàn)</b><b class='flag-5'>STM32F407</b><b class='flag-5'>單片機</b>的ADC轉換

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

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

    STM32F407STM32F105 CAN通訊失敗的定位解決

    STM32F407STM32F105 CAN通訊失敗的定位解決問題的發(fā)現(xiàn)問題的現(xiàn)象測試過程硬件調整測試軟件調整測試結論基本結論結論擴展驗證問題的發(fā)現(xiàn)在STM32 CAN總線的應用過程
    發(fā)表于 12-02 16:51 ?18次下載
    <b class='flag-5'>STM32F407</b>與<b class='flag-5'>STM32F</b>105 CAN通訊失敗的定位解決

    STM32F407芯片介紹

    1. 文檔準備做嵌入式開發(fā)的第一步就是了解主芯片,了解STM32F407主要要關注幾個文檔:1. stm32F407芯片手冊2. stm32F407參考手冊3. Arm Cortex-M4數(shù)據(jù)手冊
    發(fā)表于 12-04 13:21 ?109次下載
    <b class='flag-5'>STM32F407</b>芯片<b class='flag-5'>介紹</b>

    STM32F407原理圖下載

    STM32F407原理圖下載
    發(fā)表于 01-17 13:44 ?416次下載

    stm32f407原理圖

    stm32f407原理圖
    發(fā)表于 07-14 16:07 ?201次下載

    RM0090_STM32F405/415, STM32F407/417, STM32F427/437和STM32F429/439單片機參考手冊

    RM0090_STM32F405/415, STM32F407/417, STM32F427/437和STM32F429/439單片機參考手
    發(fā)表于 11-23 08:24 ?11次下載
    RM0090_<b class='flag-5'>STM32F</b>405/415, <b class='flag-5'>STM32F407</b>/417, <b class='flag-5'>STM32F</b>427/437和<b class='flag-5'>STM32F</b>429/439<b class='flag-5'>單片機</b>參考手冊

    stm32f407 LAN8720A速率調整

    STM32F407和LAN8720A的速率是非常重要的,尤其是在網(wǎng)絡環(huán)境中。下面我將詳細介紹如何通過軟件和硬件來調整速率。 軟件配置: 首先,我們需要在
    的頭像 發(fā)表于 01-05 13:54 ?2818次閱讀