diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index 7c3debb774..1eb23df2f1 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -66,6 +66,10 @@ config RT_USING_PIN bool "Using generic GPIO device drivers" default y +config RT_USING_PWM + bool "Using PWM device drivers" + default n + config RT_USING_MTD_NOR bool "Using MTD Nor Flash device drivers" default n diff --git a/components/drivers/include/drivers/rt_drv_pwm.h b/components/drivers/include/drivers/rt_drv_pwm.h new file mode 100644 index 0000000000..ffd08edabb --- /dev/null +++ b/components/drivers/include/drivers/rt_drv_pwm.h @@ -0,0 +1,54 @@ +/* + * File : rt_drv_pwm.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-05-07 aozima the first version + */ + +#ifndef __DRV_PWM_H_INCLUDE__ +#define __DRV_PWM_H_INCLUDE__ + +#define PWM_CMD_ENABLE (128 + 0) +#define PWM_CMD_DISABLE (128 + 1) +#define PWM_CMD_SET (128 + 2) +#define PWM_CMD_GET (128 + 3) + +struct rt_pwm_configuration +{ + rt_uint32_t channel; /* 0-n */ + rt_uint32_t period; /* unit:ns 1ns~4.29s:1Ghz~0.23hz */ + rt_uint32_t pulse; /* unit:ns (pulse<=period) */ +}; + +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; +}; + +extern 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); + +#endif /* __DRV_PWM_H_INCLUDE__ */ diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index f7aadd8305..e3c826fe53 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -112,6 +112,10 @@ extern "C" { #include "drivers/cputime.h" #endif +#ifdef RT_USING_PWM +#include "drivers/rt_drv_pwm.h" +#endif + #ifdef __cplusplus } #endif diff --git a/components/drivers/misc/SConscript b/components/drivers/misc/SConscript index 7f269d4ee9..4cc5f80084 100644 --- a/components/drivers/misc/SConscript +++ b/components/drivers/misc/SConscript @@ -8,6 +8,9 @@ group = [] if GetDepend(['RT_USING_PIN']): src = src + ['pin.c'] +if GetDepend(['RT_USING_PWM']): + src = src + ['rt_drv_pwm.c'] + if len(src): group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) diff --git a/components/drivers/misc/rt_drv_pwm.c b/components/drivers/misc/rt_drv_pwm.c new file mode 100644 index 0000000000..6884f8cfe4 --- /dev/null +++ b/components/drivers/misc/rt_drv_pwm.c @@ -0,0 +1,214 @@ +/* + * File : rt_drv_pwm.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-05-07 aozima the first version + */ + +#include + +#include +#include + + +static rt_err_t _pwm_control(rt_device_t dev, int cmd, void *args) +{ + rt_err_t result = RT_EOK; + struct rt_device_pwm *pwm = (struct rt_device_pwm *)dev; + + if (pwm->ops->control) + { + result = pwm->ops->control(pwm, cmd, args); + } + + return result; +} + + +/* +pos: channel +void *buffer: rt_uint32_t pulse[size] +size : number of pulse, only set to sizeof(rt_uint32_t). +*/ +static rt_size_t _pwm_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + rt_err_t result = RT_EOK; + struct rt_device_pwm *pwm = (struct rt_device_pwm *)dev; + rt_uint32_t *pulse = (rt_uint32_t *)buffer; + struct rt_pwm_configuration configuration = {0}; + + configuration.channel = pos; + + if (pwm->ops->control) + { + result = pwm->ops->control(pwm, PWM_CMD_GET, &configuration); + if (result != RT_EOK) + { + return 0; + } + + *pulse = configuration.pulse; + } + + return size; +} + +/* +pos: channel +void *buffer: rt_uint32_t pulse[size] +size : number of pulse, only set to sizeof(rt_uint32_t). +*/ +static rt_size_t _pwm_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + rt_err_t result = RT_EOK; + struct rt_device_pwm *pwm = (struct rt_device_pwm *)dev; + rt_uint32_t *pulse = (rt_uint32_t *)buffer; + struct rt_pwm_configuration configuration = {0}; + + configuration.channel = pos; + + if (pwm->ops->control) + { + result = pwm->ops->control(pwm, PWM_CMD_GET, &configuration); + if (result != RT_EOK) + { + return 0; + } + + configuration.pulse = *pulse; + + result = pwm->ops->control(pwm, PWM_CMD_SET, &configuration); + if (result != RT_EOK) + { + return 0; + } + + } + + return size; +} + +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 result = RT_EOK; + + memset(device, 0, sizeof(struct rt_device_pwm)); + + device->parent.type = RT_Device_Class_Miscellaneous; + + device->parent.init = RT_NULL; + device->parent.open = RT_NULL; + device->parent.close = RT_NULL; + device->parent.read = _pwm_read; + device->parent.write = _pwm_write; + device->parent.control = _pwm_control; + + device->ops = ops; + device->parent.user_data = (void *)user_data; + + result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR); + + return result; +} + +rt_err_t rt_pwm_enable(int channel) +{ + rt_err_t result = RT_EOK; + struct rt_device *device = rt_device_find("pwm"); + struct rt_pwm_configuration configuration = {0}; + + if (!device) + { + return -RT_EIO; + } + + configuration.channel = channel; + result = rt_device_control(device, PWM_CMD_ENABLE, &configuration); + + return result; +} + +rt_err_t rt_pwm_set(int channel, rt_uint32_t period, rt_uint32_t pulse) +{ + rt_err_t result = RT_EOK; + struct rt_device *device = rt_device_find("pwm"); + struct rt_pwm_configuration configuration = {0}; + + if (!device) + { + return -RT_EIO; + } + + configuration.channel = channel; + configuration.period = period; + configuration.pulse = pulse; + result = rt_device_control(device, PWM_CMD_SET, &configuration); + + return result; +} + + +#ifdef RT_USING_FINSH +#include + +FINSH_FUNCTION_EXPORT_ALIAS(rt_pwm_enable, pwm_enable, enable pwm by channel.); +FINSH_FUNCTION_EXPORT_ALIAS(rt_pwm_set, pwm_set, set pwm.); + +#ifdef FINSH_USING_MSH +static int pwm_enable(int argc, char **argv) +{ + int result = 0; + + if (argc != 2) + { + rt_kprintf("Usage: pwm_enable 1\n"); + result = -RT_ERROR; + goto _exit; + } + + result = rt_pwm_enable(atoi(argv[1])); + +_exit: + return result; +} +MSH_CMD_EXPORT(pwm_enable, pwm_enable 1); + +static int pwm_set(int argc, char **argv) +{ + int result = 0; + + if (argc != 4) + { + rt_kprintf("Usage: pwm_set 1 100 50\n"); + result = -RT_ERROR; + goto _exit; + } + + result = rt_pwm_set(atoi(argv[1]), atoi(argv[2]), atoi(argv[3])); + +_exit: + return result; +} +MSH_CMD_EXPORT(pwm_set, pwm_set 1 100 50); + +#endif /* FINSH_USING_MSH */ + + +#endif /* RT_USING_FINSH */