日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > > 嵌入式軟件實戰(zhàn)派
[導(dǎo)讀]這次我成功將妹子約到了公司附近的咖啡館,繼續(xù)探討RTOS的heap的技術(shù)特點。當我把準備好的數(shù)據(jù)和動圖展示在她面前,她立馬激動起來了。

這次我成功將妹子約到了公司附近的咖啡館,繼續(xù)探討RTOS的heap的技術(shù)特點。當我把準備好的數(shù)據(jù)和動圖展示在她面前,她立馬激動起來了。仿佛我遞出來的是一束花、鉆戒,她驚訝不已,除了臉上少了幾分嬌羞……事情上這樣的,我得好好重頭講一講。1. 妹子的問題妹子好久沒有問我問題了,想著應(yīng)該是可以自己獨立干項目了吧。這也是好事,畢竟是我親自帶出來的徒弟。但我還是懷念她經(jīng)常問我問題的日子……
有一天傍晚快下班的時候,我問她,項目上的事自己能hold得住嗎?有問題隨時可以找我哦。
她想了想,欲言又止。
還沒等她說話,我接著說,是遇到什么問題了嗎?
“其實是這樣的,我是遇到了OS上的一些疑惑問題,但也不是很要緊??茨隳敲疵Γ缓靡馑即驍_你……”“哦……沒事啊,什么問題呢?”她說,自從上次我跟她分析了OS占用內(nèi)存的問題(見妹子告訴我她被欺負了)后,她就對OS的內(nèi)存分配有不少疑惑,很想將它搞個一清二楚。這不,她現(xiàn)在的問題是,FreeRTOS里的Heap1~Heap5有什么區(qū)別?
心想:額……這次完犢子了,我還真沒怎么研究過這幾個Heap的區(qū)別。但是我不能在她面前說不行啊。
突然,心生一計,若有其事淡定地跟她說,這是個好問題,得好好探討下。然后我順手拿出手機看了看時間,問她,明天晚上有空么?
“有。”她回答很干脆。
這次,我得換個方式跟她講解這個Heap,不能像以前那樣了……
2. 熬夜研究heap于是,我背了筆記本回家,開始鉆研這個heap的用法,得用豐富的知識和強有力的技能征服妹子。
首先,我將這幾個heap的c文件移植到PC運行環(huán)境,用自動化手段分析其使用情況。我寫了個main.c文件,分別與heap_1.c~heap_5.c進行編譯。
主要思路是,向heap申請并釋放內(nèi)存,看看其地址占用空間,就一目了然了。
 addr1 = alloc_x(1); addr2 = alloc_x(2); addr4 = alloc_x(4); addr8 = alloc_x(8); addr16 = alloc_x(16); addr32 = alloc_x(32);  free_x(addr1); addr1 = alloc_x(1); free_x(addr4); addr2 = alloc_x(2); free_x(addr8); addr4 = alloc_x(4); addr4 = alloc_x(4); free_x(addr16); addr1 = alloc_x(1); addr2 = alloc_x(2); addr4 = alloc_x(4); addr8 = alloc_x(8); addr16 = alloc_x(16); addr1 = alloc_x(1); free_x(addr2); free_x(addr4); free_x(addr8); free_x(addr16); addr6 = alloc_x(6); addr10 = alloc_x(10);
這里面的alloc_xfree_x分別調(diào)用了pvPortMallocvPortFree,并打印一些信息。
void* alloc_x(size_t size){ void* addr = pvPortMalloc(size); size_t res = xPortGetFreeHeapSize(); printf("Alloc : addr=0x%p, size:0x%02X, remain:0x%04X\r\n", addr, size, res); return addr;} void free_x(void* addr){ vPortFree( addr); size_t res = xPortGetFreeHeapSize(); printf("Free  : addr=0x%p, remain:0x%04X\r\n", addr, res);}
總以為很順利,誰知道,這heap依賴的頭文件一層套一層……一狠心,大刀闊斧屏蔽了頭文件里面的內(nèi)容,手動添加heap需要的依賴項。
好不容易,編譯通過了,在搞heap_1.c這個的時候,在運行到vPortFree,就掛了!查了下代碼,發(fā)現(xiàn)heap_1原來是不允許free內(nèi)存的。
void vPortFree( void * pv ){ /* Memory cannot be freed using this scheme.  See heap_2.c, heap_3.c and * heap_4.c for alternative implementations, and the memory management pages of * https://www.FreeRTOS.org for more information. */ ( void ) pv;  /* Force an assert as it is invalid to call this function. */ configASSERT( pv == NULL );}
因為它只實現(xiàn)了pvPortMalloc而沒實現(xiàn)vPortFree,所以這個vPortFree是沒用的,僅僅是個兼容性接口而已。
接著,把后面的heap_2~heap_5的編譯運行問題一個個搞定了。
Note:我把整個工程打包好了,關(guān)注公眾號“嵌入式軟件實戰(zhàn)派”,在后臺回復(fù)“heap”即可獲得下載鏈接。
通過輸出的log信息,我還細心地做了個內(nèi)存分配動圖。
搞完這一波,看了下時間,竟然是晚上12點了。
然后,我居然興奮得睡不著,想著怎么跟她講解這個技術(shù)問題。
第二天,突發(fā)奇想,約她在公司附近的咖啡館!她居然爽快地答應(yīng)了??!
3. 促膝長談晚上下班,我們一起到了咖啡廳,就像一對小……伙伴程序員,背著筆記本電腦。跟異性來這種地方,我還有些不好意思。
為了避免尷尬,單刀直入,打開筆記本,把準備好的材料跟她一一講解。
“師兄,我們不點個咖啡嗎?”
“呵呵呵……其實……你喜歡和什么?”
……

她說晚上不喝咖啡,于是我給她點了一杯奶茶,然后迫不及待地跟她將這個heap的情況。

一開始,我用官方的文檔解釋給她說明了下總體的情況:

我問她,“你知道FreeRTOS為什么不用C庫中的malloc()free()函數(shù)來分配和釋放內(nèi)存嗎?”

“因為,不安全?!?

我聽她這么肯定的說,想著她肯定是對RTOS有很深入的認識的。

是的,C庫中的malloc()free()函數(shù):

1. they are not always available on embedded systems,

2. they take up valuable code space,

3. they are not thread safe, and

4. they are not deterministic (the amount of time taken to execute the function will differ from call to call)

FreeRTOS
“所以,F(xiàn)reeRTOS的幾個heap是為了解決這幾個問題的?!?br /> 她點了點頭,然后低頭喝了一口奶茶。我看她那手捧奶茶的溫柔,恰好點綴了窗外的夕陽……多想多停留在這一刻,但我怕她看到我在看她,接著說:“那么,這幾個heap有什么區(qū)別呢?總的來說是這樣的?!?br />

heap_1 - 最簡單的實現(xiàn)形式,不支持Free內(nèi)存;

heap_2 - 允許內(nèi)存Free,但不會合并free的內(nèi)存塊;

heap_3 - 是malloc() 和free() 的抽象層,多加了線程安全措施;

heap_4 - 合并free的塊,避免碎片

heap_5 - 類似heap_4,增加了塊內(nèi)存段操作。

“嗯!”她輕聲說。其實她已經(jīng)看過了這些解釋了,但是不是很理解,她想深入一點的,深入一點的學(xué)習(xí)。“‘Talk is cheap’,那么,我們直接上代碼吧。”
她呵呵大笑。笑的樣子也特別可愛。
“我們就按照官方的解釋,來驗證下。我寫了段測試代碼,你看看這段log就知道了?!?br />
Base Addr: 0x407080Alloc : addr=0x00407080, size:0x01, remain:0x27F0Alloc : addr=0x00407088, size:0x02, remain:0x27E8Alloc : addr=0x00407090, size:0x04, remain:0x27E0Alloc : addr=0x00407098, size:0x08, remain:0x27D8Alloc : addr=0x004070A0, size:0x10, remain:0x27C8Alloc : addr=0x004070B0, size:0x20, remain:0x27A8Free : addr=0x00407080, remain:0x27A8Alloc : addr=0x004070D0, size:0x01, remain:0x27A0Free : addr=0x00407090, remain:0x27A0Alloc : addr=0x004070D8, size:0x02, remain:0x2798Free : addr=0x00407098, remain:0x2798Alloc : addr=0x004070E0, size:0x04, remain:0x2790Alloc : addr=0x004070E8, size:0x04, remain:0x2788Free : addr=0x004070A0, remain:0x2788Alloc : addr=0x004070F0, size:0x01, remain:0x2780Alloc : addr=0x004070F8, size:0x02, remain:0x2778Alloc : addr=0x00407100, size:0x04, remain:0x2770Alloc : addr=0x00407108, size:0x08, remain:0x2768Alloc : addr=0x00407110, size:0x10, remain:0x2758Alloc : addr=0x00407120, size:0x01, remain:0x2750Free : addr=0x004070F8, remain:0x2750Free : addr=0x00407100, remain:0x2750Free : addr=0x00407108, remain:0x2750Free : addr=0x00407110, remain:0x2750Alloc : addr=0x00407128, size:0x06, remain:0x2748Alloc : addr=0x00407130, size:0x0A, remain:0x2738
她準備站起來,把頭湊過來看,我把筆記本轉(zhuǎn)過去給她。然后我繼續(xù)解釋說,“這個Free是沒有意義的”。
“哦?”她似乎有些不相信,然后試圖口算這些地址值。
“我再給個圖你看看?!?br />

“哇哦……這顏色是什么意思,代表申請的內(nèi)存塊嗎?怎么還有這么多空隙的?”她低聲問道,似乎有點好奇,又有點不是很相信的樣子。
“是的,要顏色的地方是表示內(nèi)存申請占有的地方,至于空隙嘛,我一會再跟你解釋下?!蔽医又f,“歪著頭怎么看呢!要不坐過來我這邊,我還有一個動圖。”

“厲害!這都可以做出來,走心了……”
“你仔細看,其實這個vPortFree執(zhí)行的地方,內(nèi)存是沒有變化的?!?br /> “真的哦,heap_1是不能釋放內(nèi)存的。”突然,我覺得我很有成就感。
“那么,為什么會有這么多空隙的呢?我們看看這段代碼就清楚了?!?br />
void * pvPortMalloc( size_t xWantedSize ){ void * pvReturn = NULL; static uint8_t * pucAlignedHeap = NULL;  /* Ensure that blocks are always aligned. */ #if ( portBYTE_ALIGNMENT != 1 ) { if( xWantedSize & portBYTE_ALIGNMENT_MASK ) { /* Byte alignment required. Check for overflow. */ if ( (xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) )) > xWantedSize ) { xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); } else { xWantedSize = 0; } } } #endif
“哦……原來最大多占了一個portBYTE_ALIGNMENT的空間。”她端詳了一陣這個代碼說。
“所以,官方有說,自從有了static的內(nèi)存分配方法,就很少用這個heap_1了?!?br /> “嗯!”她似乎很滿足的樣子,伸手把奶茶拿過來,接著喝了一口。
我也喝了一口咖啡,突然覺得這個咖啡不苦了。她起身,準備要坐回去。
“等下,我這還有其他數(shù)據(jù),給你看看heap_2的情況?!蔽艺f后,她慢慢坐了下來。夕陽已慢慢落在了城市的高樓之中,道路上依然車水馬龍,而安靜的咖啡館有種說不出來的溫馨。
“那么heap_2有什么不一樣呢?我們直接看圖吧?!?br />

“咦?怎么有更多的孔隙了?”
“是啊,我也納悶,但看了下源碼,確實會這樣,其中有一段是這樣的?!?
 /* The wanted size must be increased so it can contain a BlockLink_t * structure in addition to the requested amount of bytes. */ if( ( xWantedSize > 0 ) && ( ( xWantedSize + heapSTRUCT_SIZE ) >  xWantedSize ) ) /* Overflow check */ { xWantedSize += heapSTRUCT_SIZE;  /* Byte alignment required. Check for overflow. */ if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) ) > xWantedSize ) { xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 ); } else { xWantedSize = 0; } }
我接著解釋說,“你看,用heap_2每次申請一段內(nèi)存,都要多占一段heapSTRUCT_SIZE和一段portBYTE_ALIGNMENT 空間?!?br /> “哦,怪不得,我們項目定義了32K的RAM都差不多用完了,我算了下實際的分配,還差很遠,原來問題在這呢!”她似乎有種茅舍頓開的感覺。
“那么heap_3又是怎樣的呢?”她主動問我要圖片來看了。

“我用PC上位機軟件模擬的,heap_3用的是標準庫的malloc()和free(),似乎沒啥規(guī)律,其實沒什么參考價值的?!?br /> “好吧……那heap_4呢?”她似乎有點失落的樣子,而又“肆無忌憚”起來,直問我要圖看。
我不慌不忙打開了這個圖。

“好像跟heap_2一樣的哦……”
“是的,很像。但是,有個很重要的區(qū)別,你看這最后一幀內(nèi)容,特別是最后紫色的這塊?!蔽姨匾鈱eap_2的和heap_4的拿出來對比了下。

“看起來似乎heap_4更省空間……哈哈!”看著這兩個圖的對比,她樂了起來,像個天真的孩子。
“雖然還是很多孔隙,但是free掉的空間是可以合并的,這個heap_4的好處就在這了。”
“是的,師兄你真厲害!”
“哈哈!”
“對了,還有heap_5的呢?”

“哦?跟heap_4的沒啥區(qū)別哦……”這說話拉長的語調(diào),越來越可愛了。

“效果看起來,確實是一樣的,但是heap_5是可以跨不連續(xù)區(qū)域的。官方文檔也是這么說的?!?

This scheme uses the same first fit and memory coalescence algorithms as heap_4, and allows the heap to span multiple non adjacent (non-contiguous) memory regions.

FreeRTOS
“那么,它是怎么跨區(qū)域的呢?”她突然好奇起來。
“給你看段代碼吧。其實它多了一個函數(shù)?!?br />
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions )
“這個const HeapRegion_t * const pxHeapRegions就是定義不同區(qū)域段的?!?br /> “怎么分段的呢?”“那,我們看這個官方的例子?!?br />
// HeapRegion_t xHeapRegions[] =// {//     { ( uint8_t * ) 0x80000000UL, 0x10000 }, << Defines a block of 0x10000 bytes starting at address 0x80000000//     { ( uint8_t * ) 0x90000000UL, 0xa0000 }, << Defines a block of 0xa0000 bytes starting at address of 0x90000000//     { NULL, 0 }                << Terminates the array.// };// vPortDefineHeapRegions( xHeapRegions ); << Pass the array into vPortDefineHeapRegions().


本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉