环境:STM32-407ZG开发板,上层openharmony SDK,freertos的操作系统, 使用FATFS

路径
build--存放编译生成的一些库文件,可执行文件
cmake--cmake方式编译工具链的目录,此处不用
core--stm32的基本功能
drivers--stm32的相关外设(包括iic,adc等的相关功能)
FATFS--FAT文件系统的接口目录
libs--编译出来的openharmony库文件路径
middlewares--stm32自带的中间件路径
user--存放自己适配的的延时,内存分配,disck读写等接口文件
thirdparty--从oh移植过来的第三方接口路径
xtssrc--为了xts测试新增接口新建的路径
xtsinc--

步骤一:创建虚拟设备并编译

  1. 创建虚拟设备
  • 拷贝vir_device/device_qemu_L0_xts_demo 到 device/qemu/ 并重命名为L0_xts_demo
  • 拷贝vir_device/vendor_ohemu_L0_xts_demo 到vendor/ohemu/ 并重命名为L0_xts_demo
  1. 子系统配置
  • 子系统配置 vendor/ohemu/L0_xts_demo/config.json 默认有L0认证所必要的子系统,可以根据自己实际情况裁剪和添加。配置如下:
{
  "product_name": "L0_xts_demo",
  "type": "mini",
  "version": "3.0",
  "ohos_version": "OpenHarmony 1.0",
  "device_company": "qemu",
  "device_build_path": "device/qemu/L0_xts_demo",
  "board": "L0_xts_demo",
  "kernel_type": "liteos_m",
  "kernel_version": "3.0.0",
  "subsystems": [
    {
      "subsystem": "hiviewdfx",
      "components": [
        { "component": "hilog_lite", "features": [] },
        { "component": "hievent_lite", "features": [] }
      ]
    },
    {
      "subsystem": "systemabilitymgr",
      "components": [
        { "component": "samgr_lite", "features":[] }
      ]
    },
    {
      "subsystem": "security",
      "components": [
        { "component": "device_auth" },
        { "component": "huks", "features":
          [
            "huks_use_lite_storage = true",
            "huks_config_file = \"hks_config_lite.h\""
          ]
        }
      ]
    },
    {
      "subsystem": "startup",
      "components": [
        { "component": "bootstrap_lite" },
        { "component": "init", "features":
          [
            "enable_ohos_startup_init_feature_begetctl_liteos = true"
          ]
        }
      ]
    },
    {
      "subsystem": "commonlibrary",
      "components": [
        { "component": "utils_lite",
          "features":[ "utils_lite_feature_kal_timer = true" ]
        }
      ]
    },
    {
      "subsystem": "xts",
      "components": [
        { "component": "acts", "features":[] },
        { "component": "tools", "features":[] }
      ]
    }
  ],

  "third_party_dir": "//third_party",
  "product_adapter_dir": "//vendor/ohemu/L0_xts_demo/hals"
}
  1. 工具链配置
  • 编译工具链配置 device/qemu/L0_xts_demo/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_cpu = "riscv32"

# 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 toolchain.
board_toolchain = "arm-none-eabi-gcc"
#board_toolchain = "riscv32-unknown-elf"

use_board_toolchain = true

# The toolchain path installed, it's not mandatory if you have added toolchain path to your ~/.bashrc.
board_toolchain_path = ""

# Compiler prefix.
board_toolchain_prefix = "arm-none-eabi-"
#board_toolchain_prefix = "riscv32-unknown-elf-"

# Compiler type, "gcc" or "clang".
board_toolchain_type = "gcc"

#Debug compiler optimization level options
board_opt_flags = [
  "-mcpu=cortex-a5",
  "-mthumb",
  "-mfpu=fpv4-sp-d16",
  "-mfloat-abi=hard",
]

# Board related common compile flags.
board_cflags = [
  "-mthumb",
  "-Wall",
  "-fdata-sections",
  "-ffunction-sections",
  "-fno-builtin",
  "-fno-strict-aliasing",
  "-fsigned-char",
  "-std=c99",
  "-O2",
  "-DUSE_HAL_DRIVER",
  "-D__LITEOS_M__",
]
board_cflags += board_opt_flags

board_asmflags = [
  "-Og",
  "-Wall",
  "-fdata-sections",
  "-ffunction-sections",
]
board_asmflags += board_opt_flags

board_cxx_flags = board_cflags

board_ld_flags = []

# Newlib adapt.
board_ld_flags += [
  "-Wl,--wrap=_free_r",
  "-Wl,--wrap,_malloc_usable_size_r",
  "-Wl,--wrap,_malloc_r",
  "-Wl,--wrap,_memalign_r",
  "-Wl,--wrap,_realloc_r",
  "-Wl,--wrap,_calloc_r",
]

# Board related headfiles search path.
board_include_dirs = [ "//utils/native/lite/include" ,
                        "//commonlibrary/utils_lite/include"
                      ]

# Board adapter dir for OHOS components.
board_adapter_dir = "//device/qemu/L0_xts_demo/driver"

# Sysroot path.
board_configed_sysroot = ""

# Board storage type, it used for file system generation.
storage_type = "spinor"
  1. 编译配置
  • 执行命令并选择L0_xts_demo
hb set
  1. XTS编译
hb build -f -b debug --gn-args build_xts=true

编译完成后,把out/L0_xts_demo/L0_xts_demo/libs 生成的静态库,拷贝到第三方RTOS工程目录libs中。
如果编译工具链为arm-none-eabi-gcc,则可以直接拷贝此工程生成的.a到第三方RTOS工程目录libs中,无需重复以上步骤

步骤二:静态库移植

在第三方RTOS工程上按如下步骤添加相关内容

  1. ld链接文件修改
  • 在ld文件 SECTIONS.text 段中添加如下OpenHarmony 专有段
_hdf_drivers_start = .;
KEEP(*(.hdf.driver))
_hdf_drivers_end = .; /* define a section for hdf driver */

__zinitcall_bsp_start = .;
KEEP (*(.zinitcall.bsp0.init))
KEEP (*(.zinitcall.bsp1.init))
KEEP (*(.zinitcall.bsp2.init))
KEEP (*(.zinitcall.bsp3.init))
KEEP (*(.zinitcall.bsp4.init))
__zinitcall_bsp_end = .;
__zinitcall_device_start = .;
KEEP (*(.zinitcall.device0.init))
KEEP (*(.zinitcall.device1.init))
KEEP (*(.zinitcall.device2.init))
KEEP (*(.zinitcall.device3.init))
KEEP (*(.zinitcall.device4.init))
__zinitcall_device_end = .;
__zinitcall_core_start = .;
KEEP (*(.zinitcall.core0.init))
KEEP (*(.zinitcall.core1.init))
KEEP (*(.zinitcall.core2.init))
KEEP (*(.zinitcall.core3.init))
KEEP (*(.zinitcall.core4.init))
__zinitcall_core_end = .;
__zinitcall_sys_service_start = .;
KEEP (*(.zinitcall.sys.service0.init))
KEEP (*(.zinitcall.sys.service1.init))
KEEP (*(.zinitcall.sys.service2.init))
KEEP (*(.zinitcall.sys.service3.init))
KEEP (*(.zinitcall.sys.service4.init))
__zinitcall_sys_service_end = .;
__zinitcall_sys_feature_start = .;
KEEP (*(.zinitcall.sys.feature0.init))
KEEP (*(.zinitcall.sys.feature1.init))
KEEP (*(.zinitcall.sys.feature2.init))
KEEP (*(.zinitcall.sys.feature3.init))
KEEP (*(.zinitcall.sys.feature4.init))
__zinitcall_sys_feature_end = .;
__zinitcall_run_start = .;
KEEP (*(.zinitcall.run0.init))
KEEP (*(.zinitcall.run1.init))
KEEP (*(.zinitcall.run2.init))
KEEP (*(.zinitcall.run3.init))
KEEP (*(.zinitcall.run4.init))
__zinitcall_run_end = .;
__zinitcall_app_service_start = .;
KEEP (*(.zinitcall.app.service0.init))
KEEP (*(.zinitcall.app.service1.init))
KEEP (*(.zinitcall.app.service2.init))
KEEP (*(.zinitcall.app.service3.init))
KEEP (*(.zinitcall.app.service4.init))
__zinitcall_app_service_end = .;
__zinitcall_app_feature_start = .;
KEEP (*(.zinitcall.app.feature0.init))
KEEP (*(.zinitcall.app.feature1.init))
KEEP (*(.zinitcall.app.feature2.init))
KEEP (*(.zinitcall.app.feature3.init))
KEEP (*(.zinitcall.app.feature4.init))
__zinitcall_app_feature_end = .;
__zinitcall_test_start = .;
KEEP (*(.zinitcall.test0.init))
KEEP (*(.zinitcall.test1.init))
KEEP (*(.zinitcall.test2.init))
KEEP (*(.zinitcall.test3.init))
KEEP (*(.zinitcall.test4.init))
__zinitcall_test_end = .;
__zinitcall_exit_start = .;
KEEP (*(.zinitcall.exit0.init))
KEEP (*(.zinitcall.exit1.init))
KEEP (*(.zinitcall.exit2.init))
KEEP (*(.zinitcall.exit3.init))
KEEP (*(.zinitcall.exit4.init))
__zinitcall_exit_end = .;

添加位置示意:

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 1024K
}

/* Define output sections */
SECTIONS
{
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH

  /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

/**********把OHOS专有段添加到这里**************/
    _hdf_drivers_start = .;
    …… 
    __zinitcall_exit_end = .;
/************end****************************/
    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH

  /* Constant data goes into FLASH */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH
  ……
}
  1. 添加静态库
  • 以下添加静态库以Makefile为例,其它平台添加方法有差异,但添加的文件内容不变。
LIBS = -lc -lm -lnosys \
    -Wl,--whole-archive \
    libs/libbootstrap.a libs/libbroadcast.a \
    libs/libsamgr.a libs/libnative_file.a \
    libs/libhilog_lite_static.a \
    libs/libhiview_lite_static.a libs/libhievent_lite_static.a \
    libs/libsamgr_source.a libs/libsamgr_adapter.a \
    libs/libhal_file_static.a libs/libhal_token_static.a \
    libs/libhal_sysparam.a \
    libs/libbegetutil.a \
    libs/libhuks_3.0_sdk.a \
    libs/libparam_client_lite.a \
    libs/libmbedtls.a \
    libs/libinit_utils.a \
    libs/libudidcomm.a \
    libs/libinit_log.a \
    libs/libdevattest_sdk.a \
    libs/libdevattest_core.a \
    libs/libcjson_static.a \
    libs/libhctest.a \
    libs/libmodule_ActsBootstrapTest.a \
    libs/libmodule_ActsSamgrTest.a \
    libs/libmodule_ActsDfxFuncTest.a \
    libs/libmodule_ActsHieventLiteTest.a \
    libs/libmodule_ActsHuksHalFunctionTest.a \
    libs/libmodule_ActsUpdaterFuncTest.a \
    libs/libhuks_test_common.a \
    -Wl,--no-whole-archive

有3个要注意的点:

  • OHOS 提供的库必须用-Wl,--whole-archive和-Wl,--no-whole-archive包含,这样会把.a中的所有符号全量链接到可执行文件中
  • 静态库的依赖必须放在本文件之后,上面的添加顺序就是调整后的正常依赖关系。
  • 类似libmodele_xxxxTest.a是xts相关子系统的执行内容。如果需要删除或添加子系统,只需要移除相应的.a或者添加.a到以上位置
  • 随着版本更替,有些测试套件已经被废弃,因此测试库文件也可能会发生变更,此外不同的设备支持的测试项也不完全相同,因而最后的库文件也可能不完全相同

    步骤三:源文件移植

  • 源文件移植以要包括bounds_checking_funcation移植、newLibc移植、wifi接口实现等
此处先将最后的源文件、头文件以及库文件贴出来
######################################
# source
######################################
# C sources
C_SOURCES =  \
Core/Src/main.c \
Core/Src/gpio.c \
Core/Src/freertos.c \
Core/Src/spi.c \
Core/Src/usart.c \
Core/Src/stm32f4xx_it.c \
Core/Src/stm32f4xx_hal_msp.c \
FATFS/Target/user_diskio.c \
FATFS/App/fatfs.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c \
Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_usart.c \
Core/Src/system_stm32f4xx.c \
third_party/bounds_checking_function/src/vsnprintf_s.c \
third_party/bounds_checking_function/src/fscanf_s.c \
third_party/bounds_checking_function/src/fwscanf_s.c \
third_party/bounds_checking_function/src/gets_s.c \
third_party/bounds_checking_function/src/memcpy_s.c \
third_party/bounds_checking_function/src/memmove_s.c \
third_party/bounds_checking_function/src/memset_s.c \
third_party/bounds_checking_function/src/scanf_s.c \
third_party/bounds_checking_function/src/securecutil.c \
third_party/bounds_checking_function/src/secureinput_a.c \
third_party/bounds_checking_function/src/secureinput_w.c \
third_party/bounds_checking_function/src/secureprintoutput_a.c \
third_party/bounds_checking_function/src/secureprintoutput_w.c \
third_party/bounds_checking_function/src/snprintf_s.c \
third_party/bounds_checking_function/src/sprintf_s.c \
third_party/bounds_checking_function/src/sscanf_s.c \
third_party/bounds_checking_function/src/strcat_s.c \
third_party/bounds_checking_function/src/strcpy_s.c \
third_party/bounds_checking_function/src/strncat_s.c \
third_party/bounds_checking_function/src/strncpy_s.c \
third_party/bounds_checking_function/src/strtok_s.c \
third_party/bounds_checking_function/src/swprintf_s.c \
third_party/bounds_checking_function/src/swscanf_s.c \
third_party/bounds_checking_function/src/vfscanf_s.c \
third_party/bounds_checking_function/src/vfwscanf_s.c \
third_party/bounds_checking_function/src/vscanf_s.c \
third_party/bounds_checking_function/src/vsprintf_s.c \
third_party/bounds_checking_function/src/vsscanf_s.c \
third_party/bounds_checking_function/src/vswprintf_s.c \
third_party/bounds_checking_function/src/vswscanf_s.c \
third_party/bounds_checking_function/src/vwscanf_s.c \
third_party/bounds_checking_function/src/wcscat_s.c \
third_party/bounds_checking_function/src/wcscpy_s.c \
third_party/bounds_checking_function/src/wcsncat_s.c \
third_party/bounds_checking_function/src/wcsncpy_s.c \
third_party/bounds_checking_function/src/wcstok_s.c \
third_party/bounds_checking_function/src/wmemcpy_s.c \
third_party/bounds_checking_function/src/wmemmove_s.c \
third_party/bounds_checking_function/src/wscanf_s.c \
third_party/libc/newlib/porting/src/fs.c \
third_party/libc/newlib/porting/src/malloc.c \
third_party/libc/newlib/porting/src/other_adapt.c \
third_party/libc/newlib/porting/src/time.c \
third_party/libc/newlib/porting/src/network/htonl.c \
third_party/libc/newlib/porting/src/network/htons.c \
third_party/libc/newlib/porting/src/network/ntohl.c \
third_party/libc/newlib/porting/src/network/ntohs.c \
Middlewares/Third_Party/FatFs/src/diskio.c \
Middlewares/Third_Party/FatFs/src/ff.c \
Middlewares/Third_Party/FatFs/src/ff_gen_drv.c \
Middlewares/Third_Party/FatFs/src/option/syscall.c \
Middlewares/Third_Party/FreeRTOS/Source/croutine.c \
Middlewares/Third_Party/FreeRTOS/Source/event_groups.c \
Middlewares/Third_Party/FreeRTOS/Source/list.c \
Middlewares/Third_Party/FreeRTOS/Source/queue.c \
Middlewares/Third_Party/FreeRTOS/Source/stream_buffer.c \
Middlewares/Third_Party/FreeRTOS/Source/tasks.c \
Middlewares/Third_Party/FreeRTOS/Source/timers.c \
Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.c \
Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c \
Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c \
xtsSrc/xtsAdd.c \
user/w25qxx/w25qxx.c \
user/delay/delay.c \
Middlewares/Third_Party/FatFs/src/option/cc936.c \



# C includes
C_INCLUDES =  \
-ICore/Inc \
-IDrivers/STM32F4xx_HAL_Driver/Inc \
-IDrivers/STM32F4xx_HAL_Driver/Inc/Legacy \
-IMiddlewares/Third_Party/FreeRTOS/Source/include \
-IMiddlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 \
-IMiddlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F \
-IDrivers/CMSIS/Device/ST/STM32F4xx/Include \
-IDrivers/CMSIS/Include \
-IxtsInc \
-Ithird_party/bounds_checking_function/include \
-Ithird_party/libc/newlib/porting/include \
-Ithird_party/musl/include \
-IxtsInc \
-IFATFS/Target \
-IFATFS/App \
-IMiddlewares/Third_Party/FatFs/src \
-Iuser/sys \
-Iuser/w25qxx \
-Iuser/delay



# libraries
#LIBS = -lm -lnosys
LIBS = -lc -lm -lnosys \
    -Wl,--whole-archive \
    libs/libbootstrap.a libs/libbroadcast.a \
    libs/libsamgr.a libs/libnative_file.a \
    libs/libhilog_lite_static.a libs/libhiview_lite_static.a libs/libhievent_lite_static.a \
    libs/libsamgr_source.a libs/libsamgr_adapter.a \
    libs/libhal_file_static.a libs/libhal_token_static.a \
    libs/libhal_sysparam.a \
    libs/libbegetutil.a \
    libs/libhuks_3.0_sdk.a \
    libs/libparam_client_lite.a \
    libs/libmbedtls.a \
    libs/libinit_utils.a \
    libs/libudidcomm.a \
    libs/libinit_log.a \
    libs/libdevattest_sdk.a \
    libs/libdevattest_core.a \
    libs/libcjson_static.a \
    libs/libhctest.a \
    libs/libmodule_ActsBootstrapTest.a \
    libs/libmodule_ActsSamgrTest.a \
    libs/libmodule_ActsDfxFuncTest.a \
     libs/libmodule_ActsHieventLiteTest.a \
     libs/libmodule_ActsHuksHalFunctionTest.a \
     libs/libmodule_ActsUpdaterFuncTest.a \
    libs/libhuks_test_common.a \
    -Wl,--no-whole-archive
  1. bounds_checking_funcation
  • 这个是OpenHarmony依赖的安全函数实现,添加到Makefile中
third_party/bounds_checking_function为oh的代码,原样移植
third_party/libc/newlib为新建
xtsInc 为新建
具体内容见上,此处不赘述
third_party/libc/newlib/porting/src/fs.c \
third_party/libc/newlib/porting/src/malloc.c \
third_party/libc/newlib/porting/src/other_adapt.c \
third_party/libc/newlib/porting/src/time.c \
third_party/libc/newlib/porting/src/network/htonl.c \
third_party/libc/newlib/porting/src/network/htons.c \
third_party/libc/newlib/porting/src/network/ntohl.c \
third_party/libc/newlib/porting/src/network/ntohs.c \
从oh移植,根据实际情况适当修改即可(一般freertos都有对应的底层接口)
xtsSrc/xtsAdd.c \
自行补充
  1. newLibc移植
  • newLibc这个不是必要的,如果RTOS工程中有相应的libc,或者有相应依赖的接口实现,就不需要移植。如果没有,以下几组接口是必须实现的

  • 内存管理 third_party/libc/newlib/porting/src/malloc.c \
  • 内存的分配和释放使用RTOS的相应接口实现。而对_malloc_r的依赖是在工具链配置里面强制指定的。
  • 文件位置:device/qemu/L0_xts_demo/liteos_m/config.gni
# Newlib adapt.
board_ld_flags += [
  "-Wl,--wrap=_free_r",
  "-Wl,--wrap,_malloc_usable_size_r",
  "-Wl,--wrap,_malloc_r",
  "-Wl,--wrap,_memalign_r",
  "-Wl,--wrap,_realloc_r",
  "-Wl,--wrap,_calloc_r",
]
  • 示例
void *__wrap__malloc_r(struct _reent *reent, size_t nbytes)
{
    if (nbytes == 0) {
        return NULL;
    }

    // return LOS_MemAlloc(OS_SYS_MEM_ADDR, nbytes);
    return pvPortMalloc(nbytes);
    /* 此处调用freertos的内存分配函数 */
}

  • 文件系统依赖
  • OpenHarmony L0对文件系统依赖抽象化了标准的接口,RTOS工程需要完成相应的接口实现
  • 文件路径:third_party/libc/newlib/porting/src/fs.c (注意此处要根据使用的系统将LOS的文件操作接口替换为对应的rtos接口)
eg:(其他接口类似即可)
int HalFileOpen_new(FIL* fp, const char *path, int mode)
{
    int ret = 0;
    char tmpPath[LITTLEFS_MAX_LFN_LEN];
    if (HalFileGetPath_new(tmpPath, path)) {
        printf("HalFileOpen_new_get_path_err!!!\n");
        return -1;
    }

    ret = f_open(fp, tmpPath, mode);
    if (0 != ret) {
        printf("HalFileOpen_new_open_err!!!\n");
        //输出告警
    }

    return ret;
}
……

需要注意事项:

  • 在当前测试用例中我们选择用SPI访问STM的外置FLASH的方式读写测试文件。具体操作流程可以参考。如果使用不同的板子则需要根据实际引脚情况做调整
    https://blog.csdn.net/Edwinwzy/article/details/131554538
  • 特别注意,由于目前使用的是fat的文件系统,该文件系统与LOS的文件系统差异很大,(例如fat的文件系统句柄作为入参传递,返回值都是各种执行错误码。而LOS的文件系统句柄作为返回值传递。此外两者的句柄类型也不一致)因此导致上层的应用层代码也做了一些修改。
  • fat文件系统的使用,我们直接通过CUBEMAX勾选文件系统模块生成即可,底层的disk层接口则需要手动添加(有些存储模块的代码也可以通过CUBEMAX自己生成,如果没有就只能手动适配,STM32F407系列默认是W25Q128)
  • 适配时还需要注意两个文件系统的文件操作模式是否一致,不同的文件系统可能有不同的宏变量,记得根据语义调整为当前文件系统的读写宏。
  • FAT文件系统对于打开文件还有一些限制,比如不能直接用f_open打开多层目录的新文件,此处可以根据实际情况选择是否将多层目录转化为单层目录,或者先用f_opendir接口打开。
  • FAT文件系统中没有直接返回文件长度的接口,但是可以通过f_stat接口读取文件信息再解析文件长度
  • 对于长文件的支持,对于FAT文件系统而言,超过8个字符长度的就算是长文件,需要在配置文件中做相应修改。此处需要注意的是选择用静态变量而不是动态分配内存存储长文件名,可以节省移植内存池相关代码的工作内容
  • STM32F407系列板子初始分配给堆的存储空间可能不够,需要在FreeRTOSConfig.h修改 configTOTAL_HEAP_SIZE 大小,此例中从15K扩展到50K。
  • xts 认证会详细测试接口的返回值,不同的文件系统接口返回会有些许不同。比如OpenHarmony对打开文件有32个数限制,lseek()对越界返回值会有不同,需要根据自己的文件系统的差异,对返回值做些许调整
  • xts对目录有要求,比如kv_store需要有data目录,在调试时,可添加相应依赖目录

  1. wifi依赖的接口实现
  • wifi依赖的接口在xtsSrc/xtsAdd.c中。可根据具体的硬件提供wifi接口的实现
……
tips:由于有些板子不支持wifi功能,因此此处可根据实际情况调整(对于不支持的直接返回OK即可)
WifiErrorCode EnableWifi(void)
{
    return WIFI_SUCCESS;
}

int IsWifiActive(void)
{
    return 1;
}

WifiErrorCode AdvanceScan(WifiScanParams *params)
{
    return WIFI_SUCCESS;
}

WifiErrorCode DisableWifi(void)
{
    return WIFI_SUCCESS;
}
……
  1. 其它依赖的接口
  • xts认证信息都是通过串口打印输出来进行交互,确保printf()能正常输出日志
  • 在xtsSrc/xtsAdd.c文件,还有一些其它的接口需要实现。以下是对其它接口的描述:
tips:此处调用rtos的接口即可
/**
 * @brief 延时函数
 * 
 * @param value 延时单位ms
 */
void sleep(int value)
{
    osDelay(value * 1000);//使用CMSIS中 osDelay的实现
}

/**
 * @brief 使能硬件看门狗
 * 
 */
void IoTWatchDogEnable(void)
{
}

/**
 * @brief 看门狗喂狗
 * 在xts部分线程中会循环执行较长时间,会调用当前
 * 函数喂狗,防止硬件复位
 */
void IoTWatchDogKick(void)
{
}

/**
 * @brief IoTWatchDogDisable 禁止看门狗
 * 
 */
void IoTWatchDogDisable(void)
{
}

/**
 * @brief 创建互斥锁
 * 
 * @param mutex 
 * @param mutexAttr 
 * @return int 
 */
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexAttr)
{
    return 0;
}

/**
 * @brief 上锁
 * 
 * @param mutex 
 * @return int 
 */
int pthread_mutex_lock(pthread_mutex_t *mutex)
{
    return 1;
}

/**
 * @brief 解锁
 * 
 * @param mutex 
 * @return int 
 */
int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
    return 22;
}

/**
 * @brief 进入临界区
 * 
 * @return uint32_t 保存状态寄存器
 */
uint32_t ArchIntLock(void)
{
    return osKernelLock();//使用CMSIS中的实现
}

/**
 * @brief 恢复现场
 * 
 * @param intSave 恢复状态寄存器
 */
void ArchIntRestore(uint32_t intSave)
{
    osKernelRestoreLock(intSave);//使用CMSIS中的实现
}

/**
 * @brief 得到当前时钟
 * 
 * @param clock_id 
 * @param tp 
 * @return int 
 */
int clock_gettime(clockid_t clock_id, struct timespec *tp)
{
    uint32_t tick = osKernelGetTickCount();
    tp->tv_sec = tick / 1000;
    tp->tv_nsec = tick;
    return 0;
}

/**
 * @brief 得到当前任务的消息队列ID
 * 消息队列ID在创建任务时,由第二个参数带入
 * @return void* 
 */
extern void *OnGetCurrentTcbUserPara(void);
void *osThreadGetArgument(void)
{
    if (osThreadGetId() == 0) {
        return 0;
    }
    return OnGetCurrentTcbUserPara();//根据RTOS特性,返回任务创建时的第二个参数值
}

步骤四:xts调试

  1. 产品信息修改
  • 在目录vendor\ohemu\L0_xts_demo\hals\utils\sys_param\hal_sys_param.c中修改成自己的产品信息
static const char OHOS_DEVICE_TYPE[] = {"****"};
static const char OHOS_DISPLAY_VERSION[] = {"OpenHarmony 1.0.1"};
static const char OHOS_MANUFACTURE[] = {"****"};
static const char OHOS_BRAND[] = {"****"};
static const char OHOS_MARKET_NAME[] = {"****"};
static const char OHOS_PRODUCT_SERIES[] = {"****"};
static const char OHOS_PRODUCT_MODEL[] = {"****"};
static const char OHOS_SOFTWARE_MODEL[] = {"****"};
static const char OHOS_HARDWARE_MODEL[] = {"****"};
static const char OHOS_HARDWARE_PROFILE[] = {"aout:true,display:true"};
static const char OHOS_BOOTLOADER_VERSION[] = {"bootloader"};
static const char OHOS_ABI_LIST[] = {"****"};
static const char OHOS_SERIAL[] = {"1234567890"};  // provided by OEM.
static const int OHOS_FIRST_API_VERSION = 1;
  1. 打印分析
  • 在确保printf()能正常输出的情况下,在调用OHOS_SystemInit()后,会输出如下打印
hilog will init.
hievent will init.
hievent init success.
[HCtest Service] HCTest Framework inited.
******To Obtain Product Params Start******
The Product Type is [****]
The manuFacture is [****]
The brand is [****]
The marketName is [****]
The productSeries is [****]
The softwareModel is [****]
The HardwareModel is [****]
The HardwareProfile is [aout:true,display:true]
The serial is [1234567890]
The osName is [OpenHarmony-1.0.1.0(Beta)]
The OS Version is [OpenHarmony 1.0.1]
The bootloaderVersion is [bootloader]
The Security Patch is [2021-09-01]
The AbiList is [****]
The sdkApiLevel is [6]
The firstApiLevel is [1]
The incrementalVersion is [OpenHarmony 2.3 beta]
The productModel is [****]
The VersionID is [****/****/****/****/OpenHarmony-1.0.1.0(Beta)/****/****/6/OpenHarmony 2.3 beta/debug]
The buildType is [debug]
The buildUser is [jenkins]
The buildHost is [linux]
The buildTime is [1658764026025]
The BuildRootHash is []
******To Obtain Product Params End  ******
hiview Start to init succrun test sess.

XTS正常打印格式

hiview Start to init succrun test sess.
uite:ParameterFuncTestSuite
01-01 00:00:00.000 0 0 D 0/HIVIEW: log limit init success.
01-01 00:00:00.000 0 0 I 1/SAMGR: Bootstrap core services(count:12).
01-01 00:00:00.000 0 0 I 1/SAMGR: Init service:0x802fdc4
01-01 00:00:00.000 0 0 I 1/SAMGR: Init service:0x802fdd0
01-01 00:00:00.000 0 0 I 1/SAMGR: Init service:0x8030200
01-01 00:00:00.000 0 0 I 1/SAMGR: Init service:0x8030c74
01-01 00:00:00.000 0 0 I 1/SAMGR: Init service:0x8033298
01-01 00:00:00.000 0 0 I 1/SAMGR: Init service:0x80332a8
01-01 00:00:00.000 0 0 I 1/SAMGR: Init service:0x8033508
01-01 00:00:00.000 0 0 I 1/SAMGR: Init service:0x8033520
01-01 00:00:00.000 0 0 I 1/SAMGR: Init service:0x8033514
01-01 00:00:00.000 0 0 I 1/SAMGR: Init service:0x803352c
01-01 00:00:00.000 0 0 I 1/SAMGR: Init service:0x8033548
01-01 00:00:00.000 0 0 I 1/SAMGR: Init service:0x8033558
01-01 00:00:00.000 0 152 I 1/SAMGR: Init service 0x802fdd0 <time: 1ms> success!
01-01 00:00:00.000 0 152 I 1/SAMGR: Init service 0x803352c <time: 1ms> success!
01-01 00:00:00.000 0 24 I 1/SAMGR: Init service 0x802fdc4 <time: 1ms> success!
01-01 00:00:00.000 0 24 I 1/SAMGR: Init service 0x8033298 <time: 1ms> success!
01-01 00:00:00.000 0 24 I 1/SAMGR: Init service 0x80332a8 <time: 1ms> success!
01-01 00:00:00.000 0 152 I 1/SAMGR: Init service 0x8030c74 <time: 2ms> success!
01-01 00:00:00.000 0 216 I 1/SAMGR: Init service 0x8033514 <time: 3ms> success!
01-01 00:00:00.000 0 88 I 1/SAMGR: Init service 0x8033548 <time: 3ms> success!
01-01 00:00:00.000 0 88 I 1/SAMGR: Init service 0x8033558 <time: 3ms> success!
01-01 00:00:00.000 0 24 I 1/SAMGR: Init service 0x8030200 <time: 5ms> success!
01-01 00:00:00.000 0 24 I 1/SAMGR: Init service 0x8033520 <time: 8ms> success!
01-01 00:00:00.000 0 88 I 1/SAMGR: Init service 0x8033508 <time: 8ms> success!

Run test suite 1 times
Device Type=****
../../../test/xts/acts/startup_lite/syspara_hal/src/parameter_func_test.c:61:testObtainSysPara001:PASS
Manufacture=****
../../../test/xts/acts/startup_lite/syspara_hal/src/parameter_func_test.c:73:testObtainSysPara002:PASS
Brand=****
……
+-------------------------------------------+

-----------------------
7 Tests 0 Failures 0 Ignored 
OK
Start to run test suite:HieventLiteTestSuite
Run test suite 1 times
……
+-------------------------------------------+

-----------------------
32 Tests 0 Failures 0 Ignored 
OK
All the test suites finished!

附件:定位问题

  1. 编译过程
    按照步骤即可,一般不会有问题
  2. 添加静态库
    由于版本变更,编译生成的的库文件可能改名,例如从libhilog_lite.a到libhilog_lite_static.a,具体信息可以从build.gn文件中查询
  3. 关于接口的移植与适配
    对于不冲突且满足当前需求的接口,直接移植即可,注意同时将依赖移植过来,记得同步修改makefile或者其他编译脚本,移植时注意解耦
  4. 当前部分接口可能与newlibc自带的库函数有冲突,例如/usr/include/newlib/time.h包含了clock_gettime的头文件,我们只需完成其实现即可,而不要重复定义头文件,不然会报错,此处注意修改入参使其相匹配。此处应该还可以修改配置使用自定义的头文件不依赖newlib库文件的定义,暂未找到如何修改
  5. 此处生成的工程文件为附带系统的,此处是rtos系统,所以很多功能的实现可以直接调用系统提供的接口,注意匹配即可
  6. 关于调试,此处重写printf接口,使其重定向到usart函数。HAL_USART_Transmit 函数用于通过USART发送数据。具体实现方式为重写_write接口令其调用usart接口,如此当printf需要输出字符时,会调用_write接口从而实现将字符输出到串口打印,因为此处_write接口被用作串口输出,接口被占用,如果有其他的地方要使用该接口还要注意取舍。具体实现可自行百度
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐