summaryrefslogtreecommitdiff
path: root/components/drivers
diff options
context:
space:
mode:
author[email protected] <[email protected]>2018-11-19 19:04:44 +0800
committer[email protected] <[email protected]>2018-11-20 10:08:31 +0800
commit049944529fe8bda17235c0185b0a6ac1b8ae7598 (patch)
treede34f7296a0e3d25d74a51b366f4edf12d8e934b /components/drivers
parentc8d38b79ff02760632cf356e562716d6f7f7845b (diff)
[add] adc framework
Diffstat (limited to 'components/drivers')
-rwxr-xr-xcomponents/drivers/Kconfig4
-rw-r--r--components/drivers/include/drivers/adc.h42
-rw-r--r--components/drivers/include/rtdevice.h4
-rw-r--r--components/drivers/misc/SConscript5
-rw-r--r--components/drivers/misc/adc.c219
5 files changed, 273 insertions, 1 deletions
diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig
index f3b814fa08..94af352410 100755
--- a/components/drivers/Kconfig
+++ b/components/drivers/Kconfig
@@ -72,6 +72,10 @@ config RT_USING_PIN
bool "Using generic GPIO device drivers"
default y
+config RT_USING_ADC
+ bool "Using ADC device drivers"
+ default n
+
config RT_USING_PWM
bool "Using PWM device drivers"
default n
diff --git a/components/drivers/include/drivers/adc.h b/components/drivers/include/drivers/adc.h
new file mode 100644
index 0000000000..8e3498e791
--- /dev/null
+++ b/components/drivers/include/drivers/adc.h
@@ -0,0 +1,42 @@
+/*
+ * 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
+ */
+
+#ifndef __ADC_H__
+#define __ADC_H__
+#include <rtthread.h>
+
+struct rt_adc_device;
+struct rt_adc_ops
+{
+ rt_err_t (*enabled)(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled);
+ rt_err_t (*convert)(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value);
+};
+
+struct rt_adc_device
+{
+ struct rt_device parent;
+ const struct rt_adc_ops *ops;
+};
+typedef struct rt_adc_device *rt_adc_device_t;
+
+typedef enum
+{
+ RT_ADC_CMD_ENABLE,
+ RT_ADC_CMD_DISABLE,
+} rt_adc_cmd_t;
+
+rt_err_t rt_hw_adc_register(rt_adc_device_t adc,const char *name, const struct rt_adc_ops *ops, const void *user_data);
+
+rt_uint32_t rt_adc_read(rt_adc_device_t dev, rt_uint32_t channel);
+rt_err_t rt_adc_enable(rt_adc_device_t dev, rt_uint32_t channel);
+rt_err_t rt_adc_disable(rt_adc_device_t dev, rt_uint32_t channel);
+
+#endif /* __ADC_H__ */
diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h
index 1843432768..d59b40cc47 100644
--- a/components/drivers/include/rtdevice.h
+++ b/components/drivers/include/rtdevice.h
@@ -99,6 +99,10 @@ extern "C" {
#include "drivers/cputime.h"
#endif
+#ifdef RT_USING_ADC
+#include "drivers/adc.h"
+#endif
+
#ifdef RT_USING_PWM
#include "drivers/rt_drv_pwm.h"
#endif
diff --git a/components/drivers/misc/SConscript b/components/drivers/misc/SConscript
index 4cc5f80084..c45ba524c5 100644
--- a/components/drivers/misc/SConscript
+++ b/components/drivers/misc/SConscript
@@ -7,7 +7,10 @@ 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']
diff --git a/components/drivers/misc/adc.c b/components/drivers/misc/adc.c
new file mode 100644
index 0000000000..aa3a3b7801
--- /dev/null
+++ b/components/drivers/misc/adc.c
@@ -0,0 +1,219 @@
+/*
+ * 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_ENABLE
+#define DBG_SECTION_NAME "adc"
+#define DBG_LEVEL DBG_INFO
+#define DBG_COLOR
+#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;
+}
+
+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.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;
+
+ 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 */