aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authoracirillo87 <acirillo87@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-03-05 15:22:45 +0000
committeracirillo87 <acirillo87@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-03-05 15:22:45 +0000
commit418ccee5b51db721f2e56789e0e5e44d606c2e27 (patch)
tree083178bf7c270f89e1faad43ce70af11f0136253 /os
parentac49c69ca3c062801c55a5bafc705157918f7b6e (diff)
downloadChibiOS-418ccee5b51db721f2e56789e0e5e44d606c2e27.tar.gz
ChibiOS-418ccee5b51db721f2e56789e0e5e44d606c2e27.tar.bz2
ChibiOS-418ccee5b51db721f2e56789e0e5e44d606c2e27.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5362 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r--os/hal/platforms/SPC5xx/eTimer_v1/icu_lld.c1426
-rw-r--r--os/hal/platforms/SPC5xx/eTimer_v1/icu_lld.h512
2 files changed, 1938 insertions, 0 deletions
diff --git a/os/hal/platforms/SPC5xx/eTimer_v1/icu_lld.c b/os/hal/platforms/SPC5xx/eTimer_v1/icu_lld.c
new file mode 100644
index 000000000..68ca17b0b
--- /dev/null
+++ b/os/hal/platforms/SPC5xx/eTimer_v1/icu_lld.c
@@ -0,0 +1,1426 @@
+/*
+ * Licensed under ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * @brief SPC5xx low level icu driver header.
+ *
+ * @addtogroup ICU
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#if HAL_USE_ICU || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief ICUD1 driver identifier.
+ * @note The driver ICUD1 allocates the complex timer SMD0 when enabled.
+ */
+#if SPC5_ICU_USE_SMOD0 || defined(__DOXYGEN__)
+ICUDriver ICUD1;
+#endif
+
+/**
+ * @brief ICUD2 driver identifier.
+ * @note The driver ICUD2 allocates the complex timer SMD1 when enabled.
+ */
+#if SPC5_ICU_USE_SMOD1 || defined(__DOXYGEN__)
+ICUDriver ICUD2;
+#endif
+
+/**
+ * @brief ICUD3 driver identifier.
+ * @note The driver ICUD3 allocates the complex timer SMD2 when enabled.
+ */
+#if SPC5_ICU_USE_SMOD2 || defined(__DOXYGEN__)
+ICUDriver ICUD3;
+#endif
+
+/**
+ * @brief ICUD4 driver identifier.
+ * @note The driver ICUD4 allocates the complex timer SMD3 when enabled.
+ */
+#if SPC5_ICU_USE_SMD3 || defined(__DOXYGEN__)
+ICUDriver ICUD4;
+#endif
+
+/**
+ * @brief ICUD5 driver identifier.
+ * @note The driver ICUD5 allocates the complex timer SMD4 when enabled.
+ */
+#if SPC5_ICU_USE_SMOD4 || defined(__DOXYGEN__)
+ICUDriver ICUD5;
+#endif
+
+/**
+ * @brief ICUD6 driver identifier.
+ * @note The driver ICUD6 allocates the complex timer SMD5 when enabled.
+ */
+#if SPC5_ICU_USE_SMOD5 || defined(__DOXYGEN__)
+ICUDriver ICUD6;
+#endif
+
+/**
+ * @brief ICUD7 driver identifier.
+ * @note The driver ICUD7 allocates the complex timer SMD6 when enabled.
+ */
+#if SPC5_ICU_USE_SMOD6 || defined(__DOXYGEN__)
+ICUDriver ICUD7;
+#endif
+
+/**
+ * @brief ICUD8 driver identifier.
+ * @note The driver ICUD8 allocates the complex timer SMD7 when enabled.
+ */
+#if SPC5_ICU_USE_SMOD7 || defined(__DOXYGEN__)
+ICUDriver ICUD8;
+#endif
+
+/**
+ * @brief ICUD9 driver identifier.
+ * @note The driver ICUD9 allocates the complex timer SMD8 when enabled.
+ */
+#if SPC5_ICU_USE_SMOD8 || defined(__DOXYGEN__)
+ICUDriver ICUD9;
+#endif
+
+/**
+ * @brief ICUD10 driver identifier.
+ * @note The driver ICUD10 allocates the complex timer SMD9 when enabled.
+ */
+#if SPC5_ICU_USE_SMOD9 || defined(__DOXYGEN__)
+ICUDriver ICUD10;
+#endif
+
+/**
+ * @brief ICUD11 driver identifier.
+ * @note The driver ICUD11 allocates the complex timer SMD10 when enabled.
+ */
+#if SPC5_ICU_USE_SMOD10 || defined(__DOXYGEN__)
+ICUDriver ICUD11;
+#endif
+
+/**
+ * @brief ICUD12 driver identifier.
+ * @note The driver ICUD12 allocates the complex timer SMD11 when enabled.
+ */
+#if SPC5_ICU_USE_SMOD11 || defined(__DOXYGEN__)
+ICUDriver ICUD12;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief ICU eTimer channel enable.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @param[in] index ICU channel index
+ */
+static void spc5_icu_channel_enable(ICUDriver *icup, uint8_t index) {
+ /* Clear pending IRQs (if any).*/
+ icup->etimerp->CHANNEL[index].STS.R = 0xFFFF;
+ /* Set Capture 1 and Capture 2 Mode.*/
+ icup->etimerp->CHANNEL[index].CCCTRL.B.CPT1MODE = 0b10;
+ icup->etimerp->CHANNEL[index].CCCTRL.B.CPT2MODE = 0b01;
+ /* Active interrupts.*/
+ if (icup->config->period_cb != NULL || icup->config->width_cb != NULL) {
+ icup->etimerp->CHANNEL[index].INTDMA.B.ICF1IE = 1U;
+ icup->etimerp->CHANNEL[index].INTDMA.B.ICF2IE = 1U;
+ }
+ if (icup->config->overflow_cb != NULL) {
+ icup->etimerp->CHANNEL[index].INTDMA.B.TOFIE = 1U;
+ }
+ /* Set Capture FIFO Water Mark.*/
+ icup->etimerp->CHANNEL[index].CCCTRL.B.CFWM = 0b00;
+ /* Enable Counter.*/
+ if (ICU_SKIP_FIRST_CAPTURE) {
+ icup->etimerp->CHANNEL[index].CTRL.B.CNTMODE = 0b011;
+ }
+ else {
+ icup->etimerp->CHANNEL[index].CTRL.B.CNTMODE = 0b001;
+ }
+ /* Enable Capture process.*/
+ icup->etimerp->CHANNEL[index].CCCTRL.B.ARM = 1U;
+}
+
+/**
+ * @brief ICU eTimer channel disable.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @param[in] index ICU channel index
+ */
+static void spc5_icu_channel_disable(ICUDriver *icup, uint8_t index) {
+ /* Disable Capture process.*/
+ icup->etimerp->CHANNEL[index].CCCTRL.B.ARM = 0;
+ /* Clear pending IRQs (if any).*/
+ icup->etimerp->CHANNEL[index].STS.R = 0xFFFF;
+ /* Set Capture 1 and Capture 2 Mode to Disabled.*/
+ icup->etimerp->CHANNEL[index].CCCTRL.B.CPT1MODE = 0b00;
+ icup->etimerp->CHANNEL[index].CCCTRL.B.CPT2MODE = 0b00;
+ /* Disable interrupts.*/
+ if (icup->config->period_cb != NULL || icup->config->width_cb != NULL) {
+ icup->etimerp->CHANNEL[index].INTDMA.B.ICF1IE = 0;
+ icup->etimerp->CHANNEL[index].INTDMA.B.ICF2IE = 0;
+ }
+ if (icup->config->overflow_cb != NULL)
+ icup->etimerp->CHANNEL[index].INTDMA.B.TOFIE = 0;
+}
+
+/**
+ * @brief ICU eTimer channel start.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @param[in] index ICU channel index
+ */
+static void spc5_icu_channel_start(ICUDriver *icup, uint8_t index) {
+ /* Timer disabled.*/
+ icup->etimerp->CHANNEL[index].CTRL.B.CNTMODE = 0b000;
+ /* Clear pending IRQs (if any).*/
+ icup->etimerp->CHANNEL[index].STS.R = 0xFFFF;
+ /* All IRQs and DMA requests disabled.*/
+ icup->etimerp->CHANNEL[index].INTDMA.R = 0x0000;
+ /* Compare Load 1 disabled.*/
+ icup->etimerp->CHANNEL[index].CCCTRL.B.CLC1 = 0b000;
+ /* Compare Load 2 disabled.*/
+ icup->etimerp->CHANNEL[index].CCCTRL.B.CLC2 = 0b000;
+ /* Capture 1 disabled.*/
+ icup->etimerp->CHANNEL[index].CCCTRL.B.CPT1MODE = 0b00;
+ /* Capture 2 disabled.*/
+ icup->etimerp->CHANNEL[index].CCCTRL.B.CPT2MODE = 0b00;
+ /* Counter reset to zero.*/
+ icup->etimerp->CHANNEL[index].CNTR.R = 0x0000;
+}
+
+/**
+ * @brief ICU eTimer channel initialization.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @param[in] index ICU channel index
+ */
+static void spc5_icu_channel_init(ICUDriver *icup, uint8_t index) {
+#if !defined(psc)
+ uint32_t psc;
+#endif
+ psc = (icup->clock / icup->config->frequency);
+ chDbgAssert(
+ (psc <= 0xFFFF) && (((psc) * icup->config->frequency) == icup->clock) &&
+ ((psc == 1) || (psc == 2) || (psc == 4) || (psc == 8) || (psc == 16) ||
+ (psc == 32) || (psc == 64) || (psc == 128)),
+ "icu_lld_start(), #1", "invalid frequency");
+
+ /* Set primary source and clock prescaler.*/
+ switch (psc) {
+ case 1:
+ icup->etimerp->CHANNEL[index].CTRL.B.PRISRC = 0b11000;
+ break;
+ case 2:
+ icup->etimerp->CHANNEL[index].CTRL.B.PRISRC = 0b11001;
+ break;
+ case 4:
+ icup->etimerp->CHANNEL[index].CTRL.B.PRISRC = 0b11010;
+ break;
+ case 8:
+ icup->etimerp->CHANNEL[index].CTRL.B.PRISRC = 0b11011;
+ break;
+ case 16:
+ icup->etimerp->CHANNEL[index].CTRL.B.PRISRC = 0b11100;
+ break;
+ case 32:
+ icup->etimerp->CHANNEL[index].CTRL.B.PRISRC = 0b11101;
+ break;
+ case 64:
+ icup->etimerp->CHANNEL[index].CTRL.B.PRISRC = 0b11110;
+ break;
+ case 128:
+ icup->etimerp->CHANNEL[index].CTRL.B.PRISRC = 0b11111;
+ break;
+ }
+ /* Set control registers.*/
+ icup->etimerp->CHANNEL[index].CTRL.B.ONCE = 0;
+ icup->etimerp->CHANNEL[index].CTRL.B.LENGTH = 0;
+ icup->etimerp->CHANNEL[index].CTRL.B.DIR = 0;
+ icup->etimerp->CHANNEL[index].CTRL2.B.PIPS = 0;
+
+ /* Set secondary source.*/
+ switch (icup->config->channel) {
+ case ICU_CHANNEL_1:
+ icup->etimerp->CHANNEL[index].CTRL.B.SECSRC = 0b00000;
+ break;
+ case ICU_CHANNEL_2:
+ icup->etimerp->CHANNEL[index].CTRL.B.SECSRC = 0b00001;
+ break;
+ case ICU_CHANNEL_3:
+ icup->etimerp->CHANNEL[index].CTRL.B.SECSRC = 0b00010;
+ break;
+ case ICU_CHANNEL_4:
+ icup->etimerp->CHANNEL[index].CTRL.B.SECSRC = 0b00011;
+ break;
+ case ICU_CHANNEL_5:
+ icup->etimerp->CHANNEL[index].CTRL.B.SECSRC = 0b00100;
+ break;
+ case ICU_CHANNEL_6:
+ icup->etimerp->CHANNEL[index].CTRL.B.SECSRC = 0b00101;
+ break;
+ }
+
+ /* Set secondary source polarity.*/
+ if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH) {
+ icup->etimerp->CHANNEL[index].CTRL2.B.SIPS = 0;
+ }
+ else {
+ icup->etimerp->CHANNEL[index].CTRL2.B.SIPS = 1U;
+ }
+
+ /* Direct pointers to the capture registers in order to make reading
+ data faster from within callbacks.*/
+ icup->pccrp = &icup->etimerp->CHANNEL[index].CAPT1.R;
+ icup->wccrp = &icup->etimerp->CHANNEL[index].CAPT2.R;
+
+ /* Enable channel.*/
+ icup->etimerp->ENBL.B.ENBL |= 1U << index;
+}
+
+/**
+ * @brief Interrupt Management.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @param[in] index ICU channel index
+ */
+static void icu_lld_interrupt_management(ICUDriver *icup, uint8_t index) {
+#if !defined(sr)
+ uint16_t sr;
+#endif
+ sr = icup->etimerp->CHANNEL[index].STS.R
+ & icup->etimerp->CHANNEL[index].INTDMA.R;
+ if (ICU_SKIP_FIRST_CAPTURE) {
+ if ((sr & 0x0008) != 0) { /* TOF */
+ icup->etimerp->CHANNEL[index].STS.B.TOF = 1U;
+ _icu_isr_invoke_overflow_cb(icup);
+ }
+ if ((sr & 0x0040) != 0) { /* ICF1 */
+ if (icup->etimerp->CHANNEL[index].CTRL.B.CNTMODE == 0b011) {
+ icup->etimerp->CHANNEL[index].STS.B.ICF1 = 1U;
+ icup->etimerp->CHANNEL[index].CTRL.B.CNTMODE = 0b001;
+ }
+ else {
+ icup->etimerp->CHANNEL[index].STS.B.ICF1 = 1U;
+ icup->etimerp->CHANNEL[index].CNTR.R = 0x0000;
+ _icu_isr_invoke_period_cb(icup);
+ }
+ }
+ else if ((sr & 0x0080) != 0) { /* ICF2 */
+ if (icup->etimerp->CHANNEL[index].CTRL.B.CNTMODE == 0b011) {
+ icup->etimerp->CHANNEL[index].STS.B.ICF2 = 1U;
+ icup->etimerp->CHANNEL[index].CNTR.R = 0x0000;
+ }
+ else {
+ icup->etimerp->CHANNEL[index].STS.B.ICF2 = 1U;
+ _icu_isr_invoke_width_cb(icup);
+ }
+ }
+ } else { /* End ICU_SKIP_FIRST_CAPTURE = TRUE*/
+ if ((sr & 0x0008) != 0) { /* TOF */
+ icup->etimerp->CHANNEL[index].STS.B.TOF = 1U;
+ _icu_isr_invoke_overflow_cb(icup);
+ }
+ if ((sr & 0x0040) != 0) { /* ICF1 */
+ icup->etimerp->CHANNEL[index].STS.B.ICF1 = 1U;
+ icup->etimerp->CHANNEL[index].CNTR.R = 0x0000;
+ _icu_isr_invoke_period_cb(icup);
+ }
+ else if ((sr & 0x0080) != 0) { /* ICF2 */
+ icup->etimerp->CHANNEL[index].STS.B.ICF2 = 1U;
+ _icu_isr_invoke_width_cb(icup);
+ }
+ } /* End ICU_SKIP_FIRST_CAPTURE = FALSE*/
+}
+
+/**
+ * @brief Shared IRQ handler.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ */
+static void icu_lld_serve_interrupt(ICUDriver *icup) {
+
+#if SPC5_ICU_USE_SMOD0
+ if (&ICUD1 == icup) {
+ icu_lld_interrupt_management(icup, 0);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD1
+ if (&ICUD2 == icup) {
+ icu_lld_interrupt_management(icup, 1);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD2
+ if (&ICUD3 == icup) {
+ icu_lld_interrupt_management(icup, 2);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD3
+ if (&ICUD4 == icup) {
+ icu_lld_interrupt_management(icup, 3);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD4
+ if (&ICUD5 == icup) {
+ icu_lld_interrupt_management(icup, 4);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD5
+ if (&ICUD6 == icup) {
+ icu_lld_interrupt_management(icup, 5);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD6
+ if (&ICUD7 == icup) {
+ icu_lld_interrupt_management(icup, 0);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD7
+ if (&ICUD8 == icup) {
+ icu_lld_interrupt_management(icup, 1);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD8
+ if (&ICUD9 == icup) {
+ icu_lld_interrupt_management(icup, 2);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD9
+ if (&ICUD10 == icup) {
+ icu_lld_interrupt_management(icup, 3);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD10
+ if (&ICUD11 == icup) {
+ icu_lld_interrupt_management(icup, 4);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD11
+ if (&ICUD12 == icup) {
+ icu_lld_interrupt_management(icup, 5);
+ }
+#endif
+}
+
+/**
+ * @brief eTimer SubModules initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] sdp pointer to a @p ICUDriver object
+ * @param[in] config the architecture-dependent ICU driver configuration
+ */
+static void spc5_icu_smod_init(ICUDriver *icup) {
+
+#if SPC5_ICU_USE_SMOD0
+ if (&ICUD1 == icup) {
+ icup->clock = SPC5_ETIMER0_CLK;
+ spc5_icu_channel_init(icup, 0);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD1
+ if (&ICUD2 == icup) {
+ icup->clock = SPC5_ETIMER0_CLK;
+ spc5_icu_channel_init(icup, 1);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD2
+ if (&ICUD3 == icup) {
+ icup->clock = SPC5_ETIMER0_CLK;
+ spc5_icu_channel_init(icup, 2);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD3
+ if (&ICUD4 == icup) {
+ icup->clock = SPC5_ETIMER0_CLK;
+ spc5_icu_channel_init(icup, 3);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD4
+ if (&ICUD5 == icup) {
+ icup->clock = SPC5_ETIMER0_CLK;
+ spc5_icu_channel_init(icup, 4);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD5
+ if (&ICUD6 == icup) {
+ icup->clock = SPC5_ETIMER0_CLK;
+ spc5_icu_channel_init(icup, 5);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD6
+ if (&ICUD7 == icup) {
+ icup->clock = SPC5_ETIMER1_CLK;
+ spc5_icu_channel_init(icup, 0);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD7
+ if (&ICUD8 == icup) {
+ icup->clock = SPC5_ETIMER1_CLK;
+ spc5_icu_channel_init(icup, 1);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD8
+ if (&ICUD9 == icup) {
+ icup->clock = SPC5_ETIMER1_CLK;
+ spc5_icu_channel_init(icup, 2);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD9
+ if (&ICUD10 == icup) {
+ icup->clock = SPC5_ETIMER1_CLK;
+ spc5_icu_channel_init(icup, 3);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD10
+ if (&ICUD11 == icup) {
+ icup->clock = SPC5_ETIMER1_CLK;
+ spc5_icu_channel_init(icup, 4);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD11
+ if (&ICUD12 == icup) {
+ icup->clock = SPC5_ETIMER1_CLK;
+ spc5_icu_channel_init(icup, 5);
+ }
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if SPC5_ICU_USE_SMOD0
+#if !defined(SPC5_ETIMER0_TC0IR_HANDLER)
+#error "SPC5_ETIMER0_TC0IR_HANDLER not defined"
+#endif
+/**
+ * @brief eTimer0 Channel 0 interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */CH_IRQ_HANDLER(SPC5_ETIMER0_TC0IR_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD1);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* SPC5_ICU_USE_SMOD0 */
+
+#if SPC5_ICU_USE_SMOD1
+#if !defined(SPC5_ETIMER0_TC1IR_HANDLER)
+#error "SPC5_ETIMER0_TC1IR_HANDLER not defined"
+#endif
+/**
+ * @brief eTimer0 Channel 1 interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(SPC5_ETIMER0_TC1IR_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD2);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* SPC5_ICU_USE_SMOD1 */
+
+#if SPC5_ICU_USE_SMOD2
+#if !defined(SPC5_ETIMER0_TC2IR_HANDLER)
+#error "SPC5_ETIMER0_TC2IR_HANDLER not defined"
+#endif
+/**
+ * @brief eTimer0 Channel 2 interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(SPC5_ETIMER0_TC2IR_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD3);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* SPC5_ICU_USE_SMOD2 */
+
+#if SPC5_ICU_USE_SMOD3
+#if !defined(SPC5_ETIMER0_TC3IR_HANDLER)
+#error "SPC5_ETIMER0_TC3IR_HANDLER not defined"
+#endif
+/**
+ * @brief eTimer0 Channel 3 interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(SPC5_ETIMER0_TC3IR_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD4);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* SPC5_ICU_USE_SMOD3 */
+
+#if SPC5_ICU_USE_SMOD4
+#if !defined(SPC5_ETIMER0_TC4IR_HANDLER)
+#error "SPC5_ETIMER0_TC4IR_HANDLER not defined"
+#endif
+/**
+ * @brief eTimer0 Channel 4 interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(SPC5_ETIMER0_TC4IR_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD5);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* SPC5_ICU_USE_SMOD4 */
+
+#if SPC5_ICU_USE_SMOD5
+#if !defined(SPC5_ETIMER0_TC5IR_HANDLER)
+#error "SPC5_ETIMER0_TC5IR_HANDLER not defined"
+#endif
+/**
+ * @brief eTimer0 Channel 5 interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(SPC5_ETIMER0_TC5IR_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD6);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* SPC5_ICU_USE_SMOD5 */
+
+#if SPC5_ICU_USE_SMOD6
+#if !defined(SPC5_ETIMER1_TC0IR_HANDLER)
+#error "SPC5_ETIMER1_TC0IR_HANDLER not defined"
+#endif
+/**
+ * @brief eTimer1 Channel 0 interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(SPC5_ETIMER1_TC0IR_HANDLER) {
+
+//SIU.PCR[3*16+5].R = 556;
+//SIU.GPDO[3*16+5].R = 0;
+
+ CH_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD7);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* SPC5_ICU_USE_SMOD6 */
+
+#if SPC5_ICU_USE_SMOD7
+#if !defined(SPC5_ETIMER1_TC1IR_HANDLER)
+#error "SPC5_ETIMER1_TC1IR_HANDLER not defined"
+#endif
+/**
+ * @brief eTimer1 Channel 1 interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(SPC5_ETIMER1_TC1IR_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD8);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* SPC5_ICU_USE_SMOD7 */
+
+#if SPC5_ICU_USE_SMOD8
+#if !defined(SPC5_ETIMER1_TC2IR_HANDLER)
+#error "SPC5_ETIMER1_TC2IR_HANDLER not defined"
+#endif
+/**
+ * @brief eTimer1 Channel 2 interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(SPC5_ETIMER1_TC2IR_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD9);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* SPC5_ICU_USE_SMOD8 */
+
+#if SPC5_ICU_USE_SMOD9
+#if !defined(SPC5_ETIMER1_TC3IR_HANDLER)
+#error "SPC5_ETIMER0_TC3IR_HANDLER not defined"
+#endif
+/**
+ * @brief eTimer1 Channel 3 interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(SPC5_ETIMER1_TC3IR_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD10);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* SPC5_ICU_USE_SMOD9 */
+
+#if SPC5_ICU_USE_SMOD10
+#if !defined(SPC5_ETIMER1_TC4IR_HANDLER)
+#error "SPC5_ETIMER1_TC4IR_HANDLER not defined"
+#endif
+/**
+ * @brief eTimer1 Channel 4 interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(SPC5_ETIMER1_TC4IR_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD11);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* SPC5_ICU_USE_SMOD10 */
+
+#if SPC5_ICU_USE_SMOD11
+#if !defined(SPC5_ETIMER1_TC5IR_HANDLER)
+#error "SPC5_ETIMER1_TC5IR_HANDLER not defined"
+#endif
+/**
+ * @brief eTimer1 Channel 5 interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(SPC5_ETIMER1_TC5IR_HANDLER) {
+
+ CH_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD12);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* SPC5_ICU_USE_SMOD11 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ICU driver initialization.
+ *
+ * @notapi
+ */
+void icu_lld_init(void) {
+
+#if SPC5_ICU_USE_SMOD0
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD1);
+ ICUD1.etimerp = &ETIMER_0;
+#endif
+
+#if SPC5_ICU_USE_SMOD1
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD2);
+ ICUD2.etimerp = &ETIMER_0;
+#endif
+
+#if SPC5_ICU_USE_SMOD2
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD3);
+ ICUD3.etimerp = &ETIMER_0;
+#endif
+
+#if SPC5_ICU_USE_SMOD3
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD4);
+ ICUD4.etimerp = &ETIMER_0;
+#endif
+
+#if SPC5_ICU_USE_SMOD4
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD5);
+ ICUD5.etimerp = &ETIMER_0;
+#endif
+
+#if SPC5_ICU_USE_SMOD5
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD6);
+ ICUD6.etimerp = &ETIMER_0;
+#endif
+
+#if SPC5_ICU_USE_SMOD6
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD7);
+ ICUD7.etimerp = &ETIMER_1;
+#endif
+
+#if SPC5_ICU_USE_SMOD7
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD8);
+ ICUD8.etimerp = &ETIMER_1;
+#endif
+
+#if SPC5_ICU_USE_SMOD8
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD9);
+ ICUD9.etimerp = &ETIMER_1;
+#endif
+
+#if SPC5_ICU_USE_SMOD9
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD10);
+ ICUD10.etimerp = &ETIMER_1;
+#endif
+
+#if SPC5_ICU_USE_SMOD10
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD11);
+ ICUD11.etimerp = &ETIMER_1;
+#endif
+
+#if SPC5_ICU_USE_SMOD11
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD12);
+ ICUD12.etimerp = &ETIMER_1;
+#endif
+
+#if SPC5_ICU_USE_SMOD0 || SPC5_ICU_USE_SMOD1 || \
+ SPC5_ICU_USE_SMOD2 || SPC5_ICU_USE_SMOD3 || \
+ SPC5_ICU_USE_SMOD4 || SPC5_ICU_USE_SMOD5
+
+ INTC.PSR[SPC5_ETIMER0_TC0IR_NUMBER].R = SPC5_ICU_ETIMER0_PRIORITY;
+ INTC.PSR[SPC5_ETIMER0_TC1IR_NUMBER].R = SPC5_ICU_ETIMER0_PRIORITY;
+ INTC.PSR[SPC5_ETIMER0_TC2IR_NUMBER].R = SPC5_ICU_ETIMER0_PRIORITY;
+ INTC.PSR[SPC5_ETIMER0_TC3IR_NUMBER].R = SPC5_ICU_ETIMER0_PRIORITY;
+ INTC.PSR[SPC5_ETIMER0_TC4IR_NUMBER].R = SPC5_ICU_ETIMER0_PRIORITY;
+ INTC.PSR[SPC5_ETIMER0_TC5IR_NUMBER].R = SPC5_ICU_ETIMER0_PRIORITY;
+ INTC.PSR[SPC5_ETIMER0_WTIF_NUMBER].R = SPC5_ICU_ETIMER0_PRIORITY;
+ INTC.PSR[SPC5_ETIMER0_RCF_NUMBER].R = SPC5_ICU_ETIMER0_PRIORITY;
+
+#endif
+
+#if SPC5_ICU_USE_SMOD6 || SPC5_ICU_USE_SMOD7 || \
+ SPC5_ICU_USE_SMOD8 || SPC5_ICU_USE_SMOD9 || \
+ SPC5_ICU_USE_SMOD10 || SPC5_ICU_USE_SMOD11
+
+ INTC.PSR[SPC5_ETIMER1_TC0IR_NUMBER].R = SPC5_ICU_ETIMER1_PRIORITY;
+ INTC.PSR[SPC5_ETIMER1_TC1IR_NUMBER].R = SPC5_ICU_ETIMER1_PRIORITY;
+ INTC.PSR[SPC5_ETIMER1_TC2IR_NUMBER].R = SPC5_ICU_ETIMER1_PRIORITY;
+ INTC.PSR[SPC5_ETIMER1_TC3IR_NUMBER].R = SPC5_ICU_ETIMER1_PRIORITY;
+ INTC.PSR[SPC5_ETIMER1_TC4IR_NUMBER].R = SPC5_ICU_ETIMER1_PRIORITY;
+ INTC.PSR[SPC5_ETIMER1_TC5IR_NUMBER].R = SPC5_ICU_ETIMER1_PRIORITY;
+ INTC.PSR[SPC5_ETIMER1_RCF_NUMBER].R = SPC5_ICU_ETIMER1_PRIORITY;
+
+#endif
+}
+
+/**
+ * @brief Configures and activates the ICU peripheral.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_start(ICUDriver *icup) {
+ chDbgAssert(
+ (icup->config->channel == ICU_CHANNEL_1) ||
+ (icup->config->channel == ICU_CHANNEL_2) ||
+ (icup->config->channel == ICU_CHANNEL_3) ||
+ (icup->config->channel == ICU_CHANNEL_4) ||
+ (icup->config->channel == ICU_CHANNEL_5) ||
+ (icup->config->channel == ICU_CHANNEL_6),
+ "icu_lld_start(), #1", "invalid input");
+
+#if SPC5_ICU_USE_SMOD0 || SPC5_ICU_USE_SMOD1 || SPC5_ICU_USE_SMOD2 || \
+ SPC5_ICU_USE_SMOD3 || SPC5_ICU_USE_SMOD4 || SPC5_ICU_USE_SMOD5
+ uint8_t SMOD0 = 0;
+ uint8_t SMOD1 = 0;
+ uint8_t SMOD2 = 0;
+ uint8_t SMOD3 = 0;
+ uint8_t SMOD4 = 0;
+ uint8_t SMOD5 = 0;
+#endif
+
+#if SPC5_ICU_USE_SMOD6 || SPC5_ICU_USE_SMOD7 || SPC5_ICU_USE_SMOD8 || \
+ SPC5_ICU_USE_SMOD9 || SPC5_ICU_USE_SMOD10 || SPC5_ICU_USE_SMOD11
+ uint8_t SMOD6 = 0;
+ uint8_t SMOD7 = 0;
+ uint8_t SMOD8 = 0;
+ uint8_t SMOD9 = 0;
+ uint8_t SMOD10 = 0;
+ uint8_t SMOD11 = 0;
+#endif
+
+#if SPC5_ICU_USE_SMOD0
+ if (ICUD1.state == ICU_READY)
+ SMOD0 = 1U;
+#endif
+#if SPC5_ICU_USE_SMOD1
+ if (ICUD2.state == ICU_READY)
+ SMOD1 = 1U;
+#endif
+#if SPC5_ICU_USE_SMOD2
+ if (ICUD3.state == ICU_READY)
+ SMOD2 = 1U;
+#endif
+#if SPC5_ICU_USE_SMOD3
+ if (ICUD4.state == ICU_READY)
+ SMOD3 = 1U;
+#endif
+#if SPC5_ICU_USE_SMOD4
+ if (ICUD5.state == ICU_READY)
+ SMOD4 = 1U;
+#endif
+#if SPC5_ICU_USE_SMOD5
+ if (ICUD6.state == ICU_READY)
+ SMOD5 = 1U;
+#endif
+#if SPC5_ICU_USE_SMOD6
+ if (ICUD7.state == ICU_READY)
+ SMOD6 = 1U;
+#endif
+#if SPC5_ICU_USE_SMOD7
+ if (ICUD8.state == ICU_READY)
+ SMOD7 = 1U;
+#endif
+#if SPC5_ICU_USE_SMOD8
+ if (ICUD9.state == ICU_READY)
+ SMOD8 = 1U;
+#endif
+#if SPC5_ICU_USE_SMOD9
+ if (ICUD10.state == ICU_READY)
+ SMOD9 = 1U;
+#endif
+#if SPC5_ICU_USE_SMOD10
+ if (ICUD11.state == ICU_READY)
+ SMOD10 = 1U;
+#endif
+#if SPC5_ICU_USE_SMOD11
+ if (ICUD12.state == ICU_READY)
+ SMOD11 = 1U;
+#endif
+
+#if SPC5_ICU_USE_SMOD0 || SPC5_ICU_USE_SMOD1 || SPC5_ICU_USE_SMOD2 || \
+ SPC5_ICU_USE_SMOD3 || SPC5_ICU_USE_SMOD4 || SPC5_ICU_USE_SMOD5
+ /* Set Peripheral Clock.*/
+ if (!(SMOD0 || SMOD1 || SMOD2 || SMOD3 || SMOD4 || SMOD5)) {
+ halSPCSetPeripheralClockMode(SPC5_ETIMER0_PCTL,
+ SPC5_ICU_ETIMER0_START_PCTL);
+ }
+#endif
+#if SPC5_ICU_USE_SMOD6 || SPC5_ICU_USE_SMOD7 || SPC5_ICU_USE_SMOD8 || \
+ SPC5_ICU_USE_SMOD9 || SPC5_ICU_USE_SMOD10 || SPC5_ICU_USE_SMOD11
+ /* Set Peripheral Clock.*/
+ if (!(SMOD6 || SMOD7 || SMOD8 || SMOD9 || SMOD10 || SMOD11)) {
+ halSPCSetPeripheralClockMode(SPC5_ETIMER1_PCTL,
+ SPC5_ICU_ETIMER1_START_PCTL);
+ }
+#endif
+
+ /* Disable all channels.*/
+ //icup->etimerp->ENBL.B.ENBL = 0x00;
+
+ if (icup->state == ICU_STOP) {
+#if SPC5_ICU_USE_SMOD0
+ if (&ICUD1 == icup) {
+ spc5_icu_channel_start(icup, 0);
+ }
+#endif
+#if SPC5_ICU_USE_SMOD1
+ if (&ICUD2 == icup) {
+ spc5_icu_channel_start(icup, 1);
+ }
+#endif
+#if SPC5_ICU_USE_SMOD2
+ if (&ICUD3 == icup) {
+ spc5_icu_channel_start(icup, 2);
+ }
+#endif
+#if SPC5_ICU_USE_SMOD3
+ if (&ICUD4 == icup) {
+ spc5_icu_channel_start(icup, 3);
+ }
+#endif
+#if SPC5_ICU_USE_SMOD4
+ if (&ICUD5 == icup) {
+ spc5_icu_channel_start(icup, 4);
+ }
+#endif
+#if SPC5_ICU_USE_SMOD5
+ if (&ICUD6 == icup) {
+ spc5_icu_channel_start(icup, 5);
+ }
+#endif
+#if SPC5_ICU_USE_SMOD6
+ if (&ICUD7 == icup) {
+ spc5_icu_channel_start(icup, 0);
+ }
+#endif
+#if SPC5_ICU_USE_SMOD7
+ if (&ICUD8 == icup) {
+ spc5_icu_channel_start(icup, 1);
+ }
+#endif
+#if SPC5_ICU_USE_SMOD8
+ if (&ICUD9 == icup) {
+ spc5_icu_channel_start(icup, 2);
+ }
+#endif
+#if SPC5_ICU_USE_SMOD9
+ if (&ICUD10 == icup) {
+ spc5_icu_channel_start(icup, 3);
+ }
+#endif
+#if SPC5_ICU_USE_SMOD10
+ if (&ICUD11 == icup) {
+ spc5_icu_channel_start(icup, 4);
+ }
+#endif
+#if SPC5_ICU_USE_SMOD11
+ if (&ICUD12 == icup) {
+ spc5_icu_channel_start(icup, 5);
+ }
+#endif
+ }
+ /* Configuration.*/
+ spc5_icu_smod_init(icup);
+}
+
+/**
+ * @brief Deactivates the ICU peripheral.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_stop(ICUDriver *icup) {
+
+ if (icup->state == ICU_READY) {
+
+#if SPC5_ICU_USE_SMOD0 || SPC5_ICU_USE_SMOD1 || SPC5_ICU_USE_SMOD2 || \
+ SPC5_ICU_USE_SMOD3 || SPC5_ICU_USE_SMOD4 || SPC5_ICU_USE_SMOD5
+ uint8_t SMOD0 = 0;
+ uint8_t SMOD1 = 0;
+ uint8_t SMOD2 = 0;
+ uint8_t SMOD3 = 0;
+ uint8_t SMOD4 = 0;
+ uint8_t SMOD5 = 0;
+#endif
+
+#if SPC5_ICU_USE_SMOD6 || SPC5_ICU_USE_SMOD7 || SPC5_ICU_USE_SMOD8 || \
+ SPC5_ICU_USE_SMOD9 || SPC5_ICU_USE_SMOD10 || SPC5_ICU_USE_SMOD11
+ uint8_t SMOD6 = 0;
+ uint8_t SMOD7 = 0;
+ uint8_t SMOD8 = 0;
+ uint8_t SMOD9 = 0;
+ uint8_t SMOD10 = 0;
+ uint8_t SMOD11 = 0;
+#endif
+
+#if SPC5_ICU_USE_SMOD0
+ if (&ICUD1 == icup) {
+ /* Disable channel.*/
+ icup->etimerp->ENBL.B.ENBL &= 0b11111110;
+ SMOD0 = 1U;
+ }
+#endif
+#if SPC5_ICU_USE_SMOD1
+ if (&ICUD2 == icup) {
+ /* Disable channel.*/
+ icup->etimerp->ENBL.B.ENBL &= 0b11111101;
+ SMOD1 = 1U;
+ }
+#endif
+#if SPC5_ICU_USE_SMOD2
+ if (&ICUD3 == icup) {
+ /* Disable channel.*/
+ icup->etimerp->ENBL.B.ENBL &= 0b11111011;
+ SMOD2 = 1U;
+ }
+#endif
+#if SPC5_ICU_USE_SMOD3
+ if (&ICUD4 == icup) {
+ /* Disable channel.*/
+ icup->etimerp->ENBL.B.ENBL &= 0b11110111;
+ SMOD3 = 1U;
+ }
+#endif
+#if SPC5_ICU_USE_SMOD4
+ if (&ICUD5 == icup) {
+ /* Disable channel.*/
+ icup->etimerp->ENBL.B.ENBL &= 0b11101111;
+ SMOD4 = 1U;
+ }
+#endif
+#if SPC5_ICU_USE_SMOD5
+ if (&ICUD6 == icup) {
+ /* Disable channel.*/
+ icup->etimerp->ENBL.B.ENBL &= 0b11011111;
+ SMOD5 = 1U;
+ }
+#endif
+#if SPC5_ICU_USE_SMOD6
+ if (&ICUD7 == icup) {
+ /* Disable channel.*/
+ icup->etimerp->ENBL.B.ENBL &= 0b11111110;
+ SMOD6 = 1U;
+ }
+#endif
+#if SPC5_ICU_USE_SMOD7
+ if (&ICUD8 == icup) {
+ /* Disable channel.*/
+ icup->etimerp->ENBL.B.ENBL &= 0b11111101;
+ SMOD7 = 1U;
+ }
+#endif
+#if SPC5_ICU_USE_SMOD8
+ if (&ICUD9 == icup) {
+ /* Disable channel.*/
+ icup->etimerp->ENBL.B.ENBL &= 0b11111011;
+ SMOD8 = 1U;
+ }
+#endif
+#if SPC5_ICU_USE_SMOD9
+ if (&ICUD10 == icup) {
+ /* Disable channel.*/
+ icup->etimerp->ENBL.B.ENBL &= 0b11110111;
+ SMOD9 = 1U;
+ }
+#endif
+#if SPC5_ICU_USE_SMOD10
+ if (&ICUD11 == icup) {
+ /* Disable channel.*/
+ icup->etimerp->ENBL.B.ENBL &= 0b11101111;
+ SMOD10 = 1U;
+ }
+#endif
+#if SPC5_ICU_USE_SMOD11
+ if (&ICUD12 == icup) {
+ /* Disable channel.*/
+ icup->etimerp->ENBL.B.ENBL &= 0b11011111;
+ SMOD11 = 1U;
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD0 || SPC5_ICU_USE_SMOD1 || SPC5_ICU_USE_SMOD2 || \
+ SPC5_ICU_USE_SMOD3 || SPC5_ICU_USE_SMOD4 || SPC5_ICU_USE_SMOD5
+ if (SMOD0 || SMOD1 || SMOD2 || SMOD3 || SMOD4 || SMOD5) {
+ /* Clock deactivation.*/
+ if (icup->etimerp->ENBL.B.ENBL == 0x00) {
+ halSPCSetPeripheralClockMode(SPC5_ETIMER0_PCTL,
+ SPC5_ICU_ETIMER0_STOP_PCTL);
+ }
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD6 || SPC5_ICU_USE_SMOD7 || SPC5_ICU_USE_SMOD8 || \
+ SPC5_ICU_USE_SMOD9 || SPC5_ICU_USE_SMOD10 || SPC5_ICU_USE_SMOD11
+ if (SMOD6 || SMOD7 || SMOD8 || SMOD9 || SMOD10 || SMOD11) {
+ /* Clock deactivation.*/
+ if (icup->etimerp->ENBL.B.ENBL == 0x00) {
+ halSPCSetPeripheralClockMode(SPC5_ETIMER1_PCTL,
+ SPC5_ICU_ETIMER1_STOP_PCTL);
+ }
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Enables the input capture.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_enable(ICUDriver *icup) {
+#if SPC5_ICU_USE_SMOD0
+ if (&ICUD1 == icup) {
+ spc5_icu_channel_enable(icup, 0);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD1
+ if (&ICUD2 == icup) {
+ spc5_icu_channel_enable(icup, 1);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD2
+ if (&ICUD3 == icup) {
+ spc5_icu_channel_enable(icup, 2);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD3
+ if (&ICUD4 == icup) {
+ spc5_icu_channel_enable(icup, 3);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD4
+ if (&ICUD5 == icup) {
+ spc5_icu_channel_enable(icup, 4);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD5
+ if (&ICUD6 == icup) {
+ spc5_icu_channel_enable(icup, 5);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD6
+ if (&ICUD7 == icup) {
+ spc5_icu_channel_enable(icup, 0);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD7
+ if (&ICUD8 == icup) {
+ spc5_icu_channel_enable(icup, 1);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD8
+ if (&ICUD9 == icup) {
+ spc5_icu_channel_enable(icup, 2);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD9
+ if (&ICUD10 == icup) {
+ spc5_icu_channel_enable(icup, 3);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD10
+ if (&ICUD11 == icup) {
+ spc5_icu_channel_enable(icup, 4);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD11
+ if (&ICUD12 == icup) {
+ spc5_icu_channel_enable(icup, 5);
+ }
+#endif
+}
+
+/**
+ * @brief Disables the input capture.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_disable(ICUDriver *icup) {
+#if SPC5_ICU_USE_SMOD0
+ if (&ICUD1 == icup) {
+ spc5_icu_channel_disable(icup, 0);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD1
+ if (&ICUD2 == icup) {
+ spc5_icu_channel_disable(icup, 1);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD2
+ if (&ICUD3 == icup) {
+ spc5_icu_channel_disable(icup, 2);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD3
+ if (&ICUD4 == icup) {
+ spc5_icu_channel_disable(icup, 3);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD4
+ if (&ICUD5 == icup) {
+ spc5_icu_channel_disable(icup, 4);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD5
+ if (&ICUD6 == icup) {
+ spc5_icu_channel_disable(icup, 5);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD6
+ if (&ICUD7 == icup) {
+ spc5_icu_channel_disable(icup, 0);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD7
+ if (&ICUD8 == icup) {
+ spc5_icu_channel_disable(icup, 1);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD8
+ if (&ICUD9 == icup) {
+ spc5_icu_channel_disable(icup, 2);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD9
+ if (&ICUD10 == icup) {
+ spc5_icu_channel_disable(icup, 3);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD10
+ if (&ICUD11 == icup) {
+ spc5_icu_channel_disable(icup, 4);
+ }
+#endif
+
+#if SPC5_ICU_USE_SMOD11
+ if (&ICUD12 == icup) {
+ spc5_icu_channel_disable(icup, 5);
+ }
+#endif
+}
+
+/**
+ * @brief Returns the width of the latest pulse.
+ * @details The pulse width is defined as number of ticks between the start
+ * edge and the stop edge.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The number of ticks.
+ *
+ * @notapi
+ */
+icucnt_t icu_lld_get_width(ICUDriver *icup) {
+ return (icucnt_t)*icup->wccrp + 1;
+}
+
+/**
+ * @brief Returns the width of the latest cycle.
+ * @details The cycle width is defined as number of ticks between a start
+ * edge and the next start edge.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The number of ticks.
+ *
+ * @notapi
+ */
+icucnt_t icu_lld_get_period(ICUDriver *icup) {
+ return (icucnt_t)*icup->pccrp + 1;
+}
+
+#endif /* HAL_USE_ICU */
+
+/** @} */
diff --git a/os/hal/platforms/SPC5xx/eTimer_v1/icu_lld.h b/os/hal/platforms/SPC5xx/eTimer_v1/icu_lld.h
new file mode 100644
index 000000000..bd7ebe5da
--- /dev/null
+++ b/os/hal/platforms/SPC5xx/eTimer_v1/icu_lld.h
@@ -0,0 +1,512 @@
+/*
+ * Licensed under ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * @brief SPC5xx low level icu driver header.
+ *
+ * @addtogroup ICU
+ * @{
+ */
+
+#ifndef _ICU_LLD_H_
+#define _ICU_LLD_H_
+
+#if HAL_USE_ICU || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Mode options
+ * @{
+ */
+/**
+ * @brief Skip first capture cycle.
+ * @details If set to @p TRUE the first capture cycle is skipped.
+ * @note The default is @p FALSE.
+ */
+#if !defined(ICU_JUMP_FIRST_CAPTURE) || defined(__DOXYGEN__)
+#define ICU_SKIP_FIRST_CAPTURE FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief ICUD0 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD0 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(SPC5_ICU_USE_SMOD0) || defined(__DOXYGEN__)
+#define SPC5_ICU_USE_SMOD0 TRUE
+#endif
+
+/**
+ * @brief ICUD1 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD1 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(SPC5_ICU_USE_SMOD1) || defined(__DOXYGEN__)
+#define SPC5_ICU_USE_SMOD1 TRUE
+#endif
+
+/**
+ * @brief ICUD2 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD2 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(SPC5_ICU_USE_SMOD2) || defined(__DOXYGEN__)
+#define SPC5_ICU_USE_SMOD2 TRUE
+#endif
+
+/**
+ * @brief ICUD3 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD3 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(SPC5_ICU_USE_SMOD3) || defined(__DOXYGEN__)
+#define SPC5_ICU_USE_SMOD3 TRUE
+#endif
+
+/**
+ * @brief ICUD4 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD4 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(SPC5_ICU_USE_SMOD4) || defined(__DOXYGEN__)
+#define SPC5_ICU_USE_SMOD4 TRUE
+#endif
+
+/**
+ * @brief ICUD5 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD5 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(SPC5_ICU_USE_SMOD5) || defined(__DOXYGEN__)
+#define SPC5_ICU_USE_SMOD5 TRUE
+#endif
+
+/**
+ * @brief ICUD6 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD6 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(SPC5_ICU_USE_SMOD6) || defined(__DOXYGEN__)
+#define SPC5_ICU_USE_SMOD6 TRUE
+#endif
+
+/**
+ * @brief ICUD7 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD7 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(SPC5_ICU_USE_SMOD7) || defined(__DOXYGEN__)
+#define SPC5_ICU_USE_SMOD7 TRUE
+#endif
+
+/**
+ * @brief ICUD8 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD8 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(SPC5_ICU_USE_SMOD8) || defined(__DOXYGEN__)
+#define SPC5_ICU_USE_SMOD8 TRUE
+#endif
+
+/**
+ * @brief ICUD9 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD9 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(SPC5_ICU_USE_SMOD9) || defined(__DOXYGEN__)
+#define SPC5_ICU_USE_SMOD9 TRUE
+#endif
+
+/**
+ * @brief ICUD10 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD10 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(SPC5_ICU_USE_SMOD10) || defined(__DOXYGEN__)
+#define SPC5_ICU_USE_SMOD10 TRUE
+#endif
+
+/**
+ * @brief ICUD11 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD11 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(SPC5_ICU_USE_SMOD11) || defined(__DOXYGEN__)
+#define SPC5_ICU_USE_SMOD11 TRUE
+#endif
+
+/**
+ * @brief eTimer0 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_ETIMER0_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_ETIMER0_PRIORITY 7
+#endif
+
+/**
+ * @brief eTimer1 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_ETIMER1_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_ETIMER1_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD0 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_SMOD0_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_SMOD0_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD1 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_SMOD1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_SMOD1_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD2 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_SMOD2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_SMOD2_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD3 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_SMOD3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_SMOD3_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD4 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_SMOD4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_SMOD4_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD5 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_SMOD5_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_SMOD5_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD6 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_SMOD6_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_SMOD5_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD7 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_SMOD7_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_SMOD5_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD8 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_SMOD8_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_SMOD5_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD9 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_SMOD9_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_SMOD5_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD10 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_SMOD10_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_SMOD5_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD11 interrupt priority level setting.
+ */
+#if !defined(SPC5_ICU_SMOD11_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define SPC5_ICU_SMOD5_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief eTIMER0 peripheral configuration when started.
+ * @note The default configuration is 1 (always run) in run mode and
+ * 2 (only halt) in low power mode. The defaults of the run modes
+ * are defined in @p hal_lld.h.
+ */
+#if !defined(SPC5_ICU_ETIMER0_START_PCTL) || defined(__DOXYGEN__)
+#define SPC5_ICU_ETIMER0_START_PCTL (SPC5_ME_PCTL_RUN(1) | \
+ SPC5_ME_PCTL_LP(2))
+#endif
+
+/**
+ * @brief eTIMER0 peripheral configuration when stopped.
+ * @note The default configuration is 0 (never run) in run mode and
+ * 0 (never run) in low power mode. The defaults of the run modes
+ * are defined in @p hal_lld.h.
+ */
+#if !defined(SPC5_ICU_ETIMER0_STOP_PCTL) || defined(__DOXYGEN__)
+#define SPC5_ICU_ETIMER0_STOP_PCTL (SPC5_ME_PCTL_RUN(0) | \
+ SPC5_ME_PCTL_LP(0))
+#endif
+
+/**
+ * @brief eTIMER1 peripheral configuration when started.
+ * @note The default configuration is 1 (always run) in run mode and
+ * 2 (only halt) in low power mode. The defaults of the run modes
+ * are defined in @p hal_lld.h.
+ */
+#if !defined(SPC5_ICU_ETIMER1_START_PCTL) || defined(__DOXYGEN__)
+#define SPC5_ICU_ETIMER1_START_PCTL (SPC5_ME_PCTL_RUN(1) | \
+ SPC5_ME_PCTL_LP(2))
+#endif
+
+/**
+ * @brief eTIMER1 peripheral configuration when stopped.
+ * @note The default configuration is 0 (never run) in run mode and
+ * 0 (never run) in low power mode. The defaults of the run modes
+ * are defined in @p hal_lld.h.
+ */
+#if !defined(SPC5_ICU_ETIMER1_STOP_PCTL) || defined(__DOXYGEN__)
+#define SPC5_ICU_ETIMER1_STOP_PCTL (SPC5_ME_PCTL_RUN(0) | \
+ SPC5_ME_PCTL_LP(0))
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (SPC5_ICU_USE_SMOD0 || SPC5_ICU_USE_SMOD1 || \
+ SPC5_ICU_USE_SMOD2 || SPC5_ICU_USE_SMOD3 || \
+ SPC5_ICU_USE_SMOD4 || SPC5_ICU_USE_SMOD5) && !SPC5_HAS_ETIMER0
+#error "ETIMER0 not present in the selected device"
+#endif
+
+#if (SPC5_ICU_USE_SMOD6 || SPC5_ICU_USE_SMOD7 || \
+ SPC5_ICU_USE_SMOD8 || SPC5_ICU_USE_SMOD9 || \
+ SPC5_ICU_USE_SMOD10 || SPC5_ICU_USE_SMOD11) && !SPC5_HAS_ETIMER1
+#error "ETIMER1 not present in the selected device"
+#endif
+
+#if (!SPC5_ICU_USE_SMOD0 && !SPC5_ICU_USE_SMOD1 && \
+ !SPC5_ICU_USE_SMOD2 && !SPC5_ICU_USE_SMOD3 && \
+ !SPC5_ICU_USE_SMOD4 && !SPC5_ICU_USE_SMOD5) && SPC5_ICU_USE_ETIMER0
+#error "ICU driver activated but no SMOD peripheral assigned"
+#endif
+
+#if (!SPC5_ICU_USE_SMOD6 && !SPC5_ICU_USE_SMOD7 && \
+ !SPC5_ICU_USE_SMOD8 && !SPC5_ICU_USE_SMOD9 && \
+ !SPC5_ICU_USE_SMOD10 && !SPC5_ICU_USE_SMOD11) && SPC5_ICU_USE_ETIMER1
+#error "ICU driver activated but no SMOD peripheral assigned"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ICU driver mode.
+ */
+typedef enum {
+ ICU_INPUT_ACTIVE_HIGH = 0, /**< Trigger on rising edge. */
+ ICU_INPUT_ACTIVE_LOW = 1, /**< Trigger on falling edge. */
+}icumode_t;
+
+/**
+ * @brief ICU frequency type.
+ */
+typedef uint32_t icufreq_t;
+
+/**
+ * @brief ICU channel.
+ */
+typedef enum {
+ ICU_CHANNEL_1 = 0, /**< Use SMODxCH1. */
+ ICU_CHANNEL_2 = 1, /**< Use SMODxCH2. */
+ ICU_CHANNEL_3 = 2, /**< Use SMODxCH3. */
+ ICU_CHANNEL_4 = 3, /**< Use SMODxCH4. */
+ ICU_CHANNEL_5 = 4, /**< Use SMODxCH5. */
+ ICU_CHANNEL_6 = 5, /**< Use SMODxCH6. */
+}icuchannel_t;
+
+/**
+ * @brief ICU counter type.
+ */
+typedef uint16_t icucnt_t;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief Driver mode.
+ */
+ icumode_t mode;
+ /**
+ * @brief Timer clock in Hz.
+ * @note The low level can use assertions in order to catch invalid
+ * frequency specifications.
+ */
+ icufreq_t frequency;
+ /**
+ * @brief Callback for pulse width measurement.
+ */
+ icucallback_t width_cb;
+ /**
+ * @brief Callback for cycle period measurement.
+ */
+ icucallback_t period_cb;
+ /**
+ * @brief Callback for timer overflow.
+ */
+ icucallback_t overflow_cb;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Timer input channel to be used.
+ * @note Only inputs TIMx 1 and 2 are supported.
+ */
+ icuchannel_t channel;
+}ICUConfig;
+
+/**
+ * @brief Structure representing an ICU driver.
+ */
+struct ICUDriver {
+ /**
+ * @brief Driver state.
+ */
+ icustate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const ICUConfig *config;
+ /**
+ * @brief Pointer to the CAN registers.
+ */
+#if defined(ICU_DRIVER_EXT_FIELDS)
+ ICU_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Timer base clock.
+ */
+ uint32_t clock;
+ /**
+ * @brief Pointer to the eTimerx registers block.
+ */
+ volatile struct ETIMER_tag *etimerp;
+ /**
+ * @brief CCR register used for width capture.
+ */
+ volatile vuint16_t *wccrp;
+ /**
+ * @brief CCR register used for period capture.
+ */
+ volatile vuint16_t *pccrp;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if SPC5_ICU_USE_SMOD0 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD1;
+#endif
+
+#if SPC5_ICU_USE_SMOD1 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD2;
+#endif
+
+#if SPC5_ICU_USE_SMOD2 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD3;
+#endif
+
+#if SPC5_ICU_USE_SMOD3 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD4;
+#endif
+
+#if SPC5_ICU_USE_SMOD4 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD5;
+#endif
+
+#if SPC5_ICU_USE_SMOD5 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD6;
+#endif
+
+#if SPC5_ICU_USE_SMOD6 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD7;
+#endif
+
+#if SPC5_ICU_USE_SMOD7 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD8;
+#endif
+
+#if SPC5_ICU_USE_SMOD8 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD9;
+#endif
+
+#if SPC5_ICU_USE_SMOD9 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD10;
+#endif
+
+#if SPC5_ICU_USE_SMOD10 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD11;
+#endif
+
+#if SPC5_ICU_USE_SMOD11 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD12;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void icu_lld_init(void);
+ void icu_lld_start(ICUDriver *icup);
+ void icu_lld_stop(ICUDriver *icup);
+ void icu_lld_enable(ICUDriver *icup);
+ void icu_lld_disable(ICUDriver *icup);
+ icucnt_t icu_lld_get_width(ICUDriver *icup);
+ icucnt_t icu_lld_get_period(ICUDriver *icup);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ICU */
+
+#endif /* _ICU_LLD_H_ */
+
+/** @} */