RT-Thread移植到nRF52840

2021-02-14 RTThread物聯網作業系統

編者按:  

其實很忙的,但是還是抽時間記錄了我的學習過程。這應該是我寫的格式比較正規的第3本學習筆記了,第一本《BLE4.0低功耗藍牙協議總結》、第二本《ANT協議研究》,再就是這本了《RT-Thread BLE5.0和ANT+應用開發實戰指南》,名字取得很大,哈哈哈!!目前這本已經寫到了第19章,目前規劃到了35章左右,慢慢寫吧!在這呢!感謝熊大團隊的RT-Thread作業系統,的確是一個非常好的RTOS,至少對於我來說很喜歡,因為其他RTOS就是個內核,大一點的就是Linux,太龐大了,吃不消。本文從文檔中抽出RT-Thread移植到nRF52840這篇和大家分享,這個文檔應該會在11月底發到論壇,公眾號、qq群和百度網盤的。

《RT-Thread BLE5.0和ANT+應用開發實戰指南》

當前目錄如下圖

第11章 RT-Thread移植到nRF52840

    終於進入正文了,這裡再囉嗦一句,如果需要了解RT-Thread的內核等問題,可以參考RT-Thread官放的《rtthread_manual.zh》(下載地址-複製至外部瀏覽器打開:https://www.rt-thread.org/document/site/submodules/rtthread-manual-doc/README/)以及火哥的《RT-Thread 內核實現與應用開發實戰—基於STM32》(本公眾號後臺回覆:野火RT-Thread 即可下載),本書的重點還是側重藍牙理論和實戰。這個工程是由001.led_none工程修改而來,對應ZJ-SDK的002.led_RT_Thread_Doing工程。

11.1 RT-Thread的內核源碼加入基礎工程


    為了從0到1的移植RT-Thread,這裡先將RT-Thread的內核源碼加入到 001.led_none 基礎工程,看遇到的問題。添加的步驟是先添加.c文件,再添加.h文件路逕到頭文件,同時改了工程中文件夾的名字。

11.1.1 添加源文件

添加後的工程和基礎工程對比如圖11-1所示

  圖11-1    基礎工程添加RT-Thread內核源碼

11.1.2 添加頭文件路徑

    頭文件的添加對比如圖11-2所示,只是添加了RT-Thread的內核頭文件,以及M4核相關的頭文件。


                          

  圖11-2   基礎工程添加RT-Thread相關頭文件

11.2 編譯解除錯誤

    上面添加之後,進行編譯,編譯結果如圖11-3所示。編譯報出沒有rtconfig.h的頭文件,實際上也的確沒有這個頭文件,可以從官方RT-Thread源碼中的bsp目錄下的nrf52832中的工程中拷貝一個rtconfig.h來,放到本工程的config文件夾中。這樣編譯就能完全通過了。

  圖11-3    編譯報錯

11.3 編程成功存儲分布

    再次編譯,看看勝利的果實,如圖11-4所示的存儲分布,falsh和ram的各個段都有明確的示意,堆和棧各使用了8K空間,中斷向量表使用了256位元組flash。

 圖11-4    存儲分布圖

11.4 運行RT-Thread內核

   經過上面的處理,只需要一個銜接nRF52840和RT-Thread內核的關聯文件,以及一個初始化RT-Thread的文件,那麼就能使RT-Thread運行起來了。RT-Thread能運行起來就一定需要一個系統tick,也就是需要給RT-Thread內核創造一個產生tick的接口,實際上就是systick或者RTC的tick中斷函數,這個中斷函數中處理RT-Thread的相關東西,從而使RT-Thread和nRF52840連接在一起。

11.4.1 銜接及初始化文件來源

    這裡為了方便,我們依然從官方RT-Thread源碼中的bsp中nRF52832中得到一些參考。官方nRF52832工程所包含的文件如圖11-5所示。

    圖11-5    官方nRF52832工程文件夾

    從官方工程文件中,我們只需要4個文件,分別是application文件夾下的application.c文件和startup.c文件以及board文件夾下的board.c和board.h文件。startup文件夾是arm相關以及nrf52832相關的文件,這裡不需要。這幾個文件中application.c是用戶的函數入口,startup.c為RT-Thread系統的初始化文件,而board.c文件則是產生tick的地方。將這4個文件直接拷貝到001.len_none目錄下,如圖11-6所示。

  圖11-6    拷貝銜接啟動文件後的工程目錄

11.4.2 添加文件第一次編譯排錯

    接下來直接將這3個.c文件添加到工程,以及包含頭文件路徑後進行第一次編譯報錯如圖11-7所示。

圖11-7    第一次編譯報錯

    因為沒有使用uart,所有將這個頭文件刪掉。這樣經過多次的編譯刪掉多餘的頭文件同時添加缺少的沒有包含的頭文件路徑,一步一步地逼近編譯成功。下面統計修改的地方。

uart.hsoftdevice_handler.hnrf_drv_uart.h

nrf_drv_common.h路徑:../../../NORDIC_SDK/integration/nrfx/legacynrfx_clock.h路徑:../../../NORDIC_SDK/modules/nrfx/drivers/include

11.4.3 第二次編譯排錯

   經過上面的修改之後,再次編譯時,出現如圖11-8的錯誤,有多個main函數。

圖11-8    多個main函數定義

 可以查看到代碼中除了原本的工程中有一個main.c文件中有main函數之外,還有一個文件application.c中也有main函數,這裡為了保持led的閃爍功能,將移除main.c文件,將main.c中的main函數功能在application.c中的main函數實現。最後修改application.c的代碼如代碼清單11-1,紅色部分為修改部分:

代碼清單11-1    修改後的application.c

#include <rtthread.h>#include <stdbool.h>#include <stdint.h>#include "nrf_delay.h"#include "nrf_gpio.h"#ifdef RT_USING_FINSH#include <finsh.h>#include <shell.h>#endifvoid rt_init_thread_entry(void* parameter){    nrf_gpio_cfg_output(ZJ_LED1);    /* Toggle LEDs. */    while (true)    {       nrf_gpio_pin_toggle(ZJ_LED1);       nrf_delay_ms(500);    }}int rt_application_init(void){    rt_thread_t tid;    tid = rt_thread_create("init", rt_init_thread_entry, RT_NULL, 1024,                            RT_THREAD_PRIORITY_MAX / 3, 20);    if (tid != RT_NULL)        rt_thread_startup(tid);    return 0;}

11.4.4第三次編譯排錯

    再次進行編譯出現如圖11-9的錯誤

 圖11-9    第三次編譯出錯

看報錯記錄有3個錯誤:

    這個應該是缺少.c文件,這裡使用了RTC,但是工程中沒有相關的.c文件,所以這個錯誤只需將對應的.c文件添加到工程,同時在sdk_config.h中將這個功能宏打開即能解決。

    添加的兩個.c文件是nrfx_clock.c和nrf_drv_clock.c。

   sdk_config.h文件末尾添加宏代碼清單如11-2:

代碼清單11-2    sdk_config.h文件末尾添加宏

// </h> //==========================================================// <h> nRF_Drivers //==========================================================// <e> CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver - legacy layer//==========================================================#ifndef CLOCK_ENABLED#define CLOCK_ENABLED 1#endif// <o> CLOCK_CONFIG_LF_SRC  - LF Clock Source // <0=> RC // <1=> XTAL // <2=> Synth #ifndef CLOCK_CONFIG_LF_SRC#define CLOCK_CONFIG_LF_SRC 1#endif// <o> CLOCK_CONFIG_IRQ_PRIORITY  - Interrupt priority// <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice// <0=> 0 (highest) // <1=> 1 // <2=> 2 // <3=> 3 // <4=> 4 // <5=> 5 // <6=> 6 // <7=> 7 #ifndef CLOCK_CONFIG_IRQ_PRIORITY#define CLOCK_CONFIG_IRQ_PRIORITY 7#endif// </e>// </h> //==========================================================

    這個符號的是沒有初始在RAM中的段末地址,而這個地址要作為RT-Thread的heap的起始地址,既然知道了是沒有初始化的段末地址符號,那麼就可以直接搜索__bss_end這個符號試試運氣,可以找到在thumb_crt0.s中進行bss段清零時的使用到bss段末地址符號為__bss_end__(如圖11-10所示),所以將這個錯誤宏改為__bss_end__即可。

  圖11-10    bss段末地址符號__bss_end__


11.4.5編譯成功存儲分布

    經過多次的編譯排錯終於見到了勝利的曙光,編譯的存儲分布如圖11-11所示。和只是加入源碼的圖11-4進行對比可以明顯看到某些段有變化。

 圖11-11    RT-Thread啟動編譯成功存儲分布

11.5下載調試

     將上面的固件下載到ZJ曹孟德開發板中,可以看到LED1在閃爍,至此整個移植過程算是結束,但是我在調試時發現進入不了idle回調的休眠模式,因為在閃燈的延時函數是使用的死等延時,需要將nrf_delay_ms(500)修改為RT-Thread系統延時函數rt_thread_mdelay(500),再次編譯下載調試發現燈沒有閃爍,停止調試時,發現代碼一直在一個while等待中,如圖11-12所示。

圖11-12    RT-Thread跳不出while

   NVIC_ISPR是中斷掛起設置寄存器,這個while就是等到中斷掛起寄存器中有中斷掛起,而__WFE()則是wait for event 等待事件,即下一次事件發生前都在此hold住不幹活從而使cpu進入low-power standby模式,這裡去讀NVIC_ISPR應該是有一定的邏輯問題的,經過參考其他資料和代碼,可以將上面的do-while改為如代碼清單11-3所示:

代碼清單11-1    修改do-while

{    /* No SD -  we would just block interrupts globally.    * BASEPRI cannot be used for that because it would prevent WFE from wake up.    */     __WFE();     __WFE(); }

再次編譯下載就可以看到LED1又活躍的閃爍起來了。至此整個移植過程完畢。

11.6美化工程

    上面的工程即是ZJ-SDK中的002.led_RT_Thread_Doing工程,雖然能完美的工作了,但是工程文件夾的組織還需要做一個適當的調整。所以就出現了ZJ-SDK中的003.led_RT_Thread工程,這個工程將是帶有RT-Thread的基礎工程。這兩個工程的文件對比如圖11-13所示。

    將board.c、startup.c以及application.c都作為RT-Thread的啟動文件,而用戶的操作將在application文件夾中的app_init.c中進行,也就是LED1閃爍的功能實現是在app_init.c中了,而在application.c中進行調用,從而進入用戶應用層。同時更改工程的名字為zj_ble_rt_thread,之後的工程名都將是這個名字,不會根據功能修改工程名,只會根據功能修改工程文件夾名。002.led_RT_Thread_Doing工程文件和003.led_RT_Thread工程文件對比圖如圖11-13所示。

   board.c文件不修改也是可以運行的,但是有一些不合理的邏輯,所以0003.led_RT-Thread工程中這個文件做了大的修改,在後文的第13章分析RT-Thread基礎工程啟動流程中將會進行詳細分析。

 圖11-13    工程美化

 圖11-14    美化後的工程文件對比

往期精彩(點擊文章即可閱讀)

帶你進入絢麗多彩的柿餅M(一)

RT-Thread近期活動

1.在本公眾號後臺回復「野火RT-Thread」即可下載《RT-Thread內核實現與應用開發實戰指南》完整版

2.長按添加「小師妹」為好友,備註「學生」拉你進「RT-Thread官方學生」群,凡是在校學生組團報名參加大學生計劃審核通過的,即可獲得RT-Thread官方的競賽支持、培訓學習等。

你可以添加微信13924608367為好友,註明:公司+姓名,拉進 RT-Thread 官方微信交流群

RT-Thread


讓物聯網終端的開發變得簡單、快速,晶片的價值得到最大化發揮。GPLv2+協議,可免費在商業產品中使用。

👇點擊進入官方論壇        

相關焦點

  • RT-Thread的finsh在nRF52840上的使用
    說白了就是開發者可以通過串口直接讓內核或者應用層已經寫好了的函數直接運行後返回結果到控制臺。抄一部分官網的簡介吧!以及後面的移植也是參考官網進行的。18.1 finsh簡介   finsh是RT-Thread的命令行外殼(shell),提供一套供用戶在命令行的操作接口,主要用於調試或查看系統信息。finsh支持兩種模式:1.
  • RT_Thread系統使用總結
    (void* parameter){While(1){LED1_ON;rt_thread_delay(500); //延時500個tickLED1_OFF;Rt_thread_delay(500);//延時500個tick}}線程中的延時函數必須使用RT_Thread裡面提供的延時函數,該延時函數是阻塞延時,即調用RT_Thread_delay()函數的時候,當前線程會被掛起,調度器會切換到其它就緒的線程
  • 【RT-Thread Studio入門】使用輪詢法檢測按鍵
    = RT_NULL) 3    rt_err = rt_thread_startup(key_thread); 4else 5    rt_kprintf("key thread create failure !!!
  • RT-Thread 自動初始化詳解
    官網文檔提及到了,(他們的文檔在這裡:https://www.rt-thread.org/document/site/programming-manual/basic/basic/#rt-thread_3),但是寫的只是概念層面上的,看完後會使用但原理還是不太清楚。之前研究過,今天把它總結下,寫出來分享。
  • RT-Thread面向對象編程思路淺析
    在rtthread中所有的類型的上帝就是rt_object。對象有對應的名稱,類型,標識以及下一個的鍊表。比如說ipc,消息間的通信機制這些都是基於rt_ipc_object的基類集成的。所以rt-thread的程序設計中,大量的用到了這種面向對象的思想進行設計。
  • RT-Thread AT 組件應用筆記 - 客戶端篇
    3.2.1AT Client 配置1.下載RT-Thread 源碼2.下載env 工具3.開啟 env 工具,進入 rt-thread\bsp\stm32f4xx-HAL 目錄,在 env 命令行輸入 menuconfig 進入配置界面配置工程。
  • RT-Thread教程一之Linux下開發環境及QEMU配置
    RT-Thread原始碼Linux下安裝git後在工程目錄下(比~/Workplace)執行git clone https://github.com/RT-Thread/rt-thread我們看一下樹目錄結構rt-thread
  • RT-Thread低功耗組件用戶手冊(1)
    );按下復位按鍵重啟開發板,打開終端軟體,可以看到有定時輸出日誌:1 \ | /2- RT - Thread Operating System3 / | \ 3.1.0 build Sep 7201842006 - 2018 Copyright by rt-thread team5msh
  • RT-Thread ADC設備學習筆記
    本節,我們將會學習到RT-Thread ADC設備的基本使用。接下來,我們將基於RT-Thread Studio來構建。2、開始實踐上一節我們已經熟悉了怎麼創建工程和配置項目了,這節我們直接略過這兩步操作,直接看硬體圖。
  • RT-Thread設備框架使用指南——I2C 總線設備
    >nameI2C 總線設備名稱返回——設備句柄查找到對應設備將返回相應的設備句柄RT_NULL沒有找到相應的設備對象一般情況下,註冊到系統的 I2C  設備名稱為 i2c0 ,i2c1等,使用示例如下所示:1#define AHT10_I2C_BUS_NAME      "i2c1"  2struct rt_i2c_bus_device
  • RT-Thread Studio V1.1 新版本發布
    【官網下載地址】https://www.rt-thread.org/page/studio.html(或點擊文末閱讀原文下載) 本次發布SDK管理器只內置了STM32F1和STM32F4系列晶片支持包,如果使用其它晶片,需要先到SDK管理器安裝相應晶片支持包。
  • i.MX RT1052晶片的核心板,性能和代碼詳細資料概述
    而下面兩個版本,則可以作為產品的最終代碼,將程序下載到NOR FLASH中,但是下載速度較慢,而且運行速度較SDRAM慢,傑傑猜測,我們或許應該可以將程序寫為兩段,在發布產品的時候,從NOR FLASH啟動,運行NOR FLASH的第一段程序,將存在NOR FLASH的第二段程序加載到SDRAM中運行,直到掉電。這樣子就能提高速度了吧。
  • 使用Nordic nRF52840 Dongle跑通mesh的第一個例程
    nRF52840 Dongle最早由Nordic公司在2018年推出,Nordic公司宣稱nRF52840 Dongle是一種小型,低成本的USB Dongle。官方提供了MESH SDK供開發人員使用。
  • RT-Thread I2C總線設備學習筆記
    本節,我們將會學習到RT-Thread I2C總線設備的基本使用。接下來,我們將基於RT-Thread Studio來構建。2、開始實踐上一節我們已經熟悉了怎麼創建工程和配置項目了,這節我們直接略過這兩步操作,直接看硬體圖。2.1 硬體原理圖參考上面文章給出的文章連結。2.2 軟體功能實現
  • (4)RT-Thread 多線程學習總結
    關於多線程的使用和管理,RT-Thread官方提供了比較豐富的文檔作為參考,具體內容可以查看以下連結:https://www.rt-thread.org/document/site/programming-manual/thread/thread/本文是對RT-Thread多線程學習後的總結,並嘗試從如圖所示的以下幾個方面進行總結。
  • RT-Thread 2.1.0 beta 發布,下一方向:物聯網
    ;也第一次包括了ARM Cortex-M7的移植;在微處理器(MPU)上,RT-Thread也越加完善,POSIX接口兼容度進一步提升!而對於使用穩定版本的用戶來說,建議升級到RT-Thread 1.2.5和2.0.2版本去。2015年快要到年底了,今年半導體企業出了很多的事情。做為運行在晶片上的開源嵌入式實時作業系統RT-Thread,希望國內晶片廠家多多發力,RT-Thread會大力支持國內(32位)晶片廠家,讓BSP分支列表裡出現越來越多的國內晶片。
  • RT-Thread傳感器設備驅動框架介紹
    Sensor 驅動框架的作用是:為上層提供統一的操作接口,提高上層代碼的可重用性;簡化底層驅動開發的難度,只要實現簡單的 ops(operations: 操作命令) 就可以將傳感器註冊到系統上。14};15typedef struct rt_sensor_device *rt_sensor_t;Sensor 的信息struct rt_sensor_info info 裡存儲的是一些與 Sensor 自身相關的信息,在 Sensor 設備註冊的時候提供
  • Nordic nRF52820 SoC為nRF52系列低端器件增添全速USB 2.0和藍牙5.2
    nRF52820 SoC提供了先進的多協議支持功能,以及12 Mbps USB和功能齊全的+8 dBm輸出功率無線電,支持所有藍牙 5.2功能、藍牙長距離傳輸和尋向以及耐受高溫,適用於HID、智能家居、商業和工業應用
  • RT-Thread Studio V1.0.2 發布,物聯網作業系統一站式開發工具
    RT-Thread Studio 下載地址:https://www.rt-thread.org/page/studio.htm新版亮點:完美暗黑主題最新版Studio還推出了的完美的暗黑主題了,對於習慣於用暗黑主題的粉絲1.0.2版本簡直就是福音了
  • 第3期:RT-Thread實戰入門學習營,報名了!看看上期學員怎麼說?
    參加本次RTT的學習營剛好把任督二脈打通了,因為之前對內核理論部分還是挺熟悉的但是使用起來就不會了,在這之後可以將學到東西加以實踐,遇到問題時各位老師也能積極的去回復,總體感覺是非常好的,美中不足的是學習營時間有些短,學習的應用有限,看來RTT進階還得靠自己啦,要是RTT在舉辦中級或者高級學習營就更好了。