繼
上篇敗家之後, 該收心了, 回到
上上篇的使用 std::vector 的問題上吧!
在克服 exception handling 的編譯問題後, 可以試試看呼叫 std::vector。mycpp.cpp L150 ~ L153 是熟悉的 vector 用法, 若能在 bare metal 上用上這個, 多美好阿! 老是用固定大小的 array, 彈性不夠, 覺得很不爽。
在使用了 vector 之後, 會有很多 undefined symbol, mycpp.cpp L22 ~ L84 把他們一一補上, 你說 vector 為什麼會和 _write 有關係? 我也不知道, 反正補上就是了。
由於在 bare metal 環境並沒有類似 malloc 的記憶體配置 function (你應該不會預期有這樣的 function 可以用), 而這種會自己長大的容器一定是需要這種操作的, 那該怎麼辦呢?
從 toolchain library 補上 malloc/free, new/delete 這些東西, 這個可能工程大了點, 我改用另外一個途徑, 使用自己的 allocator, 所以要先寫一個 allocator。
看來好像也是一個大工程, 不過有現成的可以抄, 我就抄過 (就是常常被詬病的 copy/paste) 來了 (mycpp.cpp L88 ~ 140)。再把原本的 malloc 換成我自己的 mymalloc 就成了。
一開始的 mymalloc 只是回傳一個固定的記憶體位址, L86 的 memarea, 看起來很簡單也很可疑, 不過的確可以正常運作。
void *mymalloc(u32 size)
{
return memarea;
}
當然這個實在是太蠢了, 也會有一些問題, vector 在記憶體不夠的情況下, 會以 1, 2, 4, 8 的大小去配置需要的記憶體 (和書上寫的一樣耶!)。若是 vector<int> 就是 1*4, 2*4, 4*4, 8*4 去配置記憶體, 所以在某個情況下, 那個寫死的大小就會不夠用了。
所以我開發了一個相對不那麼蠢的, 對, 其實還是很蠢, 不過簡單, 又具有實用性, 還可以驗證如果配置不到需要的記憶體, 會怎麼辦? 你一定很少看到 vector 要不到記憶體的情況吧?
mem.cpp 從 64k 的 heap 分配記憶體, 很蠢的只有分配, 無法再度使用 myfree 回收的記憶體。不過實作就容易多了。
以目前的記憶體管理設計, 當 vector 要以 32 去要記憶體時, 就會不夠用, 這時候 allocate 就會丟出 std::bad_alloc() (RESULT L11)。
RESULT 是在 linux 平台下的測試結果, 再搬到 stm32f4-discovery 上測試, 可以正常的使用
vec.push_back(0)
vec.push_back(1)
vec.push_back(2)
vec.push_back(3)
vec.push_back(4)
不過由於在 stm32f4-discovery 不能丟出 std::bad_alloc(), 我得想個辦法處理要不到記憶體的情況, 否則, vector 就不威了, 處理方式也很簡單, 印出訊息然後無窮回圈。stm32f4-discovery sram 只有 192k, 很小的。
目前 github 的版本已經稍做改良, 可以用更細緻的方式配置記憶體, myfree 也會去回收用過的記憶體, 當然還是比不上一般作業系統的的精緻度。
這是 gcc malloc_allocator 的實作, L98 也是使用 malloc, 並丟出 bad_alloc exception。
以下是在 stm32 模擬器的完整範例:
https://github.com/descent/progs/tree/master/mem_alloc/mem.h
https://github.com/descent/progs/tree/master/mem_alloc/mem.cpp
https://github.com/descent/stm32_p103_demos/tree/master/demos/uart_echo/myvec
commit 317bde9c68f38eab73969a9526247dfb6bd1a870
ref:
Using Custom Allocators
沒有留言:
張貼留言
使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。
我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。