飞道的博客

当“树莓派”遇上RT-Thread Smart——应用编程入门

533人阅读  评论(0)

我们从现在开始会逐步连载RT-Thread Smart(简称rt-smart,甚至有时会称为smart os)的介绍文章,旨在让大家认识,接触到smart os的方方面面。

这个是本系列的第一篇文章,一些介绍及树莓派上rt-smart的应用编程入门(更多的从应用程序角度入手)。后续还包括在rt-smart上的不同应用程序介绍:

  • wget & curl移植

  • busybox移植

  • sdl图形类应用

  • dropbear及ssh server应用

为什么选择树莓派

树莓派是第一个smart对外提供公开支持的硬件平台?选择树莓派有诸多方面的原因:第一,它可以算是普及度最广的一款ARM Cortex-A硬件开发板,被广泛地应用在一些创新应用,高校教育等方面。第二,自树莓派4B发布以来,芯片核心部分也越来越标准化(相比较之前的树莓派2、3等,携带了标准的GIC中断控制器,有线以太网网口(vs 树莓派3的USB转有线以太网)),从这个再把rt-smart移植扩展到其他A系列处理器也会是很好的参考,例如后续ART-Pi版本ART-Pi smart开发板(ARM Cortex-A7核心,更合适的量产版本)。                

树莓派4B包括了4核的ARM Cortex-A72,1.5GHz的BCM2711芯片,可以执行ARM AArch64位指令,也可以执行ARM AArch32位指令,具备标准化的通用控制器GIC。和树莓派3B+的硬件规格对比情况:   

编写应用程序

要在树莓派上运行smart也很简单,直接下载smart的发布版,里面有树莓派4B上对应的移植代码,及一些用户态应用程序。

在smart上写程序,可以有以下几种方式:传统的RT-Thread scons构建方式;类Linux的方式,这里给出了基于Makefile的方式,及基于CMake的方式。下面通过一个 ❀ 花式的Hello World程序来进行介绍。

采用scons构建的应用程序

因为RT-Thread原生是采用scons来进行构建的,所以这里也用scons来构建一个应用程序,它会调用RT-Thread的一些API来创建一个线程,并输出"hello world!"。

examples/scons/main.c文件清单


   
  1. 1#include <rtthread.h>
  2. 2
  3. 3void thread_entry(void* parameter)
  4. 4{
  5. 5    rt_kprintf( "hello world\n");
  6. 6}
  7. 7
  8. 8int main( int argc, char** argv)
  9. 9{
  10. 10    rt_thread_t tid;
  11. 11    tid = rt_thread_create( "hello", thread_entry, RT_NULL, 
  12. 12         10242020);
  13. 13     if (tid)
  14. 14    {
  15. 15        rt_thread_startup(tid);
  16. 16    }
  17. 17    rt_thread_mdelay( 100);
  18. 18
  19. 19     return  0;
  20. 20}

对应的编译脚本,包含两个,一份是SConscript脚本,另外一份是SContruct脚本

SConstruct文件清单:


   
  1. 1import os
  2. 2import sys
  3. 3
  4. 4# UROOT_DIR指向rt-smart sdk中的userapps文件夹
  5. 5UROOT_DIR = os.path.join( '..''..')
  6. 6
  7. 7# 把building.py的目录添加到系统搜索路径中
  8. 8sys.path = sys.path + [os.path.join(UROOT_DIR,  '..''tools')]
  9. 9from building  import *
  10. 10
  11. 11# 编译一个应用程序
  12. 12BuildApplication( 'scons''SConscript', usr_root = UROOT_DIR)

SConscript文件清单,和原本的RT-Thread 组件SConscript文件类似:


   
  1. 1from building  import *
  2. 2
  3. 3cwd = GetCurrentDir()
  4. 4src = Glob( '*.c') + Glob( '*.cpp')
  5. 5CPPPATH = [cwd]
  6. 6
  7. 7CPPDEFINES = [ 'HAVE_CCONFIG_H']
  8. 8group = DefineGroup( 'scons', src, depend = [ ''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
  9. 9
  10. 10Return( 'group')

按照RT-Thread传统的构建方式,直接执行scons,会生成相应的scons.elf可执行文件。


   
  1. 1~/workspace/rtthread-smart/userapps/examples/scons$ scons 
  2. 2scons: Reading SConscript files ...
  3. 3scons: done reading SConscript files.
  4. 4scons: Building targets ...
  5. 5scons: building associated VariantDir targets: build/scons
  6. 6CC build/scons/main.o
  7. 7LINK scons.elf
  8. 8scons: done building targets.

采用Makefile构建的应用程序

除了scons构建方式以外,我们也可以使用Makefile方式,以一个C++版本的方式来给出这份例子。

main.cpp文件清单:


   
  1. 1#include <vector>
  2. 2#include <iostream>
  3. 3
  4. 4extern  "C" {
  5. 5
  6. 6int main( int argc, char** argv)
  7. 7{
  8. 8     int index =  0;
  9. 9    std::vector< int> a;
  10. 10     for (index =  0; index <  5; index ++)
  11. 11    {
  12. 12        a.push_back(index);
  13. 13    }
  14. 14
  15. 15     for (std::vector< int>::iterator it=a.begin(); it != a.end(); it++)
  16. 16        std::cout <<  "hello world, index = " << *it << std::endl;
  17. 17     return  0;
  18. 18}
  19. 19
  20. 20}

而Makefile的编写可以按照这样的方式编写:


   
  1. 1# 设置交叉工具链
  2. 2CROSS_COMPILE= arm-linux-musleabi-
  3. 3CC= $(CROSS_COMPILE)gcc
  4. 4CXX= $(CROSS_COMPILE)g++
  5. 5
  6. 6# 获得当前目录
  7. 7PWD := $(shell pwd)
  8. 8
  9. 9#  UROOT_DIR指向rt-smart sdk中的userapps文件夹
  10. 10UROOT_DIR := $(PWD)/../..
  11. 11RT_DIR=$(UROOT_DIR)/sdk/rt-thread
  12. 12INC_DIR=$(UROOT_DIR)/sdk/include
  13. 13LIB_DIR=${UROOT_DIR}/sdk/lib
  14. 14
  15. 15# 编译及链接时参数
  16. 16CFLAGS= -march=armv7-a -marm -msoft-float -D__RTTHREAD__  -Wall -O0 -g -gdwarf -2 -n --static
  17. 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. 18
  19. 19LDFLAGS= -march=armv7-a -marm -msoft-float -T ${UROOT_DIR}/linker_scripts/arm/cortex-a/link.lds
  20. 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. 21
  22. 22 default:
  23. 23    $(CXX) $(CFLAGS) -c main.cpp -o main.o
  24. 24    $(CXX) $(LDFLAGS) main.o -o main.elf
  25. 25
  26. 26clean:
  27. 27    @rm *.o *.elf
  28. 28
  29. 29.PHONY:  default clean

在目录下执行make即可生成makefile.elf可执行文件。

采用CMake构建的应用程序

针对CMake的版本,我们以pthreads的方式来编写这个pthread多线程版本的hello world:在一个POSIX thread线程中输出”hello world”。

POSIX thread版本的main.c代码清单


   
  1. 1#include <stdio.h>
  2. 2#include <pthread.h>
  3. 3
  4. 4void *pthread_entry(void* parameter)
  5. 5{
  6. 6    printf( "hello world\n");
  7. 7     return NULL;
  8. 8}
  9. 9
  10. 10int main( int argc, char** argv)
  11. 11{
  12. 12     int ret;
  13. 13    void *value;
  14. 14    pthread_t pth;
  15. 15
  16. 16     /* 创建pthread线程来执行后续的hello输出 */
  17. 17    ret = pthread_create(&pth, NULL, pthread_entry, NULL);
  18. 18    printf( "ret = %d\n", ret);
  19. 19
  20. 20     /* 等待结束 */
  21. 21    pthread_join(pth, &value);
  22. 22
  23. 23     return  0;
  24. 24}

对应的CMakeLists.txt文件清单


   
  1. 1cmake_minimum_required(VERSION  3.5)
  2. 2
  3. 3project(cmake)
  4. 4
  5. 5## system configuration
  6. 6enable_language(C ASM)
  7. 7
  8. 8set(CMAKE_SYSTEM_NAME Generic)
  9. 9set(CMAKE_SYSTEM_PROCESSOR arm)
  10. 10
  11. 11if(NOT DEFINED ENV{RTT_EXEC_PATH})
  12. 12    message(FATAL_ERROR  "not defined environment variable: RTT_EXEC_PATH")
  13. 13    message(FATAL_ERROR  "Please execute the command: $ source smart_env.sh")
  14. 14endif()
  15. 15
  16. 16set(CONFIG_PREFIX  "$ENV{RTT_EXEC_PATH}/arm-linux-musleabi-")
  17. 17#  UROOT_DIR指向rt-smart sdk中的userapps文件夹
  18. 18set(UROOT_DIR  "${PROJECT_SOURCE_DIR}/../..")
  19. 19
  20. 20set(CMAKE_C_COMPILER  "${CONFIG_PREFIX}gcc")
  21. 21set(CMAKE_CXX_COMPILER  "${CONFIG_PREFIX}g++")
  22. 22set(CMAKE_ASM_COMPILER  "${CONFIG_PREFIX}gcc")
  23. 23set(CMAKE_OBJCOPY  "${CONFIG_PREFIX}objcopy")
  24. 24set(CMAKE_C_AR  "${CONFIG_PREFIX}ar")
  25. 25set(CMAKE_SIZE  "${CONFIG_PREFIX}size")
  26. 26
  27. 27set(SDK_DIR  "${UROOT_DIR}/sdk")
  28. 28set(LINK_SCRIPTS_DIR  "${UROOT_DIR}/linker_scripts/arm/cortex-a")
  29. 29
  30. 30set(CMAKE_C_FLAGS  "${CMAKE_C_FLAGS} -march=armv7-a -marm -msoft-float -Werror -Wall -O0 -g -gdwarf-2 -n --static")
  31. 31set(CMAKE_ASM_FLAGS  "${CMAKE_ASM_FLAGS} -march=armv7-a -marm -msoft-float -x assembler-with-cpp -O0 -g")
  32. 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. 33
  34. 34set(SDK_INC 
  35. 35     "${UROOT_DIR}/include"
  36. 36     "${UROOT_DIR}/rt-thread/include"
  37. 37     "${UROOT_DIR}/rt-thread/components/dfs"
  38. 38     "${UROOT_DIR}/rt-thread/components/drivers"
  39. 39     "${UROOT_DIR}/rt-thread/components/finsh"
  40. 40     "${UROOT_DIR}/rt-thread/components/net"
  41. 41)
  42. 42
  43. 43# 设置链接脚本位置
  44. 44set(CMAKE_EXE_LINKER_FLAGS   "-T ${LINK_SCRIPTS_DIR}/link.lds -static")
  45. 45
  46. 46## user configuration
  47. 47set(APPS_INC 
  48. 48     "${PROJECT_SOURCE_DIR}"
  49. 49     "${SDK_INC}"
  50. 50)
  51. 51
  52. 52set(APPS_SRC 
  53. 53     "${PROJECT_SOURCE_DIR}/main.c"
  54. 54)
  55. 55
  56. 56set(CMAKE_EXECUTABLE_SUFFIX  ".elf")
  57. 57
  58. 58add_executable(${PROJECT_NAME} ${SDK_SRC}  ${APPS_SRC})
  59. 59target_include_directories(${PROJECT_NAME} PRIVATE ${APPS_INC})

可以在这个目录下创建一个build文件夹,然后通过cmake


   
  1. 1~/workspace/rtthread-smart/userapps/examples/cmake/build$ cmake ..
  2. 2-- The C compiler identification is GNU  7.5 .0
  3. 3-- The CXX compiler identification is GNU  7.5 .0
  4. 4-- Check  for working C compiler: /usr/bin/cc
  5. 5-- Check  for working C compiler: /usr/bin/cc -- works
  6. 6-- Detecting C compiler ABI info
  7. 7-- Detecting C compiler ABI info - done
  8. 8-- Detecting C compile features
  9. 9-- Detecting C compile features - done
  10. 10-- Check  for working CXX compiler: /usr/bin/c++
  11. 11-- Check  for working CXX compiler: /usr/bin/c++ -- works
  12. 12-- Detecting CXX compiler ABI info
  13. 13-- Detecting CXX compiler ABI info - done
  14. 14-- Detecting CXX compile features
  15. 15-- Detecting CXX compile features - done
  16. 16-- The ASM compiler identification is GNU
  17. 17-- Found assembler: /usr/bin/cc
  18. 18-- Configuring done
  19. 19-- Generating done
  20. 20-- Build files have been written to: ~/workspace/rtthread-smart/userapps/examples/cmake/build

来生成Makefile文件,然后通过make进行编译。


   
  1. 1~/workspace/rtthread-smart/userapps/examples/cmake/build$  make
  2. 250%] Building C object CMakeFiles/cmake.dir/main.c.o
  3. 3[ 100%] Linking C executable cmake.elf
  4. 4[ 100%] Built target cmake

运行应用程序

在使用的时候,需要把上面编译好的三个应用程序放置到树莓派用的SD卡上。我们可以使用读卡器在PC上把应用程序复制到SD卡上。然后再插回到树莓派板子上,重新上电。这个时候我们可以在串口上看到RT-Thread Smart的启动界面:


   
  1. 1 \ | /
  2. 2- RT -     Thread Smart Operating System
  3. 3 / | \      5.0 .0 build May   4  2021
  4. 4  2006 -  2020 Copyright by rt-thread team
  5. 5lwIP -2.1 .2 initialized!
  6. 6[I/sal.skt] Socket Abstraction Layer initialize success.
  7. 7file system initialization done!
  8. 8msh /> cd bin
  9. 9msh /bin> scons.elf
  10. 10msh /bin> hello world!

执行程序,可以输出hello world!

通过上面三个例子,我们看到了在smart上目前支持的数种技术:

1、在用户态以RT-Thread传统API方式运行:RT-Thread的多线程,基于优先级全抢占的调度都可以被使用,具备平滑的延续性;

2、可以支持C++编写应用程序,同时也可以使用stdc++库;

3、可以支持pthreads,以POSIX thread线程的模式执行,它们会被映射到RT-Thread的多线程上执行。

上面的一些代码都放在了gitee的rt-smart notes仓库中:

https://gitee.com/rtthread/rt-smart-notes/tree/master/examples

下集预告:

下集我们将通过经典的Linux方式的configure & make模式来移植wget & cURL程序到rt-smart上,从而可以看到rt-smart对POSIX的兼容能力,敬请期待。

学习活动

跟随本系列文章一起打卡学习RT-Thread Smart吧,学习期间在RT-Thread论坛分享学习心得或者提问答疑均可获得积分奖励,截止最后一篇连载文章完结的一周内,可兑换相应奖品!立即进群参与活动~

进群交流学习

RT-Thread线下技术培训:MQTT网关

本次培训RT-Thread将以ART-Pi为硬件平台+RT-Thread物联网操作系统提供MQTT网关原型,希望帮助工程师快速熟悉基于RT-Thread的项目开发流程,熟悉MQTT网关开发中所涉及到的技术要点如Modbus、MQTT、连网、文件系统、FTP、Bootloader、OTA、裁剪优化,提升产品开发速度。

我们将到访的城市有:上海、深圳、南京、广州、郑州、北京、武汉、天津、成都、西安

长按识别上方二维码报名


你可以添加微信17775982065为好友,注明:公司+姓名,拉进 RT-Thread 官方微信交流群!

???????????? 点击阅读原文报名培训


转载:https://blog.csdn.net/rtthreadiotos/article/details/116725950
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场