我們從現(xiàn)在開始會逐步連載RT-Thread Smart(簡稱rt-smart,甚至有時會稱為smart os)的介紹文章,旨在讓大家認識,接觸到smart os的方方面面。
這個是本系列的第一篇文章,一些介紹及樹莓派上rt-smart的應(yīng)用編程入門(更多的從應(yīng)用程序角度入手)。后續(xù)還包括在rt-smart上的不同應(yīng)用程序介紹:
wget & curl移植
busybox移植
sdl圖形類應(yīng)用
dropbear及ssh server應(yīng)用
為什么選擇樹莓派
樹莓派是第一個smart對外提供公開支持的硬件平臺?選擇樹莓派有諸多方面的原因:第一,它可以算是普及度最廣的一款ARM Cortex-A硬件開發(fā)板,被廣泛地應(yīng)用在一些創(chuàng)新應(yīng)用,高校教育等方面。第二,自樹莓派4B發(fā)布以來,芯片核心部分也越來越標(biāo)準(zhǔn)化(相比較之前的樹莓派2、3等,攜帶了標(biāo)準(zhǔn)的GIC中斷控制器,有線以太網(wǎng)網(wǎng)口(vs 樹莓派3的USB轉(zhuǎn)有線以太網(wǎng))),從這個再把rt-smart移植擴展到其他A系列處理器也會是很好的參考,例如后續(xù)ART-Pi版本ART-Pi smart開發(fā)板(ARM Cortex-A7核心,更合適的量產(chǎn)版本)。
樹莓派4B包括了4核的ARM Cortex-A72,1.5GHz的BCM2711芯片,可以執(zhí)行ARM AArch64位指令,也可以執(zhí)行ARM AArch32位指令,具備標(biāo)準(zhǔn)化的通用控制器GIC。和樹莓派3B+的硬件規(guī)格對比情況:
編寫應(yīng)用程序
要在樹莓派上運行smart也很簡單,直接下載smart的發(fā)布版,里面有樹莓派4B上對應(yīng)的移植代碼,及一些用戶態(tài)應(yīng)用程序。
在smart上寫程序,可以有以下幾種方式:傳統(tǒng)的RT-Thread scons構(gòu)建方式;類Linux的方式,這里給出了基于Makefile的方式,及基于CMake的方式。下面通過一個 ? 花式的Hello World程序來進行介紹。
采用scons構(gòu)建的應(yīng)用程序
因為RT-Thread原生是采用scons來進行構(gòu)建的,所以這里也用scons來構(gòu)建一個應(yīng)用程序,它會調(diào)用RT-Thread的一些API來創(chuàng)建一個線程,并輸出“hello world!”。
examples/scons/main.c文件清單
1#include 《rtthread.h》
2
3void thread_entry(void* parameter)
4{
5 rt_kprintf(“hello world
”);
6}
7
8int main(int argc, char** argv)
9{
10 rt_thread_t tid;
11 tid = rt_thread_create(“hello”, thread_entry, RT_NULL,
12 1024, 20, 20);
13 if (tid)
14 {
15 rt_thread_startup(tid);
16 }
17 rt_thread_mdelay(100);
18
19 return 0;
20}
對應(yīng)的編譯腳本,包含兩個,一份是SConscript腳本,另外一份是SContruct腳本
SConstruct文件清單:
1import os
2import sys
3
4# UROOT_DIR指向rt-smart sdk中的userapps文件夾
5UROOT_DIR = os.path.join(‘。.’, ‘。.’)
6
7# 把building.py的目錄添加到系統(tǒng)搜索路徑中
8sys.path = sys.path + [os.path.join(UROOT_DIR, ‘。.’, ‘tools’)]
9from building import *
10
11# 編譯一個應(yīng)用程序
12BuildApplication(‘scons’, ‘SConscript’, usr_root = UROOT_DIR)
SConscript文件清單,和原本的RT-Thread 組件SConscript文件類似:
1from building import *
2
3cwd = GetCurrentDir()
4src = Glob(‘*.c’) + Glob(‘*.cpp’)
5CPPPATH = [cwd]
6
7CPPDEFINES = [‘HAVE_CCONFIG_H’]
8group = DefineGroup(‘scons’, src, depend = [‘’], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
9
10Return(‘group’)
按照RT-Thread傳統(tǒng)的構(gòu)建方式,直接執(zhí)行scons,會生成相應(yīng)的scons.elf可執(zhí)行文件。
1~/workspace/rtthread-smart/userapps/examples/scons$ scons
2scons: Reading SConscript files 。..
3scons: done reading SConscript files.
4scons: Building targets 。..
5scons: building associated VariantDir targets: build/scons
6CC build/scons/main.o
7LINK scons.elf
8scons: done building targets.
采用Makefile構(gòu)建的應(yīng)用程序
除了scons構(gòu)建方式以外,我們也可以使用Makefile方式,以一個C++版本的方式來給出這份例子。
main.cpp文件清單:
1#include 《vector》
2#include 《iostream》
3
4extern “C” {
5
6int main(int argc, char** argv)
7{
8 int index = 0;
9 std::vector《int》 a;
10 for (index = 0; index 《 5; index ++)
11 {
12 a.push_back(index);
13 }
14
15 for (std::vector《int》::iterator it=a.begin(); it != a.end(); it++)
16 std::cout 《《 “hello world, index = ” 《《 *it 《《 std::endl;
17 return 0;
18}
19
20}
而Makefile的編寫可以按照這樣的方式編寫:
1# 設(shè)置交叉工具鏈
2CROSS_COMPILE= arm-linux-musleabi-
3CC= $(CROSS_COMPILE)gcc
4CXX= $(CROSS_COMPILE)g++
5
6# 獲得當(dāng)前目錄
7PWD := $(shell pwd)
8
9# UROOT_DIR指向rt-smart sdk中的userapps文件夾
10UROOT_DIR := $(PWD)/。./。.
11RT_DIR=$(UROOT_DIR)/sdk/rt-thread
12INC_DIR=$(UROOT_DIR)/sdk/include
13LIB_DIR=${UROOT_DIR}/sdk/lib
14
15# 編譯及鏈接時參數(shù)
16CFLAGS= -march=armv7-a -marm -msoft-float -D__RTTHREAD__ -Wall -O0 -g -gdwarf-2 -n --static
17CFLAGS+= -I. -I$(RT_DIR)/include -I$(RT_DIR)/components/dfs -I$(RT_DIR)/components/drivers -I$(RT_DIR)/components/finsh -I$(RT_DIR)/components/net -I${INC_DIR}
18
19LDFLAGS= -march=armv7-a -marm -msoft-float -T ${UROOT_DIR}/linker_scripts/arm/cortex-a/link.lds
20LDFLAGS+= -L$(RT_DIR)/lib -L$(LIB_DIR) -Wl,--whole-archive -lrtthread -Wl,--no-whole-archive -n --static -Wl,--start-group -lrtthread -Wl,--end-group
21
22default:
23 $(CXX) $(CFLAGS) -c main.cpp -o main.o
24 $(CXX) $(LDFLAGS) main.o -o main.elf
25
26clean:
27 @rm *.o *.elf
28
29.PHONY: default clean
在目錄下執(zhí)行make即可生成makefile.elf可執(zhí)行文件。
采用CMake構(gòu)建的應(yīng)用程序
針對CMake的版本,我們以pthreads的方式來編寫這個pthread多線程版本的hello world:在一個POSIX thread線程中輸出”hello world”。
POSIX thread版本的main.c代碼清單
1#include 《stdio.h》
2#include 《pthread.h》
3
4void *pthread_entry(void* parameter)
5{
6 printf(“hello world
”);
7 return NULL;
8}
9
10int main(int argc, char** argv)
11{
12 int ret;
13 void *value;
14 pthread_t pth;
15
16 /* 創(chuàng)建pthread線程來執(zhí)行后續(xù)的hello輸出 */
17 ret = pthread_create(&pth, NULL, pthread_entry, NULL);
18 printf(“ret = %d
”, ret);
19
20 /* 等待結(jié)束 */
21 pthread_join(pth, &value);
22
23 return 0;
24}
對應(yīng)的CMakeLists.txt文件清單
1cmake_minimum_required(VERSION 3.5)
2
3project(cmake)
4
5## system configuration
6enable_language(C ASM)
7
8set(CMAKE_SYSTEM_NAME Generic)
9set(CMAKE_SYSTEM_PROCESSOR arm)
10
11if(NOT DEFINED ENV{RTT_EXEC_PATH})
12 message(FATAL_ERROR “not defined environment variable: RTT_EXEC_PATH”)
13 message(FATAL_ERROR “Please execute the command: $ source smart_env.sh”)
14endif()
15
16set(CONFIG_PREFIX “$ENV{RTT_EXEC_PATH}/arm-linux-musleabi-”)
17# UROOT_DIR指向rt-smart sdk中的userapps文件夾
18set(UROOT_DIR “${PROJECT_SOURCE_DIR}/。./。.”)
19
20set(CMAKE_C_COMPILER “${CONFIG_PREFIX}gcc”)
21set(CMAKE_CXX_COMPILER “${CONFIG_PREFIX}g++”)
22set(CMAKE_ASM_COMPILER “${CONFIG_PREFIX}gcc”)
23set(CMAKE_OBJCOPY “${CONFIG_PREFIX}objcopy”)
24set(CMAKE_C_AR “${CONFIG_PREFIX}ar”)
25set(CMAKE_SIZE “${CONFIG_PREFIX}size”)
26
27set(SDK_DIR “${UROOT_DIR}/sdk”)
28set(LINK_SCRIPTS_DIR “${UROOT_DIR}/linker_scripts/arm/cortex-a”)
29
30set(CMAKE_C_FLAGS “${CMAKE_C_FLAGS} -march=armv7-a -marm -msoft-float -Werror -Wall -O0 -g -gdwarf-2 -n --static”)
31set(CMAKE_ASM_FLAGS “${CMAKE_ASM_FLAGS} -march=armv7-a -marm -msoft-float -x assembler-with-cpp -O0 -g”)
32set(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} -march=armv7-a -marm -msoft-float -Werror -Wall -Woverloaded-virtual -fno-exceptions -fno-rtti -O0 -g -gdwarf-2 -n --static”)
33
34set(SDK_INC
35 “${UROOT_DIR}/include”
36 “${UROOT_DIR}/rt-thread/include”
37 “${UROOT_DIR}/rt-thread/components/dfs”
38 “${UROOT_DIR}/rt-thread/components/drivers”
39 “${UROOT_DIR}/rt-thread/components/finsh”
40 “${UROOT_DIR}/rt-thread/components/net”
41)
42
43# 設(shè)置鏈接腳本位置
44set(CMAKE_EXE_LINKER_FLAGS “-T ${LINK_SCRIPTS_DIR}/link.lds -static”)
45
46## user configuration
47set(APPS_INC
48 “${PROJECT_SOURCE_DIR}”
49 “${SDK_INC}”
50)
51
52set(APPS_SRC
53 “${PROJECT_SOURCE_DIR}/main.c”
54)
55
56set(CMAKE_EXECUTABLE_SUFFIX “.elf”)
57
58add_executable(${PROJECT_NAME} ${SDK_SRC} ${APPS_SRC})
59target_include_directories(${PROJECT_NAME} PRIVATE ${APPS_INC})
可以在這個目錄下創(chuàng)建一個build文件夾,然后通過cmake
1~/workspace/rtthread-smart/userapps/examples/cmake/build$ cmake 。.
2-- The C compiler identification is GNU 7.5.0
3-- The CXX compiler identification is GNU 7.5.0
4-- Check for working C compiler: /usr/bin/cc
5-- Check for working C compiler: /usr/bin/cc -- works
6-- Detecting C compiler ABI info
7-- Detecting C compiler ABI info - done
8-- Detecting C compile features
9-- Detecting C compile features - done
10-- Check for working CXX compiler: /usr/bin/c++
11-- Check for working CXX compiler: /usr/bin/c++ -- works
12-- Detecting CXX compiler ABI info
13-- Detecting CXX compiler ABI info - done
14-- Detecting CXX compile features
15-- Detecting CXX compile features - done
16-- The ASM compiler identification is GNU
17-- Found assembler: /usr/bin/cc
18-- Configuring done
19-- Generating done
20-- Build files have been written to: ~/workspace/rtthread-smart/userapps/examples/cmake/build
來生成Makefile文件,然后通過make進行編譯。
1~/workspace/rtthread-smart/userapps/examples/cmake/build$ make
2[ 50%] Building C object CMakeFiles/cmake.dir/main.c.o
3[100%] Linking C executable cmake.elf
4[100%] Built target cmake
運行應(yīng)用程序
在使用的時候,需要把上面編譯好的三個應(yīng)用程序放置到樹莓派用的SD卡上。我們可以使用讀卡器在PC上把應(yīng)用程序復(fù)制到SD卡上。然后再插回到樹莓派板子上,重新上電。這個時候我們可以在串口上看到RT-Thread Smart的啟動界面:
1 | /
2- RT - Thread Smart Operating System
3 / | 5.0.0 build May 4 2021
4 2006 - 2020 Copyright by rt-thread team
5lwIP-2.1.2 initialized!
6[I/sal.skt] Socket Abstraction Layer initialize success.
7file system initialization done!
8msh /》 cd bin
9msh /bin》 scons.elf
10msh /bin》 hello world!
執(zhí)行程序,可以輸出hello world!
通過上面三個例子,我們看到了在smart上目前支持的數(shù)種技術(shù):1、在用戶態(tài)以RT-Thread傳統(tǒng)API方式運行:RT-Thread的多線程,基于優(yōu)先級全搶占的調(diào)度都可以被使用,具備平滑的延續(xù)性;2、可以支持C++編寫應(yīng)用程序,同時也可以使用stdc++庫;3、可以支持pthreads,以POSIX thread線程的模式執(zhí)行,它們會被映射到RT-Thread的多線程上執(zhí)行。
原文標(biāo)題:當(dāng)“樹莓派”遇上RT-Thread Smart——應(yīng)用編程入門
文章出處:【微信公眾號:RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
責(zé)任編輯:haq
-
樹莓派
+關(guān)注
關(guān)注
116文章
1688瀏覽量
105456 -
RTThread
+關(guān)注
關(guān)注
7文章
132瀏覽量
40776
原文標(biāo)題:當(dāng)“樹莓派”遇上RT-Thread Smart——應(yīng)用編程入門
文章出處:【微信號:RTThread,微信公眾號:RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論