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