RM新时代网站-首页

電子發(fā)燒友App

硬聲App

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

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

3天內(nèi)不再提示
創(chuàng)作
電子發(fā)燒友網(wǎng)>電子資料下載>電子資料>帶有RT-Thread的Arduino應(yīng)用程序

帶有RT-Thread的Arduino應(yīng)用程序

2023-06-14 | zip | 0.00 MB | 次下載 | 2積分

資料介紹

描述

介紹

本文中的“app”是指預(yù)編譯的二進(jìn)制文件,無需使用 Arduino IDE,即可直接在 Arduino 板卡上運(yùn)行。

并且因?yàn)樗且粋€(gè)文件,“應(yīng)用程序”可以通過 SD 卡、以太網(wǎng)、WiFi 或任何合適的方法分發(fā)。

標(biāo)題圖顯示了執(zhí)行 Arduino 應(yīng)用程序RTT-QRCode的 MKR ZERO 板。

你有興趣嗎?

(本文基于Arduino RT-Thread庫v0.6.0。)

動(dòng)態(tài)模塊

在 RT-Thread 架構(gòu)中,“app”被稱為動(dòng)態(tài)模塊,構(gòu)建為動(dòng)態(tài)共享庫,擴(kuò)展名為“ .mo”或“ .so”。(什么是 RT-Thread?=> Arduino 上的多任務(wù)處理

RT-Thread 提供 API 來訪問動(dòng)態(tài)模塊。更有趣的是,MSH(一個(gè)微型外殼)能夠.mo直接執(zhí)行“”文件(詳細(xì)信息在以下部分中)。

RT-Thread 的原始動(dòng)態(tài)鏈接器似乎不適用于 ARM Cortex-M。所以我修改了 Arduino RT-Thread 庫的代碼。

多發(fā)性硬化癥

Module SHell (MSH) 是默認(rèn)啟用的一項(xiàng)新功能(從 v0.5.1 開始),它構(gòu)建在 FinSH 之上。(什么是 FinSH?=> Arduino 上的多任務(wù)處理

由于 Arduino 應(yīng)用程序是由 MSH 執(zhí)行的,讓我們簡單介紹一下。

相比 FinSH,MSH 更符合 Unix shell 的使用習(xí)慣:

  • 在 FinSH 中發(fā)出命令
led(0, 1)
copy("datalog.txt", "copy.txt")
  • 在 MSH 中發(fā)出命令
led 0 1
cp datalog.txt copy.txt

但是,MSH 不支持像 FinSH 提供的那樣的 shell 變量。

另一個(gè)限制是用戶定義的 MSH 命令的原型是固定的:

int my_msh_cmd(int argc, char **argv)

MSH 執(zhí)行用戶命令時(shí),參數(shù)argc參數(shù)個(gè)數(shù)加一,參數(shù)列表argv參數(shù)列表(firstentryiscommandname)您可能已經(jīng)猜到了,所有參數(shù)只能是char數(shù)組類型。

以下是 MSH 命令格式的“l(fā)ed”示例

int led(int argc, char **argv) {
  // argc - the number of arguments
  // argv[0] - command name, e.g. "led"
  // argv[n] - nth argument in the type of char array
  
  rt_uint32_t id;
  rt_uint32_t state;
  
  if (argc != 3) {
    rt_kprintf("Usage: led \n");
    return 1;
  }
  rt_kprintf("led%s=%s\n", argv[1], argv[2]);
  
  // convert arguments to their specific types
  sscanf(argv[1], "%u", &id);
  sscanf(argv[2], "%u", &state);
  if (id != 0) {
    rt_kprintf("Error: Invalid led ID\n");
    return 1;
  }
  
  if (state) {
    digitalWrite(LED_BUILTIN, HIGH);
  } else {
    digitalWrite(LED_BUILTIN, LOW);
  }
  
  return 0;
}

制作 Arduino 應(yīng)用程序

首先,CONFIG_USING_MODULE在“rtconfig.h”中啟用,因?yàn)槟J(rèn)情況下它是禁用的。

構(gòu)建可執(zhí)行文件

讓我們在 Arduino IDE 中打開“HelloMo”示例,然后按“驗(yàn)證”。(該示例也可以在下面的“代碼”部分中找到。)代碼現(xiàn)在被構(gòu)建到一個(gè)包含草圖和庫的單個(gè)可執(zhí)行文件中。我們可以使用 GCC 工具readelf(Arduino IDE 提供)來驗(yàn)證。

{path_to_gcc_tools}\arm-none-eabi-readelf -h {path_to_output}\HelloMo.ino.elf
ELF Header:
 Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
 Class:                             ELF32
 Data:                              2's complement, little endian
 Version:                           1 (current)
 OS/ABI:                            UNIX - System V
 ABI Version:                       0
 Type:                              EXEC (Executable file)
 Machine:                           ARM
 Version:                           0x1
 Entry point address:               0xf7fd
 Start of program headers:          52 (bytes into file)
 Start of section headers:          798052 (bytes into file)
 Flags:                             0x5000002, has entry point, Version5 EABI
 Size of this header:               52 (bytes)
 Size of program headers:           32 (bytes)
 Number of program headers:         2
 Size of section headers:           40 (bytes)
 Number of section headers:         18
 Section header string table index: 15

如果您不確定 GCC 工具和編譯輸出的位置,請?jiān)?File-> Preferences 中啟用以下選項(xiàng)。

?
poYBAGNY2faAK9olAACKIlpfdZI459.png
Arduino IDE 首選項(xiàng)
?

再次單擊“驗(yàn)證”,您將在輸出窗口中觀察到信息:

...
Compiling sketch...
"C:\\Users\\onelife\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\arm-none-eabi-gcc\\4.8.3-2014q1/bin/arm-none-eabi-gcc" -mcpu=cortex-m0plus -mthumb -c -g -Os -Wall -Wextra -std=gnu11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -MMD -DF_CPU=48000000L -DARDUINO=10809 -DARDUINO_SAMD_MKRZERO -DARDUINO_ARCH_SAMD -DUSE_ARDUINO_MKR_PIN_LAYOUT -D__SAMD21G18A__ -DUSB_VID=0x2341 -DUSB_PID=0x804f -DUSBCON "-DUSB_MANUFACTURER="Arduino LLC"" "-DUSB_PRODUCT="Arduino MKRZero"" "-IC:\\Users\\onelife\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\CMSIS\\4.5.0/CMSIS/Include/" "-IC:\\Users\\onelife\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\CMSIS-Atmel\\1.1.0/CMSIS/Device/ATMEL/" "-IC:\\Users\\onelife\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\samd\\1.6.21\\cores\\arduino" "-IC:\\Users\\onelife\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\samd\\1.6.21\\variants\\mkrzero" "-IC:\\Users\\onelife\\Documents\\Arduino\\libraries\\RT-Thread\\src" "-IC:\\Users\\onelife\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\samd\\1.6.21\\libraries\\SPI" "C:\\Users\\onelife\\AppData\\Local\\Temp\\arduino_build_508434\\sketch\\hello_mo.c" -o "C:\\Users\\onelife\\AppData\\Local\\Temp\\arduino_build_508434\\sketch\\hello_mo.c.o"
...

就我而言,GCC 工具位于“ C:\\Users\\onelife\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\arm-none-eabi-gcc\\4.8.3-2014q1/bin/”,編譯輸出位于“ C:\\Users\\onelife\\AppData\\Local\\Temp\\arduino_build_508434\\”。

構(gòu)建應(yīng)用程序(動(dòng)態(tài)共享庫)

但是,我們要構(gòu)建的目標(biāo)“應(yīng)用程序”是一種共享庫。它必須與位置無關(guān),因此可以加載到任何 RAM 地址中。為了讓它更?。ㄒ?yàn)槲覀兊?RAM 大小是有限的),最終的二進(jìn)制文件將不包含其他庫的任何功能。(所有外部功能都應(yīng)由固件端提供。)

壞消息是 Arduino IDE 不提供這些選項(xiàng)。好消息是 Arduino IDE 確實(shí)提供了我們需要的所有工具。我們開始做吧。

第一步是編譯。

我們必須將選項(xiàng)“ -mlong-calls -fPIC”添加到原始編譯命令中(在輸出窗口中查找“正在編譯草圖...”)。

{path_to_gcc_tools}\arm-none-eabi-gcc -mlong-calls -fPIC ... {path_to_output}\sketch\hello_mo.c -o {path_to_output}\sketch\hello_mo.c.o
  
{path_to_gcc_tools}\arm-none-eabi-gcc -mlong-calls -fPIC ... {path_to_output}\sketch\load_mo.c -o {path_to_output}\sketch\load_mo.c.o

第二步是鏈接。

在這一步中,我們選擇將目標(biāo)文件構(gòu)建為“ app ”(帶有入口點(diǎn)的“.mo”文件)或?qū)⑵錁?gòu)建為(不帶入口點(diǎn)的“.so”文件)。在以下示例中,我們將“ load_mo.c.o”構(gòu)建為“app”,并將“ hello_mo.c.o”構(gòu)建為庫。

我們通過以下方式修改鏈接命令(尋找“將所有內(nèi)容鏈接在一起......”)

  • 只保留目標(biāo)目標(biāo)文件,例如“ load_mo.c.o”,并刪除其他
  • 刪除選項(xiàng)“ -Wl,--unresolved-symbols=report-all
  • 刪除選項(xiàng)“ -L{path_to_output}
  • 刪除選項(xiàng)“ -T.../flash_with_bootloader.ld
  • 刪除選項(xiàng)“ -Wl,--start-group ... -Wl,--end-group
  • 添加選項(xiàng)“ -shared -fPIC -nostdlib -Wl,-marmelf -Wl,-z,max-page-size=0x4
  • 添加入口點(diǎn)選項(xiàng)(例如“ -Wl,-eload_hello”或“ -Wl,-e0”表示無)
{path_to_gcc_tools}\arm-none-eabi-g++ -shared -fPIC -nostdlib -Wl,-e0 -Wl,-marmelf -Wl,-z,max-page-size=0x4 ... -o {path_to_output}\hello_mo.elf {path_to_output}\hello_mo.c.o
  
{path_to_gcc_tools}\arm-none-eabi-g++ -shared -fPIC -nostdlib -Wl,-eload_hello -Wl,-marmelf -Wl,-z,max-page-size=0x4 ... -o {path_to_output}\load_mo.elf {path_to_output}\load_mo.c.o

第三步是分條。

為了進(jìn)一步減小文件大小,我們必須去掉 ELF 文件中不必要的部分。

{path_to_gcc_tools}\arm-none-eabi-strip -R .hash -R .comment -R .ARM.attributes {path_to_output}\hello_mo.elf -o {path_to_output}\hello.so
  
{path_to_gcc_tools}\arm-none-eabi-strip -R .hash -R .comment -R .ARM.attributes {path_to_output}\load_mo.elf -o {path_to_output}\load.mo

第四步是檢查大小(可選)。

{path_to_gcc_tools}\arm-none-eabi-size {path_to_output}\hello.so
  
{path_to_gcc_tools}\arm-none-eabi-size {path_to_output}\load.mo

恭喜!您剛剛構(gòu)建了一個(gè) Arduino 應(yīng)用程序。讓我們檢查一下輸出。

{path_to_gcc_tools}\arm-none-eabi-readelf -h {path_to_output}\hello.so
ELF Header:
 Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
 Class:                             ELF32
 Data:                              2's complement, little endian
 Version:                           1 (current)
 OS/ABI:                            UNIX - System V
 ABI Version:                       0
 Type:                              DYN (Shared object file)
 Machine:                           ARM
 Version:                           0x1
 Entry point address:               0x0
 Start of program headers:          52 (bytes into file)
 Start of section headers:          896 (bytes into file)
 Flags:                             0x5000000, Version5 EABI
 Size of this header:               52 (bytes)
 Size of program headers:           32 (bytes)
 Number of program headers:         3
 Size of section headers:           40 (bytes)
 Number of section headers:         9
 Section header string table index: 8
  
{path_to_gcc_tools}\arm-none-eabi-readelf -h {path_to_output}\load.mo
ELF Header:
 Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
 Class:                             ELF32
 Data:                              2's complement, little endian
 Version:                           1 (current)
 OS/ABI:                            UNIX - System V
 ABI Version:                       0
 Type:                              DYN (Shared object file)
 Machine:                           ARM
 Version:                           0x1
 Entry point address:               0x285
 Start of program headers:          52 (bytes into file)
 Start of section headers:          1060 (bytes into file)
 Flags:                             0x5000002, has entry point, Version5 EABI
 Size of this header:               52 (bytes)
 Size of program headers:           32 (bytes)
 Number of program headers:         3
 Size of section headers:           40 (bytes)
 Number of section headers:         9
 Section header string table index: 8

它表明“ .so”和“ .mo”文件都是“ DYN”(動(dòng)態(tài))類型。不同之處在于“ .so”文件沒有入口點(diǎn),而“ .mo”文件有。

我們還沒有完成。

最后一步是公開應(yīng)用程序所需的功能。

在文件“ ”中,如果啟用mo_sym.h,所有內(nèi)核 API 都已經(jīng)公開。CONFIG_USING_MODULE如有必要,您可以添加自己的。

發(fā)出 MSH 命令“ lsym”將列出所有暴露的符號:

?
poYBAGNY2fmASgxKAAC6FCxVH6M181.png
內(nèi)核符號
?

運(yùn)行 Arduino 應(yīng)用程序

hello.so讓我們將“ ”和“ ”復(fù)制load.mo到具有以下文件結(jié)構(gòu)的SD卡。

SD_ROOT/
├── lib/
│   └── hello.so
└── mo/
    └── load.mo

規(guī)則是,如果我們將相對路徑傳遞給dlopen()或 MSH,它將分別和中查找“ .so”和“ ” 。.mo/lib//mo/

現(xiàn)在我們將卡插入 Arduino 板,在本例中為 MRKZERO ,上傳“HelloMo”草圖(草圖什么都不做),然后發(fā)出命令“ load”。

?
pYYBAGNY2fuAZCtGAACmKSD6HF4575.png
加載(帶有調(diào)試消息)
?

為了顯示有關(guān)應(yīng)用程序執(zhí)行過程的更多詳細(xì)信息,我們可以在“ dlmodule.c”中啟用調(diào)試消息:

#define LOG_LVL LOG_LVL_DBG

結(jié)果揭示了以下過程:

  • MSH 線程 ("tshell") 將 " load.mo" 加載到 RAM 并創(chuàng)建一個(gè)新線程 ("load") 以執(zhí)行入口點(diǎn)函數(shù) " load_hello()"
  • load_hello()”然后加載“ hello.so”,調(diào)用它的“ module_init()”函數(shù),調(diào)用它的“ say_hello()”函數(shù)(不是入口點(diǎn))
  • 在 " say_hello()" 返回后, " load_hello()" 關(guān)閉 " hello.so" (調(diào)用它的 " module_cleanup()" 函數(shù)然后銷毀它的 RAM 副本)
  • “加載”線程標(biāo)記以銷毀“”的RAM副本,load.mo然后退出
  • " " 的 RAM 副本load.mo最終被空閑線程 ("tidle0") 銷毀

" module_init()" 和 " module_cleanup()" 是特殊函數(shù)。如果定義,前者.mo在將應(yīng)用程序加載到 RAM 后由 MSH 線程(在“”文件的情況下)調(diào)用,后者.mo在銷毀 RAM 副本之前由空閑線程(在“”文件的情況下)調(diào)用。

讓我們將“hello_mo.c”重建為一個(gè)應(yīng)用程序(入口點(diǎn)是“ say_hello()”,例如-Wl,-esay_hello)并執(zhí)行。

?
poYBAGNY2f6AAlahAACEdZbAZoU581.png
你好,有調(diào)試信息
?

結(jié)果清楚地表明“ module_init()”被MSH線程(“tshell”)module_cleanup()調(diào)用,“ ”被空閑線程(“tidle0”)調(diào)用。順便說一句,傳遞給這兩個(gè)函數(shù)的參數(shù)是指向模塊描述符的指針。

優(yōu)點(diǎn)缺點(diǎn)

優(yōu)點(diǎn)

(我們感興趣的是)Arduino 應(yīng)用程序可以構(gòu)建一次并在許多板上運(yùn)行。根據(jù) Wiki ,“可用于 Cortex-M0 / Cortex-M0+ / Cortex-M1 的二進(jìn)制指令無需修改即可在 Cortex-M3 / Cortex-M4 / Cortex-M7 上執(zhí)行。可用于 Cortex-M3 的二進(jìn)制指令無需修改即可執(zhí)行在 Cortex-M4 / Cortex-M7 / Cortex-M33 / Cortex-M35P 上進(jìn)行修改。

因此,為 MKR Zero 板(SAMD 架構(gòu))構(gòu)建的應(yīng)用程序應(yīng)該在 Arduino Due(SAM 架構(gòu))上運(yùn)行而不會(huì)出現(xiàn)問題。

此功能可以實(shí)現(xiàn)遠(yuǎn)程添加或更新功能而無需重新啟動(dòng)(與 OTA 固件更新相比)等。

缺點(diǎn)

與 MSH 命令相比,Arduino 應(yīng)用程序需要更多 RAM。另一個(gè)主要缺點(diǎn)是在固件方面,應(yīng)用程序所需的所有外部功能都必須在那里待機(jī)(盡管固件可能不會(huì)使用它們)并暴露(在“ mo_sym.h”中)。

動(dòng)態(tài)模塊狀態(tài)

Arduino RT-Thread 庫 v0.6.0 中的功能仍處于 beta 階段。

在原始代碼(RT-Thread 項(xiàng)目)中,除了DYNELF 文件的類型,動(dòng)態(tài)鏈接器還支持REL類型。但是,經(jīng)過一些測試,我發(fā)現(xiàn)至少對于 ARM Cortex-M 架構(gòu),只有“ .o”(對象)文件類型為REL. 所以目前RELArduino RT-Thread 庫不支持 ELF 文件類型。

此外,僅測試了兩種重新分配類型:

  • R_ARM_JUMP_SLOT
  • R_ARM_RELATIVE

我需要一些代碼來測試其他類型。因此,如果您遇到其他類型的錯(cuò)誤,請幫助提出問題。

最后,并非所有“l(fā)ibgcc”函數(shù)都默認(rèn)公開。例如,開關(guān)助手功能沒有公開。您可以將它們添加到“ mo_sym.h”或在您的應(yīng)用程序中將“ switch...case...”替換為“ ” 。if...else...

RTT-QRCode 應(yīng)用程序

有一個(gè)更復(fù)雜的示例RTT-QRCode ,可以構(gòu)建為 MSH 命令或 Arduino 應(yīng)用程序。請查看代碼并玩得開心!

?
pYYBAGNY2gCAQIJpAACkN-uwl7Q563.png
RTT-二維碼
?

下一步

下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評論

查看更多

下載排行

本周

  1. 1山景DSP芯片AP8248A2數(shù)據(jù)手冊
  2. 1.06 MB  |  532次下載  |  免費(fèi)
  3. 2RK3399完整板原理圖(支持平板,盒子VR)
  4. 3.28 MB  |  339次下載  |  免費(fèi)
  5. 3TC358743XBG評估板參考手冊
  6. 1.36 MB  |  330次下載  |  免費(fèi)
  7. 4DFM軟件使用教程
  8. 0.84 MB  |  295次下載  |  免費(fèi)
  9. 5元宇宙深度解析—未來的未來-風(fēng)口還是泡沫
  10. 6.40 MB  |  227次下載  |  免費(fèi)
  11. 6迪文DGUS開發(fā)指南
  12. 31.67 MB  |  194次下載  |  免費(fèi)
  13. 7元宇宙底層硬件系列報(bào)告
  14. 13.42 MB  |  182次下載  |  免費(fèi)
  15. 8FP5207XR-G1中文應(yīng)用手冊
  16. 1.09 MB  |  178次下載  |  免費(fèi)

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費(fèi)
  3. 2555集成電路應(yīng)用800例(新編版)
  4. 0.00 MB  |  33566次下載  |  免費(fèi)
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費(fèi)
  7. 4開關(guān)電源設(shè)計(jì)實(shí)例指南
  8. 未知  |  21549次下載  |  免費(fèi)
  9. 5電氣工程師手冊免費(fèi)下載(新編第二版pdf電子書)
  10. 0.00 MB  |  15349次下載  |  免費(fèi)
  11. 6數(shù)字電路基礎(chǔ)pdf(下載)
  12. 未知  |  13750次下載  |  免費(fèi)
  13. 7電子制作實(shí)例集錦 下載
  14. 未知  |  8113次下載  |  免費(fèi)
  15. 8《LED驅(qū)動(dòng)電路設(shè)計(jì)》 溫德爾著
  16. 0.00 MB  |  6656次下載  |  免費(fèi)

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費(fèi)
  3. 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
  4. 78.1 MB  |  537798次下載  |  免費(fèi)
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420027次下載  |  免費(fèi)
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費(fèi)
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費(fèi)
  11. 6電路仿真軟件multisim 10.0免費(fèi)下載
  12. 340992  |  191187次下載  |  免費(fèi)
  13. 7十天學(xué)會(huì)AVR單片機(jī)與C語言視頻教程 下載
  14. 158M  |  183279次下載  |  免費(fèi)
  15. 8proe5.0野火版下載(中文版免費(fèi)下載)
  16. 未知  |  138040次下載  |  免費(fèi)
RM新时代网站-首页