Revert "rtt更新"

This reverts commit d6009a0773d226206cf691dda1be16f5aa6299ee.
This commit is contained in:
dgjames 2025-01-23 21:03:05 +08:00
parent 0abd316c90
commit cabe8296ea
726 changed files with 6265 additions and 103371 deletions

View File

@ -1,189 +0,0 @@
scons.args: &scons
scons_arg:
- '--strict'
# ------ kernel CI ------
kernel.klibc-stdlib:
<<: *scons
kconfig:
- CONFIG_RT_KLIBC_USING_STDLIB=y
- CONFIG_RT_KLIBC_USING_STDLIB_MEMORY=y
kernel.klibc-tinysize:
<<: *scons
kconfig:
- CONFIG_RT_KLIBC_USING_TINY_SIZE=y
kernel.klibc-vsnprintf-std:
<<: *scons
kconfig:
- CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD=y
- CONFIG_RT_KLIBC_USING_PRINTF_LONGLONG=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=y
# ------ online-packages CI ------
online-packages.iot.at_devices:
<<: *scons
kconfig:
- CONFIG_PKG_USING_AT_DEVICE=y
# Quectel M26/MC20
- CONFIG_AT_DEVICE_USING_M26=y
- CONFIG_AT_DEVICE_M26_INIT_ASYN=y
# Quectel EC20
- CONFIG_AT_DEVICE_USING_EC20=y
- CONFIG_AT_DEVICE_EC20_INIT_ASYN=y
# Espressif ESP32
- CONFIG_AT_DEVICE_USING_ESP32=y
- CONFIG_AT_DEVICE_ESP32_INIT_ASYN=y
# Espressif ESP8266
- CONFIG_AT_DEVICE_USING_ESP8266=y
- CONFIG_AT_DEVICE_ESP8266_INIT_ASYN=y
# Realthread RW007
- CONFIG_AT_DEVICE_USING_RW007=y
- CONFIG_AT_DEVICE_RW007_INIT_ASYN=y
# SIMCom SIM800C
- CONFIG_AT_DEVICE_USING_SIM800C=y
- CONFIG_AT_DEVICE_SIM800C_INIT_ASYN=y
# SIMCom SIM76XX
- CONFIG_AT_DEVICE_USING_SIM76XX=y
- CONFIG_AT_DEVICE_SIM76XX_INIT_ASYN=y
# Notion MW31
- CONFIG_AT_DEVICE_USING_MW31=y
- CONFIG_AT_DEVICE_MW31_INIT_ASYN=y
# WinnerMicro W60X
- CONFIG_AT_DEVICE_USING_W60X=y
- CONFIG_AT_DEVICE_W60X_INIT_ASYN=y
# Ai-Think A9G
- CONFIG_AT_DEVICE_USING_A9G=y
- CONFIG_AT_DEVICE_A9G_INIT_ASYN=y
# Quectel BC26
- CONFIG_AT_DEVICE_USING_BC26=y
- CONFIG_AT_DEVICE_BC26_INIT_ASYN=y
# luat Air720
- CONFIG_AT_DEVICE_USING_AIR720=y
- CONFIG_AT_DEVICE_AIR720_INIT_ASYN=y
# Gosuncn ME3616
- CONFIG_AT_DEVICE_USING_ME3616=y
- CONFIG_AT_DEVICE_ME3616_INIT_ASYN=y
# ChinaMobile M6315
- CONFIG_AT_DEVICE_USING_M6315=y
- CONFIG_AT_DEVICE_M6315_INIT_ASYN=y
# Quectel BC28
- CONFIG_AT_DEVICE_USING_BC28=y
- CONFIG_AT_DEVICE_BC28_INIT_ASYN=y
# Quectel EC200T/EC200S
- CONFIG_AT_DEVICE_USING_EC200X=y
- CONFIG_AT_DEVICE_EC200X_INIT_ASYN=y
# Neoway N21
- CONFIG_AT_DEVICE_USING_N21=y
- CONFIG_AT_DEVICE_N21_INIT_ASYN=y
# Neoway N58
- CONFIG_AT_DEVICE_USING_N58=y
- CONFIG_AT_DEVICE_N58_INIT_ASYN=y
# ChinaMobile M5311
- CONFIG_AT_DEVICE_USING_M5311=y
- CONFIG_AT_DEVICE_M5311_INIT_ASYN=y
# Fibocom L610
- CONFIG_AT_DEVICE_USING_L610=y
- CONFIG_AT_DEVICE_L610_INIT_ASYN=y
# Neoway N720
- CONFIG_AT_DEVICE_USING_N720=y
- CONFIG_AT_DEVICE_N720_INIT_ASYN=y
# Gosuncn ML305
- CONFIG_AT_DEVICE_USING_ML305=y
- CONFIG_AT_DEVICE_ML305_INIT_ASYN=y
online-packages.misc.misc:
<<: *scons
kconfig:
- CONFIG_PKG_USING_MULTIBUTTON=y
online-packages.misc.vi:
<<: *scons
kconfig:
- CONFIG_PKG_USING_VI=y
# - CONFIG_VI_ENABLE_8BIT=y
- CONFIG_VI_ENABLE_COLON=y
- CONFIG_VI_ENABLE_COLON_EXPAND=y
- CONFIG_VI_ENABLE_YANKMARK=y
- CONFIG_VI_ENABLE_SEARCH=y
- CONFIG_VI_ENABLE_DOT_CMD=y
- CONFIG_VI_ENABLE_READONLY=y
- CONFIG_VI_ENABLE_SETOPTS=y
- CONFIG_VI_ENABLE_SET=y
- CONFIG_VI_ENABLE_WIN_RESIZE=y
- CONFIG_VI_ENABLE_VI_ASK_TERMINAL=y
- CONFIG_VI_ENABLE_UNDO=y
- CONFIG_VI_ENABLE_UNDO_QUEUE=y
- CONFIG_VI_ENABLE_VERBOSE_STATUS=y
online-packages.multimedia.lvgl-v8.3-latest:
<<: *scons
kconfig:
- CONFIG_BSP_USING_LVGL=y
- CONFIG_BSP_USING_LVGL_DEMO=y
- CONFIG_PKG_LVGL_USING_V8_3_LATEST=y
online-packages.multimedia.lvgl-v8.3.11:
<<: *scons
kconfig:
- CONFIG_BSP_USING_LVGL=y
- CONFIG_BSP_USING_LVGL_DEMO=y
- CONFIG_PKG_LVGL_USING_V080311=y
online-packages.multimedia.lvgl-v8.4-latest:
<<: *scons
kconfig:
- CONFIG_BSP_USING_LVGL=y
- CONFIG_BSP_USING_LVGL_DEMO=y
- CONFIG_PKG_LVGL_USING_V8_4_LATEST=y
online-packages.system.enhanced-kservice:
<<: *scons
kconfig:
- CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE=y
- CONFIG_PKG_USING_RT_MEMCPY_CM=y
online-packages.system.os-wrappers:
<<: *scons
kconfig:
- CONFIG_PKG_USING_FREERTOS_WRAPPER=y
# ------ peripheral CI ------
peripheral.aht21:
kconfig:
- CONFIG_BSP_USING_AHT21=y
peripheral.ap3216c:
kconfig:
- CONFIG_BSP_USING_AP3216C=y
peripheral.ethernet_28j60:
kconfig:
- CONFIG_BSP_USING_ENC28j60=y
peripheral.fal_easyflash:
kconfig:
- CONFIG_BSP_USING_EASYFLASH=y
peripheral.filesystem:
kconfig:
- CONFIG_BSP_USING_FS=y
- CONFIG_BSP_USING_FLASH_FATFS=y
peripheral.icm20608:
kconfig:
- CONFIG_BSP_USING_ICM20608=y
peripheral.lcd_st7787:
kconfig:
- CONFIG_BSP_USING_ONBOARD_LCD=y
peripheral.led_matrix:
kconfig:
- CONFIG_BSP_USING_ONBOARD_LED_MATRIX=y
peripheral.rs485:
kconfig:
- CONFIG_BSP_USING_RS485=y
peripheral.rw007:
kconfig:
- CONFIG_BSP_USING_RW007_WLAN=y
peripheral.spi_flash_w25q64:
kconfig:
- CONFIG_BSP_USING_SPI_FLASH=y
peripheral.sram:
kconfig:
- CONFIG_BSP_USING_SRAM=y
peripheral.usb_mouse:
kconfig:
- CONFIG_BSP_USING_USB_MOUSE=y
# ------ nano CI ------
nano:
<<: *scons
kconfig:
- CONFIG_RT_USING_NANO=y

View File

@ -52,10 +52,8 @@ if GetDepend(['RT_USING_DAC']):
if GetDepend(['RT_USING_CAN']): if GetDepend(['RT_USING_CAN']):
src += ['drv_can.c'] src += ['drv_can.c']
if GetDepend(['RT_USING_PM']): if GetDepend(['RT_USING_PM', 'SOC_SERIES_STM32L4']):
src += ['drv_pm.c'] src += ['drv_pm.c']
if GetDepend(['BSP_USING_LPTIM']):
src += ['drv_lptim.c'] src += ['drv_lptim.c']
if GetDepend('BSP_USING_SDRAM'): if GetDepend('BSP_USING_SDRAM'):
@ -124,6 +122,9 @@ if GetDepend(['BSP_USING_PULSE_ENCODER']):
if GetDepend(['BSP_USING_USBH']): if GetDepend(['BSP_USING_USBH']):
src += ['drv_usbh.c'] src += ['drv_usbh.c']
if GetDepend(['BSP_USING_TEST']):
src += ['drv_test.c']
path += [os.path.join(cwd, 'config')] path += [os.path.join(cwd, 'config')]
if GetDepend('BSP_USING_ON_CHIP_FLASH'): if GetDepend('BSP_USING_ON_CHIP_FLASH'):

View File

@ -19,13 +19,6 @@ extern "C" {
#endif #endif
/* DMA1 channel1 */ /* DMA1 channel1 */
#if defined(BSP_ADC1_USING_DMA) && !defined(ADC1_DMA_INSTANCE)
#define ADC1_DMA_IRQHandler DMA1_Channel1_IRQHandler
#define ADC1_DMA_RCC RCC_AHBENR_DMA1EN
#define ADC1_DMA_INSTANCE DMA1_Channel1
#define ADC1_DMA_IRQ DMA1_Channel1_IRQn
#endif
/* DMA1 channel2 */ /* DMA1 channel2 */
#if defined(BSP_SPI1_RX_USING_DMA) && !defined(SPI1_RX_DMA_INSTANCE) #if defined(BSP_SPI1_RX_USING_DMA) && !defined(SPI1_RX_DMA_INSTANCE)
#define SPI1_DMA_RX_IRQHandler DMA1_Channel2_IRQHandler #define SPI1_DMA_RX_IRQHandler DMA1_Channel2_IRQHandler
@ -63,11 +56,6 @@ extern "C" {
#define UART1_TX_DMA_RCC RCC_AHBENR_DMA1EN #define UART1_TX_DMA_RCC RCC_AHBENR_DMA1EN
#define UART1_TX_DMA_INSTANCE DMA1_Channel4 #define UART1_TX_DMA_INSTANCE DMA1_Channel4
#define UART1_TX_DMA_IRQ DMA1_Channel4_IRQn #define UART1_TX_DMA_IRQ DMA1_Channel4_IRQn
#elif defined(BSP_I2C2_TX_USING_DMA) && !defined(I2C2_TX_DMA_INSTANCE)
#define I2C2_DMA_TX_IRQHandler DMA1_Channel4_IRQHandler
#define I2C2_TX_DMA_RCC RCC_AHBENR_DMA1EN
#define I2C2_TX_DMA_INSTANCE DMA1_Channel4
#define I2C2_TX_DMA_IRQ DMA1_Channel4_IRQn
#endif #endif
/* DMA1 channel5 */ /* DMA1 channel5 */
@ -76,16 +64,12 @@ extern "C" {
#define SPI2_TX_DMA_RCC RCC_AHBENR_DMA1EN #define SPI2_TX_DMA_RCC RCC_AHBENR_DMA1EN
#define SPI2_TX_DMA_INSTANCE DMA1_Channel5 #define SPI2_TX_DMA_INSTANCE DMA1_Channel5
#define SPI2_TX_DMA_IRQ DMA1_Channel5_IRQn #define SPI2_TX_DMA_IRQ DMA1_Channel5_IRQn
#elif defined(BSP_UART1_RX_USING_DMA) && !defined(UART1_RX_DMA_INSTANCE) #elif defined(BSP_UART1_RX_USING_DMA) && !defined(UART1_RX_DMA_INSTANCE)
#define UART1_DMA_RX_IRQHandler DMA1_Channel5_IRQHandler #define UART1_DMA_RX_IRQHandler DMA1_Channel5_IRQHandler
#define UART1_RX_DMA_RCC RCC_AHBENR_DMA1EN #define UART1_RX_DMA_RCC RCC_AHBENR_DMA1EN
#define UART1_RX_DMA_INSTANCE DMA1_Channel5 #define UART1_RX_DMA_INSTANCE DMA1_Channel5
#define UART1_RX_DMA_IRQ DMA1_Channel5_IRQn #define UART1_RX_DMA_IRQ DMA1_Channel5_IRQn
#elif defined(BSP_I2C2_RX_USING_DMA) && !defined(I2C2_RX_DMA_INSTANCE)
#define I2C2_DMA_RX_IRQHandler DMA1_Channel5_IRQHandler
#define I2C2_RX_DMA_RCC RCC_AHBENR_DMA1EN
#define I2C2_RX_DMA_INSTANCE DMA1_Channel5
#define I2C2_RX_DMA_IRQ DMA1_Channel5_IRQn
#endif #endif
/* DMA1 channel6 */ /* DMA1 channel6 */
@ -94,11 +78,6 @@ extern "C" {
#define UART2_RX_DMA_RCC RCC_AHBENR_DMA1EN #define UART2_RX_DMA_RCC RCC_AHBENR_DMA1EN
#define UART2_RX_DMA_INSTANCE DMA1_Channel6 #define UART2_RX_DMA_INSTANCE DMA1_Channel6
#define UART2_RX_DMA_IRQ DMA1_Channel6_IRQn #define UART2_RX_DMA_IRQ DMA1_Channel6_IRQn
#elif defined(BSP_I2C1_TX_USING_DMA) && !defined(I2C1_TX_DMA_INSTANCE)
#define I2C1_DMA_TX_IRQHandler DMA1_Channel6_IRQHandler
#define I2C1_TX_DMA_RCC RCC_AHBENR_DMA1EN
#define I2C1_TX_DMA_INSTANCE DMA1_Channel6
#define I2C1_TX_DMA_IRQ DMA1_Channel6_IRQn
#endif #endif
/* DMA1 channel7 */ /* DMA1 channel7 */
@ -107,11 +86,6 @@ extern "C" {
#define UART2_TX_DMA_RCC RCC_AHBENR_DMA1EN #define UART2_TX_DMA_RCC RCC_AHBENR_DMA1EN
#define UART2_TX_DMA_INSTANCE DMA1_Channel7 #define UART2_TX_DMA_INSTANCE DMA1_Channel7
#define UART2_TX_DMA_IRQ DMA1_Channel7_IRQn #define UART2_TX_DMA_IRQ DMA1_Channel7_IRQn
#elif defined(BSP_I2C1_RX_USING_DMA) && !defined(I2C1_RX_DMA_INSTANCE)
#define I2C1_DMA_RX_IRQHandler DMA1_Channel7_IRQHandler
#define I2C1_RX_DMA_RCC RCC_AHBENR_DMA1EN
#define I2C1_RX_DMA_INSTANCE DMA1_Channel7
#define I2C1_RX_DMA_IRQ DMA1_Channel7_IRQn
#endif #endif
/* DMA2 channel1 */ /* DMA2 channel1 */
@ -137,27 +111,9 @@ extern "C" {
#define UART4_RX_DMA_INSTANCE DMA2_Channel3 #define UART4_RX_DMA_INSTANCE DMA2_Channel3
#define UART4_RX_DMA_IRQ DMA2_Channel3_IRQn #define UART4_RX_DMA_IRQ DMA2_Channel3_IRQn
#endif #endif
/* DMA2 channel4 */ /* DMA2 channel4 */
#if defined(BSP_SDIO_TX_USING_DMA) && !defined(SDIO_TX_DMA_INSTANCE)
#define SDIO_DMA_TX_IRQHandler DMA2_Channel4_5_IRQHandler
#define SDIO_TX_DMA_RCC RCC_AHBENR_DMA2EN
#define SDIO_TX_DMA_INSTANCE DMA2_Channel4
#define SDIO_TX_DMA_IRQ DMA2_Channel4_5_IRQn
#elif defined(BSP_SDIO_RX_USING_DMA) && !defined(SDIO_RX_DMA_INSTANCE)
#define SDIO_DMA_RX_IRQHandler DMA2_Channel4_5_IRQHandler
#define SDIO_RX_DMA_RCC RCC_AHBENR_DMA2EN
#define SDIO_RX_DMA_INSTANCE DMA2_Channel4
#define SDIO_RX_DMA_IRQ DMA2_Channel4_5_IRQn
#endif
/* DMA2 channel5 */ /* DMA2 channel5 */
#if defined(BSP_ADC3_USING_DMA) && !defined(ADC3_DMA_INSTANCE) #if defined(BSP_UART4_TX_USING_DMA) && !defined(UART4_TX_DMA_INSTANCE)
#define ADC3_DMA_IRQHandler DMA2_Channel4_5_IRQHandler
#define ADC3_DMA_RCC RCC_AHBENR_DMA2EN
#define ADC3_DMA_INSTANCE DMA2_Channel5
#define ADC3_DMA_IRQ DMA2_Channel4_5_IRQn
#elif defined(BSP_UART4_TX_USING_DMA) && !defined(UART4_TX_DMA_INSTANCE)
#define UART4_DMA_TX_IRQHandler DMA2_Channel4_5_IRQHandler #define UART4_DMA_TX_IRQHandler DMA2_Channel4_5_IRQHandler
#define UART4_TX_DMA_RCC RCC_AHBENR_DMA2EN #define UART4_TX_DMA_RCC RCC_AHBENR_DMA2EN
#define UART4_TX_DMA_INSTANCE DMA2_Channel5 #define UART4_TX_DMA_INSTANCE DMA2_Channel5

View File

@ -1,129 +0,0 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-02-06 Dyyt587 first version
* 2024-04-23 Zeidan Add I2Cx_xx_DMA_CONFIG
*/
#ifndef __I2C_HARD_CONFIG_H__
#define __I2C_HARD_CONFIG_H__
#include <rtthread.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef BSP_USING_HARD_I2C1
#ifndef I2C1_BUS_CONFIG
#define I2C1_BUS_CONFIG \
{ \
.Instance = I2C1, \
.timeout=0x1000, \
.name = "hwi2c1", \
.evirq_type = I2C1_EV_IRQn, \
.erirq_type = I2C1_ER_IRQn, \
}
#endif /* I2C1_BUS_CONFIG */
#endif /* BSP_USING_HARD_I2C1 */
#ifdef BSP_I2C1_TX_USING_DMA
#ifndef I2C1_TX_DMA_CONFIG
#define I2C1_TX_DMA_CONFIG \
{ \
.dma_rcc = I2C1_TX_DMA_RCC, \
.Instance = I2C1_TX_DMA_INSTANCE, \
.dma_irq = I2C1_TX_DMA_IRQ, \
}
#endif /* I2C1_TX_DMA_CONFIG */
#endif /* BSP_I2C1_TX_USING_DMA */
#ifdef BSP_I2C1_RX_USING_DMA
#ifndef I2C1_RX_DMA_CONFIG
#define I2C1_RX_DMA_CONFIG \
{ \
.dma_rcc = I2C1_RX_DMA_RCC, \
.Instance = I2C1_RX_DMA_INSTANCE, \
.dma_irq = I2C1_RX_DMA_IRQ, \
}
#endif /* I2C1_RX_DMA_CONFIG */
#endif /* BSP_I2C1_RX_USING_DMA */
#ifdef BSP_USING_HARD_I2C2
#ifndef I2C2_BUS_CONFIG
#define I2C2_BUS_CONFIG \
{ \
.Instance = I2C2, \
.timeout=0x1000, \
.name = "hwi2c2", \
.evirq_type = I2C2_EV_IRQn, \
.erirq_type = I2C2_ER_IRQn, \
}
#endif /* I2C2_BUS_CONFIG */
#endif /* BSP_USING_HARD_I2C2 */
#ifdef BSP_I2C2_TX_USING_DMA
#ifndef I2C2_TX_DMA_CONFIG
#define I2C2_TX_DMA_CONFIG \
{ \
.dma_rcc = I2C2_TX_DMA_RCC, \
.Instance = I2C2_TX_DMA_INSTANCE, \
.dma_irq = I2C2_TX_DMA_IRQ, \
}
#endif /* I2C2_TX_DMA_CONFIG */
#endif /* BSP_I2C2_TX_USING_DMA */
#ifdef BSP_I2C2_RX_USING_DMA
#ifndef I2C2_RX_DMA_CONFIG
#define I2C2_RX_DMA_CONFIG \
{ \
.dma_rcc = I2C2_RX_DMA_RCC, \
.Instance = I2C2_RX_DMA_INSTANCE, \
.dma_irq = I2C2_RX_DMA_IRQ, \
}
#endif /* I2C2_RX_DMA_CONFIG */
#endif /* BSP_I2C2_RX_USING_DMA */
#ifdef BSP_USING_HARD_I2C3
#ifndef I2C3_BUS_CONFIG
#define I2C3_BUS_CONFIG \
{ \
.Instance = I2C3, \
.timeout=0x1000, \
.name = "hwi2c3", \
.evirq_type = I2C3_EV_IRQn, \
.erirq_type = I2C3_ER_IRQn, \
}
#endif /* I2C3_BUS_CONFIG */
#endif /* BSP_USING_HARD_I2C3 */
#ifdef BSP_I2C3_TX_USING_DMA
#ifndef I2C3_TX_DMA_CONFIG
#define I2C3_TX_DMA_CONFIG \
{ \
.dma_rcc = I2C3_TX_DMA_RCC, \
.Instance = I2C3_TX_DMA_INSTANCE, \
.dma_irq = I2C3_TX_DMA_IRQ, \
}
#endif /* I2C3_TX_DMA_CONFIG */
#endif /* BSP_I2C3_TX_USING_DMA */
#ifdef BSP_I2C3_RX_USING_DMA
#ifndef I2C3_RX_DMA_CONFIG
#define I2C3_RX_DMA_CONFIG \
{ \
.dma_rcc = I2C3_RX_DMA_RCC, \
.Instance = I2C3_RX_DMA_INSTANCE, \
.dma_irq = I2C3_RX_DMA_IRQ, \
}
#endif /* I2C3_RX_DMA_CONFIG */
#endif /* BSP_I2C3_RX_USING_DMA */
#ifdef __cplusplus
}
#endif
#endif /*__I2C_HARD_CONFIG_H__ */

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-07-11 wdfk-prog first version
*/
#ifndef __LPTIM_CONFIG_H__
#define __LPTIM_CONFIG_H__
#include <rtthread.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef LPTIM_DEV_INFO_CONFIG
#define LPTIM_DEV_INFO_CONFIG \
{ \
.maxfreq = 1000000, \
.minfreq = 3000, \
.maxcnt = 0xFFFF, \
.cntmode = HWTIMER_CNTMODE_UP, \
}
#endif /* TIM_DEV_INFO_CONFIG */
#ifdef BSP_USING_LPTIM1
#ifndef LPTIM1_CONFIG
#define LPTIM1_CONFIG \
{ \
.tim_handle.Instance = LPTIM1, \
.tim_irqn = LPTIM1_IRQn, \
.name = "lptim1", \
}
#endif /* LPTIM1_CONFIG */
#endif /* BSP_USING_LPTIM1 */
#ifdef BSP_USING_LPTIM2
#ifndef LPTIM2_CONFIG
#define LPTIM2_CONFIG \
{ \
.tim_handle.Instance = LPTIM2, \
.tim_irqn = LPTIM2_IRQn, \
.name = "lptim2", \
}
#endif /* LPTIM1_CONFIG */
#endif /* BSP_USING_LPTIM1 */
#ifdef BSP_USING_LPTIM3
#ifndef LPTIM3_CONFIG
#define LPTIM3_CONFIG \
{ \
.tim_handle.Instance = LPTIM3, \
.tim_irqn = LPTIM3_IRQn, \
.name = "lptim3", \
}
#endif /* LPTIM3_CONFIG */
#endif /* BSP_USING_LPTIM3 */
#ifdef __cplusplus
}
#endif
#endif /* __LPTIM_CONFIG_H__ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2024 RT-Thread Development Team * Copyright (c) 2006-2023, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
@ -174,6 +174,8 @@ static rt_err_t _can_config(struct rt_can_device *can, struct can_configure *cfg
/* default filter config */ /* default filter config */
HAL_CAN_ConfigFilter(&drv_can->CanHandle, &drv_can->FilterConfig); HAL_CAN_ConfigFilter(&drv_can->CanHandle, &drv_can->FilterConfig);
/* can start */
HAL_CAN_Start(&drv_can->CanHandle);
return RT_EOK; return RT_EOK;
} }
@ -319,7 +321,7 @@ static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg)
rt_uint32_t id_l = 0; rt_uint32_t id_l = 0;
rt_uint32_t mask_h = 0; rt_uint32_t mask_h = 0;
rt_uint32_t mask_l = 0; rt_uint32_t mask_l = 0;
rt_uint32_t mask_l_tail = 0; /*CAN_FxR2 bit [2:0]*/ rt_uint32_t mask_l_tail = 0; //CAN_FxR2 bit [2:0]
if (RT_NULL == arg) if (RT_NULL == arg)
{ {
@ -465,19 +467,7 @@ static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg)
drv_can->device.status.errcode = errtype & 0x07; drv_can->device.status.errcode = errtype & 0x07;
rt_memcpy(arg, &drv_can->device.status, sizeof(drv_can->device.status)); rt_memcpy(arg, &drv_can->device.status, sizeof(drv_can->device.status));
break;
} }
case RT_CAN_CMD_START:
argval = (rt_uint32_t) arg;
if (argval == 0)
{
HAL_CAN_Stop(&drv_can->CanHandle);
}
else
{
HAL_CAN_Start(&drv_can->CanHandle);
}
break; break;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2024 RT-Thread Development Team * Copyright (c) 2006-2023, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
@ -35,7 +35,6 @@ extern "C" {
#include "f1/sdio_config.h" #include "f1/sdio_config.h"
#include "f1/pwm_config.h" #include "f1/pwm_config.h"
#include "f1/usbd_config.h" #include "f1/usbd_config.h"
#include "f1/i2c_hard_config.h"
#include "f1/pulse_encoder_config.h" #include "f1/pulse_encoder_config.h"
#elif defined(SOC_SERIES_STM32F2) #elif defined(SOC_SERIES_STM32F2)
#include "f2/dma_config.h" #include "f2/dma_config.h"
@ -123,7 +122,6 @@ extern "C" {
#include "h7/adc_config.h" #include "h7/adc_config.h"
#include "h7/dac_config.h" #include "h7/dac_config.h"
#include "h7/tim_config.h" #include "h7/tim_config.h"
#include "h7/lptim_config.h"
#include "h7/sdio_config.h" #include "h7/sdio_config.h"
#include "h7/pwm_config.h" #include "h7/pwm_config.h"
#include "h7/usbd_config.h" #include "h7/usbd_config.h"

View File

@ -394,6 +394,7 @@ static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin,
const struct pin_irq_map *irqmap; const struct pin_irq_map *irqmap;
rt_base_t level; rt_base_t level;
rt_int32_t irqindex = -1; rt_int32_t irqindex = -1;
GPIO_InitTypeDef GPIO_InitStruct;
if (PIN_PORT(pin) >= PIN_STPORT_MAX) if (PIN_PORT(pin) >= PIN_STPORT_MAX)
{ {
@ -402,8 +403,6 @@ static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin,
if (enabled == PIN_IRQ_ENABLE) if (enabled == PIN_IRQ_ENABLE)
{ {
GPIO_InitTypeDef GPIO_InitStruct = {0};
irqindex = bit2bitno(PIN_STPIN(pin)); irqindex = bit2bitno(PIN_STPIN(pin));
if (irqindex < 0 || irqindex >= (rt_int32_t)ITEM_NUM(pin_irq_map)) if (irqindex < 0 || irqindex >= (rt_int32_t)ITEM_NUM(pin_irq_map))
{ {

View File

@ -7,10 +7,14 @@
* Date Author Notes * Date Author Notes
* 2024-02-17 Dyyt587 first version * 2024-02-17 Dyyt587 first version
* 2024-04-23 Zeidan fix bugs, test on STM32F429IGTx * 2024-04-23 Zeidan fix bugs, test on STM32F429IGTx
* 2024-12-10 zzk597 add support for STM32F1 series
*/ */
#include <rtthread.h>
#include <rthw.h>
#include <board.h>
#include "drv_hard_i2c.h" #include "drv_hard_i2c.h"
#include "drv_config.h"
#include <string.h>
/* not fully support for I2C4 */ /* not fully support for I2C4 */
#if defined(BSP_USING_HARD_I2C1) || defined(BSP_USING_HARD_I2C2) || defined(BSP_USING_HARD_I2C3) #if defined(BSP_USING_HARD_I2C1) || defined(BSP_USING_HARD_I2C2) || defined(BSP_USING_HARD_I2C3)
@ -47,27 +51,28 @@ static struct stm32_i2c_config i2c_config[] =
static struct stm32_i2c i2c_objs[sizeof(i2c_config) / sizeof(i2c_config[0])] = {0}; static struct stm32_i2c i2c_objs[sizeof(i2c_config) / sizeof(i2c_config[0])] = {0};
static rt_err_t stm32_i2c_init(struct stm32_i2c *i2c_drv) static rt_err_t stm32_i2c_init(struct stm32_i2c *i2c_drv)
{ {
RT_ASSERT(i2c_drv != RT_NULL); RT_ASSERT(i2c_drv != RT_NULL);
I2C_HandleTypeDef *i2c_handle = &i2c_drv->handle; I2C_HandleTypeDef *i2c_handle = &i2c_drv->handle;
struct stm32_i2c_config *cfg = i2c_drv->config;
rt_memset(i2c_handle, 0, sizeof(I2C_HandleTypeDef)); rt_memset(i2c_handle, 0, sizeof(I2C_HandleTypeDef));
struct stm32_i2c_config *cfg = i2c_drv->config;
i2c_handle->Instance = cfg->Instance; i2c_handle->Instance = cfg->Instance;
#if defined(SOC_SERIES_STM32H7) #if defined(SOC_SERIES_STM32H7)
i2c_handle->Init.Timing = cfg->timing; i2c_handle->Init.Timing = cfg->timing;
#endif /* defined(SOC_SERIES_STM32H7) */ #endif /* defined(SOC_SERIES_STM32H7) */
#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F4) #if defined(SOC_SERIES_STM32F4)
i2c_handle->Init.ClockSpeed = 100000; i2c_handle->Init.ClockSpeed = 100000;
i2c_handle->Init.DutyCycle = I2C_DUTYCYCLE_2; i2c_handle->Init.DutyCycle = I2C_DUTYCYCLE_2;
#endif /* defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F4) */ #endif /* defined(SOC_SERIES_STM32F4) */
i2c_handle->Init.OwnAddress1 = 0; i2c_handle->Init.OwnAddress1 = 0;
i2c_handle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; i2c_handle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
#if defined(SOC_SERIES_STM32H7)
i2c_handle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
#endif /* defined(SOC_SERIES_STM32H7) */
i2c_handle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; i2c_handle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
i2c_handle->Init.OwnAddress2 = 0;
i2c_handle->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; i2c_handle->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
i2c_handle->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; i2c_handle->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_DeInit(i2c_handle) != HAL_OK) if (HAL_I2C_DeInit(i2c_handle) != HAL_OK)
@ -115,12 +120,11 @@ static rt_err_t stm32_i2c_init(struct stm32_i2c *i2c_drv)
HAL_NVIC_EnableIRQ(i2c_drv->config->dma_tx->dma_irq); HAL_NVIC_EnableIRQ(i2c_drv->config->dma_tx->dma_irq);
} }
/* In the data transfer function stm32_i2c_master_xfer(), the IT transfer function if (i2c_drv->i2c_dma_flag & I2C_USING_TX_DMA_FLAG || i2c_drv->i2c_dma_flag & I2C_USING_RX_DMA_FLAG)
HAL_I2C_Master_Seq_Transmit_IT() is used when DMA is not used, so the IT interrupt {
must be enable anyway, regardless of the DMA configuration, otherwise
the rt_completion_wait() will always timeout. */
HAL_NVIC_SetPriority(i2c_drv->config->evirq_type, 2, 0); HAL_NVIC_SetPriority(i2c_drv->config->evirq_type, 2, 0);
HAL_NVIC_EnableIRQ(i2c_drv->config->evirq_type); HAL_NVIC_EnableIRQ(i2c_drv->config->evirq_type);
}
return RT_EOK; return RT_EOK;
} }
@ -156,14 +160,11 @@ static rt_ssize_t stm32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
uint8_t next_flag = 0; uint8_t next_flag = 0;
struct rt_completion *completion; struct rt_completion *completion;
rt_uint32_t timeout; rt_uint32_t timeout;
if (num == 0) if (num == 0)
{ {
return 0; return 0;
} }
RT_ASSERT((msgs != RT_NULL) && (bus != RT_NULL)); RT_ASSERT((msgs != RT_NULL) && (bus != RT_NULL));
i2c_obj = rt_container_of(bus, struct stm32_i2c, i2c_bus); i2c_obj = rt_container_of(bus, struct stm32_i2c, i2c_bus);
completion = &i2c_obj->completion; completion = &i2c_obj->completion;
I2C_HandleTypeDef *handle = &i2c_obj->handle; I2C_HandleTypeDef *handle = &i2c_obj->handle;
@ -344,48 +345,6 @@ int RT_hw_i2c_bus_init(void)
i2c_objs[i].config = &i2c_config[i]; i2c_objs[i].config = &i2c_config[i];
i2c_objs[i].i2c_bus.timeout = i2c_config[i].timeout; i2c_objs[i].i2c_bus.timeout = i2c_config[i].timeout;
if ((i2c_objs[i].i2c_dma_flag & I2C_USING_RX_DMA_FLAG))
{
i2c_objs[i].dma.handle_rx.Instance = i2c_config[i].dma_rx->Instance;
#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7)
i2c_objs[i].dma.handle_rx.Init.Channel = i2c_config[i].dma_rx->channel;
#elif defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32WB) || defined(SOC_SERIES_STM32H7)
i2c_objs[i].dma.handle_rx.Init.Request = i2c_config[i].dma_rx->request;
#endif /* defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) */
#ifndef SOC_SERIES_STM32U5
i2c_objs[i].dma.handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
i2c_objs[i].dma.handle_rx.Init.PeriphInc = DMA_PINC_DISABLE;
i2c_objs[i].dma.handle_rx.Init.MemInc = DMA_MINC_ENABLE;
i2c_objs[i].dma.handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
i2c_objs[i].dma.handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
i2c_objs[i].dma.handle_rx.Init.Mode = DMA_NORMAL;
i2c_objs[i].dma.handle_rx.Init.Priority = DMA_PRIORITY_LOW;
#endif
#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7)
i2c_objs[i].dma.handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
i2c_objs[i].dma.handle_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
i2c_objs[i].dma.handle_tx.Init.MemBurst = DMA_MBURST_INC4;
i2c_objs[i].dma.handle_tx.Init.PeriphBurst = DMA_PBURST_INC4;
#endif /* defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7) */
{
rt_uint32_t tmpreg = 0x00U;
#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32F0)
/* enable DMA clock && Delay after an RCC peripheral clock enabling*/
SET_BIT(RCC->AHBENR, i2c_config[i].dma_rx->dma_rcc);
tmpreg = READ_BIT(RCC->AHBENR, i2c_config[i].dma_rx->dma_rcc);
#elif defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32WB) || defined(SOC_SERIES_STM32H7)
SET_BIT(RCC->AHB1ENR, i2c_config[i].dma_rx->dma_rcc);
/* Delay after an RCC peripheral clock enabling */
tmpreg = READ_BIT(RCC->AHB1ENR, i2c_config[i].dma_rx->dma_rcc);
#elif defined(SOC_SERIES_STM32MP1)
__HAL_RCC_DMAMUX_CLK_ENABLE();
SET_BIT(RCC->MP_AHB2ENSETR, i2c_config[i].dma_rx->dma_rcc);
tmpreg = READ_BIT(RCC->MP_AHB2ENSETR, i2c_config[i].dma_rx->dma_rcc);
#endif /* defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32F0) */
UNUSED(tmpreg); /* To avoid compiler warnings */
}
}
if (i2c_objs[i].i2c_dma_flag & I2C_USING_TX_DMA_FLAG) if (i2c_objs[i].i2c_dma_flag & I2C_USING_TX_DMA_FLAG)
{ {
i2c_objs[i].dma.handle_tx.Instance = i2c_config[i].dma_tx->Instance; i2c_objs[i].dma.handle_tx.Instance = i2c_config[i].dma_tx->Instance;
@ -409,6 +368,32 @@ int RT_hw_i2c_bus_init(void)
i2c_objs[i].dma.handle_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; i2c_objs[i].dma.handle_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
i2c_objs[i].dma.handle_tx.Init.MemBurst = DMA_MBURST_INC4; i2c_objs[i].dma.handle_tx.Init.MemBurst = DMA_MBURST_INC4;
i2c_objs[i].dma.handle_tx.Init.PeriphBurst = DMA_PBURST_INC4; i2c_objs[i].dma.handle_tx.Init.PeriphBurst = DMA_PBURST_INC4;
#endif /* defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7) */
}
if ((i2c_objs[i].i2c_dma_flag & I2C_USING_RX_DMA_FLAG))
{
i2c_objs[i].dma.handle_rx.Instance = i2c_config[i].dma_rx->Instance;
#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7)
i2c_objs[i].dma.handle_rx.Init.Channel = i2c_config[i].dma_rx->channel;
#elif defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32WB) || defined(SOC_SERIES_STM32H7)
i2c_objs[i].dma.handle_rx.Init.Request = i2c_config[i].dma_rx->request;
#endif /* defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) */
#ifndef SOC_SERIES_STM32U5
i2c_objs[i].dma.handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
i2c_objs[i].dma.handle_rx.Init.PeriphInc = DMA_PINC_DISABLE;
i2c_objs[i].dma.handle_rx.Init.MemInc = DMA_MINC_ENABLE;
i2c_objs[i].dma.handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
i2c_objs[i].dma.handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
i2c_objs[i].dma.handle_rx.Init.Mode = DMA_NORMAL;
i2c_objs[i].dma.handle_rx.Init.Priority = DMA_PRIORITY_LOW;
#endif /* SOC_SERIES_STM32U5 */
#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7)
i2c_objs[i].dma.handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
i2c_objs[i].dma.handle_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
i2c_objs[i].dma.handle_tx.Init.MemBurst = DMA_MBURST_INC4;
i2c_objs[i].dma.handle_tx.Init.PeriphBurst = DMA_PBURST_INC4;
}
#endif /* defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7) */ #endif /* defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7) */
{ {
rt_uint32_t tmpreg = 0x00U; rt_uint32_t tmpreg = 0x00U;
@ -427,8 +412,6 @@ int RT_hw_i2c_bus_init(void)
#endif /* defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32F0) */ #endif /* defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32F0) */
UNUSED(tmpreg); /* To avoid compiler warnings */ UNUSED(tmpreg); /* To avoid compiler warnings */
} }
}
rt_completion_init(&i2c_objs[i].completion); rt_completion_init(&i2c_objs[i].completion);
stm32_i2c_configure(&i2c_objs[i].i2c_bus); stm32_i2c_configure(&i2c_objs[i].i2c_bus);
ret = rt_i2c_bus_device_register(&i2c_objs[i].i2c_bus, i2c_objs[i].config->name); ret = rt_i2c_bus_device_register(&i2c_objs[i].i2c_bus, i2c_objs[i].config->name);
@ -711,11 +694,47 @@ void I2C3_DMA_TX_IRQHandler(void)
} }
#endif /* defined(BSP_USING_HARD_I2C3) && defined(BSP_I2C3_TX_USING_DMA) */ #endif /* defined(BSP_USING_HARD_I2C3) && defined(BSP_I2C3_TX_USING_DMA) */
#if defined(BSP_USING_I2C4) && defined(BSP_I2C4_RX_USING_DMA)
/**
* @brief This function handles DMA Rx interrupt request.
* @param None
* @retval None
*/
void I2C4_DMA_RX_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
HAL_DMA_IRQHandler(&i2c_objs[I2C4_INDEX].dma.handle_rx);
/* leave interrupt */
rt_interrupt_leave();
}
#endif /* defined(BSP_USING_I2C4) && defined(BSP_I2C4_RX_USING_DMA) */
#if defined(BSP_USING_I2C4) && defined(BSP_I2C4_TX_USING_DMA)
/**
* @brief This function handles DMA Rx interrupt request.
* @param None
* @retval None
*/
void I2C4_DMA_TX_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
HAL_DMA_IRQHandler(&i2c_objs[I2C4_INDEX].dma.handle_tx);
/* leave interrupt */
rt_interrupt_leave();
}
#endif /* defined(BSP_USING_I2C4) && defined(BSP_I2C4_TX_USING_DMA) */
int rt_hw_hw_i2c_init(void) int rt_hw_hw_i2c_init(void)
{ {
stm32_get_dma_info(); stm32_get_dma_info();
return RT_hw_i2c_bus_init(); return RT_hw_i2c_bus_init();
} }
INIT_BOARD_EXPORT(rt_hw_hw_i2c_init); INIT_CORE_EXPORT(rt_hw_hw_i2c_init);
#endif /* defined(BSP_USING_HARD_I2C1) || defined(BSP_USING_HARD_I2C2) || defined(BSP_USING_HARD_I2C3) */ #endif /* defined(BSP_USING_HARD_I2C1) || defined(BSP_USING_HARD_I2C2) || defined(BSP_USING_HARD_I2C3) */

View File

@ -11,10 +11,14 @@
#ifndef __DRV_HARD_I2C_H__ #ifndef __DRV_HARD_I2C_H__
#define __DRV_HARD_I2C_H__ #define __DRV_HARD_I2C_H__
#include "drv_config.h"
#include <rtthread.h>
#include "rtdevice.h"
#include <rthw.h>
#include <drv_common.h> #include <drv_common.h>
#include "drv_dma.h" #include "drv_dma.h"
#include "drv_config.h"
#include <ipc/completion.h> #include <ipc/completion.h>
#if defined(RT_USING_I2C) && defined(BSP_USING_I2C)
/* C binding of definitions if building with C++ compiler */ /* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus #ifdef __cplusplus
@ -30,22 +34,23 @@ struct stm32_i2c_config
rt_uint32_t timeout; rt_uint32_t timeout;
IRQn_Type evirq_type; IRQn_Type evirq_type;
IRQn_Type erirq_type; IRQn_Type erirq_type;
struct dma_config *dma_rx;
struct dma_config *dma_tx; struct dma_config *dma_rx, *dma_tx;
}; };
struct stm32_i2c struct stm32_i2c
{ {
I2C_HandleTypeDef handle; I2C_HandleTypeDef handle;
struct stm32_i2c_config *config;
struct struct
{ {
DMA_HandleTypeDef handle_rx; DMA_HandleTypeDef handle_rx;
DMA_HandleTypeDef handle_tx; DMA_HandleTypeDef handle_tx;
} dma; } dma;
rt_uint8_t i2c_dma_flag; struct stm32_i2c_config *config;
struct rt_i2c_bus_device i2c_bus; struct rt_i2c_bus_device i2c_bus;
rt_uint8_t i2c_dma_flag;
struct rt_completion completion; struct rt_completion completion;
}; };
#define I2C_USING_TX_DMA_FLAG (1U) #define I2C_USING_TX_DMA_FLAG (1U)
@ -55,4 +60,6 @@ struct stm32_i2c
} }
#endif #endif
#endif /* BSP_USING_I2C */
#endif /* __DRV_I2C_H__ */ #endif /* __DRV_I2C_H__ */

View File

@ -1,87 +1,92 @@
/* /*
* Copyright (c) 2006-2024 RT-Thread Development Team * Copyright (c) 2006-2023, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2019-05-06 Zero-Free first version * 2019-05-06 Zero-Free first version
* 2024-07-04 wdfk-prog lptimer is register with hwtimer, only supports pm calls,the timer function is not supported
*/ */
#include <board.h> #include <board.h>
#include <drv_lptim.h> #include <drv_lptim.h>
#include <rtdevice.h>
#include "drv_config.h"
/*#define DRV_DEBUG*/ static LPTIM_HandleTypeDef LptimHandle;
#define LOG_TAG "drv.lptim"
#include <drv_log.h>
#ifdef BSP_USING_LPTIM void LPTIM1_IRQHandler(void)
#define LPTIM_REG_MAX_VALUE (0xFFFF)
enum
{ {
#ifdef BSP_USING_LPTIM1 HAL_LPTIM_IRQHandler(&LptimHandle);
LPTIM1_INDEX,
#endif
#ifdef BSP_USING_LPTIM2
LPTIM2_INDEX,
#endif
#ifdef BSP_USING_LPTIM3
LPTIM3_INDEX,
#endif
};
struct stm32_hw_lptimer
{
rt_hwtimer_t time_device;
LPTIM_HandleTypeDef tim_handle;
IRQn_Type tim_irqn;
char *name;
};
static struct stm32_hw_lptimer stm32_hw_lptimer_obj[] =
{
#ifdef BSP_USING_LPTIM1
LPTIM1_CONFIG,
#endif
#ifdef BSP_USING_LPTIM2
LPTIM2_CONFIG,
#endif
#ifdef BSP_USING_LPTIM3
LPTIM3_CONFIG,
#endif
};
static const struct rt_hwtimer_info _info = LPTIM_DEV_INFO_CONFIG;
static void timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
{
if(timer == RT_NULL)
{
LOG_E("init timer is NULL");
return;
} }
if (state) void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim)
{ {
struct stm32_hw_lptimer *tim_device = rt_container_of(timer, struct stm32_hw_lptimer, time_device); /* enter interrupt */
LPTIM_HandleTypeDef *tim = (LPTIM_HandleTypeDef *)timer->parent.user_data; rt_interrupt_enter();
if(tim_device == RT_NULL) /* leave interrupt */
{ rt_interrupt_leave();
LOG_E("start tim_device is NULL");
return;
}
if(tim == RT_NULL)
{
LOG_E("start %s LPTIM_Handle is NULL", tim_device->name);
return;
} }
/**
* This function get current count value of LPTIM
*
* @return the count vlaue
*/
rt_uint32_t stm32l4_lptim_get_current_tick(void)
{
return HAL_LPTIM_ReadCounter(&LptimHandle);
}
/**
* This function get the max value that LPTIM can count
*
* @return the max count
*/
rt_uint32_t stm32l4_lptim_get_tick_max(void)
{
return (0xFFFF);
}
/**
* This function start LPTIM with reload value
*
* @param reload The value that LPTIM count down from
*
* @return RT_EOK
*/
rt_err_t stm32l4_lptim_start(rt_uint32_t reload)
{
HAL_LPTIM_TimeOut_Start_IT(&LptimHandle, 0xFFFF, reload);
return (RT_EOK);
}
/**
* This function stop LPTIM
*/
void stm32l4_lptim_stop(void)
{
rt_uint32_t _ier;
_ier = LptimHandle.Instance->IER;
LptimHandle.Instance->ICR = LptimHandle.Instance->ISR & _ier;
}
/**
* This function get the count clock of LPTIM
*
* @return the count clock frequency in Hz
*/
rt_uint32_t stm32l4_lptim_get_countfreq(void)
{
return 32000 / 32;
}
/**
* This function initialize the lptim
*/
int stm32l4_hw_lptim_init(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0}; RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0};
@ -96,225 +101,23 @@ static void timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
RCC_PeriphCLKInitStruct.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSI; RCC_PeriphCLKInitStruct.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSI;
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct); HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct);
tim->Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC; LptimHandle.Instance = LPTIM1;
tim->Init.Clock.Prescaler = LPTIM_PRESCALER_DIV32; LptimHandle.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;
tim->Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE; LptimHandle.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV32;
tim->Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH; LptimHandle.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE;
tim->Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE; LptimHandle.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH;
tim->Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL; LptimHandle.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE;
LptimHandle.Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL;
HAL_StatusTypeDef ret = HAL_LPTIM_Init(tim); if (HAL_LPTIM_Init(&LptimHandle) != HAL_OK)
if (ret != HAL_OK)
{ {
LOG_E("%s init failed %d", tim_device->name, ret); return -1;
} }
else
{
NVIC_ClearPendingIRQ(LPTIM1_IRQn); NVIC_ClearPendingIRQ(LPTIM1_IRQn);
NVIC_SetPriority(LPTIM1_IRQn, 0); NVIC_SetPriority(LPTIM1_IRQn, 0);
NVIC_EnableIRQ(LPTIM1_IRQn); NVIC_EnableIRQ(LPTIM1_IRQn);
LOG_D("%s init success", tim_device->name);
} return 0;
}
} }
static rt_err_t timer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_t opmode) INIT_DEVICE_EXPORT(stm32l4_hw_lptim_init);
{
if(timer == RT_NULL)
{
LOG_E("start timer is NULL");
return -RT_EINVAL;
}
struct stm32_hw_lptimer *tim_device = rt_container_of(timer, struct stm32_hw_lptimer, time_device);
LPTIM_HandleTypeDef *tim = (LPTIM_HandleTypeDef *)timer->parent.user_data;
if(tim_device == RT_NULL)
{
LOG_E("start tim_device is NULL");
return -RT_EINVAL;
}
if(tim == RT_NULL)
{
LOG_E("start %s LPTIM_Handle is NULL", tim_device->name);
return -RT_EINVAL;
}
HAL_StatusTypeDef ret = HAL_LPTIM_TimeOut_Start_IT(tim, LPTIM_REG_MAX_VALUE, t);
if(ret != HAL_OK)
{
LOG_E("start %s failed %d", tim_device->name, ret);
return -RT_ERROR;
}
else
{
LOG_D("start %s success", tim_device->name);
return RT_EOK;
}
}
static void timer_stop(rt_hwtimer_t *timer)
{
if(timer == RT_NULL)
{
LOG_E("stop timer is NULL");
return;
}
struct stm32_hw_lptimer *tim_device = rt_container_of(timer, struct stm32_hw_lptimer, time_device);
LPTIM_HandleTypeDef *tim = (LPTIM_HandleTypeDef *)timer->parent.user_data;
if(tim_device == RT_NULL)
{
LOG_E("stop tim_device is NULL");
return;
}
if(tim == RT_NULL)
{
LOG_E("stop %s LPTIM_Handle is NULL", tim_device->name);
return;
}
HAL_StatusTypeDef ret = HAL_LPTIM_TimeOut_Stop_IT(tim);
if(ret != HAL_OK)
{
LOG_E("stop %s failed %d", tim_device->name, ret);
}
else
{
LOG_D("stop %s success", tim_device->name);
}
}
static rt_uint32_t timer_get_freq(LPTIM_HandleTypeDef *tim)
{
/*No calculation is performed. The default initial configuration is 1000hz*/
return 1000;
}
static rt_uint32_t timer_counter_get(rt_hwtimer_t *timer)
{
LPTIM_HandleTypeDef *tim = (LPTIM_HandleTypeDef *)timer->parent.user_data;
return HAL_LPTIM_ReadCounter(tim);
}
static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
{
if(timer == RT_NULL)
{
LOG_E("start timer is NULL");
return -RT_EINVAL;
}
struct stm32_hw_lptimer *tim_device = rt_container_of(timer, struct stm32_hw_lptimer, time_device);
LPTIM_HandleTypeDef *tim = (LPTIM_HandleTypeDef *)timer->parent.user_data;
if(tim_device == RT_NULL)
{
LOG_E("start tim_device is NULL");
return -RT_EINVAL;
}
if(tim == RT_NULL)
{
LOG_E("start %s LPTIM_Handle is NULL", tim_device->name);
return -RT_EINVAL;
}
rt_err_t result = RT_EOK;
switch (cmd)
{
case DRV_HW_LPTIMER_CTRL_GET_TICK_MAX:
{
*(rt_uint32_t *)arg = LPTIM_REG_MAX_VALUE;
break;
}
case DRV_HW_LPTIMER_CTRL_GET_FREQ:
{
*(rt_uint32_t *)arg = timer_get_freq(tim);
break;
}
case DRV_HW_LPTIMER_CTRL_START:
{
timer_start(timer, *(rt_uint32_t *)arg, HWTIMER_MODE_ONESHOT);
break;
}
case DRV_HW_LPTIMER_CTRL_GET_COUNT:
{
*(rt_uint32_t *)arg = timer_counter_get(timer);
break;
}
default:
{
result = -RT_ENOSYS;
}
break;
}
return result;
}
#ifdef BSP_USING_LPTIM1
void LPTIM1_IRQHandler(void)
{
rt_interrupt_enter();
HAL_LPTIM_IRQHandler(&stm32_hw_lptimer_obj[LPTIM1_INDEX].tim_handle);
rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_LPTIM2
void LPTIM2_IRQHandler(void)
{
rt_interrupt_enter();
HAL_LPTIM_IRQHandler(&stm32_hw_lptimer_obj[LPTIM2_INDEX].tim_handle);
rt_interrupt_leave();
}
#endif
#ifdef BSP_USING_LPTIM3
void LPTIM3_IRQHandler(void)
{
rt_interrupt_enter();
HAL_LPTIM_IRQHandler(&stm32_hw_lptimer_obj[LPTIM3_INDEX].tim_handle);
rt_interrupt_leave();
}
#endif
static const struct rt_hwtimer_ops _ops =
{
.init = timer_init,
.start = timer_start,
.stop = timer_stop,
.count_get = timer_counter_get,
.control = timer_ctrl,
};
/**
* This function initialize the lptim
*/
static int stm32_hw_lptim_init(void)
{
int i = 0;
int result = RT_EOK;
for (i = 0; i < sizeof(stm32_hw_lptimer_obj) / sizeof(stm32_hw_lptimer_obj[0]); i++)
{
stm32_hw_lptimer_obj[i].time_device.info = &_info;
stm32_hw_lptimer_obj[i].time_device.ops = &_ops;
if (rt_device_hwtimer_register(&stm32_hw_lptimer_obj[i].time_device, stm32_hw_lptimer_obj[i].name, &stm32_hw_lptimer_obj[i].tim_handle) == RT_EOK)
{
LOG_D("%s register success", stm32_hw_lptimer_obj[i].name);
}
else
{
LOG_E("%s register failed", stm32_hw_lptimer_obj[i].name);
result = -RT_ERROR;
}
}
return result;
}
INIT_BOARD_EXPORT(stm32_hw_lptim_init);
#endif /* BSP_USING_LPTIM */

View File

@ -1,12 +1,11 @@
/* /*
* Copyright (c) 2006-2024 RT-Thread Development Team * Copyright (c) 2006-2023, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2019-05-06 Zero-Free first version * 2019-05-06 Zero-Free first version
* 2024-07-04 wdfk-prog lptimer is register with hwtimer, only supports pm calls,the timer function is not supported
*/ */
#ifndef __DRV_PMTIMER_H__ #ifndef __DRV_PMTIMER_H__
@ -14,13 +13,11 @@
#include <rtthread.h> #include <rtthread.h>
/* 0x20 - 0x3F udevice control commands*/ rt_uint32_t stm32l4_lptim_get_countfreq(void);
typedef enum rt_uint32_t stm32l4_lptim_get_tick_max(void);
{ rt_uint32_t stm32l4_lptim_get_current_tick(void);
DRV_HW_LPTIMER_CTRL_GET_TICK_MAX = 0x20, /* get the maximum tick value*/
DRV_HW_LPTIMER_CTRL_GET_FREQ = 0X21, /* get the timer frequency*/ rt_err_t stm32l4_lptim_start(rt_uint32_t load);
DRV_HW_LPTIMER_CTRL_START = 0X22, /* set the timeout value*/ void stm32l4_lptim_stop(void);
DRV_HW_LPTIMER_CTRL_GET_COUNT = 0X23, /* get the current count value*/
} drv_hw_lptimer_ctrl_t;
#endif /* __DRV_PMTIMER_H__ */ #endif /* __DRV_PMTIMER_H__ */

View File

@ -1,50 +1,22 @@
/* /*
* Copyright (c) 2006-2024 RT-Thread Development Team * Copyright (c) 2006-2023, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2019-05-06 Zero-Free first version * 2019-05-06 Zero-Free first version
* 2024-07-04 wdfk-prog lptimer is supported
*/ */
#include <board.h> #include <board.h>
#include <drv_lptim.h> #include <drv_lptim.h>
#include <rtdevice.h> #include <rtdevice.h>
/*#define DRV_DEBUG*/ static void uart_console_reconfig(void)
#define LOG_TAG "drv.pm"
#include <drv_log.h>
#ifdef RT_USING_PM
#ifndef BSP_USING_PM_TIMER
/*
! Using LPTIM timer, the maximum sleep time is 65535, less than 1 min. Use RTC alarm timers for longer periods.
! For example: packages can be used :https://packages.rt-thread.org/detail.html?package=multi_rtimer
*/
#ifdef BSP_USING_LPTIM1
#define BSP_USING_PM_TIMER "lptim1"
#elif BSP_USING_LPTIM2
#define BSP_USING_PM_TIMER "lptim2"
#elif BSP_USING_LPTIM3
#define BSP_USING_PM_TIMER "lptim3"
#else
#error "Please define BSP_USING_PM_TIMER"
#endif
static rt_device_t timer = RT_NULL;
/* Re-configure the system clock */
rt_weak void SystemClock_ReConfig(uint8_t run_mode)
{ {
/*todo add your code here*/ struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
}
rt_weak void stm32_pm_device_run(struct rt_pm *pm, uint8_t mode) rt_device_control(rt_console_get_device(), RT_DEVICE_CTRL_CONFIG, &config);
{
/*todo add your code here*/
} }
/** /**
@ -60,6 +32,7 @@ static void sleep(struct rt_pm *pm, uint8_t mode)
break; break;
case PM_SLEEP_MODE_IDLE: case PM_SLEEP_MODE_IDLE:
// __WFI();
break; break;
case PM_SLEEP_MODE_LIGHT: case PM_SLEEP_MODE_LIGHT:
@ -76,12 +49,10 @@ static void sleep(struct rt_pm *pm, uint8_t mode)
break; break;
case PM_SLEEP_MODE_DEEP: case PM_SLEEP_MODE_DEEP:
#if defined(SOC_SERIES_STM32L4)
/* Enter STOP 2 mode */ /* Enter STOP 2 mode */
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI); HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
/* Re-configure the system clock */ /* Re-configure the system clock */
SystemClock_ReConfig(pm->run_mode); SystemClock_ReConfig(pm->run_mode);
#endif /* defined(SOC_SERIES_STM32L4) */
break; break;
case PM_SLEEP_MODE_STANDBY: case PM_SLEEP_MODE_STANDBY:
@ -90,17 +61,74 @@ static void sleep(struct rt_pm *pm, uint8_t mode)
break; break;
case PM_SLEEP_MODE_SHUTDOWN: case PM_SLEEP_MODE_SHUTDOWN:
#if defined(SOC_SERIES_STM32L4)
/* Enter SHUTDOWNN mode */ /* Enter SHUTDOWNN mode */
HAL_PWREx_EnterSHUTDOWNMode(); HAL_PWREx_EnterSHUTDOWNMode();
#endif /* defined(SOC_SERIES_STM32L4) */
break; break;
default: default:
RT_ASSERT(0);
break; break;
} }
} }
static uint8_t run_speed[PM_RUN_MODE_MAX][2] =
{
{80, 0},
{80, 1},
{24, 2},
{2, 3},
};
static void run(struct rt_pm *pm, uint8_t mode)
{
static uint8_t last_mode;
static char *run_str[] = PM_RUN_MODE_NAMES;
if (mode == last_mode)
return;
last_mode = mode;
/* 1. 设置 MSI 作为 SYSCLK 时钟源,以修改 PLL */
SystemClock_MSI_ON();
/* 2. 根据RUN模式切换时钟频率(HSI) */
switch (mode)
{
case PM_RUN_MODE_HIGH_SPEED:
case PM_RUN_MODE_NORMAL_SPEED:
HAL_PWREx_DisableLowPowerRunMode();
SystemClock_80M();
/* Configure the main internal regulator output voltage (Range1 by default)*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
break;
case PM_RUN_MODE_MEDIUM_SPEED:
HAL_PWREx_DisableLowPowerRunMode();
SystemClock_24M();
/* Configure the main internal regulator output voltage */
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);
break;
case PM_RUN_MODE_LOW_SPEED:
SystemClock_2M();
/* Enter LP RUN mode */
HAL_PWREx_EnableLowPowerRunMode();
break;
default:
break;
}
/* 3. 关闭 MSI 时钟 */
// SystemClock_MSI_OFF();
/* 4. 更新外设时钟 */
uart_console_reconfig();
/* Re-Configure the Systick time */
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / RT_TICK_PER_SECOND);
/* Re-Configure the Systick */
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
rt_kprintf("switch to %s mode, frequency = %d MHz\n", run_str[mode], run_speed[mode][0]);
}
/** /**
* This function caculate the PM tick from OS tick * This function caculate the PM tick from OS tick
* *
@ -108,19 +136,9 @@ static void sleep(struct rt_pm *pm, uint8_t mode)
* *
* @return the PM tick * @return the PM tick
*/ */
static rt_tick_t stm32_pm_tick_from_os_tick(rt_tick_t tick) static rt_tick_t stm32l4_pm_tick_from_os_tick(rt_tick_t tick)
{ {
rt_uint32_t freq = 0; rt_uint32_t freq = stm32l4_lptim_get_countfreq();
rt_err_t ret = rt_device_control(timer, DRV_HW_LPTIMER_CTRL_GET_FREQ, &freq);
if(ret != RT_EOK)
{
LOG_E("Get PM timer %s frequency failed %d", timer->parent.name, ret);
return 0;
}
else
{
LOG_D("Get PM timer %s frequency %d", timer->parent.name, freq);
}
return (freq * tick / RT_TICK_PER_SECOND); return (freq * tick / RT_TICK_PER_SECOND);
} }
@ -132,25 +150,18 @@ static rt_tick_t stm32_pm_tick_from_os_tick(rt_tick_t tick)
* *
* @return the OS tick * @return the OS tick
*/ */
static rt_tick_t stm32_os_tick_from_pm_tick(rt_uint32_t tick) static rt_tick_t stm32l4_os_tick_from_pm_tick(rt_uint32_t tick)
{ {
static rt_uint32_t os_tick_remain = 0; static rt_uint32_t os_tick_remain = 0;
rt_tick_t os_tick = 0; rt_uint32_t ret, freq;
rt_uint32_t freq = 0;
rt_err_t ret = rt_device_control(timer, DRV_HW_LPTIMER_CTRL_GET_FREQ, &freq); freq = stm32l4_lptim_get_countfreq();
if(ret != RT_EOK) ret = (tick * RT_TICK_PER_SECOND + os_tick_remain) / freq;
{
LOG_E("Get PM timer %s frequency failed %d", timer->parent.name, ret);
return 0;
}
os_tick = (tick * RT_TICK_PER_SECOND + os_tick_remain) / freq;
os_tick_remain += (tick * RT_TICK_PER_SECOND); os_tick_remain += (tick * RT_TICK_PER_SECOND);
os_tick_remain %= freq; os_tick_remain %= freq;
return os_tick; return ret;
} }
/** /**
@ -163,33 +174,18 @@ static void pm_timer_start(struct rt_pm *pm, rt_uint32_t timeout)
{ {
RT_ASSERT(pm != RT_NULL); RT_ASSERT(pm != RT_NULL);
RT_ASSERT(timeout > 0); RT_ASSERT(timeout > 0);
RT_ASSERT(timer != RT_NULL);
if (timeout != RT_TICK_MAX) if (timeout != RT_TICK_MAX)
{ {
rt_uint32_t max_tick = 0;
rt_err_t ret = rt_device_control(timer, DRV_HW_LPTIMER_CTRL_GET_TICK_MAX, &max_tick);
if(ret != RT_EOK)
{
LOG_E("Get PM timer %s max tick failed %d", timer->parent.name, ret);
return;
}
/* Convert OS Tick to pmtimer timeout value */ /* Convert OS Tick to pmtimer timeout value */
timeout = stm32_pm_tick_from_os_tick(timeout); timeout = stm32l4_pm_tick_from_os_tick(timeout);
if (timeout > stm32l4_lptim_get_tick_max())
if (timeout > max_tick)
{ {
timeout = max_tick; timeout = stm32l4_lptim_get_tick_max();
} }
/* Enter PM_TIMER_MODE */ /* Enter PM_TIMER_MODE */
ret = rt_device_control(timer, DRV_HW_LPTIMER_CTRL_START, &timeout); stm32l4_lptim_start(timeout);
if(ret != RT_EOK)
{
LOG_E("Get PM timer %s max tick failed %d", timer->parent.name, ret);
return;
}
} }
} }
@ -203,7 +199,7 @@ static void pm_timer_stop(struct rt_pm *pm)
RT_ASSERT(pm != RT_NULL); RT_ASSERT(pm != RT_NULL);
/* Reset pmtimer status */ /* Reset pmtimer status */
rt_device_control(timer, HWTIMER_CTRL_STOP, RT_NULL); stm32l4_lptim_stop();
} }
/** /**
@ -219,42 +215,29 @@ static rt_tick_t pm_timer_get_tick(struct rt_pm *pm)
RT_ASSERT(pm != RT_NULL); RT_ASSERT(pm != RT_NULL);
rt_err_t ret = rt_device_control(timer, DRV_HW_LPTIMER_CTRL_GET_COUNT, &timer_tick); timer_tick = stm32l4_lptim_get_current_tick();
if(ret != RT_EOK) return stm32l4_os_tick_from_pm_tick(timer_tick);
{
LOG_E("Get PM timer %s count failed %d", timer->parent.name, ret);
return 0;
} }
else
{
return stm32_os_tick_from_pm_tick(timer_tick);
}
}
static const struct rt_pm_ops _ops =
{
sleep,
stm32_pm_device_run,
pm_timer_start,
pm_timer_stop,
pm_timer_get_tick
};
/** /**
* This function initialize the power manager * This function initialize the power manager
*/ */
int drv_pm_hw_init(void) int drv_pm_hw_init(void)
{ {
static const struct rt_pm_ops _ops =
{
sleep,
run,
pm_timer_start,
pm_timer_stop,
pm_timer_get_tick
};
rt_uint8_t timer_mask = 0; rt_uint8_t timer_mask = 0;
/* Enable Power Clock */ /* Enable Power Clock */
#if !defined(SOC_SERIES_STM32H7) && !defined(SOC_SERIES_STM32WL) && !defined(SOC_SERIES_STM32WB)
__HAL_RCC_PWR_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE();
#ifdef SOC_SERIES_STM32F1
__HAL_RCC_BKP_CLK_ENABLE();
#endif
#endif
/* initialize timer mask */ /* initialize timer mask */
timer_mask = 1UL << PM_SLEEP_MODE_DEEP; timer_mask = 1UL << PM_SLEEP_MODE_DEEP;
@ -262,18 +245,7 @@ int drv_pm_hw_init(void)
/* initialize system pm module */ /* initialize system pm module */
rt_system_pm_init(&_ops, timer_mask, RT_NULL); rt_system_pm_init(&_ops, timer_mask, RT_NULL);
timer = rt_device_find(BSP_USING_PM_TIMER); return 0;
if(timer == RT_NULL)
{
LOG_E("Can't find PM timer device");
return -RT_ERROR;
}
else
{
return rt_device_init(timer);
}
} }
INIT_CORE_EXPORT(drv_pm_hw_init); INIT_BOARD_EXPORT(drv_pm_hw_init);
#endif /* RT_USING_PM */

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2024 RT-Thread Development Team * Copyright (c) 2006-2023, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
@ -22,7 +22,7 @@
#define RTC_BKP_DR1 RT_NULL #define RTC_BKP_DR1 RT_NULL
#endif #endif
/* #define DRV_DEBUG*/ //#define DRV_DEBUG
#define LOG_TAG "drv.rtc" #define LOG_TAG "drv.rtc"
#include <drv_log.h> #include <drv_log.h>
@ -393,7 +393,7 @@ static rt_err_t rtc_alarm_time_set(struct rtc_device_object* p_dev)
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{ {
/*LOG_D("rtc alarm isr.\n");*/ //LOG_D("rtc alarm isr.\n");
rt_alarm_update(&rtc_device.rtc_dev.parent, 1); rt_alarm_update(&rtc_device.rtc_dev.parent, 1);
} }
@ -424,5 +424,5 @@ static int rt_hw_rtc_init(void)
return RT_EOK; return RT_EOK;
} }
INIT_BOARD_EXPORT(rt_hw_rtc_init); INIT_DEVICE_EXPORT(rt_hw_rtc_init);
#endif /* BSP_USING_ONCHIP_RTC */ #endif /* BSP_USING_ONCHIP_RTC */

View File

@ -17,8 +17,8 @@
#include <drv_common.h> #include <drv_common.h>
#include "drv_dma.h" #include "drv_dma.h"
#include <string.h> #include <string.h>
#include <drivers/dev_mmcsd_core.h> #include <drivers/mmcsd_core.h>
#include <drivers/dev_sdio.h> #include <drivers/sdio.h>
#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) #if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4)
#define SDCARD_INSTANCE_TYPE SDIO_TypeDef #define SDCARD_INSTANCE_TYPE SDIO_TypeDef
@ -35,6 +35,10 @@
#define SDIO_BUFF_SIZE 4096 #define SDIO_BUFF_SIZE 4096
#define SDIO_ALIGN_LEN 32 #define SDIO_ALIGN_LEN 32
#ifndef SDIO_MAX_FREQ
#define SDIO_MAX_FREQ (1000000)
#endif
#ifndef SDIO_BASE_ADDRESS #ifndef SDIO_BASE_ADDRESS
#define SDIO_BASE_ADDRESS (0x40012800U) #define SDIO_BASE_ADDRESS (0x40012800U)
#endif #endif

View File

@ -18,8 +18,8 @@
#include <rthw.h> #include <rthw.h>
#include <drv_common.h> #include <drv_common.h>
#include <string.h> #include <string.h>
#include <drivers/dev_mmcsd_core.h> #include <drivers/mmcsd_core.h>
#include <drivers/dev_sdio.h> #include <drivers/sdio.h>
#define SDIO_BUFF_SIZE 4096 #define SDIO_BUFF_SIZE 4096
#define SDIO_ALIGN_LEN 32 #define SDIO_ALIGN_LEN 32

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2024, RT-Thread Development Team * Copyright (c) 2006-2023, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
@ -156,6 +156,36 @@ void stm32_dir_miso(void *data, rt_int32_t state)
} }
} }
static void stm32_udelay(rt_uint32_t us)
{
rt_uint32_t ticks;
rt_uint32_t told, tnow, tcnt = 0;
rt_uint32_t reload = SysTick->LOAD;
ticks = us * reload / (1000000UL / RT_TICK_PER_SECOND);
told = SysTick->VAL;
while (1)
{
tnow = SysTick->VAL;
if (tnow != told)
{
if (tnow < told)
{
tcnt += told - tnow;
}
else
{
tcnt += reload - tnow + told;
}
told = tnow;
if (tcnt >= ticks)
{
break;
}
}
}
}
static void stm32_pin_init(void) static void stm32_pin_init(void)
{ {
rt_size_t obj_num = sizeof(spi_obj) / sizeof(struct stm32_soft_spi); rt_size_t obj_num = sizeof(spi_obj) / sizeof(struct stm32_soft_spi);
@ -179,7 +209,7 @@ static struct rt_spi_bit_ops stm32_soft_spi_ops =
.get_miso = stm32_get_miso, .get_miso = stm32_get_miso,
.dir_mosi = stm32_dir_mosi, .dir_mosi = stm32_dir_mosi,
.dir_miso = stm32_dir_miso, .dir_miso = stm32_dir_miso,
.udelay = rt_hw_us_delay, .udelay = stm32_udelay,
.delay_us = 1, .delay_us = 1,
}; };

View File

@ -13,7 +13,7 @@
#include <rthw.h> #include <rthw.h>
#include <rtdevice.h> #include <rtdevice.h>
#include <dev_spi_bit_ops.h> #include <spi-bit-ops.h>
/* stm32 soft spi config */ /* stm32 soft spi config */
struct stm32_soft_spi_config struct stm32_soft_spi_config

View File

@ -357,7 +357,7 @@ static int stm32_putc(struct rt_serial_device *serial, char c)
#else #else
uart->handle.Instance->DR = c; uart->handle.Instance->DR = c;
#endif #endif
while (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) == RESET && --block_timeout); while (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) == RESET && block_timeout--);
return (block_timeout != 0) ? 1 : -1; return (block_timeout != 0) ? 1 : -1;
} }

View File

@ -11,8 +11,7 @@
[![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) [![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) [![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) [![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
RT-Thread was born in 2006, it is an open source, neutral, and community-based real-time operating system (RTOS). RT-Thread was born in 2006, it is an open source, neutral, and community-based real-time operating system (RTOS).

View File

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

View File

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

View File

@ -1,11 +0,0 @@
# 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

@ -1,698 +0,0 @@
/*
* 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

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2024 RT-Thread Development Team * Copyright (c) 2006-2022, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
@ -107,8 +107,7 @@ int dfs_init(void)
INIT_PREV_EXPORT(dfs_init); INIT_PREV_EXPORT(dfs_init);
/** /**
* @brief this function will lock device file system. * 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. * @note please don't invoke it on ISR.
*/ */
@ -127,12 +126,6 @@ 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) void dfs_file_lock(void)
{ {
rt_err_t result = -RT_EBUSY; rt_err_t result = -RT_EBUSY;
@ -149,7 +142,7 @@ void dfs_file_lock(void)
} }
/** /**
* @brief this function will unlock device file system. * this function will lock device file system.
* *
* @note please don't invoke it on ISR. * @note please don't invoke it on ISR.
*/ */
@ -158,56 +151,33 @@ void dfs_unlock(void)
rt_mutex_release(&fslock); rt_mutex_release(&fslock);
} }
/** #ifdef DFS_USING_POSIX
* @brief this function will unlock fd table.
*/
void dfs_file_unlock(void) void dfs_file_unlock(void)
{ {
rt_mutex_release(&fdlock); 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) static int fd_slot_expand(struct dfs_fdtable *fdt, int fd)
{ {
int nr; int nr;
int index; int index;
struct dfs_file **fds = NULL; struct dfs_file **fds = NULL;
/* If the file descriptor is already within the current capacity, no expansion is needed.*/
if (fd < fdt->maxfd) if (fd < fdt->maxfd)
{ {
return fd; return fd;
} }
/* If the file descriptor exceeds the maximum allowable limit, return an error.*/
if (fd >= DFS_FD_MAX) if (fd >= DFS_FD_MAX)
{ {
return -1; return -1;
} }
/* Calculate the new capacity, rounding up to the nearest multiple of 4.*/
nr = ((fd + 4) & ~3); nr = ((fd + 4) & ~3);
/* Ensure the new capacity does not exceed the maximum limit.*/
if (nr > DFS_FD_MAX) if (nr > DFS_FD_MAX)
{ {
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 *)); fds = (struct dfs_file **)rt_realloc(fdt->fds, nr * sizeof(struct dfs_file *));
if (!fds) if (!fds)
{ {
@ -219,23 +189,12 @@ static int fd_slot_expand(struct dfs_fdtable *fdt, int fd)
{ {
fds[index] = NULL; fds[index] = NULL;
} }
/* Update the file descriptor table and its capacity.*/
fdt->fds = fds; fdt->fds = fds;
fdt->maxfd = nr; fdt->maxfd = nr;
return fd; 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) static int fd_slot_alloc(struct dfs_fdtable *fdt, int startfd)
{ {
int idx; int idx;
@ -260,17 +219,6 @@ static int fd_slot_alloc(struct dfs_fdtable *fdt, int startfd)
} }
return idx; 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) static int fd_alloc(struct dfs_fdtable *fdt, int startfd)
{ {
int idx; int idx;
@ -375,11 +323,7 @@ struct dfs_file *fd_get(int fd)
/** /**
* @ingroup Fd * @ingroup Fd
* *
* @brief This function will release the file descriptor. * This function will put 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) void fdt_fd_release(struct dfs_fdtable* fdt, int fd)
{ {
@ -434,20 +378,6 @@ void fd_release(int fd)
fdt_fd_release(fdt, 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) rt_err_t sys_dup(int oldfd)
{ {
int newfd = -1; int newfd = -1;
@ -540,23 +470,6 @@ int fd_is_open(const char *pathname)
return -1; 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) rt_err_t sys_dup2(int oldfd, int newfd)
{ {
struct dfs_fdtable *fdt = NULL; struct dfs_fdtable *fdt = NULL;
@ -637,10 +550,6 @@ static int fd_get_fd_index_form_fdt(struct dfs_fdtable *fdt, struct dfs_file *fi
return fd; return fd;
} }
/**
* @brief get fd (index) by dfs file object.
*
*/
int fd_get_fd_index(struct dfs_file *file) int fd_get_fd_index(struct dfs_file *file)
{ {
struct dfs_fdtable *fdt; struct dfs_fdtable *fdt;
@ -649,21 +558,6 @@ int fd_get_fd_index(struct dfs_file *file)
return fd_get_fd_index_form_fdt(fdt, 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 fd_associate(struct dfs_fdtable *fdt, int fd, struct dfs_file *file)
{ {
int retfd = -1; int retfd = -1;
@ -697,10 +591,6 @@ exit:
return retfd; return retfd;
} }
/**
* @brief initialize a dfs file object.
*
*/
void fd_init(struct dfs_file *fd) void fd_init(struct dfs_file *fd)
{ {
if (fd) if (fd)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2024 RT-Thread Development Team * Copyright (c) 2006-2021, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
@ -18,12 +18,10 @@
#define DFS_VNODE_HASH_NR 128 #define DFS_VNODE_HASH_NR 128
/*dfs vnode manager, for saving and searching vnodes.*/
struct dfs_vnode_mgr struct dfs_vnode_mgr
{ {
struct rt_mutex lock; /* mutex for protecting dfs vnode lists */ struct rt_mutex lock;
rt_list_t head[DFS_VNODE_HASH_NR]; /* a group of dfs vnode lists, the dfs vnode is inserted to one of the lists rt_list_t head[DFS_VNODE_HASH_NR];
according to path string's hash-value mod DFS_VNODE_HASH_NR. */
}; };
static struct dfs_vnode_mgr dfs_fm; static struct dfs_vnode_mgr dfs_fm;
@ -38,10 +36,6 @@ void dfs_fm_unlock(void)
rt_mutex_release(&dfs_fm.lock); 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) void dfs_vnode_mgr_init(void)
{ {
int i = 0; int i = 0;
@ -53,23 +47,6 @@ 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) int dfs_vnode_init(struct dfs_vnode *vnode, int type, const struct dfs_file_ops *fops)
{ {
if (vnode) if (vnode)
@ -87,7 +64,7 @@ int dfs_vnode_init(struct dfs_vnode *vnode, int type, const struct dfs_file_ops
/* BKDR Hash Function */ /* BKDR Hash Function */
static unsigned int bkdr_hash(const char *str) 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; unsigned int hash = 0;
while (*str) while (*str)
@ -98,22 +75,6 @@ static unsigned int bkdr_hash(const char *str)
return (hash % DFS_VNODE_HASH_NR); 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) static struct dfs_vnode *dfs_vnode_find(const char *path, rt_list_t **hash_head)
{ {
struct dfs_vnode *vnode = NULL; struct dfs_vnode *vnode = NULL;
@ -368,12 +329,11 @@ int dfs_file_close(struct dfs_file *fd)
} }
/** /**
* this function will perform an io control on a file descriptor. * this function will perform a io control on a file descriptor.
* *
* @param fd the file descriptor. * @param fd the file descriptor.
* @param cmd the command to send to file descriptor. * @param cmd the command to send to file descriptor.
* @param args the argument 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. * @return 0 on successful, -1 on failed.
*/ */
@ -886,7 +846,7 @@ void cat(const char *filename)
{ {
buffer[length] = '\0'; buffer[length] = '\0';
rt_device_t out_device = rt_console_get_device(); rt_device_t out_device = rt_console_get_device();
rt_device_write(out_device, 0, (void *)buffer, length); rt_device_write(out_device, 0, (void *)buffer, sizeof(buffer));
} }
} while (length > 0); } while (length > 0);
rt_kprintf("\n"); rt_kprintf("\n");
@ -1066,14 +1026,14 @@ void copy(const char *src, const char *dst)
flag |= FLAG_DST_IS_FILE; flag |= FLAG_DST_IS_FILE;
} }
/*2. check status*/ //2. check status
if ((flag & FLAG_SRC_IS_DIR) && (flag & FLAG_DST_IS_FILE)) if ((flag & FLAG_SRC_IS_DIR) && (flag & FLAG_DST_IS_FILE))
{ {
rt_kprintf("cp faild, cp dir to file is not permitted!\n"); rt_kprintf("cp faild, cp dir to file is not permitted!\n");
return ; return ;
} }
/*3. do copy*/ //3. do copy
if (flag & FLAG_SRC_IS_FILE) if (flag & FLAG_SRC_IS_FILE)
{ {
if (flag & FLAG_DST_IS_DIR) if (flag & FLAG_DST_IS_DIR)
@ -1093,7 +1053,7 @@ void copy(const char *src, const char *dst)
copyfile(src, dst); copyfile(src, dst);
} }
} }
else /*flag & FLAG_SRC_IS_DIR*/ else //flag & FLAG_SRC_IS_DIR
{ {
if (flag & FLAG_DST_IS_DIR) if (flag & FLAG_DST_IS_DIR)
{ {

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2024 RT-Thread Development Team * Copyright (c) 2006-2021, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
@ -28,17 +28,7 @@
* return a file descriptor according specified flags. * return a file descriptor according specified flags.
* *
* @param file the path name of file. * @param file the path name of file.
* @param flags the file open flags. Common values include: * @param flags the file open flags.
* - 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. * @return the non-negative integer on successful open, others for failed.
*/ */
@ -75,22 +65,6 @@ RTM_EXPORT(open);
#ifndef AT_FDCWD #ifndef AT_FDCWD
#define AT_FDCWD (-100) #define AT_FDCWD (-100)
#endif #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, ...) int openat(int dirfd, const char *path, int flag, ...)
{ {
struct dfs_file *d; struct dfs_file *d;
@ -267,22 +241,14 @@ ssize_t write(int fd, const void *buf, size_t len)
RTM_EXPORT(write); RTM_EXPORT(write);
/** /**
* this function is a POSIX compliant version, which will Reposition the file offset for * this function is a POSIX compliant version, which will seek the offset for
* an open file descriptor. * an open file descriptor.
* *
* 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.
*
* @param fd the file descriptor. * @param fd the file descriptor.
* @param offset The offset, in bytes, to set the file position. * @param offset the offset to be seeked.
* The meaning of `offset` depends on the value of `whence`. * @param whence the directory of seek.
* @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. * @return the current read/write position in the file, or -1 on failed.
*/ */
off_t lseek(int fd, off_t offset, int whence) off_t lseek(int fd, off_t offset, int whence)
{ {
@ -470,15 +436,9 @@ RTM_EXPORT(fsync);
* control functions on devices. * control functions on devices.
* *
* @param fildes the file description * @param fildes the file description
* @param cmd the specified command, Common values include: * @param cmd the specified command
* - `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 * @param ... represents the additional information that is needed by this
* specific device to perform the requested function. For example: * specific device to perform the requested function.
* - 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 * @return 0 on successful completion. Otherwise, -1 shall be returned and errno
* set to indicate the error. * set to indicate the error.
@ -635,7 +595,7 @@ RTM_EXPORT(fstatfs);
* this function is a POSIX compliant version, which will make a directory * this function is a POSIX compliant version, which will make a directory
* *
* @param path the directory path to be made. * @param path the directory path to be made.
* @param mode The permission mode for the new directory (unused here, can be set to 0). * @param mode
* *
* @return 0 on successful, others on failed. * @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; rt_err_t result = RT_EOK;
file_info *fi = NULL; file_info *fi = NULL;
cromfs_info *ci = NULL; cromfs_info *ci = NULL;
ssize_t length = 0; uint32_t length = 0;
ci = (cromfs_info *)file->dentry->mnt->data; ci = (cromfs_info *)file->dentry->mnt->data;
fi = (file_info *)file->vnode->data; fi = (file_info *)file->vnode->data;
if ((off_t)count < (off_t)file->vnode->size - *pos) if (count < file->vnode->size - *pos)
{ {
length = count; length = count;
} }
else else
{ {
length = (off_t)file->vnode->size - *pos; length = file->vnode->size - *pos;
} }
if (length > 0) if (length > 0)

View File

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

View File

@ -77,7 +77,6 @@ static int dfs_devfs_open(struct dfs_file *file)
} }
} }
} }
rt_free(device_name);
} }
return ret; return ret;
@ -114,29 +113,6 @@ static int dfs_devfs_close(struct dfs_file *file)
return ret; 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) static ssize_t dfs_devfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
{ {
ssize_t ret = -RT_EIO; ssize_t ret = -RT_EIO;
@ -159,16 +135,11 @@ static ssize_t dfs_devfs_read(struct dfs_file *file, void *buf, size_t count, of
if (device->ops) if (device->ops)
#endif /* RT_USING_POSIX_DEVIO */ #endif /* RT_USING_POSIX_DEVIO */
{ {
rt_ubase_t shift = _get_unit_shift(device); /* read device data */
ret = rt_device_read(device, *pos, buf, count);
ret = rt_device_read(device, *pos, buf, count >> shift);
if (ret > 0)
{
ret <<= shift;
*pos += ret; *pos += ret;
} }
} }
}
return ret; return ret;
} }
@ -198,17 +169,11 @@ static ssize_t dfs_devfs_write(struct dfs_file *file, const void *buf, size_t co
if (device->ops) if (device->ops)
#endif /* RT_USING_POSIX_DEVIO */ #endif /* RT_USING_POSIX_DEVIO */
{ {
rt_ubase_t shift = _get_unit_shift(device);
/* read device data */ /* read device data */
ret = rt_device_write(device, *pos, buf, count >> shift); ret = rt_device_write(device, *pos, buf, count);
if (ret > 0)
{
ret <<= shift;
*pos += ret; *pos += ret;
} }
} }
}
return ret; return ret;
} }
@ -300,7 +265,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) static off_t dfs_devfs_lseek(struct dfs_file *file, off_t offset, int wherece)
{ {
off_t ret = -EPERM; off_t ret = 0;
rt_device_t device; rt_device_t device;
RT_ASSERT(file != RT_NULL); RT_ASSERT(file != RT_NULL);
@ -443,16 +408,16 @@ mode_t dfs_devfs_device_to_mode(struct rt_device *device)
switch (device->type) switch (device->type)
{ {
case RT_Device_Class_Char: case RT_Device_Class_Char:
mode = S_IFCHR | 0666; mode = S_IFCHR | 0777;
break; break;
case RT_Device_Class_Block: case RT_Device_Class_Block:
mode = S_IFBLK | 0666; mode = S_IFBLK | 0777;
break; break;
case RT_Device_Class_Pipe: case RT_Device_Class_Pipe:
mode = S_IFIFO | 0666; mode = S_IFIFO | 0777;
break; break;
default: default:
mode = S_IFCHR | 0666; mode = S_IFCHR | 0777;
break; break;
} }

View File

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

View File

@ -1,166 +0,0 @@
# 进程文件系统 (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

@ -1,11 +0,0 @@
# 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

@ -1,733 +0,0 @@
/*
* 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

@ -1,75 +0,0 @@
/*
* 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

@ -1,53 +0,0 @@
/*
* 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

@ -1,86 +0,0 @@
/*
* 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

@ -1,307 +0,0 @@
/*
* 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

@ -1,85 +0,0 @@
/*
* 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

@ -1,41 +0,0 @@
/*
* 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

@ -1,66 +0,0 @@
/*
* 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

@ -1,101 +0,0 @@
/*
* 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

@ -1,107 +0,0 @@
/*
* 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

@ -1,215 +0,0 @@
/*
* 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

@ -1,449 +0,0 @@
/*
* 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

@ -1,66 +0,0 @@
/*
* 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

@ -1,114 +0,0 @@
/*
* 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

@ -1,100 +0,0 @@
/*
* 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

@ -1,38 +0,0 @@
/*
* 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

@ -1,45 +0,0 @@
/*
* 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

@ -1,447 +0,0 @@
/*
* 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

@ -1,19 +0,0 @@
/*
* 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)); pts_file = rt_calloc(1, sizeof(struct ptyfs_file));
if (pts_file) if (pts_file)
{ {
snprintf(pts_file->basename, DIRENT_NAME_MAX, "%lu", (unsigned long)rc); snprintf(pts_file->basename, DIRENT_NAME_MAX, "%lu", rc);
ptyfile_init(pts_file, sb, 0, PTYFS_TYPE_FILE_SLAVE, ptyfile_init(pts_file, sb, 0, PTYFS_TYPE_FILE_SLAVE,
PTS_DEFAULT_FILE_MODE, pts); PTS_DEFAULT_FILE_MODE, pts);
ptyfile_add_to_root(sb, pts_file); 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 else
{ {
/* get path and findout device */ /* get path and findout device */
snprintf(path_buf, sizeof(path_buf), "%lu", (unsigned long)ptsno); snprintf(path_buf, sizeof(path_buf), "%lu", ptsno);
pts_file = ptyfile_lookup(sb, path_buf); pts_file = ptyfile_lookup(sb, path_buf);
if (pts_file) if (pts_file)
{ {

View File

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

View File

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

View File

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

View File

@ -20,38 +20,6 @@ extern "C"
{ {
#endif #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 */ /* file system partition table */
struct dfs_partition struct dfs_partition
{ {
@ -119,7 +87,6 @@ int dfs_unregister(struct dfs_filesystem_type *fs);
int dfs_register(struct dfs_filesystem_type *fs); int dfs_register(struct dfs_filesystem_type *fs);
const char *dfs_filesystem_get_mounted_path(struct rt_device *device); 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, int dfs_mount(const char *device_name,
const char *path, const char *path,
const char *filesystemtype, const char *filesystemtype,

View File

@ -39,8 +39,6 @@ struct dfs_mnt
#define MNT_IS_UMOUNT 0x8 /* the mnt is unmount */ #define MNT_IS_UMOUNT 0x8 /* the mnt is unmount */
#define MNT_IS_LOCKED 0x10 /* the mnt is locked */ #define MNT_IS_LOCKED 0x10 /* the mnt is locked */
#define MNT_FORCE 0x20 /* the mnt force unmount */ #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 */ rt_atomic_t ref_count; /* reference count */
@ -62,16 +60,9 @@ const char *dfs_mnt_get_mounted_path(struct rt_device *device);
struct dfs_mnt* dfs_mnt_ref(struct dfs_mnt* mnt); struct dfs_mnt* dfs_mnt_ref(struct dfs_mnt* mnt);
int dfs_mnt_unref(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); 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_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 #ifdef __cplusplus
} }

View File

@ -118,7 +118,6 @@ 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_release(size_t count);
void dfs_pcache_unmount(struct dfs_mnt *mnt); void dfs_pcache_unmount(struct dfs_mnt *mnt);
void dfs_pcache_clean(struct dfs_mnt *mnt);
#ifdef __cplusplus #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); 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_read(struct dfs_file *file, void *buf, size_t size, off_t *pos);
off_t dfs_seq_lseek(struct dfs_file *file, off_t offset, int whence); ssize_t dfs_seq_lseek(struct dfs_file *file, off_t offset, int whence);
int dfs_seq_release(struct dfs_file *file); int dfs_seq_release(struct dfs_file *file);
int dfs_seq_write(struct dfs_seq_file *seq, const void *data, size_t len); int dfs_seq_write(struct dfs_seq_file *seq, const void *data, size_t len);

View File

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

View File

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

View File

@ -95,52 +95,6 @@ int dfs_unregister(struct dfs_filesystem_type *fs)
return ret; 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) * parent(mount path)
* mnt_parent <- - - - - - - + * mnt_parent <- - - - - - - +
@ -173,7 +127,7 @@ int dfs_mount(const char *device_name,
} }
else else
{ {
rt_set_errno(ENODEV); rt_set_errno(ENOENT);
ret = -1; ret = -1;
} }
@ -346,7 +300,7 @@ int dfs_mount(const char *device_name,
int dfs_umount(const char *specialfile, int flags) int dfs_umount(const char *specialfile, int flags)
{ {
int ret = -1; int ret = -RT_ERROR;
char *fullpath = RT_NULL; char *fullpath = RT_NULL;
struct dfs_mnt *mnt = RT_NULL; struct dfs_mnt *mnt = RT_NULL;
@ -360,7 +314,7 @@ int dfs_umount(const char *specialfile, int flags)
if (strcmp(mnt->fullpath, fullpath) == 0) if (strcmp(mnt->fullpath, fullpath) == 0)
{ {
/* is the mount point */ /* is the mount point */
rt_base_t ref_count = rt_atomic_load(&(mnt->ref_count)); rt_atomic_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))) if (!(mnt->flags & MNT_IS_LOCKED) && rt_list_isempty(&mnt->child) && (ref_count == 1 || (flags & MNT_FORCE)))
{ {
@ -373,19 +327,17 @@ int dfs_umount(const char *specialfile, int flags)
} }
else else
{ {
LOG_I("the file system is busy!"); LOG_E("the file system is busy!");
ret = -EBUSY;
} }
} }
else else
{ {
LOG_I("the path:%s is not a mountpoint!", fullpath); LOG_E("the path:%s is not a mountpoint!", fullpath);
ret = -EINVAL;
} }
} }
else else
{ {
LOG_I("no filesystem found."); LOG_E("no filesystem found.");
} }
rt_free(fullpath); rt_free(fullpath);
} }

View File

@ -10,21 +10,17 @@
#include <rtthread.h> #include <rtthread.h>
#include "dfs.h"
#include "dfs_mnt.h"
#include "dfs_dentry.h"
#include "dfs_private.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_TAG "DFS.mnt"
#define DBG_LVL DBG_WARNING #define DBG_LVL DBG_WARNING
#include <rtdbg.h> #include <rtdbg.h>
static struct dfs_mnt *_root_mnt = RT_NULL; static struct dfs_mnt *_root_mnt = RT_NULL;
RT_OBJECT_HOOKLIST_DEFINE(dfs_mnt_umnt);
/* /*
* mnt tree structure * mnt tree structure
* *
@ -79,7 +75,6 @@ int dfs_mnt_insert(struct dfs_mnt* mnt, struct dfs_mnt* child)
child = _root_mnt; child = _root_mnt;
rt_atomic_sub(&(_root_mnt->parent->ref_count), 1); rt_atomic_sub(&(_root_mnt->parent->ref_count), 1);
rt_atomic_sub(&(_root_mnt->ref_count), 1); rt_atomic_sub(&(_root_mnt->ref_count), 1);
_root_mnt->flags &= ~MNT_IS_LOCKED;
_root_mnt = dfs_mnt_ref(mnt); _root_mnt = dfs_mnt_ref(mnt);
mnt->parent = dfs_mnt_ref(mnt); mnt->parent = dfs_mnt_ref(mnt);
@ -250,21 +245,18 @@ struct dfs_mnt* dfs_mnt_ref(struct dfs_mnt* mnt)
int dfs_mnt_unref(struct dfs_mnt* mnt) int dfs_mnt_unref(struct dfs_mnt* mnt)
{ {
rt_err_t ret = RT_EOK; rt_err_t ret = RT_EOK;
rt_base_t ref_count;
if (mnt) if (mnt)
{ {
ref_count = rt_atomic_sub(&(mnt->ref_count), 1) - 1; rt_atomic_sub(&(mnt->ref_count), 1);
if (ref_count == 0) if (rt_atomic_load(&(mnt->ref_count)) == 0)
{ {
dfs_lock(); dfs_lock();
if (mnt->flags & MNT_IS_UMOUNT) if (mnt->flags & MNT_IS_UMOUNT)
{ {
mnt->fs_ops->umount(mnt); mnt->fs_ops->umount(mnt);
RT_OBJECT_HOOKLIST_CALL(dfs_mnt_umnt, (mnt));
} }
/* free full path */ /* free full path */
@ -286,21 +278,6 @@ int dfs_mnt_unref(struct dfs_mnt *mnt)
return ret; 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) int dfs_mnt_destroy(struct dfs_mnt* mnt)
{ {
rt_err_t ret = RT_EOK; rt_err_t ret = RT_EOK;

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2024 RT-Thread Development Team * Copyright (c) 2006-2023, RT-Thread Development Team
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
@ -31,17 +31,7 @@
* return a file descriptor according specified flags. * return a file descriptor according specified flags.
* *
* @param file the path name of file. * @param file the path name of file.
* @param flags the file open flags. Common values include: * @param flags the file open flags.
* - 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. * @return the non-negative integer on successful open, others for failed.
*/ */
@ -91,22 +81,6 @@ RTM_EXPORT(open);
#ifndef AT_FDCWD #ifndef AT_FDCWD
#define AT_FDCWD (-100) #define AT_FDCWD (-100)
#endif #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, ...) int openat(int dirfd, const char *path, int flag, ...)
{ {
struct dfs_file *d; struct dfs_file *d;
@ -197,7 +171,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; attr.ia_valid = ATTR_ATIME_SET | ATTR_MTIME_SET;
time(&current_time); time(&current_time);
if (UTIME_NOW == __times[0].tv_nsec) if (UTIME_NOW == __times[0].tv_nsec)
@ -400,22 +374,14 @@ ssize_t write(int fd, const void *buf, size_t len)
RTM_EXPORT(write); RTM_EXPORT(write);
/** /**
* this function is a POSIX compliant version, which will Reposition the file offset for * this function is a POSIX compliant version, which will seek the offset for
* an open file descriptor. * an open file descriptor.
* *
* 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.
*
* @param fd the file descriptor. * @param fd the file descriptor.
* @param offset The offset, in bytes, to set the file position. * @param offset the offset to be seeked.
* The meaning of `offset` depends on the value of `whence`. * @param whence the directory of seek.
* @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. * @return the current read/write position in the file, or -1 on failed.
*/ */
off_t lseek(int fd, off_t offset, int whence) off_t lseek(int fd, off_t offset, int whence)
{ {
@ -433,7 +399,7 @@ off_t lseek(int fd, off_t offset, int whence)
result = dfs_file_lseek(file, offset, whence); result = dfs_file_lseek(file, offset, whence);
if (result < 0) if (result < 0)
{ {
rt_set_errno(-EPERM); rt_set_errno(result);
return -1; return -1;
} }
@ -615,15 +581,9 @@ RTM_EXPORT(fsync);
* control functions on devices. * control functions on devices.
* *
* @param fildes the file description * @param fildes the file description
* @param cmd the specified command, Common values include: * @param cmd the specified command
* - `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 * @param ... represents the additional information that is needed by this
* specific device to perform the requested function. For example: * specific device to perform the requested function.
* - 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 * @return 0 on successful completion. Otherwise, -1 shall be returned and errno
* set to indicate the error. * set to indicate the error.
@ -805,7 +765,7 @@ RTM_EXPORT(fstatfs);
* this function is a POSIX compliant version, which will make a directory * this function is a POSIX compliant version, which will make a directory
* *
* @param path the directory path to be made. * @param path the directory path to be made.
* @param mode The permission mode for the new directory (unused here, can be set to 0). * @param mode
* *
* @return 0 on successful, others on failed. * @return 0 on successful, others on failed.
*/ */
@ -867,7 +827,7 @@ int rmdir(const char *pathname)
if (!pathname) if (!pathname)
{ {
rt_set_errno(-EPERM); rt_set_errno(-RT_ERROR);
return -1; return -1;
} }
@ -892,7 +852,7 @@ int rmdir(const char *pathname)
if (dirent) if (dirent)
{ {
rt_set_errno(-EPERM); rt_set_errno(-RT_ERROR);
return -1; return -1;
} }
} }
@ -901,7 +861,7 @@ int rmdir(const char *pathname)
{ {
if (S_ISLNK(stat.st_mode)) if (S_ISLNK(stat.st_mode))
{ {
rt_set_errno(-EPERM); rt_set_errno(-RT_ERROR);
return -1; return -1;
} }
} }

View File

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

View File

@ -21,21 +21,8 @@ rsource "touch/Kconfig"
rsource "graphic/Kconfig" rsource "graphic/Kconfig"
rsource "hwcrypto/Kconfig" rsource "hwcrypto/Kconfig"
rsource "wlan/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 "virtio/Kconfig"
rsource "dma/Kconfig"
rsource "mfd/Kconfig"
rsource "ofw/Kconfig" rsource "ofw/Kconfig"
rsource "pci/Kconfig"
rsource "pic/Kconfig" rsource "pic/Kconfig"
rsource "pin/Kconfig" rsource "pin/Kconfig"
rsource "pinctrl/Kconfig" rsource "pinctrl/Kconfig"

View File

@ -1,22 +0,0 @@
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

@ -1,21 +0,0 @@
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

@ -1,206 +0,0 @@
/*
* 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

@ -1,896 +0,0 @@
/*
* 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

@ -1,612 +0,0 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-05-09 Urey first version
* 2019-07-09 Zero-Free improve device ops interface and data flows
*/
#include <stdio.h>
#include <string.h>
#include <rthw.h>
#include <rtdevice.h>
#define DBG_TAG "audio"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
enum
{
REPLAY_EVT_NONE = 0x00,
REPLAY_EVT_START = 0x01,
REPLAY_EVT_STOP = 0x02,
};
static rt_err_t _audio_send_replay_frame(struct rt_audio_device *audio)
{
rt_err_t result = RT_EOK;
rt_uint8_t *data;
rt_size_t dst_size, src_size;
rt_uint16_t position, remain_bytes = 0, index = 0;
struct rt_audio_buf_info *buf_info;
RT_ASSERT(audio != RT_NULL);
buf_info = &audio->replay->buf_info;
/* save current pos */
position = audio->replay->pos;
dst_size = buf_info->block_size;
/* check replay queue is empty */
if (rt_data_queue_peek(&audio->replay->queue, (const void **)&data, &src_size) != RT_EOK)
{
/* ack stop event */
if (audio->replay->event & REPLAY_EVT_STOP)
rt_completion_done(&audio->replay->cmp);
/* send zero frames */
rt_memset(&buf_info->buffer[audio->replay->pos], 0, dst_size);
audio->replay->pos += dst_size;
audio->replay->pos %= buf_info->total_size;
}
else
{
rt_memset(&buf_info->buffer[audio->replay->pos], 0, dst_size);
/* copy data from memory pool to hardware device fifo */
while (index < dst_size)
{
result = rt_data_queue_peek(&audio->replay->queue, (const void **)&data, &src_size);
if (result != RT_EOK)
{
LOG_D("under run %d, remain %d", audio->replay->pos, remain_bytes);
audio->replay->pos -= remain_bytes;
audio->replay->pos += dst_size;
audio->replay->pos %= buf_info->total_size;
audio->replay->read_index = 0;
result = -RT_EEMPTY;
break;
}
remain_bytes = MIN((dst_size - index), (src_size - audio->replay->read_index));
rt_memcpy(&buf_info->buffer[audio->replay->pos],
&data[audio->replay->read_index], remain_bytes);
index += remain_bytes;
audio->replay->read_index += remain_bytes;
audio->replay->pos += remain_bytes;
audio->replay->pos %= buf_info->total_size;
if (audio->replay->read_index == src_size)
{
/* free memory */
audio->replay->read_index = 0;
rt_data_queue_pop(&audio->replay->queue, (const void **)&data, &src_size, RT_WAITING_NO);
rt_mp_free(data);
/* notify transmitted complete. */
if (audio->parent.tx_complete != RT_NULL)
audio->parent.tx_complete(&audio->parent, (void *)data);
}
}
}
if (audio->ops->transmit != RT_NULL)
{
if (audio->ops->transmit(audio, &buf_info->buffer[position], RT_NULL, dst_size) != dst_size)
result = -RT_ERROR;
}
return result;
}
static rt_err_t _audio_flush_replay_frame(struct rt_audio_device *audio)
{
rt_err_t result = RT_EOK;
if (audio->replay->write_index)
{
result = rt_data_queue_push(&audio->replay->queue,
(const void **)audio->replay->write_data,
audio->replay->write_index,
RT_WAITING_FOREVER);
audio->replay->write_index = 0;
}
return result;
}
static rt_err_t _aduio_replay_start(struct rt_audio_device *audio)
{
rt_err_t result = RT_EOK;
if (audio->replay->activated != RT_TRUE)
{
/* start playback hardware device */
if (audio->ops->start)
result = audio->ops->start(audio, AUDIO_STREAM_REPLAY);
audio->replay->activated = RT_TRUE;
LOG_D("start audio replay device");
}
return result;
}
static rt_err_t _aduio_replay_stop(struct rt_audio_device *audio)
{
rt_err_t result = RT_EOK;
if (audio->replay->activated == RT_TRUE)
{
/* flush replay remian frames */
_audio_flush_replay_frame(audio);
/* notify irq(or thread) to stop the data transmission */
audio->replay->event |= REPLAY_EVT_STOP;
/* waiting for the remaining data transfer to complete */
rt_completion_init(&audio->replay->cmp);
rt_completion_wait(&audio->replay->cmp, RT_WAITING_FOREVER);
audio->replay->event &= ~REPLAY_EVT_STOP;
/* stop playback hardware device */
if (audio->ops->stop)
result = audio->ops->stop(audio, AUDIO_STREAM_REPLAY);
audio->replay->activated = RT_FALSE;
LOG_D("stop audio replay device");
}
return result;
}
static rt_err_t _audio_record_start(struct rt_audio_device *audio)
{
rt_err_t result = RT_EOK;
if (audio->record->activated != RT_TRUE)
{
/* open audio record pipe */
rt_device_open(RT_DEVICE(&audio->record->pipe), RT_DEVICE_OFLAG_RDONLY);
/* start record hardware device */
if (audio->ops->start)
result = audio->ops->start(audio, AUDIO_STREAM_RECORD);
audio->record->activated = RT_TRUE;
LOG_D("start audio record device");
}
return result;
}
static rt_err_t _audio_record_stop(struct rt_audio_device *audio)
{
rt_err_t result = RT_EOK;
if (audio->record->activated == RT_TRUE)
{
/* stop record hardware device */
if (audio->ops->stop)
result = audio->ops->stop(audio, AUDIO_STREAM_RECORD);
/* close audio record pipe */
rt_device_close(RT_DEVICE(&audio->record->pipe));
audio->record->activated = RT_FALSE;
LOG_D("stop audio record device");
}
return result;
}
static rt_err_t _audio_dev_init(struct rt_device *dev)
{
rt_err_t result = RT_EOK;
struct rt_audio_device *audio;
RT_ASSERT(dev != RT_NULL);
audio = (struct rt_audio_device *) dev;
/* initialize replay & record */
audio->replay = RT_NULL;
audio->record = RT_NULL;
/* initialize replay */
if (dev->flag & RT_DEVICE_FLAG_WRONLY)
{
struct rt_audio_replay *replay = (struct rt_audio_replay *) rt_malloc(sizeof(struct rt_audio_replay));
if (replay == RT_NULL)
return -RT_ENOMEM;
rt_memset(replay, 0, sizeof(struct rt_audio_replay));
/* init memory pool for replay */
replay->mp = rt_mp_create("adu_mp", RT_AUDIO_REPLAY_MP_BLOCK_COUNT, RT_AUDIO_REPLAY_MP_BLOCK_SIZE);
if (replay->mp == RT_NULL)
{
rt_free(replay);
LOG_E("create memory pool for replay failed");
return -RT_ENOMEM;
}
/* init queue for audio replay */
rt_data_queue_init(&replay->queue, CFG_AUDIO_REPLAY_QUEUE_COUNT, 0, RT_NULL);
/* init mutex lock for audio replay */
rt_mutex_init(&replay->lock, "replay", RT_IPC_FLAG_PRIO);
replay->activated = RT_FALSE;
audio->replay = replay;
}
/* initialize record */
if (dev->flag & RT_DEVICE_FLAG_RDONLY)
{
struct rt_audio_record *record = (struct rt_audio_record *) rt_malloc(sizeof(struct rt_audio_record));
rt_uint8_t *buffer;
if (record == RT_NULL)
return -RT_ENOMEM;
rt_memset(record, 0, sizeof(struct rt_audio_record));
/* init pipe for record*/
buffer = rt_malloc(RT_AUDIO_RECORD_PIPE_SIZE);
if (buffer == RT_NULL)
{
rt_free(record);
LOG_E("malloc memory for for record pipe failed");
return -RT_ENOMEM;
}
rt_audio_pipe_init(&record->pipe, "record",
(rt_int32_t)(RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD),
buffer,
RT_AUDIO_RECORD_PIPE_SIZE);
record->activated = RT_FALSE;
audio->record = record;
}
/* initialize hardware configuration */
if (audio->ops->init)
audio->ops->init(audio);
/* get replay buffer information */
if (audio->ops->buffer_info)
audio->ops->buffer_info(audio, &audio->replay->buf_info);
return result;
}
static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag)
{
struct rt_audio_device *audio;
RT_ASSERT(dev != RT_NULL);
audio = (struct rt_audio_device *) dev;
/* check device flag with the open flag */
if ((oflag & RT_DEVICE_OFLAG_RDONLY) && !(dev->flag & RT_DEVICE_FLAG_RDONLY))
return -RT_EIO;
if ((oflag & RT_DEVICE_OFLAG_WRONLY) && !(dev->flag & RT_DEVICE_FLAG_WRONLY))
return -RT_EIO;
/* get open flags */
dev->open_flag = oflag & 0xff;
/* initialize the Rx/Tx structure according to open flag */
if (oflag & RT_DEVICE_OFLAG_WRONLY)
{
if (audio->replay->activated != RT_TRUE)
{
LOG_D("open audio replay device, oflag = %x\n", oflag);
audio->replay->write_index = 0;
audio->replay->read_index = 0;
audio->replay->pos = 0;
audio->replay->event = REPLAY_EVT_NONE;
}
dev->open_flag |= RT_DEVICE_OFLAG_WRONLY;
}
if (oflag & RT_DEVICE_OFLAG_RDONLY)
{
/* open record pipe */
if (audio->record->activated != RT_TRUE)
{
LOG_D("open audio record device ,oflag = %x\n", oflag);
_audio_record_start(audio);
audio->record->activated = RT_TRUE;
}
dev->open_flag |= RT_DEVICE_OFLAG_RDONLY;
}
return RT_EOK;
}
static rt_err_t _audio_dev_close(struct rt_device *dev)
{
struct rt_audio_device *audio;
RT_ASSERT(dev != RT_NULL);
audio = (struct rt_audio_device *) dev;
if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY)
{
/* stop replay stream */
_aduio_replay_stop(audio);
dev->open_flag &= ~RT_DEVICE_OFLAG_WRONLY;
}
if (dev->open_flag & RT_DEVICE_OFLAG_RDONLY)
{
/* stop record stream */
_audio_record_stop(audio);
dev->open_flag &= ~RT_DEVICE_OFLAG_RDONLY;
}
return RT_EOK;
}
static rt_ssize_t _audio_dev_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size)
{
struct rt_audio_device *audio;
RT_ASSERT(dev != RT_NULL);
audio = (struct rt_audio_device *) dev;
if (!(dev->open_flag & RT_DEVICE_OFLAG_RDONLY) || (audio->record == RT_NULL))
return 0;
return rt_device_read(RT_DEVICE(&audio->record->pipe), pos, buffer, size);
}
static rt_ssize_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
struct rt_audio_device *audio;
rt_uint8_t *ptr;
rt_uint16_t block_size, remain_bytes, index = 0;
RT_ASSERT(dev != RT_NULL);
audio = (struct rt_audio_device *) dev;
if (!(dev->open_flag & RT_DEVICE_OFLAG_WRONLY) || (audio->replay == RT_NULL))
return 0;
/* push a new frame to replay data queue */
ptr = (rt_uint8_t *)buffer;
block_size = RT_AUDIO_REPLAY_MP_BLOCK_SIZE;
rt_mutex_take(&audio->replay->lock, RT_WAITING_FOREVER);
while (index < size)
{
/* request buffer from replay memory pool */
if (audio->replay->write_index % block_size == 0)
{
audio->replay->write_data = rt_mp_alloc(audio->replay->mp, RT_WAITING_FOREVER);
rt_memset(audio->replay->write_data, 0, block_size);
}
/* copy data to replay memory pool */
remain_bytes = MIN((block_size - audio->replay->write_index), (size - index));
rt_memcpy(&audio->replay->write_data[audio->replay->write_index], &ptr[index], remain_bytes);
index += remain_bytes;
audio->replay->write_index += remain_bytes;
audio->replay->write_index %= block_size;
if (audio->replay->write_index == 0)
{
rt_data_queue_push(&audio->replay->queue,
audio->replay->write_data,
block_size,
RT_WAITING_FOREVER);
}
}
rt_mutex_release(&audio->replay->lock);
/* check replay state */
if (audio->replay->activated != RT_TRUE)
{
_aduio_replay_start(audio);
audio->replay->activated = RT_TRUE;
}
return index;
}
static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args)
{
rt_err_t result = RT_EOK;
struct rt_audio_device *audio;
RT_ASSERT(dev != RT_NULL);
audio = (struct rt_audio_device *) dev;
/* dev stat...*/
switch (cmd)
{
case AUDIO_CTL_GETCAPS:
{
struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
LOG_D("AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d", caps->main_type, caps->sub_type);
if (audio->ops->getcaps != RT_NULL)
{
result = audio->ops->getcaps(audio, caps);
}
break;
}
case AUDIO_CTL_CONFIGURE:
{
struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
LOG_D("AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d", caps->main_type, caps->sub_type);
if (audio->ops->configure != RT_NULL)
{
result = audio->ops->configure(audio, caps);
}
break;
}
case AUDIO_CTL_START:
{
int stream = *(int *) args;
LOG_D("AUDIO_CTL_START: stream = %d", stream);
if (stream == AUDIO_STREAM_REPLAY)
{
result = _aduio_replay_start(audio);
}
else
{
result = _audio_record_start(audio);
}
break;
}
case AUDIO_CTL_STOP:
{
int stream = *(int *) args;
LOG_D("AUDIO_CTL_STOP: stream = %d", stream);
if (stream == AUDIO_STREAM_REPLAY)
{
result = _aduio_replay_stop(audio);
}
else
{
result = _audio_record_stop(audio);
}
break;
}
default:
break;
}
return result;
}
#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops audio_ops =
{
_audio_dev_init,
_audio_dev_open,
_audio_dev_close,
_audio_dev_read,
_audio_dev_write,
_audio_dev_control
};
#endif
rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data)
{
rt_err_t result = RT_EOK;
struct rt_device *device;
RT_ASSERT(audio != RT_NULL);
device = &(audio->parent);
device->type = RT_Device_Class_Sound;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
#ifdef RT_USING_DEVICE_OPS
device->ops = &audio_ops;
#else
device->init = _audio_dev_init;
device->open = _audio_dev_open;
device->close = _audio_dev_close;
device->read = _audio_dev_read;
device->write = _audio_dev_write;
device->control = _audio_dev_control;
#endif
device->user_data = data;
/* register a character device */
result = rt_device_register(device, name, flag | RT_DEVICE_FLAG_REMOVABLE);
/* initialize audio device */
if (result == RT_EOK)
result = rt_device_init(device);
return result;
}
int rt_audio_samplerate_to_speed(rt_uint32_t bitValue)
{
int speed = 0;
switch (bitValue)
{
case AUDIO_SAMP_RATE_8K:
speed = 8000;
break;
case AUDIO_SAMP_RATE_11K:
speed = 11052;
break;
case AUDIO_SAMP_RATE_16K:
speed = 16000;
break;
case AUDIO_SAMP_RATE_22K:
speed = 22050;
break;
case AUDIO_SAMP_RATE_32K:
speed = 32000;
break;
case AUDIO_SAMP_RATE_44K:
speed = 44100;
break;
case AUDIO_SAMP_RATE_48K:
speed = 48000;
break;
case AUDIO_SAMP_RATE_96K:
speed = 96000;
break;
case AUDIO_SAMP_RATE_128K:
speed = 128000;
break;
case AUDIO_SAMP_RATE_160K:
speed = 160000;
break;
case AUDIO_SAMP_RATE_172K:
speed = 176400;
break;
case AUDIO_SAMP_RATE_192K:
speed = 192000;
break;
default:
break;
}
return speed;
}
void rt_audio_tx_complete(struct rt_audio_device *audio)
{
/* try to send next frame */
_audio_send_replay_frame(audio);
}
void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len)
{
/* save data to record pipe */
rt_device_write(RT_DEVICE(&audio->record->pipe), 0, pbuf, len);
/* invoke callback */
if (audio->parent.rx_indicate != RT_NULL)
audio->parent.rx_indicate(&audio->parent, len);
}

View File

@ -1,296 +0,0 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2012-09-30 Bernard first version.
*/
#include <rthw.h>
#include <rtdevice.h>
#include "dev_audio_pipe.h"
static void _rt_audio_pipe_resume_writer(struct rt_audio_pipe *pipe)
{
if (!rt_list_isempty(&pipe->suspended_write_list))
{
rt_thread_t thread;
RT_ASSERT(pipe->flag & RT_PIPE_FLAG_BLOCK_WR);
/* get suspended thread */
thread = RT_THREAD_LIST_NODE_ENTRY(pipe->suspended_write_list.next);
/* resume the write thread */
rt_thread_resume(thread);
rt_schedule();
}
}
static rt_ssize_t rt_audio_pipe_read(rt_device_t dev,
rt_off_t pos,
void *buffer,
rt_size_t size)
{
rt_base_t level;
rt_thread_t thread;
struct rt_audio_pipe *pipe;
rt_size_t read_nbytes;
pipe = (struct rt_audio_pipe *)dev;
RT_ASSERT(pipe != RT_NULL);
if (!(pipe->flag & RT_PIPE_FLAG_BLOCK_RD))
{
level = rt_hw_interrupt_disable();
read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), (rt_uint8_t *)buffer, size);
/* if the ringbuffer is empty, there won't be any writer waiting */
if (read_nbytes)
_rt_audio_pipe_resume_writer(pipe);
rt_hw_interrupt_enable(level);
return read_nbytes;
}
thread = rt_thread_self();
/* current context checking */
RT_DEBUG_NOT_IN_INTERRUPT;
do
{
level = rt_hw_interrupt_disable();
read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), (rt_uint8_t *)buffer, size);
if (read_nbytes == 0)
{
rt_thread_suspend(thread);
/* waiting on suspended read list */
rt_list_insert_before(&(pipe->suspended_read_list),
&RT_THREAD_LIST_NODE(thread));
rt_hw_interrupt_enable(level);
rt_schedule();
}
else
{
_rt_audio_pipe_resume_writer(pipe);
rt_hw_interrupt_enable(level);
break;
}
}
while (read_nbytes == 0);
return read_nbytes;
}
static void _rt_audio_pipe_resume_reader(struct rt_audio_pipe *pipe)
{
if (pipe->parent.rx_indicate)
pipe->parent.rx_indicate(&pipe->parent,
rt_ringbuffer_data_len(&pipe->ringbuffer));
if (!rt_list_isempty(&pipe->suspended_read_list))
{
rt_thread_t thread;
RT_ASSERT(pipe->flag & RT_PIPE_FLAG_BLOCK_RD);
/* get suspended thread */
thread = RT_THREAD_LIST_NODE_ENTRY(pipe->suspended_read_list.next);
/* resume the read thread */
rt_thread_resume(thread);
rt_schedule();
}
}
static rt_ssize_t rt_audio_pipe_write(rt_device_t dev,
rt_off_t pos,
const void *buffer,
rt_size_t size)
{
rt_base_t level;
rt_thread_t thread;
struct rt_audio_pipe *pipe;
rt_size_t write_nbytes;
pipe = (struct rt_audio_pipe *)dev;
RT_ASSERT(pipe != RT_NULL);
if ((pipe->flag & RT_PIPE_FLAG_FORCE_WR) ||
!(pipe->flag & RT_PIPE_FLAG_BLOCK_WR))
{
level = rt_hw_interrupt_disable();
if (pipe->flag & RT_PIPE_FLAG_FORCE_WR)
write_nbytes = rt_ringbuffer_put_force(&(pipe->ringbuffer),
(const rt_uint8_t *)buffer, size);
else
write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer),
(const rt_uint8_t *)buffer, size);
_rt_audio_pipe_resume_reader(pipe);
rt_hw_interrupt_enable(level);
return write_nbytes;
}
thread = rt_thread_self();
/* current context checking */
RT_DEBUG_NOT_IN_INTERRUPT;
do
{
level = rt_hw_interrupt_disable();
write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), (const rt_uint8_t *)buffer, size);
if (write_nbytes == 0)
{
/* pipe full, waiting on suspended write list */
rt_thread_suspend(thread);
/* waiting on suspended read list */
rt_list_insert_before(&(pipe->suspended_write_list),
&RT_THREAD_LIST_NODE(thread));
rt_hw_interrupt_enable(level);
rt_schedule();
}
else
{
_rt_audio_pipe_resume_reader(pipe);
rt_hw_interrupt_enable(level);
break;
}
}
while (write_nbytes == 0);
return write_nbytes;
}
static rt_err_t rt_audio_pipe_control(rt_device_t dev, int cmd, void *args)
{
struct rt_audio_pipe *pipe;
pipe = (struct rt_audio_pipe *)dev;
if (cmd == PIPE_CTRL_GET_SPACE && args)
*(rt_size_t *)args = rt_ringbuffer_space_len(&pipe->ringbuffer);
return RT_EOK;
}
#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops audio_pipe_ops =
{
RT_NULL,
RT_NULL,
RT_NULL,
rt_audio_pipe_read,
rt_audio_pipe_write,
rt_audio_pipe_control
};
#endif
/**
* This function will initialize a pipe device and put it under control of
* resource management.
*
* @param pipe the pipe device
* @param name the name of pipe device
* @param flag the attribute of the pipe device
* @param buf the buffer of pipe device
* @param size the size of pipe device buffer
*
* @return the operation status, RT_EOK on successful
*/
rt_err_t rt_audio_pipe_init(struct rt_audio_pipe *pipe,
const char *name,
rt_int32_t flag,
rt_uint8_t *buf,
rt_size_t size)
{
RT_ASSERT(pipe);
RT_ASSERT(buf);
/* initialize suspended list */
rt_list_init(&pipe->suspended_read_list);
rt_list_init(&pipe->suspended_write_list);
/* initialize ring buffer */
rt_ringbuffer_init(&pipe->ringbuffer, buf, size);
pipe->flag = flag;
/* create pipe */
pipe->parent.type = RT_Device_Class_Pipe;
#ifdef RT_USING_DEVICE_OPS
pipe->parent.ops = &audio_pipe_ops;
#else
pipe->parent.init = RT_NULL;
pipe->parent.open = RT_NULL;
pipe->parent.close = RT_NULL;
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);
}
/**
* This function will detach a pipe device from resource management
*
* @param pipe the pipe device
*
* @return the operation status, RT_EOK on successful
*/
rt_err_t rt_audio_pipe_detach(struct rt_audio_pipe *pipe)
{
return rt_device_unregister(&pipe->parent);
}
#ifdef RT_USING_HEAP
rt_err_t rt_audio_pipe_create(const char *name, rt_int32_t flag, rt_size_t size)
{
rt_uint8_t *rb_memptr = RT_NULL;
struct rt_audio_pipe *pipe = RT_NULL;
/* get aligned size */
size = RT_ALIGN(size, RT_ALIGN_SIZE);
pipe = (struct rt_audio_pipe *)rt_calloc(1, sizeof(struct rt_audio_pipe));
if (pipe == RT_NULL)
return -RT_ENOMEM;
/* create ring buffer of pipe */
rb_memptr = (rt_uint8_t *)rt_malloc(size);
if (rb_memptr == RT_NULL)
{
rt_free(pipe);
return -RT_ENOMEM;
}
return rt_audio_pipe_init(pipe, name, flag, rb_memptr, size);
}
void rt_audio_pipe_destroy(struct rt_audio_pipe *pipe)
{
if (pipe == RT_NULL)
return;
/* un-register pipe device */
rt_audio_pipe_detach(pipe);
/* release memory */
rt_free(pipe->ringbuffer.buffer_ptr);
rt_free(pipe);
return;
}
#endif /* RT_USING_HEAP */

View File

@ -1,75 +0,0 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#ifndef __DEV_AUDIO_PIPE_H__
#define __DEV_AUDIO_PIPE_H__
/**
* Pipe Device
*/
#include <rtdevice.h>
#ifndef RT_PIPE_BUFSZ
#define PIPE_BUFSZ 512
#else
#define PIPE_BUFSZ RT_PIPE_BUFSZ
#endif
/* portal device */
struct rt_audio_portal_device
{
struct rt_device parent;
struct rt_device *write_dev;
struct rt_device *read_dev;
};
enum rt_audio_pipe_flag
{
/* both read and write won't block */
RT_PIPE_FLAG_NONBLOCK_RDWR = 0x00,
/* read would block */
RT_PIPE_FLAG_BLOCK_RD = 0x01,
/* write would block */
RT_PIPE_FLAG_BLOCK_WR = 0x02,
/* write to this pipe will discard some data when the pipe is full.
* When this flag is set, RT_PIPE_FLAG_BLOCK_WR will be ignored since write
* operation will always be success. */
RT_PIPE_FLAG_FORCE_WR = 0x04,
};
struct rt_audio_pipe
{
struct rt_device parent;
/* ring buffer in pipe device */
struct rt_ringbuffer ringbuffer;
rt_int32_t flag;
/* suspended list */
rt_list_t suspended_read_list;
rt_list_t suspended_write_list;
struct rt_audio_portal_device *write_portal;
struct rt_audio_portal_device *read_portal;
};
#define PIPE_CTRL_GET_SPACE 0x14 /**< get the remaining size of a pipe device */
rt_err_t rt_audio_pipe_init(struct rt_audio_pipe *pipe,
const char *name,
rt_int32_t flag,
rt_uint8_t *buf,
rt_size_t size);
rt_err_t rt_audio_pipe_detach(struct rt_audio_pipe *pipe);
#ifdef RT_USING_HEAP
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 /* __DEV_AUDIO_PIPE_H__ */

View File

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

View File

@ -1,23 +0,0 @@
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

@ -1,573 +0,0 @@
/*
* 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

@ -1,297 +0,0 @@
/*
* 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

@ -1,49 +0,0 @@
/*
* 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

@ -1,274 +0,0 @@
/*
* 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

@ -1,23 +0,0 @@
/*
* 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

@ -1,154 +0,0 @@
/*
* 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

@ -1,22 +0,0 @@
/*
* 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

@ -1,12 +0,0 @@
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

@ -1,18 +0,0 @@
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

@ -1,55 +0,0 @@
/*
* 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

@ -1,738 +0,0 @@
/*
* 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

@ -1,141 +0,0 @@
/*
* 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,974 +0,0 @@
/*
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-05-14 aubrcool@qq.com first version
* 2015-07-06 Bernard code cleanup and remove RT_CAN_USING_LED;
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#define CAN_LOCK(can) rt_mutex_take(&(can->lock), RT_WAITING_FOREVER)
#define CAN_UNLOCK(can) rt_mutex_release(&(can->lock))
static rt_err_t rt_can_init(struct rt_device *dev)
{
rt_err_t result = RT_EOK;
struct rt_can_device *can;
RT_ASSERT(dev != RT_NULL);
can = (struct rt_can_device *)dev;
/* initialize rx/tx */
can->can_rx = RT_NULL;
can->can_tx = RT_NULL;
#ifdef RT_CAN_USING_HDR
can->hdr = RT_NULL;
#endif
/* apply configuration */
if (can->ops->configure)
result = can->ops->configure(can, &can->config);
else
result = -RT_ENOSYS;
return result;
}
/*
* can interrupt routines
*/
rt_inline rt_ssize_t _can_int_rx(struct rt_can_device *can, struct rt_can_msg *data, rt_ssize_t msgs)
{
rt_ssize_t size;
struct rt_can_rx_fifo *rx_fifo;
RT_ASSERT(can != RT_NULL);
size = msgs;
rx_fifo = (struct rt_can_rx_fifo *) can->can_rx;
RT_ASSERT(rx_fifo != RT_NULL);
/* read from software FIFO */
while (msgs / sizeof(struct rt_can_msg) > 0)
{
rt_base_t level;
#ifdef RT_CAN_USING_HDR
rt_int8_t hdr;
#endif /*RT_CAN_USING_HDR*/
struct rt_can_msg_list *listmsg = RT_NULL;
/* disable interrupt */
level = rt_hw_interrupt_disable();
#ifdef RT_CAN_USING_HDR
hdr = data->hdr_index;
if (hdr >= 0 && can->hdr && hdr < can->config.maxhdr && !rt_list_isempty(&can->hdr[hdr].list))
{
listmsg = rt_list_entry(can->hdr[hdr].list.next, struct rt_can_msg_list, hdrlist);
rt_list_remove(&listmsg->list);
rt_list_remove(&listmsg->hdrlist);
if (can->hdr[hdr].msgs)
{
can->hdr[hdr].msgs--;
}
listmsg->owner = RT_NULL;
}
else if (hdr == -1)
#endif /*RT_CAN_USING_HDR*/
{
if (!rt_list_isempty(&rx_fifo->uselist))
{
listmsg = rt_list_entry(rx_fifo->uselist.next, struct rt_can_msg_list, list);
rt_list_remove(&listmsg->list);
#ifdef RT_CAN_USING_HDR
rt_list_remove(&listmsg->hdrlist);
if (listmsg->owner != RT_NULL && listmsg->owner->msgs)
{
listmsg->owner->msgs--;
}
listmsg->owner = RT_NULL;
#endif /*RT_CAN_USING_HDR*/
}
else
{
/* no data, enable interrupt and break out */
rt_hw_interrupt_enable(level);
break;
}
}
/* enable interrupt */
rt_hw_interrupt_enable(level);
if (listmsg != RT_NULL)
{
rt_memcpy(data, &listmsg->data, sizeof(struct rt_can_msg));
level = rt_hw_interrupt_disable();
rt_list_insert_before(&rx_fifo->freelist, &listmsg->list);
rx_fifo->freenumbers++;
RT_ASSERT(rx_fifo->freenumbers <= can->config.msgboxsz);
rt_hw_interrupt_enable(level);
listmsg = RT_NULL;
}
else
{
break;
}
data ++;
msgs -= sizeof(struct rt_can_msg);
}
return (size - msgs);
}
rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *data, int msgs)
{
int size;
struct rt_can_tx_fifo *tx_fifo;
RT_ASSERT(can != RT_NULL);
size = msgs;
tx_fifo = (struct rt_can_tx_fifo *) can->can_tx;
RT_ASSERT(tx_fifo != RT_NULL);
while (msgs)
{
rt_base_t level;
rt_uint32_t no;
rt_uint32_t result;
struct rt_can_sndbxinx_list *tx_tosnd = RT_NULL;
rt_sem_take(&(tx_fifo->sem), RT_WAITING_FOREVER);
level = rt_hw_interrupt_disable();
tx_tosnd = rt_list_entry(tx_fifo->freelist.next, struct rt_can_sndbxinx_list, list);
RT_ASSERT(tx_tosnd != RT_NULL);
rt_list_remove(&tx_tosnd->list);
rt_hw_interrupt_enable(level);
no = ((rt_ubase_t)tx_tosnd - (rt_ubase_t)tx_fifo->buffer) / sizeof(struct rt_can_sndbxinx_list);
tx_tosnd->result = RT_CAN_SND_RESULT_WAIT;
rt_completion_init(&tx_tosnd->completion);
if (can->ops->sendmsg(can, data, no) != RT_EOK)
{
/* send failed. */
level = rt_hw_interrupt_disable();
rt_list_insert_before(&tx_fifo->freelist, &tx_tosnd->list);
rt_hw_interrupt_enable(level);
rt_sem_release(&(tx_fifo->sem));
goto err_ret;
}
can->status.sndchange = 1;
rt_completion_wait(&(tx_tosnd->completion), RT_WAITING_FOREVER);
level = rt_hw_interrupt_disable();
result = tx_tosnd->result;
if (!rt_list_isempty(&tx_tosnd->list))
{
rt_list_remove(&tx_tosnd->list);
}
rt_list_insert_before(&tx_fifo->freelist, &tx_tosnd->list);
rt_hw_interrupt_enable(level);
rt_sem_release(&(tx_fifo->sem));
if (result == RT_CAN_SND_RESULT_OK)
{
level = rt_hw_interrupt_disable();
can->status.sndpkg++;
rt_hw_interrupt_enable(level);
data ++;
msgs -= sizeof(struct rt_can_msg);
if (!msgs) break;
}
else
{
err_ret:
level = rt_hw_interrupt_disable();
can->status.dropedsndpkg++;
rt_hw_interrupt_enable(level);
break;
}
}
return (size - msgs);
}
rt_inline int _can_int_tx_priv(struct rt_can_device *can, const struct rt_can_msg *data, int msgs)
{
int size;
rt_base_t level;
rt_uint32_t no, result;
struct rt_can_tx_fifo *tx_fifo;
RT_ASSERT(can != RT_NULL);
size = msgs;
tx_fifo = (struct rt_can_tx_fifo *) can->can_tx;
RT_ASSERT(tx_fifo != RT_NULL);
while (msgs)
{
no = data->priv;
if (no >= can->config.sndboxnumber)
{
break;
}
level = rt_hw_interrupt_disable();
if ((tx_fifo->buffer[no].result != RT_CAN_SND_RESULT_OK))
{
rt_hw_interrupt_enable(level);
rt_completion_wait(&(tx_fifo->buffer[no].completion), RT_WAITING_FOREVER);
continue;
}
tx_fifo->buffer[no].result = RT_CAN_SND_RESULT_WAIT;
rt_hw_interrupt_enable(level);
if (can->ops->sendmsg(can, data, no) != RT_EOK)
{
continue;
}
can->status.sndchange = 1;
rt_completion_wait(&(tx_fifo->buffer[no].completion), RT_WAITING_FOREVER);
result = tx_fifo->buffer[no].result;
if (result == RT_CAN_SND_RESULT_OK)
{
level = rt_hw_interrupt_disable();
can->status.sndpkg++;
rt_hw_interrupt_enable(level);
data ++;
msgs -= sizeof(struct rt_can_msg);
if (!msgs) break;
}
else
{
level = rt_hw_interrupt_disable();
can->status.dropedsndpkg++;
rt_hw_interrupt_enable(level);
break;
}
}
return (size - msgs);
}
static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag)
{
struct rt_can_device *can;
char tmpname[16];
RT_ASSERT(dev != RT_NULL);
can = (struct rt_can_device *)dev;
CAN_LOCK(can);
/* get open flags */
dev->open_flag = oflag & 0xff;
if (can->can_rx == RT_NULL)
{
if (oflag & RT_DEVICE_FLAG_INT_RX)
{
int i = 0;
struct rt_can_rx_fifo *rx_fifo;
rx_fifo = (struct rt_can_rx_fifo *) rt_malloc(sizeof(struct rt_can_rx_fifo) +
can->config.msgboxsz * sizeof(struct rt_can_msg_list));
RT_ASSERT(rx_fifo != RT_NULL);
rx_fifo->buffer = (struct rt_can_msg_list *)(rx_fifo + 1);
rt_memset(rx_fifo->buffer, 0, can->config.msgboxsz * sizeof(struct rt_can_msg_list));
rt_list_init(&rx_fifo->freelist);
rt_list_init(&rx_fifo->uselist);
rx_fifo->freenumbers = can->config.msgboxsz;
for (i = 0; i < can->config.msgboxsz; i++)
{
rt_list_insert_before(&rx_fifo->freelist, &rx_fifo->buffer[i].list);
#ifdef RT_CAN_USING_HDR
rt_list_init(&rx_fifo->buffer[i].hdrlist);
rx_fifo->buffer[i].owner = RT_NULL;
#endif
}
can->can_rx = rx_fifo;
dev->open_flag |= RT_DEVICE_FLAG_INT_RX;
/* open can rx interrupt */
can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
}
}
if (can->can_tx == RT_NULL)
{
if (oflag & RT_DEVICE_FLAG_INT_TX)
{
int i = 0;
struct rt_can_tx_fifo *tx_fifo;
tx_fifo = (struct rt_can_tx_fifo *) rt_malloc(sizeof(struct rt_can_tx_fifo) +
can->config.sndboxnumber * sizeof(struct rt_can_sndbxinx_list));
RT_ASSERT(tx_fifo != RT_NULL);
tx_fifo->buffer = (struct rt_can_sndbxinx_list *)(tx_fifo + 1);
rt_memset(tx_fifo->buffer, 0,
can->config.sndboxnumber * sizeof(struct rt_can_sndbxinx_list));
rt_list_init(&tx_fifo->freelist);
for (i = 0; i < can->config.sndboxnumber; i++)
{
rt_list_insert_before(&tx_fifo->freelist, &tx_fifo->buffer[i].list);
rt_completion_init(&(tx_fifo->buffer[i].completion));
tx_fifo->buffer[i].result = RT_CAN_SND_RESULT_OK;
}
rt_sprintf(tmpname, "%stl", dev->parent.name);
rt_sem_init(&(tx_fifo->sem), tmpname, can->config.sndboxnumber, RT_IPC_FLAG_FIFO);
can->can_tx = tx_fifo;
dev->open_flag |= RT_DEVICE_FLAG_INT_TX;
/* open can tx interrupt */
can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_TX);
}
}
can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_CAN_INT_ERR);
#ifdef RT_CAN_USING_HDR
if (can->hdr == RT_NULL)
{
int i = 0;
struct rt_can_hdr *phdr;
phdr = (struct rt_can_hdr *) rt_malloc(can->config.maxhdr * sizeof(struct rt_can_hdr));
RT_ASSERT(phdr != RT_NULL);
rt_memset(phdr, 0, can->config.maxhdr * sizeof(struct rt_can_hdr));
for (i = 0; i < can->config.maxhdr; i++)
{
rt_list_init(&phdr[i].list);
}
can->hdr = phdr;
}
#endif
if (!can->timerinitflag)
{
can->timerinitflag = 1;
rt_timer_start(&can->timer);
}
CAN_UNLOCK(can);
return RT_EOK;
}
static rt_err_t rt_can_close(struct rt_device *dev)
{
struct rt_can_device *can;
RT_ASSERT(dev != RT_NULL);
can = (struct rt_can_device *)dev;
CAN_LOCK(can);
/* this device has more reference count */
if (dev->ref_count > 1)
{
CAN_UNLOCK(can);
return RT_EOK;
}
if (can->timerinitflag)
{
can->timerinitflag = 0;
rt_timer_stop(&can->timer);
}
can->status_indicate.ind = RT_NULL;
can->status_indicate.args = RT_NULL;
#ifdef RT_CAN_USING_HDR
if (can->hdr != RT_NULL)
{
rt_free(can->hdr);
can->hdr = RT_NULL;
}
#endif
if (dev->open_flag & RT_DEVICE_FLAG_INT_RX)
{
struct rt_can_rx_fifo *rx_fifo;
/* clear can rx interrupt */
can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX);
rx_fifo = (struct rt_can_rx_fifo *)can->can_rx;
RT_ASSERT(rx_fifo != RT_NULL);
rt_free(rx_fifo);
dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX;
can->can_rx = RT_NULL;
}
if (dev->open_flag & RT_DEVICE_FLAG_INT_TX)
{
struct rt_can_tx_fifo *tx_fifo;
/* clear can tx interrupt */
can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_TX);
tx_fifo = (struct rt_can_tx_fifo *)can->can_tx;
RT_ASSERT(tx_fifo != RT_NULL);
rt_sem_detach(&(tx_fifo->sem));
rt_free(tx_fifo);
dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX;
can->can_tx = RT_NULL;
}
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;
}
static rt_ssize_t rt_can_read(struct rt_device *dev,
rt_off_t pos,
void *buffer,
rt_size_t size)
{
struct rt_can_device *can;
RT_ASSERT(dev != RT_NULL);
if (size == 0) return 0;
can = (struct rt_can_device *)dev;
if ((dev->open_flag & RT_DEVICE_FLAG_INT_RX) && (dev->ref_count > 0))
{
return _can_int_rx(can, buffer, size);
}
return 0;
}
static rt_ssize_t rt_can_write(struct rt_device *dev,
rt_off_t pos,
const void *buffer,
rt_size_t size)
{
struct rt_can_device *can;
RT_ASSERT(dev != RT_NULL);
if (size == 0) return 0;
can = (struct rt_can_device *)dev;
if ((dev->open_flag & RT_DEVICE_FLAG_INT_TX) && (dev->ref_count > 0))
{
if (can->config.privmode)
{
return _can_int_tx_priv(can, buffer, size);
}
else
{
return _can_int_tx(can, buffer, size);
}
}
return 0;
}
static rt_err_t rt_can_control(struct rt_device *dev,
int cmd,
void *args)
{
struct rt_can_device *can;
rt_err_t res;
res = RT_EOK;
RT_ASSERT(dev != RT_NULL);
can = (struct rt_can_device *)dev;
switch (cmd)
{
case RT_DEVICE_CTRL_SUSPEND:
/* suspend device */
dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
break;
case RT_DEVICE_CTRL_RESUME:
/* resume device */
dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
break;
case RT_DEVICE_CTRL_CONFIG:
/* configure device */
res = can->ops->configure(can, (struct can_configure *)args);
break;
case RT_CAN_CMD_SET_PRIV:
/* configure device */
if ((rt_uint32_t)(rt_ubase_t)args != can->config.privmode)
{
int i;
rt_base_t level;
struct rt_can_tx_fifo *tx_fifo;
res = can->ops->control(can, cmd, args);
if (res != RT_EOK) return res;
tx_fifo = (struct rt_can_tx_fifo *) can->can_tx;
if (can->config.privmode)
{
for (i = 0; i < can->config.sndboxnumber; i++)
{
level = rt_hw_interrupt_disable();
if(rt_list_isempty(&tx_fifo->buffer[i].list))
{
rt_sem_release(&(tx_fifo->sem));
}
else
{
rt_list_remove(&tx_fifo->buffer[i].list);
}
rt_hw_interrupt_enable(level);
}
}
else
{
for (i = 0; i < can->config.sndboxnumber; i++)
{
level = rt_hw_interrupt_disable();
if (tx_fifo->buffer[i].result == RT_CAN_SND_RESULT_OK)
{
rt_list_insert_before(&tx_fifo->freelist, &tx_fifo->buffer[i].list);
}
rt_hw_interrupt_enable(level);
}
}
}
break;
case RT_CAN_CMD_SET_STATUS_IND:
can->status_indicate.ind = ((rt_can_status_ind_type_t)args)->ind;
can->status_indicate.args = ((rt_can_status_ind_type_t)args)->args;
break;
#ifdef RT_CAN_USING_HDR
case RT_CAN_CMD_SET_FILTER:
res = can->ops->control(can, cmd, args);
if (res != RT_EOK || can->hdr == RT_NULL)
{
return res;
}
struct rt_can_filter_config *pfilter;
struct rt_can_filter_item *pitem;
rt_uint32_t count;
rt_base_t level;
pfilter = (struct rt_can_filter_config *)args;
RT_ASSERT(pfilter);
count = pfilter->count;
pitem = pfilter->items;
if (pfilter->actived)
{
while (count)
{
if (pitem->hdr_bank >= can->config.maxhdr || pitem->hdr_bank < 0)
{
count--;
pitem++;
continue;
}
level = rt_hw_interrupt_disable();
if (!can->hdr[pitem->hdr_bank].connected)
{
rt_hw_interrupt_enable(level);
rt_memcpy(&can->hdr[pitem->hdr_bank].filter, pitem,
sizeof(struct rt_can_filter_item));
level = rt_hw_interrupt_disable();
can->hdr[pitem->hdr_bank].connected = 1;
can->hdr[pitem->hdr_bank].msgs = 0;
rt_list_init(&can->hdr[pitem->hdr_bank].list);
}
rt_hw_interrupt_enable(level);
count--;
pitem++;
}
}
else
{
while (count)
{
if (pitem->hdr_bank >= can->config.maxhdr || pitem->hdr_bank < 0)
{
count--;
pitem++;
continue;
}
level = rt_hw_interrupt_disable();
if (can->hdr[pitem->hdr_bank].connected)
{
can->hdr[pitem->hdr_bank].connected = 0;
can->hdr[pitem->hdr_bank].msgs = 0;
if (!rt_list_isempty(&can->hdr[pitem->hdr_bank].list))
{
rt_list_remove(can->hdr[pitem->hdr_bank].list.next);
}
rt_hw_interrupt_enable(level);
rt_memset(&can->hdr[pitem->hdr_bank].filter, 0,
sizeof(struct rt_can_filter_item));
}
else
{
rt_hw_interrupt_enable(level);
}
count--;
pitem++;
}
}
break;
#endif /*RT_CAN_USING_HDR*/
#ifdef RT_CAN_USING_BUS_HOOK
case RT_CAN_CMD_SET_BUS_HOOK:
can->bus_hook = (rt_can_bus_hook) args;
break;
#endif /*RT_CAN_USING_BUS_HOOK*/
default :
/* control device */
if (can->ops->control != RT_NULL)
{
res = can->ops->control(can, cmd, args);
}
else
{
res = -RT_ENOSYS;
}
break;
}
return res;
}
/*
* can timer
*/
static void cantimeout(void *arg)
{
rt_can_t can;
can = (rt_can_t)arg;
RT_ASSERT(can);
rt_device_control((rt_device_t)can, RT_CAN_CMD_GET_STATUS, (void *)&can->status);
if (can->status_indicate.ind != RT_NULL)
{
can->status_indicate.ind(can, can->status_indicate.args);
}
#ifdef RT_CAN_USING_BUS_HOOK
if(can->bus_hook)
{
can->bus_hook(can);
}
#endif /*RT_CAN_USING_BUS_HOOK*/
if (can->timerinitflag == 1)
{
can->timerinitflag = 0xFF;
}
}
#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops can_device_ops =
{
rt_can_init,
rt_can_open,
rt_can_close,
rt_can_read,
rt_can_write,
rt_can_control
};
#endif
/*
* can register
*/
rt_err_t rt_hw_can_register(struct rt_can_device *can,
const char *name,
const struct rt_can_ops *ops,
void *data)
{
struct rt_device *device;
RT_ASSERT(can != RT_NULL);
device = &(can->parent);
device->type = RT_Device_Class_CAN;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
#ifdef RT_CAN_USING_HDR
can->hdr = RT_NULL;
#endif
can->can_rx = RT_NULL;
can->can_tx = RT_NULL;
rt_mutex_init(&(can->lock), "can", RT_IPC_FLAG_PRIO);
#ifdef RT_CAN_USING_BUS_HOOK
can->bus_hook = RT_NULL;
#endif /*RT_CAN_USING_BUS_HOOK*/
#ifdef RT_USING_DEVICE_OPS
device->ops = &can_device_ops;
#else
device->init = rt_can_init;
device->open = rt_can_open;
device->close = rt_can_close;
device->read = rt_can_read;
device->write = rt_can_write;
device->control = rt_can_control;
#endif
can->ops = ops;
can->status_indicate.ind = RT_NULL;
can->status_indicate.args = RT_NULL;
rt_memset(&can->status, 0, sizeof(can->status));
device->user_data = data;
can->timerinitflag = 0;
rt_timer_init(&can->timer,
name,
cantimeout,
(void *)can,
can->config.ticks,
RT_TIMER_FLAG_PERIODIC);
/* register a character device */
return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
}
/* ISR for can interrupt */
void rt_hw_can_isr(struct rt_can_device *can, int event)
{
switch (event & 0xff)
{
case RT_CAN_EVENT_RXOF_IND:
{
rt_base_t level;
level = rt_hw_interrupt_disable();
can->status.dropedrcvpkg++;
rt_hw_interrupt_enable(level);
}
case RT_CAN_EVENT_RX_IND:
{
struct rt_can_msg tmpmsg;
struct rt_can_rx_fifo *rx_fifo;
struct rt_can_msg_list *listmsg = RT_NULL;
#ifdef RT_CAN_USING_HDR
rt_int8_t hdr;
#endif
int ch = -1;
rt_base_t level;
rt_uint32_t no;
rx_fifo = (struct rt_can_rx_fifo *)can->can_rx;
RT_ASSERT(rx_fifo != RT_NULL);
/* interrupt mode receive */
RT_ASSERT(can->parent.open_flag & RT_DEVICE_FLAG_INT_RX);
no = event >> 8;
ch = can->ops->recvmsg(can, &tmpmsg, no);
if (ch == -1) break;
/* disable interrupt */
level = rt_hw_interrupt_disable();
can->status.rcvpkg++;
can->status.rcvchange = 1;
if (!rt_list_isempty(&rx_fifo->freelist))
{
listmsg = rt_list_entry(rx_fifo->freelist.next, struct rt_can_msg_list, list);
rt_list_remove(&listmsg->list);
#ifdef RT_CAN_USING_HDR
rt_list_remove(&listmsg->hdrlist);
if (listmsg->owner != RT_NULL && listmsg->owner->msgs)
{
listmsg->owner->msgs--;
}
listmsg->owner = RT_NULL;
#endif /*RT_CAN_USING_HDR*/
RT_ASSERT(rx_fifo->freenumbers > 0);
rx_fifo->freenumbers--;
}
else if (!rt_list_isempty(&rx_fifo->uselist))
{
listmsg = rt_list_entry(rx_fifo->uselist.next, struct rt_can_msg_list, list);
can->status.dropedrcvpkg++;
rt_list_remove(&listmsg->list);
#ifdef RT_CAN_USING_HDR
rt_list_remove(&listmsg->hdrlist);
if (listmsg->owner != RT_NULL && listmsg->owner->msgs)
{
listmsg->owner->msgs--;
}
listmsg->owner = RT_NULL;
#endif
}
/* enable interrupt */
rt_hw_interrupt_enable(level);
if (listmsg != RT_NULL)
{
rt_memcpy(&listmsg->data, &tmpmsg, sizeof(struct rt_can_msg));
level = rt_hw_interrupt_disable();
rt_list_insert_before(&rx_fifo->uselist, &listmsg->list);
#ifdef RT_CAN_USING_HDR
hdr = tmpmsg.hdr_index;
if (can->hdr != RT_NULL)
{
RT_ASSERT(hdr < can->config.maxhdr && hdr >= 0);
if (can->hdr[hdr].connected)
{
rt_list_insert_before(&can->hdr[hdr].list, &listmsg->hdrlist);
listmsg->owner = &can->hdr[hdr];
can->hdr[hdr].msgs++;
}
}
#endif
rt_hw_interrupt_enable(level);
}
/* invoke callback */
#ifdef RT_CAN_USING_HDR
if (can->hdr != RT_NULL && can->hdr[hdr].connected && can->hdr[hdr].filter.ind)
{
rt_size_t rx_length;
RT_ASSERT(hdr < can->config.maxhdr && hdr >= 0);
level = rt_hw_interrupt_disable();
rx_length = can->hdr[hdr].msgs * sizeof(struct rt_can_msg);
rt_hw_interrupt_enable(level);
if (rx_length)
{
can->hdr[hdr].filter.ind(&can->parent, can->hdr[hdr].filter.args, hdr, rx_length);
}
}
else
#endif
{
if (can->parent.rx_indicate != RT_NULL)
{
rt_size_t rx_length;
level = rt_hw_interrupt_disable();
/* get rx length */
rx_length = rt_list_len(&rx_fifo->uselist)* sizeof(struct rt_can_msg);
rt_hw_interrupt_enable(level);
if (rx_length)
{
can->parent.rx_indicate(&can->parent, rx_length);
}
}
}
break;
}
case RT_CAN_EVENT_TX_DONE:
case RT_CAN_EVENT_TX_FAIL:
{
struct rt_can_tx_fifo *tx_fifo;
rt_uint32_t no;
no = event >> 8;
tx_fifo = (struct rt_can_tx_fifo *) can->can_tx;
RT_ASSERT(tx_fifo != RT_NULL);
if ((event & 0xff) == RT_CAN_EVENT_TX_DONE)
{
tx_fifo->buffer[no].result = RT_CAN_SND_RESULT_OK;
}
else
{
tx_fifo->buffer[no].result = RT_CAN_SND_RESULT_ERR;
}
rt_completion_done(&(tx_fifo->buffer[no].completion));
break;
}
}
}
#ifdef RT_USING_FINSH
#include <finsh.h>
int cmd_canstat(int argc, void **argv)
{
static const char *ErrCode[] =
{
"No Error!",
"Warning !",
"Passive !",
"Bus Off !"
};
if (argc >= 2)
{
struct rt_can_status status;
rt_device_t candev = rt_device_find(argv[1]);
if (!candev)
{
rt_kprintf(" Can't find can device %s\n", argv[1]);
return -1;
}
rt_kprintf(" Found can device: %s...", argv[1]);
rt_device_control(candev, RT_CAN_CMD_GET_STATUS, &status);
rt_kprintf("\n Receive...error..count: %010ld. Send.....error....count: %010ld.",
status.rcverrcnt, status.snderrcnt);
rt_kprintf("\n Bit..pad..error..count: %010ld. Format...error....count: %010ld",
status.bitpaderrcnt, status.formaterrcnt);
rt_kprintf("\n Ack.......error..count: %010ld. Bit......error....count: %010ld.",
status.ackerrcnt, status.biterrcnt);
rt_kprintf("\n CRC.......error..count: %010ld. Error.code.[%010ld]: ",
status.crcerrcnt, status.errcode);
switch (status.errcode)
{
case 0:
rt_kprintf("%s.", ErrCode[0]);
break;
case 1:
rt_kprintf("%s.", ErrCode[1]);
break;
case 2:
case 3:
rt_kprintf("%s.", ErrCode[2]);
break;
case 4:
case 5:
case 6:
case 7:
rt_kprintf("%s.", ErrCode[3]);
break;
}
rt_kprintf("\n Total.receive.packages: %010ld. Dropped.receive.packages: %010ld.",
status.rcvpkg, status.dropedrcvpkg);
rt_kprintf("\n Total..send...packages: %010ld. Dropped...send..packages: %010ld.\n",
status.sndpkg + status.dropedsndpkg, status.dropedsndpkg);
}
else
{
rt_kprintf(" Invalid Call %s\n", argv[0]);
rt_kprintf(" Please using %s cannamex .Here canname is driver name and x is candrive number.\n", argv[0]);
}
return 0;
}
MSH_CMD_EXPORT_ALIAS(cmd_canstat, canstat, stat can device status);
#endif

View File

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

View File

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

View File

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

View File

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

View File

@ -53,137 +53,6 @@ void rt_dm_secondary_cpu_init(void)
} }
#endif /* RT_USING_SMP */ #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 struct prefix_track
{ {
rt_list_t list; rt_list_t list;

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