1. Kernel
1.1 編譯安裝5.9.6 on Ubuntu
https://phoenixnap.com/kb/build-linux-kernel 需要的改動:
1.UEFI BIOS, secure boot要禁止,不然報linux kernel: invalid signature, you need to load the kernel first’,可也自己生成signature:https://help.univention.com/t/problem-booting-server-shows-invalid-signature-you-need-to-load-the-kernel-first/13557
2.改.config兩行,去掉找不到的debian license,去debug以減小尺寸,改後為:
CONFIG_SYSTEM_TRUSTED_KEYS=""
CONFIG_DEBUG_INFO_BTF=n
3.生成的initrd.img需要strip剪裁,不然啟動時裝入kernel後停在initrd.img處,辦法是https://unix.stackexchange.com/questions/270390/how-to-reduce-the-size-of-the-initrd-when-compiling-your-kernel :
cd /lib/modules/
find . -name *.ko -exec strip --strip-unneeded {} +
cd
sudo make install
1.2 編譯安裝5.13.1 on Ubuntu
sudo apt update && sudo apt upgrade
sudo reboot
sudo apt install build-essential libncurses5-dev fakeroot xz-utils libelf-dev flex bison libssl-dev dwarves zstd
cd ~/Downloads
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.13.1.tar.xz
tar xf linux-5.13.1.tar.xz
cd linux-5.13
sudo find /boot/ ( -iname "*config*" -a -iname "*`uname -r`*" ) -exec cp -i -t ./ {} ;
mv *`uname -r`* .config
ls /boot | grep config
sudo gedit .config &
==comment out: #CONFIG_SYSTEM_TRUSTED_KEYS, #CONFIG_SYSTEM_REVOCATION_KEYS,
==enable: CONFIG_PCIEPORTBUS=y, CONFIG_PCIEAER=y, CONFIG_PCIEAER_INJECT=y, CONFIG_PCIE_ECRC=y,
sudo make menuconfig
sudo make -j 8
sudo make bzImage -j 8
sudo make modules_install
sudo make install
cd /lib/modules/5.13.1
sudo find . -name *.ko -exec strip --strip-unneeded {} +
sudo update-initramfs -c -k 5.13.1
sudo update-grub
sudo reboot
uname -mrs
1.3 remove kernel
https://phoenixnap.com/kb/ubuntu-remove-old-kernels
2 .Zhphyr RTOS
Zhphyr文檔:https://docs.zephyrproject.org/2.7.0/zephyr.pdf? https://docs.zephyrproject.org/latest/
Zephyr on ESP32: https://www.zephyrproject.org/zephyr-rtos-on-esp32/
2.0 west:https://docs.zephyrproject.org/latest/boards/xtensa/esp32/doc/index.html 需要運行west init才能運行
west espressif update
2.1 install Zephyr
https://docs.zephyrproject.org/latest/getting_started/index.html?upgrade stc: https://askubuntu.com/questions/1090223/how-to-upgrade-dtc-version-in-ubuntu-18-04
https://docs.zephyrproject.org/latest/getting_started/index.html 裝Zephyr,編譯前要加裝 pip3 install pyelftools 不然出錯:
cd ~/zephyrproject/zephyr
west build -p auto -b arduino_nano samples/basic/blinky
起步還可以讀:https://www.zephyrproject.org/blinking-an-led-with-zephyr-rtos-creating-an-application/
2.2 install ESP32 tool chain
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html#get-started-prerequisites?
在Connect your device一節,Linux下可用dmesh | grep /dev/ttyUSB*確定插入的串口號。
裝ESPRESSIF: https://docs.espressif.com/projects/esp-idf/en/v4.2/esp32/get-started/index.html#get-started-get-prerequisites 在configure之前要加裝:
sudo apt install python-pip;pip install click
另一錯誤多半是缺省用了Python2,去掉改用Python3的辦法是:
sudo apt purge -y python2.7-minimal
sudo ln -s /usr/bin/python3 /usr/bin/python
sudo apt install -y python3-pip
sudo ln -s /usr/bin/pip3 /usr/bin/pip
python --version
錯誤在menuconfig失敗,找不到不到支持bidict>=0.21.0的模塊,最後將Ubuntu升級到20.04按此文裝成功:https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html#get-started-prerequisites 編譯用idf.py
2.3 不匹配
至此,Zephyr和ESP32各自的工具都就緒,可是Zephyr編譯ESP32不是用ESP32的工具鏈,因此我按https://www.zephyrproject.org/zephyr-rtos-on-esp32/ 裝後,編譯時才發現Zephyr version: 3.0.99是,cmake需3.20,west需0.7.1,dtc需1.5.0,似乎是官網要求的:https://docs.zephyrproject.org/latest/getting_started/index.html
換句話無論按哪個指南做,其中部分軟件更新後,都可導致失敗。按官網發現sdk是0.14而非0.12,又是個耗時的過程。最後編譯錯誤出在
1)-- Found west (found suitable version "0.12.0", minimum required is "0.7.1")
2)-- Found dtc: /usr/bin/dtc (found suitable version "1.5.0", minimum required is "1.4.6")
3)CMake Error at /home/jodai/zephyrproject/zephyr/cmake/toolchain/espressif/generic.cmake:52 (message):
Unable to find toolchain in
/home/jodai/.espressif/tools/xtensa-esp32-elf/esp-2020r3-8.4.0/xtensa-esp32-elf
錯誤3最重要,看Cmake可知它產生的工具鏈是: ~/.espressif/tools/xtensa-esp32-elf/esp-2020r3-8.4.0/xtensa-esp32-elf而實際的是:~/.espressif/tools/zephyr/xtensa-esp32-elf/xtensa-esp32-elf,換句話工具鏈要由github下指定版本。
2.3 nRF52840-MDK
支持 Bluetooth 5、Bluetooth Mesh、Thread、IEEE 802.15.4、ANT 等無線協議,帶有片上 Arm CryptoCell 加密子係統,集成了多功能調試器 Arm Mbed DAPLink,提供“拖放式”下載固件、USB CDC 虛擬串口、CMSIS-DAP 仿真等功能。板載Microchip 兩端口 USB 2.0 高速集線器,隻需一個 USB 接口即可同時使用 DAPLink 和 nRF52840 的 USB 設備控製器;有64Mbit 超低功耗 QSPI FLASH、可編程按鍵、RGB LED、晶片天線及外部天線連接器等硬件資源。
nRF52840-MDK 支持Zephyr框架,跨平台開發,可以玩轉多種開源軟件框架(如:nRF5 SDK, Mesh, OpenThread, ZigBee 3.0, Mbed OS 5, Zephyr, Mynewt, iBeacon, Eddystone, Web Bluetooth 等等),提供豐富的在線文檔及示例,幫助加速物聯網應用開發。https://bbs.huaweicloud.com/blogs/163505
中肯提醒:如果您是 MCU 世界的新手且功耗不是大問題,請選擇 ESP32。 Nordic 的東西(比如這個板子)更適合實際的生產綁定產品開發和原型設計,更加健壯和靈活,但根據我的經驗,IDE 並不直觀,支持庫也不那麽廣泛。 我隻向有經驗的用戶或快速學習者推薦這個產品。 如果您知道自己在做什麽,這是一個很棒的產品,並且比官方的 Nordic nRF 開發板小得多,後者是無用的巨大。直觀的 arduino IDE 更好地支持相同外形尺寸的 esp32 板,並具有廣泛的支持庫、示例代碼示例和龐大的社區來提供幫助。
Zephyr用了類似Linux的menuconfig,Intel曾在開始時很熱心,現在是NXP。缺點是比較複雜,樣本多是板子廠家提供通用性一般,感覺工具出問題比較麻煩不如make直接給出原因。arduino IDE就太簡潔直觀了。所用版本備忘:
$ cmake --version
cmake version 3.23.0
$ python3 --version
Python 3.8.10
$ dtc --version
Version: DTC 1.5.0
$ west --version
West version: v0.12.0
~/zephyrproject/zephyr$ west build -p auto -b esp32 samples/basic/blinky
https://github.com/espressif/crosstool-NG/releases
3. FreeRTOS
https://github.com/freertos? https://zhuanlan.zhihu.com/p/145699420 https://blog.csdn.net/Chuangke_Andy/article/details/115397230 官網的18f452代碼不能編譯:1)所有源碼是同一目錄上載到官網變成多級目錄 2)XIDE加include路徑無效 3)核心已經修改不配套 4)原編譯器用PICC與XC8不兼容,XC8聲稱的#asm也不能用,asm()可用。新片PIC18F26/46/56Q43為28/40/44/48pin,PIC18F26Q43-I/SP $2.08,PIC18F45Q43T-I/PT $1.7, PIC18F4550T-I/PT $7.91:
18F4550T-I/PT TQFP44,10x10 2.0-5.5V 32K 2KB-DRAM 256B-EEPROM 48MHz I/O-35 UART/I2C/SPI 10bx13chAD no-DAC USB2.0
18F45Q43T-I/PT TQFP48,7x7 1.8-5.5V 32K 2KB-DRAM 1KB-EEPROM 64MHz I/O-36 +I2S+PWM 12bx35chAD 8bx1ch no-USB
18F45K50-I/P DIP40 2.3-5.5V $2.08 32K 2KB-DRAM 256B-EEPROM 48MHz I/O-35 UART/I2C/SPI 10bx13chAD 5bx1ch USB2.0
https://github.com/tahaemara/MicroRTOS-for-PIC-18F-Family PIC18F4550用mikroc PRO for PIC編譯。https://www.youtube.com/watch?v=hYynOanPZWU 使用T0時鍾延遲和軟件堆棧。uP初始化棧指針STKPTR為0,TOSU:TOSH:TOSL存有當前棧指針STKPTR的內容24bit,操作棧時需禁止GIE。STKOVF/STKUNF為上溢/下溢標誌。上溢時若STVREN置位將中斷,否則棧頂0x7F內容被重寫;但是人工設置STVREN不會中斷。STKUNF同理。新品F45K50:1) Have lesser flash write cycles
2) Needs no crystal for USB. built in oscillator works up to 16 MHz.
3) Oscillator configuration, config bits are slightly different.
4) Has a 5-bit DAC and CTMU peripheral for capacitive sensing.
5) might not supported by free mcc18 compilers
6) not supported by PICkit2 (non-official device file supports this)
7) LPT1OSC config bit not available on the K part.
https://github.com/FreeRTOS/FreeRTOS/releases
以前就說過,Pic因為時間長芯片程序會丟,現有用Pic的產品需重編程,否則不要用。ESP32價廉物美可覆蓋多數嵌入式,但是基於ARM的板子也很多。我用Arduino IDE試了ESP32版本的FreeRTOS-因為CPU是雙核,很好用很容易,如果sample code夾雜了其它CPU的.h文件需要改造。
3.1 FreeRTOS的學習筆記
https://freertos.org/Documentation/161204_Mastering_the_FreeRTOS_Real_Time_Kernel-A_Hands-On_Tutorial_Guide.pdf
FreeRTOS
└─Source
├─tasks.c FreeRTOS source file - always required
├─list.c FreeRTOS source file - always required
├─queue.c FreeRTOS source file - nearly always required
├─timers.c FreeRTOS source file - optional
├─event_groups.c FreeRTOS source file - optional
└─Portable
├─[compiler]/[architecture] All C/asm files
└─MemMang
└─heap_?.c heap_?.c, ?=1-5, heap files
目前v10,由v9開始無需heap manager,有5個heap?.c可選:1適用於任務創建後無需刪除,沒有回收的環境;3類似傳統malloc/free但有線程安全性且忽略TOTAL_HEAP_SIZE;4是2的增強,會把釋放的相連的緩衝池合並;5用於緩衝池不連續的環境需要配置。函數是pvPortMalloc() 和vPortFree(),也有統計函數xPortGetFreeHeapSize()(unit in bytes)和configTOTAL_HEAP_SIZE定義堆的大小單位是棧寬,如64bit則為64bit。FreeRTOS中,函數前綴v返回void,x返回變量,pv返回void指針,pd是常量。注意ESP32的RAM類型多,官網另有heap說明。注意在原版Vanilla FreeRTOS中uxTaskGetStackHighWaterMark返回Dword長度而在ESP-IDF中返回Byte長度,是堆棧空餘最小值。https://www.youtube.com/watch?v=Qske3yZRW5I#t=10m38s?
配置文件是FreeRTOS/Source/include/FreeRTOSConfig.h,缺省配置的tick是10ms(可改為1ms)是所有延遲的最小單位,延遲時間用pdMS_TO_TICKS()轉為tick,延遲函數是vTaskDelay()和vTaskDelayUntil(),後者是定周期的任務執行。如果不用係統延遲函數,較低優先級的任務將被堵塞。FreeRTOS配置configUSE_PREEMPTION和configUSE_TIME_SLICING可為搶占式或合作(輪轉)式,通常兩者都置1。任務是一個死循環的函數或進程,其堆棧和變量均在其heap中,由主程序中的vTaskStartScheduler係統調度將其在條件滿足時投入運行,這些條件包括端口或定時中斷、各種信號量等。任務相關函數有:xTaskCreate、xTaskCreateStatic、vTaskPrioritySet、uxTaskPriorityGet、vTaskDelete()。任務狀態有:running、ready、blocked、suspended四種狀態。任務優先級通常是0-31。最低為0是係統idle任務專用,idle任務實現一些係統統計功能,可用vApplicationIdleHook添加用戶任務,如將係統置於低功耗,此時configUSE_IDLE_HOOK需為1。
Queue隊列是一個FIFO先進先出的數據區,但數據的拷貝也可以取消或重寫,任何任務均可訪問。通常用於任務間通信,也可用於任務與中斷服務程序的通信。在任務等待隊列數據時會進入blocked態。可能會有多個任務因等待數據而進入blocked;一旦數據到來,隻有最高優先級或等待最久的任務會被激活。 同樣,可能會有多個寫任務因隊列滿處於blocked,待可寫入時隻有一個被激活,但寫入操作可指定最大等待時延。Queue由 xQueueCreateStatic() 或 xQueueCreateStatic()創建並返回handle;由xQueueSendToBack()和xQueueSendToFront()寫入,或xQueueSendToFrontFromISR()和xQueueSendToBackFromISR();讀是xQueueReceive()。Queue的內容可以是任何數據結構。
TCP TCP/IP stack包的例子:從網絡接收的數據通過結構IPStackEvent_t的發送到TCP/IP任務,結構中的eEventType設置為eNetworkRxEvent,而pvData 指向包含接收數據的緩衝區;根據eEventType來處理各類事件/數據。
如果必須用多個Queue來處理數據,可以把它們放入Queue Set隊列集中,而無需逐個判斷是否有數據待處理,並可捆綁Semaphores信號燈。這是通過將configUSE_QUEUE_SETS置1和xQueueCreateSet、xQueueAddToSet來實現的。然後用xQueueSelectFromSet先取得有數據的Queue Handle或SemaphoreHandle_t handle,比較其名後用xQueueReceive或xSemaphoreTake做相應處理。
mail box在此是長度為1的Queue。Queue通常為另一個任務或中斷服務程序提供數據,後者則取出數據;mailbox不同的是它的寫xQueueOverwrite是覆蓋性的;數據可為任何任務或中斷服務程序通過xQueuePeek來讀但並不取出,用戶代碼可用返回pdTRUE來表明新數據,否則pdFALSE。
軟件計時器用於以固定頻率周期或在未來設定時刻執行程序,籍由其ATimerCallback回調函數實現。這是可選的,需要configUSE_TIMERS置1並包括FreeRTOS/Source/timers.c。回調函數不能被blocked,因此不能調用API、vTaskDelay或xTicksToWait不為0的xQueueReceive。Software Timer由xTimerCreateStatic或xTimerCreate創建,相關函數有xTimerStart/Stop/Reset/ChangePeriod等。它可以是One shot或Auto-reload,有Dormant休眠和Running運行兩種狀態,Timer service或稱RTOS daemon任務自動運行並由configTIMER_TASK_PRIORITY和configTIMER_TASK_STACK_DEPTH配置,API通過timer command queue給它下達命令,隊列長度是configTIMER_QUEUE_LENGTH。每個Timer可通過vTimerSetTimerID()設置ID,由pvTimerGetTimerID()直接讀取,不通過命令隊列。xTimerChangePeriod可以改變定時,例如在CheckTasksAreRunningWithoutError返回錯誤後。
中斷服務調用的API函數(*fromISR)導致更高優先級任務應當被換入時,FreeRTOS設計為在中斷內不做自動切換,但可通過portYIELD_FROM_ISR()或portEND_SWITCHING_ISR()來切換,兩者功能相同,都是taskYIELD()的可在中斷內使用的的版本,有的隻移植其一。調用的參數是pxHigherPriorityTaskWoken,它應初始化為pdFALSE,在發生上述情況下被RTOS置為pdTRUE。如果初始化為NULL則禁止其功能。極少數移植隻允許portYIELD_FROM_ISR()在終端服務程序的最後使用。
Deferred Interrupt Processing是指盡可能的把中斷服務的功能放在服務程序之外的任務中,以減小中斷開銷和使用更多的API功能,該任務的優先級通常高於其它任務,用xSemaphoreCreateBinary創建且調用xSemaphoreTake()使自己掛起。在中斷服務程序中調用xSemaphoreGiveFromISR()給該任務、開中斷後調用portYIELD_FROM_ISR(),將直接切換到該任務。這種semaphore的用法與常規不同-不給還,更像是長度為1的Queue。vPortGenerateSimulatedInterrupt()可用於中斷仿真。
centralized deferred interrupt processing是指用xTimerPendFunctionCallFromISR()延遲中斷處理給RTOS Daemon守護程序,避免每個中斷都要一個外處理任務;該函數的中斷不安全版是xTimerPendFunctionCall。許多API函數有中斷安全版(fromISR),例如Queue讀寫函數。
嵌套的中斷需要配置,注意Cortex-M的中斷是數字越小優先級越高,可以用Assert使得FreeRTOS檢測。
資源管理:任務在訪問不可重入且非線程安全的共享資源時,需要獨占訪問權直至資源到一致狀態。用於例如對非原子的讀-修改-寫代碼用Mutex以免被打斷,或在打印字符行時不會被插入其它字符串,兩者均可用宏調用taskENTER_CRITICAL()和taskEXIT_CRITICAL()來包圍,稱為基本臨界區。在中斷中臨界區可用uxSavedIntruptStatus = taskENTER_CRITICAL_FROM_ISR();和taskEXIT_CRITICAL_FROM_ISR(uxSavedIntrStatus);來包圍。另一對可以使用的函數是vTaskSuspendAll和xTaskResumeAll。
binary semaphore通常用於事件同步或延遲的中斷處理,counting semaphore通常用於事件或資源計數。常規的它是0~N之間的變量;但在FreeRTOS中是長度為N內容不論的Queue。它由configUSE_COUNTING_SEMAPHORES置1使能,用xSemaphoreCreateCounting創建,多次調用xSemaphoreGiveFromISR可以設置大於1的值。
mutual exclusion(Mutex)互斥鎖與之類似,常用於任務中來獨占被多個任務共享的資源。Mutex可理解為token,獲得它的任務獨享資源,用後必須交回;而binary semaphore多用於事件同步,獲得後不必交回多被丟棄。由configUSE_MUTEXES使能,xSemaphoreCreateMutex創建,仍用xSemaphoreTake和xSemaphoreGive來獲得和交回。低優先級的任務能因獲得Mutex而導致高優先級的任務被blocked,直至Mutex被釋放,這被稱為Priority inversion優先級反轉。由於低優先級的任務不被換出,相當於它具有了與高優先級任務同樣的優先級,又稱Mutex有Priority Inheritance優先級繼承的特點;而binary semaphore沒有這個特點。如果是同一優先級,剛獲得Mutex的任務B要等下次調度;但前一任務A可能再次獲得Mutex並繼續運行,導致任務B不能即時運行,這需要適當的編碼以平衡任務的運行時間,或及時調用taskYIELD。
如果兩個任務互相用Mutex獨占了對方所需資源,兩者都因等待而無法運行,這被稱為Dead lock死鎖,需要在編碼時避免或給Mutex等待限時,或者將資源置於Gatekeeper任務管理之下,需要的任務都通過它來獲得資源。使用時configUSE_TICK_HOOK置1,然後定義vApplicationTickHook(),它在每個tick被執行,因此必須簡短。
Dead Lock死鎖也可在單個任務中因多次獲取Mutex而忘了釋放而產生,這時可用Recursive Mutex,同一任務可N次獲得該Mutex,但是在N次釋放前別的任務不可獲得該Mutex。相關函數名在Mutex前有前綴Recursive。
事件組:允許任務在阻塞狀態下等待多個組合事件;可在事件發生時unblock等待該事件(組)的所有任務,可以由多個任務共享。EventBits_t缺省為32bit,低24bit分別對應一個事件。以FreeRTOS+TCP TCP/IP stack包為例,它包括在FreeRTOS_Socket_t結構中,含有TCP socket的accept/bind/read/close及Abort事件,由FreeRTOS+TCP API使用。
相關函數為xEventGroupCreate、xEventGroupSetBits(FromISR)、xEventGroupWaitBits,最後這個函數允許所在任務按事件組blocked和unblocked。事件組也可用於任務同步,例如接受到TCP包的任務委托其它幾個任務處理,在都處理完後相關事件都被置位,該包就可close。
Task Notifications任務通知:指任務間直接通信,不通過例如queue、semaphore等對象中轉。將configUSE_TASK_NOTIFICATIONS置1後,每個任務都有“Notification State”和uint32的“Notification Value”。注意:發送任務不能阻塞以待發送完成。接收任務隻允許是一個且不能是中斷服務程序,可選指定時延的堵塞式等待它的通知狀態變為Pending,在讀取通知值後狀態被置為Not-Pending。有兩套函數:簡化的發送xTaskNotifyGive()/xTaskNotifyGiveFromISR(),發送後通知值自動加1,配用堵塞等待的ulTaskNotifyTake()接收,可以取代以前的binary semaphore用於延遲的中斷服務;增強的xTaskNotify()/xTaskNotifyFromISR() /xTaskNotifyWait(),多了對通知值的讀寫,可提供類似mail box或事件組覆蓋寫入的功能。xTaskNotifyWait()以可選的超時等待調用任務接收通知。如果接收任務在等待通知到達時已在等待通知的blocked態,則接收RTOS任務將被unblock並清除通知。
書中偽碼例154:由Mutex互斥的xUART_Send()被共享來發送數據,先用xSemaphoreTake()清空,繼而調用底層發送,再用xSemaphoreTake()使自己處於堵塞態。UART硬件在最後一字符被發送後中斷,在中斷服務中用xSemaphoreGiveFromISR()使得xUART_Send()解除堵塞,隨即portYIELD_FROM_ISR()切換運行。
例155:semaphore帶來的存儲和執行開銷、及初始化在上例中是不必要的。本例中semaphore由TaskHandle_t類型的xTaskToNotify取代,後者由API和中斷共享。如果CPU位長不低於任務通知值,寫入是原子操作,否則寫入需臨界域保護。用於接收的類似實現見例156。例157則用xTaskNotifyWait()以便傳送ADC值,很實用的方法。本章最後說明了雲端收發的流程。
關於調試:並非所有編譯器都提供Assert,為此可在配置中定義等效的configASSERT(),出錯時後續的代碼不會運行。例如自定義函數vAssertCalled()然後定義:
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )
FreeRTOS提供Malloc failed hook、Stack overflow hook、Task Run-Time Statistics、Run-Time Statistics Clock,配置後與uxTaskGetSystemState()聯用。另有Helper函數和Trace Hook Macros,許多IDE也提供debug plugin。FreeRTOS+Trace是Percepio提供的運行時診斷和優化工具,包括互聯的20種圖表。
最常見開發問題是incorrect interrupt priority assignment, stack overflow, inappropriate use of printf().
1)中斷優先級:硬件中斷的優先級應高於任務。不能超出configMAX_SYSCALL_INTERRUPT_PRIORITY,不能不定義,ARM Cortex把最低數字認為最高優先級。例如某CPU中斷和配置最高中斷都是5,但可被優先級4中斷,則API中斷優先級的值不應低於5。ARM Cortex的硬件和庫實現都各有不同。優先級可分為pre-emption priority和sub-priority兩部分,請隻使用前一部分。有時候configMAX_SYSCALL_INTERRUPT_PRIORITY被稱為configMAX_API_CALL_INTERRUPT_PRIORITY。
2)堆棧溢出:uxTaskGetStackHighWaterMark()返回某任務棧的最小剩餘空間。配置configCHECK_FOR_STACK_OVERFLOW為1(返回棧的曆史)或2(返回最近20此)並使用下列函數原型來勾取棧溢出的處理函數:void vApplicationStackOverflowHook( TaskHandle_t *pxTask, signed char *pcTaskName );
3)亂用printf()/sprintf():除非特殊設計。這兩函數通常不具有線程安全性,可能會用malloc()或用堆棧,會加大程序尺寸和開銷。開源的printf-stdarg.c可用來替代庫函數,並可將輸出重定向到端口。
其它注意事項:在中斷服務中或調度器被掛起-例如在臨界區域內-使用一般API函數可能崩盤。在調度器運行前的中斷可能崩盤。在調度器工作前使用API可能導致中斷被禁止。