Change in osmo-ccid-firmware[master]: add SERCOM HAL Async library

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Kévin Redon gerrit-no-reply at lists.osmocom.org
Sun Feb 3 13:47:41 UTC 2019


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


Change subject: add SERCOM HAL Async library
......................................................................

add SERCOM HAL Async library

Change-Id: I530a5bc5ee7e89149eb251bda0adf7963733d2ee
---
M sysmoOCTSIM/AtmelStart.gpdsc
M sysmoOCTSIM/atmel_start_config.atstart
M sysmoOCTSIM/driver_init.c
M sysmoOCTSIM/driver_init.h
M sysmoOCTSIM/examples/driver_examples.c
M sysmoOCTSIM/gcc/Makefile
A sysmoOCTSIM/hal/documentation/usart_async.rst
A sysmoOCTSIM/hal/include/hal_usart_async.h
A sysmoOCTSIM/hal/src/hal_usart_async.c
A sysmoOCTSIM/hal/utils/include/utils_ringbuffer.h
A sysmoOCTSIM/hal/utils/src/utils_ringbuffer.c
M sysmoOCTSIM/hpl/sercom/hpl_sercom.c
12 files changed, 1,207 insertions(+), 30 deletions(-)



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

diff --git a/sysmoOCTSIM/AtmelStart.gpdsc b/sysmoOCTSIM/AtmelStart.gpdsc
index 44b5c62..ebb4d1e 100644
--- a/sysmoOCTSIM/AtmelStart.gpdsc
+++ b/sysmoOCTSIM/AtmelStart.gpdsc
@@ -42,7 +42,7 @@
       <description>Atmel Start Framework</description>
       <RTE_Components_h>#define ATMEL_START</RTE_Components_h>
       <files>
-        <file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/usart_sync.rst"/>
+        <file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/usart_async.rst"/>
         <file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/usb_device_async.rst"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_atomic.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_cache.h"/>
@@ -94,9 +94,11 @@
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/utils_increment_macro.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/utils_list.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/utils_repeat_macro.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/utils_ringbuffer.h"/>
         <file category="source" condition="ARMCC, GCC, IAR" name="hal/utils/src/utils_assert.c"/>
         <file category="source" condition="ARMCC, GCC, IAR" name="hal/utils/src/utils_event.c"/>
         <file category="source" condition="ARMCC, GCC, IAR" name="hal/utils/src/utils_list.c"/>
+        <file category="source" condition="ARMCC, GCC, IAR" name="hal/utils/src/utils_ringbuffer.c"/>
         <file category="source" condition="GCC" name="hal/utils/src/utils_syscalls.c"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hri/hri_ac_e54.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hri/hri_adc_e54.h"/>
@@ -165,12 +167,12 @@
         <file category="header" condition="ARMCC, GCC, IAR" name="atmel_start_pins.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="examples/driver_examples.h"/>
         <file category="source" condition="ARMCC, GCC, IAR" name="examples/driver_examples.c"/>
-        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_usart_sync.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_usart_async.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_missing_features.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_reset.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_usart_async.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_usart_sync.h"/>
-        <file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_usart_sync.c"/>
+        <file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_usart_async.c"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/parts.h"/>
         <file category="source" condition="ARMCC, GCC, IAR" name="hpl/cmcc/hpl_cmcc.c"/>
         <file category="source" condition="ARMCC, GCC, IAR" name="hpl/core/hpl_core_m4.c"/>
diff --git a/sysmoOCTSIM/atmel_start_config.atstart b/sysmoOCTSIM/atmel_start_config.atstart
index cb7826a..af87e97 100644
--- a/sysmoOCTSIM/atmel_start_config.atstart
+++ b/sysmoOCTSIM/atmel_start_config.atstart
@@ -959,9 +959,9 @@
       domain_group: null
   UART_debug:
     user_label: UART_debug
-    definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::SERCOM2::driver_config_definition::UART::HAL:Driver:USART.Sync
+    definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::SERCOM2::driver_config_definition::UART::HAL:Driver:USART.Async
     functionality: USART
-    api: HAL:Driver:USART_Sync
+    api: HAL:Driver:USART_Async
     configuration:
       usart_advanced: false
       usart_arch_clock_mode: USART with internal clock
diff --git a/sysmoOCTSIM/driver_init.c b/sysmoOCTSIM/driver_init.c
index 72f2c88..efd24bc 100644
--- a/sysmoOCTSIM/driver_init.c
+++ b/sysmoOCTSIM/driver_init.c
@@ -11,9 +11,33 @@
 #include <utils.h>
 #include <hal_init.h>
 
-struct usart_sync_descriptor UART_debug;
+/*! The buffer size for USART */
+#define UART_DEBUG_BUFFER_SIZE 16
 
-void UART_debug_PORT_init(void)
+struct usart_async_descriptor UART_debug;
+
+static uint8_t UART_debug_buffer[UART_DEBUG_BUFFER_SIZE];
+
+/**
+ * \brief USART Clock initialization function
+ *
+ * Enables register interface and peripheral clock
+ */
+void UART_debug_CLOCK_init()
+{
+
+	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_CORE, CONF_GCLK_SERCOM2_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
+	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_SLOW, CONF_GCLK_SERCOM2_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
+
+	hri_mclk_set_APBBMASK_SERCOM2_bit(MCLK);
+}
+
+/**
+ * \brief USART pinmux initialization function
+ *
+ * Set each required pin to USART functionality
+ */
+void UART_debug_PORT_init()
 {
 
 	gpio_set_pin_function(PB25, PINMUX_PB25D_SERCOM2_PAD0);
@@ -21,18 +45,15 @@
 	gpio_set_pin_function(PB24, PINMUX_PB24D_SERCOM2_PAD1);
 }
 
-void UART_debug_CLOCK_init(void)
-{
-	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_CORE, CONF_GCLK_SERCOM2_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
-	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_SLOW, CONF_GCLK_SERCOM2_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
-
-	hri_mclk_set_APBBMASK_SERCOM2_bit(MCLK);
-}
-
+/**
+ * \brief USART initialization function
+ *
+ * Enables USART peripheral, clocks and initializes USART driver
+ */
 void UART_debug_init(void)
 {
 	UART_debug_CLOCK_init();
-	usart_sync_init(&UART_debug, SERCOM2, (void *)NULL);
+	usart_async_init(&UART_debug, SERCOM2, UART_debug_buffer, UART_DEBUG_BUFFER_SIZE, (void *)NULL);
 	UART_debug_PORT_init();
 }
 
diff --git a/sysmoOCTSIM/driver_init.h b/sysmoOCTSIM/driver_init.h
index 7067684..25e6370 100644
--- a/sysmoOCTSIM/driver_init.h
+++ b/sysmoOCTSIM/driver_init.h
@@ -21,11 +21,11 @@
 #include <hal_io.h>
 #include <hal_sleep.h>
 
-#include <hal_usart_sync.h>
+#include <hal_usart_async.h>
 
 #include "hal_usb_device.h"
 
-extern struct usart_sync_descriptor UART_debug;
+extern struct usart_async_descriptor UART_debug;
 
 void UART_debug_PORT_init(void);
 void UART_debug_CLOCK_init(void);
diff --git a/sysmoOCTSIM/examples/driver_examples.c b/sysmoOCTSIM/examples/driver_examples.c
index 56247ff..8384c87 100644
--- a/sysmoOCTSIM/examples/driver_examples.c
+++ b/sysmoOCTSIM/examples/driver_examples.c
@@ -12,12 +12,29 @@
 
 /**
  * Example of using UART_debug to write "Hello World" using the IO abstraction.
+ *
+ * Since the driver is asynchronous we need to use statically allocated memory for string
+ * because driver initiates transfer and then returns before the transmission is completed.
+ *
+ * Once transfer has been completed the tx_cb function will be called.
  */
+
+static uint8_t example_UART_debug[12] = "Hello World!";
+
+static void tx_cb_UART_debug(const struct usart_async_descriptor *const io_descr)
+{
+	/* Transfer completed */
+}
+
 void UART_debug_example(void)
 {
 	struct io_descriptor *io;
-	usart_sync_get_io_descriptor(&UART_debug, &io);
-	usart_sync_enable(&UART_debug);
 
-	io_write(io, (uint8_t *)"Hello World!", 12);
+	usart_async_register_callback(&UART_debug, USART_ASYNC_TXC_CB, tx_cb_UART_debug);
+	/*usart_async_register_callback(&UART_debug, USART_ASYNC_RXC_CB, rx_cb);
+	usart_async_register_callback(&UART_debug, USART_ASYNC_ERROR_CB, err_cb);*/
+	usart_async_get_io_descriptor(&UART_debug, &io);
+	usart_async_enable(&UART_debug);
+
+	io_write(io, example_UART_debug, 12);
 }
diff --git a/sysmoOCTSIM/gcc/Makefile b/sysmoOCTSIM/gcc/Makefile
index 57ec70c..ff11dd9 100644
--- a/sysmoOCTSIM/gcc/Makefile
+++ b/sysmoOCTSIM/gcc/Makefile
@@ -52,7 +52,7 @@
 hpl/core/hpl_core_m4.o \
 usb/class/cdc/device/cdcdf_acm.o \
 hal/utils/src/utils_syscalls.o \
-hpl/dmac/hpl_dmac.o \
+usb_start.o \
 gcc/system_same54.o \
 hpl/usb/hpl_usb.o \
 hal/src/hal_delay.o \
@@ -61,9 +61,8 @@
 hpl/gclk/hpl_gclk.o \
 hal/utils/src/utils_list.o \
 hal/utils/src/utils_assert.o \
-usb_start.o \
+hpl/dmac/hpl_dmac.o \
 hpl/oscctrl/hpl_oscctrl.o \
-hal/src/hal_usart_sync.o \
 hpl/mclk/hpl_mclk.o \
 hpl/ramecc/hpl_ramecc.o \
 usb/usb_protocol.o \
@@ -73,7 +72,9 @@
 hpl/osc32kctrl/hpl_osc32kctrl.o \
 examples/driver_examples.o \
 driver_init.o \
+hal/src/hal_usart_async.o \
 hpl/sercom/hpl_sercom.o \
+hal/utils/src/utils_ringbuffer.o \
 hal/src/hal_gpio.o \
 hal/utils/src/utils_event.o \
 hal/src/hal_sleep.o \
@@ -89,7 +90,7 @@
 "hpl/core/hpl_core_m4.o" \
 "usb/class/cdc/device/cdcdf_acm.o" \
 "hal/utils/src/utils_syscalls.o" \
-"hpl/dmac/hpl_dmac.o" \
+"usb_start.o" \
 "gcc/system_same54.o" \
 "hpl/usb/hpl_usb.o" \
 "hal/src/hal_delay.o" \
@@ -98,9 +99,8 @@
 "hpl/gclk/hpl_gclk.o" \
 "hal/utils/src/utils_list.o" \
 "hal/utils/src/utils_assert.o" \
-"usb_start.o" \
+"hpl/dmac/hpl_dmac.o" \
 "hpl/oscctrl/hpl_oscctrl.o" \
-"hal/src/hal_usart_sync.o" \
 "hpl/mclk/hpl_mclk.o" \
 "hpl/ramecc/hpl_ramecc.o" \
 "usb/usb_protocol.o" \
@@ -110,7 +110,9 @@
 "hpl/osc32kctrl/hpl_osc32kctrl.o" \
 "examples/driver_examples.o" \
 "driver_init.o" \
+"hal/src/hal_usart_async.o" \
 "hpl/sercom/hpl_sercom.o" \
+"hal/utils/src/utils_ringbuffer.o" \
 "hal/src/hal_gpio.o" \
 "hal/utils/src/utils_event.o" \
 "hal/src/hal_sleep.o" \
@@ -135,7 +137,7 @@
 "hpl/usb/hpl_usb.d" \
 "hal/utils/src/utils_list.d" \
 "hpl/cmcc/hpl_cmcc.d" \
-"usb_start.d" \
+"hpl/dmac/hpl_dmac.d" \
 "hal/utils/src/utils_assert.d" \
 "hal/src/hal_delay.d" \
 "hpl/core/hpl_init.d" \
@@ -143,16 +145,17 @@
 "usb/usb_protocol.d" \
 "hpl/gclk/hpl_gclk.d" \
 "hal/src/hal_usb_device.d" \
-"hpl/dmac/hpl_dmac.d" \
+"usb_start.d" \
 "hal/src/hal_init.d" \
-"hal/src/hal_usart_sync.d" \
 "main.d" \
 "hpl/mclk/hpl_mclk.d" \
 "driver_init.d" \
+"hal/src/hal_usart_async.d" \
 "hpl/osc32kctrl/hpl_osc32kctrl.d" \
 "examples/driver_examples.d" \
 "hal/src/hal_cache.d" \
 "hal/src/hal_sleep.d" \
+"hal/utils/src/utils_ringbuffer.d" \
 "hpl/sercom/hpl_sercom.d" \
 "hal/src/hal_gpio.d" \
 "hal/src/hal_atomic.d" \
diff --git a/sysmoOCTSIM/hal/documentation/usart_async.rst b/sysmoOCTSIM/hal/documentation/usart_async.rst
new file mode 100644
index 0000000..6bf4a23
--- /dev/null
+++ b/sysmoOCTSIM/hal/documentation/usart_async.rst
@@ -0,0 +1,72 @@
+The USART Asynchronous Driver
+=============================
+
+The universal synchronous and asynchronous receiver and transmitter
+(USART) is usually used to transfer data from one device to the other.
+
+The USART driver use a ring buffer to store received data. When the USART
+raise the data received interrupt, this data will be stored in the ring buffer
+at the next free location. When the ring buffer is full, the next reception
+will overwrite the oldest data stored in the ring buffer. There is one
+USART_BUFFER_SIZE macro per used hardware instance, e.g. for SERCOM0 the macro
+is called SERCOM0_USART_BUFFER_SIZE.
+
+On the other hand, when sending data over USART, the data is not copied to an
+internal buffer, but the data buffer supplied by the user is used. The callback
+will only be generated at the end of the buffer and not for each byte.
+
+User can set action for flow control pins by function usart_set_flow_control,
+if the flow control is enabled. All the available states are defined in union
+usart_flow_control_state.
+
+Note that user can set state of flow control pins only if automatic support of
+the flow control is not supported by the hardware.
+
+Features
+--------
+
+* Initialization/de-initialization
+* Enabling/disabling
+* Control of the following settings:
+
+  * Baudrate
+  * UART or USRT communication mode
+  * Character size
+  * Data order
+  * Flow control
+* Data transfer: transmission, reception
+* Notifications about transfer done or error case via callbacks
+* Status information with busy state and transfer count
+
+Applications
+------------
+
+They are commonly used in a terminal application or low-speed communication
+between devices.
+
+Dependencies
+------------
+
+USART capable hardware, with interrupt on each character is sent or
+received.
+
+Concurrency
+-----------
+
+Write buffer should not be changed while data is being sent.
+
+
+Limitations
+-----------
+
+* The driver does not support 9-bit character size.
+* The "USART with ISO7816" mode can be only used in ISO7816 capable devices. 
+  And the SCK pin can't be set directly. Application can use a GCLK output PIN
+  to generate SCK. For example to communicate with a SMARTCARD with ISO7816
+  (F = 372 ; D = 1), and baudrate=9600, the SCK pin output frequency should be
+  config as 372*9600=3571200Hz. More information can be refer to ISO7816 Specification.
+
+Known issues and workarounds
+----------------------------
+
+N/A
diff --git a/sysmoOCTSIM/hal/include/hal_usart_async.h b/sysmoOCTSIM/hal/include/hal_usart_async.h
new file mode 100644
index 0000000..3a6de39
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hal_usart_async.h
@@ -0,0 +1,339 @@
+/**
+ * \file
+ *
+ * \brief USART related functionality declaration.
+ *
+ * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \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_H_INCLUDED
+#define _HAL_USART_ASYNC_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_descriptor;
+
+/**
+ * \brief USART callback type
+ */
+typedef void (*usart_cb_t)(const struct usart_async_descriptor *const descr);
+
+/**
+ * \brief USART callback types
+ */
+enum usart_async_callback_type { USART_ASYNC_RXC_CB, USART_ASYNC_TXC_CB, USART_ASYNC_ERROR_CB };
+
+/**
+ * \brief USART callbacks
+ */
+struct usart_async_callbacks {
+	usart_cb_t tx_done;
+	usart_cb_t rx_done;
+	usart_cb_t error;
+};
+
+/** \brief USART status
+ *  Status descriptor holds the current status of transfer.
+ */
+struct usart_async_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_descriptor {
+	struct io_descriptor         io;
+	struct _usart_async_device   device;
+	struct usart_async_callbacks usart_cb;
+	uint32_t                     stat;
+
+	struct ringbuffer rx;
+	uint16_t          tx_por;
+	uint8_t *         tx_buffer;
+	uint16_t          tx_buffer_length;
+};
+
+/** USART write busy */
+#define USART_ASYNC_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] 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_init(struct usart_async_descriptor *const descr, void *const hw, uint8_t *const rx_buffer,
+                         const uint16_t rx_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_deinit(struct usart_async_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_enable(struct usart_async_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_disable(struct usart_async_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_get_io_descriptor(struct usart_async_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_register_callback(struct usart_async_descriptor *const descr,
+                                      const enum usart_async_callback_type type, usart_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_set_flow_control(struct usart_async_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_set_baud_rate(struct usart_async_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_set_data_order(struct usart_async_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_set_mode(struct usart_async_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_set_parity(struct usart_async_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_set_stopbits(struct usart_async_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_set_character_size(struct usart_async_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_flow_control_status(const struct usart_async_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_is_tx_empty(const struct usart_async_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_is_rx_not_empty(const struct usart_async_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_get_status(struct usart_async_descriptor *const descr, struct usart_async_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_flush_rx_buffer(struct usart_async_descriptor *const descr);
+
+/**
+ * \brief Retrieve the current driver version
+ *
+ * \return Current driver version.
+ */
+uint32_t usart_async_get_version(void);
+
+#ifdef __cplusplus
+}
+#endif
+/**@}*/
+#endif /* _HAL_USART_ASYNC_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/src/hal_usart_async.c b/sysmoOCTSIM/hal/src/hal_usart_async.c
new file mode 100644
index 0000000..f07b266
--- /dev/null
+++ b/sysmoOCTSIM/hal/src/hal_usart_async.c
@@ -0,0 +1,420 @@
+/**
+ * \file
+ *
+ * \brief I/O USART related functionality implementation.
+ *
+ * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \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.h"
+#include <utils_assert.h>
+#include <hal_atomic.h>
+#include <utils.h>
+
+/**
+ * \brief Driver version
+ */
+#define DRIVER_VERSION 0x00000001u
+
+static int32_t usart_async_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length);
+static int32_t usart_async_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_init(struct usart_async_descriptor *const descr, void *const hw, uint8_t *rx_buffer,
+                         uint16_t rx_buffer_length, void *const func)
+{
+	int32_t init_status;
+	ASSERT(descr && hw && rx_buffer && rx_buffer_length);
+
+	if (ERR_NONE != ringbuffer_init(&descr->rx, rx_buffer, rx_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_read;
+	descr->io.write = usart_async_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_deinit(struct usart_async_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_enable(struct usart_async_descriptor *const descr)
+{
+	ASSERT(descr);
+	_usart_async_enable(&descr->device);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Disable usart interface
+ */
+int32_t usart_async_disable(struct usart_async_descriptor *const descr)
+{
+	ASSERT(descr);
+	_usart_async_disable(&descr->device);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Retrieve I/O descriptor
+ */
+int32_t usart_async_get_io_descriptor(struct usart_async_descriptor *const descr, struct io_descriptor **io)
+{
+	ASSERT(descr && io);
+
+	*io = &descr->io;
+	return ERR_NONE;
+}
+
+/**
+ * \brief Register usart callback
+ */
+int32_t usart_async_register_callback(struct usart_async_descriptor *const descr,
+                                      const enum usart_async_callback_type type, usart_cb_t cb)
+{
+	ASSERT(descr);
+
+	switch (type) {
+	case USART_ASYNC_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_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_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_set_flow_control(struct usart_async_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_set_baud_rate(struct usart_async_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_set_data_order(struct usart_async_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_set_mode(struct usart_async_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_set_parity(struct usart_async_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_set_stopbits(struct usart_async_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_set_character_size(struct usart_async_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_flow_control_status(const struct usart_async_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_is_tx_empty(const struct usart_async_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_is_rx_not_empty(const struct usart_async_descriptor *const descr)
+{
+	ASSERT(descr);
+
+	return ringbuffer_num(&descr->rx) > 0;
+}
+
+/**
+ * \brief Retrieve the current interface status
+ */
+int32_t usart_async_get_status(struct usart_async_descriptor *const descr, struct usart_async_status *const status)
+{
+	ASSERT(descr);
+
+	volatile uint32_t *tmp_stat  = &(descr->stat);
+	volatile uint16_t *tmp_txcnt = &(descr->tx_por);
+
+	if (status) {
+		status->flags = *tmp_stat;
+		status->txcnt = *tmp_txcnt;
+		status->rxcnt = ringbuffer_num(&descr->rx);
+	}
+	if (*tmp_stat & USART_ASYNC_STATUS_BUSY) {
+		return ERR_BUSY;
+	}
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief flush usart rx ringbuf
+ */
+int32_t usart_async_flush_rx_buffer(struct usart_async_descriptor *const descr)
+{
+	ASSERT(descr);
+
+	return ringbuffer_flush(&descr->rx);
+}
+
+/**
+ * \brief Retrieve the current driver version
+ */
+uint32_t usart_async_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_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length)
+{
+	struct usart_async_descriptor *descr = CONTAINER_OF(io_descr, struct usart_async_descriptor, io);
+
+	ASSERT(descr && buf && length);
+
+	if (descr->tx_por != descr->tx_buffer_length) {
+		return ERR_NO_RESOURCE;
+	}
+	descr->tx_buffer        = (uint8_t *)buf;
+	descr->tx_buffer_length = length;
+	descr->tx_por           = 0;
+	descr->stat             = USART_ASYNC_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_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_descriptor *descr = CONTAINER_OF(io_descr, struct usart_async_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_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device);
+	if (descr->tx_por != descr->tx_buffer_length) {
+		_usart_async_write_byte(&descr->device, descr->tx_buffer[descr->tx_por++]);
+		_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_descriptor *descr = CONTAINER_OF(device, struct usart_async_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_descriptor *descr = CONTAINER_OF(device, struct usart_async_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_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device);
+
+	descr->stat = 0;
+	if (descr->usart_cb.error) {
+		descr->usart_cb.error(descr);
+	}
+}
+
+//@}
diff --git a/sysmoOCTSIM/hal/utils/include/utils_ringbuffer.h b/sysmoOCTSIM/hal/utils/include/utils_ringbuffer.h
new file mode 100644
index 0000000..401d557
--- /dev/null
+++ b/sysmoOCTSIM/hal/utils/include/utils_ringbuffer.h
@@ -0,0 +1,116 @@
+/**
+ * \file
+ *
+ * \brief Ringbuffer declaration.
+ *
+ * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \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 _UTILS_RINGBUFFER_H_INCLUDED
+#define _UTILS_RINGBUFFER_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \addtogroup doc_driver_hal_utils_ringbuffer
+ *
+ * @{
+ */
+
+#include "compiler.h"
+#include "utils_assert.h"
+
+/**
+ * \brief Ring buffer element type
+ */
+struct ringbuffer {
+	uint8_t *buf;         /** Buffer base address */
+	uint32_t size;        /** Buffer size */
+	uint32_t read_index;  /** Buffer read index */
+	uint32_t write_index; /** Buffer write index */
+};
+
+/**
+ * \brief Ring buffer init
+ *
+ * \param[in] rb The pointer to a ring buffer structure instance
+ * \param[in] buf Space to store the data
+ * \param[in] size The buffer length, must be aligned with power of 2
+ *
+ * \return ERR_NONE on success, or an error code on failure.
+ */
+int32_t ringbuffer_init(struct ringbuffer *const rb, void *buf, uint32_t size);
+
+/**
+ * \brief Get one byte from ring buffer, the user needs to handle the concurrent
+ * access on buffer via put/get/flush
+ *
+ * \param[in] rb The pointer to a ring buffer structure instance
+ * \param[in] data One byte space to store the read data
+ *
+ * \return ERR_NONE on success, or an error code on failure.
+ */
+int32_t ringbuffer_get(struct ringbuffer *const rb, uint8_t *data);
+
+/**
+ * \brief Put one byte to ring buffer, the user needs to handle the concurrent access
+ * on buffer via put/get/flush
+ *
+ * \param[in] rb The pointer to a ring buffer structure instance
+ * \param[in] data One byte data to be put into ring buffer
+ *
+ * \return ERR_NONE on success, or an error code on failure.
+ */
+int32_t ringbuffer_put(struct ringbuffer *const rb, uint8_t data);
+
+/**
+ * \brief Return the element number of ring buffer
+ *
+ * \param[in] rb The pointer to a ring buffer structure instance
+ *
+ * \return The number of elements in ring buffer [0, rb->size]
+ */
+uint32_t ringbuffer_num(const struct ringbuffer *const rb);
+
+/**
+ * \brief Flush ring buffer, the user needs to handle the concurrent access on buffer
+ * via put/get/flush
+ *
+ * \param[in] rb The pointer to a ring buffer structure instance
+ *
+ * \return ERR_NONE on success, or an error code on failure.
+ */
+uint32_t ringbuffer_flush(struct ringbuffer *const rb);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _UTILS_RINGBUFFER_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/utils/src/utils_ringbuffer.c b/sysmoOCTSIM/hal/utils/src/utils_ringbuffer.c
new file mode 100644
index 0000000..45cac83
--- /dev/null
+++ b/sysmoOCTSIM/hal/utils/src/utils_ringbuffer.c
@@ -0,0 +1,118 @@
+/**
+ * \file
+ *
+ * \brief Ringbuffer functionality implementation.
+ *
+ * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \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 "utils_ringbuffer.h"
+
+/**
+ * \brief Ringbuffer init
+ */
+int32_t ringbuffer_init(struct ringbuffer *const rb, void *buf, uint32_t size)
+{
+	ASSERT(rb && buf && size);
+
+	/*
+	 * buf size must be aligned to power of 2
+	 */
+	if ((size & (size - 1)) != 0) {
+		return ERR_INVALID_ARG;
+	}
+
+	/* size - 1 is faster in calculation */
+	rb->size        = size - 1;
+	rb->read_index  = 0;
+	rb->write_index = rb->read_index;
+	rb->buf         = (uint8_t *)buf;
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Get one byte from ringbuffer
+ *
+ */
+int32_t ringbuffer_get(struct ringbuffer *const rb, uint8_t *data)
+{
+	ASSERT(rb && data);
+
+	if (rb->write_index != rb->read_index) {
+		*data = rb->buf[rb->read_index & rb->size];
+		rb->read_index++;
+		return ERR_NONE;
+	}
+
+	return ERR_NOT_FOUND;
+}
+
+/**
+ * \brief Put one byte to ringbuffer
+ *
+ */
+int32_t ringbuffer_put(struct ringbuffer *const rb, uint8_t data)
+{
+	ASSERT(rb);
+
+	rb->buf[rb->write_index & rb->size] = data;
+
+	/*
+	 * buffer full strategy: new data will overwrite the oldest data in
+	 * the buffer
+	 */
+	if ((rb->write_index - rb->read_index) > rb->size) {
+		rb->read_index = rb->write_index - rb->size;
+	}
+
+	rb->write_index++;
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Return the element number of ringbuffer
+ */
+uint32_t ringbuffer_num(const struct ringbuffer *const rb)
+{
+	ASSERT(rb);
+
+	return rb->write_index - rb->read_index;
+}
+
+/**
+ * \brief Flush ringbuffer
+ */
+uint32_t ringbuffer_flush(struct ringbuffer *const rb)
+{
+	ASSERT(rb);
+
+	rb->read_index = rb->write_index;
+
+	return ERR_NONE;
+}
diff --git a/sysmoOCTSIM/hpl/sercom/hpl_sercom.c b/sysmoOCTSIM/hpl/sercom/hpl_sercom.c
index 130f63a..11192d0 100644
--- a/sysmoOCTSIM/hpl/sercom/hpl_sercom.c
+++ b/sysmoOCTSIM/hpl/sercom/hpl_sercom.c
@@ -163,6 +163,8 @@
 };
 #endif
 
+static struct _usart_async_device *_sercom2_dev = NULL;
+
 static uint8_t _get_sercom_index(const void *const hw);
 static uint8_t _sercom_get_irq_num(const void *const hw);
 static void    _sercom_init_irq_param(const void *const hw, void *dev);
@@ -563,6 +565,40 @@
 }
 
 /**
+ * \internal Sercom interrupt handler
+ *
+ * \param[in] p The pointer to interrupt parameter
+ */
+static void _sercom_usart_interrupt_handler(struct _usart_async_device *device)
+{
+	void *hw = device->hw;
+
+	if (hri_sercomusart_get_interrupt_DRE_bit(hw) && hri_sercomusart_get_INTEN_DRE_bit(hw)) {
+		hri_sercomusart_clear_INTEN_DRE_bit(hw);
+		device->usart_cb.tx_byte_sent(device);
+	} else if (hri_sercomusart_get_interrupt_TXC_bit(hw) && hri_sercomusart_get_INTEN_TXC_bit(hw)) {
+		hri_sercomusart_clear_INTEN_TXC_bit(hw);
+		device->usart_cb.tx_done_cb(device);
+	} else if (hri_sercomusart_get_interrupt_RXC_bit(hw)) {
+		if (hri_sercomusart_read_STATUS_reg(hw)
+		    & (SERCOM_USART_STATUS_PERR | SERCOM_USART_STATUS_FERR | SERCOM_USART_STATUS_BUFOVF
+		       | SERCOM_USART_STATUS_ISF | SERCOM_USART_STATUS_COLL)) {
+			hri_sercomusart_clear_STATUS_reg(hw, SERCOM_USART_STATUS_MASK);
+			return;
+		}
+
+		device->usart_cb.rx_done_cb(device, hri_sercomusart_read_DATA_reg(hw));
+	} else if (hri_sercomusart_get_interrupt_ERROR_bit(hw)) {
+		uint32_t status;
+
+		hri_sercomusart_clear_interrupt_ERROR_bit(hw);
+		device->usart_cb.error_cb(device);
+		status = hri_sercomusart_read_STATUS_reg(hw);
+		hri_sercomusart_clear_STATUS_reg(hw, status);
+	}
+}
+
+/**
  * \internal Retrieve ordinal number of the given sercom hardware instance
  *
  * \param[in] hw The pointer to hardware instance
@@ -589,6 +625,10 @@
  */
 static void _sercom_init_irq_param(const void *const hw, void *dev)
 {
+
+	if (hw == SERCOM2) {
+		_sercom2_dev = (struct _usart_async_device *)dev;
+	}
 }
 
 /**
@@ -2349,6 +2389,35 @@
 	return NULL;
 }
 
+/**
+ * \internal Sercom interrupt handler
+ */
+void SERCOM2_0_Handler(void)
+{
+	_sercom_usart_interrupt_handler(_sercom2_dev);
+}
+/**
+ * \internal Sercom interrupt handler
+ */
+void SERCOM2_1_Handler(void)
+{
+	_sercom_usart_interrupt_handler(_sercom2_dev);
+}
+/**
+ * \internal Sercom interrupt handler
+ */
+void SERCOM2_2_Handler(void)
+{
+	_sercom_usart_interrupt_handler(_sercom2_dev);
+}
+/**
+ * \internal Sercom interrupt handler
+ */
+void SERCOM2_3_Handler(void)
+{
+	_sercom_usart_interrupt_handler(_sercom2_dev);
+}
+
 int32_t _spi_m_sync_init(struct _spi_m_sync_dev *dev, void *const hw)
 {
 	const struct sercomspi_regs_cfg *regs = _spi_get_regs((uint32_t)hw);

-- 
To view, visit https://gerrit.osmocom.org/12803
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: I530a5bc5ee7e89149eb251bda0adf7963733d2ee
Gerrit-Change-Number: 12803
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/20190203/cc20f45f/attachment.htm>


More information about the gerrit-log mailing list