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

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

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

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

0 引言

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

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

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

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

1.1 簡介

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

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

(1)自動變量

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

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

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

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

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

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

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

(1)堆棧

堆棧可以包含:未存儲在寄存器中的局部變量和參數(shù);表達(dá)式的臨時結(jié)果;函數(shù)的返回值(在寄存器中傳遞的除外);中斷期間的處理器狀態(tài);應(yīng)在函數(shù)返回前恢復(fù)的處理器寄存器(被調(diào)用者保存的寄存器)。

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

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

(2)優(yōu)點

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

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

(3)潛在的問題

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

int * MyFunction(){

int x;

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

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

}

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

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

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

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

在 C++ 語言中,一個特殊的關(guān)鍵字new 分配內(nèi)存和運行構(gòu)造器。通過 new 分配的內(nèi)存必須使用關(guān)鍵字 delete 來釋放。

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

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

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

2 問題分析與解決方案

以下介紹的程序?qū)嵗诰幾g器EWARM7.40、Fre-eRTOS 10.0.0 下驗證通過。

2.1 STM32F407 的片內(nèi) SRAM

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

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

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

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

圖1 STM32F407 的內(nèi)存映射

2.2 解決方案

由于編譯器 EWARM7.40 的局限性,堆無法在兩片不連續(xù)的內(nèi)存空間實現(xiàn)。為了解決此問題,筆者聯(lián)想到了免費的實時操作系統(tǒng) FreeRTOS, 該操作系統(tǒng)在2014年8月發(fā)布的 V8.1.0中提供了新的內(nèi)存管理文件 heap_5.c, 允許堆跨越多個不連續(xù)的內(nèi)存區(qū)域。后續(xù)版本對此功能做了優(yōu)化與改進(jìn)。筆者嘗試用此方案解決堆的實現(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ù)應(yīng)用程序的需求靈活調(diào)整。

③在main.c中定義兩片內(nèi)存區(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); //調(diào)用FreeRTOS 的內(nèi)存分配函數(shù)

return p;

void operator delete(void *p){

vPortFree(p); // 調(diào)用 FreeRTOS 的內(nèi)存釋放函數(shù)

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

3 結(jié)語

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



審核編輯:劉清

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

    關(guān)注

    41

    文章

    3593

    瀏覽量

    129466
  • 加速器
    +關(guān)注

    關(guān)注

    2

    文章

    799

    瀏覽量

    37867
  • Flash存儲器
    +關(guān)注

    關(guān)注

    3

    文章

    104

    瀏覽量

    25762
  • STM32F407
    +關(guān)注

    關(guān)注

    15

    文章

    187

    瀏覽量

    29454
  • 靜態(tài)變量
    +關(guān)注

    關(guān)注

    0

    文章

    13

    瀏覽量

    6650

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

文章出處:【微信號:麥克泰技術(shù),微信公眾號:麥克泰技術(shù)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    國產(chǎn)優(yōu)秀替代_APM32F407替代STM32F407記錄

    前言 最近一段時間玩極海的APM32F407系列的MCU,研究一段時間后發(fā)現(xiàn)其資源和意法半導(dǎo)體的STM32F407不相上下。通過對比兩者的數(shù)據(jù)手冊和參考手冊,我發(fā)現(xiàn)APM32
    的頭像 發(fā)表于 05-10 11:22 ?2w次閱讀
    國產(chǎn)優(yōu)秀替代_APM32<b class='flag-5'>F407</b>替代<b class='flag-5'>STM32F407</b>記錄

    STM32F407 串口配置步驟

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

    STM32F407 位帶配置步驟

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

    STM32F407 基本定時器使用

    介紹STM32F407基本定時器的配置方法,分別介紹輪詢方式、中斷方式使用定時器完成定時。
    的頭像 發(fā)表于 07-06 14:32 ?3332次閱讀
    <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 ?133次下載

    STM32F407 UCOS III實驗

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

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

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

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

    STM32F407芯片介紹

    1. 文檔準(zhǔn)備做嵌入式開發(fā)的第一步就是了解主芯片,了解STM32F407主要要關(guān)注幾個文檔: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 ?422次下載

    stm32f407原理圖

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

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

    RM0090_STM32F405/415, STM32F407/417, STM32F427/437和STM32F429/439單片機參考手
    發(fā)表于 11-23 08:24 ?23次下載
    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>參考手冊