stm32系列芯片移植openhrmony3.0 liteos_m
之前找了很多文章,但是由于本身这方面文章较少加上官网文档太过简洁,移植过程比较繁琐,特此纪录。 附上最终模板地址:https://gitee.com/emb-y/hm3-to-stm32
一、创建stm32cubemx模板工程 为了方便移植先使用stm32cubemx生成模板工程, 以stm32f411为例
文章图片
当然要用嵌软人的helloworld–点灯来证明是否移植成功
这块核心板的led在pc13,直接用cubemx生成一个模板程序
文章图片
这里只初始化pc13为Output
文章图片
只需要设置一个名字以及把工具链设置为MakeFile,然后点击生成即可。
工程目录如下:
文章图片
二、添加鸿蒙需要的配置文件以及修改MakeFile 该处参考连志安老师的帖子和鸿蒙官方文档
添加target_config.h到项目根目录
#ifndef _TARGET_CONFIG_H
#define _TARGET_CONFIG_H#include "stm32f4xx.h"#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus *//*=============================================================================
System clock module configuration
=============================================================================*/
#define OS_SYS_CLOCKSystemCoreClock
#define LOSCFG_BASE_CORE_TICK_PER_SECOND(1000UL)
#define LOSCFG_BASE_CORE_TICK_HW_TIME0
#define LOSCFG_BASE_CORE_TICK_WTIMER0
#define LOSCFG_BASE_CORE_TICK_RESPONSE_MAXSysTick_LOAD_RELOAD_Msk/*=============================================================================
Hardware interrupt module configuration
=============================================================================*/
#define LOSCFG_PLATFORM_HWI1
#define LOSCFG_USE_SYSTEM_DEFINED_INTERRUPT1
#define LOSCFG_PLATFORM_HWI_LIMIT128
/*=============================================================================
Task module configuration
=============================================================================*/
#define LOSCFG_BASE_CORE_TSK_LIMIT24
#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_TIMESLICE1
#define LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT20000
/*=============================================================================
Semaphore module configuration
=============================================================================*/
#define LOSCFG_BASE_IPC_SEM1
#define LOSCFG_BASE_IPC_SEM_LIMIT48
/*=============================================================================
Mutex module configuration
=============================================================================*/
#define LOSCFG_BASE_IPC_MUX1
#define LOSCFG_BASE_IPC_MUX_LIMIT24
/*=============================================================================
Queue module configuration
=============================================================================*/
#define LOSCFG_BASE_IPC_QUEUE1
#define LOSCFG_BASE_IPC_QUEUE_LIMIT24
/*=============================================================================
Software timer module configuration
=============================================================================*/
#define LOSCFG_BASE_CORE_SWTMR1
#define LOSCFG_BASE_CORE_SWTMR_ALIGN0
#define LOSCFG_BASE_CORE_SWTMR_LIMIT48
/*=============================================================================
Memory module configuration
=============================================================================*/
#define LOSCFG_MEM_MUL_POOL1
#define OS_SYS_MEM_NUM20
/*=============================================================================
Exception module configuration
=============================================================================*/
#define LOSCFG_PLATFORM_EXC1
/* =============================================================================
printf module configuration
============================================================================= */
#define LOSCFG_KERNEL_PRINTF1#define LOSCFG_BASE_CORE_SCHED_SLEEP1#define LOSCFG_SYS_HEAP_SIZE0x4000UL#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */#endif /* _TARGET_CONFIG_H */
该文件为liteos_m的配置文件
添加build.sh文件到根目录
#!/bin/bashset -eOUT_DIR="$1"
TOOLCHAIN_DIR="$2"function main(){
ROOT_DIR=$(cd $(dirname "$0");
pwd)
if [ -z "${TOOLCHAIN_DIR}" ];
then
make clean &&make -j16 OUT_DIR_PATH=${OUT_DIR}
else
make clean &&make -j16 OUT_DIR_PATH=${OUT_DIR} TOOLCHAIN_DIR_PATH=${TOOLCHAIN_DIR}
fi
}main "$@"
该文件为编译脚本
在根目录下新建liteos_m文件夹并添加config.gni文件
# Kernel type, e.g. "linux", "liteos_a", "liteos_m".
kernel_type = "liteos_m"# Kernel version.
kernel_version = "3.0.0"# Board CPU type, e.g. "cortex-a7", "riscv32".
board_cpu = "cortex-m4"# Board arch, e.g."armv7-a", "rv32imac".
board_arch = ""# Toolchain name used for system compiling.
# E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang,riscv32-unknown-elf.
# Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain.
board_toolchain = "arm-none-eabi-gcc"# The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc.
board_toolchain_path = ""# Compiler prefix.
board_toolchain_prefix = "arm-none-eabi-"# Compiler type, "gcc" or "clang".
board_toolchain_type = "gcc"# Board related common compile flags.
board_cflags = [
"-mcpu=cortex-m4",
"-mfpu=fpv4-sp-d16",
"-mfloat-abi=hard",
"-mthumb",
"-Og",
"-fdata-sections",
"-ffunction-sections",
"-DUSE_HAL_DRIVER", # 视情况修改!!!!!!!!!!!
"-DSTM32F411xE", # 视情况修改!!!!!!!!!!!
]
board_cxx_flags = board_cflagsboard_ld_flags = []# Board related headfiles search path.
# 视情况修改!!!!!!!!!!!
board_include_dirs = [
"//kernel/liteos_m/kernel/arch/arm/cortex-m4/gcc",
"//device/st/stm32f411core",
"//device/st/stm32f411core/Core/Inc",
"//device/st/stm32f411core/Drivers/CMSIS/Include",
"//device/st/stm32f411core/Drivers/CMSIS/Device/ST/STM32F4xx/Include",
"//device/st/stm32f411core/Drivers/STM32F4xx_HAL_Driver/Inc",
"//device/st/stm32f411core/third_party/LWIP",
"//drivers/framework/support/platform/include/common",
"//kernel/liteos_m/kal/cmsis",
]# Board adapter dir for OHOS components.
board_adapter_dir = ""# Sysroot path.
board_configed_sysroot = ""# Board storage type, it used for file system generation.
storage_type = ""
其中board_cflags 的最后两项需要按照芯片修改makefile中可以找到对应选项
board_include_dirs 为依赖的头文件目录,需要自行修改
修改Makefile文件
# File automatically-generated by tool: [projectgenerator] version: [3.13.0-B3] date: [Fri Apr 30 08:31:16 CST 2021]
########################################################################################################################### ------------------------------------------------
# Generic Makefile (based on gcc)
#
# ChangeLog :
# 2017-02-10 - Several enhancements + project update mode
#2015-07-22 - first version
# ------------------------------------------------######################################
# target
######################################
TARGET = stm32f411core_ninjia#######################################
# paths
#######################################
# Build path
BUILD_DIR = $(OUT_DIR_PATH)#######################################
# toolchain paths
#######################################
# Toolchain path
ifneq ($(TOOLCHAIN_DIR_PATH), )
GCC_PATH = $(TOOLCHAIN_DIR_PATH)
endif#######################################
# binaries
#######################################
PREFIX = arm-none-eabi-
# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
# either it can be added to the PATH environment variable.
ifneq ($(GCC_PATH), )
CC = $(GCC_PATH)/$(PREFIX)gcc
AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
CP = $(GCC_PATH)/$(PREFIX)objcopy
SZ = $(GCC_PATH)/$(PREFIX)size
else
CC = $(PREFIX)gcc
AS = $(PREFIX)gcc -x assembler-with-cpp
CP = $(PREFIX)objcopy
SZ = $(PREFIX)size
endif
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S
#######################################
# CFLAGS
#######################################
# cpu
CPU = -mcpu=cortex-m4# fpu
FPU = -mfpu=fpv4-sp-d16# float-abi
FLOAT-ABI = -mfloat-abi=hard# mcu
MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)#######################################
# LDFLAGS
#######################################
# link script
LDSCRIPT = STM32F411CEUx_FLASH.ld # 视情况修改!!!!!!!!!!!# libraries
# 视情况修改!!!!!!!!!!!
STATIC_LIB = -larch -lbacktrace -lcmsis -lcore -lcpup -lexchook -lkernel \
-lsec_static -lpm -lstartup_stm32f411xe -lSTM32F4xx_HAL_Driver -lutils \
-lhdf_core -lhdf_osal_lite
STATIC_LIB_DIR = -L$(BUILD_DIR)/libs
LIBS = -lc -lm -lnosys
LIBDIR =
LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin#######################################
# build the application
#######################################
$(BUILD_DIR)/$(TARGET).elf: Makefile
$(CC) $(STATIC_LIB_DIR) -Wl,--whole-archive -Wl,--start-group $(STATIC_LIB) -Wl,--end-group -Wl,--no-whole-archive $(LDFLAGS) -o $@
$(SZ) $@$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(HEX) $< $@
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(BIN) $< $@
$(BUILD_DIR):
mkdir -p $@#######################################
# clean up
#######################################
clean:
-rm -fR $(BUILD_DIR)# *** EOF ***
其中LDSCRIPT 为生成的ld文件需要修改
STATIC_LIB 为链接.a文件的选项需要修改(如果不知道怎么写可以先编译,在鸿蒙源码的out目录下找到需要链接的lib文件)
配置各级目录下的BUILD.gn脚本
根目录下:
import("//build/lite/config/component/lite_component.gni")group("stm32f411core") {
}build_ext_component("stm32f411core_ninjia") {
exec_path = rebase_path(".", root_build_dir)
outdir = rebase_path("$root_out_dir")
print("$board_toolchain")if (board_toolchain_path != "") {
toolchain_path = rebase_path("$board_toolchain_path")
command = "./build.sh ${outdir} ${toolchain_path}"
} else {
command = "./build.sh ${outdir}"
}
deps = [ "//build/lite:ohos" ]
}static_library("startup_stm32f411xe") {
sources = [ "startup_stm32f411xe.s" ]include_dirs = [ "." ]deps = [
"//drivers/adapter/khdf/liteos_m:hdf_lite",
"//device/st/stm32f411core/Core:core",
"//device/st/stm32f411core/Drivers/STM32F4xx_HAL_Driver:STM32F4xx_HAL_Driver",
]
}
其中sources 为cubemx生成的.s文件的名称
group及build_ext_component视情况修改
deps 为下级gn文件列表
Drivers\STM32F4xx_HAL_Driver下的BUILD.gn:
static_library("STM32F4xx_HAL_Driver") {
sources = [
"Src/stm32f4xx_hal_tim.c",
"Src/stm32f4xx_hal_tim_ex.c",
"Src/stm32f4xx_hal_rcc.c",
"Src/stm32f4xx_hal_rcc_ex.c",
"Src/stm32f4xx_hal_flash.c",
"Src/stm32f4xx_hal_flash_ex.c",
"Src/stm32f4xx_hal_flash_ramfunc.c",
"Src/stm32f4xx_hal_gpio.c",
"Src/stm32f4xx_hal_dma_ex.c",
"Src/stm32f4xx_hal_dma.c",
"Src/stm32f4xx_hal_pwr.c",
"Src/stm32f4xx_hal_pwr_ex.c",
"Src/stm32f4xx_hal_cortex.c",
"Src/stm32f4xx_hal.c",
"Src/stm32f4xx_hal_exti.c",
]include_dirs = [
"Inc",
"Inc/Legacy",
"../CMSIS/Include",
"../CMSIS/Device/ST/STM32F4xx/Include",
"//kernel/liteos_m/kal/cmsis",
"../../Core/Inc",
]}
【harmony|手把手教你移植openharmony3.0到stm32(liteos_m)】source及include_dirs是c文件和头文件目录,视情况修改
Core下的BUILD.gn:
static_library("core") {
sources = [
"Src/main.c",
"Src/stm32f4xx_hal_msp.c",
"Src/stm32f4xx_it.c",
"Src/system_stm32f4xx.c",
]include_dirs = [
"Inc",
"../",
"../Drivers/STM32F4xx_HAL_Driver/Inc",
"../Drivers/CMSIS/Include",
"../Drivers/CMSIS/Device/ST/STM32F4xx/Include",
"//kernel/liteos_m/kernel/include",
"//kernel/liteos_m/utils",
"//kernel/liteos_m/kernel/arch/include",
"//kernel/liteos_m/kal/cmsis"
]
}
source及include_dirs是c文件和头文件目录,视情况修改
修改main.c文件
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os2.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void *LedTask(const char *arg);
static void LedExampleEntry(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//**
* @briefThe application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
osKernelInitialize();
/* USER CODE END SysInit *//* Initialize all configured peripherals *//* USER CODE BEGIN 2 */
LedExampleEntry();
/* USER CODE END 2 */
osKernelStart();
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
osDelay(500);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = https://www.it610.com/article/RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
/*Configure GPIO pin : PC13 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}/* USER CODE BEGIN 4 */
static void *LedTask(const char *arg)
{
(void)arg;
while(1)
{
osDelay(500);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 0);
osDelay(500);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 1);
}
return NULL;
}static void LedExampleEntry(void)
{
osThreadAttr_t attr;
MX_GPIO_Init();
attr.name ="LedTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 1024;
attr.priority = 13;
if (osThreadNew((osThreadFunc_t)LedTask, NULL, &attr) == NULL) {
printf("[LedExample] Falied to create LedTask!\n");
}
}
/* USER CODE END 4 *//**
* @briefThis function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}#ifdefUSE_FULL_ASSERT
/**
* @briefReports the name of the source file and the source line number
*where the assert_param error has occurred.
* @paramfile: pointer to the source file name
* @paramline: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
该例程采用cmsis,就是最简单的创建了一个任务,在任务中让灯闪烁。
文章图片
按照鸿蒙官方的要求规范目录结构
修改stm32cubemx项目名为stm32f411core
规则为:
device/厂商名称/板卡名称
新建ventor文件夹
创建如下目录结构:
文章图片
在config.json文件中写入:
{
"product_name": "stm32f411core",
"ohos_version": "OpenHarmony 1.0",
"device_company": "st",
"board": "stm32f411core",
"kernel_type": "liteos_m",
"kernel_version": "3.0.0",
"subsystems": [
{
"subsystem": "kernel",
"components": [
{ "component": "liteos_m",
"features":[
"enable_ohos_kernel_liteos_m_fs = false",
"enable_ohos_kernel_liteos_m_kal = false"
]
}
]
}
],
"vendor_adapter_dir": "//device/st/stm32f411core",
"third_party_dir": "//third_party",
"product_adapter_dir": "",
"ohos_product_type":"",
"ohos_manufacture":"",
"ohos_brand":"",
"ohos_market_name":"",
"ohos_product_series":"",
"ohos_product_model":"",
"ohos_software_model":"",
"ohos_hardware_model":"",
"ohos_hardware_profile":"",
"ohos_serial":"",
"ohos_bootloader_version":"",
"ohos_secure_patch_level":"",
"ohos_abi_list":""
}
该文件为鸿蒙的编译选项配置,可参考鸿蒙官方文档
在BUILD.gn中写入:
group("gd32f303_qidian") {
}
在hdf.hcs中写入:
//#include "../../../../device/hisilicon/hispark_taurus/sdk_liteos/config/uart/uart_config.hcs"#include "device_info/device_info.hcs"root {
module = "st,stm32_chip";
}
在device_info.hcs中写入:
root {
device_info {
match_attr = "hdf_manager";
template host {
hostName = "";
priority = 100;
template device {
template deviceNode {
policy = 0;
priority = 100;
preload = 0;
permission = 0664;
moduleName = "";
serviceName = "";
deviceMatchAttr = "";
}
}
}
platform :: host {
hostName = "platform_host";
priority = 50;
device_uart :: device {
device0 :: deviceNode {
policy = 1;
priority = 40;
permission = 0644;
moduleName = "HDF_PLATFORM_UART";
serviceName = "HDF_PLATFORM_UART_0";
deviceMatchAttr = "hisilicon_hi35xx_uart_0";
}
}
}
}
}
三、将自己写的工程文件移入鸿蒙源码 该处采用全量代码
此处略过鸿蒙hpm等配置(通过鸿蒙官网设备开发3.0的工具可以自动化配置)
下载arm-none-eabi-gcc、gn、ninja工具链并配置环境变量
并复制目录到鸿蒙源码对应目录
文章图片
文章图片
这时候激活鸿蒙官方的python虚拟环境(如果使用官方工具配置环境需要这一步)
source /opt/Huawei/DevEco-Device-Tool/core/deveco-venv/bin/activate
在源码更目录终端下输入hb set可以看到自己设置的开发板编译选项
文章图片
回车选择后输入
hb build
即可开始编译
四、修改报错问题 如果不出会遇到报错
有两处错误可能是因为工作人员粗心
文章图片
这里的PRINT_ERR少了一个参数,我直接补了个字符串。(这个问题现在开源社区已经修复了)
还有一处是也是输出报错,uint32_t类型打印时传的是%u,这个也可能是编译器问题
另一处我猜测是我编译配置有问题,但是这个地方为了省事我直接把一个编译选项屏蔽掉了
文章图片
最后再此编译,令人激动的时刻到来了
文章图片
在out目录下可以看到.bin文件
文章图片
五、烧录验证 打开STM32 ST-Link Utility烧录到开发板
文章图片
按下开发板rst键
文章图片
可以看到led闪烁,移植成功!
推荐阅读
- OpenHarmony|【OpenHarmony】VSCode下移植 LiteOS-M 到STM32
- #|VSCode 搭建 STM32 开发环境
- 学习记录|C语言学习(1)VScode配置C语言环境(超详细)
- 鸿蒙硬件开发|鸿蒙硬件开发(HarmonyOS下的LiteOS-M)
- harmonyos|HarmonyOS新手入门设备开发的“芯”路历程
- STM32|STM32之俄罗斯方块
- C语言|嵌入式机考笔试之C语言数组问题
- STM32|STM32之LWIP网络协议栈连接腾讯云
- stm32|【记录STM32H7 IAP跳转失败】