From a14b0ead827e0e556203aa687fe5d197a17755ae Mon Sep 17 00:00:00 2001 From: MacRsh Date: Sat, 25 Nov 2023 00:28:56 +0800 Subject: [PATCH] =?UTF-8?q?1.=E9=87=8D=E5=91=BD=E5=90=8D=E4=B8=B2=E5=8F=A3?= =?UTF-8?q?=E4=B8=BAserial=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- device/serial.c | 260 ++++++++++++++++++++++++++++++++++++++++ device/uart.c | 256 --------------------------------------- include/device/serial.h | 120 +++++++++++++++++++ include/device/uart.h | 121 ------------------- 4 files changed, 380 insertions(+), 377 deletions(-) create mode 100644 device/serial.c delete mode 100644 device/uart.c create mode 100644 include/device/serial.h delete mode 100644 include/device/uart.h diff --git a/device/serial.c b/device/serial.c new file mode 100644 index 0000000..9632d43 --- /dev/null +++ b/device/serial.c @@ -0,0 +1,260 @@ +/* + * @copyright (c) 2023, MR Development Team + * + * @license SPDX-License-Identifier: Apache-2.0 + * + * @date 2023-10-20 MacRsh First version + */ + +#include "include/device/serial.h" + +#ifdef MR_USING_SERIAL + +static int mr_serial_open(struct mr_dev *dev) +{ + struct mr_serial *serial = (struct mr_serial *)dev; + struct mr_serial_ops *ops = (struct mr_serial_ops *)dev->drv->ops; + + /* Allocate FIFO buffers */ + int ret = mr_ringbuf_allocate(&serial->rd_fifo, serial->rd_bufsz); + if (ret != MR_EOK) + { + return ret; + } + ret = mr_ringbuf_allocate(&serial->wr_fifo, serial->wr_bufsz); + if (ret != MR_EOK) + { + return ret; + } + + return ops->configure(serial, &serial->config); +} + +static int mr_serial_close(struct mr_dev *dev) +{ + struct mr_serial *serial = (struct mr_serial *)dev; + struct mr_serial_ops *ops = (struct mr_serial_ops *)dev->drv->ops; + struct mr_serial_config close_config = {0}; + + /* Free FIFO buffers */ + mr_ringbuf_free(&serial->rd_fifo); + mr_ringbuf_free(&serial->wr_fifo); + + return ops->configure(serial, &close_config); +} + +static ssize_t mr_serial_read(struct mr_dev *dev, int off, void *buf, size_t size, int sync_or_async) +{ + struct mr_serial *serial = (struct mr_serial *)dev; + struct mr_serial_ops *ops = (struct mr_serial_ops *)dev->drv->ops; + + if (mr_ringbuf_get_bufsz(&serial->rd_fifo) == 0) + { + return ops->read(serial, buf, size); + } else + { + return (ssize_t)mr_ringbuf_read(&serial->rd_fifo, buf, size); + } +} + +static ssize_t mr_serial_write(struct mr_dev *dev, int off, const void *buf, size_t size, int sync_or_async) +{ + struct mr_serial *serial = (struct mr_serial *)dev; + struct mr_serial_ops *ops = (struct mr_serial_ops *)dev->drv->ops; + + if (sync_or_async == MR_SYNC) + { + return ops->write(serial, buf, size); + } else + { + if (mr_ringbuf_get_bufsz(&serial->wr_fifo) == 0) + { + return ops->write(serial, buf, size); + } else + { + ssize_t ret = (ssize_t)mr_ringbuf_write(&serial->wr_fifo, buf, size); + + /* Start interrupt sending */ + ops->start_tx(serial); + return ret; + } + } +} + +static int mr_serial_ioctl(struct mr_dev *dev, int off, int cmd, void *args) +{ + struct mr_serial *serial = (struct mr_serial *)dev; + struct mr_serial_ops *ops = (struct mr_serial_ops *)dev->drv->ops; + + switch (cmd) + { + case MR_CTRL_SET_CONFIG: + { + if (args != MR_NULL) + { + struct mr_serial_config config = *(struct mr_serial_config *)args; + + int ret = ops->configure(serial, &config); + if (ret == MR_EOK) + { + serial->config = config; + } + return ret; + } + return MR_EINVAL; + } + case MR_CTRL_SET_RD_BUFSZ: + { + if (args != MR_NULL) + { + size_t bufsz = *(size_t *)args; + + int ret = mr_ringbuf_allocate(&serial->rd_fifo, bufsz); + serial->rd_bufsz = 0; + if (ret == MR_EOK) + { + serial->rd_bufsz = bufsz; + } + return ret; + } + return MR_EINVAL; + } + case MR_CTRL_SET_WR_BUFSZ: + { + if (args != MR_NULL) + { + size_t bufsz = *(size_t *)args; + + int ret = mr_ringbuf_allocate(&serial->wr_fifo, bufsz); + serial->wr_bufsz = 0; + if (ret == MR_EOK) + { + serial->wr_bufsz = bufsz; + } + return ret; + } + return MR_EINVAL; + } + + case MR_CTRL_GET_CONFIG: + { + if (args != MR_NULL) + { + struct mr_serial_config *config = (struct mr_serial_config *)args; + + *config = serial->config; + return MR_EOK; + } + return MR_EINVAL; + } + case MR_CTRL_GET_RD_BUFSZ: + { + if (args != MR_NULL) + { + *(size_t *)args = serial->rd_bufsz; + return MR_EOK; + } + return MR_EINVAL; + } + case MR_CTRL_GET_WR_BUFSZ: + { + if (args != MR_NULL) + { + *(size_t *)args = serial->wr_bufsz; + return MR_EOK; + } + return MR_EINVAL; + } + + default: + { + return MR_ENOTSUP; + } + } +} + +static ssize_t mr_serial_isr(struct mr_dev *dev, int event, void *args) +{ + struct mr_serial *serial = (struct mr_serial *)dev; + struct mr_serial_ops *ops = (struct mr_serial_ops *)dev->drv->ops; + + switch (event) + { + case MR_ISR_EVENT_RD_INTER: + { + uint8_t data = 0; + + /* Read data to FIFO */ + ops->read(serial, &data, sizeof(data)); + mr_ringbuf_push_force(&serial->rd_fifo, data); + + return (ssize_t)mr_ringbuf_get_data_size(&serial->rd_fifo); + } + case MR_ISR_EVENT_WR_INTER: + { + uint8_t data = 0; + + /* Write data from FIFO */ + if (mr_ringbuf_pop(&serial->wr_fifo, &data) == sizeof(data)) + { + ops->write(serial, &data, sizeof(data)); + } else + { + ops->stop_tx(serial); + } + + return (ssize_t)mr_ringbuf_get_data_size(&serial->wr_fifo); + } + + default: + { + return MR_ENOTSUP; + } + } +} + +/** + * @brief This function register a serial. + * + * @param serial The serial. + * @param name The name of the serial. + * @param drv The driver of the serial. + * + * @return MR_EOK on success, otherwise an error code. + */ +int mr_serial_register(struct mr_serial *serial, const char *name, struct mr_drv *drv) +{ + static struct mr_dev_ops ops = + { + mr_serial_open, + mr_serial_close, + mr_serial_read, + mr_serial_write, + mr_serial_ioctl, + mr_serial_isr + }; + struct mr_serial_config default_config = MR_SERIAL_CONFIG_DEFAULT; + + mr_assert(serial != MR_NULL); + mr_assert(name != MR_NULL); + mr_assert(drv != MR_NULL); + mr_assert(drv->ops != MR_NULL); + + /* Initialize the fields */ + serial->config = default_config; + mr_ringbuf_init(&serial->rd_fifo, MR_NULL, 0); + mr_ringbuf_init(&serial->wr_fifo, MR_NULL, 0); +#ifndef MR_CFG_SERIAL_RD_BUFSZ +#define MR_CFG_SERIAL_RD_BUFSZ (0) +#endif /* MR_CFG_SERIAL_RD_BUFSZ */ +#ifndef MR_CFG_SERIAL_WR_BUFSZ +#define MR_CFG_SERIAL_WR_BUFSZ (0) +#endif /* MR_CFG_SERIAL_WR_BUFSZ */ + serial->rd_bufsz = MR_CFG_SERIAL_RD_BUFSZ; + serial->wr_bufsz = MR_CFG_SERIAL_WR_BUFSZ; + + /* Register the serial */ + return mr_dev_register(&serial->dev, name, Mr_Dev_Type_Serial, MR_SFLAG_RDWR | MR_SFLAG_NONBLOCK, &ops, drv); +} + +#endif /* MR_USING_SERIAL */ diff --git a/device/uart.c b/device/uart.c deleted file mode 100644 index ac05229..0000000 --- a/device/uart.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * @copyright (c) 2023, MR Development Team - * - * @license SPDX-License-Identifier: Apache-2.0 - * - * @date 2023-10-20 MacRsh First version - */ - -#include "include/device/uart.h" - -#ifdef MR_USING_UART - -static int mr_uart_open(struct mr_dev *dev) -{ - struct mr_uart *uart = (struct mr_uart *)dev; - struct mr_uart_ops *ops = (struct mr_uart_ops *)dev->drv->ops; - - /* Allocate FIFO buffers */ - int ret = mr_ringbuf_allocate(&uart->rd_fifo, uart->rd_bufsz); - if (ret != MR_EOK) - { - return ret; - } - ret = mr_ringbuf_allocate(&uart->wr_fifo, uart->wr_bufsz); - if (ret != MR_EOK) - { - return ret; - } - - return ops->configure(uart, &uart->config); -} - -static int mr_uart_close(struct mr_dev *dev) -{ - struct mr_uart *uart = (struct mr_uart *)dev; - struct mr_uart_ops *ops = (struct mr_uart_ops *)dev->drv->ops; - struct mr_uart_config close_config = {0}; - - /* Free FIFO buffers */ - mr_ringbuf_free(&uart->rd_fifo); - mr_ringbuf_free(&uart->wr_fifo); - - return ops->configure(uart, &close_config); -} - -static ssize_t mr_uart_read(struct mr_dev *dev, int off, void *buf, size_t size, int sync_or_async) -{ - struct mr_uart *uart = (struct mr_uart *)dev; - struct mr_uart_ops *ops = (struct mr_uart_ops *)dev->drv->ops; - - if (mr_ringbuf_get_bufsz(&uart->rd_fifo) == 0) - { - return (ssize_t)ops->read(uart, buf, size); - } else - { - return (ssize_t)mr_ringbuf_read(&uart->rd_fifo, buf, size); - } -} - -static ssize_t mr_uart_write(struct mr_dev *dev, int off, const void *buf, size_t size, int sync_or_async) -{ - struct mr_uart *uart = (struct mr_uart *)dev; - struct mr_uart_ops *ops = (struct mr_uart_ops *)dev->drv->ops; - - if (sync_or_async == MR_SYNC) - { - return (ssize_t)ops->write(uart, buf, size); - } else - { - if (mr_ringbuf_get_bufsz(&uart->wr_fifo) == 0) - { - return (ssize_t)ops->write(uart, buf, size); - } else - { - ssize_t ret = (ssize_t)mr_ringbuf_write(&uart->wr_fifo, buf, size); - - /* Start interrupt sending */ - ops->start_tx(uart); - return ret; - } - } -} - -static int mr_uart_ioctl(struct mr_dev *dev, int off, int cmd, void *args) -{ - struct mr_uart *uart = (struct mr_uart *)dev; - struct mr_uart_ops *ops = (struct mr_uart_ops *)dev->drv->ops; - - switch (cmd) - { - case MR_CTRL_SET_CONFIG: - { - if (args != MR_NULL) - { - struct mr_uart_config config = *(struct mr_uart_config *)args; - - int ret = ops->configure(uart, &config); - if (ret == MR_EOK) - { - uart->config = config; - } - return ret; - } - return MR_EINVAL; - } - case MR_CTRL_SET_RD_BUFSZ: - { - if (args != MR_NULL) - { - size_t bufsz = *(size_t *)args; - - int ret = mr_ringbuf_allocate(&uart->rd_fifo, bufsz); - uart->rd_bufsz = 0; - if (ret == MR_EOK) - { - uart->rd_bufsz = bufsz; - } - return ret; - } - return MR_EINVAL; - } - case MR_CTRL_SET_WR_BUFSZ: - { - if (args != MR_NULL) - { - size_t bufsz = *(size_t *)args; - - int ret = mr_ringbuf_allocate(&uart->wr_fifo, bufsz); - uart->wr_bufsz = 0; - if (ret == MR_EOK) - { - uart->wr_bufsz = bufsz; - } - return ret; - } - return MR_EINVAL; - } - - case MR_CTRL_GET_CONFIG: - { - if (args != MR_NULL) - { - struct mr_uart_config *config = (struct mr_uart_config *)args; - - *config = uart->config; - return MR_EOK; - } - return MR_EINVAL; - } - case MR_CTRL_GET_RD_BUFSZ: - { - if (args != MR_NULL) - { - *(size_t *)args = uart->rd_bufsz; - return MR_EOK; - } - return MR_EINVAL; - } - case MR_CTRL_GET_WR_BUFSZ: - { - if (args != MR_NULL) - { - *(size_t *)args = uart->wr_bufsz; - return MR_EOK; - } - return MR_EINVAL; - } - - default: - { - return MR_ENOTSUP; - } - } -} - -static ssize_t mr_uart_isr(struct mr_dev *dev, int event, void *args) -{ - struct mr_uart *uart = (struct mr_uart *)dev; - struct mr_uart_ops *ops = (struct mr_uart_ops *)dev->drv->ops; - - switch (event) - { - case MR_ISR_EVENT_RD_INTER: - { - uint8_t data = 0; - - ops->read(uart, &data, sizeof(data)); - mr_ringbuf_push_force(&uart->rd_fifo, data); - return (ssize_t)mr_ringbuf_get_data_size(&uart->rd_fifo); - } - case MR_ISR_EVENT_WR_INTER: - { - uint8_t data = 0; - - if (mr_ringbuf_pop(&uart->wr_fifo, &data) == sizeof(data)) - { - ops->write(uart, &data, sizeof(data)); - } else - { - ops->stop_tx(uart); - } - return (ssize_t)mr_ringbuf_get_data_size(&uart->wr_fifo); - } - - default: - { - return MR_ENOTSUP; - } - } -} - -/** - * @brief This function register a uart. - * - * @param uart The uart. - * @param name The name of the uart. - * @param drv The driver of the uart. - * - * @return MR_EOK on success, otherwise an error code. - */ -int mr_uart_register(struct mr_uart *uart, const char *name, struct mr_drv *drv) -{ - static struct mr_dev_ops ops = - { - mr_uart_open, - mr_uart_close, - mr_uart_read, - mr_uart_write, - mr_uart_ioctl, - mr_uart_isr - }; - struct mr_uart_config default_config = MR_UART_CONFIG_DEFAULT; - - mr_assert(uart != MR_NULL); - mr_assert(name != MR_NULL); - mr_assert(drv != MR_NULL); - mr_assert(drv->ops != MR_NULL); - - /* Initialize the fields */ - uart->config = default_config; - mr_ringbuf_init(&uart->rd_fifo, MR_NULL, 0); - mr_ringbuf_init(&uart->wr_fifo, MR_NULL, 0); -#ifndef MR_CFG_UART_RD_BUFSZ_INIT -#define MR_CFG_UART_RD_BUFSZ_INIT (0) -#endif /* MR_CFG_UART_RD_BUFSZ_INIT */ -#ifndef MR_CFG_UART_WR_BUFSZ_INIT -#define MR_CFG_UART_WR_BUFSZ_INIT (0) -#endif /* MR_CFG_UART_WR_BUFSZ_INIT */ - uart->rd_bufsz = MR_CFG_UART_RD_BUFSZ_INIT; - uart->wr_bufsz = MR_CFG_UART_WR_BUFSZ_INIT; - - /* Register the uart */ - return mr_dev_register(&uart->dev, name, Mr_Dev_Type_Uart, MR_SFLAG_RDWR | MR_SFLAG_NONBLOCK, &ops, drv); -} - -#endif /* MR_USING_UART */ diff --git a/include/device/serial.h b/include/device/serial.h new file mode 100644 index 0000000..8f60644 --- /dev/null +++ b/include/device/serial.h @@ -0,0 +1,120 @@ +/* + * @copyright (c) 2023, MR Development Team + * + * @license SPDX-License-Identifier: Apache-2.0 + * + * @date 2023-10-20 MacRsh First version + */ + +#ifndef _MR_SERIAL_H_ +#define _MR_SERIAL_H_ + +#include "mr_api.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef MR_USING_SERIAL + +/** + * @brief SERIAL data bits. + */ +#define MR_SERIAL_DATA_BITS_5 (5) /**< 5 bits data */ +#define MR_SERIAL_DATA_BITS_6 (6) /**< 6 bits data */ +#define MR_SERIAL_DATA_BITS_7 (7) /**< 7 bits data */ +#define MR_SERIAL_DATA_BITS_8 (8) /**< 8 bits data */ + +/** + * @brief SERIAL stop bits. + */ +#define MR_SERIAL_STOP_BITS_1 (1) /**< 1 bit stop */ +#define MR_SERIAL_STOP_BITS_2 (2) /**< 2 bit stop */ +#define MR_SERIAL_STOP_BITS_3 (3) /**< 3 bit stop */ +#define MR_SERIAL_STOP_BITS_4 (4) /**< 4 bit stop */ + +/** + * @brief SERIAL parity. + */ +#define MR_SERIAL_PARITY_NONE (0) /**< No parity */ +#define MR_SERIAL_PARITY_EVEN (1) /**< Even parity */ +#define MR_SERIAL_PARITY_ODD (2) /**< Odd parity */ + +/** + * @brief SERIAL bit order. + */ +#define MR_SERIAL_BIT_ORDER_LSB (0) /**< LSB first */ +#define MR_SERIAL_BIT_ORDER_MSB (1) /**< MSB first */ + +/** + * @brief SERIAL polarity. + */ +#define MR_SERIAL_NRZ_NORMAL (0) /**< Normal polarity */ +#define MR_SERIAL_NRZ_INVERTED (1) /**< Inverted polarity */ + +/** + * @brief SERIAL default configuration. + */ +#define MR_SERIAL_CONFIG_DEFAULT \ +{ \ + 115200, \ + MR_SERIAL_DATA_BITS_8, \ + MR_SERIAL_STOP_BITS_1, \ + MR_SERIAL_PARITY_NONE, \ + MR_SERIAL_BIT_ORDER_LSB, \ + MR_SERIAL_NRZ_NORMAL, \ +} + +/** + * @brief SERIAL configuration structure. + */ +struct mr_serial_config +{ + uint32_t baud_rate; /**< Baud rate */ + uint32_t data_bits: 4; /**< Data bits */ + uint32_t stop_bits: 3; /**< Stop bits */ + uint32_t parity: 2; /**< Parity */ + uint32_t bit_order: 1; /**< Bit order */ + uint32_t invert: 1; /**< Invert */ + uint32_t reserved: 21; +}; + +/** + * @brief SERIAL structure. + */ +struct mr_serial +{ + struct mr_dev dev; /**< Device structure */ + + struct mr_serial_config config; /**< Configuration */ + struct mr_ringbuf rd_fifo; /**< Read FIFO */ + struct mr_ringbuf wr_fifo; /**< Write FIFO */ + size_t rd_bufsz; /**< Read buffer size */ + size_t wr_bufsz; /**< Write buffer size */ +}; + +/** + * @brief SERIAL operations structure. + */ +struct mr_serial_ops +{ + int (*configure)(struct mr_serial *serial, struct mr_serial_config *config); + ssize_t (*read)(struct mr_serial *serial, uint8_t *buf, size_t size); + ssize_t (*write)(struct mr_serial *serial, const uint8_t *buf, size_t size); + void (*start_tx)(struct mr_serial *serial); + void (*stop_tx)(struct mr_serial *serial); +}; + +/** + * @addtogroup SERIAL. + * @{ + */ +int mr_serial_register(struct mr_serial *serial, const char *name, struct mr_drv *drv); +/** @} */ +#endif /* MR_USING_SERIAL */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _MR_SERIAL_H_ */ diff --git a/include/device/uart.h b/include/device/uart.h deleted file mode 100644 index 70859f3..0000000 --- a/include/device/uart.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * @copyright (c) 2023, MR Development Team - * - * @license SPDX-License-Identifier: Apache-2.0 - * - * @date 2023-10-20 MacRsh First version - */ - -#ifndef _MR_UART_H_ -#define _MR_UART_H_ - -#include "mr_api.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifdef MR_USING_UART - -/** - * @brief UART data bits. - */ -#define MR_UART_DATA_BITS_5 (5) /**< 5 bits data */ -#define MR_UART_DATA_BITS_6 (6) /**< 6 bits data */ -#define MR_UART_DATA_BITS_7 (7) /**< 7 bits data */ -#define MR_UART_DATA_BITS_8 (8) /**< 8 bits data */ -#define MR_UART_DATA_BITS_9 (9) /**< 9 bits data */ - -/** - * @brief UART stop bits. - */ -#define MR_UART_STOP_BITS_1 (1) /**< 1 bit stop */ -#define MR_UART_STOP_BITS_2 (2) /**< 2 bit stop */ -#define MR_UART_STOP_BITS_3 (3) /**< 3 bit stop */ -#define MR_UART_STOP_BITS_4 (4) /**< 4 bit stop */ - -/** - * @brief UART parity. - */ -#define MR_UART_PARITY_NONE (0) /**< No parity */ -#define MR_UART_PARITY_EVEN (1) /**< Even parity */ -#define MR_UART_PARITY_ODD (2) /**< Odd parity */ - -/** - * @brief UART bit order. - */ -#define MR_UART_BIT_ORDER_LSB (0) /**< LSB first */ -#define MR_UART_BIT_ORDER_MSB (1) /**< MSB first */ - -/** - * @brief UART polarity. - */ -#define MR_UART_NRZ_NORMAL (0) /**< Normal polarity */ -#define MR_UART_NRZ_INVERTED (1) /**< Inverted polarity */ - -/** - * @brief UART default configuration. - */ -#define MR_UART_CONFIG_DEFAULT \ -{ \ - 115200, \ - MR_UART_DATA_BITS_8, \ - MR_UART_STOP_BITS_1, \ - MR_UART_PARITY_NONE, \ - MR_UART_BIT_ORDER_LSB, \ - MR_UART_NRZ_NORMAL, \ -} - -/** - * @brief UART configuration structure. - */ -struct mr_uart_config -{ - uint32_t baud_rate; /**< Baud rate */ - uint32_t data_bits: 4; /**< Data bits */ - uint32_t stop_bits: 3; /**< Stop bits */ - uint32_t parity: 2; /**< Parity */ - uint32_t bit_order: 1; /**< Bit order */ - uint32_t invert: 1; /**< Invert */ - uint32_t reserved: 21; -}; - -/** - * @brief UART structure. - */ -struct mr_uart -{ - struct mr_dev dev; /**< Device structure */ - - struct mr_uart_config config; /**< Configuration */ - struct mr_ringbuf rd_fifo; /**< Read FIFO */ - struct mr_ringbuf wr_fifo; /**< Write FIFO */ - size_t rd_bufsz; /**< Read buffer size */ - size_t wr_bufsz; /**< Write buffer size */ -}; - -/** - * @brief UART operations structure. - */ -struct mr_uart_ops -{ - int (*configure)(struct mr_uart *uart, struct mr_uart_config *config); - ssize_t (*read)(struct mr_uart *uart, uint8_t *buf, size_t size); - ssize_t (*write)(struct mr_uart *uart, const uint8_t *buf, size_t size); - void (*start_tx)(struct mr_uart *uart); - void (*stop_tx)(struct mr_uart *uart); -}; - -/** - * @addtogroup UART. - * @{ - */ -int mr_uart_register(struct mr_uart *uart, const char *name, struct mr_drv *drv); -/** @} */ -#endif /* MR_USING_UART */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _MR_UART_H_ */