前言4 H* c/ ^6 v) l! L
随着 OpenHarmony3.1 的正式发布,其功能也在不断完善。OpenHarmony LiteOS-M 内核是面向IoT领域构建的轻量级物联网操作系统内核,具有小体积、低功耗、高性能的特点,其代码结构简单,主要包括内核最小功能集、内核抽象层、可选组件以及工程目录等,分为硬件相关层以及硬件无关层,硬件相关层提供统一的HAL(Hardware Abstraction Layer)接口,提升硬件易适配性,不同编译工具链和芯片架构的组合分类,满足AIoT类型丰富的硬件和编译工具链的拓展。本文主要介绍如何在STM32上移植 OpenHarmony LiteOS-M 内核,及其注意事项。& M; N4 r# q& P4 Z9 O
+ }! h5 w0 Q" x- j) d( n一、开发环境6 m. B8 h# I L( w' l
硬件:% m D, k8 |7 C) a" y
- STM32F429I-DISC1 开发板$ I. W6 s, _$ T
5 G0 Y: O' l6 s4 V8 h, Z( G0 h
- p% L/ ^& r* f: O0 b软件:9 n8 r+ D3 ]+ k% k9 [: W
- VSCode:用于编辑代码+ B) F/ v- Z1 t- Z$ K( |7 L, X
- STM32CubeMX:用于生成工程
; ]" Z0 U# T) K5 G- make、arm-none-eabi-gcc:用于编译工程) f4 ^* `" y+ \+ A$ F
- STM32Cubeprogrammer:用于下载工程' m+ a Y( Q4 d- v
- Git:用于获取 OpenHarmony LiteOS-M 内核源码
; j# l$ N2 j2 U: U4 H" N' h; k% ~& i7 `) n3 h9 F
二、移植内核; O* y7 p8 p" X" Z
1. 操作流程
# ~, x8 w7 k: B" T Y$ V拉取仓库代码。
6 H- A6 ^7 E. `" [使用STM32CubeMX在 /target 目录下生成工程。
* P+ {: h. G4 v6 b" j- O& p4 |修改Makefile文件,工程加入 OpenHarmony LiteOS-M 内核所需的文件。8 m8 O. j" t/ T( `% Y
添加用户代码以支持printf。添加用户自定义任务。* C# R0 H4 f- W# N
编译下载程序, U" ]4 e F7 |# O3 F/ C
: o& M: Y: |) [% i+ Z5 `
2. 获取源码
: F5 W' H0 W3 |8 `- Q% X: T) F5 V0 H/ D
3 {: \) `7 A" C
- W9 A* [1 d$ x使用Git Bush,拉取内核源码到本地。
4 s4 y, N, E: p- r# ]0 c' V: ^+ x! _, W9 ^0 k- Y
2 P' E: ]+ z F- @, r& L$ B
5 A' w" [9 ~+ M: X创建 /third_party 目录,用于存放第三方依赖文件(STM32 所需的 CMSIS 等),拉取第三方依赖文件。
6 r9 F9 ~$ R/ H2 M' P* v9 p/ I9 K& O8 ]- z# W) \
2 E! G# F+ W* s1 l% B. ^, ^
$ m1 x7 h7 _ ^' u1 P( G
到这里 OpenHarmony LiteOS-M 内核源码就获取完毕了。
& n$ [& `7 z! m/ A- v% k, f0 q5 @$ T0 |, k" h; F, W' c$ S. A; D; k9 a8 W: v
3. 生成工程/ E9 K T" m8 Q5 o/ W, z" C9 `
进入/targets 目录,使用 STM32CubeMX 生成工程 STM32F429ZI_Harmony_LiteOS_M
$ w' p7 {# g% K7 Z
- N1 ~8 I/ P8 J. ?
7 y) I/ q3 X' A: I
3 f' j. Z" h9 `7 e/ m3 b; H与FreeRTOS类似,由于LiteOS会占用SysTick定时器,因此需要修改HAL库延时的基础时钟,改为其他非SysTick的定时器,避免HAL库延时的定时器和系统运行的定时器冲突。
& V! O# F& H4 w& L( Q9 W2 T/ T7 S& e/ x
7 C3 a$ c7 }* m# C
& f: I" C& X& b, O
配置:下载调试端口SW、串口USART、LED_GPIO、时钟树。5 o6 k4 E' d4 d. e5 g2 a! w8 O- @
* v6 ]/ t3 ]+ A+ l& `2 j
- W2 P7 s: W/ p3 O) X$ t4 b/ }
! D$ v2 ]' C# x1 G! g6 n
开发环境选择 Makefile
4 O. _: L. w$ ^* M t
# H* t! }3 l1 f: Y
: ^8 {4 {4 @* I) R O0 @
# P; n4 g) U: B( L5 J. z/ CCode Generator 中一定要选择 Copy only necessary library files ! 如果选择所有库文件都添加的话,那么就会生成很多模板文件。由于我们需要在 Makefile 中添加文件,如果目录中有模板文件的话,我们就无法直接使用筛选功能将所有源文件快速添加到工程中了。
% i S5 f5 x) f* A, Y) Q! k; H7 j# j1 c% T& u0 ?
4 K S3 T5 { g7 Z: z0 a8 k
/ [8 o% ]& V" d3 w. p: x7 D7 n
至此工程配置已结束,点击 Generate 即可生成工程。5 B$ F7 ]3 t: A3 F
8 S1 @4 j/ d& V4 j. d8 @7 D6 A" ?4. 修改工程文件3 J% g. \4 i% |2 z( n- S
1.使用 VS Code 打开targets下的工程目录,新建liteos_file_path.mk用于将内核源码文件添加到工程Makefile中,该文件相当于C语言中的头文件,主 Makefile 文件可以直接包含该文件。
5 {4 I, j5 }; c; W! C3 {9 x' Z- ]* M) B. D0 @" Z. j1 m
5 m/ L, K9 z2 i j0 |3 i/ D
2 z% ^) b, U! W& a2 ^2.添加内核源文件目录到 liteos_file_path.mk 中。, w9 D0 }/ x; j8 |
- # Topdir 顶层目录
$ A6 a N( H4 s; m& I8 k/ e - LITEOSTOPDIR := ../../" l( i& m3 S2 L8 J& a
- LITEOSTOPDIR := $(realpath $(LITEOSTOPDIR))) m1 ]2 K+ l7 w
5 U$ u$ b5 N6 ~; q: Z/ p, A- # Common 内核源文件及头文件目录& Y% i' I( L$ A8 C% C- e3 r# X( ^4 X
- C_SOURCES += \
2 Z7 _, `6 N8 u( S5 z. k - $(wildcard $(LITEOSTOPDIR)/kernel/src/*.c) \; [* D' d$ ?* j
- $(wildcard $(LITEOSTOPDIR)/kernel/src/mm/*.c) \ {% e8 ?, ]9 l* H( Y
- $(wildcard $(LITEOSTOPDIR)/components/cpup/*.c) \- @) g8 @( Z. z: u
- $(wildcard $(LITEOSTOPDIR)/components/power/*.c) \
5 K. L8 d5 N/ Z& D4 Y" N - $(wildcard $(LITEOSTOPDIR)/components/backtrace/*.c) \
6 Q5 Q! g( l {2 g9 Y% A* i - $(wildcard $(LITEOSTOPDIR)/components/exchook/*.c) \
3 y. R' {5 }4 A B2 z( Y - $(wildcard $(LITEOSTOPDIR)/components/signal/*.c) \
q, `* K( j. e+ x. k6 k" q - $(wildcard $(LITEOSTOPDIR)/utils/*.c)/ D, n) ], n v5 Y5 I& x6 ]
- $ w- {& ]9 W. ~( n
- C_INCLUDES += \
% y \$ U; ?/ u% l - -I$(LITEOSTOPDIR)/utils \
7 y& {3 [; c( q! I r - -I$(LITEOSTOPDIR)/kernel/include \
7 {5 L2 ~$ k+ `0 \( G% [ - -I$(LITEOSTOPDIR)/components/cpup \
5 Y; ^: h+ d; o) d& L1 W - -I$(LITEOSTOPDIR)/components/power \
+ b6 z+ y- D' N( z6 b0 y, g - -I$(LITEOSTOPDIR)/components/backtrace \; H- N' _, y9 R+ F, x1 [4 r3 }
- -I$(LITEOSTOPDIR)/components/exchook \7 k" z' A) Z7 a n0 C% I3 B% y
- -I$(LITEOSTOPDIR)/components/signal" C4 p. [7 M& W% i2 D& G
- 2 B5 U: g! x: _( T
- ; ?' y s% P3 M9 z4 S
- # Third party related 第三方依赖文件及头文件目录6 ~% m. b# C! O: u9 r
- C_SOURCES += \
3 ]6 g/ r- @6 \& x( }6 Q - $(wildcard $(LITEOSTOPDIR)/third_party/bounds_checking_function/src/*.c)\. ^" W8 |* n3 R$ C7 X+ I
- $(wildcard $(LITEOSTOPDIR)/kal/cmsis/*.c)\8 `# O% c) U) R. x5 A5 P9 _
- $(wildcard $(LITEOSTOPDIR)/kal/posix/src/*.c)2 _8 Q' }8 R% u% L
- - k+ n9 ^ P0 B5 o. ~4 w6 C: k0 D
- C_INCLUDES += \: z: u. _8 E( `6 K. ^# t T8 @& w
- -I$(LITEOSTOPDIR)/third_party/bounds_checking_function/include \+ j6 t& Y; M5 {
- -I$(LITEOSTOPDIR)/third_party/bounds_checking_function/src\
3 n) y0 R s3 {9 ]. S( Z3 m* X - -I$(LITEOSTOPDIR)/third_party/cmsis/CMSIS/RTOS2/Include \
# ^$ g& m" x' H; B! l - -I$(LITEOSTOPDIR)/third_party/musl/porting/liteos_m/kernel/include\5 Q& @$ \# q/ \. U
- -I$(LITEOSTOPDIR)/kal/cmsis \
" c( C7 X& r( V8 u$ K - -I$(LITEOSTOPDIR)/kal/posix/include \
7 E- y7 G( R4 E - -I$(LITEOSTOPDIR)/kal/posix/musl_src/internal
+ [! P3 V$ Y& l7 p/ L) g9 F4 s
/ e% |4 N K h' u: b/ Z- O/ Q- : n: j" P# m1 i/ m
- # Arch related * Y9 g4 `5 {7 ~9 v1 }# p( K" X
- ASM_SOURCES += $(wildcard $(LITEOSTOPDIR)/arch/arm/cortex-m4/gcc/*.s)+ q( @/ u* E* o, v4 i
- " l% y% J' ^% v/ G
- ASMS_SOURCES += $(wildcard $(LITEOSTOPDIR)/arch/arm/cortex-m4/gcc/*.S)
6 p6 V4 @* b7 | - * z( p7 F y+ x( g( N
- C_SOURCES += $(wildcard $(LITEOSTOPDIR)/arch/arm/cortex-m4/gcc/*.c)5 z$ Y, J9 n4 k% \
7 m! H7 c+ [, P- C_INCLUDES += -I. \ X7 u T& O, d* b
- -I$(LITEOSTOPDIR)/arch/include \
; W2 S' I& Z5 @5 O; ?0 ] x - -I$(LITEOSTOPDIR)/arch/arm/cortex-m4/gcc
* |, X+ I7 d7 s9 z- x" X3 v8 F" w - ; Z2 R, c: q0 g7 u
- CFLAGS += -nostdinc -nostdlib
0 R0 e( X/ W$ l$ J( i) l! Y# F - ASFLAGS += -imacros $(LITEOSTOPDIR)/kernel/include/los_config.h -DCLZ=CLZ
7 u. }7 l ?1 @# E. W( ?9 ^ - 4 l2 F; q! `( E1 @3 i, `
- # list of ASM .S program objects
; V( N+ I/ _( |2 M% t, I" o# i* ^7 a - OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASMS_SOURCES:.S=.o)))7 M! A: Y- Q& m6 F' I1 d
- vpath %.S $(sort $(dir $(ASMS_SOURCES)))" q" [% N; b5 T. w4 H- U
- {+ N2 y/ Q2 d5 i- $(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR)
& B0 r) u( J$ G( p9 x5 c, D - $(CC) -c $(CFLAGS) $(ASFLAGS) lt; -o $@! D, A! |9 ?* v9 m8 g, }- }7 Y, l4 W
复制代码
/ M1 w1 w8 y# i这里注意:最后一行前面的缩进必须为tab,而不是空格。否则编译会报错。, {. b* b) r# _- U, }' K) J
6 m7 x# v; A3 `3.修改项目Makefile1 n: T6 x0 I$ P* @ v5 e
在Makefile中包含liteos_file_path.mk
# b; E" m" D) v* p# o/ w
* v5 v* I1 ^0 \/ z# d7 Q
, h9 p0 U! ^3 x9 C o% q. D
& b- k* e6 \6 [5 l3 y增加*.S文件的编译规则
% i, ^! i7 h+ U1 q- # list of ASM .S program objects b: m# X3 q/ o% u* E4 T5 H* G$ ~
- OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASMS_SOURCES:.S=.o)))* A9 @4 i+ q( [ B4 g' @% b
- vpath %.S $(sort $(dir $(ASMS_SOURCES)))) Q8 c- E e/ H% |8 j
- $ V2 \2 t0 I+ z3 c( Z
- $(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR)6 h6 T# _) Q" {% C
- $(CC) -c $(CFLAGS) $(ASFLAGS) lt; -o $@
复制代码 1 a# z( A0 ?* `) u9 j- @
6 X" [: q, y O1 a$ {
4 l" K9 D7 g, E, M
4.添加 target_config.h 用于配置裁剪内核。该文件相当于FreeRTOS的FreeRTOSConfig.h
6 ^ h. c' ?8 ?! \9 @- /**@defgroup los_config System configuration items
; r% ?5 \, i/ \ - * @ingroup kernel: q8 w) O/ l* n9 ~% y" o8 c! d
- */
9 ~' x% Y: o( p9 E/ ]8 _ - % k' P4 f6 l6 m3 I: n% F$ m
- #ifndef _TARGET_CONFIG_H" A8 s& z" G% E6 r
- #define _TARGET_CONFIG_H9 k: G! K' f9 T- a. l
" o4 W) U, F9 m/ N- #include "stm32f4xx.h"
# V& R- U& m& b5 i' O, q - #include "stm32f4xx_it.h"
4 c! h- s$ Q5 a
6 O. o- Z9 d0 b5 O- #ifdef __cplusplus& S% u1 U0 c6 x% d- o
- #if __cplusplus
' o5 r* X5 q g; b" o( Q - extern "C"% _' L5 S- p- g
- {
9 i4 L0 J; |! z9 }5 ` - #endif /* __cplusplus */& u0 c9 m H% n, v2 M6 f
- #endif /* __cplusplus */- ^; y. G9 E/ h
- # U5 w E2 k/ Q5 `5 {$ y
- /*=============================================================================' g( Z: A5 D3 I. i
- System clock module configuration$ W( q: D: Z2 U7 K3 _5 T
- =============================================================================*/
& @1 f, ^0 G; Z6 X* r, u" I - #define OS_SYS_CLOCK SystemCoreClock
- E' l. f4 _$ @$ ]( N - #define LOSCFG_BASE_CORE_TICK_PER_SECOND (1000UL)& V- o. v! r4 ^9 A
- #define LOSCFG_BASE_CORE_TICK_HW_TIME 0% I2 e1 M: l1 c4 {
- #define LOSCFG_BASE_CORE_TICK_WTIMER 0+ T; J4 g; T! ^* }' o" C; e* \; E
- #define LOSCFG_BASE_CORE_TICK_RESPONSE_MAX SysTick_LOAD_RELOAD_Msk
$ L% A& d# W7 V+ O& [
# O9 \# r! c0 R: q' U/ T- /*=============================================================================
: B8 h$ s/ @: ]' S' D+ Z - Hardware interrupt module configuration, ]8 [# T. U/ t
- =============================================================================*/
" ~; e, P+ s: v' R8 H - #define LOSCFG_PLATFORM_HWI 0
/ Y7 p) a: a6 t3 d8 z2 u - #define LOSCFG_USE_SYSTEM_DEFINED_INTERRUPT 0* b- l- E3 |& t# o4 E1 E
- #define LOSCFG_PLATFORM_HWI_LIMIT 128
9 c' ^8 i/ a; f6 K% t, |9 N
- s% e' ?& W2 q" T! F/ {- /*=============================================================================
3 ?/ Q5 Q, h, H/ i0 k8 v, I) V: y - Openharmony Kernel configuration2 B# e+ [1 q0 T, e4 s
- =============================================================================*/: f9 K4 a* U0 N# T6 o& {
- 7 {7 U* }6 I6 O/ G) n) w& A" W; d
- /*=============================================================================
: M3 x3 B) v, D, A' S - Task module configuration
( n/ q6 Z3 j$ W4 [9 y - =============================================================================*/; Q4 p" o* a; K+ W$ a& r
- #define LOSCFG_BASE_CORE_TSK_LIMIT 24% t! K; W6 u* U2 s/ a) Z
- #define LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE (0x500U). A# m# ?5 g d3 g
- #define LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE (0x2D0U)- P$ }: [3 a* n, ~8 o. ? D! T
- #define LOSCFG_BASE_CORE_TSK_MIN_STACK_SIZE (0x130U)& O% K c% o" K2 R* Q8 u% J0 v
- #define LOSCFG_BASE_CORE_TIMESLICE 1
. M1 T5 L" e8 R& E* ], w6 b - #define LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT 20000* D9 b$ h: O# k( N
- /*=============================================================================
2 k2 g/ W$ b( C7 V5 `% g0 a" ^4 w - Semaphore module configuration3 o) A" l: w `/ q0 ~
- =============================================================================*/
( e; r& x1 R+ b$ k( h; w% J. o6 g - #define LOSCFG_BASE_IPC_SEM 1
" q( Z: F6 q" G - #define LOSCFG_BASE_IPC_SEM_LIMIT 48$ [ Q, G" ~3 o+ o3 G8 e U: d- r5 p
- * j7 f- u0 J5 Y5 L
- /*=============================================================================4 [+ r1 Z1 F4 `! z3 n
- Mutex module configuration
" G# |0 s5 I4 U: Q - =============================================================================*/) U9 M2 L! p* ~8 l
- #define LOSCFG_BASE_IPC_MUX 1
# ^$ C& c& e; h: }) g9 ]* G - #define LOSCFG_BASE_IPC_MUX_LIMIT 241 v5 E9 v2 D6 q
- /*=============================================================================1 h' G& S: B$ v0 Z- o
- Queue module configuration
3 X1 Q4 R. Z& h6 i7 L1 ?. P! ?. M - =============================================================================*/
9 [& r K! A* Q) c2 M: q, q5 `' N3 l - #define LOSCFG_BASE_IPC_QUEUE 1) A# `& c2 z1 v% s! b
- #define LOSCFG_BASE_IPC_QUEUE_LIMIT 24! F# X0 g3 a: @' `) b
- /*=============================================================================. I! D0 _$ @0 s( }
- Software timer module configuration
6 ?) L0 L$ W7 K* x; y7 U9 q2 t - =============================================================================*/
# A$ F/ a5 {! e& Q8 N% B7 \! E - #define LOSCFG_BASE_CORE_SWTMR 1$ F# U& i3 i# }- a
- #define LOSCFG_BASE_CORE_SWTMR_ALIGN 1. {" U/ {/ h/ L( k6 m
- #define LOSCFG_BASE_CORE_SWTMR_LIMIT 48. K) Z0 O1 b4 Q8 _
- /*=============================================================================+ w& G: V# ?$ f3 |# I k7 ~
- Memory module configuration
1 S# m6 e+ ~# o- Y) M4 ?8 b3 o - =============================================================================*/
+ u7 J; E: M* q - #define LOSCFG_MEM_MUL_POOL 1
! y8 K: \# h, J* q8 [: [/ A - #define OS_SYS_MEM_NUM 20, e& `! k F( W
- /*============================================================================= ]" V: a% H# }1 x$ a% J5 _3 d* f
- Exception module configuration
( x' v! @; l( O. j/ f& t - =============================================================================*/- h- U. G! p2 R5 M; u+ o' ~
- #define LOSCFG_PLATFORM_EXC 1 k/ K t2 D! Y A. A
6 _3 B4 N3 L) B9 s. q9 u- /*=============================================================================
& j4 C' F) \: q% i( v - TestSuite configuration
9 L9 `4 F5 @. [; B, _, l& m) J - =============================================================================*/1 @; R3 H5 i- |$ t
- #define LOSCFG_TEST 0/ J: X2 D1 Y9 j8 \# f
- 6 w- _+ N- x* `+ H& ^/ Z
- #ifndef LOSCFG_BACKTRACE_TYPE
% Z2 Y3 F" B% H* b - #define LOSCFG_BACKTRACE_TYPE 1) Y4 B1 N& P1 s* B( z
- #endif( L" a' J% D( l/ O0 I) P) R& _
- /**5 o F* R: J9 x" w4 s! G
- * @ingroup los_config. ?! x/ m7 P- h% L
- * Configuration backtrace depth.% a7 W/ w" E1 S- @1 I( i
- */
0 k' M. Y6 V& l Y) i# d! X - #ifndef LOSCFG_BACKTRACE_DEPTH( Z0 g$ E4 L+ q' h3 i. N
- #define LOSCFG_BACKTRACE_DEPTH 15
7 T% w8 }8 p" t3 w - #endif4 u; ^/ U+ v. C8 f; L8 j7 M
- #ifdef __cplusplus
N( v3 ?+ Y8 H5 A% ~ - #if __cplusplus! Z! r/ X! b) z1 G& p7 S7 C
- }4 l+ \) @% y& H( e1 [+ q& T
- #endif /* __cplusplus */8 r1 j7 o1 y m/ x* X/ f
- #endif /* __cplusplus */, ~, k* t: f: C) H- }
|- J. I! ]: _ o% M0 N9 m& C- #endif /* _TARGET_CONFIG_H */
复制代码 5 z) p. Q+ Z0 y ~1 _ W) x
5.修改链接脚本文件 STM32F407ZGTx_FLASH.ld5 B' ] d }* G& L
添加程序起始地址 _sstack = 0x20000000; /* start of RAM */
2 O6 Q ~: k" C, U: |, t) ~/ f添加.text 段的起始地址,这是链接脚本的语法,将当前位置地址赋值给_stext。_stext = .;
2 n; C1 O0 a9 k! e9 f2 u2 { F t7 E( y4 \' _9 p# \7 Q: {, h
; O/ X' c; b+ r
& ?* l0 \- i9 F6.修改中断服务函数 Core\Src\stm32f4xx_it.c
+ s3 d. h4 h3 p0 g# G! V添加 LiteOS 头文件. I. H6 g% w- @
在PendSV异常中进入LiteOS HalPendSV 异常处理函数,进行任务切换操作3 \5 H. D4 N$ a v, R: Q/ `( V
在SysTick中断服务函数添加OsTickHandler函数,为系统提供时间基准
& j {! {6 @/ M- k. V/ k! X9 j' ]- #include "los_arch_context.h"
7 k; e( h/ T) {& ?! ~( F6 S - #include "los_tick.h"" S7 f5 @& q3 q( `+ e. D
- /*
$ e8 r! U0 v+ D% B+ d0 G! r& N - .........
! _* v8 f4 g2 x8 ~2 S7 s0 g9 ]" { - */
" p! I# o5 Y2 Y* F - void PendSV_Handler(void)" u$ j# H( V3 Z( v& `
- {* h$ j z2 Q! V9 I1 c" _" x6 d
- /* USER CODE BEGIN PendSV_IRQn 0 */
( i! t( z2 ~) J' G# ? - HalPendSV();: b2 c1 C/ D" T) W
- /* USER CODE END PendSV_IRQn 0 */
" ^- O: `+ C1 V/ X$ O P, x - /* USER CODE BEGIN PendSV_IRQn 1 */; |* v2 W. ]0 b( S! E
- /* USER CODE END PendSV_IRQn 1 */ D$ b; M r! A+ y9 s/ k5 e# x
- }4 [3 d9 A& U5 [& d
- /*9 `3 I$ A$ f8 M2 N- I% ^0 x0 c' l
- .........4 c; y( M, P+ p. f6 i
- */" Y1 J! t: b2 D! F! c2 R
- void SysTick_Handler(void)
, P* Y" r5 x3 g; G1 u - {
2 A& N3 p. s0 C7 }$ K - /* USER CODE BEGIN SysTick_IRQn 0 */
! C# J6 c R8 X+ J - OsTickHandler();5 \- I1 J- n+ w5 |
- /* USER CODE END SysTick_IRQn 0 */# K9 X" I4 H; ^! a. `& q3 r) L
- /* USER CODE BEGIN SysTick_IRQn 1 */
7 U, W6 D+ }) ?! B5 m5 f - /* USER CODE END SysTick_IRQn 1 */+ R( Y& F, @, _; }# q
- }
- r! l8 b7 d. w& G8 ^( `! Z - /*0 a. L) l& Y- A, n8 ?1 }8 E
- .........
! L& z3 }" H% P5 a - */
复制代码
, m7 n* J* `7 l# r7.修改串口映射 Core\Src\main.c% E9 O$ n+ c0 v1 r
包含头文件#include "stdio.h"
. r1 z5 G/ Z+ V& @) y* k修改串口映射以支持printf
! ]# c/ n& [5 i3 o- /* USER CODE BEGIN 0 */$ r, N5 H+ a1 p2 c
- #if 1
* ?( t9 {2 u& f7 U z. z - int _write(int fd, char *ptr, int len)
, q5 ]" [+ G3 r* }" F8 @ - {
& q: i& e$ f! [1 A( [7 u$ y - osStatus_t result;
; P( T0 ]3 ?: U/ A1 `+ Y- @ - osKernelState_t state;( Z0 ^- E* x$ o% O3 X
% ~" n5 T7 ]% f1 ^+ V% [6 Q- if (osKernelGetState() == osKernelInactive)5 j$ A+ X. d3 u0 A* o S
- {
; A* O2 R+ k7 V7 x+ M - //系统未启动时不使用DMA
7 j `" M* i& `) e( l; N - HAL_UART_Transmit(&huart1, ptr, len, 0xFFFF);
% S5 H# l/ X5 U' i$ M - return len;/ D) F& q3 e E$ [
- }& d f9 _ ~; C2 d" m# L
- else% Y. {$ s: g, W% p( D% B3 ^0 W
- {7 ~8 j; @- b. j
- //获取信号,如果上一个DMA传输完成/ @/ S7 ~5 V) n0 ]
- //信号就能获取到,没有传输完成任务就挂起
$ K6 i B4 [5 V9 n6 _) [+ Q& D - //等到传输完成再恢复1 B% j" W# R- {% i
- result = osSemaphoreAcquire(UART1_TX_DMA_SemaphoreHandle, 0xFFFF);
0 @9 \' N6 C" M* _ - if (result == osOK)- Y4 {8 n) S O+ w
- {4 g+ ~& }# B4 \: G+ x4 {
- HAL_UART_Transmit_DMA(&huart1, ptr, len); //获取成功,发送数据, d6 N% P. t7 _$ f3 ?4 h; X
- return len;
( y/ S9 f9 v$ m3 l. A - }
( |* b; R* q' i# t% M - else
( S5 ]- `# T: P3 i, A3 ?8 ], j# @: [ - {6 F- f, C: W* u" q6 Z. f
- return -1; //获取失败
5 b7 L0 L1 C$ h- J) |' k - } Q3 S/ `: l* ^4 r9 m! R ?
- }
8 A2 c( l9 v$ ?2 I4 B2 b: t# a$ f - }* {5 b, c' W: m8 f9 @& P
- #endif
* ~: P2 E, J1 E: J" {9 V( X% S
/ j$ N: J5 h, y. m% Q7 y0 w/ ]- // DMA 传输完成后会调用传输完成回调函数,在该函数中我们释放信号- A# _- l. F$ o+ A+ {
- void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
* F4 q. l" v! ^% D3 H' z& q - {
8 r: }& y1 l5 ~- U4 G - if (huart->Instance == huart1.Instance)
$ x+ H9 [& K- q# z- S - osSemaphoreRelease(UART1_TX_DMA_SemaphoreHandle);
' _# f8 N4 G3 ~' c - }
1 O {7 e/ ?( [$ T1 D6 j/ p - /* USER CODE END 0 */
复制代码
, {$ n- c4 k3 \3 W9 B% l. i8.添加测试任务 Core\Src\main.c- b" P5 i r5 e2 E: o9 _+ X3 y) w1 H
包含os头文件#include "cmsis_os.h"
+ p: c" `3 H6 Y/ Z. G! y增加测试任务
9 ^8 j' J) u6 A2 B2 {. o- /*
: v9 X! e8 {4 W: s( x* } - .........
. q4 ]7 x: ~5 \3 F A* {9 q/ { - */ d# ~ ]+ U7 n8 q$ v s2 a
- #include "cmsis_os.h"
+ e, M5 G/ a& t* X3 m- R - /*- ?# o9 ]. m2 n# C0 y! w- `
- ........./ Q$ J) u4 o. Y+ p( E- X4 o' n
- */* a6 b+ d8 j' v% m9 e* ?( \* _
- /* USER CODE BEGIN PV */
# A- d2 g7 s8 T- [/ u - osSemaphoreId_t UART1_TX_DMA_SemaphoreHandle;
- n0 E* C7 d- f' L - const osSemaphoreAttr_t UART1_TX_DMA_Semaphore_attributes = {
& }' U$ H) ~( T. V+ T8 W; z' M - .name = "UART1_TX_DMA_Semaphore",
' \6 A: A5 X7 ?9 y - };
5 H+ t3 |" ^+ O" s - n* m( m8 K7 x/ P' e/ G
- osThreadId_t uart_taskHandle;
' I; b7 W' b) H/ X# e4 w2 | - const osThreadAttr_t uart_task_attributes = {
+ o* P% T# U8 |$ M - .name = "uart_task",: P- e& s9 y' ]1 v" [0 o: g. \
- .stack_size = 512 * 2,- \. T5 U# d0 H( f4 G( U
- .priority = (osPriority_t)osPriorityNormal3,0 A3 p0 B2 z3 t+ e4 K' A3 `4 k
- };5 u* ?! S7 O( h
- /* USER CODE END PV */
! _5 W4 [+ ~$ v - /*
0 ?" ]1 p9 [: x5 e& w. s - .........
/ D2 w1 f; F N) K - */
6 o( \$ ~ j- u5 w; T; D - /* USER CODE BEGIN 0 */
9 m2 A% ~3 {2 A5 f- _7 _ - /*; c5 V% F# ?* w. }& A* H
- .........
- B, x3 j' F8 Z) D. C - */- b2 Q/ e8 N' G: f; n9 }
- void Uart_Task(void *argument)( D( \" c9 R2 s" ^8 F' i
- {2 v: Y r9 I" R. h7 x6 \) z- ]9 t
- HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_SET);
2 Y. u p( [4 k - HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET);# x5 V5 l7 Y2 W
- while (1)( }" f" } d7 [ y
- {
2 G2 S( e3 n1 p0 |3 j2 B5 y4 m& s# v - HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin);- v1 g3 u6 b! L1 }
- HAL_GPIO_TogglePin(LED_R_GPIO_Port, LED_R_Pin);
( A+ i" \/ p8 W9 L - printf("System Runing!!!\r\n");3 ?# E% W: b7 @2 H* X
- osDelay(1000);' z2 S( Z7 I: Z* j$ [5 Z) N8 D
- }
! O! {: @4 |! n! S8 s' m - }, e4 Q, w' ]* |7 j: g( I
- /* USER CODE END 0 */
) ]3 ]# i' }/ q* \ - /*! p0 f/ {$ O$ B8 a
- .........( ^" X: _3 Y2 Y3 v$ H
- */
1 d4 D( }) y% E m' c1 H - int main(){
1 |- q$ ~# j/ f3 ~0 `# y; x$ r - /*
" F8 w7 n8 [2 \ - .........2 U2 g& H' l6 }3 e* W# }
- */
) A- `* \# Y6 [- t# t* A - /* USER CODE BEGIN 2 */' s5 D+ P* [3 E4 T% r
- osKernelInitialize();6 ]# p" k2 T* D- w" F! C; ^
- printf("System Init!\r\n");
: P% O) G6 C9 u; z; A& U7 L - UART1_TX_DMA_SemaphoreHandle = osSemaphoreNew(1, 1, &UART1_TX_DMA_Semaphore_attributes);
3 T1 l7 X; Q+ d0 K% j - uart_taskHandle = osThreadNew(Uart_Task, NULL, &uart_task_attributes);- O+ p4 `! d) O0 ~" F2 o
- osKernelStart();* k2 O5 p3 \7 m' p/ P3 w% |- H8 t* A
- /* USER CODE END 2 */5 C6 j5 H" G, ]
- /*
% f( L4 w" n, y% i$ H0 x4 d r- d& } - .........7 X% m1 U$ B! y0 \6 p) \- |
- */
! C( B+ j& u" Q# J6 ~ - }
复制代码
) B/ E: M1 K+ ^! z$ ]; m0 m5. 编译下载
9 p K5 y! h4 |' e7 p7 ?& j1.使用make命令编译工程,这里的-j12表示使用多线程编译,可以提高速度,12表示电脑核心数。
$ k4 ~. H$ A, Jmake -j12
) [5 E* F4 C, q" E- J
' {7 m- y a: T8 c: Z- j
F8 ^; W4 ]' D! B* Q4 J2 W1 N% t& a* l
2. 使用STM32Cubeprogrammer下载位于/build中的固件STM32F429ZI_Harmony_LiteOS_M.hex
6 N6 M/ k9 @6 C3 l! M7 d0 t9 v8 ]- i: o0 Z
& e/ H) \& _1 Q O0 g
3 s% e* M7 G' m1 I/ v3. 观察到LED交替闪烁,串口助手打印出了调试信息。
8 r' A9 X4 @$ C/ ^. p5 K( ]- u9 O! D* Y
LED 交替闪烁3 L* n6 o- [2 E2 x( H5 l |$ P
) M2 |* C# a; r
5 G$ l G4 c5 i2 n! H
1 E: _+ P6 a9 ?& @- X) z- s串口输出信息
& _3 p( G* B0 a: k3 h G
& |6 ]+ z: O- H) m
7 A( P* G; P8 @& T" u8 ~
; R5 z G/ k; G/ U5 t: o总结
+ g. ^1 `, D" V, J8 B- D总的来说,移植的难点还是在于对 Makefile 相关工具链的理解与应用。由于有CMSIS_OS的封装,轻度使用时,与FreeRTOS感受相差不大。对新手来说使用FreeRTOS进行入门还是不错的选择,建议基本了解 FreeRTOS 之后再深入学习 LiteOS-M 并掌握二者之间的差别。
2 v) N' ?$ B8 q- ^) S. `( d4 ~————————————————, X2 P# ]$ o; O( O8 [& d
版权声明:PeidzzZ9 T5 q* E0 ]3 B8 u) O$ n
. |+ A' K/ d" h! D9 F! b
$ x3 B0 B b1 j |