diff --git a/drivers/Kconfig b/drivers/Kconfig index 11991ae59a..77031932d2 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -36,6 +36,7 @@ source "drivers/note/Kconfig" source "drivers/pipes/Kconfig" source "drivers/power/Kconfig" source "drivers/regmap/Kconfig" +source "drivers/rmt/Kconfig" source "drivers/rptun/Kconfig" source "drivers/sensors/Kconfig" source "drivers/serial/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index d9d3244f61..e553af04d3 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -55,6 +55,7 @@ include note/Make.defs include pipes/Make.defs include power/Make.defs include regmap/Make.defs +include rmt/Make.defs include rptun/Make.defs include sensors/Make.defs include serial/Make.defs diff --git a/drivers/rmt/CMakeLists.txt b/drivers/rmt/CMakeLists.txt new file mode 100644 index 0000000000..95d89bece4 --- /dev/null +++ b/drivers/rmt/CMakeLists.txt @@ -0,0 +1,29 @@ +# ############################################################################## +# drivers/rmt/CMakeLists.txt +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +if(CONFIG_RMT) + set(SRCS) + + if(CONFIG_RMTCHAR) + list(APPEND SRCS rmtchar.c) + endif() + + target_sources(drivers PRIVATE ${SRCS}) +endif() diff --git a/drivers/rmt/Kconfig b/drivers/rmt/Kconfig new file mode 100644 index 0000000000..0e8de76d75 --- /dev/null +++ b/drivers/rmt/Kconfig @@ -0,0 +1,36 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +menuconfig RMT + bool "RMT (Remote Control) Driver Support" + default n + ---help--- + This option selects common RMT (Remote Control) options and should be + enabled by the platforms that implement a Remote Control Peripheral. + +if RMT + +config RMTCHAR + bool "RMT character driver (for testing only)" + default n + ---help--- + The RMT character driver is a simple character driver that supports + RMT transfers via read() and write(). This driver is primarily + intended to support RMT testing. It is not suitable for use in any + real driver application in its current form because its buffer + management heuristics are dependent on the lower half driver + (device-specific). Applications that use the RMT peripheral to + implement protocols such as NEC (for Remote Control), or use this + driver to implement other 1-wire protocols such as WS2812 LED must + provide their specific driver implementation. + +config RMT_DEFAULT_RX_BUFFER_SIZE + int "Default RX buffer size" + default 100 + ---help--- + The RMT RX default buffer size. This is the expected buffer size + that should be returned on a `read()` operation. + +endif # RMT diff --git a/drivers/rmt/Make.defs b/drivers/rmt/Make.defs new file mode 100644 index 0000000000..93e20c8048 --- /dev/null +++ b/drivers/rmt/Make.defs @@ -0,0 +1,30 @@ +############################################################################ +# drivers/rmt/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifeq ($(CONFIG_RMT),y) + +ifeq ($(CONFIG_RMTCHAR),y) +CSRCS += rmtchar.c +endif + +DEPPATH += --dep-path rmt +VPATH += :rmt + +endif diff --git a/drivers/rmt/rmtchar.c b/drivers/rmt/rmtchar.c new file mode 100644 index 0000000000..2c22e8d1c0 --- /dev/null +++ b/drivers/rmt/rmtchar.c @@ -0,0 +1,339 @@ +/**************************************************************************** + * drivers/rmt/rmtchar.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define DEVNAME_FMT "/dev/rmt%d" +#define DEVNAME_FMTLEN (8 + 3 + 1) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct rmt_driver_s +{ + /* The lower half RMT driver */ + + FAR struct rmt_dev_s *rmt; + + /* The minor identification of the driver. It's provided by the lower half + * driver and it can represent the channel being used. + */ + + int minor; + + mutex_t lock; /* Assures mutually exclusive access */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int rmt_open(FAR struct file *filep); +static int rmt_close(FAR struct file *filep); +static ssize_t rmt_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t rmt_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_rmt_channel_fops = +{ + rmt_open, /* open */ + rmt_close, /* close */ + rmt_read, /* read */ + rmt_write, /* write */ + NULL, /* seek */ + NULL, /* ioctl */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rmt_open + * + * Description: + * Prepare the RMT peripheral for use. This method just calls the lower + * half `open` routine if it exists. + * + * Input Parameters: + * filep - Pointer system file data + * + * Returned Value: + * The return code of the lower half `open` routine if it exists. + * Please check device-specific driver for more information. + * + ****************************************************************************/ + +static int rmt_open(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct rmt_driver_s *priv; + int ret = OK; + + /* Get our private data structure */ + + inode = filep->f_inode; + + priv = inode->i_private; + DEBUGASSERT(priv); + + if (priv->rmt->ops->open) + { + ret = priv->rmt->ops->open(priv->rmt); + } + + return ret; +} + +/**************************************************************************** + * Name: rmt_close + * + * Description: + * Close the RMT peripheral after use. This method just calls the lower + * half `close` routine if it exists. + * + * Input Parameters: + * filep - Pointer system file data + * + * Returned Value: + * The return code of the lower half `close` routine if it exists. + * Please check device-specific driver for more information. + * + ****************************************************************************/ + +static int rmt_close(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct rmt_driver_s *priv; + int ret = OK; + + /* Get our private data structure */ + + inode = filep->f_inode; + + priv = inode->i_private; + DEBUGASSERT(priv); + + if (priv->rmt->ops->close) + { + ret = priv->rmt->ops->close(priv->rmt); + } + + return ret; +} + +/**************************************************************************** + * Name: rmt_read + * + * Description: + * This function reads data from the RMT device into the provided buffer. + * The read operation is performed by the read function pointer in the + * RMT device's operations structure, if it exists. + * + * Input Parameters: + * filep - Pointer to the file structure. + * buffer - Pointer to the buffer where the read data should be stored. + * buflen - The maximum amount of data to be read. + * + * Returned Value: + * Returns the number of bytes read from the RMT device; a negated errno + * value is returned on any failure. + * + ****************************************************************************/ + +static ssize_t rmt_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct inode *inode; + FAR struct rmt_driver_s *priv; + ssize_t nread = 0; + + /* Get our private data structure */ + + inode = filep->f_inode; + + priv = inode->i_private; + DEBUGASSERT(priv); + + if (priv->rmt->ops->read) + { + int ret = priv->rmt->ops->read(priv->rmt, buffer, buflen); + if (ret < 0) + { + return ret; + } + + for (; ; ) + { + nread = circbuf_read(priv->rmt->circbuf , buffer, buflen); + if (nread != 0 || (filep->f_oflags & O_NONBLOCK)) + { + break; + } + + while (circbuf_is_empty(priv->rmt->circbuf)) + { + nxsem_wait_uninterruptible(priv->rmt->recvsem); + } + } + } + + return nread; +} + +/**************************************************************************** + * Name: rmt_write + * + * Description: + * Write to the RMT peripheral. This method just calls the lower half + * `write` routine if it exists. + * + * Input Parameters: + * filep - Pointer system file data + * buffer - Data to write to the RMT device + * buflen - Number of bytes requested to write + * + * Returned Value: + * Number of bytes that has been successfully written, or 0 when no + * bytes could be written for any reason. + * + ****************************************************************************/ + +static ssize_t rmt_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + FAR struct inode *inode; + FAR struct rmt_driver_s *priv; + ssize_t nwritten = 0; + + /* Get our private data structure */ + + inode = filep->f_inode; + + priv = inode->i_private; + DEBUGASSERT(priv); + + if (priv->rmt->ops->write) + { + nwritten = priv->rmt->ops->write(priv->rmt, buffer, buflen); + } + + return nwritten; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rmtchar_register + * + * Description: + * Create and register the RMT character driver. + * + * The RMT character driver is a simple character driver that supports RMT + * transfers via read() and write(). This driver is primarily intended to + * support RMT testing. It is not suitable for use in any real driver + * application in its current form because its buffer management heuristics + * are dependent on the lower half driver (device-specific). + * + * Input Parameters: + * rmt - An instance of the lower half RMT driver + * + * Returned Value: + * OK if the driver was successfully registered; A negated errno value is + * returned on any failure. + * + ****************************************************************************/ + +int rmtchar_register(FAR struct rmt_dev_s *rmt) +{ + FAR struct rmt_driver_s *priv; + char devname[DEVNAME_FMTLEN]; + size_t dev_size = sizeof(struct rmt_driver_s); + int ret; + + /* Sanity check */ + + DEBUGASSERT(rmt != NULL && (unsigned)rmt->minor < 1000); + + /* Allocate a RMT character device structure */ + + priv = kmm_zalloc(dev_size); + if (priv) + { + /* Initialize the RMT character device structure */ + + priv->rmt = rmt; + priv->minor = rmt->minor; + nxmutex_init(&priv->lock); + + /* Create the character device name */ + + snprintf(devname, DEVNAME_FMTLEN, DEVNAME_FMT, priv->minor); + ret = register_driver(devname, &g_rmt_channel_fops, 0666, priv); + if (ret < 0) + { + /* Free the device structure if we failed to create the character + * device. + */ + + nxmutex_destroy(&priv->lock); + kmm_free(priv); + return ret; + } + + /* Return the result of the registration */ + + return ret; + } + + return -ENOMEM; +} diff --git a/include/nuttx/mm/circbuf.h b/include/nuttx/mm/circbuf.h index 94bd8791af..e856d3b5e2 100644 --- a/include/nuttx/mm/circbuf.h +++ b/include/nuttx/mm/circbuf.h @@ -202,7 +202,7 @@ size_t circbuf_space(FAR struct circbuf_s *circ); * Name: circbuf_peekat * * Description: - * Get data speicified position from the circular buffer without removing + * Get data specified position from the circular buffer without removing * * Note : * That with only one concurrent reader and one concurrent writer, diff --git a/include/nuttx/rmt/rmt.h b/include/nuttx/rmt/rmt.h new file mode 100644 index 0000000000..1f2b1b216c --- /dev/null +++ b/include/nuttx/rmt/rmt.h @@ -0,0 +1,96 @@ +/**************************************************************************** + * include/nuttx/rmt/rmt.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_RMT_RMT_H +#define __INCLUDE_NUTTX_RMT_RMT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#ifdef CONFIG_RMT + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct rmt_dev_s; + +/* The RMT peripheral vtable */ + +struct rmt_ops_s +{ + CODE int (*open)(FAR struct rmt_dev_s *dev); + CODE int (*close)(FAR struct rmt_dev_s *dev); + CODE ssize_t (*write)(FAR struct rmt_dev_s *dev, + FAR const char *buffer, + size_t buflen); + CODE ssize_t (*read)(FAR struct rmt_dev_s *dev, + FAR char *buffer, + size_t buflen); +}; + +/* RMT private data. This structure only defines the initial fields of the + * structure visible to the RMT client. The specific implementation may + * add additional, device-specific fields. + */ + +struct rmt_dev_s +{ + FAR const struct rmt_ops_s *ops; + FAR struct circbuf_s *circbuf; + sem_t *recvsem; + int minor; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* CONFIG_RMT */ +#endif /* __INCLUDE_NUTTX_RMT_RMT_H */ diff --git a/boards/xtensa/esp32/common/include/esp32_rmt.h b/include/nuttx/rmt/rmtchar.h similarity index 65% rename from boards/xtensa/esp32/common/include/esp32_rmt.h rename to include/nuttx/rmt/rmtchar.h index 560c64f29f..6337e6ca8d 100644 --- a/boards/xtensa/esp32/common/include/esp32_rmt.h +++ b/include/nuttx/rmt/rmtchar.h @@ -1,5 +1,5 @@ /**************************************************************************** - * boards/xtensa/esp32/common/include/esp32_rmt.h + * include/nuttx/rmt/rmtchar.h * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -18,8 +18,8 @@ * ****************************************************************************/ -#ifndef __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ESP32_RMT_H -#define __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ESP32_RMT_H +#ifndef __INCLUDE_NUTTX_RMT_RMTCHAR_H +#define __INCLUDE_NUTTX_RMT_RMTCHAR_H /**************************************************************************** * Included Files @@ -27,12 +27,16 @@ #include -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ +#include +#include +#include + +#include + +#ifdef CONFIG_RMTCHAR /**************************************************************************** - * Type Definitions + * Pre-processor Definitions ****************************************************************************/ /**************************************************************************** @@ -43,7 +47,8 @@ * Public Data ****************************************************************************/ -#ifdef __cplusplus +#undef EXTERN +#if defined(__cplusplus) #define EXTERN extern "C" extern "C" { @@ -52,16 +57,36 @@ extern "C" #endif /**************************************************************************** - * Inline Functions + * Public Functions Prototypes ****************************************************************************/ /**************************************************************************** - * Public Function Prototypes + * Name: rmtchar_register + * + * Description: + * Create and register the RMT character driver. + * + * The RMT character driver is a simple character driver that supports RMT + * transfers via read() and write(). This driver is primarily intended to + * support RMT testing. It is not suitable for use in any real driver + * application in its current form because its buffer management heuristics + * are dependent on the lower half driver (device-specific). + * + * Input Parameters: + * rmt - An instance of the lower half RMT driver + * + * Returned Value: + * OK if the driver was successfully registered; A negated errno value is + * returned on any failure. + * ****************************************************************************/ +int rmtchar_register(FAR struct rmt_dev_s *rmt); + #undef EXTERN -#ifdef __cplusplus +#if defined(__cplusplus) } #endif -#endif /* __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ESP32_RMT_H */ +#endif /* CONFIG_RMT */ +#endif /* __INCLUDE_NUTTX_RMT_RMTCHAR_H */