[PATCH v5 3/4] bsps: Add ADC API
Duc Doan
dtbpkmte at gmail.com
Sun Jul 24 12:01:10 UTC 2022
---
bsps/include/bsp/adc.h | 292 ++++++++++++++++++++++++++++++++++
bsps/shared/dev/adc/adc.c | 200 +++++++++++++++++++++++
spec/build/bsps/bspopts.yml | 4 +
spec/build/bsps/obj.yml | 2 +
spec/build/bsps/optenadc.yml | 16 ++
spec/build/bsps/optnumadc.yml | 16 ++
6 files changed, 530 insertions(+)
create mode 100644 bsps/include/bsp/adc.h
create mode 100644 bsps/shared/dev/adc/adc.c
create mode 100644 spec/build/bsps/optenadc.yml
create mode 100644 spec/build/bsps/optnumadc.yml
diff --git a/bsps/include/bsp/adc.h b/bsps/include/bsp/adc.h
new file mode 100644
index 0000000000..d168e1b201
--- /dev/null
+++ b/bsps/include/bsp/adc.h
@@ -0,0 +1,292 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBBSP_BSP_ADC_H
+#define LIBBSP_BSP_ADC_H
+
+#include <bsp.h>
+#include <rtems.h>
+#include <bsp/periph_api.h>
+#include <bsp/gpio2.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {
+ RTEMS_ADC_NOT_STARTED = 0,
+ RTEMS_ADC_NOT_READY,
+ RTEMS_ADC_READY
+} rtems_adc_status;
+
+typedef enum {
+ RTEMS_ADC_ALIGN_LEFT,
+ RTEMS_ADC_ALIGN_RIGHT
+} rtems_adc_align;
+
+typedef enum {
+ RTEMS_ADC_NB_INTERRUPT,
+ RTEMS_ADC_NB_DMA
+} rtems_adc_nb_mode;
+
+/**
+ * @brief Enumeration of reference voltages.
+ */
+typedef enum {
+ RTEMS_ADC_REF_DEFAULT = 0,
+ RTEMS_ADC_REF_INTERNAL,
+ RTEMS_ADC_REF_EXTERNAL
+} rtems_adc_ref;
+
+#define RTEMS_ADC_NO_TIMEOUT 0xFFFFFFFFU
+
+typedef void (*rtems_adc_isr)(void *);
+typedef double (*rtems_adc_tf) (void *params, uint32_t raw_value);
+typedef struct rtems_adc_handlers rtems_adc_handlers;
+typedef struct rtems_adc_api rtems_adc_api;
+
+/**
+ * @brief Macro to help creating a rtems_adc_api object.
+ *
+ * Each BSP/driver must define its own handlers and create an object
+ * of this struct with pointers to those handlers.
+ */
+#define RTEMS_ADC_BUILD_API( \
+ _init, \
+ _read_raw, \
+ _start_read_raw_nb, \
+ _read_raw_nb, \
+ _set_resolution, \
+ _set_alignment, \
+ _configure_interrupt, \
+ _remove_interrupt, \
+ _enable_interrupt, \
+ _disable_interrupt) \
+ { \
+ .base = { \
+ .api_type = RTEMS_PERIPH_API_TYPE_ADC, \
+ .init = _init \
+ }, \
+ .read_raw = ( _read_raw ), \
+ .start_read_raw_nb = ( _start_read_raw_nb ), \
+ .read_raw_nb = ( _read_raw_nb ), \
+ .set_resolution = ( _set_resolution ), \
+ .set_alignment = ( _set_alignment ), \
+ .configure_interrupt = ( _configure_interrupt ), \
+ .remove_interrupt = ( _remove_interrupt ), \
+ .enable_interrupt = ( _enable_interrupt ), \
+ .disable_interrupt = ( _disable_interrupt ), \
+ };
+
+struct rtems_adc_api {
+ /**
+ * @brief Contain base structure rtems_periph_api.
+ * @see rtems_periph_api
+ */
+ rtems_periph_api base;
+ /**
+ * @brief This member is a pointer to a transfer function
+ * that will be assigned to this pin.
+ * If no transfer function assigned, it should remain NULL.
+ */
+ rtems_adc_tf tf;
+ void *tf_params;
+ /**
+ * @brief Pointer to a function that reads raw ADC value.
+ * This function is blocking and has a timeout parameter.
+ */
+ rtems_status_code (*read_raw) (rtems_gpio *, uint32_t *, uint32_t);
+ /**
+ * @brief Pointer to a function that starts ADC conversion
+ * in non-blocking style.
+ */
+ rtems_status_code (*start_read_raw_nb) (rtems_gpio *);
+ /**
+ * @brief Pointer to a function that gets a raw ADC value when
+ * available after a start_read_raw_nb() call.
+ * If data is not available, the function should return a status
+ * to indicate that.
+ */
+ rtems_adc_status (*read_raw_nb) (rtems_gpio *, uint32_t *);
+ /**
+ * @brief Pointer to a function that sets the resolution of an
+ * ADC controller associated with a pin.
+ *
+ * @note If a controller contains multiple pins, the resolution
+ * setting may affect all of them.
+ */
+ rtems_status_code (*set_resolution) (rtems_gpio *, unsigned int);
+ /**
+ * @brief Pointer to a function that sets the alignment of an
+ * ADC controller associated with a pin.
+ *
+ * @note If a controller contains multiple pins, the alignment
+ * setting may affect all of them.
+ */
+ rtems_status_code (*set_alignment) (rtems_gpio *, rtems_adc_align);
+ /**
+ * @brief This member is the pointer to a handler for configuring
+ * interrupt of a pin.
+ *
+ * This handler should register ISR and its arguments.
+ *
+ * @note Interrupt may occur when ADC conversion is completed.
+ * @note Enabling interrupt should be done in enable_interrupt()
+ * handler.
+ */
+ rtems_status_code (*configure_interrupt) (rtems_gpio *, rtems_adc_isr, void *);
+ /**
+ * @brief This member is the pointer to a handler for removing
+ * interrupt settings of a pin.
+ */
+ rtems_status_code (*remove_interrupt) (rtems_gpio *);
+ /**
+ * @brief This member is the pointer to a handler for enabling
+ * interrupt functionality of a pin.
+ */
+ rtems_status_code (*enable_interrupt) (rtems_gpio *);
+ /**
+ * @brief This member is the pointer to a handler for disabling
+ * interrupt of a pin.
+ */
+ rtems_status_code (*disable_interrupt) (rtems_gpio *);
+};
+
+/**
+ * @brief Read raw ADC value with infinite timeout.
+ *
+ * @param base[in]
+ * @param result[out]
+ *
+ * @retval
+ */
+extern rtems_status_code rtems_adc_read_raw(
+ rtems_gpio *base,
+ uint32_t *result
+);
+extern rtems_status_code rtems_adc_read_raw_timeout(
+ rtems_gpio *base,
+ uint32_t *result,
+ uint32_t timeout
+);
+
+/**
+ * @brief Starts a non-blocking ADC conversion.
+ *
+ * This function must be called before
+ * rtems_adc_read_raw_nb() or rtems_adc_read_nb()
+ *
+ * @param base
+ *
+ * @retval
+ */
+extern rtems_status_code rtems_adc_start_read_nb(
+ rtems_gpio *base
+);
+
+/**
+ * @brief Reads raw ADC value non-blocking.
+ */
+extern rtems_adc_status rtems_adc_read_raw_nb(
+ rtems_gpio *base,
+ uint32_t *result
+);
+
+/**
+ * @brief Assigns a transfer function with parameters
+ * to a pin.
+ */
+extern rtems_status_code rtems_adc_assign_tf(
+ rtems_gpio *base,
+ rtems_adc_tf tf,
+ void *params
+);
+
+/**
+ * @brief Removes the assigned transfer function from
+ * a pin.
+ */
+extern rtems_status_code rtems_adc_remove_tf(
+ rtems_gpio *base
+);
+
+/**
+ * @brief Reads an ADC value with infinite timeout.
+ *
+ * If no transfer function assigned, this will
+ * return the raw value via result pointer. Else,
+ * it returns the calculated value using transfer
+ * function.
+ *
+ * @param base[in]
+ * @param result[out]
+ *
+ * @retval
+ */
+extern rtems_status_code rtems_adc_read(
+ rtems_gpio *base,
+ double *result
+);
+extern rtems_status_code rtems_adc_read_timeout(
+ rtems_gpio *base,
+ double *result,
+ uint32_t timeout
+);
+extern rtems_adc_status rtems_adc_read_nb(
+ rtems_gpio *base,
+ double *result
+);
+
+extern rtems_status_code rtems_adc_set_resolution(
+ rtems_gpio *base,
+ unsigned int bits
+);
+extern rtems_status_code rtems_adc_set_alignment(
+ rtems_gpio *base,
+ rtems_adc_align align
+);
+
+extern rtems_status_code rtems_adc_configure_interrupt(
+ rtems_gpio *base,
+ rtems_adc_isr isr,
+ void *arg
+);
+extern rtems_status_code rtems_adc_remove_interrupt(
+ rtems_gpio *base
+);
+extern rtems_status_code rtems_adc_enable_interrupt(
+ rtems_gpio *base
+);
+extern rtems_status_code rtems_adc_disable_interrupt(
+ rtems_gpio *base
+);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_BSP_ADC_H */
diff --git a/bsps/shared/dev/adc/adc.c b/bsps/shared/dev/adc/adc.c
new file mode 100644
index 0000000000..e288d35691
--- /dev/null
+++ b/bsps/shared/dev/adc/adc.c
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bsp/adc.h>
+#include <stdbool.h>
+
+/**
+ * @brief Macro to check if an API pointer is ADC API.
+ * This only works if RTEMS_DEBUG is defined. This macro can
+ * only be called from functions.
+ *
+ * @param _api_ptr A pointer to rtems_periph_api.
+ */
+#ifdef RTEMS_DEBUG
+#define RTEMS_ADC_API_TYPE_CHECK( _api_ptr ) \
+ do { \
+ if ( *(rtems_periph_type *) ( _api_ptr ) != ( RTEMS_PERIPH_TYPE_ADC ) ) \
+ return RTEMS_UNSATISFIED; \
+ } while (0)
+#else
+#define RTEMS_ADC_API_TYPE_CHECK( _type ) \
+ ((void) ( _type ))
+#endif /* RTEMS_DEBUG */
+
+rtems_status_code rtems_adc_read_raw(
+ rtems_gpio *base,
+ uint32_t *result
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ return ((rtems_adc_api *) (base->api))->read_raw(base, result, RTEMS_ADC_NO_TIMEOUT);
+}
+rtems_status_code rtems_adc_read_raw_timeout(
+ rtems_gpio *base,
+ uint32_t *result,
+ uint32_t timeout
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ return ((rtems_adc_api *) (base->api))->read_raw(base, result, timeout);
+}
+
+rtems_adc_status rtems_adc_read_raw_nb(
+ rtems_gpio *base,
+ uint32_t *result
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ return ((rtems_adc_api *) (base->api))->read_raw_nb(base, result);
+}
+
+rtems_status_code rtems_adc_assign_tf(
+ rtems_gpio *base,
+ rtems_adc_tf tf,
+ void *params
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ ((rtems_adc_api *) (base->api))->tf = tf;
+ ((rtems_adc_api *) (base->api))->tf_params = params;
+ return RTEMS_SUCCESSFUL;
+}
+rtems_status_code rtems_adc_remove_tf(
+ rtems_gpio *base
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ ((rtems_adc_api *) (base->api))->tf = NULL;
+ ((rtems_adc_api *) (base->api))->tf_params = NULL;
+ return RTEMS_SUCCESSFUL;
+}
+rtems_status_code rtems_adc_read(
+ rtems_gpio *base,
+ double *result
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ uint32_t raw;
+ rtems_status_code sc = rtems_adc_read_raw(base, &raw);
+ if (sc == RTEMS_SUCCESSFUL) {
+ if (((rtems_adc_api *) (base->api))->tf == NULL)
+ *result = (double) raw;
+ else
+ *result = ((rtems_adc_api *) (base->api))->tf(((rtems_adc_api *) (base->api))->tf_params, raw);
+ }
+ return sc;
+}
+rtems_status_code rtems_adc_read_timeout(
+ rtems_gpio *base,
+ double *result,
+ uint32_t timeout
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ uint32_t raw;
+ rtems_status_code sc = rtems_adc_read_raw_timeout(base, &raw, timeout);
+ if (sc == RTEMS_SUCCESSFUL) {
+ if (((rtems_adc_api *) (base->api))->tf == NULL)
+ *result = (double) raw;
+ else
+ *result = ((rtems_adc_api *) (base->api))->tf(((rtems_adc_api *) (base->api))->tf_params, raw);
+ }
+ return sc;
+}
+
+rtems_status_code rtems_adc_start_read_nb(
+ rtems_gpio *base
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ return ((rtems_adc_api *) (base->api))->start_read_raw_nb(base);
+}
+rtems_adc_status rtems_adc_read_nb(
+ rtems_gpio *base,
+ double *result
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ uint32_t raw;
+ rtems_adc_status sc = rtems_adc_read_raw_nb(base, &raw);
+ if (sc == RTEMS_ADC_READY) {
+ if (((rtems_adc_api *) (base->api))->tf == NULL)
+ *result = (double) raw;
+ else
+ *result = ((rtems_adc_api *) (base->api))->tf(((rtems_adc_api *) (base->api))->tf_params, raw);
+ }
+ return sc;
+}
+
+rtems_status_code rtems_adc_set_resolution(
+ rtems_gpio *base,
+ unsigned int bits
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ return ((rtems_adc_api *) (base->api))->set_resolution(base, bits);
+}
+rtems_status_code rtems_adc_set_alignment(
+ rtems_gpio *base,
+ rtems_adc_align align
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ return ((rtems_adc_api *) (base->api))->set_alignment(base, align);
+}
+
+rtems_status_code rtems_adc_configure_interrupt(
+ rtems_gpio *base,
+ rtems_adc_isr isr,
+ void *arg
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ return ((rtems_adc_api *) (base->api))->configure_interrupt(base, isr, arg);
+}
+rtems_status_code rtems_adc_remove_interrupt(
+ rtems_gpio *base
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ return ((rtems_adc_api *) (base->api))->remove_interrupt(base);
+}
+rtems_status_code rtems_adc_enable_interrupt(
+ rtems_gpio *base
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ return ((rtems_adc_api *) (base->api))->enable_interrupt(base);
+}
+rtems_status_code rtems_adc_disable_interrupt(
+ rtems_gpio *base
+)
+{
+ RTEMS_ADC_API_TYPE_CHECK( base->api );
+ return ((rtems_adc_api *) (base->api))->disable_interrupt(base);
+}
diff --git a/spec/build/bsps/bspopts.yml b/spec/build/bsps/bspopts.yml
index 4a4c06d321..132259bc9e 100644
--- a/spec/build/bsps/bspopts.yml
+++ b/spec/build/bsps/bspopts.yml
@@ -7,6 +7,10 @@ guard: __BSP_OPTIONS_H
include-headers: []
install-path: ${BSP_INCLUDEDIR}
links:
+- role: build-dependency
+ uid: optenadc
+- role: build-dependency
+ uid: optnumadc
- role: build-dependency
uid: optbspoptflags
- role: build-dependency
diff --git a/spec/build/bsps/obj.yml b/spec/build/bsps/obj.yml
index 80736c197d..6c5e2536b3 100644
--- a/spec/build/bsps/obj.yml
+++ b/spec/build/bsps/obj.yml
@@ -18,6 +18,7 @@ install:
- bsps/include/bsp/fdt.h
- bsps/include/bsp/periph_api.h
- bsps/include/bsp/gpio2.h
+ - bsps/include/bsp/adc.h
- bsps/include/bsp/irq-default.h
- bsps/include/bsp/irq-generic.h
- bsps/include/bsp/irq-info.h
@@ -72,6 +73,7 @@ links:
uid: objnosmp
source:
- bsps/shared/dev/gpio/gpio.c
+- bsps/shared/dev/adc/adc.c
- bsps/shared/dev/periph_api/periph_api.c
- bsps/shared/dev/display/disp_hcms29xx.c
- bsps/shared/dev/display/font_hcms29xx.c
diff --git a/spec/build/bsps/optenadc.yml b/spec/build/bsps/optenadc.yml
new file mode 100644
index 0000000000..705a4236e4
--- /dev/null
+++ b/spec/build/bsps/optenadc.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+actions:
+- get-boolean: null
+- define-condition: null
+build-type: option
+copyrights:
+- Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+default: false
+default-by-variant: []
+description: |
+ This option enables the BSP to use RTEMS ADC API.
+enabled-by: true
+format: '{}'
+links: []
+name: BSP_ENABLE_ADC
+type: build
diff --git a/spec/build/bsps/optnumadc.yml b/spec/build/bsps/optnumadc.yml
new file mode 100644
index 0000000000..f9564f9b47
--- /dev/null
+++ b/spec/build/bsps/optnumadc.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+actions:
+- get-integer: null
+- define: null
+build-type: option
+copyrights:
+- Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+default: 0
+default-by-variant: []
+description: |
+ The number of external ADC used.
+enabled-by: true
+format: '{}'
+links: []
+name: BSP_NUM_ADC
+type: build
--
2.36.1
More information about the devel
mailing list