From 416ec66380d89e2d3ff8ea37fd748ccc77130ab2 Mon Sep 17 00:00:00 2001 From: CXSforHPU <156403074+CXSforHPU@users.noreply.github.com> Date: Sat, 24 Aug 2024 06:15:09 +0800 Subject: [device] add dev_ prefix for file names --- bsp/Infineon/libraries/HAL_Drivers/drv_pwm.c | 2 +- bsp/acm32/acm32f0x0-nucleo/applications/main.c | 2 +- bsp/acm32/acm32f0x0-nucleo/drivers/drv_soft_i2c.h | 2 +- bsp/acm32/acm32f4xx-nucleo/applications/main.c | 2 +- bsp/apm32/libraries/Drivers/drv_pwm.c | 2 +- bsp/at32/libraries/rt_drivers/drv_hard_i2c.h | 2 +- bsp/at32/libraries/rt_drivers/drv_pwm.c | 2 +- bsp/cvitek/cv18xx_risc-v/applications/main.c | 2 +- bsp/dm365/drivers/i2c-davinci.c | 2 +- bsp/hc32/libraries/hc32_drivers/drv_pwm.c | 2 +- bsp/hpmicro/hpm6750evk/board/hpm_sgtl5000.h | 2 +- bsp/hpmicro/hpm6750evk2/board/hpm_wm8960.h | 2 +- bsp/hpmicro/hpm6800evk/board/hpm_wm8960.h | 2 +- bsp/hpmicro/libraries/drivers/drv_dao.c | 2 +- bsp/hpmicro/libraries/drivers/drv_i2s.c | 2 +- bsp/hpmicro/libraries/drivers/drv_pdm.c | 2 +- bsp/k210/drivers/drv_i2c.c | 2 +- bsp/loongson/ls1cdev/drivers/drv_gpio.c | 2 +- bsp/loongson/ls1cdev/drivers/drv_i2c.c | 4 +- bsp/loongson/ls2kdev/drivers/drv_gpio.c | 4 +- bsp/loongson/ls2kdev/drivers/drv_spi.c | 2 +- bsp/loongson/ls2kdev/drivers/interrupt.c | 2 +- bsp/maxim/libraries/HAL_Drivers/drv_i2c.c | 2 +- bsp/maxim/libraries/HAL_Drivers/drv_rtc.c | 2 +- bsp/n32g452xx/Libraries/rt_drivers/drv_pwm.h | 2 +- bsp/nxp/imx/imx6ull-smart/drivers/drv_pwm.c | 2 +- bsp/nxp/imx/imxrt/libraries/drivers/drv_sai.c | 2 +- .../lpc55sxx/Libraries/drivers/drv_sound_wm8904.c | 4 +- bsp/phytium/libraries/drivers/drv_i2c.c | 2 +- bsp/renesas/ra6m3-hmi-board/board/ports/can_test.c | 2 +- bsp/stm32/libraries/HAL_Drivers/drivers/drv_pwm.c | 2 +- .../board/ports/touch/drv_touch.c | 2 +- bsp/w60x/drivers/drv_rtc.h | 2 +- bsp/wch/risc-v/Libraries/ch32_drivers/drv_pwm.h | 2 +- .../risc-v/Libraries/ch56x_drivers/ch56x_gpio.c | 2 +- bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pwm.c | 4 +- bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_spi.c | 2 +- .../risc-v/Libraries/ch56x_drivers/ch56x_uart.c | 2 +- bsp/wch/risc-v/ch32v103r-evt/board/board.h | 2 +- bsp/wch/risc-v/ch32v208w-r0/applications/main.c | 2 +- bsp/wch/risc-v/ch569w-evt/applications/main.c | 2 +- bsp/wch/risc-v/ch569w-evt/applications/test.c | 4 +- bsp/wch/risc-v/ch569w-evt/board/board.c | 2 +- components/drivers/audio/audio.c | 612 ------------- components/drivers/audio/audio_pipe.c | 296 ------- components/drivers/audio/audio_pipe.h | 75 -- components/drivers/audio/dev_audio.c | 612 +++++++++++++ components/drivers/audio/dev_audio_pipe.c | 296 +++++++ components/drivers/audio/dev_audio_pipe.h | 75 ++ components/drivers/can/can.c | 974 --------------------- components/drivers/can/dev_can.c | 974 +++++++++++++++++++++ components/drivers/i2c/SConscript | 10 +- components/drivers/i2c/dev_i2c_bit_ops.c | 464 ++++++++++ components/drivers/i2c/dev_i2c_bus.c | 182 ++++ components/drivers/i2c/dev_i2c_core.c | 153 ++++ components/drivers/i2c/dev_i2c_dev.c | 137 +++ components/drivers/i2c/dev_i2c_dm.c | 50 ++ components/drivers/i2c/dev_soft_i2c.c | 264 ++++++ components/drivers/i2c/i2c-bit-ops.c | 464 ---------- components/drivers/i2c/i2c_bus.c | 182 ---- components/drivers/i2c/i2c_core.c | 153 ---- components/drivers/i2c/i2c_dev.c | 137 --- components/drivers/i2c/i2c_dm.c | 50 -- components/drivers/i2c/soft_i2c.c | 264 ------ components/drivers/include/drivers/alarm.h | 75 -- components/drivers/include/drivers/audio.h | 176 ---- components/drivers/include/drivers/can.h | 364 -------- components/drivers/include/drivers/dev_alarm.h | 75 ++ components/drivers/include/drivers/dev_audio.h | 176 ++++ components/drivers/include/drivers/dev_can.h | 364 ++++++++ components/drivers/include/drivers/dev_i2c.h | 155 ++++ .../drivers/include/drivers/dev_i2c_bit_ops.h | 42 + components/drivers/include/drivers/dev_i2c_dm.h | 51 ++ components/drivers/include/drivers/dev_pin.h | 178 ++++ components/drivers/include/drivers/dev_pwm.h | 66 ++ components/drivers/include/drivers/dev_rtc.h | 82 ++ components/drivers/include/drivers/i2c-bit-ops.h | 42 - components/drivers/include/drivers/i2c.h | 136 --- components/drivers/include/drivers/i2c_dev.h | 44 - components/drivers/include/drivers/i2c_dm.h | 51 -- components/drivers/include/drivers/pin.h | 178 ---- components/drivers/include/drivers/rt_drv_pwm.h | 66 -- components/drivers/include/drivers/rtc.h | 82 -- components/drivers/include/drivers/sensor.h | 2 +- components/drivers/include/drivers/sensor_v2.h | 2 +- components/drivers/include/drivers/spi.h | 2 +- components/drivers/include/drivers/touch.h | 2 +- components/drivers/include/rtdevice.h | 19 +- components/drivers/pin/SConscript | 6 +- components/drivers/pin/dev_pin.c | 373 ++++++++ components/drivers/pin/dev_pin_dm.c | 220 +++++ components/drivers/pin/dev_pin_dm.h | 21 + components/drivers/pin/dev_pin_ofw.c | 170 ++++ components/drivers/pin/pin.c | 373 -------- components/drivers/pin/pin_dm.c | 220 ----- components/drivers/pin/pin_dm.h | 21 - components/drivers/pin/pin_ofw.c | 170 ---- components/drivers/rtc/SConscript | 6 +- components/drivers/rtc/alarm.c | 800 ----------------- components/drivers/rtc/dev_alarm.c | 800 +++++++++++++++++ components/drivers/rtc/dev_rtc.c | 375 ++++++++ components/drivers/rtc/dev_soft_rtc.c | 325 +++++++ components/drivers/rtc/rtc.c | 375 -------- components/drivers/rtc/soft_rtc.c | 325 ------- 104 files changed, 6752 insertions(+), 6778 deletions(-) delete mode 100644 components/drivers/audio/audio.c delete mode 100644 components/drivers/audio/audio_pipe.c delete mode 100644 components/drivers/audio/audio_pipe.h create mode 100644 components/drivers/audio/dev_audio.c create mode 100644 components/drivers/audio/dev_audio_pipe.c create mode 100644 components/drivers/audio/dev_audio_pipe.h delete mode 100644 components/drivers/can/can.c create mode 100644 components/drivers/can/dev_can.c create mode 100644 components/drivers/i2c/dev_i2c_bit_ops.c create mode 100644 components/drivers/i2c/dev_i2c_bus.c create mode 100644 components/drivers/i2c/dev_i2c_core.c create mode 100644 components/drivers/i2c/dev_i2c_dev.c create mode 100644 components/drivers/i2c/dev_i2c_dm.c create mode 100644 components/drivers/i2c/dev_soft_i2c.c delete mode 100644 components/drivers/i2c/i2c-bit-ops.c delete mode 100644 components/drivers/i2c/i2c_bus.c delete mode 100644 components/drivers/i2c/i2c_core.c delete mode 100644 components/drivers/i2c/i2c_dev.c delete mode 100644 components/drivers/i2c/i2c_dm.c delete mode 100644 components/drivers/i2c/soft_i2c.c delete mode 100644 components/drivers/include/drivers/alarm.h delete mode 100644 components/drivers/include/drivers/audio.h delete mode 100644 components/drivers/include/drivers/can.h create mode 100644 components/drivers/include/drivers/dev_alarm.h create mode 100644 components/drivers/include/drivers/dev_audio.h create mode 100644 components/drivers/include/drivers/dev_can.h create mode 100644 components/drivers/include/drivers/dev_i2c.h create mode 100644 components/drivers/include/drivers/dev_i2c_bit_ops.h create mode 100644 components/drivers/include/drivers/dev_i2c_dm.h create mode 100644 components/drivers/include/drivers/dev_pin.h create mode 100644 components/drivers/include/drivers/dev_pwm.h create mode 100644 components/drivers/include/drivers/dev_rtc.h delete mode 100644 components/drivers/include/drivers/i2c-bit-ops.h delete mode 100644 components/drivers/include/drivers/i2c.h delete mode 100644 components/drivers/include/drivers/i2c_dev.h delete mode 100644 components/drivers/include/drivers/i2c_dm.h delete mode 100644 components/drivers/include/drivers/pin.h delete mode 100644 components/drivers/include/drivers/rt_drv_pwm.h delete mode 100644 components/drivers/include/drivers/rtc.h create mode 100644 components/drivers/pin/dev_pin.c create mode 100644 components/drivers/pin/dev_pin_dm.c create mode 100644 components/drivers/pin/dev_pin_dm.h create mode 100644 components/drivers/pin/dev_pin_ofw.c delete mode 100644 components/drivers/pin/pin.c delete mode 100644 components/drivers/pin/pin_dm.c delete mode 100644 components/drivers/pin/pin_dm.h delete mode 100644 components/drivers/pin/pin_ofw.c delete mode 100644 components/drivers/rtc/alarm.c create mode 100644 components/drivers/rtc/dev_alarm.c create mode 100644 components/drivers/rtc/dev_rtc.c create mode 100644 components/drivers/rtc/dev_soft_rtc.c delete mode 100644 components/drivers/rtc/rtc.c delete mode 100644 components/drivers/rtc/soft_rtc.c diff --git a/bsp/Infineon/libraries/HAL_Drivers/drv_pwm.c b/bsp/Infineon/libraries/HAL_Drivers/drv_pwm.c index 7a6a624f6a..cd7a024a72 100644 --- a/bsp/Infineon/libraries/HAL_Drivers/drv_pwm.c +++ b/bsp/Infineon/libraries/HAL_Drivers/drv_pwm.c @@ -11,7 +11,7 @@ #ifdef RT_USING_PWM -#include +#include #include "drv_gpio.h" //#define DRV_DEBUG diff --git a/bsp/acm32/acm32f0x0-nucleo/applications/main.c b/bsp/acm32/acm32f0x0-nucleo/applications/main.c index 18d7a17b4d..aa93e7d728 100644 --- a/bsp/acm32/acm32f0x0-nucleo/applications/main.c +++ b/bsp/acm32/acm32f0x0-nucleo/applications/main.c @@ -9,7 +9,7 @@ * 2021-10-17 AisinoChip remove unused header file */ #include "board.h" -#include +#include #define LED_PIN_NUM 1 /* PA1 */ diff --git a/bsp/acm32/acm32f0x0-nucleo/drivers/drv_soft_i2c.h b/bsp/acm32/acm32f0x0-nucleo/drivers/drv_soft_i2c.h index fce6a0f0eb..e66083b0d9 100644 --- a/bsp/acm32/acm32f0x0-nucleo/drivers/drv_soft_i2c.h +++ b/bsp/acm32/acm32f0x0-nucleo/drivers/drv_soft_i2c.h @@ -15,7 +15,7 @@ #include #include #include -#include +#include /* acm32 config class */ struct acm32_soft_i2c_config diff --git a/bsp/acm32/acm32f4xx-nucleo/applications/main.c b/bsp/acm32/acm32f4xx-nucleo/applications/main.c index cc4acc7fc6..76d26d22f5 100644 --- a/bsp/acm32/acm32f4xx-nucleo/applications/main.c +++ b/bsp/acm32/acm32f4xx-nucleo/applications/main.c @@ -11,7 +11,7 @@ #include #include #include "board.h" -#include +#include #define LED_PIN_NUM 83 /* PF3 */ diff --git a/bsp/apm32/libraries/Drivers/drv_pwm.c b/bsp/apm32/libraries/Drivers/drv_pwm.c index cff924384b..2c3b4c7263 100644 --- a/bsp/apm32/libraries/Drivers/drv_pwm.c +++ b/bsp/apm32/libraries/Drivers/drv_pwm.c @@ -14,7 +14,7 @@ #include #ifdef RT_USING_PWM -#include +#include #define DBG_TAG "drv.pwm" #define DBG_LVL DBG_INFO diff --git a/bsp/at32/libraries/rt_drivers/drv_hard_i2c.h b/bsp/at32/libraries/rt_drivers/drv_hard_i2c.h index bc34abf1c9..c1c683e5aa 100644 --- a/bsp/at32/libraries/rt_drivers/drv_hard_i2c.h +++ b/bsp/at32/libraries/rt_drivers/drv_hard_i2c.h @@ -12,7 +12,7 @@ #define __DRV_HARD_I2C_H__ #include -#include +#include #include "drv_common.h" #include "drv_dma.h" diff --git a/bsp/at32/libraries/rt_drivers/drv_pwm.c b/bsp/at32/libraries/rt_drivers/drv_pwm.c index 32e15af868..f50f2dacde 100644 --- a/bsp/at32/libraries/rt_drivers/drv_pwm.c +++ b/bsp/at32/libraries/rt_drivers/drv_pwm.c @@ -12,7 +12,7 @@ #ifdef RT_USING_PWM #include "drv_pwm.h" -#include +#include //#define DRV_DEBUG #define LOG_TAG "drv.pwm" diff --git a/bsp/cvitek/cv18xx_risc-v/applications/main.c b/bsp/cvitek/cv18xx_risc-v/applications/main.c index 4da2afdf63..eb689ece32 100755 --- a/bsp/cvitek/cv18xx_risc-v/applications/main.c +++ b/bsp/cvitek/cv18xx_risc-v/applications/main.c @@ -10,7 +10,7 @@ #include #include -#include +#include #if defined(BOARD_TYPE_MILKV_DUO256M) || defined(BOARD_TYPE_MILKV_DUO256M_SPINOR) #define LED_PIN "E02" /* Onboard LED pins */ diff --git a/bsp/dm365/drivers/i2c-davinci.c b/bsp/dm365/drivers/i2c-davinci.c index 6da4e72d6c..ce3be1528c 100644 --- a/bsp/dm365/drivers/i2c-davinci.c +++ b/bsp/dm365/drivers/i2c-davinci.c @@ -9,7 +9,7 @@ */ #include -#include +#include #include /* ----- global defines ----------------------------------------------- */ diff --git a/bsp/hc32/libraries/hc32_drivers/drv_pwm.c b/bsp/hc32/libraries/hc32_drivers/drv_pwm.c index 47e2aaa329..f882f17bf1 100644 --- a/bsp/hc32/libraries/hc32_drivers/drv_pwm.c +++ b/bsp/hc32/libraries/hc32_drivers/drv_pwm.c @@ -12,7 +12,7 @@ #include #include "drv_config.h" -#include +#include #include #if defined(BSP_USING_PWM) diff --git a/bsp/hpmicro/hpm6750evk/board/hpm_sgtl5000.h b/bsp/hpmicro/hpm6750evk/board/hpm_sgtl5000.h index c0073d1948..f3c4f22130 100644 --- a/bsp/hpmicro/hpm6750evk/board/hpm_sgtl5000.h +++ b/bsp/hpmicro/hpm6750evk/board/hpm_sgtl5000.h @@ -13,7 +13,7 @@ #include #include #include "rtt_board.h" -#include "drivers/i2c.h" +#include "drivers/dev_i2c.h" /*! * @addtogroup sgtl5000 diff --git a/bsp/hpmicro/hpm6750evk2/board/hpm_wm8960.h b/bsp/hpmicro/hpm6750evk2/board/hpm_wm8960.h index a288b08db9..a163a52390 100644 --- a/bsp/hpmicro/hpm6750evk2/board/hpm_wm8960.h +++ b/bsp/hpmicro/hpm6750evk2/board/hpm_wm8960.h @@ -15,7 +15,7 @@ #include #include #include "rtt_board.h" -#include "drivers/i2c.h" +#include "drivers/dev_i2c.h" #include "hpm_wm8960_regs.h" #define WM8960_I2C_ADDR 0x1A diff --git a/bsp/hpmicro/hpm6800evk/board/hpm_wm8960.h b/bsp/hpmicro/hpm6800evk/board/hpm_wm8960.h index a288b08db9..a163a52390 100644 --- a/bsp/hpmicro/hpm6800evk/board/hpm_wm8960.h +++ b/bsp/hpmicro/hpm6800evk/board/hpm_wm8960.h @@ -15,7 +15,7 @@ #include #include #include "rtt_board.h" -#include "drivers/i2c.h" +#include "drivers/dev_i2c.h" #include "hpm_wm8960_regs.h" #define WM8960_I2C_ADDR 0x1A diff --git a/bsp/hpmicro/libraries/drivers/drv_dao.c b/bsp/hpmicro/libraries/drivers/drv_dao.c index 3143fca99b..caa73dd86b 100644 --- a/bsp/hpmicro/libraries/drivers/drv_dao.c +++ b/bsp/hpmicro/libraries/drivers/drv_dao.c @@ -13,7 +13,7 @@ #include #ifdef BSP_USING_DAO -#include "drivers/audio.h" +#include "drivers/dev_audio.h" #include "hpm_i2s_drv.h" #include "hpm_dao_drv.h" #include "board.h" diff --git a/bsp/hpmicro/libraries/drivers/drv_i2s.c b/bsp/hpmicro/libraries/drivers/drv_i2s.c index c9092766c1..4108e4fb68 100644 --- a/bsp/hpmicro/libraries/drivers/drv_i2s.c +++ b/bsp/hpmicro/libraries/drivers/drv_i2s.c @@ -26,7 +26,7 @@ #include "hpm_dma_mgr.h" #include "drv_i2s.h" -#include "drivers/audio.h" +#include "drivers/dev_audio.h" static rt_ssize_t hpm_i2s_transmit(struct rt_audio_device* audio, const void* writeBuf, void* readBuf, rt_size_t size); diff --git a/bsp/hpmicro/libraries/drivers/drv_pdm.c b/bsp/hpmicro/libraries/drivers/drv_pdm.c index 1648b1ecb4..8fa3d20a13 100644 --- a/bsp/hpmicro/libraries/drivers/drv_pdm.c +++ b/bsp/hpmicro/libraries/drivers/drv_pdm.c @@ -14,7 +14,7 @@ #ifdef BSP_USING_PDM #include "board.h" -#include "drivers/audio.h" +#include "drivers/dev_audio.h" #include "hpm_i2s_drv.h" #include "hpm_pdm_drv.h" #include "drv_pdm.h" diff --git a/bsp/k210/drivers/drv_i2c.c b/bsp/k210/drivers/drv_i2c.c index 78d223a3a8..d6f5676982 100644 --- a/bsp/k210/drivers/drv_i2c.c +++ b/bsp/k210/drivers/drv_i2c.c @@ -13,7 +13,7 @@ #include #include "board.h" -#include "i2c.h" +#include "drivers/dev_i2c.h" #include "gpiohs.h" #include "utils.h" #include "sleep.h" diff --git a/bsp/loongson/ls1cdev/drivers/drv_gpio.c b/bsp/loongson/ls1cdev/drivers/drv_gpio.c index fb75ab0d49..14c1a6682c 100644 --- a/bsp/loongson/ls1cdev/drivers/drv_gpio.c +++ b/bsp/loongson/ls1cdev/drivers/drv_gpio.c @@ -10,7 +10,7 @@ */ #include -#include +#include #include "ls1c_gpio.h" #include "ls1c.h" #include diff --git a/bsp/loongson/ls1cdev/drivers/drv_i2c.c b/bsp/loongson/ls1cdev/drivers/drv_i2c.c index 50c27fc8ba..6904155eb5 100644 --- a/bsp/loongson/ls1cdev/drivers/drv_i2c.c +++ b/bsp/loongson/ls1cdev/drivers/drv_i2c.c @@ -9,8 +9,8 @@ */ #include -#include -#include +#include +#include #include "drv_i2c.h" #include "../libraries/ls1c_gpio.h" #include "../libraries/ls1c_delay.h" diff --git a/bsp/loongson/ls2kdev/drivers/drv_gpio.c b/bsp/loongson/ls2kdev/drivers/drv_gpio.c index 2a66825ef6..79c4c20a0d 100644 --- a/bsp/loongson/ls2kdev/drivers/drv_gpio.c +++ b/bsp/loongson/ls2kdev/drivers/drv_gpio.c @@ -6,10 +6,10 @@ * Date Author Notes * 2015-01-20 Bernard the first version * 2017-10-20 ZYH add mode open drain and input pull down - * 2020-06-01 Du Huanpeng GPIO driver based on + * 2020-06-01 Du Huanpeng GPIO driver based on */ #include -#include +#include #include #include "drv_gpio.h" diff --git a/bsp/loongson/ls2kdev/drivers/drv_spi.c b/bsp/loongson/ls2kdev/drivers/drv_spi.c index daf069412b..b29f7b9bc3 100644 --- a/bsp/loongson/ls2kdev/drivers/drv_spi.c +++ b/bsp/loongson/ls2kdev/drivers/drv_spi.c @@ -23,7 +23,7 @@ #ifdef RT_USING_SPI #ifdef RT_USING_SPI_GPIOCS -#include +#include #endif static void spi_init(uint8_t spre_spr, uint8_t copl, uint8_t cpha) diff --git a/bsp/loongson/ls2kdev/drivers/interrupt.c b/bsp/loongson/ls2kdev/drivers/interrupt.c index 9e9c210aa0..57770e7910 100644 --- a/bsp/loongson/ls2kdev/drivers/interrupt.c +++ b/bsp/loongson/ls2kdev/drivers/interrupt.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include "ls2k1000.h" #include "interrupt.h" diff --git a/bsp/maxim/libraries/HAL_Drivers/drv_i2c.c b/bsp/maxim/libraries/HAL_Drivers/drv_i2c.c index 4ae3a06319..37ede9e151 100644 --- a/bsp/maxim/libraries/HAL_Drivers/drv_i2c.c +++ b/bsp/maxim/libraries/HAL_Drivers/drv_i2c.c @@ -10,7 +10,7 @@ */ #include "drv_i2c.h" -#include "i2c.h" +#include "drivers/dev_i2c.h" #include #include #include "board.h" diff --git a/bsp/maxim/libraries/HAL_Drivers/drv_rtc.c b/bsp/maxim/libraries/HAL_Drivers/drv_rtc.c index 6584f55752..563ee24dc2 100644 --- a/bsp/maxim/libraries/HAL_Drivers/drv_rtc.c +++ b/bsp/maxim/libraries/HAL_Drivers/drv_rtc.c @@ -8,7 +8,7 @@ * 2021-03-15 picospuch Porting for maxiam32660 */ -#include "rtc.h" +#include "drivers/dev_rtc.h" #include "board.h" #include diff --git a/bsp/n32g452xx/Libraries/rt_drivers/drv_pwm.h b/bsp/n32g452xx/Libraries/rt_drivers/drv_pwm.h index 03a773ef28..ebdca04b5a 100644 --- a/bsp/n32g452xx/Libraries/rt_drivers/drv_pwm.h +++ b/bsp/n32g452xx/Libraries/rt_drivers/drv_pwm.h @@ -12,7 +12,7 @@ #define __PWM_CONFIG_H__ #include -#include +#include #ifdef __cplusplus extern "C" { diff --git a/bsp/nxp/imx/imx6ull-smart/drivers/drv_pwm.c b/bsp/nxp/imx/imx6ull-smart/drivers/drv_pwm.c index 6e4e4e0e2c..fe9489baef 100644 --- a/bsp/nxp/imx/imx6ull-smart/drivers/drv_pwm.c +++ b/bsp/nxp/imx/imx6ull-smart/drivers/drv_pwm.c @@ -22,7 +22,7 @@ #include "fsl_pwm.h" #include "drv_pwm.h" #include -#include +#include #define PWM_SRC_CLK_FREQ CLOCK_GetFreq(kCLOCK_IpgClk) /* PWMPR register value of 0xffff has the same effect as 0xfffe */ diff --git a/bsp/nxp/imx/imxrt/libraries/drivers/drv_sai.c b/bsp/nxp/imx/imxrt/libraries/drivers/drv_sai.c index 98c8a99bc7..b078959e86 100644 --- a/bsp/nxp/imx/imxrt/libraries/drivers/drv_sai.c +++ b/bsp/nxp/imx/imxrt/libraries/drivers/drv_sai.c @@ -17,7 +17,7 @@ #include #include -#include "drivers/audio.h" +#include "drivers/dev_audio.h" #include "bsp_wm8960.h" #include "drv_i2c.h" #include "drv_sai.h" diff --git a/bsp/nxp/lpc/lpc55sxx/Libraries/drivers/drv_sound_wm8904.c b/bsp/nxp/lpc/lpc55sxx/Libraries/drivers/drv_sound_wm8904.c index 7ac19ffbe7..4144b9b332 100644 --- a/bsp/nxp/lpc/lpc55sxx/Libraries/drivers/drv_sound_wm8904.c +++ b/bsp/nxp/lpc/lpc55sxx/Libraries/drivers/drv_sound_wm8904.c @@ -9,8 +9,8 @@ */ #include -#include -#include +#include +#include #include "drv_sound_wm8904.h" /** diff --git a/bsp/phytium/libraries/drivers/drv_i2c.c b/bsp/phytium/libraries/drivers/drv_i2c.c index 4f195ee982..fe216adf7f 100644 --- a/bsp/phytium/libraries/drivers/drv_i2c.c +++ b/bsp/phytium/libraries/drivers/drv_i2c.c @@ -21,7 +21,7 @@ #include "fio_mux.h" #include "fmio_hw.h" #include "fmio.h" -#include "drivers/i2c.h" +#include "drivers/dev_i2c.h" #include "fparameters.h" #ifdef RT_USING_SMART #include diff --git a/bsp/renesas/ra6m3-hmi-board/board/ports/can_test.c b/bsp/renesas/ra6m3-hmi-board/board/ports/can_test.c index 9309c22e88..bb8670a99a 100644 --- a/bsp/renesas/ra6m3-hmi-board/board/ports/can_test.c +++ b/bsp/renesas/ra6m3-hmi-board/board/ports/can_test.c @@ -8,7 +8,7 @@ #include #include "rtdevice.h" -#include "drivers/can.h" +#include "drivers/dev_can.h" #ifdef BSP_USING_CAN0 #define CAN_DEV_NAME "can0" /* CAN 设备名称 */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_pwm.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_pwm.c index 478d1d89e2..d097e68f3c 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_pwm.c +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_pwm.c @@ -15,7 +15,7 @@ #ifdef BSP_USING_PWM #include "drv_config.h" #include "drv_tim.h" -#include +#include //#define DRV_DEBUG #define LOG_TAG "drv.pwm" diff --git a/bsp/stm32/stm32f429-st-disco/board/ports/touch/drv_touch.c b/bsp/stm32/stm32f429-st-disco/board/ports/touch/drv_touch.c index d70e444ef4..7ae1cf57f5 100644 --- a/bsp/stm32/stm32f429-st-disco/board/ports/touch/drv_touch.c +++ b/bsp/stm32/stm32f429-st-disco/board/ports/touch/drv_touch.c @@ -9,7 +9,7 @@ */ #include "drv_touch.h" -#include "drivers/i2c.h" +#include "drivers/dev_i2c.h" #ifdef PKG_USING_LITTLEVGL2RTT #include "littlevgl2rtt.h" diff --git a/bsp/w60x/drivers/drv_rtc.h b/bsp/w60x/drivers/drv_rtc.h index f1c55172ff..da62b3cce7 100644 --- a/bsp/w60x/drivers/drv_rtc.h +++ b/bsp/w60x/drivers/drv_rtc.h @@ -14,7 +14,7 @@ #include #ifdef RT_USING_ALARM -#include +#include "drivers/dev_alarm.h" #endif struct rt_rtc_device diff --git a/bsp/wch/risc-v/Libraries/ch32_drivers/drv_pwm.h b/bsp/wch/risc-v/Libraries/ch32_drivers/drv_pwm.h index 086201cc47..ec8db3aec7 100644 --- a/bsp/wch/risc-v/Libraries/ch32_drivers/drv_pwm.h +++ b/bsp/wch/risc-v/Libraries/ch32_drivers/drv_pwm.h @@ -19,7 +19,7 @@ #if defined(SOC_RISCV_SERIES_CH32V2) #include "ch32v20x_tim.h" #endif -#include +#include #include #include diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_gpio.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_gpio.c index 72477c4a12..c40cf6d486 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_gpio.c +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_gpio.c @@ -8,7 +8,7 @@ * 2022-07-15 Emuzit first version */ #include -#include +#include #include "ch56x_gpio.h" #include "isr_sp.h" diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pwm.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pwm.c index d1ce6aad83..c3b27703f6 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pwm.c +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pwm.c @@ -8,8 +8,8 @@ * 2022-08-04 Emuzit first version */ #include -#include -#include +#include +#include #include "ch56x_pwm.h" #include "ch56x_sys.h" diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_spi.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_spi.c index 68b10f0eae..a57952d98c 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_spi.c +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_spi.c @@ -9,7 +9,7 @@ */ #include #include -#include +#include #include "ch56x_spi.h" #include "ch56x_sys.h" diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c index ae0c79d29f..918b50c7bc 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c @@ -15,7 +15,7 @@ #else #include #endif -#include +#include #include "ch56x_sys.h" #include "ch56x_uart.h" #include "isr_sp.h" diff --git a/bsp/wch/risc-v/ch32v103r-evt/board/board.h b/bsp/wch/risc-v/ch32v103r-evt/board/board.h index 6496052cb1..26842e9af5 100644 --- a/bsp/wch/risc-v/ch32v103r-evt/board/board.h +++ b/bsp/wch/risc-v/ch32v103r-evt/board/board.h @@ -15,7 +15,7 @@ #include "ch32v10x.h" #include -#include "drivers/pin.h" +#include "drivers/dev_pin.h" #define CH32V10X_PIN_NUMBERS 64 /* board configuration */ diff --git a/bsp/wch/risc-v/ch32v208w-r0/applications/main.c b/bsp/wch/risc-v/ch32v208w-r0/applications/main.c index 0b6bd980f6..6e40dcefca 100644 --- a/bsp/wch/risc-v/ch32v208w-r0/applications/main.c +++ b/bsp/wch/risc-v/ch32v208w-r0/applications/main.c @@ -11,7 +11,7 @@ #include "ch32v20x.h" #include #include -#include "drivers/pin.h" +#include "drivers/dev_pin.h" #include #define LED0 rt_pin_get("PA.0") diff --git a/bsp/wch/risc-v/ch569w-evt/applications/main.c b/bsp/wch/risc-v/ch569w-evt/applications/main.c index a83dc5c09c..d9f4494de9 100644 --- a/bsp/wch/risc-v/ch569w-evt/applications/main.c +++ b/bsp/wch/risc-v/ch569w-evt/applications/main.c @@ -9,7 +9,7 @@ */ #include #include -#include +#include #include "board.h" void main(void) diff --git a/bsp/wch/risc-v/ch569w-evt/applications/test.c b/bsp/wch/risc-v/ch569w-evt/applications/test.c index a1396af879..e6e6cd5c17 100644 --- a/bsp/wch/risc-v/ch569w-evt/applications/test.c +++ b/bsp/wch/risc-v/ch569w-evt/applications/test.c @@ -12,11 +12,11 @@ * 2022-08-04 Emuzit add pwm test */ #include -#include +#include #include #include #include -#include +#include #include "board.h" #define PWM_CYCLE_MAX 255 diff --git a/bsp/wch/risc-v/ch569w-evt/board/board.c b/bsp/wch/risc-v/ch569w-evt/board/board.c index 03c699b1bb..3f89ac56ef 100644 --- a/bsp/wch/risc-v/ch569w-evt/board/board.c +++ b/bsp/wch/risc-v/ch569w-evt/board/board.c @@ -8,7 +8,7 @@ * 2022-07-15 Emuzit first version */ #include -#include +#include #include "board.h" #include "ch56x_pfic.h" #include "ch56x_uart.h" diff --git a/components/drivers/audio/audio.c b/components/drivers/audio/audio.c deleted file mode 100644 index 22ee81e51f..0000000000 --- a/components/drivers/audio/audio.c +++ /dev/null @@ -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 -#include -#include -#include - -#define DBG_TAG "audio" -#define DBG_LVL DBG_INFO -#include - -#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); -} diff --git a/components/drivers/audio/audio_pipe.c b/components/drivers/audio/audio_pipe.c deleted file mode 100644 index d4d24b844d..0000000000 --- a/components/drivers/audio/audio_pipe.c +++ /dev/null @@ -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 -#include -#include "audio_pipe.h" - -static void _rt_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_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_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_pipe_resume_writer(pipe); - rt_hw_interrupt_enable(level); - break; - } - } - while (read_nbytes == 0); - - return read_nbytes; -} - -static void _rt_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_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_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_pipe_resume_reader(pipe); - rt_hw_interrupt_enable(level); - break; - } - } - while (write_nbytes == 0); - - return write_nbytes; -} - -static rt_err_t rt_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_pipe_read, - rt_pipe_write, - rt_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_pipe_read; - pipe->parent.write = rt_pipe_write; - pipe->parent.control = rt_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 */ diff --git a/components/drivers/audio/audio_pipe.h b/components/drivers/audio/audio_pipe.h deleted file mode 100644 index 88cbecaa22..0000000000 --- a/components/drivers/audio/audio_pipe.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ -#ifndef __AUDIO_PIPE_H__ -#define __AUDIO_PIPE_H__ - -/** - * Pipe Device - */ -#include - -#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 /* __AUDIO_PIPE_H__ */ diff --git a/components/drivers/audio/dev_audio.c b/components/drivers/audio/dev_audio.c new file mode 100644 index 0000000000..22ee81e51f --- /dev/null +++ b/components/drivers/audio/dev_audio.c @@ -0,0 +1,612 @@ +/* + * 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 +#include +#include +#include + +#define DBG_TAG "audio" +#define DBG_LVL DBG_INFO +#include + +#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); +} diff --git a/components/drivers/audio/dev_audio_pipe.c b/components/drivers/audio/dev_audio_pipe.c new file mode 100644 index 0000000000..2f5e9df12e --- /dev/null +++ b/components/drivers/audio/dev_audio_pipe.c @@ -0,0 +1,296 @@ +/* + * 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 +#include +#include "dev_audio_pipe.h" + +static void _rt_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_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_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_pipe_resume_writer(pipe); + rt_hw_interrupt_enable(level); + break; + } + } + while (read_nbytes == 0); + + return read_nbytes; +} + +static void _rt_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_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_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_pipe_resume_reader(pipe); + rt_hw_interrupt_enable(level); + break; + } + } + while (write_nbytes == 0); + + return write_nbytes; +} + +static rt_err_t rt_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_pipe_read, + rt_pipe_write, + rt_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_pipe_read; + pipe->parent.write = rt_pipe_write; + pipe->parent.control = rt_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 */ diff --git a/components/drivers/audio/dev_audio_pipe.h b/components/drivers/audio/dev_audio_pipe.h new file mode 100644 index 0000000000..f22fd14a1f --- /dev/null +++ b/components/drivers/audio/dev_audio_pipe.h @@ -0,0 +1,75 @@ +/* + * 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 + +#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__ */ diff --git a/components/drivers/can/can.c b/components/drivers/can/can.c deleted file mode 100644 index f10e05dc55..0000000000 --- a/components/drivers/can/can.c +++ /dev/null @@ -1,974 +0,0 @@ -/* - * Copyright (c) 2006-2023, 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 -#include -#include - -#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_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 -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 diff --git a/components/drivers/can/dev_can.c b/components/drivers/can/dev_can.c new file mode 100644 index 0000000000..f10e05dc55 --- /dev/null +++ b/components/drivers/can/dev_can.c @@ -0,0 +1,974 @@ +/* + * Copyright (c) 2006-2023, 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 +#include +#include + +#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_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 +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 diff --git a/components/drivers/i2c/SConscript b/components/drivers/i2c/SConscript index 3685e44e2d..269c6f54ba 100644 --- a/components/drivers/i2c/SConscript +++ b/components/drivers/i2c/SConscript @@ -3,16 +3,16 @@ from building import * cwd = GetCurrentDir() src = Split(""" -i2c_core.c -i2c_dev.c +dev_i2c_core.c +dev_i2c_dev.c """) if GetDepend('RT_USING_I2C_BITOPS'): - src = src + ['i2c-bit-ops.c'] + src = src + ['dev_i2c_bit_ops.c'] if GetDepend('RT_USING_SOFT_I2C'): - src = src + ['soft_i2c.c'] + src = src + ['dev_soft_i2c.c'] if GetDepend(['RT_USING_DM']): - src += ['i2c_bus.c', 'i2c_dm.c'] + src += ['dev_i2c_bus.c', 'dev_i2c_dm.c'] # The set of source files associated with this SConscript file. path = [cwd + '/../include'] diff --git a/components/drivers/i2c/dev_i2c_bit_ops.c b/components/drivers/i2c/dev_i2c_bit_ops.c new file mode 100644 index 0000000000..005cf9035e --- /dev/null +++ b/components/drivers/i2c/dev_i2c_bit_ops.c @@ -0,0 +1,464 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-04-25 weety first version + */ + +#include + +#define DBG_TAG "I2C" +#ifdef RT_I2C_BITOPS_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif +#include + +#define SET_SDA(ops, val) ops->set_sda(ops->data, val) +#define SET_SCL(ops, val) ops->set_scl(ops->data, val) +#define GET_SDA(ops) ops->get_sda(ops->data) +#define GET_SCL(ops) ops->get_scl(ops->data) + +rt_inline void i2c_delay(struct rt_i2c_bit_ops *ops) +{ + ops->udelay((ops->delay_us + 1) >> 1); +} + +rt_inline void i2c_delay2(struct rt_i2c_bit_ops *ops) +{ + ops->udelay(ops->delay_us); +} + +#define SDA_L(ops) SET_SDA(ops, 0) +#define SDA_H(ops) SET_SDA(ops, 1) +#define SCL_L(ops) SET_SCL(ops, 0) + +/** + * release scl line, and wait scl line to high. + */ +static rt_err_t SCL_H(struct rt_i2c_bit_ops *ops) +{ + rt_tick_t start; + + SET_SCL(ops, 1); + + if (!ops->get_scl) + goto done; + + start = rt_tick_get(); + while (!GET_SCL(ops)) + { + if ((rt_tick_get() - start) > ops->timeout) + return -RT_ETIMEOUT; + i2c_delay(ops); + } +#ifdef RT_I2C_BITOPS_DEBUG + if (rt_tick_get() != start) + { + LOG_D("wait %ld tick for SCL line to go high", + rt_tick_get() - start); + } +#endif + +done: + i2c_delay(ops); + + return RT_EOK; +} + +static void i2c_start(struct rt_i2c_bit_ops *ops) +{ +#ifdef RT_I2C_BITOPS_DEBUG + if (ops->get_scl && !GET_SCL(ops)) + { + LOG_E("I2C bus error, SCL line low"); + } + if (ops->get_sda && !GET_SDA(ops)) + { + LOG_E("I2C bus error, SDA line low"); + } +#endif + SDA_L(ops); + i2c_delay(ops); + SCL_L(ops); +} + +static void i2c_restart(struct rt_i2c_bit_ops *ops) +{ + SDA_H(ops); + SCL_H(ops); + i2c_delay(ops); + SDA_L(ops); + i2c_delay(ops); + SCL_L(ops); +} + +static void i2c_stop(struct rt_i2c_bit_ops *ops) +{ + SDA_L(ops); + i2c_delay(ops); + SCL_H(ops); + i2c_delay(ops); + SDA_H(ops); + i2c_delay2(ops); +} + +rt_inline rt_bool_t i2c_waitack(struct rt_i2c_bit_ops *ops) +{ + rt_bool_t ack; + + SDA_H(ops); + i2c_delay(ops); + + if (SCL_H(ops) < 0) + { + LOG_W("wait ack timeout"); + + return -RT_ETIMEOUT; + } + + ack = !GET_SDA(ops); /* ACK : SDA pin is pulled low */ + LOG_D("%s", ack ? "ACK" : "NACK"); + + SCL_L(ops); + + return ack; +} + +static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data) +{ + rt_int32_t i; + rt_uint8_t bit; + + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; + + for (i = 7; i >= 0; i--) + { + SCL_L(ops); + bit = (data >> i) & 1; + SET_SDA(ops, bit); + i2c_delay(ops); + if (SCL_H(ops) < 0) + { + LOG_D("i2c_writeb: 0x%02x, " + "wait scl pin high timeout at bit %d", + data, i); + + return -RT_ETIMEOUT; + } + } + SCL_L(ops); + i2c_delay(ops); + + return i2c_waitack(ops); +} + +static rt_int32_t i2c_readb(struct rt_i2c_bus_device *bus) +{ + rt_uint8_t i; + rt_uint8_t data = 0; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; + + SDA_H(ops); + i2c_delay(ops); + for (i = 0; i < 8; i++) + { + data <<= 1; + + if (SCL_H(ops) < 0) + { + LOG_D("i2c_readb: wait scl pin high " + "timeout at bit %d", 7 - i); + + return -RT_ETIMEOUT; + } + + if (GET_SDA(ops)) + data |= 1; + SCL_L(ops); + i2c_delay2(ops); + } + + return data; +} + +static rt_ssize_t i2c_send_bytes(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg *msg) +{ + rt_int32_t ret; + rt_size_t bytes = 0; + const rt_uint8_t *ptr = msg->buf; + rt_int32_t count = msg->len; + rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; + + while (count > 0) + { + ret = i2c_writeb(bus, *ptr); + + if ((ret > 0) || (ignore_nack && (ret == 0))) + { + count --; + ptr ++; + bytes ++; + } + else if (ret == 0) + { + LOG_D("send bytes: NACK."); + + return 0; + } + else + { + LOG_E("send bytes: error %d", ret); + + return ret; + } + } + + return bytes; +} + +static rt_err_t i2c_send_ack_or_nack(struct rt_i2c_bus_device *bus, int ack) +{ + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; + + if (ack) + SET_SDA(ops, 0); + i2c_delay(ops); + if (SCL_H(ops) < 0) + { + LOG_E("ACK or NACK timeout."); + + return -RT_ETIMEOUT; + } + SCL_L(ops); + + return RT_EOK; +} + +static rt_ssize_t i2c_recv_bytes(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg *msg) +{ + rt_int32_t val; + rt_int32_t bytes = 0; /* actual bytes */ + rt_uint8_t *ptr = msg->buf; + rt_int32_t count = msg->len; + const rt_uint32_t flags = msg->flags; + + while (count > 0) + { + val = i2c_readb(bus); + if (val >= 0) + { + *ptr = val; + bytes ++; + } + else + { + break; + } + + ptr ++; + count --; + + LOG_D("recieve bytes: 0x%02x, %s", + val, (flags & RT_I2C_NO_READ_ACK) ? + "(No ACK/NACK)" : (count ? "ACK" : "NACK")); + + if (!(flags & RT_I2C_NO_READ_ACK)) + { + val = i2c_send_ack_or_nack(bus, count); + if (val < 0) + return val; + } + } + + return bytes; +} + +static rt_int32_t i2c_send_address(struct rt_i2c_bus_device *bus, + rt_uint8_t addr, + rt_int32_t retries) +{ + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; + rt_int32_t i; + rt_err_t ret = 0; + + for (i = 0; i <= retries; i++) + { + ret = i2c_writeb(bus, addr); + if (ret == 1 || i == retries) + break; + LOG_D("send stop condition"); + i2c_stop(ops); + i2c_delay2(ops); + LOG_D("send start condition"); + i2c_start(ops); + } + + return ret; +} + +static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg *msg) +{ + rt_uint16_t flags = msg->flags; + rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; + + rt_uint8_t addr1, addr2; + rt_int32_t retries; + rt_err_t ret; + + retries = ignore_nack ? 0 : bus->retries; + + if (flags & RT_I2C_ADDR_10BIT) + { + addr1 = 0xf0 | ((msg->addr >> 7) & 0x06); + addr2 = msg->addr & 0xff; + + LOG_D("addr1: %d, addr2: %d", addr1, addr2); + + ret = i2c_send_address(bus, addr1, retries); + if ((ret != 1) && !ignore_nack) + { + LOG_W("NACK: sending first addr"); + + return -RT_EIO; + } + + ret = i2c_writeb(bus, addr2); + if ((ret != 1) && !ignore_nack) + { + LOG_W("NACK: sending second addr"); + + return -RT_EIO; + } + if (flags & RT_I2C_RD) + { + LOG_D("send repeated start condition"); + i2c_restart(ops); + addr1 |= 0x01; + ret = i2c_send_address(bus, addr1, retries); + if ((ret != 1) && !ignore_nack) + { + LOG_E("NACK: sending repeated addr"); + + return -RT_EIO; + } + } + } + else + { + /* 7-bit addr */ + addr1 = msg->addr << 1; + if (flags & RT_I2C_RD) + addr1 |= 1; + ret = i2c_send_address(bus, addr1, retries); + if ((ret != 1) && !ignore_nack) + return -RT_EIO; + } + + return RT_EOK; +} + +static rt_ssize_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + struct rt_i2c_msg *msg; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; + rt_int32_t ret; + rt_uint32_t i; + rt_uint16_t ignore_nack; + + if((ops->i2c_pin_init_flag == RT_FALSE) && (ops->pin_init != RT_NULL)) + { + ops->pin_init(); + ops->i2c_pin_init_flag = RT_TRUE; + } + + if (num == 0) return 0; + + for (i = 0; i < num; i++) + { + msg = &msgs[i]; + ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; + if (!(msg->flags & RT_I2C_NO_START)) + { + if (i) + { + i2c_restart(ops); + } + else + { + LOG_D("send start condition"); + i2c_start(ops); + } + ret = i2c_bit_send_address(bus, msg); + if ((ret != RT_EOK) && !ignore_nack) + { + LOG_D("receive NACK from device addr 0x%02x msg %d", + msgs[i].addr, i); + goto out; + } + } + if (msg->flags & RT_I2C_RD) + { + ret = i2c_recv_bytes(bus, msg); + if (ret >= 1) + { + LOG_D("read %d byte%s", ret, ret == 1 ? "" : "s"); + } + if (ret < msg->len) + { + if (ret >= 0) + ret = -RT_EIO; + goto out; + } + } + else + { + ret = i2c_send_bytes(bus, msg); + if (ret >= 1) + { + LOG_D("write %d byte%s", ret, ret == 1 ? "" : "s"); + } + if (ret < msg->len) + { + if (ret >= 0) + ret = -RT_ERROR; + goto out; + } + } + } + ret = i; + +out: + if (!(msg->flags & RT_I2C_NO_STOP)) + { + LOG_D("send stop condition"); + i2c_stop(ops); + } + + return ret; +} + +static const struct rt_i2c_bus_device_ops i2c_bit_bus_ops = +{ + i2c_bit_xfer, + RT_NULL, + RT_NULL +}; + +rt_err_t rt_i2c_bit_add_bus(struct rt_i2c_bus_device *bus, + const char *bus_name) +{ + bus->ops = &i2c_bit_bus_ops; + + return rt_i2c_bus_device_register(bus, bus_name); +} diff --git a/components/drivers/i2c/dev_i2c_bus.c b/components/drivers/i2c/dev_i2c_bus.c new file mode 100644 index 0000000000..8a52471504 --- /dev/null +++ b/components/drivers/i2c/dev_i2c_bus.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-12-06 GuEe-GUI first version + */ + +#include + +#define DBG_TAG "dev.i2c.bus" +#define DBG_LVL DBG_INFO +#include + +static struct rt_bus i2c_bus; + +void i2c_bus_scan_clients(struct rt_i2c_bus_device *bus) +{ +#ifdef RT_USING_OFW + if (bus->parent.ofw_node) + { + struct rt_ofw_node *np = bus->parent.ofw_node, *child_np, *i2c_client_np; + + rt_ofw_foreach_available_child_node(np, child_np) + { + rt_uint32_t client_addr; + struct rt_i2c_client *client; + + if (rt_ofw_prop_read_bool(child_np, "compatible")) + { + i2c_client_np = child_np; + } + else + { + /* Maybe in i2c-mux */ + i2c_client_np = rt_ofw_get_next_child(child_np, RT_NULL); + + if (!rt_ofw_prop_read_bool(i2c_client_np, "compatible")) + { + continue; + } + } + + client = rt_calloc(1, sizeof(*client)); + + if (!client) + { + rt_ofw_node_put(i2c_client_np); + LOG_E("Not memory to create i2c client: %s", + rt_ofw_node_full_name(i2c_client_np)); + + return; + } + + rt_ofw_prop_read_u32(i2c_client_np, "reg", &client_addr); + + client->parent.ofw_node = i2c_client_np; + client->name = rt_ofw_node_name(i2c_client_np); + client->bus = bus; + client->client_addr = client_addr; + + rt_i2c_device_register(client); + + if (i2c_client_np != child_np) + { + rt_ofw_node_put(i2c_client_np); + } + } + } +#endif /* RT_USING_OFW */ +} + +rt_err_t rt_i2c_driver_register(struct rt_i2c_driver *driver) +{ + RT_ASSERT(driver != RT_NULL); + + driver->parent.bus = &i2c_bus; + + return rt_driver_register(&driver->parent); +} + +rt_err_t rt_i2c_device_register(struct rt_i2c_client *client) +{ + RT_ASSERT(client != RT_NULL); + + return rt_bus_add_device(&i2c_bus, &client->parent); +} + +static rt_bool_t i2c_match(rt_driver_t drv, rt_device_t dev) +{ + const struct rt_i2c_device_id *id; + struct rt_i2c_driver *driver = rt_container_of(drv, struct rt_i2c_driver, parent); + struct rt_i2c_client *client = rt_container_of(dev, struct rt_i2c_client, parent); + + if ((id = driver->ids)) + { + for (; id->name[0]; ++id) + { + if (!rt_strcmp(id->name, client->name)) + { + client->id = id; + client->ofw_id = RT_NULL; + + return RT_TRUE; + } + } + } + +#ifdef RT_USING_OFW + client->ofw_id = rt_ofw_node_match(client->parent.ofw_node, driver->ofw_ids); + + if (client->ofw_id) + { + client->id = RT_NULL; + + return RT_TRUE; + } +#endif + + return RT_FALSE; +} + +static rt_err_t i2c_probe(rt_device_t dev) +{ + rt_err_t err; + struct rt_i2c_driver *driver = rt_container_of(dev->drv, struct rt_i2c_driver, parent); + struct rt_i2c_client *client = rt_container_of(dev, struct rt_i2c_client, parent); + + if (!client->bus) + { + return -RT_EINVAL; + } + + err = driver->probe(client); + + return err; +} + +static rt_err_t i2c_remove(rt_device_t dev) +{ + struct rt_i2c_driver *driver = rt_container_of(dev->drv, struct rt_i2c_driver, parent); + struct rt_i2c_client *client = rt_container_of(dev, struct rt_i2c_client, parent); + + if (driver && driver->remove) + { + driver->remove(client); + } + + return RT_EOK; +} + +static rt_err_t i2c_shutdown(rt_device_t dev) +{ + struct rt_i2c_driver *driver = rt_container_of(dev->drv, struct rt_i2c_driver, parent); + struct rt_i2c_client *client = rt_container_of(dev, struct rt_i2c_client, parent); + + if (driver && driver->shutdown) + { + driver->shutdown(client); + } + + return RT_EOK; +} + +static struct rt_bus i2c_bus = +{ + .name = "i2c", + .match = i2c_match, + .probe = i2c_probe, + .remove = i2c_remove, + .shutdown = i2c_shutdown, +}; + +static int i2c_bus_init(void) +{ + rt_bus_register(&i2c_bus); + + return 0; +} +INIT_CORE_EXPORT(i2c_bus_init); diff --git a/components/drivers/i2c/dev_i2c_core.c b/components/drivers/i2c/dev_i2c_core.c new file mode 100644 index 0000000000..2b8e58c90c --- /dev/null +++ b/components/drivers/i2c/dev_i2c_core.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-04-25 weety first version + * 2021-04-20 RiceChen added support for bus control api + */ + +#include + +#define DBG_TAG "I2C" +#ifdef RT_I2C_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif +#include + +rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, + const char *bus_name) +{ + rt_err_t res = RT_EOK; + + rt_mutex_init(&bus->lock, "i2c_bus_lock", RT_IPC_FLAG_PRIO); + + if (bus->timeout == 0) bus->timeout = RT_TICK_PER_SECOND; + + res = rt_i2c_bus_device_device_init(bus, bus_name); + + LOG_I("I2C bus [%s] registered", bus_name); + +#ifdef RT_USING_DM + if (!res) + { + i2c_bus_scan_clients(bus); + } +#endif + + return res; +} + +struct rt_i2c_bus_device *rt_i2c_bus_device_find(const char *bus_name) +{ + struct rt_i2c_bus_device *bus; + rt_device_t dev = rt_device_find(bus_name); + if (dev == RT_NULL || dev->type != RT_Device_Class_I2CBUS) + { + LOG_E("I2C bus %s not exist", bus_name); + + return RT_NULL; + } + + bus = (struct rt_i2c_bus_device *)dev->user_data; + + return bus; +} + +rt_ssize_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + rt_ssize_t ret; + rt_err_t err; + + if (bus->ops->master_xfer) + { +#ifdef RT_I2C_DEBUG + for (ret = 0; ret < num; ret++) + { + LOG_D("msgs[%d] %c, addr=0x%02x, len=%d", ret, + (msgs[ret].flags & RT_I2C_RD) ? 'R' : 'W', + msgs[ret].addr, msgs[ret].len); + } +#endif + err = rt_mutex_take(&bus->lock, RT_WAITING_FOREVER); + if (err != RT_EOK) + { + return (rt_ssize_t)err; + } + ret = bus->ops->master_xfer(bus, msgs, num); + err = rt_mutex_release(&bus->lock); + if (err != RT_EOK) + { + return (rt_ssize_t)err; + } + return ret; + } + else + { + LOG_E("I2C bus operation not supported"); + return -RT_EINVAL; + } +} + +rt_err_t rt_i2c_control(struct rt_i2c_bus_device *bus, + int cmd, + void *args) +{ + rt_err_t ret; + + if(bus->ops->i2c_bus_control) + { + ret = bus->ops->i2c_bus_control(bus, cmd, args); + return ret; + } + else + { + LOG_E("I2C bus operation not supported"); + return -RT_EINVAL; + } +} + +rt_ssize_t rt_i2c_master_send(struct rt_i2c_bus_device *bus, + rt_uint16_t addr, + rt_uint16_t flags, + const rt_uint8_t *buf, + rt_uint32_t count) +{ + rt_ssize_t ret; + struct rt_i2c_msg msg; + + msg.addr = addr; + msg.flags = flags; + msg.len = count; + msg.buf = (rt_uint8_t *)buf; + + ret = rt_i2c_transfer(bus, &msg, 1); + + return (ret == 1) ? count : ret; +} + +rt_ssize_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus, + rt_uint16_t addr, + rt_uint16_t flags, + rt_uint8_t *buf, + rt_uint32_t count) +{ + rt_ssize_t ret; + struct rt_i2c_msg msg; + RT_ASSERT(bus != RT_NULL); + + msg.addr = addr; + msg.flags = flags | RT_I2C_RD; + msg.len = count; + msg.buf = buf; + + ret = rt_i2c_transfer(bus, &msg, 1); + + return (ret == 1) ? count : ret; +} diff --git a/components/drivers/i2c/dev_i2c_dev.c b/components/drivers/i2c/dev_i2c_dev.c new file mode 100644 index 0000000000..96110b9e7d --- /dev/null +++ b/components/drivers/i2c/dev_i2c_dev.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-04-25 weety first version + * 2014-08-03 bernard fix some compiling warning + * 2021-04-20 RiceChen added support for bus clock control + */ + +#include + +#define DBG_TAG "I2C" +#ifdef RT_I2C_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif +#include + +static rt_ssize_t i2c_bus_device_read(rt_device_t dev, + rt_off_t pos, + void *buffer, + rt_size_t count) +{ + rt_uint16_t addr; + rt_uint16_t flags; + struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data; + + RT_ASSERT(bus != RT_NULL); + RT_ASSERT(buffer != RT_NULL); + + LOG_D("I2C bus dev [%s] reading %u bytes.", dev->parent.name, count); + + addr = pos & 0xffff; + flags = (pos >> 16) & 0xffff; + + return rt_i2c_master_recv(bus, addr, flags, (rt_uint8_t *)buffer, count); +} + +static rt_ssize_t i2c_bus_device_write(rt_device_t dev, + rt_off_t pos, + const void *buffer, + rt_size_t count) +{ + rt_uint16_t addr; + rt_uint16_t flags; + struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data; + + RT_ASSERT(bus != RT_NULL); + RT_ASSERT(buffer != RT_NULL); + + LOG_D("I2C bus dev [%s] writing %u bytes.", dev->parent.name, count); + + addr = pos & 0xffff; + flags = (pos >> 16) & 0xffff; + + return rt_i2c_master_send(bus, addr, flags, (const rt_uint8_t *)buffer, count); +} + +static rt_err_t i2c_bus_device_control(rt_device_t dev, + int cmd, + void *args) +{ + rt_err_t ret; + struct rt_i2c_priv_data *priv_data; + struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data; + + RT_ASSERT(bus != RT_NULL); + + switch (cmd) + { + /* set 10-bit addr mode */ + case RT_I2C_DEV_CTRL_10BIT: + bus->flags |= RT_I2C_ADDR_10BIT; + break; + case RT_I2C_DEV_CTRL_TIMEOUT: + bus->timeout = *(rt_uint32_t *)args; + break; + case RT_I2C_DEV_CTRL_RW: + priv_data = (struct rt_i2c_priv_data *)args; + ret = rt_i2c_transfer(bus, priv_data->msgs, priv_data->number); + if (ret < 0) + { + return -RT_EIO; + } + break; + default: + return rt_i2c_control(bus, cmd, args); + } + + return RT_EOK; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops i2c_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + i2c_bus_device_read, + i2c_bus_device_write, + i2c_bus_device_control +}; +#endif + +rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device *bus, + const char *name) +{ + struct rt_device *device; + RT_ASSERT(bus != RT_NULL); + + device = &bus->parent; + + device->user_data = bus; + + /* set device type */ + device->type = RT_Device_Class_I2CBUS; + /* initialize device interface */ +#ifdef RT_USING_DEVICE_OPS + device->ops = &i2c_ops; +#else + device->init = RT_NULL; + device->open = RT_NULL; + device->close = RT_NULL; + device->read = i2c_bus_device_read; + device->write = i2c_bus_device_write; + device->control = i2c_bus_device_control; +#endif + + /* register to device manager */ + rt_device_register(device, name, RT_DEVICE_FLAG_RDWR); + + return RT_EOK; +} diff --git a/components/drivers/i2c/dev_i2c_dm.c b/components/drivers/i2c/dev_i2c_dm.c new file mode 100644 index 0000000000..5701dd580b --- /dev/null +++ b/components/drivers/i2c/dev_i2c_dm.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-12-06 GuEe-GUI first version + */ + +#include + +#define DBG_TAG "dev.i2c.dm" +#define DBG_LVL DBG_INFO +#include + +#ifdef RT_USING_OFW +static void i2c_parse_timing(struct rt_ofw_node *dev_np, const char *propname, + rt_uint32_t *out_value, rt_uint32_t def_value, rt_bool_t use_defaults) +{ + if (rt_ofw_prop_read_u32(dev_np, propname, out_value) && use_defaults) + { + *out_value = def_value; + } +} + +rt_err_t i2c_timings_ofw_parse(struct rt_ofw_node *dev_np, struct i2c_timings *timings, + rt_bool_t use_defaults) +{ + rt_ubase_t def; + rt_bool_t udef = use_defaults; + struct i2c_timings *t = timings; + + i2c_parse_timing(dev_np, "clock-frequency", &t->bus_freq_hz, I2C_MAX_STANDARD_MODE_FREQ, udef); + + def = t->bus_freq_hz <= I2C_MAX_STANDARD_MODE_FREQ ? 1000 : t->bus_freq_hz <= I2C_MAX_FAST_MODE_FREQ ? 300 : 120; + i2c_parse_timing(dev_np, "i2c-scl-rising-time-ns", &t->scl_rise_ns, def, udef); + + def = t->bus_freq_hz <= I2C_MAX_FAST_MODE_FREQ ? 300 : 120; + i2c_parse_timing(dev_np, "i2c-scl-falling-time-ns", &t->scl_fall_ns, def, udef); + + i2c_parse_timing(dev_np, "i2c-scl-internal-delay-ns", &t->scl_int_delay_ns, 0, udef); + i2c_parse_timing(dev_np, "i2c-sda-falling-time-ns", &t->sda_fall_ns, t->scl_fall_ns, udef); + i2c_parse_timing(dev_np, "i2c-sda-hold-time-ns", &t->sda_hold_ns, 0, udef); + i2c_parse_timing(dev_np, "i2c-digital-filter-width-ns", &t->digital_filter_width_ns, 0, udef); + i2c_parse_timing(dev_np, "i2c-analog-filter-cutoff-frequency", &t->analog_filter_cutoff_freq_hz, 0, udef); + + return RT_EOK; +} +#endif /* RT_USING_OFW */ diff --git a/components/drivers/i2c/dev_soft_i2c.c b/components/drivers/i2c/dev_soft_i2c.c new file mode 100644 index 0000000000..54c7395121 --- /dev/null +++ b/components/drivers/i2c/dev_soft_i2c.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-07-30 sp-cai first version + */ + +#include + +#ifdef RT_USING_SOFT_I2C +#if !defined(RT_USING_SOFT_I2C1) && !defined(RT_USING_SOFT_I2C2) &&\ + !defined(RT_USING_SOFT_I2C3) && !defined(RT_USING_SOFT_I2C4) &&\ + !defined(RT_USING_SOFT_I2C5) && !defined(RT_USING_SOFT_I2C6) &&\ + !defined(RT_USING_SOFT_I2C7) && !defined(RT_USING_SOFT_I2C8) + #error "Please define at least one RT_USING_SOFT_I2Cx" + /* + This driver can be disabled at: + menuconfig -> RT-Thread Components -> Device Drivers -> Using I2C device drivers + */ +#endif + +#define DBG_ENABLE +#define DBG_TAG "I2C_S" +#ifdef RT_I2C_BITOPS_DEBUG + #define DBG_LEVEL DBG_LOG +#endif +#include + +/* i2c config class */ +struct soft_i2c_config +{ + rt_base_t scl_pin; + rt_base_t sda_pin; + const char *bus_name; + rt_uint16_t timing_delay; /* scl and sda line delay */ + rt_uint16_t timing_timeout; /* in tick */ +}; + +/* i2c dirver class */ +struct rt_soft_i2c +{ + struct rt_i2c_bus_device i2c_bus; + struct rt_i2c_bit_ops ops; +}; + +struct soft_i2c_config i2c_cfg[] = +{ + #ifdef RT_USING_SOFT_I2C1 + { + .scl_pin = RT_SOFT_I2C1_SCL_PIN, + .sda_pin = RT_SOFT_I2C1_SDA_PIN, + .bus_name = RT_SOFT_I2C1_BUS_NAME, + .timing_delay = RT_SOFT_I2C1_TIMING_DELAY, + .timing_timeout = RT_SOFT_I2C1_TIMING_TIMEOUT, + }, + #endif //RT_USING_SOFT_I2C1 + #ifdef RT_USING_SOFT_I2C2 + { + .scl_pin = RT_SOFT_I2C2_SCL_PIN, + .sda_pin = RT_SOFT_I2C2_SDA_PIN, + .bus_name = RT_SOFT_I2C2_BUS_NAME, + .timing_delay = RT_SOFT_I2C2_TIMING_DELAY, + .timing_timeout = RT_SOFT_I2C2_TIMING_TIMEOUT, + }, + #endif //RT_USING_SOFT_I2C2 + #ifdef RT_USING_SOFT_I2C3 + { + .scl_pin = RT_SOFT_I2C3_SCL_PIN, + .sda_pin = RT_SOFT_I2C3_SDA_PIN, + .bus_name = RT_SOFT_I2C3_BUS_NAME, + .timing_delay = RT_SOFT_I2C3_TIMING_DELAY, + .timing_timeout = RT_SOFT_I2C3_TIMING_TIMEOUT, + }, + #endif //RT_USING_SOFT_I2C3 + #ifdef RT_USING_SOFT_I2C4 + { + .scl_pin = RT_SOFT_I2C4_SCL_PIN, + .sda_pin = RT_SOFT_I2C4_SDA_PIN, + .bus_name = RT_SOFT_I2C4_BUS_NAME, + .timing_delay = RT_SOFT_I2C4_TIMING_DELAY, + .timing_timeout = RT_SOFT_I2C4_TIMING_TIMEOUT, + }, + #endif //RT_USING_SOFT_I2C4 + #ifdef RT_USING_SOFT_I2C5 + { + .scl_pin = RT_SOFT_I2C5_SCL_PIN, + .sda_pin = RT_SOFT_I2C5_SDA_PIN, + .bus_name = RT_SOFT_I2C5_BUS_NAME, + .timing_delay = RT_SOFT_I2C5_TIMING_DELAY, + .timing_timeout = RT_SOFT_I2C5_TIMING_TIMEOUT, + }, + #endif //RT_USING_SOFT_I2C5 + #ifdef RT_USING_SOFT_I2C6 + { + .scl_pin = RT_SOFT_I2C6_SCL_PIN, + .sda_pin = RT_SOFT_I2C6_SDA_PIN, + .bus_name = RT_SOFT_I2C6_BUS_NAME, + .timing_delay = RT_SOFT_I2C6_TIMING_DELAY, + .timing_timeout = RT_SOFT_I2C6_TIMING_TIMEOUT, + }, + #endif //RT_USING_SOFT_I2C6 + #ifdef RT_USING_SOFT_I2C7 + { + .scl_pin = RT_SOFT_I2C7_SCL_PIN, + .sda_pin = RT_SOFT_I2C7_SDA_PIN, + .bus_name = RT_SOFT_I2C7_BUS_NAME, + .timing_delay = RT_SOFT_I2C7_TIMING_DELAY, + .timing_timeout = RT_SOFT_I2C7_TIMING_TIMEOUT, + }, + #endif //RT_USING_SOFT_I2C7 + #ifdef RT_USING_SOFT_I2C8 + { + .scl_pin = RT_SOFT_I2C8_SCL_PIN, + .sda_pin = RT_SOFT_I2C8_SDA_PIN, + .bus_name = RT_SOFT_I2C8_BUS_NAME, + .timing_delay = RT_SOFT_I2C8_TIMING_DELAY, + .timing_timeout = RT_SOFT_I2C8_TIMING_TIMEOUT, + }, + #endif //RT_USING_SOFT_I2C8 +}; + + +static struct rt_soft_i2c i2c_bus_obj[sizeof(i2c_cfg) / sizeof(i2c_cfg[0])] = +{ 0 }; + +/** +* This function initializes the i2c pin. +* @param i2c config class. +*/ +static void pin_init(const struct soft_i2c_config *cfg) +{ + rt_pin_mode(cfg->scl_pin, PIN_MODE_OUTPUT_OD); + rt_pin_mode(cfg->sda_pin, PIN_MODE_OUTPUT_OD); + rt_pin_write(cfg->scl_pin, PIN_HIGH); + rt_pin_write(cfg->sda_pin, PIN_HIGH); +} + + +/** +* This function sets the sda pin. +* @param i2c config class. +* @param The sda pin state. +*/ +static void set_sda(void *cfg, rt_int32_t value) +{ + rt_pin_write(((const struct soft_i2c_config*)cfg)->sda_pin, value); +} + +/** +* This function sets the scl pin. +* @param i2c config class. +* @param The sda pin state. +*/ +static void set_scl(void *cfg, rt_int32_t value) +{ + rt_pin_write(((const struct soft_i2c_config*)cfg)->scl_pin, value); +} + +/** +* This function gets the sda pin state. +* @param i2c config class. +*/ +static rt_int32_t get_sda(void *cfg) +{ + return rt_pin_read(((const struct soft_i2c_config*)cfg)->sda_pin); +} + +/** +* This function gets the scl pin state. +* @param i2c config class. +*/ +static rt_int32_t get_scl(void *cfg) +{ + return rt_pin_read(((const struct soft_i2c_config*)cfg)->scl_pin); +} + + +static const struct rt_i2c_bit_ops soft_i2c_ops = +{ + .set_sda = set_sda, + .set_scl = set_scl, + .get_sda = get_sda, + .get_scl = get_scl, + .udelay = rt_hw_us_delay, +}; + +/** +* if i2c is locked, this function will unlock it +* +* @param i2c config class. +* +* @return RT_EOK indicates successful unlock. +*/ +static rt_err_t i2c_bus_unlock(const struct soft_i2c_config *cfg) +{ + rt_ubase_t i = 0; + + if(PIN_LOW == rt_pin_read(cfg->sda_pin)) + { + while(i++ < 9) + { + rt_pin_write(cfg->scl_pin, PIN_HIGH); + rt_hw_us_delay(cfg->timing_delay); + rt_pin_write(cfg->scl_pin, PIN_LOW); + rt_hw_us_delay(cfg->timing_delay); + } + } + if(PIN_LOW == rt_pin_read(cfg->sda_pin)) + { + return -RT_ERROR; + } + + return RT_EOK; +} + +/* I2C initialization function */ +int rt_soft_i2c_init(void) +{ + int err = RT_EOK; + struct rt_soft_i2c *obj; + int i; + + for(i = 0; i < sizeof(i2c_bus_obj) / sizeof(i2c_bus_obj[0]); i++) + { + struct soft_i2c_config *cfg = &i2c_cfg[i]; + + pin_init(cfg); + + obj = &i2c_bus_obj[i]; + obj->ops = soft_i2c_ops; + obj->ops.data = cfg; + obj->i2c_bus.priv = &obj->ops; + obj->ops.delay_us = cfg->timing_delay; + obj->ops.timeout = cfg->timing_timeout; + if(rt_i2c_bit_add_bus(&obj->i2c_bus, cfg->bus_name) == RT_EOK) + { + i2c_bus_unlock(cfg); + LOG_D("Software simulation %s init done" + ", SCL pin: 0x%02X, SDA pin: 0x%02X" + , cfg->bus_name + , cfg->scl_pin + , cfg->sda_pin + ); + } + else + { + err++; + LOG_E("Software simulation %s init fail" + ", SCL pin: 0x%02X, SDA pin: 0x%02X" + , cfg->bus_name + , cfg->scl_pin + , cfg->sda_pin + ); + } + } + + return err; +} +INIT_PREV_EXPORT(rt_soft_i2c_init); + +#endif // RT_USING_SOFT_I2C diff --git a/components/drivers/i2c/i2c-bit-ops.c b/components/drivers/i2c/i2c-bit-ops.c deleted file mode 100644 index 005cf9035e..0000000000 --- a/components/drivers/i2c/i2c-bit-ops.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2012-04-25 weety first version - */ - -#include - -#define DBG_TAG "I2C" -#ifdef RT_I2C_BITOPS_DEBUG -#define DBG_LVL DBG_LOG -#else -#define DBG_LVL DBG_INFO -#endif -#include - -#define SET_SDA(ops, val) ops->set_sda(ops->data, val) -#define SET_SCL(ops, val) ops->set_scl(ops->data, val) -#define GET_SDA(ops) ops->get_sda(ops->data) -#define GET_SCL(ops) ops->get_scl(ops->data) - -rt_inline void i2c_delay(struct rt_i2c_bit_ops *ops) -{ - ops->udelay((ops->delay_us + 1) >> 1); -} - -rt_inline void i2c_delay2(struct rt_i2c_bit_ops *ops) -{ - ops->udelay(ops->delay_us); -} - -#define SDA_L(ops) SET_SDA(ops, 0) -#define SDA_H(ops) SET_SDA(ops, 1) -#define SCL_L(ops) SET_SCL(ops, 0) - -/** - * release scl line, and wait scl line to high. - */ -static rt_err_t SCL_H(struct rt_i2c_bit_ops *ops) -{ - rt_tick_t start; - - SET_SCL(ops, 1); - - if (!ops->get_scl) - goto done; - - start = rt_tick_get(); - while (!GET_SCL(ops)) - { - if ((rt_tick_get() - start) > ops->timeout) - return -RT_ETIMEOUT; - i2c_delay(ops); - } -#ifdef RT_I2C_BITOPS_DEBUG - if (rt_tick_get() != start) - { - LOG_D("wait %ld tick for SCL line to go high", - rt_tick_get() - start); - } -#endif - -done: - i2c_delay(ops); - - return RT_EOK; -} - -static void i2c_start(struct rt_i2c_bit_ops *ops) -{ -#ifdef RT_I2C_BITOPS_DEBUG - if (ops->get_scl && !GET_SCL(ops)) - { - LOG_E("I2C bus error, SCL line low"); - } - if (ops->get_sda && !GET_SDA(ops)) - { - LOG_E("I2C bus error, SDA line low"); - } -#endif - SDA_L(ops); - i2c_delay(ops); - SCL_L(ops); -} - -static void i2c_restart(struct rt_i2c_bit_ops *ops) -{ - SDA_H(ops); - SCL_H(ops); - i2c_delay(ops); - SDA_L(ops); - i2c_delay(ops); - SCL_L(ops); -} - -static void i2c_stop(struct rt_i2c_bit_ops *ops) -{ - SDA_L(ops); - i2c_delay(ops); - SCL_H(ops); - i2c_delay(ops); - SDA_H(ops); - i2c_delay2(ops); -} - -rt_inline rt_bool_t i2c_waitack(struct rt_i2c_bit_ops *ops) -{ - rt_bool_t ack; - - SDA_H(ops); - i2c_delay(ops); - - if (SCL_H(ops) < 0) - { - LOG_W("wait ack timeout"); - - return -RT_ETIMEOUT; - } - - ack = !GET_SDA(ops); /* ACK : SDA pin is pulled low */ - LOG_D("%s", ack ? "ACK" : "NACK"); - - SCL_L(ops); - - return ack; -} - -static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data) -{ - rt_int32_t i; - rt_uint8_t bit; - - struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; - - for (i = 7; i >= 0; i--) - { - SCL_L(ops); - bit = (data >> i) & 1; - SET_SDA(ops, bit); - i2c_delay(ops); - if (SCL_H(ops) < 0) - { - LOG_D("i2c_writeb: 0x%02x, " - "wait scl pin high timeout at bit %d", - data, i); - - return -RT_ETIMEOUT; - } - } - SCL_L(ops); - i2c_delay(ops); - - return i2c_waitack(ops); -} - -static rt_int32_t i2c_readb(struct rt_i2c_bus_device *bus) -{ - rt_uint8_t i; - rt_uint8_t data = 0; - struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; - - SDA_H(ops); - i2c_delay(ops); - for (i = 0; i < 8; i++) - { - data <<= 1; - - if (SCL_H(ops) < 0) - { - LOG_D("i2c_readb: wait scl pin high " - "timeout at bit %d", 7 - i); - - return -RT_ETIMEOUT; - } - - if (GET_SDA(ops)) - data |= 1; - SCL_L(ops); - i2c_delay2(ops); - } - - return data; -} - -static rt_ssize_t i2c_send_bytes(struct rt_i2c_bus_device *bus, - struct rt_i2c_msg *msg) -{ - rt_int32_t ret; - rt_size_t bytes = 0; - const rt_uint8_t *ptr = msg->buf; - rt_int32_t count = msg->len; - rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; - - while (count > 0) - { - ret = i2c_writeb(bus, *ptr); - - if ((ret > 0) || (ignore_nack && (ret == 0))) - { - count --; - ptr ++; - bytes ++; - } - else if (ret == 0) - { - LOG_D("send bytes: NACK."); - - return 0; - } - else - { - LOG_E("send bytes: error %d", ret); - - return ret; - } - } - - return bytes; -} - -static rt_err_t i2c_send_ack_or_nack(struct rt_i2c_bus_device *bus, int ack) -{ - struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; - - if (ack) - SET_SDA(ops, 0); - i2c_delay(ops); - if (SCL_H(ops) < 0) - { - LOG_E("ACK or NACK timeout."); - - return -RT_ETIMEOUT; - } - SCL_L(ops); - - return RT_EOK; -} - -static rt_ssize_t i2c_recv_bytes(struct rt_i2c_bus_device *bus, - struct rt_i2c_msg *msg) -{ - rt_int32_t val; - rt_int32_t bytes = 0; /* actual bytes */ - rt_uint8_t *ptr = msg->buf; - rt_int32_t count = msg->len; - const rt_uint32_t flags = msg->flags; - - while (count > 0) - { - val = i2c_readb(bus); - if (val >= 0) - { - *ptr = val; - bytes ++; - } - else - { - break; - } - - ptr ++; - count --; - - LOG_D("recieve bytes: 0x%02x, %s", - val, (flags & RT_I2C_NO_READ_ACK) ? - "(No ACK/NACK)" : (count ? "ACK" : "NACK")); - - if (!(flags & RT_I2C_NO_READ_ACK)) - { - val = i2c_send_ack_or_nack(bus, count); - if (val < 0) - return val; - } - } - - return bytes; -} - -static rt_int32_t i2c_send_address(struct rt_i2c_bus_device *bus, - rt_uint8_t addr, - rt_int32_t retries) -{ - struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; - rt_int32_t i; - rt_err_t ret = 0; - - for (i = 0; i <= retries; i++) - { - ret = i2c_writeb(bus, addr); - if (ret == 1 || i == retries) - break; - LOG_D("send stop condition"); - i2c_stop(ops); - i2c_delay2(ops); - LOG_D("send start condition"); - i2c_start(ops); - } - - return ret; -} - -static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus, - struct rt_i2c_msg *msg) -{ - rt_uint16_t flags = msg->flags; - rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; - struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; - - rt_uint8_t addr1, addr2; - rt_int32_t retries; - rt_err_t ret; - - retries = ignore_nack ? 0 : bus->retries; - - if (flags & RT_I2C_ADDR_10BIT) - { - addr1 = 0xf0 | ((msg->addr >> 7) & 0x06); - addr2 = msg->addr & 0xff; - - LOG_D("addr1: %d, addr2: %d", addr1, addr2); - - ret = i2c_send_address(bus, addr1, retries); - if ((ret != 1) && !ignore_nack) - { - LOG_W("NACK: sending first addr"); - - return -RT_EIO; - } - - ret = i2c_writeb(bus, addr2); - if ((ret != 1) && !ignore_nack) - { - LOG_W("NACK: sending second addr"); - - return -RT_EIO; - } - if (flags & RT_I2C_RD) - { - LOG_D("send repeated start condition"); - i2c_restart(ops); - addr1 |= 0x01; - ret = i2c_send_address(bus, addr1, retries); - if ((ret != 1) && !ignore_nack) - { - LOG_E("NACK: sending repeated addr"); - - return -RT_EIO; - } - } - } - else - { - /* 7-bit addr */ - addr1 = msg->addr << 1; - if (flags & RT_I2C_RD) - addr1 |= 1; - ret = i2c_send_address(bus, addr1, retries); - if ((ret != 1) && !ignore_nack) - return -RT_EIO; - } - - return RT_EOK; -} - -static rt_ssize_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, - struct rt_i2c_msg msgs[], - rt_uint32_t num) -{ - struct rt_i2c_msg *msg; - struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; - rt_int32_t ret; - rt_uint32_t i; - rt_uint16_t ignore_nack; - - if((ops->i2c_pin_init_flag == RT_FALSE) && (ops->pin_init != RT_NULL)) - { - ops->pin_init(); - ops->i2c_pin_init_flag = RT_TRUE; - } - - if (num == 0) return 0; - - for (i = 0; i < num; i++) - { - msg = &msgs[i]; - ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; - if (!(msg->flags & RT_I2C_NO_START)) - { - if (i) - { - i2c_restart(ops); - } - else - { - LOG_D("send start condition"); - i2c_start(ops); - } - ret = i2c_bit_send_address(bus, msg); - if ((ret != RT_EOK) && !ignore_nack) - { - LOG_D("receive NACK from device addr 0x%02x msg %d", - msgs[i].addr, i); - goto out; - } - } - if (msg->flags & RT_I2C_RD) - { - ret = i2c_recv_bytes(bus, msg); - if (ret >= 1) - { - LOG_D("read %d byte%s", ret, ret == 1 ? "" : "s"); - } - if (ret < msg->len) - { - if (ret >= 0) - ret = -RT_EIO; - goto out; - } - } - else - { - ret = i2c_send_bytes(bus, msg); - if (ret >= 1) - { - LOG_D("write %d byte%s", ret, ret == 1 ? "" : "s"); - } - if (ret < msg->len) - { - if (ret >= 0) - ret = -RT_ERROR; - goto out; - } - } - } - ret = i; - -out: - if (!(msg->flags & RT_I2C_NO_STOP)) - { - LOG_D("send stop condition"); - i2c_stop(ops); - } - - return ret; -} - -static const struct rt_i2c_bus_device_ops i2c_bit_bus_ops = -{ - i2c_bit_xfer, - RT_NULL, - RT_NULL -}; - -rt_err_t rt_i2c_bit_add_bus(struct rt_i2c_bus_device *bus, - const char *bus_name) -{ - bus->ops = &i2c_bit_bus_ops; - - return rt_i2c_bus_device_register(bus, bus_name); -} diff --git a/components/drivers/i2c/i2c_bus.c b/components/drivers/i2c/i2c_bus.c deleted file mode 100644 index e9626cadd7..0000000000 --- a/components/drivers/i2c/i2c_bus.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-12-06 GuEe-GUI first version - */ - -#include - -#define DBG_TAG "i2c.bus" -#define DBG_LVL DBG_INFO -#include - -static struct rt_bus i2c_bus; - -void i2c_bus_scan_clients(struct rt_i2c_bus_device *bus) -{ -#ifdef RT_USING_OFW - if (bus->parent.ofw_node) - { - struct rt_ofw_node *np = bus->parent.ofw_node, *child_np, *i2c_client_np; - - rt_ofw_foreach_available_child_node(np, child_np) - { - rt_uint32_t client_addr; - struct rt_i2c_client *client; - - if (rt_ofw_prop_read_bool(child_np, "compatible")) - { - i2c_client_np = child_np; - } - else - { - /* Maybe in i2c-mux */ - i2c_client_np = rt_ofw_get_next_child(child_np, RT_NULL); - - if (!rt_ofw_prop_read_bool(i2c_client_np, "compatible")) - { - continue; - } - } - - client = rt_calloc(1, sizeof(*client)); - - if (!client) - { - rt_ofw_node_put(i2c_client_np); - LOG_E("Not memory to create i2c client: %s", - rt_ofw_node_full_name(i2c_client_np)); - - return; - } - - rt_ofw_prop_read_u32(i2c_client_np, "reg", &client_addr); - - client->parent.ofw_node = i2c_client_np; - client->name = rt_ofw_node_name(i2c_client_np); - client->bus = bus; - client->client_addr = client_addr; - - rt_i2c_device_register(client); - - if (i2c_client_np != child_np) - { - rt_ofw_node_put(i2c_client_np); - } - } - } -#endif /* RT_USING_OFW */ -} - -rt_err_t rt_i2c_driver_register(struct rt_i2c_driver *driver) -{ - RT_ASSERT(driver != RT_NULL); - - driver->parent.bus = &i2c_bus; - - return rt_driver_register(&driver->parent); -} - -rt_err_t rt_i2c_device_register(struct rt_i2c_client *client) -{ - RT_ASSERT(client != RT_NULL); - - return rt_bus_add_device(&i2c_bus, &client->parent); -} - -static rt_bool_t i2c_match(rt_driver_t drv, rt_device_t dev) -{ - const struct rt_i2c_device_id *id; - struct rt_i2c_driver *driver = rt_container_of(drv, struct rt_i2c_driver, parent); - struct rt_i2c_client *client = rt_container_of(dev, struct rt_i2c_client, parent); - - if ((id = driver->ids)) - { - for (; id->name[0]; ++id) - { - if (!rt_strcmp(id->name, client->name)) - { - client->id = id; - client->ofw_id = RT_NULL; - - return RT_TRUE; - } - } - } - -#ifdef RT_USING_OFW - client->ofw_id = rt_ofw_node_match(client->parent.ofw_node, driver->ofw_ids); - - if (client->ofw_id) - { - client->id = RT_NULL; - - return RT_TRUE; - } -#endif - - return RT_FALSE; -} - -static rt_err_t i2c_probe(rt_device_t dev) -{ - rt_err_t err; - struct rt_i2c_driver *driver = rt_container_of(dev->drv, struct rt_i2c_driver, parent); - struct rt_i2c_client *client = rt_container_of(dev, struct rt_i2c_client, parent); - - if (!client->bus) - { - return -RT_EINVAL; - } - - err = driver->probe(client); - - return err; -} - -static rt_err_t i2c_remove(rt_device_t dev) -{ - struct rt_i2c_driver *driver = rt_container_of(dev->drv, struct rt_i2c_driver, parent); - struct rt_i2c_client *client = rt_container_of(dev, struct rt_i2c_client, parent); - - if (driver && driver->remove) - { - driver->remove(client); - } - - return RT_EOK; -} - -static rt_err_t i2c_shutdown(rt_device_t dev) -{ - struct rt_i2c_driver *driver = rt_container_of(dev->drv, struct rt_i2c_driver, parent); - struct rt_i2c_client *client = rt_container_of(dev, struct rt_i2c_client, parent); - - if (driver && driver->shutdown) - { - driver->shutdown(client); - } - - return RT_EOK; -} - -static struct rt_bus i2c_bus = -{ - .name = "i2c", - .match = i2c_match, - .probe = i2c_probe, - .remove = i2c_remove, - .shutdown = i2c_shutdown, -}; - -static int i2c_bus_init(void) -{ - rt_bus_register(&i2c_bus); - - return 0; -} -INIT_CORE_EXPORT(i2c_bus_init); diff --git a/components/drivers/i2c/i2c_core.c b/components/drivers/i2c/i2c_core.c deleted file mode 100644 index 2b8e58c90c..0000000000 --- a/components/drivers/i2c/i2c_core.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2012-04-25 weety first version - * 2021-04-20 RiceChen added support for bus control api - */ - -#include - -#define DBG_TAG "I2C" -#ifdef RT_I2C_DEBUG -#define DBG_LVL DBG_LOG -#else -#define DBG_LVL DBG_INFO -#endif -#include - -rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, - const char *bus_name) -{ - rt_err_t res = RT_EOK; - - rt_mutex_init(&bus->lock, "i2c_bus_lock", RT_IPC_FLAG_PRIO); - - if (bus->timeout == 0) bus->timeout = RT_TICK_PER_SECOND; - - res = rt_i2c_bus_device_device_init(bus, bus_name); - - LOG_I("I2C bus [%s] registered", bus_name); - -#ifdef RT_USING_DM - if (!res) - { - i2c_bus_scan_clients(bus); - } -#endif - - return res; -} - -struct rt_i2c_bus_device *rt_i2c_bus_device_find(const char *bus_name) -{ - struct rt_i2c_bus_device *bus; - rt_device_t dev = rt_device_find(bus_name); - if (dev == RT_NULL || dev->type != RT_Device_Class_I2CBUS) - { - LOG_E("I2C bus %s not exist", bus_name); - - return RT_NULL; - } - - bus = (struct rt_i2c_bus_device *)dev->user_data; - - return bus; -} - -rt_ssize_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, - struct rt_i2c_msg msgs[], - rt_uint32_t num) -{ - rt_ssize_t ret; - rt_err_t err; - - if (bus->ops->master_xfer) - { -#ifdef RT_I2C_DEBUG - for (ret = 0; ret < num; ret++) - { - LOG_D("msgs[%d] %c, addr=0x%02x, len=%d", ret, - (msgs[ret].flags & RT_I2C_RD) ? 'R' : 'W', - msgs[ret].addr, msgs[ret].len); - } -#endif - err = rt_mutex_take(&bus->lock, RT_WAITING_FOREVER); - if (err != RT_EOK) - { - return (rt_ssize_t)err; - } - ret = bus->ops->master_xfer(bus, msgs, num); - err = rt_mutex_release(&bus->lock); - if (err != RT_EOK) - { - return (rt_ssize_t)err; - } - return ret; - } - else - { - LOG_E("I2C bus operation not supported"); - return -RT_EINVAL; - } -} - -rt_err_t rt_i2c_control(struct rt_i2c_bus_device *bus, - int cmd, - void *args) -{ - rt_err_t ret; - - if(bus->ops->i2c_bus_control) - { - ret = bus->ops->i2c_bus_control(bus, cmd, args); - return ret; - } - else - { - LOG_E("I2C bus operation not supported"); - return -RT_EINVAL; - } -} - -rt_ssize_t rt_i2c_master_send(struct rt_i2c_bus_device *bus, - rt_uint16_t addr, - rt_uint16_t flags, - const rt_uint8_t *buf, - rt_uint32_t count) -{ - rt_ssize_t ret; - struct rt_i2c_msg msg; - - msg.addr = addr; - msg.flags = flags; - msg.len = count; - msg.buf = (rt_uint8_t *)buf; - - ret = rt_i2c_transfer(bus, &msg, 1); - - return (ret == 1) ? count : ret; -} - -rt_ssize_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus, - rt_uint16_t addr, - rt_uint16_t flags, - rt_uint8_t *buf, - rt_uint32_t count) -{ - rt_ssize_t ret; - struct rt_i2c_msg msg; - RT_ASSERT(bus != RT_NULL); - - msg.addr = addr; - msg.flags = flags | RT_I2C_RD; - msg.len = count; - msg.buf = buf; - - ret = rt_i2c_transfer(bus, &msg, 1); - - return (ret == 1) ? count : ret; -} diff --git a/components/drivers/i2c/i2c_dev.c b/components/drivers/i2c/i2c_dev.c deleted file mode 100644 index 96110b9e7d..0000000000 --- a/components/drivers/i2c/i2c_dev.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2012-04-25 weety first version - * 2014-08-03 bernard fix some compiling warning - * 2021-04-20 RiceChen added support for bus clock control - */ - -#include - -#define DBG_TAG "I2C" -#ifdef RT_I2C_DEBUG -#define DBG_LVL DBG_LOG -#else -#define DBG_LVL DBG_INFO -#endif -#include - -static rt_ssize_t i2c_bus_device_read(rt_device_t dev, - rt_off_t pos, - void *buffer, - rt_size_t count) -{ - rt_uint16_t addr; - rt_uint16_t flags; - struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data; - - RT_ASSERT(bus != RT_NULL); - RT_ASSERT(buffer != RT_NULL); - - LOG_D("I2C bus dev [%s] reading %u bytes.", dev->parent.name, count); - - addr = pos & 0xffff; - flags = (pos >> 16) & 0xffff; - - return rt_i2c_master_recv(bus, addr, flags, (rt_uint8_t *)buffer, count); -} - -static rt_ssize_t i2c_bus_device_write(rt_device_t dev, - rt_off_t pos, - const void *buffer, - rt_size_t count) -{ - rt_uint16_t addr; - rt_uint16_t flags; - struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data; - - RT_ASSERT(bus != RT_NULL); - RT_ASSERT(buffer != RT_NULL); - - LOG_D("I2C bus dev [%s] writing %u bytes.", dev->parent.name, count); - - addr = pos & 0xffff; - flags = (pos >> 16) & 0xffff; - - return rt_i2c_master_send(bus, addr, flags, (const rt_uint8_t *)buffer, count); -} - -static rt_err_t i2c_bus_device_control(rt_device_t dev, - int cmd, - void *args) -{ - rt_err_t ret; - struct rt_i2c_priv_data *priv_data; - struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data; - - RT_ASSERT(bus != RT_NULL); - - switch (cmd) - { - /* set 10-bit addr mode */ - case RT_I2C_DEV_CTRL_10BIT: - bus->flags |= RT_I2C_ADDR_10BIT; - break; - case RT_I2C_DEV_CTRL_TIMEOUT: - bus->timeout = *(rt_uint32_t *)args; - break; - case RT_I2C_DEV_CTRL_RW: - priv_data = (struct rt_i2c_priv_data *)args; - ret = rt_i2c_transfer(bus, priv_data->msgs, priv_data->number); - if (ret < 0) - { - return -RT_EIO; - } - break; - default: - return rt_i2c_control(bus, cmd, args); - } - - return RT_EOK; -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops i2c_ops = -{ - RT_NULL, - RT_NULL, - RT_NULL, - i2c_bus_device_read, - i2c_bus_device_write, - i2c_bus_device_control -}; -#endif - -rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device *bus, - const char *name) -{ - struct rt_device *device; - RT_ASSERT(bus != RT_NULL); - - device = &bus->parent; - - device->user_data = bus; - - /* set device type */ - device->type = RT_Device_Class_I2CBUS; - /* initialize device interface */ -#ifdef RT_USING_DEVICE_OPS - device->ops = &i2c_ops; -#else - device->init = RT_NULL; - device->open = RT_NULL; - device->close = RT_NULL; - device->read = i2c_bus_device_read; - device->write = i2c_bus_device_write; - device->control = i2c_bus_device_control; -#endif - - /* register to device manager */ - rt_device_register(device, name, RT_DEVICE_FLAG_RDWR); - - return RT_EOK; -} diff --git a/components/drivers/i2c/i2c_dm.c b/components/drivers/i2c/i2c_dm.c deleted file mode 100644 index 95b1fe63ab..0000000000 --- a/components/drivers/i2c/i2c_dm.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-12-06 GuEe-GUI first version - */ - -#include - -#define DBG_TAG "i2c.dm" -#define DBG_LVL DBG_INFO -#include - -#ifdef RT_USING_OFW -static void i2c_parse_timing(struct rt_ofw_node *dev_np, const char *propname, - rt_uint32_t *out_value, rt_uint32_t def_value, rt_bool_t use_defaults) -{ - if (rt_ofw_prop_read_u32(dev_np, propname, out_value) && use_defaults) - { - *out_value = def_value; - } -} - -rt_err_t i2c_timings_ofw_parse(struct rt_ofw_node *dev_np, struct i2c_timings *timings, - rt_bool_t use_defaults) -{ - rt_ubase_t def; - rt_bool_t udef = use_defaults; - struct i2c_timings *t = timings; - - i2c_parse_timing(dev_np, "clock-frequency", &t->bus_freq_hz, I2C_MAX_STANDARD_MODE_FREQ, udef); - - def = t->bus_freq_hz <= I2C_MAX_STANDARD_MODE_FREQ ? 1000 : t->bus_freq_hz <= I2C_MAX_FAST_MODE_FREQ ? 300 : 120; - i2c_parse_timing(dev_np, "i2c-scl-rising-time-ns", &t->scl_rise_ns, def, udef); - - def = t->bus_freq_hz <= I2C_MAX_FAST_MODE_FREQ ? 300 : 120; - i2c_parse_timing(dev_np, "i2c-scl-falling-time-ns", &t->scl_fall_ns, def, udef); - - i2c_parse_timing(dev_np, "i2c-scl-internal-delay-ns", &t->scl_int_delay_ns, 0, udef); - i2c_parse_timing(dev_np, "i2c-sda-falling-time-ns", &t->sda_fall_ns, t->scl_fall_ns, udef); - i2c_parse_timing(dev_np, "i2c-sda-hold-time-ns", &t->sda_hold_ns, 0, udef); - i2c_parse_timing(dev_np, "i2c-digital-filter-width-ns", &t->digital_filter_width_ns, 0, udef); - i2c_parse_timing(dev_np, "i2c-analog-filter-cutoff-frequency", &t->analog_filter_cutoff_freq_hz, 0, udef); - - return RT_EOK; -} -#endif /* RT_USING_OFW */ diff --git a/components/drivers/i2c/soft_i2c.c b/components/drivers/i2c/soft_i2c.c deleted file mode 100644 index 54c7395121..0000000000 --- a/components/drivers/i2c/soft_i2c.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2023-07-30 sp-cai first version - */ - -#include - -#ifdef RT_USING_SOFT_I2C -#if !defined(RT_USING_SOFT_I2C1) && !defined(RT_USING_SOFT_I2C2) &&\ - !defined(RT_USING_SOFT_I2C3) && !defined(RT_USING_SOFT_I2C4) &&\ - !defined(RT_USING_SOFT_I2C5) && !defined(RT_USING_SOFT_I2C6) &&\ - !defined(RT_USING_SOFT_I2C7) && !defined(RT_USING_SOFT_I2C8) - #error "Please define at least one RT_USING_SOFT_I2Cx" - /* - This driver can be disabled at: - menuconfig -> RT-Thread Components -> Device Drivers -> Using I2C device drivers - */ -#endif - -#define DBG_ENABLE -#define DBG_TAG "I2C_S" -#ifdef RT_I2C_BITOPS_DEBUG - #define DBG_LEVEL DBG_LOG -#endif -#include - -/* i2c config class */ -struct soft_i2c_config -{ - rt_base_t scl_pin; - rt_base_t sda_pin; - const char *bus_name; - rt_uint16_t timing_delay; /* scl and sda line delay */ - rt_uint16_t timing_timeout; /* in tick */ -}; - -/* i2c dirver class */ -struct rt_soft_i2c -{ - struct rt_i2c_bus_device i2c_bus; - struct rt_i2c_bit_ops ops; -}; - -struct soft_i2c_config i2c_cfg[] = -{ - #ifdef RT_USING_SOFT_I2C1 - { - .scl_pin = RT_SOFT_I2C1_SCL_PIN, - .sda_pin = RT_SOFT_I2C1_SDA_PIN, - .bus_name = RT_SOFT_I2C1_BUS_NAME, - .timing_delay = RT_SOFT_I2C1_TIMING_DELAY, - .timing_timeout = RT_SOFT_I2C1_TIMING_TIMEOUT, - }, - #endif //RT_USING_SOFT_I2C1 - #ifdef RT_USING_SOFT_I2C2 - { - .scl_pin = RT_SOFT_I2C2_SCL_PIN, - .sda_pin = RT_SOFT_I2C2_SDA_PIN, - .bus_name = RT_SOFT_I2C2_BUS_NAME, - .timing_delay = RT_SOFT_I2C2_TIMING_DELAY, - .timing_timeout = RT_SOFT_I2C2_TIMING_TIMEOUT, - }, - #endif //RT_USING_SOFT_I2C2 - #ifdef RT_USING_SOFT_I2C3 - { - .scl_pin = RT_SOFT_I2C3_SCL_PIN, - .sda_pin = RT_SOFT_I2C3_SDA_PIN, - .bus_name = RT_SOFT_I2C3_BUS_NAME, - .timing_delay = RT_SOFT_I2C3_TIMING_DELAY, - .timing_timeout = RT_SOFT_I2C3_TIMING_TIMEOUT, - }, - #endif //RT_USING_SOFT_I2C3 - #ifdef RT_USING_SOFT_I2C4 - { - .scl_pin = RT_SOFT_I2C4_SCL_PIN, - .sda_pin = RT_SOFT_I2C4_SDA_PIN, - .bus_name = RT_SOFT_I2C4_BUS_NAME, - .timing_delay = RT_SOFT_I2C4_TIMING_DELAY, - .timing_timeout = RT_SOFT_I2C4_TIMING_TIMEOUT, - }, - #endif //RT_USING_SOFT_I2C4 - #ifdef RT_USING_SOFT_I2C5 - { - .scl_pin = RT_SOFT_I2C5_SCL_PIN, - .sda_pin = RT_SOFT_I2C5_SDA_PIN, - .bus_name = RT_SOFT_I2C5_BUS_NAME, - .timing_delay = RT_SOFT_I2C5_TIMING_DELAY, - .timing_timeout = RT_SOFT_I2C5_TIMING_TIMEOUT, - }, - #endif //RT_USING_SOFT_I2C5 - #ifdef RT_USING_SOFT_I2C6 - { - .scl_pin = RT_SOFT_I2C6_SCL_PIN, - .sda_pin = RT_SOFT_I2C6_SDA_PIN, - .bus_name = RT_SOFT_I2C6_BUS_NAME, - .timing_delay = RT_SOFT_I2C6_TIMING_DELAY, - .timing_timeout = RT_SOFT_I2C6_TIMING_TIMEOUT, - }, - #endif //RT_USING_SOFT_I2C6 - #ifdef RT_USING_SOFT_I2C7 - { - .scl_pin = RT_SOFT_I2C7_SCL_PIN, - .sda_pin = RT_SOFT_I2C7_SDA_PIN, - .bus_name = RT_SOFT_I2C7_BUS_NAME, - .timing_delay = RT_SOFT_I2C7_TIMING_DELAY, - .timing_timeout = RT_SOFT_I2C7_TIMING_TIMEOUT, - }, - #endif //RT_USING_SOFT_I2C7 - #ifdef RT_USING_SOFT_I2C8 - { - .scl_pin = RT_SOFT_I2C8_SCL_PIN, - .sda_pin = RT_SOFT_I2C8_SDA_PIN, - .bus_name = RT_SOFT_I2C8_BUS_NAME, - .timing_delay = RT_SOFT_I2C8_TIMING_DELAY, - .timing_timeout = RT_SOFT_I2C8_TIMING_TIMEOUT, - }, - #endif //RT_USING_SOFT_I2C8 -}; - - -static struct rt_soft_i2c i2c_bus_obj[sizeof(i2c_cfg) / sizeof(i2c_cfg[0])] = -{ 0 }; - -/** -* This function initializes the i2c pin. -* @param i2c config class. -*/ -static void pin_init(const struct soft_i2c_config *cfg) -{ - rt_pin_mode(cfg->scl_pin, PIN_MODE_OUTPUT_OD); - rt_pin_mode(cfg->sda_pin, PIN_MODE_OUTPUT_OD); - rt_pin_write(cfg->scl_pin, PIN_HIGH); - rt_pin_write(cfg->sda_pin, PIN_HIGH); -} - - -/** -* This function sets the sda pin. -* @param i2c config class. -* @param The sda pin state. -*/ -static void set_sda(void *cfg, rt_int32_t value) -{ - rt_pin_write(((const struct soft_i2c_config*)cfg)->sda_pin, value); -} - -/** -* This function sets the scl pin. -* @param i2c config class. -* @param The sda pin state. -*/ -static void set_scl(void *cfg, rt_int32_t value) -{ - rt_pin_write(((const struct soft_i2c_config*)cfg)->scl_pin, value); -} - -/** -* This function gets the sda pin state. -* @param i2c config class. -*/ -static rt_int32_t get_sda(void *cfg) -{ - return rt_pin_read(((const struct soft_i2c_config*)cfg)->sda_pin); -} - -/** -* This function gets the scl pin state. -* @param i2c config class. -*/ -static rt_int32_t get_scl(void *cfg) -{ - return rt_pin_read(((const struct soft_i2c_config*)cfg)->scl_pin); -} - - -static const struct rt_i2c_bit_ops soft_i2c_ops = -{ - .set_sda = set_sda, - .set_scl = set_scl, - .get_sda = get_sda, - .get_scl = get_scl, - .udelay = rt_hw_us_delay, -}; - -/** -* if i2c is locked, this function will unlock it -* -* @param i2c config class. -* -* @return RT_EOK indicates successful unlock. -*/ -static rt_err_t i2c_bus_unlock(const struct soft_i2c_config *cfg) -{ - rt_ubase_t i = 0; - - if(PIN_LOW == rt_pin_read(cfg->sda_pin)) - { - while(i++ < 9) - { - rt_pin_write(cfg->scl_pin, PIN_HIGH); - rt_hw_us_delay(cfg->timing_delay); - rt_pin_write(cfg->scl_pin, PIN_LOW); - rt_hw_us_delay(cfg->timing_delay); - } - } - if(PIN_LOW == rt_pin_read(cfg->sda_pin)) - { - return -RT_ERROR; - } - - return RT_EOK; -} - -/* I2C initialization function */ -int rt_soft_i2c_init(void) -{ - int err = RT_EOK; - struct rt_soft_i2c *obj; - int i; - - for(i = 0; i < sizeof(i2c_bus_obj) / sizeof(i2c_bus_obj[0]); i++) - { - struct soft_i2c_config *cfg = &i2c_cfg[i]; - - pin_init(cfg); - - obj = &i2c_bus_obj[i]; - obj->ops = soft_i2c_ops; - obj->ops.data = cfg; - obj->i2c_bus.priv = &obj->ops; - obj->ops.delay_us = cfg->timing_delay; - obj->ops.timeout = cfg->timing_timeout; - if(rt_i2c_bit_add_bus(&obj->i2c_bus, cfg->bus_name) == RT_EOK) - { - i2c_bus_unlock(cfg); - LOG_D("Software simulation %s init done" - ", SCL pin: 0x%02X, SDA pin: 0x%02X" - , cfg->bus_name - , cfg->scl_pin - , cfg->sda_pin - ); - } - else - { - err++; - LOG_E("Software simulation %s init fail" - ", SCL pin: 0x%02X, SDA pin: 0x%02X" - , cfg->bus_name - , cfg->scl_pin - , cfg->sda_pin - ); - } - } - - return err; -} -INIT_PREV_EXPORT(rt_soft_i2c_init); - -#endif // RT_USING_SOFT_I2C diff --git a/components/drivers/include/drivers/alarm.h b/components/drivers/include/drivers/alarm.h deleted file mode 100644 index 864933d78c..0000000000 --- a/components/drivers/include/drivers/alarm.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2012-10-27 heyuanjie87 first version. - * 2013-05-17 aozima initial alarm event & mutex in system init. - * 2020-10-15 zhangsz add alarm flags hour minute second. - */ - -#ifndef __ALARM_H__ -#define __ALARM_H__ - -#include -#include - -#define RT_ALARM_TM_NOW -1 /* set the alarm tm_day,tm_mon,tm_sec,etc. - to now.we also call it "don't care" value */ - -/* alarm flags */ -#define RT_ALARM_ONESHOT 0x000 /* only alarm once */ -#define RT_ALARM_DAILY 0x100 /* alarm everyday */ -#define RT_ALARM_WEEKLY 0x200 /* alarm weekly at Monday or Friday etc. */ -#define RT_ALARM_MONTHLY 0x400 /* alarm monthly at someday */ -#define RT_ALARM_YAERLY 0x800 /* alarm yearly at a certain date */ -#define RT_ALARM_HOUR 0x1000 /* alarm each hour at a certain min:second */ -#define RT_ALARM_MINUTE 0x2000 /* alarm each minute at a certain second */ -#define RT_ALARM_SECOND 0x4000 /* alarm each second */ - -#define RT_ALARM_STATE_INITED 0x02 -#define RT_ALARM_STATE_START 0x01 -#define RT_ALARM_STATE_STOP 0x00 - -/* alarm control cmd */ -#define RT_ALARM_CTRL_MODIFY 1 /* modify alarm time or alarm flag */ - -typedef struct rt_alarm *rt_alarm_t; -typedef void (*rt_alarm_callback_t)(rt_alarm_t alarm, time_t timestamp); - -struct rt_alarm -{ - rt_list_t list; - rt_uint32_t flag; - rt_alarm_callback_t callback; - struct tm wktime; - - void *user_data; -}; - -struct rt_alarm_setup -{ - rt_uint32_t flag; /* alarm flag */ - struct tm wktime; /* when will the alarm wake up user */ -}; - -struct rt_alarm_container -{ - rt_list_t head; - struct rt_mutex mutex; - struct rt_event event; - struct rt_alarm *current; -}; - -rt_alarm_t rt_alarm_create(rt_alarm_callback_t callback, - struct rt_alarm_setup *setup); -rt_err_t rt_alarm_control(rt_alarm_t alarm, int cmd, void *arg); -void rt_alarm_update(rt_device_t dev, rt_uint32_t event); -rt_err_t rt_alarm_delete(rt_alarm_t alarm); -rt_err_t rt_alarm_start(rt_alarm_t alarm); -rt_err_t rt_alarm_stop(rt_alarm_t alarm); -int rt_alarm_system_init(void); - -#endif /* __ALARM_H__ */ diff --git a/components/drivers/include/drivers/audio.h b/components/drivers/include/drivers/audio.h deleted file mode 100644 index 6d98272556..0000000000 --- a/components/drivers/include/drivers/audio.h +++ /dev/null @@ -1,176 +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 - * - */ - -#ifndef __AUDIO_H__ -#define __AUDIO_H__ - -#include "audio_pipe.h" - -/* AUDIO command */ -#define _AUDIO_CTL(a) (RT_DEVICE_CTRL_BASE(Sound) + a) - -#define AUDIO_CTL_GETCAPS _AUDIO_CTL(1) -#define AUDIO_CTL_CONFIGURE _AUDIO_CTL(2) -#define AUDIO_CTL_START _AUDIO_CTL(3) -#define AUDIO_CTL_STOP _AUDIO_CTL(4) -#define AUDIO_CTL_GETBUFFERINFO _AUDIO_CTL(5) - -/* Audio Device Types */ -#define AUDIO_TYPE_QUERY 0x00 -#define AUDIO_TYPE_INPUT 0x01 -#define AUDIO_TYPE_OUTPUT 0x02 -#define AUDIO_TYPE_MIXER 0x04 - -/* Supported Sampling Rates */ -#define AUDIO_SAMP_RATE_8K 0x0001 -#define AUDIO_SAMP_RATE_11K 0x0002 -#define AUDIO_SAMP_RATE_16K 0x0004 -#define AUDIO_SAMP_RATE_22K 0x0008 -#define AUDIO_SAMP_RATE_32K 0x0010 -#define AUDIO_SAMP_RATE_44K 0x0020 -#define AUDIO_SAMP_RATE_48K 0x0040 -#define AUDIO_SAMP_RATE_96K 0x0080 -#define AUDIO_SAMP_RATE_128K 0x0100 -#define AUDIO_SAMP_RATE_160K 0x0200 -#define AUDIO_SAMP_RATE_172K 0x0400 -#define AUDIO_SAMP_RATE_192K 0x0800 - -/* Supported Bit Rates */ -#define AUDIO_BIT_RATE_22K 0x01 -#define AUDIO_BIT_RATE_44K 0x02 -#define AUDIO_BIT_RATE_48K 0x04 -#define AUDIO_BIT_RATE_96K 0x08 -#define AUDIO_BIT_RATE_128K 0x10 -#define AUDIO_BIT_RATE_160K 0x20 -#define AUDIO_BIT_RATE_172K 0x40 -#define AUDIO_BIT_RATE_192K 0x80 - -/* Support Dsp(input/output) Units controls */ -#define AUDIO_DSP_PARAM 0 /* get/set all params */ -#define AUDIO_DSP_SAMPLERATE 1 /* samplerate */ -#define AUDIO_DSP_CHANNELS 2 /* channels */ -#define AUDIO_DSP_SAMPLEBITS 3 /* sample bits width */ - -/* Supported Mixer Units controls */ -#define AUDIO_MIXER_QUERY 0x0000 -#define AUDIO_MIXER_MUTE 0x0001 -#define AUDIO_MIXER_VOLUME 0x0002 -#define AUDIO_MIXER_BASS 0x0004 -#define AUDIO_MIXER_MID 0x0008 -#define AUDIO_MIXER_TREBLE 0x0010 -#define AUDIO_MIXER_EQUALIZER 0x0020 -#define AUDIO_MIXER_LINE 0x0040 -#define AUDIO_MIXER_DIGITAL 0x0080 -#define AUDIO_MIXER_MIC 0x0100 -#define AUDIO_MIXER_VITURAL 0x0200 -#define AUDIO_MIXER_EXTEND 0x8000 /* extend mixer command */ - -#define AUDIO_VOLUME_MAX (100) -#define AUDIO_VOLUME_MIN (0) - -#define CFG_AUDIO_REPLAY_QUEUE_COUNT 4 - -enum -{ - AUDIO_STREAM_REPLAY = 0, - AUDIO_STREAM_RECORD, - AUDIO_STREAM_LAST = AUDIO_STREAM_RECORD, -}; - -/* the preferred number and size of audio pipeline buffer for the audio device */ -struct rt_audio_buf_info -{ - rt_uint8_t *buffer; - rt_uint16_t block_size; - rt_uint16_t block_count; - rt_uint32_t total_size; -}; - -struct rt_audio_device; -struct rt_audio_caps; -struct rt_audio_configure; -struct rt_audio_ops -{ - rt_err_t (*getcaps)(struct rt_audio_device *audio, struct rt_audio_caps *caps); - rt_err_t (*configure)(struct rt_audio_device *audio, struct rt_audio_caps *caps); - rt_err_t (*init)(struct rt_audio_device *audio); - rt_err_t (*start)(struct rt_audio_device *audio, int stream); - rt_err_t (*stop)(struct rt_audio_device *audio, int stream); - rt_ssize_t (*transmit)(struct rt_audio_device *audio, const void *writeBuf, void *readBuf, rt_size_t size); - /* get page size of codec or private buffer's info */ - void (*buffer_info)(struct rt_audio_device *audio, struct rt_audio_buf_info *info); -}; - -struct rt_audio_configure -{ - rt_uint32_t samplerate; - rt_uint16_t channels; - rt_uint16_t samplebits; -}; - -struct rt_audio_caps -{ - int main_type; - int sub_type; - - union - { - rt_uint32_t mask; - int value; - struct rt_audio_configure config; - } udata; -}; - -struct rt_audio_replay -{ - struct rt_mempool *mp; - struct rt_data_queue queue; - struct rt_mutex lock; - struct rt_completion cmp; - struct rt_audio_buf_info buf_info; - rt_uint8_t *write_data; - rt_uint16_t write_index; - rt_uint16_t read_index; - rt_uint32_t pos; - rt_uint8_t event; - rt_bool_t activated; -}; - -struct rt_audio_record -{ - struct rt_audio_pipe pipe; - rt_bool_t activated; -}; - -struct rt_audio_device -{ - struct rt_device parent; - struct rt_audio_ops *ops; - struct rt_audio_replay *replay; - struct rt_audio_record *record; -}; - -rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data); -void rt_audio_tx_complete(struct rt_audio_device *audio); -void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len); - -/* Device Control Commands */ -#define CODEC_CMD_RESET 0 -#define CODEC_CMD_SET_VOLUME 1 -#define CODEC_CMD_GET_VOLUME 2 -#define CODEC_CMD_SAMPLERATE 3 -#define CODEC_CMD_EQ 4 -#define CODEC_CMD_3D 5 - -#define CODEC_VOLUME_MAX (63) - -#endif /* __AUDIO_H__ */ diff --git a/components/drivers/include/drivers/can.h b/components/drivers/include/drivers/can.h deleted file mode 100644 index 2ce60d8072..0000000000 --- a/components/drivers/include/drivers/can.h +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (c) 2006-2023, 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 remove RT_CAN_USING_LED. - * 2022-05-08 hpmicro add CANFD support, fixed typos - */ - -#ifndef CAN_H_ -#define CAN_H_ - -#include - -#ifndef RT_CANMSG_BOX_SZ -#define RT_CANMSG_BOX_SZ 16 -#endif -#ifndef RT_CANSND_BOX_NUM -#define RT_CANSND_BOX_NUM 1 -#endif - -enum CAN_DLC -{ - CAN_MSG_0BYTE = 0, - CAN_MSG_1BYTE, - CAN_MSG_2BYTES, - CAN_MSG_3BYTES, - CAN_MSG_4BYTES, - CAN_MSG_5BYTES, - CAN_MSG_6BYTES, - CAN_MSG_7BYTES, - CAN_MSG_8BYTES, - CAN_MSG_12BYTES, - CAN_MSG_16BYTES, - CAN_MSG_20BYTES, - CAN_MSG_24BYTES, - CAN_MSG_32BYTES, - CAN_MSG_48BYTES, - CAN_MSG_64BYTES, -}; - -enum CANBAUD -{ - CAN1MBaud = 1000UL * 1000,/* 1 MBit/sec */ - CAN800kBaud = 1000UL * 800, /* 800 kBit/sec */ - CAN500kBaud = 1000UL * 500, /* 500 kBit/sec */ - CAN250kBaud = 1000UL * 250, /* 250 kBit/sec */ - CAN125kBaud = 1000UL * 125, /* 125 kBit/sec */ - CAN100kBaud = 1000UL * 100, /* 100 kBit/sec */ - CAN50kBaud = 1000UL * 50, /* 50 kBit/sec */ - CAN20kBaud = 1000UL * 20, /* 20 kBit/sec */ - CAN10kBaud = 1000UL * 10 /* 10 kBit/sec */ -}; - -#define RT_CAN_MODE_NORMAL 0 -#define RT_CAN_MODE_LISTEN 1 -#define RT_CAN_MODE_LOOPBACK 2 -#define RT_CAN_MODE_LOOPBACKANLISTEN 3 - -#define RT_CAN_MODE_PRIV 0x01 -#define RT_CAN_MODE_NOPRIV 0x00 - -/** @defgroup CAN_receive_FIFO_number CAN Receive FIFO Number - * @{ - */ -#define CAN_RX_FIFO0 (0x00000000U) /*!< CAN receive FIFO 0 */ -#define CAN_RX_FIFO1 (0x00000001U) /*!< CAN receive FIFO 1 */ - -struct rt_can_filter_item -{ - rt_uint32_t id : 29; - rt_uint32_t ide : 1; - rt_uint32_t rtr : 1; - rt_uint32_t mode : 1; - rt_uint32_t mask; - rt_int32_t hdr_bank;/*Should be defined as:rx.FilterBank,which should be changed to rt_int32_t hdr_bank*/ - rt_uint32_t rxfifo;/*Add a configuration item that CAN_RX_FIFO0/CAN_RX_FIFO1*/ -#ifdef RT_CAN_USING_HDR - rt_err_t (*ind)(rt_device_t dev, void *args , rt_int32_t hdr, rt_size_t size); - void *args; -#endif /*RT_CAN_USING_HDR*/ -}; - - -#ifdef RT_CAN_USING_HDR -#define RT_CAN_FILTER_ITEM_INIT(id,ide,rtr,mode,mask,ind,args) \ - {(id), (ide), (rtr), (mode),(mask), -1, CAN_RX_FIFO0,(ind), (args)}/*0:CAN_RX_FIFO0*/ -#define RT_CAN_FILTER_STD_INIT(id,ind,args) \ - RT_CAN_FILTER_ITEM_INIT(id,0,0,0,0xFFFFFFFF,ind,args) -#define RT_CAN_FILTER_EXT_INIT(id,ind,args) \ - RT_CAN_FILTER_ITEM_INIT(id,1,0,0,0xFFFFFFFF,ind,args) -#define RT_CAN_STD_RMT_FILTER_INIT(id,ind,args) \ - RT_CAN_FILTER_ITEM_INIT(id,0,1,0,0xFFFFFFFF,ind,args) -#define RT_CAN_EXT_RMT_FILTER_INIT(id,ind,args) \ - RT_CAN_FILTER_ITEM_INIT(id,1,1,0,0xFFFFFFFF,ind,args) -#define RT_CAN_STD_RMT_DATA_FILTER_INIT(id,ind,args) \ - RT_CAN_FILTER_ITEM_INIT(id,0,0,1,0xFFFFFFFF,ind,args) -#define RT_CAN_EXT_RMT_DATA_FILTER_INIT(id,ind,args) \ - RT_CAN_FILTER_ITEM_INIT(id,1,0,1,0xFFFFFFFF,ind,args) -#else - -#define RT_CAN_FILTER_ITEM_INIT(id,ide,rtr,mode,mask) \ - {(id), (ide), (rtr), (mode), (mask), -1, CAN_RX_FIFO0 }/*0:CAN_RX_FIFO0*/ -#define RT_CAN_FILTER_STD_INIT(id) \ - RT_CAN_FILTER_ITEM_INIT(id,0,0,0,0xFFFFFFFF) -#define RT_CAN_FILTER_EXT_INIT(id) \ - RT_CAN_FILTER_ITEM_INIT(id,1,0,0,0xFFFFFFFF) -#define RT_CAN_STD_RMT_FILTER_INIT(id) \ - RT_CAN_FILTER_ITEM_INIT(id,0,1,0,0xFFFFFFFF) -#define RT_CAN_EXT_RMT_FILTER_INIT(id) \ - RT_CAN_FILTER_ITEM_INIT(id,1,1,0,0xFFFFFFFF) -#define RT_CAN_STD_RMT_DATA_FILTER_INIT(id) \ - RT_CAN_FILTER_ITEM_INIT(id,0,0,1,0xFFFFFFFF) -#define RT_CAN_EXT_RMT_DATA_FILTER_INIT(id) \ - RT_CAN_FILTER_ITEM_INIT(id,1,0,1,0xFFFFFFFF) -#endif - -struct rt_can_filter_config -{ - rt_uint32_t count; - rt_uint32_t actived; - struct rt_can_filter_item *items; -}; - -struct rt_can_bit_timing -{ - rt_uint16_t prescaler; /* Pre-scaler */ - rt_uint16_t num_seg1; /* Bit Timing Segment 1, in terms of Tq */ - rt_uint16_t num_seg2; /* Bit Timing Segment 2, in terms of Tq */ - rt_uint8_t num_sjw; /* Synchronization Jump Width, in terms of Tq */ - rt_uint8_t num_sspoff; /* Secondary Sample Point Offset, in terms of Tq */ -}; - -/** - * CAN bit timing configuration list - * NOTE: - * items[0] always for CAN2.0/CANFD Arbitration Phase - * items[1] always for CANFD (if it exists) - */ -struct rt_can_bit_timing_config -{ - rt_uint32_t count; - struct rt_can_bit_timing *items; -}; - -struct can_configure -{ - rt_uint32_t baud_rate; - rt_uint32_t msgboxsz; - rt_uint32_t sndboxnumber; - rt_uint32_t mode : 8; - rt_uint32_t privmode : 8; - rt_uint32_t reserved : 16; - rt_uint32_t ticks; -#ifdef RT_CAN_USING_HDR - rt_uint32_t maxhdr; -#endif - -#ifdef RT_CAN_USING_CANFD - rt_uint32_t baud_rate_fd; /* CANFD data bit rate*/ - rt_uint32_t use_bit_timing: 8; /* Use the bit timing for CAN timing configuration */ - rt_uint32_t enable_canfd : 8; /* Enable CAN-FD mode */ - rt_uint32_t reserved1 : 16; - - /* The below fields take effect only if use_bit_timing is non-zero */ - struct rt_can_bit_timing can_timing; /* CAN bit-timing /CANFD bit-timing for arbitration phase */ - struct rt_can_bit_timing canfd_timing; /* CANFD bit-timing for datat phase */ -#endif -}; - -#define CANDEFAULTCONFIG \ -{\ - CAN1MBaud,\ - RT_CANMSG_BOX_SZ,\ - RT_CANSND_BOX_NUM,\ - RT_CAN_MODE_NORMAL,\ -}; - -struct rt_can_ops; -#define RT_CAN_CMD_SET_FILTER 0x13 -#define RT_CAN_CMD_SET_BAUD 0x14 -#define RT_CAN_CMD_SET_MODE 0x15 -#define RT_CAN_CMD_SET_PRIV 0x16 -#define RT_CAN_CMD_GET_STATUS 0x17 -#define RT_CAN_CMD_SET_STATUS_IND 0x18 -#define RT_CAN_CMD_SET_BUS_HOOK 0x19 -#define RT_CAN_CMD_SET_CANFD 0x1A -#define RT_CAN_CMD_SET_BAUD_FD 0x1B -#define RT_CAN_CMD_SET_BITTIMING 0x1C - -#define RT_DEVICE_CAN_INT_ERR 0x1000 - -enum RT_CAN_STATUS_MODE -{ - NORMAL = 0, - ERRWARNING = 1, - ERRPASSIVE = 2, - BUSOFF = 4, -}; -enum RT_CAN_BUS_ERR -{ - RT_CAN_BUS_NO_ERR = 0, - RT_CAN_BUS_BIT_PAD_ERR = 1, - RT_CAN_BUS_FORMAT_ERR = 2, - RT_CAN_BUS_ACK_ERR = 3, - RT_CAN_BUS_IMPLICIT_BIT_ERR = 4, - RT_CAN_BUS_EXPLICIT_BIT_ERR = 5, - RT_CAN_BUS_CRC_ERR = 6, -}; - -struct rt_can_status -{ - rt_uint32_t rcverrcnt; - rt_uint32_t snderrcnt; - rt_uint32_t errcode; - rt_uint32_t rcvpkg; - rt_uint32_t dropedrcvpkg; - rt_uint32_t sndpkg; - rt_uint32_t dropedsndpkg; - rt_uint32_t bitpaderrcnt; - rt_uint32_t formaterrcnt; - rt_uint32_t ackerrcnt; - rt_uint32_t biterrcnt; - rt_uint32_t crcerrcnt; - rt_uint32_t rcvchange; - rt_uint32_t sndchange; - rt_uint32_t lasterrtype; -}; - -#ifdef RT_CAN_USING_HDR -struct rt_can_hdr -{ - rt_uint32_t connected; - rt_uint32_t msgs; - struct rt_can_filter_item filter; - struct rt_list_node list; -}; -#endif -struct rt_can_device; -typedef rt_err_t (*rt_canstatus_ind)(struct rt_can_device *, void *); -typedef struct rt_can_status_ind_type -{ - rt_canstatus_ind ind; - void *args; -} *rt_can_status_ind_type_t; -typedef void (*rt_can_bus_hook)(struct rt_can_device *); -struct rt_can_device -{ - struct rt_device parent; - - const struct rt_can_ops *ops; - struct can_configure config; - struct rt_can_status status; - - rt_uint32_t timerinitflag; - struct rt_timer timer; - - struct rt_can_status_ind_type status_indicate; -#ifdef RT_CAN_USING_HDR - struct rt_can_hdr *hdr; -#endif -#ifdef RT_CAN_USING_BUS_HOOK - rt_can_bus_hook bus_hook; -#endif /*RT_CAN_USING_BUS_HOOK*/ - struct rt_mutex lock; - void *can_rx; - void *can_tx; -}; -typedef struct rt_can_device *rt_can_t; - -#define RT_CAN_STDID 0 -#define RT_CAN_EXTID 1 -#define RT_CAN_DTR 0 -#define RT_CAN_RTR 1 - -typedef struct rt_can_status *rt_can_status_t; - -struct rt_can_msg -{ - rt_uint32_t id : 29; - rt_uint32_t ide : 1; - rt_uint32_t rtr : 1; - rt_uint32_t rsv : 1; - rt_uint32_t len : 8; - rt_uint32_t priv : 8; - rt_int32_t hdr_index : 8;/*Should be defined as:rx.FilterMatchIndex,which should be changed to rt_int32_t hdr_index : 8*/ -#ifdef RT_CAN_USING_CANFD - rt_uint32_t fd_frame : 1; - rt_uint32_t brs : 1; - rt_uint32_t rxfifo : 2;/*Redefined to return :CAN RX FIFO0/CAN RX FIFO1*/ - rt_uint32_t reserved : 4; -#else - rt_uint32_t rxfifo : 2;/*Redefined to return :CAN RX FIFO0/CAN RX FIFO1*/ - rt_uint32_t reserved : 6; -#endif -#ifdef RT_CAN_USING_CANFD - rt_uint8_t data[64]; -#else - rt_uint8_t data[8]; -#endif -}; -typedef struct rt_can_msg *rt_can_msg_t; - -struct rt_can_msg_list -{ - struct rt_list_node list; -#ifdef RT_CAN_USING_HDR - struct rt_list_node hdrlist; - struct rt_can_hdr *owner; -#endif - struct rt_can_msg data; -}; - -struct rt_can_rx_fifo -{ - /* software fifo */ - struct rt_can_msg_list *buffer; - rt_uint32_t freenumbers; - struct rt_list_node freelist; - struct rt_list_node uselist; -}; - -#define RT_CAN_SND_RESULT_OK 0 -#define RT_CAN_SND_RESULT_ERR 1 -#define RT_CAN_SND_RESULT_WAIT 2 - -#define RT_CAN_EVENT_RX_IND 0x01 /* Rx indication */ -#define RT_CAN_EVENT_TX_DONE 0x02 /* Tx complete */ -#define RT_CAN_EVENT_TX_FAIL 0x03 /* Tx fail */ -#define RT_CAN_EVENT_RX_TIMEOUT 0x05 /* Rx timeout */ -#define RT_CAN_EVENT_RXOF_IND 0x06 /* Rx overflow */ - -struct rt_can_sndbxinx_list -{ - struct rt_list_node list; - struct rt_completion completion; - rt_uint32_t result; -}; - -struct rt_can_tx_fifo -{ - struct rt_can_sndbxinx_list *buffer; - struct rt_semaphore sem; - struct rt_list_node freelist; -}; - -struct rt_can_ops -{ - rt_err_t (*configure)(struct rt_can_device *can, struct can_configure *cfg); - rt_err_t (*control)(struct rt_can_device *can, int cmd, void *arg); - rt_ssize_t (*sendmsg)(struct rt_can_device *can, const void *buf, rt_uint32_t boxno); - rt_ssize_t (*recvmsg)(struct rt_can_device *can, void *buf, rt_uint32_t boxno); -}; - -rt_err_t rt_hw_can_register(struct rt_can_device *can, - const char *name, - const struct rt_can_ops *ops, - void *data); -void rt_hw_can_isr(struct rt_can_device *can, int event); -#endif /*_CAN_H*/ - diff --git a/components/drivers/include/drivers/dev_alarm.h b/components/drivers/include/drivers/dev_alarm.h new file mode 100644 index 0000000000..4553569260 --- /dev/null +++ b/components/drivers/include/drivers/dev_alarm.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-10-27 heyuanjie87 first version. + * 2013-05-17 aozima initial alarm event & mutex in system init. + * 2020-10-15 zhangsz add alarm flags hour minute second. + */ + +#ifndef __DEV_ALARM_H__ +#define __DEV_ALARM_H__ + +#include +#include + +#define RT_ALARM_TM_NOW -1 /* set the alarm tm_day,tm_mon,tm_sec,etc. + to now.we also call it "don't care" value */ + +/* alarm flags */ +#define RT_ALARM_ONESHOT 0x000 /* only alarm once */ +#define RT_ALARM_DAILY 0x100 /* alarm everyday */ +#define RT_ALARM_WEEKLY 0x200 /* alarm weekly at Monday or Friday etc. */ +#define RT_ALARM_MONTHLY 0x400 /* alarm monthly at someday */ +#define RT_ALARM_YAERLY 0x800 /* alarm yearly at a certain date */ +#define RT_ALARM_HOUR 0x1000 /* alarm each hour at a certain min:second */ +#define RT_ALARM_MINUTE 0x2000 /* alarm each minute at a certain second */ +#define RT_ALARM_SECOND 0x4000 /* alarm each second */ + +#define RT_ALARM_STATE_INITED 0x02 +#define RT_ALARM_STATE_START 0x01 +#define RT_ALARM_STATE_STOP 0x00 + +/* alarm control cmd */ +#define RT_ALARM_CTRL_MODIFY 1 /* modify alarm time or alarm flag */ + +typedef struct rt_alarm *rt_alarm_t; +typedef void (*rt_alarm_callback_t)(rt_alarm_t alarm, time_t timestamp); + +struct rt_alarm +{ + rt_list_t list; + rt_uint32_t flag; + rt_alarm_callback_t callback; + struct tm wktime; + + void *user_data; +}; + +struct rt_alarm_setup +{ + rt_uint32_t flag; /* alarm flag */ + struct tm wktime; /* when will the alarm wake up user */ +}; + +struct rt_alarm_container +{ + rt_list_t head; + struct rt_mutex mutex; + struct rt_event event; + struct rt_alarm *current; +}; + +rt_alarm_t rt_alarm_create(rt_alarm_callback_t callback, + struct rt_alarm_setup *setup); +rt_err_t rt_alarm_control(rt_alarm_t alarm, int cmd, void *arg); +void rt_alarm_update(rt_device_t dev, rt_uint32_t event); +rt_err_t rt_alarm_delete(rt_alarm_t alarm); +rt_err_t rt_alarm_start(rt_alarm_t alarm); +rt_err_t rt_alarm_stop(rt_alarm_t alarm); +int rt_alarm_system_init(void); + +#endif /* __DEV_ALARM_H__ */ diff --git a/components/drivers/include/drivers/dev_audio.h b/components/drivers/include/drivers/dev_audio.h new file mode 100644 index 0000000000..ef92a935ab --- /dev/null +++ b/components/drivers/include/drivers/dev_audio.h @@ -0,0 +1,176 @@ +/* + * 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 + * + */ + +#ifndef __DEV_AUDIO_H__ +#define __DEV_AUDIO_H__ + +#include "dev_audio_pipe.h" + +/* AUDIO command */ +#define _AUDIO_CTL(a) (RT_DEVICE_CTRL_BASE(Sound) + a) + +#define AUDIO_CTL_GETCAPS _AUDIO_CTL(1) +#define AUDIO_CTL_CONFIGURE _AUDIO_CTL(2) +#define AUDIO_CTL_START _AUDIO_CTL(3) +#define AUDIO_CTL_STOP _AUDIO_CTL(4) +#define AUDIO_CTL_GETBUFFERINFO _AUDIO_CTL(5) + +/* Audio Device Types */ +#define AUDIO_TYPE_QUERY 0x00 +#define AUDIO_TYPE_INPUT 0x01 +#define AUDIO_TYPE_OUTPUT 0x02 +#define AUDIO_TYPE_MIXER 0x04 + +/* Supported Sampling Rates */ +#define AUDIO_SAMP_RATE_8K 0x0001 +#define AUDIO_SAMP_RATE_11K 0x0002 +#define AUDIO_SAMP_RATE_16K 0x0004 +#define AUDIO_SAMP_RATE_22K 0x0008 +#define AUDIO_SAMP_RATE_32K 0x0010 +#define AUDIO_SAMP_RATE_44K 0x0020 +#define AUDIO_SAMP_RATE_48K 0x0040 +#define AUDIO_SAMP_RATE_96K 0x0080 +#define AUDIO_SAMP_RATE_128K 0x0100 +#define AUDIO_SAMP_RATE_160K 0x0200 +#define AUDIO_SAMP_RATE_172K 0x0400 +#define AUDIO_SAMP_RATE_192K 0x0800 + +/* Supported Bit Rates */ +#define AUDIO_BIT_RATE_22K 0x01 +#define AUDIO_BIT_RATE_44K 0x02 +#define AUDIO_BIT_RATE_48K 0x04 +#define AUDIO_BIT_RATE_96K 0x08 +#define AUDIO_BIT_RATE_128K 0x10 +#define AUDIO_BIT_RATE_160K 0x20 +#define AUDIO_BIT_RATE_172K 0x40 +#define AUDIO_BIT_RATE_192K 0x80 + +/* Support Dsp(input/output) Units controls */ +#define AUDIO_DSP_PARAM 0 /* get/set all params */ +#define AUDIO_DSP_SAMPLERATE 1 /* samplerate */ +#define AUDIO_DSP_CHANNELS 2 /* channels */ +#define AUDIO_DSP_SAMPLEBITS 3 /* sample bits width */ + +/* Supported Mixer Units controls */ +#define AUDIO_MIXER_QUERY 0x0000 +#define AUDIO_MIXER_MUTE 0x0001 +#define AUDIO_MIXER_VOLUME 0x0002 +#define AUDIO_MIXER_BASS 0x0004 +#define AUDIO_MIXER_MID 0x0008 +#define AUDIO_MIXER_TREBLE 0x0010 +#define AUDIO_MIXER_EQUALIZER 0x0020 +#define AUDIO_MIXER_LINE 0x0040 +#define AUDIO_MIXER_DIGITAL 0x0080 +#define AUDIO_MIXER_MIC 0x0100 +#define AUDIO_MIXER_VITURAL 0x0200 +#define AUDIO_MIXER_EXTEND 0x8000 /* extend mixer command */ + +#define AUDIO_VOLUME_MAX (100) +#define AUDIO_VOLUME_MIN (0) + +#define CFG_AUDIO_REPLAY_QUEUE_COUNT 4 + +enum +{ + AUDIO_STREAM_REPLAY = 0, + AUDIO_STREAM_RECORD, + AUDIO_STREAM_LAST = AUDIO_STREAM_RECORD, +}; + +/* the preferred number and size of audio pipeline buffer for the audio device */ +struct rt_audio_buf_info +{ + rt_uint8_t *buffer; + rt_uint16_t block_size; + rt_uint16_t block_count; + rt_uint32_t total_size; +}; + +struct rt_audio_device; +struct rt_audio_caps; +struct rt_audio_configure; +struct rt_audio_ops +{ + rt_err_t (*getcaps)(struct rt_audio_device *audio, struct rt_audio_caps *caps); + rt_err_t (*configure)(struct rt_audio_device *audio, struct rt_audio_caps *caps); + rt_err_t (*init)(struct rt_audio_device *audio); + rt_err_t (*start)(struct rt_audio_device *audio, int stream); + rt_err_t (*stop)(struct rt_audio_device *audio, int stream); + rt_ssize_t (*transmit)(struct rt_audio_device *audio, const void *writeBuf, void *readBuf, rt_size_t size); + /* get page size of codec or private buffer's info */ + void (*buffer_info)(struct rt_audio_device *audio, struct rt_audio_buf_info *info); +}; + +struct rt_audio_configure +{ + rt_uint32_t samplerate; + rt_uint16_t channels; + rt_uint16_t samplebits; +}; + +struct rt_audio_caps +{ + int main_type; + int sub_type; + + union + { + rt_uint32_t mask; + int value; + struct rt_audio_configure config; + } udata; +}; + +struct rt_audio_replay +{ + struct rt_mempool *mp; + struct rt_data_queue queue; + struct rt_mutex lock; + struct rt_completion cmp; + struct rt_audio_buf_info buf_info; + rt_uint8_t *write_data; + rt_uint16_t write_index; + rt_uint16_t read_index; + rt_uint32_t pos; + rt_uint8_t event; + rt_bool_t activated; +}; + +struct rt_audio_record +{ + struct rt_audio_pipe pipe; + rt_bool_t activated; +}; + +struct rt_audio_device +{ + struct rt_device parent; + struct rt_audio_ops *ops; + struct rt_audio_replay *replay; + struct rt_audio_record *record; +}; + +rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data); +void rt_audio_tx_complete(struct rt_audio_device *audio); +void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len); + +/* Device Control Commands */ +#define CODEC_CMD_RESET 0 +#define CODEC_CMD_SET_VOLUME 1 +#define CODEC_CMD_GET_VOLUME 2 +#define CODEC_CMD_SAMPLERATE 3 +#define CODEC_CMD_EQ 4 +#define CODEC_CMD_3D 5 + +#define CODEC_VOLUME_MAX (63) + +#endif /* __DEV_AUDIO_H__ */ diff --git a/components/drivers/include/drivers/dev_can.h b/components/drivers/include/drivers/dev_can.h new file mode 100644 index 0000000000..9f2d7c0677 --- /dev/null +++ b/components/drivers/include/drivers/dev_can.h @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2006-2023, 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 remove RT_CAN_USING_LED. + * 2022-05-08 hpmicro add CANFD support, fixed typos + */ + +#ifndef __DEV_CAN_H_ +#define __DEV_CAN_H_ + +#include + +#ifndef RT_CANMSG_BOX_SZ +#define RT_CANMSG_BOX_SZ 16 +#endif +#ifndef RT_CANSND_BOX_NUM +#define RT_CANSND_BOX_NUM 1 +#endif + +enum CAN_DLC +{ + CAN_MSG_0BYTE = 0, + CAN_MSG_1BYTE, + CAN_MSG_2BYTES, + CAN_MSG_3BYTES, + CAN_MSG_4BYTES, + CAN_MSG_5BYTES, + CAN_MSG_6BYTES, + CAN_MSG_7BYTES, + CAN_MSG_8BYTES, + CAN_MSG_12BYTES, + CAN_MSG_16BYTES, + CAN_MSG_20BYTES, + CAN_MSG_24BYTES, + CAN_MSG_32BYTES, + CAN_MSG_48BYTES, + CAN_MSG_64BYTES, +}; + +enum CANBAUD +{ + CAN1MBaud = 1000UL * 1000,/* 1 MBit/sec */ + CAN800kBaud = 1000UL * 800, /* 800 kBit/sec */ + CAN500kBaud = 1000UL * 500, /* 500 kBit/sec */ + CAN250kBaud = 1000UL * 250, /* 250 kBit/sec */ + CAN125kBaud = 1000UL * 125, /* 125 kBit/sec */ + CAN100kBaud = 1000UL * 100, /* 100 kBit/sec */ + CAN50kBaud = 1000UL * 50, /* 50 kBit/sec */ + CAN20kBaud = 1000UL * 20, /* 20 kBit/sec */ + CAN10kBaud = 1000UL * 10 /* 10 kBit/sec */ +}; + +#define RT_CAN_MODE_NORMAL 0 +#define RT_CAN_MODE_LISTEN 1 +#define RT_CAN_MODE_LOOPBACK 2 +#define RT_CAN_MODE_LOOPBACKANLISTEN 3 + +#define RT_CAN_MODE_PRIV 0x01 +#define RT_CAN_MODE_NOPRIV 0x00 + +/** @defgroup CAN_receive_FIFO_number CAN Receive FIFO Number + * @{ + */ +#define CAN_RX_FIFO0 (0x00000000U) /*!< CAN receive FIFO 0 */ +#define CAN_RX_FIFO1 (0x00000001U) /*!< CAN receive FIFO 1 */ + +struct rt_can_filter_item +{ + rt_uint32_t id : 29; + rt_uint32_t ide : 1; + rt_uint32_t rtr : 1; + rt_uint32_t mode : 1; + rt_uint32_t mask; + rt_int32_t hdr_bank;/*Should be defined as:rx.FilterBank,which should be changed to rt_int32_t hdr_bank*/ + rt_uint32_t rxfifo;/*Add a configuration item that CAN_RX_FIFO0/CAN_RX_FIFO1*/ +#ifdef RT_CAN_USING_HDR + rt_err_t (*ind)(rt_device_t dev, void *args , rt_int32_t hdr, rt_size_t size); + void *args; +#endif /*RT_CAN_USING_HDR*/ +}; + + +#ifdef RT_CAN_USING_HDR +#define RT_CAN_FILTER_ITEM_INIT(id,ide,rtr,mode,mask,ind,args) \ + {(id), (ide), (rtr), (mode),(mask), -1, CAN_RX_FIFO0,(ind), (args)}/*0:CAN_RX_FIFO0*/ +#define RT_CAN_FILTER_STD_INIT(id,ind,args) \ + RT_CAN_FILTER_ITEM_INIT(id,0,0,0,0xFFFFFFFF,ind,args) +#define RT_CAN_FILTER_EXT_INIT(id,ind,args) \ + RT_CAN_FILTER_ITEM_INIT(id,1,0,0,0xFFFFFFFF,ind,args) +#define RT_CAN_STD_RMT_FILTER_INIT(id,ind,args) \ + RT_CAN_FILTER_ITEM_INIT(id,0,1,0,0xFFFFFFFF,ind,args) +#define RT_CAN_EXT_RMT_FILTER_INIT(id,ind,args) \ + RT_CAN_FILTER_ITEM_INIT(id,1,1,0,0xFFFFFFFF,ind,args) +#define RT_CAN_STD_RMT_DATA_FILTER_INIT(id,ind,args) \ + RT_CAN_FILTER_ITEM_INIT(id,0,0,1,0xFFFFFFFF,ind,args) +#define RT_CAN_EXT_RMT_DATA_FILTER_INIT(id,ind,args) \ + RT_CAN_FILTER_ITEM_INIT(id,1,0,1,0xFFFFFFFF,ind,args) +#else + +#define RT_CAN_FILTER_ITEM_INIT(id,ide,rtr,mode,mask) \ + {(id), (ide), (rtr), (mode), (mask), -1, CAN_RX_FIFO0 }/*0:CAN_RX_FIFO0*/ +#define RT_CAN_FILTER_STD_INIT(id) \ + RT_CAN_FILTER_ITEM_INIT(id,0,0,0,0xFFFFFFFF) +#define RT_CAN_FILTER_EXT_INIT(id) \ + RT_CAN_FILTER_ITEM_INIT(id,1,0,0,0xFFFFFFFF) +#define RT_CAN_STD_RMT_FILTER_INIT(id) \ + RT_CAN_FILTER_ITEM_INIT(id,0,1,0,0xFFFFFFFF) +#define RT_CAN_EXT_RMT_FILTER_INIT(id) \ + RT_CAN_FILTER_ITEM_INIT(id,1,1,0,0xFFFFFFFF) +#define RT_CAN_STD_RMT_DATA_FILTER_INIT(id) \ + RT_CAN_FILTER_ITEM_INIT(id,0,0,1,0xFFFFFFFF) +#define RT_CAN_EXT_RMT_DATA_FILTER_INIT(id) \ + RT_CAN_FILTER_ITEM_INIT(id,1,0,1,0xFFFFFFFF) +#endif + +struct rt_can_filter_config +{ + rt_uint32_t count; + rt_uint32_t actived; + struct rt_can_filter_item *items; +}; + +struct rt_can_bit_timing +{ + rt_uint16_t prescaler; /* Pre-scaler */ + rt_uint16_t num_seg1; /* Bit Timing Segment 1, in terms of Tq */ + rt_uint16_t num_seg2; /* Bit Timing Segment 2, in terms of Tq */ + rt_uint8_t num_sjw; /* Synchronization Jump Width, in terms of Tq */ + rt_uint8_t num_sspoff; /* Secondary Sample Point Offset, in terms of Tq */ +}; + +/** + * CAN bit timing configuration list + * NOTE: + * items[0] always for CAN2.0/CANFD Arbitration Phase + * items[1] always for CANFD (if it exists) + */ +struct rt_can_bit_timing_config +{ + rt_uint32_t count; + struct rt_can_bit_timing *items; +}; + +struct can_configure +{ + rt_uint32_t baud_rate; + rt_uint32_t msgboxsz; + rt_uint32_t sndboxnumber; + rt_uint32_t mode : 8; + rt_uint32_t privmode : 8; + rt_uint32_t reserved : 16; + rt_uint32_t ticks; +#ifdef RT_CAN_USING_HDR + rt_uint32_t maxhdr; +#endif + +#ifdef RT_CAN_USING_CANFD + rt_uint32_t baud_rate_fd; /* CANFD data bit rate*/ + rt_uint32_t use_bit_timing: 8; /* Use the bit timing for CAN timing configuration */ + rt_uint32_t enable_canfd : 8; /* Enable CAN-FD mode */ + rt_uint32_t reserved1 : 16; + + /* The below fields take effect only if use_bit_timing is non-zero */ + struct rt_can_bit_timing can_timing; /* CAN bit-timing /CANFD bit-timing for arbitration phase */ + struct rt_can_bit_timing canfd_timing; /* CANFD bit-timing for datat phase */ +#endif +}; + +#define CANDEFAULTCONFIG \ +{\ + CAN1MBaud,\ + RT_CANMSG_BOX_SZ,\ + RT_CANSND_BOX_NUM,\ + RT_CAN_MODE_NORMAL,\ +}; + +struct rt_can_ops; +#define RT_CAN_CMD_SET_FILTER 0x13 +#define RT_CAN_CMD_SET_BAUD 0x14 +#define RT_CAN_CMD_SET_MODE 0x15 +#define RT_CAN_CMD_SET_PRIV 0x16 +#define RT_CAN_CMD_GET_STATUS 0x17 +#define RT_CAN_CMD_SET_STATUS_IND 0x18 +#define RT_CAN_CMD_SET_BUS_HOOK 0x19 +#define RT_CAN_CMD_SET_CANFD 0x1A +#define RT_CAN_CMD_SET_BAUD_FD 0x1B +#define RT_CAN_CMD_SET_BITTIMING 0x1C + +#define RT_DEVICE_CAN_INT_ERR 0x1000 + +enum RT_CAN_STATUS_MODE +{ + NORMAL = 0, + ERRWARNING = 1, + ERRPASSIVE = 2, + BUSOFF = 4, +}; +enum RT_CAN_BUS_ERR +{ + RT_CAN_BUS_NO_ERR = 0, + RT_CAN_BUS_BIT_PAD_ERR = 1, + RT_CAN_BUS_FORMAT_ERR = 2, + RT_CAN_BUS_ACK_ERR = 3, + RT_CAN_BUS_IMPLICIT_BIT_ERR = 4, + RT_CAN_BUS_EXPLICIT_BIT_ERR = 5, + RT_CAN_BUS_CRC_ERR = 6, +}; + +struct rt_can_status +{ + rt_uint32_t rcverrcnt; + rt_uint32_t snderrcnt; + rt_uint32_t errcode; + rt_uint32_t rcvpkg; + rt_uint32_t dropedrcvpkg; + rt_uint32_t sndpkg; + rt_uint32_t dropedsndpkg; + rt_uint32_t bitpaderrcnt; + rt_uint32_t formaterrcnt; + rt_uint32_t ackerrcnt; + rt_uint32_t biterrcnt; + rt_uint32_t crcerrcnt; + rt_uint32_t rcvchange; + rt_uint32_t sndchange; + rt_uint32_t lasterrtype; +}; + +#ifdef RT_CAN_USING_HDR +struct rt_can_hdr +{ + rt_uint32_t connected; + rt_uint32_t msgs; + struct rt_can_filter_item filter; + struct rt_list_node list; +}; +#endif +struct rt_can_device; +typedef rt_err_t (*rt_canstatus_ind)(struct rt_can_device *, void *); +typedef struct rt_can_status_ind_type +{ + rt_canstatus_ind ind; + void *args; +} *rt_can_status_ind_type_t; +typedef void (*rt_can_bus_hook)(struct rt_can_device *); +struct rt_can_device +{ + struct rt_device parent; + + const struct rt_can_ops *ops; + struct can_configure config; + struct rt_can_status status; + + rt_uint32_t timerinitflag; + struct rt_timer timer; + + struct rt_can_status_ind_type status_indicate; +#ifdef RT_CAN_USING_HDR + struct rt_can_hdr *hdr; +#endif +#ifdef RT_CAN_USING_BUS_HOOK + rt_can_bus_hook bus_hook; +#endif /*RT_CAN_USING_BUS_HOOK*/ + struct rt_mutex lock; + void *can_rx; + void *can_tx; +}; +typedef struct rt_can_device *rt_can_t; + +#define RT_CAN_STDID 0 +#define RT_CAN_EXTID 1 +#define RT_CAN_DTR 0 +#define RT_CAN_RTR 1 + +typedef struct rt_can_status *rt_can_status_t; + +struct rt_can_msg +{ + rt_uint32_t id : 29; + rt_uint32_t ide : 1; + rt_uint32_t rtr : 1; + rt_uint32_t rsv : 1; + rt_uint32_t len : 8; + rt_uint32_t priv : 8; + rt_int32_t hdr_index : 8;/*Should be defined as:rx.FilterMatchIndex,which should be changed to rt_int32_t hdr_index : 8*/ +#ifdef RT_CAN_USING_CANFD + rt_uint32_t fd_frame : 1; + rt_uint32_t brs : 1; + rt_uint32_t rxfifo : 2;/*Redefined to return :CAN RX FIFO0/CAN RX FIFO1*/ + rt_uint32_t reserved : 4; +#else + rt_uint32_t rxfifo : 2;/*Redefined to return :CAN RX FIFO0/CAN RX FIFO1*/ + rt_uint32_t reserved : 6; +#endif +#ifdef RT_CAN_USING_CANFD + rt_uint8_t data[64]; +#else + rt_uint8_t data[8]; +#endif +}; +typedef struct rt_can_msg *rt_can_msg_t; + +struct rt_can_msg_list +{ + struct rt_list_node list; +#ifdef RT_CAN_USING_HDR + struct rt_list_node hdrlist; + struct rt_can_hdr *owner; +#endif + struct rt_can_msg data; +}; + +struct rt_can_rx_fifo +{ + /* software fifo */ + struct rt_can_msg_list *buffer; + rt_uint32_t freenumbers; + struct rt_list_node freelist; + struct rt_list_node uselist; +}; + +#define RT_CAN_SND_RESULT_OK 0 +#define RT_CAN_SND_RESULT_ERR 1 +#define RT_CAN_SND_RESULT_WAIT 2 + +#define RT_CAN_EVENT_RX_IND 0x01 /* Rx indication */ +#define RT_CAN_EVENT_TX_DONE 0x02 /* Tx complete */ +#define RT_CAN_EVENT_TX_FAIL 0x03 /* Tx fail */ +#define RT_CAN_EVENT_RX_TIMEOUT 0x05 /* Rx timeout */ +#define RT_CAN_EVENT_RXOF_IND 0x06 /* Rx overflow */ + +struct rt_can_sndbxinx_list +{ + struct rt_list_node list; + struct rt_completion completion; + rt_uint32_t result; +}; + +struct rt_can_tx_fifo +{ + struct rt_can_sndbxinx_list *buffer; + struct rt_semaphore sem; + struct rt_list_node freelist; +}; + +struct rt_can_ops +{ + rt_err_t (*configure)(struct rt_can_device *can, struct can_configure *cfg); + rt_err_t (*control)(struct rt_can_device *can, int cmd, void *arg); + rt_ssize_t (*sendmsg)(struct rt_can_device *can, const void *buf, rt_uint32_t boxno); + rt_ssize_t (*recvmsg)(struct rt_can_device *can, void *buf, rt_uint32_t boxno); +}; + +rt_err_t rt_hw_can_register(struct rt_can_device *can, + const char *name, + const struct rt_can_ops *ops, + void *data); +void rt_hw_can_isr(struct rt_can_device *can, int event); +#endif /*__DEV_CAN_H*/ + diff --git a/components/drivers/include/drivers/dev_i2c.h b/components/drivers/include/drivers/dev_i2c.h new file mode 100644 index 0000000000..1a469eb473 --- /dev/null +++ b/components/drivers/include/drivers/dev_i2c.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-04-25 weety first version + * 2021-04-20 RiceChen added support for bus control api + */ + +#ifndef __DEV_I2C_H__ +#define __DEV_I2C_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define RT_I2C_WR 0x0000 +#define RT_I2C_RD (1u << 0) +#define RT_I2C_ADDR_10BIT (1u << 2) /* this is a ten bit chip address */ +#define RT_I2C_NO_START (1u << 4) +#define RT_I2C_IGNORE_NACK (1u << 5) +#define RT_I2C_NO_READ_ACK (1u << 6) /* when I2C reading, we do not ACK */ +#define RT_I2C_NO_STOP (1u << 7) + +#define RT_I2C_DEV_CTRL_10BIT (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x01) +#define RT_I2C_DEV_CTRL_ADDR (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x02) +#define RT_I2C_DEV_CTRL_TIMEOUT (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x03) +#define RT_I2C_DEV_CTRL_RW (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x04) +#define RT_I2C_DEV_CTRL_CLK (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x05) +#define RT_I2C_DEV_CTRL_UNLOCK (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x06) +#define RT_I2C_DEV_CTRL_GET_STATE (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x07) +#define RT_I2C_DEV_CTRL_GET_MODE (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x08) +#define RT_I2C_DEV_CTRL_GET_ERROR (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x09) + +struct rt_i2c_priv_data +{ + struct rt_i2c_msg *msgs; + rt_size_t number; +}; + +struct rt_i2c_msg +{ + rt_uint16_t addr; + rt_uint16_t flags; + rt_uint16_t len; + rt_uint8_t *buf; +}; + +struct rt_i2c_bus_device; + +struct rt_i2c_bus_device_ops +{ + rt_ssize_t (*master_xfer)(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); + rt_ssize_t (*slave_xfer)(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); + rt_err_t (*i2c_bus_control)(struct rt_i2c_bus_device *bus, + int cmd, + void *args); +}; + +/*for i2c bus driver*/ +struct rt_i2c_bus_device +{ + struct rt_device parent; + const struct rt_i2c_bus_device_ops *ops; + rt_uint16_t flags; + struct rt_mutex lock; + rt_uint32_t timeout; + rt_uint32_t retries; + void *priv; +}; + +struct rt_i2c_client +{ +#ifdef RT_USING_DM + struct rt_device parent; + + const char *name; + const struct rt_i2c_device_id *id; + const struct rt_ofw_node_id *ofw_id; +#endif + struct rt_i2c_bus_device *bus; + rt_uint16_t client_addr; +}; + +#ifdef RT_USING_DM +struct rt_i2c_device_id +{ + char name[20]; + void *data; +}; + +struct rt_i2c_driver +{ + struct rt_driver parent; + + const struct rt_i2c_device_id *ids; + const struct rt_ofw_node_id *ofw_ids; + + rt_err_t (*probe)(struct rt_i2c_client *client); + rt_err_t (*remove)(struct rt_i2c_client *client); + rt_err_t (*shutdown)(struct rt_i2c_client *client); +}; + +rt_err_t rt_i2c_driver_register(struct rt_i2c_driver *driver); +rt_err_t rt_i2c_device_register(struct rt_i2c_client *client); + +#define RT_I2C_DRIVER_EXPORT(driver) RT_DRIVER_EXPORT(driver, i2c, BUILIN) +#endif /* RT_USING_DM */ + +rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device *bus, + const char *name); + +rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, + const char *bus_name); +struct rt_i2c_bus_device *rt_i2c_bus_device_find(const char *bus_name); +rt_ssize_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); +rt_err_t rt_i2c_control(struct rt_i2c_bus_device *bus, + int cmd, + void *args); +rt_ssize_t rt_i2c_master_send(struct rt_i2c_bus_device *bus, + rt_uint16_t addr, + rt_uint16_t flags, + const rt_uint8_t *buf, + rt_uint32_t count); +rt_ssize_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus, + rt_uint16_t addr, + rt_uint16_t flags, + rt_uint8_t *buf, + rt_uint32_t count); + +rt_inline rt_err_t rt_i2c_bus_lock(struct rt_i2c_bus_device *bus, rt_tick_t timeout) +{ + return rt_mutex_take(&bus->lock, timeout); +} + +rt_inline rt_err_t rt_i2c_bus_unlock(struct rt_i2c_bus_device *bus) +{ + return rt_mutex_release(&bus->lock); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/include/drivers/dev_i2c_bit_ops.h b/components/drivers/include/drivers/dev_i2c_bit_ops.h new file mode 100644 index 0000000000..3c28714b92 --- /dev/null +++ b/components/drivers/include/drivers/dev_i2c_bit_ops.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-04-25 weety first version + */ + +#ifndef __DEV_I2C_BIT_OPS_H__ +#define __DEV_I2C_BIT_OPS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct rt_i2c_bit_ops +{ + void *data; /* private data for lowlevel routines */ + void (*set_sda)(void *data, rt_int32_t state); + void (*set_scl)(void *data, rt_int32_t state); + rt_int32_t (*get_sda)(void *data); + rt_int32_t (*get_scl)(void *data); + + void (*udelay)(rt_uint32_t us); + + rt_uint32_t delay_us; /* scl and sda line delay */ + rt_uint32_t timeout; /* in tick */ + + void (*pin_init)(void); + rt_bool_t i2c_pin_init_flag; +}; + +rt_err_t rt_i2c_bit_add_bus(struct rt_i2c_bus_device *bus, + const char *bus_name); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/include/drivers/dev_i2c_dm.h b/components/drivers/include/drivers/dev_i2c_dm.h new file mode 100644 index 0000000000..c59d6e9a82 --- /dev/null +++ b/components/drivers/include/drivers/dev_i2c_dm.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-11-26 GuEe-GUI first version + */ + +#ifndef __DEV_I2C_DM_H__ +#define __DEV_I2C_DM_H__ + +#include +#include +#include + +/* I2C Frequency Modes */ +#define I2C_MAX_STANDARD_MODE_FREQ 100000 +#define I2C_MAX_FAST_MODE_FREQ 400000 +#define I2C_MAX_FAST_MODE_PLUS_FREQ 1000000 +#define I2C_MAX_TURBO_MODE_FREQ 1400000 +#define I2C_MAX_HIGH_SPEED_MODE_FREQ 3400000 +#define I2C_MAX_ULTRA_FAST_MODE_FREQ 5000000 + +struct i2c_timings +{ + rt_uint32_t bus_freq_hz; /* the bus frequency in Hz */ + rt_uint32_t scl_rise_ns; /* time SCL signal takes to rise in ns; t(r) in the I2C specification */ + rt_uint32_t scl_fall_ns; /* time SCL signal takes to fall in ns; t(f) in the I2C specification */ + rt_uint32_t scl_int_delay_ns; /* time IP core additionally needs to setup SCL in ns */ + rt_uint32_t sda_fall_ns; /* time SDA signal takes to fall in ns; t(f) in the I2C specification */ + rt_uint32_t sda_hold_ns; /* time IP core additionally needs to hold SDA in ns */ + rt_uint32_t digital_filter_width_ns; /* width in ns of spikes on i2c lines that the IP core digital filter can filter out */ + rt_uint32_t analog_filter_cutoff_freq_hz; /* threshold frequency for the low pass IP core analog filter */ +}; + +#ifdef RT_USING_OFW +rt_err_t i2c_timings_ofw_parse(struct rt_ofw_node *dev_np, struct i2c_timings *timings, + rt_bool_t use_defaults); +#else +rt_inline rt_err_t i2c_timings_ofw_parse(struct rt_ofw_node *dev_np, struct i2c_timings *timings, + rt_bool_t use_defaults) +{ + return RT_EOK; +} +#endif /* RT_USING_OFW */ + +void i2c_bus_scan_clients(struct rt_i2c_bus_device *bus); + +#endif /* __DEV_I2C_DM_H__ */ diff --git a/components/drivers/include/drivers/dev_pin.h b/components/drivers/include/drivers/dev_pin.h new file mode 100644 index 0000000000..55289c0b1a --- /dev/null +++ b/components/drivers/include/drivers/dev_pin.h @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2015-01-20 Bernard the first version + * 2017-10-20 ZYH add mode open drain and input pull down + */ + +#ifndef DEV_PIN_H__ +#define DEV_PIN_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef RT_USING_DM +#include + +struct rt_pin_irqchip +{ + struct rt_pic parent; + + int irq; + rt_base_t pin_range[2]; +}; +#endif /* RT_USING_DM */ + +/* pin device and operations for RT-Thread */ +struct rt_device_pin +{ + struct rt_device parent; +#ifdef RT_USING_DM + struct rt_pin_irqchip irqchip; +#endif /* RT_USING_DM */ + const struct rt_pin_ops *ops; +}; + +#define PIN_NONE (-1) + +#define PIN_LOW 0x00 +#define PIN_HIGH 0x01 + +#define PIN_MODE_OUTPUT 0x00 +#define PIN_MODE_INPUT 0x01 +#define PIN_MODE_INPUT_PULLUP 0x02 +#define PIN_MODE_INPUT_PULLDOWN 0x03 +#define PIN_MODE_OUTPUT_OD 0x04 + +#ifdef RT_USING_PINCTRL +enum +{ + PIN_CONFIG_BIAS_BUS_HOLD, + PIN_CONFIG_BIAS_DISABLE, + PIN_CONFIG_BIAS_HIGH_IMPEDANCE, + PIN_CONFIG_BIAS_PULL_DOWN, + PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, + PIN_CONFIG_BIAS_PULL_UP, + PIN_CONFIG_DRIVE_OPEN_DRAIN, + PIN_CONFIG_DRIVE_OPEN_SOURCE, + PIN_CONFIG_DRIVE_PUSH_PULL, + PIN_CONFIG_DRIVE_STRENGTH, + PIN_CONFIG_DRIVE_STRENGTH_UA, + PIN_CONFIG_INPUT_DEBOUNCE, + PIN_CONFIG_INPUT_ENABLE, + PIN_CONFIG_INPUT_SCHMITT, + PIN_CONFIG_INPUT_SCHMITT_ENABLE, + PIN_CONFIG_MODE_LOW_POWER, + PIN_CONFIG_MODE_PWM, + PIN_CONFIG_OUTPUT, + PIN_CONFIG_OUTPUT_ENABLE, + PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS, + PIN_CONFIG_PERSIST_STATE, + PIN_CONFIG_POWER_SOURCE, + PIN_CONFIG_SKEW_DELAY, + PIN_CONFIG_SLEEP_HARDWARE_STATE, + PIN_CONFIG_SLEW_RATE, + PIN_CONFIG_END = 0x7f, + PIN_CONFIG_MAX = 0xff, +}; +#endif /* RT_USING_PINCTRL */ + +#define PIN_IRQ_MODE_RISING 0x00 +#define PIN_IRQ_MODE_FALLING 0x01 +#define PIN_IRQ_MODE_RISING_FALLING 0x02 +#define PIN_IRQ_MODE_HIGH_LEVEL 0x03 +#define PIN_IRQ_MODE_LOW_LEVEL 0x04 + +#define PIN_IRQ_DISABLE 0x00 +#define PIN_IRQ_ENABLE 0x01 + +#define PIN_IRQ_PIN_NONE PIN_NONE + +struct rt_device_pin_mode +{ + rt_base_t pin; + rt_uint8_t mode; /* e.g. PIN_MODE_OUTPUT */ +}; + +struct rt_device_pin_value +{ + rt_base_t pin; + rt_uint8_t value; /* PIN_LOW or PIN_HIGH */ +}; + +struct rt_pin_irq_hdr +{ + rt_base_t pin; + rt_uint8_t mode; /* e.g. PIN_IRQ_MODE_RISING */ + void (*hdr)(void *args); + void *args; +}; + +#ifdef RT_USING_PINCTRL +struct rt_pin_ctrl_conf_params +{ + const char *propname; + rt_uint32_t param; + rt_uint32_t default_value; +}; +#endif /* RT_USING_PINCTRL */ + +struct rt_pin_ops +{ + void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_uint8_t mode); + void (*pin_write)(struct rt_device *device, rt_base_t pin, rt_uint8_t value); + rt_ssize_t (*pin_read)(struct rt_device *device, rt_base_t pin); + rt_err_t (*pin_attach_irq)(struct rt_device *device, rt_base_t pin, + rt_uint8_t mode, void (*hdr)(void *args), void *args); + rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_base_t pin); + rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled); + rt_base_t (*pin_get)(const char *name); +#ifdef RT_USING_DM + rt_err_t (*pin_irq_mode)(struct rt_device *device, rt_base_t pin, rt_uint8_t mode); + rt_ssize_t (*pin_parse)(struct rt_device *device, struct rt_ofw_cell_args *args, rt_uint32_t *flags); +#endif +#ifdef RT_USING_PINCTRL + rt_err_t (*pin_ctrl_confs_apply)(struct rt_device *device, void *fw_conf_np); +#endif /* RT_USING_PINCTRL */ +}; + +int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data); +void rt_pin_mode(rt_base_t pin, rt_uint8_t mode); +void rt_pin_write(rt_base_t pin, rt_ssize_t value); +rt_ssize_t rt_pin_read(rt_base_t pin); +rt_base_t rt_pin_get(const char *name); +rt_err_t rt_pin_attach_irq(rt_base_t pin, rt_uint8_t mode, + void (*hdr)(void *args), void *args); +rt_err_t rt_pin_detach_irq(rt_base_t pin); +rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint8_t enabled); + +#ifdef RT_USING_DM +rt_ssize_t rt_pin_get_named_pin(struct rt_device *dev, const char *propname, int index, + rt_uint8_t *out_mode, rt_uint8_t *out_value); +rt_ssize_t rt_pin_get_named_pin_count(struct rt_device *dev, const char *propname); + +#ifdef RT_USING_OFW +rt_ssize_t rt_ofw_get_named_pin(struct rt_ofw_node *np, const char *propname, int index, + rt_uint8_t *out_mode, rt_uint8_t *out_value); +rt_ssize_t rt_ofw_get_named_pin_count(struct rt_ofw_node *np, const char *propname); +#endif +#endif /* RT_USING_DM */ + +#ifdef RT_USING_PINCTRL +rt_ssize_t rt_pin_ctrl_confs_lookup(struct rt_device *device, const char *name); +rt_err_t rt_pin_ctrl_confs_apply(struct rt_device *device, int index); +rt_err_t rt_pin_ctrl_confs_apply_by_name(struct rt_device *device, const char *name); +#endif /* RT_USING_PINCTRL */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/include/drivers/dev_pwm.h b/components/drivers/include/drivers/dev_pwm.h new file mode 100644 index 0000000000..98d6cef6d6 --- /dev/null +++ b/components/drivers/include/drivers/dev_pwm.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-05-07 aozima the first version + * 2022-09-24 yuqi add phase and dead time configuration + */ + +#ifndef __DEV_PWM_H__ +#define __DEV_PWM_H__ + +#include + +#define PWM_CMD_ENABLE (RT_DEVICE_CTRL_BASE(PWM) + 0) +#define PWM_CMD_DISABLE (RT_DEVICE_CTRL_BASE(PWM) + 1) +#define PWM_CMD_SET (RT_DEVICE_CTRL_BASE(PWM) + 2) +#define PWM_CMD_GET (RT_DEVICE_CTRL_BASE(PWM) + 3) +#define PWMN_CMD_ENABLE (RT_DEVICE_CTRL_BASE(PWM) + 4) +#define PWMN_CMD_DISABLE (RT_DEVICE_CTRL_BASE(PWM) + 5) +#define PWM_CMD_SET_PERIOD (RT_DEVICE_CTRL_BASE(PWM) + 6) +#define PWM_CMD_SET_PULSE (RT_DEVICE_CTRL_BASE(PWM) + 7) +#define PWM_CMD_SET_DEAD_TIME (RT_DEVICE_CTRL_BASE(PWM) + 8) +#define PWM_CMD_SET_PHASE (RT_DEVICE_CTRL_BASE(PWM) + 9) +#define PWM_CMD_ENABLE_IRQ (RT_DEVICE_CTRL_BASE(PWM) + 10) +#define PWM_CMD_DISABLE_IRQ (RT_DEVICE_CTRL_BASE(PWM) + 11) + +struct rt_pwm_configuration +{ + rt_uint32_t channel; /* 0 ~ n or 0 ~ -n, which depends on specific MCU requirements */ + rt_uint32_t period; /* unit:ns 1ns~4.29s:1Ghz~0.23hz */ + rt_uint32_t pulse; /* unit:ns (pulse<=period) */ + rt_uint32_t dead_time; /* unit:ns */ + rt_uint32_t phase; /*unit: degree, 0~360, which is the phase of pwm output, */ + /* + * RT_TRUE : The channel of pwm is complememtary. + * RT_FALSE : The channel of pwm is nomal. + */ + rt_bool_t complementary; +}; + +struct rt_device_pwm; +struct rt_pwm_ops +{ + rt_err_t (*control)(struct rt_device_pwm *device, int cmd, void *arg); +}; + +struct rt_device_pwm +{ + struct rt_device parent; + const struct rt_pwm_ops *ops; +}; + +rt_err_t rt_device_pwm_register(struct rt_device_pwm *device, const char *name, const struct rt_pwm_ops *ops, const void *user_data); + +rt_err_t rt_pwm_enable(struct rt_device_pwm *device, int channel); +rt_err_t rt_pwm_disable(struct rt_device_pwm *device, int channel); +rt_err_t rt_pwm_set(struct rt_device_pwm *device, int channel, rt_uint32_t period, rt_uint32_t pulse); +rt_err_t rt_pwm_set_period(struct rt_device_pwm *device, int channel, rt_uint32_t period); +rt_err_t rt_pwm_set_pulse(struct rt_device_pwm *device, int channel, rt_uint32_t pulse); +rt_err_t rt_pwm_set_dead_time(struct rt_device_pwm *device, int channel, rt_uint32_t dead_time); +rt_err_t rt_pwm_set_phase(struct rt_device_pwm *device, int channel, rt_uint32_t phase); + +#endif /* __DEV_PWM_H__ */ diff --git a/components/drivers/include/drivers/dev_rtc.h b/components/drivers/include/drivers/dev_rtc.h new file mode 100644 index 0000000000..96658968e5 --- /dev/null +++ b/components/drivers/include/drivers/dev_rtc.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-10-10 aozima first version. + * 2021-06-11 iysheng implement RTC framework V2.0 + * 2021-07-30 Meco Man move rtc_core.h to rtc.h + * 2022-04-05 tyx add timestamp function + */ + +#ifndef __DEV_RTC_H__ +#define __DEV_RTC_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define RT_DEVICE_CTRL_RTC_GET_TIME (RT_DEVICE_CTRL_BASE(RTC) + 0x01) /**< get second time */ +#define RT_DEVICE_CTRL_RTC_SET_TIME (RT_DEVICE_CTRL_BASE(RTC) + 0x02) /**< set second time */ +#define RT_DEVICE_CTRL_RTC_GET_TIMEVAL (RT_DEVICE_CTRL_BASE(RTC) + 0x03) /**< get timeval for gettimeofday */ +#define RT_DEVICE_CTRL_RTC_SET_TIMEVAL (RT_DEVICE_CTRL_BASE(RTC) + 0x04) /**< set timeval for gettimeofday */ +#define RT_DEVICE_CTRL_RTC_GET_ALARM (RT_DEVICE_CTRL_BASE(RTC) + 0x05) /**< get alarm */ +#define RT_DEVICE_CTRL_RTC_SET_ALARM (RT_DEVICE_CTRL_BASE(RTC) + 0x06) /**< set alarm */ +#define RT_DEVICE_CTRL_RTC_GET_TIMESPEC (RT_DEVICE_CTRL_BASE(RTC) + 0x07) /**< get timespec for clock_gettime */ +#define RT_DEVICE_CTRL_RTC_SET_TIMESPEC (RT_DEVICE_CTRL_BASE(RTC) + 0x08) /**< set timespec for clock_settime */ +#define RT_DEVICE_CTRL_RTC_GET_TIMERES (RT_DEVICE_CTRL_BASE(RTC) + 0x09) /**< get resolution for clock_getres */ + +/* used for alarm function */ +struct rt_rtc_wkalarm +{ + rt_bool_t enable; /* 0 = alarm disabled, 1 = alarm enabled */ + rt_int32_t tm_sec; /* alarm at tm_sec */ + rt_int32_t tm_min; /* alarm at tm_min */ + rt_int32_t tm_hour; /* alarm at tm_hour */ + rt_int32_t tm_mday; /* alarm at tm_mday */ + rt_int32_t tm_mon; /* alarm at tm_mon */ + rt_int32_t tm_year; /* alarm at tm_year */ +}; + +struct rt_rtc_ops +{ + rt_err_t (*init)(void); + rt_err_t (*get_secs)(time_t *sec); + rt_err_t (*set_secs)(time_t *sec); + rt_err_t (*get_alarm)(struct rt_rtc_wkalarm *alarm); + rt_err_t (*set_alarm)(struct rt_rtc_wkalarm *alarm); + rt_err_t (*get_timeval)(struct timeval *tv); + rt_err_t (*set_timeval)(struct timeval *tv); +}; + +typedef struct rt_rtc_device +{ + struct rt_device parent; + const struct rt_rtc_ops *ops; +} rt_rtc_dev_t; + +rt_err_t rt_hw_rtc_register(rt_rtc_dev_t *rtc, + const char *name, + rt_uint32_t flag, + void *data); + +rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day); +rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second); +rt_err_t set_timestamp(time_t timestamp); +rt_err_t get_timestamp(time_t *timestamp); + +#ifdef RT_USING_SYSTEM_WORKQUEUE +rt_err_t rt_soft_rtc_sync(void); +rt_err_t rt_soft_rtc_set_source(const char *name); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __DEV_RTC_H__ */ diff --git a/components/drivers/include/drivers/i2c-bit-ops.h b/components/drivers/include/drivers/i2c-bit-ops.h deleted file mode 100644 index 2b4ea57990..0000000000 --- a/components/drivers/include/drivers/i2c-bit-ops.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2012-04-25 weety first version - */ - -#ifndef __I2C_BIT_OPS_H__ -#define __I2C_BIT_OPS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -struct rt_i2c_bit_ops -{ - void *data; /* private data for lowlevel routines */ - void (*set_sda)(void *data, rt_int32_t state); - void (*set_scl)(void *data, rt_int32_t state); - rt_int32_t (*get_sda)(void *data); - rt_int32_t (*get_scl)(void *data); - - void (*udelay)(rt_uint32_t us); - - rt_uint32_t delay_us; /* scl and sda line delay */ - rt_uint32_t timeout; /* in tick */ - - void (*pin_init)(void); - rt_bool_t i2c_pin_init_flag; -}; - -rt_err_t rt_i2c_bit_add_bus(struct rt_i2c_bus_device *bus, - const char *bus_name); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/drivers/include/drivers/i2c.h b/components/drivers/include/drivers/i2c.h deleted file mode 100644 index 0473a1e8dd..0000000000 --- a/components/drivers/include/drivers/i2c.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2012-04-25 weety first version - * 2021-04-20 RiceChen added support for bus control api - */ - -#ifndef __I2C_H__ -#define __I2C_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define RT_I2C_WR 0x0000 -#define RT_I2C_RD (1u << 0) -#define RT_I2C_ADDR_10BIT (1u << 2) /* this is a ten bit chip address */ -#define RT_I2C_NO_START (1u << 4) -#define RT_I2C_IGNORE_NACK (1u << 5) -#define RT_I2C_NO_READ_ACK (1u << 6) /* when I2C reading, we do not ACK */ -#define RT_I2C_NO_STOP (1u << 7) - -struct rt_i2c_msg -{ - rt_uint16_t addr; - rt_uint16_t flags; - rt_uint16_t len; - rt_uint8_t *buf; -}; - -struct rt_i2c_bus_device; - -struct rt_i2c_bus_device_ops -{ - rt_ssize_t (*master_xfer)(struct rt_i2c_bus_device *bus, - struct rt_i2c_msg msgs[], - rt_uint32_t num); - rt_ssize_t (*slave_xfer)(struct rt_i2c_bus_device *bus, - struct rt_i2c_msg msgs[], - rt_uint32_t num); - rt_err_t (*i2c_bus_control)(struct rt_i2c_bus_device *bus, - int cmd, - void *args); -}; - -/*for i2c bus driver*/ -struct rt_i2c_bus_device -{ - struct rt_device parent; - const struct rt_i2c_bus_device_ops *ops; - rt_uint16_t flags; - struct rt_mutex lock; - rt_uint32_t timeout; - rt_uint32_t retries; - void *priv; -}; - -struct rt_i2c_client -{ -#ifdef RT_USING_DM - struct rt_device parent; - - const char *name; - const struct rt_i2c_device_id *id; - const struct rt_ofw_node_id *ofw_id; -#endif - struct rt_i2c_bus_device *bus; - rt_uint16_t client_addr; -}; - -#ifdef RT_USING_DM -struct rt_i2c_device_id -{ - char name[20]; - void *data; -}; - -struct rt_i2c_driver -{ - struct rt_driver parent; - - const struct rt_i2c_device_id *ids; - const struct rt_ofw_node_id *ofw_ids; - - rt_err_t (*probe)(struct rt_i2c_client *client); - rt_err_t (*remove)(struct rt_i2c_client *client); - rt_err_t (*shutdown)(struct rt_i2c_client *client); -}; - -rt_err_t rt_i2c_driver_register(struct rt_i2c_driver *driver); -rt_err_t rt_i2c_device_register(struct rt_i2c_client *client); - -#define RT_I2C_DRIVER_EXPORT(driver) RT_DRIVER_EXPORT(driver, i2c, BUILIN) -#endif /* RT_USING_DM */ - -rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, - const char *bus_name); -struct rt_i2c_bus_device *rt_i2c_bus_device_find(const char *bus_name); -rt_ssize_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, - struct rt_i2c_msg msgs[], - rt_uint32_t num); -rt_err_t rt_i2c_control(struct rt_i2c_bus_device *bus, - int cmd, - void *args); -rt_ssize_t rt_i2c_master_send(struct rt_i2c_bus_device *bus, - rt_uint16_t addr, - rt_uint16_t flags, - const rt_uint8_t *buf, - rt_uint32_t count); -rt_ssize_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus, - rt_uint16_t addr, - rt_uint16_t flags, - rt_uint8_t *buf, - rt_uint32_t count); - -rt_inline rt_err_t rt_i2c_bus_lock(struct rt_i2c_bus_device *bus, rt_tick_t timeout) -{ - return rt_mutex_take(&bus->lock, timeout); -} - -rt_inline rt_err_t rt_i2c_bus_unlock(struct rt_i2c_bus_device *bus) -{ - return rt_mutex_release(&bus->lock); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/drivers/include/drivers/i2c_dev.h b/components/drivers/include/drivers/i2c_dev.h deleted file mode 100644 index 6744fa142d..0000000000 --- a/components/drivers/include/drivers/i2c_dev.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2012-04-25 weety first version - * 2021-04-20 RiceChen added bus clock command - */ - -#ifndef __I2C_DEV_H__ -#define __I2C_DEV_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define RT_I2C_DEV_CTRL_10BIT (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x01) -#define RT_I2C_DEV_CTRL_ADDR (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x02) -#define RT_I2C_DEV_CTRL_TIMEOUT (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x03) -#define RT_I2C_DEV_CTRL_RW (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x04) -#define RT_I2C_DEV_CTRL_CLK (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x05) -#define RT_I2C_DEV_CTRL_UNLOCK (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x06) -#define RT_I2C_DEV_CTRL_GET_STATE (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x07) -#define RT_I2C_DEV_CTRL_GET_MODE (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x08) -#define RT_I2C_DEV_CTRL_GET_ERROR (RT_DEVICE_CTRL_BASE(I2CBUS) + 0x09) - -struct rt_i2c_priv_data -{ - struct rt_i2c_msg *msgs; - rt_size_t number; -}; - -rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device *bus, - const char *name); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/drivers/include/drivers/i2c_dm.h b/components/drivers/include/drivers/i2c_dm.h deleted file mode 100644 index 4f5b251c60..0000000000 --- a/components/drivers/include/drivers/i2c_dm.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-11-26 GuEe-GUI first version - */ - -#ifndef __I2C_DM_H__ -#define __I2C_DM_H__ - -#include -#include -#include - -/* I2C Frequency Modes */ -#define I2C_MAX_STANDARD_MODE_FREQ 100000 -#define I2C_MAX_FAST_MODE_FREQ 400000 -#define I2C_MAX_FAST_MODE_PLUS_FREQ 1000000 -#define I2C_MAX_TURBO_MODE_FREQ 1400000 -#define I2C_MAX_HIGH_SPEED_MODE_FREQ 3400000 -#define I2C_MAX_ULTRA_FAST_MODE_FREQ 5000000 - -struct i2c_timings -{ - rt_uint32_t bus_freq_hz; /* the bus frequency in Hz */ - rt_uint32_t scl_rise_ns; /* time SCL signal takes to rise in ns; t(r) in the I2C specification */ - rt_uint32_t scl_fall_ns; /* time SCL signal takes to fall in ns; t(f) in the I2C specification */ - rt_uint32_t scl_int_delay_ns; /* time IP core additionally needs to setup SCL in ns */ - rt_uint32_t sda_fall_ns; /* time SDA signal takes to fall in ns; t(f) in the I2C specification */ - rt_uint32_t sda_hold_ns; /* time IP core additionally needs to hold SDA in ns */ - rt_uint32_t digital_filter_width_ns; /* width in ns of spikes on i2c lines that the IP core digital filter can filter out */ - rt_uint32_t analog_filter_cutoff_freq_hz; /* threshold frequency for the low pass IP core analog filter */ -}; - -#ifdef RT_USING_OFW -rt_err_t i2c_timings_ofw_parse(struct rt_ofw_node *dev_np, struct i2c_timings *timings, - rt_bool_t use_defaults); -#else -rt_inline rt_err_t i2c_timings_ofw_parse(struct rt_ofw_node *dev_np, struct i2c_timings *timings, - rt_bool_t use_defaults) -{ - return RT_EOK; -} -#endif /* RT_USING_OFW */ - -void i2c_bus_scan_clients(struct rt_i2c_bus_device *bus); - -#endif /* __I2C_DM_H__ */ diff --git a/components/drivers/include/drivers/pin.h b/components/drivers/include/drivers/pin.h deleted file mode 100644 index 22d4328e16..0000000000 --- a/components/drivers/include/drivers/pin.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2015-01-20 Bernard the first version - * 2017-10-20 ZYH add mode open drain and input pull down - */ - -#ifndef PIN_H__ -#define PIN_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef RT_USING_DM -#include - -struct rt_pin_irqchip -{ - struct rt_pic parent; - - int irq; - rt_base_t pin_range[2]; -}; -#endif /* RT_USING_DM */ - -/* pin device and operations for RT-Thread */ -struct rt_device_pin -{ - struct rt_device parent; -#ifdef RT_USING_DM - struct rt_pin_irqchip irqchip; -#endif /* RT_USING_DM */ - const struct rt_pin_ops *ops; -}; - -#define PIN_NONE (-1) - -#define PIN_LOW 0x00 -#define PIN_HIGH 0x01 - -#define PIN_MODE_OUTPUT 0x00 -#define PIN_MODE_INPUT 0x01 -#define PIN_MODE_INPUT_PULLUP 0x02 -#define PIN_MODE_INPUT_PULLDOWN 0x03 -#define PIN_MODE_OUTPUT_OD 0x04 - -#ifdef RT_USING_PINCTRL -enum -{ - PIN_CONFIG_BIAS_BUS_HOLD, - PIN_CONFIG_BIAS_DISABLE, - PIN_CONFIG_BIAS_HIGH_IMPEDANCE, - PIN_CONFIG_BIAS_PULL_DOWN, - PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, - PIN_CONFIG_BIAS_PULL_UP, - PIN_CONFIG_DRIVE_OPEN_DRAIN, - PIN_CONFIG_DRIVE_OPEN_SOURCE, - PIN_CONFIG_DRIVE_PUSH_PULL, - PIN_CONFIG_DRIVE_STRENGTH, - PIN_CONFIG_DRIVE_STRENGTH_UA, - PIN_CONFIG_INPUT_DEBOUNCE, - PIN_CONFIG_INPUT_ENABLE, - PIN_CONFIG_INPUT_SCHMITT, - PIN_CONFIG_INPUT_SCHMITT_ENABLE, - PIN_CONFIG_MODE_LOW_POWER, - PIN_CONFIG_MODE_PWM, - PIN_CONFIG_OUTPUT, - PIN_CONFIG_OUTPUT_ENABLE, - PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS, - PIN_CONFIG_PERSIST_STATE, - PIN_CONFIG_POWER_SOURCE, - PIN_CONFIG_SKEW_DELAY, - PIN_CONFIG_SLEEP_HARDWARE_STATE, - PIN_CONFIG_SLEW_RATE, - PIN_CONFIG_END = 0x7f, - PIN_CONFIG_MAX = 0xff, -}; -#endif /* RT_USING_PINCTRL */ - -#define PIN_IRQ_MODE_RISING 0x00 -#define PIN_IRQ_MODE_FALLING 0x01 -#define PIN_IRQ_MODE_RISING_FALLING 0x02 -#define PIN_IRQ_MODE_HIGH_LEVEL 0x03 -#define PIN_IRQ_MODE_LOW_LEVEL 0x04 - -#define PIN_IRQ_DISABLE 0x00 -#define PIN_IRQ_ENABLE 0x01 - -#define PIN_IRQ_PIN_NONE PIN_NONE - -struct rt_device_pin_mode -{ - rt_base_t pin; - rt_uint8_t mode; /* e.g. PIN_MODE_OUTPUT */ -}; - -struct rt_device_pin_value -{ - rt_base_t pin; - rt_uint8_t value; /* PIN_LOW or PIN_HIGH */ -}; - -struct rt_pin_irq_hdr -{ - rt_base_t pin; - rt_uint8_t mode; /* e.g. PIN_IRQ_MODE_RISING */ - void (*hdr)(void *args); - void *args; -}; - -#ifdef RT_USING_PINCTRL -struct rt_pin_ctrl_conf_params -{ - const char *propname; - rt_uint32_t param; - rt_uint32_t default_value; -}; -#endif /* RT_USING_PINCTRL */ - -struct rt_pin_ops -{ - void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_uint8_t mode); - void (*pin_write)(struct rt_device *device, rt_base_t pin, rt_uint8_t value); - rt_ssize_t (*pin_read)(struct rt_device *device, rt_base_t pin); - rt_err_t (*pin_attach_irq)(struct rt_device *device, rt_base_t pin, - rt_uint8_t mode, void (*hdr)(void *args), void *args); - rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_base_t pin); - rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled); - rt_base_t (*pin_get)(const char *name); -#ifdef RT_USING_DM - rt_err_t (*pin_irq_mode)(struct rt_device *device, rt_base_t pin, rt_uint8_t mode); - rt_ssize_t (*pin_parse)(struct rt_device *device, struct rt_ofw_cell_args *args, rt_uint32_t *flags); -#endif -#ifdef RT_USING_PINCTRL - rt_err_t (*pin_ctrl_confs_apply)(struct rt_device *device, void *fw_conf_np); -#endif /* RT_USING_PINCTRL */ -}; - -int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data); -void rt_pin_mode(rt_base_t pin, rt_uint8_t mode); -void rt_pin_write(rt_base_t pin, rt_ssize_t value); -rt_ssize_t rt_pin_read(rt_base_t pin); -rt_base_t rt_pin_get(const char *name); -rt_err_t rt_pin_attach_irq(rt_base_t pin, rt_uint8_t mode, - void (*hdr)(void *args), void *args); -rt_err_t rt_pin_detach_irq(rt_base_t pin); -rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint8_t enabled); - -#ifdef RT_USING_DM -rt_ssize_t rt_pin_get_named_pin(struct rt_device *dev, const char *propname, int index, - rt_uint8_t *out_mode, rt_uint8_t *out_value); -rt_ssize_t rt_pin_get_named_pin_count(struct rt_device *dev, const char *propname); - -#ifdef RT_USING_OFW -rt_ssize_t rt_ofw_get_named_pin(struct rt_ofw_node *np, const char *propname, int index, - rt_uint8_t *out_mode, rt_uint8_t *out_value); -rt_ssize_t rt_ofw_get_named_pin_count(struct rt_ofw_node *np, const char *propname); -#endif -#endif /* RT_USING_DM */ - -#ifdef RT_USING_PINCTRL -rt_ssize_t rt_pin_ctrl_confs_lookup(struct rt_device *device, const char *name); -rt_err_t rt_pin_ctrl_confs_apply(struct rt_device *device, int index); -rt_err_t rt_pin_ctrl_confs_apply_by_name(struct rt_device *device, const char *name); -#endif /* RT_USING_PINCTRL */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/drivers/include/drivers/rt_drv_pwm.h b/components/drivers/include/drivers/rt_drv_pwm.h deleted file mode 100644 index e9e1707144..0000000000 --- a/components/drivers/include/drivers/rt_drv_pwm.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-05-07 aozima the first version - * 2022-09-24 yuqi add phase and dead time configuration - */ - -#ifndef __DRV_PWM_H_INCLUDE__ -#define __DRV_PWM_H_INCLUDE__ - -#include - -#define PWM_CMD_ENABLE (RT_DEVICE_CTRL_BASE(PWM) + 0) -#define PWM_CMD_DISABLE (RT_DEVICE_CTRL_BASE(PWM) + 1) -#define PWM_CMD_SET (RT_DEVICE_CTRL_BASE(PWM) + 2) -#define PWM_CMD_GET (RT_DEVICE_CTRL_BASE(PWM) + 3) -#define PWMN_CMD_ENABLE (RT_DEVICE_CTRL_BASE(PWM) + 4) -#define PWMN_CMD_DISABLE (RT_DEVICE_CTRL_BASE(PWM) + 5) -#define PWM_CMD_SET_PERIOD (RT_DEVICE_CTRL_BASE(PWM) + 6) -#define PWM_CMD_SET_PULSE (RT_DEVICE_CTRL_BASE(PWM) + 7) -#define PWM_CMD_SET_DEAD_TIME (RT_DEVICE_CTRL_BASE(PWM) + 8) -#define PWM_CMD_SET_PHASE (RT_DEVICE_CTRL_BASE(PWM) + 9) -#define PWM_CMD_ENABLE_IRQ (RT_DEVICE_CTRL_BASE(PWM) + 10) -#define PWM_CMD_DISABLE_IRQ (RT_DEVICE_CTRL_BASE(PWM) + 11) - -struct rt_pwm_configuration -{ - rt_uint32_t channel; /* 0 ~ n or 0 ~ -n, which depends on specific MCU requirements */ - rt_uint32_t period; /* unit:ns 1ns~4.29s:1Ghz~0.23hz */ - rt_uint32_t pulse; /* unit:ns (pulse<=period) */ - rt_uint32_t dead_time; /* unit:ns */ - rt_uint32_t phase; /*unit: degree, 0~360, which is the phase of pwm output, */ - /* - * RT_TRUE : The channel of pwm is complememtary. - * RT_FALSE : The channel of pwm is nomal. - */ - rt_bool_t complementary; -}; - -struct rt_device_pwm; -struct rt_pwm_ops -{ - rt_err_t (*control)(struct rt_device_pwm *device, int cmd, void *arg); -}; - -struct rt_device_pwm -{ - struct rt_device parent; - const struct rt_pwm_ops *ops; -}; - -rt_err_t rt_device_pwm_register(struct rt_device_pwm *device, const char *name, const struct rt_pwm_ops *ops, const void *user_data); - -rt_err_t rt_pwm_enable(struct rt_device_pwm *device, int channel); -rt_err_t rt_pwm_disable(struct rt_device_pwm *device, int channel); -rt_err_t rt_pwm_set(struct rt_device_pwm *device, int channel, rt_uint32_t period, rt_uint32_t pulse); -rt_err_t rt_pwm_set_period(struct rt_device_pwm *device, int channel, rt_uint32_t period); -rt_err_t rt_pwm_set_pulse(struct rt_device_pwm *device, int channel, rt_uint32_t pulse); -rt_err_t rt_pwm_set_dead_time(struct rt_device_pwm *device, int channel, rt_uint32_t dead_time); -rt_err_t rt_pwm_set_phase(struct rt_device_pwm *device, int channel, rt_uint32_t phase); - -#endif /* __DRV_PWM_H_INCLUDE__ */ diff --git a/components/drivers/include/drivers/rtc.h b/components/drivers/include/drivers/rtc.h deleted file mode 100644 index cba0ff9149..0000000000 --- a/components/drivers/include/drivers/rtc.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2012-10-10 aozima first version. - * 2021-06-11 iysheng implement RTC framework V2.0 - * 2021-07-30 Meco Man move rtc_core.h to rtc.h - * 2022-04-05 tyx add timestamp function - */ - -#ifndef __RTC_H__ -#define __RTC_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define RT_DEVICE_CTRL_RTC_GET_TIME (RT_DEVICE_CTRL_BASE(RTC) + 0x01) /**< get second time */ -#define RT_DEVICE_CTRL_RTC_SET_TIME (RT_DEVICE_CTRL_BASE(RTC) + 0x02) /**< set second time */ -#define RT_DEVICE_CTRL_RTC_GET_TIMEVAL (RT_DEVICE_CTRL_BASE(RTC) + 0x03) /**< get timeval for gettimeofday */ -#define RT_DEVICE_CTRL_RTC_SET_TIMEVAL (RT_DEVICE_CTRL_BASE(RTC) + 0x04) /**< set timeval for gettimeofday */ -#define RT_DEVICE_CTRL_RTC_GET_ALARM (RT_DEVICE_CTRL_BASE(RTC) + 0x05) /**< get alarm */ -#define RT_DEVICE_CTRL_RTC_SET_ALARM (RT_DEVICE_CTRL_BASE(RTC) + 0x06) /**< set alarm */ -#define RT_DEVICE_CTRL_RTC_GET_TIMESPEC (RT_DEVICE_CTRL_BASE(RTC) + 0x07) /**< get timespec for clock_gettime */ -#define RT_DEVICE_CTRL_RTC_SET_TIMESPEC (RT_DEVICE_CTRL_BASE(RTC) + 0x08) /**< set timespec for clock_settime */ -#define RT_DEVICE_CTRL_RTC_GET_TIMERES (RT_DEVICE_CTRL_BASE(RTC) + 0x09) /**< get resolution for clock_getres */ - -/* used for alarm function */ -struct rt_rtc_wkalarm -{ - rt_bool_t enable; /* 0 = alarm disabled, 1 = alarm enabled */ - rt_int32_t tm_sec; /* alarm at tm_sec */ - rt_int32_t tm_min; /* alarm at tm_min */ - rt_int32_t tm_hour; /* alarm at tm_hour */ - rt_int32_t tm_mday; /* alarm at tm_mday */ - rt_int32_t tm_mon; /* alarm at tm_mon */ - rt_int32_t tm_year; /* alarm at tm_year */ -}; - -struct rt_rtc_ops -{ - rt_err_t (*init)(void); - rt_err_t (*get_secs)(time_t *sec); - rt_err_t (*set_secs)(time_t *sec); - rt_err_t (*get_alarm)(struct rt_rtc_wkalarm *alarm); - rt_err_t (*set_alarm)(struct rt_rtc_wkalarm *alarm); - rt_err_t (*get_timeval)(struct timeval *tv); - rt_err_t (*set_timeval)(struct timeval *tv); -}; - -typedef struct rt_rtc_device -{ - struct rt_device parent; - const struct rt_rtc_ops *ops; -} rt_rtc_dev_t; - -rt_err_t rt_hw_rtc_register(rt_rtc_dev_t *rtc, - const char *name, - rt_uint32_t flag, - void *data); - -rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day); -rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second); -rt_err_t set_timestamp(time_t timestamp); -rt_err_t get_timestamp(time_t *timestamp); - -#ifdef RT_USING_SYSTEM_WORKQUEUE -rt_err_t rt_soft_rtc_sync(void); -rt_err_t rt_soft_rtc_set_source(const char *name); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __RTC_H__ */ diff --git a/components/drivers/include/drivers/sensor.h b/components/drivers/include/drivers/sensor.h index 6c8b78e8a5..537266d705 100644 --- a/components/drivers/include/drivers/sensor.h +++ b/components/drivers/include/drivers/sensor.h @@ -12,7 +12,7 @@ #define __SENSOR_H__ #include -#include "pin.h" +#include "dev_pin.h" #ifdef __cplusplus extern "C" { diff --git a/components/drivers/include/drivers/sensor_v2.h b/components/drivers/include/drivers/sensor_v2.h index d90cef89c7..3cb00cac88 100644 --- a/components/drivers/include/drivers/sensor_v2.h +++ b/components/drivers/include/drivers/sensor_v2.h @@ -13,7 +13,7 @@ #define __SENSOR_H__ #include -#include "pin.h" +#include "dev_pin.h" #ifdef __cplusplus extern "C" { diff --git a/components/drivers/include/drivers/spi.h b/components/drivers/include/drivers/spi.h index b35c7b30b3..8c0bf0bbe9 100644 --- a/components/drivers/include/drivers/spi.h +++ b/components/drivers/include/drivers/spi.h @@ -15,7 +15,7 @@ #include #include -#include +#include #ifdef __cplusplus extern "C"{ diff --git a/components/drivers/include/drivers/touch.h b/components/drivers/include/drivers/touch.h index aa297491dc..edaf0ad230 100644 --- a/components/drivers/include/drivers/touch.h +++ b/components/drivers/include/drivers/touch.h @@ -12,7 +12,7 @@ #define __TOUCH_H__ #include -#include "pin.h" +#include "dev_pin.h" #ifdef __cplusplus extern "C" { diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index 5b080fced7..caff5284e5 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -59,9 +59,9 @@ extern "C" { #endif /* RT_USING_DM */ #ifdef RT_USING_RTC -#include "drivers/rtc.h" +#include "drivers/dev_rtc.h" #ifdef RT_USING_ALARM -#include "drivers/alarm.h" +#include "drivers/dev_alarm.h" #endif #endif /* RT_USING_RTC */ @@ -94,15 +94,14 @@ extern "C" { #endif /* RT_USING_SERIAL */ #ifdef RT_USING_I2C -#include "drivers/i2c.h" -#include "drivers/i2c_dev.h" +#include "drivers/dev_i2c.h" #ifdef RT_USING_I2C_BITOPS -#include "drivers/i2c-bit-ops.h" +#include "drivers/dev_i2c_bit_ops.h" #endif /* RT_USING_I2C_BITOPS */ #ifdef RT_USING_DM -#include "drivers/i2c_dm.h" +#include "drivers/dev_i2c_dm.h" #endif /* RT_USING_DM */ #endif /* RT_USING_I2C */ @@ -123,7 +122,7 @@ extern "C" { #endif /* RT_USING_WDT */ #ifdef RT_USING_PIN -#include "drivers/pin.h" +#include "drivers/dev_pin.h" #endif /* RT_USING_PIN */ #ifdef RT_USING_SENSOR @@ -135,7 +134,7 @@ extern "C" { #endif /* RT_USING_SENSOR */ #ifdef RT_USING_CAN -#include "drivers/can.h" +#include "drivers/dev_can.h" #endif /* RT_USING_CAN */ #ifdef RT_USING_HWTIMER @@ -143,7 +142,7 @@ extern "C" { #endif /* RT_USING_HWTIMER */ #ifdef RT_USING_AUDIO -#include "drivers/audio.h" +#include "drivers/dev_audio.h" #endif /* RT_USING_AUDIO */ #ifdef RT_USING_CPUTIME @@ -159,7 +158,7 @@ extern "C" { #endif /* RT_USING_DAC */ #ifdef RT_USING_PWM -#include "drivers/rt_drv_pwm.h" +#include "drivers/dev_pwm.h" #endif /* RT_USING_PWM */ #ifdef RT_USING_PM diff --git a/components/drivers/pin/SConscript b/components/drivers/pin/SConscript index bdad84827f..69e3b533f3 100755 --- a/components/drivers/pin/SConscript +++ b/components/drivers/pin/SConscript @@ -8,13 +8,13 @@ if not GetDepend(['RT_USING_PIN']): cwd = GetCurrentDir() CPPPATH = [cwd + '/../include'] -src = ['pin.c'] +src = ['dev_pin.c'] if GetDepend(['RT_USING_DM']): - src += ['pin_dm.c'] + src += ['dev_pin_dm.c'] if GetDepend(['RT_USING_OFW']): - src += ['pin_ofw.c'] + src += ['dev_pin_ofw.c'] group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) diff --git a/components/drivers/pin/dev_pin.c b/components/drivers/pin/dev_pin.c new file mode 100644 index 0000000000..ddea62ff0e --- /dev/null +++ b/components/drivers/pin/dev_pin.c @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2015-01-20 Bernard the first version + * 2021-02-06 Meco Man fix RT_ENOSYS code in negative + * 2022-04-29 WangQiang add pin operate command in MSH + */ + +#include + +static struct rt_device_pin _hw_pin; +static rt_ssize_t _pin_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + struct rt_device_pin_value *value; + struct rt_device_pin *pin = (struct rt_device_pin *)dev; + + /* check parameters */ + RT_ASSERT(pin != RT_NULL); + + value = (struct rt_device_pin_value *)buffer; + if (value == RT_NULL || size != sizeof(*value)) + return 0; + + value->value = pin->ops->pin_read(dev, value->pin); + return size; +} + +static rt_ssize_t _pin_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + struct rt_device_pin_value *value; + struct rt_device_pin *pin = (struct rt_device_pin *)dev; + + /* check parameters */ + RT_ASSERT(pin != RT_NULL); + + value = (struct rt_device_pin_value *)buffer; + if (value == RT_NULL || size != sizeof(*value)) + return 0; + + pin->ops->pin_write(dev, (rt_base_t)value->pin, (rt_base_t)value->value); + + return size; +} + +static rt_err_t _pin_control(rt_device_t dev, int cmd, void *args) +{ + struct rt_device_pin_mode *mode; + struct rt_device_pin *pin = (struct rt_device_pin *)dev; + + /* check parameters */ + RT_ASSERT(pin != RT_NULL); + + mode = (struct rt_device_pin_mode *)args; + if (mode == RT_NULL) + return -RT_ERROR; + + pin->ops->pin_mode(dev, (rt_base_t)mode->pin, (rt_base_t)mode->mode); + + return 0; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops pin_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + _pin_read, + _pin_write, + _pin_control +}; +#endif + +int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data) +{ + _hw_pin.parent.type = RT_Device_Class_Pin; + _hw_pin.parent.rx_indicate = RT_NULL; + _hw_pin.parent.tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + _hw_pin.parent.ops = &pin_ops; +#else + _hw_pin.parent.init = RT_NULL; + _hw_pin.parent.open = RT_NULL; + _hw_pin.parent.close = RT_NULL; + _hw_pin.parent.read = _pin_read; + _hw_pin.parent.write = _pin_write; + _hw_pin.parent.control = _pin_control; +#endif + + _hw_pin.ops = ops; + _hw_pin.parent.user_data = user_data; + + /* register a character device */ + rt_device_register(&_hw_pin.parent, name, RT_DEVICE_FLAG_RDWR); + + return 0; +} + +rt_err_t rt_pin_attach_irq(rt_base_t pin, rt_uint8_t mode, + void (*hdr)(void *args), void *args) +{ + RT_ASSERT(_hw_pin.ops != RT_NULL); + if (_hw_pin.ops->pin_attach_irq) + { + return _hw_pin.ops->pin_attach_irq(&_hw_pin.parent, pin, mode, hdr, args); + } + return -RT_ENOSYS; +} + +rt_err_t rt_pin_detach_irq(rt_base_t pin) +{ + RT_ASSERT(_hw_pin.ops != RT_NULL); + if (_hw_pin.ops->pin_detach_irq) + { + return _hw_pin.ops->pin_detach_irq(&_hw_pin.parent, pin); + } + return -RT_ENOSYS; +} + +rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint8_t enabled) +{ + RT_ASSERT(_hw_pin.ops != RT_NULL); + if (_hw_pin.ops->pin_irq_enable) + { + return _hw_pin.ops->pin_irq_enable(&_hw_pin.parent, pin, enabled); + } + return -RT_ENOSYS; +} + +/* RT-Thread Hardware PIN APIs */ +void rt_pin_mode(rt_base_t pin, rt_uint8_t mode) +{ + RT_ASSERT(_hw_pin.ops != RT_NULL); + _hw_pin.ops->pin_mode(&_hw_pin.parent, pin, mode); +} + +void rt_pin_write(rt_base_t pin, rt_ssize_t value) +{ + RT_ASSERT(_hw_pin.ops != RT_NULL); + _hw_pin.ops->pin_write(&_hw_pin.parent, pin, value); +} + +rt_ssize_t rt_pin_read(rt_base_t pin) +{ + RT_ASSERT(_hw_pin.ops != RT_NULL); + return _hw_pin.ops->pin_read(&_hw_pin.parent, pin); +} + +/* Get pin number by name, such as PA.0, P0.12 */ +rt_base_t rt_pin_get(const char *name) +{ + RT_ASSERT(_hw_pin.ops != RT_NULL); + + if (_hw_pin.ops->pin_get == RT_NULL) + { + return -RT_ENOSYS; + } + return _hw_pin.ops->pin_get(name); +} + +#ifdef RT_USING_FINSH +#include +#include +#include +#include +#include + +/* + * convert function for port name + */ +static rt_base_t _pin_cmd_conv(const char *name) +{ + return rt_pin_get(name); +} + +static void _pin_cmd_print_usage(void) +{ + rt_kprintf("pin [option] GPIO\n"); + rt_kprintf(" num: get pin number from hardware pin\n"); + rt_kprintf(" mode: set pin mode to output/input/input_pullup/input_pulldown/output_od\n"); + rt_kprintf(" e.g. MSH >pin mode GPIO output\n"); + rt_kprintf(" read: read pin level of hardware pin\n"); + rt_kprintf(" e.g. MSH >pin read GPIO\n"); + rt_kprintf(" write: write pin level(high/low or on/off) to hardware pin\n"); + rt_kprintf(" e.g. MSH >pin write GPIO high\n"); + rt_kprintf(" help: this help list\n"); + rt_kprintf("GPIO e.g.:"); + rt_pin_get(" "); +} + +/* e.g. MSH >pin num PA.16 */ +static void _pin_cmd_get(int argc, char *argv[]) +{ + rt_base_t pin; + if (argc < 3) + { + _pin_cmd_print_usage(); + return; + } + pin = _pin_cmd_conv(argv[2]); + if (pin < 0) + { + rt_kprintf("Parameter invalid : %s!\n", argv[2]); + _pin_cmd_print_usage(); + return ; + } + rt_kprintf("%s : %d\n", argv[2], pin); +} + +/* e.g. MSH >pin mode PA.16 output */ +static void _pin_cmd_mode(int argc, char *argv[]) +{ + rt_base_t pin; + rt_base_t mode; + if (argc < 4) + { + _pin_cmd_print_usage(); + return; + } + if (!msh_isint(argv[2])) + { + pin = _pin_cmd_conv(argv[2]); + if (pin < 0) + { + rt_kprintf("Parameter invalid : %s!\n", argv[2]); + _pin_cmd_print_usage(); + return; + } + } + else + { + pin = atoi(argv[2]); + } + if (0 == rt_strcmp("output", argv[3])) + { + mode = PIN_MODE_OUTPUT; + } + else if (0 == rt_strcmp("input", argv[3])) + { + mode = PIN_MODE_INPUT; + } + else if (0 == rt_strcmp("input_pullup", argv[3])) + { + mode = PIN_MODE_INPUT_PULLUP; + } + else if (0 == rt_strcmp("input_pulldown", argv[3])) + { + mode = PIN_MODE_INPUT_PULLDOWN; + } + else if (0 == rt_strcmp("output_od", argv[3])) + { + mode = PIN_MODE_OUTPUT_OD; + } + else + { + _pin_cmd_print_usage(); + return; + } + + rt_pin_mode(pin, mode); +} + +/* e.g. MSH >pin read PA.16 */ +static void _pin_cmd_read(int argc, char *argv[]) +{ + rt_base_t pin; + rt_uint8_t value; + if (argc < 3) + { + _pin_cmd_print_usage(); + return; + } + if (!msh_isint(argv[2])) + { + pin = _pin_cmd_conv(argv[2]); + if (pin < 0) + { + rt_kprintf("Parameter invalid : %s!\n", argv[2]); + _pin_cmd_print_usage(); + return; + } + } + else + { + pin = atoi(argv[2]); + } + value = rt_pin_read(pin); + if (value == PIN_HIGH) + { + rt_kprintf("pin[%d] = high\n", pin); + } + else + { + rt_kprintf("pin[%d] = low\n", pin); + } +} + +/* e.g. MSH >pin write PA.16 high */ +static void _pin_cmd_write(int argc, char *argv[]) +{ + rt_base_t pin; + rt_uint8_t value; + if (argc < 4) + { + _pin_cmd_print_usage(); + return; + } + if (!msh_isint(argv[2])) + { + pin = _pin_cmd_conv(argv[2]); + if (pin < 0) + { + rt_kprintf("Parameter invalid : %s!\n", argv[2]); + _pin_cmd_print_usage(); + return; + } + } + else + { + pin = atoi(argv[2]); + } + if ((0 == rt_strcmp("high", argv[3])) || (0 == rt_strcmp("on", argv[3]))) + { + value = PIN_HIGH; + } + else if ((0 == rt_strcmp("low", argv[3])) || (0 == rt_strcmp("off", argv[3]))) + { + value = PIN_LOW; + } + else + { + _pin_cmd_print_usage(); + return; + } + rt_pin_write(pin, value); +} + +static void _pin_cmd(int argc, char *argv[]) +{ + if (argc < 3) + { + _pin_cmd_print_usage(); + return ; + } + if (0 == rt_strcmp("num", argv[1])) + { + _pin_cmd_get(argc, argv); + } + else if (0 == rt_strcmp("mode", argv[1])) + { + _pin_cmd_mode(argc, argv); + } + else if (0 == rt_strcmp("read", argv[1])) + { + _pin_cmd_read(argc, argv); + } + else if (0 == rt_strcmp("write", argv[1])) + { + _pin_cmd_write(argc, argv); + } + else + { + _pin_cmd_print_usage(); + return; + } +} +MSH_CMD_EXPORT_ALIAS(_pin_cmd, pin, pin [option]); +#endif /* RT_USING_FINSH */ diff --git a/components/drivers/pin/dev_pin_dm.c b/components/drivers/pin/dev_pin_dm.c new file mode 100644 index 0000000000..d7714c5a75 --- /dev/null +++ b/components/drivers/pin/dev_pin_dm.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-11-26 GuEe-GUI first version + */ + +#include "dev_pin_dm.h" + +static void pin_dm_irq_mask(struct rt_pic_irq *pirq) +{ + struct rt_device_pin *gpio = pirq->pic->priv_data; + + gpio->ops->pin_irq_enable(&gpio->parent, pirq->hwirq, 0); +} + +static void pin_dm_irq_unmask(struct rt_pic_irq *pirq) +{ + struct rt_device_pin *gpio = pirq->pic->priv_data; + + gpio->ops->pin_irq_enable(&gpio->parent, pirq->hwirq, 1); +} + +static rt_err_t pin_dm_irq_set_triger_mode(struct rt_pic_irq *pirq, rt_uint32_t mode) +{ + rt_uint8_t pin_mode; + struct rt_device_pin *gpio = pirq->pic->priv_data; + + switch (mode) + { + case RT_IRQ_MODE_EDGE_RISING: + pin_mode = PIN_IRQ_MODE_RISING; + break; + + case RT_IRQ_MODE_EDGE_FALLING: + pin_mode = PIN_IRQ_MODE_FALLING; + break; + + case RT_IRQ_MODE_EDGE_BOTH: + pin_mode = PIN_IRQ_MODE_RISING_FALLING; + break; + + case RT_IRQ_MODE_LEVEL_HIGH: + pin_mode = PIN_IRQ_MODE_HIGH_LEVEL; + break; + + case RT_IRQ_MODE_LEVEL_LOW: + pin_mode = PIN_IRQ_MODE_LOW_LEVEL; + break; + + default: + return -RT_ENOSYS; + } + + return gpio->ops->pin_irq_mode(&gpio->parent, pirq->hwirq, pin_mode); +} + +static int pin_dm_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode) +{ + int irq = -1; + struct rt_device_pin *gpio = pic->priv_data; + struct rt_pic_irq *pirq = rt_pic_find_irq(pic, hwirq); + + if (pirq) + { + irq = rt_pic_config_irq(pic, hwirq, hwirq); + + if (irq >= 0) + { + rt_pic_cascade(pirq, gpio->irqchip.irq); + rt_pic_irq_set_triger_mode(irq, mode); + } + } + + return irq; +} + +static rt_err_t pin_dm_irq_parse(struct rt_pic *pic, struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq) +{ + rt_err_t err = RT_EOK; + + if (args->args_count == 2) + { + out_pirq->hwirq = args->args[0]; + out_pirq->mode = args->args[1] & RT_IRQ_MODE_MASK; + } + else + { + err = -RT_EINVAL; + } + + return err; +} + +static struct rt_pic_ops pin_dm_ops = +{ + .name = "GPIO", + .irq_enable = pin_dm_irq_mask, + .irq_disable = pin_dm_irq_unmask, + .irq_mask = pin_dm_irq_mask, + .irq_unmask = pin_dm_irq_unmask, + .irq_set_triger_mode = pin_dm_irq_set_triger_mode, + .irq_map = pin_dm_irq_map, + .irq_parse = pin_dm_irq_parse, +}; + +rt_err_t pin_pic_handle_isr(struct rt_device_pin *gpio, rt_base_t pin) +{ + rt_err_t err; + + if (gpio) + { + struct rt_pin_irqchip *irqchip = &gpio->irqchip; + + if (pin >= irqchip->pin_range[0] && pin <= irqchip->pin_range[1]) + { + struct rt_pic_irq *pirq; + + pirq = rt_pic_find_irq(&irqchip->parent, pin - irqchip->pin_range[0]); + + if (pirq->irq >= 0) + { + err = rt_pic_handle_isr(pirq); + } + else + { + err = -RT_EINVAL; + } + } + else + { + err = -RT_EINVAL; + } + } + else + { + err = -RT_EINVAL; + } + + return err; +} + +rt_err_t pin_pic_init(struct rt_device_pin *gpio) +{ + rt_err_t err; + + if (gpio) + { + struct rt_pin_irqchip *irqchip = &gpio->irqchip; + + if (irqchip->pin_range[0] >= 0 && irqchip->pin_range[1] >= irqchip->pin_range[0]) + { + struct rt_pic *pic = &irqchip->parent; + rt_size_t pin_nr = irqchip->pin_range[1] - irqchip->pin_range[0] + 1; + + pic->priv_data = gpio; + pic->ops = &pin_dm_ops; + /* Make sure the type of gpio for pic */ + gpio->parent.parent.type = RT_Object_Class_Device; + rt_pic_default_name(&irqchip->parent); + + err = rt_pic_linear_irq(pic, pin_nr); + rt_pic_user_extends(pic); + } + else + { + err = -RT_EINVAL; + } + } + else + { + err = -RT_EINVAL; + } + + return err; +} + +rt_ssize_t rt_pin_get_named_pin(struct rt_device *dev, const char *propname, int index, + rt_uint8_t *out_mode, rt_uint8_t *out_value) +{ + rt_ssize_t res = -RT_ENOSYS; + + RT_ASSERT(dev != RT_NULL); + +#ifdef RT_USING_OFW + if (dev->ofw_node) + { + res = rt_ofw_get_named_pin(dev->ofw_node, propname, index, out_mode, out_value); + } + else + { + res = -RT_EINVAL; + } +#endif /* RT_USING_OFW */ + + return res; +} + +rt_ssize_t rt_pin_get_named_pin_count(struct rt_device *dev, const char *propname) +{ + rt_ssize_t count = -RT_ENOSYS; + + RT_ASSERT(dev != RT_NULL); + +#ifdef RT_USING_OFW + if (dev->ofw_node) + { + count = rt_ofw_get_named_pin_count(dev->ofw_node, propname); + } + else + { + count = -RT_EINVAL; + } +#endif /* RT_USING_OFW */ + + return count; +} diff --git a/components/drivers/pin/dev_pin_dm.h b/components/drivers/pin/dev_pin_dm.h new file mode 100644 index 0000000000..c85d93ca41 --- /dev/null +++ b/components/drivers/pin/dev_pin_dm.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-11-26 GuEe-GUI first version + */ + +#ifndef __PIN_DM_H__ +#define __PIN_DM_H__ + +#include +#include +#include + +rt_err_t pin_pic_handle_isr(struct rt_device_pin *gpio, rt_base_t pin); +rt_err_t pin_pic_init(struct rt_device_pin *gpio); + +#endif /* __DEV_PIN_DM_H__ */ diff --git a/components/drivers/pin/dev_pin_ofw.c b/components/drivers/pin/dev_pin_ofw.c new file mode 100644 index 0000000000..d42cd83076 --- /dev/null +++ b/components/drivers/pin/dev_pin_ofw.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-11-26 GuEe-GUI first version + */ + +#include + +#include "dev_pin_dm.h" + +static const char * const gpio_suffixes[] = +{ + "gpios", "gpio" +}; + +rt_ssize_t rt_ofw_get_named_pin(struct rt_ofw_node *np, const char *propname, int index, + rt_uint8_t *out_mode, rt_uint8_t *out_value) +{ + rt_ssize_t pin = -1; + rt_uint8_t mode; + rt_uint8_t value; + rt_uint32_t flags; + char gpios_name[64]; + struct rt_device_pin *pin_dev = 0; + struct rt_ofw_node *pin_dev_np = 0; + struct rt_ofw_cell_args pin_args = {0}; + + if (!np && index < 0) + { + return -RT_EINVAL; + } + + for (int i = 0; i < RT_ARRAY_SIZE(gpio_suffixes); ++i) + { + if (propname) + { + rt_snprintf(gpios_name, sizeof(gpios_name), "%s-%s", propname, gpio_suffixes[i]); + } + else + { + rt_snprintf(gpios_name, sizeof(gpios_name), "%s", gpio_suffixes[i]); + } + + pin = rt_ofw_parse_phandle_cells(np, gpios_name, "#gpio-cells", index, &pin_args); + + if (pin >= 0) + { + break; + } + } + + if (pin < 0) + { + return pin; + } + + pin_dev_np = pin_args.data; + pin_dev = rt_ofw_data(pin_dev_np); + + if (!pin_dev) + { + pin = -RT_ERROR; + + goto _out_converts; + } + + value = PIN_LOW; + mode = PIN_MODE_OUTPUT; + + if (pin_dev->ops->pin_parse) + { + pin = pin_dev->ops->pin_parse(&pin_dev->parent, &pin_args, &flags); + } + else + { + /* + * We always assume that the args[0] is the pin number if driver not + * implemented `pin_parse`. + */ + pin = pin_args.args[0]; + + goto _out_converts; + } + + if (out_mode) + { + if (flags & PIN_OPEN_DRAIN) + { + mode = PIN_MODE_OUTPUT_OD; + } + + switch (flags & RT_GENMASK(6, 4)) + { + case PIN_PULL_UP: + mode = PIN_MODE_INPUT_PULLUP; + break; + + case PIN_PULL_DOWN: + mode = PIN_MODE_INPUT_PULLDOWN; + break; + + case PIN_PULL_DISABLE: + mode = PIN_MODE_INPUT; + break; + } + } + + if (out_value) + { + if (flags == (PIN_ACTIVE_HIGH | PIN_PUSH_PULL)) + { + value = PIN_HIGH; + } + else if (flags == (PIN_ACTIVE_LOW | PIN_PUSH_PULL)) + { + value = PIN_LOW; + } + } + +_out_converts: + rt_ofw_node_put(pin_dev_np); + + if (out_mode) + { + *out_mode = mode; + } + + if (out_value) + { + *out_value = value; + } + + return pin; +} + +rt_ssize_t rt_ofw_get_named_pin_count(struct rt_ofw_node *np, const char *propname) +{ + char gpios_name[64]; + rt_ssize_t count = 0; + + if (!np || !propname) + { + return -RT_EINVAL; + } + + for (int i = 0; i < RT_ARRAY_SIZE(gpio_suffixes); ++i) + { + if (propname) + { + rt_snprintf(gpios_name, sizeof(gpios_name), "%s-%s", propname, gpio_suffixes[i]); + } + else + { + rt_snprintf(gpios_name, sizeof(gpios_name), "%s", gpio_suffixes[i]); + } + + count = rt_ofw_count_phandle_cells(np, propname, "#gpio-cells"); + + if (count > 0) + { + break; + } + } + + return count; +} diff --git a/components/drivers/pin/pin.c b/components/drivers/pin/pin.c deleted file mode 100644 index 303fb25b27..0000000000 --- a/components/drivers/pin/pin.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2015-01-20 Bernard the first version - * 2021-02-06 Meco Man fix RT_ENOSYS code in negative - * 2022-04-29 WangQiang add pin operate command in MSH - */ - -#include - -static struct rt_device_pin _hw_pin; -static rt_ssize_t _pin_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) -{ - struct rt_device_pin_value *value; - struct rt_device_pin *pin = (struct rt_device_pin *)dev; - - /* check parameters */ - RT_ASSERT(pin != RT_NULL); - - value = (struct rt_device_pin_value *)buffer; - if (value == RT_NULL || size != sizeof(*value)) - return 0; - - value->value = pin->ops->pin_read(dev, value->pin); - return size; -} - -static rt_ssize_t _pin_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) -{ - struct rt_device_pin_value *value; - struct rt_device_pin *pin = (struct rt_device_pin *)dev; - - /* check parameters */ - RT_ASSERT(pin != RT_NULL); - - value = (struct rt_device_pin_value *)buffer; - if (value == RT_NULL || size != sizeof(*value)) - return 0; - - pin->ops->pin_write(dev, (rt_base_t)value->pin, (rt_base_t)value->value); - - return size; -} - -static rt_err_t _pin_control(rt_device_t dev, int cmd, void *args) -{ - struct rt_device_pin_mode *mode; - struct rt_device_pin *pin = (struct rt_device_pin *)dev; - - /* check parameters */ - RT_ASSERT(pin != RT_NULL); - - mode = (struct rt_device_pin_mode *)args; - if (mode == RT_NULL) - return -RT_ERROR; - - pin->ops->pin_mode(dev, (rt_base_t)mode->pin, (rt_base_t)mode->mode); - - return 0; -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops pin_ops = -{ - RT_NULL, - RT_NULL, - RT_NULL, - _pin_read, - _pin_write, - _pin_control -}; -#endif - -int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data) -{ - _hw_pin.parent.type = RT_Device_Class_Pin; - _hw_pin.parent.rx_indicate = RT_NULL; - _hw_pin.parent.tx_complete = RT_NULL; - -#ifdef RT_USING_DEVICE_OPS - _hw_pin.parent.ops = &pin_ops; -#else - _hw_pin.parent.init = RT_NULL; - _hw_pin.parent.open = RT_NULL; - _hw_pin.parent.close = RT_NULL; - _hw_pin.parent.read = _pin_read; - _hw_pin.parent.write = _pin_write; - _hw_pin.parent.control = _pin_control; -#endif - - _hw_pin.ops = ops; - _hw_pin.parent.user_data = user_data; - - /* register a character device */ - rt_device_register(&_hw_pin.parent, name, RT_DEVICE_FLAG_RDWR); - - return 0; -} - -rt_err_t rt_pin_attach_irq(rt_base_t pin, rt_uint8_t mode, - void (*hdr)(void *args), void *args) -{ - RT_ASSERT(_hw_pin.ops != RT_NULL); - if (_hw_pin.ops->pin_attach_irq) - { - return _hw_pin.ops->pin_attach_irq(&_hw_pin.parent, pin, mode, hdr, args); - } - return -RT_ENOSYS; -} - -rt_err_t rt_pin_detach_irq(rt_base_t pin) -{ - RT_ASSERT(_hw_pin.ops != RT_NULL); - if (_hw_pin.ops->pin_detach_irq) - { - return _hw_pin.ops->pin_detach_irq(&_hw_pin.parent, pin); - } - return -RT_ENOSYS; -} - -rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint8_t enabled) -{ - RT_ASSERT(_hw_pin.ops != RT_NULL); - if (_hw_pin.ops->pin_irq_enable) - { - return _hw_pin.ops->pin_irq_enable(&_hw_pin.parent, pin, enabled); - } - return -RT_ENOSYS; -} - -/* RT-Thread Hardware PIN APIs */ -void rt_pin_mode(rt_base_t pin, rt_uint8_t mode) -{ - RT_ASSERT(_hw_pin.ops != RT_NULL); - _hw_pin.ops->pin_mode(&_hw_pin.parent, pin, mode); -} - -void rt_pin_write(rt_base_t pin, rt_ssize_t value) -{ - RT_ASSERT(_hw_pin.ops != RT_NULL); - _hw_pin.ops->pin_write(&_hw_pin.parent, pin, value); -} - -rt_ssize_t rt_pin_read(rt_base_t pin) -{ - RT_ASSERT(_hw_pin.ops != RT_NULL); - return _hw_pin.ops->pin_read(&_hw_pin.parent, pin); -} - -/* Get pin number by name, such as PA.0, P0.12 */ -rt_base_t rt_pin_get(const char *name) -{ - RT_ASSERT(_hw_pin.ops != RT_NULL); - - if (_hw_pin.ops->pin_get == RT_NULL) - { - return -RT_ENOSYS; - } - return _hw_pin.ops->pin_get(name); -} - -#ifdef RT_USING_FINSH -#include -#include -#include -#include -#include - -/* - * convert function for port name - */ -static rt_base_t _pin_cmd_conv(const char *name) -{ - return rt_pin_get(name); -} - -static void _pin_cmd_print_usage(void) -{ - rt_kprintf("pin [option] GPIO\n"); - rt_kprintf(" num: get pin number from hardware pin\n"); - rt_kprintf(" mode: set pin mode to output/input/input_pullup/input_pulldown/output_od\n"); - rt_kprintf(" e.g. MSH >pin mode GPIO output\n"); - rt_kprintf(" read: read pin level of hardware pin\n"); - rt_kprintf(" e.g. MSH >pin read GPIO\n"); - rt_kprintf(" write: write pin level(high/low or on/off) to hardware pin\n"); - rt_kprintf(" e.g. MSH >pin write GPIO high\n"); - rt_kprintf(" help: this help list\n"); - rt_kprintf("GPIO e.g.:"); - rt_pin_get(" "); -} - -/* e.g. MSH >pin num PA.16 */ -static void _pin_cmd_get(int argc, char *argv[]) -{ - rt_base_t pin; - if (argc < 3) - { - _pin_cmd_print_usage(); - return; - } - pin = _pin_cmd_conv(argv[2]); - if (pin < 0) - { - rt_kprintf("Parameter invalid : %s!\n", argv[2]); - _pin_cmd_print_usage(); - return ; - } - rt_kprintf("%s : %d\n", argv[2], pin); -} - -/* e.g. MSH >pin mode PA.16 output */ -static void _pin_cmd_mode(int argc, char *argv[]) -{ - rt_base_t pin; - rt_base_t mode; - if (argc < 4) - { - _pin_cmd_print_usage(); - return; - } - if (!msh_isint(argv[2])) - { - pin = _pin_cmd_conv(argv[2]); - if (pin < 0) - { - rt_kprintf("Parameter invalid : %s!\n", argv[2]); - _pin_cmd_print_usage(); - return; - } - } - else - { - pin = atoi(argv[2]); - } - if (0 == rt_strcmp("output", argv[3])) - { - mode = PIN_MODE_OUTPUT; - } - else if (0 == rt_strcmp("input", argv[3])) - { - mode = PIN_MODE_INPUT; - } - else if (0 == rt_strcmp("input_pullup", argv[3])) - { - mode = PIN_MODE_INPUT_PULLUP; - } - else if (0 == rt_strcmp("input_pulldown", argv[3])) - { - mode = PIN_MODE_INPUT_PULLDOWN; - } - else if (0 == rt_strcmp("output_od", argv[3])) - { - mode = PIN_MODE_OUTPUT_OD; - } - else - { - _pin_cmd_print_usage(); - return; - } - - rt_pin_mode(pin, mode); -} - -/* e.g. MSH >pin read PA.16 */ -static void _pin_cmd_read(int argc, char *argv[]) -{ - rt_base_t pin; - rt_uint8_t value; - if (argc < 3) - { - _pin_cmd_print_usage(); - return; - } - if (!msh_isint(argv[2])) - { - pin = _pin_cmd_conv(argv[2]); - if (pin < 0) - { - rt_kprintf("Parameter invalid : %s!\n", argv[2]); - _pin_cmd_print_usage(); - return; - } - } - else - { - pin = atoi(argv[2]); - } - value = rt_pin_read(pin); - if (value == PIN_HIGH) - { - rt_kprintf("pin[%d] = high\n", pin); - } - else - { - rt_kprintf("pin[%d] = low\n", pin); - } -} - -/* e.g. MSH >pin write PA.16 high */ -static void _pin_cmd_write(int argc, char *argv[]) -{ - rt_base_t pin; - rt_uint8_t value; - if (argc < 4) - { - _pin_cmd_print_usage(); - return; - } - if (!msh_isint(argv[2])) - { - pin = _pin_cmd_conv(argv[2]); - if (pin < 0) - { - rt_kprintf("Parameter invalid : %s!\n", argv[2]); - _pin_cmd_print_usage(); - return; - } - } - else - { - pin = atoi(argv[2]); - } - if ((0 == rt_strcmp("high", argv[3])) || (0 == rt_strcmp("on", argv[3]))) - { - value = PIN_HIGH; - } - else if ((0 == rt_strcmp("low", argv[3])) || (0 == rt_strcmp("off", argv[3]))) - { - value = PIN_LOW; - } - else - { - _pin_cmd_print_usage(); - return; - } - rt_pin_write(pin, value); -} - -static void _pin_cmd(int argc, char *argv[]) -{ - if (argc < 3) - { - _pin_cmd_print_usage(); - return ; - } - if (0 == rt_strcmp("num", argv[1])) - { - _pin_cmd_get(argc, argv); - } - else if (0 == rt_strcmp("mode", argv[1])) - { - _pin_cmd_mode(argc, argv); - } - else if (0 == rt_strcmp("read", argv[1])) - { - _pin_cmd_read(argc, argv); - } - else if (0 == rt_strcmp("write", argv[1])) - { - _pin_cmd_write(argc, argv); - } - else - { - _pin_cmd_print_usage(); - return; - } -} -MSH_CMD_EXPORT_ALIAS(_pin_cmd, pin, pin [option]); -#endif /* RT_USING_FINSH */ diff --git a/components/drivers/pin/pin_dm.c b/components/drivers/pin/pin_dm.c deleted file mode 100644 index 52dd47fd97..0000000000 --- a/components/drivers/pin/pin_dm.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-11-26 GuEe-GUI first version - */ - -#include "pin_dm.h" - -static void pin_dm_irq_mask(struct rt_pic_irq *pirq) -{ - struct rt_device_pin *gpio = pirq->pic->priv_data; - - gpio->ops->pin_irq_enable(&gpio->parent, pirq->hwirq, 0); -} - -static void pin_dm_irq_unmask(struct rt_pic_irq *pirq) -{ - struct rt_device_pin *gpio = pirq->pic->priv_data; - - gpio->ops->pin_irq_enable(&gpio->parent, pirq->hwirq, 1); -} - -static rt_err_t pin_dm_irq_set_triger_mode(struct rt_pic_irq *pirq, rt_uint32_t mode) -{ - rt_uint8_t pin_mode; - struct rt_device_pin *gpio = pirq->pic->priv_data; - - switch (mode) - { - case RT_IRQ_MODE_EDGE_RISING: - pin_mode = PIN_IRQ_MODE_RISING; - break; - - case RT_IRQ_MODE_EDGE_FALLING: - pin_mode = PIN_IRQ_MODE_FALLING; - break; - - case RT_IRQ_MODE_EDGE_BOTH: - pin_mode = PIN_IRQ_MODE_RISING_FALLING; - break; - - case RT_IRQ_MODE_LEVEL_HIGH: - pin_mode = PIN_IRQ_MODE_HIGH_LEVEL; - break; - - case RT_IRQ_MODE_LEVEL_LOW: - pin_mode = PIN_IRQ_MODE_LOW_LEVEL; - break; - - default: - return -RT_ENOSYS; - } - - return gpio->ops->pin_irq_mode(&gpio->parent, pirq->hwirq, pin_mode); -} - -static int pin_dm_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode) -{ - int irq = -1; - struct rt_device_pin *gpio = pic->priv_data; - struct rt_pic_irq *pirq = rt_pic_find_irq(pic, hwirq); - - if (pirq) - { - irq = rt_pic_config_irq(pic, hwirq, hwirq); - - if (irq >= 0) - { - rt_pic_cascade(pirq, gpio->irqchip.irq); - rt_pic_irq_set_triger_mode(irq, mode); - } - } - - return irq; -} - -static rt_err_t pin_dm_irq_parse(struct rt_pic *pic, struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq) -{ - rt_err_t err = RT_EOK; - - if (args->args_count == 2) - { - out_pirq->hwirq = args->args[0]; - out_pirq->mode = args->args[1] & RT_IRQ_MODE_MASK; - } - else - { - err = -RT_EINVAL; - } - - return err; -} - -static struct rt_pic_ops pin_dm_ops = -{ - .name = "GPIO", - .irq_enable = pin_dm_irq_mask, - .irq_disable = pin_dm_irq_unmask, - .irq_mask = pin_dm_irq_mask, - .irq_unmask = pin_dm_irq_unmask, - .irq_set_triger_mode = pin_dm_irq_set_triger_mode, - .irq_map = pin_dm_irq_map, - .irq_parse = pin_dm_irq_parse, -}; - -rt_err_t pin_pic_handle_isr(struct rt_device_pin *gpio, rt_base_t pin) -{ - rt_err_t err; - - if (gpio) - { - struct rt_pin_irqchip *irqchip = &gpio->irqchip; - - if (pin >= irqchip->pin_range[0] && pin <= irqchip->pin_range[1]) - { - struct rt_pic_irq *pirq; - - pirq = rt_pic_find_irq(&irqchip->parent, pin - irqchip->pin_range[0]); - - if (pirq->irq >= 0) - { - err = rt_pic_handle_isr(pirq); - } - else - { - err = -RT_EINVAL; - } - } - else - { - err = -RT_EINVAL; - } - } - else - { - err = -RT_EINVAL; - } - - return err; -} - -rt_err_t pin_pic_init(struct rt_device_pin *gpio) -{ - rt_err_t err; - - if (gpio) - { - struct rt_pin_irqchip *irqchip = &gpio->irqchip; - - if (irqchip->pin_range[0] >= 0 && irqchip->pin_range[1] >= irqchip->pin_range[0]) - { - struct rt_pic *pic = &irqchip->parent; - rt_size_t pin_nr = irqchip->pin_range[1] - irqchip->pin_range[0] + 1; - - pic->priv_data = gpio; - pic->ops = &pin_dm_ops; - /* Make sure the type of gpio for pic */ - gpio->parent.parent.type = RT_Object_Class_Device; - rt_pic_default_name(&irqchip->parent); - - err = rt_pic_linear_irq(pic, pin_nr); - rt_pic_user_extends(pic); - } - else - { - err = -RT_EINVAL; - } - } - else - { - err = -RT_EINVAL; - } - - return err; -} - -rt_ssize_t rt_pin_get_named_pin(struct rt_device *dev, const char *propname, int index, - rt_uint8_t *out_mode, rt_uint8_t *out_value) -{ - rt_ssize_t res = -RT_ENOSYS; - - RT_ASSERT(dev != RT_NULL); - -#ifdef RT_USING_OFW - if (dev->ofw_node) - { - res = rt_ofw_get_named_pin(dev->ofw_node, propname, index, out_mode, out_value); - } - else - { - res = -RT_EINVAL; - } -#endif /* RT_USING_OFW */ - - return res; -} - -rt_ssize_t rt_pin_get_named_pin_count(struct rt_device *dev, const char *propname) -{ - rt_ssize_t count = -RT_ENOSYS; - - RT_ASSERT(dev != RT_NULL); - -#ifdef RT_USING_OFW - if (dev->ofw_node) - { - count = rt_ofw_get_named_pin_count(dev->ofw_node, propname); - } - else - { - count = -RT_EINVAL; - } -#endif /* RT_USING_OFW */ - - return count; -} diff --git a/components/drivers/pin/pin_dm.h b/components/drivers/pin/pin_dm.h deleted file mode 100644 index b5146a2795..0000000000 --- a/components/drivers/pin/pin_dm.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-11-26 GuEe-GUI first version - */ - -#ifndef __PIN_DM_H__ -#define __PIN_DM_H__ - -#include -#include -#include - -rt_err_t pin_pic_handle_isr(struct rt_device_pin *gpio, rt_base_t pin); -rt_err_t pin_pic_init(struct rt_device_pin *gpio); - -#endif /* __PIN_DM_H__ */ diff --git a/components/drivers/pin/pin_ofw.c b/components/drivers/pin/pin_ofw.c deleted file mode 100644 index 29d29d4368..0000000000 --- a/components/drivers/pin/pin_ofw.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-11-26 GuEe-GUI first version - */ - -#include - -#include "pin_dm.h" - -static const char * const gpio_suffixes[] = -{ - "gpios", "gpio" -}; - -rt_ssize_t rt_ofw_get_named_pin(struct rt_ofw_node *np, const char *propname, int index, - rt_uint8_t *out_mode, rt_uint8_t *out_value) -{ - rt_ssize_t pin = -1; - rt_uint8_t mode; - rt_uint8_t value; - rt_uint32_t flags; - char gpios_name[64]; - struct rt_device_pin *pin_dev = 0; - struct rt_ofw_node *pin_dev_np = 0; - struct rt_ofw_cell_args pin_args = {0}; - - if (!np && index < 0) - { - return -RT_EINVAL; - } - - for (int i = 0; i < RT_ARRAY_SIZE(gpio_suffixes); ++i) - { - if (propname) - { - rt_snprintf(gpios_name, sizeof(gpios_name), "%s-%s", propname, gpio_suffixes[i]); - } - else - { - rt_snprintf(gpios_name, sizeof(gpios_name), "%s", gpio_suffixes[i]); - } - - pin = rt_ofw_parse_phandle_cells(np, gpios_name, "#gpio-cells", index, &pin_args); - - if (pin >= 0) - { - break; - } - } - - if (pin < 0) - { - return pin; - } - - pin_dev_np = pin_args.data; - pin_dev = rt_ofw_data(pin_dev_np); - - if (!pin_dev) - { - pin = -RT_ERROR; - - goto _out_converts; - } - - value = PIN_LOW; - mode = PIN_MODE_OUTPUT; - - if (pin_dev->ops->pin_parse) - { - pin = pin_dev->ops->pin_parse(&pin_dev->parent, &pin_args, &flags); - } - else - { - /* - * We always assume that the args[0] is the pin number if driver not - * implemented `pin_parse`. - */ - pin = pin_args.args[0]; - - goto _out_converts; - } - - if (out_mode) - { - if (flags & PIN_OPEN_DRAIN) - { - mode = PIN_MODE_OUTPUT_OD; - } - - switch (flags & RT_GENMASK(6, 4)) - { - case PIN_PULL_UP: - mode = PIN_MODE_INPUT_PULLUP; - break; - - case PIN_PULL_DOWN: - mode = PIN_MODE_INPUT_PULLDOWN; - break; - - case PIN_PULL_DISABLE: - mode = PIN_MODE_INPUT; - break; - } - } - - if (out_value) - { - if (flags == (PIN_ACTIVE_HIGH | PIN_PUSH_PULL)) - { - value = PIN_HIGH; - } - else if (flags == (PIN_ACTIVE_LOW | PIN_PUSH_PULL)) - { - value = PIN_LOW; - } - } - -_out_converts: - rt_ofw_node_put(pin_dev_np); - - if (out_mode) - { - *out_mode = mode; - } - - if (out_value) - { - *out_value = value; - } - - return pin; -} - -rt_ssize_t rt_ofw_get_named_pin_count(struct rt_ofw_node *np, const char *propname) -{ - char gpios_name[64]; - rt_ssize_t count = 0; - - if (!np || !propname) - { - return -RT_EINVAL; - } - - for (int i = 0; i < RT_ARRAY_SIZE(gpio_suffixes); ++i) - { - if (propname) - { - rt_snprintf(gpios_name, sizeof(gpios_name), "%s-%s", propname, gpio_suffixes[i]); - } - else - { - rt_snprintf(gpios_name, sizeof(gpios_name), "%s", gpio_suffixes[i]); - } - - count = rt_ofw_count_phandle_cells(np, propname, "#gpio-cells"); - - if (count > 0) - { - break; - } - } - - return count; -} diff --git a/components/drivers/rtc/SConscript b/components/drivers/rtc/SConscript index fe0d5e9db3..f1e180fffe 100644 --- a/components/drivers/rtc/SConscript +++ b/components/drivers/rtc/SConscript @@ -7,11 +7,11 @@ CPPPATH = [cwd + '/../include'] group = [] if GetDepend(['RT_USING_RTC']): - src = src + ['rtc.c'] + src = src + ['dev_rtc.c'] if GetDepend(['RT_USING_ALARM']): - src = src + ['alarm.c'] + src = src + ['dev_alarm.c'] if GetDepend(['RT_USING_SOFT_RTC']): - src = src + ['soft_rtc.c'] + src = src + ['dev_soft_rtc.c'] group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_RTC'], CPPPATH = CPPPATH) diff --git a/components/drivers/rtc/alarm.c b/components/drivers/rtc/alarm.c deleted file mode 100644 index b78528a04c..0000000000 --- a/components/drivers/rtc/alarm.c +++ /dev/null @@ -1,800 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2012-10-27 heyuanjie87 first version. - * 2013-05-17 aozima initial alarm event & mutex in system init. - * 2020-10-15 zhangsz add alarm flags hour minute second. - * 2020-11-09 zhangsz fix alarm set when modify rtc time. - */ - -#include -#include -#include - -#define RT_RTC_YEARS_MAX 137 -#ifdef RT_USING_SOFT_RTC -#define RT_ALARM_DELAY 0 -#else -#define RT_ALARM_DELAY 2 -#endif - -#if (defined(RT_USING_RTC) && defined(RT_USING_ALARM)) -static struct rt_alarm_container _container; - -rt_inline rt_uint32_t alarm_mkdaysec(struct tm *time) -{ - rt_uint32_t sec; - - sec = time->tm_sec; - sec += time->tm_min * 60; - sec += time->tm_hour * 3600; - - return (sec); -} - -static rt_err_t alarm_set(struct rt_alarm *alarm) -{ - rt_device_t device; - struct rt_rtc_wkalarm wkalarm; - rt_err_t ret; - - device = rt_device_find("rtc"); - - if (device == RT_NULL) - { - return (RT_ERROR); - } - - if (alarm->flag & RT_ALARM_STATE_START) - wkalarm.enable = RT_TRUE; - else - wkalarm.enable = RT_FALSE; - - wkalarm.tm_sec = alarm->wktime.tm_sec; - wkalarm.tm_min = alarm->wktime.tm_min; - wkalarm.tm_hour = alarm->wktime.tm_hour; - wkalarm.tm_mday = alarm->wktime.tm_mday; - wkalarm.tm_mon = alarm->wktime.tm_mon; - wkalarm.tm_year = alarm->wktime.tm_year; - - ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_ALARM, &wkalarm); - if ((ret == RT_EOK) && wkalarm.enable) - { - ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_ALARM, &wkalarm); - if (ret == RT_EOK) - { - /* - some RTC device like RX8025,it's alarms precision is 1 minute. - in this case,low level RTC driver should set wkalarm->tm_sec to 0. - */ - alarm->wktime.tm_sec = wkalarm.tm_sec; - alarm->wktime.tm_min = wkalarm.tm_min; - alarm->wktime.tm_hour = wkalarm.tm_hour; - alarm->wktime.tm_mday = wkalarm.tm_mday; - alarm->wktime.tm_mon = wkalarm.tm_mon; - alarm->wktime.tm_year = wkalarm.tm_year; - } - } - - return (ret); -} - -static void alarm_wakeup(struct rt_alarm *alarm, struct tm *now) -{ - rt_uint32_t sec_alarm, sec_now; - rt_bool_t wakeup = RT_FALSE; - time_t timestamp; - - sec_alarm = alarm_mkdaysec(&alarm->wktime); - sec_now = alarm_mkdaysec(now); - - if (alarm->flag & RT_ALARM_STATE_START) - { - switch (alarm->flag & 0xFF00) - { - case RT_ALARM_ONESHOT: - { - sec_alarm = timegm(&alarm->wktime); - sec_now = timegm(now); - if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm)) - { - /* stop alarm */ - alarm->flag &= ~RT_ALARM_STATE_START; - alarm_set(alarm); - wakeup = RT_TRUE; - } - } - break; - case RT_ALARM_SECOND: - { - alarm->wktime.tm_hour = now->tm_hour; - alarm->wktime.tm_min = now->tm_min; - alarm->wktime.tm_sec = now->tm_sec + 1; - if (alarm->wktime.tm_sec > 59) - { - alarm->wktime.tm_sec = 0; - alarm->wktime.tm_min = alarm->wktime.tm_min + 1; - if (alarm->wktime.tm_min > 59) - { - alarm->wktime.tm_min = 0; - alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; - if (alarm->wktime.tm_hour > 23) - { - alarm->wktime.tm_hour = 0; - } - } - } - wakeup = RT_TRUE; - } - break; - case RT_ALARM_MINUTE: - { - alarm->wktime.tm_hour = now->tm_hour; - if (alarm->wktime.tm_sec == now->tm_sec) - { - alarm->wktime.tm_min = now->tm_min + 1; - if (alarm->wktime.tm_min > 59) - { - alarm->wktime.tm_min = 0; - alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; - if (alarm->wktime.tm_hour > 23) - { - alarm->wktime.tm_hour = 0; - } - } - wakeup = RT_TRUE; - } - } - break; - case RT_ALARM_HOUR: - { - if ((alarm->wktime.tm_min == now->tm_min) && - (alarm->wktime.tm_sec == now->tm_sec)) - { - alarm->wktime.tm_hour = now->tm_hour + 1; - if (alarm->wktime.tm_hour > 23) - { - alarm->wktime.tm_hour = 0; - } - wakeup = RT_TRUE; - } - } - break; - case RT_ALARM_DAILY: - { - if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm)) - wakeup = RT_TRUE; - } - break; - case RT_ALARM_WEEKLY: - { - /* alarm at wday */ - if (alarm->wktime.tm_wday == now->tm_wday) - { - sec_alarm += alarm->wktime.tm_wday * 24 * 3600; - sec_now += now->tm_wday * 24 * 3600; - - if (sec_now == sec_alarm) - wakeup = RT_TRUE; - } - } - break; - case RT_ALARM_MONTHLY: - { - /* monthly someday generate alarm signals */ - if (alarm->wktime.tm_mday == now->tm_mday) - { - if ((sec_now - sec_alarm) <= RT_ALARM_DELAY) - wakeup = RT_TRUE; - } - } - break; - case RT_ALARM_YAERLY: - { - if ((alarm->wktime.tm_mday == now->tm_mday) && \ - (alarm->wktime.tm_mon == now->tm_mon)) - { - if ((sec_now - sec_alarm) <= RT_ALARM_DELAY) - wakeup = RT_TRUE; - } - } - break; - } - - if ((wakeup == RT_TRUE) && (alarm->callback != RT_NULL)) - { - timestamp = (time_t)0; - get_timestamp(×tamp); - alarm->callback(alarm, timestamp); - } - } -} - -static void alarm_update(rt_uint32_t event) -{ - struct rt_alarm *alm_prev = RT_NULL, *alm_next = RT_NULL; - struct rt_alarm *alarm; - rt_int32_t sec_now, sec_alarm, sec_tmp; - rt_int32_t sec_next = 24 * 3600, sec_prev = 0; - time_t timestamp = (time_t)0; - struct tm now; - rt_list_t *next; - - rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); - if (!rt_list_isempty(&_container.head)) - { - /* get time of now */ - get_timestamp(×tamp); - gmtime_r(×tamp, &now); - - for (next = _container.head.next; next != &_container.head; next = next->next) - { - alarm = rt_list_entry(next, struct rt_alarm, list); - /* check the overtime alarm */ - alarm_wakeup(alarm, &now); - } - - /* get time of now */ - get_timestamp(×tamp); - gmtime_r(×tamp, &now); - sec_now = alarm_mkdaysec(&now); - - for (next = _container.head.next; next != &_container.head; next = next->next) - { - alarm = rt_list_entry(next, struct rt_alarm, list); - /* calculate seconds from 00:00:00 */ - sec_alarm = alarm_mkdaysec(&alarm->wktime); - if (alarm->flag & RT_ALARM_STATE_START) - { - sec_tmp = sec_alarm - sec_now; - if (sec_tmp > 0) - { - /* find alarm after now(now to 23:59:59) and the most recent */ - if (sec_tmp < sec_next) - { - sec_next = sec_tmp; - alm_next = alarm; - } - } - else - { - /* find alarm before now(00:00:00 to now) and furthest from now */ - if (sec_tmp < sec_prev) - { - sec_prev = sec_tmp; - alm_prev = alarm; - } - } - } - } - - /* enable the alarm after now first */ - if (sec_next < 24 * 3600) - { - if (alarm_set(alm_next) == RT_EOK) - _container.current = alm_next; - } - else if (sec_prev < 0) - { - /* enable the alarm before now */ - if (alarm_set(alm_prev) == RT_EOK) - _container.current = alm_prev; - } - else - { - if (_container.current != RT_NULL) - { - alarm_set(_container.current); - if (!(_container.current->flag & RT_ALARM_STATE_START)) - _container.current = RT_NULL; - } - } - } - rt_mutex_release(&_container.mutex); -} - -static int days_of_year_month(int tm_year, int tm_mon) -{ - int ret, year; - - year = tm_year + 1900; - if (tm_mon == 1) - { - ret = 28 + ((!(year % 4) && (year % 100)) || !(year % 400)); - } - else if (((tm_mon <= 6) && (tm_mon % 2 == 0)) || ((tm_mon > 6) && (tm_mon % 2 == 1))) - { - ret = 31; - } - else - { - ret = 30; - } - - return (ret); -} - -static rt_bool_t is_valid_date(struct tm *date) -{ - if ((date->tm_year < 0) || (date->tm_year > RT_RTC_YEARS_MAX)) - { - return (RT_FALSE); - } - - if ((date->tm_mon < 0) || (date->tm_mon > 11)) - { - return (RT_FALSE); - } - - if ((date->tm_mday < 1) || \ - (date->tm_mday > days_of_year_month(date->tm_year, date->tm_mon))) - { - return (RT_FALSE); - } - - return (RT_TRUE); -} - -static rt_err_t alarm_setup(rt_alarm_t alarm, struct tm *wktime) -{ - rt_err_t ret = -RT_ERROR; - time_t timestamp = (time_t)0; - struct tm *setup, now; - - setup = &alarm->wktime; - *setup = *wktime; - /* get time of now */ - get_timestamp(×tamp); - gmtime_r(×tamp, &now); - - /* if these are a "don't care" value,we set them to now*/ - if ((setup->tm_sec > 59) || (setup->tm_sec < 0)) - setup->tm_sec = now.tm_sec; - if ((setup->tm_min > 59) || (setup->tm_min < 0)) - setup->tm_min = now.tm_min; - if ((setup->tm_hour > 23) || (setup->tm_hour < 0)) - setup->tm_hour = now.tm_hour; - - switch (alarm->flag & 0xFF00) - { - case RT_ALARM_SECOND: - { - alarm->wktime.tm_hour = now.tm_hour; - alarm->wktime.tm_min = now.tm_min; - alarm->wktime.tm_sec = now.tm_sec + 1; - if (alarm->wktime.tm_sec > 59) - { - alarm->wktime.tm_sec = 0; - alarm->wktime.tm_min = alarm->wktime.tm_min + 1; - if (alarm->wktime.tm_min > 59) - { - alarm->wktime.tm_min = 0; - alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; - if (alarm->wktime.tm_hour > 23) - { - alarm->wktime.tm_hour = 0; - } - } - } - } - break; - case RT_ALARM_MINUTE: - { - alarm->wktime.tm_hour = now.tm_hour; - alarm->wktime.tm_min = now.tm_min + 1; - if (alarm->wktime.tm_min > 59) - { - alarm->wktime.tm_min = 0; - alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; - if (alarm->wktime.tm_hour > 23) - { - alarm->wktime.tm_hour = 0; - } - } - } - break; - case RT_ALARM_HOUR: - { - alarm->wktime.tm_hour = now.tm_hour + 1; - if (alarm->wktime.tm_hour > 23) - { - alarm->wktime.tm_hour = 0; - } - } - break; - case RT_ALARM_DAILY: - { - /* do nothing but needed */ - } - break; - case RT_ALARM_ONESHOT: - { - /* if these are "don't care" value we set them to now */ - if (setup->tm_year == RT_ALARM_TM_NOW) - setup->tm_year = now.tm_year; - if (setup->tm_mon == RT_ALARM_TM_NOW) - setup->tm_mon = now.tm_mon; - if (setup->tm_mday == RT_ALARM_TM_NOW) - setup->tm_mday = now.tm_mday; - /* make sure the setup is valid */ - if (!is_valid_date(setup)) - goto _exit; - } - break; - case RT_ALARM_WEEKLY: - { - /* if tm_wday is a "don't care" value we set it to now */ - if ((setup->tm_wday < 0) || (setup->tm_wday > 6)) - setup->tm_wday = now.tm_wday; - } - break; - case RT_ALARM_MONTHLY: - { - /* if tm_mday is a "don't care" value we set it to now */ - if ((setup->tm_mday < 1) || (setup->tm_mday > 31)) - setup->tm_mday = now.tm_mday; - } - break; - case RT_ALARM_YAERLY: - { - /* if tm_mon is a "don't care" value we set it to now */ - if ((setup->tm_mon < 0) || (setup->tm_mon > 11)) - setup->tm_mon = now.tm_mon; - - if (setup->tm_mon == 1) - { - /* tm_mon is February */ - - /* tm_mday should be 1~29.otherwise,it's a "don't care" value */ - if ((setup->tm_mday < 1) || (setup->tm_mday > 29)) - setup->tm_mday = now.tm_mday; - } - else if (((setup->tm_mon <= 6) && (setup->tm_mon % 2 == 0)) || \ - ((setup->tm_mon > 6) && (setup->tm_mon % 2 == 1))) - { - /* Jan,Mar,May,Jul,Aug,Oct,Dec */ - - /* tm_mday should be 1~31.otherwise,it's a "don't care" value */ - if ((setup->tm_mday < 1) || (setup->tm_mday > 31)) - setup->tm_mday = now.tm_mday; - } - else - { - /* tm_mday should be 1~30.otherwise,it's a "don't care" value */ - if ((setup->tm_mday < 1) || (setup->tm_mday > 30)) - setup->tm_mday = now.tm_mday; - } - } - break; - default: - { - goto _exit; - } - } - - if ((setup->tm_hour == 23) && (setup->tm_min == 59) && (setup->tm_sec == 59)) - { - /* - for insurance purposes, we will generate an alarm - signal two seconds ahead of. - */ - setup->tm_sec = 60 - RT_ALARM_DELAY; - } - /* set initialized state */ - alarm->flag |= RT_ALARM_STATE_INITED; - ret = RT_EOK; - -_exit: - - return (ret); -} - -/** \brief send a rtc alarm event - * - * \param dev pointer to RTC device(currently unused,you can ignore it) - * \param event RTC event(currently unused) - * \return none - */ -void rt_alarm_update(rt_device_t dev, rt_uint32_t event) -{ - rt_event_send(&_container.event, 1); -} - -/** \brief modify the alarm setup - * - * \param alarm pointer to alarm - * \param cmd control command - * \param arg argument - */ -rt_err_t rt_alarm_control(rt_alarm_t alarm, int cmd, void *arg) -{ - rt_err_t ret = -RT_ERROR; - - RT_ASSERT(alarm != RT_NULL); - - rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); - switch (cmd) - { - case RT_ALARM_CTRL_MODIFY: - { - struct rt_alarm_setup *setup; - - RT_ASSERT(arg != RT_NULL); - setup = arg; - rt_alarm_stop(alarm); - alarm->flag = setup->flag & 0xFF00; - alarm->wktime = setup->wktime; - ret = alarm_setup(alarm, &alarm->wktime); - } - break; - } - - rt_mutex_release(&_container.mutex); - - return (ret); -} - -/** \brief start an alarm - * - * \param alarm pointer to alarm - * \return RT_EOK - */ -rt_err_t rt_alarm_start(rt_alarm_t alarm) -{ - rt_int32_t sec_now, sec_old, sec_new; - rt_err_t ret = RT_EOK; - time_t timestamp = (time_t)0; - struct tm now; - - if (alarm == RT_NULL) - return (RT_ERROR); - rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); - - if (!(alarm->flag & RT_ALARM_STATE_START)) - { - if (alarm_setup(alarm, &alarm->wktime) != RT_EOK) - { - ret = -RT_ERROR; - goto _exit; - } - - /* get time of now */ - get_timestamp(×tamp); - gmtime_r(×tamp, &now); - - alarm->flag |= RT_ALARM_STATE_START; - - /* set alarm */ - if (_container.current == RT_NULL) - { - ret = alarm_set(alarm); - } - else - { - sec_now = alarm_mkdaysec(&now); - sec_old = alarm_mkdaysec(&_container.current->wktime); - sec_new = alarm_mkdaysec(&alarm->wktime); - - if ((sec_new < sec_old) && (sec_new > sec_now)) - { - ret = alarm_set(alarm); - } - else if ((sec_new > sec_now) && (sec_old < sec_now)) - { - ret = alarm_set(alarm); - } - else if ((sec_new < sec_old) && (sec_old < sec_now)) - { - ret = alarm_set(alarm); - } - else - { - ret = RT_EOK; - goto _exit; - } - } - - if (ret == RT_EOK) - { - _container.current = alarm; - } - } - -_exit: - rt_mutex_release(&_container.mutex); - - return (ret); -} - -/** \brief stop an alarm - * - * \param alarm pointer to alarm - * \return RT_EOK - */ -rt_err_t rt_alarm_stop(rt_alarm_t alarm) -{ - rt_err_t ret = RT_EOK; - - if (alarm == RT_NULL) - return (RT_ERROR); - rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); - if (!(alarm->flag & RT_ALARM_STATE_START)) - goto _exit; - /* stop alarm */ - alarm->flag &= ~RT_ALARM_STATE_START; - - if (_container.current == alarm) - { - ret = alarm_set(alarm); - _container.current = RT_NULL; - } - - if (ret == RT_EOK) - alarm_update(0); - -_exit: - rt_mutex_release(&_container.mutex); - - return (ret); -} - -/** \brief delete an alarm - * - * \param alarm pointer to alarm - * \return RT_EOK - */ -rt_err_t rt_alarm_delete(rt_alarm_t alarm) -{ - rt_err_t ret = RT_EOK; - - if (alarm == RT_NULL) - return -RT_ERROR; - rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); - /* stop the alarm */ - alarm->flag &= ~RT_ALARM_STATE_START; - if (_container.current == alarm) - { - ret = alarm_set(alarm); - _container.current = RT_NULL; - /* set new alarm if necessary */ - alarm_update(0); - } - rt_list_remove(&alarm->list); - rt_free(alarm); - - rt_mutex_release(&_container.mutex); - - return (ret); -} - -/** \brief create an alarm - * - * \param flag set alarm mode e.g: RT_ALARM_DAILY - * \param setup pointer to setup infomation - */ -rt_alarm_t rt_alarm_create(rt_alarm_callback_t callback, struct rt_alarm_setup *setup) -{ - struct rt_alarm *alarm; - - if (setup == RT_NULL) - return (RT_NULL); - - alarm = rt_malloc(sizeof(struct rt_alarm)); - if (alarm == RT_NULL) - return (RT_NULL); - - rt_list_init(&alarm->list); - - alarm->wktime = setup->wktime; - alarm->flag = setup->flag & 0xFF00; - alarm->callback = callback; - rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); - rt_list_insert_after(&_container.head, &alarm->list); - rt_mutex_release(&_container.mutex); - - return (alarm); -} - -/** \brief rtc alarm service thread entry - * - */ -static void rt_alarmsvc_thread_init(void *param) -{ - rt_uint32_t recv; - - _container.current = RT_NULL; - - while (1) - { - if (rt_event_recv(&_container.event, 0xFFFF, - RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, - RT_WAITING_FOREVER, &recv) == RT_EOK) - { - alarm_update(recv); - } - } -} - -struct _alarm_flag -{ - const char* name; - rt_uint32_t flag; -}; - -static const struct _alarm_flag _alarm_flag_tbl[] = -{ - {"N", 0xffff}, /* none */ - {"O", RT_ALARM_ONESHOT}, /* only alarm once */ - {"D", RT_ALARM_DAILY}, /* alarm everyday */ - {"W", RT_ALARM_WEEKLY}, /* alarm weekly at Monday or Friday etc. */ - {"Mo", RT_ALARM_MONTHLY}, /* alarm monthly at someday */ - {"Y", RT_ALARM_YAERLY}, /* alarm yearly at a certain date */ - {"H", RT_ALARM_HOUR}, /* alarm each hour at a certain min:second */ - {"M", RT_ALARM_MINUTE}, /* alarm each minute at a certain second */ - {"S", RT_ALARM_SECOND}, /* alarm each second */ -}; - -static rt_uint8_t _alarm_flag_tbl_size = sizeof(_alarm_flag_tbl) / sizeof(_alarm_flag_tbl[0]); - -static rt_uint8_t get_alarm_flag_index(rt_uint32_t alarm_flag) -{ - for (rt_uint8_t index = 0; index < _alarm_flag_tbl_size; index++) - { - alarm_flag &= 0xff00; - if (alarm_flag == _alarm_flag_tbl[index].flag) - { - return index; - } - } - - return 0; -} - -void rt_alarm_dump(void) -{ - rt_list_t *next; - rt_alarm_t alarm; - - rt_kprintf("| hh:mm:ss | week | flag | en |\n"); - rt_kprintf("+----------+------+------+----+\n"); - for (next = _container.head.next; next != &_container.head; next = next->next) - { - alarm = rt_list_entry(next, struct rt_alarm, list); - rt_uint8_t flag_index = get_alarm_flag_index(alarm->flag); - rt_kprintf("| %02d:%02d:%02d | %2d | %2s | %2d |\n", - alarm->wktime.tm_hour, alarm->wktime.tm_min, alarm->wktime.tm_sec, - alarm->wktime.tm_wday, _alarm_flag_tbl[flag_index].name, alarm->flag & RT_ALARM_STATE_START); - } - rt_kprintf("+----------+------+------+----+\n"); -} - -MSH_CMD_EXPORT_ALIAS(rt_alarm_dump, list_alarm, list alarm info); - -/** \brief initialize alarm service system - * - * \param none - * \return none - */ -int rt_alarm_system_init(void) -{ - rt_thread_t tid; - - rt_list_init(&_container.head); - rt_event_init(&_container.event, "alarmsvc", RT_IPC_FLAG_FIFO); - rt_mutex_init(&_container.mutex, "alarmsvc", RT_IPC_FLAG_PRIO); - - tid = rt_thread_create("alarmsvc", - rt_alarmsvc_thread_init, RT_NULL, - 2048, 10, 5); - if (tid != RT_NULL) - rt_thread_startup(tid); - - return 0; -} - -INIT_PREV_EXPORT(rt_alarm_system_init); -#endif diff --git a/components/drivers/rtc/dev_alarm.c b/components/drivers/rtc/dev_alarm.c new file mode 100644 index 0000000000..b78528a04c --- /dev/null +++ b/components/drivers/rtc/dev_alarm.c @@ -0,0 +1,800 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-10-27 heyuanjie87 first version. + * 2013-05-17 aozima initial alarm event & mutex in system init. + * 2020-10-15 zhangsz add alarm flags hour minute second. + * 2020-11-09 zhangsz fix alarm set when modify rtc time. + */ + +#include +#include +#include + +#define RT_RTC_YEARS_MAX 137 +#ifdef RT_USING_SOFT_RTC +#define RT_ALARM_DELAY 0 +#else +#define RT_ALARM_DELAY 2 +#endif + +#if (defined(RT_USING_RTC) && defined(RT_USING_ALARM)) +static struct rt_alarm_container _container; + +rt_inline rt_uint32_t alarm_mkdaysec(struct tm *time) +{ + rt_uint32_t sec; + + sec = time->tm_sec; + sec += time->tm_min * 60; + sec += time->tm_hour * 3600; + + return (sec); +} + +static rt_err_t alarm_set(struct rt_alarm *alarm) +{ + rt_device_t device; + struct rt_rtc_wkalarm wkalarm; + rt_err_t ret; + + device = rt_device_find("rtc"); + + if (device == RT_NULL) + { + return (RT_ERROR); + } + + if (alarm->flag & RT_ALARM_STATE_START) + wkalarm.enable = RT_TRUE; + else + wkalarm.enable = RT_FALSE; + + wkalarm.tm_sec = alarm->wktime.tm_sec; + wkalarm.tm_min = alarm->wktime.tm_min; + wkalarm.tm_hour = alarm->wktime.tm_hour; + wkalarm.tm_mday = alarm->wktime.tm_mday; + wkalarm.tm_mon = alarm->wktime.tm_mon; + wkalarm.tm_year = alarm->wktime.tm_year; + + ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_ALARM, &wkalarm); + if ((ret == RT_EOK) && wkalarm.enable) + { + ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_ALARM, &wkalarm); + if (ret == RT_EOK) + { + /* + some RTC device like RX8025,it's alarms precision is 1 minute. + in this case,low level RTC driver should set wkalarm->tm_sec to 0. + */ + alarm->wktime.tm_sec = wkalarm.tm_sec; + alarm->wktime.tm_min = wkalarm.tm_min; + alarm->wktime.tm_hour = wkalarm.tm_hour; + alarm->wktime.tm_mday = wkalarm.tm_mday; + alarm->wktime.tm_mon = wkalarm.tm_mon; + alarm->wktime.tm_year = wkalarm.tm_year; + } + } + + return (ret); +} + +static void alarm_wakeup(struct rt_alarm *alarm, struct tm *now) +{ + rt_uint32_t sec_alarm, sec_now; + rt_bool_t wakeup = RT_FALSE; + time_t timestamp; + + sec_alarm = alarm_mkdaysec(&alarm->wktime); + sec_now = alarm_mkdaysec(now); + + if (alarm->flag & RT_ALARM_STATE_START) + { + switch (alarm->flag & 0xFF00) + { + case RT_ALARM_ONESHOT: + { + sec_alarm = timegm(&alarm->wktime); + sec_now = timegm(now); + if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm)) + { + /* stop alarm */ + alarm->flag &= ~RT_ALARM_STATE_START; + alarm_set(alarm); + wakeup = RT_TRUE; + } + } + break; + case RT_ALARM_SECOND: + { + alarm->wktime.tm_hour = now->tm_hour; + alarm->wktime.tm_min = now->tm_min; + alarm->wktime.tm_sec = now->tm_sec + 1; + if (alarm->wktime.tm_sec > 59) + { + alarm->wktime.tm_sec = 0; + alarm->wktime.tm_min = alarm->wktime.tm_min + 1; + if (alarm->wktime.tm_min > 59) + { + alarm->wktime.tm_min = 0; + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + } + wakeup = RT_TRUE; + } + break; + case RT_ALARM_MINUTE: + { + alarm->wktime.tm_hour = now->tm_hour; + if (alarm->wktime.tm_sec == now->tm_sec) + { + alarm->wktime.tm_min = now->tm_min + 1; + if (alarm->wktime.tm_min > 59) + { + alarm->wktime.tm_min = 0; + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + wakeup = RT_TRUE; + } + } + break; + case RT_ALARM_HOUR: + { + if ((alarm->wktime.tm_min == now->tm_min) && + (alarm->wktime.tm_sec == now->tm_sec)) + { + alarm->wktime.tm_hour = now->tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + wakeup = RT_TRUE; + } + } + break; + case RT_ALARM_DAILY: + { + if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm)) + wakeup = RT_TRUE; + } + break; + case RT_ALARM_WEEKLY: + { + /* alarm at wday */ + if (alarm->wktime.tm_wday == now->tm_wday) + { + sec_alarm += alarm->wktime.tm_wday * 24 * 3600; + sec_now += now->tm_wday * 24 * 3600; + + if (sec_now == sec_alarm) + wakeup = RT_TRUE; + } + } + break; + case RT_ALARM_MONTHLY: + { + /* monthly someday generate alarm signals */ + if (alarm->wktime.tm_mday == now->tm_mday) + { + if ((sec_now - sec_alarm) <= RT_ALARM_DELAY) + wakeup = RT_TRUE; + } + } + break; + case RT_ALARM_YAERLY: + { + if ((alarm->wktime.tm_mday == now->tm_mday) && \ + (alarm->wktime.tm_mon == now->tm_mon)) + { + if ((sec_now - sec_alarm) <= RT_ALARM_DELAY) + wakeup = RT_TRUE; + } + } + break; + } + + if ((wakeup == RT_TRUE) && (alarm->callback != RT_NULL)) + { + timestamp = (time_t)0; + get_timestamp(×tamp); + alarm->callback(alarm, timestamp); + } + } +} + +static void alarm_update(rt_uint32_t event) +{ + struct rt_alarm *alm_prev = RT_NULL, *alm_next = RT_NULL; + struct rt_alarm *alarm; + rt_int32_t sec_now, sec_alarm, sec_tmp; + rt_int32_t sec_next = 24 * 3600, sec_prev = 0; + time_t timestamp = (time_t)0; + struct tm now; + rt_list_t *next; + + rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); + if (!rt_list_isempty(&_container.head)) + { + /* get time of now */ + get_timestamp(×tamp); + gmtime_r(×tamp, &now); + + for (next = _container.head.next; next != &_container.head; next = next->next) + { + alarm = rt_list_entry(next, struct rt_alarm, list); + /* check the overtime alarm */ + alarm_wakeup(alarm, &now); + } + + /* get time of now */ + get_timestamp(×tamp); + gmtime_r(×tamp, &now); + sec_now = alarm_mkdaysec(&now); + + for (next = _container.head.next; next != &_container.head; next = next->next) + { + alarm = rt_list_entry(next, struct rt_alarm, list); + /* calculate seconds from 00:00:00 */ + sec_alarm = alarm_mkdaysec(&alarm->wktime); + if (alarm->flag & RT_ALARM_STATE_START) + { + sec_tmp = sec_alarm - sec_now; + if (sec_tmp > 0) + { + /* find alarm after now(now to 23:59:59) and the most recent */ + if (sec_tmp < sec_next) + { + sec_next = sec_tmp; + alm_next = alarm; + } + } + else + { + /* find alarm before now(00:00:00 to now) and furthest from now */ + if (sec_tmp < sec_prev) + { + sec_prev = sec_tmp; + alm_prev = alarm; + } + } + } + } + + /* enable the alarm after now first */ + if (sec_next < 24 * 3600) + { + if (alarm_set(alm_next) == RT_EOK) + _container.current = alm_next; + } + else if (sec_prev < 0) + { + /* enable the alarm before now */ + if (alarm_set(alm_prev) == RT_EOK) + _container.current = alm_prev; + } + else + { + if (_container.current != RT_NULL) + { + alarm_set(_container.current); + if (!(_container.current->flag & RT_ALARM_STATE_START)) + _container.current = RT_NULL; + } + } + } + rt_mutex_release(&_container.mutex); +} + +static int days_of_year_month(int tm_year, int tm_mon) +{ + int ret, year; + + year = tm_year + 1900; + if (tm_mon == 1) + { + ret = 28 + ((!(year % 4) && (year % 100)) || !(year % 400)); + } + else if (((tm_mon <= 6) && (tm_mon % 2 == 0)) || ((tm_mon > 6) && (tm_mon % 2 == 1))) + { + ret = 31; + } + else + { + ret = 30; + } + + return (ret); +} + +static rt_bool_t is_valid_date(struct tm *date) +{ + if ((date->tm_year < 0) || (date->tm_year > RT_RTC_YEARS_MAX)) + { + return (RT_FALSE); + } + + if ((date->tm_mon < 0) || (date->tm_mon > 11)) + { + return (RT_FALSE); + } + + if ((date->tm_mday < 1) || \ + (date->tm_mday > days_of_year_month(date->tm_year, date->tm_mon))) + { + return (RT_FALSE); + } + + return (RT_TRUE); +} + +static rt_err_t alarm_setup(rt_alarm_t alarm, struct tm *wktime) +{ + rt_err_t ret = -RT_ERROR; + time_t timestamp = (time_t)0; + struct tm *setup, now; + + setup = &alarm->wktime; + *setup = *wktime; + /* get time of now */ + get_timestamp(×tamp); + gmtime_r(×tamp, &now); + + /* if these are a "don't care" value,we set them to now*/ + if ((setup->tm_sec > 59) || (setup->tm_sec < 0)) + setup->tm_sec = now.tm_sec; + if ((setup->tm_min > 59) || (setup->tm_min < 0)) + setup->tm_min = now.tm_min; + if ((setup->tm_hour > 23) || (setup->tm_hour < 0)) + setup->tm_hour = now.tm_hour; + + switch (alarm->flag & 0xFF00) + { + case RT_ALARM_SECOND: + { + alarm->wktime.tm_hour = now.tm_hour; + alarm->wktime.tm_min = now.tm_min; + alarm->wktime.tm_sec = now.tm_sec + 1; + if (alarm->wktime.tm_sec > 59) + { + alarm->wktime.tm_sec = 0; + alarm->wktime.tm_min = alarm->wktime.tm_min + 1; + if (alarm->wktime.tm_min > 59) + { + alarm->wktime.tm_min = 0; + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + } + } + break; + case RT_ALARM_MINUTE: + { + alarm->wktime.tm_hour = now.tm_hour; + alarm->wktime.tm_min = now.tm_min + 1; + if (alarm->wktime.tm_min > 59) + { + alarm->wktime.tm_min = 0; + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + } + break; + case RT_ALARM_HOUR: + { + alarm->wktime.tm_hour = now.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + break; + case RT_ALARM_DAILY: + { + /* do nothing but needed */ + } + break; + case RT_ALARM_ONESHOT: + { + /* if these are "don't care" value we set them to now */ + if (setup->tm_year == RT_ALARM_TM_NOW) + setup->tm_year = now.tm_year; + if (setup->tm_mon == RT_ALARM_TM_NOW) + setup->tm_mon = now.tm_mon; + if (setup->tm_mday == RT_ALARM_TM_NOW) + setup->tm_mday = now.tm_mday; + /* make sure the setup is valid */ + if (!is_valid_date(setup)) + goto _exit; + } + break; + case RT_ALARM_WEEKLY: + { + /* if tm_wday is a "don't care" value we set it to now */ + if ((setup->tm_wday < 0) || (setup->tm_wday > 6)) + setup->tm_wday = now.tm_wday; + } + break; + case RT_ALARM_MONTHLY: + { + /* if tm_mday is a "don't care" value we set it to now */ + if ((setup->tm_mday < 1) || (setup->tm_mday > 31)) + setup->tm_mday = now.tm_mday; + } + break; + case RT_ALARM_YAERLY: + { + /* if tm_mon is a "don't care" value we set it to now */ + if ((setup->tm_mon < 0) || (setup->tm_mon > 11)) + setup->tm_mon = now.tm_mon; + + if (setup->tm_mon == 1) + { + /* tm_mon is February */ + + /* tm_mday should be 1~29.otherwise,it's a "don't care" value */ + if ((setup->tm_mday < 1) || (setup->tm_mday > 29)) + setup->tm_mday = now.tm_mday; + } + else if (((setup->tm_mon <= 6) && (setup->tm_mon % 2 == 0)) || \ + ((setup->tm_mon > 6) && (setup->tm_mon % 2 == 1))) + { + /* Jan,Mar,May,Jul,Aug,Oct,Dec */ + + /* tm_mday should be 1~31.otherwise,it's a "don't care" value */ + if ((setup->tm_mday < 1) || (setup->tm_mday > 31)) + setup->tm_mday = now.tm_mday; + } + else + { + /* tm_mday should be 1~30.otherwise,it's a "don't care" value */ + if ((setup->tm_mday < 1) || (setup->tm_mday > 30)) + setup->tm_mday = now.tm_mday; + } + } + break; + default: + { + goto _exit; + } + } + + if ((setup->tm_hour == 23) && (setup->tm_min == 59) && (setup->tm_sec == 59)) + { + /* + for insurance purposes, we will generate an alarm + signal two seconds ahead of. + */ + setup->tm_sec = 60 - RT_ALARM_DELAY; + } + /* set initialized state */ + alarm->flag |= RT_ALARM_STATE_INITED; + ret = RT_EOK; + +_exit: + + return (ret); +} + +/** \brief send a rtc alarm event + * + * \param dev pointer to RTC device(currently unused,you can ignore it) + * \param event RTC event(currently unused) + * \return none + */ +void rt_alarm_update(rt_device_t dev, rt_uint32_t event) +{ + rt_event_send(&_container.event, 1); +} + +/** \brief modify the alarm setup + * + * \param alarm pointer to alarm + * \param cmd control command + * \param arg argument + */ +rt_err_t rt_alarm_control(rt_alarm_t alarm, int cmd, void *arg) +{ + rt_err_t ret = -RT_ERROR; + + RT_ASSERT(alarm != RT_NULL); + + rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); + switch (cmd) + { + case RT_ALARM_CTRL_MODIFY: + { + struct rt_alarm_setup *setup; + + RT_ASSERT(arg != RT_NULL); + setup = arg; + rt_alarm_stop(alarm); + alarm->flag = setup->flag & 0xFF00; + alarm->wktime = setup->wktime; + ret = alarm_setup(alarm, &alarm->wktime); + } + break; + } + + rt_mutex_release(&_container.mutex); + + return (ret); +} + +/** \brief start an alarm + * + * \param alarm pointer to alarm + * \return RT_EOK + */ +rt_err_t rt_alarm_start(rt_alarm_t alarm) +{ + rt_int32_t sec_now, sec_old, sec_new; + rt_err_t ret = RT_EOK; + time_t timestamp = (time_t)0; + struct tm now; + + if (alarm == RT_NULL) + return (RT_ERROR); + rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); + + if (!(alarm->flag & RT_ALARM_STATE_START)) + { + if (alarm_setup(alarm, &alarm->wktime) != RT_EOK) + { + ret = -RT_ERROR; + goto _exit; + } + + /* get time of now */ + get_timestamp(×tamp); + gmtime_r(×tamp, &now); + + alarm->flag |= RT_ALARM_STATE_START; + + /* set alarm */ + if (_container.current == RT_NULL) + { + ret = alarm_set(alarm); + } + else + { + sec_now = alarm_mkdaysec(&now); + sec_old = alarm_mkdaysec(&_container.current->wktime); + sec_new = alarm_mkdaysec(&alarm->wktime); + + if ((sec_new < sec_old) && (sec_new > sec_now)) + { + ret = alarm_set(alarm); + } + else if ((sec_new > sec_now) && (sec_old < sec_now)) + { + ret = alarm_set(alarm); + } + else if ((sec_new < sec_old) && (sec_old < sec_now)) + { + ret = alarm_set(alarm); + } + else + { + ret = RT_EOK; + goto _exit; + } + } + + if (ret == RT_EOK) + { + _container.current = alarm; + } + } + +_exit: + rt_mutex_release(&_container.mutex); + + return (ret); +} + +/** \brief stop an alarm + * + * \param alarm pointer to alarm + * \return RT_EOK + */ +rt_err_t rt_alarm_stop(rt_alarm_t alarm) +{ + rt_err_t ret = RT_EOK; + + if (alarm == RT_NULL) + return (RT_ERROR); + rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); + if (!(alarm->flag & RT_ALARM_STATE_START)) + goto _exit; + /* stop alarm */ + alarm->flag &= ~RT_ALARM_STATE_START; + + if (_container.current == alarm) + { + ret = alarm_set(alarm); + _container.current = RT_NULL; + } + + if (ret == RT_EOK) + alarm_update(0); + +_exit: + rt_mutex_release(&_container.mutex); + + return (ret); +} + +/** \brief delete an alarm + * + * \param alarm pointer to alarm + * \return RT_EOK + */ +rt_err_t rt_alarm_delete(rt_alarm_t alarm) +{ + rt_err_t ret = RT_EOK; + + if (alarm == RT_NULL) + return -RT_ERROR; + rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); + /* stop the alarm */ + alarm->flag &= ~RT_ALARM_STATE_START; + if (_container.current == alarm) + { + ret = alarm_set(alarm); + _container.current = RT_NULL; + /* set new alarm if necessary */ + alarm_update(0); + } + rt_list_remove(&alarm->list); + rt_free(alarm); + + rt_mutex_release(&_container.mutex); + + return (ret); +} + +/** \brief create an alarm + * + * \param flag set alarm mode e.g: RT_ALARM_DAILY + * \param setup pointer to setup infomation + */ +rt_alarm_t rt_alarm_create(rt_alarm_callback_t callback, struct rt_alarm_setup *setup) +{ + struct rt_alarm *alarm; + + if (setup == RT_NULL) + return (RT_NULL); + + alarm = rt_malloc(sizeof(struct rt_alarm)); + if (alarm == RT_NULL) + return (RT_NULL); + + rt_list_init(&alarm->list); + + alarm->wktime = setup->wktime; + alarm->flag = setup->flag & 0xFF00; + alarm->callback = callback; + rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); + rt_list_insert_after(&_container.head, &alarm->list); + rt_mutex_release(&_container.mutex); + + return (alarm); +} + +/** \brief rtc alarm service thread entry + * + */ +static void rt_alarmsvc_thread_init(void *param) +{ + rt_uint32_t recv; + + _container.current = RT_NULL; + + while (1) + { + if (rt_event_recv(&_container.event, 0xFFFF, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + RT_WAITING_FOREVER, &recv) == RT_EOK) + { + alarm_update(recv); + } + } +} + +struct _alarm_flag +{ + const char* name; + rt_uint32_t flag; +}; + +static const struct _alarm_flag _alarm_flag_tbl[] = +{ + {"N", 0xffff}, /* none */ + {"O", RT_ALARM_ONESHOT}, /* only alarm once */ + {"D", RT_ALARM_DAILY}, /* alarm everyday */ + {"W", RT_ALARM_WEEKLY}, /* alarm weekly at Monday or Friday etc. */ + {"Mo", RT_ALARM_MONTHLY}, /* alarm monthly at someday */ + {"Y", RT_ALARM_YAERLY}, /* alarm yearly at a certain date */ + {"H", RT_ALARM_HOUR}, /* alarm each hour at a certain min:second */ + {"M", RT_ALARM_MINUTE}, /* alarm each minute at a certain second */ + {"S", RT_ALARM_SECOND}, /* alarm each second */ +}; + +static rt_uint8_t _alarm_flag_tbl_size = sizeof(_alarm_flag_tbl) / sizeof(_alarm_flag_tbl[0]); + +static rt_uint8_t get_alarm_flag_index(rt_uint32_t alarm_flag) +{ + for (rt_uint8_t index = 0; index < _alarm_flag_tbl_size; index++) + { + alarm_flag &= 0xff00; + if (alarm_flag == _alarm_flag_tbl[index].flag) + { + return index; + } + } + + return 0; +} + +void rt_alarm_dump(void) +{ + rt_list_t *next; + rt_alarm_t alarm; + + rt_kprintf("| hh:mm:ss | week | flag | en |\n"); + rt_kprintf("+----------+------+------+----+\n"); + for (next = _container.head.next; next != &_container.head; next = next->next) + { + alarm = rt_list_entry(next, struct rt_alarm, list); + rt_uint8_t flag_index = get_alarm_flag_index(alarm->flag); + rt_kprintf("| %02d:%02d:%02d | %2d | %2s | %2d |\n", + alarm->wktime.tm_hour, alarm->wktime.tm_min, alarm->wktime.tm_sec, + alarm->wktime.tm_wday, _alarm_flag_tbl[flag_index].name, alarm->flag & RT_ALARM_STATE_START); + } + rt_kprintf("+----------+------+------+----+\n"); +} + +MSH_CMD_EXPORT_ALIAS(rt_alarm_dump, list_alarm, list alarm info); + +/** \brief initialize alarm service system + * + * \param none + * \return none + */ +int rt_alarm_system_init(void) +{ + rt_thread_t tid; + + rt_list_init(&_container.head); + rt_event_init(&_container.event, "alarmsvc", RT_IPC_FLAG_FIFO); + rt_mutex_init(&_container.mutex, "alarmsvc", RT_IPC_FLAG_PRIO); + + tid = rt_thread_create("alarmsvc", + rt_alarmsvc_thread_init, RT_NULL, + 2048, 10, 5); + if (tid != RT_NULL) + rt_thread_startup(tid); + + return 0; +} + +INIT_PREV_EXPORT(rt_alarm_system_init); +#endif diff --git a/components/drivers/rtc/dev_rtc.c b/components/drivers/rtc/dev_rtc.c new file mode 100644 index 0000000000..f789036628 --- /dev/null +++ b/components/drivers/rtc/dev_rtc.c @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-01-29 aozima first version. + * 2012-04-12 aozima optimization: find rtc device only first. + * 2012-04-16 aozima add scheduler lock for set_date and set_time. + * 2018-02-16 armink add auto sync time by NTP + * 2021-05-09 Meco Man remove NTP + * 2021-06-11 iysheng implement RTC framework V2.0 + * 2021-07-30 Meco Man move rtc_core.c to rtc.c + */ + +#include +#include +#include +#include + +#ifdef RT_USING_RTC + +static rt_device_t _rtc_device; +/* + * This function initializes rtc_core + */ +static rt_err_t rt_rtc_init(struct rt_device *dev) +{ + rt_rtc_dev_t *rtc_core; + + RT_ASSERT(dev != RT_NULL); + rtc_core = (rt_rtc_dev_t *)dev; + if (rtc_core->ops->init) + { + return (rtc_core->ops->init()); + } + + return -RT_ENOSYS; +} + +static rt_err_t rt_rtc_open(struct rt_device *dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +static rt_err_t rt_rtc_close(struct rt_device *dev) +{ + /* Add close member function in rt_rtc_ops when need, + * then call that function here. + * */ + return RT_EOK; +} + +static rt_err_t rt_rtc_control(struct rt_device *dev, int cmd, void *args) +{ +#define TRY_DO_RTC_FUNC(rt_rtc_dev, func_name, args) \ + rt_rtc_dev->ops->func_name ? rt_rtc_dev->ops->func_name(args) : -RT_EINVAL; + + rt_rtc_dev_t *rtc_device; + rt_err_t ret = -RT_EINVAL; + + RT_ASSERT(dev != RT_NULL); + rtc_device = (rt_rtc_dev_t *)dev; + + switch (cmd) + { + case RT_DEVICE_CTRL_RTC_GET_TIME: + ret = TRY_DO_RTC_FUNC(rtc_device, get_secs, args); + break; + case RT_DEVICE_CTRL_RTC_SET_TIME: + ret = TRY_DO_RTC_FUNC(rtc_device, set_secs, args); + break; + case RT_DEVICE_CTRL_RTC_GET_TIMEVAL: + ret = TRY_DO_RTC_FUNC(rtc_device, get_timeval, args); + break; + case RT_DEVICE_CTRL_RTC_SET_TIMEVAL: + ret = TRY_DO_RTC_FUNC(rtc_device, set_timeval, args); + break; + case RT_DEVICE_CTRL_RTC_GET_ALARM: + ret = TRY_DO_RTC_FUNC(rtc_device, get_alarm, args); + break; + case RT_DEVICE_CTRL_RTC_SET_ALARM: + ret = TRY_DO_RTC_FUNC(rtc_device, set_alarm, args); + break; + default: + break; + } + + return ret; + +#undef TRY_DO_RTC_FUNC +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops rtc_core_ops = +{ + rt_rtc_init, + rt_rtc_open, + rt_rtc_close, + RT_NULL, + RT_NULL, + rt_rtc_control, +}; +#endif /* RT_USING_DEVICE_OPS */ + +rt_err_t rt_hw_rtc_register(rt_rtc_dev_t *rtc, + const char *name, + rt_uint32_t flag, + void *data) +{ + struct rt_device *device; + RT_ASSERT(rtc != RT_NULL); + + device = &(rtc->parent); + + device->type = RT_Device_Class_RTC; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &rtc_core_ops; +#else + device->init = rt_rtc_init; + device->open = rt_rtc_open; + device->close = rt_rtc_close; + device->read = RT_NULL; + device->write = RT_NULL; + device->control = rt_rtc_control; +#endif /* RT_USING_DEVICE_OPS */ + device->user_data = data; + + /* register a character device */ + return rt_device_register(device, name, flag); +} + +/** + * Set system date(time not modify, local timezone). + * + * @param rt_uint32_t year e.g: 2012. + * @param rt_uint32_t month e.g: 12 (1~12). + * @param rt_uint32_t day e.g: 31. + * + * @return rt_err_t if set success, return RT_EOK. + */ +rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day) +{ + time_t now, old_timestamp = 0; + struct tm tm_new = {0}; + rt_err_t ret = -RT_ERROR; + + if (_rtc_device == RT_NULL) + { + _rtc_device = rt_device_find("rtc"); + if (_rtc_device == RT_NULL) + { + return -RT_ERROR; + } + } + + /* get current time */ + ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_GET_TIME, &old_timestamp); + if (ret != RT_EOK) + { + return ret; + } + + /* converts calendar time into local time. */ + localtime_r(&old_timestamp, &tm_new); + + /* update date. */ + tm_new.tm_year = year - 1900; + tm_new.tm_mon = month - 1; /* tm_mon: 0~11 */ + tm_new.tm_mday = day; + + /* converts the local time into the calendar time. */ + now = mktime(&tm_new); + + /* update to RTC device. */ + ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_SET_TIME, &now); + return ret; +} + +/** + * Set system time(date not modify, local timezone). + * + * @param rt_uint32_t hour e.g: 0~23. + * @param rt_uint32_t minute e.g: 0~59. + * @param rt_uint32_t second e.g: 0~59. + * + * @return rt_err_t if set success, return RT_EOK. + */ +rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second) +{ + time_t now, old_timestamp = 0; + struct tm tm_new = {0}; + rt_err_t ret = -RT_ERROR; + + if (_rtc_device == RT_NULL) + { + _rtc_device = rt_device_find("rtc"); + if (_rtc_device == RT_NULL) + { + return -RT_ERROR; + } + } + + /* get current time */ + ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_GET_TIME, &old_timestamp); + if (ret != RT_EOK) + { + return ret; + } + + /* converts calendar time into local time. */ + localtime_r(&old_timestamp, &tm_new); + + /* update time. */ + tm_new.tm_hour = hour; + tm_new.tm_min = minute; + tm_new.tm_sec = second; + + /* converts the local time into the calendar time. */ + now = mktime(&tm_new); + + /* update to RTC device. */ + ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_SET_TIME, &now); + return ret; +} + +/** + * Set timestamp(UTC). + * + * @param time_t timestamp + * + * @return rt_err_t if set success, return RT_EOK. + */ +rt_err_t set_timestamp(time_t timestamp) +{ + if (_rtc_device == RT_NULL) + { + _rtc_device = rt_device_find("rtc"); + if (_rtc_device == RT_NULL) + { + return -RT_ERROR; + } + } + + /* update to RTC device. */ + return rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_SET_TIME, ×tamp); +} + +/** + * Get timestamp(UTC). + * + * @param time_t* timestamp + * + * @return rt_err_t if set success, return RT_EOK. + */ +rt_err_t get_timestamp(time_t *timestamp) +{ + if (_rtc_device == RT_NULL) + { + _rtc_device = rt_device_find("rtc"); + if (_rtc_device == RT_NULL) + { + return -RT_ERROR; + } + } + + /* Get timestamp from RTC device. */ + return rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_GET_TIME, timestamp); +} + +#ifdef RT_USING_FINSH +#include +/** + * get date and time or set (local timezone) [year month day hour min sec] + */ +static void date(int argc, char **argv) +{ + time_t now = (time_t)0; + + if (argc == 1) + { + struct timeval tv = { 0 }; + int32_t tz_offset_sec = 0; + uint32_t abs_tz_offset_sec = 0U; + +#if defined(RT_LIBC_USING_LIGHT_TZ_DST) + tz_offset_sec = rt_tz_get(); +#endif /* RT_LIBC_USING_LIGHT_TZ_DST */ + + gettimeofday(&tv, RT_NULL); + now = tv.tv_sec; + + abs_tz_offset_sec = tz_offset_sec > 0 ? tz_offset_sec : -tz_offset_sec; + /* output current time */ + rt_kprintf("local time: %.*s", 25U, ctime(&now)); + rt_kprintf("timestamps: %ld\n", (long)tv.tv_sec); + rt_kprintf("timezone: UTC%c%02d:%02d:%02d\n", + tz_offset_sec > 0 ? '+' : '-', abs_tz_offset_sec / 3600U, abs_tz_offset_sec % 3600U / 60U, abs_tz_offset_sec % 3600U % 60U); + } + else if (argc >= 7) + { + /* set time and date */ + struct tm tm_new = {0}; + time_t old = (time_t)0; + rt_err_t err; + + tm_new.tm_year = atoi(argv[1]) - 1900; + tm_new.tm_mon = atoi(argv[2]) - 1; /* .tm_min's range is [0-11] */ + tm_new.tm_mday = atoi(argv[3]); + tm_new.tm_hour = atoi(argv[4]); + tm_new.tm_min = atoi(argv[5]); + tm_new.tm_sec = atoi(argv[6]); + if (tm_new.tm_year <= 0) + { + rt_kprintf("year is out of range [1900-]\n"); + return; + } + if (tm_new.tm_mon > 11) /* .tm_min's range is [0-11] */ + { + rt_kprintf("month is out of range [1-12]\n"); + return; + } + if (tm_new.tm_mday == 0 || tm_new.tm_mday > 31) + { + rt_kprintf("day is out of range [1-31]\n"); + return; + } + if (tm_new.tm_hour > 23) + { + rt_kprintf("hour is out of range [0-23]\n"); + return; + } + if (tm_new.tm_min > 59) + { + rt_kprintf("minute is out of range [0-59]\n"); + return; + } + if (tm_new.tm_sec > 60) + { + rt_kprintf("second is out of range [0-60]\n"); + return; + } + /* save old timestamp */ + err = get_timestamp(&old); + if (err != RT_EOK) + { + rt_kprintf("Get current timestamp failed. %d\n", err); + return; + } + /* converts the local time into the calendar time. */ + now = mktime(&tm_new); + err = set_timestamp(now); + if (err != RT_EOK) + { + rt_kprintf("set date failed. %d\n", err); + return; + } + get_timestamp(&now); /* get new timestamp */ + rt_kprintf("old: %.*s", 25, ctime(&old)); + rt_kprintf("now: %.*s", 25, ctime(&now)); + } + else + { + rt_kprintf("please input: date [year month day hour min sec] or date\n"); + rt_kprintf("e.g: date 2018 01 01 23 59 59 or date\n"); + } +} +MSH_CMD_EXPORT(date, get date and time or set (local timezone) [year month day hour min sec]) +#endif /* RT_USING_FINSH */ + +#endif /* RT_USING_RTC */ diff --git a/components/drivers/rtc/dev_soft_rtc.c b/components/drivers/rtc/dev_soft_rtc.c new file mode 100644 index 0000000000..0eab72ebe5 --- /dev/null +++ b/components/drivers/rtc/dev_soft_rtc.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-01-30 armink the first version + */ + +#include +#include +#include +#include + +#ifdef RT_USING_KTIME +#include +#endif + +#ifdef RT_USING_SOFT_RTC + +/* 2018-01-30 14:44:50 = RTC_TIME_INIT(2018, 1, 30, 14, 44, 50) */ +#define RTC_TIME_INIT(year, month, day, hour, minute, second) \ + {.tm_year = year - 1900, .tm_mon = month - 1, .tm_mday = day, .tm_hour = hour, .tm_min = minute, .tm_sec = second} + +#ifndef SOFT_RTC_TIME_DEFAULT +#define SOFT_RTC_TIME_DEFAULT RTC_TIME_INIT(2018, 1, 1, 0, 0 ,0) +#endif + +#ifndef RTC_AUTO_SYNC_FIRST_DELAY +#define RTC_AUTO_SYNC_FIRST_DELAY 25 +#endif +#ifndef RTC_AUTO_SYNC_PERIOD +#define RTC_AUTO_SYNC_PERIOD 3600 +#endif + +static struct rt_work rtc_sync_work; +static rt_device_t source_device = RT_NULL; + +static struct rt_device soft_rtc_dev; +static rt_tick_t init_tick; +static time_t init_time; +static struct timeval init_tv = {0}; + +#ifdef RT_USING_KTIME +static struct timespec init_ts = {0}; +#endif + +#ifdef RT_USING_ALARM + +static struct rt_rtc_wkalarm wkalarm; +static struct rt_timer alarm_time; + +static void alarm_timeout(void *param) +{ + rt_alarm_update(param, 1); +} + +static void soft_rtc_alarm_update(struct rt_rtc_wkalarm *palarm) +{ + rt_tick_t next_tick; + + if (palarm->enable) + { + next_tick = RT_TICK_PER_SECOND; + rt_timer_control(&alarm_time, RT_TIMER_CTRL_SET_TIME, &next_tick); + rt_timer_start(&alarm_time); + } + else + { + rt_timer_stop(&alarm_time); + } +} + +#endif + +static void set_rtc_time(time_t t) +{ + init_time = t - (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND; +#ifdef RT_USING_ALARM + soft_rtc_alarm_update(&wkalarm); +#endif +} + +static void _source_device_control(int cmd, void *args) +{ + if (source_device == RT_NULL) + return; + + if (rt_device_open(source_device, 0) == RT_EOK) + { + rt_device_control(source_device, cmd, args); + rt_device_close(source_device); + } +} + +static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args) +{ + time_t *t; + struct tm time_temp; + + RT_ASSERT(dev != RT_NULL); + rt_memset(&time_temp, 0, sizeof(struct tm)); + + switch (cmd) + { + case RT_DEVICE_CTRL_RTC_GET_TIME: + { + t = (time_t *) args; + *t = init_time + (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND; + break; + } + case RT_DEVICE_CTRL_RTC_SET_TIME: + { + t = (time_t *) args; + set_rtc_time(*t); + _source_device_control(RT_DEVICE_CTRL_RTC_SET_TIME, t); + break; + } +#ifdef RT_USING_ALARM + case RT_DEVICE_CTRL_RTC_GET_ALARM: + *((struct rt_rtc_wkalarm *)args) = wkalarm; + break; + case RT_DEVICE_CTRL_RTC_SET_ALARM: + wkalarm = *((struct rt_rtc_wkalarm *)args); + soft_rtc_alarm_update(&wkalarm); + break; +#endif +#ifdef RT_USING_KTIME + case RT_DEVICE_CTRL_RTC_GET_TIMEVAL: + { + struct timeval _tv; + struct timeval *tv = (struct timeval *)args; + rt_ktime_boottime_get_us(&_tv); + tv->tv_sec = init_time + _tv.tv_sec; + tv->tv_usec = init_tv.tv_usec + _tv.tv_usec; + break; + } + case RT_DEVICE_CTRL_RTC_SET_TIMEVAL: + { + struct timeval _tv; + struct timeval *tv = (struct timeval *)args; + rt_ktime_boottime_get_us(&_tv); + set_rtc_time(tv->tv_sec); + init_tv.tv_usec = tv->tv_usec - _tv.tv_usec; + _source_device_control(RT_DEVICE_CTRL_RTC_SET_TIME, &(tv->tv_sec)); + break; + } + case RT_DEVICE_CTRL_RTC_GET_TIMESPEC: + { + struct timespec _ts; + struct timespec *ts = (struct timespec *)args; + rt_ktime_boottime_get_ns(&_ts); + ts->tv_sec = init_time + _ts.tv_sec; + ts->tv_nsec = init_ts.tv_nsec + _ts.tv_nsec; + break; + } + case RT_DEVICE_CTRL_RTC_SET_TIMESPEC: + { + struct timespec _ts; + struct timespec *ts = (struct timespec *)args; + rt_ktime_boottime_get_ns(&_ts); + set_rtc_time(ts->tv_sec); + init_ts.tv_nsec = ts->tv_nsec - _ts.tv_nsec; + _source_device_control(RT_DEVICE_CTRL_RTC_SET_TIME, &(ts->tv_sec)); + break; + } + case RT_DEVICE_CTRL_RTC_GET_TIMERES: + { + struct timespec *ts = (struct timespec *)args; + ts->tv_sec = 0; + ts->tv_nsec = (rt_ktime_cputimer_getres() / RT_KTIME_RESMUL); + break; + } +#else + case RT_DEVICE_CTRL_RTC_GET_TIMEVAL: + { + struct timeval *tv = (struct timeval *)args; + rt_tick_t tick = rt_tick_get() - init_tick; + tv->tv_sec = init_time + tick / RT_TICK_PER_SECOND; + tv->tv_usec = init_tv.tv_usec + ((tick % RT_TICK_PER_SECOND) * (1000000 / RT_TICK_PER_SECOND)); + break; + } + case RT_DEVICE_CTRL_RTC_SET_TIMEVAL: + { + struct timeval *tv = (struct timeval *)args; + rt_tick_t tick = rt_tick_get() - init_tick; + set_rtc_time(tv->tv_sec); + init_tv.tv_usec = tv->tv_usec - ((tick % RT_TICK_PER_SECOND) * (1000000 / RT_TICK_PER_SECOND)); + _source_device_control(RT_DEVICE_CTRL_RTC_SET_TIME, &(tv->tv_sec)); + break; + } + case RT_DEVICE_CTRL_RTC_GET_TIMERES: + { + struct timespec *ts = (struct timespec *)args; + ts->tv_sec = 0; + ts->tv_nsec = (1000UL * 1000 * 1000) / RT_TICK_PER_SECOND; + break; + } +#endif /* RT_USING_KTIME */ + default: + return -RT_EINVAL; + } + + return RT_EOK; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops soft_rtc_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + soft_rtc_control +}; +#endif + +static int rt_soft_rtc_init(void) +{ + static rt_bool_t init_ok = RT_FALSE; + struct tm time_new = SOFT_RTC_TIME_DEFAULT; + + if (init_ok) + { + return 0; + } + /* make sure only one 'rtc' device */ + RT_ASSERT(!rt_device_find("rtc")); + +#ifdef RT_USING_ALARM + rt_timer_init(&alarm_time, + "alarm", + alarm_timeout, + &soft_rtc_dev, + 0, + RT_TIMER_FLAG_SOFT_TIMER|RT_TIMER_FLAG_ONE_SHOT); +#endif + + init_tick = rt_tick_get(); + init_time = timegm(&time_new); + + soft_rtc_dev.type = RT_Device_Class_RTC; + + /* register rtc device */ +#ifdef RT_USING_DEVICE_OPS + soft_rtc_dev.ops = &soft_rtc_ops; +#else + soft_rtc_dev.init = RT_NULL; + soft_rtc_dev.open = RT_NULL; + soft_rtc_dev.close = RT_NULL; + soft_rtc_dev.read = RT_NULL; + soft_rtc_dev.write = RT_NULL; + soft_rtc_dev.control = soft_rtc_control; +#endif + + /* no private */ + soft_rtc_dev.user_data = RT_NULL; + + rt_device_register(&soft_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR); + + init_ok = RT_TRUE; + + return 0; +} +INIT_DEVICE_EXPORT(rt_soft_rtc_init); + +#ifdef RT_USING_SYSTEM_WORKQUEUE + +rt_err_t rt_soft_rtc_sync(void) +{ + time_t time = 0; + + if (source_device == RT_NULL) + { + rt_kprintf("error: rtc source not found, please set it!!!\n"); + return RT_ENOSYS; + } + + _source_device_control(RT_DEVICE_CTRL_RTC_GET_TIME, &time); + set_rtc_time(time); + return RT_EOK; +} + +static void rtc_sync_work_func(struct rt_work *work, void *work_data) +{ + rt_soft_rtc_sync(); + rt_work_submit(work, rt_tick_from_millisecond(RTC_AUTO_SYNC_PERIOD * 1000)); +} + +rt_err_t rt_soft_rtc_set_source(const char *name) +{ + RT_ASSERT(name != RT_NULL); + RT_ASSERT(rt_device_find(name)); // make sure source is exist + + source_device = rt_device_find(name); + rt_work_init(&rtc_sync_work, rtc_sync_work_func, RT_NULL); + rt_work_submit(&rtc_sync_work, rt_tick_from_millisecond(RTC_AUTO_SYNC_FIRST_DELAY * 1000)); + + return RT_EOK; +} + +#ifdef FINSH_USING_MSH +#include +static void cmd_rtc_sync(int argc, char **argv) +{ + struct timeval tv = {0}; + struct timezone tz = {0}; + time_t now = (time_t)0; + + rt_soft_rtc_sync(); + + gettimeofday(&tv, &tz); + now = tv.tv_sec; + /* output current time */ + rt_kprintf("local time: %.*s", 25, ctime(&now)); + rt_kprintf("timestamps: %ld\n", (long)tv.tv_sec); +} +MSH_CMD_EXPORT_ALIAS(cmd_rtc_sync, rtc_sync, Update time by real rtc); +#endif + +#endif /* RT_USING_SYSTEM_WORKQUEUE */ + +#endif /* RT_USING_SOFT_RTC */ diff --git a/components/drivers/rtc/rtc.c b/components/drivers/rtc/rtc.c deleted file mode 100644 index 4f4fbc61b0..0000000000 --- a/components/drivers/rtc/rtc.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2012-01-29 aozima first version. - * 2012-04-12 aozima optimization: find rtc device only first. - * 2012-04-16 aozima add scheduler lock for set_date and set_time. - * 2018-02-16 armink add auto sync time by NTP - * 2021-05-09 Meco Man remove NTP - * 2021-06-11 iysheng implement RTC framework V2.0 - * 2021-07-30 Meco Man move rtc_core.c to rtc.c - */ - -#include -#include -#include -#include - -#ifdef RT_USING_RTC - -static rt_device_t _rtc_device; -/* - * This function initializes rtc_core - */ -static rt_err_t rt_rtc_init(struct rt_device *dev) -{ - rt_rtc_dev_t *rtc_core; - - RT_ASSERT(dev != RT_NULL); - rtc_core = (rt_rtc_dev_t *)dev; - if (rtc_core->ops->init) - { - return (rtc_core->ops->init()); - } - - return -RT_ENOSYS; -} - -static rt_err_t rt_rtc_open(struct rt_device *dev, rt_uint16_t oflag) -{ - return RT_EOK; -} - -static rt_err_t rt_rtc_close(struct rt_device *dev) -{ - /* Add close member function in rt_rtc_ops when need, - * then call that function here. - * */ - return RT_EOK; -} - -static rt_err_t rt_rtc_control(struct rt_device *dev, int cmd, void *args) -{ -#define TRY_DO_RTC_FUNC(rt_rtc_dev, func_name, args) \ - rt_rtc_dev->ops->func_name ? rt_rtc_dev->ops->func_name(args) : -RT_EINVAL; - - rt_rtc_dev_t *rtc_device; - rt_err_t ret = -RT_EINVAL; - - RT_ASSERT(dev != RT_NULL); - rtc_device = (rt_rtc_dev_t *)dev; - - switch (cmd) - { - case RT_DEVICE_CTRL_RTC_GET_TIME: - ret = TRY_DO_RTC_FUNC(rtc_device, get_secs, args); - break; - case RT_DEVICE_CTRL_RTC_SET_TIME: - ret = TRY_DO_RTC_FUNC(rtc_device, set_secs, args); - break; - case RT_DEVICE_CTRL_RTC_GET_TIMEVAL: - ret = TRY_DO_RTC_FUNC(rtc_device, get_timeval, args); - break; - case RT_DEVICE_CTRL_RTC_SET_TIMEVAL: - ret = TRY_DO_RTC_FUNC(rtc_device, set_timeval, args); - break; - case RT_DEVICE_CTRL_RTC_GET_ALARM: - ret = TRY_DO_RTC_FUNC(rtc_device, get_alarm, args); - break; - case RT_DEVICE_CTRL_RTC_SET_ALARM: - ret = TRY_DO_RTC_FUNC(rtc_device, set_alarm, args); - break; - default: - break; - } - - return ret; - -#undef TRY_DO_RTC_FUNC -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops rtc_core_ops = -{ - rt_rtc_init, - rt_rtc_open, - rt_rtc_close, - RT_NULL, - RT_NULL, - rt_rtc_control, -}; -#endif /* RT_USING_DEVICE_OPS */ - -rt_err_t rt_hw_rtc_register(rt_rtc_dev_t *rtc, - const char *name, - rt_uint32_t flag, - void *data) -{ - struct rt_device *device; - RT_ASSERT(rtc != RT_NULL); - - device = &(rtc->parent); - - device->type = RT_Device_Class_RTC; - device->rx_indicate = RT_NULL; - device->tx_complete = RT_NULL; - -#ifdef RT_USING_DEVICE_OPS - device->ops = &rtc_core_ops; -#else - device->init = rt_rtc_init; - device->open = rt_rtc_open; - device->close = rt_rtc_close; - device->read = RT_NULL; - device->write = RT_NULL; - device->control = rt_rtc_control; -#endif /* RT_USING_DEVICE_OPS */ - device->user_data = data; - - /* register a character device */ - return rt_device_register(device, name, flag); -} - -/** - * Set system date(time not modify, local timezone). - * - * @param rt_uint32_t year e.g: 2012. - * @param rt_uint32_t month e.g: 12 (1~12). - * @param rt_uint32_t day e.g: 31. - * - * @return rt_err_t if set success, return RT_EOK. - */ -rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day) -{ - time_t now, old_timestamp = 0; - struct tm tm_new = {0}; - rt_err_t ret = -RT_ERROR; - - if (_rtc_device == RT_NULL) - { - _rtc_device = rt_device_find("rtc"); - if (_rtc_device == RT_NULL) - { - return -RT_ERROR; - } - } - - /* get current time */ - ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_GET_TIME, &old_timestamp); - if (ret != RT_EOK) - { - return ret; - } - - /* converts calendar time into local time. */ - localtime_r(&old_timestamp, &tm_new); - - /* update date. */ - tm_new.tm_year = year - 1900; - tm_new.tm_mon = month - 1; /* tm_mon: 0~11 */ - tm_new.tm_mday = day; - - /* converts the local time into the calendar time. */ - now = mktime(&tm_new); - - /* update to RTC device. */ - ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_SET_TIME, &now); - return ret; -} - -/** - * Set system time(date not modify, local timezone). - * - * @param rt_uint32_t hour e.g: 0~23. - * @param rt_uint32_t minute e.g: 0~59. - * @param rt_uint32_t second e.g: 0~59. - * - * @return rt_err_t if set success, return RT_EOK. - */ -rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second) -{ - time_t now, old_timestamp = 0; - struct tm tm_new = {0}; - rt_err_t ret = -RT_ERROR; - - if (_rtc_device == RT_NULL) - { - _rtc_device = rt_device_find("rtc"); - if (_rtc_device == RT_NULL) - { - return -RT_ERROR; - } - } - - /* get current time */ - ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_GET_TIME, &old_timestamp); - if (ret != RT_EOK) - { - return ret; - } - - /* converts calendar time into local time. */ - localtime_r(&old_timestamp, &tm_new); - - /* update time. */ - tm_new.tm_hour = hour; - tm_new.tm_min = minute; - tm_new.tm_sec = second; - - /* converts the local time into the calendar time. */ - now = mktime(&tm_new); - - /* update to RTC device. */ - ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_SET_TIME, &now); - return ret; -} - -/** - * Set timestamp(UTC). - * - * @param time_t timestamp - * - * @return rt_err_t if set success, return RT_EOK. - */ -rt_err_t set_timestamp(time_t timestamp) -{ - if (_rtc_device == RT_NULL) - { - _rtc_device = rt_device_find("rtc"); - if (_rtc_device == RT_NULL) - { - return -RT_ERROR; - } - } - - /* update to RTC device. */ - return rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_SET_TIME, ×tamp); -} - -/** - * Get timestamp(UTC). - * - * @param time_t* timestamp - * - * @return rt_err_t if set success, return RT_EOK. - */ -rt_err_t get_timestamp(time_t *timestamp) -{ - if (_rtc_device == RT_NULL) - { - _rtc_device = rt_device_find("rtc"); - if (_rtc_device == RT_NULL) - { - return -RT_ERROR; - } - } - - /* Get timestamp from RTC device. */ - return rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_GET_TIME, timestamp); -} - -#ifdef RT_USING_FINSH -#include -/** - * get date and time or set (local timezone) [year month day hour min sec] - */ -static void date(int argc, char **argv) -{ - time_t now = (time_t)0; - - if (argc == 1) - { - struct timeval tv = { 0 }; - int32_t tz_offset_sec = 0; - uint32_t abs_tz_offset_sec = 0U; - -#if defined(RT_LIBC_USING_LIGHT_TZ_DST) - tz_offset_sec = rt_tz_get(); -#endif /* RT_LIBC_USING_LIGHT_TZ_DST */ - - gettimeofday(&tv, RT_NULL); - now = tv.tv_sec; - - abs_tz_offset_sec = tz_offset_sec > 0 ? tz_offset_sec : -tz_offset_sec; - /* output current time */ - rt_kprintf("local time: %.*s", 25U, ctime(&now)); - rt_kprintf("timestamps: %ld\n", (long)tv.tv_sec); - rt_kprintf("timezone: UTC%c%02d:%02d:%02d\n", - tz_offset_sec > 0 ? '+' : '-', abs_tz_offset_sec / 3600U, abs_tz_offset_sec % 3600U / 60U, abs_tz_offset_sec % 3600U % 60U); - } - else if (argc >= 7) - { - /* set time and date */ - struct tm tm_new = {0}; - time_t old = (time_t)0; - rt_err_t err; - - tm_new.tm_year = atoi(argv[1]) - 1900; - tm_new.tm_mon = atoi(argv[2]) - 1; /* .tm_min's range is [0-11] */ - tm_new.tm_mday = atoi(argv[3]); - tm_new.tm_hour = atoi(argv[4]); - tm_new.tm_min = atoi(argv[5]); - tm_new.tm_sec = atoi(argv[6]); - if (tm_new.tm_year <= 0) - { - rt_kprintf("year is out of range [1900-]\n"); - return; - } - if (tm_new.tm_mon > 11) /* .tm_min's range is [0-11] */ - { - rt_kprintf("month is out of range [1-12]\n"); - return; - } - if (tm_new.tm_mday == 0 || tm_new.tm_mday > 31) - { - rt_kprintf("day is out of range [1-31]\n"); - return; - } - if (tm_new.tm_hour > 23) - { - rt_kprintf("hour is out of range [0-23]\n"); - return; - } - if (tm_new.tm_min > 59) - { - rt_kprintf("minute is out of range [0-59]\n"); - return; - } - if (tm_new.tm_sec > 60) - { - rt_kprintf("second is out of range [0-60]\n"); - return; - } - /* save old timestamp */ - err = get_timestamp(&old); - if (err != RT_EOK) - { - rt_kprintf("Get current timestamp failed. %d\n", err); - return; - } - /* converts the local time into the calendar time. */ - now = mktime(&tm_new); - err = set_timestamp(now); - if (err != RT_EOK) - { - rt_kprintf("set date failed. %d\n", err); - return; - } - get_timestamp(&now); /* get new timestamp */ - rt_kprintf("old: %.*s", 25, ctime(&old)); - rt_kprintf("now: %.*s", 25, ctime(&now)); - } - else - { - rt_kprintf("please input: date [year month day hour min sec] or date\n"); - rt_kprintf("e.g: date 2018 01 01 23 59 59 or date\n"); - } -} -MSH_CMD_EXPORT(date, get date and time or set (local timezone) [year month day hour min sec]) -#endif /* RT_USING_FINSH */ - -#endif /* RT_USING_RTC */ diff --git a/components/drivers/rtc/soft_rtc.c b/components/drivers/rtc/soft_rtc.c deleted file mode 100644 index 0eab72ebe5..0000000000 --- a/components/drivers/rtc/soft_rtc.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-01-30 armink the first version - */ - -#include -#include -#include -#include - -#ifdef RT_USING_KTIME -#include -#endif - -#ifdef RT_USING_SOFT_RTC - -/* 2018-01-30 14:44:50 = RTC_TIME_INIT(2018, 1, 30, 14, 44, 50) */ -#define RTC_TIME_INIT(year, month, day, hour, minute, second) \ - {.tm_year = year - 1900, .tm_mon = month - 1, .tm_mday = day, .tm_hour = hour, .tm_min = minute, .tm_sec = second} - -#ifndef SOFT_RTC_TIME_DEFAULT -#define SOFT_RTC_TIME_DEFAULT RTC_TIME_INIT(2018, 1, 1, 0, 0 ,0) -#endif - -#ifndef RTC_AUTO_SYNC_FIRST_DELAY -#define RTC_AUTO_SYNC_FIRST_DELAY 25 -#endif -#ifndef RTC_AUTO_SYNC_PERIOD -#define RTC_AUTO_SYNC_PERIOD 3600 -#endif - -static struct rt_work rtc_sync_work; -static rt_device_t source_device = RT_NULL; - -static struct rt_device soft_rtc_dev; -static rt_tick_t init_tick; -static time_t init_time; -static struct timeval init_tv = {0}; - -#ifdef RT_USING_KTIME -static struct timespec init_ts = {0}; -#endif - -#ifdef RT_USING_ALARM - -static struct rt_rtc_wkalarm wkalarm; -static struct rt_timer alarm_time; - -static void alarm_timeout(void *param) -{ - rt_alarm_update(param, 1); -} - -static void soft_rtc_alarm_update(struct rt_rtc_wkalarm *palarm) -{ - rt_tick_t next_tick; - - if (palarm->enable) - { - next_tick = RT_TICK_PER_SECOND; - rt_timer_control(&alarm_time, RT_TIMER_CTRL_SET_TIME, &next_tick); - rt_timer_start(&alarm_time); - } - else - { - rt_timer_stop(&alarm_time); - } -} - -#endif - -static void set_rtc_time(time_t t) -{ - init_time = t - (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND; -#ifdef RT_USING_ALARM - soft_rtc_alarm_update(&wkalarm); -#endif -} - -static void _source_device_control(int cmd, void *args) -{ - if (source_device == RT_NULL) - return; - - if (rt_device_open(source_device, 0) == RT_EOK) - { - rt_device_control(source_device, cmd, args); - rt_device_close(source_device); - } -} - -static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args) -{ - time_t *t; - struct tm time_temp; - - RT_ASSERT(dev != RT_NULL); - rt_memset(&time_temp, 0, sizeof(struct tm)); - - switch (cmd) - { - case RT_DEVICE_CTRL_RTC_GET_TIME: - { - t = (time_t *) args; - *t = init_time + (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND; - break; - } - case RT_DEVICE_CTRL_RTC_SET_TIME: - { - t = (time_t *) args; - set_rtc_time(*t); - _source_device_control(RT_DEVICE_CTRL_RTC_SET_TIME, t); - break; - } -#ifdef RT_USING_ALARM - case RT_DEVICE_CTRL_RTC_GET_ALARM: - *((struct rt_rtc_wkalarm *)args) = wkalarm; - break; - case RT_DEVICE_CTRL_RTC_SET_ALARM: - wkalarm = *((struct rt_rtc_wkalarm *)args); - soft_rtc_alarm_update(&wkalarm); - break; -#endif -#ifdef RT_USING_KTIME - case RT_DEVICE_CTRL_RTC_GET_TIMEVAL: - { - struct timeval _tv; - struct timeval *tv = (struct timeval *)args; - rt_ktime_boottime_get_us(&_tv); - tv->tv_sec = init_time + _tv.tv_sec; - tv->tv_usec = init_tv.tv_usec + _tv.tv_usec; - break; - } - case RT_DEVICE_CTRL_RTC_SET_TIMEVAL: - { - struct timeval _tv; - struct timeval *tv = (struct timeval *)args; - rt_ktime_boottime_get_us(&_tv); - set_rtc_time(tv->tv_sec); - init_tv.tv_usec = tv->tv_usec - _tv.tv_usec; - _source_device_control(RT_DEVICE_CTRL_RTC_SET_TIME, &(tv->tv_sec)); - break; - } - case RT_DEVICE_CTRL_RTC_GET_TIMESPEC: - { - struct timespec _ts; - struct timespec *ts = (struct timespec *)args; - rt_ktime_boottime_get_ns(&_ts); - ts->tv_sec = init_time + _ts.tv_sec; - ts->tv_nsec = init_ts.tv_nsec + _ts.tv_nsec; - break; - } - case RT_DEVICE_CTRL_RTC_SET_TIMESPEC: - { - struct timespec _ts; - struct timespec *ts = (struct timespec *)args; - rt_ktime_boottime_get_ns(&_ts); - set_rtc_time(ts->tv_sec); - init_ts.tv_nsec = ts->tv_nsec - _ts.tv_nsec; - _source_device_control(RT_DEVICE_CTRL_RTC_SET_TIME, &(ts->tv_sec)); - break; - } - case RT_DEVICE_CTRL_RTC_GET_TIMERES: - { - struct timespec *ts = (struct timespec *)args; - ts->tv_sec = 0; - ts->tv_nsec = (rt_ktime_cputimer_getres() / RT_KTIME_RESMUL); - break; - } -#else - case RT_DEVICE_CTRL_RTC_GET_TIMEVAL: - { - struct timeval *tv = (struct timeval *)args; - rt_tick_t tick = rt_tick_get() - init_tick; - tv->tv_sec = init_time + tick / RT_TICK_PER_SECOND; - tv->tv_usec = init_tv.tv_usec + ((tick % RT_TICK_PER_SECOND) * (1000000 / RT_TICK_PER_SECOND)); - break; - } - case RT_DEVICE_CTRL_RTC_SET_TIMEVAL: - { - struct timeval *tv = (struct timeval *)args; - rt_tick_t tick = rt_tick_get() - init_tick; - set_rtc_time(tv->tv_sec); - init_tv.tv_usec = tv->tv_usec - ((tick % RT_TICK_PER_SECOND) * (1000000 / RT_TICK_PER_SECOND)); - _source_device_control(RT_DEVICE_CTRL_RTC_SET_TIME, &(tv->tv_sec)); - break; - } - case RT_DEVICE_CTRL_RTC_GET_TIMERES: - { - struct timespec *ts = (struct timespec *)args; - ts->tv_sec = 0; - ts->tv_nsec = (1000UL * 1000 * 1000) / RT_TICK_PER_SECOND; - break; - } -#endif /* RT_USING_KTIME */ - default: - return -RT_EINVAL; - } - - return RT_EOK; -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops soft_rtc_ops = -{ - RT_NULL, - RT_NULL, - RT_NULL, - RT_NULL, - RT_NULL, - soft_rtc_control -}; -#endif - -static int rt_soft_rtc_init(void) -{ - static rt_bool_t init_ok = RT_FALSE; - struct tm time_new = SOFT_RTC_TIME_DEFAULT; - - if (init_ok) - { - return 0; - } - /* make sure only one 'rtc' device */ - RT_ASSERT(!rt_device_find("rtc")); - -#ifdef RT_USING_ALARM - rt_timer_init(&alarm_time, - "alarm", - alarm_timeout, - &soft_rtc_dev, - 0, - RT_TIMER_FLAG_SOFT_TIMER|RT_TIMER_FLAG_ONE_SHOT); -#endif - - init_tick = rt_tick_get(); - init_time = timegm(&time_new); - - soft_rtc_dev.type = RT_Device_Class_RTC; - - /* register rtc device */ -#ifdef RT_USING_DEVICE_OPS - soft_rtc_dev.ops = &soft_rtc_ops; -#else - soft_rtc_dev.init = RT_NULL; - soft_rtc_dev.open = RT_NULL; - soft_rtc_dev.close = RT_NULL; - soft_rtc_dev.read = RT_NULL; - soft_rtc_dev.write = RT_NULL; - soft_rtc_dev.control = soft_rtc_control; -#endif - - /* no private */ - soft_rtc_dev.user_data = RT_NULL; - - rt_device_register(&soft_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR); - - init_ok = RT_TRUE; - - return 0; -} -INIT_DEVICE_EXPORT(rt_soft_rtc_init); - -#ifdef RT_USING_SYSTEM_WORKQUEUE - -rt_err_t rt_soft_rtc_sync(void) -{ - time_t time = 0; - - if (source_device == RT_NULL) - { - rt_kprintf("error: rtc source not found, please set it!!!\n"); - return RT_ENOSYS; - } - - _source_device_control(RT_DEVICE_CTRL_RTC_GET_TIME, &time); - set_rtc_time(time); - return RT_EOK; -} - -static void rtc_sync_work_func(struct rt_work *work, void *work_data) -{ - rt_soft_rtc_sync(); - rt_work_submit(work, rt_tick_from_millisecond(RTC_AUTO_SYNC_PERIOD * 1000)); -} - -rt_err_t rt_soft_rtc_set_source(const char *name) -{ - RT_ASSERT(name != RT_NULL); - RT_ASSERT(rt_device_find(name)); // make sure source is exist - - source_device = rt_device_find(name); - rt_work_init(&rtc_sync_work, rtc_sync_work_func, RT_NULL); - rt_work_submit(&rtc_sync_work, rt_tick_from_millisecond(RTC_AUTO_SYNC_FIRST_DELAY * 1000)); - - return RT_EOK; -} - -#ifdef FINSH_USING_MSH -#include -static void cmd_rtc_sync(int argc, char **argv) -{ - struct timeval tv = {0}; - struct timezone tz = {0}; - time_t now = (time_t)0; - - rt_soft_rtc_sync(); - - gettimeofday(&tv, &tz); - now = tv.tv_sec; - /* output current time */ - rt_kprintf("local time: %.*s", 25, ctime(&now)); - rt_kprintf("timestamps: %ld\n", (long)tv.tv_sec); -} -MSH_CMD_EXPORT_ALIAS(cmd_rtc_sync, rtc_sync, Update time by real rtc); -#endif - -#endif /* RT_USING_SYSTEM_WORKQUEUE */ - -#endif /* RT_USING_SOFT_RTC */ -- cgit v1.3.1