【精选】【STM32】STM32 移植鸿蒙操作系统

您所在的位置:网站首页 nove3鸿蒙智联 【精选】【STM32】STM32 移植鸿蒙操作系统

【精选】【STM32】STM32 移植鸿蒙操作系统

2023-10-18 06:38| 来源: 网络整理| 查看: 265

前言

随着 OpenHarmony3.1 的正式发布,其功能也在不断完善。OpenHarmony LiteOS-M 内核是面向IoT领域构建的轻量级物联网操作系统内核,具有小体积、低功耗、高性能的特点,其代码结构简单,主要包括内核最小功能集、内核抽象层、可选组件以及工程目录等,分为硬件相关层以及硬件无关层,硬件相关层提供统一的HAL(Hardware Abstraction Layer)接口,提升硬件易适配性,不同编译工具链和芯片架构的组合分类,满足AIoT类型丰富的硬件和编译工具链的拓展。本文主要介绍如何在STM32上移植 OpenHarmony LiteOS-M 内核,及其注意事项。

一、开发环境

硬件: - STM32F429I-DISC1 开发板 在这里插入图片描述 软件: - VSCode:用于编辑代码 - STM32CubeMX:用于生成工程 - make、arm-none-eabi-gcc:用于编译工程 - STM32Cubeprogrammer:用于下载工程 - Git:用于获取 OpenHarmony LiteOS-M 内核源码

二、移植内核 1. 操作流程 拉取仓库代码。使用STM32CubeMX在 /target 目录下生成工程。修改Makefile文件,工程加入 OpenHarmony LiteOS-M 内核所需的文件。添加用户代码以支持printf。添加用户自定义任务。编译下载程序 2. 获取源码 进入https://gitee.com/openharmony/kernel_liteos_m,获取Git仓库地址。 https://gitee.com/openharmony/kernel_liteos_m.git

在这里插入图片描述

使用Git Bush,拉取内核源码到本地。 在这里插入图片描述创建 /third_party 目录,用于存放第三方依赖文件(STM32 所需的 CMSIS 等),拉取第三方依赖文件。 cd kernel_liteos_m mkdir ./third_party cd third_party git clone https://gitee.com/openharmony/third_party_bounds_checking_function.git ./bounds_checking_function git clone https://gitee.com/openharmony/third_party_cmsis.git ./cmsis git clone https://gitee.com/openharmony/third_party_musl.git ./musl

在这里插入图片描述 到这里 OpenHarmony LiteOS-M 内核源码就获取完毕了。

3. 生成工程

进入/targets 目录,使用 STM32CubeMX 生成工程 STM32F429ZI_Harmony_LiteOS_M 在这里插入图片描述

与FreeRTOS类似,由于LiteOS会占用SysTick定时器,因此需要修改HAL库延时的基础时钟,改为其他非SysTick的定时器,避免HAL库延时的定时器和系统运行的定时器冲突。在这里插入图片描述

配置:下载调试端口SW、串口USART、LED_GPIO、时钟树。 在这里插入图片描述

开发环境选择 Makefile 在这里插入图片描述

Code Generator 中一定要选择 Copy only necessary library files ! 如果选择所有库文件都添加的话,那么就会生成很多模板文件。由于我们需要在 Makefile 中添加文件,如果目录中有模板文件的话,我们就无法直接使用筛选功能将所有源文件快速添加到工程中了。 在这里插入图片描述 至此工程配置已结束,点击 Generate 即可生成工程。

4. 修改工程文件 使用 VS Code 打开targets下的工程目录,新建liteos_file_path.mk用于将内核源码文件添加到工程Makefile中,该文件相当于C语言中的头文件,主 Makefile 文件可以直接包含该文件。 在这里插入图片描述添加内核源文件目录到 liteos_file_path.mk 中。 # Topdir 顶层目录 LITEOSTOPDIR := ../../ LITEOSTOPDIR := $(realpath $(LITEOSTOPDIR)) # Common 内核源文件及头文件目录 C_SOURCES += \ $(wildcard $(LITEOSTOPDIR)/kernel/src/*.c) \ $(wildcard $(LITEOSTOPDIR)/kernel/src/mm/*.c) \ $(wildcard $(LITEOSTOPDIR)/components/cpup/*.c) \ $(wildcard $(LITEOSTOPDIR)/components/power/*.c) \ $(wildcard $(LITEOSTOPDIR)/components/backtrace/*.c) \ $(wildcard $(LITEOSTOPDIR)/components/exchook/*.c) \ $(wildcard $(LITEOSTOPDIR)/components/signal/*.c) \ $(wildcard $(LITEOSTOPDIR)/utils/*.c) C_INCLUDES += \ -I$(LITEOSTOPDIR)/utils \ -I$(LITEOSTOPDIR)/kernel/include \ -I$(LITEOSTOPDIR)/components/cpup \ -I$(LITEOSTOPDIR)/components/power \ -I$(LITEOSTOPDIR)/components/backtrace \ -I$(LITEOSTOPDIR)/components/exchook \ -I$(LITEOSTOPDIR)/components/signal # Third party related 第三方依赖文件及头文件目录 C_SOURCES += \ $(wildcard $(LITEOSTOPDIR)/third_party/bounds_checking_function/src/*.c)\ $(wildcard $(LITEOSTOPDIR)/kal/cmsis/*.c)\ $(wildcard $(LITEOSTOPDIR)/kal/posix/src/*.c) C_INCLUDES += \ -I$(LITEOSTOPDIR)/third_party/bounds_checking_function/include \ -I$(LITEOSTOPDIR)/third_party/bounds_checking_function/src\ -I$(LITEOSTOPDIR)/third_party/cmsis/CMSIS/RTOS2/Include \ -I$(LITEOSTOPDIR)/third_party/musl/porting/liteos_m/kernel/include\ -I$(LITEOSTOPDIR)/kal/cmsis \ -I$(LITEOSTOPDIR)/kal/posix/include \ -I$(LITEOSTOPDIR)/kal/posix/musl_src/internal # Arch related ASM_SOURCES += $(wildcard $(LITEOSTOPDIR)/arch/arm/cortex-m4/gcc/*.s) ASMS_SOURCES += $(wildcard $(LITEOSTOPDIR)/arch/arm/cortex-m4/gcc/*.S) C_SOURCES += $(wildcard $(LITEOSTOPDIR)/arch/arm/cortex-m4/gcc/*.c) C_INCLUDES += -I. \ -I$(LITEOSTOPDIR)/arch/include \ -I$(LITEOSTOPDIR)/arch/arm/cortex-m4/gcc CFLAGS += -nostdinc -nostdlib ASFLAGS += -imacros $(LITEOSTOPDIR)/kernel/include/los_config.h -DCLZ=CLZ # list of ASM .S program objects OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASMS_SOURCES:.S=.o))) vpath %.S $(sort $(dir $(ASMS_SOURCES))) $(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR) $(CC) -c $(CFLAGS) $(ASFLAGS) $< -o $@

这里注意:最后一行前面的缩进必须为tab,而不是空格。否则编译会报错。

修改项目Makefile 在Makefile中包含liteos_file_path.mk 在这里插入图片描述增加*.S文件的编译规则 # list of ASM .S program objects OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASMS_SOURCES:.S=.o))) vpath %.S $(sort $(dir $(ASMS_SOURCES))) $(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR) $(CC) -c $(CFLAGS) $(ASFLAGS) $< -o $@

在这里插入图片描述

添加 target_config.h 用于配置裁剪内核。该文件相当于FreeRTOS的FreeRTOSConfig.h /**@defgroup los_config System configuration items * @ingroup kernel */ #ifndef _TARGET_CONFIG_H #define _TARGET_CONFIG_H #include "stm32f4xx.h" #include "stm32f4xx_it.h" #ifdef __cplusplus #if __cplusplus extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ /*============================================================================= System clock module configuration =============================================================================*/ #define OS_SYS_CLOCK SystemCoreClock #define LOSCFG_BASE_CORE_TICK_PER_SECOND (1000UL) #define LOSCFG_BASE_CORE_TICK_HW_TIME 0 #define LOSCFG_BASE_CORE_TICK_WTIMER 0 #define LOSCFG_BASE_CORE_TICK_RESPONSE_MAX SysTick_LOAD_RELOAD_Msk /*============================================================================= Hardware interrupt module configuration =============================================================================*/ #define LOSCFG_PLATFORM_HWI 0 #define LOSCFG_USE_SYSTEM_DEFINED_INTERRUPT 0 #define LOSCFG_PLATFORM_HWI_LIMIT 128 /*============================================================================= Openharmony Kernel configuration =============================================================================*/ /*============================================================================= Task module configuration =============================================================================*/ #define LOSCFG_BASE_CORE_TSK_LIMIT 24 #define LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE (0x500U) #define LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE (0x2D0U) #define LOSCFG_BASE_CORE_TSK_MIN_STACK_SIZE (0x130U) #define LOSCFG_BASE_CORE_TIMESLICE 1 #define LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT 20000 /*============================================================================= Semaphore module configuration =============================================================================*/ #define LOSCFG_BASE_IPC_SEM 1 #define LOSCFG_BASE_IPC_SEM_LIMIT 48 /*============================================================================= Mutex module configuration =============================================================================*/ #define LOSCFG_BASE_IPC_MUX 1 #define LOSCFG_BASE_IPC_MUX_LIMIT 24 /*============================================================================= Queue module configuration =============================================================================*/ #define LOSCFG_BASE_IPC_QUEUE 1 #define LOSCFG_BASE_IPC_QUEUE_LIMIT 24 /*============================================================================= Software timer module configuration =============================================================================*/ #define LOSCFG_BASE_CORE_SWTMR 1 #define LOSCFG_BASE_CORE_SWTMR_ALIGN 1 #define LOSCFG_BASE_CORE_SWTMR_LIMIT 48 /*============================================================================= Memory module configuration =============================================================================*/ #define LOSCFG_MEM_MUL_POOL 1 #define OS_SYS_MEM_NUM 20 /*============================================================================= Exception module configuration =============================================================================*/ #define LOSCFG_PLATFORM_EXC 1 /*============================================================================= TestSuite configuration =============================================================================*/ #define LOSCFG_TEST 0 #ifndef LOSCFG_BACKTRACE_TYPE #define LOSCFG_BACKTRACE_TYPE 1 #endif /** * @ingroup los_config * Configuration backtrace depth. */ #ifndef LOSCFG_BACKTRACE_DEPTH #define LOSCFG_BACKTRACE_DEPTH 15 #endif #ifdef __cplusplus #if __cplusplus } #endif /* __cplusplus */ #endif /* __cplusplus */ #endif /* _TARGET_CONFIG_H */ 修改链接脚本文件 STM32F407ZGTx_FLASH.ld 添加程序起始地址 _sstack = 0x20000000; /* start of RAM */添加.text 段的起始地址,这是链接脚本的语法,将当前位置地址赋值给_stext。_stext = .; 在这里插入图片描述 修改中断服务函数 Core\Src\stm32f4xx_it.c 添加 LiteOS 头文件在PendSV异常中进入LiteOS HalPendSV 异常处理函数,进行任务切换操作在SysTick中断服务函数添加OsTickHandler函数,为系统提供时间基准 #include "los_arch_context.h" #include "los_tick.h" /* ......... */ void PendSV_Handler(void) { /* USER CODE BEGIN PendSV_IRQn 0 */ HalPendSV(); /* USER CODE END PendSV_IRQn 0 */ /* USER CODE BEGIN PendSV_IRQn 1 */ /* USER CODE END PendSV_IRQn 1 */ } /* ......... */ void SysTick_Handler(void) { /* USER CODE BEGIN SysTick_IRQn 0 */ OsTickHandler(); /* USER CODE END SysTick_IRQn 0 */ /* USER CODE BEGIN SysTick_IRQn 1 */ /* USER CODE END SysTick_IRQn 1 */ } /* ......... */ 修改串口映射 Core\Src\main.c 包含头文件#include "stdio.h"修改串口映射以支持printf /* USER CODE BEGIN 0 */ #if 1 int _write(int fd, char *ptr, int len) { osStatus_t result; osKernelState_t state; if (osKernelGetState() == osKernelInactive) { //系统未启动时不使用DMA HAL_UART_Transmit(&huart1, ptr, len, 0xFFFF); return len; } else { //获取信号,如果上一个DMA传输完成 //信号就能获取到,没有传输完成任务就挂起 //等到传输完成再恢复 result = osSemaphoreAcquire(UART1_TX_DMA_SemaphoreHandle, 0xFFFF); if (result == osOK) { HAL_UART_Transmit_DMA(&huart1, ptr, len); //获取成功,发送数据 return len; } else { return -1; //获取失败 } } } #endif // DMA 传输完成后会调用传输完成回调函数,在该函数中我们释放信号 void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == huart1.Instance) osSemaphoreRelease(UART1_TX_DMA_SemaphoreHandle); } /* USER CODE END 0 */ 添加测试任务 Core\Src\main.c 包含os头文件#include "cmsis_os.h"增加测试任务 /* ......... */ #include "cmsis_os.h" /* ......... */ /* USER CODE BEGIN PV */ osSemaphoreId_t UART1_TX_DMA_SemaphoreHandle; const osSemaphoreAttr_t UART1_TX_DMA_Semaphore_attributes = { .name = "UART1_TX_DMA_Semaphore", }; osThreadId_t uart_taskHandle; const osThreadAttr_t uart_task_attributes = { .name = "uart_task", .stack_size = 512 * 2, .priority = (osPriority_t)osPriorityNormal3, }; /* USER CODE END PV */ /* ......... */ /* USER CODE BEGIN 0 */ /* ......... */ void Uart_Task(void *argument) { HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET); while (1) { HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin); HAL_GPIO_TogglePin(LED_R_GPIO_Port, LED_R_Pin); printf("System Runing!!!\r\n"); osDelay(1000); } } /* USER CODE END 0 */ /* ......... */ int main(){ /* ......... */ /* USER CODE BEGIN 2 */ osKernelInitialize(); printf("System Init!\r\n"); UART1_TX_DMA_SemaphoreHandle = osSemaphoreNew(1, 1, &UART1_TX_DMA_Semaphore_attributes); uart_taskHandle = osThreadNew(Uart_Task, NULL, &uart_task_attributes); osKernelStart(); /* USER CODE END 2 */ /* ......... */ } 5. 编译下载 使用make命令编译工程,这里的-j12表示使用多线程编译,可以提高速度,12表示电脑核心数。 make -j12

在这里插入图片描述 2. 使用STM32Cubeprogrammer下载位于/build中的固件STM32F429ZI_Harmony_LiteOS_M.hex 在这里插入图片描述 3. 观察到LED交替闪烁,串口助手打印出了调试信息。

LED 交替闪烁 请添加图片描述

串口输出信息 在这里插入图片描述

总结

总的来说,移植的难点还是在于对 Makefile 相关工具链的理解与应用。由于有CMSIS_OS的封装,轻度使用时,与FreeRTOS感受相差不大。对新手来说使用FreeRTOS进行入门还是不错的选择,建议基本了解 FreeRTOS 之后再深入学习 LiteOS-M 并掌握二者之间的差别。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3