commit dd56d6561f4a7be799e8f65c29057df4601d0fc6
Author: Thomas Schöpping <tschoepp@cit-ec.uni-bielefeld.de>
Date:   Wed Nov 13 13:35:11 2019 +0100

    Updated AMiRo-LLD and applied to the new interface structure.

diff --git a/core/src/aos_system.c b/core/src/aos_system.c
index 8a6b16a..2d2fc81 100644
--- a/core/src/aos_system.c
+++ b/core/src/aos_system.c
@@ -239,7 +239,7 @@ static void _printSystemInfo(BaseSequentialStream* stream)
 #else /* (AMIROOS_CFG_SSSP_ENABLE == true) */
   _printSystemInfoLine(stream, "AMiRo-OS" , SYSTEM_INFO_NAMEWIDTH, "%u.%u.%u %s", AMIROOS_VERSION_MAJOR, AMIROOS_VERSION_MINOR, AMIROOS_VERSION_PATCH, AMIROOS_RELEASE_TYPE);
 #endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
-  _printSystemInfoLine(stream, "AMiRo-LLD" , SYSTEM_INFO_NAMEWIDTH, "%u.%u.%u %s (periphAL %u.%u)", AMIRO_LLD_VERSION_MAJOR, AMIRO_LLD_VERSION_MINOR, AMIRO_LLD_VERSION_PATCH, AMIRO_LLD_RELEASE_TYPE, PERIPHAL_VERSION_MAJOR, PERIPHAL_VERSION_MINOR);
+  _printSystemInfoLine(stream, "AMiRo-LLD" , SYSTEM_INFO_NAMEWIDTH, "%u.%u.%u %s (periphAL %u.%u)", AMIROLLD_VERSION_MAJOR, AMIROLLD_VERSION_MINOR, AMIROLLD_VERSION_PATCH, AMIROLLD_RELEASE_TYPE, PERIPHAL_VERSION_MAJOR, PERIPHAL_VERSION_MINOR);
   _printSystemInfoLine(stream, "ChibiOS/RT" , SYSTEM_INFO_NAMEWIDTH, "%u.%u.%u %s", CH_KERNEL_MAJOR, CH_KERNEL_MINOR, CH_KERNEL_PATCH, (CH_KERNEL_STABLE == 1) ? "stable" : "non-stable");
   _printSystemInfoLine(stream, "ChibiOS/HAL", SYSTEM_INFO_NAMEWIDTH, "%u.%u.%u %s", CH_HAL_MAJOR, CH_HAL_MINOR, CH_HAL_PATCH, (CH_HAL_STABLE == 1) ? "stable" : "non-stable");
   _printSystemInfoLine(stream, "build type", SYSTEM_INFO_NAMEWIDTH,"%s", (AMIROOS_CFG_DBG == true) ? "debug" : "release");
diff --git a/modules/DiWheelDrive_1-1/alldconf.h b/modules/DiWheelDrive_1-1/alldconf.h
index a9d0072..b5ce81a 100644
--- a/modules/DiWheelDrive_1-1/alldconf.h
+++ b/modules/DiWheelDrive_1-1/alldconf.h
@@ -29,19 +29,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define ALLDCONF_H
 
 /*
- * compatibility guards
+ * common configuration
  */
-#define _AMIRO_LLD_CFG_
-#define AMIRO_LLD_CFG_VERSION_MAJOR             1
-#define AMIRO_LLD_CFG_VERSION_MINOR             1
-
-/**
- * @brief   Width of the apalTime_t data type.
- *
- * @details Possible values are 8, 16, 32, and 64 bits.
- *          By definition time is represented at microsecond precision.
- */
-#define AMIROLLD_CFG_TIME_SIZE                  32
+#include <aos_alldconf.h>
 
 #endif /* ALLDCONF_H */
 
diff --git a/modules/DiWheelDrive_1-2/alldconf.h b/modules/DiWheelDrive_1-2/alldconf.h
index 621cb15..c9ae462 100644
--- a/modules/DiWheelDrive_1-2/alldconf.h
+++ b/modules/DiWheelDrive_1-2/alldconf.h
@@ -29,19 +29,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define ALLDCONF_H
 
 /*
- * compatibility guards
+ * common configuration
  */
-#define _AMIRO_LLD_CFG_
-#define AMIRO_LLD_CFG_VERSION_MAJOR             1
-#define AMIRO_LLD_CFG_VERSION_MINOR             1
-
-/**
- * @brief   Width of the apalTime_t data type.
- *
- * @details Possible values are 8, 16, 32, and 64 bits.
- *          By definition time is represented at microsecond precision.
- */
-#define AMIROLLD_CFG_TIME_SIZE                  32
+#include <aos_alldconf.h>
 
 #endif /* ALLDCONF_H */
 
diff --git a/modules/LightRing_1-0/alldconf.h b/modules/LightRing_1-0/alldconf.h
index 79fa42d..f84df65 100644
--- a/modules/LightRing_1-0/alldconf.h
+++ b/modules/LightRing_1-0/alldconf.h
@@ -29,19 +29,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define ALLDCONF_H
 
 /*
- * compatibility guards
+ * common configuration
  */
-#define _AMIRO_LLD_CFG_
-#define AMIRO_LLD_CFG_VERSION_MAJOR             1
-#define AMIRO_LLD_CFG_VERSION_MINOR             1
-
-/**
- * @brief   Width of the apalTime_t data type.
- *
- * @details Possible values are 8, 16, 32, and 64 bits.
- *          By definition time is represented at microsecond precision.
- */
-#define AMIROLLD_CFG_TIME_SIZE                  32
+#include <aos_alldconf.h>
 
 #endif /* ALLDCONF_H */
 
diff --git a/modules/LightRing_1-2/alldconf.h b/modules/LightRing_1-2/alldconf.h
index 2f3ac50..7880802 100644
--- a/modules/LightRing_1-2/alldconf.h
+++ b/modules/LightRing_1-2/alldconf.h
@@ -28,26 +28,16 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef ALLDCONF_H
 #define ALLDCONF_H
 
-/*
- * compatibility guards
- */
-#define _AMIRO_LLD_CFG_
-#define AMIRO_LLD_CFG_VERSION_MAJOR             1
-#define AMIRO_LLD_CFG_VERSION_MINOR             1
-
-/**
- * @brief   Width of the apalTime_t data type.
- *
- * @details Possible values are 8, 16, 32, and 64 bits.
- *          By definition time is represented at microsecond precision.
- */
-#define AMIROLLD_CFG_TIME_SIZE                  32
-
 /**
  * @brief   TLC5947 chained configuration
  */
 #define TLC5947_LLD_CHAINED                     3
 
+/*
+ * common configuration
+ */
+#include <aos_alldconf.h>
+
 #endif /* ALLDCONF_H */
 
 /** @} */
diff --git a/modules/NUCLEO-F103RB/alldconf.h b/modules/NUCLEO-F103RB/alldconf.h
index a1e4ea4..0cb858d 100644
--- a/modules/NUCLEO-F103RB/alldconf.h
+++ b/modules/NUCLEO-F103RB/alldconf.h
@@ -29,19 +29,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define ALLDCONF_H
 
 /*
- * compatibility guards
+ * common configuration
  */
-#define _AMIRO_LLD_CFG_
-#define AMIRO_LLD_CFG_VERSION_MAJOR             1
-#define AMIRO_LLD_CFG_VERSION_MINOR             1
-
-/**
- * @brief   Width of the apalTime_t data type.
- *
- * @details Possible values are 8, 16, 32, and 64 bits.
- *          By definition time is represented at microsecond precision.
- */
-#define AMIROLLD_CFG_TIME_SIZE                  32
+#include <aos_alldconf.h>
 
 #endif /* ALLDCONF_H */
 
diff --git a/modules/NUCLEO-F401RE/alldconf.h b/modules/NUCLEO-F401RE/alldconf.h
index 2ba9287..9374aab 100644
--- a/modules/NUCLEO-F401RE/alldconf.h
+++ b/modules/NUCLEO-F401RE/alldconf.h
@@ -29,19 +29,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define ALLDCONF_H
 
 /*
- * compatibility guards
+ * common configuration
  */
-#define _AMIRO_LLD_CFG_
-#define AMIRO_LLD_CFG_VERSION_MAJOR             1
-#define AMIRO_LLD_CFG_VERSION_MINOR             1
-
-/**
- * @brief   Width of the apalTime_t data type.
- *
- * @details Possible values are 8, 16, 32, and 64 bits.
- *          By definition time is represented at microsecond precision.
- */
-#define AMIROLLD_CFG_TIME_SIZE                  32
+#include <aos_alldconf.h>
 
 #endif /* ALLDCONF_H */
 
diff --git a/modules/NUCLEO-F767ZI/alldconf.h b/modules/NUCLEO-F767ZI/alldconf.h
index 4fa4d41..187f5f5 100644
--- a/modules/NUCLEO-F767ZI/alldconf.h
+++ b/modules/NUCLEO-F767ZI/alldconf.h
@@ -29,19 +29,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define ALLDCONF_H
 
 /*
- * compatibility guards
+ * common configuration
  */
-#define _AMIRO_LLD_CFG_
-#define AMIRO_LLD_CFG_VERSION_MAJOR             1
-#define AMIRO_LLD_CFG_VERSION_MINOR             1
-
-/**
- * @brief   Width of the apalTime_t data type.
- *
- * @details Possible values are 8, 16, 32, and 64 bits.
- *          By definition time is represented at microsecond precision.
- */
-#define AMIROLLD_CFG_TIME_SIZE                  32
+#include <aos_alldconf.h>
 
 #endif /* ALLDCONF_H */
 
diff --git a/modules/NUCLEO-L476RG/alldconf.h b/modules/NUCLEO-L476RG/alldconf.h
index 25e56bd..2cad937 100644
--- a/modules/NUCLEO-L476RG/alldconf.h
+++ b/modules/NUCLEO-L476RG/alldconf.h
@@ -29,19 +29,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define ALLDCONF_H
 
 /*
- * compatibility guards
+ * common configuration
  */
-#define _AMIRO_LLD_CFG_
-#define AMIRO_LLD_CFG_VERSION_MAJOR             1
-#define AMIRO_LLD_CFG_VERSION_MINOR             1
-
-/**
- * @brief   Width of the apalTime_t data type.
- *
- * @details Possible values are 8, 16, 32, and 64 bits.
- *          By definition time is represented at microsecond precision.
- */
-#define AMIROLLD_CFG_TIME_SIZE                  32
+#include <aos_alldconf.h>
 
 #endif /* ALLDCONF_H */
 
diff --git a/modules/PowerManagement_1-1/alldconf.h b/modules/PowerManagement_1-1/alldconf.h
index 3273f0e..1b3f8c5 100644
--- a/modules/PowerManagement_1-1/alldconf.h
+++ b/modules/PowerManagement_1-1/alldconf.h
@@ -28,21 +28,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef ALLDCONF_H
 #define ALLDCONF_H
 
-/*
- * compatibility guards
- */
-#define _AMIRO_LLD_CFG_
-#define AMIRO_LLD_CFG_VERSION_MAJOR             1
-#define AMIRO_LLD_CFG_VERSION_MINOR             1
-
-/**
- * @brief   Width of the apalTime_t data type.
- *
- * @details Possible values are 8, 16, 32, and 64 bits.
- *          By definition time is represented at microsecond precision.
- */
-#define AMIROLLD_CFG_TIME_SIZE                  32
-
 /**
  * @brief   BQ27500 hardware version
  */
@@ -55,6 +40,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define PKxxxExxx_LLD_FREQUENCY_SPEC            4000
 #define PKxxxExxx_LLD_FREQUENCY_MAX             6000
 
+/*
+ * common configuration
+ */
+#include <aos_alldconf.h>
+
 #endif /* ALLDCONF_H */
 
 /** @} */
diff --git a/modules/PowerManagement_1-2/alldconf.h b/modules/PowerManagement_1-2/alldconf.h
index 99c1b1c..310974d 100644
--- a/modules/PowerManagement_1-2/alldconf.h
+++ b/modules/PowerManagement_1-2/alldconf.h
@@ -28,21 +28,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef ALLDCONF_H
 #define ALLDCONF_H
 
-/*
- * compatibility guards
- */
-#define _AMIRO_LLD_CFG_
-#define AMIRO_LLD_CFG_VERSION_MAJOR             1
-#define AMIRO_LLD_CFG_VERSION_MINOR             1
-
-/**
- * @brief   Width of the apalTime_t data type.
- *
- * @details Possible values are 8, 16, 32, and 64 bits.
- *          By definition time is represented at microsecond precision.
- */
-#define AMIROLLD_CFG_TIME_SIZE                  32
-
 /**
  * @brief   BQ27500 hardware version
  */
@@ -55,6 +40,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define PKxxxExxx_LLD_FREQUENCY_SPEC            4000
 #define PKxxxExxx_LLD_FREQUENCY_MAX             6000
 
+/*
+ * common configuration
+ */
+#include <aos_alldconf.h>
+
 #endif /* ALLDCONF_H */
 
 /** @} */
diff --git a/modules/STM32F407G-DISC1/alldconf.h b/modules/STM32F407G-DISC1/alldconf.h
index 157777c..a9a8bea 100644
--- a/modules/STM32F407G-DISC1/alldconf.h
+++ b/modules/STM32F407G-DISC1/alldconf.h
@@ -29,19 +29,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define ALLDCONF_H
 
 /*
- * compatibility guards
+ * common configuration
  */
-#define _AMIRO_LLD_CFG_
-#define AMIRO_LLD_CFG_VERSION_MAJOR             1
-#define AMIRO_LLD_CFG_VERSION_MINOR             1
-
-/**
- * @brief   Width of the apalTime_t data type.
- *
- * @details Possible values are 8, 16, 32, and 64 bits.
- *          By definition time is represented at microsecond precision.
- */
-#define AMIROLLD_CFG_TIME_SIZE                  32
+#include <aos_alldconf.h>
 
 #endif /* ALLDCONF_H */
 
diff --git a/periphery-lld/AMiRo-LLD b/periphery-lld/AMiRo-LLD
index bb7c534..1304b12 160000
--- a/periphery-lld/AMiRo-LLD
+++ b/periphery-lld/AMiRo-LLD
@@ -1 +1 @@
-Subproject commit bb7c53481afaa76d993538c5e2b2eae430cfb441
+Subproject commit 1304b12bd859603ad9f9b68493e1a3257f5e4595
diff --git a/periphery-lld/aos_alldconf.h b/periphery-lld/aos_alldconf.h
new file mode 100644
index 0000000..e0b3bc3
--- /dev/null
+++ b/periphery-lld/aos_alldconf.h
@@ -0,0 +1,117 @@
+/*
+AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
+Copyright (C) 2016..2019  Thomas Schöpping et al.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file
+ * @brief   Common AMiRo-LLD configuration file for all modules.
+ * @details Contains common AMiRo-LLD settings.
+ * @{
+ */
+
+#ifndef AOS_ALLDCONF_H
+#define AOS_ALLDCONF_H
+
+#define _AMIRO_LLD_CFG_
+#define AMIRO_LLD_CFG_VERSION_MAJOR             1
+#define AMIRO_LLD_CFG_VERSION_MINOR             1
+
+#include <aosconf.h>
+#include <hal.h>
+
+/**
+ * @brief   Width of the apalTime_t data type.
+ *
+ * @details Possible values are 8, 16, 32, and 64 bits.
+ *          By definition time is represented at microsecond precision.
+ */
+#if !defined(AMIROLLD_CFG_TIME_SIZE)
+  #define AMIROLLD_CFG_TIME_SIZE                32
+#endif
+
+/**
+ * @brief   Flag to enable/disable DBG API.
+ */
+#if !defined(AMIROLLD_CFG_DBG)
+  #define AMIROLLD_CFG_DBG                      AMIROOS_CFG_DBG
+#endif
+
+/**
+ * @brief   Flag to enable/disable GPIO API.
+ */
+#if !defined(AMIROLLD_CFG_GPIO)
+  #if (HAL_USE_PAL == TRUE)
+    #define AMIROLLD_CFG_GPIO                   true
+  #else
+    #define AMIROLLD_CFG_GPIO                   false
+  #endif
+#endif
+
+/**
+ * @brief   Flag to enable/disable PWM API.
+ */
+#if !defined(AMIROLLD_CFG_PWM)
+  #if (HAL_USE_PWM == TRUE)
+    #define AMIROLLD_CFG_PWM                    true
+  #else
+    #define AMIROLLD_CFG_PWM                    false
+  #endif
+#endif
+
+/**
+ * @brief   Flag to enable/disable QEI API.
+ */
+#if !defined(AMIROLLD_CFG_QEI)
+  #if (HAL_USE_QEI == TRUE)
+    #define AMIROLLD_CFG_QEI                    true
+  #else
+    #define AMIROLLD_CFG_QEI                    false
+  #endif
+#endif
+
+/**
+ * @brief   Flag to enable/disable I2C API.
+ */
+#if !defined(AMIROLLD_CFG_I2C)
+  #if (HAL_USE_I2C == TRUE)
+    #define AMIROLLD_CFG_I2C                    true
+  #else
+    #define AMIROLLD_CFG_I2C                    false
+  #endif
+#endif
+
+/**
+ * @brief   Flag to enable/disable SPI API.
+ */
+#if !defined(AMIROLLD_CFG_SPI)
+  #if (HAL_USE_SPI == TRUE)
+    #define AMIROLLD_CFG_SPI                    true
+  #else
+    #define AMIROLLD_CFG_SPI                    false
+  #endif
+#endif
+
+/**
+ * @brief   Hook macro to insert a custom header to periphAL.h file.
+ */
+#if !defined(AMIROLLD_CFG_PERIPHAL_HEADER)
+  #define AMIROLLD_CFG_PERIPHAL_HEADER          <aos_periphAL.h>
+#endif
+
+#endif /* AOS_ALLDCONF_H */
+
+/** @} */
diff --git a/periphery-lld/aos_periphAL.c b/periphery-lld/aos_periphAL.c
new file mode 100644
index 0000000..768b994
--- /dev/null
+++ b/periphery-lld/aos_periphAL.c
@@ -0,0 +1,488 @@
+/*
+AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
+Copyright (C) 2016..2019  Thomas Schöpping et al.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <periphAL.h>
+
+/*============================================================================*/
+/* DEBUG                                                                      */
+/*============================================================================*/
+
+#if (AMIROOS_CFG_DBG == true)
+
+#include <amiroos.h>
+#include <chprintf.h>
+
+void apalDbgAssertMsg(const bool c, const char* fmt, ...)
+{
+  if (!c) {
+    va_list ap;
+
+    va_start(ap, fmt);
+    chvprintf((BaseSequentialStream*)&aos.iostream, fmt, ap);
+    va_end(ap);
+    chThdExit(MSG_RESET);
+  }
+
+  return;
+}
+
+int apalDbgPrintf(const char* fmt, ...)
+{
+  va_list ap;
+
+  va_start(ap, fmt);
+  const int chars = chvprintf((BaseSequentialStream*)&aos.iostream, fmt, ap);
+  va_end(ap);
+
+  return chars;
+}
+
+#endif /* (AMIROOS_CFG_DBG == true) */
+
+/*============================================================================*/
+/* TIMING                                                                     */
+/*============================================================================*/
+
+#if (AMIROOS_CFG_DBG == true)
+
+void apalSleep(apalTime_t us)
+{
+  // check if the specified time can be represented by the system
+  apalDbgAssert(us <= chTimeI2US(TIME_INFINITE));
+
+  const sysinterval_t interval = chTimeUS2I(us);
+  // TIME_IMMEDIATE makes no sense and would even cause system halt
+  if (interval != TIME_IMMEDIATE) {
+    chThdSleep(interval);
+  }
+
+  return;
+}
+
+#endif /* (AMIROOS_CFG_DBG == true) */
+
+/*============================================================================*/
+/* GPIO                                                                       */
+/*============================================================================*/
+
+#if (HAL_USE_PAL == TRUE)
+
+apalExitStatus_t apalGpioRead(apalGpio_t* gpio, apalGpioState_t* const val)
+{
+  apalDbgAssert(gpio != NULL);
+  apalDbgAssert(val != NULL);
+
+  *val = (palReadLine(gpio->line) == PAL_HIGH) ? APAL_GPIO_HIGH : APAL_GPIO_LOW;
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalGpioWrite(apalGpio_t* gpio, const apalGpioState_t val)
+{
+  apalDbgAssert(gpio != NULL);
+
+  // palWriteLine() is not guaranteed to be atomic, thus the scheduler is locked.
+  syssts_t sysstatus = chSysGetStatusAndLockX();
+  palWriteLine(gpio->line, (val == APAL_GPIO_HIGH) ? PAL_HIGH : PAL_LOW);
+  chSysRestoreStatusX(sysstatus);
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalGpioToggle(apalGpio_t* gpio)
+{
+  apalDbgAssert(gpio != NULL);
+
+  // palWriteLine() is not guaranteed to be atomic, thus the scheduler is locked.
+  syssts_t sysstatus = chSysGetStatusAndLockX();
+  palWriteLine(gpio->line, (palReadLine(gpio->line) == PAL_HIGH) ? PAL_LOW : PAL_HIGH);
+  chSysRestoreStatusX(sysstatus);
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalGpioIsInterruptEnabled(apalGpio_t* gpio, bool* const enabled)
+{
+  apalDbgAssert(gpio != NULL);
+  apalDbgAssert(enabled != NULL);
+
+  *enabled = palIsLineEventEnabledX(gpio->line);
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalControlGpioGet(const apalControlGpio_t* const cgpio, apalControlGpioState_t* const val)
+{
+  apalDbgAssert(cgpio != NULL);
+  apalDbgAssert(cgpio->gpio != NULL);
+  apalDbgAssert(val != NULL);
+
+  *val = ((palReadLine(cgpio->gpio->line) == PAL_HIGH) ^ (cgpio->meta.active == APAL_GPIO_ACTIVE_HIGH)) ? APAL_GPIO_OFF : APAL_GPIO_ON;
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalControlGpioSet(const apalControlGpio_t* const cgpio, const apalControlGpioState_t val)
+{
+  apalDbgAssert(cgpio != NULL);
+  apalDbgAssert(cgpio->gpio != NULL);
+  apalDbgAssert(cgpio->meta.direction == APAL_GPIO_DIRECTION_OUTPUT || cgpio->meta.direction == APAL_GPIO_DIRECTION_BIDIRECTIONAL);
+
+  // palWriteLine() is not guaranteed to be atomic, thus the scheduler is locked.
+  syssts_t sysstatus = chSysGetStatusAndLockX();
+  palWriteLine(cgpio->gpio->line, ((cgpio->meta.active == APAL_GPIO_ACTIVE_HIGH) ^ (val == APAL_GPIO_ON)) ? PAL_LOW : PAL_HIGH);
+  chSysRestoreStatusX(sysstatus);
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalControlGpioSetInterrupt(const apalControlGpio_t* const cgpio, const bool enable)
+{
+  apalDbgAssert(cgpio != NULL);
+  apalDbgAssert(cgpio->gpio != NULL);
+
+  if (enable) {
+    apalDbgAssert(pal_lld_get_line_event(cgpio->gpio->line) != NULL);
+    palEnableLineEvent(cgpio->gpio->line, APAL2CH_EDGE(cgpio->meta.edge));
+  } else {
+    palDisableLineEvent(cgpio->gpio->line);
+  }
+
+  return APAL_STATUS_OK;
+}
+
+#endif /* (HAL_USE_PAL == TRUE) */
+
+/*============================================================================*/
+/* PWM                                                                        */
+/*============================================================================*/
+
+#if (HAL_USE_PWM == TRUE)
+
+apalExitStatus_t apalPWMSet(apalPWMDriver_t* pwm, const apalPWMchannel_t channel, const apalPWMwidth_t width)
+{
+  apalDbgAssert(pwm != NULL);
+
+  pwmEnableChannel(pwm, (pwmchannel_t)channel, pwm->period * ((float)width / (float)APAL_PWM_WIDTH_MAX) + 0.5f);
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalPWMGetFrequency(apalPWMDriver_t* pwm, apalPWMfrequency_t* const frequency)
+{
+  apalDbgAssert(pwm != NULL);
+  apalDbgAssert(frequency != NULL);
+
+  *frequency = pwm->config->frequency;
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalPWMGetPeriod(apalPWMDriver_t* pwm, apalPWMperiod_t* const period)
+{
+  apalDbgAssert(pwm != NULL);
+  apalDbgAssert(period != NULL);
+
+  *period = pwm->period;
+
+  return APAL_STATUS_OK;
+}
+
+#endif /* (HAL_USE_PWM == TRUE) */
+
+/*============================================================================*/
+/* QEI                                                                        */
+/*============================================================================*/
+
+#if (HAL_USE_QEI == TRUE)
+
+apalExitStatus_t apalQEIGetDirection(apalQEIDriver_t* qei, apalQEIDirection_t* const direction)
+{
+  apalDbgAssert(qei != NULL);
+  apalDbgAssert(direction != NULL);
+
+  *direction = (qei_lld_get_direction(qei)) ? APAL_QEI_DIRECTION_DOWN : APAL_QEI_DIRECTION_UP;
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalQEIGetPosition(apalQEIDriver_t* qei, apalQEICount_t* const position)
+{
+  apalDbgAssert(qei != NULL);
+  apalDbgAssert(position != NULL);
+
+  *position = qei_lld_get_position(qei);
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalQEIGetRange(apalQEIDriver_t* qei, apalQEICount_t* const range)
+{
+  apalDbgAssert(qei != NULL);
+  apalDbgAssert(range != NULL);
+
+  *range = qei_lld_get_range(qei);
+
+  return APAL_STATUS_OK;
+}
+
+#endif /* (HAL_USE_QEI == TRUE) */
+
+/*============================================================================*/
+/* I2C                                                                        */
+/*============================================================================*/
+
+#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
+
+apalExitStatus_t apalI2CMasterTransmit(apalI2CDriver_t* i2cd, const apalI2Caddr_t addr, const uint8_t* const txbuf, const size_t txbytes, uint8_t* const rxbuf, const size_t rxbytes, const apalTime_t timeout)
+{
+  apalDbgAssert(i2cd != NULL);
+
+#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
+  // check whether the I2C driver was locked externally
+  const bool i2cd_locked_external = i2cd->mutex.owner == currp;
+  if (!i2cd_locked_external) {
+    i2cAcquireBus(i2cd);
+  }
+#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wtype-limits"
+#if defined(STM32F1XX_I2C)
+  // Due to a hardware limitation, for STM32F1 platform the minimum number of bytes that can be received is two.
+  msg_t status = MSG_OK;
+  if (rxbytes == 1) {
+    uint8_t buffer[2];
+    status = i2cMasterTransmitTimeout(i2cd, addr, txbuf, txbytes, buffer, 2, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
+    rxbuf[0] = buffer[0];
+  } else {
+    status = i2cMasterTransmitTimeout(i2cd, addr, txbuf, txbytes, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
+  }
+#else /* defined(STM32F1XX_I2C) */
+  const msg_t status = i2cMasterTransmitTimeout(i2cd, addr, txbuf, txbytes, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
+#endif /* defined(STM32F1XX_I2C) */
+#pragma GCC diagnostic pop
+
+#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
+  if (!i2cd_locked_external) {
+    i2cReleaseBus(i2cd);
+  }
+#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
+
+  switch (status)
+  {
+    case MSG_OK:
+#if defined(STM32F1XX_I2C)
+      return (rxbytes != 1) ? APAL_STATUS_OK : APAL_STATUS_WARNING;
+#else /* defined(STM32F1XX_I2C) */
+      return APAL_STATUS_OK;
+#endif /* defined(STM32F1XX_I2C) */
+    case MSG_TIMEOUT:
+      return APAL_STATUS_TIMEOUT;
+    case MSG_RESET:
+    default:
+      return APAL_STATUS_ERROR;
+  }
+}
+
+apalExitStatus_t apalI2CMasterReceive(apalI2CDriver_t* i2cd, const apalI2Caddr_t addr, uint8_t* const rxbuf, const size_t rxbytes, const apalTime_t timeout)
+{
+  apalDbgAssert(i2cd != NULL);
+
+#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
+  // check whether the I2C driver was locked externally
+  const bool i2cd_locked_external = i2cd->mutex.owner == currp;
+  if (!i2cd_locked_external) {
+    i2cAcquireBus(i2cd);
+  }
+#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wtype-limits"
+#if defined(STM32F1XX_I2C)
+  // Due to a hardware limitation, for STM32F1 platform the minimum number of bytes that can be received is two.
+  msg_t status = MSG_OK;
+  if (rxbytes == 1) {
+    uint8_t buffer[2];
+    status = i2cMasterReceiveTimeout(i2cd, addr, buffer, 2, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
+    rxbuf[0] = buffer[0];
+  } else {
+    status = i2cMasterReceiveTimeout(i2cd, addr, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
+  }
+#else /* defined(STM32F1XX_I2C) */
+  const msg_t status = i2cMasterReceiveTimeout(i2cd, addr, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
+#endif /* defined(STM32F1XX_I2C) */
+#pragma GCC diagnostic pop
+
+#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
+  if (!i2cd_locked_external) {
+    i2cReleaseBus(i2cd);
+  }
+#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
+
+  switch (status)
+  {
+    case MSG_OK:
+#if defined(STM32F1XX_I2C)
+      return (rxbytes != 1) ? APAL_STATUS_OK : APAL_STATUS_WARNING;
+#else /* defined(STM32F1XX_I2C) */
+      return APAL_STATUS_OK;
+#endif /* defined(STM32F1XX_I2C) */
+    case MSG_TIMEOUT:
+      return APAL_STATUS_TIMEOUT;
+    case MSG_RESET:
+    default:
+      return APAL_STATUS_ERROR;
+  }
+}
+
+#endif /* (HAL_USE_I2C == TRUE) */
+
+/*============================================================================*/
+/* SPI                                                                        */
+/*============================================================================*/
+
+#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
+
+apalExitStatus_t apalSPITransmit(apalSPIDriver_t* spid, const uint8_t* const data, const size_t length)
+{
+  apalDbgAssert(spid != NULL);
+
+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
+  // check whether the SPI driver was locked externally
+  const bool spid_locked_external = spid->mutex.owner == currp;
+  if (!spid_locked_external) {
+    spiAcquireBus(spid);
+  }
+#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
+
+  spiSelect(spid);
+  spiSend(spid, length, data);
+  spiUnselect(spid);
+
+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
+  if (!spid_locked_external) {
+    spiReleaseBus(spid);
+  }
+#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalSPIReceive(apalSPIDriver_t* spid, uint8_t* const data, const size_t length)
+{
+  apalDbgAssert(spid != NULL);
+
+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
+  // check whether the SPI driver was locked externally
+  const bool spid_locked_external = spid->mutex.owner == currp;
+  if (!spid_locked_external) {
+    spiAcquireBus(spid);
+  }
+#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
+
+  spiSelect(spid);
+  spiReceive(spid, length, data);
+  spiUnselect(spid);
+
+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
+  if (!spid_locked_external) {
+    spiReleaseBus(spid);
+  }
+#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalSPITransmitAndReceive(apalSPIDriver_t* spid, const uint8_t* const txData , uint8_t* const rxData, const size_t txLength, const size_t rxLength)
+{
+  apalDbgAssert(spid != NULL);
+
+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
+  // check whether the SPI driver was locked externally
+  const bool spid_locked_external = spid->mutex.owner == currp;
+  if (!spid_locked_external) {
+    spiAcquireBus(spid);
+  }
+#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
+
+  spiSelect(spid);
+  spiSend(spid, txLength, txData);
+  spiReceive(spid, rxLength, rxData);
+  spiUnselect(spid);
+
+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
+  if (!spid_locked_external) {
+    spiReleaseBus(spid);
+  }
+#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalSPIExchange(apalSPIDriver_t* spid, const uint8_t* const txData , uint8_t* const rxData, const size_t length)
+{
+  apalDbgAssert(spid != NULL);
+
+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
+  // check whether the SPI driver was locked externally
+  const bool spid_locked_external = spid->mutex.owner == currp;
+  if (!spid_locked_external) {
+    spiAcquireBus(spid);
+  }
+#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
+
+  spiSelect(spid);
+  spiExchange(spid, length, txData, rxData);
+  spiUnselect(spid);
+
+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
+  if (!spid_locked_external) {
+    spiReleaseBus(spid);
+  }
+#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
+
+  return APAL_STATUS_OK;
+}
+
+apalExitStatus_t apalSPIReconfigure(apalSPIDriver_t* spid, const apalSPIConfig_t* config)
+{
+  apalDbgAssert(spid != NULL);
+  apalDbgAssert(config != NULL);
+
+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
+  // check whether the SPI driver was locked externally
+  const bool spid_locked_external = spid->mutex.owner == currp;
+  if (!spid_locked_external) {
+    spiAcquireBus(spid);
+  }
+#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
+
+  spiStop(spid);
+  spiStart(spid, config);
+
+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
+  if (!spid_locked_external) {
+    spiReleaseBus(spid);
+  }
+#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
+
+  return APAL_STATUS_OK;
+}
+
+#endif /* (HAL_USE_SPI == TRUE) */
diff --git a/periphery-lld/aos_periphAL.h b/periphery-lld/aos_periphAL.h
new file mode 100644
index 0000000..c1f371d
--- /dev/null
+++ b/periphery-lld/aos_periphAL.h
@@ -0,0 +1,132 @@
+/*
+AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
+Copyright (C) 2016..2019  Thomas Schöpping et al.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef AMIROOS_PERIPHAL_H
+#define AMIROOS_PERIPHAL_H
+
+/*============================================================================*/
+/* DEPENDENCIES                                                               */
+/*============================================================================*/
+
+#include <aosconf.h>
+#include <hal.h>
+
+/*============================================================================*/
+/* DEBUG                                                                      */
+/*============================================================================*/
+
+#if (AMIROOS_CFG_DBG != true)
+
+#define apalDbgAssert(condition)
+
+#define apalDbgPrintf(fmt, ...)                 0
+
+#endif /* (AMIROOS_CFG_DBG == true) */
+
+/*============================================================================*/
+/* TIMING                                                                     */
+/*============================================================================*/
+
+#if (AMIROOS_CFG_DBG != true)
+
+#define apalSleep(us)   chThdSleep(chTimeUS2I((apalTime_t)us))
+
+#endif /* (AMIROOS_CFG_DBG == true) */
+
+/*============================================================================*/
+/* GPIO                                                                       */
+/*============================================================================*/
+
+#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
+
+/**
+ * @brief GPIO driver type.
+ */
+typedef struct {
+  ioline_t line;
+} PACKED_VAR apalGpio_t;
+
+/**
+ * @brief   Converts an apalGpioEdge_t to an ChibiOS PAL edge.
+ */
+#define APAL2CH_EDGE(edge)                                            \
+  ((edge == APAL_GPIO_EDGE_RISING) ? PAL_EVENT_MODE_RISING_EDGE :     \
+    (edge == APAL_GPIO_EDGE_FALLING) ? PAL_EVENT_MODE_FALLING_EDGE :  \
+     (edge == APAL_GPIO_EDGE_BOTH) ? PAL_EVENT_MODE_BOTH_EDGES :      \
+      PAL_EVENT_MODE_DISABLED)
+
+#endif /* (HAL_USE_PAL == TRUE) */
+
+/*============================================================================*/
+/* PWM                                                                        */
+/*============================================================================*/
+
+#if (HAL_USE_PWM == TRUE) || defined (__DOXYGEN__)
+
+/**
+ * @brief PWM driver type.
+ */
+typedef PWMDriver apalPWMDriver_t;
+
+#endif /* (HAL_USE_PWM == TRUE) */
+
+/*============================================================================*/
+/* QEI                                                                        */
+/*============================================================================*/
+
+#if (HAL_USE_QEI == TRUE) || defined (__DOXYGEN__)
+
+/**
+ * @brief QEI driver type.
+ */
+typedef QEIDriver apalQEIDriver_t;
+
+#endif /* (HAL_USE_QEI == TRUE) */
+
+/*============================================================================*/
+/* I2C                                                                        */
+/*============================================================================*/
+
+#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
+
+/**
+ * @brief I2C driver type.
+ */
+typedef I2CDriver apalI2CDriver_t;
+
+#endif /* (HAL_USE_I2C == TRUE) */
+
+/*============================================================================*/
+/* SPI                                                                        */
+/*============================================================================*/
+
+#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
+
+/**
+ * @brief SPI driver type.
+ */
+typedef SPIDriver apalSPIDriver_t;
+
+/**
+ * @brief SPI confguration type.
+ */
+typedef SPIConfig apalSPIConfig_t;
+
+#endif /* (HAL_USE_SPI == TRUE) */
+
+#endif /* AMIROOS_PERIPHAL_H */
diff --git a/periphery-lld/periphAL.c b/periphery-lld/periphAL.c
deleted file mode 100644
index c137feb..0000000
--- a/periphery-lld/periphAL.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
-Copyright (C) 2016..2019  Thomas Schöpping et al.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <amiro-lld.h>
-
-#if (AMIROOS_CFG_DBG == true) || defined(__DOXYGEN__)
-
-#include <amiroos.h>
-#include <chprintf.h>
-
-/**
- * @brief Assert function to check a given condition and print a message string.
- *
- * @param[in] c     The condition to check.
- * @param[in] fmt   Formatted message string to print.
- */
-void _apalDbgAssertMsg(const bool c, const char* fmt, ...)
-{
-  if (!c) {
-    va_list ap;
-
-    va_start(ap, fmt);
-    chvprintf((BaseSequentialStream*)&aos.iostream, fmt, ap);
-    va_end(ap);
-    chThdExit(MSG_RESET);
-  }
-  return;
-}
-
-/**
- * @brief Printf function for messages printed only in debug builds.
- *
- * @param[in] fmt   Formatted string to print.
- */
-void apalDbgPrintf(const char* fmt, ...)
-{
-  va_list ap;
-
-  va_start(ap, fmt);
-  chvprintf((BaseSequentialStream*)&aos.iostream, fmt, ap);
-  va_end(ap);
-
-  return;
-}
-
-#endif /* (AMIROOS_CFG_DBG == true) */
diff --git a/periphery-lld/periphAL.h b/periphery-lld/periphAL.h
deleted file mode 100644
index 027f815..0000000
--- a/periphery-lld/periphAL.h
+++ /dev/null
@@ -1,724 +0,0 @@
-/*
-AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
-Copyright (C) 2016..2019  Thomas Schöpping et al.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef AMIROOS_PERIPHAL_H
-#define AMIROOS_PERIPHAL_H
-
-#include <amiro-lld.h>
-
-/*============================================================================*/
-/* VERSION                                                                    */
-/*============================================================================*/
-
-/**
- * @brief   The periphery abstraction layer interface major version.
- * @note    Changes of the major version imply incompatibilities.
- */
-#define PERIPHAL_VERSION_MAJOR    1
-
-/**
- * @brief   The periphery abstraction layer interface minor version.
- * @note    A higher minor version implies new functionalty, but all old interfaces are still available.
- */
-#define PERIPHAL_VERSION_MINOR    1
-
-/*============================================================================*/
-/* DEPENDENCIES                                                               */
-/*============================================================================*/
-
-#include <aosconf.h>
-#include <hal.h>
-
-/*============================================================================*/
-/* DEBUG                                                                      */
-/*============================================================================*/
-
-#if (AMIROOS_CFG_DBG == true) || defined(__DOXYGEN__)
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* defined(__cplusplus) */
-  void _apalDbgAssertMsg(const bool c, const char* fmt, ...);
-  void apalDbgPrintf(const char* fmt, ...);
-#if defined(__cplusplus)
-}
-#endif /* defined(__cplusplus) */
-
-/**
- * @brief Assert function to check a given condition.
- *
- * @param[in] c     The condition to check.
- */
-#define apalDbgAssert(c) _apalDbgAssertMsg(c, "%s(%u): apalDbgAssert failed", __FILE__, __LINE__)
-
-
-#else /* (AMIROOS_CFG_DBG != true) */
-
-#define apalDbgAssert(condition)                                              \
-  (void)(condition)
-
-#define apalDbgAssertMsg(condition, fmt, ...)                                 \
-  (void)(condition);                                                          \
-  (void)(fmt)
-
-#define apalDbgPrintf(fmt, ...)                                               \
-  (void)(fmt)
-
-#endif /* (AMIROOS_CFG_DBG == true) */
-
-/*============================================================================*/
-/* GENERAL                                                                    */
-/*============================================================================*/
-
-/**
- * @brief Delay execution by a specific number of microseconds.
- *
- * @param[in]   us    Time to sleep until execution continues in microseconds.
- */
-static inline void apalSleep(apalTime_t us)
-{
-  // check if the specified time can be represented by the system
-  apalDbgAssert(us <= chTimeI2US(TIME_INFINITE));
-
-  const sysinterval_t interval = chTimeUS2I(us);
-  // TIME_IMMEDIATE makes no sense and would even cause system halt
-  if (interval != TIME_IMMEDIATE) {
-    chThdSleep(interval);
-  }
-  return;
-}
-
-/*============================================================================*/
-/* GPIO                                                                       */
-/*============================================================================*/
-
-#if (HAL_USE_PAL == TRUE) || defined (__DOXYGEN__)
-
-/**
- * @brief GPIO driver type.
- */
-struct apalGpio_t {
-  ioline_t line;
-} PACKED_VAR;
-
-/**
- * @brief Read the current value of a GPIO pin.
- *
- * @param[in]   gpio  GPIO to read.
- * @param[out]  val   Current value of the GPIO.
- *
- * @return The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalGpioRead(apalGpio_t* gpio, apalGpioState_t* const val)
-{
-  apalDbgAssert(gpio != NULL);
-  apalDbgAssert(val != NULL);
-
-  *val = (palReadLine(gpio->line) == PAL_HIGH) ? APAL_GPIO_HIGH : APAL_GPIO_LOW;
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief Set the value of a GPIO pin.
- *
- * @param[in] gpio  GPIO to write.
- * @param[in] val   Value to set for the GPIO.
- *
- * @return The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalGpioWrite(apalGpio_t* gpio, const apalGpioState_t val)
-{
-  apalDbgAssert(gpio != NULL);
-
-  // palWriteLine() is not guaranteed to be atomic, thus the scheduler is locked.
-  syssts_t sysstatus = chSysGetStatusAndLockX();
-  palWriteLine(gpio->line, (val == APAL_GPIO_HIGH) ? PAL_HIGH : PAL_LOW);
-  chSysRestoreStatusX(sysstatus);
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief Toggle the output of a GPIO.
- *
- * @param[in] gpio  GPIO to toggle.
- *
- * @return The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalGpioToggle(apalGpio_t* gpio)
-{
-  apalDbgAssert(gpio != NULL);
-
-  // palWriteLine() is not guaranteed to be atomic, thus the scheduler is locked.
-  syssts_t sysstatus = chSysGetStatusAndLockX();
-  palWriteLine(gpio->line, (palReadLine(gpio->line) == PAL_HIGH) ? PAL_LOW : PAL_HIGH);
-  chSysRestoreStatusX(sysstatus);
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief Return the interrupt enable status of the GPIO.
- *
- * @param[in]   gpio      GPIO to check.
- * @param[out]  enabled   Flag, indicating whether interrupt is enabled for the GPIO.
- *
- * @return The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalGpioIsInterruptEnabled(apalGpio_t* gpio, bool* const enabled)
-{
-  apalDbgAssert(gpio != NULL);
-  apalDbgAssert(enabled != NULL);
-
-  *enabled = palIsLineEventEnabledX(gpio->line);
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief Get the current on/off state of a control GPIO.
- *
- * @param[in]   gpio  Control GPIO to read.
- * @param[out]  val   Current activation status of the control GPIO.
- *
- * @return The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalControlGpioGet(const apalControlGpio_t* const cgpio, apalControlGpioState_t* const val)
-{
-  apalDbgAssert(cgpio != NULL);
-  apalDbgAssert(cgpio->gpio != NULL);
-  apalDbgAssert(val != NULL);
-
-  *val = ((palReadLine(cgpio->gpio->line) == PAL_HIGH) ^ (cgpio->meta.active == APAL_GPIO_ACTIVE_HIGH)) ? APAL_GPIO_OFF : APAL_GPIO_ON;
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief Turn a control GPIO 'on' or 'off' respectively.
- *
- * @param[in] gpio  Control GPIO to set.
- * @param[in] val   Activation value to set for the control GPIO.
- *
- * @return The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalControlGpioSet(const apalControlGpio_t* const cgpio, const apalControlGpioState_t val)
-{
-  apalDbgAssert(cgpio != NULL);
-  apalDbgAssert(cgpio->gpio != NULL);
-  apalDbgAssert(cgpio->meta.direction == APAL_GPIO_DIRECTION_OUTPUT || cgpio->meta.direction == APAL_GPIO_DIRECTION_BIDIRECTIONAL);
-
-  // palWriteLine() is not guaranteed to be atomic, thus the scheduler is locked.
-  syssts_t sysstatus = chSysGetStatusAndLockX();
-  palWriteLine(cgpio->gpio->line, ((cgpio->meta.active == APAL_GPIO_ACTIVE_HIGH) ^ (val == APAL_GPIO_ON)) ? PAL_LOW : PAL_HIGH);
-  chSysRestoreStatusX(sysstatus);
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief   Converts an apalGpioEdge_t to an ChibiOS PAL edge.
- */
-#define APAL2CH_EDGE(edge)                                            \
-  ((edge == APAL_GPIO_EDGE_RISING) ? PAL_EVENT_MODE_RISING_EDGE :     \
-    (edge == APAL_GPIO_EDGE_FALLING) ? PAL_EVENT_MODE_FALLING_EDGE :  \
-     (edge == APAL_GPIO_EDGE_BOTH) ? PAL_EVENT_MODE_BOTH_EDGES :      \
-      PAL_EVENT_MODE_DISABLED)
-
-/**
- * @brief Enable or disable the interrupt event functionality.
- *
- * @param[in] cgpio   Control GPIO to set.
- * @param[in] enable  Flag, indicating whether the interrupt shall be activated (true) or deactivated (false).
- *
- * @return The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalControlGpioSetInterrupt(const apalControlGpio_t* const cgpio, const bool enable)
-{
-  apalDbgAssert(cgpio != NULL);
-  apalDbgAssert(cgpio->gpio != NULL);
-
-  if (enable) {
-    apalDbgAssert(pal_lld_get_line_event(cgpio->gpio->line) != NULL);
-    palEnableLineEvent(cgpio->gpio->line, APAL2CH_EDGE(cgpio->meta.edge));
-  } else {
-    palDisableLineEvent(cgpio->gpio->line);
-  }
-
-  return APAL_STATUS_OK;
-}
-
-#endif /* (HAL_USE_PAL == TRUE) */
-
-/*============================================================================*/
-/* PWM                                                                        */
-/*============================================================================*/
-
-#if (HAL_USE_PWM == TRUE) || defined (__DOXYGEN__)
-
-/**
- * @brief PWM driver type.
- */
-typedef PWMDriver apalPWMDriver_t;
-
-/**
- * @brief   Set the PWM with given parameters.
- *
- * @param[in] pwm       PWM driver to set.
- * @param[in] channel   Channel of the PWM driver to set.
- * @param[in] width     Width to set the channel to.
- *
- * @return  The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalPWMSet(apalPWMDriver_t* pwm, const apalPWMchannel_t channel, const apalPWMwidth_t width)
-{
-  apalDbgAssert(pwm != NULL);
-
-  pwmEnableChannel(pwm, (pwmchannel_t)channel, pwm->period * ((float)width / (float)APAL_PWM_WIDTH_MAX) + 0.5f);
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief   Retrieve the current frequency of the PWM.
- *
- * @param[in]  pwm        PWM driver to read.
- * @param[out] frequency  The currently set frequency.
- *
- * @return  The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalPWMGetFrequency(apalPWMDriver_t* pwm, apalPWMfrequency_t* const frequency)
-{
-  apalDbgAssert(pwm != NULL);
-  apalDbgAssert(frequency != NULL);
-
-  *frequency = pwm->config->frequency;
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief   Retrieve the current period of the PWM.
- *
- * @param[in]   pwm     PWM driver to read.
- * @param[out]  period  The currently set period.
- *
- * @return  The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalPWMGetPeriod(apalPWMDriver_t* pwm, apalPWMperiod_t* const period)
-{
-  apalDbgAssert(pwm != NULL);
-  apalDbgAssert(period != NULL);
-
-  *period = pwm->period;
-  return APAL_STATUS_OK;
-}
-
-#endif /* (HAL_USE_PWM == TRUE) */
-
-/*============================================================================*/
-/* QEI                                                                        */
-/*============================================================================*/
-
-#if (HAL_USE_QEI == TRUE) || defined (__DOXYGEN__)
-
-/**
- * @brief QEI driver type.
- */
-typedef QEIDriver apalQEIDriver_t;
-
-/**
- * @brief Gets the direction of the last transition.
- *
- * @param[in]   qei         The QEI driver to use.
- * @param[out]  direction   The direction of the last transition.
- *
- * @return The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalQEIGetDirection(apalQEIDriver_t* qei, apalQEIDirection_t* const direction)
-{
-  apalDbgAssert(qei != NULL);
-  apalDbgAssert(direction != NULL);
-
-  *direction = (qei_lld_get_direction(qei)) ? APAL_QEI_DIRECTION_DOWN : APAL_QEI_DIRECTION_UP;
-
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief Gets the current position of the ecnoder.
- *
- * @param[in]   qei       The QEI driver to use.
- * @param[out]  position  The current position of the encoder.
- *
- * @return The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalQEIGetPosition(apalQEIDriver_t* qei, apalQEICount_t* const position)
-{
-  apalDbgAssert(qei != NULL);
-  apalDbgAssert(position != NULL);
-
-  *position = qei_lld_get_position(qei);
-
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief Gets the value range of the encoder.
- *
- * @param[in]   qei     The QEI driver to use.
- * @param[out]  range   The value range of the encoder.
- *
- * @return The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalQEIGetRange(apalQEIDriver_t* qei, apalQEICount_t* const range)
-{
-  apalDbgAssert(qei != NULL);
-  apalDbgAssert(range != NULL);
-
-  *range = qei_lld_get_range(qei);
-
-  return APAL_STATUS_OK;
-}
-
-#endif /* (HAL_USE_QEI == TRUE) */
-
-/*============================================================================*/
-/* I2C                                                                        */
-/*============================================================================*/
-
-#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
-
-/**
- * @brief I2C driver type.
- */
-typedef I2CDriver apalI2CDriver_t;
-
-/**
- * @brief Transmit data and receive a response.
- *
- * @param[in]   i2cd      The I2C driver to use.
- * @param[in]   addr      Address to write to.
- * @param[in]   txbuf     Buffer containing data to send.
- * @param[in]   txbytes   Number of bytes to send.
- * @param[out]  rxbuf     Buffer to store a response to.
- * @param[in]   rxbytes   Number of bytes to receive.
- * @param[in]   timeout   Timeout for the function to return (in microseconds).
- *
- * @return The status indicates whether the function call was succesful or a timeout occurred.
- */
-static inline apalExitStatus_t apalI2CMasterTransmit(apalI2CDriver_t* i2cd, const apalI2Caddr_t addr, const uint8_t* const txbuf, const size_t txbytes, uint8_t* const rxbuf, const size_t rxbytes, const apalTime_t timeout)
-{
-  apalDbgAssert(i2cd != NULL);
-
-#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
-  // check whether the I2C driver was locked externally
-  const bool i2cd_locked_external = i2cd->mutex.owner == currp;
-  if (!i2cd_locked_external) {
-    i2cAcquireBus(i2cd);
-  }
-#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wtype-limits"
-#if defined(STM32F1XX_I2C)
-  // Due to a hardware limitation, for STM32F1 platform the minimum number of bytes that can be received is two.
-  msg_t status = MSG_OK;
-  if (rxbytes == 1) {
-    uint8_t buffer[2];
-    status = i2cMasterTransmitTimeout(i2cd, addr, txbuf, txbytes, buffer, 2, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
-    rxbuf[0] = buffer[0];
-  } else {
-    status = i2cMasterTransmitTimeout(i2cd, addr, txbuf, txbytes, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
-  }
-#else /* defined(STM32F1XX_I2C) */
-  const msg_t status = i2cMasterTransmitTimeout(i2cd, addr, txbuf, txbytes, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
-#endif /* defined(STM32F1XX_I2C) */
-#pragma GCC diagnostic pop
-
-#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
-  if (!i2cd_locked_external) {
-    i2cReleaseBus(i2cd);
-  }
-#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
-
-  switch (status)
-  {
-    case MSG_OK:
-#if defined(STM32F1XX_I2C)
-      return (rxbytes != 1) ? APAL_STATUS_OK : APAL_STATUS_WARNING;
-#else /* defined(STM32F1XX_I2C) */
-      return APAL_STATUS_OK;
-#endif /* defined(STM32F1XX_I2C) */
-    case MSG_TIMEOUT:
-      return APAL_STATUS_TIMEOUT;
-    case MSG_RESET:
-    default:
-      return APAL_STATUS_ERROR;
-  }
-}
-
-/**
- * @brief Read data from a specific address.
- *
- * @param[in]   i2cd      The I2C driver to use.
- * @param[in]   addr      Address to read.
- * @param[out]  rxbuf     Buffer to store the response to.
- * @param[in]   rxbytes   Number of bytes to receive.
- * @param[in]   timeout   Timeout for the function to return (in microseconds).
- *
- * @return The status indicates whether the function call was succesful or a timeout occurred.
- */
-static inline apalExitStatus_t apalI2CMasterReceive(apalI2CDriver_t* i2cd, const apalI2Caddr_t addr, uint8_t* const rxbuf, const size_t rxbytes, const apalTime_t timeout)
-{
-  apalDbgAssert(i2cd != NULL);
-
-#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
-  // check whether the I2C driver was locked externally
-  const bool i2cd_locked_external = i2cd->mutex.owner == currp;
-  if (!i2cd_locked_external) {
-    i2cAcquireBus(i2cd);
-  }
-#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wtype-limits"
-#if defined(STM32F1XX_I2C)
-  // Due to a hardware limitation, for STM32F1 platform the minimum number of bytes that can be received is two.
-  msg_t status = MSG_OK;
-  if (rxbytes == 1) {
-    uint8_t buffer[2];
-    status = i2cMasterReceiveTimeout(i2cd, addr, buffer, 2, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
-    rxbuf[0] = buffer[0];
-  } else {
-    status = i2cMasterReceiveTimeout(i2cd, addr, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
-  }
-#else /* defined(STM32F1XX_I2C) */
-  const msg_t status = i2cMasterReceiveTimeout(i2cd, addr, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
-#endif /* defined(STM32F1XX_I2C) */
-#pragma GCC diagnostic pop
-
-#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
-  if (!i2cd_locked_external) {
-    i2cReleaseBus(i2cd);
-  }
-#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
-
-  switch (status)
-  {
-    case MSG_OK:
-#if defined(STM32F1XX_I2C)
-      return (rxbytes != 1) ? APAL_STATUS_OK : APAL_STATUS_WARNING;
-#else /* defined(STM32F1XX_I2C) */
-      return APAL_STATUS_OK;
-#endif /* defined(STM32F1XX_I2C) */
-    case MSG_TIMEOUT:
-      return APAL_STATUS_TIMEOUT;
-    case MSG_RESET:
-    default:
-      return APAL_STATUS_ERROR;
-  }
-}
-
-#endif /* (HAL_USE_I2C == TRUE) */
-
-/*============================================================================*/
-/* SPI                                                                        */
-/*============================================================================*/
-
-#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
-
-/**
- * @brief SPI driver type.
- */
-typedef SPIDriver apalSPIDriver_t;
-
-/**
- * @brief SPI confguration type.
- */
-typedef SPIConfig apalSPIConfig_t;
-
-/**
- * @brief Reconfigure an SPI driver.
- *
- * @param[in] spid    The SPI driver to be reconfigured.
- * @param[in] config  Configuration to apply.
- *
- * @return The status indicates whether the function call was succesful.
- */
-static inline apalExitStatus_t apalSPIReconfigure(apalSPIDriver_t* spid, const apalSPIConfig_t* config)
-{
-  apalDbgAssert(spid != NULL);
-  apalDbgAssert(config != NULL);
-
-#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
-  // check whether the SPI driver was locked externally
-  const bool spid_locked_external = spid->mutex.owner == currp;
-  if (!spid_locked_external) {
-    spiAcquireBus(spid);
-  }
-#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
-
-  spiStop(spid);
-  spiStart(spid, config);
-
-#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
-  if (!spid_locked_external) {
-    spiReleaseBus(spid);
-  }
-#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
-
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief Transmit and receive data from SPI
- *
- * @param[in]   spid      The SPI driver to use.
- * @param[in]   txData    Buffer containing data to send.
- * @param[out]  rxData    Buffer to store.
- * @param[in]   length    Number of bytes to send.
- *
- * @return The status indicates whether the function call was succesful.
- */
-static inline apalExitStatus_t apalSPIExchange(apalSPIDriver_t* spid, const uint8_t* const txData , uint8_t* const rxData, const size_t length)
-{
-  apalDbgAssert(spid != NULL);
-
-#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
-  // check whether the SPI driver was locked externally
-  const bool spid_locked_external = spid->mutex.owner == currp;
-  if (!spid_locked_external) {
-    spiAcquireBus(spid);
-  }
-#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
-
-  spiSelect(spid);
-  spiExchange(spid, length, txData, rxData);
-  spiUnselect(spid);
-
-#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
-  if (!spid_locked_external) {
-    spiReleaseBus(spid);
-  }
-#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
-
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief Receive data from SPI
- *
- * @param[in]   spid      The SPI driver to use.
- * @param[out]  data      Buffer to store.
- * @param[in]   length    Number of bytes to send.
- *
- * @return The status indicates whether the function call was succesful.
- */
-static inline apalExitStatus_t apalSPIReceive(apalSPIDriver_t* spid, uint8_t* const data, const size_t length)
-{
-  apalDbgAssert(spid != NULL);
-
-#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
-  // check whether the SPI driver was locked externally
-  const bool spid_locked_external = spid->mutex.owner == currp;
-  if (!spid_locked_external) {
-    spiAcquireBus(spid);
-  }
-#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
-
-  spiSelect(spid);
-  spiReceive(spid, length, data);
-  spiUnselect(spid);
-
-#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
-  if (!spid_locked_external) {
-    spiReleaseBus(spid);
-  }
-#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
-
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief Transmit data to SPI
- *
- * @param[in]   spid      The SPI driver to use.
- * @param[in]   data      Buffer containing data to send.
- * @param[in]   length    Number of bytes to send.
- *
- * @return The status indicates whether the function call was succesful.
- */
-static inline apalExitStatus_t apalSPITransmit(apalSPIDriver_t* spid, const uint8_t* const data, const size_t length)
-{
-  apalDbgAssert(spid != NULL);
-
-#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
-  // check whether the SPI driver was locked externally
-  const bool spid_locked_external = spid->mutex.owner == currp;
-  if (!spid_locked_external) {
-    spiAcquireBus(spid);
-  }
-#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
-
-  spiSelect(spid);
-  spiSend(spid, length, data);
-  spiUnselect(spid);
-
-#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
-  if (!spid_locked_external) {
-    spiReleaseBus(spid);
-  }
-#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
-
-  return APAL_STATUS_OK;
-}
-
-/**
- * @brief Transmit data to SPI and receive data afterwards without releasing the bus in between.
- *
- * @param   spid        The SPI driver to use.
- * @param   txData      Transmit data buffer.
- * @param   rxData      Receive data buffer.
- * @param   txLength    Number of bytes to send.
- * @param   rxLength    Number of bytes to receive.
- *
- * @return The status indicates whether the function call was succesful.
- */
-static inline apalExitStatus_t apalSPITransmitAndReceive(apalSPIDriver_t* spid, const uint8_t* const txData , uint8_t* const rxData, const size_t txLength, const size_t rxLength)
-{
-  apalDbgAssert(spid != NULL);
-
-#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
-  // check whether the SPI driver was locked externally
-  const bool spid_locked_external = spid->mutex.owner == currp;
-  if (!spid_locked_external) {
-    spiAcquireBus(spid);
-  }
-#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
-
-  spiSelect(spid);
-  spiSend(spid, txLength, txData);
-  spiReceive(spid, rxLength, rxData);
-  spiUnselect(spid);
-
-#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
-  if (!spid_locked_external) {
-    spiReleaseBus(spid);
-  }
-#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
-
-  return APAL_STATUS_OK;
-}
-
-#endif /* (HAL_USE_SPI == TRUE) */
-
-#endif /* AMIROOS_PERIPHAL_H */
diff --git a/periphery-lld/periphery-lld.mk b/periphery-lld/periphery-lld.mk
index 75d22da..b0e2593 100644
--- a/periphery-lld/periphery-lld.mk
+++ b/periphery-lld/periphery-lld.mk
@@ -34,5 +34,5 @@ AMIROOS_PERIPHERYLLD_INC = $(AMIRO_PERIPHERYLLD_DIR:/=) \
                            $(AMIROLLD_INC)
 
 # C source files
-AMIROOS_PERIPHERYLLD_CSRC = $(AMIRO_PERIPHERYLLD_DIR)periphAL.c \
+AMIROOS_PERIPHERYLLD_CSRC = $(AMIRO_PERIPHERYLLD_DIR)aos_periphAL.c \
                             $(AMIROLLD_CSRC)
