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