更新rtt成功

This commit is contained in:
dgjames 2025-03-14 11:04:51 +08:00
parent 3847fcb4e0
commit c431b61900
731 changed files with 77517 additions and 9955 deletions

152
.config
View File

@ -4,10 +4,126 @@ CONFIG_BOARD_STM32F407_SPARK=y
#
# RT-Thread Kernel
#
#
# klibc options
#
#
# rt_vsnprintf options
#
# CONFIG_RT_KLIBC_USING_LIBC_VSNPRINTF is not set
CONFIG_RT_KLIBC_USING_VSNPRINTF_LONGLONG=y
CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD=y
CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS=y
CONFIG_RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS=y
CONFIG_RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER=y
CONFIG_RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER=y
# CONFIG_RT_KLIBC_USING_VSNPRINTF_MSVC_STYLE_INTEGER_SPECIFIERS is not set
CONFIG_RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE=32
CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE=32
CONFIG_RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION=6
CONFIG_RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL=9
CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4
# end of rt_vsnprintf options
#
# rt_vsscanf options
#
# CONFIG_RT_KLIBC_USING_LIBC_VSSCANF is not set
# end of rt_vsscanf options
#
# rt_memset options
#
# CONFIG_RT_KLIBC_USING_USER_MEMSET is not set
# CONFIG_RT_KLIBC_USING_LIBC_MEMSET is not set
# CONFIG_RT_KLIBC_USING_TINY_MEMSET is not set
# end of rt_memset options
#
# rt_memcpy options
#
# CONFIG_RT_KLIBC_USING_USER_MEMCPY is not set
# CONFIG_RT_KLIBC_USING_LIBC_MEMCPY is not set
# CONFIG_RT_KLIBC_USING_TINY_MEMCPY is not set
# end of rt_memcpy options
#
# rt_memmove options
#
# CONFIG_RT_KLIBC_USING_USER_MEMMOVE is not set
# CONFIG_RT_KLIBC_USING_LIBC_MEMMOVE is not set
# end of rt_memmove options
#
# rt_memcmp options
#
# CONFIG_RT_KLIBC_USING_USER_MEMCMP is not set
# CONFIG_RT_KLIBC_USING_LIBC_MEMCMP is not set
# end of rt_memcmp options
#
# rt_strstr options
#
# CONFIG_RT_KLIBC_USING_USER_STRSTR is not set
# CONFIG_RT_KLIBC_USING_LIBC_STRSTR is not set
# end of rt_strstr options
#
# rt_strcasecmp options
#
# CONFIG_RT_KLIBC_USING_USER_STRCASECMP is not set
# end of rt_strcasecmp options
#
# rt_strncpy options
#
# CONFIG_RT_KLIBC_USING_USER_STRNCPY is not set
# CONFIG_RT_KLIBC_USING_LIBC_STRNCPY is not set
# end of rt_strncpy options
#
# rt_strcpy options
#
# CONFIG_RT_KLIBC_USING_USER_STRCPY is not set
# CONFIG_RT_KLIBC_USING_LIBC_STRCPY is not set
# end of rt_strcpy options
#
# rt_strncmp options
#
# CONFIG_RT_KLIBC_USING_USER_STRNCMP is not set
# CONFIG_RT_KLIBC_USING_LIBC_STRNCMP is not set
# end of rt_strncmp options
#
# rt_strcmp options
#
# CONFIG_RT_KLIBC_USING_USER_STRCMP is not set
# CONFIG_RT_KLIBC_USING_LIBC_STRCMP is not set
# end of rt_strcmp options
#
# rt_strlen options
#
# CONFIG_RT_KLIBC_USING_USER_STRLEN is not set
# CONFIG_RT_KLIBC_USING_LIBC_STRLEN is not set
# end of rt_strlen options
#
# rt_strnlen options
#
# CONFIG_RT_KLIBC_USING_USER_STRNLEN is not set
# end of rt_strnlen options
# CONFIG_RT_UTEST_TC_USING_KLIBC is not set
# end of klibc options
CONFIG_RT_NAME_MAX=8
# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
# CONFIG_RT_USING_SMART is not set
# CONFIG_RT_USING_NANO is not set
# CONFIG_RT_USING_SMART is not set
# CONFIG_RT_USING_AMP is not set
# CONFIG_RT_USING_SMP is not set
CONFIG_RT_CPUS_NR=1
@ -17,6 +133,7 @@ CONFIG_RT_THREAD_PRIORITY_32=y
# CONFIG_RT_THREAD_PRIORITY_256 is not set
CONFIG_RT_THREAD_PRIORITY_MAX=32
CONFIG_RT_TICK_PER_SECOND=1000
CONFIG_RT_USING_OVERFLOW_CHECK=y
CONFIG_RT_USING_HOOK=y
CONFIG_RT_HOOK_USING_FUNC_PTR=y
# CONFIG_RT_USING_HOOKLIST is not set
@ -30,25 +147,17 @@ CONFIG_RT_TIMER_THREAD_STACK_SIZE=512
# CONFIG_RT_USING_CPU_USAGE_TRACER is not set
#
# kservice optimization
# kservice options
#
# CONFIG_RT_USING_TINY_FFS is not set
# end of kservice optimization
#
# klibc optimization
#
# CONFIG_RT_KLIBC_USING_STDLIB is not set
# CONFIG_RT_KLIBC_USING_TINY_SIZE is not set
# CONFIG_RT_KLIBC_USING_PRINTF_LONGLONG is not set
# end of klibc optimization
# end of kservice options
CONFIG_RT_USING_DEBUG=y
CONFIG_RT_DEBUGING_ASSERT=y
CONFIG_RT_DEBUGING_COLOR=y
CONFIG_RT_DEBUGING_CONTEXT=y
# CONFIG_RT_DEBUGING_AUTO_INIT is not set
CONFIG_RT_USING_OVERFLOW_CHECK=y
# CONFIG_RT_USING_CI_ACTION is not set
#
# Inter-Thread communication
@ -83,7 +192,6 @@ CONFIG_RT_USING_DEVICE=y
# CONFIG_RT_USING_DEVICE_OPS is not set
# CONFIG_RT_USING_INTERRUPT_INFO is not set
# CONFIG_RT_USING_THREADSAFE_PRINTF is not set
# CONFIG_RT_USING_SCHED_THREAD_CTX is not set
CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=128
CONFIG_RT_CONSOLE_DEVICE_NAME="uart1"
@ -172,8 +280,7 @@ CONFIG_RT_USING_DFS_ROMFS=y
# end of DFS: device virtual file system
CONFIG_RT_USING_FAL=y
CONFIG_FAL_DEBUG_CONFIG=y
CONFIG_FAL_DEBUG=1
CONFIG_FAL_USING_DEBUG=y
CONFIG_FAL_PART_HAS_TABLE_CFG=y
CONFIG_FAL_USING_SFUD_PORT=y
CONFIG_FAL_USING_NOR_FLASH_DEV_NAME="norflash0"
@ -193,6 +300,7 @@ CONFIG_RT_USING_SERIAL_V1=y
# CONFIG_RT_USING_SERIAL_V2 is not set
CONFIG_RT_SERIAL_USING_DMA=y
CONFIG_RT_SERIAL_RB_BUFSZ=64
# CONFIG_RT_USING_SERIAL_BYPASS is not set
# CONFIG_RT_USING_CAN is not set
# CONFIG_RT_USING_CPUTIME is not set
CONFIG_RT_USING_I2C=y
@ -201,6 +309,7 @@ CONFIG_RT_USING_I2C_BITOPS=y
# CONFIG_RT_I2C_BITOPS_DEBUG is not set
# CONFIG_RT_USING_SOFT_I2C is not set
# CONFIG_RT_USING_PHY is not set
# CONFIG_RT_USING_PHY_V2 is not set
CONFIG_RT_USING_ADC=y
# CONFIG_RT_USING_DAC is not set
# CONFIG_RT_USING_NULL is not set
@ -222,6 +331,7 @@ CONFIG_RT_MMCSD_STACK_SIZE=1024
CONFIG_RT_MMCSD_THREAD_PREORITY=22
CONFIG_RT_MMCSD_MAX_PARTITION=16
# CONFIG_RT_SDIO_DEBUG is not set
# CONFIG_RT_USING_SDHCI is not set
CONFIG_RT_USING_SPI=y
# CONFIG_RT_USING_SPI_BITOPS is not set
# CONFIG_RT_USING_QSPI is not set
@ -270,6 +380,15 @@ CONFIG_RT_WLAN_WORKQUEUE_THREAD_NAME="wlan"
CONFIG_RT_WLAN_WORKQUEUE_THREAD_SIZE=2048
CONFIG_RT_WLAN_WORKQUEUE_THREAD_PRIO=15
# CONFIG_RT_WLAN_DEBUG is not set
CONFIG_RT_USING_BLK=y
#
# Partition Types
#
CONFIG_RT_BLK_PARTITION_DFS=y
CONFIG_RT_BLK_PARTITION_EFI=y
# end of Partition Types
# CONFIG_RT_USING_VIRTIO is not set
CONFIG_RT_USING_PIN=y
# CONFIG_RT_USING_KTIME is not set
@ -355,6 +474,7 @@ CONFIG_NETDEV_USING_IFCONFIG=y
CONFIG_NETDEV_USING_PING=y
CONFIG_NETDEV_USING_NETSTAT=y
CONFIG_NETDEV_USING_AUTO_DEFAULT=y
# CONFIG_NETDEV_USING_LINK_STATUS_CALLBACK is not set
# CONFIG_NETDEV_USING_IPV6 is not set
CONFIG_NETDEV_IPV4=1
CONFIG_NETDEV_IPV6=0
@ -418,6 +538,7 @@ CONFIG_LWIP_NETIF_LOOPBACK=0
# CONFIG_RT_LWIP_USING_HW_CHECKSUM is not set
CONFIG_RT_LWIP_USING_PING=y
# CONFIG_LWIP_USING_DHCPD is not set
# CONFIG_RT_LWIP_ENABLE_USER_HOOKS is not set
# CONFIG_RT_LWIP_DEBUG is not set
CONFIG_RT_USING_AT=y
CONFIG_AT_DEBUG=y
@ -955,6 +1076,7 @@ CONFIG_PKG_PERF_COUNTER_PATH="/packages/system/perf_counter"
CONFIG_PKG_USING_PERF_COUNTER_V2241=y
# CONFIG_PKG_USING_PERF_COUNTER_LATEST_VERSION is not set
CONFIG_PKG_PERF_COUNTER_VER="v2.2.4.1"
CONFIG_FAL_DEBUG_CONFIG=y
# CONFIG_PKG_USING_FILEX is not set
# CONFIG_PKG_USING_LEVELX is not set
# CONFIG_PKG_USING_FLASHDB is not set

View File

@ -4,12 +4,379 @@
"name": "rt-thread",
"defines": [
"RT_USING_LIBC",
"RT_USING_NEWLIBC",
"STM32F407xx",
"USE_HAL_DRIVER",
"_POSIX_C_SOURCE=1",
"__RTTHREAD__",
"__perf_counter_printf__=rt_kprintf"
"__STDC_LIMIT_MACROS",
"__CLK_TCK=RT_TICK_PER_SECOND",
"STM32F407xx",
"RT_USING_ARMLIBC",
"__alignof__(x)=",
"__asm(x)=",
"__asm__(x)=",
"__forceinline=",
"__restrict=",
"__volatile__=",
"__inline=",
"__inline__=",
"__declspec(x)=",
"__attribute__(x)=",
"__nonnull__(x)=",
"__unaligned=",
"__promise(x)=",
"__irq=",
"__swi=",
"__weak=",
"__register=",
"__pure=",
"__value_in_regs=",
"__breakpoint(x)=",
"__current_pc()=0U",
"__current_sp()=0U",
"__disable_fiq()=",
"__disable_irq()=",
"__enable_fiq()=",
"__enable_irq()=",
"__force_stores()=",
"__memory_changed()=",
"__schedule_barrier()=",
"__semihost(x,y)=0",
"__vfp_status(x,y)=0",
"__builtin_arm_nop()=",
"__builtin_arm_wfi()=",
"__builtin_arm_wfe()=",
"__builtin_arm_sev()=",
"__builtin_arm_sevl()=",
"__builtin_arm_yield()=",
"__builtin_arm_isb(x)=",
"__builtin_arm_dsb(x)=",
"__builtin_arm_dmb(x)=",
"__builtin_bswap32(x)=0U",
"__builtin_bswap16(x)=0U",
"__builtin_arm_rbit(x)=0U",
"__builtin_clz(x)=0U",
"__builtin_arm_ldrex(x)=0U",
"__builtin_arm_strex(x,y)=0U",
"__builtin_arm_clrex()=",
"__builtin_arm_ssat(x,y)=0U",
"__builtin_arm_usat(x,y)=0U",
"__builtin_arm_ldaex(x)=0U",
"__builtin_arm_stlex(x,y)=0U",
"_ILP32=1",
"_USE_STATIC_INLINE=1",
"__APCS_32__=1",
"__ARMCC_VERSION=6070001",
"__ARMCOMPILER_VERSION=6070001",
"__ARMEL__=1",
"__ARM_32BIT_STATE=1",
"__ARM_ACLE=200",
"__ARM_ARCH=4",
"__ARM_ARCH_4T__=1",
"__ARM_ARCH_ISA_ARM=1",
"__ARM_ARCH_ISA_THUMB=1",
"__ARM_EABI__=1",
"__ARM_FP16_ARGS=1",
"__ARM_FP16_FORMAT_IEEE=1",
"__ARM_NO_IMAGINARY_TYPE=1",
"__ARM_PCS=1",
"__ARM_PROMISE=__builtin_assume",
"__ARM_SIZEOF_MINIMAL_ENUM=4",
"__ARM_SIZEOF_WCHAR_T=4",
"__ARM_TARGET_COPROC=1",
"__ARM_TARGET_COPROC_V4=1",
"__ATOMIC_ACQUIRE=2",
"__ATOMIC_ACQ_REL=4",
"__ATOMIC_CONSUME=1",
"__ATOMIC_RELAXED=0",
"__ATOMIC_RELEASE=3",
"__ATOMIC_SEQ_CST=5",
"__BIGGEST_ALIGNMENT__=8",
"__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__",
"__CHAR16_TYPE__=unsigned short",
"__CHAR32_TYPE__=unsigned int",
"__CHAR_BIT__=8",
"__CHAR_UNSIGNED__=1",
"__CONSTANT_CFSTRINGS__=1",
"__DBL_DECIMAL_DIG__=17",
"__DBL_DENORM_MIN__=4.9406564584124654e-324",
"__DBL_DIG__=15",
"__DBL_EPSILON__=2.2204460492503131e-16",
"__DBL_HAS_DENORM__=1",
"__DBL_HAS_INFINITY__=1",
"__DBL_HAS_QUIET_NAN__=1",
"__DBL_MANT_DIG__=53",
"__DBL_MAX_10_EXP__=308",
"__DBL_MAX_EXP__=1024",
"__DBL_MAX__=1.7976931348623157e+308",
"__DBL_MIN_10_EXP__=(-307)",
"__DBL_MIN_EXP__=(-1021)",
"__DBL_MIN__=2.2250738585072014e-308",
"__DECIMAL_DIG__=__LDBL_DECIMAL_DIG__",
"__ELF__=1",
"__ESCAPE__=",
"__FINITE_MATH_ONLY__=1",
"__FLT_DECIMAL_DIG__=9",
"__FLT_DENORM_MIN__=1.40129846e-45F",
"__FLT_DIG__=6",
"__FLT_EPSILON__=1.19209290e-7F",
"__FLT_EVAL_METHOD__=0",
"__FLT_HAS_DENORM__=1",
"__FLT_HAS_INFINITY__=1",
"__FLT_HAS_QUIET_NAN__=1",
"__FLT_MANT_DIG__=24",
"__FLT_MAX_10_EXP__=38",
"__FLT_MAX_EXP__=128",
"__FLT_MAX__=3.40282347e+38F",
"__FLT_MIN_10_EXP__=(-37)",
"__FLT_MIN_EXP__=(-125)",
"__FLT_MIN__=1.17549435e-38F",
"__FLT_RADIX__=2",
"__GCC_ATOMIC_BOOL_LOCK_FREE=1",
"__GCC_ATOMIC_CHAR16_T_LOCK_FREE=1",
"__GCC_ATOMIC_CHAR32_T_LOCK_FREE=1",
"__GCC_ATOMIC_CHAR_LOCK_FREE=1",
"__GCC_ATOMIC_INT_LOCK_FREE=1",
"__GCC_ATOMIC_LLONG_LOCK_FREE=1",
"__GCC_ATOMIC_LONG_LOCK_FREE=1",
"__GCC_ATOMIC_POINTER_LOCK_FREE=1",
"__GCC_ATOMIC_SHORT_LOCK_FREE=1",
"__GCC_ATOMIC_TEST_AND_SET_TRUEVAL=1",
"__GCC_ATOMIC_WCHAR_T_LOCK_FREE=1",
"__GNUC_MINOR__=2",
"__GNUC_PATCHLEVEL__=1",
"__GNUC_STDC_INLINE__=1",
"__GNUC__=4",
"__GXX_ABI_VERSION=1002",
"__ILP32__=1",
"__INT16_C_SUFFIX__=",
"__INT16_FMTd__=\"hd\"",
"__INT16_FMTi__=\"hi\"",
"__INT16_MAX__=32767",
"__INT16_TYPE__=short",
"__INT32_C_SUFFIX__=",
"__INT32_FMTd__=\"d\"",
"__INT32_FMTi__=\"i\"",
"__INT32_MAX__=2147483647",
"__INT32_TYPE__=int",
"__INT64_C_SUFFIX__=LL",
"__INT64_FMTd__=\"lld\"",
"__INT64_FMTi__=\"lli\"",
"__INT64_MAX__=9223372036854775807LL",
"__INT64_TYPE__=long long int",
"__INT8_C_SUFFIX__=",
"__INT8_FMTd__=\"hhd\"",
"__INT8_FMTi__=\"hhi\"",
"__INT8_MAX__=127",
"__INT8_TYPE__=signed char",
"__INTMAX_C_SUFFIX__=LL",
"__INTMAX_FMTd__=\"lld\"",
"__INTMAX_FMTi__=\"lli\"",
"__INTMAX_MAX__=9223372036854775807LL",
"__INTMAX_TYPE__=long long int",
"__INTMAX_WIDTH__=64",
"__INTPTR_FMTd__=\"ld\"",
"__INTPTR_FMTi__=\"li\"",
"__INTPTR_MAX__=2147483647L",
"__INTPTR_TYPE__=long int",
"__INTPTR_WIDTH__=32",
"__INT_FAST16_FMTd__=\"hd\"",
"__INT_FAST16_FMTi__=\"hi\"",
"__INT_FAST16_MAX__=32767",
"__INT_FAST16_TYPE__=short",
"__INT_FAST32_FMTd__=\"d\"",
"__INT_FAST32_FMTi__=\"i\"",
"__INT_FAST32_MAX__=2147483647",
"__INT_FAST32_TYPE__=int",
"__INT_FAST64_FMTd__=\"lld\"",
"__INT_FAST64_FMTi__=\"lli\"",
"__INT_FAST64_MAX__=9223372036854775807LL",
"__INT_FAST64_TYPE__=long long int",
"__INT_FAST8_FMTd__=\"hhd\"",
"__INT_FAST8_FMTi__=\"hhi\"",
"__INT_FAST8_MAX__=127",
"__INT_FAST8_TYPE__=signed char",
"__INT_LEAST16_FMTd__=\"hd\"",
"__INT_LEAST16_FMTi__=\"hi\"",
"__INT_LEAST16_MAX__=32767",
"__INT_LEAST16_TYPE__=short",
"__INT_LEAST32_FMTd__=\"d\"",
"__INT_LEAST32_FMTi__=\"i\"",
"__INT_LEAST32_MAX__=2147483647",
"__INT_LEAST32_TYPE__=int",
"__INT_LEAST64_FMTd__=\"lld\"",
"__INT_LEAST64_FMTi__=\"lli\"",
"__INT_LEAST64_MAX__=9223372036854775807LL",
"__INT_LEAST64_TYPE__=long long int",
"__INT_LEAST8_FMTd__=\"hhd\"",
"__INT_LEAST8_FMTi__=\"hhi\"",
"__INT_LEAST8_MAX__=127",
"__INT_LEAST8_TYPE__=signed char",
"__INT_MAX__=2147483647",
"__I__=1.0if",
"__LDBL_DECIMAL_DIG__=17",
"__LDBL_DENORM_MIN__=4.9406564584124654e-324L",
"__LDBL_DIG__=15",
"__LDBL_EPSILON__=2.2204460492503131e-16L",
"__LDBL_HAS_DENORM__=1",
"__LDBL_HAS_INFINITY__=1",
"__LDBL_HAS_QUIET_NAN__=1",
"__LDBL_MANT_DIG__=53",
"__LDBL_MAX_10_EXP__=308",
"__LDBL_MAX_EXP__=1024",
"__LDBL_MAX__=1.7976931348623157e+308L",
"__LDBL_MIN_10_EXP__=(-307)",
"__LDBL_MIN_EXP__=(-1021)",
"__LDBL_MIN__=2.2250738585072014e-308L",
"__LITTLE_ENDIAN__=1",
"__LONG_LONG_MAX__=9223372036854775807LL",
"__LONG_MAX__=2147483647L",
"__NO_INLINE__=1",
"__OBJC_BOOL_IS_BOOL=0",
"__ORDER_BIG_ENDIAN__=4321",
"__ORDER_LITTLE_ENDIAN__=1234",
"__ORDER_PDP_ENDIAN__=3412",
"__POINTER_WIDTH__=32",
"__PRAGMA_REDEFINE_EXTNAME=1",
"__PTRDIFF_FMTd__=\"d\"",
"__PTRDIFF_FMTi__=\"i\"",
"__PTRDIFF_MAX__=2147483647",
"__PTRDIFF_TYPE__=int",
"__PTRDIFF_WIDTH__=32",
"__REGISTER_PREFIX__=",
"__SCHAR_MAX__=127",
"__SHRT_MAX__=32767",
"__SIG_ATOMIC_MAX__=2147483647",
"__SIG_ATOMIC_WIDTH__=32",
"__SIZEOF_DOUBLE__=8",
"__SIZEOF_FLOAT__=4",
"__SIZEOF_INT__=4",
"__SIZEOF_LONG_DOUBLE__=8",
"__SIZEOF_LONG_LONG__=8",
"__SIZEOF_LONG__=4",
"__SIZEOF_POINTER__=4",
"__SIZEOF_PTRDIFF_T__=4",
"__SIZEOF_SHORT__=2",
"__SIZEOF_SIZE_T__=4",
"__SIZEOF_WCHAR_T__=4",
"__SIZEOF_WINT_T__=4",
"__SIZE_FMTX__=\"X\"",
"__SIZE_FMTo__=\"o\"",
"__SIZE_FMTu__=\"u\"",
"__SIZE_FMTx__=\"x\"",
"__SIZE_MAX__=4294967295U",
"__SIZE_TYPE__=unsigned int",
"__SIZE_WIDTH__=32",
"__STDC_HOSTED__=1",
"__STDC_UTF_16__=1",
"__STDC_UTF_32__=1",
"__STDC_VERSION__=201112L",
"__STDC__=1",
"__UINT16_C_SUFFIX__=",
"__UINT16_FMTX__=\"hX\"",
"__UINT16_FMTo__=\"ho\"",
"__UINT16_FMTu__=\"hu\"",
"__UINT16_FMTx__=\"hx\"",
"__UINT16_MAX__=65535",
"__UINT16_TYPE__=unsigned short",
"__UINT32_C_SUFFIX__=U",
"__UINT32_FMTX__=\"X\"",
"__UINT32_FMTo__=\"o\"",
"__UINT32_FMTu__=\"u\"",
"__UINT32_FMTx__=\"x\"",
"__UINT32_MAX__=4294967295U",
"__UINT32_TYPE__=unsigned int",
"__UINT64_C_SUFFIX__=ULL",
"__UINT64_FMTX__=\"llX\"",
"__UINT64_FMTo__=\"llo\"",
"__UINT64_FMTu__=\"llu\"",
"__UINT64_FMTx__=\"llx\"",
"__UINT64_MAX__=18446744073709551615ULL",
"__UINT64_TYPE__=long long unsigned int",
"__UINT8_C_SUFFIX__=",
"__UINT8_FMTX__=\"hhX\"",
"__UINT8_FMTo__=\"hho\"",
"__UINT8_FMTu__=\"hhu\"",
"__UINT8_FMTx__=\"hhx\"",
"__UINT8_MAX__=255",
"__UINT8_TYPE__=unsigned char",
"__UINTMAX_C_SUFFIX__=ULL",
"__UINTMAX_FMTX__=\"llX\"",
"__UINTMAX_FMTo__=\"llo\"",
"__UINTMAX_FMTu__=\"llu\"",
"__UINTMAX_FMTx__=\"llx\"",
"__UINTMAX_MAX__=18446744073709551615ULL",
"__UINTMAX_TYPE__=long long unsigned int",
"__UINTMAX_WIDTH__=64",
"__UINTPTR_FMTX__=\"lX\"",
"__UINTPTR_FMTo__=\"lo\"",
"__UINTPTR_FMTu__=\"lu\"",
"__UINTPTR_FMTx__=\"lx\"",
"__UINTPTR_MAX__=4294967295UL",
"__UINTPTR_TYPE__=long unsigned int",
"__UINTPTR_WIDTH__=32",
"__UINT_FAST16_FMTX__=\"hX\"",
"__UINT_FAST16_FMTo__=\"ho\"",
"__UINT_FAST16_FMTu__=\"hu\"",
"__UINT_FAST16_FMTx__=\"hx\"",
"__UINT_FAST16_MAX__=65535",
"__UINT_FAST16_TYPE__=unsigned short",
"__UINT_FAST32_FMTX__=\"X\"",
"__UINT_FAST32_FMTo__=\"o\"",
"__UINT_FAST32_FMTu__=\"u\"",
"__UINT_FAST32_FMTx__=\"x\"",
"__UINT_FAST32_MAX__=4294967295U",
"__UINT_FAST32_TYPE__=unsigned int",
"__UINT_FAST64_FMTX__=\"llX\"",
"__UINT_FAST64_FMTo__=\"llo\"",
"__UINT_FAST64_FMTu__=\"llu\"",
"__UINT_FAST64_FMTx__=\"llx\"",
"__UINT_FAST64_MAX__=18446744073709551615ULL",
"__UINT_FAST64_TYPE__=long long unsigned int",
"__UINT_FAST8_FMTX__=\"hhX\"",
"__UINT_FAST8_FMTo__=\"hho\"",
"__UINT_FAST8_FMTu__=\"hhu\"",
"__UINT_FAST8_FMTx__=\"hhx\"",
"__UINT_FAST8_MAX__=255",
"__UINT_FAST8_TYPE__=unsigned char",
"__UINT_LEAST16_FMTX__=\"hX\"",
"__UINT_LEAST16_FMTo__=\"ho\"",
"__UINT_LEAST16_FMTu__=\"hu\"",
"__UINT_LEAST16_FMTx__=\"hx\"",
"__UINT_LEAST16_MAX__=65535",
"__UINT_LEAST16_TYPE__=unsigned short",
"__UINT_LEAST32_FMTX__=\"X\"",
"__UINT_LEAST32_FMTo__=\"o\"",
"__UINT_LEAST32_FMTu__=\"u\"",
"__UINT_LEAST32_FMTx__=\"x\"",
"__UINT_LEAST32_MAX__=4294967295U",
"__UINT_LEAST32_TYPE__=unsigned int",
"__UINT_LEAST64_FMTX__=\"llX\"",
"__UINT_LEAST64_FMTo__=\"llo\"",
"__UINT_LEAST64_FMTu__=\"llu\"",
"__UINT_LEAST64_FMTx__=\"llx\"",
"__UINT_LEAST64_MAX__=18446744073709551615ULL",
"__UINT_LEAST64_TYPE__=long long unsigned int",
"__UINT_LEAST8_FMTX__=\"hhX\"",
"__UINT_LEAST8_FMTo__=\"hho\"",
"__UINT_LEAST8_FMTu__=\"hhu\"",
"__UINT_LEAST8_FMTx__=\"hhx\"",
"__UINT_LEAST8_MAX__=255",
"__UINT_LEAST8_TYPE__=unsigned char",
"__USER_LABEL_PREFIX__=",
"__VERSION__=\"4.2.1 Compatible Clang 5.0.0 \"",
"__WCHAR_MAX__=4294967295U",
"__WCHAR_TYPE__=unsigned int",
"__WCHAR_UNSIGNED__=1",
"__WCHAR_WIDTH__=32",
"__WINT_TYPE__=int",
"__WINT_WIDTH__=32",
"__arm=1",
"__arm__=1",
"__clang__=1",
"__clang_major__=5",
"__clang_minor__=0",
"__clang_patchlevel__=0",
"__clang_version__=\"5.0.0 \"",
"__llvm__=1"
],
"intelliSenseMode": "gcc-arm",
"compilerPath": "d:/DevTools/env2/tools/gnu_gcc/arm_gcc/mingw/bin/arm-none-eabi-gcc",
@ -19,78 +386,45 @@
"build/compile_commands.json"
],
"includePath": [
"packages\\aht10-latest\\inc",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\infra",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\mqtt\\impl",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\mqtt",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\client",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\server",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_sign",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\wrappers",
"packages\\ap3216c-latest",
"applications",
"my_pro",
"rt-thread\\components\\net\\at\\include",
"packages\\cJSON-v1.7.17",
"rt-thread\\components\\libc\\compilers\\common\\include",
"rt-thread\\components\\libc\\compilers\\newlib",
"rt-thread\\components\\libc\\cplusplus",
"rt-thread\\components\\drivers\\include",
"rt-thread\\components\\drivers\\spi",
"rt-thread\\components\\drivers\\spi\\sfud\\inc",
"rt-thread\\components\\drivers\\wlan",
"board",
"board\\CubeMX_Config\\Inc",
"board\\ports",
"board\\ports\\fal",
"board\\ports\\lcd",
"board\\ports\\led_matrix",
"libraries\\HAL_Drivers\\drivers",
"libraries\\HAL_Drivers\\drivers\\config",
"libraries\\HAL_Drivers\\drivers\\drv_flash",
"libraries\\HAL_Drivers",
"libraries\\HAL_Drivers\\CMSIS\\Include",
"rt-thread\\components\\fal\\inc",
"rt-thread\\components\\dfs\\dfs_v1\\include",
"rt-thread\\components\\dfs\\dfs_v1\\filesystems\\devfs",
"rt-thread\\components\\dfs\\dfs_v1\\filesystems\\elmfat",
"rt-thread\\components\\dfs\\dfs_v1\\filesystems\\romfs",
"rt-thread\\components\\finsh",
"packages\\FlexibleButton-v1.0.0",
"packages\\icm20608-latest",
"packages\\infrared-v0.1.1\\inc",
".",
"rt-thread\\include",
"packages\\kernel_samples-latest\\en",
"rt-thread\\components\\legacy",
"rt-thread\\components\\legacy\\dfs",
"rt-thread\\libcpu\\arm\\common",
"rt-thread\\libcpu\\arm\\cortex-m4",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Inc",
"libraries\\STM32F4xx_HAL\\CMSIS\\Device\\ST\\STM32F4xx\\Include",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\include",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\include\\ipv4",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\include\\netif",
"rt-thread\\components\\net\\lwip\\port",
"packages\\netutils-latest\\ntp",
"packages\\perf_counter-v2.2.4.1",
"rt-thread\\components\\libc\\posix\\io\\epoll",
"rt-thread\\components\\libc\\posix\\io\\eventfd",
"rt-thread\\components\\libc\\posix\\io\\poll",
"rt-thread\\components\\libc\\posix\\ipc",
"board\\ports\\rs485",
"rt-thread\\components\\legacy\\usb\\usbdevice",
"packages\\rw007-v2.1.0",
"packages\\rw007-v2.1.0\\inc",
"rt-thread\\components\\net\\netdev\\include",
"rt-thread\\components\\net\\sal\\include",
"rt-thread\\components\\net\\sal\\include\\socket",
"rt-thread\\components\\net\\sal\\impl",
"rt-thread\\components\\net\\sal\\include\\dfs_net",
"rt-thread\\components\\net\\sal\\include\\socket\\sys_socket",
"rt-thread\\components\\utilities\\ulog",
"packages\\vconsole-latest"
"d:\\components\\drivers\\include",
"d:\\Develop\\libraries\\HAL_Drivers\\drivers\\config",
"d:\\Develop\\libraries\\HAL_Drivers\\drivers",
"d:\\components\\libc\\posix\\io\\eventfd",
"d:\\Develop\\SumProject\\board",
"d:\\Develop\\SumProject\\board\\CubeMX_Config\\Inc",
"d:\\libcpu\\arm\\common",
"d:\\components\\libc\\posix\\ipc",
"d:\\Develop\\libraries\\HAL_Drivers\\CMSIS\\Include",
"d:\\Develop\\SumProject\\board\\ports",
"d:\\Develop\\libraries\\HAL_Drivers",
"d:\\components\\libc\\compilers\\common\\include",
"d:\\libcpu\\arm\\cortex-m4",
"d:\\components\\libc\\posix\\io\\poll",
"d:\\Develop\\SumProject",
"d:\\components\\libc\\posix\\io\\epoll",
"d:\\components\\finsh",
"d:\\Develop\\libraries\\STM32F4xx_HAL\\CMSIS\\Device\\ST\\STM32F4xx\\Include",
"d:\\Develop\\libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Inc",
"d:\\components\\libc\\compilers\\common\\extension",
"d:\\components\\libc\\compilers\\common\\extension\\fcntl\\octal",
"d:\\Develop\\SumProject\\applications",
"d:\\include",
"D:\\Keil5\\ARM\\ARMCLANG\\include",
"D:\\Keil5\\ARM\\ARMCLANG\\include\\libcxx",
"d:\\components\\libc\\compilers\\armlibc",
"d:\\components\\libc\\compilers\\common",
"d:\\components\\drivers\\core",
"d:\\components\\drivers\\i2c",
"d:\\components\\drivers\\ipc",
"d:\\components\\drivers\\misc",
"d:\\components\\drivers\\pin",
"d:\\components\\drivers\\serial",
"d:\\Develop\\libraries\\STM32F4xx_HAL\\CMSIS\\Device\\ST\\STM32F4xx\\Source\\Templates\\arm",
"d:\\Develop\\SumProject\\board\\CubeMX_Config\\Src",
"d:\\src",
"d:\\src\\klibc",
"d:\\Develop\\libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src",
"d:\\Develop\\libraries\\STM32F4xx_HAL\\CMSIS\\Device\\ST\\STM32F4xx\\Source\\Templates"
]
}
],

519
.vscode/project.json vendored Normal file
View File

@ -0,0 +1,519 @@
{
"RT-Thread": "D:\\Develop\\SumProject\\rt-thread",
"Groups": [
{
"name": "aht10",
"path": "packages\\aht10-latest",
"files": [
"packages\\aht10-latest\\src\\aht10.c",
"packages\\aht10-latest\\SConscript"
]
},
{
"name": "ali-iotkit",
"path": "packages\\ali-iotkit-v3.0.2",
"files": [
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\mqtt\\impl\\MQTTSerializePublish.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\infra\\infra_compat.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\dm_ota.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\dm_fota.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\dm_ipc.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\infra\\infra_log.c",
"packages\\ali-iotkit-v3.0.2\\ports\\rtthread\\HAL_TCP_rtthread.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\mqtt\\impl\\MQTTDeserializePublish.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_sign\\dev_sign_mqtt.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\infra\\infra_prt_nwk_payload.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\mqtt\\impl\\MQTTConnectClient.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\iotx_cm.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\client\\dm_client.c",
"packages\\ali-iotkit-v3.0.2\\ports\\wrapper.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\dm_log_report.c",
"packages\\ali-iotkit-v3.0.2\\ports\\rtthread\\HAL_UDP_rtthread.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\impl_linkkit.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\mqtt\\impl\\MQTTPacket.c",
"packages\\ali-iotkit-v3.0.2\\ports\\rtthread\\HAL_OS_rtthread.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\infra\\infra_report.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\dm_message_cache.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\mqtt\\impl\\iotx_mqtt_client.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\infra\\infra_cjson.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\mqtt\\mqtt_api.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\infra\\infra_net.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\dm_manager.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\mqtt\\impl\\MQTTSubscribeClient.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\infra\\infra_defs.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\infra\\infra_string.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\dm_cota.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\dm_opt.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\iotx_cm_mqtt.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\client\\dm_client_adapter.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\dm_message.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\dm_utils.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\dm_api.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\infra\\infra_timer.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\dev_model\\dm_msg_process.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\mqtt\\impl\\MQTTUnsubscribeClient.c",
"packages\\ali-iotkit-v3.0.2\\iotkit-embedded\\src\\infra\\infra_sha256.c",
"packages\\ali-iotkit-v3.0.2\\SConscript"
]
},
{
"name": "ap3216c",
"path": "packages\\ap3216c-latest",
"files": [
"packages\\ap3216c-latest\\ap3216c.c",
"packages\\ap3216c-latest\\SConscript"
]
},
{
"name": "Applications",
"path": "applications",
"files": [
"applications\\app_lcd.c",
"applications\\init.c",
"applications\\main.c",
"applications\\sim.c",
"my_pro\\AHT10.c",
"my_pro\\icm_20608_sample.c",
"my_pro\\indicator_led.c",
"my_pro\\my_func.c",
"my_pro\\myinfrared.c",
"my_pro\\myproject.c",
"my_pro\\mysnake.c",
"my_pro\\mytest.c",
"my_pro\\pin_irq_example.c",
"my_pro\\test_drv_example.c",
"applications\\SConscript"
]
},
{
"name": "AT",
"path": "rt-thread\\components\\net\\at",
"files": [
"rt-thread\\components\\net\\at\\src\\at_cli.c",
"rt-thread\\components\\net\\at\\src\\at_client.c",
"rt-thread\\components\\net\\at\\src\\at_utils.c",
"rt-thread\\components\\net\\at\\SConscript"
]
},
{
"name": "cJSON",
"path": "packages\\cJSON-v1.7.17",
"files": [
"packages\\cJSON-v1.7.17\\cJSON_Utils.c",
"packages\\cJSON-v1.7.17\\cJSON.c",
"packages\\cJSON-v1.7.17\\SConscript"
]
},
{
"name": "Compiler",
"path": "rt-thread\\components\\libc\\compilers\\common",
"files": [
"rt-thread\\components\\libc\\compilers\\common\\cctype.c",
"rt-thread\\components\\libc\\compilers\\common\\cstdlib.c",
"rt-thread\\components\\libc\\compilers\\common\\cstring.c",
"rt-thread\\components\\libc\\compilers\\common\\ctime.c",
"rt-thread\\components\\libc\\compilers\\common\\cunistd.c",
"rt-thread\\components\\libc\\compilers\\common\\cwchar.c",
"rt-thread\\components\\libc\\compilers\\newlib\\syscalls.c",
"rt-thread\\components\\libc\\compilers\\common\\SConscript"
]
},
{
"name": "CPP",
"path": "rt-thread\\components\\libc\\cplusplus",
"files": [
"rt-thread\\components\\libc\\cplusplus\\cxx_crt_init.c",
"rt-thread\\components\\libc\\cplusplus\\cxx_crt.cpp",
"rt-thread\\components\\libc\\cplusplus\\SConscript"
]
},
{
"name": "DeviceDrivers",
"path": "rt-thread\\components\\drivers\\block",
"files": [
"rt-thread\\components\\drivers\\block\\blk.c",
"rt-thread\\components\\drivers\\block\\blk_dev.c",
"rt-thread\\components\\drivers\\block\\blk_dfs.c",
"rt-thread\\components\\drivers\\block\\blk_partition.c",
"rt-thread\\components\\drivers\\block\\partitions\\dfs.c",
"rt-thread\\components\\drivers\\block\\partitions\\efi.c",
"rt-thread\\components\\drivers\\core\\device.c",
"rt-thread\\components\\drivers\\hwtimer\\hwtimer.c",
"rt-thread\\components\\drivers\\i2c\\dev_i2c_bit_ops.c",
"rt-thread\\components\\drivers\\i2c\\dev_i2c_core.c",
"rt-thread\\components\\drivers\\i2c\\dev_i2c_dev.c",
"rt-thread\\components\\drivers\\ipc\\completion_comm.c",
"rt-thread\\components\\drivers\\ipc\\completion_up.c",
"rt-thread\\components\\drivers\\ipc\\condvar.c",
"rt-thread\\components\\drivers\\ipc\\dataqueue.c",
"rt-thread\\components\\drivers\\ipc\\pipe.c",
"rt-thread\\components\\drivers\\ipc\\ringblk_buf.c",
"rt-thread\\components\\drivers\\ipc\\ringbuffer.c",
"rt-thread\\components\\drivers\\ipc\\waitqueue.c",
"rt-thread\\components\\drivers\\ipc\\workqueue.c",
"rt-thread\\components\\drivers\\misc\\adc.c",
"rt-thread\\components\\drivers\\misc\\rt_drv_pwm.c",
"rt-thread\\components\\drivers\\pin\\dev_pin.c",
"rt-thread\\components\\drivers\\rtc\\dev_rtc.c",
"rt-thread\\components\\drivers\\rtc\\dev_soft_rtc.c",
"rt-thread\\components\\drivers\\sdio\\dev_block.c",
"rt-thread\\components\\drivers\\sdio\\dev_mmc.c",
"rt-thread\\components\\drivers\\sdio\\dev_mmcsd_core.c",
"rt-thread\\components\\drivers\\sdio\\dev_sd.c",
"rt-thread\\components\\drivers\\sdio\\dev_sdio.c",
"rt-thread\\components\\drivers\\sensor\\v1\\sensor.c",
"rt-thread\\components\\drivers\\sensor\\v1\\sensor_cmd.c",
"rt-thread\\components\\drivers\\serial\\dev_serial.c",
"rt-thread\\components\\drivers\\spi\\dev_spi.c",
"rt-thread\\components\\drivers\\spi\\dev_spi_core.c",
"rt-thread\\components\\drivers\\spi\\dev_spi_flash_sfud.c",
"rt-thread\\components\\drivers\\spi\\sfud\\src\\sfud.c",
"rt-thread\\components\\drivers\\spi\\sfud\\src\\sfud_sfdp.c",
"rt-thread\\components\\drivers\\wlan\\dev_wlan.c",
"rt-thread\\components\\drivers\\wlan\\dev_wlan_cfg.c",
"rt-thread\\components\\drivers\\wlan\\dev_wlan_cmd.c",
"rt-thread\\components\\drivers\\wlan\\dev_wlan_lwip.c",
"rt-thread\\components\\drivers\\wlan\\dev_wlan_mgnt.c",
"rt-thread\\components\\drivers\\wlan\\dev_wlan_prot.c",
"rt-thread\\components\\drivers\\wlan\\dev_wlan_workqueue.c",
"rt-thread\\components\\drivers\\block\\SConscript"
]
},
{
"name": "Drivers",
"path": "board",
"files": [
"board\\CubeMX_Config\\Src\\stm32f4xx_hal_msp.c",
"board\\board.c",
"board\\ports\\drv_filesystem.c",
"board\\ports\\fal\\fal_spi_flash_sfud_port.c",
"board\\ports\\lcd\\drv_lcd.c",
"board\\ports\\led_matrix\\drv_matrix_led.c",
"board\\ports\\spi_flash_init.c",
"board\\startup_stm32f407xx.s",
"libraries\\HAL_Drivers\\drivers\\drv_adc.c",
"libraries\\HAL_Drivers\\drivers\\drv_flash\\drv_flash_f4.c",
"libraries\\HAL_Drivers\\drivers\\drv_gpio.c",
"libraries\\HAL_Drivers\\drivers\\drv_pwm.c",
"libraries\\HAL_Drivers\\drivers\\drv_sdio.c",
"libraries\\HAL_Drivers\\drivers\\drv_soft_i2c.c",
"libraries\\HAL_Drivers\\drivers\\drv_spi.c",
"libraries\\HAL_Drivers\\drivers\\drv_test.c",
"libraries\\HAL_Drivers\\drivers\\drv_tim.c",
"libraries\\HAL_Drivers\\drivers\\drv_usart.c",
"libraries\\HAL_Drivers\\drivers\\drv_usbd.c",
"libraries\\HAL_Drivers\\drv_common.c",
"board\\SConscript"
]
},
{
"name": "Fal",
"path": "rt-thread\\components\\fal",
"files": [
"rt-thread\\components\\fal\\src\\fal.c",
"rt-thread\\components\\fal\\src\\fal_partition.c",
"rt-thread\\components\\fal\\samples\\porting\\fal_flash_sfud_port.c",
"rt-thread\\components\\fal\\src\\fal_flash.c",
"rt-thread\\components\\fal\\src\\fal_rtt.c",
"rt-thread\\components\\fal\\SConscript"
]
},
{
"name": "Filesystem",
"path": "rt-thread\\components\\dfs\\dfs_v1",
"files": [
"rt-thread\\components\\dfs\\dfs_v1\\filesystems\\devfs\\devfs.c",
"rt-thread\\components\\dfs\\dfs_v1\\filesystems\\elmfat\\dfs_elm.c",
"rt-thread\\components\\dfs\\dfs_v1\\filesystems\\elmfat\\ff.c",
"rt-thread\\components\\dfs\\dfs_v1\\filesystems\\elmfat\\ffunicode.c",
"rt-thread\\components\\dfs\\dfs_v1\\filesystems\\romfs\\dfs_romfs.c",
"rt-thread\\components\\dfs\\dfs_v1\\src\\dfs.c",
"rt-thread\\components\\dfs\\dfs_v1\\src\\dfs_file.c",
"rt-thread\\components\\dfs\\dfs_v1\\src\\dfs_fs.c",
"rt-thread\\components\\dfs\\dfs_v1\\src\\dfs_posix.c",
"rt-thread\\components\\dfs\\dfs_v1\\SConscript"
]
},
{
"name": "Finsh",
"path": "rt-thread\\components\\finsh",
"files": [
"rt-thread\\components\\finsh\\msh_parse.c",
"rt-thread\\components\\finsh\\msh.c",
"rt-thread\\components\\finsh\\msh_file.c",
"rt-thread\\components\\finsh\\cmd.c",
"rt-thread\\components\\finsh\\shell.c",
"rt-thread\\components\\finsh\\SConscript"
]
},
{
"name": "flex_button",
"path": "packages\\FlexibleButton-v1.0.0",
"files": [
"packages\\FlexibleButton-v1.0.0\\flexible_button.c",
"packages\\FlexibleButton-v1.0.0\\SConscript"
]
},
{
"name": "icm20608",
"path": "packages\\icm20608-latest",
"files": [
"packages\\icm20608-latest\\icm20608.c",
"packages\\icm20608-latest\\SConscript"
]
},
{
"name": "Infrared_frame",
"path": "packages\\infrared-v0.1.1",
"files": [
"packages\\infrared-v0.1.1\\src\\drv_infrared.c",
"packages\\infrared-v0.1.1\\src\\infrared.c",
"packages\\infrared-v0.1.1\\src\\nec_decoder.c",
"packages\\infrared-v0.1.1\\SConscript"
]
},
{
"name": "Kernel",
"path": ".",
"files": [
"rt-thread\\src\\clock.c",
"rt-thread\\src\\components.c",
"rt-thread\\src\\cpu_up.c",
"rt-thread\\src\\defunct.c",
"rt-thread\\src\\idle.c",
"rt-thread\\src\\ipc.c",
"rt-thread\\src\\irq.c",
"rt-thread\\src\\kservice.c",
"rt-thread\\src\\mem.c",
"rt-thread\\src\\mempool.c",
"rt-thread\\src\\object.c",
"rt-thread\\src\\scheduler_comm.c",
"rt-thread\\src\\scheduler_up.c",
"rt-thread\\src\\thread.c",
"rt-thread\\src\\timer.c",
".\\SConscript"
]
},
{
"name": "kernel-samples",
"path": "packages\\kernel_samples-latest\\en",
"files": [
"packages\\kernel_samples-latest\\en\\semaphore_sample.c",
"packages\\kernel_samples-latest\\en\\mailbox_sample.c",
"packages\\kernel_samples-latest\\en\\msgq_sample.c",
"packages\\kernel_samples-latest\\en\\thread_sample.c",
"packages\\kernel_samples-latest\\en\\event_sample.c",
"packages\\kernel_samples-latest\\en\\mutex_sample.c",
"packages\\kernel_samples-latest\\en\\SConscript"
]
},
{
"name": "klibc",
"path": "rt-thread\\src\\klibc",
"files": [
"rt-thread\\src\\klibc\\rt_vsscanf.c",
"rt-thread\\src\\klibc\\rt_vsnprintf_std.c",
"rt-thread\\src\\klibc\\kerrno.c",
"rt-thread\\src\\klibc\\kstdio.c",
"rt-thread\\src\\klibc\\kstring.c",
"rt-thread\\src\\klibc\\SConscript"
]
},
{
"name": "Legacy",
"path": "rt-thread\\components\\legacy",
"files": [
"rt-thread\\components\\legacy\\ipc\\workqueue_legacy.c",
"rt-thread\\components\\legacy\\SConscript"
]
},
{
"name": "libcpu",
"path": "rt-thread\\libcpu\\arm\\common",
"files": [
"rt-thread\\libcpu\\arm\\common\\atomic_arm.c",
"rt-thread\\libcpu\\arm\\common\\div0.c",
"rt-thread\\libcpu\\arm\\common\\showmem.c",
"rt-thread\\libcpu\\arm\\cortex-m4\\context_gcc.S",
"rt-thread\\libcpu\\arm\\cortex-m4\\cpuport.c",
"rt-thread\\libcpu\\arm\\common\\SConscript"
]
},
{
"name": "Libraries",
"path": "libraries\\STM32F4xx_HAL",
"files": [
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_ll_usb.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_ll_fmc.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_sram.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_ll_sdmmc.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_i2c.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_rcc.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_hcd.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_tim.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_usart.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_dma.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_adc.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_rtc_ex.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_i2c_ex.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_flash_ramfunc.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_gpio.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_dma_ex.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_rcc_ex.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_rtc.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_pccard.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_cec.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_crc.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_pwr.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_sd.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_pcd.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_flash_ex.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_cortex.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_ll_fsmc.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_flash.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_adc_ex.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_pwr_ex.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_pcd_ex.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_cryp_ex.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_uart.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_qspi.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_tim_ex.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_spi.c",
"libraries\\STM32F4xx_HAL\\CMSIS\\Device\\ST\\STM32F4xx\\Source\\Templates\\system_stm32f4xx.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_lptim.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_rng.c",
"libraries\\STM32F4xx_HAL\\STM32F4xx_HAL_Driver\\Src\\stm32f4xx_hal_cryp.c",
"libraries\\STM32F4xx_HAL\\SConscript"
]
},
{
"name": "lwIP",
"path": "rt-thread\\components\\net\\lwip\\lwip-2.0.3",
"files": [
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\api\\api_lib.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\api\\api_msg.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\api\\err.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\api\\netbuf.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\api\\netdb.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\api\\netifapi.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\api\\sockets.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\api\\tcpip.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\apps\\ping\\ping.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\def.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\dns.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\inet_chksum.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\init.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\ip.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\ipv4\\autoip.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\ipv4\\dhcp.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\ipv4\\etharp.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\ipv4\\icmp.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\ipv4\\igmp.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\ipv4\\ip4.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\ipv4\\ip4_addr.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\ipv4\\ip4_frag.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\memp.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\netif.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\pbuf.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\raw.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\stats.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\sys.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\tcp.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\tcp_in.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\tcp_out.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\timeouts.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\core\\udp.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\netif\\ethernet.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\src\\netif\\lowpan6.c",
"rt-thread\\components\\net\\lwip\\port\\ethernetif.c",
"rt-thread\\components\\net\\lwip\\port\\sys_arch.c",
"rt-thread\\components\\net\\lwip\\lwip-2.0.3\\SConscript"
]
},
{
"name": "NetUtils",
"path": "packages\\netutils-latest\\ntp",
"files": [
"packages\\netutils-latest\\ntp\\ntp.c",
"packages\\netutils-latest\\ntp\\SConscript"
]
},
{
"name": "perf_counter",
"path": "packages\\perf_counter-v2.2.4.1",
"files": [
"packages\\perf_counter-v2.2.4.1\\os\\perf_os_patch_rt_thread.c",
"packages\\perf_counter-v2.2.4.1\\perf_counter.c",
"packages\\perf_counter-v2.2.4.1\\SConscript"
]
},
{
"name": "POSIX",
"path": "rt-thread\\components\\libc\\posix\\io\\epoll",
"files": [
"rt-thread\\components\\libc\\posix\\io\\poll\\poll.c",
"rt-thread\\components\\libc\\posix\\io\\poll\\select.c",
"rt-thread\\components\\libc\\posix\\io\\epoll\\SConscript"
]
},
{
"name": "RS485_port",
"path": "board\\ports\\rs485",
"files": [
"board\\ports\\rs485\\drv_rs485.c",
"board\\ports\\rs485\\SConscript"
]
},
{
"name": "rt_usbd",
"path": "rt-thread\\components\\legacy\\usb\\usbdevice",
"files": [
"rt-thread\\components\\legacy\\usb\\usbdevice\\core\\usbdevice.c",
"rt-thread\\components\\legacy\\usb\\usbdevice\\class\\cdc_vcom.c",
"rt-thread\\components\\legacy\\usb\\usbdevice\\core\\usbdevice_core.c",
"rt-thread\\components\\legacy\\usb\\usbdevice\\SConscript"
]
},
{
"name": "rw007",
"path": "packages\\rw007-v2.1.0",
"files": [
"packages\\rw007-v2.1.0\\src\\spi_wifi_rw007.c",
"packages\\rw007-v2.1.0\\example\\rw007_stm32_port.c",
"packages\\rw007-v2.1.0\\SConscript"
]
},
{
"name": "SAL",
"path": "rt-thread\\components\\net\\netdev",
"files": [
"rt-thread\\components\\net\\netdev\\src\\netdev.c",
"rt-thread\\components\\net\\netdev\\src\\netdev_ipaddr.c",
"rt-thread\\components\\net\\sal\\dfs_net\\dfs_net.c",
"rt-thread\\components\\net\\sal\\impl\\af_inet_lwip.c",
"rt-thread\\components\\net\\sal\\socket\\net_netdb.c",
"rt-thread\\components\\net\\sal\\socket\\net_sockets.c",
"rt-thread\\components\\net\\sal\\src\\sal_socket.c",
"rt-thread\\components\\net\\netdev\\SConscript"
]
},
{
"name": "Utilities",
"path": "rt-thread\\components\\utilities\\ulog",
"files": [
"rt-thread\\components\\utilities\\ulog\\backend\\console_be.c",
"rt-thread\\components\\utilities\\ulog\\ulog.c",
"rt-thread\\components\\utilities\\ulog\\SConscript"
]
},
{
"name": "vconsole",
"path": "packages\\vconsole-latest",
"files": [
"packages\\vconsole-latest\\vconsole.c",
"packages\\vconsole-latest\\SConscript"
]
}
]
}

View File

@ -1,9 +1,9 @@
#include "sim.h"
#include <rtthread.h>
#include <rthw.h>
#include <wlan_mgnt.h>
#include <wlan_cfg.h>
#include <wlan_prot.h>
#include <dev_wlan_mgnt.h>
#include <dev_wlan_cfg.h>
#include <dev_wlan_prot.h>
#include <ap3216c.h>
#include "my_func.h"

View File

@ -12,7 +12,7 @@
#include <sfud.h>
#ifdef RT_USING_SFUD
#include <spi_flash_sfud.h>
#include <dev_spi_flash_sfud.h>
#endif
static int init(void);

View File

@ -9,8 +9,8 @@
*/
#include <rtthread.h>
#include "spi_flash.h"
#include "spi_flash_sfud.h"
#include "dev_spi_flash.h"
#include "dev_spi_flash_sfud.h"
#include <drv_spi.h>
#include <drv_gpio.h>

View File

@ -15,7 +15,7 @@
#ifdef BSP_USING_PWM
#include "drv_config.h"
#include "drv_tim.h"
#include <drivers/rt_drv_pwm.h>
#include <drivers/dev_pwm.h>
//#define DRV_DEBUG
#define LOG_TAG "drv.pwm"

View File

@ -17,8 +17,8 @@
#include <drv_common.h>
#include "drv_dma.h"
#include <string.h>
#include <drivers/mmcsd_core.h>
#include <drivers/sdio.h>
#include <drivers/dev_mmcsd_core.h>
#include <drivers/dev_sdio.h>
#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4)
#define SDCARD_INSTANCE_TYPE SDIO_TypeDef

View File

@ -11,7 +11,8 @@
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/RT-Thread/rt-thread?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![GitHub pull-requests](https://img.shields.io/github/issues-pr/RT-Thread/rt-thread.svg)](https://github.com/RT-Thread/rt-thread/pulls)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)](https://github.com/RT-Thread/rt-thread/pulls)
[![RT-Thread BSP Static Build Check](https://github.com/RT-Thread/rt-thread/actions/workflows/bsp_buildings.yml/badge.svg)](https://github.com/RT-Thread/rt-thread/actions/workflows/bsp_buildings.yml)
<a href="https://hellogithub.com/repository/5816fc3c1e714d109631ceb377538ca9" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=5816fc3c1e714d109631ceb377538ca9&claim_uid=kVCe5FXIMGAjJfy" alt="FeaturedHelloGitHub" style="width: 100px; height: 20px;" width="250" height="54" /></a>
# RT-Thread
RT-Thread was born in 2006, it is an open source, neutral, and community-based real-time operating system (RTOS).

View File

@ -162,20 +162,32 @@ endif
bool "Using devfs for device objects"
default y
config RT_USING_DFS_ROMFS
if RT_USING_DFS_V1
config RT_USING_DFS_ISO9660
bool "Using ISO9660 filesystem"
depends on RT_USING_MEMHEAP
default n
endif
menuconfig RT_USING_DFS_ROMFS
bool "Enable ReadOnly file system on flash"
default n
config RT_USING_DFS_ROMFS_USER_ROOT
bool "Use user's romfs root"
depends on RT_USING_DFS_ROMFS
default n
if RT_USING_DFS_ROMFS
config RT_USING_DFS_ROMFS_USER_ROOT
bool "Use user's romfs root"
depends on RT_USING_DFS_V1
default n
endif
if RT_USING_SMART
config RT_USING_DFS_PTYFS
bool "Using Pseudo-Teletype Filesystem (UNIX98 PTY)"
depends on RT_USING_DFS_DEVFS
default y
config RT_USING_DFS_PROCFS
bool "Enable proc file system"
default n
endif
config RT_USING_DFS_CROMFS

View File

@ -1,4 +1,6 @@
from building import *
from gcc import *
import rtconfig
import os
# The set of source files associated with this SConscript file.
@ -6,6 +8,7 @@ src = []
cwd = GetCurrentDir()
CPPPATH = [cwd + "/include"]
group = []
LOCAL_CFLAGS = ''
if GetDepend('RT_USING_DFS') and not GetDepend('RT_USING_DFS_V2'):
src = ['src/dfs.c', 'src/dfs_file.c', 'src/dfs_fs.c']
@ -13,7 +16,12 @@ if GetDepend('RT_USING_DFS') and not GetDepend('RT_USING_DFS_V2'):
if GetDepend('DFS_USING_POSIX'):
src += ['src/dfs_posix.c']
group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS'], CPPPATH = CPPPATH)
if rtconfig.PLATFORM in GetGCCLikePLATFORM():
LOCAL_CFLAGS += ' -std=c99'
elif rtconfig.PLATFORM in ['armcc']:
LOCAL_CFLAGS += ' --c99'
group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS'], CPPPATH = CPPPATH, LOCAL_CFLAGS = LOCAL_CFLAGS)
# search in the file system implementation
list = os.listdir(cwd)

View File

@ -0,0 +1,11 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS', 'RT_USING_DFS_ISO9660'], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,698 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtservice.h>
#define DBG_TAG "dfs.iso9660"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include "dfs_iso9660.h"
#include <dfs.h>
#include <dfs_fs.h>
#include <dfs_file.h>
#include <posix/string.h>
#include <drivers/misc.h>
#include <drivers/byteorder.h>
#include <sys/time.h>
#define ISO9660_FSTYPE_DIR 0040000
#define ISO9660_FSTYPE_REG 0100000
#define ISO9660_FSTYPE_SYMLINK 0120000
#define ISO9660_FSTYPE_MASK 0170000
#define ISO9660_BLKSZ 2048
#define ISO9660_VOLDESC_BOOT 0
#define ISO9660_VOLDESC_PRIMARY 1
#define ISO9660_VOLDESC_SUPP 2
#define ISO9660_VOLDESC_PART 3
#define ISO9660_VOLDESC_END 255
rt_packed(struct iso9660_voldesc
{
rt_uint8_t type;
rt_uint8_t magic[5];
rt_uint8_t version;
});
rt_packed(struct iso9660_date2
{
rt_uint8_t year;
rt_uint8_t month;
rt_uint8_t day;
rt_uint8_t hour;
rt_uint8_t minute;
rt_uint8_t second;
rt_uint8_t offset;
});
/* Directory entry */
rt_packed(struct iso9660_dir
{
rt_uint8_t len;
rt_uint8_t ext_sectors;
rt_le32_t first_sector;
rt_le32_t first_sector_be;
rt_le32_t size;
rt_le32_t size_be;
struct iso9660_date2 mtime;
#define FLAG_TYPE_PLAIN 0
#define FLAG_TYPE_DIR 2
#define FLAG_TYPE 3
#define FLAG_MORE_EXTENTS 0x80
rt_uint8_t flags;
rt_uint8_t file_unit_size;
rt_uint8_t interleave_gap_size;
rt_le16_t vol_seq_num;
rt_le16_t vol_seq_num_be;
#define MAX_NAMELEN 255
rt_uint8_t namelen;
char name[0];
});
rt_packed(struct iso9660_date
{
rt_uint8_t year[4];
rt_uint8_t month[2];
rt_uint8_t day[2];
rt_uint8_t hour[2];
rt_uint8_t minute[2];
rt_uint8_t second[2];
rt_uint8_t hundredth[2];
rt_uint8_t offset;
});
/* Common volume descriptor */
rt_packed(struct iso9660_common_voldesc
{
struct iso9660_voldesc voldesc;
rt_uint8_t sysname[33];
rt_uint8_t volname[32];
rt_uint8_t unused2[8];
rt_le32_t vol_space_size_le;
rt_le32_t vol_space_size_be;
rt_uint8_t escape[32];
rt_le16_t vol_set_size_le;
rt_le16_t vol_set_size_be;
rt_le16_t vol_seq_num_le;
rt_le16_t vol_seq_num_be;
rt_le16_t logical_block_size_le;
rt_le16_t logical_block_size_be;
rt_le32_t path_table_size;
rt_le32_t path_table_size_be;
rt_le32_t path_table;
rt_le32_t path_table_be;
rt_uint8_t unused3[8];
struct iso9660_dir rootdir;
rt_uint8_t unused4[624];
struct iso9660_date created;
struct iso9660_date modified;
rt_uint8_t unused5[0 /* 1201 */];
});
struct iso9660
{
struct rt_device *dev;
rt_uint8_t joliet;
rt_uint8_t swap[ISO9660_BLKSZ];
struct iso9660_common_voldesc primary, supp;
};
struct iso9660_fd
{
struct iso9660 *iso;
struct iso9660_dir dirent;
};
struct iso9660_iterate
{
struct iso9660_fd *fd;
int i, index, count;
struct dirent *dirp;
};
static void iso9660_convert_string(char *dest, rt_uint16_t *src, int len)
{
/* UTF16 to ASCII */
len >>= 1;
for (int i = 0; i < len; ++i)
{
rt_uint16_t utf16 = rt_be16_to_cpu(*src++);
if (utf16 < 0x80)
{
*dest++ = (rt_uint8_t)utf16;
}
else
{
*dest++ = '?';
}
}
*dest = '\0';
}
static void iso9660_convert_lower(char *dest, rt_uint8_t *src, int len)
{
for (int i = 0; i < len; ++i, ++src)
{
if (*src >= 'A' && *src <= 'Z')
{
*dest++ = *src - ('A' - 'a');
}
else
{
*dest++ = *src;
}
}
*dest = '\0';
}
static time_t iso9660_convert_unixtime(struct iso9660_date *date)
{
struct tm tm;
tm.tm_sec = (date->second[0] - '0') * 10 + (date->second[1] - '0');
tm.tm_min = (date->minute[0] - '0') * 10 + (date->minute[1] - '0');
tm.tm_hour = (date->hour[0] - '0') * 10 + (date->hour[1] - '0');
tm.tm_mday = (date->day[0] - '0') * 10 + (date->day[1] - '0');
tm.tm_mon = (date->month[0] - '0') * 10 + (date->month[1] - '0');
tm.tm_year = (date->year[0] - '0') * 1000 + (date->year[1] - '0') * 100 +
(date->year[2] - '0') * 10 + (date->year[3] - '0');
tm.tm_wday = 0;
return mktime(&tm);
}
static time_t iso9660_convert_unixtime2(struct iso9660_date2 *date)
{
struct tm tm;
tm.tm_sec = date->second;
tm.tm_min = date->minute;
tm.tm_hour = date->hour;
tm.tm_mday = date->day;
tm.tm_mon = date->month;
tm.tm_year = date->year + 1900;
tm.tm_wday = 0;
return mktime(&tm);
}
static struct iso9660_fd *iso9660_lookup(struct iso9660 *iso, const char *path,
struct iso9660_iterate *it)
{
rt_uint32_t lba;
rt_size_t sz, len, namelen;
char sname[MAX_NAMELEN];
struct iso9660_fd *fd;
struct iso9660_dir *dirent;
if (it)
{
fd = it->fd;
iso = fd->iso;
dirent = &fd->dirent;
/* No next entry, always goon */
len = 1;
}
else
{
if (!(fd = rt_malloc(sizeof(*fd))))
{
return fd;
}
fd->iso = iso;
dirent = iso->joliet ? &iso->supp.rootdir : &iso->primary.rootdir;
if (!rt_strcmp(path, "/"))
{
rt_memcpy(&fd->dirent, dirent, sizeof(*dirent));
return fd;
}
/* Skip the first '/' */
++path;
len = strchrnul(path, '/') - path;
}
lba = rt_le32_to_cpu(dirent->first_sector);
if (rt_device_read(iso->dev, lba, iso->swap, 1) <= 0)
{
goto _fail;
}
dirent = (void *)iso->swap;
sz = 0;
do {
/* Ignore "." and ".." */
do {
rt_uint32_t dlen = rt_le32_to_cpu(dirent->len);
dirent = (void *)dirent + dlen;
sz += dlen;
if (ISO9660_BLKSZ - sz < sizeof(*dirent))
{
/* Sector end, goto the next sector */
if (rt_device_read(iso->dev, ++lba, iso->swap, 1) <= 0)
{
goto _fail;
}
dirent = (void *)iso->swap;
sz = 0;
}
if (rt_le32_to_cpu(dirent->first_sector) == 0)
{
/* Is end, no found. */
goto _fail;
}
} while (dirent->name[0] >> 1 == 0 && rt_le32_to_cpu(dirent->namelen) == 1);
namelen = rt_le32_to_cpu(dirent->namelen);
if (iso->joliet)
{
iso9660_convert_string(sname, (rt_uint16_t *)dirent->name, namelen);
}
else
{
if (!(rt_le32_to_cpu(dirent->flags) & FLAG_TYPE_DIR))
{
/* Remove ";1" */
namelen -= 2;
}
iso9660_convert_lower(sname, (rt_uint8_t *)dirent->name, namelen);
}
if (it)
{
if (it->i < it->index)
{
goto _next;
}
if ((rt_le32_to_cpu(dirent->flags) & FLAG_TYPE) == FLAG_TYPE_DIR)
{
it->dirp->d_type = DT_DIR;
}
else
{
it->dirp->d_type = DT_REG;
}
it->dirp->d_namlen = namelen;
rt_strncpy(it->dirp->d_name, sname, namelen);
it->dirp->d_name[namelen] = '\0';
it->dirp->d_reclen = (rt_uint16_t)sizeof(struct dirent);
++it->dirp;
_next:
++it->i;
if (it->i - it->index >= it->count)
{
/* Iterate end */
return RT_NULL;
}
/* No next entry */
continue;
}
if (!rt_strncmp(sname, path, len))
{
/* The end of path, found ok */
if (!path[len])
{
rt_memcpy(&fd->dirent, dirent, sizeof(*dirent));
return fd;
}
/* Next entry */
lba = rt_le32_to_cpu(dirent->first_sector);
if (rt_device_read(iso->dev, lba, iso->swap, 1) <= 0)
{
goto _fail;
}
dirent = (void *)iso->swap;
sz = 0;
path += len + 1;
len = strchrnul(path, '/') - path;
}
} while (len);
_fail:
if (!it)
{
rt_free(fd);
}
return RT_NULL;
}
static int dfs_iso9660_open(struct dfs_file *fd)
{
struct iso9660 *iso = fd->vnode->fs->data;
fd->vnode->data = iso9660_lookup(iso, fd->vnode->path, RT_NULL);
return fd->vnode->data ? 0 : -EINVAL;
}
static int dfs_iso9660_close(struct dfs_file *fd)
{
struct iso9660_fd *iso_fd = fd->vnode->data;
rt_free(iso_fd);
return 0;
}
static int dfs_iso9660_read(struct dfs_file *fd, void *buf, size_t count)
{
rt_uint32_t pos;
void *buf_ptr;
ssize_t read_blk, toread_blk;
size_t rcount = 0, remain, size;
struct iso9660_fd *iso_fd = fd->vnode->data;
struct iso9660 *iso = iso_fd->iso;
if (fd->pos + count > rt_le32_to_cpu(iso_fd->dirent.size))
{
count = rt_le32_to_cpu(iso_fd->dirent.size) - fd->pos;
}
pos = rt_le32_to_cpu(iso_fd->dirent.first_sector);
/* Align to a sector */
if (fd->pos)
{
pos += fd->pos / ISO9660_BLKSZ;
remain = fd->pos & (ISO9660_BLKSZ - 1);
if (rt_device_read(iso->dev, pos, iso->swap, 1) <= 0)
{
return -EIO;
}
size = rt_min_t(size_t, ISO9660_BLKSZ - remain, count);
rt_memcpy(buf, &iso->swap[remain], size);
rcount += size;
count -= size;
buf += size;
pos += 1;
fd->pos += size;
if (!count)
{
goto _end;
}
}
remain = count & (ISO9660_BLKSZ - 1);
count = rt_max_t(size_t, count / ISO9660_BLKSZ, 1);
while ((ssize_t)count > 0)
{
if (count == 1)
{
buf_ptr = iso->swap;
toread_blk = 1;
}
else
{
buf_ptr = buf;
toread_blk = count;
}
read_blk = rt_device_read(iso->dev, pos, buf_ptr, toread_blk);
if (read_blk <= 0)
{
return (int)read_blk;
}
if (count == 1)
{
size = remain;
rt_memcpy(buf, iso->swap, size);
}
else
{
size = read_blk * ISO9660_BLKSZ;
}
rcount += size;
count -= read_blk;
buf += size;
pos += read_blk;
fd->pos += size;
}
_end:
return rcount;
}
static off_t dfs_iso9660_lseek(struct dfs_file *fd, off_t offset)
{
int ret = -EIO;
if (offset <= fd->vnode->size)
{
fd->pos = offset;
ret = fd->pos;
}
return ret;
}
static int dfs_iso9660_getdents(struct dfs_file *fd, struct dirent *dirp, uint32_t count)
{
struct iso9660_iterate it;
struct iso9660_fd *iso_fd = fd->vnode->data;
count = (count / sizeof(struct dirent));
if (!count)
{
return -EINVAL;
}
it.fd = iso_fd;
it.i = 0;
it.index = fd->pos;
it.count = count;
it.dirp = dirp;
iso9660_lookup(RT_NULL, RT_NULL, &it);
count = it.i - it.index;
if (count > 0)
{
fd->pos += count;
}
count *= sizeof(struct dirent);
return count;
}
static const struct dfs_file_ops _iso9660_fops =
{
.open = dfs_iso9660_open,
.close = dfs_iso9660_close,
.read = dfs_iso9660_read,
.lseek = dfs_iso9660_lseek,
.getdents = dfs_iso9660_getdents,
};
static int dfs_iso9660_mount(struct dfs_filesystem *fs,
unsigned long rwflag, const void *data)
{
int err;
struct iso9660 *iso;
struct iso9660_voldesc *voldesc;
struct rt_device_blk_geometry geometry;
if (!(iso = rt_malloc(sizeof(*iso))))
{
return -RT_ENOMEM;
}
iso->dev = fs->dev_id;
rt_device_control(iso->dev, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
if (geometry.bytes_per_sector != ISO9660_BLKSZ)
{
LOG_E("%s: Logical block size = %d is not supported",
iso->dev->parent.name, geometry.bytes_per_sector);
err = -EINVAL;
goto _fail;
}
iso->primary.rootdir.first_sector = 0;
iso->supp.rootdir.first_sector = 0;
/* LBA 0-15 is the bootloader's information */
for (int lba = 16; ; ++lba)
{
if (rt_device_read(iso->dev, lba, &iso->swap, 1) <= 0)
{
err = -EIO;
goto _fail;
}
voldesc = (void *)iso->swap;
if (rt_strncmp((char *)voldesc->magic, "CD001", 5))
{
LOG_E("%s: Invalid magic \"%s\"", voldesc->magic);
err = -EINVAL;
goto _fail;
}
if (voldesc->type == ISO9660_VOLDESC_BOOT)
{
LOG_D("System Name: %s", ((struct iso9660_common_voldesc *)voldesc)->sysname);
LOG_D("Volume Name: %s", ((struct iso9660_common_voldesc *)voldesc)->volname);
}
else if (voldesc->type == ISO9660_VOLDESC_PRIMARY)
{
iso->joliet = 0;
rt_memcpy(&iso->primary, &iso->swap, sizeof(iso->primary));
}
else if (voldesc->type == ISO9660_VOLDESC_SUPP)
{
rt_memcpy(&iso->supp, &iso->swap, sizeof(iso->supp));
if (iso->supp.escape[0] == 0x25 && iso->supp.escape[1] == 0x2f)
{
if (iso->supp.escape[2] == 0x40)
{
iso->joliet = 1;
}
else if (iso->supp.escape[2] == 0x43)
{
iso->joliet = 2;
}
else if (iso->supp.escape[2] == 0x45)
{
iso->joliet = 3;
}
else
{
continue;
}
}
}
else if (voldesc->type == ISO9660_VOLDESC_PART)
{
LOG_D("System Name: %s", ((struct iso9660_common_voldesc *)voldesc)->sysname);
LOG_D("Volume Name: %s", ((struct iso9660_common_voldesc *)voldesc)->volname);
}
else if (voldesc->type == ISO9660_VOLDESC_END)
{
break;
}
}
if (!iso->primary.rootdir.first_sector || !iso->supp.rootdir.first_sector)
{
LOG_E("No primary or secondary partition found");
err = -EINVAL;
goto _fail;
}
fs->data = iso;
return 0;
_fail:
rt_free(iso);
return err;
}
static int dfs_iso9660_unmount(struct dfs_filesystem *fs)
{
struct iso9660 *iso = fs->data;
rt_free(iso);
return 0;
}
static int dfs_iso9660_stat(struct dfs_filesystem *fs,
const char *filename, struct stat *st)
{
struct iso9660 *iso = fs->data;
struct iso9660_fd *fd = iso9660_lookup(iso, filename, RT_NULL);
if (!fd)
{
return -EINVAL;
}
st->st_dev = 0;
st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
S_IWUSR | S_IWGRP | S_IWOTH;
if ((fd->dirent.flags & FLAG_TYPE) == FLAG_TYPE_DIR)
{
st->st_mode &= ~S_IFREG;
st->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
}
st->st_atime = iso9660_convert_unixtime(iso->joliet ?
&iso->supp.created : &iso->primary.created);
st->st_mtime = iso9660_convert_unixtime2(&fd->dirent.mtime);
st->st_size = rt_le32_to_cpu(fd->dirent.size);
rt_free(fd);
return 0;
}
static const struct dfs_filesystem_ops _iso9660 =
{
.name = "iso9660",
.flags = DFS_FS_FLAG_DEFAULT,
.fops = &_iso9660_fops,
.mount = dfs_iso9660_mount,
.unmount = dfs_iso9660_unmount,
.stat = dfs_iso9660_stat,
};
int dfs_iso9660_init(void)
{
/* register iso9660 file system */
return dfs_register(&_iso9660);
}
INIT_COMPONENT_EXPORT(dfs_iso9660_init);

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI the first version
*/
#ifndef __DFS_ISO9660_H__
#define __DFS_ISO9660_H__
int dfs_iso9660_init(void);
#endif /* __DFS_ISO9660_H__ */

View File

@ -92,7 +92,7 @@ struct ramfs_dirent *dfs_ramfs_lookup(struct dfs_ramfs *ramfs,
return NULL;
}
int dfs_ramfs_read(struct dfs_file *file, void *buf, size_t count)
ssize_t dfs_ramfs_read(struct dfs_file *file, void *buf, size_t count)
{
rt_size_t length;
struct ramfs_dirent *dirent;
@ -114,7 +114,7 @@ int dfs_ramfs_read(struct dfs_file *file, void *buf, size_t count)
return length;
}
int dfs_ramfs_write(struct dfs_file *fd, const void *buf, size_t count)
ssize_t dfs_ramfs_write(struct dfs_file *fd, const void *buf, size_t count)
{
struct ramfs_dirent *dirent;
struct dfs_ramfs *ramfs;
@ -151,7 +151,7 @@ int dfs_ramfs_write(struct dfs_file *fd, const void *buf, size_t count)
return count;
}
int dfs_ramfs_lseek(struct dfs_file *file, off_t offset)
off_t dfs_ramfs_lseek(struct dfs_file *file, off_t offset)
{
if (offset <= (off_t)file->vnode->size)
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -107,7 +107,8 @@ int dfs_init(void)
INIT_PREV_EXPORT(dfs_init);
/**
* this function will lock device file system.
* @brief this function will lock device file system.
* this lock (fslock) is used for protecting filesystem_operation_table and filesystem_table.
*
* @note please don't invoke it on ISR.
*/
@ -126,6 +127,12 @@ void dfs_lock(void)
}
}
/**
* @brief this function will lock file descriptors.
* this lock (fdlock) is used for protecting fd table (_fdtab).
*
* @note please don't invoke it on ISR.
*/
void dfs_file_lock(void)
{
rt_err_t result = -RT_EBUSY;
@ -142,7 +149,7 @@ void dfs_file_lock(void)
}
/**
* this function will lock device file system.
* @brief this function will unlock device file system.
*
* @note please don't invoke it on ISR.
*/
@ -151,33 +158,56 @@ void dfs_unlock(void)
rt_mutex_release(&fslock);
}
#ifdef DFS_USING_POSIX
/**
* @brief this function will unlock fd table.
*/
void dfs_file_unlock(void)
{
rt_mutex_release(&fdlock);
}
#ifdef DFS_USING_POSIX
/**
* @brief Expand the file descriptor table to accommodate a specific file descriptor.
*
* This function ensures that the file descriptor table in the given `dfs_fdtable` structure
* has sufficient capacity to include the specified file descriptor `fd`. If the table
* needs to be expanded, it reallocates memory and initializes new slots to `NULL`.
*
* @param fdt Pointer to the `dfs_fdtable` structure representing the file descriptor table.
* @param fd The file descriptor that the table must accommodate.
* @return int
* - The input file descriptor `fd` if it is within the current or newly expanded table's capacity.
* - `-1` if the requested file descriptor exceeds `DFS_FD_MAX` or memory allocation fails.
*/
static int fd_slot_expand(struct dfs_fdtable *fdt, int fd)
{
int nr;
int index;
struct dfs_file **fds = NULL;
/* If the file descriptor is already within the current capacity, no expansion is needed.*/
if (fd < fdt->maxfd)
{
return fd;
}
/* If the file descriptor exceeds the maximum allowable limit, return an error.*/
if (fd >= DFS_FD_MAX)
{
return -1;
}
/* Calculate the new capacity, rounding up to the nearest multiple of 4.*/
nr = ((fd + 4) & ~3);
/* Ensure the new capacity does not exceed the maximum limit.*/
if (nr > DFS_FD_MAX)
{
nr = DFS_FD_MAX;
}
/* Attempt to reallocate the file descriptor table to the new capacity.*/
fds = (struct dfs_file **)rt_realloc(fdt->fds, nr * sizeof(struct dfs_file *));
if (!fds)
{
@ -189,12 +219,23 @@ static int fd_slot_expand(struct dfs_fdtable *fdt, int fd)
{
fds[index] = NULL;
}
/* Update the file descriptor table and its capacity.*/
fdt->fds = fds;
fdt->maxfd = nr;
return fd;
}
/**
* @brief Allocate a file descriptor slot starting from a specified index.
*
* @param fdt fdt Pointer to the `dfs_fdtable` structure representing the file descriptor table.
* @param startfd The starting index for the search for an empty slot.
* @return int
* - The index of the first available slot if successful.
* - `-1` if no slot is available or if table expansion fails
*/
static int fd_slot_alloc(struct dfs_fdtable *fdt, int startfd)
{
int idx;
@ -219,6 +260,17 @@ static int fd_slot_alloc(struct dfs_fdtable *fdt, int startfd)
}
return idx;
}
/**
* @brief Allocate a new file descriptor and associate it with a newly allocated `struct dfs_file`.
*
* @param fdt Pointer to the `dfs_fdtable` structure representing the file descriptor table.
* @param startfd The starting index for searching an available file descriptor slot.
*
* @return
* - The index of the allocated file descriptor if successful.
* - `-1` if no slot is available or memory allocation fails.
*/
static int fd_alloc(struct dfs_fdtable *fdt, int startfd)
{
int idx;
@ -323,7 +375,11 @@ struct dfs_file *fd_get(int fd)
/**
* @ingroup Fd
*
* This function will put the file descriptor.
* @brief This function will release the file descriptor.
*
* This function releases a file descriptor slot in the file descriptor table, decrements reference
* counts, and cleans up resources associated with the `dfs_file` and `dfs_vnode` structures when applicable.
*
*/
void fdt_fd_release(struct dfs_fdtable* fdt, int fd)
{
@ -378,6 +434,20 @@ void fd_release(int fd)
fdt_fd_release(fdt, fd);
}
/**
* @brief Duplicates a file descriptor.
*
* This function duplicates an existing file descriptor (`oldfd`) and returns
* a new file descriptor that refers to the same underlying file object.
*
* @param oldfd The file descriptor to duplicate. It must be a valid file
* descriptor within the range of allocated descriptors.
*
* @return The new file descriptor if successful, or a negative value
* (e.g., -1) if an error occurs.
*
* @see sys_dup2()
*/
rt_err_t sys_dup(int oldfd)
{
int newfd = -1;
@ -470,6 +540,23 @@ int fd_is_open(const char *pathname)
return -1;
}
/**
* @brief Duplicates a file descriptor to a specified file descriptor.
*
* This function duplicates an existing file descriptor (`oldfd`) and assigns it
* to the specified file descriptor (`newfd`).
*
* @param oldfd The file descriptor to duplicate. It must be a valid and open file
* descriptor within the range of allocated descriptors.
* @param newfd The target file descriptor. If `newfd` is already in use, it will
* be closed before duplication. If `newfd` exceeds the current file
* descriptor table size, the table will be expanded to accommodate it.
*
* @return The value of `newfd` on success, or a negative value (e.g., -1) if an
* error occurs.
*
* @see sys_dup()
*/
rt_err_t sys_dup2(int oldfd, int newfd)
{
struct dfs_fdtable *fdt = NULL;
@ -550,6 +637,10 @@ static int fd_get_fd_index_form_fdt(struct dfs_fdtable *fdt, struct dfs_file *fi
return fd;
}
/**
* @brief get fd (index) by dfs file object.
*
*/
int fd_get_fd_index(struct dfs_file *file)
{
struct dfs_fdtable *fdt;
@ -558,6 +649,21 @@ int fd_get_fd_index(struct dfs_file *file)
return fd_get_fd_index_form_fdt(fdt, file);
}
/**
* @brief Associates a file descriptor with a file object.
*
* This function associates a given file descriptor (`fd`) with a specified
* file object (`file`) in the file descriptor table (`fdt`).
*
* @param fdt The file descriptor table to operate on. It must be a valid
* and initialized `dfs_fdtable` structure.
* @param fd The file descriptor to associate. It must be within the range
* of allocated file descriptors and currently unoccupied.
* @param file The file object to associate with the file descriptor. It must
* be a valid and initialized `dfs_file` structure.
*
* @return The value of `fd` on success, or -1 if an error occurs.
*/
int fd_associate(struct dfs_fdtable *fdt, int fd, struct dfs_file *file)
{
int retfd = -1;
@ -591,6 +697,10 @@ exit:
return retfd;
}
/**
* @brief initialize a dfs file object.
*
*/
void fd_init(struct dfs_file *fd)
{
if (fd)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -18,10 +18,12 @@
#define DFS_VNODE_HASH_NR 128
/*dfs vnode manager, for saving and searching vnodes.*/
struct dfs_vnode_mgr
{
struct rt_mutex lock;
rt_list_t head[DFS_VNODE_HASH_NR];
struct rt_mutex lock; /* mutex for protecting dfs vnode lists */
rt_list_t head[DFS_VNODE_HASH_NR]; /* a group of dfs vnode lists, the dfs vnode is inserted to one of the lists
according to path string's hash-value mod DFS_VNODE_HASH_NR. */
};
static struct dfs_vnode_mgr dfs_fm;
@ -36,6 +38,10 @@ void dfs_fm_unlock(void)
rt_mutex_release(&dfs_fm.lock);
}
/**
* @brief Initialize dfs vnode manager structure, including a lock and hash tables for vnode.
*
*/
void dfs_vnode_mgr_init(void)
{
int i = 0;
@ -47,6 +53,23 @@ void dfs_vnode_mgr_init(void)
}
}
/**
* @brief Initialize a DFS vnode structure.
*
* @param vnode Pointer to the DFS vnode structure to be initialized.
* The caller must ensure this is a valid, allocated structure.
* @param type The type of the vnode, representing its role or category (e.g., regular file, directory).
* @param fops Pointer to the file operations structure associated with this vnode.
* This structure defines the behavior of the vnode for operations such as open, read, write, etc.
* If `fops` is NULL, the vnode will have no associated file operations.
*
* @return 0 on success, or a negative error code on failure.
*
* @note The caller should ensure that:
* - The `vnode` pointer is valid and properly allocated.
* - The `fops` pointer (if not NULL) points to a valid `struct dfs_file_ops`
* instance, where all necessary function pointers are properly set.
*/
int dfs_vnode_init(struct dfs_vnode *vnode, int type, const struct dfs_file_ops *fops)
{
if (vnode)
@ -64,7 +87,7 @@ int dfs_vnode_init(struct dfs_vnode *vnode, int type, const struct dfs_file_ops
/* BKDR Hash Function */
static unsigned int bkdr_hash(const char *str)
{
unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
unsigned int seed = 131; /* 31 131 1313 13131 131313 etc..*/
unsigned int hash = 0;
while (*str)
@ -75,6 +98,22 @@ static unsigned int bkdr_hash(const char *str)
return (hash % DFS_VNODE_HASH_NR);
}
/**
* @brief Find a DFS vnode by its path.
*
* This function searches for a vnode in the vnode hash table using the specified path.
* If found, it returns a pointer to the vnode and updates the hash head if required.
*
* @param path The file path to search for. This should be a valid null-terminated string.
* @param hash_head Pointer to a location where the hash table head associated with the vnode
* can be stored. This can be NULL if the hash head is not needed.
*
* @return Pointer to the DFS vnode if found, or NULL if no vnode matches the specified path.
*
* @note The caller must ensure that:
* - The `path` pointer is valid and points to a properly null-terminated string.
* - If `hash_head` is not NULL, it points to a valid location to store the hash head.
*/
static struct dfs_vnode *dfs_vnode_find(const char *path, rt_list_t **hash_head)
{
struct dfs_vnode *vnode = NULL;
@ -329,11 +368,12 @@ int dfs_file_close(struct dfs_file *fd)
}
/**
* this function will perform a io control on a file descriptor.
* this function will perform an io control on a file descriptor.
*
* @param fd the file descriptor.
* @param cmd the command to send to file descriptor.
* @param args the argument to send to file descriptor.
* - When `cmd` is `F_SETFL`, an additional integer argument specifies the new status flags.
*
* @return 0 on successful, -1 on failed.
*/
@ -846,7 +886,7 @@ void cat(const char *filename)
{
buffer[length] = '\0';
rt_device_t out_device = rt_console_get_device();
rt_device_write(out_device, 0, (void *)buffer, sizeof(buffer));
rt_device_write(out_device, 0, (void *)buffer, length);
}
} while (length > 0);
rt_kprintf("\n");
@ -1026,14 +1066,14 @@ void copy(const char *src, const char *dst)
flag |= FLAG_DST_IS_FILE;
}
//2. check status
/*2. check status*/
if ((flag & FLAG_SRC_IS_DIR) && (flag & FLAG_DST_IS_FILE))
{
rt_kprintf("cp faild, cp dir to file is not permitted!\n");
return ;
}
//3. do copy
/*3. do copy*/
if (flag & FLAG_SRC_IS_FILE)
{
if (flag & FLAG_DST_IS_DIR)
@ -1053,7 +1093,7 @@ void copy(const char *src, const char *dst)
copyfile(src, dst);
}
}
else //flag & FLAG_SRC_IS_DIR
else /*flag & FLAG_SRC_IS_DIR*/
{
if (flag & FLAG_DST_IS_DIR)
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -322,8 +322,8 @@ int dfs_mount(const char *device_name,
/* open device, but do not check the status of device */
if (dev_id != NULL)
{
if (rt_device_open(fs->dev_id,
RT_DEVICE_OFLAG_RDWR) != RT_EOK)
if (rt_device_open(fs->dev_id, RT_DEVICE_OFLAG_RDWR) != RT_EOK &&
rt_device_open(fs->dev_id, RT_DEVICE_OFLAG_RDONLY) != RT_EOK)
{
/* The underlying device has error, clear the entry. */
dfs_lock();
@ -529,7 +529,8 @@ int dfs_mount_device(rt_device_t dev)
{
int index = 0;
if(dev == RT_NULL) {
if(dev == RT_NULL)
{
rt_kprintf("the device is NULL to be mounted.\n");
return -RT_ERROR;
}
@ -538,7 +539,8 @@ int dfs_mount_device(rt_device_t dev)
{
if (mount_table[index].path == NULL) break;
if(strcmp(mount_table[index].device_name, dev->parent.name) == 0) {
if(strcmp(mount_table[index].device_name, dev->parent.name) == 0)
{
if (dfs_mount(mount_table[index].device_name,
mount_table[index].path,
mount_table[index].filesystemtype,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -28,7 +28,17 @@
* return a file descriptor according specified flags.
*
* @param file the path name of file.
* @param flags the file open flags.
* @param flags the file open flags. Common values include:
* - Access modes (mutually exclusive):
* - `O_RDONLY`: Open for read-only access.
* - `O_WRONLY`: Open for write-only access.
* - `O_RDWR`: Open for both reading and writing.
* - File status flags (can be combined with bitwise OR `|`):
* - `O_CREAT`: Create the file if it does not exist. Requires a `mode` argument.
* - `O_TRUNC`: Truncate the file to zero length if it already exists.
* - `O_APPEND`: Append writes to the end of the file.
* - `O_EXCL`: Ensure that `O_CREAT` creates the file exclusively.
* - Other platform-specific flags
*
* @return the non-negative integer on successful open, others for failed.
*/
@ -65,6 +75,22 @@ RTM_EXPORT(open);
#ifndef AT_FDCWD
#define AT_FDCWD (-100)
#endif
/**
* @brief Opens a file relative to a directory file descriptor.
*
* @param dirfd The file descriptor of the directory to base the relative path on.
* @param pathname The path to the file to be opened, relative to the directory specified by `dirfd`.
* Can be an absolute path (in which case `dirfd` is ignored).
* @param flags File access and status flags (e.g., `O_RDONLY`, `O_WRONLY`, `O_CREAT`).
*
* @return On success, returns a new file descriptor for the opened file.
* On failure, returns `-1` and sets `errno` to indicate the error.
*
* @note When using relative paths, ensure `dirfd` is a valid directory descriptor.
* When `pathname` is absolute, the `dirfd` argument is ignored.
*
*/
int openat(int dirfd, const char *path, int flag, ...)
{
struct dfs_file *d;
@ -241,14 +267,22 @@ ssize_t write(int fd, const void *buf, size_t len)
RTM_EXPORT(write);
/**
* this function is a POSIX compliant version, which will seek the offset for
* this function is a POSIX compliant version, which will Reposition the file offset for
* an open file descriptor.
*
* @param fd the file descriptor.
* @param offset the offset to be seeked.
* @param whence the directory of seek.
* The `lseek` function sets the file offset for the file descriptor `fd`
* to a new value, determined by the `offset` and `whence` parameters.
* It can be used to seek to specific positions in a file for reading or writing.
*
* @return the current read/write position in the file, or -1 on failed.
* @param fd the file descriptor.
* @param offset The offset, in bytes, to set the file position.
* The meaning of `offset` depends on the value of `whence`.
* @param whence the directive of seek. It can be one of:
* - `SEEK_SET`: Set the offset to `offset` bytes from the beginning of the file.
* - `SEEK_CUR`: Set the offset to its current location plus `offset` bytes.
* - `SEEK_END`: Set the offset to the size of the file plus `offset` bytes.
*
* @return the resulting read/write position in the file, or -1 on failed.
*/
off_t lseek(int fd, off_t offset, int whence)
{
@ -436,9 +470,15 @@ RTM_EXPORT(fsync);
* control functions on devices.
*
* @param fildes the file description
* @param cmd the specified command
* @param cmd the specified command, Common values include:
* - `F_DUPFD`: Duplicate a file descriptor.
* - `F_GETFD`: Get the file descriptor flags.
* - `F_SETFD`: Set the file descriptor flags.
* - `F_GETFL`: Get the file status flags.
* - `F_SETFL`: Set the file status flags.
* @param ... represents the additional information that is needed by this
* specific device to perform the requested function.
* specific device to perform the requested function. For example:
* - When `cmd` is `F_SETFL`, an additional integer argument specifies the new status flags.
*
* @return 0 on successful completion. Otherwise, -1 shall be returned and errno
* set to indicate the error.
@ -595,7 +635,7 @@ RTM_EXPORT(fstatfs);
* this function is a POSIX compliant version, which will make a directory
*
* @param path the directory path to be made.
* @param mode
* @param mode The permission mode for the new directory (unused here, can be set to 0).
*
* @return 0 on successful, others on failed.
*/

View File

@ -786,18 +786,18 @@ static ssize_t dfs_cromfs_read(struct dfs_file *file, void *buf, size_t count, o
rt_err_t result = RT_EOK;
file_info *fi = NULL;
cromfs_info *ci = NULL;
uint32_t length = 0;
ssize_t length = 0;
ci = (cromfs_info *)file->dentry->mnt->data;
fi = (file_info *)file->vnode->data;
if (count < file->vnode->size - *pos)
if ((off_t)count < (off_t)file->vnode->size - *pos)
{
length = count;
}
else
{
length = file->vnode->size - *pos;
length = (off_t)file->vnode->size - *pos;
}
if (length > 0)

View File

@ -11,6 +11,9 @@
#ifndef __DFS_CROMFS_H__
#define __DFS_CROMFS_H__
#include <stdint.h>
int dfs_cromfs_init(void);
uint8_t *cromfs_get_partition_data(uint32_t *len);
#endif /*__DFS_CROMFS_H__*/

View File

@ -77,6 +77,7 @@ static int dfs_devfs_open(struct dfs_file *file)
}
}
}
rt_free(device_name);
}
return ret;
@ -113,6 +114,29 @@ static int dfs_devfs_close(struct dfs_file *file)
return ret;
}
static rt_ubase_t _get_unit_shift(rt_device_t device)
{
rt_ubase_t shift = 0;
/**
* transfer unit size from POSIX RW(in bytes) to rt_device_R/W
* (block size for blk device, otherwise in bytes).
*/
if (device->type == RT_Device_Class_Block)
{
struct rt_device_blk_geometry geometry = {0};
/* default to 512 */
shift = 9;
if (!rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry))
{
shift = __rt_ffs(geometry.block_size) - 1;
}
}
return shift;
}
static ssize_t dfs_devfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
{
ssize_t ret = -RT_EIO;
@ -135,9 +159,14 @@ static ssize_t dfs_devfs_read(struct dfs_file *file, void *buf, size_t count, of
if (device->ops)
#endif /* RT_USING_POSIX_DEVIO */
{
/* read device data */
ret = rt_device_read(device, *pos, buf, count);
*pos += ret;
rt_ubase_t shift = _get_unit_shift(device);
ret = rt_device_read(device, *pos, buf, count >> shift);
if (ret > 0)
{
ret <<= shift;
*pos += ret;
}
}
}
@ -169,9 +198,15 @@ static ssize_t dfs_devfs_write(struct dfs_file *file, const void *buf, size_t co
if (device->ops)
#endif /* RT_USING_POSIX_DEVIO */
{
rt_ubase_t shift = _get_unit_shift(device);
/* read device data */
ret = rt_device_write(device, *pos, buf, count);
*pos += ret;
ret = rt_device_write(device, *pos, buf, count >> shift);
if (ret > 0)
{
ret <<= shift;
*pos += ret;
}
}
}
@ -265,7 +300,7 @@ static int dfs_devfs_flush(struct dfs_file *file)
static off_t dfs_devfs_lseek(struct dfs_file *file, off_t offset, int wherece)
{
off_t ret = 0;
off_t ret = -EPERM;
rt_device_t device;
RT_ASSERT(file != RT_NULL);
@ -408,16 +443,16 @@ mode_t dfs_devfs_device_to_mode(struct rt_device *device)
switch (device->type)
{
case RT_Device_Class_Char:
mode = S_IFCHR | 0777;
mode = S_IFCHR | 0666;
break;
case RT_Device_Class_Block:
mode = S_IFBLK | 0777;
mode = S_IFBLK | 0666;
break;
case RT_Device_Class_Pipe:
mode = S_IFIFO | 0777;
mode = S_IFIFO | 0666;
break;
default:
mode = S_IFCHR | 0777;
mode = S_IFCHR | 0666;
break;
}

View File

@ -18,6 +18,7 @@
#include <dfs_dentry.h>
#include <dfs_file.h>
#include <dfs_mnt.h>
#include <dfs_vfs.h>
#include <devfs.h>
#include <unistd.h>
@ -34,10 +35,9 @@ struct devtmpfs_file
char name[DIRENT_NAME_MAX]; /* file name */
rt_uint32_t type; /* file type */
rt_list_t subdirs; /* file subdir list */
rt_list_t sibling; /* file sibling list */
struct dfs_vfs_node node; /* file node in the devtmpfs */
struct devtmpfs_sb *sb; /* superblock ptr */
struct devtmpfs_sb *sb; /* superblock ptr */
rt_uint32_t mode;
char *link;
@ -48,7 +48,6 @@ struct devtmpfs_sb
rt_uint32_t magic; /* TMPFS_MAGIC */
struct devtmpfs_file root; /* root dir */
rt_size_t df_size; /* df size */
rt_list_t sibling; /* sb sibling list */
struct rt_spinlock lock; /* tmpfs lock */
};
@ -111,15 +110,13 @@ static int _get_subdir(const char *path, char *name)
#if 0
static int _free_subdir(struct devtmpfs_file *dfile)
{
struct devtmpfs_file *file;
rt_list_t *list, *temp_list;
struct devtmpfs_file *file, *tmp;
struct devtmpfs_sb *superblock;
RT_ASSERT(dfile->type == TMPFS_TYPE_DIR);
rt_list_for_each_safe(list, temp_list, &dfile->subdirs)
dfs_vfs_for_each_subnode(file, tmp, dfile, node)
{
file = rt_list_entry(list, struct devtmpfs_file, sibling);
if (file->type == TMPFS_TYPE_DIR)
{
_free_subdir(file);
@ -134,7 +131,7 @@ static int _free_subdir(struct devtmpfs_file *dfile)
RT_ASSERT(superblock);
rt_spin_lock(&superblock->lock);
rt_list_remove(&(file->sibling));
dfs_vfs_remove_node(&file->node);
rt_spin_unlock(&superblock->lock);
rt_free(file);
@ -152,14 +149,12 @@ static int devtmpfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void
{
superblock->df_size = sizeof(struct devtmpfs_sb);
superblock->magic = TMPFS_MAGIC;
rt_list_init(&superblock->sibling);
superblock->root.name[0] = '/';
superblock->root.sb = superblock;
superblock->root.type = TMPFS_TYPE_DIR;
superblock->root.mode = S_IFDIR | (S_IRUSR | S_IRGRP | S_IROTH) | (S_IXUSR | S_IXGRP | S_IXOTH);
rt_list_init(&superblock->root.sibling);
rt_list_init(&superblock->root.subdirs);
dfs_vfs_init_node(&superblock->root.node);
rt_spin_lock_init(&superblock->lock);
@ -193,8 +188,7 @@ static struct devtmpfs_file *devtmpfs_file_lookup(struct devtmpfs_sb *superblock
{
const char *subpath, *curpath, *filename = RT_NULL;
char subdir_name[DIRENT_NAME_MAX];
struct devtmpfs_file *file, *curfile;
rt_list_t *list;
struct devtmpfs_file *file, *curfile, *tmp;
subpath = path;
while (*subpath == '/' && *subpath)
@ -222,9 +216,8 @@ find_subpath:
rt_spin_lock(&superblock->lock);
rt_list_for_each(list, &curfile->subdirs)
dfs_vfs_for_each_subnode(file, tmp, curfile, node)
{
file = rt_list_entry(list, struct devtmpfs_file, sibling);
if (filename) /* find file */
{
if (rt_strcmp(file->name, filename) == 0)
@ -293,7 +286,9 @@ static int devtmpfs_stat(struct dfs_dentry *dentry, struct stat *st)
static int devtmpfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
{
struct devtmpfs_file *d_file;
rt_size_t index, end;
struct dirent *d;
struct devtmpfs_file *d_file, *n_file = RT_NULL, *tmp;
struct devtmpfs_sb *superblock;
RT_ASSERT(file);
@ -306,11 +301,6 @@ static int devtmpfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_
d_file = devtmpfs_file_lookup(superblock, file->dentry->pathname);
if (d_file)
{
rt_size_t index, end;
struct dirent *d;
struct devtmpfs_file *n_file;
rt_list_t *list;
/* make integer count */
count = (count / sizeof(struct dirent));
if (count == 0)
@ -322,12 +312,10 @@ static int devtmpfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_
index = 0;
count = 0;
rt_list_for_each(list, &d_file->subdirs)
dfs_vfs_for_each_subnode(n_file, tmp, d_file, node)
{
if (index >= (rt_size_t)file->fpos)
{
n_file = rt_list_entry(list, struct devtmpfs_file, sibling);
d = dirp + count;
if (n_file->type == TMPFS_TYPE_FILE)
{
@ -378,8 +366,7 @@ static int devtmpfs_symlink(struct dfs_dentry *parent_dentry, const char *target
strncpy(l_file->name, linkpath, DIRENT_NAME_MAX - 1);
rt_list_init(&(l_file->subdirs));
rt_list_init(&(l_file->sibling));
dfs_vfs_init_node(&l_file->node);
l_file->sb = superblock;
l_file->type = TMPFS_TYPE_FILE;
l_file->mode = p_file->mode;
@ -388,7 +375,7 @@ static int devtmpfs_symlink(struct dfs_dentry *parent_dentry, const char *target
l_file->link = rt_strdup(target);
rt_spin_lock(&superblock->lock);
rt_list_insert_after(&(p_file->subdirs), &(l_file->sibling));
dfs_vfs_append_node(&p_file->node, &l_file->node);
rt_spin_unlock(&superblock->lock);
}
}
@ -460,7 +447,7 @@ static int devtmpfs_unlink(struct dfs_dentry *dentry)
}
rt_spin_lock(&superblock->lock);
rt_list_remove(&(d_file->sibling));
dfs_vfs_remove_node(&d_file->node);
rt_spin_unlock(&superblock->lock);
rt_free(d_file);
@ -537,8 +524,7 @@ static struct dfs_vnode *devtmpfs_create_vnode(struct dfs_dentry *dentry, int ty
strncpy(d_file->name, file_name, DIRENT_NAME_MAX);
rt_list_init(&(d_file->subdirs));
rt_list_init(&(d_file->sibling));
dfs_vfs_init_node(&d_file->node);
d_file->sb = superblock;
vnode->nlink = 1;
@ -563,7 +549,7 @@ static struct dfs_vnode *devtmpfs_create_vnode(struct dfs_dentry *dentry, int ty
d_file->mode = vnode->mode;
rt_spin_lock(&superblock->lock);
rt_list_insert_after(&(p_file->subdirs), &(d_file->sibling));
dfs_vfs_append_node(&p_file->node, &d_file->node);
rt_spin_unlock(&superblock->lock);
}

View File

@ -0,0 +1,166 @@
# 进程文件系统 (procfs)
## 数据结构
```c
struct proc_dentry
{
rt_uint32_t mode;
rt_atomic_t ref_count;
struct proc_dentry *parent;
struct dfs_vfs_node node;
const struct dfs_file_ops *fops;
const struct proc_ops *ops;
char *name;
void *data;
};
```
```log
root { mode: S_IFDIR, ref_count: 1, parent: root, name: /, child->next: file1->node }
|
|—— file1 { mode: S_IFREG, ref_count: 1, parent: root, name: file1, node->next: link1->node }
|—— link1 { mode: S_IFLNK, ref_count: 1, parent: root, name: link1, data: fullpath, node->next: dir1->node }
|—— dir1 { mode: S_IFDIR, ref_count: 1, parent: root, name: dir1, node->next: file3->node, child->next: file2->node }
| |
| |—— dir2 { mode: S_IFDIR, ref_count: 1, parent: dir1, name: dir2, node->next: link2->node }
| |—— link2 { mode: S_IFLNK, ref_count: 1, parent: dir1, name: link2, data: fullpath, node->next: file2->node }
| |—— file2 { mode: S_IFREG, ref_count: 1, parent: dir1, name: file2 }
|
|—— file3 { mode: S_IFREG, ref_count: 1, parent: root, name: file3 }
```
## API 介绍
```c
struct proc_dentry *dfs_proc_find(const char *name);
struct proc_dentry *proc_mkdir_data(const char *name, mode_t mode, struct proc_dentry *parent,
const struct dfs_file_ops *fops, void *data);
struct proc_dentry *proc_mkdir_mode(const char *name, mode_t mode, struct proc_dentry *parent);
struct proc_dentry *proc_mkdir(const char *name, struct proc_dentry *parent);
struct proc_dentry *proc_create_data(const char *name, mode_t mode, struct proc_dentry *parent,
const struct dfs_file_ops *fops, void *data);
struct proc_dentry *proc_symlink(const char *name, struct proc_dentry *parent, const char *dest);
struct proc_dentry *proc_acquire(struct proc_dentry *dentry);
void proc_release(struct proc_dentry *dentry);
void proc_remove(struct proc_dentry *dentry);
```
- dfs_proc_find
查找指定节点,并返回节点数据指针
| 入参 | 说明 |
| ---- | ---------------------------------------------------- |
| name | 从 procfs 的 root 起始的完整路径,比如 “/dir1/file2” |
- proc_mkdir_data
创建一个目录,并返回节点数据指针
| 入参 | 说明 |
| ------ | ------------------------------------------------------------ |
| name | 从 procfs 的 root 起始的完整路径,比如 “/dir1/file2”<br />从 parent 起始的完整路径 |
| mode | 权限配置 |
| parent | 指定创建目录的起始节点 |
| fops | 文件操作接口配置 |
| data | 私有数据 |
- proc_mkdir_mode
创建一个目录,并返回节点数据指针
| 入参 | 说明 |
| ------ | ------------------------------------------------------------ |
| name | 从 procfs 的 root 起始的完整路径,比如 “/dir1/file2”<br />从 parent 起始的完整路径 |
| mode | 权限配置 |
| parent | 指定创建目录的起始节点 |
- proc_mkdir
创建一个目录,并返回节点数据指针
| 入参 | 说明 |
| ---- | ------------------------------------------------------------ |
| name | 从 procfs 的 root 起始的完整路径,比如 “/dir1/file2”<br />从 parent 起始的完整路径 |
| mode | 权限配置 |
- proc_create_data
创建一个文件,并返回节点数据指针
| 入参 | 说明 |
| ------ | ------------------------------------------------------------ |
| name | 从 procfs 的 root 起始的完整路径,比如 “/dir1/file2”<br />从 parent 起始的完整路径 |
| mode | 权限配置 |
| parent | 指定创建文件的起始节点 |
| fops | 文件操作接口配置 |
| data | 私有数据 |
- proc_symlink
创建一个符号链接,并返回节点数据指针
| 入参 | 说明 |
| ------ | ------------------------------------------------------------ |
| name | 从 procfs 的 root 起始的完整路径,比如 “/dir1/file2”<br />从 parent 起始的完整路径 |
| parent | 指定创建文件的起始节点 |
| dest | 链接的目标文件完整路径 |
- proc_acquire
引用一个节点,并返回节点数据指针
| 入参 | 说明 |
| ------ | -------------- |
| dentry | 需要引用的节点 |
- proc_release
释放一个节点
| 入参 | 说明 |
| ------ | -------------- |
| dentry | 需要释放的节点 |
- proc_remove
删除一个节点包含子节点
| 入参 | 说明 |
| ------ | -------------- |
| dentry | 需要删除的节点 |
## msh 调试命令
- proc_dump
遍历打印指定节点含子节点的信息(名称、引用计数),比如 `proc_dump /dir1` 或者 `proc_dump`
- proc_remove
删除指定节点含子节点,比如 `proc_remove /dir1` 或者 `proc_remove /file3`
- proc_symlink
创建一个符号链接,`proc_symlink /link3 /mnt`
- proc_echo
创建一个空文件,`proc_echo /file4`
- proc_mkdir
创建一个空目录,`proc_mkdir /dir3`
- proc_pid
创建一个 pid 目录,`proc_pid /101`

View File

@ -0,0 +1,11 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS', 'RT_USING_DFS_PROCFS'], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,733 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
/*
* This is the root in the proc tree..
*/
static struct proc_dentry _proc_root = {
.mode = S_IFDIR | (S_IRUSR | S_IRGRP | S_IROTH) | (S_IXUSR | S_IXGRP | S_IXOTH),
.ref_count = 1,
.parent = &_proc_root,
.node.sibling = RT_LIST_OBJECT_INIT(_proc_root.node.sibling),
.node.subnode = RT_LIST_OBJECT_INIT(_proc_root.node.subnode),
.fops = RT_NULL,
.name = "/",
.data = RT_NULL,
};
static int _proc_find(struct proc_dentry **parent, const char *name)
{
struct proc_dentry *dentry = RT_NULL, *tmp;
dfs_vfs_for_each_subnode(dentry, tmp, (*parent), node)
{
if (dentry == RT_NULL)
{
break;
}
if (rt_strcmp(dentry->name, name) == 0)
{
*parent = dentry;
return 0;
}
}
return -1;
}
static int proc_find(struct proc_dentry **parent, const char **name, rt_bool_t force_lookup)
{
int ret = 0;
char *tmp = RT_NULL;
if (!(*parent))
{
*parent = &_proc_root;
}
tmp = rt_strdup(*name);
if (tmp)
{
char *begin = tmp, *end = RT_NULL;
if (*begin == '/')
{
begin++;
if (*begin == '\0')
{
rt_free(tmp);
*parent = proc_acquire(*parent);
return ret;
}
}
while (1)
{
end = rt_strstr(begin, "/");
if (end)
{
*end = '\0';
ret = _proc_find(parent, begin);
if (ret < 0 || !S_ISDIR((*parent)->mode))
{
*parent = RT_NULL;
ret = -1;
break;
}
begin = end + 1;
}
else if (force_lookup)
{
ret = _proc_find(parent, begin);
if (ret < 0)
{
if ((*parent)->ops && (*parent)->ops->lookup)
{
*parent = (*parent)->ops->lookup(*parent, begin);
if (*parent == RT_NULL)
{
ret = -1;
}
}
else
{
*parent = RT_NULL;
}
}
else
{
*parent = proc_acquire(*parent);
}
break;
}
else
{
*parent = proc_acquire(*parent);
break;
}
}
*name = *name + (begin - tmp);
rt_free(tmp);
}
return ret;
}
static void *single_start(struct dfs_seq_file *seq, off_t *index)
{
return NULL + (*index == 0);
}
static void *single_next(struct dfs_seq_file *seq, void *data, off_t *index)
{
++*index;
return NULL;
}
static void single_stop(struct dfs_seq_file *seq, void *data)
{
}
static int proc_open(struct dfs_file *file)
{
struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
if (entry->single_show)
{
struct dfs_seq_ops *seq_ops = (struct dfs_seq_ops *)rt_calloc(1, sizeof(struct dfs_seq_ops));
if (seq_ops)
{
int ret = 0;
seq_ops->start = single_start;
seq_ops->next = single_next;
seq_ops->stop = single_stop;
seq_ops->show = entry->single_show;
ret = dfs_seq_open(file, seq_ops);
if (ret != 0)
{
rt_free(seq_ops);
}
return ret;
}
}
return dfs_seq_open(file, entry->seq_ops);
}
static int proc_close(struct dfs_file *file)
{
struct dfs_seq_file *seq = file->data;
struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
if (seq && entry->single_show && seq->ops)
{
rt_free((void *)seq->ops);
seq->ops = RT_NULL;
}
return dfs_seq_release(file);
}
static const struct dfs_file_ops proc_file_ops = {
.open = proc_open,
.read = dfs_seq_read,
.lseek = dfs_seq_lseek,
.close = proc_close,
};
static struct proc_dentry *proc_create(struct proc_dentry **parent, const char *name, mode_t mode)
{
int ret = 0;
struct proc_dentry *dentry = RT_NULL;
ret = proc_find(parent, &name, 0);
if (ret >= 0)
{
dentry = *parent;
ret = proc_find(&dentry, &name, 1);
if (ret < 0)
{
dentry = rt_calloc(1, sizeof(struct proc_dentry));
if (dentry)
{
dentry->mode = mode;
dentry->ref_count = 1;
dentry->name = rt_strdup(name);
dfs_vfs_init_node(&dentry->node);
}
}
else
{
proc_release(dentry);
dentry = RT_NULL;
}
}
return dentry;
}
/**
* @brief The dentry reference count is incremented by one
*
* @param dentry
*
* @return dentry
*/
struct proc_dentry *proc_acquire(struct proc_dentry *dentry)
{
if (dentry)
{
dentry->ref_count += 1;
}
return dentry;
}
/**
* @brief The dentry reference count is minus one, or release
*
* @param dentry
*
* @return none
*/
void proc_release(struct proc_dentry *dentry)
{
if (dentry)
{
if (dentry->ref_count == 1)
{
if (dentry->name)
{
rt_free(dentry->name);
}
if (S_ISLNK(dentry->mode) && dentry->data)
{
rt_free(dentry->data);
}
rt_free(dentry);
}
else
{
dentry->ref_count -= 1;
}
}
}
static struct proc_dentry *proc_register(struct proc_dentry *parent, struct proc_dentry *child)
{
child->parent = parent;
dfs_vfs_append_node(&parent->node, &child->node);
child->ref_count += 1;
child->pid = parent->pid;
return child;
}
/**
* @brief Make a dir
*
* @param name fullpath based on _proc_root or parent
* @param mode permission configuration
* @param parent can be empty
* @param fops
* @param data
*
* @return dentry
*/
struct proc_dentry *proc_mkdir_data(const char *name, mode_t mode, struct proc_dentry *parent,
const struct dfs_file_ops *fops, void *data)
{
struct proc_dentry *dentry, *_parent = parent;
if (mode == 0)
mode = (S_IRUSR | S_IRGRP | S_IROTH) | (S_IXUSR | S_IXGRP | S_IXOTH);
dentry = proc_create(&_parent, name, S_IFDIR | mode);
if (dentry)
{
dentry->fops = fops;
dentry->data = data;
dentry = proc_register(_parent, dentry);
}
proc_release(_parent);
return dentry;
}
/**
* @brief Make a dir
*
* @param name fullpath based on _proc_root or parent
* @param mode permission configuration
* @param parent can be empty
*
* @return dentry
*/
struct proc_dentry *proc_mkdir_mode(const char *name, mode_t mode, struct proc_dentry *parent)
{
return proc_mkdir_data(name, mode, parent, NULL, NULL);
}
/**
* @brief Make a dir
*
* @param name fullpath based on _proc_root or parent
* @param parent can be empty
*
* @return dentry
*/
struct proc_dentry *proc_mkdir(const char *name, struct proc_dentry *parent)
{
return proc_mkdir_data(name, 0, parent, NULL, NULL);
}
static struct proc_dentry *proc_create_reg(const char *name, mode_t mode, struct proc_dentry **parent)
{
struct proc_dentry *dentry = RT_NULL;
if ((mode & S_IFMT) == 0)
mode |= S_IFREG;
if ((mode & (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)) == 0)
mode |= S_IRUSR | S_IRGRP | S_IROTH;
if (!S_ISREG(mode))
{
*parent = RT_NULL;
return dentry;
}
return proc_create(parent, name, mode);
}
/**
* @brief Make a file
*
* @param name fullpath based on _proc_root or parent
* @param mode permission configuration
* @param parent can be empty
* @param fops
* @param data
*
* @return dentry
*/
struct proc_dentry *proc_create_data(const char *name, mode_t mode, struct proc_dentry *parent,
const struct dfs_file_ops *fops, void *data)
{
struct proc_dentry *dentry, *_parent = parent;
dentry = proc_create_reg(name, mode, &_parent);
if (dentry)
{
dentry->fops = fops ? fops : &proc_file_ops;
dentry->data = data;
dentry = proc_register(_parent, dentry);
}
proc_release(_parent);
return dentry;
}
/**
* @brief Make a file
*
* @param name fullpath based on _proc_root or parent
* @param mode permission configuration
* @param parent can be empty
* @param show
* @param data
*
* @return dentry
*/
struct proc_dentry *proc_create_single_data(const char *name, mode_t mode, struct proc_dentry *parent,
int (*show)(struct dfs_seq_file *, void *), void *data)
{
struct proc_dentry *dentry, *_parent = parent;
dentry = proc_create_reg(name, mode, &_parent);
if (dentry)
{
dentry->fops = &proc_file_ops;
dentry->single_show = show;
dentry->data = data;
dentry = proc_register(_parent, dentry);
}
proc_release(_parent);
return dentry;
}
/**
* @brief Make a symlink
*
* @param name fullpath based on _proc_root or parent
* @param parent can be empty
* @param dest link file fullpath
*
* @return dentry
*/
struct proc_dentry *proc_symlink(const char *name, struct proc_dentry *parent, const char *dest)
{
struct proc_dentry *dentry, *_parent = parent;
dentry = proc_create(&_parent, name, (S_IFLNK | (S_IRUSR | S_IRGRP | S_IROTH)
| (S_IWUSR | S_IWGRP | S_IWOTH) | (S_IXUSR | S_IXGRP | S_IXOTH)));
if (dentry)
{
dentry->data = (void *)rt_strdup(dest);
if (dentry->data)
{
dentry = proc_register(_parent, dentry);
}
else
{
proc_release(dentry);
dentry = NULL;
}
}
proc_release(_parent);
return dentry;
}
static void remove_proc_subtree(struct proc_dentry *dentry)
{
struct proc_dentry *iter = RT_NULL, *iter_tmp, *tmp = RT_NULL;
dfs_vfs_for_each_subnode(iter, iter_tmp, dentry, node)
{
if (iter == RT_NULL)
{
break;
}
if (tmp)
{
proc_release(tmp);
tmp = RT_NULL;
}
tmp = iter;
if (S_ISDIR(dentry->mode))
{
remove_proc_subtree(iter);
}
}
if (tmp)
{
proc_release(tmp);
tmp = RT_NULL;
}
}
/**
* @brief remove a dentry
*
* @param dentry
*
* @return none
*/
void proc_remove(struct proc_dentry *dentry)
{
if (dentry && dentry != &_proc_root)
{
if (S_ISDIR(dentry->mode))
{
remove_proc_subtree(dentry);
}
dfs_vfs_remove_node(&dentry->node);
proc_release(dentry);
}
}
/**
* @brief find dentry exist
*
* @param name fullpath based on _proc_root
*
* @return dentry
*/
struct proc_dentry *dfs_proc_find(const char *name)
{
struct proc_dentry *dentry = RT_NULL;
proc_find(&dentry, &name, 1);
return dentry;
}
/**
* @brief remove a dentry on parent
*
* @param name fullpath based on parent
* @param parent
*
* @return none
*/
void proc_remove_dentry(const char *name, struct proc_dentry *parent)
{
struct proc_dentry *dentry = parent;
if (proc_find(&dentry, &name, 1) >= 0)
{
proc_remove(dentry);
proc_release(dentry);
}
}
#define _COLOR_RED "\033[31m"
#define _COLOR_GREEN "\033[32m"
#define _COLOR_BLUE "\033[34m"
#define _COLOR_CYAN "\033[36m"
#define _COLOR_WHITE "\033[37m"
#define _COLOR_NORMAL "\033[0m"
static void dump_proc_subtree(struct proc_dentry *dentry, int tab)
{
struct proc_dentry *iter = RT_NULL, *tmp;
dfs_vfs_for_each_subnode(iter, tmp, dentry, node)
{
if (iter == RT_NULL)
{
break;
}
for(int i = 0; i < tab; i ++)
{
rt_kprintf("%-4s", i + 1 >= tab ? "|-" : " ");
}
if (S_ISDIR(iter->mode))
{
rt_kprintf(_COLOR_BLUE "%-20s" _COLOR_NORMAL " %d\n", iter->name, iter->ref_count);
dump_proc_subtree(iter, tab + 1);
}
else if (S_ISLNK(iter->mode))
{
rt_kprintf(_COLOR_CYAN "%-20s" _COLOR_NORMAL " %d\n", iter->name, iter->ref_count);
}
else
{
rt_kprintf("%-20s %d\n", iter->name, iter->ref_count);
}
}
}
static void proc_dump(struct proc_dentry *dentry)
{
if (dentry)
{
if (S_ISDIR(dentry->mode))
{
rt_kprintf(_COLOR_BLUE "%-20s" _COLOR_NORMAL " %d\n", dentry->name, dentry->ref_count);
dump_proc_subtree(dentry, 1);
}
else if (S_ISLNK(dentry->mode))
{
rt_kprintf(_COLOR_CYAN "%-20s" _COLOR_NORMAL " %d\n", dentry->name, dentry->ref_count);
}
else
{
rt_kprintf("%-20s %d\n", dentry->name, dentry->ref_count);
}
}
}
static int msh_proc_dump(int argc, char** argv)
{
const char *name = argc > 1 ? argv[1] : "/";
struct proc_dentry *dentry = RT_NULL;
int ret = proc_find(&dentry, &name, 1);
if (ret >= 0)
{
proc_dump(dentry);
}
proc_release(dentry);
return 0;
}
MSH_CMD_EXPORT_ALIAS(msh_proc_dump, proc_dump, proc dump);
static int msh_proc_remove(int argc, char** argv)
{
if (argc > 1)
{
const char *name = argv[1];
struct proc_dentry *dentry = RT_NULL;
int ret = proc_find(&dentry, &name, 1);
if (ret >= 0)
{
if (dentry != &_proc_root)
{
proc_remove(dentry);
}
else
{
struct proc_dentry *iter = RT_NULL, *iter_tmp, *tmp = RT_NULL;
dfs_vfs_for_each_subnode(iter, iter_tmp, dentry, node)
{
if (iter == RT_NULL)
{
break;
}
if (tmp)
{
proc_remove(tmp);
}
tmp = iter;
}
if (tmp)
{
proc_remove(tmp);
}
}
}
proc_release(dentry);
}
else
{
rt_kprintf("proc_remove path\n");
}
return 0;
}
MSH_CMD_EXPORT_ALIAS(msh_proc_remove, proc_remove, proc remove);
static int msh_proc_symlink(int argc, char** argv)
{
if (argc > 2)
{
struct proc_dentry *entry = proc_symlink(argv[1], 0, argv[2]);
if (entry)
{
proc_release(entry);
}
}
else
{
rt_kprintf("proc_symlink path dest\n");
}
return 0;
}
MSH_CMD_EXPORT_ALIAS(msh_proc_symlink, proc_symlink, proc symlink);
static int msh_proc_echo(int argc, char** argv)
{
if (argc > 1)
{
for(int i = 1; i <= argc - 1; i ++)
{
struct proc_dentry *entry = proc_create_data(argv[i], 0, 0, 0, 0);
if (entry)
{
proc_release(entry);
}
}
}
else
{
rt_kprintf("proc_echo path\n");
}
return 0;
}
MSH_CMD_EXPORT_ALIAS(msh_proc_echo, proc_echo, proc echo);
static int msh_proc_mkdir(int argc, char** argv)
{
if (argc > 1)
{
for(int i = 1; i <= argc - 1; i ++)
{
struct proc_dentry *entry = proc_mkdir(argv[i], 0);
if (entry)
{
proc_release(entry);
}
}
}
else
{
rt_kprintf("proc_mkdir path\n");
}
return 0;
}
MSH_CMD_EXPORT_ALIAS(msh_proc_mkdir, proc_mkdir, proc mkdir);

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#ifndef __PROC_H__
#define __PROC_H__
#include <dfs_file.h>
#include <dfs_seq_file.h>
#include <dfs_vfs.h>
#ifdef __cplusplus
extern "C"
{
#endif
struct proc_dentry;
struct proc_ops
{
struct proc_dentry *(*lookup)(struct proc_dentry *parent, const char *name);
int (*readlink)(struct proc_dentry *dentry, char *buf, int len);
};
struct proc_dentry
{
rt_uint32_t mode;
rt_atomic_t ref_count;
struct proc_dentry *parent;
struct dfs_vfs_node node;
const struct dfs_file_ops *fops;
const struct proc_ops *ops;
const struct dfs_seq_ops *seq_ops;
int (*single_show)(struct dfs_seq_file *seq, void *data);
int pid;
char *name;
void *data;
};
struct proc_dentry *dfs_proc_find(const char *name);
struct proc_dentry *proc_mkdir_data(const char *name, mode_t mode, struct proc_dentry *parent,
const struct dfs_file_ops *fops, void *data);
struct proc_dentry *proc_mkdir_mode(const char *name, mode_t mode, struct proc_dentry *parent);
struct proc_dentry *proc_mkdir(const char *name, struct proc_dentry *parent);
struct proc_dentry *proc_create_data(const char *name, mode_t mode, struct proc_dentry *parent,
const struct dfs_file_ops *fops, void *data);
struct proc_dentry *proc_create_single_data(const char *name, mode_t mode, struct proc_dentry *parent,
int (*show)(struct dfs_seq_file *, void *), void *data);
struct proc_dentry *proc_symlink(const char *name, struct proc_dentry *parent, const char *dest);
struct proc_dentry *proc_acquire(struct proc_dentry *dentry);
void proc_release(struct proc_dentry *dentry);
void proc_remove(struct proc_dentry *dentry);
void proc_remove_dentry(const char *name, struct proc_dentry *parent);
int proc_pid(int pid);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
static char *__proc_cmdline = NULL;
int proc_cmdline_save(const char *cmdline)
{
if (__proc_cmdline)
{
free(__proc_cmdline);
__proc_cmdline = NULL;
}
__proc_cmdline = strdup(cmdline);
return 0;
}
static int single_show(struct dfs_seq_file *seq, void *data)
{
if (__proc_cmdline)
{
dfs_seq_puts(seq, __proc_cmdline);
}
return 0;
}
int proc_cmdline_init(void)
{
struct proc_dentry *dentry = proc_create_single_data("cmdline", 0, NULL, single_show, NULL);
proc_release(dentry);
return 0;
}
INIT_ENV_EXPORT(proc_cmdline_init);

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
static void *seq_start(struct dfs_seq_file *seq, off_t *index)
{
off_t i = *index; // seq->index
return NULL + (i == 0);
}
static void seq_stop(struct dfs_seq_file *seq, void *data)
{
}
static void *seq_next(struct dfs_seq_file *seq, void *data, off_t *index)
{
/* data: The return value of the start or next*/
off_t i = *index + 1; // seq->index
*index = i;
return NULL;
}
static int seq_show(struct dfs_seq_file *seq, void *data)
{
/* data: The return value of the start or next*/
dfs_seq_puts(seq, "rt_weak const struct dfs_seq_ops *cpuinfo_get_seq_ops(void)\n--need your own function--\n");
return 0;
}
static const struct dfs_seq_ops seq_ops = {
.start = seq_start,
.stop = seq_stop,
.next = seq_next,
.show = seq_show,
};
rt_weak const struct dfs_seq_ops *cpuinfo_get_seq_ops(void)
{
return &seq_ops;
}
static int proc_open(struct dfs_file *file)
{
return dfs_seq_open(file, cpuinfo_get_seq_ops());
}
static int proc_close(struct dfs_file *file)
{
return dfs_seq_release(file);
}
static const struct dfs_file_ops file_ops = {
.open = proc_open,
.read = dfs_seq_read,
.lseek = dfs_seq_lseek,
.close = proc_close,
};
int proc_cpuinfo_init(void)
{
struct proc_dentry *dentry = proc_create_data("cpuinfo", 0, NULL, &file_ops, NULL);
proc_release(dentry);
return 0;
}
INIT_ENV_EXPORT(proc_cpuinfo_init);

View File

@ -0,0 +1,307 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
#include <rthw.h>
#include <rtthread.h>
#include <string.h>
#define LIST_FIND_OBJ_NR 8
struct device_show
{
char *buf;
int size;
int len;
int index;
};
typedef struct
{
rt_list_t *list;
rt_list_t **array;
rt_uint8_t type;
int nr; /* input: max nr, can't be 0 */
int nr_out; /* out: got nr */
} list_get_next_t;
static void list_find_init(list_get_next_t *p, rt_uint8_t type, rt_list_t **array, int nr)
{
struct rt_object_information *info;
rt_list_t *list;
info = rt_object_get_information((enum rt_object_class_type)type);
list = &info->object_list;
p->list = list;
p->type = type;
p->array = array;
p->nr = nr;
p->nr_out = 0;
}
static rt_list_t *list_get_next(rt_list_t *current, list_get_next_t *arg)
{
int first_flag = 0;
rt_base_t level;
rt_list_t *node, *list;
rt_list_t **array;
struct rt_object_information *info;
int nr;
arg->nr_out = 0;
if (!arg->nr || !arg->type)
{
return (rt_list_t *)RT_NULL;
}
list = arg->list;
info = rt_list_entry(list, struct rt_object_information, object_list);
if (!current) /* find first */
{
node = list;
first_flag = 1;
}
else
{
node = current;
}
level = rt_spin_lock_irqsave(&info->spinlock);
if (!first_flag)
{
struct rt_object *obj;
/* The node in the list? */
obj = rt_list_entry(node, struct rt_object, list);
if ((obj->type & ~RT_Object_Class_Static) != arg->type)
{
rt_spin_unlock_irqrestore(&info->spinlock, level);
return (rt_list_t *)RT_NULL;
}
}
nr = 0;
array = arg->array;
while (1)
{
node = node->next;
if (node == list)
{
node = (rt_list_t *)RT_NULL;
break;
}
nr++;
*array++ = node;
if (nr == arg->nr)
{
break;
}
}
rt_spin_unlock_irqrestore(&info->spinlock, level);
arg->nr_out = nr;
return node;
}
static char *const device_type_str[RT_Device_Class_Unknown] =
{
"Character Device",
"Block Device",
"Network Interface",
"MTD Device",
"CAN Device",
"RTC",
"Sound Device",
"Graphic Device",
"I2C Bus",
"USB Slave Device",
"USB Host Bus",
"USB OTG Bus",
"SPI Bus",
"SPI Device",
"SDIO Bus",
"PM Pseudo Device",
"Pipe",
"Portal Device",
"Timer Device",
"Miscellaneous Device",
"Sensor Device",
"Touch Device",
"Phy Device",
"Security Device",
"WLAN Device",
"Pin Device",
"ADC Device",
"DAC Device",
"WDT Device",
"PWM Device",
"Bus Device",
};
static void save_info(struct device_show *dev, char *dev_name)
{
char tmp[256] = {0};
int len;
dev->index ++;
rt_snprintf(tmp, 256, "%d %s\n", dev->index, dev_name);
tmp[255] = 0;
len = rt_strlen(tmp);
if (dev->size > dev->len + len)
{
strcat(dev->buf, tmp);
dev->len += len;
}
else
{
if (dev->buf == RT_NULL)
{
dev->buf = rt_calloc(1, 4096);
}
else
{
dev->buf = rt_realloc(dev->buf, dev->size + 4096);
}
if (dev->buf)
{
dev->size += 4096;
strcat(dev->buf, tmp);
dev->len += len;
}
}
}
static void list_device(struct device_show *dev)
{
rt_base_t level;
list_get_next_t find_arg;
struct rt_object_information *info;
rt_list_t *obj_list[LIST_FIND_OBJ_NR];
rt_list_t *next = (rt_list_t *)RT_NULL;
list_find_init(&find_arg, RT_Object_Class_Device, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
info = rt_list_entry(find_arg.list, struct rt_object_information, object_list);
do
{
next = list_get_next(next, &find_arg);
{
int i;
for (i = 0; i < find_arg.nr_out; i++)
{
struct rt_object *obj;
struct rt_device *device;
obj = rt_list_entry(obj_list[i], struct rt_object, list);
level = rt_spin_lock_irqsave(&info->spinlock);
if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
{
rt_spin_unlock_irqrestore(&info->spinlock, level);
continue;
}
rt_spin_unlock_irqrestore(&info->spinlock, level);
device = (struct rt_device *)obj;
if (device->type < RT_Device_Class_Unknown)
{
save_info(dev + device->type, device->parent.name);
}
}
}
}
while (next != (rt_list_t *)RT_NULL);
}
static int show_info(struct dfs_seq_file *seq)
{
struct device_show _show[RT_Device_Class_Unknown] = {0};
list_device(_show);
for (int i = 0; i < RT_Device_Class_Unknown; i++)
{
if (_show[i].buf)
{
dfs_seq_printf(seq, "%s:\n", device_type_str[i]);
dfs_seq_write(seq, _show[i].buf, _show[i].len);
dfs_seq_putc(seq, '\n');
rt_free(_show[i].buf);
}
}
return 0;
}
static void *seq_start(struct dfs_seq_file *seq, off_t *index)
{
off_t i = *index; // seq->index
return NULL + (i == 0);
}
static void seq_stop(struct dfs_seq_file *seq, void *data)
{
}
static void *seq_next(struct dfs_seq_file *seq, void *data, off_t *index)
{
/* data: The return value of the start or next*/
off_t i = *index + 1; // seq->index
*index = i;
return NULL;
}
static int seq_show(struct dfs_seq_file *seq, void *data)
{
/* data: The return value of the start or next*/
show_info(seq);
return 0;
}
static const struct dfs_seq_ops seq_ops = {
.start = seq_start,
.stop = seq_stop,
.next = seq_next,
.show = seq_show,
};
int proc_devices_init(void)
{
struct proc_dentry *dentry = proc_create_data("devices", 0, NULL, NULL, NULL);
if (dentry)
{
dentry->seq_ops = &seq_ops;
}
proc_release(dentry);
return 0;
}
INIT_ENV_EXPORT(proc_devices_init);

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
#include <dfs_fs.h>
static void *seq_start(struct dfs_seq_file *seq, off_t *index)
{
off_t i = *index; // seq->index
struct dfs_filesystem_type *fs = dfs_filesystems();
if (fs)
{
while (i--)
{
fs = fs->next;
if (!fs)
{
break;
}
}
}
return fs;
}
static void seq_stop(struct dfs_seq_file *seq, void *data)
{
}
static void *seq_next(struct dfs_seq_file *seq, void *data, off_t *index)
{
/* data: The return value of the start or next*/
off_t i = *index + 1; // seq->index
struct dfs_filesystem_type *fs = (struct dfs_filesystem_type *)data;
*index = i;
return fs->next;
}
static int seq_show(struct dfs_seq_file *seq, void *data)
{
/* data: The return value of the start or next*/
struct dfs_filesystem_type *fs = (struct dfs_filesystem_type *)data;
dfs_seq_printf(seq, "%-9s%s\n", (fs->fs_ops->flags == FS_NEED_DEVICE) ? "" : "nodev", fs->fs_ops->name);
return 0;
}
static const struct dfs_seq_ops seq_ops = {
.start = seq_start,
.stop = seq_stop,
.next = seq_next,
.show = seq_show,
};
int proc_filesystems_init(void)
{
struct proc_dentry *dentry = proc_create_data("filesystems", 0, NULL, NULL, NULL);
if (dentry)
{
dentry->seq_ops = &seq_ops;
}
proc_release(dentry);
return 0;
}
INIT_ENV_EXPORT(proc_filesystems_init);

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
#include <mm_page.h>
extern void rt_memory_info(rt_size_t *total,
rt_size_t *used,
rt_size_t *max_used);
static int single_show(struct dfs_seq_file *seq, void *data)
{
dfs_seq_printf(seq, "0.13 0.16 0.17 1/1035 380436\n");
return 0;
}
int proc_loadavg_init(void)
{
struct proc_dentry *dentry = proc_create_single_data("loadavg", 0, NULL, single_show, NULL);
proc_release(dentry);
return 0;
}
INIT_ENV_EXPORT(proc_loadavg_init);

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
#include <mm_page.h>
extern void rt_memory_info(rt_size_t *total,
rt_size_t *used,
rt_size_t *max_used);
static int single_show(struct dfs_seq_file *seq, void *data)
{
rt_size_t total, used, max_used, freed;
rt_size_t total_sum = 0;
rt_size_t total_freed = 0;
rt_memory_info(&total, &used, &max_used);
total_sum = total_sum + total;
total_freed = total_freed + total - used;
dfs_seq_printf(seq, "%-16s%8d KB\n", "MemMaxUsed:", max_used / 1024);
dfs_seq_printf(seq, "%-16s%8d KB\n", "MemAvailable:", (total - used) / 1024);
dfs_seq_printf(seq, "%-16s%8d KB\n", "Cached:", 0);
dfs_seq_printf(seq, "%-16s%8d KB\n", "SReclaimable:", 0);
rt_page_get_info(&total, &freed);
total_sum = total_sum + total * RT_MM_PAGE_SIZE;
total_freed = total_freed + freed * RT_MM_PAGE_SIZE;
dfs_seq_printf(seq, "%-16s%8d KB\n", "MemTotal:", total_sum / 1024);
dfs_seq_printf(seq, "%-16s%8d KB\n", "MemFree:", total_freed / 1024);
dfs_seq_printf(seq, "%-16s%8d KB\n", "LowPageTotal:", total * RT_MM_PAGE_SIZE / 1024);
dfs_seq_printf(seq, "%-16s%8d KB\n", "lowPageFree:", freed * RT_MM_PAGE_SIZE/ 1024);
rt_page_high_get_info(&total, &freed);
dfs_seq_printf(seq, "%-16s%8d KB\n", "HighPageTotal:", total * RT_MM_PAGE_SIZE / 1024);
dfs_seq_printf(seq, "%-16s%8d KB\n", "HighPageFree:", freed * RT_MM_PAGE_SIZE / 1024);
return 0;
}
int proc_meminfo_init(void)
{
struct proc_dentry *dentry = proc_create_single_data("meminfo", 0, NULL, single_show, NULL);
proc_release(dentry);
return 0;
}
INIT_ENV_EXPORT(proc_meminfo_init);

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
#include <dfs_mnt.h>
const char *mnt_flag(int flag)
{
/*if (flag & MNT_READONLY)
{
return "ro";
}*/
return "rw";
}
static struct dfs_mnt* mnt_show(struct dfs_mnt *mnt, void *parameter)
{
struct dfs_seq_file *seq = (struct dfs_seq_file *)parameter;
if (mnt)
{
if (mnt->dev_id)
{
dfs_seq_printf(seq, "%s %s %s %s 0 0\n", mnt->dev_id->parent.name, mnt->fullpath,
mnt->fs_ops->name, mnt_flag(mnt->flags));
}
else
{
dfs_seq_printf(seq, "%s %s %s %s 0 0\n", mnt->fs_ops->name, mnt->fullpath,
mnt->fs_ops->name, mnt_flag(mnt->flags));
}
}
return RT_NULL;
}
static void *seq_start(struct dfs_seq_file *seq, off_t *index)
{
off_t i = *index; // seq->index
return NULL + (i == 0);
}
static void seq_stop(struct dfs_seq_file *seq, void *data)
{
}
static void *seq_next(struct dfs_seq_file *seq, void *data, off_t *index)
{
/* data: The return value of the start or next*/
off_t i = *index + 1; // seq->index
*index = i;
return NULL;
}
static int seq_show(struct dfs_seq_file *seq, void *data)
{
/* data: The return value of the start or next*/
dfs_mnt_foreach(mnt_show, seq);
return 0;
}
static const struct dfs_seq_ops seq_ops = {
.start = seq_start,
.stop = seq_stop,
.next = seq_next,
.show = seq_show,
};
int proc_mounts_init(void)
{
struct proc_dentry *dentry = proc_create_data("mounts", 0, NULL, NULL, NULL);
if (dentry)
{
dentry->seq_ops = &seq_ops;
}
proc_release(dentry);
return 0;
}
INIT_ENV_EXPORT(proc_mounts_init);

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
#ifdef RT_USING_LWIP
#include "lwip/opt.h"
#endif
#if LWIP_ROUTE
extern int inet_route_foreach(void (*func)(const char *name, uint32_t ip_addr, uint32_t netmask, void *parameter), void *parameter);
#endif
static void *seq_start(struct dfs_seq_file *seq, off_t *index)
{
off_t i = *index; // seq->index
return NULL + (i == 0);
}
static void seq_stop(struct dfs_seq_file *seq, void *data)
{
}
static void *seq_next(struct dfs_seq_file *seq, void *data, off_t *index)
{
/* data: The return value of the start or next*/
off_t i = *index + 1; // seq->index
*index = i;
return NULL;
}
static void route_show(const char *name, uint32_t ip_addr, uint32_t netmask, void *parameter)
{
struct dfs_seq_file *seq = (struct dfs_seq_file *)parameter;
/* "Iface\tDestination\tGateway "
"\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
"\tWindow\tIRTT"); */
/* "%63s%lx%lx%X%d%d%d%lx%d%d%d\n" */
dfs_seq_printf(seq, "%s ", name);
dfs_seq_printf(seq, "%lx ", ip_addr);
dfs_seq_printf(seq, "%lx ", 0);
dfs_seq_printf(seq, "%X ", 1);
dfs_seq_printf(seq, "%d ", 0);
dfs_seq_printf(seq, "%d ", 0);
dfs_seq_printf(seq, "%d ", 0);
dfs_seq_printf(seq, "%lx ", netmask);
dfs_seq_printf(seq, "%d ", 0);
dfs_seq_printf(seq, "%d ", 0);
dfs_seq_printf(seq, "%d\n", 0);
}
static int seq_show(struct dfs_seq_file *seq, void *data)
{
/* data: The return value of the start or next*/
dfs_seq_printf(seq, "\n");
#if LWIP_ROUTE
inet_route_foreach(route_show, seq);
#endif
return 0;
}
static const struct dfs_seq_ops seq_ops = {
.start = seq_start,
.stop = seq_stop,
.next = seq_next,
.show = seq_show,
};
int proc_net_init(void)
{
struct proc_dentry *dentry;
dentry = proc_mkdir("net", NULL);
if (!dentry)
return -1;
proc_release(dentry);
dentry = proc_create_data("net/route", 0, NULL, NULL, NULL);
if (dentry)
{
dentry->seq_ops = &seq_ops;
}
proc_release(dentry);
return 0;
}
INIT_ENV_EXPORT(proc_net_init);

View File

@ -0,0 +1,215 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
#include <rthw.h>
#include <rtthread.h>
#include <string.h>
#define LIST_FIND_OBJ_NR 8
typedef struct
{
rt_list_t *list;
rt_list_t **array;
rt_uint8_t type;
int nr; /* input: max nr, can't be 0 */
int nr_out; /* out: got nr */
} list_get_next_t;
static void list_find_init(list_get_next_t *p, rt_uint8_t type, rt_list_t **array, int nr)
{
struct rt_object_information *info;
rt_list_t *list;
info = rt_object_get_information((enum rt_object_class_type)type);
list = &info->object_list;
p->list = list;
p->type = type;
p->array = array;
p->nr = nr;
p->nr_out = 0;
}
static rt_list_t *list_get_next(rt_list_t *current, list_get_next_t *arg)
{
int first_flag = 0;
rt_base_t level;
rt_list_t *node, *list;
rt_list_t **array;
struct rt_object_information *info;
int nr;
arg->nr_out = 0;
if (!arg->nr || !arg->type)
{
return (rt_list_t *)RT_NULL;
}
list = arg->list;
info = rt_list_entry(list, struct rt_object_information, object_list);
if (!current) /* find first */
{
node = list;
first_flag = 1;
}
else
{
node = current;
}
level = rt_spin_lock_irqsave(&info->spinlock);
if (!first_flag)
{
struct rt_object *obj;
/* The node in the list? */
obj = rt_list_entry(node, struct rt_object, list);
if ((obj->type & ~RT_Object_Class_Static) != arg->type)
{
rt_spin_unlock_irqrestore(&info->spinlock, level);
return (rt_list_t *)RT_NULL;
}
}
nr = 0;
array = arg->array;
while (1)
{
node = node->next;
if (node == list)
{
node = (rt_list_t *)RT_NULL;
break;
}
nr++;
*array++ = node;
if (nr == arg->nr)
{
break;
}
}
rt_spin_unlock_irqrestore(&info->spinlock, level);
arg->nr_out = nr;
return node;
}
static int show_info(struct dfs_seq_file *seq)
{
rt_base_t level;
list_get_next_t find_arg;
struct rt_object_information *info;
rt_list_t *obj_list[LIST_FIND_OBJ_NR];
rt_list_t *next = (rt_list_t *)RT_NULL;
list_find_init(&find_arg, RT_Object_Class_Device, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
info = rt_list_entry(find_arg.list, struct rt_object_information, object_list);
do
{
next = list_get_next(next, &find_arg);
{
int i;
for (i = 0; i < find_arg.nr_out; i++)
{
struct rt_object *obj;
struct rt_device *device;
obj = rt_list_entry(obj_list[i], struct rt_object, list);
level = rt_spin_lock_irqsave(&info->spinlock);
if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
{
rt_spin_unlock_irqrestore(&info->spinlock, level);
continue;
}
rt_spin_unlock_irqrestore(&info->spinlock, level);
device = (struct rt_device *)obj;
if (device->type == RT_Device_Class_Block)
{
struct rt_device_blk_geometry geometry = { 0 };
rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
dfs_seq_printf(seq, "%4d %7d %14llu %s\n", 0, 0,
geometry.sector_count, device->parent.name);
}
}
}
} while (next != (rt_list_t *)RT_NULL);
return 0;
}
static void *seq_start(struct dfs_seq_file *seq, off_t *index)
{
off_t i = *index; // seq->index
return NULL + (i == 0);
}
static void seq_stop(struct dfs_seq_file *seq, void *data)
{
}
static void *seq_next(struct dfs_seq_file *seq, void *data, off_t *index)
{
/* data: The return value of the start or next*/
off_t i = *index + 1; // seq->index
*index = i;
return NULL;
}
static int seq_show(struct dfs_seq_file *seq, void *data)
{
dfs_seq_puts(seq, "major minor #blocks name\n\n");
/* data: The return value of the start or next*/
show_info(seq);
return 0;
}
static const struct dfs_seq_ops seq_ops = {
.start = seq_start,
.stop = seq_stop,
.next = seq_next,
.show = seq_show,
};
int proc_partitions_init(void)
{
struct proc_dentry *dentry = proc_create_data("partitions", 0, NULL, NULL, NULL);
if (dentry)
{
dentry->seq_ops = &seq_ops;
}
proc_release(dentry);
return 0;
}
INIT_ENV_EXPORT(proc_partitions_init);

View File

@ -0,0 +1,449 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#define __RT_IPC_SOURCE__
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include "lwp_internal.h"
#include <dfs_dentry.h>
#include "lwp_internal.h"
#if defined(RT_USING_SMART)
#include "lwp.h"
#include "lwp_pid.h"
#include <lwp_user_mm.h>
struct pid_dentry
{
const char *name;
mode_t mode;
const struct dfs_file_ops *fops;
const struct proc_ops *ops;
const struct dfs_seq_ops *seq_ops;
int (*single_show)(struct dfs_seq_file *seq, void *data);
void *data;
};
static char stat_transform(int __stat)
{
switch (__stat)
{
case RT_THREAD_RUNNING:
return 'R';
default:
return 'T';
}
}
static int stat_single_show(struct dfs_seq_file *seq, void *data)
{
struct proc_dentry *dentry = (struct proc_dentry *)seq->file->vnode->data;
rt_list_t *list;
int mask = 0;
rt_thread_t thread;
rt_uint64_t user_time_lwp = 0;
rt_uint64_t system_time_lwp = 0;
int lwp_oncpu = RT_CPUS_NR;
int lwp_oncpu_ok = 0;
struct rt_lwp *lwp = RT_NULL;
char** argv = RT_NULL;
char *filename = RT_NULL;
char *dot = RT_NULL;
lwp_pid_lock_take();
lwp = lwp_from_pid_locked(dentry->pid);
argv = lwp_get_command_line_args(lwp);
if (lwp)
{
dfs_seq_printf(seq,"%d ",dentry->pid);
if (argv)
{
filename = strrchr(argv[0], '/');
dot = strchr(argv[0], '.');
if (filename != NULL)
{
filename++;
}
else
{
filename = argv[0];
}
if (dot != NULL)
{
*dot = '\0';
}
if (filename != NULL)
{
dfs_seq_printf(seq,"(%s) ", filename);
}
else
{
dfs_seq_printf(seq,"(%s) ", argv[0]);
}
lwp_free_command_line_args(argv);
}
else
{
dfs_seq_printf(seq,"(%s) ", "");
}
if (lwp->terminated)
{
dfs_seq_printf(seq,"%c ",'Z');
}
else
{
list = lwp->t_grp.next;
while (list != &lwp->t_grp)
{
thread = rt_list_entry(list, struct rt_thread, sibling);
user_time_lwp = user_time_lwp + thread->user_time;
system_time_lwp = system_time_lwp + thread->system_time;
#if RT_CPUS_NR > 1
#define ONCPU(thread) RT_SCHED_CTX(thread).oncpu
#else
#define ONCPU(thread) 0
#endif
if (lwp_oncpu_ok == 0)
{
lwp_oncpu = ONCPU(thread);
lwp_oncpu_ok = 1;
}
if (stat_transform(RT_SCHED_CTX(thread).stat) == 'R')
{
lwp_oncpu = ONCPU(thread);
mask = 1;
}
list = list->next;
}
if (mask == 1)
{
dfs_seq_printf(seq,"%c ",'R');
}
else
{
dfs_seq_printf(seq,"%c ",'S');
}
}
lwp_pid_lock_release();
if (lwp->parent != NULL)
dfs_seq_printf(seq,"%d ",lwp->parent->pid);
else
dfs_seq_printf(seq,"0 ");
dfs_seq_printf(seq, "1 1 0 -1 4194560 48245 133976064 732 425574 ");
dfs_seq_printf(seq,"%llu ",user_time_lwp);//utime
dfs_seq_printf(seq,"%llu ",system_time_lwp);//stime
dfs_seq_printf(seq, "1204291 518742 20 0 1 0 50 ");
dfs_seq_printf(seq, "%d ",rt_aspace_count_vsz(lwp->aspace));//VSZ
dfs_seq_printf(seq, "1422 18446744073709551615 ");
dfs_seq_printf(seq, "1 1 0 0 0 0 671173123 4096 1260 0 0 0 17 ");
dfs_seq_printf(seq, "%d ", lwp_oncpu);//CPU
dfs_seq_printf(seq, "0 0 0 0 0 0 0 0 0 0 0 0 0");
dfs_seq_printf(seq,"\n");
}
else
{
lwp_pid_lock_release();
}
return 0;
}
static int cmdline_single_show(struct dfs_seq_file *seq, void *data)
{
struct proc_dentry *dentry = (struct proc_dentry *)seq->file->vnode->data;
struct rt_lwp *lwp;
char** argv;
lwp_pid_lock_take();
lwp = lwp_from_pid_locked(dentry->pid);
argv = lwp_get_command_line_args(lwp);
lwp_pid_lock_release();
if (argv)
{
for (int i = 0; argv[i] != NULL; i++)
{
dfs_seq_printf(seq, "%s ", argv[i]);
}
dfs_seq_puts(seq, "\n");
lwp_free_command_line_args(argv);
}
else
{
dfs_seq_puts(seq, "error\n");
}
return 0;
}
struct proc_dentry *proc_pid_fd_lookup(struct proc_dentry *parent, const char *name)
{
struct proc_dentry *dentry = RT_NULL;
char num[DIRENT_NAME_MAX];
struct rt_lwp *lwp;
struct dfs_fdtable *table;
lwp_pid_lock_take();
lwp = lwp_from_pid_locked(parent->pid);
table = lwp ? &lwp->fdt : RT_NULL;
lwp_pid_lock_release();
if (!table)
{
return RT_NULL;
}
dfs_file_lock();
for (int i = 0; i < table->maxfd; i++)
{
struct dfs_file *file = table->fds[i];
if (file)
{
rt_snprintf(num, DIRENT_NAME_MAX, "%d", i);
if (rt_strcmp(num, name) == 0)
{
dentry = rt_calloc(1, sizeof(struct proc_dentry));
if (dentry)
{
dentry->mode = (S_IFLNK | (S_IRUSR | S_IRGRP | S_IROTH) | (S_IWUSR | S_IWGRP | S_IWOTH) | (S_IXUSR | S_IXGRP | S_IXOTH));
dentry->ref_count = 1;
dentry->name = rt_strdup(name);
dentry->data = (void *)dfs_dentry_full_path(file->dentry);
if (dentry->data == RT_NULL)
{
//todo add vnode->data
if (file->vnode->type == FT_SOCKET)
dentry->data = (void *)rt_strdup("socket");
else if (file->vnode->type == FT_USER)
dentry->data = (void *)rt_strdup("user");
else if (file->vnode->type == FT_DEVICE)
dentry->data = (void *)rt_strdup("device");
else
dentry->data = (void *)rt_strdup("unknown");
}
dentry->pid = parent->pid;
break;
}
}
}
}
dfs_file_unlock();
return dentry;
}
int proc_pid_fd_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
{
int ret = 0, index = 0;
struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
struct rt_lwp *lwp;
struct dfs_fdtable *table;
lwp_pid_lock_take();
lwp = lwp_from_pid_locked(entry->pid);
LWP_LOCK(lwp);
table = lwp ? &lwp->fdt : RT_NULL;
if (!table->fds)
{
LWP_UNLOCK(lwp);
lwp_pid_lock_release();
return 0;
}
count = (count / sizeof(struct dirent));
if (count == 0)
{
LWP_UNLOCK(lwp);
lwp_pid_lock_release();
return -EINVAL;
}
dfs_file_lock();
for (int i = 0; i < table->maxfd; i++)
{
struct dfs_file *df = table->fds[i];
if (df)
{
if (index >= file->fpos)
{
struct dirent *d = dirp + index - file->fpos;
d->d_type = DT_SYMLINK;
d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
rt_snprintf(d->d_name, DIRENT_NAME_MAX, "%d", i);
d->d_namlen = rt_strlen(d->d_name);
ret++;
}
index++;
if (index - file->fpos >= count)
{
break;
}
}
}
dfs_file_unlock();
LWP_UNLOCK(lwp);
lwp_pid_lock_release();
if (ret > 0)
{
file->fpos = index;
ret = ret * sizeof(struct dirent);
}
return ret;
}
static const struct proc_ops proc_pid_fd_ops = {
.lookup = proc_pid_fd_lookup,
};
static const struct dfs_file_ops proc_pid_fd_fops = {
.getdents = proc_pid_fd_getdents,
};
int proc_pid_exe_readlink(struct proc_dentry *dentry, char *buf, int len)
{
struct rt_lwp *lwp;
lwp = lwp_self();
len = rt_snprintf(buf, len, "%s", lwp ? lwp->exe_file : "null");
return len;
}
static const struct proc_ops proc_pid_exe_ops = {
.readlink = proc_pid_exe_readlink,
};
int proc_pid_cwd_readlink(struct proc_dentry *dentry, char *buf, int len)
{
struct rt_lwp *lwp;
lwp = lwp_self();
len = rt_snprintf(buf, len, "%s", lwp ? lwp->working_directory : "null");
return len;
}
static const struct proc_ops proc_pid_cwd_ops = {
.readlink = proc_pid_cwd_readlink,
};
static struct pid_dentry pid_dentry_base[] = {
{"cmdline", S_IFREG | S_IRUSR | S_IRGRP | S_IROTH, 0, 0, 0, cmdline_single_show, 0},
{"cwd", S_IFLNK | S_IRUSR | S_IXUSR, 0, &proc_pid_cwd_ops, 0, 0},
{"exe", S_IFLNK | S_IRUSR | S_IXUSR, 0, &proc_pid_exe_ops, 0, 0},
{"fd", S_IFDIR | S_IRUSR | S_IXUSR, &proc_pid_fd_fops, &proc_pid_fd_ops, 0, 0, 0},
{"mounts", S_IFLNK | S_IRUSR | S_IXUSR, 0, 0, 0, 0, "/proc/mounts"},
{"stat", S_IFREG | S_IRUSR | S_IRGRP | S_IROTH, 0, 0, 0, stat_single_show, 0},
};
int proc_pid(int pid)
{
char pid_str[64] = {0};
struct proc_dentry *dentry;
rt_snprintf(pid_str, 64, "%d", pid);
pid_str[63] = 0;
dentry = proc_mkdir(pid_str, 0);
if (dentry)
{
struct proc_dentry *ent;
dentry->pid = pid;
for (int j = 0; j < sizeof(pid_dentry_base) / sizeof(struct pid_dentry); j++)
{
if (S_ISDIR(pid_dentry_base[j].mode))
{
ent = proc_mkdir_data(pid_dentry_base[j].name, pid_dentry_base[j].mode, dentry,
pid_dentry_base[j].fops, pid_dentry_base[j].data);
}
else if (S_ISLNK(pid_dentry_base[j].mode))
{
if (pid_dentry_base[j].data == RT_NULL)
{
pid_dentry_base[j].data = "NULL";
}
ent = proc_symlink(pid_dentry_base[j].name, dentry, pid_dentry_base[j].data);
}
else
{
ent = proc_create_data(pid_dentry_base[j].name, pid_dentry_base[j].mode, dentry,
pid_dentry_base[j].fops, pid_dentry_base[j].data);
}
if (ent)
{
if (pid_dentry_base[j].ops)
{
ent->ops = pid_dentry_base[j].ops;
}
if (pid_dentry_base[j].seq_ops)
{
ent->seq_ops = pid_dentry_base[j].seq_ops;
}
if (pid_dentry_base[j].single_show)
{
ent->single_show = pid_dentry_base[j].single_show;
}
proc_release(ent);
}
}
proc_release(dentry);
}
return 0;
}
int msh_proc_pid(int argc, char **argv)
{
if (argc > 1)
{
for (int i = 1; i <= argc - 1; i++)
{
proc_pid(atoi(argv[i]));
}
}
return 0;
}
MSH_CMD_EXPORT_ALIAS(msh_proc_pid, proc_pid, proc pid);
#endif

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
#if defined(RT_USING_SMART)
#include <lwp.h>
int proc_self_readlink(struct proc_dentry *dentry, char *buf, int len)
{
struct rt_lwp *lwp = RT_NULL;
lwp = lwp_self();
if (lwp)
{
rt_snprintf(buf, len, "%d", lwp_to_pid(lwp));
buf[len - 1] = 0;
return rt_strlen(buf);
}
else
{
rt_snprintf(buf, len, "null");
buf[len - 1] = 0;
return rt_strlen(buf);
}
return -1;
}
static const struct proc_ops proc_pid_fd_ops = {
.readlink = proc_self_readlink,
};
int proc_self_init(void)
{
struct proc_dentry *ent;
ent = proc_symlink("self", NULL, "NULL");
if (ent)
{
ent->ops = &proc_pid_fd_ops;
}
proc_release(ent);
return 0;
}
INIT_ENV_EXPORT(proc_self_init);
#endif

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
static void *seq_start(struct dfs_seq_file *seq, off_t *index)
{
off_t i = *index; // seq->index
return NULL + (i == 0);
}
static void seq_stop(struct dfs_seq_file *seq, void *data)
{
}
static void *seq_next(struct dfs_seq_file *seq, void *data, off_t *index)
{
/* data: The return value of the start or next*/
off_t i = *index + 1; // seq->index
*index = i;
return NULL;
}
static int seq_show(struct dfs_seq_file *seq, void *data)
{
int i;
rt_cpu_t pcpu;
rt_uint64_t user_total = 0;
rt_uint64_t system_total = 0;
rt_uint64_t idle_total = 0;
for (i = 0; i < RT_CPUS_NR; i++)
{
pcpu = rt_cpu_index(i);
user_total = user_total + pcpu->cpu_stat.user;
system_total = system_total + pcpu->cpu_stat.system;
idle_total = idle_total + pcpu->cpu_stat.idle;
}
dfs_seq_printf(seq, "cpu %llu 0 %llu %llu 0 0 0 0 0 0\n", user_total, system_total, idle_total);
for (i = 0; i < RT_CPUS_NR; i++)
{
pcpu = rt_cpu_index(i);
dfs_seq_printf(seq, "cpu%d ",i);
dfs_seq_printf(seq, "%llu ",pcpu->cpu_stat.user);//user
dfs_seq_printf(seq, "0 ");//nice
dfs_seq_printf(seq, "%llu ",pcpu->cpu_stat.system);//system
dfs_seq_printf(seq, "%llu ",pcpu->cpu_stat.idle);//idle
dfs_seq_printf(seq, "0 ");//iowait
dfs_seq_printf(seq, "0 ");//irq
dfs_seq_printf(seq, "0 ");//softirq
dfs_seq_printf(seq, "0 0 0\n");//steal,guest,guest_nice
}
return 0;
}
static const struct dfs_seq_ops seq_ops = {
.start = seq_start,
.stop = seq_stop,
.next = seq_next,
.show = seq_show,
};
rt_weak const struct dfs_seq_ops *stat_get_seq_ops(void)
{
return &seq_ops;
}
static int proc_open(struct dfs_file *file)
{
return dfs_seq_open(file, stat_get_seq_ops());
}
static int proc_close(struct dfs_file *file)
{
return dfs_seq_release(file);
}
static const struct dfs_file_ops file_ops = {
.open = proc_open,
.read = dfs_seq_read,
.lseek = dfs_seq_lseek,
.close = proc_close,
};
int proc_stat_init(void)
{
struct proc_dentry *dentry = proc_create_data("stat", 0, NULL, &file_ops, NULL);
proc_release(dentry);
return 0;
}
INIT_ENV_EXPORT(proc_stat_init);

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
static void *seq_start(struct dfs_seq_file *seq, off_t *index)
{
off_t i = *index; // seq->index
return NULL + (i == 0);
}
static void seq_stop(struct dfs_seq_file *seq, void *data)
{
}
static void *seq_next(struct dfs_seq_file *seq, void *data, off_t *index)
{
/* data: The return value of the start or next*/
off_t i = *index + 1; // seq->index
*index = i;
return NULL;
}
static int seq_show(struct dfs_seq_file *seq, void *data)
{
/* data: The return value of the start or next*/
dfs_seq_puts(seq, "todo\n");
return 0;
}
static const struct dfs_seq_ops seq_ops = {
.start = seq_start,
.stop = seq_stop,
.next = seq_next,
.show = seq_show,
};
void proc_tty_register_driver(void *driver)
{
//todo
}
void proc_tty_unregister_driver(void *driver)
{
//todo
}
int proc_tty_init(void)
{
struct proc_dentry *dentry;
dentry = proc_mkdir("tty", NULL);
if (!dentry)
return -1;
proc_release(dentry);
dentry = proc_mkdir("tty/ldisc", NULL);
proc_release(dentry);
dentry = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL);
proc_release(dentry);
dentry = proc_create_data("tty/ldiscs", 0, NULL, NULL, NULL);
if (dentry)
{
dentry->seq_ops = &seq_ops;
}
proc_release(dentry);
dentry = proc_create_data("tty/drivers", 0, NULL, NULL, NULL);
if (dentry)
{
dentry->seq_ops = &seq_ops;
}
proc_release(dentry);
return 0;
}
INIT_ENV_EXPORT(proc_tty_init);

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
static int single_show(struct dfs_seq_file *seq, void *data)
{
dfs_seq_printf(seq, "%lu.%02lu %lu.%02lu\n",
(unsigned long)rt_tick_get_millisecond() / 1000, (unsigned long)(rt_tick_get_millisecond() % 1000) / 100,
(unsigned long)rt_tick_get_millisecond() / 1000, (unsigned long)(rt_tick_get_millisecond() % 1000) / 100);
return 0;
}
int proc_uptime_init(void)
{
struct proc_dentry *dentry = proc_create_single_data("uptime", 0, NULL, single_show, NULL);
proc_release(dentry);
return 0;
}
INIT_ENV_EXPORT(proc_uptime_init);

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "proc.h"
#include "procfs.h"
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs_dentry.h>
static int single_show(struct dfs_seq_file *seq, void *data)
{
dfs_seq_puts(seq, "\n \\ | /\n");
#ifdef RT_USING_SMART
dfs_seq_puts(seq, "- RT - Thread Smart Operating System\n");
#else
dfs_seq_puts(seq, "- RT - Thread Operating System\n");
#endif
dfs_seq_printf(seq, " / | \\ %d.%d.%d build %s %s\n",
(rt_int32_t)RT_VERSION_MAJOR, (rt_int32_t)RT_VERSION_MINOR, (rt_int32_t)RT_VERSION_PATCH,
__DATE__, __TIME__);
dfs_seq_puts(seq, " 2006 - 2022 Copyright by RT-Thread team\n");
return 0;
}
int proc_version_init(void)
{
struct proc_dentry *dentry = proc_create_single_data("version", 0, NULL, single_show, NULL);
proc_release(dentry);
return 0;
}
INIT_ENV_EXPORT(proc_version_init);

View File

@ -0,0 +1,447 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include <rthw.h>
#include <rtdbg.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs.h>
#include <dfs_fs.h>
#include <dfs_file.h>
#include <dfs_posix.h>
#include <dfs_mnt.h>
#include <dfs_dentry.h>
#include "proc.h"
#include "procfs.h"
#define PROC_DEBUG(...) //rt_kprintf
static int dfs_procfs_open(struct dfs_file *file)
{
rt_err_t ret = RT_EOK;
struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
RT_ASSERT(file->ref_count > 0);
// this file is opened and in an fdtable
if (file->ref_count > 1)
{
file->fpos = 0;
return ret;
}
if (entry->fops && entry->fops->open)
{
ret = entry->fops->open(file);
}
PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
return ret;
}
static int dfs_procfs_close(struct dfs_file *file)
{
rt_err_t ret = RT_EOK;
struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
RT_ASSERT(file->vnode->ref_count > 0);
if (file->vnode->ref_count > 1)
{
return ret;
}
if (entry && entry->fops && entry->fops->close)
{
ret = entry->fops->close(file);
}
PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
return ret;
}
static ssize_t dfs_procfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
{
ssize_t ret = -RT_ERROR;
struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
if (entry && entry->fops && entry->fops->read)
{
ret = entry->fops->read(file, buf, count, pos);
}
PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
return ret;
}
static ssize_t dfs_procfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
{
ssize_t ret = -RT_ERROR;
struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
if (entry && entry->fops && entry->fops->write)
{
ret = entry->fops->write(file, buf, count, pos);
}
PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
return ret;
}
static int dfs_procfs_ioctl(struct dfs_file *file, int cmd, void *args)
{
int ret = -RT_ERROR;
struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
if (entry && entry->fops && entry->fops->ioctl)
{
ret = entry->fops->ioctl(file, cmd, args);
}
PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
return ret;
}
static int dfs_procfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
{
int ret = 0;
rt_uint32_t index = 0;
struct dirent *d;
struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
if (entry)
{
struct proc_dentry *iter = RT_NULL, *tmp;
/* make integer count */
count = (count / sizeof(struct dirent));
if (count == 0)
{
return -EINVAL;
}
dfs_vfs_for_each_subnode(iter, tmp, entry, node)
{
if (iter == RT_NULL)
{
break;
}
if (index >= file->fpos)
{
d = dirp + index - file->fpos;
if (S_ISDIR(entry->mode))
{
d->d_type = DT_DIR;
}
else if (S_ISLNK(entry->mode))
{
d->d_type = DT_SYMLINK;
}
else
{
d->d_type = DT_REG;
}
d->d_namlen = rt_strlen(iter->name);
d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
rt_strncpy(d->d_name, iter->name, rt_strlen(iter->name) + 1);
ret ++;
}
index++;
if (index - file->fpos >= count)
{
break;
}
}
if (ret > 0)
{
file->fpos = index;
}
if (entry->fops && entry->fops->getdents && ret < count)
{
int r;
file->fpos -= index;
r = entry->fops->getdents(file, dirp + ret, (count - ret) * sizeof(struct dirent));
ret = ret * sizeof(struct dirent);
if (r > 0)
{
ret += r;
}
file->fpos += index;
}
else
{
ret = ret * sizeof(struct dirent);
}
}
PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
return ret;
}
static int dfs_procfs_poll(struct dfs_file *file, struct rt_pollreq *req)
{
int ret = -RT_ERROR;
struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
if (entry && entry->fops && entry->fops->poll)
{
ret = entry->fops->poll(file, req);
}
PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
return ret;
}
static int dfs_procfs_flush(struct dfs_file *file)
{
int ret = -RT_ERROR;
struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
if (entry && entry->fops && entry->fops->flush)
{
ret = entry->fops->flush(file);
}
PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, file->dentry->pathname, ret);
return ret;
}
static int dfs_procfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data)
{
RT_ASSERT(mnt != RT_NULL);
return RT_EOK;
}
static int dfs_procfs_umount(struct dfs_mnt *mnt)
{
RT_ASSERT(mnt != RT_NULL);
return RT_EOK;
}
static int dfs_procfs_readlink(struct dfs_dentry *dentry, char *buf, int len)
{
int ret = 0;
struct proc_dentry *entry = dfs_proc_find(dentry->pathname);
if (entry)
{
if (S_ISLNK(entry->mode) && entry->data)
{
if (entry->ops && entry->ops->readlink)
{
ret = entry->ops->readlink(entry, buf, len);
}
else
{
rt_strncpy(buf, (const char *)entry->data, len);
buf[len - 1] = '\0';
ret = rt_strlen(buf);
}
}
proc_release(entry);
}
PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, dentry->pathname, ret);
return ret;
}
static int dfs_procfs_unlink(struct dfs_dentry *dentry)
{
PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, dentry->pathname, -1);
return -RT_ERROR;
}
static int dfs_procfs_stat(struct dfs_dentry *dentry, struct stat *st)
{
int ret = RT_EOK;
struct dfs_vnode *vnode;
if (dentry && dentry->vnode)
{
vnode = dentry->vnode;
st->st_dev = (dev_t)(dentry->mnt->dev_id);
st->st_ino = (ino_t)dfs_dentry_full_path_crc32(dentry);
st->st_gid = vnode->gid;
st->st_uid = vnode->uid;
st->st_mode = vnode->mode;
st->st_nlink = vnode->nlink;
st->st_size = vnode->size;
st->st_mtim.tv_nsec = vnode->mtime.tv_nsec;
st->st_mtim.tv_sec = vnode->mtime.tv_sec;
st->st_ctim.tv_nsec = vnode->ctime.tv_nsec;
st->st_ctim.tv_sec = vnode->ctime.tv_sec;
st->st_atim.tv_nsec = vnode->atime.tv_nsec;
st->st_atim.tv_sec = vnode->atime.tv_sec;
}
PROC_DEBUG(" %s %d >> %s ret: %d\n", __func__, __LINE__, dentry->pathname, ret);
return ret;
}
static int dfs_procfs_statfs(struct dfs_mnt *mnt, struct statfs *buf)
{
if (mnt && buf)
{
buf->f_bsize = 512;
buf->f_blocks = 2048 * 64; // 64M
buf->f_bfree = buf->f_blocks;
buf->f_bavail = buf->f_bfree;
}
PROC_DEBUG(" %s %d\n", __func__, __LINE__);
return RT_EOK;
}
static struct dfs_vnode *dfs_procfs_lookup(struct dfs_dentry *dentry)
{
struct dfs_vnode *vnode = RT_NULL;
struct proc_dentry *entry = dfs_proc_find(dentry->pathname);
if (entry)
{
vnode = dfs_vnode_create();
if (vnode)
{
vnode->nlink = 1;
vnode->size = 0;
if (S_ISDIR(entry->mode))
{
vnode->mode = entry->mode;
vnode->type = FT_DIRECTORY;
}
else if (S_ISLNK(entry->mode))
{
vnode->mode = entry->mode;
vnode->type = FT_SYMLINK;
}
else
{
vnode->mode = entry->mode;
vnode->type = FT_REGULAR;
}
vnode->data = entry;
vnode->mnt = dentry->mnt;
}
proc_release(entry);
}
PROC_DEBUG(" %s %d >> %s\n", __func__, __LINE__, dentry->pathname);
return vnode;
}
static struct dfs_vnode *dfs_procfs_create_vnode(struct dfs_dentry *dentry, int type, mode_t mode)
{
return RT_NULL;
}
static int dfs_procfs_free_vnode(struct dfs_vnode *vnode)
{
return 0;
}
static const struct dfs_file_ops _procfs_fops =
{
.open = dfs_procfs_open,
.close = dfs_procfs_close,
.lseek = generic_dfs_lseek,
.read = dfs_procfs_read,
.write = dfs_procfs_write,
.ioctl = dfs_procfs_ioctl,
.getdents = dfs_procfs_getdents,
.poll = dfs_procfs_poll,
.flush = dfs_procfs_flush,
};
static const struct dfs_filesystem_ops _procfs_ops =
{
.name = "procfs",
.default_fops = &_procfs_fops,
.mount = dfs_procfs_mount,
.umount = dfs_procfs_umount,
.readlink = dfs_procfs_readlink,
.unlink = dfs_procfs_unlink,
.stat = dfs_procfs_stat,
.statfs = dfs_procfs_statfs,
.lookup = dfs_procfs_lookup,
.create_vnode = dfs_procfs_create_vnode,
.free_vnode = dfs_procfs_free_vnode,
};
static struct dfs_filesystem_type _procfs =
{
.fs_ops = &_procfs_ops,
};
int dfs_procfs_init(void)
{
/* register procfs file system */
dfs_register(&_procfs);
return 0;
}
INIT_COMPONENT_EXPORT(dfs_procfs_init);
int proc_read_data(struct dfs_file *file, void *buf, size_t count, off_t *pos)
{
if (file->fpos >= file->vnode->size)
{
return 0;
}
if (file->data)
{
count = file->vnode->size - file->fpos >= count ? count : file->vnode->size - file->fpos;
rt_strncpy(buf, file->data + file->fpos, count);
file->fpos += count;
*pos = file->fpos;
}
else
{
return 0;
}
return count;
}

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#ifndef __PROC_FS_H__
#define __PROC_FS_H__
#include <dfs_file.h>
int dfs_procfs_init(void);
int proc_read_data(struct dfs_file *file, void *buf, size_t count, off_t *pos);
#endif

View File

@ -262,7 +262,7 @@ ptsno_t ptyfs_register_pts(rt_device_t ptmx, rt_device_t pts)
pts_file = rt_calloc(1, sizeof(struct ptyfs_file));
if (pts_file)
{
snprintf(pts_file->basename, DIRENT_NAME_MAX, "%lu", rc);
snprintf(pts_file->basename, DIRENT_NAME_MAX, "%lu", (unsigned long)rc);
ptyfile_init(pts_file, sb, 0, PTYFS_TYPE_FILE_SLAVE,
PTS_DEFAULT_FILE_MODE, pts);
ptyfile_add_to_root(sb, pts_file);
@ -296,7 +296,7 @@ rt_err_t ptyfs_unregister_pts(rt_device_t ptmx, ptsno_t ptsno)
else
{
/* get path and findout device */
snprintf(path_buf, sizeof(path_buf), "%lu", ptsno);
snprintf(path_buf, sizeof(path_buf), "%lu", (unsigned long)ptsno);
pts_file = ptyfile_lookup(sb, path_buf);
if (pts_file)
{

View File

@ -365,6 +365,7 @@ static const struct dfs_file_ops _rom_fops =
{
.open = dfs_romfs_open,
.close = dfs_romfs_close,
.ioctl = dfs_romfs_ioctl,
.lseek = generic_dfs_lseek,
.read = dfs_romfs_read,
.getdents = dfs_romfs_getdents,

View File

@ -99,15 +99,13 @@ static int _get_subdir(const char *path, char *name)
static int _free_subdir(struct tmpfs_file *dfile)
{
struct tmpfs_file *file;
rt_list_t *list, *temp_list;
struct tmpfs_file *file = RT_NULL, *tmp;
struct tmpfs_sb *superblock;
RT_ASSERT(dfile->type == TMPFS_TYPE_DIR);
rt_list_for_each_safe(list, temp_list, &dfile->subdirs)
dfs_vfs_for_each_subnode(file, tmp, dfile, node)
{
file = rt_list_entry(list, struct tmpfs_file, sibling);
if (file->type == TMPFS_TYPE_DIR)
{
_free_subdir(file);
@ -122,7 +120,7 @@ static int _free_subdir(struct tmpfs_file *dfile)
RT_ASSERT(superblock != NULL);
rt_spin_lock(&superblock->lock);
rt_list_remove(&(file->sibling));
dfs_vfs_remove_node(&file->node);
rt_spin_unlock(&superblock->lock);
rt_free(file);
@ -141,13 +139,11 @@ static int dfs_tmpfs_mount(struct dfs_mnt *mnt,
{
superblock->df_size = sizeof(struct tmpfs_sb);
superblock->magic = TMPFS_MAGIC;
rt_list_init(&superblock->sibling);
superblock->root.name[0] = '/';
superblock->root.sb = superblock;
superblock->root.type = TMPFS_TYPE_DIR;
rt_list_init(&superblock->root.sibling);
rt_list_init(&superblock->root.subdirs);
dfs_vfs_init_node(&superblock->root.node);
rt_spin_lock_init(&superblock->lock);
@ -236,8 +232,7 @@ struct tmpfs_file *dfs_tmpfs_lookup(struct tmpfs_sb *superblock,
{
const char *subpath, *curpath, *filename = RT_NULL;
char subdir_name[TMPFS_NAME_MAX];
struct tmpfs_file *file, *curfile;
rt_list_t *list;
struct tmpfs_file *file, *curfile, *tmp;
subpath = path;
while (*subpath == '/' && *subpath)
@ -265,9 +260,8 @@ find_subpath:
rt_spin_lock(&superblock->lock);
rt_list_for_each(list, &curfile->subdirs)
dfs_vfs_for_each_subnode(file, tmp, curfile, node)
{
file = rt_list_entry(list, struct tmpfs_file, sibling);
if (filename) /* find file */
{
if (rt_strcmp(file->name, filename) == 0)
@ -503,8 +497,7 @@ static int dfs_tmpfs_getdents(struct dfs_file *file,
{
rt_size_t index, end;
struct dirent *d;
struct tmpfs_file *d_file, *n_file;
rt_list_t *list;
struct tmpfs_file *d_file, *n_file, *tmp;
struct tmpfs_sb *superblock;
d_file = (struct tmpfs_file *)file->vnode->data;
@ -527,9 +520,8 @@ static int dfs_tmpfs_getdents(struct dfs_file *file,
index = 0;
count = 0;
rt_list_for_each(list, &d_file->subdirs)
dfs_vfs_for_each_subnode(n_file, tmp, d_file, node)
{
n_file = rt_list_entry(list, struct tmpfs_file, sibling);
if (index >= (rt_size_t)file->fpos)
{
d = dirp + count;
@ -573,7 +565,7 @@ static int dfs_tmpfs_unlink(struct dfs_dentry *dentry)
return -ENOENT;
rt_spin_lock(&superblock->lock);
rt_list_remove(&(d_file->sibling));
dfs_vfs_remove_node(&d_file->node);
rt_spin_unlock(&superblock->lock);
if (rt_atomic_load(&(dentry->ref_count)) == 1)
@ -631,13 +623,13 @@ static int dfs_tmpfs_rename(struct dfs_dentry *old_dentry, struct dfs_dentry *ne
RT_ASSERT(p_file != NULL);
rt_spin_lock(&superblock->lock);
rt_list_remove(&(d_file->sibling));
dfs_vfs_remove_node(&d_file->node);
rt_spin_unlock(&superblock->lock);
strncpy(d_file->name, file_name, TMPFS_NAME_MAX);
rt_spin_lock(&superblock->lock);
rt_list_insert_after(&(p_file->subdirs), &(d_file->sibling));
dfs_vfs_append_node(&p_file->node, &d_file->node);
rt_spin_unlock(&superblock->lock);
rt_free(parent_path);
@ -745,8 +737,7 @@ static struct dfs_vnode *dfs_tmpfs_create_vnode(struct dfs_dentry *dentry, int t
strncpy(d_file->name, file_name, TMPFS_NAME_MAX);
rt_list_init(&(d_file->subdirs));
rt_list_init(&(d_file->sibling));
dfs_vfs_init_node(&d_file->node);
d_file->data = NULL;
d_file->size = 0;
d_file->sb = superblock;
@ -767,7 +758,7 @@ static struct dfs_vnode *dfs_tmpfs_create_vnode(struct dfs_dentry *dentry, int t
#endif
}
rt_spin_lock(&superblock->lock);
rt_list_insert_after(&(p_file->subdirs), &(d_file->sibling));
dfs_vfs_append_node(&p_file->node, &d_file->node);
rt_spin_unlock(&superblock->lock);
vnode->mnt = dentry->mnt;

View File

@ -12,6 +12,7 @@
#define __DFS_TMPFS_H__
#include <rtthread.h>
#include <dfs_vfs.h>
#define TMPFS_NAME_MAX 32
#define TMPFS_MAGIC 0x0B0B0B0B
@ -25,8 +26,7 @@ struct tmpfs_file
{
rt_uint32_t type; /* file type */
char name[TMPFS_NAME_MAX]; /* file name */
rt_list_t subdirs; /* file subdir list */
rt_list_t sibling; /* file sibling list */
struct dfs_vfs_node node; /* file node in the tmpfs */
struct tmpfs_sb *sb; /* superblock ptr */
rt_uint8_t *data; /* file date ptr */
rt_size_t size; /* file size */

View File

@ -20,6 +20,38 @@ extern "C"
{
#endif
#define MS_RDONLY 1
#define MS_NOSUID 2
#define MS_NODEV 4
#define MS_NOEXEC 8
#define MS_SYNCHRONOUS 16
#define MS_REMOUNT 32
#define MS_MANDLOCK 64
#define MS_DIRSYNC 128
#define MS_NOATIME 1024
#define MS_NODIRATIME 2048
#define MS_BIND 4096
#define MS_MOVE 8192
#define MS_REC 16384
#define MS_SILENT 32768
#define MS_POSIXACL (1<<16)
#define MS_UNBINDABLE (1<<17)
#define MS_PRIVATE (1<<18)
#define MS_SLAVE (1<<19)
#define MS_SHARED (1<<20)
#define MS_RELATIME (1<<21)
#define MS_KERNMOUNT (1<<22)
#define MS_I_VERSION (1<<23)
#define MS_STRICTATIME (1<<24)
#define MS_LAZYTIME (1<<25)
#define MS_NOREMOTELOCK (1<<27)
#define MS_NOSEC (1<<28)
#define MS_BORN (1<<29)
#define MS_ACTIVE (1<<30)
#define MS_NOUSER (1U<<31)
#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|MS_LAZYTIME)
/* file system partition table */
struct dfs_partition
{
@ -87,6 +119,7 @@ int dfs_unregister(struct dfs_filesystem_type *fs);
int dfs_register(struct dfs_filesystem_type *fs);
const char *dfs_filesystem_get_mounted_path(struct rt_device *device);
int dfs_remount(const char *path, rt_ubase_t flags, void *data);
int dfs_mount(const char *device_name,
const char *path,
const char *filesystemtype,

View File

@ -39,6 +39,8 @@ struct dfs_mnt
#define MNT_IS_UMOUNT 0x8 /* the mnt is unmount */
#define MNT_IS_LOCKED 0x10 /* the mnt is locked */
#define MNT_FORCE 0x20 /* the mnt force unmount */
#define MNT_LAZY_UMNT 0x40 /* the mnt has pending umount */
#define MNT_RDONLY 0x80 /* the mnt is read only */
rt_atomic_t ref_count; /* reference count */
@ -60,9 +62,16 @@ const char *dfs_mnt_get_mounted_path(struct rt_device *device);
struct dfs_mnt* dfs_mnt_ref(struct dfs_mnt* mnt);
int dfs_mnt_unref(struct dfs_mnt* mnt);
int dfs_mnt_umount(struct dfs_mnt *mnt, int flags);
int dfs_mnt_setflags(struct dfs_mnt *mnt, int flags);
rt_bool_t dfs_mnt_has_child_mnt(struct dfs_mnt *mnt, const char* fullpath);
int dfs_mnt_foreach(struct dfs_mnt* (*func)(struct dfs_mnt *mnt, void *parameter), void *parameter);
int dfs_mnt_umount_iter(rt_bool_t (*filter)(struct dfs_mnt *mnt, void *parameter), void *parameter);
typedef void (*dfs_mnt_umnt_cb_t)(struct dfs_mnt *mnt);
RT_OBJECT_HOOKLIST_DECLARE(dfs_mnt_umnt_cb_t, dfs_mnt_umnt);
#ifdef __cplusplus
}

View File

@ -118,6 +118,7 @@ int dfs_aspace_mmap_write(struct dfs_file *file, struct rt_varea *varea, void *d
void dfs_pcache_release(size_t count);
void dfs_pcache_unmount(struct dfs_mnt *mnt);
void dfs_pcache_clean(struct dfs_mnt *mnt);
#ifdef __cplusplus
}

View File

@ -56,7 +56,7 @@ static inline void dfs_seq_setwidth(struct dfs_seq_file *seq, size_t size)
int dfs_seq_open(struct dfs_file *file, const struct dfs_seq_ops *ops);
ssize_t dfs_seq_read(struct dfs_file *file, void *buf, size_t size, off_t *pos);
ssize_t dfs_seq_lseek(struct dfs_file *file, off_t offset, int whence);
off_t dfs_seq_lseek(struct dfs_file *file, off_t offset, int whence);
int dfs_seq_release(struct dfs_file *file);
int dfs_seq_write(struct dfs_seq_file *seq, const void *data, size_t len);

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2006-2024, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#ifndef __DFS_VFS_H__
#define __DFS_VFS_H__
#include "dfs_file.h"
#include "dfs_fs.h"
#ifdef __cplusplus
extern "C"
{
#endif
struct dfs_vfs_node
{
rt_list_t subnode; /* file subnode list */
rt_list_t sibling; /* file sibling list */
};
rt_inline void dfs_vfs_init_node(struct dfs_vfs_node *node)
{
rt_list_init(&node->subnode);
rt_list_init(&node->sibling);
}
rt_inline void dfs_vfs_append_node(struct dfs_vfs_node *dir, struct dfs_vfs_node *node)
{
rt_list_insert_after(&(dir->subnode), &(node->sibling));
}
rt_inline void dfs_vfs_remove_node(struct dfs_vfs_node *node)
{
rt_list_remove(&(node->sibling));
}
#define dfs_vfs_for_each_subnode(node, tmp, dir, member) \
rt_list_for_each_entry_safe(node, tmp, &dir->member.subnode, member.sibling)
#ifdef __cplusplus
}
#endif
#endif /*__DFS_VFS_H__*/

View File

@ -537,6 +537,7 @@ int dfs_dup(int oldfd, int startfd)
fdt = dfs_fdtable_get();
if ((oldfd < 0) || (oldfd >= fdt->maxfd))
{
rt_set_errno(-EBADF);
goto exit;
}
if (!fdt->fds[oldfd])
@ -668,12 +669,17 @@ sysret_t sys_dup(int oldfd)
int sys_dup(int oldfd)
#endif
{
int err = 0;
int newfd = dfs_dup(oldfd, (dfs_fdtable_get() == &_fdtab) ? DFS_STDIO_OFFSET : 0);
if(newfd < 0)
{
err = rt_get_errno();
}
#ifdef RT_USING_SMART
return (sysret_t)newfd;
return err < 0 ? err : newfd;
#else
return newfd;
return err < 0 ? err : newfd;
#endif
}

View File

@ -1379,6 +1379,7 @@ int dfs_file_link(const char *oldname, const char *newname)
if (dfs_file_isdir(oldname) == 0)
{
rt_set_errno(-EPERM);
return ret;
}
@ -1567,6 +1568,10 @@ int dfs_file_symlink(const char *target, const char *linkpath)
rt_free(parent);
}
}
else
{
rt_set_errno(-EPERM);
}
if (fullpath != linkpath)
rt_free(fullpath);

View File

@ -95,6 +95,52 @@ int dfs_unregister(struct dfs_filesystem_type *fs)
return ret;
}
#define REMNT_UNSUPP_FLAGS (~(MS_REMOUNT | MS_RMT_MASK))
int dfs_remount(const char *path, rt_ubase_t flags, void *data)
{
int rc = 0;
char *fullpath = RT_NULL;
struct dfs_mnt *mnt = RT_NULL;
if (flags & REMNT_UNSUPP_FLAGS)
{
return -EINVAL;
}
fullpath = dfs_normalize_path(RT_NULL, path);
if (!fullpath)
{
rc = -ENOENT;
}
else
{
DLOG(msg, "dfs", "mnt", DLOG_MSG, "mnt = dfs_mnt_lookup(%s)", fullpath);
mnt = dfs_mnt_lookup(fullpath);
if (mnt)
{
dfs_lock();
dfs_mnt_setflags(mnt, flags);
dfs_unlock();
}
else
{
struct stat buf = {0};
if (dfs_file_stat(fullpath, &buf) == 0 && S_ISBLK(buf.st_mode))
{
/* path was not already mounted on target */
rc = -EINVAL;
}
else
{
/* path is not a directory */
rc = -ENOTDIR;
}
}
}
return rc;
}
/*
* parent(mount path)
* mnt_parent <- - - - - - - +
@ -127,7 +173,7 @@ int dfs_mount(const char *device_name,
}
else
{
rt_set_errno(ENOENT);
rt_set_errno(ENODEV);
ret = -1;
}
@ -300,7 +346,7 @@ int dfs_mount(const char *device_name,
int dfs_umount(const char *specialfile, int flags)
{
int ret = -RT_ERROR;
int ret = -1;
char *fullpath = RT_NULL;
struct dfs_mnt *mnt = RT_NULL;
@ -314,7 +360,7 @@ int dfs_umount(const char *specialfile, int flags)
if (strcmp(mnt->fullpath, fullpath) == 0)
{
/* is the mount point */
rt_atomic_t ref_count = rt_atomic_load(&(mnt->ref_count));
rt_base_t ref_count = rt_atomic_load(&(mnt->ref_count));
if (!(mnt->flags & MNT_IS_LOCKED) && rt_list_isempty(&mnt->child) && (ref_count == 1 || (flags & MNT_FORCE)))
{
@ -327,17 +373,19 @@ int dfs_umount(const char *specialfile, int flags)
}
else
{
LOG_E("the file system is busy!");
LOG_I("the file system is busy!");
ret = -EBUSY;
}
}
else
{
LOG_E("the path:%s is not a mountpoint!", fullpath);
LOG_I("the path:%s is not a mountpoint!", fullpath);
ret = -EINVAL;
}
}
else
{
LOG_E("no filesystem found.");
LOG_I("no filesystem found.");
}
rt_free(fullpath);
}

View File

@ -10,17 +10,21 @@
#include <rtthread.h>
#include "dfs.h"
#include "dfs_mnt.h"
#include "dfs_dentry.h"
#include "dfs_private.h"
#include <dfs.h>
#include <dfs_dentry.h>
#include <dfs_mnt.h>
#include <dfs_pcache.h>
#define DBG_TAG "DFS.mnt"
#define DBG_LVL DBG_WARNING
#include <rtdbg.h>
static struct dfs_mnt *_root_mnt = RT_NULL;
RT_OBJECT_HOOKLIST_DEFINE(dfs_mnt_umnt);
/*
* mnt tree structure
*
@ -75,6 +79,7 @@ int dfs_mnt_insert(struct dfs_mnt* mnt, struct dfs_mnt* child)
child = _root_mnt;
rt_atomic_sub(&(_root_mnt->parent->ref_count), 1);
rt_atomic_sub(&(_root_mnt->ref_count), 1);
_root_mnt->flags &= ~MNT_IS_LOCKED;
_root_mnt = dfs_mnt_ref(mnt);
mnt->parent = dfs_mnt_ref(mnt);
@ -242,21 +247,24 @@ struct dfs_mnt* dfs_mnt_ref(struct dfs_mnt* mnt)
return mnt;
}
int dfs_mnt_unref(struct dfs_mnt* mnt)
int dfs_mnt_unref(struct dfs_mnt *mnt)
{
rt_err_t ret = RT_EOK;
rt_base_t ref_count;
if (mnt)
{
rt_atomic_sub(&(mnt->ref_count), 1);
ref_count = rt_atomic_sub(&(mnt->ref_count), 1) - 1;
if (rt_atomic_load(&(mnt->ref_count)) == 0)
if (ref_count == 0)
{
dfs_lock();
if (mnt->flags & MNT_IS_UMOUNT)
{
mnt->fs_ops->umount(mnt);
RT_OBJECT_HOOKLIST_CALL(dfs_mnt_umnt, (mnt));
}
/* free full path */
@ -278,6 +286,21 @@ int dfs_mnt_unref(struct dfs_mnt* mnt)
return ret;
}
int dfs_mnt_setflags(struct dfs_mnt *mnt, int flags)
{
int error = 0;
if (flags & MS_RDONLY)
{
mnt->flags |= MNT_RDONLY;
#ifdef RT_USING_PAGECACHE
dfs_pcache_clean(mnt);
#endif
}
return error;
}
int dfs_mnt_destroy(struct dfs_mnt* mnt)
{
rt_err_t ret = RT_EOK;

View File

@ -13,17 +13,19 @@
#define DBG_LVL DBG_WARNING
#include <rtdbg.h>
#include "dfs_pcache.h"
#include "dfs_dentry.h"
#include "dfs_mnt.h"
#include "mm_page.h"
#include <mmu.h>
#include <tlb.h>
#include <dfs_pcache.h>
#include <dfs_dentry.h>
#include <dfs_mnt.h>
#include <rthw.h>
#ifdef RT_USING_PAGECACHE
#include <mm_page.h>
#include <mm_private.h>
#include <mmu.h>
#include <tlb.h>
#ifndef RT_PAGECACHE_COUNT
#define RT_PAGECACHE_COUNT 4096
#endif
@ -160,7 +162,7 @@ void dfs_pcache_release(size_t count)
dfs_pcache_unlock();
}
void dfs_pcache_unmount(struct dfs_mnt *mnt)
static void _pcache_clean(struct dfs_mnt *mnt, int (*cb)(struct dfs_aspace *aspace))
{
rt_list_t *node = RT_NULL;
struct dfs_aspace *aspace = RT_NULL;
@ -175,7 +177,7 @@ void dfs_pcache_unmount(struct dfs_mnt *mnt)
if (aspace && aspace->mnt == mnt)
{
dfs_aspace_clean(aspace);
dfs_aspace_release(aspace);
cb(aspace);
}
}
@ -187,13 +189,28 @@ void dfs_pcache_unmount(struct dfs_mnt *mnt)
if (aspace && aspace->mnt == mnt)
{
dfs_aspace_clean(aspace);
dfs_aspace_release(aspace);
cb(aspace);
}
}
dfs_pcache_unlock();
}
void dfs_pcache_unmount(struct dfs_mnt *mnt)
{
_pcache_clean(mnt, dfs_aspace_release);
}
static int _dummy_cb(struct dfs_aspace *mnt)
{
return 0;
}
void dfs_pcache_clean(struct dfs_mnt *mnt)
{
_pcache_clean(mnt, _dummy_cb);
}
static int dfs_pcache_limit_check(void)
{
int index = 4;
@ -1138,14 +1155,21 @@ int dfs_aspace_write(struct dfs_file *file, const void *buf, size_t count, off_t
if (file && file->vnode && file->vnode->aspace)
{
if (!(file->vnode->aspace->ops->write))
return ret;
struct dfs_vnode *vnode = file->vnode;
struct dfs_aspace *aspace = vnode->aspace;
struct dfs_page *page;
char *ptr = (char *)buf;
if (!(aspace->ops->write))
{
return ret;
}
else if (aspace->mnt && (aspace->mnt->flags & MNT_RDONLY))
{
return -EROFS;
}
ret = 0;
while (count)
@ -1380,7 +1404,8 @@ int dfs_aspace_unmap(struct dfs_file *file, struct rt_varea *varea)
rt_varea_unmap_page(map_varea, vaddr);
if (varea->attr == MMU_MAP_U_RWCB && page->fpos < page->aspace->vnode->size)
if (!rt_varea_is_private_locked(varea) &&
page->fpos < page->aspace->vnode->size)
{
dfs_page_dirty(page);
}
@ -1425,7 +1450,7 @@ int dfs_aspace_page_unmap(struct dfs_file *file, struct rt_varea *varea, void *v
if (map && varea->aspace == map->aspace && vaddr == map->vaddr)
{
if (varea->attr == MMU_MAP_U_RWCB)
if (!rt_varea_is_private_locked(varea))
{
dfs_page_dirty(page);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -31,7 +31,17 @@
* return a file descriptor according specified flags.
*
* @param file the path name of file.
* @param flags the file open flags.
* @param flags the file open flags. Common values include:
* - Access modes (mutually exclusive):
* - `O_RDONLY`: Open for read-only access.
* - `O_WRONLY`: Open for write-only access.
* - `O_RDWR`: Open for both reading and writing.
* - File status flags (can be combined with bitwise OR `|`):
* - `O_CREAT`: Create the file if it does not exist. Requires a `mode` argument.
* - `O_TRUNC`: Truncate the file to zero length if it already exists.
* - `O_APPEND`: Append writes to the end of the file.
* - `O_EXCL`: Ensure that `O_CREAT` creates the file exclusively.
* - Other platform-specific flags
*
* @return the non-negative integer on successful open, others for failed.
*/
@ -81,6 +91,22 @@ RTM_EXPORT(open);
#ifndef AT_FDCWD
#define AT_FDCWD (-100)
#endif
/**
* @brief Opens a file relative to a directory file descriptor.
*
* @param dirfd The file descriptor of the directory to base the relative path on.
* @param path The path to the file to be opened, relative to the directory specified by `dirfd`.
* Can be an absolute path (in which case `dirfd` is ignored).
* @param flag File access and status flags (e.g., `O_RDONLY`, `O_WRONLY`, `O_CREAT`).
*
* @return On success, returns a new file descriptor for the opened file.
* On failure, returns `-1` and sets `errno` to indicate the error.
*
* @note When using relative paths, ensure `dirfd` is a valid directory descriptor.
* When `pathname` is absolute, the `dirfd` argument is ignored.
*
*/
int openat(int dirfd, const char *path, int flag, ...)
{
struct dfs_file *d;
@ -171,7 +197,7 @@ int utimensat(int __fd, const char *__path, const struct timespec __times[2], in
}
}
//update time
/*update time*/
attr.ia_valid = ATTR_ATIME_SET | ATTR_MTIME_SET;
time(&current_time);
if (UTIME_NOW == __times[0].tv_nsec)
@ -374,14 +400,22 @@ ssize_t write(int fd, const void *buf, size_t len)
RTM_EXPORT(write);
/**
* this function is a POSIX compliant version, which will seek the offset for
* this function is a POSIX compliant version, which will Reposition the file offset for
* an open file descriptor.
*
* @param fd the file descriptor.
* @param offset the offset to be seeked.
* @param whence the directory of seek.
* The `lseek` function sets the file offset for the file descriptor `fd`
* to a new value, determined by the `offset` and `whence` parameters.
* It can be used to seek to specific positions in a file for reading or writing.
*
* @return the current read/write position in the file, or -1 on failed.
* @param fd the file descriptor.
* @param offset The offset, in bytes, to set the file position.
* The meaning of `offset` depends on the value of `whence`.
* @param whence the directive of seek. It can be one of:
* - `SEEK_SET`: Set the offset to `offset` bytes from the beginning of the file.
* - `SEEK_CUR`: Set the offset to its current location plus `offset` bytes.
* - `SEEK_END`: Set the offset to the size of the file plus `offset` bytes.
*
* @return the resulting read/write position in the file, or -1 on failed.
*/
off_t lseek(int fd, off_t offset, int whence)
{
@ -399,7 +433,7 @@ off_t lseek(int fd, off_t offset, int whence)
result = dfs_file_lseek(file, offset, whence);
if (result < 0)
{
rt_set_errno(result);
rt_set_errno(-EPERM);
return -1;
}
@ -581,9 +615,15 @@ RTM_EXPORT(fsync);
* control functions on devices.
*
* @param fildes the file description
* @param cmd the specified command
* @param cmd the specified command, Common values include:
* - `F_DUPFD`: Duplicate a file descriptor.
* - `F_GETFD`: Get the file descriptor flags.
* - `F_SETFD`: Set the file descriptor flags.
* - `F_GETFL`: Get the file status flags.
* - `F_SETFL`: Set the file status flags.
* @param ... represents the additional information that is needed by this
* specific device to perform the requested function.
* specific device to perform the requested function. For example:
* - When `cmd` is `F_SETFL`, an additional integer argument specifies the new status flags.
*
* @return 0 on successful completion. Otherwise, -1 shall be returned and errno
* set to indicate the error.
@ -765,7 +805,7 @@ RTM_EXPORT(fstatfs);
* this function is a POSIX compliant version, which will make a directory
*
* @param path the directory path to be made.
* @param mode
* @param mode The permission mode for the new directory (unused here, can be set to 0).
*
* @return 0 on successful, others on failed.
*/
@ -827,7 +867,7 @@ int rmdir(const char *pathname)
if (!pathname)
{
rt_set_errno(-RT_ERROR);
rt_set_errno(-EPERM);
return -1;
}
@ -852,7 +892,7 @@ int rmdir(const char *pathname)
if (dirent)
{
rt_set_errno(-RT_ERROR);
rt_set_errno(-EPERM);
return -1;
}
}
@ -861,7 +901,7 @@ int rmdir(const char *pathname)
{
if (S_ISLNK(stat.st_mode))
{
rt_set_errno(-RT_ERROR);
rt_set_errno(-EPERM);
return -1;
}
}

View File

@ -256,7 +256,7 @@ Enomem:
goto Done;
}
ssize_t dfs_seq_lseek(struct dfs_file *file, off_t offset, int whence)
off_t dfs_seq_lseek(struct dfs_file *file, off_t offset, int whence)
{
struct dfs_seq_file *seq = file->data;
off_t retval = -EINVAL;

View File

@ -21,8 +21,21 @@ rsource "touch/Kconfig"
rsource "graphic/Kconfig"
rsource "hwcrypto/Kconfig"
rsource "wlan/Kconfig"
rsource "led/Kconfig"
rsource "mailbox/Kconfig"
rsource "phye/Kconfig"
rsource "ata/Kconfig"
rsource "nvme/Kconfig"
rsource "block/Kconfig"
rsource "scsi/Kconfig"
rsource "regulator/Kconfig"
rsource "reset/Kconfig"
rsource "thermal/Kconfig"
rsource "virtio/Kconfig"
rsource "dma/Kconfig"
rsource "mfd/Kconfig"
rsource "ofw/Kconfig"
rsource "pci/Kconfig"
rsource "pic/Kconfig"
rsource "pin/Kconfig"
rsource "pinctrl/Kconfig"

View File

@ -0,0 +1,22 @@
menuconfig RT_USING_ATA
bool "Using Advanced Technology Attachment (ATA) device drivers"
depends on RT_USING_DM
depends on RT_USING_BLK
depends on RT_USING_DMA
default n
config RT_ATA_AHCI
bool "Advanced Host Controller Interface (AHCI)"
depends on RT_USING_ATA
depends on RT_USING_SCSI
default y
config RT_ATA_AHCI_PCI
bool "AHCI support on PCI bus"
depends on RT_ATA_AHCI
depends on RT_USING_PCI
default n
if RT_USING_ATA
osource "$(SOC_DM_ATA_DIR)/Kconfig"
endif

View File

@ -0,0 +1,21 @@
from building import *
group = []
if not GetDepend(['RT_USING_ATA']):
Return('group')
cwd = GetCurrentDir()
CPPPATH = [cwd + '/../include']
src = []
if GetDepend(['RT_ATA_AHCI']):
src += ['ahci.c']
if GetDepend(['RT_ATA_AHCI_PCI']):
src += ['ahci-pci.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,206 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI the first version
*/
#include <rtthread.h>
#include <rtdevice.h>
#define AHCI_REG_BAR 5
struct pci_ahci_quirk
{
int bar_idx;
rt_bool_t bar_offset;
const struct rt_ahci_ops *ops;
};
struct pci_ahci_host
{
struct rt_ahci_host parent;
const struct pci_ahci_quirk *quirk;
rt_bool_t is_msi;
};
#define raw_to_pci_ahci_host(raw) rt_container_of(raw, struct pci_ahci_host, parent)
static rt_err_t pci_ahci_init(struct rt_ahci_host *host)
{
struct rt_pci_device *pdev;
pdev = rt_container_of(host->parent.dev, struct rt_pci_device, parent);
if (pdev->vendor == PCI_VENDOR_ID_JMICRON)
{
rt_pci_write_config_u8(pdev, 0x41, 0xa1);
}
return RT_EOK;
}
static const struct rt_ahci_ops pci_ahci_ops =
{
.host_init = pci_ahci_init,
};
static rt_err_t pci_ahci_intel_init(struct rt_ahci_host *host)
{
rt_uint16_t val;
struct rt_pci_device *pdev;
pdev = rt_container_of(host->parent.dev, struct rt_pci_device, parent);
rt_pci_read_config_u16(pdev, 0x92, &val);
rt_pci_write_config_u16(pdev, 0x92, val & ~0xf);
rt_thread_mdelay(10);
rt_pci_write_config_u16(pdev, 0x92, val | 0xf);
return RT_EOK;
}
static const struct rt_ahci_ops pci_ahci_intel_ops =
{
.host_init = pci_ahci_intel_init,
};
static rt_err_t pci_ahci_probe(struct rt_pci_device *pdev)
{
rt_err_t err;
int bar_idx;
struct rt_ahci_host *ahci;
struct pci_ahci_host *pci_ahci = rt_calloc(1, sizeof(*pci_ahci));
const struct pci_ahci_quirk *quirk = pdev->id->data;
if (!pci_ahci)
{
return -RT_ENOMEM;
}
pci_ahci->quirk = quirk;
ahci = &pci_ahci->parent;
ahci->parent.dev = &pdev->parent;
bar_idx = quirk && quirk->bar_offset ? quirk->bar_idx : AHCI_REG_BAR;
ahci->regs = rt_pci_iomap(pdev, bar_idx);
if (!ahci->regs)
{
err = -RT_EIO;
goto _fail;
}
ahci->ops = quirk && quirk->ops ? quirk->ops : &pci_ahci_ops;
if (rt_pci_msi_enable(pdev) > 0)
{
pci_ahci->is_msi = RT_TRUE;
}
else
{
rt_pci_irq_unmask(pdev);
}
ahci->irq = pdev->irq;
rt_pci_set_master(pdev);
if ((err = rt_ahci_host_register(ahci)))
{
goto _disable;
}
pdev->parent.user_data = pci_ahci;
return RT_EOK;
_disable:
if (pci_ahci->is_msi)
{
rt_pci_msix_disable(pdev);
}
else
{
rt_pci_irq_mask(pdev);
}
rt_pci_clear_master(pdev);
rt_iounmap(ahci->regs);
_fail:
rt_free(pci_ahci);
return err;
}
static rt_err_t pci_ahci_remove(struct rt_pci_device *pdev)
{
struct rt_ahci_host *ahci;
struct pci_ahci_host *pci_ahci = pdev->parent.user_data;
ahci = &pci_ahci->parent;
rt_ahci_host_unregister(ahci);
if (pci_ahci->is_msi)
{
rt_pci_msi_disable(pdev);
}
else
{
/* INTx is shared, don't mask all */
rt_hw_interrupt_umask(pdev->irq);
rt_pci_irq_mask(pdev);
}
rt_pci_clear_master(pdev);
rt_iounmap(ahci->regs);
rt_free(pci_ahci);
return RT_EOK;
}
static rt_err_t pci_ahci_shutdown(struct rt_pci_device *pdev)
{
return pci_ahci_remove(pdev);
}
static struct pci_ahci_quirk intel_quirk =
{
.ops = &pci_ahci_intel_ops,
};
static struct pci_ahci_quirk cavium_sata_quirk =
{
.bar_idx = 0,
.bar_offset = RT_TRUE,
};
static const struct rt_pci_device_id pci_ahci_ids[] =
{
{ RT_PCI_DEVICE_ID(PCI_VENDOR_ID_INTEL, 0x2922), .data = &intel_quirk },
{ RT_PCI_DEVICE_ID(PCI_VENDOR_ID_ASMEDIA, 0x0611) },
{ RT_PCI_DEVICE_ID(PCI_VENDOR_ID_MARVELL, 0x6121) },
{ RT_PCI_DEVICE_ID(PCI_VENDOR_ID_MARVELL, 0x6145) },
{ RT_PCI_DEVICE_ID(PCI_VENDOR_ID_CAVIUM, 0xa01c), .data = &cavium_sata_quirk },
{ RT_PCI_DEVICE_CLASS(PCIS_STORAGE_SATA_AHCI, ~0) },
{ /* sentinel */ }
};
static struct rt_pci_driver pci_ahci_driver =
{
.name = "ahci-pci",
.ids = pci_ahci_ids,
.probe = pci_ahci_probe,
.remove = pci_ahci_remove,
.shutdown = pci_ahci_shutdown,
};
RT_PCI_DRIVER_EXPORT(pci_ahci_driver);

View File

@ -0,0 +1,896 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#define DBG_TAG "rtdm.ahci"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#define HWREG32_FLUSH(base, value) \
do { \
rt_uint32_t __value = value; \
HWREG32(base) = __value; \
__value = HWREG32(base); \
} while (0)
static void ahci_fill_cmd_slot(struct rt_ahci_port *port, rt_uint32_t opts)
{
rt_ubase_t dma_addr = port->cmd_tbl_dma;
struct rt_ahci_cmd_hdr *cmd_slot = port->cmd_slot;
cmd_slot->opts = rt_cpu_to_le32(opts);
cmd_slot->status = 0;
cmd_slot->tbl_addr_lo = rt_cpu_to_le32(rt_lower_32_bits(dma_addr));
cmd_slot->tbl_addr_hi = rt_cpu_to_le32(rt_upper_32_bits(dma_addr));
}
static int ahci_fill_sg(struct rt_ahci_host *host, int id,
void *buffer, rt_size_t buffer_size)
{
int sg_count;
rt_ubase_t dma_addr;
struct rt_ahci_port *port = &host->ports[id];
struct rt_ahci_sg *ahci_sg = port->cmd_tbl_sg;
sg_count = ((buffer_size - 1) / RT_ACHI_PRDT_BYTES_MAX) + 1;
if (sg_count > RT_AHCI_MAX_SG)
{
return -1;
}
dma_addr = (rt_ubase_t)rt_kmem_v2p(buffer);
for (int i = 0; i < sg_count; ++i, ++ahci_sg)
{
ahci_sg->addr_lo = rt_cpu_to_le32(rt_lower_32_bits(dma_addr));
ahci_sg->addr_hi = rt_cpu_to_le32(rt_upper_32_bits(dma_addr));
if (ahci_sg->addr_hi && !(host->cap & RT_AHCI_CAP_64))
{
return -1;
}
ahci_sg->flags_size = rt_cpu_to_le32(0x3fffff &
(rt_min_t(rt_uint32_t, buffer_size, RT_ACHI_PRDT_BYTES_MAX) - 1));
dma_addr += RT_ACHI_PRDT_BYTES_MAX;
buffer_size -= RT_ACHI_PRDT_BYTES_MAX;
}
return sg_count;
}
static rt_err_t ahci_request_io(struct rt_ahci_host *host, int id,
void *fis, rt_size_t fis_size,
void *buffer, rt_size_t buffer_size, rt_bool_t is_read)
{
int sg_count;
rt_err_t err;
struct rt_ahci_port *port = &host->ports[id];
if ((HWREG32(port->regs + RT_AHCI_PORT_SSTS) & 0xf) != RT_AHCI_PORT_SSTS_DET_PHYRDY)
{
return -RT_EIO;
}
if ((sg_count = ahci_fill_sg(host, id, buffer, buffer_size)) <= 0)
{
return -RT_EINVAL;
}
rt_memcpy(port->cmd_tbl, fis, fis_size);
ahci_fill_cmd_slot(port, (fis_size >> 2) | (sg_count << 16) | (!is_read << 6));
if (!is_read)
{
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, buffer, buffer_size);
}
HWREG32_FLUSH(port->regs + RT_AHCI_PORT_CI, 1);
err = rt_completion_wait(&port->done, rt_tick_from_millisecond(10000));
if (!err && is_read)
{
rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, buffer, buffer_size);
}
return err;
}
static rt_err_t ahci_scsi_cmd_rw(struct rt_ahci_host *host, int id,
rt_off_t lba, void *buffer, rt_ssize_t size, rt_bool_t is_read)
{
rt_err_t err;
rt_uint8_t fis[20];
struct rt_ahci_port *port = &host->ports[id];
rt_memset(fis, 0, sizeof(fis));
fis[0] = RT_AHCI_FIS_TYPE_REG_H2D;
fis[1] = 1 << 7; /* Command */
fis[2] = is_read ? RT_AHCI_ATA_CMD_READ_EXT : RT_AHCI_ATA_CMD_WRITE_EXT;
while (size > 0)
{
rt_size_t t_size, t_lba;
t_lba = rt_min_t(rt_size_t, host->max_blocks, size);
t_size = port->block_size * t_lba;
fis[3] = 0xe0; /* Features */
fis[4] = (lba >> 0) & 0xff; /* LBA low register */
fis[5] = (lba >> 8) & 0xff; /* LBA mid register */
fis[6] = (lba >> 16) & 0xff; /* LBA high register */
fis[7] = 1 << 6; /* Device */
fis[8] = ((lba >> 24) & 0xff); /* LBA register, 31:24 */
fis[9] = ((lba >> 32) & 0xff); /* LBA register, 39:32 */
fis[10] = ((lba >> 40) & 0xff); /* LBA register, 47:40 */
fis[12] = (t_lba >> 0) & 0xff; /* Count register, 7:0 */
fis[13] = (t_lba >> 8) & 0xff; /* Count register, 15:8 */
if ((err = ahci_request_io(host, id, fis, sizeof(fis), buffer, t_size, is_read)))
{
return err;
}
size -= t_lba;
lba += t_lba;
buffer += t_size;
}
return RT_EOK;
}
static rt_err_t ahci_scsi_synchronize_cache(struct rt_ahci_host *host, int id,
rt_off_t lba, rt_size_t size)
{
rt_uint8_t fis[20];
rt_uint16_t *ataid;
struct rt_ahci_port *port = &host->ports[id];
ataid = port->ataid;
if (!rt_ahci_ata_id_wcache_enabled(ataid) &&
!rt_ahci_ata_id_has_flush(ataid) &&
!rt_ahci_ata_id_has_flush_ext(ataid))
{
return -RT_ENOSYS;
}
rt_memset(fis, 0, sizeof(fis));
fis[0] = RT_AHCI_FIS_TYPE_REG_H2D;
fis[1] = 1 << 7; /* Command */
if (rt_ahci_ata_id_has_flush_ext(ataid))
{
fis[2] = RT_AHCI_ATA_CMD_FLUSH_EXT;
}
else
{
fis[2] = RT_AHCI_ATA_CMD_FLUSH;
}
rt_memcpy(port->cmd_tbl, fis, 20);
ahci_fill_cmd_slot(port, 5);
HWREG32_FLUSH(port->regs + RT_AHCI_PORT_CI, 1);
return rt_completion_wait(&port->done, rt_tick_from_millisecond(5000));
}
static rt_err_t ahci_scsi_cmd_write_same(struct rt_ahci_host *host, int id,
rt_off_t lba, rt_size_t size)
{
rt_uint8_t fis[20];
struct rt_ahci_port *port = &host->ports[id];
rt_memset(fis, 0, sizeof(fis));
fis[0] = RT_AHCI_FIS_TYPE_REG_H2D;
fis[1] = 1 << 7; /* Command */
fis[2] = RT_AHCI_ATA_CMD_DSM;
fis[3] = RT_AHCI_ATA_DSM_TRIM; /* Features */
fis[4] = (lba >> 0) & 0xff; /* LBA low register */
fis[5] = (lba >> 8) & 0xff; /* LBA mid register */
fis[6] = (lba >> 16) & 0xff; /* LBA high register */
fis[7] = 1 << 6; /* Device */
fis[8] = ((lba >> 24) & 0xff); /* LBA register, 31:24 */
fis[9] = ((lba >> 32) & 0xff); /* LBA register, 39:32 */
fis[10] = ((lba >> 40) & 0xff); /* LBA register, 47:40 */
fis[12] = (size >> 0) & 0xff; /* Count register, 7:0 */
fis[13] = (size >> 8) & 0xff; /* Count register, 15:8 */
HWREG32_FLUSH(port->regs + RT_AHCI_PORT_CI, 1);
return rt_completion_wait(&port->done, rt_tick_from_millisecond(5000));
}
static rt_err_t ahci_scsi_cmd_read_capacity(struct rt_ahci_host *host, int id,
rt_size_t *out_last_block, rt_size_t *out_block_size)
{
struct rt_ahci_port *port = &host->ports[id];
if (!port->ataid)
{
return -RT_EIO;
}
*out_last_block = rt_ahci_ata_id_n_sectors(port->ataid) - 1;
*out_block_size = port->block_size;
return RT_EOK;
}
static rt_err_t ahci_scsi_cmd_test_unit_ready(struct rt_ahci_host *host, int id)
{
struct rt_ahci_port *port = &host->ports[id];
return port->ataid ? RT_EOK : -RT_EIO;
}
static rt_err_t ahci_scsi_cmd_inquiry(struct rt_ahci_host *host, int id,
char *prodid, rt_size_t prodid_len, char *prodrev, rt_size_t prodrev_len)
{
rt_err_t err;
rt_uint8_t fis[20];
rt_uint16_t *ataid;
struct rt_ahci_port *port = &host->ports[id];
if (!port->link)
{
return -RT_EIO;
}
if (!port->ataid && !(port->ataid = rt_malloc(RT_AHCI_ATA_ID_WORDS * 2)))
{
return -RT_ENOMEM;
}
ataid = port->ataid;
rt_memset(fis, 0, sizeof(fis));
fis[0] = RT_AHCI_FIS_TYPE_REG_H2D;
fis[1] = 1 << 7; /* Command */
fis[2] = RT_AHCI_ATA_CMD_ID_ATA;
if ((err = ahci_request_io(host, id, fis, sizeof(fis),
ataid, RT_AHCI_ATA_ID_WORDS * 2, RT_TRUE)))
{
return err;
}
for (int i = 0; i < RT_AHCI_ATA_ID_WORDS; ++i)
{
ataid[i] = rt_le16_to_cpu(ataid[i]);
}
for (int i = 0; i < prodid_len / 2; ++i)
{
rt_uint16_t src = ataid[RT_AHCI_ATA_ID_PROD + i];
prodid[i] = (src & 0x00ff) << 8 | (src & 0xff00) >> 8;
}
for (int i = 0; i < prodrev_len / 2; ++i)
{
rt_uint16_t src = ataid[RT_AHCI_ATA_ID_FW_REV + i];
prodrev[i] = (src & 0x00ff) << 8 | (src & 0xff00) >> 8;
}
return err;
}
static rt_err_t ahci_scsi_transfer(struct rt_scsi_device *sdev,
struct rt_scsi_cmd *cmd)
{
rt_err_t err;
struct rt_ahci_host *host;
host = rt_container_of(sdev->host, struct rt_ahci_host, parent);
switch (cmd->op.unknow.opcode)
{
case RT_SCSI_CMD_REQUEST_SENSE:
{
struct rt_scsi_request_sense_data *request_sense = &cmd->data.request_sense;
request_sense->error_code = 0x72;
err = RT_EOK;
}
break;
case RT_SCSI_CMD_READ10:
{
struct rt_scsi_read10 *read10 = &cmd->op.read10;
err = ahci_scsi_cmd_rw(host, sdev->id,
rt_be32_to_cpu(read10->lba),
cmd->data.ptr,
rt_be16_to_cpu(read10->size),
RT_TRUE);
}
break;
case RT_SCSI_CMD_READ16:
{
struct rt_scsi_read16 *read16 = &cmd->op.read16;
err = ahci_scsi_cmd_rw(host, sdev->id,
rt_be64_to_cpu(read16->lba),
cmd->data.ptr,
rt_be32_to_cpu(read16->size),
RT_TRUE);
}
break;
case RT_SCSI_CMD_READ12:
{
struct rt_scsi_read12 *read12 = &cmd->op.read12;
err = ahci_scsi_cmd_rw(host, sdev->id,
rt_be32_to_cpu(read12->lba),
cmd->data.ptr,
rt_be32_to_cpu(read12->size),
RT_TRUE);
}
break;
case RT_SCSI_CMD_WRITE10:
{
struct rt_scsi_write10 *write10 = &cmd->op.write10;
err = ahci_scsi_cmd_rw(host, sdev->id,
rt_be32_to_cpu(write10->lba),
cmd->data.ptr,
rt_be16_to_cpu(write10->size),
RT_FALSE);
}
break;
case RT_SCSI_CMD_WRITE16:
{
struct rt_scsi_write16 *write16 = &cmd->op.write16;
err = ahci_scsi_cmd_rw(host, sdev->id,
rt_be64_to_cpu(write16->lba),
cmd->data.ptr,
rt_be32_to_cpu(write16->size),
RT_FALSE);
}
break;
case RT_SCSI_CMD_WRITE12:
{
struct rt_scsi_write12 *write12 = &cmd->op.write12;
err = ahci_scsi_cmd_rw(host, sdev->id,
rt_be32_to_cpu(write12->lba),
cmd->data.ptr,
rt_be32_to_cpu(write12->size),
RT_FALSE);
}
break;
case RT_SCSI_CMD_SYNCHRONIZE_CACHE10:
{
struct rt_scsi_synchronize_cache10 *synchronize_cache10 = &cmd->op.synchronize_cache10;
err = ahci_scsi_synchronize_cache(host, sdev->id,
rt_be32_to_cpu(synchronize_cache10->lba),
rt_be16_to_cpu(synchronize_cache10->size));
}
break;
case RT_SCSI_CMD_SYNCHRONIZE_CACHE16:
{
struct rt_scsi_synchronize_cache16 *synchronize_cache16 = &cmd->op.synchronize_cache16;
err = ahci_scsi_synchronize_cache(host, sdev->id,
rt_be64_to_cpu(synchronize_cache16->lba),
rt_be32_to_cpu(synchronize_cache16->size));
}
break;
case RT_SCSI_CMD_WRITE_SAME10:
{
struct rt_scsi_write_same10 *write_same10 = &cmd->op.write_same10;
err = ahci_scsi_cmd_write_same(host, sdev->id,
rt_be32_to_cpu(write_same10->lba), rt_be16_to_cpu(write_same10->size));
}
break;
case RT_SCSI_CMD_WRITE_SAME16:
{
struct rt_scsi_write_same16 *write_same16 = &cmd->op.write_same16;
err = ahci_scsi_cmd_write_same(host, sdev->id,
rt_be64_to_cpu(write_same16->lba), rt_be32_to_cpu(write_same16->size));
}
break;
case RT_SCSI_CMD_READ_CAPACITY10:
{
rt_size_t last_block, block_size;
struct rt_scsi_read_capacity10_data *data = &cmd->data.read_capacity10;
err = ahci_scsi_cmd_read_capacity(host, sdev->id, &last_block, &block_size);
if (!err)
{
if (last_block > 0x100000000ULL)
{
last_block = 0xffffffff;
}
data->last_block = rt_cpu_to_be32(last_block);
data->block_size = rt_cpu_to_be32(block_size);
}
}
break;
case RT_SCSI_CMD_READ_CAPACITY16:
{
rt_size_t last_block, block_size;
struct rt_scsi_read_capacity16_data *data = &cmd->data.read_capacity16;
err = ahci_scsi_cmd_read_capacity(host, sdev->id, &last_block, &block_size);
if (!err)
{
data->last_block = rt_cpu_to_be64(last_block);
data->block_size = rt_cpu_to_be32(block_size);
}
}
break;
case RT_SCSI_CMD_TEST_UNIT_READY:
err = ahci_scsi_cmd_test_unit_ready(host, sdev->id);
break;
case RT_SCSI_CMD_INQUIRY:
{
struct rt_ahci_port *port = &host->ports[sdev->id];
struct rt_scsi_inquiry_data *inquiry = &cmd->data.inquiry;
err = ahci_scsi_cmd_inquiry(host, sdev->id,
inquiry->prodid, sizeof(inquiry->prodid),
inquiry->prodrev, sizeof(inquiry->prodrev));
if (!err)
{
rt_memcpy(inquiry->vendor, "ATA ", sizeof(inquiry->vendor));
if (HWREG32(port->regs + RT_AHCI_PORT_SIG) != RT_AHCI_PORT_SIG_SATA_CDROM)
{
port->block_size = 512;
inquiry->devtype = SCSI_DEVICE_TYPE_DIRECT;
}
else
{
port->block_size = 2048;
inquiry->devtype = SCSI_DEVICE_TYPE_CDROM;
}
inquiry->rmb = 0;
inquiry->length = 95 - 4;
}
}
break;
case RT_SCSI_CMD_MODE_SENSE:
case RT_SCSI_CMD_MODE_SENSE10:
case RT_SCSI_CMD_MODE_SELECT:
case RT_SCSI_CMD_MODE_SELECT10:
return -RT_ENOSYS;
default:
return -RT_EINVAL;
}
return err;
}
static struct rt_scsi_ops ahci_scsi_ops =
{
.transfer = ahci_scsi_transfer,
};
static void ahci_isr(int irqno, void *param)
{
int id;
rt_uint32_t isr;
rt_bitmap_t int_map;
struct rt_ahci_port *port;
struct rt_ahci_host *host = param;
int_map = HWREG32(host->regs + RT_AHCI_HBA_INTS);
rt_bitmap_for_each_set_bit(&int_map, id, host->ports_nr)
{
port = &host->ports[id];
isr = HWREG32(port->regs + RT_AHCI_PORT_INTS);
if (port->link)
{
if (host->ops->port_isr)
{
host->ops->port_isr(host, port, isr);
}
rt_completion_done(&port->done);
}
HWREG32(port->regs + RT_AHCI_PORT_INTS) = isr;
}
HWREG32(host->regs + RT_AHCI_HBA_INTS) = int_map;
}
rt_err_t rt_ahci_host_register(struct rt_ahci_host *host)
{
rt_err_t err;
rt_uint32_t value;
char dev_name[RT_NAME_MAX];
struct rt_scsi_host *scsi;
if (!host || !host->parent.dev || !host->ops)
{
return -RT_EINVAL;
}
host->max_blocks = host->max_blocks ? : 0x80;
/*
* 1. Reset HBA.
*/
err = -RT_EIO;
value = HWREG32(host->regs + RT_AHCI_HBA_GHC);
if (!(value & RT_AHCI_GHC_RESET))
{
HWREG32_FLUSH(host->regs + RT_AHCI_HBA_GHC, value | RT_AHCI_GHC_RESET);
}
for (int i = 0; i < 5; ++i)
{
rt_thread_mdelay(200);
if (!(HWREG32(host->regs + RT_AHCI_HBA_GHC) & RT_AHCI_GHC_RESET))
{
err = RT_EOK;
break;
}
}
if (err)
{
goto _fail;
}
/*
* 2. Enable AHCI and get the ports' information.
*/
HWREG32_FLUSH(host->regs + RT_AHCI_HBA_GHC, RT_AHCI_GHC_AHCI_EN);
host->cap = HWREG32(host->regs + RT_AHCI_HBA_CAP);
host->cap &= RT_AHCI_CAP_SPM | RT_AHCI_CAP_SSS | RT_AHCI_CAP_SIS;
HWREG32(host->regs + RT_AHCI_HBA_CAP) = host->cap;
host->cap = HWREG32(host->regs + RT_AHCI_HBA_CAP);
HWREG32_FLUSH(host->regs + RT_AHCI_HBA_PI, 0xf);
if (host->ops->host_init && (err = host->ops->host_init(host)))
{
goto _fail;
}
host->ports_nr = (host->cap & RT_AHCI_CAP_NP) + 1;
host->ports_map = HWREG32(host->regs + RT_AHCI_HBA_PI);
/* Check implemented in firmware */
rt_dm_dev_prop_read_u32(host->parent.dev, "ports-implemented", &host->ports_map);
for (int i = 0; i < host->ports_nr; ++i)
{
struct rt_ahci_port *port;
if (!(host->ports_map & RT_BIT(i)))
{
continue;
}
port = &host->ports[i];
/*
* 3. Alloc port io memory.
*/
port->regs = host->regs + 0x100 + (i * 0x80);
/*
* 4. Make port stop.
*/
value = HWREG32(port->regs + RT_AHCI_PORT_CMD);
if (value & (RT_AHCI_PORT_CMD_LIST_ON | RT_AHCI_PORT_CMD_FIS_ON |
RT_AHCI_PORT_CMD_FIS_RX | RT_AHCI_PORT_CMD_START))
{
value &= ~(RT_AHCI_PORT_CMD_LIST_ON | RT_AHCI_PORT_CMD_FIS_ON |
RT_AHCI_PORT_CMD_FIS_RX | RT_AHCI_PORT_CMD_START);
HWREG32_FLUSH(port->regs + RT_AHCI_PORT_CMD, value);
rt_thread_mdelay(500);
}
if (host->ops->port_init && (err = host->ops->port_init(host, port)))
{
LOG_E("Init port[%d] error = %s", rt_strerror(err));
continue;
}
value = HWREG32(port->regs + RT_AHCI_PORT_CMD);
value |= RT_AHCI_PORT_CMD_SPIN_UP;
HWREG32(port->regs + RT_AHCI_PORT_CMD) = value;
/*
* 5. Enable port's SATA link.
*/
if (host->ops->port_link_up)
{
err = host->ops->port_link_up(host, port);
}
else
{
err = -RT_ETIMEOUT;
for (int retry = 0; retry < 5; ++retry)
{
value = HWREG32(port->regs + RT_AHCI_PORT_SSTS);
if ((value & RT_AHCI_PORT_SSTS_DET_MASK) == RT_AHCI_PORT_SSTS_DET_PHYRDY)
{
err = RT_EOK;
break;
}
rt_thread_mdelay(2);
}
}
if (err)
{
if (HWREG32(port->regs + RT_AHCI_PORT_SSTS) & RT_AHCI_PORT_SSTS_DET_MASK)
{
LOG_E("SATA[%d] link error = %s", i, rt_strerror(err));
}
else
{
LOG_D("SATA[%d] not device", i);
}
continue;
}
/* Clear error status */
if ((value = HWREG32(port->regs + RT_AHCI_PORT_SERR)))
{
HWREG32(port->regs + RT_AHCI_PORT_SERR) = value;
}
for (int retry = 0; retry < 5; ++retry)
{
value = HWREG32(port->regs + RT_AHCI_PORT_TFD);
if (!(value & (RT_AHCI_PORT_TFDATA_BSY | RT_AHCI_PORT_TFDATA_DRQ)))
{
break;
}
rt_thread_mdelay(2);
value = HWREG32(port->regs + RT_AHCI_PORT_SSTS);
if ((value & RT_AHCI_PORT_SSTS_DET_MASK) == RT_AHCI_PORT_SSTS_DET_PHYRDY)
{
break;
}
}
value = HWREG32(port->regs + RT_AHCI_PORT_SSTS) & RT_AHCI_PORT_SSTS_DET_MASK;
if (value == RT_AHCI_PORT_SSTS_DET_COMINIT)
{
/* Retry to setup */
--i;
continue;
}
/* Clear error */
value = HWREG32(port->regs + RT_AHCI_PORT_SERR);
HWREG32(port->regs + RT_AHCI_PORT_SERR) = value;
/* Clear pending IRQ */
if ((value = HWREG32(port->regs + RT_AHCI_PORT_INTS)))
{
HWREG32(port->regs + RT_AHCI_PORT_INTS) = value;
}
HWREG32(host->regs + RT_AHCI_HBA_INTS) = RT_BIT(i);
value = HWREG32(port->regs + RT_AHCI_PORT_SSTS);
if ((value & RT_AHCI_PORT_SSTS_DET_MASK) == RT_AHCI_PORT_SSTS_DET_PHYRDY)
{
port->link = RT_TRUE;
}
}
HWREG32(host->regs + RT_AHCI_HBA_GHC) |= RT_AHCI_GHC_IRQ_EN;
for (int i = 0; i < host->ports_nr; ++i)
{
void *dma;
rt_ubase_t dma_addr;
rt_tick_t timeout;
struct rt_ahci_port *port = &host->ports[i];
if (!port->link)
{
continue;
}
/*
* 6. Alloc transport memory, Port x Command List and FIS Base Address.
*/
port->dma = rt_dma_alloc_coherent(host->parent.dev,
RT_AHCI_DMA_SIZE, &port->dma_handle);
if (!port->dma)
{
LOG_E("No memory to setup port[%d]", i);
break;
}
dma = port->dma;
rt_memset(dma, 0, RT_AHCI_DMA_SIZE);
port->cmd_slot = dma;
dma += (RT_AHCI_CMD_SLOT_SIZE + 224);
port->rx_fis = dma;
dma += RT_AHCI_RX_FIS_SIZE;
port->cmd_tbl = dma;
port->cmd_tbl_dma = (rt_ubase_t)rt_kmem_v2p(dma);
dma += RT_AHCI_CMD_TBL_HDR;
port->cmd_tbl_sg = dma;
dma_addr = (rt_ubase_t)rt_kmem_v2p(port->cmd_slot);
HWREG32_FLUSH(port->regs + RT_AHCI_PORT_CLB, rt_lower_32_bits(dma_addr));
HWREG32_FLUSH(port->regs + RT_AHCI_PORT_CLBU, rt_upper_32_bits(dma_addr));
dma_addr = (rt_ubase_t)rt_kmem_v2p(port->rx_fis);
HWREG32_FLUSH(port->regs + RT_AHCI_PORT_FB, rt_lower_32_bits(dma_addr));
HWREG32_FLUSH(port->regs + RT_AHCI_PORT_FBU, rt_upper_32_bits(dma_addr));
if (host->ops->port_dma_init && (err = host->ops->port_dma_init(host, port)))
{
LOG_E("Init port[%d] DMA error = %s", rt_strerror(err));
}
HWREG32_FLUSH(port->regs + RT_AHCI_PORT_CMD, RT_AHCI_PORT_CMD_ACTIVE |
RT_AHCI_PORT_CMD_FIS_RX | RT_AHCI_PORT_CMD_POWER_ON |
RT_AHCI_PORT_CMD_SPIN_UP | RT_AHCI_PORT_CMD_START);
/* Wait spinup */
err = -RT_ETIMEOUT;
timeout = rt_tick_from_millisecond(20000);
timeout += rt_tick_get();
do {
if (!(HWREG32(port->regs + RT_AHCI_PORT_TFD) & RT_AHCI_PORT_TFDATA_BSY))
{
err = RT_EOK;
break;
}
rt_hw_cpu_relax();
} while (rt_tick_get() < timeout);
if (err)
{
rt_dma_free_coherent(host->parent.dev, RT_AHCI_DMA_SIZE, port->dma,
port->dma_handle);
port->dma = RT_NULL;
LOG_E("Start up port[%d] fail", i);
continue;
}
port->int_enabled |= RT_AHCI_PORT_INTE_HBUS_ERR | RT_AHCI_PORT_INTE_IF_ERR |
RT_AHCI_PORT_INTE_CONNECT | RT_AHCI_PORT_INTE_PHYRDY |
RT_AHCI_PORT_INTE_UNK_FIS | RT_AHCI_PORT_INTE_BAD_PMP |
RT_AHCI_PORT_INTE_TF_ERR | RT_AHCI_PORT_INTE_HBUS_DATA_ERR |
RT_AHCI_PORT_INTE_SG_DONE | RT_AHCI_PORT_INTE_SDB_FIS |
RT_AHCI_PORT_INTE_DMAS_FIS | RT_AHCI_PORT_INTE_PIOS_FIS |
RT_AHCI_PORT_INTE_D2H_REG_FIS;
HWREG32(port->regs + RT_AHCI_PORT_INTE) = port->int_enabled;
rt_completion_init(&port->done);
}
rt_snprintf(dev_name, sizeof(dev_name), "ahci-%s",
rt_dm_dev_get_name(host->parent.dev));
rt_hw_interrupt_install(host->irq, ahci_isr, host, dev_name);
rt_hw_interrupt_umask(host->irq);
scsi = &host->parent;
scsi->max_lun = rt_max_t(rt_size_t, scsi->max_lun, 1);
scsi->max_id = host->ports_nr;
scsi->ops = &ahci_scsi_ops;
if ((err = rt_scsi_host_register(scsi)))
{
goto _fail;
}
return RT_EOK;
_fail:
rt_hw_interrupt_mask(host->irq);
rt_pic_detach_irq(host->irq, host);
return err;
}
rt_err_t rt_ahci_host_unregister(struct rt_ahci_host *host)
{
rt_err_t err;
struct rt_scsi_host *scsi;
if (!host)
{
return -RT_EINVAL;
}
scsi = &host->parent;
if ((err = rt_scsi_host_unregister(scsi)))
{
return err;
}
rt_hw_interrupt_mask(host->irq);
rt_pic_detach_irq(host->irq, host);
for (int i = 0; i < host->ports_nr; ++i)
{
struct rt_ahci_port *port = &host->ports[i];
if (port->ataid)
{
rt_free(port->ataid);
}
HWREG32(port->regs) &= ~(RT_AHCI_PORT_CMD_ACTIVE | RT_AHCI_PORT_CMD_POWER_ON |
RT_AHCI_PORT_CMD_SPIN_UP | RT_AHCI_PORT_CMD_START);
if (port->dma)
{
rt_dma_free_coherent(host->parent.dev, RT_AHCI_DMA_SIZE, port->dma,
port->dma_handle);
}
}
HWREG32(host->regs + RT_AHCI_HBA_GHC) &= ~(RT_AHCI_GHC_AHCI_EN | RT_AHCI_GHC_IRQ_EN);
return RT_EOK;
}

View File

@ -10,9 +10,9 @@
#include <rthw.h>
#include <rtdevice.h>
#include "audio_pipe.h"
#include "dev_audio_pipe.h"
static void _rt_pipe_resume_writer(struct rt_audio_pipe *pipe)
static void _rt_audio_pipe_resume_writer(struct rt_audio_pipe *pipe)
{
if (!rt_list_isempty(&pipe->suspended_write_list))
{
@ -30,7 +30,7 @@ static void _rt_pipe_resume_writer(struct rt_audio_pipe *pipe)
}
}
static rt_ssize_t rt_pipe_read(rt_device_t dev,
static rt_ssize_t rt_audio_pipe_read(rt_device_t dev,
rt_off_t pos,
void *buffer,
rt_size_t size)
@ -50,7 +50,7 @@ static rt_ssize_t rt_pipe_read(rt_device_t dev,
/* if the ringbuffer is empty, there won't be any writer waiting */
if (read_nbytes)
_rt_pipe_resume_writer(pipe);
_rt_audio_pipe_resume_writer(pipe);
rt_hw_interrupt_enable(level);
@ -78,7 +78,7 @@ static rt_ssize_t rt_pipe_read(rt_device_t dev,
}
else
{
_rt_pipe_resume_writer(pipe);
_rt_audio_pipe_resume_writer(pipe);
rt_hw_interrupt_enable(level);
break;
}
@ -88,7 +88,7 @@ static rt_ssize_t rt_pipe_read(rt_device_t dev,
return read_nbytes;
}
static void _rt_pipe_resume_reader(struct rt_audio_pipe *pipe)
static void _rt_audio_pipe_resume_reader(struct rt_audio_pipe *pipe)
{
if (pipe->parent.rx_indicate)
pipe->parent.rx_indicate(&pipe->parent,
@ -110,7 +110,7 @@ static void _rt_pipe_resume_reader(struct rt_audio_pipe *pipe)
}
}
static rt_ssize_t rt_pipe_write(rt_device_t dev,
static rt_ssize_t rt_audio_pipe_write(rt_device_t dev,
rt_off_t pos,
const void *buffer,
rt_size_t size)
@ -135,7 +135,7 @@ static rt_ssize_t rt_pipe_write(rt_device_t dev,
write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer),
(const rt_uint8_t *)buffer, size);
_rt_pipe_resume_reader(pipe);
_rt_audio_pipe_resume_reader(pipe);
rt_hw_interrupt_enable(level);
@ -164,7 +164,7 @@ static rt_ssize_t rt_pipe_write(rt_device_t dev,
}
else
{
_rt_pipe_resume_reader(pipe);
_rt_audio_pipe_resume_reader(pipe);
rt_hw_interrupt_enable(level);
break;
}
@ -174,7 +174,7 @@ static rt_ssize_t rt_pipe_write(rt_device_t dev,
return write_nbytes;
}
static rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args)
static rt_err_t rt_audio_pipe_control(rt_device_t dev, int cmd, void *args)
{
struct rt_audio_pipe *pipe;
@ -191,9 +191,9 @@ const static struct rt_device_ops audio_pipe_ops =
RT_NULL,
RT_NULL,
RT_NULL,
rt_pipe_read,
rt_pipe_write,
rt_pipe_control
rt_audio_pipe_read,
rt_audio_pipe_write,
rt_audio_pipe_control
};
#endif
@ -235,9 +235,9 @@ rt_err_t rt_audio_pipe_init(struct rt_audio_pipe *pipe,
pipe->parent.init = RT_NULL;
pipe->parent.open = RT_NULL;
pipe->parent.close = RT_NULL;
pipe->parent.read = rt_pipe_read;
pipe->parent.write = rt_pipe_write;
pipe->parent.control = rt_pipe_control;
pipe->parent.read = rt_audio_pipe_read;
pipe->parent.write = rt_audio_pipe_write;
pipe->parent.control = rt_audio_pipe_control;
#endif
return rt_device_register(&(pipe->parent), name, RT_DEVICE_FLAG_RDWR);

View File

@ -6,8 +6,8 @@
* Change Logs:
* Date Author Notes
*/
#ifndef __AUDIO_PIPE_H__
#define __AUDIO_PIPE_H__
#ifndef __DEV_AUDIO_PIPE_H__
#define __DEV_AUDIO_PIPE_H__
/**
* Pipe Device
@ -72,4 +72,4 @@ rt_err_t rt_audio_pipe_create(const char *name, rt_int32_t flag, rt_size_t size)
void rt_audio_pipe_destroy(struct rt_audio_pipe *pipe);
#endif /* RT_USING_HEAP */
#endif /* __AUDIO_PIPE_H__ */
#endif /* __DEV_AUDIO_PIPE_H__ */

View File

@ -0,0 +1,7 @@
menuconfig RT_USING_BLK
bool "Using Block device drivers"
default n
if RT_USING_BLK
rsource "partitions/Kconfig"
endif

View File

@ -0,0 +1,23 @@
from building import *
group = []
objs = []
if not GetDepend(['RT_USING_BLK']):
Return('group')
cwd = GetCurrentDir()
list = os.listdir(cwd)
CPPPATH = [cwd + '/../include']
src = ['blk.c', 'blk_dev.c', 'blk_dfs.c', 'blk_partition.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
objs = objs + group
Return('objs')

View File

@ -0,0 +1,573 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI the first version
*/
#define DBG_TAG "rtdm.blk"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include "blk_dev.h"
#include "blk_dfs.h"
static void blk_remove_all(struct rt_blk_disk *disk)
{
struct rt_blk_device *blk, *blk_next;
/* Remove all partitions */
rt_list_for_each_entry_safe(blk, blk_next, &disk->part_nodes, list)
{
disk_remove_blk_dev(blk, RT_TRUE);
}
}
static rt_err_t blk_open(rt_device_t dev, rt_uint16_t oflag)
{
struct rt_blk_disk *disk = to_blk_disk(dev);
if (disk->read_only && (oflag & RT_DEVICE_OFLAG_WRONLY))
{
return -RT_EINVAL;
}
return RT_EOK;
}
static rt_err_t blk_close(rt_device_t dev)
{
return RT_EOK;
}
static rt_ssize_t blk_read(rt_device_t dev, rt_off_t sector,
void *buffer, rt_size_t sector_count)
{
rt_ssize_t res;
struct rt_blk_disk *disk = to_blk_disk(dev);
rt_sem_take(&disk->usr_lock, RT_WAITING_FOREVER);
res = disk->ops->read(disk, sector, buffer, sector_count);
rt_sem_release(&disk->usr_lock);
return res;
}
static rt_ssize_t blk_write(rt_device_t dev, rt_off_t sector,
const void *buffer, rt_size_t sector_count)
{
rt_ssize_t res;
struct rt_blk_disk *disk = to_blk_disk(dev);
if (!disk->read_only)
{
rt_sem_take(&disk->usr_lock, RT_WAITING_FOREVER);
res = disk->ops->write(disk, sector, buffer, sector_count);
rt_sem_release(&disk->usr_lock);
return res;
}
return -RT_ENOSYS;
}
static rt_ssize_t blk_parallel_read(rt_device_t dev, rt_off_t sector,
void *buffer, rt_size_t sector_count)
{
struct rt_blk_disk *disk = to_blk_disk(dev);
return disk->ops->read(disk, sector, buffer, sector_count);
}
static rt_ssize_t blk_parallel_write(rt_device_t dev, rt_off_t sector,
const void *buffer, rt_size_t sector_count)
{
struct rt_blk_disk *disk = to_blk_disk(dev);
if (!disk->read_only)
{
return disk->ops->write(disk, sector, buffer, sector_count);
}
return -RT_ENOSYS;
}
static rt_err_t blk_control(rt_device_t dev, int cmd, void *args)
{
rt_err_t err;
struct rt_blk_disk *disk = to_blk_disk(dev);
switch (cmd)
{
case RT_DEVICE_CTRL_BLK_GETGEOME:
if (args)
{
err = disk->ops->getgeome(disk, args);
}
else
{
err = -RT_EINVAL;
}
break;
case RT_DEVICE_CTRL_BLK_SYNC:
if (disk->ops->sync)
{
rt_sem_take(&disk->usr_lock, RT_WAITING_FOREVER);
spin_lock(&disk->lock);
err = disk->ops->sync(disk);
spin_unlock(&disk->lock);
rt_sem_release(&disk->usr_lock);
}
else
{
err = -RT_ENOSYS;
}
break;
case RT_DEVICE_CTRL_BLK_ERASE:
if (disk->ops->erase)
{
rt_sem_take(&disk->usr_lock, RT_WAITING_FOREVER);
spin_lock(&disk->lock);
if (disk->parent.ref_count != 1)
{
err = -RT_EBUSY;
goto _unlock;
}
blk_remove_all(disk);
err = disk->ops->erase(disk);
_unlock:
spin_unlock(&disk->lock);
rt_sem_release(&disk->usr_lock);
}
else
{
err = -RT_ENOSYS;
}
break;
case RT_DEVICE_CTRL_BLK_AUTOREFRESH:
if (disk->ops->autorefresh)
{
err = disk->ops->autorefresh(disk, !!args);
}
else
{
err = -RT_ENOSYS;
}
break;
case RT_DEVICE_CTRL_BLK_PARTITION:
err = -RT_EINVAL;
break;
case RT_DEVICE_CTRL_BLK_SSIZEGET:
device_get_blk_ssize(dev, args);
err = RT_EOK;
break;
case RT_DEVICE_CTRL_ALL_BLK_SSIZEGET:
device_get_all_blk_ssize(dev, args);
err = RT_EOK;
break;
default:
if (disk->ops->control)
{
err = disk->ops->control(disk, RT_NULL, cmd, args);
}
else
{
err = -RT_ENOSYS;
}
break;
}
return err;
}
#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops blk_ops =
{
.open = blk_open,
.close = blk_close,
.read = blk_read,
.write = blk_write,
.control = blk_control,
};
const static struct rt_device_ops blk_parallel_ops =
{
.open = blk_open,
.close = blk_close,
.read = blk_parallel_read,
.write = blk_parallel_write,
.control = blk_control,
};
#endif /* RT_USING_DEVICE_OPS */
rt_err_t rt_hw_blk_disk_register(struct rt_blk_disk *disk)
{
rt_err_t err;
#ifdef RT_USING_DM
int device_id;
#endif
const char *disk_name;
rt_uint16_t flags = RT_DEVICE_FLAG_RDONLY;
if (!disk || !disk->ops)
{
return -RT_EINVAL;
}
#ifdef RT_USING_DM
if (!disk->ida)
{
return -RT_EINVAL;
}
#endif
#if RT_NAME_MAX > 0
if (disk->parent.parent.name[0] == '\0')
#else
if (disk->parent.parent.name)
#endif
{
return -RT_EINVAL;
}
#ifdef RT_USING_DM
if ((device_id = rt_dm_ida_alloc(disk->ida)) < 0)
{
return -RT_EFULL;
}
#endif
disk->__magic = RT_BLK_DISK_MAGIC;
disk_name = to_disk_name(disk);
err = rt_sem_init(&disk->usr_lock, disk_name, 1, RT_IPC_FLAG_PRIO);
if (err)
{
#ifdef RT_USING_DM
rt_dm_ida_free(disk->ida, device_id);
#endif
LOG_E("%s: Init user mutex error = %s", rt_strerror(err));
return err;
}
rt_list_init(&disk->part_nodes);
rt_spin_lock_init(&disk->lock);
disk->parent.type = RT_Device_Class_Block;
#ifdef RT_USING_DEVICE_OPS
if (disk->parallel_io)
{
disk->parent.ops = &blk_parallel_ops;
}
else
{
disk->parent.ops = &blk_ops;
}
#else
disk->parent.open = blk_open;
disk->parent.close = blk_close;
if (disk->parallel_io)
{
disk->parent.read = blk_parallel_read;
disk->parent.write = blk_parallel_write;
}
else
{
disk->parent.read = blk_read;
disk->parent.write = blk_write;
}
disk->parent.control = blk_control;
#endif
if (!disk->ops->write)
{
disk->read_only = RT_TRUE;
}
if (!disk->read_only)
{
flags |= RT_DEVICE_FLAG_WRONLY;
}
#ifdef RT_USING_DM
disk->parent.master_id = disk->ida->master_id;
disk->parent.device_id = device_id;
#endif
device_set_blk_fops(&disk->parent);
err = rt_device_register(&disk->parent, disk_name, flags);
if (err)
{
rt_sem_detach(&disk->usr_lock);
}
/* Ignore partition scanning errors */
rt_blk_disk_probe_partition(disk);
return err;
}
rt_err_t rt_hw_blk_disk_unregister(struct rt_blk_disk *disk)
{
rt_err_t err;
if (!disk)
{
return -RT_EINVAL;
}
spin_lock(&disk->lock);
if (disk->parent.ref_count > 0)
{
err = -RT_EBUSY;
goto _unlock;
}
/* Flush all data */
if (disk->ops->sync)
{
err = disk->ops->sync(disk);
if (err)
{
LOG_E("%s: Sync error = %s", to_disk_name(disk), rt_strerror(err));
goto _unlock;
}
}
rt_sem_detach(&disk->usr_lock);
blk_remove_all(disk);
#ifdef RT_USING_DM
rt_dm_ida_free(disk->ida, disk->parent.device_id);
#endif
err = rt_device_unregister(&disk->parent);
_unlock:
spin_unlock(&disk->lock);
return err;
}
rt_ssize_t rt_blk_disk_get_capacity(struct rt_blk_disk *disk)
{
rt_ssize_t res;
struct rt_device_blk_geometry geometry;
if (!disk)
{
return -RT_EINVAL;
}
res = disk->ops->getgeome(disk, &geometry);
if (!res)
{
return geometry.sector_count;
}
return res;
}
rt_ssize_t rt_blk_disk_get_logical_block_size(struct rt_blk_disk *disk)
{
rt_ssize_t res;
struct rt_device_blk_geometry geometry;
if (!disk)
{
return -RT_EINVAL;
}
res = disk->ops->getgeome(disk, &geometry);
if (!res)
{
return geometry.bytes_per_sector;
}
return res;
}
#ifdef RT_USING_DFS_MNTTABLE
static int blk_dfs_mnt_table(void)
{
rt_ubase_t level;
struct rt_object *obj;
struct rt_device *dev;
struct rt_blk_disk *disk;
struct rt_blk_device *blk_dev;
struct rt_object_information *info = rt_object_get_information(RT_Object_Class_Device);
level = rt_hw_interrupt_disable();
rt_list_for_each_entry(obj, &info->object_list, list)
{
dev = rt_container_of(obj, struct rt_device, parent);
if (dev->type != RT_Device_Class_Block)
{
continue;
}
disk = to_blk_disk(dev);
if (disk->__magic != RT_BLK_DISK_MAGIC)
{
continue;
}
if (disk->max_partitions == RT_BLK_PARTITION_NONE)
{
dfs_mount_device(&disk->parent);
continue;
}
rt_list_for_each_entry(blk_dev, &disk->part_nodes, list)
{
dfs_mount_device(&blk_dev->parent);
}
}
rt_hw_interrupt_enable(level);
return 0;
}
INIT_ENV_EXPORT(blk_dfs_mnt_table);
#endif /* RT_USING_DFS_MNTTABLE */
#if defined(RT_USING_CONSOLE) && defined(RT_USING_MSH)
const char *convert_size(struct rt_device_blk_geometry *geome,
rt_size_t sector_count, rt_size_t *out_cap, rt_size_t *out_minor)
{
rt_size_t cap, minor = 0;
int size_index = 0;
const char *size_name[] = { "B", "K", "M", "G", "T", "P", "E" };
cap = geome->bytes_per_sector * sector_count;
for (size_index = 0; size_index < RT_ARRAY_SIZE(size_name) - 1; ++size_index)
{
if (cap < 1024)
{
break;
}
/* Only one decimal point */
minor = (cap % 1024) * 10 / 1024;
cap = cap / 1024;
}
*out_cap = cap;
*out_minor = minor;
return size_name[size_index];
}
static int list_blk(int argc, char**argv)
{
rt_ubase_t level;
rt_size_t cap, minor;
const char *size_name;
struct rt_object *obj;
struct rt_device *dev;
struct rt_blk_disk *disk;
struct rt_blk_device *blk_dev;
struct rt_device_blk_geometry geome;
struct rt_object_information *info = rt_object_get_information(RT_Object_Class_Device);
level = rt_hw_interrupt_disable();
rt_kprintf("%-*.s MAJ:MIN RM SIZE\tRO TYPE MOUNTPOINT\n", RT_NAME_MAX, "NAME");
rt_list_for_each_entry(obj, &info->object_list, list)
{
dev = rt_container_of(obj, struct rt_device, parent);
if (dev->type != RT_Device_Class_Block)
{
continue;
}
disk = to_blk_disk(dev);
if (disk->__magic != RT_BLK_DISK_MAGIC)
{
continue;
}
if (disk->ops->getgeome(disk, &geome))
{
continue;
}
size_name = convert_size(&geome, geome.sector_count, &cap, &minor);
rt_kprintf("%-*.s %3u.%-3u %u %u.%u%s\t%u disk %s\n",
RT_NAME_MAX, to_disk_name(disk),
#ifdef RT_USING_DM
disk->parent.master_id, disk->parent.device_id,
#else
0, 0,
#endif
disk->removable, cap, minor, size_name, disk->read_only,
disk->max_partitions != RT_BLK_PARTITION_NONE ? "\b" :
(dfs_filesystem_get_mounted_path(&disk->parent) ? : "\b"));
rt_list_for_each_entry(blk_dev, &disk->part_nodes, list)
{
size_name = convert_size(&geome, blk_dev->sector_count, &cap, &minor);
rt_kprintf("%c--%-*.s %3u.%-3u %u %u.%u%s\t%u part %s\n",
blk_dev->list.next != &disk->part_nodes ? '|' : '`',
RT_NAME_MAX - 3, to_blk_name(blk_dev),
#ifdef RT_USING_DM
blk_dev->parent.master_id, blk_dev->parent.device_id,
#else
0, 0,
#endif
disk->removable, cap, minor, size_name, disk->read_only,
dfs_filesystem_get_mounted_path(&blk_dev->parent) ? : "");
}
}
rt_hw_interrupt_enable(level);
return 0;
}
MSH_CMD_EXPORT(list_blk, dump all of blks information);
#endif /* RT_USING_CONSOLE && RT_USING_MSH */

View File

@ -0,0 +1,297 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI first version
*/
#include "blk_dev.h"
#include "blk_dfs.h"
#define DBG_TAG "blk.dm"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#ifdef RT_USING_DFS
#include <dfs_fs.h>
#endif
static rt_err_t blk_dev_open(rt_device_t dev, rt_uint16_t oflag)
{
struct rt_blk_device *blk = to_blk(dev);
return rt_device_open(&blk->disk->parent, oflag);
}
static rt_err_t blk_dev_close(rt_device_t dev)
{
struct rt_blk_device *blk = to_blk(dev);
return rt_device_close(&blk->disk->parent);
}
static rt_ssize_t blk_dev_read(rt_device_t dev, rt_off_t sector,
void *buffer, rt_size_t sector_count)
{
struct rt_blk_device *blk = to_blk(dev);
if (sector <= blk->sector_start + blk->sector_count &&
sector_count <= blk->sector_count)
{
return rt_device_read(&blk->disk->parent,
blk->sector_start + sector, buffer, sector_count);
}
return -RT_EINVAL;
}
static rt_ssize_t blk_dev_write(rt_device_t dev, rt_off_t sector,
const void *buffer, rt_size_t sector_count)
{
struct rt_blk_device *blk = to_blk(dev);
if (sector <= blk->sector_start + blk->sector_count &&
sector_count <= blk->sector_count)
{
return rt_device_write(&blk->disk->parent,
blk->sector_start + sector, buffer, sector_count);
}
return -RT_EINVAL;
}
static rt_err_t blk_dev_control(rt_device_t dev, int cmd, void *args)
{
rt_err_t err = -RT_EINVAL;
struct rt_blk_device *blk = to_blk(dev);
struct rt_blk_disk *disk = blk->disk;
struct rt_device_blk_geometry disk_geometry, *geometry;
switch (cmd)
{
case RT_DEVICE_CTRL_BLK_GETGEOME:
if ((geometry = args))
{
if (!(err = disk->ops->getgeome(disk, &disk_geometry)))
{
geometry->bytes_per_sector = disk_geometry.bytes_per_sector;
geometry->block_size = disk_geometry.block_size;
geometry->sector_count = blk->sector_count;
}
}
else
{
err = -RT_EINVAL;
}
break;
case RT_DEVICE_CTRL_BLK_SYNC:
rt_device_control(&disk->parent, cmd, args);
break;
case RT_DEVICE_CTRL_BLK_ERASE:
case RT_DEVICE_CTRL_BLK_AUTOREFRESH:
if (disk->partitions <= 1)
{
rt_device_control(&disk->parent, cmd, args);
}
else
{
err = -RT_EIO;
}
break;
case RT_DEVICE_CTRL_BLK_PARTITION:
if (args)
{
rt_memcpy(args, &blk->partition, sizeof(blk->partition));
}
else
{
err = -RT_EINVAL;
}
break;
case RT_DEVICE_CTRL_BLK_SSIZEGET:
device_get_blk_ssize(dev, args);
err = RT_EOK;
break;
case RT_DEVICE_CTRL_ALL_BLK_SSIZEGET:
device_get_all_blk_ssize(dev, args);
err = RT_EOK;
break;
default:
if (disk->ops->control)
{
err = disk->ops->control(disk, blk, cmd, args);
}
break;
}
return err;
}
#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops blk_dev_ops =
{
.open = blk_dev_open,
.close = blk_dev_close,
.read = blk_dev_read,
.write = blk_dev_write,
.control = blk_dev_control,
};
#endif
rt_err_t blk_dev_initialize(struct rt_blk_device *blk)
{
struct rt_device *dev;
if (!blk)
{
return -RT_EINVAL;
}
dev = &blk->parent;
dev->type = RT_Device_Class_Block;
#ifdef RT_USING_DEVICE_OPS
dev->ops = &blk_dev_ops;
#else
dev->open = blk_dev_open;
dev->close = blk_dev_close;
dev->read = blk_dev_read;
dev->write = blk_dev_write;
dev->control = blk_dev_control;
#endif
return RT_EOK;
}
rt_err_t disk_add_blk_dev(struct rt_blk_disk *disk, struct rt_blk_device *blk)
{
rt_err_t err;
#ifdef RT_USING_DM
int device_id;
#endif
const char *disk_name, *name_fmt;
if (!disk || !blk)
{
return -RT_EINVAL;
}
#ifdef RT_USING_DM
if ((device_id = rt_dm_ida_alloc(disk->ida)) < 0)
{
return -RT_EFULL;
}
#endif
blk->disk = disk;
rt_list_init(&blk->list);
disk_name = to_disk_name(disk);
/* End is [a-zA-Z] or [0-9] */
if (disk_name[rt_strlen(disk_name) - 1] < 'a')
{
name_fmt = "%sp%d";
}
else
{
name_fmt = "%s%d";
}
#ifdef RT_USING_DM
rt_dm_dev_set_name(&blk->parent, name_fmt, disk_name, blk->partno);
blk->parent.master_id = disk->ida->master_id;
blk->parent.device_id = device_id;
#else
rt_snprintf(blk->parent.parent.name, RT_NAME_MAX, name_fmt, disk_name, blk->partno);
#endif
device_set_blk_fops(&blk->parent);
err = rt_device_register(&blk->parent, to_blk_name(blk),
disk->parent.flag & RT_DEVICE_FLAG_RDWR);
if (err)
{
#ifdef RT_USING_DM
rt_dm_ida_free(disk->ida, device_id);
#endif
return err;
}
spin_lock(&disk->lock);
rt_list_insert_before(&disk->part_nodes, &blk->list);
spin_unlock(&disk->lock);
return RT_EOK;
}
rt_err_t disk_remove_blk_dev(struct rt_blk_device *blk, rt_bool_t lockless)
{
struct rt_blk_disk *disk;
if (!blk)
{
return -RT_EINVAL;
}
disk = blk->disk;
if (!disk)
{
return -RT_EINVAL;
}
else
{
#ifdef RT_USING_DFS
const char *mountpath;
if ((mountpath = dfs_filesystem_get_mounted_path(&blk->parent)))
{
dfs_unmount(mountpath);
LOG_D("%s: Unmount file system on %s",
to_blk_name(blk), mountpath);
}
#endif
}
#ifdef RT_USING_DM
rt_dm_ida_free(disk->ida, blk->parent.device_id);
#endif
rt_device_unregister(&blk->parent);
if (!lockless)
{
spin_lock(&disk->lock);
}
rt_list_remove(&blk->list);
if (!lockless)
{
spin_unlock(&disk->lock);
}
--disk->partitions;
return RT_EOK;
}
rt_uint32_t blk_request_ioprio(void)
{
struct rt_thread *task = rt_thread_self();
return task ? RT_SCHED_PRIV(task).current_priority : 0;
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI first version
*/
#ifndef __BLK_DEV_H__
#define __BLK_DEV_H__
#include <rthw.h>
#include <rtthread.h>
#include <drivers/blk.h>
#include <drivers/misc.h>
#define to_blk_disk(dev) rt_container_of(dev, struct rt_blk_disk, parent)
#define to_blk(dev) rt_container_of(dev, struct rt_blk_device, parent)
#ifdef RT_USING_DM
#define to_disk_name(disk) rt_dm_dev_get_name(&(disk)->parent)
#define to_blk_name(blk) rt_dm_dev_get_name(&(blk)->parent)
#else
#define to_disk_name(disk) (disk)->parent.parent.name
#define to_blk_name(blk) (blk)->parent.parent.name
#endif
/* %c%c name */
#define letter_name(n) ('a' + (n) / ((n) >= 26 ? (26 * 2) : 1)), ((n) >= 26 ? 'a' + (n) % 26 : '\0')
rt_inline void spin_lock(struct rt_spinlock *spinlock)
{
rt_hw_spin_lock(&spinlock->lock);
}
rt_inline void spin_unlock(struct rt_spinlock *spinlock)
{
rt_hw_spin_unlock(&spinlock->lock);
}
rt_err_t blk_dev_initialize(struct rt_blk_device *blk);
rt_err_t disk_add_blk_dev(struct rt_blk_disk *disk, struct rt_blk_device *blk);
rt_err_t disk_remove_blk_dev(struct rt_blk_device *blk, rt_bool_t lockless);
rt_uint32_t blk_request_ioprio(void);
#endif /* __BLK_DEV_H__ */

View File

@ -0,0 +1,274 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-08-08 GuEe-GUI first version
*/
#include "blk_dfs.h"
#include <dfs_file.h>
#include <drivers/classes/block.h>
#if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_DFS_V2)
struct blk_fops_data
{
struct rt_device_blk_geometry geometry;
};
static int blk_fops_open(struct dfs_file *file)
{
struct rt_device *dev = file->vnode->data;
struct blk_fops_data *data = rt_malloc(sizeof(*data));
if (!data)
{
return (int)-RT_ENOMEM;
}
dev->user_data = data;
rt_device_control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &data->geometry);
rt_device_control(dev, RT_DEVICE_CTRL_ALL_BLK_SSIZEGET, &file->vnode->size);
return 0;
}
static int blk_fops_close(struct dfs_file *file)
{
struct rt_device *dev = file->vnode->data;
rt_free(dev->user_data);
dev->user_data = RT_NULL;
return 0;
}
static int blk_fops_ioctl(struct dfs_file *file, int cmd, void *arg)
{
struct rt_device *dev = file->vnode->data;
return (int)rt_device_control(dev, cmd, arg);
}
static ssize_t blk_fops_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
{
void *rbuf;
rt_ssize_t res = 0;
int bytes_per_sector, blk_pos, first_offs, rsize = 0;
struct rt_device *dev = file->vnode->data;
struct blk_fops_data *data = dev->user_data;
bytes_per_sector = data->geometry.bytes_per_sector;
blk_pos = *pos / bytes_per_sector;
first_offs = *pos % bytes_per_sector;
if ((rbuf = rt_malloc(bytes_per_sector)))
{
/*
** #1: read first unalign block size.
*/
res = rt_device_read(dev, blk_pos, rbuf, 1);
if (res == 1)
{
if (count > bytes_per_sector - first_offs)
{
rsize = bytes_per_sector - first_offs;
}
else
{
rsize = count;
}
rt_memcpy(buf, rbuf + first_offs, rsize);
++blk_pos;
/*
** #2: read continuous block size.
*/
while (rsize < count)
{
res = rt_device_read(dev, blk_pos++, rbuf, 1);
if (res != 1)
{
break;
}
if (count - rsize >= bytes_per_sector)
{
rt_memcpy(buf + rsize, rbuf, bytes_per_sector);
rsize += bytes_per_sector;
}
else
{
rt_memcpy(buf + rsize, rbuf, count - rsize);
rsize = count;
}
}
*pos += rsize;
}
rt_free(rbuf);
}
return rsize;
}
static ssize_t blk_fops_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
{
void *rbuf;
rt_ssize_t res = 0;
int bytes_per_sector, blk_pos, first_offs, wsize = 0;
struct rt_device *dev = file->vnode->data;
struct blk_fops_data *data = dev->user_data;
bytes_per_sector = data->geometry.bytes_per_sector;
blk_pos = *pos / bytes_per_sector;
first_offs = *pos % bytes_per_sector;
/*
** #1: write first unalign block size.
*/
if (first_offs != 0)
{
if (count > bytes_per_sector - first_offs)
{
wsize = bytes_per_sector - first_offs;
}
else
{
wsize = count;
}
if ((rbuf = rt_malloc(bytes_per_sector)))
{
res = rt_device_read(dev, blk_pos, rbuf, 1);
if (res == 1)
{
rt_memcpy(rbuf + first_offs, buf, wsize);
res = rt_device_write(dev, blk_pos, (const void *)rbuf, 1);
if (res == 1)
{
blk_pos += 1;
rt_free(rbuf);
goto _goon;
}
}
rt_free(rbuf);
}
return 0;
}
_goon:
/*
** #2: write continuous block size.
*/
if ((count - wsize) / bytes_per_sector != 0)
{
res = rt_device_write(dev, blk_pos, buf + wsize, (count - wsize) / bytes_per_sector);
wsize += res * bytes_per_sector;
blk_pos += res;
if (res != (count - wsize) / bytes_per_sector)
{
*pos += wsize;
return wsize;
}
}
/*
** # 3: write last unalign block size.
*/
if ((count - wsize) != 0)
{
if ((rbuf = rt_malloc(bytes_per_sector)))
{
res = rt_device_read(dev, blk_pos, rbuf, 1);
if (res == 1)
{
rt_memcpy(rbuf, buf + wsize, count - wsize);
res = rt_device_write(dev, blk_pos, (const void *)rbuf, 1);
if (res == 1)
{
wsize += count - wsize;
}
}
rt_free(rbuf);
}
}
*pos += wsize;
return wsize;
}
static int blk_fops_flush(struct dfs_file *file)
{
struct rt_device *dev = file->vnode->data;
return (int)rt_device_control(dev, RT_DEVICE_CTRL_BLK_SYNC, RT_NULL);
}
static int blk_fops_poll(struct dfs_file *file, struct rt_pollreq *req)
{
int mask = 0;
return mask;
}
const static struct dfs_file_ops blk_fops =
{
.open = blk_fops_open,
.close = blk_fops_close,
.ioctl = blk_fops_ioctl,
.read = blk_fops_read,
.write = blk_fops_write,
.flush = blk_fops_flush,
.lseek = generic_dfs_lseek,
.poll = blk_fops_poll
};
void device_set_blk_fops(struct rt_device *dev)
{
dev->fops = &blk_fops;
}
#else
void device_set_blk_fops(struct rt_device *dev)
{
}
#endif /* RT_USING_POSIX_DEVIO && RT_USING_DFS_V2 */
void device_get_blk_ssize(struct rt_device *dev, void *args)
{
rt_uint32_t bytes_per_sector;
struct rt_device_blk_geometry geometry;
rt_device_control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
bytes_per_sector = geometry.bytes_per_sector;
RT_ASSERT(sizeof(bytes_per_sector) == sizeof(geometry.bytes_per_sector));
rt_memcpy(args, &bytes_per_sector, sizeof(bytes_per_sector));
}
void device_get_all_blk_ssize(struct rt_device *dev, void *args)
{
rt_uint64_t count_mul_per;
struct rt_device_blk_geometry geometry;
rt_device_control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
count_mul_per = geometry.bytes_per_sector * geometry.sector_count;
rt_memcpy(args, &count_mul_per, sizeof(count_mul_per));
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-08-08 GuEe-GUI first version
*/
#ifndef __BLK_DFS_H__
#define __BLK_DFS_H__
#include <rtdef.h>
#define RT_DEVICE_CTRL_BLK_SSIZEGET 0x00001268 /**< get number of bytes per sector */
#define RT_DEVICE_CTRL_ALL_BLK_SSIZEGET 0x80081272 /**< get number of bytes per sector * sector counts */
void device_set_blk_fops(struct rt_device *dev);
void device_get_blk_ssize(struct rt_device *dev, void *args);
void device_get_all_blk_ssize(struct rt_device *dev, void *args);
#endif /* __BLK_DFS_H__ */

View File

@ -0,0 +1,154 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI the first version
*/
#define DBG_TAG "blk.part"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include "blk_partition.h"
static rt_err_t (*partition_list[])(struct rt_blk_disk *) =
{
#ifdef RT_BLK_PARTITION_EFI
efi_partition,
#endif
#ifdef RT_BLK_PARTITION_DFS
dfs_partition,
#endif
};
rt_err_t blk_put_partition(struct rt_blk_disk *disk, const char *type,
rt_size_t start, rt_size_t count, int partno)
{
rt_err_t err;
struct rt_blk_device *blk = rt_calloc(1, sizeof(*blk));
if (type && rt_strcmp(type, "dfs"))
{
rt_uint32_t ssz = rt_blk_disk_get_logical_block_size(disk);
rt_kprintf("found part[%u], begin: %lu, size: ", partno, start * ssz);
if ((count >> 11) == 0)
{
rt_kprintf("%u%cB\n", count >> 1, 'K'); /* KB */
}
else
{
rt_uint32_t size_mb = count >> 11; /* MB */
if ((size_mb >> 10) == 0)
{
rt_kprintf("%u.%u%cB\n", size_mb, (count >> 1) & 0x3ff, 'M');
}
else
{
rt_kprintf("%u.%u%cB\n", size_mb >> 10, size_mb & 0x3ff, 'G');
}
}
}
if (!blk)
{
err = -RT_ENOMEM;
goto _fail;
}
err = blk_dev_initialize(blk);
if (err)
{
goto _fail;
}
blk->partno = partno;
blk->sector_start = start;
blk->sector_count = count;
blk->partition.offset = start;
blk->partition.size = count;
blk->partition.lock = &disk->usr_lock;
err = disk_add_blk_dev(disk, blk);
if (err)
{
goto _fail;
}
++disk->partitions;
return RT_EOK;
_fail:
LOG_E("%s: Put partition.%s[%u] start = %lu count = %lu error = %s",
to_disk_name(disk), type, partno, start, count, rt_strerror(err));
if (blk)
{
rt_free(blk);
}
return err;
}
rt_err_t rt_blk_disk_probe_partition(struct rt_blk_disk *disk)
{
rt_err_t err = RT_EOK;
if (!disk)
{
return -RT_EINVAL;
}
LOG_D("%s: Probing disk partitions", to_disk_name(disk));
if (disk->partitions)
{
return err;
}
err = -RT_EEMPTY;
if (disk->max_partitions == RT_BLK_PARTITION_NONE)
{
LOG_D("%s: Unsupported partitions", to_disk_name(disk));
return err;
}
for (int i = 0; i < RT_ARRAY_SIZE(partition_list); ++i)
{
rt_err_t part_err = partition_list[i](disk);
if (part_err == -RT_ENOMEM)
{
err = part_err;
break;
}
if (!part_err)
{
err = RT_EOK;
break;
}
}
if ((err && err != -RT_ENOMEM) || disk->partitions == 0)
{
/* No partition found */
rt_size_t total_sectors = rt_blk_disk_get_capacity(disk);
err = blk_put_partition(disk, RT_NULL, 0, total_sectors, 0);
}
return err;
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI first version
*/
#ifndef __BLK_PARTITION_H__
#define __BLK_PARTITION_H__
#include "blk_dev.h"
rt_err_t blk_put_partition(struct rt_blk_disk *disk, const char *type,
rt_size_t start, rt_size_t count, int partno);
rt_err_t dfs_partition(struct rt_blk_disk *disk);
rt_err_t efi_partition(struct rt_blk_disk *disk);
#endif /* __BLK_PARTITION_H__ */

View File

@ -0,0 +1,12 @@
menu "Partition Types"
config RT_BLK_PARTITION_DFS
bool "DFS Partition support"
depends on RT_USING_DFS
default y
config RT_BLK_PARTITION_EFI
bool "EFI Globally Unique Identifier (GUID) Partition support"
default y
endmenu

View File

@ -0,0 +1,18 @@
from building import *
group = []
cwd = GetCurrentDir()
CPPPATH = [cwd + '/../../include']
src = []
if GetDepend(['RT_BLK_PARTITION_DFS']):
src += ['dfs.c']
if GetDepend(['RT_BLK_PARTITION_EFI']):
src += ['efi.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2011-07-25 weety first version
* 2023-02-25 GuEe-GUI make blk interface
*/
#include "efi.h"
#define DBG_TAG "blk.part.dfs"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
rt_err_t dfs_partition(struct rt_blk_disk *disk)
{
rt_ssize_t res;
struct dfs_partition part;
rt_uint8_t *sector = rt_malloc(rt_blk_disk_get_logical_block_size(disk));
if (!sector)
{
return -RT_ENOMEM;
}
res = disk->ops->read(disk, 0, sector, 1);
if (res < 0)
{
rt_free(sector);
return res;
}
for (rt_size_t i = 0; i < disk->max_partitions; ++i)
{
res = dfs_filesystem_get_partition(&part, sector, i);
if (res)
{
break;
}
if (blk_put_partition(disk, "dfs", part.offset, part.size, i) == -RT_ENOMEM)
{
break;
}
}
rt_free(sector);
return RT_EOK;
}

View File

@ -0,0 +1,738 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-05-05 linzhenxing first version
* 2023-02-25 GuEe-GUI make blk interface
*/
#include "efi.h"
#define DBG_TAG "blk.part.efi"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
static rt_bool_t force_gpt = 0;
static int force_gpt_setup(void)
{
#ifdef RT_USING_OFW
force_gpt = !!rt_ofw_bootargs_select("gpt", 0);
#endif
return 0;
}
INIT_CORE_EXPORT(force_gpt_setup);
/**
* @brief This function is EFI version of crc32 function.
*
* @param buf the buffer to calculate crc32 of.
* @param len the length of buf.
* @return EFI-style CRC32 value for @buf.
*/
rt_inline rt_uint32_t efi_crc32(const rt_uint8_t *buf, rt_size_t len)
{
rt_ubase_t crc = 0xffffffffUL;
for (rt_size_t i = 0; i < len; ++i)
{
crc ^= buf[i];
for (int j = 0; j < 8; ++j)
{
crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320L : 0);
}
}
return ~crc;
}
/**
* @brief This function get number of last logical block of device.
*
* @param disk the blk of disk.
* @return last LBA value on success, 0 on error.
* This is stored (by sd and ide-geometry) in
* the part[0] entry for this disk, and is the number of
* physical sectors available on the disk.
*/
static rt_size_t last_lba(struct rt_blk_disk *disk)
{
return rt_blk_disk_get_capacity(disk) - 1ULL;
}
rt_inline int pmbr_part_valid(gpt_mbr_record *part)
{
if (part->os_type != EFI_PMBR_OSTYPE_EFI_GPT)
{
return 0;
}
/* set to 0x00000001 (i.e., the LBA of the GPT Partition Header) */
if (rt_le32_to_cpu(part->starting_lba) != GPT_PRIMARY_PARTITION_TABLE_LBA)
{
return 0;
}
return GPT_MBR_PROTECTIVE;
}
/**
* @brief This function test Protective MBR for validity.
*
* @param mbr the pointer to a legacy mbr structure.
* @param total_sectors the amount of sectors in the device
* @return
* 0 -> Invalid MBR
* 1 -> GPT_MBR_PROTECTIVE
* 2 -> GPT_MBR_HYBRID
*/
static int is_pmbr_valid(legacy_mbr *mbr, rt_size_t total_sectors)
{
rt_uint32_t sz = 0;
int part = 0, ret = 0; /* invalid by default */
if (!mbr || rt_le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE)
{
goto _done;
}
for (int i = 0; i < 4; ++i)
{
ret = pmbr_part_valid(&mbr->partition_record[i]);
if (ret == GPT_MBR_PROTECTIVE)
{
part = i;
/*
* Ok, we at least know that there's a protective MBR,
* now check if there are other partition types for
* hybrid MBR.
*/
goto _check_hybrid;
}
}
if (ret != GPT_MBR_PROTECTIVE)
{
goto _done;
}
_check_hybrid:
for (int i = 0; i < 4; i++)
{
if (mbr->partition_record[i].os_type != EFI_PMBR_OSTYPE_EFI_GPT &&
mbr->partition_record[i].os_type != 0x00)
{
ret = GPT_MBR_HYBRID;
}
}
/*
* Protective MBRs take up the lesser of the whole disk
* or 2 TiB (32bit LBA), ignoring the rest of the disk.
* Some partitioning programs, nonetheless, choose to set
* the size to the maximum 32-bit limitation, disregarding
* the disk size.
*
* Hybrid MBRs do not necessarily comply with this.
*
* Consider a bad value here to be a warning to support dd'ing
* an image from a smaller disk to a larger disk.
*/
if (ret == GPT_MBR_PROTECTIVE)
{
sz = rt_le32_to_cpu(mbr->partition_record[part].size_in_lba);
if (sz != (rt_uint32_t)total_sectors - 1 && sz != 0xffffffff)
{
LOG_W("GPT: mbr size in lba (%u) different than whole disk (%u)",
sz, rt_min_t(rt_uint32_t, total_sectors - 1, 0xffffffff));
}
}
_done:
return ret;
}
/**
* @brief This function read bytes from disk, starting at given LBA.
*
* @param disk the blk of disk.
* @param lba the Logical Block Address of the partition table.
* @param buffer the destination buffer.
* @param count the bytes to read.
* @return number of bytes read on success, 0 on error.
*/
static rt_size_t read_lba(struct rt_blk_disk *disk,
rt_uint64_t lba, rt_uint8_t *buffer, rt_size_t count)
{
rt_size_t totalreadcount = 0;
if (!buffer || lba > last_lba(disk))
{
return 0;
}
for (rt_uint64_t n = lba; count; ++n)
{
int copied = 512;
disk->ops->read(disk, n, buffer, 1);
if (copied > count)
{
copied = count;
}
buffer += copied;
totalreadcount += copied;
count -= copied;
}
return totalreadcount;
}
/**
* @brief This function reads partition entries from disk.
*
* @param disk the blk of disk.
* @param gpt the GPT header
* @return ptes on success, null on error.
*/
static gpt_entry *alloc_read_gpt_entries(struct rt_blk_disk *disk,
gpt_header *gpt)
{
rt_size_t count;
gpt_entry *pte;
rt_uint64_t entry_lba;
if (!gpt)
{
return RT_NULL;
}
count = (rt_size_t)rt_le32_to_cpu(gpt->num_partition_entries) *
rt_le32_to_cpu(gpt->sizeof_partition_entry);
if (!count)
{
return RT_NULL;
}
pte = rt_malloc(count);
if (!pte)
{
return RT_NULL;
}
entry_lba = rt_le64_to_cpu(gpt->partition_entry_lba);
if (read_lba(disk, entry_lba, (rt_uint8_t *)pte, count) < count)
{
rt_free(pte);
pte = RT_NULL;
return RT_NULL;
}
/* Remember to free pte when done */
return pte;
}
/**
* @brief This function allocates GPT header, reads into it from disk.
*
* @param disk the blk of disk.
* @param lba the Logical Block Address of the partition table
* @return GPT header on success, null on error.
*/
static gpt_header *alloc_read_gpt_header(struct rt_blk_disk *disk, rt_uint64_t lba)
{
gpt_header *gpt;
rt_uint32_t ssz = rt_blk_disk_get_logical_block_size(disk);
gpt = rt_malloc(ssz);
if (!gpt)
{
return RT_NULL;
}
if (read_lba(disk, lba, (rt_uint8_t *)gpt, ssz) < ssz)
{
rt_free(gpt);
gpt = RT_NULL;
return RT_NULL;
}
/* Remember to free gpt when finished with it */
return gpt;
}
/**
* @brief This function tests one GPT header and PTEs for validity.
*
* @param disk the blk of disk.
* @param lba the Logical Block Address of the GPT header to test.
* @param gpt the GPT header ptr, filled on return.
* @param ptes the PTEs ptr, filled on return.
* @returns true if valid, false on error.
* If valid, returns pointers to newly allocated GPT header and PTEs.
*/
static rt_bool_t is_gpt_valid(struct rt_blk_disk *disk,
rt_uint64_t lba, gpt_header **gpt, gpt_entry **ptes)
{
rt_uint32_t crc, origcrc;
rt_uint64_t lastlba, pt_size;
rt_ssize_t logical_block_size;
if (!ptes)
{
return RT_FALSE;
}
if (!(*gpt = alloc_read_gpt_header(disk, lba)))
{
return RT_FALSE;
}
/* Check the GUID Partition Table signature */
if (rt_le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE)
{
LOG_D("%s: GUID Partition Table Header signature is wrong: %lld != %lld",
to_disk_name(disk),
(rt_uint64_t)rt_le64_to_cpu((*gpt)->signature),
(rt_uint64_t)GPT_HEADER_SIGNATURE);
goto _fail;
}
/* Check the GUID Partition Table header size is too big */
logical_block_size = rt_blk_disk_get_logical_block_size(disk);
if (rt_le32_to_cpu((*gpt)->header_size) > logical_block_size)
{
LOG_D("%s: GUID Partition Table Header size is too large: %u > %u",
to_disk_name(disk),
rt_le32_to_cpu((*gpt)->header_size),
logical_block_size);
goto _fail;
}
/* Check the GUID Partition Table header size is too small */
if (rt_le32_to_cpu((*gpt)->header_size) < sizeof(gpt_header))
{
LOG_D("%s: GUID Partition Table Header size is too small: %u < %u",
to_disk_name(disk),
rt_le32_to_cpu((*gpt)->header_size),
sizeof(gpt_header));
goto _fail;
}
/* Check the GUID Partition Table CRC */
origcrc = rt_le32_to_cpu((*gpt)->header_crc32);
(*gpt)->header_crc32 = 0;
crc = efi_crc32((const rt_uint8_t *)(*gpt), rt_le32_to_cpu((*gpt)->header_size));
if (crc != origcrc)
{
LOG_D("%s: GUID Partition Table Header CRC is wrong: %x != %x",
to_disk_name(disk), crc, origcrc);
goto _fail;
}
(*gpt)->header_crc32 = rt_cpu_to_le32(origcrc);
/*
* Check that the start_lba entry points to the LBA that contains
* the GUID Partition Table
*/
if (rt_le64_to_cpu((*gpt)->start_lba) != lba)
{
LOG_D("%s: GPT start_lba incorrect: %lld != %lld",
to_disk_name(disk),
(rt_uint64_t)rt_le64_to_cpu((*gpt)->start_lba),
(rt_uint64_t)lba);
goto _fail;
}
/* Check the first_usable_lba and last_usable_lba are within the disk */
lastlba = last_lba(disk);
if (rt_le64_to_cpu((*gpt)->first_usable_lba) > lastlba)
{
LOG_D("%s: GPT: first_usable_lba incorrect: %lld > %lld",
to_disk_name(disk),
(rt_uint64_t)rt_le64_to_cpu((*gpt)->first_usable_lba),
(rt_uint64_t)lastlba);
goto _fail;
}
if (rt_le64_to_cpu((*gpt)->last_usable_lba) > lastlba)
{
LOG_D("%s: GPT: last_usable_lba incorrect: %lld > %lld",
to_disk_name(disk),
(rt_uint64_t)rt_le64_to_cpu((*gpt)->last_usable_lba),
(rt_uint64_t)lastlba);
goto _fail;
}
if (rt_le64_to_cpu((*gpt)->last_usable_lba) < rt_le64_to_cpu((*gpt)->first_usable_lba))
{
LOG_D("%s: GPT: last_usable_lba incorrect: %lld > %lld",
to_disk_name(disk),
(rt_uint64_t)rt_le64_to_cpu((*gpt)->last_usable_lba),
(rt_uint64_t)rt_le64_to_cpu((*gpt)->first_usable_lba));
goto _fail;
}
/* Check that sizeof_partition_entry has the correct value */
if (rt_le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry))
{
LOG_D("%s: GUID Partition Entry Size check failed", to_disk_name(disk));
goto _fail;
}
/* Sanity check partition table size */
pt_size = (rt_uint64_t)rt_le32_to_cpu((*gpt)->num_partition_entries) *
rt_le32_to_cpu((*gpt)->sizeof_partition_entry);
if (!(*ptes = alloc_read_gpt_entries(disk, *gpt)))
{
goto _fail;
}
/* Check the GUID Partition Entry Array CRC */
crc = efi_crc32((const rt_uint8_t *)(*ptes), pt_size);
if (crc != rt_le32_to_cpu((*gpt)->partition_entry_array_crc32))
{
LOG_D("%s: GUID Partition Entry Array CRC check failed", to_disk_name(disk));
goto _fail_ptes;
}
/* We're done, all's well */
return RT_TRUE;
_fail_ptes:
rt_free(*ptes);
*ptes = RT_NULL;
_fail:
rt_free(*gpt);
*gpt = RT_NULL;
return RT_FALSE;
}
/**
* @brief This function tests one PTE for validity.
*
* @param pte the pte to check.
* @param lastlba the last lba of the disk.
* @return valid boolean of pte.
*/
rt_inline rt_bool_t is_pte_valid(const gpt_entry *pte, const rt_size_t lastlba)
{
if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) ||
rt_le64_to_cpu(pte->starting_lba) > lastlba ||
rt_le64_to_cpu(pte->ending_lba) > lastlba)
{
return RT_FALSE;
}
return RT_TRUE;
}
/**
* @brief This function search disk for valid GPT headers and PTEs.
*
* @param disk the blk of disk.
* @param pgpt the primary GPT header.
* @param agpt the alternate GPT header.
* @param lastlba the last LBA number.
*/
static void compare_gpts(struct rt_blk_disk *disk,
gpt_header *pgpt, gpt_header *agpt, rt_uint64_t lastlba)
{
int error_found = 0;
if (!pgpt || !agpt)
{
return;
}
if (rt_le64_to_cpu(pgpt->start_lba) != rt_le64_to_cpu(agpt->alternate_lba))
{
LOG_W("%s: GPT:Primary header LBA(%lld) != Alt(%lld), header alternate_lba",
to_disk_name(disk),
(rt_uint64_t)rt_le64_to_cpu(pgpt->start_lba),
(rt_uint64_t)rt_le64_to_cpu(agpt->alternate_lba));
++error_found;
}
if (rt_le64_to_cpu(pgpt->alternate_lba) != rt_le64_to_cpu(agpt->start_lba))
{
LOG_W("%s: GPT:Primary header alternate_lba(%lld) != Alt(%lld), header start_lba",
to_disk_name(disk),
(rt_uint64_t)rt_le64_to_cpu(pgpt->alternate_lba),
(rt_uint64_t)rt_le64_to_cpu(agpt->start_lba));
++error_found;
}
if (rt_le64_to_cpu(pgpt->first_usable_lba) != rt_le64_to_cpu(agpt->first_usable_lba))
{
LOG_W("%s: GPT:first_usable_lbas don't match %lld != %lld",
to_disk_name(disk),
(rt_uint64_t)rt_le64_to_cpu(pgpt->first_usable_lba),
(rt_uint64_t)rt_le64_to_cpu(agpt->first_usable_lba));
++error_found;
}
if (rt_le64_to_cpu(pgpt->last_usable_lba) != rt_le64_to_cpu(agpt->last_usable_lba))
{
LOG_W("%s: GPT:last_usable_lbas don't match %lld != %lld",
to_disk_name(disk),
(rt_uint64_t)rt_le64_to_cpu(pgpt->last_usable_lba),
(rt_uint64_t)rt_le64_to_cpu(agpt->last_usable_lba));
++error_found;
}
if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid))
{
LOG_W("%s: GPT:disk_guids don't match", to_disk_name(disk));
++error_found;
}
if (rt_le32_to_cpu(pgpt->num_partition_entries) !=
rt_le32_to_cpu(agpt->num_partition_entries))
{
LOG_W("%s: GPT:num_partition_entries don't match: 0x%x != 0x%x",
to_disk_name(disk),
rt_le32_to_cpu(pgpt->num_partition_entries),
rt_le32_to_cpu(agpt->num_partition_entries));
++error_found;
}
if (rt_le32_to_cpu(pgpt->sizeof_partition_entry) !=
rt_le32_to_cpu(agpt->sizeof_partition_entry))
{
LOG_W("%s: GPT:sizeof_partition_entry values don't match: 0x%x != 0x%x",
to_disk_name(disk),
rt_le32_to_cpu(pgpt->sizeof_partition_entry),
rt_le32_to_cpu(agpt->sizeof_partition_entry));
++error_found;
}
if (rt_le32_to_cpu(pgpt->partition_entry_array_crc32) !=
rt_le32_to_cpu(agpt->partition_entry_array_crc32))
{
LOG_W("%s: GPT:partition_entry_array_crc32 values don't match: 0x%x != 0x%x",
to_disk_name(disk),
rt_le32_to_cpu(pgpt->partition_entry_array_crc32),
rt_le32_to_cpu(agpt->partition_entry_array_crc32));
++error_found;
}
if (rt_le64_to_cpu(pgpt->alternate_lba) != lastlba)
{
LOG_W("%s: GPT:Primary header thinks Alt. header is not at the end of the disk: %lld != %lld",
to_disk_name(disk),
(rt_uint64_t)rt_le64_to_cpu(pgpt->alternate_lba),
(rt_uint64_t)lastlba);
++error_found;
}
if (rt_le64_to_cpu(agpt->start_lba) != lastlba)
{
LOG_W("%s: GPT:Alternate GPT header not at the end of the disk: %lld != %lld",
to_disk_name(disk),
(rt_uint64_t)rt_le64_to_cpu(agpt->start_lba),
(rt_uint64_t)lastlba);
++error_found;
}
if (error_found)
{
LOG_W("GPT: Use GNU Parted to correct GPT errors");
}
}
/**
* @brief This function search disk for valid GPT headers and PTEs.
*
* @param disk the disk parsed partitions.
* @param gpt the GPT header ptr, filled on return.
* @param ptes the PTEs ptr, filled on return.
* @return 1 if valid, 0 on error.
* If valid, returns pointers to newly allocated GPT header and PTEs.
* Validity depends on PMBR being valid (or being overridden by the
* 'gpt' kernel command line option) and finding either the Primary
* GPT header and PTEs valid, or the Alternate GPT header and PTEs
* valid. If the Primary GPT header is not valid, the Alternate GPT header
* is not checked unless the 'gpt' kernel command line option is passed.
* This protects against devices which misreport their size, and forces
* the user to decide to use the Alternate GPT.
*/
static rt_bool_t find_valid_gpt(struct rt_blk_disk *disk,
gpt_header **gpt, gpt_entry **ptes)
{
int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
gpt_header *pgpt = RT_NULL, *agpt = RT_NULL;
gpt_entry *pptes = RT_NULL, *aptes = RT_NULL;
legacy_mbr *legacymbr;
rt_size_t total_sectors = rt_blk_disk_get_capacity(disk);
rt_size_t lastlba;
if (!ptes)
{
return RT_FALSE;
}
lastlba = last_lba(disk);
if (!force_gpt)
{
/* This will be added to the EFI Spec. per Intel after v1.02. */
legacymbr = rt_malloc(sizeof(*legacymbr));
if (!legacymbr)
{
return RT_FALSE;
}
read_lba(disk, 0, (rt_uint8_t *)legacymbr, sizeof(*legacymbr));
good_pmbr = is_pmbr_valid(legacymbr, total_sectors);
rt_free(legacymbr);
if (!good_pmbr)
{
return RT_FALSE;
}
LOG_D("%s: Device has a %s MBR", to_disk_name(disk),
good_pmbr == GPT_MBR_PROTECTIVE ? "protective" : "hybrid");
}
good_pgpt = is_gpt_valid(disk, GPT_PRIMARY_PARTITION_TABLE_LBA, &pgpt, &pptes);
if (good_pgpt)
{
good_agpt = is_gpt_valid(disk, rt_le64_to_cpu(pgpt->alternate_lba), &agpt, &aptes);
}
if (!good_agpt && force_gpt)
{
good_agpt = is_gpt_valid(disk, lastlba, &agpt, &aptes);
}
/* The obviously unsuccessful case */
if (!good_pgpt && !good_agpt)
{
goto _fail;
}
compare_gpts(disk, pgpt, agpt, lastlba);
/* The good cases */
if (good_pgpt)
{
*gpt = pgpt;
*ptes = pptes;
rt_free(agpt);
rt_free(aptes);
if (!good_agpt)
{
LOG_D("%s: Alternate GPT is invalid, using primary GPT", to_disk_name(disk));
}
return RT_TRUE;
}
else if (good_agpt)
{
*gpt = agpt;
*ptes = aptes;
rt_free(pgpt);
rt_free(pptes);
LOG_D("%s: Primary GPT is invalid, using alternate GPT", to_disk_name(disk));
return RT_TRUE;
}
_fail:
rt_free(pgpt);
rt_free(agpt);
rt_free(pptes);
rt_free(aptes);
*gpt = RT_NULL;
*ptes = RT_NULL;
return RT_FALSE;
}
rt_err_t efi_partition(struct rt_blk_disk *disk)
{
rt_uint32_t entries_nr;
gpt_header *gpt = RT_NULL;
gpt_entry *ptes = RT_NULL;
if (!find_valid_gpt(disk, &gpt, &ptes) || !gpt || !ptes)
{
rt_free(gpt);
rt_free(ptes);
return -RT_EINVAL;
}
entries_nr = rt_le32_to_cpu(gpt->num_partition_entries);
for (int i = 0; i < entries_nr && i < disk->max_partitions; ++i)
{
rt_uint64_t start = rt_le64_to_cpu(ptes[i].starting_lba);
rt_uint64_t size = rt_le64_to_cpu(ptes[i].ending_lba) -
rt_le64_to_cpu(ptes[i].starting_lba) + 1ULL;
if (!is_pte_valid(&ptes[i], last_lba(disk)))
{
continue;
}
if (blk_put_partition(disk, "gpt", start, size, i) == -RT_ENOMEM)
{
break;
}
}
rt_free(gpt);
rt_free(ptes);
return RT_EOK;
}

View File

@ -0,0 +1,141 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-05-05 linzhenxing first version
* 2023-02-25 GuEe-GUI make blk interface
*/
#ifndef __PARTITIONS_EFI_H__
#define __PARTITIONS_EFI_H__
#include "../blk_partition.h"
#include <drivers/misc.h>
#include <drivers/byteorder.h>
#define MSDOS_MBR_SIGNATURE 0xaa55
#define EFI_PMBR_OSTYPE_EFI 0xef
#define EFI_PMBR_OSTYPE_EFI_GPT 0xee
#define GPT_MBR_PROTECTIVE 1
#define GPT_MBR_HYBRID 2
#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
#define GPT_HEADER_REVISION_V1 0x00010000
#define GPT_PRIMARY_PARTITION_TABLE_LBA 1
#ifndef __UUID_H__
#define UUID_SIZE 16
typedef struct
{
rt_uint8_t b[UUID_SIZE];
} guid_t;
#endif /* __UUID_H__ */
#ifndef __EFI_H__
typedef guid_t efi_guid_t rt_align(4);
#define EFI_GUID(a, b, c, d...) (efi_guid_t) \
{{ \
(a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
(b) & 0xff, ((b) >> 8) & 0xff, \
(c) & 0xff, ((c) >> 8) & 0xff, \
d \
}}
#define NULL_GUID \
EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
rt_inline int efi_guidcmp(efi_guid_t left, efi_guid_t right)
{
return rt_memcmp(&left, &right, sizeof (efi_guid_t));
}
#endif /* __EFI_H__ */
#define PARTITION_SYSTEM_GUID \
EFI_GUID(0xc12a7328, 0xf81f, 0x11d2, 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b)
#define LEGACY_MBR_PARTITION_GUID \
EFI_GUID(0x024dee41, 0x33e7, 0x11d3, 0x9d, 0x69, 0x00, 0x08, 0xc7, 0x81, 0xf3, 0x9f)
#define PARTITION_MSFT_RESERVED_GUID \
EFI_GUID(0xe3c9e316, 0x0b5c, 0x4db8, 0x81, 0x7d, 0xf9, 0x2d, 0xf0, 0x02, 0x15, 0xae)
#define PARTITION_BASIC_DATA_GUID \
EFI_GUID(0xebd0a0a2, 0xb9e5, 0x4433, 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7)
rt_packed(struct _gpt_header
{
rt_le64_t signature;
rt_le32_t revision;
rt_le32_t header_size;
rt_le32_t header_crc32;
rt_le32_t reserved1;
rt_le64_t start_lba;
rt_le64_t alternate_lba;
rt_le64_t first_usable_lba;
rt_le64_t last_usable_lba;
efi_guid_t disk_guid;
rt_le64_t partition_entry_lba;
rt_le32_t num_partition_entries;
rt_le32_t sizeof_partition_entry;
rt_le32_t partition_entry_array_crc32;
/*
* The rest of the logical block is reserved by UEFI and must be zero.
* EFI standard handles this by:
*
* uint8_t reserved2[BlockSize - 92];
*/
});
typedef struct _gpt_header gpt_header;
rt_packed(struct _gpt_entry_attributes
{
rt_uint64_t required_to_function:1;
rt_uint64_t reserved:47;
rt_uint64_t type_guid_specific:16;
});
typedef struct _gpt_entry_attributes gpt_entry_attributes;
rt_packed(struct _gpt_entry
{
efi_guid_t partition_type_guid;
efi_guid_t unique_partition_guid;
rt_le64_t starting_lba;
rt_le64_t ending_lba;
gpt_entry_attributes attributes;
rt_le16_t partition_name[72/sizeof(rt_le16_t)];
});
typedef struct _gpt_entry gpt_entry;
rt_packed(struct _gpt_mbr_record
{
rt_uint8_t boot_indicator; /* unused by EFI, set to 0x80 for bootable */
rt_uint8_t start_head; /* unused by EFI, pt start in CHS */
rt_uint8_t start_sector; /* unused by EFI, pt start in CHS */
rt_uint8_t start_track;
rt_uint8_t os_type; /* EFI and legacy non-EFI OS types */
rt_uint8_t end_head; /* unused by EFI, pt end in CHS */
rt_uint8_t end_sector; /* unused by EFI, pt end in CHS */
rt_uint8_t end_track; /* unused by EFI, pt end in CHS */
rt_le32_t starting_lba; /* used by EFI - start addr of the on disk pt */
rt_le32_t size_in_lba; /* used by EFI - size of pt in LBA */
});
typedef struct _gpt_mbr_record gpt_mbr_record;
rt_packed(struct _legacy_mbr
{
rt_uint8_t boot_code[440];
rt_le32_t unique_mbr_signature;
rt_le16_t unknown;
gpt_mbr_record partition_record[4];
rt_le16_t signature;
});
typedef struct _legacy_mbr legacy_mbr;
#endif /* __PARTITIONS_EFI_H__ */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -435,7 +435,7 @@ static rt_err_t rt_can_close(struct rt_device *dev)
}
can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_CAN_INT_ERR);
can->ops->control(can, RT_CAN_CMD_START, RT_FALSE);
CAN_UNLOCK(can);
return RT_EOK;

View File

@ -3,3 +3,7 @@ menuconfig RT_USING_CLK
depends on RT_USING_DM
select RT_USING_ADT_REF
default y
if RT_USING_CLK
osource "$(SOC_DM_CLK_DIR)/Kconfig"
endif

View File

@ -55,6 +55,10 @@ static struct rt_clk *clk_alloc(struct rt_clk_node *clk_np, const char *dev_id,
clk->fw_node = fw_node;
}
else
{
clk = rt_err_ptr(-RT_ENOMEM);
}
return clk;
}
@ -76,7 +80,7 @@ static struct rt_clk *clk_create(struct rt_clk_node *clk_np, const char *dev_id,
{
struct rt_clk *clk = clk_alloc(clk_np, dev_id, con_id, fw_node);
if (clk)
if (!rt_is_err(clk))
{
clk_get(clk_np);
@ -135,15 +139,6 @@ rt_err_t rt_clk_register(struct rt_clk_node *clk_np, struct rt_clk_node *parent_
struct rt_clk *clk = RT_NULL;
if (clk_np)
{
clk = clk_alloc(clk_np, RT_NULL, RT_NULL, RT_NULL);
}
else
{
err = -RT_EINVAL;
}
if (!err && clk_np)
{
clk_np->clk = clk;
@ -152,6 +147,12 @@ rt_err_t rt_clk_register(struct rt_clk_node *clk_np, struct rt_clk_node *parent_
clk_np->ops = &unused_clk_ops;
}
#if RT_NAME_MAX > 0
rt_strncpy(clk_np->rt_parent.name, RT_CLK_NODE_OBJ_NAME, RT_NAME_MAX);
#else
clk_np->rt_parent.name = RT_CLK_NODE_OBJ_NAME;
#endif
rt_ref_init(&clk_np->ref);
rt_list_init(&clk_np->list);
rt_list_init(&clk_np->children_nodes);
@ -159,7 +160,16 @@ rt_err_t rt_clk_register(struct rt_clk_node *clk_np, struct rt_clk_node *parent_
if (parent_np)
{
clk_set_parent(clk_np, parent_np);
clk_np->clk = clk_alloc(clk_np, RT_NULL, RT_NULL, RT_NULL);
if (clk_np->clk)
{
clk_set_parent(clk_np, parent_np);
}
else
{
err = -RT_ENOMEM;
}
}
else
{
@ -265,11 +275,16 @@ static rt_err_t clk_prepare(struct rt_clk *clk, struct rt_clk_node *clk_np)
clk_prepare(clk_np->clk, clk_np->parent);
}
if (clk_np->ops->prepare)
if (clk->prepare_count == 0 && clk_np->ops->prepare)
{
err = clk_np->ops->prepare(clk);
}
if (!err)
{
++clk->prepare_count;
}
return err;
}
@ -287,10 +302,6 @@ rt_err_t rt_clk_prepare(struct rt_clk *clk)
rt_hw_spin_unlock(&_clk_lock.lock);
}
else
{
err = -RT_EINVAL;
}
return err;
}
@ -302,10 +313,14 @@ static void clk_unprepare(struct rt_clk *clk, struct rt_clk_node *clk_np)
clk_unprepare(clk_np->clk, clk_np->parent);
}
if (clk_np->ops->unprepare)
if (clk->prepare_count == 1 && clk_np->ops->unprepare)
{
clk_np->ops->unprepare(clk);
}
if (clk->prepare_count)
{
--clk->prepare_count;
}
}
rt_err_t rt_clk_unprepare(struct rt_clk *clk)
@ -322,10 +337,6 @@ rt_err_t rt_clk_unprepare(struct rt_clk *clk)
rt_hw_spin_unlock(&_clk_lock.lock);
}
else
{
err = -RT_EINVAL;
}
return err;
}
@ -339,11 +350,16 @@ static rt_err_t clk_enable(struct rt_clk *clk, struct rt_clk_node *clk_np)
clk_enable(clk_np->clk, clk_np->parent);
}
if (clk_np->ops->enable)
if (clk->enable_count == 0 && clk_np->ops->enable)
{
err = clk_np->ops->enable(clk);
}
if (!err)
{
++clk->enable_count;
}
return err;
}
@ -359,10 +375,6 @@ rt_err_t rt_clk_enable(struct rt_clk *clk)
rt_hw_spin_unlock(&_clk_lock.lock);
}
else
{
err = -RT_EINVAL;
}
return err;
}
@ -374,10 +386,14 @@ static void clk_disable(struct rt_clk *clk, struct rt_clk_node *clk_np)
clk_disable(clk_np->clk, clk_np->parent);
}
if (clk_np->ops->disable)
if (clk->enable_count == 1 && clk_np->ops->disable)
{
clk_np->ops->disable(clk);
}
if (clk->enable_count)
{
--clk->enable_count;
}
}
void rt_clk_disable(struct rt_clk *clk)
@ -394,7 +410,7 @@ void rt_clk_disable(struct rt_clk *clk)
rt_err_t rt_clk_prepare_enable(struct rt_clk *clk)
{
rt_err_t err;
rt_err_t err = RT_EOK;
RT_DEBUG_NOT_IN_INTERRUPT;
@ -412,10 +428,6 @@ rt_err_t rt_clk_prepare_enable(struct rt_clk *clk)
}
}
}
else
{
err = -RT_EINVAL;
}
return err;
}
@ -453,10 +465,6 @@ rt_err_t rt_clk_array_prepare(struct rt_clk_array *clk_arr)
}
}
}
else
{
err = -RT_EINVAL;
}
return err;
}
@ -478,10 +486,6 @@ rt_err_t rt_clk_array_unprepare(struct rt_clk_array *clk_arr)
}
}
}
else
{
err = -RT_EINVAL;
}
return err;
}
@ -508,10 +512,6 @@ rt_err_t rt_clk_array_enable(struct rt_clk_array *clk_arr)
}
}
}
else
{
err = -RT_EINVAL;
}
return err;
}
@ -529,29 +529,16 @@ void rt_clk_array_disable(struct rt_clk_array *clk_arr)
rt_err_t rt_clk_array_prepare_enable(struct rt_clk_array *clk_arr)
{
rt_err_t err = RT_EOK;
rt_err_t err;
if (clk_arr)
if ((err = rt_clk_array_prepare(clk_arr)))
{
for (int i = 0; i < clk_arr->count; ++i)
{
if ((err = rt_clk_prepare_enable(clk_arr->clks[i])))
{
LOG_E("CLK Array[%d] %s failed error = %s", i,
"prepare_enable", rt_strerror(err));
while (i --> 0)
{
rt_clk_disable_unprepare(clk_arr->clks[i]);
}
break;
}
}
return err;
}
else
if ((err = rt_clk_array_enable(clk_arr)))
{
err = -RT_EINVAL;
rt_clk_array_unprepare(clk_arr);
}
return err;
@ -559,13 +546,8 @@ rt_err_t rt_clk_array_prepare_enable(struct rt_clk_array *clk_arr)
void rt_clk_array_disable_unprepare(struct rt_clk_array *clk_arr)
{
if (clk_arr)
{
for (int i = 0; i < clk_arr->count; ++i)
{
rt_clk_disable_unprepare(clk_arr->clks[i]);
}
}
rt_clk_array_disable(clk_arr);
rt_clk_array_unprepare(clk_arr);
}
rt_err_t rt_clk_set_rate_range(struct rt_clk *clk, rt_ubase_t min, rt_ubase_t max)
@ -604,10 +586,6 @@ rt_err_t rt_clk_set_rate_range(struct rt_clk *clk, rt_ubase_t min, rt_ubase_t ma
rt_hw_spin_unlock(&_clk_lock.lock);
}
else
{
err = -RT_EINVAL;
}
return err;
}
@ -622,10 +600,6 @@ rt_err_t rt_clk_set_min_rate(struct rt_clk *clk, rt_ubase_t rate)
err = rt_clk_set_rate_range(clk, rate, clk_np->max_rate);
}
else
{
err = -RT_EINVAL;
}
return err;
}
@ -640,10 +614,6 @@ rt_err_t rt_clk_set_max_rate(struct rt_clk *clk, rt_ubase_t rate)
err = rt_clk_set_rate_range(clk, clk_np->min_rate, rate);
}
else
{
err = -RT_EINVAL;
}
return err;
}
@ -652,7 +622,9 @@ rt_err_t rt_clk_set_rate(struct rt_clk *clk, rt_ubase_t rate)
{
rt_err_t err = RT_EOK;
if (clk && clk->clk_np)
rate = rt_clk_round_rate(clk, rate);
if (clk && clk->clk_np && rate > 0)
{
struct rt_clk_node *clk_np = clk->clk_np;
@ -690,17 +662,13 @@ rt_err_t rt_clk_set_rate(struct rt_clk *clk, rt_ubase_t rate)
rt_hw_spin_unlock(&_clk_lock.lock);
}
else
{
err = -RT_EINVAL;
}
return err;
}
rt_ubase_t rt_clk_get_rate(struct rt_clk *clk)
{
rt_ubase_t rate = -1UL;
rt_ubase_t rate = 0;
if (clk)
{
@ -729,10 +697,6 @@ rt_err_t rt_clk_set_phase(struct rt_clk *clk, int degrees)
rt_hw_spin_unlock(&_clk_lock.lock);
}
else
{
err = -RT_EINVAL;
}
return err;
}
@ -749,38 +713,49 @@ rt_base_t rt_clk_get_phase(struct rt_clk *clk)
rt_hw_spin_unlock(&_clk_lock.lock);
}
else
{
res = -RT_EINVAL;
}
return res;
}
rt_base_t rt_clk_round_rate(struct rt_clk *clk, rt_ubase_t rate)
{
rt_base_t res = RT_EOK;
rt_base_t res = -RT_EINVAL;
if (clk && clk->clk_np && clk->clk_np->ops->round_rate)
if (clk && clk->clk_np)
{
rt_ubase_t best_parent_rate;
struct rt_clk_node *clk_np = clk->clk_np;
rt_hw_spin_lock(&_clk_lock.lock);
if (clk_np->min_rate && clk_np->max_rate)
if (clk_np->ops->round_rate)
{
rate = rt_clamp(rate, clk_np->min_rate, clk_np->max_rate);
rt_ubase_t best_parent_rate;
rt_hw_spin_lock(&_clk_lock.lock);
if (clk_np->min_rate && clk_np->max_rate)
{
rate = rt_clamp(rate, clk_np->min_rate, clk_np->max_rate);
}
res = clk_np->ops->round_rate(clk, rate, &best_parent_rate);
(void)best_parent_rate;
rt_hw_spin_unlock(&_clk_lock.lock);
}
else
{
if (rate < clk_np->min_rate)
{
res = clk_np->min_rate;
}
else if (rate > clk_np->max_rate)
{
res = clk_np->max_rate;
}
else
{
res = rate;
}
}
res = clk->clk_np->ops->round_rate(clk, rate, &best_parent_rate);
(void)best_parent_rate;
rt_hw_spin_unlock(&_clk_lock.lock);
}
else
{
res = -RT_EINVAL;
}
return res;
@ -798,10 +773,6 @@ rt_err_t rt_clk_set_parent(struct rt_clk *clk, struct rt_clk *clk_parent)
rt_hw_spin_unlock(&_clk_lock.lock);
}
else
{
err = -RT_EINVAL;
}
return err;
}
@ -887,7 +858,7 @@ void rt_clk_put(struct rt_clk *clk)
}
#ifdef RT_USING_OFW
static struct rt_clk *ofw_get_clk_no_lock(struct rt_ofw_node *np, int index, const char *name)
static struct rt_clk *ofw_get_clk_no_lock(struct rt_ofw_node *np, int index, const char *name, rt_bool_t locked)
{
struct rt_clk *clk = RT_NULL;
struct rt_ofw_cell_args clk_args;
@ -895,10 +866,32 @@ static struct rt_clk *ofw_get_clk_no_lock(struct rt_ofw_node *np, int index, con
if (!rt_ofw_parse_phandle_cells(np, "clocks", "#clock-cells", index, &clk_args))
{
int count;
struct rt_object *obj;
struct rt_clk_node *clk_np = RT_NULL;
struct rt_ofw_node *clk_ofw_np = clk_args.data;
struct rt_clk_node *clk_np = rt_ofw_data(clk_ofw_np);
count = rt_ofw_count_of_clk(clk_ofw_np);
if (!rt_ofw_data(clk_ofw_np))
{
if (locked)
{
rt_hw_spin_unlock(&_clk_lock.lock);
}
rt_platform_ofw_request(clk_ofw_np);
if (locked)
{
rt_hw_spin_lock(&_clk_lock.lock);
}
}
if (rt_ofw_data(clk_ofw_np) && (obj = rt_ofw_parse_object(clk_ofw_np,
RT_CLK_NODE_OBJ_NAME, "#clock-cells")))
{
clk_np = rt_container_of(obj, struct rt_clk_node, rt_parent);
count = rt_ofw_count_of_clk(clk_ofw_np);
}
rt_ofw_node_put(clk_ofw_np);
@ -912,6 +905,10 @@ static struct rt_clk *ofw_get_clk_no_lock(struct rt_ofw_node *np, int index, con
clk = clk_create(clk_np, np->full_name, name, &clk_args, np);
}
else
{
clk = rt_err_ptr(-RT_ERROR);
}
}
return clk;
@ -923,7 +920,7 @@ static struct rt_clk *ofw_get_clk(struct rt_ofw_node *np, int index, const char
rt_hw_spin_lock(&_clk_lock.lock);
clk = ofw_get_clk_no_lock(np, index, name);
clk = ofw_get_clk_no_lock(np, index, name, RT_TRUE);
rt_hw_spin_unlock(&_clk_lock.lock);
@ -935,6 +932,11 @@ struct rt_clk_array *rt_ofw_get_clk_array(struct rt_ofw_node *np)
int count;
struct rt_clk_array *clk_arr = RT_NULL;
if (!np)
{
return rt_err_ptr(-RT_EINVAL);
}
if ((count = rt_ofw_count_phandle_cells(np, "clocks", "#clock-cells")) > 0)
{
clk_arr = rt_calloc(1, sizeof(*clk_arr) + sizeof(clk_arr->clks[0]) * count);
@ -942,6 +944,7 @@ struct rt_clk_array *rt_ofw_get_clk_array(struct rt_ofw_node *np)
if (clk_arr)
{
int i;
rt_err_t err = RT_EOK;
rt_bool_t has_name = rt_ofw_prop_read_bool(np, "clock-names");
clk_arr->count = count;
@ -957,10 +960,12 @@ struct rt_clk_array *rt_ofw_get_clk_array(struct rt_ofw_node *np)
rt_ofw_prop_read_string_index(np, "clock-names", i, &name);
}
clk_arr->clks[i] = ofw_get_clk_no_lock(np, i, name);
clk_arr->clks[i] = ofw_get_clk_no_lock(np, i, name, RT_FALSE);
if (!clk_arr->clks[i])
if (rt_is_err(clk_arr->clks[i]))
{
err = rt_ptr_err(clk_arr->clks[i]);
--i;
break;
}
@ -971,7 +976,7 @@ struct rt_clk_array *rt_ofw_get_clk_array(struct rt_ofw_node *np)
if (i > 0 && i < count)
{
rt_clk_array_put(clk_arr);
clk_arr = RT_NULL;
clk_arr = rt_err_ptr(err);
}
}
}

View File

@ -360,9 +360,9 @@ rt_err_t rt_bus_remove_device(rt_device_t dev)
}
else if (drv)
{
if (drv->shutdown)
if (drv->remove)
{
err = drv->shutdown(dev);
err = drv->remove(dev);
}
/* device and driver are in the same bus */

View File

@ -13,6 +13,8 @@
* 2013-07-09 Grissiom add ref_count support
* 2016-04-02 Bernard fix the open_flag initialization issue.
* 2021-03-19 Meco Man remove rt_device_init_all()
* 2024-09-15 milo fix log format issue
* fix reopen with a different oflag issue
*/
#include <rtthread.h>
@ -29,9 +31,9 @@
#include <rtdevice.h> /* for wqueue_init */
#endif /* RT_USING_POSIX_DEVIO */
#ifdef RT_USING_DFS_V2
#if defined (RT_USING_DFS_V2) && defined (RT_USING_DFS_DEVFS)
#include <devfs.h>
#endif /* RT_USING_DFS_V2 */
#endif /* RT_USING_DFS_V2 RT_USING_DFS_DEVFS */
#ifdef RT_USING_DEVICE
@ -82,7 +84,7 @@ rt_err_t rt_device_register(rt_device_t dev,
rt_wqueue_init(&(dev->wait_queue));
#endif /* RT_USING_POSIX_DEVIO */
#ifdef RT_USING_DFS_V2
#if defined (RT_USING_DFS_V2) && defined (RT_USING_DFS_DEVFS)
dfs_devfs_device_add(dev);
#endif /* RT_USING_DFS_V2 */
@ -163,7 +165,7 @@ void rt_device_destroy(rt_device_t dev)
{
/* parameter check */
RT_ASSERT(dev != RT_NULL);
RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Null);
RT_ASSERT(rt_object_is_systemobject(&dev->parent) == RT_FALSE);
rt_object_detach(&(dev->parent));
@ -195,8 +197,8 @@ rt_err_t rt_device_init(rt_device_t dev)
result = device_init(dev);
if (result != RT_EOK)
{
LOG_E("To initialize device:%s failed. The error code is %d",
dev->parent.name, result);
LOG_E("To initialize device:%.*s failed. The error code is %d",
RT_NAME_MAX, dev->parent.name, result);
}
else
{
@ -233,8 +235,8 @@ rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag)
result = device_init(dev);
if (result != RT_EOK)
{
LOG_E("To initialize device:%s failed. The error code is %d",
dev->parent.name, result);
LOG_E("To initialize device:%.*s failed. The error code is %d",
RT_NAME_MAX, dev->parent.name, result);
return result;
}
@ -252,7 +254,7 @@ rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag)
/* device is not opened or opened by other oflag, call device_open interface */
if (!(dev->open_flag & RT_DEVICE_OFLAG_OPEN) ||
((dev->open_flag & RT_DEVICE_OFLAG_MASK) != (oflag & RT_DEVICE_OFLAG_MASK)))
((dev->open_flag & RT_DEVICE_OFLAG_MASK) != ((oflag & RT_DEVICE_OFLAG_MASK) | RT_DEVICE_OFLAG_OPEN)))
{
if (device_open != RT_NULL)
{

View File

@ -53,6 +53,137 @@ void rt_dm_secondary_cpu_init(void)
}
#endif /* RT_USING_SMP */
/**
* @brief This function will alloc an id in an IDA object
*
* @param ida is the IDA object
*
* @return the id or -RT_EEMPTY
*/
int rt_dm_ida_alloc(struct rt_dm_ida *ida)
{
int id;
RT_ASSERT(ida != RT_NULL);
rt_spin_lock(&ida->lock);
id = rt_bitmap_next_clear_bit(ida->map, 0, RT_DM_IDA_NUM);
if (id != RT_DM_IDA_NUM)
{
rt_bitmap_set_bit(ida->map, id);
}
rt_spin_unlock(&ida->lock);
if (id != RT_DM_IDA_NUM)
{
return id;
}
return -RT_EEMPTY;
}
/**
* @brief This function will take (force) an id in an IDA object
*
* @param ida is the IDA object
*
* @param id is the id that want to take
*
* @return the result of taking
*/
rt_bool_t rt_dm_ida_take(struct rt_dm_ida *ida, int id)
{
RT_ASSERT(ida != RT_NULL);
RT_ASSERT(id >= 0);
rt_spin_lock(&ida->lock);
if (!rt_bitmap_test_bit(ida->map, id))
{
rt_bitmap_set_bit(ida->map, id);
}
else
{
id = RT_DM_IDA_NUM;
}
rt_spin_unlock(&ida->lock);
return id != RT_DM_IDA_NUM;
}
/**
* @brief This function will release an id in an IDA object
*
* @param ida is the IDA object
*
* @param id is the id of IDA object
*/
void rt_dm_ida_free(struct rt_dm_ida *ida, int id)
{
RT_ASSERT(ida != RT_NULL);
RT_ASSERT(id >= 0);
rt_spin_lock(&ida->lock);
rt_bitmap_clear_bit(ida->map, id);
rt_spin_unlock(&ida->lock);
}
/**
* @brief This function will return the specified master id and device id of device.
*
* @param master_id is the master id (0, 255] of device
*
* @param device_id is the device id [-1, 255] of device, when device_id is -1,
* the function will end when find the first device.
*
* @return the device object or RT_NULL
*/
rt_device_t rt_dm_device_find(int master_id, int device_id)
{
struct rt_device *dev, *ret_dev = RT_NULL;
struct rt_object_information *information = RT_NULL;
if (master_id <= 0 || device_id > 255)
{
return RT_NULL;
}
information = rt_object_get_information(RT_Object_Class_Device);
/* parameter check */
if (!information)
{
return RT_NULL;
}
/* which is invoke in interrupt status */
RT_DEBUG_NOT_IN_INTERRUPT;
/* enter critical */
rt_enter_critical();
/* try to find object */
rt_list_for_each_entry(dev, &information->object_list, parent.list)
{
if (master_id == dev->master_id &&
(device_id == -1 || device_id == dev->device_id))
{
ret_dev = dev;
break;
}
}
/* leave critical */
rt_exit_critical();
return ret_dev;
}
struct prefix_track
{
rt_list_t list;

View File

@ -78,21 +78,21 @@ static rt_bool_t platform_match(rt_driver_t drv, rt_device_t dev)
{
struct rt_platform_driver *pdrv = rt_container_of(drv, struct rt_platform_driver, parent);
struct rt_platform_device *pdev = rt_container_of(dev, struct rt_platform_device, parent);
#ifdef RT_USING_OFW
struct rt_ofw_node *np = dev->ofw_node;
/* 1、match with ofw node */
if (np)
{
#ifdef RT_USING_OFW
pdev->id = rt_ofw_node_match(np, pdrv->ids);
#else
pdev->id = RT_NULL;
#endif
if (pdev->id)
{
return RT_TRUE;
}
}
#endif
/* 2、match with name */
if (pdev->name && pdrv->name)
@ -123,7 +123,13 @@ static rt_err_t platform_probe(rt_device_t dev)
if (err && err != -RT_EEMPTY)
{
LOG_E("Attach power domain error = %s in device %s", pdev->name, rt_strerror(err));
LOG_E("Attach power domain error = %s in device %s", rt_strerror(err),
#ifdef RT_USING_OFW
(pdev->name && pdev->name[0]) ? pdev->name : rt_ofw_node_full_name(np)
#else
pdev->name
#endif
);
return err;
}

View File

@ -17,6 +17,7 @@
#include <drivers/ofw_io.h>
#include <drivers/ofw_fdt.h>
#include <drivers/platform.h>
#include <drivers/core/bus.h>
#include <drivers/core/dm.h>
#include "../ofw/ofw_internal.h"
@ -161,6 +162,7 @@ static rt_err_t platform_ofw_device_probe_once(struct rt_ofw_node *parent_np)
}
pdev->dev_id = ofw_alias_node_id(np);
np->dev = &pdev->parent;
LOG_D("%s register to bus", np->full_name);
rt_platform_device_register(pdev);
@ -199,6 +201,53 @@ rt_err_t rt_platform_ofw_device_probe_child(struct rt_ofw_node *np)
return err;
}
rt_err_t rt_platform_ofw_request(struct rt_ofw_node *np)
{
rt_err_t err;
if (np)
{
struct rt_device *dev = np->dev;
if (dev)
{
/* Was create */
if (dev->drv)
{
/* Was probe OK */
err = RT_EOK;
}
else
{
err = rt_bus_reload_driver_device(dev->bus, dev);
}
}
else
{
struct rt_platform_device *pdev = alloc_ofw_platform_device(np);
if (pdev)
{
pdev->dev_id = ofw_alias_node_id(np);
np->dev = &pdev->parent;
LOG_D("%s register to bus", np->full_name);
err = rt_platform_device_register(pdev);
}
else
{
err = -RT_ENOMEM;
}
}
}
else
{
err = -RT_EINVAL;
}
return err;
}
static int platform_ofw_device_probe(void)
{
rt_err_t err = RT_EOK;
@ -206,6 +255,8 @@ static int platform_ofw_device_probe(void)
if (ofw_node_root)
{
rt_ofw_node_get(ofw_node_root);
err = platform_ofw_device_probe_once(ofw_node_root);
rt_ofw_node_put(ofw_node_root);
@ -216,11 +267,19 @@ static int platform_ofw_device_probe(void)
rt_ofw_node_put(node);
}
if ((node = rt_ofw_find_node_by_path("/clocks")))
{
platform_ofw_device_probe_once(node);
rt_ofw_node_put(node);
}
rt_ofw_node_get(ofw_node_chosen);
if ((node = rt_ofw_get_child_by_compatible(ofw_node_chosen, "simple-framebuffer")))
{
platform_ofw_device_probe_once(node);
rt_ofw_node_put(node);
}
rt_ofw_node_get(ofw_node_chosen);
}
else
{
@ -244,7 +303,7 @@ rt_err_t rt_platform_ofw_free(struct rt_platform_device *pdev)
rt_ofw_node_clear_flag(np, RT_OFW_F_PLATFORM);
rt_ofw_node_put(np);
pdev->parent.ofw_node = RT_NULL;
rt_free(pdev);
}
}
else

View File

@ -0,0 +1,10 @@
menuconfig RT_USING_DMA
bool "Using Direct Memory Access (DMA)"
depends on RT_USING_DM
select RT_USING_ADT
select RT_USING_ADT_BITMAP
default n
if RT_USING_DMA
osource "$(SOC_DM_DMA_DIR)/Kconfig"
endif

View File

@ -0,0 +1,15 @@
from building import *
group = []
if not GetDepend(['RT_USING_DMA']):
Return('group')
cwd = GetCurrentDir()
CPPPATH = [cwd + '/../include']
src = ['dma.c', 'dma_pool.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,589 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#define DBG_TAG "rtdm.dma"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
static rt_list_t dmac_nodes = RT_LIST_OBJECT_INIT(dmac_nodes);
static struct rt_spinlock dmac_nodes_lock = {};
rt_err_t rt_dma_controller_register(struct rt_dma_controller *ctrl)
{
const char *dev_name;
char dma_name[RT_NAME_MAX];
if (!ctrl || !ctrl->dev || !ctrl->ops)
{
return -RT_EINVAL;
}
dev_name = rt_dm_dev_get_name(ctrl->dev);
if (rt_bitmap_next_set_bit(ctrl->dir_cap, 0, RT_DMA_DIR_MAX) == RT_DMA_DIR_MAX)
{
LOG_E("%s: Not direction capability", dev_name);
return -RT_EINVAL;
}
rt_snprintf(dma_name, sizeof(dma_name), "%s-dmac", dev_name);
rt_list_init(&ctrl->list);
rt_spin_lock(&dmac_nodes_lock);
rt_list_insert_before(&dmac_nodes, &ctrl->list);
rt_spin_unlock(&dmac_nodes_lock);
rt_list_init(&ctrl->channels_nodes);
rt_mutex_init(&ctrl->mutex, dma_name, RT_IPC_FLAG_PRIO);
if (ctrl->dev->ofw_node)
{
rt_dm_dev_bind_fwdata(ctrl->dev, RT_NULL, ctrl);
}
return RT_EOK;
}
rt_err_t rt_dma_controller_unregister(struct rt_dma_controller *ctrl)
{
if (!ctrl)
{
return -RT_EINVAL;
}
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
if (!rt_list_isempty(&ctrl->channels_nodes))
{
rt_mutex_release(&ctrl->mutex);
return -RT_EBUSY;
}
if (ctrl->dev->ofw_node)
{
rt_dm_dev_unbind_fwdata(ctrl->dev, RT_NULL);
}
rt_mutex_release(&ctrl->mutex);
rt_mutex_detach(&ctrl->mutex);
rt_spin_lock(&dmac_nodes_lock);
rt_list_remove(&ctrl->list);
rt_spin_unlock(&dmac_nodes_lock);
return RT_EOK;
}
rt_err_t rt_dma_chan_start(struct rt_dma_chan *chan)
{
rt_err_t err;
struct rt_dma_controller *ctrl;
if (!chan)
{
return -RT_EINVAL;
}
if (chan->prep_err)
{
LOG_D("%s: Not config done", rt_dm_dev_get_name(chan->slave));
return chan->prep_err;
}
ctrl = chan->ctrl;
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
err = ctrl->ops->start(chan);
rt_mutex_release(&ctrl->mutex);
return err;
}
rt_err_t rt_dma_chan_stop(struct rt_dma_chan *chan)
{
rt_err_t err;
struct rt_dma_controller *ctrl;
if (!chan)
{
return -RT_EINVAL;
}
if (chan->prep_err)
{
LOG_D("%s: Not prepare done", rt_dm_dev_get_name(chan->slave));
return chan->prep_err;
}
ctrl = chan->ctrl;
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
err = ctrl->ops->stop(chan);
rt_mutex_release(&ctrl->mutex);
return err;
}
rt_err_t rt_dma_chan_config(struct rt_dma_chan *chan,
struct rt_dma_slave_config *conf)
{
rt_err_t err;
struct rt_dma_controller *ctrl;
enum rt_dma_transfer_direction dir;
if (!chan || !conf)
{
err = -RT_EINVAL;
goto _end;
}
dir = conf->direction;
if (dir >= RT_DMA_DIR_MAX)
{
err = -RT_EINVAL;
goto _end;
}
if (conf->src_addr_width >= RT_DMA_SLAVE_BUSWIDTH_BYTES_MAX ||
conf->dst_addr_width >= RT_DMA_SLAVE_BUSWIDTH_BYTES_MAX)
{
err = -RT_EINVAL;
goto _end;
}
ctrl = chan->ctrl;
if (!rt_bitmap_test_bit(ctrl->dir_cap, dir))
{
err = -RT_ENOSYS;
goto _end;
}
if (!chan->name && dir != RT_DMA_MEM_TO_MEM)
{
LOG_E("%s: illegal config for uname channels",
rt_dm_dev_get_name(ctrl->dev));
err = -RT_EINVAL;
goto _end;
}
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
err = ctrl->ops->config(chan, conf);
rt_mutex_release(&ctrl->mutex);
if (!err)
{
rt_memcpy(&chan->conf, conf, sizeof(*conf));
}
_end:
chan->conf_err = err;
return err;
}
rt_err_t rt_dma_chan_done(struct rt_dma_chan *chan, rt_size_t size)
{
if (!chan)
{
return -RT_EINVAL;
}
if (chan->callback)
{
chan->callback(chan, size);
}
return RT_EOK;
}
static rt_bool_t range_is_illegal(const char *name, const char *desc,
rt_ubase_t addr0, rt_ubase_t addr1)
{
rt_bool_t illegal = addr0 < addr1;
if (illegal)
{
LOG_E("%s: %s %p is out of config %p", name, desc, addr0, addr1);
}
return illegal;
}
rt_err_t rt_dma_prep_memcpy(struct rt_dma_chan *chan,
struct rt_dma_slave_transfer *transfer)
{
rt_err_t err;
rt_size_t len;
rt_ubase_t dma_addr_src, dma_addr_dst;
struct rt_dma_controller *ctrl;
struct rt_dma_slave_config *conf;
if (!chan || !transfer)
{
return -RT_EINVAL;
}
ctrl = chan->ctrl;
conf = &chan->conf;
if (chan->conf_err)
{
LOG_D("%s: Not config done", rt_dm_dev_get_name(chan->slave));
return chan->conf_err;
}
RT_ASSERT(chan->conf.direction == RT_DMA_MEM_TO_MEM);
dma_addr_src = transfer->src_addr;
dma_addr_dst = transfer->dst_addr;
len = transfer->buffer_len;
if (range_is_illegal(rt_dm_dev_get_name(ctrl->dev), "source",
dma_addr_src, conf->src_addr))
{
return -RT_EINVAL;
}
if (range_is_illegal(rt_dm_dev_get_name(ctrl->dev), "dest",
dma_addr_dst, conf->dst_addr))
{
return -RT_EINVAL;
}
if (ctrl->ops->prep_memcpy)
{
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
err = ctrl->ops->prep_memcpy(chan, dma_addr_dst, dma_addr_src, len);
rt_mutex_release(&ctrl->mutex);
}
else
{
err = -RT_ENOSYS;
}
if (!err)
{
rt_memcpy(&chan->transfer, transfer, sizeof(*transfer));
}
chan->prep_err = err;
return err;
}
rt_err_t rt_dma_prep_cyclic(struct rt_dma_chan *chan,
struct rt_dma_slave_transfer *transfer)
{
rt_err_t err;
rt_ubase_t dma_buf_addr;
struct rt_dma_controller *ctrl;
struct rt_dma_slave_config *conf;
enum rt_dma_transfer_direction dir;
if (!chan || !transfer)
{
return -RT_EINVAL;
}
ctrl = chan->ctrl;
conf = &chan->conf;
if (chan->conf_err)
{
LOG_D("%s: Not config done", rt_dm_dev_get_name(chan->slave));
return chan->conf_err;
}
dir = chan->conf.direction;
if (dir == RT_DMA_MEM_TO_DEV || dir == RT_DMA_MEM_TO_MEM)
{
dma_buf_addr = transfer->src_addr;
if (range_is_illegal(rt_dm_dev_get_name(ctrl->dev), "source",
dma_buf_addr, conf->src_addr))
{
return -RT_EINVAL;
}
}
else if (dir == RT_DMA_DEV_TO_MEM)
{
dma_buf_addr = transfer->dst_addr;
if (range_is_illegal(rt_dm_dev_get_name(ctrl->dev), "dest",
dma_buf_addr, conf->dst_addr))
{
return -RT_EINVAL;
}
}
else
{
dma_buf_addr = ~0UL;
}
if (ctrl->ops->prep_cyclic)
{
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
err = ctrl->ops->prep_cyclic(chan, dma_buf_addr,
transfer->buffer_len, transfer->period_len, dir);
rt_mutex_release(&ctrl->mutex);
}
else
{
err = -RT_ENOSYS;
}
if (!err)
{
rt_memcpy(&chan->transfer, transfer, sizeof(*transfer));
}
chan->prep_err = err;
return err;
}
rt_err_t rt_dma_prep_single(struct rt_dma_chan *chan,
struct rt_dma_slave_transfer *transfer)
{
rt_err_t err;
rt_ubase_t dma_buf_addr;
struct rt_dma_controller *ctrl;
struct rt_dma_slave_config *conf;
enum rt_dma_transfer_direction dir;
if (!chan || !transfer)
{
return -RT_EINVAL;
}
ctrl = chan->ctrl;
conf = &chan->conf;
if (chan->conf_err)
{
LOG_D("%s: Not config done", rt_dm_dev_get_name(chan->slave));
return chan->conf_err;
}
dir = chan->conf.direction;
if (dir == RT_DMA_MEM_TO_DEV || dir == RT_DMA_MEM_TO_MEM)
{
dma_buf_addr = transfer->src_addr;
if (range_is_illegal(rt_dm_dev_get_name(ctrl->dev), "source",
dma_buf_addr, conf->src_addr))
{
return -RT_EINVAL;
}
}
else if (dir == RT_DMA_DEV_TO_MEM)
{
dma_buf_addr = transfer->dst_addr;
if (range_is_illegal(rt_dm_dev_get_name(ctrl->dev), "dest",
dma_buf_addr, conf->dst_addr))
{
return -RT_EINVAL;
}
}
else
{
dma_buf_addr = ~0UL;
}
if (ctrl->ops->prep_single)
{
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
err = ctrl->ops->prep_single(chan, dma_buf_addr,
transfer->buffer_len, dir);
rt_mutex_release(&ctrl->mutex);
}
else
{
err = -RT_ENOSYS;
}
if (!err)
{
rt_memcpy(&chan->transfer, transfer, sizeof(*transfer));
}
chan->prep_err = err;
return err;
}
static struct rt_dma_controller *ofw_find_dma_controller(struct rt_device *dev,
const char *name, struct rt_ofw_cell_args *args)
{
struct rt_dma_controller *ctrl = RT_NULL;
#ifdef RT_USING_OFW
int index;
struct rt_ofw_node *np = dev->ofw_node, *ctrl_np;
if (!np)
{
return RT_NULL;
}
index = rt_ofw_prop_index_of_string(np, "dma-names", name);
if (index < 0)
{
return RT_NULL;
}
if (!rt_ofw_parse_phandle_cells(np, "dmas", "#dma-cells", index, args))
{
ctrl_np = args->data;
if (!rt_ofw_data(ctrl_np))
{
rt_platform_ofw_request(ctrl_np);
}
ctrl = rt_ofw_data(ctrl_np);
rt_ofw_node_put(ctrl_np);
}
#endif /* RT_USING_OFW */
return ctrl;
}
struct rt_dma_chan *rt_dma_chan_request(struct rt_device *dev, const char *name)
{
void *fw_data = RT_NULL;
struct rt_dma_chan *chan;
struct rt_ofw_cell_args dma_args;
struct rt_dma_controller *ctrl = RT_NULL;
if (!dev)
{
return rt_err_ptr(-RT_EINVAL);
}
if (name)
{
fw_data = &dma_args;
ctrl = ofw_find_dma_controller(dev, name, &dma_args);
}
else
{
struct rt_dma_controller *ctrl_tmp;
rt_spin_lock(&dmac_nodes_lock);
rt_list_for_each_entry(ctrl_tmp, &dmac_nodes, list)
{
/* Only memory to memory for uname request */
if (rt_bitmap_test_bit(ctrl_tmp->dir_cap, RT_DMA_MEM_TO_MEM))
{
ctrl = ctrl_tmp;
break;
}
}
rt_spin_unlock(&dmac_nodes_lock);
}
if (rt_is_err_or_null(ctrl))
{
return ctrl ? ctrl : rt_err_ptr(-RT_ENOSYS);
}
if (ctrl->ops->request_chan)
{
chan = ctrl->ops->request_chan(ctrl, dev, fw_data);
}
else
{
chan = rt_calloc(1, sizeof(*chan));
if (!chan)
{
chan = rt_err_ptr(-RT_ENOMEM);
}
}
if (rt_is_err(chan))
{
return chan;
}
if (!chan)
{
LOG_E("%s: unset request channels error", rt_dm_dev_get_name(ctrl->dev));
return rt_err_ptr(-RT_ERROR);
}
chan->name = name;
chan->ctrl = ctrl;
chan->slave = dev;
rt_list_init(&chan->list);
chan->conf_err = -RT_ERROR;
chan->prep_err = -RT_ERROR;
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
rt_list_insert_before(&ctrl->channels_nodes, &chan->list);
rt_mutex_release(&ctrl->mutex);
return chan;
}
rt_err_t rt_dma_chan_release(struct rt_dma_chan *chan)
{
rt_err_t err = RT_EOK;
if (!chan)
{
return -RT_EINVAL;
}
rt_mutex_take(&chan->ctrl->mutex, RT_WAITING_FOREVER);
rt_list_remove(&chan->list);
rt_mutex_release(&chan->ctrl->mutex);
if (chan->ctrl->ops->release_chan)
{
err = chan->ctrl->ops->release_chan(chan);
}
else
{
rt_free(chan);
}
return err;
}

View File

@ -0,0 +1,691 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#define DBG_TAG "dma.pool"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include <mm_aspace.h>
#include <dt-bindings/size.h>
static struct rt_spinlock dma_pools_lock = {};
static rt_list_t dma_pool_nodes = RT_LIST_OBJECT_INIT(dma_pool_nodes);
static struct rt_dma_pool *dma_pool_install(rt_region_t *region);
static void *dma_alloc(struct rt_device *dev, rt_size_t size,
rt_ubase_t *dma_handle, rt_ubase_t flags);
static void dma_free(struct rt_device *dev, rt_size_t size,
void *cpu_addr, rt_ubase_t dma_handle, rt_ubase_t flags);
rt_inline void region_pool_lock(void)
{
rt_hw_spin_lock(&dma_pools_lock.lock);
}
rt_inline void region_pool_unlock(void)
{
rt_hw_spin_unlock(&dma_pools_lock.lock);
}
static rt_err_t dma_map_coherent_sync_out_data(struct rt_device *dev,
void *data, rt_size_t size, rt_ubase_t *dma_handle, rt_ubase_t flags)
{
if (dma_handle)
{
*dma_handle = (rt_ubase_t)rt_kmem_v2p(data);
}
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, data, size);
return RT_EOK;
}
static rt_err_t dma_map_coherent_sync_in_data(struct rt_device *dev,
void *out_data, rt_size_t size, rt_ubase_t dma_handle, rt_ubase_t flags)
{
rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, out_data, size);
return RT_EOK;
}
static const struct rt_dma_map_ops dma_map_coherent_ops =
{
.sync_out_data = dma_map_coherent_sync_out_data,
.sync_in_data = dma_map_coherent_sync_in_data,
};
static rt_err_t dma_map_nocoherent_sync_out_data(struct rt_device *dev,
void *data, rt_size_t size, rt_ubase_t *dma_handle, rt_ubase_t flags)
{
if (dma_handle)
{
*dma_handle = (rt_ubase_t)rt_kmem_v2p(data);
}
return RT_EOK;
}
static rt_err_t dma_map_nocoherent_sync_in_data(struct rt_device *dev,
void *out_data, rt_size_t size, rt_ubase_t dma_handle, rt_ubase_t flags)
{
return RT_EOK;
}
static const struct rt_dma_map_ops dma_map_nocoherent_ops =
{
.sync_out_data = dma_map_nocoherent_sync_out_data,
.sync_in_data = dma_map_nocoherent_sync_in_data,
};
#ifdef RT_USING_OFW
rt_inline rt_ubase_t ofw_addr_cpu2dma(struct rt_device *dev, rt_ubase_t addr)
{
return (rt_ubase_t)rt_ofw_translate_cpu2dma(dev->ofw_node, addr);
}
rt_inline rt_ubase_t ofw_addr_dma2cpu(struct rt_device *dev, rt_ubase_t addr)
{
return (rt_ubase_t)rt_ofw_translate_dma2cpu(dev->ofw_node, addr);
}
static void *ofw_dma_map_alloc(struct rt_device *dev, rt_size_t size,
rt_ubase_t *dma_handle, rt_ubase_t flags)
{
void *cpu_addr = dma_alloc(dev, size, dma_handle, flags);
if (cpu_addr && dma_handle)
{
*dma_handle = ofw_addr_cpu2dma(dev, *dma_handle);
}
return cpu_addr;
}
static void ofw_dma_map_free(struct rt_device *dev, rt_size_t size,
void *cpu_addr, rt_ubase_t dma_handle, rt_ubase_t flags)
{
dma_handle = ofw_addr_dma2cpu(dev, dma_handle);
dma_free(dev, size, cpu_addr, dma_handle, flags);
}
static rt_err_t ofw_dma_map_sync_out_data(struct rt_device *dev,
void *data, rt_size_t size,
rt_ubase_t *dma_handle, rt_ubase_t flags)
{
rt_err_t err;
if (flags & RT_DMA_F_NOCACHE)
{
err = dma_map_nocoherent_sync_out_data(dev, data, size, dma_handle, flags);
}
else
{
err = dma_map_coherent_sync_out_data(dev, data, size, dma_handle, flags);
}
if (!err && dma_handle)
{
*dma_handle = ofw_addr_cpu2dma(dev, *dma_handle);
}
return err;
}
static rt_err_t ofw_dma_map_sync_in_data(struct rt_device *dev,
void *out_data, rt_size_t size,
rt_ubase_t dma_handle, rt_ubase_t flags)
{
dma_handle = ofw_addr_dma2cpu(dev, dma_handle);
if (flags & RT_DMA_F_NOCACHE)
{
return dma_map_nocoherent_sync_in_data(dev, out_data, size, dma_handle, flags);
}
return dma_map_coherent_sync_in_data(dev, out_data, size, dma_handle, flags);
}
static const struct rt_dma_map_ops ofw_dma_map_ops =
{
.alloc = ofw_dma_map_alloc,
.free = ofw_dma_map_free,
.sync_out_data = ofw_dma_map_sync_out_data,
.sync_in_data = ofw_dma_map_sync_in_data,
};
static const struct rt_dma_map_ops *ofw_device_dma_ops(struct rt_device *dev)
{
rt_err_t err;
int region_nr = 0;
const fdt32_t *cell;
rt_phandle phandle;
rt_region_t region;
struct rt_ofw_prop *prop;
struct rt_dma_pool *dma_pool;
const struct rt_dma_map_ops *ops = RT_NULL;
struct rt_ofw_node *mem_np, *np = dev->ofw_node;
rt_ofw_foreach_prop_u32(np, "memory-region", prop, cell, phandle)
{
rt_uint64_t addr, size;
if (!(mem_np = rt_ofw_find_node_by_phandle(phandle)))
{
if (region_nr == 0)
{
return RT_NULL;
}
break;
}
if ((err = rt_ofw_get_address(mem_np, 0, &addr, &size)))
{
LOG_E("%s: Read '%s' error = %s", rt_ofw_node_full_name(mem_np),
"memory-region", rt_strerror(err));
rt_ofw_node_put(mem_np);
continue;
}
region.start = addr;
region.end = addr + size;
region.name = rt_dm_dev_get_name(dev);
rt_ofw_node_put(mem_np);
if (!(dma_pool = dma_pool_install(&region)))
{
return RT_NULL;
}
if (rt_ofw_prop_read_bool(mem_np, "no-map"))
{
dma_pool->flags |= RT_DMA_F_NOMAP;
}
if (!rt_dma_device_is_coherent(dev))
{
dma_pool->flags |= RT_DMA_F_NOCACHE;
}
dma_pool->dev = dev;
++region_nr;
}
if (region_nr)
{
ops = &ofw_dma_map_ops;
}
return ops;
}
#endif /* RT_USING_OFW */
static const struct rt_dma_map_ops *device_dma_ops(struct rt_device *dev)
{
const struct rt_dma_map_ops *ops = dev->dma_ops;
if (ops)
{
return ops;
}
#ifdef RT_USING_OFW
if (dev->ofw_node && (ops = ofw_device_dma_ops(dev)))
{
return ops;
}
#endif
if (rt_dma_device_is_coherent(dev))
{
ops = &dma_map_coherent_ops;
}
else
{
ops = &dma_map_nocoherent_ops;
}
dev->dma_ops = ops;
return ops;
}
static rt_ubase_t dma_pool_alloc(struct rt_dma_pool *pool, rt_size_t size)
{
rt_size_t bit, next_bit, end_bit, max_bits;
size = RT_DIV_ROUND_UP(size, ARCH_PAGE_SIZE);
max_bits = pool->bits - size;
rt_bitmap_for_each_clear_bit(pool->map, bit, max_bits)
{
end_bit = bit + size;
for (next_bit = bit + 1; next_bit < end_bit; ++next_bit)
{
if (rt_bitmap_test_bit(pool->map, next_bit))
{
bit = next_bit;
goto _next;
}
}
if (next_bit == end_bit)
{
while (next_bit --> bit)
{
rt_bitmap_set_bit(pool->map, next_bit);
}
return pool->start + bit * ARCH_PAGE_SIZE;
}
_next:
}
return RT_NULL;
}
static void dma_pool_free(struct rt_dma_pool *pool, rt_ubase_t offset, rt_size_t size)
{
rt_size_t bit = (offset - pool->start) / ARCH_PAGE_SIZE, end_bit;
size = RT_DIV_ROUND_UP(size, ARCH_PAGE_SIZE);
end_bit = bit + size;
for (; bit < end_bit; ++bit)
{
rt_bitmap_clear_bit(pool->map, bit);
}
}
static void *dma_alloc(struct rt_device *dev, rt_size_t size,
rt_ubase_t *dma_handle, rt_ubase_t flags)
{
void *dma_buffer = RT_NULL;
struct rt_dma_pool *pool;
region_pool_lock();
rt_list_for_each_entry(pool, &dma_pool_nodes, list)
{
if (pool->flags & RT_DMA_F_DEVICE)
{
if (!(flags & RT_DMA_F_DEVICE) || pool->dev != dev)
{
continue;
}
}
else if ((flags & RT_DMA_F_DEVICE))
{
continue;
}
if ((flags & RT_DMA_F_NOMAP) && !((pool->flags & RT_DMA_F_NOMAP)))
{
continue;
}
if ((flags & RT_DMA_F_32BITS) && !((pool->flags & RT_DMA_F_32BITS)))
{
continue;
}
if ((flags & RT_DMA_F_LINEAR) && !((pool->flags & RT_DMA_F_LINEAR)))
{
continue;
}
*dma_handle = dma_pool_alloc(pool, size);
if (*dma_handle && !(flags & RT_DMA_F_NOMAP))
{
if (flags & RT_DMA_F_NOCACHE)
{
dma_buffer = rt_ioremap_nocache((void *)*dma_handle, size);
}
else
{
dma_buffer = rt_ioremap_cached((void *)*dma_handle, size);
}
if (!dma_buffer)
{
dma_pool_free(pool, *dma_handle, size);
continue;
}
break;
}
else if (*dma_handle)
{
dma_buffer = (void *)*dma_handle;
break;
}
}
region_pool_unlock();
return dma_buffer;
}
static void dma_free(struct rt_device *dev, rt_size_t size,
void *cpu_addr, rt_ubase_t dma_handle, rt_ubase_t flags)
{
struct rt_dma_pool *pool;
region_pool_lock();
rt_list_for_each_entry(pool, &dma_pool_nodes, list)
{
if (dma_handle >= pool->region.start &&
dma_handle <= pool->region.end)
{
rt_iounmap(cpu_addr);
dma_pool_free(pool, dma_handle, size);
break;
}
}
region_pool_unlock();
}
void *rt_dma_alloc(struct rt_device *dev, rt_size_t size,
rt_ubase_t *dma_handle, rt_ubase_t flags)
{
void *dma_buffer = RT_NULL;
rt_ubase_t dma_handle_s = 0;
const struct rt_dma_map_ops *ops;
if (!dev || !size)
{
return RT_NULL;
}
ops = device_dma_ops(dev);
if (ops->alloc)
{
dma_buffer = ops->alloc(dev, size, &dma_handle_s, flags);
}
else
{
dma_buffer = dma_alloc(dev, size, &dma_handle_s, flags);
}
if (!dma_buffer)
{
return dma_buffer;
}
if (dma_handle)
{
*dma_handle = dma_handle_s;
}
return dma_buffer;
}
void rt_dma_free(struct rt_device *dev, rt_size_t size,
void *cpu_addr, rt_ubase_t dma_handle, rt_ubase_t flags)
{
const struct rt_dma_map_ops *ops;
if (!dev || !size || !cpu_addr)
{
return;
}
ops = device_dma_ops(dev);
if (ops->free)
{
ops->free(dev, size, cpu_addr, dma_handle, flags);
}
else
{
dma_free(dev, size, cpu_addr, dma_handle, flags);
}
}
rt_err_t rt_dma_sync_out_data(struct rt_device *dev, void *data, rt_size_t size,
rt_ubase_t *dma_handle, rt_ubase_t flags)
{
rt_err_t err;
rt_ubase_t dma_handle_s = 0;
const struct rt_dma_map_ops *ops;
if (!data || !size)
{
return -RT_EINVAL;
}
ops = device_dma_ops(dev);
err = ops->sync_out_data(dev, data, size, &dma_handle_s, flags);
if (dma_handle)
{
*dma_handle = dma_handle_s;
}
return err;
}
rt_err_t rt_dma_sync_in_data(struct rt_device *dev, void *out_data, rt_size_t size,
rt_ubase_t dma_handle, rt_ubase_t flags)
{
rt_err_t err;
const struct rt_dma_map_ops *ops;
if (!out_data || !size)
{
return -RT_EINVAL;
}
ops = device_dma_ops(dev);
err = ops->sync_in_data(dev, out_data, size, dma_handle, flags);
return err;
}
static struct rt_dma_pool *dma_pool_install(rt_region_t *region)
{
rt_err_t err;
struct rt_dma_pool *pool;
if (!(pool = rt_calloc(1, sizeof(*pool))))
{
LOG_E("Install pool[%p, %p] error = %s",
region->start, region->end, rt_strerror(-RT_ENOMEM));
return RT_NULL;
}
rt_memcpy(&pool->region, region, sizeof(*region));
pool->flags |= RT_DMA_F_LINEAR;
if (region->end < 4UL * SIZE_GB)
{
pool->flags |= RT_DMA_F_32BITS;
}
pool->start = RT_ALIGN(pool->region.start, ARCH_PAGE_SIZE);
pool->bits = (pool->region.end - pool->start) / ARCH_PAGE_SIZE;
if (!pool->bits)
{
err = -RT_EINVAL;
goto _fail;
}
pool->map = rt_calloc(RT_BITMAP_LEN(pool->bits), sizeof(*pool->map));
if (!pool->map)
{
err = -RT_ENOMEM;
goto _fail;
}
rt_list_init(&pool->list);
region_pool_lock();
rt_list_insert_before(&dma_pool_nodes, &pool->list);
region_pool_unlock();
return pool;
_fail:
rt_free(pool);
LOG_E("Install pool[%p, %p] error = %s",
region->start, region->end, rt_strerror(err));
return RT_NULL;
}
struct rt_dma_pool *rt_dma_pool_install(rt_region_t *region)
{
struct rt_dma_pool *pool;
if (!region)
{
return RT_NULL;
}
if ((pool = dma_pool_install(region)))
{
region = &pool->region;
LOG_I("%s: Reserved %u.%u MiB at %p",
region->name,
(region->end - region->start) / SIZE_MB,
(region->end - region->start) / SIZE_KB & (SIZE_KB - 1),
region->start);
}
return pool;
}
rt_err_t rt_dma_pool_extract(rt_region_t *region_list, rt_size_t list_len,
rt_size_t cma_size, rt_size_t coherent_pool_size)
{
struct rt_dma_pool *pool;
rt_region_t *region = region_list, *region_high = RT_NULL, cma, coherent_pool;
if (!region_list || !list_len || cma_size < coherent_pool_size)
{
return -RT_EINVAL;
}
for (rt_size_t i = 0; i < list_len; ++i, ++region)
{
if (!region->name)
{
continue;
}
/* Always use low address in 4G */
if (region->end - region->start >= cma_size)
{
if ((rt_ssize_t)((4UL * SIZE_GB) - region->start) < cma_size)
{
region_high = region;
continue;
}
goto _found;
}
}
if (region_high)
{
region = region_high;
LOG_W("No available DMA zone in 4G");
goto _found;
}
return -RT_EEMPTY;
_found:
if (region->end - region->start != cma_size)
{
cma.start = region->start;
cma.end = cma.start + cma_size;
/* Update input region */
region->start += cma_size;
}
else
{
rt_memcpy(&cma, region, sizeof(cma));
}
coherent_pool.name = "coherent-pool";
coherent_pool.start = cma.start;
coherent_pool.end = coherent_pool.start + coherent_pool_size;
cma.name = "cma";
cma.start += coherent_pool_size;
if (!(pool = rt_dma_pool_install(&coherent_pool)))
{
return -RT_ENOMEM;
}
/* Use: CMA > coherent-pool */
if (!(pool = rt_dma_pool_install(&cma)))
{
return -RT_ENOMEM;
}
return RT_EOK;
}
#if defined(RT_USING_CONSOLE) && defined(RT_USING_MSH)
static int list_dma_pool(int argc, char**argv)
{
int count = 0;
rt_region_t *region;
struct rt_dma_pool *pool;
rt_kprintf("%-*.s Region\n", RT_NAME_MAX, "Name");
region_pool_lock();
rt_list_for_each_entry(pool, &dma_pool_nodes, list)
{
region = &pool->region;
rt_kprintf("%-*.s [%p, %p]\n", RT_NAME_MAX, region->name,
region->start, region->end);
++count;
}
rt_kprintf("%d DMA memory found\n", count);
region_pool_unlock();
return 0;
}
MSH_CMD_EXPORT(list_dma_pool, dump all dma memory pool);
#endif /* RT_USING_CONSOLE && RT_USING_MSH */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -320,7 +320,14 @@ static rt_err_t rt_hwtimer_control(struct rt_device *dev, int cmd, void *args)
break;
default:
{
result = -RT_ENOSYS;
if (timer->ops->control != RT_NULL)
{
result = timer->ops->control(timer, cmd, args);
}
else
{
result = -RT_ENOSYS;
}
}
break;
}

View File

@ -17,203 +17,227 @@ if RT_USING_I2C
default n
endif
config RT_USING_SOFT_I2C
menuconfig RT_USING_SOFT_I2C
bool "Use GPIO to soft simulate I2C"
default n
select RT_USING_PIN
select RT_USING_I2C_BITOPS
if RT_USING_SOFT_I2C
config RT_USING_SOFT_I2C1
bool "Enable I2C1 Bus (software simulation)"
default y
if RT_USING_SOFT_I2C1
config RT_SOFT_I2C1_SCL_PIN
int "SCL pin number"
range 0 32767
default 1
config RT_SOFT_I2C1_SDA_PIN
int "SDA pin number"
range 0 32767
default 2
config RT_SOFT_I2C1_BUS_NAME
string "Bus name"
default "i2c1"
config RT_SOFT_I2C1_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C1_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
config RT_USING_SOFT_I2C2
bool "Enable I2C2 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C2
config RT_SOFT_I2C2_SCL_PIN
int "SCL pin number"
range 0 32767
default 3
config RT_SOFT_I2C2_SDA_PIN
int "SDA pin number"
range 0 32767
default 4
config RT_SOFT_I2C2_BUS_NAME
string "Bus name"
default "i2c2"
config RT_SOFT_I2C2_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C2_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
config RT_USING_SOFT_I2C3
bool "Enable I2C3 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C3
config RT_SOFT_I2C3_SCL_PIN
int "SCL pin number"
range 0 32767
default 5
config RT_SOFT_I2C3_SDA_PIN
int "SDA pin number"
range 0 32767
default 6
config RT_SOFT_I2C3_BUS_NAME
string "Bus name"
default "i2c3"
config RT_SOFT_I2C3_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C3_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
config RT_USING_SOFT_I2C4
bool "Enable I2C4 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C4
config RT_SOFT_I2C4_SCL_PIN
int "SCL pin number"
range 0 32767
default 7
config RT_SOFT_I2C4_SDA_PIN
int "SDA pin number"
range 0 32767
default 8
config RT_SOFT_I2C4_BUS_NAME
string "Bus name"
default "i2c4"
config RT_SOFT_I2C4_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C4_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
config RT_USING_SOFT_I2C5
bool "Enable I2C5 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C5
config RT_SOFT_I2C5_SCL_PIN
int "SCL pin number"
range 0 32767
default 9
config RT_SOFT_I2C5_SDA_PIN
int "SDA pin number"
range 0 32767
default 10
config RT_SOFT_I2C5_BUS_NAME
string "Bus name"
default "i2c5"
config RT_SOFT_I2C5_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C5_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
config RT_USING_SOFT_I2C6
bool "Enable I2C6 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C6
config RT_SOFT_I2C6_SCL_PIN
int "SCL pin number"
range 0 32767
default 11
config RT_SOFT_I2C6_SDA_PIN
int "SDA pin number"
range 0 32767
default 12
config RT_SOFT_I2C6_BUS_NAME
string "Bus name"
default "i2c6"
config RT_SOFT_I2C6_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C6_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
config RT_USING_SOFT_I2C7
bool "Enable I2C7 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C7
config RT_SOFT_I2C7_SCL_PIN
int "SCL pin number"
range 0 32767
default 13
config RT_SOFT_I2C7_SDA_PIN
int "SDA pin number"
range 0 32767
default 14
config RT_SOFT_I2C7_BUS_NAME
string "Bus name"
default "i2c7"
config RT_SOFT_I2C7_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C7_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
config RT_USING_SOFT_I2C8
bool "Enable I2C8 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C8
config RT_SOFT_I2C8_SCL_PIN
int "SCL pin number"
range 0 32767
default 15
config RT_SOFT_I2C8_SDA_PIN
int "SDA pin number"
range 0 32767
default 16
config RT_SOFT_I2C8_BUS_NAME
string "Bus name"
default "i2c8"
config RT_SOFT_I2C8_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C8_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
endif
if RT_USING_SOFT_I2C
menuconfig RT_USING_SOFT_I2C0
bool "Enable I2C0 Bus (software simulation)"
default y
if RT_USING_SOFT_I2C0
config RT_SOFT_I2C0_SCL_PIN
int "SCL pin number"
range 0 32767
default 1
config RT_SOFT_I2C0_SDA_PIN
int "SDA pin number"
range 0 32767
default 2
config RT_SOFT_I2C0_BUS_NAME
string "Bus name"
default "i2c0"
config RT_SOFT_I2C0_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C0_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
menuconfig RT_USING_SOFT_I2C1
bool "Enable I2C1 Bus (software simulation)"
default y
if RT_USING_SOFT_I2C1
config RT_SOFT_I2C1_SCL_PIN
int "SCL pin number"
range 0 32767
default 3
config RT_SOFT_I2C1_SDA_PIN
int "SDA pin number"
range 0 32767
default 4
config RT_SOFT_I2C1_BUS_NAME
string "Bus name"
default "i2c1"
config RT_SOFT_I2C1_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C1_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
menuconfig RT_USING_SOFT_I2C2
bool "Enable I2C2 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C2
config RT_SOFT_I2C2_SCL_PIN
int "SCL pin number"
range 0 32767
default 5
config RT_SOFT_I2C2_SDA_PIN
int "SDA pin number"
range 0 32767
default 6
config RT_SOFT_I2C2_BUS_NAME
string "Bus name"
default "i2c2"
config RT_SOFT_I2C2_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C2_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
menuconfig RT_USING_SOFT_I2C3
bool "Enable I2C3 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C3
config RT_SOFT_I2C3_SCL_PIN
int "SCL pin number"
range 0 32767
default 7
config RT_SOFT_I2C3_SDA_PIN
int "SDA pin number"
range 0 32767
default 8
config RT_SOFT_I2C3_BUS_NAME
string "Bus name"
default "i2c3"
config RT_SOFT_I2C3_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C3_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
menuconfig RT_USING_SOFT_I2C4
bool "Enable I2C4 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C4
config RT_SOFT_I2C4_SCL_PIN
int "SCL pin number"
range 0 32767
default 9
config RT_SOFT_I2C4_SDA_PIN
int "SDA pin number"
range 0 32767
default 10
config RT_SOFT_I2C4_BUS_NAME
string "Bus name"
default "i2c4"
config RT_SOFT_I2C4_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C4_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
menuconfig RT_USING_SOFT_I2C5
bool "Enable I2C5 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C5
config RT_SOFT_I2C5_SCL_PIN
int "SCL pin number"
range 0 32767
default 11
config RT_SOFT_I2C5_SDA_PIN
int "SDA pin number"
range 0 32767
default 12
config RT_SOFT_I2C5_BUS_NAME
string "Bus name"
default "i2c5"
config RT_SOFT_I2C5_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C5_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
menuconfig RT_USING_SOFT_I2C6
bool "Enable I2C6 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C6
config RT_SOFT_I2C6_SCL_PIN
int "SCL pin number"
range 0 32767
default 13
config RT_SOFT_I2C6_SDA_PIN
int "SDA pin number"
range 0 32767
default 14
config RT_SOFT_I2C6_BUS_NAME
string "Bus name"
default "i2c6"
config RT_SOFT_I2C6_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C6_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
menuconfig RT_USING_SOFT_I2C7
bool "Enable I2C7 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C7
config RT_SOFT_I2C7_SCL_PIN
int "SCL pin number"
range 0 32767
default 15
config RT_SOFT_I2C7_SDA_PIN
int "SDA pin number"
range 0 32767
default 16
config RT_SOFT_I2C7_BUS_NAME
string "Bus name"
default "i2c7"
config RT_SOFT_I2C7_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C7_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
menuconfig RT_USING_SOFT_I2C8
bool "Enable I2C8 Bus (software simulation)"
default n
if RT_USING_SOFT_I2C8
config RT_SOFT_I2C8_SCL_PIN
int "SCL pin number"
range 0 32767
default 17
config RT_SOFT_I2C8_SDA_PIN
int "SDA pin number"
range 0 32767
default 18
config RT_SOFT_I2C8_BUS_NAME
string "Bus name"
default "i2c8"
config RT_SOFT_I2C8_TIMING_DELAY
int "Timing delay (us)"
range 0 32767
default 10
config RT_SOFT_I2C8_TIMING_TIMEOUT
int "Timing timeout (tick)"
range 0 32767
default 10
endif
endif
endif

View File

@ -3,16 +3,16 @@ from building import *
cwd = GetCurrentDir()
src = Split("""
i2c_core.c
i2c_dev.c
dev_i2c_core.c
dev_i2c_dev.c
""")
if GetDepend('RT_USING_I2C_BITOPS'):
src = src + ['i2c-bit-ops.c']
src = src + ['dev_i2c_bit_ops.c']
if GetDepend('RT_USING_SOFT_I2C'):
src = src + ['soft_i2c.c']
src = src + ['dev_soft_i2c.c']
if GetDepend(['RT_USING_DM']):
src += ['i2c_bus.c', 'i2c_dm.c']
src += ['dev_i2c_bus.c', 'dev_i2c_dm.c']
# The set of source files associated with this SConscript file.
path = [cwd + '/../include']

View File

@ -10,7 +10,7 @@
#include <rtdevice.h>
#define DBG_TAG "i2c.bus"
#define DBG_TAG "dev.i2c.bus"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

View File

@ -30,7 +30,7 @@ rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus,
res = rt_i2c_bus_device_device_init(bus, bus_name);
LOG_I("I2C bus [%s] registered", bus_name);
LOG_D("I2C bus [%s] registered", bus_name);
#ifdef RT_USING_DM
if (!res)

Some files were not shown because too many files have changed in this diff Show More