你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32移植RT_thread经验分享

[复制链接]
STMCU小助手 发布时间:2023-3-10 12:11
RT-Thread Nano 简介

RT-Thread Nano 是一个极简版的硬实时内核,它是由 C 语言开发,采用面向对象的编程思维,具有良好的代码风格,是一款可裁剪的、抢占式实时多任务的 RTOS。其内存资源占用极小,功能包括任务处理、软件定时器、信号量、邮箱和实时调度等相对完整的实时操作系统特性。适用于家电、消费电子、医疗设备、工控等领域大量使用的 32 位 ARM 入门级 MCU 的场合。

下图是 RT-Thread Nano 的软件框图,包含支持的 CPU 架构与内核源码,还有可拆卸的 FinSH 组件:


- @! I, E" G0 i3 A; S

1b3dbfb6fe85d38e112bd58feb27f391.png

+ }; }3 M8 \* v! `6 N0 H* K* n

支持架构:ARM:Cortex M0/ M3/ M4/ M7 等、RISC-V 及其他。

功能:线程管理、线程间同步与通信、时钟管理、中断管理、内存管理。

) g  w( l( P3 l. b
1 从官网下载RT-Thread源码,里面包含stm32f1xx的例程。

建议使用最新的源码。很多功能老版本的代码里面都没有,比如之前使用3.1.2的源码,想使用ADC功能,发现源码里没有这部分,更新到4.0.0就有了,并且4.0版本也是现在官方推荐使用的,配合ENV工具开发很方便,现在RTT的社区有很多软件包了,通过ENV就可以很轻松的使用这些功能。

BSP  文件夹内

# k. y( U2 ^' l  S' a0 U- R' C

( p9 H2 H- ]% f% ]4 N8 x, |. N) F
2020122409590473.png & H/ V& z8 G& i9 N, u


; h' I1 \$ L8 D, {9 D) {; k

此版本是基于 HAL 的例程   大家如果熟悉使用HAL库 可直接在此使用


# j) M% G' {. E

: e: a  \, F5 f 20201224095942708.png 3 W# _, [9 E1 m# y' D) W1 Z

& C  k7 e3 c# [3 J

下面开始正式的介绍移植过程


8 p. {& _* I8 B, L) U1 u  lNano Pack 安装

Nano Pack 可以通过在 Keil MDK IDE 内进行安装,也可以手动安装。下面开始介绍两种安装方式。

方法一:在 IDE 内安装

打开 MDK 软件,点击工具栏的 Pack Installer 图标:


; s6 P5 l  }9 P, {7 @5 |  J

41342f0db73e7befc8b0076af4d625c1.png

& S. H1 H9 `% n6 a  Y1 c

点击右侧的 Pack,展开 Generic,可以找到 RealThread::RT-Thread,点击 Action 栏对应的 Install ,就可以在线安装 Nano Pack 了。另外,如果需要安装其他版本,则需要展开 RealThread::RT-Thread,进行选择。

7 Z, d& T8 O$ [" U8 w: q6 s0 J0 C

708412061fe08312095ad4b350db527b.png


4 e- \: K7 _7 X- [

方法二:手动安装

我们也可以从官网下载安装文件,RT-Thread Nano 离线安装包下载,下载结束后双击文件进行安装:


( @' a* }9 S7 ]5 }3 _

99a840701f0837d6ac4c2d2b7f39e590.png

- B7 l! |: i% o$ }* \7 s, F

添加 RT-Thread Nano 到工程

打开已经准备好的可以运行的裸机程序,将 RT-Thread 添加到工程。如下图,点击 Manage Run-Time Environment。


, e3 P* G! J2 l) _- w$ \8 _

6d0962b9bed03fec9b637e345539b44d.png

* b4 r$ L9 ^2 G9 o: s

在 Manage Rum-Time Environment 里 "Software Component" 栏找到 RTOS,Variant 栏选择 RT-Thread,然后勾选 kernel,点击 "OK" 就添加 RT-Thread 内核到工程了。


  }* T( @; K7 _4 y# g

40c4e7a7d03954dea4dfde0a0d951bd6.png

# C4 u/ y+ E9 ?3 i$ P

现在可以在 Project 看到 RT-Thread RTOS 已经添加进来了,展开 RTOS,可以看到添加到工程的文件:


5 Q- Y0 ?- ~- Z1 @

742204638963aeaf0aab8ee4257510a7.png


( C4 s1 I, @) |& O" G

移植完  打开过程文件是错误的

7 T" K* t! ?. n; N

20201224100720186.png


+ a5 I" K, \( C) [

适配 RT-Thread Nano中断与异常处理

RT-Thread 会接管异常处理函数 HardFault_Handler() 和悬挂处理函数 PendSV_Handler(),这两个函数已由 RT-Thread 实现,所以需要删除工程里中断服务例程文件中的这两个函数,避免在编译时产生重复定义。如果此时对工程进行编译,没有出现函数重复定义的错误,则不用做修改。


" h  |( X7 o" l& A) W

系统时钟配置

需要在 board.c 中实现 系统时钟配置(为 MCU、外设提供工作时钟)与 os tick 的配置(为操作系统提供心跳 / 节拍)。

如下代码所示, HAL_Init() 初始化 HAL 库, SystemClock_Config()配置了系统时钟, SystemCoreClockUpdate() 对系统时钟进行更新,_SysTick_Config() 配置了 OS Tick。此处 OS Tick 使用滴答定时器 systick 实现,需要用户在 board.c 中实现 SysTick_Handler() 中断服务例程,调用 RT-Thread 提供的 rt_tick_increase() ,如下图所示。

  1.        /* board.c */
    , r) Y5 X* K( w, E1 o
  2.        void 7 D% [( f8 g4 m/ H
  3.        rt_hw_board_init()
    2 b( L& U' \- T/ f
  4.        {
      d4 X. u5 V; k+ S/ Q& f( s
  5.        HAL_Init();  m4 Y, J% h/ n
  6.        SystemClock_Config();
    & y) O% _( ?' u5 L
  7.        /* System Clock Update */
    + z% ^/ `; [. J% \+ x
  8.        SystemCoreClockUpdate();
    * Q; g- c# N! q
  9.        /* System Tick Configuration */" Q" K4 U6 t( g5 N7 U
  10.        _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
    ' Y& _  V% B9 x5 c& n
  11.        /* Call components board initial (use INIT_BOARD_EXPORT()) */
    % [2 T9 H: O# G
  12.        #ifdef      RT_USING_COMPONENTS_INIT
    1 ?, {! ^/ J) L
  13.        rt_components_board_init()6 C: ]) l8 y3 y. o  f5 C
  14.        #endif
    5 }6 ?( z  V; J
  15.        #if defined(RT_USING_USER_MAIN)
    % z: U! ~% {5 c' r, Y2 Z5 F
  16.        &) t+ h4 M4 T7 v1 {/ ~
  17.        & - K1 \4 k$ L( x# n1 D' U
  18.        defined(RT_USING_HEAP)       rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get())
    ! l! Y, ?* w+ z' O+ n
  19.        #endif
    ) \* w3 B- T. Q# G# v: a% E0 x
  20.        }
复制代码

2 |5 x" i2 r# g% l

01828e115c452708d24b825adec73a79.png

- \$ C8 X+ V" X$ p" a" w* @0 _2 a

由于 SysTick_Handler() 中断服务例程由用户在 board.c 中重新实现,做了系统 OS Tick,所以还需要删除工程里中原本已经实现的 SysTick_Handler() ,避免在编译时产生重复定义。如果此时对工程进行编译,没有出现函数重复定义的错误,则不用做修改。

- n% w* D; ~( J3 U! O- o7 K4 \/ Z

内存堆初始化

系统内存堆的初始化在 board.c 中的 rt_hw_board_init() 函数中完成,内存堆功能是否使用取决于宏 RT_USING_HEAP 是否开启,RT-Thread Nano 默认不开启内存堆功能,这样可以保持一个较小的体积,不用为内存堆开辟空间。

开启系统 heap 将可以使用动态内存功能,如使用 rt_malloc、rt_free 以及各种系统动态创建对象的 API。若需要使用系统内存堆功能,则打开 RT_USING_HEAP 宏定义即可,此时内存堆初始化函数 rt_system_heap_init() 将被调用,如下所示:


, a6 y5 P% O* n' v. M2 ^% A7 ]0 H

ba3278f41f36daf68a3e24a3ba33b4f2.png

( k8 x% z7 a* l

初始化内存堆需要堆的起始地址与结束地址这两个参数,系统中默认使用数组作为 heap,并获取了 heap 的起始地址与结束地址,该数组大小可手动更改,如下所示:


0 |/ E& F. y* P% X  x6 H8 H, Z, @7 ~

d505d2049539b632a2951a5001656866.png

8 x5 V7 f& X) O% P* a, J

注意:开启 heap 动态内存功能后,heap 默认值较小,在使用的时候需要改大,否则可能会有申请内存失败或者创建线程失败的情况,修改方法有以下两种:

  • 可以直接修改数组中定义的 RT_HEAP_SIZE 的大小,至少大于各个动态申请内存大小之和,但要小于芯片 RAM 总大小。
  • 也可以参考进行修改,使用 RAM ZI 段结尾处作为 HEAP 的起始地址,使用 RAM 的结尾地址作为 HEAP 的结尾地址,这是 heap 能设置的最大值的方法。# _1 n0 L$ `4 [8 ?

    3 O/ ~* U, H' Z$ M
编写第一个应用

移植好 RT-Thread Nano 之后,则可以开始编写第一个应用代码验证移植结果。此时 main() 函数就转变成 RT-Thread 操作系统的一个线程,现在可以在 main() 函数中实现第一个应用:板载 LED 指示灯闪烁,这里直接基于裸机 LED 指示灯进行修改。

  • 首先在文件首部增加 RT-Thread 的相关头文件 <rtthread.h> 。
  • 在 main() 函数中(也就是在 main 线程中)实现 LED 闪烁代码:初始化 LED 引脚、在循环中点亮 / 熄灭 LED。
  • 将延时函数替换为 RT-Thread 提供的延时函数 rt_thread_mdelay()。该函数会引起系统调度,切换到其他线程运行,体现了线程实时性的特点。' H5 h0 e! v- H9 L


7 t/ ~# Z1 N- A5 Y# ^

ad4be7cd4c79e9844056b46d53c5b8c6.png

9 Z( s( `0 M/ m2 {3 I

编译程序之后下载到芯片就可以看到基于 RT-Thread 的程序运行起来了,LED 正常闪烁。

注意事项:当添加 RT-Thread 之后,裸机中的 main() 函数会自动变成 RT-Thread 系统中 main 线程 的入口函数。由于线程不能一直独占 CPU,所以此时在 main() 中使用 while(1) 时,需要有让出 CPU 的动作,比如使用 rt_thread_mdelay() 系列的函数让出 CPU。

  E! d) u0 @! l# ?) b

与裸机 LED 闪烁应用代码的不同:

1). 延时函数不同: RT-Thread 提供的 rt_thread_mdelay() 函数可以引起操作系统进行调度,当调用该函数进行延时时,本线程将不占用 CPU,调度器切换到系统的其他线程开始运行。而裸机的 delay 函数是一直占用 CPU 运行的。

2). 初始化系统时钟的位置不同:移植好 RT-Thread Nano 之后,不需要再在 main() 中做相应的系统配置(如 hal 初始化、时钟初始化等),这是因为 RT-Thread 在系统启动时,已经做好了系统时钟初始化等的配置,这在上一小节 “系统时钟配置” 中有讲解。


! }0 F0 D0 n' {. D# d) S

配置 RT-Thread Nano

用户可以根据自己的需要通过修改 rtconfig.h 文件里面的宏定义配置相应功能。

RT-Thread Nano 默认未开启宏 RT_USING_HEAP,故只支持静态方式创建任务及信号量。若要通过动态方式创建对象则需要在 rtconfig.h 文件里开启 RT_USING_HEAP 宏定义。

MDK 的配置向导 configuration Wizard 可以很方便的对工程进行配置,Value 一栏可以选中对应功能及修改相关值,等同于直接修改配置文件 rtconfig.h。


" ~& q# p- }) b6 D, A7 [实现动态内存堆

RT-Thread Nano 默认不开启动态内存堆功能,开启 RT_USING_HEAP 将可以使用动态内存功能,即可以使用 rt_malloc、rt_free 以及各种系统动态创建对象的 API。动态内存堆管理功能的初始化是通过 rt_system_heap_init() 函数完成的,动态内存堆的初始化需要指定堆内存的起始地址和结束地址,函数原型如下:

  1. void rt_system_heap_init(void *begin_addr, void *end_addr)
复制代码

开启 RT_USING_HEAP 后,系统默认使用数组作为 heap,heap 的起始地址与结束地址作为参数传入 heap 初始化函数,heap 初始化函数 rt_system_heap_init() 将在 rt_hw_board_init() 中被调用。

开启 heap 后,系统中默认使用数组作为 heap(heap 默认较小,实际使用时请根据芯片 RAM 情况改大),获得的 heap 的起始地址与结束地址,作为参数传入 heap 初始化函数:

  1. #define RT_HEAP_SIZE 1024
    ) b7 i  Z' c0 j( F
  2.        static
    3 H+ G4 G; I  P1 t+ Q; N" ]
  3.        uint32_t rt_heap[RT_HEAP_SIZE];8 y6 i% t3 }8 L* k1 i- D, B
  4.        RT_WEAK void *rt_heap_begin_get(void)$ K1 A' q+ c+ s- M4 l0 v6 m
  5.        {& g! ]( ?( V; V& t+ a
  6.        return rt_heap;
    . q5 \$ }* w9 S! n% i  d$ N
  7.        }6 z* J! G. R+ {' f" J) G1 y6 [2 f$ p
  8.        RT_WEAK void *rt_heap_end_get(void)
    $ k8 }; [, h; ^" i" a. u
  9.        {
    8 b/ v+ r4 ?$ y2 J
  10.        return rt_heap + RT_HEAP_SIZE;# p' h& ?2 j% m5 K' x
  11.        }
    ! Q% k1 l. b! ]8 p5 ~( Y( d
  12.        void rt_hw_board_init(void)
    - I& D+ J9 J' @* F
  13.        {+ z! ^( B0 ~; z
  14.            ..../ l% C3 Z- w' q6 I5 v
  15.        #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    ' F4 b( ?( U3 ]' z; Z
  16.            rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());    2 e' w: P9 R! g6 y1 V3 J% x4 |2 i
  17.        //传入 heap 的起始地址与结束地址
    ( [# u5 l  ?! x7 k! K8 [6 i
  18.        #endif
    6 P' d4 t' x6 j- B$ Z5 v2 K* N
  19.            ....+ {. h/ p" Y- \. L5 M( [$ }% R/ P# [
  20.        }
复制代码
: C' i9 y/ H! {5 e


) d  d% D$ c8 H4 J1 k" Q# x2 v" m

如果不想使用数组作为动态内存堆,则可以重新指定系统 HEAP 的大小,例如使用 RAM ZI 段结尾处作为 HEAP 的起始地址(这里需检查与链接脚本是否对应),使用 RAM 的结尾地址作为 HEAP 的结尾地址,这样可以将空余RAM 全部作为动态内存 heap 使用。如下示例重新定义了 HEAP 的起始地址与结尾地址,并作为初始化参数进行系统 HEAP 初始化。

  1. #define STM32_SRAM1_START              (0x20000000)
    % e  D- c( M# e  l, o, _
  2.        #define STM32_SRAM1_END                (STM32_SRAM1_START + 20 * 1024)   // 结束地址 = 0x20000000(基址) + 20K(RAM大小). j9 W! B* N9 p
  3.        #if defined(__CC_ARM) || defined(__CLANG_ARM)
    ( B' F9 y% X6 |! ~% q9 [
  4.        extern : a- o* `) v  W4 e9 |+ c; a
  5.        int Image$RW_IRAM1$ZI$Limit;                  
    " Y5 m& ^. R3 m& b; M
  6.        // RW_IRAM1,需与链接脚本中运行时域名相对应; q& F# p$ a2 O
  7.        #define HEAP_BEGIN      ((void *)&Image$RW_IRAM1$ZI$Limit)
    * ^4 _7 k2 r$ G: H
  8.        #endif3 |( }0 B: q4 A, |, I+ |7 g: s: ^
  9.        #define HEAP_END                       STM32_SRAM1_END
复制代码
  1. void rt_hw_board_init(void)6 o3 _& M, `' T/ a
  2.        {1 ]$ x, q- T: Z( I1 P/ {! G+ k
  3.            ....
    ) T" E  Z; O, O, i1 J
  4.        #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    ) x3 Y' i' }9 k; h4 \0 z/ a
  5. rt_system_heap_init((
    + v/ K4 @9 b- n
  6.        void *)HEAP_BEGIN, (
    # T1 d; i& h1 t# P  W) u; F
  7.        void *)HEAP_END);. K$ F+ H, g& S8 A9 x
  8.        #endif) F! }; ?, x% P3 [
  9.            ....
    " J" G/ g+ p' R% I+ }7 R  s4 j! \
  10.        }
复制代码

/ ^' T, k  e  K5 i7 G- o
5 e3 w- f& }. B' h! G2 _8 T

链接脚本

链接脚本,也称分散加载文件,决定在生成 image 文件时如何来分配相关数据的存放基址,如果不指定特定的链接脚本,连接器就会自动采用默认的链接脚本来生成镜像。

举例 stm32 在 KEIL MDK 开发环境下的链接脚本文件 xxx.sct:

  1.        LR_IROM1
    ; ]; r5 l7 B% Q; X6 I4 A
  2.        0x08000000 ' _8 H' t/ G- z3 L
  3.        0x00020000  {   
    % l- l% Z! @' ~/ I  P* t
  4.        ; ' K( ]. k7 B! M5 Q& D/ W7 R
  5.        load
    5 ~" y' j$ p: I) r+ b7 e' ?
  6.        region $ h0 W8 W* M( ?" ]) s2 c( Q* `
  7.        size_region
    % k. c3 F, ^" g- {# O! Z
  8.        ER_IROM1 1 F. H) z: a, _  u
  9.        0x08000000
    # w+ g$ L6 \1 H# d
  10.        0x00020000  {  / U/ _" m) B5 [, K9 S
  11.        ;
    5 L5 i1 I  K5 N  x* v* g( z
  12.        load
    : z  f* l# T" i
  13.        address 1 b4 d7 l4 l6 }+ e. d
  14.        =
    * i. d' Q) T) X! R8 |4 f
  15.        execution
    , x$ Y" ?1 Z2 T% z
  16.        address
    4 n5 h) X- L2 y) X8 Z' [, w
  17.        *.o
    ; l/ x$ _9 m8 X5 H% h
  18.        (RESET,
    - P* T% a* a; T6 A" S4 k7 U
  19.        +First)- k. Q  g) P3 N: }; d
  20.        *(InRoot$Sections)
    * Z/ ~2 ?6 c8 V) |) u! s1 v
  21.        .ANY
    ! g( w! _2 J3 c; W) v, _; M7 A1 {
  22.        (+RO)7 a1 j- Y! r2 L0 o0 T2 O( m
  23.          }
    * K2 s9 {4 Z- K5 e9 p
  24.        RW_IRAM1
    9 d8 }  s8 C1 {2 M" [
  25.        0x20000000 7 l  n. l& z: l- w
  26.        0x00005000  {  / H7 F3 Z+ W; J, I. M( g9 x
  27.        ; & q: b$ F8 T$ Z! T4 i
  28.        RW
    0 K3 S4 B  t, }+ ]8 _
  29.        data
    $ v+ B7 U% C% [# L: t% {
  30.        .ANY
    / n7 }6 _! L8 N" a, C  B* k6 a  I; ]
  31.        (+RW 3 F) W' n% o) ]  @
  32.        +ZI)- _7 ^% B9 _, [& l
  33.          }9 v# B* T/ z4 q0 _& ?6 M
  34.        }
复制代码

4 K8 D: \4 q% _/ H" ^

其中 RW_IRAM1 0x20000000 0x00005000 表示定义一个运行时域 RW_IRAM1(默认域名),域基址为 0x20000000,域大小为 0x00005000(即 20K ),对应实际 RAM 大小。.ANY (+RW +ZI) 表示加载所有匹配目标文件的可读写数据 RW-Data、清零数据 ZI-Data。所以运行时所占内存的结尾处就是 ZI 段结尾处,可以将 ZI 结尾处之后的内存空间作为系统动态内存堆使用。


2 C, J8 X% b# _# f9 I/ f

20210320113521357.png


: d1 ~$ v  a( j$ @, y* H; Q- T

02c0c30e07d086dec972a520ff3a733d.png

1 P1 k% y% y+ Q* P; b5 P

获取示例代码

Keil MDK 中集成的 RT-Thread Nano 软件包附带示例代码,如果需要参照示例代码,则可以在 Keil 中打开相应的示例代码工程。

首先点击 Pack Installer,进入下图所示界面:

( [: A- U: n6 T: f

a2f3187d72324887f4e7e80633e7299a.png

! {1 V: g4 Z  _' H& f1 Y3 w+ p

右侧界面切换到 Examples,然后在左侧界面搜索 Device 或者 Boards,点击搜索出的芯片或者开发板,会显示与其相关的所有示例代码,同时可以看到 RT-Thread 的示例代码也在其中,点击 Copy,选择一个路径,然后点击 OK 即可打开示例代码工程


' d9 a5 v) ^) A

20201224101212395.png

  ^- a+ H; `, m9 V7 u3 o8 w+ O5 }

打开 keil  的安装路径 将  RT-Thread Package 到裸机工程根目录

/ u9 L" Y# e, g) H9 \

. y6 }- c( a9 a9 a% w 2020122410322937.png
, J% u, j, N& M/ i8 |# A) y
$ d7 Z2 V" D3 H 20201224103321378.png $ w* D4 c! F" y9 G: {

# T' j5 ~* s, `, i 20201224103347482.png
0 }, d: a) }" F0 |9 S9 V, P4 n& F. ^/ E% p* @9 w! M

1、拷贝 rtconfig.h 文件到 user 文件夹1 w# C2 ~( y/ N! B5 T$ _
将 RT-Thread/3.0.3/bsp 文件夹下面的 rtconfig.h 文件拷贝到工程根目录下面的 user文件夹, 可以通过修改这个 RT-Thread 内核的配置头文件来裁剪 RT-Thread 的功能

2、拷贝 board.c 文件到 user 文件夹下(新建RTE )' a/ z8 q1 L! ]9 F
将 RT-Thread/3.0.3/bsp 文件夹下面的 board.c 文件拷贝到工程根目录下面的 user 文件夹, 等下我们需要对这个 board.c 进行修改。


, e1 f3 J8 a1 I; @6 H  \5 _

20201224103553656.png
. {5 I8 I9 ?% Z; F( p' p& @- B. _4 L
20201224103930352.png 2 w& N5 `) }. G& M4 k. ?. m, A3 m

' Y4 M* i( T; Y( R( m

3、添加 RT-Thread 源码到工程组文件夹
( t/ E! ]) m# z8 ~- B- l3 E2 R新建 rtt/source 和 rtt/cpu 两个组文件夹,其中 rtt/source 用于存放 src 文件夹的内容, rtt/cpu用于存放 libcpu/arm/cortex-m? 文件夹的内容,“?”表示0  3、 4 或者 7。内核文件   我们移植的为stm32f103  内核选择  Cortex-M3

6 i: W: N- [( [% l% c: S$ O

20201224105043688.png

( \9 z* F2 w" I

指定 RT-Thread 头文件的路径
4 A8 t- l) x: _4 d* L- JRT-Thread 的 源 码 里 面 只 有

RT-Thread\3.1.3\include\libcpu
7 z* J! v5 {8 F% s# kRTThread\3.1.3\include
% A6 ^7 {1 O1 E! O! @& z* HRTThread\3.1.3\src- U* V3 G' _+ x, @3 E6 j& q
RTThread\3.1.3\components\finsh

和 user 文件夹下(RTE) rtconfig.h 有头文件,只需要将这头文件的路径在开发环境里面指定即可。


( o' Z+ i& }- p+ ^! @6 B" v4 b0 g. n

20201224110224895.png ) ^$ M8 S& o# G! k; E$ W


2 ]1 Y, Y% g6 l0 r* t

这些都做完之后   编译还是有两个错误

因为还没有配置 RT-Thread Nano

参考上面讲述的配置 步骤

) Z( ~4 r8 ^& z% B8 Z
20201224110649146.png
5 r% ^5 |3 n; Z" k( h1 D* o3 k$ t4 l; z$ }, d
20201224111035816.png % T9 p& S, i( `$ s) i

: k- c, E* ]; I8 W# y

rtconfig.H0 ?: h; b) L5 P2 a% E- O
  1. /* RT-Thread config file */! ?. M4 j( ^, N, k
  2.        #ifndef __RTTHREAD_CFG_H__
    , O( d, {; `4 J  t
  3.        #define __RTTHREAD_CFG_H__& ?7 k7 [. F% m! p" p; H3 `
  4.        #include "RTE_Components.h"( u* s9 U3 i; {$ q9 i; f
  5.        // <<< Use Configuration Wizard in Context Menu >>>: g' X# ~/ B; v
  6.        // <h>Basic Configuration
    $ K$ d' l5 Z" x8 B
  7.        // <o>Maximal level of thread priority <8-256>
    , T! v! v2 l2 N9 e9 d2 ~
  8.        //        <i>Default: 328 Q! Z5 i/ ~! w4 q
  9. #define RT_THREAD_PRIORITY_MAX  322 ~7 U" B  \& ~) d/ W  S
  10.        // <o>OS tick per second
    , _" @% t/ L6 X' m. s4 m- i- [
  11. //  <i>Default: 1000   (1ms)
    - W8 g$ Q$ ?: K& y% N  Y9 b! P
  12. #define RT_TICK_PER_SECOND        1000* [# s/ Q+ T* o1 e$ k4 T1 Q4 t
  13. // <o>Alignment size for CPU architecture data access
    / U, P9 _2 ?; J/ C% p6 C
  14. //        <i>Default: 4$ q7 V0 n/ [  w6 v, `
  15.        #define RT_ALIGN_SIZE   4
    / r6 [' D9 @( A8 i
  16.        // <o>the max length of object name<2-16>8 P- x. x; E. V$ r4 e5 J' O7 y) V- @& a
  17.        //        <i>Default: 82 B( j# g  X& j; `9 T
  18.        #define RT_NAME_MAX           8
    5 _# ~8 s7 N' m/ I& \7 p; Z+ J9 W
  19.        // <c1>Using RT-Thread components initialization% R, P1 f# Q1 B9 S# I6 [
  20.        //  <i>Using RT-Thread components initialization
      ~! _, Z8 w6 b8 n+ S+ @  H2 r
  21.        #define RT_USING_COMPONENTS_INIT
    : W) S8 L3 B% g. ?
  22.        // </c>
    2 f0 h8 L) z% |6 N# r
  23.        // <c1>Using user main
    1 q8 Z+ m! ~. G3 k/ @
  24.        //  <i>Using user main
    6 x6 A/ S3 T+ F3 F) U! K
  25. #define RT_USING_USER_MAIN
    ! M8 q2 W% R0 n0 u
  26.        // </c>
    : F' U' F) _6 d1 }1 t# E  l2 e# M# _7 J
  27.        // <o>the size of main thread<1-4086>
    2 ]$ {/ e% u3 Z! w5 f
  28.        //        <i>Default: 512$ W6 s3 x. X3 T# X& ?9 a' a
  29.        #define RT_MAIN_THREAD_STACK_SIZE     256
    5 r$ R: R# p! P6 O7 R
  30.        // </h>/ J3 D  D- l; E/ j$ |; Q2 \& g
  31.        // <h>Debug Configuration
    : r  \! S+ N1 b0 j. c% ~! `
  32.        // <c1>enable kernel debug configuration7 u: n2 J; s) o. t8 y* b, H
  33.        //  <i>Default: enable kernel debug configuration
    2 f$ t) j1 W  {9 H0 t# b
  34.        //#define RT_DEBUG/ m: D  e1 x  v+ f
  35.        // </c>
    : \1 ~$ K6 I5 {8 K! ]' }7 m
  36.        // <o>enable components initialization debug configuration<0-1>! W* X; Q: K% ?- |  H
  37.        //  <i>Default: 0
    ( m6 q+ B; k! B# |5 r* ?
  38. #define RT_DEBUG_INIT 0
    2 }) Q' P! S# H6 t0 j+ A# _/ L/ j
  39.        // <c1>thread stack over flow detect0 _/ W- ~7 N8 |9 G! ~2 u4 F4 _/ a
  40.        //  <i> Diable Thread stack over flow detect8 ^9 q6 M7 h$ Y! }) w' [
  41.        //#define RT_USING_OVERFLOW_CHECK. n0 U, x/ U  }; l
  42.        // </c>% P" z- x& @+ Z+ A- `' u' U( q
  43.        // </h>1 T# l! ]4 X% f1 N4 [) F+ ]
  44.        // <h>Hook Configuration
    ! E& _3 n9 A4 t, l1 t0 u$ i) o4 N
  45.        // <c1>using hook3 N. M- R9 d  @' f
  46.        //  <i>using hook
    & \4 N0 a$ a+ n" m9 D+ b) {1 f* g, a# |
  47.        //#define RT_USING_HOOK) h0 y  ]5 V& r9 x8 W& P0 z
  48.        // </c>, W9 G9 |' P3 w1 t8 V7 V! e2 ?8 H. v
  49.        // <c1>using idle hook
    " r1 F- I& d$ N! L+ F: K- d7 f
  50.        //  <i>using idle hook, V5 p- g7 J2 D4 f' Z+ F$ j4 }
  51.        //#define RT_USING_IDLE_HOOK3 x! E* ^/ p! _9 E7 \9 a! ]
  52. //</c>
复制代码

% b8 d4 b8 }" g, M, T! Qboard.c
  1. /*( q7 m; l7 R3 {  [( n4 \' n" E) B
  2.         * File      : application.c8 ~9 p) x/ R' Y4 M2 n" p8 ^
  3.         * This file is part of RT-Thread RTOS
      k2 I" E- I) E5 _
  4.         * COPYRIGHT (C) 2006, RT-Thread Development Team4 U8 L  z$ R. o/ p8 N
  5.         *
    . I' O! f; R( p' E$ J
  6.         * The license and distribution terms for this file may be. Z+ K. N& P/ c0 e
  7.         * found in the file LICENSE in this distribution or at
    0 J. w: m8 H( o* |9 L
  8.         * http://www.rt-thread.org/license/LICENSE5 k! _, b$ D4 n, c9 I8 ?5 ^
  9.         *
    6 }9 c. Y" }9 h* g
  10.         * Change Logs:# v% h2 n+ e# g  m8 i
  11.         * Date           Author       Notes& F6 y  D' G6 Y5 K" h, ^, Q* b
  12.         * 2017-07-24     Tanek        the first version
    - [! N% d$ H& }8 {: m( b2 F  d
  13.         */
    ' H! M5 G; t- {7 w& p, C8 S! @8 e
  14.        #include <rthw.h>
    ( o# c! f& Y' n6 `" s9 ]
  15.        #include <rtthread.h>
    . ~9 q6 g. J" _0 G" D
  16.        #include "usart.h"
    7 g$ k/ A- c+ m
  17.        #include "delay.h"
    - W5 X5 i  c. u% T2 k+ y4 G
  18.        #include "led.h"3 P  J6 }* q  W9 }
  19.        // rtthread tick configuration
    " u6 {6 b! \( @0 Q( ?9 x7 L
  20.        // 1. include header files( \% g( g7 a- B1 Y
  21.        // 2. configure rtos tick and interrupt
    $ B7 d- h/ F7 y: r
  22.        // 3. add tick interrupt handler
    , E2 m! M" K. m  U) I9 }
  23.        // rtthread tick configuration
    ' f0 T' S- }0 J# Z
  24.        // 1. include some header file as need8 k1 \( V  S: [( U
  25.        #include <stm32f10x.h>+ g  K7 F0 q2 D" z. G. {/ }
  26.        #ifdef __CC_ARM" _) x4 S8 W* Q' Z( y
  27.        extern " x; U9 _( V* C5 N
  28.        int Image$RW_IRAM1$ZI$Limit;
    ! t; k+ x1 Z/ d+ i( V
  29.        #define HEAP_BEGIN    (&Image$RW_IRAM1$ZI$Limit). N2 Z0 M1 }9 t5 _, ~
  30.        #elif __ICCARM__8 l7 c& T- G4 i9 Z1 p% \; \4 `4 l
  31.        #pragma section="HEAP"/ L# H6 U4 H! M% z
  32.        #define HEAP_BEGIN    (__segment_end("HEAP"))
    # V, n2 Y+ E# \( H6 v$ m7 e6 ~
  33.        #else
    0 b! A: I6 \, S) M" F/ u/ {
  34.        extern
    ( J9 J' ]' k# P( o' H2 d; I
  35.        int __bss_end;
    2 v% l: v, c' |* B2 s* @
  36.        #define HEAP_BEGIN    (&__bss_end)2 P, V+ {& T3 A0 l: n7 ^
  37.        #endif) U8 {9 e: S, t4 A
  38.        #define SRAM_SIZE         8
    : L* L3 v0 ]7 C7 P% C9 n
  39.        #define SRAM_END          (0x20000000 + SRAM_SIZE * 1024)
    7 A4 D4 V  @, e- b) ?+ I+ j7 r1 G
  40.        extern uint8_t OSRunning;
    4 {& M; @5 M/ m' V
  41.        /**
    # x# a$ c$ {% x6 s* A% C/ O  p
  42.         * This function will initial STM32 board.  @/ x- }$ j! R' ~( n: w; D
  43.         */
    ! b+ `( m8 w' T" a; O' f
  44.        void rt_hw_board_init()0 Z$ {. Y- }. Y! H3 P
  45.        {
    ; ^: Z+ w# c8 d' m: Q% p
  46.        // rtthread tick configuration
    # t! U, ^0 S. M# J
  47.        // 2. Configure rtos tick and interrupt
    8 P2 R* Y! o5 @" D! y% |, C( h
  48.                SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);0 T7 d2 K; n2 B; ?; ^" {
  49.        //串口初始化
    . l- X* G" Z; D, e# B) D% {
  50.                uart_init(2 ^3 B7 l# X/ t: f& O8 K
  51.        115200);0 L9 s8 r; E, L- b" B. W2 ]
  52.                delay_init(4 N5 x9 s5 f  |
  53.        72);
    ' B0 _! |  s6 _8 h4 W1 e+ _
  54.        //初始化LED1 l+ W# ~8 r* F9 T3 E4 P( g' \
  55.                LED_Init();
    % y, b* t5 I4 Z1 F3 E8 q% e# L
  56.        //tips:把硬件初始化放上面% W: L4 h! C" }8 \( @
  57.                OSRunning=
    : g, R9 n5 i3 l( }  l
  58.        1;
    1 |  u' y8 }+ b" \: ?  Y3 M+ X
  59.        /* Call components board initial (use INIT_BOARD_EXPORT()) */$ P- `0 Q3 V& c
  60.        #ifdef RT_USING_COMPONENTS_INIT
    2 A+ _' w" G/ y
  61.            rt_components_board_init();
    4 F  H2 ^) D4 P. T" l- c. `
  62.        #endif
    , U) Q1 i! F0 x9 c
  63.        #if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
    & M0 V. f) w! a4 P  Q7 N
  64.                rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
    3 a! s6 s. F5 a% I
  65.        #endif
    8 n* J( h& s& \
  66.        #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    4 Z5 V* J1 N* }) u" a# w/ w, G8 w
  67.            rt_system_heap_init((1 j% y9 e9 I( V0 }# J+ f
  68.        void*)HEAP_BEGIN, (  D0 l. @1 R0 P3 w. B0 C* r! l
  69.        void*)SRAM_END);
    * x2 o" ]  |( |* Z, o; Q" `6 j
  70.        #endif6 J3 x3 Y( y, G+ _5 M; f2 K
  71.        }
    " n% Q8 c+ U3 X" T7 a' J8 m+ ~$ D' I' |
  72.        // rtthread tick configuration1 J! i2 B0 z$ q* h( t; ?$ F6 U  y8 {, {
  73.        // 3. add tick interrupt handler! L7 E3 Z$ k& W- ]8 h  n( h
  74.        void SysTick_Handler(8 f& Q8 l  e3 J4 b2 y3 B" K! M) r
  75.        void)$ y! i3 B0 t/ p- V% P
  76.         {2 p8 a" s' \4 p$ f& L3 g/ J4 a) h% e% [
  77.        /* enter interrupt */9 k% z1 q: \/ G* l8 A1 J& h
  78.                 rt_interrupt_enter();
    ) c  H% \* u0 U8 Q& `
  79.                 rt_tick_increase();$ c/ ~& N% A) o' G& X) m
  80.        /* leave interrupt */
    & A5 P7 u, n% t' d6 P2 W8 ~* I% D
  81.                 rt_interrupt_leave();
    5 |; m; f( a! a5 n8 T
  82.         }
复制代码
+ m' R9 @' ~2 @* B
修改完rtconfig.h 和board.c  编译通过


" m- h: q6 P9 q. t6 s

20201224133909599.png 7 F9 l* G; K1 V$ i' J
" m" s" M" r0 |1 D; P, u: d$ \
20201224154224945.png
4 X' ?4 c8 |* l8 ^' k, X" F
* l1 r) C- `) W% Q
( V/ N' m5 }7 d* k  a转载:熬鱼不放汤1 A! F; m9 W5 j$ f% G# Z4 i, [

9 i. I! h) Q* @. s4 g) }; k如有侵权请联系删除
8 G0 O  }! J. P! [/ c% u# E; _- V7 D
( M( o0 ~1 ?/ a0 Y; V
收藏 评论0 发布时间:2023-3-10 12:11

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版