add SERCOM peripheral for UART debug

currently only the SERCOM peripheral driver is added an configured,
but it is not being used.
UART debug will be done through the EDBG COM port, on PB24/PB25 of
SAM E54 Xplained Pro board

Change-Id: Id7af37ce1dd2d0a356e019c96bf6438ce459411b
diff --git a/sysmoOCTSIM/AtmelStart.gpdsc b/sysmoOCTSIM/AtmelStart.gpdsc
index 4784595..44b5c62 100644
--- a/sysmoOCTSIM/AtmelStart.gpdsc
+++ b/sysmoOCTSIM/AtmelStart.gpdsc
@@ -42,6 +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/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"/>
@@ -56,10 +57,23 @@
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_delay.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_dma.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_gpio.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_i2c_m_async.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_i2c_m_sync.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_i2c_s_async.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_i2c_s_sync.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_init.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_irq.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_ramecc.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_sleep.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_spi.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_spi_async.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_spi_m_async.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_spi_m_dma.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_spi_m_sync.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_spi_s_async.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_spi_s_sync.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_spi_sync.h"/>
+        <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_usart.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_usb.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_usb_device.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_usb_host.h"/>
@@ -151,8 +165,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/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="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"/>
@@ -168,6 +186,7 @@
         <file category="header" condition="ARMCC, GCC, IAR" name="hpl/pm/hpl_pm_base.h"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="hpl/port/hpl_gpio_base.h"/>
         <file category="source" condition="ARMCC, GCC, IAR" name="hpl/ramecc/hpl_ramecc.c"/>
+        <file category="source" condition="ARMCC, GCC, IAR" name="hpl/sercom/hpl_sercom.c"/>
         <file category="source" condition="ARMCC, GCC, IAR" name="hpl/usb/hpl_usb.c"/>
         <file category="source" condition="ARMCC, GCC, IAR" name="usb_start.c"/>
         <file category="header" condition="ARMCC, GCC, IAR" name="usb_start.h"/>
@@ -180,6 +199,7 @@
         <file attr="config" category="header" condition="ARMCC, GCC, IAR" name="config/hpl_osc32kctrl_config.h"/>
         <file attr="config" category="header" condition="ARMCC, GCC, IAR" name="config/hpl_oscctrl_config.h"/>
         <file attr="config" category="header" condition="ARMCC, GCC, IAR" name="config/hpl_port_config.h"/>
+        <file attr="config" category="header" condition="ARMCC, GCC, IAR" name="config/hpl_sercom_config.h"/>
         <file attr="config" category="header" condition="ARMCC, GCC, IAR" name="config/hpl_usb_config.h"/>
         <file attr="config" category="header" condition="ARMCC, GCC, IAR" name="config/peripheral_clk_config.h"/>
         <file attr="config" category="header" condition="ARMCC, GCC, IAR" name="config/usbd_config.h"/>
@@ -198,6 +218,7 @@
         <file category="include" condition="ARMCC, GCC, IAR" name="hpl/pm"/>
         <file category="include" condition="ARMCC, GCC, IAR" name="hpl/port"/>
         <file category="include" condition="ARMCC, GCC, IAR" name="hpl/ramecc"/>
+        <file category="include" condition="ARMCC, GCC, IAR" name="hpl/sercom"/>
         <file category="include" condition="ARMCC, GCC, IAR" name="hpl/usb"/>
         <file category="include" condition="ARMCC, GCC, IAR" name="hri"/>
         <file category="include" condition="ARMCC, GCC, IAR" name=""/>
diff --git a/sysmoOCTSIM/armcc/Makefile b/sysmoOCTSIM/armcc/Makefile
index a131e45..3a130a8 100644
--- a/sysmoOCTSIM/armcc/Makefile
+++ b/sysmoOCTSIM/armcc/Makefile
@@ -37,11 +37,12 @@
 usb \
 armcc/arm_addon/armcc/arm \
 hal/utils/src \
-armcc/arm_addon/armcc \
+hpl/sercom \
 examples \
 hpl/gclk \
 usb/device \
 hpl/oscctrl \
+armcc/arm_addon/armcc \
 hpl/usb \
 hpl/core \
 hpl/cmcc
@@ -62,6 +63,7 @@
 hal/utils/src/utils_assert.o \
 usb_start.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 \
@@ -70,6 +72,7 @@
 hpl/osc32kctrl/hpl_osc32kctrl.o \
 examples/driver_examples.o \
 driver_init.o \
+hpl/sercom/hpl_sercom.o \
 hal/src/hal_gpio.o \
 hal/utils/src/utils_event.o \
 hal/src/hal_sleep.o \
@@ -96,6 +99,7 @@
 "hal/utils/src/utils_assert.o" \
 "usb_start.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" \
@@ -104,6 +108,7 @@
 "hpl/osc32kctrl/hpl_osc32kctrl.o" \
 "examples/driver_examples.o" \
 "driver_init.o" \
+"hpl/sercom/hpl_sercom.o" \
 "hal/src/hal_gpio.o" \
 "hal/utils/src/utils_event.o" \
 "hal/src/hal_sleep.o" \
@@ -138,6 +143,7 @@
 "hal/src/hal_usb_device.d" \
 "hpl/dmac/hpl_dmac.d" \
 "hal/src/hal_init.d" \
+"hal/src/hal_usart_sync.d" \
 "usb_cdc_echo_main.d" \
 "hpl/mclk/hpl_mclk.d" \
 "driver_init.d" \
@@ -145,6 +151,7 @@
 "examples/driver_examples.d" \
 "hal/src/hal_cache.d" \
 "hal/src/hal_sleep.d" \
+"hpl/sercom/hpl_sercom.d" \
 "hal/src/hal_gpio.d" \
 "hal/src/hal_atomic.d" \
 "usb/device/usbdc.d" \
@@ -186,7 +193,7 @@
 	@echo Building file: $<
 	@echo ARMCC Compiler
 	$(QUOTE)armcc$(QUOTE) --c99 -c -DDEBUG -O1 -g --apcs=interwork --split_sections --cpu Cortex-M4 -D__SAME54P20A__ \
--I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \
+-I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \
 --depend "$@"  -o "$@" "$<"
 
 	@echo Finished building: $<
@@ -195,7 +202,7 @@
 	@echo Building file: $<
 	@echo ARMCC Assembler
 	$(QUOTE)armasm$(QUOTE) -g --apcs=interwork --cpu Cortex-M4 --pd "D__SAME54P20A__ SETA 1" \
--I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \
+-I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \
 --depend "$(@:%.o=%.d)" -o "$@" "$<"
 
 	@echo Finished building: $<
@@ -204,7 +211,7 @@
 	@echo Building file: $<
 	@echo ARMCC Preprocessing Assembler
 	$(QUOTE)armcc$(QUOTE) --c99 -c -DDEBUG -O1 -g --apcs=interwork --split_sections --cpu Cortex-M4 -D__SAME54P20A__ \
--I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \
+-I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \
 --depend "$@"  -o "$@" "$<"
 
 	@echo Finished building: $<
diff --git a/sysmoOCTSIM/atmel_start_config.atstart b/sysmoOCTSIM/atmel_start_config.atstart
index 3899d79..cb7826a 100644
--- a/sysmoOCTSIM/atmel_start_config.atstart
+++ b/sysmoOCTSIM/atmel_start_config.atstart
@@ -957,6 +957,51 @@
     variant: null
     clocks:
       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
+    functionality: USART
+    api: HAL:Driver:USART_Sync
+    configuration:
+      usart_advanced: false
+      usart_arch_clock_mode: USART with internal clock
+      usart_arch_cloden: false
+      usart_arch_dbgstop: Keep running
+      usart_arch_dord: LSB is transmitted first
+      usart_arch_enc: No encoding
+      usart_arch_fractional: 0
+      usart_arch_ibon: false
+      usart_arch_lin_slave_enable: Disable
+      usart_arch_runstdby: false
+      usart_arch_sampa: 7-8-9 (3-4-5 8-bit over-sampling)
+      usart_arch_sampr: 16x arithmetic
+      usart_arch_sfde: false
+      usart_baud_rate: 921600
+      usart_character_size: 8 bits
+      usart_parity: No parity
+      usart_rx_enable: true
+      usart_stop_bit: One stop bit
+      usart_tx_enable: true
+    optional_signals: []
+    variant:
+      specification: TXPO=0, RXPO=1, CMODE=0
+      required_signals:
+      - name: SERCOM2/PAD/0
+        pad: PB25
+        label: TX
+      - name: SERCOM2/PAD/1
+        pad: PB24
+        label: RX
+    clocks:
+      domain_group:
+        nodes:
+        - name: Core
+          input: Generic clock generator 2
+        - name: Slow
+          input: Generic clock generator 3
+        configuration:
+          core_gclk_selection: Generic clock generator 2
+          slow_gclk_selection: Generic clock generator 3
   USB_DEVICE_INSTANCE:
     user_label: USB_DEVICE_INSTANCE
     definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::USB::driver_config_definition::USB.Device::HAL:Driver:USB.Device
@@ -1011,4 +1056,16 @@
     mode: Advanced
     user_label: PA25
     configuration: {}
+  PB24:
+    name: PB24
+    definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PB24
+    mode: Peripheral IO
+    user_label: PB24
+    configuration: null
+  PB25:
+    name: PB25
+    definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PB25
+    mode: Peripheral IO
+    user_label: PB25
+    configuration: null
 toolchain_options: []
diff --git a/sysmoOCTSIM/atmel_start_pins.h b/sysmoOCTSIM/atmel_start_pins.h
index dbf9891..3631847 100644
--- a/sysmoOCTSIM/atmel_start_pins.h
+++ b/sysmoOCTSIM/atmel_start_pins.h
@@ -29,5 +29,7 @@
 
 #define PA24 GPIO(GPIO_PORTA, 24)
 #define PA25 GPIO(GPIO_PORTA, 25)
+#define PB24 GPIO(GPIO_PORTB, 24)
+#define PB25 GPIO(GPIO_PORTB, 25)
 
 #endif // ATMEL_START_PINS_H_INCLUDED
diff --git a/sysmoOCTSIM/config/hpl_gclk_config.h b/sysmoOCTSIM/config/hpl_gclk_config.h
index 0ad8ead..12c1539 100644
--- a/sysmoOCTSIM/config/hpl_gclk_config.h
+++ b/sysmoOCTSIM/config/hpl_gclk_config.h
@@ -218,7 +218,7 @@
 // <i> Indicates whether Generic Clock Generator Enable is enabled or not
 // <id> gclk_arch_gen_2_enable
 #ifndef CONF_GCLK_GEN_2_GENEN
-#define CONF_GCLK_GEN_2_GENEN 0
+#define CONF_GCLK_GEN_2_GENEN 1
 #endif
 // </h>
 
diff --git a/sysmoOCTSIM/config/hpl_sercom_config.h b/sysmoOCTSIM/config/hpl_sercom_config.h
new file mode 100644
index 0000000..e154ce2
--- /dev/null
+++ b/sysmoOCTSIM/config/hpl_sercom_config.h
@@ -0,0 +1,278 @@
+/* Auto-generated config file hpl_sercom_config.h */
+#ifndef HPL_SERCOM_CONFIG_H
+#define HPL_SERCOM_CONFIG_H
+
+// <<< Use Configuration Wizard in Context Menu >>>
+
+#include <peripheral_clk_config.h>
+
+#ifndef CONF_SERCOM_2_USART_ENABLE
+#define CONF_SERCOM_2_USART_ENABLE 1
+#endif
+
+// <h> Basic Configuration
+
+// <q> Receive buffer enable
+// <i> Enable input buffer in SERCOM module
+// <id> usart_rx_enable
+#ifndef CONF_SERCOM_2_USART_RXEN
+#define CONF_SERCOM_2_USART_RXEN 1
+#endif
+
+// <q> Transmitt buffer enable
+// <i> Enable output buffer in SERCOM module
+// <id> usart_tx_enable
+#ifndef CONF_SERCOM_2_USART_TXEN
+#define CONF_SERCOM_2_USART_TXEN 1
+#endif
+
+// <o> Frame parity
+// <0x0=>No parity
+// <0x1=>Even parity
+// <0x2=>Odd parity
+// <i> Parity bit mode for USART frame
+// <id> usart_parity
+#ifndef CONF_SERCOM_2_USART_PARITY
+#define CONF_SERCOM_2_USART_PARITY 0x0
+#endif
+
+// <o> Character Size
+// <0x0=>8 bits
+// <0x1=>9 bits
+// <0x5=>5 bits
+// <0x6=>6 bits
+// <0x7=>7 bits
+// <i> Data character size in USART frame
+// <id> usart_character_size
+#ifndef CONF_SERCOM_2_USART_CHSIZE
+#define CONF_SERCOM_2_USART_CHSIZE 0x0
+#endif
+
+// <o> Stop Bit
+// <0=>One stop bit
+// <1=>Two stop bits
+// <i> Number of stop bits in USART frame
+// <id> usart_stop_bit
+#ifndef CONF_SERCOM_2_USART_SBMODE
+#define CONF_SERCOM_2_USART_SBMODE 0
+#endif
+
+// <o> Baud rate <1-6250000>
+// <i> USART baud rate setting
+// <id> usart_baud_rate
+#ifndef CONF_SERCOM_2_USART_BAUD
+#define CONF_SERCOM_2_USART_BAUD 921600
+#endif
+
+// </h>
+
+// <e> Advanced configuration
+// <id> usart_advanced
+#ifndef CONF_SERCOM_2_USART_ADVANCED_CONFIG
+#define CONF_SERCOM_2_USART_ADVANCED_CONFIG 0
+#endif
+
+// <q> Run in stand-by
+// <i> Keep the module running in standby sleep mode
+// <id> usart_arch_runstdby
+#ifndef CONF_SERCOM_2_USART_RUNSTDBY
+#define CONF_SERCOM_2_USART_RUNSTDBY 0
+#endif
+
+// <q> Immediate Buffer Overflow Notification
+// <i> Controls when the BUFOVF status bit is asserted
+// <id> usart_arch_ibon
+#ifndef CONF_SERCOM_2_USART_IBON
+#define CONF_SERCOM_2_USART_IBON 0
+#endif
+
+// <q> Start of Frame Detection Enable
+// <i> Will wake the device from any sleep mode if usart_init and usart_enable was run priort to going to sleep. (receive buffer must be enabled)
+// <id> usart_arch_sfde
+#ifndef CONF_SERCOM_2_USART_SFDE
+#define CONF_SERCOM_2_USART_SFDE 0
+#endif
+
+// <q> Collision Detection Enable
+// <i> Collision detection enable
+// <id> usart_arch_cloden
+#ifndef CONF_SERCOM_2_USART_CLODEN
+#define CONF_SERCOM_2_USART_CLODEN 0
+#endif
+
+// <o> Operating Mode
+// <0x0=>USART with external clock
+// <0x1=>USART with internal clock
+// <i> Drive the shift register by an internal clock generated by the baud rate generator or an external clock supplied on the XCK pin.
+// <id> usart_arch_clock_mode
+#ifndef CONF_SERCOM_2_USART_MODE
+#define CONF_SERCOM_2_USART_MODE 0x1
+#endif
+
+// <o> Sample Rate
+// <0x0=>16x arithmetic
+// <0x1=>16x fractional
+// <0x2=>8x arithmetic
+// <0x3=>8x fractional
+// <0x4=>3x arithmetic
+// <i> How many over-sampling bits used when sampling data state
+// <id> usart_arch_sampr
+#ifndef CONF_SERCOM_2_USART_SAMPR
+#define CONF_SERCOM_2_USART_SAMPR 0x0
+#endif
+
+// <o> Sample Adjustment
+// <0x0=>7-8-9 (3-4-5 8-bit over-sampling)
+// <0x1=>9-10-11 (4-5-6 8-bit over-sampling)
+// <0x2=>11-12-13 (5-6-7 8-bit over-sampling)
+// <0x3=>13-14-15 (6-7-8 8-bit over-sampling)
+// <i> Adjust which samples to use for data sampling in asynchronous mode
+// <id> usart_arch_sampa
+#ifndef CONF_SERCOM_2_USART_SAMPA
+#define CONF_SERCOM_2_USART_SAMPA 0x0
+#endif
+
+// <o> Fractional Part <0-7>
+// <i> Fractional part of the baud rate if baud rate generator is in fractional mode
+// <id> usart_arch_fractional
+#ifndef CONF_SERCOM_2_USART_FRACTIONAL
+#define CONF_SERCOM_2_USART_FRACTIONAL 0x0
+#endif
+
+// <o> Data Order
+// <0=>MSB is transmitted first
+// <1=>LSB is transmitted first
+// <i> Data order of the data bits in the frame
+// <id> usart_arch_dord
+#ifndef CONF_SERCOM_2_USART_DORD
+#define CONF_SERCOM_2_USART_DORD 1
+#endif
+
+// Does not do anything in UART mode
+#define CONF_SERCOM_2_USART_CPOL 0
+
+// <o> Encoding Format
+// <0=>No encoding
+// <1=>IrDA encoded
+// <id> usart_arch_enc
+#ifndef CONF_SERCOM_2_USART_ENC
+#define CONF_SERCOM_2_USART_ENC 0
+#endif
+
+// <o> LIN Slave Enable
+// <i> Break Character Detection and Auto-Baud/LIN Slave Enable.
+// <i> Additional setting needed: 16x sample rate using fractional baud rate generation (CTRLA.SAMPR = 1).
+// <0=>Disable
+// <1=>Enable
+// <id> usart_arch_lin_slave_enable
+#ifndef CONF_SERCOM_2_USART_LIN_SLAVE_ENABLE
+#define CONF_SERCOM_2_USART_LIN_SLAVE_ENABLE 0
+#endif
+
+// <o> Debug Stop Mode
+// <i> Behavior of the baud-rate generator when CPU is halted by external debugger.
+// <0=>Keep running
+// <1=>Halt
+// <id> usart_arch_dbgstop
+#ifndef CONF_SERCOM_2_USART_DEBUG_STOP_MODE
+#define CONF_SERCOM_2_USART_DEBUG_STOP_MODE 0
+#endif
+
+// </e>
+
+#ifndef CONF_SERCOM_2_USART_INACK
+#define CONF_SERCOM_2_USART_INACK 0x0
+#endif
+
+#ifndef CONF_SERCOM_2_USART_DSNACK
+#define CONF_SERCOM_2_USART_DSNACK 0x0
+#endif
+
+#ifndef CONF_SERCOM_2_USART_MAXITER
+#define CONF_SERCOM_2_USART_MAXITER 0x7
+#endif
+
+#ifndef CONF_SERCOM_2_USART_GTIME
+#define CONF_SERCOM_2_USART_GTIME 0x2
+#endif
+
+#define CONF_SERCOM_2_USART_RXINV 0x0
+#define CONF_SERCOM_2_USART_TXINV 0x0
+
+#ifndef CONF_SERCOM_2_USART_CMODE
+#define CONF_SERCOM_2_USART_CMODE 0
+#endif
+
+#ifndef CONF_SERCOM_2_USART_RXPO
+#define CONF_SERCOM_2_USART_RXPO 1 /* RX is on PIN_PB24 */
+#endif
+
+#ifndef CONF_SERCOM_2_USART_TXPO
+#define CONF_SERCOM_2_USART_TXPO 0 /* TX is on PIN_PB25 */
+#endif
+
+/* Set correct parity settings in register interface based on PARITY setting */
+#if CONF_SERCOM_2_USART_LIN_SLAVE_ENABLE == 1
+#if CONF_SERCOM_2_USART_PARITY == 0
+#define CONF_SERCOM_2_USART_PMODE 0
+#define CONF_SERCOM_2_USART_FORM 4
+#else
+#define CONF_SERCOM_2_USART_PMODE CONF_SERCOM_2_USART_PARITY - 1
+#define CONF_SERCOM_2_USART_FORM 5
+#endif
+#else /* #if CONF_SERCOM_2_USART_LIN_SLAVE_ENABLE == 0 */
+#if CONF_SERCOM_2_USART_PARITY == 0
+#define CONF_SERCOM_2_USART_PMODE 0
+#define CONF_SERCOM_2_USART_FORM 0
+#else
+#define CONF_SERCOM_2_USART_PMODE CONF_SERCOM_2_USART_PARITY - 1
+#define CONF_SERCOM_2_USART_FORM 1
+#endif
+#endif
+
+// Calculate BAUD register value in UART mode
+#if CONF_SERCOM_2_USART_SAMPR == 0
+#ifndef CONF_SERCOM_2_USART_BAUD_RATE
+#define CONF_SERCOM_2_USART_BAUD_RATE                                                                                  \
+	65536 - ((65536 * 16.0f * CONF_SERCOM_2_USART_BAUD) / CONF_GCLK_SERCOM2_CORE_FREQUENCY)
+#endif
+#ifndef CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH
+#define CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH 0
+#endif
+#elif CONF_SERCOM_2_USART_SAMPR == 1
+#ifndef CONF_SERCOM_2_USART_BAUD_RATE
+#define CONF_SERCOM_2_USART_BAUD_RATE                                                                                  \
+	((CONF_GCLK_SERCOM2_CORE_FREQUENCY) / (CONF_SERCOM_2_USART_BAUD * 16)) - (CONF_SERCOM_2_USART_FRACTIONAL / 8)
+#endif
+#ifndef CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH
+#define CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH 0
+#endif
+#elif CONF_SERCOM_2_USART_SAMPR == 2
+#ifndef CONF_SERCOM_2_USART_BAUD_RATE
+#define CONF_SERCOM_2_USART_BAUD_RATE                                                                                  \
+	65536 - ((65536 * 8.0f * CONF_SERCOM_2_USART_BAUD) / CONF_GCLK_SERCOM2_CORE_FREQUENCY)
+#endif
+#ifndef CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH
+#define CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH 0
+#endif
+#elif CONF_SERCOM_2_USART_SAMPR == 3
+#ifndef CONF_SERCOM_2_USART_BAUD_RATE
+#define CONF_SERCOM_2_USART_BAUD_RATE                                                                                  \
+	((CONF_GCLK_SERCOM2_CORE_FREQUENCY) / (CONF_SERCOM_2_USART_BAUD * 8)) - (CONF_SERCOM_2_USART_FRACTIONAL / 8)
+#endif
+#ifndef CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH
+#define CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH 0
+#endif
+#elif CONF_SERCOM_2_USART_SAMPR == 4
+#ifndef CONF_SERCOM_2_USART_BAUD_RATE
+#define CONF_SERCOM_2_USART_BAUD_RATE                                                                                  \
+	65536 - ((65536 * 3.0f * CONF_SERCOM_2_USART_BAUD) / CONF_GCLK_SERCOM2_CORE_FREQUENCY)
+#endif
+#ifndef CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH
+#define CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH 0
+#endif
+#endif
+
+// <<< end of configuration section >>>
+
+#endif // HPL_SERCOM_CONFIG_H
diff --git a/sysmoOCTSIM/config/peripheral_clk_config.h b/sysmoOCTSIM/config/peripheral_clk_config.h
index 8078e4b..c9852b6 100644
--- a/sysmoOCTSIM/config/peripheral_clk_config.h
+++ b/sysmoOCTSIM/config/peripheral_clk_config.h
@@ -12,6 +12,86 @@
 #define CONF_CPU_FREQUENCY 120000000
 #endif
 
+// <y> Core Clock Source
+// <id> core_gclk_selection
+
+// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
+
+// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
+
+// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
+
+// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
+
+// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
+
+// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
+
+// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
+
+// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
+
+// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
+
+// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
+
+// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
+
+// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
+
+// <i> Select the clock source for CORE.
+#ifndef CONF_GCLK_SERCOM2_CORE_SRC
+#define CONF_GCLK_SERCOM2_CORE_SRC GCLK_PCHCTRL_GEN_GCLK2_Val
+#endif
+
+// <y> Slow Clock Source
+// <id> slow_gclk_selection
+
+// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
+
+// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
+
+// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
+
+// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
+
+// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
+
+// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
+
+// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
+
+// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
+
+// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
+
+// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
+
+// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
+
+// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
+
+// <i> Select the slow clock source.
+#ifndef CONF_GCLK_SERCOM2_SLOW_SRC
+#define CONF_GCLK_SERCOM2_SLOW_SRC GCLK_PCHCTRL_GEN_GCLK3_Val
+#endif
+
+/**
+ * \def CONF_GCLK_SERCOM2_CORE_FREQUENCY
+ * \brief SERCOM2's Core Clock frequency
+ */
+#ifndef CONF_GCLK_SERCOM2_CORE_FREQUENCY
+#define CONF_GCLK_SERCOM2_CORE_FREQUENCY 100000000
+#endif
+
+/**
+ * \def CONF_GCLK_SERCOM2_SLOW_FREQUENCY
+ * \brief SERCOM2's Slow Clock frequency
+ */
+#ifndef CONF_GCLK_SERCOM2_SLOW_FREQUENCY
+#define CONF_GCLK_SERCOM2_SLOW_FREQUENCY 32768
+#endif
+
 // <y> USB Clock Source
 // <id> usb_gclk_selection
 
diff --git a/sysmoOCTSIM/driver_init.c b/sysmoOCTSIM/driver_init.c
index 920593a..72f2c88 100644
--- a/sysmoOCTSIM/driver_init.c
+++ b/sysmoOCTSIM/driver_init.c
@@ -11,6 +11,31 @@
 #include <utils.h>
 #include <hal_init.h>
 
+struct usart_sync_descriptor UART_debug;
+
+void UART_debug_PORT_init(void)
+{
+
+	gpio_set_pin_function(PB25, PINMUX_PB25D_SERCOM2_PAD0);
+
+	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);
+}
+
+void UART_debug_init(void)
+{
+	UART_debug_CLOCK_init();
+	usart_sync_init(&UART_debug, SERCOM2, (void *)NULL);
+	UART_debug_PORT_init();
+}
+
 void USB_DEVICE_INSTANCE_PORT_init(void)
 {
 
@@ -130,5 +155,7 @@
 {
 	init_mcu();
 
+	UART_debug_init();
+
 	USB_DEVICE_INSTANCE_init();
 }
diff --git a/sysmoOCTSIM/driver_init.h b/sysmoOCTSIM/driver_init.h
index 5c029a4..7067684 100644
--- a/sysmoOCTSIM/driver_init.h
+++ b/sysmoOCTSIM/driver_init.h
@@ -21,8 +21,16 @@
 #include <hal_io.h>
 #include <hal_sleep.h>
 
+#include <hal_usart_sync.h>
+
 #include "hal_usb_device.h"
 
+extern struct usart_sync_descriptor UART_debug;
+
+void UART_debug_PORT_init(void);
+void UART_debug_CLOCK_init(void);
+void UART_debug_init(void);
+
 void USB_DEVICE_INSTANCE_CLOCK_init(void);
 void USB_DEVICE_INSTANCE_init(void);
 
diff --git a/sysmoOCTSIM/examples/driver_examples.c b/sysmoOCTSIM/examples/driver_examples.c
index 69d50de..56247ff 100644
--- a/sysmoOCTSIM/examples/driver_examples.c
+++ b/sysmoOCTSIM/examples/driver_examples.c
@@ -9,3 +9,15 @@
 #include "driver_examples.h"
 #include "driver_init.h"
 #include "utils.h"
+
+/**
+ * Example of using UART_debug to write "Hello World" using the IO abstraction.
+ */
+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);
+}
diff --git a/sysmoOCTSIM/examples/driver_examples.h b/sysmoOCTSIM/examples/driver_examples.h
index ef1c619..7bb60eb 100644
--- a/sysmoOCTSIM/examples/driver_examples.h
+++ b/sysmoOCTSIM/examples/driver_examples.h
@@ -12,6 +12,8 @@
 extern "C" {
 #endif
 
+void UART_debug_example(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sysmoOCTSIM/gcc/Makefile b/sysmoOCTSIM/gcc/Makefile
index 6542661..aeae7a5 100644
--- a/sysmoOCTSIM/gcc/Makefile
+++ b/sysmoOCTSIM/gcc/Makefile
@@ -36,6 +36,7 @@
 hpl/mclk \
 usb \
 hal/utils/src \
+hpl/sercom \
 examples \
 hpl/gclk \
 usb/device \
@@ -62,6 +63,7 @@
 hal/utils/src/utils_assert.o \
 usb_start.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 \
@@ -71,6 +73,7 @@
 hpl/osc32kctrl/hpl_osc32kctrl.o \
 examples/driver_examples.o \
 driver_init.o \
+hpl/sercom/hpl_sercom.o \
 hal/src/hal_gpio.o \
 hal/utils/src/utils_event.o \
 hal/src/hal_sleep.o \
@@ -97,6 +100,7 @@
 "hal/utils/src/utils_assert.o" \
 "usb_start.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" \
@@ -106,6 +110,7 @@
 "hpl/osc32kctrl/hpl_osc32kctrl.o" \
 "examples/driver_examples.o" \
 "driver_init.o" \
+"hpl/sercom/hpl_sercom.o" \
 "hal/src/hal_gpio.o" \
 "hal/utils/src/utils_event.o" \
 "hal/src/hal_sleep.o" \
@@ -140,6 +145,7 @@
 "hal/src/hal_usb_device.d" \
 "hpl/dmac/hpl_dmac.d" \
 "hal/src/hal_init.d" \
+"hal/src/hal_usart_sync.d" \
 "usb_cdc_echo_main.d" \
 "hpl/mclk/hpl_mclk.d" \
 "driver_init.d" \
@@ -147,6 +153,7 @@
 "examples/driver_examples.d" \
 "hal/src/hal_cache.d" \
 "hal/src/hal_sleep.d" \
+"hpl/sercom/hpl_sercom.d" \
 "hal/src/hal_gpio.d" \
 "hal/src/hal_atomic.d" \
 "usb/device/usbdc.d" \
@@ -199,7 +206,7 @@
 	@echo ARM/GNU C Compiler
 	$(QUOTE)arm-none-eabi-gcc$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \
 -D__SAME54P20A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \
--I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \
+-I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \
 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"  -o "$@" "$<"
 	@echo Finished building: $<
 
@@ -208,7 +215,7 @@
 	@echo ARM/GNU Assembler
 	$(QUOTE)arm-none-eabi-as$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \
 -D__SAME54P20A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \
--I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \
+-I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \
 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"  -o "$@" "$<"
 	@echo Finished building: $<
 
@@ -217,7 +224,7 @@
 	@echo ARM/GNU Preprocessing Assembler
 	$(QUOTE)arm-none-eabi-gcc$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \
 -D__SAME54P20A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \
--I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \
+-I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/cdc" -I"../usb/class/cdc/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include"  \
 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"  -o "$@" "$<"
 	@echo Finished building: $<
 
diff --git a/sysmoOCTSIM/hal/documentation/usart_sync.rst b/sysmoOCTSIM/hal/documentation/usart_sync.rst
new file mode 100644
index 0000000..15e4b13
--- /dev/null
+++ b/sysmoOCTSIM/hal/documentation/usart_sync.rst
@@ -0,0 +1,58 @@
+The USART Synchronous Driver
+============================
+
+The universal synchronous and asynchronous receiver and transmitter
+(USART) is usually used to transfer data from one device to the other.
+
+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
+
+Applications
+------------
+
+They are commonly used in a terminal application or low-speed communication
+between devices.
+
+Dependencies
+------------
+
+USART capable hardware.
+
+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_sync.h b/sysmoOCTSIM/hal/include/hal_usart_sync.h
new file mode 100644
index 0000000..1ef22fc
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hal_usart_sync.h
@@ -0,0 +1,247 @@
+/**
+ * \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_SYNC_USART_H_INCLUDED
+#define _HAL_SYNC_USART_H_INCLUDED
+
+#include "hal_io.h"
+#include <hpl_usart_sync.h>
+
+/**
+ * \addtogroup doc_driver_hal_usart_sync
+ *
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Synchronous USART descriptor
+ */
+struct usart_sync_descriptor {
+	struct io_descriptor      io;
+	struct _usart_sync_device device;
+};
+
+/**
+ * \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 USART
+ * \param[in] hw The pointer to hardware instance
+ * \param[in] func The pointer to as set of functions pointers
+ *
+ * \return Initialization status.
+ */
+int32_t usart_sync_init(struct usart_sync_descriptor *const descr, void *const hw, 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_sync_deinit(struct usart_sync_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_sync_enable(struct usart_sync_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_sync_disable(struct usart_sync_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 the I/O descriptor retrieving.
+ */
+int32_t usart_sync_get_io_descriptor(struct usart_sync_descriptor *const descr, struct io_descriptor **io);
+
+/**
+ * \brief Specify action for flow control pins
+ *
+ * This function sets the action (or state) for the flow control pins
+ * if the flow control is enabled.
+ * It sets the state of flow control pins only if the 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_sync_set_flow_control(struct usart_sync_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_sync_set_baud_rate(struct usart_sync_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_sync_set_data_order(struct usart_sync_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_sync_set_mode(struct usart_sync_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_sync_set_parity(struct usart_sync_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_sync_set_stopbits(struct usart_sync_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_sync_set_character_size(struct usart_sync_descriptor *const descr, const enum usart_character_size size);
+
+/**
+ * \brief Retrieve the state of flow control pins
+ *
+ * This function retrieves the of flow control pins
+ * if the flow control is enabled.
+ * 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_sync_flow_control_status(const struct usart_sync_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_sync_is_tx_empty(const struct usart_sync_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 USART RX empty checking.
+ * \retval 1 The USART receiver is not empty
+ * \retval 0 The USART receiver is empty
+ */
+int32_t usart_sync_is_rx_not_empty(const struct usart_sync_descriptor *const descr);
+
+/**
+ * \brief Retrieve the current driver version
+ *
+ * \return Current driver version.
+ */
+uint32_t usart_sync_get_version(void);
+
+#ifdef __cplusplus
+}
+#endif
+/**@}*/
+#endif /* _HAL_SYNC_USART_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/include/hpl_i2c_m_async.h b/sysmoOCTSIM/hal/include/hpl_i2c_m_async.h
new file mode 100644
index 0000000..8a9491d
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_i2c_m_async.h
@@ -0,0 +1,205 @@
+/**
+ * \file
+ *
+ * \brief I2C Master Hardware Proxy Layer(HPL) declaration.
+ *
+ * Copyright (c) 2015-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 _HPL_I2C_M_ASYNC_H_INCLUDED
+#define _HPL_I2C_M_ASYNC_H_INCLUDED
+
+#include "hpl_i2c_m_sync.h"
+#include "hpl_irq.h"
+#include "utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief i2c master callback names
+ */
+enum _i2c_m_async_callback_type {
+	I2C_M_ASYNC_DEVICE_ERROR,
+	I2C_M_ASYNC_DEVICE_TX_COMPLETE,
+	I2C_M_ASYNC_DEVICE_RX_COMPLETE
+};
+
+struct _i2c_m_async_device;
+
+typedef void (*_i2c_complete_cb_t)(struct _i2c_m_async_device *i2c_dev);
+typedef void (*_i2c_error_cb_t)(struct _i2c_m_async_device *i2c_dev, int32_t errcode);
+
+/**
+ * \brief i2c callback pointers structure
+ */
+struct _i2c_m_async_callback {
+	_i2c_error_cb_t    error;
+	_i2c_complete_cb_t tx_complete;
+	_i2c_complete_cb_t rx_complete;
+};
+
+/**
+ * \brief i2c device structure
+ */
+struct _i2c_m_async_device {
+	struct _i2c_m_service        service;
+	void *                       hw;
+	struct _i2c_m_async_callback cb;
+	struct _irq_descriptor       irq;
+};
+
+/**
+ * \name HPL functions
+ */
+
+/**
+ * \brief Initialize I2C in interrupt mode
+ *
+ * This function does low level I2C configuration.
+ *
+ * \param[in] i2c_dev The pointer to i2c interrupt device structure
+ * \param[in] hw The pointer to hardware instance
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_async_init(struct _i2c_m_async_device *const i2c_dev, void *const hw);
+
+/**
+ * \brief Deinitialize I2C in interrupt mode
+ *
+ * \param[in] i2c_dev The pointer to i2c device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_async_deinit(struct _i2c_m_async_device *const i2c_dev);
+
+/**
+ * \brief Enable I2C module
+ *
+ * This function does low level I2C enable.
+ *
+ * \param[in] i2c_dev The pointer to i2c device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_async_enable(struct _i2c_m_async_device *const i2c_dev);
+
+/**
+ * \brief Disable I2C module
+ *
+ * This function does low level I2C disable.
+ *
+ * \param[in] i2c_dev The pointer to i2c device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_async_disable(struct _i2c_m_async_device *const i2c_dev);
+
+/**
+ * \brief Transfer data by I2C
+ *
+ * This function does low level I2C data transfer.
+ *
+ * \param[in] i2c_dev The pointer to i2c device structure
+ * \param[in] msg The pointer to i2c msg structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_async_transfer(struct _i2c_m_async_device *const i2c_dev, struct _i2c_m_msg *msg);
+
+/**
+ * \brief Set baud rate of I2C
+ *
+ * This function does low level I2C set baud rate.
+ *
+ * \param[in] i2c_dev The pointer to i2c device structure
+ * \param[in] clkrate The clock rate(KHz) input to i2c module
+ * \param[in] baudrate The demand baud rate(KHz) of i2c module
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_async_set_baudrate(struct _i2c_m_async_device *const i2c_dev, uint32_t clkrate, uint32_t baudrate);
+
+/**
+ * \brief Register callback to I2C
+ *
+ * This function does low level I2C callback register.
+ *
+ * \param[in] i2c_dev The pointer to i2c device structure
+ * \param[in] cb_type The callback type request
+ * \param[in] func The callback function pointer
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_async_register_callback(struct _i2c_m_async_device *i2c_dev, enum _i2c_m_async_callback_type cb_type,
+                                       FUNC_PTR func);
+
+/**
+ * \brief Generate stop condition on the I2C bus
+ *
+ * This function will generate a stop condition on the I2C bus
+ *
+ * \param[in] i2c_m_async_descriptor An i2c descriptor which is used to communicate through I2C
+ *
+ * \return Operation status
+ * \retval 0 Operation executed successfully
+ * \retval <0 Operation failed
+ */
+int32_t _i2c_m_async_send_stop(struct _i2c_m_async_device *const i2c_dev);
+
+/**
+ * \brief Returns the number of bytes left or not used in the I2C message buffer
+ *
+ * This function will return the number of bytes left (not written to the bus) or still free
+ * (not received from the bus) in the message buffer, depending on direction of transmission.
+ *
+ * \param[in] i2c_m_async_descriptor An i2c descriptor which is used to communicate through I2C
+ *
+ * \return Number of bytes or error code
+ * \retval >0 Positive number indicating bytes left
+ * \retval 0  Buffer is full/empty depending on direction
+ * \retval <0 Error code
+ */
+int32_t _i2c_m_async_get_bytes_left(struct _i2c_m_async_device *const i2c_dev);
+
+/**
+ * \brief Enable/disable I2C master interrupt
+ *
+ * param[in] device The pointer to I2C master device instance
+ * param[in] type The type of interrupt to disable/enable if applicable
+ * param[in] state Enable or disable
+ */
+void _i2c_m_async_set_irq_state(struct _i2c_m_async_device *const device, const enum _i2c_m_async_callback_type type,
+                                const bool state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sysmoOCTSIM/hal/include/hpl_i2c_m_sync.h b/sysmoOCTSIM/hal/include/hpl_i2c_m_sync.h
new file mode 100644
index 0000000..ce173ae
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_i2c_m_sync.h
@@ -0,0 +1,185 @@
+/**
+ * \file
+ *
+ * \brief I2C Master Hardware Proxy Layer(HPL) 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 _HPL_I2C_M_SYNC_H_INCLUDED
+#define _HPL_I2C_M_SYNC_H_INCLUDED
+
+#include <compiler.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief i2c flags
+ */
+#define I2C_M_RD 0x0001 /* read data, from slave to master */
+#define I2C_M_BUSY 0x0100
+#define I2C_M_TEN 0x0400   /* this is a ten bit chip address */
+#define I2C_M_SEVEN 0x0800 /* this is a seven bit chip address */
+#define I2C_M_FAIL 0x1000
+#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+
+/**
+ * \brief i2c Return codes
+ */
+#define I2C_OK 0                     /* Operation successful */
+#define I2C_ACK -1                   /* Received ACK from device on I2C bus */
+#define I2C_NACK -2                  /* Received NACK from device on I2C bus */
+#define I2C_ERR_ARBLOST -3           /* Arbitration lost */
+#define I2C_ERR_BAD_ADDRESS -4       /* Bad address */
+#define I2C_ERR_BUS -5               /* Bus error */
+#define I2C_ERR_BUSY -6              /* Device busy */
+#define I2c_ERR_PACKAGE_COLLISION -7 /* Package collision */
+
+/**
+ * \brief i2c I2C Modes
+ */
+#define I2C_STANDARD_MODE 0x00
+#define I2C_FASTMODE 0x01
+#define I2C_HIGHSPEED_MODE 0x02
+
+/**
+ * \brief i2c master message structure
+ */
+struct _i2c_m_msg {
+	uint16_t          addr;
+	volatile uint16_t flags;
+	int32_t           len;
+	uint8_t *         buffer;
+};
+
+/**
+ * \brief i2c master service
+ */
+struct _i2c_m_service {
+	struct _i2c_m_msg msg;
+	uint16_t          mode;
+	uint16_t          trise;
+};
+
+/**
+ * \brief i2c sync master device structure
+ */
+struct _i2c_m_sync_device {
+	struct _i2c_m_service service;
+	void *                hw;
+};
+
+/**
+ * \name HPL functions
+ */
+
+/**
+ * \brief Initialize I2C
+ *
+ * This function does low level I2C configuration.
+ *
+ * \param[in] i2c_dev The pointer to i2c device structure
+ * \param[in] hw The pointer to hardware instance
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_sync_init(struct _i2c_m_sync_device *const i2c_dev, void *const hw);
+
+/**
+ * \brief Deinitialize I2C
+ *
+ * \param[in] i2c_dev The pointer to i2c device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_sync_deinit(struct _i2c_m_sync_device *const i2c_dev);
+
+/**
+ * \brief Enable I2C module
+ *
+ * This function does low level I2C enable.
+ *
+ * \param[in] i2c_dev The pointer to i2c device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_sync_enable(struct _i2c_m_sync_device *const i2c_dev);
+
+/**
+ * \brief Disable I2C module
+ *
+ * This function does low level I2C disable.
+ *
+ * \param[in] i2c_dev The pointer to i2c device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_sync_disable(struct _i2c_m_sync_device *const i2c_dev);
+
+/**
+ * \brief Transfer data by I2C
+ *
+ * This function does low level I2C data transfer.
+ *
+ * \param[in] i2c_dev The pointer to i2c device structure
+ * \param[in] msg The pointer to i2c msg structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_sync_transfer(struct _i2c_m_sync_device *const i2c_dev, struct _i2c_m_msg *msg);
+
+/**
+ * \brief Set baud rate of I2C
+ *
+ * This function does low level I2C set baud rate.
+ *
+ * \param[in] i2c_dev The pointer to i2c device structure
+ * \param[in] clkrate The clock rate(KHz) input to i2c module
+ * \param[in] baudrate The demand baud rate(KHz) of i2c module
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_sync_set_baudrate(struct _i2c_m_sync_device *const i2c_dev, uint32_t clkrate, uint32_t baudrate);
+
+/**
+ * \brief Send send condition on the I2C bus
+ *
+ * This function will generate a stop condition on the I2C bus
+ *
+ * \param[in] i2c_dev The pointer to i2c device struct
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_m_sync_send_stop(struct _i2c_m_sync_device *const i2c_dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sysmoOCTSIM/hal/include/hpl_i2c_s_async.h b/sysmoOCTSIM/hal/include/hpl_i2c_s_async.h
new file mode 100644
index 0000000..92a5765
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_i2c_s_async.h
@@ -0,0 +1,184 @@
+/**
+ * \file
+ *
+ * \brief I2C Slave Hardware Proxy Layer(HPL) declaration.
+ *
+ * Copyright (c) 2015-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 _HPL_I2C_S_ASYNC_H_INCLUDED
+#define _HPL_I2C_S_ASYNC_H_INCLUDED
+
+#include "hpl_i2c_s_sync.h"
+#include "hpl_irq.h"
+#include "utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief i2c callback types
+ */
+enum _i2c_s_async_callback_type { I2C_S_DEVICE_ERROR, I2C_S_DEVICE_TX, I2C_S_DEVICE_RX_COMPLETE };
+
+/**
+ * \brief Forward declaration of I2C Slave device
+ */
+struct _i2c_s_async_device;
+
+/**
+ * \brief i2c slave callback function type
+ */
+typedef void (*_i2c_s_async_cb_t)(struct _i2c_s_async_device *device);
+
+/**
+ * \brief i2c slave callback pointers structure
+ */
+struct _i2c_s_async_callback {
+	void (*error)(struct _i2c_s_async_device *const device);
+	void (*tx)(struct _i2c_s_async_device *const device);
+	void (*rx_done)(struct _i2c_s_async_device *const device, const uint8_t data);
+};
+
+/**
+ * \brief i2c slave device structure
+ */
+struct _i2c_s_async_device {
+	void *                       hw;
+	struct _i2c_s_async_callback cb;
+	struct _irq_descriptor       irq;
+};
+
+/**
+ * \name HPL functions
+ */
+
+/**
+ * \brief Initialize asynchronous I2C slave
+ *
+ * This function does low level I2C configuration.
+ *
+ * \param[in] device The pointer to i2c interrupt device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_s_async_init(struct _i2c_s_async_device *const device, void *const hw);
+
+/**
+ * \brief Deinitialize asynchronous I2C in interrupt mode
+ *
+ * \param[in] device The pointer to i2c device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_s_async_deinit(struct _i2c_s_async_device *const device);
+
+/**
+ * \brief Enable I2C module
+ *
+ * This function does low level I2C enable.
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_s_async_enable(struct _i2c_s_async_device *const device);
+
+/**
+ * \brief Disable I2C module
+ *
+ * This function does low level I2C disable.
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_s_async_disable(struct _i2c_s_async_device *const device);
+
+/**
+ * \brief Check if 10-bit addressing mode is on
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ * \return Cheking status
+ * \retval 1 10-bit addressing mode is on
+ * \retval 0 10-bit addressing mode is off
+ */
+int32_t _i2c_s_async_is_10bit_addressing_on(const struct _i2c_s_async_device *const device);
+
+/**
+ * \brief Set I2C slave address
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ * \param[in] address Address to set
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_s_async_set_address(struct _i2c_s_async_device *const device, const uint16_t address);
+
+/**
+ * \brief Write a byte to the given I2C instance
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ * \param[in] data Data to write
+ */
+void _i2c_s_async_write_byte(struct _i2c_s_async_device *const device, const uint8_t data);
+
+/**
+ * \brief Retrieve I2C slave status
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ *\return I2C slave status
+ */
+i2c_s_status_t _i2c_s_async_get_status(const struct _i2c_s_async_device *const device);
+
+/**
+ * \brief Abort data transmission
+ *
+ * \param[in] device The pointer to i2c device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_s_async_abort_transmission(const struct _i2c_s_async_device *const device);
+
+/**
+ * \brief Enable/disable I2C slave interrupt
+ *
+ * param[in] device The pointer to I2C slave device instance
+ * param[in] type The type of interrupt to disable/enable if applicable
+ * param[in] disable Enable or disable
+ */
+int32_t _i2c_s_async_set_irq_state(struct _i2c_s_async_device *const device, const enum _i2c_s_async_callback_type type,
+                                   const bool disable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HPL_I2C_S_ASYNC_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/include/hpl_i2c_s_sync.h b/sysmoOCTSIM/hal/include/hpl_i2c_s_sync.h
new file mode 100644
index 0000000..93b5934
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_i2c_s_sync.h
@@ -0,0 +1,184 @@
+/**
+ * \file
+ *
+ * \brief I2C Slave Hardware Proxy Layer(HPL) declaration.
+ *
+ * Copyright (c) 2015-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 _HPL_I2C_S_SYNC_H_INCLUDED
+#define _HPL_I2C_S_SYNC_H_INCLUDED
+
+#include <compiler.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief I2C Slave status type
+ */
+typedef uint32_t i2c_s_status_t;
+
+/**
+ * \brief i2c slave device structure
+ */
+struct _i2c_s_sync_device {
+	void *hw;
+};
+
+#include <compiler.h>
+
+/**
+ * \name HPL functions
+ */
+
+/**
+ * \brief Initialize synchronous I2C slave
+ *
+ * This function does low level I2C configuration.
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_s_sync_init(struct _i2c_s_sync_device *const device, void *const hw);
+
+/**
+ * \brief Deinitialize synchronous I2C slave
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_s_sync_deinit(struct _i2c_s_sync_device *const device);
+
+/**
+ * \brief Enable I2C module
+ *
+ * This function does low level I2C enable.
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_s_sync_enable(struct _i2c_s_sync_device *const device);
+
+/**
+ * \brief Disable I2C module
+ *
+ * This function does low level I2C disable.
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_s_sync_disable(struct _i2c_s_sync_device *const device);
+
+/**
+ * \brief Check if 10-bit addressing mode is on
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ * \return Cheking status
+ * \retval 1 10-bit addressing mode is on
+ * \retval 0 10-bit addressing mode is off
+ */
+int32_t _i2c_s_sync_is_10bit_addressing_on(const struct _i2c_s_sync_device *const device);
+
+/**
+ * \brief Set I2C slave address
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ * \param[in] address Address to set
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_s_sync_set_address(struct _i2c_s_sync_device *const device, const uint16_t address);
+
+/**
+ * \brief Write a byte to the given I2C instance
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ * \param[in] data Data to write
+ */
+void _i2c_s_sync_write_byte(struct _i2c_s_sync_device *const device, const uint8_t data);
+
+/**
+ * \brief Retrieve I2C slave status
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ *\return I2C slave status
+ */
+i2c_s_status_t _i2c_s_sync_get_status(const struct _i2c_s_sync_device *const device);
+
+/**
+ * \brief Clear the Data Ready interrupt flag
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ * \return Return 0 for success and negative value for error
+ */
+int32_t _i2c_s_sync_clear_data_ready_flag(const struct _i2c_s_sync_device *const device);
+
+/**
+ * \brief Read a byte from the given I2C instance
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ * \return Data received via I2C interface.
+ */
+uint8_t _i2c_s_sync_read_byte(const struct _i2c_s_sync_device *const device);
+
+/**
+ * \brief Check if I2C is ready to send next byte
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ * \return Status of the ready check.
+ * \retval true if the I2C is ready to send next byte
+ * \retval false if the I2C is not ready to send next byte
+ */
+bool _i2c_s_sync_is_byte_sent(const struct _i2c_s_sync_device *const device);
+
+/**
+ * \brief Check if there is data received by I2C
+ *
+ * \param[in] device The pointer to i2c slave device structure
+ *
+ * \return Status of the data received check.
+ * \retval true if the I2C has received a byte
+ * \retval false if the I2C has not received a byte
+ */
+bool _i2c_s_sync_is_byte_received(const struct _i2c_s_sync_device *const device);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HPL_I2C_S_SYNC_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/include/hpl_spi.h b/sysmoOCTSIM/hal/include/hpl_spi.h
new file mode 100644
index 0000000..a5652e5
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_spi.h
@@ -0,0 +1,163 @@
+/**
+ * \file
+ *
+ * \brief SPI 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 _HPL_SPI_H_INCLUDED
+#define _HPL_SPI_H_INCLUDED
+
+#include <compiler.h>
+#include <utils.h>
+
+/**
+ * \addtogroup hpl_spi HPL SPI
+ *
+ *@{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief SPI Dummy char is used when reading data from the SPI slave
+ */
+#define SPI_DUMMY_CHAR 0x1ff
+
+/**
+ *  \brief SPI message to let driver to process
+ */
+//@{
+struct spi_msg {
+	/** Pointer to the output data buffer */
+	uint8_t *txbuf;
+	/** Pointer to the input data buffer */
+	uint8_t *rxbuf;
+	/** Size of the message data in SPI characters */
+	uint32_t size;
+};
+//@}
+
+/**
+ *  \brief SPI transfer modes
+ *  SPI transfer mode controls clock polarity and clock phase.
+ *  Mode 0: leading edge is rising edge, data sample on leading edge.
+ *  Mode 1: leading edge is rising edge, data sample on trailing edge.
+ *  Mode 2: leading edge is falling edge, data sample on leading edge.
+ *  Mode 3: leading edge is falling edge, data sample on trailing edge.
+ */
+enum spi_transfer_mode {
+	/** Leading edge is rising edge, data sample on leading edge. */
+	SPI_MODE_0,
+	/** Leading edge is rising edge, data sample on trailing edge. */
+	SPI_MODE_1,
+	/** Leading edge is falling edge, data sample on leading edge. */
+	SPI_MODE_2,
+	/** Leading edge is falling edge, data sample on trailing edge. */
+	SPI_MODE_3
+};
+
+/**
+ *  \brief SPI character sizes
+ *  The character size influence the way the data is sent/received.
+ *  For char size <= 8 data is stored byte by byte.
+ *  For char size between 9 ~ 16 data is stored in 2-byte length.
+ *  Note that the default and recommended char size is 8 bit since it's
+ *  supported by all system.
+ */
+enum spi_char_size {
+	/** Character size is 8 bit. */
+	SPI_CHAR_SIZE_8 = 0,
+	/** Character size is 9 bit. */
+	SPI_CHAR_SIZE_9 = 1,
+	/** Character size is 10 bit. */
+	SPI_CHAR_SIZE_10 = 2,
+	/** Character size is 11 bit. */
+	SPI_CHAR_SIZE_11 = 3,
+	/** Character size is 12 bit. */
+	SPI_CHAR_SIZE_12 = 4,
+	/** Character size is 13 bit. */
+	SPI_CHAR_SIZE_13 = 5,
+	/** Character size is 14 bit. */
+	SPI_CHAR_SIZE_14 = 6,
+	/** Character size is 15 bit. */
+	SPI_CHAR_SIZE_15 = 7,
+	/** Character size is 16 bit. */
+	SPI_CHAR_SIZE_16 = 8
+};
+
+/**
+ *  \brief SPI data order
+ */
+enum spi_data_order {
+	/** MSB goes first. */
+	SPI_DATA_ORDER_MSB_1ST = 0,
+	/** LSB goes first. */
+	SPI_DATA_ORDER_LSB_1ST = 1
+};
+
+/** \brief Transfer descriptor for SPI
+ *  Transfer descriptor holds TX and RX buffers
+ */
+struct spi_xfer {
+	/** Pointer to data buffer to TX */
+	uint8_t *txbuf;
+	/** Pointer to data buffer to RX */
+	uint8_t *rxbuf;
+	/** Size of data characters to TX & RX */
+	uint32_t size;
+};
+
+/** SPI generic driver. */
+struct spi_dev {
+	/** Pointer to the hardware base or private data for special device. */
+	void *prvt;
+	/** Reference start of sync/async variables */
+	uint32_t sync_async_misc[1];
+};
+
+/**
+ *  \brief Calculate the baudrate value for hardware to use to set baudrate
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] clk Clock frequency (Hz) for baudrate generation.
+ *  \param[in] baud Target baudrate (bps).
+ *  \return Error or baudrate value.
+ *  \retval >0 Baudrate value.
+ *  \retval ERR_INVALID_ARG Calculation fail.
+ */
+int32_t _spi_calc_baud_val(struct spi_dev *dev, const uint32_t clk, const uint32_t baud);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@}*/
+#endif /* ifndef _HPL_SPI_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/include/hpl_spi_async.h b/sysmoOCTSIM/hal/include/hpl_spi_async.h
new file mode 100644
index 0000000..8e5a848
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_spi_async.h
@@ -0,0 +1,131 @@
+/**
+ * \file
+ *
+ * \brief Common SPI related functionality declaration.
+ *
+ * Copyright (c) 2015-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 _HPL_SPI_ASYNC_H_INCLUDED
+#define _HPL_SPI_ASYNC_H_INCLUDED
+
+#include <hpl_spi.h>
+#include <hpl_irq.h>
+
+/**
+ * \addtogroup hpl_spi HPL SPI
+ *
+ *@{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  \brief Callbacks the SPI driver must offer in async mode
+ */
+//@{
+/** The callback types */
+enum _spi_async_dev_cb_type {
+	/** Callback type for transmit, see \ref _spi_async_dev_cb_xfer_t. */
+	SPI_DEV_CB_TX,
+	/** Callback type for receive, see \ref _spi_async_dev_cb_xfer_t. */
+	SPI_DEV_CB_RX,
+	/** Callback type for \ref _spi_async_dev_cb_complete_t. */
+	SPI_DEV_CB_COMPLETE,
+	/** Callback type for error */
+	SPI_DEV_CB_ERROR,
+	/** Number of callbacks. */
+	SPI_DEV_CB_N
+};
+
+struct _spi_async_dev;
+
+/** \brief The prototype for callback on SPI transfer error.
+ *  If status code is zero, it indicates the normal completion, that is,
+ *  SS deactivation.
+ *  If status code belows zero, it indicates complete.
+ */
+typedef void (*_spi_async_dev_cb_error_t)(struct _spi_async_dev *dev, int32_t status);
+
+/** \brief The prototype for callback on SPI transmit/receive event
+ *  For TX, the callback is invoked when transmit is done or ready to start
+ *  transmit.
+ *  For RX, the callback is invoked when receive is done or ready to read data,
+ *  see \ref _spi_async_dev_read_one_t on data reading.
+ *  Without DMA enabled, the callback is invoked on each character event.
+ *  With DMA enabled, the callback is invoked on DMA buffer done.
+ */
+typedef void (*_spi_async_dev_cb_xfer_t)(struct _spi_async_dev *dev);
+
+/**
+ *  \brief The callbacks offered by SPI driver
+ */
+struct _spi_async_dev_callbacks {
+	/** TX callback, see \ref _spi_async_dev_cb_xfer_t. */
+	_spi_async_dev_cb_xfer_t tx;
+	/** RX callback, see \ref _spi_async_dev_cb_xfer_t. */
+	_spi_async_dev_cb_xfer_t rx;
+	/** Complete or complete callback, see \ref _spi_async_dev_cb_complete_t. */
+	_spi_async_dev_cb_xfer_t complete;
+	/** Error callback, see \ref */
+	_spi_async_dev_cb_error_t err;
+};
+//@}
+
+/**
+ *  \brief SPI async driver
+ */
+//@{
+
+/** SPI driver to support async HAL */
+struct _spi_async_dev {
+	/** Pointer to the hardware base or private data for special device. */
+	void *prvt;
+	/** Data size, number of bytes for each character */
+	uint8_t char_size;
+	/** Dummy byte used in master mode when reading the slave */
+	uint16_t dummy_byte;
+
+	/** \brief Pointer to callback functions, ignored for polling mode
+	 *  Pointer to the callback functions so that initialize the driver to
+	 *  handle interrupts.
+	 */
+	struct _spi_async_dev_callbacks callbacks;
+	/** IRQ instance for SPI device. */
+	struct _irq_descriptor irq;
+};
+//@}
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@}*/
+#endif /* ifndef _HPL_SPI_ASYNC_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/include/hpl_spi_m_async.h b/sysmoOCTSIM/hal/include/hpl_spi_m_async.h
new file mode 100644
index 0000000..69dd435
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_spi_m_async.h
@@ -0,0 +1,238 @@
+/**
+ * \file
+ *
+ * \brief SPI Slave Async related functionality declaration.
+ *
+ * Copyright (c) 2015-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 _HPL_SPI_M_ASYNC_H_INCLUDED
+#define _HPL_SPI_M_ASYNC_H_INCLUDED
+
+#include <hpl_spi.h>
+#include <hpl_spi_async.h>
+
+/**
+ * \addtogroup hpl_spi HPL SPI
+ *
+ *
+ *@{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Uses common SPI async device driver. */
+#define _spi_m_async_dev _spi_async_dev
+
+#define _spi_m_async_dev_cb_type _spi_async_dev_cb_type
+
+/** Uses common SPI async device driver complete callback type. */
+#define _spi_m_async_dev_cb_error_t _spi_async_dev_cb_error_t
+
+/** Uses common SPI async device driver transfer callback type. */
+#define _spi_m_async_dev_cb_xfer_t _spi_async_dev_cb_xfer_t
+
+/**
+ *  \brief Initialize SPI for access with interrupts
+ *  It will load default hardware configuration and software struct.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] hw Pointer to the hardware base.
+ *  \retval ERR_INVALID_ARG Input parameter problem.
+ *  \retval ERR_BUSY SPI hardware not ready (resetting).
+ *  \retval ERR_DENIED SPI has been enabled.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_async_init(struct _spi_m_async_dev *dev, void *const hw);
+
+/**
+ *  \brief Initialize SPI for access with interrupts
+ *  Disable, reset the hardware and the software struct.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_async_deinit(struct _spi_m_async_dev *dev);
+
+/**
+ *  \brief Enable SPI for access with interrupts
+ *  Enable the SPI and enable callback generation of receive and error
+ *  interrupts.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG Input parameter problem.
+ *  \retval ERR_BUSY SPI hardware not ready (resetting).
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_async_enable(struct _spi_m_async_dev *dev);
+
+/**
+ *  \brief Disable SPI for access without interrupts
+ *  Disable SPI and interrupts. Deactivate all CS pins if works as master.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_async_disable(struct _spi_m_async_dev *dev);
+
+/**
+ *  \brief Set SPI transfer mode
+ *  Set SPI transfer mode (\ref spi_transfer_mode),
+ *  which controls clock polarity and clock phase.
+ *  Mode 0: leading edge is rising edge, data sample on leading edge.
+ *  Mode 1: leading edge is rising edge, data sample on trailing edge.
+ *  Mode 2: leading edge is falling edge, data sample on leading edge.
+ *  Mode 3: leading edge is falling edge, data sample on trailing edge.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] mode The SPI transfer mode.
+ *  \return Operation status.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_async_set_mode(struct _spi_m_async_dev *dev, const enum spi_transfer_mode mode);
+
+/**
+ *  \brief Set SPI baudrate
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] baud_val The SPI baudrate value, see \ref _spi_calc_baud_val() on
+ *                  how it's generated.
+ *  \return Operation status.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_async_set_baudrate(struct _spi_m_async_dev *dev, const uint32_t baud_val);
+
+/**
+ *  \brief Set SPI baudrate
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] char_size The character size, see \ref spi_char_size.
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG The character size is not supported.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_async_set_char_size(struct _spi_m_async_dev *dev, const enum spi_char_size char_size);
+
+/**
+ *  \brief Set SPI data order
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] dord SPI data order (LSB/MSB first).
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG The character size is not supported.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_async_set_data_order(struct _spi_m_async_dev *dev, const enum spi_data_order dord);
+
+/**
+ * \brief Enable interrupt on character output
+ *
+ * Enable interrupt when a new character can be written
+ * to the SPI device.
+ *
+ * \param[in] dev   Pointer to the SPI device instance
+ * \param[in] state true  = enable output interrupt
+ *                  false = disable output interrupt
+ *
+ * \return Status code
+ * \retval 0 Ok status
+ */
+int32_t _spi_m_async_enable_tx(struct _spi_m_async_dev *dev, bool state);
+
+/**
+ * \brief Enable interrupt on character input
+ *
+ * Enable interrupt when a new character is ready to be
+ * read from the SPI device.
+ *
+ * \param[in] dev  Pointer to the SPI device instance
+ * \param[in] state true  = enable input interrupts
+ *                  false = disable input interrupt
+ *
+ * \return Status code
+ * \retvat 0 OK Status
+ */
+int32_t _spi_m_async_enable_rx(struct _spi_m_async_dev *dev, bool state);
+
+/**
+ * \brief Enable interrupt on after data transmission complate
+ *
+ * \param[in] dev  Pointer to the SPI device instance
+ * \param[in] state true  = enable input interrupts
+ *                  false = disable input interrupt
+ *
+ * \return Status code
+ * \retvat 0 OK Status
+ */
+int32_t _spi_m_async_enable_tx_complete(struct _spi_m_async_dev *dev, bool state);
+
+/**
+ *  \brief Read one character to SPI device instance
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *
+ *  \return Character read from SPI module
+ */
+uint16_t _spi_m_async_read_one(struct _spi_m_async_dev *dev);
+
+/**
+ *  \brief Write one character to assigned buffer
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] data
+ *
+ *  \return Status code of write operation
+ *  \retval 0 Write operation OK
+ */
+int32_t _spi_m_async_write_one(struct _spi_m_async_dev *dev, uint16_t data);
+
+/**
+ *  \brief Register the SPI device callback
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] cb_type The callback type.
+ *  \param[in] func The callback function to register. NULL to disable callback.
+ *  \return Always 0.
+ */
+int32_t _spi_m_async_register_callback(struct _spi_m_async_dev *dev, const enum _spi_m_async_dev_cb_type cb_type,
+                                       const FUNC_PTR func);
+
+/**
+ * \brief Enable/disable SPI master interrupt
+ *
+ * param[in] device The pointer to SPI master device instance
+ * param[in] type The type of interrupt to disable/enable if applicable
+ * param[in] state Enable or disable
+ */
+void _spi_m_async_set_irq_state(struct _spi_m_async_dev *const device, const enum _spi_m_async_dev_cb_type type,
+                                const bool state);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@}*/
+#endif /* ifndef _HPL_SPI_M_ASYNC_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/include/hpl_spi_m_dma.h b/sysmoOCTSIM/hal/include/hpl_spi_m_dma.h
new file mode 100644
index 0000000..f481fb8
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_spi_m_dma.h
@@ -0,0 +1,177 @@
+/**
+ * \file
+ *
+ * \brief SPI Master DMA related functionality declaration.
+ *
+ * Copyright (c) 2016-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 _HPL_SPI_M_DMA_H_INCLUDED
+#define _HPL_SPI_M_DMA_H_INCLUDED
+
+#include <hpl_spi.h>
+#include <hpl_spi_dma.h>
+
+/**
+ * \addtogroup hpl_spi HPL SPI
+ *
+ *
+ *@{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Uses common SPI dma device driver. */
+#define _spi_m_dma_dev _spi_dma_dev
+
+#define _spi_m_dma_dev_cb_type _spi_dma_dev_cb_type
+
+/**
+ *  \brief Initialize SPI for access with interrupts
+ *  It will load default hardware configuration and software struct.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] hw Pointer to the hardware base.
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG Input parameter problem.
+ *  \retval ERR_BUSY SPI hardware not ready (resetting).
+ *  \retval ERR_DENIED SPI has been enabled.
+ *  \retval 0 ERR_NONE is operation done successfully.
+ */
+int32_t _spi_m_dma_init(struct _spi_m_dma_dev *dev, void *const hw);
+
+/**
+ *  \brief Initialize SPI for access with interrupts
+ *  Disable, reset the hardware and the software struct.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval 0 ERR_NONE is operation done successfully.
+ */
+int32_t _spi_m_dma_deinit(struct _spi_m_dma_dev *dev);
+
+/**
+ *  \brief Enable SPI for access with interrupts
+ *  Enable the SPI and enable callback generation of receive and error
+ *  interrupts.
+ *  \param[in] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG Input parameter problem.
+ *  \retval ERR_BUSY SPI hardware not ready (resetting).
+ *  \retval 0 ERR_NONE is operation done successfully.
+ */
+int32_t _spi_m_dma_enable(struct _spi_m_dma_dev *dev);
+
+/**
+ *  \brief Disable SPI for access without interrupts
+ *  Disable SPI and interrupts. Deactivate all CS pins if works as master.
+ *  \param[in] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval 0 ERR_NONE is operation done successfully.
+ */
+int32_t _spi_m_dma_disable(struct _spi_m_dma_dev *dev);
+
+/**
+ *  \brief Set SPI transfer mode
+ *  Set SPI transfer mode (\ref spi_transfer_mode),
+ *  which controls clock polarity and clock phase.
+ *  Mode 0: leading edge is rising edge, data sample on leading edge.
+ *  Mode 1: leading edge is rising edge, data sample on trailing edge.
+ *  Mode 2: leading edge is falling edge, data sample on leading edge.
+ *  Mode 3: leading edge is falling edge, data sample on trailing edge.
+ *  \param[in] dev Pointer to the SPI device instance.
+ *  \param[in] mode The SPI transfer mode.
+ *  \return Operation status.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 ERR_NONE is operation done successfully.
+ */
+int32_t _spi_m_dma_set_mode(struct _spi_m_dma_dev *dev, const enum spi_transfer_mode mode);
+
+/**
+ *  \brief Set SPI baudrate
+ *  \param[in] dev Pointer to the SPI device instance.
+ *  \param[in] baud_val The SPI baudrate value, see \ref _spi_calc_baud_val() on
+ *                  how it's generated.
+ *  \return Operation status.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_dma_set_baudrate(struct _spi_m_dma_dev *dev, const uint32_t baud_val);
+
+/**
+ *  \brief Set SPI baudrate
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] char_size The character size, see \ref spi_char_size.
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG The character size is not supported.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_dma_set_char_size(struct _spi_m_dma_dev *dev, const enum spi_char_size char_size);
+
+/**
+ *  \brief Set SPI data order
+ *  \param[in] dev Pointer to the SPI device instance.
+ *  \param[in] dord SPI data order (LSB/MSB first).
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG The character size is not supported.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_dma_set_data_order(struct _spi_m_dma_dev *dev, const enum spi_data_order dord);
+
+/**
+ *  \brief Register the SPI device callback
+ *  \param[in] dev Pointer to the SPI device instance.
+ *  \param[in] cb_type The callback type.
+ *  \param[in] func The callback function to register. NULL to disable callback.
+ *  \return Always 0.
+ */
+void _spi_m_dma_register_callback(struct _spi_m_dma_dev *dev, enum _spi_dma_dev_cb_type, _spi_dma_cb_t func);
+
+/** \brief Do SPI data transfer (TX & RX) with DMA
+ *  Log the TX & RX buffers and transfer them in background. It never blocks.
+ *
+ *  \param[in] dev Pointer to the SPI device instance.
+ *  \param[in] txbuf Pointer to the transfer information (\ref spi_transfer).
+ *  \param[out] rxbuf Pointer to the receiver information (\ref spi_receive).
+ *  \param[in] length spi transfer data length.
+ *
+ *  \return Operation status.
+ *  \retval ERR_NONE Success.
+ *  \retval ERR_BUSY Busy.
+ */
+int32_t _spi_m_dma_transfer(struct _spi_m_dma_dev *dev, uint8_t const *txbuf, uint8_t *const rxbuf,
+                            const uint16_t length);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@}*/
+#endif /* ifndef _HPL_SPI_M_DMA_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/include/hpl_spi_m_sync.h b/sysmoOCTSIM/hal/include/hpl_spi_m_sync.h
new file mode 100644
index 0000000..01e8fc3
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_spi_m_sync.h
@@ -0,0 +1,161 @@
+/**
+ * \file
+ *
+ * \brief SPI related functionality declaration.
+ *
+ * Copyright (c) 2015-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 _HPL_SPI_M_SYNC_H_INCLUDED
+#define _HPL_SPI_M_SYNC_H_INCLUDED
+
+#include <hpl_spi.h>
+#include <hpl_spi_sync.h>
+
+/**
+ * \addtogroup hpl_spi HPL SPI
+ *
+ *@{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Uses common SPI async device driver. */
+#define _spi_m_sync_dev _spi_sync_dev
+
+/**
+ *  \brief Initialize SPI for access without interrupts
+ *  It will load default hardware configuration and software struct.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] hw Pointer to the hardware base.
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG Input parameter problem.
+ *  \retval ERR_BUSY SPI hardware not ready (resetting).
+ *  \retval ERR_DENIED SPI has been enabled.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_sync_init(struct _spi_m_sync_dev *dev, void *const hw);
+
+/**
+ *  \brief Deinitialize SPI
+ *  Disable, reset the hardware and the software struct.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_sync_deinit(struct _spi_m_sync_dev *dev);
+
+/**
+ *  \brief Enable SPI for access without interrupts
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval ERR_BUSY SPI hardware not ready (resetting).
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_sync_enable(struct _spi_m_sync_dev *dev);
+
+/**
+ *  \brief Disable SPI for access without interrupts
+ *  Disable SPI. Deactivate all CS pins if works as master.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_sync_disable(struct _spi_m_sync_dev *dev);
+
+/**
+ *  \brief Set SPI transfer mode
+ *  Set SPI transfer mode (\ref spi_transfer_mode),
+ *  which controls clock polarity and clock phase.
+ *  Mode 0: leading edge is rising edge, data sample on leading edge.
+ *  Mode 1: leading edge is rising edge, data sample on trailing edge.
+ *  Mode 2: leading edge is falling edge, data sample on leading edge.
+ *  Mode 3: leading edge is falling edge, data sample on trailing edge.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] mode The SPI transfer mode.
+ *  \return Operation status.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_sync_set_mode(struct _spi_m_sync_dev *dev, const enum spi_transfer_mode mode);
+
+/**
+ *  \brief Set SPI baudrate
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] baud_val The SPI baudrate value, see \ref _spi_calc_baud_val() on
+ *                  how it's generated.
+ *  \return Operation status.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_sync_set_baudrate(struct _spi_m_sync_dev *dev, const uint32_t baud_val);
+
+/**
+ *  \brief Set SPI baudrate
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] char_size The character size, see \ref spi_char_size.
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG The character size is not supported.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_sync_set_char_size(struct _spi_m_sync_dev *dev, const enum spi_char_size char_size);
+
+/**
+ *  \brief Set SPI data order
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] dord SPI data order (LSB/MSB first).
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG The character size is not supported.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_m_sync_set_data_order(struct _spi_m_sync_dev *dev, const enum spi_data_order dord);
+
+/**
+ *  \brief Transfer the whole message without interrupt
+ *  Transfer the message, it will keep waiting until the message finish or
+ *  error.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] msg Pointer to the message instance to process.
+ *  \return Error or number of characters transferred.
+ *  \retval ERR_BUSY SPI hardware is not ready to start transfer (not
+ *                   enabled, busy applying settings, ...).
+ *  \retval SPI_ERR_OVERFLOW Overflow error.
+ *  \retval >=0 Number of characters transferred.
+ */
+int32_t _spi_m_sync_trans(struct _spi_m_sync_dev *dev, const struct spi_msg *msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@}*/
+#endif /* ifndef _HPL_SPI_M_SYNC_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/include/hpl_spi_s_async.h b/sysmoOCTSIM/hal/include/hpl_spi_s_async.h
new file mode 100644
index 0000000..2892e2c
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_spi_s_async.h
@@ -0,0 +1,227 @@
+/**
+ * \file
+ *
+ * \brief SPI Slave Async related functionality declaration.
+ *
+ * Copyright (c) 2015-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 _HPL_SPI_S_ASYNC_H_INCLUDED
+#define _HPL_SPI_S_ASYNC_H_INCLUDED
+
+#include <hpl_spi_async.h>
+
+/**
+ * \addtogroup hpl_spi HPL SPI
+ *
+ *
+ *@{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Uses common SPI async device driver. */
+#define _spi_s_async_dev _spi_async_dev
+
+#define _spi_s_async_dev_cb_type _spi_async_dev_cb_type
+
+/** Uses common SPI async device driver complete callback type. */
+#define _spi_m_async_dev_cb_error_t _spi_async_dev_cb_error_t
+
+/** Uses common SPI async device driver transfer callback type. */
+#define _spi_s_async_dev_cb_xfer_t _spi_async_dev_cb_xfer_t
+
+/**
+ *  \brief Initialize SPI for access with interrupts
+ *  It will load default hardware configuration and software struct.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] hw Pointer to the hardware base.
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG Input parameter problem.
+ *  \retval ERR_BUSY SPI hardware not ready (resetting).
+ *  \retval ERR_DENIED SPI has been enabled.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_async_init(struct _spi_s_async_dev *dev, void *const hw);
+
+/**
+ *  \brief Initialize SPI for access with interrupts
+ *  Disable, reset the hardware and the software struct.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_async_deinit(struct _spi_s_async_dev *dev);
+
+/**
+ *  \brief Enable SPI for access with interrupts
+ *  Enable the SPI and enable callback generation of receive and error
+ *  interrupts.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG Input parameter problem.
+ *  \retval ERR_BUSY SPI hardware not ready (resetting).
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_async_enable(struct _spi_s_async_dev *dev);
+
+/**
+ *  \brief Disable SPI for access without interrupts
+ *  Disable SPI and interrupts. Deactivate all CS pins if works as master.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_async_disable(struct _spi_s_async_dev *dev);
+
+/**
+ *  \brief Set SPI transfer mode
+ *  Set SPI transfer mode (\ref spi_transfer_mode),
+ *  which controls clock polarity and clock phase.
+ *  Mode 0: leading edge is rising edge, data sample on leading edge.
+ *  Mode 1: leading edge is rising edge, data sample on trailing edge.
+ *  Mode 2: leading edge is falling edge, data sample on leading edge.
+ *  Mode 3: leading edge is falling edge, data sample on trailing edge.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] mode The SPI transfer mode.
+ *  \return Operation status.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_async_set_mode(struct _spi_s_async_dev *dev, const enum spi_transfer_mode mode);
+
+/**
+ *  \brief Set SPI baudrate
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] char_size The character size, see \ref spi_char_size.
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG The character size is not supported.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_async_set_char_size(struct _spi_s_async_dev *dev, const enum spi_char_size char_size);
+
+/**
+ *  \brief Set SPI data order
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] dord SPI data order (LSB/MSB first).
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG The character size is not supported.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_async_set_data_order(struct _spi_s_async_dev *dev, const enum spi_data_order dord);
+
+/**
+ * \brief Enable interrupt on character output
+ *
+ * Enable interrupt when a new character can be written
+ * to the SPI device.
+ *
+ * \param[in] dev   Pointer to the SPI device instance
+ * \param[in] state true  = enable output interrupt
+ *                  false = disable output interrupt
+ *
+ * \return Status code
+ * \retval 0 Ok status
+ */
+int32_t _spi_s_async_enable_tx(struct _spi_s_async_dev *dev, bool state);
+
+/**
+ * \brief Enable interrupt on character input
+ *
+ * Enable interrupt when a new character is ready to be
+ * read from the SPI device.
+ *
+ * \param[in] dev  Pointer to the SPI device instance
+ * \param[in] state true  = enable input interrupts
+ *                  false = disable input interrupt
+ *
+ * \return Status code
+ * \retvat 0 OK Status
+ */
+int32_t _spi_s_async_enable_rx(struct _spi_s_async_dev *dev, bool state);
+
+/**
+ * \brief Enable interrupt on Slave Select (SS) rising
+ *
+ * \param[in] dev  Pointer to the SPI device instance
+ * \param[in] state true  = enable input interrupts
+ *                  false = disable input interrupt
+ *
+ * \return Status code
+ * \retvat 0 OK Status
+ */
+int32_t _spi_s_async_enable_ss_detect(struct _spi_s_async_dev *dev, bool state);
+
+/**
+ *  \brief Read one character to SPI device instance
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *
+ *  \return Character read from SPI module
+ */
+uint16_t _spi_s_async_read_one(struct _spi_s_async_dev *dev);
+
+/**
+ *  \brief Write one character to assigned buffer
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] data
+ *
+ *  \return Status code of write operation
+ *  \retval 0 Write operation OK
+ */
+int32_t _spi_s_async_write_one(struct _spi_s_async_dev *dev, uint16_t data);
+
+/**
+ *  \brief Register the SPI device callback
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] cb_type The callback type.
+ *  \param[in] func The callback function to register. NULL to disable callback.
+ *  \return Always 0.
+ */
+int32_t _spi_s_async_register_callback(struct _spi_s_async_dev *dev, const enum _spi_s_async_dev_cb_type cb_type,
+                                       const FUNC_PTR func);
+
+/**
+ * \brief Enable/disable SPI slave interrupt
+ *
+ * param[in] device The pointer to SPI slave device instance
+ * param[in] type The type of interrupt to disable/enable if applicable
+ * param[in] state Enable or disable
+ */
+void _spi_s_async_set_irq_state(struct _spi_s_async_dev *const device, const enum _spi_async_dev_cb_type type,
+                                const bool state);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@}*/
+#endif /* ifndef _HPL_SPI_S_ASYNC_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/include/hpl_spi_s_sync.h b/sysmoOCTSIM/hal/include/hpl_spi_s_sync.h
new file mode 100644
index 0000000..4fda095
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_spi_s_sync.h
@@ -0,0 +1,227 @@
+/**
+ * \file
+ *
+ * \brief SPI related functionality declaration.
+ *
+ * Copyright (c) 2015-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 _HPL_SPI_S_SYNC_H_INCLUDED
+#define _HPL_SPI_S_SYNC_H_INCLUDED
+
+#include <hpl_spi_sync.h>
+
+/**
+ * \addtogroup hpl_spi HPL SPI
+ *
+ *@{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Uses common SPI async device driver. */
+#define _spi_s_sync_dev _spi_sync_dev
+
+/**
+ *  \brief Initialize SPI for access without interrupts
+ *  It will load default hardware configuration and software struct.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] hw Pointer to the hardware base.
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG Input parameter problem.
+ *  \retval ERR_BUSY SPI hardware not ready (resetting).
+ *  \retval ERR_DENIED SPI has been enabled.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_sync_init(struct _spi_s_sync_dev *dev, void *const hw);
+
+/**
+ *  \brief Initialize SPI for access with interrupts
+ *  Disable, reset the hardware and the software struct.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_sync_deinit(struct _spi_s_sync_dev *dev);
+
+/**
+ *  \brief Enable SPI for access without interrupts
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval ERR_BUSY SPI hardware not ready (resetting).
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_sync_enable(struct _spi_s_sync_dev *dev);
+
+/**
+ *  \brief Disable SPI for access without interrupts
+ *  Disable SPI. Deactivate all CS pins if works as master.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \return Operation status.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_sync_disable(struct _spi_s_sync_dev *dev);
+
+/**
+ *  \brief Set SPI transfer mode
+ *  Set SPI transfer mode (\ref spi_transfer_mode),
+ *  which controls clock polarity and clock phase.
+ *  Mode 0: leading edge is rising edge, data sample on leading edge.
+ *  Mode 1: leading edge is rising edge, data sample on trailing edge.
+ *  Mode 2: leading edge is falling edge, data sample on leading edge.
+ *  Mode 3: leading edge is falling edge, data sample on trailing edge.
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] mode The SPI transfer mode.
+ *  \return Operation status.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_sync_set_mode(struct _spi_s_sync_dev *dev, const enum spi_transfer_mode mode);
+
+/**
+ *  \brief Set SPI baudrate
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] char_size The character size, see \ref spi_char_size.
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG The character size is not supported.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_sync_set_char_size(struct _spi_s_sync_dev *dev, const enum spi_char_size char_size);
+
+/**
+ *  \brief Set SPI data order
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] dord SPI data order (LSB/MSB first).
+ *  \return Operation status.
+ *  \retval ERR_INVALID_ARG The character size is not supported.
+ *  \retval ERR_BUSY SPI is not ready to accept new setting.
+ *  \retval 0 Operation done successfully.
+ */
+int32_t _spi_s_sync_set_data_order(struct _spi_s_sync_dev *dev, const enum spi_data_order dord);
+
+/**
+ * \brief Enable interrupt on character output
+ *
+ * Enable interrupt when a new character can be written
+ * to the SPI device.
+ *
+ * \param[in] dev   Pointer to the SPI device instance
+ * \param[in] state true  = enable output interrupt
+ *                  false = disable output interrupt
+ *
+ * \return Status code
+ * \retval 0 Ok status
+ */
+int32_t _spi_s_sync_enable_tx(struct _spi_s_sync_dev *dev, bool state);
+
+/**
+ * \brief Enable interrupt on character input
+ *
+ * Enable interrupt when a new character is ready to be
+ * read from the SPI device.
+ *
+ * \param[in] dev  Pointer to the SPI device instance
+ * \param[in] state true  = enable input interrupts
+ *                  false = disable input interrupt
+ *
+ * \return Status code
+ * \retval 0 OK Status
+ */
+int32_t _spi_s_sync_enable_rx(struct _spi_s_sync_dev *dev, bool state);
+
+/**
+ *  \brief Read one character to SPI device instance
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *
+ *  \return Character read from SPI module
+ */
+uint16_t _spi_s_sync_read_one(struct _spi_s_sync_dev *dev);
+
+/**
+ *  \brief Write one character to assigned buffer
+ *  \param[in, out] dev Pointer to the SPI device instance.
+ *  \param[in] data
+ *
+ *  \return Status code of write operation
+ *  \retval 0 Write operation OK
+ */
+int32_t _spi_s_sync_write_one(struct _spi_s_sync_dev *dev, uint16_t data);
+
+/**
+ * \brief Check if TX ready
+ *
+ * \param[in] dev  Pointer to the SPI device instance
+ *
+ * \return TX ready state
+ * \retval true TX ready
+ * \retval false TX not ready
+ */
+bool _spi_s_sync_is_tx_ready(struct _spi_s_sync_dev *dev);
+
+/**
+ * \brief Check if RX character ready
+ *
+ * \param[in] dev  Pointer to the SPI device instance
+ *
+ * \return RX character ready state
+ * \retval true RX character ready
+ * \retval false RX character not ready
+ */
+bool _spi_s_sync_is_rx_ready(struct _spi_s_sync_dev *dev);
+
+/**
+ * \brief Check if SS deactiviation detected
+ *
+ * \param[in] dev  Pointer to the SPI device instance
+ *
+ * \return SS deactiviation state
+ * \retval true SS deactiviation detected
+ * \retval false SS deactiviation not detected
+ */
+bool _spi_s_sync_is_ss_deactivated(struct _spi_s_sync_dev *dev);
+
+/**
+ * \brief Check if error is detected
+ *
+ * \param[in] dev  Pointer to the SPI device instance
+ *
+ * \return Error detection state
+ * \retval true Error detected
+ * \retval false Error not detected
+ */
+bool _spi_s_sync_is_error(struct _spi_s_sync_dev *dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@}*/
+#endif /* ifndef _HPL_SPI_S_SYNC_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/include/hpl_spi_sync.h b/sysmoOCTSIM/hal/include/hpl_spi_sync.h
new file mode 100644
index 0000000..dc88648
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_spi_sync.h
@@ -0,0 +1,70 @@
+/**
+ * \file
+ *
+ * \brief Common SPI related functionality declaration.
+ *
+ * Copyright (c) 2015-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 _HPL_SPI_SYNC_H_INCLUDED
+#define _HPL_SPI_SYNC_H_INCLUDED
+
+#include <compiler.h>
+#include <utils.h>
+
+#include <hpl_spi.h>
+
+/**
+ * \addtogroup hpl_spi HPL SPI
+ *
+ * \section hpl_spi_rev Revision History
+ * - v1.0.0 Initial Release
+ *
+ *@{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** SPI driver to support sync HAL */
+struct _spi_sync_dev {
+	/** Pointer to the hardware base or private data for special device. */
+	void *prvt;
+	/** Data size, number of bytes for each character */
+	uint8_t char_size;
+	/** Dummy byte used in master mode when reading the slave */
+	uint16_t dummy_byte;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@}*/
+#endif /* ifndef _HPL_SPI_SYNC_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/include/hpl_usart.h b/sysmoOCTSIM/hal/include/hpl_usart.h
new file mode 100644
index 0000000..0e09501
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_usart.h
@@ -0,0 +1,113 @@
+/**
+ * \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 _HPL_USART_H_INCLUDED
+#define _HPL_USART_H_INCLUDED
+
+/**
+ * \addtogroup HPL USART SYNC
+ *
+ * \section hpl_usart_sync_rev Revision History
+ * - v1.0.0 Initial Release
+ *
+ *@{
+ */
+
+#include <compiler.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief USART flow control state
+ */
+union usart_flow_control_state {
+	struct {
+		uint8_t cts : 1;
+		uint8_t rts : 1;
+		uint8_t unavailable : 1;
+		uint8_t reserved : 5;
+	} bit;
+	uint8_t value;
+};
+
+/**
+ * \brief USART baud rate mode
+ */
+enum usart_baud_rate_mode { USART_BAUDRATE_ASYNCH_ARITHMETIC, USART_BAUDRATE_ASYNCH_FRACTIONAL, USART_BAUDRATE_SYNCH };
+
+/**
+ * \brief USART data order
+ */
+enum usart_data_order { USART_DATA_ORDER_MSB = 0, USART_DATA_ORDER_LSB = 1 };
+
+/**
+ * \brief USART mode
+ */
+enum usart_mode { USART_MODE_ASYNCHRONOUS = 0, USART_MODE_SYNCHRONOUS = 1 };
+
+/**
+ * \brief USART parity
+ */
+enum usart_parity {
+	USART_PARITY_EVEN  = 0,
+	USART_PARITY_ODD   = 1,
+	USART_PARITY_NONE  = 2,
+	USART_PARITY_SPACE = 3,
+	USART_PARITY_MARK  = 4
+};
+
+/**
+ * \brief USART stop bits mode
+ */
+enum usart_stop_bits { USART_STOP_BITS_ONE = 0, USART_STOP_BITS_TWO = 1, USART_STOP_BITS_ONE_P_FIVE = 2 };
+
+/**
+ * \brief USART character size
+ */
+enum usart_character_size {
+	USART_CHARACTER_SIZE_8BITS = 0,
+	USART_CHARACTER_SIZE_9BITS = 1,
+	USART_CHARACTER_SIZE_5BITS = 5,
+	USART_CHARACTER_SIZE_6BITS = 6,
+	USART_CHARACTER_SIZE_7BITS = 7
+};
+
+//@}
+
+#ifdef __cplusplus
+}
+#endif
+/**@}*/
+#endif /* _HPL_USART_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/include/hpl_usart_async.h b/sysmoOCTSIM/hal/include/hpl_usart_async.h
new file mode 100644
index 0000000..3f833d1
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_usart_async.h
@@ -0,0 +1,270 @@
+/**
+ * \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 _HPL_USART_ASYNC_H_INCLUDED
+#define _HPL_USART_ASYNC_H_INCLUDED
+
+/**
+ * \addtogroup HPL USART
+ *
+ * \section hpl_usart_rev Revision History
+ * - v1.0.0 Initial Release
+ *
+ *@{
+ */
+
+#include "hpl_usart.h"
+#include "hpl_irq.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief USART callback types
+ */
+enum _usart_async_callback_type { USART_ASYNC_BYTE_SENT, USART_ASYNC_RX_DONE, USART_ASYNC_TX_DONE, USART_ASYNC_ERROR };
+
+/**
+ * \brief USART device structure
+ *
+ * The USART device structure forward declaration.
+ */
+struct _usart_async_device;
+
+/**
+ * \brief USART interrupt callbacks
+ */
+struct _usart_async_callbacks {
+	void (*tx_byte_sent)(struct _usart_async_device *device);
+	void (*rx_done_cb)(struct _usart_async_device *device, uint8_t data);
+	void (*tx_done_cb)(struct _usart_async_device *device);
+	void (*error_cb)(struct _usart_async_device *device);
+};
+
+/**
+ * \brief USART descriptor device structure
+ */
+struct _usart_async_device {
+	struct _usart_async_callbacks usart_cb;
+	struct _irq_descriptor        irq;
+	void *                        hw;
+};
+/**
+ * \name HPL functions
+ */
+//@{
+/**
+ * \brief Initialize asynchronous USART
+ *
+ * This function does low level USART configuration.
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] hw The pointer to hardware instance
+ *
+ * \return Initialization status
+ */
+int32_t _usart_async_init(struct _usart_async_device *const device, void *const hw);
+
+/**
+ * \brief Deinitialize USART
+ *
+ * This function closes the given USART by disabling its clock.
+ *
+ * \param[in] device The pointer to USART device instance
+ */
+void _usart_async_deinit(struct _usart_async_device *const device);
+
+/**
+ * \brief Enable usart module
+ *
+ * This function will enable the usart module
+ *
+ * \param[in] device The pointer to USART device instance
+ */
+void _usart_async_enable(struct _usart_async_device *const device);
+
+/**
+ * \brief Disable usart module
+ *
+ * This function will disable the usart module
+ *
+ * \param[in] device The pointer to USART device instance
+ */
+void _usart_async_disable(struct _usart_async_device *const device);
+
+/**
+ * \brief Calculate baud rate register value
+ *
+ * \param[in] baud Required baud rate
+ * \param[in] clock_rate clock frequency
+ * \param[in] samples The number of samples
+ * \param[in] mode USART mode
+ * \param[in] fraction A fraction value
+ *
+ * \return Calculated baud rate register value
+ */
+uint16_t _usart_async_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
+                                          const enum usart_baud_rate_mode mode, const uint8_t fraction);
+
+/**
+ * \brief Set baud rate
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] baud_rate A baud rate to set
+ */
+void _usart_async_set_baud_rate(struct _usart_async_device *const device, const uint32_t baud_rate);
+
+/**
+ * \brief Set data order
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] order A data order to set
+ */
+void _usart_async_set_data_order(struct _usart_async_device *const device, const enum usart_data_order order);
+
+/**
+ * \brief Set mode
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] mode A mode to set
+ */
+void _usart_async_set_mode(struct _usart_async_device *const device, const enum usart_mode mode);
+
+/**
+ * \brief Set parity
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] parity A parity to set
+ */
+void _usart_async_set_parity(struct _usart_async_device *const device, const enum usart_parity parity);
+
+/**
+ * \brief Set stop bits mode
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] stop_bits A stop bits mode to set
+ */
+void _usart_async_set_stop_bits(struct _usart_async_device *const device, const enum usart_stop_bits stop_bits);
+
+/**
+ * \brief Set character size
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] size A character size to set
+ */
+void _usart_async_set_character_size(struct _usart_async_device *const device, const enum usart_character_size size);
+
+/**
+ * \brief Retrieve usart status
+ *
+ * \param[in] device The pointer to USART device instance
+ */
+uint32_t _usart_async_get_status(const struct _usart_async_device *const device);
+
+/**
+ * \brief Write a byte to the given USART instance
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] data Data to write
+ */
+void _usart_async_write_byte(struct _usart_async_device *const device, uint8_t data);
+
+/**
+ * \brief Check if USART is ready to send next byte
+ *
+ * \param[in] device The pointer to USART device instance
+ *
+ * \return Status of the ready check.
+ * \retval true if the USART is ready to send next byte
+ * \retval false if the USART is not ready to send next byte
+ */
+bool _usart_async_is_byte_sent(const struct _usart_async_device *const device);
+
+/**
+ * \brief Set the state of flow control pins
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] state - A state of flow control pins to set
+ */
+void _usart_async_set_flow_control_state(struct _usart_async_device *const    device,
+                                         const union usart_flow_control_state state);
+
+/**
+ * \brief Retrieve the state of flow control pins
+ *
+ * This function retrieves the of flow control pins.
+ *
+ * \return USART_FLOW_CONTROL_STATE_UNAVAILABLE.
+ */
+union usart_flow_control_state _usart_async_get_flow_control_state(const struct _usart_async_device *const device);
+
+/**
+ * \brief Enable data register empty interrupt
+ *
+ * \param[in] device The pointer to USART device instance
+ */
+void _usart_async_enable_byte_sent_irq(struct _usart_async_device *const device);
+
+/**
+ * \brief Enable transmission complete interrupt
+ *
+ * \param[in] device The pointer to USART device instance
+ */
+void _usart_async_enable_tx_done_irq(struct _usart_async_device *const device);
+
+/**
+ * \brief Retrieve ordinal number of the given USART hardware instance
+ *
+ * \param[in] device The pointer to USART device instance
+ *
+ * \return The ordinal number of the given USART hardware instance
+ */
+uint8_t _usart_async_get_hardware_index(const struct _usart_async_device *const device);
+
+/**
+ * \brief Enable/disable USART interrupt
+ *
+ * param[in] device The pointer to USART device instance
+ * param[in] type The type of interrupt to disable/enable if applicable
+ * param[in] state Enable or disable
+ */
+void _usart_async_set_irq_state(struct _usart_async_device *const device, const enum _usart_async_callback_type type,
+                                const bool state);
+//@}
+
+#ifdef __cplusplus
+}
+#endif
+/**@}*/
+#endif /* _HPL_USART_ASYNC_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/include/hpl_usart_sync.h b/sysmoOCTSIM/hal/include/hpl_usart_sync.h
new file mode 100644
index 0000000..abc7264
--- /dev/null
+++ b/sysmoOCTSIM/hal/include/hpl_usart_sync.h
@@ -0,0 +1,254 @@
+/**
+ * \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 _HPL_SYNC_USART_H_INCLUDED
+#define _HPL_SYNC_USART_H_INCLUDED
+
+/**
+ * \addtogroup HPL USART SYNC
+ *
+ * \section hpl_usart_sync_rev Revision History
+ * - v1.0.0 Initial Release
+ *
+ *@{
+ */
+
+#include <hpl_usart.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief USART descriptor device structure
+ */
+struct _usart_sync_device {
+	void *hw;
+};
+
+/**
+ * \name HPL functions
+ */
+//@{
+/**
+ * \brief Initialize synchronous USART
+ *
+ * This function does low level USART configuration.
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] hw The pointer to hardware instance
+ *
+ * \return Initialization status
+ */
+int32_t _usart_sync_init(struct _usart_sync_device *const device, void *const hw);
+
+/**
+ * \brief Deinitialize USART
+ *
+ * This function closes the given USART by disabling its clock.
+ *
+ * \param[in] device The pointer to USART device instance
+ */
+void _usart_sync_deinit(struct _usart_sync_device *const device);
+
+/**
+ * \brief Enable usart module
+ *
+ * This function will enable the usart module
+ *
+ * \param[in] device The pointer to USART device instance
+ */
+void _usart_sync_enable(struct _usart_sync_device *const device);
+
+/**
+ * \brief Disable usart module
+ *
+ * This function will disable the usart module
+ *
+ * \param[in] device The pointer to USART device instance
+ */
+void _usart_sync_disable(struct _usart_sync_device *const device);
+
+/**
+ * \brief Calculate baud rate register value
+ *
+ * \param[in] baud Required baud rate
+ * \param[in] clock_rate clock frequency
+ * \param[in] samples The number of samples
+ * \param[in] mode USART mode
+ * \param[in] fraction A fraction value
+ *
+ * \return Calculated baud rate register value
+ */
+uint16_t _usart_sync_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
+                                         const enum usart_baud_rate_mode mode, const uint8_t fraction);
+
+/**
+ * \brief Set baud rate
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] baud_rate A baud rate to set
+ */
+void _usart_sync_set_baud_rate(struct _usart_sync_device *const device, const uint32_t baud_rate);
+
+/**
+ * \brief Set data order
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] order A data order to set
+ */
+void _usart_sync_set_data_order(struct _usart_sync_device *const device, const enum usart_data_order order);
+
+/**
+ * \brief Set mode
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] mode A mode to set
+ */
+void _usart_sync_set_mode(struct _usart_sync_device *const device, const enum usart_mode mode);
+
+/**
+ * \brief Set parity
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] parity A parity to set
+ */
+void _usart_sync_set_parity(struct _usart_sync_device *const device, const enum usart_parity parity);
+
+/**
+ * \brief Set stop bits mode
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] stop_bits A stop bits mode to set
+ */
+void _usart_sync_set_stop_bits(struct _usart_sync_device *const device, const enum usart_stop_bits stop_bits);
+
+/**
+ * \brief Set character size
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] size A character size to set
+ */
+void _usart_sync_set_character_size(struct _usart_sync_device *const device, const enum usart_character_size size);
+
+/**
+ * \brief Retrieve usart status
+ *
+ * \param[in] device The pointer to USART device instance
+ */
+uint32_t _usart_sync_get_status(const struct _usart_sync_device *const device);
+
+/**
+ * \brief Write a byte to the given USART instance
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] data Data to write
+ */
+void _usart_sync_write_byte(struct _usart_sync_device *const device, uint8_t data);
+
+/**
+ * \brief Read a byte from the given USART instance
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] data Data to write
+ *
+ * \return Data received via USART interface.
+ */
+uint8_t _usart_sync_read_byte(const struct _usart_sync_device *const device);
+
+/**
+ * \brief Check if USART is ready to send next byte
+ *
+ * \param[in] device The pointer to USART device instance
+ *
+ * \return Status of the ready check.
+ * \retval true if the USART is ready to send next byte
+ * \retval false if the USART is not ready to send next byte
+ */
+bool _usart_sync_is_ready_to_send(const struct _usart_sync_device *const device);
+
+/**
+ * \brief Check if USART transmitter has sent the byte
+ *
+ * \param[in] device The pointer to USART device instance
+ *
+ * \return Status of the ready check.
+ * \retval true if the USART transmitter has sent the byte
+ * \retval false if the USART transmitter has not send the byte
+ */
+bool _usart_sync_is_transmit_done(const struct _usart_sync_device *const device);
+
+/**
+ * \brief Check if there is data received by USART
+ *
+ * \param[in] device The pointer to USART device instance
+ *
+ * \return Status of the data received check.
+ * \retval true if the USART has received a byte
+ * \retval false if the USART has not received a byte
+ */
+bool _usart_sync_is_byte_received(const struct _usart_sync_device *const device);
+
+/**
+ * \brief Set the state of flow control pins
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] state - A state of flow control pins to set
+ */
+void _usart_sync_set_flow_control_state(struct _usart_sync_device *const     device,
+                                        const union usart_flow_control_state state);
+
+/**
+ * \brief Retrieve the state of flow control pins
+ *
+ * This function retrieves the of flow control pins.
+ *
+ * \return USART_FLOW_CONTROL_STATE_UNAVAILABLE.
+ */
+union usart_flow_control_state _usart_sync_get_flow_control_state(const struct _usart_sync_device *const device);
+
+/**
+ * \brief Retrieve ordinal number of the given USART hardware instance
+ *
+ * \param[in] device The pointer to USART device instance
+ *
+ * \return The ordinal number of the given USART hardware instance
+ */
+uint8_t _usart_sync_get_hardware_index(const struct _usart_sync_device *const device);
+//@}
+
+#ifdef __cplusplus
+}
+#endif
+/**@}*/
+#endif /* _HPL_SYNC_USART_H_INCLUDED */
diff --git a/sysmoOCTSIM/hal/src/hal_usart_sync.c b/sysmoOCTSIM/hal/src/hal_usart_sync.c
new file mode 100644
index 0000000..ab99c1d
--- /dev/null
+++ b/sysmoOCTSIM/hal/src/hal_usart_sync.c
@@ -0,0 +1,276 @@
+/**
+ * \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_sync.h"
+#include <utils_assert.h>
+#include <utils.h>
+
+/**
+ * \brief Driver version
+ */
+#define DRIVER_VERSION 0x00000001u
+
+static int32_t usart_sync_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length);
+static int32_t usart_sync_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length);
+
+/**
+ * \brief Initialize usart interface
+ */
+int32_t usart_sync_init(struct usart_sync_descriptor *const descr, void *const hw, void *const func)
+{
+	int32_t init_status;
+	ASSERT(descr && hw);
+	init_status = _usart_sync_init(&descr->device, hw);
+	if (init_status) {
+		return init_status;
+	}
+
+	descr->io.read  = usart_sync_read;
+	descr->io.write = usart_sync_write;
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Uninitialize usart interface
+ */
+int32_t usart_sync_deinit(struct usart_sync_descriptor *const descr)
+{
+	ASSERT(descr);
+	_usart_sync_deinit(&descr->device);
+
+	descr->io.read  = NULL;
+	descr->io.write = NULL;
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Enable usart interface
+ */
+int32_t usart_sync_enable(struct usart_sync_descriptor *const descr)
+{
+	ASSERT(descr);
+	_usart_sync_enable(&descr->device);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Disable usart interface
+ */
+int32_t usart_sync_disable(struct usart_sync_descriptor *const descr)
+{
+	ASSERT(descr);
+	_usart_sync_disable(&descr->device);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Retrieve I/O descriptor
+ */
+int32_t usart_sync_get_io_descriptor(struct usart_sync_descriptor *const descr, struct io_descriptor **io)
+{
+	ASSERT(descr && io);
+
+	*io = &descr->io;
+	return ERR_NONE;
+}
+
+/**
+ * \brief Specify action for flow control pins
+ */
+int32_t usart_sync_set_flow_control(struct usart_sync_descriptor *const  descr,
+                                    const union usart_flow_control_state state)
+{
+	ASSERT(descr);
+	_usart_sync_set_flow_control_state(&descr->device, state);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set usart baud rate
+ */
+int32_t usart_sync_set_baud_rate(struct usart_sync_descriptor *const descr, const uint32_t baud_rate)
+{
+	ASSERT(descr);
+	_usart_sync_set_baud_rate(&descr->device, baud_rate);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set usart data order
+ */
+int32_t usart_sync_set_data_order(struct usart_sync_descriptor *const descr, const enum usart_data_order data_order)
+{
+	ASSERT(descr);
+	_usart_sync_set_data_order(&descr->device, data_order);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set usart mode
+ */
+int32_t usart_sync_set_mode(struct usart_sync_descriptor *const descr, const enum usart_mode mode)
+{
+	ASSERT(descr);
+	_usart_sync_set_mode(&descr->device, mode);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set usart parity
+ */
+int32_t usart_sync_set_parity(struct usart_sync_descriptor *const descr, const enum usart_parity parity)
+{
+	ASSERT(descr);
+	_usart_sync_set_parity(&descr->device, parity);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set usart stop bits
+ */
+int32_t usart_sync_set_stopbits(struct usart_sync_descriptor *const descr, const enum usart_stop_bits stop_bits)
+{
+	ASSERT(descr);
+	_usart_sync_set_stop_bits(&descr->device, stop_bits);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set usart character size
+ */
+int32_t usart_sync_set_character_size(struct usart_sync_descriptor *const descr, const enum usart_character_size size)
+{
+	ASSERT(descr);
+	_usart_sync_set_character_size(&descr->device, size);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Retrieve the state of flow control pins
+ */
+int32_t usart_sync_flow_control_status(const struct usart_sync_descriptor *const descr,
+                                       union usart_flow_control_state *const     state)
+{
+	ASSERT(descr && state);
+	*state = _usart_sync_get_flow_control_state(&descr->device);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Check if the usart transmitter is empty
+ */
+int32_t usart_sync_is_tx_empty(const struct usart_sync_descriptor *const descr)
+{
+	ASSERT(descr);
+	return _usart_sync_is_ready_to_send(&descr->device);
+}
+
+/**
+ * \brief Check if the usart receiver is not empty
+ */
+int32_t usart_sync_is_rx_not_empty(const struct usart_sync_descriptor *const descr)
+{
+	ASSERT(descr);
+	return _usart_sync_is_byte_received(&descr->device);
+}
+
+/**
+ * \brief Retrieve the current driver version
+ */
+uint32_t usart_sync_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_sync_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length)
+{
+	uint32_t                      offset = 0;
+	struct usart_sync_descriptor *descr  = CONTAINER_OF(io_descr, struct usart_sync_descriptor, io);
+
+	ASSERT(io_descr && buf && length);
+	while (!_usart_sync_is_ready_to_send(&descr->device))
+		;
+	do {
+		_usart_sync_write_byte(&descr->device, buf[offset]);
+		while (!_usart_sync_is_ready_to_send(&descr->device))
+			;
+	} while (++offset < length);
+	while (!_usart_sync_is_transmit_done(&descr->device))
+		;
+	return (int32_t)offset;
+}
+
+/*
+ * \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_sync_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length)
+{
+	uint32_t                      offset = 0;
+	struct usart_sync_descriptor *descr  = CONTAINER_OF(io_descr, struct usart_sync_descriptor, io);
+
+	ASSERT(io_descr && buf && length);
+	do {
+		while (!_usart_sync_is_byte_received(&descr->device))
+			;
+		buf[offset] = _usart_sync_read_byte(&descr->device);
+	} while (++offset < length);
+
+	return (int32_t)offset;
+}
diff --git a/sysmoOCTSIM/hpl/sercom/hpl_sercom.c b/sysmoOCTSIM/hpl/sercom/hpl_sercom.c
new file mode 100644
index 0000000..130f63a
--- /dev/null
+++ b/sysmoOCTSIM/hpl/sercom/hpl_sercom.c
@@ -0,0 +1,2948 @@
+
+/**
+ * \file
+ *
+ * \brief SAM Serial Communication Interface
+ *
+ * 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 <hpl_dma.h>
+#include <hpl_i2c_m_async.h>
+#include <hpl_i2c_m_sync.h>
+#include <hpl_i2c_s_async.h>
+#include <hpl_sercom_config.h>
+#include <hpl_spi_m_async.h>
+#include <hpl_spi_m_sync.h>
+#include <hpl_spi_s_async.h>
+#include <hpl_spi_s_sync.h>
+#include <hpl_usart_async.h>
+#include <hpl_usart_sync.h>
+#include <utils.h>
+#include <utils_assert.h>
+
+#ifndef CONF_SERCOM_0_USART_ENABLE
+#define CONF_SERCOM_0_USART_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_1_USART_ENABLE
+#define CONF_SERCOM_1_USART_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_2_USART_ENABLE
+#define CONF_SERCOM_2_USART_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_3_USART_ENABLE
+#define CONF_SERCOM_3_USART_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_4_USART_ENABLE
+#define CONF_SERCOM_4_USART_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_5_USART_ENABLE
+#define CONF_SERCOM_5_USART_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_6_USART_ENABLE
+#define CONF_SERCOM_6_USART_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_7_USART_ENABLE
+#define CONF_SERCOM_7_USART_ENABLE 0
+#endif
+
+/** Amount of SERCOM that is used as USART. */
+#define SERCOM_USART_AMOUNT                                                                                            \
+	(CONF_SERCOM_0_USART_ENABLE + CONF_SERCOM_1_USART_ENABLE + CONF_SERCOM_2_USART_ENABLE + CONF_SERCOM_3_USART_ENABLE \
+	 + CONF_SERCOM_4_USART_ENABLE + CONF_SERCOM_5_USART_ENABLE + CONF_SERCOM_6_USART_ENABLE                            \
+	 + CONF_SERCOM_7_USART_ENABLE)
+
+/**
+ * \brief Macro is used to fill usart configuration structure based on
+ * its number
+ *
+ * \param[in] n The number of structures
+ */
+#define SERCOM_CONFIGURATION(n)                                                                                        \
+	{                                                                                                                  \
+		n,                                                                                                             \
+		    SERCOM_USART_CTRLA_MODE(CONF_SERCOM_##n##_USART_MODE)                                                      \
+		        | (CONF_SERCOM_##n##_USART_RUNSTDBY << SERCOM_USART_CTRLA_RUNSTDBY_Pos)                                \
+		        | (CONF_SERCOM_##n##_USART_IBON << SERCOM_USART_CTRLA_IBON_Pos)                                        \
+		        | (CONF_SERCOM_##n##_USART_TXINV << SERCOM_USART_CTRLA_TXINV_Pos)                                      \
+		        | (CONF_SERCOM_##n##_USART_RXINV << SERCOM_USART_CTRLA_RXINV_Pos)                                      \
+		        | SERCOM_USART_CTRLA_SAMPR(CONF_SERCOM_##n##_USART_SAMPR)                                              \
+		        | SERCOM_USART_CTRLA_TXPO(CONF_SERCOM_##n##_USART_TXPO)                                                \
+		        | SERCOM_USART_CTRLA_RXPO(CONF_SERCOM_##n##_USART_RXPO)                                                \
+		        | SERCOM_USART_CTRLA_SAMPA(CONF_SERCOM_##n##_USART_SAMPA)                                              \
+		        | SERCOM_USART_CTRLA_FORM(CONF_SERCOM_##n##_USART_FORM)                                                \
+		        | (CONF_SERCOM_##n##_USART_CMODE << SERCOM_USART_CTRLA_CMODE_Pos)                                      \
+		        | (CONF_SERCOM_##n##_USART_CPOL << SERCOM_USART_CTRLA_CPOL_Pos)                                        \
+		        | (CONF_SERCOM_##n##_USART_DORD << SERCOM_USART_CTRLA_DORD_Pos),                                       \
+		    SERCOM_USART_CTRLB_CHSIZE(CONF_SERCOM_##n##_USART_CHSIZE)                                                  \
+		        | (CONF_SERCOM_##n##_USART_SBMODE << SERCOM_USART_CTRLB_SBMODE_Pos)                                    \
+		        | (CONF_SERCOM_##n##_USART_CLODEN << SERCOM_USART_CTRLB_COLDEN_Pos)                                    \
+		        | (CONF_SERCOM_##n##_USART_SFDE << SERCOM_USART_CTRLB_SFDE_Pos)                                        \
+		        | (CONF_SERCOM_##n##_USART_ENC << SERCOM_USART_CTRLB_ENC_Pos)                                          \
+		        | (CONF_SERCOM_##n##_USART_PMODE << SERCOM_USART_CTRLB_PMODE_Pos)                                      \
+		        | (CONF_SERCOM_##n##_USART_TXEN << SERCOM_USART_CTRLB_TXEN_Pos)                                        \
+		        | (CONF_SERCOM_##n##_USART_RXEN << SERCOM_USART_CTRLB_RXEN_Pos),                                       \
+		    SERCOM_USART_CTRLC_GTIME(CONF_SERCOM_##n##_USART_GTIME)                                                    \
+		        | (CONF_SERCOM_##n##_USART_DSNACK << SERCOM_USART_CTRLC_DSNACK_Pos)                                    \
+		        | (CONF_SERCOM_##n##_USART_INACK << SERCOM_USART_CTRLC_INACK_Pos)                                      \
+		        | SERCOM_USART_CTRLC_MAXITER(CONF_SERCOM_##n##_USART_MAXITER),                                         \
+		    (uint16_t)(CONF_SERCOM_##n##_USART_BAUD_RATE), CONF_SERCOM_##n##_USART_FRACTIONAL,                         \
+		    CONF_SERCOM_##n##_USART_RECEIVE_PULSE_LENGTH, CONF_SERCOM_##n##_USART_DEBUG_STOP_MODE,                     \
+	}
+
+/**
+ * \brief SERCOM USART configuration type
+ */
+struct usart_configuration {
+	uint8_t                       number;
+	hri_sercomusart_ctrla_reg_t   ctrl_a;
+	hri_sercomusart_ctrlb_reg_t   ctrl_b;
+	hri_sercomusart_ctrlc_reg_t   ctrl_c;
+	hri_sercomusart_baud_reg_t    baud;
+	uint8_t                       fractional;
+	hri_sercomusart_rxpl_reg_t    rxpl;
+	hri_sercomusart_dbgctrl_reg_t debug_ctrl;
+};
+
+#if SERCOM_USART_AMOUNT < 1
+/** Dummy array to pass compiling. */
+static struct usart_configuration _usarts[1] = {{0}};
+#else
+/**
+ * \brief Array of SERCOM USART configurations
+ */
+static struct usart_configuration _usarts[] = {
+#if CONF_SERCOM_0_USART_ENABLE == 1
+    SERCOM_CONFIGURATION(0),
+#endif
+#if CONF_SERCOM_1_USART_ENABLE == 1
+    SERCOM_CONFIGURATION(1),
+#endif
+#if CONF_SERCOM_2_USART_ENABLE == 1
+    SERCOM_CONFIGURATION(2),
+#endif
+#if CONF_SERCOM_3_USART_ENABLE == 1
+    SERCOM_CONFIGURATION(3),
+#endif
+#if CONF_SERCOM_4_USART_ENABLE == 1
+    SERCOM_CONFIGURATION(4),
+#endif
+#if CONF_SERCOM_5_USART_ENABLE == 1
+    SERCOM_CONFIGURATION(5),
+#endif
+#if CONF_SERCOM_6_USART_ENABLE == 1
+    SERCOM_CONFIGURATION(6),
+#endif
+#if CONF_SERCOM_7_USART_ENABLE == 1
+    SERCOM_CONFIGURATION(7),
+#endif
+};
+#endif
+
+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);
+static uint8_t _sercom_get_hardware_index(const void *const hw);
+
+static int32_t     _usart_init(void *const hw);
+static inline void _usart_deinit(void *const hw);
+static uint16_t    _usart_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
+                                              const enum usart_baud_rate_mode mode, const uint8_t fraction);
+static void        _usart_set_baud_rate(void *const hw, const uint32_t baud_rate);
+static void        _usart_set_data_order(void *const hw, const enum usart_data_order order);
+static void        _usart_set_mode(void *const hw, const enum usart_mode mode);
+static void        _usart_set_parity(void *const hw, const enum usart_parity parity);
+static void        _usart_set_stop_bits(void *const hw, const enum usart_stop_bits stop_bits);
+static void        _usart_set_character_size(void *const hw, const enum usart_character_size size);
+
+/**
+ * \brief Initialize synchronous SERCOM USART
+ */
+int32_t _usart_sync_init(struct _usart_sync_device *const device, void *const hw)
+{
+	ASSERT(device);
+
+	device->hw = hw;
+
+	return _usart_init(hw);
+}
+
+/**
+ * \brief Initialize asynchronous SERCOM USART
+ */
+int32_t _usart_async_init(struct _usart_async_device *const device, void *const hw)
+{
+	int32_t init_status;
+
+	ASSERT(device);
+
+	init_status = _usart_init(hw);
+	if (init_status) {
+		return init_status;
+	}
+	device->hw = hw;
+	_sercom_init_irq_param(hw, (void *)device);
+	uint8_t irq = _sercom_get_irq_num(hw);
+	for (uint32_t i = 0; i < 4; i++) {
+		NVIC_DisableIRQ((IRQn_Type)irq);
+		NVIC_ClearPendingIRQ((IRQn_Type)irq);
+		NVIC_EnableIRQ((IRQn_Type)irq);
+		irq++;
+	}
+	return ERR_NONE;
+}
+
+/**
+ * \brief De-initialize SERCOM USART
+ */
+void _usart_sync_deinit(struct _usart_sync_device *const device)
+{
+	_usart_deinit(device->hw);
+}
+
+/**
+ * \brief De-initialize SERCOM USART
+ */
+void _usart_async_deinit(struct _usart_async_device *const device)
+{
+	NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(device->hw));
+	_usart_deinit(device->hw);
+}
+
+/**
+ * \brief Calculate baud rate register value
+ */
+uint16_t _usart_sync_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
+                                         const enum usart_baud_rate_mode mode, const uint8_t fraction)
+{
+	return _usart_calculate_baud_rate(baud, clock_rate, samples, mode, fraction);
+}
+
+/**
+ * \brief Calculate baud rate register value
+ */
+uint16_t _usart_async_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
+                                          const enum usart_baud_rate_mode mode, const uint8_t fraction)
+{
+	return _usart_calculate_baud_rate(baud, clock_rate, samples, mode, fraction);
+}
+
+/**
+ * \brief Enable SERCOM module
+ */
+void _usart_sync_enable(struct _usart_sync_device *const device)
+{
+	hri_sercomusart_set_CTRLA_ENABLE_bit(device->hw);
+}
+
+/**
+ * \brief Enable SERCOM module
+ */
+void _usart_async_enable(struct _usart_async_device *const device)
+{
+	hri_sercomusart_set_CTRLA_ENABLE_bit(device->hw);
+}
+
+/**
+ * \brief Disable SERCOM module
+ */
+void _usart_sync_disable(struct _usart_sync_device *const device)
+{
+	hri_sercomusart_clear_CTRLA_ENABLE_bit(device->hw);
+}
+
+/**
+ * \brief Disable SERCOM module
+ */
+void _usart_async_disable(struct _usart_async_device *const device)
+{
+	hri_sercomusart_clear_CTRLA_ENABLE_bit(device->hw);
+}
+
+/**
+ * \brief Set baud rate
+ */
+void _usart_sync_set_baud_rate(struct _usart_sync_device *const device, const uint32_t baud_rate)
+{
+	_usart_set_baud_rate(device->hw, baud_rate);
+}
+
+/**
+ * \brief Set baud rate
+ */
+void _usart_async_set_baud_rate(struct _usart_async_device *const device, const uint32_t baud_rate)
+{
+	_usart_set_baud_rate(device->hw, baud_rate);
+}
+
+/**
+ * \brief Set data order
+ */
+void _usart_sync_set_data_order(struct _usart_sync_device *const device, const enum usart_data_order order)
+{
+	_usart_set_data_order(device->hw, order);
+}
+
+/**
+ * \brief Set data order
+ */
+void _usart_async_set_data_order(struct _usart_async_device *const device, const enum usart_data_order order)
+{
+	_usart_set_data_order(device->hw, order);
+}
+
+/**
+ * \brief Set mode
+ */
+void _usart_sync_set_mode(struct _usart_sync_device *const device, const enum usart_mode mode)
+{
+	_usart_set_mode(device->hw, mode);
+}
+
+/**
+ * \brief Set mode
+ */
+void _usart_async_set_mode(struct _usart_async_device *const device, const enum usart_mode mode)
+{
+	_usart_set_mode(device->hw, mode);
+}
+
+/**
+ * \brief Set parity
+ */
+void _usart_sync_set_parity(struct _usart_sync_device *const device, const enum usart_parity parity)
+{
+	_usart_set_parity(device->hw, parity);
+}
+
+/**
+ * \brief Set parity
+ */
+void _usart_async_set_parity(struct _usart_async_device *const device, const enum usart_parity parity)
+{
+	_usart_set_parity(device->hw, parity);
+}
+
+/**
+ * \brief Set stop bits mode
+ */
+void _usart_sync_set_stop_bits(struct _usart_sync_device *const device, const enum usart_stop_bits stop_bits)
+{
+	_usart_set_stop_bits(device->hw, stop_bits);
+}
+
+/**
+ * \brief Set stop bits mode
+ */
+void _usart_async_set_stop_bits(struct _usart_async_device *const device, const enum usart_stop_bits stop_bits)
+{
+	_usart_set_stop_bits(device->hw, stop_bits);
+}
+
+/**
+ * \brief Set character size
+ */
+void _usart_sync_set_character_size(struct _usart_sync_device *const device, const enum usart_character_size size)
+{
+	_usart_set_character_size(device->hw, size);
+}
+
+/**
+ * \brief Set character size
+ */
+void _usart_async_set_character_size(struct _usart_async_device *const device, const enum usart_character_size size)
+{
+	_usart_set_character_size(device->hw, size);
+}
+
+/**
+ * \brief Retrieve SERCOM usart status
+ */
+uint32_t _usart_sync_get_status(const struct _usart_sync_device *const device)
+{
+	return hri_sercomusart_read_STATUS_reg(device->hw);
+}
+
+/**
+ * \brief Retrieve SERCOM usart status
+ */
+uint32_t _usart_async_get_status(const struct _usart_async_device *const device)
+{
+	return hri_sercomusart_read_STATUS_reg(device->hw);
+}
+
+/**
+ * \brief Write a byte to the given SERCOM USART instance
+ */
+void _usart_sync_write_byte(struct _usart_sync_device *const device, uint8_t data)
+{
+	hri_sercomusart_write_DATA_reg(device->hw, data);
+}
+
+/**
+ * \brief Write a byte to the given SERCOM USART instance
+ */
+void _usart_async_write_byte(struct _usart_async_device *const device, uint8_t data)
+{
+	hri_sercomusart_write_DATA_reg(device->hw, data);
+}
+
+/**
+ * \brief Read a byte from the given SERCOM USART instance
+ */
+uint8_t _usart_sync_read_byte(const struct _usart_sync_device *const device)
+{
+	return hri_sercomusart_read_DATA_reg(device->hw);
+}
+
+/**
+ * \brief Check if USART is ready to send next byte
+ */
+bool _usart_sync_is_ready_to_send(const struct _usart_sync_device *const device)
+{
+	return hri_sercomusart_get_interrupt_DRE_bit(device->hw);
+}
+
+/**
+ * \brief Check if USART transmission complete
+ */
+bool _usart_sync_is_transmit_done(const struct _usart_sync_device *const device)
+{
+	return hri_sercomusart_get_interrupt_TXC_bit(device->hw);
+}
+
+/**
+ * \brief Check if USART is ready to send next byte
+ */
+bool _usart_async_is_byte_sent(const struct _usart_async_device *const device)
+{
+	return hri_sercomusart_get_interrupt_DRE_bit(device->hw);
+}
+
+/**
+ * \brief Check if there is data received by USART
+ */
+bool _usart_sync_is_byte_received(const struct _usart_sync_device *const device)
+{
+	return hri_sercomusart_get_interrupt_RXC_bit(device->hw);
+}
+
+/**
+ * \brief Set the state of flow control pins
+ */
+void _usart_sync_set_flow_control_state(struct _usart_sync_device *const     device,
+                                        const union usart_flow_control_state state)
+{
+	(void)device;
+	(void)state;
+}
+
+/**
+ * \brief Set the state of flow control pins
+ */
+void _usart_async_set_flow_control_state(struct _usart_async_device *const    device,
+                                         const union usart_flow_control_state state)
+{
+	(void)device;
+	(void)state;
+}
+
+/**
+ * \brief Retrieve the state of flow control pins
+ */
+union usart_flow_control_state _usart_sync_get_flow_control_state(const struct _usart_sync_device *const device)
+{
+	(void)device;
+	union usart_flow_control_state state;
+
+	state.value           = 0;
+	state.bit.unavailable = 1;
+	return state;
+}
+
+/**
+ * \brief Retrieve the state of flow control pins
+ */
+union usart_flow_control_state _usart_async_get_flow_control_state(const struct _usart_async_device *const device)
+{
+	(void)device;
+	union usart_flow_control_state state;
+
+	state.value           = 0;
+	state.bit.unavailable = 1;
+	return state;
+}
+
+/**
+ * \brief Enable data register empty interrupt
+ */
+void _usart_async_enable_byte_sent_irq(struct _usart_async_device *const device)
+{
+	hri_sercomusart_set_INTEN_DRE_bit(device->hw);
+}
+
+/**
+ * \brief Enable transmission complete interrupt
+ */
+void _usart_async_enable_tx_done_irq(struct _usart_async_device *const device)
+{
+	hri_sercomusart_set_INTEN_TXC_bit(device->hw);
+}
+
+/**
+ * \brief Retrieve ordinal number of the given sercom hardware instance
+ */
+static uint8_t _sercom_get_hardware_index(const void *const hw)
+{
+	Sercom *const sercom_modules[] = SERCOM_INSTS;
+	/* Find index for SERCOM instance. */
+	for (uint32_t i = 0; i < SERCOM_INST_NUM; i++) {
+		if ((uint32_t)hw == (uint32_t)sercom_modules[i]) {
+			return i;
+		}
+	}
+	return 0;
+}
+
+/**
+ * \brief Retrieve ordinal number of the given SERCOM USART hardware instance
+ */
+uint8_t _usart_sync_get_hardware_index(const struct _usart_sync_device *const device)
+{
+	return _sercom_get_hardware_index(device->hw);
+}
+
+/**
+ * \brief Retrieve ordinal number of the given SERCOM USART hardware instance
+ */
+uint8_t _usart_async_get_hardware_index(const struct _usart_async_device *const device)
+{
+	return _sercom_get_hardware_index(device->hw);
+}
+
+/**
+ * \brief Enable/disable USART interrupt
+ */
+void _usart_async_set_irq_state(struct _usart_async_device *const device, const enum _usart_async_callback_type type,
+                                const bool state)
+{
+	ASSERT(device);
+
+	if (USART_ASYNC_BYTE_SENT == type || USART_ASYNC_TX_DONE == type) {
+		hri_sercomusart_write_INTEN_DRE_bit(device->hw, state);
+		hri_sercomusart_write_INTEN_TXC_bit(device->hw, state);
+	} else if (USART_ASYNC_RX_DONE == type) {
+		hri_sercomusart_write_INTEN_RXC_bit(device->hw, state);
+	} else if (USART_ASYNC_ERROR == type) {
+		hri_sercomusart_write_INTEN_ERROR_bit(device->hw, state);
+	}
+}
+
+/**
+ * \internal Retrieve ordinal number of the given sercom hardware instance
+ *
+ * \param[in] hw The pointer to hardware instance
+
+ * \return The ordinal number of the given sercom hardware instance
+ */
+static uint8_t _get_sercom_index(const void *const hw)
+{
+	uint8_t sercom_offset = _sercom_get_hardware_index(hw);
+	uint8_t i;
+
+	for (i = 0; i < ARRAY_SIZE(_usarts); i++) {
+		if (_usarts[i].number == sercom_offset) {
+			return i;
+		}
+	}
+
+	ASSERT(false);
+	return 0;
+}
+
+/**
+ * \brief Init irq param with the given sercom hardware instance
+ */
+static void _sercom_init_irq_param(const void *const hw, void *dev)
+{
+}
+
+/**
+ * \internal Initialize SERCOM USART
+ *
+ * \param[in] hw The pointer to hardware instance
+ *
+ * \return The status of initialization
+ */
+static int32_t _usart_init(void *const hw)
+{
+	uint8_t i = _get_sercom_index(hw);
+
+	if (!hri_sercomusart_is_syncing(hw, SERCOM_USART_SYNCBUSY_SWRST)) {
+		uint32_t mode = _usarts[i].ctrl_a & SERCOM_USART_CTRLA_MODE_Msk;
+		if (hri_sercomusart_get_CTRLA_reg(hw, SERCOM_USART_CTRLA_ENABLE)) {
+			hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
+			hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
+		}
+		hri_sercomusart_write_CTRLA_reg(hw, SERCOM_USART_CTRLA_SWRST | mode);
+	}
+	hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_SWRST);
+
+	hri_sercomusart_write_CTRLA_reg(hw, _usarts[i].ctrl_a);
+	hri_sercomusart_write_CTRLB_reg(hw, _usarts[i].ctrl_b);
+	hri_sercomusart_write_CTRLC_reg(hw, _usarts[i].ctrl_c);
+	if ((_usarts[i].ctrl_a & SERCOM_USART_CTRLA_SAMPR(0x1)) || (_usarts[i].ctrl_a & SERCOM_USART_CTRLA_SAMPR(0x3))) {
+		((Sercom *)hw)->USART.BAUD.FRAC.BAUD = _usarts[i].baud;
+		((Sercom *)hw)->USART.BAUD.FRAC.FP   = _usarts[i].fractional;
+	} else {
+		hri_sercomusart_write_BAUD_reg(hw, _usarts[i].baud);
+	}
+
+	hri_sercomusart_write_RXPL_reg(hw, _usarts[i].rxpl);
+	hri_sercomusart_write_DBGCTRL_reg(hw, _usarts[i].debug_ctrl);
+
+	return ERR_NONE;
+}
+
+/**
+ * \internal De-initialize SERCOM USART
+ *
+ * \param[in] hw The pointer to hardware instance
+ */
+static inline void _usart_deinit(void *const hw)
+{
+	hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
+	hri_sercomusart_set_CTRLA_SWRST_bit(hw);
+}
+
+/**
+ * \internal Calculate baud rate register value
+ *
+ * \param[in] baud Required baud rate
+ * \param[in] clock_rate SERCOM clock frequency
+ * \param[in] samples The number of samples
+ * \param[in] mode USART mode
+ * \param[in] fraction A fraction value
+ *
+ * \return Calculated baud rate register value
+ */
+static uint16_t _usart_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
+                                           const enum usart_baud_rate_mode mode, const uint8_t fraction)
+{
+	if (USART_BAUDRATE_ASYNCH_ARITHMETIC == mode) {
+		return 65536 - ((uint64_t)65536 * samples * baud) / clock_rate;
+	}
+
+	if (USART_BAUDRATE_ASYNCH_FRACTIONAL == mode) {
+		return clock_rate / baud / samples + SERCOM_USART_BAUD_FRACFP_FP(fraction);
+	}
+
+	if (USART_BAUDRATE_SYNCH == mode) {
+		return clock_rate / baud / 2 - 1;
+	}
+
+	return 0;
+}
+
+/**
+ * \internal Set baud rate
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] baud_rate A baud rate to set
+ */
+static void _usart_set_baud_rate(void *const hw, const uint32_t baud_rate)
+{
+	bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
+
+	hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
+
+	CRITICAL_SECTION_ENTER()
+	hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
+	hri_sercomusart_write_BAUD_reg(hw, baud_rate);
+	CRITICAL_SECTION_LEAVE()
+
+	hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
+}
+
+/**
+ * \internal Set data order
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] order A data order to set
+ */
+static void _usart_set_data_order(void *const hw, const enum usart_data_order order)
+{
+	bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
+
+	hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
+
+	CRITICAL_SECTION_ENTER()
+	hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
+	hri_sercomusart_write_CTRLA_DORD_bit(hw, order);
+	CRITICAL_SECTION_LEAVE()
+
+	hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
+}
+
+/**
+ * \internal Set mode
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] mode A mode to set
+ */
+static void _usart_set_mode(void *const hw, const enum usart_mode mode)
+{
+	bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
+
+	hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
+
+	CRITICAL_SECTION_ENTER()
+	hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
+	hri_sercomusart_write_CTRLA_CMODE_bit(hw, mode);
+	CRITICAL_SECTION_LEAVE()
+
+	hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
+}
+
+/**
+ * \internal Set parity
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] parity A parity to set
+ */
+static void _usart_set_parity(void *const hw, const enum usart_parity parity)
+{
+	bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
+
+	hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
+
+	CRITICAL_SECTION_ENTER()
+	hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
+
+	if (USART_PARITY_NONE != parity) {
+		hri_sercomusart_set_CTRLA_FORM_bf(hw, 1);
+	} else {
+		hri_sercomusart_clear_CTRLA_FORM_bf(hw, 1);
+	}
+
+	hri_sercomusart_write_CTRLB_PMODE_bit(hw, parity);
+	CRITICAL_SECTION_LEAVE()
+
+	hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
+}
+
+/**
+ * \internal Set stop bits mode
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] stop_bits A stop bits mode to set
+ */
+static void _usart_set_stop_bits(void *const hw, const enum usart_stop_bits stop_bits)
+{
+	bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
+
+	hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
+
+	CRITICAL_SECTION_ENTER()
+	hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
+	hri_sercomusart_write_CTRLB_SBMODE_bit(hw, stop_bits);
+	CRITICAL_SECTION_LEAVE()
+
+	hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
+}
+
+/**
+ * \internal Set character size
+ *
+ * \param[in] device The pointer to USART device instance
+ * \param[in] size A character size to set
+ */
+static void _usart_set_character_size(void *const hw, const enum usart_character_size size)
+{
+	bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
+
+	hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
+
+	CRITICAL_SECTION_ENTER()
+	hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
+	hri_sercomusart_write_CTRLB_CHSIZE_bf(hw, size);
+	CRITICAL_SECTION_LEAVE()
+
+	if (enabled) {
+		hri_sercomusart_set_CTRLA_ENABLE_bit(hw);
+	}
+}
+
+	/* Sercom I2C implementation */
+
+#ifndef CONF_SERCOM_0_I2CM_ENABLE
+#define CONF_SERCOM_0_I2CM_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_1_I2CM_ENABLE
+#define CONF_SERCOM_1_I2CM_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_2_I2CM_ENABLE
+#define CONF_SERCOM_2_I2CM_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_3_I2CM_ENABLE
+#define CONF_SERCOM_3_I2CM_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_4_I2CM_ENABLE
+#define CONF_SERCOM_4_I2CM_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_5_I2CM_ENABLE
+#define CONF_SERCOM_5_I2CM_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_6_I2CM_ENABLE
+#define CONF_SERCOM_6_I2CM_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_7_I2CM_ENABLE
+#define CONF_SERCOM_7_I2CM_ENABLE 0
+#endif
+
+/** Amount of SERCOM that is used as I2C Master. */
+#define SERCOM_I2CM_AMOUNT                                                                                             \
+	(CONF_SERCOM_0_I2CM_ENABLE + CONF_SERCOM_1_I2CM_ENABLE + CONF_SERCOM_2_I2CM_ENABLE + CONF_SERCOM_3_I2CM_ENABLE     \
+	 + CONF_SERCOM_4_I2CM_ENABLE + CONF_SERCOM_5_I2CM_ENABLE + CONF_SERCOM_6_I2CM_ENABLE + CONF_SERCOM_7_I2CM_ENABLE)
+
+/**
+ * \brief Macro is used to fill i2cm configuration structure based on
+ * its number
+ *
+ * \param[in] n The number of structures
+ */
+#define I2CM_CONFIGURATION(n)                                                                                          \
+	{                                                                                                                  \
+		(n),                                                                                                           \
+		    (SERCOM_I2CM_CTRLA_MODE_I2C_MASTER) | (CONF_SERCOM_##n##_I2CM_RUNSTDBY << SERCOM_I2CM_CTRLA_RUNSTDBY_Pos)  \
+		        | (CONF_SERCOM_##n##_I2CM_SPEED << SERCOM_I2CM_CTRLA_SPEED_Pos)                                        \
+		        | (CONF_SERCOM_##n##_I2CM_MEXTTOEN << SERCOM_I2CM_CTRLA_MEXTTOEN_Pos)                                  \
+		        | (CONF_SERCOM_##n##_I2CM_SEXTTOEN << SERCOM_I2CM_CTRLA_SEXTTOEN_Pos)                                  \
+		        | (CONF_SERCOM_##n##_I2CM_INACTOUT << SERCOM_I2CM_CTRLA_INACTOUT_Pos)                                  \
+		        | (CONF_SERCOM_##n##_I2CM_LOWTOUT << SERCOM_I2CM_CTRLA_LOWTOUTEN_Pos)                                  \
+		        | (CONF_SERCOM_##n##_I2CM_SDAHOLD << SERCOM_I2CM_CTRLA_SDAHOLD_Pos),                                   \
+		    SERCOM_I2CM_CTRLB_SMEN, (uint32_t)(CONF_SERCOM_##n##_I2CM_BAUD_RATE),                                      \
+		    CONF_SERCOM_##n##_I2CM_DEBUG_STOP_MODE, CONF_SERCOM_##n##_I2CM_TRISE, CONF_GCLK_SERCOM##n##_CORE_FREQUENCY \
+	}
+
+#define ERROR_FLAG (1 << 7)
+#define SB_FLAG (1 << 1)
+#define MB_FLAG (1 << 0)
+
+#define CMD_STOP 0x3
+#define I2C_IDLE 0x1
+#define I2C_SM 0x0
+#define I2C_FM 0x1
+#define I2C_HS 0x2
+#define TEN_ADDR_FRAME 0x78
+#define TEN_ADDR_MASK 0x3ff
+#define SEVEN_ADDR_MASK 0x7f
+
+/**
+ * \brief SERCOM I2CM configuration type
+ */
+struct i2cm_configuration {
+	uint8_t                      number;
+	hri_sercomi2cm_ctrla_reg_t   ctrl_a;
+	hri_sercomi2cm_ctrlb_reg_t   ctrl_b;
+	hri_sercomi2cm_baud_reg_t    baud;
+	hri_sercomi2cm_dbgctrl_reg_t dbgctrl;
+	uint16_t                     trise;
+	uint32_t                     clk; /* SERCOM peripheral clock frequency */
+};
+
+static inline void _i2c_m_enable_implementation(void *hw);
+static int32_t     _i2c_m_sync_init_impl(struct _i2c_m_service *const service, void *const hw);
+
+#if SERCOM_I2CM_AMOUNT < 1
+/** Dummy array to pass compiling. */
+static struct i2cm_configuration _i2cms[1] = {{0}};
+#else
+/**
+ * \brief Array of SERCOM I2CM configurations
+ */
+static struct i2cm_configuration _i2cms[] = {
+#if CONF_SERCOM_0_I2CM_ENABLE == 1
+    I2CM_CONFIGURATION(0),
+#endif
+#if CONF_SERCOM_1_I2CM_ENABLE == 1
+    I2CM_CONFIGURATION(1),
+#endif
+#if CONF_SERCOM_2_I2CM_ENABLE == 1
+    I2CM_CONFIGURATION(2),
+#endif
+#if CONF_SERCOM_3_I2CM_ENABLE == 1
+    I2CM_CONFIGURATION(3),
+#endif
+#if CONF_SERCOM_4_I2CM_ENABLE == 1
+    I2CM_CONFIGURATION(4),
+#endif
+#if CONF_SERCOM_5_I2CM_ENABLE == 1
+    I2CM_CONFIGURATION(5),
+#endif
+#if CONF_SERCOM_6_I2CM_ENABLE == 1
+    I2CM_CONFIGURATION(6),
+#endif
+#if CONF_SERCOM_7_I2CM_ENABLE == 1
+    I2CM_CONFIGURATION(7),
+#endif
+};
+#endif
+
+/**
+ * \internal Retrieve ordinal number of the given sercom hardware instance
+ *
+ * \param[in] hw The pointer to hardware instance
+
+ * \return The ordinal number of the given sercom hardware instance
+ */
+static int8_t _get_i2cm_index(const void *const hw)
+{
+	uint8_t sercom_offset = _sercom_get_hardware_index(hw);
+	uint8_t i;
+
+	for (i = 0; i < ARRAY_SIZE(_i2cms); i++) {
+		if (_i2cms[i].number == sercom_offset) {
+			return i;
+		}
+	}
+
+	ASSERT(false);
+	return -1;
+}
+
+static inline void _sercom_i2c_send_stop(void *const hw)
+{
+	hri_sercomi2cm_set_CTRLB_CMD_bf(hw, CMD_STOP);
+}
+
+/**
+ * \brief SERCOM I2CM analyze hardware status and transfer next byte
+ */
+static inline int32_t _sercom_i2c_sync_analyse_flags(void *const hw, uint32_t flags, struct _i2c_m_msg *const msg)
+{
+	int      sclsm  = hri_sercomi2cm_get_CTRLA_SCLSM_bit(hw);
+	uint16_t status = hri_sercomi2cm_read_STATUS_reg(hw);
+
+	if (flags & MB_FLAG) {
+		/* tx error */
+		if (status & SERCOM_I2CM_STATUS_ARBLOST) {
+			hri_sercomi2cm_clear_interrupt_MB_bit(hw);
+			msg->flags |= I2C_M_FAIL;
+			msg->flags &= ~I2C_M_BUSY;
+
+			if (status & SERCOM_I2CM_STATUS_BUSERR) {
+				return I2C_ERR_BUS;
+			}
+
+			return I2C_ERR_BAD_ADDRESS;
+		} else {
+			if (status & SERCOM_I2CM_STATUS_RXNACK) {
+
+				/* Slave rejects to receive more data */
+				if (msg->len > 0) {
+					msg->flags |= I2C_M_FAIL;
+				}
+
+				if (msg->flags & I2C_M_STOP) {
+					_sercom_i2c_send_stop(hw);
+				}
+
+				msg->flags &= ~I2C_M_BUSY;
+
+				return I2C_NACK;
+			}
+
+			if (msg->flags & I2C_M_TEN) {
+				hri_sercomi2cm_write_ADDR_reg(hw,
+				                              ((((msg->addr & TEN_ADDR_MASK) >> 8) | TEN_ADDR_FRAME) << 1) | I2C_M_RD
+				                                  | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
+				msg->flags &= ~I2C_M_TEN;
+
+				return I2C_OK;
+			}
+
+			if (msg->len == 0) {
+				if (msg->flags & I2C_M_STOP) {
+					_sercom_i2c_send_stop(hw);
+				}
+
+				msg->flags &= ~I2C_M_BUSY;
+			} else {
+				hri_sercomi2cm_write_DATA_reg(hw, *msg->buffer);
+				msg->buffer++;
+				msg->len--;
+			}
+
+			return I2C_OK;
+		}
+	} else if (flags & SB_FLAG) {
+		if ((msg->len) && !(status & SERCOM_I2CM_STATUS_RXNACK)) {
+			msg->len--;
+
+			/* last byte, send nack */
+			if ((msg->len == 0 && !sclsm) || (msg->len == 1 && sclsm)) {
+				hri_sercomi2cm_set_CTRLB_ACKACT_bit(hw);
+			}
+
+			if (msg->len == 0) {
+				if (msg->flags & I2C_M_STOP) {
+					hri_sercomi2cm_clear_CTRLB_SMEN_bit(hw);
+					_sercom_i2c_send_stop(hw);
+				}
+
+				msg->flags &= ~I2C_M_BUSY;
+			}
+
+			/* Accessing DATA.DATA auto-triggers I2C bus operations.
+			 * The operation performed depends on the state of
+			 * CTRLB.ACKACT, CTRLB.SMEN
+			 **/
+			*msg->buffer++ = hri_sercomi2cm_read_DATA_reg(hw);
+		} else {
+			hri_sercomi2cm_clear_interrupt_SB_bit(hw);
+			return I2C_NACK;
+		}
+
+		hri_sercomi2cm_clear_interrupt_SB_bit(hw);
+	}
+
+	return I2C_OK;
+}
+
+/**
+ * \brief Enable the i2c master module
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ */
+int32_t _i2c_m_async_enable(struct _i2c_m_async_device *const i2c_dev)
+{
+	ASSERT(i2c_dev);
+
+	_i2c_m_enable_implementation(i2c_dev->hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Disable the i2c master module
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ */
+int32_t _i2c_m_async_disable(struct _i2c_m_async_device *const i2c_dev)
+{
+	void *hw = i2c_dev->hw;
+
+	ASSERT(i2c_dev);
+	ASSERT(i2c_dev->hw);
+
+	NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(hw));
+	hri_sercomi2cm_clear_CTRLA_ENABLE_bit(hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set baudrate of master
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ * \param[in] clkrate The clock rate of i2c master, in KHz
+ * \param[in] baudrate The baud rate desired for i2c master, in KHz
+ */
+int32_t _i2c_m_async_set_baudrate(struct _i2c_m_async_device *const i2c_dev, uint32_t clkrate, uint32_t baudrate)
+{
+	uint32_t tmp;
+	void *   hw = i2c_dev->hw;
+
+	if (hri_sercomi2cm_get_CTRLA_ENABLE_bit(hw)) {
+		return ERR_DENIED;
+	}
+
+	tmp     = _get_i2cm_index(hw);
+	clkrate = _i2cms[tmp].clk / 1000;
+
+	if (i2c_dev->service.mode == I2C_STANDARD_MODE) {
+		tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001))
+		                 / (2 * baudrate));
+		hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp);
+	} else if (i2c_dev->service.mode == I2C_FASTMODE) {
+		tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001))
+		                 / (2 * baudrate));
+		hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp);
+	} else if (i2c_dev->service.mode == I2C_HIGHSPEED_MODE) {
+		tmp = (clkrate - 2 * baudrate) / (2 * baudrate);
+		hri_sercomi2cm_write_BAUD_HSBAUD_bf(hw, tmp);
+	} else {
+		/* error baudrate */
+		return ERR_INVALID_ARG;
+	}
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Retrieve IRQ number for the given hardware instance
+ */
+static uint8_t _sercom_get_irq_num(const void *const hw)
+{
+	return SERCOM0_0_IRQn + (_sercom_get_hardware_index(hw) << 2);
+}
+
+/**
+ * \brief Initialize sercom i2c module to use in async mode
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ */
+int32_t _i2c_m_async_init(struct _i2c_m_async_device *const i2c_dev, void *const hw)
+{
+	int32_t init_status;
+
+	ASSERT(i2c_dev);
+
+	i2c_dev->hw = hw;
+
+	init_status = _i2c_m_sync_init_impl(&i2c_dev->service, hw);
+	if (init_status) {
+		return init_status;
+	}
+
+	_sercom_init_irq_param(hw, (void *)i2c_dev);
+	uint8_t irq = _sercom_get_irq_num(hw);
+	for (uint32_t i = 0; i < 4; i++) {
+		NVIC_DisableIRQ((IRQn_Type)irq);
+		NVIC_ClearPendingIRQ((IRQn_Type)irq);
+		NVIC_EnableIRQ((IRQn_Type)irq);
+		irq++;
+	}
+	return ERR_NONE;
+}
+
+/**
+ * \brief Deinitialize sercom i2c module
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ */
+int32_t _i2c_m_async_deinit(struct _i2c_m_async_device *const i2c_dev)
+{
+	ASSERT(i2c_dev);
+
+	hri_sercomi2cm_clear_CTRLA_ENABLE_bit(i2c_dev->hw);
+	hri_sercomi2cm_set_CTRLA_SWRST_bit(i2c_dev->hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Transfer the slave address to bus, which will start the transfer
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ */
+static int32_t _sercom_i2c_send_address(struct _i2c_m_async_device *const i2c_dev)
+{
+	void *             hw    = i2c_dev->hw;
+	struct _i2c_m_msg *msg   = &i2c_dev->service.msg;
+	int                sclsm = hri_sercomi2cm_get_CTRLA_SCLSM_bit(hw);
+
+	ASSERT(i2c_dev);
+
+	if (msg->len == 1 && sclsm) {
+		hri_sercomi2cm_set_CTRLB_ACKACT_bit(hw);
+	} else {
+		hri_sercomi2cm_clear_CTRLB_ACKACT_bit(hw);
+	}
+
+	/* ten bit address */
+	if (msg->addr & I2C_M_TEN) {
+		if (msg->flags & I2C_M_RD) {
+			msg->flags |= I2C_M_TEN;
+		}
+
+		hri_sercomi2cm_write_ADDR_reg(hw,
+		                              ((msg->addr & TEN_ADDR_MASK) << 1) | SERCOM_I2CM_ADDR_TENBITEN
+		                                  | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
+	} else {
+		hri_sercomi2cm_write_ADDR_reg(hw,
+		                              ((msg->addr & SEVEN_ADDR_MASK) << 1) | (msg->flags & I2C_M_RD ? I2C_M_RD : 0x0)
+		                                  | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
+	}
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Transfer data specified by msg
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ * \param[in] msg The pointer to i2c message
+ *
+ * \return Transfer status.
+ * \retval 0 Transfer success
+ * \retval <0 Transfer fail, return the error code
+ */
+int32_t _i2c_m_async_transfer(struct _i2c_m_async_device *i2c_dev, struct _i2c_m_msg *msg)
+{
+	int ret;
+
+	ASSERT(i2c_dev);
+	ASSERT(i2c_dev->hw);
+	ASSERT(msg);
+
+	if (msg->len == 0) {
+		return ERR_NONE;
+	}
+
+	if (i2c_dev->service.msg.flags & I2C_M_BUSY) {
+		return ERR_BUSY;
+	}
+
+	msg->flags |= I2C_M_BUSY;
+	i2c_dev->service.msg = *msg;
+	hri_sercomi2cm_set_CTRLB_SMEN_bit(i2c_dev->hw);
+
+	ret = _sercom_i2c_send_address(i2c_dev);
+
+	if (ret) {
+		i2c_dev->service.msg.flags &= ~I2C_M_BUSY;
+
+		return ret;
+	}
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set callback to be called in interrupt handler
+ *
+ * \param[in] i2c_dev The pointer to master i2c device
+ * \param[in] type The callback type
+ * \param[in] func The callback function pointer
+ */
+int32_t _i2c_m_async_register_callback(struct _i2c_m_async_device *const i2c_dev, enum _i2c_m_async_callback_type type,
+                                       FUNC_PTR func)
+{
+	switch (type) {
+	case I2C_M_ASYNC_DEVICE_ERROR:
+		i2c_dev->cb.error = (_i2c_error_cb_t)func;
+		break;
+	case I2C_M_ASYNC_DEVICE_TX_COMPLETE:
+		i2c_dev->cb.tx_complete = (_i2c_complete_cb_t)func;
+		break;
+	case I2C_M_ASYNC_DEVICE_RX_COMPLETE:
+		i2c_dev->cb.rx_complete = (_i2c_complete_cb_t)func;
+		break;
+	default:
+		/* error */
+		break;
+	}
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set stop condition on I2C
+ *
+ * \param i2c_dev Pointer to master i2c device
+ *
+ * \return Operation status
+ * \retval I2C_OK Operation was successfull
+ */
+int32_t _i2c_m_async_send_stop(struct _i2c_m_async_device *const i2c_dev)
+{
+	void *hw = i2c_dev->hw;
+
+	_sercom_i2c_send_stop(hw);
+
+	return I2C_OK;
+}
+
+/**
+ * \brief Get number of bytes left in transfer buffer
+ *
+ * \param i2c_dev Pointer to i2c master device
+ *
+ * \return Bytes left in buffer
+ * \retval =>0 Bytes left in buffer
+ */
+int32_t _i2c_m_async_get_bytes_left(struct _i2c_m_async_device *const i2c_dev)
+{
+	if (i2c_dev->service.msg.flags & I2C_M_BUSY) {
+		return i2c_dev->service.msg.len;
+	}
+
+	return 0;
+}
+
+/**
+ * \brief Initialize sercom i2c module to use in sync mode
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ */
+int32_t _i2c_m_sync_init(struct _i2c_m_sync_device *const i2c_dev, void *const hw)
+{
+	ASSERT(i2c_dev);
+
+	i2c_dev->hw = hw;
+
+	return _i2c_m_sync_init_impl(&i2c_dev->service, hw);
+}
+
+/**
+ * \brief Deinitialize sercom i2c module
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ */
+int32_t _i2c_m_sync_deinit(struct _i2c_m_sync_device *const i2c_dev)
+{
+	ASSERT(i2c_dev);
+
+	hri_sercomi2cm_clear_CTRLA_ENABLE_bit(i2c_dev->hw);
+	hri_sercomi2cm_set_CTRLA_SWRST_bit(i2c_dev->hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Enable the i2c master module
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ */
+int32_t _i2c_m_sync_enable(struct _i2c_m_sync_device *const i2c_dev)
+{
+	ASSERT(i2c_dev);
+
+	_i2c_m_enable_implementation(i2c_dev->hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Disable the i2c master module
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ */
+int32_t _i2c_m_sync_disable(struct _i2c_m_sync_device *const i2c_dev)
+{
+	void *hw = i2c_dev->hw;
+
+	ASSERT(i2c_dev);
+	ASSERT(i2c_dev->hw);
+
+	hri_sercomi2cm_clear_CTRLA_ENABLE_bit(hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Set baudrate of master
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ * \param[in] clkrate The clock rate of i2c master, in KHz
+ * \param[in] baudrate The baud rate desired for i2c master, in KHz
+ */
+int32_t _i2c_m_sync_set_baudrate(struct _i2c_m_sync_device *const i2c_dev, uint32_t clkrate, uint32_t baudrate)
+{
+	uint32_t tmp;
+	void *   hw = i2c_dev->hw;
+
+	if (hri_sercomi2cm_get_CTRLA_ENABLE_bit(hw)) {
+		return ERR_DENIED;
+	}
+
+	tmp     = _get_i2cm_index(hw);
+	clkrate = _i2cms[tmp].clk / 1000;
+
+	if (i2c_dev->service.mode == I2C_STANDARD_MODE) {
+		tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001))
+		                 / (2 * baudrate));
+		hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp);
+	} else if (i2c_dev->service.mode == I2C_FASTMODE) {
+		tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001))
+		                 / (2 * baudrate));
+		hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp);
+	} else if (i2c_dev->service.mode == I2C_HIGHSPEED_MODE) {
+		tmp = (clkrate - 2 * baudrate) / (2 * baudrate);
+		hri_sercomi2cm_write_BAUD_HSBAUD_bf(hw, tmp);
+	} else {
+		/* error baudrate */
+		return ERR_INVALID_ARG;
+	}
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Enable/disable I2C master interrupt
+ */
+void _i2c_m_async_set_irq_state(struct _i2c_m_async_device *const device, const enum _i2c_m_async_callback_type type,
+                                const bool state)
+{
+	if (I2C_M_ASYNC_DEVICE_TX_COMPLETE == type || I2C_M_ASYNC_DEVICE_RX_COMPLETE == type) {
+		hri_sercomi2cm_write_INTEN_SB_bit(device->hw, state);
+		hri_sercomi2cm_write_INTEN_MB_bit(device->hw, state);
+	} else if (I2C_M_ASYNC_DEVICE_ERROR == type) {
+		hri_sercomi2cm_write_INTEN_ERROR_bit(device->hw, state);
+	}
+}
+
+/**
+ * \brief Wait for bus response
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ * \param[in] flags Store the hardware response
+ *
+ * \return Bus response status.
+ * \retval 0 Bus response status OK
+ * \retval <0 Bus response fail
+ */
+inline static int32_t _sercom_i2c_sync_wait_bus(struct _i2c_m_sync_device *const i2c_dev, uint32_t *flags)
+{
+	uint32_t timeout = 65535;
+	void *   hw      = i2c_dev->hw;
+
+	do {
+		*flags = hri_sercomi2cm_read_INTFLAG_reg(hw);
+
+		if (timeout-- == 0) {
+			return I2C_ERR_BUS;
+		}
+	} while (!(*flags & MB_FLAG) && !(*flags & SB_FLAG));
+
+	return I2C_OK;
+}
+
+/**
+ * \brief Send the slave address to bus, which will start the transfer
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ */
+static int32_t _sercom_i2c_sync_send_address(struct _i2c_m_sync_device *const i2c_dev)
+{
+	void *             hw    = i2c_dev->hw;
+	struct _i2c_m_msg *msg   = &i2c_dev->service.msg;
+	int                sclsm = hri_sercomi2cm_get_CTRLA_SCLSM_bit(hw);
+	uint32_t           flags;
+
+	ASSERT(i2c_dev);
+
+	if (msg->len == 1 && sclsm) {
+		hri_sercomi2cm_set_CTRLB_ACKACT_bit(hw);
+	} else {
+		hri_sercomi2cm_clear_CTRLB_ACKACT_bit(hw);
+	}
+
+	/* ten bit address */
+	if (msg->addr & I2C_M_TEN) {
+		if (msg->flags & I2C_M_RD) {
+			msg->flags |= I2C_M_TEN;
+		}
+
+		hri_sercomi2cm_write_ADDR_reg(hw,
+		                              ((msg->addr & TEN_ADDR_MASK) << 1) | SERCOM_I2CM_ADDR_TENBITEN
+		                                  | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
+	} else {
+		hri_sercomi2cm_write_ADDR_reg(hw,
+		                              ((msg->addr & SEVEN_ADDR_MASK) << 1) | (msg->flags & I2C_M_RD ? I2C_M_RD : 0x0)
+		                                  | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
+	}
+
+	_sercom_i2c_sync_wait_bus(i2c_dev, &flags);
+	return _sercom_i2c_sync_analyse_flags(hw, flags, msg);
+}
+
+/**
+ * \brief Transfer data specified by msg
+ *
+ * \param[in] i2c_dev The pointer to i2c device
+ * \param[in] msg The pointer to i2c message
+ *
+ * \return Transfer status.
+ * \retval 0 Transfer success
+ * \retval <0 Transfer fail or partial fail, return the error code
+ */
+int32_t _i2c_m_sync_transfer(struct _i2c_m_sync_device *const i2c_dev, struct _i2c_m_msg *msg)
+{
+	uint32_t flags;
+	int      ret;
+	void *   hw = i2c_dev->hw;
+
+	ASSERT(i2c_dev);
+	ASSERT(i2c_dev->hw);
+	ASSERT(msg);
+
+	if (i2c_dev->service.msg.flags & I2C_M_BUSY) {
+		return I2C_ERR_BUSY;
+	}
+
+	msg->flags |= I2C_M_BUSY;
+	i2c_dev->service.msg = *msg;
+	hri_sercomi2cm_set_CTRLB_SMEN_bit(hw);
+
+	ret = _sercom_i2c_sync_send_address(i2c_dev);
+
+	if (ret) {
+		i2c_dev->service.msg.flags &= ~I2C_M_BUSY;
+
+		return ret;
+	}
+
+	while (i2c_dev->service.msg.flags & I2C_M_BUSY) {
+		ret = _sercom_i2c_sync_wait_bus(i2c_dev, &flags);
+
+		if (ret) {
+			if (msg->flags & I2C_M_STOP) {
+				_sercom_i2c_send_stop(hw);
+			}
+
+			i2c_dev->service.msg.flags &= ~I2C_M_BUSY;
+
+			return ret;
+		}
+
+		ret = _sercom_i2c_sync_analyse_flags(hw, flags, &i2c_dev->service.msg);
+	}
+
+	return ret;
+}
+
+int32_t _i2c_m_sync_send_stop(struct _i2c_m_sync_device *const i2c_dev)
+{
+	void *hw = i2c_dev->hw;
+
+	_sercom_i2c_send_stop(hw);
+
+	return I2C_OK;
+}
+
+static inline void _i2c_m_enable_implementation(void *const hw)
+{
+	int timeout = 65535;
+
+	ASSERT(hw);
+
+	/* Enable interrupts */
+	hri_sercomi2cm_set_CTRLA_ENABLE_bit(hw);
+
+	while (hri_sercomi2cm_read_STATUS_BUSSTATE_bf(hw) != I2C_IDLE) {
+		timeout--;
+
+		if (timeout <= 0) {
+			hri_sercomi2cm_clear_STATUS_reg(hw, SERCOM_I2CM_STATUS_BUSSTATE(I2C_IDLE));
+		}
+	}
+}
+
+static int32_t _i2c_m_sync_init_impl(struct _i2c_m_service *const service, void *const hw)
+{
+	uint8_t i = _get_i2cm_index(hw);
+
+	if (!hri_sercomi2cm_is_syncing(hw, SERCOM_I2CM_SYNCBUSY_SWRST)) {
+		uint32_t mode = _i2cms[i].ctrl_a & SERCOM_I2CM_CTRLA_MODE_Msk;
+		if (hri_sercomi2cm_get_CTRLA_reg(hw, SERCOM_I2CM_CTRLA_ENABLE)) {
+			hri_sercomi2cm_clear_CTRLA_ENABLE_bit(hw);
+			hri_sercomi2cm_wait_for_sync(hw, SERCOM_I2CM_SYNCBUSY_ENABLE);
+		}
+		hri_sercomi2cm_write_CTRLA_reg(hw, SERCOM_I2CM_CTRLA_SWRST | mode);
+	}
+	hri_sercomi2cm_wait_for_sync(hw, SERCOM_I2CM_SYNCBUSY_SWRST);
+
+	hri_sercomi2cm_write_CTRLA_reg(hw, _i2cms[i].ctrl_a);
+	hri_sercomi2cm_write_CTRLB_reg(hw, _i2cms[i].ctrl_b);
+	hri_sercomi2cm_write_BAUD_reg(hw, _i2cms[i].baud);
+
+	service->mode = (_i2cms[i].ctrl_a & SERCOM_I2CM_CTRLA_SPEED_Msk) >> SERCOM_I2CM_CTRLA_SPEED_Pos;
+	hri_sercomi2cm_write_ADDR_HS_bit(hw, service->mode < I2C_HS ? 0 : 1);
+
+	service->trise = _i2cms[i].trise;
+
+	return ERR_NONE;
+}
+
+	/* SERCOM I2C slave */
+
+#ifndef CONF_SERCOM_0_I2CS_ENABLE
+#define CONF_SERCOM_0_I2CS_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_1_I2CS_ENABLE
+#define CONF_SERCOM_1_I2CS_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_2_I2CS_ENABLE
+#define CONF_SERCOM_2_I2CS_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_3_I2CS_ENABLE
+#define CONF_SERCOM_3_I2CS_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_4_I2CS_ENABLE
+#define CONF_SERCOM_4_I2CS_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_5_I2CS_ENABLE
+#define CONF_SERCOM_5_I2CS_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_6_I2CS_ENABLE
+#define CONF_SERCOM_6_I2CS_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_7_I2CS_ENABLE
+#define CONF_SERCOM_7_I2CS_ENABLE 0
+#endif
+
+/** Amount of SERCOM that is used as I2C Slave. */
+#define SERCOM_I2CS_AMOUNT                                                                                             \
+	(CONF_SERCOM_0_I2CS_ENABLE + CONF_SERCOM_1_I2CS_ENABLE + CONF_SERCOM_2_I2CS_ENABLE + CONF_SERCOM_3_I2CS_ENABLE     \
+	 + CONF_SERCOM_4_I2CS_ENABLE + CONF_SERCOM_5_I2CS_ENABLE + CONF_SERCOM_6_I2CS_ENABLE + CONF_SERCOM_7_I2CS_ENABLE)
+
+/**
+ * \brief Macro is used to fill I2C slave configuration structure based on
+ * its number
+ *
+ * \param[in] n The number of structures
+ */
+#define I2CS_CONFIGURATION(n)                                                                                          \
+	{                                                                                                                  \
+		n,                                                                                                             \
+		    SERCOM_I2CM_CTRLA_MODE_I2C_SLAVE | (CONF_SERCOM_##n##_I2CS_RUNSTDBY << SERCOM_I2CS_CTRLA_RUNSTDBY_Pos)     \
+		        | SERCOM_I2CS_CTRLA_SDAHOLD(CONF_SERCOM_##n##_I2CS_SDAHOLD)                                            \
+		        | (CONF_SERCOM_##n##_I2CS_SEXTTOEN << SERCOM_I2CS_CTRLA_SEXTTOEN_Pos)                                  \
+		        | (CONF_SERCOM_##n##_I2CS_SPEED << SERCOM_I2CS_CTRLA_SPEED_Pos)                                        \
+		        | (CONF_SERCOM_##n##_I2CS_SCLSM << SERCOM_I2CS_CTRLA_SCLSM_Pos)                                        \
+		        | (CONF_SERCOM_##n##_I2CS_LOWTOUT << SERCOM_I2CS_CTRLA_LOWTOUTEN_Pos),                                 \
+		    SERCOM_I2CS_CTRLB_SMEN | SERCOM_I2CS_CTRLB_AACKEN | SERCOM_I2CS_CTRLB_AMODE(CONF_SERCOM_##n##_I2CS_AMODE), \
+		    (CONF_SERCOM_##n##_I2CS_GENCEN << SERCOM_I2CS_ADDR_GENCEN_Pos)                                             \
+		        | SERCOM_I2CS_ADDR_ADDR(CONF_SERCOM_##n##_I2CS_ADDRESS)                                                \
+		        | (CONF_SERCOM_##n##_I2CS_TENBITEN << SERCOM_I2CS_ADDR_TENBITEN_Pos)                                   \
+		        | SERCOM_I2CS_ADDR_ADDRMASK(CONF_SERCOM_##n##_I2CS_ADDRESS_MASK)                                       \
+	}
+
+/**
+ * \brief Macro to check 10-bit addressing
+ */
+#define I2CS_7BIT_ADDRESSING_MASK 0x7F
+
+static int32_t     _i2c_s_init(void *const hw);
+static int8_t      _get_i2c_s_index(const void *const hw);
+static inline void _i2c_s_deinit(void *const hw);
+static int32_t     _i2c_s_set_address(void *const hw, const uint16_t address);
+
+/**
+ * \brief SERCOM I2C slave configuration type
+ */
+struct i2cs_configuration {
+	uint8_t                    number;
+	hri_sercomi2cs_ctrla_reg_t ctrl_a;
+	hri_sercomi2cs_ctrlb_reg_t ctrl_b;
+	hri_sercomi2cs_addr_reg_t  address;
+};
+
+#if SERCOM_I2CS_AMOUNT < 1
+/** Dummy array for compiling. */
+static struct i2cs_configuration _i2css[1] = {{0}};
+#else
+/**
+ * \brief Array of SERCOM I2C slave configurations
+ */
+static struct i2cs_configuration _i2css[] = {
+#if CONF_SERCOM_0_I2CS_ENABLE == 1
+    I2CS_CONFIGURATION(0),
+#endif
+#if CONF_SERCOM_1_I2CS_ENABLE == 1
+    I2CS_CONFIGURATION(1),
+#endif
+#if CONF_SERCOM_2_I2CS_ENABLE == 1
+    I2CS_CONFIGURATION(2),
+#endif
+#if CONF_SERCOM_3_I2CS_ENABLE == 1
+    I2CS_CONFIGURATION(3),
+#endif
+#if CONF_SERCOM_4_I2CS_ENABLE == 1
+    I2CS_CONFIGURATION(4),
+#endif
+#if CONF_SERCOM_5_I2CS_ENABLE == 1
+    I2CS_CONFIGURATION(5),
+#endif
+};
+#endif
+
+/**
+ * \brief Initialize synchronous I2C slave
+ */
+int32_t _i2c_s_sync_init(struct _i2c_s_sync_device *const device, void *const hw)
+{
+	int32_t status;
+
+	ASSERT(device);
+
+	status = _i2c_s_init(hw);
+	if (status) {
+		return status;
+	}
+	device->hw = hw;
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Initialize asynchronous I2C slave
+ */
+int32_t _i2c_s_async_init(struct _i2c_s_async_device *const device, void *const hw)
+{
+	int32_t init_status;
+
+	ASSERT(device);
+
+	init_status = _i2c_s_init(hw);
+	if (init_status) {
+		return init_status;
+	}
+
+	device->hw = hw;
+	_sercom_init_irq_param(hw, (void *)device);
+	uint8_t irq = _sercom_get_irq_num(hw);
+	for (uint32_t i = 0; i < 4; i++) {
+		NVIC_DisableIRQ((IRQn_Type)irq);
+		NVIC_ClearPendingIRQ((IRQn_Type)irq);
+		NVIC_EnableIRQ((IRQn_Type)irq);
+		irq++;
+	}
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Deinitialize synchronous I2C
+ */
+int32_t _i2c_s_sync_deinit(struct _i2c_s_sync_device *const device)
+{
+	_i2c_s_deinit(device->hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Deinitialize asynchronous I2C
+ */
+int32_t _i2c_s_async_deinit(struct _i2c_s_async_device *const device)
+{
+	NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(device->hw));
+	_i2c_s_deinit(device->hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Enable I2C module
+ */
+int32_t _i2c_s_sync_enable(struct _i2c_s_sync_device *const device)
+{
+	hri_sercomi2cs_set_CTRLA_ENABLE_bit(device->hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Enable I2C module
+ */
+int32_t _i2c_s_async_enable(struct _i2c_s_async_device *const device)
+{
+	hri_sercomi2cs_set_CTRLA_ENABLE_bit(device->hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Disable I2C module
+ */
+int32_t _i2c_s_sync_disable(struct _i2c_s_sync_device *const device)
+{
+	hri_sercomi2cs_clear_CTRLA_ENABLE_bit(device->hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Disable I2C module
+ */
+int32_t _i2c_s_async_disable(struct _i2c_s_async_device *const device)
+{
+	hri_sercomi2cs_clear_CTRLA_ENABLE_bit(device->hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Check if 10-bit addressing mode is on
+ */
+int32_t _i2c_s_sync_is_10bit_addressing_on(const struct _i2c_s_sync_device *const device)
+{
+	return hri_sercomi2cs_get_ADDR_TENBITEN_bit(device->hw);
+}
+
+/**
+ * \brief Check if 10-bit addressing mode is on
+ */
+int32_t _i2c_s_async_is_10bit_addressing_on(const struct _i2c_s_async_device *const device)
+{
+	return hri_sercomi2cs_get_ADDR_TENBITEN_bit(device->hw);
+}
+
+/**
+ * \brief Set I2C slave address
+ */
+int32_t _i2c_s_sync_set_address(struct _i2c_s_sync_device *const device, const uint16_t address)
+{
+	return _i2c_s_set_address(device->hw, address);
+}
+
+/**
+ * \brief Set I2C slave address
+ */
+int32_t _i2c_s_async_set_address(struct _i2c_s_async_device *const device, const uint16_t address)
+{
+	return _i2c_s_set_address(device->hw, address);
+}
+
+/**
+ * \brief Write a byte to the given I2C instance
+ */
+void _i2c_s_sync_write_byte(struct _i2c_s_sync_device *const device, const uint8_t data)
+{
+	hri_sercomi2cs_write_DATA_reg(device->hw, data);
+}
+
+/**
+ * \brief Write a byte to the given I2C instance
+ */
+void _i2c_s_async_write_byte(struct _i2c_s_async_device *const device, const uint8_t data)
+{
+	hri_sercomi2cs_write_DATA_reg(device->hw, data);
+}
+
+/**
+ * \brief Read a byte from the given I2C instance
+ */
+uint8_t _i2c_s_sync_read_byte(const struct _i2c_s_sync_device *const device)
+{
+	return hri_sercomi2cs_read_DATA_reg(device->hw);
+}
+
+/**
+ * \brief Check if I2C is ready to send next byt
+ */
+bool _i2c_s_sync_is_byte_sent(const struct _i2c_s_sync_device *const device)
+{
+	return hri_sercomi2cs_get_interrupt_DRDY_bit(device->hw);
+}
+
+/**
+ * \brief Check if there is data received by I2C
+ */
+bool _i2c_s_sync_is_byte_received(const struct _i2c_s_sync_device *const device)
+{
+	return hri_sercomi2cs_get_interrupt_DRDY_bit(device->hw);
+}
+
+/**
+ * \brief Retrieve I2C slave status
+ */
+i2c_s_status_t _i2c_s_sync_get_status(const struct _i2c_s_sync_device *const device)
+{
+	return hri_sercomi2cs_read_STATUS_reg(device->hw);
+}
+
+/**
+ * \brief Clear the Data Ready interrupt flag
+ */
+int32_t _i2c_s_sync_clear_data_ready_flag(const struct _i2c_s_sync_device *const device)
+{
+	hri_sercomi2cs_clear_INTFLAG_DRDY_bit(device->hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Retrieve I2C slave status
+ */
+i2c_s_status_t _i2c_s_async_get_status(const struct _i2c_s_async_device *const device)
+{
+	return hri_sercomi2cs_read_STATUS_reg(device->hw);
+}
+
+/**
+ * \brief Abort data transmission
+ */
+int32_t _i2c_s_async_abort_transmission(const struct _i2c_s_async_device *const device)
+{
+	hri_sercomi2cs_clear_INTEN_DRDY_bit(device->hw);
+
+	return ERR_NONE;
+}
+
+/**
+ * \brief Enable/disable I2C slave interrupt
+ */
+int32_t _i2c_s_async_set_irq_state(struct _i2c_s_async_device *const device, const enum _i2c_s_async_callback_type type,
+                                   const bool state)
+{
+	ASSERT(device);
+
+	if (I2C_S_DEVICE_TX == type || I2C_S_DEVICE_RX_COMPLETE == type) {
+		hri_sercomi2cs_write_INTEN_DRDY_bit(device->hw, state);
+	} else if (I2C_S_DEVICE_ERROR == type) {
+		hri_sercomi2cs_write_INTEN_ERROR_bit(device->hw, state);
+	}
+
+	return ERR_NONE;
+}
+
+/**
+ * \internal Initalize i2c slave hardware
+ *
+ * \param[in] p The pointer to hardware instance
+ *
+ *\ return status of initialization
+ */
+static int32_t _i2c_s_init(void *const hw)
+{
+	int8_t i = _get_i2c_s_index(hw);
+	if (i == -1) {
+		return ERR_INVALID_ARG;
+	}
+
+	if (!hri_sercomi2cs_is_syncing(hw, SERCOM_I2CS_CTRLA_SWRST)) {
+		uint32_t mode = _i2css[i].ctrl_a & SERCOM_I2CS_CTRLA_MODE_Msk;
+		if (hri_sercomi2cs_get_CTRLA_reg(hw, SERCOM_I2CS_CTRLA_ENABLE)) {
+			hri_sercomi2cs_clear_CTRLA_ENABLE_bit(hw);
+			hri_sercomi2cs_wait_for_sync(hw, SERCOM_I2CS_SYNCBUSY_ENABLE);
+		}
+		hri_sercomi2cs_write_CTRLA_reg(hw, SERCOM_I2CS_CTRLA_SWRST | mode);
+	}
+	hri_sercomi2cs_wait_for_sync(hw, SERCOM_I2CS_SYNCBUSY_SWRST);
+
+	hri_sercomi2cs_write_CTRLA_reg(hw, _i2css[i].ctrl_a);
+	hri_sercomi2cs_write_CTRLB_reg(hw, _i2css[i].ctrl_b);
+	hri_sercomi2cs_write_ADDR_reg(hw, _i2css[i].address);
+
+	return ERR_NONE;
+}
+
+/**
+ * \internal Retrieve ordinal number of the given sercom hardware instance
+ *
+ * \param[in] hw The pointer to hardware instance
+ *
+ * \return The ordinal number of the given sercom hardware instance
+ */
+static int8_t _get_i2c_s_index(const void *const hw)
+{
+	uint8_t sercom_offset = _sercom_get_hardware_index(hw);
+	uint8_t i;
+
+	for (i = 0; i < ARRAY_SIZE(_i2css); i++) {
+		if (_i2css[i].number == sercom_offset) {
+			return i;
+		}
+	}
+
+	ASSERT(false);
+	return -1;
+}
+
+/**
+ * \internal De-initialize i2c slave
+ *
+ * \param[in] hw The pointer to hardware instance
+ */
+static inline void _i2c_s_deinit(void *const hw)
+{
+	hri_sercomi2cs_clear_CTRLA_ENABLE_bit(hw);
+	hri_sercomi2cs_set_CTRLA_SWRST_bit(hw);
+}
+
+/**
+ * \internal De-initialize i2c slave
+ *
+ * \param[in] hw The pointer to hardware instance
+ * \param[in] address Address to set
+ */
+static int32_t _i2c_s_set_address(void *const hw, const uint16_t address)
+{
+	bool enabled;
+
+	enabled = hri_sercomi2cs_get_CTRLA_ENABLE_bit(hw);
+
+	CRITICAL_SECTION_ENTER()
+	hri_sercomi2cs_clear_CTRLA_ENABLE_bit(hw);
+	hri_sercomi2cs_write_ADDR_ADDR_bf(hw, address);
+	CRITICAL_SECTION_LEAVE()
+
+	if (enabled) {
+		hri_sercomi2cs_set_CTRLA_ENABLE_bit(hw);
+	}
+
+	return ERR_NONE;
+}
+
+	/* Sercom SPI implementation */
+
+#ifndef SERCOM_USART_CTRLA_MODE_SPI_SLAVE
+#define SERCOM_USART_CTRLA_MODE_SPI_SLAVE (2 << 2)
+#endif
+
+#define SPI_DEV_IRQ_MODE 0x8000
+
+#define _SPI_CS_PORT_EXTRACT(cs) (((cs) >> 0) & 0xFF)
+#define _SPI_CS_PIN_EXTRACT(cs) (((cs) >> 8) & 0xFF)
+
+COMPILER_PACK_SET(1)
+/** Initialization configuration of registers. */
+struct sercomspi_regs_cfg {
+	uint32_t ctrla;
+	uint32_t ctrlb;
+	uint32_t addr;
+	uint8_t  baud;
+	uint8_t  dbgctrl;
+	uint16_t dummy_byte;
+	uint8_t  n;
+};
+COMPILER_PACK_RESET()
+
+/** Build configuration from header macros. */
+#define SERCOMSPI_REGS(n)                                                                                              \
+	{                                                                                                                  \
+		(((CONF_SERCOM_##n##_SPI_DORD) << SERCOM_SPI_CTRLA_DORD_Pos)                                                   \
+		 | (CONF_SERCOM_##n##_SPI_CPOL << SERCOM_SPI_CTRLA_CPOL_Pos)                                                   \
+		 | (CONF_SERCOM_##n##_SPI_CPHA << SERCOM_SPI_CTRLA_CPHA_Pos)                                                   \
+		 | (CONF_SERCOM_##n##_SPI_AMODE_EN ? SERCOM_SPI_CTRLA_FORM(2) : SERCOM_SPI_CTRLA_FORM(0))                      \
+		 | SERCOM_SPI_CTRLA_DOPO(CONF_SERCOM_##n##_SPI_TXPO) | SERCOM_SPI_CTRLA_DIPO(CONF_SERCOM_##n##_SPI_RXPO)       \
+		 | (CONF_SERCOM_##n##_SPI_IBON << SERCOM_SPI_CTRLA_IBON_Pos)                                                   \
+		 | (CONF_SERCOM_##n##_SPI_RUNSTDBY << SERCOM_SPI_CTRLA_RUNSTDBY_Pos)                                           \
+		 | SERCOM_SPI_CTRLA_MODE(CONF_SERCOM_##n##_SPI_MODE)), /* ctrla */                                             \
+		    ((CONF_SERCOM_##n##_SPI_RXEN << SERCOM_SPI_CTRLB_RXEN_Pos)                                                 \
+		     | (CONF_SERCOM_##n##_SPI_MSSEN << SERCOM_SPI_CTRLB_MSSEN_Pos)                                             \
+		     | (CONF_SERCOM_##n##_SPI_SSDE << SERCOM_SPI_CTRLB_SSDE_Pos)                                               \
+		     | (CONF_SERCOM_##n##_SPI_PLOADEN << SERCOM_SPI_CTRLB_PLOADEN_Pos)                                         \
+		     | SERCOM_SPI_CTRLB_AMODE(CONF_SERCOM_##n##_SPI_AMODE)                                                     \
+		     | SERCOM_SPI_CTRLB_CHSIZE(CONF_SERCOM_##n##_SPI_CHSIZE)), /* ctrlb */                                     \
+		    (SERCOM_SPI_ADDR_ADDR(CONF_SERCOM_##n##_SPI_ADDR)                                                          \
+		     | SERCOM_SPI_ADDR_ADDRMASK(CONF_SERCOM_##n##_SPI_ADDRMASK)),      /* addr */                              \
+		    ((uint8_t)CONF_SERCOM_##n##_SPI_BAUD_RATE),                        /* baud */                              \
+		    (CONF_SERCOM_##n##_SPI_DBGSTOP << SERCOM_SPI_DBGCTRL_DBGSTOP_Pos), /* dbgctrl */                           \
+		    CONF_SERCOM_##n##_SPI_DUMMYBYTE,                                   /* Dummy byte for SPI master mode */    \
+		    n                                                                  /* sercom number */                     \
+	}
+
+#ifndef CONF_SERCOM_0_SPI_ENABLE
+#define CONF_SERCOM_0_SPI_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_1_SPI_ENABLE
+#define CONF_SERCOM_1_SPI_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_2_SPI_ENABLE
+#define CONF_SERCOM_2_SPI_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_3_SPI_ENABLE
+#define CONF_SERCOM_3_SPI_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_4_SPI_ENABLE
+#define CONF_SERCOM_4_SPI_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_5_SPI_ENABLE
+#define CONF_SERCOM_5_SPI_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_6_SPI_ENABLE
+#define CONF_SERCOM_6_SPI_ENABLE 0
+#endif
+#ifndef CONF_SERCOM_7_SPI_ENABLE
+#define CONF_SERCOM_7_SPI_ENABLE 0
+#endif
+
+/** Amount of SERCOM that is used as SPI */
+#define SERCOM_SPI_AMOUNT                                                                                              \
+	(CONF_SERCOM_0_SPI_ENABLE + CONF_SERCOM_1_SPI_ENABLE + CONF_SERCOM_2_SPI_ENABLE + CONF_SERCOM_3_SPI_ENABLE         \
+	 + CONF_SERCOM_4_SPI_ENABLE + CONF_SERCOM_5_SPI_ENABLE + CONF_SERCOM_6_SPI_ENABLE + CONF_SERCOM_7_SPI_ENABLE)
+
+#if SERCOM_SPI_AMOUNT < 1
+/** Dummy array for compiling. */
+static const struct sercomspi_regs_cfg sercomspi_regs[1] = {{0}};
+#else
+/** The SERCOM SPI configurations of SERCOM that is used as SPI. */
+static const struct sercomspi_regs_cfg sercomspi_regs[] = {
+#if CONF_SERCOM_0_SPI_ENABLE
+    SERCOMSPI_REGS(0),
+#endif
+#if CONF_SERCOM_1_SPI_ENABLE
+    SERCOMSPI_REGS(1),
+#endif
+#if CONF_SERCOM_2_SPI_ENABLE
+    SERCOMSPI_REGS(2),
+#endif
+#if CONF_SERCOM_3_SPI_ENABLE
+    SERCOMSPI_REGS(3),
+#endif
+#if CONF_SERCOM_4_SPI_ENABLE
+    SERCOMSPI_REGS(4),
+#endif
+#if CONF_SERCOM_5_SPI_ENABLE
+    SERCOMSPI_REGS(5),
+#endif
+#if CONF_SERCOM_6_SPI_ENABLE
+    SERCOMSPI_REGS(6),
+#endif
+#if CONF_SERCOM_7_SPI_ENABLE
+    SERCOMSPI_REGS(7),
+#endif
+};
+#endif
+
+/** \internal De-initialize SERCOM SPI
+ *
+ *  \param[in] hw Pointer to the hardware register base.
+ *
+ * \return De-initialization status
+ */
+static int32_t _spi_deinit(void *const hw)
+{
+	hri_sercomspi_clear_CTRLA_ENABLE_bit(hw);
+	hri_sercomspi_set_CTRLA_SWRST_bit(hw);
+
+	return ERR_NONE;
+}
+
+/** \internal Enable SERCOM SPI
+ *
+ *  \param[in] hw Pointer to the hardware register base.
+ *
+ * \return Enabling status
+ */
+static int32_t _spi_sync_enable(void *const hw)
+{
+	if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
+		return ERR_BUSY;
+	}
+
+	hri_sercomspi_set_CTRLA_ENABLE_bit(hw);
+
+	return ERR_NONE;
+}
+
+/** \internal Enable SERCOM SPI
+ *
+ *  \param[in] hw Pointer to the hardware register base.
+ *
+ * \return Enabling status
+ */
+static int32_t _spi_async_enable(void *const hw)
+{
+	_spi_sync_enable(hw);
+	uint8_t irq = _sercom_get_irq_num(hw);
+	for (uint32_t i = 0; i < 4; i++) {
+		NVIC_EnableIRQ((IRQn_Type)irq++);
+	}
+
+	return ERR_NONE;
+}
+
+/** \internal Disable SERCOM SPI
+ *
+ *  \param[in] hw Pointer to the hardware register base.
+ *
+ * \return Disabling status
+ */
+static int32_t _spi_sync_disable(void *const hw)
+{
+	if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
+		return ERR_BUSY;
+	}
+	hri_sercomspi_clear_CTRLA_ENABLE_bit(hw);
+
+	return ERR_NONE;
+}
+
+/** \internal Disable SERCOM SPI
+ *
+ *  \param[in] hw Pointer to the hardware register base.
+ *
+ * \return Disabling status
+ */
+static int32_t _spi_async_disable(void *const hw)
+{
+	_spi_sync_disable(hw);
+	hri_sercomspi_clear_INTEN_reg(
+	    hw, SERCOM_SPI_INTFLAG_ERROR | SERCOM_SPI_INTFLAG_RXC | SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE);
+	uint8_t irq = _sercom_get_irq_num(hw);
+	for (uint32_t i = 0; i < 4; i++) {
+		NVIC_DisableIRQ((IRQn_Type)irq++);
+	}
+
+	return ERR_NONE;
+}
+
+/** \internal Set SERCOM SPI mode
+ *
+ * \param[in] hw Pointer to the hardware register base.
+ * \param[in] mode The mode to set
+ *
+ * \return Setting mode status
+ */
+static int32_t _spi_set_mode(void *const hw, const enum spi_transfer_mode mode)
+{
+	uint32_t ctrla;
+
+	if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_ENABLE)) {
+		return ERR_BUSY;
+	}
+
+	ctrla = hri_sercomspi_read_CTRLA_reg(hw);
+	ctrla &= ~(SERCOM_SPI_CTRLA_CPOL | SERCOM_SPI_CTRLA_CPHA);
+	ctrla |= (mode & 0x3u) << SERCOM_SPI_CTRLA_CPHA_Pos;
+	hri_sercomspi_write_CTRLA_reg(hw, ctrla);
+
+	return ERR_NONE;
+}
+
+/** \internal Set SERCOM SPI baudrate
+ *
+ * \param[in] hw Pointer to the hardware register base.
+ * \param[in] baud_val The baudrate to set
+ *
+ * \return Setting baudrate status
+ */
+static int32_t _spi_set_baudrate(void *const hw, const uint32_t baud_val)
+{
+	if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
+		return ERR_BUSY;
+	}
+
+	hri_sercomspi_write_BAUD_reg(hw, baud_val);
+
+	return ERR_NONE;
+}
+
+/** \internal Set SERCOM SPI char size
+ *
+ * \param[in] hw Pointer to the hardware register base.
+ * \param[in] baud_val The baudrate to set
+ * \param[out] size Stored char size
+ *
+ * \return Setting char size status
+ */
+static int32_t _spi_set_char_size(void *const hw, const enum spi_char_size char_size, uint8_t *const size)
+{
+	/* Only 8-bit or 9-bit accepted */
+	if (!(char_size == SPI_CHAR_SIZE_8 || char_size == SPI_CHAR_SIZE_9)) {
+		return ERR_INVALID_ARG;
+	}
+
+	if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_CTRLB)) {
+		return ERR_BUSY;
+	}
+
+	hri_sercomspi_write_CTRLB_CHSIZE_bf(hw, char_size);
+	*size = (char_size == SPI_CHAR_SIZE_8) ? 1 : 2;
+
+	return ERR_NONE;
+}
+
+/** \internal Set SERCOM SPI data order
+ *
+ * \param[in] hw Pointer to the hardware register base.
+ * \param[in] baud_val The baudrate to set
+ *
+ * \return Setting data order status
+ */
+static int32_t _spi_set_data_order(void *const hw, const enum spi_data_order dord)
+{
+	uint32_t ctrla;
+
+	if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
+		return ERR_BUSY;
+	}
+
+	ctrla = hri_sercomspi_read_CTRLA_reg(hw);
+
+	if (dord == SPI_DATA_ORDER_LSB_1ST) {
+		ctrla |= SERCOM_SPI_CTRLA_DORD;
+	} else {
+		ctrla &= ~SERCOM_SPI_CTRLA_DORD;
+	}
+	hri_sercomspi_write_CTRLA_reg(hw, ctrla);
+
+	return ERR_NONE;
+}
+
+/** \brief Load SERCOM registers to init for SPI master mode
+ *  The settings will be applied with default master mode, unsupported things
+ *  are ignored.
+ *  \param[in, out] hw Pointer to the hardware register base.
+ *  \param[in] regs Pointer to register configuration values.
+ */
+static inline void _spi_load_regs_master(void *const hw, const struct sercomspi_regs_cfg *regs)
+{
+	ASSERT(hw && regs);
+	hri_sercomspi_write_CTRLA_reg(
+	    hw, regs->ctrla & ~(SERCOM_SPI_CTRLA_IBON | SERCOM_SPI_CTRLA_ENABLE | SERCOM_SPI_CTRLA_SWRST));
+	hri_sercomspi_write_CTRLB_reg(
+	    hw,
+	    (regs->ctrlb
+	     & ~(SERCOM_SPI_CTRLB_MSSEN | SERCOM_SPI_CTRLB_AMODE_Msk | SERCOM_SPI_CTRLB_SSDE | SERCOM_SPI_CTRLB_PLOADEN))
+	        | (SERCOM_SPI_CTRLB_RXEN));
+	hri_sercomspi_write_BAUD_reg(hw, regs->baud);
+	hri_sercomspi_write_DBGCTRL_reg(hw, regs->dbgctrl);
+}
+
+/** \brief Load SERCOM registers to init for SPI slave mode
+ *  The settings will be applied with default slave mode, unsupported things
+ *  are ignored.
+ *  \param[in, out] hw Pointer to the hardware register base.
+ *  \param[in] regs Pointer to register configuration values.
+ */
+static inline void _spi_load_regs_slave(void *const hw, const struct sercomspi_regs_cfg *regs)
+{
+	ASSERT(hw && regs);
+	hri_sercomspi_write_CTRLA_reg(
+	    hw, regs->ctrla & ~(SERCOM_SPI_CTRLA_IBON | SERCOM_SPI_CTRLA_ENABLE | SERCOM_SPI_CTRLA_SWRST));
+	hri_sercomspi_write_CTRLB_reg(hw,
+	                              (regs->ctrlb & ~(SERCOM_SPI_CTRLB_MSSEN))
+	                                  | (SERCOM_SPI_CTRLB_RXEN | SERCOM_SPI_CTRLB_SSDE | SERCOM_SPI_CTRLB_PLOADEN));
+	hri_sercomspi_write_ADDR_reg(hw, regs->addr);
+	hri_sercomspi_write_DBGCTRL_reg(hw, regs->dbgctrl);
+	while (hri_sercomspi_is_syncing(hw, 0xFFFFFFFF))
+		;
+}
+
+/** \brief Return the pointer to register settings of specific SERCOM
+ *  \param[in] hw_addr The hardware register base address.
+ *  \return Pointer to register settings of specific SERCOM.
+ */
+static inline const struct sercomspi_regs_cfg *_spi_get_regs(const uint32_t hw_addr)
+{
+	uint8_t n = _sercom_get_hardware_index((const void *)hw_addr);
+	uint8_t i;
+
+	for (i = 0; i < sizeof(sercomspi_regs) / sizeof(struct sercomspi_regs_cfg); i++) {
+		if (sercomspi_regs[i].n == n) {
+			return &sercomspi_regs[i];
+		}
+	}
+
+	return NULL;
+}
+
+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);
+
+	ASSERT(dev && hw);
+
+	if (regs == NULL) {
+		return ERR_INVALID_ARG;
+	}
+
+	if (!hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
+		uint32_t mode = regs->ctrla & SERCOM_SPI_CTRLA_MODE_Msk;
+		if (hri_sercomspi_get_CTRLA_reg(hw, SERCOM_SPI_CTRLA_ENABLE)) {
+			hri_sercomspi_clear_CTRLA_ENABLE_bit(hw);
+			hri_sercomspi_wait_for_sync(hw, SERCOM_SPI_SYNCBUSY_ENABLE);
+		}
+		hri_sercomspi_write_CTRLA_reg(hw, SERCOM_SPI_CTRLA_SWRST | mode);
+	}
+	hri_sercomspi_wait_for_sync(hw, SERCOM_SPI_SYNCBUSY_SWRST);
+
+	dev->prvt = hw;
+
+	if ((regs->ctrla & SERCOM_SPI_CTRLA_MODE_Msk) == SERCOM_USART_CTRLA_MODE_SPI_SLAVE) {
+		_spi_load_regs_slave(hw, regs);
+	} else {
+		_spi_load_regs_master(hw, regs);
+	}
+
+	/* Load character size from default hardware configuration */
+	dev->char_size = ((regs->ctrlb & SERCOM_SPI_CTRLB_CHSIZE_Msk) == 0) ? 1 : 2;
+
+	dev->dummy_byte = regs->dummy_byte;
+
+	return ERR_NONE;
+}
+
+int32_t _spi_s_sync_init(struct _spi_s_sync_dev *dev, void *const hw)
+{
+	return _spi_m_sync_init(dev, hw);
+}
+
+int32_t _spi_m_async_init(struct _spi_async_dev *dev, void *const hw)
+{
+	struct _spi_async_dev *spid = dev;
+	/* Do hardware initialize. */
+	int32_t rc = _spi_m_sync_init((struct _spi_m_sync_dev *)dev, hw);
+
+	if (rc < 0) {
+		return rc;
+	}
+
+	_sercom_init_irq_param(hw, (void *)dev);
+	/* Initialize callbacks: must use them */
+	spid->callbacks.complete = NULL;
+	spid->callbacks.rx       = NULL;
+	spid->callbacks.tx       = NULL;
+	uint8_t irq              = _sercom_get_irq_num(hw);
+	for (uint32_t i = 0; i < 4; i++) {
+		NVIC_DisableIRQ((IRQn_Type)irq);
+		NVIC_ClearPendingIRQ((IRQn_Type)irq);
+		irq++;
+	}
+
+	return ERR_NONE;
+}
+
+int32_t _spi_s_async_init(struct _spi_s_async_dev *dev, void *const hw)
+{
+	return _spi_m_async_init(dev, hw);
+}
+
+int32_t _spi_m_async_deinit(struct _spi_async_dev *dev)
+{
+	NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt));
+	NVIC_ClearPendingIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt));
+
+	return _spi_deinit(dev->prvt);
+}
+
+int32_t _spi_s_async_deinit(struct _spi_s_async_dev *dev)
+{
+	NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt));
+	NVIC_ClearPendingIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt));
+
+	return _spi_deinit(dev->prvt);
+}
+
+int32_t _spi_m_sync_deinit(struct _spi_m_sync_dev *dev)
+{
+	return _spi_deinit(dev->prvt);
+}
+
+int32_t _spi_s_sync_deinit(struct _spi_s_sync_dev *dev)
+{
+	return _spi_deinit(dev->prvt);
+}
+
+int32_t _spi_m_sync_enable(struct _spi_m_sync_dev *dev)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_sync_enable(dev->prvt);
+}
+
+int32_t _spi_s_sync_enable(struct _spi_s_sync_dev *dev)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_sync_enable(dev->prvt);
+}
+
+int32_t _spi_m_async_enable(struct _spi_async_dev *dev)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_async_enable(dev->prvt);
+}
+
+int32_t _spi_s_async_enable(struct _spi_s_async_dev *dev)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_async_enable(dev->prvt);
+}
+
+int32_t _spi_m_sync_disable(struct _spi_m_sync_dev *dev)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_sync_disable(dev->prvt);
+}
+
+int32_t _spi_s_sync_disable(struct _spi_s_sync_dev *dev)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_sync_disable(dev->prvt);
+}
+
+int32_t _spi_m_async_disable(struct _spi_async_dev *dev)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_async_disable(dev->prvt);
+}
+
+int32_t _spi_s_async_disable(struct _spi_s_async_dev *dev)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_async_disable(dev->prvt);
+}
+
+int32_t _spi_m_sync_set_mode(struct _spi_m_sync_dev *dev, const enum spi_transfer_mode mode)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_mode(dev->prvt, mode);
+}
+
+int32_t _spi_m_async_set_mode(struct _spi_async_dev *dev, const enum spi_transfer_mode mode)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_mode(dev->prvt, mode);
+}
+
+int32_t _spi_s_async_set_mode(struct _spi_s_async_dev *dev, const enum spi_transfer_mode mode)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_mode(dev->prvt, mode);
+}
+
+int32_t _spi_s_sync_set_mode(struct _spi_s_sync_dev *dev, const enum spi_transfer_mode mode)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_mode(dev->prvt, mode);
+}
+
+int32_t _spi_calc_baud_val(struct spi_dev *dev, const uint32_t clk, const uint32_t baud)
+{
+	int32_t rc;
+	ASSERT(dev);
+
+	/* Not accept 0es */
+	if (clk == 0 || baud == 0) {
+		return ERR_INVALID_ARG;
+	}
+
+	/* Check baudrate range of current assigned clock */
+	if (!(baud <= (clk >> 1) && baud >= (clk >> 8))) {
+		return ERR_INVALID_ARG;
+	}
+
+	rc = ((clk >> 1) / baud) - 1;
+	return rc;
+}
+
+int32_t _spi_m_sync_set_baudrate(struct _spi_m_sync_dev *dev, const uint32_t baud_val)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_baudrate(dev->prvt, baud_val);
+}
+
+int32_t _spi_m_async_set_baudrate(struct _spi_async_dev *dev, const uint32_t baud_val)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_baudrate(dev->prvt, baud_val);
+}
+
+int32_t _spi_m_sync_set_char_size(struct _spi_m_sync_dev *dev, const enum spi_char_size char_size)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_char_size(dev->prvt, char_size, &dev->char_size);
+}
+
+int32_t _spi_m_async_set_char_size(struct _spi_async_dev *dev, const enum spi_char_size char_size)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_char_size(dev->prvt, char_size, &dev->char_size);
+}
+
+int32_t _spi_s_async_set_char_size(struct _spi_s_async_dev *dev, const enum spi_char_size char_size)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_char_size(dev->prvt, char_size, &dev->char_size);
+}
+
+int32_t _spi_s_sync_set_char_size(struct _spi_s_sync_dev *dev, const enum spi_char_size char_size)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_char_size(dev->prvt, char_size, &dev->char_size);
+}
+
+int32_t _spi_m_sync_set_data_order(struct _spi_m_sync_dev *dev, const enum spi_data_order dord)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_data_order(dev->prvt, dord);
+}
+
+int32_t _spi_m_async_set_data_order(struct _spi_async_dev *dev, const enum spi_data_order dord)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_data_order(dev->prvt, dord);
+}
+
+int32_t _spi_s_async_set_data_order(struct _spi_s_async_dev *dev, const enum spi_data_order dord)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_data_order(dev->prvt, dord);
+}
+
+int32_t _spi_s_sync_set_data_order(struct _spi_s_sync_dev *dev, const enum spi_data_order dord)
+{
+	ASSERT(dev && dev->prvt);
+
+	return _spi_set_data_order(dev->prvt, dord);
+}
+
+/** Wait until SPI bus idle. */
+static inline void _spi_wait_bus_idle(void *const hw)
+{
+	while (!(hri_sercomspi_get_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE))) {
+		;
+	}
+	hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE);
+}
+
+/** Holds run time information for message sync transaction. */
+struct _spi_trans_ctrl {
+	/** Pointer to transmitting data buffer. */
+	uint8_t *txbuf;
+	/** Pointer to receiving data buffer. */
+	uint8_t *rxbuf;
+	/** Count number of data transmitted. */
+	uint32_t txcnt;
+	/** Count number of data received. */
+	uint32_t rxcnt;
+	/** Data character size. */
+	uint8_t char_size;
+};
+
+/** Check interrupt flag of RXC and update transaction runtime information. */
+static inline bool _spi_rx_check_and_receive(void *const hw, const uint32_t iflag, struct _spi_trans_ctrl *ctrl)
+{
+	uint32_t data;
+
+	if (!(iflag & SERCOM_SPI_INTFLAG_RXC)) {
+		return false;
+	}
+
+	data = hri_sercomspi_read_DATA_reg(hw);
+
+	if (ctrl->rxbuf) {
+		*ctrl->rxbuf++ = (uint8_t)data;
+
+		if (ctrl->char_size > 1) {
+			*ctrl->rxbuf++ = (uint8_t)(data >> 8);
+		}
+	}
+
+	ctrl->rxcnt++;
+
+	return true;
+}
+
+/** Check interrupt flag of DRE and update transaction runtime information. */
+static inline void _spi_tx_check_and_send(void *const hw, const uint32_t iflag, struct _spi_trans_ctrl *ctrl,
+                                          uint16_t dummy)
+{
+	uint32_t data;
+
+	if (!(SERCOM_SPI_INTFLAG_DRE & iflag)) {
+		return;
+	}
+
+	if (ctrl->txbuf) {
+		data = *ctrl->txbuf++;
+
+		if (ctrl->char_size > 1) {
+			data |= (*ctrl->txbuf) << 8;
+			ctrl->txbuf++;
+		}
+	} else {
+		data = dummy;
+	}
+
+	ctrl->txcnt++;
+	hri_sercomspi_write_DATA_reg(hw, data);
+}
+
+/** Check interrupt flag of ERROR and update transaction runtime information. */
+static inline int32_t _spi_err_check(const uint32_t iflag, void *const hw)
+{
+	if (SERCOM_SPI_INTFLAG_ERROR & iflag) {
+		hri_sercomspi_clear_STATUS_reg(hw, ~0);
+		hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_ERROR);
+		return ERR_OVERFLOW;
+	}
+
+	return ERR_NONE;
+}
+
+int32_t _spi_m_sync_trans(struct _spi_m_sync_dev *dev, const struct spi_msg *msg)
+{
+	void *                 hw   = dev->prvt;
+	int32_t                rc   = 0;
+	struct _spi_trans_ctrl ctrl = {msg->txbuf, msg->rxbuf, 0, 0, dev->char_size};
+
+	ASSERT(dev && hw);
+
+	/* If settings are not applied (pending), we can not go on */
+	if (hri_sercomspi_is_syncing(
+	        hw, (SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_ENABLE | SERCOM_SPI_SYNCBUSY_CTRLB))) {
+		return ERR_BUSY;
+	}
+
+	/* SPI must be enabled to start synchronous transfer */
+	if (!hri_sercomspi_get_CTRLA_ENABLE_bit(hw)) {
+		return ERR_NOT_INITIALIZED;
+	}
+
+	for (;;) {
+		uint32_t iflag = hri_sercomspi_read_INTFLAG_reg(hw);
+
+		if (!_spi_rx_check_and_receive(hw, iflag, &ctrl)) {
+			/* In master mode, do not start next byte before previous byte received
+			 * to make better output waveform */
+			if (ctrl.rxcnt >= ctrl.txcnt) {
+				_spi_tx_check_and_send(hw, iflag, &ctrl, dev->dummy_byte);
+			}
+		}
+
+		rc = _spi_err_check(iflag, hw);
+
+		if (rc < 0) {
+			break;
+		}
+		if (ctrl.txcnt >= msg->size && ctrl.rxcnt >= msg->size) {
+			rc = ctrl.txcnt;
+			break;
+		}
+	}
+	/* Wait until SPI bus idle */
+	_spi_wait_bus_idle(hw);
+
+	return rc;
+}
+
+int32_t _spi_m_async_enable_tx(struct _spi_async_dev *dev, bool state)
+{
+	void *hw = dev->prvt;
+
+	ASSERT(dev && hw);
+
+	if (state) {
+		hri_sercomspi_set_INTEN_DRE_bit(hw);
+	} else {
+		hri_sercomspi_clear_INTEN_DRE_bit(hw);
+	}
+
+	return ERR_NONE;
+}
+
+int32_t _spi_s_async_enable_tx(struct _spi_s_async_dev *dev, bool state)
+{
+	return _spi_m_async_enable_tx(dev, state);
+}
+
+int32_t _spi_m_async_enable_rx(struct _spi_async_dev *dev, bool state)
+{
+	void *hw = dev->prvt;
+
+	ASSERT(dev);
+	ASSERT(hw);
+
+	if (state) {
+		hri_sercomspi_set_INTEN_RXC_bit(hw);
+	} else {
+		hri_sercomspi_clear_INTEN_RXC_bit(hw);
+	}
+
+	return ERR_NONE;
+}
+
+int32_t _spi_s_async_enable_rx(struct _spi_s_async_dev *dev, bool state)
+{
+	return _spi_m_async_enable_rx(dev, state);
+}
+
+int32_t _spi_m_async_enable_tx_complete(struct _spi_async_dev *dev, bool state)
+{
+	ASSERT(dev && dev->prvt);
+
+	if (state) {
+		hri_sercomspi_set_INTEN_TXC_bit(dev->prvt);
+	} else {
+		hri_sercomspi_clear_INTEN_TXC_bit(dev->prvt);
+	}
+
+	return ERR_NONE;
+}
+
+int32_t _spi_s_async_enable_ss_detect(struct _spi_s_async_dev *dev, bool state)
+{
+	return _spi_m_async_enable_tx_complete(dev, state);
+}
+
+int32_t _spi_m_async_write_one(struct _spi_async_dev *dev, uint16_t data)
+{
+	ASSERT(dev && dev->prvt);
+
+	hri_sercomspi_write_DATA_reg(dev->prvt, data);
+
+	return ERR_NONE;
+}
+
+int32_t _spi_s_async_write_one(struct _spi_s_async_dev *dev, uint16_t data)
+{
+	ASSERT(dev && dev->prvt);
+
+	hri_sercomspi_write_DATA_reg(dev->prvt, data);
+
+	return ERR_NONE;
+}
+
+int32_t _spi_s_sync_write_one(struct _spi_s_sync_dev *dev, uint16_t data)
+{
+	ASSERT(dev && dev->prvt);
+
+	hri_sercomspi_write_DATA_reg(dev->prvt, data);
+
+	return ERR_NONE;
+}
+
+uint16_t _spi_m_async_read_one(struct _spi_async_dev *dev)
+{
+	ASSERT(dev && dev->prvt);
+
+	return hri_sercomspi_read_DATA_reg(dev->prvt);
+}
+
+uint16_t _spi_s_async_read_one(struct _spi_s_async_dev *dev)
+{
+	ASSERT(dev && dev->prvt);
+
+	return hri_sercomspi_read_DATA_reg(dev->prvt);
+}
+
+uint16_t _spi_s_sync_read_one(struct _spi_s_sync_dev *dev)
+{
+	ASSERT(dev && dev->prvt);
+
+	return hri_sercomspi_read_DATA_reg(dev->prvt);
+}
+
+int32_t _spi_m_async_register_callback(struct _spi_async_dev *dev, const enum _spi_async_dev_cb_type cb_type,
+                                       const FUNC_PTR func)
+{
+	typedef void (*func_t)(void);
+	struct _spi_async_dev *spid = dev;
+
+	ASSERT(dev && (cb_type < SPI_DEV_CB_N));
+
+	func_t *p_ls  = (func_t *)&spid->callbacks;
+	p_ls[cb_type] = (func_t)func;
+
+	return ERR_NONE;
+}
+
+int32_t _spi_s_async_register_callback(struct _spi_s_async_dev *dev, const enum _spi_s_async_dev_cb_type cb_type,
+                                       const FUNC_PTR func)
+{
+	return _spi_m_async_register_callback(dev, cb_type, func);
+}
+
+bool _spi_s_sync_is_tx_ready(struct _spi_s_sync_dev *dev)
+{
+	ASSERT(dev && dev->prvt);
+
+	return hri_sercomi2cm_get_INTFLAG_reg(dev->prvt, SERCOM_SPI_INTFLAG_DRE);
+}
+
+bool _spi_s_sync_is_rx_ready(struct _spi_s_sync_dev *dev)
+{
+	ASSERT(dev && dev->prvt);
+
+	return hri_sercomi2cm_get_INTFLAG_reg(dev->prvt, SERCOM_SPI_INTFLAG_RXC);
+}
+
+bool _spi_s_sync_is_ss_deactivated(struct _spi_s_sync_dev *dev)
+{
+	void *hw = dev->prvt;
+
+	ASSERT(dev && hw);
+
+	if (hri_sercomi2cm_get_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC)) {
+		hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC);
+		return true;
+	}
+	return false;
+}
+
+bool _spi_s_sync_is_error(struct _spi_s_sync_dev *dev)
+{
+	void *hw = dev->prvt;
+
+	ASSERT(dev && hw);
+
+	if (hri_sercomi2cm_get_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_ERROR)) {
+		hri_sercomspi_clear_STATUS_reg(hw, SERCOM_SPI_STATUS_BUFOVF);
+		hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_ERROR);
+		return true;
+	}
+	return false;
+}
+
+/**
+ * \brief Enable/disable SPI master interrupt
+ *
+ * param[in] device The pointer to SPI master device instance
+ * param[in] type The type of interrupt to disable/enable if applicable
+ * param[in] state Enable or disable
+ */
+void _spi_m_async_set_irq_state(struct _spi_async_dev *const device, const enum _spi_async_dev_cb_type type,
+                                const bool state)
+{
+	ASSERT(device);
+
+	if (SPI_DEV_CB_ERROR == type) {
+		hri_sercomspi_write_INTEN_ERROR_bit(device->prvt, state);
+	}
+}
+
+/**
+ * \brief Enable/disable SPI slave interrupt
+ *
+ * param[in] device The pointer to SPI slave device instance
+ * param[in] type The type of interrupt to disable/enable if applicable
+ * param[in] state Enable or disable
+ */
+void _spi_s_async_set_irq_state(struct _spi_async_dev *const device, const enum _spi_async_dev_cb_type type,
+                                const bool state)
+{
+	_spi_m_async_set_irq_state(device, type, state);
+}