summaryrefslogtreecommitdiff
path: root/components/drivers/misc
diff options
context:
space:
mode:
authorxph <[email protected]>2020-04-09 16:35:28 +0800
committerGitHub <[email protected]>2020-04-09 16:35:28 +0800
commitca7f01d79b3e0a997c771cec298e4ebd65b75809 (patch)
tree3d2c48aae7203b14038ba7b98b500b5343ed7f2a /components/drivers/misc
parentf763f8e7284b0492c5a65ad0abf94ee1963d7dcc (diff)
parentbaa3145bfe61b3330b6a160523cc5470fa5db3a7 (diff)
Merge pull request #1 from RT-Thread/master
sync rtt
Diffstat (limited to 'components/drivers/misc')
-rw-r--r--components/drivers/misc/SConscript11
-rw-r--r--components/drivers/misc/adc.c235
-rw-r--r--components/drivers/misc/pulse_encoder.c136
-rw-r--r--components/drivers/misc/rt_drv_pwm.c33
-rw-r--r--components/drivers/misc/rt_inputcapture.c195
5 files changed, 600 insertions, 10 deletions
diff --git a/components/drivers/misc/SConscript b/components/drivers/misc/SConscript
index 4cc5f80084..8a9fdb5eb9 100644
--- a/components/drivers/misc/SConscript
+++ b/components/drivers/misc/SConscript
@@ -7,9 +7,18 @@ group = []
if GetDepend(['RT_USING_PIN']):
src = src + ['pin.c']
-
+
+if GetDepend(['RT_USING_ADC']):
+ src = src + ['adc.c']
+
if GetDepend(['RT_USING_PWM']):
src = src + ['rt_drv_pwm.c']
+
+if GetDepend(['RT_USING_PULSE_ENCODER']):
+ src = src + ['pulse_encoder.c']
+
+if GetDepend(['RT_USING_INPUT_CAPTURE']):
+ src = src + ['rt_inputcapture.c']
if len(src):
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
diff --git a/components/drivers/misc/adc.c b/components/drivers/misc/adc.c
new file mode 100644
index 0000000000..2d26beb243
--- /dev/null
+++ b/components/drivers/misc/adc.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018-05-07 aozima the first version
+ * 2018-11-16 Ernest Chen add finsh command and update adc function
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#define DBG_TAG "adc"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+static rt_size_t _adc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+ rt_err_t result = RT_EOK;
+ rt_size_t i;
+ struct rt_adc_device *adc = (struct rt_adc_device *)dev;
+ rt_uint32_t *value = (rt_uint32_t *)buffer;
+
+ for (i = 0; i < size; i += sizeof(int))
+ {
+ result = adc->ops->convert(adc, pos + i, value);
+ if (result != RT_EOK)
+ {
+ return 0;
+ }
+ value++;
+ }
+
+ return i;
+}
+
+static rt_err_t _adc_control(rt_device_t dev, int cmd, void *args)
+{
+ rt_err_t result = RT_EOK;
+ rt_adc_device_t adc = (struct rt_adc_device *)dev;
+
+ if (adc->ops->enabled == RT_NULL)
+ {
+ return -RT_ENOSYS;
+ }
+ if (cmd == RT_ADC_CMD_ENABLE)
+ {
+ result = adc->ops->enabled(adc, (rt_uint32_t)args, RT_TRUE);
+ }
+ else if (cmd == RT_ADC_CMD_DISABLE)
+ {
+ result = adc->ops->enabled(adc, (rt_uint32_t)args, RT_FALSE);
+ }
+
+ return result;
+}
+
+#ifdef RT_USING_DEVICE_OPS
+const static struct rt_device_ops adc_ops =
+{
+ RT_NULL,
+ RT_NULL,
+ RT_NULL,
+ _adc_read,
+ RT_NULL,
+ _adc_control,
+};
+#endif
+
+rt_err_t rt_hw_adc_register(rt_adc_device_t device, const char *name, const struct rt_adc_ops *ops, const void *user_data)
+{
+ rt_err_t result = RT_EOK;
+ RT_ASSERT(ops != RT_NULL && ops->convert != RT_NULL);
+
+ device->parent.type = RT_Device_Class_Miscellaneous;
+ device->parent.rx_indicate = RT_NULL;
+ device->parent.tx_complete = RT_NULL;
+
+#ifdef RT_USING_DEVICE_OPS
+ device->parent.ops = &adc_ops;
+#else
+ device->parent.init = RT_NULL;
+ device->parent.open = RT_NULL;
+ device->parent.close = RT_NULL;
+ device->parent.read = _adc_read;
+ device->parent.write = RT_NULL;
+ device->parent.control = _adc_control;
+#endif
+ device->ops = ops;
+ device->parent.user_data = (void *)user_data;
+
+ result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR);
+
+ return result;
+}
+
+rt_uint32_t rt_adc_read(rt_adc_device_t dev, rt_uint32_t channel)
+{
+ rt_uint32_t value;
+
+ RT_ASSERT(dev);
+
+ dev->ops->convert(dev, channel, &value);
+
+ return value;
+}
+
+rt_err_t rt_adc_enable(rt_adc_device_t dev, rt_uint32_t channel)
+{
+ rt_err_t result = RT_EOK;
+
+ RT_ASSERT(dev);
+ if (dev->ops->enabled != RT_NULL)
+ {
+ result = dev->ops->enabled(dev, channel, RT_TRUE);
+ }
+ else
+ {
+ result = -RT_ENOSYS;
+ }
+
+ return result;
+}
+
+rt_err_t rt_adc_disable(rt_adc_device_t dev, rt_uint32_t channel)
+{
+ rt_err_t result = RT_EOK;
+
+ RT_ASSERT(dev);
+ if (dev->ops->enabled != RT_NULL)
+ {
+ result = dev->ops->enabled(dev, channel, RT_FALSE);
+ }
+ else
+ {
+ result = -RT_ENOSYS;
+ }
+
+ return result;
+}
+
+#ifdef FINSH_USING_MSH
+
+static int adc(int argc, char **argv)
+{
+ int value = 0;
+ int result = RT_EOK;
+ static rt_adc_device_t adc_device = RT_NULL;
+ char *result_str;
+
+ if (argc > 1)
+ {
+ if (!strcmp(argv[1], "probe"))
+ {
+ if (argc == 3)
+ {
+ adc_device = (rt_adc_device_t)rt_device_find(argv[2]);
+ result_str = (adc_device == RT_NULL) ? "failure" : "success";
+ rt_kprintf("probe %s %s \n", argv[2], result_str);
+ }
+ else
+ {
+ rt_kprintf("adc probe <adc_name> - probe adc by name\n");
+ }
+ }
+ else
+ {
+ if (adc_device == RT_NULL)
+ {
+ rt_kprintf("Please using 'adc probe <adc_name>' first\n");
+ return -RT_ERROR;
+ }
+ if (!strcmp(argv[1], "enable"))
+ {
+ if (argc == 3)
+ {
+ result = rt_adc_enable(adc_device, atoi(argv[2]));
+ result_str = (result == RT_EOK) ? "success" : "failure";
+ rt_kprintf("%s channel %d enables %s \n", adc_device->parent.parent.name, atoi(argv[2]), result_str);
+ }
+ else
+ {
+ rt_kprintf("adc enable <channel> - enable adc channel\n");
+ }
+ }
+ else if (!strcmp(argv[1], "read"))
+ {
+ if (argc == 3)
+ {
+ value = rt_adc_read(adc_device, atoi(argv[2]));
+ rt_kprintf("%s channel %d read value is 0x%08X \n", adc_device->parent.parent.name, atoi(argv[2]), value);
+ }
+ else
+ {
+ rt_kprintf("adc read <channel> - read adc value on the channel\n");
+ }
+ }
+ else if (!strcmp(argv[1], "disable"))
+ {
+ if (argc == 3)
+ {
+ result = rt_adc_disable(adc_device, atoi(argv[2]));
+ result_str = (result == RT_EOK) ? "success" : "failure";
+ rt_kprintf("%s channel %d disable %s \n", adc_device->parent.parent.name, atoi(argv[2]), result_str);
+ }
+ else
+ {
+ rt_kprintf("adc disable <channel> - disable adc channel\n");
+ }
+ }
+ else
+ {
+ rt_kprintf("Unknown command. Please enter 'adc' for help\n");
+ }
+ }
+ }
+ else
+ {
+ rt_kprintf("Usage: \n");
+ rt_kprintf("adc probe <adc_name> - probe adc by name\n");
+ rt_kprintf("adc read <channel> - read adc value on the channel\n");
+ rt_kprintf("adc disable <channel> - disable adc channel\n");
+ rt_kprintf("adc enable <channel> - enable adc channel\n");
+ result = -RT_ERROR;
+ }
+ return RT_EOK;
+}
+MSH_CMD_EXPORT(adc, adc function);
+
+#endif /* FINSH_USING_MSH */
diff --git a/components/drivers/misc/pulse_encoder.c b/components/drivers/misc/pulse_encoder.c
new file mode 100644
index 0000000000..3145c24675
--- /dev/null
+++ b/components/drivers/misc/pulse_encoder.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2019-08-08 balanceTWK the first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+static rt_err_t rt_pulse_encoder_init(struct rt_device *dev)
+{
+ struct rt_pulse_encoder_device *pulse_encoder;
+
+ pulse_encoder = (struct rt_pulse_encoder_device *)dev;
+ if (pulse_encoder->ops->init)
+ {
+ return pulse_encoder->ops->init(pulse_encoder);
+ }
+ else
+ {
+ return -RT_ENOSYS;
+ }
+}
+
+static rt_err_t rt_pulse_encoder_open(struct rt_device *dev, rt_uint16_t oflag)
+{
+ struct rt_pulse_encoder_device *pulse_encoder;
+
+ pulse_encoder = (struct rt_pulse_encoder_device *)dev;
+ if (pulse_encoder->ops->control)
+ {
+ return pulse_encoder->ops->control(pulse_encoder, PULSE_ENCODER_CMD_ENABLE, RT_NULL);
+ }
+ else
+ {
+ return -RT_ENOSYS;
+ }
+}
+
+static rt_err_t rt_pulse_encoder_close(struct rt_device *dev)
+{
+ struct rt_pulse_encoder_device *pulse_encoder;
+
+ pulse_encoder = (struct rt_pulse_encoder_device *)dev;
+ if (pulse_encoder->ops->control)
+ {
+ return pulse_encoder->ops->control(pulse_encoder, PULSE_ENCODER_CMD_DISABLE, RT_NULL);
+ }
+ else
+ {
+ return -RT_ENOSYS;
+ }
+}
+
+static rt_size_t rt_pulse_encoder_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+ struct rt_pulse_encoder_device *pulse_encoder;
+
+ pulse_encoder = (struct rt_pulse_encoder_device *)dev;
+ if (pulse_encoder->ops->get_count)
+ {
+ *(rt_int32_t *)buffer = pulse_encoder->ops->get_count(pulse_encoder);
+ }
+ return 1;
+}
+
+static rt_err_t rt_pulse_encoder_control(struct rt_device *dev, int cmd, void *args)
+{
+ rt_err_t result;
+ struct rt_pulse_encoder_device *pulse_encoder;
+
+ result = RT_EOK;
+ pulse_encoder = (struct rt_pulse_encoder_device *)dev;
+ switch (cmd)
+ {
+ case PULSE_ENCODER_CMD_CLEAR_COUNT:
+ result = pulse_encoder->ops->clear_count(pulse_encoder);
+ break;
+ case PULSE_ENCODER_CMD_GET_TYPE:
+ *(enum rt_pulse_encoder_type *)args = pulse_encoder->type;
+ break;
+ case PULSE_ENCODER_CMD_ENABLE:
+ case PULSE_ENCODER_CMD_DISABLE:
+ result = pulse_encoder->ops->control(pulse_encoder, cmd, args);
+ break;
+ default:
+ result = -RT_ENOSYS;
+ break;
+ }
+
+ return result;
+}
+
+#ifdef RT_USING_DEVICE_OPS
+const static struct rt_device_ops pulse_encoder_ops =
+{
+ rt_pulse_encoder_init,
+ rt_pulse_encoder_open,
+ rt_pulse_encoder_close,
+ rt_pulse_encoder_read,
+ RT_NULL,
+ rt_pulse_encoder_control
+};
+#endif
+
+rt_err_t rt_device_pulse_encoder_register(struct rt_pulse_encoder_device *pulse_encoder, const char *name, void *user_data)
+{
+ struct rt_device *device;
+
+ RT_ASSERT(pulse_encoder != RT_NULL);
+ RT_ASSERT(pulse_encoder->ops != RT_NULL);
+
+ device = &(pulse_encoder->parent);
+
+ device->type = RT_Device_Class_Miscellaneous;
+ device->rx_indicate = RT_NULL;
+ device->tx_complete = RT_NULL;
+
+#ifdef RT_USING_DEVICE_OPS
+ device->ops = &pulse_encoder_ops;
+#else
+ device->init = rt_pulse_encoder_init;
+ device->open = rt_pulse_encoder_open;
+ device->close = rt_pulse_encoder_close;
+ device->read = rt_pulse_encoder_read;
+ device->write = RT_NULL;
+ device->control = rt_pulse_encoder_control;
+#endif
+ device->user_data = user_data;
+
+ return rt_device_register(device, name, RT_DEVICE_FLAG_RDONLY | RT_DEVICE_FLAG_STANDALONE);
+}
diff --git a/components/drivers/misc/rt_drv_pwm.c b/components/drivers/misc/rt_drv_pwm.c
index 6890e0e793..97d38d51b3 100644
--- a/components/drivers/misc/rt_drv_pwm.c
+++ b/components/drivers/misc/rt_drv_pwm.c
@@ -88,21 +88,36 @@ static rt_size_t _pwm_write(rt_device_t dev, rt_off_t pos, const void *buffer, r
return size;
}
+#ifdef RT_USING_DEVICE_OPS
+static const struct rt_device_ops pwm_device_ops =
+{
+ RT_NULL,
+ RT_NULL,
+ RT_NULL,
+ _pwm_read,
+ _pwm_write,
+ _pwm_control
+};
+#endif /* RT_USING_DEVICE_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 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;
+#ifdef RT_USING_DEVICE_OPS
+ device->parent.ops = &pwm_device_ops;
+#else
+ 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;
+#endif /* RT_USING_DEVICE_OPS */
+ device->parent.type = RT_Device_Class_Miscellaneous;
device->ops = ops;
device->parent.user_data = (void *)user_data;
@@ -244,7 +259,7 @@ static int pwm_set(int argc, char **argv)
_exit:
return result;
}
-MSH_CMD_EXPORT(pwm_set, pwm_set 1 100 50);
+MSH_CMD_EXPORT(pwm_set, pwm_set pwm1 1 100 50);
#endif /* FINSH_USING_MSH */
#endif /* RT_USING_FINSH */
diff --git a/components/drivers/misc/rt_inputcapture.c b/components/drivers/misc/rt_inputcapture.c
new file mode 100644
index 0000000000..d1886186d7
--- /dev/null
+++ b/components/drivers/misc/rt_inputcapture.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2019-08-13 balanceTWK the first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <rtdbg.h>
+
+static rt_err_t rt_inputcapture_init(struct rt_device *dev)
+{
+ rt_err_t ret;
+ struct rt_inputcapture_device *inputcapture;
+
+ RT_ASSERT(dev != RT_NULL);
+
+ ret = RT_EOK;
+ inputcapture = (struct rt_inputcapture_device *)dev;
+ inputcapture->watermark = RT_INPUT_CAPTURE_RB_SIZE / 2;
+ if (inputcapture->ops->init)
+ {
+ ret = inputcapture->ops->init(inputcapture);
+ }
+
+ return ret;
+}
+
+static rt_err_t rt_inputcapture_open(struct rt_device *dev, rt_uint16_t oflag)
+{
+ rt_err_t ret;
+ struct rt_inputcapture_device *inputcapture;
+
+ RT_ASSERT(dev != RT_NULL);
+
+ ret = RT_EOK;
+ inputcapture = (struct rt_inputcapture_device *)dev;
+ if (inputcapture->ringbuff == RT_NULL)
+ {
+ inputcapture->ringbuff = rt_ringbuffer_create(sizeof(struct rt_inputcapture_data) * RT_INPUT_CAPTURE_RB_SIZE);
+ }
+ if (inputcapture->ops->open)
+ {
+ ret = inputcapture->ops->open(inputcapture);
+ }
+
+ return ret;
+}
+
+static rt_err_t rt_inputcapture_close(struct rt_device *dev)
+{
+ rt_err_t ret;
+ struct rt_inputcapture_device *inputcapture;
+
+ RT_ASSERT(dev != RT_NULL);
+
+ ret = -RT_ERROR;
+ inputcapture = (struct rt_inputcapture_device *)dev;
+
+ if (inputcapture->ops->close)
+ {
+ ret = inputcapture->ops->close(inputcapture);
+ }
+
+ if (ret != RT_EOK)
+ {
+ return ret;
+ }
+
+ if (inputcapture->ringbuff)
+ {
+ rt_ringbuffer_destroy(inputcapture->ringbuff);
+ inputcapture->ringbuff = RT_NULL;
+ }
+ return ret;
+}
+
+static rt_size_t rt_inputcapture_read(struct rt_device *dev,
+ rt_off_t pos,
+ void *buffer,
+ rt_size_t size)
+{
+ rt_size_t receive_size;
+ struct rt_inputcapture_device *inputcapture;
+
+ RT_ASSERT(dev != RT_NULL);
+
+ inputcapture = (struct rt_inputcapture_device *)dev;
+ receive_size = rt_ringbuffer_get(inputcapture->ringbuff, (rt_uint8_t *)buffer, sizeof(struct rt_inputcapture_data) * size);
+
+ return receive_size / sizeof(struct rt_inputcapture_data);
+}
+
+static rt_err_t rt_inputcapture_control(struct rt_device *dev, int cmd, void *args)
+{
+ rt_err_t result;
+ struct rt_inputcapture_device *inputcapture;
+
+ RT_ASSERT(dev != RT_NULL);
+
+ result = RT_EOK;
+ inputcapture = (struct rt_inputcapture_device *)dev;
+ switch (cmd)
+ {
+ case INPUTCAPTURE_CMD_CLEAR_BUF:
+ if (inputcapture->ringbuff)
+ {
+ rt_ringbuffer_reset(inputcapture->ringbuff);
+ }
+ break;
+ case INPUTCAPTURE_CMD_SET_WATERMARK:
+ inputcapture->watermark = *(rt_size_t *)args;
+ break;
+ default:
+ result = -RT_ENOSYS;
+ break;
+ }
+
+ return result;
+}
+
+#ifdef RT_USING_DEVICE_OPS
+const static struct rt_device_ops inputcapture_ops =
+{
+ rt_inputcapture_init,
+ rt_inputcapture_open,
+ rt_inputcapture_close,
+ rt_inputcapture_read,
+ RT_NULL,
+ rt_inputcapture_control
+};
+#endif
+
+rt_err_t rt_device_inputcapture_register(struct rt_inputcapture_device *inputcapture, const char *name, void *user_data)
+{
+ struct rt_device *device;
+
+ RT_ASSERT(inputcapture != RT_NULL);
+ RT_ASSERT(inputcapture->ops != RT_NULL);
+ RT_ASSERT(inputcapture->ops->get_pulsewidth != RT_NULL);
+
+ device = &(inputcapture->parent);
+
+ device->type = RT_Device_Class_Miscellaneous;
+ device->rx_indicate = RT_NULL;
+ device->tx_complete = RT_NULL;
+ inputcapture->ringbuff = RT_NULL;
+
+#ifdef RT_USING_DEVICE_OPS
+ device->ops = &inputcapture_ops;
+#else
+ device->init = rt_inputcapture_init;
+ device->open = rt_inputcapture_open;
+ device->close = rt_inputcapture_close;
+ device->read = rt_inputcapture_read;
+ device->write = RT_NULL;
+ device->control = rt_inputcapture_control;
+#endif
+ device->user_data = user_data;
+
+ return rt_device_register(device, name, RT_DEVICE_FLAG_RDONLY | RT_DEVICE_FLAG_STANDALONE);
+}
+
+/**
+ * This function is ISR for inputcapture interrupt.
+ * level: RT_TRUE denotes high level pulse, and RT_FALSE denotes low level pulse.
+ */
+void rt_hw_inputcapture_isr(struct rt_inputcapture_device *inputcapture, rt_bool_t level)
+{
+ struct rt_inputcapture_data data;
+ rt_size_t receive_size;
+ if (inputcapture->ops->get_pulsewidth(inputcapture, &data.pulsewidth_us) != RT_EOK)
+ {
+ return;
+ }
+
+ data.is_high = level;
+ if (rt_ringbuffer_put(inputcapture->ringbuff, (rt_uint8_t *)&data, sizeof(struct rt_inputcapture_data)) == 0)
+ {
+ LOG_W("inputcapture ringbuffer doesn't have enough space.");
+ }
+
+ receive_size = rt_ringbuffer_data_len(inputcapture->ringbuff) / sizeof(struct rt_inputcapture_data);
+
+ if (receive_size >= inputcapture->watermark)
+ {
+ /* indicate to upper layer application */
+ if (inputcapture->parent.rx_indicate != RT_NULL)
+ inputcapture->parent.rx_indicate(&inputcapture->parent, receive_size);
+ }
+}