Change in osmo-ccid-firmware[master]: add async library with ring on TX

Kévin Redon gerrit-no-reply at lists.osmocom.org
Tue Apr 16 23:29:21 UTC 2019


Kévin Redon has uploaded this change for review. ( https://gerrit.osmocom.org/13677


Change subject: add async library with ring on TX
......................................................................

add async library with ring on TX

the standard async library expected the caller to wait until the
transmission was complete (by counting using the transmit callback
or checking using usart_async_get_status) before freeing/reusing
the memory holding the data to be transmitted.
this is not practical when using stdio on top of the peripheral
since printf returns directly and reuses the memory.
the new USART async library has a ring buffer for the data to be
transmitted (similar to the data being received).

WARNING: the ring buffer library overwrites old data when the
buffer size is exceeded. We do not prevent this since don't want
to block. To prevent this behaviour, provide a large enough buffer
of check the buffer status yourself using usart_async_get_status.

Change-Id: Iafd5295b90ef9f428f640314c24f6c31ee82c9d6
---
M sysmoOCTSIM/gcc/Makefile
A sysmoOCTSIM/hal/include/hal_usart_async_rings.h
A sysmoOCTSIM/hal/src/hal_usart_async_rings.c
3 files changed, 767 insertions(+), 0 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-ccid-firmware refs/changes/77/13677/1

diff --git a/sysmoOCTSIM/gcc/Makefile b/sysmoOCTSIM/gcc/Makefile
index bd4bdb0..046970f 100644
--- a/sysmoOCTSIM/gcc/Makefile
+++ b/sysmoOCTSIM/gcc/Makefile
@@ -84,6 +84,7 @@
 hpl/osc32kctrl/hpl_osc32kctrl.o \
 driver_init.o \
 hal/src/hal_usart_async.o \
+hal/src/hal_usart_async_rings.o \
 hpl/sercom/hpl_sercom.o \
 hal/utils/src/utils_ringbuffer.o \
 main.o \
@@ -131,6 +132,7 @@
 "hpl/osc32kctrl/hpl_osc32kctrl.o" \
 "driver_init.o" \
 "hal/src/hal_usart_async.o" \
+"hal/src/hal_usart_async_rings.o" \
 "hpl/sercom/hpl_sercom.o" \
 "hal/utils/src/utils_ringbuffer.o" \
 "main.o" \
@@ -177,6 +179,7 @@
 "driver_init.d" \
 "stdio_redirect/gcc/read.d" \
 "hal/src/hal_usart_async.d" \
+"hal/src/hal_usart_async_rings.d" \
 "hpl/osc32kctrl/hpl_osc32kctrl.d" \
 "i2c_bitbang.d" \
 "octsim_i2c.d" \
diff --git a/sysmoOCTSIM/hal/include/hal_usart_async_rings.h b/sysmoOCTSIM/hal/include/hal_usart_async_rings.h
new file mode 100644
index 0000000..c66e21c
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hal_usart_async_rings.h
@@ -0,0 +1,341 @@
+/**
+ * \file
+ *
+ * \brief USART related functionality declaration.
+ *
+ * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
+ * Copyright (C) 2019 sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon at sysmocom.de>
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef _HAL_USART_ASYNC_RINGS_H_INCLUDED
+#define _HAL_USART_ASYNC_RINGS_H_INCLUDED
+
+#include "hal_io.h"
+#include <hpl_usart_async.h>
+#include <utils_ringbuffer.h>
+
+/**
+ * \addtogroup doc_driver_hal_usart_async
+ *
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief USART descriptor
+ *
+ * The USART descriptor forward declaration.
+ */
+struct usart_async_rings_descriptor;
+
+/**
+ * \brief USART callback type
+ */
+typedef void (*usart_rings_cb_t)(const struct usart_async_rings_descriptor *const descr);
+
+/**
+ * \brief USART callback types
+ */
+enum usart_async_rings_callback_type { USART_ASYNC_RINGS_RXC_CB, USART_ASYNC_RINGS_TXC_CB, USART_ASYNC_RINGS_ERROR_CB };
+
+/**
+ * \brief USART callbacks
+ */
+struct usart_async_rings_callbacks {
+	usart_rings_cb_t tx_done;
+	usart_rings_cb_t rx_done;
+	usart_rings_cb_t error;
+};
+
+/** \brief USART status
+ *  Status descriptor holds the current status of transfer.
+ */
+struct usart_async_rings_status {
+	/** Status flags */
+	uint32_t flags;
+	/** Number of characters transmitted */
+	uint16_t txcnt;
+	/** Number of characters receviced */
+	uint16_t rxcnt;
+};
+
+/**
+ * \brief Asynchronous USART descriptor structure
+ */
+struct usart_async_rings_descriptor {
+	struct io_descriptor         io;
+	struct _usart_async_device   device;
+	struct usart_async_rings_callbacks usart_cb;
+	uint32_t                     stat;
+
+	struct ringbuffer rx;
+	struct ringbuffer tx;
+};
+
+/** USART write busy */
+#define USART_ASYNC_RINGS_STATUS_BUSY 0x0001
+
+/**
+ * \brief Initialize USART interface
+ *
+ * This function initializes the given I/O descriptor to be used as USART
+ * interface descriptor.
+ * It checks if the given hardware is not initialized and if the given hardware
+ * is permitted to be initialized.
+ *
+ * \param[out] descr A USART descriptor which is used to communicate via the USART
+ * \param[in] hw The pointer to the hardware instance
+ * \param[in] rx_buffer An RX buffer
+ * \param[in] rx_buffer_length The length of the buffer above
+ * \param[in] tx_buffer An TX buffer
+ * \param[in] tx_buffer_length The length of the buffer above
+ * \param[in] func The pointer to a set of function pointers
+ *
+ * \return Initialization status.
+ * \retval -1 Passed parameters were invalid or the interface is already
+ * initialized
+ * \retval 0 The initialization is completed successfully
+ */
+int32_t usart_async_rings_init(struct usart_async_rings_descriptor *const descr, void *const hw, uint8_t *const rx_buffer,
+                         const uint16_t rx_buffer_length, uint8_t *const tx_buffer,
+                         const uint16_t tx_buffer_length, void *const func);
+
+/**
+ * \brief Deinitialize USART interface
+ *
+ * This function deinitializes the given I/O descriptor.
+ * It checks if the given hardware is initialized and if the given hardware
+ * is permitted to be deinitialized.
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ *
+ * \return De-initialization status.
+ */
+int32_t usart_async_rings_deinit(struct usart_async_rings_descriptor *const descr);
+
+/**
+ * \brief Enable USART interface
+ *
+ * Enables the USART interface
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ *
+ * \return Enabling status.
+ */
+int32_t usart_async_rings_enable(struct usart_async_rings_descriptor *const descr);
+
+/**
+ * \brief Disable USART interface
+ *
+ * Disables the USART interface
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ *
+ * \return Disabling status.
+ */
+int32_t usart_async_rings_disable(struct usart_async_rings_descriptor *const descr);
+
+/**
+ * \brief Retrieve I/O descriptor
+ *
+ * This function retrieves the I/O descriptor of the given USART descriptor.
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ * \param[out] io An I/O descriptor to retrieve
+ *
+ * \return The status of I/O descriptor retrieving.
+ */
+int32_t usart_async_rings_get_io_descriptor(struct usart_async_rings_descriptor *const descr, struct io_descriptor **io);
+
+/**
+ * \brief Register USART callback
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ * \param[in] type Callback type
+ * \param[in] cb A callback function
+ *
+ * \return The status of callback assignment.
+ * \retval -1 Passed parameters were invalid or the interface is not initialized
+ * \retval 0 A callback is registered successfully
+ */
+int32_t usart_async_rings_register_callback(struct usart_async_rings_descriptor *const descr,
+                                      const enum usart_async_rings_callback_type type, usart_rings_cb_t cb);
+
+/**
+ * \brief Specify action for flow control pins
+ *
+ * This function sets action (or state) for flow control pins if
+ * the flow control is enabled.
+ * It sets state of flow control pins only if automatic support of
+ * the flow control is not supported by the hardware.
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ * \param[in] state A state to set the flow control pins
+ *
+ * \return The status of flow control action setup.
+ */
+int32_t usart_async_rings_set_flow_control(struct usart_async_rings_descriptor *const descr,
+                                     const union usart_flow_control_state state);
+
+/**
+ * \brief Set USART baud rate
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ * \param[in] baud_rate A baud rate to set
+ *
+ * \return The status of baud rate setting.
+ */
+int32_t usart_async_rings_set_baud_rate(struct usart_async_rings_descriptor *const descr, const uint32_t baud_rate);
+
+/**
+ * \brief Set USART data order
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ * \param[in] data_order A data order to set
+ *
+ * \return The status of data order setting.
+ */
+int32_t usart_async_rings_set_data_order(struct usart_async_rings_descriptor *const descr, const enum usart_data_order data_order);
+
+/**
+ * \brief Set USART mode
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ * \param[in] mode A mode to set
+ *
+ * \return The status of mode setting.
+ */
+int32_t usart_async_rings_set_mode(struct usart_async_rings_descriptor *const descr, const enum usart_mode mode);
+
+/**
+ * \brief Set USART parity
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ * \param[in] parity A parity to set
+ *
+ * \return The status of parity setting.
+ */
+int32_t usart_async_rings_set_parity(struct usart_async_rings_descriptor *const descr, const enum usart_parity parity);
+
+/**
+ * \brief Set USART stop bits
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ * \param[in] stop_bits Stop bits to set
+ *
+ * \return The status of stop bits setting.
+ */
+int32_t usart_async_rings_set_stopbits(struct usart_async_rings_descriptor *const descr, const enum usart_stop_bits stop_bits);
+
+/**
+ * \brief Set USART character size
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ * \param[in] size A character size to set
+ *
+ * \return The status of character size setting.
+ */
+int32_t usart_async_rings_set_character_size(struct usart_async_rings_descriptor *const descr,
+                                       const enum usart_character_size      size);
+
+/**
+ * \brief Retrieve the state of flow control pins
+ *
+ * This function retrieves the flow control pins
+ * if the flow control is enabled.
+ *
+ * The function can return USART_FLOW_CONTROL_STATE_UNAVAILABLE in case
+ * if the flow control is done by the hardware
+ * and the pins state cannot be read out.
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ * \param[out] state The state of flow control pins
+ *
+ * \return The status of flow control state reading.
+ */
+int32_t usart_async_rings_flow_control_status(const struct usart_async_rings_descriptor *const descr,
+                                        union usart_flow_control_state *const      state);
+
+/**
+ * \brief Check if the USART transmitter is empty
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ *
+ * \return The status of USART TX empty checking.
+ * \retval 0 The USART transmitter is not empty
+ * \retval 1 The USART transmitter is empty
+ */
+int32_t usart_async_rings_is_tx_empty(const struct usart_async_rings_descriptor *const descr);
+
+/**
+ * \brief Check if the USART receiver is not empty
+ *
+ * \param[in] descr A USART descriptor which is used to communicate via USART
+ *
+ * \return The status of the USART RX empty checking.
+ * \retval 1 The USART receiver is not empty
+ * \retval 0 The USART receiver is empty
+ */
+int32_t usart_async_rings_is_rx_not_empty(const struct usart_async_rings_descriptor *const descr);
+
+/**
+ * \brief Retrieve the current interface status
+ *
+ * \param[in]  descr A USART descriptor which is used to communicate via USART
+ * \param[out] status The state of USART
+ *
+ * \return The status of USART status retrieving.
+ */
+int32_t usart_async_rings_get_status(struct usart_async_rings_descriptor *const descr, struct usart_async_rings_status *const status);
+
+/**
+ * \brief flush USART ringbuf
+ *
+ * This function flush USART RX ringbuf.
+ *
+ * \param[in] descr The pointer to USART descriptor
+ *
+ * \return ERR_NONE
+ */
+int32_t usart_async_rings_flush_rx_buffer(struct usart_async_rings_descriptor *const descr);
+
+/**
+ * \brief Retrieve the current driver version
+ *
+ * \return Current driver version.
+ */
+uint32_t usart_async_rings_get_version(void);
+
+#ifdef __cplusplus
+}
+#endif
+/**@}*/
+#endif /* _HAL_USART_ASYNC_RINGS_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/src/hal_usart_async_rings.c b/sysmoOCTSIM/hal/src/hal_usart_async_rings.c
new file mode 100644
index 0000000..578d945
--- /dev/null
+++ b/sysmoOCTSIM/hal/src/hal_usart_async_rings.c
@@ -0,0 +1,423 @@
+/**
+ * \file
+ *
+ * \brief I/O USART related functionality implementation.
+ *
+ * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
+ * Copyright (C) 2019 sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon at sysmocom.de>
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#include "hal_usart_async_rings.h"
+#include <utils_assert.h>
+#include <hal_atomic.h>
+#include <utils.h>
+
+/**
+ * \brief Driver version
+ */
+#define DRIVER_VERSION 0x00000001u
+
+static int32_t usart_async_rings_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length);
+static int32_t usart_async_rings_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length);
+static void    usart_process_byte_sent(struct _usart_async_device *device);
+static void    usart_transmission_complete(struct _usart_async_device *device);
+static void    usart_error(struct _usart_async_device *device);
+static void    usart_fill_rx_buffer(struct _usart_async_device *device, uint8_t data);
+
+/**
+ * \brief Initialize usart interface
+ */
+int32_t usart_async_rings_init(struct usart_async_rings_descriptor *const descr, void *const hw, uint8_t *const rx_buffer,
+                         const uint16_t rx_buffer_length, uint8_t *const tx_buffer,
+                         const uint16_t tx_buffer_length, void *const func)
+{
+	int32_t init_status;
+	ASSERT(descr && hw && rx_buffer && rx_buffer_length && tx_buffer && tx_buffer_length);
+
+	if (ERR_NONE != ringbuffer_init(&descr->rx, rx_buffer, rx_buffer_length)) {
+		return ERR_INVALID_ARG;
+	}
+	if (ERR_NONE != ringbuffer_init(&descr->tx, tx_buffer, tx_buffer_length)) {
+		return ERR_INVALID_ARG;
+	}
+	init_status = _usart_async_init(&descr->device, hw);
+	if (init_status) {
+		return init_status;
+	}
+
+	descr->io.read  = usart_async_rings_read;
+	descr->io.write = usart_async_rings_write;
+
+	descr->device.usart_cb.tx_byte_sent = usart_process_byte_sent;
+	descr->device.usart_cb.rx_done_cb   = usart_fill_rx_buffer;
+	descr->device.usart_cb.tx_done_cb   = usart_transmission_complete;
+	descr->device.usart_cb.error_cb     = usart_error;
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Deinitialize usart interface
+ */
+int32_t usart_async_rings_deinit(struct usart_async_rings_descriptor *const descr)
+{
+	ASSERT(descr);
+	_usart_async_deinit(&descr->device);
+	descr->io.read  = NULL;
+	descr->io.write = NULL;
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Enable usart interface
+ */
+int32_t usart_async_rings_enable(struct usart_async_rings_descriptor *const descr)
+{
+	ASSERT(descr);
+	_usart_async_enable(&descr->device);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Disable usart interface
+ */
+int32_t usart_async_rings_disable(struct usart_async_rings_descriptor *const descr)
+{
+	ASSERT(descr);
+	_usart_async_disable(&descr->device);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Retrieve I/O descriptor
+ */
+int32_t usart_async_rings_get_io_descriptor(struct usart_async_rings_descriptor *const descr, struct io_descriptor **io)
+{
+	ASSERT(descr && io);
+
+	*io = &descr->io;
+	return ERR_NONE;
+}
+
+/**
+ * \brief Register usart callback
+ */
+int32_t usart_async_rings_register_callback(struct usart_async_rings_descriptor *const descr,
+                                      const enum usart_async_rings_callback_type type, usart_rings_cb_t cb)
+{
+	ASSERT(descr);
+
+	switch (type) {
+	case USART_ASYNC_RINGS_RXC_CB:
+		descr->usart_cb.rx_done = cb;
+		_usart_async_set_irq_state(&descr->device, USART_ASYNC_RX_DONE, NULL != cb);
+		break;
+	case USART_ASYNC_RINGS_TXC_CB:
+		descr->usart_cb.tx_done = cb;
+		_usart_async_set_irq_state(&descr->device, USART_ASYNC_TX_DONE, NULL != cb);
+		break;
+	case USART_ASYNC_RINGS_ERROR_CB:
+		descr->usart_cb.error = cb;
+		_usart_async_set_irq_state(&descr->device, USART_ASYNC_ERROR, NULL != cb);
+		break;
+	default:
+		return ERR_INVALID_ARG;
+	}
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Specify action for flow control pins
+ */
+int32_t usart_async_rings_set_flow_control(struct usart_async_rings_descriptor *const descr,
+                                     const union usart_flow_control_state state)
+{
+	ASSERT(descr);
+	_usart_async_set_flow_control_state(&descr->device, state);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set usart baud rate
+ */
+int32_t usart_async_rings_set_baud_rate(struct usart_async_rings_descriptor *const descr, const uint32_t baud_rate)
+{
+	ASSERT(descr);
+	_usart_async_set_baud_rate(&descr->device, baud_rate);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set usart data order
+ */
+int32_t usart_async_rings_set_data_order(struct usart_async_rings_descriptor *const descr, const enum usart_data_order data_order)
+{
+	ASSERT(descr);
+	_usart_async_set_data_order(&descr->device, data_order);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set usart mode
+ */
+int32_t usart_async_rings_set_mode(struct usart_async_rings_descriptor *const descr, const enum usart_mode mode)
+{
+	ASSERT(descr);
+	_usart_async_set_mode(&descr->device, mode);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set usart parity
+ */
+int32_t usart_async_rings_set_parity(struct usart_async_rings_descriptor *const descr, const enum usart_parity parity)
+{
+	ASSERT(descr);
+	_usart_async_set_parity(&descr->device, parity);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set usart stop bits
+ */
+int32_t usart_async_rings_set_stopbits(struct usart_async_rings_descriptor *const descr, const enum usart_stop_bits stop_bits)
+{
+	ASSERT(descr);
+	_usart_async_set_stop_bits(&descr->device, stop_bits);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set usart character size
+ */
+int32_t usart_async_rings_set_character_size(struct usart_async_rings_descriptor *const descr, const enum usart_character_size size)
+{
+	ASSERT(descr);
+	_usart_async_set_character_size(&descr->device, size);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Retrieve the state of flow control pins
+ */
+int32_t usart_async_rings_flow_control_status(const struct usart_async_rings_descriptor *const descr,
+                                        union usart_flow_control_state *const      state)
+{
+	ASSERT(descr && state);
+	*state = _usart_async_get_flow_control_state(&descr->device);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Check if the usart transmitter is empty
+ */
+int32_t usart_async_rings_is_tx_empty(const struct usart_async_rings_descriptor *const descr)
+{
+	ASSERT(descr);
+	return _usart_async_is_byte_sent(&descr->device);
+}
+
+/**
+ * \brief Check if the usart receiver is not empty
+ */
+int32_t usart_async_rings_is_rx_not_empty(const struct usart_async_rings_descriptor *const descr)
+{
+	ASSERT(descr);
+
+	return ringbuffer_num(&descr->rx) > 0;
+}
+
+/**
+ * \brief Retrieve the current interface status
+ */
+int32_t usart_async_rings_get_status(struct usart_async_rings_descriptor *const descr, struct usart_async_rings_status *const status)
+{
+	ASSERT(descr);
+
+	volatile uint32_t *tmp_stat  = &(descr->stat);
+
+	if (status) {
+		status->flags = *tmp_stat;
+		status->txcnt = ringbuffer_num(&descr->tx);
+		status->rxcnt = ringbuffer_num(&descr->rx);
+	}
+	if (*tmp_stat & USART_ASYNC_RINGS_STATUS_BUSY) {
+		return ERR_BUSY;
+	}
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief flush usart rx ringbuf
+ */
+int32_t usart_async_rings_flush_rx_buffer(struct usart_async_rings_descriptor *const descr)
+{
+	ASSERT(descr);
+
+	return ringbuffer_flush(&descr->rx);
+}
+
+/**
+ * \brief Retrieve the current driver version
+ */
+uint32_t usart_async_rings_get_version(void)
+{
+	return DRIVER_VERSION;
+}
+
+/*
+ * \internal Write the given data to usart interface
+ *
+ * \param[in] descr The pointer to an io descriptor
+ * \param[in] buf Data to write to usart
+ * \param[in] length The number of bytes to write
+ *
+ * \return The number of bytes written.
+ */
+static int32_t usart_async_rings_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length)
+{
+	struct usart_async_rings_descriptor *descr = CONTAINER_OF(io_descr, struct usart_async_rings_descriptor, io);
+
+	ASSERT(descr && buf && length);
+
+	for (uint16_t i = 0; i < length; i++) {
+		ringbuffer_put(&descr->tx, buf[i]);
+	}
+	descr->stat             = USART_ASYNC_RINGS_STATUS_BUSY;
+	_usart_async_enable_byte_sent_irq(&descr->device);
+
+	return (int32_t)length;
+}
+
+/*
+ * \internal Read data from usart interface
+ *
+ * \param[in] descr The pointer to an io descriptor
+ * \param[in] buf A buffer to read data to
+ * \param[in] length The size of a buffer
+ *
+ * \return The number of bytes read.
+ */
+static int32_t usart_async_rings_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length)
+{
+	uint16_t                       was_read = 0;
+	uint32_t                       num;
+	struct usart_async_rings_descriptor *descr = CONTAINER_OF(io_descr, struct usart_async_rings_descriptor, io);
+
+	ASSERT(descr && buf && length);
+
+	CRITICAL_SECTION_ENTER()
+	num = ringbuffer_num(&descr->rx);
+	CRITICAL_SECTION_LEAVE()
+
+	while ((was_read < num) && (was_read < length)) {
+		ringbuffer_get(&descr->rx, &buf[was_read++]);
+	}
+
+	return (int32_t)was_read;
+}
+
+/**
+ * \brief Process "byte is sent" interrupt
+ *
+ * \param[in] device The pointer to device structure
+ */
+static void usart_process_byte_sent(struct _usart_async_device *device)
+{
+	struct usart_async_rings_descriptor *descr = CONTAINER_OF(device, struct usart_async_rings_descriptor, device);
+	if (ringbuffer_num(&descr->tx)) {
+		uint8_t byte;
+		ringbuffer_get(&descr->tx, &byte);
+		_usart_async_write_byte(&descr->device, byte);
+		_usart_async_enable_byte_sent_irq(&descr->device);
+	} else {
+		_usart_async_enable_tx_done_irq(&descr->device);
+	}
+}
+
+/**
+ * \brief Process completion of data sending
+ *
+ * \param[in] device The pointer to device structure
+ */
+static void usart_transmission_complete(struct _usart_async_device *device)
+{
+	struct usart_async_rings_descriptor *descr = CONTAINER_OF(device, struct usart_async_rings_descriptor, device);
+
+	descr->stat = 0;
+	if (descr->usart_cb.tx_done) {
+		descr->usart_cb.tx_done(descr);
+	}
+}
+
+/**
+ * \brief Process byte reception
+ *
+ * \param[in] device The pointer to device structure
+ * \param[in] data Data read
+ */
+static void usart_fill_rx_buffer(struct _usart_async_device *device, uint8_t data)
+{
+	struct usart_async_rings_descriptor *descr = CONTAINER_OF(device, struct usart_async_rings_descriptor, device);
+
+	ringbuffer_put(&descr->rx, data);
+
+	if (descr->usart_cb.rx_done) {
+		descr->usart_cb.rx_done(descr);
+	}
+}
+
+/**
+ * \brief Process error interrupt
+ *
+ * \param[in] device The pointer to device structure
+ */
+static void usart_error(struct _usart_async_device *device)
+{
+	struct usart_async_rings_descriptor *descr = CONTAINER_OF(device, struct usart_async_rings_descriptor, device);
+
+	descr->stat = 0;
+	if (descr->usart_cb.error) {
+		descr->usart_cb.error(descr);
+	}
+}
+
+//@}

-- 
To view, visit https://gerrit.osmocom.org/13677
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ccid-firmware
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iafd5295b90ef9f428f640314c24f6c31ee82c9d6
Gerrit-Change-Number: 13677
Gerrit-PatchSet: 1
Gerrit-Owner: Kévin Redon <kredon at sysmocom.de>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190416/f2c783a8/attachment.html>


More information about the gerrit-log mailing list