diff --git a/CMakeLists.txt b/CMakeLists.txt index 119d72a..83b59eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,8 @@ set(LIB_RUN_TYPE "$ENV{LIB_RUN_TYPE}" ) set(HOME_PATH "$ENV{HOME_PATH}" ) set(BUILD_MACHINE_PLATFORM "$ENV{BUILD_MACHINE_PLATFORM}" ) set(RPROTON_BINARY_DIR "$ENV{RPROTON_BINARY_DIR}" ) +#用于保存所有的对象库 +set(ALL_OBJECT_LIBRARYS "" CACHE STRING INTERNAL) if("${RPROTON_BINARY_DIR}" STREQUAL "") # this branch will be taken @@ -75,6 +77,18 @@ include_directories( ./platform/libboundscheck/include ) +if (${CONFIG_OS_OPTION_POSIX}) +include_directories( + ./src/osal/posix/include + ./src/include/posix +) +endif() + +if (${CONFIG_OS_OPTION_OPENAMP}) +include_directories( + ./thirdpart/openamp +) +endif() if (NOT ${COMPILE_OPTION} STREQUAL "UniProton") ###添加安全库的cmakelists diff --git a/README.OpenSource b/README.OpenSource index 5f4bbd1..fcaf89e 100644 --- a/README.OpenSource +++ b/README.OpenSource @@ -3,7 +3,7 @@ "Name" : "uniproton", "License" : "MulanPSL-2.0", "License File" : "LICENSE", - "Version Number" : "1.0.0", + "Version Number" : "1.0.1", "Owner" : "zhushengle@huawei.com", "Upstream URL" : "https://gitee.com/openeuler/UniProton", "Description" : "Uniproton is a highly real-time kernel implementation of the MulanPSL-2.0 license" diff --git a/README.md b/README.md index 2777e39..ebec828 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,19 @@ # UniProton介绍 -UniProton主要目的在于为上层业务软件提供一个统一的操作系统平台,屏蔽底层硬件差异,并提供强大的调试功能。使得业务软件可在不同的硬件平台之间快速移植,方便产品芯片选型,降低硬件采购成本和软件维护成本。 +UniProton是一款实时操作系统,具备极致的低时延和灵活的混合关键性部署特性,可以适用于工业控制场景,既支持微控制器MCU,也支持算力强的多核CPU。 ## 功能介绍 -- 任务 -- 中断 -- 事件 -- 队列 -- 信号量 -- 内存管理 -- 软件定时器 -- 异常 -- 错误处理 -- cpu占用率 +- [任务](./doc/design/task.md) +- [中断](./doc/design/hwi.md) +- [事件](./doc/design/event.md) +- [队列](./doc/design/queue.md) +- [信号量](./doc/design/sem.md) +- [内存管理](./doc/design/mem.md) +- [软件定时器](./doc/design/timer.md) +- [异常](./doc/design/exc.md) +- [错误处理](./doc/design/err.md) +- [cpu占用率](./doc/design/cpup.md) 注: UniProton基础内核机制请参考[官方介绍](https://gitee.com/openeuler/UniProton)。 @@ -53,7 +53,7 @@ alientek ## 约束 -- 当前开源版本仅支持cortex_m4芯片,默认编译脚本的安全编译选项仅支持栈保护,其他选项由用户根据需要自行添加。 +- 当前开源版本支持cortex_m4和armv8芯片,默认编译脚本的安全编译选项仅支持栈保护,其他选项由用户根据需要自行添加。 - 遵循MulanPSL2开源许可协议。 diff --git a/build/uniproton_ci_lib/globle.py b/build/uniproton_ci_lib/globle.py index 967c0cb..6e71ba9 100644 --- a/build/uniproton_ci_lib/globle.py +++ b/build/uniproton_ci_lib/globle.py @@ -25,10 +25,14 @@ home_path = os.path.dirname(build_dir) config_dir = os.path.join(home_path,'config.xml') kbuild_path = '%s/cmake/common/build_auxiliary_script' % home_path -cpus_ = {'all': ['clean', 'm4'], +cpus_ = {'all': ['clean', 'm4', 'raspi4', 'hi3093'], 'clean':['clean'], - 'm4': ['m4'] + 'm4': ['m4'], + 'raspi4': ['raspi4'], + 'hi3093': ['hi3093'], } -cpu_plat = {'m4': ['cortex'] +cpu_plat = {'m4': ['cortex'], + 'raspi4': ['armv8'], + 'hi3093': ['armv8'], } diff --git a/build/uniproton_config/config_armv8_hi3093/defconfig b/build/uniproton_config/config_armv8_hi3093/defconfig new file mode 100644 index 0000000..8086510 --- /dev/null +++ b/build/uniproton_config/config_armv8_hi3093/defconfig @@ -0,0 +1,133 @@ +# +# Automatically generated file; DO NOT EDIT. +# UniProton Configuration +# + +# +# Arch Modules Configuration +# +CONFIG_OS_ARCH_ARMV8=y +# CONFIG_OS_OPTION_GUARD_STACK is not set + +# +# ARMV8 Sepecfic Configuration +# +CONFIG_INTERNAL_OS_PLATFORM_ARMV8_AX=y +CONFIG_INTERNAL_OS_HI3093=y + +# +# ARMV8 DRV Features Configuration +# +CONFIG_INTERNAL_OS_GIC_VER="gicv600" +CONFIG_OS_GIC_VER=3 + +# +# Generic Configuration +# +CONFIG_OS_HARDWARE_PLATFORM="OS_ARMV8" +CONFIG_OS_CPU_TYPE="OS_HI3093" +CONFIG_OS_MAX_CORE_NUM=4 +CONFIG_OS_THIS_CORE=3 +CONFIG_INTERNAL_OS_BYTE_ORDER_LE=y +CONFIG_OS_BYTE_ORDER="OS_LITTLE_ENDIAN" +# CONFIG_OS_OPTION_DCACHE is not set +CONFIG_OS_CACHE_LINE_SIZE=64 + +# +# Core Modules Configuration +# + +# +# IPC Modules Configuration +# + +# +# Event feature configuration +# +CONFIG_OS_OPTION_EVENT=y +CONFIG_OS_OPTION_QUEUE=y + +# +# Semaphore feature configuration +# + +# +# Kernel Modules Configuration +# + +# +# IRQ Modules Configuration +# +# CONFIG_OS_OPTION_HWI_COMBINE is not set +CONFIG_OS_OPTION_HWI_PRIORITY=y +CONFIG_OS_OPTION_HWI_ATTRIBUTE=y +# CONFIG_OS_OPTION_HWI_MAX_NUM_CONFIG is not set + +# +# Exc Modules Configuration +CONFIG_INTERNAL_OS_SCHEDULE_SINGLE_CORE_BY_CCODE=y +CONFIG_OS_OPTION_SYS_TIME_USR=y +# + +# +# Task module Configuration +# +CONFIG_OS_OPTION_TASK=y + +# +# TASK features configuration +# +# CONFIG_OS_OPTION_TASK_MON is not set +CONFIG_OS_OPTION_TASK_DELETE=y +CONFIG_OS_OPTION_TASK_SUSPEND=y +CONFIG_OS_OPTION_TASK_INFO=y +CONFIG_OS_OPTION_TASK_YIELD=y +CONFIG_OS_TSK_PRIORITY_HIGHEST=0 +CONFIG_OS_TSK_PRIORITY_LOWEST=63 +CONFIG_OS_TSK_NUM_OF_PRIORITIES=64 +CONFIG_OS_TSK_CORE_BYTES_IN_PID=2 +CONFIG_OS_OPTION_TICK=y + +# +# Timer Modules Configuration +# +CONFIG_INTERNAL_OS_SWTMR=y + +# +# MM Modules Configuration +# + +# +# OM Modules Configuration +# +# CONFIG_OS_OPTION_CPUP is not set + +# +# CPUP features configuration +# +CONFIG_INTERNAL_OS_CPUP_THREAD=y +CONFIG_OS_OPTION_CPUP_WARN=y + +# +# Error Report Module Configuration +# + +# +# Hook feature configuration +# + +# +# security Modules Configuration +# +CONFIG_OS_OPTION_RND=y + +# +# Utility Modules Configuration +# +CONFIG_OS_OPTION_POSIX=y +CONFIG_OS_POSIX_TYPE_NEWLIB=y + +# +# Openamp Modules Configuration +# +CONFIG_OS_OPTION_OPENAMP=y diff --git a/build/uniproton_config/config_armv8_raspi4/defconfig b/build/uniproton_config/config_armv8_raspi4/defconfig new file mode 100644 index 0000000..9f2dff4 --- /dev/null +++ b/build/uniproton_config/config_armv8_raspi4/defconfig @@ -0,0 +1,133 @@ +# +# Automatically generated file; DO NOT EDIT. +# UniProton Configuration +# + +# +# Arch Modules Configuration +# +CONFIG_OS_ARCH_ARMV8=y +# CONFIG_OS_OPTION_GUARD_STACK is not set + +# +# ARMV8 Sepecfic Configuration +# +CONFIG_INTERNAL_OS_PLATFORM_ARMV8_AX=y +CONFIG_INTERNAL_OS_RASPI4=y + +# +# ARMV8 DRV Features Configuration +# +CONFIG_INTERNAL_OS_GIC_VER="gicv600" +CONFIG_OS_GIC_VER=2 + +# +# Generic Configuration +# +CONFIG_OS_HARDWARE_PLATFORM="OS_ARMV8" +CONFIG_OS_CPU_TYPE="OS_RASPI4" +CONFIG_OS_MAX_CORE_NUM=4 +CONFIG_OS_THIS_CORE=3 +CONFIG_INTERNAL_OS_BYTE_ORDER_LE=y +CONFIG_OS_BYTE_ORDER="OS_LITTLE_ENDIAN" +# CONFIG_OS_OPTION_DCACHE is not set +CONFIG_OS_CACHE_LINE_SIZE=64 + +# +# Core Modules Configuration +# + +# +# IPC Modules Configuration +# + +# +# Event feature configuration +# +CONFIG_OS_OPTION_EVENT=y +CONFIG_OS_OPTION_QUEUE=y + +# +# Semaphore feature configuration +# + +# +# Kernel Modules Configuration +# + +# +# IRQ Modules Configuration +# +# CONFIG_OS_OPTION_HWI_COMBINE is not set +CONFIG_OS_OPTION_HWI_PRIORITY=y +CONFIG_OS_OPTION_HWI_ATTRIBUTE=y +# CONFIG_OS_OPTION_HWI_MAX_NUM_CONFIG is not set + +# +# Exc Modules Configuration +CONFIG_INTERNAL_OS_SCHEDULE_SINGLE_CORE_BY_CCODE=y +CONFIG_OS_OPTION_SYS_TIME_USR=y +# + +# +# Task module Configuration +# +CONFIG_OS_OPTION_TASK=y + +# +# TASK features configuration +# +# CONFIG_OS_OPTION_TASK_MON is not set +CONFIG_OS_OPTION_TASK_DELETE=y +CONFIG_OS_OPTION_TASK_SUSPEND=y +CONFIG_OS_OPTION_TASK_INFO=y +CONFIG_OS_OPTION_TASK_YIELD=y +CONFIG_OS_TSK_PRIORITY_HIGHEST=0 +CONFIG_OS_TSK_PRIORITY_LOWEST=63 +CONFIG_OS_TSK_NUM_OF_PRIORITIES=64 +CONFIG_OS_TSK_CORE_BYTES_IN_PID=2 +CONFIG_OS_OPTION_TICK=y + +# +# Timer Modules Configuration +# +CONFIG_INTERNAL_OS_SWTMR=y + +# +# MM Modules Configuration +# + +# +# OM Modules Configuration +# +# CONFIG_OS_OPTION_CPUP is not set + +# +# CPUP features configuration +# +CONFIG_INTERNAL_OS_CPUP_THREAD=y +CONFIG_OS_OPTION_CPUP_WARN=y + +# +# Error Report Module Configuration +# + +# +# Hook feature configuration +# + +# +# security Modules Configuration +# +CONFIG_OS_OPTION_RND=y + +# +# Utility Modules Configuration +# +CONFIG_OS_OPTION_POSIX=y +CONFIG_OS_POSIX_TYPE_NEWLIB=y + +# +# Openamp Modules Configuration +# +CONFIG_OS_OPTION_OPENAMP=y diff --git a/build/uniproton_config/config_m4/defconfig b/build/uniproton_config/config_m4/defconfig index 7b79a8d..3323cf8 100644 --- a/build/uniproton_config/config_m4/defconfig +++ b/build/uniproton_config/config_m4/defconfig @@ -7,6 +7,7 @@ # Arch Modules Configuration # CONFIG_OS_ARCH_ARMV7_M=y +CONFIG_OS_OPTION_GUARD_STACK=y # # ARM7-M Sepecfic Configuration @@ -44,6 +45,9 @@ CONFIG_OS_OPTION_QUEUE=y # # Semaphore feature configuration # +CONFIG_OS_OPTION_BIN_SEM=y +CONFIG_OS_OPTION_SEM_RECUR_PV=y +CONFIG_OS_OPTION_SEM_PRIOR=y # # Kernel Modules Configuration @@ -114,3 +118,5 @@ CONFIG_OS_OPTION_RND=y # # Utility Modules Configuration # +CONFIG_OS_OPTION_POSIX=y +CONFIG_OS_POSIX_TYPE_NEWLIB=y diff --git a/cmake/common/build_auxiliary_script/Kconfig2macro.py b/cmake/common/build_auxiliary_script/Kconfig2macro.py index 0472e90..03106e6 100644 --- a/cmake/common/build_auxiliary_script/Kconfig2macro.py +++ b/cmake/common/build_auxiliary_script/Kconfig2macro.py @@ -162,6 +162,18 @@ def write_tail(out_file): return 0 +def wirte_buildef_header(out_file): + """ + wirte_buildef_header + :param out_file: + :return: + """ + with codecs.open(out_file, 'a+') as fd_out: + text = "\n/* common macros's definitions */\n" + text = '%s#include "prt_buildef_common.h"\n' % (text) + fd_out.write(text) + return 0 + def kconfig2macro(in_file, out_file, flag): header_type = headerType(in_file) if header_type == HEADER_TYPE_INVALID: @@ -175,13 +187,14 @@ def kconfig2macro(in_file, out_file, flag): if ret != 0: return ret - ret = write_external_macro(out_file) - if ret != 0: - return ret - ret = write_c_external_tail(out_file) if ret != 0: return ret + + if header_type == HEADER_TYPE_BUILD: + ret_code = wirte_buildef_header(out_file) + if ret_code != 0: + return ret_code ret = write_tail(out_file) if ret != 0: diff --git a/cmake/common/build_auxiliary_script/make_lib_rename_file_type.sh b/cmake/common/build_auxiliary_script/make_lib_rename_file_type.sh index eb30515..bc8cae8 100644 --- a/cmake/common/build_auxiliary_script/make_lib_rename_file_type.sh +++ b/cmake/common/build_auxiliary_script/make_lib_rename_file_type.sh @@ -16,6 +16,8 @@ file=lib"${CK_LIB_SUFFIX}" if [ "${CPU_TYPE}" = "m4" ] ; then ARNAME=arm-none-eabi-ar ; OBJCOPYNAME=arm-none-eabi-objcopy; +elif [ "${CPU_TYPE}" = "raspi4" ] || [ "${CPU_TYPE}" = "hi3093" ]; + then ARNAME=aarch64-none-elf-ar; OBJCOPYNAME=aarch64-none-elf-objcopy; else ARNAME=ar; OBJCOPYNAME=objcopy; fi @@ -23,7 +25,7 @@ fi sleep 2 pushd "$CK_LIB_PATH" ##为什么不加这一行要报错 -if [ "${CPU_TYPE}" = "m4" ] ; then +if [ "${CPU_TYPE}" = "m4" ] || [ "${CPU_TYPE}" = "raspi4" ] || [ "${CPU_TYPE}" = "hi3093" ] ; then [ -n tmp_"${file}" ] && rm -rf tmp_"${file}" fi mkdir tmp_"${file}" @@ -34,13 +36,15 @@ pushd tmp_"${file}" # 删除某变量指定的目录下所有文件。 # 通过对变量${FILE_PATH}进行判断,当${FILE_PATH}为空时,不会错误删除根目录下的文件。 [ -n "${file}" ] && rm -rf "${file}" -if [ "${CPU_TYPE}" = "m4" ] ; then +if [ "${CPU_TYPE}" = "m4" ] || [ "${CPU_TYPE}" = "raspi4" ] || [ "${CPU_TYPE}" = "hi3093" ]; then find . -name '*.s.o'| awk -F "." '{print $2}'|xargs -I'{}' mv ./{}.s.o ./{}.o find . -name '*.S.o'| awk -F "." '{print $2}'|xargs -I'{}' mv ./{}.S.o ./{}.o find . -name '*.c.o'| awk -F "." '{print $2}'|xargs -I'{}' mv ./{}.c.o ./{}.o - - for i in $(ls *.o); - do +fi + +if [ "${CPU_TYPE}" = "m4" ] ; then + for i in $(ls *.o); + do if [ -f "${i}" ] ; then "${AR_TOOL_PATH}"/"${OBJCOPYNAME}" --remove-section=.comment -I elf32-littlearm -O elf32-littlearm "${i}" "${i}".oooo "${AR_TOOL_PATH}"/"${OBJCOPYNAME}" --strip-unneeded "${i}".oooo @@ -49,6 +53,17 @@ if [ "${CPU_TYPE}" = "m4" ] ; then done fi +if [ "${CPU_TYPE}" = "raspi4" ] || [ "${CPU_TYPE}" = "hi3093" ]; then + for i in $(ls *.o); + do + if [ -f "${i}" ] ; then + "${AR_TOOL_PATH}"/"${OBJCOPYNAME}" --remove-section=.comment -I elf64-littleaarch64 -O elf64-littleaarch64 "${i}" "${i}".oooo + "${AR_TOOL_PATH}"/"${OBJCOPYNAME}" --strip-unneeded "${i}".oooo + mv "${i}".oooo "${i}" + fi + done +fi + "$AR_TOOL_PATH"/"${ARNAME}" -r -D "$file" *.o mv "$file" ../ popd @@ -59,4 +74,4 @@ popd popd -exit 0 \ No newline at end of file +exit 0 diff --git a/cmake/functions/uniproton_functions.cmake b/cmake/functions/uniproton_functions.cmake index e365b54..224223f 100644 --- a/cmake/functions/uniproton_functions.cmake +++ b/cmake/functions/uniproton_functions.cmake @@ -169,3 +169,30 @@ function(link_library target_name target_path link_flag object_name object_pat add_dependencies(${target_name} ${object_target}) endforeach() endfunction() + +function(add_library_ex file_name) + #[[ + 函数功能:传入要生成的对象库的文件名(不包含路径),生成对应的对象库并添加到全局变量中 + 用于后续能自动生成打包文件,无需开发人员再次人工指定 + 局限性: + 1、只能传入单个文件,确保每个对象库只包含单个文件 + 2、生成对象库的文件,必然都是.c 或者.S文件 + ]] + #查询传递进来的文件名是否包含路径 + string(FIND ${file_name} "/" idx REVERSE) + if(${idx} GREATER -1) + string(SUBSTRING ${file_name} ${idx} -1 str2) + string(REPLACE "/" "" object_name ${str2}) + string(REPLACE ".c" "" object_name ${object_name}) + else() + #将.c .S文件去除后缀名,只保留文件名(文件名作为对象库的名字) + string(REPLACE ".c" "" object_name ${file_name}) + endif() + + string(REPLACE ".S" "" object_name ${object_name}) + add_library(${object_name} OBJECT ${file_name}) + #将对象库添加到全局变量中 + list(APPEND ALL_OBJECT_LIBRARYS ${object_name}) + set(ALL_OBJECT_LIBRARYS ${ALL_OBJECT_LIBRARYS} CACHE STRING INTERNAL FORCE) + +endfunction() \ No newline at end of file diff --git a/cmake/tool_chain/hi3093_armv8.cmake b/cmake/tool_chain/hi3093_armv8.cmake new file mode 100644 index 0000000..5b49aaa --- /dev/null +++ b/cmake/tool_chain/hi3093_armv8.cmake @@ -0,0 +1,144 @@ +set(OBJCOPY_PATH "$ENV{HCC_PATH}" ) +##最终的链接目标,会生成对应的.a库 +################################################# +## guest代码 +################################################# +#添加进列表 +foreach(FILE_NAME ${ALL_OBJECT_LIBRARYS}) + list(FIND exclude "${FILE_NAME}" is_inclide) + if(${is_inclide} EQUAL -1) + list(APPEND GUEST_SRCS + $ + ) + endif() +endforeach() + +#编译结果 +string(TOUPPER ${PLAM_TYPE} PLAM_TYPE_UP) +string(TOUPPER ${CPU_TYPE} CPU_TYPE_UP) +add_library(HI3093 STATIC "${GUEST_SRCS}") +add_custom_target(cleanobj) +add_custom_command(TARGET cleanobj POST_BUILD + COMMAND echo finishing) + +if (${COMPILE_MODE} MATCHES "^.*dbg.*$") + message("=============== COMPILE_MODE is ${COMPILE_MODE} ===============") +else() + add_custom_command( + TARGET HI3093 + POST_BUILD + COMMAND sh ${PROJECT_SOURCE_DIR}/cmake/common/build_auxiliary_script/make_lib_rename_file_type.sh ${OBJCOPY_PATH} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} "HI3093.a" + ) +endif() + +####以下为make install打包脚本##### +set(hi3093_armv8_export modules) + +# 下面的变量分别定义了安装根目录、头文件安装目录、动态库安装目录、静态库安装目录、OBJECT文件安装目录、可执行程序安装目录、配置文件安装目录。 +# 注意:所有安装路径必须是相对CMAKE_INSTALL_PREFIX的相对路径,不可以使用绝对路径!!! +# 否则安装目录下的配置文件(foo-config.cmake, foo-tragets.cmake等)拷贝到其它目录时无法工作。 +set(INSTALL_HI3093_ARMV8_BASE_DIR .) +set(INSTALL_HI3093_ARMV8_INCLUDE_DIR UniProton/include) +set(INSTALL_HI3093_ARMV8_ARCHIVE_DIR UniProton/lib/hi3093) +set(INSTALL_HI3093_ARMV8_ARCHIVE_SEC_DIR libboundscheck/lib/hi3093) +set(INSTALL_HI3093_ARMV8_ARCHIVE_CONFIG_DIR UniProton/config) +set(INSTALL_HI3093_ARMV8_CONFIG_DIR cmake/hi3093) + + +include(CMakePackageConfigHelpers) +configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/tool_chain/hi3093_armv8_config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/uniproton-hi3093-armv8-config.cmake + INSTALL_DESTINATION ${INSTALL_HI3093_ARMV8_CONFIG_DIR} + PATH_VARS + INSTALL_HI3093_ARMV8_BASE_DIR + INSTALL_HI3093_ARMV8_INCLUDE_DIR + INSTALL_HI3093_ARMV8_ARCHIVE_DIR + INSTALL_HI3093_ARMV8_ARCHIVE_SEC_DIR + INSTALL_HI3093_ARMV8_ARCHIVE_CONFIG_DIR + INSTALL_HI3093_ARMV8_CONFIG_DIR + INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} +) +install(EXPORT ${hi3093_armv8_export} + NAMESPACE UniProton:: + FILE uniproton-hi3093-armv8-targets.cmake + DESTINATION ${INSTALL_HI3093_ARMV8_CONFIG_DIR} +) +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/uniproton-hi3093-armv8-config.cmake + DESTINATION ${INSTALL_HI3093_ARMV8_CONFIG_DIR} +) + +install(TARGETS + CortexMXsec_c + EXPORT ${hi3093_armv8_export} + ARCHIVE DESTINATION ${INSTALL_HI3093_ARMV8_ARCHIVE_SEC_DIR} +) + +install(TARGETS + HI3093 + EXPORT ${hi3093_armv8_export} + ARCHIVE DESTINATION ${INSTALL_HI3093_ARMV8_ARCHIVE_DIR}/ +) + +set(TOOLCHAIN_DIR "$ENV{HCC_PATH}") #该路径应该是外部传入,指向编译工具路径 +if (${COMPILE_MODE} MATCHES "^.*dbg.*$") + message("=============== COMPILE_MODE is ${COMPILE_MODE} ===============") +else() + +endif() + +install(FILES + ${PROJECT_SOURCE_DIR}/build/uniproton_config/config_armv8_hi3093/prt_buildef.h + DESTINATION ${INSTALL_HI3093_ARMV8_ARCHIVE_CONFIG_DIR}/hi3093 +) + +if (NOT "${LIBCK_INSTALL_FILE_OPTION}" STREQUAL "SUPER_BUILD") + ##{GLOB 所有文件 | GLOB_RECURSE 递归查找文件&文件夹} + install(FILES + ${PROJECT_SOURCE_DIR}/src/config/prt_config.c + ${PROJECT_SOURCE_DIR}/src/config/prt_config_internal.h + ${PROJECT_SOURCE_DIR}/src/config/config/prt_config.h + DESTINATION ${INSTALL_HI3093_ARMV8_ARCHIVE_CONFIG_DIR} + ) + ##{GLOB 所有文件 | GLOB_RECURSE 递归查找文件&文件夹} + file(GLOB common_include_files ${PROJECT_SOURCE_DIR}/src/include/uapi/*.h) + install(FILES + ${common_include_files} + DESTINATION ${INSTALL_HI3093_ARMV8_INCLUDE_DIR}/common + ) + + + ##{GLOB 所有文件 | GLOB_RECURSE 递归查找文件&文件夹 =======} + file(GLOB hw_board_include_files ${PROJECT_SOURCE_DIR}/src/include/uapi/hw/armv8/*) + install(FILES + ${hw_board_include_files} + DESTINATION ${INSTALL_HI3093_ARMV8_INCLUDE_DIR}/hw/board + ) + + ##{GLOB 所有文件 | GLOB_RECURSE 递归查找文件&文件夹} + file(GLOB hw_cpu_include_files ${PROJECT_SOURCE_DIR}/src/include/posix/*) + install(FILES + ${hw_cpu_include_files} + DESTINATION ${INSTALL_HI3093_ARMV8_INCLUDE_DIR}/hw/cpu + ) + + install(FILES + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_errno.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_event.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_exc.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_hook.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_hwi.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_mem.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_module.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_queue.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_sem.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_sys.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_task.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_tick.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_timer.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_typedef.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_cpup.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_err.h + DESTINATION ${INSTALL_HI3093_ARMV8_INCLUDE_DIR}/ + ) +endif() diff --git a/cmake/tool_chain/hi3093_armv8_config.cmake.in b/cmake/tool_chain/hi3093_armv8_config.cmake.in new file mode 100644 index 0000000..4f1aed1 --- /dev/null +++ b/cmake/tool_chain/hi3093_armv8_config.cmake.in @@ -0,0 +1,12 @@ +@PACKAGE_INIT@ +include(${CMAKE_CURRENT_LIST_DIR}/uniproton-hi3093-armv8-targets.cmake) + + + +set_and_check(INSTALL_HI3093_ARMV8_BASE_DIR "@PACKAGE_INSTALL_HI3093_ARMV8_BASE_DIR@") +set_and_check(INSTALL_HI3093_ARMV8_INCLUDE_DIR "@PACKAGE_INSTALL_HI3093_ARMV8_INCLUDE_DIR@") +set_and_check(INSTALL_HI3093_ARMV8_ARCHIVE_DIR "@PACKAGE_INSTALL_HI3093_ARMV8_ARCHIVE_DIR@") +set_and_check(INSTALL_HI3093_ARMV8_ARCHIVE_CONFIG_DIR "@PACKAGE_INSTALL_HI3093_ARMV8_ARCHIVE_CONFIG_DIR@") +set_and_check(INSTALL_HI3093_ARMV8_CONFIG_DIR "@PACKAGE_INSTALL_HI3093_ARMV8_CONFIG_DIR@") + +check_required_components(uniproton-hi3093-armv8) diff --git a/cmake/tool_chain/m4_cortex.cmake b/cmake/tool_chain/m4_cortex.cmake index 2befbf8..6406a03 100644 --- a/cmake/tool_chain/m4_cortex.cmake +++ b/cmake/tool_chain/m4_cortex.cmake @@ -1,107 +1,21 @@ set(BUILD_DIR "$ENV{BUILD_TMP_DIR}" ) #version id set(OBJCOPY_PATH "$ENV{OBJCOPY_PATH}" ) #OBJCOPY_PATH - - -##最终的链接目标,会生成对应的.a库 -################################################# -## arch代码 -################################################# -list(APPEND ARCH_SRCS - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ -) - -################################################# -## kernel代码 -################################################# -list(APPEND KERNEL_SRCS - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ -) -list(APPEND IPC_SRCS - $ - $ - $ - $ - $ -) -list(APPEND MEM_SRCS - $ - $ -) -list(APPEND OM_SRCS - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ -) -list(APPEND BASE_LIB_SRCS - $ - $ -) - +#将所有对象库添加到列表中 +foreach(FILE_NAME ${ALL_OBJECT_LIBRARYS}) + list(APPEND CORTEX_M4_SRCS + $ + ) +endforeach() + #编译结果 string(TOUPPER ${PLAM_TYPE} PLAM_TYPE_UP) string(TOUPPER ${CPU_TYPE} CPU_TYPE_UP) -#编译通用的.a库 -add_library(CortexMXarch STATIC "${ARCH_SRCS}") -add_library(CortexMXkernel STATIC "${KERNEL_SRCS}" "${BASE_LIB_SRCS}") -add_library(CortexMXmem STATIC "${MEM_SRCS}") -add_library(CortexMXom STATIC "${OM_SRCS}") -add_library(CortexMXipc STATIC "${IPC_SRCS}") - -set_target_properties(CortexMXarch PROPERTIES SUFFIX ".lib") -set_target_properties(CortexMXkernel PROPERTIES SUFFIX ".lib") -set_target_properties(CortexMXmem PROPERTIES SUFFIX ".lib") -set_target_properties(CortexMXom PROPERTIES SUFFIX ".lib") -set_target_properties(CortexMXipc PROPERTIES SUFFIX ".lib") +#编译.a库 +add_library(CortexM4 STATIC "${CORTEX_M4_SRCS}") +set_target_properties(CortexM4 PROPERTIES SUFFIX ".a") add_custom_target(cleanobj) add_custom_command(TARGET cleanobj POST_BUILD @@ -112,33 +26,9 @@ if (${COMPILE_MODE} STREQUAL "debug") message("=============== COMPILE_MODE is ${COMPILE_MODE} ===============") else() add_custom_command( - TARGET CortexMXarch + TARGET CortexM4 POST_BUILD - COMMAND sh ${PROJECT_SOURCE_DIR}/cmake/common/build_auxiliary_script/make_lib_rename_file_type.sh ${OBJCOPY_PATH} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} "CortexMXarch.lib" - ) - - add_custom_command( - TARGET CortexMXkernel - POST_BUILD - COMMAND sh ${PROJECT_SOURCE_DIR}/cmake/common/build_auxiliary_script/make_lib_rename_file_type.sh ${OBJCOPY_PATH} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} "CortexMXkernel.lib" - ) - - add_custom_command( - TARGET CortexMXmem - POST_BUILD - COMMAND sh ${PROJECT_SOURCE_DIR}/cmake/common/build_auxiliary_script/make_lib_rename_file_type.sh ${OBJCOPY_PATH} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} "CortexMXmem.lib" - ) - - add_custom_command( - TARGET CortexMXom - POST_BUILD - COMMAND sh ${PROJECT_SOURCE_DIR}/cmake/common/build_auxiliary_script/make_lib_rename_file_type.sh ${OBJCOPY_PATH} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} "CortexMXom.lib" - ) - - add_custom_command( - TARGET CortexMXipc - POST_BUILD - COMMAND sh ${PROJECT_SOURCE_DIR}/cmake/common/build_auxiliary_script/make_lib_rename_file_type.sh ${OBJCOPY_PATH} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} "CortexMXipc.lib" + COMMAND sh ${PROJECT_SOURCE_DIR}/cmake/common/build_auxiliary_script/make_lib_rename_file_type.sh ${OBJCOPY_PATH} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} "CortexM4.a" ) endif() ####以下为m4 make install打包脚本##### @@ -183,11 +73,7 @@ install(FILES ) install(TARGETS - CortexMXarch - CortexMXkernel - CortexMXmem - CortexMXom - CortexMXipc + CortexM4 EXPORT ${m4_cortex_export} ARCHIVE DESTINATION ${INSTALL_M4_CORTEX_ARCHIVE_DIR}/ ) diff --git a/cmake/tool_chain/raspi4_armv8.cmake b/cmake/tool_chain/raspi4_armv8.cmake new file mode 100644 index 0000000..fbf5e7b --- /dev/null +++ b/cmake/tool_chain/raspi4_armv8.cmake @@ -0,0 +1,151 @@ +set(OBJCOPY_PATH "$ENV{HCC_PATH}" ) +##最终的链接目标,会生成对应的.a库 +################################################# +## guest代码 +################################################# +#添加进列表 +foreach(FILE_NAME ${ALL_OBJECT_LIBRARYS}) + list(FIND exclude "${FILE_NAME}" is_inclide) + if(${is_inclide} EQUAL -1) + list(APPEND GUEST_SRCS + $ + ) + endif() +endforeach() + +#编译结果 +string(TOUPPER ${PLAM_TYPE} PLAM_TYPE_UP) +string(TOUPPER ${CPU_TYPE} CPU_TYPE_UP) +add_library(RASPI4 STATIC "${GUEST_SRCS}") +add_custom_target(cleanobj) +add_custom_command(TARGET cleanobj POST_BUILD + COMMAND echo finishing) + +if (${COMPILE_MODE} MATCHES "^.*dbg.*$") + message("=============== COMPILE_MODE is ${COMPILE_MODE} ===============") +else() + add_custom_command( + TARGET RASPI4 + POST_BUILD + COMMAND sh ${PROJECT_SOURCE_DIR}/cmake/common/build_auxiliary_script/make_lib_rename_file_type.sh ${OBJCOPY_PATH} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} "RASPI4.a" + ) +endif() + +####以下为make install打包脚本##### +set(raspi4_armv8_export modules) + +# 下面的变量分别定义了安装根目录、头文件安装目录、动态库安装目录、静态库安装目录、OBJECT文件安装目录、可执行程序安装目录、配置文件安装目录。 +# 注意:所有安装路径必须是相对CMAKE_INSTALL_PREFIX的相对路径,不可以使用绝对路径!!! +# 否则安装目录下的配置文件(foo-config.cmake, foo-tragets.cmake等)拷贝到其它目录时无法工作。 +set(INSTALL_RASPI4_ARMV8_BASE_DIR .) +set(INSTALL_RASPI4_ARMV8_INCLUDE_DIR UniProton/include) +set(INSTALL_RASPI4_ARMV8_ARCHIVE_DIR UniProton/lib/raspi4) +set(INSTALL_RASPI4_ARMV8_ARCHIVE_SEC_DIR libboundscheck/lib/raspi4) +set(INSTALL_RASPI4_ARMV8_ARCHIVE_CONFIG_DIR UniProton/config) +set(INSTALL_RASPI4_ARMV8_CONFIG_DIR cmake/raspi4) + + +include(CMakePackageConfigHelpers) +configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/tool_chain/raspi4_armv8_config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/uniproton-raspi4-armv8-config.cmake + INSTALL_DESTINATION ${INSTALL_RASPI4_ARMV8_CONFIG_DIR} + PATH_VARS + INSTALL_RASPI4_ARMV8_BASE_DIR + INSTALL_RASPI4_ARMV8_INCLUDE_DIR + INSTALL_RASPI4_ARMV8_ARCHIVE_DIR + INSTALL_RASPI4_ARMV8_ARCHIVE_SEC_DIR + INSTALL_RASPI4_ARMV8_ARCHIVE_CONFIG_DIR + INSTALL_RASPI4_ARMV8_CONFIG_DIR + INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} +) +install(EXPORT ${raspi4_armv8_export} + NAMESPACE UniProton:: + FILE uniproton-raspi4-armv8-targets.cmake + DESTINATION ${INSTALL_RASPI4_ARMV8_CONFIG_DIR} +) +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/uniproton-raspi4-armv8-config.cmake + DESTINATION ${INSTALL_RASPI4_ARMV8_CONFIG_DIR} +) + +install(TARGETS + CortexMXsec_c + EXPORT ${raspi4_armv8_export} + ARCHIVE DESTINATION ${INSTALL_RASPI4_ARMV8_ARCHIVE_SEC_DIR} +) + +install(TARGETS + RASPI4 + EXPORT ${raspi4_armv8_export} + ARCHIVE DESTINATION ${INSTALL_RASPI4_ARMV8_ARCHIVE_DIR}/ +) + +set(TOOLCHAIN_DIR "$ENV{HCC_PATH}") #该路径应该是外部传入,指向编译工具路径 +if (${COMPILE_MODE} MATCHES "^.*dbg.*$") + message("=============== COMPILE_MODE is ${COMPILE_MODE} ===============") +else() + +endif() + +install(FILES + ${PROJECT_SOURCE_DIR}/build/uniproton_config/config_armv8_raspi4/prt_buildef.h + DESTINATION ${INSTALL_RASPI4_ARMV8_ARCHIVE_CONFIG_DIR}/raspi4 +) + +if (NOT "${LIBCK_INSTALL_FILE_OPTION}" STREQUAL "SUPER_BUILD") + ##{GLOB 所有文件 | GLOB_RECURSE 递归查找文件&文件夹} + install(FILES + ${PROJECT_SOURCE_DIR}/src/config/prt_config.c + ${PROJECT_SOURCE_DIR}/src/config/prt_config_internal.h + ${PROJECT_SOURCE_DIR}/src/config/config/prt_config.h + DESTINATION ${INSTALL_RASPI4_ARMV8_ARCHIVE_CONFIG_DIR} + ) + ##{GLOB 所有文件 | GLOB_RECURSE 递归查找文件&文件夹} + file(GLOB common_include_files ${PROJECT_SOURCE_DIR}/src/include/uapi/common/*.h) + install(FILES + ${common_include_files} + DESTINATION ${INSTALL_RASPI4_ARMV8_INCLUDE_DIR}/common + ) + + + ##{GLOB 所有文件 | GLOB_RECURSE 递归查找文件&文件夹 =======} + file(GLOB hw_board_include_files ${PROJECT_SOURCE_DIR}/src/include/uapi/sre/hw/board/*) + install(FILES + ${hw_board_include_files} + DESTINATION ${INSTALL_RASPI4_ARMV8_INCLUDE_DIR}/hw/board + ) + + ##{GLOB 所有文件 | GLOB_RECURSE 递归查找文件&文件夹} + file(GLOB hw_cpu_include_files ${PROJECT_SOURCE_DIR}/src/include/uapi/sre/hw/cpu/*) + install(FILES + ${hw_cpu_include_files} + DESTINATION ${INSTALL_RASPI4_ARMV8_INCLUDE_DIR}/hw/cpu + ) + + ##{GLOB 所有文件 | GLOB_RECURSE 递归查找文件&文件夹} + file(GLOB hw_drv_include_files ${PROJECT_SOURCE_DIR}/src/include/uapi/sre/hw/drv/*) + install(FILES + ${hw_drv_include_files} + DESTINATION ${INSTALL_RASPI4_ARMV8_INCLUDE_DIR}/hw/drv + ) + + install(FILES + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_errno.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_event.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_exc.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_hook.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_hwi.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_mem.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_module.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_queue.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_sem.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_sys.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_task.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_tick.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_timer.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_typedef.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_cpup.h + ${PROJECT_SOURCE_DIR}/src/include/uapi/prt_err.h + DESTINATION ${INSTALL_RASPI4_ARMV8_INCLUDE_DIR}/ + ) +endif() diff --git a/cmake/tool_chain/raspi4_armv8_config.cmake.in b/cmake/tool_chain/raspi4_armv8_config.cmake.in new file mode 100644 index 0000000..1bcbcbb --- /dev/null +++ b/cmake/tool_chain/raspi4_armv8_config.cmake.in @@ -0,0 +1,12 @@ +@PACKAGE_INIT@ +include(${CMAKE_CURRENT_LIST_DIR}/uniproton-raspi4-armv8-targets.cmake) + + + +set_and_check(INSTALL_RASPI4_ARMV8_BASE_DIR "@PACKAGE_INSTALL_RASPI4_ARMV8_BASE_DIR@") +set_and_check(INSTALL_RASPI4_ARMV8_INCLUDE_DIR "@PACKAGE_INSTALL_RASPI4_ARMV8_INCLUDE_DIR@") +set_and_check(INSTALL_RASPI4_ARMV8_ARCHIVE_DIR "@PACKAGE_INSTALL_RASPI4_ARMV8_ARCHIVE_DIR@") +set_and_check(INSTALL_RASPI4_ARMV8_ARCHIVE_CONFIG_DIR "@PACKAGE_INSTALL_RASPI4_ARMV8_ARCHIVE_CONFIG_DIR@") +set_and_check(INSTALL_RASPI4_ARMV8_CONFIG_DIR "@PACKAGE_INSTALL_RASPI4_ARMV8_CONFIG_DIR@") + +check_required_components(uniproton-raspi4-armv8) diff --git a/cmake/tool_chain/uniproton_tool_chain.cmake b/cmake/tool_chain/uniproton_tool_chain.cmake index 58b287a..f34e0b7 100644 --- a/cmake/tool_chain/uniproton_tool_chain.cmake +++ b/cmake/tool_chain/uniproton_tool_chain.cmake @@ -13,12 +13,18 @@ set(COMPILE_OPTION "$ENV{COMPILE_OPTION}" ) set(RPROTON_INSTALL_FILE_OPTION "$ENV{RPROTON_INSTALL_FILE_OPTION}" )##RPROTON_INSTALL_FILE_OPTION="SUPER_BUILD"; +if (${CPU_TYPE} STREQUAL "m4") #### 统一告警选项,请审慎增删 set(STRONG_COMPILE_WARING_FLAG "-Wunused -Wredundant-decls -Wfloat-conversion -Wwrite-strings -Wunused-macros -Wswitch-default -Wshift-overflow=2 -Wnested-externs -Wmissing-include-dirs -Wlogical-op -Wjump-misses-init -Wformat-security -Wvla -Wframe-larger-than=4096 -Wduplicated-cond -Wdisabled-optimization -Wduplicated-branches -Wignored-qualifiers -Wimplicit-fallthrough=3 -Wpointer-arith -Wshift-negative-value -Wsign-compare -Wtype-limits -Wcast-qual -Wundef -Wbad-function-cast -Wold-style-definition -Wpacked -Wstrict-prototypes -Wstack-usage=2048") set(COMPILE_WARING_FLAG " -Wall -Werror -Wextra -Wformat=2 -Wfloat-equal -Wshadow -Wtrampolines -Wdate-time ")## -Wall -Werror -Wextra -Wformat=2 -Wfloat-equal +include(${HOME_PATH}/cmake/tool_chain/uniproton_tool_chain_gcc.cmake) +endif() -if (${CPU_TYPE} STREQUAL "m4" ) - include(${HOME_PATH}/cmake/tool_chain/rtosk_tool_chain_gcc.cmake) +if (${CPU_TYPE} STREQUAL "raspi4" OR ${CPU_TYPE} STREQUAL "hi3093") +#### 统一告警选项,请审慎增删 +set(STRONG_COMPILE_WARING_FLAG "-Wunused -Wredundant-decls -Wfloat-conversion -Wwrite-strings -Wunused-macros -Wswitch-default -Wshift-overflow=2 -Wnested-externs -Wmissing-include-dirs -Wlogical-op -Wjump-misses-init -Wformat-security -Wvla -Wframe-larger-than=4096 -Wduplicated-cond -Wdisabled-optimization -Wduplicated-branches -Wignored-qualifiers -Wimplicit-fallthrough=3 -Wpointer-arith -Wshift-negative-value -Wsign-compare -Wtype-limits -Wcast-qual -Wundef -Wbad-function-cast -Wold-style-definition -Wpacked -Wstrict-prototypes -Wstack-usage=2048") +set(COMPILE_WARING_FLAG " -Wall -Werror -Wextra -Wformat=2 -Wfloat-equal -Wshadow -Wtrampolines -Wdate-time ")## -Wall -Werror -Wextra -Wformat=2 -Wfloat-equal +include(${HOME_PATH}/cmake/tool_chain/uniproton_tool_chain_gcc_arm64.cmake) endif() diff --git a/cmake/tool_chain/rtosk_tool_chain_gcc.cmake b/cmake/tool_chain/uniproton_tool_chain_gcc.cmake similarity index 65% rename from cmake/tool_chain/rtosk_tool_chain_gcc.cmake rename to cmake/tool_chain/uniproton_tool_chain_gcc.cmake index 636d61c..84cd3a0 100644 --- a/cmake/tool_chain/rtosk_tool_chain_gcc.cmake +++ b/cmake/tool_chain/uniproton_tool_chain_gcc.cmake @@ -29,7 +29,13 @@ if(${CPU_TYPE} STREQUAL "m4") set(CMAKE_ASM_FLAGS "--specs=nosys.specs") set(CMAKE_ASM_COMPILE_OBJECT " -O2 -pipe ${STRONG_COMPILE_WARING_FLAG} ${COMPILE_WARING_FLAG} -std=gnu11 -fno-common -fomit-frame-pointer -mthumb -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -Wa,-mimplicit-it=thumb -fstack-protector-strong -funsigned-char -c -o ") set(CMAKE_C_FLAGS "--specs=nosys.specs") #原ID形式\"888888\" - set(CMAKE_C_COMPILE_OBJECT " -O2 -pipe ${STRONG_COMPILE_WARING_FLAG} ${COMPILE_WARING_FLAG} -std=gnu11 -fno-common -fomit-frame-pointer -mcpu=cortex-m4 -mthumb -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -fstack-protector-strong -fdata-sections -ffunction-sections -fshort-enums -funsigned-char -DSECUREC_BUFFER_SIZE=32 -c -o ") + set(CMAKE_C_COMPILE_OBJECT " -O2 -pipe ") + + file(STRINGS "$ENV{CONFIG_FILE_PATH}/defconfig" config_options REGEX "^CONFIG_OS_OPTION_POSIX" ENCODING "UTF-8") + foreach(config_option ${config_options}) + set(CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT} -D_GNU_SOURCE -D_POSIX_THREADS -D_POSIX_THREAD_PRIORITY_SCHEDULING -D_POSIX_PRIORITY_SCHEDULING -D_POSIX_TIMERS -D_POSIX_CPUTIME -D_POSIX_THREAD_CPUTIME -D_POSIX_MONOTONIC_CLOCK -D_POSIX_TIMEOUTS -D_POSIX_CLOCK_SELECTION -D_POSIX_THREAD_PRIO_PROTECT -D_UNIX98_THREAD_MUTEX_ATTRIBUTES -D_POSIX_READER_WRITER_LOCKS") + endforeach() + set(CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT} ${STRONG_COMPILE_WARING_FLAG} ${COMPILE_WARING_FLAG} -std=gnu11 -fno-common -fomit-frame-pointer -mcpu=cortex-m4 -mthumb -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -fstack-protector-strong -fdata-sections -ffunction-sections -fshort-enums -funsigned-char -DSECUREC_BUFFER_SIZE=32 -c -o ") endif() diff --git a/cmake/tool_chain/uniproton_tool_chain_gcc_arm64.cmake b/cmake/tool_chain/uniproton_tool_chain_gcc_arm64.cmake new file mode 100644 index 0000000..16ad670 --- /dev/null +++ b/cmake/tool_chain/uniproton_tool_chain_gcc_arm64.cmake @@ -0,0 +1,53 @@ +################交叉编译##################### +#cross-compilation config +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR arm) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + + +set(CPU_TYPE "$ENV{CPU_TYPE}" ) +set(PLAM_TYPE "$ENV{PLAM_TYPE}" ) +set(LIB_TYPE "$ENV{LIB_TYPE}" ) +set(SYSTEM "$ENV{SYSTEM}" ) +set(CORE "$ENV{CORE}" ) +set(LIB_RUN_TYPE "$ENV{LIB_RUN_TYPE}" ) +set(BUILD_DIR "$ENV{BUILD_TMP_DIR}" ) #version id +set(OBJCOPY_PATH "$ENV{OBJCOPY_PATH}" ) #OBJCOPY_PATH +set(COMPILE_MODE "$ENV{COMPILE_MODE}" ) +set(CC_TYPE "$ENV{CC_TYPE}" ) +set(TOOLCHAIN_DIR "$ENV{HCC_PATH}") #该路径应该是外部传入,指向编译工具路径 + + +# 设置gcc_arm64编译器公共的编译选项 +set(CC_OPT_LEVEL "-Os") +set(CC_WARN_FLAGS "-Wformat-signedness") +set(CC_MD_DEPENDENT_FLAGS "-Wl,--build-id=none") +# 初始化为空,不能删除这句 +set(CC_OPT_FLAGS "") +set(CC_SEC_FLAGS "${CC_SEC_FLAGS} -fno-PIE") +# 待确认的编译选项,暂时没进行分类,待处理 +set(CC_OTHER_FLAGS "--specs=nosys.specs -fno-builtin -fno-dwarf2-cfi-asm -mcmodel=large -fomit-frame-pointer -fzero-initialized-in-bss -fdollars-in-identifiers -ffunction-sections -fdata-sections -fno-aggressive-loop-optimizations -fno-optimize-strlen -fno-schedule-insns -fno-inline-small-functions -fno-inline-functions-called-once -fno-strict-aliasing -finline-limit=20 -mstrict-align -mlittle-endian -nostartfiles -funwind-tables") +set(CC_DEFINE_FLAGS "") + +##compiler specified in /etc/profile +set(CMAKE_C_COMPILER "${TOOLCHAIN_DIR}/aarch64-none-elf-gcc" CACHE PATH "arm-gcc C compiler" FORCE) +set(CMAKE_ASM_COMPILER "${TOOLCHAIN_DIR}/aarch64-none-elf-gcc" CACHE PATH "arm-gcc ASM compiler" FORCE) + +# 设置C和ASM相关的所有使用的编译选项 +set(CMAKE_C_FLAGS "${CC_OPT_LEVEL} ${CC_OVERALL_FLAGS_COMMON} ${CC_WARN_FLAGS_COMMON} ${CC_WARN_FLAGS} ${CC_LANGUAGE_FLAGS_COMMON} ${CC_LANGUAGE_FLAGS} ${CC_CDG_FLAGS} ${CC_MD_DEPENDENT_FLAGS} ${CC_OPT_FLAGS} ${CC_SEC_FLAGS} ${CC_OTHER_FLAGS} ${CC_DEFINE_FLAGS_COMMON} ${CC_DEFINE_FLAGS}") +set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} ${ASM_EXTRA_FLAGS}") +set(CMAKE_C_COMPILE_OBJECT " -c -o ") +file(STRINGS "$ENV{CONFIG_FILE_PATH}/defconfig" config_options REGEX "^CONFIG_OS_OPTION_POSIX" ENCODING "UTF-8") +foreach(config_option ${config_options}) + set(CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT} -D_GNU_SOURCE -D_POSIX_THREADS -D_POSIX_THREAD_PRIORITY_SCHEDULING -D_POSIX_PRIORITY_SCHEDULING -D_POSIX_TIMERS -D_POSIX_CPUTIME -D_POSIX_THREAD_CPUTIME -D_POSIX_MONOTONIC_CLOCK -D_POSIX_TIMEOUTS -D_POSIX_CLOCK_SELECTION -D_POSIX_THREAD_PRIO_PROTECT -D_UNIX98_THREAD_MUTEX_ATTRIBUTES -D_POSIX_READER_WRITER_LOCKS") +endforeach() +set(CMAKE_ASM_COMPILE_OBJECT " -c -o ") + +set(CMAKE_LINKER "${TOOLCHAIN_DIR}/aarch64-none-elf-ld" CACHE STRING "" FORCE) +set(CMAKE_AR "${TOOLCHAIN_DIR}/aarch64-none-elf-ar" CACHE STRING "" FORCE) +set(CMAKE_C_LINK_FLAGS "-r ") +set(CMAKE_C_ARCHIVE_CREATE " -r ") diff --git a/config.xml b/config.xml index b0e44b5..a88bb40 100644 --- a/config.xml +++ b/config.xml @@ -37,4 +37,26 @@ + + + SRE + + armv8 + /opt/buildtools/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin + /opt/buildtools/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin + armv8_raspi4 + + + + + + SRE + + armv8 + /opt/buildtools/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin + /opt/buildtools/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin + armv8_hi3093 + + + diff --git a/demos/helloworld/CMakeLists.txt b/demos/helloworld/CMakeLists.txt new file mode 100644 index 0000000..c50108b --- /dev/null +++ b/demos/helloworld/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.12) +project(exmaples LANGUAGES C ASM CXX) + +set(CMAKE_C_COMPILER ${TOOLCHAIN_PATH}/bin/arm-none-eabi-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PATH}/bin/arm-none-eabi-g++) +set(CMAKE_C_FLAGS "-g -O2 -mthumb -mcpu=cortex-m4 -std=gnu11 -fno-common -fomit-frame-pointer -mthumb -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -Wa,-mimplicit-it=thumb -fstack-protector-strong -funsigned-char -fdata-sections -ffunction-sections -fshort-enums") +set(CMAKE_CXX_FLAGS "-mthumb -mcpu=cortex-m4 -fno-threadsafe-statics -fno-builtin -DEIGEN_NO_IO=1") +set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +set(CMAKE_ASM_FLAGS ${CMAKE_C_FLAGS}) + +set(CXX_LIB ${TOOLCHAIN_PATH}/lib/gcc/arm-none-eabi/10.2.1/crti.o + ${TOOLCHAIN_PATH}/lib/gcc/arm-none-eabi/10.2.1/crtbegin.o + ${TOOLCHAIN_PATH}/arm-none-eabi/lib/crt0.o + ${TOOLCHAIN_PATH}/lib/gcc/arm-none-eabi/10.2.1/crtend.o + ${TOOLCHAIN_PATH}/lib/gcc/arm-none-eabi/10.2.1/crtn.o) + +set(CMAKE_EXE_LINKER_FLAGS "-Wl,-EL -Wl,-d -Wl,-no-enum-size-warning -u _printf_float -nostartfiles -static -T ../examples.ld") + +include_directories(./include ./config ./bsp) +link_directories(./libs) +link_libraries("${CMAKE_CURRENT_SOURCE_DIR}/libs/libCortexM4.a" "${CMAKE_CURRENT_SOURCE_DIR}/libs/libCortexMXsec_c.lib" "${CMAKE_CURRENT_SOURCE_DIR}/libs/libCortexM4.a" "${CMAKE_CURRENT_SOURCE_DIR}/libs/libCortexMXsec_c.lib") +link_libraries(-lm -lc_nano -lnosys -lgcc) + +add_subdirectory(bsp) +add_subdirectory(config) +add_subdirectory(apps) + +list(APPEND OBJS $ $ $) +add_executable(${APP} ${CXX_LIB} ${OBJS}) diff --git a/demos/helloworld/apps/CMakeLists.txt b/demos/helloworld/apps/CMakeLists.txt new file mode 100644 index 0000000..5140f7c --- /dev/null +++ b/demos/helloworld/apps/CMakeLists.txt @@ -0,0 +1,3 @@ +if(APP STREQUAL "helloworld") + add_subdirectory(helloworld) +endif() diff --git a/demos/helloworld/apps/helloworld/CMakeLists.txt b/demos/helloworld/apps/helloworld/CMakeLists.txt new file mode 100644 index 0000000..9dbc99d --- /dev/null +++ b/demos/helloworld/apps/helloworld/CMakeLists.txt @@ -0,0 +1,2 @@ +set(SRCS main.c) +add_library(apps OBJECT ${SRCS}) \ No newline at end of file diff --git a/demos/helloworld/apps/helloworld/main.c b/demos/helloworld/apps/helloworld/main.c new file mode 100644 index 0000000..271d840 --- /dev/null +++ b/demos/helloworld/apps/helloworld/main.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: the uniproton helloworld demo + */ +#include +#include +#include +#include +#include "securec.h" +#include "rtt_viewer.h" +#include "prt_config.h" +#include "prt_config_internal.h" +#include "prt_clk.h" +#include "test.h" + +void helloworld_task(U32 uwParam1, U32 uParam2, U32 uwParam3, U32 uwParam4) +{ + printf("hello world!\n"); + while (1) { + PRT_TaskDelay(10); + } + + return; +} + +U32 PRT_AppInit(void) +{ + U32 ret; + TskHandle taskPid; + struct TskInitParam stInitParam = {helloworld_task, 10, 0, {0}, 0x800, "TaskA", 0}; + + ret = PRT_TaskCreate(&taskPid, &stInitParam); + if (ret) { + return ret; + } + + ret = PRT_TaskResume(taskPid); + if (ret) { + return ret; + } + + return OS_OK; +} + +U32 PRT_HardDrvInit(void) +{ + RttViewerInit(); + RttViewerModeSet(0, RTT_VIEWER_MODE_BLOCK_IF_FIFO_FULL); + + return OS_OK; +} + +U32 g_testRandStackProtect; +void OsRandomSeedInit(void) +{ +#if defined(OS_OPTION_RND) + U32 ret; + U32 seed; + seed = PRT_ClkGetCycleCount64(); + g_testRandStackProtect = rand_r(&seed); + ret = PRT_SysSetRndNum(OS_SYS_RND_STACK_PROTECT,g_testRandStackProtect); +#endif +} + +extern U32 __data_start__; +extern U32 __data_end__; +extern U32 __text_end__; +void OsGlobalDataInit(void) +{ + U32 size; + U32 *dest = (U32 *)&__data_start__; + U32 *src = (U32 *)&__text_end__; + U32 i; + + size = (U32)&__data_end__ - (U32)&__data_start__; + for (i = 0; i < (size / 4); i++) { + dest[i] = src[i]; + } +} + +void PRT_HardBootInit(void) +{ + OsGlobalDataInit(); + OsRandomSeedInit(); +} + +U32 PRT_Printf(const char *format, ...) +{ + va_list vaList; + char buff[0x200] = { 0 }; + S32 count; + U32 ret; + + va_start(vaList, format); + count = vsprintf_s(buff, 0x200, format, vaList); + va_end(vaList); + + if (count == -1) { + return OS_ERROR; + } + + RttViewerWrite(0, buff, count); + + return count; +} + +S32 main(void) +{ + return OsConfigStart(); +} + diff --git a/demos/helloworld/apps/helloworld/test.h b/demos/helloworld/apps/helloworld/test.h new file mode 100644 index 0000000..be14e86 --- /dev/null +++ b/demos/helloworld/apps/helloworld/test.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: the uniproton helloworld demo + */ +#include "prt_config.h" +#include "prt_task.h" +#include "prt_hwi.h" +#include "prt_hook.h" +#include "prt_exc.h" +#include "prt_mem.h" + +extern U32 PRT_Printf(const char *format, ...); +#define printf PRT_Printf diff --git a/demos/helloworld/apps/readme.txt b/demos/helloworld/apps/readme.txt new file mode 100644 index 0000000..8f30d23 --- /dev/null +++ b/demos/helloworld/apps/readme.txt @@ -0,0 +1 @@ +请您参考example目录添加您的源代码,制作您的工程。如有疑问请联系华为对接工程师。 diff --git a/demos/helloworld/bsp/CMakeLists.txt b/demos/helloworld/bsp/CMakeLists.txt new file mode 100644 index 0000000..14c1d15 --- /dev/null +++ b/demos/helloworld/bsp/CMakeLists.txt @@ -0,0 +1,2 @@ +set(SRCS rtt_viewer.c) +add_library(bsp OBJECT ${SRCS}) diff --git a/demos/helloworld/bsp/rtt_viewer.c b/demos/helloworld/bsp/rtt_viewer.c new file mode 100644 index 0000000..8456e5f --- /dev/null +++ b/demos/helloworld/bsp/rtt_viewer.c @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: Hardware interrupt implementation + */ +#include "rtt_viewer.h" +#include "prt_typedef.h" +#include "prt_mem.h" +#include "securec.h" + +TagRttViewerCb _SEGGER_RTT; + +/* + * 描述: rtt viewer加锁 + */ +static unsigned int RttViewerLock() +{ + unsigned int lockState; + OS_EMBED_ASM("mrs %0, basepri \n\t" + "mov r1, %1 \n\t" + "msr basepri, r1 \n\t" + : "=r" (lockState) \ + : "i"(RTT_VIEWER_MAX_INT_PRI) + : "r1", "cc" + ); + + return lockState; +} + +/* + * 描述: rtt viewer释放锁 + */ +static void RttViewerUnlock(unsigned int lockSave) +{ + OS_EMBED_ASM("msr basepri, %0 \n\t" + : + : "r" (lockSave) + : + ); +} + +/* + * 描述: rtt viewer初始化 + */ +void RttViewerInit(void) +{ + unsigned int idx; + unsigned int size; + unsigned char *wbuffer; + unsigned char *rbuffer; + + g_rttViewerCb.wbMaxNum = RTT_VIEWER_WB_MAX_NUM; + g_rttViewerCb.rbMaxNum = RTT_VIEWER_RB_MAX_NUM; + + /* rtt viewer写缓冲区资源申请 */ + size = RTT_VIEWER_WB_MAX_NUM * RTT_VIEWER_WB_BUFFER_SIZE; + wbuffer = (unsigned char *)PRT_MemAlloc(0, OS_MEM_DEFAULT_FSC_PT, size); + if ((wbuffer == NULL) || (memset_s(wbuffer, size, 0, size) != EOK)) { + return; + } + + /* rtt viewer写缓冲区初始化 */ + for (idx = 0; idx < RTT_VIEWER_WB_MAX_NUM; idx++) { + g_rttViewerCb.aUp[idx].sName = "Terminal"; + g_rttViewerCb.aUp[idx].pBuffer = &wbuffer[idx * RTT_VIEWER_WB_BUFFER_SIZE]; + g_rttViewerCb.aUp[idx].size = RTT_VIEWER_WB_BUFFER_SIZE; + g_rttViewerCb.aUp[idx].rIdx = 0; + g_rttViewerCb.aUp[idx].wIdx = 0; + g_rttViewerCb.aUp[idx].flags = RTT_VIEWER_MODE_DEFAULT; + } + + /* rtt viewer读缓冲区资源申请 */ + size = RTT_VIEWER_RB_MAX_NUM * RTT_VIEWER_RB_BUFFER_SIZE; + rbuffer = (unsigned char *)PRT_MemAlloc(0, OS_MEM_DEFAULT_FSC_PT, size); + if ((rbuffer == NULL) || (memset_s(rbuffer, size, 0, size) != EOK)) { + return; + } + + /* rtt viewer读缓冲区初始化 */ + for (idx = 0; idx < RTT_VIEWER_RB_MAX_NUM; idx++) { + g_rttViewerCb.aDown[idx].sName = "Terminal"; + g_rttViewerCb.aDown[idx].pBuffer = &rbuffer[idx * RTT_VIEWER_RB_BUFFER_SIZE]; + g_rttViewerCb.aDown[idx].size = RTT_VIEWER_RB_BUFFER_SIZE; + g_rttViewerCb.aDown[idx].rIdx = 0; + g_rttViewerCb.aDown[idx].wIdx = 0; + g_rttViewerCb.aDown[idx].flags = RTT_VIEWER_MODE_DEFAULT; + } + + /* 设置rtt viewer的id */ + strcpy((char *)&g_rttViewerCb.acID[0], "SEGGER"); + RTT_DMB(); + g_rttViewerCb.acID[6] = ' '; + RTT_DMB(); + strcpy((char *)&g_rttViewerCb.acID[7], "RTT"); + RTT_DMB(); + + return; +} + +/* + * 描述: rtt viewer写模式配置 + */ +unsigned int RttViewerModeSet(unsigned int chn, unsigned int mode) +{ + if ((mode > RTT_VIEWER_MODE_MASK) || (chn >= RTT_VIEWER_WB_MAX_NUM)) { + return OS_ERROR; + } + + /* 设置模式 */ + g_rttViewerCb.aUp[chn].flags = mode; +} + +/* + * 描述: 参数校验 + */ +static unsigned int RttViewerWriteParaCheck(unsigned int chn, const void *buffer, unsigned int numBytes) +{ + if (chn >= RTT_VIEWER_WB_MAX_NUM) { + return OS_ERROR; + } + + if (buffer == NULL) { + return OS_ERROR; + } + + if ((numBytes == 0) || (numBytes > RTT_VIEWER_WB_BUFFER_SIZE)) { + return OS_ERROR; + } + + return OS_OK; +} + +/* + * 描述: 获取可以写入环形缓冲区而不阻塞的字节数 + */ +static unsigned int GetAvailWriteSpace(RTT_VIEWER_RING_BUFFER *ringBuffer) { + unsigned int freeSize; + + if (ringBuffer->rIdx <= ringBuffer->wIdx) { + freeSize = ringBuffer->size - 1 - ringBuffer->wIdx + ringBuffer->rIdx; + } else { + freeSize = ringBuffer->rIdx - ringBuffer->wIdx - 1; + } + + return freeSize; +} + +/* + * 描述: 环缓冲区中存储指定数量的字符 + */ +static void RingBufferPush(RTT_VIEWER_RING_BUFFER *ringBuffer, const char *data, unsigned int numBytes) +{ + unsigned int numBytesAtOnce; + unsigned int wIdx; + unsigned int rem; + volatile char *dst; + + wIdx = ringBuffer->wIdx; + rem = ringBuffer->size - wIdx; + dst = ringBuffer->pBuffer + wIdx; + if (rem > numBytes) { + memcpy_s((void*)dst, numBytes, data, numBytes); + RTT_DMB(); + ringBuffer->wIdx = wIdx + numBytes; + } else { + numBytesAtOnce = rem; + memcpy_s((void*)dst, numBytesAtOnce, data, numBytesAtOnce); + numBytesAtOnce = numBytes - rem; + + if (numBytesAtOnce > 0) { + dst = ringBuffer->pBuffer; + memcpy_s((void*)dst, numBytesAtOnce, data + rem, numBytesAtOnce); + RTT_DMB(); + } + ringBuffer->wIdx = numBytesAtOnce; + } + + return; +} + +/* + * 描述: 环缓冲区中存储指定数量的字符,数据长度可以 + */ +static unsigned int RingBufferBlockPush(RTT_VIEWER_RING_BUFFER *ringBuffer, const char *buffer, unsigned int numBytes) { + unsigned int numBytesToWrite; + unsigned int numBytesWritten; + unsigned int rIdx; + unsigned int wIdx; + volatile char *dst; + + numBytesWritten = 0; + wIdx = ringBuffer->wIdx; + do { + rIdx = ringBuffer->rIdx; + if (rIdx > wIdx) { + numBytesToWrite = rIdx - wIdx - 1u; + } else { + numBytesToWrite = ringBuffer->size - (wIdx - rIdx + 1u); + } + + numBytesToWrite = MIN(numBytesToWrite, (ringBuffer->size - wIdx)); + numBytesToWrite = MIN(numBytesToWrite, numBytes); + dst = ringBuffer->pBuffer + wIdx; + memcpy_s((void*)dst, numBytesToWrite, buffer, numBytesToWrite); + + numBytesWritten += numBytesToWrite; + buffer += numBytesToWrite; + numBytes -= numBytesToWrite; + wIdx += numBytesToWrite; + if (wIdx == ringBuffer->size) { + wIdx = 0; + } + RTT_DMB(); + ringBuffer->wIdx = wIdx; + } while (numBytes); + + return numBytesWritten; +} + +/* + * 描述: rtt viewer写数据 + */ +unsigned int RttViewerWrite(unsigned int chn, const void *buffer, unsigned int numBytes) +{ + unsigned int ret; + unsigned int intSave; + unsigned int freeSize; + unsigned int writeBytes; + RTT_VIEWER_RING_BUFFER *wRingBuffer; + + if (memcmp(g_rttViewerCb.acID, "SEGGER RTT", sizeof("SEGGER RTT")) != 0) { + return OS_ERROR; + } + + /* 校验入参 */ + ret = RttViewerWriteParaCheck(chn, buffer, numBytes); + if (ret != OS_OK) { + return ret; + } + + intSave = RttViewerLock(); + + wRingBuffer = &g_rttViewerCb.aUp[chn]; + + switch (wRingBuffer->flags) { + case RTT_VIEWER_MODE_NO_BLOCK_SKIP: + freeSize = GetAvailWriteSpace(wRingBuffer); + if (freeSize >= numBytes) { + RingBufferPush(wRingBuffer, buffer, numBytes); + } + break; + + case RTT_VIEWER_MODE_NO_BLOCK_TRIM: + freeSize = GetAvailWriteSpace(wRingBuffer); + RingBufferPush(wRingBuffer, buffer, MIN(freeSize, numBytes)); + break; + + case RTT_VIEWER_MODE_BLOCK_IF_FIFO_FULL: + writeBytes = RingBufferBlockPush(wRingBuffer, buffer, numBytes); + break; + + default: + break; + } + + RttViewerUnlock(intSave); + + return OS_OK; +} + +/* + * 描述: 参数校验 + */ +unsigned int RttViewerReadParaCheck(unsigned int chn, const void *buffer, unsigned int numBytes) +{ + if (chn >= RTT_VIEWER_RB_MAX_NUM) { + return OS_ERROR; + } + + if (buffer == NULL) { + return OS_ERROR; + } + + if ((numBytes == 0) || (numBytes > RTT_VIEWER_RB_BUFFER_SIZE)) { + return OS_ERROR; + } + + return OS_OK; +} + +/* + * 描述: rtt viewer读数据 + */ +unsigned int RttViewerRead(unsigned int chn, void *buffer, unsigned int numBytes) +{ + unsigned int ret; + unsigned int intSave; + unsigned int numBytesRem; + unsigned int numBytesRead; + unsigned int rIdx; + unsigned int wIdx; + volatile char *src; + RTT_VIEWER_RING_BUFFER *rRingBuffer; + + if (memcmp(g_rttViewerCb.acID, "SEGGER RTT", sizeof("SEGGER RTT")) != 0) { + return OS_ERROR; + } + + /* 校验入参 */ + ret = RttViewerReadParaCheck(chn, buffer, numBytes); + if (ret != OS_OK) { + return 0; + } + + intSave = RttViewerLock(); + + rRingBuffer = &g_rttViewerCb.aDown[chn]; + rIdx = rRingBuffer->rIdx; + wIdx = rRingBuffer->wIdx; + numBytesRead = 0u; + + if (rIdx > wIdx) { + numBytesRem = rRingBuffer->size - rIdx; + numBytesRem = MIN(numBytesRem, numBytes); + src = rRingBuffer->pBuffer + rIdx; + memcpy_s(buffer, numBytesRem, (void*)src, numBytesRem); + + numBytesRead += numBytesRem; + buffer += numBytesRem; + numBytes -= numBytesRem; + rIdx += numBytesRem; + if (rIdx == rRingBuffer->size) { + rIdx = 0u; + } + } + + numBytesRem = wIdx - rIdx; + numBytesRem = MIN(numBytesRem, numBytes); + if (numBytesRem > 0) { + src = rRingBuffer->pBuffer + rIdx; + memcpy_s(buffer, numBytesRem, (void*)src, numBytesRem); + + numBytesRead += numBytesRem; + buffer += numBytesRem; + numBytes -= numBytesRem; + rIdx += numBytesRem; + } + + if (numBytesRead) { + rRingBuffer->rIdx = rIdx; + } + + RttViewerUnlock(intSave); + + return numBytesRead; +} + +/* + * 描述: rtt viewer输出单个字符 + */ +unsigned int RttViewerPutChar(unsigned int chn, char c) +{ + unsigned int ret; + + if (chn >= RTT_VIEWER_WB_MAX_NUM) { + return OS_ERROR; + } + + ret = RttViewerWrite(chn, &c, 1); + + return ret; +} + +char g_rttViewerShowBuffer[RTT_VIEWER_MAX_SHOW_LEN]; + +/* + * 描述: rtt viewer打印函数 + */ +unsigned int RttViewerPrintf(unsigned int chn, const char *format, ...) +{ + unsigned int ret; + int len; + char *str = g_rttViewerShowBuffer; + va_list vaList; + + if (chn >= RTT_VIEWER_WB_MAX_NUM) { + return OS_ERROR; + } + + va_start(vaList, format); + len = vsnprintf_s(str, RTT_VIEWER_MAX_SHOW_LEN, RTT_VIEWER_MAX_SHOW_LEN, format, vaList); + va_end(vaList); + if (len == -1) { + return len; + } + + ret = RttViewerWrite(chn, str, len); + + return ret; +} diff --git a/demos/helloworld/bsp/rtt_viewer.h b/demos/helloworld/bsp/rtt_viewer.h new file mode 100644 index 0000000..821b1b9 --- /dev/null +++ b/demos/helloworld/bsp/rtt_viewer.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: Hardware interrupt implementation + */ +#ifndef RTT_VIEWER_H +#define RTT_VIEWER_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define RTT_VIEWER_MODE_NO_BLOCK_SKIP 0 +#define RTT_VIEWER_MODE_NO_BLOCK_TRIM 1 +#define RTT_VIEWER_MODE_BLOCK_IF_FIFO_FULL 2 +#define RTT_VIEWER_MODE_MASK 3 + +#ifndef RTT_VIEWER_MODE_DEFAULT +#define RTT_VIEWER_MODE_DEFAULT RTT_VIEWER_MODE_NO_BLOCK_SKIP +#endif + +#ifndef RTT_VIEWER_WB_MAX_NUM +#define RTT_VIEWER_WB_MAX_NUM 1 +#endif + +#ifndef RTT_VIEWER_RB_MAX_NUM +#define RTT_VIEWER_RB_MAX_NUM 1 +#endif + +#ifndef RTT_VIEWER_WB_BUFFER_SIZE +#define RTT_VIEWER_WB_BUFFER_SIZE 1024 +#endif + +#ifndef RTT_VIEWER_RB_BUFFER_SIZE +#define RTT_VIEWER_RB_BUFFER_SIZE 16 +#endif + +#ifndef RTT_VIEWER_MAX_INT_PRI +#define RTT_VIEWER_MAX_INT_PRI 0x20 +#endif + +#ifndef RTT_VIEWER_MAX_SHOW_LEN +#define RTT_VIEWER_MAX_SHOW_LEN 0x200 +#endif + +#define RTT_DMB() __asm volatile ("dmb\n" : : :); + +#define RTT_VIEWER_CTRL_RESET "\x1B[0m" +#define RTT_VIEWER_CTRL_CLEAR "\x1B[2J" + +#define RTT_VIEWER_CTRL_TEXT_BLACK "\x1B[2;30m" +#define RTT_VIEWER_CTRL_TEXT_RED "\x1B[2;31m" +#define RTT_VIEWER_CTRL_TEXT_GREEN "\x1B[2;32m" +#define RTT_VIEWER_CTRL_TEXT_YELLOW "\x1B[2;33m" +#define RTT_VIEWER_CTRL_TEXT_BLUE "\x1B[2;34m" +#define RTT_VIEWER_CTRL_TEXT_MAGENTA "\x1B[2;35m" +#define RTT_VIEWER_CTRL_TEXT_CYAN "\x1B[2;36m" +#define RTT_VIEWER_CTRL_TEXT_WHITE "\x1B[2;37m" + +#define RTT_VIEWER_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m" +#define RTT_VIEWER_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m" +#define RTT_VIEWER_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m" +#define RTT_VIEWER_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m" +#define RTT_VIEWER_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m" +#define RTT_VIEWER_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m" +#define RTT_VIEWER_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m" +#define RTT_VIEWER_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m" + +#define RTT_VIEWER_CTRL_BG_BLACK "\x1B[24;40m" +#define RTT_VIEWER_CTRL_BG_RED "\x1B[24;41m" +#define RTT_VIEWER_CTRL_BG_GREEN "\x1B[24;42m" +#define RTT_VIEWER_CTRL_BG_YELLOW "\x1B[24;43m" +#define RTT_VIEWER_CTRL_BG_BLUE "\x1B[24;44m" +#define RTT_VIEWER_CTRL_BG_MAGENTA "\x1B[24;45m" +#define RTT_VIEWER_CTRL_BG_CYAN "\x1B[24;46m" +#define RTT_VIEWER_CTRL_BG_WHITE "\x1B[24;47m" + +#define RTT_VIEWER_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m" +#define RTT_VIEWER_CTRL_BG_BRIGHT_RED "\x1B[4;41m" +#define RTT_VIEWER_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m" +#define RTT_VIEWER_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m" +#define RTT_VIEWER_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m" +#define RTT_VIEWER_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m" +#define RTT_VIEWER_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m" +#define RTT_VIEWER_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m" + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +/* + * rtt viewer环形缓冲区 + */ +typedef struct { + const char *sName; + char *pBuffer; + unsigned int size; + unsigned int wIdx; + volatile unsigned int rIdx; + unsigned int flags; +} RTT_VIEWER_RING_BUFFER; + +typedef struct { + char acID[16]; + int wbMaxNum; + int rbMaxNum; + RTT_VIEWER_RING_BUFFER aUp[RTT_VIEWER_WB_MAX_NUM]; + RTT_VIEWER_RING_BUFFER aDown[RTT_VIEWER_RB_MAX_NUM]; +} TagRttViewerCb; + +extern TagRttViewerCb _SEGGER_RTT; +#define g_rttViewerCb _SEGGER_RTT + +void RttViewerInit(void); +unsigned int RttViewerModeSet(unsigned int chn, unsigned int mode); +unsigned int RttViewerWrite(unsigned int chn, const void *buffer, unsigned int numBytes); +unsigned int RttViewerRead(unsigned int chn, void *buffer, unsigned int numBytes); +unsigned int RttViewerPutChar(unsigned int chn, char c); +unsigned int RttViewerPrintf(unsigned int chn, const char *format, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* RTT_VIEWER_H */ diff --git a/demos/helloworld/build/build_app.sh b/demos/helloworld/build/build_app.sh new file mode 100644 index 0000000..eb4042a --- /dev/null +++ b/demos/helloworld/build/build_app.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Copyright (c) 2023 Huawei Device Co., Ltd. +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. + +export TOOLCHAIN_PATH=/opt/buildtools/gcc-arm-none-eabi-10-2020-q4-major +export APP=helloworld +export TMP_DIR=$APP + +sh ./build_static.sh + +cmake -S .. -B $TMP_DIR -DAPP:STRING=$APP -DTOOLCHAIN_PATH:STRING=$TOOLCHAIN_PATH +pushd $TMP_DIR +make $APP +popd +cp $TMP_DIR/$APP $APP.elf +$TOOLCHAIN_PATH/bin/arm-none-eabi-objcopy -O binary $TMP_DIR/$APP $APP.bin +rm -rf $TMP_DIR diff --git a/demos/helloworld/build/build_static.sh b/demos/helloworld/build/build_static.sh new file mode 100644 index 0000000..48f3567 --- /dev/null +++ b/demos/helloworld/build/build_static.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Copyright (c) 2023 Huawei Device Co., Ltd. +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. + +git clone https://gitee.com/openeuler/libboundscheck.git + +cp libboundscheck/include/* ../../../platform/libboundscheck/include +cp libboundscheck/include/* ../include +cp libboundscheck/src/* ../../../platform/libboundscheck/src +rm -rf libboundscheck + +pushd ./../../../ +python build.py m4 +cp output/UniProton/lib/cortex_m4/* demos/helloworld/libs +cp output/libboundscheck/lib/cortex_m4/* demos/helloworld/libs +cp -r src/include/uapi/* demos/helloworld/include +popd diff --git a/demos/helloworld/build/examples.ld b/demos/helloworld/build/examples.ld new file mode 100644 index 0000000..687caf7 --- /dev/null +++ b/demos/helloworld/build/examples.ld @@ -0,0 +1,76 @@ +/***********************************************************/ +/* Configure memory regions */ +MEMORY +{ + IROM (rwx) : ORIGIN = 0x08000000, LENGTH = 0x00100000 + SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0001A000 + SYSSTACK (rwx) : ORIGIN = 0x2001A000, LENGTH = 0x2000 +} + +ENTRY(OsResetVector) + +SECTIONS +{ + .resetzone : + { + __text_section_start = .; + KEEP(*(.reset)) + } > IROM + + .text : + { + . = ALIGN(4); + __text_start__ = .; + *(.text*) + *(.rodata*) + *(.kernel*) + *(.rel*) + } > IROM + + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + . = ALIGN(4); + } > IROM + + .data : AT(LOADADDR(.ARM.exidx) + SIZEOF(.ARM.exidx)) + { + __text_end__ = LOADADDR(.data); + __data_start__ = .; + KEEP(*(VECTOR)) + *(vtable) + *(.data*) + . = ALIGN(4); + __data_end__ = .; + } > SRAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + g_bssStart = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + g_bssEnd = .; + } > SRAM + + .osStack : + { + g_stackStart = .; + . = . + 0x2000; + g_stackEnd = .; + } > SYSSTACK + + .heap (COPY): + { + __end__ = .; + end = __end__; + *(.heap*) + __HeapLimit = .; + } > SYSSTACK +} + +/***********************************************************/ + diff --git a/demos/helloworld/build/readme.txt b/demos/helloworld/build/readme.txt new file mode 100644 index 0000000..096fc53 --- /dev/null +++ b/demos/helloworld/build/readme.txt @@ -0,0 +1,3 @@ +本目录中的build_app.sh可以构建出/../apps中的示例镜像: +1、在sh中选择/更改EXAMPLE的工程目录名(helloworld),默认使用helloworld +2、将编译工具的路径和编译工具的静态库路径配置正确,编译工具在compiler目录取出安装使用; diff --git a/demos/helloworld/config/CMakeLists.txt b/demos/helloworld/config/CMakeLists.txt new file mode 100644 index 0000000..ab9f478 --- /dev/null +++ b/demos/helloworld/config/CMakeLists.txt @@ -0,0 +1,2 @@ +set(SRCS prt_config.c) +add_library(config OBJECT ${SRCS}) diff --git a/demos/helloworld/config/prt_buildef.h b/demos/helloworld/config/prt_buildef.h new file mode 100644 index 0000000..8b25d71 --- /dev/null +++ b/demos/helloworld/config/prt_buildef.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: the common part buildef.h + */ +#ifndef PRT_BUILDEF_H +#define PRT_BUILDEF_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define OS_ARCH_ARMV7_M + +#ifndef OS_HARDWARE_PLATFORM +#define OS_HARDWARE_PLATFORM OS_CORTEX_M4 +#endif + +#ifndef OS_CPU_TYPE +#define OS_CPU_TYPE OS_STM32F407 +#endif + +#define OS_MAX_CORE_NUM 1 + +#ifndef OS_BYTE_ORDER +#define OS_BYTE_ORDER OS_LITTLE_ENDIAN +#endif + +#define OS_OPTION_EVENT + +#define OS_OPTION_QUEUE + +#define OS_OPTION_HWI_COMBINE + +#define OS_OPTION_HWI_PRIORITY + +#define OS_OPTION_HWI_ATTRIBUTE + +#define OS_OPTION_HWI_MAX_NUM_CONFIG + +#define OS_OPTION_TASK + +#define OS_OPTION_TASK_DELETE + +#define OS_OPTION_TASK_SUSPEND + +#define OS_OPTION_TASK_INFO + +#define OS_OPTION_TASK_YIELD + +#define OS_TSK_PRIORITY_HIGHEST 0 + +#define OS_TSK_PRIORITY_LOWEST 31 + +#define OS_TSK_NUM_OF_PRIORITIES 32 + +#define OS_TSK_CORE_BYTES_IN_PID 2 + +#define OS_OPTION_CPUP + +#define OS_OPTION_CPUP_WARN + +#define OS_OPTION_RND + +#define OS_LITTLE_ENDIAN 0x1234 + +#define OS_BIG_ENDIAN 0x4321 + +#define OS_CORTEX_M4 0x1 + +#define OS_STM32F407 0x1 + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif diff --git a/demos/helloworld/config/prt_config.c b/demos/helloworld/config/prt_config.c new file mode 100644 index 0000000..06769a5 --- /dev/null +++ b/demos/helloworld/config/prt_config.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton的初始化C文件。 + */ +#include "prt_config_internal.h" + +U8 m_aucMemRegion00[OS_MEM_FSC_PT_SIZE] ; /* 私有静态内存分区(缺省) */ + +OS_SEC_ALW_INLINE INLINE void OsConfigAddrSizeGet(uintptr_t addr, uintptr_t size, + uintptr_t *destAddr, uintptr_t *destSize) +{ + *destAddr = addr; + *destSize = size; +} + +U32 OsMemConfigReg(void) +{ + U32 ret; + + ret = OsFscMemInit(OS_MEM_FSC_PT_ADDR, OS_MEM_FSC_PT_SIZE); + if (ret != OS_OK) { + return ret; + } + + return OS_OK; +} + +U32 OsMemDefPtInit(void) +{ + return OS_OK; +} + +U32 OsMemConfigInit(void) +{ + /* 系统默认FSC内存分区初始化 */ + return OsMemDefPtInit(); +} + +U32 OsSystemReg(void) +{ + struct SysModInfo sysModInfo; + + sysModInfo.systemClock = OS_SYS_CLOCK; + sysModInfo.cpuType = OS_CPU_TYPE; +#if defined(OS_OPTION_HWI_MAX_NUM_CONFIG) + sysModInfo.hwiMaxNum = OS_HWI_MAX_NUM_CONFIG; +#endif + + return OsSysRegister(&sysModInfo); +} + +#if (OS_INCLUDE_SEM == YES) +U32 OsSemConfigReg(void) +{ + struct SemModInfo semModInfo; + + semModInfo.maxNum = OS_SEM_MAX_SUPPORT_NUM; + return OsSemRegister(&semModInfo); + +} +#endif + +#if (OS_INCLUDE_TASK == YES) +void OsTaskInfoSet(struct TskModInfo *taskModInfo) +{ + taskModInfo->maxNum = OS_TSK_MAX_SUPPORT_NUM; + taskModInfo->defaultSize = OS_TSK_DEFAULT_STACK_SIZE; + taskModInfo->idleStackSize = OS_TSK_IDLE_STACK_SIZE; + taskModInfo->magicWord = WORD_PACK((U32)OS_TSK_STACK_MAGIC_WORD); +} +#else +#error "OS_INCLUDE_TASK MUST BE YES! The SWI has been cut out,the task can not cut out." +#endif + +U32 OsHookConfigReg(void) +{ + struct HookModInfo hookModInfo; + + hookModInfo.maxNum[OS_HOOK_HWI_ENTRY] = OS_HOOK_HWI_ENTRY_NUM; + hookModInfo.maxNum[OS_HOOK_HWI_EXIT] = OS_HOOK_HWI_EXIT_NUM; + hookModInfo.maxNum[OS_HOOK_TSK_SWITCH] = OS_HOOK_TSK_SWITCH_NUM; + hookModInfo.maxNum[OS_HOOK_IDLE_PERIOD] = OS_HOOK_IDLE_NUM; + + return OsHookRegister(&hookModInfo); +} + +U32 OsSysConfigReg(void) +{ + U32 ret; + + ret = OsSystemReg(); + if (ret != OS_OK) { + return ret; + } + return OS_OK; +} + +#if (OS_INCLUDE_TICK == YES) +U32 OsTickConfigReg(void) +{ + struct TickModInfo tickModInfo; + + tickModInfo.tickPerSecond = OS_TICK_PER_SECOND; + tickModInfo.tickPriority = 0; + + return OsTickRegister(&tickModInfo); +} +#endif + +#if (OS_INCLUDE_TASK == YES) +U32 OsTskConfigReg(void) +{ + struct TskModInfo taskModInfo; + OsTaskInfoSet(&taskModInfo); + return OsTskRegister(&taskModInfo); +} +#endif + +#if (OS_INCLUDE_QUEUE == YES) +U32 OsQueueConfigReg(void) +{ + return OsQueueRegister(OS_QUEUE_MAX_SUPPORT_NUM); +} +#endif + +#if (OS_INCLUDE_CPUP == YES) +U32 OsCpupConfigReg(void) +{ + struct CpupModInfo cpupModInfo; + + cpupModInfo.cpupWarnFlag = (bool)OS_CONFIG_CPUP_WARN; + cpupModInfo.sampleTime = OS_CPUP_SAMPLE_INTERVAL; + cpupModInfo.warn = OS_CPUP_SHORT_WARN; + cpupModInfo.resume = OS_CPUP_SHORT_RESUME; + + return OsCpupRegister(&cpupModInfo); +} +#endif + +#if (OS_INCLUDE_TICK_SWTMER == YES) +U32 OsSwTmrConfigInit(void) +{ + return OsSwTmrInit(OS_TICK_SWITIMER_MAX_NUM); +} +#endif + +#if (OS_INCLUDE_CPUP == YES) +#if (OS_INCLUDE_TICK == NO) +#error "OS_INCLUDE_CPUP depend on OS_INCLUDE_TICK!" +#endif +U32 OsCpupConfigInit(void) +{ + U32 ret; + + ret = OsCpupInit(); + if (ret != OS_OK) { + return ret; + } + + if (OS_CONFIG_CPUP_WARN == YES) { +#if defined(OS_OPTION_CPUP_WARN) + OsCpupWarnInit(); +#else + return OS_ERRNO_SYS_NO_CPUP_WARN; +#endif + } + return OS_OK; +} +#endif + +#if (OS_INCLUDE_SEM == YES) +U32 OsSemConfigInit(void) +{ + return OsSemInit(); +} +#endif + +#if (OS_INCLUDE_TASK == YES) +U32 OsTskConfigInit(void) +{ + return OsTskInit(); +} +#endif + +/* 系统初始化注册表 */ +struct OsModuleConfigInfo g_moduleConfigTab[] = { + /* {模块号, 模块注册函数, 模块初始化函数} */ + {OS_MID_SYS, {OsSysConfigReg, NULL}}, + {OS_MID_MEM, {OsMemConfigReg, OsMemConfigInit}}, + {OS_MID_HWI, {NULL, OsHwiConfigInit}}, + {OS_MID_HARDDRV, {NULL, PRT_HardDrvInit}}, + {OS_MID_HOOK, {OsHookConfigReg, OsHookConfigInit}}, + {OS_MID_EXC, {NULL, OsExcConfigInit}}, +#if (OS_INCLUDE_TASK == YES) + {OS_MID_TSK, {OsTskConfigReg, OsTskConfigInit}}, +#endif +#if (OS_INCLUDE_TICK == YES) + {OS_MID_TICK, {OsTickConfigReg, OsTickConfigInit}}, +#endif + +#if (OS_INCLUDE_TICK_SWTMER == YES) + {OS_MID_SWTMR, {NULL, OsSwTmrConfigInit}}, +#endif + +#if (OS_INCLUDE_CPUP == YES) + {OS_MID_CPUP, {OsCpupConfigReg, OsCpupConfigInit}}, +#endif +#if (OS_INCLUDE_SEM == YES) + {OS_MID_SEM, {OsSemConfigReg, OsSemConfigInit}}, +#endif +#if (OS_INCLUDE_QUEUE == YES) + {OS_MID_QUEUE, {OsQueueConfigReg, OsQueueConfigInit}}, +#endif + {OS_MID_APP, {NULL, PRT_AppInit}}, + + {OS_MID_BUTT, {NULL, NULL}}, +}; + +/* + * 描述:OS模块注册、初始化运行函数 + */ +U32 OsModuleConfigRun(enum OsinitPhaseId initPhaseId, U32 initPhase) +{ + U32 idx = 0; + U32 ret = OS_OK; + while (g_moduleConfigTab[idx].moudleId != OS_MID_BUTT) { + if (g_moduleConfigTab[idx].moudleConfigFunc[initPhaseId] == NULL) { + idx++; + continue; + } + ret = g_moduleConfigTab[idx].moudleConfigFunc[initPhaseId](); + if (ret != OS_OK) { + break; + } + idx++; + } + return ret; +} +U32 OsRegister(void) +{ + return OsModuleConfigRun(OS_REGISTER_ID, OS_REGISTER_PHASE); +} + +/* + * 描述:OsInitialize阶段 + */ +U32 OsInitialize(void) +{ + return OsModuleConfigRun(OS_INIT_ID, OS_INITIALIZE_PHASE); +} + +/* + * 描述:OsStart阶段 + */ +U32 OsStart(void) +{ + U32 ret; + +#if (OS_INCLUDE_TICK == YES) + /* 表示系统在进行启动阶段,匹配MOUDLE_ID之后,标记进入TICK模块的启动 */ + ret = OsTickStart(); + if (ret != OS_OK) { + return ret; + } +#endif + +#if (OS_INCLUDE_TASK == YES) + /* 表示系统在进行启动阶段,匹配MOUDLE_ID之后,标记进入任务模块的启动 */ + ret = OsActivate(); +#else + ret = OS_OK; +#endif + + return ret; +} + +S32 OsConfigStart(void) +{ + U32 ret; + + OsHwInit(); + + /* OS模块注册 */ + ret = OsRegister(); + if (ret != OS_OK) { + return (S32)ret; + } + + /* OS模块初始化 */ + ret = OsInitialize(); + if (ret != OS_OK) { + return (S32)ret; + } + + /* OS启动调度 */ + ret = OsStart(); + if (ret != OS_OK) { + return (S32)ret; + } + + /* Execution should not reach this point */ + return (S32)OS_ERROR; +} diff --git a/demos/helloworld/config/prt_config.h b/demos/helloworld/config/prt_config.h new file mode 100644 index 0000000..6980fc9 --- /dev/null +++ b/demos/helloworld/config/prt_config.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton配置头文件,裁剪开关和配置项。 + */ +#ifndef PRT_CONFIG_H +#define PRT_CONFIG_H + +#include "prt_buildef.h" +#include "prt_typedef.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/* ***************************** 配置系统基本信息 ******************************* */ +/* 芯片主频 */ +#define OS_SYS_CLOCK 168000000 + +/* ***************************** 中断模块配置 ************************** */ +/* 硬中断最大支持个数 */ +#define OS_HWI_MAX_NUM_CONFIG 87 + +/* ***************************** 配置Tick中断模块 *************************** */ +/* Tick中断模块裁剪开关 */ +#define OS_INCLUDE_TICK YES +/* Tick中断时间间隔,tick处理时间不能超过1/OS_TICK_PER_SECOND(s) */ +#define OS_TICK_PER_SECOND 5000 + +/* ***************************** 配置定时器模块 ***************************** */ +/* 基于TICK的软件定时器裁剪开关 */ +#define OS_INCLUDE_TICK_SWTMER YES +/* 基于TICK的软件定时器最大个数 */ +#define OS_TICK_SWITIMER_MAX_NUM 8 + +/* ***************************** 配置任务模块 ******************************* */ +/* 任务模块裁剪开关 */ +#define OS_INCLUDE_TASK YES +/* 最大支持的任务数,最大共支持254个 */ +#define OS_TSK_MAX_SUPPORT_NUM 8 +/* 缺省的任务栈大小 */ +#define OS_TSK_DEFAULT_STACK_SIZE 0x800 +/* IDLE任务栈的大小 */ +#define OS_TSK_IDLE_STACK_SIZE 0x800 +/* 任务栈初始化魔术字,默认是0xCA,只支持配置一个字节 */ +#define OS_TSK_STACK_MAGIC_WORD 0xCA + +/* ***************************** 配置CPU占用率及CPU告警模块 **************** */ +/* CPU占用率模块裁剪开关 */ +#define OS_INCLUDE_CPUP NO +/* 采样时间间隔(单位tick),若其值大于0,则作为采样周期,否则两次调用PRT_CpupNow或PRT_CpupThread间隔作为周期 */ +#define OS_CPUP_SAMPLE_INTERVAL 0 +/* CPU占用率告警动态配置项 */ +#define OS_CONFIG_CPUP_WARN NO +/* CPU占用率告警阈值(精度为万分比) */ +#define OS_CPUP_SHORT_WARN 0 +/* CPU占用率告警恢复阈值(精度为万分比) */ +#define OS_CPUP_SHORT_RESUME 0 + +/* ***************************** 配置内存管理模块 ************************** */ +/* 用户可以创建的最大分区数,取值范围[0,253] */ +#define OS_MEM_MAX_PT_NUM 10 +/* 私有FSC内存分区起始地址 */ +#define OS_MEM_FSC_PT_ADDR (U32)&m_aucMemRegion00[0] +/* 私有FSC内存分区大小 */ +#define OS_MEM_FSC_PT_SIZE 0x00008000 + +/* ***************************** 配置信号量管理模块 ************************* */ +/* 信号量模块裁剪开关 */ +#define OS_INCLUDE_SEM YES + +/* 最大支持的信号量数 */ +#define OS_SEM_MAX_SUPPORT_NUM 10 + +/* ***************************** 配置队列模块 ******************************* */ +/* 队列模块裁剪开关 */ +#define OS_INCLUDE_QUEUE YES +/* 最大支持的队列数,范围(0,0xFFFF] */ +#define OS_QUEUE_MAX_SUPPORT_NUM 10 + +/* ************************* 钩子模块配置 *********************************** */ +/* 硬中断进入钩子最大支持个数, 范围[0, 255] */ +#define OS_HOOK_HWI_ENTRY_NUM 20 +/* 硬中断退出钩子最大支持个数, 范围[0, 255] */ +#define OS_HOOK_HWI_EXIT_NUM 19 +/* 任务切换钩子最大支持个数, 范围[0, 255] */ +#define OS_HOOK_TSK_SWITCH_NUM 14 +/* IDLE钩子最大支持个数, 范围[0, 255] */ +#define OS_HOOK_IDLE_NUM 13 + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +#endif /* PRT_CONFIG_H */ diff --git a/demos/helloworld/config/prt_config_internal.h b/demos/helloworld/config/prt_config_internal.h new file mode 100644 index 0000000..47d2635 --- /dev/null +++ b/demos/helloworld/config/prt_config_internal.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton配置私有文件。 + */ +#ifndef PRT_CONFIG_INTERNAL_H +#define PRT_CONFIG_INTERNAL_H + +#include +#include "prt_config.h" +#include "prt_sys.h" +#include "prt_task.h" +#include "prt_sem.h" +#include "prt_tick.h" +#include "prt_exc.h" +#include "prt_cpup.h" +#include "prt_mem.h" +#include "prt_hook.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +#define WORD_PACK(val) (((val) << 24) | ((val) << 16) | ((val) << 8) | (val)) + +enum OsinitPhaseId { + OS_REGISTER_ID = 0, + OS_INIT_ID, + OS_MOUDLE_CONFIG +}; + +extern U8 m_aucMemRegion00[OS_MEM_FSC_PT_SIZE] ; /* 私有静态内存分区(缺省) */ + +/* UniProton模块注册函数的声明 */ +extern U32 OsFscMemInit(U32 addr, U32 size); +extern U32 OsSysRegister(struct SysModInfo *modInfo); +extern U32 OsTickRegister(struct TickModInfo *modInfo); +extern U32 OsTskRegister(struct TskModInfo *modInfo); +extern U32 OsCpupRegister(struct CpupModInfo *modInfo); +extern U32 OsSemRegister(const struct SemModInfo *modInfo); +extern U32 OsHookRegister(struct HookModInfo *modInfo); + +extern U32 OsHwiConfigInit(void); +extern U32 OsTickConfigInit(void); +extern U32 OsTskInit(void); +extern U32 OsCpupInit(void); +extern void OsCpupWarnInit(void); +extern U32 OsExcConfigInit(void); +extern U32 OsSemInit(void); +extern U32 OsHookConfigInit(void); + +/* UniProton系统启动相关函数的声明 */ +extern void OsHwInit(void); +extern U32 OsActivate(void); +extern U32 OsTickStart(void); +extern U32 PRT_HardDrvInit(void); +/* Notes: PRT_HardBootInit接口在栈保护支持随机数设置场景下必须在bss初始化后调用 */ +extern void PRT_HardBootInit(void); +extern U32 PRT_AppInit(void); + +extern U32 OsQueueRegister(U16 maxQueue); +extern U32 OsQueueConfigInit(void); + +#if (OS_INCLUDE_TICK_SWTMER == YES) +extern U32 OsSwTmrInit(U32 maxTimerNum); +#endif + +typedef U32 (*ConfigInitFunc)(void); +struct OsModuleConfigInfo { + enum MoudleId moudleId; + ConfigInitFunc moudleConfigFunc[OS_MOUDLE_CONFIG]; +}; + +extern S32 OsConfigStart(void); +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +#endif /* PRT_CONFIG_INTERNAL_H */ diff --git a/demos/helloworld/include/.keep b/demos/helloworld/include/.keep new file mode 100644 index 0000000..be72af3 --- /dev/null +++ b/demos/helloworld/include/.keep @@ -0,0 +1,10 @@ +# Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. +# +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. diff --git a/demos/helloworld/libs/.keep b/demos/helloworld/libs/.keep new file mode 100644 index 0000000..be72af3 --- /dev/null +++ b/demos/helloworld/libs/.keep @@ -0,0 +1,10 @@ +# Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. +# +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. diff --git a/demos/helloworld/readme.txt b/demos/helloworld/readme.txt new file mode 100644 index 0000000..bfb4c15 --- /dev/null +++ b/demos/helloworld/readme.txt @@ -0,0 +1,9 @@ +本目录下放置的是UniProton实时部分版本。 + +├─apps # 基于UniProton实时OS编程的demo程序; +│ └─hello_world # hello_world示例程序; +├─bsp # 提供的板级驱动与OS对接; +├─build # 提供编译脚本编译出最终镜像; +├─config # 配置选项,供用户调整运行时参数; +├─include # UniProton实时部分提供的编程接口API; +└─libs # UniProton实时部分的静态库,build目录中的makefile示例已经将头文件和静态库的引用准备好,应用可直接使用; diff --git a/demos/hi3093/CMakeLists.txt b/demos/hi3093/CMakeLists.txt new file mode 100644 index 0000000..83817d4 --- /dev/null +++ b/demos/hi3093/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.12) +project(exmaples LANGUAGES C ASM) + +set(CMAKE_C_COMPILER ${TOOLCHAIN_PATH}/bin/aarch64-none-elf-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PATH}/bin/aarch64-none-elf-g++) +set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PATH}/bin/aarch64-none-elf-gcc) +set(CMAKE_LINKER ${TOOLCHAIN_PATH}/bin/aarch64-none-elf-ld) + +set(POSIX_OPTION "-D_POSIX_THREADS -D_POSIX_THREAD_PRIORITY_SCHEDULING -D_POSIX_PRIORITY_SCHEDULING -D_POSIX_TIMERS -D_POSIX_CPUTIME -D_POSIX_THREAD_CPUTIME -D_POSIX_MONOTONIC_CLOCK -D_POSIX_TIMEOUTS -D_POSIX_CLOCK_SELECTION -D_POSIX_THREAD_PRIO_PROTECT -D_UNIX98_THREAD_MUTEX_ATTRIBUTES -D_POSIX_READER_WRITER_LOCKS") +set(CC_OPTION "-g -march=armv8.2-a+nofp+nosimd -Wl,--build-id=none -fno-builtin -fno-PIE -Wall -fno-dwarf2-cfi-asm -O0 -mcmodel=large -fomit-frame-pointer -fzero-initialized-in-bss -fdollars-in-identifiers -ffunction-sections -fdata-sections -fno-common -fno-aggressive-loop-optimizations -fno-optimize-strlen -fno-schedule-insns -fno-inline-small-functions -fno-inline-functions-called-once -fno-strict-aliasing -fno-builtin -finline-limit=20 -mstrict-align -mlittle-endian -specs=nosys.specs -nostartfiles -funwind-tables") +set(AS_OPTION "-g -march=armv8.2-a+nofp+nosimd -Wl,--build-id=none -fno-builtin -fno-PIE -Wall -fno-dwarf2-cfi-asm -O0 -mcmodel=large -fomit-frame-pointer -fzero-initialized-in-bss -fdollars-in-identifiers -ffunction-sections -fdata-sections -fno-common -fno-aggressive-loop-optimizations -fno-optimize-strlen -fno-schedule-insns -fno-inline-small-functions -fno-inline-functions-called-once -fno-strict-aliasing -fno-builtin -finline-limit=20 -mstrict-align -mlittle-endian -nostartfiles -mgeneral-regs-only -DENV_EL1") +set(LD_OPTION "-static -no-pie -Wl,--wrap=memset -Wl,--wrap=memcpy") +set(CMAKE_C_FLAGS "${CC_OPTION} ${POSIX_OPTION}") +set(CMAKE_ASM_FLAGS "${AS_OPTION} ${POSIX_OPTION}") +set(CMAKE_LINK_FLAGS "${LD_OPTION} -T ../hi3093.ld") +set(CMAKE_EXE_LINKER_FLAGS "${LD_OPTION} -T ../hi3093.ld") + +include_directories( + ./include + ./config + ./bsp + ./bsp/hi3093 + ./bsp/uart + ./apps/openamp + ./build/open-amp/output/usr/local/include + ./build/libmetal/output/usr/local/include +) + +link_directories(./libs) +link_libraries( + -Wl,--start-group + "${CMAKE_CURRENT_SOURCE_DIR}/libs/libCortexMXsec_c.lib" + "${CMAKE_CURRENT_SOURCE_DIR}/libs/libHI3093.a" + "${CMAKE_CURRENT_SOURCE_DIR}/libs/libmetal.a" + "${CMAKE_CURRENT_SOURCE_DIR}/libs/libopen_amp.a" + -Wl,--end-group +) + +add_subdirectory(bsp) +add_subdirectory(config) +add_subdirectory(apps) + +list(APPEND OBJS $ $ $ $) +add_executable(${APP} ${OBJS}) diff --git a/demos/hi3093/apps/CMakeLists.txt b/demos/hi3093/apps/CMakeLists.txt new file mode 100644 index 0000000..e9ada4d --- /dev/null +++ b/demos/hi3093/apps/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(openamp) diff --git a/demos/hi3093/apps/openamp/CMakeLists.txt b/demos/hi3093/apps/openamp/CMakeLists.txt new file mode 100644 index 0000000..e56098a --- /dev/null +++ b/demos/hi3093/apps/openamp/CMakeLists.txt @@ -0,0 +1,2 @@ +set(SRC rpmsg_backend.c rpmsg_service.c main.c) +add_library(rpmsg OBJECT ${SRC}) diff --git a/demos/hi3093/apps/openamp/main.c b/demos/hi3093/apps/openamp/main.c new file mode 100644 index 0000000..dfc7451 --- /dev/null +++ b/demos/hi3093/apps/openamp/main.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * See the Mulan PSL v2 for more details. + * Create: 2022-12-05 + * Description: openamp configuration + */ +#include +#include +#include +#include +#include "securec.h" +#include "prt_config.h" +#include "prt_config_internal.h" +#include "prt_task.h" +#include "test.h" + +TskHandle g_testTskHandle; +U8 g_memRegion00[OS_MEM_FSC_PT_SIZE]; + +extern U32 PRT_PrintfInit(); + +#if defined(OS_OPTION_OPENAMP) +int TestOpenamp() +{ + int ret; + + ret = rpmsg_service_init(); + if (ret) { + return ret; + } + + return OS_OK; +} +#endif + +void TestTaskEntry() +{ +#if defined(OS_OPTION_OPENAMP) + TestOpenamp(); +#endif +} + +U32 OsTestInit(void) +{ + U32 ret; + U8 ptNo = OS_MEM_DEFAULT_FSC_PT; + struct TskInitParam param = {0}; + + param.stackAddr = (U32)PRT_MemAllocAlign(0, ptNo, 0x2000, MEM_ADDR_ALIGN_016); + param.taskEntry = (TskEntryFunc)TestTaskEntry; + param.taskPrio = 25; + param.name = "TestTask"; + param.stackSize = 0x2000; + + ret = PRT_TaskCreate(&g_testTskHandle, ¶m); + if (ret) { + return ret; + } + + ret = PRT_TaskResume(g_testTskHandle); + if (ret) { + return ret; + } + + return OS_OK; +} + +U32 PRT_AppInit(void) +{ + U32 ret; + + ret = OsTestInit(); + if (ret) { + return ret; + } + + ret = TestClkStart(); + if (ret) { + return ret; + } + + return OS_OK; +} + +U32 PRT_HardDrvInit(void) +{ + U32 ret; + + ret = OsHwiInit(); + if (ret) { + return ret; + } + + ret = PRT_PrintfInit(); + if (ret) { + return ret; + } + + return OS_OK; +} + +void PRT_HardBootInit(void) +{ +} + +S32 main(void) +{ + return OsConfigStart(); +} + +extern void *__wrap_memset(void *dest, int set, U32 len) +{ + if (dest == NULL || len == 0) { + return NULL; + } + + char *ret = (char *)dest; + for (int i = 0; i < len; ++i) { + ret[i] = set; + } + return ret; +} + +extern void *__wrap_memcpy(void *dest, const void *src, size_t size) +{ + for (size_t i = 0; i < size; ++i) { + *(char *)(dest + i) = *(char *)(src + i); + } +} + diff --git a/demos/hi3093/apps/openamp/openamp_common.h b/demos/hi3093/apps/openamp/openamp_common.h new file mode 100644 index 0000000..ebbdc5c --- /dev/null +++ b/demos/hi3093/apps/openamp/openamp_common.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * See the Mulan PSL v2 for more details. + * Create: 2022-12-05 + * Description: openamp configuration + */ + +#ifndef COMMON_H__ +#define COMMON_H__ + +#include "cpu_config.h" +#include "test.h" + +#define VDEV_START_ADDR MMU_OPENAMP_ADDR +#define VDEV_SIZE 0x30000 + +#define VDEV_STATUS_ADDR VDEV_START_ADDR +#define VDEV_STATUS_SIZE 0x4000 + +#define SHM_START_ADDR (VDEV_START_ADDR + VDEV_STATUS_SIZE) +#define SHM_SIZE (VDEV_SIZE - VDEV_STATUS_SIZE) +#define SHM_DEVICE_NAME "lonely_device" + +#define VRING_COUNT 2 +#define VRING_RX_ADDRESS (VDEV_START_ADDR + SHM_SIZE - VDEV_STATUS_SIZE) +#define VRING_TX_ADDRESS (VDEV_START_ADDR + SHM_SIZE) +#define VRING_ALIGNMENT 4 +#define VRING_SIZE 16 + +#define CONFIG_RPMSG_SERVICE_NUM_ENDPOINTS 1 + +#define DEFAULT_PAGE_SHIFT 0xffffffffffffffffULL +#define DEFAULT_PAGE_MASK 0xffffffffffffffffULL + +#define VIRTQUEUE_ID 1 +#define RPMSG_ROLE RPMSG_REMOTE + +#define OS_OPENAMP_NOTIFY_HWI_NUM OS_HWI_IPI_NO_07 +#define OS_OPENAMP_NOTIFY_HWI_PRIO 0 + +#define BIT(n) (1 << (n)) + +OS_SEC_ALW_INLINE INLINE void sys_write32(uint32_t data, uintptr_t addr) +{ + __asm__ volatile ("dmb sy" : : : "memory"); + __asm__ volatile ("str %w0, [%1]" : : "r" (data), "r" (addr)); +} + +OS_SEC_ALW_INLINE INLINE uint32_t sys_read32(uintptr_t addr) +{ + uint32_t val; + __asm__ volatile ("ldr %w0, [%1]" : "=r" (val) : "r" (addr)); + __asm__ volatile ("dmb sy" : : : "memory"); + return val; +} + +OS_SEC_ALW_INLINE INLINE void sys_write8(uint8_t data, uintptr_t addr) +{ + __asm__ volatile ("dmb sy" : : : "memory"); + __asm__ volatile ("strb %w0, [%1]" : : "r" (data), "r" (addr)); +} + +OS_SEC_ALW_INLINE INLINE uint8_t sys_read8(uintptr_t addr) +{ + uint8_t val; + __asm__ volatile ("ldrb %w0, [%1]" : "=r" (val) : "r" (addr)); + __asm__ volatile ("dmb sy" : : : "memory"); + return val; +} + +#endif diff --git a/demos/hi3093/apps/openamp/rpmsg_backend.c b/demos/hi3093/apps/openamp/rpmsg_backend.c new file mode 100644 index 0000000..918f146 --- /dev/null +++ b/demos/hi3093/apps/openamp/rpmsg_backend.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * See the Mulan PSL v2 for more details. + * Create: 2022-12-05 + * Description: openamp backend + */ + +#include "rpmsg_backend.h" +#include "metal/device.h" +#include "prt_hwi.h" + +static metal_phys_addr_t shm_physmap[] = { SHM_START_ADDR }; +static struct metal_device shm_device = { + .name = SHM_DEVICE_NAME, + .bus = NULL, + .num_regions = 1, + { + { + .virt = (void *) SHM_START_ADDR, + .physmap = shm_physmap, + .size = SHM_SIZE, + .page_shift = DEFAULT_PAGE_SHIFT, + .page_mask = DEFAULT_PAGE_MASK, + .mem_flags = 0, + .ops = { NULL }, + }, + }, + .node = { NULL }, + .irq_num = 0, + .irq_info = NULL +}; + +static struct virtio_vring_info rvrings[2] = { + [0] = { + .info.align = VRING_ALIGNMENT, + }, + [1] = { + .info.align = VRING_ALIGNMENT, + }, +}; + +static struct virtqueue *vq[2]; + +static unsigned char virtio_get_status(struct virtio_device *vdev) +{ + return sys_read8(VDEV_STATUS_ADDR); +} + +static void virtio_set_status(struct virtio_device *vdev, unsigned char status) +{ + sys_write8(status, VDEV_STATUS_ADDR); +} + +static uint32_t virtio_get_features(struct virtio_device *vdev) +{ + return BIT(VIRTIO_RPMSG_F_NS); +} + +static void virtio_set_features(struct virtio_device *vdev, uint32_t features) +{ +} + +static void virtio_notify(struct virtqueue *vq) +{ + uint16_t coreMask = 1; + OsHwiMcTrigger(coreMask, OS_HWI_IPI_NO_07); +} + +const struct virtio_dispatch dispatch = { + .get_status = virtio_get_status, + .set_status = virtio_set_status, + .get_features = virtio_get_features, + .set_features = virtio_set_features, + .notify = virtio_notify, +}; + +static void rpmsg_hwi_handler(void) +{ + virtqueue_notification(vq[VIRTQUEUE_ID]); +} + +static U32 rpmsg_hwi_init(void) +{ + U32 ret; + + ret = PRT_HwiSetAttr(OS_OPENAMP_NOTIFY_HWI_NUM, OS_OPENAMP_NOTIFY_HWI_PRIO, OS_HWI_MODE_ENGROSS); + if (ret != OS_OK) { + return ret; + } + + ret = PRT_HwiCreate(OS_OPENAMP_NOTIFY_HWI_NUM, (HwiProcFunc)rpmsg_hwi_handler, 0); + if (ret != OS_OK) { + return ret; + } + +#if (OS_GIC_VER == 3) + ret = PRT_HwiEnable(OS_OPENAMP_NOTIFY_HWI_NUM); + if (ret != OS_OK) { + return ret; + } +#endif + + return OS_OK; +} + +int rpmsg_backend_init(struct metal_io_region **io, struct virtio_device *vdev) +{ + int32_t err; + struct metal_init_params metal_params = METAL_INIT_DEFAULTS; + struct metal_device *device; + + err = rpmsg_hwi_init(); + if (err) { + return err; + } + + /* Libmetal setup */ + err = metal_init(&metal_params); + if (err) { + return err; + } + + err = metal_register_generic_device(&shm_device); + if (err) { + return err; + } + + err = metal_device_open("generic", SHM_DEVICE_NAME, &device); + if (err) { + return err; + } + + *io = metal_device_io_region(device, 0); + if (!*io) { + return err; + } + + /* Virtqueue setup */ + vq[0] = virtqueue_allocate(VRING_SIZE); + if (!vq[0]) { + return -ENOMEM; + } + + vq[1] = virtqueue_allocate(VRING_SIZE); + if (!vq[1]) { + return -ENOMEM; + } + + rvrings[0].io = *io; + rvrings[0].info.vaddr = (void *)VRING_TX_ADDRESS; + rvrings[0].info.num_descs = VRING_SIZE; + rvrings[0].info.align = VRING_ALIGNMENT; + rvrings[0].vq = vq[0]; + + rvrings[1].io = *io; + rvrings[1].info.vaddr = (void *)VRING_RX_ADDRESS; + rvrings[1].info.num_descs = VRING_SIZE; + rvrings[1].info.align = VRING_ALIGNMENT; + rvrings[1].vq = vq[1]; + + vdev->role = RPMSG_ROLE; + vdev->vrings_num = VRING_COUNT; + vdev->func = &dispatch; + vdev->vrings_info = &rvrings[0]; + + return 0; +} diff --git a/demos/hi3093/apps/openamp/rpmsg_backend.h b/demos/hi3093/apps/openamp/rpmsg_backend.h new file mode 100644 index 0000000..1b738f4 --- /dev/null +++ b/demos/hi3093/apps/openamp/rpmsg_backend.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * See the Mulan PSL v2 for more details. + * Create: 2022-12-05 + * Description: openamp backend + */ + +#include "openamp/open_amp.h" +#include "openamp_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rpmsg_service_init(void); + +/* + * @brief Initialize RPMsg backend + * + * @param io Shared memory IO region. This is an output parameter providing + * a pointer to an actual shared memory IO region structure. + * Caller of this function shall pass an address at which the + * pointer to the shared memory IO region structure is stored. + * @param vdev Pointer to the virtio device initialized by this function. + * + * @retval 0 Initialization successful + * @retval <0 Initialization error reported by OpenAMP + */ +extern int rpmsg_backend_init(struct metal_io_region **io, struct virtio_device *vdev); + +#ifdef __cplusplus +} +#endif diff --git a/demos/hi3093/apps/openamp/rpmsg_service.c b/demos/hi3093/apps/openamp/rpmsg_service.c new file mode 100644 index 0000000..673e02f --- /dev/null +++ b/demos/hi3093/apps/openamp/rpmsg_service.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * See the Mulan PSL v2 for more details. + * Create: 2022-12-05 + * Description: openamp configuration + */ + +#include "rpmsg_backend.h" + +static struct virtio_device vdev; +static struct rpmsg_virtio_device rvdev; +static struct metal_io_region *io; +struct rpmsg_device *g_rdev; +struct rpmsg_endpoint g_ept; +U32 g_receivedMsg; +bool g_openampFlag = false; +#define RPMSG_ENDPOINT_NAME "console" + +void rpmsg_service_unbind(struct rpmsg_endpoint *ep) +{ + rpmsg_destroy_ept(ep); +} + +int send_message(unsigned char *message, int len) +{ + return rpmsg_send(&g_ept, message, len); +} + +char *g_s1 = "Hello, UniProton! \r\n"; +int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv) +{ + g_openampFlag = true; + send_message((void *)g_s1, strlen(g_s1) * sizeof(char)); + + return OS_OK; +} + +int openamp_init(void) +{ + int32_t err; + + err = rpmsg_backend_init(&io, &vdev); + if (err) { + return err; + } + + err = rpmsg_init_vdev(&rvdev, &vdev, NULL, io, NULL); + if (err) { + return err; + } + + g_rdev = rpmsg_virtio_get_rpmsg_device(&rvdev); + + + err = rpmsg_create_ept(&g_ept, g_rdev, RPMSG_ENDPOINT_NAME, + 0xF, RPMSG_ADDR_ANY, + rpmsg_endpoint_cb, rpmsg_service_unbind); + if (err) { + return err; + } + + return OS_OK; +} + +void openamp_deinit(void) +{ + rpmsg_deinit_vdev(&rvdev); + if (io) { + free(io); + } +} + +int rpmsg_service_init(void) +{ + int32_t err; + err = openamp_init(); + if (err) { + return err; + } + + send_message((void *)&g_receivedMsg, sizeof(U32)); + + while (!g_openampFlag); + + return OS_OK; +} diff --git a/demos/hi3093/apps/openamp/test.h b/demos/hi3093/apps/openamp/test.h new file mode 100644 index 0000000..8e57632 --- /dev/null +++ b/demos/hi3093/apps/openamp/test.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * See the Mulan PSL v2 for more details. + * Create: 2022-12-05 + * Description: openamp test Printf + */ +#include "prt_config.h" +#include "prt_task.h" +#include "prt_hwi.h" +#include "prt_hook.h" +#include "prt_exc.h" +#include "prt_mem.h" + +extern U32 PRT_Printf(const char *format, ...); diff --git a/demos/hi3093/apps/readme.txt b/demos/hi3093/apps/readme.txt new file mode 100644 index 0000000..8f30d23 --- /dev/null +++ b/demos/hi3093/apps/readme.txt @@ -0,0 +1 @@ +请您参考example目录添加您的源代码,制作您的工程。如有疑问请联系华为对接工程师。 diff --git a/demos/hi3093/bsp/CMakeLists.txt b/demos/hi3093/bsp/CMakeLists.txt new file mode 100644 index 0000000..5a7b0da --- /dev/null +++ b/demos/hi3093/bsp/CMakeLists.txt @@ -0,0 +1,4 @@ +set(SRCS start.S cache_asm.S hwi_init.c mmu.c print.c timer.c) +add_library(bsp OBJECT ${SRCS}) + +add_subdirectory(uart) \ No newline at end of file diff --git a/demos/hi3093/bsp/cache_asm.S b/demos/hi3093/bsp/cache_asm.S new file mode 100644 index 0000000..5f2f301 --- /dev/null +++ b/demos/hi3093/bsp/cache_asm.S @@ -0,0 +1,103 @@ +@/* +@ * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. +@ * +@ * UniProton is licensed under Mulan PSL v2. +@ * You can use this software according to the terms and conditions of the Mulan PSL v2. +@ * You may obtain a copy of Mulan PSL v2 at: +@ * http://license.coscl.org.cn/MulanPSL2 +@ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +@ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +@ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +@ * See the Mulan PSL v2 for more details. +@ * Create: 2009-12-22 +@ * Description: thread scheduler +@ */ +.global os_asm_invalidate_dcache_all +.global os_asm_invalidate_icache_all +.global os_asm_invalidate_tlb_all + + .type os_asm_dcache_level, "function" +os_asm_dcache_level: + lsl x12, x0, #1 + msr csselr_el1, x12 + isb + mrs x6, ccsidr_el1 + and x2, x6, #7 + add x2, x2, #4 + mov x3, #0x3ff + and x3, x3, x6, lsr #3 + clz w5, w3 + mov x4, #0x7fff + and x4, x4, x6, lsr #13 + +loop_set: + mov x6, x3 +loop_way: + lsl x7, x6, x5 + orr x9, x12, x7 + lsl x7, x4, x2 + orr x9, x9, x7 + tbz w1, #1, 3f + dc csw, x9 + b 2f +3: tbz w1, #0, 1f + dc isw, x9 + b 2f +1: dc cisw, x9 +2: subs x6, x6, #1 + b.ge loop_way + subs x4, x4, #1 + b.ge loop_set + + ret + + .type os_asm_dcache_all, "function" +os_asm_dcache_all: + mov x1, x0 + dsb sy + mrs x10, clidr_el1 + lsr x11, x10, #24 + and x11, x11, #0x7 + cbz x11, finished + mov x15, x30 + mov x0, #0 + +loop_level: + lsl x12, x0, #1 + add x12, x12, x0 + lsr x12, x10, x12 + and x12, x12, #7 + cmp x12, #2 + b.lt skip + bl os_asm_dcache_level +skip: + add x0, x0, #1 + cmp x11, x0 + b.gt loop_level + + mov x0, #0 + msr csselr_el1, x0 + dsb sy + isb + mov x30, x15 + +finished: + ret + + .type os_asm_invalidate_dcache_all, "function" +os_asm_invalidate_dcache_all: + mov x0, #0x1 + b os_asm_dcache_all + + .type os_asm_invalidate_icache_all, "function" +os_asm_invalidate_icache_all: + ic ialluis + isb sy + ret + + .type os_asm_invalidate_tlb_all, "function" +os_asm_invalidate_tlb_all: + tlbi vmalle1 + dsb sy + isb + ret diff --git a/demos/hi3093/bsp/cache_asm.h b/demos/hi3093/bsp/cache_asm.h new file mode 100644 index 0000000..ca1bed9 --- /dev/null +++ b/demos/hi3093/bsp/cache_asm.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton hi3093 demo + */ +#ifndef __CACHE_H__ +#define __CACHE_H__ + +#include "prt_buildef.h" +#include "prt_typedef.h" +#include "prt_module.h" +#include "prt_errno.h" + +extern void os_asm_invalidate_dcache_all(void); +extern void os_asm_invalidate_icache_all(void); +extern void os_asm_invalidate_tlb_all(void); +#endif diff --git a/demos/hi3093/bsp/hi3093/cpu_config.h b/demos/hi3093/bsp/hi3093/cpu_config.h new file mode 100644 index 0000000..3b7b704 --- /dev/null +++ b/demos/hi3093/bsp/hi3093/cpu_config.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton配置私有文件。 + */ +#ifndef CPU_CONFIG_H +#define CPU_CONFIG_H + +#include "cache_asm.h" + +#define MMU_IMAGE_ADDR 0x93000000ULL +#define MMU_GIC_ADDR 0x24000000ULL +#define MMU_UART_ADDR 0x08743000ULL +#define MMU_OPENAMP_ADDR 0x90000000ULL + +#define UART_BASE_ADDR MMU_UART_ADDR + +#define TEST_CLK_INT 30 + +#define OS_GIC_VER 3 +#define SICR_ADDR_OFFSET_PER_CORE 0x20000U +#define GIC_REG_BASE_ADDR 0x24000000ULL + +#define GICD_CTLR_S_ADDR (GIC_REG_BASE_ADDR + 0x0000U) +#define GICD_IGROUPN_ADDR (GIC_REG_BASE_ADDR + 0x0080U) +#define GICD_ISENABLER0_ADDR (GIC_REG_BASE_ADDR + 0x0100U) +#define GICD_ICENABLER0_ADDR (GIC_REG_BASE_ADDR + 0x0180U) +#define GICD_IPRIORITYN_ADDR (GIC_REG_BASE_ADDR + 0x0400U) +#define GICD_IGRPMODRN_ADDR (GIC_REG_BASE_ADDR + 0x0D00U) + +#define GICR_BASE0 (GIC_REG_BASE_ADDR + 0x40000U) +#define GICR_BASE1 (GIC_REG_BASE_ADDR + 0x50000U) + +#define GICR_CTRL_ADDR (GICR_BASE0 + 0x0000U) +#define GICR_WAKER_ADDR (GICR_BASE0 + 0x0014U) + +#define GICR_IGROUPR0_ADDR (GICR_BASE1 + 0x0080U) +#define GICR_ISENABLER0_ADDR (GICR_BASE1 + 0x0100U) +#define GICR_ICENABLER0_ADDR (GICR_BASE1 + 0x0180U) +#define GICR_IGRPMODR0_ADDR (GICR_BASE1 + 0x0D00U) + + +#define MAX_INT_NUM 387 +#define MIN_GIC_SPI_NUM 32 +#define SICD_IGROUP_INT_NUM 32 +#define SICD_REG_SIZE 4 + +#define GROUP_MAX_BPR 0x7U +#define GROUP0_BP 0 +#define GROUP1_BP 0 + +#define PRIO_MASK_LEVEL 0xFFU + +#define ICC_SRE_EL1 S3_0_C12_C12_5 +#define ICC_BPR0_EL1 S3_0_C12_C8_3 +#define ICC_BPR1_EL1 S3_0_C12_C12_3 +#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 +#define ICC_PMR_EL1 S3_0_C4_C6_0 + +#define PARAS_TO_STRING(x...) #x +#define REG_ALIAS(x...) PARAS_TO_STRING(x) + +#define GIC_REG_READ(addr) (*(volatile U32 *)((uintptr_t)(addr))) +#define GIC_REG_WRITE(addr, data) (*(volatile U32 *)((uintptr_t)(addr)) = (U32)(data)) + +#endif diff --git a/demos/hi3093/bsp/hwi_init.c b/demos/hi3093/bsp/hwi_init.c new file mode 100644 index 0000000..c231ce3 --- /dev/null +++ b/demos/hi3093/bsp/hwi_init.c @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton hi3093 demo + */ +#include "securec.h" +#include "prt_tick.h" +#include "prt_hwi.h" +#include "prt_sys.h" +#include "prt_task.h" +#include "cpu_config.h" + +#if (OS_GIC_VER == 3) +enum GicIntState { + GIC_DISABLE = 0, + GIC_ENABLE = 1 +}; + +enum SicGroupType { + SIC_GROUP_G0S = 0, + SIC_GROUP_G1NS = 1, + SIC_GROUP_G1S = 2, + SIC_GROUP_BUTT, +}; + +union SicrWaker { + struct { + U32 res0 : 1; + U32 sleepReq : 1; + U32 isSleep : 1; + U32 res1 : 29; + } bits; + U32 value; +}; + +union SicrCtrl { + struct { + U32 enLpis : 1; + U32 res2 : 2; + U32 rwp : 1; + U32 res1 : 20; + U32 dpg0 : 1; + U32 dpg1ns : 1; + U32 dpg1s : 1; + U32 res0 : 4; + U32 uwp : 1; + } bits; + U32 value; +}; + +union HwiIccSreElx { + struct { + U64 prt : 1; + U64 dfb : 1; + U64 dib : 1; + U64 enable : 1; + U64 res : 60; + } bits; + U64 value; +}; + +union SicdCtrl { + struct { + U32 enG0S : 1; + U32 enG1Ns : 1; + U32 enG1S : 1; + U32 res1 : 1; + U32 areS : 1; + U32 areNs : 1; + U32 ds : 1; + U32 res0 : 24; + U32 rwp : 1; + } bits; + U32 value; +}; + +extern void OsGicdWaitCfgWork(); + +void OsSicrInit(void) +{ + union SicrWaker sicrWaker; + uintptr_t regAddr; + U32 intId; + + regAddr = GICR_WAKER_ADDR + OsGetCoreID() * SICR_ADDR_OFFSET_PER_CORE; + sicrWaker.value = GIC_REG_READ(regAddr); + sicrWaker.bits.sleepReq = 0; + GIC_REG_WRITE(regAddr, sicrWaker.value); + sicrWaker.value = GIC_REG_READ(regAddr); + while (sicrWaker.bits.isSleep == 1) { + sicrWaker.value = GIC_REG_READ(regAddr); + } +} + +void OsSicrSetIntGroup(U32 coreId, U64 intId, enum SicGroupType groupId) +{ + uintptr_t group0RegAddr; + uintptr_t modRegAddr; + U32 group0RegTmp; + U32 modRegTmp; + + group0RegAddr = GICR_IGROUPR0_ADDR + OsGetCoreID() * SICR_ADDR_OFFSET_PER_CORE; + group0RegTmp = GIC_REG_READ(group0RegAddr); + + if ((groupId == SIC_GROUP_G0S) || (groupId == SIC_GROUP_G1S)) { + group0RegTmp &= ~(0x1U << intId); + } else { + group0RegTmp |= (0x1U << intId); + } + GIC_REG_WRITE(group0RegAddr, group0RegTmp); + + modRegAddr = GICR_IGRPMODR0_ADDR + OsGetCoreID() * SICR_ADDR_OFFSET_PER_CORE; + modRegTmp = GIC_REG_READ(modRegAddr); + + if (groupId == SIC_GROUP_G1S) { + modRegTmp |= (0x1U << intId); + } else { + modRegTmp &= ~(0x1U << intId); + } + GIC_REG_WRITE(modRegAddr, modRegTmp); +} + +U32 OsSiccEnableSre(void) +{ + volatile union HwiIccSreElx iccSre; + + OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_SRE_EL1) " \n" : "=&r"(iccSre)); + iccSre.bits.prt = 1; + iccSre.bits.dfb = 1; + iccSre.bits.dib = 1; + OS_EMBED_ASM("MSR " REG_ALIAS(ICC_SRE_EL1) ", %0 \n" : : "r"(iccSre)); + OS_EMBED_ASM("DSB SY"); + OS_EMBED_ASM("ISB"); + + OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_SRE_EL1) " \n" : "=&r"(iccSre.value)); + + if (iccSre.bits.prt != 1) { + return OS_FAIL; + } + + return OS_OK; +} + +void OsSiccCfgIntPreempt(void) +{ + U64 tmp = 0; + + OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_BPR1_EL1) " \n" : "=&r"(tmp) : : "memory"); + tmp &= ~(GROUP_MAX_BPR); + tmp |= GROUP1_BP; + OS_EMBED_ASM("MSR " REG_ALIAS(ICC_BPR1_EL1) ", %0 \n" : : "r"(tmp) : "memory"); +} + +void OsSiccEnableGroup1(void) +{ + U64 tmp = 0; + + OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_IGRPEN1_EL1) " \n" : "=&r"(tmp) : : "memory"); + tmp |= 0x01U; + OS_EMBED_ASM("MSR " REG_ALIAS(ICC_IGRPEN1_EL1) ", %0 \n" : : "r"(tmp) : "memory"); +} + +void OsSiccCfgPriorityMask(void) +{ + U64 tmp = 0; + + OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_PMR_EL1) " \n" : "=&r"(tmp) : : "memory"); + tmp |= PRIO_MASK_LEVEL; + OS_EMBED_ASM("MSR " REG_ALIAS(ICC_PMR_EL1) ", %0 \n" : : "r"(tmp) : "memory"); +} + +U32 OsSiccInit(void) +{ + U32 ret; + + ret = OsSiccEnableSre(); + if (ret != OS_OK) { + return ret; + } + + OsSiccCfgIntPreempt(); + + OsSiccEnableGroup1(); + + OsSiccCfgPriorityMask(); + + return OS_OK; +} + +void OsSicdSetIntGroup(U32 intId, enum SicGroupType groupId) +{ + U64 group0RegAddr; + U64 modRegAddr; + U32 group0RegTmp; + U32 modRegTmp; + U32 sicdM; + U32 bitOffset; + + sicdM = (intId - MIN_GIC_SPI_NUM) / SICD_IGROUP_INT_NUM; + group0RegAddr = GICD_IGROUPN_ADDR + (SICD_REG_SIZE * sicdM); + modRegAddr = GICD_IGRPMODRN_ADDR + (SICD_REG_SIZE * sicdM); + bitOffset = (intId - MIN_GIC_SPI_NUM) % SICD_IGROUP_INT_NUM; + + group0RegTmp = GIC_REG_READ(group0RegAddr); + if ((groupId == SIC_GROUP_G0S) || (groupId == SIC_GROUP_G1S)) { + group0RegTmp &= ~(0x1U << bitOffset); + } else { + group0RegTmp |= (0x1U << bitOffset); + } + GIC_REG_WRITE(group0RegAddr, group0RegTmp); + + modRegTmp = GIC_REG_READ(modRegAddr); + if (groupId == SIC_GROUP_G1S) { + modRegTmp |= (0x1U << bitOffset); + } else { + modRegTmp &= ~(0x1U << bitOffset); + } + GIC_REG_WRITE(modRegAddr, modRegTmp); +} + +void OsSicSetGroup(U32 intId, enum SicGroupType groupId) +{ + U32 coreId = OsGetCoreID(); + enum GicIntState state; + + if (intId < MIN_GIC_SPI_NUM) { + state = OsGicrGetIntState(coreId, intId); + OsGicrDisableInt(coreId, intId); + OsSicrSetIntGroup(coreId, intId, groupId); + if (state == GIC_ENABLE) { + OsGicrEnableInt(coreId, intId); + } + } else { + state = OsGicdGetIntState(intId); + OsGicdDisableInt(intId); + OsSicdSetIntGroup(intId, groupId); + if (state == GIC_ENABLE) { + OsGicdEnableInt(intId); + } + } +} + +U32 OsSicInitLocal(void) +{ + U32 ret; + U32 intId; + + OsSicrInit(); + + ret = OsSiccInit(); + if (ret != OS_OK) { + return ret; + } + + for (intId = 0; intId < MIN_GIC_SPI_NUM; ++intId) { + OsSicSetGroup(intId, SIC_GROUP_G1NS); + } + + return OS_OK; +} + +void OsSicdInit(void) +{ + union SicdCtrl sicdCtrl; + + sicdCtrl.value = GIC_REG_READ(GICD_CTLR_S_ADDR); + + if ((sicdCtrl.bits.enG0S == 1) || (sicdCtrl.bits.enG1Ns == 1) || (sicdCtrl.bits.enG1S == 1)) { + return; + } + + sicdCtrl.bits.ds = 0; + sicdCtrl.bits.areNs = 1; + sicdCtrl.bits.areS = 1; + sicdCtrl.bits.enG1Ns = 1; + GIC_REG_WRITE(GICD_CTLR_S_ADDR, sicdCtrl.value); + + OsGicdWaitCfgWork(); +} + +void OsSicInitGlobal(void) +{ + U32 intId; + + OsSicdInit(); + + for (intId = MIN_GIC_SPI_NUM; intId < MAX_INT_NUM; ++intId) { + OsSicSetGroup(intId, SIC_GROUP_G1NS); + } +} +#elif (OS_GIC_VER == 2) +int IsrRegister(U32 intNo, U32 pri) +{ + U32 bitn, reg, shift; + U32 *addr; + + bitn = intNo / 32U; + addr = (U32 *)(GICD_ISENABLERn + 4U * bitn); + reg = *addr; + *addr = (reg | (0x1U << (intNo % 32U))); + + bitn = intNo / 4U; + addr = (U32 *)(GICD_IPRIORITYn + 4U * bitn); + shift = (intNo % 4U) * 8U; + reg = (*addr) & ~(0xFFU << shift); + *addr = (reg | pri << shift); +} + +void OsGicInitCpuInterface(void) +{ + int i; + U32 val; + + GIC_REG_WRITE(0xFFFFFFFF, GICD_ICACTIVERn); + GIC_REG_WRITE(0xFFFF0000, GICD_ICENABLERn); + GIC_REG_WRITE(0x0000FFFF, GICD_ISENABLERn); + + for (i = 0; i < 32; i += 4) { + GIC_REG_WRITE(0xA0A0A0A0, GICD_IPRIORITYn + i); + } + + GIC_REG_WRITE(0xF0, GICC_PMR); + val = GIC_REG_READ(GICC_CTLR); + val &= ~GICC_CTLR_BYPASS_MASK; + val |= GICC_CTLR_ENABLE_MASK; + GIC_REG_WRITE(val, GICC_CTLR); +} +#endif +U32 OsHwiInit(void) +{ +#if (OS_GIC_VER == 3) + U32 ret; + + ret = OsSicInitLocal(); + if (ret != OS_OK) { + return ret; + } + + if(PRT_GetCoreID() == 0) { + OsSicInitGlobal(); + } +#elif (OS_GIC_VER == 2) + OsGicInitCpuInterface(); +#endif + return OS_OK; +} diff --git a/demos/hi3093/bsp/mmu.c b/demos/hi3093/bsp/mmu.c new file mode 100644 index 0000000..cab7f32 --- /dev/null +++ b/demos/hi3093/bsp/mmu.c @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton hi3093 demo + */ +#include "prt_buildef.h" +#include "prt_typedef.h" +#include "prt_module.h" +#include "prt_errno.h" +#include "mmu.h" +#include "cache_asm.h" +#include "prt_sys.h" +#include "prt_task.h" +#include "cpu_config.h" + +extern U64 g_mmu_page_begin; +extern U64 g_mmu_page_end; + +static mmu_mmap_region_s g_mem_map_info[] = { + { + .virt = MMU_OPENAMP_ADDR, + .phys = MMU_OPENAMP_ADDR, + .size = 0x30000, + .max_level = 0x2, + .attrs = MMU_ATTR_DEVICE_NGNRNE | MMU_ACCESS_RWX, + }, { + .virt = MMU_IMAGE_ADDR, + .phys = MMU_IMAGE_ADDR, + .size = 0x1000000, + .max_level = 0x2, + .attrs = MMU_ATTR_CACHE_SHARE | MMU_ACCESS_RWX, + }, { + .virt = MMU_GIC_ADDR, + .phys = MMU_GIC_ADDR, + .size = 0x1000000, + .max_level = 0x2, + .attrs = MMU_ATTR_DEVICE_NGNRNE | MMU_ACCESS_RWX, + }, { + .virt = MMU_UART_ADDR, + .phys = MMU_UART_ADDR, + .size = 0x2000, + .max_level = 0x2, + .attrs = MMU_ATTR_DEVICE_NGNRNE | MMU_ACCESS_RWX, + } +}; + +static mmu_ctrl_s g_mmu_ctrl = { 0 }; + +static U64 mmu_get_tcr(U32 *pips, U32 *pva_bits) +{ + U64 max_addr = 0; + U64 ips, va_bits; + U64 tcr; + U32 i; + U32 mmu_table_num = sizeof(g_mem_map_info) / sizeof(mmu_mmap_region_s); + + for (i = 0; i < mmu_table_num; ++i) { + max_addr = MAX(max_addr, g_mem_map_info[i].virt + g_mem_map_info[i].size); + } + + if (max_addr > (1ULL << MMU_BITS_44)) { + ips = MMU_PHY_ADDR_LEVEL_5; + va_bits = MMU_BITS_48; + } else if (max_addr > (1ULL << MMU_BITS_42)) { + ips = MMU_PHY_ADDR_LEVEL_4; + va_bits = MMU_BITS_44; + } else if (max_addr > (1ULL << MMU_BITS_40)) { + ips = MMU_PHY_ADDR_LEVEL_3; + va_bits = MMU_BITS_42; + } else if (max_addr > (1ULL << MMU_BITS_36)) { + ips = MMU_PHY_ADDR_LEVEL_2; + va_bits = MMU_BITS_40; + } else if (max_addr > (1ULL << MMU_BITS_32)) { + ips = MMU_PHY_ADDR_LEVEL_1; + va_bits = MMU_BITS_36; + } else { + ips = MMU_PHY_ADDR_LEVEL_0; + va_bits = MMU_BITS_32; + } + + tcr = TCR_EL1_RSVD | TCR_IPS(ips); + + if (g_mmu_ctrl.granule == MMU_GRANULE_4K) { + tcr |= TCR_TG0_4K | TCR_SHARED_INNER | TCR_ORGN_WBWA | TCR_IRGN_WBWA; + } else { + tcr |= TCR_TG0_64K | TCR_SHARED_INNER | TCR_ORGN_WBWA | TCR_IRGN_WBWA; + } + + tcr |= TCR_T0SZ(va_bits); + + if (pips != NULL) { + *pips = ips; + } + + if (pva_bits != NULL) { + *pva_bits = va_bits; + } + + return tcr; +} + +static U32 mmu_get_pte_type(U64 const *pte) +{ + return (U32)(*pte & PTE_TYPE_MASK); +} + +static U32 mmu_level2shift(U32 level) +{ + if (g_mmu_ctrl.granule == MMU_GRANULE_4K) { + return (U32)(MMU_BITS_12 + MMU_BITS_9 * (MMU_LEVEL_3 - level)); + } else { + return (U32)(MMU_BITS_16 + MMU_BITS_13 * (MMU_LEVEL_3 - level)); + } +} + +static U64 *mmu_find_pte(U64 addr, U32 level) +{ + U64 *pte = NULL; + U64 idx; + U32 i; + + if (level < g_mmu_ctrl.start_level) { + return NULL; + } + + pte = (U64 *)g_mmu_ctrl.tlb_addr; + + for (i = g_mmu_ctrl.start_level; i < MMU_LEVEL_MAX; ++i) { + if (g_mmu_ctrl.granule == MMU_GRANULE_4K) { + idx = (addr >> mmu_level2shift(i)) & 0x1FF; + } else { + idx = (addr >> mmu_level2shift(i)) & 0x1FFF; + } + + pte += idx; + + if (i == level) { + return pte; + } + + if (mmu_get_pte_type(pte) != PTE_TYPE_TABLE) { + return NULL; + } + + if (g_mmu_ctrl.granule == MMU_GRANULE_4K) { + pte = (U64 *)(*pte & PTE_TABLE_ADDR_MARK_4K); + } else { + pte = (U64 *)(*pte & PTE_TABLE_ADDR_MARK_64K); + } + } + + return NULL; +} + +static U64 *mmu_create_table(void) +{ + U32 pt_len; + U64 *new_table = (U64 *)g_mmu_ctrl.tlb_fillptr; + + if (g_mmu_ctrl.granule == MMU_GRANULE_4K) { + pt_len = MAX_PTE_ENTRIES_4K * sizeof(U64); + } else { + pt_len = MAX_PTE_ENTRIES_64K * sizeof(U64); + } + + g_mmu_ctrl.tlb_fillptr += pt_len; + + if (g_mmu_ctrl.tlb_fillptr - g_mmu_ctrl.tlb_addr > g_mmu_ctrl.tlb_size) { + return NULL; + } + + (void)memset_s((void *)new_table, MAX_PTE_ENTRIES_64K * sizeof(U64), 0, pt_len); + + return new_table; +} + +static void mmu_set_pte_table(U64 *pte, U64 *table) +{ + *pte = PTE_TYPE_TABLE | (U64)table; +} + +static S32 mmu_add_map_pte_process(mmu_mmap_region_s const *map, U64 *pte, U64 phys, U32 level) +{ + U64 *new_table = NULL; + + if (level < map->max_level) { + if (mmu_get_pte_type(pte) == PTE_TYPE_FAULT) { + new_table = mmu_create_table(); + if (new_table == NULL) { + return -1; + } + mmu_set_pte_table(pte, new_table); + } + } else if (level == MMU_LEVEL_3) { + *pte = phys | map->attrs | PTE_TYPE_PAGE; + } else { + *pte = phys | map->attrs | PTE_TYPE_BLOCK; + } + + return 0; +} + +static S32 mmu_add_map(mmu_mmap_region_s const *map) +{ + U64 virt = map->virt; + U64 phys = map->phys; + U64 max_level = map->max_level; + U64 start_level = g_mmu_ctrl.start_level; + U64 block_size = 0; + U64 map_size = 0; + U32 level; + U64 *pte = NULL; + S32 ret; + + if (map->max_level <= start_level) { + return -2; + } + + while (map_size < map->size) { + for (level = start_level; level <= max_level; ++level) { + pte = mmu_find_pte(virt, level); + if (pte == NULL) { + return -3; + } + + ret = mmu_add_map_pte_process(map, pte, phys, level); + if (ret) { + return ret; + } + + if (level != start_level) { + block_size = 1ULL << mmu_level2shift(level); + } + } + + virt += block_size; + phys += block_size; + map_size += block_size; + } + + return 0; +} + +static inline void mmu_set_ttbr_tcr_mair(U64 table, U64 tcr, U64 attr) +{ + OS_EMBED_ASM("dsb sy"); + + OS_EMBED_ASM("msr ttbr0_el1, %0" : : "r" (table) : "memory"); + OS_EMBED_ASM("msr ttbr1_el1, %0" : : "r" (table) : "memory"); + OS_EMBED_ASM("msr tcr_el1, %0" : : "r" (tcr) : "memory"); + OS_EMBED_ASM("msr mair_el1, %0" : : "r" (attr) : "memory"); + + OS_EMBED_ASM("isb"); +} + +static U32 mmu_setup_pgtables(mmu_mmap_region_s *mem_map, U32 mem_region_num, U64 tlb_addr, U64 tlb_len, U32 granule) +{ + U32 i; + U32 ret; + U64 tcr; + U64 *new_table = NULL; + + g_mmu_ctrl.tlb_addr = tlb_addr; + g_mmu_ctrl.tlb_size = tlb_len; + g_mmu_ctrl.tlb_fillptr = tlb_addr; + g_mmu_ctrl.granule = granule; + g_mmu_ctrl.start_level = 0; + + tcr = mmu_get_tcr(NULL, &g_mmu_ctrl.va_bits); + + if (g_mmu_ctrl.granule == MMU_GRANULE_4K) { + if (g_mmu_ctrl.va_bits < MMU_BITS_39) { + g_mmu_ctrl.start_level = MMU_LEVEL_1; + } else { + g_mmu_ctrl.start_level = MMU_LEVEL_0; + } + } else { + if (g_mmu_ctrl.va_bits <= MMU_BITS_36) { + g_mmu_ctrl.start_level = MMU_LEVEL_2; + } else { + g_mmu_ctrl.start_level = MMU_LEVEL_1; + return 3; + } + } + + new_table = mmu_create_table(); + if (new_table == NULL) { + return 1; + } + + for (i = 0; i < mem_region_num; ++i) { + ret = mmu_add_map(&mem_map[i]); + if (ret) { + return ret; + } + } + + mmu_set_ttbr_tcr_mair(g_mmu_ctrl.tlb_addr, tcr, MEMORY_ATTRIBUTES); + + return 0; +} + +static S32 mmu_setup(void) +{ + S32 ret; + U64 page_addr; + U64 page_len; + + page_addr = (U64)&g_mmu_page_begin; + page_len = (U64)&g_mmu_page_end - (U64)&g_mmu_page_begin; + + ret = mmu_setup_pgtables(g_mem_map_info, (sizeof(g_mem_map_info) / sizeof(mmu_mmap_region_s)), + page_addr, page_len, MMU_GRANULE_4K); + if (ret) { + return ret; + } + + return 0; +} + +S32 mmu_init(void) +{ + S32 ret; + + ret = mmu_setup(); + if (ret) { + return ret; + } + + os_asm_invalidate_dcache_all(); + os_asm_invalidate_icache_all(); + os_asm_invalidate_tlb_all(); + + set_sctlr(get_sctlr() | CR_C | CR_M | CR_I); + + return 0; +} diff --git a/demos/hi3093/bsp/mmu.h b/demos/hi3093/bsp/mmu.h new file mode 100644 index 0000000..dbdb144 --- /dev/null +++ b/demos/hi3093/bsp/mmu.h @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton hi3093 demo + */ +#ifndef __MMU_H__ +#define __MMU_H__ + +#include "prt_typedef.h" + +#define CACHE_POS 0x2 +#define CACHE_ENABLE 0x4 +#define CACHE_MASK 0x7 + +#define MT_DEVICE_NGNRNE 0 +#define MT_DEVICE_NGNRE 1 +#define MT_DEVICE_GRE 2 +#define MT_NORMAL_NC 3 +#define MT_NORMAL 4 + +#define MEMORY_ATTRIBUTES ((0x00 << (MT_DEVICE_NGNRNE * 8)) | \ + (0x04 << (MT_DEVICE_NGNRE * 8)) | \ + (0x0c << (MT_DEVICE_GRE * 8)) | \ + (0x44 << (MT_NORMAL_NC * 8)) | \ + (0xffUL << (MT_NORMAL * 8))) + +#define PTE_TYPE_FAULT (0 << 0) +#define PTE_TYPE_BLOCK (1 << 0) +#define PTE_TYPE_VALID (1 << 0) +#define PTE_TYPE_MASK (3 << 0) +#define PTE_TYPE_PAGE (3 << 0) +#define PTE_TYPE_TABLE (3 << 0) + +#define PTE_TABLE_PXN (1UL << 59) +#define PTE_TABLE_XN (1UL << 60) +#define PTE_TABLE_AP (1UL << 61) +#define PTE_TABLE_NS (1UL << 63) + +#define PTE_BLOCK_MEMTYPE(x) ((x) << 2) +#define PTE_BLOCK_NS (1 << 5) +#define PTE_BLOCK_AP_R (2 << 6) +#define PTE_BLOCK_AP_RW (0 << 6) +#define PTE_BLOCK_NON_SHARE (0 << 8) +#define PTE_BLOCK_OUTER_SHARE (2 << 8) +#define PTE_BLOCK_INNER_SHARE (3 << 8) +#define PTE_BLOCK_AF (1 << 10) +#define PTE_BLOCK_NG (1 << 11) +#define PTE_BLOCK_PXN (1UL << 53) +#define PTE_BLOCK_UXN (1UL << 54) + +#define PMD_ATTRINDX(t) ((t) << 2) +#define PMD_ATTRINDX_MASK (7 << 2) +#define PMD_ATTRMASK (PTE_BLOCK_PXN | \ + PTE_BLOCK_UXN | \ + PMD_ATTRINDX_MASK | \ + PTE_TYPE_VALID) + +#define TCR_IPS(x) ((x) << 32) +#define TCR_T0SZ(x) ((64 - (x)) << 0) +#define TCR_IRGN_NC (0 << 8) +#define TCR_IRGN_WBWA (1 << 8) +#define TCR_IRGN_WT (2 << 8) +#define TCR_IRGN_WBNWA (3 << 8) +#define TCR_IRGN_MASK (3 << 8) +#define TCR_ORGN_NC (0 << 10) +#define TCR_ORGN_WBWA (1 << 10) +#define TCR_ORGN_WT (2 << 10) +#define TCR_ORGN_WBNWA (3 << 10) +#define TCR_ORGN_MASK (3 << 10) +#define TCR_SHARED_NON (0 << 12) +#define TCR_SHARED_OUTER (2 << 12) +#define TCR_SHARED_INNER (3 << 12) +#define TCR_TG0_4K (0 << 14) +#define TCR_TG0_64K (1 << 14) +#define TCR_TG0_16K (2 << 14) +#define TCR_EPD1_DISABLE (1 << 23) + +#define TCR_EL1_RSVD (1UL << 31) +#define TCR_EL2_RSVD (1UL << 31 | 1UL << 23) +#define TCR_EL3_RSVD (1UL << 31 | 1UL << 23) + +#define MAX_PTE_ENTRIES_4K 512 +#define MAX_PTE_ENTRIES_64K 8192 + +#define PTE_TABLE_ADDR_MARK_4K 0x0000FFFFFFFFF000ULL +#define PTE_TABLE_ADDR_MARK_64K 0x0000FFFFFFFF0000ULL + + +#define MMU_ATTR_DEVICE_NGNRNE (PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE)) +#define MMU_ATTR_DEVICE (PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE)) +#define MMU_ATTR_UNCACHE_UNSHARE (PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) | PTE_BLOCK_NON_SHARE) +#define MMU_ATTR_UNCACHE_SHARE (PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) | PTE_BLOCK_INNER_SHARE) +#define MMU_ATTR_CACHE_UNSHARE (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE) +#define MMU_ATTR_CACHE_SHARE (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE) +#define MMU_ATTR_MASK 0X31CULL + +#define MMU_ACCESS_NONE (PTE_BLOCK_AP_RW) +#define MMU_ACCESS_R (PTE_BLOCK_AF | PTE_BLOCK_UXN | PTE_BLOCK_PXN | PTE_BLOCK_AP_R) +#define MMU_ACCESS_RW (PTE_BLOCK_AF | PTE_BLOCK_UXN | PTE_BLOCK_PXN | PTE_BLOCK_AP_RW) +#define MMU_ACCESS_RWX (PTE_BLOCK_AF | PTE_BLOCK_AP_RW) +#define MMU_ACCESS_RX (PTE_BLOCK_AF | PTE_BLOCK_AP_R) +#define MMU_ACCESS_MASK 0X600000000004C0ULL + +#define MMU_GRANULE_4K 0 +#define MMU_GRANULE_64K 1 + +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define CR_M (1 << 0) +#define CR_A (1 << 1) +#define CR_C (1 << 2) +#define CR_SA (1 << 3) +#define CR_I (1 << 12) +#define CR_WXN (1 << 19) +#define CR_EE (1 << 25) + +#define SPSR_EL_END_LE (0 << 9) +#define SPSR_EL_DEBUG_MASK (1 << 9) +#define SPSR_EL_ASYN_MASK (1 << 8) +#define SPSR_EL_SERR_MASK (1 << 8) +#define SPSR_EL_IRQ_MASK (1 << 7) +#define SPSR_EL_FIQ_MASK (1 << 6) +#define SPSR_EL_T_A32 (0 << 5) +#define SPSR_EL_M_AARCH64 (0 << 4) +#define SPSR_EL_M_AARCH32 (1 << 4) +#define SPSR_EL_M_SVC (0x3) +#define SPSR_EL_M_HYP (0xa) +#define SPSR_EL_M_EL1H (5) +#define SPSR_EL_M_EL2H (9) + +#define CPUECTLR_EL1_L1PCTL_MASK (7 << 13) +#define CPUECTLR_EL1_L3PCTL_MASK (7 << 10) + +typedef enum { + MMU_LEVEL_0 = 0, + MMU_LEVEL_1, + MMU_LEVEL_2, + MMU_LEVEL_3, + MMU_LEVEL_MAX +} mmu_level_e; + +typedef enum { + MMU_PHY_ADDR_LEVEL_0 = 0, + MMU_PHY_ADDR_LEVEL_1, + MMU_PHY_ADDR_LEVEL_2, + MMU_PHY_ADDR_LEVEL_3, + MMU_PHY_ADDR_LEVEL_4, + MMU_PHY_ADDR_LEVEL_5 +} mmu_physical_addr_size_e; + +typedef enum { + MMU_BITS_9 = 9, + MMU_BITS_12 = 12, + MMU_BITS_13 = 13, + MMU_BITS_16 = 16, + MMU_BITS_32 = 32, + MMU_BITS_36 = 36, + MMU_BITS_39 = 39, + MMU_BITS_40 = 40, + MMU_BITS_42 = 42, + MMU_BITS_44 = 44, + MMU_BITS_48 = 48, +} mmu_bits_e; + +typedef struct { + U64 tlb_addr; + U64 tlb_size; + U64 tlb_fillptr; + U32 granule; + U32 start_level; + U32 va_bits; +} mmu_ctrl_s; + +typedef struct { + U64 virt; + U64 phys; + U64 size; + U64 max_level; + U64 attrs; +} mmu_mmap_region_s; + +static inline unsigned long get_sctlr(void) +{ + unsigned long val; + + __asm__ __volatile__("mrs %0, sctlr_el1" : "=r" (val) : : "cc"); + + return val; +} + +static inline unsigned long get_cpuectr(void) +{ + unsigned long val; + + __asm__ __volatile__("mrs %0, S3_1_C15_C2_1" : "=r" (val) : : "cc"); + + return val; +} + +static inline void set_sctlr(unsigned long val) +{ + __asm__ __volatile__("dsb sy"); + __asm__ __volatile__("msr sctlr_el1, %0" : : "r" (val) : "cc"); + __asm__ __volatile__("dsb sy"); + __asm__ __volatile__("isb"); +} + +extern S32 mmu_init(void); + +#endif diff --git a/demos/hi3093/bsp/print.c b/demos/hi3093/bsp/print.c new file mode 100644 index 0000000..69e025f --- /dev/null +++ b/demos/hi3093/bsp/print.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton hi3093 demo + */ +#include +#include "prt_typedef.h" +#include "cpu_config.h" +#include "securec.h" +#include "serial.h" +#include "prt_hwi.h" + +typedef U32 (*PrintFunc)(const char *format, va_list vaList); +#define OS_MAX_SHOW_LEN 0x200 + +U32 uart_recv(U8 *value) +{ + S32 ret = 0; + ret = serial_getc(); + if (ret == -EAGAIN) { + return EAGAIN; + } + + *value = (U8)ret; + + return 0; +} + +void uart_recv_hwi(void) +{ + U8 data; + while (uart_recv(&data) == 0) { + /*Do not printf in this task*/ + } +} + +U32 PRT_UartInit(void) +{ + + U32 ret; + (void)PRT_HwiDelete(CCORE_SYS_UART4_INTID); + + ret = PRT_HwiSetAttr(CCORE_SYS_UART4_INTID, 12, OS_HWI_MODE_ENGROSS); + if (ret != OS_OK) { + return ret; + } + + ret = PRT_HwiCreate(CCORE_SYS_UART4_INTID, (HwiProcFunc)uart_recv_hwi, CCORE_SYS_UART4_INTID); + if (ret != OS_OK) { + return ret; + } + + ret = PRT_HwiEnable(CCORE_SYS_UART4_INTID); + if (ret != OS_OK) { + return ret; + } + + serial_init(&g_uart_cfg, &g_uart_ops); + + return OS_OK; +} + +void uart_poll_send(unsigned char ch) +{ + serial_putc((char)ch); +} + +void TestPutc(unsigned char ch) +{ + uart_poll_send(ch); + if (ch == '\n') { + uart_poll_send('\r'); + } +} + +int TestPrintf(const char *format, va_list vaList) +{ + int len; + char buff[OS_MAX_SHOW_LEN] = {0}; + char *str = buff; + + len = vsnprintf_s(buff, OS_MAX_SHOW_LEN, OS_MAX_SHOW_LEN, format, vaList); + if (len == -1) { + return len; + } + + while (*str != '\0') { + TestPutc(*str); + str++; + } + + return OS_OK; +} + +U32 PRT_Printf(const char *format, ...) +{ + va_list vaList; + S32 count; + + va_start(vaList, format); + count = TestPrintf(format, vaList); + va_end(vaList); + + return count; +} + +U32 PRT_PrintfInit() +{ + U32 ret; + + ret = PRT_UartInit(); + if (ret != OS_OK) { + return ret; + } + + return OS_OK; +} diff --git a/demos/hi3093/bsp/start.S b/demos/hi3093/bsp/start.S new file mode 100644 index 0000000..c425013 --- /dev/null +++ b/demos/hi3093/bsp/start.S @@ -0,0 +1,121 @@ +@/* +@ * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. +@ * +@ * UniProton is licensed under Mulan PSL v2. +@ * You can use this software according to the terms and conditions of the Mulan PSL v2. +@ * You may obtain a copy of Mulan PSL v2 at: +@ * http://license.coscl.org.cn/MulanPSL2 +@ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +@ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +@ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +@ * See the Mulan PSL v2 for more details. +@ * Create: 2009-12-22 +@ * Description: thread scheduler +@ */ +#include "prt_buildef.h" + + .global OsResetVector + .global mmu_init + + .type mmu_init, function + .type start, function + .section .text.bspinit, "ax" + .balign 4 + +#define HCR_EL2_FMO (1 << 3) +#define HCR_EL2_IMO (1 << 4) +#define HCR_EL2_AMO (1 << 5) +#define HCR_EL2_TWI (1 << 13) +#define HCR_EL2_TWE (1 << 14) +#define HCR_EL2_TVM (1 << 26) +#define HCR_EL2_TGE (1 << 27) +#define HCR_EL2_TDZ (1 << 28) +#define HCR_EL2_HCD (1 << 29) +#define HCR_EL2_TRVM (1 << 30) +#define HCR_EL2_RW (1 << 31) + +#define SPSR_DBG_MASK (1 << 9) +#define SPSR_SERR_MASK (1 << 8) +#define SPSR_IRQ_MASK (1 << 7) +#define SPSR_FIQ_MASK (1 << 6) +#define SPSR_M_AARCH64 (0 << 4) +#define SPSR_M_AARCH32 (1 << 4) +#define SPSR_M_EL1H (5) +#define SPSR_M_EL2H (9) + +#define CNTHCTL_EL2_EL1PCEN_EN (1 << 1) +#define CNTHCTL_EL2_EL1PCTEN_EN (1 << 0) +#define CPACR_EL1_FPEN_EN (3 << 20) + + .global OsElxState + .type OsElxState, @function +OsElxState: + MRS x6, CurrentEL + MOV x2, #0x4 + CMP w6, w2 + + BEQ Start + +OsEl2Entry: + MRS x10, CNTHCTL_EL2 + ORR x10, x10, #0x3 + MSR CNTHCTL_EL2, x10 + + MRS x10, CNTKCTL_EL1 + ORR x10, x10, #0x3 + MSR CNTKCTL_EL1, x10 + + MRS x10, MIDR_EL1 + MRS x1, MPIDR_EL1 + MSR VPIDR_EL2, x10 + MSR VMPIDR_EL2, x1 + + MOV x10, #0x33ff + MSR CPTR_EL2, x10 + MSR HSTR_EL2, xzr + + MRS x10, CPACR_EL1 + MOV x10, #3 << 20 + MSR CPACR_EL1, x10 + + MOV x10, #(HCR_EL2_RW) + ORR x10, x10, #(HCR_EL2_HCD) + BIC x10, x10, #(HCR_EL2_TVM) + BIC x10, x10, #(HCR_EL2_TRVM) + BIC x10, x10, #(HCR_EL2_TGE) + BIC x10, x10, #(HCR_EL2_AMO) + BIC x10, x10, #(HCR_EL2_IMO) + BIC x10, x10, #(HCR_EL2_FMO) + BIC x10, x10, #(HCR_EL2_TWI) + BIC x10, x10, #(HCR_EL2_TWE) + + MSR HCR_EL2, x10 + +OsEl2SwitchToEl1: + ADR x0, Start + MSR SP_EL1, XZR + MSR ELR_EL2, x0 + MOV x0, XZR + + LDR x20, =(SPSR_DBG_MASK | SPSR_SERR_MASK | \ + SPSR_IRQ_MASK | SPSR_FIQ_MASK | SPSR_M_EL1H) + MSR SPSR_EL2, x20 + + TLBI ALLE1IS + IC IALLU + DSB SY + ISB + ERET + +Start: + LDR x1, =__os_sys_sp_end + BIC sp, x1, #0xf + + BL mmu_init + B OsResetVector + +OsEnterReset: + B OsEnterReset + + .section .text, "ax" + .balign 4 diff --git a/demos/hi3093/bsp/timer.c b/demos/hi3093/bsp/timer.c new file mode 100644 index 0000000..e6dd72f --- /dev/null +++ b/demos/hi3093/bsp/timer.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton hi3093 demo + */ +#include "prt_sys.h" +#include "prt_tick.h" +#include "prt_config.h" +#include "prt_task.h" +#include "prt_hwi.h" +#include "cpu_config.h" +#include "securec.h" + +U64 g_timerFrequency; +#define PMU_TIMER_FREQUENCY g_timerFrequency + +U64 GetGenericTimerFreq(void) +{ + U64 freq; + + OS_EMBED_ASM("MRS %0, CNTFRQ_EL0" : "=r"(freq) : : "memory", "cc"); + + return freq; +} + +void TimerIsr(uintptr_t para) +{ + (void)para; + U32 cfgMask = 0x0; + U64 cycle = PMU_TIMER_FREQUENCY / OS_TICK_PER_SECOND; + + OS_EMBED_ASM("MSR CNTP_CTL_EL0, %0" : : "r"(cfgMask) : "memory"); + PRT_ISB(); + OS_EMBED_ASM("MSR CNTP_TVAL_EL0, %0" : : "r"(cycle) : "memory", "cc"); + + cfgMask = 0x1; + OS_EMBED_ASM("MSR CNTP_CTL_EL0, %0" : : "r"(cfgMask) : "memory"); + + PRT_TickISR(); + PRT_ISB(); +} + +void CoreTimerInit(void) +{ + U32 cfgMask = 0x0; + U64 cycle = PMU_TIMER_FREQUENCY / OS_TICK_PER_SECOND; + + OS_EMBED_ASM("MSR CNTP_CTL_EL0, %0" : : "r"(cfgMask) : "memory"); + PRT_ISB(); + OS_EMBED_ASM("MSR CNTP_TVAL_EL0, %0" : : "r"(cycle) : "memory", "cc"); + + cfgMask = 0x1; + OS_EMBED_ASM("MSR CNTP_CTL_EL0, %0" : : "r"(cfgMask) : "memory"); +} + +U32 CoreTimerStart(void) +{ + g_timerFrequency = GetGenericTimerFreq(); + CoreTimerInit(); + + return OS_OK; +} + +U32 TestClkStart(void) +{ + U32 ret; + + ret = PRT_HwiSetAttr(TEST_CLK_INT, 10, OS_HWI_MODE_ENGROSS); + if (ret != OS_OK) { + return ret; + } + + ret = PRT_HwiCreate(TEST_CLK_INT, (HwiProcFunc)TimerIsr, 0); + if (ret != OS_OK) { + return ret; + } + +#if (OS_GIC_VER == 3) + ret = PRT_HwiEnable(TEST_CLK_INT); + if (ret != OS_OK) { + return ret; + } +#elif (OS_GIC_VER == 2) + IsrRegister(TEST_CLK_INT, 0xaU, (0x1U << 0x3U)); +#endif + + ret = CoreTimerStart(); + if (ret != OS_OK) { + return ret; + } + + return OS_OK; +} diff --git a/demos/hi3093/bsp/uart/CMakeLists.txt b/demos/hi3093/bsp/uart/CMakeLists.txt new file mode 100644 index 0000000..53669b0 --- /dev/null +++ b/demos/hi3093/bsp/uart/CMakeLists.txt @@ -0,0 +1,2 @@ +set(SRCS uart.c uart_core.c serial.c) +add_library(uart OBJECT ${SRCS}) \ No newline at end of file diff --git a/demos/hi3093/bsp/uart/common.h b/demos/hi3093/bsp/uart/common.h new file mode 100644 index 0000000..bf1890f --- /dev/null +++ b/demos/hi3093/bsp/uart/common.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton hi3093 demo + */ +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include "prt_config.h" + +#define PERI_APB_FREQ 100000000 +#define UART_BUSY_TIMEOUT 1000000 +#define ETIME 62 + +#define DIV_ROUND_CLOSEST(x, divisor, result) \ +({ \ + typeof(x) __x = x; \ + typeof(divisor) __d = divisor; \ + result = (((typeof(x)) - 1) > 0 || \ + ((typeof(divisor)) - 1) > 0 || \ + (((__x) > 0) == ((__d) > 0))) ? \ + (((__x) + ((__d) / 2)) / (__d)) : \ + (((__x) - ((__d) / 2)) / (__d)); \ +}) + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ + +#endif /* __COMMON_H__ */ \ No newline at end of file diff --git a/demos/hi3093/bsp/uart/serial.c b/demos/hi3093/bsp/uart/serial.c new file mode 100644 index 0000000..de2cdbf --- /dev/null +++ b/demos/hi3093/bsp/uart/serial.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton hi3093 demo + */ +#include "serial.h" +#include "securec.h" +#include "common.h" + +serial_t g_sys_serial; +#define HW_UART_NO (g_sys_serial.cfg.hw_uart_no) +#define UART_CLK (PERI_APB_FREQ) +#define EAGAIN 11 + +void serial_soft_init(serial_cfg *cfg, uart_ops *hw_ops) +{ + if (!cfg || !hw_ops) { + return; + } + + g_sys_serial.cfg.init_done = 0; + g_sys_serial.cfg.hw_uart_no = SERIAL_SEL_UART_PORT; + g_sys_serial.cfg.uart_src_clk = UART_CLK; + strncpy_s(g_sys_serial.cfg.name, SERIAL_NAME_SIZE, cfg->name, SERIAL_NAME_SIZE - 1); + g_sys_serial.cfg.data_bits = cfg->data_bits; + g_sys_serial.cfg.stop = cfg->stop; + g_sys_serial.cfg.pen = cfg->pen; + g_sys_serial.cfg.eps = cfg->eps; + g_sys_serial.cfg.baud_rate = cfg->baud_rate; + g_sys_serial.hw_ops = hw_ops; + + g_sys_serial.cfg.init_done = 1; + + return; +} + +void serial_init(serial_cfg *cfg, uart_ops *hw_ops) +{ + if (!cfg || !hw_ops) { + return; + } + + serial_soft_init(cfg, hw_ops); + + g_sys_serial.cfg.init_done = 0; + + if (g_sys_serial.hw_ops->init(&g_sys_serial.cfg)) { + return; + } + + g_sys_serial.cfg.init_done = 1; + + return; +} + +void serial_putc(const char ch) +{ + uart_ops *hw_ops = g_sys_serial.hw_ops; + + if (g_sys_serial.cfg.init_done) { + if (ch == '\n') { + hw_ops->put_char(HW_UART_NO, '\r'); + } + hw_ops->put_char(HW_UART_NO, ch); + } + + return; +} + +S32 serial_getc(void) +{ + uart_ops *hw_ops = g_sys_serial.hw_ops; + + if (g_sys_serial.cfg.init_done) { + if (!hw_ops->rx_ready(HW_UART_NO)) { + return -EAGAIN; + } + + return hw_ops->get_char(HW_UART_NO); + } + + return -EAGAIN; +} + +void serial_puts(const char *s) +{ + if (!g_sys_serial.cfg.init_done) { + return; + } + + while (*s) { + serial_putc(*s++); + } + + return; +} + +S32 serial_tstc(void) +{ + uart_ops *hw_ops = NULL; + + if (!g_sys_serial.cfg.init_done) { + return OS_OK; + } + + hw_ops = g_sys_serial.hw_ops; + + return (S32)hw_ops->rx_ready(HW_UART_NO); +} + +void serial_flush(void) +{ + uart_ops *hw_ops = g_sys_serial.hw_ops; + + if (!g_sys_serial.cfg.init_done) { + return; + } + + /* just flush, don't care fail */ + (void)hw_ops->wait4idle(g_sys_serial.cfg.hw_uart_no, SERIAL_FLUSH_TMOUT); +} diff --git a/demos/hi3093/bsp/uart/serial.h b/demos/hi3093/bsp/uart/serial.h new file mode 100644 index 0000000..427bc86 --- /dev/null +++ b/demos/hi3093/bsp/uart/serial.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton hi3093 demo + */ +#ifndef __SERIAL_H__ +#define __SERIAL_H__ + +#include "uart_regs.h" +#include "prt_typedef.h" + +#define SERIAL_SEL_UART_PORT 4 + +#define SERIAL_TIMEOUT_MS 10 +#define SERIAL_NAME_SIZE 32 +#define SERIAL_FLUSH_TMOUT 0x100000 + +typedef struct _serial_cfg { + char name[SERIAL_NAME_SIZE]; + S32 init_done; + S32 hw_uart_no; + U32 uart_src_clk; + U8 data_bits; + U8 stop; + U8 pen; + U8 eps; + S32 baud_rate; +} serial_cfg; + +typedef struct { + S32 (*init)(serial_cfg *cfg); + void (*setbrg)(serial_cfg *cfg); + S32 (*put_char)(S32 hw_uart_no, const char ch); + S32 (*get_char)(S32 hw_uart_no); + S32 (*tx_ready)(S32 hw_uart_no); + S32 (*rx_ready)(S32 hw_uart_no); + S32 (*wait4idle)(S32 hw_uart_no, U32 time_out); +} uart_ops; + +typedef struct _serial { + serial_cfg cfg; + uart_ops *hw_ops; +} serial_t; + +extern uart_ops g_uart_ops; +extern serial_cfg g_uart_cfg; + +extern void serial_soft_init(serial_cfg *cfg, uart_ops *hw_ops); +extern void serial_init(serial_cfg *cfg, uart_ops *hw_ops); +extern serial_t *serial_get(void); +extern void serial_putc(const char ch); +extern S32 serial_getc(void); +extern void serial_puts(const char *s); +extern S32 serial_tstc(void); +extern void serial_flush(void); +extern void printf_resource_init(void); +extern S32 uart_init(serial_cfg *cfg); +extern void uart_raw_puts(S32 uart_no, const S8 *str); +extern S32 uart_busy_poll(S32 hw_uart_no); + +#endif /* __SERIAL_H__ */ \ No newline at end of file diff --git a/demos/hi3093/bsp/uart/uart.c b/demos/hi3093/bsp/uart/uart.c new file mode 100644 index 0000000..68c207d --- /dev/null +++ b/demos/hi3093/bsp/uart/uart.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton hi3093 demo + */ +#include "serial.h" +#include "uart_core.h" +#include "uart_regs.h" +#include "common.h" +#include "prt_typedef.h" + +static S32 uart_busy_timeout(void) +{ + return UART_BUSY_TIMEOUT; +} + +/* Caculate UART Divisor Factor */ +void calc_uart_dll_dlh(U32 uartclk, U32 baudrate, U32 *dll, U32 *dlh) +{ + U32 divisor; + + /* + * baudrate = bus_clock / (16 * divisor) + * ==> divisor = bus_clock/(baudrate * 16) */ + DIV_ROUND_CLOSEST(uartclk, (16 * baudrate), divisor); /* 16 just for codestyle */ + *dll = divisor & 0xFF; + *dlh = (divisor >> 8) & 0xFF; /* take high 8 bits */ +} + +static U32 calc_lcr_reg_val(serial_cfg *cfg) +{ + U32 lcr = 0; + + switch (cfg->data_bits) { + case 8: /* 8个数据位 */ + lcr |= DW_UART_8bit; + break; + case 7: /* 7个数据位 */ + lcr |= DW_UART_7bit; + break; + case 6: /* 6个数据位 */ + lcr |= DW_UART_6bit; + break; + case 5: /* 5个数据位 */ + lcr |= DW_UART_5bit; + break; + default: + lcr |= DW_UART_8bit; + break; + } + + /* 0 - 1 stop bit 1 - 2 stop bit */ + if (cfg->stop == 2) { + lcr |= DW_UART_STOP; + } + + if (cfg->pen) { + lcr |= DW_UART_PEN; + if (cfg->eps) { + lcr |= DW_UART_EPS; + } + } + + return lcr; +} + +void uart_set_baudrate(serial_cfg *cfg) +{ + U32 dll = 0; + U32 dlh = 0; + + /* Wait till uart is idle */ + (void)uart_wait4idle(cfg->hw_uart_no, uart_busy_timeout()); + calc_uart_dll_dlh(cfg->uart_src_clk, cfg->baud_rate, &dll, &dlh); + uart_set_dll_dlh(cfg->hw_uart_no, dll, dlh); +} + +S32 uart_init(serial_cfg *cfg) +{ + U32 fifo_ctrl; + + /* max data_bits is 8 */ + if ((cfg == NULL) || (cfg->hw_uart_no >= MAX_UART_NUM) || (cfg->hw_uart_no < 0) || (cfg->data_bits > 8)) { + return -EINVAL; + } + + /* Config FIFO,DLL,DLH at first */ + uart_set_baudrate(cfg); + fifo_ctrl = FIFOENA | UART_FCR_RXCLR | UART_FCR_TXCLR; + uart_set_fifo_ctrl(cfg->hw_uart_no, fifo_ctrl); + /* Set data bits, stop bit, parity check */ + uart_set_lcr(cfg->hw_uart_no, calc_lcr_reg_val(cfg)); + + /* enable rx irq */ + uart_set_irq_enable(cfg->hw_uart_no, 1); + return OS_OK; +} + +S32 uart_tx(S32 hw_uart_no, const char c) +{ + S32 timeout = 0; + S32 max_timeout = uart_busy_timeout(); + + while (uart_is_txfifo_full(hw_uart_no)) { + timeout++; + if (timeout >= max_timeout) { + return -ETIME; + } + } + + uart_tx_char(hw_uart_no, c); + return OS_OK; +} + +S32 uart_rx(S32 hw_uart_no) +{ + S32 timeout = 0; + S32 max_timeout = uart_busy_timeout(); + S32 c = 0; + + while (!uart_is_rx_ready(hw_uart_no)) { + timeout++; + if (timeout >= max_timeout) { + return -ETIME; + } + } + + uart_rx_char(hw_uart_no, (S8 *)&c); + return c; +} + +void uart_raw_puts(S32 hw_uart_no, const S8 *str) +{ + while (*str != '\0') { + uart_tx_char(hw_uart_no, *str++); + } +} + +S32 uart_tx_ready(S32 hw_uart_no) +{ + if (uart_is_txfifo_full(hw_uart_no)) { + return OS_OK; + } else { + return 1; + } +} + +S32 uart_rx_ready(S32 hw_uart_no) +{ + return uart_is_rx_ready(hw_uart_no); +} + +/* + * Wait until uart is not busy + * Return 0 if success,otherwise return -1 + */ +S32 uart_busy_poll(S32 hw_uart_no) +{ + return uart_wait4idle(hw_uart_no, uart_busy_timeout()); +} + +serial_cfg g_uart_cfg = { + .name = "uart", + .data_bits = 8, /* default data_bits is 8 */ + .stop = 1, + .pen = 0, + .baud_rate = 115200 /* default baud_rate is 115200 */ +}; + +uart_ops g_uart_ops = { + .init = uart_init, + .setbrg = uart_set_baudrate, + .put_char = uart_tx, + .get_char = uart_rx, + .tx_ready = uart_tx_ready, + .rx_ready = uart_rx_ready, + .wait4idle = uart_wait4idle, +}; diff --git a/demos/hi3093/bsp/uart/uart_core.c b/demos/hi3093/bsp/uart/uart_core.c new file mode 100644 index 0000000..f7377bb --- /dev/null +++ b/demos/hi3093/bsp/uart/uart_core.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton hi3093 demo + */ +#include "uart_core.h" +#include "common.h" + +#define UART_REG_READ(addr) (*(volatile U32 *)(((uintptr_t)addr))) +#define UART_REG_WRITE(value, addr) (*(volatile U32 *)((uintptr_t)addr) = (U32)value) + +/* Get UART register base address */ +static S32 uart_core_base_addr(S32 uartno, U32 *reg_base) +{ + unsigned long reg_bases[] = { + UART0_REG_BASE, + UART1_REG_BASE, + UART2_REG_BASE, + UART3_REG_BASE, + UART4_REG_BASE + }; + + if (uartno >= MAX_UART_NUM || uartno < 0) { + return -1; + } + + *reg_base = reg_bases[uartno]; + + return OS_OK; +} + +S32 uart_reg_read(S32 uartno, U32 offset, U32 *val) +{ + S32 ret; + U32 reg_base = 0x0; + + ret = uart_core_base_addr(uartno, ®_base); + if (ret) { + return ret; + } + + *val = UART_REG_READ((unsigned long)(reg_base + offset)); + return OS_OK; +} + +void uart_reg_write(S32 uartno, U32 offset, U32 val) +{ + S32 ret; + U32 reg_base = 0x0; + + ret = uart_core_base_addr(uartno, ®_base); + if (ret) { + return; + } + + UART_REG_WRITE(val, (unsigned long)(reg_base + offset)); + return; +} + +void uart_set_lcr_dlab(S32 uartno, S32 dlab_sel) +{ + S32 ret; + U32 lcr = 0; + + ret = uart_reg_read(uartno, DW_UART_LCR, &lcr); + if (ret) { + return; + } + + if (dlab_sel) { + lcr |= DW_UART_DLAB; + } else { + lcr &= ~DW_UART_DLAB; + } + + uart_reg_write(uartno, DW_UART_LCR, lcr); + return; +} + +void uart_set_dll_dlh(S32 uartno, U32 dll, U32 dlh) +{ + /* Enable DLL/DLH/FCR access */ + uart_set_lcr_dlab(uartno, 1); + uart_reg_write(uartno, DW_UART_DLL, dll); + uart_reg_write(uartno, DW_UART_DLH, dlh); + uart_set_lcr_dlab(uartno, 0); + return; +} + +void uart_get_dll_dlh(S32 uartno, U32 *dll, U32 *dlh) +{ + /* Enable DLL/DLH/FCR access */ + uart_set_lcr_dlab(uartno, 1); + uart_reg_read(uartno, DW_UART_DLL, dll); + uart_reg_read(uartno, DW_UART_DLH, dlh); + uart_set_lcr_dlab(uartno, 0); + return; +} + +void uart_set_fifo_ctrl(S32 uartno, U32 fifo_ctrl) +{ + /* Enable DLL/DLH/FCR access */ + uart_set_lcr_dlab(uartno, 1); + uart_reg_write(uartno, DW_UART_FCR, fifo_ctrl); + uart_set_lcr_dlab(uartno, 0); + return; +} + +void uart_set_lcr(S32 uartno, U32 lcr) +{ + uart_reg_write(uartno, DW_UART_LCR, lcr); + return; +} + +/* value: 0:禁止;1:使能 */ +void uart_set_irq_enable(S32 uartno, U32 value) +{ + uart_reg_write(uartno, ELSI, value); + return; +} + +S32 uart_is_txfifo_full(S32 uartno) +{ + S32 ret; + U32 usr = 0; + + ret = uart_reg_read(uartno, DW_UART_USR, &usr); + if (ret) { + return OS_OK; + } + + return (usr & DW_XFIFO_NOT_FULL) ? 0 : 1; +} + +S32 uart_is_rx_ready(S32 uartno) +{ + U32 lsr = 0; + + (void)uart_reg_read(uartno, DW_UART_LSR, &lsr); + return (lsr & DW_UART_LSR_DDR) ? 1 : 0; +} + +void uart_tx_char(S32 uartno, const S8 c) +{ + uart_reg_write(uartno, DW_UART_THR, (U32)(U8)c); + return; +} + +void uart_rx_char(S32 uartno, S8 *c) +{ + U32 rbr = 0; + + (void)uart_reg_read(uartno, DW_UART_RBR, &rbr); + *c = (S8)(rbr & 0xFF); + + return; +} + +S32 uart_wait4idle(S32 uartno, U32 timeout) +{ + U32 usr = 0; + + while (timeout) { + (void)uart_reg_read(uartno, DW_UART_USR, &usr); + if ((usr & (DW_UART_BUSY)) == 0) { + return OS_OK; + } + + timeout--; + } + + return -1; +} diff --git a/demos/hi3093/bsp/uart/uart_core.h b/demos/hi3093/bsp/uart/uart_core.h new file mode 100644 index 0000000..15c5951 --- /dev/null +++ b/demos/hi3093/bsp/uart/uart_core.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton hi3093 demo + */ +#ifndef __DW_UART_CORE_H__ +#define __DW_UART_CORE_H__ + +#include "uart_regs.h" +#include "common.h" + +#define MAX_UART_NUM 8 + +extern S32 uart_reg_read(S32 uart_num, U32 offset, U32 *val); +extern void uart_reg_write(S32 uart_num, U32 offset, U32 val); +extern void uart_set_dll_dlh(S32 uart_num, U32 dll, U32 dlh); +extern void uart_get_dll_dlh(S32 uart_num, U32 *dll, U32 *dlh); +extern void uart_set_fifo_ctrl(S32 uart_num, U32 fifo_ctrl); +extern void uart_set_lcr(S32 uart_num, U32 lcr); +extern void uart_set_irq_enable(S32 uartno, U32 value); +extern S32 uart_is_txfifo_full(S32 uart_num); +extern S32 uart_is_rx_ready(S32 uart_num); +extern void uart_tx_char(S32 uart_num, const S8 c); +extern void uart_rx_char(S32 uart_num, S8 *c); +extern S32 uart_wait4idle(S32 uartno, U32 timeout); + +#endif /* __DW_UART_CORE_H__ */ \ No newline at end of file diff --git a/demos/hi3093/bsp/uart/uart_regs.h b/demos/hi3093/bsp/uart/uart_regs.h new file mode 100644 index 0000000..741340a --- /dev/null +++ b/demos/hi3093/bsp/uart/uart_regs.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton hi3093 demo + */ +#ifndef __DW_UART_REGS_H__ +#define __DW_UART_REGS_H__ + +#define UART0_REG_BASE 0x0872A000 +#define UART1_REG_BASE 0x0872B000 +#define UART2_REG_BASE 0x08710000 +#define UART3_REG_BASE 0x08711000 +#define UART4_REG_BASE 0x08743000 +#define UART5_REG_BASE 0x08744000 +#define UART6_REG_BASE 0x0875D000 +#define UART7_REG_BASE 0x0875E000 + +#define CCORE_SYS_UART2_INTID 90 +#define CCORE_SYS_UART3_INTID 91 +#define CCORE_SYS_UART4_INTID 92 +#define CCORE_SYS_UART5_INTID 93 +#define CCORE_SYS_UART6_INTID 94 +#define CCORE_SYS_UART7_INTID 95 + +/* + * UART register offsets + */ +#define DW_UART_RBR 0x00 +#define DW_UART_THR 0x00 +#define DW_UART_DLL 0x00 + +#define DW_UART_DLH 0x04 +#define DW_UART_IER 0x04 + +#define DW_UART_IIR 0x08 +#define DW_UART_FCR 0x08 + +#define DW_UART_LCR 0x0C + +#define DW_UART_MCR 0x10 + +#define DW_UART_LSR 0x14 +#define DW_UART_MSR 0x18 + +#define DW_UART_USR 0x7C +#define DW_UART_TFL 0x80 +#define DW_UART_RFL 0x84 + +#define DW_UART_HTX 0xA4 + +/* LSR 线性状态寄存器区域 */ +#define DW_UART_LSR_TEMT 0x40 +#define DW_UART_LSR_THRE 0x20 +#define DW_UART_LSR_BI 0x10 +#define DW_UART_LSR_FE 0x08 +#define DW_UART_LSR_PE 0x04 +#define DW_UART_LSR_R 0x02 +#define DW_UART_LSR_DDR 0x01 + +#define BIT(n) (1 << (n)) + +/* LCR bit field */ +#define DW_UART_DLAB BIT(7) +#define DW_UART_BREAK BIT(6) +#define DW_UART_STICK BIT(5) +#define DW_UART_EPS BIT(4) +#define DW_UART_PEN BIT(3) +#define DW_UART_STOP BIT(2) +#define DW_UART_8bit 0x3 +#define DW_UART_7bit 0x2 +#define DW_UART_6bit 0x1 +#define DW_UART_5bit 0x0 +#define DW_UART_DATALEN_MASK 0x03 + +/* IER bit field */ +#define PTIME BIT(7) +#define EDSSI BIT(3) +#define ELSI BIT(2) +#define ETBEI BIT(1) +#define ERBFI BIT(0) + +/* LSR bit field */ +#define DW_RFE BIT(7) +#define DW_TEMT BIT(6) +#define DW_THRE BIT(5) +#define DW_BI BIT(4) +#define DW_FE BIT(3) +#define DW_PE BIT(2) +#define DW_OE BIT(1) +#define DW_DR BIT(0) + +#define UART_DW_DR_PE DW_PE +#define UART_DW_DR_FE DW_FE +#define UART_DW_DR_OE DW_OE +#define UART_DW_DR_BE DW_BI + +#define DW_RSR_ANY (DW_OE | DW_PE | DW_FE | DW_BI) +#define DW_DUMMY_RSR_RX + +/* MCR bit field */ +#define DW_MC_AFCE BIT(5) +#define DW_MC_LOOP BIT(4) +#define DW_MC_OUT2 BIT(3) +#define DW_MC_OUT1 BIT(2) +#define DW_MC_RTS BIT(1) +#define DW_MC_DTR BIT(0) + +/* MSR bit field */ +#define DW_DCD BIT(7) +#define DW_RI BIT(6) +#define DW_DSR BIT(5) +#define DW_CTS BIT(4) +#define DW_MSR_ANY (DW_DCD | DW_DSR | DW_CTS) + +/* IIR bit field */ +#define DW_RECEIVERR 0x06 +#define DW_RECEIVEAVA 0x04 +#define DW_RECTIMEOUT 0x0C +#define DW_TRANSEMP 0x02 +#define DW_NOINTERRUPT 0x01 +#define DW_MODEMSTA 0x0 +#define DW_BUSY 0x7 + +/* FCR bit field */ +#define RECFIFO1_2 (0x02 << 6) +#define TXFIFO1_2 (0x03 << 4) +#define FIFOENA 1 +#define UART_FCR_RXCLR 0x02 +#define UART_FCR_TXCLR 0x04 + +/* USR bit field */ +#define DW_UART_BUSY 0x01 +#define DW_XFIFO_NOT_FULL 0x02 +#define DW_XFIFO_EMP 0x04 +#define DW_RFIFO_NOT_EMP 0x08 +#define DW_RFIFO_FULL 0x10 + +#endif /* __DW_UART_REGS_H__ */ \ No newline at end of file diff --git a/demos/hi3093/build/build_app.sh b/demos/hi3093/build/build_app.sh new file mode 100644 index 0000000..4806420 --- /dev/null +++ b/demos/hi3093/build/build_app.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Copyright (c) 2023 Huawei Device Co., Ltd. +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. + +export TOOLCHAIN_PATH=/opt/buildtools/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf +export APP=hi3093 +export TMP_DIR=$APP + +sh ./build_static.sh $APP +sh ./build_openamp.sh + +cmake -S .. -B $TMP_DIR -DAPP:STRING=$APP -DTOOLCHAIN_PATH:STRING=$TOOLCHAIN_PATH +pushd $TMP_DIR +make $APP +popd +cp ./$TMP_DIR/$APP $APP.elf +$TOOLCHAIN_PATH/bin/aarch64-none-elf-objcopy -O binary ./$APP.elf $APP.bin +$TOOLCHAIN_PATH/bin/aarch64-none-elf-objdump -D ./$APP.elf > $APP.asm +rm -rf $TMP_DIR diff --git a/demos/hi3093/build/build_openamp.sh b/demos/hi3093/build/build_openamp.sh new file mode 100644 index 0000000..22febe9 --- /dev/null +++ b/demos/hi3093/build/build_openamp.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# Copyright (c) 2023 Huawei Device Co., Ltd. +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. + +echo "################# git clone libmetal #################" +pushd ../component +rm -rf ./libmetal* +git clone https://gitee.com/src-openeuler/libmetal.git +mv ./libmetal/libmetal-2022.10.0.tar.gz . +rm -rf ./libmetal +tar -zxvf libmetal-2022.10.0.tar.gz +mv ./libmetal-2022.10.0 ./libmetal +cp UniProton-patch-for-libmetal.patch ./libmetal +cd libmetal +patch -p1 -d . < UniProton-patch-for-libmetal.patch +popd + +echo "################# git clone openamp #################" +pushd ../component +rm -rf ./open-amp* +git clone https://gitee.com/src-openeuler/OpenAMP.git +mv ./OpenAMP/openamp-2022.10.1.tar.gz . +rm -rf ./OpenAMP +tar -zxvf openamp-2022.10.1.tar.gz +mv ./openamp-2022.10.1 ./open-amp +cp UniProton-patch-for-openamp.patch ./open-amp +cd open-amp +patch -p1 -d . < UniProton-patch-for-openamp.patch +popd + +echo "######################### build metal #########################" +pushd . +mkdir -p libmetal +cd libmetal +mkdir -p build +cd build +rm -rf * +cmake ../../../component/libmetal -DCMAKE_TOOLCHAIN_FILE=../../../component/libmetal/cmake/platforms/uniproton_arm64_gcc.cmake -DWITH_DOC=OFF -DWITH_EXAMPLES=OFF -DWITH_TESTS=OFF -DWITH_DEFAULT_LOGGER=OFF -DWITH_SHARED_LIB=OFF +make VERBOSE=1 DESTDIR=../output install +if [ $? -ne 0 ];then + echo "make metal failed!" + exit 1 +fi +popd + +echo "######################### build openamp #########################" +pushd . +mkdir -p open-amp +cd open-amp +mkdir -p build +cd build +rm -rf * +cmake ../../../component/open-amp -DCMAKE_TOOLCHAIN_FILE=../../../component/open-amp/cmake/platforms/uniproton_arm64_gcc.cmake +make VERBOSE=1 DESTDIR=../output install +if [ $? -ne 0 ];then + echo "make openamp failed!" + exit 1 +fi +popd + +cp ./libmetal/output/usr/local/lib/*.a ../libs +cp ./open-amp/output/usr/local/lib/*.a ../libs diff --git a/demos/hi3093/build/build_static.sh b/demos/hi3093/build/build_static.sh new file mode 100644 index 0000000..3e7092e --- /dev/null +++ b/demos/hi3093/build/build_static.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Copyright (c) 2023 Huawei Device Co., Ltd. +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. + +git clone https://gitee.com/openeuler/libboundscheck.git + +cp libboundscheck/include/* ../../../platform/libboundscheck/include +cp libboundscheck/include/* ../include +cp libboundscheck/src/* ../../../platform/libboundscheck/src +rm -rf libboundscheck + +pushd ./../../../ +python build.py $1 +cp output/UniProton/lib/$1/* demos/$1/libs +cp output/libboundscheck/lib/$1/* demos/$1/libs +cp -r src/include/uapi/* demos/$1/include +popd diff --git a/demos/hi3093/build/hi3093.ld b/demos/hi3093/build/hi3093.ld new file mode 100644 index 0000000..e0d119b --- /dev/null +++ b/demos/hi3093/build/hi3093.ld @@ -0,0 +1,120 @@ +ENTRY(__text_start) + +_stack_size = 0x10000; +_heap_size = 0x10000; + +MEMORY +{ + IMU_SRAM (rwx) : ORIGIN = 0x93000000, LENGTH = 0x800000 + MMU_MEM (rwx) : ORIGIN = 0x93800000, LENGTH = 0x800000 +} + +SECTIONS +{ + text_start = .; + .start_bspinit : + { + __text_start = .; + KEEP(*(.text.bspinit)) + } > IMU_SRAM + + .start_text : + { + KEEP(*(.text.startup)) + } > IMU_SRAM + + .text : + { + *(.text) + *(.text.*) + *(*.text) + . = ALIGN(8); + __text_end = .; + } > IMU_SRAM + . = ALIGN(8); + data_copy_start = .; + + .rodata : + { + . = ALIGN(8); + __rodata_start = .; + *(.rodata) + *(.rodata.*) + . = ALIGN(8); + __rodata_end = .; + } > IMU_SRAM + + .eh_frame : + { + . = ALIGN(8); + __os_unwind_table_start = .; + *(.eh_frame) + __os_unwind_table_end = .; + } > IMU_SRAM + + .heap (NOLOAD) : + { + . = ALIGN(8); + PROVIDE (__HEAP_INIT = .); + . = . + _heap_size; + . = ALIGN(8); + PROVIDE (__HEAP_END = .); + } > IMU_SRAM + + .stack (NOLOAD) : + { + . = ALIGN(8); + PROVIDE (__os_sys_sp_start = .); + . = . + _stack_size; + . = ALIGN(8); + PROVIDE (__os_sys_sp_end = .); + } > IMU_SRAM + end = .; + + .percpu.data : + { + __os_per_cpu_start = .; + *(.os.percpu.data) + __os_per_cpu_end = .; + LONG (ALIGNOF(.percpu.data)) + } > IMU_SRAM + + .data : + { + . = ALIGN(8); + __data_start = .; + *(.data) + *(.data.*) + . = ALIGN(8); + __os_text_start = .; + QUAD(__text_start) + QUAD(__text_end) + __os_text_end = .; + __data_end = .; + } > IMU_SRAM + + .llt.bss : + { + _llt_bss_start = .; + *__code_measure_stub*.o(.bss) + *__code_measure_stub*.o(.bss.*) + _llt_bss_end = .; + } > IMU_SRAM + + .bss (NOLOAD) : + { + . = ALIGN(8); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(8); + __bss_end__ = .; + } > IMU_SRAM + + .mmu.table.base : + { + PROVIDE (g_mmu_page_begin = .); + PROVIDE (g_mmu_page_end = g_mmu_page_begin + 0x8000); + } > MMU_MEM +} diff --git a/demos/hi3093/component/UniProton-patch-for-libmetal.patch b/demos/hi3093/component/UniProton-patch-for-libmetal.patch new file mode 100644 index 0000000..d22262a --- /dev/null +++ b/demos/hi3093/component/UniProton-patch-for-libmetal.patch @@ -0,0 +1,581 @@ +diff -uparN libmetal-2022.10.0/cmake/platforms/uniproton_arm64_gcc.cmake libmetal/cmake/platforms/uniproton_arm64_gcc.cmake +--- libmetal-2022.10.0/cmake/platforms/uniproton_arm64_gcc.cmake 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/cmake/platforms/uniproton_arm64_gcc.cmake 2023-02-22 11:01:30.000000000 +0800 +@@ -0,0 +1,16 @@ ++#cross-compilation config ++ ++set(CMAKE_SYSTEM_PROCESSOR arm) ++set(PROJECT_SYSTEM uniproton) ++ ++set(CMAKE_C_COMPILER_WORKS 1) ++set(CMAKE_CXX_COMPILER_WORKS 1) ++ ++set(CROSS_PREFIX "/opt/buildtools/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/aarch64-none-elf-" CACHE STRING "") ++set(CMAKE_C_COMPILER "${CROSS_PREFIX}gcc" CACHE STRING "") ++set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE STRING "") ++set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER CACHE STRING "") ++set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER CACHE STRING "") ++set(CMAKE_C_FLAGS "-D_GNU_SOURCE -D_POSIX_THREADS -D_POSIX_THREAD_PRIORITY_SCHEDULING -D_POSIX_PRIORITY_SCHEDULING -D_POSIX_TIMERS -D_POSIX_CPUTIME -D_POSIX_THREAD_CPUTIME -D_POSIX_MONOTONIC_CLOCK -D_POSIX_TIMEOUTS -D_POSIX_CLOCK_SELECTION -D_POSIX_THREAD_PRIO_PROTECT -D_UNIX98_THREAD_MUTEX_ATTRIBUTES -D_POSIX_READER_WRITER_LOCKS" CACHE STRING "") ++ ++# vim: expandtab:ts=2:sw=2:smartindent +diff -uparN libmetal-2022.10.0/CMakeLists.txt libmetal/CMakeLists.txt +--- libmetal-2022.10.0/CMakeLists.txt 2022-10-28 10:12:23.000000000 +0800 ++++ libmetal/CMakeLists.txt 2023-02-24 16:25:04.000000000 +0800 +@@ -6,7 +6,8 @@ endif() + if (POLICY CMP0077) + cmake_policy(SET CMP0077 NEW) + endif() +- ++include_directories(../../include) ++set (CMAKE_SYSTEM_NAME Uniproton) + set (LIBMETAL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + + list (APPEND CMAKE_MODULE_PATH +diff -uparN libmetal-2022.10.0/lib/system/uniproton/alloc.h libmetal/lib/system/uniproton/alloc.h +--- libmetal-2022.10.0/lib/system/uniproton/alloc.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/alloc.h 2023-02-20 14:53:22.000000000 +0800 +@@ -0,0 +1,39 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/alloc.h ++ * @brief Uniproton libmetal memory allocattion definitions. ++ */ ++ ++#ifndef __METAL_ALLOC__H__ ++#error "Include metal/alloc.h instead of metal/uniproton/alloc.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_ALLOC__H__ ++#define __METAL_UNIPROTON_ALLOC__H__ ++ ++#include "prt_mem.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++static inline void *metal_allocate_memory(unsigned int size) ++{ ++ return PRT_MemAlloc(OS_MID_SYS, OS_MEM_DEFAULT_PT0, size); ++} ++ ++static inline void metal_free_memory(void *ptr) ++{ ++ PRT_MemFree(OS_MID_SYS, ptr); ++} ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_ALLOC__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/assert.h libmetal/lib/system/uniproton/assert.h +--- libmetal-2022.10.0/lib/system/uniproton/assert.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/assert.h 2022-12-26 10:59:44.000000000 +0800 +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file assert.h ++ * @brief Uniproton assertion support. ++ */ ++ ++#ifndef __METAL_ASSERT__H__ ++#error "Include metal/assert.h instead of metal/uniproton/assert.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_ASSERT__H__ ++#define __METAL_UNIPROTON_ASSERT__H__ ++ ++/** ++ * @brief Assertion macro. ++ * @param cond Condition to test. ++ */ ++#define metal_sys_assert(cond) ++ ++#endif /* __METAL_UNIPROTON_ASSERT__H__ */ ++ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/cache.h libmetal/lib/system/uniproton/cache.h +--- libmetal-2022.10.0/lib/system/uniproton/cache.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/cache.h 2022-12-26 11:02:08.000000000 +0800 +@@ -0,0 +1,39 @@ ++/* ++ * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/cache.h ++ * @brief Uniproton cache operation primitives for libmetal. ++ */ ++ ++#ifndef __METAL_CACHE__H__ ++#error "Include metal/cache.h instead of metal/uniproton/cache.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_CACHE__H__ ++#define __METAL_UNIPROTON_CACHE__H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++static inline void __metal_cache_flush(void *addr, unsigned int len) ++{ ++ (void)addr; ++ (void)len; ++} ++ ++static inline void __metal_cache_invalidate(void *addr, unsigned int len) ++{ ++ (void)addr; ++ (void)len; ++} ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_CACHE__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/CMakeLists.txt libmetal/lib/system/uniproton/CMakeLists.txt +--- libmetal-2022.10.0/lib/system/uniproton/CMakeLists.txt 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/CMakeLists.txt 2022-12-26 14:13:48.000000000 +0800 +@@ -0,0 +1,17 @@ ++collect (PROJECT_LIB_HEADERS alloc.h) ++collect (PROJECT_LIB_HEADERS assert.h) ++collect (PROJECT_LIB_HEADERS cache.h) ++collect (PROJECT_LIB_HEADERS condition.h) ++collect (PROJECT_LIB_HEADERS io.h) ++collect (PROJECT_LIB_HEADERS irq.h) ++collect (PROJECT_LIB_HEADERS log.h) ++collect (PROJECT_LIB_HEADERS mutex.h) ++collect (PROJECT_LIB_HEADERS sleep.h) ++collect (PROJECT_LIB_HEADERS sys.h) ++ ++collect (PROJECT_LIB_SOURCES condition.c) ++collect (PROJECT_LIB_SOURCES device.c) ++collect (PROJECT_LIB_SOURCES init.c) ++collect (PROJECT_LIB_SOURCES shmem.c) ++ ++# vim: expandtab:ts=2:sw=2:smartindent +diff -uparN libmetal-2022.10.0/lib/system/uniproton/condition.c libmetal/lib/system/uniproton/condition.c +--- libmetal-2022.10.0/lib/system/uniproton/condition.c 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/condition.c 2022-12-26 11:06:12.000000000 +0800 +@@ -0,0 +1,33 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/condition.c ++ * @brief Uniproton libmetal condition variable handling. ++ */ ++ ++#include ++#include ++#include ++ ++int metal_condition_wait(struct metal_condition *cv, ++ metal_mutex_t *m) ++{ ++ unsigned int flags; ++ ++ /* Check if the mutex has been acquired */ ++ if (!cv || !m || !metal_mutex_is_acquired(m)) { ++ return -EINVAL; ++ } ++ ++ flags = metal_irq_save_disable(); ++ /* Release the mutex first. */ ++ metal_mutex_release(m); ++ metal_irq_restore_enable(flags); ++ /* Acquire the mutex again. */ ++ metal_mutex_acquire(m); ++ return 0; ++} +diff -uparN libmetal-2022.10.0/lib/system/uniproton/condition.h libmetal/lib/system/uniproton/condition.h +--- libmetal-2022.10.0/lib/system/uniproton/condition.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/condition.h 2022-12-26 11:09:02.000000000 +0800 +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/condition.h ++ * @brief Uniproton condition variable primitives for libmetal. ++ */ ++ ++#ifndef __METAL_CONDITION__H__ ++#error "Include metal/condition.h instead of metal/uniproton/condition.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_CONDITION__H__ ++#define __METAL_UNIPROTON_CONDITION__H__ ++ ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_CONDITION__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/device.c libmetal/lib/system/uniproton/device.c +--- libmetal-2022.10.0/lib/system/uniproton/device.c 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/device.c 2022-12-26 11:13:30.000000000 +0800 +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/device.c ++ * @brief Uniproton libmetal device definitions. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++int metal_generic_dev_sys_open(struct metal_device *dev) ++{ ++ return 0; ++} ++ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/init.c libmetal/lib/system/uniproton/init.c +--- libmetal-2022.10.0/lib/system/uniproton/init.c 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/init.c 2022-12-26 11:14:34.000000000 +0800 +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/init.c ++ * @brief Uniproton libmetal initialization. ++ */ ++ ++#include ++#include ++ ++struct metal_state _metal; ++ ++int metal_sys_init(const struct metal_init_params *params) ++{ ++ (void)params; ++ metal_bus_register(&metal_generic_bus); ++ return 0; ++} ++ ++void metal_sys_finish(void) ++{ ++ metal_bus_unregister(&metal_generic_bus); ++} +diff -uparN libmetal-2022.10.0/lib/system/uniproton/io.h libmetal/lib/system/uniproton/io.h +--- libmetal-2022.10.0/lib/system/uniproton/io.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/io.h 2022-12-26 11:16:50.000000000 +0800 +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/io.h ++ * @brief Uniproton specific io definitions. ++ */ ++ ++#ifndef __METAL_IO__H__ ++#error "Include metal/io.h instead of metal/uniproton/io.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_IO__H__ ++#define __METAL_UNIPROTON_IO__H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef METAL_INTERNAL ++/** ++ * @brief memory mapping for an I/O region ++ */ ++static inline void metal_sys_io_mem_map(struct metal_io_region *io) ++{ ++ (void)io; ++} ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_IO__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/irq.h libmetal/lib/system/uniproton/irq.h +--- libmetal-2022.10.0/lib/system/uniproton/irq.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/irq.h 2022-12-26 11:17:54.000000000 +0800 +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/irq.c ++ * @brief Uniproton libmetal irq definitions. ++ */ ++ ++#ifndef __METAL_IRQ__H__ ++#error "Include metal/irq.h instead of metal/uniproton/irq.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_IRQ__H__ ++#define __METAL_UNIPROTON_IRQ__H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_IRQ__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/log.h libmetal/lib/system/uniproton/log.h +--- libmetal-2022.10.0/lib/system/uniproton/log.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/log.h 2022-12-26 11:19:38.000000000 +0800 +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/log.h ++ * @brief Uniproton libmetal log handler definition. ++ */ ++ ++#ifndef __METAL_METAL_LOG__H__ ++#error "Include metal/log.h instead of metal/uniproton/log.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_LOG__H__ ++#define __METAL_UNIPROTON_LOG__H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_LOG__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/mutex.h libmetal/lib/system/uniproton/mutex.h +--- libmetal-2022.10.0/lib/system/uniproton/mutex.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/mutex.h 2023-02-23 14:22:12.000000000 +0800 +@@ -0,0 +1,73 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/mutex.h ++ * @brief Uniproton mutex primitives for libmetal. ++ */ ++ ++#ifndef __METAL_MUTEX__H__ ++#error "Include metal/mutex.h instead of metal/uniproton/mutex.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_MUTEX__H__ ++#define __METAL_UNIPROTON_MUTEX__H__ ++ ++#include "errno.h" ++#include "pthread.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef pthread_mutex_t metal_mutex_t; ++ ++/* ++ * METAL_MUTEX_INIT - used for initializing an mutex element in a static struct ++ * or global ++ */ ++#define METAL_MUTEX_INIT(m) MUTEX_INITIALIZER ++/* ++ * METAL_MUTEX_DEFINE - used for defining and initializing a global or ++ * static singleton mutex ++ */ ++#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = MUTEX_INITIALIZER ++ ++static inline void __metal_mutex_init(metal_mutex_t *mutex) ++{ ++ pthread_mutex_init(mutex, NULL); ++} ++ ++static inline void __metal_mutex_deinit(metal_mutex_t *mutex) ++{ ++ pthread_mutex_destroy(mutex); ++} ++ ++static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex) ++{ ++ return pthread_mutex_trylock(mutex); ++} ++ ++static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex) ++{ ++ ++} ++ ++static inline void __metal_mutex_acquire(metal_mutex_t *mutex) ++{ ++ pthread_mutex_lock(mutex); ++} ++ ++static inline void __metal_mutex_release(metal_mutex_t *mutex) ++{ ++ pthread_mutex_unlock(mutex); ++} ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_MUTEX__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/shmem.c libmetal/lib/system/uniproton/shmem.c +--- libmetal-2022.10.0/lib/system/uniproton/shmem.c 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/shmem.c 2022-12-26 11:20:44.000000000 +0800 +@@ -0,0 +1,19 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * ++ * @file uniproton/shmem.c ++ * @brief Uniproton libmetal shared memory handling. ++ */ ++ ++#include ++ ++int metal_shmem_open(const char *name, size_t size, ++ struct metal_io_region **io) ++{ ++ return metal_shmem_open_generic(name, size, io); ++} +diff -uparN libmetal-2022.10.0/lib/system/uniproton/sleep.h libmetal/lib/system/uniproton/sleep.h +--- libmetal-2022.10.0/lib/system/uniproton/sleep.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/sleep.h 2023-02-22 16:55:06.000000000 +0800 +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/sleep.h ++ * @brief Uniproton sleep primitives for libmetal. ++ */ ++ ++#ifndef __METAL_SLEEP__H__ ++#error "Include metal/sleep.h instead of metal/uniproton/sleep.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_SLEEP__H__ ++#define __METAL_UNIPROTON_SLEEP__H__ ++ ++#include "prt_task.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++static inline int __metal_sleep_usec(unsigned int usec) ++{ ++ return PRT_TaskDelay((U32)(usec / 1000)); ++} ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_SLEEP__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/sys.h libmetal/lib/system/uniproton/sys.h +--- libmetal-2022.10.0/lib/system/uniproton/sys.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/sys.h 2022-12-26 11:25:18.000000000 +0800 +@@ -0,0 +1,39 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/sys.h ++ * @brief Uniproton system primitives for libmetal. ++ */ ++ ++#ifndef __METAL_SYS__H__ ++#error "Include metal/sys.h instead of metal/uniproton/sys.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_SYS__H__ ++#define __METAL_UNIPROTON_SYS__H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define METAL_INIT_DEFAULTS \ ++{ \ ++ .log_handler = metal_default_log_handler, \ ++ .log_level = METAL_LOG_INFO, \ ++} ++ ++/** Structure of libmetal runtime state. */ ++struct metal_state { ++ /** Common (system independent) data. */ ++ struct metal_common_state common; ++}; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_SYS__H__ */ diff --git a/demos/hi3093/component/UniProton-patch-for-openamp.patch b/demos/hi3093/component/UniProton-patch-for-openamp.patch new file mode 100644 index 0000000..d4f0c31 --- /dev/null +++ b/demos/hi3093/component/UniProton-patch-for-openamp.patch @@ -0,0 +1,61 @@ +diff -uparN open-amp-2022.10.1/cmake/depends.cmake open-amp/cmake/depends.cmake +--- open-amp-2022.10.1/cmake/depends.cmake 2022-12-13 11:21:05.000000000 +0800 ++++ open-amp/cmake/depends.cmake 2023-02-24 16:36:38.000000000 +0800 +@@ -1,5 +1,5 @@ + if (WITH_LIBMETAL_FIND) +- find_package (Libmetal REQUIRED) ++ #find_package (Libmetal REQUIRED) + collect (PROJECT_INC_DIRS "${LIBMETAL_INCLUDE_DIR}") + collect (PROJECT_LIB_DIRS "${LIBMETAL_LIB_DIR}") + collect (PROJECT_LIB_DEPS "${LIBMETAL_LIB}") +diff -uparN open-amp-2022.10.1/cmake/platforms/uniproton_arm64_gcc.cmake open-amp/cmake/platforms/uniproton_arm64_gcc.cmake +--- open-amp-2022.10.1/cmake/platforms/uniproton_arm64_gcc.cmake 1970-01-01 08:00:00.000000000 +0800 ++++ open-amp/cmake/platforms/uniproton_arm64_gcc.cmake 2023-02-20 14:24:50.000000000 +0800 +@@ -0,0 +1,14 @@ ++#cross-compilation config ++ ++set(CMAKE_SYSTEM_PROCESSOR arm) ++set(PROJECT_SYSTEM uniproton) ++ ++set(CMAKE_C_COMPILER_WORKS 1) ++set(CMAKE_CXX_COMPILER_WORKS 1) ++ ++set(CROSS_PREFIX "/opt/buildtools/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/aarch64-none-elf-" CACHE STRING "") ++set(CMAKE_C_COMPILER "${CROSS_PREFIX}gcc" CACHE STRING "") ++set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE STRING "") ++set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER CACHE STRING "") ++set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER CACHE STRING "") ++# vim: expandtab:ts=2:sw=2:smartindent +diff -uparN open-amp-2022.10.1/CMakeLists.txt open-amp/CMakeLists.txt +--- open-amp-2022.10.1/CMakeLists.txt 2022-12-13 11:21:05.000000000 +0800 ++++ open-amp/CMakeLists.txt 2023-02-24 16:27:30.000000000 +0800 +@@ -6,7 +6,8 @@ endif() + if (POLICY CMP0077) + cmake_policy(SET CMP0077 NEW) + endif() +- ++include_directories(../../build/libmetal/output/usr/local/include ../../component/open-amp/lib/include ../../include ../../config) ++set (CMAKE_SYSTEM_NAME Uniproton) + set (OPENAMP_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + set (OPENAMP_BIN_ROOT "${CMAKE_CURRENT_BINARY_DIR}") + +diff -uparN open-amp-2022.10.1/lib/remoteproc/rsc_table_parser.c open-amp/lib/remoteproc/rsc_table_parser.c +--- open-amp-2022.10.1/lib/remoteproc/rsc_table_parser.c 2022-12-13 11:21:05.000000000 +0800 ++++ open-amp/lib/remoteproc/rsc_table_parser.c 2023-02-24 16:16:20.000000000 +0800 +@@ -144,6 +144,8 @@ int handle_vdev_rsc(struct remoteproc *r + + num_vrings = vdev_rsc->num_of_vrings; + for (i = 0; i < num_vrings; i++) { ++ struct fw_rsc_vdev_vring *vring_rsc; ++ + vring_rsc = &vdev_rsc->vring[i]; + notifyid = vring_rsc->notifyid; + notifyid = remoteproc_allocate_id(rproc, +diff -uparN open-amp-2022.10.1/VERSION open-amp/VERSION +--- open-amp-2022.10.1/VERSION 2022-12-13 11:21:05.000000000 +0800 ++++ open-amp/VERSION 2023-02-24 15:51:04.000000000 +0800 +@@ -1,3 +1,3 @@ + VERSION_MAJOR = 1 + VERSION_MINOR = 3 +-VERSION_PATCH = 1 ++VERSION_PATCH = 0 diff --git a/demos/hi3093/config/CMakeLists.txt b/demos/hi3093/config/CMakeLists.txt new file mode 100644 index 0000000..ab9f478 --- /dev/null +++ b/demos/hi3093/config/CMakeLists.txt @@ -0,0 +1,2 @@ +set(SRCS prt_config.c) +add_library(config OBJECT ${SRCS}) diff --git a/demos/hi3093/config/prt_buildef.h b/demos/hi3093/config/prt_buildef.h new file mode 100644 index 0000000..4c354b7 --- /dev/null +++ b/demos/hi3093/config/prt_buildef.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: the common part buildef.h + */ +#ifndef PRT_BUILDEF_H +#define PRT_BUILDEF_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define OS_ARCH_ARMV8 + +#define OS_GIC_VER 3 + +#ifndef OS_HARDWARE_PLATFORM +#define OS_HARDWARE_PLATFORM OS_ARMV8 +#endif + +#ifndef OS_CPU_TYPE +#define OS_CPU_TYPE OS_HI3093 +#endif + +#define OS_MAX_CORE_NUM 4 + +#define OS_THIS_CORE 3 + +#ifndef OS_BYTE_ORDER +#define OS_BYTE_ORDER OS_LITTLE_ENDIAN +#endif + +#define OS_CACHE_LINE_SIZE 64 + +#define OS_OPTION_EVENT + +#define OS_OPTION_QUEUE + +#define OS_OPTION_HWI_PRIORITY + +#define OS_OPTION_HWI_ATTRIBUTE + +#define OS_OPTION_SYS_TIME_USR + +#define OS_OPTION_TASK + +#define OS_OPTION_TASK_DELETE + +#define OS_OPTION_TASK_SUSPEND + +#define OS_OPTION_TASK_INFO + +#define OS_OPTION_TASK_YIELD + +#define OS_TSK_PRIORITY_HIGHEST 0 + +#define OS_TSK_PRIORITY_LOWEST 63 + +#define OS_TSK_NUM_OF_PRIORITIES 64 + +#define OS_TSK_CORE_BYTES_IN_PID 2 + +#define OS_OPTION_TICK + +#define OS_OPTION_CPUP_WARN + +#define OS_OPTION_RND + +#define OS_OPTION_POSIX + +#define OS_POSIX_TYPE_NEWLIB + +#define OS_OPTION_OPENAMP + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +/* common macros's definitions */ +#include "prt_buildef_common.h" + +#endif diff --git a/demos/hi3093/config/prt_config.c b/demos/hi3093/config/prt_config.c new file mode 100644 index 0000000..2dbe9d7 --- /dev/null +++ b/demos/hi3093/config/prt_config.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton的初始化C文件。 + */ +#include "prt_config_internal.h" + +OS_SEC_ALW_INLINE INLINE void OsConfigAddrSizeGet(uintptr_t addr, uintptr_t size, + uintptr_t *destAddr, uintptr_t *destSize) +{ + *destAddr = addr; + *destSize = size; +} + +U32 OsMemConfigReg(void) +{ + U32 ret; + + ret = OsFscMemInit(OS_MEM_FSC_PT_ADDR, OS_MEM_FSC_PT_SIZE); + if (ret != OS_OK) { + return ret; + } + + return OS_OK; +} + +U32 OsMemDefPtInit(void) +{ + return OS_OK; +} + +U32 OsMemConfigInit(void) +{ + /* 系统默认FSC内存分区初始化 */ + return OsMemDefPtInit(); +} + +U32 OsSystemReg(void) +{ + struct SysModInfo sysModInfo; + + sysModInfo.systemClock = OS_SYS_CLOCK; + sysModInfo.cpuType = OS_CPU_TYPE; + sysModInfo.sysTimeHook = OS_SYS_TIME_HOOK; +#if defined(OS_OPTION_HWI_MAX_NUM_CONFIG) + sysModInfo.hwiMaxNum = OS_HWI_MAX_NUM_CONFIG; +#endif + + return OsSysRegister(&sysModInfo); +} + +#if (OS_INCLUDE_SEM == YES) +U32 OsSemConfigReg(void) +{ + struct SemModInfo semModInfo; + + semModInfo.maxNum = OS_SEM_MAX_SUPPORT_NUM; + return OsSemRegister(&semModInfo); + +} +#endif + +#if (OS_INCLUDE_TASK == YES) +void OsTaskInfoSet(struct TskModInfo *taskModInfo) +{ + taskModInfo->maxNum = OS_TSK_MAX_SUPPORT_NUM; + taskModInfo->defaultSize = OS_TSK_DEFAULT_STACK_SIZE; + taskModInfo->idleStackSize = OS_TSK_IDLE_STACK_SIZE; + taskModInfo->magicWord = WORD_PACK((U32)OS_TSK_STACK_MAGIC_WORD); +} +#else +#error "OS_INCLUDE_TASK MUST BE YES! The SWI has been cut out,the task can not cut out." +#endif + +U32 OsHookConfigReg(void) +{ + struct HookModInfo hookModInfo; + + hookModInfo.maxNum[OS_HOOK_HWI_ENTRY] = OS_HOOK_HWI_ENTRY_NUM; + hookModInfo.maxNum[OS_HOOK_HWI_EXIT] = OS_HOOK_HWI_EXIT_NUM; + hookModInfo.maxNum[OS_HOOK_TSK_SWITCH] = OS_HOOK_TSK_SWITCH_NUM; + hookModInfo.maxNum[OS_HOOK_IDLE_PERIOD] = OS_HOOK_IDLE_NUM; + + return OsHookRegister(&hookModInfo); +} + +U32 OsSysConfigReg(void) +{ + U32 ret; + + ret = OsSystemReg(); + if (ret != OS_OK) { + return ret; + } + return OS_OK; +} + +#if (OS_INCLUDE_TICK == YES) +U32 OsTickConfigReg(void) +{ + struct TickModInfo tickModInfo; + + tickModInfo.tickPerSecond = OS_TICK_PER_SECOND; + tickModInfo.tickPriority = 0; + + return OsTickRegister(&tickModInfo); +} +#endif + +#if (OS_INCLUDE_TASK == YES) +U32 OsTskConfigReg(void) +{ + struct TskModInfo taskModInfo; + OsTaskInfoSet(&taskModInfo); + return OsTskRegister(&taskModInfo); +} +#endif + +#if (OS_INCLUDE_QUEUE == YES) +U32 OsQueueConfigReg(void) +{ + return OsQueueRegister(OS_QUEUE_MAX_SUPPORT_NUM); +} +#endif + +#if (OS_INCLUDE_CPUP == YES) +U32 OsCpupConfigReg(void) +{ + struct CpupModInfo cpupModInfo; + + cpupModInfo.cpupWarnFlag = (bool)OS_CONFIG_CPUP_WARN; + cpupModInfo.sampleTime = OS_CPUP_SAMPLE_INTERVAL; + cpupModInfo.warn = OS_CPUP_SHORT_WARN; + cpupModInfo.resume = OS_CPUP_SHORT_RESUME; + + return OsCpupRegister(&cpupModInfo); +} +#endif + +#if (OS_INCLUDE_TICK_SWTMER == YES) +U32 OsSwTmrConfigInit(void) +{ + return OsSwTmrInit(OS_TICK_SWITIMER_MAX_NUM); +} +#endif + +#if (OS_INCLUDE_CPUP == YES) +#if (OS_INCLUDE_TICK == NO) +#error "OS_INCLUDE_CPUP depend on OS_INCLUDE_TICK!" +#endif +U32 OsCpupConfigInit(void) +{ + U32 ret; + + ret = OsCpupInit(); + if (ret != OS_OK) { + return ret; + } + + if (OS_CONFIG_CPUP_WARN == YES) { +#if defined(OS_OPTION_CPUP_WARN) + OsCpupWarnInit(); +#else + return OS_ERRNO_SYS_NO_CPUP_WARN; +#endif + } + return OS_OK; +} +#endif + +#if (OS_INCLUDE_SEM == YES) +U32 OsSemConfigInit(void) +{ + return OsSemInit(); +} +#endif + +#if (OS_INCLUDE_TASK == YES) +U32 OsTskConfigInit(void) +{ + return OsTskInit(); +} +#endif + +static U32 OsHwiConfigReg(void) +{ +#if (OS_INCLUDE_GIC_BASE_ADDR_CONFIG == YES) + U32 ret; + ret = OsGicConfigRegister((uintptr_t)OS_GIC_BASE_ADDR, (uintptr_t)OS_GICR_OFFSET, (uintptr_t)OS_GICR_STRIDE); + if (ret != OS_OK) { + return ret; + } +#endif + return OS_OK; +} + +/* 系统初始化注册表 */ +struct OsModuleConfigInfo g_moduleConfigTab[] = { + /* {模块号, 模块注册函数, 模块初始化函数} */ + {OS_MID_SYS, {OsSysConfigReg, NULL}}, + {OS_MID_MEM, {OsMemConfigReg, OsMemConfigInit}}, + {OS_MID_HWI, {OsHwiConfigReg, OsHwiConfigInit}}, + {OS_MID_HARDDRV, {NULL, PRT_HardDrvInit}}, + {OS_MID_HOOK, {OsHookConfigReg, OsHookConfigInit}}, + {OS_MID_EXC, {NULL, OsExcConfigInit}}, +#if (OS_INCLUDE_TASK == YES) + {OS_MID_TSK, {OsTskConfigReg, OsTskConfigInit}}, +#endif +#if (OS_INCLUDE_TICK == YES) + {OS_MID_TICK, {OsTickConfigReg, OsTickConfigInit}}, +#endif + +#if (OS_INCLUDE_TICK_SWTMER == YES) + {OS_MID_SWTMR, {NULL, OsSwTmrConfigInit}}, +#endif + +#if (OS_INCLUDE_CPUP == YES) + {OS_MID_CPUP, {OsCpupConfigReg, OsCpupConfigInit}}, +#endif +#if (OS_INCLUDE_SEM == YES) + {OS_MID_SEM, {OsSemConfigReg, OsSemConfigInit}}, +#endif +#if (OS_INCLUDE_QUEUE == YES) + {OS_MID_QUEUE, {OsQueueConfigReg, OsQueueConfigInit}}, +#endif + {OS_MID_APP, {NULL, PRT_AppInit}}, + + {OS_MID_BUTT, {NULL, NULL}}, +}; + +/* + * 描述:OS模块注册、初始化运行函数 + */ +U32 OsModuleConfigRun(enum OsinitPhaseId initPhaseId, U32 initPhase) +{ + U32 idx = 0; + U32 ret = OS_OK; + while (g_moduleConfigTab[idx].moudleId != OS_MID_BUTT) { + if (g_moduleConfigTab[idx].moudleConfigFunc[initPhaseId] == NULL) { + idx++; + continue; + } + ret = g_moduleConfigTab[idx].moudleConfigFunc[initPhaseId](); + if (ret != OS_OK) { + break; + } + idx++; + } + return ret; +} +U32 OsRegister(void) +{ + return OsModuleConfigRun(OS_REGISTER_ID, OS_REGISTER_PHASE); +} + +/* + * 描述:OsInitialize阶段 + */ +U32 OsInitialize(void) +{ + return OsModuleConfigRun(OS_INIT_ID, OS_INITIALIZE_PHASE); +} + +/* + * 描述:OsStart阶段 + */ +U32 OsStart(void) +{ + U32 ret; + +#if (OS_INCLUDE_TICK == YES) + /* 表示系统在进行启动阶段,匹配MOUDLE_ID之后,标记进入TICK模块的启动 */ + ret = OsTickStart(); + if (ret != OS_OK) { + return ret; + } +#endif + +#if (OS_INCLUDE_TASK == YES) + /* 表示系统在进行启动阶段,匹配MOUDLE_ID之后,标记进入任务模块的启动 */ + ret = OsActivate(); +#else + ret = OS_OK; +#endif + + return ret; +} + +S32 OsConfigStart(void) +{ + U32 ret; + + OsHwInit(); + + /* OS模块注册 */ + ret = OsRegister(); + if (ret != OS_OK) { + return (S32)ret; + } + + /* OS模块初始化 */ + ret = OsInitialize(); + if (ret != OS_OK) { + return (S32)ret; + } + + /* OS启动调度 */ + ret = OsStart(); + if (ret != OS_OK) { + return (S32)ret; + } + + /* Execution should not reach this point */ + return (S32)OS_ERROR; +} diff --git a/demos/hi3093/config/prt_config.h b/demos/hi3093/config/prt_config.h new file mode 100644 index 0000000..831b73d --- /dev/null +++ b/demos/hi3093/config/prt_config.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton配置头文件,裁剪开关和配置项。 + */ +#ifndef PRT_CONFIG_H +#define PRT_CONFIG_H + +#include "prt_buildef.h" +#include "prt_typedef.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/* ***************************** 配置系统基本信息 ******************************* */ +/* 芯片主频 */ +#define OS_SYS_CLOCK 250000000 +/* 用户注册的获取系统时间的函数*/ +#define OS_SYS_TIME_HOOK NULL + +/* ***************************** 中断模块配置 ************************** */ +/* 硬中断最大支持个数 */ +#define OS_HWI_MAX_NUM_CONFIG 150 + +/* ***************************** 配置Tick中断模块 *************************** */ +/* Tick中断模块裁剪开关 */ +#define OS_INCLUDE_TICK YES +/* Tick中断时间间隔,tick处理时间不能超过1/OS_TICK_PER_SECOND(s) */ +#define OS_TICK_PER_SECOND 1000 + +/* ***************************** 配置定时器模块 ***************************** */ +/* 基于TICK的软件定时器裁剪开关 */ +#define OS_INCLUDE_TICK_SWTMER NO +/* 基于TICK的软件定时器最大个数 */ +#define OS_TICK_SWITIMER_MAX_NUM 32 + +/* ***************************** 配置任务模块 ******************************* */ +/* 任务模块裁剪开关 */ +#define OS_INCLUDE_TASK YES +/* 最大支持的任务数,最大共支持254个 */ +#define OS_TSK_MAX_SUPPORT_NUM 8 +/* 缺省的任务栈大小 */ +#define OS_TSK_DEFAULT_STACK_SIZE 0x1000 +/* IDLE任务栈的大小 */ +#define OS_TSK_IDLE_STACK_SIZE 0x1000 +/* 任务栈初始化魔术字,默认是0xCA,只支持配置一个字节 */ +#define OS_TSK_STACK_MAGIC_WORD 0xCA + +/* ***************************** 配置CPU占用率及CPU告警模块 **************** */ +/* CPU占用率模块裁剪开关 */ +#define OS_INCLUDE_CPUP NO +/* 采样时间间隔(单位tick),若其值大于0,则作为采样周期,否则两次调用PRT_CpupNow或PRT_CpupThread间隔作为周期 */ +#define OS_CPUP_SAMPLE_INTERVAL 10 +/* CPU占用率告警动态配置项 */ +#define OS_CONFIG_CPUP_WARN NO +/* CPU占用率告警阈值(精度为万分比) */ +#define OS_CPUP_SHORT_WARN 8500 +/* CPU占用率告警恢复阈值(精度为万分比) */ +#define OS_CPUP_SHORT_RESUME 7500 + +/* ***************************** 配置内存管理模块 ************************** */ +/* 用户可以创建的最大分区数,取值范围[0,253] */ +#define OS_MEM_MAX_PT_NUM 200 +/* 私有FSC内存分区起始地址 */ +#define OS_MEM_FSC_PT_ADDR (uintptr_t)&g_memRegion00[0] +/* 私有FSC内存分区大小 */ +#define OS_MEM_FSC_PT_SIZE 0x80000 + +/* ***************************** 配置信号量管理模块 ************************* */ +/* 信号量模块裁剪开关 */ +#define OS_INCLUDE_SEM YES + +/* 最大支持的信号量数 */ +#define OS_SEM_MAX_SUPPORT_NUM 10 + +/* ***************************** 配置队列模块 ******************************* */ +/* 队列模块裁剪开关 */ +#define OS_INCLUDE_QUEUE YES +/* 最大支持的队列数,范围(0,0xFFFF] */ +#define OS_QUEUE_MAX_SUPPORT_NUM 10 + +/* ************************* 钩子模块配置 *********************************** */ +/* 硬中断进入钩子最大支持个数, 范围[0, 255] */ +#define OS_HOOK_HWI_ENTRY_NUM 5 +/* 硬中断退出钩子最大支持个数, 范围[0, 255] */ +#define OS_HOOK_HWI_EXIT_NUM 5 +/* 任务切换钩子最大支持个数, 范围[0, 255] */ +#define OS_HOOK_TSK_SWITCH_NUM 8 +/* IDLE钩子最大支持个数, 范围[0, 255] */ +#define OS_HOOK_IDLE_NUM 4 + +/* ************************* GIC模块配置 *********************************** */ +/* GIC地址可配置开关 */ +#define OS_INCLUDE_GIC_BASE_ADDR_CONFIG YES +/* GIC基地址配置 */ +#define OS_GIC_BASE_ADDR 0x24000000U +/* GICR相对于GIC基地址偏移量配置 */ +#define OS_GICR_OFFSET 0x40000U +/* GICR核间偏移量配置 */ +#define OS_GICR_STRIDE 0x20000U + +extern U8 g_memRegion00[]; + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +#endif /* PRT_CONFIG_H */ diff --git a/demos/hi3093/config/prt_config_internal.h b/demos/hi3093/config/prt_config_internal.h new file mode 100644 index 0000000..e62b9d4 --- /dev/null +++ b/demos/hi3093/config/prt_config_internal.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton配置私有文件。 + */ +#ifndef PRT_CONFIG_INTERNAL_H +#define PRT_CONFIG_INTERNAL_H + +#include +#include "prt_config.h" +#include "prt_sys.h" +#include "prt_task.h" +#include "prt_sem.h" +#include "prt_tick.h" +#include "prt_exc.h" +#include "prt_cpup.h" +#include "prt_mem.h" +#include "prt_hook.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +#define WORD_PACK(val) (((val) << 24) | ((val) << 16) | ((val) << 8) | (val)) + +/* UniProton模块注册函数的声明 */ +extern U32 OsFscMemInit(U32 addr, U32 size); +extern U32 OsSysRegister(struct SysModInfo *modInfo); +extern U32 OsTickRegister(struct TickModInfo *modInfo); +extern U32 OsTskRegister(struct TskModInfo *modInfo); +extern U32 OsCpupRegister(struct CpupModInfo *modInfo); +extern U32 OsSemRegister(const struct SemModInfo *modInfo); +extern U32 OsHookRegister(struct HookModInfo *modInfo); + +extern U32 OsHwiConfigInit(void); +extern U32 OsTickConfigInit(void); +extern U32 OsTskInit(void); +extern U32 OsCpupInit(void); +extern void OsCpupWarnInit(void); +extern U32 OsExcConfigInit(void); +extern U32 OsSemInit(void); +extern U32 OsHookConfigInit(void); + +/* UniProton系统启动相关函数的声明 */ +extern void OsHwInit(void); +extern U32 OsActivate(void); +extern U32 OsTickStart(void); +extern U32 PRT_HardDrvInit(void); +extern void PRT_HardBootInit(void); +extern U32 PRT_AppInit(void); + +extern U32 OsQueueRegister(U16 maxQueue); +extern U32 OsQueueConfigInit(void); + +#if (OS_INCLUDE_TICK_SWTMER == YES) +extern U32 OsSwTmrInit(U32 maxTimerNum); +#endif + +enum OsinitPhaseId { + OS_REGISTER_ID = 0, + OS_INIT_ID, + OS_MOUDLE_CONFIG +}; +typedef U32 (*ConfigInitFunc)(void); +struct OsModuleConfigInfo { + enum MoudleId moudleId; + ConfigInitFunc moudleConfigFunc[OS_MOUDLE_CONFIG]; +}; +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +#endif /* PRT_CONFIG_INTERNAL_H */ diff --git a/demos/hi3093/include/.keep b/demos/hi3093/include/.keep new file mode 100644 index 0000000..74b2a0f --- /dev/null +++ b/demos/hi3093/include/.keep @@ -0,0 +1,10 @@ +# Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. +# +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. \ No newline at end of file diff --git a/demos/hi3093/libs/.keep b/demos/hi3093/libs/.keep new file mode 100644 index 0000000..74b2a0f --- /dev/null +++ b/demos/hi3093/libs/.keep @@ -0,0 +1,10 @@ +# Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. +# +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. \ No newline at end of file diff --git a/demos/hi3093/readme.txt b/demos/hi3093/readme.txt new file mode 100644 index 0000000..82d81b9 --- /dev/null +++ b/demos/hi3093/readme.txt @@ -0,0 +1,10 @@ +本目录下放置的是UniProton实时部分版本。 + +├─apps # 基于UniProton实时OS编程的demo程序; +│ └─openamp # openamp示例程序; +├─bsp # 提供的板级驱动与OS对接; +├─build # 提供编译脚本编译出最终镜像; +├─component # 适配openamp框架patch文件,openamp源码下载存放路径; +├─config # 配置选项,供用户调整运行时参数; +├─include # UniProton实时部分提供的编程接口API; +└─libs # UniProton实时部分的静态库,build目录中的makefile示例已经将头文件和静态库的引用准备好,应用可直接使用; diff --git a/demos/raspi4/CMakeLists.txt b/demos/raspi4/CMakeLists.txt new file mode 100644 index 0000000..0b59ffb --- /dev/null +++ b/demos/raspi4/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 3.12) +project(exmaples LANGUAGES C ASM) + +set(CMAKE_C_COMPILER ${TOOLCHAIN_PATH}/bin/aarch64-none-elf-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PATH}/bin/aarch64-none-elf-g++) +set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PATH}/bin/aarch64-none-elf-gcc) +set(CMAKE_LINKER ${TOOLCHAIN_PATH}/bin/aarch64-none-elf-ld) + +set(POSIX_OPTION "-D_POSIX_THREADS -D_POSIX_THREAD_PRIORITY_SCHEDULING -D_POSIX_PRIORITY_SCHEDULING -D_POSIX_TIMERS -D_POSIX_CPUTIME -D_POSIX_THREAD_CPUTIME -D_POSIX_MONOTONIC_CLOCK -D_POSIX_TIMEOUTS -D_POSIX_CLOCK_SELECTION -D_POSIX_THREAD_PRIO_PROTECT -D_UNIX98_THREAD_MUTEX_ATTRIBUTES -D_POSIX_READER_WRITER_LOCKS") +set(CC_OPTION "-g -march=armv8.2-a+nofp+nosimd -Wl,--build-id=none -fno-builtin -fno-PIE -Wall -fno-dwarf2-cfi-asm -O0 -mcmodel=large -fomit-frame-pointer -fzero-initialized-in-bss -fdollars-in-identifiers -ffunction-sections -fdata-sections -fno-common -fno-aggressive-loop-optimizations -fno-optimize-strlen -fno-schedule-insns -fno-inline-small-functions -fno-inline-functions-called-once -fno-strict-aliasing -fno-builtin -finline-limit=20 -mstrict-align -mlittle-endian -specs=nosys.specs -nostartfiles -funwind-tables") +set(AS_OPTION "-g -march=armv8.2-a+nofp+nosimd -Wl,--build-id=none -fno-builtin -fno-PIE -Wall -fno-dwarf2-cfi-asm -O0 -mcmodel=large -fomit-frame-pointer -fzero-initialized-in-bss -fdollars-in-identifiers -ffunction-sections -fdata-sections -fno-common -fno-aggressive-loop-optimizations -fno-optimize-strlen -fno-schedule-insns -fno-inline-small-functions -fno-inline-functions-called-once -fno-strict-aliasing -fno-builtin -finline-limit=20 -mstrict-align -mlittle-endian -nostartfiles -mgeneral-regs-only -DENV_EL1") +set(LD_OPTION "-static -no-pie -Wl,--wrap=memset -Wl,--wrap=memcpy") +set(CMAKE_C_FLAGS "${CC_OPTION} ${POSIX_OPTION}") +set(CMAKE_ASM_FLAGS "${AS_OPTION} ${POSIX_OPTION}") +set(CMAKE_LINK_FLAGS "${LD_OPTION} -T ../raspi4.ld") +set(CMAKE_EXE_LINKER_FLAGS "${LD_OPTION} -T ../raspi4.ld") + +include_directories( + ./include + ./config + ./bsp + ./bsp/raspi4 + ./apps/openamp + ./build/open-amp/output/usr/local/include + ./build/libmetal/output/usr/local/include +) + +link_directories(./libs) +link_libraries( + -Wl,--start-group + "${CMAKE_CURRENT_SOURCE_DIR}/libs/libCortexMXsec_c.lib" + "${CMAKE_CURRENT_SOURCE_DIR}/libs/libRASPI4.a" + "${CMAKE_CURRENT_SOURCE_DIR}/libs/libmetal.a" + "${CMAKE_CURRENT_SOURCE_DIR}/libs/libopen_amp.a" + -Wl,--end-group +) + +add_subdirectory(bsp) +add_subdirectory(config) +add_subdirectory(apps) + +list(APPEND OBJS $ $ $) +add_executable(${APP} ${OBJS}) diff --git a/demos/raspi4/apps/CMakeLists.txt b/demos/raspi4/apps/CMakeLists.txt new file mode 100644 index 0000000..e9ada4d --- /dev/null +++ b/demos/raspi4/apps/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(openamp) diff --git a/demos/raspi4/apps/openamp/CMakeLists.txt b/demos/raspi4/apps/openamp/CMakeLists.txt new file mode 100644 index 0000000..e56098a --- /dev/null +++ b/demos/raspi4/apps/openamp/CMakeLists.txt @@ -0,0 +1,2 @@ +set(SRC rpmsg_backend.c rpmsg_service.c main.c) +add_library(rpmsg OBJECT ${SRC}) diff --git a/demos/raspi4/apps/openamp/main.c b/demos/raspi4/apps/openamp/main.c new file mode 100644 index 0000000..bb7ba7b --- /dev/null +++ b/demos/raspi4/apps/openamp/main.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton raspi4 demo + */ +#include +#include +#include +#include +#include "securec.h" +#include "prt_config.h" +#include "prt_config_internal.h" +#include "prt_task.h" +#include "test.h" + +TskHandle g_testTskHandle; +U8 g_memRegion00[OS_MEM_FSC_PT_SIZE]; + +#if defined(OS_OPTION_OPENAMP) +int TestOpenamp() +{ + int ret; + + ret = rpmsg_service_init(); + if (ret) { + return ret; + } + + return OS_OK; +} +#endif + +void TestTaskEntry() +{ +#if defined(OS_OPTION_OPENAMP) + TestOpenamp(); +#endif +} + +U32 OsTestInit(void) +{ + U32 ret; + U8 ptNo = OS_MEM_DEFAULT_FSC_PT; + struct TskInitParam param = {0}; + + param.stackAddr = (U32)PRT_MemAllocAlign(0, ptNo, 0x2000, MEM_ADDR_ALIGN_016); + param.taskEntry = (TskEntryFunc)TestTaskEntry; + param.taskPrio = 25; + param.name = "TestTask"; + param.stackSize = 0x2000; + + ret = PRT_TaskCreate(&g_testTskHandle, ¶m); + if (ret) { + return ret; + } + + ret = PRT_TaskResume(g_testTskHandle); + if (ret) { + return ret; + } + + return OS_OK; +} + +U32 PRT_AppInit(void) +{ + U32 ret; + + ret = OsTestInit(); + if (ret) { + return ret; + } + + ret = TestClkStart(); + if (ret) { + return ret; + } + + return OS_OK; +} + +U32 PRT_HardDrvInit(void) +{ + U32 ret; + + ret = OsHwiInit(); + if (ret) { + return ret; + } + + return OS_OK; +} + +void PRT_HardBootInit(void) +{ +} + +S32 main(void) +{ + return OsConfigStart(); +} + +extern void *__wrap_memset(void *dest, int set, U32 len) +{ + if (dest == NULL || len == 0) { + return NULL; + } + + char *ret = (char *)dest; + for (int i = 0; i < len; ++i) { + ret[i] = set; + } + return ret; +} + +extern void *__wrap_memcpy(void *dest, const void *src, size_t size) +{ + for (size_t i = 0; i < size; ++i) { + *(char *)(dest + i) = *(char *)(src + i); + } +} + diff --git a/demos/raspi4/apps/openamp/openamp_common.h b/demos/raspi4/apps/openamp/openamp_common.h new file mode 100644 index 0000000..ebbdc5c --- /dev/null +++ b/demos/raspi4/apps/openamp/openamp_common.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * See the Mulan PSL v2 for more details. + * Create: 2022-12-05 + * Description: openamp configuration + */ + +#ifndef COMMON_H__ +#define COMMON_H__ + +#include "cpu_config.h" +#include "test.h" + +#define VDEV_START_ADDR MMU_OPENAMP_ADDR +#define VDEV_SIZE 0x30000 + +#define VDEV_STATUS_ADDR VDEV_START_ADDR +#define VDEV_STATUS_SIZE 0x4000 + +#define SHM_START_ADDR (VDEV_START_ADDR + VDEV_STATUS_SIZE) +#define SHM_SIZE (VDEV_SIZE - VDEV_STATUS_SIZE) +#define SHM_DEVICE_NAME "lonely_device" + +#define VRING_COUNT 2 +#define VRING_RX_ADDRESS (VDEV_START_ADDR + SHM_SIZE - VDEV_STATUS_SIZE) +#define VRING_TX_ADDRESS (VDEV_START_ADDR + SHM_SIZE) +#define VRING_ALIGNMENT 4 +#define VRING_SIZE 16 + +#define CONFIG_RPMSG_SERVICE_NUM_ENDPOINTS 1 + +#define DEFAULT_PAGE_SHIFT 0xffffffffffffffffULL +#define DEFAULT_PAGE_MASK 0xffffffffffffffffULL + +#define VIRTQUEUE_ID 1 +#define RPMSG_ROLE RPMSG_REMOTE + +#define OS_OPENAMP_NOTIFY_HWI_NUM OS_HWI_IPI_NO_07 +#define OS_OPENAMP_NOTIFY_HWI_PRIO 0 + +#define BIT(n) (1 << (n)) + +OS_SEC_ALW_INLINE INLINE void sys_write32(uint32_t data, uintptr_t addr) +{ + __asm__ volatile ("dmb sy" : : : "memory"); + __asm__ volatile ("str %w0, [%1]" : : "r" (data), "r" (addr)); +} + +OS_SEC_ALW_INLINE INLINE uint32_t sys_read32(uintptr_t addr) +{ + uint32_t val; + __asm__ volatile ("ldr %w0, [%1]" : "=r" (val) : "r" (addr)); + __asm__ volatile ("dmb sy" : : : "memory"); + return val; +} + +OS_SEC_ALW_INLINE INLINE void sys_write8(uint8_t data, uintptr_t addr) +{ + __asm__ volatile ("dmb sy" : : : "memory"); + __asm__ volatile ("strb %w0, [%1]" : : "r" (data), "r" (addr)); +} + +OS_SEC_ALW_INLINE INLINE uint8_t sys_read8(uintptr_t addr) +{ + uint8_t val; + __asm__ volatile ("ldrb %w0, [%1]" : "=r" (val) : "r" (addr)); + __asm__ volatile ("dmb sy" : : : "memory"); + return val; +} + +#endif diff --git a/demos/raspi4/apps/openamp/rpmsg_backend.c b/demos/raspi4/apps/openamp/rpmsg_backend.c new file mode 100644 index 0000000..918f146 --- /dev/null +++ b/demos/raspi4/apps/openamp/rpmsg_backend.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * See the Mulan PSL v2 for more details. + * Create: 2022-12-05 + * Description: openamp backend + */ + +#include "rpmsg_backend.h" +#include "metal/device.h" +#include "prt_hwi.h" + +static metal_phys_addr_t shm_physmap[] = { SHM_START_ADDR }; +static struct metal_device shm_device = { + .name = SHM_DEVICE_NAME, + .bus = NULL, + .num_regions = 1, + { + { + .virt = (void *) SHM_START_ADDR, + .physmap = shm_physmap, + .size = SHM_SIZE, + .page_shift = DEFAULT_PAGE_SHIFT, + .page_mask = DEFAULT_PAGE_MASK, + .mem_flags = 0, + .ops = { NULL }, + }, + }, + .node = { NULL }, + .irq_num = 0, + .irq_info = NULL +}; + +static struct virtio_vring_info rvrings[2] = { + [0] = { + .info.align = VRING_ALIGNMENT, + }, + [1] = { + .info.align = VRING_ALIGNMENT, + }, +}; + +static struct virtqueue *vq[2]; + +static unsigned char virtio_get_status(struct virtio_device *vdev) +{ + return sys_read8(VDEV_STATUS_ADDR); +} + +static void virtio_set_status(struct virtio_device *vdev, unsigned char status) +{ + sys_write8(status, VDEV_STATUS_ADDR); +} + +static uint32_t virtio_get_features(struct virtio_device *vdev) +{ + return BIT(VIRTIO_RPMSG_F_NS); +} + +static void virtio_set_features(struct virtio_device *vdev, uint32_t features) +{ +} + +static void virtio_notify(struct virtqueue *vq) +{ + uint16_t coreMask = 1; + OsHwiMcTrigger(coreMask, OS_HWI_IPI_NO_07); +} + +const struct virtio_dispatch dispatch = { + .get_status = virtio_get_status, + .set_status = virtio_set_status, + .get_features = virtio_get_features, + .set_features = virtio_set_features, + .notify = virtio_notify, +}; + +static void rpmsg_hwi_handler(void) +{ + virtqueue_notification(vq[VIRTQUEUE_ID]); +} + +static U32 rpmsg_hwi_init(void) +{ + U32 ret; + + ret = PRT_HwiSetAttr(OS_OPENAMP_NOTIFY_HWI_NUM, OS_OPENAMP_NOTIFY_HWI_PRIO, OS_HWI_MODE_ENGROSS); + if (ret != OS_OK) { + return ret; + } + + ret = PRT_HwiCreate(OS_OPENAMP_NOTIFY_HWI_NUM, (HwiProcFunc)rpmsg_hwi_handler, 0); + if (ret != OS_OK) { + return ret; + } + +#if (OS_GIC_VER == 3) + ret = PRT_HwiEnable(OS_OPENAMP_NOTIFY_HWI_NUM); + if (ret != OS_OK) { + return ret; + } +#endif + + return OS_OK; +} + +int rpmsg_backend_init(struct metal_io_region **io, struct virtio_device *vdev) +{ + int32_t err; + struct metal_init_params metal_params = METAL_INIT_DEFAULTS; + struct metal_device *device; + + err = rpmsg_hwi_init(); + if (err) { + return err; + } + + /* Libmetal setup */ + err = metal_init(&metal_params); + if (err) { + return err; + } + + err = metal_register_generic_device(&shm_device); + if (err) { + return err; + } + + err = metal_device_open("generic", SHM_DEVICE_NAME, &device); + if (err) { + return err; + } + + *io = metal_device_io_region(device, 0); + if (!*io) { + return err; + } + + /* Virtqueue setup */ + vq[0] = virtqueue_allocate(VRING_SIZE); + if (!vq[0]) { + return -ENOMEM; + } + + vq[1] = virtqueue_allocate(VRING_SIZE); + if (!vq[1]) { + return -ENOMEM; + } + + rvrings[0].io = *io; + rvrings[0].info.vaddr = (void *)VRING_TX_ADDRESS; + rvrings[0].info.num_descs = VRING_SIZE; + rvrings[0].info.align = VRING_ALIGNMENT; + rvrings[0].vq = vq[0]; + + rvrings[1].io = *io; + rvrings[1].info.vaddr = (void *)VRING_RX_ADDRESS; + rvrings[1].info.num_descs = VRING_SIZE; + rvrings[1].info.align = VRING_ALIGNMENT; + rvrings[1].vq = vq[1]; + + vdev->role = RPMSG_ROLE; + vdev->vrings_num = VRING_COUNT; + vdev->func = &dispatch; + vdev->vrings_info = &rvrings[0]; + + return 0; +} diff --git a/demos/raspi4/apps/openamp/rpmsg_backend.h b/demos/raspi4/apps/openamp/rpmsg_backend.h new file mode 100644 index 0000000..1b738f4 --- /dev/null +++ b/demos/raspi4/apps/openamp/rpmsg_backend.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * See the Mulan PSL v2 for more details. + * Create: 2022-12-05 + * Description: openamp backend + */ + +#include "openamp/open_amp.h" +#include "openamp_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rpmsg_service_init(void); + +/* + * @brief Initialize RPMsg backend + * + * @param io Shared memory IO region. This is an output parameter providing + * a pointer to an actual shared memory IO region structure. + * Caller of this function shall pass an address at which the + * pointer to the shared memory IO region structure is stored. + * @param vdev Pointer to the virtio device initialized by this function. + * + * @retval 0 Initialization successful + * @retval <0 Initialization error reported by OpenAMP + */ +extern int rpmsg_backend_init(struct metal_io_region **io, struct virtio_device *vdev); + +#ifdef __cplusplus +} +#endif diff --git a/demos/raspi4/apps/openamp/rpmsg_service.c b/demos/raspi4/apps/openamp/rpmsg_service.c new file mode 100644 index 0000000..673e02f --- /dev/null +++ b/demos/raspi4/apps/openamp/rpmsg_service.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * See the Mulan PSL v2 for more details. + * Create: 2022-12-05 + * Description: openamp configuration + */ + +#include "rpmsg_backend.h" + +static struct virtio_device vdev; +static struct rpmsg_virtio_device rvdev; +static struct metal_io_region *io; +struct rpmsg_device *g_rdev; +struct rpmsg_endpoint g_ept; +U32 g_receivedMsg; +bool g_openampFlag = false; +#define RPMSG_ENDPOINT_NAME "console" + +void rpmsg_service_unbind(struct rpmsg_endpoint *ep) +{ + rpmsg_destroy_ept(ep); +} + +int send_message(unsigned char *message, int len) +{ + return rpmsg_send(&g_ept, message, len); +} + +char *g_s1 = "Hello, UniProton! \r\n"; +int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv) +{ + g_openampFlag = true; + send_message((void *)g_s1, strlen(g_s1) * sizeof(char)); + + return OS_OK; +} + +int openamp_init(void) +{ + int32_t err; + + err = rpmsg_backend_init(&io, &vdev); + if (err) { + return err; + } + + err = rpmsg_init_vdev(&rvdev, &vdev, NULL, io, NULL); + if (err) { + return err; + } + + g_rdev = rpmsg_virtio_get_rpmsg_device(&rvdev); + + + err = rpmsg_create_ept(&g_ept, g_rdev, RPMSG_ENDPOINT_NAME, + 0xF, RPMSG_ADDR_ANY, + rpmsg_endpoint_cb, rpmsg_service_unbind); + if (err) { + return err; + } + + return OS_OK; +} + +void openamp_deinit(void) +{ + rpmsg_deinit_vdev(&rvdev); + if (io) { + free(io); + } +} + +int rpmsg_service_init(void) +{ + int32_t err; + err = openamp_init(); + if (err) { + return err; + } + + send_message((void *)&g_receivedMsg, sizeof(U32)); + + while (!g_openampFlag); + + return OS_OK; +} diff --git a/demos/raspi4/apps/openamp/test.h b/demos/raspi4/apps/openamp/test.h new file mode 100644 index 0000000..67089be --- /dev/null +++ b/demos/raspi4/apps/openamp/test.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton raspi4 demo + */ +#include "prt_config.h" +#include "prt_task.h" +#include "prt_hwi.h" +#include "prt_hook.h" +#include "prt_exc.h" +#include "prt_mem.h" + +extern U32 PRT_Printf(const char *format, ...); diff --git a/demos/raspi4/apps/readme.txt b/demos/raspi4/apps/readme.txt new file mode 100644 index 0000000..8f30d23 --- /dev/null +++ b/demos/raspi4/apps/readme.txt @@ -0,0 +1 @@ +请您参考example目录添加您的源代码,制作您的工程。如有疑问请联系华为对接工程师。 diff --git a/demos/raspi4/bsp/CMakeLists.txt b/demos/raspi4/bsp/CMakeLists.txt new file mode 100644 index 0000000..c134b13 --- /dev/null +++ b/demos/raspi4/bsp/CMakeLists.txt @@ -0,0 +1,2 @@ +set(SRCS start.S cache_asm.S hwi_init.c mmu.c print.c timer.c) +add_library(bsp OBJECT ${SRCS}) diff --git a/demos/raspi4/bsp/cache_asm.S b/demos/raspi4/bsp/cache_asm.S new file mode 100644 index 0000000..5f2f301 --- /dev/null +++ b/demos/raspi4/bsp/cache_asm.S @@ -0,0 +1,103 @@ +@/* +@ * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. +@ * +@ * UniProton is licensed under Mulan PSL v2. +@ * You can use this software according to the terms and conditions of the Mulan PSL v2. +@ * You may obtain a copy of Mulan PSL v2 at: +@ * http://license.coscl.org.cn/MulanPSL2 +@ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +@ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +@ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +@ * See the Mulan PSL v2 for more details. +@ * Create: 2009-12-22 +@ * Description: thread scheduler +@ */ +.global os_asm_invalidate_dcache_all +.global os_asm_invalidate_icache_all +.global os_asm_invalidate_tlb_all + + .type os_asm_dcache_level, "function" +os_asm_dcache_level: + lsl x12, x0, #1 + msr csselr_el1, x12 + isb + mrs x6, ccsidr_el1 + and x2, x6, #7 + add x2, x2, #4 + mov x3, #0x3ff + and x3, x3, x6, lsr #3 + clz w5, w3 + mov x4, #0x7fff + and x4, x4, x6, lsr #13 + +loop_set: + mov x6, x3 +loop_way: + lsl x7, x6, x5 + orr x9, x12, x7 + lsl x7, x4, x2 + orr x9, x9, x7 + tbz w1, #1, 3f + dc csw, x9 + b 2f +3: tbz w1, #0, 1f + dc isw, x9 + b 2f +1: dc cisw, x9 +2: subs x6, x6, #1 + b.ge loop_way + subs x4, x4, #1 + b.ge loop_set + + ret + + .type os_asm_dcache_all, "function" +os_asm_dcache_all: + mov x1, x0 + dsb sy + mrs x10, clidr_el1 + lsr x11, x10, #24 + and x11, x11, #0x7 + cbz x11, finished + mov x15, x30 + mov x0, #0 + +loop_level: + lsl x12, x0, #1 + add x12, x12, x0 + lsr x12, x10, x12 + and x12, x12, #7 + cmp x12, #2 + b.lt skip + bl os_asm_dcache_level +skip: + add x0, x0, #1 + cmp x11, x0 + b.gt loop_level + + mov x0, #0 + msr csselr_el1, x0 + dsb sy + isb + mov x30, x15 + +finished: + ret + + .type os_asm_invalidate_dcache_all, "function" +os_asm_invalidate_dcache_all: + mov x0, #0x1 + b os_asm_dcache_all + + .type os_asm_invalidate_icache_all, "function" +os_asm_invalidate_icache_all: + ic ialluis + isb sy + ret + + .type os_asm_invalidate_tlb_all, "function" +os_asm_invalidate_tlb_all: + tlbi vmalle1 + dsb sy + isb + ret diff --git a/demos/raspi4/bsp/cache_asm.h b/demos/raspi4/bsp/cache_asm.h new file mode 100644 index 0000000..d41c5ef --- /dev/null +++ b/demos/raspi4/bsp/cache_asm.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton raspi4 demo + */ +#ifndef __CACHE_H__ +#define __CACHE_H__ + +#include "prt_buildef.h" +#include "prt_typedef.h" +#include "prt_module.h" +#include "prt_errno.h" + +extern void os_asm_invalidate_dcache_all(void); +extern void os_asm_invalidate_icache_all(void); +extern void os_asm_invalidate_tlb_all(void); +#endif diff --git a/demos/raspi4/bsp/hwi_init.c b/demos/raspi4/bsp/hwi_init.c new file mode 100644 index 0000000..47f8516 --- /dev/null +++ b/demos/raspi4/bsp/hwi_init.c @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton raspi4 demo + */ +#include "securec.h" +#include "prt_tick.h" +#include "prt_hwi.h" +#include "prt_sys.h" +#include "prt_task.h" +#include "cpu_config.h" + +#if (OS_GIC_VER == 3) +enum GicIntState { + GIC_DISABLE = 0, + GIC_ENABLE = 1 +}; + +enum SicGroupType { + SIC_GROUP_G0S = 0, + SIC_GROUP_G1NS = 1, + SIC_GROUP_G1S = 2, + SIC_GROUP_BUTT, +}; + +union SicrWaker { + struct { + U32 res0 : 1; + U32 sleepReq : 1; + U32 isSleep : 1; + U32 res1 : 29; + } bits; + U32 value; +}; + +union SicrCtrl { + struct { + U32 enLpis : 1; + U32 res2 : 2; + U32 rwp : 1; + U32 res1 : 20; + U32 dpg0 : 1; + U32 dpg1ns : 1; + U32 dpg1s : 1; + U32 res0 : 4; + U32 uwp : 1; + } bits; + U32 value; +}; + +union HwiIccSreElx { + struct { + U64 prt : 1; + U64 dfb : 1; + U64 dib : 1; + U64 enable : 1; + U64 res : 60; + } bits; + U64 value; +}; + +union SicdCtrl { + struct { + U32 enG0S : 1; + U32 enG1Ns : 1; + U32 enG1S : 1; + U32 res1 : 1; + U32 areS : 1; + U32 areNs : 1; + U32 ds : 1; + U32 res0 : 24; + U32 rwp : 1; + } bits; + U32 value; +}; + +extern void OsGicdWaitCfgWork(); + +void OsSicrInit(void) +{ + union SicrWaker sicrWaker; + uintptr_t regAddr; + U32 intId; + + regAddr = GICR_WAKER_ADDR + OsGetCoreID() * SICR_ADDR_OFFSET_PER_CORE; + sicrWaker.value = GIC_REG_READ(regAddr); + sicrWaker.bits.sleepReq = 0; + GIC_REG_WRITE(regAddr, sicrWaker.value); + + sicrWaker.value = GIC_REG_READ(regAddr); + while (sicrWaker.bits.isSleep == 1) { + sicrWaker.value = GIC_REG_READ(regAddr); + } +} + +void OsSicrSetIntGroup(U32 coreId, U64 intId, enum SicGroupType groupId) +{ + uintptr_t group0RegAddr; + uintptr_t modRegAddr; + U32 group0RegTmp; + U32 modRegTmp; + + group0RegAddr = GICR_IGROUPR0_ADDR + OsGetCoreID() * SICR_ADDR_OFFSET_PER_CORE; + group0RegTmp = GIC_REG_READ(group0RegAddr); + + if ((groupId == SIC_GROUP_G0S) || (groupId == SIC_GROUP_G1S)) { + group0RegTmp &= ~(0x1U << intId); + } else { + group0RegTmp |= (0x1U << intId); + } + GIC_REG_WRITE(group0RegAddr, group0RegTmp); + + modRegAddr = GICR_IGRPMODR0_ADDR + OsGetCoreID() * SICR_ADDR_OFFSET_PER_CORE; + modRegTmp = GIC_REG_READ(modRegAddr); + + if (groupId == SIC_GROUP_G1S) { + modRegTmp |= (0x1U << intId); + } else { + modRegTmp &= ~(0x1U << intId); + } + GIC_REG_WRITE(modRegAddr, modRegTmp); +} + +U32 OsSiccEnableSre(void) +{ + volatile union HwiIccSreElx iccSre; + + OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_SRE_EL1) " \n" : "=&r"(iccSre)); + iccSre.bits.prt = 1; + iccSre.bits.dfb = 1; + iccSre.bits.dib = 1; + OS_EMBED_ASM("MSR " REG_ALIAS(ICC_SRE_EL1) ", %0 \n" : : "r"(iccSre)); + OS_EMBED_ASM("DSB SY"); + OS_EMBED_ASM("ISB"); + + OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_SRE_EL1) " \n" : "=&r"(iccSre.value)); + + if (iccSre.bits.prt != 1) { + return OS_FAIL; + } + + return OS_OK; +} + +void OsSiccCfgIntPreempt(void) +{ + U64 tmp = 0; + + OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_BPR1_EL1) " \n" : "=&r"(tmp) : : "memory"); + tmp &= ~(GROUP_MAX_BPR); + tmp |= GROUP1_BP; + OS_EMBED_ASM("MSR " REG_ALIAS(ICC_BPR1_EL1) ", %0 \n" : : "r"(tmp) : "memory"); +} + +void OsSiccEnableGroup1(void) +{ + U64 tmp = 0; + + OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_IGRPEN1_EL1) " \n" : "=&r"(tmp) : : "memory"); + tmp |= 0x01U; + OS_EMBED_ASM("MSR " REG_ALIAS(ICC_IGRPEN1_EL1) ", %0 \n" : : "r"(tmp) : "memory"); +} + +void OsSiccCfgPriorityMask(void) +{ + U64 tmp = 0; + + OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_PMR_EL1) " \n" : "=&r"(tmp) : : "memory"); + tmp |= PRIO_MASK_LEVEL; + OS_EMBED_ASM("MSR " REG_ALIAS(ICC_PMR_EL1) ", %0 \n" : : "r"(tmp) : "memory"); +} + +U32 OsSiccInit(void) +{ + U32 ret; + + ret = OsSiccEnableSre(); + if (ret != OS_OK) { + return ret; + } + + OsSiccCfgIntPreempt(); + + OsSiccEnableGroup1(); + + OsSiccCfgPriorityMask(); + + return OS_OK; +} + +void OsSicdSetIntGroup(U32 intId, enum SicGroupType groupId) +{ + U64 group0RegAddr; + U64 modRegAddr; + U32 group0RegTmp; + U32 modRegTmp; + U32 sicdM; + U32 bitOffset; + + sicdM = (intId - MIN_GIC_SPI_NUM) / SICD_IGROUP_INT_NUM; + group0RegAddr = GICD_IGROUPN_ADDR + (SICD_REG_SIZE * sicdM); + modRegAddr = GICD_IGRPMODRN_ADDR + (SICD_REG_SIZE * sicdM); + bitOffset = (intId - MIN_GIC_SPI_NUM) % SICD_IGROUP_INT_NUM; + + group0RegTmp = GIC_REG_READ(group0RegAddr); + if ((groupId == SIC_GROUP_G0S) || (groupId == SIC_GROUP_G1S)) { + group0RegTmp &= ~(0x1U << bitOffset); + } else { + group0RegTmp |= (0x1U << bitOffset); + } + GIC_REG_WRITE(group0RegAddr, group0RegTmp); + + modRegTmp = GIC_REG_READ(modRegAddr); + if (groupId == SIC_GROUP_G1S) { + modRegTmp |= (0x1U << bitOffset); + } else { + modRegTmp &= ~(0x1U << bitOffset); + } + GIC_REG_WRITE(modRegAddr, modRegTmp); +} + +void OsSicSetGroup(U32 intId, enum SicGroupType groupId) +{ + U32 coreId = OsGetCoreID(); + enum GicIntState state; + + if (intId < MIN_GIC_SPI_NUM) { + state = OsGicrGetIntState(coreId, intId); + OsGicrDisableInt(coreId, intId); + OsSicrSetIntGroup(coreId, intId, groupId); + if (state == GIC_ENABLE) { + OsGicrEnableInt(coreId, intId); + } + } else { + state = OsGicdGetIntState(intId); + OsGicdDisableInt(intId); + OsSicdSetIntGroup(intId, groupId); + if (state == GIC_ENABLE) { + OsGicdEnableInt(intId); + } + } +} + +U32 OsSicInitLocal(void) +{ + U32 ret; + U32 intId; + + OsSicrInit(); + + ret = OsSiccInit(); + if (ret != OS_OK) { + return ret; + } + + for (intId = 0; intId < MIN_GIC_SPI_NUM; ++intId) { + OsSicSetGroup(intId, SIC_GROUP_G1NS); + } + + return OS_OK; +} + +void OsSicdInit(void) +{ + union SicdCtrl sicdCtrl; + + sicdCtrl.value = GIC_REG_READ(GICD_CTLR_S_ADDR); + + if ((sicdCtrl.bits.enG0S == 1) || (sicdCtrl.bits.enG1Ns == 1) || (sicdCtrl.bits.enG1S == 1)) { + return; + } + + sicdCtrl.bits.ds = 0; + sicdCtrl.bits.areNs = 1; + sicdCtrl.bits.areS = 1; + sicdCtrl.bits.enG1Ns = 1; + GIC_REG_WRITE(GICD_CTLR_S_ADDR, sicdCtrl.value); + + OsGicdWaitCfgWork(); +} + +void OsSicInitGlobal(void) +{ + U32 intId; + + OsSicdInit(); + + for (intId = MIN_GIC_SPI_NUM; intId < MAX_INT_NUM; ++intId) { + OsSicSetGroup(intId, SIC_GROUP_G1NS); + } +} +#elif (OS_GIC_VER == 2) +int IsrRegister(U32 intNo, U32 pri) +{ + U32 bitn, reg, shift; + U32 *addr; + + bitn = intNo / 32U; + addr = (U32 *)(GICD_ISENABLERn + 4U * bitn); + reg = *addr; + *addr = (reg | (0x1U << (intNo % 32U))); + + bitn = intNo / 4U; + addr = (U32 *)(GICD_IPRIORITYn + 4U * bitn); + shift = (intNo % 4U) * 8U; + reg = (*addr) & ~(0xFFU << shift); + *addr = (reg | pri << shift); +} + +void OsGicInitCpuInterface(void) +{ + int i; + U32 val; + + GIC_REG_WRITE(0xFFFFFFFF, GICD_ICACTIVERn); + GIC_REG_WRITE(0xFFFF0000, GICD_ICENABLERn); + GIC_REG_WRITE(0x0000FFFF, GICD_ISENABLERn); + + for (i = 0; i < 32; i += 4) { + GIC_REG_WRITE(0xA0A0A0A0, GICD_IPRIORITYn + i); + } + + GIC_REG_WRITE(0xF0, GICC_PMR); + val = GIC_REG_READ(GICC_CTLR); + val &= ~GICC_CTLR_BYPASS_MASK; + val |= GICC_CTLR_ENABLE_MASK; + GIC_REG_WRITE(val, GICC_CTLR); +} +#endif +U32 OsHwiInit(void) +{ +#if (OS_GIC_VER == 3) + U32 ret; + + ret = OsSicInitLocal(); + if (ret != OS_OK) { + return ret; + } + + if(OsGetCoreID() == 0) { + OsSicInitGlobal(); + } +#elif (OS_GIC_VER == 2) + OsGicInitCpuInterface(); +#endif + return OS_OK; +} diff --git a/demos/raspi4/bsp/mmu.c b/demos/raspi4/bsp/mmu.c new file mode 100644 index 0000000..1bddbf0 --- /dev/null +++ b/demos/raspi4/bsp/mmu.c @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton raspi4 demo + */ +#include "prt_buildef.h" +#include "prt_typedef.h" +#include "prt_module.h" +#include "prt_errno.h" +#include "mmu.h" +#include "cache_asm.h" +#include "prt_sys.h" +#include "prt_task.h" +#include "cpu_config.h" + +extern U64 g_mmu_page_begin; +extern U64 g_mmu_page_end; + +static mmu_mmap_region_s g_mem_map_info[] = { + { + .virt = MMU_OPENAMP_ADDR, + .phys = MMU_OPENAMP_ADDR, + .size = 0x30000, + .max_level = 0x2, + .attrs = MMU_ATTR_DEVICE_NGNRNE | MMU_ACCESS_RWX, + }, { + .virt = MMU_IMAGE_ADDR, + .phys = MMU_IMAGE_ADDR, + .size = 0x1000000, + .max_level = 0x2, + .attrs = MMU_ATTR_CACHE_SHARE | MMU_ACCESS_RWX, + }, { + .virt = MMU_GIC_ADDR, + .phys = MMU_GIC_ADDR, + .size = 0x1000000, + .max_level = 0x2, + .attrs = MMU_ATTR_DEVICE_NGNRNE | MMU_ACCESS_RWX, + }, { + .virt = MMU_UART_ADDR, + .phys = MMU_UART_ADDR, + .size = 0x2000, + .max_level = 0x2, + .attrs = MMU_ATTR_DEVICE_NGNRNE | MMU_ACCESS_RWX, + } +}; + +static mmu_ctrl_s g_mmu_ctrl = { 0 }; + +static U64 mmu_get_tcr(U32 *pips, U32 *pva_bits) +{ + U64 max_addr = 0; + U64 ips, va_bits; + U64 tcr; + U32 i; + U32 mmu_table_num = sizeof(g_mem_map_info) / sizeof(mmu_mmap_region_s); + + for (i = 0; i < mmu_table_num; ++i) { + max_addr = MAX(max_addr, g_mem_map_info[i].virt + g_mem_map_info[i].size); + } + + if (max_addr > (1ULL << MMU_BITS_44)) { + ips = MMU_PHY_ADDR_LEVEL_5; + va_bits = MMU_BITS_48; + } else if (max_addr > (1ULL << MMU_BITS_42)) { + ips = MMU_PHY_ADDR_LEVEL_4; + va_bits = MMU_BITS_44; + } else if (max_addr > (1ULL << MMU_BITS_40)) { + ips = MMU_PHY_ADDR_LEVEL_3; + va_bits = MMU_BITS_42; + } else if (max_addr > (1ULL << MMU_BITS_36)) { + ips = MMU_PHY_ADDR_LEVEL_2; + va_bits = MMU_BITS_40; + } else if (max_addr > (1ULL << MMU_BITS_32)) { + ips = MMU_PHY_ADDR_LEVEL_1; + va_bits = MMU_BITS_36; + } else { + ips = MMU_PHY_ADDR_LEVEL_0; + va_bits = MMU_BITS_32; + } + + tcr = TCR_EL1_RSVD | TCR_IPS(ips); + + if (g_mmu_ctrl.granule == MMU_GRANULE_4K) { + tcr |= TCR_TG0_4K | TCR_SHARED_INNER | TCR_ORGN_WBWA | TCR_IRGN_WBWA; + } else { + tcr |= TCR_TG0_64K | TCR_SHARED_INNER | TCR_ORGN_WBWA | TCR_IRGN_WBWA; + } + + tcr |= TCR_T0SZ(va_bits); + + if (pips != NULL) { + *pips = ips; + } + + if (pva_bits != NULL) { + *pva_bits = va_bits; + } + + return tcr; +} + +static U32 mmu_get_pte_type(U64 const *pte) +{ + return (U32)(*pte & PTE_TYPE_MASK); +} + +static U32 mmu_level2shift(U32 level) +{ + if (g_mmu_ctrl.granule == MMU_GRANULE_4K) { + return (U32)(MMU_BITS_12 + MMU_BITS_9 * (MMU_LEVEL_3 - level)); + } else { + return (U32)(MMU_BITS_16 + MMU_BITS_13 * (MMU_LEVEL_3 - level)); + } +} + +static U64 *mmu_find_pte(U64 addr, U32 level) +{ + U64 *pte = NULL; + U64 idx; + U32 i; + + if (level < g_mmu_ctrl.start_level) { + return NULL; + } + + pte = (U64 *)g_mmu_ctrl.tlb_addr; + + for (i = g_mmu_ctrl.start_level; i < MMU_LEVEL_MAX; ++i) { + if (g_mmu_ctrl.granule == MMU_GRANULE_4K) { + idx = (addr >> mmu_level2shift(i)) & 0x1FF; + } else { + idx = (addr >> mmu_level2shift(i)) & 0x1FFF; + } + + pte += idx; + + if (i == level) { + return pte; + } + + if (mmu_get_pte_type(pte) != PTE_TYPE_TABLE) { + return NULL; + } + + if (g_mmu_ctrl.granule == MMU_GRANULE_4K) { + pte = (U64 *)(*pte & PTE_TABLE_ADDR_MARK_4K); + } else { + pte = (U64 *)(*pte & PTE_TABLE_ADDR_MARK_64K); + } + } + + return NULL; +} + +static U64 *mmu_create_table(void) +{ + U32 pt_len; + U64 *new_table = (U64 *)g_mmu_ctrl.tlb_fillptr; + + if (g_mmu_ctrl.granule == MMU_GRANULE_4K) { + pt_len = MAX_PTE_ENTRIES_4K * sizeof(U64); + } else { + pt_len = MAX_PTE_ENTRIES_64K * sizeof(U64); + } + + g_mmu_ctrl.tlb_fillptr += pt_len; + + if (g_mmu_ctrl.tlb_fillptr - g_mmu_ctrl.tlb_addr > g_mmu_ctrl.tlb_size) { + return NULL; + } + + (void)memset_s((void *)new_table, MAX_PTE_ENTRIES_64K * sizeof(U64), 0, pt_len); + + return new_table; +} + +static void mmu_set_pte_table(U64 *pte, U64 *table) +{ + *pte = PTE_TYPE_TABLE | (U64)table; +} + +static S32 mmu_add_map_pte_process(mmu_mmap_region_s const *map, U64 *pte, U64 phys, U32 level) +{ + U64 *new_table = NULL; + + if (level < map->max_level) { + if (mmu_get_pte_type(pte) == PTE_TYPE_FAULT) { + new_table = mmu_create_table(); + if (new_table == NULL) { + return -1; + } + mmu_set_pte_table(pte, new_table); + } + } else if (level == MMU_LEVEL_3) { + *pte = phys | map->attrs | PTE_TYPE_PAGE; + } else { + *pte = phys | map->attrs | PTE_TYPE_BLOCK; + } + + return 0; +} + +static S32 mmu_add_map(mmu_mmap_region_s const *map) +{ + U64 virt = map->virt; + U64 phys = map->phys; + U64 max_level = map->max_level; + U64 start_level = g_mmu_ctrl.start_level; + U64 block_size = 0; + U64 map_size = 0; + U32 level; + U64 *pte = NULL; + S32 ret; + + if (map->max_level <= start_level) { + return -2; + } + + while (map_size < map->size) { + for (level = start_level; level <= max_level; ++level) { + pte = mmu_find_pte(virt, level); + if (pte == NULL) { + return -3; + } + + ret = mmu_add_map_pte_process(map, pte, phys, level); + if (ret) { + return ret; + } + + if (level != start_level) { + block_size = 1ULL << mmu_level2shift(level); + } + } + + virt += block_size; + phys += block_size; + map_size += block_size; + } + + return 0; +} + +static inline void mmu_set_ttbr_tcr_mair(U64 table, U64 tcr, U64 attr) +{ + OS_EMBED_ASM("dsb sy"); + + OS_EMBED_ASM("msr ttbr0_el1, %0" : : "r" (table) : "memory"); + OS_EMBED_ASM("msr ttbr1_el1, %0" : : "r" (table) : "memory"); + OS_EMBED_ASM("msr tcr_el1, %0" : : "r" (tcr) : "memory"); + OS_EMBED_ASM("msr mair_el1, %0" : : "r" (attr) : "memory"); + + OS_EMBED_ASM("isb"); +} + +static U32 mmu_setup_pgtables(mmu_mmap_region_s *mem_map, U32 mem_region_num, U64 tlb_addr, U64 tlb_len, U32 granule) +{ + U32 i; + U32 ret; + U64 tcr; + U64 *new_table = NULL; + + g_mmu_ctrl.tlb_addr = tlb_addr; + g_mmu_ctrl.tlb_size = tlb_len; + g_mmu_ctrl.tlb_fillptr = tlb_addr; + g_mmu_ctrl.granule = granule; + g_mmu_ctrl.start_level = 0; + + tcr = mmu_get_tcr(NULL, &g_mmu_ctrl.va_bits); + + if (g_mmu_ctrl.granule == MMU_GRANULE_4K) { + if (g_mmu_ctrl.va_bits < MMU_BITS_39) { + g_mmu_ctrl.start_level = MMU_LEVEL_1; + } else { + g_mmu_ctrl.start_level = MMU_LEVEL_0; + } + } else { + if (g_mmu_ctrl.va_bits <= MMU_BITS_36) { + g_mmu_ctrl.start_level = MMU_LEVEL_2; + } else { + g_mmu_ctrl.start_level = MMU_LEVEL_1; + return 3; + } + } + + new_table = mmu_create_table(); + if (new_table == NULL) { + return 1; + } + + for (i = 0; i < mem_region_num; ++i) { + ret = mmu_add_map(&mem_map[i]); + if (ret) { + return ret; + } + } + + mmu_set_ttbr_tcr_mair(g_mmu_ctrl.tlb_addr, tcr, MEMORY_ATTRIBUTES); + + return 0; +} + +static S32 mmu_setup(void) +{ + S32 ret; + U64 page_addr; + U64 page_len; + + page_addr = (U64)&g_mmu_page_begin; + page_len = (U64)&g_mmu_page_end - (U64)&g_mmu_page_begin; + + ret = mmu_setup_pgtables(g_mem_map_info, (sizeof(g_mem_map_info) / sizeof(mmu_mmap_region_s)), + page_addr, page_len, MMU_GRANULE_4K); + if (ret) { + return ret; + } + + return 0; +} + +S32 mmu_init(void) +{ + S32 ret; + + ret = mmu_setup(); + if (ret) { + return ret; + } + + os_asm_invalidate_dcache_all(); + os_asm_invalidate_icache_all(); + os_asm_invalidate_tlb_all(); + + set_sctlr(get_sctlr() | CR_C | CR_M | CR_I); + + return 0; +} diff --git a/demos/raspi4/bsp/mmu.h b/demos/raspi4/bsp/mmu.h new file mode 100644 index 0000000..6b5cc74 --- /dev/null +++ b/demos/raspi4/bsp/mmu.h @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton raspi4 demo + */ +#ifndef __MMU_H__ +#define __MMU_H__ + +#include "prt_typedef.h" + +#define CACHE_POS 0x2 +#define CACHE_ENABLE 0x4 +#define CACHE_MASK 0x7 + +#define MT_DEVICE_NGNRNE 0 +#define MT_DEVICE_NGNRE 1 +#define MT_DEVICE_GRE 2 +#define MT_NORMAL_NC 3 +#define MT_NORMAL 4 + +#define MEMORY_ATTRIBUTES ((0x00 << (MT_DEVICE_NGNRNE * 8)) | \ + (0x04 << (MT_DEVICE_NGNRE * 8)) | \ + (0x0c << (MT_DEVICE_GRE * 8)) | \ + (0x44 << (MT_NORMAL_NC * 8)) | \ + (0xffUL << (MT_NORMAL * 8))) + +#define PTE_TYPE_FAULT (0 << 0) +#define PTE_TYPE_BLOCK (1 << 0) +#define PTE_TYPE_VALID (1 << 0) +#define PTE_TYPE_MASK (3 << 0) +#define PTE_TYPE_PAGE (3 << 0) +#define PTE_TYPE_TABLE (3 << 0) + +#define PTE_TABLE_PXN (1UL << 59) +#define PTE_TABLE_XN (1UL << 60) +#define PTE_TABLE_AP (1UL << 61) +#define PTE_TABLE_NS (1UL << 63) + +#define PTE_BLOCK_MEMTYPE(x) ((x) << 2) +#define PTE_BLOCK_NS (1 << 5) +#define PTE_BLOCK_AP_R (2 << 6) +#define PTE_BLOCK_AP_RW (0 << 6) +#define PTE_BLOCK_NON_SHARE (0 << 8) +#define PTE_BLOCK_OUTER_SHARE (2 << 8) +#define PTE_BLOCK_INNER_SHARE (3 << 8) +#define PTE_BLOCK_AF (1 << 10) +#define PTE_BLOCK_NG (1 << 11) +#define PTE_BLOCK_PXN (1UL << 53) +#define PTE_BLOCK_UXN (1UL << 54) + +#define PMD_ATTRINDX(t) ((t) << 2) +#define PMD_ATTRINDX_MASK (7 << 2) +#define PMD_ATTRMASK (PTE_BLOCK_PXN | \ + PTE_BLOCK_UXN | \ + PMD_ATTRINDX_MASK | \ + PTE_TYPE_VALID) + +#define TCR_IPS(x) ((x) << 32) +#define TCR_T0SZ(x) ((64 - (x)) << 0) +#define TCR_IRGN_NC (0 << 8) +#define TCR_IRGN_WBWA (1 << 8) +#define TCR_IRGN_WT (2 << 8) +#define TCR_IRGN_WBNWA (3 << 8) +#define TCR_IRGN_MASK (3 << 8) +#define TCR_ORGN_NC (0 << 10) +#define TCR_ORGN_WBWA (1 << 10) +#define TCR_ORGN_WT (2 << 10) +#define TCR_ORGN_WBNWA (3 << 10) +#define TCR_ORGN_MASK (3 << 10) +#define TCR_SHARED_NON (0 << 12) +#define TCR_SHARED_OUTER (2 << 12) +#define TCR_SHARED_INNER (3 << 12) +#define TCR_TG0_4K (0 << 14) +#define TCR_TG0_64K (1 << 14) +#define TCR_TG0_16K (2 << 14) +#define TCR_EPD1_DISABLE (1 << 23) + +#define TCR_EL1_RSVD (1UL << 31) +#define TCR_EL2_RSVD (1UL << 31 | 1UL << 23) +#define TCR_EL3_RSVD (1UL << 31 | 1UL << 23) + +#define MAX_PTE_ENTRIES_4K 512 +#define MAX_PTE_ENTRIES_64K 8192 + +#define PTE_TABLE_ADDR_MARK_4K 0x0000FFFFFFFFF000ULL +#define PTE_TABLE_ADDR_MARK_64K 0x0000FFFFFFFF0000ULL + + +#define MMU_ATTR_DEVICE_NGNRNE (PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE)) +#define MMU_ATTR_DEVICE (PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE)) +#define MMU_ATTR_UNCACHE_UNSHARE (PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) | PTE_BLOCK_NON_SHARE) +#define MMU_ATTR_UNCACHE_SHARE (PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) | PTE_BLOCK_INNER_SHARE) +#define MMU_ATTR_CACHE_UNSHARE (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE) +#define MMU_ATTR_CACHE_SHARE (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE) +#define MMU_ATTR_MASK 0X31CULL + +#define MMU_ACCESS_NONE (PTE_BLOCK_AP_RW) +#define MMU_ACCESS_R (PTE_BLOCK_AF | PTE_BLOCK_UXN | PTE_BLOCK_PXN | PTE_BLOCK_AP_R) +#define MMU_ACCESS_RW (PTE_BLOCK_AF | PTE_BLOCK_UXN | PTE_BLOCK_PXN | PTE_BLOCK_AP_RW) +#define MMU_ACCESS_RWX (PTE_BLOCK_AF | PTE_BLOCK_AP_RW) +#define MMU_ACCESS_RX (PTE_BLOCK_AF | PTE_BLOCK_AP_R) +#define MMU_ACCESS_MASK 0X600000000004C0ULL + +#define MMU_GRANULE_4K 0 +#define MMU_GRANULE_64K 1 + +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define CR_M (1 << 0) +#define CR_A (1 << 1) +#define CR_C (1 << 2) +#define CR_SA (1 << 3) +#define CR_I (1 << 12) +#define CR_WXN (1 << 19) +#define CR_EE (1 << 25) + +#define SPSR_EL_END_LE (0 << 9) +#define SPSR_EL_DEBUG_MASK (1 << 9) +#define SPSR_EL_ASYN_MASK (1 << 8) +#define SPSR_EL_SERR_MASK (1 << 8) +#define SPSR_EL_IRQ_MASK (1 << 7) +#define SPSR_EL_FIQ_MASK (1 << 6) +#define SPSR_EL_T_A32 (0 << 5) +#define SPSR_EL_M_AARCH64 (0 << 4) +#define SPSR_EL_M_AARCH32 (1 << 4) +#define SPSR_EL_M_SVC (0x3) +#define SPSR_EL_M_HYP (0xa) +#define SPSR_EL_M_EL1H (5) +#define SPSR_EL_M_EL2H (9) + +#define CPUECTLR_EL1_L1PCTL_MASK (7 << 13) +#define CPUECTLR_EL1_L3PCTL_MASK (7 << 10) + +typedef enum { + MMU_LEVEL_0 = 0, + MMU_LEVEL_1, + MMU_LEVEL_2, + MMU_LEVEL_3, + MMU_LEVEL_MAX +} mmu_level_e; + +typedef enum { + MMU_PHY_ADDR_LEVEL_0 = 0, + MMU_PHY_ADDR_LEVEL_1, + MMU_PHY_ADDR_LEVEL_2, + MMU_PHY_ADDR_LEVEL_3, + MMU_PHY_ADDR_LEVEL_4, + MMU_PHY_ADDR_LEVEL_5 +} mmu_physical_addr_size_e; + +typedef enum { + MMU_BITS_9 = 9, + MMU_BITS_12 = 12, + MMU_BITS_13 = 13, + MMU_BITS_16 = 16, + MMU_BITS_32 = 32, + MMU_BITS_36 = 36, + MMU_BITS_39 = 39, + MMU_BITS_40 = 40, + MMU_BITS_42 = 42, + MMU_BITS_44 = 44, + MMU_BITS_48 = 48, +} mmu_bits_e; + +typedef struct { + U64 tlb_addr; + U64 tlb_size; + U64 tlb_fillptr; + U32 granule; + U32 start_level; + U32 va_bits; +} mmu_ctrl_s; + +typedef struct { + U64 virt; + U64 phys; + U64 size; + U64 max_level; + U64 attrs; +} mmu_mmap_region_s; + +static inline unsigned long get_sctlr(void) +{ + unsigned long val; + + __asm__ __volatile__("mrs %0, sctlr_el1" : "=r" (val) : : "cc"); + + return val; +} + +static inline unsigned long get_cpuectr(void) +{ + unsigned long val; + + __asm__ __volatile__("mrs %0, S3_1_C15_C2_1" : "=r" (val) : : "cc"); + + return val; +} + +static inline void set_sctlr(unsigned long val) +{ + __asm__ __volatile__("dsb sy"); + __asm__ __volatile__("msr sctlr_el1, %0" : : "r" (val) : "cc"); + __asm__ __volatile__("dsb sy"); + __asm__ __volatile__("isb"); +} + +extern S32 mmu_init(void); + +#endif diff --git a/demos/raspi4/bsp/print.c b/demos/raspi4/bsp/print.c new file mode 100644 index 0000000..b48e6a3 --- /dev/null +++ b/demos/raspi4/bsp/print.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton raspi4 demo + */ +#include +#include "prt_typedef.h" +#include "cpu_config.h" +#include "securec.h" + +typedef U32 (*PrintFunc)(const char *format, va_list vaList); +#define OS_MAX_SHOW_LEN 0x200 + +void uart_poll_send(unsigned char ch) +{ + volatile int time = 100000; + *(unsigned int *)UART_BASE_ADDR = ch; + while (time--); +} + +void TestPutc(unsigned char ch) +{ + uart_poll_send(ch); + if (ch == '\n') { + uart_poll_send('\r'); + } +} + +int TestPrintf(const char *format, va_list vaList) +{ + int len; + char buff[OS_MAX_SHOW_LEN] = {0}; + char *str = buff; + + len = vsnprintf_s(buff, OS_MAX_SHOW_LEN, OS_MAX_SHOW_LEN, format, vaList); + if (len == -1) { + return len; + } + + while (*str != '\0') { + TestPutc(*str); + str++; + } + + return OS_OK; +} + +U32 PRT_Printf(const char *format, ...) +{ + va_list vaList; + S32 count; + + va_start(vaList, format); + count = TestPrintf(format, vaList); + va_end(vaList); + + return count; +} diff --git a/demos/raspi4/bsp/raspi4/cpu_config.h b/demos/raspi4/bsp/raspi4/cpu_config.h new file mode 100644 index 0000000..a12e7f5 --- /dev/null +++ b/demos/raspi4/bsp/raspi4/cpu_config.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton raspi4 demo + */ +#ifndef CPU_CONFIG_H +#define CPU_CONFIG_H + +#include "cache_asm.h" + +#define MMU_IMAGE_ADDR 0x7A000000ULL +#define MMU_GIC_ADDR 0xFF800000ULL +#define MMU_UART_ADDR 0xFE200000ULL +#define MMU_OPENAMP_ADDR 0x70000000ULL + +#define UART_BASE_ADDR 0xFE201000ULL + +#define TEST_CLK_INT 30 + +#define OS_GIC_VER 2 +#define SICR_ADDR_OFFSET_PER_CORE 0x200U +#define GIC_REG_BASE_ADDR 0xFF841000ULL + +#define GIC_DIST_BASE GIC_REG_BASE_ADDR +#define GIC_CPU_BASE (GIC_DIST_BASE + 0x1000U) + +#define GICD_CTLR (GIC_DIST_BASE + 0x0000U) +#define GICD_TYPER (GIC_DIST_BASE + 0x0004U) +#define GICD_IIDR (GIC_DIST_BASE + 0x0008U) +#define GICD_IGROUPRn (GIC_DIST_BASE + 0x0080U) +#define GICD_ISENABLERn (GIC_DIST_BASE + 0x0100U) +#define GICD_ICENABLERn (GIC_DIST_BASE + 0x0180U) +#define GICD_ISPENDRn (GIC_DIST_BASE + 0x0200U) +#define GICD_ICPENDRn (GIC_DIST_BASE + 0x0280U) +#define GICD_ISACTIVERn (GIC_DIST_BASE + 0x0300U) +#define GICD_ICACTIVERn (GIC_DIST_BASE + 0x0380U) +#define GICD_IPRIORITYn (GIC_DIST_BASE + 0x0400U) + +#define GICC_CTLR (GIC_CPU_BASE + 0x0000U) +#define GICC_PMR (GIC_CPU_BASE + 0x0004U) + +#define BIT(n) (1 << (n)) + +#define GICC_CTLR_ENABLEGRP0 BIT(0) +#define GICC_CTLR_ENABLEGRP1 BIT(1) +#define GICC_CTLR_FIQBYPDISGRP0 BIT(5) +#define GICC_CTLR_IRQBYPDISGRP0 BIT(6) +#define GICC_CTLR_FIQBYPDISGRP1 BIT(7) +#define GICC_CTLR_IRQBYPDISGRP1 BIT(8) + +#define GICC_CTLR_ENABLE_MASK (GICC_CTLR_ENABLEGRP0 | \ + GICC_CTLR_ENABLEGRP1) + +#define GICC_CTLR_BYPASS_MASK (GICC_CTLR_FIQBYPDISGRP0 | \ + GICC_CTLR_IRQBYPDISGRP0 | \ + GICC_CTLR_FIQBYPDISGRP1 | \ + GICC_CTLR_IRQBYPDISGRP1) + +#define GIC_REG_READ(addr) (*(volatile U32 *)((uintptr_t)(addr))) +#define GIC_REG_WRITE(data, addr) (*(volatile U32 *)((uintptr_t)(addr)) = (U32)(data)) + +#endif diff --git a/demos/raspi4/bsp/start.S b/demos/raspi4/bsp/start.S new file mode 100644 index 0000000..c425013 --- /dev/null +++ b/demos/raspi4/bsp/start.S @@ -0,0 +1,121 @@ +@/* +@ * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. +@ * +@ * UniProton is licensed under Mulan PSL v2. +@ * You can use this software according to the terms and conditions of the Mulan PSL v2. +@ * You may obtain a copy of Mulan PSL v2 at: +@ * http://license.coscl.org.cn/MulanPSL2 +@ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +@ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +@ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +@ * See the Mulan PSL v2 for more details. +@ * Create: 2009-12-22 +@ * Description: thread scheduler +@ */ +#include "prt_buildef.h" + + .global OsResetVector + .global mmu_init + + .type mmu_init, function + .type start, function + .section .text.bspinit, "ax" + .balign 4 + +#define HCR_EL2_FMO (1 << 3) +#define HCR_EL2_IMO (1 << 4) +#define HCR_EL2_AMO (1 << 5) +#define HCR_EL2_TWI (1 << 13) +#define HCR_EL2_TWE (1 << 14) +#define HCR_EL2_TVM (1 << 26) +#define HCR_EL2_TGE (1 << 27) +#define HCR_EL2_TDZ (1 << 28) +#define HCR_EL2_HCD (1 << 29) +#define HCR_EL2_TRVM (1 << 30) +#define HCR_EL2_RW (1 << 31) + +#define SPSR_DBG_MASK (1 << 9) +#define SPSR_SERR_MASK (1 << 8) +#define SPSR_IRQ_MASK (1 << 7) +#define SPSR_FIQ_MASK (1 << 6) +#define SPSR_M_AARCH64 (0 << 4) +#define SPSR_M_AARCH32 (1 << 4) +#define SPSR_M_EL1H (5) +#define SPSR_M_EL2H (9) + +#define CNTHCTL_EL2_EL1PCEN_EN (1 << 1) +#define CNTHCTL_EL2_EL1PCTEN_EN (1 << 0) +#define CPACR_EL1_FPEN_EN (3 << 20) + + .global OsElxState + .type OsElxState, @function +OsElxState: + MRS x6, CurrentEL + MOV x2, #0x4 + CMP w6, w2 + + BEQ Start + +OsEl2Entry: + MRS x10, CNTHCTL_EL2 + ORR x10, x10, #0x3 + MSR CNTHCTL_EL2, x10 + + MRS x10, CNTKCTL_EL1 + ORR x10, x10, #0x3 + MSR CNTKCTL_EL1, x10 + + MRS x10, MIDR_EL1 + MRS x1, MPIDR_EL1 + MSR VPIDR_EL2, x10 + MSR VMPIDR_EL2, x1 + + MOV x10, #0x33ff + MSR CPTR_EL2, x10 + MSR HSTR_EL2, xzr + + MRS x10, CPACR_EL1 + MOV x10, #3 << 20 + MSR CPACR_EL1, x10 + + MOV x10, #(HCR_EL2_RW) + ORR x10, x10, #(HCR_EL2_HCD) + BIC x10, x10, #(HCR_EL2_TVM) + BIC x10, x10, #(HCR_EL2_TRVM) + BIC x10, x10, #(HCR_EL2_TGE) + BIC x10, x10, #(HCR_EL2_AMO) + BIC x10, x10, #(HCR_EL2_IMO) + BIC x10, x10, #(HCR_EL2_FMO) + BIC x10, x10, #(HCR_EL2_TWI) + BIC x10, x10, #(HCR_EL2_TWE) + + MSR HCR_EL2, x10 + +OsEl2SwitchToEl1: + ADR x0, Start + MSR SP_EL1, XZR + MSR ELR_EL2, x0 + MOV x0, XZR + + LDR x20, =(SPSR_DBG_MASK | SPSR_SERR_MASK | \ + SPSR_IRQ_MASK | SPSR_FIQ_MASK | SPSR_M_EL1H) + MSR SPSR_EL2, x20 + + TLBI ALLE1IS + IC IALLU + DSB SY + ISB + ERET + +Start: + LDR x1, =__os_sys_sp_end + BIC sp, x1, #0xf + + BL mmu_init + B OsResetVector + +OsEnterReset: + B OsEnterReset + + .section .text, "ax" + .balign 4 diff --git a/demos/raspi4/bsp/timer.c b/demos/raspi4/bsp/timer.c new file mode 100644 index 0000000..75008f5 --- /dev/null +++ b/demos/raspi4/bsp/timer.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton raspi4 demo + */ +#include "prt_sys.h" +#include "prt_tick.h" +#include "prt_config.h" +#include "prt_task.h" +#include "prt_hwi.h" +#include "cpu_config.h" +#include "securec.h" + +U64 g_timerFrequency; +#define PMU_TIMER_FREQUENCY g_timerFrequency + +U64 GetGenericTimerFreq(void) +{ + U64 freq; + + OS_EMBED_ASM("MRS %0, CNTFRQ_EL0" : "=r"(freq) : : "memory", "cc"); + + return freq; +} + +void TimerIsr(uintptr_t para) +{ + (void)para; + U32 cfgMask = 0x0; + U64 cycle = PMU_TIMER_FREQUENCY / OS_TICK_PER_SECOND; + + OS_EMBED_ASM("MSR CNTP_CTL_EL0, %0" : : "r"(cfgMask) : "memory"); + PRT_ISB(); + OS_EMBED_ASM("MSR CNTP_TVAL_EL0, %0" : : "r"(cycle) : "memory", "cc"); + + cfgMask = 0x1; + OS_EMBED_ASM("MSR CNTP_CTL_EL0, %0" : : "r"(cfgMask) : "memory"); + + PRT_TickISR(); + PRT_ISB(); +} + +void CoreTimerInit(void) +{ + U32 cfgMask = 0x0; + U64 cycle = PMU_TIMER_FREQUENCY / OS_TICK_PER_SECOND; + + OS_EMBED_ASM("MSR CNTP_CTL_EL0, %0" : : "r"(cfgMask) : "memory"); + PRT_ISB(); + OS_EMBED_ASM("MSR CNTP_TVAL_EL0, %0" : : "r"(cycle) : "memory", "cc"); + + cfgMask = 0x1; + OS_EMBED_ASM("MSR CNTP_CTL_EL0, %0" : : "r"(cfgMask) : "memory"); +} + +U32 CoreTimerStart(void) +{ + g_timerFrequency = GetGenericTimerFreq(); + CoreTimerInit(); + + return OS_OK; +} + +U32 TestClkStart(void) +{ + U32 ret; + + ret = PRT_HwiSetAttr(TEST_CLK_INT, 10, OS_HWI_MODE_ENGROSS); + if (ret != OS_OK) { + return ret; + } + + ret = PRT_HwiCreate(TEST_CLK_INT, (HwiProcFunc)TimerIsr, 0); + if (ret != OS_OK) { + return ret; + } + +#if (OS_GIC_VER == 3) + ret = PRT_HwiEnable(TEST_CLK_INT); + if (ret != OS_OK) { + return ret; + } +#elif (OS_GIC_VER == 2) + IsrRegister(TEST_CLK_INT, 0xaU, (0x1U << 0x3U)); +#endif + + ret = CoreTimerStart(); + if (ret != OS_OK) { + return ret; + } + + return OS_OK; +} diff --git a/demos/raspi4/build/build_app.sh b/demos/raspi4/build/build_app.sh new file mode 100644 index 0000000..d4b5e7c --- /dev/null +++ b/demos/raspi4/build/build_app.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Copyright (c) 2023 Huawei Device Co., Ltd. +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. + +export TOOLCHAIN_PATH=/opt/buildtools/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf +export APP=raspi4 +export TMP_DIR=$APP + +sh ./build_static.sh $APP +sh ./build_openamp.sh + +cmake -S .. -B $TMP_DIR -DAPP:STRING=$APP -DTOOLCHAIN_PATH:STRING=$TOOLCHAIN_PATH +pushd $TMP_DIR +make $APP +popd +cp ./$TMP_DIR/$APP $APP.elf +$TOOLCHAIN_PATH/bin/aarch64-none-elf-objcopy -O binary ./$APP.elf $APP.bin +$TOOLCHAIN_PATH/bin/aarch64-none-elf-objdump -D ./$APP.elf > $APP.asm +rm -rf $TMP_DIR diff --git a/demos/raspi4/build/build_openamp.sh b/demos/raspi4/build/build_openamp.sh new file mode 100644 index 0000000..493d230 --- /dev/null +++ b/demos/raspi4/build/build_openamp.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# Copyright (c) 2023 Huawei Device Co., Ltd. +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. + +echo "################# git clone libmetal #################" +pushd ../component +rm -rf ./libmetal* +git clone https://gitee.com/src-openeuler/libmetal.git +mv ./libmetal/libmetal-2022.10.0.tar.gz . +rm -rf ./libmetal +tar -zxvf libmetal-2022.10.0.tar.gz +mv ./libmetal-2022.10.0 ./libmetal +cp UniProton-patch-for-libmetal.patch ./libmetal +cd libmetal +patch -p1 -d . < UniProton-patch-for-libmetal.patch +popd + +echo "################# git clone openamp #################" +pushd ../component +rm -rf ./open-amp* +git clone https://gitee.com/src-openeuler/OpenAMP.git +mv ./OpenAMP/open-amp-2022.10.1.tar.gz . +rm -rf ./OpenAMP +tar -zxvf open-amp-2022.10.1.tar.gz +mv ./open-amp-2022.10.1 ./open-amp +cp UniProton-patch-for-openamp.patch ./open-amp +cd open-amp +patch -p1 -d . < UniProton-patch-for-openamp.patch +popd + +echo "######################### build metal #########################" +pushd . +mkdir -p libmetal +cd libmetal +mkdir -p build +cd build +rm -rf * +cmake ../../../component/libmetal -DCMAKE_TOOLCHAIN_FILE=../../../component/libmetal/cmake/platforms/uniproton_arm64_gcc.cmake -DWITH_DOC=OFF -DWITH_EXAMPLES=OFF -DWITH_TESTS=OFF -DWITH_DEFAULT_LOGGER=OFF -DWITH_SHARED_LIB=OFF +make VERBOSE=1 DESTDIR=../output install +if [ $? -ne 0 ];then + echo "make metal failed!" + exit 1 +fi +popd + +echo "######################### build openamp #########################" +pushd . +mkdir -p open-amp +cd open-amp +mkdir -p build +cd build +rm -rf * +cmake ../../../component/open-amp -DCMAKE_TOOLCHAIN_FILE=../../../component/open-amp/cmake/platforms/uniproton_arm64_gcc.cmake +make VERBOSE=1 DESTDIR=../output install +if [ $? -ne 0 ];then + echo "make openamp failed!" + exit 1 +fi +popd + +cp ./libmetal/output/usr/local/lib/*.a ../libs +cp ./open-amp/output/usr/local/lib/*.a ../libs diff --git a/demos/raspi4/build/build_static.sh b/demos/raspi4/build/build_static.sh new file mode 100644 index 0000000..3e7092e --- /dev/null +++ b/demos/raspi4/build/build_static.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Copyright (c) 2023 Huawei Device Co., Ltd. +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. + +git clone https://gitee.com/openeuler/libboundscheck.git + +cp libboundscheck/include/* ../../../platform/libboundscheck/include +cp libboundscheck/include/* ../include +cp libboundscheck/src/* ../../../platform/libboundscheck/src +rm -rf libboundscheck + +pushd ./../../../ +python build.py $1 +cp output/UniProton/lib/$1/* demos/$1/libs +cp output/libboundscheck/lib/$1/* demos/$1/libs +cp -r src/include/uapi/* demos/$1/include +popd diff --git a/demos/raspi4/build/raspi4.ld b/demos/raspi4/build/raspi4.ld new file mode 100644 index 0000000..bd751ee --- /dev/null +++ b/demos/raspi4/build/raspi4.ld @@ -0,0 +1,120 @@ +ENTRY(__text_start) + +_stack_size = 0x10000; +_heap_size = 0x10000; + +MEMORY +{ + IMU_SRAM (rwx) : ORIGIN = 0x7a000000, LENGTH = 0x800000 + MMU_MEM (rwx) : ORIGIN = 0x7a800000, LENGTH = 0x800000 +} + +SECTIONS +{ + text_start = .; + .start_bspinit : + { + __text_start = .; + KEEP(*(.text.bspinit)) + } > IMU_SRAM + + .start_text : + { + KEEP(*(.text.startup)) + } > IMU_SRAM + + .text : + { + *(.text) + *(.text.*) + *(*.text) + . = ALIGN(8); + __text_end = .; + } > IMU_SRAM + . = ALIGN(8); + data_copy_start = .; + + .rodata : + { + . = ALIGN(8); + __rodata_start = .; + *(.rodata) + *(.rodata.*) + . = ALIGN(8); + __rodata_end = .; + } > IMU_SRAM + + .eh_frame : + { + . = ALIGN(8); + __os_unwind_table_start = .; + *(.eh_frame) + __os_unwind_table_end = .; + } > IMU_SRAM + + .heap (NOLOAD) : + { + . = ALIGN(8); + PROVIDE (__HEAP_INIT = .); + . = . + _heap_size; + . = ALIGN(8); + PROVIDE (__HEAP_END = .); + } > IMU_SRAM + + .stack (NOLOAD) : + { + . = ALIGN(8); + PROVIDE (__os_sys_sp_start = .); + . = . + _stack_size; + . = ALIGN(8); + PROVIDE (__os_sys_sp_end = .); + } > IMU_SRAM + end = .; + + .percpu.data : + { + __os_per_cpu_start = .; + *(.os.percpu.data) + __os_per_cpu_end = .; + LONG (ALIGNOF(.percpu.data)) + } > IMU_SRAM + + .data : + { + . = ALIGN(8); + __data_start = .; + *(.data) + *(.data.*) + . = ALIGN(8); + __os_text_start = .; + QUAD(__text_start) + QUAD(__text_end) + __os_text_end = .; + __data_end = .; + } > IMU_SRAM + + .llt.bss : + { + _llt_bss_start = .; + *__code_measure_stub*.o(.bss) + *__code_measure_stub*.o(.bss.*) + _llt_bss_end = .; + } > IMU_SRAM + + .bss (NOLOAD) : + { + . = ALIGN(8); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(8); + __bss_end__ = .; + } > IMU_SRAM + + .mmu.table.base : + { + PROVIDE (g_mmu_page_begin = .); + PROVIDE (g_mmu_page_end = g_mmu_page_begin + 0x8000); + } > MMU_MEM +} diff --git a/demos/raspi4/component/UniProton-patch-for-libmetal.patch b/demos/raspi4/component/UniProton-patch-for-libmetal.patch new file mode 100644 index 0000000..d22262a --- /dev/null +++ b/demos/raspi4/component/UniProton-patch-for-libmetal.patch @@ -0,0 +1,581 @@ +diff -uparN libmetal-2022.10.0/cmake/platforms/uniproton_arm64_gcc.cmake libmetal/cmake/platforms/uniproton_arm64_gcc.cmake +--- libmetal-2022.10.0/cmake/platforms/uniproton_arm64_gcc.cmake 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/cmake/platforms/uniproton_arm64_gcc.cmake 2023-02-22 11:01:30.000000000 +0800 +@@ -0,0 +1,16 @@ ++#cross-compilation config ++ ++set(CMAKE_SYSTEM_PROCESSOR arm) ++set(PROJECT_SYSTEM uniproton) ++ ++set(CMAKE_C_COMPILER_WORKS 1) ++set(CMAKE_CXX_COMPILER_WORKS 1) ++ ++set(CROSS_PREFIX "/opt/buildtools/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/aarch64-none-elf-" CACHE STRING "") ++set(CMAKE_C_COMPILER "${CROSS_PREFIX}gcc" CACHE STRING "") ++set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE STRING "") ++set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER CACHE STRING "") ++set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER CACHE STRING "") ++set(CMAKE_C_FLAGS "-D_GNU_SOURCE -D_POSIX_THREADS -D_POSIX_THREAD_PRIORITY_SCHEDULING -D_POSIX_PRIORITY_SCHEDULING -D_POSIX_TIMERS -D_POSIX_CPUTIME -D_POSIX_THREAD_CPUTIME -D_POSIX_MONOTONIC_CLOCK -D_POSIX_TIMEOUTS -D_POSIX_CLOCK_SELECTION -D_POSIX_THREAD_PRIO_PROTECT -D_UNIX98_THREAD_MUTEX_ATTRIBUTES -D_POSIX_READER_WRITER_LOCKS" CACHE STRING "") ++ ++# vim: expandtab:ts=2:sw=2:smartindent +diff -uparN libmetal-2022.10.0/CMakeLists.txt libmetal/CMakeLists.txt +--- libmetal-2022.10.0/CMakeLists.txt 2022-10-28 10:12:23.000000000 +0800 ++++ libmetal/CMakeLists.txt 2023-02-24 16:25:04.000000000 +0800 +@@ -6,7 +6,8 @@ endif() + if (POLICY CMP0077) + cmake_policy(SET CMP0077 NEW) + endif() +- ++include_directories(../../include) ++set (CMAKE_SYSTEM_NAME Uniproton) + set (LIBMETAL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + + list (APPEND CMAKE_MODULE_PATH +diff -uparN libmetal-2022.10.0/lib/system/uniproton/alloc.h libmetal/lib/system/uniproton/alloc.h +--- libmetal-2022.10.0/lib/system/uniproton/alloc.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/alloc.h 2023-02-20 14:53:22.000000000 +0800 +@@ -0,0 +1,39 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/alloc.h ++ * @brief Uniproton libmetal memory allocattion definitions. ++ */ ++ ++#ifndef __METAL_ALLOC__H__ ++#error "Include metal/alloc.h instead of metal/uniproton/alloc.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_ALLOC__H__ ++#define __METAL_UNIPROTON_ALLOC__H__ ++ ++#include "prt_mem.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++static inline void *metal_allocate_memory(unsigned int size) ++{ ++ return PRT_MemAlloc(OS_MID_SYS, OS_MEM_DEFAULT_PT0, size); ++} ++ ++static inline void metal_free_memory(void *ptr) ++{ ++ PRT_MemFree(OS_MID_SYS, ptr); ++} ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_ALLOC__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/assert.h libmetal/lib/system/uniproton/assert.h +--- libmetal-2022.10.0/lib/system/uniproton/assert.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/assert.h 2022-12-26 10:59:44.000000000 +0800 +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file assert.h ++ * @brief Uniproton assertion support. ++ */ ++ ++#ifndef __METAL_ASSERT__H__ ++#error "Include metal/assert.h instead of metal/uniproton/assert.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_ASSERT__H__ ++#define __METAL_UNIPROTON_ASSERT__H__ ++ ++/** ++ * @brief Assertion macro. ++ * @param cond Condition to test. ++ */ ++#define metal_sys_assert(cond) ++ ++#endif /* __METAL_UNIPROTON_ASSERT__H__ */ ++ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/cache.h libmetal/lib/system/uniproton/cache.h +--- libmetal-2022.10.0/lib/system/uniproton/cache.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/cache.h 2022-12-26 11:02:08.000000000 +0800 +@@ -0,0 +1,39 @@ ++/* ++ * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/cache.h ++ * @brief Uniproton cache operation primitives for libmetal. ++ */ ++ ++#ifndef __METAL_CACHE__H__ ++#error "Include metal/cache.h instead of metal/uniproton/cache.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_CACHE__H__ ++#define __METAL_UNIPROTON_CACHE__H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++static inline void __metal_cache_flush(void *addr, unsigned int len) ++{ ++ (void)addr; ++ (void)len; ++} ++ ++static inline void __metal_cache_invalidate(void *addr, unsigned int len) ++{ ++ (void)addr; ++ (void)len; ++} ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_CACHE__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/CMakeLists.txt libmetal/lib/system/uniproton/CMakeLists.txt +--- libmetal-2022.10.0/lib/system/uniproton/CMakeLists.txt 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/CMakeLists.txt 2022-12-26 14:13:48.000000000 +0800 +@@ -0,0 +1,17 @@ ++collect (PROJECT_LIB_HEADERS alloc.h) ++collect (PROJECT_LIB_HEADERS assert.h) ++collect (PROJECT_LIB_HEADERS cache.h) ++collect (PROJECT_LIB_HEADERS condition.h) ++collect (PROJECT_LIB_HEADERS io.h) ++collect (PROJECT_LIB_HEADERS irq.h) ++collect (PROJECT_LIB_HEADERS log.h) ++collect (PROJECT_LIB_HEADERS mutex.h) ++collect (PROJECT_LIB_HEADERS sleep.h) ++collect (PROJECT_LIB_HEADERS sys.h) ++ ++collect (PROJECT_LIB_SOURCES condition.c) ++collect (PROJECT_LIB_SOURCES device.c) ++collect (PROJECT_LIB_SOURCES init.c) ++collect (PROJECT_LIB_SOURCES shmem.c) ++ ++# vim: expandtab:ts=2:sw=2:smartindent +diff -uparN libmetal-2022.10.0/lib/system/uniproton/condition.c libmetal/lib/system/uniproton/condition.c +--- libmetal-2022.10.0/lib/system/uniproton/condition.c 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/condition.c 2022-12-26 11:06:12.000000000 +0800 +@@ -0,0 +1,33 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/condition.c ++ * @brief Uniproton libmetal condition variable handling. ++ */ ++ ++#include ++#include ++#include ++ ++int metal_condition_wait(struct metal_condition *cv, ++ metal_mutex_t *m) ++{ ++ unsigned int flags; ++ ++ /* Check if the mutex has been acquired */ ++ if (!cv || !m || !metal_mutex_is_acquired(m)) { ++ return -EINVAL; ++ } ++ ++ flags = metal_irq_save_disable(); ++ /* Release the mutex first. */ ++ metal_mutex_release(m); ++ metal_irq_restore_enable(flags); ++ /* Acquire the mutex again. */ ++ metal_mutex_acquire(m); ++ return 0; ++} +diff -uparN libmetal-2022.10.0/lib/system/uniproton/condition.h libmetal/lib/system/uniproton/condition.h +--- libmetal-2022.10.0/lib/system/uniproton/condition.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/condition.h 2022-12-26 11:09:02.000000000 +0800 +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/condition.h ++ * @brief Uniproton condition variable primitives for libmetal. ++ */ ++ ++#ifndef __METAL_CONDITION__H__ ++#error "Include metal/condition.h instead of metal/uniproton/condition.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_CONDITION__H__ ++#define __METAL_UNIPROTON_CONDITION__H__ ++ ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_CONDITION__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/device.c libmetal/lib/system/uniproton/device.c +--- libmetal-2022.10.0/lib/system/uniproton/device.c 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/device.c 2022-12-26 11:13:30.000000000 +0800 +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/device.c ++ * @brief Uniproton libmetal device definitions. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++int metal_generic_dev_sys_open(struct metal_device *dev) ++{ ++ return 0; ++} ++ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/init.c libmetal/lib/system/uniproton/init.c +--- libmetal-2022.10.0/lib/system/uniproton/init.c 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/init.c 2022-12-26 11:14:34.000000000 +0800 +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/init.c ++ * @brief Uniproton libmetal initialization. ++ */ ++ ++#include ++#include ++ ++struct metal_state _metal; ++ ++int metal_sys_init(const struct metal_init_params *params) ++{ ++ (void)params; ++ metal_bus_register(&metal_generic_bus); ++ return 0; ++} ++ ++void metal_sys_finish(void) ++{ ++ metal_bus_unregister(&metal_generic_bus); ++} +diff -uparN libmetal-2022.10.0/lib/system/uniproton/io.h libmetal/lib/system/uniproton/io.h +--- libmetal-2022.10.0/lib/system/uniproton/io.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/io.h 2022-12-26 11:16:50.000000000 +0800 +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/io.h ++ * @brief Uniproton specific io definitions. ++ */ ++ ++#ifndef __METAL_IO__H__ ++#error "Include metal/io.h instead of metal/uniproton/io.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_IO__H__ ++#define __METAL_UNIPROTON_IO__H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef METAL_INTERNAL ++/** ++ * @brief memory mapping for an I/O region ++ */ ++static inline void metal_sys_io_mem_map(struct metal_io_region *io) ++{ ++ (void)io; ++} ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_IO__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/irq.h libmetal/lib/system/uniproton/irq.h +--- libmetal-2022.10.0/lib/system/uniproton/irq.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/irq.h 2022-12-26 11:17:54.000000000 +0800 +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/irq.c ++ * @brief Uniproton libmetal irq definitions. ++ */ ++ ++#ifndef __METAL_IRQ__H__ ++#error "Include metal/irq.h instead of metal/uniproton/irq.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_IRQ__H__ ++#define __METAL_UNIPROTON_IRQ__H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_IRQ__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/log.h libmetal/lib/system/uniproton/log.h +--- libmetal-2022.10.0/lib/system/uniproton/log.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/log.h 2022-12-26 11:19:38.000000000 +0800 +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/log.h ++ * @brief Uniproton libmetal log handler definition. ++ */ ++ ++#ifndef __METAL_METAL_LOG__H__ ++#error "Include metal/log.h instead of metal/uniproton/log.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_LOG__H__ ++#define __METAL_UNIPROTON_LOG__H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_LOG__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/mutex.h libmetal/lib/system/uniproton/mutex.h +--- libmetal-2022.10.0/lib/system/uniproton/mutex.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/mutex.h 2023-02-23 14:22:12.000000000 +0800 +@@ -0,0 +1,73 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/mutex.h ++ * @brief Uniproton mutex primitives for libmetal. ++ */ ++ ++#ifndef __METAL_MUTEX__H__ ++#error "Include metal/mutex.h instead of metal/uniproton/mutex.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_MUTEX__H__ ++#define __METAL_UNIPROTON_MUTEX__H__ ++ ++#include "errno.h" ++#include "pthread.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef pthread_mutex_t metal_mutex_t; ++ ++/* ++ * METAL_MUTEX_INIT - used for initializing an mutex element in a static struct ++ * or global ++ */ ++#define METAL_MUTEX_INIT(m) MUTEX_INITIALIZER ++/* ++ * METAL_MUTEX_DEFINE - used for defining and initializing a global or ++ * static singleton mutex ++ */ ++#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = MUTEX_INITIALIZER ++ ++static inline void __metal_mutex_init(metal_mutex_t *mutex) ++{ ++ pthread_mutex_init(mutex, NULL); ++} ++ ++static inline void __metal_mutex_deinit(metal_mutex_t *mutex) ++{ ++ pthread_mutex_destroy(mutex); ++} ++ ++static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex) ++{ ++ return pthread_mutex_trylock(mutex); ++} ++ ++static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex) ++{ ++ ++} ++ ++static inline void __metal_mutex_acquire(metal_mutex_t *mutex) ++{ ++ pthread_mutex_lock(mutex); ++} ++ ++static inline void __metal_mutex_release(metal_mutex_t *mutex) ++{ ++ pthread_mutex_unlock(mutex); ++} ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_MUTEX__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/shmem.c libmetal/lib/system/uniproton/shmem.c +--- libmetal-2022.10.0/lib/system/uniproton/shmem.c 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/shmem.c 2022-12-26 11:20:44.000000000 +0800 +@@ -0,0 +1,19 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * ++ * @file uniproton/shmem.c ++ * @brief Uniproton libmetal shared memory handling. ++ */ ++ ++#include ++ ++int metal_shmem_open(const char *name, size_t size, ++ struct metal_io_region **io) ++{ ++ return metal_shmem_open_generic(name, size, io); ++} +diff -uparN libmetal-2022.10.0/lib/system/uniproton/sleep.h libmetal/lib/system/uniproton/sleep.h +--- libmetal-2022.10.0/lib/system/uniproton/sleep.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/sleep.h 2023-02-22 16:55:06.000000000 +0800 +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/sleep.h ++ * @brief Uniproton sleep primitives for libmetal. ++ */ ++ ++#ifndef __METAL_SLEEP__H__ ++#error "Include metal/sleep.h instead of metal/uniproton/sleep.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_SLEEP__H__ ++#define __METAL_UNIPROTON_SLEEP__H__ ++ ++#include "prt_task.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++static inline int __metal_sleep_usec(unsigned int usec) ++{ ++ return PRT_TaskDelay((U32)(usec / 1000)); ++} ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_SLEEP__H__ */ +diff -uparN libmetal-2022.10.0/lib/system/uniproton/sys.h libmetal/lib/system/uniproton/sys.h +--- libmetal-2022.10.0/lib/system/uniproton/sys.h 1970-01-01 08:00:00.000000000 +0800 ++++ libmetal/lib/system/uniproton/sys.h 2022-12-26 11:25:18.000000000 +0800 +@@ -0,0 +1,39 @@ ++/* ++ * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * @file uniproton/sys.h ++ * @brief Uniproton system primitives for libmetal. ++ */ ++ ++#ifndef __METAL_SYS__H__ ++#error "Include metal/sys.h instead of metal/uniproton/sys.h" ++#endif ++ ++#ifndef __METAL_UNIPROTON_SYS__H__ ++#define __METAL_UNIPROTON_SYS__H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define METAL_INIT_DEFAULTS \ ++{ \ ++ .log_handler = metal_default_log_handler, \ ++ .log_level = METAL_LOG_INFO, \ ++} ++ ++/** Structure of libmetal runtime state. */ ++struct metal_state { ++ /** Common (system independent) data. */ ++ struct metal_common_state common; ++}; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __METAL_UNIPROTON_SYS__H__ */ diff --git a/demos/raspi4/component/UniProton-patch-for-openamp.patch b/demos/raspi4/component/UniProton-patch-for-openamp.patch new file mode 100644 index 0000000..d4f0c31 --- /dev/null +++ b/demos/raspi4/component/UniProton-patch-for-openamp.patch @@ -0,0 +1,61 @@ +diff -uparN open-amp-2022.10.1/cmake/depends.cmake open-amp/cmake/depends.cmake +--- open-amp-2022.10.1/cmake/depends.cmake 2022-12-13 11:21:05.000000000 +0800 ++++ open-amp/cmake/depends.cmake 2023-02-24 16:36:38.000000000 +0800 +@@ -1,5 +1,5 @@ + if (WITH_LIBMETAL_FIND) +- find_package (Libmetal REQUIRED) ++ #find_package (Libmetal REQUIRED) + collect (PROJECT_INC_DIRS "${LIBMETAL_INCLUDE_DIR}") + collect (PROJECT_LIB_DIRS "${LIBMETAL_LIB_DIR}") + collect (PROJECT_LIB_DEPS "${LIBMETAL_LIB}") +diff -uparN open-amp-2022.10.1/cmake/platforms/uniproton_arm64_gcc.cmake open-amp/cmake/platforms/uniproton_arm64_gcc.cmake +--- open-amp-2022.10.1/cmake/platforms/uniproton_arm64_gcc.cmake 1970-01-01 08:00:00.000000000 +0800 ++++ open-amp/cmake/platforms/uniproton_arm64_gcc.cmake 2023-02-20 14:24:50.000000000 +0800 +@@ -0,0 +1,14 @@ ++#cross-compilation config ++ ++set(CMAKE_SYSTEM_PROCESSOR arm) ++set(PROJECT_SYSTEM uniproton) ++ ++set(CMAKE_C_COMPILER_WORKS 1) ++set(CMAKE_CXX_COMPILER_WORKS 1) ++ ++set(CROSS_PREFIX "/opt/buildtools/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/aarch64-none-elf-" CACHE STRING "") ++set(CMAKE_C_COMPILER "${CROSS_PREFIX}gcc" CACHE STRING "") ++set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE STRING "") ++set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER CACHE STRING "") ++set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER CACHE STRING "") ++# vim: expandtab:ts=2:sw=2:smartindent +diff -uparN open-amp-2022.10.1/CMakeLists.txt open-amp/CMakeLists.txt +--- open-amp-2022.10.1/CMakeLists.txt 2022-12-13 11:21:05.000000000 +0800 ++++ open-amp/CMakeLists.txt 2023-02-24 16:27:30.000000000 +0800 +@@ -6,7 +6,8 @@ endif() + if (POLICY CMP0077) + cmake_policy(SET CMP0077 NEW) + endif() +- ++include_directories(../../build/libmetal/output/usr/local/include ../../component/open-amp/lib/include ../../include ../../config) ++set (CMAKE_SYSTEM_NAME Uniproton) + set (OPENAMP_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + set (OPENAMP_BIN_ROOT "${CMAKE_CURRENT_BINARY_DIR}") + +diff -uparN open-amp-2022.10.1/lib/remoteproc/rsc_table_parser.c open-amp/lib/remoteproc/rsc_table_parser.c +--- open-amp-2022.10.1/lib/remoteproc/rsc_table_parser.c 2022-12-13 11:21:05.000000000 +0800 ++++ open-amp/lib/remoteproc/rsc_table_parser.c 2023-02-24 16:16:20.000000000 +0800 +@@ -144,6 +144,8 @@ int handle_vdev_rsc(struct remoteproc *r + + num_vrings = vdev_rsc->num_of_vrings; + for (i = 0; i < num_vrings; i++) { ++ struct fw_rsc_vdev_vring *vring_rsc; ++ + vring_rsc = &vdev_rsc->vring[i]; + notifyid = vring_rsc->notifyid; + notifyid = remoteproc_allocate_id(rproc, +diff -uparN open-amp-2022.10.1/VERSION open-amp/VERSION +--- open-amp-2022.10.1/VERSION 2022-12-13 11:21:05.000000000 +0800 ++++ open-amp/VERSION 2023-02-24 15:51:04.000000000 +0800 +@@ -1,3 +1,3 @@ + VERSION_MAJOR = 1 + VERSION_MINOR = 3 +-VERSION_PATCH = 1 ++VERSION_PATCH = 0 diff --git a/demos/raspi4/config/CMakeLists.txt b/demos/raspi4/config/CMakeLists.txt new file mode 100644 index 0000000..ab9f478 --- /dev/null +++ b/demos/raspi4/config/CMakeLists.txt @@ -0,0 +1,2 @@ +set(SRCS prt_config.c) +add_library(config OBJECT ${SRCS}) diff --git a/demos/raspi4/config/prt_buildef.h b/demos/raspi4/config/prt_buildef.h new file mode 100644 index 0000000..b6597d7 --- /dev/null +++ b/demos/raspi4/config/prt_buildef.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: the common part buildef.h + */ +#ifndef PRT_BUILDEF_H +#define PRT_BUILDEF_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define OS_ARCH_ARMV8 + +#define OS_GIC_VER 2 + +#ifndef OS_HARDWARE_PLATFORM +#define OS_HARDWARE_PLATFORM OS_ARMV8 +#endif + +#ifndef OS_CPU_TYPE +#define OS_CPU_TYPE OS_RASPI4 +#endif + +#define OS_MAX_CORE_NUM 4 + +#define OS_THIS_CORE 3 + +#ifndef OS_BYTE_ORDER +#define OS_BYTE_ORDER OS_LITTLE_ENDIAN +#endif + +#define OS_CACHE_LINE_SIZE 64 + +#define OS_OPTION_EVENT + +#define OS_OPTION_QUEUE + +#define OS_OPTION_HWI_PRIORITY + +#define OS_OPTION_HWI_ATTRIBUTE + +#define OS_OPTION_SYS_TIME_USR + +#define OS_OPTION_TASK + +#define OS_OPTION_TASK_DELETE + +#define OS_OPTION_TASK_SUSPEND + +#define OS_OPTION_TASK_INFO + +#define OS_OPTION_TASK_YIELD + +#define OS_TSK_PRIORITY_HIGHEST 0 + +#define OS_TSK_PRIORITY_LOWEST 63 + +#define OS_TSK_NUM_OF_PRIORITIES 64 + +#define OS_TSK_CORE_BYTES_IN_PID 2 + +#define OS_OPTION_TICK + +#define OS_OPTION_CPUP_WARN + +#define OS_OPTION_RND + +#define OS_OPTION_POSIX + +#define OS_POSIX_TYPE_NEWLIB + +#define OS_OPTION_OPENAMP + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +/* common macros's definitions */ +#include "prt_buildef_common.h" + +#endif diff --git a/demos/raspi4/config/prt_config.c b/demos/raspi4/config/prt_config.c new file mode 100644 index 0000000..2dbe9d7 --- /dev/null +++ b/demos/raspi4/config/prt_config.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton的初始化C文件。 + */ +#include "prt_config_internal.h" + +OS_SEC_ALW_INLINE INLINE void OsConfigAddrSizeGet(uintptr_t addr, uintptr_t size, + uintptr_t *destAddr, uintptr_t *destSize) +{ + *destAddr = addr; + *destSize = size; +} + +U32 OsMemConfigReg(void) +{ + U32 ret; + + ret = OsFscMemInit(OS_MEM_FSC_PT_ADDR, OS_MEM_FSC_PT_SIZE); + if (ret != OS_OK) { + return ret; + } + + return OS_OK; +} + +U32 OsMemDefPtInit(void) +{ + return OS_OK; +} + +U32 OsMemConfigInit(void) +{ + /* 系统默认FSC内存分区初始化 */ + return OsMemDefPtInit(); +} + +U32 OsSystemReg(void) +{ + struct SysModInfo sysModInfo; + + sysModInfo.systemClock = OS_SYS_CLOCK; + sysModInfo.cpuType = OS_CPU_TYPE; + sysModInfo.sysTimeHook = OS_SYS_TIME_HOOK; +#if defined(OS_OPTION_HWI_MAX_NUM_CONFIG) + sysModInfo.hwiMaxNum = OS_HWI_MAX_NUM_CONFIG; +#endif + + return OsSysRegister(&sysModInfo); +} + +#if (OS_INCLUDE_SEM == YES) +U32 OsSemConfigReg(void) +{ + struct SemModInfo semModInfo; + + semModInfo.maxNum = OS_SEM_MAX_SUPPORT_NUM; + return OsSemRegister(&semModInfo); + +} +#endif + +#if (OS_INCLUDE_TASK == YES) +void OsTaskInfoSet(struct TskModInfo *taskModInfo) +{ + taskModInfo->maxNum = OS_TSK_MAX_SUPPORT_NUM; + taskModInfo->defaultSize = OS_TSK_DEFAULT_STACK_SIZE; + taskModInfo->idleStackSize = OS_TSK_IDLE_STACK_SIZE; + taskModInfo->magicWord = WORD_PACK((U32)OS_TSK_STACK_MAGIC_WORD); +} +#else +#error "OS_INCLUDE_TASK MUST BE YES! The SWI has been cut out,the task can not cut out." +#endif + +U32 OsHookConfigReg(void) +{ + struct HookModInfo hookModInfo; + + hookModInfo.maxNum[OS_HOOK_HWI_ENTRY] = OS_HOOK_HWI_ENTRY_NUM; + hookModInfo.maxNum[OS_HOOK_HWI_EXIT] = OS_HOOK_HWI_EXIT_NUM; + hookModInfo.maxNum[OS_HOOK_TSK_SWITCH] = OS_HOOK_TSK_SWITCH_NUM; + hookModInfo.maxNum[OS_HOOK_IDLE_PERIOD] = OS_HOOK_IDLE_NUM; + + return OsHookRegister(&hookModInfo); +} + +U32 OsSysConfigReg(void) +{ + U32 ret; + + ret = OsSystemReg(); + if (ret != OS_OK) { + return ret; + } + return OS_OK; +} + +#if (OS_INCLUDE_TICK == YES) +U32 OsTickConfigReg(void) +{ + struct TickModInfo tickModInfo; + + tickModInfo.tickPerSecond = OS_TICK_PER_SECOND; + tickModInfo.tickPriority = 0; + + return OsTickRegister(&tickModInfo); +} +#endif + +#if (OS_INCLUDE_TASK == YES) +U32 OsTskConfigReg(void) +{ + struct TskModInfo taskModInfo; + OsTaskInfoSet(&taskModInfo); + return OsTskRegister(&taskModInfo); +} +#endif + +#if (OS_INCLUDE_QUEUE == YES) +U32 OsQueueConfigReg(void) +{ + return OsQueueRegister(OS_QUEUE_MAX_SUPPORT_NUM); +} +#endif + +#if (OS_INCLUDE_CPUP == YES) +U32 OsCpupConfigReg(void) +{ + struct CpupModInfo cpupModInfo; + + cpupModInfo.cpupWarnFlag = (bool)OS_CONFIG_CPUP_WARN; + cpupModInfo.sampleTime = OS_CPUP_SAMPLE_INTERVAL; + cpupModInfo.warn = OS_CPUP_SHORT_WARN; + cpupModInfo.resume = OS_CPUP_SHORT_RESUME; + + return OsCpupRegister(&cpupModInfo); +} +#endif + +#if (OS_INCLUDE_TICK_SWTMER == YES) +U32 OsSwTmrConfigInit(void) +{ + return OsSwTmrInit(OS_TICK_SWITIMER_MAX_NUM); +} +#endif + +#if (OS_INCLUDE_CPUP == YES) +#if (OS_INCLUDE_TICK == NO) +#error "OS_INCLUDE_CPUP depend on OS_INCLUDE_TICK!" +#endif +U32 OsCpupConfigInit(void) +{ + U32 ret; + + ret = OsCpupInit(); + if (ret != OS_OK) { + return ret; + } + + if (OS_CONFIG_CPUP_WARN == YES) { +#if defined(OS_OPTION_CPUP_WARN) + OsCpupWarnInit(); +#else + return OS_ERRNO_SYS_NO_CPUP_WARN; +#endif + } + return OS_OK; +} +#endif + +#if (OS_INCLUDE_SEM == YES) +U32 OsSemConfigInit(void) +{ + return OsSemInit(); +} +#endif + +#if (OS_INCLUDE_TASK == YES) +U32 OsTskConfigInit(void) +{ + return OsTskInit(); +} +#endif + +static U32 OsHwiConfigReg(void) +{ +#if (OS_INCLUDE_GIC_BASE_ADDR_CONFIG == YES) + U32 ret; + ret = OsGicConfigRegister((uintptr_t)OS_GIC_BASE_ADDR, (uintptr_t)OS_GICR_OFFSET, (uintptr_t)OS_GICR_STRIDE); + if (ret != OS_OK) { + return ret; + } +#endif + return OS_OK; +} + +/* 系统初始化注册表 */ +struct OsModuleConfigInfo g_moduleConfigTab[] = { + /* {模块号, 模块注册函数, 模块初始化函数} */ + {OS_MID_SYS, {OsSysConfigReg, NULL}}, + {OS_MID_MEM, {OsMemConfigReg, OsMemConfigInit}}, + {OS_MID_HWI, {OsHwiConfigReg, OsHwiConfigInit}}, + {OS_MID_HARDDRV, {NULL, PRT_HardDrvInit}}, + {OS_MID_HOOK, {OsHookConfigReg, OsHookConfigInit}}, + {OS_MID_EXC, {NULL, OsExcConfigInit}}, +#if (OS_INCLUDE_TASK == YES) + {OS_MID_TSK, {OsTskConfigReg, OsTskConfigInit}}, +#endif +#if (OS_INCLUDE_TICK == YES) + {OS_MID_TICK, {OsTickConfigReg, OsTickConfigInit}}, +#endif + +#if (OS_INCLUDE_TICK_SWTMER == YES) + {OS_MID_SWTMR, {NULL, OsSwTmrConfigInit}}, +#endif + +#if (OS_INCLUDE_CPUP == YES) + {OS_MID_CPUP, {OsCpupConfigReg, OsCpupConfigInit}}, +#endif +#if (OS_INCLUDE_SEM == YES) + {OS_MID_SEM, {OsSemConfigReg, OsSemConfigInit}}, +#endif +#if (OS_INCLUDE_QUEUE == YES) + {OS_MID_QUEUE, {OsQueueConfigReg, OsQueueConfigInit}}, +#endif + {OS_MID_APP, {NULL, PRT_AppInit}}, + + {OS_MID_BUTT, {NULL, NULL}}, +}; + +/* + * 描述:OS模块注册、初始化运行函数 + */ +U32 OsModuleConfigRun(enum OsinitPhaseId initPhaseId, U32 initPhase) +{ + U32 idx = 0; + U32 ret = OS_OK; + while (g_moduleConfigTab[idx].moudleId != OS_MID_BUTT) { + if (g_moduleConfigTab[idx].moudleConfigFunc[initPhaseId] == NULL) { + idx++; + continue; + } + ret = g_moduleConfigTab[idx].moudleConfigFunc[initPhaseId](); + if (ret != OS_OK) { + break; + } + idx++; + } + return ret; +} +U32 OsRegister(void) +{ + return OsModuleConfigRun(OS_REGISTER_ID, OS_REGISTER_PHASE); +} + +/* + * 描述:OsInitialize阶段 + */ +U32 OsInitialize(void) +{ + return OsModuleConfigRun(OS_INIT_ID, OS_INITIALIZE_PHASE); +} + +/* + * 描述:OsStart阶段 + */ +U32 OsStart(void) +{ + U32 ret; + +#if (OS_INCLUDE_TICK == YES) + /* 表示系统在进行启动阶段,匹配MOUDLE_ID之后,标记进入TICK模块的启动 */ + ret = OsTickStart(); + if (ret != OS_OK) { + return ret; + } +#endif + +#if (OS_INCLUDE_TASK == YES) + /* 表示系统在进行启动阶段,匹配MOUDLE_ID之后,标记进入任务模块的启动 */ + ret = OsActivate(); +#else + ret = OS_OK; +#endif + + return ret; +} + +S32 OsConfigStart(void) +{ + U32 ret; + + OsHwInit(); + + /* OS模块注册 */ + ret = OsRegister(); + if (ret != OS_OK) { + return (S32)ret; + } + + /* OS模块初始化 */ + ret = OsInitialize(); + if (ret != OS_OK) { + return (S32)ret; + } + + /* OS启动调度 */ + ret = OsStart(); + if (ret != OS_OK) { + return (S32)ret; + } + + /* Execution should not reach this point */ + return (S32)OS_ERROR; +} diff --git a/demos/raspi4/config/prt_config.h b/demos/raspi4/config/prt_config.h new file mode 100644 index 0000000..ed96d54 --- /dev/null +++ b/demos/raspi4/config/prt_config.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton配置头文件,裁剪开关和配置项。 + */ +#ifndef PRT_CONFIG_H +#define PRT_CONFIG_H + +#include "prt_buildef.h" +#include "prt_typedef.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/* ***************************** 配置系统基本信息 ******************************* */ +/* 芯片主频 */ +#define OS_SYS_CLOCK 250000000 +/* 用户注册的获取系统时间的函数*/ +#define OS_SYS_TIME_HOOK NULL + +/* ***************************** 中断模块配置 ************************** */ +/* 硬中断最大支持个数 */ +#define OS_HWI_MAX_NUM_CONFIG 150 + +/* ***************************** 配置Tick中断模块 *************************** */ +/* Tick中断模块裁剪开关 */ +#define OS_INCLUDE_TICK YES +/* Tick中断时间间隔,tick处理时间不能超过1/OS_TICK_PER_SECOND(s) */ +#define OS_TICK_PER_SECOND 1000 + +/* ***************************** 配置定时器模块 ***************************** */ +/* 基于TICK的软件定时器裁剪开关 */ +#define OS_INCLUDE_TICK_SWTMER NO +/* 基于TICK的软件定时器最大个数 */ +#define OS_TICK_SWITIMER_MAX_NUM 32 + +/* ***************************** 配置任务模块 ******************************* */ +/* 任务模块裁剪开关 */ +#define OS_INCLUDE_TASK YES +/* 最大支持的任务数,最大共支持254个 */ +#define OS_TSK_MAX_SUPPORT_NUM 8 +/* 缺省的任务栈大小 */ +#define OS_TSK_DEFAULT_STACK_SIZE 0x1000 +/* IDLE任务栈的大小 */ +#define OS_TSK_IDLE_STACK_SIZE 0x1000 +/* 任务栈初始化魔术字,默认是0xCA,只支持配置一个字节 */ +#define OS_TSK_STACK_MAGIC_WORD 0xCA + +/* ***************************** 配置CPU占用率及CPU告警模块 **************** */ +/* CPU占用率模块裁剪开关 */ +#define OS_INCLUDE_CPUP NO +/* 采样时间间隔(单位tick),若其值大于0,则作为采样周期,否则两次调用PRT_CpupNow或PRT_CpupThread间隔作为周期 */ +#define OS_CPUP_SAMPLE_INTERVAL 10 +/* CPU占用率告警动态配置项 */ +#define OS_CONFIG_CPUP_WARN NO +/* CPU占用率告警阈值(精度为万分比) */ +#define OS_CPUP_SHORT_WARN 8500 +/* CPU占用率告警恢复阈值(精度为万分比) */ +#define OS_CPUP_SHORT_RESUME 7500 + +/* ***************************** 配置内存管理模块 ************************** */ +/* 用户可以创建的最大分区数,取值范围[0,253] */ +#define OS_MEM_MAX_PT_NUM 200 +/* 私有FSC内存分区起始地址 */ +#define OS_MEM_FSC_PT_ADDR (uintptr_t)&g_memRegion00[0] +/* 私有FSC内存分区大小 */ +#define OS_MEM_FSC_PT_SIZE 0x80000 + +/* ***************************** 配置信号量管理模块 ************************* */ +/* 信号量模块裁剪开关 */ +#define OS_INCLUDE_SEM YES + +/* 最大支持的信号量数 */ +#define OS_SEM_MAX_SUPPORT_NUM 10 + +/* ***************************** 配置队列模块 ******************************* */ +/* 队列模块裁剪开关 */ +#define OS_INCLUDE_QUEUE YES +/* 最大支持的队列数,范围(0,0xFFFF] */ +#define OS_QUEUE_MAX_SUPPORT_NUM 10 + +/* ************************* 钩子模块配置 *********************************** */ +/* 硬中断进入钩子最大支持个数, 范围[0, 255] */ +#define OS_HOOK_HWI_ENTRY_NUM 5 +/* 硬中断退出钩子最大支持个数, 范围[0, 255] */ +#define OS_HOOK_HWI_EXIT_NUM 5 +/* 任务切换钩子最大支持个数, 范围[0, 255] */ +#define OS_HOOK_TSK_SWITCH_NUM 8 +/* IDLE钩子最大支持个数, 范围[0, 255] */ +#define OS_HOOK_IDLE_NUM 4 + +extern U8 g_memRegion00[]; + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +#endif /* PRT_CONFIG_H */ diff --git a/demos/raspi4/config/prt_config_internal.h b/demos/raspi4/config/prt_config_internal.h new file mode 100644 index 0000000..e62b9d4 --- /dev/null +++ b/demos/raspi4/config/prt_config_internal.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: UniProton配置私有文件。 + */ +#ifndef PRT_CONFIG_INTERNAL_H +#define PRT_CONFIG_INTERNAL_H + +#include +#include "prt_config.h" +#include "prt_sys.h" +#include "prt_task.h" +#include "prt_sem.h" +#include "prt_tick.h" +#include "prt_exc.h" +#include "prt_cpup.h" +#include "prt_mem.h" +#include "prt_hook.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +#define WORD_PACK(val) (((val) << 24) | ((val) << 16) | ((val) << 8) | (val)) + +/* UniProton模块注册函数的声明 */ +extern U32 OsFscMemInit(U32 addr, U32 size); +extern U32 OsSysRegister(struct SysModInfo *modInfo); +extern U32 OsTickRegister(struct TickModInfo *modInfo); +extern U32 OsTskRegister(struct TskModInfo *modInfo); +extern U32 OsCpupRegister(struct CpupModInfo *modInfo); +extern U32 OsSemRegister(const struct SemModInfo *modInfo); +extern U32 OsHookRegister(struct HookModInfo *modInfo); + +extern U32 OsHwiConfigInit(void); +extern U32 OsTickConfigInit(void); +extern U32 OsTskInit(void); +extern U32 OsCpupInit(void); +extern void OsCpupWarnInit(void); +extern U32 OsExcConfigInit(void); +extern U32 OsSemInit(void); +extern U32 OsHookConfigInit(void); + +/* UniProton系统启动相关函数的声明 */ +extern void OsHwInit(void); +extern U32 OsActivate(void); +extern U32 OsTickStart(void); +extern U32 PRT_HardDrvInit(void); +extern void PRT_HardBootInit(void); +extern U32 PRT_AppInit(void); + +extern U32 OsQueueRegister(U16 maxQueue); +extern U32 OsQueueConfigInit(void); + +#if (OS_INCLUDE_TICK_SWTMER == YES) +extern U32 OsSwTmrInit(U32 maxTimerNum); +#endif + +enum OsinitPhaseId { + OS_REGISTER_ID = 0, + OS_INIT_ID, + OS_MOUDLE_CONFIG +}; +typedef U32 (*ConfigInitFunc)(void); +struct OsModuleConfigInfo { + enum MoudleId moudleId; + ConfigInitFunc moudleConfigFunc[OS_MOUDLE_CONFIG]; +}; +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +#endif /* PRT_CONFIG_INTERNAL_H */ diff --git a/demos/raspi4/include/.keep b/demos/raspi4/include/.keep new file mode 100644 index 0000000..74b2a0f --- /dev/null +++ b/demos/raspi4/include/.keep @@ -0,0 +1,10 @@ +# Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. +# +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. \ No newline at end of file diff --git a/demos/raspi4/libs/.keep b/demos/raspi4/libs/.keep new file mode 100644 index 0000000..74b2a0f --- /dev/null +++ b/demos/raspi4/libs/.keep @@ -0,0 +1,10 @@ +# Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. +# +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. \ No newline at end of file diff --git a/demos/raspi4/readme.txt b/demos/raspi4/readme.txt new file mode 100644 index 0000000..7d3f0dc --- /dev/null +++ b/demos/raspi4/readme.txt @@ -0,0 +1,10 @@ +本目录下放置的是UniProton实时部分版本。 + +├─apps # 基于UniProton实时OS编程的demo程序; +│ └─openamp # openamp示例程序; +├─bsp # 提供的板级驱动与OS对接; +├─build # 提供编译脚本编译出最终镜像; +├─component # 适配openamp框架patch文件,openamp源码下载存放路径; +├─config # 配置选项,供用户调整运行时参数; +├─include # UniProton实时部分提供的编程接口API; +└─libs # UniProton实时部分的静态库,build目录中的makefile示例已经将头文件和静态库的引用准备好,应用可直接使用; diff --git a/doc/UniProton_build.md b/doc/UniProton_build.md index 5525a08..2281eee 100644 --- a/doc/UniProton_build.md +++ b/doc/UniProton_build.md @@ -9,11 +9,14 @@ ## 1.2 安装编译器&构建器 - #### 安装GNU Arm Embedded Toolchain编译器。 1. 下载编译器. -- 当前开源版本只涉及32位,官方下载地址为:[GNU Arm Embedded Toolchain编译器](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads),指定版本:10-2020-q4-major。 +- cortex_m4版本编译器,官方下载地址为:[GNU Arm Embedded Toolchain编译器](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads),指定版本:10-2020-q4-major。 +- armv8版本编译器,官方下载地址为:[gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz](https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz) 2. 解压编译器. - 可以参考如下命令完成解压: -
+``` tar -xvf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 -C /opt/buildtools + tar -xvf gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz -C /opt/buildtools +``` ## 1.3 安装Cmake 1. 通过官网进行下载[Cmake](https://cmake.org/download/),下载指定版本3.20.5 @@ -105,10 +108,10 @@ # 二、提供镜像,用户自行下载 1. 在虚拟机操作命令: - `docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/uniproton:v001` + `docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/uniproton:v002` - 执行完成之后,创建容器并进入(默认挂载当前执行命令的目录为容器内的/home/uniproton目录) - `docker run -it -v $(pwd):/home/uniproton swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/uniproton:v001` + `docker run -it -v $(pwd):/home/uniproton swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/uniproton:v002` 2. 下载代码 - 下载UniProton代码 `git clone https://gitee.com/openeuler/UniProton.git` diff --git a/doc/demoUsageGuide/RASPI4_demo_usage_guide.md b/doc/demoUsageGuide/RASPI4_demo_usage_guide.md new file mode 100644 index 0000000..1e13bfe --- /dev/null +++ b/doc/demoUsageGuide/RASPI4_demo_usage_guide.md @@ -0,0 +1,71 @@ +## 开发环境说明 +开发平台:armv8 + +芯片型号:bcm2711 + +OS版本信息:UniProton 22.03 + +集成开发环境:UniProton-docker + +### 实现过程 +以RASPI4 demo为例:[demo目录结构](../demos/RASPI4/readme.txt) +
    +
  1. 进入到用户的工作目录,这里假设为/workspace/UniProton。
  2. +
  3. 将UniProton的源码放在/workspace/UniProton目录下。
  4. +
  5. 参考[编译指导](./UniProton_build.md) 准备编译环境以及libboundscheck库下载。
  6. +
  7. 编译生成的libRASPI4.a文件和libCortexMXsec_c.lib文件在UniProton/output/UniProton/lib/raspi4/目录下。将这两个静态库文件拷贝到demos/RASPI4/libs目录下。
  8. +
  9. 将UniProton/src/include目录下的头文件拷贝到demos/RASPI4/include目录下。
  10. +
  11. 可以通过修改demos/RASPI4/config目录下的prt_config.c和prt_config.h以适配用户功能,prt_config.h可配置os功能开关,按需裁剪。
  12. +
  13. demos/RASPI4/bsp目录下可以新增板级驱动代码,demos/RASPI4/build目录下配置编译构建相关内容,raspi4.ld为链接文件,根据单板内存地址等修改适配。
  14. +
  15. 代码修改完成后,适配cmake,最后在build目录下运行sh build_app.sh即可在同级目录下生成RASPI4可执行二进制文件。
  16. +
  17. 加载到单板上运行可执行文件RASPI4。
  18. +
+ +### RASPI4 示例程序 +RASPI4 示例程序在demos/RASPI4/apps/openamp目录下,main.c文件主要用于系统初始化,rpmsg_backend.c文件主要用于openamp后端资源的初始化,rpmsg_service.c文件主要用于openamp的前端应用。 + +### openamp使用指导 & 结果验证 +**材料准备** +
  • 1、上述编译获取到的RASPI4可执行二进制文件
  • +
  • 2、对应版本的mcs_km.ko、rpmsg_main,libmetal、libopen_amp、libsysfs的动态库(具体构建过程参考https://gitee.com/openeuler/mcs) +
  • 3、刷写好对应openEuler镜像的树莓派单板(具体刷写过程参考https://gitee.com/openeuler/raspberry)
  • +**使用指导** +
  • 1、将上述1和2的材料通过ssh传输到树莓派单板上,这里假设传到/root/mcsdir目录。
  • +
  • 2、通过chmod +x rpmsg_main添加可执行权限
  • +
  • 3、将libmetal.so\*、libopen_amp.so\*复制到/usr/lib64目录下,将libsysfs.so复制到/lib64目录下
  • +
  • 4、进入/root/mcsdir目录依次执行 + + insmod mcs_km.ko + + # 执行rpmsg_main, + # -c cpu 指定在哪个cpu拉起二进制文件 + # -t RASPI4.bin 可执行二进制文件 + # -a address 指定二进制文件的加载地址 + ./rpmsg_main -c 3 -t RASPI4.bin -a 0x7a000000 +
  • +
  • 5、运行后,根据提示使用对应的pty设备和UniProton进行通信: + + raspberrypi4-64 ~ # insmod mcs_km.ko + raspberrypi4-64 ~ # ./rpmsg_main -c 3 -t RASPI4.bin -a 0x7a000000 + cpu:3, ld:7a000000, entry:7a000000, path:RASPI4.bin + mcs fd:3 + + Initialize the virtio, virtqueue and rpmsg device + virt add:0x7f8b700000, status_reg:0x7f8b700000, tx:0x7f8b72c000, rx:0x7f8b728000, mempool:0x7f8b704000 + number of services: 1 + start client os + pty master fd is :4 + pls open /dev/pts/1 to talk with client OS + pty_thread for uart is runnning + pty master fd is :5 + pls open /dev/pts/2 to talk with client OS + pty_thread for console is runnning + found matched endpoint, creating console with id:2 in host os + +如上所示,接着在另一个ssh窗口中,运行screen /dev/pts/2,此处在该窗口中,敲击回车即可触发demo程序。 +
  • + +可以在screen界面上看到输出结果如下: +``` +hello, UniProton! +``` \ No newline at end of file diff --git a/doc/design/architecture_design.md b/doc/design/architecture_design.md index 39bc999..80c434e 100644 --- a/doc/design/architecture_design.md +++ b/doc/design/architecture_design.md @@ -17,6 +17,14 @@ UniProton系统由Mem、Arch、Kernel、IPC、OM五大子系统构成,Mem、Ar | cmake | common | build_auxiliary_script | 转换Kconfig文件为buildef.h脚本 | | | functions | | cmake的公共功能函数 | | | tool_chain | | 编译器和编译选项配置文件 | +| demos | helloworld | apps | 示例程序的main函数文件以及业务代码 | +| | | bsp | 板级驱动适配代码 | +| | | build | demo构建及链接脚本 | +| | | config | 用户配置文件,功能宏定制头文件 | +| | | include | src/include/uapi及posix目录下头文件拷贝目录 | +| | | libs | 源码编译静态库文件存放目录 | +| | Hi3093 | | 与helloworld demo类似,详见对应目录下的readme文件 | +| | RASPI4 | | 与helloworld demo类似,详见对应目录下的readme文件 | | doc | | | 项目配置、规范、协议等文档 | | | design | | UniProton系统架构和特性说明 | | platform | | | libboundscheck使用说明 | @@ -27,13 +35,18 @@ UniProton系统由Mem、Arch、Kernel、IPC、OM五大子系统构成,Mem、Ar | | | config | 用户配置功能宏开关 | | | core | ipc | 事件、队列、信号量等功能 | | | | kernel | 任务、中断、异常、软件定时器等功能 | +| | fs | littlefs | littlefs适配层代码,不包含完整littlefs代码 | +| | | vfs | 文件系统vfs层接口代码 | | | include | uapi | 对外头文件 | +| | | posix | posix接口头文件 | | | mem | | 内存管理基本功能 | | | | fsc | 内存管理FSC算法代码 | | | | include | 内存管理头文件 | +| | net | lwip-2.1 | lwip适配层代码,不包含完整lwip代码 | | | om | cpup | cpu占用率统计功能 | | | | err | 错误处理功能 | | | | hook | 钩子函数功能 | | | | include | 系统管理头文件 | +| | osal | posix | posix功能实现源码 | | | security | rnd | 随机化功能 | -| | utility | lib | 公共库函数 | \ No newline at end of file +| | utility | lib | 公共库函数 | diff --git a/doc/getting_started.md b/doc/getting_started.md index f3b889c..a07c9bb 100644 --- a/doc/getting_started.md +++ b/doc/getting_started.md @@ -4,74 +4,128 @@ ## 开发环境说明 开发平台:cortex_m4 -OS版本信息:Linux +芯片型号:stm32f407 + +OS版本信息:UniProton 22.03 + 集成开发环境:UniProton-docker + ### 实现过程 +以helloworld demo为例:[demo目录结构](../demos/helloworld/readme.txt)
    1. 进入到用户的工作目录,这里假设为/workspace/UniProton。
    2. 将UniProton的源码放在/workspace/UniProton目录下。
    3. -
    4. 在docker环境中搭建工程。
    5. -
    6. 配置链接器配置文件(.lds文件)。
    7. -
    8. 配置功能模块,用户需要按照自己实际使用模块配置功能模块。
    9. -
    10. 在该工程下规划各开发模块的目录结构,如在/UniProton/src/config/prt_config.c文件中实现用户程序。
    11. -
    12. 在docker中编译整个工程,编译完成后在/UniProton/output目录下生成可执行文件hello。
    13. -
    14. 加载到单板上运行可执行文件hello。
    15. +
    16. 参考[编译指导](./UniProton_build.md) 准备编译环境以及libboundscheck库下载。
    17. +
    18. 编译生成的libCortexM4.a文件在UniProton/output/UniProton/lib/cortex_m4/目录下,生成的libCortexMXsec_c.lib在UniProton/output/libboundscheck/lib/cortex_m4/目录下。将这两个静态库文件拷贝到demos/helloworld/libs目录下。
    19. +
    20. 将UniProton/src/include目录下的头文件拷贝到demos/helloworld/include目录下。
    21. +
    22. 将UniProton/src/config目录和UniProton/build/uniproton_config/config_m4目录下的文件拷贝到demos/helloworld/config目录下,并修改prt_config.c以及prt_config.h以适配用户功能,prt_config.h可配置os功能开关,按需裁剪。
    23. +
    24. demos/helloworld/bsp目录下可以新增板级驱动代码,demos/helloworld/build目录下配置编译构建相关内容,examples.ld为链接文件,根据单板内存地址等修改适配。
    25. +
    26. 代码修改完成后,适配cmake,最后在build目录下运行sh build.sh即可在同级目录下生成helloworld可执行二进制文件。
    27. +
    28. 加载到单板上运行可执行文件helloworld。
    ### Hello World 示例程序 在main.c文件中编写Hello World示例程序,如参考内容如下(如前所述,PRT_HardBootInit/PRT_HardDrvInit接口中添加用户自定义硬件模块初始化程序,PRT_AppInit接口中添加用户业务代码): ```c -#include "prt_task.h" +#include +#include +#include +#include +#include "securec.h" +#include "rtt_viewer.h" #include "prt_config.h" +#include "prt_config_internal.h" +#include "prt_clk.h" +#include "test.h" -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif /* __cpluscplus */ -#endif /* __cpluscplus */ +void helloworld_task(U32 uwParam1, U32 uParam2, U32 uwParam3, U32 uwParam4) +{ + printf("hello world!\n"); + while (1) { + PRT_TaskDelay(10); + } -U32 PRT_HardDrvInit(void) -{ - return OS_OK; + return; } -void PRT_HardBootInit() -{ -} -void OsTskUser(void) -{ - printf("\n\r Hello World !\n\r"); -} - U32 PRT_AppInit(void) { U32 ret; - TskHandle taskId; - struct TskInitParam taskParam; + TskHandle taskPid; + struct TskInitParam stInitParam = {helloworld_task, 10, 0, {0}, 0x500, "TaskA", 0}; - taskParam.taskEntry = (TskEntryFunc)OsTskUser; - taskParam.stackSize = 0x800; - taskParam.name = "uniUserTask"; - taskParam.taskPrio = OS_TSK_PRIORITY_05; - taskParam.stackAddr = 0; - - ret = PRT_TaskCreate(&taskId, &taskParam); - if (ret != OS_OK) { + ret = PRT_TaskCreate(&taskPid, &stInitParam); + if (ret) { return ret; } - + + ret = PRT_TaskResume(taskPid); + if (ret) { + return ret; + } + return OS_OK; } - -#ifdef __cplusplus -#if __cplusplus + +U32 PRT_HardDrvInit(void) +{ + RttViewerInit(); + RttViewerModeSet(0, RTT_VIEWER_MODE_BLOCK_IF_FIFO_FULL); + + return OS_OK; } -#endif /* __cpluscplus */ -#endif /* __cpluscplus */ + +U32 g_testRandStackProtect; +void OsRandomSeedInit(void) +{ +#if defined(OS_OPTION_RND) + U32 ret; + U32 seed; + seed = PRT_ClkGetCycleCount64(); + g_testRandStackProtect = rand_r(&seed); + ret = PRT_SysSetRndNum(OS_SYS_RND_STACK_PROTECT,g_testRandStackProtect); +#endif +} + +void OsGlobalDataInit(void) +{ +} + +void PRT_HardBootInit(void) +{ + OsGlobalDataInit(); + OsRandomSeedInit(); +} + +U32 PRT_Printf(const char *format, ...) +{ + va_list vaList; + char buff[0x200] = { 0 }; + S32 count; + U32 ret; + + va_start(vaList, format); + count = vsprintf_s(buff, 0x200, format, vaList); + va_end(vaList); + + if (count == -1) { + return OS_ERROR; + } + + RttViewerWrite(0, buff, count); + + return count; +} + +S32 main(void) +{ + return OsConfigStart(); +} + ``` ### 结果验证 -在docker中编译整个工程后生成的可执行文件hello下载到单板上运行,输出结果如下: +在docker环境中使用demos/helloworld/build/build_app.sh脚本编译整个工程后生成的可执行文件helloworld加载载到单板上运行,单板连接arm仿真器,打开jlink软件,可以在软件界面上看到输出结果如下: ``` -Hello world! +hello world! ``` \ No newline at end of file diff --git a/platform/libboundscheck/.keep b/platform/libboundscheck/.keep index e69de29..74b2a0f 100644 --- a/platform/libboundscheck/.keep +++ b/platform/libboundscheck/.keep @@ -0,0 +1,10 @@ +# Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. +# +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. \ No newline at end of file diff --git a/platform/libboundscheck/include/.keep b/platform/libboundscheck/include/.keep index e69de29..74b2a0f 100644 --- a/platform/libboundscheck/include/.keep +++ b/platform/libboundscheck/include/.keep @@ -0,0 +1,10 @@ +# Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. +# +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. \ No newline at end of file diff --git a/platform/libboundscheck/src/.keep b/platform/libboundscheck/src/.keep index e69de29..74b2a0f 100644 --- a/platform/libboundscheck/src/.keep +++ b/platform/libboundscheck/src/.keep @@ -0,0 +1,10 @@ +# Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. +# +# UniProton is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 26a04a3..5f1b38c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,7 @@ add_subdirectory(arch) add_subdirectory(core) add_subdirectory(mem) add_subdirectory(om) +add_subdirectory(osal) add_subdirectory(security) add_subdirectory(utility) diff --git a/src/arch/CMakeLists.txt b/src/arch/CMakeLists.txt index 9f4db84..c6f8832 100644 --- a/src/arch/CMakeLists.txt +++ b/src/arch/CMakeLists.txt @@ -1 +1,4 @@ add_subdirectory(cpu) +if(${CONFIG_OS_ARCH_ARMV8}) + add_subdirectory(drv) +endif() diff --git a/src/arch/Kconfig b/src/arch/Kconfig index 6e472f2..8bc9d5a 100644 --- a/src/arch/Kconfig +++ b/src/arch/Kconfig @@ -13,6 +13,7 @@ config OS_CPU_TYPE config OS_MAX_CORE_NUM int "The maxinum number of cores" + default 4 if INTERNAL_OS_PLATFORM_ARMV8_AX default 1 if INTERNAL_OS_PLATFORM_M4 config INTERNAL_OS_BYTE_ORDER_LE diff --git a/src/arch/cpu/CMakeLists.txt b/src/arch/cpu/CMakeLists.txt index 0b54372..9176fee 100644 --- a/src/arch/cpu/CMakeLists.txt +++ b/src/arch/cpu/CMakeLists.txt @@ -1,3 +1,6 @@ if(${CONFIG_OS_ARCH_ARMV7_M}) add_subdirectory(armv7-m) endif() +if(${CONFIG_OS_ARCH_ARMV8}) + add_subdirectory(armv8) +endif() \ No newline at end of file diff --git a/src/arch/cpu/armv7-m/common/CMakeLists.txt b/src/arch/cpu/armv7-m/common/CMakeLists.txt index 0e58768..d719c82 100644 --- a/src/arch/cpu/armv7-m/common/CMakeLists.txt +++ b/src/arch/cpu/armv7-m/common/CMakeLists.txt @@ -2,4 +2,4 @@ add_subdirectory(boot) add_subdirectory(exc) add_subdirectory(hwi) add_subdirectory(tick) -add_library(prt_port OBJECT prt_port.c) \ No newline at end of file +add_library_ex(prt_port.c) \ No newline at end of file diff --git a/src/arch/cpu/armv7-m/common/boot/CMakeLists.txt b/src/arch/cpu/armv7-m/common/boot/CMakeLists.txt index 0ef700d..3e33b12 100644 --- a/src/arch/cpu/armv7-m/common/boot/CMakeLists.txt +++ b/src/arch/cpu/armv7-m/common/boot/CMakeLists.txt @@ -1 +1 @@ -add_library(prt_hw_boot OBJECT prt_hw_boot.c) +add_library_ex(prt_hw_boot.c) diff --git a/src/arch/cpu/armv7-m/common/exc/CMakeLists.txt b/src/arch/cpu/armv7-m/common/exc/CMakeLists.txt index e61305b..a3a408b 100644 --- a/src/arch/cpu/armv7-m/common/exc/CMakeLists.txt +++ b/src/arch/cpu/armv7-m/common/exc/CMakeLists.txt @@ -1 +1 @@ -add_library(prt_exc OBJECT prt_exc.c) +add_library_ex(prt_exc.c) diff --git a/src/arch/cpu/armv7-m/common/hwi/CMakeLists.txt b/src/arch/cpu/armv7-m/common/hwi/CMakeLists.txt index b50e7cf..f14c34d 100644 --- a/src/arch/cpu/armv7-m/common/hwi/CMakeLists.txt +++ b/src/arch/cpu/armv7-m/common/hwi/CMakeLists.txt @@ -1,2 +1,2 @@ -add_library(prt_hwi OBJECT prt_hwi.c) -add_library(prt_vi_dispatch OBJECT prt_vi_dispatch.c) +add_library_ex(prt_hwi.c) +add_library_ex(prt_vi_dispatch.c) diff --git a/src/arch/cpu/armv7-m/common/os_cpu_armv7_m_external.h b/src/arch/cpu/armv7-m/common/os_cpu_armv7_m_external.h index 7542c54..3817195 100644 --- a/src/arch/cpu/armv7-m/common/os_cpu_armv7_m_external.h +++ b/src/arch/cpu/armv7-m/common/os_cpu_armv7_m_external.h @@ -109,11 +109,6 @@ OS_SEC_ALW_INLINE INLINE U32 OsGetHwThreadId(void) return 0x0U; } -OS_SEC_ALW_INLINE INLINE uintptr_t OsMemAddrToUncache(uintptr_t addr) -{ - return addr; -} - extern U32 OsGetSp(void); extern U32 OsIntNumGet(void); extern void OsTaskSwitch(void); @@ -137,7 +132,10 @@ OS_SEC_ALW_INLINE INLINE uintptr_t OsTskGetInstrAddr(uintptr_t addr) return ((struct TagHwContext *)addr)->pc; } -#define OS_SPIN_LOCK_INIT(lockVar) +OS_SEC_ALW_INLINE INLINE void OsSpinLockInitInner(volatile uintptr_t *lockVar) +{ + (void)lockVar; +} #if (OS_HARDWARE_PLATFORM == OS_CORTEX_M4) #include "../cortex-m4/prt_cpu_m4_external.h" diff --git a/src/arch/cpu/armv7-m/common/tick/CMakeLists.txt b/src/arch/cpu/armv7-m/common/tick/CMakeLists.txt index b5ea5fa..bf64c02 100644 --- a/src/arch/cpu/armv7-m/common/tick/CMakeLists.txt +++ b/src/arch/cpu/armv7-m/common/tick/CMakeLists.txt @@ -1,2 +1,2 @@ -add_library(prt_hw_tick OBJECT prt_hw_tick.c) -add_library(prt_hw_tick_minor OBJECT prt_hw_tick_minor.c) +add_library_ex(prt_hw_tick.c) +add_library_ex(prt_hw_tick_minor.c) diff --git a/src/arch/cpu/armv7-m/cortex-m4/CMakeLists.txt b/src/arch/cpu/armv7-m/cortex-m4/CMakeLists.txt index 30e6abd..95693bc 100644 --- a/src/arch/cpu/armv7-m/cortex-m4/CMakeLists.txt +++ b/src/arch/cpu/armv7-m/cortex-m4/CMakeLists.txt @@ -1,10 +1,6 @@ set(CMAKE_ASM_COMPILER_ID "ARMASM") -add_library(prt_hw OBJECT prt_hw.S) -set_target_properties(prt_hw PROPERTIES OUTPUT_NAME "prt_hw") #对目标文件重命名 -add_library(prt_hw_exc OBJECT prt_hw_exc.S) -set_target_properties(prt_hw_exc PROPERTIES OUTPUT_NAME "prt_hw_exc") #对目标文件重命名 -add_library(prt_dispatch OBJECT prt_dispatch.S) -set_target_properties(prt_dispatch PROPERTIES OUTPUT_NAME "prt_dispatch") #对目标文件重命名 -add_library(prt_vector OBJECT prt_vector.S) -set_target_properties(prt_vector PROPERTIES OUTPUT_NAME "prt_vector") #对目标文件重命名 -add_library(prt_div64 OBJECT prt_div64.c) \ No newline at end of file +add_library_ex(prt_hw.S) +add_library_ex(prt_hw_exc.S) +add_library_ex(prt_dispatch.S) +add_library_ex(prt_vector.S) +add_library_ex(prt_div64.c) \ No newline at end of file diff --git a/src/arch/cpu/armv7-m/cortex-m4/prt_vector.S b/src/arch/cpu/armv7-m/cortex-m4/prt_vector.S index 47d55fb..aad84f1 100644 --- a/src/arch/cpu/armv7-m/cortex-m4/prt_vector.S +++ b/src/arch/cpu/armv7-m/cortex-m4/prt_vector.S @@ -149,7 +149,9 @@ OsBoot: BL OsFpuInit LDR R0, =PRT_HardBootInit BLX R0 +#if defined(OS_OPTION_GUARD_STACK) InitChkGuardRnd R9, R10, R11 +#endif LDR R0, =main BX R0 diff --git a/src/arch/cpu/armv8/CMakeLists.txt b/src/arch/cpu/armv8/CMakeLists.txt new file mode 100644 index 0000000..688b5c8 --- /dev/null +++ b/src/arch/cpu/armv8/CMakeLists.txt @@ -0,0 +1,2 @@ +### armv8 通用模块 +add_subdirectory(common) diff --git a/src/arch/cpu/armv8/Kconfig b/src/arch/cpu/armv8/Kconfig new file mode 100644 index 0000000..c4e9473 --- /dev/null +++ b/src/arch/cpu/armv8/Kconfig @@ -0,0 +1,16 @@ +menu "ARMV8 Sepecfic Configuration" + +depends on (OS_ARCH_ARMV8) + +config INTERNAL_OS_PLATFORM_ARMV8_AX + bool + select INTERNAL_OS_BYTE_ORDER_LE + +choice + prompt "Cpu Type" + +config INTERNAL_OS_RASPI4 + bool "OS_RASPI4" + select INTERNAL_OS_PLATFORM_ARMV8_AX + +endchoice \ No newline at end of file diff --git a/src/arch/cpu/armv8/common/CMakeLists.txt b/src/arch/cpu/armv8/common/CMakeLists.txt new file mode 100644 index 0000000..73c54ee --- /dev/null +++ b/src/arch/cpu/armv8/common/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(boot) +add_subdirectory(cache) +add_subdirectory(exc) +add_subdirectory(hwi) +add_library_ex(prt_port.c) \ No newline at end of file diff --git a/src/arch/cpu/armv8/common/boot/CMakeLists.txt b/src/arch/cpu/armv8/common/boot/CMakeLists.txt new file mode 100644 index 0000000..83cc0a7 --- /dev/null +++ b/src/arch/cpu/armv8/common/boot/CMakeLists.txt @@ -0,0 +1,2 @@ +add_library_ex(prt_bss_init.c) +add_library_ex(prt_hw_boot.c) \ No newline at end of file diff --git a/src/arch/cpu/armv8/common/boot/prt_bss_init.c b/src/arch/cpu/armv8/common/boot/prt_bss_init.c new file mode 100644 index 0000000..45c4cf1 --- /dev/null +++ b/src/arch/cpu/armv8/common/boot/prt_bss_init.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: BSS初始化。 + */ +#include "prt_cpu_external.h" +/* + * 描述: BSS段初始化 + */ +INIT_SEC_L4_TEXT void OsBssInit(void) +{ + uintptr_t len = (uintptr_t)(&__bss_end__) - (uintptr_t)(&__bss_start__); + if (memset_s((void *)&__bss_start__, len, 0, len) != EOK) { + OS_GOTO_SYS_ERROR(); + } + + return; +} \ No newline at end of file diff --git a/src/arch/cpu/armv8/common/boot/prt_hw_boot.c b/src/arch/cpu/armv8/common/boot/prt_hw_boot.c new file mode 100644 index 0000000..5411f50 --- /dev/null +++ b/src/arch/cpu/armv8/common/boot/prt_hw_boot.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: 硬件相关的通用处理。 + */ +#include "prt_buildef.h" +#include "prt_attr_external.h" + +INIT_SEC_L4_TEXT void OsHwInit(void) +{ +} diff --git a/src/arch/cpu/armv8/common/cache/CMakeLists.txt b/src/arch/cpu/armv8/common/cache/CMakeLists.txt new file mode 100644 index 0000000..77ec3c2 --- /dev/null +++ b/src/arch/cpu/armv8/common/cache/CMakeLists.txt @@ -0,0 +1 @@ +add_library_ex(prt_cache.S) \ No newline at end of file diff --git a/src/arch/cpu/armv8/common/cache/prt_cache.S b/src/arch/cpu/armv8/common/cache/prt_cache.S new file mode 100644 index 0000000..b40d035 --- /dev/null +++ b/src/arch/cpu/armv8/common/cache/prt_cache.S @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: cache相关处理。 + */ + + .section .os.init.text, "ax" + + .global OsCacheConfigInit + .global OsCacheFlushDcache + .global OsCacheInvIcache + + .type OsCacheConfigInit, "function" + .type OsCacheFlushDcache, "function" + .type OsCacheInvIcache, "function" + +.macro GetCacheLineSize size, tmp + mrs \tmp, ctr_el0 + lsr \tmp, \tmp, #16 + and \tmp, \tmp, #0xf + mov \size, #4 + lsl \size, \size, \tmp +.endm + +OsCacheConfigInit: + mov w0, #0 + ret + +/* + * 描述:按地址范围进行DCache写回 + * 备注:当前仅用于动态加载模块 + */ +OsCacheFlushDcache: + GetCacheLineSize x2, x3 + sub x3, x2, #1 + add x1, x0, x1 + bic x0, x0, x3 +1: dc cvac, x0 /* Data Cache Clean by address to Point of Coherency */ + add x0, x0, x2 + cmp x0, x1 + b.lo 1b + dsb sy + ret + +/* + * 描述:按地址范围进行ICache无效 + * 备注:当前仅用于动态加载模块 + */ +OsCacheInvIcache: + GetCacheLineSize x2, x3 + sub x3, x2, #1 + add x1, x0, x1 + bic x0, x0, x3 +1: ic ivau, x0 /* I cache Invalidate by address to Point of Unification */ + add x0, x0, x2 + cmp x0, x1 + b.lo 1b + dsb sy + isb sy + ret + + .text diff --git a/src/arch/cpu/armv8/common/exc/CMakeLists.txt b/src/arch/cpu/armv8/common/exc/CMakeLists.txt new file mode 100644 index 0000000..6a1ca57 --- /dev/null +++ b/src/arch/cpu/armv8/common/exc/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library_ex(prt_exc.c) +add_library_ex(prt_hw_exc.S) +add_library_ex(prt_exc_init.c) \ No newline at end of file diff --git a/src/arch/cpu/armv8/common/exc/prt_exc.c b/src/arch/cpu/armv8/common/exc/prt_exc.c new file mode 100644 index 0000000..c9cdc35 --- /dev/null +++ b/src/arch/cpu/armv8/common/exc/prt_exc.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: 异常处理。 + */ +#include "prt_exc_internal.h" + +// 异常时获取当前任务的信息 +OS_SEC_BSS ExcTaskInfoFunc g_excTaskInfoGet; + +/* + * 描述: 获取异常前的线程信息 + */ +OS_SEC_ALW_INLINE INLINE void OsExcSetThreadInfo(struct ExcInfo *excInfo) +{ + U32 threadId = INVALIDPID; + struct TskInfo taskInfo = {0}; + + if (g_excTaskInfoGet != NULL) { + g_excTaskInfoGet(&threadId, &taskInfo); + } + + /* 记录发生异常时的线程ID,发生在任务和软中断中,此项具有意义,其他线程中,此项无意义 */ + excInfo->threadId = INVALIDPID; + + /* 设置异常前的线程类型 */ + if (OS_INT_COUNT > 0) { + excInfo->threadType = EXC_IN_HWI; + } else if ((UNI_FLAG & OS_FLG_TICK_ACTIVE) != 0) { + excInfo->threadType = EXC_IN_TICK; + } else if ((UNI_FLAG & OS_FLG_SYS_ACTIVE) != 0) { + excInfo->threadType = EXC_IN_SYS; + } else if ((UNI_FLAG & OS_FLG_BGD_ACTIVE) != 0) { + excInfo->threadType = EXC_IN_TASK; + if (OsTskMaxNumGet() > 0) { /* 任务存在时 */ + excInfo->threadId = threadId; + } + } else { /* OS_FLG_BGD_ACTIVE没有置位,代表此时还在系统进程中,没有进入业务线程 */ + excInfo->threadType = EXC_IN_SYS_BOOT; + } + + /* 任务栈栈底 */ + if (excInfo->threadType == EXC_IN_TASK) { + excInfo->stackBottom = TRUNCATE((taskInfo.topOfStack + taskInfo.stackSize), OS_EXC_STACK_ALIGN); + } +} + +/* + * 描述: 记录异常信息 + */ +INIT_SEC_L4_TEXT void OsExcSaveInfo(struct ExcInfo *excInfo, struct ExcRegInfo *regs) +{ + U64 cycle; + + /* 记录异常嵌套计数 */ + excInfo->nestCnt = CUR_NEST_COUNT; + + /* 记录os版本号 */ + if (strncpy_s(excInfo->osVer, sizeof(excInfo->osVer), PRT_SysGetOsVersion(), (sizeof(excInfo->osVer) - 1)) != EOK) { + OS_GOTO_SYS_ERROR(); + } + excInfo->osVer[OS_SYS_OS_VER_LEN - 1] = '\0'; + + /* 记录CPU ID */ + excInfo->coreId = 0x0U; + + /* 设置字节序 */ + /* 魔术字 */ + excInfo->byteOrder = OS_BYTE_ORDER; + + /* 记录CPU类型 */ + excInfo->cpuType = OsGetCpuType(); + + /* 记录CPU TICK值 */ + cycle = OsCurCycleGet64(); + excInfo->cpuTick.cntHi = OS_GET_64BIT_HIGH_32BIT(cycle); + excInfo->cpuTick.cntLo = (U32)cycle; + + /* 记录寄存器信息 */ + excInfo->regInfo = *regs; + + /* 记录异常前栈指针 */ + excInfo->sp = regs->sp; + + /* 记录异常前栈底,系统栈栈底 */ + excInfo->stackBottom = (uintptr_t)&__os_sys_sp_end; + + OsExcSetThreadInfo(excInfo); +} diff --git a/src/arch/cpu/armv8/common/exc/prt_exc_init.c b/src/arch/cpu/armv8/common/exc/prt_exc_init.c new file mode 100644 index 0000000..18c39b9 --- /dev/null +++ b/src/arch/cpu/armv8/common/exc/prt_exc_init.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: 异常处理(初始化相关)。 + */ +#include "prt_exc_internal.h" +#include "prt_err_external.h" + +/* + * 描述: 获取异常类型 + */ +static INIT_SEC_L4_TEXT U32 OsExcGetDefExctype(uintptr_t esr) +{ + U32 excCause; + union TagExcEsr excEsr; + + excEsr.esr = esr; + + switch ((U32)excEsr.bits.ec) { + case OS_EXC_ESR_UNDEF_INSTR: + /* fall through */ + case OS_EXC_ESR_UNDEF_INSTR + 1: + excCause = OS_EXCEPT_UNDEF_INSTR; + break; + case OS_EXC_ESR_PC_NOT_ALIGN: + excCause = OS_EXCEPT_PC_NOT_ALIGN; + break; + case OS_EXC_ESR_DATA_ABORT: + /* fall through */ + case OS_EXC_ESR_DATA_ABORT + 1: + excCause = OS_EXCEPT_DATA_ABORT; + break; + case OS_EXC_ESR_SP_INSTR: + excCause = OS_EXCEPT_SP_NOT_ALIGN; + break; + default: + excCause = OS_EXCEPT_ESR; + break; + } + return excCause; +} + +/* + * 描述: 记录异常原因 + */ +static INIT_SEC_L4_TEXT void OsExcSaveCause(uintptr_t esr) +{ + U32 preFatalErr; + U32 excCause; + struct ExcInfo *excInfo = OS_EXC_INFO_ADDR; + + /* 记录异常类型 */ + preFatalErr = OsFatalErrClr(); + if (preFatalErr == OS_EXC_DEFAULT_EXC_TYPE) { + excCause = OsExcGetDefExctype(esr); + } else { + excCause = OS_EXCEPT_FATALERROR; + } + + excInfo->excCause = excCause; + excInfo->fatalErrNo = preFatalErr; + return; +} + +/* + * 描述: EXC钩子处理函数 + */ +INIT_SEC_L4_TEXT void OsExcHookHandle(void) +{ + struct ExcInfo *excInfo = OS_EXC_INFO_ADDR; + + if (g_excModInfo.excepHook != NULL) { + (void)g_excModInfo.excepHook(excInfo); // 目前不支持异常返回 + } + + PRT_SysReboot(); +} + +/* + * 描述: FIQ异常处理 + */ +OS_SEC_ALW_INLINE INLINE void OsExcFiqProc(U32 excType) +{ + struct ExcInfo excInfo = {0}; + excInfo.excCause = excType; + + if (g_excModInfo.excepHook != NULL) { + (void)g_excModInfo.excepHook(&excInfo); + } + + PRT_SysReboot(); +} + +/* + * 描述: EXC模块的处理分发函数 + */ +INIT_SEC_L4_TEXT void OsExcHandleEntry(U32 excType, struct ExcRegInfo *excRegs) +{ + U32 coreID = THIS_CORE(); + struct ExcInfo *excInfo = OS_EXC_INFO_ADDR; + + UNI_FLAG |= (OS_FLG_HWI_ACTIVE | OS_FLG_EXC_ACTIVE); + if (excType == OS_EXCEPT_FIQ) { + OsExcFiqProc(excType); + return; + } + + OsExcSaveCause(excRegs->esr); + + CUR_NEST_COUNT++; + + /* 记录异常信息 */ + OsExcSaveInfo(excInfo, excRegs); + + /* 回调异常钩子函数 */ + OsExcHookHandle(); +} + +/* + * 描述: EXC模块的初始化 + */ +OS_SEC_L4_TEXT U32 OsExcConfigInit(void) +{ +#if defined(OS_OPTION_CDA) + OsCdaExcInit(); +#endif + return OS_OK; +} + +/* + * 描述: 切换到系统栈 + */ +INIT_SEC_L4_TEXT uintptr_t OsSwitchToSysStack(uintptr_t sp) +{ + uintptr_t sysStackHigh; + uintptr_t sysStackLow; + uintptr_t dstSp; + + sysStackHigh = OsGetSysStackEnd(); + sysStackLow = OsGetSysStackStart(); + if (sp <= sysStackHigh && sp >= sysStackLow) { + return sp; + } + + RUNNING_TASK->stackPointer = (void *)sp; + dstSp = sysStackHigh - sizeof(struct TskContext); + + if (memcpy_s((void *)dstSp, sizeof(struct TskContext), (void *)sp, sizeof(struct TskContext)) != EOK) { + OS_GOTO_SYS_ERROR(); + } + + return dstSp; +} diff --git a/src/arch/cpu/armv8/common/exc/prt_exc_internal.h b/src/arch/cpu/armv8/common/exc/prt_exc_internal.h new file mode 100644 index 0000000..195a464 --- /dev/null +++ b/src/arch/cpu/armv8/common/exc/prt_exc_internal.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: 异常模块内部头文件。 + */ +#ifndef PRT_EXC_INTERNAL_H +#define PRT_EXC_INTERNAL_H + +#include "prt_attr_external.h" +#include "prt_err_external.h" +#include "prt_sys_external.h" +#include "prt_cpu_external.h" +#include "prt_exc_external.h" +#include "prt_irq_external.h" +#include "prt_task_external.h" +#include "prt_hook_external.h" +#include "prt_mem_external.h" +#include "prt_sem_external.h" +#include "prt_task_external.h" +#include "prt_queue_external.h" +#include "prt_swtmr_external.h" +#include "prt_timer_external.h" + +/* + * 模块内宏定义 + */ +#define OS_EXC_DEFAULT_EXC_TYPE 0 + +#define OS_EXC_STACK_ALIGN 0x10U + +#define OS_EXC_ESR_UNDEF_INSTR 0x20U +#define OS_EXC_ESR_PC_NOT_ALIGN 0x22U +#define OS_EXC_ESR_DATA_ABORT 0x24U +#define OS_EXC_ESR_SP_INSTR 0x26U + +#define INVALIDPID 0xFFFFFFFFUL +#define INVALIDSTACKBOTTOM 0xFFFFFFFFUL + +/* + * 模块内结构体定义 + */ +/* information for esr */ +union TagExcEsr { + struct { + uintptr_t iss : 25; // bit[0:24] The Instruction specific syndrome field. + uintptr_t il : 1; // bit[25] 指令长度位,用于同步异常,0:16-bit; 0:32-bit + uintptr_t ec : 6; // bit[26:31] Exception class 标记错误原因 + uintptr_t res0 : 32; // bit[32:63] + } bits; + uintptr_t esr; +}; + +/* + * 模块内全局变量声明 + */ +extern U32 OsVectorTable(void); + +/* + * 模块内函数声明 + */ +extern void OsExcSaveInfo(struct ExcInfo *excInfo, struct ExcRegInfo *regs); + +#endif /* PRT_EXC_INTERNAL_H */ diff --git a/src/arch/cpu/armv8/common/exc/prt_hw_exc.S b/src/arch/cpu/armv8/common/exc/prt_hw_exc.S new file mode 100644 index 0000000..2afe550 --- /dev/null +++ b/src/arch/cpu/armv8/common/exc/prt_hw_exc.S @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: 异常处理的汇编部分。 + */ + +#include "prt_asm_cpu_external.h" + + .global OsExcHandleEntry + .type OsExcHandleEntry, function + .equ OS_TSKCONTEXT_SIZE, 0x120 + +// save x2~x30, xzr +.macro GENERAL_REGS_SAVE + stp x3, x2, [sp,#-16]! + stp x5, x4, [sp,#-16]! + stp x7, x6, [sp,#-16]! + stp x9, x8, [sp,#-16]! + stp x11, x10, [sp,#-16]! + stp x13, x12, [sp,#-16]! + stp x15, x14, [sp,#-16]! + stp x17, x16, [sp,#-16]! + stp x19, x18, [sp,#-16]! + stp x21, x20, [sp,#-16]! + stp x23, x22, [sp,#-16]! + stp x25, x24, [sp,#-16]! + stp x27, x26, [sp,#-16]! + stp x29, x28, [sp,#-16]! + stp xzr, x30, [sp,#-16]! +.endm + +.macro ELX_REGS_INIT + mov x10, xzr + mov x11, xzr + mov x12, xzr + mov x13, xzr + mov x14, xzr + mov x15, xzr + mov x16, xzr + mov x17, xzr + mov x18, xzr + mov x19, xzr +.endm + +.section .os.init.text, "ax" + + .globl OsSaveElxRegs + .type OsSaveElxRegs, @function + .align 4 +OsSaveElxRegs: + stp x18, x19, [sp,#-16]! + stp x16, x17, [sp,#-16]! + stp x14, x15, [sp,#-16]! + stp x12, x13, [sp,#-16]! + stp x10, x11, [sp,#-16]! + ret + + .globl OsExcDispatch + .type OsExcDispatch, @function + .align 4 +OsExcDispatch: + GENERAL_REGS_SAVE + + mrs x5, esr_el1 + mrs x4, far_el1 + mrs x3, spsr_el1 + mrs x2, elr_el1 + stp x4, x5, [sp,#-16]! + stp x2, x3, [sp,#-16]! + + mov x0, sp + + /* (X19-X29) These registers are saved in the callee frame. */ + mov x22, x1 // x22: save excType + /* 异常后又压栈了TskContext大小 */ + /* 记录异常发生现场时需要把这部分退栈回去 */ + add x21, sp, #OS_TSKCONTEXT_SIZE // x21: callee-save, x21=original sp + BL OsSwitchToSysStack + mov sp, x0 + + mrs x20, CurrentEL + mrs x19, vbar_el1 + mrs x18, sctlr_el1 + mrs x17, mair_el1 + mrs x16, tcr_el1 + mrs x15, ttbr1_el1 + mrs x14, ttbr0_el1 + stp x20, x21, [sp,#-16]! + stp x18, x19, [sp,#-16]! + stp x16, x17, [sp,#-16]! + stp x14, x15, [sp,#-16]! + + mov w0, w22 + mov x1, sp + bl OsExcHandleEntry + + sub x21, x21, #OS_TSKCONTEXT_SIZE + mov sp, x21 // x21=original sp + ldp x2, x3, [sp],#16 + add sp, sp, #16 // 跳过far, esr, HCR_EL2.TRVM==1的时候,EL1不能写far, esr + msr spsr_el1, x3 + msr elr_el1, x2 + dsb sy + isb + + ldp xzr, x30, [sp,#16] + ldp x29, x28, [sp],#16 + ldp x27, x26, [sp],#16 + ldp x25, x24, [sp],#16 + ldp x23, x22, [sp],#16 + ldp x21, x20, [sp],#16 + ldp x19, x18, [sp],#16 + ldp x17, x16, [sp],#16 + ldp x15, x14, [sp],#16 + ldp x13, x12, [sp],#16 + ldp x11, x10, [sp],#16 + ldp x9, x8, [sp],#16 + ldp x7, x6, [sp],#16 + ldp x5, x4, [sp],#16 + ldp x3, x2, [sp],#16 + ldp x1, x0, [sp],#16 + eret + + .text diff --git a/src/arch/cpu/armv8/common/hwi/CMakeLists.txt b/src/arch/cpu/armv8/common/hwi/CMakeLists.txt new file mode 100644 index 0000000..635a581 --- /dev/null +++ b/src/arch/cpu/armv8/common/hwi/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library_ex(prt_dispatch.S) +add_library_ex(prt_hwi.c) +add_library_ex(prt_vector.S) +add_library_ex(prt_reset_vector.S) \ No newline at end of file diff --git a/src/arch/cpu/armv8/common/hwi/prt_dispatch.S b/src/arch/cpu/armv8/common/hwi/prt_dispatch.S new file mode 100644 index 0000000..5b55d7f --- /dev/null +++ b/src/arch/cpu/armv8/common/hwi/prt_dispatch.S @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: 线程调度的汇编部分。 + */ +#include "prt_buildef.h" +#include "prt_asm_arm_external.h" + + .global g_sysStackHigh + .global OsHwiDispatch, OsMainSchedule + + .type OsMainSchedule, function + +// save x2~x30, xzr +.macro GENERAL_REGS_SAVE + stp x3, x2, [sp,#-16]! + stp x5, x4, [sp,#-16]! + stp x7, x6, [sp,#-16]! + stp x9, x8, [sp,#-16]! + stp x11, x10, [sp,#-16]! + stp x13, x12, [sp,#-16]! + stp x15, x14, [sp,#-16]! + stp x17, x16, [sp,#-16]! + stp x19, x18, [sp,#-16]! + stp x21, x20, [sp,#-16]! + stp x23, x22, [sp,#-16]! + stp x25, x24, [sp,#-16]! + stp x27, x26, [sp,#-16]! + stp x29, x28, [sp,#-16]! + stp xzr, x30, [sp,#-16]! +.endm + + .section .os.text, "ax" + +/* + * 描述: Task调度处理函数。 X0 is g_runningTask + */ + .globl OsTaskTrap + .type OsTaskTrap, @function + .align 4 + +OsTaskTrap: + LDR x1, =g_runningTask /* OsTaskTrap是函数调用过来,x0 x1寄存器是caller save,此处能直接使用 */ + LDR x0, [x1] /* x0 is the &g_pRunningTask->sp */ + + stp x1, x0, [sp,#-16]! + GENERAL_REGS_SAVE + + /* TskTrap需要保存CPSR,由于不能直接访问,需要拼接获取当前CPSR入栈 */ + mrs x3, DAIF /* CPSR:DAIF 4种事件的mask, bits[9:6] */ + mrs x2, NZCV /* NZCV:Condition flags, bits[31:28] */ + orr x3, x3, x2 + orr x3, x3, #(0x1U << 2) /* 当前的 exception level,bits[3:2] 00:EL0,01:El1,10:El2,11:EL3 */ + orr x3, x3, #(0x1U) /* 当前栈的选择,bits[0] 0:SP_EL0,1:SP_ELX */ + + mov x2, x30 // 用返回地址x30作为现场恢复点 + sub sp, sp, #16 // 跳过esr_el1, far_el1, 异常时才有用 + stp x2, x3, [sp,#-16]! + + // 存入SP指针到g_pRunningTask->sp + mov x1, sp + str x1, [x0] // x0 is the &g_pRunningTask->sp + + ldr x0, =g_sysStackHigh + ldr x0, [x0] + mov sp, x0 + B OsMainSchedule +loop1: + B loop1 + +/* + * 描述: hwi分发 + */ + .globl OsHwiDispatcher + .type OsHwiDispatcher, @function + .align 4 +OsHwiDispatcher: + GENERAL_REGS_SAVE + + mrs x3, spsr_el1 + mrs x2, elr_el1 + sub sp, sp, #16 // 跳过esr_el1, far_el1, 异常时才有用 + stp x2, x3, [sp,#-16]! + + MOV x0, SP + + BL OsHwiDispatch // 跳转C代码继续处理中断 + + // 中断嵌套,tick嵌套场景, 会从OsHwiDispatch返回 + b OsContextLoad + +/* + * 描述: void OsTskContextLoad(uintptr_t stackPointer) + */ + .globl OsTskContextLoad + .type OsTskContextLoad, @function + .align 4 +OsTskContextLoad: + ldr X0, [X0] + mov SP, X0 // X0 is stackPointer + +OsContextLoad: + ldp x2, x3, [sp],#16 + add sp, sp, #16 // 跳过far, esr, HCR_EL2.TRVM==1的时候,EL1不能写far, esr + msr spsr_el1, x3 + msr elr_el1, x2 + dsb sy + isb + ldp xzr, x30, [sp],#16 + ldp x29, x28, [sp],#16 + ldp x27, x26, [sp],#16 + ldp x25, x24, [sp],#16 + ldp x23, x22, [sp],#16 + ldp x21, x20, [sp],#16 + ldp x19, x18, [sp],#16 + ldp x17, x16, [sp],#16 + ldp x15, x14, [sp],#16 + ldp x13, x12, [sp],#16 + ldp x11, x10, [sp],#16 + ldp x9, x8, [sp],#16 + ldp x7, x6, [sp],#16 + ldp x5, x4, [sp],#16 + ldp x3, x2, [sp],#16 + ldp x1, x0, [sp],#16 + eret + + .globl OsSetSysStackSP + .type OsSetSysStackSP, @function + .align 4 +OsSetSysStackSP: + MOV SP, X0 + MOV X0, X1 + BL OsHwiDispatchHandle + + .text diff --git a/src/arch/cpu/armv8/common/hwi/prt_hwi.c b/src/arch/cpu/armv8/common/hwi/prt_hwi.c new file mode 100644 index 0000000..e7fbd0d --- /dev/null +++ b/src/arch/cpu/armv8/common/hwi/prt_hwi.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: 硬中断。 + */ +#include "prt_hwi_external.h" +#include "prt_task_external.h" +#include "prt_irq_external.h" +#include "prt_hwi_internal.h" + +/* + * 描述: GIC模块初始化 + */ +INIT_SEC_L4_TEXT void OsHwiGICInit(void) +{ + return; +} + +/* + * 描述: 获取硬中断优先级 + */ +INIT_SEC_L4_TEXT U32 OsHwiPriorityGet(HwiHandle hwiNum) +{ + return OsGicGetPriority(hwiNum); +} + +/* + * 描述: 设置硬中断优先级 + */ +INIT_SEC_L4_TEXT void OsHwiPrioritySet(HwiHandle hwiNum, HwiPrior hwiPrio) +{ + OS_ERR_RECORD(OsGicSetPriority(hwiNum, hwiPrio)); +} + +/* + * 描述: 禁止指定中断 + */ +OS_SEC_L2_TEXT U32 PRT_HwiDisable(HwiHandle hwiNum) +{ + if (hwiNum > OS_HWI_MAX) { + return OS_ERRNO_HWI_NUM_INVALID; + } + OsGicDisableInt(hwiNum); + + return OS_OK; +} + +/* + * 描述: 使能指定中断 + */ +OS_SEC_L2_TEXT U32 PRT_HwiEnable(HwiHandle hwiNum) +{ + if (hwiNum > OS_HWI_MAX) { + return OS_ERRNO_HWI_NUM_INVALID; + } + OsGicEnableInt(hwiNum); + + return OS_OK; +} + +/* + * 描述: 触发核间SGI中断,放置OS_SEC_TEXT段 + */ +OS_SEC_TEXT void OsHwiMcTrigger(U32 coreMask, U32 hwiNum) +{ + OsGicTrigIntToCores(hwiNum, coreMask); + return; +} + +/* + * 描述: 上报中断号错误 + */ +OS_SEC_TEXT void OsHwiReportHwiNumErr(void) +{ + OS_REPORT_ERROR(OS_ERRNO_HWI_HW_REPORT_HWINO_INVALID); + return; +} + +/* + * 描述: 中断处理, 调用处外部已关中断 + */ +OS_SEC_L0_TEXT void OsHwiDispatchHandle(U32 arg1) +{ + U32 hwiNum; + (void)arg1; + + UNI_FLAG |= OS_FLG_HWI_ACTIVE; + OS_INT_COUNT++; + /* ARMv8硬件约束,fiq和和irq都会在在异常和入口被mask掉 */ + /* 此处需要同时清F比特,确保FIQ能及时响应 */ + OsFiqEnable(); + + hwiNum = OsHwiNumGet(); + + if (OS_HWI_CLEAR_CHECK(hwiNum) || OS_HWI_NUM_CHECK(hwiNum)) { + goto OS_HWI_CONTINUE; + } + + OsHwiNestedIntEnable(); + OsHwiHookDispatcher(hwiNum); + OsHwiNestedIntDisable(); + +OS_HWI_CONTINUE: + // 清除中断位 + OsHwiClear(hwiNum); + OS_INT_COUNT--; + /* 不支持中断嵌套,但这里防止中断服务程序中错误打开了中断 */ + if (OS_INT_COUNT > 0) { + return; + } + + UNI_FLAG &= ~OS_FLG_HWI_ACTIVE; + + OsHwiDispatchTail(); +} + +/* + * 描述: 中断处理入口, 调用处外部已关中断 + */ +OS_SEC_L0_TEXT void OsHwiDispatch(uintptr_t sp, U32 arg1) +{ + // 该函数体内有切栈动作, 不允许有局部变量 + if (!OS_INT_ACTIVE) { + // 被打断的是任务 + RUNNING_TASK->stackPointer = (void *)sp; + OsSetSysStackSP(OsGetSysStackSP(), arg1); + } + + // 有可能切栈, 中断入口函数不使用局部变量 + OsHwiDispatchHandle(arg1); +} + +/* + * 描述: 开启全局可屏蔽中断。 + */ +OS_SEC_L0_TEXT uintptr_t PRT_HwiUnLock(void) +{ + uintptr_t state = 0; + + OS_EMBED_ASM( + "mrs %0, DAIF \n" + "msr DAIFClr, %1 \n" + : "=r"(state) + : "i"(DAIF_IRQ_BIT) + : "memory", "cc"); + + return state & INT_MASK; +} + +/* + * 描述: 关闭全局可屏蔽中断。 + */ +OS_SEC_L0_TEXT uintptr_t PRT_HwiLock(void) +{ + uintptr_t state = 0; + OS_EMBED_ASM( + "mrs %0, DAIF \n" + "msr DAIFSet, %1 \n" + : "=r"(state) + : "i"(DAIF_IRQ_BIT) + : "memory", "cc"); + return state & INT_MASK; +} + +/* + * 描述: 恢复原中断状态寄存器。 + */ +OS_SEC_L0_TEXT void PRT_HwiRestore(uintptr_t intSave) +{ + if ((intSave & INT_MASK) == 0) { + OS_EMBED_ASM( + "msr DAIFClr, %0\n" + : + : "i"(DAIF_IRQ_BIT) + : "memory", "cc"); + } else { + OS_EMBED_ASM( + "msr DAIFSet, %0\n" + : + : "i"(DAIF_IRQ_BIT) + : "memory", "cc"); + } + return; +} \ No newline at end of file diff --git a/src/arch/cpu/armv8/common/hwi/prt_hwi_internal.h b/src/arch/cpu/armv8/common/hwi/prt_hwi_internal.h new file mode 100644 index 0000000..586a4b7 --- /dev/null +++ b/src/arch/cpu/armv8/common/hwi/prt_hwi_internal.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: hwi模块内部头文件。 + */ +#ifndef PRT_HWI_INTERNAL_H +#define PRT_HWI_INTERNAL_H + +#include "prt_cpu_external.h" + +/* + * 模块内 内联函数 + */ +#if defined(OS_OPTION_HWI_NESTED) +/* + * 描述: 支持中断嵌套场景--进入ISR前开中断 + */ +OS_SEC_ALW_INLINE INLINE void OsHwiNestedIntEnable(void) +{ + OsIntEnable(); +} + +/* + * 描述: 支持中断嵌套场景--退出ISR后关中断 + */ +OS_SEC_ALW_INLINE INLINE void OsHwiNestedIntDisable(void) +{ + OsIntDisable(); +} +#else +OS_SEC_ALW_INLINE INLINE void OsHwiNestedIntEnable(void) +{ +} + +OS_SEC_ALW_INLINE INLINE void OsHwiNestedIntDisable(void) +{ +} +#endif /* OS_OPTION_HWI_NESTED */ + +#endif /* PRT_HWI_INTERNAL_H */ diff --git a/src/arch/cpu/armv8/common/hwi/prt_reset_vector.S b/src/arch/cpu/armv8/common/hwi/prt_reset_vector.S new file mode 100644 index 0000000..a54ba3c --- /dev/null +++ b/src/arch/cpu/armv8/common/hwi/prt_reset_vector.S @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: GUEST启动处理。 + */ +#include "prt_buildef.h" +#include "prt_asm_arm_external.h" + +DAIF_MASK = 0x1C0 // disable Abort, IRQ, FIQ + +.macro REG_INIT xreg + mov \xreg, #0 +.endm + + + .global __os_sys_sp_end + .global g_cfgPrimaryCore + .global g_gicCoreMap + .global OsResetVector + .global OsBssInit + .global InitSystemSp + .global OsVectorTable + + .type __os_sys_sp_end, object + .type g_cfgPrimaryCore, object + .type g_gicCoreMap, object + .type OsResetVector, function + .type OsBssInit, function + + .section .text.startup, "ax" +OsResetVector: +OsVectTblInit: + LDR x0, =OsVectorTable + MSR VBAR_EL1, X0 + +OsGeneralRegsInit: // The X30 general-purpose register is used as the procedure call link register + REG_INIT x0 + REG_INIT x1 + REG_INIT x2 + REG_INIT x3 + REG_INIT x4 + REG_INIT x5 + REG_INIT x6 + REG_INIT x7 + REG_INIT x8 + REG_INIT x9 + REG_INIT x10 + REG_INIT x11 + REG_INIT x12 + REG_INIT x13 + REG_INIT x14 + REG_INIT x15 + REG_INIT x16 + REG_INIT x17 + REG_INIT x18 + REG_INIT x19 + REG_INIT x20 + REG_INIT x21 + REG_INIT x22 + REG_INIT x23 + REG_INIT x24 + REG_INIT x25 + REG_INIT x26 + REG_INIT x27 + REG_INIT x28 + REG_INIT x29 + +OsStackBssInit: + LDR x0, =__os_sys_sp_end + BIC sp, x0, #0xf /* 16-byte alignment for ABI compliance */ + BL OsBssInit + BL InitSystemSp + B OsCoreMapInit + +OsCoreMapInit: + MRS x1, mpidr_el1 // 读取CoreMap + LDR x2, =g_gicCoreMap + STR x1, [x2] + +OsPrimaryMain: /* OsPrimaryMain函数主核调用 */ + BL PRT_HardBootInit /* 用户调用的第一个函数钩子,用户在此处完成Seed随机数生成 */ + /* Notes:X9存g_memCanaryRdm地址,X10存__stack_chk_guard地址,w11存g_memCanaryRdm的值 U32类型 */ + /* __stack_chk_guard赋值后 g_memCanaryRdm 以及 w11都会被销毁 */ +#if defined(OS_OPTION_GUARD_STACK) + InitChkGuardRnd x9, x10, w11 /* RND 写入 StackChkGuard */ +#endif + +OsEnterMain: + BL main + + MOV x2, DAIF_MASK + MSR DAIF, x2 + +EXITLOOP: + B EXITLOOP + + .text diff --git a/src/arch/cpu/armv8/common/hwi/prt_vector.S b/src/arch/cpu/armv8/common/hwi/prt_vector.S new file mode 100644 index 0000000..2c410cf --- /dev/null +++ b/src/arch/cpu/armv8/common/hwi/prt_vector.S @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: 向量表处理。 + */ + + .section .os.vector.text, "ax" + + .global OsVectorTable + .global OsHwiDispatcher + .global OsVectorTable + + .type OsHwiDispatcher, function + .type OsVectorTable,function + +.macro EXC_HANDLE vecId + stp x1, x0, [sp,#-16]! + mov x1, #\vecId + b OsExcDispatch +.endm + + .align 13 + +OsVectorTable: +.set VBAR, OsVectorTable +.org VBAR // Synchronous, Current EL with SP_EL0 + EXC_HANDLE 0 + +.org (VBAR + 0x80) // IRQ/vIRQ, Current EL with SP_EL0 + EXC_HANDLE 1 + +.org (VBAR + 0x100) // FIQ/vFIQ, Current EL with SP_EL0 + EXC_HANDLE 2 + +.org (VBAR + 0x180) // SERROR, Current EL with SP_EL0 + EXC_HANDLE 3 + +.org (VBAR + 0x200) // Synchronous, Current EL with SP_ELx + EXC_HANDLE 4 + +.org (VBAR + 0x280) // IRQ/vIRQ, Current EL with SP_ELx + stp x1, x0, [sp,#-16]! + mov x1, #5 + b OsHwiDispatcher + +.org (VBAR + 0x300) // FIQ/vFIQ, Current EL with SP_ELx + EXC_HANDLE 6 + +.org (VBAR + 0x380) // SERROR, Current EL with SP_ELx + EXC_HANDLE 7 + +.org (VBAR + 0x400) // Synchronous, EL changes and the target EL is using AArch64 + EXC_HANDLE 8 + +.org (VBAR + 0x480) // IRQ/vIRQ, EL changes and the target EL is using AArch64 + EXC_HANDLE 9 + +.org (VBAR + 0x500) // FIQ/vFIQ, EL changes and the target EL is using AArch64 + EXC_HANDLE 10 +.org (VBAR + 0x580) // SERROR, EL changes and the target EL is using AArch64 + EXC_HANDLE 11 +.org (VBAR + 0x600) // Synchronous, L changes and the target EL is using AArch32 + EXC_HANDLE 12 + +.org (VBAR + 0x680) // IRQ/vIRQ, EL changes and the target EL is using AArch32 + EXC_HANDLE 13 + +.org (VBAR + 0x700) // FIQ/vFIQ, EL changes and the target EL is using AArch32 + EXC_HANDLE 14 +.org (VBAR + 0x780) // SERROR, EL changes and the target EL is using AArch32 + EXC_HANDLE 15 + + .text + diff --git a/src/arch/cpu/armv8/common/os_asm_cpu_armv8_external.h b/src/arch/cpu/armv8/common/os_asm_cpu_armv8_external.h new file mode 100644 index 0000000..bc3b162 --- /dev/null +++ b/src/arch/cpu/armv8/common/os_asm_cpu_armv8_external.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: ARMV8 公共汇编宏文件。 + */ +#ifndef OS_ASM_CPU_ARMV8_EXTERNAL_H +#define OS_ASM_CPU_ARMV8_EXTERNAL_H + +/* + * 描述: 读取当前核号 + * 使用mpidr 寄存器 (64bit) 根据核的线程模式获取核号 + * bit 63-40 39-32 31 30 29~25 24 23-16 15-8 7~0 + * res0 aff3 res1 u res0 mt aff2 aff1 aff0 + */ +.macro OsAsmGetCoreId, xArg + mrs \xArg, mpidr_el1 + orr \xArg, \xArg, \xArg, lsr #0x8 + and \xArg, \xArg, #0xff /* 截取核号部分 */ +.endm + +#endif /* OS_ASM_CPU_ARMV8_EXTERNAL_H */ diff --git a/src/arch/cpu/armv8/common/os_attr_armv8_external.h b/src/arch/cpu/armv8/common/os_attr_armv8_external.h new file mode 100644 index 0000000..a4b81b8 --- /dev/null +++ b/src/arch/cpu/armv8/common/os_attr_armv8_external.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: 属性宏相关内部头文件 + */ +#ifndef OS_ATTR_ARMV8_EXTERNAL_H +#define OS_ATTR_ARMV8_EXTERNAL_H + +/* 定义操作系统的代码数据分段 */ +#ifndef CONFIG_OPTION_FX_SECTIONS +/* L0表示最高性能内存段 */ +#ifndef OS_SEC_L0_TEXT +#define OS_SEC_L0_TEXT __attribute__((section(".os.text"))) +#endif + +#ifndef OS_SEC_LX0_TEXT +#define OS_SEC_LX0_TEXT __attribute__((section(".os.text"))) +#endif + +/* OS_SEC_L1_TEXT, L1表示性能敏感内存段,如PL2,默认缺省,不显示指定 */ +#ifndef OS_SEC_TEXT +#define OS_SEC_TEXT __attribute__((section(".os.text"))) +#endif + +#ifndef OS_SEC_L2_TEXT +#define OS_SEC_L2_TEXT __attribute__((section(".os.minor.text"))) +#endif + +#ifndef OS_SEC_L4_TEXT +#define OS_SEC_L4_TEXT __attribute__((section(".os.init.text"))) +#endif + +#ifndef OS_SEC_LX_TEXT +#define OS_SEC_LX_TEXT __attribute__((section(".os.init.text"))) +#endif + +#ifndef OS_SEC_DATA +#define OS_SEC_DATA __attribute__((section(".os.data"))) +#endif + +#ifndef OS_SEC_L4_DATA +#define OS_SEC_L4_DATA __attribute__((section(".os.data"))) +#endif + +#ifndef OS_SEC_BSS +#define OS_SEC_BSS __attribute__((section(".os.bss"))) +#endif + +#ifndef OS_SEC_L4_BSS +#define OS_SEC_L4_BSS __attribute__((section(".os.bss"))) +#endif + +#ifndef OS_SEC_L4_INSTSH_DATA +#define OS_SEC_L4_INSTSH_DATA __attribute__((section(".os.data"))) +#endif +#endif /* CONFIG_OPTION_FX_SECTIONS */ + +#endif /* OS_ATTR_ARMV8_EXTERNAL_H */ diff --git a/src/arch/cpu/armv8/common/os_cpu_armv8_external.h b/src/arch/cpu/armv8/common/os_cpu_armv8_external.h new file mode 100644 index 0000000..ec9371e --- /dev/null +++ b/src/arch/cpu/armv8/common/os_cpu_armv8_external.h @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: 属性宏相关内部头文件 + */ +#ifndef OS_CPU_ARMV8_EXTERNAL_H +#define OS_CPU_ARMV8_EXTERNAL_H + +#include "prt_buildef.h" +#include "prt_hwi.h" +#include "prt_gic_external.h" + +/* + * 模块间宏定义 + */ +#define OS_IRQ2HWI(irqNum) (irqNum) +#define OS_HWI2IRQ(hwiNum) (hwiNum) +#define OS_HWI_GET_HWINUM(archNum) (archNum) +#define OS_HWI_GET_HWI_PRIO(hwiPrio) (hwiPrio) +#define OS_HWI_IS_SGI(hwiNum) ((hwiNum) <= MAX_SGI_ID) +#define OS_HWI_IS_PPI(hwiNum) (((hwiNum) > MAX_SGI_ID) && ((hwiNum) <= MAX_PPI_ID)) + +/* OS_HWI_MAX_NUM 大小会影响bss段大小。需要根据实际使用hwi个数配置 */ +#define OS_HWI_MAX_NUM 0x182U +#define OS_HWI_NUM_CHECK(hwiNum) ((hwiNum) >= OS_HWI_MAX_NUM) + +#define OS_HWI_MAX (OS_HWI_MAX_NUM - 1) +#define OS_HWI_FORMARRAY_NUM OS_HWI_MAX_NUM +#define OS_HWI_MIN 0 +#define OS_HWI_PRI_NUM 14 + +/* 中断优先级0~15,但非安全世界的中断优先级只能是偶数 */ +#define OS_HWI_PRIO_CHECK(hwiPrio) ((hwiPrio) >= OS_HWI_PRI_NUM || ((hwiPrio) & 1U)) +#define OS_HWI_SET_HOOK_ATTR(hwiNum, hwiPrio, hook) + +#define OS_HWI_CLEAR_CHECK(hwiNum) ((hwiNum) == GIC_INT_ID_MASK) + +#define OS_HWI_INTERNAL_NUM 5 + +#define OS_TICK_COUNT_UPDATE() + +#define OS_HW_TICK_INIT() OS_OK + +#define OS_IS_TICK_PERIOD_INVALID(cyclePerTick) (FALSE) + +#define OS_TSK_STACK_SIZE_ALIGN 16U +#define OS_TSK_STACK_SIZE_ALLOC_ALIGN MEM_ADDR_ALIGN_016 +#define OS_TSK_STACK_ADDR_ALIGN 16U + +#define OS_MAX_CACHE_LINE_SIZE 4 /* 单核芯片定义为4 */ + +/* 任务栈最小值 */ +#define OS_TSK_MIN_STACK_SIZE (ALIGN((0x1D0 + 0x10 + 0x4), 16)) + +/* Idle任务的消息队列数 */ +#define OS_IDLE_TASK_QUE_NUM 1 + +#define DIV64(a, b) ((a) / (b)) +#define DIV64_REMAIN(a, b) ((a) % (b)) + +#define OsIntUnLock() PRT_HwiUnLock() +#define OsIntLock() PRT_HwiLock() +#define OsIntRestore(intSave) PRT_HwiRestore(intSave) + +/* 硬件平台保存的任务上下文 */ +struct TagHwContext { + uintptr_t pc; + uintptr_t spsr; + uintptr_t far; + uintptr_t esr; + uintptr_t xzr; + uintptr_t lr; + uintptr_t x[30]; +}; + +/* + * 模块间变量声明 + */ +extern uintptr_t __os_sys_sp_end; +extern uintptr_t __os_sys_sp_start; +extern uintptr_t __bss_end__; +extern uintptr_t __bss_start__; + +/* + * 模块间函数声明 + */ +extern uintptr_t OsGetSysStackSP(void); +extern void OsSetSysStackSP(uintptr_t stackPointer, U32 hwiNum); +extern uintptr_t OsGetSysStackStart(void); +extern uintptr_t OsGetSysStackEnd(void); +extern void OsTaskTrap(void); +extern void OsTskContextLoad(uintptr_t stackPointer); + +/* + * 描述: 使能IRQ中断 + */ +OS_SEC_ALW_INLINE INLINE void OsIntEnable(void) +{ + OS_EMBED_ASM( + "msr daifclr, %0" + : + : "i"(DAIF_IRQ_BIT) // IRQ mask + : "memory"); +} + +/* + * 描述: 使能FIQ中断 + */ +OS_SEC_ALW_INLINE INLINE void OsFiqEnable(void) +{ + OS_EMBED_ASM( + "msr daifclr, %0" + : + : "i"(DAIF_FIQ_BIT) // FIQ mask + : "memory"); +} + +/* + * 描述: 禁止IRQ中断 + */ +OS_SEC_ALW_INLINE INLINE void OsIntDisable(void) +{ + OS_EMBED_ASM( + "msr daifset, %0" + : + : "i"(DAIF_IRQ_BIT) // IRQ mask + : "memory", "cc"); +} +#if (OS_GIC_VER == 2) +OS_SEC_ALW_INLINE INLINE U32 OsHwiNumGet(void) +{ + U32 iar; + + iar = GIC_REG_READ(GICC_IAR); + + return (iar & IAR_MASK); +} +#else +/* + * 描述: 获取当前PENDING的中断号, 中断状态PENDING->ACTIVE + */ +OS_SEC_ALW_INLINE INLINE U32 OsHwiNumGet(void) +{ + U32 iar; + + OS_EMBED_ASM("MRS %0," REG_ALIAS(ICC_IAR1_EL1)" \n" + : "=&r"(iar) : : "memory"); + + return iar; +} +#endif + +#if (OS_GIC_VER == 2) +OS_SEC_ALW_INLINE INLINE void OsHwiClear(U32 intId) +{ + GIC_REG_WRITE(GICC_EOIR, intId & IAR_MASK); +} +#else +/* + * 描述: 清除中断ACTIVE状态 + */ +OS_SEC_ALW_INLINE INLINE void OsHwiClear(U32 intId) +{ + OS_EMBED_ASM("MSR " REG_ALIAS(ICC_EOIR1_EL1)", %0 \n" + : : "r"(intId) : "memory"); + return; +} +#endif + +/* + * 描述: 获取SP + */ +OS_SEC_ALW_INLINE INLINE uintptr_t OsGetSp(void) +{ + uintptr_t sp; + + OS_EMBED_ASM("MOV %0, SP" : "=r"(sp)); + + return sp; +} + +/* + * 描述: 传入任务切换时的栈地址 + */ +OS_SEC_ALW_INLINE INLINE uintptr_t OsTskGetInstrAddr(uintptr_t addr) +{ + return ((struct TagHwContext *)addr)->pc; +} + +OS_SEC_ALW_INLINE INLINE void OsTaskTrapFast(void) +{ + OsTaskTrap(); +} + +OS_SEC_ALW_INLINE INLINE void OsTaskTrapFastPs(uintptr_t intSave) +{ + (void)intSave; + OsTaskTrap(); +} + +#endif /* OS_CPU_ARMV8_EXTERNAL_H */ diff --git a/src/arch/cpu/armv8/common/prt_port.c b/src/arch/cpu/armv8/common/prt_port.c new file mode 100644 index 0000000..4e085e7 --- /dev/null +++ b/src/arch/cpu/armv8/common/prt_port.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: Hardware Initialization + */ +#include "prt_cpu_external.h" +#include "prt_sys_external.h" + +#define ARMV8_X1_INIT_VALUE 0x01010101UL +#define ARMV8_X2_INIT_VALUE 0x02020202UL +#define ARMV8_X3_INIT_VALUE 0x03030303UL +#define ARMV8_X4_INIT_VALUE 0x04040404UL +#define ARMV8_X5_INIT_VALUE 0x05050505UL +#define ARMV8_X6_INIT_VALUE 0x06060606UL +#define ARMV8_X7_INIT_VALUE 0x07070707UL +#define ARMV8_X8_INIT_VALUE 0x08080808UL +#define ARMV8_X9_INIT_VALUE 0x09090909UL +#define ARMV8_X10_INIT_VALUE 0x10101010UL +#define ARMV8_X11_INIT_VALUE 0x11111111UL +#define ARMV8_X12_INIT_VALUE 0x12121212UL +#define ARMV8_X13_INIT_VALUE 0x13131313UL +#define ARMV8_X14_INIT_VALUE 0x14141414UL +#define ARMV8_X15_INIT_VALUE 0x15151515UL +#define ARMV8_X16_INIT_VALUE 0x16161616UL +#define ARMV8_X17_INIT_VALUE 0x17171717UL +#define ARMV8_X18_INIT_VALUE 0x18181818UL +#define ARMV8_X19_INIT_VALUE 0x19191919UL +#define ARMV8_X20_INIT_VALUE 0x20202020UL +#define ARMV8_X21_INIT_VALUE 0x21212121UL +#define ARMV8_X22_INIT_VALUE 0x22222222UL +#define ARMV8_X23_INIT_VALUE 0x23232323UL +#define ARMV8_X24_INIT_VALUE 0x24242424UL +#define ARMV8_X25_INIT_VALUE 0x25252525UL +#define ARMV8_X26_INIT_VALUE 0x26262626UL +#define ARMV8_X27_INIT_VALUE 0x27272727UL +#define ARMV8_X28_INIT_VALUE 0x28282828UL +#define ARMV8_X29_INIT_VALUE 0x29292929UL + +#define ARMV8_SPSR_INIT_VALUE 0x305U // EL1_SP1 | D | A | I | F + +/* Tick中断对应的硬件定时器ID */ +OS_SEC_DATA U32 g_tickTimerID = U32_INVALID; + +// 系统栈配置 +OS_SEC_DATA uintptr_t g_sysStackHigh = (uintptr_t)&__os_sys_sp_end; +OS_SEC_DATA uintptr_t g_sysStackLow = (uintptr_t)&__os_sys_sp_start; + +INIT_SEC_L4_TEXT void InitSystemSp(void) +{ + return; +} + +/* + * 描述: 获取系统栈的起始地址(低地址) + */ +INIT_SEC_L4_TEXT uintptr_t OsGetSysStackStart(void) +{ + return g_sysStackLow; +} + +/* + * 描述: 获取系统栈的结束地址(高地址) + */ +INIT_SEC_L4_TEXT uintptr_t OsGetSysStackEnd(void) +{ + return g_sysStackHigh; +} + +/* + * 描述: 获取系统栈的栈底(高地址) + */ +OS_SEC_L0_TEXT uintptr_t OsGetSysStackSP(void) +{ + return OsGetSysStackEnd(); +} + +/* + * 描述: 初始化任务栈的上下文 + */ +INIT_SEC_L4_TEXT void *OsTskContextInit(U32 taskID, U32 stackSize, uintptr_t *topStack, uintptr_t funcTskEntry) +{ + (void)taskID; + struct TskContext *stack = (struct TskContext *)((uintptr_t)topStack + stackSize); + + stack -= 1; + + stack->x00 = 0; + stack->x01 = ARMV8_X1_INIT_VALUE; + stack->x02 = ARMV8_X2_INIT_VALUE; + stack->x03 = ARMV8_X3_INIT_VALUE; + stack->x04 = ARMV8_X4_INIT_VALUE; + stack->x05 = ARMV8_X5_INIT_VALUE; + stack->x06 = ARMV8_X6_INIT_VALUE; + stack->x07 = ARMV8_X7_INIT_VALUE; + stack->x08 = ARMV8_X8_INIT_VALUE; + stack->x09 = ARMV8_X9_INIT_VALUE; + stack->x10 = ARMV8_X10_INIT_VALUE; + stack->x11 = ARMV8_X11_INIT_VALUE; + stack->x12 = ARMV8_X12_INIT_VALUE; + stack->x13 = ARMV8_X13_INIT_VALUE; + stack->x14 = ARMV8_X14_INIT_VALUE; + stack->x15 = ARMV8_X15_INIT_VALUE; + stack->x16 = ARMV8_X16_INIT_VALUE; + stack->x17 = ARMV8_X17_INIT_VALUE; + stack->x18 = ARMV8_X18_INIT_VALUE; + stack->x19 = ARMV8_X19_INIT_VALUE; + stack->x20 = ARMV8_X20_INIT_VALUE; + stack->x21 = ARMV8_X21_INIT_VALUE; + stack->x22 = ARMV8_X22_INIT_VALUE; + stack->x23 = ARMV8_X23_INIT_VALUE; + stack->x24 = ARMV8_X24_INIT_VALUE; + stack->x25 = ARMV8_X25_INIT_VALUE; + stack->x26 = ARMV8_X26_INIT_VALUE; + stack->x27 = ARMV8_X27_INIT_VALUE; + stack->x28 = ARMV8_X28_INIT_VALUE; + stack->x29 = ARMV8_X29_INIT_VALUE; + stack->x30 = funcTskEntry; // x30: lr(link register) + stack->xzr = 0; + + stack->elr = funcTskEntry; + stack->esr = 0; + stack->far = 0; + stack->spsr = ARMV8_SPSR_INIT_VALUE; // EL1_SP1 | D | A | I | F + return stack; +} + +/* + * 描述: 从指定地址获取任务上下文 + */ +OS_SEC_L4_TEXT void OsTskContextGet(uintptr_t saveAddr, struct TskContext *context) +{ + *context = *((struct TskContext *)saveAddr); + + return; +} + +/* + * 描述: 手动触发异常(EL1) + */ +OS_SEC_L4_TEXT void OsAsmIll(void) +{ + OS_EMBED_ASM("svc 0"); +} diff --git a/src/arch/drv/CMakeLists.txt b/src/arch/drv/CMakeLists.txt new file mode 100644 index 0000000..032beeb --- /dev/null +++ b/src/arch/drv/CMakeLists.txt @@ -0,0 +1,3 @@ +if(${CONFIG_OS_ARCH_ARMV8}) + add_subdirectory(gic) +endif() diff --git a/src/arch/drv/Kconfig b/src/arch/drv/Kconfig new file mode 100644 index 0000000..2762123 --- /dev/null +++ b/src/arch/drv/Kconfig @@ -0,0 +1,4 @@ +menu "ARMV8 DRV Features Configuration" +depends on (OS_ARCH_ARMV8) +source "arch/drv/gic/Kconfig" +endmenu diff --git a/src/arch/drv/gic/CMakeLists.txt b/src/arch/drv/gic/CMakeLists.txt new file mode 100644 index 0000000..4b8f990 --- /dev/null +++ b/src/arch/drv/gic/CMakeLists.txt @@ -0,0 +1,7 @@ +if("${CONFIG_INTERNAL_OS_GIC_VER}" STREQUAL "gicv600") + include_directories(./gicv600) +endif() + +add_library_ex(prt_gic_init.c) +add_library_ex(prt_gicd_init.c) +add_library_ex(prt_gicr_init.c) \ No newline at end of file diff --git a/src/arch/drv/gic/Kconfig b/src/arch/drv/gic/Kconfig new file mode 100644 index 0000000..fde5c2e --- /dev/null +++ b/src/arch/drv/gic/Kconfig @@ -0,0 +1,4 @@ +config INTERNAL_OS_GIC_VER + string + depends on OS_ARCH_ARMV8 + default "gicv600" if (INTERNAL_OS_RASPI4) \ No newline at end of file diff --git a/src/arch/drv/gic/gicv600/prt_gic_internal.h b/src/arch/drv/gic/gicv600/prt_gic_internal.h new file mode 100644 index 0000000..0859bd1 --- /dev/null +++ b/src/arch/drv/gic/gicv600/prt_gic_internal.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022/11/18 + * Description: shared data declaration + */ + +#ifndef PRT_GIC_INTERNAL_H +#define PRT_GIC_INTERNAL_H + +#include "../prt_gic_common_internal.h" + +/* + * 模块间宏定义 + */ +/* 各个board有差异的中断配置 */ +#define MAX_NNSPI_ID 31 // 系统可支持的最大NNSPI的中断号,为了代码归一,不支持NNSPI场景配置成MAX_PPI_ID相同 +#define MIN_SPI_ID 32 // 系统可支持的最小SPI的中断号 +#define GICD_SPI_IROUTERN_L_ADDR (GIC_GICD_BASE + 0x6000U) // GIC亲和性配置寄存器 + +/* + * 描述: GicV3 根据中断号获取全局中断亲和配置寄存器地址 + */ +OS_SEC_ALW_INLINE INLINE uintptr_t OsGicGetRouterAddr(U32 intId) +{ + return GICD_SPI_IROUTERN_L_ADDR + (uintptr_t)(sizeof(uintptr_t) * intId); +} + +#endif /* PRT_GIC_INTERNAL_H */ diff --git a/src/arch/drv/gic/prt_gic_common_internal.h b/src/arch/drv/gic/prt_gic_common_internal.h new file mode 100644 index 0000000..991454e --- /dev/null +++ b/src/arch/drv/gic/prt_gic_common_internal.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-18 + * Description: shared data declaration + */ + +#ifndef PRT_GIC_COMMON_INTERNAL_H +#define PRT_GIC_COMMON_INTERNAL_H + +#include "prt_gic_external.h" + +/* + * 模块间宏定义 + */ +/* 各个平台公共的宏 */ +#define GIC_GICD_BASE (GIC_REG_BASE + 0x0) +#define GICD_CTLR_S_ADDR (GIC_GICD_BASE + 0x0000) +#define GICD_ISENABLER0_ADDR (GIC_GICD_BASE + 0x0100) +#define GICD_ICENABLER0_ADDR (GIC_GICD_BASE + 0x0180) +#define GICD_SGI_IPRIORITY_S_ADDR (GIC_GICD_BASE + 0x0400) +#define GICD_SGI_ICFGR_ADDR (GIC_GICD_BASE + 0x0C00) + +#define GIC_GICR_BASE0 (GIC_REG_BASE + g_gicrOffset) +#define GIC_GICR_BASE1 (GIC_GICR_BASE0 + 0x10000) +#define GICR_CTRL_ADDR (GIC_GICR_BASE0 + 0x0000) +#define GICR_ISENABLER0_ADDR (GIC_GICR_BASE1 + 0x0100) +#define GICR_ICENABLER0_ADDR (GIC_GICR_BASE1 + 0x0180) +#define GICR_IPRIORITY_SGI_S_ADDR (GIC_GICR_BASE1 + 0x0400) +#define GICR_ADDR_OFFSET_PER_CORE g_gicrStride + +#endif /* PRT_GIC_COMMON_INTERNAL_H */ diff --git a/src/arch/drv/gic/prt_gic_init.c b/src/arch/drv/gic/prt_gic_init.c new file mode 100644 index 0000000..914b8d7 --- /dev/null +++ b/src/arch/drv/gic/prt_gic_init.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-18 + * Description: 硬件GIC相关的处理。 + */ +#include "prt_hwi.h" +#include "prt_gic_external.h" +#include "prt_gic_internal.h" +#include "prt_attr_external.h" +#include "prt_task.h" + +#if (OS_GIC_VER == 2) +union IccSgirEl1 { + struct { + U32 intId : 4; + U32 rsvd0 : 11; + U32 nsatt : 1; + U32 targetlist : 8; + U32 filter : 2; + U32 rsvd1 : 6; + } bits; + U32 value; +}; +#elif (OS_GIC_VER == 3) +/* ICC_SGIR_EL1 */ +union IccSgirEl1 { + struct { + U64 targetlist : 16; // bit[0..15] 每bit对应1个核,bit置1代表中断会触发到对应的核 + U64 aff1 : 8; // bit[16..23] + U64 intId : 4; // bit[24..27] SGI 中断号. + U64 rsvd0 : 4; // bit[28..31] + U64 aff2 : 8; // bit[32..39] + /* bit[40] 0:中断触发给Aff3.Aff2.Aff1.;1:中断触发给本核以外的所有核 */ + U64 irm : 1; // bit[40] + U64 rsvd1 : 3; // bit[41..43] + /* bit[44..47] range selector,RS域共4个bit,可以表示16个范围,16×16=256,刚好表示256个cpu */ + /* 所以spec里面,说TargetList[n]表示的aff0的值为RS*16 + n。 */ + U64 rs : 4; // bit[44..47] + U64 aff3 : 8; // bit[48..55] + U64 rsvd2 : 8; // bit[63..56] + } bits; + U64 value; +}; +#endif + +/* GIC基地址 */ +OS_SEC_BSS uintptr_t g_gicdBase; +/* GICR相对于GIC基地址偏移向量 */ +OS_SEC_BSS uintptr_t g_gicrOffset; +/* GICR核间偏移向量配置 */ +OS_SEC_BSS uintptr_t g_gicrStride; +/* 存放Core Map值 */ +OS_SEC_DATA union GicCoreMap g_gicCoreMap = {0}; + +/* + * 描述: 去使能指定中断 + */ +OS_SEC_L4_TEXT void OsGicDisableInt(U32 intId) +{ + if (intId <= MAX_NNSPI_ID) { + OsGicrDisableInt(PRT_GetCoreID(), intId); + } else if (intId <= MAX_SPI_ID) { + OsGicdDisableInt(intId); + } +} + +/* + * 描述: 使能指定中断 + */ +OS_SEC_L4_TEXT void OsGicEnableInt(U32 intId) +{ + if (intId <= MAX_NNSPI_ID) { + OsGicrEnableInt(PRT_GetCoreID(), intId); + } else if (intId <= MAX_SPI_ID) { + OsGicdEnableInt(intId); + } +} + +#if (OS_GIC_VER == 2) +/* + * 描述: 触发中断到目标核,仅支持SGI + */ +OS_SEC_TEXT void OsGicTrigIntToCores(U32 intId, U32 targetList) +{ + union IccSgirEl1 iccSgirEl1; + U32 core; + + PRT_DSB(); + for (core = 0; (core < OS_MAX_CORE_NUM) && (targetList != 0); ++core) { + if ((targetList & (1U << core)) != 0) { + iccSgirEl1.value = 0; // 每个位域默认为0 + iccSgirEl1.bits.intId = intId; + iccSgirEl1.bits.targetlist = 1 << core; + GIC_REG_WRITE(GICD_SGIR, iccSgirEl1.value); + } + } + /* 内存屏障,强制生效执行上述对ICC_SGI1R_EL1的写操作 */ + PRT_ISB(); +} +#elif (OS_GIC_VER == 3) +/* + * 描述: 触发中断到目标核,仅支持SGI + */ +OS_SEC_TEXT void OsGicTrigIntToCores(U32 intId, U32 targetList) +{ + union IccSgirEl1 iccSgirEl1; + U32 core; + U16 targetMask = 0x1; + + PRT_DSB(); + for (core = 0; (core < OS_MAX_CORE_NUM) && (targetList != 0); ++core) { + if ((targetList & (1U << core)) != 0) { + iccSgirEl1.value = 0; // 每个位域默认为0 + iccSgirEl1.bits.intId = intId; + iccSgirEl1.bits.targetlist = targetMask; + iccSgirEl1.bits.aff1 = core; + iccSgirEl1.bits.aff2 = g_gicCoreMap.bits.aff2; + iccSgirEl1.bits.aff3 = g_gicCoreMap.bits.aff3; + OS_EMBED_ASM("MSR " REG_ALIAS(ICC_SGI1R_EL1) ", %0 \n" : : "r"(iccSgirEl1.value) : "memory"); + } + } + /* 内存屏障,强制生效执行上述对ICC_SGI1R_EL1的写操作 */ + PRT_ISB(); +} +#endif + + +/* + * 描述: 设置中断的优先级 + */ +OS_SEC_L4_TEXT U32 OsGicSetPriority(U32 intId, U32 priority) +{ + U32 coreId; + enum GicIntState state; + + if (intId > MAX_SPI_ID || priority > MAX_INT_PRIORITY) { + return OS_FAIL; + } + + /* 修改配置前,务必保证中断处于禁能状态 */ + if (intId <= MAX_NNSPI_ID) { + for (coreId = 0; coreId < OS_MAX_CORE_NUM; coreId++) { + state = OsGicrGetIntState(coreId, intId); + OsGicrDisableInt(coreId, intId); + OsGicrSetPriority(coreId, intId, priority); + if (state == GIC_ENABLE) { + OsGicrEnableInt(coreId, intId); + } + } + } else { + state = OsGicdGetIntState(intId); + OsGicdDisableInt(intId); + OsGicdSetPriority(intId, priority); + if (state == GIC_ENABLE) { + OsGicdEnableInt(intId); + } + } + return OS_OK; +} + +/* + * 描述: 获取中断的优先级 + */ +OS_SEC_L4_TEXT U32 OsGicGetPriority(U32 intId) +{ + if (intId <= MAX_NNSPI_ID) { + return OsGicrGetPriority(PRT_GetCoreID(), intId); + } + + return OsGicdGetPriority(intId); +} + +/* + * 描述: 设置中断路由目标核,参数有效性由调用者保证 + * 备注: 仅对非N-N SPI有效,仅支持1个目标核。 + */ +OS_SEC_L4_TEXT void OsGicSetTargetId(U32 intId, U32 targetId) +{ + enum GicIntState state; + + /* 修改配置前,务必保证中断处于禁能状态 */ + state = OsGicdGetIntState(intId); + OsGicdDisableInt(intId); + OsGicdCfgTargetId(intId, targetId); + if (state == GIC_ENABLE) { + OsGicdEnableInt(intId); + } +} + +/* + * 描述: 配置GIC基地址 + * 备注: 此处仅对入参做基础校验,需要用户参考硬件手册,保证入参的正确。 + */ +OS_SEC_L4_TEXT U32 OsGicConfigRegister(uintptr_t gicdBase, uintptr_t gicrOffset, uintptr_t gicrStride) +{ + if ((gicdBase == 0) || (gicrOffset == 0) || (gicrStride == 0)) { + return OS_ERROR_HWI_BASE_ADDR_INVALID; + } + + g_gicdBase = gicdBase; + g_gicrOffset = gicrOffset; + g_gicrStride = gicrStride; + + return OS_OK; +} + +/* + * 描述: SPI中断范围Check + */ +OS_SEC_L4_TEXT bool OsGicIsSpi(U32 intId) +{ + return (((intId) >= MIN_SPI_ID) && ((intId) <= MAX_SPI_ID)); +} diff --git a/src/arch/drv/gic/prt_gicd_init.c b/src/arch/drv/gic/prt_gicd_init.c new file mode 100644 index 0000000..74829ea --- /dev/null +++ b/src/arch/drv/gic/prt_gicd_init.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-18 + * Description: 硬件GICD相关的处理。 + */ +#include "prt_gic_external.h" +#include "prt_gic_internal.h" +#include "prt_attr_external.h" + +/* GICD_ROUTER */ +union GicdRouter { + struct { + U64 af0 : 2; // bit[1:0] + U64 res1 : 6; // bit[7:2] + U64 af1 : 2; // bit[9:8] + U64 res0 : 21; // bit[30:10] + U64 mode : 1; // bit[31] + U64 res2 : 32; // bit[32~63] + } bits; + U64 value; +}; + +/* GICD_CTRL */ +union GicdCtrl { + struct { + U32 enG0S : 1; // bit[0] Enable Secure Group0 interrupt, Group0安全中断使能 + U32 enG1Ns : 1; // bit[1] Enable Non-Secure Group1 interrupt, Group1非安全中断使能 + U32 enG1S : 1; // bit[2] Enable Secure Group1 interrupt, Group1安全中断使能 + U32 res1 : 1; // bit[3] + U32 areS : 1; // bit[4] Affinity Routing Eanble(for Secure) + U32 areNs : 1; // bit[5] 非安全状态下的关联路由使能 + U32 ds : 1; // bit[6] Disable Security,当DS置1时,非安全操作可以访问Group0的配置寄存器 + U32 res0 : 24; // bit[30:7] + U32 rwp : 1; // bit[31] 标识前面一次写GICD_CTLR寄存器的配置信息是否生效,0表示已生效 + } bits; + U32 value; +}; + +/* + * 描述: 等待寄存器配置成功 + */ +OS_SEC_TEXT void OsGicdWaitCfgWork(void) +{ + union GicdCtrl gicdCtrl; + + do { + gicdCtrl.value = GIC_REG_READ(GICD_CTLR_S_ADDR); + } while (gicdCtrl.bits.rwp == 1); +} + +/* + * 描述: 获取SPI中断的使能状态, 调用者保证入参的有效性 + */ +OS_SEC_TEXT enum GicIntState OsGicdGetIntState(U32 intId) +{ + // 每个寄存器对应32个中断 + return OsGicGetReg(GICD_ISENABLER0_ADDR, GIC_IENABLE_INT_NUM, intId); +} + +/* + * 描述: 使能SPI中断, 调用者保证入参的有效性 + */ +OS_SEC_TEXT void OsGicdEnableInt(U32 intId) +{ + // 每个寄存器对应32个中断,写1使能中断,写0无效 + OsGicSetReg(GICD_ISENABLER0_ADDR, GIC_IENABLE_INT_NUM, intId, 1); + + OsGicdWaitCfgWork(); +} + +/* + * 描述: 去使能SPI中断, 调用者保证入参的有效性 + */ +OS_SEC_TEXT void OsGicdDisableInt(U32 intId) +{ + // 每个寄存器对应32个中断,写1去使能中断,写0无效 + OsGicSetReg(GICD_ICENABLER0_ADDR, GIC_IENABLE_INT_NUM, intId, 1); + + OsGicdWaitCfgWork(); +} + +/* + * 描述: 设置SPI中断的优先级, 调用者保证入参的有效性 + */ +OS_SEC_L4_TEXT void OsGicdSetPriority(U32 intId, U32 priority) +{ + // 每个寄存器对应4个中断, 每8bit中的高4bit对应一个中断优先级 + OsGicRmwReg(GICD_SGI_IPRIORITY_S_ADDR, GIC_IPRIORITY_INT_NUM, intId, priority << GIC_IPRIORITY_HIGH_BIT); +} + +/* + * 描述: 获取SPI中断的优先级, 调用者保证入参的有效性 + */ +OS_SEC_L4_TEXT U32 OsGicdGetPriority(U32 intId) +{ + U32 priority; + + // 每个寄存器对应4个中断 + priority = OsGicGetReg(GICD_SGI_IPRIORITY_S_ADDR, GIC_IPRIORITY_INT_NUM, intId); + + return priority >> GIC_IPRIORITY_HIGH_BIT; // 每8bit中的高4bit对应一个中断的优先级, 低4bit预留。 +} + +/* + * 描述: 配置SPI中断的目标核, 调用者保证入参的有效性 + */ +OS_SEC_TEXT void OsGicdCfgTargetId(U32 intId, U32 targetId) +{ + union GicdRouter gicdRouter; + uintptr_t addr; + + addr = OsGicGetRouterAddr(intId); + gicdRouter.value = GIC_REG_READ(addr); + + /* 当前仅支持1-1模式 */ + gicdRouter.bits.mode = 0x0; + if (g_gicCoreMap.bits.mt == 0) { + /* single-thread 模式下,核号取AFF0 */ + gicdRouter.bits.af1 = 0; + gicdRouter.bits.af0 = targetId; + } else { + /* muti-thread 模式下,核号取AFF1 */ + gicdRouter.bits.af0 = 0; + gicdRouter.bits.af1 = targetId; + } + + GIC_REG_WRITE(addr, gicdRouter.value); +} diff --git a/src/arch/drv/gic/prt_gicr_init.c b/src/arch/drv/gic/prt_gicr_init.c new file mode 100644 index 0000000..aa98149 --- /dev/null +++ b/src/arch/drv/gic/prt_gicr_init.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-18 + * Description: 硬件GICR相关的处理。 + */ +#include "prt_gic_external.h" +#include "prt_gic_internal.h" +#include "prt_attr_external.h" + +/* GICR_CTRL */ +union GicrCtrl { + struct { + U32 enLpis : 1; // bit[0] LPIs中断使能控制寄存器 + U32 res2 : 2; // bit[2:1] + U32 rwp : 1; // bit[3] 标识前面一次写GICR寄存器的配置信息是否生效 + U32 res1 : 20; // bit[23:4] + U32 dpg0 : 1; // bit[24] + U32 dpg1ns : 1; // bit[25] + U32 dpg1s : 1; // bit[26] + U32 res0 : 4; // bit[30:27] + U32 uwp : 1; // bit[31] GICD对Upstream Write和Generate SGI是否可见 + } bits; + U32 value; +}; + +/* + * 描述: 等待写寄存器操作生效 + */ +OS_SEC_TEXT void OsGicrWaitCfgWork(U32 coreId) +{ + union GicrCtrl gicrCtrl; + uintptr_t regAddr; + + regAddr = GICR_CTRL_ADDR + (coreId * GICR_ADDR_OFFSET_PER_CORE); + do { + gicrCtrl.value = GIC_REG_READ(regAddr); + } while (gicrCtrl.bits.rwp == 1); +} + +/* + * 描述: 获取PPI, SGI, NNSPI的使能状态, 调用者保证入参的有效性 + */ +OS_SEC_TEXT enum GicIntState OsGicrGetIntState(U32 coreId, U32 intId) +{ + // 每个寄存器对应32个中断 + return OsGicGetReg(GICR_ISENABLER0_ADDR + coreId * GICR_ADDR_OFFSET_PER_CORE, + GIC_IENABLE_INT_NUM, intId); +} + +/* + * 描述: 使能PPI, SGI, NNSPI, 调用者保证入参的有效性 + */ +OS_SEC_TEXT void OsGicrEnableInt(U32 coreId, U32 intId) +{ + // 每个寄存器对应32个中断,写1使能中断,写0无效 + OsGicSetReg(GICR_ISENABLER0_ADDR + coreId * GICR_ADDR_OFFSET_PER_CORE, + GIC_IENABLE_INT_NUM, intId, 1); + + OsGicrWaitCfgWork(coreId); // 确保操作生效 +} + +/* + * 描述: 去使能PPI, SGI, NNSPI, 调用者保证入参的有效性 + */ +OS_SEC_TEXT void OsGicrDisableInt(U32 coreId, U32 intId) +{ + // 每个寄存器对应32个中断,写1去使能中断,写0无效 + OsGicSetReg(GICR_ICENABLER0_ADDR + coreId * GICR_ADDR_OFFSET_PER_CORE, + GIC_IENABLE_INT_NUM, intId, 1); + + OsGicrWaitCfgWork(coreId); // 确保操作生效 +} + +/* + * 描述: 设置SGI, PPI, NNSPI中断的优先级, 调用者保证入参的有效性 + */ +OS_SEC_L4_TEXT void OsGicrSetPriority(U32 coreId, U32 intId, U32 priority) +{ + // 每个寄存器对应4个中断, 每8bit中的高4bit对应一个中断优先级 + OsGicRmwReg(GICR_IPRIORITY_SGI_S_ADDR + coreId * GICR_ADDR_OFFSET_PER_CORE, + GIC_IPRIORITY_INT_NUM, intId, priority << GIC_IPRIORITY_HIGH_BIT); +} + +/* + * 描述: 获取SGI, PPI, NNSPI中断的优先级, 调用者保证入参的有效性 + */ +OS_SEC_L2_TEXT U32 OsGicrGetPriority(U32 coreId, U32 intId) +{ + U32 gicrPrio; + + // 每个寄存器(32位)对应4个中断, 即每8bit对应1个中断 + gicrPrio = OsGicGetReg(GICR_IPRIORITY_SGI_S_ADDR + coreId * GICR_ADDR_OFFSET_PER_CORE, + GIC_IPRIORITY_INT_NUM, intId); + + return (gicrPrio >> GIC_IPRIORITY_HIGH_BIT); // 4: 每8bit中的高4bit对应一个中断的优先级, 低4bit预留。 +} diff --git a/src/arch/include/prt_asm_arm_external.h b/src/arch/include/prt_asm_arm_external.h index db3fc02..c2b16f5 100644 --- a/src/arch/include/prt_asm_arm_external.h +++ b/src/arch/include/prt_asm_arm_external.h @@ -15,6 +15,10 @@ #ifndef PRT_ASM_ARM_EXTERNAL_H #define PRT_ASM_ARM_EXTERNAL_H +#if defined(OS_ARCH_ARMV8) +#include "../cpu/armv8/common/os_asm_cpu_armv8_external.h" +#endif + /* * 描述 : stack_chk_guard支持用户传入seed写入函数宏 * argA argB argC 需要使用处传入三个可用寄存器 diff --git a/src/arch/include/prt_attr_external.h b/src/arch/include/prt_attr_external.h index 69f5097..9616fbd 100644 --- a/src/arch/include/prt_attr_external.h +++ b/src/arch/include/prt_attr_external.h @@ -21,4 +21,8 @@ #include "../cpu/armv7-m/common/os_attr_armv7_m_external.h" #endif +#if defined(OS_ARCH_ARMV8) +#include "../cpu/armv8/common/os_attr_armv8_external.h" +#endif + #endif /* PRT_ATTR_EXTERNAL_H */ diff --git a/src/arch/include/prt_cpu_external.h b/src/arch/include/prt_cpu_external.h index d52e2fa..429edb1 100644 --- a/src/arch/include/prt_cpu_external.h +++ b/src/arch/include/prt_cpu_external.h @@ -35,4 +35,8 @@ extern void OsTickStartRegSet(U16 tickHwTimerIndex, U32 cyclePerTick); #include "../cpu/armv7-m/common/os_cpu_armv7_m_external.h" #endif +#if defined(OS_ARCH_ARMV8) +#include "../cpu/armv8/common/os_cpu_armv8_external.h" +#endif + #endif /* PRT_CPU_EXTERNAL_H */ diff --git a/src/arch/include/prt_gic_external.h b/src/arch/include/prt_gic_external.h new file mode 100644 index 0000000..1968868 --- /dev/null +++ b/src/arch/include/prt_gic_external.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2020-06-16 + * Description: 硬件GIC内部公共头文件 + */ +#ifndef PRT_GIC_EXTERNAL_H +#define PRT_GIC_EXTERNAL_H + +#include "prt_lib_external.h" +#include "prt_buildef.h" + +// 配置中断优先级,每个寄存器对应4个中断 +#define GIC_IPRIORITY_INT_NUM 4 +// 配置中断优先级,每8bit的高4bit有效,低bit预留 +#define GIC_IPRIORITY_HIGH_BIT 4 + +#if (OS_GIC_VER == 2) +#define GIC_DIST_BASE 0xff841000 +#define GIC_CPU_BASE 0xff842000 +#define IAR_MASK 0x3FFU +#define GICC_IAR (GIC_CPU_BASE + 0xc) +#define GICC_EOIR (GIC_CPU_BASE + 0x10) +#define GICD_SGIR (GIC_DIST_BASE + 0xf00) +#elif (OS_GIC_VER == 3) +#define ICC_IAR1_EL1 S3_0_C12_C12_0 +#define ICC_EOIR1_EL1 S3_0_C12_C12_1 +#define ICC_SGI1R_EL1 S3_0_C12_C11_5 +#endif +#define GIC_REG_BASE g_gicdBase +#define MAX_SGI_ID 15 // 系统支持的最大SGI的中断号 +#define MIN_PPI_ID 16 // 系统支持的最小PPI的中断号 +#define MAX_PPI_ID 31 // 系统支持的最大PPI的中断号 +#define MAX_SPI_ID 1019 // 系统可支持的最大SPI的中断号 +#define MAX_INT_PRIORITY 0xF // 安全可配置的最大优先级 +#define GIC_INT_ID_MASK 0x3FFU +// 使能/去使能中断,每个寄存器对应32个中断 +#define GIC_IENABLE_INT_NUM 32 +// 将变参列表字符串化 +#define PARAS_TO_STRING(x...) #x +// 获得变参的值 +#define REG_ALIAS(x...) PARAS_TO_STRING(x) +// 读写GIC寄存器,32位 +#define GIC_REG_READ(addr) (*(volatile U32 *)((uintptr_t)(addr))) +#define GIC_REG_WRITE(addr, data) (*(volatile U32 *)((uintptr_t)(addr)) = (U32)(data)) + +enum GicIntState { + GIC_DISABLE = 0, + GIC_ENABLE = 1 +}; + +/* 存放Core Map值 */ +union GicCoreMap { + struct { + U64 aff0 : 8; // bit[7:0] + U64 aff1 : 8; // bit[15:8] + U64 aff2 : 8; // bit[23:16] + U64 mt : 1; // bit[24] 0:single-thread 核号取AFF0, 1: muti-thread 模式,核号取AFF1 + U64 rsvd0 : 5; // bit[29:25] + U64 uni : 1; // bit[30] + U64 rsvd1 : 1; // bit[31] + U64 aff3 : 8; // bit[39:32] + U64 rsvd2 : 24; // bit[63~40] + } bits; + U64 value; +}; + +/* + * 描述: 按bit设置GIC寄存器, Read-Modify-Write方式 + */ +OS_SEC_ALW_INLINE INLINE void OsGicRmwReg(uintptr_t base, U32 intNum, U32 intId, U32 val) +{ + uintptr_t regAddr; + U32 regVal; + U32 offset; + U32 bitWidth; + U32 bitMask; + + // 每个寄存器(32位)可配置idNum个硬中断 + bitWidth = OS_WORD_BIT_NUM / intNum; // 每个硬中断对应的bit位宽:32 / idNum + bitMask = (1u << bitWidth) - 1u; // 每个硬中断对应的bit掩码 + regAddr = base + ((intId / intNum) * sizeof(U32)); + offset = ((intId % intNum) * bitWidth); + + regVal = GIC_REG_READ(regAddr); + regVal &= ~(bitMask << offset); // 清除旧值 + regVal |= ((val & bitMask) << offset); // 设置新值 + GIC_REG_WRITE(regAddr, regVal); +} + +/* + * 描述: 按bit设置GIC寄存器, 直接写,写前不需要先读 + */ +OS_SEC_ALW_INLINE INLINE void OsGicSetReg(uintptr_t base, U32 intNum, U32 intId, U32 val) +{ + uintptr_t regAddr; + U32 regVal; + U32 offset; + U32 bitWidth; + U32 bitMask; + + // 每个寄存器(32位)可配置idNum个硬中断 + bitWidth = OS_WORD_BIT_NUM / intNum; // 每个硬中断对应的bit位宽:32 / idNum + bitMask = (1u << bitWidth) - 1u; // 每个硬中断对应的bit掩码 + regAddr = base + ((intId / intNum) * sizeof(U32)); + offset = ((intId % intNum) * bitWidth); + + regVal = ((val & bitMask) << offset); // 设置新值 + GIC_REG_WRITE(regAddr, regVal); +} + +/* + * 描述: 按bit读取GIC寄存器的值 + */ +OS_SEC_ALW_INLINE INLINE U32 OsGicGetReg(uintptr_t base, U32 idNum, U32 id) +{ + U64 regAddr; + U32 regVal; + U32 offset; + U32 bitWidth; + U32 bitMask; + + // 每个寄存器有idNum个id,每个id对应的bit位数为sizeof(U32) / idNum + bitWidth = OS_WORD_BIT_NUM / idNum; + bitMask = (1u << bitWidth) - 1u; + regAddr = base + ((id / idNum) * sizeof(U32)); + offset = ((id % idNum) * bitWidth); + + regVal = GIC_REG_READ(regAddr); + + return (regVal & (bitMask << offset)) >> offset; +} + +/* GIC基地址 */ +extern uintptr_t g_gicdBase; +/* GICR相对于GIC基地址偏移向量 */ +extern uintptr_t g_gicrOffset; +/* GICR核间偏移向量配置 */ +extern uintptr_t g_gicrStride; +/* 存放Core Map值 */ +extern union GicCoreMap g_gicCoreMap; + +extern void OsGicEnableInt(U32 intId); +extern void OsGicDisableInt(U32 intId); +extern void OsGicTrigIntToCores(U32 intId, U32 targetList); +extern void OsGicSetTargetId(U32 intId, U32 targetId); +extern U32 OsGicGetPriority(U32 intId); +extern U32 OsGicSetPriority(U32 intId, U32 priority); + +extern enum GicIntState OsGicdGetIntState(U32 intId); +extern void OsGicdEnableInt(U32 intId); +extern void OsGicdDisableInt(U32 intId); +extern void OsGicdSetPriority(U32 intId, U32 priority); +extern void OsGicdCfgTargetId(U32 intId, U32 targetId); +extern U32 OsGicdGetPriority(U32 intId); + +extern enum GicIntState OsGicrGetIntState(U32 coreId, U32 intId); +extern void OsGicrEnableInt(U32 coreId, U32 intId); +extern void OsGicrDisableInt(U32 coreId, U32 intId); +extern void OsGicrSetPriority(U32 coreId, U32 intId, U32 priority); +extern U32 OsGicrGetPriority(U32 coreId, U32 intId); +extern bool OsGicIsSpi(U32 intId); + +#endif /* PRT_GIC_EXTERNAL_H */ diff --git a/src/arch/include/prt_hwi_external.h b/src/arch/include/prt_hwi_external.h index f139924..a6b03cd 100644 --- a/src/arch/include/prt_hwi_external.h +++ b/src/arch/include/prt_hwi_external.h @@ -16,6 +16,7 @@ #define PRT_HWI_EXTERNAL_H #include "prt_hwi.h" +#include "prt_buildef.h" #define OS_HWI_NUM_MASK 0x1FU @@ -30,5 +31,6 @@ extern U8 g_hwiNum[]; extern void OsHwiGICInit(void); extern U32 OsHwiPriorityGet(HwiHandle hwiNum); extern void OsHwiPrioritySet(HwiHandle hwiNum, HwiPrior hwiPrio); +extern void OsHwiMcTrigger(U32 coreMask, U32 hwiNum); #endif /* PRT_HWI_EXTERNAL_H */ diff --git a/src/config/prt_config.c b/src/config/prt_config.c index d81a65c..c5dfa29 100644 --- a/src/config/prt_config.c +++ b/src/config/prt_config.c @@ -50,6 +50,7 @@ U32 OsSystemReg(void) sysModInfo.systemClock = OS_SYS_CLOCK; sysModInfo.cpuType = OS_CPU_TYPE; + sysModInfo.sysTimeHook = OS_SYS_TIME_HOOK; #if defined(OS_OPTION_HWI_MAX_NUM_CONFIG) sysModInfo.hwiMaxNum = OS_HWI_MAX_NUM_CONFIG; #endif @@ -190,12 +191,24 @@ U32 OsTskConfigInit(void) } #endif +static U32 OsHwiConfigReg(void) +{ +#if (OS_INCLUDE_GIC_BASE_ADDR_CONFIG == YES) + U32 ret; + ret = OsGicConfigRegister((uintptr_t)OS_GIC_BASE_ADDR, (uintptr_t)OS_GICR_OFFSET, (uintptr_t)OS_GICR_STRIDE); + if (ret != OS_OK) { + return ret; + } +#endif + return OS_OK; +} + /* 系统初始化注册表 */ struct OsModuleConfigInfo g_moduleConfigTab[] = { /* {模块号, 模块注册函数, 模块初始化函数} */ {OS_MID_SYS, {OsSysConfigReg, NULL}}, {OS_MID_MEM, {OsMemConfigReg, OsMemConfigInit}}, - {OS_MID_HWI, {NULL, OsHwiConfigInit}}, + {OS_MID_HWI, {OsHwiConfigReg, OsHwiConfigInit}}, {OS_MID_HARDDRV, {NULL, PRT_HardDrvInit}}, {OS_MID_HOOK, {OsHookConfigReg, OsHookConfigInit}}, {OS_MID_EXC, {NULL, OsExcConfigInit}}, diff --git a/src/config/prt_config_internal.h b/src/config/prt_config_internal.h index 974cc30..a48eeb6 100644 --- a/src/config/prt_config_internal.h +++ b/src/config/prt_config_internal.h @@ -68,6 +68,11 @@ extern U32 OsQueueConfigInit(void); extern U32 OsSwTmrInit(U32 maxTimerNum); #endif +enum OsinitPhaseId { + OS_REGISTER_ID = 0, + OS_INIT_ID, + OS_MOUDLE_CONFIG +}; typedef U32 (*ConfigInitFunc)(void); struct OsModuleConfigInfo { enum MoudleId moudleId; diff --git a/src/core/ipc/CMakeLists.txt b/src/core/ipc/CMakeLists.txt index 66e28e6..37cdccd 100644 --- a/src/core/ipc/CMakeLists.txt +++ b/src/core/ipc/CMakeLists.txt @@ -9,3 +9,6 @@ endif() add_subdirectory(sem) +if(${CONFIG_OS_OPTION_POSIX}) + add_subdirectory(rwlock) +endif() diff --git a/src/core/ipc/event/CMakeLists.txt b/src/core/ipc/event/CMakeLists.txt index 35932ee..1209a44 100644 --- a/src/core/ipc/event/CMakeLists.txt +++ b/src/core/ipc/event/CMakeLists.txt @@ -1 +1 @@ -add_library(prt_event OBJECT prt_event.c) +add_library_ex(prt_event.c) diff --git a/src/core/ipc/include/prt_sem_external.h b/src/core/ipc/include/prt_sem_external.h index d89249d..5f65740 100644 --- a/src/core/ipc/include/prt_sem_external.h +++ b/src/core/ipc/include/prt_sem_external.h @@ -17,33 +17,57 @@ #include "prt_sem.h" #include "prt_task_external.h" +#if defined(OS_OPTION_POSIX) +#include "semaphore.h" +#include "prt_posix_internal.h" +#endif #define OS_SEM_UNUSED 0 -#define OS_SEM_USED 1 +#define OS_SEM_USED 1 -#define OS_SEM_WITH_LOCK_FLAG 1 +#define SEM_PROTOCOL_PRIO_INHERIT 1 +#define SEM_TYPE_BIT_WIDTH 0x4U +#define SEM_PROTOCOL_BIT_WIDTH 0x8U + +#define OS_SEM_WITH_LOCK_FLAG 1 #define OS_SEM_WITHOUT_LOCK_FLAG 0 #define GET_SEM_LIST(ptr) LIST_COMPONENT(ptr, struct TagSemCb, semList) #define GET_SEM(semid) (((struct TagSemCb *)g_allSem) + (semid)) #define GET_SEM_TSK(semid) (((SEM_TSK_S *)g_semTsk) + (semid)) #define GET_TSK_SEM(tskid) (((TSK_SEM_S *)g_tskSem) + (tskid)) +#define GET_SEM_TYPE(semType) (U32)((semType) & ((1U << SEM_TYPE_BIT_WIDTH) - 1)) +#define GET_MUTEX_TYPE(semType) (U32)(((semType) >> SEM_TYPE_BIT_WIDTH) & ((1U << SEM_TYPE_BIT_WIDTH) - 1)) +#define GET_SEM_PROTOCOL(semType) (U32)((semType) >> SEM_PROTOCOL_BIT_WIDTH) struct TagSemCb { /* 是否使用 OS_SEM_UNUSED/OS_SEM_USED */ U16 semStat; /* 核内信号量索引号 */ U16 semId; +#if defined(OS_OPTION_SEM_RECUR_PV) + /* 二进制互斥信号量递归P计数,计数型信号量和二进制同步模式信号量无效 */ + U32 recurCount; +#endif /* 当该信号量已用时,其信号量计数 */ U32 semCount; /* 挂接阻塞于该信号量的任务 */ struct TagListObject semList; - U32 maxSemCount; + /* 挂接任务持有的互斥信号量,计数型信号量信号量无效 */ + struct TagListObject semBList; /* Pend到该信号量的线程ID */ U32 semOwner; /* 信号量唤醒阻塞任务的方式 */ enum SemMode semMode; + /* 信号量,计数型或二进制 */ + U32 semType; +#if defined(OS_OPTION_POSIX) + /* 信号量名称 */ + char name[MAX_POSIX_SEMAPHORE_NAME_LEN + 1]; // + \0 + /* sem_open 句柄 */ + sem_t handle; +#endif }; /* 模块间全局变量声明 */ @@ -51,4 +75,7 @@ extern U16 g_maxSem; /* 指向核内信号量控制块 */ extern struct TagSemCb *g_allSem; + +extern U32 OsSemCreate(U32 count, U32 semType, enum SemMode semMode, SemHandle *semHandle, U32 cookie); + #endif /* PRT_SEM_EXTERNAL_H */ diff --git a/src/core/ipc/queue/CMakeLists.txt b/src/core/ipc/queue/CMakeLists.txt index b70510b..2c06f75 100644 --- a/src/core/ipc/queue/CMakeLists.txt +++ b/src/core/ipc/queue/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(prt_queue OBJECT prt_queue.c) -add_library(prt_queue_del OBJECT prt_queue_del.c) -add_library(prt_queue_minor OBJECT prt_queue_minor.c) -add_library(prt_queue_init OBJECT prt_queue_init.c) +add_library_ex(prt_queue.c) +add_library_ex(prt_queue_del.c) +add_library_ex(prt_queue_minor.c) +add_library_ex(prt_queue_init.c) diff --git a/src/core/ipc/queue/prt_queue.c b/src/core/ipc/queue/prt_queue.c index be29bb1..ffc8364 100644 --- a/src/core/ipc/queue/prt_queue.c +++ b/src/core/ipc/queue/prt_queue.c @@ -22,7 +22,7 @@ OS_SEC_ALW_INLINE INLINE U32 OsGetSrcPid(void) if (OS_HWI_ACTIVE) { /* 硬中断创建消息不具体区别中断号 */ - srcPid = COMPOSE_PID(OsGetHwThreadId(), OS_HWI_HANDLE); + srcPid = COMPOSE_PID(0x0U, OS_HWI_HANDLE); } else { srcPid = RUNNING_TASK->taskPid; } diff --git a/src/core/ipc/rwlock/CMakeLists.txt b/src/core/ipc/rwlock/CMakeLists.txt new file mode 100644 index 0000000..16f1376 --- /dev/null +++ b/src/core/ipc/rwlock/CMakeLists.txt @@ -0,0 +1 @@ +add_library_ex(prt_rwlock.c) diff --git a/src/core/ipc/rwlock/prt_rwlock.c b/src/core/ipc/rwlock/prt_rwlock.c new file mode 100644 index 0000000..ae379e7 --- /dev/null +++ b/src/core/ipc/rwlock/prt_rwlock.c @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: pthread rwlock功能实现 + */ +#include "prt_rwlock_internal.h" +#include "prt_task_external.h" + +OS_SEC_ALW_INLINE INLINE bool OsRwlockPriCompare(struct TagTskCb *runTask, struct TagListObject *rwList) +{ + struct TagTskCb *task; + + if (!ListEmpty(rwList)) { + task = GET_TCB_PEND(LIST_FIRST(rwList)); + if (runTask->priority < task->priority) { + return TRUE; + } + return FALSE; + } + return TRUE; +} + +struct TagListObject *OsRwLockPendFindPosSub(const struct TagTskCb *runTask, const struct TagListObject *lockList) +{ + struct TagTskCb *pendedTask; + struct TagListObject *node = NULL; + + LIST_FOR_EACH_SAFE(pendedTask, lockList, struct TagTskCb, pendList) { + if (pendedTask->priority < runTask->priority) { + continue; + } else if (pendedTask->priority > runTask->priority) { + node = &pendedTask->pendList; + break; + } else { + node = pendedTask->pendList.next; + break; + } + } + + return node; +} + +struct TagListObject *OsRwLockPendFindPos(struct TagTskCb *runTask, struct TagListObject *lockList) +{ + struct TagListObject *node = NULL; + struct TagTskCb *taskFirst; + struct TagTskCb *taskLast; + + if (ListEmpty(lockList)) { + node = lockList; + } else { + taskFirst = GET_TCB_PEND(LIST_FIRST(lockList)); + taskLast = GET_TCB_PEND(LIST_LAST(lockList)); + if (taskFirst->priority > runTask->priority) { + node = lockList->next; + } else if (taskLast->priority <= runTask->priority) { + node = lockList; + } else { + node = OsRwLockPendFindPosSub(runTask, lockList); + } + } + + return node; +} + +void OsRwLockPendPre(struct TagTskCb *runTask, struct TagListObject *list, U32 timeout) +{ + OsTskReadyDel(runTask); + + TSK_STATUS_SET(runTask, OS_TSK_PEND); + + if (timeout != OS_WAIT_FOREVER) { + TSK_STATUS_SET(runTask, OS_TSK_TIMEOUT); + OsTskTimerAdd(runTask, timeout); + } + + ListTailAdd(&(runTask->pendList), list); +} + +void OsRwLockTaskWake(struct TagTskCb *resumedTask) +{ + ListDelete(&resumedTask->pendList); + + if (TSK_STATUS_TST(resumedTask, OS_TSK_TIMEOUT)) { + OS_TSK_DELAY_LOCKED_DETACH(resumedTask); + } + + TSK_STATUS_CLEAR(resumedTask, OS_TSK_TIMEOUT | OS_TSK_PEND); + + if (!TSK_STATUS_TST(resumedTask, OS_TSK_SUSPEND_READY_BLOCK)) { + OsTskReadyAddBgd(resumedTask); + } +} + +U32 OsRwLockTryRdCheck(struct TagTskCb *runTask, prt_pthread_rwlock_t *rwl) +{ + if ((struct TagTskCb *)(rwl->rw_owner) == runTask) { + return EINVAL; + } + + /* 读写锁为读模式或者初始化模式,并且当前读锁任务的优先级比第一个写锁pend任务的优先级低, + * 当前读锁任务不能获取锁 + */ + if ((rwl->rw_count >= 0) && !OsRwlockPriCompare(runTask, &(rwl->rw_write))) { + return EBUSY; + } + + /* 读写锁被写锁获得,当前读锁任务不能获取锁 */ + if (rwl->rw_count < 0) { + return EBUSY; + } + + return OS_OK; +} + +U32 OsRwlockTryWrCheck(struct TagTskCb *runTask, prt_pthread_rwlock_t *rwl) +{ + /* 读写锁被读锁获得,当前写锁任务不能获取锁 */ + if (rwl->rw_count > 0) { + return EBUSY; + } + + /* 读写锁被写锁获得,当前写锁任务不能获取锁. */ + if ((rwl->rw_count < 0) && ((struct TagTskCb *)(rwl->rw_owner) != runTask)) { + return EBUSY; + } + + return OS_OK; +} + +OS_SEC_ALW_INLINE INLINE U32 OsRwLockCheck(prt_pthread_rwlock_t *rwl) +{ + if (rwl == NULL) { + return EINVAL; + } + + if ((rwl->rw_magic & RWLOCK_COUNT_MASK) != RWLOCK_MAGIC_NUM) { + return EINVAL; + } + + if (OS_INT_ACTIVE) { + return EINVAL; + } + + if (OS_TASK_LOCK_DATA != 0) { + return EDEADLK; + } + + return OS_OK; +} + +U32 OsRwLockPendSchedule(struct TagTskCb *runTask, struct TagListObject *lockList, U32 timeout, U32 intSave) +{ + struct TagListObject *node; + + if (timeout == 0) { + PRT_HwiRestore(intSave); + return EINVAL; + } + + node = OsRwLockPendFindPos(runTask, lockList); + OsRwLockPendPre(runTask, node, timeout); + if (timeout != OS_WAIT_FOREVER) { + PRT_HwiRestore(intSave); + OsTskSchedule(); + intSave = PRT_HwiLock(); + /* 判断是否是等待信号量超时 */ + if (TSK_STATUS_TST(runTask, OS_TSK_TIMEOUT)) { + TSK_STATUS_CLEAR(runTask, OS_TSK_TIMEOUT); + PRT_HwiRestore(intSave); + return ETIMEDOUT; + } + PRT_HwiRestore(intSave); + } else { + PRT_HwiRestore(intSave); + OsTskSchedule(); + } + + return OS_OK; +} + +U32 OsRwLockRdPend(prt_pthread_rwlock_t *rwl, U32 timeout, U32 rwType) +{ + U32 ret; + U32 intSave; + struct TagTskCb *runTask = NULL; + + intSave = PRT_HwiLock(); + + ret = OsRwLockCheck(rwl); + if (ret != OS_OK) { + PRT_HwiRestore(intSave); + return ret; + } + + runTask = (struct TagTskCb *)RUNNING_TASK; + + if (rwType == RWLOCK_TRYRD) { + ret = OsRwLockTryRdCheck(runTask, rwl); + if (ret != OS_OK) { + PRT_HwiRestore(intSave); + return ret; + } + } + + /* + * 读写锁为读模式或者初始化模式,并且当前读锁任务的优先级比第一个写锁pend任务的优先级高, + * 当前读锁任务能获取锁 + */ + if (rwl->rw_count >= 0) { + if (OsRwlockPriCompare(runTask, &(rwl->rw_write))) { + if (rwl->rw_count == S32_MAX) { + PRT_HwiRestore(intSave); + return EINVAL; + } + rwl->rw_count++; + PRT_HwiRestore(intSave); + return OS_OK; + } + } + + if ((struct TagTskCb *)(rwl->rw_owner) == runTask) { + PRT_HwiRestore(intSave); + return EINVAL; + } + + return OsRwLockPendSchedule(runTask, &(rwl->rw_read), timeout, intSave); +} + +U32 OsRwLockWrPend(prt_pthread_rwlock_t *rwl, U32 timeout, U32 rwType) +{ + U32 ret; + U32 intSave; + struct TagTskCb *runTask; + + intSave = PRT_HwiLock(); + + ret = OsRwLockCheck(rwl); + if (ret != OS_OK) { + PRT_HwiRestore(intSave); + return ret; + } + + runTask = (struct TagTskCb *)RUNNING_TASK; + if (rwType == RWLOCK_TRYWR) { + ret = OsRwlockTryWrCheck(runTask, rwl); + if (ret != OS_OK) { + PRT_HwiRestore(intSave); + return ret; + } + } + + if (rwl->rw_count == 0) { + rwl->rw_count = -1; + rwl->rw_owner = (void *)runTask; + PRT_HwiRestore(intSave); + return OS_OK; + } + + /* 如果读写锁被自身获取,只能获取一次. */ + if ((rwl->rw_count < 0) && ((struct TagTskCb *)(rwl->rw_owner) == runTask)) { + if (rwl->rw_count == S32_MIN) { + PRT_HwiRestore(intSave); + return EINVAL; + } + PRT_HwiRestore(intSave); + return OS_OK; + } + + return OsRwLockPendSchedule(runTask, &(rwl->rw_write), timeout, intSave); +} + +U32 OsRwLockGetMode(struct TagListObject *readList, struct TagListObject *writeList) +{ + bool isReadEmpty = ListEmpty(readList); + bool isWriteEmpty = ListEmpty(writeList); + if (isReadEmpty && isWriteEmpty) { + return RWLOCK_NONE_MODE; + } + if (!isReadEmpty && isWriteEmpty) { + return RWLOCK_READ_MODE; + } + if (isReadEmpty && !isWriteEmpty) { + return RWLOCK_WRITE_MODE; + } + + struct TagTskCb *pendedReadTask = GET_TCB_PEND(LIST_FIRST(readList)); + struct TagTskCb *pendedWriteTask = GET_TCB_PEND(LIST_FIRST(writeList)); + if (pendedWriteTask->priority <= pendedReadTask->priority) { + return RWLOCK_WRITEFIRST_MODE; + } + return RWLOCK_READFIRST_MODE; +} + +U32 OsRwLockPost(prt_pthread_rwlock_t *rwl, bool *needSched) +{ + U32 rwlockMode; + struct TagTskCb *resumedTask = NULL; + U32 pendedWriteTaskPri = 0; + + rwl->rw_count = 0; + rwl->rw_owner = NULL; + rwlockMode = OsRwLockGetMode(&(rwl->rw_read), &(rwl->rw_write)); + if (rwlockMode == RWLOCK_NONE_MODE) { + return OS_OK; + } + + /* 唤醒第一个被pend的写锁任务 */ + if ((rwlockMode == RWLOCK_WRITE_MODE) || (rwlockMode == RWLOCK_WRITEFIRST_MODE)) { + resumedTask = GET_TCB_PEND(LIST_FIRST(&(rwl->rw_write))); + rwl->rw_count = -1; + rwl->rw_owner = (void *)resumedTask; + OsRwLockTaskWake(resumedTask); + if (needSched != NULL) { + *needSched = TRUE; + } + return OS_OK; + } + + /* 唤醒被pend的读锁任务 */ + if (rwlockMode == RWLOCK_READFIRST_MODE) { + pendedWriteTaskPri = GET_TCB_PEND(LIST_FIRST(&(rwl->rw_write)))->priority; + } + + resumedTask = GET_TCB_PEND(LIST_FIRST(&(rwl->rw_read))); + rwl->rw_count = 1; + OsRwLockTaskWake(resumedTask); + while (!ListEmpty(&(rwl->rw_read))) { + resumedTask = GET_TCB_PEND(LIST_FIRST(&(rwl->rw_read))); + if ((rwlockMode == RWLOCK_READFIRST_MODE) && (resumedTask->priority >= pendedWriteTaskPri)) { + break; + } + + if (rwl->rw_count == S32_MAX) { + return EINVAL; + } + + rwl->rw_count++; + OsRwLockTaskWake(resumedTask); + } + + if (needSched != NULL) { + *needSched = TRUE; + } + return OS_OK; +} + +U32 OsRwLockUnlock(prt_pthread_rwlock_t *rwl, bool *needSched) +{ + struct TagTskCb *runTask; + + if (rwl == NULL) { + return EINVAL; + } + if ((rwl->rw_magic & RWLOCK_COUNT_MASK) != RWLOCK_MAGIC_NUM) { + return EINVAL; + } + + if (rwl->rw_count == 0) { + return EPERM; + } + + runTask = RUNNING_TASK; + if ((rwl->rw_count < 0) && ((struct TagTskCb *)(rwl->rw_owner) != runTask)) { + return EPERM; + } + + if (rwl->rw_count > 1) { + rwl->rw_count--; + return OS_OK; + } + + if (rwl->rw_count < -1) { + rwl->rw_count++; + return OS_OK; + } + + return OsRwLockPost(rwl, needSched); +} diff --git a/src/core/ipc/rwlock/prt_rwlock_internal.h b/src/core/ipc/rwlock/prt_rwlock_internal.h new file mode 100644 index 0000000..e21028a --- /dev/null +++ b/src/core/ipc/rwlock/prt_rwlock_internal.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: 读写锁模块内部头文件。 + */ +#ifndef PRT_RWLOCK_INTERNAL_H +#define PRT_RWLOCK_INTERNAL_H + +#include "prt_buildef.h" +#include "prt_typedef.h" +#include "prt_list_external.h" + +#define RWLOCK_COUNT_MASK 0x0000FFFFU +#define RWLOCK_MAGIC_NUM 0xFDCAU + +enum RwlockMode { + RWLOCK_NONE_MODE, + RWLOCK_READ_MODE, + RWLOCK_WRITE_MODE, + RWLOCK_READFIRST_MODE, + RWLOCK_WRITEFIRST_MODE +}; + +enum RwlockType { + RWLOCK_RD, + RWLOCK_TRYRD, + RWLOCK_TIMERD, + RWLOCK_WR, + RWLOCK_TRYWR, + RWLOCK_TIMEWR +}; + +#if defined(OS_POSIX_TYPE_NEWLIB) +typedef struct prt_pthread_rwlock_s { + U32 rw_magic : 16; + U32 index : 16; + int rw_count; + void *rw_owner; + struct prt_pthread_rwlock_s *next; + struct TagListObject rw_write; + struct TagListObject rw_read; +} prt_pthread_rwlock_t; +#else +typedef pthread_rwlock_t prt_pthread_rwlock_t; +#endif + +extern U32 OsRwLockRdPend(prt_pthread_rwlock_t *rwl, U32 timeout, U32 rwType); +extern U32 OsRwLockWrPend(prt_pthread_rwlock_t *rwl, U32 timeout, U32 rwType); +extern U32 OsRwLockUnlock(prt_pthread_rwlock_t *rwl, bool *needSched); + +#endif /* PRT_RWLOCK_INTERNAL_H */ diff --git a/src/core/ipc/sem/CMakeLists.txt b/src/core/ipc/sem/CMakeLists.txt index 42bbc79..db217e1 100644 --- a/src/core/ipc/sem/CMakeLists.txt +++ b/src/core/ipc/sem/CMakeLists.txt @@ -1,3 +1,3 @@ -add_library(prt_sem OBJECT prt_sem.c) -add_library(prt_sem_init OBJECT prt_sem_init.c) -add_library(prt_sem_minor OBJECT prt_sem_minor.c) +add_library_ex(prt_sem.c) +add_library_ex(prt_sem_init.c) +add_library_ex(prt_sem_minor.c) diff --git a/src/core/ipc/sem/prt_sem.c b/src/core/ipc/sem/prt_sem.c index a038a45..9f92244 100644 --- a/src/core/ipc/sem/prt_sem.c +++ b/src/core/ipc/sem/prt_sem.c @@ -18,6 +18,58 @@ /* 核内信号量最大个数 */ OS_SEC_BSS U16 g_maxSem; +#if defined(OS_OPTION_BIN_SEM) +OS_SEC_ALW_INLINE INLINE U32 OsSemPostErrorCheck(struct TagSemCb *semPosted, SemHandle semHandle) +{ + (void)semHandle; + /* 检查信号量控制块是否UNUSED,排除大部分错误场景 */ + if (semPosted->semStat == OS_SEM_UNUSED) { + return OS_ERRNO_SEM_INVALID; + } + if (GET_SEM_TYPE((semPosted)->semType) == SEM_TYPE_COUNT) { + /* 释放计数型信号量且信号量计数大于最大计数 */ + if ((semPosted)->semCount >= OS_SEM_COUNT_MAX) { + return OS_ERRNO_SEM_OVERFLOW; + } + } else if (GET_SEM_TYPE(semPosted->semType) == SEM_TYPE_BIN) { + if (OS_INT_ACTIVE) { + return OS_ERRNO_SEM_MUTEX_POST_INTERR; + } + + /* 如果不是 互斥信号量的持有任务来做post操作 */ + if (semPosted->semOwner != RUNNING_TASK->taskPid) { + return OS_ERRNO_SEM_MUTEX_NOT_OWNER_POST; + } + } + return OS_OK; +} + +OS_SEC_ALW_INLINE INLINE void OsSemPostBinMutex(struct TagSemCb *semPosted, struct TagTskCb *resumedTask) +{ + semPosted->semOwner = resumedTask->taskPid; + if (semPosted->semType == SEM_TYPE_BIN) { + ListDelete(&semPosted->semBList); + ListTailAdd(&semPosted->semBList, &resumedTask->semBList); + } +} +#else +OS_SEC_ALW_INLINE INLINE U32 OsSemPostErrorCheck(struct TagSemCb *semPosted, SemHandle semHandle) +{ + (void)semHandle; + /* 检查信号量控制块是否UNUSED,排除大部分错误场景 */ + if (semPosted->semStat == OS_SEM_UNUSED) { + return OS_ERRNO_SEM_INVALID; + } + + /* post计数型信号量的错误场景, 释放计数型信号量且信号量计数大于最大计数 */ + if ((semPosted)->semCount >= OS_SEM_COUNT_MAX) { + return OS_ERRNO_SEM_OVERFLOW; + } + + return OS_OK; +} +#endif + /* * 描述:把当前运行任务挂接到信号量链表上 */ @@ -51,7 +103,6 @@ TIMER_ADD: TSK_STATUS_SET(runTsk, OS_TSK_TIMEOUT); } - } /* @@ -67,7 +118,7 @@ OS_SEC_L0_TEXT struct TagTskCb *OsSemPendListGet(struct TagSemCb *semPended) OS_TSK_DELAY_LOCKED_DETACH(taskCb); } - // 必须先去除 OS_TSK_TIMEOUT 态,再入队[睡眠时是先出ready队,再置OS_TSK_TIMEOUT态] + /* 必须先去除 OS_TSK_TIMEOUT 态,再入队[睡眠时是先出ready队,再置OS_TSK_TIMEOUT态] */ TSK_STATUS_CLEAR(taskCb, OS_TSK_TIMEOUT | OS_TSK_PEND); taskCb->taskSem = NULL; /* 如果去除信号量阻塞位后,该任务不处于阻塞态则将该任务挂入就绪队列并触发任务调度 */ @@ -75,6 +126,9 @@ OS_SEC_L0_TEXT struct TagTskCb *OsSemPendListGet(struct TagSemCb *semPended) OsTskReadyAddBgd(taskCb); } +#if defined(OS_OPTION_BIN_SEM) + OsSemPostBinMutex(semPended, taskCb); +#endif return taskCb; } @@ -84,7 +138,6 @@ OS_SEC_L0_TEXT U32 OsSemPendParaCheck(U32 timeout) return OS_ERRNO_SEM_UNAVAILABLE; } - /* 如果锁任务的情况下 */ if (OS_TASK_LOCK_DATA != 0) { return OS_ERRNO_SEM_PEND_IN_LOCK; } @@ -93,11 +146,23 @@ OS_SEC_L0_TEXT U32 OsSemPendParaCheck(U32 timeout) OS_SEC_L0_TEXT bool OsSemPendNotNeedSche(struct TagSemCb *semPended, struct TagTskCb *runTsk) { - // 信号量获取成功 +#if defined(OS_OPTION_SEM_RECUR_PV) + if (GET_SEM_TYPE(semPended->semType) == SEM_TYPE_BIN && semPended->semOwner == runTsk->taskPid && + (GET_MUTEX_TYPE(semPended->semType) == PTHREAD_MUTEX_RECURSIVE)) { + semPended->recurCount++; + return TRUE; + } +#endif + if (semPended->semCount > 0) { semPended->semCount--; semPended->semOwner = runTsk->taskPid; - +#if defined(OS_OPTION_BIN_SEM) + /* 如果是互斥信号量,把持有的互斥信号量挂接起来 */ + if (GET_SEM_TYPE(semPended->semType) == SEM_TYPE_BIN) { + ListTailAdd(&semPended->semBList, &runTsk->semBList); + } +#endif return TRUE; } return FALSE; @@ -125,7 +190,6 @@ OS_SEC_L0_TEXT U32 PRT_SemPend(SemHandle semHandle, U32 timeout) return OS_ERRNO_SEM_INVALID; } - /* 如果是中断的情况 */ if (OS_INT_ACTIVE) { OsIntRestore(intSave); return OS_ERRNO_SEM_PEND_INTERR; @@ -170,22 +234,37 @@ OS_SEC_ALW_INLINE INLINE void OsSemPostSchePre(struct TagSemCb *semPosted) resumedTask = OsSemPendListGet(semPosted); semPosted->semOwner = resumedTask->taskPid; +#if defined(OS_OPTION_BIN_SEM) + /* + * 如果释放的是互斥信号量,就从释放此互斥信号量任务的持有链表上摘除它, + * 再把它挂接到新的持有它的任务的持有链表上;然后尝试降低任务的优先级 + */ + if (GET_SEM_TYPE(semPosted->semType) == SEM_TYPE_BIN) { + ListDelete(&semPosted->semBList); + ListTailAdd(&semPosted->semBList, &resumedTask->semBList); + } +#endif } -OS_SEC_ALW_INLINE INLINE U32 OsSemPostErrorCheck(struct TagSemCb *semPosted, SemHandle semHandle) +/* + * 描述:判断信号量post是否有效 + * 备注:以下情况表示post无效,返回TRUE: post互斥二进制信号量,若该信号量被嵌套pend或者已处于空闲状态 + */ +OS_SEC_ALW_INLINE INLINE bool OsSemPostIsInvalid(struct TagSemCb *semPosted) { - (void)semHandle; - /* 检查信号量控制块是否UNUSED,排除大部分错误场景 */ - if (semPosted->semStat == OS_SEM_UNUSED) { - return OS_ERRNO_SEM_INVALID; + if (GET_SEM_TYPE(semPosted->semType) == SEM_TYPE_BIN) { +#if defined(OS_OPTION_SEM_RECUR_PV) + if ((GET_MUTEX_TYPE(semPosted->semType) == PTHREAD_MUTEX_RECURSIVE) && semPosted->recurCount > 0) { + semPosted->recurCount--; + return TRUE; + } +#endif + /* 释放互斥二进制信号量且信号量已处于空闲状态 */ + if ((semPosted)->semCount == OS_SEM_FULL) { + return TRUE; + } } - - /* post计数型信号量的错误场景, 释放计数型信号量且信号量计数大于最大计数 */ - if ((semPosted)->maxSemCount <= (semPosted)->semCount) { - return OS_ERRNO_SEM_OVERFLOW; - } - /* post同步二进制信号量或者不存在上述错误场景 */ - return OS_OK; + return FALSE; } /* @@ -203,22 +282,33 @@ OS_SEC_L0_TEXT U32 PRT_SemPost(SemHandle semHandle) semPosted = GET_SEM(semHandle); intSave = OsIntLock(); - /* 检查post信号量时的错误场景 */ + ret = OsSemPostErrorCheck(semPosted, semHandle); if (ret != OS_OK) { OsIntRestore(intSave); return ret; } + /* 信号量post无效,不需要调度 */ + if (OsSemPostIsInvalid(semPosted) == TRUE) { + OsIntRestore(intSave); + return OS_OK; + } + /* 如果有任务阻塞在信号量上,就激活信号量阻塞队列上的首个任务 */ if (!ListEmpty(&semPosted->semList)) { OsSemPostSchePre(semPosted); /* 相当于快速切换+中断恢复 */ OsTskScheduleFastPs(intSave); } else { - /* 释放信号量,把持有信号量的任务ID设置为OS_THREAD_ID_INVALID */ semPosted->semCount++; semPosted->semOwner = OS_INVALID_OWNER_ID; +#if defined(OS_OPTION_BIN_SEM) + /* 如果释放的是互斥信号量,就从释放此互斥信号量任务的持有链表上摘除它 */ + if (GET_SEM_TYPE(semPosted->semType) == SEM_TYPE_BIN) { + ListDelete(&semPosted->semBList); + } +#endif } OsIntRestore(intSave); diff --git a/src/core/ipc/sem/prt_sem_init.c b/src/core/ipc/sem/prt_sem_init.c index 4ac588e..bc6205c 100644 --- a/src/core/ipc/sem/prt_sem_init.c +++ b/src/core/ipc/sem/prt_sem_init.c @@ -63,12 +63,12 @@ OS_SEC_L4_TEXT U32 OsSemInit(void) /* * 描述:创建一个信号量 */ -OS_SEC_L4_TEXT U32 OsSemCreate(U32 count, enum SemMode semMode, SemHandle *semHandle, U32 cookie) +OS_SEC_L4_TEXT U32 OsSemCreate(U32 count, U32 semType, enum SemMode semMode, + SemHandle *semHandle, U32 cookie) { uintptr_t intSave; struct TagSemCb *semCreated = NULL; struct TagListObject *unusedSem = NULL; - (void)cookie; if (semHandle == NULL) { @@ -91,8 +91,16 @@ OS_SEC_L4_TEXT U32 OsSemCreate(U32 count, enum SemMode semMode, SemHandle *semHa semCreated->semCount = count; semCreated->semStat = OS_SEM_USED; semCreated->semMode = semMode; + semCreated->semType = semType; semCreated->semOwner = OS_INVALID_OWNER_ID; - semCreated->maxSemCount = OS_SEM_COUNT_MAX; + if (GET_SEM_TYPE(semType) == SEM_TYPE_BIN) { + INIT_LIST_OBJECT(&semCreated->semBList); +#if defined(OS_OPTION_SEM_RECUR_PV) + if (GET_MUTEX_TYPE(semType) == PTHREAD_MUTEX_RECURSIVE) { + semCreated->recurCount = 0; + } +#endif + } INIT_LIST_OBJECT(&semCreated->semList); *semHandle = (SemHandle)semCreated->semId; @@ -112,7 +120,7 @@ OS_SEC_L4_TEXT U32 PRT_SemCreate(U32 count, SemHandle *semHandle) return OS_ERRNO_SEM_OVERFLOW; } - ret = OsSemCreate(count, SEM_MODE_FIFO, semHandle, (U32)(uintptr_t)semHandle); + ret = OsSemCreate(count, SEM_TYPE_COUNT, SEM_MODE_FIFO, semHandle, (U32)(uintptr_t)semHandle); return ret; } @@ -139,6 +147,11 @@ OS_SEC_L4_TEXT U32 PRT_SemDelete(SemHandle semHandle) OsIntRestore(intSave); return OS_ERRNO_SEM_PENDED; } +#ifdef OS_OPTION_BIN_SEM + if ((semDeleted->semOwner != OS_INVALID_OWNER_ID) && (GET_SEM_TYPE(semDeleted->semType) == SEM_TYPE_BIN)) { + ListDelete(&semDeleted->semBList); + } +#endif semDeleted->semStat = OS_SEM_UNUSED; ListAdd(&semDeleted->semList, &g_unusedSemList); diff --git a/src/core/ipc/sem/prt_sem_minor.c b/src/core/ipc/sem/prt_sem_minor.c index bb4cdab..1270996 100644 --- a/src/core/ipc/sem/prt_sem_minor.c +++ b/src/core/ipc/sem/prt_sem_minor.c @@ -40,7 +40,7 @@ OS_SEC_L4_TEXT U32 PRT_SemGetInfo(SemHandle semHandle, struct SemInfo *semInfo) semInfo->owner = semGet->semOwner; semInfo->count = semGet->semCount; semInfo->mode = semGet->semMode; - semInfo->type = SEM_TYPE_COUNT; + semInfo->type = (GET_SEM_TYPE(semGet->semType) == SEM_TYPE_COUNT) ? SEM_TYPE_COUNT : SEM_TYPE_BIN; OsIntRestore(intSave); return OS_OK; diff --git a/src/core/kernel/CMakeLists.txt b/src/core/kernel/CMakeLists.txt index 44bfaad..a6c6321 100644 --- a/src/core/kernel/CMakeLists.txt +++ b/src/core/kernel/CMakeLists.txt @@ -4,3 +4,6 @@ add_subdirectory(sys) add_subdirectory(task) add_subdirectory(tick) add_subdirectory(timer) +if(${CONFIG_OS_ARCH_ARMV8}) + add_subdirectory(sched) +endif() \ No newline at end of file diff --git a/src/core/kernel/include/prt_list_external.h b/src/core/kernel/include/prt_list_external.h index 9787fbd..60e4f39 100644 --- a/src/core/kernel/include/prt_list_external.h +++ b/src/core/kernel/include/prt_list_external.h @@ -32,6 +32,7 @@ struct TagListObject { (object)->prev = (object); \ } while (0) +#define LIST_LAST(object) ((object)->prev) #define LIST_FIRST(object) ((object)->next) #define OS_LIST_FIRST(object) ((object)->next) @@ -90,4 +91,9 @@ OS_SEC_ALW_INLINE INLINE bool ListEmpty(const struct TagListObject *listObject) for ((posOfList) = LIST_COMPONENT((listObject)->next, typeOfList, field); &(posOfList)->field != (listObject); \ (posOfList) = LIST_COMPONENT((posOfList)->field.next, typeOfList, field)) +#define LIST_FOR_EACH_SAFE(posOfList, listObject, typeOfList, field) \ + for ((posOfList) = LIST_COMPONENT((listObject)->next, typeOfList, field); \ + (&(posOfList)->field != (listObject))&&((posOfList)->field.next != NULL); \ + (posOfList) = LIST_COMPONENT((posOfList)->field.next, typeOfList, field)) + #endif /* PRT_LIST_EXTERNAL_H */ diff --git a/src/core/kernel/include/prt_sys_external.h b/src/core/kernel/include/prt_sys_external.h index 07b6b48..ee63468 100644 --- a/src/core/kernel/include/prt_sys_external.h +++ b/src/core/kernel/include/prt_sys_external.h @@ -23,7 +23,10 @@ #include "prt_asm_cpu_external.h" #include "prt_cpu_external.h" -#define OS_SYS_PID_BASE (OsGetHwThreadId() << OS_TSK_TCB_INDEX_BITS) +#define OS_VAR_ARRAY_NUM OS_MAX_CORE_NUM +#define THIS_CORE() OS_THIS_CORE + +#define OS_SYS_PID_BASE (0x0U << OS_TSK_TCB_INDEX_BITS) #define OS_INT_ACTIVE_MASK \ (OS_FLG_HWI_ACTIVE | OS_FLG_TICK_ACTIVE | OS_FLG_SYS_ACTIVE | OS_FLG_EXC_ACTIVE) @@ -49,12 +52,10 @@ typedef void (*TickDispFunc)(void); /* 有TICK情况下CPU占用率触发函数类型定义。 */ typedef void (*TickEntryFunc)(void); typedef void (*TaskScanFunc)(void); -typedef U64 (*SysTimeFunc)(void); /* * 模块间全局变量声明 */ extern U32 g_threadNum; - extern U32 g_tickNoRespondCnt; #define TICK_NO_RESPOND_CNT g_tickNoRespondCnt @@ -87,4 +88,9 @@ extern enum SysThreadType OsCurThreadType(void); } \ } while (0) +OS_SEC_ALW_INLINE INLINE U32 OsSysGetTickPerSecond(void) +{ + return g_tickModInfo.tickPerSecond; +} + #endif /* PRT_SYS_EXTERNAL_H */ diff --git a/src/core/kernel/include/prt_task_external.h b/src/core/kernel/include/prt_task_external.h index 3369dcc..bc0664b 100644 --- a/src/core/kernel/include/prt_task_external.h +++ b/src/core/kernel/include/prt_task_external.h @@ -24,6 +24,11 @@ #include "prt_cpu_external.h" #include "prt_mem_external.h" +#if defined(OS_OPTION_POSIX) +#include "pthread.h" +#define PTHREAD_KEYS_MAX 32 +#endif + struct TagOsRunQue { U32 taskReadyListBitMap; /* 优先级bit位表 */ @@ -46,8 +51,8 @@ struct TagTskCb { U32 taskStatus; /* 任务的运行优先级 */ TskPrior priority; - /* 保留字段 */ - U16 reserved2; + /* 任务栈配置标记 */ + U16 stackCfgFlg; /* 任务栈大小 */ U32 stackSize; TskHandle taskPid; @@ -66,13 +71,12 @@ struct TagTskCb { /* 存放任务名 */ char name[OS_TSK_NAME_LEN]; #endif - /* 任务栈配置标记 */ - U16 stackCfgFlg; - U16 reserved; /* 信号量链表指针 */ struct TagListObject pendList; /* 任务延时链表指针 */ struct TagListObject timerList; + /* 持有互斥信号量链表 */ + struct TagListObject semBList; #if defined(OS_OPTION_EVENT) /* 任务事件 */ @@ -85,6 +89,24 @@ struct TagTskCb { U32 lastErr; /* 任务恢复的时间点(单位Tick) */ U64 expirationTick; +#if defined(OS_OPTION_POSIX) + /* 当前任务状态 */ + U8 state; + /* pthread cancel */ + U8 cancelState; + U8 cancelType; + U8 cancelPending; + struct _pthread_cleanup_context *cancelBuf; + /* exit status */ + void *retval; + /* count for thread join */ + U16 joinCount; + /* semaphore for thread join */ + SemHandle joinableSem; + /* pthread key */ + void *tsd[PTHREAD_KEYS_MAX]; + U32 tsdUsed; +#endif }; /* @@ -163,6 +185,7 @@ extern volatile TskCoresleep g_taskCoreSleep; #define OS_TSK_BLOCK (OS_TSK_DELAY | OS_TSK_PEND | OS_TSK_SUSPEND | OS_TSK_QUEUE_PEND | \ OS_TSK_EVENT_PEND) +#define OS_TSK_SUSPEND_READY_BLOCK (OS_TSK_SUSPEND) // 设置任务优先级就绪链表主BitMap中Bit位,每32个优先级对应一个BIT位,即Bit0(优先级0~31),Bit1(优先级32~63),依次类推。 #define OS_SET_RDY_TSK_BIT_MAP(priority) \ (OS_TSK_PRIO_RDY_BIT >> ((priority) >> OS_TSK_PRIO_BIT_MAP_POW)) diff --git a/src/core/kernel/irq/CMakeLists.txt b/src/core/kernel/irq/CMakeLists.txt index 5382535..34b4b2e 100644 --- a/src/core/kernel/irq/CMakeLists.txt +++ b/src/core/kernel/irq/CMakeLists.txt @@ -1 +1 @@ -add_library(prt_irq OBJECT prt_irq.c) +add_library_ex(prt_irq.c) diff --git a/src/core/kernel/irq/prt_irq.c b/src/core/kernel/irq/prt_irq.c index 504f053..c13f505 100644 --- a/src/core/kernel/irq/prt_irq.c +++ b/src/core/kernel/irq/prt_irq.c @@ -210,10 +210,6 @@ OS_SEC_L4_TEXT U32 PRT_HwiSetAttr(HwiHandle hwiNum, HwiPrior hwiPrio, HwiMode mo } #endif -#if defined(OS_OPTION_HWI_PRIORITY) - OsHwiPrioritySet(hwiNum, hwiPrio); -#endif - OsHwiAttrSet(irqNum, hwiPrio, mode); OS_HWI_IRQ_UNLOCK(intSave); diff --git a/src/core/kernel/kexc/CMakeLists.txt b/src/core/kernel/kexc/CMakeLists.txt index 8868772..b36fb9a 100644 --- a/src/core/kernel/kexc/CMakeLists.txt +++ b/src/core/kernel/kexc/CMakeLists.txt @@ -1 +1 @@ -add_library(prt_kexc OBJECT prt_kexc.c) +add_library_ex(prt_kexc.c) diff --git a/src/core/kernel/sched/CMakeLists.txt b/src/core/kernel/sched/CMakeLists.txt new file mode 100644 index 0000000..ee06b06 --- /dev/null +++ b/src/core/kernel/sched/CMakeLists.txt @@ -0,0 +1,9 @@ + +##条件判断 +##if(${CONFIG_INTERNAL_OS_SCHEDULE_SINGLE_CORE_BY_CCODE})##条件判断 + ##根据条件添加库 + add_library_ex(prt_sched_single.c) + ##条件结束符号 +##endif()##条件结束符号 + + diff --git a/src/core/kernel/sched/Kconfig b/src/core/kernel/sched/Kconfig new file mode 100644 index 0000000..d2405a3 --- /dev/null +++ b/src/core/kernel/sched/Kconfig @@ -0,0 +1,21 @@ +config OS_OPTION_TASK_MIGRATE + bool "Whether support task migrate features or not" + default y + depends on OS_OPTION_SMP + +config OS_OPTION_SCHED_DOMAIN + bool "Whether schedule domain feature or not" + depends on OS_OPTION_SMP + default n + +config INTERNAL_OS_SCHEDULE_SINGLE_CORE_BY_CCODE + bool "single core when the scheduling part is implemented by using the C language or not" + depends on (OS_MAX_CORE_NUM=1) + default n + help + Internal function macro.This macro is used by the single core when the scheduling part is implemented by using the C language. + +config INTERNAL_OS_SCHEDULE_RT + bool "Whether support rt scheduler or not" + depends on OS_OPTION_SMP + default y \ No newline at end of file diff --git a/src/core/kernel/sched/prt_sched_single.c b/src/core/kernel/sched/prt_sched_single.c new file mode 100644 index 0000000..75d0657 --- /dev/null +++ b/src/core/kernel/sched/prt_sched_single.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: 单核调度函数实现 + */ +#include "prt_hook_external.h" +#include "prt_task_external.h" + +/* + * 描述: 调度的主入口 + * 备注: NA + */ +OS_SEC_L0_TEXT void OsMainSchedule(void) +{ + if ((UNI_FLAG & OS_FLG_TSK_REQ) != 0) { + /* 有任务切换钩子&最高优先级任务等待调度 */ + if (RUNNING_TASK != g_highestTask) { + OsTskSwitchHookCaller(RUNNING_TASK->taskPid, g_highestTask->taskPid); + } + + /* 清除OS_FLG_TSK_REQ标记位 */ + UNI_FLAG &= ~OS_FLG_TSK_REQ; + + RUNNING_TASK->taskStatus &= ~OS_TSK_RUNNING; + g_highestTask->taskStatus |= OS_TSK_RUNNING; + + RUNNING_TASK = g_highestTask; + } + // 如果中断没有驱动一个任务ready,直接回到被打断的任务 + OsTskContextLoad((uintptr_t)RUNNING_TASK); +} + +/* + * 描述: 切换任务 + * 备注: 包含任务切换钩子,和任务上下文恢复操作 + */ +OS_SEC_L0_TEXT void OsContextSwitch(struct TagTskCb *prev, struct TagTskCb *next) +{ + /* 有任务切换钩子&最高优先级任务等待调度 */ + if (prev != next) { + OsTskSwitchHookCaller(prev->taskPid, next->taskPid); + } + /* 正式切换,prev已经在putprev经过处理,这里跳过 */ + OsTskContextLoad((uintptr_t)next); +} + +/* + * 描述: 系统启动时的首次任务调度 + * 备注: NA + */ +OS_SEC_L4_TEXT void OsFirstTimeSwitch(void) +{ + OsTskHighestSet(); + RUNNING_TASK = g_highestTask; + TSK_STATUS_SET(RUNNING_TASK, OS_TSK_RUNNING); + OsTskContextLoad((uintptr_t)RUNNING_TASK); + // never get here + return; +} + +/* + * 描述: 中断处理流程尾部处理,TICK 、任务调用 + * 备注: NA + */ +OS_SEC_L0_TEXT void OsHwiDispatchTail(void) +{ + if (TICK_NO_RESPOND_CNT > 0) { + if ((UNI_FLAG & OS_FLG_TICK_ACTIVE) != 0) { + // OsTskContextLoad, 回到被打断的tick处理现场 + return; + } + UNI_FLAG |= OS_FLG_TICK_ACTIVE; + + do { + OsIntEnable(); + // tickISRִ,这里开中断 + g_tickDispatcher(); + OsIntDisable(); + TICK_NO_RESPOND_CNT--; + } while (TICK_NO_RESPOND_CNT > 0); + + UNI_FLAG &= ~OS_FLG_TICK_ACTIVE; + } + + OsMainSchedule(); +} diff --git a/src/core/kernel/sys/CMakeLists.txt b/src/core/kernel/sys/CMakeLists.txt index b13c887..0b0271a 100644 --- a/src/core/kernel/sys/CMakeLists.txt +++ b/src/core/kernel/sys/CMakeLists.txt @@ -1,3 +1,3 @@ -add_library(prt_sys OBJECT prt_sys.c) -add_library(prt_sys_init OBJECT prt_sys_init.c) -add_library(prt_sys_time OBJECT prt_sys_time.c) +add_library_ex(prt_sys.c) +add_library_ex(prt_sys_init.c) +add_library_ex(prt_sys_time.c) diff --git a/src/core/kernel/sys/prt_sys_init.c b/src/core/kernel/sys/prt_sys_init.c index 369b9bc..79f681f 100644 --- a/src/core/kernel/sys/prt_sys_init.c +++ b/src/core/kernel/sys/prt_sys_init.c @@ -26,9 +26,14 @@ OS_SEC_L4_TEXT U8 OsGetCpuType(void) return g_cpuType; } -OS_SEC_L4_TEXT U32 OsSysTimeHookReg(void) +OS_SEC_L4_TEXT U32 OsSysTimeHookReg(SysTimeFunc hook) { +#if defined(OS_OPTION_SYS_TIME_USR) + return OsSetSysTimeHook(hook); +#else + (void)hook; return OsSetSysTimeHook(PRT_ClkGetCycleCount64); +#endif } OS_SEC_L4_TEXT U32 OsSysRegister(struct SysModInfo *modInfo) @@ -39,7 +44,7 @@ OS_SEC_L4_TEXT U32 OsSysRegister(struct SysModInfo *modInfo) return OS_ERRNO_SYS_CLOCK_INVALID; } - ret = OsSysTimeHookReg(); + ret = OsSysTimeHookReg(modInfo->sysTimeHook); if (ret != OS_OK) { return ret; } diff --git a/src/core/kernel/task/CMakeLists.txt b/src/core/kernel/task/CMakeLists.txt index 9259506..526e18a 100644 --- a/src/core/kernel/task/CMakeLists.txt +++ b/src/core/kernel/task/CMakeLists.txt @@ -1,15 +1,15 @@ -add_library(prt_task OBJECT prt_task.c) -add_library(prt_task_attrib OBJECT prt_task_attrib.c) -add_library(prt_task_del OBJECT prt_task_del.c) -add_library(prt_task_init OBJECT prt_task_init.c) -add_library(prt_task_global OBJECT prt_task_global.c) -add_library(prt_task_info OBJECT prt_task_info.c) -add_library(prt_task_minor OBJECT prt_task_minor.c) -add_library(prt_task_priority OBJECT prt_task_priority.c) -add_library(prt_task_sem OBJECT prt_task_sem.c) -add_library(prt_taskself_id OBJECT prt_taskself_id.c) -add_library(prt_amp_task OBJECT prt_amp_task.c) -add_library(prt_amp_task_del OBJECT prt_amp_task_del.c) -add_library(prt_amp_task_init OBJECT prt_amp_task_init.c) -add_library(prt_amp_task_minor OBJECT prt_amp_task_minor.c) +add_library_ex(prt_task.c) +add_library_ex(prt_task_attrib.c) +add_library_ex(prt_task_del.c) +add_library_ex(prt_task_init.c) +add_library_ex(prt_task_global.c) +add_library_ex(prt_task_info.c) +add_library_ex(prt_task_minor.c) +add_library_ex(prt_task_priority.c) +add_library_ex(prt_task_sem.c) +add_library_ex(prt_taskself_id.c) +add_library_ex(prt_amp_task.c) +add_library_ex(prt_amp_task_del.c) +add_library_ex(prt_amp_task_init.c) +add_library_ex(prt_amp_task_minor.c) diff --git a/src/core/kernel/task/prt_amp_task_init.c b/src/core/kernel/task/prt_amp_task_init.c index 17149dc..1f096a0 100644 --- a/src/core/kernel/task/prt_amp_task_init.c +++ b/src/core/kernel/task/prt_amp_task_init.c @@ -79,7 +79,7 @@ OS_SEC_L4_TEXT U32 OsIdleTskAMPCreate(void) { U32 ret; TskHandle taskHdl; - struct TskInitParam taskInitParam; + struct TskInitParam taskInitParam = {0}; char tskName[OS_TSK_NAME_LEN] = "IdleTask"; /* Create background task. */ diff --git a/src/core/kernel/task/prt_amp_task_minor.c b/src/core/kernel/task/prt_amp_task_minor.c index 5548f56..439580e 100644 --- a/src/core/kernel/task/prt_amp_task_minor.c +++ b/src/core/kernel/task/prt_amp_task_minor.c @@ -91,8 +91,8 @@ OS_SEC_L2_TEXT U32 PRT_TaskResume(TskHandle taskPid) } if (((OS_TSK_RUNNING & taskCb->taskStatus) != 0) && (g_uniTaskLock != 0)) { - OsIntRestore(intSave); - return OS_ERRNO_TSK_ACTIVE_FAILED; + OsIntRestore(intSave); + return OS_ERRNO_TSK_ACTIVE_FAILED; } /* If task is not suspended then return */ diff --git a/src/core/kernel/task/prt_task_init.c b/src/core/kernel/task/prt_task_init.c index 80964a3..89c08e6 100644 --- a/src/core/kernel/task/prt_task_init.c +++ b/src/core/kernel/task/prt_task_init.c @@ -246,22 +246,6 @@ OS_SEC_L4_TEXT void OsTskStackInit(U32 stackSize, uintptr_t topStack) *((U32 *)(topStack)) = OS_TSK_STACK_TOP_MAGIC; } -OS_SEC_ALW_INLINE INLINE U32 OsTaskCreateChkAndGetTcb(struct TagTskCb **taskCb) -{ - OsTskRecycle(); - - if (ListEmpty(&g_tskCbFreeList)) { - return OS_ERRNO_TSK_TCB_UNAVAILABLE; - } - - // 先获取到该控制块 - *taskCb = GET_TCB_PEND(OS_LIST_FIRST(&g_tskCbFreeList)); - // 成功,从空闲列表中移除 - ListDelete(OS_LIST_FIRST(&g_tskCbFreeList)); - - return OS_OK; -} - OS_SEC_ALW_INLINE INLINE U32 OsTaskCreateRsrcInit(U32 taskId, struct TskInitParam *initParam, struct TagTskCb *taskCb, uintptr_t **topStackOut, uintptr_t *curStackSize) { @@ -317,6 +301,7 @@ OS_SEC_ALW_INLINE INLINE void OsTskCreateTcbInit(uintptr_t stackPtr, struct TskI #endif taskCb->lastErr = 0; + INIT_LIST_OBJECT(&taskCb->semBList); INIT_LIST_OBJECT(&taskCb->pendList); INIT_LIST_OBJECT(&taskCb->timerList); diff --git a/src/core/kernel/task/prt_task_internal.h b/src/core/kernel/task/prt_task_internal.h index 8e16f96..baff9f4 100644 --- a/src/core/kernel/task/prt_task_internal.h +++ b/src/core/kernel/task/prt_task_internal.h @@ -37,6 +37,8 @@ extern struct TagListObject g_tskRecyleList; extern void *OsTskMemAlloc(U32 size); extern void OsTskIdleBgd(void); extern U32 OsTaskDelStatusCheck(struct TagTskCb *taskCb); +extern void OsTskRecycle(void); +extern void OsTskStackInit(U32 stackSize, uintptr_t topStack); OS_SEC_ALW_INLINE INLINE void OsMoveTaskToReady(struct TagTskCb *taskCb) { @@ -57,4 +59,21 @@ OS_SEC_ALW_INLINE INLINE void OsTskResRecycle(struct TagTskCb *taskCb) OS_ERR_RECORD(PRT_MemFree((U32)OS_MID_TSK, (void *)taskCb->topOfStack)); } } + +OS_SEC_ALW_INLINE INLINE U32 OsTaskCreateChkAndGetTcb(struct TagTskCb **taskCb) +{ + OsTskRecycle(); + + if (ListEmpty(&g_tskCbFreeList)) { + return OS_ERRNO_TSK_TCB_UNAVAILABLE; + } + + // 先获取到该控制块 + *taskCb = GET_TCB_PEND(OS_LIST_FIRST(&g_tskCbFreeList)); + // 成功,从空闲列表中移除 + ListDelete(OS_LIST_FIRST(&g_tskCbFreeList)); + + return OS_OK; +} + #endif /* PRT_TASK_INTERNAL_H */ diff --git a/src/core/kernel/tick/CMakeLists.txt b/src/core/kernel/tick/CMakeLists.txt index 2153ae5..bcf259b 100644 --- a/src/core/kernel/tick/CMakeLists.txt +++ b/src/core/kernel/tick/CMakeLists.txt @@ -1,2 +1,2 @@ -add_library(prt_tick OBJECT prt_tick.c) -add_library(prt_tick_init OBJECT prt_tick_init.c) +add_library_ex(prt_tick.c) +add_library_ex(prt_tick_init.c) diff --git a/src/core/kernel/tick/prt_tick.c b/src/core/kernel/tick/prt_tick.c index 947bdde..a81caaf 100644 --- a/src/core/kernel/tick/prt_tick.c +++ b/src/core/kernel/tick/prt_tick.c @@ -47,3 +47,11 @@ OS_SEC_TEXT void OsTickDispatcher(void) TSKMON_TICK_RUN(); } +void PRT_TickISR(void) +{ +#if !defined(OS_OPTION_TICK_USE_HWTMR) + if (OsSysGetTickPerSecond() != 0) { + TICK_NO_RESPOND_CNT++; + } +#endif +} \ No newline at end of file diff --git a/src/core/kernel/timer/CMakeLists.txt b/src/core/kernel/timer/CMakeLists.txt index 4d267d7..1df8ad0 100644 --- a/src/core/kernel/timer/CMakeLists.txt +++ b/src/core/kernel/timer/CMakeLists.txt @@ -1,5 +1,5 @@ -add_library(prt_timer OBJECT prt_timer.c) -add_library(prt_timer_minor OBJECT prt_timer_minor.c) +add_library_ex(prt_timer.c) +add_library_ex(prt_timer_minor.c) if(${CONFIG_INTERNAL_OS_SWTMR}) add_subdirectory(swtmr) diff --git a/src/core/kernel/timer/swtmr/CMakeLists.txt b/src/core/kernel/timer/swtmr/CMakeLists.txt index cc4a0e2..a130019 100644 --- a/src/core/kernel/timer/swtmr/CMakeLists.txt +++ b/src/core/kernel/timer/swtmr/CMakeLists.txt @@ -1,3 +1,4 @@ -add_library(prt_swtmr OBJECT prt_swtmr.c) -add_library(prt_swtmr_init OBJECT prt_swtmr_init.c) -add_library(prt_swtmr_minor OBJECT prt_swtmr_minor.c) +add_library_ex(prt_swtmr.c) +add_library_ex(prt_swtmr_init.c) +add_library_ex(prt_swtmr_minor.c) +add_library_ex(prt_swtmr_info.c) diff --git a/src/core/kernel/timer/swtmr/prt_swtmr.c b/src/core/kernel/timer/swtmr/prt_swtmr.c index f6329a1..9247f05 100644 --- a/src/core/kernel/timer/swtmr/prt_swtmr.c +++ b/src/core/kernel/timer/swtmr/prt_swtmr.c @@ -137,7 +137,7 @@ OS_SEC_TEXT void OsSwTmrScan(void) return; } -OS_SEC_ALW_INLINE INLINE struct TagListObject *OsSwtmrCtrlInit(struct TagSwTmrCtrl *swtmr, U32 interval) +OS_SEC_ALW_INLINE INLINE struct TagListObject *OsSwTmrStartInner(struct TagSwTmrCtrl *swtmr, U32 interval) { U32 sortIndex; U32 rollNum; @@ -163,7 +163,7 @@ OS_SEC_TEXT void OsSwTmrStart(struct TagSwTmrCtrl *swtmr, U32 interval) struct TagSwTmrCtrl *temp = NULL; struct TagListObject *listObject = NULL; - listObject = OsSwtmrCtrlInit(swtmr, interval); + listObject = OsSwTmrStartInner(swtmr, interval); if (listObject->next == listObject) { // 该SortLink成员上是空链 swtmr->next = (struct TagSwTmrCtrl *)listObject; swtmr->prev = (struct TagSwTmrCtrl *)listObject; diff --git a/src/core/kernel/timer/swtmr/prt_swtmr_info.c b/src/core/kernel/timer/swtmr/prt_swtmr_info.c new file mode 100644 index 0000000..2e69031 --- /dev/null +++ b/src/core/kernel/timer/swtmr/prt_swtmr_info.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: 获取软件定时器信息功能 + */ +#include "prt_swtmr_internal.h" + +OS_SEC_L4_TEXT U32 PRT_SwTmrInfoGet(TimerHandle tmrHandle, struct SwTmrInfo *info) +{ + struct TagSwTmrCtrl *swtmr = NULL; + uintptr_t intSave; + U32 expireTime = 0; + + if (g_timerApi[TIMER_TYPE_SWTMR].createTimer == NULL) { + return OS_ERRNO_TIMER_NOT_INIT_OR_GROUP_NOT_CREATED; + } + + if (tmrHandle < OS_SWTMR_MIN_NUM) { + return OS_ERRNO_TIMER_HANDLE_INVALID; + } + + if (tmrHandle >= OS_TIMER_MAX_NUM) { + return OS_ERRNO_TIMER_HANDLE_INVALID; + } + + if (info == NULL) { + return OS_ERRNO_SWTMR_RET_PTR_NULL; + } + + intSave = OsIntLock(); + + swtmr = g_swtmrCbArray + OS_SWTMR_ID_2_INDEX(tmrHandle); + if (swtmr->state == (U8)OS_TIMER_FREE) { + OsIntRestore(intSave); + return OS_ERRNO_SWTMR_NOT_CREATED; + } + + /* 写入返回参数 */ + info->handler = swtmr->handler; + info->mode = (enum TmrMode)swtmr->mode; + info->state = (U8)((U32)swtmr->state & OS_SWTMR_STATUS_MASK); + // Interval转化为毫秒一定为整数 + info->interval = (U32)DIV64(((U64)swtmr->interval * OS_SYS_MS_PER_SECOND), g_tickModInfo.tickPerSecond); + + /* 调用内部接口osSwTmrQuery获取剩余时间 */ + OsErrRecord(OsSwTmrQuery(tmrHandle, &expireTime)); + + info->remainMs = expireTime; + OsIntRestore(intSave); + + return OS_OK; +} diff --git a/src/include/posix/semaphore.h b/src/include/posix/semaphore.h new file mode 100644 index 0000000..e09e1b6 --- /dev/null +++ b/src/include/posix/semaphore.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: 信号量头文件 + */ +#ifndef _SEMAPHORE_H +#define _SEMAPHORE_H + +#include "time.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define O_CREAT 0100 +#define O_EXCL 0200 +#define O_NOCTTY 0400 +#define O_TRUNC 01000 +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_DSYNC 010000 +#define O_SYNC 04010000 +#define O_RSYNC 04010000 +#define O_DIRECTORY 040000 +#define O_NOFOLLOW 0100000 +#define O_CLOEXEC 02000000 + +#define MAX_POSIX_SEMAPHORE_NAME_LEN 31 +#define SEM_FAILED ((sem_t *)0) + +typedef struct { + unsigned short semHandle; + unsigned short reserve; + unsigned int refCount; +} sem_t; + +int sem_destroy(sem_t *); +int sem_getvalue(sem_t *__restrict, int *__restrict); +int sem_init(sem_t *, int, unsigned); +int sem_post(sem_t *); +int sem_timedwait(sem_t *__restrict, const struct timespec *__restrict); +int sem_trywait(sem_t *); +int sem_wait(sem_t *); +sem_t *sem_open(const char *, int, ...); +int sem_close(sem_t *); +int sem_unlink(const char *); + +#ifdef __cplusplus +} +#endif + +#endif /* _SEMAPHORE_H */ diff --git a/src/include/uapi/hw/armv8/os_cpu_armv8.h b/src/include/uapi/hw/armv8/os_cpu_armv8.h new file mode 100644 index 0000000..cd328fe --- /dev/null +++ b/src/include/uapi/hw/armv8/os_cpu_armv8.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: cpu架构相关的外部头文件 + */ +#ifndef OS_CPU_ARMV8_H +#define OS_CPU_ARMV8_H + +#include "prt_typedef.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +// CurrentEl等级 +#define CURRENT_EL_2 0x8 +#define CURRENT_EL_1 0x4 +#define CURRENT_EL_0 0x0 + +#define DAIF_DBG_BIT (1U << 3) +#define DAIF_ABT_BIT (1U << 2) +#define DAIF_IRQ_BIT (1U << 1) +#define DAIF_FIQ_BIT (1U << 0) + +#define INT_MASK (1U << 7) +#define OS_CORE_ID_MASK 0xFFU +#define OS_CORE_MPID_CPUID(mpid) (((mpid) | ((mpid) >> 8)) & OS_CORE_ID_MASK) + +/* + * 任务上下文的结构体定义。 + */ +struct TskContext { + /* *< 当前物理寄存器R0-R12 */ + uintptr_t elr; // 返回地址 + uintptr_t spsr; + uintptr_t far; + uintptr_t esr; + uintptr_t xzr; + uintptr_t x30; + uintptr_t x29; + uintptr_t x28; + uintptr_t x27; + uintptr_t x26; + uintptr_t x25; + uintptr_t x24; + uintptr_t x23; + uintptr_t x22; + uintptr_t x21; + uintptr_t x20; + uintptr_t x19; + uintptr_t x18; + uintptr_t x17; + uintptr_t x16; + uintptr_t x15; + uintptr_t x14; + uintptr_t x13; + uintptr_t x12; + uintptr_t x11; + uintptr_t x10; + uintptr_t x09; + uintptr_t x08; + uintptr_t x07; + uintptr_t x06; + uintptr_t x05; + uintptr_t x04; + uintptr_t x03; + uintptr_t x02; + uintptr_t x01; + uintptr_t x00; +}; + +/* + * 描述: 读取当前核号 + * 使用mpidr 寄存器 (64bit) 根据核的线程模式获取核号 + * bit 63-40 39-32 31 30 29~25 24 23-16 15-8 7~0 + * res0 aff3 res1 u res0 mt aff2 aff1 aff0 + */ +OS_SEC_ALW_INLINE INLINE U32 OsGetCoreID(void) +{ + U64 mpid; + OS_EMBED_ASM("MRS %0, MPIDR_EL1" : "=r"(mpid)::"memory", "cc"); + OS_EMBED_ASM("dmb sy" ::: "memory"); + /* single-thread 模式下,核号取AFF0 AF1为0 */ + /* muti-thread 模式下,核号取AFF1 AF0为0 */ + /* 综上核号计算采用AFF0 + AFF1 */ + return OS_CORE_MPID_CPUID(mpid); +} + +/* + * 获取当前核ID + */ +OS_SEC_ALW_INLINE INLINE U32 PRT_GetCoreID(void) +{ + return OsGetCoreID(); +} + +#define PRT_DSB() OS_EMBED_ASM("DSB sy" : : : "memory") +#define PRT_DMB() OS_EMBED_ASM("DMB sy" : : : "memory") +#define PRT_ISB() OS_EMBED_ASM("ISB" : : : "memory") + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +#endif /* OS_CPU_ARMV8_H */ diff --git a/src/include/uapi/hw/armv8/os_exc_armv8.h b/src/include/uapi/hw/armv8/os_exc_armv8.h new file mode 100644 index 0000000..b27c372 --- /dev/null +++ b/src/include/uapi/hw/armv8/os_exc_armv8.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-22 + * Description: 异常模块的对外头文件。 + */ +#ifndef ARMV8_EXC_H +#define ARMV8_EXC_H + +#include "prt_typedef.h" +#include "prt_sys.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +/* + * OS使用的EL个数,EL1~EL3 + */ +#define OS_ELX_NUM 3 + +/* + * 通用寄存器个数, x0~x30 + */ +#define XREGS_NUM 31 + +/* + * 异常寄存器信息结构 + */ +struct ExcElxRegs { + uintptr_t esr; + uintptr_t far; + uintptr_t spsr; + uintptr_t elr; + uintptr_t sctlr; + uintptr_t sp; + uintptr_t vbar; + uintptr_t ttbr0; + uintptr_t tcr; + uintptr_t mair; +}; + +struct ExcRegInfo { + uintptr_t ttbr0; + uintptr_t ttbr1; + uintptr_t tcr; + uintptr_t mair; + uintptr_t sctlr; + uintptr_t vbar; + uintptr_t currentEl; + uintptr_t sp; + // 以下字段的内存布局与TskContext保持一致 + uintptr_t elr; // 返回地址 + uintptr_t spsr; + uintptr_t far; + uintptr_t esr; + uintptr_t xzr; + uintptr_t xregs[XREGS_NUM]; // 0~30 : x30~x0 +}; + +/* + * CpuTick结构体类型。 + * + * 用于记录64位的cycle计数值。 + */ +struct SreCpuTick { + U32 cntHi; /* cycle计数高32位 */ + U32 cntLo; /* cycle计数低32位 */ +}; + +/* + * 异常信息结构体 + */ +struct ExcInfo { + // OS版本号 + char osVer[OS_SYS_OS_VER_LEN]; + // 产品版本号 + char appVer[OS_SYS_APP_VER_LEN]; + // 异常原因 + U32 excCause; + // 异常前的线程类型 + U32 threadType; + // 异常前的线程ID, 该ID组成threadID = LTID + U32 threadId; + // 字节序 + U16 byteOrder; + // CPU类型 + U16 cpuType; + // CPU ID + U32 coreId; + // CPU Tick + struct SreCpuTick cpuTick; + // 异常嵌套计数 + U32 nestCnt; + // 致命错误码,发生致命错误时有效 + U32 fatalErrNo; + // 异常前栈指针 + uintptr_t sp; + // 异常前栈底 + uintptr_t stackBottom; + // 异常发生时的核内寄存器上下文信息 + struct ExcRegInfo regInfo; +}; + +/* + * ARMV8异常具体类型:异常原因参见ESR寄存器。 + */ +#define OS_EXCEPT_ESR 0 + +/* + * ARMV8异常具体类型:其他核异常。 + */ +#define OS_EXCEPT_OTHER_CORE 1 + +/* + * ARMV8异常具体类型:致命错误异常。 + */ +#define OS_EXCEPT_FATALERROR 2 + +/* + * ARMV8异常具体类型:栈越界异常。 + */ +#define OS_EXCEPT_STACKOVERFLOW 3 + +/* + * ARMV8异常具体类型:非法指令异常。 + */ +#define OS_EXCEPT_UNDEF_INSTR 4 + +/* + * ARMV8异常具体类型:数据中止异常。 + */ +#define OS_EXCEPT_DATA_ABORT 5 + +/* + * ARMV8异常具体类型:快速中断异常。 + */ +#define OS_EXCEPT_FIQ 6 + +/* + * ARMV8异常具体类型:pc非对齐异常。 + */ +#define OS_EXCEPT_PC_NOT_ALIGN 7 + +/* + * ARMV8异常具体类型:sp非对齐异常。 + */ +#define OS_EXCEPT_SP_NOT_ALIGN 8 + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +#endif /* ARMV8_EXC_H */ diff --git a/src/include/uapi/prt_buildef_common.h b/src/include/uapi/prt_buildef_common.h new file mode 100644 index 0000000..82d56e5 --- /dev/null +++ b/src/include/uapi/prt_buildef_common.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: the common part buildef.h + */ +#ifndef OS_BUILDEF_COMMON_H +#define OS_BUILDEF_COMMON_H + +/* the endian definition */ +#define OS_LITTLE_ENDIAN 0x1234 +#define OS_BIG_ENDIAN 0x4321 + +/* To define OS_HARDWARE_PLATFORM */ +/* 编译器有个bug, 未定义的宏的数值默认是0,所以不用使用'0' */ +#define OS_CORTEX_M4 0x01 +#define OS_ARMV8 0x02 +#define OS_PLATFORM_INVALID 0x03 + +/* To define OS_CPU_TYPE */ +/* 编译器有个bug, 未定义的宏的数值默认是0,所以不用使用'0' */ +#define OS_STM32F407 0x01 +#define OS_RASPI4 0x02 +#define OS_HI3093 0x03 +#define OS_CPU_TYPE_INVALID 0x04 + +#ifndef INIT_SEC_L4_TEXT +#define INIT_SEC_L4_TEXT +#endif + +#ifndef RESET_SEC_DATA +#define RESET_SEC_DATA __attribute__((section(".os.init.data"))) +#endif + +/* 必须方案sre_buildef的头文件中,否则会出现宏开关不生效的问题 */ +#ifdef YES +#undef YES +#endif +#define YES 1 + +#ifdef NO +#undef NO +#endif +#define NO 0 + +#endif /* OS_BUILDEF_COMMON_H */ diff --git a/src/include/uapi/prt_clk.h b/src/include/uapi/prt_clk.h index 8614930..f26b617 100644 --- a/src/include/uapi/prt_clk.h +++ b/src/include/uapi/prt_clk.h @@ -39,7 +39,7 @@ extern "C" { * @retval [0,0xFFFFFFFFFFFFFFFF] 系统当前的cycle数 * @par 依赖 *
    • prt_clk.h:该接口声明所在的头文件。
    - * @see 无 + * @see PRT_CycleCountGet32() */ extern U64 PRT_ClkGetCycleCount64(void); diff --git a/src/include/uapi/prt_exc.h b/src/include/uapi/prt_exc.h index 7652023..c0b48aa 100644 --- a/src/include/uapi/prt_exc.h +++ b/src/include/uapi/prt_exc.h @@ -22,6 +22,10 @@ #include "./hw/armv7-m/prt_exc.h" #endif +#if (OS_HARDWARE_PLATFORM == OS_ARMV8) +#include "./hw/armv8/os_exc_armv8.h" +#endif + #ifdef __cplusplus #if __cplusplus extern "C" { @@ -77,7 +81,7 @@ struct ExcModInfo { * * @param hook [IN] 类型#ExcProcFunc,钩子函数。 * - * @retval #OS_OK 0x00000000,注册失败。 + * @retval #OS_OK 0x00000000,注册成功。 * @retval #其它值,注册失败。 * * @par 依赖 diff --git a/src/include/uapi/prt_hook.h b/src/include/uapi/prt_hook.h index 2cbfbaa..54c555d 100644 --- a/src/include/uapi/prt_hook.h +++ b/src/include/uapi/prt_hook.h @@ -95,7 +95,8 @@ enum HookType { OS_HOOK_HWI_EXIT, // 硬中断退出钩子 OS_HOOK_TSK_SWITCH, // 任务切换钩子 OS_HOOK_IDLE_PERIOD, // IDLE钩子 - OS_HOOK_TYPE_NUM // 钩子总数 + OS_HOOK_LAST_WORDS, // 临终遗言钩子 + OS_HOOK_TYPE_NUM, // 钩子总数 }; /* diff --git a/src/include/uapi/prt_hwi.h b/src/include/uapi/prt_hwi.h index c2b3fc2..4beaac0 100644 --- a/src/include/uapi/prt_hwi.h +++ b/src/include/uapi/prt_hwi.h @@ -17,6 +17,7 @@ #include "prt_module.h" #include "prt_errno.h" +#include "prt_buildef.h" #ifdef __cplusplus #if __cplusplus @@ -24,6 +25,65 @@ extern "C" { #endif /* __cpluscplus */ #endif /* __cpluscplus */ +/* + * IPI触发类型。 + */ +enum OsHwiIpiType { + OS_TYPE_TRIGGER_BY_MASK = 0, /* 通过mask确定需要触发的目标核 */ + OS_TYPE_TRIGGER_TO_OTHER, /* 触发除本核外的其他核 */ + OS_TYPE_TRIGGER_TO_SELF, /* 触发本核 */ + OS_TYPE_TRIGGER_BUTT /* 非法 */ +}; + +/* + * 支持的SGI中断编号为[0,15] + * 可用的核间中断号定义。 + */ +#define OS_HWI_IPI_NO_00 0 + +/* + * 可用的核间中断号定义[OS占用1号:触发它核响应一次调度的IPI中断号]。 + */ +#define OS_HWI_IPI_NO_01 1 + +/* + * 可用的核间中断号定义[OS占用2号:一个核异常后将其它核停住的IPI中断号]。 + */ +#define OS_HWI_IPI_NO_02 2 + +/* + * 可用的核间中断号定义[OS占用3号:响应tick中断的核触发它核的模拟tickIPI中断号]。 + */ +#define OS_HWI_IPI_NO_03 3 + +/* + * 可用的核间中断号定义[OS占用4号:核间通信用于核间通知的中断号]。 + */ +#define OS_HWI_IPI_NO_04 4 + +/* + * 可用的核间中断号定义。 + */ +#define OS_HWI_IPI_NO_05 5 +#define OS_HWI_IPI_NO_06 6 + +/* + * 可用的核间中断号定义[OS占用7号:openamp要求Linux和从核使用同一个IPI,Linux核目前只能使用7号]。 + */ +#define OS_HWI_IPI_NO_07 7 + +/* + * 可用的核间中断号定义。 + */ +#define OS_HWI_IPI_NO_08 8 +#define OS_HWI_IPI_NO_09 9 +#define OS_HWI_IPI_NO_10 10 +#define OS_HWI_IPI_NO_011 11 +#define OS_HWI_IPI_NO_012 12 +#define OS_HWI_IPI_NO_013 13 +#define OS_HWI_IPI_NO_014 14 +#define OS_HWI_IPI_NO_015 15 + /* * 硬中断错误码:中断号非法。 * @@ -132,23 +192,59 @@ extern "C" { */ #define OS_ERRNO_HWI_CORE_ID_INVALID OS_ERRNO_BUILD_ERROR(OS_MID_HWI, 0x0c) +/* + * 硬中断错误码:硬件上报错误中断。 + * + * 值: 0x0200080d + * + * 解决方案:无。 + */ +#define OS_ERRNO_HWI_HW_REPORT_HWINO_INVALID OS_ERRNO_BUILD_ERROR(OS_MID_HWI, 0x0d) + /* * 系统基本功能错误码:注册不可删除的中断失败 * - * 值: 0x0300141c + * 值: 0x0300080e * * 解决方案: 请确保传是独立型中断,或者修改OS_HWI_INTERNAL_NUM值 */ -#define OS_ERROR_HWI_INT_REGISTER_FAILED OS_ERRNO_BUILD_FATAL(OS_MID_HWI, 0x1c) +#define OS_ERROR_HWI_INT_REGISTER_FAILED OS_ERRNO_BUILD_FATAL(OS_MID_HWI, 0x0e) /* * 硬中断错误码:中断内存资源申请失败 * - * 值: 0x0200080d + * 值: 0x0200080f * * 解决方案: 检查默认分区大小配置是否正确 */ -#define OS_ERRNO_HWI_RESOURCE_ALLOC_FAILED OS_ERRNO_BUILD_ERROR(OS_MID_HWI, 0x0d) +#define OS_ERRNO_HWI_RESOURCE_ALLOC_FAILED OS_ERRNO_BUILD_ERROR(OS_MID_HWI, 0x0f) + +/* + * 核间中断错误码:中断目标核不支持1-N + * + * 值: 0x02000810 + * + * 解决方案:目标核掩码只描述1个目标核,不能描述多个目标核 + */ +#define OS_ERRNO_MULTI_TARGET_CORE OS_ERRNO_BUILD_ERROR(OS_MID_HWI, 0x10) + +/* + * 硬中断错误码:删除os内部硬中断。 + * + * 值: 0x02000811 + * + * 解决方案:不允许删除os内部硬中断 + */ +#define OS_ERRNO_HWI_DELETE_INT OS_ERRNO_BUILD_ERROR(OS_MID_HWI, 0x11) + +/* + * 硬中断错误码:硬中断地址信息配置错误 + * + * 值: 0x02000812 + * + * 解决方案: 根据核手册正确配置OS_GIC_BASE_ADDR/OS_GICR_OFFSET/OS_GICR_STRIDE + */ +#define OS_ERROR_HWI_BASE_ADDR_INVALID OS_ERRNO_BUILD_ERROR(OS_MID_HWI, 0x12) /* * 硬中断优先级的类型定义。 diff --git a/src/include/uapi/prt_sem.h b/src/include/uapi/prt_sem.h index 9e2bd9e..440fdf6 100644 --- a/src/include/uapi/prt_sem.h +++ b/src/include/uapi/prt_sem.h @@ -159,6 +159,24 @@ extern "C" { */ #define OS_ERRNO_SEM_COUNT_GET_PTR_NULL OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x0f) +/* + * 信号量错误码:非当前互斥信号量的持有者释放该信号量。 + * + * 值: 0x02000710 + * + * 解决方案: 互斥信号量只能由其持有者释放,即互斥信号量的PV操作必须配对使用。 + */ +#define OS_ERRNO_SEM_MUTEX_NOT_OWNER_POST OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x10) + +/* + * 信号量错误码:在中断中释放互斥型信号量。 + * + * 值: 0x02000711 + * + * 解决方案: 只能在任务中对互斥型信号量进行PV操作。 + */ +#define OS_ERRNO_SEM_MUTEX_POST_INTERR OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x11) + /* * 信号量等待时间设定:表示不等待。 */ @@ -197,10 +215,10 @@ typedef U16 SemHandle; /* * 信号量类型。 */ -enum SemType { - SEM_TYPE_COUNT, /* 计数型信号量 */ - SEM_TYPE_BUTT /* 非法信号量类型 */ -}; +/* 计数型信号量 */ +#define SEM_TYPE_COUNT 0 +/* 二进制信号量 */ +#define SEM_TYPE_BIN 1 /* * 信号量模块被阻塞线程唤醒方式。 @@ -231,8 +249,8 @@ struct SemInfo { U32 owner; /* 信号量唤醒方式,为SEM_MODE_FIFO或SEM_MODE_PRIOR */ enum SemMode mode; - /* 信号量类型,为SEM_TYPE_COUNT(计数型) */ - enum SemType type; + /* 信号量类型,为SEM_TYPE_COUNT(计数型)或SEM_TYPE_BIN(互斥型) */ + U32 type; }; /* diff --git a/src/include/uapi/prt_sys.h b/src/include/uapi/prt_sys.h index 143eaae..84951aa 100644 --- a/src/include/uapi/prt_sys.h +++ b/src/include/uapi/prt_sys.h @@ -141,6 +141,11 @@ extern "C" { */ #define OS_SYS_US_PER_SECOND 1000000 +/* + * 每秒纳秒数 + */ +#define OS_SYS_NS_PER_SECOND 1000000000 + /* * OS版本号 */ @@ -163,6 +168,23 @@ enum SysThreadType { SYS_BUTT }; +/* + * @brief 计算系统绝对时间钩子函数的类型定义。 + * + * @par 描述 + * 由于OS没有接管硬件定时器,需要用户提供计算系统时间的钩子函数。 + * + * @attention 获取的是64bit cycles 数据。 + * + * @param 无。 + * + * @retval 系统绝对时间 + * @par 依赖 + *
    • prt_sys.h:该接口声明所在的头文件。
    + * @see 无。 + */ +typedef U64 (*SysTimeFunc)(void); + /* * 系统模块配置信息的结构体定义。 * @@ -171,6 +193,8 @@ enum SysThreadType { struct SysModInfo { /* CPU主频,时钟周期 */ U32 systemClock; + /* 用户注册的获取系统时间函数 */ + SysTimeFunc sysTimeHook; /* CPU type */ U32 cpuType; #if defined(OS_OPTION_HWI_MAX_NUM_CONFIG) diff --git a/src/include/uapi/prt_task.h b/src/include/uapi/prt_task.h index 0a6c7b1..2107174 100644 --- a/src/include/uapi/prt_task.h +++ b/src/include/uapi/prt_task.h @@ -22,6 +22,10 @@ #include "./hw/armv7-m/prt_task.h" #endif +#if ((OS_HARDWARE_PLATFORM == OS_ARMV8)) +#include "./hw/armv8/os_cpu_armv8.h" +#endif + #ifdef __cplusplus #if __cplusplus extern "C" { diff --git a/src/include/uapi/prt_tick.h b/src/include/uapi/prt_tick.h index 9cbf0fe..08843bf 100644 --- a/src/include/uapi/prt_tick.h +++ b/src/include/uapi/prt_tick.h @@ -92,6 +92,27 @@ typedef void (*TickHandleFunc)(void); */ extern U64 PRT_TickGetCount(void); +/* + * @brief Tick中断处理函数。 + * + * @par 描述 + * Tick中断处理函数。 + * + * @attention + *
      + *
    • 只有在Tick中断源由用户提供,并在Tick中断处理中调用有效。若在非tick中断处理函数中调用,可能引发tick时钟不准确
    • + *
    • Tick模块裁剪开关未打开,调用此接口无效。
    • + *
    + * + * @param 无。 + * + * @retval 无。 + * @par 依赖 + *
    • prt_tick.h:该接口声明所在的头文件。
    + * @see 无 + */ +extern void PRT_TickISR(void); + #ifdef __cplusplus #if __cplusplus } diff --git a/src/include/uapi/prt_timer.h b/src/include/uapi/prt_timer.h index 3903939..63700e0 100644 --- a/src/include/uapi/prt_timer.h +++ b/src/include/uapi/prt_timer.h @@ -196,6 +196,15 @@ enum TimerFlag { */ #define OS_ERRNO_TIMER_NUM_TOO_LARGE OS_ERRNO_BUILD_ERROR(OS_MID_TIMER, 0x12) +/* + * 软件定时器错误码:返回指针参数为空。 + * + * 值: 0x02000d13 + * + * 解决方案: 输入有效的指针参数。 + */ +#define OS_ERRNO_SWTMR_RET_PTR_NULL OS_ERRNO_BUILD_ERROR(OS_MID_TIMER, 0x13) + /* * 定时器句柄定义 */ @@ -289,6 +298,24 @@ struct TimerCreatePara { U32 arg4; }; +/* + * 软件定时器信息的结构体类型定义 + */ +struct SwTmrInfo { + /* 定时器状态,三种状态:Free,Created,Running,Expired */ + U8 state; + /* 保留字段 */ + U8 resved[3]; + /* 定时器类型,两种类型:周期性、一次性 */ + enum TmrMode mode; + /* 定时器超时间隔 */ + U32 interval; + /* 定时器离超时剩余的ms数 */ + U32 remainMs; + /* 定时器超时处理函数 */ + TmrProcFunc handler; +}; + /* * @brief 创建定时器。 * @@ -440,6 +467,29 @@ extern U32 PRT_TimerRestart(U32 mid, TimerHandle tmrHandle); */ extern U32 PRT_TimerQuery(U32 mid, TimerHandle tmrHandle, U32 *expireTime); +/* + * @brief 获取指定软件定时器的信息。 + * + * @par 描述 + * 根据指定的定时器ID,获取定时器ID为tmrHandle的定时器的信息info。 + * + * @attention + *
      + *
    • 由于OS内部采用Tick作为软件定时器的时钟源,所以剩余时间转化成ms不一定是整数, + * 当转化后的毫秒数不为整数时,返回的剩余时间是该毫秒数取整后+1; + * 例如转化后毫秒数为4.2,则最终用户得到的剩余时间是5ms。
    • + *
    + * + * @param tmrHandle [IN] 类型#TimerHandle,定时器句柄; + * @param info [OUT] 类型#struct SwTmrInfo *,存放定时器信息结构体指针。 + * + * @retval #SRE_OK 0x00000000,获取指定定时器的信息成功。 + * @retval #其他值 信息获取失败。 + *
    • prt_timer.h:该接口声明所在的头文件。
    + * @see 无 + */ +extern U32 PRT_SwTmrInfoGet(TimerHandle tmrHandle, struct SwTmrInfo *info); + #ifdef __cplusplus #if __cplusplus } diff --git a/src/include/uapi/prt_typedef.h b/src/include/uapi/prt_typedef.h index 0e71a17..e7212b9 100644 --- a/src/include/uapi/prt_typedef.h +++ b/src/include/uapi/prt_typedef.h @@ -33,6 +33,9 @@ typedef signed short S16; typedef signed int S32; typedef signed long long S64; +typedef void *VirtAddr; +typedef void *PhyAddr; + #ifndef OS_SEC_ALW_INLINE #define OS_SEC_ALW_INLINE #endif @@ -80,6 +83,42 @@ typedef void (*OsVoidFunc)(void); #define OS_OK 0 #endif +#ifndef OS_FAIL +#define OS_FAIL 1 +#endif + +#ifndef U8_INVALID +#define U8_INVALID 0xffU +#endif + +#ifndef U12_INVALID +#define U12_INVALID 0xfffU +#endif + +#ifndef U16_INVALID +#define U16_INVALID 0xffffU +#endif + +#ifndef U32_INVALID +#define U32_INVALID 0xffffffffU +#endif + +#ifndef U64_INVALID +#define U64_INVALID 0xffffffffffffffffUL +#endif + +#ifndef U32_MAX +#define U32_MAX 0xFFFFFFFFU +#endif + +#ifndef S32_MAX +#define S32_MAX 0x7FFFFFFF +#endif + +#ifndef S32_MIN +#define S32_MIN (-S32_MAX-1) +#endif + #ifndef LIKELY #define LIKELY(x) __builtin_expect(!!(x), 1) #endif diff --git a/src/mem/CMakeLists.txt b/src/mem/CMakeLists.txt index 13ec2d1..ce5f895 100644 --- a/src/mem/CMakeLists.txt +++ b/src/mem/CMakeLists.txt @@ -1,3 +1,3 @@ -add_library(prt_mem OBJECT prt_mem.c) -add_library(prt_fscmem OBJECT fsc/prt_fscmem.c) +add_library_ex(prt_mem.c) +add_library_ex(fsc/prt_fscmem.c) diff --git a/src/mem/fsc/prt_fscmem.c b/src/mem/fsc/prt_fscmem.c index 869e460..07277c6 100644 --- a/src/mem/fsc/prt_fscmem.c +++ b/src/mem/fsc/prt_fscmem.c @@ -260,7 +260,7 @@ OS_SEC_TEXT U32 OsFscMemInit(U32 addr, U32 size) currBlk = (struct TagFscMemCtrl *)(uintptr_t)addr; currBlk->next = headBlk; currBlk->prevSize = 0; - currBlk->size = (U16)size; + currBlk->size = size; currBlk->prev = headBlk; headBlk->next = currBlk; headBlk->prev = currBlk; diff --git a/src/mem/include/prt_mem_external.h b/src/mem/include/prt_mem_external.h index 788093e..78d7b60 100644 --- a/src/mem/include/prt_mem_external.h +++ b/src/mem/include/prt_mem_external.h @@ -26,7 +26,7 @@ #define OS_MEM_ALIGN_CHECK(value) ((value) & 0x3UL) #define OS_FSC_MEM_MAGIC_USED (struct TagFscMemCtrl *)0x5a5aa5a5 -#define OS_FSC_MEM_LAST_IDX 16 +#define OS_FSC_MEM_LAST_IDX 31 #define OS_FSC_MEM_USED_HEAD_SIZE (sizeof(struct TagFscMemCtrl)) #define OS_FSC_MEM_TAIL_SIZE (sizeof(U32)) diff --git a/src/om/err/CMakeLists.txt b/src/om/err/CMakeLists.txt index e9e0ef1..055cf3d 100644 --- a/src/om/err/CMakeLists.txt +++ b/src/om/err/CMakeLists.txt @@ -1,2 +1,2 @@ -add_library(prt_err OBJECT prt_err.c) -add_library(prt_err_init OBJECT prt_err_init.c) +add_library_ex(prt_err.c) +add_library_ex(prt_err_init.c) diff --git a/src/om/err/prt_err.c b/src/om/err/prt_err.c index bab7a0a..403ef73 100644 --- a/src/om/err/prt_err.c +++ b/src/om/err/prt_err.c @@ -32,7 +32,16 @@ OS_SEC_L4_TEXT void OsErrRecordInCda(U32 errorNo) g_normalErrorNo = errorNo; } -OS_SEC_ALW_INLINE INLINE void OsErrRecord(U32 errorNo) +/* 返回上次错误,并清零 */ +OS_SEC_L4_TEXT U32 OsFatalErrClr(void) +{ + U32 oldFatalErr; + oldFatalErr = g_fatalErrorNo; + g_fatalErrorNo = 0; + return oldFatalErr; +} + +OS_SEC_L4_TEXT void OsErrRecord(U32 errorNo) { enum SysThreadType curThreadType; uintptr_t interruptSave; diff --git a/src/om/hook/CMakeLists.txt b/src/om/hook/CMakeLists.txt index 752c4f3..b84e0b7 100644 --- a/src/om/hook/CMakeLists.txt +++ b/src/om/hook/CMakeLists.txt @@ -1 +1 @@ -add_library(prt_hook_init OBJECT prt_hook_init.c) +add_library_ex(prt_hook_init.c) diff --git a/src/om/hook/prt_hook_init.c b/src/om/hook/prt_hook_init.c index 1f4c72c..1c9e2a1 100644 --- a/src/om/hook/prt_hook_init.c +++ b/src/om/hook/prt_hook_init.c @@ -95,8 +95,6 @@ OS_SEC_L4_TEXT U32 OsHookConfigInit(void) hooks += hookCnt + 1; } - OS_SPIN_LOCK_INIT(g_hookRegLock); - return OS_OK; } diff --git a/src/om/include/prt_err_external.h b/src/om/include/prt_err_external.h index e059ef8..d023268 100644 --- a/src/om/include/prt_err_external.h +++ b/src/om/include/prt_err_external.h @@ -18,6 +18,7 @@ #include "prt_err.h" extern void OsErrHandle(const char *fileName, U32 lineNo, U32 errorNo, U32 paraLen, void *para); +extern void OsErrRecord(U32 errorNo); /* * 模块间宏定义 */ @@ -54,6 +55,7 @@ extern void OsErrHandle(const char *fileName, U32 lineNo, U32 errorNo, U32 paraL #endif extern void OsErrRecordInCda(U32 errorNo); +extern U32 OsFatalErrClr(void); // 函数返回值void的,都通过此接口记录返回值到cda #define OS_ERR_RECORD(errorNo) \ diff --git a/src/osal/CMakeLists.txt b/src/osal/CMakeLists.txt new file mode 100644 index 0000000..aa47ffa --- /dev/null +++ b/src/osal/CMakeLists.txt @@ -0,0 +1,4 @@ +if(${CONFIG_OS_OPTION_POSIX}) + add_subdirectory(posix) +endif() + diff --git a/src/osal/posix/CMakeLists.txt b/src/osal/posix/CMakeLists.txt new file mode 100644 index 0000000..aed3bd0 --- /dev/null +++ b/src/osal/posix/CMakeLists.txt @@ -0,0 +1,13 @@ +add_library_ex(prt_pthread.c) +add_library_ex(prt_pthread_attr.c) +add_library_ex(prt_pthread_cancel.c) +add_library_ex(prt_pthread_init.c) +add_library_ex(prt_pthread_join.c) +add_library_ex(prt_pthread_key.c) +add_library_ex(prt_pthread_op.c) +add_library_ex(prt_pthread_sched.c) +add_library_ex(prt_posix_time.c) +add_library_ex(prt_posix_sem.c) +add_library_ex(prt_posix_mem.c) +add_library_ex(prt_posix_mutex.c) +add_library_ex(prt_pthread_rwlock.c) diff --git a/src/osal/posix/errno.c b/src/osal/posix/errno.c new file mode 100644 index 0000000..71dc702 --- /dev/null +++ b/src/osal/posix/errno.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: errno功能实现 + */ + +#include +#include "prt_task_external.h" + +/* the specific errno get or set in interrupt service routine */ +static int g_isrErrno; + +int *__errno(void) +{ + struct TagTskCb *runTask; + + if (OS_INT_INACTIVE) { + runTask = RUNNING_TASK; + return &runTask->lastErr; + } else { + return &g_isrErrno; + } +} diff --git a/src/osal/posix/include/prt_posix_internal.h b/src/osal/posix/include/prt_posix_internal.h new file mode 100644 index 0000000..aa432d7 --- /dev/null +++ b/src/osal/posix/include/prt_posix_internal.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2009-12-22 + * Description: Hardware interrupt implementation + */ +#ifndef PRT_POSIX_INTERNAL_H +#define PRT_POSIX_INTERNAL_H + +#include "prt_typedef.h" +#include "prt_buildef.h" +#include "prt_task_external.h" +#include "prt_list_external.h" +#include "errno.h" + +#define PRT_SCHED_FIFO 1 +#define PTHREAD_DEFAULT_POLICY PRT_SCHED_FIFO + +#define PTHREAD_DEFAULT_PRIORITY 10 +#define PTHREAD_OP_FAIL (-1) + +#define PTHREAD_ATTR_UNINIT 0 +#define PTHREAD_ATTR_INIT 1 + +typedef void * (*prt_pthread_startroutine)(void *); + +extern int PRT_PthreadCreate(TskHandle *thread, const pthread_attr_t *attrp, + prt_pthread_startroutine routine, void *arg); +extern void PRT_PthreadExit(void *retval); +extern int PRT_PthreadKeyCreate(pthread_key_t *key, void (*destructor)(void *)); +extern int PRT_PthreadKeyDelete(pthread_key_t key); +extern int PRT_PthreadSetSpecific(pthread_key_t key, const void *value); +extern void *PRT_PthreadGetSpecific(pthread_key_t key); +extern int PRT_PthreadJoin(TskHandle thread, void **status); +extern int PRT_PthreadDetach(TskHandle thread); +extern void PRT_PthreadTestCancel(void); +extern int PRT_PthreadCancel(TskHandle thread); +extern int PRT_PthreadSetCancelState(int state, int *oldstate); +extern int PRT_PthreadSetCancelType(int type, int *oldType); +extern U32 OsTimeSpec2Tick(const struct timespec *tp); +extern U32 OsTimeOut2Ticks(const struct timespec *time, U32 *ticks); + +#endif + diff --git a/src/osal/posix/prt_posix_mem.c b/src/osal/posix/prt_posix_mem.c new file mode 100644 index 0000000..c473be2 --- /dev/null +++ b/src/osal/posix/prt_posix_mem.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: malloc free功能实现 + */ +#include "prt_posix_internal.h" +#include "prt_mem.h" + +void *malloc(size_t size) +{ + return PRT_MemAlloc(0, OS_MEM_DEFAULT_FSC_PT, size); +} + +void free(void *mem) +{ + U32 ret; + + ret = PRT_MemFree(0, mem); + if (ret != OS_OK) { + OsErrRecord(ret); + } +} diff --git a/src/osal/posix/prt_posix_mutex.c b/src/osal/posix/prt_posix_mutex.c new file mode 100644 index 0000000..67b41cc --- /dev/null +++ b/src/osal/posix/prt_posix_mutex.c @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: pthread mutex功能实现 + */ +#include "pthread.h" +#include "prt_posix_internal.h" +#include "prt_sem.h" +#include "prt_sem_external.h" + +#define PTHREAD_MUTEX_TYPE_ISVALID(type) ((type) >= PTHREAD_MUTEX_NORMAL && (type) <= PTHREAD_MUTEX_DEFAULT) + +#if defined(OS_POSIX_TYPE_NEWLIB) +#define MUTEX_MAGIC 0xEBU +typedef struct prt_pthread_mutex_s { + U8 type; + U8 magic; + SemHandle mutex_sem; +} prt_pthread_mutex_t; +#else +#define MUTEX_MAGIC 0xEBCFDEA0U +typedef pthread_mutex_t prt_pthread_mutex_t; +#endif + +bool OsSemBusy(SemHandle semHandle) +{ + struct TagSemCb *semCb = NULL; + + semCb = GET_SEM(semHandle); + if (GET_MUTEX_TYPE(semCb->semType) != PTHREAD_MUTEX_RECURSIVE && semCb->semCount == 0 && + GET_SEM_TYPE(semCb->semType) == SEM_TYPE_BIN) { + return TRUE; + } else if (GET_MUTEX_TYPE(semCb->semType) == PTHREAD_MUTEX_RECURSIVE && semCb->semCount == 0 && + semCb->semOwner != RUNNING_TASK->taskPid) { + return TRUE; + } + + return FALSE; +} + +int pthread_mutexattr_init(pthread_mutexattr_t *attr) +{ + if (attr == NULL) { + return EINVAL; + } + attr->type = PTHREAD_MUTEX_DEFAULT; + attr->protocol = PTHREAD_PRIO_NONE; + attr->is_initialized = PTHREAD_ATTR_INIT; + + return OS_OK; +} + +int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) +{ + U32 ret; + + if (attr == NULL) { + return EINVAL; + } + ret = memset_s(attr, sizeof(pthread_mutexattr_t), 0, sizeof(pthread_mutexattr_t)); + if (ret != OS_OK) { + OsErrRecord(ret); + return EINVAL; + } + + return OS_OK; +} + +int PRT_PthreadMutexInit(prt_pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) +{ + U32 ret; + U32 protocol; + + if (mutex == NULL) { + return EINVAL; + } + + if (attr == NULL) { + mutex->type = PTHREAD_MUTEX_DEFAULT; + protocol = PTHREAD_PRIO_NONE; + } else { + if (attr->is_initialized != PTHREAD_ATTR_INIT) { + return EINVAL; + } + mutex->type = (U8)attr->type; + protocol = (U32)attr->protocol; + } + + switch (mutex->type) { + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_ERRORCHECK: + case PTHREAD_MUTEX_DEFAULT: + ret = OsSemCreate(OS_SEM_FULL, SEM_TYPE_BIN | (protocol << 8), SEM_MODE_PRIOR, &mutex->mutex_sem, (U32)&mutex->mutex_sem); + break; + + case PTHREAD_MUTEX_RECURSIVE: + ret = OsSemCreate(OS_SEM_FULL, SEM_TYPE_BIN | (PTHREAD_MUTEX_RECURSIVE << 4) | (protocol << 8), SEM_MODE_PRIOR, + &mutex->mutex_sem, (U32)&mutex->mutex_sem); + break; + + default: + ret = EINVAL; + break; + } + + if (ret != OS_OK) { + return EINVAL; + } + mutex->magic = MUTEX_MAGIC; + + return OS_OK; +} + +int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) +{ + return PRT_PthreadMutexInit((prt_pthread_mutex_t *)mutex, attr); +} + +static int OsMutexParamCheck(prt_pthread_mutex_t *mutex) +{ + int ret; +#if !defined(OS_POSIX_TYPE_NEWLIB) + prt_pthread_mutex_t tmp = PTHREAD_MUTEX_INITIALIZER; +#endif + + if (mutex == NULL) { + return EINVAL; + } + +#if defined(OS_POSIX_TYPE_NEWLIB) + if (*(U32 *)mutex == PTHREAD_MUTEX_INITIALIZER) { +#else + if (memcmp(mutex, &tmp, sizeof(prt_pthread_mutex_t)) == 0) { +#endif + ret = PRT_PthreadMutexInit(mutex, NULL); + if (ret != OS_OK) { + return EINVAL; + } + } + + return OS_OK; +} + +int PRT_PthreadMutexLock(prt_pthread_mutex_t *mutex) +{ + U32 ret; + U32 intSave; + + if (OsMutexParamCheck(mutex) != OS_OK) { + return EINVAL; + } + + intSave = PRT_HwiLock(); + if (mutex->magic != MUTEX_MAGIC) { + PRT_HwiRestore(intSave); + return EINVAL; + } + + if (mutex->type == PTHREAD_MUTEX_ERRORCHECK && OsSemBusy(mutex->mutex_sem)) { + PRT_HwiRestore(intSave); + return EINVAL; + } + PRT_HwiRestore(intSave); + + ret = PRT_SemPend(mutex->mutex_sem, OS_WAIT_FOREVER); + if (ret != OS_OK) { + return EINVAL; + } + + return OS_OK; +} + +int pthread_mutex_lock(pthread_mutex_t *mutex) +{ + return PRT_PthreadMutexLock((prt_pthread_mutex_t *)mutex); +} + +int PRT_PthreadMutexUnlock(prt_pthread_mutex_t *mutex) +{ + U32 ret; + U32 intSave; + + if (OsMutexParamCheck(mutex) != OS_OK) { + return EINVAL; + } + + intSave = PRT_HwiLock(); + if (mutex->magic != MUTEX_MAGIC) { + PRT_HwiRestore(intSave); + return EINVAL; + } + PRT_HwiRestore(intSave); + + ret = PRT_SemPost(mutex->mutex_sem); + if (ret != OS_OK) { + return EINVAL; + } + + return OS_OK; +} + +int pthread_mutex_unlock(pthread_mutex_t *mutex) +{ + return PRT_PthreadMutexUnlock((prt_pthread_mutex_t *)mutex); +} + +int PRT_PthreadMutexTrylock(prt_pthread_mutex_t *mutex) +{ + U32 ret; + U32 intSave; + + if (OsMutexParamCheck(mutex) != OS_OK) { + return EINVAL; + } + + intSave = PRT_HwiLock(); + if (mutex->magic != MUTEX_MAGIC) { + PRT_HwiRestore(intSave); + return EINVAL; + } + + if (OsSemBusy(mutex->mutex_sem)) { + PRT_HwiRestore(intSave); + return EBUSY; + } + PRT_HwiRestore(intSave); + + ret = PRT_SemPend(mutex->mutex_sem, OS_WAIT_FOREVER); + if (ret != OS_OK) { + return EINVAL; + } + + return OS_OK; +} + +int pthread_mutex_trylock(pthread_mutex_t *mutex) +{ + return PRT_PthreadMutexTrylock((prt_pthread_mutex_t *)mutex); +} + +int PRT_PthreadMutexDestroy(prt_pthread_mutex_t *mutex) +{ + U32 ret; + U32 intSave; + + if (OsMutexParamCheck(mutex) != OS_OK) { + return EINVAL; + } + + intSave = PRT_HwiLock(); + if (mutex->magic != MUTEX_MAGIC) { + PRT_HwiRestore(intSave); + return EINVAL; + } + PRT_HwiRestore(intSave); + + ret = PRT_SemDelete(mutex->mutex_sem); + if (ret != OS_OK) { + return EINVAL; + } + mutex->magic = 0; + + return OS_OK; +} + +int pthread_mutex_destroy(pthread_mutex_t *mutex) +{ + return PRT_PthreadMutexDestroy((prt_pthread_mutex_t *)mutex); +} + +int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) +{ + if (type == NULL || attr == NULL) { + return EINVAL; + } + + if (attr->is_initialized != PTHREAD_ATTR_INIT) { + return EINVAL; + } + + *type = attr->type; + + return OS_OK; +} + +int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) +{ + if (!PTHREAD_MUTEX_TYPE_ISVALID(type) || attr == NULL) { + return EINVAL; + } + + if (attr->is_initialized != PTHREAD_ATTR_INIT) { + return EINVAL; + } + + attr->type = type; + + return OS_OK; +} + +int PRT_PthreadMutexTimedlock(prt_pthread_mutex_t *mutex, const struct timespec *time) +{ + U32 ret; + U32 intSave; + U32 ticks; + + if (time == NULL) { + return EINVAL; + } + + if (OsMutexParamCheck(mutex) != OS_OK) { + return EINVAL; + } + + intSave = PRT_HwiLock(); + if (mutex->magic != MUTEX_MAGIC) { + PRT_HwiRestore(intSave); + return EINVAL; + } + + if (time->tv_sec < 0 || time->tv_nsec < 0) { + PRT_HwiRestore(intSave); + return EINVAL; + } + + PRT_HwiRestore(intSave); + + ret = OsTimeOut2Ticks(time, &ticks); + if (ret != OS_OK) { + return (int)ret; + } + + ret = PRT_SemPend(mutex->mutex_sem, ticks); + if (ret != OS_OK) { + ret = (ret == OS_ERRNO_SEM_TIMEOUT) ? ETIMEDOUT : EINVAL; + } + + return (int)ret; +} + +int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *time) +{ + return PRT_PthreadMutexTimedlock((prt_pthread_mutex_t *)mutex, time); +} + +int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int ceiling) +{ + (void)attr; + (void)ceiling; + + return EINVAL; +} + +int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *__restrict attr, int *ceiling) +{ + (void)attr; + (void)ceiling; + + return EINVAL; +} + +int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol) +{ + int ret; + + if (attr == NULL) { + return EINVAL; + } + + if (attr->is_initialized != PTHREAD_ATTR_INIT) { + return EINVAL; + } + + switch (protocol) { + case PTHREAD_PRIO_NONE: + case PTHREAD_PRIO_INHERIT: + attr->protocol = protocol; + ret = OS_OK; + break; + case PTHREAD_PRIO_PROTECT: + ret = ENOTSUP; + break; + default: + ret = EINVAL; + break; + } + + return ret; +} + +int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol) +{ + if (protocol == NULL || attr == NULL) { + return EINVAL; + } + + if (attr->is_initialized != PTHREAD_ATTR_INIT) { + return EINVAL; + } + + *protocol = attr->protocol; + + return OS_OK; +} diff --git a/src/osal/posix/prt_posix_sem.c b/src/osal/posix/prt_posix_sem.c new file mode 100644 index 0000000..e7fe0c9 --- /dev/null +++ b/src/osal/posix/prt_posix_sem.c @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: posix sem功能实现 + */ +#include "semaphore.h" +#include "prt_posix_internal.h" +#include "prt_sem_external.h" +#include "prt_sem.h" +#include "prt_sys_external.h" + +int sem_init(sem_t *sem, int shared, unsigned int value) +{ + U32 ret; + uintptr_t intSave; + SemHandle semHandle; + struct TagSemCb *semCb; + + (void)shared; + if (sem == NULL) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + if (value > OS_SEM_COUNT_MAX) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + intSave = OsIntLock(); + + ret = PRT_SemCreate(value, &semHandle); + if (ret != OS_OK) { + OsIntRestore(intSave); + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + // 创建成功 + semCb = GET_SEM(semHandle); + snprintf_s(semCb->name, MAX_POSIX_SEMAPHORE_NAME_LEN + 1, MAX_POSIX_SEMAPHORE_NAME_LEN, "defaultSem%d", semHandle); + sem->refCount++; + sem->semHandle = semHandle; + OsIntRestore(intSave); + + return OS_OK; +} + +sem_t *sem_open(const char *name, int flags, ...) +{ + U32 i; + U32 ret; + U32 val; + int mode; + va_list arg; + uintptr_t intSave; + struct TagSemCb *semCb; + bool created = FALSE; + SemHandle sem; + + if (name == NULL) { + errno = EINVAL; + return SEM_FAILED; + } + + if (strlen(name) >= MAX_POSIX_SEMAPHORE_NAME_LEN) { + errno = EINVAL; + return SEM_FAILED; + } + + va_start(arg, flags); + mode = (int)va_arg(arg, unsigned int); + val = va_arg(arg, unsigned int); + va_end(arg); + (void)mode; + intSave = PRT_HwiLock(); + for (i = 0; i < g_maxSem; i++) { + semCb = GET_SEM(i); + if (strcmp((const char *)semCb->name, name) == 0) { + created = TRUE; + break; + } + } + + if (created == TRUE) { + if (((U32)flags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) { + PRT_HwiRestore(intSave); + errno = EEXIST; + return SEM_FAILED; + } + semCb->handle.refCount++; + PRT_HwiRestore(intSave); + return (sem_t *)&(semCb->handle); + } + if ((flags & O_CREAT) == 0) { + PRT_HwiRestore(intSave); + errno = ENOENT; + return SEM_FAILED; + } + if (val > OS_SEM_COUNT_MAX) { + PRT_HwiRestore(intSave); + errno = EINVAL; + return SEM_FAILED; + } + + ret = PRT_SemCreate(val, &sem); + if (ret != OS_OK) { + PRT_HwiRestore(intSave); + errno = EAGAIN; + return SEM_FAILED; + } + + semCb = GET_SEM(sem); + if (strncpy_s((char *)semCb->name, MAX_POSIX_SEMAPHORE_NAME_LEN + 1, name, strlen(name) + 1) != 0) { + OS_GOTO_SYS_ERROR1(); + } + + semCb->handle.semHandle = sem; + semCb->handle.refCount++; + PRT_HwiRestore(intSave); + + return (sem_t *)&(semCb->handle); +} + +int sem_close(sem_t *sem) +{ + uintptr_t intSave; + struct TagSemCb *semCb; + + if (sem == NULL) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + semCb = GET_SEM(sem->semHandle); + + intSave = PRT_HwiLock(); + if (semCb->name[0] == 0) { + PRT_HwiRestore(intSave); + return OS_OK; + } + + if (semCb->handle.refCount > 0) { + semCb->handle.refCount--; + } else { + PRT_HwiRestore(intSave); + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + PRT_HwiRestore(intSave); + return OS_OK; +} + +int sem_getvalue(sem_t *__restrict sem, int *__restrict val) +{ + U32 ret; + uintptr_t intSave; + struct TagSemCb *semCb; + + if (val == NULL || sem == NULL) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + semCb = GET_SEM(sem->semHandle); + intSave = PRT_HwiLock(); + if (semCb->name[0] == 0) { + PRT_HwiRestore(intSave); + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + ret = PRT_SemGetCount(sem->semHandle, (U32 *)val); + if (ret != OS_OK) { + PRT_HwiRestore(intSave); + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + PRT_HwiRestore(intSave); + + return OS_OK; +} + +int sem_wait(sem_t *sem) +{ + U32 ret; + uintptr_t intSave; + struct TagSemCb *semCb; + + if (sem == NULL) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + semCb = GET_SEM(sem->semHandle); + intSave = PRT_HwiLock(); + if (semCb->name[0] == 0) { + PRT_HwiRestore(intSave); + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + ret = PRT_SemPend(sem->semHandle, OS_WAIT_FOREVER); + if (ret != OS_OK) { + PRT_HwiRestore(intSave); + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + PRT_HwiRestore(intSave); + + return OS_OK; +} + +int sem_trywait(sem_t *sem) +{ + U32 ret; + uintptr_t intSave; + struct TagSemCb *semCb; + + if (sem == NULL) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + semCb = GET_SEM(sem->semHandle); + intSave = PRT_HwiLock(); + if (semCb->name[0] == 0) { + PRT_HwiRestore(intSave); + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + ret = PRT_SemPend(sem->semHandle, 0); + if (ret != OS_OK) { + PRT_HwiRestore(intSave); + errno = EAGAIN; + return PTHREAD_OP_FAIL; + } + PRT_HwiRestore(intSave); + + return OS_OK; +} + +int sem_timedwait(sem_t *__restrict sem, const struct timespec *__restrict at) +{ + U32 ret; + U32 ticks; + + if (at == NULL || sem == NULL) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + if ((at->tv_sec < 0) || (at->tv_nsec < 0) || (at->tv_nsec > OS_SYS_NS_PER_SECOND)) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + ret = OsTimeOut2Ticks(at, &ticks); + if (ret != OS_OK) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + ret = PRT_SemPend(sem->semHandle, ticks); + if (ret == OS_ERRNO_SEM_TIMEOUT) { + errno = ETIMEDOUT; + return PTHREAD_OP_FAIL; + } else if (ret != OS_OK) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + return OS_OK; +} + +int sem_post(sem_t *sem) +{ + U32 ret; + uintptr_t intSave; + struct TagSemCb *semCb; + + if (sem == NULL) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + semCb = GET_SEM(sem->semHandle); + + intSave = PRT_HwiLock(); + if (semCb->name[0] == 0) { + PRT_HwiRestore(intSave); + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + ret = PRT_SemPost(sem->semHandle); + if (ret != OS_OK) { + PRT_HwiRestore(intSave); + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + PRT_HwiRestore(intSave); + + return OS_OK; +} + +int sem_destroy(sem_t *sem) +{ + U32 ret; + struct TagSemCb *semCb; + + if (sem == NULL) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + semCb = GET_SEM(sem->semHandle); + + ret = PRT_SemDelete(sem->semHandle); + if (ret != OS_OK) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + (void)memset_s(semCb->name, MAX_POSIX_SEMAPHORE_NAME_LEN + 1, 0, MAX_POSIX_SEMAPHORE_NAME_LEN + 1); + sem->semHandle = 0xffffU; + sem->refCount = 0; + + return OS_OK; +} + +int sem_unlink(const char *name) +{ + U32 i; + uintptr_t intSave; + struct TagSemCb *semCb; + bool find = FALSE; + U32 ret = OS_OK; + + if (name == NULL) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + intSave = PRT_HwiLock(); + for (i = 0; i < g_maxSem; i++) { + semCb = GET_SEM(i); + if (strcmp((const char *)semCb->name, name) == 0) { + find = TRUE; + break; + } + } + if (find == FALSE) { + PRT_HwiRestore(intSave); + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + if (semCb->handle.refCount == 0) { + ret = PRT_SemDelete((SemHandle)i); + if (ret != OS_OK) { + PRT_HwiRestore(intSave); + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + } + + (void)memset_s(semCb->name, MAX_POSIX_SEMAPHORE_NAME_LEN + 1, 0, MAX_POSIX_SEMAPHORE_NAME_LEN + 1); + semCb->handle.refCount = 0; + PRT_HwiRestore(intSave); + + return OS_OK; +} diff --git a/src/osal/posix/prt_posix_time.c b/src/osal/posix/prt_posix_time.c new file mode 100644 index 0000000..9d99bb2 --- /dev/null +++ b/src/osal/posix/prt_posix_time.c @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: time功能实现 + */ +#include "time.h" +#include "prt_posix_internal.h" +#include "prt_sys_external.h" +#include "prt_timer.h" +#include "prt_swtmr_external.h" + +#define OS_SYS_NS_PER_MS (OS_SYS_NS_PER_SECOND / OS_SYS_MS_PER_SECOND) + +static struct timespec g_accDeltaFromSet; + +/* 封装超时处理函数 */ +static void OsTimerWrapper(TimerHandle tmrHandle, U32 arg1, U32 arg2, U32 arg3, U32 arg4) +{ + (void)tmrHandle; + (void)arg3; + (void)arg4; + void *(*sigev_notify_function)(union sigval) = (void *)arg1; + + union sigval val = { + .sival_int = arg2 + }; + + sigev_notify_function(val); +} + +int timer_create(clockid_t clockId, struct sigevent * restrict evp, timer_t * restrict timerId) +{ + U32 ret; + TimerHandle swtmrId; + struct TimerCreatePara timer = {0}; + + if ((timerId == NULL) || (evp == NULL) || (clockId != CLOCK_REALTIME)) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + if (evp->sigev_notify != SIGEV_THREAD) { // 必须有超时处理函数 + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + timer.type = OS_TIMER_SOFTWARE; + timer.mode = OS_TIMER_LOOP; + timer.interval = 1; + timer.timerGroupId = 0; + timer.callBackFunc = OsTimerWrapper; + timer.arg1 = (U32)evp->sigev_notify_function; + timer.arg2 = (U32)evp->sigev_value.sival_int; + ret = PRT_TimerCreate(&timer, &swtmrId); + if (ret != OS_OK) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + *timerId = (timer_t)swtmrId; + return OS_OK; +} + +int timer_delete(timer_t timerId) +{ + U32 swtmrId = (U32)timerId; + + if (PRT_TimerDelete(0, swtmrId) != OS_OK) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + return OS_OK; +} + +void OsTimeGetHwTime(struct timespec *hwTime) +{ + U64 cycle = OsCurCycleGet64(); + U64 nowNsec = (cycle / g_systemClock) * OS_SYS_NS_PER_SECOND + + (cycle % g_systemClock) * OS_SYS_NS_PER_SECOND / g_systemClock; + + hwTime->tv_sec = nowNsec / OS_SYS_NS_PER_SECOND; + hwTime->tv_nsec = nowNsec % OS_SYS_NS_PER_SECOND; +} + +void OsTimeSetRealTime(const struct timespec *realTime) +{ + U32 intSave; + struct timespec hwTime = {0}; + + OsTimeGetHwTime(&hwTime); + intSave = PRT_HwiLock(); + g_accDeltaFromSet.tv_nsec = realTime->tv_nsec - hwTime.tv_nsec; + g_accDeltaFromSet.tv_sec = (realTime->tv_sec - hwTime.tv_sec) - (time_t)(g_accDeltaFromSet.tv_nsec < 0); + g_accDeltaFromSet.tv_nsec = (g_accDeltaFromSet.tv_nsec + OS_SYS_NS_PER_SECOND) % OS_SYS_NS_PER_SECOND; + PRT_HwiRestore(intSave); +} + +void OsTimeGetRealTime(struct timespec *realTime) +{ + U32 intSave; + struct timespec hwTime = {0}; + + OsTimeGetHwTime(&hwTime); + + intSave = PRT_HwiLock(); + realTime->tv_nsec = hwTime.tv_nsec + g_accDeltaFromSet.tv_nsec; + realTime->tv_sec = hwTime.tv_sec + g_accDeltaFromSet.tv_sec + (time_t)(realTime->tv_nsec >= OS_SYS_NS_PER_SECOND); + realTime->tv_nsec %= OS_SYS_NS_PER_SECOND; + PRT_HwiRestore(intSave); +} + +bool OsTimeCheckSpec(const struct timespec *tp) +{ + if (tp == NULL) { + return FALSE; + } + + if ((tp->tv_sec < 0) || (tp->tv_nsec < 0) || (tp->tv_nsec >= OS_SYS_NS_PER_SECOND)) { + return FALSE; + } + + return TRUE; +} + +void OsTimeMs2Spec(U32 expireTime, struct timespec *tp) +{ + U32 remainder; + + tp->tv_sec = expireTime / OS_SYS_MS_PER_SECOND; + remainder = expireTime - (U32)tp->tv_sec * OS_SYS_MS_PER_SECOND; + tp->tv_nsec = (long)remainder * OS_SYS_NS_PER_MS; +} + +void OsTimeSpec2Ms(const struct timespec *tp, U32 *expireTime) +{ + U32 tickCnt; + + tickCnt = OsTimeSpec2Tick(tp); + + *expireTime = (tickCnt / g_tickModInfo.tickPerSecond) * OS_SYS_MS_PER_SECOND; +} + +U32 OsTimeSpec2Tick(const struct timespec *tp) +{ + U64 ns; + U64 tmp; + U64 tickCnt; + U32 nsPerTick; + + nsPerTick = OS_SYS_NS_PER_SECOND / OsSysGetTickPerSecond(); // 每个tick多少纳秒 + ns = (U64)tp->tv_sec * OS_SYS_NS_PER_SECOND + (U64)tp->tv_nsec; + tickCnt = ns / nsPerTick; + tmp = ns - tickCnt * nsPerTick; + if (tmp > 0) { + tickCnt++; + } + + if (tickCnt > U32_MAX) { + tickCnt = U32_MAX; + } + + return (U32)tickCnt; +} + +U32 OsTimeOut2Ticks(const struct timespec *time, U32 *ticks) +{ + struct timespec curTime; + S64 timeOutNs; + U64 timeOut; + + if ((time->tv_nsec < 0) || (time->tv_nsec >= OS_SYS_NS_PER_SECOND) || + (time->tv_sec < 0) || (time->tv_sec > S32_MAX)) { + return EINVAL; + } + + OsTimeGetRealTime(&curTime); + + timeOutNs = (time->tv_sec - curTime.tv_sec) * OS_SYS_NS_PER_SECOND + (time->tv_nsec - curTime.tv_nsec); + if (timeOutNs <= 0) { + return ETIMEDOUT; + } + + timeOut = (U64)(time->tv_sec - curTime.tv_sec) * OsSysGetTickPerSecond(); + if (time->tv_nsec > curTime.tv_nsec) { + timeOut += ((U64)(time->tv_nsec - curTime.tv_nsec) * OsSysGetTickPerSecond() - 1) / OS_SYS_NS_PER_SECOND + 1; + } else { + timeOut -= ((U64)(curTime.tv_nsec - time->tv_nsec) * OsSysGetTickPerSecond()) / OS_SYS_NS_PER_SECOND; + } + // 因为tick误差在ms级,为了确保延时时间满足要求,向上加一 + timeOut = timeOut + 1; + *ticks = timeOut >= OS_WAIT_FOREVER ? OS_WAIT_FOREVER : (U32)timeOut; + + return OS_OK; +} + +int timer_gettime(timer_t timerId, struct itimerspec *value) +{ + U32 ret; + U32 expireTime; // 剩余超时时间,单位ms + struct SwTmrInfo info; + + if (value == NULL) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + ret = PRT_TimerQuery(0, (TimerHandle)timerId, &expireTime); + if (ret != OS_OK) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + ret = PRT_SwTmrInfoGet((TimerHandle)timerId, &info); + if (ret != OS_OK) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + OsTimeMs2Spec(expireTime, &value->it_value); + OsTimeMs2Spec((info.mode == OS_TIMER_ONCE) ? 0 : info.interval, &value->it_interval); + + return OS_OK; +} + +int timer_settime(timer_t timerId, int flags, const struct itimerspec *value, struct itimerspec *ovalue) +{ + U32 intSave; + U32 interval, expiry, ret; + struct TagSwTmrCtrl *swtmr; + (void)flags; + + if (value == NULL) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + if (!OsTimeCheckSpec(&value->it_value) || !OsTimeCheckSpec(&value->it_interval)) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + expiry = OsTimeSpec2Tick(&value->it_value); + interval = OsTimeSpec2Tick(&value->it_interval); + + if (interval != 0 && interval != expiry) { + errno = ENOTSUP; + return PTHREAD_OP_FAIL; + } + + if (ovalue) { + if (timer_gettime(timerId, ovalue) != OS_OK) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + } + + ret = PRT_TimerStop(0, timerId); + if (ret != OS_OK && ret != OS_ERRNO_SWTMR_UNSTART) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + // 当 it_value = 0, 表示要停止定时器. + if ((value->it_value.tv_sec == 0) && (value->it_value.tv_nsec == 0)) { + return OS_OK; + } + + intSave = PRT_HwiLock(); + swtmr = g_swtmrCbArray + OS_SWTMR_ID_2_INDEX(timerId); + swtmr->mode = (interval ? OS_TIMER_LOOP : OS_TIMER_ONCE); + swtmr->interval = (interval ? interval : expiry); + swtmr->idxRollNum = swtmr->interval; + PRT_HwiRestore(intSave); + + if (PRT_TimerStart(0, timerId) != OS_OK) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + return OS_OK; +} + +int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) +{ + U64 nanosec; + U64 tick; + const U32 nsPerTick = OS_SYS_NS_PER_SECOND / g_tickModInfo.tickPerSecond; + + if (!OsTimeCheckSpec(rqtp)) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + nanosec = (U64)rqtp->tv_sec * OS_SYS_NS_PER_SECOND + (U64)rqtp->tv_nsec; + tick = (nanosec + nsPerTick - 1) / nsPerTick; // 睡眠时间不得小于rqtp规定的时间 + + if (tick >= U32_MAX) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + if (PRT_TaskDelay((U32)tick) == OS_OK) { + if (rmtp != NULL) { + rmtp->tv_sec = rmtp->tv_nsec = 0; + } + return OS_OK; + } + + return PTHREAD_OP_FAIL; +} + +U32 sleep(U32 seconds) +{ + U32 ret; + U32 ticks; + + ticks = seconds * g_tickModInfo.tickPerSecond; + ret = PRT_TaskDelay(ticks ? (ticks + 1) : 0); + if (ret != OS_OK) { + return EINTR; + } + + return OS_OK; +} + +int clock_getres(clockid_t clockId, struct timespec *tp) +{ + if (tp == NULL) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + switch (clockId) { + case CLOCK_MONOTONIC_RAW: + case CLOCK_MONOTONIC: + case CLOCK_REALTIME: + case CLOCK_MONOTONIC_COARSE: + case CLOCK_REALTIME_COARSE: + tp->tv_nsec = (long)((OS_SYS_NS_PER_SECOND - 1) / g_systemClock + 1); // 每个cycle多少ns + tp->tv_sec = 0; + return OS_OK; + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_BOOTTIME: + case CLOCK_REALTIME_ALARM: + case CLOCK_BOOTTIME_ALARM: + errno = ENOTSUP; + return PTHREAD_OP_FAIL; + default: + errno = EINVAL; + return PTHREAD_OP_FAIL; + } +} + +int clock_settime(clockid_t clockId, const struct timespec *tp) +{ + if (!OsTimeCheckSpec(tp)) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + switch (clockId) { + case CLOCK_REALTIME: + OsTimeSetRealTime(tp); + return OS_OK; + case CLOCK_MONOTONIC_COARSE: + case CLOCK_REALTIME_COARSE: + case CLOCK_MONOTONIC_RAW: + case CLOCK_BOOTTIME: + case CLOCK_REALTIME_ALARM: + case CLOCK_BOOTTIME_ALARM: + errno = ENOTSUP; + return PTHREAD_OP_FAIL; + case CLOCK_MONOTONIC: + default: + errno = EINVAL; + return PTHREAD_OP_FAIL; + } +} + +int clock_gettime(clockid_t clockId, struct timespec *tp) +{ + if (tp == NULL) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + + switch (clockId) { + case CLOCK_MONOTONIC_RAW: + case CLOCK_MONOTONIC: + case CLOCK_MONOTONIC_COARSE: + OsTimeGetHwTime(tp); + return OS_OK; + case CLOCK_REALTIME: + case CLOCK_REALTIME_COARSE: + OsTimeGetRealTime(tp); + return OS_OK; + case CLOCK_BOOTTIME: + case CLOCK_REALTIME_ALARM: + case CLOCK_BOOTTIME_ALARM: + errno = ENOTSUP; + return PTHREAD_OP_FAIL; + default: + errno = EINVAL; + return PTHREAD_OP_FAIL; + } +} diff --git a/src/osal/posix/prt_pthread.c b/src/osal/posix/prt_pthread.c new file mode 100644 index 0000000..3adf394 --- /dev/null +++ b/src/osal/posix/prt_pthread.c @@ -0,0 +1,618 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: os内部pthread功能实现 + */ +#include "pthread.h" +#include "prt_posix_internal.h" +#include "../../core/kernel/task/prt_task_internal.h" +#include "prt_err_external.h" + +#define PTHREAD_TERMINATED 2 +#define PTHREAD_EXITED 3 + +void (*destor[PTHREAD_KEYS_MAX])(void *) = {0}; + +static void OsPthreadNotifyParents(struct TagTskCb *tskCb) +{ + U32 count = tskCb->joinCount; + + while (count--) { + PRT_SemPost(tskCb->joinableSem); + } +} + +static void OsPthreadRunDestructor(struct TagTskCb *self) +{ + int i; + void *val; + void (*destructor)(void *); + + for (i = 0; i < PTHREAD_KEYS_MAX; i++) { + if ((self->tsdUsed & (1U << (U32)i)) != 0) { + val = self->tsd[i]; + destructor = destor[i]; + destructor(val); + } + } + self->tsdUsed = 0; +} + +void PRT_PthreadExit(void *retval) +{ + U32 ret; + uintptr_t intSave; + struct TagTskCb *tskCb; + + intSave = OsIntLock(); + + tskCb = RUNNING_TASK; + while (tskCb->cancelBuf) { + void (*f)(void *) = tskCb->cancelBuf->_routine; + void *x = tskCb->cancelBuf->_arg; + tskCb->cancelBuf = tskCb->cancelBuf->_previous; + f(x); + } + + tskCb->retval = retval; + /* thread is joinable and other threads are waitting */ + if (tskCb->state == PTHREAD_CREATE_JOINABLE && tskCb->joinCount > 0) { + tskCb->state = PTHREAD_EXITED; + OsPthreadNotifyParents(tskCb); + } else { + if (tskCb->state == PTHREAD_CREATE_JOINABLE) { + tskCb->state = PTHREAD_EXITED; + } else { + tskCb->state = PTHREAD_TERMINATED; + } + if (tskCb->joinableSem != 0) { + PRT_SemDelete(tskCb->joinableSem); + tskCb->joinableSem = 0; + } + OsPthreadRunDestructor(tskCb); + } + + OsIntRestore(intSave); + + ret = PRT_TaskDelete(tskCb->taskPid); + if (ret != OS_OK) { + OsErrRecord(ret); + } +} + +static U32 OsPthreadCreatParaCheck(TskHandle *newthread, const pthread_attr_t *attrp, + prt_pthread_startroutine routine, pthread_attr_t *attr) +{ + int ret; + + if (newthread == NULL || routine == NULL) { + return EINVAL; + } + + if (attrp != NULL) { + if (attrp->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + *attr = *attrp; + } else { + ret = pthread_attr_init(attr); + if (ret != OS_OK) { + OsErrRecord(ret); + } + } + + return OS_OK; +} + +static void OsPthreadWrapper(uintptr_t param1, uintptr_t param2, uintptr_t param3, uintptr_t param4) +{ + void *ret; + + (void)param3; + (void)param4; + void *(*threadroutine)(void *) = (void *)param1; + + ret = threadroutine((void *)param2); + PRT_PthreadExit(ret); +} + +OS_SEC_ALW_INLINE INLINE U32 OsPthreadCreateRsrcInit(U32 taskId, pthread_attr_t *attr, + struct TagTskCb *tskCb, uintptr_t **topStackOut, uintptr_t *curStackSize) +{ + U32 ret = OS_OK; + uintptr_t *topStack = NULL; + + /* 创建任务线程 */ + if (g_taskNameAdd != NULL) { + ret = g_taskNameAdd(taskId, "pthread"); + if (ret != OS_OK) { + return ret; + } + } + + /* 查看用户是否配置了任务栈,如没有,则进行内存申请,并标记为系统配置,如有,则标记为用户配置。 */ + if (attr->stackaddr != 0) { + topStack = (void *)(attr->stackaddr); + tskCb->stackCfgFlg = OS_TSK_STACK_CFG_BY_USER; + } else { + topStack = OsTskMemAlloc(attr->stacksize); + if (topStack == NULL) { + ret = OS_ERRNO_TSK_NO_MEMORY; + } else { + tskCb->stackCfgFlg = OS_TSK_STACK_CFG_BY_SYS; + } + } + *curStackSize = attr->stacksize; + if (ret != OS_OK) { + return ret; + } + + *topStackOut = topStack; + return OS_OK; +} + +OS_SEC_ALW_INLINE INLINE void OsPthreadCreateTcbInit(uintptr_t stackPtr, pthread_attr_t *attr, + uintptr_t topStackAddr, uintptr_t curStackSize, struct TagTskCb *tskCb) +{ + /* Initialize the task's stack */ + tskCb->stackPointer = (void *)stackPtr; + tskCb->topOfStack = topStackAddr; + tskCb->stackSize = curStackSize; + tskCb->taskSem = NULL; + tskCb->priority = attr->schedparam.sched_priority; + tskCb->taskEntry = OsPthreadWrapper; +#if defined(OS_OPTION_EVENT) + tskCb->event = 0; + tskCb->eventMask = 0; +#endif + tskCb->lastErr = 0; + tskCb->taskStatus = OS_TSK_SUSPEND | OS_TSK_INUSE; + /* pthread init */ + tskCb->tsdUsed = 0; + tskCb->state = attr->detachstate; + tskCb->cancelState = PTHREAD_CANCEL_ENABLE; + tskCb->cancelType = PTHREAD_CANCEL_DEFERRED; + tskCb->cancelPending = 0; + tskCb->cancelBuf = NULL; + tskCb->retval = NULL; + tskCb->joinCount = 0; + tskCb->joinableSem = 0; + tskCb->tsdUsed = 0; + + INIT_LIST_OBJECT(&tskCb->pendList); + INIT_LIST_OBJECT(&tskCb->timerList); +} + +int PRT_PthreadCreate(TskHandle *thread, const pthread_attr_t *attrp, + prt_pthread_startroutine routine, void *arg) +{ + U32 ret; + U32 taskId; + uintptr_t intSave; + void *stackPtr = NULL; + uintptr_t *topStack = NULL; + uintptr_t curStackSize = 0; + struct TagTskCb *tskCb = NULL; + pthread_attr_t attr = {0}; + + ret = OsPthreadCreatParaCheck(thread, attrp, routine, &attr); + if (ret != OS_OK) { + return ret; + } + + intSave = OsIntLock(); + ret = OsTaskCreateChkAndGetTcb(&tskCb); + if (ret != OS_OK) { + OsIntRestore(intSave); + return ENOMEM; + } + + taskId = tskCb->taskPid; + + ret = OsPthreadCreateRsrcInit(taskId, &attr, tskCb, &topStack, &curStackSize); + if (ret != OS_OK) { + ListAdd(&tskCb->pendList, &g_tskCbFreeList); + OsIntRestore(intSave); + return ENOMEM; + } + OsTskStackInit(curStackSize, (uintptr_t)topStack); + + stackPtr = OsTskContextInit(taskId, curStackSize, topStack, (uintptr_t)OsTskEntry); + + OsPthreadCreateTcbInit((uintptr_t)stackPtr, &attr, (uintptr_t)topStack, curStackSize, tskCb); + tskCb->args[OS_TSK_PARA_0] = (uintptr_t)routine; + tskCb->args[OS_TSK_PARA_1] = (uintptr_t)arg; + tskCb->args[OS_TSK_PARA_2] = 0; + tskCb->args[OS_TSK_PARA_3] = 0; + OsIntRestore(intSave); + + if (tskCb->state == PTHREAD_CREATE_JOINABLE) { + ret = PRT_SemCreate(0, &tskCb->joinableSem); + if (ret != OS_OK) { + return EAGAIN; + } + } + + ret = PRT_TaskResume(taskId); + if (ret != OS_OK) { + if (tskCb->state == PTHREAD_CREATE_JOINABLE) { + PRT_SemDelete(tskCb->joinableSem); + } + return EAGAIN; + } + *thread = taskId; + + return OS_OK; +} + +void OsPthreadDestructor(void *arg) +{ + (void)arg; +} + +int PRT_PthreadKeyCreate(pthread_key_t *key, void (*destructor)(void *)) +{ + int i; + + for (i = 0; i < PTHREAD_KEYS_MAX; i++) { + if (destor[i] == NULL) { + *key = (pthread_key_t)i; + break; + } + } + + if (i == PTHREAD_KEYS_MAX) { + return EAGAIN; + } + + if (destructor != NULL) { + destor[i] = destructor; + } else { + destor[i] = OsPthreadDestructor; + } + + return OS_OK; +} + +int PRT_PthreadKeyDelete(pthread_key_t key) +{ + U32 i; + uintptr_t intSave; + + if ((U32)key >= PTHREAD_KEYS_MAX || destor[key] == NULL) { + return EINVAL; + } + + intSave = OsIntLock(); + for (i = 0; i < g_tskMaxNum; i++) { + g_tskCbArray[i].tsdUsed = g_tskCbArray[i].tsdUsed & ~(1U << (U32)key); + g_tskCbArray[i].tsd[key] = NULL; + } + destor[key] = NULL; + OsIntRestore(intSave); + + return OS_OK; +} + +int PRT_PthreadSetSpecific(pthread_key_t key, const void *value) +{ + struct TagTskCb *tskCb = RUNNING_TASK; + + if ((U32)key >= PTHREAD_KEYS_MAX || destor[key] == NULL) { + return EINVAL; + } + tskCb->tsd[key] = (void *)(uintptr_t)value; + tskCb->tsdUsed |= (1U << (U32)key); + + return OS_OK; +} + +void *PRT_PthreadGetSpecific(pthread_key_t key) +{ + struct TagTskCb *tskCb = RUNNING_TASK; + + if ((U32)key >= PTHREAD_KEYS_MAX) { + return NULL; + } + if ((tskCb->tsdUsed & (1U << (U32)key)) == 0) { + return NULL; + } + + return tskCb->tsd[key]; +} + +static void OsPthreadDoCleanupPush(struct _pthread_cleanup_context *cb) +{ + struct TagTskCb *tskCb = RUNNING_TASK; + + cb->_previous = tskCb->cancelBuf; + tskCb->cancelBuf = cb; +} + +static void OsPthreadDoCleanupPop(struct _pthread_cleanup_context *cb) +{ + struct TagTskCb *tskCb = RUNNING_TASK; + + tskCb->cancelBuf = cb->_previous; +} + +void _pthread_cleanup_push(struct _pthread_cleanup_context *cb, void (*f)(void *), void *x) +{ + cb->_routine = f; + cb->_arg = x; + OsPthreadDoCleanupPush(cb); +} + +void _pthread_cleanup_pop(struct _pthread_cleanup_context *cb, int run) +{ + OsPthreadDoCleanupPop(cb); + if (run) cb->_routine(cb->_arg); +} + +U32 OsPthreadJoinExit(struct TagTskCb *tskCb, void **status) +{ + switch (tskCb->state) { + case PTHREAD_EXITED: + if (status != NULL) { + *status = tskCb->retval; + } + /* the last parent frees the resources */ + if (tskCb->joinCount == 0) { + tskCb->state = PTHREAD_TERMINATED; + if (tskCb->joinableSem != 0) { + PRT_SemDelete(tskCb->joinableSem); + tskCb->joinableSem = 0; + } + OsPthreadRunDestructor(tskCb); + } + return OS_OK; + case PTHREAD_CREATE_JOINABLE: + case PTHREAD_CREATE_DETACHED: + return EINVAL; + case PTHREAD_TERMINATED: /* fall through */ + default: + return ESRCH; + } +} + +int PRT_PthreadJoin(TskHandle thread, void **status) +{ + struct TagTskCb *tskCb = RUNNING_TASK; + uintptr_t intSave; + U32 ret = 0; + + if (thread == tskCb->taskPid) { + return EDEADLK; + } + if (CHECK_TSK_PID_OVERFLOW(thread)) { + return ESRCH; + } + + intSave = OsIntLock(); + + tskCb = GET_TCB_HANDLE(thread); + /* the target thread already exited */ + if (tskCb->taskStatus == OS_TSK_UNUSED) { + ret = OsPthreadJoinExit(tskCb, status); + OsIntRestore(intSave); + return ret; + } + + if (tskCb->state == PTHREAD_CREATE_JOINABLE) { + /* wait the target thread to finish */ + tskCb->joinCount++; + OsIntRestore(intSave); + ret = PRT_SemPend(tskCb->joinableSem, OS_WAIT_FOREVER); + if (ret != OS_OK) { + tskCb->joinCount--; + return EDEADLK; + } + intSave = OsIntLock(); + tskCb->joinCount--; + } + + ret = OsPthreadJoinExit(tskCb, status); + OsIntRestore(intSave); + + return ret; +} + +int PRT_PthreadDetach(TskHandle thread) +{ + struct TagTskCb *tskCb; + uintptr_t intSave; + U32 ret = 0; + + if (CHECK_TSK_PID_OVERFLOW(thread)) { + return ESRCH; + } + + tskCb = GET_TCB_HANDLE(thread); + intSave = OsIntLock(); + + switch (tskCb->state) { + case PTHREAD_CREATE_JOINABLE: + tskCb->state = PTHREAD_CREATE_DETACHED; + OsPthreadNotifyParents(tskCb); + break; + case PTHREAD_EXITED: + PRT_PthreadJoin(thread, NULL); + break; + case PTHREAD_TERMINATED: + ret = ESRCH; + break; + default: + ret = EINVAL; + break; + } + + OsIntRestore(intSave); + + return ret; +} + +void PRT_PthreadTestCancel(void) +{ + struct TagTskCb *tskCb = RUNNING_TASK; + + if (tskCb->cancelState == PTHREAD_CANCEL_ENABLE && tskCb->cancelPending) { + PRT_PthreadExit(PTHREAD_CANCELED); + } +} + +static int OsPthreadCancelDetachedHandle(struct TagTskCb *tskCb) +{ + U32 ret; + + tskCb->state = PTHREAD_TERMINATED; + if (tskCb->joinableSem != 0) { + ret = PRT_SemDelete(tskCb->joinableSem); + if (ret != OS_OK) { + return EINVAL; + } + tskCb->joinableSem = 0; + } + while (tskCb->cancelBuf) { + void (*f)(void *) = tskCb->cancelBuf->_routine; + void *x = tskCb->cancelBuf->_arg; + tskCb->cancelBuf = tskCb->cancelBuf->_previous; + f(x); + } + OsPthreadRunDestructor(tskCb); + ret = PRT_TaskDelete(tskCb->taskPid); + if (ret != OS_OK) { + return EAGAIN; + } + + return OS_OK; +} + +static int OsPthreadCancelJoinableHandle(struct TagTskCb *tskCb) +{ + U32 ret; + + while (tskCb->cancelBuf) { + void (*f)(void *) = tskCb->cancelBuf->_routine; + void *x = tskCb->cancelBuf->_arg; + tskCb->cancelBuf = tskCb->cancelBuf->_previous; + f(x); + } + tskCb->state = PTHREAD_EXITED; + if (tskCb->joinCount == 0) { + if (tskCb->joinableSem != 0) { + ret = PRT_SemDelete(tskCb->joinableSem); + if (ret != OS_OK) { + return EINVAL; + } + tskCb->joinableSem = 0; + } + OsPthreadRunDestructor(tskCb); + } else { + while (tskCb->joinCount) { + tskCb->joinCount--; + ret = PRT_SemPost(tskCb->joinableSem); + if (ret != OS_OK) { + return EINVAL; + } + } + } + ret = PRT_TaskDelete(tskCb->taskPid); + if (ret != OS_OK) { + return EAGAIN; + } + + return OS_OK; +} + +int PRT_PthreadCancel(TskHandle thread) +{ + struct TagTskCb *tskCb; + uintptr_t intSave; + int ret = OS_OK; + struct TagTskCb *curTskCb = RUNNING_TASK; + + if (CHECK_TSK_PID_OVERFLOW(thread)) { + return ESRCH; + } + + tskCb = GET_TCB_HANDLE(thread); + intSave = OsIntLock(); + if (thread == curTskCb->taskPid) { + if (tskCb->cancelState == PTHREAD_CANCEL_ENABLE && tskCb->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS) { + PRT_PthreadExit(PTHREAD_CANCELED); + } + OsIntRestore(intSave); + return OS_OK; + } + + tskCb->cancelPending = 1; + if (tskCb->cancelType == PTHREAD_CANCEL_DEFERRED) { + OsIntRestore(intSave); + return OS_OK; + } + if (tskCb->cancelState == PTHREAD_CANCEL_ENABLE) { + if (tskCb->state == PTHREAD_CREATE_DETACHED) { + ret = OsPthreadCancelDetachedHandle(tskCb); + } else if (tskCb->state == PTHREAD_CREATE_JOINABLE) { + ret = OsPthreadCancelJoinableHandle(tskCb); + } + } + + OsIntRestore(intSave); + + return ret; +} + +int PRT_PthreadSetCancelState(int state, int *oldstate) +{ + struct TagTskCb *tskCb = RUNNING_TASK; + uintptr_t intSave; + + /* currently, only supports ENABLE and DISABLE */ + if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE) { + return EINVAL; + } + + intSave = OsIntLock(); + if (oldstate != NULL) { + *oldstate = tskCb->cancelState; + } + tskCb->cancelState = state; + if (state == PTHREAD_CANCEL_ENABLE && tskCb->cancelPending) { + PRT_PthreadExit(PTHREAD_CANCELED); + } + OsIntRestore(intSave); + + return OS_OK; +} + +int PRT_PthreadSetCancelType(int type, int *oldType) +{ + struct TagTskCb *tskCb = RUNNING_TASK; + uintptr_t intSave; + + if (type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS) { + return EINVAL; + } + + intSave = OsIntLock(); + if (oldType != NULL) { + *oldType = tskCb->cancelType; + } + tskCb->cancelType = type; + if (type == PTHREAD_CANCEL_ASYNCHRONOUS) { + PRT_PthreadTestCancel(); + } + OsIntRestore(intSave); + + return OS_OK; +} diff --git a/src/osal/posix/prt_pthread_attr.c b/src/osal/posix/prt_pthread_attr.c new file mode 100644 index 0000000..3bfda02 --- /dev/null +++ b/src/osal/posix/prt_pthread_attr.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: pthread attr功能实现 + */ + +#include "pthread.h" +#include "sched.h" +#include "prt_posix_internal.h" + +int pthread_attr_init(pthread_attr_t *attr) +{ + if (attr == NULL) { + return ENOMEM; + } + + attr->schedpolicy = PTHREAD_DEFAULT_POLICY; + attr->stackaddr = NULL; + attr->stacksize = (int)g_tskModInfo.defaultSize; + attr->schedparam.sched_priority = PTHREAD_DEFAULT_PRIORITY; + attr->detachstate = PTHREAD_CREATE_JOINABLE; + attr->inheritsched = PTHREAD_EXPLICIT_SCHED; + attr->is_initialized = PTHREAD_ATTR_INIT; + + return OS_OK; +} + +int pthread_attr_destroy(pthread_attr_t *attr) +{ + if (attr != NULL && attr->is_initialized != PTHREAD_ATTR_UNINIT) { + *attr = (pthread_attr_t){0}; + return OS_OK; + } + + return EINVAL; +} + +int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachState) +{ + if (attr == NULL || detachState == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + + *detachState = attr->detachstate; + + return OS_OK; +} + +int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachState) +{ + if (attr == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + + if (detachState > PTHREAD_CREATE_JOINABLE || detachState < PTHREAD_CREATE_DETACHED) { + return EINVAL; + } + + attr->detachstate = detachState; + + return OS_OK; +} + +int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *schedpolicy) +{ + if (attr == NULL || schedpolicy == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + + *schedpolicy = attr->schedpolicy; + + return OS_OK; +} + +int pthread_attr_setschedpolicy(pthread_attr_t *attr, int schedpolicy) +{ + if (attr == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT || schedpolicy > PTHREAD_DEFAULT_POLICY) { + return EINVAL; + } + + if (schedpolicy < 0) { + return ENOTSUP; + } + + attr->schedpolicy = schedpolicy; + + return OS_OK; +} + +int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stackSize) +{ + if (attr == NULL || stackSize == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + + *stackSize = attr->stacksize; + + return OS_OK; +} + +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stackSize) +{ + U64 stackAddrLen; + + if (attr == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + + if (stackSize < OS_TSK_MIN_STACK_SIZE) { + return EINVAL; + } + + stackAddrLen = (U64)(stackSize); + /* posix接口不实现msgq, queNum默认为0 */ + if ((uintptr_t)attr->stackaddr != 0U) { + stackAddrLen += (uintptr_t)(attr->stackaddr); + } + /* 保证栈空间在4G范围内不溢出 */ + if (stackAddrLen > OS_MAX_U32) { + return EINVAL; + } + + attr->stacksize = (int)stackSize; + + return OS_OK; +} + +int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackAddr) +{ + if (attr == NULL || stackAddr == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + + *stackAddr = attr->stackaddr; + + return OS_OK; +} + +int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackAddr) +{ + U64 stackAddrLen; + + if (attr == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + + stackAddrLen = (U32)(attr->stacksize); + /* posix接口不实现msgq, queNum默认为0 */ + if ((uintptr_t)stackAddr != 0U) { + stackAddrLen += (uintptr_t)(stackAddr); + } + /* 保证栈空间在4G范围内不溢出 */ + if (stackAddrLen > OS_MAX_U32) { + return EINVAL; + } + + attr->stackaddr = stackAddr; + + return OS_OK; +} + +int pthread_attr_getstack(const pthread_attr_t *attr, void **stackAddr, size_t *stackSize) +{ + if (attr == NULL || stackAddr == NULL || stackSize == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + + *stackAddr = attr->stackaddr; + *stackSize = attr->stacksize; + + return OS_OK; +} + +int pthread_attr_setstack(pthread_attr_t *attr, void *stackAddr, size_t stackSize) +{ + U64 stackAddrLen; + + if (attr == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + + if (stackSize < (long)OS_TSK_MIN_STACK_SIZE) { + return EINVAL; + } + + stackAddrLen = (U64)(stackSize); + /* posix接口不实现msgq, queNum默认为0 */ + if ((uintptr_t)stackAddr != 0U) { + stackAddrLen += (uintptr_t)(stackAddr); + } + /* 保证栈空间在4G范围内不溢出 */ + if (stackAddrLen > OS_MAX_U32) { + return EINVAL; + } + + attr->stackaddr = stackAddr; + attr->stacksize = (int)stackSize; + + return OS_OK; +} + +int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched) +{ + if (attr == NULL || inheritsched == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + + *inheritsched = attr->inheritsched; + + return OS_OK; +} + +int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched) +{ + if (attr == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + + if ((U32)inheritsched > (U32)PTHREAD_EXPLICIT_SCHED) { + return EINVAL; + } + + attr->inheritsched = inheritsched; + + return OS_OK; +} + +int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *schedparam) +{ + if (attr == NULL || schedparam == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + + schedparam->sched_priority = attr->schedparam.sched_priority; + + return OS_OK; +} + +int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *schedparam) +{ + if (attr == NULL || schedparam == NULL || attr->is_initialized == PTHREAD_ATTR_UNINIT) { + return EINVAL; + } + /* task 优先级范围 OS_TSK_PRIORITY_HIGHEST <= priority < OS_TSK_PRIORITY_LOWEST, 避免与idle线程优先级一致得不到调度 */ + if (schedparam->sched_priority < OS_TSK_PRIORITY_HIGHEST || schedparam->sched_priority >= OS_TSK_PRIORITY_LOWEST) { + return ENOTSUP; + } + + attr->schedparam.sched_priority = schedparam->sched_priority; + + return OS_OK; +} diff --git a/src/osal/posix/prt_pthread_cancel.c b/src/osal/posix/prt_pthread_cancel.c new file mode 100644 index 0000000..b1a442f --- /dev/null +++ b/src/osal/posix/prt_pthread_cancel.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: pthread cancel功能实现 + */ +#include "pthread.h" +#include "prt_posix_internal.h" + +int pthread_cancel(pthread_t thread) +{ + return PRT_PthreadCancel((TskHandle)thread); +} + +void pthread_testcancel(void) +{ + PRT_PthreadTestCancel(); +} + +int pthread_setcancelstate(int state, int *oldstate) +{ + return PRT_PthreadSetCancelState(state, oldstate); +} + +int pthread_setcanceltype(int type, int *oldType) +{ + return PRT_PthreadSetCancelType(type, oldType); +} diff --git a/src/osal/posix/prt_pthread_init.c b/src/osal/posix/prt_pthread_init.c new file mode 100644 index 0000000..4259f75 --- /dev/null +++ b/src/osal/posix/prt_pthread_init.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: pthread创建功能实现 + */ + +#include "pthread.h" +#include "prt_posix_internal.h" + +int pthread_create(pthread_t *newthread, const pthread_attr_t *attr, void *(*threadroutine)(void *), void *arg) +{ + return PRT_PthreadCreate((TskHandle *)newthread, attr, threadroutine, arg); +} + +void pthread_exit(void *retval) +{ + PRT_PthreadExit(retval); + /* if PRT_PthreadExit is ok, never comes here */ + while (1) { + } +} \ No newline at end of file diff --git a/src/osal/posix/prt_pthread_join.c b/src/osal/posix/prt_pthread_join.c new file mode 100644 index 0000000..ca8fd79 --- /dev/null +++ b/src/osal/posix/prt_pthread_join.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: pthread join功能实现 + */ +#include "pthread.h" +#include "prt_posix_internal.h" + +int pthread_join(pthread_t thread, void **status) +{ + return PRT_PthreadJoin((TskHandle)thread, status); +} + +int pthread_detach(pthread_t thread) +{ + return PRT_PthreadDetach((TskHandle)thread); +} diff --git a/src/osal/posix/prt_pthread_key.c b/src/osal/posix/prt_pthread_key.c new file mode 100644 index 0000000..92df3f4 --- /dev/null +++ b/src/osal/posix/prt_pthread_key.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: pthread key功能实现 + */ +#include "pthread.h" +#include "prt_posix_internal.h" + +int pthread_key_create(pthread_key_t *key, void (*destructor)(void *)) +{ + return PRT_PthreadKeyCreate(key, destructor); +} + +int pthread_key_delete(pthread_key_t key) +{ + return PRT_PthreadKeyDelete(key); +} + +int pthread_setspecific(pthread_key_t key, const void *value) +{ + return PRT_PthreadSetSpecific(key, value); +} + +void *pthread_getspecific(pthread_key_t key) +{ + return PRT_PthreadGetSpecific(key); +} \ No newline at end of file diff --git a/src/osal/posix/prt_pthread_op.c b/src/osal/posix/prt_pthread_op.c new file mode 100644 index 0000000..df9ed00 --- /dev/null +++ b/src/osal/posix/prt_pthread_op.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: pthread功能实现 + */ +#include "pthread.h" +#include "prt_posix_internal.h" + +pthread_t pthread_self(void) +{ + struct TagTskCb *tskCb = RUNNING_TASK; + + if (!tskCb) { + OS_GOTO_SYS_ERROR1(); + return (pthread_t)-1; + } + + return (pthread_t)tskCb->taskPid; +} + +int pthread_equal(pthread_t pt1, pthread_t pt2) +{ + return (pt1 == pt2); +} \ No newline at end of file diff --git a/src/osal/posix/prt_pthread_rwlock.c b/src/osal/posix/prt_pthread_rwlock.c new file mode 100644 index 0000000..df08cf2 --- /dev/null +++ b/src/osal/posix/prt_pthread_rwlock.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: pthread rwlock功能实现 + */ +#include "pthread.h" +#include "prt_posix_internal.h" +#include "../../core/ipc/rwlock/prt_rwlock_internal.h" +#include "prt_mem.h" + +#if defined(OS_POSIX_TYPE_NEWLIB) +prt_pthread_rwlock_t g_rwlist_head = {0}; + +OS_SEC_ALW_INLINE INLINE U32 OsRwlockGetMagic(pthread_rwlock_t *rwlock) +{ + return ((*(U32 *)rwlock & 0xffff0000U) >> 16U); +} + +OS_SEC_ALW_INLINE INLINE void OsRwlockSetMagic(pthread_rwlock_t *rwlock, U32 val) +{ + *(U32 *)rwlock = (*(U32 *)rwlock & 0xffffU) | (val << 16U); +} + +OS_SEC_ALW_INLINE INLINE U32 OsRwlockGetIndex(pthread_rwlock_t *rwlock) +{ + return (*(U32 *)rwlock & 0xffffU); +} + +OS_SEC_ALW_INLINE INLINE void OsRwlockSetIndex(pthread_rwlock_t *rwlock, U32 val) +{ + *(U32 *)rwlock = (*(U32 *)rwlock & 0xffff0000U) | (val & 0xffffU); +} +#endif + +static prt_pthread_rwlock_t *OsRwlock2InnerStruct(pthread_rwlock_t *rwl) +{ +#if defined(OS_POSIX_TYPE_NEWLIB) + prt_pthread_rwlock_t *rwlock = NULL; + prt_pthread_rwlock_t *ptr = &g_rwlist_head; + + if (rwl == NULL) { + return NULL; + } + if (OsRwlockGetMagic(rwl) != RWLOCK_MAGIC_NUM) { + return NULL; + } + while (ptr != NULL) { + if (OsRwlockGetIndex(rwl) == ptr->index) { + rwlock = ptr; + break; + } + ptr = ptr->next; + } + + return rwlock; +#else + return (prt_pthread_rwlock_t *)rwl; +#endif +} + +/* + * 初始化读写锁 + */ +int PRT_PthreadRwlockInit(prt_pthread_rwlock_t *rwl, const pthread_rwlockattr_t *attr) +{ + U32 intSave; + + (void)attr; + if (rwl == NULL) { + return EINVAL; + } + + intSave = PRT_HwiLock(); + if ((rwl->rw_magic & RWLOCK_COUNT_MASK) == RWLOCK_MAGIC_NUM) { + PRT_HwiRestore(intSave); + return EBUSY; + } + + rwl->rw_count = 0; + rwl->rw_owner = NULL; + INIT_LIST_OBJECT(&(rwl->rw_read)); + INIT_LIST_OBJECT(&(rwl->rw_write)); + rwl->rw_magic = RWLOCK_MAGIC_NUM; + PRT_HwiRestore(intSave); + + return OS_OK; +} + +int pthread_rwlock_init(pthread_rwlock_t *rwl, const pthread_rwlockattr_t *attr) +{ +#if defined(OS_POSIX_TYPE_NEWLIB) + prt_pthread_rwlock_t *rwlock; + prt_pthread_rwlock_t *ptr = &g_rwlist_head; + U16 index = 0; + + if (rwl == NULL) { + return EINVAL; + } + if (OsRwlockGetMagic(rwl) == RWLOCK_MAGIC_NUM) { + return EBUSY; + } + rwlock = PRT_MemAlloc(0, 0, sizeof(prt_pthread_rwlock_t)); + if (rwlock == NULL) { + return ENOMEM; + } + while (ptr->next != NULL) { + if ((index + 1) != ptr->index) { + break; + } + index = ptr->index; + ptr = ptr->next; + } + rwlock->index = index + 1; + OsRwlockSetMagic(rwl, RWLOCK_MAGIC_NUM); + OsRwlockSetIndex(rwl, index + 1); + rwlock->next = ptr->next; + ptr->next = rwlock; + + return PRT_PthreadRwlockInit(rwlock, attr); +#else + return PRT_PthreadRwlockInit((prt_pthread_rwlock_t *)rwl, attr); +#endif +} + +/* + * 销毁读写锁 + */ +int PRT_PthreadRwlockDestroy(prt_pthread_rwlock_t *rwl) +{ + U32 intSave; + + if (rwl == NULL) { + return EINVAL; + } + + intSave = PRT_HwiLock(); + if ((rwl->rw_magic & RWLOCK_COUNT_MASK) != RWLOCK_MAGIC_NUM) { + PRT_HwiRestore(intSave); + return EINVAL; + } + + if (rwl->rw_count != 0) { + PRT_HwiRestore(intSave); + return EBUSY; + } + + (void)memset_s(rwl, sizeof(prt_pthread_rwlock_t), 0, sizeof(prt_pthread_rwlock_t)); + PRT_HwiRestore(intSave); + + return OS_OK; +} + +int pthread_rwlock_destroy(pthread_rwlock_t *rwl) +{ +#if defined(OS_POSIX_TYPE_NEWLIB) + prt_pthread_rwlock_t *rwlock = NULL; + prt_pthread_rwlock_t *ptr = &g_rwlist_head; + U32 ret; + + if (rwl == NULL) { + return EINVAL; + } + if (OsRwlockGetMagic(rwl) != RWLOCK_MAGIC_NUM) { + return EINVAL; + } + while (ptr != NULL) { + if (OsRwlockGetIndex(rwl) == ptr->index) { + rwlock = ptr; + break; + } + ptr = ptr->next; + } + + ret = PRT_PthreadRwlockDestroy(rwlock); + if (ret != OS_OK) { + return (int)ret; + } + OsRwlockSetIndex(rwl, 0); + OsRwlockSetMagic(rwl, 0); + ptr->next = rwlock->next; + rwlock->next = NULL; + + ret = PRT_MemFree(0, rwlock); + if (ret != OS_OK) { + OsErrRecord(ret); + } + return OS_OK; +#else + return PRT_PthreadRwlockDestroy((prt_pthread_rwlock_t *)rwl); +#endif +} + +/* + * 阻塞获取读锁 + */ +int pthread_rwlock_rdlock(pthread_rwlock_t *rwl) +{ + prt_pthread_rwlock_t *rwlock = OsRwlock2InnerStruct(rwl); + + return (int)OsRwLockRdPend(rwlock, OS_WAIT_FOREVER, RWLOCK_RD); +} + +/* + * 非阻塞获取读锁 + */ +int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwl) +{ + prt_pthread_rwlock_t *rwlock = OsRwlock2InnerStruct(rwl); + + return (int)OsRwLockRdPend(rwlock, 0, RWLOCK_TRYRD); +} + +/* + * 带超时获取读锁 + */ +int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwl, const struct timespec *time) +{ + U32 ret; + U32 ticks; + prt_pthread_rwlock_t *rwlock = OsRwlock2InnerStruct(rwl); + + if (time == NULL) { + return EINVAL; + } + + ret = OsTimeOut2Ticks(time, &ticks); + if (ret != OS_OK) { + return (int)ret; + } + + return (int)OsRwLockRdPend(rwlock, ticks, RWLOCK_TIMERD); +} + +/* + * 阻塞获取写锁 + */ +int pthread_rwlock_wrlock(pthread_rwlock_t *rwl) +{ + prt_pthread_rwlock_t *rwlock = OsRwlock2InnerStruct(rwl); + + return (int)OsRwLockWrPend(rwlock, OS_WAIT_FOREVER, RWLOCK_WR); +} + +/* + * 非阻塞获取写锁 + */ +int pthread_rwlock_trywrlock(pthread_rwlock_t *rwl) +{ + prt_pthread_rwlock_t *rwlock = OsRwlock2InnerStruct(rwl); + + return (int)OsRwLockWrPend(rwlock, 0, RWLOCK_TRYWR); +} + +/* + * 带超时获取写锁 + */ +int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwl, const struct timespec *time) +{ + U32 ret; + U32 ticks; + prt_pthread_rwlock_t *rwlock = OsRwlock2InnerStruct(rwl); + + if (time == NULL) { + return EINVAL; + } + + ret = OsTimeOut2Ticks(time, &ticks); + if (ret != OS_OK) { + return (int)ret; + } + + return (int)OsRwLockWrPend(rwlock, ticks, RWLOCK_TIMEWR); +} + +/* + * 读写锁解锁 + */ +int pthread_rwlock_unlock(pthread_rwlock_t *rwl) +{ + U32 ret; + U32 intSave; + bool needSched = FALSE; + prt_pthread_rwlock_t *rwlock = OsRwlock2InnerStruct(rwl); + + intSave = PRT_HwiLock(); + ret = OsRwLockUnlock(rwlock, &needSched); + if (ret != OS_OK) { + PRT_HwiRestore(intSave); + return (int)ret; + } + + PRT_HwiRestore(intSave); + if (needSched == TRUE) { + OsTskSchedule(); + } + + return (int)ret; +} + +/* + * 读写锁属性销毁 + */ +int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr) +{ + (void)attr; + + return OS_OK; +} + +/* + * 读写锁属性初始化 + */ +int pthread_rwlockattr_init(pthread_rwlockattr_t *attr) +{ + (void)attr; + + return OS_OK; +} + diff --git a/src/osal/posix/prt_pthread_sched.c b/src/osal/posix/prt_pthread_sched.c new file mode 100644 index 0000000..f79320a --- /dev/null +++ b/src/osal/posix/prt_pthread_sched.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * UniProton is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * Create: 2022-11-15 + * Description: pthread sched功能实现 + */ + +#include "pthread.h" +#include "sched.h" +#include "prt_posix_internal.h" + +int sched_get_priority_max(int policy) +{ + if (policy < 0) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + errno = OS_OK; + + return OS_TSK_PRIORITY_HIGHEST; +} + +int sched_get_priority_min(int policy) +{ + if (policy < 0) { + errno = EINVAL; + return PTHREAD_OP_FAIL; + } + errno = OS_OK; + + return OS_TSK_PRIORITY_LOWEST - 1; +} + +int sched_yield(void) +{ + (void)PRT_TaskDelay(0); + + return OS_OK; +} + +int pthread_setschedprio(pthread_t thread, int prio) +{ + U32 ret; + + /* task 优先级范围 0 <= priority < OS_TSK_PRIORITY_LOWEST */ + if (prio < OS_TSK_PRIORITY_HIGHEST || prio >= OS_TSK_PRIORITY_LOWEST) { + return ENOTSUP; + } + + ret = PRT_TaskSetPriority((TskHandle)thread, (TskPrior)prio); + if (ret != OS_OK) { + return EINVAL; + } + + return OS_OK; +} diff --git a/src/security/rnd/CMakeLists.txt b/src/security/rnd/CMakeLists.txt index 5f18d0d..d8eabb9 100644 --- a/src/security/rnd/CMakeLists.txt +++ b/src/security/rnd/CMakeLists.txt @@ -1,2 +1,2 @@ -add_library(prt_rnd_set OBJECT prt_rnd_set.c) +add_library_ex(prt_rnd_set.c) diff --git a/src/utility/lib/CMakeLists.txt b/src/utility/lib/CMakeLists.txt index c7958ac..05ff482 100644 --- a/src/utility/lib/CMakeLists.txt +++ b/src/utility/lib/CMakeLists.txt @@ -1,3 +1,3 @@ include_directories(./include) -add_library(prt_lib_math64 OBJECT prt_lib_math64.c) -add_library(prt_lib_version OBJECT prt_lib_version.c) +add_library_ex(prt_lib_math64.c) +add_library_ex(prt_lib_version.c)