diff --git a/kernel/atom.h b/kernel/atom.h
index 69bef924..c9c3f449 100755
--- a/kernel/atom.h
+++ b/kernel/atom.h
@@ -72,6 +72,8 @@ typedef struct atom_tcb
ATOM_TIMER *suspend_timo_cb; /* Callback registered for suspension timeouts */
uint8_t terminated; /* TRUE if task is being terminated (run to completion) */
+ uint16_t events; /* Evend flags */
+ uint16_t waits; /* Wait flags */
/* Details used if thread stack-checking is required */
#ifdef ATOM_STACK_CHECKING
POINTER stack_bottom; /* Pointer to bottom of stack allocation */
@@ -108,6 +110,13 @@ extern uint8_t atomOSStarted;
/* Idle thread priority (lowest) */
#define IDLE_THREAD_PRIORITY 255
+#ifndef EXPECTED_IDLE_TIME_BEFORE_SUSPEND
+ #define EXPECTED_IDLE_TIME_BEFORE_SUSPEND 2
+#endif
+
+#if EXPECTED_IDLE_TIME_BEFORE_SUSPEND < 2
+ #error EXPECTED_IDLE_TIME_BEFORE_SUSPEND must not be less than 2
+#endif
/* Function prototypes */
extern uint8_t atomOSInit (void *idle_thread_stack_bottom, uint32_t idle_thread_stack_size, uint8_t idle_thread_stack_check);
@@ -133,6 +142,13 @@ extern void archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top, void (*en
extern void archFirstThreadRestore(ATOM_TCB *new_tcb_ptr);
extern void atomTimerTick (void);
+extern void archSystemTickTimerStop (void);
+extern void archSystemTickTimerRestart (void);
+
+extern uint32_t atomOsSuspend(void);
+extern void atomOsResume (uint32_t sleep_ticks);
+
+extern void userIdleHook(void);
#ifdef __cplusplus
}
diff --git a/kernel/atomkernel.c b/kernel/atomkernel.c
index e10a5ac2..84106a27 100755
--- a/kernel/atomkernel.c
+++ b/kernel/atomkernel.c
@@ -180,7 +180,11 @@ uint8_t atomOSStarted = FALSE;
static ATOM_TCB *curr_tcb = NULL;
/** Storage for the idle thread's TCB */
+#ifdef ATOM_STACK_CHECKING
+ATOM_TCB idle_tcb;
+#else
static ATOM_TCB idle_tcb;
+#endif
/* Number of nested interrupts */
static int atomIntCnt = 0;
@@ -409,6 +413,8 @@ uint8_t atomThreadCreate (ATOM_TCB *tcb_ptr, uint8_t priority, void (*entry_poin
tcb_ptr->prev_tcb = NULL;
tcb_ptr->next_tcb = NULL;
tcb_ptr->suspend_timo_cb = NULL;
+ tcb_ptr->events = 0;
+ tcb_ptr->waits = 0;
/**
* Store the thread entry point and parameter in the TCB. This may
@@ -768,7 +774,7 @@ static void atomIdleThread (uint32_t param)
/* Loop forever */
while (1)
{
- /** \todo Provide user idle hooks*/
+ userIdleHook();
}
}
@@ -1049,3 +1055,84 @@ ATOM_TCB *tcbDequeuePriority (ATOM_TCB **tcb_queue_ptr, uint8_t priority)
return (ret_ptr);
}
+
+
+/**
+ * \b atomOsLock
+ *
+ * This is an internal function not for use by application code.
+ *
+ * Stop system timer to lock OS.
+ *
+ * @return None
+ */
+static void atomOsLock (void)
+{
+ archSystemTickTimerStop();
+ atomOSStarted = FALSE;
+}
+
+
+/**
+ * \b atomOsUnlock
+ *
+ * This is an internal function not for use by application code.
+ *
+ * Restart system timer to unlock OS.
+ *
+ * @return None
+ */
+static void atomOsUnlock (void)
+{
+ atomOSStarted = TRUE;
+ archSystemTickTimerRestart();
+}
+
+
+/**
+ * \b atomOsSuspend
+ *
+ * Suspend OS scheduler and return ticks count that OS can be suspended.
+ *
+ * @return Tick count that OS can be suspended
+ */
+uint32_t atomOsSuspend (void)
+{
+ uint32_t delta = 0xffff;
+
+ atomOsLock();
+
+ delta = atomUserTimerWakeupTimeGet();
+
+ if (delta < EXPECTED_IDLE_TIME_BEFORE_SUSPEND)
+ {
+ delta = 0;
+ }
+
+ return delta;
+}
+
+
+/**
+ * \b atomOsResume
+ *
+ * Resume OS scheduler after suspend.
+ *
+ * @param[in] sleep_ticks ticks count that OS was suspended
+ *
+ * @return None
+ */
+void atomOsResume (uint32_t sleep_ticks)
+{
+ uint32_t new_system_ticks, old_system_ticks;
+
+ old_system_ticks = atomTimeGet();
+
+ new_system_ticks = sleep_ticks + old_system_ticks;
+
+ atomUserTimerUpdate(sleep_ticks);
+ atomTimeSet(new_system_ticks);
+
+ atomOsUnlock();
+}
+
diff --git a/kernel/atomsignal.c b/kernel/atomsignal.c
new file mode 100644
index 00000000..0135f866
--- /dev/null
+++ b/kernel/atomsignal.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2018, Mike Yu. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. No personal names or organizations' names associated with the
+ * Atomthreads project may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "atomsignal.h"
+
+/* Forward declarations */
+
+static void atomSignalTimerCallback(POINTER cb_date);
+
+/**
+ * \b atomSignalWait
+ *
+ * Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
+ *
+ * @param[in] signals wait until all specified signal flags set or 0 for any single signal flag
+ * @param[in] timeout Max system ticks to block (0 = forever / -1 = non-blocking)
+ *
+ * @retval ATOM_SIGNAL
+ */
+ATOM_SIGNAL atomSignalWait(uint16_t signals, int32_t timeout)
+{
+ ATOM_SIGNAL ret;
+ ATOM_TCB *curr_tcb_ptr;
+ ATOM_TIMER timer_cb;
+ CRITICAL_STORE;
+
+ /* Get the current TCB */
+ curr_tcb_ptr = atomCurrentContext();
+ if (curr_tcb_ptr == NULL)
+ {
+ ret.status = ATOM_ERR_CONTEXT;
+ return ret;
+ }
+
+ if (signals & (0xFFFF << atomFeature_Signals))
+ {
+ ret.status = ATOM_ERR_PARAM;
+ return ret;
+ }
+ else
+ {
+ CRITICAL_START ();
+
+ if (signals != 0)
+ {
+ if ((curr_tcb_ptr->events & signals) == signals)
+ {
+ curr_tcb_ptr->events &= ~signals;
+ CRITICAL_END ();
+ ret.status = ATOM_OK;
+ ret.value = signals;
+ return ret;
+ }
+ curr_tcb_ptr->waits = signals;
+ }
+ else
+ {
+ if (curr_tcb_ptr->events)
+ {
+ ret.value = curr_tcb_ptr->events;
+ curr_tcb_ptr->events = 0;
+ CRITICAL_END ();
+ ret.status = ATOM_OK;
+ return ret;
+ }
+ curr_tcb_ptr->waits = 0xFFFF;
+ }
+
+ if (timeout < 0)
+ {
+ CRITICAL_END ();
+ ret.status = ATOM_TIMEOUT;
+ return ret;
+ }
+ else
+ {
+ /* Suspend ourselves */
+ curr_tcb_ptr->suspended = TRUE;
+ curr_tcb_ptr->suspend_wake_status = ATOM_OK;
+ if (timeout)
+ {
+ /* Fill out the timer callback request structure */
+ timer_cb.cb_func = atomSignalTimerCallback;
+ timer_cb.cb_data = (POINTER)curr_tcb_ptr;
+ timer_cb.cb_ticks = timeout;
+
+ /**
+ * Store the timer details in the TCB so that we can
+ * cancel the timer callback if a event is signalled
+ * before the timeout occurs.
+ */
+ curr_tcb_ptr->suspend_timo_cb = &timer_cb;
+
+ /* Register a callback on timeout */
+ if (atomTimerRegister (&timer_cb) != ATOM_OK)
+ {
+ /* Timer registration failed */
+ ret.status = ATOM_ERR_TIMER;
+
+ /* Clean up and return to the caller */
+ curr_tcb_ptr->suspended = FALSE;
+ curr_tcb_ptr->suspend_timo_cb = NULL;
+ }
+ else
+ {
+ ret.status = ATOM_OK;
+ }
+ }
+ else
+ {
+ /* No need to cancel timeouts on this one */
+ curr_tcb_ptr->suspend_timo_cb = NULL;
+ ret.status = ATOM_OK;
+ }
+ /**
+ * Only call the scheduler if we are in thread context,
+ * otherwise it will be called on exiting the ISR by
+ * atomIntExit().
+ */
+ CRITICAL_END ();
+ if ((ret.status == ATOM_OK))
+ {
+ atomSched (FALSE);
+ /* Restore returned events, clears event memory and update
+ status after context switch */
+ ret.status = curr_tcb_ptr->suspend_wake_status;
+ if (ret.status == ATOM_OK)
+ {
+ if (signals != 0)
+ {
+ curr_tcb_ptr->events &= ~signals;
+ ret.value = signals;
+ }
+ else
+ {
+ ret.value = curr_tcb_ptr->events;
+ curr_tcb_ptr->events = 0;
+ }
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+/**
+ * \b atomSignalSet
+ *
+ * Set the specified Signal Flags of an active thread.
+ *
+ * Set the specified Signal Flags to a thread given by the TCB pointer waiting in
+ * an atomSignalWait() with the same bits set in the Event Flags.
+ * If the thread is not waiting, then the signals signalled will be stored
+ * in the event register of the TCB until the atomSignalWait() is called.
+ *
+ * @param[in] curr_tcb_ptr Pointer to TCB which is to be signalled
+ * @param[in] signals signal flags
+ *
+ * @retval ATOM_OK Success
+ * @retval ATOM_ERR_PARAM Bad parameter
+ * @retval ATOM_ERR_QUEUE Problem putting the thread back on the ready queue
+ */
+uint8_t atomSignalSet (ATOM_TCB *curr_tcb_ptr, uint16_t signals)
+{
+ uint8_t status;
+ CRITICAL_STORE;
+
+ /* Check parameters */
+ if (curr_tcb_ptr == NULL)
+ {
+ /* Bad TCB pointer */
+ return ATOM_ERR_PARAM;
+ }
+
+ if (signals & (0xFFFF << atomFeature_Signals))
+ {
+ return ATOM_ERR_PARAM;
+ }
+
+ /* Protect access to the tcb object and OS queues */
+ CRITICAL_START ();
+
+ if (curr_tcb_ptr->suspended)
+ {
+ if (curr_tcb_ptr->waits & signals)
+ {
+ curr_tcb_ptr->events = curr_tcb_ptr->events | signals;
+ /* Put this thread on the ready queue */
+ if (tcbEnqueuePriority (&tcbReadyQ, curr_tcb_ptr) != ATOM_OK)
+ {
+ /* Queue-related error */
+ status = ATOM_ERR_QUEUE;
+ }
+ else
+ {
+ curr_tcb_ptr->suspended = FALSE;
+ status = curr_tcb_ptr->suspend_wake_status; /* FIX Check this */
+
+ /* If there's a timeout on this suspension, cancel it */
+ if (curr_tcb_ptr->suspend_timo_cb)
+ {
+ /* Cancel the callback */
+ if (atomTimerCancel (curr_tcb_ptr->suspend_timo_cb) != ATOM_OK)
+ {
+ /* Return timer error */
+ status = ATOM_ERR_TIMER;
+ }
+ /* Flag has no timeout registered */
+ curr_tcb_ptr->suspend_timo_cb = NULL;
+ }
+ }
+ }
+ else
+ {
+ /* No requested bits signalled which probably should be
+ considered an error in parameters. */
+ status = ATOM_ERR_PARAM;
+ }
+ /* Exit critical region */
+ CRITICAL_END ();
+ if (status == ATOM_OK)
+ {
+ if (atomCurrentContext())
+ {
+ atomSched(FALSE);
+ }
+ }
+ }
+ else
+ {
+ /* TCB is not waiting for events*/
+ curr_tcb_ptr->events |= signals;
+ /* Exit critical region */
+ CRITICAL_END ();
+ status = ATOM_OK;
+ }
+ return status;
+}
+
+/**
+ * \b atomSignalTimerCallback
+ *
+ * Clear the specified event flags of an active thread.
+ *
+ * @param[in] curr_tcb_ptr Pointer to TCB whose event flags is to be cleared.
+ * @param[in] signals event flags to be cleared
+ *
+ * @retval ATOM_OK Success
+ * @retval ATOM_ERR_PARAM Bad parameter
+ */
+uint8_t atomSignalClear(ATOM_TCB *curr_tcb_ptr, uint16_t signals)
+{
+ if (curr_tcb_ptr == NULL)
+ {
+ /* Bad TCB pointer */
+ return ATOM_ERR_PARAM;
+ }
+
+ if (signals & (0xFFFF << atomFeature_Signals))
+ {
+ return ATOM_ERR_PARAM;
+ }
+
+ curr_tcb_ptr->events &= (uint8_t)~signals;
+
+ return ATOM_OK;
+}
+
+/**
+ * \b atomSignalTimerCallback
+ *
+ * This is an internal function not for use by application code.
+ *
+ * Timeouts on suspended threads are notified by the timer system through
+ * this generic callback. The timer system calls us back with a pointer to
+ * the relevant \c ATOM_TCB object which is used to retrieve the
+ * event details.
+ *
+ * @param[in] cb_data Pointer to a ATOM_TCB object
+ */
+static void atomSignalTimerCallback (POINTER cb_data)
+{
+ ATOM_TCB *curr_tcb_ptr;
+ CRITICAL_STORE;
+
+ /* Get the pointer */
+ curr_tcb_ptr = (ATOM_TCB *)cb_data;
+
+ /* Check parameter is valid */
+ if (curr_tcb_ptr)
+ {
+ /* Enter critical region */
+ CRITICAL_START ();
+
+ /* Set status to indicate to the waiting thread that it timed out */
+ curr_tcb_ptr->suspend_wake_status = ATOM_TIMEOUT;
+
+ /* Flag as no timeout registered */
+ curr_tcb_ptr->suspend_timo_cb = NULL;
+
+ /* Put the thread on the ready queue */
+ (void)tcbEnqueuePriority (&tcbReadyQ, curr_tcb_ptr);
+
+ /* Exit critical region */
+ CRITICAL_END ();
+
+ /**
+ * Note that we don't call the scheduler now as it will be called
+ * when we exit the ISR by atomIntExit().
+ */
+ }
+}
+
diff --git a/kernel/atomsignal.h b/kernel/atomsignal.h
new file mode 100644
index 00000000..cdd8817c
--- /dev/null
+++ b/kernel/atomsignal.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018, Mike Yu. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. No personal names or organizations' names associated with the
+ * Atomthreads project may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ATOM_SIGNAL_H
+#define __ATOM_SIGNAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "atom.h"
+
+#define atomFeature_Signals 12 ///< 12 Signal Flags available per thread
+
+typedef struct atom_signal
+{
+ uint8_t status;
+ uint16_t value;
+} ATOM_SIGNAL;
+
+extern ATOM_SIGNAL atomSignalWait(uint16_t signals, int32_t timeout);
+extern uint8_t atomSignalSet(ATOM_TCB *tcb, uint16_t signals);
+extern uint8_t atomSignalClear(ATOM_TCB *tcb, uint16_t signals);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/kernel/atomtimer.c b/kernel/atomtimer.c
index ea8208ae..300861ae 100755
--- a/kernel/atomtimer.c
+++ b/kernel/atomtimer.c
@@ -547,3 +547,67 @@ static void atomTimerDelayCallback (POINTER cb_data)
}
}
+
+/**
+ * \b atomUserTimerWakeupTimeGet
+ *
+ * Get user timers wake-up time.
+ *
+ * @return None
+ */
+uint32_t atomUserTimerWakeupTimeGet(void)
+{
+ ATOM_TIMER *next_ptr = timer_queue;
+ uint32_t wake_up_time = 0;
+
+ if (tcbReadyQ && tcbReadyQ->priority != IDLE_THREAD_PRIORITY)
+ {
+ return wake_up_time;
+ }
+
+ if (next_ptr != NULL)
+ {
+ wake_up_time = next_ptr->cb_ticks;
+ next_ptr = next_ptr->next_timer;
+ }
+
+ while (next_ptr)
+ {
+ if (next_ptr->cb_ticks < wake_up_time)
+ {
+ wake_up_time = next_ptr->cb_ticks;
+ }
+
+ /* Move on to the next in the list */
+ next_ptr = next_ptr->next_timer;
+ }
+
+ return wake_up_time;
+}
+
+
+/**
+ * \b atomUserTimerUpdate
+ *
+ * This is an internal function not for use by application code.
+ *
+ * Update user timers on resume.
+ *
+ * @param[in] tick count value
+ *
+ * @return None
+ */
+void atomUserTimerUpdate (uint32_t sleep_time)
+{
+ ATOM_TIMER *next_ptr;
+
+ next_ptr = timer_queue;
+ while (next_ptr)
+ {
+ next_ptr->cb_ticks -= sleep_time;
+
+ /* Move on to the next in the list */
+ next_ptr = next_ptr->next_timer;
+ }
+}
+
diff --git a/kernel/atomtimer.h b/kernel/atomtimer.h
index efa3bd9b..0de8b9f9 100755
--- a/kernel/atomtimer.h
+++ b/kernel/atomtimer.h
@@ -61,6 +61,8 @@ extern uint8_t atomTimerCancel (ATOM_TIMER *timer_ptr);
extern uint8_t atomTimerDelay (uint32_t ticks);
extern uint32_t atomTimeGet (void);
extern void atomTimeSet (uint32_t new_time);
+extern uint32_t atomUserTimerWakeupTimeGet(void);
+extern void atomUserTimerUpdate (uint32_t sleep_time);
#ifdef __cplusplus
}
diff --git a/ports/stm8/atomport.c b/ports/stm8/atomport.c
index 7dc27bfc..1ff40ac3 100644
--- a/ports/stm8/atomport.c
+++ b/ports/stm8/atomport.c
@@ -313,3 +313,30 @@ __interrupt(11)
atomIntExit(TRUE);
}
+
+/**
+ * \b archSystemTickTimerStop
+ *
+ * Stop the system tick timer.
+ *
+ * @return None
+ */
+void archSystemTickTimerStop(void)
+{
+ /* Disable TIM1 */
+ TIM1_Cmd(DISABLE);
+}
+
+
+/**
+ * \b archSystemTickTimerRestart
+ *
+ * Restart the system tick timer.
+ *
+ * @return None
+ */
+void archSystemTickTimerRestart(void)
+{
+ /* Enable TIM1 */
+ TIM1_Cmd(ENABLE);
+}
diff --git a/ports/stm8/tests-main.c b/ports/stm8/tests-main.c
index 57b714c4..ab5f32b1 100644
--- a/ports/stm8/tests-main.c
+++ b/ports/stm8/tests-main.c
@@ -175,6 +175,21 @@ NO_REG_SAVE void main ( void )
}
+/**
+ * \b userIdleHook
+ *
+ * This function will be called in a endless loop by entry point of idle thread.
+ *
+ * It must not call any library routines which would cause it to block.
+ *
+ *@return None
+ */
+void userIdleHook(void)
+{
+
+}
+
+
/**
* \b main_thread_func
*
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x.h
new file mode 100644
index 00000000..1ab07219
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x.h
@@ -0,0 +1,3027 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the peripheral register's definitions, bits
+ * definitions and memory mapping for STM8L15x devices.
+ ******************************************************************************
+ * @attention
+ *
+ *
© COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_H
+ #define __STM8L15x_H
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+/* Uncomment the line below according to the target STM8L15x device used in your
+ application
+ */
+/* #define STM8L15X_LD */ /*!< STM8L15X_LD: STM8L15x Low density devices */
+/* #define STM8L15X_MD */ /*!< STM8L15X_MD: STM8L15x Medium density devices */
+/* #define STM8L15X_MDP */ /*!< STM8L15X_MDP: STM8L15x Medium density plus devices */
+/* #define STM8L15X_HD */ /*!< STM8L15X_HD: STM8L15x/16x High density devices */
+#define STM8L05X_LD_VL /*!< STM8L05X_LD_VL: STM8L051xx3 Low density value line devices */
+/* #define STM8L05X_MD_VL */ /*!< STM8L05X_MD_VL: STM8L052xx6 Medium density value line devices */
+/* #define STM8L05X_HD_VL */ /*!< STM8L05X_HD_VL: STM8L052xx8 High density value line devices */
+/* #define STM8AL31_L_MD */ /*!< STM8AL31_L_MD: STM8AL3x Medium density devices */
+
+
+/* Tip: To avoid modifying this file each time you need to switch between these
+ devices, you can define the device in your toolchain compiler preprocessor.
+
+ - Low density STM8L15x devices are STM8L151C3, STM8L151K3, STM8L151G3, STM8L151F3,
+ STM8L151C2, STM8L151K2, STM8L151G2 and STM8L151F2 microcontrollers where the
+ Flash memory density ranges between 4 and 8 Kbytes.
+ - Medium density STM8L15x devices are STM8L151C4, STM8L151C6, STM8L152C4,
+ STM8L152C6, STM8L151K4, STM8L151K6, STM8L152K4, STM8L152K6, STM8L151G4,
+ STM8L151G6, STM8L152G4 and STM8L152G6 microcontrollers where the Flash memory
+ density ranges between 16 and 32 Kbytes.
+ - Medium density Plus devices are STM8L151R6, STM8L152R6 microcontrollers where
+ the Flash memory density is fixed and equal to 32 Kbytes and a wider range of
+ peripheral than the medium density devices.
+ - High density STM8L15x devices are STM8L151x8, STM8L152x8, STM8L162R8 and STM8L162M8
+ microcontrollers where the Flash memory density is fixed and equal to 64 Kbytes with
+ the same peripheral set than Medium Density Plus devices.
+ - Value line low density STM8L05xx devices are STM8L051x3 microcontrollers
+ with 8-KB Flash
+ - Value line medium density STM8L05xx devices are STM8L052x6 microcontrollers
+ with 32-KB Flash
+ - Value line high density STM8L05xx devices: STM8L052x8 microcontrollers
+ with 64-KB Flash
+ - Medium density STM8AL31xx/STM8AL3Lxx devices: STM8AL3168, STM8AL3166,
+ STM8AL3148,STM8AL3146, STM8AL3138, STM8AL3136, STM8AL3L68, STM8AL3L66,
+ STM8AL3L48, STM8AL3L46 microcontrollers with 8-KB, 16-KB or 32-KB Flash
+ */
+
+#if !defined (STM8L15X_MD) && !defined (STM8L15X_MDP) && !defined (STM8L15X_HD) && !defined (STM8L15X_LD) \
+&& !defined (STM8L05X_LD_VL) && !defined (STM8L05X_MD_VL) && !defined (STM8L05X_HD_VL) && !defined (STM8AL31_L_MD)
+ #error "Please select first the target STM8L device used in your application (in stm8l15x.h file)"
+#endif
+
+/******************************************************************************/
+/* Library configuration section */
+/******************************************************************************/
+/* Check the used compiler */
+#if defined(__CSMC__)
+ #define _COSMIC_
+#elif defined(__RCSTM8__)
+ #define _RAISONANCE_
+#elif defined(__ICCSTM8__)
+ #define _IAR_
+#else
+ #error "Unsupported Compiler!" /* Compiler defines not found */
+#endif
+
+#if !defined USE_STDPERIPH_DRIVER
+/* Comment the line below if you will not use the peripherals drivers.
+ In this case, these drivers will not be included and the application code will be
+ based on direct access to peripherals registers */
+ #define USE_STDPERIPH_DRIVER
+#endif
+
+/**
+ * @brief In the following line adjust the value of External High Speed oscillator (HSE)
+ used in your application
+
+ Tip: To avoid modifying this file each time you need to use different HSE, you
+ can define the HSE value in your toolchain compiler preprocessor.
+ */
+#if !defined HSE_VALUE
+ #define HSE_VALUE ((uint32_t)16000000) /*!< Typical Value of the HSE in Hz */
+#endif /* HSE_VALUE */
+
+/**
+ * @brief Definition of External Low Speed oscillator (LSE) frequency
+ */
+#if !defined LSE_VALUE
+ #define LSE_VALUE ((uint32_t)32768) /*!< Typical Value of the LSE in Hz */
+#endif /* LSE_VALUE */
+/**
+ * @brief Definition of Device on-chip RC oscillator frequencies
+ */
+#if !defined HSI_VALUE
+ #define HSI_VALUE ((uint32_t)16000000) /*!< Typical Value of the HSI in Hz */
+#endif /* HSI_VALUE */
+
+#if !defined LSI_VALUE
+ #define LSI_VALUE ((uint32_t)38000) /*!< Typical Value of the LSI in Hz */
+#endif /* LSI_VALUE */
+
+#ifdef _COSMIC_
+ #define FAR @far
+ #define NEAR @near
+ #define TINY @tiny
+ #define EEPROM @eeprom
+ #define CONST const
+#elif defined (_RAISONANCE_) /* __RCSTM8__ */
+ #define FAR far
+ #define NEAR data
+ #define TINY page0
+ #define EEPROM eeprom
+ #define CONST code
+ #if defined (STM8L15X_MD) || defined (STM8L15X_MDP) || defined (STM8L05X_MD_VL) || \
+ defined (STM8AL31_L_MD)
+ /*!< Used with memory Models for code less than 64K */
+ #define MEMCPY memcpy
+ #elif defined (STM8L15X_HD) || defined (STM8L05X_HD_VL)
+ /*!< Used with memory Models for code higher than 64K */
+ #define MEMCPY fmemcpy
+ #endif /* STM8L15X_MD or STM8L15X_MDP or STM8L05X_MD_VL or STM8AL31_L_MD*/
+#else /*_IAR_*/
+ #define FAR __far
+ #define NEAR __near
+ #define TINY __tiny
+ #define EEPROM __eeprom
+ #define CONST const
+#endif /* __CSMC__ */
+
+/**
+ * @brief Legacy definition
+ */
+#define __CONST CONST
+
+#if defined (STM8L15X_MD) || defined (STM8L15X_MDP) || defined (STM8L15X_LD) || \
+defined (STM8L05X_LD_VL) || defined (STM8L05X_MD_VL) || defined (STM8AL31_L_MD)
+/*!< Used with memory Models for code smaller than 64K */
+ #define PointerAttr NEAR
+ #define MemoryAddressCast uint16_t
+#elif defined (STM8L15X_HD) || defined (STM8L05X_HD_VL)
+/*!< Used with memory Models for code higher than 64K */
+ #define PointerAttr FAR
+ #define MemoryAddressCast uint32_t
+#endif /* STM8L15X_MD or STM8L15X_MDP or STM8L15X_LD or STM8L05X_LD_VL or STM8L05X_MD_VL
+ or STM8AL31_L_MD */
+
+/* Uncomment the line below to enable the FLASH functions execution from RAM */
+#if !defined (RAM_EXECUTION)
+/* #define RAM_EXECUTION (1) */
+#endif /* RAM_EXECUTION */
+
+#ifdef RAM_EXECUTION
+ #ifdef _COSMIC_
+ #define IN_RAM(a) a
+ #elif defined (_RAISONANCE_) /* __RCSTM8__ */
+ #define IN_RAM(a) a inram
+ #else /*_IAR_*/
+ #define IN_RAM(a) __ramfunc a
+ #endif /* _COSMIC_ */
+#else
+ #define IN_RAM(a) a
+#endif /* RAM_EXECUTION */
+
+/*!< [31:16] STM8L15X Standard Peripheral Library main version */
+#define __STM8L15X_STDPERIPH_VERSION_MAIN ((uint8_t)0x01) /*!< [31:24] main version */
+#define __STM8L15X_STDPERIPH_VERSION_SUB1 ((uint8_t)0x06) /*!< [23:16] sub1 version */
+#define __STM8L15X_STDPERIPH_VERSION_SUB2 ((uint8_t)0x01) /*!< [15:8] sub2 version */
+#define __STM8L15X_STDPERIPH_VERSION_RC ((uint8_t)0x00) /*!< [7:0] release candidate */
+#define __STM8L15X_STDPERIPH_VERSION ( (__STM8L15X_STDPERIPH_VERSION_MAIN << 24)\
+ |(__STM8L15X_STDPERIPH_VERSION_SUB1 << 16)\
+ |(__STM8L15X_STDPERIPH_VERSION_SUB2 << 8)\
+ |(__STM8L15X_STDPERIPH_VERSION_RC))
+
+/******************************************************************************/
+
+/* Includes ------------------------------------------------------------------*/
+
+/* Exported types and constants ----------------------------------------------*/
+
+/** @addtogroup Exported_types
+ * @{
+ */
+
+/**
+ * IO definitions
+ *
+ * define access restrictions to peripheral registers
+ */
+#define __I volatile const /*!< defines 'read only' permissions */
+#define __O volatile /*!< defines 'write only' permissions */
+#define __IO volatile /*!< defines 'read / write' permissions */
+
+/*!< Signed integer types */
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed long int32_t;
+
+/*!< Unsigned integer types */
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+
+/*!< STM8Lx Standard Peripheral Library old types (maintained for legacy purpose) */
+
+typedef int32_t s32;
+typedef int16_t s16;
+typedef int8_t s8;
+
+typedef uint32_t u32;
+typedef uint16_t u16;
+typedef uint8_t u8;
+
+
+typedef enum {FALSE = 0, TRUE = !FALSE} bool;
+
+typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus, BitStatus, BitAction;
+
+typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
+#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
+
+typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus;
+
+#define U8_MAX (255)
+#define S8_MAX (127)
+#define S8_MIN (-128)
+#define U16_MAX (65535u)
+#define S16_MAX (32767)
+#define S16_MIN (-32768)
+#define U32_MAX (4294967295uL)
+#define S32_MAX (2147483647)
+#define S32_MIN (-2147483648uL)
+
+/**
+ * @}
+ */
+
+/** @addtogroup MAP_FILE_Exported_Types_and_Constants
+ * @{
+ */
+
+/******************************************************************************/
+/* IP registers structures */
+/******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/**
+ * @brief General Purpose I/Os (GPIO)
+ */
+typedef struct GPIO_struct
+{
+ __IO uint8_t ODR; /*!< Output Data Register */
+ __IO uint8_t IDR; /*!< Input Data Register */
+ __IO uint8_t DDR; /*!< Data Direction Register */
+ __IO uint8_t CR1; /*!< Configuration Register 1 */
+ __IO uint8_t CR2; /*!< Configuration Register 2 */
+}
+GPIO_TypeDef;
+
+/** @addtogroup GPIO_Registers_Reset_Value
+ * @{
+ */
+#define GPIO_ODR_RESET_VALUE ((uint8_t)0x00)
+#define GPIO_DDR_RESET_VALUE ((uint8_t)0x00)
+#define GPIO_CR1_RESET_VALUE ((uint8_t)0x00)
+#define GPIO_CR2_RESET_VALUE ((uint8_t)0x00)
+/**
+ * @}
+ */
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @brief Real-Time Clock (RTC) peripheral registers.
+ */
+typedef struct RTC_struct
+{
+ __IO uint8_t TR1; /*!< Time Register 1*/
+ __IO uint8_t TR2; /*!< Time Register 2*/
+ __IO uint8_t TR3; /*!< Time Register 3*/
+
+ uint8_t RESERVED0;
+
+ __IO uint8_t DR1; /*!< Date Register 1*/
+ __IO uint8_t DR2; /*!< Date Register 2*/
+ __IO uint8_t DR3; /*!< Date Register 3*/
+
+ uint8_t RESERVED1;
+
+ __IO uint8_t CR1; /*!< Control Register 1*/
+ __IO uint8_t CR2; /*!< Control Register 2*/
+ __IO uint8_t CR3; /*!< Control Register 3*/
+
+ uint8_t RESERVED2;
+
+ __IO uint8_t ISR1; /*!< Initialisation and Status Register 1 */
+ __IO uint8_t ISR2; /*!< Initialisation and Status Register 2 */
+
+ uint8_t RESERVED3;
+ uint8_t RESERVED4;
+
+ __IO uint8_t SPRERH; /*!< Synchronous Prediv high Register */
+ __IO uint8_t SPRERL; /*!< Synchronous Prediv Low Register */
+ __IO uint8_t APRER; /*!< Asynchronous Prediv Register */
+
+ uint8_t RESERVED5;
+
+ __IO uint8_t WUTRH; /*!< Wake-Up Timer High Register */
+ __IO uint8_t WUTRL; /*!< Wake-Up Timer Low Register */
+
+ uint8_t RESERVED6;
+
+ __IO uint8_t SSRH; /*!< Sub Second High Register */
+ __IO uint8_t SSRL; /*!< Sub Second Low Register */
+
+ __IO uint8_t WPR; /*!< Write Protection Register */
+
+ __IO uint8_t SHIFTRH; /*!< Shift control High Register */
+ __IO uint8_t SHIFTRL; /*!< Shift control Low Register */
+
+ __IO uint8_t ALRMAR1; /*!< ALARM A Register 1 */
+ __IO uint8_t ALRMAR2; /*!< ALARM A Register 2 */
+ __IO uint8_t ALRMAR3; /*!< ALARM A Register 3 */
+ __IO uint8_t ALRMAR4; /*!< ALARM A Register 4 */
+
+ uint8_t RESERVED7[4];
+
+ __IO uint8_t ALRMASSRH; /*!< ALARM A Subsecond Register High */
+ __IO uint8_t ALRMASSRL; /*!< ALARM A Subsecond Register Low */
+ __IO uint8_t ALRMASSMSKR; /*!< ALARM A Subsecond Mask Register */
+
+ uint8_t RESERVED8[3];
+
+ __IO uint8_t CALRH; /*!< Calibration register high */
+ __IO uint8_t CALRL; /*!< Calibration register low */
+
+ __IO uint8_t TCR1; /*!< Tamper control register 1 */
+ __IO uint8_t TCR2; /*!< Tamper control register 2 */
+}
+RTC_TypeDef;
+
+/** @addtogroup RTC_Registers_Reset_Value
+ * @{
+ */
+#define RTC_TR1_RESET_VALUE ((uint8_t)0x00)
+#define RTC_TR2_RESET_VALUE ((uint8_t)0x00)
+#define RTC_TR3_RESET_VALUE ((uint8_t)0x00)
+
+#define RTC_DR1_RESET_VALUE ((uint8_t)0x01)
+#define RTC_DR2_RESET_VALUE ((uint8_t)0x21)
+#define RTC_DR3_RESET_VALUE ((uint8_t)0x00)
+
+#define RTC_CR1_RESET_VALUE ((uint8_t)0x00)
+#define RTC_CR2_RESET_VALUE ((uint8_t)0x00)
+#define RTC_CR3_RESET_VALUE ((uint8_t)0x00)
+
+#define RTC_ISR1_RESET_VALUE ((uint8_t)0x07)
+#define RTC_ISR2_RESET_VALUE ((uint8_t)0x00)
+
+#define RTC_SPRERH_RESET_VALUE ((uint8_t)0x00)
+#define RTC_SPRERL_RESET_VALUE ((uint8_t)0xFF)
+#define RTC_APRER_RESET_VALUE ((uint8_t)0x7F)
+
+#define RTC_WUTRH_RESET_VALUE ((uint8_t)0xFF)
+#define RTC_WUTRL_RESET_VALUE ((uint8_t)0xFF)
+
+#define RTC_WPR_RESET_VALUE ((uint8_t)0x00)
+
+#define RTC_ALRMAR1_RESET_VALUE ((uint8_t)0x00)
+#define RTC_ALRMAR2_RESET_VALUE ((uint8_t)0x00)
+#define RTC_ALRMAR3_RESET_VALUE ((uint8_t)0x00)
+#define RTC_ALRMAR4_RESET_VALUE ((uint8_t)0x00)
+
+#define RTC_SHIFTRH_RESET_VALUE ((uint8_t)0x00)
+#define RTC_SHIFTRL_RESET_VALUE ((uint8_t)0x00)
+
+#define RTC_ALRMASSRH_RESET_VALUE ((uint8_t)0x00)
+#define RTC_ALRMASSRL_RESET_VALUE ((uint8_t)0x00)
+#define RTC_ALRMASSMSKR_RESET_VALUE ((uint8_t)0x00)
+
+#define RTC_CALRH_RESET_VALUE ((uint8_t)0x00)
+#define RTC_CALRL_RESET_VALUE ((uint8_t)0x00)
+
+#define RTC_TCR1_RESET_VALUE ((uint8_t)0x00)
+#define RTC_TCR2_RESET_VALUE ((uint8_t)0x00)
+
+/**
+ * @}
+ */
+
+/** @addtogroup RTC_Registers_Bits_Definition
+ * @{
+ */
+
+/* Bits definition for RTC_TR1 register*/
+#define RTC_TR1_ST ((uint8_t)0x70)
+#define RTC_TR1_SU ((uint8_t)0x0F)
+
+/* Bits definition for RTC_TR2 register*/
+#define RTC_TR2_MNT ((uint8_t)0x70)
+#define RTC_TR2_MNU ((uint8_t)0x0F)
+
+/* Bits definition for RTC_TR3 register*/
+#define RTC_TR3_PM ((uint8_t)0x40)
+#define RTC_TR3_HT ((uint8_t)0x30)
+#define RTC_TR3_HU ((uint8_t)0x0F)
+
+/* Bits definition for RTC_DR1 register*/
+#define RTC_DR1_DT ((uint8_t)0x30)
+#define RTC_DR1_DU ((uint8_t)0x0F)
+
+/* Bits definition for RTC_DR2 register*/
+#define RTC_DR2_WDU ((uint8_t)0xE0)
+#define RTC_DR2_MT ((uint8_t)0x10)
+#define RTC_DR2_MU ((uint8_t)0x0F)
+
+/* Bits definition for RTC_DR3 register*/
+#define RTC_DR3_YT ((uint8_t)0xF0)
+#define RTC_DR3_YU ((uint8_t)0x0F)
+
+/* Bits definition for RTC_CR1 register*/
+#define RTC_CR1_FMT ((uint8_t)0x40)
+#define RTC_CR1_RATIO ((uint8_t)0x20)
+#define RTC_CR1_WUCKSEL ((uint8_t)0x07)
+#define RTC_CR1_BYPSHAD ((uint8_t)0x10)
+
+
+/* Bits definition for RTC_CR2 register*/
+#define RTC_CR2_WUTIE ((uint8_t)0x40)
+#define RTC_CR2_ALRAIE ((uint8_t)0x10)
+#define RTC_CR2_WUTE ((uint8_t)0x04)
+#define RTC_CR2_ALRAE ((uint8_t)0x01)
+#define RTC_CR2_ALRIE ((uint8_t)0x20)
+
+
+
+/* Bits definition for RTC_CR3 register*/
+#define RTC_CR3_COE ((uint8_t)0x80)
+#define RTC_CR3_OSEL ((uint8_t)0x60)
+#define RTC_CR3_POL ((uint8_t)0x10)
+#define RTC_CR3_COSEL ((uint8_t)0x08)
+#define RTC_CR3_BCK ((uint8_t)0x04)
+#define RTC_CR3_SUB1H ((uint8_t)0x02)
+#define RTC_CR3_ADD1H ((uint8_t)0x01)
+
+
+/* Bits definition for RTC_ISR1 register*/
+#define RTC_ISR1_INIT ((uint8_t)0x80)
+#define RTC_ISR1_INITF ((uint8_t)0x40)
+#define RTC_ISR1_RSF ((uint8_t)0x20)
+#define RTC_ISR1_INITS ((uint8_t)0x10)
+#define RTC_ISR1_SHPF ((uint8_t)0x08)
+#define RTC_ISR1_WUTWF ((uint8_t)0x04)
+#define RTC_ISR1_RECALPF ((uint8_t)0x02)
+#define RTC_ISR1_ALRAWF ((uint8_t)0x01)
+
+
+/* Bits definition for RTC_ISR2 register*/
+#define RTC_ISR2_WUTF ((uint8_t)0x04)
+#define RTC_ISR2_ALRAF ((uint8_t)0x01)
+#define RTC_ISR2_TAMP3F ((uint8_t)0x80)
+#define RTC_ISR2_TAMP2F ((uint8_t)0x40)
+#define RTC_ISR2_TAMP1F ((uint8_t)0x20)
+
+/* Bits definition for RTC_SHIFTRH register*/
+#define RTC_SHIFTRH_ADD1S ((uint8_t)0x80)
+#define RTC_SHIFTRH_SUBFS ((uint8_t)0x7F)
+
+/* Bits definition for RTC_SHIFTRL register*/
+#define RTC_SHIFTRL_SUBFS ((uint8_t)0xFF)
+
+
+/* Bits definition for RTC_ALRMAR1 register*/
+#define RTC_ALRMAR1_MSK1 ((uint8_t)0x80)
+#define RTC_ALRMAR1_ST ((uint8_t)0x70)
+#define RTC_ALRMAR1_SU ((uint8_t)0x0F)
+
+/* Bits definition for RTC_ALRMAR2 register*/
+#define RTC_ALRMAR2_MSK2 ((uint8_t)0x80)
+#define RTC_ALRMAR2_MNT ((uint8_t)0x70)
+#define RTC_ALRMAR2_MNU ((uint8_t)0x0F)
+
+/* Bits definition for RTC_ALRMAR3 register*/
+#define RTC_ALRMAR3_MSK3 ((uint8_t)0x80)
+#define RTC_ALRMAR3_PM ((uint8_t)0x40)
+#define RTC_ALRMAR3_HT ((uint8_t)0x30)
+#define RTC_ALRMAR3_HU ((uint8_t)0x0F)
+
+/* Bits definition for RTC_ALRMAR4 register*/
+#define RTC_ALRMAR4_MSK4 ((uint8_t)0x80)
+#define RTC_ALRMAR4_WDSEL ((uint8_t)0x40)
+#define RTC_ALRMAR4_DT ((uint8_t)0x30)
+#define RTC_ALRMAR4_DU ((uint8_t)0x0F)
+
+/* Bits definition for RTC_ALRMASSRH register*/
+#define RTC_ALRMASSRH_ALSS ((uint8_t)0x7F)
+
+/* Bits definition for RTC_ALRMASSRL register*/
+#define RTC_ALRMASSRL_ALSS ((uint8_t)0xFF)
+
+/* Bits definition for RTC_ALRMASSMSKR register*/
+#define RTC_ALRMASSMSKR_MASKSS ((uint8_t)0x1F)
+
+
+/* Bits definition for RTC_CALRH register*/
+#define RTC_CALRH_CALP ((uint8_t)0x80)
+#define RTC_CALRH_CALW8 ((uint8_t)0x40)
+#define RTC_CALRH_CALW16 ((uint8_t)0x20)
+#define RTC_CALRH_CALWx ((uint8_t)0x60)
+#define RTC_CALRH_CALM ((uint8_t)0x01)
+
+/* Bits definition for RTC_CALRL register*/
+#define RTC_CALRL_CALM ((uint8_t)0xFF)
+
+/* Bits definition for RTC_TCR1 register*/
+#define RTC_TCR1_TAMP3LEVEL ((uint8_t)0x40)
+#define RTC_TCR1_TAMP3E ((uint8_t)0x20)
+#define RTC_TCR1_TAMP2LEVEL ((uint8_t)0x10)
+#define RTC_TCR1_TAMP2E ((uint8_t)0x08)
+#define RTC_TCR1_TAMP1LEVEL ((uint8_t)0x04)
+#define RTC_TCR1_TAMP1E ((uint8_t)0x02)
+#define RTC_TCR1_TAMPIE ((uint8_t)0x01)
+
+/* Bits definition for RTC_TCR2 register*/
+#define RTC_TCR2_TAMPPUDIS ((uint8_t)0x80)
+#define RTC_TCR2_TAMPPRCH ((uint8_t)0x60)
+#define RTC_TCR2_TAMPFLT ((uint8_t)0x18)
+#define RTC_TCR2_TAMPFREQ ((uint8_t)0x07)
+
+
+/*RTC special defines */
+#define RTC_WPR_EnableKey ((uint8_t)0xFF)
+#define RTC_WPR_DisableKey1 ((uint8_t)0xCA)
+#define RTC_WPR_DisableKey2 ((uint8_t)0x53)
+
+/**
+ * @}
+ */
+
+/**
+ * @brief CSS on LSE registers.
+ */
+typedef struct CSSLSE_struct
+{
+ __IO uint8_t CSR; /*!< Control and Status Register*/
+}
+CSSLSE_TypeDef;
+
+/** @addtogroup CSSLSE_Registers_Reset_Value
+ * @{
+ */
+#define CSSLSE_CSR_RESET_VALUE ((uint8_t)0x00)
+
+/**
+ * @}
+ */
+
+/** @addtogroup CSSLSE_Registers_Bits_Definition
+ * @{
+ */
+
+/* Bits definition for CSSLSE_CSR register*/
+#define CSSLSE_CSR_SWITCHF ((uint8_t)0x10)
+#define CSSLSE_CSR_CSSF ((uint8_t)0x08)
+#define CSSLSE_CSR_CSSIE ((uint8_t)0x04)
+#define CSSLSE_CSR_SWITCHEN ((uint8_t)0x02)
+#define CSSLSE_CSR_CSSEN ((uint8_t)0x01)
+
+/**
+ * @}
+ */
+/*----------------------------------------------------------------------------*/
+/**
+ * @brief Beeper (BEEP) peripheral registers.
+ */
+
+typedef struct BEEP_struct
+{
+ __IO uint8_t CSR1; /*!< BEEP Control status register1 */
+ uint8_t RSERVED1;
+ uint8_t RESERVED2;
+ __IO uint8_t CSR2; /*!< BEEP Control status register2 */
+}
+BEEP_TypeDef;
+
+/** @addtogroup BEEP_Registers_Reset_Value
+ * @{
+ */
+#define BEEP_CSR1_RESET_VALUE ((uint8_t)0x00)
+#define BEEP_CSR2_RESET_VALUE ((uint8_t)0x1F)
+
+/**
+ * @}
+ */
+
+/** @addtogroup BEEP_Registers_Bits_Definition
+ * @{
+ */
+
+#define BEEP_CSR1_MSR ((uint8_t)0x01) /*!< Measurement enable mask */
+
+#define BEEP_CSR2_BEEPSEL ((uint8_t)0xC0) /*!< Beeper frequency selection mask */
+#define BEEP_CSR2_BEEPEN ((uint8_t)0x20) /*!< Beeper enable mask */
+#define BEEP_CSR2_BEEPDIV ((uint8_t)0x1F) /*!< Beeper Divider prescalar mask */
+
+/**
+ * @}
+ */
+
+/*----------------------------------------------------------------------------ok*/
+
+/**
+ * @brief Configuration Registers (CFG)
+ */
+
+typedef struct CFG_struct
+{
+ __IO uint8_t GCR; /*!< Global Configuration register */
+}
+CFG_TypeDef;
+
+/** @addtogroup CFG_Registers_Reset_Value
+ * @{
+ */
+
+#define CFG_GCR_RESET_VALUE ((uint8_t)0x00)
+
+/**
+ * @}
+ */
+
+/** @addtogroup CFG_Registers_Bits_Definition
+ * @{
+ */
+
+#define CFG_GCR_SWD ((uint8_t)0x01) /*!< Swim disable bit mask */
+#define CFG_GCR_AL ((uint8_t)0x02) /*!< Activation Level bit mask */
+
+/**
+ * @}
+ */
+/*----------------------------------------------------------------------------ok*/
+
+/**
+ * @brief SYSCFG
+ */
+
+typedef struct SYSCFG_struct
+{
+ __IO uint8_t RMPCR3; /*!< Remap control register 3 */
+ __IO uint8_t RMPCR1; /*!< Remap control register 1 */
+ __IO uint8_t RMPCR2; /*!< Remap control register 2 */
+}
+SYSCFG_TypeDef;
+
+/** @addtogroup SYSCFG_Registers_Reset_Value
+ * @{
+ */
+#define SYSCFG_RMPCR1_RESET_VALUE ((uint8_t)0x0C)
+#define SYSCFG_RMPCR2_RESET_VALUE ((uint8_t)0x00)
+#define SYSCFG_RMPCR3_RESET_VALUE ((uint8_t)0x00)
+
+/**
+ * @}
+ */
+
+/** @addtogroup SYSCFG_Registers_Bits_Definition
+ * @{
+ */
+
+/* For DMA Channel Mapping*/
+#define SYSCFG_RMPCR1_ADC1DMA_REMAP ((uint8_t)0x03) /*!< ADC1 DMA channel remapping */
+#define SYSCFG_RMPCR1_TIM4DMA_REMAP ((uint8_t)0x0C) /*!< TIM4 DMA channel remapping */
+
+
+/* For GPIO Reapping*/
+#define SYSCFG_RMPCR1_USART1TR_REMAP ((uint8_t)0x30) /*!< USART1_TX and USART1_RX remapping */
+#define SYSCFG_RMPCR1_USART1CK_REMAP ((uint8_t)0x40) /*!< USART1_CK remapping */
+#define SYSCFG_RMPCR1_SPI1_REMAP ((uint8_t)0x80) /*!< SPI1 remapping */
+
+#define SYSCFG_RMPCR2_ADC1TRIG_REMAP ((uint8_t)0x01) /*!< ADC1 External Trigger remap */
+#define SYSCFG_RMPCR2_TIM2TRIG_REMAP ((uint8_t)0x02) /*!< TIM2 Trigger remap */
+#define SYSCFG_RMPCR2_TIM3TRIG_REMAP1 ((uint8_t)0x04) /*!< TIM3 Trigger remap 1 */
+#define SYSCFG_RMPCR2_TIM2TRIG_LSE ((uint8_t)0x08) /*!< TIM2 Trigger remap to LSE */
+#define SYSCFG_RMPCR2_TIM3TRIG_LSE ((uint8_t)0x10) /*!< TIM3 Trigger remap to LSE */
+#define SYSCFG_RMPCR2_SPI2_REMAP ((uint8_t)0x20) /*!< SPI2 remapping */
+#define SYSCFG_RMPCR2_TIM3TRIG_REMAP2 ((uint8_t)0x40) /*!< TIM3 Trigger remap 2 */
+#define SYSCFG_RMPCR2_TIM23BKIN_REMAP ((uint8_t)0x80) /*!< TIM2 & TIM3 Break input remap */
+
+#define SYSCFG_RMPCR3_SPI1_REMAP ((uint8_t)0x01) /*!< SPI1 remapping */
+#define SYSCFG_RMPCR3_USART3TR_REMAP ((uint8_t)0x02) /*!< USART3_TX and USART3_RX remapping */
+#define SYSCFG_RMPCR3_USART3CK_REMAP ((uint8_t)0x04) /*!< USART3_CK remapping */
+#define SYSCFG_RMPCR3_TIM3CH1_REMAP ((uint8_t)0x08) /*!< TIM3 channel 1 remapping */
+#define SYSCFG_RMPCR3_TIM3CH2_REMAP ((uint8_t)0x10) /*!< TIM3 channel 2 remapping */
+#define SYSCFG_RMPCR3_CCO_REMAP ((uint8_t)0x20) /*!< CCO remapping */
+
+/**
+ * @}
+ */
+/*----------------------------------------------------------------------------ok*/
+
+/**
+ * @brief Clock Controller (CLK)
+ */
+typedef struct CLK_struct
+{
+ __IO uint8_t CKDIVR; /*!< Clock Master Divider Register */
+ __IO uint8_t CRTCR; /*!< RTC Clock selection Register */
+ __IO uint8_t ICKCR; /*!< Internal Clocks Control Register */
+ __IO uint8_t PCKENR1; /*!< Peripheral Clock Gating Register 1 */
+ __IO uint8_t PCKENR2; /*!< Peripheral Clock Gating Register 2 */
+ __IO uint8_t CCOR; /*!< Configurable Clock Output Register */
+ __IO uint8_t ECKCR; /*!< External Clocks Control Register */
+ __IO uint8_t SCSR; /*!< System clock status Register */
+ __IO uint8_t SWR; /*!< System clock Switch Register */
+ __IO uint8_t SWCR; /*!< Switch Control Register */
+ __IO uint8_t CSSR; /*!< Clock Security Sytem Register */
+ __IO uint8_t CBEEPR; /*!< Clock BEEP Register */
+ __IO uint8_t HSICALR; /*!< HSI Calibration Register */
+ __IO uint8_t HSITRIMR; /*!< HSI clock Calibration Trimmer Register */
+ __IO uint8_t HSIUNLCKR; /*!< HSI Unlock Register */
+ __IO uint8_t REGCSR; /*!< Main regulator control status register */
+ __IO uint8_t PCKENR3; /*!< Peripheral Clock Gating Register 3 */
+}
+CLK_TypeDef;
+
+/** @addtogroup CLK_Registers_Reset_Value
+ * @{
+ */
+#define CLK_CKDIVR_RESET_VALUE ((uint8_t)0x03)
+#define CLK_CRTCR_RESET_VALUE ((uint8_t)0x00)
+#define CLK_ICKCR_RESET_VALUE ((uint8_t)0x11)
+#define CLK_PCKENR1_RESET_VALUE ((uint8_t)0x00)
+#define CLK_PCKENR2_RESET_VALUE ((uint8_t)0x80)
+#define CLK_PCKENR3_RESET_VALUE ((uint8_t)0x00)
+#define CLK_CCOR_RESET_VALUE ((uint8_t)0x00)
+#define CLK_ECKCR_RESET_VALUE ((uint8_t)0x00)
+#define CLK_SCSR_RESET_VALUE ((uint8_t)0x01)
+#define CLK_SWR_RESET_VALUE ((uint8_t)0x01)
+#define CLK_SWCR_RESET_VALUE ((uint8_t)0x00)
+#define CLK_CSSR_RESET_VALUE ((uint8_t)0x00)
+#define CLK_CBEEPR_RESET_VALUE ((uint8_t)0x00)
+#define CLK_HSICALR_RESET_VALUE ((uint8_t)0x00)
+#define CLK_HSITRIMR_RESET_VALUE ((uint8_t)0x00)
+#define CLK_HSIUNLCKR_RESET_VALUE ((uint8_t)0x00)
+#define CLK_REGCSR_RESET_VALUE ((uint8_t)0xB9)
+/**
+ * @}
+ */
+
+/** @addtogroup CLK_Registers_Bits_Definition
+ * @{
+ */
+
+#define CLK_CKDIVR_CKM ((uint8_t)0x07) /*!< System clock prescaler mask */
+
+#define CLK_CRTCR_RTCDIV ((uint8_t)0xE0) /*!< RTC clock prescaler mask*/
+#define CLK_CRTCR_RTCSEL ((uint8_t)0x1E) /*!< RTC clock output selection mask */
+#define CLK_CRTCR_RTCSWBSY ((uint8_t)0x01) /*!< RTC clock switch busy */
+
+#define CLK_ICKCR_BEEPAHALT ((uint8_t)0x40) /*!< BEEP clock Active Halt/Halt mode */
+#define CLK_ICKCR_FHWU ((uint8_t)0x20) /*!< Fast Wake-up from Active Halt/Halt mode */
+#define CLK_ICKCR_SAHALT ((uint8_t)0x10) /*!< Slow Active-halt mode */
+#define CLK_ICKCR_LSIRDY ((uint8_t)0x08) /*!< Low speed internal RC oscillator ready */
+#define CLK_ICKCR_LSION ((uint8_t)0x04) /*!< Low speed internal RC oscillator enable */
+#define CLK_ICKCR_HSIRDY ((uint8_t)0x02) /*!< High speed internal RC oscillator ready */
+#define CLK_ICKCR_HSION ((uint8_t)0x01) /*!< High speed internal RC oscillator enable */
+
+#define CLK_PCKENR1_TIM2 ((uint8_t)0x01) /*!< Timer 2 clock enable */
+#define CLK_PCKENR1_TIM3 ((uint8_t)0x02) /*!< Timer 3 clock enable */
+#define CLK_PCKENR1_TIM4 ((uint8_t)0x04) /*!< Timer 4 clock enable */
+#define CLK_PCKENR1_I2C1 ((uint8_t)0x08) /*!< I2C1 clock enable */
+#define CLK_PCKENR1_SPI1 ((uint8_t)0x10) /*!< SPI1 clock enable */
+#define CLK_PCKENR1_USART1 ((uint8_t)0x20) /*!< USART1 clock enable */
+#define CLK_PCKENR1_BEEP ((uint8_t)0x40) /*!< BEEP clock enable */
+#define CLK_PCKENR1_DAC ((uint8_t)0x80) /*!< DAC clock enable */
+
+#define CLK_PCKENR2_ADC1 ((uint8_t)0x01) /*!< ADC1 clock enable */
+#define CLK_PCKENR2_TIM1 ((uint8_t)0x02) /*!< TIM1 clock enable */
+#define CLK_PCKENR2_RTC ((uint8_t)0x04) /*!< RTC clock enable */
+#define CLK_PCKENR2_LCD ((uint8_t)0x08) /*!< LCD clock enable */
+#define CLK_PCKENR2_DMA1 ((uint8_t)0x10) /*!< DMA1 clock enable */
+#define CLK_PCKENR2_COMP ((uint8_t)0x20) /*!< Comparator clock enable */
+#define CLK_PCKENR2_BOOTROM ((uint8_t)0x80) /*!< Boot ROM clock enable */
+
+#define CLK_PCKENR3_AES ((uint8_t)0x01) /*!< AES clock enable */
+#define CLK_PCKENR3_TIM5 ((uint8_t)0x02) /*!< Timer 5 clock enable */
+#define CLK_PCKENR3_SPI2 ((uint8_t)0x04) /*!< SPI2 clock enable */
+#define CLK_PCKENR3_UASRT2 ((uint8_t)0x08) /*!< USART2 clock enable */
+#define CLK_PCKENR3_USART3 ((uint8_t)0x10) /*!< USART3 clock enable */
+
+#define CLK_CCOR_CCODIV ((uint8_t)0xE0) /*!< Configurable Clock output prescaler */
+#define CLK_CCOR_CCOSEL ((uint8_t)0x1E) /*!< Configurable clock output selection */
+#define CLK_CCOR_CCOSWBSY ((uint8_t)0x01) /*!< Configurable clock output switch busy flag */
+
+#define CLK_ECKCR_LSEBYP ((uint8_t)0x20) /*!< Low speed external clock bypass */
+#define CLK_ECKCR_HSEBYP ((uint8_t)0x10) /*!< High speed external clock bypass */
+#define CLK_ECKCR_LSERDY ((uint8_t)0x08) /*!< Low speed external crystal oscillator ready */
+#define CLK_ECKCR_LSEON ((uint8_t)0x04) /*!< Low speed external crystal oscillator enable */
+#define CLK_ECKCR_HSERDY ((uint8_t)0x02) /*!< High speed external crystal oscillator ready */
+#define CLK_ECKCR_HSEON ((uint8_t)0x01) /*!< High speed external crystal oscillator enable */
+
+#define CLK_SCSR_CKM ((uint8_t)0x0F) /*!< System clock status bits */
+
+#define CLK_SWR_SWI ((uint8_t)0x0F) /*!< System clock selection bits */
+
+#define CLK_SWCR_SWIF ((uint8_t)0x08) /*!< Clock switch interrupt flag */
+#define CLK_SWCR_SWIEN ((uint8_t)0x04) /*!< Clock switch interrupt enable */
+#define CLK_SWCR_SWEN ((uint8_t)0x02) /*!< Switch start/stop */
+#define CLK_SWCR_SWBSY ((uint8_t)0x01) /*!< Switch busy */
+
+#define CLK_CSSR_CSSDGON ((uint8_t)0x10) /*!< Clock security sytem deglitcher system */
+#define CLK_CSSR_CSSD ((uint8_t)0x08) /*!< Clock security sytem detection */
+#define CLK_CSSR_CSSDIE ((uint8_t)0x04) /*!< Clock security system detection interrupt enable */
+#define CLK_CSSR_AUX ((uint8_t)0x02) /*!< Auxiliary oscillator connected to master clock */
+#define CLK_CSSR_CSSEN ((uint8_t)0x01) /*!< Clock security system enable */
+
+#define CLK_CBEEPR_CLKBEEPSEL ((uint8_t)0x06) /*!< Configurable BEEP clock source selection */
+#define CLK_CBEEPR_BEEPSWBSY ((uint8_t)0x01) /*!< BEEP clock busy in switch */
+
+#define CLK_HSICALR_HSICAL ((uint8_t)0xFF) /*!< Copy of otpion byte trimming HSI oscillator */
+
+#define CLK_HSITRIMR_HSITRIM ((uint8_t)0xFF) /*!< High speed internal oscillator trimmer */
+
+#define CLK_HSIUNLCKR_HSIUNLCK ((uint8_t)0xFF) /*!< High speed internal oscillator trimmer unlock */
+
+#define CLK_REGCSR_EEREADY ((uint8_t)0x80) /*!< Flash program memory and Data EEPROM ready */
+#define CLK_REGCSR_EEBUSY ((uint8_t)0x40) /*!< Flash program memory and Data EEPROM busy */
+#define CLK_REGCSR_LSEPD ((uint8_t)0x20) /*!< LSE power-down */
+#define CLK_REGCSR_HSEPD ((uint8_t)0x10) /*!< HSE power-down */
+#define CLK_REGCSR_LSIPD ((uint8_t)0x08) /*!< LSI power-down */
+#define CLK_REGCSR_HSIPD ((uint8_t)0x04) /*!< HSI power-down */
+#define CLK_REGCSR_REGOFF ((uint8_t)0x02) /*!< Main regulator OFF */
+#define CLK_REGCSR_REGREADY ((uint8_t)0x01) /*!< Main regulator ready */
+
+/**
+ * @}
+ */
+/*----------------------------------------------------------------------------ok*/
+
+/**
+ * @brief Comparator interface (COMP)
+ */
+
+typedef struct COMP_struct
+{
+ __IO uint8_t CSR1; /*!< Control status register 1 */
+ __IO uint8_t CSR2; /*!< Control status register 2 */
+ __IO uint8_t CSR3; /*!< Control status register 3 */
+ __IO uint8_t CSR4; /*!< Control status register 4 */
+ __IO uint8_t CSR5; /*!< Control status register 5 */
+}
+COMP_TypeDef;
+
+
+/** @addtogroup COMP_Registers_Reset_Value
+ * @{
+ */
+#define COMP_CSR1_RESET_VALUE ((uint8_t)0x00)
+#define COMP_CSR2_RESET_VALUE ((uint8_t)0x00)
+#define COMP_CSR3_RESET_VALUE ((uint8_t)0xC0)
+#define COMP_CSR4_RESET_VALUE ((uint8_t)0x00)
+#define COMP_CSR5_RESET_VALUE ((uint8_t)0x00)
+
+/**
+ * @}
+ */
+
+/** @addtogroup COMP_Registers_Bits_Definition
+ * @{
+ */
+
+/* CSR1 */
+#define COMP_CSR1_IE1 ((uint8_t)0x20) /*!< Comparator 1 Interrupt Enable Mask. */
+#define COMP_CSR1_EF1 ((uint8_t)0x10) /*!< Comparator 1 Event Flag Mask. */
+#define COMP_CSR1_CMP1OUT ((uint8_t)0x08) /*!< Comparator 1 Ouptput Mask. */
+#define COMP_CSR1_STE ((uint8_t)0x04) /*!< Schmitt trigger enable Mask. */
+#define COMP_CSR1_CMP1 ((uint8_t)0x03) /*!< Comparator 1 Configuration Mask. */
+
+/* CSR2 */
+#define COMP_CSR2_IE2 ((uint8_t)0x20) /*!< Comparator 2 Interrupt Enable Mask. */
+#define COMP_CSR2_EF2 ((uint8_t)0x10) /*!< Comparator 2 Event Flag Mask. */
+#define COMP_CSR2_CMP2OUT ((uint8_t)0x08) /*!< Comparator 2 Ouptput Mask. */
+#define COMP_CSR2_SPEED ((uint8_t)0x04) /*!< Comparator 2 speed modeMask. */
+#define COMP_CSR2_CMP2 ((uint8_t)0x03) /*!< Comparator 2 Configuration Mask. */
+
+/* CSR3 */
+#define COMP_CSR3_OUTSEL ((uint8_t)0xC0) /*!< Comparator 2 output selection Mask. */
+#define COMP_CSR3_INSEL ((uint8_t)0x38) /*!< Inversion input selection Mask. */
+#define COMP_CSR3_VREFEN ((uint8_t)0x04) /*!< Internal reference voltage Enable Mask. */
+#define COMP_CSR3_WNDWE ((uint8_t)0x02) /*!< Window Mode Enable Mask. */
+#define COMP_CSR3_VREFOUTEN ((uint8_t)0x01) /*!< VREF Output Enable Mask. */
+
+/* CSR4 */
+#define COMP_CSR4_NINVTRIG ((uint8_t)0x38) /*!< COMP2 non-inverting input Mask. */
+#define COMP_CSR4_INVTRIG ((uint8_t)0x07) /*!< COMP2 inverting input Mask. */
+
+/* CSR5 */
+#define COMP_CSR5_DACTRIG ((uint8_t)0x38) /*!< DAC outputs Mask. */
+#define COMP_CSR5_VREFTRIG ((uint8_t)0x07) /*!< VREF outputs Mask. */
+
+/**
+ * @}
+ */
+
+/*----------------------------------------------------------------------------ok*/
+
+/**
+ * @brief External Interrupt Controller (EXTI)
+ */
+typedef struct EXTI_struct
+{
+ __IO uint8_t CR1; /*!< The four LSB EXTI pin sensitivity */
+ __IO uint8_t CR2; /*!< The four MSB EXTI pin sensitivity */
+ __IO uint8_t CR3; /*!< EXTI port B & port D sensitivity */
+ __IO uint8_t SR1; /*!< Pins Status flag register 1 */
+ __IO uint8_t SR2; /*!< Ports Status flage register 2 */
+ __IO uint8_t CONF1; /*!< Port interrupt selector */
+ uint8_t RESERVED[4]; /*!< reserved area */
+ __IO uint8_t CR4; /*!< EXTI port G & port H sensitivity */
+ __IO uint8_t CONF2; /*!< Port interrupt selector */
+}
+EXTI_TypeDef;
+
+/** @addtogroup EXTI_Registers_Reset_Value
+ * @{
+ */
+
+#define EXTI_CR1_RESET_VALUE ((uint8_t)0x00)
+#define EXTI_CR2_RESET_VALUE ((uint8_t)0x00)
+#define EXTI_CR3_RESET_VALUE ((uint8_t)0x00)
+#define EXTI_CONF1_RESET_VALUE ((uint8_t)0x00)
+#define EXTI_SR1_RESET_VALUE ((uint8_t)0x00)
+#define EXTI_SR2_RESET_VALUE ((uint8_t)0x00)
+#define EXTI_CR4_RESET_VALUE ((uint8_t)0x00)
+#define EXTI_CONF2_RESET_VALUE ((uint8_t)0x00)
+
+/**
+ * @}
+ */
+
+/** @addtogroup EXTI_Registers_Bits_Definition
+ * @{
+ */
+/* CR1 */
+#define EXTI_CR1_P3IS ((uint8_t)0xC0) /*!< EXTI Pin 3 external interrupt sensitivity bit Mask */
+#define EXTI_CR1_P2IS ((uint8_t)0x30) /*!< EXTI Pin 2 external interrupt sensitivity bit Mask */
+#define EXTI_CR1_P1IS ((uint8_t)0x0C) /*!< EXTI Pin 1 external interrupt sensitivity bit Mask */
+#define EXTI_CR1_P0IS ((uint8_t)0x03) /*!< EXTI Pin 0 external interrupt sensitivity bit Mask */
+
+/* CR2 */
+#define EXTI_CR2_P7IS ((uint8_t)0xC0) /*!< EXTI Pin 7 external interrupt sensitivity bit Mask */
+#define EXTI_CR2_P6IS ((uint8_t)0x30) /*!< EXTI Pin 6 external interrupt sensitivity bit Mask */
+#define EXTI_CR2_P5IS ((uint8_t)0x0C) /*!< EXTI Pin 5 external interrupt sensitivity bit Mask */
+#define EXTI_CR2_P4IS ((uint8_t)0x03) /*!< EXTI Pin 4 external interrupt sensitivity bit Mask */
+
+/* CR3 */
+#define EXTI_CR3_PBIS ((uint8_t)0x03) /*!< EXTI PORTB external interrupt sensitivity bits Mask */
+#define EXTI_CR3_PDIS ((uint8_t)0x0C) /*!< EXTI PORTD external interrupt sensitivity bits Mask */
+#define EXTI_CR3_PEIS ((uint8_t)0x30) /*!< EXTI PORTE external interrupt sensitivity bits Mask */
+#define EXTI_CR3_PFIS ((uint8_t)0xC0) /*!< EXTI PORTF external interrupt sensitivity bits Mask */
+
+/* CONF1 */
+#define EXTI_CONF1_PBLIS ((uint8_t)0x01) /*!< EXTI PORTB low interrupt selector bit Mask */
+#define EXTI_CONF1_PBHIS ((uint8_t)0x02) /*!< EXTI PORTB high interrupt selector bit Mask */
+#define EXTI_CONF1_PDLIS ((uint8_t)0x04) /*!< EXTI PORTD low interrupt selector bit Mask */
+#define EXTI_CONF1_PDHIS ((uint8_t)0x08) /*!< EXTI PORTD high interrupt selector bit Mask */
+#define EXTI_CONF1_PELIS ((uint8_t)0x10) /*!< EXTI PORTE low interrupt selector bit Mask */
+#define EXTI_CONF1_PEHIS ((uint8_t)0x20) /*!< EXTI PORTE high interrupt selector bit Mask */
+#define EXTI_CONF1_PFLIS ((uint8_t)0x40) /*!< EXTI PORTF low interrupt selector bit Mask */
+#define EXTI_CONF1_PFES ((uint8_t)0x80) /*!< EXTI PORTF or PORTE interrupt selector bit Mask */
+
+/* CR4 */
+#define EXTI_CR4_PGIS ((uint8_t)0x03) /*!< EXTI PORTG external interrupt sensitivity bits Mask */
+#define EXTI_CR4_PHIS ((uint8_t)0x0C) /*!< EXTI PORTH external interrupt sensitivity bits Mask */
+
+/* CONF2 */
+#define EXTI_CONF2_PFHIS ((uint8_t)0x01) /*!< EXTI PORTF high interrupt selector bit Mask */
+#define EXTI_CONF2_PGLIS ((uint8_t)0x02) /*!< EXTI PORTG low interrupt selector bit Mask */
+#define EXTI_CONF2_PGHIS ((uint8_t)0x04) /*!< EXTI PORTG high interrupt selector bit Mask */
+#define EXTI_CONF2_PHLIS ((uint8_t)0x08) /*!< EXTI PORTH low interrupt selector bit Mask */
+#define EXTI_CONF2_PHHIS ((uint8_t)0x10) /*!< EXTI PORTH high interrupt selector bit Mask */
+#define EXTI_CONF2_PGBS ((uint8_t)0x20) /*!< EXTI PORTB or PORTG interrupt selector bit Mask */
+#define EXTI_CONF2_PHDS ((uint8_t)0x40) /*!< EXTI PORTD or PORTH interrupt selector bit Mask */
+
+/**
+ * @}
+ */
+
+/*----------------------------------------------------------------------------ok*/
+
+/**
+ * @brief FLASH and Data EEPROM
+ */
+typedef struct FLASH_struct
+{
+ __IO uint8_t CR1; /*!< Flash control register 1 */
+ __IO uint8_t CR2; /*!< Flash control register 2 */
+ __IO uint8_t PUKR; /*!< Flash program memory unprotection register */
+ __IO uint8_t DUKR; /*!< Data EEPROM unprotection register */
+ __IO uint8_t IAPSR; /*!< Flash in-application programming status register */
+}
+FLASH_TypeDef;
+
+/** @addtogroup FLASH_Registers_Reset_Value
+ * @{
+ */
+#define FLASH_CR1_RESET_VALUE ((uint8_t)0x00)
+#define FLASH_CR2_RESET_VALUE ((uint8_t)0x00)
+#define FLASH_PUKR_RESET_VALUE ((uint8_t)0xAE)
+#define FLASH_DUKR_RESET_VALUE ((uint8_t)0x56)
+#define FLASH_IAPSR_RESET_VALUE ((uint8_t)0x40)
+
+
+/**
+ * @}
+ */
+
+/** @addtogroup FLASH_Registers_Bits_Definition
+ * @{
+ */
+#define FLASH_CR1_EEPM ((uint8_t)0x08) /*!< Flash low power selection during Run and Low power run mode Mask */
+#define FLASH_CR1_WAITM ((uint8_t)0x04) /*!< Flash low power selection during Wait and Low power wait mode Mask */
+#define FLASH_CR1_IE ((uint8_t)0x02) /*!< Flash Interrupt enable Mask */
+#define FLASH_CR1_FIX ((uint8_t)0x01) /*!< Fix programming time Mask */
+
+#define FLASH_CR2_OPT ((uint8_t)0x80) /*!< Enable write access to option bytes*/
+#define FLASH_CR2_WPRG ((uint8_t)0x40) /*!< Word write once Mask */
+#define FLASH_CR2_ERASE ((uint8_t)0x20) /*!< Erase block Mask */
+#define FLASH_CR2_FPRG ((uint8_t)0x10) /*!< Fast programming mode Mask */
+#define FLASH_CR2_PRG ((uint8_t)0x01) /*!< Program block Mask */
+
+#define FLASH_IAPSR_HVOFF ((uint8_t)0x40) /*!< End of high voltage flag Mask */
+#define FLASH_IAPSR_DUL ((uint8_t)0x08) /*!< Data EEPROM unlocked flag Mask */
+#define FLASH_IAPSR_EOP ((uint8_t)0x04) /*!< End of operation flag Mask */
+#define FLASH_IAPSR_PUL ((uint8_t)0x02) /*!< Program memory unlocked flag Mask */
+#define FLASH_IAPSR_WR_PG_DIS ((uint8_t)0x01) /*!< Write attempted to protected page Mask */
+
+#define FLASH_PUKR_PUK ((uint8_t)0xFF) /*!< Flash Program memory unprotection mask */
+
+#define FLASH_DUKR_DUK ((uint8_t)0xFF) /*!< Data EEPROM unprotection mask */
+
+
+/**
+ * @}
+ */
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @brief Inter-Integrated Circuit (I2C)
+ */
+typedef struct I2C_struct
+{
+ __IO uint8_t CR1; /*!< I2C control register 1 */
+ __IO uint8_t CR2; /*!< I2C control register 2 */
+ __IO uint8_t FREQR; /*!< I2C frequency register */
+ __IO uint8_t OARL; /*!< I2C own address register 1 LSB */
+ __IO uint8_t OARH; /*!< I2C own address register 1 MSB */
+ __IO uint8_t OAR2; /*!< I2C own address register 2 */
+ __IO uint8_t DR; /*!< I2C data register */
+ __IO uint8_t SR1; /*!< I2C status register 1 */
+ __IO uint8_t SR2; /*!< I2C status register 2 */
+ __IO uint8_t SR3; /*!< I2C status register 3 */
+ __IO uint8_t ITR; /*!< I2C interrupt & DMA register */
+ __IO uint8_t CCRL; /*!< I2C clock control register low */
+ __IO uint8_t CCRH; /*!< I2C clock control register high */
+ __IO uint8_t TRISER; /*!< I2C maximum rise time register */
+ __IO uint8_t PECR; /*!< I2CPacket Error Checking register */
+}
+I2C_TypeDef;
+
+/** @addtogroup I2C_Registers_Reset_Value
+ * @{
+ */
+#define I2C_CR1_RESET_VALUE ((uint8_t)0x00)
+#define I2C_CR2_RESET_VALUE ((uint8_t)0x00)
+#define I2C_FREQR_RESET_VALUE ((uint8_t)0x00)
+#define I2C_OARL_RESET_VALUE ((uint8_t)0x00)
+#define I2C_OARH_RESET_VALUE ((uint8_t)0x00)
+#define I2C_OAR2_RESET_VALUE ((uint8_t)0x00)
+#define I2C_DR_RESET_VALUE ((uint8_t)0x00)
+#define I2C_SR1_RESET_VALUE ((uint8_t)0x00)
+#define I2C_SR2_RESET_VALUE ((uint8_t)0x00)
+#define I2C_SR3_RESET_VALUE ((uint8_t)0x00)
+#define I2C_ITR_RESET_VALUE ((uint8_t)0x00)
+#define I2C_CCRL_RESET_VALUE ((uint8_t)0x00)
+#define I2C_CCRH_RESET_VALUE ((uint8_t)0x00)
+#define I2C_TRISER_RESET_VALUE ((uint8_t)0x02)
+#define I2C_PECR_RESET_VALUE ((uint8_t)0x00)
+
+/**
+ * @}
+ */
+
+/** @addtogroup I2C_Registers_Bits_Definition
+ * @{
+ */
+
+#define I2C_CR1_NOSTRETCH ((uint8_t)0x80) /*!< Clock Stretching Disable (Slave mode) */
+#define I2C_CR1_ENGC ((uint8_t)0x40) /*!< General Call Enable */
+#define I2C_CR1_ENPEC ((uint8_t)0x20) /*!< PEC Enable */
+#define I2C_CR1_ARP ((uint8_t)0x10) /*!< ARP Enable */
+#define I2C_CR1_SMBTYPE ((uint8_t)0x08) /*!< SMBus type */
+#define I2C_CR1_SMBUS ((uint8_t)0x02) /*!< SMBus mode */
+#define I2C_CR1_PE ((uint8_t)0x01) /*!< Peripheral Enable */
+
+#define I2C_CR2_SWRST ((uint8_t)0x80) /*!< Software Reset */
+#define I2C_CR2_ALERT ((uint8_t)0x20) /*!< SMBus Alert*/
+#define I2C_CR2_PEC ((uint8_t)0x10) /*!< Packet Error Checking */
+#define I2C_CR2_POS ((uint8_t)0x08) /*!< Acknowledge */
+#define I2C_CR2_ACK ((uint8_t)0x04) /*!< Acknowledge Enable */
+#define I2C_CR2_STOP ((uint8_t)0x02) /*!< Stop Generation */
+#define I2C_CR2_START ((uint8_t)0x01) /*!< Start Generation */
+
+#define I2C_FREQR_FREQ ((uint8_t)0x3F) /*!< Peripheral Clock Frequency */
+
+#define I2C_OARL_ADD ((uint8_t)0xFE) /*!< Interface Address bits [7..1] */
+#define I2C_OARL_ADD0 ((uint8_t)0x01) /*!< Interface Address bit0 */
+
+#define I2C_OARH_ADDMODE ((uint8_t)0x80) /*!< Addressing Mode (Slave mode) */
+#define I2C_OARH_ADDCONF ((uint8_t)0x40) /*!< Address mode configuration */
+#define I2C_OARH_ADD ((uint8_t)0x06) /*!< Interface Address bits [9..8] */
+
+#define I2C_OAR2_ADD2 ((uint8_t)0xFE) /*!< Interface Address bits [7..1] */
+#define I2C_OAR2_ENDUAL ((uint8_t)0x01) /*!< Dual addressing mode enable */
+
+#define I2C_DR_DR ((uint8_t)0xFF) /*!< Data Register */
+
+#define I2C_SR1_TXE ((uint8_t)0x80) /*!< Data Register Empty (transmitters) */
+#define I2C_SR1_RXNE ((uint8_t)0x40) /*!< Data Register not Empty (receivers) */
+#define I2C_SR1_STOPF ((uint8_t)0x10) /*!< Stop detection (Slave mode) */
+#define I2C_SR1_ADD10 ((uint8_t)0x08) /*!< 10-bit header sent (Master mode) */
+#define I2C_SR1_BTF ((uint8_t)0x04) /*!< Byte Transfer Finished */
+#define I2C_SR1_ADDR ((uint8_t)0x02) /*!< Address sent (master mode)/matched (slave mode) */
+#define I2C_SR1_SB ((uint8_t)0x01) /*!< Start Bit (Master mode) */
+
+#define I2C_SR2_SMBALERT ((uint8_t)0x80) /*!< SMBus Alert */
+#define I2C_SR2_TIMEOUT ((uint8_t)0x40) /*!< Time out or TLow error */
+#define I2C_SR2_WUFH ((uint8_t)0x20) /*!< Wake-up from Halt */
+#define I2C_SR2_PECERR ((uint8_t)0x10) /*!< PEC error in reception */
+#define I2C_SR2_OVR ((uint8_t)0x08) /*!< Overrun/Underrun */
+#define I2C_SR2_AF ((uint8_t)0x04) /*!< Acknowledge Failure */
+#define I2C_SR2_ARLO ((uint8_t)0x02) /*!< Arbitration Lost (master mode) */
+#define I2C_SR2_BERR ((uint8_t)0x01) /*!< Bus Error */
+
+#define I2C_SR3_DUALF ((uint8_t)0x80) /*!< Dual flag (Slave mode) */
+#define I2C_SR3_SMBHOST ((uint8_t)0x40) /*!< SMBus Host Header (Slave mode) */
+#define I2C_SR3_SMBDEFAULT ((uint8_t)0x20) /*!< SMBus Default Header (Slave mode) */
+#define I2C_SR3_GENCALL ((uint8_t)0x10) /*!< General Call Header (Slave mode) */
+#define I2C_SR3_TRA ((uint8_t)0x04) /*!< Transmitter/Receiver */
+#define I2C_SR3_BUSY ((uint8_t)0x02) /*!< Bus Busy */
+#define I2C_SR3_MSL ((uint8_t)0x01) /*!< Master/Slave */
+
+#define I2C_ITR_LAST ((uint8_t)0x10) /*!< DMA Last transfer */
+#define I2C_ITR_DMAEN ((uint8_t)0x08) /*!< DMA request Enable */
+#define I2C_ITR_ITBUFEN ((uint8_t)0x04) /*!< Buffer Interrupt Enable */
+#define I2C_ITR_ITEVTEN ((uint8_t)0x02) /*!< Event Interrupt Enable */
+#define I2C_ITR_ITERREN ((uint8_t)0x01) /*!< Error Interrupt Enable */
+
+#define I2C_CCRL_CCR ((uint8_t)0xFF) /*!< Clock Control Register (Master mode) */
+
+#define I2C_CCRH_FS ((uint8_t)0x80) /*!< Master Mode Selection */
+#define I2C_CCRH_DUTY ((uint8_t)0x40) /*!< Fast Mode Duty Cycle */
+#define I2C_CCRH_CCR ((uint8_t)0x0F) /*!< Clock Control Register in Fast/Standard mode (Master mode) bits [11..8] */
+
+#define I2C_TRISER_TRISE ((uint8_t)0x3F) /*!< Maximum Rise Time in Fast/Standard mode (Master mode) */
+
+#define I2C_PECR_PEC ((uint8_t)0xFF) /*!< Packet error checking */
+
+/**
+ * @}
+ */
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @brief IR digital interface (IRTIM)
+ */
+typedef struct IRTIM_struct
+{
+ __IO uint8_t CR; /*!< control register */
+}
+IRTIM_TypeDef;
+/** @addtogroup IRTIM_Registers_Reset_Value
+ * @{
+ */
+#define IRTIM_CR_RESET_VALUE ((uint8_t)0x00)
+
+
+/**
+* @}
+*/
+
+/** @addtogroup IRTIM_Registers_Bits_Definition
+ * @{
+ */
+/* CR*/
+#define IRTIM_CR_EN ((uint8_t)0x01) /*!< IRTIM_OUT enable Mask. */
+#define IRTIM_CR_HSEN ((uint8_t)0x02) /*!< High sink open drain buffer enable Mask */
+
+/**
+ * @}
+ */
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @brief Interrupt Controller (ITC)
+ */
+typedef struct ITC_struct
+{
+ __IO uint8_t ISPR1; /*!< Interrupt Software Priority register 1 */
+ __IO uint8_t ISPR2; /*!< Interrupt Software Priority register 2 */
+ __IO uint8_t ISPR3; /*!< Interrupt Software Priority register 3 */
+ __IO uint8_t ISPR4; /*!< Interrupt Software Priority register 4 */
+ __IO uint8_t ISPR5; /*!< Interrupt Software Priority register 5 */
+ __IO uint8_t ISPR6; /*!< Interrupt Software Priority register 6 */
+ __IO uint8_t ISPR7; /*!< Interrupt Software Priority register 7 */
+ __IO uint8_t ISPR8; /*!< Interrupt Software Priority register 8 */
+}
+ITC_TypeDef;
+
+/** @addtogroup ITC_Registers_Reset_Value
+ * @{
+ */
+#define ITC_SPRX_RESET_VALUE ((uint8_t)0xFF) /*!< Reset value of Software Priority registers 0 to 7 */
+/**
+ * @}
+ */
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @brief Internal Low Speed Watchdog (IWDG)
+ */
+typedef struct IWDG_struct
+{
+ __IO uint8_t KR; /*!< Low Speed Watchdog Key Register */
+ __IO uint8_t PR; /*!< Low Speed Watchdog Prescaler Register */
+ __IO uint8_t RLR; /*!< Low Speed Watchdog Reload Register */
+}
+IWDG_TypeDef;
+
+/** @addtogroup IWDG_Registers_Reset_Value
+ * @{
+ */
+#define IWDG_RLR_RESET_VALUE ((uint8_t)0xFF) /*!
+ #define enableInterrupts() _rim_() /*!
+ #define enableInterrupts() __enable_interrupt() /* enable interrupts */
+ #define disableInterrupts() __disable_interrupt() /* disable interrupts */
+ #define rim() __enable_interrupt() /* enable interrupts */
+ #define sim() __disable_interrupt() /* disable interrupts */
+ #define nop() __no_operation() /* No Operation */
+ #define trap() __trap() /* Trap (soft IT) */
+ #define wfi() __wait_for_interrupt() /* Wait For Interrupt */
+ #define wfe() __wait_for_event(); /* Wait for event */
+ #define halt() __halt() /* Halt */
+#endif /* _RAISONANCE_ */
+
+/*============================== Interrupt vector Handling ========================*/
+
+#ifdef _COSMIC_
+ #define INTERRUPT_HANDLER(a,b) @far @interrupt void a(void)
+ #define INTERRUPT_HANDLER_TRAP(a) void @far @interrupt a(void)
+#endif /* _COSMIC_ */
+
+#ifdef _RAISONANCE_
+ #define INTERRUPT_HANDLER(a,b) void a(void) interrupt b
+ #define INTERRUPT_HANDLER_TRAP(a) void a(void) trap
+#endif /* _RAISONANCE_ */
+
+#ifdef _IAR_
+ #define STRINGVECTOR(x) #x
+ #define VECTOR_ID(x) STRINGVECTOR( vector = (x) )
+ #define INTERRUPT_HANDLER( a, b ) \
+ _Pragma( VECTOR_ID( (b)+2 ) ) \
+ __interrupt void (a)( void )
+ #define INTERRUPT_HANDLER_TRAP(a) \
+ _Pragma( VECTOR_ID( 1 ) ) \
+ __interrupt void (a) (void)
+#endif /* _IAR_ */
+
+/*============================== Interrupt Handler declaration ========================*/
+#ifdef _COSMIC_
+ #define INTERRUPT @far @interrupt @svlreg
+#elif defined(_IAR_)
+ #define INTERRUPT __interrupt
+#endif /* _COSMIC_ */
+
+/*============================== Handling bits ====================================*/
+/*-----------------------------------------------------------------------------
+Method : I
+Description : Handle the bit from the character variables.
+Comments : The different parameters of commands are
+ - VAR : Name of the character variable where the bit is located.
+ - Place : Bit position in the variable (7 6 5 4 3 2 1 0)
+ - Value : Can be 0 (reset bit) or not 0 (set bit)
+ The "MskBit" command allows to select some bits in a source
+ variables and copy it in a destination var (return the value).
+ The "ValBit" command returns the value of a bit in a char
+ variable: the bit is reset if it returns 0 else the bit is set.
+ This method generates not an optimised code yet.
+-----------------------------------------------------------------------------*/
+#define SetBit(VAR,Place) ( (VAR) |= (uint8_t)((uint8_t)1<<(uint8_t)(Place)) )
+#define ClrBit(VAR,Place) ( (VAR) &= (uint8_t)((uint8_t)((uint8_t)1<<(uint8_t)(Place))^(uint8_t)255) )
+
+#define ChgBit(VAR,Place) ( (VAR) ^= (uint8_t)((uint8_t)1<<(uint8_t)(Place)) )
+#define AffBit(VAR,Place,Value) ((Value) ? \
+ ((VAR) |= ((uint8_t)1<<(Place))) : \
+ ((VAR) &= (((uint8_t)1<<(Place))^(uint8_t)255)))
+#define MskBit(Dest,Msk,Src) ( (Dest) = ((Msk) & (Src)) | ((~(Msk)) & (Dest)) )
+
+#define ValBit(VAR,Place) ((uint8_t)(VAR) & (uint8_t)((uint8_t)1<<(uint8_t)(Place)))
+
+#define BYTE_0(n) ((uint8_t)((n) & (uint8_t)0xFF)) /*!< Returns the low byte of the 32-bit value */
+#define BYTE_1(n) ((uint8_t)(BYTE_0((n) >> (uint8_t)8))) /*!< Returns the second byte of the 32-bit value */
+#define BYTE_2(n) ((uint8_t)(BYTE_0((n) >> (uint8_t)16))) /*!< Returns the third byte of the 32-bit value */
+#define BYTE_3(n) ((uint8_t)(BYTE_0((n) >> (uint8_t)24))) /*!< Returns the high byte of the 32-bit value */
+
+/*============================== Assert Macros ====================================*/
+#define IS_STATE_VALUE(STATE) \
+ (((STATE) == SET) || \
+ ((STATE) == RESET))
+
+/*-----------------------------------------------------------------------------
+Method : II
+Description : Handle directly the bit.
+Comments : The idea is to handle directly with the bit name. For that, it is
+ necessary to have RAM area descriptions (example: HW register...)
+ and the following command line for each area.
+ This method generates the most optimized code.
+-----------------------------------------------------------------------------*/
+
+#define AREA 0x00 /* The area of bits begins at address 0x10. */
+
+#define BitClr(BIT) ( *((unsigned char *) (AREA+(BIT)/8)) &= (~(1<<(7-(BIT)%8))) )
+#define BitSet(BIT) ( *((unsigned char *) (AREA+(BIT)/8)) |= (1<<(7-(BIT)%8)) )
+#define BitVal(BIT) ( *((unsigned char *) (AREA+(BIT)/8)) & (1<<(7-(BIT)%8)) )
+
+
+#endif /* __STM8L15x_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_adc.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_adc.h
new file mode 100644
index 00000000..cfb1d662
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_adc.h
@@ -0,0 +1,386 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_adc.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the ADC
+ * firmware library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_ADC_H
+#define __STM8L15x_ADC_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup ADC
+ * @{
+ */
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup ADC_Exported_Types
+ * @{
+ */
+
+
+/** @defgroup ADC_Channels
+ * @{
+ */
+typedef enum
+{
+ ADC_Channel_0 = ((uint16_t)0x0301), /*!< Channel 00 */
+ ADC_Channel_1 = ((uint16_t)0x0302), /*!< Channel 01 */
+ ADC_Channel_2 = ((uint16_t)0x0304), /*!< Channel 02 */
+ ADC_Channel_3 = ((uint16_t)0x0308), /*!< Channel 03 */
+ ADC_Channel_4 = ((uint16_t)0x0310), /*!< Channel 04 */
+ ADC_Channel_5 = ((uint16_t)0x0320), /*!< Channel 05 */
+ ADC_Channel_6 = ((uint16_t)0x0340), /*!< Channel 06 */
+ ADC_Channel_7 = ((uint16_t)0x0380), /*!< Channel 07 */
+
+ ADC_Channel_8 = ((uint16_t)0x0201), /*!< Channel 08 */
+ ADC_Channel_9 = ((uint16_t)0x0202), /*!< Channel 09 */
+ ADC_Channel_10 = ((uint16_t)0x0204), /*!< Channel 10 */
+ ADC_Channel_11 = ((uint16_t)0x0208), /*!< Channel 11 */
+ ADC_Channel_12 = ((uint16_t)0x0210), /*!< Channel 12 */
+ ADC_Channel_13 = ((uint16_t)0x0220), /*!< Channel 13 */
+ ADC_Channel_14 = ((uint16_t)0x0240), /*!< Channel 14 */
+ ADC_Channel_15 = ((uint16_t)0x0280), /*!< Channel 15 */
+
+ ADC_Channel_16 = ((uint16_t)0x0101), /*!< Channel 16 */
+ ADC_Channel_17 = ((uint16_t)0x0102), /*!< Channel 17 */
+ ADC_Channel_18 = ((uint16_t)0x0104), /*!< Channel 18 */
+ ADC_Channel_19 = ((uint16_t)0x0108), /*!< Channel 19 */
+ ADC_Channel_20 = ((uint16_t)0x0110), /*!< Channel 20 */
+ ADC_Channel_21 = ((uint16_t)0x0120), /*!< Channel 21 */
+ ADC_Channel_22 = ((uint16_t)0x0140), /*!< Channel 22 */
+ ADC_Channel_23 = ((uint16_t)0x0180), /*!< Channel 23 */
+
+ ADC_Channel_24 = ((uint16_t)0x0001), /*!< Channel 24 */
+ ADC_Channel_25 = ((uint16_t)0x0002), /*!< Channel 25 */
+ ADC_Channel_26 = ((uint16_t)0x0004), /*!< Channel 26 */
+ ADC_Channel_27 = ((uint16_t)0x0008), /*!< Channel 27 */
+
+ ADC_Channel_Vrefint = ((uint16_t)0x0010), /*!< Vrefint Channel */
+ ADC_Channel_TempSensor = ((uint16_t)0x0020), /*!< Temperature sensor Channel */
+
+ /* combination*/
+ ADC_Channel_00To07 = ((uint16_t)0x03FF), /*!© COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_AES_H
+#define __STM8L15x_AES_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup AES
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup AES_Exported_Types
+ * @{
+ */
+
+/** @defgroup AES_Operation_Mode
+ * @{
+ */
+typedef enum
+{
+ AES_Operation_Encryp = (uint8_t)0x00, /*!< AES in Encryption mode */
+ AES_Operation_KeyDeriv = (uint8_t)0x02, /*!< AES in Key Derivation mode */
+ AES_Operation_Decryp = (uint8_t)0x04, /*!< AES in Decryption mode */
+ AES_Operation_KeyDerivAndDecryp = (uint8_t)0x06 /*!< AES in Key Derivation and Decryption mode */
+} AES_Operation_TypeDef;
+
+#define IS_AES_MODE(Operation) (((Operation) == AES_Operation_Encryp) || \
+ ((Operation) == AES_Operation_KeyDeriv) || \
+ ((Operation) == AES_Operation_Decryp) || \
+ ((Operation) == AES_Operation_KeyDerivAndDecryp))
+/**
+ * @}
+ */
+
+/** @defgroup AES_Flags
+ * @{
+ */
+typedef enum
+{
+ AES_FLAG_CCF = (uint8_t)0x01, /*!< Computation Complete Flag */
+ AES_FLAG_RDERR = (uint8_t)0x02, /*!< Read Error Flag */
+ AES_FLAG_WRERR = (uint8_t)0x04 /*!< Write Error Flag */
+}AES_FLAG_TypeDef;
+
+#define IS_AES_FLAG(Flag) (((Flag) == AES_FLAG_CCF) || \
+ ((Flag) == AES_FLAG_RDERR) || \
+ ((Flag) == AES_FLAG_WRERR))
+
+/**
+ * @}
+ */
+
+/** @defgroup AES_Interrupts
+ * @{
+ */
+typedef enum
+{
+ AES_IT_CCIE = (uint16_t)0x20, /*!< Computation Complete interrupt enable */
+ AES_IT_ERRIE = (uint16_t)0x40 /*!< Error interrupt enable */
+}AES_IT_TypeDef;
+
+#define IS_AES_IT(IT) (((IT) == AES_IT_CCIE) || \
+ ((IT) == AES_IT_ERRIE))
+
+/**
+ * @}
+ */
+
+/** @defgroup AES_DMA_Transfer_Direction
+ * @{
+ */
+typedef enum
+{
+ AES_DMATransfer_InOut = (uint8_t) 0x80 /*!< DMA requests enabled for input transfer phase
+ as well as for the output transfer phase */
+}
+AES_DMATransfer_TypeDef;
+
+#define IS_AES_DMATRANSFER(Transfer) ((Transfer) == AES_DMATransfer_InOut)
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+/* Function used to set the AES configuration to the default reset state *****/
+void AES_DeInit(void);
+
+/* AES Configuration **********************************************************/
+void AES_OperationModeConfig(AES_Operation_TypeDef AES_Operation);
+void AES_Cmd(FunctionalState NewState);
+
+/* AES Read and Write operations **********************************************/
+void AES_WriteSubData(uint8_t Data);
+void AES_WriteSubKey(uint8_t Key);
+uint8_t AES_ReadSubData(void);
+uint8_t AES_ReadSubKey(void);
+
+/* DMA transfers management function ******************************************/
+void AES_DMAConfig(AES_DMATransfer_TypeDef AES_DMATransfer, FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void AES_ITConfig(AES_IT_TypeDef AES_IT, FunctionalState NewState);
+FlagStatus AES_GetFlagStatus(AES_FLAG_TypeDef AES_FLAG);
+void AES_ClearFlag(AES_FLAG_TypeDef AES_FLAG);
+ITStatus AES_GetITStatus(AES_IT_TypeDef AES_IT);
+void AES_ClearITPendingBit(AES_IT_TypeDef AES_IT);
+
+#endif /* __STM8L15x_AES_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_beep.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_beep.h
new file mode 100644
index 00000000..ac42d7cf
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_beep.h
@@ -0,0 +1,117 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_beep.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the BEEP firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_BEEP_H
+#define __STM8L15x_BEEP_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup BEEP
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+/** @defgroup BEEP_Exported_Types
+ * @{
+ */
+
+/** @defgroup BEEP_Frequency
+ * @{
+ */
+typedef enum {
+ BEEP_Frequency_1KHz = (uint8_t)0x00, /*!< Beep signal output frequency 1 KHz */
+ BEEP_Frequency_2KHz = (uint8_t)0x40, /*!< Beep signal output frequency 2 KHz */
+ BEEP_Frequency_4KHz = (uint8_t)0x80 /*!< Beep signal output frequency 4 KHz */
+} BEEP_Frequency_TypeDef;
+
+#define IS_BEEP_FREQUENCY(FREQ) (((FREQ) == BEEP_Frequency_1KHz) || \
+ ((FREQ) == BEEP_Frequency_2KHz) || \
+ ((FREQ) == BEEP_Frequency_4KHz))
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/** @defgroup BEEP_Exported_Constants
+ * @{
+ */
+
+#define BEEP_CALIBRATION_DEFAULT ((uint8_t)0x01) /*!< Default value when calibration is not done */
+#define LSI_FREQUENCY_MIN ((uint32_t)25000) /*!< LSI minimum value in Hertz */
+#define LSI_FREQUENCY_MAX ((uint32_t)75000) /*!< LSI maximum value in Hertz */
+
+/**
+ * @}
+ */
+
+/* Exported macros -----------------------------------------------------------*/
+/** @defgroup BEEP_Exported_Macros
+ * @{
+ */
+#define IS_LSI_FREQUENCY(FREQ) (((FREQ) >= LSI_FREQUENCY_MIN) && ((FREQ) <= LSI_FREQUENCY_MAX))
+
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+
+/* Function used to set the BEEP configuration to the default reset state *****/
+void BEEP_DeInit(void);
+
+/* Initialization and Configuration functions *********************************/
+void BEEP_Init(BEEP_Frequency_TypeDef BEEP_Frequency);
+void BEEP_Cmd(FunctionalState NewState);
+
+/* Low Speed Internal Clock(LSI) Calibration functions ***********************/
+void BEEP_LSClockToTIMConnectCmd(FunctionalState NewState);
+void BEEP_LSICalibrationConfig(uint32_t LSIFreqHz);
+
+
+#endif /* __STM8L15x_BEEP_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_clk.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_clk.h
new file mode 100644
index 00000000..5dbe24b4
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_clk.h
@@ -0,0 +1,444 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_clk.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the CLK firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_CLK_H
+#define __STM8L15x_CLK_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup CLK
+ * @{
+ */
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup Exported_Types
+ * @{
+ */
+
+/** @defgroup CLK_HSE_Configuration
+ * @{
+ */
+typedef enum {
+ CLK_HSE_OFF = (uint8_t)0x00, /*!< HSE Disable */
+ CLK_HSE_ON = (uint8_t)0x01, /*!< HSE Enable */
+ CLK_HSE_Bypass = (uint8_t)0x11 /*!< HSE Bypass and enable */
+} CLK_HSE_TypeDef;
+
+#define IS_CLK_HSE(CONFIG) (((CONFIG) == CLK_HSE_ON) ||\
+ ((CONFIG) == CLK_HSE_OFF)||\
+ ((CONFIG) == CLK_HSE_Bypass))
+/**
+ * @}
+ */
+
+/** @defgroup CLK_LSE_Configuration
+ * @{
+ */
+typedef enum {
+ CLK_LSE_OFF = (uint8_t)0x00, /*!< LSE Disable */
+ CLK_LSE_ON = (uint8_t)0x04, /*!< LSE Enable */
+ CLK_LSE_Bypass = (uint8_t)0x24 /*!< LSE Bypass and enable */
+} CLK_LSE_TypeDef;
+
+#define IS_CLK_LSE(CONFIG) (((CONFIG) == CLK_LSE_OFF) ||\
+ ((CONFIG) == CLK_LSE_ON) ||\
+ ((CONFIG) == CLK_LSE_Bypass))
+/**
+ * @}
+ */
+
+/** @defgroup CLK_System_Clock_Sources
+ * @{
+ */
+typedef enum {
+ CLK_SYSCLKSource_HSI = (uint8_t)0x01, /*!< System Clock Source HSI */
+ CLK_SYSCLKSource_LSI = (uint8_t)0x02, /*!< System Clock Source LSI */
+ CLK_SYSCLKSource_HSE = (uint8_t)0x04, /*!< System Clock Source HSE */
+ CLK_SYSCLKSource_LSE = (uint8_t)0x08 /*!< System Clock Source LSE */
+} CLK_SYSCLKSource_TypeDef;
+
+#define IS_CLK_SOURCE(SOURCE) (((SOURCE) == CLK_SYSCLKSource_HSI) ||\
+ ((SOURCE) == CLK_SYSCLKSource_LSI) ||\
+ ((SOURCE) == CLK_SYSCLKSource_HSE) ||\
+ ((SOURCE) == CLK_SYSCLKSource_LSE))
+/**
+ * @}
+ */
+
+/** @defgroup CLK_Clock_Output_Selection
+ * @{
+ */
+typedef enum {
+ CLK_CCOSource_Off = (uint8_t)0x00, /*!< Clock Output Off */
+ CLK_CCOSource_HSI = (uint8_t)0x02, /*!< HSI Clock Output */
+ CLK_CCOSource_LSI = (uint8_t)0x04, /*!< LSI Clock Output */
+ CLK_CCOSource_HSE = (uint8_t)0x08, /*!< HSE Clock Output */
+ CLK_CCOSource_LSE = (uint8_t)0x10 /*!< LSE Clock Output */
+} CLK_CCOSource_TypeDef;
+
+#define IS_CLK_OUTPUT(OUTPUT) (((OUTPUT) == CLK_CCOSource_Off) ||\
+ ((OUTPUT) == CLK_CCOSource_HSI) ||\
+ ((OUTPUT) == CLK_CCOSource_LSI) ||\
+ ((OUTPUT) == CLK_CCOSource_HSE) ||\
+ ((OUTPUT) == CLK_CCOSource_LSE))
+/**
+ * @}
+ */
+
+/** @defgroup CLK_Clock_Output_Prescaler
+ * @{
+ */
+typedef enum {
+ CLK_CCODiv_1 = (uint8_t)0x00, /*!< Clock Output Div 1 */
+ CLK_CCODiv_2 = (uint8_t)0x20, /*!< Clock Output Div 2 */
+ CLK_CCODiv_4 = (uint8_t)0x40, /*!< Clock Output Div 4 */
+ CLK_CCODiv_8 = (uint8_t)0x60, /*!< Clock Output Div 8 */
+ CLK_CCODiv_16 = (uint8_t)0x80, /*!< Clock Output Div 16 */
+ CLK_CCODiv_32 = (uint8_t)0xA0, /*!< Clock Output Div 32 */
+ CLK_CCODiv_64 = (uint8_t)0xC0 /*!< Clock Output Div 64 */
+} CLK_CCODiv_TypeDef;
+
+#define IS_CLK_OUTPUT_DIVIDER(PRESCALER) (((PRESCALER) == CLK_CCODiv_1) ||\
+ ((PRESCALER) == CLK_CCODiv_2) ||\
+ ((PRESCALER) == CLK_CCODiv_4) ||\
+ ((PRESCALER) == CLK_CCODiv_8) ||\
+ ((PRESCALER) == CLK_CCODiv_16) ||\
+ ((PRESCALER) == CLK_CCODiv_32) ||\
+ ((PRESCALER) == CLK_CCODiv_64))
+/**
+ * @}
+ */
+
+/** @defgroup CLK_Beep_Selection
+ * @{
+ */
+typedef enum {
+ CLK_BEEPCLKSource_Off = (uint8_t)0x00, /*!< Clock BEEP Off */
+ CLK_BEEPCLKSource_LSI = (uint8_t)0x02, /*!< Clock BEEP : LSI */
+ CLK_BEEPCLKSource_LSE = (uint8_t)0x04 /*!< Clock BEEP : LSE */
+} CLK_BEEPCLKSource_TypeDef;
+
+#define IS_CLK_CLOCK_BEEP(OUTPUT) (((OUTPUT) == CLK_BEEPCLKSource_Off) ||\
+ ((OUTPUT) == CLK_BEEPCLKSource_LSI) ||\
+ ((OUTPUT) == CLK_BEEPCLKSource_LSE))
+/**
+ * @}
+ */
+
+/** @defgroup CLK_RTC_Selection
+ * @{
+ */
+typedef enum {
+ CLK_RTCCLKSource_Off = (uint8_t)0x00, /*!< Clock RTC Off */
+ CLK_RTCCLKSource_HSI = (uint8_t)0x02, /*!< Clock RTC : HSI */
+ CLK_RTCCLKSource_LSI = (uint8_t)0x04, /*!< Clock RTC : LSI */
+ CLK_RTCCLKSource_HSE = (uint8_t)0x08, /*!< Clock RTC : HSE */
+ CLK_RTCCLKSource_LSE = (uint8_t)0x10 /*!< Clock RTC : LSE */
+} CLK_RTCCLKSource_TypeDef;
+
+#define IS_CLK_CLOCK_RTC(OUTPUT) (((OUTPUT) == CLK_RTCCLKSource_Off) ||\
+ ((OUTPUT) == CLK_RTCCLKSource_HSI) ||\
+ ((OUTPUT) == CLK_RTCCLKSource_LSI) ||\
+ ((OUTPUT) == CLK_RTCCLKSource_HSE) ||\
+ ((OUTPUT) == CLK_RTCCLKSource_LSE))
+/**
+ * @}
+ */
+
+/** @defgroup CLK_RTC_Prescaler
+ * @{
+ */
+typedef enum {
+ CLK_RTCCLKDiv_1 = (uint8_t)0x00, /*!< Clock RTC Div 1 */
+ CLK_RTCCLKDiv_2 = (uint8_t)0x20, /*!< Clock RTC Div 2 */
+ CLK_RTCCLKDiv_4 = (uint8_t)0x40, /*!< Clock RTC Div 4 */
+ CLK_RTCCLKDiv_8 = (uint8_t)0x60, /*!< Clock RTC Div 8 */
+ CLK_RTCCLKDiv_16 = (uint8_t)0x80, /*!< Clock RTC Div 16 */
+ CLK_RTCCLKDiv_32 = (uint8_t)0xA0, /*!< Clock RTC Div 32 */
+ CLK_RTCCLKDiv_64 = (uint8_t)0xC0 /*!< Clock RTC Div 64 */
+} CLK_RTCCLKDiv_TypeDef;
+
+#define IS_CLK_CLOCK_RTC_DIV(DIV) (((DIV) == CLK_RTCCLKDiv_1) ||\
+ ((DIV) == CLK_RTCCLKDiv_2) ||\
+ ((DIV) == CLK_RTCCLKDiv_4) ||\
+ ((DIV) == CLK_RTCCLKDiv_8) ||\
+ ((DIV) == CLK_RTCCLKDiv_16) ||\
+ ((DIV) == CLK_RTCCLKDiv_32) ||\
+ ((DIV) == CLK_RTCCLKDiv_64))
+/**
+ * @}
+ */
+
+/** @defgroup CLK_Peripherals
+ * @{
+ */
+/* Elements values convention: 0xXY
+ X = choice between the peripheral registers
+ X = 0 : PCKENR1
+ X = 1 : PCKENR2
+ X = 2 : PCKENR3
+ Y = Peripheral position in the register
+ */
+typedef enum {
+ CLK_Peripheral_TIM2 = (uint8_t)0x00, /*!< Peripheral Clock Enable 1, TIM2 */
+ CLK_Peripheral_TIM3 = (uint8_t)0x01, /*!< Peripheral Clock Enable 1, TIM3 */
+ CLK_Peripheral_TIM4 = (uint8_t)0x02, /*!< Peripheral Clock Enable 1, TIM4 */
+ CLK_Peripheral_I2C1 = (uint8_t)0x03, /*!< Peripheral Clock Enable 1, I2C1 */
+ CLK_Peripheral_SPI1 = (uint8_t)0x04, /*!< Peripheral Clock Enable 1, SPI1 */
+ CLK_Peripheral_USART1 = (uint8_t)0x05, /*!< Peripheral Clock Enable 1, USART1 */
+ CLK_Peripheral_BEEP = (uint8_t)0x06, /*!< Peripheral Clock Enable 1, BEEP */
+ CLK_Peripheral_DAC = (uint8_t)0x07, /*!< Peripheral Clock Enable 1, DAC */
+ CLK_Peripheral_ADC1 = (uint8_t)0x10, /*!< Peripheral Clock Enable 2, ADC1 */
+ CLK_Peripheral_TIM1 = (uint8_t)0x11, /*!< Peripheral Clock Enable 2, TIM1 */
+ CLK_Peripheral_RTC = (uint8_t)0x12, /*!< Peripheral Clock Enable 2, RTC */
+ CLK_Peripheral_LCD = (uint8_t)0x13, /*!< Peripheral Clock Enable 2, LCD */
+ CLK_Peripheral_DMA1 = (uint8_t)0x14, /*!< Peripheral Clock Enable 2, DMA1 */
+ CLK_Peripheral_COMP = (uint8_t)0x15, /*!< Peripheral Clock Enable 2, COMP1 and COMP2 */
+ CLK_Peripheral_BOOTROM = (uint8_t)0x17,/*!< Peripheral Clock Enable 2, Boot ROM */
+ CLK_Peripheral_AES = (uint8_t)0x20, /*!< Peripheral Clock Enable 3, AES */
+ CLK_Peripheral_TIM5 = (uint8_t)0x21, /*!< Peripheral Clock Enable 3, TIM5 */
+ CLK_Peripheral_SPI2 = (uint8_t)0x22, /*!< Peripheral Clock Enable 3, SPI2 */
+ CLK_Peripheral_USART2 = (uint8_t)0x23, /*!< Peripheral Clock Enable 3, USART2 */
+ CLK_Peripheral_USART3 = (uint8_t)0x24, /*!< Peripheral Clock Enable 3, USART3 */
+ CLK_Peripheral_CSSLSE = (uint8_t)0x25 /*!< Peripheral Clock Enable 3, CSS on LSE */
+} CLK_Peripheral_TypeDef;
+
+#define IS_CLK_PERIPHERAL(PERIPHERAL) (((PERIPHERAL) == CLK_Peripheral_DAC) ||\
+ ((PERIPHERAL) == CLK_Peripheral_ADC1) ||\
+ ((PERIPHERAL) == CLK_Peripheral_DMA1) ||\
+ ((PERIPHERAL) == CLK_Peripheral_RTC) ||\
+ ((PERIPHERAL) == CLK_Peripheral_LCD) ||\
+ ((PERIPHERAL) == CLK_Peripheral_COMP) ||\
+ ((PERIPHERAL) == CLK_Peripheral_TIM1) ||\
+ ((PERIPHERAL) == CLK_Peripheral_USART1) ||\
+ ((PERIPHERAL) == CLK_Peripheral_SPI1) ||\
+ ((PERIPHERAL) == CLK_Peripheral_I2C1) ||\
+ ((PERIPHERAL) == CLK_Peripheral_TIM4) ||\
+ ((PERIPHERAL) == CLK_Peripheral_TIM3) ||\
+ ((PERIPHERAL) == CLK_Peripheral_BEEP) ||\
+ ((PERIPHERAL) == CLK_Peripheral_BOOTROM) ||\
+ ((PERIPHERAL) == CLK_Peripheral_AES) ||\
+ ((PERIPHERAL) == CLK_Peripheral_TIM5) ||\
+ ((PERIPHERAL) == CLK_Peripheral_SPI2) ||\
+ ((PERIPHERAL) == CLK_Peripheral_USART2) ||\
+ ((PERIPHERAL) == CLK_Peripheral_USART3) ||\
+ ((PERIPHERAL) == CLK_Peripheral_CSSLSE) ||\
+ ((PERIPHERAL) == CLK_Peripheral_TIM2))
+/**
+ * @}
+ */
+
+/** @defgroup CLK_System_Clock_Divider
+ * @{
+ */
+typedef enum {
+ CLK_SYSCLKDiv_1 = (uint8_t)0x00, /*!< System Clock Divider: 1 */
+ CLK_SYSCLKDiv_2 = (uint8_t)0x01, /*!< System Clock Divider: 2 */
+ CLK_SYSCLKDiv_4 = (uint8_t)0x02, /*!< System Clock Divider: 4 */
+ CLK_SYSCLKDiv_8 = (uint8_t)0x03, /*!< System Clock Divider: 8 */
+ CLK_SYSCLKDiv_16 = (uint8_t)0x04, /*!< System Clock Divider: 16 */
+ CLK_SYSCLKDiv_32 = (uint8_t)0x05, /*!< System Clock Divider: 32 */
+ CLK_SYSCLKDiv_64 = (uint8_t)0x06, /*!< System Clock Divider: 64 */
+ CLK_SYSCLKDiv_128 = (uint8_t)0x07 /*!< System Clock Divider: 128 */
+} CLK_SYSCLKDiv_TypeDef;
+
+#define IS_CLK_SYSTEM_DIVIDER(DIV) (((DIV) == CLK_SYSCLKDiv_1) ||\
+ ((DIV) == CLK_SYSCLKDiv_2) ||\
+ ((DIV) == CLK_SYSCLKDiv_4) ||\
+ ((DIV) == CLK_SYSCLKDiv_8) ||\
+ ((DIV) == CLK_SYSCLKDiv_16) ||\
+ ((DIV) == CLK_SYSCLKDiv_32) ||\
+ ((DIV) == CLK_SYSCLKDiv_64) ||\
+ ((DIV) == CLK_SYSCLKDiv_128))
+/**
+ * @}
+ */
+
+/** @defgroup CLK_Flags
+ * @{
+ */
+/* Elements values convention: 0xXY
+ X = choice between the register's flags
+ X = 0 : CLK_CRTCR
+ X = 1 : CLK_ICKCR
+ X = 2 : CLK_CCOR
+ X = 3 : CLK_ECKCR
+ X = 4 : CLK_SWCR
+ X = 5 : CLK_CSSR
+ X = 6 : CLK_CBEEPR
+ X = 7 : CLK_REGCSRR
+ X = 8 : CSSLSE_CSR
+ Y = flag position in the register
+*/
+typedef enum {
+ CLK_FLAG_RTCSWBSY = (uint8_t)0x00, /*!< RTC clock busy in switch Flag */
+ CLK_FLAG_HSIRDY = (uint8_t)0x11, /*!< High speed internal oscillator ready Flag */
+ CLK_FLAG_LSIRDY = (uint8_t)0x13, /*!< Low speed internal oscillator ready Flag */
+ CLK_FLAG_CCOBSY = (uint8_t)0x20, /*!< Configurable clock output busy */
+ CLK_FLAG_HSERDY = (uint8_t)0x31, /*!< High speed external oscillator ready Flag */
+ CLK_FLAG_LSERDY = (uint8_t)0x33, /*!< Low speed external oscillator ready Flag */
+ CLK_FLAG_SWBSY = (uint8_t)0x40, /*!< Switch busy Flag */
+ CLK_FLAG_AUX = (uint8_t)0x51, /*!< Auxiliary oscillator connected to master clock */
+ CLK_FLAG_CSSD = (uint8_t)0x53, /*!< Clock security system detection Flag */
+ CLK_FLAG_BEEPSWBSY = (uint8_t)0x60, /*!< BEEP clock busy in switch Flag*/
+ CLK_FLAG_EEREADY = (uint8_t)0x77, /*!< Flash program memory and Data EEPROM ready Flag */
+ CLK_FLAG_EEBUSY = (uint8_t)0x76, /*!< Flash program memory and Data EEPROM busy Flag */
+ CLK_FLAG_LSEPD = (uint8_t)0x75, /*!< LSE power-down Flag */
+ CLK_FLAG_HSEPD = (uint8_t)0x74, /*!< HSE power-down Flag */
+ CLK_FLAG_LSIPD = (uint8_t)0x73, /*!< LSI power-down Flag */
+ CLK_FLAG_HSIPD = (uint8_t)0x72, /*!< HSI power-down Flag */
+ CLK_FLAG_REGREADY = (uint8_t)0x70, /*!< REGREADY Flag */
+ CLK_FLAG_LSECSSF = (uint8_t)0x83, /*!< CSS on LSE detection Flag */
+ CLK_FLAG_RTCCLKSWF = (uint8_t)0x84 /*!< RTCCLK switch completed flag on LSE failure */
+}CLK_FLAG_TypeDef;
+
+#define IS_CLK_FLAGS(FLAG) (((FLAG) == CLK_FLAG_LSIRDY) ||\
+ ((FLAG) == CLK_FLAG_HSIRDY) ||\
+ ((FLAG) == CLK_FLAG_HSERDY) ||\
+ ((FLAG) == CLK_FLAG_SWBSY) ||\
+ ((FLAG) == CLK_FLAG_CSSD) ||\
+ ((FLAG) == CLK_FLAG_AUX) ||\
+ ((FLAG) == CLK_FLAG_LSERDY) ||\
+ ((FLAG) == CLK_FLAG_CCOBSY) ||\
+ ((FLAG) == CLK_FLAG_RTCSWBSY) ||\
+ ((FLAG) == CLK_FLAG_EEREADY) ||\
+ ((FLAG) == CLK_FLAG_EEBUSY) ||\
+ ((FLAG) == CLK_FLAG_LSEPD) ||\
+ ((FLAG) == CLK_FLAG_LSIPD) ||\
+ ((FLAG) == CLK_FLAG_HSEPD) ||\
+ ((FLAG) == CLK_FLAG_HSIPD) ||\
+ ((FLAG) == CLK_FLAG_REGREADY) ||\
+ ((FLAG) == CLK_FLAG_BEEPSWBSY)||\
+ ((FLAG) == CLK_FLAG_LSECSSF)||\
+ ((FLAG) == CLK_FLAG_RTCCLKSWF))
+/**
+ * @}
+ */
+
+/** @defgroup CLK_Interrupts
+ * @{
+ */
+typedef enum {
+ CLK_IT_CSSD = (uint8_t)0x0C, /*!< Clock security system detection Flag */
+ CLK_IT_SWIF = (uint8_t)0x1C, /*!< Clock switch interrupt Flag */
+ CLK_IT_LSECSSF = (uint8_t)0x2C /*!< LSE Clock security system detection Interrupt */
+}CLK_IT_TypeDef;
+#define IS_CLK_IT(IT) (((IT) == CLK_IT_CSSD) ||\
+ ((IT) == CLK_IT_SWIF) ||\
+ ((IT) == CLK_IT_LSECSSF))
+
+#define IS_CLK_CLEAR_IT(IT) (((IT) == CLK_IT_SWIF)||\
+ ((IT) == CLK_IT_LSECSSF))
+/**
+ * @}
+ */
+
+/** @defgroup CLK_Halt_Configuration
+ * @{
+ */
+typedef enum {
+ CLK_Halt_BEEPRunning = (uint8_t)0x40, /*!< BEEP clock Halt/Active-halt mode */
+ CLK_Halt_FastWakeup = (uint8_t)0x20, /*!< Fast wakeup from Halt/Active-halt modes */
+ CLK_Halt_SlowWakeup = (uint8_t)0x10 /*!< Slow Active-halt mode */
+}
+CLK_Halt_TypeDef;
+
+#define IS_CLK_HALT(HALT) (((HALT) == CLK_Halt_BEEPRunning) ||\
+ ((HALT) == CLK_Halt_FastWakeup) ||\
+ ((HALT) == CLK_Halt_SlowWakeup))
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+/* Function used to set the CLK configuration to the default reset state ******/
+void CLK_DeInit(void);
+
+/* Internal/external clocks, CSS and CCO configuration functions **************/
+void CLK_HSICmd(FunctionalState NewState);
+void CLK_AdjustHSICalibrationValue(uint8_t CLK_HSICalibrationValue);
+void CLK_LSICmd(FunctionalState NewState);
+void CLK_HSEConfig(CLK_HSE_TypeDef CLK_HSE);
+void CLK_LSEConfig(CLK_LSE_TypeDef CLK_LSE);
+void CLK_ClockSecuritySystemEnable(void);
+void CLK_ClockSecuritySytemDeglitchCmd(FunctionalState NewState);
+void CLK_CCOConfig(CLK_CCOSource_TypeDef CLK_CCOSource, CLK_CCODiv_TypeDef CLK_CCODiv);
+
+/* System clocks configuration functions ******************/
+void CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_TypeDef CLK_SYSCLKSource);
+CLK_SYSCLKSource_TypeDef CLK_GetSYSCLKSource(void);
+uint32_t CLK_GetClockFreq(void);
+void CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_TypeDef CLK_SYSCLKDiv);
+void CLK_SYSCLKSourceSwitchCmd(FunctionalState NewState);
+
+/* Peripheral clocks configuration functions **********************************/
+void CLK_RTCClockConfig(CLK_RTCCLKSource_TypeDef CLK_RTCCLKSource, CLK_RTCCLKDiv_TypeDef CLK_RTCCLKDiv);
+void CLK_BEEPClockConfig(CLK_BEEPCLKSource_TypeDef CLK_BEEPCLKSource);
+void CLK_PeripheralClockConfig(CLK_Peripheral_TypeDef CLK_Peripheral, FunctionalState NewState);
+
+/* CSS on LSE configuration functions *****************************************/
+void CLK_LSEClockSecuritySystemEnable(void);
+void CLK_RTCCLKSwitchOnLSEFailureEnable(void);
+
+/* Low power clock configuration functions ************************************/
+void CLK_HaltConfig(CLK_Halt_TypeDef CLK_Halt, FunctionalState NewState);
+void CLK_MainRegulatorCmd(FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void CLK_ITConfig(CLK_IT_TypeDef CLK_IT, FunctionalState NewState);
+FlagStatus CLK_GetFlagStatus(CLK_FLAG_TypeDef CLK_FLAG);
+void CLK_ClearFlag(void);
+ITStatus CLK_GetITStatus(CLK_IT_TypeDef CLK_IT);
+void CLK_ClearITPendingBit(CLK_IT_TypeDef CLK_IT);
+
+
+#endif /* __STM8L15x_CLK_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_comp.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_comp.h
new file mode 100644
index 00000000..5e343887
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_comp.h
@@ -0,0 +1,242 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_comp.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the COMP firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_COMP_H
+#define __STM8L15x_COMP_H
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup COMP
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup COMP_Exported_Types
+ * @{
+ */
+
+/** @defgroup COMP_Selection
+ * @{
+ */
+typedef enum
+{
+ COMP_Selection_COMP1 = ((uint8_t)0x01), /*!< Selection of Comparator 1. */
+ COMP_Selection_COMP2 = ((uint8_t)0x02) /*!< Selection of Comparator 2. */
+}COMP_Selection_TypeDef;
+
+#define IS_COMP_ALL_PERIPH(PERIPH) (((PERIPH) == COMP_Selection_COMP1) || \
+ ((PERIPH) == COMP_Selection_COMP2))
+/**
+ * @}
+ */
+
+/** @defgroup COMP_Edge
+ * @{
+ */
+typedef enum
+{
+ COMP_Edge_Falling = ((uint8_t)0x01), /*!< Falling edge selection. */
+ COMP_Edge_Rising = ((uint8_t)0x02), /*!< Rising edge selection. */
+ COMP_Edge_Rising_Falling = ((uint8_t)0x03) /*!< Rising and Falling edge selection. */
+}COMP_Edge_TypeDef;
+
+#define IS_COMP_EDGE(EDGE) (((EDGE) == COMP_Edge_Falling) || \
+ ((EDGE) == COMP_Edge_Rising) || \
+ ((EDGE) == COMP_Edge_Rising_Falling))
+/**
+ * @}
+ */
+
+/** @defgroup COMP_Inverting_Input_Selection
+ * @{
+ */
+typedef enum
+{
+ COMP_InvertingInput_IO = ((uint8_t)0x08), /*!< Input/Output on comparator inverting input enable.*/
+ COMP_InvertingInput_VREFINT = ((uint8_t)0x10), /*!< VREFINT on comparator inverting input enable. */
+ COMP_InvertingInput_3_4VREFINT = ((uint8_t)0x18), /*!< 3/4 VREFINT on comparator inverting input enable. */
+ COMP_InvertingInput_1_2VREFINT = ((uint8_t)0x20), /*!< 1/2 VREFINT on comparator inverting input enable. */
+ COMP_InvertingInput_1_4VREFINT = ((uint8_t)0x28), /*!< 1/4 VREFINT on comparator inverting input enable. */
+ COMP_InvertingInput_DAC1 = ((uint8_t)0x30), /*!< DAC1 output on comparator inverting input enable. */
+ COMP_InvertingInput_DAC2 = ((uint8_t)0x38) /*!< DAC2 output on comparator inverting input enable. */
+}COMP_InvertingInput_Typedef;
+
+#define IS_COMP_INVERTING_INPUT(INPUT) (((INPUT) == COMP_InvertingInput_IO) || \
+ ((INPUT) == COMP_InvertingInput_VREFINT) || \
+ ((INPUT) == COMP_InvertingInput_3_4VREFINT) || \
+ ((INPUT) == COMP_InvertingInput_1_2VREFINT) || \
+ ((INPUT) == COMP_InvertingInput_1_4VREFINT) || \
+ ((INPUT) == COMP_InvertingInput_DAC1) || \
+ ((INPUT) == COMP_InvertingInput_DAC2))
+/**
+ * @}
+ */
+
+/** @defgroup COMP2_Output_Selection
+ * @{
+ */
+typedef enum
+{
+ COMP_OutputSelect_TIM2IC2 = ((uint8_t)0x00), /*!< COMP2 output connected to TIM2 Input Capture 2 */
+ COMP_OutputSelect_TIM3IC2 = ((uint8_t)0x40), /*!< COMP2 output connected to TIM3 Input Capture 2 */
+ COMP_OutputSelect_TIM1BRK = ((uint8_t)0x80), /*!< COMP2 output connected to TIM1 Break Input */
+ COMP_OutputSelect_TIM1OCREFCLR = ((uint8_t)0xC0) /*!< COMP2 output connected to TIM1 OCREF Clear */
+}COMP_OutputSelect_Typedef;
+
+#define IS_COMP_OUTPUT(OUTPUT) (((OUTPUT) == COMP_OutputSelect_TIM2IC2) || \
+ ((OUTPUT) == COMP_OutputSelect_TIM3IC2) || \
+ ((OUTPUT) == COMP_OutputSelect_TIM1BRK) || \
+ ((OUTPUT) == COMP_OutputSelect_TIM1OCREFCLR))
+/**
+ * @}
+ */
+
+/** @defgroup COMP_Speed
+ * @{
+ */
+typedef enum
+{
+ COMP_Speed_Slow = ((uint8_t)0x00), /*!< Comparator speed: slow */
+ COMP_Speed_Fast = ((uint8_t)0x04) /*!< Comparator speed: fast */
+}COMP_Speed_TypeDef;
+
+#define IS_COMP_SPEED(SPEED) (((SPEED) == COMP_Speed_Slow) || \
+ ((SPEED) == COMP_Speed_Fast))
+/**
+ * @}
+ */
+
+/** @defgroup COMP_Trigger_Group
+ * @{
+ */
+typedef enum
+{
+ COMP_TriggerGroup_InvertingInput = ((uint8_t)0x01), /*!< Trigger on comparator 2 inverting input */
+ COMP_TriggerGroup_NonInvertingInput = ((uint8_t)0x02), /*!< Trigger on comparator 2 non inverting input */
+ COMP_TriggerGroup_VREFINTOutput = ((uint8_t)0x03), /*!< Trigger on VREFINT output */
+ COMP_TriggerGroup_DACOutput = ((uint8_t)0x04) /*!< Trigger on DAC output */
+}COMP_TriggerGroup_TypeDef;
+
+#define IS_COMP_TRIGGERGROUP(TRIGGERGROUP) (((TRIGGERGROUP) == COMP_TriggerGroup_NonInvertingInput) || \
+ ((TRIGGERGROUP) == COMP_TriggerGroup_InvertingInput) || \
+ ((TRIGGERGROUP) == COMP_TriggerGroup_VREFINTOutput) || \
+ ((TRIGGERGROUP) == COMP_TriggerGroup_DACOutput)
+/**
+ * @}
+ */
+
+/** @defgroup COMP_Trigger_Pin
+ * @{
+ */
+typedef enum
+{
+ COMP_TriggerPin_0 = ((uint8_t)0x01), /*!< PE5 for the non inverting input Trigger Group
+ PC3 for the inverting input Trigger Group
+ PB6 for the DAC output Trigger Group
+ PC2 for the VREFINT output Trigger Group
+ */
+ COMP_TriggerPin_1 = ((uint8_t)0x02), /*!< PD0 for the non inverting input Trigger Group
+ PC4 for the inverting input Trigger Group
+ PB5 for the DAC output Trigger Group
+ PD7 for the VREFINT output Trigger Group
+ */
+ COMP_TriggerPin_2 = ((uint8_t)0x04) /*!< PD1 for the non inverting input Trigger Group
+ PC7 for the inverting input Trigger Group
+ PB4 for the DAC output Trigger Group
+ PD6 for the VREFINT output Trigger Group */
+}COMP_TriggerPin_TypeDef;
+
+#define IS_COMP_TRIGGERPIN(TRIGGERPIN) ((((uint8_t)(TRIGGERPIN) & (uint8_t)0xF8) == (uint8_t) 0x00) && \
+ ((TRIGGERPIN) != (uint8_t)0x00))
+/**
+ * @}
+ */
+
+/** @defgroup COMP_Output_Level
+ * @{
+ */
+typedef enum
+{
+ COMP_OutputLevel_Low = ((uint8_t)0x00), /*!< Comparator output level is low */
+ COMP_OutputLevel_High = ((uint8_t)0x01) /*!< Comparator output level is high */
+}COMP_OutputLevel_TypeDef;
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/* Function used to set the CLK configuration to the default reset state ******/
+void COMP_DeInit(void);
+/* Initialization and Configuration functions ****************************/
+void COMP_Init(COMP_InvertingInput_Typedef COMP_InvertingInput, COMP_OutputSelect_Typedef COMP_OutputSelect,
+ COMP_Speed_TypeDef COMP_Speed);
+void COMP_VrefintToCOMP1Connect(FunctionalState NewState);
+void COMP_EdgeConfig(COMP_Selection_TypeDef COMP_Selection, COMP_Edge_TypeDef COMP_Edge);
+COMP_OutputLevel_TypeDef COMP_GetOutputLevel(COMP_Selection_TypeDef COMP_Selection);
+/* Window mode control function ***********************************************/
+void COMP_WindowCmd(FunctionalState NewState);
+/* Internal Reference Voltage (VREFINT) output function ***********************/
+void COMP_VrefintOutputCmd(FunctionalState NewState);
+/* Comparator channels trigger configuration functions ************************/
+void COMP_SchmittTriggerCmd(FunctionalState NewState);
+void COMP_TriggerConfig(COMP_TriggerGroup_TypeDef COMP_TriggerGroup,
+ COMP_TriggerPin_TypeDef COMP_TriggerPin,
+ FunctionalState NewState);
+/* Interrupts and flags management functions **********************************/
+void COMP_ITConfig(COMP_Selection_TypeDef COMP_Selection, FunctionalState NewState);
+FlagStatus COMP_GetFlagStatus(COMP_Selection_TypeDef COMP_Selection);
+void COMP_ClearFlag(COMP_Selection_TypeDef COMP_Selection);
+ITStatus COMP_GetITStatus(COMP_Selection_TypeDef COMP_Selection);
+void COMP_ClearITPendingBit(COMP_Selection_TypeDef COMP_Selection);
+
+/**
+ * @}
+ */
+
+#endif /* __STM8L15x_COMP_H */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_dac.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_dac.h
new file mode 100644
index 00000000..951a8030
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_dac.h
@@ -0,0 +1,293 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_dac.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the DAC firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_DAC_H
+#define __STM8L15x_DAC_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup DAC
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup DAC_Exported_types
+ * @{
+ */
+
+/** @defgroup DAC_trigger_selection
+ * @{
+ */
+typedef enum
+{
+ DAC_Trigger_None = ((uint8_t)0x30), /*!< DAC trigger None */
+ DAC_Trigger_T4_TRGO = ((uint8_t)0x00), /*!< DAC trigger TIM4 TRGO */
+ DAC_Trigger_T5_TRGO = ((uint8_t)0x08), /*!< DAC trigger TIM5 TRGO */
+ DAC_Trigger_Ext = ((uint8_t)0x10), /*!< DAC trigger External Trigger (PE4) */
+ DAC_Trigger_Software = ((uint8_t)0x38) /*!< DAC trigger software */
+}DAC_Trigger_TypeDef;
+
+#define IS_DAC_TRIGGER(TRIGGER) (((TRIGGER) == DAC_Trigger_None) || \
+ ((TRIGGER) == DAC_Trigger_T4_TRGO) || \
+ ((TRIGGER) == DAC_Trigger_T5_TRGO) || \
+ ((TRIGGER) == DAC_Trigger_Ext) || \
+ ((TRIGGER) == DAC_Trigger_Software))
+/**
+ * @}
+ */
+
+/** @defgroup DAC_data_alignment
+ * @{
+ */
+typedef enum
+{
+ DAC_Align_12b_R = ((uint8_t)0x00), /*!< DAC alignment Right 12bit */
+ DAC_Align_12b_L = ((uint8_t)0x04), /*!< DAC alignment Left 12bit */
+ DAC_Align_8b_R = ((uint8_t)0x08) /*!< DAC alignment Right 8bit */
+}DAC_Align_TypeDef;
+
+#define IS_DAC_ALIGN(ALIGN) (((ALIGN) == DAC_Align_12b_R) || \
+ ((ALIGN) == DAC_Align_12b_L) || \
+ ((ALIGN) == DAC_Align_8b_R))
+/**
+ * @}
+ */
+
+/** @defgroup DAC_Channel_selection
+ * @{
+ */
+typedef enum
+{
+ DAC_Channel_1 = ((uint8_t)0x00), /*!< DAC Channel 1 selection */
+ DAC_Channel_2 = ((uint8_t)0x01) /*!< DAC Channel 2 selection */
+}DAC_Channel_TypeDef;
+
+#define IS_DAC_CHANNEL(CHANNEL) (((CHANNEL) == DAC_Channel_1) || \
+ ((CHANNEL) == DAC_Channel_2))
+
+/**
+ * @}
+ */
+
+/** @defgroup DAC_wave_generation
+ * @{
+ */
+
+typedef enum
+{
+ DAC_Wave_Noise = ((uint8_t)0x40), /*!< Noise Wave Generation */
+ DAC_Wave_Triangle = ((uint8_t)0x80) /*!< Triangle Wave Generation */
+}DAC_Wave_TypeDef;
+
+#define IS_DAC_WAVE(WAVE) (((WAVE) == DAC_Wave_Noise) || \
+ ((WAVE) == DAC_Wave_Triangle))
+/**
+ * @}
+ */
+
+/** @defgroup DAC_output_buffer
+ * @{
+ */
+typedef enum
+{
+ DAC_OutputBuffer_Enable = ((uint8_t)0x00), /*!< DAC output buffer Enabled */
+ DAC_OutputBuffer_Disable = ((uint8_t)0x02) /*!< DAC output buffer Disabled */
+}DAC_OutputBuffer_TypeDef;
+
+#define IS_DAC_OUTPUT_BUFFER_STATE(STATE) (((STATE) == DAC_OutputBuffer_Enable) || \
+ ((STATE) == DAC_OutputBuffer_Disable))
+/**
+ * @}
+ */
+
+/** @defgroup DAC_interrupts_definition
+ * @{
+ */
+typedef enum
+{
+ DAC_IT_DMAUDR = ((uint8_t)0x20) /*!< DMA Underrun Interrupt */
+}DAC_IT_TypeDef;
+
+#define IS_DAC_IT(IT) (((IT) == DAC_IT_DMAUDR))
+/**
+ * @}
+ */
+
+/** @defgroup DAC_flags_definition
+ * @{
+ */
+typedef enum
+{
+ DAC_FLAG_DMAUDR = ((uint8_t)0x01) /*!< DMA Underrun flag */
+}DAC_FLAG_TypeDef;
+
+#define IS_DAC_GET_FLAG(FLAG) (((FLAG) == DAC_FLAG_DMAUDR))
+#define IS_DAC_FLAG(FLAG) (((FLAG) == DAC_FLAG_DMAUDR))
+
+/**
+ * @}
+ */
+
+/** @defgroup DAC_lfsrunmask
+ * @{
+ */
+
+typedef enum
+{
+ DAC_LFSRUnmask_Bit0 = ((uint8_t)0x00), /*!< Noise LFSR Unmask 1 LSB */
+ DAC_LFSRUnmask_Bits1_0 = ((uint8_t)0x01), /*!< Noise LFSR Unmask 2 LSB */
+ DAC_LFSRUnmask_Bits2_0 = ((uint8_t)0x02), /*!< Noise LFSR Unmask 3 LSB */
+ DAC_LFSRUnmask_Bits3_0 = ((uint8_t)0x03), /*!< Noise LFSR Unmask 4 LSB */
+ DAC_LFSRUnmask_Bits4_0 = ((uint8_t)0x04), /*!< Noise LFSR Unmask 5 LSB */
+ DAC_LFSRUnmask_Bits5_0 = ((uint8_t)0x05), /*!< Noise LFSR Unmask 6 LSB */
+ DAC_LFSRUnmask_Bits6_0 = ((uint8_t)0x06), /*!< Noise LFSR Unmask 7 LSB */
+ DAC_LFSRUnmask_Bits7_0 = ((uint8_t)0x07), /*!< Noise LFSR Unmask 8 LSB */
+ DAC_LFSRUnmask_Bits8_0 = ((uint8_t)0x08), /*!< Noise LFSR Unmask 9 LSB */
+ DAC_LFSRUnmask_Bits9_0 = ((uint8_t)0x09), /*!< Noise LFSR Unmask 10 LSB */
+ DAC_LFSRUnmask_Bits10_0 = ((uint8_t)0x0A), /*!< Noise LFSR Unmask 11 LSB */
+ DAC_LFSRUnmask_Bits11_0 = ((uint8_t)0x0B) /*!< Noise LFSR Unmask 12 LSB */
+}DAC_LFSRUnmask_TypeDef;
+
+#define IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(VALUE) ((VALUE) <= 0x0F)
+/**
+ * @}
+ */
+
+/** @defgroup DAC_triangleamplitude
+ * @{
+ */
+typedef enum
+{
+ DAC_TriangleAmplitude_1 = ((uint8_t)0x00), /*!< Triangle Amplitude = Vref.(1/4096)*/
+ DAC_TriangleAmplitude_3 = ((uint8_t)0x01), /*!< Triangle Amplitude = Vref.(3/4096)*/
+ DAC_TriangleAmplitude_7 = ((uint8_t)0x02), /*!< Triangle Amplitude = Vref.(7/4096)*/
+ DAC_TriangleAmplitude_15 = ((uint8_t)0x03), /*!< Triangle Amplitude = Vref.(15/4096)*/
+ DAC_TriangleAmplitude_31 = ((uint8_t)0x04), /*!< Triangle Amplitude = Vref.(31/4096)*/
+ DAC_TriangleAmplitude_63 = ((uint8_t)0x05), /*!< Triangle Amplitude = Vref.(63/4096)*/
+ DAC_TriangleAmplitude_127 = ((uint8_t)0x06), /*!< Triangle Amplitude = Vref.(127/4096)*/
+ DAC_TriangleAmplitude_255 = ((uint8_t)0x07), /*!< Triangle Amplitude = Vref.(255/4096)*/
+ DAC_TriangleAmplitude_511 = ((uint8_t)0x08), /*!< Triangle Amplitude = Vref.(511/4096)*/
+ DAC_TriangleAmplitude_1023 = ((uint8_t)0x09), /*!< Triangle Amplitude = Vref.(1023/4096)*/
+ DAC_TriangleAmplitude_2047 = ((uint8_t)0x0A), /*!< Triangle Amplitude = Vref.(2047/4096)*/
+ DAC_TriangleAmplitude_4095 = ((uint8_t)0x0B) /*!< Triangle Amplitude = Vref.(4095/4096)*/
+}DAC_TriangleAmplitude_TypeDef;
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/* Exported constants --------------------------------------------------------*/
+/** @defgroup DAC_Exported_Constants
+ * @{
+ */
+
+/** @defgroup DAC_data
+ * @{
+ */
+#define IS_DAC_DATA_08R(DATA) ((DATA) <= 0x00FF)
+
+/**
+ * @}
+ */
+/** @defgroup DAC_Registers_Offset
+ * @{
+ */
+#define CR1_Offset ((uint8_t)0x00)
+#define CR2_Offset ((uint8_t)0x01)
+#define DCH1RDHRH_Offset ((uint8_t)0x20)
+#define CH1RDHRH_Offset ((uint8_t)0x08)
+#define CH2RDHRH_Offset ((uint8_t)0x14)
+/**
+ * @}
+ */
+
+/** @defgroup DAC_legacy
+ * @{
+ */
+#define DAC_TriangleWaveAmplitude DAC_SetTriangleWaveAmplitude
+#define DAC_NoiseWaveLFSR DAC_SetNoiseWaveLFSR
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+/* Function used to set the DAC configuration to the default reset state *****/
+void DAC_DeInit(void);
+
+/* DAC channels configuration: trigger, output buffer, data format functions */
+void DAC_Init(DAC_Channel_TypeDef DAC_Channel,
+ DAC_Trigger_TypeDef DAC_Trigger,
+ DAC_OutputBuffer_TypeDef DAC_OutputBuffer);
+void DAC_Cmd(DAC_Channel_TypeDef DAC_Channel, FunctionalState NewState);
+void DAC_SoftwareTriggerCmd(DAC_Channel_TypeDef DAC_Channel, FunctionalState NewState);
+void DAC_DualSoftwareTriggerCmd(FunctionalState NewState);
+void DAC_WaveGenerationCmd(DAC_Channel_TypeDef DAC_Channel, DAC_Wave_TypeDef DAC_Wave, FunctionalState NewState);
+void DAC_SetNoiseWaveLFSR(DAC_Channel_TypeDef DAC_Channel, DAC_LFSRUnmask_TypeDef DAC_LFSRUnmask);
+void DAC_SetTriangleWaveAmplitude(DAC_Channel_TypeDef DAC_Channel, DAC_TriangleAmplitude_TypeDef DAC_TriangleAmplitude);
+void DAC_SetChannel1Data(DAC_Align_TypeDef DAC_Align, uint16_t DAC_Data);
+void DAC_SetChannel2Data(DAC_Align_TypeDef DAC_Align, uint16_t DAC_Data);
+void DAC_SetDualChannelData(DAC_Align_TypeDef DAC_Align, uint16_t DAC_Data2, uint16_t DAC_Data1);
+uint16_t DAC_GetDataOutputValue(DAC_Channel_TypeDef DAC_Channel);
+
+/* DMA management function ***************************************************/
+void DAC_DMACmd(DAC_Channel_TypeDef DAC_Channel, FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void DAC_ITConfig(DAC_Channel_TypeDef DAC_Channel, DAC_IT_TypeDef DAC_IT, FunctionalState NewState);
+FlagStatus DAC_GetFlagStatus(DAC_Channel_TypeDef DAC_Channel, DAC_FLAG_TypeDef DAC_FLAG);
+void DAC_ClearFlag(DAC_Channel_TypeDef DAC_Channel, DAC_FLAG_TypeDef DAC_FLAG);
+ITStatus DAC_GetITStatus(DAC_Channel_TypeDef DAC_Channel, DAC_IT_TypeDef DAC_IT);
+void DAC_ClearITPendingBit(DAC_Channel_TypeDef DAC_Channel, DAC_IT_TypeDef DAC_IT);
+
+#endif /*__STM8L15x_DAC_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_dma.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_dma.h
new file mode 100644
index 00000000..aa77ffe1
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_dma.h
@@ -0,0 +1,341 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_dma.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the DMA
+ * firmware library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_DMA_H
+ #define __STM8L15x_DMA_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup DMA
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @addtogroup DMA_Exported_Types
+ * @{
+ */
+
+/** @defgroup DMA_Data_Transfer_Direction
+ * @{
+ */
+typedef enum
+{
+ DMA_DIR_PeripheralToMemory = ((uint8_t)0x00), /*!< Data transfer direction is Peripheral To Memory */
+ DMA_DIR_MemoryToPeripheral = ((uint8_t)0x08), /*!< Data transfer direction is Memory To Peripheral */
+ DMA_DIR_Memory0ToMemory1 = ((uint8_t)0x40) /*!< Data transfer direction is Memory0 To Memory 1 */
+}DMA_DIR_TypeDef;
+
+#define IS_DMA_DIR(DIR) (((DIR) == DMA_DIR_MemoryToPeripheral) || \
+ ((DIR) == DMA_DIR_PeripheralToMemory) || \
+ ((DIR) == DMA_DIR_Memory0ToMemory1 ))
+/**
+ * @}
+ */
+
+/** @defgroup DMA_Mode
+ * @{
+ */
+typedef enum
+{
+ DMA_Mode_Normal = ((uint8_t)0x00), /*!< DMA normal buffer mode*/
+ DMA_Mode_Circular = ((uint8_t)0x10) /*!< DMA circular buffer mode */
+}DMA_Mode_TypeDef;
+
+#define IS_DMA_MODE(MODE) (((MODE) == DMA_Mode_Circular) || \
+ ((MODE) == DMA_Mode_Normal))
+/**
+ * @}
+ */
+
+/** @defgroup DMA_Incremented_Mode
+ * @{
+ */
+typedef enum
+{
+ DMA_MemoryIncMode_Dec = ((uint8_t)0x00), /*!< DMA memory incremented mode is decremental */
+ DMA_MemoryIncMode_Inc = ((uint8_t)0x20) /*!< DMA memory incremented mode is incremental */
+}DMA_MemoryIncMode_TypeDef;
+
+#define IS_DMA_MEMORY_INC_MODE(MODE) (((MODE) == DMA_MemoryIncMode_Inc) || \
+ ((MODE) == DMA_MemoryIncMode_Dec))
+/**
+ * @}
+ */
+
+/** @defgroup DMA_Priority
+ * @{
+ */
+typedef enum
+{
+ DMA_Priority_Low = ((uint8_t)0x00), /*!< Software Priority is Low */
+ DMA_Priority_Medium = ((uint8_t)0x10), /*!< Software Priority is Medium */
+ DMA_Priority_High = ((uint8_t)0x20), /*!< Software Priority is High */
+ DMA_Priority_VeryHigh = ((uint8_t)0x30) /*!< Software Priority is Very High*/
+}DMA_Priority_TypeDef;
+
+#define IS_DMA_PRIORITY(PRIORITY) (((PRIORITY) == DMA_Priority_VeryHigh) || \
+ ((PRIORITY) == DMA_Priority_High) || \
+ ((PRIORITY) == DMA_Priority_Medium) || \
+ ((PRIORITY) == DMA_Priority_Low))
+/**
+ * @}
+ */
+
+/** @defgroup DMA_Memory_Data_Size
+ * @{
+ */
+typedef enum
+{
+ DMA_MemoryDataSize_Byte = ((uint8_t)0x00),/*!< Memory Data Size is 1 Byte */
+ DMA_MemoryDataSize_HalfWord = ((uint8_t)0x08) /*!< Memory Data Size is 2 Bytes */
+}DMA_MemoryDataSize_TypeDef;
+
+#define IS_DMA_DATA_SIZE(SIZE) (((SIZE) == DMA_MemoryDataSize_Byte) || \
+ ((SIZE) == DMA_MemoryDataSize_HalfWord))
+/**
+ * @}
+ */
+
+/** @defgroup DMA_Flags
+ * @{
+ */
+typedef enum
+{
+ DMA1_FLAG_GB = ((uint16_t)0x0002), /*!< Global Busy Flag */
+
+ DMA1_FLAG_IFC0 = ((uint16_t)0x1001), /*!< Global Interrupt Flag Channel 0 */
+ DMA1_FLAG_IFC1 = ((uint16_t)0x1002), /*!< Global Interrupt Flag Channel 1 */
+ DMA1_FLAG_IFC2 = ((uint16_t)0x1004), /*!< Global Interrupt Flag Channel 2 */
+ DMA1_FLAG_IFC3 = ((uint16_t)0x1008), /*!< Global Interrupt Flag Channel 3 */
+
+ DMA1_FLAG_TC0 = ((uint16_t)0x0102), /*!< Transaction Complete Interrupt Flag Channel 0 */
+ DMA1_FLAG_TC1 = ((uint16_t)0x0202), /*!< Transaction Complete Interrupt Flag Channel 1 */
+ DMA1_FLAG_TC2 = ((uint16_t)0x0402), /*!< Transaction Complete Interrupt Flag Channel 2 */
+ DMA1_FLAG_TC3 = ((uint16_t)0x0802), /*!< Transaction Complete Interrupt Flag Channel 3 */
+
+ DMA1_FLAG_HT0 = ((uint16_t)0x0104), /*!< Half Transaction Interrupt Flag Channel 0 */
+ DMA1_FLAG_HT1 = ((uint16_t)0x0204), /*!< Half Transaction Interrupt Flag Channel 1 */
+ DMA1_FLAG_HT2 = ((uint16_t)0x0404), /*!< Half Transaction Interrupt Flag Channel 2 */
+ DMA1_FLAG_HT3 = ((uint16_t)0x0804), /*!< Half Transaction Interrupt Flag Channel 3 */
+
+ DMA1_FLAG_PEND0 = ((uint16_t)0x0140), /*!< DMA Request pending on Channel 0 */
+ DMA1_FLAG_PEND1 = ((uint16_t)0x0240), /*!< DMA Request pending on Channel 1 */
+ DMA1_FLAG_PEND2 = ((uint16_t)0x0440), /*!< DMA Request pending on Channel 2 */
+ DMA1_FLAG_PEND3 = ((uint16_t)0x0840), /*!< DMA Request pending on Channel 3 */
+
+ DMA1_FLAG_BUSY0 = ((uint16_t)0x0180), /*!< No DMA transfer on going in Channel 0 */
+ DMA1_FLAG_BUSY1 = ((uint16_t)0x0280), /*!< No DMA transfer on going in Channel 1 */
+ DMA1_FLAG_BUSY2 = ((uint16_t)0x0480), /*!< No DMA transfer on going in Channel 2 */
+ DMA1_FLAG_BUSY3 = ((uint16_t)0x0880) /*!< No DMA transfer on going in Channel 3 */
+}DMA_FLAG_TypeDef;
+
+#define IS_DMA_GET_FLAG(FLAG) (((FLAG) == DMA1_FLAG_GB) || \
+ ((FLAG) == DMA1_FLAG_IFC0) || \
+ ((FLAG) == DMA1_FLAG_IFC1) || \
+ ((FLAG) == DMA1_FLAG_IFC2) || \
+ ((FLAG) == DMA1_FLAG_IFC3) || \
+ ((FLAG) == DMA1_FLAG_TC0) || \
+ ((FLAG) == DMA1_FLAG_TC1) || \
+ ((FLAG) == DMA1_FLAG_TC2) || \
+ ((FLAG) == DMA1_FLAG_TC3) || \
+ ((FLAG) == DMA1_FLAG_HT0) || \
+ ((FLAG) == DMA1_FLAG_HT1) || \
+ ((FLAG) == DMA1_FLAG_HT2) || \
+ ((FLAG) == DMA1_FLAG_HT3) || \
+ ((FLAG) == DMA1_FLAG_PEND0) || \
+ ((FLAG) == DMA1_FLAG_PEND1) || \
+ ((FLAG) == DMA1_FLAG_PEND2) || \
+ ((FLAG) == DMA1_FLAG_PEND3) || \
+ ((FLAG) == DMA1_FLAG_BUSY0) || \
+ ((FLAG) == DMA1_FLAG_BUSY1) || \
+ ((FLAG) == DMA1_FLAG_BUSY2) || \
+ ((FLAG) == DMA1_FLAG_BUSY3))
+
+#define IS_DMA_CLEAR_FLAG(FLAG) (((FLAG) == DMA1_FLAG_TC0) || \
+ ((FLAG) == DMA1_FLAG_TC1) || \
+ ((FLAG) == DMA1_FLAG_TC2) || \
+ ((FLAG) == DMA1_FLAG_TC3) || \
+ ((FLAG) == DMA1_FLAG_HT0) || \
+ ((FLAG) == DMA1_FLAG_HT1) || \
+ ((FLAG) == DMA1_FLAG_HT2) || \
+ ((FLAG) == DMA1_FLAG_HT3) || \
+ ((FLAG) == (DMA1_FLAG_TC0 |DMA1_FLAG_HT0)) || \
+ ((FLAG) == (DMA1_FLAG_TC1 |DMA1_FLAG_HT1)) || \
+ ((FLAG) == (DMA1_FLAG_TC2 |DMA1_FLAG_HT2)) || \
+ ((FLAG) == (DMA1_FLAG_TC3 |DMA1_FLAG_HT3)))
+/**
+ * @}
+ */
+
+/** @defgroup DMA_One_Channel_Interrupts
+ * @{
+ */
+typedef enum
+{
+ DMA_ITx_TC = ((uint8_t)0x02),/*!< Transaction Complete Interrupt */
+ DMA_ITx_HT = ((uint8_t)0x04) /*!< Half Transaction Interrupt*/
+}DMA_ITx_TypeDef;
+
+#define IS_DMA_CONFIG_ITX(IT) ((((IT) & 0xF9) == 0x00) && ((IT) != 0x00))
+/**
+ * @}
+ */
+
+/** @defgroup DMA_Interrupts
+ * @{
+ */
+typedef enum
+{
+ /* Transaction Complete Interrupts*/
+ DMA1_IT_TC0 = ((uint8_t)0x12), /*!< Transaction Complete Interrupt Channel 0 */
+ DMA1_IT_TC1 = ((uint8_t)0x22), /*!< Transaction Complete Interrupt Channel 1 */
+ DMA1_IT_TC2 = ((uint8_t)0x42), /*!< Transaction Complete Interrupt Channel 2 */
+ DMA1_IT_TC3 = ((uint8_t)0x82), /*!< Transaction Complete Interrupt Channel 3 */
+ /* Half Transaction Interrupts */
+ DMA1_IT_HT0 = ((uint8_t)0x14), /*!< Half Transaction Interrupt Channel 0 */
+ DMA1_IT_HT1 = ((uint8_t)0x24), /*!< Half Transaction Interrupt Channel 1 */
+ DMA1_IT_HT2 = ((uint8_t)0x44), /*!< Half Transaction Interrupt Channel 2 */
+ DMA1_IT_HT3 = ((uint8_t)0x84) /*!< Half Transaction Interrupt Channel 3 */
+}DMA_IT_TypeDef;
+
+#define IS_DMA_CLEAR_IT(IT) (((IT) == DMA1_IT_TC0) || \
+ ((IT) == DMA1_IT_TC1) || \
+ ((IT) == DMA1_IT_TC2) || \
+ ((IT) == DMA1_IT_TC3) || \
+ ((IT) == DMA1_IT_HT0) || \
+ ((IT) == DMA1_IT_HT1) || \
+ ((IT) == DMA1_IT_HT2) || \
+ ((IT) == DMA1_IT_HT3) || \
+ ((IT) == (DMA1_IT_TC0|DMA1_IT_HT0)) || \
+ ((IT) == (DMA1_IT_TC1|DMA1_IT_HT1)) || \
+ ((IT) == (DMA1_IT_TC2|DMA1_IT_HT2)) || \
+ ((IT) == (DMA1_IT_TC3|DMA1_IT_HT3)))
+
+#define IS_DMA_GET_IT(IT)(((IT) == DMA1_IT_TC0) || \
+ ((IT) == DMA1_IT_TC1) || \
+ ((IT) == DMA1_IT_TC2) || \
+ ((IT) == DMA1_IT_TC3) || \
+ ((IT) == DMA1_IT_HT0) || \
+ ((IT) == DMA1_IT_HT1) || \
+ ((IT) == DMA1_IT_HT2) || \
+ ((IT) == DMA1_IT_HT3))
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/** @addtogroup DMA_Exported_Macros
+ * @{
+ */
+
+/** @defgroup DMA_Channels
+ * @{
+ */
+#define IS_DMA_CHANNEL(PERIPH) (((*(uint16_t*)&(PERIPH)) == DMA1_Channel0_BASE) || \
+ ((*(uint16_t*)&(PERIPH)) == DMA1_Channel1_BASE) || \
+ ((*(uint16_t*)&(PERIPH)) == DMA1_Channel2_BASE) || \
+ ((*(uint16_t*)&(PERIPH)) == DMA1_Channel3_BASE))
+/**
+ * @}
+ */
+
+
+/** @defgroup DMA_Buffer_Size
+ * @{
+ */
+#define IS_DMA_BUFFER_SIZE(SIZE) ((SIZE) > (uint8_t)0x0)
+
+/**
+ * @}
+ */
+
+/** @defgroup DMA_Timeout
+ * @{
+ */
+#define IS_DMA_TIMEOUT(TIME) ((TIME) < (uint8_t)0x40)
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+
+/* Functions used to set the DMA configuration to the default reset state ****/
+void DMA_GlobalDeInit(void);
+void DMA_DeInit(DMA_Channel_TypeDef* DMA_Channelx);
+
+/* Initialization and Configuration functions *********************************/
+void DMA_Init(DMA_Channel_TypeDef* DMA_Channelx,
+ uint32_t DMA_Memory0BaseAddr,
+ uint16_t DMA_PeripheralMemory1BaseAddr,
+ uint8_t DMA_BufferSize,
+ DMA_DIR_TypeDef DMA_DIR,
+ DMA_Mode_TypeDef DMA_Mode,
+ DMA_MemoryIncMode_TypeDef DMA_MemoryIncMode,
+ DMA_Priority_TypeDef DMA_Priority,
+ DMA_MemoryDataSize_TypeDef DMA_MemoryDataSize );
+void DMA_GlobalCmd(FunctionalState NewState);
+void DMA_Cmd(DMA_Channel_TypeDef* DMA_Channelx, FunctionalState NewState);
+void DMA_SetTimeOut(uint8_t DMA_TimeOut);
+
+/* Data Counter functions *****************************************************/
+void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMA_Channelx, uint8_t DataNumber);
+uint8_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMA_Channelx);
+
+/* Interrupts and flags management functions **********************************/
+void DMA_ITConfig(DMA_Channel_TypeDef* DMA_Channelx, DMA_ITx_TypeDef DMA_ITx, FunctionalState NewState);
+FlagStatus DMA_GetFlagStatus(DMA_FLAG_TypeDef DMA_FLAG);
+void DMA_ClearFlag(DMA_FLAG_TypeDef DMA_FLAG);
+ITStatus DMA_GetITStatus(DMA_IT_TypeDef DMA_IT);
+void DMA_ClearITPendingBit(DMA_IT_TypeDef DMA_IT);
+
+#endif /*__STM8L15x_DMA_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_exti.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_exti.h
new file mode 100644
index 00000000..bcb3fbe9
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_exti.h
@@ -0,0 +1,288 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_exti.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the EXTI firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_EXTI_H
+#define __STM8L15x_EXTI_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup EXTI
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @addtogroup EXTI_Exported_Types
+ * @{
+ */
+
+/** @defgroup EXTI_Trigger
+ * @{
+ */
+typedef enum
+{
+ EXTI_Trigger_Falling_Low = (uint8_t)0x00, /*!< Interrupt on Falling edge and Low level */
+ EXTI_Trigger_Rising = (uint8_t)0x01, /*!< Interrupt on Rising edge only */
+ EXTI_Trigger_Falling = (uint8_t)0x02, /*!< Interrupt on Falling edge only */
+ EXTI_Trigger_Rising_Falling = (uint8_t)0x03 /*!< Interrupt on Rising and Falling edges */
+} EXTI_Trigger_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup EXTI_Half_Port
+ *
+ * @brief EXTI halfPort possible values
+ * Values are coded as following:
+ * - Bit 7: 0 => the half port is in EXTI_CONF1 register
+ * 1 => the half port is in EXTI_CONF2 register
+ * - Bits[6:0] => the half port selection mask
+ * @{
+ */
+typedef enum
+{
+ EXTI_HalfPort_B_LSB = (uint8_t)0x01, /*!< Interrupt selector PB(3:0) */
+ EXTI_HalfPort_B_MSB = (uint8_t)0x02, /*!< Interrupt selector PB(7:4) */
+ EXTI_HalfPort_D_LSB = (uint8_t)0x04, /*!< Interrupt selector PD(3:0) */
+ EXTI_HalfPort_D_MSB = (uint8_t)0x08, /*!< Interrupt selector PD(7:4) */
+ EXTI_HalfPort_E_LSB = (uint8_t)0x10, /*!< Interrupt selector PE(3:0) */
+ EXTI_HalfPort_E_MSB = (uint8_t)0x20, /*!< Interrupt selector PE(7:4) */
+ EXTI_HalfPort_F_LSB = (uint8_t)0x40, /*!< Interrupt selector PF(3:0) */
+ EXTI_HalfPort_F_MSB = (uint8_t)0x81, /*!< Interrupt selector PF(7:4) */
+ EXTI_HalfPort_G_LSB = (uint8_t)0x82, /*!< Interrupt selector PG(3:0) */
+ EXTI_HalfPort_G_MSB = (uint8_t)0x84, /*!< Interrupt selector PG(7:4) */
+ EXTI_HalfPort_H_LSB = (uint8_t)0x88, /*!< Interrupt selector PH(3:0) */
+ EXTI_HalfPort_H_MSB = (uint8_t)0x90 /*!< Interrupt selector PH(7:4) */
+} EXTI_HalfPort_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup EXTI_Port
+ *
+ * @brief EXTI Port possible values
+ * Values are coded in 0xXY format where
+ * X: the register index
+ * X = 0: EXTI_CR3
+ * X = 1: EXTI_CR4
+ * Y: the number of shift to be performed
+ * @{
+ */
+typedef enum
+{
+ EXTI_Port_B = (uint8_t)0x00, /*!< GPIO Port B */
+ EXTI_Port_D = (uint8_t)0x02, /*!< GPIO Port D */
+ EXTI_Port_E = (uint8_t)0x04, /*!< GPIO Port E */
+ EXTI_Port_F = (uint8_t)0x06, /*!< GPIO Port F */
+ EXTI_Port_G = (uint8_t)0x10, /*!< GPIO Port G */
+ EXTI_Port_H = (uint8_t)0x12 /*!< GPIO Port H */
+} EXTI_Port_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup EXTI_Pin
+ *
+ * @brief EXTI PinNum possible values
+ * Values are coded in 0xXY format where
+ * X: the register index
+ * X = 0: EXTI_CR1
+ * X = 1: EXTI_CR2
+ * Y: the number of shift to be performed
+ * @{
+ */
+typedef enum
+{
+ EXTI_Pin_0 = (uint8_t)0x00, /*!< GPIO Pin 0 */
+ EXTI_Pin_1 = (uint8_t)0x02, /*!< GPIO Pin 1 */
+ EXTI_Pin_2 = (uint8_t)0x04, /*!< GPIO Pin 2 */
+ EXTI_Pin_3 = (uint8_t)0x06, /*!< GPIO Pin 3 */
+ EXTI_Pin_4 = (uint8_t)0x10, /*!< GPIO Pin 4 */
+ EXTI_Pin_5 = (uint8_t)0x12, /*!< GPIO Pin 5 */
+ EXTI_Pin_6 = (uint8_t)0x14, /*!< GPIO Pin 6 */
+ EXTI_Pin_7 = (uint8_t)0x16 /*!< GPIO Pin 7 */
+} EXTI_Pin_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup EXTI_Interrupts
+ *
+ * @brief EXTI IT pending bit possible values
+ * Values are coded in 0xXY format where
+ * X: the register index
+ * X = 00: EXTI_SR1
+ * X = 01: EXTI_SR2
+ * Y: the IT pending bit mask
+ * @{
+ */
+typedef enum
+{
+ EXTI_IT_Pin0 = (uint16_t)0x0001, /*!< GPIO Pin pos 0 */
+ EXTI_IT_Pin1 = (uint16_t)0x0002, /*!< GPIO Pin pos 1 */
+ EXTI_IT_Pin2 = (uint16_t)0x0004, /*!< GPIO Pin pos 2 */
+ EXTI_IT_Pin3 = (uint16_t)0x0008, /*!< GPIO Pin pos 3 */
+ EXTI_IT_Pin4 = (uint16_t)0x0010, /*!< GPIO Pin pos 4 */
+ EXTI_IT_Pin5 = (uint16_t)0x0020, /*!< GPIO Pin pos 5 */
+ EXTI_IT_Pin6 = (uint16_t)0x0040, /*!< GPIO Pin pos 6 */
+ EXTI_IT_Pin7 = (uint16_t)0x0080, /*!< GPIO Pin pos 7 */
+ EXTI_IT_PortB = (uint16_t)0x0101, /*!< GPIO Port B */
+ EXTI_IT_PortD = (uint16_t)0x0102, /*!< GPIO Port D */
+ EXTI_IT_PortE = (uint16_t)0x0104, /*!< GPIO Port E */
+ EXTI_IT_PortF = (uint16_t)0x0108, /*!< GPIO Port F */
+ EXTI_IT_PortG = (uint16_t)0x0110, /*!< GPIO Port G */
+ EXTI_IT_PortH = (uint16_t)0x0120 /*!< GPIO Port H */
+} EXTI_IT_TypeDef;
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+
+/** @addtogroup EXTI_Exported_Macros
+ * @{
+ */
+
+/**
+ * @brief Macro used by the assert function to check the different functions parameters.
+ */
+
+/**
+ * @brief Macro used by the assert function in order to check the different values
+ * of EXTI Sensitivity
+ */
+#define IS_EXTI_TRIGGER(TRIGGER) \
+ (((TRIGGER) == EXTI_Trigger_Falling_Low) || \
+ ((TRIGGER) == EXTI_Trigger_Rising) || \
+ ((TRIGGER) == EXTI_Trigger_Falling) || \
+ ((TRIGGER) == EXTI_Trigger_Rising_Falling))
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * half ports values for configuration.
+ */
+#define IS_EXTI_HALFPORT(HALFPORT) \
+ (((HALFPORT) == EXTI_HalfPort_B_LSB) ||\
+ ((HALFPORT) == EXTI_HalfPort_B_MSB) ||\
+ ((HALFPORT) == EXTI_HalfPort_D_LSB) ||\
+ ((HALFPORT) == EXTI_HalfPort_D_MSB) ||\
+ ((HALFPORT) == EXTI_HalfPort_E_LSB) ||\
+ ((HALFPORT) == EXTI_HalfPort_E_MSB) ||\
+ ((HALFPORT) == EXTI_HalfPort_F_LSB) ||\
+ ((HALFPORT) == EXTI_HalfPort_F_MSB) ||\
+ ((HALFPORT) == EXTI_HalfPort_G_LSB) ||\
+ ((HALFPORT) == EXTI_HalfPort_G_MSB) ||\
+ ((HALFPORT) == EXTI_HalfPort_H_LSB) ||\
+ ((HALFPORT) == EXTI_HalfPort_H_MSB))
+
+/**
+ * @brief Macro used by the assert function in order to check the different Port Number values
+ */
+#define IS_EXTI_PORT(PORT) (((PORT) == EXTI_Port_B) ||\
+ ((PORT) == EXTI_Port_D) ||\
+ ((PORT) == EXTI_Port_E) ||\
+ ((PORT) == EXTI_Port_F) ||\
+ ((PORT) == EXTI_Port_G) ||\
+ ((PORT) == EXTI_Port_H))
+
+/**
+ * @brief Macro used by the assert function in order to check the different Pin numbers values
+ */
+#define IS_EXTI_PINNUM(PINNUM) \
+ (((PINNUM) == EXTI_Pin_0) ||\
+ ((PINNUM) == EXTI_Pin_1) ||\
+ ((PINNUM) == EXTI_Pin_2) ||\
+ ((PINNUM) == EXTI_Pin_3) ||\
+ ((PINNUM) == EXTI_Pin_4) ||\
+ ((PINNUM) == EXTI_Pin_5) ||\
+ ((PINNUM) == EXTI_Pin_6) ||\
+ ((PINNUM) == EXTI_Pin_7))
+
+/**
+ * @brief Macro used by the assert function in order to check the different flags values
+ */
+#define IS_EXTI_ITPENDINGBIT(ITPENDINGBIT) \
+ (((ITPENDINGBIT) == EXTI_IT_Pin0) ||\
+ ((ITPENDINGBIT) == EXTI_IT_Pin1) ||\
+ ((ITPENDINGBIT) == EXTI_IT_Pin2) ||\
+ ((ITPENDINGBIT) == EXTI_IT_Pin3) ||\
+ ((ITPENDINGBIT) == EXTI_IT_Pin4) ||\
+ ((ITPENDINGBIT) == EXTI_IT_Pin5) ||\
+ ((ITPENDINGBIT) == EXTI_IT_Pin6) ||\
+ ((ITPENDINGBIT) == EXTI_IT_Pin7) ||\
+ ((ITPENDINGBIT) == EXTI_IT_PortB) ||\
+ ((ITPENDINGBIT) == EXTI_IT_PortD) ||\
+ ((ITPENDINGBIT) == EXTI_IT_PortE) ||\
+ ((ITPENDINGBIT) == EXTI_IT_PortF) ||\
+ ((ITPENDINGBIT) == EXTI_IT_PortG) ||\
+ ((ITPENDINGBIT) == EXTI_IT_PortH))
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+/* EXTI configuration *********************************************************/
+void EXTI_DeInit(void);
+void EXTI_SetPinSensitivity(EXTI_Pin_TypeDef EXTI_Pin, EXTI_Trigger_TypeDef EXTI_Trigger);
+void EXTI_SelectPort(EXTI_Port_TypeDef EXTI_Port);
+void EXTI_SetHalfPortSelection(EXTI_HalfPort_TypeDef EXTI_HalfPort, FunctionalState NewState);
+void EXTI_SetPortSensitivity(EXTI_Port_TypeDef EXTI_Port, EXTI_Trigger_TypeDef EXTI_Trigger);
+EXTI_Trigger_TypeDef EXTI_GetPinSensitivity(EXTI_Pin_TypeDef EXTI_Pin);
+EXTI_Trigger_TypeDef EXTI_GetPortSensitivity(EXTI_Port_TypeDef EXTI_Port);
+
+/* EXTI Interrupt status management *******************************************/
+ITStatus EXTI_GetITStatus(EXTI_IT_TypeDef EXTI_IT);
+void EXTI_ClearITPendingBit(EXTI_IT_TypeDef EXTI_IT);
+
+#endif /* __STM8L15x_EXTI_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_flash.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_flash.h
new file mode 100644
index 00000000..ffe5f722
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_flash.h
@@ -0,0 +1,359 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_flash.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the FLASH firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_FLASH_H
+#define __STM8L15x_FLASH_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup FLASH
+ * @{
+ */
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @addtogroup FLASH_Exported_Constants
+ * @{
+ */
+#define FLASH_PROGRAM_START_PHYSICAL_ADDRESS ((uint32_t)0x00008000) /*!< Flash: start address */
+#define FLASH_DATA_EEPROM_START_PHYSICAL_ADDRESS ((uint32_t)0x00001000) /*!< Data Eeprom: start address */
+
+/* STM8L15x High density devices */
+#if defined (STM8L15X_HD) || defined (STM8L05X_HD_VL)
+ #define FLASH_PROGRAM_END_PHYSICAL_ADDRESS ((uint32_t)0x00017FFF) /*!< Flash: end address */
+ #define FLASH_DATA_EEPROM_END_PHYSICAL_ADDRESS ((uint32_t)0x000017FF) /*!< Data Eeprom: end address */
+ #define FLASH_PROGRAM_BLOCKS_NUMBER ((uint16_t)0x200) /*!< Flash memory: total number of Block */
+ #define FLASH_DATA_EEPROM_BLOCKS_NUMBER ((uint8_t)0x10) /*!< Data EEprom: total number of Block */
+ #define FLASH_BLOCK_SIZE ((uint8_t)0x80) /*!< Number of bytes in a Block
+ (common for Program and Data EEprom memories) */
+
+/* STM8L15x Medium density and Medium density plus devices */
+#elif defined (STM8L15X_MD) || defined (STM8L15X_MDP) || defined (STM8AL31_L_MD) || defined (STM8L05X_MD_VL)
+ #define FLASH_PROGRAM_END_PHYSICAL_ADDRESS ((uint32_t)0x0000FFFF) /*!< Flash: end address */
+ #define FLASH_DATA_EEPROM_END_PHYSICAL_ADDRESS ((uint32_t)0x000013FF) /*!< Data Eeprom: end address */
+ #define FLASH_PROGRAM_BLOCKS_NUMBER ((uint16_t)0x100) /*!< Flash memory: total number of Block */
+ #define FLASH_DATA_EEPROM_BLOCKS_NUMBER ((uint8_t)0x8) /*!< Data EEprom: total number of Block */
+ #define FLASH_BLOCK_SIZE ((uint8_t)0x80) /*!< Number of bytes in a Block
+ (common for Program and Data EEprom memories) */
+
+/* STM8L15x Low density devices */
+#elif defined (STM8L15X_LD) || defined (STM8L05X_LD_VL)
+ #define FLASH_PROGRAM_END_PHYSICAL_ADDRESS ((uint32_t)0x00009FFF) /*!< Flash: end address */
+ #define FLASH_DATA_EEPROM_END_PHYSICAL_ADDRESS ((uint32_t)0x000010FF) /*!< Data Eeprom: end address */
+ #define FLASH_PROGRAM_BLOCKS_NUMBER ((uint16_t)0x80) /*!< Flash memory: total number of Block */
+ #define FLASH_DATA_EEPROM_BLOCKS_NUMBER ((uint8_t)0x4) /*!< Data EEprom: total number of Block */
+ #define FLASH_BLOCK_SIZE ((uint8_t)0x40) /*!< Number of bytes in a Block
+ (common for Program and Data EEprom memories) */
+#endif /* STM8L15X_HD or STM8L05X_HD_VL*/
+
+/*Common defines for all STM8L15x devices */
+#define FLASH_OPTION_BYTES_START_PHYSICAL_ADDRESS ((uint32_t)0x00004800) /*!< Option bytes: start address */
+#define FLASH_OPTION_BYTES_END_PHYSICAL_ADDRESS ((uint32_t)0x0000480A) /*!< Option bytes: end address */
+#define FLASH_RASS_KEY1 ((uint8_t)0x56) /*!< First RASS key */
+#define FLASH_RASS_KEY2 ((uint8_t)0xAE) /*!< Second RASS key */
+#define FLASH_READOUTPROTECTION_KEY ((uint8_t)0xAA) /*!< Read out protection key */
+
+/**
+ * @}
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @addtogroup FLASH_Exported_Types
+ * @{
+ */
+
+/** @defgroup FLASH_Memory_Type
+ * @{
+ */
+ typedef enum
+ {
+ FLASH_MemType_Program = (uint8_t)0xFD, /*!< Program memory */
+ FLASH_MemType_Data = (uint8_t)0xF7 /*!< Data EEPROM memory */
+ } FLASH_MemType_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Programming_Mode
+ * @{
+ */
+typedef enum
+{
+ FLASH_ProgramMode_Standard = (uint8_t)0x00, /*!< Standard programming mode */
+ FLASH_ProgramMode_Fast = (uint8_t)0x10 /*!< Fast programming mode */
+} FLASH_ProgramMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Programming_Time
+ * @{
+ */
+typedef enum
+{
+ FLASH_ProgramTime_Standard = (uint8_t)0x00, /*!< Standard programming time fixed at 1/2 tprog */
+ FLASH_ProgramTime_TProg = (uint8_t)0x01 /*!< Programming time fixed at tprog */
+} FLASH_ProgramTime_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Power_Mode
+ * @{
+ */
+typedef enum
+{
+ FLASH_Power_IDDQ = (uint8_t)0x00, /*!< Flash program and data EEPROM in IDDQ */
+ FLASH_Power_On = (uint8_t)0x01 /*!< Flash program and data EEPROM not in IDDQ */
+} FLASH_Power_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Status
+ * @{
+ */
+typedef enum
+{
+ FLASH_Status_Write_Protection_Error = (uint8_t)0x01, /*!< Write attempted to protected Block */
+ FLASH_Status_TimeOut = (uint8_t)0x02, /*!< Time out error */
+ FLASH_Status_Successful_Operation = (uint8_t)0x04 /*!< End of operation flag */
+} FLASH_Status_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Power_Status
+ * @{
+ */
+typedef enum
+{
+ FLASH_PowerStatus_IDDQDuringWaitMode = (uint8_t)0x04, /*!< Flash program and data EEPROM
+ in IDDQ during Wait mode*/
+ FLASH_PowerStatus_IDDQDuringRunMode = (uint8_t)0x08, /*!< Flash program and data EEPROM
+ in IDDQ mode during Run mode*/
+ FLASH_PowerStatus_IDDQDuringWaitAndRunModes = (uint8_t)0x0C, /*!= FLASH_PROGRAM_START_PHYSICAL_ADDRESS) && \
+ ((Address) <= FLASH_PROGRAM_END_PHYSICAL_ADDRESS))
+
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * sensitivity values for the data Eeprom Address
+ */
+
+#define IS_FLASH_DATA_EEPROM_ADDRESS(Address) (((Address) >= FLASH_DATA_EEPROM_START_PHYSICAL_ADDRESS) && \
+ ((Address) <= FLASH_DATA_EEPROM_END_PHYSICAL_ADDRESS))
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * sensitivity values for the data eeprom and flash program Address
+ */
+#define IS_FLASH_ADDRESS(Address)((((Address) >= FLASH_PROGRAM_START_PHYSICAL_ADDRESS) && ((Address) <= FLASH_PROGRAM_END_PHYSICAL_ADDRESS)) || \
+ (((Address) >= FLASH_DATA_EEPROM_START_PHYSICAL_ADDRESS) && ((Address) <= FLASH_DATA_EEPROM_END_PHYSICAL_ADDRESS)))
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * sensitivity values for the option bytes Address
+ */
+#define IS_OPTION_BYTE_ADDRESS(ADDRESS) (((ADDRESS) >= FLASH_OPTION_BYTES_START_PHYSICAL_ADDRESS) && \
+ ((ADDRESS) <= FLASH_OPTION_BYTES_END_PHYSICAL_ADDRESS))
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * sensitivity values for the flash Block number
+ */
+#define IS_FLASH_PROGRAM_BLOCK_NUMBER(BlockNum) ((BlockNum) < FLASH_PROGRAM_BLOCKS_NUMBER)
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * sensitivity values for the data eeprom Block number
+ */
+#define IS_FLASH_DATA_EEPROM_BLOCK_NUMBER(BlockNum) ((BlockNum) < FLASH_DATA_EEPROM_BLOCKS_NUMBER)
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * sensitivity values for the flash memory type
+ */
+#define IS_FLASH_MEMORY_TYPE(MemType) (((MemType) == FLASH_MemType_Program) || \
+ ((MemType) == FLASH_MemType_Data))
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * sensitivity values for the flash program block mode
+ */
+#define IS_FLASH_PROGRAM_MODE(Mode) (((Mode) == FLASH_ProgramMode_Standard) || \
+ ((Mode) == FLASH_ProgramMode_Fast))
+
+/**
+ * @brief Macro used by the assert function in order to check the program time mode
+ */
+#define IS_FLASH_PROGRAM_TIME(Time) (((Time) == FLASH_ProgramTime_Standard) || \
+ ((Time) == FLASH_ProgramTime_TProg))
+
+/**
+ * @brief Macro used by the assert function in order to check the power mode
+ */
+#define IS_FLASH_POWER(Power) (((Power) == FLASH_Power_IDDQ) || \
+ ((Power) == FLASH_Power_On))
+
+/**
+ * @brief Macro used by the assert function in order to check the power status during wait and run modes
+ */
+#define IS_FLASH_POWERSTATUS(PowerStatus) (((PowerStatus) == FLASH_PowerStatus_IDDQDuringWaitMode) || \
+ ((PowerStatus) == FLASH_PowerStatus_IDDQDuringRunMode ) || \
+ ((PowerStatus) == FLASH_PowerStatus_IDDQDuringWaitAndRunModes) || \
+ ((PowerStatus) == FLASH_Power_On))
+
+/**
+ * @brief Macro used by the assert function in order to check the different flags values
+ */
+#define IS_FLASH_FLAGS(FLAG) (((FLAG) == FLASH_FLAG_HVOFF) || \
+ ((FLAG) == FLASH_FLAG_DUL) || \
+ ((FLAG) == FLASH_FLAG_EOP) || \
+ ((FLAG) == FLASH_FLAG_PUL) || \
+ ((FLAG) == FLASH_FLAG_WR_PG_DIS))
+
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+/* FLASH program and Data EEPROM memories interface configuration functions ***/
+FLASH_ProgramTime_TypeDef FLASH_GetProgrammingTime(void);
+void FLASH_SetProgrammingTime(FLASH_ProgramTime_TypeDef FLASH_ProgTime);
+void FLASH_PowerWaitModeConfig(FLASH_Power_TypeDef FLASH_Power);
+
+/* FLASH program and Data EEPROM memories Programming functions ***************/
+void FLASH_DeInit(void);
+void FLASH_Unlock(FLASH_MemType_TypeDef FLASH_MemType);
+void FLASH_Lock(FLASH_MemType_TypeDef FLASH_MemType);
+void FLASH_ProgramByte(uint32_t Address, uint8_t Data);
+void FLASH_EraseByte(uint32_t Address);
+void FLASH_ProgramWord(uint32_t Address, uint32_t Data);
+uint8_t FLASH_ReadByte(uint32_t Address);
+
+/* Option Bytes Programming functions *****************************************/
+uint16_t FLASH_GetBootSize(void);
+uint16_t FLASH_GetCodeSize(void);
+FunctionalState FLASH_GetReadOutProtectionStatus(void);
+void FLASH_ProgramOptionByte(uint16_t Address, uint8_t Data);
+void FLASH_EraseOptionByte(uint16_t Address);
+
+/* Interrupts and flags management functions **********************************/
+void FLASH_ITConfig(FunctionalState NewState);
+FlagStatus FLASH_GetFlagStatus(FLASH_FLAG_TypeDef FLASH_FLAG);
+
+/* Functions to be executed from RAM ******************************************/
+
+/**
+@code
+ All the functions declared below must be executed from RAM exclusively, except
+ for the FLASH_WaitForLastOperation function which can be executed from Flash.
+
+ Steps of the execution from RAM differs from one toolchain to another.
+ for more details refer to stm8l15x_flash.c file.
+
+ To enable execution from RAM you can either uncomment the following define
+ in the stm8s.h file or define it in your toolchain compiler preprocessor
+ - #define RAM_EXECUTION (1)
+
+@endcode
+*/
+
+IN_RAM(void FLASH_PowerRunModeConfig(FLASH_Power_TypeDef FLASH_Power));
+IN_RAM(FLASH_PowerStatus_TypeDef FLASH_GetPowerStatus(void));
+
+IN_RAM(void FLASH_ProgramBlock(uint16_t BlockNum, FLASH_MemType_TypeDef FLASH_MemType,
+ FLASH_ProgramMode_TypeDef FLASH_ProgMode, uint8_t *Buffer));
+IN_RAM(void FLASH_EraseBlock(uint16_t BlockNum, FLASH_MemType_TypeDef FLASH_MemType));
+
+IN_RAM(FLASH_Status_TypeDef FLASH_WaitForLastOperation(FLASH_MemType_TypeDef FLASH_MemType));
+
+#endif /*__STM8L15x_FLASH_H*/
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_gpio.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_gpio.h
new file mode 100644
index 00000000..65f89497
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_gpio.h
@@ -0,0 +1,179 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_gpio.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the GPIO firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_GPIO_H
+#define __STM8L15x_GPIO_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup I2C
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @addtogroup GPIO_Exported_Types
+ * @{
+ */
+
+/**
+ * @defgroup GPIO_Modes
+ *
+ * @brief
+ *
+ * Bits definitions:
+ * - Bit 7: 0 = INPUT mode
+ * 1 = OUTPUT mode
+ * 1 = PULL-UP (input) or PUSH-PULL (output)
+ * - Bit 5: 0 = No external interrupt (input) or No slope control (output)
+ * 1 = External interrupt (input) or Slow control enabled (output)
+ * - Bit 4: 0 = Low level (output)
+ * 1 = High level (output push-pull) or HI-Z (output open-drain)
+ * @{
+ */
+typedef enum
+{
+ GPIO_Mode_In_FL_No_IT = (uint8_t)0x00, /*!< Input floating, no external interrupt */
+ GPIO_Mode_In_PU_No_IT = (uint8_t)0x40, /*!< Input pull-up, no external interrupt */
+ GPIO_Mode_In_FL_IT = (uint8_t)0x20, /*!< Input floating, external interrupt */
+ GPIO_Mode_In_PU_IT = (uint8_t)0x60, /*!< Input pull-up, external interrupt */
+ GPIO_Mode_Out_OD_Low_Fast = (uint8_t)0xA0, /*!< Output open-drain, low level, 10MHz */
+ GPIO_Mode_Out_PP_Low_Fast = (uint8_t)0xE0, /*!< Output push-pull, low level, 10MHz */
+ GPIO_Mode_Out_OD_Low_Slow = (uint8_t)0x80, /*!< Output open-drain, low level, 2MHz */
+ GPIO_Mode_Out_PP_Low_Slow = (uint8_t)0xC0, /*!< Output push-pull, low level, 2MHz */
+ GPIO_Mode_Out_OD_HiZ_Fast = (uint8_t)0xB0, /*!< Output open-drain, high-impedance level, 10MHz */
+ GPIO_Mode_Out_PP_High_Fast = (uint8_t)0xF0, /*!< Output push-pull, high level, 10MHz */
+ GPIO_Mode_Out_OD_HiZ_Slow = (uint8_t)0x90, /*!< Output open-drain, high-impedance level, 2MHz */
+ GPIO_Mode_Out_PP_High_Slow = (uint8_t)0xD0 /*!< Output push-pull, high level, 2MHz */
+}GPIO_Mode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup GPIO_Pin
+ * @{
+ */
+
+typedef enum
+{
+ GPIO_Pin_0 = ((uint8_t)0x01), /*!< Pin 0 selected */
+ GPIO_Pin_1 = ((uint8_t)0x02), /*!< Pin 1 selected */
+ GPIO_Pin_2 = ((uint8_t)0x04), /*!< Pin 2 selected */
+ GPIO_Pin_3 = ((uint8_t)0x08), /*!< Pin 3 selected */
+ GPIO_Pin_4 = ((uint8_t)0x10), /*!< Pin 4 selected */
+ GPIO_Pin_5 = ((uint8_t)0x20), /*!< Pin 5 selected */
+ GPIO_Pin_6 = ((uint8_t)0x40), /*!< Pin 6 selected */
+ GPIO_Pin_7 = ((uint8_t)0x80), /*!< Pin 7 selected */
+ GPIO_Pin_LNib = ((uint8_t)0x0F), /*!< Low nibble pins selected */
+ GPIO_Pin_HNib = ((uint8_t)0xF0), /*!< High nibble pins selected */
+ GPIO_Pin_All = ((uint8_t)0xFF) /*!< All pins selected */
+}GPIO_Pin_TypeDef;
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+
+/** @addtogroup GPIO_Exported_Macros
+ * @{
+ */
+
+/**
+ * @brief Macro used by the assert function to check the different functions parameters.
+ */
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * values of GPIOMode_TypeDef.
+ */
+#define IS_GPIO_MODE(MODE) \
+ (((MODE) == GPIO_Mode_In_FL_No_IT) || \
+ ((MODE) == GPIO_Mode_In_PU_No_IT) || \
+ ((MODE) == GPIO_Mode_In_FL_IT) || \
+ ((MODE) == GPIO_Mode_In_PU_IT) || \
+ ((MODE) == GPIO_Mode_Out_OD_Low_Fast) || \
+ ((MODE) == GPIO_Mode_Out_PP_Low_Fast) || \
+ ((MODE) == GPIO_Mode_Out_OD_Low_Slow) || \
+ ((MODE) == GPIO_Mode_Out_PP_Low_Slow) || \
+ ((MODE) == GPIO_Mode_Out_OD_HiZ_Fast) || \
+ ((MODE) == GPIO_Mode_Out_PP_High_Fast) || \
+ ((MODE) == GPIO_Mode_Out_OD_HiZ_Slow) || \
+ ((MODE) == GPIO_Mode_Out_PP_High_Slow))
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * values of GPIO_Pins.
+ */
+#define IS_GPIO_PIN(PIN) ((PIN) != (uint8_t)0x00)
+
+/**
+ * @}
+ */
+
+
+/* Exported functions ------------------------------------------------------- */
+/* Initialization and Configuration *******************************************/
+void GPIO_DeInit(GPIO_TypeDef* GPIOx);
+void GPIO_Init(GPIO_TypeDef* GPIOx, uint8_t GPIO_Pin, GPIO_Mode_TypeDef GPIO_Mode);
+void GPIO_ExternalPullUpConfig(GPIO_TypeDef* GPIOx, uint8_t GPIO_Pin, FunctionalState NewState);
+
+/* GPIO Read and Write ********************************************************/
+void GPIO_Write(GPIO_TypeDef* GPIOx, uint8_t GPIO_PortVal);
+void GPIO_WriteBit(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin, BitAction GPIO_BitVal);
+void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint8_t GPIO_Pin);
+void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint8_t GPIO_Pin);
+void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint8_t GPIO_Pin);
+uint8_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
+uint8_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
+BitStatus GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin);
+BitStatus GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin);
+
+#endif /* __STM8L15x_GPIO_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_i2c.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_i2c.h
new file mode 100644
index 00000000..010b4ba0
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_i2c.h
@@ -0,0 +1,809 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_i2c.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the I2C firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_I2C_H
+#define __STM8L15x_I2C_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup I2C
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+/** @defgroup I2C_Exported_Types
+ * @{
+ */
+/** @defgroup I2C_mode
+ * @{
+ */
+typedef enum
+{
+ I2C_Mode_I2C = (uint8_t)0x00, /*!< I2C mode */
+ I2C_Mode_SMBusDevice = (uint8_t)0x02, /*!< SMBus Device mode */
+ I2C_Mode_SMBusHost = (uint8_t)0x0A /*!< SMBus Host mode */
+} I2C_Mode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_duty_cycle_in_fast_mode
+ * @{
+ */
+typedef enum
+{
+ I2C_DutyCycle_2 = (uint8_t)0x00, /*!< Fast mode Tlow/THigh = 2 */
+ I2C_DutyCycle_16_9 = (uint8_t)0x40 /*!< Fast mode Tlow/Thigh = 16/9 */
+} I2C_DutyCycle_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_acknowledgement
+ * @{
+ */
+typedef enum
+{
+ I2C_Ack_Disable = (uint8_t)0x00, /*!< No acknowledge */
+ I2C_Ack_Enable = (uint8_t)0x04 /*!< Acknowledge Enabled */
+} I2C_Ack_TypeDef;
+/**
+ * @}
+ */
+
+/** @defgroup I2C_Position_Acknowledgement
+ * @{
+ */
+typedef enum
+{
+ I2C_AckPosition_Current = (uint8_t)0x00, /*!< Acknowledge on the current byte */
+ I2C_AckPosition_Next = (uint8_t)0x08 /*!< Acknowledge on the next byte */
+} I2C_AckPosition_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_acknowledged_address
+ * @{
+ */
+typedef enum
+{
+ I2C_AcknowledgedAddress_7bit = (uint8_t)0x00, /*!< 7-bit slave address (10-bit address not acknowledged) */
+ I2C_AcknowledgedAddress_10bit = (uint8_t)0x80 /*!< 10-bit slave address (7-bit address not acknowledged) */
+} I2C_AcknowledgedAddress_TypeDef;
+/**
+ * @}
+ */
+
+/** @defgroup I2C_transfer_direction
+ * @{
+ */
+
+/**
+ * Warning: the values correspond to the ADD0 bit position in the OARL register
+ */
+typedef enum
+{
+ I2C_Direction_Transmitter = (uint8_t)0x00, /*!< Transmission direction */
+ I2C_Direction_Receiver = (uint8_t)0x01 /*!< Reception direction */
+} I2C_Direction_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_SMBus_alert_pin_level
+ * @{
+ */
+typedef enum
+{
+ I2C_SMBusAlert_High = (uint8_t)0x00, /*!< SMBAlert pin high */
+ I2C_SMBusAlert_Low = (uint8_t)0x01 /*!< SMBAlert pin Low */
+} I2C_SMBusAlert_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_PEC_position
+ * @{
+ */
+typedef enum
+{
+ I2C_PECPosition_Current = (uint8_t)0x00, /*!< Current byte in shift register is PEC */
+ I2C_PECPosition_Next = (uint8_t)0x08 /*!< Next byte in shift register is PEC */
+} I2C_PECPosition_TypeDef;
+/**
+ * @}
+ */
+
+/** @defgroup I2C_flags_definition
+ * @{
+ */
+/**
+ * @brief Elements values convention: 0xXXYY
+ * X = SRx registers index
+ * X = 1 : SR1
+ * X = 2 : SR2
+ * X = 3 : SR3
+ * Y = Flag mask in the register
+ */
+
+typedef enum
+{
+ /* SR1 register flags */
+ I2C_FLAG_TXE = (uint16_t)0x0180, /*!< Transmit Data Register Empty flag */
+ I2C_FLAG_RXNE = (uint16_t)0x0140, /*!< Read Data Register Not Empty flag */
+ I2C_FLAG_STOPF = (uint16_t)0x0110, /*!< Stop detected flag */
+ I2C_FLAG_ADD10 = (uint16_t)0x0108, /*!< 10-bit Header sent flag */
+ I2C_FLAG_BTF = (uint16_t)0x0104, /*!< Data Byte Transfer Finished flag */
+ I2C_FLAG_ADDR = (uint16_t)0x0102, /*!< Address Sent/Matched (master/slave) flag */
+ I2C_FLAG_SB = (uint16_t)0x0101, /*!< Start bit sent flag */
+
+ /* SR2 register flags */
+ I2C_FLAG_SMBALERT = (uint16_t)0x0280, /*!< SMBUS Alert flag */
+ I2C_FLAG_TIMEOUT = (uint16_t)0x0240, /*!< Time out flag */
+ I2C_FLAG_WUFH = (uint16_t)0x0220, /*!< Wake Up From Halt flag */
+ I2C_FLAG_PECERR = (uint16_t)0x0210, /*!< PEC error flag */
+ I2C_FLAG_OVR = (uint16_t)0x0208, /*!< Overrun/Underrun flag */
+ I2C_FLAG_AF = (uint16_t)0x0204, /*!< Acknowledge Failure flag */
+ I2C_FLAG_ARLO = (uint16_t)0x0202, /*!< Arbitration Loss flag */
+ I2C_FLAG_BERR = (uint16_t)0x0201, /*!< Misplaced Start or Stop condition */
+
+ /* SR3 register flags */
+ I2C_FLAG_DUALF = (uint16_t)0x0380, /*!< DUAL Flag */
+ I2C_FLAG_SMBHOST = (uint16_t)0x0340, /*!< SMBUS host Flag */
+ I2C_FLAG_SMBDEFAULT = (uint16_t)0x0320, /*!< SMBUS default flag */
+ I2C_FLAG_GENCALL = (uint16_t)0x0310, /*!< General Call header received Flag */
+ I2C_FLAG_TRA = (uint16_t)0x0304, /*!< Transmitter Receiver flag */
+ I2C_FLAG_BUSY = (uint16_t)0x0302, /*!< Bus Busy flag */
+ I2C_FLAG_MSL = (uint16_t)0x0301 /*!< Master Slave flag */
+} I2C_FLAG_TypeDef;
+
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_interrupts_definition
+ * @{
+ */
+
+/**
+ * @brief I2C Pending bits
+ * Elements values convention: 0xXYZZ
+ * X = SRx registers index
+ * X = 0 : ITR
+ * X = 1 : SR1
+ * X = 2 : SR2
+ * Y = Position of the corresponding Interrupt
+ * ZZ = flag mask in the dedicated register(X register)
+ */
+
+typedef enum
+{
+ I2C_IT_ERR = (uint16_t)0x0001, /*!< Error Interruption */
+ I2C_IT_EVT = (uint16_t)0x0002, /*!< Event Interruption */
+ I2C_IT_BUF = (uint16_t)0x0004, /*!< Buffer Interruption */
+ /* SR1 register*/
+ I2C_IT_TXE = (uint16_t)0x1680, /*!< Transmit Data Register Empty */
+ I2C_IT_RXNE = (uint16_t)0x1640, /*!< Read Data Register Not Empty */
+ I2C_IT_STOPF = (uint16_t)0x1210, /*!< Stop detected */
+ I2C_IT_ADD10 = (uint16_t)0x1208, /*!< 10-bit Header sent */
+ I2C_IT_BTF = (uint16_t)0x1204, /*!< Data Byte Transfer Finished */
+ I2C_IT_ADDR = (uint16_t)0x1202, /*!< Address Sent/Matched (master/slave) */
+ I2C_IT_SB = (uint16_t)0x1201, /*!< Start bit sent */
+
+ /* SR2 register*/
+ I2C_IT_SMBALERT = (uint16_t)0x2180, /*!< SMBUS alert */
+ I2C_IT_TIMEOUT = (uint16_t)0x2140, /*!< Time out */
+ I2C_IT_WUFH = (uint16_t)0x2220, /*!< PEC error */
+ I2C_IT_PECERR = (uint16_t)0x2110, /*!< Wake Up From Halt */
+ I2C_IT_OVR = (uint16_t)0x2108, /*!< Overrun/Underrun */
+ I2C_IT_AF = (uint16_t)0x2104, /*!< Acknowledge Failure */
+ I2C_IT_ARLO = (uint16_t)0x2102, /*!< Arbitration Loss */
+ I2C_IT_BERR = (uint16_t)0x2101 /*!< Misplaced Start or Stop condition */
+} I2C_IT_TypeDef;
+/**
+ * @}
+ */
+
+/** @defgroup I2C_Events
+ * @{
+ */
+
+/**
+ * @brief I2C possible events
+ * Values convention: 0xXXYY
+ * XX = Event SR3 corresponding value
+ * YY = Event SR1 corresponding value
+ * @note if Event = EV3_2 the rule above does not apply
+ * YY = Event SR2 corresponding value
+ */
+
+typedef enum
+{
+ /**
+ ===============================================================================
+ I2C Master Events (Events grouped in order of communication)
+ ===============================================================================
+ */
+/**
+ * @brief Communication start
+ *
+ * After sending the START condition (I2C_GenerateSTART() function) the master
+ * has to wait for this event. It means that the Start condition has been correctly
+ * released on the I2C bus (the bus is free, no other devices is communicating).
+ *
+ */
+ /* --EV5 */
+ I2C_EVENT_MASTER_MODE_SELECT = (uint16_t)0x0301, /*!< BUSY, MSL and SB flag */
+
+/**
+ * @brief Address Acknowledge
+ *
+ * After checking on EV5 (start condition correctly released on the bus), the
+ * master sends the address of the slave(s) with which it will communicate
+ * (I2C_Send7bitAddress() function, it also determines the direction of the communication:
+ * Master transmitter or Receiver).
+ * Then the master has to wait that a slave acknowledges his address.
+ * If an acknowledge is sent on the bus, one of the following events will
+ * be set:
+ *
+ * 1) In case of Master Receiver (7-bit addressing):
+ * the I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED event is set.
+ *
+ * 2) In case of Master Transmitter (7-bit addressing):
+ * the I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED is set
+ *
+ * 3) In case of 10-Bit addressing mode, the master (just after generating the START
+ * and checking on EV5) has to send the header of 10-bit addressing mode (I2C_SendData()
+ * function).
+ * Then master should wait on EV9. It means that the 10-bit addressing
+ * header has been correctly sent on the bus.
+ * Then master should send the second part of the 10-bit address (LSB) using
+ * the function I2C_Send7bitAddress(). Then master should wait for event EV6.
+ *
+ */
+ /* --EV6 */
+ I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED = (uint16_t)0x0782, /*!< BUSY, MSL, ADDR, TXE and TRA flags */
+ I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED = (uint16_t)0x0302, /*!< BUSY, MSL and ADDR flags */
+ /* --EV9 */
+ I2C_EVENT_MASTER_MODE_ADDRESS10 = (uint16_t)0x0308, /*!< BUSY, MSL and ADD10 flags */
+
+/**
+ * @brief Communication events
+ *
+ * If a communication is established (START condition generated and slave address
+ * acknowledged) then the master has to check on one of the following events for
+ * communication procedures:
+ *
+ * 1) Master Receiver mode: The master has to wait on the event EV7 then to read
+ * the data received from the slave (I2C_ReceiveData() function).
+ *
+ * 2) Master Transmitter mode: The master has to send data (I2C_SendData()
+ * function) then to wait on event EV8 or EV8_2.
+ * These two events are similar:
+ * - EV8 means that the data has been written in the data register and is
+ * being shifted out.
+ * - EV8_2 means that the data has been physically shifted out and output
+ * on the bus.
+ * In most cases, using EV8 is sufficient for the application.
+ * Using EV8_2 leads to a slower communication but ensure more reliable test.
+ * EV8_2 is also more suitable than EV8 for testing on the last data transmission
+ * (before Stop condition generation).
+ *
+ * @note In case the user software does not guarantee that this event EV7 is
+ * managed before the current byte end of transfer, then user may check on EV7
+ * and BTF flag at the same time (ie. (I2C_EVENT_MASTER_BYTE_RECEIVED | I2C_FLAG_BTF)).
+ * In this case the communication may be slower.
+ *
+ */
+ /* Master RECEIVER mode -----------------------------*/
+ /* --EV7 */
+ I2C_EVENT_MASTER_BYTE_RECEIVED = (uint16_t)0x0340, /*!< BUSY, MSL and RXNE flags */
+
+ /* Master TRANSMITTER mode --------------------------*/
+ /* --EV8 */
+ I2C_EVENT_MASTER_BYTE_TRANSMITTING = (uint16_t)0x0780, /*!< TRA, BUSY, MSL, TXE flags */
+ /* --EV8_2 */
+
+ I2C_EVENT_MASTER_BYTE_TRANSMITTED = (uint16_t)0x0784, /*!< EV8_2: TRA, BUSY, MSL, TXE and BTF flags */
+
+/**
+ ===============================================================================
+ I2C Slave Events (Events grouped in order of communication)
+ ===============================================================================
+ */
+
+/**
+ * @brief Communication start events
+ *
+ * Wait on one of these events at the start of the communication. It means that
+ * the I2C peripheral detected a Start condition on the bus (generated by master
+ * device) followed by the peripheral address.
+ * The peripheral generates an ACK condition on the bus (if the acknowledge
+ * feature is enabled through function I2C_AcknowledgeConfig()) and the events
+ * listed above are set :
+ *
+ * 1) In normal case (only one address managed by the slave), when the address
+ * sent by the master matches the own address of the peripheral (configured by
+ * I2C_OwnAddress1 field) the I2C_EVENT_SLAVE_XXX_ADDRESS_MATCHED event is set
+ * (where XXX could be TRANSMITTER or RECEIVER).
+ *
+ * 2) In case the address sent by the master matches the second address of the
+ * peripheral (configured by the function I2C_OwnAddress2Config() and enabled
+ * by the function I2C_DualAddressCmd()) the events I2C_EVENT_SLAVE_XXX_SECONDADDRESS_MATCHED
+ * (where XXX could be TRANSMITTER or RECEIVER) are set.
+ *
+ * 3) In case the address sent by the master is General Call (address 0x00) and
+ * if the General Call is enabled for the peripheral (using function I2C_GeneralCallCmd())
+ * the following event is set I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED.
+ *
+ */
+
+ /* --EV1 (all the events below are variants of EV1) */
+ /* 1) Case of One Single Address managed by the slave */
+ I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED = (uint16_t)0x0202, /*!< BUSY and ADDR flags */
+ I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED = (uint16_t)0x0682, /*!< TRA, BUSY, TXE and ADDR flags */
+
+ /* 2) Case of Dual address managed by the slave */
+ I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED = (uint16_t)0x8200, /*! DUALF and BUSY flags */
+ I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED = (uint16_t)0x8680, /*! DUALF, TRA, BUSY and TXE flags */
+
+ /* 3) Case of General Call enabled for the slave */
+ I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED = (uint16_t)0x1200, /*!< EV2: GENCALL and BUSY flags */
+
+ /**
+ * @brief Communication events
+ *
+ * Wait on one of these events when EV1 has already been checked :
+ *
+ * - Slave RECEIVER mode:
+ * - EV2: When the application is expecting a data byte to be received.
+ * - EV4: When the application is expecting the end of the communication:
+ * master sends a stop condition and data transmission is stopped.
+ *
+ * - Slave Transmitter mode:
+ * - EV3: When a byte has been transmitted by the slave and the application
+ * is expecting the end of the byte transmission.
+ * The two events I2C_EVENT_SLAVE_BYTE_TRANSMITTED and I2C_EVENT_SLAVE_BYTE_TRANSMITTING
+ * are similar. The second one can optionally be used when the user software
+ * doesn't guarantee the EV3 is managed before the current byte end of transfer.
+ * - EV3_2: When the master sends a NACK in order to tell slave that data transmission
+ * shall end (before sending the STOP condition).
+ * In this case slave has to stop sending data bytes and expect a Stop
+ * condition on the bus.
+ *
+ * @note In case the user software does not guarantee that the event EV2 is
+ * managed before the current byte end of transfer, then user may check on EV2
+ * and BTF flag at the same time (ie. (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_BTF)).
+ * In this case the communication may be slower.
+ *
+ */
+ /* Slave RECEIVER mode --------------------------*/
+ /* --EV2 */
+ I2C_EVENT_SLAVE_BYTE_RECEIVED = (uint16_t)0x0240, /*!< BUSY and RXNE flags */
+ /* --EV4 */
+ I2C_EVENT_SLAVE_STOP_DETECTED = (uint16_t)0x0010, /*!< STOPF flag */
+
+ /* Slave TRANSMITTER mode -----------------------*/
+ /* --EV3 */
+ I2C_EVENT_SLAVE_BYTE_TRANSMITTED = (uint16_t)0x0684, /*!< TRA, BUSY, TXE and BTF flags */
+ I2C_EVENT_SLAVE_BYTE_TRANSMITTING = (uint16_t)0x0680, /*!< TRA, BUSY and TXE flags */
+ /* --EV3_2 */
+ I2C_EVENT_SLAVE_ACK_FAILURE = (uint16_t)0x0004 /*!< AF flag */
+} I2C_Event_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_Registers
+ * @{
+ */
+typedef enum
+{
+ I2C_Register_CR1 = (uint8_t)0x00, /*!< Control register 1 */
+ I2C_Register_CR2 = (uint8_t)0x01, /*!< Control register 2 */
+ I2C_Register_FREQR = (uint8_t)0x02, /*!< Frequency register */
+ I2C_Register_OARL = (uint8_t)0x03, /*!< Own address register LSB */
+ I2C_Register_OARH = (uint8_t)0x04, /*!< Own address register MSB */
+ I2C_Register_DR = (uint8_t)0x06, /*!< Data register */
+ I2C_Register_SR1 = (uint8_t)0x07, /*!< Status register 1 */
+ I2C_Register_SR2 = (uint8_t)0x08, /*!< Status register 2 */
+ I2C_Register_SR3 = (uint8_t)0x09, /*!< Status register 3 */
+ I2C_Register_ITR = (uint8_t)0x0A, /*!< Interrupt and DMA register */
+ I2C_Register_CCRL = (uint8_t)0x0B, /*!< Clock control register low */
+ I2C_Register_CCRH = (uint8_t)0x0C, /*!< Clock control register high */
+ I2C_Register_TRISER = (uint8_t)0x0D, /*!< TRISE register */
+ I2C_Register_PECR = (uint8_t)0x0E /*!< PEC register */
+} I2C_Register_TypeDef;
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/* Exported constants --------------------------------------------------------*/
+/** @defgroup I2C_Exported_Constants
+ * @{
+ */
+#define I2C_MAX_STANDARD_FREQ ((uint32_t)100000)
+#define I2C_MAX_FAST_FREQ ((uint32_t)400000)
+
+/**
+ *@}
+ */
+
+/* Exported macro -----------------------------------------------------------*/
+/** @defgroup I2C_Exported_Macros
+ * @{
+ */
+
+/**
+ * @brief Macro used by the assert function to check the different functions parameters.
+ */
+
+/**
+ * @brief Macro used by the assert function to check the different I2C modes.
+ */
+#define IS_I2C_MODE(MODE)(((MODE) == I2C_Mode_I2C) || \
+ ((MODE) == I2C_Mode_SMBusDevice) || \
+ ((MODE) == I2C_Mode_SMBusHost))
+
+/**
+ * @brief Macro used by the assert function to check the different I2C duty cycles.
+ */
+#define IS_I2C_DUTY_CYCLE(CYCLE)(((CYCLE) == I2C_DutyCycle_2) || \
+ ((CYCLE) == I2C_DutyCycle_16_9))
+
+/**
+ * @brief Macro used by the assert function to check the different acknowledgement configuration
+ */
+#define IS_I2C_ACK_STATE(STATE) (((STATE) == I2C_Ack_Disable) || \
+ ((STATE) == I2C_Ack_Enable))
+/**
+ * @brief Macro used by the assert function to check the different acknowledgement position
+ */
+#define IS_I2C_ACK_POSITION(POSITION) (((POSITION) == I2C_AckPosition_Next) || \
+ ((POSITION) == I2C_AckPosition_Current))
+
+/**
+ * @brief Macro used by the assert function to check the different I2C PEC positions.
+ */
+#define IS_I2C_PEC_POSITION(POSITION) (((POSITION) == I2C_PECPosition_Current) || \
+ ((POSITION) == I2C_PECPosition_Next))
+
+/**
+ * @brief Macro used by the assert function to check the different I2C addressing modes.
+ */
+#define IS_I2C_ACKNOWLEDGE_ADDRESS(ADDMODE) (((ADDMODE) == I2C_AcknowledgedAddress_7bit) || \
+ ((ADDMODE) == I2C_AcknowledgedAddress_10bit))
+
+/**
+ * @brief Macro used by the assert function to check the different I2C SMBus Alert pin configuration.
+ */
+#define IS_I2C_SMBUS_ALERT(ALERT) (((ALERT) == I2C_SMBusAlert_High) || \
+ ((ALERT) == I2C_SMBusAlert_Low))
+
+/**
+ * @brief Macro used by the assert function to check the different I2C communication direction.
+ */
+#define IS_I2C_DIRECTION(DIR)(((DIR) == I2C_Direction_Transmitter) || \
+ ((DIR) == I2C_Direction_Receiver ))
+
+/**
+ * @brief Macro used by the assert function to check the different I2C flags.
+ */
+#define IS_I2C_GET_FLAG(FLAG) (((FLAG) == I2C_FLAG_TXE) || \
+ ((FLAG) == I2C_FLAG_RXNE) || \
+ ((FLAG) == I2C_FLAG_STOPF) || \
+ ((FLAG) == I2C_FLAG_ADD10) || \
+ ((FLAG) == I2C_FLAG_BTF) || \
+ ((FLAG) == I2C_FLAG_ADDR) || \
+ ((FLAG) == I2C_FLAG_SB) || \
+ ((FLAG) == I2C_FLAG_SMBALERT) || \
+ ((FLAG) == I2C_FLAG_TIMEOUT) || \
+ ((FLAG) == I2C_FLAG_WUFH) || \
+ ((FLAG) == I2C_FLAG_PECERR) || \
+ ((FLAG) == I2C_FLAG_OVR) || \
+ ((FLAG) == I2C_FLAG_AF) || \
+ ((FLAG) == I2C_FLAG_ARLO) || \
+ ((FLAG) == I2C_FLAG_BERR) || \
+ ((FLAG) == I2C_FLAG_DUALF) || \
+ ((FLAG) == I2C_FLAG_SMBHOST) || \
+ ((FLAG) == I2C_FLAG_SMBDEFAULT) || \
+ ((FLAG) == I2C_FLAG_GENCALL) || \
+ ((FLAG) == I2C_FLAG_TRA) || \
+ ((FLAG) == I2C_FLAG_BUSY) || \
+ ((FLAG) == I2C_FLAG_MSL))
+
+/**
+ * @brief Macro used by the assert function to check the I2C flags to clear.
+ */
+#define IS_I2C_CLEAR_FLAG(FLAG) ((((uint16_t)(FLAG) & (uint16_t)0xFD00) == 0x00) && ((uint16_t)(FLAG) != 0x00))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the different
+ * sensitivity values for the Interrupts
+ */
+#define IS_I2C_CONFIG_IT(IT) ((((uint16_t)(IT) & (uint16_t)0xFFF8) == 0x00) && ((uint16_t)(IT) != 0x00))
+
+/**
+ * @brief Macro used by the assert function to check the different I2C possible
+ * pending bits to clear by writing 0.
+ */
+#define IS_I2C_CLEAR_IT(IT) ((((uint16_t)(IT) & (uint16_t)0xDC00) == 0x00) && ((uint16_t)(IT) != 0x00))
+
+/**
+ * @brief Macro used by the assert function to check the different I2C possible pending bits.
+ */
+#define IS_I2C_GET_IT(IT) (((IT) == I2C_IT_OVR) ||\
+ ((IT) == I2C_IT_AF) ||\
+ ((IT) == I2C_IT_ARLO) ||\
+ ((IT) == I2C_IT_BERR) ||\
+ ((IT) == I2C_IT_TXE) ||\
+ ((IT) == I2C_IT_RXNE) ||\
+ ((IT) == I2C_IT_STOPF) ||\
+ ((IT) == I2C_IT_ADD10) ||\
+ ((IT) == I2C_IT_BTF) ||\
+ ((IT) == I2C_IT_ADDR) ||\
+ ((IT) == I2C_IT_PECERR) ||\
+ ((IT) == I2C_IT_TIMEOUT) ||\
+ ((IT) == I2C_IT_SMBALERT) ||\
+ ((IT) == I2C_IT_WUFH) ||\
+ ((IT) == I2C_IT_SB))
+/**
+ * @brief Macro used by the assert function to check the different I2C possible events.
+ */
+#define IS_I2C_EVENT(EVENT) (((EVENT) == I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED) || \
+ ((EVENT) == I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED) || \
+ ((EVENT) == I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED) || \
+ ((EVENT) == I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED) || \
+ ((EVENT) == I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED) || \
+ ((EVENT) == I2C_EVENT_SLAVE_BYTE_RECEIVED) || \
+ ((EVENT) == (I2C_EVENT_SLAVE_BYTE_RECEIVED | (uint16_t)I2C_FLAG_DUALF)) || \
+ ((EVENT) == (I2C_EVENT_SLAVE_BYTE_RECEIVED | (uint16_t)I2C_FLAG_GENCALL)) || \
+ ((EVENT) == I2C_EVENT_SLAVE_BYTE_TRANSMITTED) || \
+ ((EVENT) == (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | (uint16_t)I2C_FLAG_DUALF)) || \
+ ((EVENT) == (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | (uint16_t)I2C_FLAG_GENCALL)) || \
+ ((EVENT) == I2C_EVENT_SLAVE_ACK_FAILURE) || \
+ ((EVENT) == I2C_EVENT_SLAVE_STOP_DETECTED) || \
+ ((EVENT) == I2C_EVENT_MASTER_MODE_SELECT) || \
+ ((EVENT) == I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) || \
+ ((EVENT) == I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) || \
+ ((EVENT) == I2C_EVENT_MASTER_BYTE_RECEIVED) || \
+ ((EVENT) == I2C_EVENT_MASTER_BYTE_TRANSMITTED) || \
+ ((EVENT) == I2C_EVENT_MASTER_BYTE_TRANSMITTING) || \
+ ((EVENT) == I2C_EVENT_MASTER_MODE_ADDRESS10))
+/**
+ * @brief Macro used by the assert function to check the different I2C registers.
+ */
+#define IS_I2C_REGISTER(REGISTER) (((REGISTER) == I2C_Register_CR1) || \
+ ((REGISTER) == I2C_Register_CR2) || \
+ ((REGISTER) == I2C_Register_FREQR) || \
+ ((REGISTER) == I2C_Register_OARL) || \
+ ((REGISTER) == I2C_Register_OARH) || \
+ ((REGISTER) == I2C_Register_DR) || \
+ ((REGISTER) == I2C_Register_SR1) || \
+ ((REGISTER) == I2C_Register_SR2) || \
+ ((REGISTER) == I2C_Register_SR3) || \
+ ((REGISTER) == I2C_Register_ITR) || \
+ ((REGISTER) == I2C_Register_CCRL) || \
+ ((REGISTER) == I2C_Register_CCRH) || \
+ ((REGISTER) == I2C_Register_TRISER) || \
+ ((REGISTER) == I2C_Register_PECR))
+/**
+ * @brief Macro used by the assert function to check the different I2C possible own address.
+ */
+#define IS_I2C_OWN_ADDRESS(ADDRESS) ((ADDRESS) <= (uint16_t)0x03FF)
+
+/**
+ * @brief Macro used by the assert function to check the different I2C address
+ * The address must be even
+ */
+#define IS_I2C_ADDRESS(ADD) (((ADD) & (uint8_t)0x01) == (uint8_t)0x00)
+
+/**
+ * @brief Macro used by the assert function to check that I2C Output clock frequency must be between 1Hz and 400kHz.
+ */
+#define IS_I2C_OUTPUT_CLOCK_FREQ(FREQ) (((FREQ) >= (uint8_t)1) && ((FREQ) <= I2C_MAX_FAST_FREQ))
+
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+
+/* Function used to set the I2C configuration to the default reset state *****/
+void I2C_DeInit(I2C_TypeDef* I2Cx);
+
+/* Initialization and Configuration functions *********************************/
+void I2C_Init(I2C_TypeDef* I2Cx, uint32_t OutputClockFrequency, uint16_t OwnAddress,
+ I2C_Mode_TypeDef I2C_Mode, I2C_DutyCycle_TypeDef I2C_DutyCycle,
+ I2C_Ack_TypeDef I2C_Ack, I2C_AcknowledgedAddress_TypeDef I2C_AcknowledgedAddress);
+void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_ARPCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address);
+void I2C_DualAddressCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_AckPositionConfig(I2C_TypeDef* I2Cx, I2C_AckPosition_TypeDef I2C_AckPosition);
+void I2C_FastModeDutyCycleConfig(I2C_TypeDef* I2Cx, I2C_DutyCycle_TypeDef I2C_DutyCycle);
+void I2C_SMBusAlertConfig(I2C_TypeDef* I2Cx, I2C_SMBusAlert_TypeDef I2C_SMBusAlert);
+void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, I2C_Direction_TypeDef I2C_Direction);
+
+/* Data transfers functions ***************************************************/
+void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);
+uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);
+
+/* PEC management functions ***************************************************/
+void I2C_PECPositionConfig(I2C_TypeDef* I2Cx, I2C_PECPosition_TypeDef I2C_PECPosition);
+uint8_t I2C_GetPEC(I2C_TypeDef* I2Cx);
+void I2C_TransmitPEC(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_CalculatePEC(I2C_TypeDef* I2Cx, FunctionalState NewState);
+
+/* DMA transfers management functions *****************************************/
+void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
+
+/* Interrupts, events and flags management functions **************************/
+
+void I2C_ITConfig(I2C_TypeDef* I2Cx, I2C_IT_TypeDef I2C_IT, FunctionalState NewState);
+uint8_t I2C_ReadRegister(I2C_TypeDef* I2Cx, I2C_Register_TypeDef I2C_Register);
+
+/**
+ * @brief
+ *
+@verbatim
+================================================================================
+ I2C State Monitoring Functions
+================================================================================
+ This I2C driver provides three different ways for I2C state monitoring
+ depending on the application requirements and constraints:
+
+
+ 1) Basic state monitoring:
+ Using I2C_CheckEvent() function:
+ It compares the status registers (SR1, SR2 and SR3) content to a given event
+ (can be the combination of one or more flags).
+ It returns SUCCESS if the current status includes the given flags
+ and returns ERROR if one or more flags are missing in the current status.
+ - When to use:
+ - This function is suitable for most applications as well as for startup
+ activity since the events are fully described in the product reference manual
+ (RM0031).
+ - It is also suitable for users who need to define their own events.
+ - Limitations:
+ - If an error occurs (ie. error flags are set besides to the monitored flags),
+ the I2C_CheckEvent() function may return SUCCESS despite the communication
+ hold or corrupted real state.
+ In this case, it is advised to use error interrupts to monitor the error
+ events and handle them in the interrupt IRQ handler.
+
+ @note
+ For error management, it is advised to use the following functions:
+ - I2C_ITConfig() to configure and enable the error interrupts (I2C_IT_ERR).
+ - I2Cx_IRQHandler() which is called when the I2C interrupts occur.
+ Where x is the peripheral instance (I2C1,...)
+ - I2C_GetFlagStatus() or I2C_GetITStatus() to be called into the
+ I2Cx_IRQHandler() function in order to determine which error occurred.
+ - I2C_ClearFlag() or I2C_ClearITPendingBit() and/or I2C_SoftwareResetCmd()
+ and/or I2C_GenerateStop() in order to clear the error flag and
+ source and return to correct communication status.
+
+
+ 2) Advanced state monitoring:
+ Using the function I2C_GetLastEvent() which returns the image of both SR1
+ & SR3 status registers in a single word (uint16_t) (Status Register 3 value
+ is shifted left by 8 bits and concatenated to Status Register 1).
+ - When to use:
+ - This function is suitable for the same applications above but it allows to
+ overcome the limitations of I2C_GetFlagStatus() function (see below).
+ The returned value could be compared to events already defined in the
+ library (stm8l15x_i2c.h) or to custom values defined by user.
+ - This function is suitable when multiple flags are monitored at the same time.
+ - At the opposite of I2C_CheckEvent() function, this function allows user to
+ choose when an event is accepted (when all events flags are set and no
+ other flags are set or just when the needed flags are set like
+ I2C_CheckEvent() function).
+ - Limitations:
+ - User may need to define his own events.
+ - Same remark concerning the error management is applicable for this
+ function if user decides to check only regular communication flags (and
+ ignores error flags).
+
+
+ 3) Flag-based state monitoring:
+ Using the function I2C_GetFlagStatus() which simply returns the status of
+ one single flag (ie. I2C_FLAG_RXNE ...).
+ - When to use:
+ - This function could be used for specific applications or in debug phase.
+ - It is suitable when only one flag checking is needed (most I2C events
+ are monitored through multiple flags).
+ - Limitations:
+ - When calling this function, the Status register is accessed. Some flags are
+ cleared when the status register is accessed. So checking the status
+ of one Flag, may clear other ones.
+ - Function may need to be called twice or more in order to monitor one
+ single event.
+
+
+@endverbatim
+ *
+ */
+
+/**
+ ===============================================================================
+ 1. Basic state monitoring
+ ===============================================================================
+*/
+ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, I2C_Event_TypeDef I2C_Event);
+/**
+ ===============================================================================
+ 2. Advanced state monitoring
+ ===============================================================================
+ */
+I2C_Event_TypeDef I2C_GetLastEvent(I2C_TypeDef* I2Cx);
+/**
+ ===============================================================================
+ 3. Flag-based state monitoring
+ ===============================================================================
+ */
+FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, I2C_FLAG_TypeDef I2C_FLAG);
+
+void I2C_ClearFlag(I2C_TypeDef* I2Cx, I2C_FLAG_TypeDef I2C_FLAG);
+ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, I2C_IT_TypeDef I2C_IT);
+void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, I2C_IT_TypeDef I2C_IT);
+
+#endif /* __STM8L15x_I2C_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_irtim.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_irtim.h
new file mode 100644
index 00000000..e6f93227
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_irtim.h
@@ -0,0 +1,68 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_irtim.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the IRTIM firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_IRTIM_H
+#define __STM8L15x_IRTIM_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup IRTIM
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/* IRTIM configuration ********************************************************/
+void IRTIM_DeInit(void);
+void IRTIM_Cmd(FunctionalState NewState);
+void IRTIM_HighSinkODCmd(FunctionalState NewState);
+
+/* IRITM status management ****************************************************/
+FunctionalState IRTIM_GetStatus(void);
+FunctionalState IRTIM_GetHighSinkODStatus(void);
+
+/**
+ * @}
+ */
+
+#endif /* __STM8L15x_IRTIM_H */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_itc.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_itc.h
new file mode 100644
index 00000000..157769c4
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_itc.h
@@ -0,0 +1,272 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_itc.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the ITC firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_ITC_H
+#define __STM8L15x_ITC_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup ITC
+ * @{
+ */
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup ITC_Exported_Types
+ * @{
+ */
+
+/** @defgroup ITC_Interrupt_Lines_selection
+ * @{
+ */
+typedef enum {
+ FLASH_IRQn = (uint8_t)1, /*!< Flash interrupt */
+ DMA1_CHANNEL0_1_IRQn = (uint8_t)2, /*!< DMA Channels 0/1 */
+ DMA1_CHANNEL2_3_IRQn = (uint8_t)3, /*!< DMA Channels 2/3 */
+ EXTIE_F_PVD_IRQn = (uint8_t)5, /*!< GPIOE/F and PVD interrupt */
+ EXTI0_IRQn = (uint8_t)8, /*!< PIN0 interrupt */
+ EXTI1_IRQn = (uint8_t)9, /*!< PIN1 interrupt */
+ EXTI2_IRQn = (uint8_t)10, /*!< PIN2 interrupt */
+ EXTI3_IRQn = (uint8_t)11, /*!< PIN3 interrupt */
+ EXTI4_IRQn = (uint8_t)12, /*!< PIN4 interrupt */
+ EXTI5_IRQn = (uint8_t)13, /*!< PIN5 interrupt */
+ EXTI6_IRQn = (uint8_t)14, /*!< PIN6 interrupt */
+ EXTI7_IRQn = (uint8_t)15, /*!< PIN7 interrupt */
+ ADC1_COMP_IRQn = (uint8_t)18, /*!< ADC1/Comparator interrupt */
+ TIM4_UPD_OVF_TRG_IRQn = (uint8_t)25, /*!< TIM4 Update/Overflow/Trigger interrupt */
+ SPI1_IRQn = (uint8_t)26, /*!< SPI1 interrupt */
+#if defined (STM8L15X_MD) || defined (STM8L05X_MD_VL) || defined (STM8AL31_L_MD)
+ RTC_IRQn = (uint8_t)4, /*!< RTC interrupt */
+ EXTIB_IRQn = (uint8_t)6, /*!< GPIOB interrupt */
+ EXTID_IRQn = (uint8_t)7, /*!< GPIOD interrupt */
+ LCD_IRQn = (uint8_t)16, /*!< LCD Driver interrupt */
+ SWITCH_CSS_BREAK_DAC_IRQn = (uint8_t)17, /*!< Clock switch/CSS interrupt/TIM1 Break /DAC interrupt */
+ TIM2_UPD_OVF_TRG_BRK_IRQn = (uint8_t)19, /*!< TIM2 Update/Overflow/Trigger/Break interrupt*/
+ TIM2_CC_IRQn = (uint8_t)20, /*!< TIM2 input captute/output compare interrupt */
+ TIM3_UPD_OVF_TRG_BRK_IRQn = (uint8_t)21, /*!< TIM3 Update/Overflow/Trigger/Break interrupt */
+ TIM3_CC_IRQn = (uint8_t)22, /*!< TIM3 capture/compare interrupt */
+ TIM1_UPD_OVF_TRG_IRQn = (uint8_t)23, /*!< TIM1 TIM1 Update/Overflow/Trigger interrupt */
+ TIM1_CC_IRQn = (uint8_t)24, /*!< TIM1 capture/compare interrupt */
+ USART1_TX_IRQn = (uint8_t)27, /*!< USART1 TX interrupt */
+ USART1_RX_IRQn = (uint8_t)28, /*!< USART1 RX interrupt */
+ I2C1_IRQn = (uint8_t)29 /*!< I2C1 interrupt */
+#elif defined (STM8L15X_LD) || defined (STM8L05X_LD_VL)
+ RTC_CSSLSE_IRQn = (uint8_t)4, /*!< RTC / CSSLSE interrupt */
+ EXTIB_IRQn = (uint8_t)6, /*!< GPIOB interrupt */
+ EXTID_IRQn = (uint8_t)7, /*!< GPIOD interrupt */
+ SWITCH_CSS_IRQn = (uint8_t)17, /*!< Clock switch/CSS interrupt/TIM1 Break /DAC interrupt */
+ TIM2_UPD_OVF_TRG_BRK_IRQn = (uint8_t)19, /*!< TIM2 Update/Overflow/Trigger/Break interrupt*/
+ TIM2_CC_IRQn = (uint8_t)20, /*!< TIM2 input captute/output compare interrupt */
+ TIM3_UPD_OVF_TRG_BRK_IRQn = (uint8_t)21, /*!< TIM3 Update/Overflow/Trigger/Break interrupt */
+ TIM3_CC_IRQn = (uint8_t)22, /*!< TIM3 capture/compare interrupt */
+ USART1_TX_IRQn = (uint8_t)27, /*!< USART1 TX interrupt */
+ USART1_RX_IRQn = (uint8_t)28, /*!< USART1 RX interrupt */
+ I2C1_IRQn = (uint8_t)29 /*!< I2C1 interrupt */
+#elif defined (STM8L15X_HD) || defined (STM8L15X_MDP) || defined (STM8L05X_HD_VL)
+ RTC_CSSLSE_IRQn = (uint8_t)4, /*!< RTC / CSSLSE interrupt */
+ EXTIB_G_IRQn = (uint8_t)6, /*!< GPIOB / G interrupt */
+ EXTID_H_IRQn = (uint8_t)7, /*!< GPIOD / H interrupt */
+ LCD_AES_IRQn = (uint8_t)16, /*!< LCD / AES interrupt */
+ SWITCH_CSS_BREAK_DAC_IRQn = (uint8_t)17, /*!< Clock switch/CSS interrupt/TIM1 Break /DAC interrupt */
+ TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQn = (uint8_t)19, /*!< TIM2 Update/Overflow/Trigger/Break /USART2 TX interrupt*/
+ TIM2_CC_USART2_RX_IRQn = (uint8_t)20, /*!< TIM2 capture/compare / USART2 RX interrupt */
+ TIM3_UPD_OVF_TRG_BRK_USART3_TX_IRQn = (uint8_t)21, /*!< TIM3 Update/Overflow/Trigger/Break / USART3 TX interrupt */
+ TIM3_CC_USART3_RX_IRQn = (uint8_t)22, /*!< TIM3 capture/compare / USART3 RX interrupt */
+ TIM1_UPD_OVF_TRG_IRQn = (uint8_t)23, /*!< TIM1 TIM1 Update/Overflow/Trigger interrupt */
+ TIM1_CC_IRQn = (uint8_t)24, /*!< TIM1 capture/compare interrupt */
+ USART1_TX_TIM5_UPD_OVF_TRG_BRK_IRQn = (uint8_t)27, /*!< USART1 TX / TIM5 Update/Overflow/Trigger/Break interrupt */
+ USART1_RX_TIM5_CC_IRQn = (uint8_t)28, /*!< USART1 RX / TIM5 capture/compare interrupt */
+ I2C1_SPI2_IRQn = (uint8_t)29 /*!< I2C1 / SPI2 interrupt */
+#endif /* STM8L15X_MD */
+}IRQn_TypeDef;
+
+#if defined (STM8L15X_MD) || defined (STM8L05X_MD_VL) || defined (STM8AL31_L_MD)
+ #define IS_ITC_IRQ(Irq) (((Irq) == FLASH_IRQn) || \
+ ((Irq) == DMA1_CHANNEL0_1_IRQn) || \
+ ((Irq) == DMA1_CHANNEL2_3_IRQn) || \
+ ((Irq) == RTC_IRQn) || \
+ ((Irq) == EXTIE_F_PVD_IRQn) || \
+ ((Irq) == EXTIB_IRQn) || \
+ ((Irq) == EXTID_IRQn) || \
+ ((Irq) == EXTI0_IRQn) || \
+ ((Irq) == EXTI1_IRQn) || \
+ ((Irq) == EXTI2_IRQn) || \
+ ((Irq) == EXTI3_IRQn) || \
+ ((Irq) == EXTI4_IRQn) || \
+ ((Irq) == EXTI5_IRQn) || \
+ ((Irq) == EXTI6_IRQn) || \
+ ((Irq) == EXTI7_IRQn) || \
+ ((Irq) == LCD_IRQn) || \
+ ((Irq) == SWITCH_CSS_BREAK_DAC_IRQn) || \
+ ((Irq) == ADC1_COMP_IRQn) || \
+ ((Irq) == TIM2_UPD_OVF_TRG_BRK_IRQn) || \
+ ((Irq) == TIM2_CC_IRQn) || \
+ ((Irq) == TIM3_UPD_OVF_TRG_BRK_IRQn) || \
+ ((Irq) == TIM3_CC_IRQn) || \
+ ((Irq) == TIM1_UPD_OVF_TRG_IRQn) || \
+ ((Irq) == TIM1_CC_IRQn) || \
+ ((Irq) == TIM4_UPD_OVF_TRG_IRQn) || \
+ ((Irq) == SPI1_IRQn) || \
+ ((Irq) == USART1_TX_IRQn) || \
+ ((Irq) == USART1_RX_IRQn) || \
+ ((Irq) == I2C1_IRQn))
+#elif defined (STM8L15X_LD) || defined (STM8L05X_LD_VL)
+ #define IS_ITC_IRQ(Irq) (((Irq) == FLASH_IRQn) || \
+ ((Irq) == DMA1_CHANNEL0_1_IRQn) || \
+ ((Irq) == DMA1_CHANNEL2_3_IRQn) || \
+ ((Irq) == RTC_CSSLSE_IRQn) || \
+ ((Irq) == EXTIE_F_PVD_IRQn) || \
+ ((Irq) == EXTIB_IRQn) || \
+ ((Irq) == EXTID_IRQn) || \
+ ((Irq) == EXTI0_IRQn) || \
+ ((Irq) == EXTI1_IRQn) || \
+ ((Irq) == EXTI2_IRQn) || \
+ ((Irq) == EXTI3_IRQn) || \
+ ((Irq) == EXTI4_IRQn) || \
+ ((Irq) == EXTI5_IRQn) || \
+ ((Irq) == EXTI6_IRQn) || \
+ ((Irq) == EXTI7_IRQn) || \
+ ((Irq) == SWITCH_CSS_IRQn) || \
+ ((Irq) == ADC1_COMP_IRQn) || \
+ ((Irq) == TIM2_UPD_OVF_TRG_BRK_IRQn) || \
+ ((Irq) == TIM2_CC_IRQn) || \
+ ((Irq) == TIM3_UPD_OVF_TRG_BRK_IRQn) || \
+ ((Irq) == TIM3_CC_IRQn) || \
+ ((Irq) == TIM4_UPD_OVF_TRG_IRQn) || \
+ ((Irq) == SPI1_IRQn) || \
+ ((Irq) == USART1_TX_IRQn) || \
+ ((Irq) == USART1_RX_IRQn) || \
+ ((Irq) == I2C1_IRQn))
+#elif defined (STM8L15X_HD) || defined (STM8L15X_MDP) || defined (STM8L05X_HD_VL)
+ #define IS_ITC_IRQ(Irq) (((Irq) == FLASH_IRQn) || \
+ ((Irq) == DMA1_CHANNEL0_1_IRQn) || \
+ ((Irq) == DMA1_CHANNEL2_3_IRQn) || \
+ ((Irq) == RTC_CSSLSE_IRQn) || \
+ ((Irq) == EXTIE_F_PVD_IRQn) || \
+ ((Irq) == EXTIB_G_IRQn) || \
+ ((Irq) == EXTID_H_IRQn) || \
+ ((Irq) == EXTI0_IRQn) || \
+ ((Irq) == EXTI1_IRQn) || \
+ ((Irq) == EXTI2_IRQn) || \
+ ((Irq) == EXTI3_IRQn) || \
+ ((Irq) == EXTI4_IRQn) || \
+ ((Irq) == EXTI5_IRQn) || \
+ ((Irq) == EXTI6_IRQn) || \
+ ((Irq) == EXTI7_IRQn) || \
+ ((Irq) == LCD_AES_IRQn) || \
+ ((Irq) == SWITCH_CSS_BREAK_DAC_IRQn) || \
+ ((Irq) == ADC1_COMP_IRQn) || \
+ ((Irq) == TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQn) || \
+ ((Irq) == TIM2_CC_USART2_RX_IRQn) || \
+ ((Irq) == TIM3_UPD_OVF_TRG_BRK_USART3_TX_IRQn) || \
+ ((Irq) == TIM3_CC_USART3_RX_IRQn) || \
+ ((Irq) == TIM1_UPD_OVF_TRG_IRQn) || \
+ ((Irq) == TIM1_CC_IRQn) || \
+ ((Irq) == TIM4_UPD_OVF_TRG_IRQn) || \
+ ((Irq) == SPI1_IRQn) || \
+ ((Irq) == USART1_TX_TIM5_UPD_OVF_TRG_BRK_IRQn) || \
+ ((Irq) == USART1_RX_TIM5_CC_IRQn) || \
+ ((Irq) == I2C1_SPI2_IRQn))
+#endif /* STM8L15X_MD */
+
+/**
+ * @}
+ */
+
+/** @defgroup ITC_Priority_Level_selection
+ * @{
+ */
+typedef enum {
+ ITC_PriorityLevel_0 = (uint8_t)0x02, /*!< Software priority level 0 (cannot be written) */
+ ITC_PriorityLevel_1 = (uint8_t)0x01, /*!< Software priority level 1 */
+ ITC_PriorityLevel_2 = (uint8_t)0x00, /*!< Software priority level 2 */
+ ITC_PriorityLevel_3 = (uint8_t)0x03 /*!< Software priority level 3 */
+} ITC_PriorityLevel_TypeDef;
+
+#define IS_ITC_PRIORITY(PriorityValue) \
+ (((PriorityValue) == ITC_PriorityLevel_0) || \
+ ((PriorityValue) == ITC_PriorityLevel_1) || \
+ ((PriorityValue) == ITC_PriorityLevel_2) || \
+ ((PriorityValue) == ITC_PriorityLevel_3))
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup ITC_Exported_Constants
+ * @{
+ */
+
+#define CPU_SOFT_INT_DISABLED ((uint8_t)0x28) /*!< Mask for I1 and I0 bits in CPU_CC register */
+
+/**
+ * @}
+ */
+
+/* Exported macros -----------------------------------------------------------*/
+
+/** @defgroup ITC_Exported_Constants
+ * @{
+ */
+#define IS_ITC_INTERRUPTS_DISABLED (ITC_GetSoftIntStatus() == CPU_SOFT_INT_DISABLED)
+
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+/* Function used to set the ITC configuration to the default reset state ******/
+void ITC_DeInit(void);
+
+/* ITC configuration and management functions ******/
+uint8_t ITC_GetCPUCC(void);
+uint8_t ITC_GetSoftIntStatus(void);
+void ITC_SetSoftwarePriority(IRQn_TypeDef IRQn, ITC_PriorityLevel_TypeDef ITC_PriorityLevel);
+ITC_PriorityLevel_TypeDef ITC_GetSoftwarePriority(IRQn_TypeDef IRQn);
+
+#endif /* __STM8L15x_ITC_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_iwdg.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_iwdg.h
new file mode 100644
index 00000000..3463a1f0
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_iwdg.h
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * @file stm8l15x_iwdg.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the IWDG
+ * firmware library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_IWDG_H
+#define __STM8L15x_IWDG_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup IWDG
+ * @{
+ */
+
+/* Exported variables ------------------------------------------------------- */
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup IWDG_Exported_Constants
+ * @{
+ */
+
+/** @defgroup IWDG_KeyRefresh
+ * @{
+ */
+#define IWDG_KEY_REFRESH ((uint8_t)0xAA) /*!< This value written in the Key
+ register prevent the watchdog reset */
+/**
+ * @}
+ */
+
+/** @defgroup IWDG_KeyEnable
+ * @{
+ */
+#define IWDG_KEY_ENABLE ((uint8_t)0xCC) /*!< This value written in the Key
+ register start the watchdog counting down*/
+/**
+ * @}
+ */
+/**
+ * @}
+ */
+
+/* Exported macros -----------------------------------------------------------*/
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup IWDG_Exported_Types
+ * @{
+ */
+
+/** @defgroup IWDG_WriteAccess
+ * @{
+ */
+typedef enum
+{
+ IWDG_WriteAccess_Enable = (uint8_t)0x55,
+ IWDG_WriteAccess_Disable = (uint8_t)0x00
+} IWDG_WriteAccess_TypeDef;
+#define IS_IWDG_WRITE_ACCESS_MODE(MODE) (((MODE) == IWDG_WriteAccess_Enable) || \
+ ((MODE) == IWDG_WriteAccess_Disable))
+/**
+ * @}
+ */
+
+/** @defgroup IWDG_prescaler
+ * @{
+ */
+typedef enum
+{
+ IWDG_Prescaler_4 = (uint8_t)0x00, /*!< Used to set prescaler register to 4 */
+ IWDG_Prescaler_8 = (uint8_t)0x01, /*!< Used to set prescaler register to 8 */
+ IWDG_Prescaler_16 = (uint8_t)0x02, /*!< Used to set prescaler register to 16 */
+ IWDG_Prescaler_32 = (uint8_t)0x03, /*!< Used to set prescaler register to 32 */
+ IWDG_Prescaler_64 = (uint8_t)0x04, /*!< Used to set prescaler register to 64 */
+ IWDG_Prescaler_128 = (uint8_t)0x05, /*!< Used to set prescaler register to 128 */
+ IWDG_Prescaler_256 = (uint8_t)0x06 /*!< Used to set prescaler register to 256 */
+} IWDG_Prescaler_TypeDef;
+#define IS_IWDG_PRESCALER_VALUE(VALUE) (((VALUE) == IWDG_Prescaler_4) || \
+ ((VALUE) == IWDG_Prescaler_8) || \
+ ((VALUE) == IWDG_Prescaler_16) || \
+ ((VALUE) == IWDG_Prescaler_32) || \
+ ((VALUE) == IWDG_Prescaler_64) || \
+ ((VALUE) == IWDG_Prescaler_128) || \
+ ((VALUE) == IWDG_Prescaler_256))
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+/* Prescaler and Counter configuration functions ******************************/
+void IWDG_WriteAccessCmd(IWDG_WriteAccess_TypeDef IWDG_WriteAccess);
+void IWDG_SetPrescaler(IWDG_Prescaler_TypeDef IWDG_Prescaler);
+void IWDG_SetReload(uint8_t IWDG_Reload);
+void IWDG_ReloadCounter(void);
+
+/* IWDG activation function ***************************************************/
+void IWDG_Enable(void);
+
+#endif /* __STM8L15x_IWDG_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_lcd.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_lcd.h
new file mode 100644
index 00000000..53b27a1e
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_lcd.h
@@ -0,0 +1,473 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_lcd.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the LCD firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_LCD_H
+#define __STM8L15x_LCD_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup LCD
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup LCD_Exported_Types
+ * @{
+ */
+
+/** @defgroup LCD_Duty
+ * @brief element values correspond to the bits position
+ * @{
+ */
+
+typedef enum {
+ LCD_Duty_Static = (uint8_t)0x00, /*!< Static duty */
+ LCD_Duty_1_2 = (uint8_t)0x02, /*!< 1/2 duty */
+ LCD_Duty_1_3 = (uint8_t)0x04, /*!< 1/3 duty */
+ LCD_Duty_1_4 = (uint8_t)0x06, /*!< 1/4 duty */
+ LCD_Duty_1_8 = (uint8_t)0x20 /*!< 1/8 duty */
+} LCD_Duty_TypeDef;
+
+#define IS_LCD_DUTY(DUTY) (((DUTY) == LCD_Duty_Static) || ((DUTY) == LCD_Duty_1_2) || \
+ ((DUTY) == LCD_Duty_1_3) || ((DUTY) == LCD_Duty_1_4) || \
+ ((DUTY) == LCD_Duty_1_8))
+/**
+ * @}
+ */
+
+/** @defgroup LCD_Bias
+ * @brief element values correspond to the bits position
+ * @{
+ */
+typedef enum {
+ LCD_Bias_1_4 = (uint8_t)0x10, /*!< 1/4 bias */
+ LCD_Bias_1_3 = (uint8_t)0x00, /*!< 1/3 bias */
+ LCD_Bias_1_2 = (uint8_t)0x01 /*!< 1/2 bias */
+} LCD_Bias_TypeDef;
+
+#define IS_LCD_BIAS(BIAS) (((BIAS) == LCD_Bias_1_4) || \
+ ((BIAS) == LCD_Bias_1_3) || \
+ ((BIAS) == LCD_Bias_1_2))
+
+/**
+ * @}
+ */
+
+/** @defgroup LCD_Clock_Prescaler
+ * @brief element values correspond to the bits position
+ * @{
+ */
+typedef enum {
+ LCD_Prescaler_1 = (uint8_t)0x00, /*!< CLKprescaler = ClKinput */
+ LCD_Prescaler_2 = (uint8_t)0x10, /*!< CLKprescaler = ClKinput/2 */
+ LCD_Prescaler_4 = (uint8_t)0x20, /*!< CLKprescaler = ClKinput/4 */
+ LCD_Prescaler_8 = (uint8_t)0x30, /*!< CLKprescaler = ClKinput/8 */
+ LCD_Prescaler_16 = (uint8_t)0x40, /*!< CLKprescaler = ClKinput/16 */
+ LCD_Prescaler_32 = (uint8_t)0x50, /*!< CLKprescaler = ClKinput/32 */
+ LCD_Prescaler_64 = (uint8_t)0x60, /*!< CLKprescaler = ClKinput/64 */
+ LCD_Prescaler_128 = (uint8_t)0x70, /*!< CLKprescaler = ClKinput/128 */
+ LCD_Prescaler_256 = (uint8_t)0x80, /*!< CLKprescaler = ClKinput/256 */
+ LCD_Prescaler_512 = (uint8_t)0x90, /*!< CLKprescaler = ClKinput/512 */
+ LCD_Prescaler_1024 = (uint8_t)0xA0, /*!< CLKprescaler = ClKinput/1024 */
+ LCD_Prescaler_2048 = (uint8_t)0xB0, /*!< CLKprescaler = ClKinput/2048 */
+ LCD_Prescaler_4096 = (uint8_t)0xC0, /*!< CLKprescaler = ClKinput/4096 */
+ LCD_Prescaler_8192 = (uint8_t)0xD0, /*!< CLKprescaler = ClKinput/8192 */
+ LCD_Prescaler_16384 = (uint8_t)0xE0, /*!< CLKprescaler = ClKinput/16384 */
+ LCD_Prescaler_32768 = (uint8_t)0xF0 /*!< CLKprescaler = ClKinput/32768 */
+} LCD_Prescaler_TypeDef;
+
+#define IS_LCD_CLOCK_PRESCALER(PRESCALER) (((PRESCALER) == LCD_Prescaler_1) || \
+ ((PRESCALER) == LCD_Prescaler_2) || \
+ ((PRESCALER) == LCD_Prescaler_4) || \
+ ((PRESCALER) == LCD_Prescaler_8) || \
+ ((PRESCALER) == LCD_Prescaler_16) || \
+ ((PRESCALER) == LCD_Prescaler_32) || \
+ ((PRESCALER) == LCD_Prescaler_64) || \
+ ((PRESCALER) == LCD_Prescaler_128) || \
+ ((PRESCALER) == LCD_Prescaler_256) || \
+ ((PRESCALER) == LCD_Prescaler_512) || \
+ ((PRESCALER) == LCD_Prescaler_1024) || \
+ ((PRESCALER) == LCD_Prescaler_2048) || \
+ ((PRESCALER) == LCD_Prescaler_4096) || \
+ ((PRESCALER) == LCD_Prescaler_8192) || \
+ ((PRESCALER) == LCD_Prescaler_16384) || \
+ ((PRESCALER) == LCD_Prescaler_32768))
+
+/**
+ * @}
+ */
+
+/** @defgroup LCD_Clock_Divider
+ * @brief element values correspond to the bits position
+ * @{
+ */
+typedef enum {
+ LCD_Divider_16 = (uint8_t)0x00, /*!< LCD frequency = CLKprescaler/16 */
+ LCD_Divider_17 = (uint8_t)0x01, /*!< LCD frequency = CLKprescaler/17 */
+ LCD_Divider_18 = (uint8_t)0x02, /*!< LCD frequency = CLKprescaler/18 */
+ LCD_Divider_19 = (uint8_t)0x03, /*!< LCD frequency = CLKprescaler/19 */
+ LCD_Divider_20 = (uint8_t)0x04, /*!< LCD frequency = CLKprescaler/20 */
+ LCD_Divider_21 = (uint8_t)0x05, /*!< LCD frequency = CLKprescaler/21 */
+ LCD_Divider_22 = (uint8_t)0x06, /*!< LCD frequency = CLKprescaler/22 */
+ LCD_Divider_23 = (uint8_t)0x07, /*!< LCD frequency = CLKprescaler/23 */
+ LCD_Divider_24 = (uint8_t)0x08, /*!< LCD frequency = CLKprescaler/24 */
+ LCD_Divider_25 = (uint8_t)0x09, /*!< LCD frequency = CLKprescaler/25 */
+ LCD_Divider_26 = (uint8_t)0x0A, /*!< LCD frequency = CLKprescaler/26 */
+ LCD_Divider_27 = (uint8_t)0x0B, /*!< LCD frequency = CLKprescaler/27 */
+ LCD_Divider_28 = (uint8_t)0x0C, /*!< LCD frequency = CLKprescaler/28 */
+ LCD_Divider_29 = (uint8_t)0x0D, /*!< LCD frequency = CLKprescaler/29 */
+ LCD_Divider_30 = (uint8_t)0x0E, /*!< LCD frequency = CLKprescaler/30 */
+ LCD_Divider_31 = (uint8_t)0x0F /*!< LCD frequency = CLKprescaler/31 */
+} LCD_Divider_TypeDef;
+
+#define IS_LCD_CLOCK_DIVIDER(DIVIDER) (((DIVIDER) == LCD_Divider_16) || \
+ ((DIVIDER) == LCD_Divider_17) || \
+ ((DIVIDER) == LCD_Divider_18) || \
+ ((DIVIDER) == LCD_Divider_19) || \
+ ((DIVIDER) == LCD_Divider_20) || \
+ ((DIVIDER) == LCD_Divider_21) || \
+ ((DIVIDER) == LCD_Divider_22) || \
+ ((DIVIDER) == LCD_Divider_23) || \
+ ((DIVIDER) == LCD_Divider_24) || \
+ ((DIVIDER) == LCD_Divider_25) || \
+ ((DIVIDER) == LCD_Divider_26) || \
+ ((DIVIDER) == LCD_Divider_27) || \
+ ((DIVIDER) == LCD_Divider_28) || \
+ ((DIVIDER) == LCD_Divider_29) || \
+ ((DIVIDER) == LCD_Divider_30) || \
+ ((DIVIDER) == LCD_Divider_31))
+
+/**
+ * @}
+ */
+
+/** @defgroup LCD_Contrast
+ * @brief element values correspond to the bits position
+ * @{
+ */
+typedef enum {
+ LCD_Contrast_Level_0 = (uint8_t)0x00, /*!< Medium Density / High Density Maximum Voltage = 2.60V / 2.60V */
+ LCD_Contrast_Level_1 = (uint8_t)0x02, /*!< Medium Density / High Density Maximum Voltage = 2.70V / 2.73V */
+ LCD_Contrast_Level_2 = (uint8_t)0x04, /*!< Medium Density / High Density Maximum Voltage = 2.80V / 2.86V */
+ LCD_Contrast_Level_3 = (uint8_t)0x06, /*!< Medium Density / High Density Maximum Voltage = 2.90V / 2.99V */
+ LCD_Contrast_Level_4 = (uint8_t)0x08, /*!< Medium Density / High Density Maximum Voltage = 3.00V / 3.12V */
+ LCD_Contrast_Level_5 = (uint8_t)0x0A, /*!< Medium Density / High Density Maximum Voltage = 3.10V / 3.25V */
+ LCD_Contrast_Level_6 = (uint8_t)0x0C, /*!< Medium Density / High Density Maximum Voltage = 3.20V / 3.38V */
+ LCD_Contrast_Level_7 = (uint8_t)0x0E /*!< Medium Density / High Density Maximum Voltage = 3.30V / 3.51V */
+} LCD_Contrast_TypeDef;
+
+#define IS_LCD_CONTRAST(CONTRAST) (((CONTRAST) == LCD_Contrast_Level_0) || \
+ ((CONTRAST) == LCD_Contrast_Level_1) || \
+ ((CONTRAST) == LCD_Contrast_Level_2) || \
+ ((CONTRAST) == LCD_Contrast_Level_3) || \
+ ((CONTRAST) == LCD_Contrast_Level_4) || \
+ ((CONTRAST) == LCD_Contrast_Level_5) || \
+ ((CONTRAST) == LCD_Contrast_Level_6) || \
+ ((CONTRAST) == LCD_Contrast_Level_7))
+
+/**
+ * @}
+ */
+
+/** @defgroup LCD_Voltage_Source
+ * @brief element values correspond to the bits position
+ * @{
+ */
+typedef enum {
+ LCD_VoltageSource_Internal = (uint8_t)0x00, /*!< Internal voltage source for the LCD */
+ LCD_VoltageSource_External = (uint8_t)0x01 /*!< External voltage source for the LCD */
+} LCD_VoltageSource_TypeDef;
+
+#define IS_LCD_VOLTAGE_SOURCE(SOURCE) (((SOURCE) == LCD_VoltageSource_Internal) || \
+ ((SOURCE) == LCD_VoltageSource_External))
+
+/**
+ * @}
+ */
+
+/** @defgroup LCD_Pulse_On_Duration
+ * @brief element values correspond to the bits position
+ * @{
+ */
+typedef enum {
+ LCD_PulseOnDuration_0 = (uint8_t)0x00, /*!< Pulse on duration = 0/CLKprescaler */
+ LCD_PulseOnDuration_1 = (uint8_t)0x20, /*!< Pulse on duration = 1/CLKprescaler */
+ LCD_PulseOnDuration_2 = (uint8_t)0x40, /*!< Pulse on duration = 2/CLKprescaler */
+ LCD_PulseOnDuration_3 = (uint8_t)0x60, /*!< Pulse on duration = 3/CLKprescaler */
+ LCD_PulseOnDuration_4 = (uint8_t)0x80, /*!< Pulse on duration = 4/CLKprescaler */
+ LCD_PulseOnDuration_5 = (uint8_t)0xA0, /*!< Pulse on duration = 5/CLKprescaler */
+ LCD_PulseOnDuration_6 = (uint8_t)0xC0, /*!< Pulse on duration = 6/CLKprescaler */
+ LCD_PulseOnDuration_7 = (uint8_t)0xE0 /*!< Pulse on duration = 7/CLKprescaler */
+} LCD_PulseOnDuration_TypeDef;
+
+#define IS_LCD_PULSE_DURATION(DURATION) (((DURATION) == LCD_PulseOnDuration_0) || \
+ ((DURATION) == LCD_PulseOnDuration_1) || \
+ ((DURATION) == LCD_PulseOnDuration_2) || \
+ ((DURATION) == LCD_PulseOnDuration_3) || \
+ ((DURATION) == LCD_PulseOnDuration_4) || \
+ ((DURATION) == LCD_PulseOnDuration_5) || \
+ ((DURATION) == LCD_PulseOnDuration_6) || \
+ ((DURATION) == LCD_PulseOnDuration_7))
+
+/**
+ * @}
+ */
+
+/** @defgroup LCD_Dead_Time
+ * @brief element values correspond to the bits position
+ * @{
+ */
+typedef enum {
+ LCD_DeadTime_0 = (uint8_t)0x00, /*!< No dead Time */
+ LCD_DeadTime_1 = (uint8_t)0x01, /*!< One Phase between different couple of Frame */
+ LCD_DeadTime_2 = (uint8_t)0x02, /*!< Two Phase between different couple of Frame */
+ LCD_DeadTime_3 = (uint8_t)0x03, /*!< Tree Phase between different couple of Frame */
+ LCD_DeadTime_4 = (uint8_t)0x04, /*!< Four Phase between different couple of Frame */
+ LCD_DeadTime_5 = (uint8_t)0x05, /*!< Five Phase between different couple of Frame */
+ LCD_DeadTime_6 = (uint8_t)0x06, /*!< Six Phase between different couple of Frame */
+ LCD_DeadTime_7 = (uint8_t)0x07 /*!< Seven Phase between different couple of Frame */
+} LCD_DeadTime_TypeDef;
+
+#define IS_LCD_DEAD_TIME(TIME) (((TIME) == LCD_DeadTime_0) || \
+ ((TIME) == LCD_DeadTime_1) || \
+ ((TIME) == LCD_DeadTime_2) || \
+ ((TIME) == LCD_DeadTime_3) || \
+ ((TIME) == LCD_DeadTime_4) || \
+ ((TIME) == LCD_DeadTime_5) || \
+ ((TIME) == LCD_DeadTime_6) || \
+ ((TIME) == LCD_DeadTime_7))
+
+/**
+ * @}
+ */
+
+/** @defgroup LCD_BlinkMode
+ * @{
+ */
+typedef enum {
+ LCD_BlinkMode_Off = (uint8_t)0x00, /*!< Blink inactive */
+ LCD_BlinkMode_SEG0_COM0 = (uint8_t)0x40, /*!< SEG0 on COM0 blink */
+ LCD_BlinkMode_SEG0_AllCOM = (uint8_t)0x80, /*!< SEG0 on All COM blink */
+ LCD_BlinkMode_AllSEG_AllCOM = (uint8_t)0xC0 /*!< All SEG on All COm Blink */
+} LCD_BlinkMode_TypeDef;
+
+#define IS_LCD_BLINK_MODE(BLINK) (((BLINK) == LCD_BlinkMode_Off) || \
+ ((BLINK) == LCD_BlinkMode_SEG0_COM0) || \
+ ((BLINK) == LCD_BlinkMode_SEG0_AllCOM) || \
+ ((BLINK) == LCD_BlinkMode_AllSEG_AllCOM))
+
+/**
+ * @}
+ */
+
+/** @defgroup LCD_Blink_Frequency
+ * @brief element values correspond to the bits position
+ * @{
+ */
+typedef enum {
+ LCD_BlinkFrequency_Div8 = (uint8_t)0x00, /*!< The Blink frequency = fLcd/8 */
+ LCD_BlinkFrequency_Div16 = (uint8_t)0x08, /*!< The Blink frequency = fLcd/16 */
+ LCD_BlinkFrequency_Div32 = (uint8_t)0x10, /*!< The Blink frequency = fLcd/32 */
+ LCD_BlinkFrequency_Div64 = (uint8_t)0x18, /*!< The Blink frequency = fLcd/64 */
+ LCD_BlinkFrequency_Div128 = (uint8_t)0x20, /*!< The Blink frequency = fLcd/128 */
+ LCD_BlinkFrequency_Div256 = (uint8_t)0x28, /*!< The Blink frequency = fLcd/256 */
+ LCD_BlinkFrequency_Div512 = (uint8_t)0x30, /*!< The Blink frequency = fLcd/512 */
+ LCD_BlinkFrequency_Div1024 = (uint8_t)0x38 /*!< The Blink frequency = fLcd/1024 */
+} LCD_BlinkFrequency_TypeDef;
+
+#define IS_LCD_BLINK_FREQUENCY(BLINKF) (((BLINKF) == LCD_BlinkFrequency_Div8) || \
+ ((BLINKF) == LCD_BlinkFrequency_Div16) || \
+ ((BLINKF) == LCD_BlinkFrequency_Div32) || \
+ ((BLINKF) == LCD_BlinkFrequency_Div64) || \
+ ((BLINKF) == LCD_BlinkFrequency_Div128) || \
+ ((BLINKF) == LCD_BlinkFrequency_Div256) || \
+ ((BLINKF) == LCD_BlinkFrequency_Div512) || \
+ ((BLINKF) == LCD_BlinkFrequency_Div1024))
+/**
+ * @}
+ */
+
+/** @defgroup LCD_RAMRegister
+ * @{
+ */
+typedef enum {
+ LCD_RAMRegister_0 = (uint8_t)0x00, /*!< RAM Register 0 */
+ LCD_RAMRegister_1 = (uint8_t)0x01, /*!< RAM Register 1 */
+ LCD_RAMRegister_2 = (uint8_t)0x02, /*!< RAM Register 2 */
+ LCD_RAMRegister_3 = (uint8_t)0x03, /*!< RAM Register 3 */
+ LCD_RAMRegister_4 = (uint8_t)0x04, /*!< RAM Register 4 */
+ LCD_RAMRegister_5 = (uint8_t)0x05, /*!< RAM Register 5 */
+ LCD_RAMRegister_6 = (uint8_t)0x06, /*!< RAM Register 6 */
+ LCD_RAMRegister_7 = (uint8_t)0x07, /*!< RAM Register 7 */
+ LCD_RAMRegister_8 = (uint8_t)0x08, /*!< RAM Register 8 */
+ LCD_RAMRegister_9 = (uint8_t)0x09, /*!< RAM Register 9 */
+ LCD_RAMRegister_10 = (uint8_t)0x0A, /*!< RAM Register 10 */
+ LCD_RAMRegister_11 = (uint8_t)0x0B, /*!< RAM Register 11 */
+ LCD_RAMRegister_12 = (uint8_t)0x0C, /*!< RAM Register 12 */
+ LCD_RAMRegister_13 = (uint8_t)0x0D, /*!< RAM Register 13 */
+ LCD_RAMRegister_14 = (uint8_t)0x0E, /*!< RAM Register 14 */
+ LCD_RAMRegister_15 = (uint8_t)0x0F, /*!< RAM Register 15 */
+ LCD_RAMRegister_16 = (uint8_t)0x10, /*!< RAM Register 16 */
+ LCD_RAMRegister_17 = (uint8_t)0x11, /*!< RAM Register 17 */
+ LCD_RAMRegister_18 = (uint8_t)0x12, /*!< RAM Register 18 */
+ LCD_RAMRegister_19 = (uint8_t)0x13, /*!< RAM Register 19 */
+ LCD_RAMRegister_20 = (uint8_t)0x14, /*!< RAM Register 20 */
+ LCD_RAMRegister_21 = (uint8_t)0x15 /*!< RAM Register 21 */
+} LCD_RAMRegister_TypeDef;
+
+#define IS_LCD_RAM_REGISTER(REGISTER) (((REGISTER) == LCD_RAMRegister_0) || \
+ ((REGISTER) == LCD_RAMRegister_1) || \
+ ((REGISTER) == LCD_RAMRegister_2) || \
+ ((REGISTER) == LCD_RAMRegister_3) || \
+ ((REGISTER) == LCD_RAMRegister_4) || \
+ ((REGISTER) == LCD_RAMRegister_5) || \
+ ((REGISTER) == LCD_RAMRegister_6) || \
+ ((REGISTER) == LCD_RAMRegister_7) || \
+ ((REGISTER) == LCD_RAMRegister_8) || \
+ ((REGISTER) == LCD_RAMRegister_9) || \
+ ((REGISTER) == LCD_RAMRegister_10) || \
+ ((REGISTER) == LCD_RAMRegister_11) || \
+ ((REGISTER) == LCD_RAMRegister_12) || \
+ ((REGISTER) == LCD_RAMRegister_13) || \
+ ((REGISTER) == LCD_RAMRegister_14) || \
+ ((REGISTER) == LCD_RAMRegister_15) || \
+ ((REGISTER) == LCD_RAMRegister_16) || \
+ ((REGISTER) == LCD_RAMRegister_17) || \
+ ((REGISTER) == LCD_RAMRegister_18) || \
+ ((REGISTER) == LCD_RAMRegister_19) || \
+ ((REGISTER) == LCD_RAMRegister_20) || \
+ ((REGISTER) == LCD_RAMRegister_21))
+
+/**
+ * @}
+ */
+
+/** @defgroup LCD_Port_Mask_Register
+ * @{
+ */
+typedef enum {
+ LCD_PortMaskRegister_0 = (uint8_t)0x00, /*!< PortMask Register 0 */
+ LCD_PortMaskRegister_1 = (uint8_t)0x01, /*!< PortMask Register 1 */
+ LCD_PortMaskRegister_2 = (uint8_t)0x02, /*!< PortMask Register 2 */
+ LCD_PortMaskRegister_3 = (uint8_t)0x03, /*!< PortMask Register 3 */
+ LCD_PortMaskRegister_4 = (uint8_t)0x04, /*!< PortMask Register 4 */
+ LCD_PortMaskRegister_5 = (uint8_t)0x05 /*!< PortMask Register 5 */
+} LCD_PortMaskRegister_TypeDef;
+
+#define IS_LCD_PORT_MASK(MASK) (((MASK) == LCD_PortMaskRegister_0) || \
+ ((MASK) == LCD_PortMaskRegister_1) || \
+ ((MASK) == LCD_PortMaskRegister_2) || \
+ ((MASK) == LCD_PortMaskRegister_3) || \
+ ((MASK) == LCD_PortMaskRegister_4) || \
+ ((MASK) == LCD_PortMaskRegister_5))
+
+/**
+ * @}
+ */
+
+/** @defgroup LCD_Page_Selection
+ * @{
+ */
+typedef enum {
+ LCD_PageSelection_FirstPage = (uint8_t)0x00, /*!< The LCD RAM is selected as the first page */
+ LCD_PageSelection_SecondPage = (uint8_t)0x04 /*!< The LCD RAM is selected as the second page */
+} LCD_PageSelection_TypeDef;
+
+#define IS_LCD_PAGE_SELECT(PAGE) (((PAGE) == LCD_PageSelection_FirstPage) || \
+ ((PAGE) == LCD_PageSelection_SecondPage))
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private define ------------------------------------------------------------*/
+/* LCD Legacy defines */
+/** @defgroup LCD_Private_Define
+ * @ brief LCD Legacy defines
+ * @{
+ */
+#define LCD_Contrast_2V6 ((uint8_t)LCD_Contrast_Level_0)
+#define LCD_Contrast_2V7 ((uint8_t)LCD_Contrast_Level_1)
+#define LCD_Contrast_2V8 ((uint8_t)LCD_Contrast_Level_2)
+#define LCD_Contrast_2V9 ((uint8_t)LCD_Contrast_Level_3)
+#define LCD_Contrast_3V0 ((uint8_t)LCD_Contrast_Level_4)
+#define LCD_Contrast_3V1 ((uint8_t)LCD_Contrast_Level_5)
+#define LCD_Contrast_3V2 ((uint8_t)LCD_Contrast_Level_6)
+#define LCD_Contrast_3V3 ((uint8_t)LCD_Contrast_Level_7)
+/**
+ * @}
+ */
+/* Private macros ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+/* Function used to set the LCD configuration to the default reset state *****/
+void LCD_DeInit(void);
+
+/* Initialization and Configuration functions *********************************/
+void LCD_Init(LCD_Prescaler_TypeDef LCD_Prescaler, LCD_Divider_TypeDef LCD_Divider,
+ LCD_Duty_TypeDef LCD_Duty, LCD_Bias_TypeDef LCD_Bias, LCD_VoltageSource_TypeDef LCD_VoltageSource);
+void LCD_PortMaskConfig(LCD_PortMaskRegister_TypeDef LCD_PortMaskRegister, uint8_t LCD_Mask);
+void LCD_Cmd(FunctionalState NewState);
+void LCD_HighDriveCmd(FunctionalState NewState);
+void LCD_PulseOnDurationConfig(LCD_PulseOnDuration_TypeDef LCD_PulseOnDuration);
+void LCD_DeadTimeConfig(LCD_DeadTime_TypeDef LCD_DeadTime);
+void LCD_BlinkConfig(LCD_BlinkMode_TypeDef LCD_BlinkMode, LCD_BlinkFrequency_TypeDef LCD_BlinkFrequency);
+void LCD_ContrastConfig(LCD_Contrast_TypeDef LCD_Contrast);
+
+/* LCD RAM memory write functions *********************************************/
+void LCD_WriteRAM(LCD_RAMRegister_TypeDef LCD_RAMRegister, uint8_t LCD_Data);
+void LCD_PageSelect(LCD_PageSelection_TypeDef LCD_PageSelection);
+
+/* Interrupts and flags management functions **********************************/
+void LCD_ITConfig(FunctionalState NewState);
+FlagStatus LCD_GetFlagStatus(void);
+void LCD_ClearFlag(void);
+ITStatus LCD_GetITStatus(void);
+void LCD_ClearITPendingBit(void);
+
+#endif /* __STM8L15x_LCD_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_pwr.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_pwr.h
new file mode 100644
index 00000000..b9b81402
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_pwr.h
@@ -0,0 +1,131 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_pwr.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the PWR firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_PWR_H
+#define __STM8L15x_PWR_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup PWR
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup PWR_Exported_Types
+ * @{
+ */
+
+/** @defgroup PVD_detection_level
+ * @{
+ */
+
+typedef enum {
+ PWR_PVDLevel_1V85 = (uint8_t)0x00, /*!< PVD threshold = 1.85 V */
+ PWR_PVDLevel_2V05 = (uint8_t)0x02, /*!< PVD threshold = 2.05 V */
+ PWR_PVDLevel_2V26 = (uint8_t)0x04, /*!< PVD threshold = 2.26 V */
+ PWR_PVDLevel_2V45 = (uint8_t)0x06, /*!< PVD threshold = 2.45 V */
+ PWR_PVDLevel_2V65 = (uint8_t)0x08, /*!< PVD threshold = 2.65 V */
+ PWR_PVDLevel_2V85 = (uint8_t)0x0A, /*!< PVD threshold = 2.85 V */
+ PWR_PVDLevel_3V05 = (uint8_t)0x0C, /*!< PVD threshold = 3.05 V */
+ PWR_PVDLevel_PVDIn = (uint8_t)0x0E /*!< PVD threshold = PVD_IN input pin */
+} PWR_PVDLevel_TypeDef;
+
+#define IS_PWR_PVD_LEVEL(LEVEL) (((LEVEL) == PWR_PVDLevel_1V85) || \
+ ((LEVEL) == PWR_PVDLevel_2V05) || \
+ ((LEVEL) == PWR_PVDLevel_2V26) || \
+ ((LEVEL) == PWR_PVDLevel_2V45) || \
+ ((LEVEL) == PWR_PVDLevel_2V65) || \
+ ((LEVEL) == PWR_PVDLevel_2V85) || \
+ ((LEVEL) == PWR_PVDLevel_3V05) || \
+ ((LEVEL) == PWR_PVDLevel_PVDIn))
+/**
+ * @}
+ */
+
+/** @defgroup PWR_Flag
+ * @{
+ */
+
+typedef enum {
+ PWR_FLAG_PVDOF = (uint8_t)0x40,/*!< PVD output flag */
+ PWR_FLAG_PVDIF = (uint8_t)0x20, /*!< PVD Interrupt flag */
+ PWR_FLAG_VREFINTF = (uint8_t)0x01 /*!< Internal reference voltage status flag */
+} PWR_FLAG_TypeDef;
+
+#define IS_PWR_FLAG(FLAG) (((FLAG) == PWR_FLAG_PVDOF) || \
+ ((FLAG) == PWR_FLAG_PVDIF) || \
+ ((FLAG) == PWR_FLAG_VREFINTF))
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+/* Function used to set the PWR configuration to the default reset state ******/
+void PWR_DeInit(void);
+
+/* PVD configuration functions ************************************************/
+void PWR_PVDLevelConfig(PWR_PVDLevel_TypeDef PWR_PVDLevel);
+void PWR_PVDCmd(FunctionalState NewState);
+
+/* Ultra Low Power mode configuration functions *******************************/
+void PWR_FastWakeUpCmd(FunctionalState NewState);
+void PWR_UltraLowPowerCmd(FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void PWR_PVDITConfig(FunctionalState NewState);
+ITStatus PWR_PVDGetITStatus(void);
+FlagStatus PWR_GetFlagStatus(PWR_FLAG_TypeDef PWR_FLAG);
+void PWR_PVDClearFlag(void);
+void PWR_PVDClearITPendingBit(void);
+
+#endif /* __STM8L15x_PWR_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_rst.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_rst.h
new file mode 100644
index 00000000..fd9ac5b4
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_rst.h
@@ -0,0 +1,91 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_rst.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the RST firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_RST_H
+#define __STM8L15x_RST_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup RST
+ * @{
+ */
+
+/* Exported variables ------------------------------------------------------- */
+/* Exported types ------------------------------------------------------------*/
+/** @defgroup RST_Exported_Types
+ * @{
+ */
+
+/** @defgroup RST_Flags
+ * @{
+ */
+typedef enum {
+ RST_FLAG_PORF = (uint8_t)0x01, /*!< POR reset flag */
+ RST_FLAG_SWIMF = (uint8_t)0x08, /*!< SWIM reset flag */
+ RST_FLAG_ILLOPF = (uint8_t)0x04, /*!< Illegal opcode reset flag */
+ RST_FLAG_IWDGF = (uint8_t)0x02, /*!< Independent watchdog reset flag */
+ RST_FLAG_WWDGF = (uint8_t)0x10, /*!< Window watchdog reset flag */
+ RST_FLAG_BORF = (uint8_t)0x20 /*!< BOR reset flag */
+} RST_FLAG_TypeDef;
+
+#define IS_RST_FLAG(FLAG) (((FLAG) == RST_FLAG_PORF) || ((FLAG) == RST_FLAG_BORF) || \
+ ((FLAG) == RST_FLAG_IWDGF) || ((FLAG) == RST_FLAG_ILLOPF) || \
+ ((FLAG) == RST_FLAG_WWDGF) || ((FLAG) == RST_FLAG_SWIMF))
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+/* Flag management functions **************************************************/
+FlagStatus RST_GetFlagStatus(RST_FLAG_TypeDef RST_Flag);
+void RST_ClearFlag(RST_FLAG_TypeDef RST_Flag);
+
+/* NRST Pin configuration function ********************************************/
+void RST_GPOutputEnable(void);
+
+#endif /* __STM8L15x_RST_H */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_rtc.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_rtc.h
new file mode 100644
index 00000000..f3151fa3
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_rtc.h
@@ -0,0 +1,956 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_rtc.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the RTC
+ * firmware library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_RTC_H
+#define __STM8L15x_RTC_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup RTC
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+/** @defgroup RTC_Exported_Types
+ * @{
+ */
+
+/** @defgroup RTC_Weekdays
+ * @{
+ */
+typedef enum
+{
+ RTC_Weekday_Monday = ((uint8_t)0x01), /*!< WeekDay is Monday */
+ RTC_Weekday_Tuesday = ((uint8_t)0x02), /*!< WeekDay is Tuesday */
+ RTC_Weekday_Wednesday = ((uint8_t)0x03), /*!< WeekDay is Wednesday */
+ RTC_Weekday_Thursday = ((uint8_t)0x04), /*!< WeekDay is Thursday */
+ RTC_Weekday_Friday = ((uint8_t)0x05), /*!< WeekDay is Friday */
+ RTC_Weekday_Saturday = ((uint8_t)0x06), /*!< WeekDay is Saturday */
+ RTC_Weekday_Sunday = ((uint8_t)0x07) /*!< WeekDay is Sunday */
+}
+RTC_Weekday_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Months
+ * @{
+ */
+typedef enum
+{
+ RTC_Month_January = ((uint8_t)0x01), /*!< Month is January */
+ RTC_Month_February = ((uint8_t)0x02), /*!< Month is February */
+ RTC_Month_March = ((uint8_t)0x03), /*!< Month is March */
+ RTC_Month_April = ((uint8_t)0x04), /*!< Month is April */
+ RTC_Month_May = ((uint8_t)0x05), /*!< Month is May */
+ RTC_Month_June = ((uint8_t)0x06), /*!< Month is June */
+ RTC_Month_July = ((uint8_t)0x07), /*!< Month is July */
+ RTC_Month_August = ((uint8_t)0x08), /*!< Month is August */
+ RTC_Month_September = ((uint8_t)0x09), /*!< Month is September */
+ RTC_Month_October = ((uint8_t)0x10), /*!< Month is October */
+ RTC_Month_November = ((uint8_t)0x11), /*!< Month is November */
+ RTC_Month_December = ((uint8_t)0x12) /*!< Month is December */
+}
+RTC_Month_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Hour_Format
+ * @{
+ */
+typedef enum
+{
+ RTC_HourFormat_24 = ((uint8_t)0x00), /*!< Hour Format is 24H */
+ RTC_HourFormat_12 = ((uint8_t)0x40) /*!< Hour Format is 12H (using AM/PM) */
+}
+RTC_HourFormat_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Time
+ * @{
+ */
+typedef enum
+{
+ RTC_H12_AM = ((uint8_t)0x00), /*!< AM/PM notation is AM or 24 hour format */
+ RTC_H12_PM = ((uint8_t)0x40) /*!< AM/PM notation is PM */
+}
+RTC_H12_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Alarm_WeekDay_Selection
+ * @{
+ */
+typedef enum
+{
+ RTC_AlarmDateWeekDaySel_Date = ((uint8_t)0x00), /*!< Date/WeekDay selection is Date */
+ RTC_AlarmDateWeekDaySel_WeekDay = ((uint8_t)0x40) /*!< Date/WeekDay selection is WeekDay */
+}
+RTC_AlarmDateWeekDaySel_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Alarm_Mask
+ * @{
+ */
+typedef enum
+{
+ RTC_AlarmMask_None = ((uint8_t)0x00), /*!< Alarm Masks disabled */
+ RTC_AlarmMask_Seconds = ((uint8_t)0x80), /*!< Alarm Seconds Mask */
+ RTC_AlarmMask_Minutes = ((uint8_t)0x40), /*!< Alarm Minutes Mask */
+ RTC_AlarmMask_Hours = ((uint8_t)0x20), /*!< Alarm Hours Mask */
+ RTC_AlarmMask_DateWeekDay = ((uint8_t)0x10), /*!< Alarm Date/WeekDay Mask */
+ RTC_AlarmMask_All = ((uint8_t)0xF0) /*!< Alarm All Mask are enabled */
+}
+RTC_AlarmMask_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Sub_Second_Alarm_Mask
+ * @{
+ */
+typedef enum
+{
+ RTC_AlarmSubSecondMask_All = ((uint8_t)0x00), /*!< All Alarm SS fields are masked. There is no comparison on sub seconds for Alarm */
+ RTC_AlarmSubSecondMask_None = ((uint8_t)0x0F), /*!< SS[14:0] are compared and must match to activate alarm. */
+ RTC_AlarmSubSecondMask_SS14_1 = ((uint8_t)0x01), /*!< SS[14:1] are not used in Alarm comparison. Only SS[0] is compared. */
+ RTC_AlarmSubSecondMask_SS14_2 = ((uint8_t)0x02), /*!< SS[14:2] are not used in Alarm comparison. Only SS[1:0] are compared */
+ RTC_AlarmSubSecondMask_SS14_3 = ((uint8_t)0x03), /*!< SS[14:3] are not used in Alarm comparison. Only SS[1:0] are compared */
+ RTC_AlarmSubSecondMask_SS14_4 = ((uint8_t)0x04), /*!< SS[14:4] are not used in Alarm comparison. Only SS[1:0] are compared */
+ RTC_AlarmSubSecondMask_SS14_5 = ((uint8_t)0x05), /*!< SS[14:5] are not used in Alarm comparison. Only SS[1:0] are compared */
+ RTC_AlarmSubSecondMask_SS14_6 = ((uint8_t)0x06), /*!< SS[14:6] are not used in Alarm comparison. Only SS[1:0] are compared */
+ RTC_AlarmSubSecondMask_SS14_7 = ((uint8_t)0x07), /*!< SS[14:7] are not used in Alarm comparison. Only SS[1:0] are compared */
+ RTC_AlarmSubSecondMask_SS14_8 = ((uint8_t)0x08), /*!< SS[14:8] are not used in Alarm comparison. Only SS[1:0] are compared */
+ RTC_AlarmSubSecondMask_SS14_9 = ((uint8_t)0x09), /*!< SS[14:9] are not used in Alarm comparison. Only SS[1:0] are compared */
+ RTC_AlarmSubSecondMask_SS14_10 = ((uint8_t)0x0A), /*!< SS[14:10] are not used in Alarm comparison. Only SS[1:0] are compared */
+ RTC_AlarmSubSecondMask_SS14_11 = ((uint8_t)0x0B), /*!< SS[14:11] are not used in Alarm comparison. Only SS[1:0] are compared */
+ RTC_AlarmSubSecondMask_SS14_12 = ((uint8_t)0x0C), /*!< SS[14:12] are not used in Alarm comparison. Only SS[1:0] are compared */
+ RTC_AlarmSubSecondMask_SS14_13 = ((uint8_t)0x0D), /*!< SS[14:13] are not used in Alarm comparison. Only SS[1:0] are compared */
+ RTC_AlarmSubSecondMask_SS14 = ((uint8_t)0x0E) /*!< SS[14] is not used in Alarm comparison. Only SS[13:0] are compared */
+}
+RTC_AlarmSubSecondMask_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Wakeup_Clock
+ * @{
+ */
+typedef enum
+{
+ RTC_WakeUpClock_RTCCLK_Div16 = ((uint8_t)0x00), /*!< (RTC clock) div 16*/
+ RTC_WakeUpClock_RTCCLK_Div8 = ((uint8_t)0x01), /*!< (RTC clock) div 8*/
+ RTC_WakeUpClock_RTCCLK_Div4 = ((uint8_t)0x02), /*!< (RTC clock) div 4*/
+ RTC_WakeUpClock_RTCCLK_Div2 = ((uint8_t)0x03), /*!< (RTC clock) div 2*/
+ RTC_WakeUpClock_CK_SPRE_16bits = ((uint8_t)0x04), /*!< CK SPRE with a counter from 0x0000 to 0xFFFF */
+ RTC_WakeUpClock_CK_SPRE_17bits = ((uint8_t)0x06) /*!< CK SPRE with a counter from 0x10000 to 0x1FFFF */
+}
+RTC_WakeUpClock_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Output_Selection
+ * @{
+ */
+typedef enum
+{
+ RTC_Output_Disable = ((uint8_t)0x00), /*!< RTC Alternate function Output is disabled */
+ RTC_Output_Alarm = ((uint8_t)0x20), /*!< RTC Alternate function Output is the Alarm A event*/
+ RTC_Output_WakeUp = ((uint8_t)0x60) /*!< RTC Alternate function Output is the WakeUp event */
+}
+RTC_Output_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Output_Polarity
+ * @{
+ */
+typedef enum
+{
+ RTC_OutputPolarity_High = ((uint8_t)0x00), /*!< RTC Alternate function Output Polarity is High */
+ RTC_OutputPolarity_Low = ((uint8_t)0x10) /*!< RTC Alternate function Output Polarity is Low */
+}
+RTC_OutputPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Calibration_Output
+ * @{
+ */
+typedef enum
+{
+ RTC_CalibOutput_512Hz = ((uint8_t)0x00), /*!< RTC Calibration Output is 512Hz */
+ RTC_CalibOutput_1Hz = ((uint8_t)0x80) /*!< RTC Calibration Output is 1Hz */
+}
+RTC_CalibOutput_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_DayLight_Saving
+ * @{
+ */
+typedef enum
+{
+ RTC_DayLightSaving_SUB1H = ((uint8_t)0x02), /*!< Substract 1 hour to the current Time (Winter Time Adjustment) */
+ RTC_DayLightSaving_ADD1H = ((uint8_t)0x01) /*!< Add 1 hour to the current Time (Summer Time Adjustment) */
+}
+RTC_DayLightSaving_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Store_Operation
+ * @{
+ */
+typedef enum
+{
+ RTC_StoreOperation_Set = ((uint8_t)0x04), /*!< Store Operation Set */
+ RTC_StoreOperation_Reset = ((uint8_t)0x00) /*!< Store Operation Reset */
+}
+RTC_StoreOperation_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Input_Parameter_Format
+ * @{
+ */
+typedef enum
+{
+ RTC_Format_BIN = ((uint8_t)0x00), /*!< Binary Format is used */
+ RTC_Format_BCD = ((uint8_t)0x01) /*!< BCD Format is used */
+}
+RTC_Format_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Flags
+ * @{
+ */
+typedef enum
+{
+ RTC_FLAG_TAMP3F = ((uint16_t)0x0080), /*!< TAMPER3 detection Flag. If set, tamper detection event is detected on tamper input 3 */
+ RTC_FLAG_TAMP2F = ((uint16_t)0x0040), /*!< TAMPER2 detection Flag. If set, tamper detection event is detected on tamper input 2 */
+ RTC_FLAG_TAMP1F = ((uint16_t)0x0020), /*!< TAMPER1 detection Flag. If set, tamper detection event is detected on tamper input 1 */
+
+ RTC_FLAG_WUTF = ((uint16_t)0x0004), /*!< Wake up Timer Flag. If set, the Wake Up down counter reaches 0 */
+ RTC_FLAG_ALRAF = ((uint16_t)0x0001), /*!< Alarm A Flag. If set, the Time/Date registers matches Alarm A registers */
+
+ RTC_FLAG_INITF = ((uint16_t)0x4000), /*!< Initialisation Flag. If set,Calender registers has been initialized */
+ RTC_FLAG_RSF = ((uint16_t)0x2000), /*!< Registers Synchronization Flag. If set,Calender registers synchronized */
+ RTC_FLAG_INITS = ((uint16_t)0x1000), /*!< Initialisation Status Flag. If set,Calender update is allowed */
+
+ RTC_FLAG_SHPF = ((uint16_t)0x0800), /*!< Shift operation pending Flag. This flag is set by hardware as soon as a shift operation is
+ initiated by a write to the RTC_SHIFTRL. It is cleared by hardware as soon as the corresponding
+ shift operation has completed. */
+
+ RTC_FLAG_WUTWF = ((uint16_t)0x0400), /*!< Wake up Timer write Flag. If set, Wake up Timer update is allowed */
+ RTC_FLAG_RECALPF = ((uint16_t)0x0200), /*!< Recalibration pending Flag, The status flag RECALPF is automatically set to ‘1’ when software
+ writes to the register RTC_CALRL, indicating that the RTC_CALRx registers are blocked.
+ When the new calibration settings are taken into account, this Flag returns by hardware to ‘0’. */
+ RTC_FLAG_ALRAWF = ((uint16_t)0x0100) /*!< Alarm A write Flag. If set, Alarm A update is allowed */
+}
+RTC_Flag_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Interrupts
+ * @{
+ */
+typedef enum
+{
+ RTC_IT_WUT = ((uint16_t)0x0040), /*!< Wake up Timer Interrupt */
+ RTC_IT_ALRA = ((uint16_t)0x0010), /*!< Alarm A Interrupt */
+ RTC_IT_TAMP = ((uint16_t)0x0F01) /*!< Tamper Interrupt */
+}
+RTC_IT_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Tamper_Level
+ * @{
+ */
+typedef enum
+{
+ RTC_TamperLevel_Low = ((uint8_t)0x00), /*!< Tamper staying low triggers a tamper detection event. */
+ RTC_TamperLevel_High = ((uint8_t)0x54) /*!< Tamper staying high triggers a tamper detection event. */
+}
+RTC_TamperLevel_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Tamper_State
+ * @{
+ */
+typedef enum
+{
+ RTC_TamperState_Disable = ((uint8_t)0x00), /*!< Tamper State is Disable */
+ RTC_TamperState_Enable = ((uint8_t)0x01) /*!< Tamper State is Enable */
+}
+RTC_TamperState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Tamper_definition
+ * @{
+ */
+typedef enum
+{
+ RTC_Tamper_1 = ((uint8_t)0x02), /*!< Tamper 1 selection */
+ RTC_Tamper_2 = ((uint8_t)0x08), /*!< Tamper 2 selection */
+ RTC_Tamper_3 = ((uint8_t)0x20) /*!< Tamper 3 selection */
+}
+RTC_Tamper_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Tamper_Precharge_Duration
+ * @{
+ */
+typedef enum
+{
+ RTC_TamperPrechargeDuration_None = ((uint8_t)0x80), /*!< Tamper pins are not precharged before sampling */
+ RTC_TamperPrechargeDuration_1RTCCLK = ((uint8_t)0x00), /*!< Tamper pins are precharged before sampling during 1 RTCCLK cycle */
+ RTC_TamperPrechargeDuration_2RTCCLK = ((uint8_t)0x20), /*!< Tamper pins are precharged before sampling during 2 RTCCLK cycles */
+ RTC_TamperPrechargeDuration_4RTCCLK = ((uint8_t)0x40), /*!< Tamper pins are precharged before sampling during 4 RTCCLK cycles */
+ RTC_TamperPrechargeDuration_8RTCCLK = ((uint8_t)0x60) /*!< Tamper pins are precharged before sampling during 8 RTCCLK cycles */
+}
+RTC_TamperPrechargeDuration_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Tamper_Filter
+ * @{
+ */
+typedef enum
+{
+ RTC_TamperFilter_1Sample = ((uint8_t)0x00), /*!< Tamper is activated after 1 sample at the active level */
+ RTC_TamperFilter_2Sample = ((uint8_t)0x08), /*!< Tamper is activated after 2 consecutive samples at the active level. */
+ RTC_TamperFilter_4Sample = ((uint8_t)0x10), /*!< Tamper is activated after 4 consecutive samples at the active level. */
+ RTC_TamperFilter_8Sample = ((uint8_t)0x18) /*!< Tamper is activated after 8 consecutive samples at the active level. */
+}
+RTC_TamperFilter_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Tamper_Sampling_Frequency
+ * @{
+ */
+typedef enum
+{
+ RTC_TamperSamplingFreq_RTCCLK_Div32768 = ((uint8_t)0x00), /*!< Tamper inputs are sampled with a frequency = RTCCLK / 32768 */
+ RTC_TamperSamplingFreq_RTCCLK_Div16384 = ((uint8_t)0x01), /*!< Tamper inputs are sampled with a frequency = RTCCLK / 16384 */
+ RTC_TamperSamplingFreq_RTCCLK_Div8192 = ((uint8_t)0x02), /*!< Tamper inputs are sampled with a frequency = RTCCLK / 8192 */
+ RTC_TamperSamplingFreq_RTCCLK_Div4096 = ((uint8_t)0x03), /*!< Tamper inputs are sampled with a frequency = RTCCLK / 4096 */
+ RTC_TamperSamplingFreq_RTCCLK_Div2048 = ((uint8_t)0x04), /*!< Tamper inputs are sampled with a frequency = RTCCLK / 2048 */
+ RTC_TamperSamplingFreq_RTCCLK_Div1024 = ((uint8_t)0x05), /*!< Tamper inputs are sampled with a frequency = RTCCLK / 1024 */
+ RTC_TamperSamplingFreq_RTCCLK_Div512 = ((uint8_t)0x06), /*!< Tamper inputs are sampled with a frequency = RTCCLK / 512 */
+ RTC_TamperSamplingFreq_RTCCLK_Div256 = ((uint8_t)0x07) /*!< Tamper inputs are sampled with a frequency = RTCCLK / 256 */
+}
+RTC_TamperSamplingFreq_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Shift_Add_1s
+ * @{
+ */
+typedef enum
+{
+ RTC_ShiftAdd1S_Set = ((uint8_t)0x80), /*!< Add 1 Second */
+ RTC_ShiftAdd1S_Reset = ((uint8_t)0x00) /*!< Do not Add 1 Second */
+}
+RTC_ShiftAdd1S_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Smooth_Calibration_Period
+ * @{
+ */
+typedef enum
+{
+ RTC_SmoothCalibPeriod_32sec = ((uint8_t)0x00), /*!< if RTCCLK = 32768 Hz, Smooth calibration period is 32s, else 2exp20 RTCCLK seconds */
+ RTC_SmoothCalibPeriod_16sec = ((uint8_t)0x20), /*!< if RTCCLK = 32768 Hz, Smooth calibration period is 16s, else 2exp19 RTCCLK seconds */
+ RTC_SmoothCalibPeriod_8sec = ((uint8_t)0x40) /*!< if RTCCLK = 32768 Hz, Smooth calibration period is 8s, else 2exp18 RTCCLK seconds */
+}
+RTC_SmoothCalibPeriod_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Smooth_Calibration_Pulses
+ * @{
+ */
+typedef enum
+{
+ RTC_SmoothCalibPlusPulses_Set = ((uint8_t)0x80), /*!< The number of RTCCLK pulses added during a X -second window = Y - CALM[8:0].
+ with Y = 512, 256, 128 when X = 32, 16, 8 */
+ RTC_SmoothCalibPlusPulses_Reset = ((uint8_t)0x00) /*!< The number of RTCCLK pulses substituted during a 32-second window = CALM[8:0]. */
+
+}
+RTC_SmoothCalibPlusPulses_TypeDef;
+
+/**
+ * @}
+ */
+
+/**
+ * @brief RTC Init structure definition
+ */
+
+typedef struct
+{
+
+ RTC_HourFormat_TypeDef RTC_HourFormat; /*!< RTC Hour Format */
+
+ uint8_t RTC_AsynchPrediv; /*!< RTC Asynchronous Predivider.
+ This parameter can be any value from
+ 0x00 to 0x7F.*/
+
+ uint16_t RTC_SynchPrediv; /*!< RTC Synchronous Predivider.
+ This parameter can be any value from
+ 0x0000 to 0x7FFF.*/
+}
+RTC_InitTypeDef;
+
+
+/**
+ * @brief RTC Time structure definition
+ */
+typedef struct
+{
+ uint8_t RTC_Hours; /*!< RTC Hours.
+ If Binary format is selected :
+ - If RTC_Hour format is RTC_Hour format_12,
+ this parameter can be any value from 1 to 12.
+ - If RTC_Hour format is RTC_Hour format_24,
+ this parameter can be any value from 0 to 23.
+ If BCD format is selected :
+ - If RTC_Hour format is RTC_Hour format_12,
+ this parameter can be any BCD value from
+ 0x01 to 0x12.
+ - If RTC_Hour format is RTC_Hour format_24,
+ this parameter can be any BCD value from
+ 0x00 to 0x23.*/
+ uint8_t RTC_Minutes; /*!< RTC Minutes.
+ If Binary format is selected, this parameter can
+ be any value from 0 to 59.
+ If BCD format is selected, this parameter can
+ be any BCD value from 0x00 to 0x59.*/
+ uint8_t RTC_Seconds; /*!< RTC Seconds.
+ If Binary format is selected, this parameter can
+ be any value from 0 to 59.
+ If BCD format is selected, this parameter can
+ be any BCD value from 0x00 to 0x59.*/
+ RTC_H12_TypeDef RTC_H12; /*!< RTC 12-hour clock period (AM/PM) */
+}
+RTC_TimeTypeDef;
+
+/**
+ * @brief RTC Date structure definition
+ */
+typedef struct
+{
+ RTC_Weekday_TypeDef RTC_WeekDay; /*!< The RTC Calender Weekday. */
+
+ RTC_Month_TypeDef RTC_Month; /*!< The RTC Calender Month. */
+
+ uint8_t RTC_Date; /*!< The RTC Calender Date.
+ If Binary format is selected, this
+ parameter can be any value from 1 to 31.
+ If BCD format is selected, this parameter
+ can be any BCD value from 0x01 to 0x31.*/
+
+ uint8_t RTC_Year; /*!< The RTC Calender Date.
+ If Binary format is selected, this parameter
+ can be any value from 0 to 99.
+ If BCD format is selected, this parameter
+ can be any BCD value from 0x00 to 0x99.*/
+}
+RTC_DateTypeDef;
+
+/**
+ * @brief RTC Alarm structure definition
+ */
+typedef struct
+{
+ RTC_TimeTypeDef RTC_AlarmTime; /*!< RTC Alarm Time */
+
+ uint8_t RTC_AlarmMask; /*!< The RTC Alarm Fields Masks. */
+
+ RTC_AlarmDateWeekDaySel_TypeDef RTC_AlarmDateWeekDaySel; /*!< The RTC Alarm Date/WeekDay selection. */
+
+ uint8_t RTC_AlarmDateWeekDay; /*!< The RTC Alarm Date/WeekDay value.
+ - If RTC Alarm Date/WeekDay selection is Date
+ and if If Binary format is selected, this
+ parameter can be any value from 1 to 31.
+ - If RTC Alarm Date/WeekDay selection is WeekDay,
+ this parameter can be one of the
+ @ref RTC_Weekday_TypeDef enumeration.*/
+}
+RTC_AlarmTypeDef;
+ /**
+ * @}
+ */
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+/** @defgroup RTC_Exported_Macros
+* @{
+*/
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Calender Hour format
+ */
+
+#define IS_RTC_HOUR_FORMAT(FORMAT) (((FORMAT) == RTC_HourFormat_12) || \
+ ((FORMAT) == RTC_HourFormat_24))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Asynchronous Predivider
+ */
+#define IS_RTC_ASYNCH_PREDIV(PREDIV) ((PREDIV) <= 0x7F)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Synchronous Predivider
+ */
+#define IS_RTC_SYNCH_PREDIV(PREDIV) ((PREDIV) <= 0x7FFF)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Calender Hours value (format 12h)
+ */
+#define IS_RTC_HOUR12_MAX(HOUR) ((HOUR) <= (uint8_t)12)
+#define IS_RTC_HOUR12_MIN(HOUR) ((HOUR) > (uint8_t)0)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Calender Hours value (format 24h)
+ */
+#define IS_RTC_HOUR24(HOUR) ((HOUR) <= 23)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Calender minutes value
+ */
+#define IS_RTC_MINUTES(MINUTES) ((MINUTES) <= 59)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Calender seconds value
+ */
+#define IS_RTC_SECONDS(SECONDS) ((SECONDS) <= 59)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Calender H12 mode
+ */
+#define IS_RTC_H12(PM) (((PM) == (RTC_H12_AM)) || ((PM) == (RTC_H12_PM)))
+
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Calender Year value
+ */
+#define IS_RTC_YEAR(YEAR) ((YEAR) <= 99)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Calender month value
+ */
+#define IS_RTC_MONTH_MAX(MONTH) ((MONTH) <= (uint8_t)12)
+#define IS_RTC_MONTH_MIN(MONTH) ((MONTH) >= (uint8_t)1)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Calender Date value
+ */
+#define IS_RTC_DATE_MAX(DATE) ((DATE) <= (uint8_t)31)
+#define IS_RTC_DATE_MIN(DATE) ((DATE) >= (uint8_t)1)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Calender Week day value
+ */
+#define IS_RTC_WEEKDAY(WEEKDAY) (((WEEKDAY) == RTC_Weekday_Monday) || \
+ ((WEEKDAY) == RTC_Weekday_Tuesday) || \
+ ((WEEKDAY) == RTC_Weekday_Wednesday) || \
+ ((WEEKDAY) == RTC_Weekday_Thursday) || \
+ ((WEEKDAY) == RTC_Weekday_Friday) || \
+ ((WEEKDAY) == RTC_Weekday_Saturday) || \
+ ((WEEKDAY) == RTC_Weekday_Sunday))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Alarm Date/week day selection
+ */
+#define IS_RTC_ALARM_DATEWEEKDAY_SEL(SEL) (((SEL) == RTC_AlarmDateWeekDaySel_Date) || \
+ ((SEL) == RTC_AlarmDateWeekDaySel_WeekDay))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Alarm Mask
+ */
+#define IS_RTC_ALARM_MASK(MASK) (((MASK) & 0x0F) == (uint8_t)(RESET))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * wakeup clock source
+ */
+#define IS_RTC_WAKEUP_CLOCK(CLOCK) (((CLOCK) == RTC_WakeUpClock_RTCCLK_Div16) || \
+ ((CLOCK) == RTC_WakeUpClock_RTCCLK_Div8) || \
+ ((CLOCK) == RTC_WakeUpClock_RTCCLK_Div4) || \
+ ((CLOCK) == RTC_WakeUpClock_RTCCLK_Div2) || \
+ ((CLOCK) == RTC_WakeUpClock_CK_SPRE_16bits) || \
+ ((CLOCK) == RTC_WakeUpClock_CK_SPRE_17bits))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Output selection
+ */
+#define IS_RTC_OUTPUT_SEL(SEL) (((SEL) == RTC_Output_Disable) || \
+ ((SEL) == RTC_Output_Alarm) || \
+ ((SEL) == RTC_Output_WakeUp))
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Output polarity
+ */
+#define IS_RTC_OUTPUT_POL(POL) (((POL) == RTC_OutputPolarity_High) || \
+ ((POL) == RTC_OutputPolarity_Low))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Daylight saving mode
+ */
+#define IS_RTC_DAYLIGHT_SAVING(SAVE) (((SAVE) == RTC_DayLightSaving_SUB1H) || \
+ ((SAVE) == RTC_DayLightSaving_ADD1H))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Store Operation status
+ */
+#define IS_RTC_STORE_OPERATION(OP) (((OP) == RTC_StoreOperation_Set) || \
+ ((OP) == RTC_StoreOperation_Reset))
+
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * format (bin/bcd) for data user insert
+ */
+#define IS_RTC_FORMAT(FORMAT) (((FORMAT) == RTC_Format_BIN) || \
+ ((FORMAT) == RTC_Format_BCD))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Flag to get
+ */
+#define IS_RTC_GET_FLAG(FLAG) (((FLAG) == RTC_FLAG_WUTF) || \
+ ((FLAG) == RTC_FLAG_ALRAF) || \
+ ((FLAG) == RTC_FLAG_INITF) || \
+ ((FLAG) == RTC_FLAG_RSF) || \
+ ((FLAG) == RTC_FLAG_INITS) || \
+ ((FLAG) == RTC_FLAG_WUTWF) || \
+ ((FLAG) == RTC_FLAG_TAMP3F)|| \
+ ((FLAG) == RTC_FLAG_TAMP2F)|| \
+ ((FLAG) == RTC_FLAG_TAMP1F)|| \
+ ((FLAG) == RTC_FLAG_SHPF) || \
+ ((FLAG) == RTC_FLAG_RECALPF) || \
+ ((FLAG) == RTC_FLAG_ALRAWF))
+
+/* RTC_FLAG_ALRAWF is for Medium Density only but supported by High Density
+ Devices*/
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Flag to clear
+ */
+#define RTC_FLAG_CLRBLE (RTC_FLAG_RSF | RTC_FLAG_ALRAF | RTC_FLAG_WUTF| RTC_FLAG_TAMP1F|RTC_FLAG_TAMP2F|RTC_FLAG_TAMP3F)
+#define IS_RTC_CLEAR_FLAG(FLAG) (((FLAG) != RESET) && ((uint16_t)((FLAG) & (uint16_t)(~(RTC_FLAG_CLRBLE))) == RESET))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Interrupt to configure
+ */
+#define IS_RTC_CONFIG_IT(IT) (((uint16_t)(IT) != (uint8_t)RESET) && ((uint16_t)((uint16_t)(IT) & (uint16_t)(~(uint16_t)(RTC_IT_WUT|RTC_IT_ALRA|RTC_IT_TAMP))) == (uint8_t)RESET))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Interrupt to get
+ */
+#define IS_RTC_GET_IT(IT) (((IT) == RTC_IT_WUT) || \
+ ((IT) == RTC_IT_ALRA)|| \
+ ((IT) == RTC_IT_TAMP) )
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Interrupt to clear
+ */
+#define IS_RTC_CLEAR_IT(IT) (((IT) != RESET) && ((uint16_t)((IT) & (uint16_t)(~(uint16_t)(RTC_IT_WUT|RTC_IT_ALRA|RTC_IT_TAMP))) == RESET))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Tamper Levels
+ */
+#define IS_RTC_TAMPER_LEVEL(LEVEL) (((LEVEL) == RTC_TamperLevel_Low) || \
+ ((LEVEL) == RTC_TamperLevel_High))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Tamper
+ */
+#define NOT_CORRECT_TAMPER (uint8_t)~(uint8_t)( RTC_Tamper_1 | \
+ RTC_Tamper_2 | \
+ RTC_Tamper_3)
+#define IS_RTC_TAMPER(TAMPER) (((uint8_t)((TAMPER) & NOT_CORRECT_TAMPER) == RESET) && ((TAMPER) != RESET))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Tampers Filter
+ */
+#define IS_RTC_TAMPER_FILTER(SEL) (((SEL) == RTC_TamperFilter_1Sample) || \
+ ((SEL) == RTC_TamperFilter_2Sample) || \
+ ((SEL) == RTC_TamperFilter_4Sample) || \
+ ((SEL) == RTC_TamperFilter_8Sample))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Tampers Sampling Frequencies
+ */
+#define IS_RTC_TAMPER_SAMPLING_FREQ(SEL) ((SEL) <= RTC_TamperSamplingFreq_RTCCLK_Div256)
+
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Tampers Pins precharge duration
+ */
+#define IS_RTC_TAMPER_PINS_PRECHAR_DURATION(SEL) (((SEL) == RTC_TamperPrechargeDuration_None) || \
+ ((SEL) == RTC_TamperPrechargeDuration_1RTCCLK) || \
+ ((SEL) == RTC_TamperPrechargeDuration_2RTCCLK) || \
+ ((SEL) == RTC_TamperPrechargeDuration_4RTCCLK) || \
+ ((SEL) == RTC_TamperPrechargeDuration_8RTCCLK))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Smooth calibration period
+ */
+#define IS_RTC_SMOOTH_CALIB_PERIOD(SEL) (((SEL) == RTC_SmoothCalibPeriod_32sec) || \
+ ((SEL) == RTC_SmoothCalibPeriod_16sec) || \
+ ((SEL) == RTC_SmoothCalibPeriod_8sec))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Smooth calibration Plus pulses
+ */
+#define IS_RTC_SMOOTH_CALIB_PLUS(SEL) (((SEL) == RTC_SmoothCalibPlusPulses_Set) || \
+ ((SEL) == RTC_SmoothCalibPlusPulses_Reset))
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Smooth calibration Minus pulses
+ */
+#define IS_RTC_SMOOTH_CALIB_MINUS(VALUE) ((VALUE) <= 0x01FF)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Output Selection
+ */
+#define IS_RTC_OUTPUT_SELECT(SEL) (((SEL) == RTC_Output_Disable) || \
+ ((SEL) == RTC_Output_Alarm) || \
+ ((SEL) == RTC_Output_WakeUp))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the
+ * used calibration Output Selection
+ */
+#define IS_RTC_CALOUTPUT_SELECT(SEL) (((SEL) == RTC_CalibOutput_512Hz) || \
+ ((SEL) == RTC_CalibOutput_1Hz))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Alarm sub second value
+ */
+#define IS_RTC_ALARM_SS_VALUE(SS) ((SS) <= 0x7FFF)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * Alarm sub second mask
+ */
+#define IS_RTC_ALARM_SS_MASK(MASK) ((MASK) <= 0x0F)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the used
+ * fraction of seconds to sub
+ */
+#define IS_RTC_SHIFT_SUBFS(FS) ((FS) <= 0x7FFF)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the
+ * parameter of 1 second to add
+ */
+#define IS_RTC_SHIFT_ADD1S(VAL) (((VAL) == RTC_ShiftAdd1S_Set) || \
+ ((VAL) == RTC_ShiftAdd1S_Reset))
+
+/**
+ * @}
+ */
+/* Exported functions ------------------------------------------------------- */
+
+/* Function used to set the RTC configuration to the default reset state *****/
+ErrorStatus RTC_DeInit(void);
+
+/* Initialization and Configuration functions *********************************/
+ErrorStatus RTC_Init(RTC_InitTypeDef* RTC_InitStruct);
+void RTC_StructInit(RTC_InitTypeDef* RTC_InitStruct);
+void RTC_WriteProtectionCmd(FunctionalState NewState);
+ErrorStatus RTC_EnterInitMode(void);
+void RTC_ExitInitMode(void);
+ErrorStatus RTC_WaitForSynchro(void);
+void RTC_RatioCmd(FunctionalState NewState);
+void RTC_BypassShadowCmd(FunctionalState NewState);
+
+/* Time and Date configuration functions **************************************/
+ErrorStatus RTC_SetTime(RTC_Format_TypeDef RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
+void RTC_TimeStructInit(RTC_TimeTypeDef* RTC_TimeStruct);
+void RTC_GetTime(RTC_Format_TypeDef RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
+uint16_t RTC_GetSubSecond(void);
+ErrorStatus RTC_SetDate(RTC_Format_TypeDef RTC_Format, RTC_DateTypeDef* RTC_DateStruct);
+void RTC_DateStructInit(RTC_DateTypeDef* RTC_DateStruct);
+void RTC_GetDate(RTC_Format_TypeDef RTC_Format, RTC_DateTypeDef* RTC_DateStruct);
+
+/* Alarm configuration functions *********************************************/
+void RTC_SetAlarm(RTC_Format_TypeDef RTC_Format, RTC_AlarmTypeDef* RTC_AlarmStruct);
+void RTC_AlarmStructInit(RTC_AlarmTypeDef* RTC_AlarmStruct);
+void RTC_GetAlarm(RTC_Format_TypeDef RTC_Format, RTC_AlarmTypeDef* RTC_AlarmStruct);
+ErrorStatus RTC_AlarmCmd(FunctionalState NewState);
+ErrorStatus RTC_AlarmSubSecondConfig(uint16_t RTC_AlarmSubSecondValue,
+ RTC_AlarmSubSecondMask_TypeDef RTC_AlarmSubSecondMask);
+
+/* WakeUp Timer configuration functions ***************************************/
+void RTC_WakeUpClockConfig(RTC_WakeUpClock_TypeDef RTC_WakeUpClock);
+void RTC_SetWakeUpCounter(uint16_t RTC_WakeupCounter);
+uint16_t RTC_GetWakeUpCounter(void);
+ErrorStatus RTC_WakeUpCmd(FunctionalState NewState);
+
+/* Daylight Saving configuration functions ************************************/
+void RTC_DayLightSavingConfig(RTC_DayLightSaving_TypeDef RTC_DayLightSaving,
+ RTC_StoreOperation_TypeDef RTC_StoreOperation);
+RTC_StoreOperation_TypeDef RTC_GetStoreOperation(void);
+
+/* Output pin Configuration function ******************************************/
+void RTC_OutputConfig(RTC_Output_TypeDef RTC_Output,
+ RTC_OutputPolarity_TypeDef RTC_OutputPolarity);
+
+/* Shift control synchronisation function ************************************/
+ErrorStatus RTC_SynchroShiftConfig(RTC_ShiftAdd1S_TypeDef RTC_ShiftAdd1S,
+ uint16_t RTC_ShiftSubFS);
+
+/* Smooth Calibration functions **********************************************/
+ErrorStatus RTC_SmoothCalibConfig(RTC_SmoothCalibPeriod_TypeDef RTC_SmoothCalibPeriod,
+ RTC_SmoothCalibPlusPulses_TypeDef RTC_SmoothCalibPlusPulses,
+ uint16_t RTC_SmouthCalibMinusPulsesValue);
+
+/* Calibration configuration functions ****************************************/
+void RTC_CalibOutputConfig(RTC_CalibOutput_TypeDef RTC_CalibOutput);
+void RTC_CalibOutputCmd(FunctionalState NewState);
+
+/* Tampers configuration functions ********************************************/
+void RTC_TamperLevelConfig(RTC_Tamper_TypeDef RTC_Tamper,
+ RTC_TamperLevel_TypeDef RTC_TamperLevel);
+void RTC_TamperFilterConfig(RTC_TamperFilter_TypeDef RTC_TamperFilter);
+void RTC_TamperSamplingFreqConfig(RTC_TamperSamplingFreq_TypeDef RTC_TamperSamplingFreq);
+void RTC_TamperPinsPrechargeDuration(RTC_TamperPrechargeDuration_TypeDef RTC_TamperPrechargeDuration);
+void RTC_TamperCmd(RTC_Tamper_TypeDef RTC_Tamper,
+ FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void RTC_ITConfig(RTC_IT_TypeDef RTC_IT, FunctionalState NewState);
+FlagStatus RTC_GetFlagStatus(RTC_Flag_TypeDef RTC_FLAG);
+void RTC_ClearFlag(RTC_Flag_TypeDef RTC_FLAG);
+ITStatus RTC_GetITStatus(RTC_IT_TypeDef RTC_IT);
+void RTC_ClearITPendingBit(RTC_IT_TypeDef RTC_IT);
+
+#endif /*__STM8L15x_RTC_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_spi.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_spi.h
new file mode 100644
index 00000000..9587552a
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_spi.h
@@ -0,0 +1,404 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_spi.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the SPI firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_SPI_H
+#define __STM8L15x_SPI_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup SPI
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+/** @defgroup SPI_Exported_Types
+ * @{
+ */
+
+/** @defgroup SPI_Direction_Mode
+ * @brief element values correspond to BDM, BDOE, RXONLY bits position
+ * @{
+ */
+typedef enum {
+ SPI_Direction_2Lines_FullDuplex = (uint8_t)0x00, /*!< 2-line uni-directional data mode enable */
+ SPI_Direction_2Lines_RxOnly = (uint8_t)0x04, /*!< Receiver only in 2 line uni-directional data mode */
+ SPI_Direction_1Line_Rx = (uint8_t)0x80, /*!< Receiver only in 1 line bi-directional data mode */
+ SPI_Direction_1Line_Tx = (uint8_t)0xC0 /*!< Transmit only in 1 line bi-directional data mode */
+} SPI_DirectionMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_SlaveSelect_Management
+ * @brief element values correspond to LSBFIRST bit position
+ * @{
+ */
+typedef enum
+{
+ SPI_NSS_Soft = (uint8_t)0x02, /*!< Software slave management disabled */
+ SPI_NSS_Hard = (uint8_t)0x00 /*!< Software slave management enabled */
+} SPI_NSS_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Direction
+ * @{
+ */
+typedef enum
+{
+ SPI_Direction_Rx = (uint8_t)0x00, /*!< Select Rx receive direction in bi-directional mode */
+ SPI_Direction_Tx = (uint8_t)0x01 /*!< Select Tx transmission direction in bi-directional mode */
+} SPI_Direction_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Mode
+ * @{
+ */
+typedef enum
+{
+ SPI_Mode_Master = (uint8_t)0x04, /*!< SPI Master configuration */
+ SPI_Mode_Slave = (uint8_t)0x00 /*!< SPI Slave configuration */
+} SPI_Mode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_BaudRate_Prescaler
+ * @{
+ */
+typedef enum {
+ SPI_BaudRatePrescaler_2 = (uint8_t)0x00, /*!< SPI frequency = frequency(CPU)/2 */
+ SPI_BaudRatePrescaler_4 = (uint8_t)0x08, /*!< SPI frequency = frequency(CPU)/4 */
+ SPI_BaudRatePrescaler_8 = (uint8_t)0x10, /*!< SPI frequency = frequency(CPU)/8 */
+ SPI_BaudRatePrescaler_16 = (uint8_t)0x18, /*!< SPI frequency = frequency(CPU)/16 */
+ SPI_BaudRatePrescaler_32 = (uint8_t)0x20, /*!< SPI frequency = frequency(CPU)/32 */
+ SPI_BaudRatePrescaler_64 = (uint8_t)0x28, /*!< SPI frequency = frequency(CPU)/64 */
+ SPI_BaudRatePrescaler_128 = (uint8_t)0x30, /*!< SPI frequency = frequency(CPU)/128 */
+ SPI_BaudRatePrescaler_256 = (uint8_t)0x38 /*!< SPI frequency = frequency(CPU)/256 */
+} SPI_BaudRatePrescaler_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Clock_Polarity
+ * @{
+ */
+typedef enum
+{
+ SPI_CPOL_Low = (uint8_t)0x00, /*!< Clock to 0 when idle */
+ SPI_CPOL_High = (uint8_t)0x02 /*!< Clock to 1 when idle */
+} SPI_CPOL_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Clock_Phase
+ * @{
+ */
+typedef enum
+{
+ SPI_CPHA_1Edge = (uint8_t)0x00, /*!< The first clock transition is the first data capture edge */
+ SPI_CPHA_2Edge = (uint8_t)0x01 /*!< The second clock transition is the first data capture edge */
+} SPI_CPHA_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Frame_Format
+ * @{
+ */
+typedef enum
+{
+ SPI_FirstBit_MSB = (uint8_t)0x00, /*!< MSB bit will be transmitted first */
+ SPI_FirstBit_LSB = (uint8_t)0x80 /*!< LSB bit will be transmitted first */
+} SPI_FirstBit_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_DMA_requests
+ * @{
+ */
+typedef enum {
+ SPI_DMAReq_RX = (uint8_t)0x01, /*!< SPI DMA Rx transfer requests */
+ SPI_DMAReq_TX = (uint8_t)0x02 /*!< SPI DMA Tx transfer requests */
+} SPI_DMAReq_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_CRC
+ * @{
+ */
+typedef enum {
+ SPI_CRC_RX = (uint8_t)0x00, /*!< Select Tx CRC register */
+ SPI_CRC_TX = (uint8_t)0x01 /*!< Select Rx CRC register */
+} SPI_CRC_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Flags
+ * @{
+ */
+typedef enum {
+ SPI_FLAG_BSY = (uint8_t)0x80, /*!< Busy flag */
+ SPI_FLAG_OVR = (uint8_t)0x40, /*!< Overrun flag */
+ SPI_FLAG_MODF = (uint8_t)0x20, /*!< Mode fault */
+ SPI_FLAG_CRCERR = (uint8_t)0x10, /*!< CRC error flag */
+ SPI_FLAG_WKUP = (uint8_t)0x08, /*!< Wake-up flag */
+ SPI_FLAG_TXE = (uint8_t)0x02, /*!< Transmit buffer empty */
+ SPI_FLAG_RXNE = (uint8_t)0x01 /*!< Receive buffer empty */
+} SPI_FLAG_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Interrupts
+ * @brief SPI_IT possible values
+ * Elements values convention: 0xYX
+ * X: Position of the corresponding Interrupt
+ * Y: ITPENDINGBIT position
+ * @{
+ */
+typedef enum
+{
+ SPI_IT_WKUP = (uint8_t)0x34, /*!< Wake-up interrupt*/
+ SPI_IT_OVR = (uint8_t)0x65, /*!< Overrun interrupt*/
+ SPI_IT_MODF = (uint8_t)0x55, /*!< Mode fault interrupt*/
+ SPI_IT_CRCERR = (uint8_t)0x45, /*!< CRC error interrupt*/
+ SPI_IT_TXE = (uint8_t)0x17, /*!< Transmit buffer empty interrupt*/
+ SPI_IT_RXNE = (uint8_t)0x06, /*!< Receive buffer not empty interrupt*/
+ SPI_IT_ERR = (uint8_t)0x05 /*!< Error interrupt*/
+} SPI_IT_TypeDef;
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+
+/** @defgroup SPI_Exported_Macros
+ * @brief Macros used by the assert_param function to check the different functions parameters.
+ * @{
+ */
+
+/**
+ * @brief Macro used by the assert_param function in order to check the data direction mode values
+ */
+#define IS_SPI_DATA_DIRECTION(Mode) (((Mode) == SPI_Direction_2Lines_FullDuplex) || \
+ ((Mode) == SPI_Direction_2Lines_RxOnly) || \
+ ((Mode) == SPI_Direction_1Line_Rx) || \
+ ((Mode) == SPI_Direction_1Line_Tx))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the mode half duplex data direction values
+ */
+#define IS_SPI_DIRECTION(Direction) (((Direction) == SPI_Direction_Rx) || \
+ ((Direction) == SPI_Direction_Tx))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the NSS management values
+ */
+#define IS_SPI_SLAVEMANAGEMENT(NSS) (((NSS) == SPI_NSS_Soft) || \
+ ((NSS) == SPI_NSS_Hard))
+
+
+/**
+ * @brief Macro used by the assert_param function in order to check the different
+ * sensitivity values for the CRC polynomial
+ */
+#define IS_SPI_CRC_POLYNOMIAL(Polynomial) ((Polynomial) > (uint8_t)0x00)
+
+/**
+ * @brief Macro used by the assert_param function in order to check the SPI Mode values
+ */
+#define IS_SPI_MODE(Mode) (((Mode) == SPI_Mode_Master) || \
+ ((Mode) == SPI_Mode_Slave))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the baudrate values
+ */
+#define IS_SPI_BAUDRATE_PRESCALER(Prescaler) (((Prescaler) == SPI_BaudRatePrescaler_2) || \
+ ((Prescaler) == SPI_BaudRatePrescaler_4) || \
+ ((Prescaler) == SPI_BaudRatePrescaler_8) || \
+ ((Prescaler) == SPI_BaudRatePrescaler_16) || \
+ ((Prescaler) == SPI_BaudRatePrescaler_32) || \
+ ((Prescaler) == SPI_BaudRatePrescaler_64) || \
+ ((Prescaler) == SPI_BaudRatePrescaler_128) || \
+ ((Prescaler) == SPI_BaudRatePrescaler_256))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the polarity values
+ */
+#define IS_SPI_POLARITY(ClkPol) (((ClkPol) == SPI_CPOL_Low) || \
+ ((ClkPol) == SPI_CPOL_High))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the phase values
+ */
+#define IS_SPI_PHASE(ClkPha) (((ClkPha) == SPI_CPHA_1Edge) || \
+ ((ClkPha) == SPI_CPHA_2Edge))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the first bit
+ * to be transmitted values
+ */
+#define IS_SPI_FIRSTBIT(Bit) (((Bit) == SPI_FirstBit_MSB) || \
+ ((Bit) == SPI_FirstBit_LSB))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the CRC Transmit/Receive
+ */
+#define IS_SPI_CRC(CRC) (((CRC) == SPI_CRC_TX) || \
+ ((CRC) == SPI_CRC_RX))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the DMA transfer requests
+ */
+#define IS_SPI_DMAREQ(DMAREQ) ((((DMAREQ) & (uint16_t)0xFC) == 0x00) && ((DMAREQ) != 0x00))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the different flags values
+ */
+#define IS_SPI_FLAG(Flag) (((Flag) == SPI_FLAG_OVR) || \
+ ((Flag) == SPI_FLAG_MODF) || \
+ ((Flag) == SPI_FLAG_CRCERR) || \
+ ((Flag) == SPI_FLAG_WKUP) || \
+ ((Flag) == SPI_FLAG_TXE) || \
+ ((Flag) == SPI_FLAG_RXNE) || \
+ ((Flag) == SPI_FLAG_BSY))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the different
+ * sensitivity values for the flag that can be cleared by writing 0
+ */
+#define IS_SPI_CLEAR_FLAG(Flag) (((Flag) == SPI_FLAG_CRCERR) || \
+ ((Flag) == SPI_FLAG_WKUP))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the different
+ * sensitivity values for the Interrupts
+ */
+#define IS_SPI_CONFIG_IT(Interrupt) (((Interrupt) == SPI_IT_TXE) || \
+ ((Interrupt) == SPI_IT_RXNE) || \
+ ((Interrupt) == SPI_IT_ERR) || \
+ ((Interrupt) == SPI_IT_WKUP))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the different
+ * sensitivity values for the pending bit
+ */
+#define IS_SPI_GET_IT(ITPendingBit) (((ITPendingBit) == SPI_IT_OVR) || \
+ ((ITPendingBit) == SPI_IT_MODF) || \
+ ((ITPendingBit) == SPI_IT_CRCERR) || \
+ ((ITPendingBit) == SPI_IT_WKUP) || \
+ ((ITPendingBit) == SPI_IT_TXE) || \
+ ((ITPendingBit) == SPI_IT_RXNE))
+
+/**
+ * @brief Macro used by the assert_param function in order to check the different
+ * sensitivity values for the pending bit that can be cleared by writing 0
+ */
+#define IS_SPI_CLEAR_IT(ITPendingBit) (((ITPendingBit) == SPI_IT_CRCERR) || \
+ ((ITPendingBit) == SPI_IT_WKUP))
+
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+/* Function used to set the SPI configuration to the default reset state *****/
+void SPI_DeInit(SPI_TypeDef* SPIx);
+/* Initialization and Configuration functions *********************************/
+void SPI_Init(SPI_TypeDef* SPIx, SPI_FirstBit_TypeDef SPI_FirstBit,
+ SPI_BaudRatePrescaler_TypeDef SPI_BaudRatePrescaler,
+ SPI_Mode_TypeDef SPI_Mode, SPI_CPOL_TypeDef SPI_CPOL,
+ SPI_CPHA_TypeDef SPI_CPHA, SPI_DirectionMode_TypeDef SPI_Data_Direction,
+ SPI_NSS_TypeDef SPI_Slave_Management, uint8_t CRCPolynomial);
+void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);
+void SPI_NSSInternalSoftwareCmd(SPI_TypeDef* SPIx, FunctionalState NewState);
+void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, SPI_Direction_TypeDef SPI_Direction);
+
+/* Data transfers functions ***************************************************/
+void SPI_SendData(SPI_TypeDef* SPIx, uint8_t Data);
+uint8_t SPI_ReceiveData(SPI_TypeDef* SPIx);
+
+/* Hardware CRC Calculation functions *****************************************/
+void SPI_TransmitCRC(SPI_TypeDef* SPIx);
+void SPI_CalculateCRCCmd(SPI_TypeDef* SPIx, FunctionalState NewState);
+uint8_t SPI_GetCRC(SPI_TypeDef* SPIx, SPI_CRC_TypeDef SPI_CRC);
+void SPI_ResetCRC(SPI_TypeDef* SPIx);
+uint8_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx);
+
+/* DMA transfer management functions *****************************************/
+void SPI_DMACmd(SPI_TypeDef* SPIx, SPI_DMAReq_TypeDef SPI_DMAReq, FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void SPI_ITConfig(SPI_TypeDef* SPIx, SPI_IT_TypeDef SPI_IT, FunctionalState NewState);
+FlagStatus SPI_GetFlagStatus(SPI_TypeDef* SPIx, SPI_FLAG_TypeDef SPI_FLAG);
+void SPI_ClearFlag(SPI_TypeDef* SPIx, SPI_FLAG_TypeDef SPI_FLAG);
+ITStatus SPI_GetITStatus(SPI_TypeDef* SPIx, SPI_IT_TypeDef SPI_IT);
+void SPI_ClearITPendingBit(SPI_TypeDef* SPIx, SPI_IT_TypeDef SPI_IT);
+
+#endif /* __STM8L15x_SPI_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_syscfg.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_syscfg.h
new file mode 100644
index 00000000..c50c1888
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_syscfg.h
@@ -0,0 +1,424 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_syscfg.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the SYSCFG firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_SYSCFG_H
+#define __STM8L15x_SYSCFG_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup SYSCFG
+ * @{
+ */
+/* Exported types ------------------------------------------------------------*/
+/** @defgroup SYSCFG_Exported_Types
+ * @{
+ */
+
+/** @defgroup RI_Input_Capture
+ * @{
+ */
+typedef enum
+{
+ RI_InputCapture_IC2 = ((uint8_t) 0x02), /*!< TIM1 Input Capture 2 is routed */
+ RI_InputCapture_IC3 = ((uint8_t) 0x03) /*!< TIM1 Input Capture 3 is routed */
+}RI_InputCapture_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RI_Input_Capture_Routing
+ * @{
+ */
+typedef enum
+{
+ RI_InputCaptureRouting_0 = ((uint8_t) 0x00), /*!< TIM1 IC2 is routed to PD4, IC3 to PD5 */
+ RI_InputCaptureRouting_1 = ((uint8_t) 0x01), /*!< TIM1 IC2 is routed to PF0, IC3 to PF1 */
+ RI_InputCaptureRouting_2 = ((uint8_t) 0x02), /*!< TIM1 IC2 is routed to PF2, IC3 to PF3 */
+ RI_InputCaptureRouting_3 = ((uint8_t) 0x03), /*!< TIM1 IC2 is routed to PE0, IC3 to PE1 */
+ RI_InputCaptureRouting_4 = ((uint8_t) 0x04), /*!< TIM1 IC2 is routed to PE2, IC3 to PE3 */
+ RI_InputCaptureRouting_5 = ((uint8_t) 0x05), /*!< TIM1 IC2 is routed to PE4, IC3 to PE5 */
+ RI_InputCaptureRouting_6 = ((uint8_t) 0x06), /*!< TIM1 IC2 is routed to PE6, IC3 to PE7 */
+ RI_InputCaptureRouting_7 = ((uint8_t) 0x07), /*!< TIM1 IC2 is routed to PD0, IC3 to PD1 */
+ RI_InputCaptureRouting_8 = ((uint8_t) 0x08), /*!< TIM1 IC2 is routed to PD2, IC3 to PD3 */
+ RI_InputCaptureRouting_9 = ((uint8_t) 0x09), /*!< TIM1 IC2 is routed to PD4, IC3 to PD5 */
+ RI_InputCaptureRouting_10 = ((uint8_t) 0x0A), /*!< TIM1 IC2 is routed to PD6, IC3 to PD7 */
+ RI_InputCaptureRouting_11 = ((uint8_t) 0x0B), /*!< TIM1 IC2 is routed to PC0, IC3 to PC1 */
+ RI_InputCaptureRouting_12 = ((uint8_t) 0x0C), /*!< TIM1 IC2 is routed to PC2, IC3 to PC3 */
+ RI_InputCaptureRouting_13 = ((uint8_t) 0x0D), /*!< TIM1 IC2 is routed to PC4, IC3 to PC5 */
+ RI_InputCaptureRouting_14 = ((uint8_t) 0x0E), /*!< TIM1 IC2 is routed to PC6, IC3 to PC7 */
+ RI_InputCaptureRouting_15 = ((uint8_t) 0x0F), /*!< TIM1 IC2 is routed to PB0, IC3 to PB1 */
+ RI_InputCaptureRouting_16 = ((uint8_t) 0x10), /*!< TIM1 IC2 is routed to PB2, IC3 to PB3 */
+ RI_InputCaptureRouting_17 = ((uint8_t) 0x11), /*!< TIM1 IC2 is routed to PB4, IC3 to PB5 */
+ RI_InputCaptureRouting_18 = ((uint8_t) 0x12), /*!< TIM1 IC2 is routed to PB6, IC3 to PB7 */
+ RI_InputCaptureRouting_19 = ((uint8_t) 0x13), /*!< TIM1 IC2 is routed to PA0, IC3 to PA2 */
+ RI_InputCaptureRouting_20 = ((uint8_t) 0x14), /*!< TIM1 IC2 is routed to PA3, IC3 to PA4 */
+ RI_InputCaptureRouting_21 = ((uint8_t) 0x15), /*!< TIM1 IC2 is routed to PA5, IC3 to PA6 */
+ RI_InputCaptureRouting_22 = ((uint8_t) 0x16) /*!< TIM1 IC2 is routed to PA7, IC3 to PD5 */
+}RI_InputCaptureRouting_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RI_Analog_Switch
+ * @{
+ */
+/**
+ * @brief Definition of the Analog Switch to be controlled.
+ * Values are coded in 0xXY format where
+ * X: the register index (1: RI_ASCR1, 2: RI_ASCR2)
+ * Y: the bit position which corresponds with the Analog Switch
+ */
+typedef enum
+{
+ RI_AnalogSwitch_0 = ((uint8_t) 0x10), /*!< Analog switch 0 */
+ RI_AnalogSwitch_1 = ((uint8_t) 0x11), /*!< Analog switch 1 */
+ RI_AnalogSwitch_2 = ((uint8_t) 0x12), /*!< Analog switch 2 */
+ RI_AnalogSwitch_3 = ((uint8_t) 0x13), /*!< Analog switch 3 */
+ RI_AnalogSwitch_4 = ((uint8_t) 0x14), /*!< Analog switch 4 */
+ RI_AnalogSwitch_5 = ((uint8_t) 0x15), /*!< Analog switch 5 */
+ RI_AnalogSwitch_6 = ((uint8_t) 0x16), /*!< Analog switch 6 */
+ RI_AnalogSwitch_7 = ((uint8_t) 0x17), /*!< Analog switch 7 */
+ RI_AnalogSwitch_8 = ((uint8_t) 0x20), /*!< Analog switch 8 */
+ RI_AnalogSwitch_9 = ((uint8_t) 0x21), /*!< Analog switch 9 */
+ RI_AnalogSwitch_10 = ((uint8_t) 0x22), /*!< Analog switch 10 */
+ RI_AnalogSwitch_11 = ((uint8_t) 0x23), /*!< Analog switch 11 */
+ RI_AnalogSwitch_14 = ((uint8_t) 0x26) /*!< Analog switch 14 */
+}RI_AnalogSwitch_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RI_IO_Switch
+ * @{
+ */
+/**
+ * @brief Definition of the I/O Switch to be controlled.
+ * Values are coded in 0xXY format where
+ * X: the register index (1: RI_IOSR1, 2: RI_IOSR2, 3: RI_IOSR3 or 4: RI_IOSR4)
+ * Y: the bit index of the Input Output Switch in RI_IOSRx register
+ */
+typedef enum
+{
+ RI_IOSwitch_1 = ((uint8_t) 0x10), /*!< Input Output Switch switch 1 */
+ RI_IOSwitch_2 = ((uint8_t) 0x20), /*!< Input Output Switch switch 2 */
+ RI_IOSwitch_3 = ((uint8_t) 0x30), /*!< Input Output Switch switch 3 */
+ RI_IOSwitch_4 = ((uint8_t) 0x11), /*!< Input Output Switch switch 4 */
+ RI_IOSwitch_5 = ((uint8_t) 0x21), /*!< Input Output Switch switch 4 */
+ RI_IOSwitch_6 = ((uint8_t) 0x31), /*!< Input Output Switch switch 6 */
+ RI_IOSwitch_7 = ((uint8_t) 0x12), /*!< Input Output Switch switch 7 */
+ RI_IOSwitch_8 = ((uint8_t) 0x22), /*!< Input Output Switch switch 8 */
+ RI_IOSwitch_9 = ((uint8_t) 0x32), /*!< Input Output Switch switch 9 */
+ RI_IOSwitch_10 = ((uint8_t) 0x13), /*!< Input Output Switch switch 10 */
+ RI_IOSwitch_11 = ((uint8_t) 0x23), /*!< Input Output Switch switch 11 */
+ RI_IOSwitch_12 = ((uint8_t) 0x33), /*!< Input Output Switch switch 12 */
+ RI_IOSwitch_13 = ((uint8_t) 0x14), /*!< Input Output Switch switch 13 */
+ RI_IOSwitch_14 = ((uint8_t) 0x24), /*!< Input Output Switch switch 14 */
+ RI_IOSwitch_15 = ((uint8_t) 0x34), /*!< Input Output Switch switch 15 */
+ RI_IOSwitch_16 = ((uint8_t) 0x15), /*!< Input Output Switch switch 16 */
+ RI_IOSwitch_17 = ((uint8_t) 0x25), /*!< Input Output Switch switch 17 */
+ RI_IOSwitch_18 = ((uint8_t) 0x35), /*!< Input Output Switch switch 18 */
+ RI_IOSwitch_19 = ((uint8_t) 0x16), /*!< Input Output Switch switch 19 */
+ RI_IOSwitch_20 = ((uint8_t) 0x26), /*!< Input Output Switch switch 20 */
+ RI_IOSwitch_21 = ((uint8_t) 0x36), /*!< Input Output Switch switch 21 */
+ RI_IOSwitch_22 = ((uint8_t) 0x17), /*!< Input Output Switch switch 22 */
+ RI_IOSwitch_23 = ((uint8_t) 0x27), /*!< Input Output Switch switch 23 */
+ RI_IOSwitch_24 = ((uint8_t) 0x37), /*!< Input Output Switch switch 24 */
+ RI_IOSwitch_26 = ((uint8_t) 0x41), /*!< Input Output Switch switch 26 */
+ RI_IOSwitch_27 = ((uint8_t) 0x46), /*!< Input Output Switch switch 27 */
+ RI_IOSwitch_28 = ((uint8_t) 0x47), /*!< Input Output Switch switch 28 */
+ RI_IOSwitch_29 = ((uint8_t) 0x40) /*!< Input Output Switch switch 29 */
+}RI_IOSwitch_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup RI_Resistor
+ * @{
+ */
+/**
+ * @brief Definition of the pull-up and pull-down resistors for COMP1 and ADC.
+ */
+typedef enum
+{
+ RI_Resistor_10KPU = ((uint8_t) 0x01),
+ RI_Resistor_400KPU = ((uint8_t) 0x02),
+ RI_Resistor_10KPD = ((uint8_t) 0x04),
+ RI_Resistor_400KPD = ((uint8_t) 0x08)
+}RI_Resistor_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup REMAP_Pin
+ * @{
+ */
+/**
+ * @brief Definition of the REMAP pins.
+ * Elements values convention: 0xXY
+ * X = RMPCRx registers index
+ * X = 0x01 : RMPCR1
+ * X = 0x02 : RMPCR2
+ * X = 0x03 : RMPCR3
+ * Y = Mask for setting/resetting bits in RMPCRx register
+ */
+typedef enum
+{
+ /* RMPCR1 register bits */
+ REMAP_Pin_USART1TxRxPortA = ((uint16_t)0x011C), /*!< USART1 Tx- Rx (PC3- PC2) remapping to PA2- PA3 */
+ REMAP_Pin_USART1TxRxPortC = ((uint16_t)0x012C), /*!< USART1 Tx- Rx (PC3- PC2) remapping to PC5- PC6 */
+ REMAP_Pin_USART1Clk = ((uint16_t)0x014B), /*!< USART1 CK (PC4) remapping to PA0 */
+ REMAP_Pin_SPI1Full = ((uint16_t)0x0187), /*!< SPI1 MISO- MOSI- SCK- NSS(PB7- PB6- PB5- PB4)
+ remapping to PA2- PA3- PC6- PC5 */
+ /* RMPCR2 register bits */
+ REMAP_Pin_ADC1ExtTRIG1 = ((uint16_t)0x0201), /*!< ADC1 External Trigger 1 (PA6) remapping to PD0 */
+ REMAP_Pin_TIM2TRIGPortA = ((uint16_t)0x0202), /*!< TIM2 Trigger (PB3) remapping to PA4 */
+ REMAP_Pin_TIM3TRIGPortA = ((uint16_t)0x0204), /*!< TIM3 Trigger (PD1) remapping to PA5 */
+ REMAP_Pin_TIM2TRIGLSE = ((uint16_t)0x0208), /*!< TIM2 Trigger remapping to LSE */
+ REMAP_Pin_TIM3TRIGLSE = ((uint16_t)0x0210), /*!< TIM3 Trigger remapping to LSE */
+ REMAP_Pin_SPI2Full = ((uint16_t)0x0220), /*!< SPI2 MISO- MOSI- SCK- NSS(PG7- PG6- PG5- PG4)
+ remapping to PI3- PI2- PI1- PI0 */
+ REMAP_Pin_TIM3TRIGPortG = ((uint16_t)0x0240), /*!< TIM3 Trigger (PD1) remapping to PG3 */
+ REMAP_Pin_TIM23BKIN = ((uint16_t)0x0280), /*!< TIM2 Break Input (PA4) remapping to PG0
+ and TIM3 Break Input (PA5) remapping to PG1 */
+ /* RMPCR3 register bits */
+ REMAP_Pin_SPI1PortF = ((uint16_t)0x0301), /*!< SPI1 MISO- MOSI- SCK- NSS(PB7- PB6- PB5- PB4)
+ remapping to PF0- PF1- PF2- PF3 */
+ REMAP_Pin_USART3TxRxPortF = ((uint16_t)0x0302), /*!< USART3 Tx- Rx (PG1- PG0) remapping to PF0- PF1 */
+ REMAP_Pin_USART3Clk = ((uint16_t)0x0304), /*!< USART3 CK (PG2) remapping to PF2 */
+ REMAP_Pin_TIM3Channel1 = ((uint16_t)0x0308), /*!< TIM3 Channel 1 (PB1) remapping to PI0 */
+ REMAP_Pin_TIM3Channel2 = ((uint16_t)0x0310), /*!< TIM3 Channel 2 (PD0) remapping to PI3 */
+ REMAP_Pin_CCO = ((uint16_t)0x0320), /*!< CCO (PC4) remapping to PE2 */
+ REMAP_Pin_TIM2Channel1 = ((uint16_t)0x0340), /*!< TIM2 Channel 1 (PB0) remapping to PC5 */
+ REMAP_Pin_TIM2Channel2 = ((uint16_t)0x0380) /*!< TIM2 Channel 2 (PB2) remapping to PC6 */
+}REMAP_Pin_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup REMAP_DMA_Channel
+ * @{
+ */
+typedef enum
+{
+ REMAP_DMA1Channel_ADC1ToChannel0 = ((uint8_t)0x00), /*!< ADC1 DMA1 req/ack mapped on DMA1 channel 0 */
+ REMAP_DMA1Channel_ADC1ToChannel1 = ((uint8_t)0x01), /*!< ADC1 DMA1 req/ack mapped on DMA1 channel 1 */
+ REMAP_DMA1Channel_ADC1ToChannel2 = ((uint8_t)0x02), /*!< ADC1 DMA1 req/ack mapped on DMA1 channel 2 */
+ REMAP_DMA1Channel_ADC1ToChannel3 = ((uint8_t)0x03), /*!< ADC1 DMA1 req/ack mapped on DMA1 channel 3 */
+ REMAP_DMA1Channel_TIM4ToChannel0 = ((uint8_t)0xF0), /*!< TIM4 DMA1 req/ack mapped on DMA1 channel 0 */
+ REMAP_DMA1Channel_TIM4ToChannel1 = ((uint8_t)0xF4), /*!< TIM4 DMA1 req/ack mapped on DMA1 channel 1 */
+ REMAP_DMA1Channel_TIM4ToChannel2 = ((uint8_t)0xF8), /*!< TIM4 DMA1 req/ack mapped on DMA1 channel 2 */
+ REMAP_DMA1Channel_TIM4ToChannel3 = ((uint8_t)0xFC) /*!< TIM4 DMA1 req/ack mapped on DMA1 channel 3 */
+}REMAP_DMAChannel_TypeDef;
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+/** @defgroup SYSCFG_Exported_Macros
+ * @{
+ */
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * values of @ref RI_InputCaptureTypeDef enum.
+ */
+#define IS_RI_INPUTCAPTURE(RI_IC) (((RI_IC) == RI_InputCapture_IC2) || \
+ ((RI_IC) == RI_InputCapture_IC3))
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * values of @ref RI_InputCaptureRoutingTypeDef enum.
+ */
+#define IS_RI_INPUTCAPTUREROUTING(RI_IC_ROUTING) (((RI_IC_ROUTING) == RI_InputCaptureRouting_0) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_1) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_2) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_3) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_4) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_5) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_6) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_7) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_8) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_9) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_10) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_11) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_12) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_13) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_14) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_15) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_16) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_17) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_18) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_19) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_20) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_21) || \
+ ((RI_IC_ROUTING) == RI_InputCaptureRouting_22))
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * values of @ref RI_AnalogSwitch_TypeDef enum.
+ */
+#define IS_RI_ANALOGSWITCH(RI_ANALOGSWITCH) (((RI_ANALOGSWITCH) == RI_AnalogSwitch_0) || \
+ ((RI_ANALOGSWITCH) == RI_AnalogSwitch_1) || \
+ ((RI_ANALOGSWITCH) == RI_AnalogSwitch_2) || \
+ ((RI_ANALOGSWITCH) == RI_AnalogSwitch_3) || \
+ ((RI_ANALOGSWITCH) == RI_AnalogSwitch_4) || \
+ ((RI_ANALOGSWITCH) == RI_AnalogSwitch_5) || \
+ ((RI_ANALOGSWITCH) == RI_AnalogSwitch_6) || \
+ ((RI_ANALOGSWITCH) == RI_AnalogSwitch_7) || \
+ ((RI_ANALOGSWITCH) == RI_AnalogSwitch_8) || \
+ ((RI_ANALOGSWITCH) == RI_AnalogSwitch_9) || \
+ ((RI_ANALOGSWITCH) == RI_AnalogSwitch_10)|| \
+ ((RI_ANALOGSWITCH) == RI_AnalogSwitch_11)|| \
+ ((RI_ANALOGSWITCH) == RI_AnalogSwitch_14))
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * values of @ref RI_IOSwitch_TypeDef enum.
+ */
+#define IS_RI_IOSWITCH(RI_IOSWITCH) (((RI_IOSWITCH) == RI_IOSwitch_1) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_2) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_3) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_4) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_5) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_6) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_7) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_8) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_9) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_10) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_11) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_12) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_13) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_14) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_15) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_16) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_17) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_18) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_19) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_20) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_21) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_22) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_23) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_24) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_26) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_27) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_28) || \
+ ((RI_IOSWITCH) == RI_IOSwitch_29))
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * values of @ref RI_ResistorTypeDef enum.
+ */
+#define IS_RI_RESISTOR(RI_RESISTOR) (((RI_RESISTOR) == RI_Resistor_10KPU) || \
+ ((RI_RESISTOR) == RI_Resistor_400KPU) || \
+ ((RI_RESISTOR) == RI_Resistor_10KPD) || \
+ ((RI_RESISTOR) == RI_Resistor_400KPD))
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * values of @ref REMAP_Pin_TypeDef enum.
+ */
+#define IS_REMAP_PIN(PIN) (((PIN) == REMAP_Pin_USART1TxRxPortA) || \
+ ((PIN) == REMAP_Pin_USART1TxRxPortC) || \
+ ((PIN) == REMAP_Pin_USART1Clk) || \
+ ((PIN) == REMAP_Pin_SPI1Full) || \
+ ((PIN) == REMAP_Pin_ADC1ExtTRIG1) || \
+ ((PIN) == REMAP_Pin_TIM2TRIGPortA) || \
+ ((PIN) == REMAP_Pin_TIM3TRIGPortA) || \
+ ((PIN) == REMAP_Pin_TIM2TRIGLSE) || \
+ ((PIN) == REMAP_Pin_TIM3TRIGLSE) || \
+ ((PIN) == REMAP_Pin_SPI2Full) || \
+ ((PIN) == REMAP_Pin_TIM3TRIGPortG) || \
+ ((PIN) == REMAP_Pin_TIM23BKIN) || \
+ ((PIN) == REMAP_Pin_SPI1PortF) || \
+ ((PIN) == REMAP_Pin_USART3TxRxPortF) || \
+ ((PIN) == REMAP_Pin_USART3Clk) || \
+ ((PIN) == REMAP_Pin_TIM3Channel1) || \
+ ((PIN) == REMAP_Pin_TIM3Channel2) || \
+ ((PIN) == REMAP_Pin_CCO) || \
+ ((PIN) == REMAP_Pin_TIM2Channel1) || \
+ ((PIN) == REMAP_Pin_TIM2Channel2))
+
+
+/**
+ * @brief Macro used by the assert function in order to check the different
+ * values of the @ref REMAP_DMAChannel_TypeDef enum.
+ */
+#define IS_REMAP_DMACHANNEL(MAP) (((MAP) == REMAP_DMA1Channel_ADC1ToChannel0) || \
+ ((MAP) == REMAP_DMA1Channel_ADC1ToChannel1) || \
+ ((MAP) == REMAP_DMA1Channel_ADC1ToChannel2) || \
+ ((MAP) == REMAP_DMA1Channel_ADC1ToChannel3) || \
+ ((MAP) == REMAP_DMA1Channel_TIM4ToChannel0) || \
+ ((MAP) == REMAP_DMA1Channel_TIM4ToChannel1) || \
+ ((MAP) == REMAP_DMA1Channel_TIM4ToChannel2) || \
+ ((MAP) == REMAP_DMA1Channel_TIM4ToChannel3))
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+/* Routing Interface (RI) configuration ***************************************/
+void SYSCFG_RIDeInit(void);
+void SYSCFG_RITIMInputCaptureConfig(RI_InputCapture_TypeDef RI_InputCapture,
+ RI_InputCaptureRouting_TypeDef RI_InputCaptureRouting);
+void SYSCFG_RIAnalogSwitchConfig(RI_AnalogSwitch_TypeDef RI_AnalogSwitch,
+ FunctionalState NewState);
+void SYSCFG_RIIOSwitchConfig(RI_IOSwitch_TypeDef RI_IOSwitch, FunctionalState NewState);
+void SYSCFG_RIResistorConfig(RI_Resistor_TypeDef RI_Resistor, FunctionalState NewState);
+
+/* SYSCFG configuration *******************************************************/
+void SYSCFG_REMAPDeInit(void);
+void SYSCFG_REMAPPinConfig(REMAP_Pin_TypeDef REMAP_Pin, FunctionalState NewState);
+void SYSCFG_REMAPDMAChannelConfig(REMAP_DMAChannel_TypeDef REMAP_DMAChannel);
+
+#endif /* __STM8L15x_SYSCFG_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim1.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim1.h
new file mode 100644
index 00000000..5be45287
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim1.h
@@ -0,0 +1,1044 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_tim1.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the TIM1 firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_TIM1_H
+#define __STM8L15x_TIM1_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup TIM1
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+/** @defgroup TIM1_Exported_Types
+ * @{
+ */
+
+/** @defgroup TIM1_Output_Compare_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM1_OCMode_Timing = ((uint8_t)0x00),
+ TIM1_OCMode_Active = ((uint8_t)0x10),
+ TIM1_OCMode_Inactive = ((uint8_t)0x20),
+ TIM1_OCMode_Toggle = ((uint8_t)0x30),
+ TIM1_OCMode_PWM1 = ((uint8_t)0x60),
+ TIM1_OCMode_PWM2 = ((uint8_t)0x70)
+}TIM1_OCMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_One_Pulse_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM1_OPMode_Single = ((uint8_t)0x01),
+ TIM1_OPMode_Repetitive = ((uint8_t)0x00)
+}TIM1_OPMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Channels
+ * @{
+ */
+typedef enum
+{
+ TIM1_Channel_1 = ((uint8_t)0x00),
+ TIM1_Channel_2 = ((uint8_t)0x01),
+ TIM1_Channel_3 = ((uint8_t)0x02),
+ TIM1_Channel_4 = ((uint8_t)0x03)
+}TIM1_Channel_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Counter_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM1_CounterMode_Up = ((uint8_t)0x00),
+ TIM1_CounterMode_Down = ((uint8_t)0x10),
+ TIM1_CounterMode_CenterAligned1 = ((uint8_t)0x20),
+ TIM1_CounterMode_CenterAligned2 = ((uint8_t)0x40),
+ TIM1_CounterMode_CenterAligned3 = ((uint8_t)0x60)
+}TIM1_CounterMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Output_Compare_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM1_OCPolarity_High = ((uint8_t)0x00),
+ TIM1_OCPolarity_Low = ((uint8_t)0x22)
+}TIM1_OCPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Output_Compare_N_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM1_OCNPolarity_High = ((uint8_t)0x00),
+ TIM1_OCNPolarity_Low = ((uint8_t)0x88)
+}TIM1_OCNPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Output_State
+ * @{
+ */
+typedef enum
+{
+ TIM1_OutputState_Disable = ((uint8_t)0x00),
+ TIM1_OutputState_Enable = ((uint8_t)0x11)
+}TIM1_OutputState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Output_N_State
+ * @{
+ */
+typedef enum
+{
+ TIM1_OutputNState_Disable = ((uint8_t)0x00),
+ TIM1_OutputNState_Enable = ((uint8_t)0x44)
+} TIM1_OutputNState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Break_State
+ * @{
+ */
+typedef enum
+{
+ TIM1_BreakState_Enable = ((uint8_t)0x10),
+ TIM1_BreakState_Disable = ((uint8_t)0x00)
+}TIM1_BreakState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Break_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM1_BreakPolarity_Low = ((uint8_t)0x00),
+ TIM1_BreakPolarity_High = ((uint8_t)0x20)
+}TIM1_BreakPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Automatic_Output
+ * @{
+ */
+typedef enum
+{
+ TIM1_AutomaticOutput_Enable = ((uint8_t)0x40),
+ TIM1_AutomaticOutput_Disable = ((uint8_t)0x00)
+}TIM1_AutomaticOutput_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Lock_Level
+ * @{
+ */
+typedef enum
+{
+ TIM1_LockLevel_Off = ((uint8_t)0x00),
+ TIM1_LockLevel_1 = ((uint8_t)0x01),
+ TIM1_LockLevel_2 = ((uint8_t)0x02),
+ TIM1_LockLevel_3 = ((uint8_t)0x03)
+}TIM1_LockLevel_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_OSSI_State
+ * @{
+ */
+typedef enum
+{
+ TIM1_OSSIState_Enable = ((uint8_t)0x04),
+ TIM1_OSSIState_Disable = ((uint8_t)0x00)
+}TIM1_OSSIState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Output_Compare_Idle_state
+ * @{
+ */
+typedef enum
+{
+ TIM1_OCIdleState_Set = ((uint8_t)0x55),
+ TIM1_OCIdleState_Reset = ((uint8_t)0x00)
+}TIM1_OCIdleState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Output_Compare_N_Idle_state
+ * @{
+ */
+typedef enum
+{
+ TIM1_OCNIdleState_Set = ((uint8_t)0x2A),
+ TIM1_OCNIdleState_Reset = ((uint8_t)0x00)
+}TIM1_OCNIdleState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Input_Capture_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM1_ICPolarity_Rising = ((uint8_t)0x00),
+ TIM1_ICPolarity_Falling = ((uint8_t)0x01)
+}TIM1_ICPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Input_Capture_Selection
+ * @{
+ */
+typedef enum
+{
+ TIM1_ICSelection_DirectTI = ((uint8_t)0x01),
+ TIM1_ICSelection_IndirectTI = ((uint8_t)0x02),
+ TIM1_ICSelection_TRGI = ((uint8_t)0x03)
+}TIM1_ICSelection_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Input_Capture_Prescaler
+ * @{
+ */
+typedef enum
+{
+ TIM1_ICPSC_DIV1 = ((uint8_t)0x00),
+ TIM1_ICPSC_DIV2 = ((uint8_t)0x04),
+ TIM1_ICPSC_DIV4 = ((uint8_t)0x08),
+ TIM1_ICPSC_DIV8 = ((uint8_t)0x0C)
+}TIM1_ICPSC_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Output_Compare_Reference_Clear
+ * @{
+ */
+typedef enum
+{
+ TIM1_OCReferenceClear_ETRF = ((uint8_t)0x08),
+ TIM1_OCReferenceClear_OCREFCLR = ((uint8_t)0x00)
+}
+TIM1_OCReferenceClear_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Interrupts
+ * @{
+ */
+typedef enum
+{
+ TIM1_IT_Update = ((uint8_t)0x01),
+ TIM1_IT_CC1 = ((uint8_t)0x02),
+ TIM1_IT_CC2 = ((uint8_t)0x04),
+ TIM1_IT_CC3 = ((uint8_t)0x08),
+ TIM1_IT_CC4 = ((uint8_t)0x10),
+ TIM1_IT_COM = ((uint8_t)0x20),
+ TIM1_IT_Trigger = ((uint8_t)0x40),
+ TIM1_IT_Break = ((uint8_t)0x80)
+}TIM1_IT_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_External_Trigger_Prescaler
+ * @{
+ */
+typedef enum
+{
+ TIM1_ExtTRGPSC_OFF = ((uint8_t)0x00),
+ TIM1_ExtTRGPSC_DIV2 = ((uint8_t)0x10),
+ TIM1_ExtTRGPSC_DIV4 = ((uint8_t)0x20),
+ TIM1_ExtTRGPSC_DIV8 = ((uint8_t)0x30)
+}TIM1_ExtTRGPSC_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Internal_Trigger_Selection
+ * @{
+ */
+typedef enum
+{
+ TIM1_TRGSelection_TIM4 = ((uint8_t)0x00), /*!< TRIG Input source = TIM TRIG Output */
+ TIM1_TRGSelection_TIM5 = ((uint8_t)0x10), /*!< TRIG Input source = TIM TRIG Output */
+ TIM1_TRGSelection_TIM3 = ((uint8_t)0x20), /*!< TRIG Input source = TIM TRIG Output */
+ TIM1_TRGSelection_TIM2 = ((uint8_t)0x30), /*!< TRIG Input source = TIM TRIG Output */
+ TIM1_TRGSelection_TI1F_ED = ((uint8_t)0x40),
+ TIM1_TRGSelection_TI1FP1 = ((uint8_t)0x50),
+ TIM1_TRGSelection_TI2FP2 = ((uint8_t)0x60),
+ TIM1_TRGSelection_ETRF = ((uint8_t)0x70)
+}TIM1_TRGSelection_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_TI_External_Clock_Source
+ * @{
+ */
+typedef enum
+{
+ TIM1_TIxExternalCLK1Source_TI1ED = ((uint8_t)0x40),
+ TIM1_TIxExternalCLK1Source_TI1 = ((uint8_t)0x50),
+ TIM1_TIxExternalCLK1Source_TI2 = ((uint8_t)0x60)
+}TIM1_TIxExternalCLK1Source_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_External_Trigger_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM1_ExtTRGPolarity_Inverted = ((uint8_t)0x80),
+ TIM1_ExtTRGPolarity_NonInverted = ((uint8_t)0x00)
+}TIM1_ExtTRGPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Prescaler_Reload_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM1_PSCReloadMode_Update = ((uint8_t)0x00),
+ TIM1_PSCReloadMode_Immediate = ((uint8_t)0x01)
+}TIM1_PSCReloadMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Encoder_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM1_EncoderMode_TI1 = ((uint8_t)0x01),
+ TIM1_EncoderMode_TI2 = ((uint8_t)0x02),
+ TIM1_EncoderMode_TI12 = ((uint8_t)0x03)
+}TIM1_EncoderMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Event_Source
+ * @{
+ */
+typedef enum
+{
+ TIM1_EventSource_Update = ((uint8_t)0x01),
+ TIM1_EventSource_CC1 = ((uint8_t)0x02),
+ TIM1_EventSource_CC2 = ((uint8_t)0x04),
+ TIM1_EventSource_CC3 = ((uint8_t)0x08),
+ TIM1_EventSource_CC4 = ((uint8_t)0x10),
+ TIM1_EventSource_COM = ((uint8_t)0x20),
+ TIM1_EventSource_Trigger = ((uint8_t)0x40),
+ TIM1_EventSource_Break = ((uint8_t)0x80)
+}TIM1_EventSource_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Update_Source
+ * @{
+ */
+typedef enum
+{
+ TIM1_UpdateSource_Global = ((uint8_t)0x00),
+ TIM1_UpdateSource_Regular = ((uint8_t)0x01)
+}TIM1_UpdateSource_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Trigger_Output_Source
+ * @{
+ */
+typedef enum
+{
+ TIM1_TRGOSource_Reset = ((uint8_t)0x00),
+ TIM1_TRGOSource_Enable = ((uint8_t)0x10),
+ TIM1_TRGOSource_Update = ((uint8_t)0x20),
+ TIM1_TRGOSource_OC1 = ((uint8_t)0x30),
+ TIM1_TRGOSource_OC1REF = ((uint8_t)0x40),
+ TIM1_TRGOSource_OC2REF = ((uint8_t)0x50),
+ TIM1_TRGOSource_OC3REF = ((uint8_t)0x60),
+ TIM1_TRGOSource_OC4REF = ((uint8_t)0x70)
+}TIM1_TRGOSource_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Slave_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM1_SlaveMode_Reset = ((uint8_t)0x04),
+ TIM1_SlaveMode_Gated = ((uint8_t)0x05),
+ TIM1_SlaveMode_Trigger = ((uint8_t)0x06),
+ TIM1_SlaveMode_External1 = ((uint8_t)0x07)
+}TIM1_SlaveMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Flags
+ * @{
+ */
+typedef enum
+{
+ TIM1_FLAG_Update = ((uint16_t)0x0001),
+ TIM1_FLAG_CC1 = ((uint16_t)0x0002),
+ TIM1_FLAG_CC2 = ((uint16_t)0x0004),
+ TIM1_FLAG_CC3 = ((uint16_t)0x0008),
+ TIM1_FLAG_CC4 = ((uint16_t)0x0010),
+ TIM1_FLAG_COM = ((uint16_t)0x0020),
+ TIM1_FLAG_Trigger = ((uint16_t)0x0040),
+ TIM1_FLAG_Break = ((uint16_t)0x0080),
+ TIM1_FLAG_CC1OF = ((uint16_t)0x0200),
+ TIM1_FLAG_CC2OF = ((uint16_t)0x0400),
+ TIM1_FLAG_CC3OF = ((uint16_t)0x0800),
+ TIM1_FLAG_CC4OF = ((uint16_t)0x1000)
+}TIM1_FLAG_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Forced_Action
+ * @{
+ */
+typedef enum
+{
+ TIM1_ForcedAction_Active = ((uint8_t)0x50),
+ TIM1_ForcedAction_Inactive = ((uint8_t)0x40)
+}TIM1_ForcedAction_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_DMA_Source_Requests
+ * @{
+ */
+typedef enum
+{
+ TIM1_DMASource_Update = ((uint8_t)0x01), /*!< TIM1 DMA Update Request*/
+ TIM1_DMASource_CC1 = ((uint8_t)0x02), /*!< TIM1 DMA CC1 Request*/
+ TIM1_DMASource_CC2 = ((uint8_t)0x04), /*!< TIM1 DMA CC2 Request*/
+ TIM1_DMASource_CC3 = ((uint8_t)0x08), /*!< TIM1 DMA CC3 Request*/
+ TIM1_DMASource_CC4 = ((uint8_t)0x10), /*!< TIM1 DMA CC4 Request*/
+ TIM1_DMASource_COM = ((uint8_t)0x20) /*!< TIM1 DMA COM Req */
+} TIM1_DMASource_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_DMA_Base_Address
+ * @{
+ */
+typedef enum
+{
+ TIM1_DMABase_CR1 = ((uint8_t)0x00),
+ TIM1_DMABase_CR2 = ((uint8_t)0x01),
+ TIM1_DMABase_SMCR = ((uint8_t)0x02),
+ TIM1_DMABase_ETR = ((uint8_t)0x03),
+ TIM1_DMABase_DER = ((uint8_t)0x04),
+ TIM1_DMABase_IER = ((uint8_t)0x05),
+ TIM1_DMABase_SR1 = ((uint8_t)0x06),
+ TIM1_DMABase_SR2 = ((uint8_t)0x07),
+ TIM1_DMABase_EGR = ((uint8_t)0x08),
+ TIM1_DMABase_CCMR1 = ((uint8_t)0x09),
+ TIM1_DMABase_CCMR2 = ((uint8_t)0x0A),
+ TIM1_DMABase_CCMR3 = ((uint8_t)0x0B),
+ TIM1_DMABase_CCMR4 = ((uint8_t)0x0C),
+ TIM1_DMABase_CCER1 = ((uint8_t)0x0D),
+ TIM1_DMABase_CCER2 = ((uint8_t)0x0E),
+ TIM1_DMABase_CNTH = ((uint8_t)0x0F),
+ TIM1_DMABase_CNTL = ((uint8_t)0x10),
+ TIM1_DMABase_PSCH = ((uint8_t)0x11),
+ TIM1_DMABase_PSCL = ((uint8_t)0x12),
+ TIM1_DMABase_ARRH = ((uint8_t)0x13),
+ TIM1_DMABase_ARRL = ((uint8_t)0x14),
+ TIM1_DMABase_RCR = ((uint8_t)0x15),
+ TIM1_DMABase_CCR1H = ((uint8_t)0x16),
+ TIM1_DMABase_CCR1L = ((uint8_t)0x17),
+ TIM1_DMABase_CCR2H = ((uint8_t)0x18),
+ TIM1_DMABase_CCR2L = ((uint8_t)0x19),
+ TIM1_DMABase_CCR3H = ((uint8_t)0x1A),
+ TIM1_DMABase_CCR3L = ((uint8_t)0x1B),
+ TIM1_DMABase_CCR4H = ((uint8_t)0x1C),
+ TIM1_DMABase_CCR4L = ((uint8_t)0x1D),
+ TIM1_DMABase_BKR = ((uint8_t)0x1E),
+ TIM1_DMABase_DTR = ((uint8_t)0x1F)
+
+} TIM1_DMABase_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_DMA_Burst_Length
+ * @{
+ */
+typedef enum
+{
+ TIM1_DMABurstLength_1Byte = ((uint8_t)0x00),
+ TIM1_DMABurstLength_2Byte = ((uint8_t)0x01),
+ TIM1_DMABurstLength_3Byte = ((uint8_t)0x02),
+ TIM1_DMABurstLength_4Byte = ((uint8_t)0x03),
+ TIM1_DMABurstLength_5Byte = ((uint8_t)0x04),
+ TIM1_DMABurstLength_6Byte = ((uint8_t)0x05),
+ TIM1_DMABurstLength_7Byte = ((uint8_t)0x06),
+ TIM1_DMABurstLength_8Byte = ((uint8_t)0x07),
+ TIM1_DMABurstLength_9Byte = ((uint8_t)0x08),
+ TIM1_DMABurstLength_10Byte = ((uint8_t)0x09),
+ TIM1_DMABurstLength_11Byte = ((uint8_t)0x0A),
+ TIM1_DMABurstLength_12Byte = ((uint8_t)0x0B),
+ TIM1_DMABurstLength_13Byte = ((uint8_t)0x0C),
+ TIM1_DMABurstLength_14Byte = ((uint8_t)0x0D),
+ TIM1_DMABurstLength_15Byte = ((uint8_t)0x0E),
+ TIM1_DMABurstLength_16Byte = ((uint8_t)0x0F),
+ TIM1_DMABurstLength_17Byte = ((uint8_t)0x10),
+ TIM1_DMABurstLength_18Byte = ((uint8_t)0x11),
+ TIM1_DMABurstLength_19Byte = ((uint8_t)0x12),
+ TIM1_DMABurstLength_20Byte = ((uint8_t)0x13),
+ TIM1_DMABurstLength_21Byte = ((uint8_t)0x14),
+ TIM1_DMABurstLength_22Byte = ((uint8_t)0x15),
+ TIM1_DMABurstLength_23Byte = ((uint8_t)0x16),
+ TIM1_DMABurstLength_24Byte = ((uint8_t)0x17),
+ TIM1_DMABurstLength_25Byte = ((uint8_t)0x18),
+ TIM1_DMABurstLength_26Byte = ((uint8_t)0x19),
+ TIM1_DMABurstLength_27Byte = ((uint8_t)0x1A),
+ TIM1_DMABurstLength_28Byte = ((uint8_t)0x1B),
+ TIM1_DMABurstLength_29Byte = ((uint8_t)0x1C),
+ TIM1_DMABurstLength_30Byte = ((uint8_t)0x1D),
+ TIM1_DMABurstLength_31Byte = ((uint8_t)0x1E),
+ TIM1_DMABurstLength_32Byte = ((uint8_t)0x1F)
+
+} TIM1_DMABurstLength_TypeDef;
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+/** @defgroup TIM1_Exported_Macros
+ * @{
+ */
+#define IS_TIM1_OC_MODE(MODE) (((MODE) == TIM1_OCMode_Timing) || \
+ ((MODE) == TIM1_OCMode_Active) || \
+ ((MODE) == TIM1_OCMode_Inactive) || \
+ ((MODE) == TIM1_OCMode_Toggle)|| \
+ ((MODE) == TIM1_OCMode_PWM1) || \
+ ((MODE) == TIM1_OCMode_PWM2))
+
+#define IS_TIM1_OCM(MODE)(((MODE) == TIM1_OCMode_Timing) || \
+ ((MODE) == TIM1_OCMode_Active) || \
+ ((MODE) == TIM1_OCMode_Inactive) || \
+ ((MODE) == TIM1_OCMode_Toggle)|| \
+ ((MODE) == TIM1_OCMode_PWM1) || \
+ ((MODE) == TIM1_OCMode_PWM2) || \
+ ((MODE) == (uint8_t)TIM1_ForcedAction_Active) || \
+ ((MODE) == (uint8_t)TIM1_ForcedAction_Inactive))
+
+#define IS_TIM1_OPM_MODE(MODE) (((MODE) == TIM1_OPMode_Single) || \
+ ((MODE) == TIM1_OPMode_Repetitive))
+
+#define IS_TIM1_CHANNEL(CHANNEL) (((CHANNEL) == TIM1_Channel_1) || \
+ ((CHANNEL) == TIM1_Channel_2) || \
+ ((CHANNEL) == TIM1_Channel_3) || \
+ ((CHANNEL) == TIM1_Channel_4))
+
+#define IS_TIM1_PWMI_CHANNEL(CHANNEL) (((CHANNEL) == TIM1_Channel_1) || \
+ ((CHANNEL) == TIM1_Channel_2))
+
+#define IS_TIM1_COMPLEMENTARY_CHANNEL(CHANNEL) (((CHANNEL) == TIM1_Channel_1) || \
+ ((CHANNEL) == TIM1_Channel_2) || \
+ ((CHANNEL) == TIM1_Channel_3))
+
+#define IS_TIM1_COUNTER_MODE(MODE) (((MODE) == TIM1_CounterMode_Up) || \
+ ((MODE) == TIM1_CounterMode_Down) || \
+ ((MODE) == TIM1_CounterMode_CenterAligned1) || \
+ ((MODE) == TIM1_CounterMode_CenterAligned2) || \
+ ((MODE) == TIM1_CounterMode_CenterAligned3))
+
+#define IS_TIM1_OC_POLARITY(POLARITY) (((POLARITY) == TIM1_OCPolarity_High) || \
+ ((POLARITY) == TIM1_OCPolarity_Low))
+
+#define IS_TIM1_OCN_POLARITY(POLARITY) (((POLARITY) == TIM1_OCNPolarity_High) || \
+ ((POLARITY) == TIM1_OCNPolarity_Low))
+
+#define IS_TIM1_OUTPUT_STATE(STATE) (((STATE) == TIM1_OutputState_Disable) || \
+ ((STATE) == TIM1_OutputState_Enable))
+
+#define IS_TIM1_OUTPUTN_STATE(STATE) (((STATE) == TIM1_OutputNState_Disable) ||\
+ ((STATE) == TIM1_OutputNState_Enable))
+
+#define IS_TIM1_BREAK_STATE(STATE) (((STATE) == TIM1_BreakState_Enable) || \
+ ((STATE) == TIM1_BreakState_Disable))
+
+#define IS_TIM1_BREAK_POLARITY(POLARITY) (((POLARITY) == TIM1_BreakPolarity_Low) || \
+ ((POLARITY) == TIM1_BreakPolarity_High))
+
+#define IS_TIM1_AUTOMATIC_OUTPUT_STATE(STATE) (((STATE) == TIM1_AutomaticOutput_Enable) || \
+ ((STATE) == TIM1_AutomaticOutput_Disable))
+
+#define IS_TIM1_LOCK_LEVEL(LEVEL) (((LEVEL) == TIM1_LockLevel_Off) || \
+ ((LEVEL) == TIM1_LockLevel_1) || \
+ ((LEVEL) == TIM1_LockLevel_2) || \
+ ((LEVEL) == TIM1_LockLevel_3))
+
+#define IS_TIM1_OSSI_STATE(STATE) (((STATE) == TIM1_OSSIState_Enable) || \
+ ((STATE) == TIM1_OSSIState_Disable))
+
+#define IS_TIM1_OCIDLE_STATE(STATE) (((STATE) == TIM1_OCIdleState_Set) || \
+ ((STATE) == TIM1_OCIdleState_Reset))
+
+#define IS_TIM1_OCNIDLE_STATE(STATE) (((STATE) == TIM1_OCNIdleState_Set) || \
+ ((STATE) == TIM1_OCNIdleState_Reset))
+
+#define IS_TIM1_IC_POLARITY(POLARITY) (((POLARITY) == TIM1_ICPolarity_Rising) || \
+ ((POLARITY) == TIM1_ICPolarity_Falling))
+
+#define IS_TIM1_IC_SELECTION(SELECTION) (((SELECTION) == TIM1_ICSelection_DirectTI) || \
+ ((SELECTION) == TIM1_ICSelection_IndirectTI) || \
+ ((SELECTION) == TIM1_ICSelection_TRGI))
+
+#define IS_TIM1_IC_PRESCALER(PRESCALER) (((PRESCALER) == TIM1_ICPSC_DIV1) || \
+ ((PRESCALER) == TIM1_ICPSC_DIV2) || \
+ ((PRESCALER) == TIM1_ICPSC_DIV4) || \
+ ((PRESCALER) == TIM1_ICPSC_DIV8))
+
+#define IS_TIM1_OCREFERENCECECLEAR_SOURCE(SOURCE) (((SOURCE) == TIM1_OCReferenceClear_ETRF) || \
+ ((SOURCE) == TIM1_OCReferenceClear_OCREFCLR))
+
+#define IS_TIM1_IT(IT) ((IT) != 0x00)
+
+#define IS_TIM1_GET_IT(IT) (((IT) == TIM1_IT_Update) || \
+ ((IT) == TIM1_IT_CC1) || \
+ ((IT) == TIM1_IT_CC2) || \
+ ((IT) == TIM1_IT_CC3) || \
+ ((IT) == TIM1_IT_CC4) || \
+ ((IT) == TIM1_IT_COM) || \
+ ((IT) == TIM1_IT_Trigger) || \
+ ((IT) == TIM1_IT_Break))
+
+#define IS_TIM1_EXT_PRESCALER(PRESCALER) (((PRESCALER) == TIM1_ExtTRGPSC_OFF) || \
+ ((PRESCALER) == TIM1_ExtTRGPSC_DIV2) || \
+ ((PRESCALER) == TIM1_ExtTRGPSC_DIV4) || \
+ ((PRESCALER) == TIM1_ExtTRGPSC_DIV8))
+
+#define IS_TIM1_TRIGGER_SELECTION(SELECTION) \
+ (((SELECTION) == TIM1_TRGSelection_TIM2) || \
+ ((SELECTION) == TIM1_TRGSelection_TIM3) || \
+ ((SELECTION) == TIM1_TRGSelection_TIM4) || \
+ ((SELECTION) == TIM1_TRGSelection_TIM5) || \
+ ((SELECTION) == TIM1_TRGSelection_TI1F_ED) || \
+ ((SELECTION) == TIM1_TRGSelection_TI1FP1) || \
+ ((SELECTION) == TIM1_TRGSelection_TI2FP2) || \
+ ((SELECTION) == TIM1_TRGSelection_ETRF))
+
+
+#define IS_TIM1_TIX_TRIGGER_SELECTION(SELECTION) \
+ (((SELECTION) == TIM1_TRGSelection_TI1F_ED) || \
+ ((SELECTION) == TIM1_TRGSelection_TI1FP1) || \
+ ((SELECTION) == TIM1_TRGSelection_TI2FP2))
+
+#define IS_TIM1_TIXCLK_SOURCE(SOURCE) (((SOURCE) == TIM1_TIxExternalCLK1Source_TI1ED) || \
+ ((SOURCE) == TIM1_TIxExternalCLK1Source_TI2) || \
+ ((SOURCE) == TIM1_TIxExternalCLK1Source_TI1))
+
+#define IS_TIM1_EXT_POLARITY(POLARITY) (((POLARITY) == TIM1_ExtTRGPolarity_Inverted) || \
+ ((POLARITY) == TIM1_ExtTRGPolarity_NonInverted))
+
+#define IS_TIM1_PRESCALER_RELOAD(RELOAD) (((RELOAD) == TIM1_PSCReloadMode_Update) || \
+ ((RELOAD) == TIM1_PSCReloadMode_Immediate))
+
+#define IS_TIM1_ENCODER_MODE(MODE) (((MODE) == TIM1_EncoderMode_TI1) || \
+ ((MODE) == TIM1_EncoderMode_TI2) || \
+ ((MODE) == TIM1_EncoderMode_TI12))
+
+#define IS_TIM1_EVENT_SOURCE(SOURCE) ((SOURCE) != 0x00)
+
+#define IS_TIM1_TRGO_SOURCE(SOURCE) (((SOURCE) == TIM1_TRGOSource_Reset) || \
+ ((SOURCE) == TIM1_TRGOSource_Enable) || \
+ ((SOURCE) == TIM1_TRGOSource_Update) || \
+ ((SOURCE) == TIM1_TRGOSource_OC1) || \
+ ((SOURCE) == TIM1_TRGOSource_OC1REF) || \
+ ((SOURCE) == TIM1_TRGOSource_OC2REF) || \
+ ((SOURCE) == TIM1_TRGOSource_OC3REF) || \
+ ((SOURCE) == TIM1_TRGOSource_OC4REF))
+
+
+#define IS_TIM1_UPDATE_SOURCE(SOURCE) (((SOURCE) == TIM1_UpdateSource_Global) || \
+ ((SOURCE) == TIM1_UpdateSource_Regular))
+
+#define IS_TIM1_GET_FLAG(FLAG) (((FLAG) == TIM1_FLAG_Update) || \
+ ((FLAG) == TIM1_FLAG_CC1) || \
+ ((FLAG) == TIM1_FLAG_CC2) || \
+ ((FLAG) == TIM1_FLAG_CC3) || \
+ ((FLAG) == TIM1_FLAG_CC4) || \
+ ((FLAG) == TIM1_FLAG_COM) || \
+ ((FLAG) == TIM1_FLAG_Trigger)|| \
+ ((FLAG) == TIM1_FLAG_Break) || \
+ ((FLAG) == TIM1_FLAG_CC1OF) || \
+ ((FLAG) == TIM1_FLAG_CC2OF) || \
+ ((FLAG) == TIM1_FLAG_CC3OF) || \
+ ((FLAG) == TIM1_FLAG_CC4OF))
+
+
+#define IS_TIM1_SLAVE_MODE(MODE) (((MODE) == TIM1_SlaveMode_Reset) || \
+ ((MODE) == TIM1_SlaveMode_Gated) || \
+ ((MODE) == TIM1_SlaveMode_Trigger) || \
+ ((MODE) == TIM1_SlaveMode_External1))
+
+#define IS_TIM1_CLEAR_FLAG(FLAG) ((((uint16_t)(FLAG) & (uint16_t)0xE100) == 0x0000) && ((FLAG) != 0x0000))
+
+#define IS_TIM1_FORCED_ACTION(ACTION) (((ACTION) == TIM1_ForcedAction_Active) || \
+ ((ACTION) == TIM1_ForcedAction_Inactive))
+
+#define IS_TIM1_DMA_SOURCE(SOURCE) \
+ (((SOURCE) == TIM1_DMASource_Update) || \
+ ((SOURCE) == TIM1_DMASource_CC1) || \
+ ((SOURCE) == TIM1_DMASource_CC2) || \
+ ((SOURCE) == TIM1_DMASource_CC3) || \
+ ((SOURCE) == TIM1_DMASource_CC4) || \
+ ((SOURCE) == TIM1_DMASource_COM))
+
+#define IS_TIM1_DMABase(SOURCE) \
+ (((SOURCE) == TIM1_DMABase_CR1) || \
+ ((SOURCE) == TIM1_DMABase_CR2) || \
+ ((SOURCE) == TIM1_DMABase_SMCR) || \
+ ((SOURCE) == TIM1_DMABase_ETR) || \
+ ((SOURCE) == TIM1_DMABase_DER) || \
+ ((SOURCE) == TIM1_DMABase_IER) || \
+ ((SOURCE) == TIM1_DMABase_SR1) || \
+ ((SOURCE) == TIM1_DMABase_SR2) || \
+ ((SOURCE) == TIM1_DMABase_EGR) || \
+ ((SOURCE) == TIM1_DMABase_CCMR1) || \
+ ((SOURCE) == TIM1_DMABase_CCMR2 ) || \
+ ((SOURCE) == TIM1_DMABase_CCMR3) || \
+ ((SOURCE) == TIM1_DMABase_CCMR4) || \
+ ((SOURCE) == TIM1_DMABase_CCER1) || \
+ ((SOURCE) == TIM1_DMABase_CCER2) || \
+ ((SOURCE) == TIM1_DMABase_CNTH) || \
+ ((SOURCE) == TIM1_DMABase_CNTL) || \
+ ((SOURCE) == TIM1_DMABase_PSCH) || \
+ ((SOURCE) == TIM1_DMABase_PSCL) || \
+ ((SOURCE) == TIM1_DMABase_ARRH) || \
+ ((SOURCE) == TIM1_DMABase_ARRL) || \
+ ((SOURCE) == TIM1_DMABase_RCR) || \
+ ((SOURCE) == TIM1_DMABase_CCR1H) || \
+ ((SOURCE) == TIM1_DMABase_CCR1L) || \
+ ((SOURCE) == TIM1_DMABase_CCR2H ) || \
+ ((SOURCE) == TIM1_DMABase_CCR2L) || \
+ ((SOURCE) == TIM1_DMABase_CCR3H) || \
+ ((SOURCE) == TIM1_DMABase_CCR3L) || \
+ ((SOURCE) == TIM1_DMABase_CCR4H) || \
+ ((SOURCE) == TIM1_DMABase_CCR4L) || \
+ ((SOURCE) == TIM1_DMABase_BKR) || \
+ ((SOURCE) == TIM1_DMABase_DTR))
+
+#define IS_TIM1_DMABurstLength(SOURCE) \
+ (((SOURCE) == TIM1_DMABurstLength_1Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_2Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_3Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_4Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_5Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_6Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_7Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_8Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_9Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_10Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_11Byte ) || \
+ ((SOURCE) == TIM1_DMABurstLength_12Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_13Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_14Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_15Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_16Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_17Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_18Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_19Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_20Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_21Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_22Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_23Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_24Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_25Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_26Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_27Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_28Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_29Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_30Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_31Byte) || \
+ ((SOURCE) == TIM1_DMABurstLength_32Byte))
+
+/** TIM1 External Trigger Filer Value */
+#define IS_TIM1_EXT_TRG_FILTER(FILTER) ((FILTER) <= 0x0F)
+
+/** TIM1 Input Capture Filer Value */
+#define IS_TIM1_IC_FILTER(ICFILTER) ((ICFILTER) <= 0x0F)
+/**
+ * @}
+ */
+
+/* Exported Functions -----------------------------------------------------------*/
+
+/* TimeBase management ********************************************************/
+void TIM1_DeInit(void);
+void TIM1_TimeBaseInit(uint16_t TIM1_Prescaler,
+ TIM1_CounterMode_TypeDef TIM1_CounterMode,
+ uint16_t TIM1_Period,
+ uint8_t TIM1_RepetitionCounter);
+void TIM1_PrescalerConfig(uint16_t Prescaler,
+ TIM1_PSCReloadMode_TypeDef TIM1_PSCReloadMode);
+void TIM1_CounterModeConfig(TIM1_CounterMode_TypeDef TIM1_CounterMode);
+void TIM1_SetCounter(uint16_t Counter);
+void TIM1_SetAutoreload(uint16_t Autoreload);
+uint16_t TIM1_GetCounter(void);
+uint16_t TIM1_GetPrescaler(void);
+void TIM1_UpdateDisableConfig(FunctionalState NewState);
+void TIM1_UpdateRequestConfig(TIM1_UpdateSource_TypeDef TIM1_UpdateSource);
+void TIM1_ARRPreloadConfig(FunctionalState NewState);
+void TIM1_SelectOnePulseMode(TIM1_OPMode_TypeDef TIM1_OPMode);
+void TIM1_Cmd(FunctionalState NewState);
+
+/* Output Compare management **************************************************/
+void TIM1_OC1Init(TIM1_OCMode_TypeDef TIM1_OCMode,
+ TIM1_OutputState_TypeDef TIM1_OutputState,
+ TIM1_OutputNState_TypeDef TIM1_OutputNState,
+ uint16_t TIM1_Pulse,
+ TIM1_OCPolarity_TypeDef TIM1_OCPolarity,
+ TIM1_OCNPolarity_TypeDef TIM1_OCNPolarity,
+ TIM1_OCIdleState_TypeDef TIM1_OCIdleState,
+ TIM1_OCNIdleState_TypeDef TIM1_OCNIdleState);
+void TIM1_OC2Init(TIM1_OCMode_TypeDef TIM1_OCMode,
+ TIM1_OutputState_TypeDef TIM1_OutputState,
+ TIM1_OutputNState_TypeDef TIM1_OutputNState,
+ uint16_t TIM1_Pulse,
+ TIM1_OCPolarity_TypeDef TIM1_OCPolarity,
+ TIM1_OCNPolarity_TypeDef TIM1_OCNPolarity,
+ TIM1_OCIdleState_TypeDef TIM1_OCIdleState,
+ TIM1_OCNIdleState_TypeDef TIM1_OCNIdleState);
+void TIM1_OC3Init(TIM1_OCMode_TypeDef TIM1_OCMode,
+ TIM1_OutputState_TypeDef TIM1_OutputState,
+ TIM1_OutputNState_TypeDef TIM1_OutputNState,
+ uint16_t TIM1_Pulse,
+ TIM1_OCPolarity_TypeDef TIM1_OCPolarity,
+ TIM1_OCNPolarity_TypeDef TIM1_OCNPolarity,
+ TIM1_OCIdleState_TypeDef TIM1_OCIdleState,
+ TIM1_OCNIdleState_TypeDef TIM1_OCNIdleState);
+void TIM1_BDTRConfig(TIM1_OSSIState_TypeDef TIM1_OSSIState,
+ TIM1_LockLevel_TypeDef TIM1_LockLevel,
+ uint8_t TIM1_DeadTime,
+ TIM1_BreakState_TypeDef TIM1_Break,
+ TIM1_BreakPolarity_TypeDef TIM1_BreakPolarity,
+ TIM1_AutomaticOutput_TypeDef TIM1_AutomaticOutput);
+void TIM1_CtrlPWMOutputs(FunctionalState NewState);
+void TIM1_SelectOCxM(TIM1_Channel_TypeDef TIM1_Channel, TIM1_OCMode_TypeDef TIM1_OCMode);
+void TIM1_SetCompare1(uint16_t Compare1);
+void TIM1_SetCompare2(uint16_t Compare2);
+void TIM1_SetCompare3(uint16_t Compare3);
+void TIM1_SetCompare4(uint16_t Compare4);
+void TIM1_CCPreloadControl(FunctionalState NewState);
+void TIM1_ForcedOC1Config(TIM1_ForcedAction_TypeDef TIM1_ForcedAction);
+void TIM1_ForcedOC2Config(TIM1_ForcedAction_TypeDef TIM1_ForcedAction);
+void TIM1_ForcedOC3Config(TIM1_ForcedAction_TypeDef TIM1_ForcedAction);
+void TIM1_OC1PreloadConfig(FunctionalState NewState);
+void TIM1_OC2PreloadConfig(FunctionalState NewState);
+void TIM1_OC3PreloadConfig(FunctionalState NewState);
+void TIM1_OC4PreloadConfig(FunctionalState NewState);
+void TIM1_OC1FastConfig(FunctionalState NewState);
+void TIM1_OC2FastConfig(FunctionalState NewState);
+void TIM1_OC3FastConfig(FunctionalState NewState);
+void TIM1_ClearOC1Ref(FunctionalState NewState);
+void TIM1_ClearOC2Ref(FunctionalState NewState);
+void TIM1_ClearOC3Ref(FunctionalState NewState);
+void TIM1_ClearOC4Ref(FunctionalState NewState);
+void TIM1_OC1PolarityConfig(TIM1_OCPolarity_TypeDef TIM1_OCPolarity);
+void TIM1_OC1NPolarityConfig(TIM1_OCNPolarity_TypeDef TIM1_OCNPolarity);
+void TIM1_OC2PolarityConfig(TIM1_OCPolarity_TypeDef TIM1_OCPolarity);
+void TIM1_OC2NPolarityConfig(TIM1_OCNPolarity_TypeDef TIM1_OCNPolarity);
+void TIM1_OC3PolarityConfig(TIM1_OCPolarity_TypeDef TIM1_OCPolarity);
+void TIM1_OC3NPolarityConfig(TIM1_OCNPolarity_TypeDef TIM1_OCNPolarity);
+void TIM1_SelectOCREFClear(TIM1_OCReferenceClear_TypeDef TIM1_OCReferenceClear);
+void TIM1_SelectCOM(FunctionalState NewState);
+void TIM1_CCxCmd(TIM1_Channel_TypeDef TIM1_Channel, FunctionalState NewState);
+void TIM1_CCxNCmd(TIM1_Channel_TypeDef TIM1_Channel, FunctionalState NewState);
+
+/* Input Capture management ***************************************************/
+void TIM1_ICInit(TIM1_Channel_TypeDef TIM1_Channel,
+ TIM1_ICPolarity_TypeDef TIM1_ICPolarity,
+ TIM1_ICSelection_TypeDef TIM1_ICSelection,
+ TIM1_ICPSC_TypeDef TIM1_ICPrescaler,
+ uint8_t TIM1_ICFilter);
+void TIM1_PWMIConfig(TIM1_Channel_TypeDef TIM1_Channel,
+ TIM1_ICPolarity_TypeDef TIM1_ICPolarity,
+ TIM1_ICSelection_TypeDef TIM1_ICSelection,
+ TIM1_ICPSC_TypeDef TIM1_ICPrescaler,
+ uint8_t TIM1_ICFilter);
+uint16_t TIM1_GetCapture1(void);
+uint16_t TIM1_GetCapture2(void);
+uint16_t TIM1_GetCapture3(void);
+uint16_t TIM1_GetCapture4(void);
+void TIM1_SetIC1Prescaler(TIM1_ICPSC_TypeDef TIM1_IC1Prescaler);
+void TIM1_SetIC2Prescaler(TIM1_ICPSC_TypeDef TIM1_IC2Prescaler);
+void TIM1_SetIC3Prescaler(TIM1_ICPSC_TypeDef TIM1_IC3Prescaler);
+void TIM1_SetIC4Prescaler(TIM1_ICPSC_TypeDef TIM1_IC4Prescaler);
+
+/* Interrupts, DMA and flags management ***************************************/
+void TIM1_ITConfig(TIM1_IT_TypeDef TIM1_IT, FunctionalState NewState);
+void TIM1_GenerateEvent(TIM1_EventSource_TypeDef TIM1_EventSource);
+FlagStatus TIM1_GetFlagStatus(TIM1_FLAG_TypeDef TIM1_FLAG);
+void TIM1_ClearFlag(TIM1_FLAG_TypeDef TIM1_FLAG);
+ITStatus TIM1_GetITStatus(TIM1_IT_TypeDef TIM1_IT);
+void TIM1_ClearITPendingBit(TIM1_IT_TypeDef TIM1_IT);
+void TIM1_DMAConfig(TIM1_DMABase_TypeDef TIM1_DMABase,
+ TIM1_DMABurstLength_TypeDef TIM1_DMABurstLength);
+void TIM1_DMACmd(TIM1_DMASource_TypeDef TIM1_DMASource, FunctionalState NewState);
+void TIM1_SelectCCDMA(FunctionalState NewState);
+
+/* Clocks management **********************************************************/
+void TIM1_InternalClockConfig(void);
+void TIM1_TIxExternalClockConfig(TIM1_TIxExternalCLK1Source_TypeDef TIM1_TIxExternalCLKSource,
+ TIM1_ICPolarity_TypeDef TIM1_ICPolarity,
+ uint8_t ICFilter);
+void TIM1_ETRClockMode1Config(TIM1_ExtTRGPSC_TypeDef TIM1_ExtTRGPrescaler,
+ TIM1_ExtTRGPolarity_TypeDef TIM1_ExtTRGPolarity,
+ uint8_t ExtTRGFilter);
+void TIM1_ETRClockMode2Config(TIM1_ExtTRGPSC_TypeDef TIM1_ExtTRGPrescaler,
+ TIM1_ExtTRGPolarity_TypeDef TIM1_ExtTRGPolarity,
+ uint8_t ExtTRGFilter);
+
+/* Synchronization management *************************************************/
+void TIM1_SelectInputTrigger(TIM1_TRGSelection_TypeDef TIM1_InputTriggerSource);
+void TIM1_SelectOutputTrigger(TIM1_TRGOSource_TypeDef TIM1_TRGOSource);
+void TIM1_SelectSlaveMode(TIM1_SlaveMode_TypeDef TIM1_SlaveMode);
+void TIM1_SelectMasterSlaveMode(FunctionalState NewState);
+void TIM1_ETRConfig(TIM1_ExtTRGPSC_TypeDef TIM1_ExtTRGPrescaler,
+ TIM1_ExtTRGPolarity_TypeDef TIM1_ExtTRGPolarity,
+ uint8_t ExtTRGFilter);
+
+/* Specific interface management **********************************************/
+void TIM1_EncoderInterfaceConfig(TIM1_EncoderMode_TypeDef TIM1_EncoderMode,
+ TIM1_ICPolarity_TypeDef TIM1_IC1Polarity,
+ TIM1_ICPolarity_TypeDef TIM1_IC2Polarity);
+void TIM1_SelectHallSensor(FunctionalState NewState);
+
+#endif /* __STM8L15x_TIM1_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim2.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim2.h
new file mode 100644
index 00000000..101608fe
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim2.h
@@ -0,0 +1,905 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_tim2.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the TIM2 firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_TIM2_H
+#define __STM8L15x_TIM2_H
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup TIM2
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup TIM2_Exported_Types
+ * @{
+ */
+
+/** @defgroup TIM2_Forced_Action
+ * @{
+ */
+typedef enum
+{
+ TIM2_ForcedAction_Active = ((uint8_t)0x50), /*!< Output Reference is forced low */
+ TIM2_ForcedAction_Inactive = ((uint8_t)0x40) /*!< Output Reference is forced high */
+}
+TIM2_ForcedAction_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Prescaler
+ * @{
+ */
+typedef enum
+{
+ TIM2_Prescaler_1 = ((uint8_t)0x00), /*!< Time base Prescaler = 1 (No effect)*/
+ TIM2_Prescaler_2 = ((uint8_t)0x01), /*!< Time base Prescaler = 2 */
+ TIM2_Prescaler_4 = ((uint8_t)0x02), /*!< Time base Prescaler = 4 */
+ TIM2_Prescaler_8 = ((uint8_t)0x03), /*!< Time base Prescaler = 8 */
+ TIM2_Prescaler_16 = ((uint8_t)0x04), /*!< Time base Prescaler = 16 */
+ TIM2_Prescaler_32 = ((uint8_t)0x05), /*!< Time base Prescaler = 32 */
+ TIM2_Prescaler_64 = ((uint8_t)0x06), /*!< Time base Prescaler = 64 */
+ TIM2_Prescaler_128 = ((uint8_t)0x07) /*!< Time base Prescaler = 128 */
+}TIM2_Prescaler_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_OCMode
+ * @{
+ */
+typedef enum
+{
+ TIM2_OCMode_Timing = ((uint8_t)0x00), /*!< Timing (Frozen) Mode*/
+ TIM2_OCMode_Active = ((uint8_t)0x10), /*!< Active Mode*/
+ TIM2_OCMode_Inactive = ((uint8_t)0x20), /*!< Inactive Mode*/
+ TIM2_OCMode_Toggle = ((uint8_t)0x30), /*!< Toggle Mode*/
+ TIM2_OCMode_PWM1 = ((uint8_t)0x60), /*!< PWM Mode 1*/
+ TIM2_OCMode_PWM2 = ((uint8_t)0x70) /*!< PWM Mode 2*/
+}TIM2_OCMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_OnePulseMode
+ * @{
+ */
+typedef enum
+{
+ TIM2_OPMode_Single = ((uint8_t)0x01), /*!< Single one Pulse mode (OPM Active) */
+ TIM2_OPMode_Repetitive = ((uint8_t)0x00) /*!< Repetitive Pulse mode (OPM inactive) */
+}TIM2_OPMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Channel
+ * @{
+ */
+typedef enum
+{
+ TIM2_Channel_1 = ((uint8_t)0x00), /*!< Channel 1*/
+ TIM2_Channel_2 = ((uint8_t)0x01) /*!< Channel 2*/
+}TIM2_Channel_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_CounterMode
+ * @{
+ */
+typedef enum
+{
+ TIM2_CounterMode_Up = ((uint8_t)0x00), /*!< Counter Up Mode */
+ TIM2_CounterMode_Down = ((uint8_t)0x10), /*!< Counter Down Mode */
+ TIM2_CounterMode_CenterAligned1 = ((uint8_t)0x20), /*!< Counter Central aligned Mode 1 */
+ TIM2_CounterMode_CenterAligned2 = ((uint8_t)0x40), /*!< Counter Central aligned Mode 2 */
+ TIM2_CounterMode_CenterAligned3 = ((uint8_t)0x60) /*!< Counter Central aligned Mode 3 */
+}TIM2_CounterMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Output_Compare_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM2_OCPolarity_High = ((uint8_t)0x00), /*!< Output compare polarity = High */
+ TIM2_OCPolarity_Low = ((uint8_t)0x01) /*!< Output compare polarity = Low */
+}TIM2_OCPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Output_State
+ * @{
+ */
+typedef enum
+{
+ TIM2_OutputState_Disable = ((uint8_t)0x00), /*!< Output compare State disabled (channel output disabled) */
+ TIM2_OutputState_Enable = ((uint8_t)0x01) /*!< Output compare State enabled (channel output enabled) */
+}TIM2_OutputState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Break_State
+ * @{
+ */
+typedef enum
+{
+ TIM2_BreakState_Disable = ((uint8_t)0x00), /*!< Break State disabled (break option disabled) */
+ TIM2_BreakState_Enable = ((uint8_t)0x10) /*!< Break State enabled (break option enabled) */
+
+}TIM2_BreakState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Break_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM2_BreakPolarity_High = ((uint8_t)0x20), /*!< if Break, channel polarity = High */
+ TIM2_BreakPolarity_Low = ((uint8_t)0x00) /*!< if Break, channel polarity = Low */
+
+}TIM2_BreakPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Automatic_Output
+ * @{
+ */
+typedef enum
+{
+ TIM2_AutomaticOutput_Enable = ((uint8_t)0x40), /*!< Automatic Output option enabled */
+ TIM2_AutomaticOutput_Disable = ((uint8_t)0x00) /*!< Automatic Output option disabled */
+}TIM2_AutomaticOutput_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Lock_Level
+ * @{
+ */
+typedef enum
+{
+ TIM2_LockLevel_Off = ((uint8_t)0x00), /*!< Lock option disabled */
+ TIM2_LockLevel_1 = ((uint8_t)0x01), /*!< Select Lock Level 1 */
+ TIM2_LockLevel_2 = ((uint8_t)0x02), /*!< Select Lock Level 2 */
+ TIM2_LockLevel_3 = ((uint8_t)0x03) /*!< Select Lock Level 3 */
+}TIM2_LockLevel_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_OSSI_State
+ * @{
+ */
+typedef enum
+{
+ TIM2_OSSIState_Enable = ((uint8_t)0x04), /*!< Off-State Selection for Idle mode enabled */
+ TIM2_OSSIState_Disable = ((uint8_t)0x00) /*!< Off-State Selection for Idle mode disabled */
+}TIM2_OSSIState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Output_Compare_Idle_state
+ * @{
+ */
+typedef enum
+{
+ TIM2_OCIdleState_Reset = ((uint8_t)0x00), /*!< Output Compare Idle state = Reset */
+ TIM2_OCIdleState_Set = ((uint8_t)0x01) /*!< Output Compare Idle state = Set */
+}TIM2_OCIdleState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Input_Capture_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM2_ICPolarity_Rising = ((uint8_t)0x00), /*!< Input Capture on Rising Edge*/
+ TIM2_ICPolarity_Falling = ((uint8_t)0x01) /*!< Input Capture on Falling Edge*/
+}TIM2_ICPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Input_Capture_Selection
+ * @{
+ */
+typedef enum
+{
+ TIM2_ICSelection_DirectTI = ((uint8_t)0x01), /*!< Input Capture mapped on the direct input*/
+ TIM2_ICSelection_IndirectTI = ((uint8_t)0x02), /*!< Input Capture mapped on the indirect input*/
+ TIM2_ICSelection_TRGI = ((uint8_t)0x03) /*!< Input Capture mapped on the Trigger Input*/
+}TIM2_ICSelection_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Input_Capture_Prescaler
+ * @{
+ */
+typedef enum
+{
+ TIM2_ICPSC_DIV1 = ((uint8_t)0x00), /*!< Input Capture Prescaler = 1 (one capture every 1 event) */
+ TIM2_ICPSC_DIV2 = ((uint8_t)0x04), /*!< Input Capture Prescaler = 2 (one capture every 2 events) */
+ TIM2_ICPSC_DIV4 = ((uint8_t)0x08), /*!< Input Capture Prescaler = 4 (one capture every 4 events) */
+ TIM2_ICPSC_DIV8 = ((uint8_t)0x0C) /*!< Input Capture Prescaler = 8 (one capture every 8 events) */
+}TIM2_ICPSC_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Interrupts
+ * @{
+ */
+typedef enum
+{
+ TIM2_IT_Update = ((uint8_t)0x01), /*!< Update Interrupt*/
+ TIM2_IT_CC1 = ((uint8_t)0x02), /*!< Capture Compare Channel1 Interrupt*/
+ TIM2_IT_CC2 = ((uint8_t)0x04), /*!< Capture Compare Channel2 Interrupt*/
+ TIM2_IT_Trigger = ((uint8_t)0x40), /*!< Trigger Interrupt*/
+ TIM2_IT_Break = ((uint8_t)0x80) /*!< Break Interrupt*/
+}TIM2_IT_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_External_Trigger_Prescaler
+ * @{
+ */
+typedef enum
+{
+ TIM2_ExtTRGPSC_OFF = ((uint8_t)0x00), /*!< No External Trigger prescaler */
+ TIM2_ExtTRGPSC_DIV2 = ((uint8_t)0x10), /*!< External Trigger prescaler = 2 (ETRP frequency divided by 2) */
+ TIM2_ExtTRGPSC_DIV4 = ((uint8_t)0x20), /*!< External Trigger prescaler = 4 (ETRP frequency divided by 4) */
+ TIM2_ExtTRGPSC_DIV8 = ((uint8_t)0x30) /*!< External Trigger prescaler = 8 (ETRP frequency divided by 8) */
+}TIM2_ExtTRGPSC_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Internal_Trigger_Selection
+ * @{
+ */
+typedef enum
+{
+ TIM2_TRGSelection_TIM4 = ((uint8_t)0x00), /*!< TRIG Input source = TIM TRIG Output */
+ TIM2_TRGSelection_TIM1 = ((uint8_t)0x10), /*!< TRIG Input source = TIM TRIG Output */
+ TIM2_TRGSelection_TIM3 = ((uint8_t)0x20), /*!< TRIG Input source = TIM TRIG Output */
+ TIM2_TRGSelection_TIM5 = ((uint8_t)0x30), /*!< TRIG Input source = TIM TRIG Output */
+ TIM2_TRGSelection_TI1F_ED = ((uint8_t)0x40), /*!< TRIG Input source = TI1F_ED (TI1 Edge Detector) */
+ TIM2_TRGSelection_TI1FP1 = ((uint8_t)0x50), /*!< TRIG Input source = TI1FP1 (Filtered Timer Input 1) */
+ TIM2_TRGSelection_TI2FP2 = ((uint8_t)0x60), /*!< TRIG Input source = TI2FP2 (Filtered Timer Input 2) */
+ TIM2_TRGSelection_ETRF = ((uint8_t)0x70) /*!< TRIG Input source = ETRF (External Trigger Input ) */
+}TIM2_TRGSelection_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_TI_External_Clock_Source
+ * @{
+ */
+typedef enum
+{
+ TIM2_TIxExternalCLK1Source_TI1ED = ((uint8_t)0x40), /*!< External Clock mode 1 source = TI1ED */
+ TIM2_TIxExternalCLK1Source_TI1 = ((uint8_t)0x50), /*!< External Clock mode 1 source = TI1 */
+ TIM2_TIxExternalCLK1Source_TI2 = ((uint8_t)0x60) /*!< External Clock mode 1 source = TI2 */
+}TIM2_TIxExternalCLK1Source_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_External_Trigger_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM2_ExtTRGPolarity_Inverted = ((uint8_t)0x80), /*!< External Trigger Polarity = inverted */
+ TIM2_ExtTRGPolarity_NonInverted = ((uint8_t)0x00) /*!< External Trigger Polarity = non inverted */
+}TIM2_ExtTRGPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Prescaler_Reload_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM2_PSCReloadMode_Update = ((uint8_t)0x00), /*!< Prescaler value is reloaded at every update*/
+ TIM2_PSCReloadMode_Immediate = ((uint8_t)0x01) /*!< Prescaler value is reloaded immediatly*/
+}TIM2_PSCReloadMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Encoder_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM2_EncoderMode_TI1 = ((uint8_t)0x01), /*!< Encoder mode 1*/
+ TIM2_EncoderMode_TI2 = ((uint8_t)0x02), /*!< Encoder mode 2*/
+ TIM2_EncoderMode_TI12 = ((uint8_t)0x03) /*!< Encoder mode 3*/
+}TIM2_EncoderMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Event_Source
+ * @{
+ */
+typedef enum
+{
+ TIM2_EventSource_Update = ((uint8_t)0x01), /*!< Update Event*/
+ TIM2_EventSource_CC1 = ((uint8_t)0x02), /*!< Capture Compare Channel1 Event*/
+ TIM2_EventSource_CC2 = ((uint8_t)0x04), /*!< Capture Compare Channel2 Event*/
+ TIM2_EventSource_Trigger = ((uint8_t)0x40), /*!< Trigger Event*/
+ TIM2_EventSource_Break = ((uint8_t)0x80) /*!< Break Event*/
+}TIM2_EventSource_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Update_Source
+ * @{
+ */
+typedef enum
+{
+ TIM2_UpdateSource_Global = ((uint8_t)0x00), /*!< Global Update request source */
+ TIM2_UpdateSource_Regular = ((uint8_t)0x01) /*!< Regular Update request source */
+}TIM2_UpdateSource_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Trigger_Output_Source
+ * @{
+ */
+typedef enum
+{
+ TIM2_TRGOSource_Reset = ((uint8_t)0x00), /*!< Trigger Output source = Reset*/
+ TIM2_TRGOSource_Enable = ((uint8_t)0x10), /*!< Trigger Output source = TIM2 is enabled*/
+ TIM2_TRGOSource_Update = ((uint8_t)0x20), /*!< Trigger Output source = Update event*/
+ TIM2_TRGOSource_OC1 = ((uint8_t)0x30), /*!< Trigger Output source = output compare channel1 */
+ TIM2_TRGOSource_OC1REF = ((uint8_t)0x40), /*!< Trigger Output source = output compare channel 1 reference */
+ TIM2_TRGOSource_OC2REF = ((uint8_t)0x50) /*!< Trigger Output source = output compare channel 2 reference */
+}TIM2_TRGOSource_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Slave_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM2_SlaveMode_Reset = ((uint8_t)0x04), /*!< Slave Mode Selection = Reset*/
+ TIM2_SlaveMode_Gated = ((uint8_t)0x05), /*!< Slave Mode Selection = Gated*/
+ TIM2_SlaveMode_Trigger = ((uint8_t)0x06), /*!< Slave Mode Selection = Trigger*/
+ TIM2_SlaveMode_External1 = ((uint8_t)0x07) /*!< Slave Mode Selection = External 1*/
+}TIM2_SlaveMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Flags
+ * @{
+ */
+typedef enum
+{
+ TIM2_FLAG_Update = ((uint16_t)0x0001), /*!< Update Flag */
+ TIM2_FLAG_CC1 = ((uint16_t)0x0002), /*!< Capture compare 1 Flag */
+ TIM2_FLAG_CC2 = ((uint16_t)0x0004), /*!< Capture compare 2 Flag */
+ TIM2_FLAG_Trigger = ((uint16_t)0x0040), /*!< Trigger Flag */
+ TIM2_FLAG_Break = ((uint16_t)0x0080), /*!< Break Flag */
+ TIM2_FLAG_CC1OF = ((uint16_t)0x0200), /*!< Capture compare 1 over capture Flag */
+ TIM2_FLAG_CC2OF = ((uint16_t)0x0400) /*!< Capture compare 2 over capture Flag */
+}TIM2_FLAG_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_DMA_Source_Requests
+ * @{
+ */
+typedef enum
+{
+ TIM2_DMASource_Update = ((uint8_t)0x01), /*!< TIM2 DMA Update Request*/
+ TIM2_DMASource_CC1 = ((uint8_t)0x02), /*!< TIM2 DMA CC1 Request*/
+ TIM2_DMASource_CC2 = ((uint8_t)0x04) /*!< TIM2 DMA CC2 Request*/
+}TIM2_DMASource_TypeDef;
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+
+/** @defgroup TIM2_Exported_Macros
+ * @{
+ */
+
+/**
+ * @brief Macro used by the assert function to check the different functions parameters.
+ */
+
+/**
+ * @brief Macro TIM2 Forced Action
+ */
+#define IS_TIM2_FORCED_ACTION(ACTION) \
+ (((ACTION) == TIM2_ForcedAction_Active) || \
+ ((ACTION) == TIM2_ForcedAction_Inactive))
+
+/**
+ * @brief Macro TIM2 Prescaler
+ */
+#define IS_TIM2_PRESCALER(PRESCALER) \
+ (((PRESCALER) == TIM2_Prescaler_1) || \
+ ((PRESCALER) == TIM2_Prescaler_2) || \
+ ((PRESCALER) == TIM2_Prescaler_4) || \
+ ((PRESCALER) == TIM2_Prescaler_8) || \
+ ((PRESCALER) == TIM2_Prescaler_16) || \
+ ((PRESCALER) == TIM2_Prescaler_32) || \
+ ((PRESCALER) == TIM2_Prescaler_64) || \
+ ((PRESCALER) == TIM2_Prescaler_128))
+
+/**
+ * @brief Macro TIM2 Output Compare and PWM modes
+ */
+#define IS_TIM2_OC_MODE(MODE) \
+ (((MODE) == TIM2_OCMode_Timing) || \
+ ((MODE) == TIM2_OCMode_Active) || \
+ ((MODE) == TIM2_OCMode_Inactive) || \
+ ((MODE) == TIM2_OCMode_Toggle) || \
+ ((MODE) == TIM2_OCMode_PWM1) || \
+ ((MODE) == TIM2_OCMode_PWM2))
+
+#define IS_TIM2_OCM(MODE) \
+ (((MODE) == TIM2_OCMode_Timing) || \
+ ((MODE) == TIM2_OCMode_Active) || \
+ ((MODE) == TIM2_OCMode_Inactive) || \
+ ((MODE) == TIM2_OCMode_Toggle) || \
+ ((MODE) == TIM2_OCMode_PWM1) || \
+ ((MODE) == TIM2_OCMode_PWM2) || \
+ ((MODE) == (uint8_t)TIM2_ForcedAction_Active) || \
+ ((MODE) == (uint8_t)TIM2_ForcedAction_Inactive))
+/**
+ * @brief Macro TIM2 One Pulse Mode
+ */
+#define IS_TIM2_OPM_MODE(MODE) \
+ (((MODE) == TIM2_OPMode_Single) || \
+ ((MODE) == TIM2_OPMode_Repetitive))
+
+/**
+ * @brief Macro TIM2 Channel
+ */
+#define IS_TIM2_CHANNEL(CHANNEL) \
+ (((CHANNEL) == TIM2_Channel_1) || \
+ ((CHANNEL) == TIM2_Channel_2) )
+
+/**
+ * @brief Macro TIM2 Counter Mode
+ */
+#define IS_TIM2_COUNTER_MODE(MODE) \
+ (((MODE) == TIM2_CounterMode_Up) || \
+ ((MODE) == TIM2_CounterMode_Down) || \
+ ((MODE) == TIM2_CounterMode_CenterAligned1) || \
+ ((MODE) == TIM2_CounterMode_CenterAligned2) || \
+ ((MODE) == TIM2_CounterMode_CenterAligned3))
+
+/**
+ * @brief Macro TIM2 Output Compare Polarity
+ */
+#define IS_TIM2_OC_POLARITY(POLARITY) \
+ (((POLARITY) == TIM2_OCPolarity_High) || \
+ ((POLARITY) == TIM2_OCPolarity_Low))
+
+/**
+ * @brief Macro TIM2 Output Compare states
+ */
+#define IS_TIM2_OUTPUT_STATE(STATE) \
+ (((STATE) == TIM2_OutputState_Disable) || \
+ ((STATE) == TIM2_OutputState_Enable))
+
+/**
+ * @brief Macro Break Input enable/disable
+ */
+#define IS_TIM2_BREAK_STATE(STATE) \
+ (((STATE) == TIM2_BreakState_Enable) || \
+ ((STATE) == TIM2_BreakState_Disable))
+
+/**
+ * @brief Macro Break Polarity
+ */
+#define IS_TIM2_BREAK_POLARITY(POLARITY) \
+ (((POLARITY) == TIM2_BreakPolarity_Low) || \
+ ((POLARITY) == TIM2_BreakPolarity_High))
+
+/**
+ * @brief Macro TIM2 AOE Bit Set/Reset
+ */
+#define IS_TIM2_AUTOMATIC_OUTPUT_STATE(STATE) \
+ (((STATE) == TIM2_AutomaticOutput_Enable) || \
+ ((STATE) == TIM2_AutomaticOutput_Disable))
+
+/**
+ * @brief Macro Lock levels
+ */
+#define IS_TIM2_LOCK_LEVEL(LEVEL) \
+ (((LEVEL) == TIM2_LockLevel_Off) || \
+ ((LEVEL) == TIM2_LockLevel_1) || \
+ ((LEVEL) == TIM2_LockLevel_2) || \
+ ((LEVEL) == TIM2_LockLevel_3))
+
+/**
+ * @brief Macro OSSI: Off-State Selection for Idle mode states
+ */
+#define IS_TIM2_OSSI_STATE(STATE) \
+ (((STATE) == TIM2_OSSIState_Enable) || \
+ ((STATE) == TIM2_OSSIState_Disable))
+
+/**
+ * @brief Macro TIM2 OC IDLE STATE
+ */
+#define IS_TIM2_OCIDLE_STATE(STATE) \
+ (((STATE) == TIM2_OCIdleState_Set) || \
+ ((STATE) == TIM2_OCIdleState_Reset))
+
+/**
+ * @brief Macro TIM2 IC POLARITY
+ */
+
+#define IS_TIM2_IC_POLARITY(POLARITY) \
+ (((POLARITY) == TIM2_ICPolarity_Rising) || \
+ ((POLARITY) == TIM2_ICPolarity_Falling))
+
+/**
+ * @brief Macro TIM2 IC SELECTION
+ */
+#define IS_TIM2_IC_SELECTION(SELECTION) \
+ (((SELECTION) == TIM2_ICSelection_DirectTI) || \
+ ((SELECTION) == TIM2_ICSelection_IndirectTI) || \
+ ((SELECTION) == TIM2_ICSelection_TRGI))
+
+/**
+ * @brief Macro TIM2 IC PRESCALER
+ */
+#define IS_TIM2_IC_PRESCALER(PRESCALER) \
+ (((PRESCALER) == TIM2_ICPSC_DIV1) || \
+ ((PRESCALER) == TIM2_ICPSC_DIV2) || \
+ ((PRESCALER) == TIM2_ICPSC_DIV4) || \
+ ((PRESCALER) == TIM2_ICPSC_DIV8))
+
+/**
+ * @brief Macro TIM2 Input Capture Filter Value
+ */
+#define IS_TIM2_IC_FILTER(ICFILTER) \
+ ((ICFILTER) <= 0x0F)
+
+/**
+ * @brief Macro TIM2 Interrupts
+ */
+#define IS_TIM2_IT(IT) \
+ ((IT) != 0x00)
+
+#define IS_TIM2_GET_IT(IT) \
+ (((IT) == TIM2_IT_Update) || \
+ ((IT) == TIM2_IT_CC1) || \
+ ((IT) == TIM2_IT_CC2) || \
+ ((IT) == TIM2_IT_Trigger) || \
+ ((IT) == TIM2_IT_Break))
+
+/**
+ * @brief Macro TIM2 external trigger prescaler
+ */
+#define IS_TIM2_EXT_PRESCALER(PRESCALER) \
+ (((PRESCALER) == TIM2_ExtTRGPSC_OFF) || \
+ ((PRESCALER) == TIM2_ExtTRGPSC_DIV2) || \
+ ((PRESCALER) == TIM2_ExtTRGPSC_DIV4) || \
+ ((PRESCALER) == TIM2_ExtTRGPSC_DIV8))
+/**
+ * @brief Macro TIM2 Trigger Selection
+ */
+#define IS_TIM2_TRIGGER_SELECTION(SELECTION) \
+ (((SELECTION) == TIM2_TRGSelection_TIM4) || \
+ ((SELECTION) == TIM2_TRGSelection_TIM1) || \
+ ((SELECTION) == TIM2_TRGSelection_TIM3) || \
+ ((SELECTION) == TIM2_TRGSelection_TIM5) || \
+ ((SELECTION) == TIM2_TRGSelection_TI1F_ED) || \
+ ((SELECTION) == TIM2_TRGSelection_TI1FP1) || \
+ ((SELECTION) == TIM2_TRGSelection_TI2FP2) || \
+ ((SELECTION) == TIM2_TRGSelection_ETRF))
+
+
+#define IS_TIM2_TIX_TRIGGER_SELECTION(SELECTION) \
+ (((SELECTION) == TIM2_TRGSelection_TI1F_ED) || \
+ ((SELECTION) == TIM2_TRGSelection_TI1FP1) || \
+ ((SELECTION) == TIM2_TRGSelection_TI2FP2))
+
+/**
+ * @brief Macro TIM2 TIx external Clock Selection
+ */
+#define IS_TIM2_TIXCLK_SOURCE(SOURCE) \
+ (((SOURCE) == TIM2_TIxExternalCLK1Source_TI1ED) || \
+ ((SOURCE) == TIM2_TIxExternalCLK1Source_TI2) || \
+ ((SOURCE) == TIM2_TIxExternalCLK1Source_TI1))
+
+/**
+ * @brief Macro TIM2 Trigger Polarity
+ */
+#define IS_TIM2_EXT_POLARITY(POLARITY) \
+ (((POLARITY) == TIM2_ExtTRGPolarity_Inverted) || \
+ ((POLARITY) == TIM2_ExtTRGPolarity_NonInverted))
+
+/**
+ * @brief Macro TIM2 External Trigger Filter
+ */
+#define IS_TIM2_EXT_FILTER(EXTFILTER) \
+ ((EXTFILTER) <= 0x0F)
+
+/**
+ * @brief Macro TIM2 Prescaler Reload
+ */
+#define IS_TIM2_PRESCALER_RELOAD(RELOAD) \
+ (((RELOAD) == TIM2_PSCReloadMode_Update) || \
+ ((RELOAD) == TIM2_PSCReloadMode_Immediate))
+
+/**
+ * @brief Macro TIM2 encoder mode
+ */
+#define IS_TIM2_ENCODER_MODE(MODE) \
+ (((MODE) == TIM2_EncoderMode_TI1) || \
+ ((MODE) == TIM2_EncoderMode_TI2) || \
+ ((MODE) == TIM2_EncoderMode_TI12))
+
+/**
+ * @brief Macro TIM2 event source
+ */
+#define IS_TIM2_EVENT_SOURCE(SOURCE) \
+ ((((SOURCE) & (uint8_t)0x18) == 0x00) && \
+ ((SOURCE) != 0x00))
+
+/**
+ * @brief Macro TIM2 update source
+ */
+#define IS_TIM2_UPDATE_SOURCE(SOURCE) \
+ (((SOURCE) == TIM2_UpdateSource_Global) || \
+ ((SOURCE) == TIM2_UpdateSource_Regular))
+
+/**
+ * @brief Macro TIM2 TRGO source
+ */
+#define IS_TIM2_TRGO_SOURCE(SOURCE) \
+ (((SOURCE) == TIM2_TRGOSource_Reset) || \
+ ((SOURCE) == TIM2_TRGOSource_Enable) || \
+ ((SOURCE) == TIM2_TRGOSource_Update) || \
+ ((SOURCE) == TIM2_TRGOSource_OC1) || \
+ ((SOURCE) == TIM2_TRGOSource_OC1REF) || \
+ ((SOURCE) == TIM2_TRGOSource_OC2REF))
+/**
+ * @brief Macro TIM2 Slave mode
+ */
+#define IS_TIM2_SLAVE_MODE(MODE) \
+ (((MODE) == TIM2_SlaveMode_Reset) || \
+ ((MODE) == TIM2_SlaveMode_Gated) || \
+ ((MODE) == TIM2_SlaveMode_Trigger) || \
+ ((MODE) == TIM2_SlaveMode_External1))
+/**
+ * @brief Macro TIM2 Flags
+ */
+#define IS_TIM2_GET_FLAG(FLAG) \
+ (((FLAG) == TIM2_FLAG_Update) || \
+ ((FLAG) == TIM2_FLAG_CC1) || \
+ ((FLAG) == TIM2_FLAG_CC2) || \
+ ((FLAG) == TIM2_FLAG_Trigger) || \
+ ((FLAG) == TIM2_FLAG_Break) || \
+ ((FLAG) == TIM2_FLAG_CC1OF) || \
+ ((FLAG) == TIM2_FLAG_CC2OF))
+
+#define IS_TIM2_CLEAR_FLAG(FLAG) \
+ ((((FLAG) & (uint16_t)0xE100) == 0x0000) && ((FLAG) != 0x0000))
+
+/**
+ * @brief Macro TIM2 DMA sources
+ */
+
+#define IS_TIM2_DMA_SOURCE(SOURCE) \
+ (((SOURCE) == TIM2_DMASource_Update) || \
+ ((SOURCE) == TIM2_DMASource_CC1) || \
+ ((SOURCE) == TIM2_DMASource_CC2))
+
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+/* TimeBase management ********************************************************/
+void TIM2_DeInit(void);
+void TIM2_TimeBaseInit(TIM2_Prescaler_TypeDef TIM2_Prescaler,
+ TIM2_CounterMode_TypeDef TIM2_CounterMode, uint16_t TIM2_Period);
+void TIM2_PrescalerConfig(TIM2_Prescaler_TypeDef Prescaler,
+ TIM2_PSCReloadMode_TypeDef TIM2_PSCReloadMode);
+void TIM2_CounterModeConfig(TIM2_CounterMode_TypeDef TIM2_CounterMode);
+void TIM2_SetCounter(uint16_t Counter);
+void TIM2_SetAutoreload(uint16_t Autoreload);
+uint16_t TIM2_GetCounter(void);
+TIM2_Prescaler_TypeDef TIM2_GetPrescaler(void);
+void TIM2_UpdateDisableConfig(FunctionalState NewState);
+void TIM2_UpdateRequestConfig(TIM2_UpdateSource_TypeDef TIM2_UpdateSource);
+void TIM2_ARRPreloadConfig(FunctionalState NewState);
+void TIM2_SelectOnePulseMode(TIM2_OPMode_TypeDef TIM2_OPMode);
+void TIM2_Cmd(FunctionalState NewState);
+
+/* Output Compare management **************************************************/
+void TIM2_OC1Init(TIM2_OCMode_TypeDef TIM2_OCMode,
+ TIM2_OutputState_TypeDef TIM2_OutputState,
+ uint16_t TIM2_Pulse,
+ TIM2_OCPolarity_TypeDef TIM2_OCPolarity,
+ TIM2_OCIdleState_TypeDef TIM2_OCIdleState);
+void TIM2_OC2Init(TIM2_OCMode_TypeDef TIM2_OCMode,
+ TIM2_OutputState_TypeDef TIM2_OutputState,
+ uint16_t TIM2_Pulse,
+ TIM2_OCPolarity_TypeDef TIM2_OCPolarity,
+ TIM2_OCIdleState_TypeDef TIM2_OCIdleState);
+void TIM2_BKRConfig(TIM2_OSSIState_TypeDef TIM2_OSSIState,
+ TIM2_LockLevel_TypeDef TIM2_LockLevel,
+ TIM2_BreakState_TypeDef TIM2_BreakState,
+ TIM2_BreakPolarity_TypeDef TIM2_BreakPolarity,
+ TIM2_AutomaticOutput_TypeDef TIM2_AutomaticOutput);
+void TIM2_CtrlPWMOutputs(FunctionalState NewState);
+void TIM2_SelectOCxM(TIM2_Channel_TypeDef TIM2_Channel, TIM2_OCMode_TypeDef TIM2_OCMode);
+void TIM2_SetCompare1(uint16_t Compare);
+void TIM2_SetCompare2(uint16_t Compare);
+void TIM2_ForcedOC1Config(TIM2_ForcedAction_TypeDef TIM2_ForcedAction);
+void TIM2_ForcedOC2Config(TIM2_ForcedAction_TypeDef TIM2_ForcedAction);
+void TIM2_OC1PreloadConfig(FunctionalState NewState);
+void TIM2_OC2PreloadConfig(FunctionalState NewState);
+void TIM2_OC1FastConfig(FunctionalState NewState);
+void TIM2_OC2FastConfig(FunctionalState NewState);
+void TIM2_OC1PolarityConfig(TIM2_OCPolarity_TypeDef TIM2_OCPolarity);
+void TIM2_OC2PolarityConfig(TIM2_OCPolarity_TypeDef TIM2_OCPolarity);
+void TIM2_CCxCmd(TIM2_Channel_TypeDef TIM2_Channel, FunctionalState NewState);
+
+/* Input Capture management ***************************************************/
+void TIM2_ICInit(TIM2_Channel_TypeDef TIM2_Channel,
+ TIM2_ICPolarity_TypeDef TIM2_ICPolarity,
+ TIM2_ICSelection_TypeDef TIM2_ICSelection,
+ TIM2_ICPSC_TypeDef TIM2_ICPrescaler,
+ uint8_t TIM2_ICFilter);
+void TIM2_PWMIConfig(TIM2_Channel_TypeDef TIM2_Channel,
+ TIM2_ICPolarity_TypeDef TIM2_ICPolarity,
+ TIM2_ICSelection_TypeDef TIM2_ICSelection,
+ TIM2_ICPSC_TypeDef TIM2_ICPrescaler,
+ uint8_t TIM2_ICFilter);
+uint16_t TIM2_GetCapture1(void);
+uint16_t TIM2_GetCapture2(void);
+void TIM2_SetIC1Prescaler(TIM2_ICPSC_TypeDef TIM2_IC1Prescaler);
+void TIM2_SetIC2Prescaler(TIM2_ICPSC_TypeDef TIM2_IC2Prescaler);
+
+/* Interrupts, DMA and flags management ***************************************/
+void TIM2_ITConfig(TIM2_IT_TypeDef TIM2_IT, FunctionalState NewState);
+void TIM2_GenerateEvent(TIM2_EventSource_TypeDef TIM2_EventSource);
+FlagStatus TIM2_GetFlagStatus(TIM2_FLAG_TypeDef TIM2_FLAG);
+void TIM2_ClearFlag(TIM2_FLAG_TypeDef TIM2_FLAG);
+ITStatus TIM2_GetITStatus(TIM2_IT_TypeDef TIM2_IT);
+void TIM2_ClearITPendingBit(TIM2_IT_TypeDef TIM2_IT);
+void TIM2_DMACmd(TIM2_DMASource_TypeDef TIM2_DMASource, FunctionalState NewState);
+void TIM2_SelectCCDMA(FunctionalState NewState);
+
+/* Clocks management **********************************************************/
+void TIM2_InternalClockConfig(void);
+void TIM2_TIxExternalClockConfig(TIM2_TIxExternalCLK1Source_TypeDef TIM2_TIxExternalCLKSource,
+ TIM2_ICPolarity_TypeDef TIM2_ICPolarity,
+ uint8_t ICFilter);
+void TIM2_ETRClockMode1Config(TIM2_ExtTRGPSC_TypeDef TIM2_ExtTRGPrescaler,
+ TIM2_ExtTRGPolarity_TypeDef TIM2_ExtTRGPolarity,
+ uint8_t ExtTRGFilter);
+void TIM2_ETRClockMode2Config(TIM2_ExtTRGPSC_TypeDef TIM2_ExtTRGPrescaler,
+ TIM2_ExtTRGPolarity_TypeDef TIM2_ExtTRGPolarity,
+ uint8_t ExtTRGFilter);
+
+/* Synchronization management *************************************************/
+void TIM2_SelectInputTrigger(TIM2_TRGSelection_TypeDef TIM2_InputTriggerSource);
+void TIM2_SelectOutputTrigger(TIM2_TRGOSource_TypeDef TIM2_TRGOSource);
+void TIM2_SelectSlaveMode(TIM2_SlaveMode_TypeDef TIM2_SlaveMode);
+void TIM2_SelectMasterSlaveMode(FunctionalState NewState);
+void TIM2_ETRConfig(TIM2_ExtTRGPSC_TypeDef TIM2_ExtTRGPrescaler,
+ TIM2_ExtTRGPolarity_TypeDef TIM2_ExtTRGPolarity,
+ uint8_t ExtTRGFilter);
+
+/* Specific interface management **********************************************/
+void TIM2_EncoderInterfaceConfig(TIM2_EncoderMode_TypeDef TIM2_EncoderMode,
+ TIM2_ICPolarity_TypeDef TIM2_IC1Polarity,
+ TIM2_ICPolarity_TypeDef TIM2_IC2Polarity);
+void TIM2_SelectHallSensor(FunctionalState NewState);
+
+#endif /* __STM8L15x_TIM2_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim3.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim3.h
new file mode 100644
index 00000000..ae5f3051
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim3.h
@@ -0,0 +1,909 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_tim3.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the TIM3 firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_TIM3_H
+#define __STM8L15x_TIM3_H
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @defgroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup TIM3
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup TIM3_Exported_Types
+ * @{
+ */
+
+/** @defgroup TIM3_Forced_Action
+ * @{
+ */
+typedef enum
+{
+ TIM3_ForcedAction_Active = ((uint8_t)0x50), /*!< Output Reference is forced low */
+ TIM3_ForcedAction_Inactive = ((uint8_t)0x40) /*!< Output Reference is forced high */
+}
+TIM3_ForcedAction_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Prescaler
+ * @{
+ */
+typedef enum
+{
+ TIM3_Prescaler_1 = ((uint8_t)0x00), /*!< Time base Prescaler = 1 (No effect)*/
+ TIM3_Prescaler_2 = ((uint8_t)0x01), /*!< Time base Prescaler = 2 */
+ TIM3_Prescaler_4 = ((uint8_t)0x02), /*!< Time base Prescaler = 4 */
+ TIM3_Prescaler_8 = ((uint8_t)0x03), /*!< Time base Prescaler = 8 */
+ TIM3_Prescaler_16 = ((uint8_t)0x04), /*!< Time base Prescaler = 16 */
+ TIM3_Prescaler_32 = ((uint8_t)0x05), /*!< Time base Prescaler = 32 */
+ TIM3_Prescaler_64 = ((uint8_t)0x06), /*!< Time base Prescaler = 64 */
+ TIM3_Prescaler_128 = ((uint8_t)0x07) /*!< Time base Prescaler = 128 */
+}TIM3_Prescaler_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_OCMode
+ * @{
+ */
+typedef enum
+{
+ TIM3_OCMode_Timing = ((uint8_t)0x00), /*!< Timing (Frozen) Mode*/
+ TIM3_OCMode_Active = ((uint8_t)0x10), /*!< Active Mode*/
+ TIM3_OCMode_Inactive = ((uint8_t)0x20), /*!< Inactive Mode*/
+ TIM3_OCMode_Toggle = ((uint8_t)0x30), /*!< Toggle Mode*/
+ TIM3_OCMode_PWM1 = ((uint8_t)0x60), /*!< PWM Mode 1*/
+ TIM3_OCMode_PWM2 = ((uint8_t)0x70) /*!< PWM Mode 2*/
+}TIM3_OCMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_OnePulseMode
+ * @{
+ */
+typedef enum
+{
+ TIM3_OPMode_Single = ((uint8_t)0x01), /*!< Single one Pulse mode (OPM Active) */
+ TIM3_OPMode_Repetitive = ((uint8_t)0x00) /*!< Repetitive Pulse mode (OPM inactive) */
+}TIM3_OPMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Channel
+ * @{
+ */
+typedef enum
+{
+ TIM3_Channel_1 = ((uint8_t)0x00), /*!< Channel 1*/
+ TIM3_Channel_2 = ((uint8_t)0x01) /*!< Channel 2*/
+}TIM3_Channel_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_CounterMode
+ * @{
+ */
+typedef enum
+{
+ TIM3_CounterMode_Up = ((uint8_t)0x00), /*!< Counter Up Mode */
+ TIM3_CounterMode_Down = ((uint8_t)0x10), /*!< Counter Down Mode */
+ TIM3_CounterMode_CenterAligned1 = ((uint8_t)0x20), /*!< Counter Central aligned Mode 1 */
+ TIM3_CounterMode_CenterAligned2 = ((uint8_t)0x40), /*!< Counter Central aligned Mode 2 */
+ TIM3_CounterMode_CenterAligned3 = ((uint8_t)0x60) /*!< Counter Central aligned Mode 3 */
+}TIM3_CounterMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Output_Compare_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM3_OCPolarity_High = ((uint8_t)0x00), /*!< Output compare polarity = High */
+ TIM3_OCPolarity_Low = ((uint8_t)0x01) /*!< Output compare polarity = Low */
+}TIM3_OCPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Output_State
+ * @{
+ */
+typedef enum
+{
+ TIM3_OutputState_Disable = ((uint8_t)0x00), /*!< Output compare State disabled
+ (channel output disabled) */
+ TIM3_OutputState_Enable = ((uint8_t)0x01) /*!< Output compare State enabled
+ (channel output enabled) */
+}TIM3_OutputState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Break_State
+ * @{
+ */
+typedef enum
+{
+ TIM3_BreakState_Disable = ((uint8_t)0x00), /*!< Break State disabled (break option disabled) */
+ TIM3_BreakState_Enable = ((uint8_t)0x10) /*!< Break State enabled (break option enabled) */
+}TIM3_BreakState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Break_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM3_BreakPolarity_High = ((uint8_t)0x20), /*!< if Break, channel polarity = High */
+ TIM3_BreakPolarity_Low = ((uint8_t)0x00) /*!< if Break, channel polarity = Low */
+}TIM3_BreakPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Automatic_Output
+ * @{
+ */
+typedef enum
+{
+ TIM3_AutomaticOutput_Enable = ((uint8_t)0x40), /*!< Automatic Output option enabled */
+ TIM3_AutomaticOutput_Disable = ((uint8_t)0x00) /*!< Automatic Output option disabled */
+}TIM3_AutomaticOutput_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Lock_Level
+ * @{
+ */
+typedef enum
+{
+ TIM3_LockLevel_Off = ((uint8_t)0x00), /*!< Lock option disabled */
+ TIM3_LockLevel_1 = ((uint8_t)0x01), /*!< Select Lock Level 1 */
+ TIM3_LockLevel_2 = ((uint8_t)0x02), /*!< Select Lock Level 2 */
+ TIM3_LockLevel_3 = ((uint8_t)0x03) /*!< Select Lock Level 3 */
+}TIM3_LockLevel_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_OSSI_State
+ * @{
+ */
+typedef enum
+{
+ TIM3_OSSIState_Enable = ((uint8_t)0x04), /*!< Off-State Selection for Idle mode enabled */
+ TIM3_OSSIState_Disable = ((uint8_t)0x00) /*!< Off-State Selection for Idle mode disabled */
+}TIM3_OSSIState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Output_Compare_Idle_state
+ * @{
+ */
+typedef enum
+{
+ TIM3_OCIdleState_Reset = ((uint8_t)0x00), /*!< Output Compare Idle state = Reset */
+ TIM3_OCIdleState_Set = ((uint8_t)0x01) /*!< Output Compare Idle state = Set */
+}TIM3_OCIdleState_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Input_Capture_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM3_ICPolarity_Rising = ((uint8_t)0x00), /*!< Input Capture on Rising Edge*/
+ TIM3_ICPolarity_Falling = ((uint8_t)0x01) /*!< Input Capture on Falling Edge*/
+}TIM3_ICPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Input_Capture_Selection
+ * @{
+ */
+typedef enum
+{
+ TIM3_ICSelection_DirectTI = ((uint8_t)0x01), /*!< Input Capture mapped on the direct input*/
+ TIM3_ICSelection_IndirectTI = ((uint8_t)0x02), /*!< Input Capture mapped on the indirect input*/
+ TIM3_ICSelection_TRGI = ((uint8_t)0x03) /*!< Input Capture mapped on the Trigger Input*/
+}TIM3_ICSelection_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Input_Capture_Prescaler
+ * @{
+ */
+typedef enum
+{
+ TIM3_ICPSC_DIV1 = ((uint8_t)0x00), /*!< Input Capture Prescaler = 1 (one capture every 1 event) */
+ TIM3_ICPSC_DIV2 = ((uint8_t)0x04), /*!< Input Capture Prescaler = 2 (one capture every 2 events) */
+ TIM3_ICPSC_DIV4 = ((uint8_t)0x08), /*!< Input Capture Prescaler = 4 (one capture every 4 events) */
+ TIM3_ICPSC_DIV8 = ((uint8_t)0x0C) /*!< Input Capture Prescaler = 8 (one capture every 8 events) */
+}TIM3_ICPSC_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Interrupts
+ * @{
+ */
+typedef enum
+{
+ TIM3_IT_Update = ((uint8_t)0x01), /*!< Update Interrupt*/
+ TIM3_IT_CC1 = ((uint8_t)0x02), /*!< Capture Compare Channel1 Interrupt*/
+ TIM3_IT_CC2 = ((uint8_t)0x04), /*!< Capture Compare Channel2 Interrupt*/
+ TIM3_IT_Trigger = ((uint8_t)0x40), /*!< Trigger Interrupt*/
+ TIM3_IT_Break = ((uint8_t)0x80) /*!< Break Interrupt*/
+}TIM3_IT_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_External_Trigger_Prescaler
+ * @{
+ */
+typedef enum
+{
+ TIM3_ExtTRGPSC_OFF = ((uint8_t)0x00), /*!< No External Trigger prescaler */
+ TIM3_ExtTRGPSC_DIV2 = ((uint8_t)0x10), /*!< External Trigger prescaler = 2 (ETRP frequency divided by 2) */
+ TIM3_ExtTRGPSC_DIV4 = ((uint8_t)0x20), /*!< External Trigger prescaler = 4 (ETRP frequency divided by 4) */
+ TIM3_ExtTRGPSC_DIV8 = ((uint8_t)0x30) /*!< External Trigger prescaler = 8 (ETRP frequency divided by 8) */
+}TIM3_ExtTRGPSC_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Internal_Trigger_Selection
+ * @{
+ */
+typedef enum
+{
+ TIM3_TRGSelection_TIM4 = ((uint8_t)0x00), /*!< TRIG Input source = TIM TRIG Output */
+ TIM3_TRGSelection_TIM1 = ((uint8_t)0x10), /*!< TRIG Input source = TIM TRIG Output */
+ TIM3_TRGSelection_TIM5 = ((uint8_t)0x20), /*!< TRIG Input source = TIM TRIG Output */
+ TIM3_TRGSelection_TIM2 = ((uint8_t)0x30), /*!< TRIG Input source = TIM TRIG Output */
+ TIM3_TRGSelection_TI1F_ED = ((uint8_t)0x40), /*!< TRIG Input source = TI1F_ED (TI1 Edge Detector) */
+ TIM3_TRGSelection_TI1FP1 = ((uint8_t)0x50), /*!< TRIG Input source = TI1FP1 (Filtered Timer Input 1) */
+ TIM3_TRGSelection_TI2FP2 = ((uint8_t)0x60), /*!< TRIG Input source = TI2FP2 (Filtered Timer Input 2) */
+ TIM3_TRGSelection_ETRF = ((uint8_t)0x70) /*!< TRIG Input source = ETRF (External Trigger Input ) */
+}TIM3_TRGSelection_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_TI_External_Clock_Source
+ * @{
+ */
+typedef enum
+{
+ TIM3_TIxExternalCLK1Source_TI1ED = ((uint8_t)0x40), /*!< External Clock mode 1 source = TI1ED */
+ TIM3_TIxExternalCLK1Source_TI1 = ((uint8_t)0x50), /*!< External Clock mode 1 source = TI1 */
+ TIM3_TIxExternalCLK1Source_TI2 = ((uint8_t)0x60) /*!< External Clock mode 1 source = TI2 */
+}TIM3_TIxExternalCLK1Source_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_External_Trigger_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM3_ExtTRGPolarity_Inverted = ((uint8_t)0x80), /*!< External Trigger Polarity = inverted */
+ TIM3_ExtTRGPolarity_NonInverted = ((uint8_t)0x00) /*!< External Trigger Polarity = non inverted */
+}TIM3_ExtTRGPolarity_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Prescaler_Reload_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM3_PSCReloadMode_Update = ((uint8_t)0x00), /*!< Prescaler value is reloaded at every update*/
+ TIM3_PSCReloadMode_Immediate = ((uint8_t)0x01) /*!< Prescaler value is reloaded immediatly*/
+}TIM3_PSCReloadMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Encoder_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM3_EncoderMode_TI1 = ((uint8_t)0x01), /*!< Encoder mode 1*/
+ TIM3_EncoderMode_TI2 = ((uint8_t)0x02), /*!< Encoder mode 2*/
+ TIM3_EncoderMode_TI12 = ((uint8_t)0x03) /*!< Encoder mode 3*/
+}TIM3_EncoderMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Event_Source
+ * @{
+ */
+typedef enum
+{
+ TIM3_EventSource_Update = ((uint8_t)0x01), /*!< Update Event*/
+ TIM3_EventSource_CC1 = ((uint8_t)0x02), /*!< Capture Compare Channel1 Event*/
+ TIM3_EventSource_CC2 = ((uint8_t)0x04), /*!< Capture Compare Channel2 Event*/
+ TIM3_EventSource_Trigger = ((uint8_t)0x40), /*!< Trigger Event*/
+ TIM3_EventSource_Break = ((uint8_t)0x80) /*!< Break Event*/
+}TIM3_EventSource_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Update_Source
+ * @{
+ */
+typedef enum
+{
+ TIM3_UpdateSource_Global = ((uint8_t)0x00), /*!< Global Update request source */
+ TIM3_UpdateSource_Regular = ((uint8_t)0x01) /*!< Regular Update request source */
+}TIM3_UpdateSource_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Trigger_Output_Source
+ * @{
+ */
+typedef enum
+{
+ TIM3_TRGOSource_Reset = ((uint8_t)0x00), /*!< Trigger Output source = Reset*/
+ TIM3_TRGOSource_Enable = ((uint8_t)0x10), /*!< Trigger Output source = TIM3 is enabled*/
+ TIM3_TRGOSource_Update = ((uint8_t)0x20), /*!< Trigger Output source = Update event*/
+ TIM3_TRGOSource_OC1 = ((uint8_t)0x30), /*!< Trigger Output source = output compare channel1 */
+ TIM3_TRGOSource_OC1REF = ((uint8_t)0x40), /*!< Trigger Output source = output compare channel 1 reference */
+ TIM3_TRGOSource_OC2REF = ((uint8_t)0x50) /*!< Trigger Output source = output compare channel 2 reference */
+}TIM3_TRGOSource_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Slave_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM3_SlaveMode_Reset = ((uint8_t)0x04), /*!< Slave Mode Selection = Reset*/
+ TIM3_SlaveMode_Gated = ((uint8_t)0x05), /*!< Slave Mode Selection = Gated*/
+ TIM3_SlaveMode_Trigger = ((uint8_t)0x06), /*!< Slave Mode Selection = Trigger*/
+ TIM3_SlaveMode_External1 = ((uint8_t)0x07) /*!< Slave Mode Selection = External 1*/
+}TIM3_SlaveMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Flags
+ * @{
+ */
+typedef enum
+{
+ TIM3_FLAG_Update = ((uint16_t)0x0001), /*!< Update Flag */
+ TIM3_FLAG_CC1 = ((uint16_t)0x0002), /*!< Capture compare 1 Flag */
+ TIM3_FLAG_CC2 = ((uint16_t)0x0004), /*!< Capture compare 2 Flag */
+ TIM3_FLAG_Trigger = ((uint16_t)0x0040), /*!< Trigger Flag */
+ TIM3_FLAG_Break = ((uint16_t)0x0080), /*!< Break Flag */
+ TIM3_FLAG_CC1OF = ((uint16_t)0x0200), /*!< Capture compare 1 over capture Flag */
+ TIM3_FLAG_CC2OF = ((uint16_t)0x0400) /*!< Capture compare 2 over capture Flag */
+}TIM3_FLAG_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_DMA_Source_Requests
+ * @{
+ */
+typedef enum
+{
+ TIM3_DMASource_Update = ((uint8_t)0x01), /*!< TIM3 DMA Update Request*/
+ TIM3_DMASource_CC1 = ((uint8_t)0x02),
+ TIM3_DMASource_CC2 = ((uint8_t)0x04)
+}TIM3_DMASource_TypeDef;
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+
+/** @defgroup TIM3_Exported_Macros
+ * @{
+ */
+
+/**
+ * @brief Macro used by the assert function to check the different functions parameters.
+ */
+
+/**
+ * @brief Macro TIM3 Forced Action
+ */
+#define IS_TIM3_FORCED_ACTION(ACTION) \
+ (((ACTION) == TIM3_ForcedAction_Active) || \
+ ((ACTION) == TIM3_ForcedAction_Inactive))
+
+/**
+ * @brief Macro TIM3 Prescaler
+ */
+#define IS_TIM3_PRESCALER(PRESCALER) \
+ (((PRESCALER) == TIM3_Prescaler_1) || \
+ ((PRESCALER) == TIM3_Prescaler_2) || \
+ ((PRESCALER) == TIM3_Prescaler_4) || \
+ ((PRESCALER) == TIM3_Prescaler_8) || \
+ ((PRESCALER) == TIM3_Prescaler_16) || \
+ ((PRESCALER) == TIM3_Prescaler_32) || \
+ ((PRESCALER) == TIM3_Prescaler_64) || \
+ ((PRESCALER) == TIM3_Prescaler_128))
+
+/**
+ * @brief Macro TIM3 Output Compare and PWM modes
+ */
+#define IS_TIM3_OC_MODE(MODE) \
+ (((MODE) == TIM3_OCMode_Timing) || \
+ ((MODE) == TIM3_OCMode_Active) || \
+ ((MODE) == TIM3_OCMode_Inactive) || \
+ ((MODE) == TIM3_OCMode_Toggle) || \
+ ((MODE) == TIM3_OCMode_PWM1) || \
+ ((MODE) == TIM3_OCMode_PWM2))
+
+#define IS_TIM3_OCM(MODE) \
+ (((MODE) == TIM3_OCMode_Timing) || \
+ ((MODE) == TIM3_OCMode_Active) || \
+ ((MODE) == TIM3_OCMode_Inactive) || \
+ ((MODE) == TIM3_OCMode_Toggle) || \
+ ((MODE) == TIM3_OCMode_PWM1) || \
+ ((MODE) == TIM3_OCMode_PWM2) || \
+ ((MODE) == (uint8_t)TIM3_ForcedAction_Active) || \
+ ((MODE) == (uint8_t)TIM3_ForcedAction_Inactive))
+/**
+ * @brief Macro TIM3 One Pulse Mode
+ */
+#define IS_TIM3_OPM_MODE(MODE) \
+ (((MODE) == TIM3_OPMode_Single) || \
+ ((MODE) == TIM3_OPMode_Repetitive))
+
+/**
+ * @brief Macro TIM3 Channel
+ */
+#define IS_TIM3_CHANNEL(CHANNEL) \
+ (((CHANNEL) == TIM3_Channel_1) || \
+ ((CHANNEL) == TIM3_Channel_2) )
+
+/**
+ * @brief Macro TIM3 Counter Mode
+ */
+#define IS_TIM3_COUNTER_MODE(MODE) \
+ (((MODE) == TIM3_CounterMode_Up) || \
+ ((MODE) == TIM3_CounterMode_Down) || \
+ ((MODE) == TIM3_CounterMode_CenterAligned1) || \
+ ((MODE) == TIM3_CounterMode_CenterAligned2) || \
+ ((MODE) == TIM3_CounterMode_CenterAligned3))
+
+/**
+ * @brief Macro TIM3 Output Compare Polarity
+ */
+#define IS_TIM3_OC_POLARITY(POLARITY) \
+ (((POLARITY) == TIM3_OCPolarity_High) || \
+ ((POLARITY) == TIM3_OCPolarity_Low))
+
+/**
+ * @brief Macro TIM3 Output Compare states
+ */
+#define IS_TIM3_OUTPUT_STATE(STATE) \
+ (((STATE) == TIM3_OutputState_Disable) || \
+ ((STATE) == TIM3_OutputState_Enable))
+
+
+/**
+ * @brief Macro Break Input enable/disable
+ */
+#define IS_TIM3_BREAK_STATE(STATE) \
+ (((STATE) == TIM3_BreakState_Enable) || \
+ ((STATE) == TIM3_BreakState_Disable))
+
+/**
+ * @brief Macro Break Polarity
+ */
+#define IS_TIM3_BREAK_POLARITY(POLARITY) \
+ (((POLARITY) == TIM3_BreakPolarity_Low) || \
+ ((POLARITY) == TIM3_BreakPolarity_High))
+
+/**
+ * @brief Macro TIM3 AOE Bit Set/Reset
+ */
+#define IS_TIM3_AUTOMATIC_OUTPUT_STATE(STATE) \
+ (((STATE) == TIM3_AutomaticOutput_Enable) || \
+ ((STATE) == TIM3_AutomaticOutput_Disable))
+
+/**
+ * @brief Macro Lock levels
+ */
+#define IS_TIM3_LOCK_LEVEL(LEVEL) \
+ (((LEVEL) == TIM3_LockLevel_Off) || \
+ ((LEVEL) == TIM3_LockLevel_1) || \
+ ((LEVEL) == TIM3_LockLevel_2) || \
+ ((LEVEL) == TIM3_LockLevel_3))
+
+/**
+ * @brief Macro OSSI: Off-State Selection for Idle mode states
+ */
+#define IS_TIM3_OSSI_STATE(STATE) \
+ (((STATE) == TIM3_OSSIState_Enable) || \
+ ((STATE) == TIM3_OSSIState_Disable))
+
+/**
+ * @brief Macro TIM3 OC IDLE STATE
+ */
+#define IS_TIM3_OCIDLE_STATE(STATE) \
+ (((STATE) == TIM3_OCIdleState_Set) || \
+ ((STATE) == TIM3_OCIdleState_Reset))
+
+/**
+ * @brief Macro TIM3 IC POLARITY
+ */
+
+#define IS_TIM3_IC_POLARITY(POLARITY) \
+ (((POLARITY) == TIM3_ICPolarity_Rising) || \
+ ((POLARITY) == TIM3_ICPolarity_Falling))
+
+/**
+ * @brief Macro TIM3 IC SELECTION
+ */
+#define IS_TIM3_IC_SELECTION(SELECTION) \
+ (((SELECTION) == TIM3_ICSelection_DirectTI) || \
+ ((SELECTION) == TIM3_ICSelection_IndirectTI) || \
+ ((SELECTION) == TIM3_ICSelection_TRGI))
+
+
+/**
+ * @brief Macro TIM3 IC PRESCALER
+ */
+#define IS_TIM3_IC_PRESCALER(PRESCALER) \
+ (((PRESCALER) == TIM3_ICPSC_DIV1) || \
+ ((PRESCALER) == TIM3_ICPSC_DIV2) || \
+ ((PRESCALER) == TIM3_ICPSC_DIV4) || \
+ ((PRESCALER) == TIM3_ICPSC_DIV8))
+
+/**
+ * @brief Macro TIM3 Input Capture Filter Value
+ */
+#define IS_TIM3_IC_FILTER(ICFILTER) \
+ ((ICFILTER) <= 0x0F)
+
+/**
+ * @brief Macro TIM3 Interrupts
+ */
+#define IS_TIM3_IT(IT) \
+ ((IT) != 0x00)
+
+#define IS_TIM3_GET_IT(IT) \
+ (((IT) == TIM3_IT_Update) || \
+ ((IT) == TIM3_IT_CC1) || \
+ ((IT) == TIM3_IT_CC2) || \
+ ((IT) == TIM3_IT_Trigger) || \
+ ((IT) == TIM3_IT_Break))
+
+/**
+ * @brief Macro TIM3 external trigger prescaler
+ */
+#define IS_TIM3_EXT_PRESCALER(PRESCALER) \
+ (((PRESCALER) == TIM3_ExtTRGPSC_OFF) || \
+ ((PRESCALER) == TIM3_ExtTRGPSC_DIV2) || \
+ ((PRESCALER) == TIM3_ExtTRGPSC_DIV4) || \
+ ((PRESCALER) == TIM3_ExtTRGPSC_DIV8))
+
+/**
+ * @brief Macro TIM3 Trigger Selection
+ */
+#define IS_TIM3_TRIGGER_SELECTION(SELECTION) \
+ (((SELECTION) == TIM3_TRGSelection_TI1F_ED) || \
+ ((SELECTION) == TIM3_TRGSelection_TI1FP1) || \
+ ((SELECTION) == TIM3_TRGSelection_TI2FP2) || \
+ ((SELECTION) == TIM3_TRGSelection_TIM4) || \
+ ((SELECTION) == TIM3_TRGSelection_TIM1) || \
+ ((SELECTION) == TIM3_TRGSelection_TIM5) || \
+ ((SELECTION) == TIM3_TRGSelection_TIM2) || \
+ ((SELECTION) == TIM3_TRGSelection_ETRF))
+
+
+#define IS_TIM3_TIX_TRIGGER_SELECTION(SELECTION) \
+ (((SELECTION) == TIM3_TRGSelection_TI1F_ED) || \
+ ((SELECTION) == TIM3_TRGSelection_TI1FP1) || \
+ ((SELECTION) == TIM3_TRGSelection_TI2FP2))
+
+/**
+ * @brief Macro TIM3 TIx external Clock Selection
+ */
+#define IS_TIM3_TIXCLK_SOURCE(SOURCE) \
+ (((SOURCE) == TIM3_TIxExternalCLK1Source_TI1ED) || \
+ ((SOURCE) == TIM3_TIxExternalCLK1Source_TI2) || \
+ ((SOURCE) == TIM3_TIxExternalCLK1Source_TI1))
+
+/**
+ * @brief Macro TIM3 Trigger Polarity
+ */
+#define IS_TIM3_EXT_POLARITY(POLARITY) \
+ (((POLARITY) == TIM3_ExtTRGPolarity_Inverted) || \
+ ((POLARITY) == TIM3_ExtTRGPolarity_NonInverted))
+
+/**
+ * @brief Macro TIM3 External Trigger Filter
+ */
+#define IS_TIM3_EXT_FILTER(EXTFILTER) \
+ ((EXTFILTER) <= 0x0F)
+
+/**
+ * @brief Macro TIM3 Prescaler Reload
+ */
+#define IS_TIM3_PRESCALER_RELOAD(RELOAD) \
+ (((RELOAD) == TIM3_PSCReloadMode_Update) || \
+ ((RELOAD) == TIM3_PSCReloadMode_Immediate))
+
+/**
+ * @brief Macro TIM3 encoder mode
+ */
+#define IS_TIM3_ENCODER_MODE(MODE) \
+ (((MODE) == TIM3_EncoderMode_TI1) || \
+ ((MODE) == TIM3_EncoderMode_TI2) || \
+ ((MODE) == TIM3_EncoderMode_TI12))
+
+/**
+ * @brief Macro TIM3 event source
+ */
+#define IS_TIM3_EVENT_SOURCE(SOURCE) \
+ ((((SOURCE) & (uint8_t)0x18) == 0x00) && ((SOURCE) != 0x00))
+
+/**
+ * @brief Macro TIM3 update source
+ */
+#define IS_TIM3_UPDATE_SOURCE(SOURCE) \
+ (((SOURCE) == TIM3_UpdateSource_Global) || \
+ ((SOURCE) == TIM3_UpdateSource_Regular))
+
+/**
+ * @brief Macro TIM3 TRGO source
+ */
+#define IS_TIM3_TRGO_SOURCE(SOURCE) \
+ (((SOURCE) == TIM3_TRGOSource_Reset) || \
+ ((SOURCE) == TIM3_TRGOSource_Enable) || \
+ ((SOURCE) == TIM3_TRGOSource_Update) || \
+ ((SOURCE) == TIM3_TRGOSource_OC1) || \
+ ((SOURCE) == TIM3_TRGOSource_OC1REF) || \
+ ((SOURCE) == TIM3_TRGOSource_OC2REF))
+/**
+ * @brief Macro TIM3 Slave mode
+ */
+#define IS_TIM3_SLAVE_MODE(MODE) \
+ (((MODE) == TIM3_SlaveMode_Reset) || \
+ ((MODE) == TIM3_SlaveMode_Gated) || \
+ ((MODE) == TIM3_SlaveMode_Trigger) || \
+ ((MODE) == TIM3_SlaveMode_External1))
+/**
+ * @brief Macro TIM3 Flags
+ */
+#define IS_TIM3_GET_FLAG(FLAG) \
+ (((FLAG) == TIM3_FLAG_Update) || \
+ ((FLAG) == TIM3_FLAG_CC1) || \
+ ((FLAG) == TIM3_FLAG_CC2) || \
+ ((FLAG) == TIM3_FLAG_Trigger) || \
+ ((FLAG) == TIM3_FLAG_Break) || \
+ ((FLAG) == TIM3_FLAG_CC1OF) || \
+ ((FLAG) == TIM3_FLAG_CC2OF))
+
+#define IS_TIM3_CLEAR_FLAG(FLAG) \
+ ((((FLAG) & (uint16_t)0xE100) == 0x0000) && ((FLAG) != 0x0000))
+
+/**
+ * @brief Macro TIM3 DMA sources
+ */
+
+#define IS_TIM3_DMA_SOURCE(SOURCE) \
+ (((SOURCE) == TIM3_DMASource_Update) || \
+ ((SOURCE) == TIM3_DMASource_CC1) || \
+ ((SOURCE) == TIM3_DMASource_CC2))
+
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+/* TimeBase management ********************************************************/
+void TIM3_DeInit(void);
+void TIM3_TimeBaseInit(TIM3_Prescaler_TypeDef TIM3_Prescaler,
+ TIM3_CounterMode_TypeDef TIM3_CounterMode,
+ uint16_t TIM3_Period);
+void TIM3_PrescalerConfig(TIM3_Prescaler_TypeDef Prescaler,
+ TIM3_PSCReloadMode_TypeDef TIM3_PSCReloadMode);
+void TIM3_CounterModeConfig(TIM3_CounterMode_TypeDef TIM3_CounterMode);
+void TIM3_SetCounter(uint16_t Counter);
+void TIM3_SetAutoreload(uint16_t Autoreload);
+uint16_t TIM3_GetCounter(void);
+TIM3_Prescaler_TypeDef TIM3_GetPrescaler(void);
+void TIM3_UpdateDisableConfig(FunctionalState NewState);
+void TIM3_UpdateRequestConfig(TIM3_UpdateSource_TypeDef TIM3_UpdateSource);
+void TIM3_ARRPreloadConfig(FunctionalState NewState);
+void TIM3_SelectOnePulseMode(TIM3_OPMode_TypeDef TIM3_OPMode);
+void TIM3_Cmd(FunctionalState NewState);
+
+/* Output Compare management **************************************************/
+void TIM3_OC1Init(TIM3_OCMode_TypeDef TIM3_OCMode,
+ TIM3_OutputState_TypeDef TIM3_OutputState,
+ uint16_t TIM3_Pulse,
+ TIM3_OCPolarity_TypeDef TIM3_OCPolarity,
+ TIM3_OCIdleState_TypeDef TIM3_OCIdleState);
+void TIM3_OC2Init(TIM3_OCMode_TypeDef TIM3_OCMode,
+ TIM3_OutputState_TypeDef TIM3_OutputState,
+ uint16_t TIM3_Pulse,
+ TIM3_OCPolarity_TypeDef TIM3_OCPolarity,
+ TIM3_OCIdleState_TypeDef TIM3_OCIdleState);
+void TIM3_BKRConfig(TIM3_OSSIState_TypeDef TIM3_OSSIState,
+ TIM3_LockLevel_TypeDef TIM3_LockLevel,
+ TIM3_BreakState_TypeDef TIM3_BreakState,
+ TIM3_BreakPolarity_TypeDef TIM3_BreakPolarity,
+ TIM3_AutomaticOutput_TypeDef TIM3_AutomaticOutput);
+void TIM3_CtrlPWMOutputs(FunctionalState NewState);
+void TIM3_SelectOCxM(TIM3_Channel_TypeDef TIM3_Channel,
+ TIM3_OCMode_TypeDef TIM3_OCMode);
+void TIM3_SetCompare1(uint16_t Compare);
+void TIM3_SetCompare2(uint16_t Compare);
+void TIM3_ForcedOC1Config(TIM3_ForcedAction_TypeDef TIM3_ForcedAction);
+void TIM3_ForcedOC2Config(TIM3_ForcedAction_TypeDef TIM3_ForcedAction);
+void TIM3_OC1PreloadConfig(FunctionalState NewState);
+void TIM3_OC2PreloadConfig(FunctionalState NewState);
+void TIM3_OC1FastConfig(FunctionalState NewState);
+void TIM3_OC2FastConfig(FunctionalState NewState);
+void TIM3_OC1PolarityConfig(TIM3_OCPolarity_TypeDef TIM3_OCPolarity);
+void TIM3_OC2PolarityConfig(TIM3_OCPolarity_TypeDef TIM3_OCPolarity);
+void TIM3_CCxCmd(TIM3_Channel_TypeDef TIM3_Channel, FunctionalState NewState);
+
+/* Input Capture management ***************************************************/
+void TIM3_ICInit(TIM3_Channel_TypeDef TIM3_Channel,
+ TIM3_ICPolarity_TypeDef TIM3_ICPolarity,
+ TIM3_ICSelection_TypeDef TIM3_ICSelection,
+ TIM3_ICPSC_TypeDef TIM3_ICPrescaler,
+ uint8_t TIM3_ICFilter);
+void TIM3_PWMIConfig(TIM3_Channel_TypeDef TIM3_Channel,
+ TIM3_ICPolarity_TypeDef TIM3_ICPolarity,
+ TIM3_ICSelection_TypeDef TIM3_ICSelection,
+ TIM3_ICPSC_TypeDef TIM3_ICPrescaler,
+ uint8_t TIM3_ICFilter);
+uint16_t TIM3_GetCapture1(void);
+uint16_t TIM3_GetCapture2(void);
+void TIM3_SetIC1Prescaler(TIM3_ICPSC_TypeDef TIM3_IC1Prescaler);
+void TIM3_SetIC2Prescaler(TIM3_ICPSC_TypeDef TIM3_IC2Prescaler);
+
+/* Interrupts, DMA and flags management ***************************************/
+void TIM3_ITConfig(TIM3_IT_TypeDef TIM3_IT, FunctionalState NewState);
+void TIM3_GenerateEvent(TIM3_EventSource_TypeDef TIM3_EventSource);
+FlagStatus TIM3_GetFlagStatus(TIM3_FLAG_TypeDef TIM3_FLAG);
+void TIM3_ClearFlag(TIM3_FLAG_TypeDef TIM3_FLAG);
+ITStatus TIM3_GetITStatus(TIM3_IT_TypeDef TIM3_IT);
+void TIM3_ClearITPendingBit(TIM3_IT_TypeDef TIM3_IT);
+void TIM3_DMACmd(TIM3_DMASource_TypeDef TIM3_DMASource, FunctionalState NewState);
+void TIM3_SelectCCDMA(FunctionalState NewState);
+
+/* Clocks management **********************************************************/
+void TIM3_InternalClockConfig(void);
+void TIM3_TIxExternalClockConfig(TIM3_TIxExternalCLK1Source_TypeDef TIM3_TIxExternalCLKSource,
+ TIM3_ICPolarity_TypeDef TIM3_ICPolarity,
+ uint8_t ICFilter);
+void TIM3_ETRClockMode1Config(TIM3_ExtTRGPSC_TypeDef TIM3_ExtTRGPrescaler,
+ TIM3_ExtTRGPolarity_TypeDef TIM3_ExtTRGPolarity,
+ uint8_t ExtTRGFilter);
+void TIM3_ETRClockMode2Config(TIM3_ExtTRGPSC_TypeDef TIM3_ExtTRGPrescaler,
+ TIM3_ExtTRGPolarity_TypeDef TIM3_ExtTRGPolarity,
+ uint8_t ExtTRGFilter);
+
+/* Synchronization management *************************************************/
+void TIM3_SelectInputTrigger(TIM3_TRGSelection_TypeDef TIM3_InputTriggerSource);
+void TIM3_SelectOutputTrigger(TIM3_TRGOSource_TypeDef TIM3_TRGOSource);
+void TIM3_SelectSlaveMode(TIM3_SlaveMode_TypeDef TIM3_SlaveMode);
+void TIM3_SelectMasterSlaveMode(FunctionalState NewState);
+void TIM3_ETRConfig(TIM3_ExtTRGPSC_TypeDef TIM3_ExtTRGPrescaler,
+ TIM3_ExtTRGPolarity_TypeDef TIM3_ExtTRGPolarity,
+ uint8_t ExtTRGFilter);
+
+/* Specific interface management **********************************************/
+void TIM3_EncoderInterfaceConfig(TIM3_EncoderMode_TypeDef TIM3_EncoderMode,
+ TIM3_ICPolarity_TypeDef TIM3_IC1Polarity,
+ TIM3_ICPolarity_TypeDef TIM3_IC2Polarity);
+void TIM3_SelectHallSensor(FunctionalState NewState);
+
+#endif /* __STM8L15x_TIM3_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim4.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim4.h
new file mode 100644
index 00000000..c8b881ea
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim4.h
@@ -0,0 +1,374 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_tim4.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the TIM4 firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_TIM4_H
+#define __STM8L15x_TIM4_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup TIM4
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup TIM4_Exported_Types
+ * @{
+ */
+
+
+/** @defgroup TIM4_Prescaler
+ * @{
+ */
+typedef enum
+{
+ TIM4_Prescaler_1 = ((uint8_t)0x00), /*!< Time base Prescaler = 1 (No effect)*/
+ TIM4_Prescaler_2 = ((uint8_t)0x01), /*!< Time base Prescaler = 2 */
+ TIM4_Prescaler_4 = ((uint8_t)0x02), /*!< Time base Prescaler = 4 */
+ TIM4_Prescaler_8 = ((uint8_t)0x03), /*!< Time base Prescaler = 8 */
+ TIM4_Prescaler_16 = ((uint8_t)0x04), /*!< Time base Prescaler = 16 */
+ TIM4_Prescaler_32 = ((uint8_t)0x05), /*!< Time base Prescaler = 32 */
+ TIM4_Prescaler_64 = ((uint8_t)0x06), /*!< Time base Prescaler = 64 */
+ TIM4_Prescaler_128 = ((uint8_t)0x07), /*!< Time base Prescaler = 128 */
+ TIM4_Prescaler_256 = ((uint8_t)0x08), /*!< Time base Prescaler = 256 */
+ TIM4_Prescaler_512 = ((uint8_t)0x09), /*!< Time base Prescaler = 512 */
+ TIM4_Prescaler_1024 = ((uint8_t)0x0A), /*!< Time base Prescaler = 1024 */
+ TIM4_Prescaler_2048 = ((uint8_t)0x0B), /*!< Time base Prescaler = 2048 */
+ TIM4_Prescaler_4096 = ((uint8_t)0x0C), /*!< Time base Prescaler = 4096 */
+ TIM4_Prescaler_8192 = ((uint8_t)0x0D), /*!< Time base Prescaler = 8196 */
+ TIM4_Prescaler_16384 = ((uint8_t)0x0E), /*!< Time base Prescaler = 16384 */
+ TIM4_Prescaler_32768 = ((uint8_t)0x0F) /*!< Time base Prescaler = 32768 */
+}TIM4_Prescaler_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM4_One_Pulse_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM4_OPMode_Single = ((uint8_t) 0x01), /*!< Single one Pulse mode (OPM Active) */
+ TIM4_OPMode_Repetitive = ((uint8_t) 0x00) /*!< Repetitive Pulse mode (OPM inactive) */
+}TIM4_OPMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM4_Reload_Mode_Prescaler
+ * @{
+ */
+typedef enum
+{
+ TIM4_PSCReloadMode_Update = ((uint8_t)0x00), /*!< Prescaler value is reloaded at every update */
+ TIM4_PSCReloadMode_Immediate = ((uint8_t)0x01) /*!< Prescaler value is reloaded immediatly */
+}TIM4_PSCReloadMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM4_Update_Source
+ * @{
+ */
+typedef enum
+{
+ TIM4_UpdateSource_Global = ((uint8_t)0x00), /*!< Global Update request source */
+ TIM4_UpdateSource_Regular = ((uint8_t)0x01) /*!< Regular Update request source */
+}TIM4_UpdateSource_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM4_Event_Source
+ * @{
+ */
+typedef enum
+{
+ TIM4_EventSource_Update = ((uint8_t)0x01), /*!< Update Event */
+ TIM4_EventSource_Trigger = ((uint8_t)0x40) /*!< Trigger Event */
+}TIM4_EventSource_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM4_Trigger_Output_Source
+ * @{
+ */
+typedef enum
+{
+ TIM4_TRGOSource_Reset = ((uint8_t)0x00), /*!< Trigger Output source = Reset */
+ TIM4_TRGOSource_Enable = ((uint8_t)0x10), /*!< Trigger Output source = TIM4 is enabled */
+ TIM4_TRGOSource_Update = ((uint8_t)0x20) /*!< Trigger Output source = Update event */
+}TIM4_TRGOSource_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM4_Salve_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM4_SlaveMode_Disable = ((uint8_t)0x00), /*!< Disable slave mode to clock the prescaler
+ directly with the internal clock */
+ TIM4_SlaveMode_Reset = ((uint8_t)0x04), /*!< Slave Mode Selection = Reset*/
+ TIM4_SlaveMode_Gated = ((uint8_t)0x05), /*!< Slave Mode Selection = Gated*/
+ TIM4_SlaveMode_Trigger = ((uint8_t)0x06), /*!< Slave Mode Selection = Trigger*/
+ TIM4_SlaveMode_External1 = ((uint8_t)0x07) /*!< Slave Mode Selection = External 1*/
+}TIM4_SlaveMode_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM4_Flags
+ * @{
+ */
+typedef enum
+{
+ TIM4_FLAG_Update = ((uint8_t)0x01), /*!< Update Flag */
+ TIM4_FLAG_Trigger = ((uint8_t)0x40) /*!< Trigger Flag */
+}TIM4_FLAG_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM4_Interrupts
+ * @{
+ */
+typedef enum
+{
+ TIM4_IT_Update = ((uint8_t)0x01), /*!< Update Interrupt*/
+ TIM4_IT_Trigger = ((uint8_t)0x40) /*!< Trigger Interrupt*/
+}TIM4_IT_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM4_Internal_Trigger_Selection
+ * @{
+ */
+typedef enum
+{
+ TIM4_TRGSelection_TIM5 = ((uint8_t)0x00), /*!< TRIG Input source = TIM5 TRIG Output */
+ TIM4_TRGSelection_TIM1 = ((uint8_t)0x10), /*!< TRIG Input source = TIM1 TRIG Output */
+ TIM4_TRGSelection_TIM3 = ((uint8_t)0x20), /*!< TRIG Input source = TIM3 TRIG Output */
+ TIM4_TRGSelection_TIM2 = ((uint8_t)0x30) /*!< TRIG Input source = TIM2 TRIG Output */
+}TIM4_TRGSelection_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM4_DMA_source_requests
+ * @{
+ */
+typedef enum
+{
+ TIM4_DMASource_Update = ((uint8_t)0x01) /*!< TIM4 DMA Update Request*/
+}TIM4_DMASource_TypeDef;
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+
+/** @defgroup TIM4_Exported_Macros
+ * @{
+ */
+
+/**
+ * @brief Macro used by the assert function to check the different functions parameters.
+ */
+
+/**
+ * @brief Macro TIM4 Prescaler
+ */
+#define IS_TIM4_Prescaler(PRESCALER) \
+ (((PRESCALER) == TIM4_Prescaler_1) || \
+ ((PRESCALER) == TIM4_Prescaler_2) || \
+ ((PRESCALER) == TIM4_Prescaler_4) || \
+ ((PRESCALER) == TIM4_Prescaler_8) || \
+ ((PRESCALER) == TIM4_Prescaler_16) || \
+ ((PRESCALER) == TIM4_Prescaler_32) || \
+ ((PRESCALER) == TIM4_Prescaler_64) || \
+ ((PRESCALER) == TIM4_Prescaler_128) || \
+ ((PRESCALER) == TIM4_Prescaler_256) || \
+ ((PRESCALER) == TIM4_Prescaler_512) || \
+ ((PRESCALER) == TIM4_Prescaler_1024) || \
+ ((PRESCALER) == TIM4_Prescaler_2048) || \
+ ((PRESCALER) == TIM4_Prescaler_4096) || \
+ ((PRESCALER) == TIM4_Prescaler_8192) || \
+ ((PRESCALER) == TIM4_Prescaler_16384)|| \
+ ((PRESCALER) == TIM4_Prescaler_32768))
+/**
+ * @brief Macro TIM4 One Pulse Mode
+ */
+#define IS_TIM4_OPM_MODE(MODE) \
+ (((MODE) == TIM4_OPMode_Single) || \
+ ((MODE) == TIM4_OPMode_Repetitive))
+
+/**
+ * @brief Macro TIM4 Prescaler reload
+ */
+#define IS_TIM4_Prescaler_RELOAD(RELOAD) \
+ (((RELOAD) == TIM4_PSCReloadMode_Update) || \
+ ((RELOAD) == TIM4_PSCReloadMode_Immediate))
+/**
+ * @brief Macro TIM4 Update source
+ */
+#define IS_TIM4_UPDATE_SOURCE(SOURCE) \
+ (((SOURCE) == TIM4_UpdateSource_Global) || \
+ ((SOURCE) == TIM4_UpdateSource_Regular))
+/**
+ * @brief Macro TIM4 Event source
+ */
+#define IS_TIM4_EVENT_SOURCE(SOURCE) \
+ ((((SOURCE) & (uint8_t)0xBE) == 0x00) && \
+ ((SOURCE) != 0x00))
+
+/**
+ * @brief Macro TIM4 TRGO source
+ */
+#define IS_TIM4_TRGO_SOURCE(SOURCE) \
+ (((SOURCE) == TIM4_TRGOSource_Reset) || \
+ ((SOURCE) == TIM4_TRGOSource_Enable)|| \
+ ((SOURCE) == TIM4_TRGOSource_Update))
+/**
+ * @brief Macro TIM4 Slave mode
+ */
+#define IS_TIM4_SLAVE_MODE(MODE) \
+ (((MODE) == TIM4_SlaveMode_Disable) || \
+ ((MODE) == TIM4_SlaveMode_Reset) || \
+ ((MODE) == TIM4_SlaveMode_Gated) || \
+ ((MODE) == TIM4_SlaveMode_Trigger) || \
+ ((MODE) == TIM4_SlaveMode_External1))
+/**
+ * @brief Macro TIM4 Flags
+ */
+#define IS_TIM4_GET_FLAG(FLAG) \
+ (((FLAG) == TIM4_FLAG_Update) || \
+ ((FLAG) == TIM4_FLAG_Trigger))
+
+#define IS_TIM4_CLEAR_FLAG(FLAG) \
+ ((((FLAG) & (uint8_t)0xBE) == 0x00) && ((FLAG) != 0x00))
+/**
+ * @brief Macro TIM4 interrupts
+ */
+#define IS_TIM4_IT(IT) \
+ (((IT) != 0x00) && \
+ (((uint8_t)(IT) & (uint8_t)(~(uint8_t)(0x41)))== 0x00))
+
+#define IS_TIM4_GET_IT(IT) \
+ (((IT) == TIM4_IT_Update) || \
+ ((IT) == TIM4_IT_Trigger))
+/**
+ * @brief Macro TIM4 Trigger selection
+ */
+#define IS_TIM4_TRIGGER_SELECTION(SELECTION) \
+ (((SELECTION) == TIM4_TRGSelection_TIM5) || \
+ ((SELECTION) == TIM4_TRGSelection_TIM1) || \
+ ((SELECTION) == TIM4_TRGSelection_TIM3) || \
+ ((SELECTION) == TIM4_TRGSelection_TIM2))
+
+/**
+ * @brief Macro TIM4 DMA sources
+ */
+
+#define IS_TIM4_DMA_SOURCE(SOURCE) (((SOURCE) == TIM4_DMASource_Update))
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/* TimeBase management ********************************************************/
+void TIM4_DeInit(void);
+void TIM4_TimeBaseInit(TIM4_Prescaler_TypeDef TIM4_Prescaler,
+ uint8_t TIM4_Period);
+void TIM4_PrescalerConfig(TIM4_Prescaler_TypeDef Prescaler,
+ TIM4_PSCReloadMode_TypeDef TIM4_PSCReloadMode);
+void TIM4_SetCounter(uint8_t Counter);
+void TIM4_SetAutoreload(uint8_t Autoreload);
+uint8_t TIM4_GetCounter(void);
+TIM4_Prescaler_TypeDef TIM4_GetPrescaler(void);
+void TIM4_UpdateDisableConfig(FunctionalState NewState);
+void TIM4_UpdateRequestConfig(TIM4_UpdateSource_TypeDef TIM4_UpdateSource);
+void TIM4_ARRPreloadConfig(FunctionalState NewState);
+void TIM4_SelectOnePulseMode(TIM4_OPMode_TypeDef TIM4_OPMode);
+void TIM4_Cmd(FunctionalState NewState);
+
+/* Interrupts, DMA and flags management ***************************************/
+void TIM4_ITConfig(TIM4_IT_TypeDef TIM4_IT, FunctionalState NewState);
+void TIM4_GenerateEvent(TIM4_EventSource_TypeDef TIM4_EventSource);
+FlagStatus TIM4_GetFlagStatus(TIM4_FLAG_TypeDef TIM4_FLAG);
+void TIM4_ClearFlag(TIM4_FLAG_TypeDef TIM4_FLAG);
+ITStatus TIM4_GetITStatus(TIM4_IT_TypeDef TIM4_IT);
+void TIM4_ClearITPendingBit(TIM4_IT_TypeDef TIM4_IT);
+void TIM4_DMACmd(TIM4_DMASource_TypeDef TIM4_DMASource, FunctionalState NewState);
+
+/* Clocks management **********************************************************/
+void TIM4_InternalClockConfig(void);
+
+/* Synchronization management *************************************************/
+void TIM4_SelectInputTrigger(TIM4_TRGSelection_TypeDef TIM4_InputTriggerSource);
+void TIM4_SelectOutputTrigger(TIM4_TRGOSource_TypeDef TIM4_TRGOSource);
+void TIM4_SelectSlaveMode(TIM4_SlaveMode_TypeDef TIM4_SlaveMode);
+void TIM4_SelectMasterSlaveMode(FunctionalState NewState);
+
+#endif /* __STM8L15x_TIM4_H */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim5.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim5.h
new file mode 100644
index 00000000..15efbd53
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_tim5.h
@@ -0,0 +1,771 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_tim5.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the TIM5 firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_TIM5_H
+#define __STM8L15x_TIM5_H
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup TIM5
+ * @{
+ */
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup TIM5_Exported_Types
+ * @{
+ */
+
+/** @defgroup TIM5_Forced_Action
+ * @{
+ */
+typedef enum
+{
+ TIM5_ForcedAction_Active = ((uint8_t)0x50), /*!< Output Reference is forced low */
+ TIM5_ForcedAction_Inactive = ((uint8_t)0x40) /*!< Output Reference is forced high */
+}
+TIM5_ForcedAction_TypeDef;
+
+#define IS_TIM5_FORCED_ACTION(ACTION) (((ACTION) == TIM5_ForcedAction_Active) || \
+ ((ACTION) == TIM5_ForcedAction_Inactive))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Prescaler
+ * @{
+ */
+typedef enum
+{
+ TIM5_Prescaler_1 = ((uint8_t)0x00), /*!< Time base Prescaler = 1 (No effect)*/
+ TIM5_Prescaler_2 = ((uint8_t)0x01), /*!< Time base Prescaler = 2 */
+ TIM5_Prescaler_4 = ((uint8_t)0x02), /*!< Time base Prescaler = 4 */
+ TIM5_Prescaler_8 = ((uint8_t)0x03), /*!< Time base Prescaler = 8 */
+ TIM5_Prescaler_16 = ((uint8_t)0x04), /*!< Time base Prescaler = 16 */
+ TIM5_Prescaler_32 = ((uint8_t)0x05), /*!< Time base Prescaler = 32 */
+ TIM5_Prescaler_64 = ((uint8_t)0x06), /*!< Time base Prescaler = 64 */
+ TIM5_Prescaler_128 = ((uint8_t)0x07) /*!< Time base Prescaler = 128 */
+}TIM5_Prescaler_TypeDef;
+
+#define IS_TIM5_PRESCALER(PRESCALER) (((PRESCALER) == TIM5_Prescaler_1) || \
+ ((PRESCALER) == TIM5_Prescaler_2) || \
+ ((PRESCALER) == TIM5_Prescaler_4) || \
+ ((PRESCALER) == TIM5_Prescaler_8) || \
+ ((PRESCALER) == TIM5_Prescaler_16) || \
+ ((PRESCALER) == TIM5_Prescaler_32) || \
+ ((PRESCALER) == TIM5_Prescaler_64) || \
+ ((PRESCALER) == TIM5_Prescaler_128))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_OCMode
+ * @{
+ */
+typedef enum
+{
+ TIM5_OCMode_Timing = ((uint8_t)0x00), /*!< Timing (Frozen) Mode*/
+ TIM5_OCMode_Active = ((uint8_t)0x10), /*!< Active Mode*/
+ TIM5_OCMode_Inactive = ((uint8_t)0x20), /*!< Inactive Mode*/
+ TIM5_OCMode_Toggle = ((uint8_t)0x30), /*!< Toggle Mode*/
+ TIM5_OCMode_PWM1 = ((uint8_t)0x60), /*!< PWM Mode 1*/
+ TIM5_OCMode_PWM2 = ((uint8_t)0x70) /*!< PWM Mode 2*/
+}TIM5_OCMode_TypeDef;
+
+#define IS_TIM5_OC_MODE(MODE) (((MODE) == TIM5_OCMode_Timing) || \
+ ((MODE) == TIM5_OCMode_Active) || \
+ ((MODE) == TIM5_OCMode_Inactive) || \
+ ((MODE) == TIM5_OCMode_Toggle) || \
+ ((MODE) == TIM5_OCMode_PWM1) || \
+ ((MODE) == TIM5_OCMode_PWM2))
+
+#define IS_TIM5_OCM(MODE) (((MODE) == TIM5_OCMode_Timing) || \
+ ((MODE) == TIM5_OCMode_Active) || \
+ ((MODE) == TIM5_OCMode_Inactive) || \
+ ((MODE) == TIM5_OCMode_Toggle) || \
+ ((MODE) == TIM5_OCMode_PWM1) || \
+ ((MODE) == TIM5_OCMode_PWM2) || \
+ ((MODE) == (uint8_t)TIM5_ForcedAction_Active) || \
+ ((MODE) == (uint8_t)TIM5_ForcedAction_Inactive))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_OnePulseMode
+ * @{
+ */
+typedef enum
+{
+ TIM5_OPMode_Single = ((uint8_t)0x01), /*!< Single one Pulse mode (OPM Active) */
+ TIM5_OPMode_Repetitive = ((uint8_t)0x00) /*!< Repetitive Pulse mode (OPM inactive) */
+}TIM5_OPMode_TypeDef;
+
+#define IS_TIM5_OPM_MODE(MODE) (((MODE) == TIM5_OPMode_Single) || \
+ ((MODE) == TIM5_OPMode_Repetitive))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Channel
+ * @{
+ */
+typedef enum
+{
+ TIM5_Channel_1 = ((uint8_t)0x00), /*!< Channel 1*/
+ TIM5_Channel_2 = ((uint8_t)0x01) /*!< Channel 2*/
+}TIM5_Channel_TypeDef;
+
+#define IS_TIM5_CHANNEL(CHANNEL) (((CHANNEL) == TIM5_Channel_1) || \
+ ((CHANNEL) == TIM5_Channel_2) )
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_CounterMode
+ * @{
+ */
+typedef enum
+{
+ TIM5_CounterMode_Up = ((uint8_t)0x00), /*!< Counter Up Mode */
+ TIM5_CounterMode_Down = ((uint8_t)0x10), /*!< Counter Down Mode */
+ TIM5_CounterMode_CenterAligned1 = ((uint8_t)0x20), /*!< Counter Central aligned Mode 1 */
+ TIM5_CounterMode_CenterAligned2 = ((uint8_t)0x40), /*!< Counter Central aligned Mode 2 */
+ TIM5_CounterMode_CenterAligned3 = ((uint8_t)0x60) /*!< Counter Central aligned Mode 3 */
+}TIM5_CounterMode_TypeDef;
+
+#define IS_TIM5_COUNTER_MODE(MODE) (((MODE) == TIM5_CounterMode_Up) || \
+ ((MODE) == TIM5_CounterMode_Down) || \
+ ((MODE) == TIM5_CounterMode_CenterAligned1) || \
+ ((MODE) == TIM5_CounterMode_CenterAligned2) || \
+ ((MODE) == TIM5_CounterMode_CenterAligned3))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Output_Compare_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM5_OCPolarity_High = ((uint8_t)0x00), /*!< Output compare polarity = High */
+ TIM5_OCPolarity_Low = ((uint8_t)0x01) /*!< Output compare polarity = Low */
+}TIM5_OCPolarity_TypeDef;
+
+#define IS_TIM5_OC_POLARITY(POLARITY) (((POLARITY) == TIM5_OCPolarity_High) || \
+ ((POLARITY) == TIM5_OCPolarity_Low))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Output_State
+ * @{
+ */
+typedef enum
+{
+ TIM5_OutputState_Disable = ((uint8_t)0x00), /*!< Output compare State disabled (channel output disabled) */
+ TIM5_OutputState_Enable = ((uint8_t)0x01) /*!< Output compare State enabled (channel output enabled) */
+}TIM5_OutputState_TypeDef;
+
+#define IS_TIM5_OUTPUT_STATE(STATE) (((STATE) == TIM5_OutputState_Disable) || \
+ ((STATE) == TIM5_OutputState_Enable))
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Break_State
+ * @{
+ */
+typedef enum
+{
+ TIM5_BreakState_Disable = ((uint8_t)0x00), /*!< Break State disabled (break option disabled) */
+ TIM5_BreakState_Enable = ((uint8_t)0x10) /*!< Break State enabled (break option enabled) */
+}TIM5_BreakState_TypeDef;
+
+#define IS_TIM5_BREAK_STATE(STATE) (((STATE) == TIM5_BreakState_Enable) || \
+ ((STATE) == TIM5_BreakState_Disable))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Break_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM5_BreakPolarity_High = ((uint8_t)0x20), /*!< if Break, channel polarity = High */
+ TIM5_BreakPolarity_Low = ((uint8_t)0x00) /*!< if Break, channel polarity = Low */
+}TIM5_BreakPolarity_TypeDef;
+
+#define IS_TIM5_BREAK_POLARITY(POLARITY) \
+ (((POLARITY) == TIM5_BreakPolarity_Low) || \
+ ((POLARITY) == TIM5_BreakPolarity_High))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Automatic_Output
+ * @{
+ */
+typedef enum
+{
+ TIM5_AutomaticOutput_Enable = ((uint8_t)0x40), /*!< Automatic Output option enabled */
+ TIM5_AutomaticOutput_Disable = ((uint8_t)0x00) /*!< Automatic Output option disabled */
+}TIM5_AutomaticOutput_TypeDef;
+
+#define IS_TIM5_AUTOMATIC_OUTPUT_STATE(STATE) \
+ (((STATE) == TIM5_AutomaticOutput_Enable) || \
+ ((STATE) == TIM5_AutomaticOutput_Disable))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Lock_Level
+ * @{
+ */
+typedef enum
+{
+ TIM5_LockLevel_Off = ((uint8_t)0x00), /*!< Lock option disabled */
+ TIM5_LockLevel_1 = ((uint8_t)0x01), /*!< Select Lock Level 1 */
+ TIM5_LockLevel_2 = ((uint8_t)0x02), /*!< Select Lock Level 2 */
+ TIM5_LockLevel_3 = ((uint8_t)0x03) /*!< Select Lock Level 3 */
+}TIM5_LockLevel_TypeDef;
+
+#define IS_TIM5_LOCK_LEVEL(LEVEL) (((LEVEL) == TIM5_LockLevel_Off) || \
+ ((LEVEL) == TIM5_LockLevel_1) || \
+ ((LEVEL) == TIM5_LockLevel_2) || \
+ ((LEVEL) == TIM5_LockLevel_3))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_OSSI_State
+ * @{
+ */
+typedef enum
+{
+ TIM5_OSSIState_Enable = ((uint8_t)0x04), /*!< Off-State Selection for Idle mode enabled */
+ TIM5_OSSIState_Disable = ((uint8_t)0x00) /*!< Off-State Selection for Idle mode disabled */
+}TIM5_OSSIState_TypeDef;
+
+#define IS_TIM5_OSSI_STATE(STATE) \
+ (((STATE) == TIM5_OSSIState_Enable) || \
+ ((STATE) == TIM5_OSSIState_Disable))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Output_Compare_Idle_state
+ * @{
+ */
+typedef enum
+{
+ TIM5_OCIdleState_Reset = ((uint8_t)0x00), /*!< Output Compare Idle state = Reset */
+ TIM5_OCIdleState_Set = ((uint8_t)0x01) /*!< Output Compare Idle state = Set */
+}TIM5_OCIdleState_TypeDef;
+
+#define IS_TIM5_OCIDLE_STATE(STATE) \
+ (((STATE) == TIM5_OCIdleState_Set) || \
+ ((STATE) == TIM5_OCIdleState_Reset))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Input_Capture_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM5_ICPolarity_Rising = ((uint8_t)0x00), /*!< Input Capture on Rising Edge*/
+ TIM5_ICPolarity_Falling = ((uint8_t)0x01) /*!< Input Capture on Falling Edge*/
+}TIM5_ICPolarity_TypeDef;
+
+#define IS_TIM5_IC_POLARITY(POLARITY) \
+ (((POLARITY) == TIM5_ICPolarity_Rising) || \
+ ((POLARITY) == TIM5_ICPolarity_Falling))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Input_Capture_Selection
+ * @{
+ */
+typedef enum
+{
+ TIM5_ICSelection_DirectTI = ((uint8_t)0x01), /*!< Input Capture mapped on the direct input*/
+ TIM5_ICSelection_IndirectTI = ((uint8_t)0x02), /*!< Input Capture mapped on the indirect input*/
+ TIM5_ICSelection_TRGI = ((uint8_t)0x03) /*!< Input Capture mapped on the Trigger Input*/
+}TIM5_ICSelection_TypeDef;
+
+#define IS_TIM5_IC_SELECTION(SELECTION) \
+ (((SELECTION) == TIM5_ICSelection_DirectTI) || \
+ ((SELECTION) == TIM5_ICSelection_IndirectTI) || \
+ ((SELECTION) == TIM5_ICSelection_TRGI))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Input_Capture_Prescaler
+ * @{
+ */
+typedef enum
+{
+ TIM5_ICPSC_DIV1 = ((uint8_t)0x00), /*!< Input Capture Prescaler = 1 (one capture every 1 event) */
+ TIM5_ICPSC_DIV2 = ((uint8_t)0x04), /*!< Input Capture Prescaler = 2 (one capture every 2 events) */
+ TIM5_ICPSC_DIV4 = ((uint8_t)0x08), /*!< Input Capture Prescaler = 4 (one capture every 4 events) */
+ TIM5_ICPSC_DIV8 = ((uint8_t)0x0C) /*!< Input Capture Prescaler = 8 (one capture every 8 events) */
+}TIM5_ICPSC_TypeDef;
+
+#define IS_TIM5_IC_PRESCALER(PRESCALER) \
+ (((PRESCALER) == TIM5_ICPSC_DIV1) || \
+ ((PRESCALER) == TIM5_ICPSC_DIV2) || \
+ ((PRESCALER) == TIM5_ICPSC_DIV4) || \
+ ((PRESCALER) == TIM5_ICPSC_DIV8))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Interrupts
+ * @{
+ */
+typedef enum
+{
+ TIM5_IT_Update = ((uint8_t)0x01), /*!< Update Interrupt*/
+ TIM5_IT_CC1 = ((uint8_t)0x02), /*!< Capture Compare Channel1 Interrupt*/
+ TIM5_IT_CC2 = ((uint8_t)0x04), /*!< Capture Compare Channel2 Interrupt*/
+ TIM5_IT_Trigger = ((uint8_t)0x40), /*!< Trigger Interrupt*/
+ TIM5_IT_Break = ((uint8_t)0x80) /*!< Break Interrupt*/
+}TIM5_IT_TypeDef;
+
+#define IS_TIM5_IT(IT) \
+ ((IT) != 0x00)
+
+#define IS_TIM5_GET_IT(IT) \
+ (((IT) == TIM5_IT_Update) || \
+ ((IT) == TIM5_IT_CC1) || \
+ ((IT) == TIM5_IT_CC2) || \
+ ((IT) == TIM5_IT_Trigger) || \
+ ((IT) == TIM5_IT_Break))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_External_Trigger_Prescaler
+ * @{
+ */
+typedef enum
+{
+ TIM5_ExtTRGPSC_OFF = ((uint8_t)0x00), /*!< No External Trigger prescaler */
+ TIM5_ExtTRGPSC_DIV2 = ((uint8_t)0x10), /*!< External Trigger prescaler = 2 (ETRP frequency divided by 2) */
+ TIM5_ExtTRGPSC_DIV4 = ((uint8_t)0x20), /*!< External Trigger prescaler = 4 (ETRP frequency divided by 4) */
+ TIM5_ExtTRGPSC_DIV8 = ((uint8_t)0x30) /*!< External Trigger prescaler = 8 (ETRP frequency divided by 8) */
+}TIM5_ExtTRGPSC_TypeDef;
+
+#define IS_TIM5_EXT_PRESCALER(PRESCALER) \
+ (((PRESCALER) == TIM5_ExtTRGPSC_OFF) || \
+ ((PRESCALER) == TIM5_ExtTRGPSC_DIV2) || \
+ ((PRESCALER) == TIM5_ExtTRGPSC_DIV4) || \
+ ((PRESCALER) == TIM5_ExtTRGPSC_DIV8))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Internal_Trigger_Selection
+ * @{
+ */
+typedef enum
+{
+ TIM5_TRGSelection_TIM4 = ((uint8_t)0x00), /*!< TRIG Input source = TIM TRIG Output */
+ TIM5_TRGSelection_TIM1 = ((uint8_t)0x10), /*!< TRIG Input source = TIM TRIG Output */
+ TIM5_TRGSelection_TIM3 = ((uint8_t)0x20), /*!< TRIG Input source = TIM TRIG Output */
+ TIM5_TRGSelection_TIM2 = ((uint8_t)0x30), /*!< TRIG Input source = TIM TRIG Output */
+ TIM5_TRGSelection_TI1F_ED = ((uint8_t)0x40), /*!< TRIG Input source = TI1F_ED (TI1 Edge Detector) */
+ TIM5_TRGSelection_TI1FP1 = ((uint8_t)0x50), /*!< TRIG Input source = TI1FP1 (Filtered Timer Input 1) */
+ TIM5_TRGSelection_TI2FP2 = ((uint8_t)0x60), /*!< TRIG Input source = TI2FP2 (Filtered Timer Input 2) */
+ TIM5_TRGSelection_ETRF = ((uint8_t)0x70) /*!< TRIG Input source = ETRF (External Trigger Input ) */
+}TIM5_TRGSelection_TypeDef;
+
+#define IS_TIM5_TRIGGER_SELECTION(SELECTION) \
+ (((SELECTION) == TIM5_TRGSelection_TIM4) || \
+ ((SELECTION) == TIM5_TRGSelection_TIM1) || \
+ ((SELECTION) == TIM5_TRGSelection_TIM3) || \
+ ((SELECTION) == TIM5_TRGSelection_TIM2) || \
+ ((SELECTION) == TIM5_TRGSelection_TI1F_ED) || \
+ ((SELECTION) == TIM5_TRGSelection_TI1FP1) || \
+ ((SELECTION) == TIM5_TRGSelection_TI2FP2) || \
+ ((SELECTION) == TIM5_TRGSelection_ETRF))
+
+
+#define IS_TIM5_TIX_TRIGGER_SELECTION(SELECTION) \
+ (((SELECTION) == TIM5_TRGSelection_TI1F_ED) || \
+ ((SELECTION) == TIM5_TRGSelection_TI1FP1) || \
+ ((SELECTION) == TIM5_TRGSelection_TI2FP2))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_TI_External_Clock_Source
+ * @{
+ */
+typedef enum
+{
+ TIM5_TIxExternalCLK1Source_TI1ED = ((uint8_t)0x40), /*!< External Clock mode 1 source = TI1ED */
+ TIM5_TIxExternalCLK1Source_TI1 = ((uint8_t)0x50), /*!< External Clock mode 1 source = TI1 */
+ TIM5_TIxExternalCLK1Source_TI2 = ((uint8_t)0x60) /*!< External Clock mode 1 source = TI2 */
+}TIM5_TIxExternalCLK1Source_TypeDef;
+
+#define IS_TIM5_TIXCLK_SOURCE(SOURCE) \
+ (((SOURCE) == TIM5_TIxExternalCLK1Source_TI1ED) || \
+ ((SOURCE) == TIM5_TIxExternalCLK1Source_TI2) || \
+ ((SOURCE) == TIM5_TIxExternalCLK1Source_TI1))
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_External_Trigger_Polarity
+ * @{
+ */
+typedef enum
+{
+ TIM5_ExtTRGPolarity_Inverted = ((uint8_t)0x80), /*!< External Trigger Polarity = inverted */
+ TIM5_ExtTRGPolarity_NonInverted = ((uint8_t)0x00) /*!< External Trigger Polarity = non inverted */
+}TIM5_ExtTRGPolarity_TypeDef;
+
+#define IS_TIM5_EXT_POLARITY(POLARITY) \
+ (((POLARITY) == TIM5_ExtTRGPolarity_Inverted) || \
+ ((POLARITY) == TIM5_ExtTRGPolarity_NonInverted))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Prescaler_Reload_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM5_PSCReloadMode_Update = ((uint8_t)0x00), /*!< Prescaler value is reloaded at every update*/
+ TIM5_PSCReloadMode_Immediate = ((uint8_t)0x01) /*!< Prescaler value is reloaded immediatly*/
+}TIM5_PSCReloadMode_TypeDef;
+
+#define IS_TIM5_PRESCALER_RELOAD(RELOAD) \
+ (((RELOAD) == TIM5_PSCReloadMode_Update) || \
+ ((RELOAD) == TIM5_PSCReloadMode_Immediate))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Encoder_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM5_EncoderMode_TI1 = ((uint8_t)0x01), /*!< Encoder mode 1*/
+ TIM5_EncoderMode_TI2 = ((uint8_t)0x02), /*!< Encoder mode 2*/
+ TIM5_EncoderMode_TI12 = ((uint8_t)0x03) /*!< Encoder mode 3*/
+}TIM5_EncoderMode_TypeDef;
+
+#define IS_TIM5_ENCODER_MODE(MODE) \
+ (((MODE) == TIM5_EncoderMode_TI1) || \
+ ((MODE) == TIM5_EncoderMode_TI2) || \
+ ((MODE) == TIM5_EncoderMode_TI12))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Event_Source
+ * @{
+ */
+typedef enum
+{
+ TIM5_EventSource_Update = ((uint8_t)0x01), /*!< Update Event*/
+ TIM5_EventSource_CC1 = ((uint8_t)0x02), /*!< Capture Compare Channel1 Event*/
+ TIM5_EventSource_CC2 = ((uint8_t)0x04), /*!< Capture Compare Channel2 Event*/
+ TIM5_EventSource_Trigger = ((uint8_t)0x40), /*!< Trigger Event*/
+ TIM5_EventSource_Break = ((uint8_t)0x80) /*!< Break Event*/
+}TIM5_EventSource_TypeDef;
+
+#define IS_TIM5_EVENT_SOURCE(SOURCE) ((((SOURCE) & (uint8_t)0x18) == 0x00) && \
+ ((SOURCE) != 0x00))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Update_Source
+ * @{
+ */
+typedef enum
+{
+ TIM5_UpdateSource_Global = ((uint8_t)0x00), /*!< Global Update request source */
+ TIM5_UpdateSource_Regular = ((uint8_t)0x01) /*!< Regular Update request source */
+}TIM5_UpdateSource_TypeDef;
+
+#define IS_TIM5_UPDATE_SOURCE(SOURCE) \
+ (((SOURCE) == TIM5_UpdateSource_Global) || \
+ ((SOURCE) == TIM5_UpdateSource_Regular))
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Trigger_Output_Source
+ * @{
+ */
+typedef enum
+{
+ TIM5_TRGOSource_Reset = ((uint8_t)0x00), /*!< Trigger Output source = Reset*/
+ TIM5_TRGOSource_Enable = ((uint8_t)0x10), /*!< Trigger Output source = TIM5 is enabled*/
+ TIM5_TRGOSource_Update = ((uint8_t)0x20), /*!< Trigger Output source = Update event*/
+ TIM5_TRGOSource_OC1 = ((uint8_t)0x30), /*!< Trigger Output source = output compare channel1 */
+ TIM5_TRGOSource_OC1REF = ((uint8_t)0x40), /*!< Trigger Output source = output compare channel 1 reference */
+ TIM5_TRGOSource_OC2REF = ((uint8_t)0x50) /*!< Trigger Output source = output compare channel 2 reference */
+}TIM5_TRGOSource_TypeDef;
+
+#define IS_TIM5_TRGO_SOURCE(SOURCE) \
+ (((SOURCE) == TIM5_TRGOSource_Reset) || \
+ ((SOURCE) == TIM5_TRGOSource_Enable) || \
+ ((SOURCE) == TIM5_TRGOSource_Update) || \
+ ((SOURCE) == TIM5_TRGOSource_OC1) || \
+ ((SOURCE) == TIM5_TRGOSource_OC1REF) || \
+ ((SOURCE) == TIM5_TRGOSource_OC2REF))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Slave_Mode
+ * @{
+ */
+typedef enum
+{
+ TIM5_SlaveMode_Reset = ((uint8_t)0x04), /*!< Slave Mode Selection = Reset*/
+ TIM5_SlaveMode_Gated = ((uint8_t)0x05), /*!< Slave Mode Selection = Gated*/
+ TIM5_SlaveMode_Trigger = ((uint8_t)0x06), /*!< Slave Mode Selection = Trigger*/
+ TIM5_SlaveMode_External1 = ((uint8_t)0x07) /*!< Slave Mode Selection = External 1*/
+}TIM5_SlaveMode_TypeDef;
+
+#define IS_TIM5_SLAVE_MODE(MODE) \
+ (((MODE) == TIM5_SlaveMode_Reset) || \
+ ((MODE) == TIM5_SlaveMode_Gated) || \
+ ((MODE) == TIM5_SlaveMode_Trigger) || \
+ ((MODE) == TIM5_SlaveMode_External1))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Flags
+ * @{
+ */
+typedef enum
+{
+ TIM5_FLAG_Update = ((uint16_t)0x0001), /*!< Update Flag */
+ TIM5_FLAG_CC1 = ((uint16_t)0x0002), /*!< Capture compare 1 Flag */
+ TIM5_FLAG_CC2 = ((uint16_t)0x0004), /*!< Capture compare 2 Flag */
+ TIM5_FLAG_Trigger = ((uint16_t)0x0040), /*!< Trigger Flag */
+ TIM5_FLAG_Break = ((uint16_t)0x0080), /*!< Break Flag */
+ TIM5_FLAG_CC1OF = ((uint16_t)0x0200), /*!< Capture compare 1 over capture Flag */
+ TIM5_FLAG_CC2OF = ((uint16_t)0x0400) /*!< Capture compare 2 over capture Flag */
+}TIM5_FLAG_TypeDef;
+
+#define IS_TIM5_GET_FLAG(FLAG) \
+ (((FLAG) == TIM5_FLAG_Update) || \
+ ((FLAG) == TIM5_FLAG_CC1) || \
+ ((FLAG) == TIM5_FLAG_CC2) || \
+ ((FLAG) == TIM5_FLAG_Trigger) || \
+ ((FLAG) == TIM5_FLAG_Break) || \
+ ((FLAG) == TIM5_FLAG_CC1OF) || \
+ ((FLAG) == TIM5_FLAG_CC2OF))
+
+#define IS_TIM5_CLEAR_FLAG(FLAG) \
+ ((((FLAG) & (uint16_t)0xE100) == 0x0000) && ((FLAG) != 0x0000))
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_DMA_Source_Requests
+ * @{
+ */
+typedef enum
+{
+ TIM5_DMASource_Update = ((uint8_t)0x01), /*!< TIM5 DMA Update Request*/
+ TIM5_DMASource_CC1 = ((uint8_t)0x02), /*!< TIM5 DMA CC1 Request*/
+ TIM5_DMASource_CC2 = ((uint8_t)0x04) /*!< TIM5 DMA CC2 Request*/
+}TIM5_DMASource_TypeDef;
+
+#define IS_TIM5_DMA_SOURCE(SOURCE) \
+ (((SOURCE) == TIM5_DMASource_Update) || \
+ ((SOURCE) == TIM5_DMASource_CC1) || \
+ ((SOURCE) == TIM5_DMASource_CC2))
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+
+/** @defgroup TIM5_Exported_Macros
+ * @{
+ */
+
+/**
+ * @brief Macro TIM5 Input Capture Filter Value
+ */
+#define IS_TIM5_IC_FILTER(ICFILTER) ((ICFILTER) <= 0x0F)
+
+/**
+ * @brief Macro TIM5 External Trigger Filter
+ */
+#define IS_TIM5_EXT_FILTER(EXTFILTER) \
+ ((EXTFILTER) <= 0x0F)
+
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+
+/* TimeBase management ********************************************************/
+void TIM5_DeInit(void);
+void TIM5_TimeBaseInit(TIM5_Prescaler_TypeDef TIM5_Prescaler,
+ TIM5_CounterMode_TypeDef TIM5_CounterMode, uint16_t TIM5_Period);
+void TIM5_PrescalerConfig(TIM5_Prescaler_TypeDef Prescaler,
+ TIM5_PSCReloadMode_TypeDef TIM5_PSCReloadMode);
+void TIM5_CounterModeConfig(TIM5_CounterMode_TypeDef TIM5_CounterMode);
+void TIM5_SetCounter(uint16_t Counter);
+void TIM5_SetAutoreload(uint16_t Autoreload);
+uint16_t TIM5_GetCounter(void);
+TIM5_Prescaler_TypeDef TIM5_GetPrescaler(void);
+void TIM5_UpdateDisableConfig(FunctionalState NewState);
+void TIM5_UpdateRequestConfig(TIM5_UpdateSource_TypeDef TIM5_UpdateSource);
+void TIM5_ARRPreloadConfig(FunctionalState NewState);
+void TIM5_SelectOnePulseMode(TIM5_OPMode_TypeDef TIM5_OPMode);
+void TIM5_Cmd(FunctionalState NewState);
+
+/* Output Compare management **************************************************/
+void TIM5_OC1Init(TIM5_OCMode_TypeDef TIM5_OCMode,
+ TIM5_OutputState_TypeDef TIM5_OutputState,
+ uint16_t TIM5_Pulse,
+ TIM5_OCPolarity_TypeDef TIM5_OCPolarity,
+ TIM5_OCIdleState_TypeDef TIM5_OCIdleState);
+void TIM5_OC2Init(TIM5_OCMode_TypeDef TIM5_OCMode,
+ TIM5_OutputState_TypeDef TIM5_OutputState,
+ uint16_t TIM5_Pulse,
+ TIM5_OCPolarity_TypeDef TIM5_OCPolarity,
+ TIM5_OCIdleState_TypeDef TIM5_OCIdleState);
+void TIM5_BKRConfig(TIM5_OSSIState_TypeDef TIM5_OSSIState,
+ TIM5_LockLevel_TypeDef TIM5_LockLevel,
+ TIM5_BreakState_TypeDef TIM5_BreakState,
+ TIM5_BreakPolarity_TypeDef TIM5_BreakPolarity,
+ TIM5_AutomaticOutput_TypeDef TIM5_AutomaticOutput);
+void TIM5_CtrlPWMOutputs(FunctionalState NewState);
+void TIM5_SelectOCxM(TIM5_Channel_TypeDef TIM5_Channel, TIM5_OCMode_TypeDef TIM5_OCMode);
+void TIM5_SetCompare1(uint16_t Compare);
+void TIM5_SetCompare2(uint16_t Compare);
+void TIM5_ForcedOC1Config(TIM5_ForcedAction_TypeDef TIM5_ForcedAction);
+void TIM5_ForcedOC2Config(TIM5_ForcedAction_TypeDef TIM5_ForcedAction);
+void TIM5_OC1PreloadConfig(FunctionalState NewState);
+void TIM5_OC2PreloadConfig(FunctionalState NewState);
+void TIM5_OC1FastConfig(FunctionalState NewState);
+void TIM5_OC2FastConfig(FunctionalState NewState);
+void TIM5_OC1PolarityConfig(TIM5_OCPolarity_TypeDef TIM5_OCPolarity);
+void TIM5_OC2PolarityConfig(TIM5_OCPolarity_TypeDef TIM5_OCPolarity);
+void TIM5_CCxCmd(TIM5_Channel_TypeDef TIM5_Channel, FunctionalState NewState);
+
+/* Input Capture management ***************************************************/
+void TIM5_ICInit(TIM5_Channel_TypeDef TIM5_Channel,
+ TIM5_ICPolarity_TypeDef TIM5_ICPolarity,
+ TIM5_ICSelection_TypeDef TIM5_ICSelection,
+ TIM5_ICPSC_TypeDef TIM5_ICPrescaler,
+ uint8_t TIM5_ICFilter);
+void TIM5_PWMIConfig(TIM5_Channel_TypeDef TIM5_Channel,
+ TIM5_ICPolarity_TypeDef TIM5_ICPolarity,
+ TIM5_ICSelection_TypeDef TIM5_ICSelection,
+ TIM5_ICPSC_TypeDef TIM5_ICPrescaler,
+ uint8_t TIM5_ICFilter);
+uint16_t TIM5_GetCapture1(void);
+uint16_t TIM5_GetCapture2(void);
+void TIM5_SetIC1Prescaler(TIM5_ICPSC_TypeDef TIM5_IC1Prescaler);
+void TIM5_SetIC2Prescaler(TIM5_ICPSC_TypeDef TIM5_IC2Prescaler);
+
+/* Interrupts, DMA and flags management ***************************************/
+void TIM5_ITConfig(TIM5_IT_TypeDef TIM5_IT, FunctionalState NewState);
+void TIM5_GenerateEvent(TIM5_EventSource_TypeDef TIM5_EventSource);
+FlagStatus TIM5_GetFlagStatus(TIM5_FLAG_TypeDef TIM5_FLAG);
+void TIM5_ClearFlag(TIM5_FLAG_TypeDef TIM5_FLAG);
+ITStatus TIM5_GetITStatus(TIM5_IT_TypeDef TIM5_IT);
+void TIM5_ClearITPendingBit(TIM5_IT_TypeDef TIM5_IT);
+void TIM5_DMACmd(TIM5_DMASource_TypeDef TIM5_DMASource, FunctionalState NewState);
+void TIM5_SelectCCDMA(FunctionalState NewState);
+
+/* Clocks management **********************************************************/
+void TIM5_InternalClockConfig(void);
+void TIM5_TIxExternalClockConfig(TIM5_TIxExternalCLK1Source_TypeDef TIM5_TIxExternalCLKSource,
+ TIM5_ICPolarity_TypeDef TIM5_ICPolarity,
+ uint8_t ICFilter);
+void TIM5_ETRClockMode1Config(TIM5_ExtTRGPSC_TypeDef TIM5_ExtTRGPrescaler,
+ TIM5_ExtTRGPolarity_TypeDef TIM5_ExtTRGPolarity,
+ uint8_t ExtTRGFilter);
+void TIM5_ETRClockMode2Config(TIM5_ExtTRGPSC_TypeDef TIM5_ExtTRGPrescaler,
+ TIM5_ExtTRGPolarity_TypeDef TIM5_ExtTRGPolarity,
+ uint8_t ExtTRGFilter);
+
+/* Synchronization management *************************************************/
+void TIM5_SelectInputTrigger(TIM5_TRGSelection_TypeDef TIM5_InputTriggerSource);
+void TIM5_SelectOutputTrigger(TIM5_TRGOSource_TypeDef TIM5_TRGOSource);
+void TIM5_SelectSlaveMode(TIM5_SlaveMode_TypeDef TIM5_SlaveMode);
+void TIM5_SelectMasterSlaveMode(FunctionalState NewState);
+void TIM5_ETRConfig(TIM5_ExtTRGPSC_TypeDef TIM5_ExtTRGPrescaler,
+ TIM5_ExtTRGPolarity_TypeDef TIM5_ExtTRGPolarity,
+ uint8_t ExtTRGFilter);
+
+/* Specific interface management **********************************************/
+void TIM5_EncoderInterfaceConfig(TIM5_EncoderMode_TypeDef TIM5_EncoderMode,
+ TIM5_ICPolarity_TypeDef TIM5_IC1Polarity,
+ TIM5_ICPolarity_TypeDef TIM5_IC2Polarity);
+void TIM5_SelectHallSensor(FunctionalState NewState);
+
+#endif /* __STM8L15x_TIM5_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_usart.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_usart.h
new file mode 100644
index 00000000..41abd618
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_usart.h
@@ -0,0 +1,393 @@
+/**
+ ********************************************************************************
+ * @file stm8l15x_usart.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the USART firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_USART_H
+#define __STM8L15x_USART_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+#include "stm8l15x_clk.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+/** @addtogroup USART
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup USART_Exported_Types
+ * @{
+ */
+
+/** @defgroup USART_Flags
+ * @{
+ */
+typedef enum
+{
+ USART_FLAG_TXE = (uint16_t)0x0080, /*!< Transmit Data Register Empty flag */
+ USART_FLAG_TC = (uint16_t)0x0040, /*!< Transmission Complete flag */
+ USART_FLAG_RXNE = (uint16_t)0x0020, /*!< Read Data Register Not Empty flag */
+ USART_FLAG_IDLE = (uint16_t)0x0010, /*!< Idle line detected flag */
+ USART_FLAG_OR = (uint16_t)0x0008, /*!< OverRun error flag */
+ USART_FLAG_NF = (uint16_t)0x0004, /*!< Noise error flag */
+ USART_FLAG_FE = (uint16_t)0x0002, /*!< Framing Error flag */
+ USART_FLAG_PE = (uint16_t)0x0001, /*!< Parity Error flag */
+ USART_FLAG_SBK = (uint16_t)0x0101 /*!< Send Break characters Flag */
+} USART_FLAG_TypeDef;
+
+#define IS_USART_FLAG(Flag) \
+ (((Flag) == USART_FLAG_TXE) || \
+ ((Flag) == USART_FLAG_TC) || \
+ ((Flag) == USART_FLAG_RXNE) || \
+ ((Flag) == USART_FLAG_IDLE) || \
+ ((Flag) == USART_FLAG_OR) || \
+ ((Flag) == USART_FLAG_NF) || \
+ ((Flag) == USART_FLAG_FE) || \
+ ((Flag) == USART_FLAG_PE) || \
+ ((Flag) == USART_FLAG_SBK))
+
+#define IS_USART_CLEAR_FLAG(Flag) (((Flag) == USART_FLAG_TC))
+
+/**
+ * @}
+ */
+
+/** @defgroup USART_Interrupts
+ * @{
+ */
+
+/**
+ * @brief USART Interrupt definition
+ * USART_IT possible values
+ * Elements values convention: 0x0ZYX
+ * X: Position of the corresponding Interrupt
+ * Y: Flag position
+ * Z: Register index
+ */
+typedef enum
+{
+ USART_IT_TXE = (uint16_t)0x0277, /*!< Transmit interrupt */
+ USART_IT_TC = (uint16_t)0x0266, /*!< Transmission Complete interrupt */
+ USART_IT_RXNE = (uint16_t)0x0255, /*!< Receive interrupt */
+ USART_IT_IDLE = (uint16_t)0x0244, /*!< IDLE line interrupt */
+ USART_IT_OR = (uint16_t)0x0235, /*!< Overrun Error interrupt */
+ USART_IT_PE = (uint16_t)0x0100, /*!< Parity Error interrupt */
+ USART_IT_ERR = (uint16_t)0x0500, /*!< Error interrupt */
+ USART_IT_NF = (uint16_t)0x0102, /*!< Noise Error interrupt */
+ USART_IT_FE = (uint16_t)0x0101 /*!< Frame Error interrupt */
+} USART_IT_TypeDef;
+
+#define IS_USART_CONFIG_IT(Interrupt) \
+ (((Interrupt) == USART_IT_PE) || \
+ ((Interrupt) == USART_IT_TXE) || \
+ ((Interrupt) == USART_IT_TC) || \
+ ((Interrupt) == USART_IT_RXNE) || \
+ ((Interrupt) == USART_IT_OR) || \
+ ((Interrupt) == USART_IT_ERR) || \
+ ((Interrupt) == USART_IT_IDLE))
+
+#define IS_USART_GET_IT(ITPendingBit) \
+ (((ITPendingBit) == USART_IT_TXE) || \
+ ((ITPendingBit) == USART_IT_TC) || \
+ ((ITPendingBit) == USART_IT_RXNE) || \
+ ((ITPendingBit) == USART_IT_IDLE) || \
+ ((ITPendingBit) == USART_IT_OR) || \
+ ((ITPendingBit) == USART_IT_PE))
+
+#define IS_USART_CLEAR_IT(IT) (((IT) == USART_IT_TC) || ((IT) == USART_IT_RXNE))
+/**
+ * @}
+ */
+
+/** @defgroup USART_Wakeup_Modes
+ * @{
+ */
+typedef enum
+{
+ USART_WakeUp_IdleLine = (uint8_t)0x00, /*!< 0x01 Idle Line wake up */
+ USART_WakeUp_AddressMark = (uint8_t)0x08 /*!< 0x02 Address Mark wake up */
+} USART_WakeUp_TypeDef;
+
+#define IS_USART_WAKEUP(WakeUpMode)(((WakeUpMode) == USART_WakeUp_IdleLine) || \
+ ((WakeUpMode) == USART_WakeUp_AddressMark))
+/**
+ * @}
+ */
+
+/** @defgroup USART_Stop_Bits
+ * @{
+ */
+typedef enum
+{
+ USART_StopBits_1 = (uint8_t)0x00, /*!< One stop bit is transmitted at the end of frame*/
+ USART_StopBits_2 = (uint8_t)0x20, /*!< Two stop bits are transmitted at the end of frame*/
+ USART_StopBits_1_5 = (uint8_t)0x30 /*!< One and half stop bits*/
+} USART_StopBits_TypeDef;
+
+#define IS_USART_STOPBITS(StopBit)(((StopBit) == USART_StopBits_1) || \
+ ((StopBit) == USART_StopBits_1_5) || \
+ ((StopBit) == USART_StopBits_2))
+/**
+ * @}
+ */
+
+/** @defgroup USART_Parity
+ * @{
+ */
+typedef enum
+{
+ USART_Parity_No = (uint8_t)0x00, /*!< No Parity*/
+ USART_Parity_Even = (uint8_t)0x04, /*!< Even Parity*/
+ USART_Parity_Odd = (uint8_t)0x06 /*!< Odd Parity*/
+} USART_Parity_TypeDef;
+
+#define IS_USART_PARITY(Parity)(((Parity) == USART_Parity_No) || \
+ ((Parity) == USART_Parity_Even) || \
+ ((Parity) == USART_Parity_Odd ))
+/**
+ * @}
+ */
+
+/** @defgroup USART_Lin_Break_Detection_Length
+ * @{
+ */
+typedef enum
+{
+ USART_LINBreakDetectionLength_10BITS = (uint8_t)0x00, /*!< 10 bits Lin Break detection */
+ USART_LINBreakDetectionLength_11BITS = (uint8_t)0x01 /*!< 11 bits Lin Break detection */
+} USART_LINBreakDetectionLength_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @defgroup USART_Word_Length
+ * @{
+ */
+typedef enum
+{
+ USART_WordLength_8b = (uint8_t)0x00, /*!< 8 bits Data */
+ USART_WordLength_9b = (uint8_t)0x10 /*!< 9 bits Data */
+} USART_WordLength_TypeDef;
+
+#define IS_USART_WORDLENGTH(WordLength) (((WordLength) == USART_WordLength_8b) || \
+ ((WordLength) == USART_WordLength_9b))
+
+/**
+ * @}
+ */
+
+/** @defgroup USART_Mode
+ * @{
+ */
+typedef enum
+{
+ USART_Mode_Rx = (uint8_t)0x04, /*!< Receive Enable */
+ USART_Mode_Tx = (uint8_t)0x08 /*!< Transmit Enable */
+} USART_Mode_TypeDef;
+
+#define IS_USART_MODE(MODE) ((((MODE) & (uint8_t)0xF3) == 0x00) && ((MODE) != (uint16_t)0x00))
+/**
+ * @}
+ */
+
+/** @defgroup USART_DMA_Requests
+ * @{
+ */
+typedef enum
+{
+ USART_DMAReq_TX = (uint8_t)0x80, /*!< Receive DMA request Enable */
+ USART_DMAReq_RX = (uint8_t)0x40 /*!< Transmit DMA request Enable */
+} USART_DMAReq_TypeDef;
+
+#define IS_USART_DMAREQ(DMAReq) ((((DMAReq) & (uint8_t)0x3F) == 0x00) && ((DMAReq) != (uint8_t)0x00))
+/**
+ * @}
+ */
+
+/** @defgroup USART_IrDA_Mode
+ * @{
+ */
+typedef enum
+{
+ USART_IrDAMode_Normal = (uint8_t)0x00, /*!< IrDA Normal Mode */
+ USART_IrDAMode_LowPower = (uint8_t)0x01 /*!< IrDA Low Power Mode */
+} USART_IrDAMode_TypeDef;
+
+#define IS_USART_IRDAMODE(IrDAMode) (((IrDAMode) == USART_IrDAMode_LowPower) || \
+ ((IrDAMode) == USART_IrDAMode_Normal))
+/**
+ * @}
+ */
+
+/** @defgroup USART_Clock
+ * @{
+ */
+typedef enum
+{
+ USART_Clock_Disable = (uint8_t)0x00, /*!< CK pin disabled */
+ USART_Clock_Enable = (uint8_t)0x08 /*!< CK pin enabled */
+} USART_Clock_TypeDef;
+
+#define IS_USART_CLOCK(CLOCK) (((CLOCK) == USART_Clock_Disable) ||((CLOCK) == USART_Clock_Enable))
+/**
+ * @}
+ */
+
+/** @defgroup USART_Clock_Polarity
+ * @{
+ */
+typedef enum
+{
+ USART_CPOL_Low = (uint8_t)0x00, /*!< CK to 0 when idle */
+ USART_CPOL_High = (uint8_t)0x04 /*!< CK to 1 when idle.*/
+} USART_CPOL_TypeDef;
+
+#define IS_USART_CPOL(CPOL) (((CPOL) == USART_CPOL_Low) || ((CPOL) == USART_CPOL_High))
+/**
+ * @}
+ */
+
+/** @defgroup USART_Clock_Phase
+ * @{
+ */
+typedef enum
+{
+ USART_CPHA_1Edge = (uint8_t)0x00, /*!< The first clock transition is the first data capture edge*/
+ USART_CPHA_2Edge = (uint8_t)0x02 /*!< The second clock transition is the first data capture edge*/
+} USART_CPHA_TypeDef;
+
+#define IS_USART_CPHA(CPHA) (((CPHA) == USART_CPHA_1Edge) || ((CPHA) == USART_CPHA_2Edge))
+/**
+ * @}
+ */
+
+/** @defgroup USART_LastBit
+ * @{
+ */
+typedef enum
+{
+ USART_LastBit_Disable = (uint8_t)0x00, /*!< The clock pulse of the last data bit is not output to the SCLK pin.*/
+ USART_LastBit_Enable = (uint8_t)0x01 /*!< The clock pulse of the last data bit is output to the SCLK pin.*/
+} USART_LastBit_TypeDef;
+
+#define IS_USART_LASTBIT(LASTBIT) (((LASTBIT) == USART_LastBit_Disable) || \
+ ((LASTBIT) == USART_LastBit_Enable))
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+/** @defgroupUSART_Exported_Macros
+ * @{
+ */
+/* BaudRate value should be < 625000 bps */
+#define IS_USART_BAUDRATE(NUM) ((NUM) <= (uint32_t)625000)
+
+#define USART_ADDRESS_MAX ((uint8_t)16)
+#define IS_USART_ADDRESS(address) ((address) < USART_ADDRESS_MAX)
+
+#define USART_DATA_9BITS_MAX ((uint16_t)0x1FF)
+#define IS_USART_DATA_9BITS(DATA) ((DATA) < USART_DATA_9BITS_MAX)
+
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+
+/* Function used to set the USART configuration to the default reset state ***/
+void USART_DeInit(USART_TypeDef* USARTx);
+
+/* Initialization and Configuration functions *********************************/
+void USART_Init(USART_TypeDef* USARTx, uint32_t BaudRate, USART_WordLength_TypeDef
+ USART_WordLength, USART_StopBits_TypeDef USART_StopBits,
+ USART_Parity_TypeDef USART_Parity, USART_Mode_TypeDef USART_Mode);
+void USART_ClockInit(USART_TypeDef* USARTx, USART_Clock_TypeDef USART_Clock,
+ USART_CPOL_TypeDef USART_CPOL, USART_CPHA_TypeDef USART_CPHA,
+ USART_LastBit_TypeDef USART_LastBit);
+void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
+void USART_SetPrescaler(USART_TypeDef* USARTx, uint8_t USART_Prescaler);
+void USART_SendBreak(USART_TypeDef* USARTx);
+
+/* Data transfers functions ***************************************************/
+void USART_SendData8(USART_TypeDef* USARTx, uint8_t Data);
+void USART_SendData9(USART_TypeDef* USARTx, uint16_t Data);
+uint8_t USART_ReceiveData8(USART_TypeDef* USARTx);
+uint16_t USART_ReceiveData9(USART_TypeDef* USARTx);
+
+/* Multi-Processor Communication functions ************************************/
+void USART_WakeUpConfig(USART_TypeDef* USARTx, USART_WakeUp_TypeDef USART_WakeUp);
+void USART_ReceiverWakeUpCmd(USART_TypeDef* USARTx, FunctionalState NewState);
+void USART_SetAddress(USART_TypeDef* USARTx, uint8_t USART_Address);
+
+/* Half-duplex mode function **************************************************/
+void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState NewState);
+
+/* Smartcard mode functions ***************************************************/
+void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState NewState);
+void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState NewState);
+void USART_SetGuardTime(USART_TypeDef* USARTx, uint8_t USART_GuardTime);
+
+/* IrDA mode functions ********************************************************/
+void USART_IrDAConfig(USART_TypeDef* USARTx, USART_IrDAMode_TypeDef USART_IrDAMode);
+void USART_IrDACmd(USART_TypeDef* USARTx, FunctionalState NewState);
+
+/* DMA transfers management functions *****************************************/
+void USART_DMACmd(USART_TypeDef* USARTx, USART_DMAReq_TypeDef USART_DMAReq,
+ FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void USART_ITConfig(USART_TypeDef* USARTx, USART_IT_TypeDef USART_IT,
+ FunctionalState NewState);
+FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, USART_FLAG_TypeDef USART_FLAG);
+void USART_ClearFlag(USART_TypeDef* USARTx, USART_FLAG_TypeDef USART_FLAG);
+ITStatus USART_GetITStatus(USART_TypeDef* USARTx, USART_IT_TypeDef USART_IT);
+void USART_ClearITPendingBit(USART_TypeDef* USARTx, USART_IT_TypeDef USART_IT);
+
+
+
+#endif /* __STM8L15x_USART_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_wfe.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_wfe.h
new file mode 100644
index 00000000..8caa8fef
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_wfe.h
@@ -0,0 +1,154 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_wfe.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the WFE firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_WFE_H
+#define __STM8L15x_WFE_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup WFE
+ * @{
+ */
+/* Exported types ------------------------------------------------------------*/
+
+/** @defgroup WFE_Exported_Types
+ * @{
+ */
+/** @defgroup WFE_Sources
+ * @brief Signal Sources to generate wake_up events
+@verbatim
+ Elements values convention: 0xXXYY
+ X = SRx registers index
+ XX = 01 : CR1
+ XX = 02 : CR2
+ XX = 03 : CR3
+ XX = 04 : CR4
+ YY = flag mask in the dedicated register(XX register)
+@endverbatim
+ * @{
+ */
+typedef enum {
+ WFE_Source_TIM2_EV0 = (uint16_t)0x0101, /*!< TIM2 Update/Trigger and Break interrupt */
+ WFE_Source_TIM2_EV1 = (uint16_t)0x0102, /*!< TIM2 Capture/Compare interrupt */
+ WFE_Source_TIM1_EV0 = (uint16_t)0x0104, /*!< TIM1 Update/Trigger and Break interrupt */
+ WFE_Source_TIM1_EV1 = (uint16_t)0x0108, /*!< TIM1 Capture/Compare interrupt */
+ WFE_Source_EXTI_EV0 = (uint16_t)0x0110, /*!< I/O port interrupt from Pins 0 */
+ WFE_Source_EXTI_EV1 = (uint16_t)0x0120, /*!< I/O port interrupt from Pins 1 */
+ WFE_Source_EXTI_EV2 = (uint16_t)0x0140, /*!< I/O port interrupt from Pins 2 */
+ WFE_Source_EXTI_EV3 = (uint16_t)0x0180, /*!< I/O port interrupt from Pins 3 */
+ WFE_Source_EXTI_EV4 = (uint16_t)0x0201, /*!< I/O port interrupt from Pins 4 */
+ WFE_Source_EXTI_EV5 = (uint16_t)0x0202, /*!< I/O port interrupt from Pins 5 */
+ WFE_Source_EXTI_EV6 = (uint16_t)0x0204, /*!< I/O port interrupt from Pins 6 */
+ WFE_Source_EXTI_EV7 = (uint16_t)0x0208, /*!< I/O port interrupt from Pins 7 */
+ WFE_Source_EXTI_EVB_G = (uint16_t)0x0210, /*!< I/O port interrupt from port B and G */
+ WFE_Source_EXTI_EVD_H = (uint16_t)0x0220, /*!< I/O port interrupt from Port D and H */
+ WFE_Source_EXTI_EVE_F = (uint16_t)0x0240, /*!< I/O port interrupt from Port E and F */
+ WFE_Source_ADC1_COMP_EV = (uint16_t)0x0280, /*!< ADC1, COMP1 and COMP2 interrupts */
+ WFE_Source_TIM3_EV0 = (uint16_t)0x0301, /*!< TIM3 Update/Trigger and Break interrupt */
+ WFE_Source_TIM3_EV1 = (uint16_t)0x0302, /*!< TIM3 Capture/Compare interrupt */
+ WFE_Source_TIM4_EV = (uint16_t)0x0304, /*!< TIM4 Update and Trigger interrupt */
+ WFE_Source_SPI1_EV = (uint16_t)0x0308, /*!< SPI1 Rx and Tx interrupt */
+ WFE_Source_I2C1_EV = (uint16_t)0x0310, /*!< I2C1 Rx and Tx interrupt */
+ WFE_Source_USART1_EV = (uint16_t)0x0320, /*!< USART1 Rx and Tx interrupt */
+ WFE_Source_DMA1CH01_EV = (uint16_t)0x0340, /*!< DMA1 channel 0 and 1 interrupt */
+ WFE_Source_DMA1CH23_EV = (uint16_t)0x0380, /*!< DMA1 channel 2 and 3 interrupt */
+ WFE_Source_RTC_CSS_EV = (uint16_t)0x0401, /*!< RTC or CSS on LSE event */
+ WFE_Source_SPI2_EV = (uint16_t)0x0402, /*!< SPI2 Rx and Tx interrupt */
+ WFE_Source_USART2_EV = (uint16_t)0x0404, /*!< USART2 Rx and Tx interrupt */
+ WFE_Source_USART3_EV = (uint16_t)0x0408, /*!< USART3 Rx and Tx interrupt */
+ WFE_Source_TIM5_EV0 = (uint16_t)0x0410, /*!< TIM5 Update/Trigger and Break interrupt */
+ WFE_Source_TIM5_EV1 = (uint16_t)0x0420, /*!< TIM5 Capture/Compare interrupt */
+ WFE_Source_AES_EV = (uint16_t)0x0440 /*!< AES interrupt */
+} WFE_Source_TypeDef;
+
+#define IS_WFE_SOURCE(Source) (((Source) == WFE_Source_TIM2_EV0) || \
+ ((Source) == WFE_Source_TIM2_EV1) || \
+ ((Source) == WFE_Source_TIM1_EV0) || \
+ ((Source) == WFE_Source_TIM1_EV1) || \
+ ((Source) == WFE_Source_EXTI_EV0) || \
+ ((Source) == WFE_Source_EXTI_EV1) || \
+ ((Source) == WFE_Source_EXTI_EV2) || \
+ ((Source) == WFE_Source_EXTI_EV3) || \
+ ((Source) == WFE_Source_EXTI_EV4) || \
+ ((Source) == WFE_Source_EXTI_EV5) || \
+ ((Source) == WFE_Source_EXTI_EV6) || \
+ ((Source) == WFE_Source_EXTI_EV7) || \
+ ((Source) == WFE_Source_EXTI_EVB_G) || \
+ ((Source) == WFE_Source_EXTI_EVD_H) || \
+ ((Source) == WFE_Source_EXTI_EVE_F) || \
+ ((Source) == WFE_Source_ADC1_COMP_EV) || \
+ ((Source) == WFE_Source_TIM3_EV0) || \
+ ((Source) == WFE_Source_TIM3_EV1) || \
+ ((Source) == WFE_Source_TIM4_EV) || \
+ ((Source) == WFE_Source_SPI1_EV) || \
+ ((Source) == WFE_Source_I2C1_EV) || \
+ ((Source) == WFE_Source_USART1_EV) || \
+ ((Source) == WFE_Source_DMA1CH01_EV) || \
+ ((Source) == WFE_Source_AES_EV) || \
+ ((Source) == WFE_Source_TIM5_EV1) || \
+ ((Source) == WFE_Source_TIM5_EV0) || \
+ ((Source) == WFE_Source_USART3_EV) || \
+ ((Source) == WFE_Source_USART2_EV) || \
+ ((Source) == WFE_Source_SPI2_EV) || \
+ ((Source) == WFE_Source_RTC_CSS_EV) || \
+ ((Source) == WFE_Source_DMA1CH23_EV))
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+/* Function used to set the WFE configuration to the default reset state ******/
+void WFE_DeInit(void);
+
+/* WFE Source configuration and management functions **************************/
+void WFE_WakeUpSourceEventCmd(WFE_Source_TypeDef WFE_Source, FunctionalState NewState);
+FunctionalState WFE_GetWakeUpSourceEventStatus(WFE_Source_TypeDef WFE_Source);
+
+#endif /* __STM8L15x_WFE_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_wwdg.h b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_wwdg.h
new file mode 100644
index 00000000..c97ef292
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/inc/stm8l15x_wwdg.h
@@ -0,0 +1,96 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_wwdg.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains all the functions prototypes for the WWDG firmware
+ * library.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_WWDG_H
+#define __STM8L15x_WWDG_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @addtogroup WWDG
+ * @{
+ */
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+
+/** @defgroup WWDG_Exported_Macros
+ * @{
+ */
+
+/** @defgroup WWDG_WindowLimitValue
+ * @{
+ */
+#define IS_WWDG_WINDOW_LIMIT_VALUE(WindowLimitValue) ((WindowLimitValue) <= 0x7F)
+
+/**
+ * @}
+ */
+
+/** @defgroup WWDG_CounterValue
+ * @{
+ */
+#define IS_WWDG_COUNTER_VALUE(CounterValue) ((CounterValue) <= 0x7F)
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Exported functions ------------------------------------------------------- */
+/* Refresh window and Counter configuration functions *************************/
+void WWDG_Init(uint8_t Counter, uint8_t WindowValue);
+void WWDG_SetWindowValue(uint8_t WindowValue);
+void WWDG_SetCounter(uint8_t Counter);
+
+/* WWDG activation function ***************************************************/
+void WWDG_Enable(uint8_t Counter);
+
+/* WWDG counter and software reset management **********************************/
+uint8_t WWDG_GetCounter(void);
+void WWDG_SWReset(void);
+
+
+#endif /* __STM8L15x_WWDG_H */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
\ No newline at end of file
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_adc.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_adc.c
new file mode 100644
index 00000000..e03e2d3c
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_adc.c
@@ -0,0 +1,988 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_adc.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Analog to Digital Convertor (ADC) peripheral:
+ * - Initialization and Configuration
+ * - Power saving
+ * - Analog Watchdog configuration
+ * - Temperature Sensor & Vrefint (Voltage Reference internal) management
+ * - Regular Channels Configuration
+ * - Regular Channels DMA Configuration
+ * - Injected channels Configuration
+ * - Interrupts and flags management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * 1. Enable The ADC controller clock using CLK_PeripheralClockConfig()
+ * function : CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, ENABLE).
+ *
+ * 2. Configure the ADC Prescaler, conversion resolution and data
+ * alignment using the ADC_Init() function.
+ *
+ * 3. Activate the ADC peripheral using ADC_Cmd() function.
+ *
+ * Regular channels group configuration
+ * ====================================
+ * - To configure the ADC regular channels group features, use
+ * ADC_Init() and ADC_RegularChannelConfig() functions.
+ * - To activate the continuous mode, use the ADC_continuousModeCmd()
+ * function.
+ * - To configure and activate the Discontinuous mode, use the
+ * ADC_DiscModeChannelCountConfig() and ADC_DiscModeCmd() functions.
+ * - To read the ADC converted values, use the ADC_GetConversionValue()
+ * function.
+ *
+ * DMA for Regular channels group features configuration
+ * ======================================================
+ * - To enable the DMA mode for regular channels group, use the
+ * ADC_DMACmd() function.
+ * - To enable the generation of DMA requests continuously at the end
+ * of the last DMA transfer, use the ADC_DMARequestAfterLastTransferCmd()
+ * function.
+
+ * Injected channels group configuration
+ * =====================================
+ * - To configure the ADC Injected channels group features, use
+ * ADC_InjectedChannelConfig() and ADC_InjectedSequencerLengthConfig()
+ * functions.
+ * - To activate the continuous mode, use the ADC_continuousModeCmd()
+ * function.
+ * - To activate the Injected Discontinuous mode, use the
+ * ADC_InjectedDiscModeCmd() function.
+ * - To activate the AutoInjected mode, use the ADC_AutoInjectedConvCmd()
+ * function.
+ * - To read the ADC converted values, use the ADC_GetInjectedConversionValue()
+ * function.
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_adc.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup ADC
+ * @brief ADC driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup ADC_Private_Functions
+ * @{
+ */
+
+
+/** @defgroup ADC_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Initialization and Configuration functions
+ ===============================================================================
+ This section provides functions allowing to:
+ - Enable or disable the ADC peripheral,
+ - Initialize and configure the ADC Prescaler, ADC Conversion Resolution
+ (12bit..6bit), ADC Continuous Conversion Mode (Continuous or Single
+ conversion),
+ - Configure External trigger Sensitivity and source,
+ - Start ADC conversion, by software trigger.
+
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Deinitializes the ADC peripheral registers to their default reset
+ * values.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @retval None
+ */
+void ADC_DeInit(ADC_TypeDef* ADCx)
+{
+ /* Set the Configuration registers to their reset values */
+ ADCx->CR1 = ADC_CR1_RESET_VALUE;
+ ADCx->CR2 = ADC_CR2_RESET_VALUE;
+ ADCx->CR3 = ADC_CR3_RESET_VALUE;
+
+ /* Set the status registers to their reset values */
+ ADCx->SR = (uint8_t)~ADC_SR_RESET_VALUE;
+
+ /* Set the High threshold registers to their reset values */
+ ADCx->HTRH = ADC_HTRH_RESET_VALUE;
+ ADCx->HTRL = ADC_HTRL_RESET_VALUE;
+
+ /* Set the low threshold registers to their reset values */
+ ADCx->LTRH = ADC_LTRH_RESET_VALUE;
+ ADCx->LTRL = ADC_LTRL_RESET_VALUE;
+
+ /* Set the channels sequence registers to their reset values */
+ ADCx->SQR[0] = ADC_SQR1_RESET_VALUE;
+ ADCx->SQR[1] = ADC_SQR2_RESET_VALUE;
+ ADCx->SQR[2] = ADC_SQR3_RESET_VALUE;
+ ADCx->SQR[3] = ADC_SQR4_RESET_VALUE;
+
+ /* Set the channels Trigger registers to their reset values */
+ ADCx->TRIGR[0] = ADC_TRIGR1_RESET_VALUE;
+ ADCx->TRIGR[1] = ADC_TRIGR2_RESET_VALUE;
+ ADCx->TRIGR[2] = ADC_TRIGR3_RESET_VALUE;
+ ADCx->TRIGR[3] = ADC_TRIGR4_RESET_VALUE;
+}
+
+/**
+ * @brief Initializes the specified ADC peripheral according to the specified
+ * parameters.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param ADC_ConversionMode : specifies the ADC conversion mode,
+ * This parameter can be one of the following values:
+ * @arg ADC_ConversionMode_Single: Single Conversion Mode
+ * @arg ADC_ConversionMode_Continuous: Continuous Conversion Mode
+ * @param ADC_Resolution : specifies the ADC Data resolution,
+ * This parameter can be one of the following values:
+ * @arg ADC_Resolution_12Bit: 12 bit resolution
+ * @arg ADC_Resolution_10Bit: 10 bit resolution
+ * @arg ADC_Resolution_8Bit: 8 bit resolution
+ * @arg ADC_Resolution_6Bit: 6 bit resolution
+ * @param ADC_Prescaler : specifies the ADC Prescaler,
+ * This parameter can be one of the following values:
+ * @arg ADC_Prescaler_1: ADC Clock frequency is divided by 1
+ * @arg ADC_Prescaler_2: ADC Clock frequency is divided by 2
+ * @retval None
+ */
+void ADC_Init(ADC_TypeDef* ADCx,
+ ADC_ConversionMode_TypeDef ADC_ConversionMode,
+ ADC_Resolution_TypeDef ADC_Resolution,
+ ADC_Prescaler_TypeDef ADC_Prescaler)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_CONVERSION_MODE(ADC_ConversionMode));
+ assert_param(IS_ADC_RESOLUTION(ADC_Resolution));
+ assert_param(IS_ADC_PRESCALER(ADC_Prescaler));
+
+ /*clear CR1 register */
+ ADCx->CR1 &= (uint8_t)~(ADC_CR1_CONT | ADC_CR1_RES);
+
+ /* set the resolution and the conversion mode */
+ ADCx->CR1 |= (uint8_t)((uint8_t)ADC_ConversionMode | (uint8_t)ADC_Resolution);
+
+ /*clear CR2 register */
+ ADCx->CR2 &= (uint8_t)~(ADC_CR2_PRESC);
+
+ /* set the Prescaler */
+ ADCx->CR2 |= (uint8_t) ADC_Prescaler;
+}
+
+/**
+ * @brief Enables or disables the selected ADC peripheral.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param NewState : new state of the specified ADC peripheral.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_Cmd(ADC_TypeDef* ADCx,
+ FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Set the ADON bit to wake up the specified ADC from power down mode */
+ ADCx->CR1 |= ADC_CR1_ADON;
+ }
+ else
+ {
+ /* Disable the selected ADC peripheral */
+ ADCx->CR1 &= (uint8_t)~ADC_CR1_ADON;
+ }
+}
+
+/**
+ * @brief Starts ADC conversion, by software trigger.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @retval None
+ */
+void ADC_SoftwareStartConv(ADC_TypeDef* ADCx)
+{
+ /* Start the ADC software conversion */
+ ADCx->CR1 |= ADC_CR1_START;
+}
+
+/**
+ * @brief Configures the ADC conversion through external trigger.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param ADC_ExtEventSelection : Specifies the external trigger.
+ * This parameter can be one of the following values:
+ * @arg ADC_ExtEventSelection_None: Conversion starts only by software start
+ * @arg ADC_ExtEventSelection_Trigger1: Trigger 1 Enables conversion
+ * @arg ADC_ExtEventSelection_Trigger2: Trigger 2 Enables conversion
+ * @arg ADC_ExtEventSelection_Trigger3: Trigger 3 Enables conversion
+ * @param ADC_ExtTRGSensitivity : Specifies the external trigger sensitivity.
+ * This parameter can be one of the following values:
+ * @arg ADC_ExtTRGSensitivity_Rising: External Trigger Sensitivity is Rising Edge
+ * @arg ADC_ExtTRGSensitivity_Falling: External Trigger Sensitivity is Falling Edge
+ * @arg ADC_ExtTRGSensitivity_All: External Trigger Sensitivity is Falling and Rising Edge
+ * @retval None
+ */
+void ADC_ExternalTrigConfig(ADC_TypeDef* ADCx,
+ ADC_ExtEventSelection_TypeDef ADC_ExtEventSelection,
+ ADC_ExtTRGSensitivity_TypeDef ADC_ExtTRGSensitivity)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_EXT_EVENT_SELECTION(ADC_ExtEventSelection));
+ assert_param(IS_ADC_EXT_TRG_SENSITIVITY(ADC_ExtTRGSensitivity));
+
+ /*clear old configuration of CR2 register */
+ ADCx->CR2 &= (uint8_t)~(ADC_CR2_TRIGEDGE | ADC_CR2_EXTSEL);
+
+ /* set the External Trigger Edge Sensitivity and the external event
+ selection */
+ ADCx->CR2 |= (uint8_t)( (uint8_t)ADC_ExtTRGSensitivity | \
+ (uint8_t)ADC_ExtEventSelection);
+}
+
+ /**
+ * @}
+ */
+
+/** @defgroup ADC_Group2 Analog Watchdog configuration functions
+ * @brief Analog Watchdog configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Analog Watchdog configuration functions
+ ===============================================================================
+
+ This section provides functions allowing to configure the Analog Watchdog
+ (AWD) feature in the ADC.
+
+ A typical configuration Analog Watchdog is done following these steps :
+ 1. the ADC guarded channel is selected using the
+ ADC_AnalogWatchdogChannelSelect() function.
+ 2. The Analog watchdog lower and higher threshold are configured using the
+ ADC_AnalogWatchdogThresholdsConfig() function.
+
+ Note : Both AWD selection and thresholds can be configured with one unique
+ function ADC_AnalogWatchdogConfig(), which is kept for firmware
+ compatibility reason.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Configures the channel to be checked by the Analog watchdog.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param ADC_AnalogWatchdogSelection : Specifies the channel to be checked
+ * by the Analog watchdog.
+ * This parameter can be one of the following values:
+ * @arg ADC_AnalogWatchdogSelection_Channel0: AWD affected to Channel 0
+ * @arg ADC_AnalogWatchdogSelection_Channel1: AWD affected to Channel 1
+ * @arg ADC_AnalogWatchdogSelection_Channel2: AWD affected to Channel 2
+ * @arg ADC_AnalogWatchdogSelection_Channel3: AWD affected to Channel 3
+ * @arg ADC_AnalogWatchdogSelection_Channel4: AWD affected to Channel 4
+ * @arg ADC_AnalogWatchdogSelection_Channel5: AWD affected to Channel 5
+ * @arg ADC_AnalogWatchdogSelection_Channel6: AWD affected to Channel 6
+ * @arg ADC_AnalogWatchdogSelection_Channel7: AWD affected to Channel 7
+ * @arg ADC_AnalogWatchdogSelection_Channel8: AWD affected to Channel 8
+ * @arg ADC_AnalogWatchdogSelection_Channel9: AWD affected to Channel 9
+ * @arg ADC_AnalogWatchdogSelection_Channel10: AWD affected to Channel 10
+ * @arg ADC_AnalogWatchdogSelection_Channel11: AWD affected to Channel 11
+ * @arg ADC_AnalogWatchdogSelection_Channel12: AWD affected to Channel 12
+ * @arg ADC_AnalogWatchdogSelection_Channel13: AWD affected to Channel 13
+ * @arg ADC_AnalogWatchdogSelection_Channel14: AWD affected to Channel 14
+ * @arg ADC_AnalogWatchdogSelection_Channel15: AWD affected to Channel 15
+ * @arg ADC_AnalogWatchdogSelection_Channel16: AWD affected to Channel 16
+ * @arg ADC_AnalogWatchdogSelection_Channel17: AWD affected to Channel 17
+ * @arg ADC_AnalogWatchdogSelection_Channel18: AWD affected to Channel 18
+ * @arg ADC_AnalogWatchdogSelection_Channel19: AWD affected to Channel 19
+ * @arg ADC_AnalogWatchdogSelection_Channel20: AWD affected to Channel 20
+ * @arg ADC_AnalogWatchdogSelection_Channel21: AWD affected to Channel 21
+ * @arg ADC_AnalogWatchdogSelection_Channel22: AWD affected to Channel 22
+ * @arg ADC_AnalogWatchdogSelection_Channel23: AWD affected to Channel 23
+ * @ref ADC_AnalogWatchdogSelection_TypeDef enumeration.
+ * @retval None
+ */
+void ADC_AnalogWatchdogChannelSelect(ADC_TypeDef* ADCx,
+ ADC_AnalogWatchdogSelection_TypeDef ADC_AnalogWatchdogSelection)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ANALOGWATCHDOG_SELECTION(ADC_AnalogWatchdogSelection));
+
+ /* Reset the CHSEL bits */
+ ADCx->CR3 &= ((uint8_t)~ADC_CR3_CHSEL);
+
+ /* Select the channel to be checked by the Analog watchdog */
+ ADCx->CR3 |= (uint8_t)ADC_AnalogWatchdogSelection;
+}
+
+/**
+ * @brief Configures the high and low thresholds of the Analog watchdog.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param HighThreshold: Analog watchdog High threshold value.
+ * This parameter must be a 12bit value.
+ * @param LowThreshold: Analog watchdog Low threshold value.
+ * This parameter must be a 12bit value.
+ * @retval None
+ */
+void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_THRESHOLD(HighThreshold));
+ assert_param(IS_ADC_THRESHOLD(LowThreshold));
+
+ /* Set the ADC high threshold */
+ ADCx->HTRH = (uint8_t)(HighThreshold >> 8);
+ ADCx->HTRL = (uint8_t)(HighThreshold);
+
+ /* Set the ADC low threshold */
+ ADCx->LTRH = (uint8_t)(LowThreshold >> 8);
+ ADCx->LTRL = (uint8_t)(LowThreshold);
+}
+
+/**
+ * @brief Configures the Analog watchdog.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param ADC_AnalogWatchdogSelection : Specifies the channel to be checked
+ * by the Analog watchdog.
+ * This parameter can be one of the following values:
+ * @arg ADC_AnalogWatchdogSelection_Channel0: AWD affected to Channel 0
+ * @arg ADC_AnalogWatchdogSelection_Channel1: AWD affected to Channel 1
+ * @arg ADC_AnalogWatchdogSelection_Channel2: AWD affected to Channel 2
+ * @arg ADC_AnalogWatchdogSelection_Channel3: AWD affected to Channel 3
+ * @arg ADC_AnalogWatchdogSelection_Channel4: AWD affected to Channel 4
+ * @arg ADC_AnalogWatchdogSelection_Channel5: AWD affected to Channel 5
+ * @arg ADC_AnalogWatchdogSelection_Channel6: AWD affected to Channel 6
+ * @arg ADC_AnalogWatchdogSelection_Channel7: AWD affected to Channel 7
+ * @arg ADC_AnalogWatchdogSelection_Channel8: AWD affected to Channel 8
+ * @arg ADC_AnalogWatchdogSelection_Channel9: AWD affected to Channel 9
+ * @arg ADC_AnalogWatchdogSelection_Channel10: AWD affected to Channel 10
+ * @arg ADC_AnalogWatchdogSelection_Channel11: AWD affected to Channel 11
+ * @arg ADC_AnalogWatchdogSelection_Channel12: AWD affected to Channel 12
+ * @arg ADC_AnalogWatchdogSelection_Channel13: AWD affected to Channel 13
+ * @arg ADC_AnalogWatchdogSelection_Channel14: AWD affected to Channel 14
+ * @arg ADC_AnalogWatchdogSelection_Channel15: AWD affected to Channel 15
+ * @arg ADC_AnalogWatchdogSelection_Channel16: AWD affected to Channel 16
+ * @arg ADC_AnalogWatchdogSelection_Channel17: AWD affected to Channel 17
+ * @arg ADC_AnalogWatchdogSelection_Channel18: AWD affected to Channel 18
+ * @arg ADC_AnalogWatchdogSelection_Channel19: AWD affected to Channel 19
+ * @arg ADC_AnalogWatchdogSelection_Channel20: AWD affected to Channel 20
+ * @arg ADC_AnalogWatchdogSelection_Channel21: AWD affected to Channel 21
+ * @arg ADC_AnalogWatchdogSelection_Channel22: AWD affected to Channel 22
+ * @arg ADC_AnalogWatchdogSelection_Channel23: AWD affected to Channel 23
+ * @param HighThreshold: Analog watchdog High threshold value.
+ * This parameter must be a 12bit value.
+ * @param LowThreshold: Analog watchdog Low threshold value.
+ * This parameter must be a 12bit value.
+ * @retval None
+ */
+void ADC_AnalogWatchdogConfig(ADC_TypeDef* ADCx,
+ ADC_AnalogWatchdogSelection_TypeDef ADC_AnalogWatchdogSelection,
+ uint16_t HighThreshold,
+ uint16_t LowThreshold)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_ANALOGWATCHDOG_SELECTION(ADC_AnalogWatchdogSelection));
+ assert_param(IS_ADC_THRESHOLD(HighThreshold));
+ assert_param(IS_ADC_THRESHOLD(LowThreshold));
+
+ /*Reset the CHSEL bits */
+ ADCx->CR3 &= ((uint8_t)~ADC_CR3_CHSEL);
+
+ /* Select the channel to be checked by the Analog watchdog.*/
+ ADCx->CR3 |= (uint8_t)ADC_AnalogWatchdogSelection;
+
+ /* Set the ADC high threshold */
+ ADCx->HTRH = (uint8_t)(HighThreshold >> 8);
+ ADCx->HTRL = (uint8_t)(HighThreshold);
+
+ /* Set the ADC low threshold */
+ ADCx->LTRH = (uint8_t)(LowThreshold >> 8);
+ ADCx->LTRL = (uint8_t)LowThreshold;
+}
+
+ /**
+ * @}
+ */
+
+/** @defgroup ADC_Group3 Temperature Sensor & Vrefint (Voltage Reference
+ * internal) management functions
+ * @brief Temperature Sensor & Vrefint (Voltage Reference internal)
+ * management functions
+ *
+@verbatim
+ ===============================================================================
+ Temperature Sensor & Vrefint (Voltage Reference internal) management functions
+ ===============================================================================
+
+ This section provides functions allowing to enable/ disable the internal
+ connections between the ADC and the Temperature Sensor and the Vrefint source.
+
+ A typical configuration to get the Temperature sensor or/and Vrefint channels
+ voltages is done following these steps :
+ 1. Enable the internal connection of Temperature sensor or/and Vrefint sources
+ with the ADC channels:
+ - for the Temperature sensor using ADC_TempSensorCmd() function.
+ - for the Internal Voltage reference using ADC_VrefintCmd() function.
+ 2. Enable the ADC_Channel_TempSensor and/or ADC_Channel_Vrefint channels
+ using ADC_ChannelCmd()function.
+ 3. Get the voltage values, using ADC_GetConversionValue().
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the Temperature sensor internal reference.
+ * @param NewState : new state of the Temperature sensor internal reference.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_TempSensorCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /*Enable the Temperature sensor internal reference.*/
+ ADC1->TRIGR[0] |= (uint8_t)(ADC_TRIGR1_TSON);
+ }
+ else
+ {
+ /*Disable the Temperature sensor internal reference.*/
+ ADC1->TRIGR[0] &= (uint8_t)(~ADC_TRIGR1_TSON);
+ }
+}
+
+/**
+ * @brief Enables or disables the Internal Voltage reference.
+ * @param NewState : new state of the Internal Voltage reference.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_VrefintCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the Internal Voltage reference.*/
+ ADC1->TRIGR[0] |= (uint8_t)(ADC_TRIGR1_VREFINTON);
+ }
+ else
+ {
+ /* Disable the Internal Voltage reference.*/
+ ADC1->TRIGR[0] &= (uint8_t)(~ADC_TRIGR1_VREFINTON);
+ }
+}
+
+ /**
+ * @}
+ */
+/** @defgroup ADC_Group4 Channels Configuration functions
+ * @brief Channels Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Channels Configuration functions
+ ===============================================================================
+ This section provides functions allowing to:
+ - Enable or disable the ADC channel using ADC_ChannelCmd() function,
+ - Configure the channels sampling times using ADC_SamplingTimeConfig()
+ function.
+ Note: there are 2 sampling times configuration values :
+ - 1st Group value : for channels 0..23
+ - 2nd Group value : for channels 24..27 (depending on the MCU
+ package density) and Temperature Sensor and Vrefint channels.
+ - Configure the channels Schmitt Trigger for each channel using
+ ADC_SchmittTriggerConfig() function.
+ - Get the current ADC conversion value.
+
+ @endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the selected ADC channel(s).
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param ADC_Channels: specifies the ADC channels to be initialized
+ * This parameter can be one of the following values:
+ * @arg ADC_Channel_0: Channel 0
+ * @arg ADC_Channel_1: Channel 1
+ * @arg ADC_Channel_2: Channel 2
+ * @arg ADC_Channel_3: Channel 3
+ * @arg ADC_Channel_4: Channel 4
+ * @arg ADC_Channel_5: Channel 5
+ * @arg ADC_Channel_6: Channel 6
+ * @arg ADC_Channel_7: Channel 7
+ * @arg ADC_Channel_8: Channel 8
+ * @arg ADC_Channel_9: Channel 9
+ * @arg ADC_Channel_10: Channel 10
+ * @arg ADC_Channel_11: Channel 11
+ * @arg ADC_Channel_12: Channel 12
+ * @arg ADC_Channel_13: Channel 13
+ * @arg ADC_Channel_14: Channel 14
+ * @arg ADC_Channel_15: Channel 15
+ * @arg ADC_Channel_16: Channel 16
+ * @arg ADC_Channel_17: Channel 17
+ * @arg ADC_Channel_18: Channel 18
+ * @arg ADC_Channel_19: Channel 19
+ * @arg ADC_Channel_20: Channel 20
+ * @arg ADC_Channel_21: Channel 21
+ * @arg ADC_Channel_22: Channel 22
+ * @arg ADC_Channel_23: Channel 23
+ * @arg ADC_Channel_24: Channel 24
+ * @arg ADC_Channel_25: Channel 25
+ * @arg ADC_Channel_26: Channel 26
+ * @arg ADC_Channel_27: Channel 27
+ * @arg ADC_Channel_Vrefint: Vrefint Channel
+ * @arg ADC_Channel_TempSensor: Temperature sensor Channel
+ * @arg ADC_Channel_00To07: select from channel00 to channel07
+ * @arg ADC_Channel_08To15: select from channel08 to channel15
+ * @arg ADC_Channel_16To23: select from channel16 to channel23
+ * @arg ADC_Channel_24To27: select from channel24 to channel27
+ * @param NewState : new state of the specified ADC channel(s).
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_ChannelCmd(ADC_TypeDef* ADCx, ADC_Channel_TypeDef ADC_Channels, FunctionalState NewState)
+{
+ uint8_t regindex = 0;
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ regindex = (uint8_t)((uint16_t)ADC_Channels >> 8);
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected ADC channel(s). */
+ ADCx->SQR[regindex] |= (uint8_t)(ADC_Channels);
+ }
+ else
+ {
+ /* Disable the selected ADC channel(s). */
+ ADCx->SQR[regindex] &= (uint8_t)(~(uint8_t)(ADC_Channels));
+ }
+}
+
+/**
+ * @brief Configures the sampling time for the selected ADC channel group.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param ADC_GroupChannels : ADC channel group to configure.
+ * This parameter can be one of the following values:
+ * @arg ADC_Group_SlowChannels: Slow Channels group
+ * @arg ADC_Group_FastChannels: Fast Channels group
+ * @note The channels of 1st ADC Group can be channels 0..23
+ * @note The channels of 2nd ADC Group can be channels 24..27 (depending on the MCU
+ * package density) and Temperature Sensor and Vrefint channels.
+ * @param ADC_SamplingTime : Specifies the sample time value
+ * This parameter can be one of the following values:
+ * @arg ADC_SamplingTime_4Cycles: Sampling Time Cycles is 4
+ * @arg ADC_SamplingTime_9Cycles: Sampling Time Cycles is 9
+ * @arg ADC_SamplingTime_16Cycles: Sampling Time Cycles is 16
+ * @arg ADC_SamplingTime_24Cycles: Sampling Time Cycles is 24
+ * @arg ADC_SamplingTime_48Cycles: Sampling Time Cycles is 48
+ * @arg ADC_SamplingTime_96Cycles: Sampling Time Cycles is 96
+ * @arg ADC_SamplingTime_192Cycles: Sampling Time Cycles is 192
+ * @arg ADC_SamplingTime_384Cycles: Sampling Time Cycles is 384
+ * @retval None
+ */
+void ADC_SamplingTimeConfig(ADC_TypeDef* ADCx,
+ ADC_Group_TypeDef ADC_GroupChannels,
+ ADC_SamplingTime_TypeDef ADC_SamplingTime)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_GROUP(ADC_GroupChannels));
+ assert_param(IS_ADC_SAMPLING_TIME_CYCLES(ADC_SamplingTime));
+
+ if ( ADC_GroupChannels != ADC_Group_SlowChannels)
+ {
+ /* Configures the sampling time for the Fast ADC channel group. */
+ ADCx->CR3 &= (uint8_t)~ADC_CR3_SMPT2;
+ ADCx->CR3 |= (uint8_t)(ADC_SamplingTime << 5);
+ }
+ else
+ {
+ /* Configures the sampling time for the Slow ADC channel group. */
+ ADCx->CR2 &= (uint8_t)~ADC_CR2_SMPT1;
+ ADCx->CR2 |= (uint8_t)ADC_SamplingTime;
+ }
+}
+
+/**
+ * @brief Configures the status of the Schmitt Trigger for the selected ADC
+ * channel(s).
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param ADC_Channels: specifies the ADC channels to be initialized,
+ * This parameter can be one of the following values:
+ * @arg ADC_Channel_0: Channel 0
+ * @arg ADC_Channel_1: Channel 1
+ * @arg ADC_Channel_2: Channel 2
+ * @arg ADC_Channel_3: Channel 3
+ * @arg ADC_Channel_4: Channel 4
+ * @arg ADC_Channel_5: Channel 5
+ * @arg ADC_Channel_6: Channel 6
+ * @arg ADC_Channel_7: Channel 7
+ * @arg ADC_Channel_8: Channel 8
+ * @arg ADC_Channel_9: Channel 9
+ * @arg ADC_Channel_10: Channel 10
+ * @arg ADC_Channel_11: Channel 11
+ * @arg ADC_Channel_12: Channel 12
+ * @arg ADC_Channel_13: Channel 13
+ * @arg ADC_Channel_14: Channel 14
+ * @arg ADC_Channel_15: Channel 15
+ * @arg ADC_Channel_16: Channel 16
+ * @arg ADC_Channel_17: Channel 17
+ * @arg ADC_Channel_18: Channel 18
+ * @arg ADC_Channel_19: Channel 19
+ * @arg ADC_Channel_20: Channel 20
+ * @arg ADC_Channel_21: Channel 21
+ * @arg ADC_Channel_22: Channel 22
+ * @arg ADC_Channel_23: Channel 23
+ * @arg ADC_Channel_24: Channel 24
+ * @arg ADC_Channel_25: Channel 25
+ * @arg ADC_Channel_26: Channel 26
+ * @arg ADC_Channel_27: Channel 27
+ * @arg ADC_Channel_Vrefint: Vrefint Channel
+ * @arg ADC_Channel_TempSensor: Temperature sensor Channel
+ * @arg ADC_Channel_00To07: select from channel00 to channel07
+ * @arg ADC_Channel_08To15: select from channel08 to channel15
+ * @arg ADC_Channel_16To23: select from channel16 to channel23
+ * @arg ADC_Channel_24To27: select from channel24 to channel27
+ * @param NewState : new state of the Schmitt Trigger
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_SchmittTriggerConfig(ADC_TypeDef* ADCx, ADC_Channel_TypeDef ADC_Channels,
+ FunctionalState NewState)
+{
+ uint8_t regindex = 0;
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ regindex = (uint8_t)((uint16_t)ADC_Channels >> 8);
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the Schmitt Trigger for the selected ADC channel(s).*/
+ ADCx->TRIGR[regindex] &= (uint8_t)(~(uint8_t)ADC_Channels);
+ }
+ else
+ {
+ /* Disable the Schmitt Trigger for the selected ADC channel(s).*/
+ ADCx->TRIGR[regindex] |= (uint8_t)(ADC_Channels);
+ }
+}
+
+/**
+ * @brief Returns the last ADC converted data.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @retval The Data conversion value.
+ */
+uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx)
+{
+ uint16_t tmpreg = 0;
+
+ /* Get last ADC converted data.*/
+ tmpreg = (uint16_t)(ADCx->DRH);
+ tmpreg = (uint16_t)((uint16_t)((uint16_t)tmpreg << 8) | ADCx->DRL);
+
+ /* Return the selected ADC conversion value */
+ return (uint16_t)(tmpreg) ;
+}
+
+ /**
+ * @}
+ */
+
+/** @defgroup ADC_Group5 ADC Channels DMA Configuration function
+ * @brief ADC Channels DMA Configuration function
+ *
+@verbatim
+ ===============================================================================
+ ADC Channels DMA Configuration function
+ ===============================================================================
+
+ This section provides a function allowing to configure the DMA for ADC
+ channel.
+ Since converted channel values are stored into a unique data register,
+ it is useful to use DMA for conversion of more than one channel. This
+ avoids the loss of the data already stored in the ADC Data register.
+
+ When the DMA mode is enabled (using the ADC_DMACmd() function), after each
+ conversion of a channel, a DMA request is generated.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Enables or disables the specified ADC DMA request.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param NewState : new state of the specified ADC DMA transfer.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the specified ADC DMA request */
+ ADCx->SQR[0] &= (uint8_t)~ADC_SQR1_DMAOFF;
+ }
+ else
+ {
+ /* Disable the specified ADC DMA request */
+ ADCx->SQR[0] |= ADC_SQR1_DMAOFF;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup ADC_Group6 Interrupts and flags management functions
+ * @brief Interrupts and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts and flags management functions
+ ===============================================================================
+
+ This section provides functions allowing to configure the ADC Interrupts and
+ get the status and clear flags and Interrupts pending bits.
+
+ The ADC provides 3 Interrupt sources and 3 Flags:
+
+ Flags :
+ ----------
+ 1. ADC_FLAG_OVR : Overrun detection when ADC channel converted data is lost
+
+ 2. ADC_FLAG_EOC : End of conversion - to indicate the end of a regular
+ CHANNEL conversion or a GROUP conversions, depending of the
+ ADC Continuous Conversion Mode (Continuous or Single
+ conversion) and of the DMA usage.
+ Note : if DMA is used, EOC occurs at the end of the sequence
+ conversion, else it occurs after each conversion
+ 3. ADC_FLAG_AWD: to indicate if the converted voltage crosses the
+ programmed Analog watchdog thresholds values.
+
+
+ Interrupts :
+ ------------
+ 1. ADC_IT_OVR : specifies the interrupt source for the Overrun detection event.
+ 2. ADC_IT_EOC : specifies the interrupt source for the End of conversion event.
+ 3. ADC_IT_AWD : specifies the interrupt source for the Analog watchdog event.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the specified ADC interrupts.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param ADC_IT : specifies the ADC interrupt sources to be enabled or
+ * disabled.
+ * This parameter can be one of the following values:
+ * @arg ADC_IT_EOC: End of Conversion Interrupt
+ * @arg ADC_IT_AWD: Analog Watchdog Interrupt
+ * @arg ADC_IT_OVER: Over Run Interrupt
+ * @param NewState : new state of the specified ADC interrupts.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ADC_ITConfig(ADC_TypeDef* ADCx, ADC_IT_TypeDef ADC_IT, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ assert_param(IS_ADC_IT(ADC_IT));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected ADC interrupts */
+ ADCx->CR1 |= (uint8_t) ADC_IT;
+ }
+ else
+ {
+ /* Disable the selected ADC interrupts */
+ ADCx->CR1 &= (uint8_t)(~ADC_IT);
+ }
+}
+
+/**
+ * @brief Checks whether the specified ADC flag is set or not.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param ADC_FLAG: specifies the flag to check.
+ * This parameter can be one of the following values:
+ * @arg ADC_FLAG_EOC: End of Conversion flag
+ * @arg ADC_FLAG_AWD: Analog Watchdog flag
+ * @arg ADC_FLAG_OVER: Over Run flag
+ * @retval The new state of ADC_FLAG (SET or RESET).
+ */
+FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, ADC_FLAG_TypeDef ADC_FLAG)
+{
+ FlagStatus flagstatus = RESET;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_GET_FLAG(ADC_FLAG));
+
+ /* Check the status of the specified ADC flag */
+ if ((ADCx->SR & ADC_FLAG) != (uint8_t)RESET)
+ {
+ /* ADC_FLAG is set */
+ flagstatus = SET;
+ }
+ else
+ {
+ /* ADC_FLAG is reset */
+ flagstatus = RESET;
+ }
+
+ /* Return the ADC_FLAG status */
+ return flagstatus;
+}
+
+/**
+ * @brief Clears the ADC's pending flags.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param ADC_FLAG: specifies the flag to clear.
+ * This parameter can be one of the following values:
+ * @arg ADC_FLAG_EOC: End of Conversion flag
+ * @arg ADC_FLAG_AWD: Analog Watchdog flag
+ * @arg ADC_FLAG_OVER: Over Run flag
+ * @retval None
+ */
+void ADC_ClearFlag(ADC_TypeDef* ADCx,
+ ADC_FLAG_TypeDef ADC_FLAG)
+{
+ /* Check the parameters */
+ assert_param(IS_ADC_CLEAR_FLAG(ADC_FLAG));
+
+ /* Clear the selected ADC flags */
+ ADCx->SR = (uint8_t)~ADC_FLAG;
+}
+
+/**
+ * @brief Checks whether the specified ADC interrupt has occurred or not.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param ADC_IT: specifies the ADC interrupt source to check.
+ * This parameter can be one of the following values:
+ * @arg ADC_IT_EOC: End of Conversion Interrupt
+ * @arg ADC_IT_AWD: Analog Watchdog Interrupt
+ * @arg ADC_IT_OVER: Over Run Interrupt
+ * @retval Status of ADC_IT (SET or RESET).
+ */
+ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx,
+ ADC_IT_TypeDef ADC_IT)
+{
+ ITStatus itstatus = RESET;
+ uint8_t itmask = 0, enablestatus = 0;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_GET_IT(ADC_IT));
+
+ /* Get the ADC IT index */
+ itmask = (uint8_t)(ADC_IT >> 3);
+ itmask = (uint8_t)((uint8_t)((uint8_t)(itmask & (uint8_t)0x10) >> 2) | \
+ (uint8_t)(itmask & (uint8_t)0x03));
+
+ /* Get the ADC_IT enable bit status */
+ enablestatus = (uint8_t)(ADCx->CR1 & (uint8_t)ADC_IT) ;
+
+ /* Check the status of the specified ADC interrupt */
+ if (((ADCx->SR & itmask) != (uint8_t)RESET) && enablestatus)
+ {
+ /* ADC_IT is set */
+ itstatus = SET;
+ }
+ else
+ {
+ /* ADC_IT is reset */
+ itstatus = RESET;
+ }
+
+ /* Return the ADC_IT status */
+ return itstatus;
+}
+
+/**
+ * @brief Clears the ADC’s interrupt pending bits.
+ * @param ADCx where x can be 1 to select the specified ADC peripheral.
+ * @param ADC_IT: specifies the ADC interrupt pending bit to clear.
+ * This parameter can be one of the following values:
+ * @arg ADC_IT_EOC: End of Conversion Interrupt
+ * @arg ADC_IT_AWD: Analog Watchdog Interrupt
+ * @arg ADC_IT_OVER: Over Run Interrupt
+ * @retval None
+ */
+void ADC_ClearITPendingBit(ADC_TypeDef* ADCx,
+ ADC_IT_TypeDef ADC_IT)
+{
+ uint8_t itmask = 0;
+
+ /* Check the parameters */
+ assert_param(IS_ADC_IT(ADC_IT));
+
+ /* Get the ADC IT index */
+ itmask = (uint8_t)(ADC_IT >> 3);
+ itmask = (uint8_t)((uint8_t)(((uint8_t)(itmask & (uint8_t)0x10)) >> 2) | \
+ (uint8_t)(itmask & (uint8_t)0x03));
+
+ /* Clear the selected ADC interrupt pending bits */
+ ADCx->SR = (uint8_t)~itmask;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_aes.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_aes.c
new file mode 100644
index 00000000..a5c4ed89
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_aes.c
@@ -0,0 +1,488 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_aes.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Advanced Encryption Standard (AES) peripheral:
+ * - Configuration
+ * - Read/Write operations
+ * - DMA transfers management
+ * - Interrupts and flags management
+ *
+ * @verbatim
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * 1- Enable AES clock to get write access to AES registers
+ * using CLK_PeripheralClockConfig(CLK_Peripheral_AES, ENABLE);
+ *
+ * 2- Configure the AES operation mode using AES_OperationModeConfig()
+ *
+ * 3- If required, enable interrupt source using AES_ITConfig()
+ *
+ * 4- If required, when using the DMA mode
+ * - Configure the DMA using DMA_Init()
+ * - Enable DMA requests using AES_DMAConfig()
+ *
+ * 5- Enable the AES peripheral using AES_Cmd()
+ *
+ * 6- Write data/key using AES_WriteSubData() / AES_WriteSubKey()
+ *
+ * @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_aes.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup AES
+ * @brief AES driver modules
+ * @{
+ */
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup AES_Private_Functions
+ * @{
+ */
+
+/** @defgroup AES_Group1 Configuration
+ * @brief Configuration
+ *
+@verbatim
+ ===============================================================================
+ Configuration
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the AES peripheral.
+ * @param None.
+ * @retval None
+ */
+void AES_DeInit(void)
+{
+ /* Set AES_CR to reset value 0x00, AES_SR is reset by setting ERRC and CCFC bits in CR */
+ AES->CR = AES_CR_ERRC | AES_CR_CCFC;
+ AES->DINR = AES_DINR_RESET_VALUE; /* Set AES_DINR to reset value 0x00 */
+ AES->DOUTR = AES_DOUTR_RESET_VALUE; /* Set AES_DOUTR to reset value 0x00 */
+}
+
+/**
+ * @brief Configures the AES operation mode.
+ * @param AES_Operation : the selected AES operation mode.
+ * This parameter can be one of the following values:
+ * @arg AES_Operation_Encryp: AES in Encryption mode
+ * @arg AES_Operation_KeyDeriv: AES in Key Derivation mode
+ * @arg AES_Operation_Decryp: AES in Decryption mode
+ * @arg AES_Operation_KeyDerivAndDecryp: AES in Key Derivation and Decryption mode
+ * @note The operation mode must be configured when AES peripheral is disabled.
+ * @retval None
+ */
+void AES_OperationModeConfig(AES_Operation_TypeDef AES_Operation)
+{
+ /* Check the parameter */
+ assert_param(IS_AES_MODE(AES_Operation));
+
+ /* Reset the operation mode bits in CR register */
+ AES->CR &= (uint8_t) (~AES_CR_MODE);
+
+ /* Set the new operation mode bits in CR register */
+ AES->CR |= (uint8_t) (AES_Operation);
+}
+
+/**
+ * @brief Enable the AES peripheral.
+ * @param NewState : The new state of the AES peripheral.
+ * This parameter can be: ENABLE or DISABLE.
+ * @note AES peripheral can be enabled once operation mode is configured using
+ * AES_OperationModeConfig()
+ * @retval None
+ */
+void AES_Cmd(FunctionalState NewState)
+{
+ /* Check the parameter */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ AES->CR |= (uint8_t) AES_CR_EN; /**< AES Enable */
+ }
+ else
+ {
+ AES->CR &= (uint8_t)(~AES_CR_EN); /**< AES Disable */
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup AES_Group2 AES Read and Write
+ * @brief AES Read and Write
+ *
+@verbatim
+ ===============================================================================
+ AES Read and Write operations
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Write data in DINR register to be processed by AES peripheral.
+ * @param Data: The data to be processed.
+ * @note When an unexpected write to DINR register is detected, WRERR flag is
+ * set.
+ * @retval None
+ */
+void AES_WriteSubData(uint8_t Data)
+{
+ /* Write Data */
+ AES->DINR = Data;
+}
+
+/**
+ * @brief Write key in DINR register.
+ * @param Key: The key to be used for encryption/decryption.
+ * @note When an unexpected write to DINR register is detected, WRERR flag is
+ * set.
+ * @retval None
+ */
+void AES_WriteSubKey(uint8_t Key)
+{
+ /* Write key */
+ AES->DINR = Key;
+}
+
+/**
+ * @brief Returns the data in DOUTR register processed by AES peripheral.
+ * @note When an unexpected read of DOUTR register is detected, RDERR flag is
+ * set
+ * @retval The processed data.
+ */
+uint8_t AES_ReadSubData(void)
+{
+ return AES->DOUTR;
+}
+
+/**
+ * @brief Returns the DOUTR register content.
+ * @retval The derivation key.
+ * @note When an unexpected read of DOUTR register is detected, RDERR flag is
+ * set.
+ */
+uint8_t AES_ReadSubKey(void)
+{
+ return AES->DOUTR;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup AES_Group3 DMA transfers management functions
+ * @brief DMA transfers management function
+ *
+@verbatim
+ ===============================================================================
+ DMA transfers management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures the AES DMA interface.
+ * @param AES_DMATransfer: Specifies the AES DMA transfer.
+ * This parameter can be one of the following values:
+ * @arg AES_DMATransfer_InOut: DMA requests enabled for input/Output transfer phase
+ * @param NewState Indicates the new state of the AES DMA interface.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ * @note CCF bit has no meaning when DMA requests are enabled (DMAEN = 1).
+ */
+void AES_DMAConfig(AES_DMATransfer_TypeDef AES_DMATransfer, FunctionalState NewState)
+{
+ /* Check the parameter */
+ assert_param(IS_AES_DMATRANSFER(AES_DMATransfer));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the DMA transfer */
+ AES->CR |= (uint8_t) AES_DMATransfer;
+ }
+ else
+ {
+ /* Disable the DMA transfer */
+ AES->CR &= (uint8_t)(~AES_DMATransfer);
+ }
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup AES_Group4 Interrupts and flags management functions
+ * @brief Interrupts and flags management functions
+ *
+@verbatim
+
+ ===============================================================================
+ Interrupts and flags management functions
+ ===============================================================================
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the specified AES interrupt.
+ * @param AES_IT: Specifies the AES interrupt source to enable/disable.
+ * This parameter can be one of the following values:
+ * @arg AES_IT_CCIE: Computation Complete interrupt enable
+ * @arg AES_IT_ERRIE: Error interrupt enable
+ * @param NewState : The new state of the AES peripheral.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void AES_ITConfig(AES_IT_TypeDef AES_IT, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ assert_param(IS_AES_IT(AES_IT));
+
+ if (NewState != DISABLE)
+ {
+ AES->CR |= (uint8_t) AES_IT; /**< AES_IT Enable */
+ }
+ else
+ {
+ AES->CR &= (uint8_t)(~AES_IT); /**< AES_IT Disable */
+ }
+}
+
+/**
+ * @brief Checks whether the specified AES flag is set or not.
+ * @param AES_FLAG specifies the flag to check.
+ * This parameter can be one of the following values:
+ * @arg AES_FLAG_CCF: Computation Complete Flag
+ * @arg AES_FLAG_RDERR: Read Error Flag
+ * @arg AES_FLAG_WRERR: Write Error Flag
+ * @retval FlagStatus (SET or RESET)
+ * @note CCF bit has a meaning only when DMA requests are disabled (DMAEN bit = 0).
+ */
+FlagStatus AES_GetFlagStatus(AES_FLAG_TypeDef AES_FLAG)
+{
+ FlagStatus status = RESET;
+
+ /* Check parameters */
+ assert_param(IS_AES_FLAG(AES_FLAG));
+
+ if (AES_FLAG == AES_FLAG_CCF)
+ {
+ if ((AES->SR & (uint8_t)AES_FLAG_CCF) != (uint8_t)0x00)
+ {
+ /* Computation Complete Flag CCF is set */
+ status = (FlagStatus) SET;
+ }
+ else
+ {
+ /* Computation Complete Flag CCF is reset */
+ status = (FlagStatus) RESET;
+ }
+ }
+ else if (AES_FLAG == AES_FLAG_RDERR)
+ {
+ if ((AES->SR & (uint8_t)AES_FLAG_RDERR) != (uint8_t)0x00)
+ {
+ /* Read Error Flag RDERR is set */
+ status = (FlagStatus) SET;
+ }
+ else
+ {
+ /* Read Error Flag RDERR is reset */
+ status = (FlagStatus) RESET;
+ }
+ }
+ else
+ {
+ if ((AES->SR & (uint8_t)AES_FLAG_WRERR) != (uint8_t)0x00)
+ {
+ /* Write Error Flag WRERR is set */
+ status = (FlagStatus) SET;
+ }
+ else
+ {
+ /* Write Error Flag WRERR is reset */
+ status = (FlagStatus) RESET;
+ }
+ }
+ /* Return the AES_FLAG status */
+ return ((FlagStatus) status);
+}
+
+/**
+ * @brief Clears the AES flags.
+ * @param AES_FLAG: specifies the flag to clear.
+ * This parameter can be one of the following values:
+ * @arg AES_FLAG_CCF: Computation Complete Flag
+ * @arg AES_FLAG_RDERR: Read Error Flag
+ * @arg AES_FLAG_WRERR: Write Error Flag
+ * @retval None
+ */
+void AES_ClearFlag(AES_FLAG_TypeDef AES_FLAG)
+{
+ /* Check the parameters */
+ assert_param(IS_AES_FLAG(AES_FLAG));
+
+ /* Check if AES_FLAG is AES_FLAG_CCF */
+ if (AES_FLAG == AES_FLAG_CCF)
+ {
+ /* Clear CCF flag by setting CCFC bit */
+ AES->CR |= (uint8_t) AES_CR_CCFC;
+ }
+ else /* AES_FLAG is AES_FLAG_RDERR or AES_FLAG_WRERR */
+ {
+ /* Clear RDERR and WRERR flags by setting ERRC bit */
+ AES->CR |= (uint8_t) AES_CR_ERRC;
+ }
+}
+
+/**
+ * @brief Checks whether the specified AES interrupt has occurred or not.
+ * @param AES_IT: Specifies the AES interrupt pending bit to check.
+ * This parameter can be one of the following values:
+ * @arg AES_IT_CCIE: Computation Complete interrupt enable
+ * @arg AES_IT_ERRIE: Error interrupt enable
+ * @retval ITStatus The new state of AES_IT (SET or RESET).
+ */
+ITStatus AES_GetITStatus(AES_IT_TypeDef AES_IT)
+{
+ ITStatus itstatus = RESET;
+ BitStatus cciebitstatus, ccfbitstatus = RESET;
+
+ /* Check parameters */
+ assert_param(IS_AES_IT(AES_IT));
+
+ cciebitstatus = (BitStatus) (AES->CR & AES_CR_CCIE);
+ ccfbitstatus = (BitStatus) (AES->SR & AES_SR_CCF);
+
+ /* Check if AES_IT is AES_IT_CCIE */
+ if (AES_IT == AES_IT_CCIE)
+ {
+ /* Check the status of the specified AES interrupt */
+ if (((cciebitstatus) != RESET) && ((ccfbitstatus) != RESET))
+ {
+ /* Interrupt occurred */
+ itstatus = (ITStatus) SET;
+ }
+ else
+ {
+ /* Interrupt not occurred */
+ itstatus = (ITStatus) RESET;
+ }
+ }
+ else /* AES_IT is AES_IT_ERRIE */
+ {
+ /* Check the status of the specified AES interrupt */
+ if ((AES->CR & AES_CR_ERRIE) != RESET)
+ {
+ /* Check if WRERR or RDERR flags are set */
+ if ((AES->SR & (uint8_t)(AES_SR_WRERR | AES_SR_RDERR)) != RESET)
+ {
+ /* Interrupt occurred */
+ itstatus = (ITStatus) SET;
+ }
+ else
+ {
+ /* Interrupt not occurred */
+ itstatus = (ITStatus) RESET;
+ }
+ }
+ else
+ {
+ /* Interrupt not occurred */
+ itstatus = (ITStatus) RESET;
+ }
+ }
+
+ /* Return the AES_IT status */
+ return ((ITStatus)itstatus);
+}
+
+/**
+ * @brief Clears the AES's interrupt pending bits.
+ * @param AES_IT: specifies the interrupt pending bit to clear.
+ * This parameter can be one of the following values:
+ * @arg AES_IT_CCIE: Computation Complete interrupt enable
+ * @arg AES_IT_ERRIE: Error interrupt enable
+ * @retval None
+ */
+void AES_ClearITPendingBit(AES_IT_TypeDef AES_IT)
+{
+ /* Check the parameters */
+ assert_param(IS_AES_IT(AES_IT));
+
+ /* Check if AES_IT is AES_IT_CCIE */
+ if (AES_IT == AES_IT_CCIE)
+ {
+ /* Clear CCF flag by setting CCFC bit */
+ AES->CR |= (uint8_t) AES_CR_CCFC;
+ }
+ else /* AES_IT is AES_IT_ERRIE */
+ {
+ /* Clear RDERR and WRERR flags by setting ERRC bit */
+ AES->CR |= (uint8_t) AES_CR_ERRC;
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_beep.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_beep.c
new file mode 100644
index 00000000..dde50619
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_beep.c
@@ -0,0 +1,247 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_beep.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the BEEPER (BEEP) peripheral:
+ * - Initialization and Configuration
+ * - Low Speed Internal Clock(LSI) Calibration
+ *
+ * @verbatim
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * 1- Make sure that the LS RC clock calibration is performed by the following
+ * steps:
+ * - Connect internally the LS clock source to TIM2 channel 1 input
+ * capture for measurement using BEEP_LSClockToTIMConnectCmd() function
+ * - Update the BEEP_CSR register by the measured LSI frequency
+ * --> During this phase the BEEPER must be disabled to avoid
+ * unwanted interrupts
+ *
+ * 2- Configure the output beeper frequency using the BEEP_Init() function
+ *
+ * 3- Enable the beeper using the BEEP_Cmd() function
+ *
+ * @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_beep.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+/** @defgroup BEEP
+ * @brief BEEP driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup BEEP_Private_Functions
+ * @{
+ */
+
+/** @defgroup BEEP_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Initialization and Configuration functions
+ ===============================================================================
+ This section provides functions allowing to:
+ - Initialize and configure the Beeper frequency
+ - Enable and Disable the Beeper output
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the BEEP peripheral registers to their default
+ * reset values.
+ * @param None
+ * @retval None
+ */
+void BEEP_DeInit(void)
+{
+ BEEP->CSR1 = BEEP_CSR1_RESET_VALUE;
+ BEEP->CSR2 = BEEP_CSR2_RESET_VALUE;
+}
+
+/**
+ * @brief Initializes the BEEP function according to the specified parameters.
+ * @note The LS RC calibration must be performed before calling this function.
+ * @param BEEP_Frequency Frequency selection.
+ * This parameter can be one of the values of @ref BEEP_Frequency_TypeDef.
+ * @retval None
+ */
+void BEEP_Init(BEEP_Frequency_TypeDef BEEP_Frequency)
+{
+
+ /* Check parameter */
+ assert_param(IS_BEEP_FREQUENCY(BEEP_Frequency));
+
+ /* Set a default calibration value if no calibration is done */
+ if ((BEEP->CSR2 & BEEP_CSR2_BEEPDIV) == BEEP_CSR2_BEEPDIV)
+ {
+ BEEP->CSR2 &= (uint8_t)(~BEEP_CSR2_BEEPDIV); /* Clear bits */
+ BEEP->CSR2 |= BEEP_CALIBRATION_DEFAULT;
+ }
+
+ /* Select the output frequency */
+ BEEP->CSR2 &= (uint8_t)(~BEEP_CSR2_BEEPSEL);
+ BEEP->CSR2 |= (uint8_t)(BEEP_Frequency);
+
+}
+
+/**
+ * @brief Enable or disable the BEEP function.
+ * @note Initialisation of BEEP and LS RC calibration must be done before.
+ * @param NewState Indicates the new state of the BEEP function.
+ * @retval None
+ */
+void BEEP_Cmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the BEEP peripheral */
+ BEEP->CSR2 |= BEEP_CSR2_BEEPEN;
+ }
+ else
+ {
+ /* Disable the BEEP peripheral */
+ BEEP->CSR2 &= (uint8_t)(~BEEP_CSR2_BEEPEN);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup BEEP_Group2 Low Speed Internal Clock(LSI) Calibration functions
+ * @brief Low Speed Internal Clock(LSI) Calibration functions
+ *
+@verbatim
+ ===============================================================================
+ Low Speed Internal Clock(LSI) Calibration functions
+ ===============================================================================
+
+ This section provides functions allowing to measure and calibrate the internal
+ low speed clock source to ensure better BEEPER output frequency .
+
+ A typical configuration for LSI calibration is done following these steps :
+ 1. Disable the Beeper to avoid any unwanted interrupt using BEEP_Cmd() function
+ 2. Measure the LSI clock frequency by connecting it internally to TIM2 input capture
+ using BEEP_LSClockToTIMConnectCmd() function.
+ 3. Calibrate the beeper frequency with the measured LSI clock frequency using
+ BEEP_LSICalibrationConfig() function.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable or disable the LS clock source connection to TIM for measurement.
+ * @param NewState Indicates the new state of the LS clock to TIM connection
+ * @retval None
+ */
+void BEEP_LSClockToTIMConnectCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Connect LS clock to TIM for measurement */
+ BEEP->CSR1 |= BEEP_CSR1_MSR;
+ }
+ else
+ {
+ /* Disconnect LS clock to TIM */
+ BEEP->CSR1 &= (uint8_t)(~BEEP_CSR1_MSR);
+ }
+}
+/**
+ * @brief Update CSR register with the measured LSI frequency.
+ * @note BEEP must be disabled to avoid unwanted interrupts.
+ * @note Prescaler calculation:
+ * A is the integer part of LSIFreqkHz/4 and x the decimal part.
+ * x <= A/(1+2A) is equivalent to A >= x(1+2A)
+ * and also to 4A >= 4x(1+2A) [F1]
+ * but we know that A + x = LSIFreqkHz/4 ==> 4x = LSIFreqkHz-4A
+ * so [F1] can be written :
+ * 4A >= (LSIFreqkHz-4A)(1+2A)
+ * @param LSIFreqHz Low Speed RC frequency measured by timer (in Hz).
+ * @retval None
+ */
+void BEEP_LSICalibrationConfig(uint32_t LSIFreqHz)
+{
+ uint16_t lsifreqkhz;
+ uint16_t A;
+
+ /* Check parameter */
+ assert_param(IS_LSI_FREQUENCY(LSIFreqHz));
+
+ lsifreqkhz = (uint16_t)(LSIFreqHz / 1000); /* Converts value in kHz */
+
+ /* Calculation of BEEPER calibration value */
+
+ BEEP->CSR2 &= (uint8_t)(~BEEP_CSR2_BEEPDIV); /* Clear bits */
+
+ A = (uint16_t)(lsifreqkhz >> 3U); /* Division by 8, keep integer part only */
+
+ if ((8U * A) >= ((lsifreqkhz - (8U * A)) * (1U + (2U * A))))
+ {
+ BEEP->CSR2 |= (uint8_t)(A - 2U);
+ }
+ else
+ {
+ BEEP->CSR2 |= (uint8_t)(A - 1U);
+ }
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_clk.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_clk.c
new file mode 100644
index 00000000..1847de37
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_clk.c
@@ -0,0 +1,1123 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_clk.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the clock controller (CLK) peripheral:
+ * - Internal/external clocks, CSS and CCO configuration
+ * - System clocks configuration
+ * - Peripheral clocks configuration
+ * - CSS on LSE configuration
+ * - Low power clock configuration
+ * - Interrupts and flags management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * CLK specific features
+ * ===================================================================
+ *
+ * After reset the device is running from Internal High Speed oscillator
+ * divided by 8 (HSI/8 = 2MHz) with all peripherals off.
+ * - The clock for all peripherals is switched off, except for the BootROM
+ * clock used for bootloader, in which case, the software should be properly
+ * written to switch off that clock after the bootloader execution.
+ *
+ * Once the device starts from reset, the user application has to:
+ * - Configure the clock source to be used to drive the System clock
+ * (if the application needs higher frequency/performance)
+ * - Configure the System clock frequency
+ * - Enable the clock for the peripheral(s) to be used
+ * - Configure the clock source(s) for peripherals which clocks are not
+ * derived from the System clock (RTC/LCD, BEEP)
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "stm8l15x_clk.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup CLK
+ * @brief CLK driver modules
+ * @{
+ */
+/* Private typedef -----------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private Variables ---------------------------------------------------------*/
+/* Private Constant ---------------------------------------------------------*/
+CONST uint8_t SYSDivFactor[5] = {1, 2, 4, 8, 16}; /*!< Holds the different Master clock Divider factors */
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup CLK_Private_Functions
+ * @{
+ */
+
+/** @defgroup CLK_Group1 Internal and external clocks, CSS and CCO configuration functions
+ * @brief Internal and external clocks, CSS and CCO configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Internal/external clocks, CSS and CCO configuration functions
+ ===============================================================================
+
+ This section provides functions allowing to configure the internal/external clocks,
+ CSS and CCO pins.
+
+ 1. HSI (high-speed internal), 16 MHz factory-trimmed RC used directly as System
+ clock source.
+
+ 2. LSI (low-speed internal), 32 KHz low consumption RC used as IWDG and/or RTC
+ and/or BEEP clock source.
+
+ 3. HSE (high-speed external), 1 to 16 MHz crystal oscillator used directly as
+ System clock source. Can be used also as RTC/LCD clock source.
+
+ 4. LSE (low-speed external), 32 KHz oscillator used as RTC/LCD and/or BEEP clock source.
+
+ 5. CSS (Clock security system), once enabled and if a HSE clock failure occurs
+ (HSE used as System clock source), the System clock is automatically switched
+ to HSI and an interrupt is generated if enabled.
+
+ 6. CCO (configurable clock output), used to output HSI, LSE, HSE, HSI, LSI
+ clock (through a configurable prescaler) on PC4 pin.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the CLK peripheral registers to their default reset values.
+ * @param None
+ * @retval None
+ */
+void CLK_DeInit(void)
+{
+ CLK->ICKCR = CLK_ICKCR_RESET_VALUE;
+ CLK->ECKCR = CLK_ECKCR_RESET_VALUE;
+ CLK->CRTCR = CLK_CRTCR_RESET_VALUE;
+ CLK->CBEEPR = CLK_CBEEPR_RESET_VALUE;
+ CLK->SWR = CLK_SWR_RESET_VALUE;
+ CLK->SWCR = CLK_SWCR_RESET_VALUE;
+ CLK->CKDIVR = CLK_CKDIVR_RESET_VALUE;
+ CLK->PCKENR1 = CLK_PCKENR1_RESET_VALUE;
+ CLK->PCKENR2 = CLK_PCKENR2_RESET_VALUE;
+ CLK->PCKENR3 = CLK_PCKENR3_RESET_VALUE;
+ CLK->CSSR = CLK_CSSR_RESET_VALUE;
+ CLK->CCOR = CLK_CCOR_RESET_VALUE;
+ CLK->HSITRIMR = CLK_HSITRIMR_RESET_VALUE;
+ CLK->HSICALR = CLK_HSICALR_RESET_VALUE;
+ CLK->HSIUNLCKR = CLK_HSIUNLCKR_RESET_VALUE;
+ CLK->REGCSR = CLK_REGCSR_RESET_VALUE;
+}
+
+/**
+ * @brief Enables or disables the Internal High Speed oscillator (HSI).
+ * @note The HSI is stopped by hardware when entering Halt and active Halt modes.
+ * It is used (enabled by hardware) as system clock source after startup
+ * from Reset, wakeup from Halt and active Halt mode when the FHWU bit is
+ * set in the ICKCR register, or in case of HSE failure used as system clock
+ * (if the Clock Security System CSS is enabled).
+ * @note HSI can not be stopped if it is used as active CCO source, as active
+ * RTC clock, if the safe oscillator (AUX) is enabled or as system clock source,
+ * In this case, you have to select another source of the system clock
+ * then stop the HSI.
+ * @note After enabling the HSI, the application software should wait on HSIRDY
+ * flag to be set indicating that HSI clock is stable and can be used as
+ * system clock source.
+ * @param NewState: new state of the HSI.
+ * This parameter can be: ENABLE or DISABLE.
+ * @note When the HSI is stopped, HSIRDY flag goes low after 6 HSI oscillator
+ * clock cycles.
+ * @retval None
+ */
+void CLK_HSICmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Set HSION bit */
+ CLK->ICKCR |= CLK_ICKCR_HSION;
+ }
+ else
+ {
+ /* Reset HSION bit */
+ CLK->ICKCR &= (uint8_t)(~CLK_ICKCR_HSION);
+ }
+}
+
+/**
+ * @brief Adjusts the Internal High Speed oscillator (HSI) calibration value.
+ * @note The calibration is used to compensate for the variations in voltage
+ * and temperature that influence the frequency of the internal HSI RC.
+ * @param CLK_HSICalibrationValue : calibration trimming value.
+ * This parameter must be a number between [(HSICALR register value) -12]
+ * and [(HSICALR register value) + 8 ]
+ * @note Once HSITRIMR register configured, its value is used instead of the HSICALR
+ * register values.
+ * @retval None
+ */
+void CLK_AdjustHSICalibrationValue(uint8_t CLK_HSICalibrationValue)
+{
+ /* two consecutive write access to HSIUNLCKR register to unlock HSITRIMR */
+ CLK->HSIUNLCKR = 0xAC;
+ CLK->HSIUNLCKR = 0x35;
+
+ /* Store the new value */
+ CLK->HSITRIMR = (uint8_t)CLK_HSICalibrationValue;
+}
+
+/**
+ * @brief Enables or disables the Internal Low Speed oscillator (LSI).
+ * @note After enabling the LSI, the application software should wait on
+ * LSIRDY flag to be set indicating that LSI clock is stable and can
+ * be used to clock the IWDG and/or the RTC.
+ * @note LSI can not be disabled if used as system clock source, as active CCO
+ * source, as BEEP clock source while BEEPAHALT bit is set or, as RTC active
+ * clock source.
+ * @param NewState: new state of the LSI.
+ * This parameter can be: ENABLE or DISABLE.
+ * @note When the LSI is stopped, LSIRDY flag goes low after 6 LSI oscillator
+ * clock cycles.
+ * @retval None
+ */
+void CLK_LSICmd(FunctionalState NewState)
+{
+
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Set LSION bit */
+ CLK->ICKCR |= CLK_ICKCR_LSION;
+ }
+ else
+ {
+ /* Reset LSION bit */
+ CLK->ICKCR &= (uint8_t)(~CLK_ICKCR_LSION);
+ }
+}
+
+/**
+ * @brief Configures the External High Speed oscillator (HSE).
+ * @note After enabling the HSE (CLK_HSE_ON or CLK_HSE_Bypass), the application
+ * software should wait on HSERDY flag to be set indicating that HSE clock
+ * is stable and can be used to clock the system.
+ * @note HSE state can not be changed if it is used as system clock. In this case,
+ * you have to select another source of the system clock then change
+ * the HSE state (ex. disable it).
+ * @note The HSE is stopped by hardware when entering HALT and active HALT modes.
+ * @param CLK_HSE: specifies the new state of the HSE.
+ * This parameter can be one of the following values:
+ * @arg CLK_HSE_OFF: turn OFF the HSE oscillator, HSERDY flag goes low after
+ * 6 HSE oscillator clock cycles.
+ * @arg CLK_HSE_ON: turn ON the HSE oscillator
+ * @arg CLK_HSE_Bypass: HSE oscillator bypassed with external clock
+ * @note In case of Enabling HSE Bypass make sure that the HSE clock source is
+ * not used by the RTC, output or involved in a switching operation.
+ * @retval None
+ */
+void CLK_HSEConfig(CLK_HSE_TypeDef CLK_HSE)
+{
+ /* Check the parameters */
+ assert_param(IS_CLK_HSE(CLK_HSE));
+
+ /* Reset HSEON and HSEBYP bits before configuring the HSE ------------------*/
+ /* Reset HSEON bit */
+ CLK->ECKCR &= (uint8_t)~CLK_ECKCR_HSEON;
+
+ /* Reset HSEBYP bit */
+ CLK->ECKCR &= (uint8_t)~CLK_ECKCR_HSEBYP;
+
+ /* Configure HSE */
+ CLK->ECKCR |= (uint8_t)CLK_HSE;
+}
+
+/**
+ * @brief Configures the External Low Speed oscillator (LSE).
+ * @note After enabling the LSE (CLK_LSE_ON or CLK_LSE_Bypass), the application
+ * software should wait on LSERDY flag to be set indicating that LSE clock
+ * is stable and can be used to clock the RTC.
+ * @param CLK_LSE: specifies the new state of the LSE.
+ * This parameter can be one of the following values:
+ * @arg CLK_LSE_OFF: turn OFF the LSE oscillator, LSERDY flag goes low after
+ * 6 LSE oscillator clock cycles.
+ * @arg CLK_LSE_ON: turn ON the LSE oscillator
+ * @arg CLK_LSE_Bypass: LSE oscillator bypassed with external clock
+ * @note In case of Enabling LSE Bypass make sure that the LSE clock source is
+ * not used by the RTC, output or involved in a switching operation.
+ * @retval None
+ */
+void CLK_LSEConfig(CLK_LSE_TypeDef CLK_LSE)
+{
+ /* Check the parameters */
+ assert_param(IS_CLK_LSE(CLK_LSE));
+
+ /* Reset LSEON and LSEBYP bits before configuring the LSE ------------------*/
+ /* Reset LSEON bit */
+ CLK->ECKCR &= (uint8_t)~CLK_ECKCR_LSEON;
+
+ /* Reset LSEBYP bit */
+ CLK->ECKCR &= (uint8_t)~CLK_ECKCR_LSEBYP;
+
+ /* Configure LSE */
+ CLK->ECKCR |= (uint8_t)CLK_LSE;
+
+}
+
+/**
+ * @brief Enables the Clock Security System.
+ * @note If a failure is detected on the HSE oscillator clock, this oscillator
+ * is automatically disabled and an interrupt is generated to inform the
+ * software about the failure allowing the MCU to perform rescue operations.
+ * @note Once CSS is enabled it cannot be disabled until the next reset.
+ * @param None
+ * @retval None
+ */
+void CLK_ClockSecuritySystemEnable(void)
+{
+ /* Set CSSEN bit */
+ CLK->CSSR |= CLK_CSSR_CSSEN;
+}
+
+/**
+ * @brief Enables the Clock Security System deglitcher system.
+ * @param None
+ * @retval None
+ */
+void CLK_ClockSecuritySytemDeglitchCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Set CSSDGON bit */
+ CLK->CSSR |= CLK_CSSR_CSSDGON;
+ }
+ else
+ {
+ /* Reset CSSDGON bit */
+ CLK->CSSR &= (uint8_t)(~CLK_CSSR_CSSDGON);
+ }
+}
+
+/**
+ * @brief Selects the clock source to output on CCO pin(PC4).
+ * @note PC4 should be configured output push-pull with the speed that matches
+ * maximum output speed of the desired clock.
+ * @param CLK_CCOSource: specifies the clock source to output.
+ * This parameter can be one of the following values:
+ * @arg CLK_CCOSource_Off: No clock selected as CCO source
+ * @arg CLK_CCOSource_HSI: HSI clock selected as CCO source
+ * @arg CLK_CCOSource_LSI: LSI clock selected as CCO source
+ * @arg CLK_CCOSource_LSE: LSE clock selected as CCO source
+ * @arg CLK_CCOSource_HSE: HSE clock selected as CCO source
+ * @param CLK_CCODiv: specifies the CCO prescaler.
+ * This parameter can be one of the following values:
+ * @arg CLK_CCODiv_1: no division applied to CCO clock
+ * @arg CLK_CCODiv_2: division by 2 applied to CCO clock
+ * @arg CLK_CCODiv_4: division by 4 applied to CCO clock
+ * @arg CLK_CCODiv_8: division by 8 applied to CCO clock
+ * @arg CLK_CCODiv_16: division by 16 applied to CCO clock
+ * @arg CLK_CCODiv_32: division by 32 applied to CCO clock
+ * @arg CLK_CCODiv_64: division by 64 applied to CCO clock
+ * @retval None
+ */
+void CLK_CCOConfig(CLK_CCOSource_TypeDef CLK_CCOSource, CLK_CCODiv_TypeDef CLK_CCODiv)
+{
+ /* check teh parameters */
+ assert_param(IS_CLK_OUTPUT(CLK_CCOSource));
+ assert_param(IS_CLK_OUTPUT_DIVIDER(CLK_CCODiv));
+
+ /* Selects the source provided on cco_ck output and its divider*/
+ CLK->CCOR = (uint8_t)((uint8_t)CLK_CCOSource | (uint8_t)CLK_CCODiv);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup CLK_Group2 System clock configuration functions
+ * @brief System clock configuration functions
+ *
+@verbatim
+ ===============================================================================
+ System clock configuration functions
+ ===============================================================================
+
+ This section provides functions allowing to configure the System clock.
+
+ 1. Several clock sources can be used to drive the System clock (SYSCLK): HSI,
+ HSE, LSI and LSE.
+ You can use "CLK_GetClocksFreq()" function to retrieve the frequencies of these clocks.
+
+@note All the peripheral clocks are derived from the System clock (SYSCLK) except:
+ - BEEP: the Beeper clock can be derived either from a LSE or LSI clock sources.
+ You have to use CLK_BEEPClockConfig() function to configure this clock.
+ - RTC: the RTC clock can be derived either from the LSI, LSE, HSI or HSE clock
+ divided by 1 to 64. You have to use CLK_RTCClockConfig() functions to
+ configure this clock.
+ - LCD : LCD clock is the RTC Clock divided by 2.
+ - IWDG clock which is always the LSI clock.
+
+ 2. The maximum frequency of the SYSCLK is 16 MHz.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures the system clock (SYSCLK).
+ * @note The HSI is used (enabled by hardware) as system clock source after
+ * startup from Reset, wake-up from Halt and active Halt modes, or in case
+ * of failure of the HSE used as system clock (if the Clock Security System CSS is enabled).
+ * @note A switch from one clock source to another occurs only if the target
+ * clock source is ready (clock stable after startup delay or PLL locked).
+ * You can use CLK_GetSYSCLKSource() function to know which clock is
+ * currently used as system clock source.
+ * @param CLK_SYSCLKSource: specifies the clock source used as system clock.
+ * This parameter can be one of the following values:
+ * @arg CLK_SYSCLKSource_HSI: HSI selected as system clock source
+ * @arg CLK_SYSCLKSource_HSE: HSE selected as system clock source
+ * @arg CLK_SYSCLKSource_LSI: LSI selected as system clock source
+ * @arg CLK_SYSCLKSource_LSE: LSE selected as system clock source
+ * @retval None
+ */
+void CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_TypeDef CLK_SYSCLKSource)
+{
+ /* check teh parameters */
+ assert_param(IS_CLK_SOURCE(CLK_SYSCLKSource));
+
+ /* Selection of the target clock source */
+ CLK->SWR = (uint8_t)CLK_SYSCLKSource;
+}
+
+/**
+ * @brief Returns the clock source used as system clock.
+ * @param None
+ * @retval Clock used as System clock (SYSCLK) source.
+ * The returned value can be one of the following:
+ * - CLK_SYSCLKSource_HSI: HSI used as system clock
+ * - CLK_SYSCLKSource_LSI: LSI used as system clock
+ * - CLK_SYSCLKSource_HSE: HSE used as system clock
+ * - CLK_SYSCLKSource_LSE: LSE used as system clock
+ */
+CLK_SYSCLKSource_TypeDef CLK_GetSYSCLKSource(void)
+{
+ return ((CLK_SYSCLKSource_TypeDef)(CLK->SCSR));
+}
+
+/**
+ * @brief Returns the frequencies of different the SYSCLK
+ *
+ * @note The system frequency computed by this function is not the real
+ * frequency in the chip. It is calculated based on the predefined
+ * constant and the selected clock source:
+ * @note If SYSCLK source is HSI, function returns values based on HSI_VALUE(*)
+ * @note If SYSCLK source is HSE, function returns values based on HSE_VALUE(**)
+ * @note If SYSCLK source is LSE, function returns values based on LSE_VALUE(***)
+ * @note If SYSCLK source is LSI, function returns values based on LSI_VALUE(****)
+ * @note (*) HSI_VALUE is a constant defined in stm8l15x.h file (default value
+ * 16 MHz) but the real value may vary depending on the variations
+ * in voltage and temperature.
+ * @note (**) HSE_VALUE is a constant defined in stm8l15x.h file (default value
+ * 16 MHz), user has to ensure that HSE_VALUE is same as the real
+ * frequency of the crystal used. Otherwise, this function may
+ * have wrong result.
+ * @note (***) LSI_VALUE is a constant defined in stm8l15x.h file (default value
+ * 38 KHz) but the real value may vary depending on the variations
+ * in voltage and temperature.
+ * @note (****) LSE_VALUE is a constant defined in stm8l15x.h file (default value
+ * 32,768 KHz), user has to ensure that LSE_VALUE is same as the real
+ * frequency of the crystal used. Otherwise, this function may
+ * have wrong result.
+ *
+ * @note The result of this function could be not correct when using fractional
+ * value for HSE crystal.
+ *
+ * @param None
+ *
+ * @note This function can be used by the user application to compute the
+ * baudrate for the communication peripherals or configure other parameters.
+ * @note Each time SYSCLK clock changes, this function must be called to update
+ * the returned value. Otherwise, any configuration based on this
+ * function will be incorrect.
+ *
+ * @retval System Clock frequency value
+ */
+uint32_t CLK_GetClockFreq(void)
+{
+ uint32_t clockfrequency = 0;
+ uint32_t sourcefrequency = 0;
+ CLK_SYSCLKSource_TypeDef clocksource = CLK_SYSCLKSource_HSI;
+ uint8_t tmp = 0, presc = 0;
+
+ /* Get SYSCLK source. */
+ clocksource = (CLK_SYSCLKSource_TypeDef)CLK->SCSR;
+
+ if ( clocksource == CLK_SYSCLKSource_HSI)
+ {
+ sourcefrequency = HSI_VALUE;
+ }
+ else if ( clocksource == CLK_SYSCLKSource_LSI)
+ {
+ sourcefrequency = LSI_VALUE;
+ }
+ else if ( clocksource == CLK_SYSCLKSource_HSE)
+ {
+ sourcefrequency = HSE_VALUE;
+ }
+ else
+ {
+ clockfrequency = LSE_VALUE;
+ }
+
+ /* Get System clock divider factor*/
+ tmp = (uint8_t)(CLK->CKDIVR & CLK_CKDIVR_CKM);
+ presc = SYSDivFactor[tmp];
+
+ /* Get System clock frequency */
+ clockfrequency = sourcefrequency / presc;
+
+ return((uint32_t)clockfrequency);
+}
+
+/**
+ * @brief Configures the System clock (SYSCLK) dividers.
+ * @param CLK_SYSCLKDiv : Specifies the system clock divider to apply.
+ * This parameter can be one of the following values:
+ * @arg CLK_SYSCLKDiv_1
+ * @arg CLK_SYSCLKDiv_2
+ * @arg CLK_SYSCLKDiv_4
+ * @arg CLK_SYSCLKDiv_8
+ * @arg CLK_SYSCLKDiv_16
+ * @arg CLK_SYSCLKDiv_64
+ * @arg CLK_SYSCLKDiv_128
+ * @retval None
+ */
+void CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_TypeDef CLK_SYSCLKDiv)
+{
+ /* check the parameters */
+ assert_param(IS_CLK_SYSTEM_DIVIDER(CLK_SYSCLKDiv));
+
+ CLK->CKDIVR = (uint8_t)(CLK_SYSCLKDiv);
+}
+
+/**
+ * @brief Enables or disables the clock switch execution.
+ * @param NewState : new state of clock switch, value accepted ENABLE, DISABLE.
+ * @retval None
+ */
+void CLK_SYSCLKSourceSwitchCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Set SWEN bit */
+ CLK->SWCR |= CLK_SWCR_SWEN;
+ }
+ else
+ {
+ /* Reset SWEN bit */
+ CLK->SWCR &= (uint8_t)(~CLK_SWCR_SWEN);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup CLK_Group3 Peripheral clocks configuration functions
+ * @brief Peripheral clocks configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Peripheral clocks configuration functions
+ ===============================================================================
+
+ This section provides functions allowing to configure the Peripheral clocks.
+
+ 1. The RTC clock which is derived from the LSI, LSE, HSI or HSE clock divided by 1 to 64.
+
+ 2. The BEEP clock which is derived from the LSI or LSE clocks.
+
+ 3. After restart from Reset or wakeup from HALT, all peripherals are off
+ Before to start using a peripheral you have to enable its interface clock.
+ You can do this using CLK_AHBPeriphClockCmd()
+ , CLK_APB2PeriphClockCmd() and CLK_APB1PeriphClockCmd() functions.
+
+ 4. To reset the peripherals configuration (to the default state after device reset)
+ you can use CLK_PeripheralClockConfig() function.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures the RTC clock (RTCCLK).
+ * @param CLK_RTCCLKSource: specifies the RTC clock source.
+ * This parameter can be one of the following values:
+ * @arg CLK_RTCCLKSource_Off: RTC clock Off
+ * @arg CLK_RTCCLKSource_LSE: LSE selected as RTC clock
+ * @arg CLK_RTCCLKSource_LSI: LSI selected as RTC clock
+ * @arg CLK_RTCCLKSource_HSE: HSE selected as RTC clock
+ * @arg CLK_RTCCLKSource_HSI: HSI selected as RTC clock
+ *
+ * @param CLK_RTCCLKDiv: specifies the RTC clock source divider.
+ * This parameter can be one of the following values:
+ * @arg CLK_RTCCLKDiv_1: Clock RTC Div 1
+ * @arg CLK_RTCCLKDiv_2: Clock RTC Div 2
+ * @arg CLK_RTCCLKDiv_4: Clock RTC Div 4
+ * @arg CLK_RTCCLKDiv_8: Clock RTC Div 8
+ * @arg CLK_RTCCLKDiv_16: Clock RTC Div 16
+ * @arg CLK_RTCCLKDiv_32: Clock RTC Div 32
+ * @arg CLK_RTCCLKDiv_64: Clock RTC Div 64
+ *
+ * @note If the LSE or LSI is used as RTC clock source, the RTC continues to
+ * work in HALT and Active HALT modes, and can be used as wakeup source.
+ * However, when the HSE clock is used as RTC clock source.
+ * @note The maximum input clock frequency for RTC is 1MHz (when using HSE/HSI as
+ * RTC clock source).
+ *
+ * @retval None
+ */
+void CLK_RTCClockConfig(CLK_RTCCLKSource_TypeDef CLK_RTCCLKSource, CLK_RTCCLKDiv_TypeDef CLK_RTCCLKDiv)
+{
+ /* check the parameters */
+ assert_param(IS_CLK_CLOCK_RTC(CLK_RTCCLKSource));
+ assert_param(IS_CLK_CLOCK_RTC_DIV(CLK_RTCCLKDiv));
+
+ /* Selects the source provided on to RTC and its divider*/
+ CLK->CRTCR = (uint8_t)((uint8_t)CLK_RTCCLKSource | (uint8_t)CLK_RTCCLKDiv);
+}
+
+/**
+ * @brief Configures the BEEP clock (BEEPCLK).
+ * @param CLK_BEEPCLKSource: specifies the BEEP clock source.
+ * This parameter can be one of the following values:
+ * @arg CLK_BEEPCLKSource_Off: BEEP clock Off
+ * @arg CLK_BEEPCLKSource_LSE: LSE selected as BEEP clock
+ * @arg CLK_BEEPCLKSource_LSI: LSI selected as BEEP clock
+ * @retval None
+ */
+void CLK_BEEPClockConfig(CLK_BEEPCLKSource_TypeDef CLK_BEEPCLKSource)
+{
+ /* check the parameters */
+ assert_param(IS_CLK_CLOCK_BEEP(CLK_BEEPCLKSource));
+
+ /* Selects the source provided to BEEP*/
+ CLK->CBEEPR = (uint8_t)(CLK_BEEPCLKSource);
+
+}
+
+/**
+* @brief Enables or disables the specified peripheral clock.
+ * @note After reset, the peripheral clock (used for registers read/write access)
+ * is disabled and the application software has to enable this clock before
+ * using it.
+ * @param CLK_Peripheral: specifies the peripheral to gate its clock.
+ * This parameter can be any combination of the following values:
+ * @arg CLK_Peripheral_TIM2: TIM2 clock
+ * @arg CLK_Peripheral_TIM3: TIM3 clock
+ * @arg CLK_Peripheral_TIM4: TIM4 clock
+ * @arg CLK_Peripheral_I2C1: I2C1 clock
+ * @arg CLK_Peripheral_SPI1: SPI1 clock
+ * @arg CLK_Peripheral_USART1: USART1 clock
+ * @arg CLK_Peripheral_BEEP: BEEP clock
+ * @arg CLK_Peripheral_DAC: DAC clock
+ * @arg CLK_Peripheral_ADC1: ADC1 clock
+ * @arg CLK_Peripheral_TIM1: TIM1 clock
+ * @arg CLK_Peripheral_RTC: RTC clock
+ * @arg CLK_Peripheral_LCD: LCD clock
+ * @arg CLK_Peripheral_DMA1: DMA1 clock
+ * @arg CLK_Peripheral_COMP: COMP clock
+ * @arg CLK_Peripheral_BOOTROM: BOOTROM clock
+ * @arg CLK_Peripheral_AES: AES clock
+ * @arg CLK_Peripheral_TIM5: TIM5 clock
+ * @arg CLK_Peripheral_SPI2: SPI2 clock
+ * @arg CLK_Peripheral_USART2: USART2 clock
+ * @arg CLK_Peripheral_USART3: USART3 clock
+ * @arg CLK_Peripheral_CSSLSE: CSS on LSE clock
+ * @param NewState: new state of the specified peripheral clock.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void CLK_PeripheralClockConfig(CLK_Peripheral_TypeDef CLK_Peripheral, FunctionalState NewState)
+{
+ uint8_t reg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_CLK_PERIPHERAL(CLK_Peripheral));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* get flag register */
+ reg = (uint8_t)((uint8_t)CLK_Peripheral & (uint8_t)0xF0);
+
+ if ( reg == 0x00)
+ {
+ if (NewState != DISABLE)
+ {
+ /* Enable the peripheral Clock */
+ CLK->PCKENR1 |= (uint8_t)((uint8_t)1 << ((uint8_t)CLK_Peripheral & (uint8_t)0x0F));
+ }
+ else
+ {
+ /* Disable the peripheral Clock */
+ CLK->PCKENR1 &= (uint8_t)(~(uint8_t)(((uint8_t)1 << ((uint8_t)CLK_Peripheral & (uint8_t)0x0F))));
+ }
+ }
+ else if (reg == 0x10)
+ {
+ if (NewState != DISABLE)
+ {
+ /* Enable the peripheral Clock */
+ CLK->PCKENR2 |= (uint8_t)((uint8_t)1 << ((uint8_t)CLK_Peripheral & (uint8_t)0x0F));
+ }
+ else
+ {
+ /* Disable the peripheral Clock */
+ CLK->PCKENR2 &= (uint8_t)(~(uint8_t)(((uint8_t)1 << ((uint8_t)CLK_Peripheral & (uint8_t)0x0F))));
+ }
+ }
+ else
+ {
+ if (NewState != DISABLE)
+ {
+ /* Enable the peripheral Clock */
+ CLK->PCKENR3 |= (uint8_t)((uint8_t)1 << ((uint8_t)CLK_Peripheral & (uint8_t)0x0F));
+ }
+ else
+ {
+ /* Disable the peripheral Clock */
+ CLK->PCKENR3 &= (uint8_t)(~(uint8_t)(((uint8_t)1 << ((uint8_t)CLK_Peripheral & (uint8_t)0x0F))));
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup CLK_Group4 CSS on LSE configuration functions
+ * @brief CSS on LSE configuration functions
+ *
+@verbatim
+ ===============================================================================
+ CSS on LSE configuration functions
+ ===============================================================================
+
+ This section provides functions allowing to configure the CSS on LSE capability.
+
+ 1. The LSE crystal clock source failures can be monitored when used as RTC clock
+ by the mean of the LSI oscillator.
+
+ 2. The CSS on LSE is a feature implemented externally to RTC peripheral and though
+ has no impact the clock controller registers.
+
+ 3. To enable the CSS on LSE you can use CLK_LSEClockSecuritySystemEnable() function
+
+ 4. To configure the action to perform at RTC clock failure you can use
+ CLK_RTCCLKSwitchOnLSEFailureEnable() function that allows to switch the RTC clock
+ from LSE to LSI.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables the clock CSS on LSE.
+ * @note Once Enabled, only POR can Disable it.
+ * @param None
+ * @retval None
+ */
+void CLK_LSEClockSecuritySystemEnable(void)
+{
+ /* Set CSSEN bit */
+ CSSLSE->CSR |= CSSLSE_CSR_CSSEN;
+}
+
+/**
+ * @brief Enables RTC clock switch to LSI in case of LSE failure.
+ * @note Once Enabled, only POR can Disable it.
+ * @param None
+ * @retval None
+ */
+void CLK_RTCCLKSwitchOnLSEFailureEnable(void)
+{
+ /* Set SWITCHEN bit */
+ CSSLSE->CSR |= CSSLSE_CSR_SWITCHEN;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup CLK_Group5 Low power clock configuration functions
+ * @brief Low power clock configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Low power clock configuration functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures clock during halt and active halt modes.
+ * @param CLK_Halt : Specifies the clock state and wake-up mode from halt way.
+ * This parameter can be a value of @ref CLK_Halt_TypeDef.
+ * @param NewState : Specifies the System clock (SYSCLK) state in active halt mode.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void CLK_HaltConfig(CLK_Halt_TypeDef CLK_Halt, FunctionalState NewState)
+{
+ /* check the parameters */
+ assert_param(IS_CLK_HALT(CLK_Halt));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ CLK->ICKCR |= (uint8_t)(CLK_Halt);
+ }
+ else
+ {
+ CLK->ICKCR &= (uint8_t)(~CLK_Halt);
+ }
+}
+
+/**
+ * @brief Configures the main voltage regulator
+ * @param NewState: specifies the MVR state.
+ * This parameter can be one of the following values:
+ * - DISABLE: MVR disabled;
+ * - ENABLE: MVR enabled.
+ * @retval None
+ */
+void CLK_MainRegulatorCmd(FunctionalState NewState)
+{
+ /* check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Reset REGUOFF bit */
+ CLK->REGCSR &= (uint8_t)(~CLK_REGCSR_REGOFF);
+ }
+ else
+ {
+ /* Set REGUOFF bit */
+ CLK->REGCSR |= CLK_REGCSR_REGOFF;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup CLK_Group6 Interrupts and flags management functions
+ * @brief Interrupts and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts and flags management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+ /**
+ * @brief Enables or disables the specified CLK interrupts.
+ * @param CLK_IT: specifies the CLK interrupt sources to be enabled or disabled.
+ * This parameter can be any combination of the following values:
+ * @arg CLK_IT_CSSD: Clock security system detection interrupt
+ * @arg CLK_IT_SWIF: Clock switch interrupt
+ * @arg CLK_IT_LSECSSF: LSE Clock security system detection interrupt
+ * @param NewState: new state of the specified CLK interrupts.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void CLK_ITConfig(CLK_IT_TypeDef CLK_IT, FunctionalState NewState)
+{
+
+ /* check the parameters */
+ assert_param(IS_CLK_IT(CLK_IT));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ if (CLK_IT == CLK_IT_SWIF)
+ {
+ /* Enable the clock switch interrupt */
+ CLK->SWCR |= CLK_SWCR_SWIEN;
+ }
+ else if (CLK_IT == CLK_IT_LSECSSF)
+ {
+ /* Enable the CSS on LSE interrupt */
+ CSSLSE->CSR |= CSSLSE_CSR_CSSIE;
+ }
+ else
+ {
+ /* Enable the clock security system detection interrupt */
+ CLK->CSSR |= CLK_CSSR_CSSDIE;
+ }
+ }
+ else /*(NewState == DISABLE)*/
+ {
+ if (CLK_IT == CLK_IT_SWIF)
+ {
+ /* Disable the clock switch interrupt */
+ CLK->SWCR &= (uint8_t)(~CLK_SWCR_SWIEN);
+ }
+ else if (CLK_IT == CLK_IT_LSECSSF)
+ {
+ /* Disable the CSS on LSE interrupt */
+ CSSLSE->CSR &= (uint8_t)(~CSSLSE_CSR_CSSIE);
+ }
+ else
+ {
+ /* Disable the clock security system detection interrupt */
+ CLK->CSSR &= (uint8_t)(~CLK_CSSR_CSSDIE);
+ }
+ }
+}
+
+/**
+ * @brief Checks whether the specified CLK flag is set or not.
+ * @param CLK_FLAG: specifies the flag to check.
+ * This parameter can be one of the following values:
+ * @arg CLK_FLAG_LSIRDY: LSI oscillator clock ready
+ * @arg CLK_FLAG_HSIRDY: HSI oscillator clock ready
+ * @arg CLK_FLAG_HSERDY: HSE oscillator clock ready
+ * @arg CLK_FLAG_SWBSY: Switch busy
+ * @arg CLK_FLAG_CSSD: Clock security system detection
+ * @arg CLK_FLAG_AUX: Auxiliary oscillator connected to master clock
+ * @arg CLK_FLAG_LSERDY: LSE oscillator clock ready
+ * @arg CLK_FLAG_CCOBSY: Configurable clock output busy
+ * @arg CLK_FLAG_RTCSWBSY: RTC clock busy in switch
+ * @arg CLK_FLAG_EEREADY: Flash program memory and Data EEPROM ready
+ * @arg CLK_FLAG_EEBUSY: Flash program memory and Data EEPROM busy
+ * @arg CLK_FLAG_LSEPD: LSE power-down
+ * @arg CLK_FLAG_LSIPD: LSI power-down
+ * @arg CLK_FLAG_HSEPD: HSE power-down
+ * @arg CLK_FLAG_HSIPD: HSI power-down
+ * @arg CLK_FLAG_REGREADY: REGREADY
+ * @arg CLK_FLAG_BEEPSWBSY: BEEP clock busy in switch
+ * @arg CLK_FLAG_LSECSSF: CSS on LSE detection
+ * @arg CLK_FLAG_RTCCLKSWF: RTCCLK switch completed on LSE failure
+ * @retval The new state of CLK_FLAG (SET or RESET).
+ */
+FlagStatus CLK_GetFlagStatus(CLK_FLAG_TypeDef CLK_FLAG)
+{
+ uint8_t reg = 0;
+ uint8_t pos = 0;
+ FlagStatus bitstatus = RESET;
+
+ /* check the parameters */
+ assert_param(IS_CLK_FLAGS(CLK_FLAG));
+
+ /* get flag register */
+ reg = (uint8_t)((uint8_t)CLK_FLAG & (uint8_t)0xF0);
+
+ /* get flag position */
+ pos = (uint8_t)((uint8_t)CLK_FLAG & (uint8_t)0x0F);
+
+ if (reg == 0x00) /* The flag to check is in CRTC Rregister */
+ {
+ reg = CLK->CRTCR;
+ }
+ else if (reg == 0x10) /* The flag to check is in ICKCR register */
+ {
+ reg = CLK->ICKCR;
+ }
+ else if (reg == 0x20) /* The flag to check is in CCOR register */
+ {
+ reg = CLK->CCOR;
+ }
+ else if (reg == 0x30) /* The flag to check is in ECKCR register */
+ {
+ reg = CLK->ECKCR;
+ }
+ else if (reg == 0x40) /* The flag to check is in SWCR register */
+ {
+ reg = CLK->SWCR;
+ }
+ else if (reg == 0x50) /* The flag to check is in CSSR register */
+ {
+ reg = CLK->CSSR;
+ }
+ else if (reg == 0x70) /* The flag to check is in REGCSR register */
+ {
+ reg = CLK->REGCSR;
+ }
+ else if (reg == 0x80) /* The flag to check is in CSSLSE_CSRregister */
+ {
+ reg = CSSLSE->CSR;
+ }
+ else /* The flag to check is in CBEEPR register */
+ {
+ reg = CLK->CBEEPR;
+ }
+
+
+ if ((reg & (uint8_t)((uint8_t)1 << (uint8_t)pos)) != (uint8_t)RESET)
+ {
+ bitstatus = SET;
+ }
+ else
+ {
+ bitstatus = RESET;
+ }
+
+ /* Return the flag status */
+ return((FlagStatus)bitstatus);
+}
+
+/**
+ * @brief Clears the CSS LSE Flag.
+ * @param None
+ * @retval None
+ */
+void CLK_ClearFlag(void)
+{
+
+ /* Clear the clock security system on LSE detection Flag */
+ CSSLSE->CSR &= (uint8_t)(~CSSLSE_CSR_CSSF);
+}
+
+/**
+ * @brief Checks whether the specified CLK interrupt has occurred or not.
+ * @param CLK_IT: specifies the CLK interrupt source to check.
+ * This parameter can be one of the following values:
+ * @arg CLK_IT_SWIF: LSI ready interrupt
+ * @arg CLK_IT_LSECSSF: LSE ready interrupt
+ * @arg CLK_IT_CSSD: HSI ready interrupt
+ * @retval The new state of CLK_IT (SET or RESET).
+ */
+ITStatus CLK_GetITStatus(CLK_IT_TypeDef CLK_IT)
+{
+
+ ITStatus bitstatus = RESET;
+
+ /* check the parameters */
+ assert_param(IS_CLK_IT(CLK_IT));
+
+ if (CLK_IT == CLK_IT_SWIF)
+ {
+ /* Check the status of the clock switch interrupt */
+ if ((CLK->SWCR & (uint8_t)CLK_IT) == (uint8_t)0x0C)
+ {
+ bitstatus = SET;
+ }
+ else
+ {
+ bitstatus = RESET;
+ }
+ }
+ else if (CLK_IT == CLK_IT_LSECSSF)
+ {
+ /* Check the status of the clock security system on LSE interrupt */
+ if ((CSSLSE->CSR & (uint8_t)CLK_IT) == (uint8_t)0x0C)
+ {
+ bitstatus = SET;
+ }
+ else
+ {
+ bitstatus = RESET;
+ }
+ }
+ else /* CLK_IT == CLK_IT_CSSD */
+ {
+ /* Check the status of the security system detection interrupt */
+ if ((CLK->CSSR & (uint8_t)CLK_IT) == (uint8_t)0x0C)
+ {
+ bitstatus = SET;
+ }
+ else
+ {
+ bitstatus = RESET;
+ }
+ }
+
+ /* Return the CLK_IT status */
+ return bitstatus;
+}
+
+/**
+ * @brief Clears the CLK's interrupt pending bits.
+ * @param CLK_IT: specifies the interrupt pending bit to clear.
+ * This parameter can be any combination of the following values:
+ * @arg CLK_IT_SWIF: Clock switch interrupt
+ * @arg CLK_IT_LSECSSF: LSE Clock security system detection interrupt
+ * @retval None
+ */
+void CLK_ClearITPendingBit(CLK_IT_TypeDef CLK_IT)
+{
+
+ /* check the parameters */
+ assert_param(IS_CLK_CLEAR_IT(CLK_IT));
+
+ if ((uint8_t)((uint8_t)CLK_IT & (uint8_t)0xF0) == (uint8_t)0x20)
+ {
+ /* Clear the status of the clock security system on LSE interrupt */
+ CSSLSE->CSR &= (uint8_t)(~CSSLSE_CSR_CSSF);
+ }
+ else
+ {
+ /* Clear the status of the clock switch interrupt */
+ CLK->SWCR &= (uint8_t)(~CLK_SWCR_SWIF);
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_comp.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_comp.c
new file mode 100644
index 00000000..40e7d14c
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_comp.c
@@ -0,0 +1,728 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_comp.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the comparators (COMP1 and COMP2) peripheral:
+ * - Comparators configuration
+ * - Window mode control
+ * - Internal Reference Voltage (VREFINT) output
+ * - Comparator channels trigger configuration
+ * - Interrupts and flags management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * 1- Enable comparators clock using CLK_PeripheralClockConfig(CLK_Peripheral_COMP, ENABLE);
+ *
+ * When using COMP1:
+ * 2- Connect internal reference voltage to COMP1 inverting input
+ * using COMP_VrefintToCOMP1Connect()
+ * 3- Close the analog switch number 14 using SYSCFG_RIAnalogSwitchConfig()
+ * 4- Close the analog switch that corresponds to the pin to be used as
+ * non inverting input using SYSCFG_RIAnalogSwitchConfig()
+ * 5- Close the I/O switch of the pin to be used as non inverting input
+ * using SYSCFG_RIIOSwitchConfig()
+ * 6- Configure the event detection using COMP_EdgeConfig()
+ *
+ * When using COMP2:
+ * 2- Select the COMP2 inverting input, configure the speed and COMP2
+ * output redirection using COMP_Init()
+ * If the inverting input is an external pin, close the I/O channel
+ * switch using SYSCFG_RIIOSwitchConfig()
+ * 3- Close I/O Switch that corresponds to the selected pin as
+ * comparator 2 non inverting input using SYSCFG_RIIOSwitchConfig()
+ * 4- Configure the event detection using COMP_EdgeConfig()
+ *
+ * @note
+ * 1- COMP1 comparator and ADC can't be used at the same time since
+ * they share the same ADC switch matrix (analog switches).
+ *
+ * 2- When an I/O is used as comparator input, the corresponding GPIO
+ * registers should be configured in input floating.
+ *
+ * 3- Comparators outputs (CMP1OUT and CMP2OUT) are not mapped on
+ * GPIO pin. They are only internal.
+ * To get the comparator output level, use COMP_GetOutputLevel() function
+ * @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_comp.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup COMP
+ * @brief COMP driver modules
+ * @{
+ */
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup COMP_Private_Functions
+ * @{
+ */
+
+/** @defgroup COMP_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Initialization and Configuration functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the COMPx peripheral registers to their default reset values.
+ * @param None.
+ * @retval None.
+ */
+void COMP_DeInit(void)
+{
+ /* Set COMP->CSR1 to reset value 0x00 */
+ COMP->CSR1 = (uint8_t) COMP_CSR1_RESET_VALUE;
+
+ /* Set COMP->CSR2 to reset value 0x00 */
+ COMP->CSR2 = (uint8_t) COMP_CSR2_RESET_VALUE;
+
+ /* Set COMP->CSR3 to reset value 0xC0 */
+ COMP->CSR3 = (uint8_t) COMP_CSR3_RESET_VALUE;
+
+ /* Set COMP->CSR4 to reset value 0x00 */
+ COMP->CSR4 = (uint8_t) COMP_CSR4_RESET_VALUE;
+
+ /* Set COMP->CSR5 to reset value 0x00 */
+ COMP->CSR5 = (uint8_t) COMP_CSR5_RESET_VALUE;
+}
+
+/**
+ * @brief Initializes the comparator inverting input, output and speed.
+ * @note This function configures only COMP2.
+ * @param COMP_InvertingInput : selects the comparator inverting input.
+ * This parameter can be one of the following values:
+ * @arg COMP_InvertingInput_IO: Input/Output on comparator inverting input enable
+ * @arg COMP_InvertingInput_VREFINT: VREFINT on comparator inverting input enable
+ * @arg COMP_InvertingInput_3_4VREFINT: 3/4 VREFINT on comparator inverting input enable
+ * @arg COMP_InvertingInput_1_2VREFINT: 1/2 VREFINT on comparator inverting input enable
+ * @arg COMP_InvertingInput_1_4VREFINT: 1/4 VREFINT on comparator inverting input enable
+ * @arg COMP_InvertingInput_DAC1: DAC1 output on comparator inverting input enable
+ * @arg COMP_InvertingInput_DAC2: DAC2 output on comparator inverting input enable
+ * @param COMP_OutputSelect : selects the comparator output
+ * This parameter can be one of the following values:
+ * @arg COMP_OutputSelect_TIM2IC2: COMP2 output connected to TIM2 Input Capture 2
+ * @arg COMP_OutputSelect_TIM3IC2: COMP2 output connected to TIM3 Input Capture 2
+ * @arg COMP_OutputSelect_TIM1BRK: COMP2 output connected to TIM1 Break Input
+ * @arg COMP_OutputSelect_TIM1OCREFCLR: COMP2 output connected to TIM1 OCREF Clear
+ * @param COMP_Speed selects the comparator speed
+ * This parameter can be one of the following values:
+ * @arg COMP_Speed_Slow: Comparator speed: slow
+ * @arg COMP_Speed_Fast: Comparator speed: fast
+ * @retval None.
+ */
+void COMP_Init(COMP_InvertingInput_Typedef COMP_InvertingInput,
+ COMP_OutputSelect_Typedef COMP_OutputSelect, COMP_Speed_TypeDef COMP_Speed)
+{
+ /* Check the parameters */
+ assert_param(IS_COMP_INVERTING_INPUT(COMP_InvertingInput));
+ assert_param(IS_COMP_OUTPUT(COMP_OutputSelect));
+ assert_param(IS_COMP_SPEED(COMP_Speed));
+
+ /* Reset the INSEL[2:0] bits in CSR3 register */
+ COMP->CSR3 &= (uint8_t) (~COMP_CSR3_INSEL);
+ /* Select the comparator inverting input */
+ COMP->CSR3 |= (uint8_t) COMP_InvertingInput;
+
+ /* Reset the OUTSEL[1:0] bits in CSR3 register */
+ COMP->CSR3 &= (uint8_t) (~COMP_CSR3_OUTSEL);
+ /* Redirect the comparator output */
+ COMP->CSR3 |= (uint8_t) COMP_OutputSelect;
+
+ /* Reset the comparator speed bit */
+ COMP->CSR2 &= (uint8_t) (~COMP_CSR2_SPEED);
+ /* Select the comparator speed */
+ COMP->CSR2 |= (uint8_t) COMP_Speed;
+}
+
+/**
+ * @brief Enables or disables connection between VREFINT and COMP1 inverting input.
+ * @param NewState new state of the VREFINT connection to COMP1 inverting input.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void COMP_VrefintToCOMP1Connect(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the comparator */
+ COMP->CSR3 |= COMP_CSR3_VREFEN;
+ }
+ else
+ {
+ /* Disable the comparator */
+ COMP->CSR3 &= (uint8_t)(~COMP_CSR3_VREFEN);
+ }
+}
+
+/**
+ * @brief Configures the COMP edge detection.
+ * @param COMP_Selection: selects the comparator.
+ * This parameter can be one of the following values:
+ * @arg COMP_Selection_COMP1: Selection of Comparator 1
+ * @arg COMP_Selection_COMP2: Selection of Comparator 2
+ * @param COMP_Edge: This parameter can be one of the following values:
+ * @arg COMP_Edge_Falling: Falling edge selection
+ * @arg COMP_Edge_Rising: Rising edge selection
+ * @arg COMP_Edge_Rising_Falling: Rising and Falling edge selection
+ * @retval None.
+ */
+void COMP_EdgeConfig(COMP_Selection_TypeDef COMP_Selection, COMP_Edge_TypeDef COMP_Edge)
+{
+ /* Check the parameters */
+ assert_param(IS_COMP_ALL_PERIPH(COMP_Selection));
+ assert_param(IS_COMP_EDGE(COMP_Edge));
+
+ /* Check if comparator 1 is selected */
+ if (COMP_Selection == COMP_Selection_COMP1)
+ {
+ /* Reset the comparator 1 edge control bits */
+ COMP->CSR1 &= (uint8_t) (~COMP_CSR1_CMP1);
+
+ /* Select the edge detection of comparator 1 output */
+ COMP->CSR1 |= (uint8_t) COMP_Edge;
+ }
+ /* The comparator 2 is selected */
+ else
+ {
+ /* Reset the comparator 2 edge control bits */
+ COMP->CSR2 &= (uint8_t) (~COMP_CSR2_CMP2);
+
+ /* Select the edge detection of comparator 2 output */
+ COMP->CSR2 |= (uint8_t) COMP_Edge;
+ }
+}
+
+/**
+ * @brief Returns the output level of the comparator.
+ * @note Comparators outputs aren't available on GPIO (outputs levels are
+ * only internal).
+ * @param COMP_Selection: selects the comparator.
+ * This parameter can be one of the following values:
+ * @arg COMP_Selection_COMP1: Selection of Comparator 1
+ * @arg COMP_Selection_COMP2: Selection of Comparator 2
+ * @retval Returns the comparator output level
+ * This value can be one of the following:
+ * - COMP_OutputLevel_Low: Comparator output level is low
+ * - COMP_OutputLevel_High: Comparator output level is high
+ */
+COMP_OutputLevel_TypeDef COMP_GetOutputLevel(COMP_Selection_TypeDef COMP_Selection)
+{
+ uint8_t compout;
+
+ /* Check the parameters */
+ assert_param(IS_COMP_ALL_PERIPH(COMP_Selection));
+
+ /* Check if Comparator 1 is selected */
+ if (COMP_Selection == COMP_Selection_COMP1)
+ {
+ /* Check if comparator 1 output level is high */
+ if ((COMP->CSR1 & COMP_CSR1_CMP1OUT) != (uint8_t) RESET)
+ {
+ /* Get Comparator 1 output level */
+ compout = (COMP_OutputLevel_TypeDef) COMP_OutputLevel_High;
+ }
+ /* comparator 1 output level is low */
+ else
+ {
+ /* Get Comparator 1 output level */
+ compout = (COMP_OutputLevel_TypeDef) COMP_OutputLevel_Low;
+ }
+ }
+ /* Comparator 2 is selected */
+ else
+ {
+ /* Check if comparator 2 output level is high */
+ if ((COMP->CSR2 & COMP_CSR2_CMP2OUT) != (uint8_t) RESET)
+ {
+ /* Get Comparator output level */
+ compout = (COMP_OutputLevel_TypeDef) COMP_OutputLevel_High;
+ }
+ /* comparator 2 output level is low */
+ else
+ {
+ /* Get Comparator 2 output level */
+ compout = (COMP_OutputLevel_TypeDef) COMP_OutputLevel_Low;
+ }
+ }
+
+ /* Return the comparator output level */
+ return (COMP_OutputLevel_TypeDef)(compout);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup COMP_Group2 Window mode control function
+ * @brief Window mode control function
+ *
+@verbatim
+ ===============================================================================
+ Window mode control function
+ ===============================================================================
+
+ In window mode:
+ - COMP1 inverting input is fixed to VREFINT defining the first
+ threshold
+ - COMP2 inverting input is configurable (DAC_OUT1, VREFINT sub-multiples, ...)
+ defining the second threshold
+ - COMP1 and COMP2 non inverting inputs are connected together.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the window mode.
+ * @param NewState new state of the window mode.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void COMP_WindowCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the window mode */
+ COMP->CSR3 |= (uint8_t) COMP_CSR3_WNDWE;
+ }
+ else
+ {
+ /* Disable the window mode */
+ COMP->CSR3 &= (uint8_t)(~COMP_CSR3_WNDWE);
+ }
+}
+/**
+ * @}
+ */
+
+/** @defgroup COMP_Group3 Internal Reference Voltage output function
+ * @brief Internal Reference Voltage (VREFINT) output function
+ *
+@verbatim
+ ===============================================================================
+ Internal Reference Voltage (VREFINT) output function
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the output of the internal reference voltage.
+ * @param NewState : new state of the Vrefint output.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void COMP_VrefintOutputCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the output of internal reference voltage */
+ COMP->CSR3 |= (uint8_t) COMP_CSR3_VREFOUTEN;
+ }
+ else
+ {
+ /* Disable the output of internal reference voltage */
+ COMP->CSR3 &= (uint8_t) (~COMP_CSR3_VREFOUTEN);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup COMP_Group4 Comparator channels trigger configuration
+ * @brief Comparator channels trigger configuration
+ *
+@verbatim
+ ===============================================================================
+ Comparator channels trigger configuration
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the schmitt trigger.
+ * @param NewState : new state of the schmitt trigger.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void COMP_SchmittTriggerCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable Schmitt trigger on Input Output switches Channels */
+ COMP->CSR1 |= (uint8_t) COMP_CSR1_STE;
+ }
+ else
+ {
+ /* Enable Schmitt trigger on Input Output switches Channels */
+ COMP->CSR1 &= (uint8_t) (~COMP_CSR1_STE);
+ }
+}
+
+/**
+ * @brief Enables or disables trigger on the specified input/output group.
+ * @param COMP_TriggerGroup : specifies the input/output group
+ * This parameter can be one of the following values:
+ * @arg COMP_TriggerGroup_InvertingInput: Trigger on comparator 2 inverting input
+ * @arg COMP_TriggerGroup_NonInvertingInput: Trigger on comparator 2 non inverting input
+ * @arg COMP_TriggerGroup_VREFINTOutput: Trigger on VREFINT output
+ * @arg COMP_TriggerGroup_DACOutput: Trigger on DAC output
+ * @param COMP_TriggerPin : specifies the pin(s) within the input/output group
+ * This parameter can be one of the following values:
+ * @arg COMP_TriggerPin_0: Trigger Pin 0
+ * @arg COMP_TriggerPin_0: Trigger Pin 1
+ * @arg COMP_TriggerPin_0: Trigger Pin 2
+ * @param NewState : enable or disable the trigger on the selected pin(s)
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void COMP_TriggerConfig(COMP_TriggerGroup_TypeDef COMP_TriggerGroup,
+ COMP_TriggerPin_TypeDef COMP_TriggerPin,
+ FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_COMP_TRIGGERGROUP(COMP_TriggerGroup));
+ assert_param(IS_COMP_TRIGGERPIN(COMP_TriggerPin));
+
+ switch (COMP_TriggerGroup)
+ {
+ case COMP_TriggerGroup_InvertingInput:
+
+ if (NewState != DISABLE)
+ {
+ COMP->CSR4 &= (uint8_t) ~COMP_TriggerPin;
+ }
+ else
+ {
+ COMP->CSR4 |= (uint8_t) COMP_TriggerPin;
+ }
+ break;
+
+ case COMP_TriggerGroup_NonInvertingInput:
+ if (NewState != DISABLE)
+ {
+ COMP->CSR4 &= (uint8_t) ~((uint8_t)(COMP_TriggerPin << 3));
+ }
+ else
+ {
+ COMP->CSR4 |= (uint8_t) (COMP_TriggerPin << 3);
+ }
+ break;
+
+ case COMP_TriggerGroup_VREFINTOutput:
+ if (NewState != DISABLE)
+ {
+ COMP->CSR5 &= (uint8_t) ~COMP_TriggerPin;
+ }
+ else
+ {
+ COMP->CSR5 |= (uint8_t) COMP_TriggerPin;
+ }
+ break;
+
+ case COMP_TriggerGroup_DACOutput:
+ if (NewState != DISABLE)
+ {
+ COMP->CSR5 &= (uint8_t) ~((uint8_t)(COMP_TriggerPin << 3));
+ }
+ else
+ {
+ COMP->CSR5 |= (uint8_t) (COMP_TriggerPin << 3);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup COMP_Group5 Interrupts and flags management functions
+ * @brief Interrupts and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts and flags management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the interrupt generation when an event is detected.
+ * @param COMP_Selection : selects the comparator
+ * This parameter can be one of the following values:
+ * @arg COMP_Selection_COMP1: Selection of Comparator 1
+ * @arg COMP_Selection_COMP2: Selection of Comparator 2
+ * @param NewState : new state of the COMPx interrupt.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void COMP_ITConfig(COMP_Selection_TypeDef COMP_Selection, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_COMP_ALL_PERIPH(COMP_Selection));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Check if Comparator 1 is selected */
+ if (COMP_Selection == COMP_Selection_COMP1)
+ {
+ if (NewState != DISABLE)
+ {
+ /* Enable the COMP1 Interrupt source */
+ COMP->CSR1 |= (uint8_t) COMP_CSR1_IE1;
+ }
+ else
+ {
+ /* Disable the COMP1 Interrupt source */
+ COMP->CSR1 &= (uint8_t)(~COMP_CSR1_IE1);
+ }
+ }
+ else /* Comparator 2 is selected */
+ {
+ if (NewState != DISABLE)
+ {
+ /* Enable the COMP2 Interrupt source */
+ COMP->CSR2 |= (uint8_t) COMP_CSR2_IE2;
+ }
+ else
+ {
+ /* Disable the COMP2 Interrupt source */
+ COMP->CSR2 &= (uint8_t)(~COMP_CSR2_IE2);
+ }
+ }
+}
+
+/**
+ * @brief Checks whether the comparator flag is set or not.
+ * @param COMP_Selection : selects the comparator
+ * This parameter can be one of the following values:
+ * @arg COMP_Selection_COMP1: Selection of Comparator 1
+ * @arg COMP_Selection_COMP2: Selection of Comparator 2
+ * @retval The new state of COMPx event flag (SET or RESET).
+ */
+FlagStatus COMP_GetFlagStatus(COMP_Selection_TypeDef COMP_Selection)
+{
+ FlagStatus bitstatus = RESET;
+
+ /* Check the parameters */
+ assert_param(IS_COMP_ALL_PERIPH(COMP_Selection));
+
+ /* Check if COMP1 is selected */
+ if (COMP_Selection == COMP_Selection_COMP1)
+ {
+ if ((COMP->CSR1 & COMP_CSR1_EF1) != (uint8_t) RESET)
+ {
+ /* The comparator 1 event flag is set */
+ bitstatus = SET;
+ }
+ else
+ {
+ /* The comparator 1 event flag is reset */
+ bitstatus = RESET;
+ }
+ }
+ else /* COMP2 is selected */
+ {
+ if ((COMP->CSR2 & COMP_CSR2_EF2) != (uint8_t) RESET)
+ {
+ /* The comparator 2 event flag is set */
+ bitstatus = SET;
+ }
+ else
+ {
+ /* The comparator 2 event flag is reset */
+ bitstatus = RESET;
+ }
+ }
+
+ /* return the comparator event flag status */
+ return (FlagStatus)(bitstatus);
+}
+
+/**
+ * @brief Clears the comparator’s pending flag.
+ * @param COMP_Selection : selects the comparator
+ * This parameter can be one of the following values:
+ * @arg COMP_Selection_COMP1: Selection of Comparator 1
+ * @arg COMP_Selection_COMP2: Selection of Comparator 2
+ * @retval None.
+ */
+void COMP_ClearFlag(COMP_Selection_TypeDef COMP_Selection)
+{
+ /* Check the parameters */
+ assert_param(IS_COMP_ALL_PERIPH(COMP_Selection));
+
+ if (COMP_Selection == COMP_Selection_COMP1)
+ {
+ /* Clear the flag EF1 (rc_w0) clear this bit by writing 0. */
+ COMP->CSR1 &= (uint8_t) (~COMP_CSR1_EF1);
+ }
+ else
+ {
+ /* Clear the flag EF2 (rc_w0) clear this bit by writing 0. */
+ COMP->CSR2 &= (uint8_t) (~COMP_CSR2_EF2);
+ }
+}
+
+/**
+ * @brief Checks whether the comparator interrupt has occurred or not.
+ * @param COMP_Selection : selects the comparator
+ * This parameter can be one of the following values:
+ * @arg COMP_Selection_COMP1: Selection of Comparator 1
+ * @arg COMP_Selection_COMP2: Selection of Comparator 2
+ * @retval ITStatus : The state of the COMPx event flag (SET or RESET).
+ */
+ITStatus COMP_GetITStatus(COMP_Selection_TypeDef COMP_Selection)
+{
+ ITStatus bitstatus = RESET;
+ uint8_t itstatus = 0x00, itenable = 0x00;
+
+ /* Check the parameters */
+ assert_param(IS_COMP_ALL_PERIPH(COMP_Selection));
+
+ if (COMP_Selection == COMP_Selection_COMP1)
+ {
+ /* Get the EF1 comparator event flag status */
+ itstatus = (uint8_t) (COMP->CSR1 & COMP_CSR1_EF1);
+
+ /* Get the IE1 interrupt enable bit status */
+ itenable = (uint8_t) (COMP->CSR1 & COMP_CSR1_IE1);
+
+ if ((itstatus != (uint8_t) RESET) && (itenable != (uint8_t) RESET))
+ {
+ /* the EF1 and IE1 are set */
+ bitstatus = SET;
+ }
+ else
+ {
+ /* the EF1 or IE1 is reset */
+ bitstatus = RESET;
+ }
+ }
+ else
+ {
+ /* Get the EF2 comparator event flag value */
+ itstatus = (uint8_t) (COMP->CSR2 & COMP_CSR2_EF2);
+
+ /* Get the IE2 interrupt enable bit value */
+ itenable = (uint8_t) (COMP->CSR2 & COMP_CSR2_IE2);
+
+ if ((itstatus != (uint8_t)RESET) && (itenable != (uint8_t)RESET))
+ {
+ /* The EF2 and IE2 are set */
+ bitstatus = SET;
+ }
+ else
+ {
+ /* The EF2 or IE2 is reset */
+ bitstatus = RESET;
+ }
+ }
+
+ /* Return the COMP interrupt status */
+ return (ITStatus) bitstatus;
+}
+
+/**
+ * @brief Clears the interrupt pending bits of the comparator.
+ * @param COMP_Selection : selects the comparator
+ * This parameter can be one of the following values:
+ * @arg COMP_Selection_COMP1: Selection of Comparator 1
+ * @arg COMP_Selection_COMP2: Selection of Comparator 2
+ * @retval None
+ */
+void COMP_ClearITPendingBit(COMP_Selection_TypeDef COMP_Selection)
+{
+ /* Check the parameters */
+ assert_param(IS_COMP_ALL_PERIPH(COMP_Selection));
+
+ if (COMP_Selection == COMP_Selection_COMP1)
+ {
+ /* Clear the flag EF1 (rc_w0) clear this bit by writing 0. */
+ COMP->CSR1 &= (uint8_t) (~COMP_CSR1_EF1);
+ }
+ else
+ {
+ /* Clear the flag EF2 (rc_w0) clear this bit by writing 0. */
+ COMP->CSR2 &= (uint8_t) (~COMP_CSR2_EF2);
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_dac.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_dac.c
new file mode 100644
index 00000000..6bbae694
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_dac.c
@@ -0,0 +1,839 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_dac.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Digital-to-Analog Converter (DAC) peripheral:
+ * - DAC channels configuration: trigger, output buffer, data format
+ * - DMA management
+ * - Interrupts and flags management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * DAC Peripheral features
+ * ===================================================================
+ * The device integrates two 12-bit Digital Analog Converters that can
+ * be used independently or simultaneously (dual mode):
+ * 1- DAC channel1 with DAC_OUT1 (PF0) as output
+ * 1- DAC channel2 with DAC_OUT2 (PF1) as output
+ *
+ * Digital to Analog conversion can be non-triggered using DAC_Trigger_None
+ * and DAC_OUT1/DAC_OUT2 is available once writing to DHRx register using
+ * DAC_SetChannel1Data()/DAC_SetChannel2Data.
+ *
+ * Digital to Analog conversion can be triggered by:
+ * 1- External event: PE4 using DAC_Trigger_Ext.
+ * This pin (PE4) must be configured in input mode.
+ *
+ * 2- Timers TRGO: TIM4, TIM5
+ * (DAC_Trigger_T4_TRGO, DAC_Trigger_T5_TRGO)
+ * The timer TRGO event should be selected using TIMx_SelectOutputTrigger()
+ *
+ * 3- Software using DAC_Trigger_Software
+ *
+ * Each DAC channel integrates an output buffer that can be used to
+ * reduce the output impedance, and to drive external loads directly
+ * without having to add an external operational amplifier.
+ *
+ * Refer to the device datasheet for more details about output impedance
+ * value with and without output buffer.
+ *
+ * Both DAC channels can be used to generate
+ * 1- Noise wave using DAC_Wave_Noise
+ * 2- Triangle wave using DAC_Wave_Triangle
+ *
+ *
+ * The DAC data format can be:
+ * 1- 8-bit right alignment using DAC_Align_8b_R
+ * 2- 12-bit left alignment using DAC_Align_12b_L
+ * 3- 12-bit right alignment using DAC_Align_12b_R
+ *
+ * The analog output voltage on each DAC channel pin is determined
+ * by the following equation: DAC_OUTx = VREF+ * DOR / 4095
+ * with DOR is the Data Output Register
+ * VEF+ is the input voltage reference (refer to the device datasheet)
+ * e.g. To set DAC_OUT1 to 0.7V, use
+ * DAC_SetChannel1Data(DAC_Align_12b_R, 868);
+ * Assuming that VREF+ = 3.3, DAC_OUT1 = (3.3 * 868) / 4095 = 0.7V
+ *
+ * A DMA1 request can be generated when an external trigger (but not
+ * a software trigger) occurs if DMA1 requests are enabled using
+ * DAC_DMACmd()
+ * DMA1 requests are mapped as following:
+ * 1- DAC channel1 is mapped on DMA1 channel3 which must be already
+ * configured
+ * 2- DAC channel2 is mapped on DMA1 channel1 which must be already
+ * configured
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * - DAC clock must be enabled to get write access to DAC registers using
+ * CLK_PeripheralClockConfig(CLK_Peripheral_DAC, ENABLE)
+ * - Configure DAC_OUTx (DAC_OUT1: PF0, DAC_OUT2: PF1) in analog mode.
+ * - Configure the DAC channel using DAC_Init()
+ * - Enable the DAC channel using DAC_Cmd()
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_dac.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup DAC
+ * @brief DAC driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup DAC_Private_Functions
+ * @{
+ */
+
+/** @defgroup DAC_Group1 DAC channels configuration
+ * @brief DAC channels configuration: trigger, output buffer, data format
+ *
+@verbatim
+ ===============================================================================
+ DAC channels configuration: trigger, output buffer, data format
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the DAC peripheral registers to their default reset values.
+ * @param None
+ * @retval None
+ */
+void DAC_DeInit(void)
+{
+ /* Set Channel1 the Configuration registers to their reset values */
+ DAC->CH1CR1 = DAC_CR1_RESET_VALUE;
+ DAC->CH1CR2 = DAC_CR2_RESET_VALUE;
+
+ /* Set Channel2 the Configuration registers to their reset values */
+ DAC->CH2CR1 = DAC_CR1_RESET_VALUE;
+ DAC->CH2CR2 = DAC_CR2_RESET_VALUE;
+
+ /* Set the Software Trigger configuration registers to their reset values */
+ DAC->SWTRIGR = DAC_SWTRIGR_RESET_VALUE;
+
+ /* Set the Status registers to their reset values */
+ DAC->SR = (uint8_t)~DAC_SR_RESET_VALUE;
+
+ /* Set the Channel1 Data holding registers to their reset values */
+ DAC->CH1RDHRH = DAC_RDHRH_RESET_VALUE;
+ DAC->CH1RDHRL = DAC_RDHRL_RESET_VALUE;
+ DAC->CH1LDHRH = DAC_LDHRH_RESET_VALUE;
+ DAC->CH1LDHRL = DAC_LDHRL_RESET_VALUE;
+ DAC->CH1DHR8 = DAC_DHR8_RESET_VALUE;
+
+ /* Set the Channel2 Data holding registers to their reset values */
+ DAC->CH2RDHRH = DAC_RDHRH_RESET_VALUE;
+ DAC->CH2RDHRL = DAC_RDHRL_RESET_VALUE;
+ DAC->CH2LDHRH = DAC_LDHRH_RESET_VALUE;
+ DAC->CH2LDHRL = DAC_LDHRL_RESET_VALUE;
+ DAC->CH2DHR8 = DAC_DHR8_RESET_VALUE;
+
+ /* Set the Dual mode 12bit Right Data holding registers to their reset values */
+ DAC->DCH1RDHRH = DAC_RDHRH_RESET_VALUE;
+ DAC->DCH1RDHRL = DAC_RDHRL_RESET_VALUE;
+ DAC->DCH2RDHRH = DAC_RDHRH_RESET_VALUE;
+ DAC->DCH2RDHRL = DAC_RDHRL_RESET_VALUE;
+
+ /* Set the Dual mode 12bit Left Data holding registers to their reset values */
+ DAC->DCH1LDHRH = DAC_LDHRH_RESET_VALUE;
+ DAC->DCH1LDHRL = DAC_LDHRL_RESET_VALUE;
+ DAC->DCH2LDHRH = DAC_LDHRH_RESET_VALUE;
+ DAC->DCH2LDHRL = DAC_LDHRL_RESET_VALUE;
+
+ /* Set the Dual mode 8bit Data holding registers to their reset values */
+ DAC->DCH1DHR8 = DAC_DHR8_RESET_VALUE;
+ DAC->DCH2DHR8 = DAC_DHR8_RESET_VALUE;
+}
+
+/**
+ * @brief Initializes the DAC according to the specified parameters.
+ * @param DAC_Channel: the selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_Channel_1: DAC Channel1 selected
+ * @arg DAC_Channel_2: DAC Channel2 selected
+ * @param DAC_Trigger : the selected DAC trigger.
+ * This parameter can be one of the following values:
+ * @arg DAC_Trigger_None: DAC trigger None
+ * @arg DAC_Trigger_T4_TRGO: DAC trigger TIM4 TRGO
+ * @arg DAC_Trigger_T5_TRGO: DAC trigger TIM5 TRGO
+ * @arg DAC_Trigger_Ext: DAC trigger External Trigger (PE4)
+ * @arg DAC_Trigger_Software: DAC trigger software
+ * @param DAC_OutputBuffer : the status of DAC load Buffer
+ * This parameter can be one of the following values:
+ * @arg DAC_OutputBuffer_Enable: DAC output buffer Enabled
+ * @arg DAC_OutputBuffer_Disable: DAC output buffer Disabled
+ * @retval None
+ */
+void DAC_Init(DAC_Channel_TypeDef DAC_Channel,
+ DAC_Trigger_TypeDef DAC_Trigger,
+ DAC_OutputBuffer_TypeDef DAC_OutputBuffer)
+{
+ uint8_t tmpreg = 0;
+ uint16_t tmpreg2 = 0;
+
+ /* Check the DAC parameters */
+ assert_param(IS_DAC_CHANNEL(DAC_Channel));
+ assert_param(IS_DAC_TRIGGER(DAC_Trigger));
+ assert_param(IS_DAC_OUTPUT_BUFFER_STATE(DAC_OutputBuffer));
+
+ /* Get the DAC CHxCR1 value */
+ tmpreg2 = (uint16_t)((uint8_t)((uint8_t)DAC_Channel << 1));
+ tmpreg = *(uint8_t*)((uint16_t)(DAC_BASE + CR1_Offset + tmpreg2));
+
+ /* Clear BOFFx, TENx, TSELx bits */
+ tmpreg &= (uint8_t)~(DAC_CR1_BOFF | DAC_CR1_TEN | DAC_CR1_TSEL );
+
+ /* Set BOFFx bit according to DAC_OutputBuffer value */
+ tmpreg |= (uint8_t)(DAC_OutputBuffer);
+
+
+ /* Configure for the selected DAC channel trigger*/
+ if (DAC_Trigger != DAC_Trigger_None)
+ {
+ /* Set TSELx and TEN bits according to DAC_Trigger value */
+ tmpreg |= (uint8_t)(DAC_CR1_TEN | DAC_Trigger) ;
+ }
+
+ /* Write to DAC CHxCR1 */
+ *(uint8_t*)((uint16_t)(DAC_BASE + CR1_Offset + tmpreg2)) = (uint8_t)tmpreg;
+}
+
+/**
+ * @brief Enables or disables the specified DAC channel.
+ * @param DAC_Channel: the selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_Channel_1: DAC Channel1 selected
+ * @arg DAC_Channel_2: DAC Channel2 selected
+ * @param NewState: new state of the DAC channel.
+ * This parameter can be: ENABLE or DISABLE.
+ * @note When the DAC channel is enabled the trigger source can no more
+ * be modified.
+ * @retval None
+ */
+void DAC_Cmd(DAC_Channel_TypeDef DAC_Channel, FunctionalState NewState)
+{
+ uint16_t cr1addr = 0;
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(DAC_Channel));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Find CHxCR1 register Address */
+ cr1addr = DAC_BASE + CR1_Offset + (uint8_t)((uint8_t)DAC_Channel << 1);
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected DAC channel */
+ (*(uint8_t*)(cr1addr)) |= DAC_CR1_EN;
+ }
+ else
+ {
+ /* Disable the selected DAC channel */
+ (*(uint8_t*)(cr1addr)) &= (uint8_t) ~(DAC_CR1_EN);
+ }
+}
+
+/**
+ * @brief Enables or disables the selected DAC channel software trigger.
+ * @param DAC_Channel: the selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_Channel_1: DAC Channel1 selected
+ * @arg DAC_Channel_2: DAC Channel2 selected
+ * @param NewState: new state of the selected DAC channel software trigger.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None.
+ */
+void DAC_SoftwareTriggerCmd(DAC_Channel_TypeDef DAC_Channel, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(DAC_Channel));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable software trigger for the selected DAC channel */
+ DAC->SWTRIGR |= (uint8_t)(DAC_SWTRIGR_SWTRIG1 << DAC_Channel);
+ }
+ else
+ {
+ /* Disable software trigger for the selected DAC channel */
+ DAC->SWTRIGR &= (uint8_t)~((uint8_t)(DAC_SWTRIGR_SWTRIG1 << DAC_Channel));
+ }
+}
+
+/**
+ * @brief Enables or disables simultaneously the two DAC channels software
+ * triggers.
+ * @param NewState: new state of the DAC channels software triggers.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None.
+ */
+void DAC_DualSoftwareTriggerCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable software trigger for both DAC channels */
+ DAC->SWTRIGR |= (DAC_SWTRIGR_SWTRIG1 | DAC_SWTRIGR_SWTRIG2) ;
+ }
+ else
+ {
+ /* Disable software trigger for both DAC channels */
+ DAC->SWTRIGR &= (uint8_t)~(DAC_SWTRIGR_SWTRIG1 | DAC_SWTRIGR_SWTRIG2);
+ }
+}
+
+/**
+ * @brief Enables or disables the selected DAC channel wave generation.
+ * @param DAC_Channel: the selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_Channel_1: DAC Channel1 selected
+ * @arg DAC_Channel_2: DAC Channel2 selected
+ * @param DAC_Wave: Specifies the wave type to enable or disable.
+ * This parameter can be one of the following values:
+ * @arg DAC_Wave_Noise: noise wave generation
+ * @arg DAC_Wave_Triangle: triangle wave generation
+ * @param NewState: new state of the selected DAC channel wave generation.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void DAC_WaveGenerationCmd(DAC_Channel_TypeDef DAC_Channel,
+ DAC_Wave_TypeDef DAC_Wave,
+ FunctionalState NewState)
+{
+ uint8_t tmpreg = 0;
+
+ /* Check the DAC parameters */
+ assert_param(IS_DAC_CHANNEL(DAC_Channel));
+ assert_param(IS_DAC_WAVE(DAC_Wave));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Get the DAC CHxCR1 value & Clear WAVEN bits */
+ tmpreg = (uint8_t)((*(uint8_t*)(uint16_t)(DAC_BASE + CR1_Offset + (uint8_t)((uint8_t)DAC_Channel << 1))) & (uint8_t)~(DAC_CR1_WAVEN));
+
+ if (NewState != DISABLE)
+ {
+ tmpreg |= (uint8_t)(DAC_Wave);
+ }
+
+ /* Write to DAC CHxCR1 */
+ (*(uint8_t*) (uint16_t)(DAC_BASE + CR1_Offset + (uint8_t)((uint8_t)DAC_Channel << 1))) = tmpreg;
+
+}
+
+/**
+ * @brief Select DAC Noise Wave Generation LFSR according to the specified parameters.
+ * @param DAC_Channel: the selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_Channel_1: DAC Channel1 selected
+ * @arg DAC_Channel_2: DAC Channel2 selected
+ * @param DAC_LFSRUnmask : the selected unmasked bit.
+ * This parameter can be one of the following values:
+ * @arg DAC_LFSRUnmask_Bit0: Noise LFSR Unmask 1 LSB
+ * @arg DAC_LFSRUnmask_Bits1_0: Noise LFSR Unmask 2 LSB
+ * @arg DAC_LFSRUnmask_Bit2_0: Noise LFSR Unmask 3 LSB
+ * @arg DAC_LFSRUnmask_Bit3_0: Noise LFSR Unmask 4 LSB
+ * @arg DAC_LFSRUnmask_Bit4_0: Noise LFSR Unmask 5 LSB
+ * @arg DAC_LFSRUnmask_Bit5_0: Noise LFSR Unmask 6 LSB
+ * @arg DAC_LFSRUnmask_Bit6_0: Noise LFSR Unmask 7 LSB
+ * @arg DAC_LFSRUnmask_Bit7_0: Noise LFSR Unmask 8 LSB
+ * @arg DAC_LFSRUnmask_Bit8_0: Noise LFSR Unmask 9 LSB
+ * @arg DAC_LFSRUnmask_Bit9_0: Noise LFSR Unmask 10 LSB
+ * @arg DAC_LFSRUnmask_Bit10_0: Noise LFSR Unmask 11 LSB
+ * @arg DAC_LFSRUnmask_Bit11_0: Noise LFSR Unmask 12 LSB
+ * @retval None
+ */
+void DAC_SetNoiseWaveLFSR(DAC_Channel_TypeDef DAC_Channel, DAC_LFSRUnmask_TypeDef DAC_LFSRUnmask)
+{
+ uint8_t tmpreg = 0;
+ uint16_t cr2addr = 0;
+
+ /* Check the DAC parameters */
+ assert_param(IS_DAC_CHANNEL(DAC_Channel));
+ assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(DAC_LFSRUnmask));
+
+ /* Get the DAC CHxCR2 value & Clear MAMPx bits */
+ cr2addr = (uint16_t)(DAC_BASE + CR2_Offset + (uint8_t)((uint8_t)DAC_Channel << 1));
+ tmpreg = (uint8_t)((*(uint8_t*)(cr2addr)) & (uint8_t)~(DAC_CR2_MAMPx));
+
+ /* Write to DAC CHxCR2 */
+ (*(uint8_t*)(cr2addr)) = (uint8_t)( tmpreg | DAC_LFSRUnmask);
+}
+
+/**
+ * @brief Select DAC Triangle Wave Generation Amplitude according to the specified parameters.
+ * @param DAC_Channel: the selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_Channel_1: DAC Channel1 selected
+ * @arg DAC_Channel_2: DAC Channel2 selected
+ * @param DAC_TriangleAmplitude : the selected Amplitude
+ * This parameter can be one of the following values:
+ * @arg DAC_TriangleAmplitude_1: Triangle Amplitude = Vref.(1/4096)
+ * @arg DAC_TriangleAmplitude_3: Triangle Amplitude = Vref.(3/4096)
+ * @arg DAC_TriangleAmplitude_7: Triangle Amplitude = Vref.(7/4096)
+ * @arg DAC_TriangleAmplitude_15: Triangle Amplitude = Vref.(15/4096)
+ * @arg DAC_TriangleAmplitude_31: Triangle Amplitude = Vref.(31/4096)
+ * @arg DAC_TriangleAmplitude_63: Triangle Amplitude = Vref.(63/4096)
+ * @arg DAC_TriangleAmplitude_127: Triangle Amplitude = Vref.(127/4096)
+ * @arg DAC_TriangleAmplitude_255: Triangle Amplitude = Vref.(255/4096)
+ * @arg DAC_TriangleAmplitude_511: Triangle Amplitude = Vref.(511/4096)
+ * @arg DAC_TriangleAmplitude_1023: Triangle Amplitude = Vref.(1023/4096)
+ * @arg DAC_TriangleAmplitude_2047: Triangle Amplitude = Vref.(2047/4096)
+ * @arg DAC_TriangleAmplitude_4095: Triangle Amplitude = Vref.(4095/4096)
+ * @retval None
+ */
+void DAC_SetTriangleWaveAmplitude(DAC_Channel_TypeDef DAC_Channel, DAC_TriangleAmplitude_TypeDef DAC_TriangleAmplitude)
+{
+ uint8_t tmpreg = 0;
+ uint16_t cr2addr = 0;
+
+ /* Check the DAC parameters */
+ assert_param(IS_DAC_CHANNEL(DAC_Channel));
+ assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(DAC_TriangleAmplitude));
+
+
+ /* Get the DAC CHxCR2 value & Clear MAMPx bits */
+ cr2addr = (uint16_t)(DAC_BASE + CR2_Offset + (uint8_t)((uint8_t)DAC_Channel << 1));
+ tmpreg = (uint8_t)((*(uint8_t*)(cr2addr)) & (uint8_t)~(DAC_CR2_MAMPx));
+
+ /* Write to DAC CHxCR2 */
+ (*(uint8_t*)(cr2addr)) = (uint8_t)( tmpreg | DAC_TriangleAmplitude);
+}
+
+/**
+ * @brief Set the specified data holding register value for DAC channel1.
+ * @param DAC_Align: Specifies the data alignment for DAC channel1.
+ * This parameter can be one of the following values:
+ * @arg DAC_Align_8b_R: 8bit right data alignment selected
+ * @arg DAC_Align_12b_L: 12bit left data alignment selected
+ * @arg DAC_Align_12b_R: 12bit right data alignment selected
+ * @param Data : Data to be loaded in the selected data holding register.
+ * @retval None.
+ */
+void DAC_SetChannel1Data(DAC_Align_TypeDef DAC_Align, uint16_t DAC_Data)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_ALIGN(DAC_Align));
+
+ if (DAC_Align != DAC_Align_8b_R)
+ {
+ /* Set the DAC channel1 selected data holding register */
+ *(uint8_t*)((uint16_t)(DAC_BASE + CH1RDHRH_Offset + DAC_Align )) = (uint8_t)(((uint16_t)DAC_Data) >> 8);
+ *(uint8_t*)((uint16_t)(DAC_BASE + CH1RDHRH_Offset + 1 + DAC_Align )) = (uint8_t)DAC_Data;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_DAC_DATA_08R(DAC_Data));
+
+ /* Set the DAC channel1 selected data holding register */
+ DAC->CH1DHR8 = (uint8_t)(DAC_Data);
+ }
+}
+
+/**
+ * @brief Set the specified data holding register value for DAC channel2.
+ * @param DAC_Align: Specifies the data alignment for DAC channel2.
+ * This parameter can be one of the following values:
+ * @arg DAC_Align_8b_R: 8bit right data alignment selected
+ * @arg DAC_Align_12b_L: 12bit left data alignment selected
+ * @arg DAC_Align_12b_R: 12bit right data alignment selected
+ * @param Data : Data to be loaded in the selected data holding register.
+ * @retval None.
+ */
+void DAC_SetChannel2Data(DAC_Align_TypeDef DAC_Align, uint16_t DAC_Data)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_ALIGN(DAC_Align));
+
+ if (DAC_Align != DAC_Align_8b_R)
+ {
+ /* Set the DAC channel2 selected data holding register */
+ *(uint8_t*)((uint16_t)(DAC_BASE + CH2RDHRH_Offset + DAC_Align )) = (uint8_t)(((uint16_t)DAC_Data) >> 8);
+ *(uint8_t*)((uint16_t)(DAC_BASE + CH2RDHRH_Offset + 1 + DAC_Align )) = (uint8_t)DAC_Data;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_DAC_DATA_08R(DAC_Data));
+
+ /* Set the DAC channel2 selected data holding register */
+ DAC->CH2DHR8 = (uint8_t)(DAC_Data);
+ }
+}
+
+/**
+ * @brief Set the specified data holding register value for dual channel DAC.
+ * @param DAC_Align: Specifies the data alignment for dual channel DAC.
+ * This parameter can be one of the following values:
+ * @arg DAC_Align_8b_R: 8bit right data alignment selected
+ * @arg DAC_Align_12b_L: 12bit left data alignment selected
+ * @arg DAC_Align_12b_R: 12bit right data alignment selected
+ * @param Data2: Data for DAC Channel2 to be loaded in the selected data
+ * holding register.
+ * @param Data1: Data for DAC Channel1 to be loaded in the selected data
+ * holding register.
+ * @note In dual mode, a unique register access is required to write in both
+ * DAC channels at the same time.
+ * @retval None.
+ */
+void DAC_SetDualChannelData(DAC_Align_TypeDef DAC_Align, uint16_t DAC_Data2, uint16_t DAC_Data1)
+{
+ uint16_t dchxrdhrhaddr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_ALIGN(DAC_Align));
+
+ if (DAC_Align != DAC_Align_8b_R)
+ {
+ /* Identify the DCHxRDHRH address*/
+ dchxrdhrhaddr = (uint16_t)(DAC_BASE + DCH1RDHRH_Offset + DAC_Align);
+
+ /* Set the DAC channels Dual data holding registers */
+ *(uint8_t*)(uint16_t)dchxrdhrhaddr = (uint8_t)(((uint16_t)DAC_Data1) >> 8);
+ *(uint8_t*)(uint16_t)(dchxrdhrhaddr + 1) = (uint8_t)DAC_Data1;
+ *(uint8_t*)(uint16_t)(dchxrdhrhaddr + 2) = (uint8_t)(((uint16_t)DAC_Data2) >> 8);
+ *(uint8_t*)(uint16_t)(dchxrdhrhaddr + 3) = (uint8_t)DAC_Data2;
+ }
+ else
+ {
+ /* Check the parameter */
+ assert_param(IS_DAC_DATA_08R(DAC_Data1 | DAC_Data2));
+
+ /* Set the DAC channels Dual data holding registers */
+ DAC->DCH1DHR8 = (uint8_t)(DAC_Data1);
+ DAC->DCH2DHR8 = (uint8_t)(DAC_Data2);
+ }
+}
+
+/**
+ * @brief Returns the last data output value of the selected DAC channel.
+ * @param DAC_Channel: the selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_Channel_1: DAC Channel1 selected
+ * @arg DAC_Channel_2: DAC Channel2 selected
+ * @retval The selected DAC channel data output value.
+ */
+uint16_t DAC_GetDataOutputValue(DAC_Channel_TypeDef DAC_Channel)
+{
+ uint16_t outputdata = 0;
+ uint16_t tmp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(DAC_Channel));
+
+ if ( DAC_Channel == DAC_Channel_1)
+ {
+ /* Returns the DAC channel data output register value */
+ tmp = (uint16_t)((uint16_t)DAC->CH1DORH << 8);
+ outputdata = (uint16_t)(tmp | (DAC->CH1DORL));
+ }
+ else
+ {
+ /* Returns the DAC channel data output register value */
+ tmp = (uint16_t)((uint16_t)DAC->CH2DORH << 8);
+ outputdata = (uint16_t)(tmp | (DAC->CH2DORL));
+ }
+
+ /* return the selected DAC channel data output value.*/
+ return (uint16_t)outputdata;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DAC_Group2 DMA management functions
+ * @brief DMA management functions
+ *
+@verbatim
+ ===============================================================================
+ DMA management function
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the specified DAC channel DMA request.
+ * When enabled DMA1 is generated when an external trigger occurs
+ * @param DAC_Channel: the selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_Channel_1: DAC Channel1 selected
+ * @arg DAC_Channel_2: DAC Channel2 selected
+ * @param NewState: new state of the selected DAC channel DMA request.
+ * This parameter can be: ENABLE or DISABLE.
+ * The DAC channel1 (channel2) is mapped on DMA1 channel3 (channel1) which
+ * must be already configured.
+ * @retval None
+ */
+void DAC_DMACmd(DAC_Channel_TypeDef DAC_Channel, FunctionalState NewState)
+{
+ uint16_t cr2addr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(DAC_Channel));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Find CHxCR2 register Address */
+ cr2addr = DAC_BASE + CR2_Offset + (uint8_t)((uint8_t)DAC_Channel << 1);
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected DAC channel DMA request */
+ (*(uint8_t*)(cr2addr)) |= DAC_CR2_DMAEN;
+ }
+ else
+ {
+ /* Disable the selected DAC channel DMA request */
+ (*(uint8_t*)(cr2addr)) &= (uint8_t)~(DAC_CR2_DMAEN);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DAC_Group3 Interrupts and flags management functions
+ * @brief Interrupts and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts and flags management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the specified DAC interrupts.
+ * @param DAC_Channel: the selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_Channel_1: DAC Channel1 selected
+ * @arg DAC_Channel_2: DAC Channel2 selected
+ * @param DAC_IT: specifies the DAC interrupt sources to be enabled or disabled.
+ * This parameter can be the following values:
+ * @arg DAC_IT_DMAUDR: DMA underrun interrupt mask
+ * @note The DMA underrun occurs when a second external trigger arrives before
+ * the acknowledgement for the first external trigger is received (first request).
+ * @param NewState: new state of the specified DAC interrupts.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void DAC_ITConfig(DAC_Channel_TypeDef DAC_Channel, DAC_IT_TypeDef DAC_IT, FunctionalState NewState)
+{
+ uint16_t cr2addr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(DAC_Channel));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ assert_param(IS_DAC_IT(DAC_IT));
+
+ /* Find CHxCR2 register Address */
+ cr2addr = DAC_BASE + CR2_Offset + (uint8_t)((uint8_t)DAC_Channel << 1);
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected DAC interrupts */
+ (*(uint8_t*)(cr2addr)) |= (uint8_t)(DAC_IT);
+ }
+ else
+ {
+ /* Disable the selected DAC interrupts */
+ (*(uint8_t*)(cr2addr)) &= (uint8_t)(~(DAC_IT));
+ }
+}
+
+/**
+ * @brief Checks whether the specified DAC flag is set or not.
+ * @param DAC_Channel: thee selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_Channel_1: DAC Channel1 selected
+ * @arg DAC_Channel_2: DAC Channel2 selected
+ * @param DAC_FLAG: specifies the flag to check.
+ * This parameter can be only of the following value:
+ * @arg DAC_FLAG_DMAUDR: DMA underrun flag
+ * @note The DMA underrun occurs when a second external trigger arrives before
+ * the acknowledgement for the first external trigger is received (first request).
+ * @retval The new state of DAC_FLAG (SET or RESET).
+ */
+FlagStatus DAC_GetFlagStatus(DAC_Channel_TypeDef DAC_Channel, DAC_FLAG_TypeDef DAC_FLAG)
+{
+ FlagStatus flagstatus = RESET;
+ uint8_t flag = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(DAC_Channel));
+ assert_param(IS_DAC_FLAG(DAC_FLAG));
+
+ flag = (uint8_t)(DAC_FLAG << DAC_Channel);
+
+ /* Check the status of the specified DAC flag */
+ if ((DAC->SR & flag ) != (uint8_t)RESET)
+ {
+ /* DAC FLAG is set */
+ flagstatus = SET;
+ }
+ else
+ {
+ /* DAC FLAG is reset */
+ flagstatus = RESET;
+ }
+
+ /* Return the DAC FLAG status */
+ return flagstatus;
+}
+
+/**
+ * @brief Clears the DAC channel's pending flags.
+ * @param DAC_Channel: the selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_Channel_1: DAC Channel1 selected
+ * @arg DAC_Channel_2: DAC Channel2 selected
+ * @param DAC_FLAG: specifies the flag to clear.
+ * This parameter can be of the following value:
+ * @arg DAC_FLAG_DMAUDR: DMA underrun flag
+ * @retval None
+ */
+void DAC_ClearFlag(DAC_Channel_TypeDef DAC_Channel, DAC_FLAG_TypeDef DAC_FLAG)
+{
+ uint8_t flag = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(DAC_Channel));
+ assert_param(IS_DAC_FLAG(DAC_FLAG));
+
+ /* identify the selected flag*/
+ flag = (uint8_t)(DAC_FLAG << DAC_Channel);
+
+ /* Clear the selected DAC flag */
+ DAC->SR = (uint8_t)(~flag);
+}
+
+/**
+ * @brief Checks whether the specified DAC interrupt has occurred or not.
+ * @param DAC_Channel: the selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_Channel_1: DAC Channel1 selected
+ * @arg DAC_Channel_2: DAC Channel2 selected
+ * @param DAC_IT: specifies the DAC interrupt source to check.
+ * This parameter can be the following values:
+ * @arg DAC_IT_DMAUDR: DMA underrun interrupt mask
+ * @note The DMA underrun occurs when a second external trigger arrives before
+ * the acknowledgement for the first external trigger is received (first request).
+ * @retval The new state of DAC_IT (SET or RESET).
+ */
+ITStatus DAC_GetITStatus(DAC_Channel_TypeDef DAC_Channel, DAC_IT_TypeDef DAC_IT)
+{
+ ITStatus itstatus = RESET;
+ uint8_t enablestatus = 0;
+ uint8_t flagstatus = 0;
+ uint8_t tempreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(DAC_Channel));
+ assert_param(IS_DAC_IT(DAC_IT));
+
+ /* identify the status of the IT and its correspondent flag*/
+ tempreg = *(uint8_t*)(uint16_t)(DAC_BASE + CR2_Offset + (uint8_t)((uint8_t)DAC_Channel << 2));
+ enablestatus = (uint8_t)( tempreg & (uint8_t)((uint8_t)DAC_IT << DAC_Channel));
+ flagstatus = (uint8_t)(DAC->SR & (uint8_t)(DAC_IT >> ((uint8_t)0x05 - DAC_Channel)));
+
+ /* Check the status of the specified DAC interrupt */
+ if (((flagstatus) != (uint8_t)RESET) && enablestatus)
+ {
+ /* DAC IT is set */
+ itstatus = SET;
+ }
+ else
+ {
+ /* DAC IT is reset */
+ itstatus = RESET;
+ }
+
+ /* Return the DAC IT status */
+ return itstatus;
+}
+
+/**
+ * @brief Clears the DAC channel's interrupt pending bits.
+ * @param DAC_Channel: the selected DAC channel.
+ * This parameter can be one of the following values:
+ * @arg DAC_Channel_1: DAC Channel1 selected
+ * @arg DAC_Channel_2: DAC Channel2 selected
+ * @param DAC_IT: specifies the DAC interrupt pending bit to clear.
+ * This parameter can be the following values:
+ * @arg DAC_IT_DMAUDR: DMA underrun interrupt mask
+ * @retval None
+ */
+void DAC_ClearITPendingBit(DAC_Channel_TypeDef DAC_Channel, DAC_IT_TypeDef DAC_IT)
+{
+ /* Check the parameters */
+ assert_param(IS_DAC_CHANNEL(DAC_Channel));
+ assert_param(IS_DAC_IT(DAC_IT));
+
+ /* Clear the selected DAC interrupt pending bits */
+ DAC->SR = (uint8_t)~(uint8_t)((uint8_t)DAC_IT >> (0x05 - DAC_Channel));
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_dma.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_dma.c
new file mode 100644
index 00000000..aa5ae1e9
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_dma.c
@@ -0,0 +1,753 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_dma.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides all the DMA firmware functions.
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Direct Memory Access controller (DMA):
+ * - Initialization and Configuration
+ * - Data Counter
+ * - Interrupts and flags management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * 1. Enable The DMA controller clock using CLK_PeripheralClockConfig()
+ * function: CLK_PeripheralClockConfig(CLK_Peripheral_DMA1, ENABLE).
+ *
+ * 2. Enable and configure the peripheral to be connected to the DMA
+ * channel (except for internal SRAM / FLASH memories: no
+ * initialization is necessary).
+ *
+ * 3. For a given Channel, program the Source and Destination
+ * addresses, the transfer Direction, the Buffer Size, the
+ * Peripheral and Memory Incrementation mode and Data Size,
+ * the Circular or Normal mode, the channel transfer Priority
+ * and the Memory-to-Memory transfer mode (for channel 3 only,
+ * if needed) using the DMA_Init() function.
+ *
+ * 4. Enable the corresponding interrupt(s) using the function
+ * DMA_ITConfig() if you need to use DMA interrupts.
+ *
+ * 5. Enable the DMA channel using the DMA_Cmd() function.
+ *
+ * 6. Activate the needed channel Request using PPP_DMACmd() function
+ * for any PPP peripheral except internal SRAM and FLASH (ie. TIM4,
+ * USART ...). The function allowing this operation is provided in
+ * each PPP peripheral driver (ie. TIM4_DMACmd for TIM4 peripheral).
+ *
+ * 7. Optionally, you can configure the number of data to be
+ * transferred when the channel is disabled (ie. after each
+ * Transfer Complete event or when a Transfer Error occurs) using
+ * the function DMA_SetCurrDataCounter().
+ * And you can get the number of remaining data to be transferred
+ * using the function DMA_GetCurrDataCounter() at run time (when
+ * the DMA channel is enabled and running).
+ *
+ * 8. To control DMA events you can use one of the following
+ * two methods:
+ * a- Check on DMA channel flags using the function
+ * DMA_GetFlagStatus().
+ * b- Use DMA interrupts through the function DMA_ITConfig()
+ * at initialization phase and DMA_GetITStatus() function
+ * into interrupt routines in communication phase.
+ * After checking on a flag you should clear it using
+ * DMA_ClearFlag() function. And after checking on an interrupt
+ * event you should clear it using DMA_ClearITPendingBit()
+ * function.
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_dma.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup DMA
+ * @brief DMA driver modules
+ * @{
+ */
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup DMA_Private_Functions
+ * @{
+ */
+
+/** @defgroup DMA_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Initialization and Configuration functions
+ ===============================================================================
+
+ This subsection provides functions allowing to initialize the DMA channel
+ source and destination addresses, incrementation and data sizes, transfer
+ direction, buffer size, circular/normal mode selection, memory-to-memory mode
+ selection and channel priority value.
+
+ - The DMA_Init() function follows the DMA configuration procedures.
+ - All DMA channels can be enabled and disabled in the same time using
+ DMA_GlobalCmd() function.
+ - The DMA has 4 channels, User can enable or disable channels using
+ DMA_Cmd() function.
+ - The timeout duration (number of wait cycles starting from the latest
+ request) is configured using DMA_SetTimeOut() function. The DMA then waits
+ until this timeout has elapsed before requesting from the core a high
+ priority access to the bus.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the DMA Global Status register to its default reset
+ * values.
+ * @param None
+ * @retval None
+ */
+void DMA_GlobalDeInit(void)
+{
+ /* Disable the DMA */
+ DMA1->GCSR &= (uint8_t)~(DMA_GCSR_GE);
+
+ /* Reset DMA Channelx control register */
+ DMA1->GCSR = (uint8_t)DMA_GCSR_RESET_VALUE;
+}
+
+/**
+ * @brief Deinitializes the DMA Channelx registers to their default reset
+ * values.
+ * @param DMA_Channelx: selects the DMA Channelx where x can be 0 to 3
+ * @retval None
+ */
+void DMA_DeInit(DMA_Channel_TypeDef* DMA_Channelx)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA_CHANNEL(DMA_Channelx));
+
+ /* Disable the selected DMA Channelx */
+ DMA_Channelx->CCR &= (uint8_t)~(DMA_CCR_CE);
+
+ /* Reset DMA Channelx control register */
+ DMA_Channelx->CCR = DMA_CCR_RESET_VALUE;
+
+ /* Reset DMA Channelx remaining bytes register */
+ DMA_Channelx->CNBTR = DMA_CNBTR_RESET_VALUE;
+
+ /* Reset DMA Channelx peripheral address register */
+ if (DMA_Channelx == DMA1_Channel3)
+ {
+ DMA_Channelx->CPARH = DMA_C3PARH_RESET_VALUE;
+ DMA_Channelx->CM0EAR = DMA_C3M0EAR_RESET_VALUE;
+ }
+ else
+ {
+ DMA_Channelx->CPARH = DMA_CPARH_RESET_VALUE;
+ }
+ DMA_Channelx->CPARL = DMA_CPARL_RESET_VALUE;
+
+ /* Reset DMA Channelx memory address register */
+ DMA_Channelx->CM0ARH = DMA_CM0ARH_RESET_VALUE;
+ DMA_Channelx->CM0ARL = DMA_CM0ARL_RESET_VALUE;
+
+ /* Reset interrupt pending bits for DMA Channel */
+ DMA_Channelx->CSPR = DMA_CSPR_RESET_VALUE;
+}
+
+
+/**
+ * @brief Initializes the DMA Channelx according to the specified parameters.
+ * @param DMA_Channelx: selects the DMA Channelx where x can be 0 to 3
+ * @param DMA_Memory0BaseAddr: Specifies Memory 0 Base Address
+ * @param DMA_PeripheralMemory1BaseAddr: Specifies DMA channelx Peripheral
+ * Base Address (if data is from/to peripheral) or DMA channelx
+ * Memory1 Base Address (if data is from Memory0 to Memory1).
+ * @param DMA_BufferSize: Specifies the size of the DMA channelx Buffer.
+ * This parameter must be a value greater than 0.
+ * @param DMA_DIR: Specifies the DMA Channelx transfer direction.
+ * This parameter can be one of the following values:
+ * @arg DMA_DIR_PeripheralToMemory: Data transfer direction is Peripheral To Memory
+ * @arg DMA_DIR_MemoryToPeripheral: Data transfer direction is Memory To Peripheral
+ * @arg DMA_DIR_Memory0ToMemory1: Data transfer direction is Memory0 To Memory 1
+ * @param DMA_Mode: Specifies the DMA channelx mode.
+ * This parameter can be one of the following values:
+ * @arg DMA_Mode_Normal: DMA normal buffer mode
+ * @arg DMA_Mode_Circular: DMA circular buffer mode
+ * @param DMA_MemoryIncMode: Specifies the DMA channelx memory Incremental/Decremental mode
+ * This parameter can be one of the following values:
+ * @arg DMA_MemoryIncMode_Dec: DMA memory incremented mode is decremental
+ * @arg DMA_MemoryIncMode_Inc: DMA memory incremented mode is incremental
+ * @param DMA_Priority: Specifies the DMA channelx priority.
+ * This parameter can be one of the following values:
+ * @arg DMA_Priority_Low: Software Priority is Low
+ * @arg DMA_Priority_Medium: Software Priority is Medium
+ * @arg DMA_Priority_High: Software Priority is High
+ * @arg DMA_Priority_VeryHigh: Software Priority is Very High
+ * @param DMA_MemoryDataSize: Specifies the DMA channelx transfer Data size
+ * This parameter can be one of the following values:
+ * @arg DMA_MemoryDataSize_Byte: Memory Data Size is 1 Byte
+ * @arg DMA_MemoryDataSize_HalfWord: Memory Data Size is 2 Bytes
+ * @retval None
+ */
+void DMA_Init(DMA_Channel_TypeDef* DMA_Channelx,
+ uint32_t DMA_Memory0BaseAddr,
+ uint16_t DMA_PeripheralMemory1BaseAddr,
+ uint8_t DMA_BufferSize,
+ DMA_DIR_TypeDef DMA_DIR,
+ DMA_Mode_TypeDef DMA_Mode,
+ DMA_MemoryIncMode_TypeDef DMA_MemoryIncMode,
+ DMA_Priority_TypeDef DMA_Priority,
+ DMA_MemoryDataSize_TypeDef DMA_MemoryDataSize )
+{
+ /* Check the parameters */
+ assert_param(IS_DMA_CHANNEL(DMA_Channelx));
+ assert_param(IS_DMA_DIR(DMA_DIR));
+ assert_param(IS_DMA_BUFFER_SIZE(DMA_BufferSize));
+ assert_param(IS_DMA_MODE(DMA_Mode));
+ assert_param(IS_DMA_MEMORY_INC_MODE(DMA_MemoryIncMode));
+ assert_param(IS_DMA_PRIORITY(DMA_Priority));
+
+ /*--------------------------- DMA Channelx CCR Configuration ---------------*/
+ /* Disable the selected DMA Channelx */
+ DMA_Channelx->CCR &= (uint8_t)~(DMA_CCR_CE);
+
+ /* Reset DMA Channelx control register */
+ DMA_Channelx->CCR = DMA_CCR_RESET_VALUE;
+
+ /* Set DMA direction & Mode & Incremental Memory mode */
+ DMA_Channelx->CCR |= (uint8_t)((uint8_t)((uint8_t)DMA_DIR | \
+ (uint8_t)DMA_Mode) | \
+ (uint8_t)DMA_MemoryIncMode);
+
+ /*Clear old priority and memory data size option */
+ DMA_Channelx->CSPR &= (uint8_t)(~(uint8_t)(DMA_CSPR_PL | DMA_CSPR_16BM));
+
+ /* Set old priority and memory data size option */
+ DMA_Channelx->CSPR |= (uint8_t)((uint8_t)DMA_Priority | \
+ (uint8_t)DMA_MemoryDataSize);
+
+ /*--------------------------- DMA Channelx CNDTR Configuration -------------*/
+ /* Write to DMA Channelx CNDTR */
+ DMA_Channelx->CNBTR = (uint8_t)DMA_BufferSize;
+
+ /*--------------------------- DMA Channelx CPAR Configuration --------------*/
+ /* Write to DMA Channelx (0, 1 or 2) Peripheral address or Write to
+ DMA Channel 3 Memory 1 address */
+ DMA_Channelx->CPARH = (uint8_t)(DMA_PeripheralMemory1BaseAddr >> (uint8_t)8);
+ DMA_Channelx->CPARL = (uint8_t)(DMA_PeripheralMemory1BaseAddr);
+
+ /*--------------------------- DMA Channelx CMAR Configuration --------------*/
+ /* Write to DMA Channelx Memory address */
+ if (DMA_Channelx == DMA1_Channel3)
+ {
+ DMA_Channelx->CM0EAR = (uint8_t)(DMA_Memory0BaseAddr >> (uint8_t)16);
+ }
+ DMA_Channelx->CM0ARH = (uint8_t)(DMA_Memory0BaseAddr >> (uint8_t)8);
+ DMA_Channelx->CM0ARL = (uint8_t)(DMA_Memory0BaseAddr);
+
+}
+
+/**
+ * @brief Enables or disables All the DMA.
+ * @param NewState: new state of the DMA. This parameter can be: ENABLE
+ * or DISABLE.
+ * @retval None
+ */
+void DMA_GlobalCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the DMA */
+ DMA1->GCSR |= (uint8_t)DMA_GCSR_GE;
+ }
+ else
+ {
+ /* Disable the DMA */
+ DMA1->GCSR &= (uint8_t)(~DMA_GCSR_GE);
+ }
+}
+
+/**
+ * @brief Enables or disables the specified DMA Channelx.
+ * @note DMA_GlobalCmd function must be called first to enable or disable
+ * the global DMA.
+ * @param DMA_Channelx: selects the DMA Channelx where x can be 0 to 3
+ * @param NewState: new state of the DMA Channelx.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void DMA_Cmd(DMA_Channel_TypeDef* DMA_Channelx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA_CHANNEL(DMA_Channelx));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected DMA Channelx */
+ DMA_Channelx->CCR |= DMA_CCR_CE;
+ }
+ else
+ {
+ /* Disable the selected DMA Channelx */
+ DMA_Channelx->CCR &= (uint8_t)(~DMA_CCR_CE);
+ }
+}
+
+/**
+ * @brief Sets the Time out Value.
+ * @param DMA_TimeOut: an integer from 0 to 63
+ * @note If timeout duration >0 (number of wait cycles starting from the
+ * latest request), the DMA waits until this timeout has elapsed before
+ * requesting from the core a high priority access to the bus.
+ * @note If timeout duration =0, there is no timeout and once a request is served,
+ * the DMA immediately asks to the CPU a high priority access to the bus.
+ * @retval None
+ */
+void DMA_SetTimeOut(uint8_t DMA_TimeOut)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA_TIMEOUT(DMA_TimeOut));
+
+ /* set the time out, GB and GE must be = 0 */
+ DMA1->GCSR = 0;
+ DMA1->GCSR = (uint8_t)(DMA_TimeOut << (uint8_t)2);
+
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DMA_Group2 Data Counter functions
+ * @brief Data Counter functions
+ *
+@verbatim
+ ===============================================================================
+ Data Counter functions
+ ===============================================================================
+
+ This subsection provides functions allowing to configure and read the buffer
+ size (number of data to be transferred).
+
+ The DMA data counter can be written only when the DMA channel is disabled
+ (ie. after transfer complete event).
+
+ The DMA_SetCurrDataCounter() function can be used to write the Channel data
+ counter value.
+
+
+ Note: It is advised to use this function rather than DMA_Init() (DMA_BufferSize
+ parameter) in situations where only the Data buffer needs to be reloaded.
+
+ The DMA data counter can be read to indicate the number of remaining transfers
+ for the relative DMA channel. This counter is decremented at the end of each
+ data transfer and when the transfer is complete:
+ - If Normal mode is selected: the counter is set to 0.
+ - If Circular mode is selected: the counter is reloaded with the initial value
+ (configured before enabling the DMA channel)
+
+ The DMA_GetCurrDataCounter() function can be used to read the Channel current
+ data counter value.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set the number of data units to transfer for DMA Channelx.
+ * @param DMA_Channelx: selects the DMA Channelx where x can be 0 to 3
+ * @param DataNumber: The number of data units to transfer, it can be any value
+ * from 0 to 255
+ * @note It is advised to use this function rather than DMA_Init() in situations
+ * where only the Data buffer needs to be reloaded.
+ * @retval None
+ */
+void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMA_Channelx, uint8_t DataNumber)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA_CHANNEL(DMA_Channelx));
+
+ /*Set the number of data units for DMA Channelx */
+ DMA_Channelx->CNBTR = DataNumber;
+}
+
+/**
+ * @brief Returns the number of remaining data units in the current DMA Channelx transfer.
+ * @param DMA_Channelx: selects the DMA Channelx where x can be 0 to 3
+ * @retval The number of remaining data units in the current DMA Channelx
+ */
+uint8_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMA_Channelx)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA_CHANNEL(DMA_Channelx));
+
+ /* Return the number of remaining data units for DMA Channelx */
+ return ((uint8_t)(DMA_Channelx->CNBTR));
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DMA_Group3 Interrupts and flags management functions
+ * @brief Interrupts and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts and flags management functions
+ ===============================================================================
+
+ This subsection provides functions allowing to configure the DMA Interrupts
+ sources and check or clear the flags or pending bits status.
+ The user should identify which mode will be used in his application to manage
+ the DMA controller events: Polling mode or Interrupt mode.
+
+ Polling Mode
+ =============
+ Each DMA channel can be managed through 2 event Flags:
+ (x: DMA channel number )
+ 1. DMA1_FLAG_TCx: to indicate that a Transfer Complete event occurred
+ 2. DMA1_FLAG_HTx: to indicate that a Half-Transfer Complete event
+ occurred
+
+ In this Mode it is advised to use DMA_GetFlagStatus() and DMA_ClearFlag()
+ functions.
+
+
+ Interrupt Mode
+ ===============
+ Each DMA channel can be managed through 2 Interrupts:
+
+ Interrupt Source
+ ----------------
+ 1. DMA_IT_TC: specifies the interrupt source for the Transfer Complete
+ event.
+ 2. DMA_IT_HT: specifies the interrupt source for the Half-transfer
+ Complete event.
+
+ In this Mode it is advised to use DMA_ITConfig(), DMA_GetITStatus() and
+ DMA_ClearITPendingBit() functions.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the specified DMA Channelx interrupts.
+ * @param DMA_Channelx: selects the DMA Channelx where x can be 0 to 3
+ * @param DMA_ITx: specifies the DMA interrupts sources to be enabled or disabled.
+ * This parameter can be one of the following values:
+ * @arg DMA_ITx_TC: Transaction Complete Interrupt
+ * @arg DMA_ITx_HT: Half Transaction Interrupt
+ * @param NewState: new state of the specified DMA interrupts.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void DMA_ITConfig(DMA_Channel_TypeDef* DMA_Channelx,
+ DMA_ITx_TypeDef DMA_ITx,
+ FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA_CHANNEL(DMA_Channelx));
+ assert_param(IS_DMA_CONFIG_ITX(DMA_ITx));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected DMA interrupts */
+ DMA_Channelx->CCR |= (uint8_t)(DMA_ITx);
+ }
+ else
+ {
+ /* Disable the selected DMA interrupts */
+ DMA_Channelx->CCR &= (uint8_t)~(DMA_ITx);
+ }
+}
+
+/**
+ * @brief Checks whether the specified DMA Channelx flag is set or not.
+ * @param DMA_FLAG: specifies the flag to check.
+ * This parameter can be one of the following values:
+ * @arg DMA1_FLAG_GB: Global Busy Flag
+ * @arg DMA1_FLAG_IFC0: Global Interrupt Flag Channel 0
+ * @arg DMA1_FLAG_IFC1: Global Interrupt Flag Channel 1
+ * @arg DMA1_FLAG_IFC2: Global Interrupt Flag Channel 2
+ * @arg DMA1_FLAG_IFC3: Global Interrupt Flag Channel 3
+ * @arg DMA1_FLAG_TC0: Transaction Complete Interrupt Flag Channel 0
+ * @arg DMA1_FLAG_TC1: Transaction Complete Interrupt Flag Channel 1
+ * @arg DMA1_FLAG_TC2: Transaction Complete Interrupt Flag Channel 2
+ * @arg DMA1_FLAG_TC2: Transaction Complete Interrupt Flag Channel 3
+ * @arg DMA1_FLAG_HT0: Half Transaction Interrupt Flag Channel 0
+ * @arg DMA1_FLAG_HT1: Half Transaction Interrupt Flag Channel 1
+ * @arg DMA1_FLAG_HT2: Half Transaction Interrupt Flag Channel 2
+ * @arg DMA1_FLAG_HT3: Half Transaction Interrupt Flag Channel 3
+ * @arg DMA1_FLAG_PEND0: DMA Request pending on Channel 0
+ * @arg DMA1_FLAG_PEND1: DMA Request pending on Channel 1
+ * @arg DMA1_FLAG_PEND2: DMA Request pending on Channel 2
+ * @arg DMA1_FLAG_PEND3: DMA Request pending on Channel 3
+ * @arg DMA1_FLAG_BUSY0: No DMA transfer on going in Channel 0
+ * @arg DMA1_FLAG_BUSY1: No DMA transfer on going in Channel 1
+ * @arg DMA1_FLAG_BUSY2: No DMA transfer on going in Channel 2
+ * @arg DMA1_FLAG_BUSY3: No DMA transfer on going in Channel 3
+ * @retval The status of DMA_FLAG (SET or RESET).
+ */
+FlagStatus DMA_GetFlagStatus(DMA_FLAG_TypeDef DMA_FLAG)
+{
+ FlagStatus flagstatus = RESET;
+ DMA_Channel_TypeDef* DMA_Channelx = DMA1_Channel0;
+ uint8_t tmpgir1 = 0;
+ uint8_t tmpgcsr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DMA_GET_FLAG(DMA_FLAG));
+
+ /* Get flags registers values*/
+ tmpgcsr = DMA1->GCSR;
+ tmpgir1 = DMA1->GIR1;
+
+ if (((uint16_t)DMA_FLAG & (uint16_t)0x0F00) != (uint16_t)RESET)
+ {
+ /* find the used DMA channel */
+ if (((uint16_t)DMA_FLAG & 0x0100) != (uint16_t)RESET)
+ {
+ DMA_Channelx = DMA1_Channel0;
+ }
+ else if (((uint16_t)DMA_FLAG & 0x0200) != (uint16_t)RESET)
+ {
+ DMA_Channelx = DMA1_Channel1;
+ }
+ else if (((uint16_t)DMA_FLAG & 0x0400) != (uint16_t)RESET)
+ {
+ DMA_Channelx = DMA1_Channel2;
+ }
+ else
+ {
+ DMA_Channelx = DMA1_Channel3;
+ }
+
+ /* Get the specified DMA Channelx flag status. */
+ flagstatus = (FlagStatus)((uint8_t)(DMA_Channelx->CSPR) & (uint8_t)DMA_FLAG);
+ }
+ else if (((uint16_t)DMA_FLAG & 0x1000) != (uint16_t)RESET)
+ {
+ /* Get the specified DMA Channelx flag status. */
+ flagstatus = (FlagStatus)(tmpgir1 & (uint8_t)DMA_FLAG);
+ }
+ else /*if ((DMA_FLAG & DMA_FLAG_GB) != (uint16_t)RESET)*/
+ {
+ /* Get the specified DMA Channelx flag status. */
+ flagstatus = (FlagStatus)(tmpgcsr & DMA_GCSR_GB);
+ }
+
+ /* Return the specified DMA Channelx flag status. */
+ return (flagstatus);
+}
+
+/**
+ * @brief Clears the DMA Channels selected flags.
+ * @param DMA_FLAG: specifies the flag to clear.
+ * This parameter can be one or a combination (for the same channel)of
+ * the following values:
+ * @arg DMA1_FLAG_TC0: Transaction Complete Interrupt Flag Channel 0
+ * @arg DMA1_FLAG_TC1: Transaction Complete Interrupt Flag Channel 1
+ * @arg DMA1_FLAG_TC2: Transaction Complete Interrupt Flag Channel 2
+ * @arg DMA1_FLAG_TC2: Transaction Complete Interrupt Flag Channel 3
+ * @arg DMA1_FLAG_HT0: Half Transaction Interrupt Flag Channel 0
+ * @arg DMA1_FLAG_HT1: Half Transaction Interrupt Flag Channel 1
+ * @arg DMA1_FLAG_HT2: Half Transaction Interrupt Flag Channel 2
+ * @arg DMA1_FLAG_HT3: Half Transaction Interrupt Flag Channel 3
+ * @retval None
+ */
+void DMA_ClearFlag(DMA_FLAG_TypeDef DMA_FLAG)
+{
+ DMA_Channel_TypeDef* DMA_Channelx = DMA1_Channel0;
+
+ /* Check the parameters */
+ assert_param(IS_DMA_CLEAR_FLAG(DMA_FLAG));
+
+ /* Identify the used DMA channel */
+ if (((uint16_t)DMA_FLAG & (uint16_t)0x0100) != (uint16_t)RESET)
+ {
+ DMA_Channelx = DMA1_Channel0;
+ }
+ else
+ {
+ if (((uint16_t)DMA_FLAG & (uint16_t)0x0200) != (uint16_t)RESET)
+ {
+ DMA_Channelx = DMA1_Channel1;
+ }
+ else
+ {
+ if (((uint16_t)DMA_FLAG & (uint16_t)0x0400) != (uint16_t)RESET)
+ {
+ DMA_Channelx = DMA1_Channel2;
+ }
+ else
+ {
+ DMA_Channelx = DMA1_Channel3;
+ }
+ }
+ }
+
+ /*Clears the DMA flags.*/
+ DMA_Channelx->CSPR &= (uint8_t)~(uint8_t)((uint8_t)DMA_FLAG & (uint8_t)0x06);
+}
+
+/**
+ * @brief Checks whether the specified DMA Channelx interrupt has occurred or not.
+ * @param DMA_IT: specifies the DMA interrupt source to check.
+ * This parameter can be one or a combination of the following values:
+ * @arg DMA1_IT_TC0: Transaction Complete Interrupt Channel 0
+ * @arg DMA1_IT_TC1: Transaction Complete Interrupt Channel 1
+ * @arg DMA1_IT_TC2: Transaction Complete Interrupt Channel 2
+ * @arg DMA1_IT_TC3: Transaction Complete Interrupt Channel 3
+ * @arg DMA1_IT_HT0: Half Transaction Interrupt Channel 0
+ * @arg DMA1_IT_HT1: Half Transaction Interrupt Channel 1
+ * @arg DMA1_IT_HT2: Half Transaction Interrupt Channel 2
+ * @arg DMA1_IT_HT3: Half Transaction Interrupt Channel 3
+ * @retval ITStatus: The status of DMA_IT (SET or RESET).
+ */
+ITStatus DMA_GetITStatus(DMA_IT_TypeDef DMA_IT)
+{
+ ITStatus itstatus = RESET;
+ uint8_t tmpreg = 0;
+ uint8_t tmp2 = 0;
+ DMA_Channel_TypeDef* DMA_Channelx = DMA1_Channel0;
+
+ /* Check the parameters */
+ assert_param(IS_DMA_GET_IT(DMA_IT));
+
+ /* Identify the used DMA channel */
+ if ((DMA_IT & 0x10) != (uint8_t)RESET)
+ {
+ DMA_Channelx = DMA1_Channel0;
+ }
+ else
+ {
+ if ((DMA_IT & 0x20) != (uint8_t)RESET)
+ {
+ DMA_Channelx = DMA1_Channel1;
+ }
+ else
+ {
+ if ((DMA_IT & 0x40) != (uint8_t)RESET)
+ {
+ DMA_Channelx = DMA1_Channel2;
+ }
+ else
+ {
+ DMA_Channelx = DMA1_Channel3;
+ }
+ }
+ }
+ /* Get the specified DMA Channelx interrupt status. */
+ tmpreg = DMA_Channelx->CSPR ;
+ tmpreg &= DMA_Channelx->CCR ;
+ tmp2 = (uint8_t)(DMA_IT & (uint8_t)(DMA_CCR_TCIE | DMA_CCR_HTIE));
+ itstatus = (ITStatus)((uint8_t)tmpreg & (uint8_t)tmp2);
+
+ /* Return the specified DMA Channelx interrupt status. */
+ return (itstatus);
+}
+
+/**
+ * @brief Clears the DMA Channelx’s interrupt pending bits.
+ * @param DMA_IT: specifies the DMA interrupt pending bit to clear.
+ * This parameter can be one or a combination(for the same channel)of
+ * the following values:
+ * @arg DMA1_IT_TC0: Transaction Complete Interrupt Channel 0
+ * @arg DMA1_IT_TC1: Transaction Complete Interrupt Channel 1
+ * @arg DMA1_IT_TC2: Transaction Complete Interrupt Channel 2
+ * @arg DMA1_IT_TC3: Transaction Complete Interrupt Channel 3
+ * @arg DMA1_IT_HT0: Half Transaction Interrupt Channel 0
+ * @arg DMA1_IT_HT1: Half Transaction Interrupt Channel 1
+ * @arg DMA1_IT_HT2: Half Transaction Interrupt Channel 2
+ * @arg DMA1_IT_HT3: Half Transaction Interrupt Channel 3
+ * @retval None
+ */
+void DMA_ClearITPendingBit(DMA_IT_TypeDef DMA_IT)
+{
+ DMA_Channel_TypeDef* DMA_Channelx = DMA1_Channel0;
+
+ /* Check the parameters */
+ assert_param(IS_DMA_CLEAR_IT(DMA_IT));
+ /* Identify the used DMA channel */
+ if ((DMA_IT & 0x10) != (uint8_t)RESET)
+ {
+ DMA_Channelx = DMA1_Channel0;
+ }
+ else
+ {
+ if ((DMA_IT & 0x20) != (uint8_t)RESET)
+ {
+ DMA_Channelx = DMA1_Channel1;
+ }
+ else
+ {
+ if ((DMA_IT & 0x40) != (uint8_t)RESET)
+ {
+ DMA_Channelx = DMA1_Channel2;
+ }
+ else
+ {
+ DMA_Channelx = DMA1_Channel3;
+ }
+ }
+ }
+ /*Clears the DMA Channelx’s interrupt pending bits*/
+ DMA_Channelx->CSPR &= (uint8_t)~(uint8_t)(DMA_IT & (uint8_t)0x06);
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_exti.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_exti.c
new file mode 100644
index 00000000..c8c78b14
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_exti.c
@@ -0,0 +1,559 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_exti.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the EXTI peripheral:
+ * - Interrupt sensitivity of GPIO ports/pins configuration
+ * - Interrupt status management
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * This driver provides functions to configure and initialize the EXTI
+ * peripheral
+ * These functions are split in 2 groups:
+ *
+ * 1. EXTI configuration: this group includes all needed functions
+ * to configure the EXTI GPIO ports and pins:
+ * - Set GPIO pins sensitivity
+ * - Select GPIO port, GPIO half port and set the GPIO port sensitivity
+ *
+ * 2. EXTI interrupt status management
+ * - Get the interrupt status: set/reset
+ * - Clear interrupt pending bits
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_exti.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup EXTI
+ * @brief EXTI driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup EXTI_Private_Functions
+ * @{
+ */
+
+/** @defgroup EXTI_Group1 Interrupt sensitivity of GPIO ports/pins configuration
+ * @brief Interrupt sensitivity of GPIO ports/pins configuration
+ *
+@verbatim
+ ===============================================================================
+ EXTI configuration functions
+ ===============================================================================
+
+ ===================================================================
+ EXTI Driver: how to configure EXTI
+ ===================================================================
+ To use a GPIO pin as an interrupt source, follow theses steps:
+
+ 1. Configure the GPIO pin in input mode with interrupt enabled using
+ GPIO_Init()
+
+ 2. Configure the GPIO pin sensitivity (falling, rising...) using
+ EXTI_SetPinSensitivity()
+
+ 3. Enable global interrupts using enableInterrupts()
+
+ 4. In the IRQ handler corresponding to the GPIO pin, clear the interrupt
+ pending bit using EXTI_ClearITPendingBit()
+
+ To use a GPIO port as an interrupt source, follows theses steps:
+
+ 1. Configure the GPIO pins of the same port in input mode with interrupt
+ enabled using GPIO_Init()
+
+ 2. Configure the GPIO port sensitivity (falling, rising...) using
+ EXTI_SetPortSensitivity()
+
+ 3. Select the GPIO port and the corresponding half port using
+ EXTI_SelectPort() then EXTI_SetHalfPortSelection()
+
+ 4. Enable global interrupts using enableInterrupts()
+
+ 5. In the IRQ handler corresponding to the GPIO port, clear the interrupt
+ pending bit using EXTI_ClearITPendingBit()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the EXTI registers to their default reset value.
+ * @param None
+ * @retval None
+ */
+void EXTI_DeInit(void)
+{
+ EXTI->CR1 = EXTI_CR1_RESET_VALUE;
+ EXTI->CR2 = EXTI_CR2_RESET_VALUE;
+ EXTI->CR3 = EXTI_CR3_RESET_VALUE;
+ EXTI->CR4 = EXTI_CR4_RESET_VALUE;
+ EXTI->SR1 = 0xFF; /* Setting SR1 bits in order to clear flags */
+ EXTI->SR2 = 0xFF; /* Setting SR2 bits in order to clear flags */
+ EXTI->CONF1 = EXTI_CONF1_RESET_VALUE;
+ EXTI->CONF2 = EXTI_CONF2_RESET_VALUE;
+}
+
+/**
+ * @brief Sets the external interrupt sensitivity of the selected pin.
+ * @note Global interrupts must be disabled before calling this function.
+ * @note The modification of external interrupt sensitivity is only possible
+ * when he interrupts are disabled.
+ * @note The normal behavior is to disable the interrupts before calling this
+ * function, and re-enable them after.
+ * @param EXTI_Pin : The pin to configure.
+ * This parameter can be one of the following values:
+ * @arg EXTI_Pin_0: GPIO Pin 0
+ * @arg EXTI_Pin_1: GPIO Pin 1
+ * @arg EXTI_Pin_2: GPIO Pin 2
+ * @arg EXTI_Pin_3: GPIO Pin 3
+ * @arg EXTI_Pin_4: GPIO Pin 4
+ * @arg EXTI_Pin_5: GPIO Pin 5
+ * @arg EXTI_Pin_6: GPIO Pin 6
+ * @arg EXTI_Pin_7: GPIO Pin 7
+ * @param EXTI_Trigger : The external interrupt sensitivity value to set.
+ * This parameter can be one of the following values:
+ * @arg EXTI_Trigger_Falling_Low: Interrupt on Falling edge and Low level
+ * @arg EXTI_Trigger_Rising: Interrupt on Rising edge only
+ * @arg EXTI_Trigger_Falling: Interrupt on Falling edge only
+ * @arg EXTI_Trigger_Rising_Falling: Interrupt on Rising and Falling edges
+ * @retval None
+ */
+void EXTI_SetPinSensitivity(EXTI_Pin_TypeDef EXTI_Pin, EXTI_Trigger_TypeDef EXTI_Trigger)
+{
+
+ /* Check function parameters */
+ assert_param(IS_EXTI_PINNUM(EXTI_Pin));
+ assert_param(IS_EXTI_TRIGGER(EXTI_Trigger));
+
+ /* Clear port sensitivity bits */
+ switch (EXTI_Pin)
+ {
+ case EXTI_Pin_0:
+ EXTI->CR1 &= (uint8_t)(~EXTI_CR1_P0IS);
+ EXTI->CR1 |= (uint8_t)((uint8_t)(EXTI_Trigger) << EXTI_Pin);
+ break;
+ case EXTI_Pin_1:
+ EXTI->CR1 &= (uint8_t)(~EXTI_CR1_P1IS);
+ EXTI->CR1 |= (uint8_t)((uint8_t)(EXTI_Trigger) << EXTI_Pin);
+ break;
+ case EXTI_Pin_2:
+ EXTI->CR1 &= (uint8_t)(~EXTI_CR1_P2IS);
+ EXTI->CR1 |= (uint8_t)((uint8_t)(EXTI_Trigger) << EXTI_Pin);
+ break;
+ case EXTI_Pin_3:
+ EXTI->CR1 &= (uint8_t)(~EXTI_CR1_P3IS);
+ EXTI->CR1 |= (uint8_t)((uint8_t)(EXTI_Trigger) << EXTI_Pin);
+ break;
+ case EXTI_Pin_4:
+ EXTI->CR2 &= (uint8_t)(~EXTI_CR2_P4IS);
+ EXTI->CR2 |= (uint8_t)((uint8_t)(EXTI_Trigger) << ((uint8_t)EXTI_Pin & (uint8_t)0xEF));
+ break;
+ case EXTI_Pin_5:
+ EXTI->CR2 &= (uint8_t)(~EXTI_CR2_P5IS);
+ EXTI->CR2 |= (uint8_t)((uint8_t)(EXTI_Trigger) << ((uint8_t)EXTI_Pin & (uint8_t)0xEF));
+ break;
+ case EXTI_Pin_6:
+ EXTI->CR2 &= (uint8_t)(~EXTI_CR2_P6IS);
+ EXTI->CR2 |= (uint8_t)((uint8_t)(EXTI_Trigger) << ((uint8_t)EXTI_Pin & (uint8_t)0xEF));
+ break;
+ case EXTI_Pin_7:
+ EXTI->CR2 &= (uint8_t)(~EXTI_CR2_P7IS);
+ EXTI->CR2 |= (uint8_t)((uint8_t)(EXTI_Trigger) << ((uint8_t)EXTI_Pin & (uint8_t)0xEF));
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * @brief Selects the port interrupt selection.
+ * @param EXTI_Port : The port number to access.
+ * This parameter can be one of the following values:
+ * @arg EXTI_Port_B: GPIO Port B
+ * @arg EXTI_Port_D: GPIO Port D
+ * @arg EXTI_Port_E: GPIO Port E
+ * @arg EXTI_Port_F: GPIO Port F
+ * @arg EXTI_Port_G: GPIO Port G
+ * @arg EXTI_Port_H: GPIO Port H
+ * @retval None
+ */
+void EXTI_SelectPort(EXTI_Port_TypeDef EXTI_Port)
+{
+ /* Check function parameter */
+ assert_param(IS_EXTI_PORT(EXTI_Port));
+
+ if (EXTI_Port == EXTI_Port_B)
+ {
+ /* Select Port B by resetting PGBS bit in CONF2 register */
+ EXTI->CONF2 &= (uint8_t) (~EXTI_CONF2_PGBS);
+ }
+ else if (EXTI_Port == EXTI_Port_D)
+ {
+ /* Select Port D by resetting PHDS bit in CONF2 register */
+ EXTI->CONF2 &= (uint8_t) (~EXTI_CONF2_PHDS);
+ }
+ else if (EXTI_Port == EXTI_Port_E)
+ {
+ /* Select Port E by resetting PFES bit in CONF1 register */
+ EXTI->CONF1 &= (uint8_t) (~EXTI_CONF1_PFES);
+ }
+ else if (EXTI_Port == EXTI_Port_F)
+ {
+ /* Select Port F by setting PFES bit in CONF1 register */
+ EXTI->CONF1 |= (uint8_t) (EXTI_CONF1_PFES);
+ }
+ else if (EXTI_Port == EXTI_Port_G)
+ {
+ /* Select Port G by setting PGBS bit in CONF2 register */
+ EXTI->CONF2 |= (uint8_t) (EXTI_CONF2_PGBS);
+ }
+ else /* EXTI_Port is EXTI_Port_H */
+ {
+ /* Select Port H by setting PHDS bit in CONF2 register */
+ EXTI->CONF2 |= (uint8_t) (EXTI_CONF2_PHDS);
+ }
+}
+
+/**
+ * @brief Configures the half port interrupt selection.
+ * @note This function should be called once the port sensitivity configured,
+ * otherwise it will not have any effect on the port external interrupt.
+ * @note This function should be called after EXTI_SelectPort() function which
+ * selects the port to be used otherwise ports are selected by default
+ * @param EXTI_HalfPort : The port part to access (MSB or LSB).
+ * This parameter can be one of the following values:
+ * @arg EXTI_HalfPort_B_LSB: Interrupt selector PB(3:0)
+ * @arg EXTI_HalfPort_B_MSB: Interrupt selector PB(7:4)
+ * @arg EXTI_HalfPort_D_LSB: Interrupt selector PD(3:0)
+ * @arg EXTI_HalfPort_D_MSB: Interrupt selector PD(7:4)
+ * @arg EXTI_HalfPort_E_LSB: Interrupt selector PE(3:0)
+ * @arg EXTI_HalfPort_E_MSB: Interrupt selector PE(7:4)
+ * @arg EXTI_HalfPort_F_LSB: Interrupt selector PF(3:0)
+ * @arg EXTI_HalfPort_F_MSB: Interrupt selector PF(7:4)
+ * @arg EXTI_HalfPort_G_LSB: Interrupt selector PG(3:0)
+ * @arg EXTI_HalfPort_G_MSB: Interrupt selector PG(7:4)
+ * @arg EXTI_HalfPort_H_LSB: Interrupt selector PH(3:0)
+ * @arg EXTI_HalfPort_H_MSB: Interrupt selector PH(7:4)
+ * @param NewState : The external interrupt new state.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void EXTI_SetHalfPortSelection(EXTI_HalfPort_TypeDef EXTI_HalfPort,
+ FunctionalState NewState)
+{
+ /* Check function parameters */
+ assert_param(IS_EXTI_HALFPORT(EXTI_HalfPort));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if ((EXTI_HalfPort & 0x80) == 0x00)
+ {
+ if (NewState != DISABLE)
+ {
+ /* Enable port interrupt selector */
+ EXTI->CONF1 |= (uint8_t)EXTI_HalfPort;
+ }
+ else /*NewState == DISABLE */
+ {
+ /* Disable port interrupt selector */
+ EXTI->CONF1 &= (uint8_t)(~(uint8_t)EXTI_HalfPort);
+ }
+ }
+ else
+ {
+ if (NewState != DISABLE)
+ {
+ /* Enable port interrupt selector */
+ EXTI->CONF2 |= (uint8_t)(EXTI_HalfPort & (uint8_t)0x7F);
+ }
+ else /*NewState == DISABLE */
+ {
+ /* Disable port interrupt selector */
+ EXTI->CONF2 &= (uint8_t)(~(uint8_t) (EXTI_HalfPort & (uint8_t)0x7F));
+ }
+ }
+}
+
+/**
+ * @brief Sets the external interrupt sensitivity of the selected port.
+ * @note Global interrupts must be disabled before calling this function.
+ * @note The modification of external interrupt sensitivity is only possible
+ * when the interrupts are disabled.
+ * @note The normal behavior is to disable the interrupts before calling this
+ * function, and re-enable them after.
+ * @param EXTI_Port : The port number to access.
+ * This parameter can be one of the following values:
+ * @arg EXTI_Port_B: GPIO Port B
+ * @arg EXTI_Port_D: GPIO Port D
+ * @arg EXTI_Port_E: GPIO Port E
+ * @arg EXTI_Port_F: GPIO Port F
+ * @arg EXTI_Port_G: GPIO Port G
+ * @arg EXTI_Port_H: GPIO Port H
+ * @param EXTI_Trigger : The external interrupt sensitivity value to set.
+ * This parameter can be one of the following values:
+ * @arg EXTI_Trigger_Falling_Low: Interrupt on Falling edge and Low level
+ * @arg EXTI_Trigger_Rising: Interrupt on Rising edge only
+ * @arg EXTI_Trigger_Falling: Interrupt on Falling edge only
+ * @arg EXTI_Trigger_Rising_Falling: Interrupt on Rising and Falling edges
+ * @retval None
+ */
+void EXTI_SetPortSensitivity(EXTI_Port_TypeDef EXTI_Port,
+ EXTI_Trigger_TypeDef EXTI_Trigger)
+{
+ /* Check function parameters */
+ assert_param(IS_EXTI_PORT(EXTI_Port));
+ assert_param(IS_EXTI_TRIGGER(EXTI_Trigger));
+
+ /* Ceck if selected port is in EXTI_CR3 register */
+ if ((EXTI_Port & 0xF0) == 0x00)
+ {
+ /* Reset the trigger bits corresponding to EXTI_Port */
+ EXTI->CR3 &= (uint8_t) (~(uint8_t)((uint8_t)0x03 << EXTI_Port));
+ /* Write EXTI port trigger */
+ EXTI->CR3 |= (uint8_t)((uint8_t)(EXTI_Trigger) << EXTI_Port);
+ }
+ else /* selected port is in EXTI_CR4 register */
+ {
+ /* Reset the trigger bits corresponding to EXTI_Port */
+ EXTI->CR4 &= (uint8_t) (~(uint8_t)((uint8_t)0x03 << (EXTI_Port & 0x0F)));
+ /* Write EXTI port trigger */
+ EXTI->CR4 |= (uint8_t)(EXTI_Trigger << (EXTI_Port & 0x0F));
+ }
+}
+
+/**
+ * @brief Gets the external interrupt sensitivity of the selected pin.
+ * @param EXTI_Pin : The pin number to access.
+ * This parameter can be one of the following values:
+ * @arg EXTI_Pin_0: GPIO Pin 0
+ * @arg EXTI_Pin_1: GPIO Pin 1
+ * @arg EXTI_Pin_2: GPIO Pin 2
+ * @arg EXTI_Pin_3: GPIO Pin 3
+ * @arg EXTI_Pin_4: GPIO Pin 4
+ * @arg EXTI_Pin_5: GPIO Pin 5
+ * @arg EXTI_Pin_6: GPIO Pin 6
+ * @arg EXTI_Pin_7: GPIO Pin 7
+ * @retval The external interrupt sensitivity of the selected port.
+ */
+EXTI_Trigger_TypeDef EXTI_GetPinSensitivity(EXTI_Pin_TypeDef EXTI_Pin)
+{
+ uint8_t value = 0;
+
+ /* Check function parameters */
+ assert_param(IS_EXTI_PINNUM(EXTI_Pin));
+
+ switch (EXTI_Pin)
+ {
+ case EXTI_Pin_0:
+ value = (uint8_t)(EXTI->CR1 & EXTI_CR1_P0IS);
+ break;
+ case EXTI_Pin_1:
+ value = (uint8_t)((uint8_t)(EXTI->CR1 & EXTI_CR1_P1IS) >> EXTI_Pin_1);
+ break;
+ case EXTI_Pin_2:
+ value = (uint8_t)((uint8_t)(EXTI->CR1 & EXTI_CR1_P2IS) >> EXTI_Pin_2);
+ break;
+ case EXTI_Pin_3:
+ value = (uint8_t)((uint8_t)(EXTI->CR1 & EXTI_CR1_P3IS) >> EXTI_Pin_3);
+ break;
+ case EXTI_Pin_4:
+ value = (uint8_t)(EXTI->CR2 & EXTI_CR2_P4IS);
+ break;
+ case EXTI_Pin_5:
+ value = (uint8_t)((uint8_t)(EXTI->CR2 & EXTI_CR2_P5IS) >> ((uint8_t)EXTI_Pin_5 & (uint8_t)0x0F));
+ break;
+ case EXTI_Pin_6:
+ value = (uint8_t)((uint8_t)(EXTI->CR2 & EXTI_CR2_P6IS) >> ((uint8_t)EXTI_Pin_6 & (uint8_t)0x0F));
+ break;
+ case EXTI_Pin_7:
+ value = (uint8_t)((uint8_t)(EXTI->CR2 & EXTI_CR2_P7IS) >> ((uint8_t)EXTI_Pin_7 & (uint8_t)0x0F));
+ break;
+ default:
+ break;
+ }
+ return((EXTI_Trigger_TypeDef)value);
+}
+
+/**
+ * @brief Gets the external interrupt sensitivity of the selected port.
+ * @param EXTI_Port : The port number to access.
+ * This parameter can be one of the following values:
+ * @arg EXTI_Port_B: GPIO Port B
+ * @arg EXTI_Port_D: GPIO Port D
+ * @arg EXTI_Port_E: GPIO Port E
+ * @arg EXTI_Port_F: GPIO Port F
+ * @arg EXTI_Port_G: GPIO Port G
+ * @arg EXTI_Port_H: GPIO Port H
+ * @retval The external interrupt sensitivity of the selected port.
+ */
+EXTI_Trigger_TypeDef EXTI_GetPortSensitivity(EXTI_Port_TypeDef EXTI_Port)
+{
+ uint8_t portsensitivity = 0;
+
+ /* Check function parameters */
+ assert_param(IS_EXTI_PORT(EXTI_Port));
+
+ /* Check if selected port is in EXTI_CR3 */
+ if ((EXTI_Port & 0xF0) == 0x00)
+ {
+ /* Get port sensitivity */
+ portsensitivity = (uint8_t)((uint8_t)0x03 & (uint8_t)(EXTI->CR3 >> EXTI_Port));
+ }
+ /* selected port is in EXTI_CR4 */
+ else
+ {
+ /* Get port sensitivity */
+ portsensitivity = (uint8_t)((uint8_t)0x03 & (uint8_t)(EXTI->CR4 >> (EXTI_Port & 0x0F)));
+ }
+
+ return((EXTI_Trigger_TypeDef)portsensitivity);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup EXTI_Group2 EXTI Interrupt status management functions
+ * @brief EXTI Interrupt status management functions
+ *
+@verbatim
+ ===============================================================================
+ EXTI Interrupt status management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Gets the external interrupt status.
+ * @param EXTI_IT : Specifies the interrupt to read.
+ * This parameter can be one of the following values:
+ * @arg EXTI_IT_Pin0: GPIO Pin 0
+ * @arg EXTI_IT_Pin1: GPIO Pin 1
+ * @arg EXTI_IT_Pin2: GPIO Pin 2
+ * @arg EXTI_IT_Pin3: GPIO Pin 3
+ * @arg EXTI_IT_Pin4: GPIO Pin 4
+ * @arg EXTI_IT_Pin5: GPIO Pin 5
+ * @arg EXTI_IT_Pin6: GPIO Pin 6
+ * @arg EXTI_IT_Pin7: GPIO Pin 7
+ * @arg EXTI_IT_PortB: GPIO Port B
+ * @arg EXTI_IT_PortD: GPIO Port D
+ * @arg EXTI_IT_PortE: GPIO Port E
+ * @arg EXTI_IT_PortF: GPIO Port F
+ * @arg EXTI_IT_PortG: GPIO Port G
+ * @arg EXTI_IT_PortH: GPIO Port H
+ * @retval The status of the specified interrupt.
+ * This parameter can be a SET or RESET
+ */
+ITStatus EXTI_GetITStatus(EXTI_IT_TypeDef EXTI_IT)
+{
+ ITStatus status = RESET;
+ /* Check function parameters */
+ assert_param(IS_EXTI_ITPENDINGBIT(EXTI_IT));
+
+ if (((uint16_t)EXTI_IT & (uint16_t)0xFF00) == 0x0100)
+ {
+ status = (ITStatus)(EXTI->SR2 & (uint8_t)((uint16_t)EXTI_IT & (uint16_t)0x00FF));
+ }
+ else
+ {
+ status = (ITStatus)(EXTI->SR1 & ((uint8_t)((uint16_t)EXTI_IT & (uint16_t)0x00FF)));
+ }
+ return((ITStatus)status);
+}
+
+/**
+ * @brief Clears the specified interrupt pending bit
+ * @param EXTI_IT : Specifies the interrupt to clear
+ * This parameter can be one of the following values:
+ * @arg EXTI_IT_Pin0: GPIO Pin 0
+ * @arg EXTI_IT_Pin1: GPIO Pin 1
+ * @arg EXTI_IT_Pin2: GPIO Pin 2
+ * @arg EXTI_IT_Pin3: GPIO Pin 3
+ * @arg EXTI_IT_Pin4: GPIO Pin 4
+ * @arg EXTI_IT_Pin5: GPIO Pin 5
+ * @arg EXTI_IT_Pin6: GPIO Pin 6
+ * @arg EXTI_IT_Pin7: GPIO Pin 7
+ * @arg EXTI_IT_PortB: GPIO Port B
+ * @arg EXTI_IT_PortD: GPIO Port D
+ * @arg EXTI_IT_PortE: GPIO Port E
+ * @arg EXTI_IT_PortF: GPIO Port F
+ * @arg EXTI_IT_PortG: GPIO Port G
+ * @arg EXTI_IT_PortH: GPIO Port H
+ * @retval None
+ */
+void EXTI_ClearITPendingBit(EXTI_IT_TypeDef EXTI_IT)
+{
+ uint16_t tempvalue = 0;
+
+ /* Check function parameters */
+ assert_param(IS_EXTI_ITPENDINGBIT(EXTI_IT));
+
+ tempvalue = ((uint16_t)EXTI_IT & (uint16_t)0xFF00);
+
+ if ( tempvalue == 0x0100)
+ {
+ EXTI->SR2 = (uint8_t)((uint16_t)EXTI_IT & (uint16_t)0x00FF);
+ }
+ else
+ {
+ EXTI->SR1 = (uint8_t) (EXTI_IT);
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_flash.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_flash.c
new file mode 100644
index 00000000..d0407e70
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_flash.c
@@ -0,0 +1,929 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_flash.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides all the Flash firmware functions. These functions
+ * can be executed from Internal FLASH or Internal RAM memories.
+ * - FLASH program and Data EEPROM memories interface configuration
+ * - FLASH program and Data EEPROM memories Programming
+ * - Option Bytes Programming
+ * - Interrupts and flags management
+ * - Functions to be executed from RAM
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ *
+ * This driver provides functions to configure and program the Flash
+ * memory of all STM8L15x devices
+ * These functions are split in 4 groups
+ *
+ * 1. FLASH program and Data EEPROM memories interface configuration
+ * functions: this group includes the management of the following
+ * features:
+ * - Set the fixed programming time
+ * - Configure the power state during WFI mode
+ * - Configure the power state during run, low power run and
+ * WFE modes (should be executed from internal RAM)
+ *
+ * 2. FLASH program and Data EEPROM memories Programming functions:
+ * this group includes all needed functions to erase and program
+ * the FLASH program or the Data EEPROM memory.
+ * - Lock and Unlock the Flash program interface.
+ * - Lock and Unlock the Data EEPROM interface.
+ * - Erase function: Erase Byte, Erase Word and Erase Block
+ * (should be executed from internal RAM).
+ * - Program functions: Program Byte, Program Word,
+ * Program Block (should be executed from internal RAM)
+ * and Fast Program Block (should be executed from internal
+ * RAM).
+ *
+ * 3. FLASH Option Bytes Programming functions: this group includes
+ * all needed functions to:
+ * - Program/erase the user option Bytes
+ * - Get the Read Out Protection status (ROP option byte)
+ * - Get the User Boot Code size (UBC option byte)
+ * - Get the Protected Code size (PCODE option byte)
+ *
+ * Note: Option byte programming is very similar to data EEPROM byte
+ * programming.
+ *
+ * 4. FLASH Interrupts and flag management functions: this group
+ * includes all needed functions to:
+ * - Enable/Disable the flash interrupt sources
+ * - Get flags status
+ * - Wait for last flash operation(can be executed from
+ * internal RAM)
+ *
+ * 5. Functions to be executed from RAM: this group includes the functions
+ * that should be executed from RAM and provides description on how
+ * to handle this with the different supported toolchains
+ *
+ * The table below lists the functions that can be executed from RAM.
+ *
+ * +--------------------------------------------------------------------------------|
+ * | Functions prototypes | RAM execution | Comments |
+ * ---------------------------------------------------------------------------------|
+ * | | Mandatory in case of block | Can be executed |
+ * | FLASH_WaitForLastOperation | Operation: | from Flash in case |
+ * | | - Block programming | of byte and word |
+ * | | - Block erase | Operations |
+ * |--------------------------------------------------------------------------------|
+ * | FLASH_PowerRunModeConfig | Exclusively | useless from Flash |
+ * |--------------------------------------------------------------------------------|
+ * | FLASH_GetPowerStatus | Exclusively | useless from Flash |
+ * |--------------------------------------------------------------------------------|
+ * | FLASH_ProgramBlock | Exclusively | useless from Flash |
+ * |--------------------------------------------------------------------------------|
+ * | FLASH_EraseBlock | Exclusively | useless from Flash |
+ * |--------------------------------------------------------------------------------|
+ *
+ * To be able to execute functions from RAM several steps have to be followed.
+ * These steps may differ from one toolchain to another.
+ * A detailed description is available below within this driver.
+ * You can also refer to the Flash_DataProgram example provided within the
+ * STM8L15x_StdPeriph_Lib package.
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_flash.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup FLASH
+ * @brief FLASH driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup FLASH_Private_Define
+ * @{
+ */
+#define FLASH_CLEAR_BYTE ((uint8_t)0x00)
+#define FLASH_SET_BYTE ((uint8_t)0xFF)
+#define OPERATION_TIMEOUT ((uint16_t)0xFFFF)
+/**
+ * @}
+ */
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup FLASH_Private_Functions
+ * @{
+ */
+
+/** @defgroup FLASH_Group1 FLASH program and Data EEPROM memories Interface
+ * configuration functions
+ * @brief FLASH Interface configuration functions
+ *
+@verbatim
+ ===============================================================================
+ FLASH program and Data EEPROM memories interface configuration functions
+ ===============================================================================
+
+ The FLASH program and Data EEPROM memories interface configuration functions,
+ includes the following functions:
+
+ - FLASH_ProgramTime_TypeDef FLASH_GetProgrammingTime(void);
+ - void FLASH_SetProgrammingTime(FLASH_ProgramTime_TypeDef FLASH_ProgTime);
+ - void FLASH_PowerWaitModeConfig(FLASH_Power_TypeDef FLASH_Power);
+
+ These functions don't need the unlock sequence.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Sets the fixed programming time
+ * @param FLASH_ProgTime : Indicates the programming time to be fixed
+ * This parameter can be one of the following values:
+ * @arg FLASH_ProgramTime_Standard: Standard programming time fixed at 1/2 tprog
+ * @arg FLASH_ProgramTime_TProg: Programming time fixed at tprog
+ * @retval None
+ */
+void FLASH_SetProgrammingTime(FLASH_ProgramTime_TypeDef FLASH_ProgTime)
+{
+ /* Check parameter */
+ assert_param(IS_FLASH_PROGRAM_TIME(FLASH_ProgTime));
+
+ FLASH->CR1 &= (uint8_t)(~FLASH_CR1_FIX);
+ FLASH->CR1 |= (uint8_t)FLASH_ProgTime;
+}
+
+/**
+ * @brief Returns the fixed programming time
+ * @param None
+ * @retval Fixed programming time value
+ */
+FLASH_ProgramTime_TypeDef FLASH_GetProgrammingTime(void)
+{
+ return((FLASH_ProgramTime_TypeDef)(FLASH->CR1 & FLASH_CR1_FIX));
+}
+
+/**
+ * @brief Configures the power state for Flash program and data EEPROM during
+ * wait for interrupt mode
+ * @param FLASH_Power: The power state for Flash program and data EEPROM during
+ * wait for interrupt mode
+ * This parameter can be one of the following values:
+ * @arg FLASH_Power_IDDQ: Flash program and data EEPROM in IDDQ
+ * @arg FLASH_Power_On: Flash program and data EEPROM not in IDDQ
+ * @retval None
+ */
+void FLASH_PowerWaitModeConfig(FLASH_Power_TypeDef FLASH_Power)
+{
+ /* Check parameter */
+ assert_param(IS_FLASH_POWER(FLASH_Power));
+
+ /* Flash program and data EEPROM in IDDQ during wait for interrupt mode*/
+ if(FLASH_Power != FLASH_Power_On)
+ {
+ FLASH->CR1 |= (uint8_t)FLASH_CR1_WAITM;
+ }
+ /* Flash program and data EEPROM not in IDDQ during wait for interrupt mode*/
+ else
+ {
+ FLASH->CR1 &= (uint8_t)(~FLASH_CR1_WAITM);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Group2 FLASH Memory Programming functions
+ * @brief FLASH Memory Programming functions
+ *
+@verbatim
+ ===============================================================================
+ FLASH Memory Programming functions
+ ===============================================================================
+
+ The FLASH Memory Programming functions, includes the following functions:
+ - void FLASH_DeInit(void);
+ - void FLASH_Unlock(FLASH_MemType_TypeDef FLASH_MemType);
+ - void FLASH_Lock(FLASH_MemType_TypeDef FLASH_MemType);
+ - void FLASH_ProgramByte(uint32_t Address, uint8_t Data);
+ - void FLASH_EraseByte(uint32_t Address);
+ - void FLASH_ProgramWord(uint32_t Address, uint32_t Data);
+ - uint8_t FLASH_ReadByte(uint32_t Address);
+
+ Any operation of erase or program should follow these steps:
+
+ 1. Call the FLASH_Unlock(FLASH_MemType) function to enable the memory access
+
+ 2. Call the desired function to erase or program data
+
+ 3. Call the FLASH_Lock() function to disable the memory access
+ (it is recommended to protect the FLASH memory against possible unwanted operation)
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the FLASH registers to their default reset values.
+ * @param None
+ * @retval None
+ */
+void FLASH_DeInit(void)
+{
+ FLASH->CR1 = FLASH_CR1_RESET_VALUE;
+ FLASH->CR2 = FLASH_CR2_RESET_VALUE;
+ FLASH->IAPSR = FLASH_IAPSR_RESET_VALUE;
+ (void) FLASH->IAPSR; /* Reading of this register causes the clearing of status flags */
+}
+
+/**
+ * @brief Unlocks the program or data EEPROM memory
+ * @param FLASH_MemType : Memory type to unlock
+ * This parameter can be one of the following values:
+ * @arg FLASH_MemType_Program: Program memory
+ * @arg FLASH_MemType_Data: Data EEPROM memory
+ * @retval None
+ */
+void FLASH_Unlock(FLASH_MemType_TypeDef FLASH_MemType)
+{
+ /* Check parameter */
+ assert_param(IS_FLASH_MEMORY_TYPE(FLASH_MemType));
+
+ /* Unlock program memory */
+ if(FLASH_MemType == FLASH_MemType_Program)
+ {
+ FLASH->PUKR = FLASH_RASS_KEY1;
+ FLASH->PUKR = FLASH_RASS_KEY2;
+ }
+
+ /* Unlock data memory */
+ if(FLASH_MemType == FLASH_MemType_Data)
+ {
+ FLASH->DUKR = FLASH_RASS_KEY2; /* Warning: keys are reversed on data memory !!! */
+ FLASH->DUKR = FLASH_RASS_KEY1;
+ }
+}
+
+/**
+ * @brief Locks the program or data EEPROM memory
+ * @param FLASH_MemType : Memory type
+ * This parameter can be one of the following values:
+ * @arg FLASH_MemType_Program: Program memory
+ * @arg FLASH_MemType_Data: Data EEPROM memory
+ * @retval None
+ */
+void FLASH_Lock(FLASH_MemType_TypeDef FLASH_MemType)
+{
+ /* Check parameter */
+ assert_param(IS_FLASH_MEMORY_TYPE(FLASH_MemType));
+
+ /* Lock memory */
+ FLASH->IAPSR &= (uint8_t)FLASH_MemType;
+}
+
+/**
+ * @brief Programs one byte in program or data EEPROM memory
+ * @param Address : Address where the byte will be programmed
+ * @param Data : Value to be programmed
+ * @retval None
+ */
+void FLASH_ProgramByte(uint32_t Address, uint8_t Data)
+{
+ /* Check parameters */
+ assert_param(IS_FLASH_ADDRESS(Address));
+
+ *(PointerAttr uint8_t*) (MemoryAddressCast)Address = Data;
+}
+
+/**
+ * @brief Erases one byte in the program or data EEPROM memory
+ * @param Address : Address of the byte to erase
+ * @retval None
+ */
+void FLASH_EraseByte(uint32_t Address)
+{
+ /* Check parameter */
+ assert_param(IS_FLASH_ADDRESS(Address));
+
+ *(PointerAttr uint8_t*) (MemoryAddressCast)Address = FLASH_CLEAR_BYTE; /* Erase byte */
+}
+
+/**
+ * @brief Programs one word (4 bytes) in program or data EEPROM memory
+ * @param Address : The address where the data will be programmed
+ * @param Data : Value to be programmed
+ * @retval None
+ */
+void FLASH_ProgramWord(uint32_t Address, uint32_t Data)
+{
+ /* Check parameters */
+ assert_param(IS_FLASH_ADDRESS(Address));
+ /* Enable Word Write Once */
+ FLASH->CR2 |= FLASH_CR2_WPRG;
+
+ /* Write one byte - from lowest address*/
+ *((PointerAttr uint8_t*)(MemoryAddressCast)Address) = *((uint8_t*)(&Data));
+ /* Write one byte*/
+ *(((PointerAttr uint8_t*)(MemoryAddressCast)Address) + 1) = *((uint8_t*)(&Data) + 1);
+ /* Write one byte*/
+ *(((PointerAttr uint8_t*)(MemoryAddressCast)Address) + 2) = *((uint8_t*)(&Data) + 2);
+ /* Write one byte - from higher address*/
+ *(((PointerAttr uint8_t*)(MemoryAddressCast)Address) + 3) = *((uint8_t*)(&Data) + 3);
+}
+
+/**
+ * @brief Reads one byte from flash memory
+ * @param Address : Address to read
+ * @retval Value of the byte
+ */
+uint8_t FLASH_ReadByte(uint32_t Address)
+{
+ /* Read byte */
+ return(*(PointerAttr uint8_t *) (MemoryAddressCast)Address);
+}
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Group3 Option Bytes Programming functions
+ * @brief Option Bytes Programming functions
+ *
+@verbatim
+ ===============================================================================
+ Option Bytes Programming functions
+ ===============================================================================
+
+ The FLASH_Option Bytes Programming_functions, includes the following functions:
+
+ - void FLASH_ProgramOptionByte(uint16_t Address, uint8_t Data);
+ - void FLASH_EraseOptionByte(uint16_t Address);
+ - FunctionalState FLASH_GetReadOutProtectionStatus(void);
+ - uint16_t FLASH_GetBootSize(void);
+ - uint16_t FLASH_GetCodeSize(void);
+
+ Any operation of erase or program should follow these steps:
+
+ 1. Call the FLASH_Unlock(FLASH_MemType_Data); function to enable the Flash
+ option control register access
+
+ 2. Call the desired function to erase or program data
+ - void FLASH_ProgramOptionByte(uint16_t Address, uint8_t Data); => to program
+ the option byte Address with the desired Data value.
+ - void FLASH_EraseOptionByte(uint16_t Address); => to erase the option byte
+ Address.
+
+ 3. Once all needed option bytes to be programmed are correctly written, call the
+ FLASH_Lock(FLASH_MemType_Data) to disable the memory access ( It is recommended to
+ protect the FLASH memory against possible unwanted operation)
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Programs option byte
+ * @param Address : option byte address to program
+ * @param Data : Value to write
+ * @retval None
+ */
+void FLASH_ProgramOptionByte(uint16_t Address, uint8_t Data)
+{
+ /* Check parameter */
+ assert_param(IS_OPTION_BYTE_ADDRESS(Address));
+
+ /* Enable write access to option bytes */
+ FLASH->CR2 |= FLASH_CR2_OPT;
+
+ /* Program option byte and his complement */
+ *((PointerAttr uint8_t*)Address) = Data;
+
+ FLASH_WaitForLastOperation(FLASH_MemType_Program);
+
+ /* Disable write access to option bytes */
+ FLASH->CR2 &= (uint8_t)(~FLASH_CR2_OPT);
+}
+
+/**
+ * @brief Erases option byte
+ * @param Address : Option byte address to erase
+ * @retval None
+ */
+void FLASH_EraseOptionByte(uint16_t Address)
+{
+ /* Check parameter */
+ assert_param(IS_OPTION_BYTE_ADDRESS(Address));
+
+ /* Enable write access to option bytes */
+ FLASH->CR2 |= FLASH_CR2_OPT;
+
+ /* Erase option byte and his complement */
+ *((PointerAttr uint8_t*)Address) = FLASH_CLEAR_BYTE;
+
+ FLASH_WaitForLastOperation(FLASH_MemType_Program);
+
+ /* Disable write access to option bytes */
+ FLASH->CR2 &= (uint8_t)(~FLASH_CR2_OPT);
+}
+
+/**
+ * @brief Returns the FLASH Read Out Protection Status.
+ * @param None
+ * @retval FLASH Read Out Protection Status.
+ * This parameter can be a ENABLE or DISABLE
+ */
+FunctionalState FLASH_GetReadOutProtectionStatus(void)
+{
+ FunctionalState state = DISABLE;
+
+ if(OPT->ROP == FLASH_READOUTPROTECTION_KEY)
+ {
+ /* The status of the Flash read out protection is enabled*/
+ state = ENABLE;
+ }
+ else
+ {
+ /* The status of the Flash read out protection is disabled*/
+ state = DISABLE;
+ }
+
+ return state;
+}
+
+/**
+ * @brief Returns the Boot memory size in bytes
+ * @param None
+ * @retval Boot memory size in bytes
+ */
+uint16_t FLASH_GetBootSize(void)
+{
+ uint16_t temp = 0;
+
+ /* Calculates the number of bytes */
+ temp = (uint16_t)((uint16_t)OPT->UBC * (uint16_t)128);
+
+ /* Correction because size upper 8kb doesn't exist */
+ if(OPT->UBC > 0x7F)
+ {
+ temp = 8192;
+ }
+
+ /* Return value */
+ return(temp);
+}
+
+/**
+ *
+ * @brief Returns the Code Area size in bytes
+ * @param None
+ * @retval Code Area size in bytes
+ */
+uint16_t FLASH_GetCodeSize(void)
+{
+ uint16_t temp = 0;
+
+ /* Calculates the number of bytes */
+ temp = (uint16_t)((uint16_t)OPT->PCODESIZE * (uint16_t)128);
+
+ /* Correction because size upper of 8kb doesn't exist */
+ if(OPT->PCODESIZE > 0x7F)
+ {
+ temp = 8192;
+ }
+
+ /* Return value */
+ return(temp);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Group4 Interrupts and flags management functions
+ * @brief Interrupts and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts and flags management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or Disables the Flash interrupt mode
+ * @param NewState : The new state of the flash interrupt mode
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void FLASH_ITConfig(FunctionalState NewState)
+{
+ /* Check parameter */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if(NewState != DISABLE)
+ {
+ /* Enables the interrupt sources */
+ FLASH->CR1 |= FLASH_CR1_IE;
+ }
+ else
+ {
+ /* Disables the interrupt sources */
+ FLASH->CR1 &= (uint8_t)(~FLASH_CR1_IE);
+ }
+}
+
+/**
+ * @brief Checks whether the specified FLASH flag is set or not.
+ * @param FLASH_FLAG : specifies the Flash Flag to check.
+ * This parameter can be one of the following values:
+ * @arg FLASH_FLAG_HVOFF: End of high voltage
+ * @arg FLASH_FLAG_DUL: Data EEPROM unlocked
+ * @arg FLASH_FLAG_EOP: End of programming (write or erase operation)
+ * @arg FLASH_FLAG_PUL: Flash Program memory unlocked
+ * @arg FLASH_FLAG_WR_PG_DIS: Write attempted to protected page
+ * @retval Indicates the state of the Flash_FLAG.
+ * This parameter can be SET or RESET
+ */
+FlagStatus FLASH_GetFlagStatus(FLASH_FLAG_TypeDef FLASH_FLAG)
+{
+ FlagStatus status = RESET;
+ assert_param(IS_FLASH_FLAGS(FLASH_FLAG));
+
+ /* Check the status of the specified flash flag*/
+ if((FLASH->IAPSR & (uint8_t)FLASH_FLAG) != (uint8_t)RESET)
+ {
+ status = SET; /* Flash_FLAG is set*/
+ }
+ else
+ {
+ status = RESET; /* Flash_FLAG is reset*/
+ }
+
+ /* Return the Flash_FLAG status*/
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Group5 Functions to be executed from RAM
+ * @brief Functions to be executed from RAM
+ *
+@verbatim
+ ===============================================================================
+ Functions to be executed from RAM
+ ===============================================================================
+
+ All the functions defined below must be executed from RAM exclusively, except
+ for the FLASH_WaitForLastOperation function which can be executed from Flash.
+
+ Steps of the execution from RAM differs from one toolchain to another:
+ - For Cosmic Compiler:
+ 1- Define a segment FLASH_CODE by the mean of " #pragma section (FLASH_CODE)".
+ This segment is defined in the stm8l15x_flash.c file.
+ 2- Uncomment the "#define RAM_EXECUTION (1)" line in the stm8l15x.h file,
+ or define it in Cosmic compiler preprocessor to enable the FLASH_CODE segment
+ definition.
+ 3- In STVD Select Project\Settings\Linker\Category "input" and in the RAM section
+ add the FLASH_CODE segment with "-ic" options.
+ 4- In main.c file call the _fctcpy() function with first segment character as
+ parameter "_fctcpy('F');" to load the declared moveable code segment
+ (FLASH_CODE) in RAM before execution.
+ 5- By default the _fctcpy function is packaged in the Cosmic machine library,
+ so the function prototype "int _fctcopy(char name);" must be added in main.c
+ file.
+
+ - For Raisonance Compiler
+ 1- Use the inram keyword in the function declaration to specify that it can be
+ executed from RAM.
+ This is done within the stm8l15x_flash.c file, and it's conditioned by
+ RAM_EXECUTION definition.
+ 2- Uncomment the "#define RAM_EXECUTION (1)" line in the stm8l15x.h file, or
+ define it in Raisonance compiler preprocessor to enable the access for the
+ inram functions.
+ 3- An inram function code is copied from Flash to RAM by the C startup code.
+ In some applications, the RAM area where the code was initially stored may be
+ erased or corrupted, so it may be desirable to perform the copy again.
+ Depending on the application memory model, the memcpy() or fmemcpy() functions
+ should be used to perform the copy.
+ • In case your project uses the SMALL memory model (code smaller than 64K),
+ memcpy()function is recommended to perform the copy
+ • In case your project uses the LARGE memory model, functions can be
+ everywhere in the 24-bits address space (not limited to the first 64KB of
+ code), In this case, the use of memcpy() function will not be appropriate,
+ you need to use the specific fmemcpy() function (which copies objects with
+ 24-bit addresses).
+ - The linker automatically defines 2 symbols for each inram function:
+ • __address__functionname is a symbol that holds the Flash address
+ where the given function code is stored.
+ • __size__functionname is a symbol that holds the function size in bytes.
+ And we already have the function address (which is itself a pointer)
+ 4- In main.c file these two steps should be performed for each inram function:
+ • Import the "__address__functionname" and "__size__functionname" symbols
+ as global variables:
+ extern int __address__functionname; // Symbol holding the flash address
+ extern int __size__functionname; // Symbol holding the function size
+ • In case of SMALL memory model use, Call the memcpy() function to copy the
+ inram function to the RAM destination address:
+ memcpy(functionname, // RAM destination address
+ (void*)&__address__functionname, // Flash source address
+ (int)&__size__functionname); // Code size of the function
+ • In case of LARGE memory model use, call the fmemcpy() function to copy
+ the inram function to the RAM destination address:
+ memcpy(functionname, // RAM destination address
+ (void @far*)&__address__functionname, // Flash source address
+ (int)&__size__functionname); // Code size of the function
+
+ - For IAR Compiler:
+ 1- Use the __ramfunc keyword in the function declaration to specify that it
+ can be executed from RAM.
+ This is done within the stm8l15x_flash.c file, and it's conditioned by
+ RAM_EXECUTION definition.
+ 2- Uncomment the "#define RAM_EXECUTION (1)" line in the stm8l15x.h file, or
+ define it in IAR compiler preprocessor to enable the access for the
+ __ramfunc functions.
+
+ - Note:
+ 1- Ignore the IAR compiler warnings, these warnings don't impact the FLASH Program/Erase
+ operations.
+ The code performing the Flash Program/erase must be executed from RAM; the variables
+ initializations don't necessary require the execution from RAM, only CR2 registers
+ configuration and data programing must be executed from RAM.
+ 2- These warnings depends on IAR compiler: as the code generation is made using many
+ runtime library functions to keep code size to a minimum.
+ 3- It is recommended to use High Speed Optimization with IAR (-Ohs), in order
+ to reduce the runtime library calls in the generated code.
+
+ The Flash_DataProgram example provided within the STM8L15x_StdPeriph_Lib package
+ details all the steps described above.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief
+ *******************************************************************************
+ * Execution from RAM enable
+ *******************************************************************************
+ *
+ * To enable execution from RAM you can either uncomment the following define
+ * in the stm8l15x.h file or define it in your toolchain compiler preprocessor
+ * - #define RAM_EXECUTION (1)
+ */
+
+#if defined (_COSMIC_) && defined (RAM_EXECUTION)
+ #pragma section (FLASH_CODE)
+#endif /* _COSMIC_ && RAM_EXECUTION */
+
+/**
+ * @brief Configures the power state for Flash program and data EEPROM during
+ * run, low power run and low power wait modes
+ * @note This function must be called and executed from RAM.
+ * @param FLASH_Power: power state of the Flash program and data EEPROM
+ * This parameter can be one of the following values:
+ * @arg FLASH_Power_IDDQ: Flash program and data EEPROM in IDDQ
+ * @arg FLASH_Power_On: Flash program and data EEPROM not in IDDQ
+ * @retval None
+ */
+IN_RAM(void FLASH_PowerRunModeConfig(FLASH_Power_TypeDef FLASH_Power))
+{
+ /* Check parameter */
+ assert_param(IS_FLASH_POWER(FLASH_Power));
+
+ if(FLASH_Power != FLASH_Power_On)
+ {
+ FLASH->CR1 |= (uint8_t)FLASH_CR1_EEPM;
+ }
+ else
+ {
+ FLASH->CR1 &= (uint8_t)(~FLASH_CR1_EEPM);
+ }
+}
+
+/**
+ * @brief Checks the power status for Flash program and data EEPROM
+ * @note This function should be called and executed from RAM.
+ * @param None
+ * @retval Flash program and data EEPROM power status
+ * The returned value can be one of the following:
+ * - FLASH_PowerStatus_IDDQDuringWaitMode: IDDQ during Wait mode
+ * - FLASH_PowerStatus_IDDQDuringRunMode: IDDQ during Run mode
+ * - FLASH_PowerStatus_IDDQDuringWaitAndRunModes: IDDQ during Wait/Run mode
+ * - FLASH_PowerStatus_On: Powered on during Wait and Run modes
+ */
+IN_RAM(FLASH_PowerStatus_TypeDef FLASH_GetPowerStatus(void))
+{
+ return((FLASH_PowerStatus_TypeDef)(FLASH->CR1 & (uint8_t)0x0C));
+}
+
+/**
+ * @brief Programs a memory block
+ * @note This function should be called and executed from RAM.
+ * @param FLASH_MemType : The type of memory to program
+ * This parameter can be one of the following values:
+ * @arg FLASH_MemType_Program: Program memory
+ * @arg FLASH_MemType_Data: Data EEPROM memory
+ * @param BlockNum : The block number
+ * @param FLASH_ProgMode : The programming mode.
+ * This parameter can be one of the following values:
+ * @arg FLASH_ProgramMode_Standard: Standard programming mode
+ * @arg FLASH_ProgramMode_Fast: Fast programming mode
+ * @param Buffer : Pointer to buffer containing source data.
+ * @retval None.
+ */
+IN_RAM(void FLASH_ProgramBlock(uint16_t BlockNum, FLASH_MemType_TypeDef FLASH_MemType,
+ FLASH_ProgramMode_TypeDef FLASH_ProgMode, uint8_t *Buffer))
+{
+ uint16_t Count = 0;
+ uint32_t startaddress = 0;
+
+ /* Check parameters */
+ assert_param(IS_FLASH_MEMORY_TYPE(FLASH_MemType));
+ assert_param(IS_FLASH_PROGRAM_MODE(FLASH_ProgMode));
+ if(FLASH_MemType == FLASH_MemType_Program)
+ {
+ assert_param(IS_FLASH_PROGRAM_BLOCK_NUMBER(BlockNum));
+ startaddress = FLASH_PROGRAM_START_PHYSICAL_ADDRESS;
+ }
+ else
+ {
+ assert_param(IS_FLASH_DATA_EEPROM_BLOCK_NUMBER(BlockNum));
+ startaddress = FLASH_DATA_EEPROM_START_PHYSICAL_ADDRESS;
+ }
+
+ /* Point to the first block address */
+ startaddress = startaddress + ((uint32_t)BlockNum * FLASH_BLOCK_SIZE);
+
+ /* Selection of Standard or Fast programming mode */
+ if(FLASH_ProgMode == FLASH_ProgramMode_Standard)
+ {
+ /* Standard programming mode */
+ FLASH->CR2 |= FLASH_CR2_PRG;
+ }
+ else
+ {
+ /* Fast programming mode */
+ FLASH->CR2 |= FLASH_CR2_FPRG;
+ }
+
+ /* Copy data bytes from RAM to FLASH memory */
+ for(Count = 0; Count < FLASH_BLOCK_SIZE; Count++)
+ {
+ *((PointerAttr uint8_t*) (MemoryAddressCast)startaddress + Count) = ((uint8_t)(Buffer[Count]));
+ }
+}
+
+/**
+ * @brief Erases a block in the program or data memory.
+ * @note This function should be called and executed from RAM.
+ * @param BlockNum : Indicates the block number to erase
+ * @param FLASH_MemType : The type of memory to erase
+ * This parameter can be one of the following values:
+ * @arg FLASH_MemType_Program: Program memory
+ * @arg FLASH_MemType_Data: Data EEPROM memory
+ * @retval None.
+ */
+IN_RAM(void FLASH_EraseBlock(uint16_t BlockNum, FLASH_MemType_TypeDef FLASH_MemType))
+{
+ uint32_t startaddress = 0;
+#if defined (STM8L15X_MD) || defined (STM8L15X_MDP) || defined (STM8L15X_LD) || \
+ defined (STM8L05X_LD_VL) || defined (STM8L05X_MD_VL) || defined (STM8AL31_L_MD)
+ uint32_t PointerAttr *pwFlash;
+
+#elif defined (STM8L15X_HD) || defined (STM8L05X_HD_VL)
+ uint8_t PointerAttr *pwFlash;
+#endif
+
+ /* Check parameters */
+ assert_param(IS_FLASH_MEMORY_TYPE(FLASH_MemType));
+ if(FLASH_MemType == FLASH_MemType_Program)
+ {
+ assert_param(IS_FLASH_PROGRAM_BLOCK_NUMBER(BlockNum));
+ startaddress = FLASH_PROGRAM_START_PHYSICAL_ADDRESS;
+ }
+ else
+ {
+ assert_param(IS_FLASH_DATA_EEPROM_BLOCK_NUMBER(BlockNum));
+ startaddress = FLASH_DATA_EEPROM_START_PHYSICAL_ADDRESS;
+ }
+
+ /* Point to the first block address */
+#if defined (STM8L15X_MD) || defined (STM8L15X_MDP)|| defined (STM8L15X_LD) || \
+ defined (STM8L05X_LD_VL) || defined (STM8L05X_MD_VL) || defined (STM8AL31_L_MD)
+ pwFlash = (PointerAttr uint32_t *)(uint16_t)(startaddress + ((uint32_t)BlockNum * FLASH_BLOCK_SIZE));
+
+#elif defined (STM8L15X_HD) || defined (STM8L05X_HD_VL)
+ pwFlash = (PointerAttr uint8_t *)(uint32_t)(startaddress + ((uint32_t)BlockNum * FLASH_BLOCK_SIZE));
+#endif
+
+ /* Enable erase block mode */
+ FLASH->CR2 |= FLASH_CR2_ERASE;
+
+#if defined (STM8L15X_MD) || defined (STM8L15X_MDP) || defined (STM8L15X_LD) || \
+ defined (STM8L05X_LD_VL) || defined (STM8L05X_MD_VL) || defined (STM8AL31_L_MD)
+ *pwFlash = (uint32_t)0;
+
+#elif defined (STM8L15X_HD) || defined (STM8L05X_HD_VL)
+ *pwFlash = (uint8_t)0;
+ *(pwFlash + 1) = (uint8_t)0;
+ *(pwFlash + 2) = (uint8_t)0;
+ *(pwFlash + 3) = (uint8_t)0;
+#endif
+}
+
+/**
+ * @brief Waits for a Flash operation to complete.
+ * @note The call and execution of this function must be done from RAM in case
+ * of Block operation, otherwise it can be executed from Flash
+ * @param FLASH_MemType : Memory type
+ * This parameter can be one of the following values:
+ * @arg FLASH_MemType_Program: Program memory
+ * @arg FLASH_MemType_Data: Data EEPROM memory
+ * @retval FLASH status
+ */
+IN_RAM(FLASH_Status_TypeDef FLASH_WaitForLastOperation(FLASH_MemType_TypeDef FLASH_MemType))
+{
+ uint16_t timeout = OPERATION_TIMEOUT;
+ uint8_t flagstatus = 0x00;
+
+ /* Wait until operation completion or write protected page occurred */
+ if(FLASH_MemType == FLASH_MemType_Program)
+ {
+ while((flagstatus == 0x00) && (timeout != 0x00))
+ {
+ flagstatus = (uint8_t)(FLASH->IAPSR & (uint8_t)(FLASH_IAPSR_EOP |
+ FLASH_IAPSR_WR_PG_DIS));
+ timeout--;
+ }
+ }
+ else
+ {
+ while((flagstatus == 0x00) && (timeout != 0x00))
+ {
+ flagstatus = (uint8_t)(FLASH->IAPSR & (uint8_t)(FLASH_IAPSR_HVOFF |
+ FLASH_IAPSR_WR_PG_DIS));
+ timeout--;
+ }
+ }
+
+ if(timeout == 0x00)
+ {
+ flagstatus = FLASH_Status_TimeOut;
+ }
+
+ return((FLASH_Status_TypeDef)flagstatus);
+}
+
+#if defined (_COSMIC_) && defined (RAM_EXECUTION)
+ /* End of FLASH_CODE section */
+ #pragma section ()
+#endif /* _COSMIC_ && RAM_EXECUTION */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+ /**
+ * @}
+ */
+
+ /**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
\ No newline at end of file
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_gpio.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_gpio.c
new file mode 100644
index 00000000..f264d599
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_gpio.c
@@ -0,0 +1,410 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_gpio.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the GPIO peripheral:
+ * - Initialization and Configuration
+ * - GPIO Read and Write
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * 1. Configure the GPIO pin(s) using GPIO_Init()
+ * Two main configuration are available for each pin:
+ * - Input: Floating
+ * Pull-up.
+ * In Input mode, external interrupt can be enabled or disabled
+ * - Output: Push-Pull
+ * Open Drain.
+ * In output mode, the GPIO pin speed is configurable:
+ * Slow (2 MHz) or Fast (10MHz).
+ *
+ * 2. To get the level of a pin configured in input mode use GPIO_ReadInputDataBit()
+ *
+ * 3. To set/reset GPIO pins sharing the same GPIO port use
+ * GPIO_SetBits() / GPIO_ResetBits()
+ *
+ * 4. To enable external interrupt, the GPIO pin must be configured
+ * in input mode with interrupt enabled. Interrupt sensitivity
+ * (rising, falling...) is configurable using
+ * EXTI_SetPinSensitivity() in the EXTI peripheral driver "stm8l15x_exti.c"
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_gpio.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup CLK
+ * @brief CLK driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup GPIO_Private_Functions
+ * @{
+ */
+
+
+/** @defgroup GPIO_Group1 Initialization and Configuration
+ * @brief Initialization and Configuration
+ *
+@verbatim
+ ===============================================================================
+ Initialization and Configuration
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the GPIOx peripheral registers to their default reset values.
+ * @param GPIOx: Select the GPIO peripheral number (x = A to I).
+ * @retval None
+ */
+void GPIO_DeInit(GPIO_TypeDef* GPIOx)
+{
+ GPIOx->CR2 = GPIO_CR2_RESET_VALUE; /* Reset Control Register 2 */
+ GPIOx->ODR = GPIO_ODR_RESET_VALUE; /* Reset Output Data Register */
+ GPIOx->DDR = GPIO_DDR_RESET_VALUE; /* Reset Data Direction Register */
+ GPIOx->CR1 = GPIO_CR1_RESET_VALUE; /* Reset Control Register 1 */
+}
+
+/**
+ * @brief Initializes the GPIOx according to the specified parameters.
+ * @param GPIOx : Select the GPIO peripheral number (x = A to I).
+ * @param GPIO_Pin : This parameter contains the pin number
+ * This parameter can be one of the following values:
+ * @arg GPIO_Pin_0: Pin 0
+ * @arg GPIO_Pin_1: Pin 1
+ * @arg GPIO_Pin_2: Pin 2
+ * @arg GPIO_Pin_3: Pin 3
+ * @arg GPIO_Pin_4: Pin 4
+ * @arg GPIO_Pin_5: Pin 5
+ * @arg GPIO_Pin_6: Pin 6
+ * @arg GPIO_Pin_7: Pin 7
+ * @param GPIO_Mode : This parameter can be a value of the
+ * This parameter can be one of the following values:
+ * @arg GPIO_Mode_In_FL_No_IT: Input floating, no external interrupt
+ * @arg GPIO_Mode_In_PU_No_IT: Input pull-up, no external interrupt
+ * @arg GPIO_Mode_In_FL_IT: Input pull-up, external interrupt
+ * @arg GPIO_Mode_Out_OD_Low_Fast: Output open-drain, low level, 10MHz
+ * @arg GPIO_Mode_Out_PP_Low_Fast: Output push-pull, low level, 10MHz
+ * @arg GPIO_Mode_Out_OD_Low_Slow: Output open-drain, low level, 2MHz
+ * @arg GPIO_Mode_Out_PP_Low_Slow: Output push-pull, low level, 2MHz
+ * @arg GPIO_Mode_Out_OD_HiZ_Fast: Output open-drain, high-impedance level, 10MHz
+ * @arg GPIO_Mode_Out_PP_High_Fast: Output push-pull, high level, 10MHz
+ * @arg GPIO_Mode_Out_OD_HiZ_Slow: Output open-drain, high-impedance level, 2MHz
+ * @arg GPIO_Mode_Out_PP_High_Slow: Output push-pull, high level, 2MHz
+ * @retval None
+ */
+
+void GPIO_Init(GPIO_TypeDef* GPIOx, uint8_t GPIO_Pin, GPIO_Mode_TypeDef GPIO_Mode)
+{
+ /*----------------------*/
+ /* Check the parameters */
+ /*----------------------*/
+
+ assert_param(IS_GPIO_MODE(GPIO_Mode));
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ /* Reset corresponding bit to GPIO_Pin in CR2 register */
+ GPIOx->CR2 &= (uint8_t)(~(GPIO_Pin));
+
+ /*-----------------------------*/
+ /* Input/Output mode selection */
+ /*-----------------------------*/
+
+ if ((((uint8_t)(GPIO_Mode)) & (uint8_t)0x80) != (uint8_t)0x00) /* Output mode */
+ {
+ if ((((uint8_t)(GPIO_Mode)) & (uint8_t)0x10) != (uint8_t)0x00) /* High level */
+ {
+ GPIOx->ODR |= GPIO_Pin;
+ } else /* Low level */
+ {
+ GPIOx->ODR &= (uint8_t)(~(GPIO_Pin));
+ }
+ /* Set Output mode */
+ GPIOx->DDR |= GPIO_Pin;
+ } else /* Input mode */
+ {
+ /* Set Input mode */
+ GPIOx->DDR &= (uint8_t)(~(GPIO_Pin));
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Pull-Up/Float (Input) or Push-Pull/Open-Drain (Output) modes selection */
+ /*------------------------------------------------------------------------*/
+
+ if ((((uint8_t)(GPIO_Mode)) & (uint8_t)0x40) != (uint8_t)0x00) /* Pull-Up or Push-Pull */
+ {
+ GPIOx->CR1 |= GPIO_Pin;
+ } else /* Float or Open-Drain */
+ {
+ GPIOx->CR1 &= (uint8_t)(~(GPIO_Pin));
+ }
+
+ /*-----------------------------------------------------*/
+ /* Interrupt (Input) or Slope (Output) modes selection */
+ /*-----------------------------------------------------*/
+
+ if ((((uint8_t)(GPIO_Mode)) & (uint8_t)0x20) != (uint8_t)0x00) /* Interrupt or Slow slope */
+ {
+ GPIOx->CR2 |= GPIO_Pin;
+ } else /* No external interrupt or No slope control */
+ {
+ GPIOx->CR2 &= (uint8_t)(~(GPIO_Pin));
+ }
+
+}
+
+/**
+ * @brief Configures the external pull-up on GPIOx pins.
+ * @param GPIOx : Select the GPIO peripheral number (x = A to I).
+ * @param GPIO_Pin : Specifies the pin number
+ * This parameter can be one of the following values:
+ * @arg GPIO_Pin_0: Pin 0
+ * @arg GPIO_Pin_1: Pin 1
+ * @arg GPIO_Pin_2: Pin 2
+ * @arg GPIO_Pin_3: Pin 3
+ * @arg GPIO_Pin_4: Pin 4
+ * @arg GPIO_Pin_5: Pin 5
+ * @arg GPIO_Pin_6: Pin 6
+ * @arg GPIO_Pin_7: Pin 7
+ * @param NewState : The new state of the pull up pin.
+ * Can be ENABLE or DISABLE
+ * @retval None
+ */
+void GPIO_ExternalPullUpConfig(GPIO_TypeDef* GPIOx, uint8_t GPIO_Pin, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE) /* External Pull-Up Set*/
+ {
+ GPIOx->CR1 |= GPIO_Pin;
+ } else /* External Pull-Up Reset*/
+ {
+ GPIOx->CR1 &= (uint8_t)(~(GPIO_Pin));
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup GPIO_Group2 GPIO Read and Write
+ * @brief GPIO Read and Write
+ *
+@verbatim
+ ===============================================================================
+ GPIO Read and Write
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Writes data to the specified GPIO data port.
+ * @note The port must be configured in output mode.
+ * @param GPIOx : Select the GPIO peripheral number (x = A to I).
+ * @param GPIO_PortVal : Specifies the value to be written to the port output
+ * data register.
+ * @retval None
+ */
+void GPIO_Write(GPIO_TypeDef* GPIOx, uint8_t GPIO_PortVal)
+{
+ GPIOx->ODR = GPIO_PortVal;
+}
+
+/**
+ * @brief Sets or clears the selected data port bit.
+ * @param GPIOx : Select the GPIO peripheral number (x = A to I).
+ * @param GPIO_Pin: Specifies the port bit to be written.
+ * This parameter can be one of the following values:
+ * @arg GPIO_Pin_0: Pin 0
+ * @arg GPIO_Pin_1: Pin 1
+ * @arg GPIO_Pin_2: Pin 2
+ * @arg GPIO_Pin_3: Pin 3
+ * @arg GPIO_Pin_4: Pin 4
+ * @arg GPIO_Pin_5: Pin 5
+ * @arg GPIO_Pin_6: Pin 6
+ * @arg GPIO_Pin_7: Pin 7
+ * @param GPIO_BitVal: specifies the desired status to be written.
+ * This parameter can be SET or RESET
+ * @retval None
+ */
+void GPIO_WriteBit(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin, BitAction GPIO_BitVal)
+{
+ /* Check the parameters */
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+ assert_param(IS_STATE_VALUE(GPIO_BitVal));
+
+ if (GPIO_BitVal != RESET)
+ {
+ GPIOx->ODR |= GPIO_Pin;
+
+ }
+ else
+ {
+ GPIOx->ODR &= (uint8_t)(~GPIO_Pin);
+ }
+}
+
+/**
+ * @brief Writes high level to the specified GPIO pins.
+ * @note The port must be configured in output mode.
+ * @param GPIOx : Select the GPIO peripheral number (x = A to I).
+ * @param GPIO_Pin : Specifies the pins to be turned high.
+ * This parameter can be one of the following values:
+ * @arg GPIO_Pin_0: Pin 0
+ * @arg GPIO_Pin_1: Pin 1
+ * @arg GPIO_Pin_2: Pin 2
+ * @arg GPIO_Pin_3: Pin 3
+ * @arg GPIO_Pin_4: Pin 4
+ * @arg GPIO_Pin_5: Pin 5
+ * @arg GPIO_Pin_6: Pin 6
+ * @arg GPIO_Pin_7: Pin 7
+ * @retval None
+ */
+void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint8_t GPIO_Pin)
+{
+ GPIOx->ODR |= GPIO_Pin;
+}
+
+/**
+ * @brief Writes low level to the specified GPIO pins.
+ * @note The port must be configured in output mode.
+ * @param GPIOx : Select the GPIO peripheral number (x = A to I).
+ * @param GPIO_Pin : Specifies the pins to be turned low
+ * This parameter can be one of the following values:
+ * @arg GPIO_Pin_0: Pin 0
+ * @arg GPIO_Pin_1: Pin 1
+ * @arg GPIO_Pin_2: Pin 2
+ * @arg GPIO_Pin_3: Pin 3
+ * @arg GPIO_Pin_4: Pin 4
+ * @arg GPIO_Pin_5: Pin 5
+ * @arg GPIO_Pin_6: Pin 6
+ * @arg GPIO_Pin_7: Pin 7
+ * @retval None
+ */
+void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint8_t GPIO_Pin)
+{
+ GPIOx->ODR &= (uint8_t)(~GPIO_Pin);
+}
+
+/**
+ * @brief Toggles the specified GPIO pins.
+ * @note The port must be configured in output mode.
+ * @param GPIOx : Select the GPIO peripheral number (x = A to I).
+ * @param GPIO_Pin : Specifies the pins to be toggled.
+ * @retval None
+ */
+void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint8_t GPIO_Pin)
+{
+ GPIOx->ODR ^= GPIO_Pin;
+}
+
+/**
+ * @brief Reads the specified GPIO input data port.
+ * @note The port must be configured in input mode.
+ * @param GPIOx : Select the GPIO peripheral number (x = A to I).
+ * @retval The GPIOx input data port value.
+ */
+uint8_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
+{
+ return ((uint8_t)GPIOx->IDR);
+}
+
+/**
+ * @brief Reads the specified GPIO output data port.
+ * @note The port must be configured in input mode.
+ * @param GPIOx : Select the GPIO peripheral number (x = A to I).
+ * @retval The GPIOx output data port value.
+ */
+uint8_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
+{
+ return ((uint8_t)GPIOx->ODR);
+}
+
+/**
+ * @brief Reads the specified GPIO input data pin.
+ * @param GPIOx : Select the GPIO peripheral number (x = A to I).
+ * @param GPIO_Pin : Specifies the pin number.
+ * This parameter can be one of the following values:
+ * @arg GPIO_Pin_0: Pin 0
+ * @arg GPIO_Pin_1: Pin 1
+ * @arg GPIO_Pin_2: Pin 2
+ * @arg GPIO_Pin_3: Pin 3
+ * @arg GPIO_Pin_4: Pin 4
+ * @arg GPIO_Pin_5: Pin 5
+ * @arg GPIO_Pin_6: Pin 6
+ * @arg GPIO_Pin_7: Pin 7
+ * @retval BitStatus : GPIO input pin status.
+ */
+BitStatus GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin)
+{
+ return ((BitStatus)(GPIOx->IDR & (uint8_t)GPIO_Pin));
+}
+
+/**
+ * @brief Reads the specified GPIO Output data pin.
+ * @param GPIOx : Select the GPIO peripheral number (x = A to I).
+ * @param GPIO_Pin : Specifies the pin number
+ * @retval BitStatus : GPIO output pin status.
+ */
+BitStatus GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin)
+{
+ return ((BitStatus)(GPIOx->ODR & (uint8_t)GPIO_Pin));
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_i2c.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_i2c.c
new file mode 100644
index 00000000..1c2cd881
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_i2c.c
@@ -0,0 +1,1369 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_i2c.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Inter-integrated circuit (I2C)
+ * - Initialization and Configuration
+ * - Data transfers
+ * - PEC management
+ * - DMA transfers management
+ * - Interrupts, events and flags management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * 1. Enable peripheral clock using CLK_PeripheralClockConfig(CLK_Peripheral_I2Cx,
+ * ENABLE) function (Refer to the product datasheet for the available I2C
+ * peripherals)
+ *
+ *
+ * 2. Program the Mode, duty cycle , Own address, Ack, Speed and Acknowledged
+ * Address using the I2C_Init() function.
+ *
+ * 3. Optionally you can enable/configure the following parameters without
+ * re-initialization (i.e there is no need to call again I2C_Init() function):
+ * - Enable the acknowledge feature using I2C_AcknowledgeConfig() function
+ * - Enable the dual addressing mode using I2C_DualAddressCmd() function
+ * - Enable the general call using the I2C_GeneralCallCmd() function
+ * - Enable the clock stretching using I2C_StretchClockCmd() function
+ * - Enable the fast mode duty cycle using the I2C_FastModeDutyCycleConfig()
+ * function
+ * - Enable the PEC Calculation using I2C_CalculatePEC() function
+ * - For SMBus Mode:
+ * - Enable the Address Resolution Protocol (ARP) using I2C_ARPCmd() function
+ * - Configure the SMBusAlert pin using I2C_SMBusAlertConfig() function
+ *
+ * 4. Enable the interrupt using the function I2C_ITConfig() if you need
+ * to use interrupt mode.
+ *
+ * 5. When using the DMA mode
+ * - Configure the DMA using DMA_Init() function
+ * - Active the needed channel Request using I2C_DMACmd() or
+ * I2C_DMALastTransferCmd() function
+ * Note: When using DMA mode, I2C interrupts may be used at the same time to
+ * control the communication flow (Start/Stop/Ack... events and errors).
+ *
+ * 6. Enable the I2C using the I2C_Cmd() function.
+ *
+ * 7. Enable the DMA using the DMA_Cmd() function when using DMA mode in the
+ * transfers.
+ *
+ * Note: The external Pull-up resistors must be connected on SDA and SCL.
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_i2c.h"
+#include "stm8l15x_clk.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup I2C
+ * @brief I2C driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup I2C_Private_Define
+ * @{
+ */
+
+/* I2C register mask */
+#define REGISTER_Mask ((uint16_t)0x3000)
+#define REGISTER_SR1_Index ((uint16_t)0x0100)
+#define REGISTER_SR2_Index ((uint16_t)0x0200)
+/* I2C Interrupt Enable mask */
+#define ITEN_Mask ((uint16_t)0x0700)
+/* I2C FLAG mask */
+#define FLAG_Mask ((uint16_t)0x00FF)
+/* I2C ADD0 mask */
+#define OAR1_ADD0_Set ((uint8_t)0x01)
+#define OAR1_ADD0_Reset ((uint8_t)0xFE)
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup I2C_Private_Functions
+ * @{
+ */
+
+/** @defgroup I2C_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Initialization and Configuration functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the I2C peripheral registers to their default reset values.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @retval None
+ */
+void I2C_DeInit(I2C_TypeDef* I2Cx)
+{
+ I2Cx->CR1 = I2C_CR1_RESET_VALUE;
+ I2Cx->CR2 = I2C_CR2_RESET_VALUE;
+ I2Cx->FREQR = I2C_FREQR_RESET_VALUE;
+ I2Cx->OARL = I2C_OARL_RESET_VALUE;
+ I2Cx->OARH = I2C_OARH_RESET_VALUE;
+ I2Cx->OAR2 = I2C_OAR2_RESET_VALUE;
+ I2Cx->ITR = I2C_ITR_RESET_VALUE;
+ I2Cx->CCRL = I2C_CCRL_RESET_VALUE;
+ I2Cx->CCRH = I2C_CCRH_RESET_VALUE;
+ I2Cx->TRISER = I2C_TRISER_RESET_VALUE;
+}
+
+/**
+ * @brief Initializes the I2C according to the specified parameters in standard
+ * or fast mode.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param OutputClockFrequency: Specifies the output clock frequency in Hz.
+ * @param OwnAddress: Specifies the own address.
+ * @param I2C_Mode: Specifies the addressing mode to apply.
+ * This parameter can be one of the following values:
+ * @arg I2C_Mode_I2C: I2C mode
+ * @arg I2C_Mode_SMBusDevice: SMBus Device mode
+ * @arg I2C_Mode_SMBusHost: SMBus Host mode
+ * @param I2C_DutyCycle: Specifies the duty cycle to apply in fast mode.
+ * This parameter can be one of the following values:
+ * @arg I2C_DutyCycle_2: I2C fast mode Tlow/Thigh = 2
+ * @arg I2C_DutyCycle_16_9: I2C fast mode Tlow/Thigh = 16/9
+ * @note The I2C_DutyCycle parameter doesn't have impact when the OutputClockFrequency
+ * is lower than 100KHz.
+ * @param I2C_Ack: Specifies the acknowledge mode to apply.
+ * This parameter can be one of the following values:
+ * @arg I2C_Ack_Disable: No acknowledge
+ * @arg I2C_Ack_Enable: Acknowledge Enabled
+ * @param I2C_AcknowledgedAddress: Specifies the acknowledge address to apply.
+ * This parameter can be one of the following values:
+ * @arg I2C_AcknowledgedAddress_7bit: 7-bit slave address
+ * @arg I2C_AcknowledgedAddress_10bit: 10-bit slave address
+ * @note To use the I2C at 400 KHz (in fast mode), the PCLK frequency
+ * (I2C peripheral input clock) must be a multiple of 10 MHz.
+ * @retval None
+ */
+void I2C_Init(I2C_TypeDef* I2Cx, uint32_t OutputClockFrequency, uint16_t OwnAddress,
+ I2C_Mode_TypeDef I2C_Mode, I2C_DutyCycle_TypeDef I2C_DutyCycle,
+ I2C_Ack_TypeDef I2C_Ack, I2C_AcknowledgedAddress_TypeDef I2C_AcknowledgedAddress)
+{
+ uint32_t result = 0x0004;
+ uint16_t tmpval = 0;
+ uint8_t tmpccrh = 0;
+ uint8_t input_clock = 0;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MODE(I2C_Mode));
+ assert_param(IS_I2C_ACK_STATE(I2C_Ack));
+ assert_param(IS_I2C_ACKNOWLEDGE_ADDRESS(I2C_AcknowledgedAddress));
+ assert_param(IS_I2C_DUTY_CYCLE(I2C_DutyCycle));
+ assert_param(IS_I2C_OWN_ADDRESS(OwnAddress));
+ assert_param(IS_I2C_OUTPUT_CLOCK_FREQ(OutputClockFrequency));
+
+
+ /* Get system clock frequency */
+ input_clock = (uint8_t) (CLK_GetClockFreq() / 1000000);
+
+ /*------------------------- I2C FREQ Configuration ------------------------*/
+ /* Clear frequency bits */
+ I2Cx->FREQR &= (uint8_t)(~I2C_FREQR_FREQ);
+ /* Write new value */
+ I2Cx->FREQR |= input_clock;
+
+ /*--------------------------- I2C CCR Configuration ------------------------*/
+ /* Disable I2C to configure TRISER */
+ I2Cx->CR1 &= (uint8_t)(~I2C_CR1_PE);
+
+ /* Clear CCRH & CCRL */
+ I2Cx->CCRH &= (uint8_t)(~(I2C_CCRH_FS | I2C_CCRH_DUTY | I2C_CCRH_CCR));
+ I2Cx->CCRL &= (uint8_t)(~I2C_CCRL_CCR);
+
+ /* Detect Fast or Standard mode depending on the Output clock frequency selected */
+ if (OutputClockFrequency > I2C_MAX_STANDARD_FREQ) /* FAST MODE */
+ {
+ /* Set F/S bit for fast mode */
+ tmpccrh = I2C_CCRH_FS;
+
+ if (I2C_DutyCycle == I2C_DutyCycle_2)
+ {
+ /* Fast mode speed calculate: Tlow/Thigh = 2 */
+ result = (uint32_t) ((input_clock * 1000000) / (OutputClockFrequency * 3));
+ }
+ else /* I2C_DUTYCYCLE_16_9 */
+ {
+ /* Fast mode speed calculate: Tlow/Thigh = 16/9 */
+ result = (uint32_t) ((input_clock * 1000000) / (OutputClockFrequency * 25));
+ /* Set DUTY bit */
+ tmpccrh |= I2C_CCRH_DUTY;
+ }
+
+ /* Verify and correct CCR value if below minimum value */
+ if (result < (uint16_t)0x01)
+ {
+ /* Set the minimum allowed value */
+ result = (uint16_t)0x0001;
+ }
+
+ /* Set Maximum Rise Time: 300ns max in Fast Mode
+ = [300ns/(1/input_clock.10e6)]+1
+ = [(input_clock * 3)/10]+1 */
+ tmpval = ((input_clock * 3) / 10) + 1;
+ I2Cx->TRISER = (uint8_t)tmpval;
+
+ }
+ else /* STANDARD MODE */
+ {
+
+ /* Calculate standard mode speed */
+ result = (uint16_t)((input_clock * 1000000) / (OutputClockFrequency << (uint8_t)1));
+
+ /* Verify and correct CCR value if below minimum value */
+ if (result < (uint16_t)0x0004)
+ {
+ /* Set the minimum allowed value */
+ result = (uint16_t)0x0004;
+ }
+
+ /* Set Maximum Rise Time: 1000ns max in Standard Mode
+ = [1000ns/(1/input_clock.10e6)]+1
+ = input_clock+1 */
+ I2Cx->TRISER = (uint8_t)((uint8_t)input_clock + (uint8_t)1);
+
+ }
+
+ /* Write CCR with new calculated value */
+ I2Cx->CCRL = (uint8_t)result;
+ I2Cx->CCRH = (uint8_t)((uint8_t)((uint8_t)((uint8_t)result >> 8) & I2C_CCRH_CCR) | tmpccrh);
+
+ /* Enable I2C and Configure its mode*/
+ I2Cx->CR1 |= (uint8_t)(I2C_CR1_PE | I2C_Mode);
+
+ /* Configure I2C acknowledgement */
+ I2Cx->CR2 |= (uint8_t)I2C_Ack;
+
+ /*--------------------------- I2C OAR Configuration ------------------------*/
+ I2Cx->OARL = (uint8_t)(OwnAddress);
+ I2Cx->OARH = (uint8_t)((uint8_t)(I2C_AcknowledgedAddress | I2C_OARH_ADDCONF ) | \
+ (uint8_t)((uint16_t)( (uint16_t)OwnAddress & (uint16_t)0x0300) >> 7));
+}
+
+/**
+ * @brief Enables or disables the I2C peripheral.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param NewState: Indicate the new I2C peripheral state.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable I2C peripheral */
+ I2Cx->CR1 |= I2C_CR1_PE;
+ }
+ else /* NewState == DISABLE */
+ {
+ /* Disable I2C peripheral */
+ I2Cx->CR1 &= (uint8_t)(~I2C_CR1_PE);
+ }
+}
+
+/**
+ * @brief Enables or disables the I2C General Call feature.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param NewState: State of the General Call feature.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable General Call */
+ I2Cx->CR1 |= I2C_CR1_ENGC;
+ }
+ else /* NewState == DISABLE */
+ {
+ /* Disable General Call */
+ I2Cx->CR1 &= (uint8_t)(~I2C_CR1_ENGC);
+ }
+}
+
+/**
+ * @brief Generates I2C communication START condition.
+ * @note CCR must be programmed, i.e. I2C_Init function must have been called
+ * with a valid I2C_ClockSpeed
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param NewState: Enable or disable the start condition.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Generate a START condition */
+ I2Cx->CR2 |= I2C_CR2_START;
+ }
+ else /* NewState == DISABLE */
+ {
+ /* Disable the START condition generation */
+ I2Cx->CR2 &= (uint8_t)(~I2C_CR2_START);
+ }
+}
+
+/**
+ * @brief Generates I2C communication STOP condition.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param NewState: Enable or disable the stop condition.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Generate a STOP condition */
+ I2Cx->CR2 |= I2C_CR2_STOP;
+ }
+ else /* NewState == DISABLE */
+ {
+ /* Disable the STOP condition generation */
+ I2Cx->CR2 &= (uint8_t)(~I2C_CR2_STOP);
+ }
+}
+
+/**
+ * @brief Enables or disables I2C software reset.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param NewState: Specifies the new state of the I2C software reset.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Peripheral under reset */
+ I2Cx->CR2 |= I2C_CR2_SWRST;
+ }
+ else /* NewState == DISABLE */
+ {
+ /* Peripheral not under reset */
+ I2Cx->CR2 &= (uint8_t)(~I2C_CR2_SWRST);
+ }
+}
+
+/**
+ * @brief Enables or disables the I2C clock stretching.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param NewState: Specifies the new state of the I2C Clock stretching.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Clock Stretching Enable */
+ I2Cx->CR1 &= (uint8_t)(~I2C_CR1_NOSTRETCH);
+
+ }
+ else /* NewState == DISABLE */
+ {
+ /* Clock Stretching Disable (Slave mode) */
+ I2Cx->CR1 |= I2C_CR1_NOSTRETCH;
+ }
+}
+
+/**
+ * @brief Enables or disables the I2C ARP.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param NewState: Specifies the new state of the I2C ARP
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_ARPCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* ARP Enable */
+ I2Cx->CR1 |= I2C_CR1_ARP;
+
+ }
+ else /* NewState == DISABLE */
+ {
+ /* ARP Disable */
+ I2Cx->CR1 &= (uint8_t)(~I2C_CR1_ARP);
+ }
+}
+
+/**
+ * @brief Enable or Disable the I2C acknowledge feature.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param NewState: Specifies the new state of the I2C acknowledge.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the acknowledgement */
+ I2Cx->CR2 |= I2C_CR2_ACK;
+ }
+ else
+ {
+ /* Disable the acknowledgement */
+ I2Cx->CR2 &= (uint8_t)(~I2C_CR2_ACK);
+ }
+}
+
+/**
+ * @brief Configures the specified I2C own address2.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param Address: specifies the 7bit I2C own address2.
+ * @retval None.
+ */
+void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address)
+{
+ uint8_t tmpreg = 0;
+
+ /* Get the old register value */
+ tmpreg = I2Cx->OAR2;
+
+ /* Reset I2Cx Own address2 bit [7:1] */
+ tmpreg &= (uint8_t)(~I2C_OAR2_ADD2);
+
+ /* Set I2Cx Own address2 */
+ tmpreg |= (uint8_t) ((uint8_t)Address & (uint8_t)0xFE);
+
+ /* Store the new register value */
+ I2Cx->OAR2 = tmpreg;
+}
+
+/**
+ * @brief Enables or disables the specified I2C dual addressing mode.
+ * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
+ * @param NewState: new state of the I2C dual addressing mode.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_DualAddressCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable dual addressing mode */
+ I2Cx->OAR2 |= I2C_OAR2_ENDUAL;
+ }
+ else
+ {
+ /* Disable dual addressing mode */
+ I2Cx->OAR2 &= (uint8_t)(~I2C_OAR2_ENDUAL);
+ }
+}
+
+/**
+ * @brief Selects the specified I2C Ack position.
+ * @note This function must be called before data reception starts.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param I2C_AckPosition: specifies the Ack position.
+ * This parameter can be one of the following values:
+ * @arg I2C_AckPosition_Current: Acknowledge on the current byte
+ * @arg I2C_AckPosition_Next: Acknowledge on the next byte
+ * @retval None
+ */
+void I2C_AckPositionConfig(I2C_TypeDef* I2Cx, I2C_AckPosition_TypeDef I2C_AckPosition)
+{
+ /* Check function parameters */
+ assert_param(IS_I2C_ACK_POSITION(I2C_AckPosition));
+
+ /* Clear the I2C Ack position */
+ I2Cx->CR2 &= (uint8_t)(~I2C_CR2_POS);
+ /* Configure the specified I2C Ack position*/
+ I2Cx->CR2 |= (uint8_t)I2C_AckPosition;
+}
+
+/**
+ * @brief Drives the SMBusAlert pin high or low.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param I2C_SMBusAlert: SMBusAlert pin state.
+ * This parameter can be one of the following values:
+ * @arg I2C_SMBusAlert_High: SMBAlert pin high
+ * @arg I2C_SMBusAlert_Low: SMBAlert pin Low
+ * @retval None
+ */
+void I2C_SMBusAlertConfig(I2C_TypeDef* I2Cx, I2C_SMBusAlert_TypeDef I2C_SMBusAlert)
+{
+
+ /* Check functions parameters */
+ assert_param(IS_I2C_SMBUS_ALERT(I2C_SMBusAlert));
+
+ if (I2C_SMBusAlert != I2C_SMBusAlert_High)
+ {
+ /* SMBus Alert pin low */
+ I2Cx->CR2 |= (uint8_t)I2C_CR2_ALERT;
+ }
+ else /*I2C_SMBusAlert = I2C_SMBusAlert_High */
+ {
+ /* SMBus Alert pin high */
+ I2Cx->CR2 &= (uint8_t)(~I2C_CR2_ALERT);
+ }
+}
+
+/**
+ * @brief Selects I2C fast mode duty cycle.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param I2C_DutyCycle: specifies the fast mode duty cycle.
+ * This parameter can be one of the following values:
+ * @arg I2C_DutyCycle_2: I2C fast mode Tlow/Thigh = 2
+ * @arg I2C_DutyCycle_16_9: I2C fast mode Tlow/Thigh = 16/9
+ * @retval None
+ */
+void I2C_FastModeDutyCycleConfig(I2C_TypeDef* I2Cx, I2C_DutyCycle_TypeDef I2C_DutyCycle)
+{
+
+ /* Check function parameters */
+ assert_param(IS_I2C_DUTY_CYCLE(I2C_DutyCycle));
+
+ if (I2C_DutyCycle == I2C_DutyCycle_16_9)
+ {
+ /* I2C fast mode Tlow/Thigh = 16/9 */
+ I2Cx->CCRH |= I2C_CCRH_DUTY;
+ }
+ else /* I2C_DUTYCYCLE_2 */
+ {
+ /* I2C fast mode Tlow/Thigh = 2 */
+ I2Cx->CCRH &= (uint8_t)(~I2C_CCRH_DUTY);
+ }
+}
+
+/**
+ * @brief Transmits the 7-bit address (to select the) slave device.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param Address: Specifies the slave address which will be transmitted.
+ * @param I2C_Direction: specifies whether the I2C device will be a Transmitter
+ * or a Receiver.
+ * This parameter can be one of the following values
+ * @arg I2C_Direction_Transmitter: Transmitter mode
+ * @arg I2C_Direction_Receiver: Receiver mode
+ * @retval None
+ */
+void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, I2C_Direction_TypeDef I2C_Direction)
+{
+ /* Check function parameters */
+ assert_param(IS_I2C_ADDRESS(Address));
+ assert_param(IS_I2C_DIRECTION(I2C_Direction));
+
+ /* Test on the direction to set/reset the read/write bit */
+ if (I2C_Direction != I2C_Direction_Transmitter)
+ {
+ /* Set the address bit0 for read */
+ Address |= OAR1_ADD0_Set;
+ }
+ else
+ {
+ /* Reset the address bit0 for write */
+ Address &= OAR1_ADD0_Reset;
+ }
+ /* Send the address */
+ I2Cx->DR = Address;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_Group2 Data transfers functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ===============================================================================
+ Data transfers functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Send a byte by writing in the DR register.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param Data: Byte to be sent.
+ * @retval None
+ */
+void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data)
+{
+ /* Write in the DR register the data to be sent */
+ I2Cx->DR = Data;
+}
+
+/**
+ * @brief Returns the most recent received data.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param None
+ * @retval The value of the received byte data.
+ */
+uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx)
+{
+ /* Return the data present in the DR register */
+ return ((uint8_t)I2Cx->DR);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_Group3 PEC management functions
+ * @brief PEC management functions
+ *
+@verbatim
+ ===============================================================================
+ PEC management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables PEC transfer.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param NewState: indicates the PEC transfer state.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_TransmitPEC(I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the PEC transmission */
+ I2Cx->CR2 |= I2C_CR2_PEC;
+ }
+ else
+ {
+ /* Disable the PEC transmission */
+ I2Cx->CR2 &= (uint8_t)(~I2C_CR2_PEC);
+ }
+}
+
+/**
+ * @brief Enables or disables PEC calculation.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param NewState: indicates the PEC calculation state.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_CalculatePEC(I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable PEC calculation */
+ I2Cx->CR1 |= I2C_CR1_ENPEC;
+ }
+ else
+ {
+ /* Disable PEC calculation */
+ I2Cx->CR1 &= (uint8_t)(~I2C_CR1_ENPEC);
+ }
+}
+
+/**
+ * @brief Selects I2C PEC position..
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param I2C_PECPosition:PEC position.
+ * This parameter can be one of the following values:
+ * @arg I2C_PECPosition_Current: Current byte in shift register is PEC
+ * @arg I2C_PECPosition_Next: Next byte in shift register is PEC
+ * @retval None
+ */
+void I2C_PECPositionConfig(I2C_TypeDef* I2Cx, I2C_PECPosition_TypeDef I2C_PECPosition)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_PEC_POSITION(I2C_PECPosition));
+
+ /* Clear the I2C PEC position */
+ I2Cx->CR2 &= (uint8_t)(~I2C_CR2_POS);
+ /* Configure the specified I2C PEC position*/
+ I2Cx->CR2 |= (uint8_t)I2C_PECPosition;
+}
+
+/**
+ * @brief Returns PEC value.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param None
+ * @retval The value of the PEC.
+ */
+uint8_t I2C_GetPEC(I2C_TypeDef* I2Cx)
+{
+ /* Return the PEC value */
+ return (I2Cx->PECR);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_Group4 DMA transfers management functions
+ * @brief DMA transfers management functions
+ *
+@verbatim
+ ===============================================================================
+ DMA transfers management functions
+ ===============================================================================
+ This section provides functions allowing to configure the I2C DMA channels
+ requests.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the I2C DMA requests .
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param NewState: Indicate the new I2C DMA state.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable I2C DMA requests */
+ I2Cx->ITR |= I2C_ITR_DMAEN;
+ }
+ else
+ {
+ /* Disable I2C DMA requests */
+ I2Cx->ITR &= (uint8_t)(~I2C_ITR_DMAEN);
+ }
+}
+
+/**
+ * @brief Specifies that the next DMA transfer is the last one .
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param NewState: Indicate the new I2C DMA state.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable I2C DMA requests */
+ I2Cx->ITR |= I2C_ITR_LAST;
+ }
+ else
+ {
+ /* Disable I2C DMA requests */
+ I2Cx->ITR &= (uint8_t)(~I2C_ITR_LAST);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_Group5 Interrupts events and flags management functions
+ * @brief Interrupts, events and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts, events and flags management functions
+ ===============================================================================
+ This section provides functions allowing to configure the I2C Interrupts
+ sources and check or clear the flags or pending bits status.
+ The user should identify which mode will be used in his application to manage
+ the communication: Polling mode, Interrupt mode or DMA mode.
+
+ ===============================================================================
+ I2C State Monitoring Functions
+ ===============================================================================
+ This I2C driver provides three different ways for I2C state monitoring
+ depending on the application requirements and constraints:
+
+
+ 1. Basic state monitoring (Using I2C_CheckEvent() function)
+ -----------------------------------------------------------
+ It compares the status registers (SR1, SR2 and SR3) content to a given event
+ (can be the combination of one or more flags).
+ It returns SUCCESS if the current status includes the given flags
+ and returns ERROR if one or more flags are missing in the current status.
+ - When to use:
+ - This function is suitable for most applications as well as for startup
+ activity since the events are fully described in the product reference manual
+ (RM0031).
+ - It is also suitable for users who need to define their own events.
+ - Limitations:
+ - If an error occurs (ie. error flags are set besides to the monitored flags),
+ the I2C_CheckEvent() function may return SUCCESS despite the communication
+ hold or corrupted real state.
+ In this case, it is advised to use error interrupts to monitor the error
+ events and handle them in the interrupt IRQ handler.
+
+ @note
+ For error management, it is advised to use the following functions:
+ - I2C_ITConfig() to configure and enable the error interrupts (I2C_IT_ERR).
+ - I2Cx_IRQHandler() which is called when the I2C interrupts occur.
+ Where x is the peripheral instance (I2C1,...)
+ - I2C_GetFlagStatus() or I2C_GetITStatus() to be called into the
+ I2Cx_IRQHandler() function in order to determine which error occurred.
+ - I2C_ClearFlag() or I2C_ClearITPendingBit() and/or I2C_SoftwareResetCmd()
+ and/or I2C_GenerateStop() in order to clear the error flag and
+ source and return to correct communication status.
+
+
+ 2. Advanced state monitoring (Using the function I2C_GetLastEvent())
+ --------------------------------------------------------------------
+ Using the function I2C_GetLastEvent() which returns the image of both SR1
+ & SR3 status registers in a single word (uint16_t) (Status Register 3 value
+ is shifted left by 8 bits and concatenated to Status Register 1).
+ - When to use:
+ - This function is suitable for the same applications above but it allows to
+ overcome the limitations of I2C_GetFlagStatus() function (see below).
+ The returned value could be compared to events already defined in the
+ library (stm8l15x_i2c.h) or to custom values defined by user.
+ - This function is suitable when multiple flags are monitored at the same time.
+ - At the opposite of I2C_CheckEvent() function, this function allows user to
+ choose when an event is accepted (when all events flags are set and no
+ other flags are set or just when the needed flags are set like
+ I2C_CheckEvent() function).
+ - Limitations:
+ - User may need to define his own events.
+ - Same remark concerning the error management is applicable for this
+ function if user decides to check only regular communication flags (and
+ ignores error flags).
+
+
+ 3. Flag-based state monitoring (Using the function I2C_GetFlagStatus())
+ -----------------------------------------------------------------------
+ Using the function I2C_GetFlagStatus() which simply returns the status of
+ one single flag (ie. I2C_FLAG_RXNE ...).
+ - When to use:
+ - This function could be used for specific applications or in debug phase.
+ - It is suitable when only one flag checking is needed (most I2C events
+ are monitored through multiple flags).
+ - Limitations:
+ - When calling this function, the Status register is accessed. Some flags are
+ cleared when the status register is accessed. So checking the status
+ of one Flag, may clear other ones.
+ - Function may need to be called twice or more in order to monitor one
+ single event.
+
+ For detailed description of Events, please refer to section I2C_Events in
+ stm8l15x_i2c.h file.
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the specified I2C interrupt.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param I2C_IT: specifies the I2C interrupts sources to be enabled or disabled.
+ * This parameter can be any combination of the following values:
+ * @arg I2C_IT_BUF: Buffer interrupt mask
+ * @arg I2C_IT_EVT: Event interrupt mask
+ * @arg I2C_IT_ERR: Error interrupt mask
+ * @param NewState: State of the interrupt.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void I2C_ITConfig(I2C_TypeDef* I2Cx, I2C_IT_TypeDef I2C_IT, FunctionalState NewState)
+{
+ /* Check functions parameters */
+ assert_param(IS_I2C_CONFIG_IT(I2C_IT));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected I2C interrupts */
+ I2Cx->ITR |= (uint8_t)I2C_IT;
+ }
+ else /* NewState == DISABLE */
+ {
+ /* Disable the selected I2C interrupts */
+ I2Cx->ITR &= (uint8_t)(~(uint8_t)I2C_IT);
+ }
+}
+
+/**
+ * @brief Reads the specified I2C register and returns its value.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param I2C_Register: specifies the register to read.
+ * This parameter can be one of the following values:
+ * @arg I2C_Register_CR1: CR1 register.
+ * @arg I2C_Register_CR2: CR2 register.
+ * @arg I2C_Register_FREQR: Frequency register.
+ * @arg I2C_Register_OARL: Own address register LSB.
+ * @arg I2C_Register_OARH: Own address register MSB
+ * @arg I2C_Register_DR: DR register.
+ * @arg I2C_Register_SR1: SR1 register.
+ * @arg I2C_Register_SR2: SR2 register.
+ * @arg I2C_Register_SR3: SR3 register.
+ * @arg I2C_Register_ITR: Interrupt and DMA register.
+ * @arg I2C_Register_CCRL: Clock control register low.
+ * @arg I2C_Register_CCRH: Clock control register high.
+ * @arg I2C_Register_TRISER: TRISE register.
+ * @arg I2C_Register_PECR: PEC register.
+ * @retval The value of the read register.
+ */
+
+uint8_t I2C_ReadRegister(I2C_TypeDef* I2Cx, I2C_Register_TypeDef I2C_Register)
+{
+ __IO uint16_t tmp = 0;
+ /* Check the parameters */
+ assert_param(IS_I2C_REGISTER(I2C_Register));
+
+ tmp = (uint16_t) I2Cx;
+ tmp += I2C_Register;
+
+ /* Return the selected register value */
+ return (*(__IO uint8_t *) tmp);
+}
+
+
+/**
+ ===============================================================================
+ 1. Basic state monitoring
+ ===============================================================================
+ */
+
+/**
+ * @brief Checks whether the last I2Cx Event is equal to the one passed
+ * as parameter.
+ * @param I2Cx: where x can be 1 to select the I2C peripheral.
+ * @param I2C_EVENT: specifies the event to be checked.
+ * This parameter can be one of the following values:
+ * @arg I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: EV1
+ * @arg I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: EV1
+ * @arg I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED: EV1
+ * @arg I2C_EVENT_SLAVE_BYTE_RECEIVED: EV2
+ * @arg (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_GENCALL): EV2
+ * @arg I2C_EVENT_SLAVE_BYTE_TRANSMITTED: EV3
+ * @arg (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_GENCALL): EV3
+ * @arg I2C_EVENT_SLAVE_ACK_FAILURE: EV3_2
+ * @arg I2C_EVENT_SLAVE_STOP_DETECTED: EV4
+ * @arg I2C_EVENT_MASTER_MODE_SELECT: EV5
+ * @arg I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: EV6
+ * @arg I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: EV6
+ * @arg I2C_EVENT_MASTER_BYTE_RECEIVED: EV7
+ * @arg I2C_EVENT_MASTER_BYTE_TRANSMITTING: EV8
+ * @arg I2C_EVENT_MASTER_BYTE_TRANSMITTED: EV8_2
+ * @arg I2C_EVENT_MASTER_MODE_ADDRESS10: EV9
+ *
+ * @note: For detailed description of Events, please refer to section
+ * I2C_Events in stm8l15x_i2c.h file.
+ *
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: Last event is equal to the I2C_EVENT
+ * - ERROR: Last event is different from the I2C_EVENT
+ */
+ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, I2C_Event_TypeDef I2C_Event)
+{
+ __IO uint16_t lastevent = 0x00;
+ uint8_t flag1 = 0x00 ;
+ uint8_t flag2 = 0x00;
+ ErrorStatus status = ERROR;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_EVENT(I2C_Event));
+
+ if (I2C_Event == I2C_EVENT_SLAVE_ACK_FAILURE)
+ {
+ lastevent = I2Cx->SR2 & I2C_SR2_AF;
+ }
+ else
+ {
+ flag1 = I2Cx->SR1;
+ flag2 = I2Cx->SR3;
+ lastevent = ((uint16_t)((uint16_t)flag2 << (uint16_t)8) | (uint16_t)flag1);
+ }
+ /* Check whether the last event is equal to I2C_EVENT */
+ if (((uint16_t)lastevent & (uint16_t)I2C_Event) == (uint16_t)I2C_Event)
+ {
+ /* SUCCESS: last event is equal to I2C_EVENT */
+ status = SUCCESS;
+ }
+ else
+ {
+ /* ERROR: last event is different from I2C_EVENT */
+ status = ERROR;
+ }
+
+ /* Return status */
+ return status;
+}
+
+/**
+ ===============================================================================
+ 2. Advanced state monitoring
+ ===============================================================================
+ */
+
+/**
+ * @brief Returns the last I2C Event.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ *
+ * @note: For detailed description of Events, please refer to section
+ * I2C_Events in stm8l15xx_i2c.h file.
+ *
+ * @retval The last event
+ */
+I2C_Event_TypeDef I2C_GetLastEvent(I2C_TypeDef* I2Cx)
+{
+ __IO uint16_t lastevent = 0;
+ uint16_t flag1 = 0;
+ uint16_t flag2 = 0;
+
+ if ((I2Cx->SR2 & I2C_SR2_AF) != 0x00)
+ {
+ lastevent = I2C_EVENT_SLAVE_ACK_FAILURE;
+ }
+ else
+ {
+ /* Read the I2C status register */
+ flag1 = I2Cx->SR1;
+ flag2 = I2Cx->SR3;
+
+ /* Get the last event value from I2C status register */
+ lastevent = ((uint16_t)((uint16_t)flag2 << 8) | (uint16_t)flag1);
+ }
+ /* Return status */
+ return (I2C_Event_TypeDef)lastevent;
+}
+
+/**
+ ===============================================================================
+ 3. Flag-based state monitoring
+ ===============================================================================
+ */
+
+/**
+ * @brief Checks whether the specified I2C flag is set or not.
+ * @param I2Cx: where x can be 1 select the I2C peripheral.
+ * @param I2C_FLAG: specifies the flag to check.
+ * This parameter can be one of the following values:
+ * @arg I2C_FLAG_SMBHOST: SMBus host header (Slave mode)
+ * @arg I2C_FLAG_SMBDEFAULT: SMBus default header (Slave mode)
+ * @arg I2C_FLAG_GENCALL: General call header flag (Slave mode)
+ * @arg I2C_FLAG_TRA: Transmitter/Receiver flag
+ * @arg I2C_FLAG_BUSY: Bus busy flag
+ * @arg I2C_FLAG_MSL: Master/Slave flag
+ * @arg I2C_FLAG_SMBALERT: SMBus Alert flag
+ * @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag
+ * @arg I2C_FLAG_PECERR: PEC error in reception flag
+ * @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode)
+ * @arg I2C_FLAG_AF: Acknowledge failure flag
+ * @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode)
+ * @arg I2C_FLAG_BERR: Bus error flag
+ * @arg I2C_FLAG_TXE: Data register empty flag (Transmitter)
+ * @arg I2C_FLAG_RXNE: Data register not empty (Receiver) flag
+ * @arg I2C_FLAG_STOPF: Stop detection flag (Slave mode)
+ * @arg I2C_FLAG_ADD10: 10-bit header sent flag (Master mode)
+ * @arg I2C_FLAG_BTF: Byte transfer finished flag
+ * @arg I2C_FLAG_ADDR: Address sent flag (Master mode) “ADSL”
+ * Address matched flag (Slave mode)”ENDAD”
+ * @arg I2C_FLAG_SB: Start bit flag (Master mode)
+ * @retval The new state of I2C_FLAG (SET or RESET).
+ */
+FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, I2C_FLAG_TypeDef I2C_FLAG)
+{
+ uint8_t tempreg = 0;
+ uint8_t regindex = 0;
+ FlagStatus bitstatus = RESET;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_GET_FLAG(I2C_FLAG));
+
+ /* Read flag register index */
+ regindex = (uint8_t)((uint16_t)I2C_FLAG >> 8);
+ /* Check SRx index */
+ switch (regindex)
+ {
+ /* Returns whether the status register to check is SR1 */
+ case 0x01:
+ tempreg = (uint8_t)I2Cx->SR1;
+ break;
+
+ /* Returns whether the status register to check is SR2 */
+ case 0x02:
+ tempreg = (uint8_t)I2Cx->SR2;
+ break;
+
+ /* Returns whether the status register to check is SR3 */
+ case 0x03:
+ tempreg = (uint8_t)I2Cx->SR3;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Check the status of the specified I2C flag */
+ if ((tempreg & (uint8_t)I2C_FLAG ) != 0)
+ {
+ /* Flag is set */
+ bitstatus = SET;
+ }
+ else
+ {
+ /* Flag is reset */
+ bitstatus = RESET;
+ }
+ /* Return the flag status */
+ return bitstatus;
+}
+/**
+ * @brief Clear flags
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param I2C_Flag: Specifies the flag to clear
+ * This parameter can be any combination of the following values:
+ * @arg I2C_FLAG_SMBALERT: SMBus Alert flag
+ * @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag
+ * @arg I2C_FLAG_PECERR: PEC error in reception flag
+ * @arg I2C_FLAG_WUFH: Wakeup from Halt
+ * @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode)
+ * @arg I2C_FLAG_AF: Acknowledge failure flag
+ * @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode)
+ * @arg I2C_FLAG_BERR: Bus error flag.
+ * @note STOPF (STOP detection) is cleared by software sequence: a read operation
+ * to I2C_SR1 register (I2C_GetFlagStatus()) followed by a write operation
+ * to I2C_CR2 register.
+ * @note ADD10 (10-bit header sent) is cleared by software sequence: a read
+ * operation to I2C_SR1 (I2C_GetFlagStatus()) followed by writing the
+ * second byte of the address in DR register.
+ * @note BTF (Byte Transfer Finished) is cleared by software sequence: a read
+ * operation to I2C_SR1 register (I2C_GetFlagStatus()) followed by a
+ * read/write to I2C_DR register (I2C_SendData()).
+ * @note ADDR (Address sent) is cleared by software sequence: a read operation
+ * to I2C_SR1 register(I2C_GetFlagStatus()) followed by a read operation
+ * to I2C_SR3 register ((void)(I2Cx->SR3)).
+ * @note SB (Start Bit) is cleared software sequence: a read operation to
+ * I2C_SR1 register (I2C_GetFlagStatus()) followed by a write operation
+ * to I2C_DR register (I2C_SendData()).
+ * @retval None
+ */
+void I2C_ClearFlag(I2C_TypeDef* I2Cx, I2C_FLAG_TypeDef I2C_FLAG)
+{
+ uint16_t flagpos = 0;
+ /* Check the parameters */
+ assert_param(IS_I2C_CLEAR_FLAG(I2C_FLAG));
+
+ /* Get the I2C flag position */
+ flagpos = (uint16_t)I2C_FLAG & FLAG_Mask;
+ /* Clear the selected I2C flag */
+ I2Cx->SR2 = (uint8_t)((uint16_t)(~flagpos));
+}
+
+/**
+ * @brief Checks whether the specified I2C interrupt has occurred or not.
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param I2C_IT: specifies the interrupt source to check.
+ * This parameter can be one of the following values:
+ * @arg I2C_IT_SMBALERT: SMBus Alert interrupt
+ * @arg I2C_IT_TIMEOUT: Timeout or Tlow error interrupt
+ * @arg I2C_IT_PECERR: PEC error in reception interrupt
+ * @arg I2C_IT_WUFH: Wakeup from Halt
+ * @arg I2C_IT_OVR: Overrun/Underrun flag (Slave mode)
+ * @arg I2C_IT_AF: Acknowledge failure flag
+ * @arg I2C_IT_ARLO: Arbitration lost flag (Master mode)
+ * @arg I2C_IT_BERR: Bus error flag
+ * @arg I2C_IT_TXE: Data register empty flag (Transmitter)
+ * @arg I2C_IT_RXNE: Data register not empty (Receiver) flag
+ * @arg I2C_IT_STOPF: Stop detection flag (Slave mode)
+ * @arg I2C_IT_ADD10: 10-bit header sent flag (Master mode)
+ * @arg I2C_IT_BTF: Byte transfer finished flag
+ * @arg I2C_IT_ADDR: Address sent flag (Master mode) “ADSL”
+ * Address matched flag (Slave mode)“ENDAD”
+ * @arg I2C_IT_SB: Start bit flag (Master mode)
+ * @retval The new state of I2C_IT
+ */
+ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, I2C_IT_TypeDef I2C_IT)
+{
+ ITStatus bitstatus = RESET;
+ __IO uint8_t enablestatus = 0;
+ uint16_t tempregister = 0;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_GET_IT(I2C_IT));
+
+ tempregister = (uint8_t)( ((uint16_t)((uint16_t)I2C_IT & ITEN_Mask)) >> 8);
+
+ /* Check if the interrupt source is enabled or not */
+ enablestatus = (uint8_t)(I2Cx->ITR & ( uint8_t)tempregister);
+
+ if ((uint16_t)((uint16_t)I2C_IT & REGISTER_Mask) == REGISTER_SR1_Index)
+ {
+ /* Check the status of the specified I2C flag */
+ if (((I2Cx->SR1 & (uint8_t)I2C_IT) != RESET) && enablestatus)
+ {
+ /* I2C_IT is set */
+ bitstatus = SET;
+ }
+ else
+ {
+ /* I2C_IT is reset */
+ bitstatus = RESET;
+ }
+ }
+ else
+ {
+ /* Check the status of the specified I2C flag */
+ if (((I2Cx->SR2 & (uint8_t)I2C_IT) != RESET) && enablestatus)
+ {
+ /* I2C_IT is set */
+ bitstatus = SET;
+ }
+ else
+ {
+ /* I2C_IT is reset */
+ bitstatus = RESET;
+ }
+ }
+ /* Return the I2C_IT status */
+ return bitstatus;
+}
+/**
+ * @brief Clear IT pending bit
+ * @param I2Cx: where x can be 1 to select the specified I2C peripheral.
+ * @param I2C_IT: specifies the interrupt pending bit to clear.
+ * This parameter can be any combination of the following values:
+ * @arg I2C_IT_SMBALERT: SMBus Alert interrupt
+ * @arg I2C_IT_TIMEOUT: Timeout or Tlow error interrupt
+ * @arg I2C_IT_PECERR: PEC error in reception interrupt
+ * @arg I2C_IT_WUFH: Wakeup from Halt
+ * @arg I2C_IT_OVR: Overrun/Underrun interrupt (Slave mode)
+ * @arg I2C_IT_AF: Acknowledge failure interrupt
+ * @arg I2C_IT_ARLO: Arbitration lost interrupt (Master mode)
+ * @arg I2C_IT_BERR: Bus error interrupt
+ *
+ * @note STOPF (STOP detection) is cleared by software sequence: a read operation
+ * to I2C_SR1 register (I2C_GetITStatus()) followed by a write operation to
+ * I2C_CR2 register (I2C_AcknowledgeConfig() to configure the I2C peripheral Acknowledge).
+ * @note ADD10 (10-bit header sent) is cleared by software sequence: a read
+ * operation to I2C_SR1 (I2C_GetITStatus()) followed by writing the second
+ * byte of the address in I2C_DR register.
+ * @note BTF (Byte Transfer Finished) is cleared by software sequence: a read
+ * operation to I2C_SR1 register (I2C_GetITStatus()) followed by a read/write to
+ * I2C_DR register (I2C_SendData()).
+ * @note ADDR (Address sent) is cleared by software sequence: a read operation
+ * to I2C_SR1 register (I2C_GetITStatus()) followed by a read operation
+ * to I2C_SR3 register ((void)(I2Cx->SR3)).
+ * @note SB (Start Bit) is cleared by software sequence: a read operation to
+ * I2C_SR1 register (I2C_GetITStatus()) followed by a write operation to
+ * I2C_DR register (I2C_SendData()).
+ * @retval None
+ */
+void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, I2C_IT_TypeDef I2C_IT)
+{
+ uint16_t flagpos = 0;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_CLEAR_IT(I2C_IT));
+
+ /* Get the I2C flag position */
+ flagpos = (uint16_t)I2C_IT & FLAG_Mask;
+
+ /* Clear the selected I2C flag */
+ I2Cx->SR2 = (uint8_t)((uint16_t)~flagpos);
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_irtim.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_irtim.c
new file mode 100644
index 00000000..9e0ba4d3
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_irtim.c
@@ -0,0 +1,199 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_irtim.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to configure the IRTIM peripheral.
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * This driver provides functions to:
+ * 1. Enable the IRTIM peripheral
+ * 2. Enable the high sink mode on the IRTIM pin
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_irtim.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup IRTIM
+ * @brief IRTIM driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+
+/** @defgroup IRTIM_Private_Functions
+ * @{
+ */
+
+/** @defgroup IRTIM_Group1 IRTIM configuration functions
+ * @brief IRTIM configuration functions
+ *
+@verbatim
+ ===============================================================================
+ IRTIM configuration functions
+ ===============================================================================
+
+ ===================================================================
+ IRTIM Driver: how to use it
+ ===================================================================
+ To generate the infrared remote control signal, perform the following steps:
+ 1. Use TIM2 channel 1 to generate the high frequency carrier signal
+ by calling TIM2_OC1Init()
+ 2. Use TIM3 channel 1 to generate the modulation envelope by
+ calling TIM3_OC1Init()
+ 3. Enable the IRTIM peripheral using IRTIM_Cmd()
+
+ Note1: When IRTIM peripheral is enabled, TIM2 channel 1 and TIM3 channel 1
+ become inactive (no signal on output) and can be used as GPIO.
+
+ Note2: The high sink LED driver capability (only available on the IRTIM pin)
+ can be activated using IRTIM_HighSinkODCmd() to sink the high
+ current needed to directly control an infrared LED
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the IRTIM peripheral registers to their default reset values.
+ * @param None
+ * @retval None
+ */
+void IRTIM_DeInit(void)
+{
+ IRTIM->CR = IRTIM_CR_RESET_VALUE;
+}
+
+/**
+ * @brief Enables or disables the IRTIM peripheral.
+ * @param NewState : The new state of the IRTIM peripheral.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void IRTIM_Cmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* set or Reset the EN Bit */
+ if (NewState == DISABLE)
+ {
+ IRTIM->CR &= (uint8_t)(~IRTIM_CR_EN) ;
+ }
+ else
+ {
+ IRTIM->CR |= IRTIM_CR_EN ;
+ }
+}
+
+/**
+ * @brief Enables or disables the High sink open drain buffer of the IRTIM peripheral.
+ * @param NewState : The new state of the High sink open drain buffer.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void IRTIM_HighSinkODCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* set or Reset the EN Bit */
+ if (NewState == DISABLE)
+ {
+ IRTIM->CR &= (uint8_t)(~IRTIM_CR_HSEN) ;
+ }
+ else
+ {
+ IRTIM->CR |= IRTIM_CR_HSEN ;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup IRTIM_Group2 IRITM status management functions
+ * @brief IRITM status management functions
+ *
+@verbatim
+ ===============================================================================
+ IRITM status management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Checks whether the IRTIM device is enabled or not.
+ * @param None
+ * @retval state of the IRTIM device.
+ */
+
+FunctionalState IRTIM_GetStatus(void)
+{
+ return ((FunctionalState) (IRTIM->CR & IRTIM_CR_EN));
+}
+
+/**
+ * @brief Checks whether the IRTIM High Sink Open Drain buffer is Enabled or not.
+ * @param None
+ * @retval state of High Sink Open Drain buffer.
+ */
+FunctionalState IRTIM_GetHighSinkODStatus(void)
+{
+ return ((FunctionalState)(IRTIM->CR & IRTIM_CR_HSEN));
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_itc.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_itc.c
new file mode 100644
index 00000000..294056d0
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_itc.c
@@ -0,0 +1,393 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_itc.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionality of the Interrupt controller (ITC) peripheral:
+ * - Configuration and management
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_itc.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup ITC
+ * @brief ITC driver modules
+ * @{
+ */
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup ITC_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Utility function used to read CC register.
+ * @param None
+ * @retval CPU CC register value
+ */
+uint8_t ITC_GetCPUCC(void)
+{
+#ifdef _COSMIC_
+ _asm("push cc");
+ _asm("pop a");
+ return; /* Ignore compiler warning, the returned value is in A register */
+#elif defined _RAISONANCE_ /* _RAISONANCE_ */
+ return _getCC_();
+#else /* _IAR_ */
+ asm("push cc");
+ asm("pop a"); /* Ignore compiler warning, the returned value is in A register */
+#endif /* _COSMIC_*/
+}
+
+/** @defgroup ITC_Group1 ITC configuration and management functions
+ * @brief ITC configuration and management functions
+ *
+@verbatim
+ ===============================================================================
+ ITC configuration and management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the ITC registers to their default reset value.
+ * @param None
+ * @retval None
+ */
+void ITC_DeInit(void)
+{
+ ITC->ISPR1 = ITC_SPRX_RESET_VALUE;
+ ITC->ISPR2 = ITC_SPRX_RESET_VALUE;
+ ITC->ISPR3 = ITC_SPRX_RESET_VALUE;
+ ITC->ISPR4 = ITC_SPRX_RESET_VALUE;
+ ITC->ISPR5 = ITC_SPRX_RESET_VALUE;
+ ITC->ISPR6 = ITC_SPRX_RESET_VALUE;
+ ITC->ISPR7 = ITC_SPRX_RESET_VALUE;
+ ITC->ISPR8 = ITC_SPRX_RESET_VALUE;
+}
+
+/**
+ * @brief Gets the interrupt software priority bits (I1, I0) value from CPU CC register.
+ * @param None
+ * @retval The interrupt software priority bits value.
+ */
+uint8_t ITC_GetSoftIntStatus(void)
+{
+ return ((uint8_t)(ITC_GetCPUCC() & CPU_SOFT_INT_DISABLED));
+}
+
+/**
+ * @brief Gets the software priority of the specified interrupt source.
+ * @param IRQn : Specifies the peripheral interrupt source.
+ * @retval Specifies the software priority of the interrupt source.
+ */
+ITC_PriorityLevel_TypeDef ITC_GetSoftwarePriority(IRQn_TypeDef IRQn)
+{
+ uint8_t Value = 0;
+ uint8_t Mask = 0;
+
+ /* Check function parameters */
+ assert_param(IS_ITC_IRQ(IRQn));
+
+ /* Define the mask corresponding to the bits position in the SPR register */
+ Mask = (uint8_t)(0x03U << ((IRQn % 4U) * 2U));
+
+ switch (IRQn)
+ {
+ case FLASH_IRQn:
+ case DMA1_CHANNEL0_1_IRQn:
+ case DMA1_CHANNEL2_3_IRQn:
+ Value = (uint8_t)(ITC->ISPR1 & Mask); /* Read software priority */
+ break;
+
+ case EXTIE_F_PVD_IRQn:
+#if defined (STM8L15X_MD) || defined (STM8L05X_MD_VL) || defined (STM8AL31_L_MD)
+ case RTC_IRQn:
+ case EXTIB_IRQn:
+ case EXTID_IRQn:
+#elif defined (STM8L15X_LD) || defined (STM8L05X_LD_VL)
+ case RTC_CSSLSE_IRQn:
+ case EXTIB_IRQn:
+ case EXTID_IRQn:
+#elif defined (STM8L15X_HD) || defined (STM8L15X_MDP) || defined (STM8L05X_HD_VL)
+ case RTC_CSSLSE_IRQn:
+ case EXTIB_G_IRQn:
+ case EXTID_H_IRQn:
+#endif /* STM8L15X_MD */
+ Value = (uint8_t)(ITC->ISPR2 & Mask); /* Read software priority */
+ break;
+
+ case EXTI0_IRQn:
+ case EXTI1_IRQn:
+ case EXTI2_IRQn:
+ case EXTI3_IRQn:
+ Value = (uint8_t)(ITC->ISPR3 & Mask); /* Read software priority */
+ break;
+
+ case EXTI4_IRQn:
+ case EXTI5_IRQn:
+ case EXTI6_IRQn:
+ case EXTI7_IRQn:
+ Value = (uint8_t)(ITC->ISPR4 & Mask); /* Read software priority */
+ break;
+
+#if defined (STM8L15X_LD) || defined (STM8L05X_LD_VL)
+ case SWITCH_CSS_IRQn:
+#else
+ case SWITCH_CSS_BREAK_DAC_IRQn:
+#endif /* STM8L15X_LD */
+ case ADC1_COMP_IRQn:
+#if defined (STM8L15X_MD) || defined (STM8L05X_MD_VL) || defined (STM8AL31_L_MD)
+ case LCD_IRQn:
+ case TIM2_UPD_OVF_TRG_BRK_IRQn:
+#elif defined (STM8L15X_LD) || defined (STM8L05X_LD_VL)
+ case TIM2_UPD_OVF_TRG_BRK_IRQn:
+#elif defined (STM8L15X_HD) || defined (STM8L15X_MDP) || defined (STM8L05X_HD_VL)
+ case LCD_AES_IRQn:
+ case TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQn:
+#endif /* STM8L15X_MD */
+ Value = (uint8_t)(ITC->ISPR5 & Mask); /* Read software priority */
+ break;
+
+#if !defined (STM8L15X_LD) && !defined (STM8L05X_LD_VL)
+ case TIM1_UPD_OVF_TRG_IRQn:
+#endif /* STM8L15X_LD */
+#if defined (STM8L15X_MD) || defined (STM8L15X_LD) || defined (STM8L05X_MD_VL) ||\
+ defined (STM8AL31_L_MD) || defined (STM8L05X_LD_VL)
+ case TIM2_CC_IRQn:
+ case TIM3_UPD_OVF_TRG_BRK_IRQn :
+ case TIM3_CC_IRQn:
+#elif defined (STM8L15X_HD) || defined (STM8L15X_MDP) || defined (STM8L05X_HD_VL)
+ case TIM2_CC_USART2_RX_IRQn:
+ case TIM3_UPD_OVF_TRG_BRK_USART3_TX_IRQn :
+ case TIM3_CC_USART3_RX_IRQn:
+#endif /* STM8L15X_MD */
+ Value = (uint8_t)(ITC->ISPR6 & Mask); /* Read software priority */
+ break;
+
+#if !defined (STM8L15X_LD) && !defined (STM8L05X_LD_VL)
+ case TIM1_CC_IRQn:
+#endif /* STM8L15X_LD */
+ case TIM4_UPD_OVF_TRG_IRQn:
+ case SPI1_IRQn:
+#if defined (STM8L15X_MD) || defined (STM8L15X_LD) || defined (STM8L05X_MD_VL) ||\
+ defined (STM8AL31_L_MD) || defined (STM8L05X_LD_VL)
+ case USART1_TX_IRQn:
+#elif defined (STM8L15X_HD) || defined (STM8L15X_MDP) || defined (STM8L05X_HD_VL)
+ case USART1_TX_TIM5_UPD_OVF_TRG_BRK_IRQn:
+#endif /* STM8L15X_MD || STM8L15X_LD */
+ Value = (uint8_t)(ITC->ISPR7 & Mask); /* Read software priority */
+ break;
+
+#if defined (STM8L15X_MD) || defined (STM8L15X_LD) || defined (STM8L05X_MD_VL) ||\
+ defined (STM8AL31_L_MD) || defined (STM8L05X_LD_VL)
+ case USART1_RX_IRQn:
+ case I2C1_IRQn:
+#elif defined (STM8L15X_HD) || defined (STM8L15X_MDP) || defined (STM8L05X_HD_VL)
+ case USART1_RX_TIM5_CC_IRQn:
+ case I2C1_SPI2_IRQn:
+#endif /* STM8L15X_MD || STM8L15X_LD*/
+ Value = (uint8_t)(ITC->ISPR8 & Mask); /* Read software priority */
+ break;
+
+ default:
+ break;
+ }
+
+ Value >>= (uint8_t)((IRQn % 4u) * 2u);
+
+ return((ITC_PriorityLevel_TypeDef)Value);
+
+}
+
+/**
+ * @brief Sets the software priority of the specified interrupt source.
+ * @note The modification of the software priority is only possible when
+ * the interrupts are disabled.
+ * @note The normal behavior is to disable the interrupt before calling
+ * this function, and re-enable it after.
+ * @note The priority level 0 cannot be set (see product specification
+ * for more details).
+ * @param IRQn : Specifies the peripheral interrupt source.
+ * @param ITC_PriorityLevel : Specifies the software priority value to set
+ * This parameter can be one of the following values:
+ * @arg ITC_PriorityLevel_0: Software priority level 0 (cannot be written)
+ * @arg ITC_PriorityLevel_1: Software priority level 1
+ * @arg ITC_PriorityLevel_2: Software priority level 2
+ * @arg ITC_PriorityLevel_3: Software priority level 3
+ * @retval None
+ */
+void ITC_SetSoftwarePriority(IRQn_TypeDef IRQn, ITC_PriorityLevel_TypeDef ITC_PriorityLevel)
+{
+ uint8_t Mask = 0;
+ uint8_t NewPriority = 0;
+
+ /* Check function parameters */
+ assert_param(IS_ITC_IRQ(IRQn));
+ assert_param(IS_ITC_PRIORITY(ITC_PriorityLevel));
+
+ /* Check if interrupts are disabled */
+ assert_param(IS_ITC_INTERRUPTS_DISABLED);
+
+ /* Define the mask corresponding to the bits position in the SPR register */
+ /* The mask is reversed in order to clear the 2 bits after more easily */
+ Mask = (uint8_t)(~(uint8_t)(0x03U << ((IRQn % 4U) * 2U)));
+ /* Define the new priority to write */
+ NewPriority = (uint8_t)((uint8_t)(ITC_PriorityLevel) << ((IRQn % 4U) * 2U));
+
+ switch (IRQn)
+ {
+ case FLASH_IRQn:
+ case DMA1_CHANNEL0_1_IRQn:
+ case DMA1_CHANNEL2_3_IRQn:
+ ITC->ISPR1 &= Mask;
+ ITC->ISPR1 |= NewPriority;
+ break;
+
+ case EXTIE_F_PVD_IRQn:
+#if defined (STM8L15X_MD) || defined (STM8L05X_MD_VL) || defined (STM8AL31_L_MD)
+ case RTC_IRQn:
+ case EXTIB_IRQn:
+ case EXTID_IRQn:
+#elif defined (STM8L15X_LD) || defined (STM8L05X_LD_VL)
+ case RTC_CSSLSE_IRQn:
+ case EXTIB_IRQn:
+ case EXTID_IRQn:
+#elif defined (STM8L15X_HD) || defined (STM8L15X_MDP) || defined (STM8L05X_HD_VL)
+ case RTC_CSSLSE_IRQn:
+ case EXTIB_G_IRQn:
+ case EXTID_H_IRQn:
+#endif /* STM8L15X_MD */
+ ITC->ISPR2 &= Mask;
+ ITC->ISPR2 |= NewPriority;
+ break;
+
+ case EXTI0_IRQn:
+ case EXTI1_IRQn:
+ case EXTI2_IRQn:
+ case EXTI3_IRQn:
+ ITC->ISPR3 &= Mask;
+ ITC->ISPR3 |= NewPriority;
+ break;
+
+ case EXTI4_IRQn:
+ case EXTI5_IRQn:
+ case EXTI6_IRQn:
+ case EXTI7_IRQn:
+ ITC->ISPR4 &= Mask;
+ ITC->ISPR4 |= NewPriority;
+ break;
+#if !defined (STM8L15X_LD) && !defined (STM8L05X_LD_VL)
+ case SWITCH_CSS_BREAK_DAC_IRQn:
+#else
+ case SWITCH_CSS_IRQn:
+#endif /* STM8L15X_LD */
+ case ADC1_COMP_IRQn:
+#if defined (STM8L15X_MD) || defined (STM8L05X_MD_VL) || defined (STM8AL31_L_MD)
+ case LCD_IRQn:
+ case TIM2_UPD_OVF_TRG_BRK_IRQn:
+#elif defined (STM8L15X_LD) || defined (STM8L05X_LD_VL)
+ case TIM2_UPD_OVF_TRG_BRK_IRQn:
+#elif defined (STM8L15X_HD) || defined (STM8L15X_MDP) || defined (STM8L05X_HD_VL)
+ case LCD_AES_IRQn:
+ case TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQn:
+#endif /* STM8L15X_MD */
+ ITC->ISPR5 &= Mask;
+ ITC->ISPR5 |= NewPriority;
+ break;
+#if !defined (STM8L15X_LD) && !defined (STM8L05X_LD_VL)
+ case TIM1_UPD_OVF_TRG_IRQn:
+#endif /* STM8L15X_LD */
+#if defined (STM8L15X_MD) || defined (STM8L15X_LD) || defined (STM8L05X_MD_VL) ||\
+ defined (STM8AL31_L_MD) || defined (STM8L05X_LD_VL)
+ case TIM2_CC_IRQn:
+ case TIM3_UPD_OVF_TRG_BRK_IRQn :
+ case TIM3_CC_IRQn:
+#elif defined (STM8L15X_HD) || defined (STM8L15X_MDP) || defined (STM8L05X_HD_VL)
+ case TIM2_CC_USART2_RX_IRQn:
+ case TIM3_UPD_OVF_TRG_BRK_USART3_TX_IRQn :
+ case TIM3_CC_USART3_RX_IRQn:
+#endif /* STM8L15X_MD */
+ ITC->ISPR6 &= Mask;
+ ITC->ISPR6 |= NewPriority;
+ break;
+
+#if !defined (STM8L15X_LD) && !defined (STM8L05X_LD_VL)
+ case TIM1_CC_IRQn:
+#endif /* STM8L15X_LD */
+ case TIM4_UPD_OVF_TRG_IRQn:
+ case SPI1_IRQn:
+#if defined (STM8L15X_MD) || defined (STM8L15X_LD) || defined (STM8L05X_MD_VL) ||\
+ defined (STM8AL31_L_MD) || defined (STM8L05X_LD_VL)
+ case USART1_TX_IRQn:
+#elif defined (STM8L15X_HD) || defined (STM8L15X_MDP) || defined (STM8L05X_HD_VL)
+ case USART1_TX_TIM5_UPD_OVF_TRG_BRK_IRQn:
+#endif /* STM8L15X_MD */
+ ITC->ISPR7 &= Mask;
+ ITC->ISPR7 |= NewPriority;
+ break;
+
+#if defined (STM8L15X_MD) || defined (STM8L15X_LD) || defined (STM8L05X_MD_VL) ||\
+ defined (STM8AL31_L_MD) || defined (STM8L05X_LD_VL)
+ case USART1_RX_IRQn:
+ case I2C1_IRQn:
+#elif defined (STM8L15X_HD) || defined (STM8L15X_MDP) || defined (STM8L05X_HD_VL)
+ case USART1_RX_TIM5_CC_IRQn:
+ case I2C1_SPI2_IRQn:
+#endif /* STM8L15X_MD */
+ ITC->ISPR8 &= Mask;
+ ITC->ISPR8 |= NewPriority;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_iwdg.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_iwdg.c
new file mode 100644
index 00000000..8c63ba79
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_iwdg.c
@@ -0,0 +1,220 @@
+/**
+ ********************************************************************************
+ * @file stm8l15x_iwdg.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Independent watchdog (IWDG) peripheral:
+ * - Prescaler and Counter configuration
+ * - IWDG activation
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * IWDG features
+ * ===================================================================
+ *
+ * The IWDG can be started by either software or hardware (configurable
+ * through option byte).
+ *
+ * The IWDG is clocked by its own dedicated low-speed clock (LSI) and
+ * thus stays active even if the main clock fails.
+ * Once the IWDG is started, the LSI is forced ON and cannot be disabled
+ * (LSI cannot be disabled too), and the counter starts counting down from
+ * the reset value of 0xFF. When it reaches the end of count value (0x00)
+ * a system reset is generated.
+ * The IWDG counter should be reloaded at regular intervals to prevent
+ * an MCU reset.
+ *
+ * The IWDG is implemented in the VDD voltage domain that is still functional
+ * in Halt and Active Halt mode depending on the configuration of the IWDG_HALT
+ * option byte. (IWDG reset can wake-up from Halt).
+ *
+ * IWDGF flag in RST_SR register can be used to inform when a IWDG
+ * reset occurs.
+ *
+ * Min-max timeout value @38KHz (LSI): 0.10 ms / ~1.724s
+ * The IWDG timeout may vary due to LSI frequency dispersion. STM8L15x
+ * devices provide the capability to measure the LSI frequency (LSI clock
+ * connected internally to TIM2 CH1 input capture). The measured value
+ * can be used to have an IWDG timeout with an acceptable accuracy.
+ * For more information, please refer to the STM8L15x Reference manual
+ *
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * 1. Enable write access to IWDG_PR and IWDG_RLR registers using
+ * IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable) function
+ *
+ * 2. Configure the IWDG prescaler using IWDG_SetPrescaler() function
+ *
+ * 3. Configure the IWDG counter value using IWDG_SetReload() function.
+ * This value will be loaded in the IWDG counter each time the counter
+ * is reloaded, then the IWDG will start counting down from this value.
+ *
+ * 4. Start the IWDG using IWDG_Enable() function, when the IWDG is used
+ * in software mode (no need to enable the LSI, it will be enabled
+ * by hardware)
+ *
+ * 5. Then the application program must reload the IWDG counter at regular
+ * intervals during normal operation to prevent an MCU reset, using
+ * IWDG_ReloadCounter() function.
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_iwdg.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup IWDG
+ * @brief IWDG driver modules
+ * @{
+ */
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup IWDG_Private_Functions
+ * @{
+ */
+
+/** @defgroup IWDG_Group1 Prescaler and Counter configuration functions
+ * @brief Prescaler and Counter configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Prescaler and Counter configuration functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables write access to IWDG_PR and IWDG_RLR registers.
+ * @param IWDG_WriteAccess: new state of write access to IWDG_PR and IWDG_RLR registers.
+ * This parameter can be one of the following values:
+ * @arg IWDG_WriteAccess_Enable: Enable write access to IWDG_PR and IWDG_RLR registers
+ * @arg IWDG_WriteAccess_Disable: Disable write access to IWDG_PR and IWDG_RLR registers
+ * @retval None
+ */
+void IWDG_WriteAccessCmd(IWDG_WriteAccess_TypeDef IWDG_WriteAccess)
+{
+ /* Check the parameters */
+ assert_param(IS_IWDG_WRITE_ACCESS_MODE(IWDG_WriteAccess));
+ IWDG->KR = IWDG_WriteAccess; /* Write Access */
+}
+
+/**
+ * @brief Sets IWDG Prescaler value.
+ * @param IWDG_Prescaler: specifies the IWDG Prescaler value.
+ * This parameter can be one of the following values:
+ * @arg IWDG_Prescaler_4: IWDG prescaler set to 4
+ * @arg IWDG_Prescaler_8: IWDG prescaler set to 8
+ * @arg IWDG_Prescaler_16: IWDG prescaler set to 16
+ * @arg IWDG_Prescaler_32: IWDG prescaler set to 32
+ * @arg IWDG_Prescaler_64: IWDG prescaler set to 64
+ * @arg IWDG_Prescaler_128: IWDG prescaler set to 128
+ * @arg IWDG_Prescaler_256: IWDG prescaler set to 256
+ * @retval None
+ */
+void IWDG_SetPrescaler(IWDG_Prescaler_TypeDef IWDG_Prescaler)
+{
+ /* Check the parameters */
+ assert_param(IS_IWDG_PRESCALER_VALUE(IWDG_Prescaler));
+ IWDG->PR = IWDG_Prescaler;
+}
+
+/**
+ * @brief Sets IWDG Reload value.
+ * @note Write access should be enabled
+ * @param IWDG_Reload : Reload register value.
+ * This parameter must be a number between 0 and 0xFF.
+ * @retval None
+ */
+void IWDG_SetReload(uint8_t IWDG_Reload)
+{
+ IWDG->RLR = IWDG_Reload;
+}
+
+/**
+ * @brief Reloads IWDG counter with value defined in the reload register
+ * (write access to IWDG_PR and IWDG_RLR registers disabled).
+ * @param None
+ * @retval None
+ */
+void IWDG_ReloadCounter(void)
+{
+ IWDG->KR = IWDG_KEY_REFRESH;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup IWDG_Group2 IWDG activation function
+ * @brief IWDG activation function
+ *
+@verbatim
+ ===============================================================================
+ IWDG activation function
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables IWDG (write access to IWDG_PR and IWDG_RLR registers disabled).
+ * @param None
+ * @retval None
+ */
+void IWDG_Enable(void)
+{
+ IWDG->KR = IWDG_KEY_ENABLE;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
\ No newline at end of file
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_lcd.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_lcd.c
new file mode 100644
index 00000000..fe953799
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_lcd.c
@@ -0,0 +1,632 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_lcd.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the LCD controller (LCD) peripheral:
+ * - Initialization and configuration
+ * - LCD RAM memory write
+ * - Interrupts and flags management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * LCD Clock
+ * ===================================================================
+ * LCD has tow clock sources:
+ * - RTCCLK divided by 2 used to generate LCD frame rate
+ * - LCDCLK to used for LCD registers read/write access
+ *
+ * To configure the RTCCLK/LCDCLK, proceed as follows:
+ * - Enable RTC clock using CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE)
+ * function
+ * - Enable LCD clock using CLK_PeripheralClockConfig(CLK_Peripheral_LCD, ENABLE)
+ * function
+ * - Select the RTC clock source using the CLK_RTCClockConfig() function.
+ *
+ * ===================================================================
+ * LCD and low power modes
+ * ===================================================================
+ * The LCD remains active during Active-halt, Wait, Low power run and
+ * Low power wait modes unless disabled
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * 1. Enable RTC clock using CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE) function
+ *
+ * 2. Enable LCD clock using CLK_PeripheralClockConfig(CLK_Peripheral_LCD, ENABLE) function
+ *
+ * 3. Select the RTC clock source using the CLK_RTCClockConfig() function.
+ *
+ * 4. Configure the LCD prescaler, divider, duty, bias and voltage source
+ * using LCD_Init() function
+ *
+ * 5. Call the LCD_PortMaskConfig() function to assign the unused SEGx
+ * (segment) and COMx (common) pins as standard general purpose IOs
+ *
+ * 6. Optionally you can enable/configure:
+ * - LCD High Drive using the LCD_HighDriveCmd() function
+ * - LCD Pulse ON Duration using the LCD_PulseOnDurationConfig() function
+ * - LCD Dead Time using the LCD_DeadTimeConfig() function
+ * - The LCD Blink mode and frequency using the LCD_BlinkConfig() function
+ * - The LCD Contrast using the LCD_ContrastConfig() function
+ *
+ * 7. Call the LCD_Cmd() to enable the LCD controller
+ *
+ * 8. Write to the LCD RAM memory using the LCD_WriteRAM() function.
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_lcd.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup LCD
+ * @brief LCD driver modules
+ * @{
+ */
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup LCD_Private_Functions
+ * @{
+ */
+
+/** @defgroup LCD_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Initialization and Configuration functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the LCD Controller registers to their default reset values.
+ * @param None
+ * @retval None
+ */
+void LCD_DeInit(void)
+{
+ uint8_t counter = 0;
+
+ LCD->CR1 = LCD_CR1_RESET_VALUE;
+ LCD->CR2 = LCD_CR2_RESET_VALUE;
+ LCD->CR3 = LCD_CR3_RESET_VALUE;
+ LCD->FRQ = LCD_FRQ_RESET_VALUE;
+
+ for (counter = 0;counter < 0x05; counter++)
+ {
+ LCD->PM[counter] = LCD_PM_RESET_VALUE;
+ }
+
+ for (counter = 0;counter < 0x16; counter++)
+ {
+ LCD->RAM[counter] = LCD_RAM_RESET_VALUE;
+ }
+
+ LCD->CR4 = LCD_CR4_RESET_VALUE;
+
+}
+
+/**
+ * @brief Initializes the LCD according to the specified parameters.
+ * @param LCD_CLKPrescalerDiv : LCD clock prescaler
+ * This parameter can be one of the following values:
+ * @arg LCD_Prescaler_1: CLKprescaler = ClKinput
+ * @arg LCD_Prescaler_2: CLKprescaler = ClKinput/2
+ * @arg LCD_Prescaler_4: CLKprescaler = ClKinput/4
+ * @arg LCD_Prescaler_8: CLKprescaler = ClKinput/8
+ * @arg LCD_Prescaler_16: CLKprescaler = ClKinput/16
+ * @arg LCD_Prescaler_32: CLKprescaler = ClKinput/32
+ * @arg LCD_Prescaler_64: CLKprescaler = ClKinput/64
+ * @arg LCD_Prescaler_128: CLKprescaler = ClKinput/128
+ * @arg LCD_Prescaler_256: CLKprescaler = ClKinput/256
+ * @arg LCD_Prescaler_512: CLKprescaler = ClKinput/512
+ * @arg LCD_Prescaler_1024: CLKprescaler = ClKinput/1024
+ * @arg LCD_Prescaler_2048: CLKprescaler = ClKinput/2048
+ * @arg LCD_Prescaler_4096: CLKprescaler = ClKinput/4096
+ * @arg LCD_Prescaler_8192: CLKprescaler = ClKinput/8192
+ * @arg LCD_Prescaler_16384: CLKprescaler = ClKinput/16384
+ * @arg LCD_Prescaler_32768: CLKprescaler = ClKinput/32768
+ * @param LCD_Divider : LCD clock divider
+ * This parameter can be one of the following values:
+ * @arg LCD_Divider_16: LCD frequency = CLKprescaler/16
+ * @arg LCD_Divider_17: LCD frequency = CLKprescaler/17
+ * @arg LCD_Divider_18: LCD frequency = CLKprescaler/18
+ * @arg LCD_Divider_19: LCD frequency = CLKprescaler/19
+ * @arg LCD_Divider_20: LCD frequency = CLKprescaler/20
+ * @arg LCD_Divider_21: LCD frequency = CLKprescaler/21
+ * @arg LCD_Divider_22: LCD frequency = CLKprescaler/22
+ * @arg LCD_Divider_23: LCD frequency = CLKprescaler/23
+ * @arg LCD_Divider_24: LCD frequency = CLKprescaler/24
+ * @arg LCD_Divider_25: LCD frequency = CLKprescaler/25
+ * @arg LCD_Divider_26: LCD frequency = CLKprescaler/26
+ * @arg LCD_Divider_27: LCD frequency = CLKprescaler/27
+ * @arg LCD_Divider_28: LCD frequency = CLKprescaler/28
+ * @arg LCD_Divider_29: LCD frequency = CLKprescaler/29
+ * @arg LCD_Divider_30: LCD frequency = CLKprescaler/30
+ * @arg LCD_Divider_31: LCD frequency = CLKprescaler/31
+ * @param LCD_Duty : LCD duty
+ * This parameter can be one of the following values:
+ * @arg LCD_Duty_Static: Static duty
+ * @arg LCD_Duty_1_2: 1/2 duty
+ * @arg LCD_Duty_1_3: 1/3 duty
+ * @arg LCD_Duty_1_4: 1/4 duty
+ * @arg LCD_Duty_1_8: 1/8 duty
+ * @param LCD_Bias : LCD bias
+ * This parameter can be one of the following values:
+ * @arg LCD_Bias_1_4: 1/4 bias
+ * @arg LCD_Bias_1_3: 1/3 bias
+ * @arg LCD_Bias_1_2: 1/2 bias
+ * @param LCD_VoltageSource : LCD voltage source
+ * This parameter can be one of the following values:
+ * @arg LCD_VoltageSource_Internal: Internal voltage source
+ * @arg LCD_VoltageSource_External: External voltage source
+ * @retval None
+ */
+void LCD_Init(LCD_Prescaler_TypeDef LCD_Prescaler, LCD_Divider_TypeDef LCD_Divider,
+ LCD_Duty_TypeDef LCD_Duty, LCD_Bias_TypeDef LCD_Bias,
+ LCD_VoltageSource_TypeDef LCD_VoltageSource)
+{
+ /* Check function parameters */
+ assert_param(IS_LCD_CLOCK_PRESCALER(LCD_Prescaler));
+ assert_param(IS_LCD_CLOCK_DIVIDER(LCD_Divider));
+ assert_param(IS_LCD_DUTY(LCD_Duty));
+ assert_param(IS_LCD_BIAS(LCD_Bias));
+ assert_param(IS_LCD_VOLTAGE_SOURCE(LCD_VoltageSource));
+
+ LCD->FRQ &= (uint8_t)(~LCD_FRQ_PS); /* Clear the prescaler bits */
+ LCD->FRQ |= LCD_Prescaler;
+
+ LCD->FRQ &= (uint8_t)(~LCD_FRQ_DIV); /* Clear the divider bits */
+ LCD->FRQ |= LCD_Divider;
+
+ /* Configure the Duty cycle */
+ LCD->CR1 &= (uint8_t)(~LCD_CR1_DUTY); /* Clear the duty bits */
+ LCD->CR4 &= (uint8_t)(~LCD_CR4_DUTY8); /* Clear the DUTY8 bit */
+
+ if (LCD_Duty == LCD_Duty_1_8)
+ {
+ LCD->CR4 |= (uint8_t)((uint8_t)((uint8_t)LCD_Duty & (uint8_t)0xF0) >> 4);
+ }
+ else
+ {
+ LCD->CR1 |= (uint8_t)((uint8_t)LCD_Duty & (uint8_t)0x0F);
+ }
+
+ /* Configure the Bias */
+ LCD->CR1 &= (uint8_t)(~LCD_CR1_B2); /* Clear the B2 bit */
+ LCD->CR4 &= (uint8_t)(~LCD_CR4_B4); /* Clear the B4 bit */
+
+ if (LCD_Bias == LCD_Bias_1_4)
+ {
+ LCD->CR1 |= (uint8_t)((uint8_t)LCD_Bias & (uint8_t)0x0F);
+ LCD->CR4 |= (uint8_t)((uint8_t)((uint8_t)LCD_Bias & (uint8_t)0xF0) >> 4);
+ }
+ else
+ {
+ LCD->CR1 |= (uint8_t)((uint8_t)LCD_Bias & (uint8_t)0x0F);
+ }
+
+ LCD->CR2 &= (uint8_t)(~LCD_CR2_VSEL); /* Clear the voltage source bit */
+ LCD->CR2 |= LCD_VoltageSource;
+
+}
+
+/**
+ * @brief Configures the LCD Port Mask.
+ * @param LCD_PortMaskRegister: The LCD register index in the port mask matrix.
+ * This parameter can be one of the following values:
+ * @arg LCD_PortMaskRegister_0: PortMask Register 0
+ * @arg LCD_PortMaskRegister_1: PortMask Register 1
+ * @arg LCD_PortMaskRegister_2: PortMask Register 2
+ * @arg LCD_PortMaskRegister_3: PortMask Register 3
+ * @arg LCD_PortMaskRegister_4: PortMask Register 4
+ * @arg LCD_PortMaskRegister_5: PortMask Register 5
+ * @param LCD_Mask : Value to be written
+ * @retval None
+ */
+void LCD_PortMaskConfig(LCD_PortMaskRegister_TypeDef LCD_PortMaskRegister, uint8_t LCD_Mask)
+{
+ /* Check function parameters */
+ assert_param(IS_LCD_PORT_MASK(LCD_PortMaskRegister));
+
+ /* Copy data bytes to Port mask register */
+ LCD->PM[LCD_PortMaskRegister] = LCD_Mask;
+
+}
+
+/**
+ * @brief Enables or disables the LCD Controller.
+ * @param NewState: new state of the LCD peripheral.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ * @retval None
+ */
+void LCD_Cmd(FunctionalState NewState)
+{
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ LCD->CR3 |= LCD_CR3_LCDEN; /* Enable the LCD peripheral*/
+ }
+ else
+ {
+ LCD->CR3 &= (uint8_t)(~LCD_CR3_LCDEN); /* Disable the LCD peripheral*/
+ }
+}
+
+/**
+ * @brief Enables or disables the low resistance divider. Displays with high
+ * internal resistance may need a longer drive time to achieve
+ * satisfactory contrast. This function is useful in this case if some
+ * additional power consumption can be tolerated.
+ * @note When this mode is enabled, the PulseOn Duration (PON) have to be
+ * programmed to 1/CK_PS (LCD_PulseOnDuration_1).
+ * @param NewState: new state of the low resistance divider.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void LCD_HighDriveCmd(FunctionalState NewState)
+{
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ LCD->CR2 |= LCD_CR2_HD; /* Permanently enable low resistance divider */
+ }
+ else
+ {
+ LCD->CR2 &= (uint8_t)(~LCD_CR2_HD); /* Permanently disable low resistance divider */
+ }
+}
+
+/**
+ * @brief Configures the LCD pulses on duration.
+ * @param LCD_PulseOnDuration: specifies the LCD pulse on duration in terms of
+ * CLKprescaler (prescaled LCD clock period) pulses.
+ * This parameter can be one of the following values:
+ * @arg LCD_PulseOnDuration_0: 0 pulse
+ * @arg LCD_PulseOnDuration_1: Pulse ON duration = 1/CLKprescaler
+ * @arg LCD_PulseOnDuration_2: Pulse ON duration = 2/CLKprescaler
+ * @arg LCD_PulseOnDuration_3: Pulse ON duration = 3/CLKprescaler
+ * @arg LCD_PulseOnDuration_4: Pulse ON duration = 4/CLKprescaler
+ * @arg LCD_PulseOnDuration_5: Pulse ON duration = 5/CLKprescaler
+ * @arg LCD_PulseOnDuration_6: Pulse ON duration = 6/CLKprescaler
+ * @arg LCD_PulseOnDuration_7: Pulse ON duration = 7/CLKprescaler
+ * @retval None
+ */
+void LCD_PulseOnDurationConfig(LCD_PulseOnDuration_TypeDef LCD_PulseOnDuration)
+{
+ /* Check function parameters */
+ assert_param(IS_LCD_PULSE_DURATION(LCD_PulseOnDuration));
+
+ LCD->CR2 &= (uint8_t)(~LCD_CR2_PON); /* Clear the pulses on duration bits */
+ LCD->CR2 |= LCD_PulseOnDuration;
+}
+
+/**
+ * @brief Configures the LCD dead time.
+ * @param LCD_DeadTime: specifies the LCD dead time.
+ * This parameter can be one of the following values:
+ * @arg LCD_DeadTime_0: No dead Time
+ * @arg LCD_DeadTime_1: One Phase between different couple of Frame
+ * @arg LCD_DeadTime_2: Two Phase between different couple of Frame
+ * @arg LCD_DeadTime_3: Three Phase between different couple of Frame
+ * @arg LCD_DeadTime_4: Four Phase between different couple of Frame
+ * @arg LCD_DeadTime_5: Five Phase between different couple of Frame
+ * @arg LCD_DeadTime_6: Six Phase between different couple of Frame
+ * @arg LCD_DeadTime_7: Seven Phase between different couple of Frame
+ * @retval None
+ */
+void LCD_DeadTimeConfig(LCD_DeadTime_TypeDef LCD_DeadTime)
+{
+ /* Check function parameters */
+ assert_param(IS_LCD_DEAD_TIME(LCD_DeadTime));
+
+ LCD->CR3 &= (uint8_t)(~LCD_CR3_DEAD); /* Clear the dead time bits */
+
+ LCD->CR3 |= LCD_DeadTime;
+
+}
+
+/**
+ * @brief Configures the LCD Blink mode and Blink frequency.
+ * @param LCD_BlinkMode: specifies the LCD blink mode.
+ * This parameter can be one of the following values:
+ * @arg LCD_BlinkMode_Off: Blink disabled
+ * @arg LCD_BlinkMode_SEG0_COM0: Blink enabled on SEG[0], COM[0] (1 pixel)
+ * @arg LCD_BlinkMode_SEG0_AllCOM: Blink enabled on SEG[0], all COM (up to 8
+ * pixels according to the programmed duty)
+ * @arg LCD_BlinkMode_AllSEG_AllCOM: Blink enabled on all SEG and all COM
+ * (all pixels)
+ * @param LCD_BlinkFrequency: specifies the LCD blink frequency.
+ * This parameter can be one of the following values:
+ * @arg LCD_BlinkFrequency_Div8: The Blink frequency = fLcd/8
+ * @arg LCD_BlinkFrequency_Div16: The Blink frequency = fLcd/16
+ * @arg LCD_BlinkFrequency_Div32: The Blink frequency = fLcd/32
+ * @arg LCD_BlinkFrequency_Div64: The Blink frequency = fLcd/64
+ * @arg LCD_BlinkFrequency_Div128: The Blink frequency = fLcd/128
+ * @arg LCD_BlinkFrequency_Div256: The Blink frequency = fLcd/256
+ * @arg LCD_BlinkFrequency_Div512: The Blink frequency = fLcd/512
+ * @arg LCD_BlinkFrequency_Div1024: The Blink frequency = fLcd/1024
+ * @retval None
+ */
+void LCD_BlinkConfig(LCD_BlinkMode_TypeDef LCD_BlinkMode, LCD_BlinkFrequency_TypeDef LCD_BlinkFrequency)
+{
+ /* Check function parameters */
+ assert_param(IS_LCD_BLINK_MODE(LCD_BlinkMode));
+ assert_param(IS_LCD_BLINK_FREQUENCY(LCD_BlinkFrequency));
+
+ LCD->CR1 &= (uint8_t)(~LCD_CR1_BLINK); /* Clear the blink mode bits */
+ LCD->CR1 |= LCD_BlinkMode; /* Config the LCD Blink Mode */
+
+ LCD->CR1 &= (uint8_t)(~LCD_CR1_BLINKF); /* Clear the blink frequency bits */
+ LCD->CR1 |= LCD_BlinkFrequency; /* Config the LCD Blink Frequency */
+
+}
+
+/**
+ * @brief Configures the LCD Contrast.
+ * @param LCD_Contrast: specifies the LCD Contrast.
+ * This parameter can be one of the following values:
+ * @arg LCD_Contrast_Level_0: Medium Density / High Density Maximum Voltage = 2.60V / 2.60V
+ * @arg LCD_Contrast_Level_1: Medium Density / High Density Maximum Voltage = 2.70V / 2.73V
+ * @arg LCD_Contrast_Level_2: Medium Density / High Density Maximum Voltage = 2.80V / 2.86V
+ * @arg LCD_Contrast_Level_3: Medium Density / High Density Maximum Voltage = 2.90V / 2.99V
+ * @arg LCD_Contrast_Level_4: Medium Density / High Density Maximum Voltage = 3.00V / 3.12V
+ * @arg LCD_Contrast_Level_5: Medium Density / High Density Maximum Voltage = 3.10V / 3.25V
+ * @arg LCD_Contrast_Level_6: Medium Density / High Density Maximum Voltage = 3.20V / 3.38V
+ * @arg LCD_Contrast_Level_7: Medium Density / High Density Maximum Voltage = 3.30V / 3.51V
+ * @retval None
+ */
+void LCD_ContrastConfig(LCD_Contrast_TypeDef LCD_Contrast)
+{
+ /* Check function parameters */
+ assert_param(IS_LCD_CONTRAST(LCD_Contrast));
+
+ LCD->CR2 &= (uint8_t)(~LCD_CR2_CC); /* Clear the contrast bits */
+ LCD->CR2 |= LCD_Contrast; /* Select the maximum voltage value Vlcd */
+
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup LCD_Group2 LCD RAM memory write functions
+ * @brief LCD RAM memory write functions
+ *
+@verbatim
+ ===============================================================================
+ LCD RAM memory write functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Writes a word in the specific LCD RAM.
+ * @param LCD_RAMRegister: specifies the LCD Contrast.
+ * This parameter can be one of the following values:
+ * @arg LCD_RAMRegister_0: LCD RAM Register 0
+ * @arg LCD_RAMRegister_1: LCD RAM Register 1
+ * @arg LCD_RAMRegister_2: LCD RAM Register 2
+ * @arg LCD_RAMRegister_3: LCD RAM Register 3
+ * @arg LCD_RAMRegister_4: LCD RAM Register 4
+ * @arg LCD_RAMRegister_5: LCD RAM Register 5
+ * @arg LCD_RAMRegister_6: LCD RAM Register 6
+ * @arg LCD_RAMRegister_7: LCD RAM Register 7
+ * @arg LCD_RAMRegister_8: LCD RAM Register 8
+ * @arg LCD_RAMRegister_9: LCD RAM Register 9
+ * @arg LCD_RAMRegister_10: LCD RAM Register 10
+ * @arg LCD_RAMRegister_11: LCD RAM Register 11
+ * @arg LCD_RAMRegister_12: LCD RAM Register 12
+ * @arg LCD_RAMRegister_13: LCD RAM Register 13
+ * @arg LCD_RAMRegister_14: LCD RAM Register 14
+ * @arg LCD_RAMRegister_15: LCD RAM Register 15
+ * @arg LCD_RAMRegister_15: LCD RAM Register 16
+ * @arg LCD_RAMRegister_15: LCD RAM Register 17
+ * @arg LCD_RAMRegister_15: LCD RAM Register 18
+ * @arg LCD_RAMRegister_15: LCD RAM Register 19
+ * @arg LCD_RAMRegister_15: LCD RAM Register 20
+ * @arg LCD_RAMRegister_15: LCD RAM Register 21
+ * @param LCD_Data: specifies LCD Data Value to be written.
+ * @retval None
+ */
+void LCD_WriteRAM(LCD_RAMRegister_TypeDef LCD_RAMRegister, uint8_t LCD_Data)
+{
+ /* Check function parameters */
+ assert_param(IS_LCD_RAM_REGISTER(LCD_RAMRegister));
+
+ /* Copy data bytes to RAM register */
+ LCD->RAM[LCD_RAMRegister] = LCD_Data;
+
+}
+
+/**
+ * @brief Select the LCD page where the data will be written.
+ * @param LCD_Page: The accessed LCD page.
+ * This parameter can be one of the following values:
+ * @arg LCD_PageSelection_FirstPage: The LCD RAM is selected as the first page
+ * @arg LCD_PageSelection_SecondPage: The LCD RAM is selected as the second page
+ * @retval None
+ */
+void LCD_PageSelect(LCD_PageSelection_TypeDef LCD_PageSelection)
+{
+ /* Check function parameters */
+ assert_param(IS_LCD_PAGE_SELECT(LCD_PageSelection));
+
+ LCD->CR4 &= (uint8_t)(~LCD_CR4_PAGECOM); /* Clear the PAGE COM bit */
+ LCD->CR4 |= LCD_PageSelection; /* Select the LCD page */
+
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup LCD_Group3 Interrupts and flags management functions
+ * @brief Interrupts and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts and flags management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Enables or disables the start of frame interrupt.
+ * @param NewState: new state of the specified LCD interrupts.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void LCD_ITConfig(FunctionalState NewState)
+{
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ LCD->CR3 |= LCD_CR3_SOFIE; /* Enable interrupt*/
+ }
+ else
+ {
+ LCD->CR3 &= (uint8_t)(~LCD_CR3_SOFIE); /* Disable interrupt*/
+ }
+
+}
+
+/**
+ * @brief Checks whether the LCD start of new frame flag is set or not.
+ * @retval The new state of the start of new frame flag.
+ * This returned value can be: SET or RESET.
+ */
+FlagStatus LCD_GetFlagStatus(void)
+{
+ FlagStatus status = RESET;
+
+ /* Check the status of the start of new frame LCD flag */
+ if ((LCD->CR3 & (uint8_t)LCD_CR3_SOF) != (uint8_t)RESET)
+ {
+ status = SET; /* Flag is set */
+ }
+ else
+ {
+ status = RESET; /* Flag is reset*/
+ }
+ /* Return the FLAG status */
+ return status;
+
+}
+
+/**
+ * @brief Clears the start of frame LCD flag.
+ * @param None
+ * @retval None
+ */
+void LCD_ClearFlag(void)
+{
+ /* Clear the flag bit */
+ LCD->CR3 |= (uint8_t)(LCD_CR3_SOFC);
+
+}
+
+/**
+ * @brief Checks whether the start of frame interrupt has occurred or not.
+ * @param None
+ * @retval The new state of the start of new frame interrupt.
+ * This returned value can be: SET or RESET.
+ */
+ITStatus LCD_GetITStatus(void)
+{
+ ITStatus pendingbitstatus = RESET;
+ uint8_t enablestatus = 0;
+
+ enablestatus = (uint8_t)((uint8_t)LCD->CR3 & LCD_CR3_SOFIE);
+ /* Check the status of the start of frame interrupt */
+ if (((LCD->CR3 & LCD_CR3_SOF) != RESET) && enablestatus)
+ {
+ /* ITPENDINGBIT is set */
+ pendingbitstatus = SET;
+ }
+ else
+ {
+ /* ITPENDINGBIT is reset */
+ pendingbitstatus = RESET;
+ }
+ /* Return the ITPENDINGBIT status */
+ return pendingbitstatus;
+
+}
+
+/**
+ * @brief Clears the start of frame interrupt pending bits.
+ * @param None
+ * @retval None
+ */
+void LCD_ClearITPendingBit(void)
+{
+ /* Clear the flag bit */
+ LCD->CR3 |= (uint8_t)(LCD_CR3_SOFC);
+
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_pwr.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_pwr.c
new file mode 100644
index 00000000..dc3ebf3b
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_pwr.c
@@ -0,0 +1,358 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_pwr.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Power Controller (PWR) peripheral:
+ * - PVD configuration
+ * - Ultra Low Power mode configuration
+ * - Interrupts and flags management
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_pwr.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup PWR
+ * @brief PWR driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup PWR_Private_Functions
+ * @{
+ */
+
+/** @defgroup PWR_Group1 PVD configuration functions
+ * @brief PVD configuration functions
+ *
+@verbatim
+ ===============================================================================
+ PVD configuration functions
+ ===============================================================================
+
+ - The PVD is used to monitor the VDD power supply by comparing it to a threshold
+ selected by the PVD Level (PLS[2:0] bits in the PWR_CSR1).
+ - The PVD can use an external input analog voltage (PVD_IN) which is compared
+ internally to VREFINT. The PVD_IN (PE6) has to be configured in Analog mode
+ when PWR_PVDLevel_PVDIn is selected (PLS[2:0] = 111).
+ - A PVDO flag is available to indicate if VDD/VDDA is higher or lower than the
+ PVD threshold. An interrupt is generated in case enabled for PVD.
+ - The PVD interrup event has the capability to wake up the CPU from Halt/Active Halt modes.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the PWR peripheral registers to their default reset values.
+ * @param None
+ * @retval None
+ */
+void PWR_DeInit(void)
+{
+ PWR->CSR1 = PWR_CSR1_PVDIF;
+ PWR->CSR2 = PWR_CSR2_RESET_VALUE;
+}
+
+/**
+ * @brief Configures the voltage threshold detected by the Power Voltage Detector(PVD).
+ * @param PWR_PVDLevel: specifies the PVD detection level
+ * This parameter can be one of the following values:
+ * @arg PWR_PVDLevel_1V85: PVD detection level set to 1.85V
+ * @arg PWR_PVDLevel_2V05: PVD detection level set to 2.05V
+ * @arg PWR_PVDLevel_2V26: PVD detection level set to 2.26V
+ * @arg PWR_PVDLevel_2V45: PVD detection level set to 2.45V
+ * @arg PWR_PVDLevel_2V65: PVD detection level set to 2.65V
+ * @arg PWR_PVDLevel_2V85: PVD detection level set to 2.85V
+ * @arg PWR_PVDLevel_3V05: PVD detection level set to 3.05V
+ * @arg PWR_PVDLevel_PVDIn: External input analog voltage (Compare internally to VREFINT)
+ * @retval None
+ */
+void PWR_PVDLevelConfig(PWR_PVDLevel_TypeDef PWR_PVDLevel)
+{
+ /* Check the parameters */
+ assert_param(IS_PWR_PVD_LEVEL(PWR_PVDLevel));
+
+ /* Clear the PVD level */
+ PWR->CSR1 &= (uint8_t)(~PWR_CSR1_PLS);
+
+ /* Configure the PVD level */
+ PWR->CSR1 |= PWR_PVDLevel;
+
+}
+
+/**
+ * @brief Enables or disables the Power Voltage Detector(PVD).
+ * @param NewState: new state of the PVD.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void PWR_PVDCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the PWR PVD */
+ PWR->CSR1 |= PWR_CSR1_PVDE;
+ }
+ else
+ {
+ /* Disable the PWR PVD */
+ PWR->CSR1 &= (uint8_t)(~PWR_CSR1_PVDE);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup PWR_Group2 Ultra Low Power mode configuration functions
+ * @brief Ultra Low Power mode configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Ultra Low Power mode configuration functions
+ ===============================================================================
+
+ - The internal voltage reference consumption is not negligible, in particular
+ in Halt and Active Halt modes. To reduce power consumption, use the PWR_UltraLowPowerCmd()
+ function (ULP bit (Ultra low power) in the PWR_CSR2 register) to disable the
+ internal voltage reference. However, in this case, when exiting from the
+ Halt/Active Halt modes, the functions managed through the internal voltage reference
+ are not reliable during the internal voltage reference startup time (up to 3 ms).
+ To reduce the wakeup time, the device can exit from Halt/Active Halt modes without
+ waiting for the internal voltage reference startup time. This is performed
+ by using the PWR_FastWakeUpCmd() function (setting the FWU bit (Fast
+ wakeup) in the PWR_CSR2 register) before entering Halt/Active Halt mode.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the Fast WakeUp from Ultra Low Power mode.
+ * @param NewState: new state of the Fast WakeUp functionality.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void PWR_FastWakeUpCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the PWR FWU */
+ PWR->CSR2 |= PWR_CSR2_FWU;
+ }
+ else
+ {
+ /* Disable the PWR FWU */
+ PWR->CSR2 &= (uint8_t)(~PWR_CSR2_FWU);
+ }
+}
+
+/**
+ * @brief Enables or disables the Ultra Low Power mode.
+ * @param NewState: new state of the Ultra Low Power mode.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void PWR_UltraLowPowerCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the PWR ULP */
+ PWR->CSR2 |= PWR_CSR2_ULP;
+ }
+ else
+ {
+ /* Disable the PWR ULP */
+ PWR->CSR2 &= (uint8_t)(~PWR_CSR2_ULP);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup PWR_Group3 Interrupts and Flags management functions
+ * @brief Interrupts and Flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts and Flags management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures the Programmable Voltage Detector (PVD) Interrupt .
+ * @param NewState : Indicates the new state of the PVD interrupt.
+ * @retval None
+ */
+void PWR_PVDITConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the PVD interrupt */
+ PWR->CSR1 |= PWR_CSR1_PVDIEN;
+ }
+ else
+ {
+ /* Disable the PVD interrupt */
+ PWR->CSR1 &= (uint8_t)(~PWR_CSR1_PVDIEN);
+ }
+}
+
+/**
+ * @brief Checks whether the specified PWR flag is set or not.
+ * @param PWR_FLAG: specifies the flag to check.
+ * This parameter can be one of the following values:
+ * @arg PWR_FLAG_PVDOF: PVD Output. This flag is valid only if PVD is enabled
+ * by the PWR_PVDCmd() function.
+ * @arg PWR_FLAG_VREFINTF: Internal Voltage Reference Ready flag. This
+ * flag indicates the state of the internal voltage reference, VREFINT.
+ * @arg PWR_FLAG_PVDIF: PVD Interrupt Flag, it's set by hardware when a PVD
+ * event occurs
+ * @retval The new state of PWR_FLAG (SET or RESET).
+ */
+FlagStatus PWR_GetFlagStatus(PWR_FLAG_TypeDef PWR_FLAG)
+{
+ FlagStatus bitstatus = RESET;
+
+ /* Check the parameters */
+ assert_param(IS_PWR_FLAG(PWR_FLAG));
+
+ if ((PWR_FLAG & PWR_FLAG_VREFINTF) != 0)
+ {
+ if ((PWR->CSR2 & PWR_CR2_VREFINTF) != (uint8_t)RESET )
+ {
+ bitstatus = SET;
+ }
+ else
+ {
+ bitstatus = RESET;
+ }
+ }
+ else
+ {
+ if ((PWR->CSR1 & PWR_FLAG) != (uint8_t)RESET )
+ {
+ bitstatus = SET;
+ }
+ else
+ {
+ bitstatus = RESET;
+ }
+ }
+
+ /* Return the flag status */
+ return((FlagStatus)bitstatus);
+}
+
+/**
+ * @brief Clears the PWR PVDIF Flag.
+ * @param None
+ * @retval None
+ */
+void PWR_PVDClearFlag(void)
+{
+ /* Set the PVDIF to clear it */
+ PWR->CSR1 |= PWR_CSR1_PVDIF;
+}
+
+/**
+ * @brief Checks whether the PVD interrupt has occurred or not.
+ * @param None
+ * @retval The new state of the PVD Interrupt (SET or RESET).
+ */
+ITStatus PWR_PVDGetITStatus(void)
+{
+ ITStatus bitstatus = RESET;
+
+ uint8_t PVD_itStatus = 0x0, PVD_itEnable = 0x0;
+
+ PVD_itStatus = (uint8_t)(PWR->CSR1 & (uint8_t)PWR_CSR1_PVDIF);
+ PVD_itEnable = (uint8_t)(PWR->CSR1 & (uint8_t)PWR_CSR1_PVDIEN);
+
+ if ((PVD_itStatus != (uint8_t)RESET ) && (PVD_itEnable != (uint8_t)RESET))
+ {
+ bitstatus = (ITStatus)SET;
+ }
+ else
+ {
+ bitstatus = (ITStatus)RESET;
+ }
+ return ((ITStatus)bitstatus);
+}
+
+/**
+ * @brief Clears the PWR interrupt pending bit.
+ * @param None
+ * @retval None
+ */
+void PWR_PVDClearITPendingBit(void)
+{
+ /* Set the PVDIF to clear it */
+ PWR->CSR1 |= PWR_CSR1_PVDIF;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_rst.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_rst.c
new file mode 100644
index 00000000..ffeeacfb
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_rst.c
@@ -0,0 +1,171 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_rst.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the RST peripheral:
+ * - Flag management
+ * - NRST Pin configuration
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * RST specific features
+ * ===================================================================
+ *
+ * When a reset occurs, there is a reset phase from the external pin
+ * pull-down to the internal reset signal release. During this phase,
+ * the microcontroller sets some hardware configurations before going
+ * to the reset vector.
+ * At the end of this phase, most of the registers are configured with
+ * their “reset state” values.
+ * During the reset phase, some pin configurations may be different from
+ * their “reset state” configuration.
+ *
+ * The NRST pin is an input and can be configured as open-drain output
+ * using the RST_GPOutputEnable() function
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "stm8l15x_rst.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup RST
+ * @brief RST driver modules
+ * @{
+ */
+/* Private define ------------------------------------------------------------*/
+#define RST_CR_MASK 0xD0 /*!< Enable the GPIO */
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup RST_Private_Functions
+ * @{
+ */
+
+/** @defgroup RST_Group1 Flag management functions
+ * @brief Flag management functions
+ *
+@verbatim
+ ===============================================================================
+ Flag management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Checks whether the specified RST flag is set or not.
+ * @param RST_Flag : specify the reset flag to check.
+ * This parameter can be one of the following values:
+ * @arg RST_FLAG_PORF: POR reset flag
+ * @arg RST_FLAG_SWIMF: SWIM reset flag
+ * @arg RST_FLAG_ILLOPF: Illegal opcode reset flag
+ * @arg RST_FLAG_IWDGF: Independent watchdog reset flag
+ * @arg RST_FLAG_WWDGF: Window watchdog reset flag
+ * @arg RST_FLAG_BORF: BOR reset flag
+ * @retval The new state of RST_Flag (SET or RESET).
+ */
+FlagStatus RST_GetFlagStatus(RST_FLAG_TypeDef RST_Flag)
+{
+ /* Check the parameters */
+ assert_param(IS_RST_FLAG(RST_Flag));
+
+ /* Get flag status */
+ return((FlagStatus)(((uint8_t)(RST->SR & RST_Flag) == (uint8_t)0x00) ? RESET : SET));
+}
+
+/**
+ * @brief Clears the specified RST flag.
+ * @param RST_Flag : specify the reset flag to check.
+ * This parameter can be one of the following values:
+ * @arg RST_FLAG_PORF: POR reset flag
+ * @arg RST_FLAG_SWIMF: SWIM reset flag
+ * @arg RST_FLAG_ILLOPF: Illegal opcode reset flag
+ * @arg RST_FLAG_IWDGF: Independent watchdog reset flag
+ * @arg RST_FLAG_WWDGF: Window watchdog reset flag
+ * @arg RST_FLAG_BORF: BOR reset flag
+ * @retval None
+ */
+void RST_ClearFlag(RST_FLAG_TypeDef RST_Flag)
+{
+ /* Check the parameters */
+ assert_param(IS_RST_FLAG(RST_Flag));
+
+ RST->SR = (uint8_t)RST_Flag;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RST_Group2 NRST Pin configuration function
+ * @brief NRST Pin configuration function
+ *
+@verbatim
+ ===============================================================================
+ NRST Pin configuration function
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures the reset pad as GP output.
+ * @param None
+ * @retval None
+ */
+void RST_GPOutputEnable(void)
+{
+
+ RST->CR = RST_CR_MASK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_rtc.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_rtc.c
new file mode 100644
index 00000000..df0d0bbd
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_rtc.c
@@ -0,0 +1,2245 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_rtc.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Real-Time Clock (RTC) peripheral:
+ * - Initialization
+ * - Calendar (Time and Date) configuration
+ * - Alarm configuration
+ * - WakeUp Timer configuration
+ * - Daylight Saving configuration
+ * - Output pin Configuration
+ * - Smooth Calibration configuration
+ * - Tampers configuration
+ * - Output Type configuration
+ * - Interrupts and flags management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * RTC Domain Reset
+ * ===================================================================
+ * After power-on reset, the RTC domain (RTC registers) is reset.
+ *
+ * ===================================================================
+ * RTC Operating Condition
+ * ===================================================================
+ * As long as the supply voltage remains in the operating range,
+ * the RTC never stops, regardless of the device status (Run mode,
+ * low power modes or under reset).
+ *
+ * ===================================================================
+ * RTC Domain Access
+ * ===================================================================
+ * After reset, the RTC domain (RTC registers) is protected against
+ * possible stray write accesses.
+ * To enable access to the RTC registers, proceed as follows:
+ * - Select the RTC clock source using the CLK_RTCClockConfig()
+ * function : HSE, HSI, LSE or LSI.
+ * CLK_RTCClockConfig(CLK_RTCCLKSource_HSI, CLK_RTCCLKDiv_1)
+ * - Enable RTC Clock using the CLK_PeripheralClockConfig() function
+ * : CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE).
+ *
+ * ===================================================================
+ * RTC Driver: how to use it
+ * ===================================================================
+ * - Enable the RTC domain access (see description in the section above)
+ * - Configure the RTC Prescaler (Asynchronous and Synchronous) and
+ * RTC hour format using the RTC_Init() function.
+ *
+ * Time and Date configuration
+ * ===========================
+ * - To configure the RTC Calendar (Time and Date) use the RTC_SetTime()
+ * and RTC_SetDate() functions.
+ * - To read the RTC Calendar, use the RTC_GetTime() and RTC_GetDate()
+ * functions.
+ * - Use the RTC_DayLightSavingConfig() function to add or sub 1hour
+ * to the RTC Calendar.
+ *
+ * Alarm configuration
+ * ===================
+ * - To configure the RTC Alarm use the RTC_SetAlarm() function.
+ * - Enable the selected RTC Alarm using the RTC_AlarmCmd() function
+ * - To read the RTC Alarm, use the RTC_GetAlarm() function.
+ *
+ * RTC Wakeup configuration
+ * ========================
+ * - Configure the RTC Wakeup Clock source use the RTC_WakeUpClockConfig()
+ * function.
+ * - Configure the RTC WakeUp Counter using the RTC_SetWakeUpCounter()
+ * function
+ * - Enable the RTC WakeUp using the RTC_WakeUpCmd() function
+ * - To read the RTC WakeUp Counter register, use the RTC_GetWakeUpCounter()
+ * function.
+ *
+ * Outputs configuration
+ * =====================
+ * The RTC has 2 different outputs:
+ * - AFO_ALARM: this output is used to manage the RTC Alarm and
+ * WaKeUp signals.
+ * To output the selected RTC signal on RTC_ALARM pin, use the
+ * RTC_OutputConfig() function.
+ * - AFO_CALIB: this output is used to manage the RTC Clock divided
+ * by 64 (512Hz) signal or divided by 32768 (1Hz) which can be
+ * configured using RTC_CalibOutputConfig() function.
+ * To output the RTC Clock on RTC_CALIB pin, use the
+ * RTC_CalibOutputCmd() function.
+ *
+ * Smooth Calibration configuration
+ * =================================
+ * - Configure the RTC Smooth Calibration Value and the corresponding
+ * sign using the RTC_SmoothCalibConfig() function.
+
+ *
+ *
+ * Tamper configuration
+ * ====================
+ * - Configure the RTC Tamper Level using the RTC_TamperConfig()
+ * function.
+ * - Enable the RTC Tamper using the RTC_TamperCmd() function.
+ *
+ *
+ * ===================================================================
+ * RTC and low power modes
+ * ===================================================================
+ * The MCU can be woken up from a low power mode by an RTC alternate
+ * function.
+ * The RTC alternate functions are the RTC alarms,
+ * RTC wakeup and RTC tamper event detection.
+ * These RTC alternate functions can wake up the system from the
+ * lowpower modes.
+ * The system can also wake up from low power modes without depending
+ * on an external interrupt (Auto-wakeup mode), by using the RTC alarm
+ * or the RTC wakeup events.
+ * The RTC provides a programmable time base for waking up from the
+ * halt or wfe or wfi modes at regular intervals.
+ *
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_rtc.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup RTC
+ * @brief RTC driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define INIT_TIMEOUT ((uint16_t)0xFFFF)
+#define RSF_TIMEOUT ((uint16_t)0xFFFF)
+#define INITF_TIMEOUT ((uint16_t)0xFFFF)
+#define WUTWF_TIMEOUT ((uint16_t)0xFFFF)
+#define ALRAWF_TIMEOUT ((uint16_t)0xFFFF)
+#define RECALPF_TIMEOUT ((uint16_t)0xFFFF)
+#define SHPF_TIMEOUT ((uint16_t)0xFFFF)
+
+#define TEN_VALUE_BCD ((uint8_t)0x10)
+#define TEN_VALUE_BIN ((uint8_t)0x0A)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+
+/** @defgroup RTC_Private_Functions_Prototype
+ * @{
+ */
+static uint8_t ByteToBcd2(uint8_t Value);
+static uint8_t Bcd2ToByte(uint8_t Value);
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Private_Functions
+ * @{
+ */
+
+/** @defgroup RTC_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Initialization and Configuration functions
+ ===============================================================================
+
+ This section provide functions allowing to initialize and configure the RTC
+ Prescaler (Synchronous and Asynchronous), RTC Hour format, disable RTC registers
+ Write protection, enter and exit the RTC initialization mode, RTC registers
+ synchronization check and reference clock detection enable.
+
+ 1. The RTC Prescaler is programmed to generate the RTC 1Hz time base. It is
+ split into 2 programmable prescaler to minimize power consumption.
+ - A 7-bit asynchronous prescaler and A 13-bit or 15-bit synchronous
+ prescaler depending to density of the mcu package.
+ - When both prescaler are used, it is recommended to configure the
+ asynchronous prescaler to a high value to minimize consumption.
+
+ 2. All RTC registers are Write protected. Writing to the RTC registers
+ is enabled by writing a key into the Write Protection register, RTC_WPR.
+
+ 3. To Configure the RTC Calendar, user application should enter initialization
+ mode. In this mode, the Calendar counter is stopped and its value can be
+ updated. When the initialization sequence is complete, the Calendar restarts
+ counting after 4 RTCCLK cycles.
+
+ 4. To read the Calendar through the shadow registers after Calendar initialization,
+ Calendar update or after wakeup from low power modes the software must first
+ clear the RSF flag. The software must then wait until it is set again before
+ reading the Calendar, which means that the Calendar registers have been
+ correctly copied into the RTC_TR and RTC_DR shadow registers.
+ The RTC_WaitForSynchro() function implements the above software sequence
+ (RSF clear and RSF check).
+
+@endverbatim
+ * @{
+ */
+/**
+* @brief Deinitializes the RTC registers to their default reset values.
+* @note This function doesn't reset the RTC Clock source.
+* @param None
+* @retval An ErrorStatus enumeration value:
+* - SUCCESS: RTC registers are deinitialized
+* - ERROR: RTC registers are not deinitialized
+*/
+ErrorStatus RTC_DeInit(void)
+{
+ ErrorStatus status = ERROR;
+ uint16_t wutwfcount = 0;
+ uint16_t recalpfcount = 0;
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* Set Initialization mode */
+ if (RTC_EnterInitMode() == ERROR)
+ {
+ status = ERROR;
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+ }
+ else
+ {
+ /* Reset TR registers */
+ RTC->TR1 = RTC_TR1_RESET_VALUE;
+ RTC->TR2 = RTC_TR2_RESET_VALUE;
+ RTC->TR3 = RTC_TR3_RESET_VALUE;
+
+ /* Reset DR registers */
+ RTC->DR1 = RTC_DR1_RESET_VALUE;
+ RTC->DR2 = RTC_DR2_RESET_VALUE;
+ RTC->DR3 = RTC_DR3_RESET_VALUE;
+
+ /* Reset SPER & ARPER registers */
+ RTC->SPRERH = RTC_SPRERH_RESET_VALUE;
+ RTC->SPRERL = RTC_SPRERL_RESET_VALUE;
+ RTC->APRER = RTC_APRER_RESET_VALUE;
+
+ RTC->TCR1 = RTC_TCR1_RESET_VALUE;
+ RTC->TCR2 = RTC_TCR2_RESET_VALUE;
+
+ /* Reset All CR1 bits except CR1[2:0] */
+
+ RTC->CR1 = RTC_CR1_RESET_VALUE;
+ RTC->CR2 = RTC_CR2_RESET_VALUE;
+ RTC->CR3 = RTC_CR3_RESET_VALUE;
+
+ /* Wait till RTC WUTWF flag is set or if Time out is reached exit */
+ while (((RTC->ISR1 & RTC_ISR1_WUTWF) == RESET) && ( wutwfcount != WUTWF_TIMEOUT))
+ {
+ wutwfcount++;
+ RTC->ISR1 = 0;
+ }
+
+ if ((RTC->ISR1 & RTC_ISR1_WUTWF) == RESET)
+ {
+ status = ERROR;
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+ }
+ else
+ {
+ /* Reset All CR1 bits */
+ RTC->CR1 = RTC_CR1_RESET_VALUE;
+
+ /* Reset WUTR registers */
+ RTC->WUTRH = RTC_WUTRH_RESET_VALUE;
+ RTC->WUTRL = RTC_WUTRL_RESET_VALUE;
+
+ /* Reset ALARM registers */
+ RTC->ALRMAR1 = RTC_ALRMAR1_RESET_VALUE;
+ RTC->ALRMAR2 = RTC_ALRMAR2_RESET_VALUE;
+ RTC->ALRMAR3 = RTC_ALRMAR3_RESET_VALUE;
+ RTC->ALRMAR4 = RTC_ALRMAR4_RESET_VALUE;
+
+ RTC->ALRMASSRH = RTC_ALRMASSRH_RESET_VALUE;
+ RTC->ALRMASSRL = RTC_ALRMASSRL_RESET_VALUE;
+ RTC->ALRMASSMSKR = RTC_ALRMASSMSKR_RESET_VALUE;
+
+ /* Reset ISR register and exit initialization mode */
+ RTC->ISR1 = (uint8_t)0x00;
+ RTC->ISR2 = RTC_ISR2_RESET_VALUE;
+
+ if ((RTC->ISR1 & RTC_ISR1_RECALPF) != RESET)
+ {
+ while (((RTC->ISR1 & RTC_ISR1_RECALPF) != RESET) && (recalpfcount != RECALPF_TIMEOUT))
+ {
+ recalpfcount++;
+ }
+ }
+ if ((RTC->ISR1 & RTC_ISR1_RECALPF) == RESET)
+ {
+ RTC->CALRH = RTC_CALRH_RESET_VALUE;
+ RTC->CALRL = RTC_CALRL_RESET_VALUE;
+
+ if (RTC_WaitForSynchro() == ERROR)
+ {
+ status = ERROR;
+ }
+ else
+ {
+ status = SUCCESS;
+ }
+ }
+ else
+ {
+ status = ERROR;
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+ }
+ }
+
+ /* return Deinitialize RTC registers status*/
+ return (ErrorStatus)status;
+}
+
+
+
+/**
+* @brief Initializes the RTC registers according to the specified parameters
+* in RTC_InitStruct.
+* @param RTC_InitStruct: pointer to a RTC_InitTypeDef structure that contains
+* the configuration information for the RTC peripheral.
+* @note The RTC Prescaler register is write protected and can be written in
+* initialization mode only.
+* @retval An ErrorStatus enumeration value:
+* - SUCCESS: RTC registers are initialized
+* - ERROR: RTC registers are not initialized
+*/
+ErrorStatus RTC_Init(RTC_InitTypeDef* RTC_InitStruct)
+{
+ ErrorStatus status = ERROR;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_HOUR_FORMAT(RTC_InitStruct->RTC_HourFormat));
+ assert_param(IS_RTC_ASYNCH_PREDIV(RTC_InitStruct->RTC_AsynchPrediv));
+ assert_param(IS_RTC_SYNCH_PREDIV(RTC_InitStruct->RTC_SynchPrediv));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* Set Initialization mode */
+ if (RTC_EnterInitMode() == ERROR)
+ {
+ status = ERROR;
+ }
+ else
+ {
+ /* Clear the bits to be configured first */
+ RTC->CR1 &= ((uint8_t)~( RTC_CR1_FMT ));
+
+ /* Set RTC_CR1 register */
+ RTC->CR1 |= ((uint8_t)(RTC_InitStruct->RTC_HourFormat));
+
+ /* Set Prescalers registers */
+ RTC->SPRERH = (uint8_t)(RTC_InitStruct->RTC_SynchPrediv >> 8);
+ RTC->SPRERL = (uint8_t)(RTC_InitStruct->RTC_SynchPrediv);
+ RTC->APRER = (uint8_t)(RTC_InitStruct->RTC_AsynchPrediv);
+
+ /* Exit Initialization mode */
+ RTC->ISR1 &= (uint8_t)~RTC_ISR1_INIT;
+
+ status = SUCCESS;
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+
+ /* return Initialize the RTC registers status*/
+ return (ErrorStatus)(status);
+}
+
+/**
+* @brief Fills each RTC_InitStruct member with its default value
+* Hour format = 24h / Prescalers configured to their reset values.
+* @param RTC_InitStruct: pointer to a RTC_InitTypeDef structure which will be
+* initialized.
+* @retval None
+*/
+void RTC_StructInit(RTC_InitTypeDef* RTC_InitStruct)
+{
+ /* Initialize the RTC_Hourformat member */
+ RTC_InitStruct->RTC_HourFormat = RTC_HourFormat_24;
+
+ /* Initialize the RTC_AsynchPrediv member */
+ RTC_InitStruct->RTC_AsynchPrediv = RTC_APRER_RESET_VALUE;
+
+ /* Initialize the RTC_SynchPrediv member */
+ RTC_InitStruct->RTC_SynchPrediv = RTC_SPRERL_RESET_VALUE;
+}
+
+/**
+* @brief Enables or disables the RTC registers write protection.
+* @param NewState: new state of the write protection.
+ * This parameter can be: ENABLE or DISABLE.
+* @note Writing a wrong key reactivates the write protection.
+* @note The protection mechanism is not affected by system reset.
+* @retval None
+*/
+void RTC_WriteProtectionCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = RTC_WPR_EnableKey;
+ }
+ else
+ {
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = RTC_WPR_DisableKey1;
+ RTC->WPR = RTC_WPR_DisableKey2;
+ }
+}
+
+
+/**
+* @brief Enters the RTC Initialization mode.
+* @note The RTC Initialization mode is write protected, use the
+* RTC_WriteProtectionCmd(DISABLE) before calling this function.
+* @param None
+* @retval An ErrorStatus enumeration value:
+* - SUCCESS: RTC is in Init mode
+* - ERROR: RTC is not in Init mode
+*/
+ErrorStatus RTC_EnterInitMode(void)
+{
+ ErrorStatus status = ERROR;
+ uint16_t initfcount = 0;
+
+ /* Check if the Initialization mode is set */
+ if ((RTC->ISR1 & RTC_ISR1_INITF) == RESET)
+ {
+ /* Set the Initialization mode */
+ RTC->ISR1 = (uint8_t)RTC_ISR1_INIT;
+
+ /* Wait until INITF flag is set */
+ while (((RTC->ISR1 & RTC_ISR1_INITF) == RESET) && ( initfcount != INITF_TIMEOUT))
+ {
+ initfcount++;
+ }
+ }
+
+ if ((RTC->ISR1 & RTC_ISR1_INITF) == RESET)
+ {
+ status = ERROR;
+ }
+ else
+ {
+ status = SUCCESS;
+ }
+
+ return (ErrorStatus)status;
+}
+
+
+/**
+* @brief Exits the RTC Initialization mode.
+* @note When the initialization sequence is complete, the Calendar restarts
+* counting after 4 RTCCLK cycles.
+* @note The RTC Initialization mode is write protected, use the
+* RTC_WriteProtectionCmd(DISABLE) before calling this function.
+* @param None
+* @retval None
+*/
+void RTC_ExitInitMode(void)
+{
+ /* Exit Initialization mode */
+ RTC->ISR1 &= (uint8_t)~RTC_ISR1_INIT;
+}
+
+
+/**
+* @brief Waits until the RTC Calendar registers (Time and Date)
+* are synchronized with RTC clock.
+* @note This function is meaningless when BYPASS feature is enabled in RTC_CR1
+* register.
+* @note To read the Calendar through the shadow registers after Calendar
+* initialization, Calendar update or after wakeup from low power modes
+* the software must first clear the RSF flag.
+* The software must then wait until it is set again before reading
+* the Calendar (if not yet done), which means that the Calendar registers
+* have been correctly copied into the RTC_TRx and RTC_DRx shadow registers.
+* @note RTC_SetTime() and RTC_SetDate() functions call RTC_WaitForSynchro() function
+* after updating the Calendar. In Run mode, User can use RTC_GetDate(),
+* RTC_GetTime() and/or RTC_GetSubSecond() without need to call
+* RTC_WaitForSynchro() function. After waking up from low power mode, this
+* function must be called before calling RTC_GetDate(), RTC_GetTime() or
+* RTC_GetSubSecond() functions.
+* @param None
+* @retval An ErrorStatus enumeration value:
+* - SUCCESS: RTC registers are synchronized
+* - ERROR: RTC registers are not synchronized
+*/
+ErrorStatus RTC_WaitForSynchro(void)
+{
+ uint16_t rsfcount = 0;
+ ErrorStatus status = ERROR;
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* Clear RSF flag by writing 0 in RSF bit */
+ RTC->ISR1 &= (uint8_t)~(RTC_ISR1_RSF | RTC_ISR1_INIT);
+
+ /* Wait the registers to be synchronised */
+ while (((RTC->ISR1 & RTC_ISR1_RSF) == RESET) && ( rsfcount != RSF_TIMEOUT))
+ {
+ rsfcount++;
+ }
+
+ /* Check if RSF flag occurs*/
+ if ((RTC->ISR1 & RTC_ISR1_RSF) != RESET)
+ {
+ status = SUCCESS;
+ }
+ else
+ {
+ status = ERROR;
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+
+ return (ErrorStatus)status;
+}
+
+
+/**
+* @brief Enables or Disables the RTC Ratio.
+* @param NewState: new state of the Ratio feature.
+ * This parameter can be: ENABLE or DISABLE.
+* @retval None
+*/
+void RTC_RatioCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ if (NewState != DISABLE)
+ {
+ /* Set the RATIO bit */
+ RTC->CR1 |= (uint8_t)RTC_CR1_RATIO;
+ }
+ else
+ {
+ /* Reset the RATIO bit */
+ RTC->CR1 &= (uint8_t)~RTC_CR1_RATIO;
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+
+/**
+* @brief Enables or Disables the Bypass Shadow feature.
+* @param NewState: new state of the Bypass Shadow feature.
+ * This parameter can be: ENABLE or DISABLE.
+* @retval None
+*/
+void RTC_BypassShadowCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ if (NewState != DISABLE)
+ {
+ /* Set the BYPSHAD bit */
+ RTC->CR1 |= (uint8_t)RTC_CR1_BYPSHAD;
+ }
+ else
+ {
+ /* Reset the BYPSHAD bit */
+ RTC->CR1 &= (uint8_t)~RTC_CR1_BYPSHAD;
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+
+
+
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Group2 Time and Date configuration functions
+ * @brief Time and Date configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Time and Date configuration functions
+ ===============================================================================
+
+ This section provide functions allowing to program and read the RTC Calendar
+ (Time and Date).
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+* @brief Sets the RTC current time.
+* @note After updating the Calendar, this routine clears the RSF flag and waits
+* until it is set again (using RTC_WaitForSynchro() function) , which means
+* that the Calendar registers have been correctly copied into the RTC_TRx
+* and RTC_DRx shadow registers.
+* @param RTC_Format: specifies the format of the entered parameters.
+* This parameter can be one of the @ref RTC_Format_TypeDef enumeration.
+* @param RTC_TimeStruct: pointer to a @ref RTC_TimeTypeDef structure that
+* contains the time configuration information for the RTC
+* @retval An ErrorStatus enumeration value:
+* - SUCCESS: RTC Time register is configured
+* - ERROR: RTC Time register is not configured
+*/
+ErrorStatus RTC_SetTime(RTC_Format_TypeDef RTC_Format,
+ RTC_TimeTypeDef* RTC_TimeStruct)
+{
+ ErrorStatus status = ERROR;
+ uint8_t temp = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(RTC_Format));
+
+ if (RTC_Format == RTC_Format_BIN)
+ {
+ /* Check Hour Format (24h or 12h)*/
+ if ((RTC->CR1 & RTC_CR1_FMT) != RESET)
+ {
+ assert_param(IS_RTC_HOUR12_MAX(RTC_TimeStruct->RTC_Hours));
+ assert_param(IS_RTC_HOUR12_MIN(RTC_TimeStruct->RTC_Hours));
+ }
+ else
+ {
+ assert_param(IS_RTC_HOUR24(RTC_TimeStruct->RTC_Hours));
+ }
+ assert_param(IS_RTC_MINUTES(RTC_TimeStruct->RTC_Minutes));
+ assert_param(IS_RTC_SECONDS(RTC_TimeStruct->RTC_Seconds));
+ }
+ else
+ {
+ /* Check Hour Format (24h or 12h)*/
+ if ((RTC->CR1 & RTC_CR1_FMT) != RESET)
+ {
+ assert_param(IS_RTC_HOUR12_MAX(Bcd2ToByte(RTC_TimeStruct->RTC_Hours)));
+ assert_param(IS_RTC_HOUR12_MIN(Bcd2ToByte(RTC_TimeStruct->RTC_Hours)));
+ }
+ else
+ {
+ assert_param(IS_RTC_HOUR24(Bcd2ToByte(RTC_TimeStruct->RTC_Hours)));
+ }
+ assert_param(IS_RTC_MINUTES(Bcd2ToByte(RTC_TimeStruct->RTC_Minutes)));
+ assert_param(IS_RTC_SECONDS(Bcd2ToByte(RTC_TimeStruct->RTC_Seconds)));
+ }
+
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* Set Initialization mode */
+ if (RTC_EnterInitMode() == ERROR)
+ {
+ status = ERROR;
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+ }
+ else
+ {
+ /* Check Hour Format is 12h)*/
+ if ((RTC->CR1 & RTC_CR1_FMT) != RESET)
+ {
+ assert_param(IS_RTC_H12(RTC_TimeStruct->RTC_H12));
+ temp = RTC_TimeStruct->RTC_H12;
+ }
+ else
+ {
+ temp = 0;
+ }
+ /* Check the input parameters format */
+ if (RTC_Format != RTC_Format_BIN)
+ {
+ RTC->TR1 = (uint8_t)(RTC_TimeStruct->RTC_Seconds);
+ RTC->TR2 = (uint8_t)(RTC_TimeStruct->RTC_Minutes) ;
+ RTC->TR3 = (uint8_t)( temp | RTC_TimeStruct->RTC_Hours) ;
+ }
+ else
+ {
+ RTC->TR1 = (uint8_t)(ByteToBcd2(RTC_TimeStruct->RTC_Seconds));
+ RTC->TR2 = (uint8_t)(ByteToBcd2(RTC_TimeStruct->RTC_Minutes)) ;
+ RTC->TR3 = (uint8_t)( temp | ByteToBcd2(RTC_TimeStruct->RTC_Hours));
+ }
+ /* Read DR3 register to unfreeze calender registers */
+ (void)(RTC->DR3);
+
+ /* Exit Initialization mode */
+ RTC->ISR1 &= (uint8_t)~RTC_ISR1_INIT;
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+
+ /* if RTC_CR1_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if ((RTC->CR1 & RTC_CR1_BYPSHAD) == RESET)
+ {
+ if (RTC_WaitForSynchro() == ERROR)
+ {
+ status = ERROR;
+ }
+ else
+ {
+ status = SUCCESS;
+ }
+ }
+ else
+ {
+ status = SUCCESS;
+ }
+ }
+
+ return (ErrorStatus)status;
+}
+
+
+
+/**
+* @brief Fills each RTC_TimeStruct member with its default value
+* (Time = 00h:00min:00sec).
+* @param RTC_TimeStruct: pointer to a @ref RTC_TimeTypeDef structure which will be
+* initialized.
+* @retval None
+*/
+void RTC_TimeStructInit(RTC_TimeTypeDef* RTC_TimeStruct)
+{
+ /* Time = 00h:00min:00sec*/
+ RTC_TimeStruct->RTC_H12 = RTC_H12_AM;
+ RTC_TimeStruct->RTC_Hours = 0;
+ RTC_TimeStruct->RTC_Minutes = 0;
+ RTC_TimeStruct->RTC_Seconds = 0;
+}
+
+
+/**
+* @brief Gets the RTC current Time.
+* @note To read the Calendar after wake up from low power mode, user software
+* must first check that the RSF flag is set in RTC_ISR1, using
+* RTC_WaitForSynchro() function, which means that the Calendar registers
+* have been correctly copied into the shadow registers (RTC_TRx and RTC_DRx).
+* @param RTC_Format: specifies the format of the returned parameters.
+* This parameter can be one of the @ref RTC_Format_TypeDef enumeration.
+* @param RTC_TimeStruct: pointer to a @ref RTC_TimeTypeDef structure that
+* will contain the returned current time configuration.
+* @retval None
+
+*/
+void RTC_GetTime(RTC_Format_TypeDef RTC_Format,
+ RTC_TimeTypeDef* RTC_TimeStruct)
+{
+ uint8_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(RTC_Format));
+
+ /* Fill the structure fields with the read parameters */
+ /* Get RTC seconds */
+ RTC_TimeStruct->RTC_Seconds = RTC->TR1;
+
+ /* Get RTC Minutes */
+ RTC_TimeStruct->RTC_Minutes = RTC->TR2;
+
+ /* Get the RTC_TR3 register */
+ tmpreg = (uint8_t)RTC->TR3;
+
+ /* Read DR3 register to unfreeze calender registers */
+ (void) (RTC->DR3) ;
+
+
+ /* Get RTC Hours */
+ RTC_TimeStruct->RTC_Hours = (uint8_t)(tmpreg & (uint8_t)~(RTC_TR3_PM));
+
+ /* Get RTC H12 state */
+ RTC_TimeStruct->RTC_H12 = (RTC_H12_TypeDef)(tmpreg & RTC_TR3_PM);
+
+ /* Check the input parameters format */
+ if (RTC_Format == RTC_Format_BIN)
+ {
+ /* Convert the structure parameters to Binary format */
+ RTC_TimeStruct->RTC_Hours = (uint8_t)Bcd2ToByte(RTC_TimeStruct->RTC_Hours);
+ RTC_TimeStruct->RTC_Minutes = (uint8_t)Bcd2ToByte(RTC_TimeStruct->RTC_Minutes);
+ RTC_TimeStruct->RTC_Seconds = (uint8_t)Bcd2ToByte(RTC_TimeStruct->RTC_Seconds);
+ }
+}
+
+/**
+* @brief Gets the RTC current Calendar Subseconds value.
+* @note To read the Calendar after wake up from low power mode, user software
+* must first check that the RSF flag is set in RTC_ISR1, using
+* RTC_WaitForSynchro() function, which means that the Calendar registers
+* have been correctly copied into the shadow registers (RTC_TRx and RTC_DRx).
+* @param None
+* @retval RTC current Calendar Subseconds value.
+*/
+uint16_t RTC_GetSubSecond(void)
+{
+ uint8_t ssrhreg = 0, ssrlreg = 0;
+ uint16_t ssrreg = 0;
+
+ /* Get subseconds values from the correspondent registers*/
+ ssrhreg = RTC->SSRH;
+ ssrlreg = RTC->SSRL;
+
+ /* Read DR3 register to unfreeze calender registers */
+ (void) (RTC->DR3);
+
+
+ ssrreg = (uint16_t)((uint16_t)((uint16_t)ssrhreg << 8) | (uint16_t)(ssrlreg));
+ return (uint16_t)(ssrreg);
+}
+
+/**
+* @brief Set the RTC current date.
+* @note After updating the Calendar, this routine clears the RSF flag and waits
+* until it is set again (using RTC_WaitForSynchro() function) , which means
+* that the Calendar registers have been correctly copied into the RTC_TRx
+* and RTC_DRx shadow registers.
+* @param RTC_Format: specifies the format of the entered parameters.
+* This parameter can be one of the @ref RTC_Format_TypeDef enumeration.
+* @param RTC_DateStruct: pointer to a @ref RTC_TimeTypeDef structure that
+* contains the date configuration information for the RTC.
+* @retval An ErrorStatus enumeration value:
+* - SUCCESS: RTC Date register is configured
+* - ERROR: RTC Date register is not configured
+*/
+ErrorStatus RTC_SetDate(RTC_Format_TypeDef RTC_Format,
+ RTC_DateTypeDef* RTC_DateStruct)
+{
+ ErrorStatus status = ERROR;
+
+ if ((RTC_Format == RTC_Format_BIN) && ((RTC_DateStruct->RTC_Month & TEN_VALUE_BCD) == TEN_VALUE_BCD))
+ {
+ RTC_DateStruct->RTC_Month = (RTC_Month_TypeDef)((RTC_DateStruct->RTC_Month & (uint8_t)~(TEN_VALUE_BCD)) + TEN_VALUE_BIN);
+ }
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(RTC_Format));
+ if (RTC_Format == RTC_Format_BIN)
+ {
+ assert_param(IS_RTC_YEAR(RTC_DateStruct->RTC_Year));
+ assert_param(IS_RTC_MONTH_MIN(RTC_DateStruct->RTC_Month));
+ assert_param(IS_RTC_MONTH_MAX(RTC_DateStruct->RTC_Month));
+ assert_param(IS_RTC_DATE_MIN(RTC_DateStruct->RTC_Date));
+ assert_param(IS_RTC_DATE_MAX(RTC_DateStruct->RTC_Date));
+ }
+ else
+ {
+ assert_param(IS_RTC_YEAR(Bcd2ToByte(RTC_DateStruct->RTC_Year)));
+ assert_param(IS_RTC_MONTH_MAX(Bcd2ToByte((uint8_t)RTC_DateStruct->RTC_Month)));
+ assert_param(IS_RTC_MONTH_MIN(Bcd2ToByte((uint8_t)RTC_DateStruct->RTC_Month)));
+ assert_param(IS_RTC_DATE_MIN(Bcd2ToByte((uint8_t)RTC_DateStruct->RTC_Date)));
+ assert_param(IS_RTC_DATE_MAX(Bcd2ToByte((uint8_t)RTC_DateStruct->RTC_Date)));
+ }
+ assert_param(IS_RTC_WEEKDAY(RTC_DateStruct->RTC_WeekDay));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* Set Initialization mode */
+ if (RTC_EnterInitMode() == ERROR)
+ {
+ status = ERROR;
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+ }
+ else
+ {
+ (void)(RTC->TR1);
+ /* Set the RTC_DR registers */
+ /* Check the input parameters format */
+ if (RTC_Format != RTC_Format_BIN)
+ {
+ RTC->DR1 = (uint8_t)(RTC_DateStruct->RTC_Date);
+ RTC->DR2 = (uint8_t)((RTC_DateStruct->RTC_Month) | (uint8_t)((RTC_DateStruct->RTC_WeekDay) << 5));
+ RTC->DR3 = (uint8_t)((RTC_DateStruct->RTC_Year));
+ }
+ else
+ {
+ RTC->DR1 = (uint8_t)(ByteToBcd2 ((uint8_t)RTC_DateStruct->RTC_Date));
+ RTC->DR2 = (uint8_t)((ByteToBcd2((uint8_t)RTC_DateStruct->RTC_Month)) | (uint8_t)((RTC_DateStruct->RTC_WeekDay) << 5));
+ RTC->DR3 = (uint8_t)(ByteToBcd2((uint8_t)RTC_DateStruct->RTC_Year));
+ }
+
+ /* Exit Initialization mode */
+ RTC->ISR1 &= (uint8_t)~RTC_ISR1_INIT;
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+
+ /* if RTC_CR1_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+ if ((RTC->CR1 & RTC_CR1_BYPSHAD) == RESET)
+ {
+ if (RTC_WaitForSynchro() == ERROR)
+ {
+ status = ERROR;
+ }
+ else
+ {
+ status = SUCCESS;
+ }
+ }
+ else
+ {
+ status = SUCCESS;
+ }
+ }
+
+ return (ErrorStatus)status;
+}
+/**
+* @brief Fills each RTC_DateStruct member with its default value
+* (Monday 01 January xx00).
+* @param RTC_DateStruct: pointer to a @ref RTC_DateTypeDef structure which will be
+* initialized.
+* @retval None
+*/
+void RTC_DateStructInit(RTC_DateTypeDef* RTC_DateStruct)
+{
+ /* * (Monday 01 January xx00)*/
+ RTC_DateStruct->RTC_WeekDay = RTC_Weekday_Monday;
+ RTC_DateStruct->RTC_Date = 1;
+ RTC_DateStruct->RTC_Month = RTC_Month_January;
+ RTC_DateStruct->RTC_Year = 0;
+}
+/**
+* @brief Get the RTC current date.
+* @note To read the Calendar after wake up from low power mode, user software
+* must first check that the RSF flag is set in RTC_ISR1, using
+* RTC_WaitForSynchro() function, which means that the Calendar registers
+* have been correctly copied into the shadow registers (RTC_TRx and RTC_DRx).
+* @param RTC_Format: specifies the format of the returned parameters.
+* This parameter can be one of the @ref RTC_Format_TypeDef enumeration.
+* @param RTC_DateStruct: pointer to a @ref RTC_DateTypeDef structure that
+* will contain the returned current Date configuration.
+* @retval None
+*/
+void RTC_GetDate(RTC_Format_TypeDef RTC_Format,
+ RTC_DateTypeDef* RTC_DateStruct)
+{
+ uint8_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(RTC_Format));
+
+ /* Fill the structure fields with the read parameters */
+ (void) (RTC->TR1) ;
+ RTC_DateStruct->RTC_Date = (uint8_t)(RTC->DR1);
+ tmpreg = (uint8_t)RTC->DR2;
+ RTC_DateStruct->RTC_Year = (uint8_t)(RTC->DR3);
+
+
+ RTC_DateStruct->RTC_Month = (RTC_Month_TypeDef)(tmpreg & (uint8_t)(RTC_DR2_MT | RTC_DR2_MU));
+ RTC_DateStruct->RTC_WeekDay = (RTC_Weekday_TypeDef)((uint8_t)((uint8_t)tmpreg & (uint8_t)(RTC_DR2_WDU)) >> (uint8_t)5);
+
+ /* Check the input parameters format */
+ if (RTC_Format == RTC_Format_BIN)
+ {
+ /* Convert the structure parameters to Binary format */
+ RTC_DateStruct->RTC_Year = (uint8_t)Bcd2ToByte((uint8_t)RTC_DateStruct->RTC_Year);
+ RTC_DateStruct->RTC_Month = (RTC_Month_TypeDef)Bcd2ToByte((uint8_t)RTC_DateStruct->RTC_Month);
+ RTC_DateStruct->RTC_Date = (uint8_t)(Bcd2ToByte((uint8_t)RTC_DateStruct->RTC_Date));
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Group3 Alarms configuration functions
+ * @brief Alarms (Alarm A and Alarm B) configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Alarms (Alarm A and Alarm B) configuration functions
+ ===============================================================================
+
+ This section provide functions allowing to program and read the RTC Alarms.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Sets the RTC Alarm configuration.
+ * @note Before configuring the Alarm settings, the Alarm Unit must be disabled
+ * (if enabled) using RTC_AlarmCmd(DISABLE) function.
+ * @param RTC_Format: specifies the format of the entered parameters.
+ * This parameter can be one of the @ref RTC_Format_TypeDef enumeration.
+ * @param RTC_AlarmStruct: pointer to a @ref RTC_AlarmTypeDef structure that
+ * contains the Alarm configuration information for the RTC.
+ * @retval None.
+ */
+void RTC_SetAlarm(RTC_Format_TypeDef RTC_Format,
+ RTC_AlarmTypeDef* RTC_AlarmStruct)
+{
+ uint8_t tmpreg1 = 0;
+ uint8_t tmpreg2 = 0;
+ uint8_t tmpreg3 = 0;
+ uint8_t tmpreg4 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALARM_MASK(RTC_AlarmStruct->RTC_AlarmMask));
+ assert_param(IS_RTC_FORMAT(RTC_Format));
+ assert_param(IS_RTC_H12(RTC_AlarmStruct->RTC_AlarmTime.RTC_H12));
+ assert_param(IS_RTC_ALARM_DATEWEEKDAY_SEL(RTC_AlarmStruct->RTC_AlarmDateWeekDaySel));
+
+
+ if (RTC_Format == RTC_Format_BIN)
+ {
+ /* Check Hour Format (24h or 12h)*/
+ if ((RTC->CR1 & RTC_CR1_FMT) != RESET)
+ {
+ assert_param(IS_RTC_HOUR12_MAX(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours));
+ assert_param(IS_RTC_HOUR12_MIN(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours));
+ }
+ else
+ {
+ assert_param(IS_RTC_HOUR24(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours));
+ }
+ assert_param(IS_RTC_MINUTES(RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes));
+ assert_param(IS_RTC_SECONDS(RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds));
+ }
+ else
+ {
+ /* Check Hour Format (24h or 12h)*/
+ if ((RTC->CR1 & RTC_CR1_FMT) != RESET)
+ {
+ assert_param(IS_RTC_HOUR12_MAX(Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours)));
+ assert_param(IS_RTC_HOUR12_MIN(Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours)));
+ }
+ else
+ {
+ assert_param(IS_RTC_HOUR24(Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours)));
+ }
+
+ assert_param(IS_RTC_MINUTES(Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes)));
+
+ assert_param(IS_RTC_SECONDS(Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds)));
+
+ }
+
+ /* if Date/Weekday field is not masked */
+ if ((RTC_AlarmStruct->RTC_AlarmMask & RTC_AlarmMask_DateWeekDay) == RESET )
+ {
+ if (RTC_AlarmStruct->RTC_AlarmDateWeekDaySel == RTC_AlarmDateWeekDaySel_WeekDay)
+ {
+ assert_param(IS_RTC_WEEKDAY(RTC_AlarmStruct->RTC_AlarmDateWeekDay));
+ }
+ else
+ {
+ assert_param(IS_RTC_DATE_MIN(RTC_AlarmStruct->RTC_AlarmDateWeekDay));
+ assert_param(IS_RTC_DATE_MAX(RTC_AlarmStruct->RTC_AlarmDateWeekDay));
+ }
+ }
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+
+ /* Check the input parameters format & Configure the Alarm register */
+ if (RTC_Format != RTC_Format_BIN)
+ {
+ tmpreg1 = (uint8_t)((uint8_t)(RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds) | \
+ (uint8_t)((uint8_t)(RTC_AlarmStruct->RTC_AlarmMask) & (uint8_t)RTC_ALRMAR1_MSK1));
+
+ tmpreg2 = (uint8_t)((uint8_t)(RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes) | \
+ (uint8_t)((uint8_t)(RTC_AlarmStruct->RTC_AlarmMask << 1) & (uint8_t)RTC_ALRMAR2_MSK2));
+
+ tmpreg3 = (uint8_t)((uint8_t)((uint8_t)(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours) | \
+ (uint8_t)(RTC_AlarmStruct->RTC_AlarmTime.RTC_H12)) | \
+ (uint8_t)((uint8_t)(RTC_AlarmStruct->RTC_AlarmMask << 2) & (uint8_t)RTC_ALRMAR3_MSK3));
+
+ tmpreg4 = (uint8_t)((uint8_t)((uint8_t)(RTC_AlarmStruct->RTC_AlarmDateWeekDay) | \
+ (uint8_t)(RTC_AlarmStruct->RTC_AlarmDateWeekDaySel)) | \
+ (uint8_t)((uint8_t)(RTC_AlarmStruct->RTC_AlarmMask << 3) & (uint8_t)RTC_ALRMAR4_MSK4));
+
+ }
+ else
+ {
+ tmpreg1 = (uint8_t)((ByteToBcd2(RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds)) | \
+ (uint8_t)(RTC_AlarmStruct->RTC_AlarmMask & RTC_ALRMAR1_MSK1));
+
+ tmpreg2 = (uint8_t)((ByteToBcd2(RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes)) | \
+ (uint8_t)((uint8_t)(RTC_AlarmStruct->RTC_AlarmMask << 1) & (uint8_t)RTC_ALRMAR2_MSK2));
+
+ tmpreg3 = (uint8_t)((uint8_t)((ByteToBcd2(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours)) | \
+ (uint8_t)(RTC_AlarmStruct->RTC_AlarmTime.RTC_H12)) | \
+ (uint8_t)((uint8_t)(RTC_AlarmStruct->RTC_AlarmMask << 2) & (uint8_t)RTC_ALRMAR3_MSK3));
+
+ tmpreg4 = (uint8_t)((uint8_t)((ByteToBcd2(RTC_AlarmStruct->RTC_AlarmDateWeekDay)) | \
+ (uint8_t)(RTC_AlarmStruct->RTC_AlarmDateWeekDaySel)) | \
+ (uint8_t)((uint8_t)(RTC_AlarmStruct->RTC_AlarmMask << 3) & (uint8_t)(RTC_ALRMAR4_MSK4)));
+ }
+
+ /* Configure the Alarm register */
+ RTC->ALRMAR1 = tmpreg1;
+ RTC->ALRMAR2 = tmpreg2;
+ RTC->ALRMAR3 = tmpreg3;
+ RTC->ALRMAR4 = tmpreg4;
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+
+/**
+* @brief Fills each RTC_AlarmStruct member with its default value
+* (Time = 00h:00mn:00sec / Date = 1st day of the month/Mask =
+* all fields are masked).
+* @param RTC_AlarmStruct: pointer to a @ref RTC_AlarmTypeDef structure which
+* will be initialized.
+* @retval None
+*/
+void RTC_AlarmStructInit(RTC_AlarmTypeDef* RTC_AlarmStruct)
+{
+ /* Alarm Time Settings : Time = 00h:00mn:00sec */
+ RTC_AlarmStruct->RTC_AlarmTime.RTC_H12 = RTC_H12_AM;
+ RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours = 0;
+ RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes = 0;
+ RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds = 0;
+
+ /* Alarm Date Settings : Date = 1st day of the month*/
+ RTC_AlarmStruct->RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
+ RTC_AlarmStruct->RTC_AlarmDateWeekDay = 1;
+
+ /* Alarm Masks Settings : Mask = all fields are masked*/
+ RTC_AlarmStruct->RTC_AlarmMask = RTC_AlarmMask_All;
+}
+/**
+ * @brief Gets the RTC Alarm configuration.
+ * @param RTC_Format: specifies the format of the entered parameters.
+ * This parameter can be one of the @ref RTC_Format_TypeDef enumeration.
+ * @param RTC_AlarmStruct: pointer to a @ref RTC_AlarmTypeDef structure that
+ * will contain the Alarm configuration information of the RTC.
+ * @retval None
+ */
+void RTC_GetAlarm(RTC_Format_TypeDef RTC_Format,
+ RTC_AlarmTypeDef* RTC_AlarmStruct)
+{
+ uint8_t tmpreg1 = 0;
+ uint8_t tmpreg2 = 0;
+ uint8_t tmpreg3 = 0;
+ uint8_t tmpreg4 = 0;
+ uint8_t alarmmask = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_FORMAT(RTC_Format));
+
+ /* Get Alarm registers data */
+ tmpreg1 = (uint8_t)RTC->ALRMAR1;
+ tmpreg2 = (uint8_t)RTC->ALRMAR2;
+ tmpreg3 = (uint8_t)RTC->ALRMAR3;
+ tmpreg4 = (uint8_t)RTC->ALRMAR4;
+
+ /* Fill the structure with the read parameters */
+ RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds = (uint8_t)((uint8_t)tmpreg1 & (uint8_t)((uint8_t)RTC_ALRMAR1_ST | (uint8_t)RTC_ALRMAR1_SU));
+ alarmmask = (uint8_t)(tmpreg1 & RTC_ALRMAR1_MSK1);
+
+ /* Fill the structure with the read parameters */
+ RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes = (uint8_t)((uint8_t)tmpreg2 & (uint8_t)((uint8_t)RTC_ALRMAR2_MNT | (uint8_t)RTC_ALRMAR2_MNU));
+ alarmmask = (uint8_t)((alarmmask) | (uint8_t)((uint8_t)(tmpreg2 & RTC_ALRMAR2_MSK2) >> 1));
+
+ /* Fill the structure with the read parameters */
+ RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours = (uint8_t)((uint8_t)tmpreg3 & (uint8_t)((uint8_t)RTC_ALRMAR3_HT | (uint8_t)RTC_ALRMAR3_HU));
+ RTC_AlarmStruct->RTC_AlarmTime.RTC_H12 = (RTC_H12_TypeDef)((uint8_t)tmpreg3 & (uint8_t)RTC_ALRMAR3_PM);
+ alarmmask = (uint8_t)((alarmmask) | (uint8_t)((uint8_t)((uint8_t)tmpreg3 & (uint8_t)RTC_ALRMAR3_MSK3) >> 2));
+
+ /* Fill the structure with the read parameters */
+ RTC_AlarmStruct->RTC_AlarmDateWeekDay = (uint8_t)((uint8_t)tmpreg4 & (uint8_t)((uint8_t)RTC_ALRMAR4_DT | (uint8_t)RTC_ALRMAR4_DU));
+ RTC_AlarmStruct->RTC_AlarmDateWeekDaySel = (RTC_AlarmDateWeekDaySel_TypeDef)((uint8_t)tmpreg4 & (uint8_t)RTC_ALRMAR4_WDSEL);
+ alarmmask = (uint8_t)((alarmmask) | (uint8_t)((uint8_t)((uint8_t)tmpreg4 & RTC_ALRMAR4_MSK4) >> 3));
+
+ RTC_AlarmStruct->RTC_AlarmMask = alarmmask;
+
+ if (RTC_Format == RTC_Format_BIN)
+ {
+ RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours = Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours);
+ RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes = Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes);
+ RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds = Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds);
+ RTC_AlarmStruct->RTC_AlarmDateWeekDay = Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmDateWeekDay);
+ }
+}
+
+/**
+ * @brief Enables or disables the RTC Alarm.
+ * @param NewState: new state of the alarm. This parameter can be: ENABLE or DISABLE.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS: RTC Alarm is enabled/disabled
+ * - ERROR: RTC Alarm is not enabled/disabled
+ */
+ErrorStatus RTC_AlarmCmd(FunctionalState NewState)
+{
+ __IO uint16_t alrawfcount = 0;
+ ErrorStatus status = ERROR;
+ uint8_t temp1 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* Configure the Alarm state */
+ if (NewState != DISABLE)
+ { /*Enable the Alarm*/
+ RTC->CR2 |= (uint8_t)(RTC_CR2_ALRAE);
+ status = SUCCESS;
+ }
+ else
+ { /* Disable the Alarm */
+ RTC->CR2 &= (uint8_t)~(RTC_CR2_ALRAE) ;
+
+ /* Wait until ALRxWF flag is set */
+ temp1 = (uint8_t)(RTC->ISR1 & RTC_ISR1_ALRAWF);
+ while ((alrawfcount != ALRAWF_TIMEOUT) && (temp1 == RESET))
+ {
+ alrawfcount++;
+ }
+
+ if ((RTC->ISR1 & RTC_ISR1_ALRAWF) == RESET)
+ {
+ status = ERROR;
+ }
+ else
+ {
+ status = SUCCESS;
+ }
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+
+ /* Return the status*/
+ return (ErrorStatus)status;
+}
+/**
+* @brief Configure the RTC Alarm Subseconds value and mask.
+* @param RTC_AlarmSubSecondValue: specifies the Subseconds value.
+* This parameter can be a value from 0 to 0x7FFF.
+* @param RTC_AlarmSubSecondMask: specifies the Subseconds Mask.
+* This parameter can be one of the @ref RTC_AlarmSubSecondMask_TypeDef enumeration.
+* @retval An ErrorStatus enumeration value:
+* - SUCCESS: Alarm Subseconds value and mask are configured
+* - ERROR: Alarm Subseconds value and mask are not configured
+*/
+ErrorStatus RTC_AlarmSubSecondConfig(uint16_t RTC_AlarmSubSecondValue,
+ RTC_AlarmSubSecondMask_TypeDef RTC_AlarmSubSecondMask)
+{
+ uint8_t alarmstatus = 0;
+ ErrorStatus status = ERROR;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_ALARM_SS_VALUE(RTC_AlarmSubSecondValue));
+ assert_param(IS_RTC_ALARM_SS_MASK(RTC_AlarmSubSecondMask));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* Check if the initialization mode is not set */
+ if ((RTC->ISR1 & RTC_ISR1_INITF) == RESET)
+ {
+ /* save Alarm status */
+ alarmstatus = (uint8_t)(RTC->CR2 | RTC_CR2_ALRAE);
+
+ /* Disable the Alarm */
+ RTC->CR2 &= (uint8_t)~(RTC_CR2_ALRAE);
+
+ /* Configure the Alarm register */
+ RTC->ALRMASSRH = (uint8_t)(RTC_AlarmSubSecondValue >> 8);
+ RTC->ALRMASSRL = (uint8_t)(RTC_AlarmSubSecondValue);
+ RTC->ALRMASSMSKR = (uint8_t)RTC_AlarmSubSecondMask;
+
+ /* restore the saved Alarm status */
+ RTC->CR2 |= alarmstatus;
+
+ status = SUCCESS;
+ }
+ else
+ {
+ status = ERROR;
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+
+ return (ErrorStatus)status;
+}
+
+
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Group4 WakeUp Timer configuration functions
+ * @brief WakeUp Timer configuration functions
+ *
+@verbatim
+ ===============================================================================
+ WakeUp Timer configuration functions
+ ===============================================================================
+
+ This section provide functions allowing to program and read the RTC WakeUp.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Configures the RTC Wakeup clock source.
+ * @pre Before configuring the wakeup unit Clock source, the wake up Unit must
+ * be disabled (if enabled) using RTC_WakeUpCmd(Disable) .
+ * @param RTC_WakeupClockSrc: specifies the Wakeup clock source,
+ * this parameter can be one of the @ref RTC_WakeupClockSrc_TypeDef enumeration.
+ * @retval None
+ */
+void RTC_WakeUpClockConfig(RTC_WakeUpClock_TypeDef RTC_WakeUpClock)
+{
+
+ /* Check the parameters */
+ assert_param(IS_RTC_WAKEUP_CLOCK(RTC_WakeUpClock));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* Disable the Wakeup timer in RTC_CR2 register */
+ RTC->CR2 &= (uint8_t)~RTC_CR2_WUTE;
+
+ /* Clear the Wakeup Timer clock source bits in CR1 register */
+ RTC->CR1 &= (uint8_t)~RTC_CR1_WUCKSEL;
+
+ /* Configure the clock source */
+ RTC->CR1 |= (uint8_t)RTC_WakeUpClock;
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+
+/**
+ * @brief Sets the RTC Wakeup counter.
+ * @note Before configuring the wakeup unit counter, the wake up Unit must be
+ * disabled (if enabled) using RTC_WakeUpCmd(Disable).
+ * @param RTC_WakeupCounter: specifies the Wake up counter,
+ * This parameter can be a value from 0x0000 to 0xFFFF.
+ * @retval None.
+ */
+void RTC_SetWakeUpCounter(uint16_t RTC_WakeupCounter)
+{
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+
+ /* Configure the Wakeup Timer counter */
+ RTC->WUTRH = (uint8_t)(RTC_WakeupCounter >> 8);
+ RTC->WUTRL = (uint8_t)(RTC_WakeupCounter);
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+
+/**
+ * @brief Returns the RTC Wakeup timer counter value.
+ * @param None.
+ * @retval RTC Wakeup Counter value.
+ */
+uint16_t RTC_GetWakeUpCounter(void)
+{
+ uint16_t tmpreg = 0;
+
+ /* Get the counter value */
+ tmpreg = ((uint16_t)RTC->WUTRH) << 8;
+ tmpreg |= RTC->WUTRL;
+
+ /* return RTC Wakeup Counter value*/
+ return (uint16_t)tmpreg;
+}
+
+/**
+ * @brief Enables or Disables the RTC Wakeup Unit.
+ * @param NewState: new state of the Wakeup Unit. This parameter can
+ * be: ENABLE or DISABLE.
+ * @retval An ErrorStatus enumeration value:
+ * - SUCCESS : RTC Wakeup Unit is enabled/disabled
+ * - ERROR : RTC Wakeup Unit is not enabled/disabled
+ */
+ErrorStatus RTC_WakeUpCmd(FunctionalState NewState)
+{
+ ErrorStatus status = ERROR;
+ uint16_t wutwfcount = 0;
+
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the Wakeup Timer */
+ RTC->CR2 |= (uint8_t)RTC_CR2_WUTE;
+
+ status = SUCCESS;
+ }
+ else
+ {
+ /* Disable the Wakeup Timer */
+ RTC->CR2 &= (uint8_t)~RTC_CR2_WUTE;
+
+ /* Wait until WUTWF flag is set */
+ while (((RTC->ISR1 & RTC_ISR1_WUTWF) == RESET) && ( wutwfcount != WUTWF_TIMEOUT))
+ {
+ wutwfcount++;
+ }
+
+ /* Check WUTWF flag is set or not */
+ if ((RTC->ISR1 & RTC_ISR1_WUTWF) == RESET)
+ {
+ status = ERROR;
+ }
+ else
+ {
+ status = SUCCESS;
+ }
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+
+ /* Return the status*/
+ return (ErrorStatus)status;
+}
+
+
+
+
+
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Group5 Daylight Saving configuration functions
+ * @brief Daylight Saving configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Daylight Saving configuration functions
+ ===============================================================================
+
+ This section provide functions allowing to configure the RTC DayLight Saving.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Adds or subtracts one hour from the current time depending on
+ * the daylight saving parameter.
+ * @param RTC_DayLightSaving: the day light saving Mode
+ * This parameter can be one of the @ref RTC_DayLightSaving_TypeDef
+ * enumeration.
+ * @param RTC_StoreOperation: the day light saving store operation
+ * This parameter can be one of the @ref RTC_StoreOperation_TypeDef
+ * enumeration.
+ * @retval None
+ */
+void RTC_DayLightSavingConfig(RTC_DayLightSaving_TypeDef RTC_DayLightSaving,
+ RTC_StoreOperation_TypeDef RTC_StoreOperation)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_DAYLIGHT_SAVING(RTC_DayLightSaving));
+ assert_param(IS_RTC_STORE_OPERATION(RTC_StoreOperation));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* Clear the bits to be configured */
+ RTC->CR3 &= (uint8_t)~(RTC_CR3_BCK);
+
+ /* Configure the RTC_CR3 register */
+ RTC->CR3 |= (uint8_t)((uint8_t)RTC_DayLightSaving | (uint8_t)RTC_StoreOperation);
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+
+/**
+ * @brief Returns the stored operation.
+ * @param None
+ * @retval the store operation, this parameter can be one of
+ * the @ref RTC_StoreOperation_TypeDef enumeration.
+ */
+RTC_StoreOperation_TypeDef RTC_GetStoreOperation(void)
+{
+ /* Return the stored operation*/
+ return (RTC_StoreOperation_TypeDef)(RTC->CR3 & RTC_CR3_BCK);
+}
+
+
+
+
+
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Group6 Output pin Configuration function
+ * @brief Output pin Configuration function
+ *
+@verbatim
+ ===============================================================================
+ Output pin Configuration function
+ ===============================================================================
+
+ This section provide functions allowing to configure the RTC Output source.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Configures the RTC output for the output pin (RTC_ALARM output).
+ * @param RTC_OutputSel: Specifies which signal will be mapped to the output.
+ * This parameter can be one parameter from the
+ * @ref RTC_OutputSel_TypeDef enumeration.
+ * @param RTC_OutputPolarity: Specifies the polarity of the output signal.
+ * This parameter can be one parameter from the
+ * @ref RTC_OutputPolarity_TypeDef enumeration.
+ * @retval None
+ */
+void RTC_OutputConfig(RTC_Output_TypeDef RTC_Output,
+ RTC_OutputPolarity_TypeDef RTC_OutputPolarity)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_OUTPUT_SEL(RTC_Output));
+ assert_param(IS_RTC_OUTPUT_POL(RTC_OutputPolarity));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* Clear the bits to be configured */
+ RTC->CR3 &= (uint8_t)~(RTC_CR3_OSEL | RTC_CR3_POL);
+
+ /* Configure the output selection and polarity */
+ RTC->CR3 |= (uint8_t)((uint8_t)RTC_Output | (uint8_t)RTC_OutputPolarity);
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+
+
+
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Group7 Output pin Configuration function
+ * @brief Output pin Configuration function
+ *
+@verbatim
+ ===============================================================================
+ Output pin Configuration function
+ ===============================================================================
+
+ This section provide functions allowing to configure the RTC Output source.
+
+@endverbatim
+ * @{
+ */
+/**
+* @brief Configures the Synchronization Shift Control Settings.
+* @param RTC_ShiftAdd1S : Select to add or not 1 second to the time Calendar.
+* This parameter can be one parameter from the @ref RTC_ShiftAdd1S_TypeDef
+* enumeration.
+* @param RTC_ShiftSubFS: Select the number of Second Fractions to Substitute.
+* This parameter can be one any value from 0 to 0x7FFF.
+ * @retval An ErrorStatus enumeration value:
+* - SUCCESS: RTC Shift registers are configured
+* - ERROR: RTC Shift registers are not configured
+*/
+ErrorStatus RTC_SynchroShiftConfig(RTC_ShiftAdd1S_TypeDef RTC_ShiftAdd1S,
+ uint16_t RTC_ShiftSubFS)
+{
+ uint8_t shiftrhreg = 0;
+ ErrorStatus status = ERROR;
+ uint16_t shpfcount = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_SHIFT_ADD1S(RTC_ShiftAdd1S));
+ assert_param(IS_RTC_SHIFT_SUBFS(RTC_ShiftSubFS));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* Check if a Shift is pending*/
+ if ((RTC->ISR1 & RTC_ISR1_SHPF) != RESET)
+ {
+ /* wait until the shift is completed*/
+ while (((RTC->ISR1 & RTC_ISR1_SHPF) != RESET) && (shpfcount != SHPF_TIMEOUT))
+ {
+ shpfcount++;
+ }
+ }
+
+ /* check if the Shift pending is completed or if there is no Shift operation at all*/
+ if ((RTC->ISR1 & RTC_ISR1_SHPF) == RESET)
+ {
+ /* Configure the Shift settings */
+ shiftrhreg = (uint8_t)((uint8_t)(RTC_ShiftSubFS >> 8) | (uint8_t)(RTC_ShiftAdd1S));
+ RTC->SHIFTRH = (uint8_t)(shiftrhreg);
+ RTC->SHIFTRL = (uint8_t)(RTC_ShiftSubFS);
+
+ status = SUCCESS;
+ }
+ else
+ {
+ status = ERROR;
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+
+ return (ErrorStatus)(status);
+}
+
+
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Group8 Output pin Configuration function
+ * @brief Output pin Configuration function
+ *
+@verbatim
+ ===============================================================================
+ Output pin Configuration function
+ ===============================================================================
+
+ This section provide functions allowing to configure the RTC Output source.
+
+@endverbatim
+ * @{
+ */
+/**
+* @brief Configures the Smooth Calibration Settings.
+* @param RTC_SmoothCalibPeriod : Select the Smooth Calibration Period.
+* This parameter can be one parameter from
+* the @ref RTC_SmoothCalibPeriod_TypeDef enumeration.
+* @param RTC_SmoothCalibPlusPulses : Select to Set or reset the CALP bit.
+* This parameter can be one parameter from the
+* @ref RTC_SmoothCalibPlusPulses_TypeDef enumeration.
+* @param RTC_SmouthCalibMinusPulsesValue: Select the value of CALM[8:0] bits.
+* This parameter can be one any value from 0 to 0x01FF.
+* @retval An ErrorStatus enumeration value:
+* - SUCCESS: RTC Calib registers are configured
+* - ERROR: RTC Calib registers are not configured
+*/
+ErrorStatus RTC_SmoothCalibConfig(RTC_SmoothCalibPeriod_TypeDef RTC_SmoothCalibPeriod,
+ RTC_SmoothCalibPlusPulses_TypeDef RTC_SmoothCalibPlusPulses,
+ uint16_t RTC_SmouthCalibMinusPulsesValue)
+{
+ ErrorStatus status = ERROR;
+ uint16_t recalpfcount = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_SMOOTH_CALIB_PERIOD(RTC_SmoothCalibPeriod));
+ assert_param(IS_RTC_SMOOTH_CALIB_PLUS(RTC_SmoothCalibPlusPulses));
+ assert_param(IS_RTC_SMOOTH_CALIB_MINUS(RTC_SmouthCalibMinusPulsesValue));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* check if a calibration is pending*/
+ if ((RTC->ISR1 & RTC_ISR1_RECALPF) != RESET)
+ {
+ /* wait until the Calibration is completed*/
+ while (((RTC->ISR1 & RTC_ISR1_RECALPF) != RESET) && (recalpfcount != RECALPF_TIMEOUT))
+ {
+ recalpfcount++;
+ }
+ }
+
+ /* check if the calibration pending is completed or if there is
+ no calibration operation at all*/
+ if ((RTC->ISR1 & RTC_ISR1_RECALPF) == RESET)
+ {
+ /* Configure the Smooth calibration settings */
+ RTC->CALRH = (uint8_t)((uint8_t)((uint8_t)RTC_SmoothCalibPeriod | \
+ (uint8_t)RTC_SmoothCalibPlusPulses) | \
+ (uint8_t)((uint16_t)RTC_SmouthCalibMinusPulsesValue >> 8));
+ RTC->CALRL = (uint8_t)(RTC_SmouthCalibMinusPulsesValue);
+
+ status = SUCCESS;
+ }
+ else
+ {
+ status = ERROR;
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+
+ return (ErrorStatus)(status);
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Group9 Digital Calibration configuration functions
+ * @brief Digital Calibration configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Calibration configuration functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+/**
+* @brief Configure the Calibration Pin-out (RTC_CALIB) Selection (1Hz or 512Hz).
+* @param RTC_CalibOutput : Select the Calibration output Selection .
+* This parameter can be one parameter from the
+* @ref RTC_CalibOutput_TypeDef enumeration.
+* @retval None
+*/
+void RTC_CalibOutputConfig(RTC_CalibOutput_TypeDef RTC_CalibOutput)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_CALOUTPUT_SELECT(RTC_CalibOutput));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ if (RTC_CalibOutput != RTC_CalibOutput_512Hz)
+ {
+ /* Enable the RTC clock output */
+ RTC->CR3 |= (uint8_t)RTC_CR3_COSEL;
+ }
+ else
+ {
+ /* Disable the RTC clock output */
+ RTC->CR3 &= (uint8_t)~RTC_CR3_COSEL;
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+
+/**
+* @brief Enables or disables the RTC clock to be output through the relative pin.
+* @param NewState: new state of the RTC Calibration output
+ * This parameter can be: ENABLE or DISABLE.
+* @retval None
+*/
+void RTC_CalibOutputCmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the RTC clock output */
+ RTC->CR3 |= (uint8_t)RTC_CR3_COE;
+ }
+ else
+ {
+ /* Disable the RTC clock output */
+ RTC->CR3 &= (uint8_t)~RTC_CR3_COE;
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Group10 Tampers configuration functions
+ * @brief Tampers configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Tampers configuration functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+* @brief Configures the Tamper Sensitive Level.
+* @param RTC_Tamper: Select the tamper to configure.
+* This parameter can be one parameter from the @ref RTC_Tamper_TypeDef
+* enumeration.
+* @param RTC_TamperLevel: Select the tamper Sensitive Level.
+* This parameter can be one parameter from the
+* @ref RTC_TamperLevel_TypeDef enumeration.
+* @retval None
+*/
+void RTC_TamperLevelConfig(RTC_Tamper_TypeDef RTC_Tamper,
+ RTC_TamperLevel_TypeDef RTC_TamperLevel)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_TAMPER((uint8_t)RTC_Tamper));
+ assert_param(IS_RTC_TAMPER_LEVEL(RTC_TamperLevel));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ if (RTC_TamperLevel != RTC_TamperLevel_Low)
+ {
+ /* Enable the selected Tampers */
+ RTC->TCR1 |= (uint8_t)(RTC_Tamper << 1);
+ }
+ else
+ {
+ /* Disable the selected Tampers */
+ RTC->TCR1 &= (uint8_t)~(uint8_t)(RTC_Tamper << 1);
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+/**
+ * @brief Configures the Tampers Filter.
+ * @param RTC_TamperFilter: Specifies the tampers filter.
+ * This parameter can be one parameter from the
+ * @ref RTC_TamperFilter_TypeDef enumeration.
+ * @retval None
+ */
+void RTC_TamperFilterConfig(RTC_TamperFilter_TypeDef RTC_TamperFilter)
+{
+
+ /* Check the parameters */
+ assert_param(IS_RTC_TAMPER_FILTER(RTC_TamperFilter));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /*clear flags before configuration */
+ RTC->TCR2 &= (uint8_t)~(RTC_TCR2_TAMPFLT);
+
+ /* Configure the RTC_TCR register */
+ RTC->TCR2 |= (uint8_t)RTC_TamperFilter;
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+
+}
+
+/**
+ * @brief Configures the Tampers Sampling Frequency.
+ * @param RTC_TamperSamplingFreq: Specifies the tampers Sampling Frequency.
+ * This parameter can be one parameter from the
+ * @ref RTC_TamperSamplingFreq_TypeDef enumeration.
+ * @retval None
+ */
+void RTC_TamperSamplingFreqConfig(RTC_TamperSamplingFreq_TypeDef RTC_TamperSamplingFreq)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(RTC_TamperSamplingFreq));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* Clear flags before configuration */
+ RTC->TCR2 &= (uint8_t)~(RTC_TCR2_TAMPFREQ);
+
+ /* Configure the RTC_TCR register */
+ RTC->TCR2 |= (uint8_t)RTC_TamperSamplingFreq;
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+
+/**
+* @brief Configures the Tampers Pins input Precharge Duration.
+* @param RTC_TamperPrechargeDuration: Specifies the Tampers Pins input
+* Precharge Duration.
+* This parameter can be one parameter from the
+* @ref RTC_TamperPrechargeDuration_TypeDef enumeration.
+* @retval None
+*/
+void RTC_TamperPinsPrechargeDuration(RTC_TamperPrechargeDuration_TypeDef RTC_TamperPrechargeDuration)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_TAMPER_PINS_PRECHAR_DURATION(RTC_TamperPrechargeDuration));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ /* Clear the tampers pull-up and precharge/discharge duration Old settings*/
+ RTC->TCR2 &= (uint8_t)~(RTC_TCR2_TAMPPUDIS | RTC_TCR2_TAMPPRCH);
+
+ /* Configure the Tampers Precharge Duration and pull-up New settings*/
+ RTC->TCR2 |= (uint8_t)RTC_TamperPrechargeDuration;
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+
+
+/**
+* @brief Enables or Disables the Tamper detection.
+* @param RTC_Tamper: Select the tamper to configure.
+* This parameter can be one parameter from the @ref RTC_Tamper_TypeDef
+* enumeration.
+* @param NewState: new state of the tamper pin.
+ * This parameter can be: ENABLE or DISABLE.
+* @retval None
+*/
+void RTC_TamperCmd(RTC_Tamper_TypeDef RTC_Tamper,
+ FunctionalState NewState)
+{
+
+ /* Check the parameters */
+ assert_param(IS_RTC_TAMPER((uint8_t)RTC_Tamper));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected Tampers */
+ RTC->TCR1 |= (uint8_t)RTC_Tamper;
+ }
+ else
+ {
+ /* Disable the selected Tampers */
+ RTC->TCR1 &= (uint8_t)~RTC_Tamper;
+ }
+
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+
+
+
+/**
+ * @}
+ */
+
+/** @defgroup RTC_Group11 Interrupts and flags management functions
+ * @brief Interrupts and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts and flags management functions
+ ===============================================================================
+
+ To enable the RTC Alarm interrupt, the following sequence is required:
+ - Configure the RTC to generate RTC alarm (Alarm A) using the RTC_SetAlarm()
+ and RTC_AlarmCmd() functions.
+
+ To enable the RTC Wakeup interrupt, the following sequence is required:
+ - Configure the RTC to generate the RTC wakeup timer event using the
+ RTC_WakeUpClockConfig(), RTC_SetWakeUpCounter() and RTC_WakeUpCmd() functions.
+
+ To enable the RTC Tamper interrupt, the following sequence is required:
+ - Configure the RTC to detect the RTC tamper event using the
+ RTC_TamperTriggerConfig() and RTC_TamperCmd() functions.
+
+
+
+@endverbatim
+ * @{
+ */
+/**
+* @brief Enables or Disables the specified RTC interrupts.
+* @param RTC_IT: specifies the RTC interrupt sources to be enabled or disabled.
+* This parameter can be any combination of the following values:
+* @arg RTC_IT_ALRA: Alarm A interrupt
+* @arg RTC_IT_TAMP: Tampers interrupt
+* @arg RTC_IT_WUT: WakeUp Timer interrupt
+* @param NewState: new state of the specified RTC interrupts.
+ * This parameter can be: ENABLE or DISABLE.
+* @retval None
+*/
+void RTC_ITConfig(RTC_IT_TypeDef RTC_IT, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_CONFIG_IT(RTC_IT));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Disable the write protection for RTC registers */
+ RTC->WPR = 0xCA;
+ RTC->WPR = 0x53;
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the Interrupts */
+ RTC->CR2 |= (uint8_t)((uint16_t)RTC_IT & (uint16_t)0x00F0);
+ RTC->TCR1 |= (uint8_t)((uint16_t)RTC_IT & RTC_TCR1_TAMPIE);
+ }
+ else
+ {
+ /* Disable the Interrupts */
+ RTC->CR2 &= (uint8_t)~(uint8_t)((uint16_t)RTC_IT & (uint16_t)0x00F0);
+ RTC->TCR1 &= (uint8_t)~(uint8_t)((uint16_t)RTC_IT & (uint16_t)RTC_TCR1_TAMPIE);
+ }
+
+ /* Enable the write protection for RTC registers */
+ RTC->WPR = 0xFF;
+}
+/**
+* @brief Checks whether the specified RTC flag is set or not.
+* @param RTC_FLAG: specifies the flag to check.
+* This parameter can be one of the @ref RTC_Flag_TypeDef enumeration.
+* @retval Status of RTC_FLAG (SET or RESET)
+*/
+FlagStatus RTC_GetFlagStatus(RTC_Flag_TypeDef RTC_FLAG)
+{
+ FlagStatus flagstatus = RESET;
+ uint16_t tmpreg1 = 0;
+ uint16_t tmpreg2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_GET_FLAG(RTC_FLAG));
+
+ /* Get all the flags */
+ tmpreg2 = (uint16_t)((uint16_t)RTC->ISR1 << 8);
+ tmpreg1 = (uint16_t)((uint16_t)((uint16_t)(RTC->ISR2)) | tmpreg2);
+
+ /* Return the status of the flag */
+ if ((tmpreg1 & (uint16_t)RTC_FLAG) != RESET)
+ {
+ flagstatus = SET;
+ }
+ else
+ {
+ flagstatus = RESET;
+ }
+ return (FlagStatus)flagstatus;
+}
+
+/**
+* @brief Clears the RTC's pending flags.
+* @param RTC_FLAG: specifies the RTC flag to clear.
+* This parameter can be any combination of the @ref RTC_Flag_TypeDef
+* enumeration.
+* @retval None
+*/
+void RTC_ClearFlag(RTC_Flag_TypeDef RTC_FLAG)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_CLEAR_FLAG((uint16_t)RTC_FLAG));
+
+ /* Clear the Flags in the RTC_ISR registers */
+ RTC->ISR2 = (uint8_t)~((uint8_t)RTC_FLAG) ;
+ RTC->ISR1 = (uint8_t)(((uint8_t)~(uint8_t)((uint16_t)RTC_FLAG >> (uint8_t)8)) & ((uint8_t)~(uint8_t)(RTC_ISR1_INIT)));
+}
+
+/**
+* @brief Checks whether the specified RTC interrupt has occurred or not.
+* @param RTC_IT: specifies the RTC interrupt source to check.
+* This parameter can be one of the @ref RTC_IT_TypeDef enumeration.
+* @retval Status of RTC_IT (SET or RESET).
+*/
+ITStatus RTC_GetITStatus(RTC_IT_TypeDef RTC_IT)
+{
+ ITStatus itstatus = RESET;
+ uint8_t enablestatus = 0, tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RTC_GET_IT(RTC_IT));
+
+ /* Get the Interrupt enable Status */
+ enablestatus = (uint8_t)(RTC->CR2 & (uint16_t)RTC_IT);
+
+ /* Get the Interrupt pending bit */
+ tmpreg = (uint8_t)(RTC->ISR2 & (uint8_t)((uint16_t)RTC_IT >> 4));
+
+ /* Get the status of the Interrupt */
+ if ((enablestatus != (uint8_t)RESET) && (tmpreg != (uint8_t)RESET))
+ {
+ itstatus = SET;
+ }
+ else
+ {
+ itstatus = RESET;
+ }
+
+ return (ITStatus)itstatus;
+}
+
+/**
+* @brief Clears the RTC's interrupt pending bits.
+* @param RTC_IT: specifies the RTC interrupt pending bit to clear.
+* This parameter can be any combination of the @ref RTC_IT_TypeDef
+* enumeration.
+* @retval None
+*/
+void RTC_ClearITPendingBit(RTC_IT_TypeDef RTC_IT)
+{
+ /* Check the parameters */
+ assert_param(IS_RTC_CLEAR_IT((uint16_t)RTC_IT));
+
+ /* Clear the interrupt pending bits in the RTC_ISR registers */
+ RTC->ISR2 = (uint8_t)~(uint8_t)((uint16_t)RTC_IT >> 4);
+}
+
+/**
+ * @}
+ */
+
+
+
+
+
+
+
+
+
+/**
+ * @addtogroup RTC_Private_Functions
+ * @{
+ */
+/**
+* @brief Converts a 2 digit decimal to BCD format
+* @param Value: Byte to be converted.
+* @retval Converted byte
+*/
+static uint8_t ByteToBcd2(uint8_t Value)
+{
+ uint8_t bcdhigh = 0;
+
+ while (Value >= 10)
+ {
+ bcdhigh++;
+ Value -= 10;
+ }
+
+ return (uint8_t)((uint8_t)(bcdhigh << 4) | Value);
+}
+
+/**
+* @brief Converts from 2 digit BCD to Binary format
+* @param Value: BCD value to be converted.
+* @retval Converted word
+*/
+static uint8_t Bcd2ToByte(uint8_t Value)
+{
+ uint8_t tmp = 0;
+
+ tmp = (uint8_t)((uint8_t)((uint8_t)(Value & (uint8_t)0xF0) >> 4) * (uint8_t)10);
+
+ return (uint8_t)(tmp + (Value & (uint8_t)0x0F));
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
\ No newline at end of file
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_spi.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_spi.c
new file mode 100644
index 00000000..bed5735e
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_spi.c
@@ -0,0 +1,794 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_spi.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Serial peripheral interface (SPI):
+ * - Initialization and Configuration
+ * - Data transfers functions
+ * - Hardware CRC Calculation
+ * - DMA transfers management
+ * - Interrupts and flags management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * 1. Enable peripheral clock using CLK_PeripheralClockConfig(CLK_Peripheral_SPIx,
+ * ENABLE) function (Refer to the product datasheet for the available SPI
+ * peripherals)
+ *
+ * 2. Enable the external Pull-up on the used SPI Pins using the
+ * GPIO_ExternalPullUpConfig() function or an eternal pull-up equivalent resistor
+ * (RPU = 45 KOhm typical value).
+ *
+ *
+ * 3. Program the Polarity, Phase, First Data, Baud Rate Prescaler, Slave
+ * Management, Peripheral Mode and CRC Polynomial values using the SPI_Init()
+ * function.
+ *
+ * 4. Enable the corresponding interrupt using the function SPI_ITConfig() if you
+ * need to use interrupt mode.
+ *
+ * 5. When using the DMA mode
+ * - Configure the DMA using DMA_Init() function
+ * - Active the needed channel Request using SPI_DMACmd() function
+ *
+ * 6. Enable the SPI using the SPI_Cmd() function.
+ *
+ * 7. Enable the DMA using the DMA_Cmd() function when using DMA mode.
+ *
+ * 8. Optionally you can enable/configure the following parameters without
+ * re-initialization (i.e there is no need to call again SPI_Init() function):
+ * - When bidirectional mode (SPI_Direction_1Line_Rx or SPI_Direction_1Line_Tx)
+ * is programmed as Data direction parameter using the SPI_Init() function
+ * it can be possible to switch between SPI_Direction_Tx or SPI_Direction_Rx
+ * using the SPI_BiDirectionalLineConfig() function.
+ * - When SPI_NSS_Soft is selected as Slave Select Management parameter
+ * using the SPI_Init() function it can be possible to manage the
+ * NSS internal signal using the SPI_NSSInternalSoftwareConfig() function.
+ *
+ * 9. To use the CRC Hardware calculation feature refer to the Peripheral
+ * CRC hardware Calculation subsection.
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_spi.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup SPI
+ * @brief SPI driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup SPI_Private_Functions
+ * @{
+ */
+
+/** @defgroup SPI_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Initialization and Configuration functions
+ ===============================================================================
+
+ This section provides a set of functions allowing to initialize the SPI Direction,
+ SPI Mode, SPI Data Size, SPI Polarity, SPI Phase, SPI NSS Management, SPI Baud
+ Rate Prescaler, SPI First Bit and SPI CRC Polynomial.
+
+ The SPI_Init() function follows the SPI configuration procedures for Master mode
+ and Slave mode (details for these procedures are available in reference manual
+ (RM0031)).
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the SPI peripheral registers to their default reset values.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param None
+ * @retval None
+ */
+void SPI_DeInit(SPI_TypeDef* SPIx)
+{
+ SPIx->CR1 = SPI_CR1_RESET_VALUE;
+ SPIx->CR2 = SPI_CR2_RESET_VALUE;
+ SPIx->CR3 = SPI_CR3_RESET_VALUE;
+ SPIx->SR = SPI_SR_RESET_VALUE;
+ SPIx->CRCPR = SPI_CRCPR_RESET_VALUE;
+}
+
+/**
+ * @brief Initializes the SPI according to the specified parameters.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param SPI_FirstBit: This parameter can be any of the
+ * This parameter can be one of the following values:
+ * @arg SPI_FirstBit_MSB: MSB bit will be transmitted first
+ * @arg SPI_FirstBit_LSB: LSB bit will be transmitted first
+ * @param SPI_BaudRatePrescaler: This parameter can be any of the
+ * This parameter can be one of the following values:
+ * @arg SPI_BaudRatePrescaler_2: SPI frequency = frequency(CPU)/2
+ * @arg SPI_BaudRatePrescaler_4: SPI frequency = frequency(CPU)/4
+ * @arg SPI_BaudRatePrescaler_8: SPI frequency = frequency(CPU)/8
+ * @arg SPI_BaudRatePrescaler_16: SPI frequency = frequency(CPU)/16
+ * @arg SPI_BaudRatePrescaler_32: SPI frequency = frequency(CPU)/32
+ * @arg SPI_BaudRatePrescaler_64: SPI frequency = frequency(CPU)/64
+ * @arg SPI_BaudRatePrescaler_128: SPI frequency = frequency(CPU)/128
+ * @arg SPI_BaudRatePrescaler_256: SPI frequency = frequency(CPU)/256
+ * @param SPI_Mode: Mode
+ * This parameter can be one of the following values:
+ * @arg SPI_Mode_Master: SPI Master configuration
+ * @arg SPI_Mode_Slave: SPI Slave configuration
+ * @param SPI_CPOL: Clock Polarity
+ * This parameter can be one of the following values:
+ * @arg SPI_CPOL_Low: Clock to 0 when idle
+ * @arg SPI_CPOL_High: Clock to 1 when idle
+ * @param SPI_CPHA: Clock Phase
+ * This parameter can be one of the following values:
+ * @arg SPI_CPHA_1Edge: The first clock transition is the first data capture edge
+ * @arg SPI_CPHA_2Edge: The second clock transition is the first data capture edge
+ * @param SPI_Data_Direction: Data direction
+ * This parameter can be one of the following values:
+ * @arg SPI_Direction_Rx: Select Rx receive direction in bi-directional mode
+ * @arg SPI_Direction_Tx: Select Tx transmission direction in bi-directional mode
+ * @param SPI_Slave_Management: Slave management
+ * This parameter can be one of the following values:
+ * @arg SPI_NSS_Soft: Software slave management disabled
+ * @arg SPI_NSS_Hard: Software slave management enabled
+ * @param CRCPolynomial: Configures the CRC polynomial.
+ * @retval None
+ */
+void SPI_Init(SPI_TypeDef* SPIx, SPI_FirstBit_TypeDef SPI_FirstBit,
+ SPI_BaudRatePrescaler_TypeDef SPI_BaudRatePrescaler,
+ SPI_Mode_TypeDef SPI_Mode, SPI_CPOL_TypeDef SPI_CPOL,
+ SPI_CPHA_TypeDef SPI_CPHA, SPI_DirectionMode_TypeDef SPI_Data_Direction,
+ SPI_NSS_TypeDef SPI_Slave_Management, uint8_t CRCPolynomial)
+{
+ /* Check structure elements */
+ assert_param(IS_SPI_FIRSTBIT(SPI_FirstBit));
+ assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
+ assert_param(IS_SPI_MODE(SPI_Mode));
+ assert_param(IS_SPI_POLARITY(SPI_CPOL));
+ assert_param(IS_SPI_PHASE(SPI_CPHA));
+ assert_param(IS_SPI_DATA_DIRECTION(SPI_Data_Direction));
+ assert_param(IS_SPI_SLAVEMANAGEMENT(SPI_Slave_Management));
+ assert_param(IS_SPI_CRC_POLYNOMIAL(CRCPolynomial));
+
+ /* Frame Format, BaudRate, Clock Polarity and Phase configuration */
+ SPIx->CR1 = (uint8_t)((uint8_t)((uint8_t)SPI_FirstBit |
+ (uint8_t)SPI_BaudRatePrescaler) |
+ (uint8_t)((uint8_t)SPI_CPOL |
+ SPI_CPHA));
+
+ /* Data direction configuration: BDM, BDOE and RXONLY bits */
+ SPIx->CR2 = (uint8_t)((uint8_t)(SPI_Data_Direction) | (uint8_t)(SPI_Slave_Management));
+
+ if (SPI_Mode == SPI_Mode_Master)
+ {
+ SPIx->CR2 |= (uint8_t)SPI_CR2_SSI;
+ }
+ else
+ {
+ SPIx->CR2 &= (uint8_t)~(SPI_CR2_SSI);
+ }
+
+ /* Master/Slave mode configuration */
+ SPIx->CR1 |= (uint8_t)(SPI_Mode);
+
+ /* CRC configuration */
+ SPIx->CRCPR = (uint8_t)CRCPolynomial;
+}
+
+/**
+ * @brief Enables or disables the SPI peripheral.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param NewState New state of the SPI peripheral.
+ * This parameter can be: ENABLE or DISABLE
+ * @retval None
+ */
+void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState)
+{
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ SPIx->CR1 |= SPI_CR1_SPE; /* Enable the SPI peripheral*/
+ }
+ else
+ {
+ SPIx->CR1 &= (uint8_t)(~SPI_CR1_SPE); /* Disable the SPI peripheral*/
+ }
+}
+
+/**
+ * @brief Configures internally by software the NSS pin.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param NewState Indicates the new state of the SPI Software slave management.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void SPI_NSSInternalSoftwareCmd(SPI_TypeDef* SPIx, FunctionalState NewState)
+{
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ SPIx->CR2 |= SPI_CR2_SSI; /* Set NSS pin internally by software*/
+ }
+ else
+ {
+ SPIx->CR2 &= (uint8_t)(~SPI_CR2_SSI); /* Reset NSS pin internally by software*/
+ }
+}
+
+/**
+ * @brief Selects the data transfer direction in Bi-directional mode.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param SPI_Direction Specifies the data transfer direction in Bi-directional mode.
+ * This parameter can be one of the following values:
+ * @arg SPI_Direction_Rx: Select Rx receive direction in bi-directional mode
+ * @arg SPI_Direction_Tx: Select Tx transmission direction in bi-directional mode
+ * @retval None
+ */
+void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, SPI_Direction_TypeDef SPI_Direction)
+{
+ /* Check function parameters */
+ assert_param(IS_SPI_DIRECTION(SPI_Direction));
+
+ if (SPI_Direction != SPI_Direction_Rx)
+ {
+ SPIx->CR2 |= SPI_CR2_BDOE; /* Set the Tx only mode*/
+ }
+ else
+ {
+ SPIx->CR2 &= (uint8_t)(~SPI_CR2_BDOE); /* Set the Rx only mode*/
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Group2 Data transfers functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ===============================================================================
+ Data transfers functions
+ ===============================================================================
+
+ This section provides a set of functions allowing to manage the SPI data transfers
+
+ In reception, data are received and then stored into an internal Rx buffer while
+ In transmission, data are first stored into an internal Tx buffer before being
+ transmitted.
+
+ The read access of the SPI_DR register can be done using the SPI_ReceiveData()
+ function and returns the Rx buffered value. Whereas a write access to the SPI_DR
+ can be done using SPI_SendData() function and stores the written data into
+ Tx buffer.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Transmits a Data through the SPI peripheral.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param Data: Byte to be transmitted.
+ * @retval None
+ */
+void SPI_SendData(SPI_TypeDef* SPIx, uint8_t Data)
+{
+ SPIx->DR = Data; /* Write in the DR register the data to be sent*/
+}
+
+/**
+ * @brief Returns the most recent received data by the SPI peripheral.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @retval The value of the received data.
+ */
+uint8_t SPI_ReceiveData(SPI_TypeDef* SPIx)
+{
+ return ((uint8_t)SPIx->DR); /* Return the data in the DR register*/
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Group3 Hardware CRC Calculation functions
+ * @brief Hardware CRC Calculation functions
+ *
+@verbatim
+ ===============================================================================
+ Hardware CRC Calculation functions
+ ===============================================================================
+
+ This section provides a set of functions allowing to manage the SPI CRC hardware
+ calculation
+
+ SPI communication using CRC is possible through the following procedure:
+ 1. Program the Data direction, Polarity, Phase, First Data, Baud Rate Prescaler,
+ Slave Management, Peripheral Mode and CRC Polynomial values using the SPI_Init()
+ function.
+ 2. Enable the CRC calculation using the SPI_CalculateCRC() function.
+ 3. Enable the SPI using the SPI_Cmd() function
+ 4. Before writing the last data to the TX buffer, set the CRCNext bit using the
+ SPI_TransmitCRC() function to indicate that after transmission of the last
+ data, the CRC should be transmitted.
+ 5. After transmitting the last data, the SPI transmits the CRC. The SPI_CR2_CRCNEXT
+ bit is reset. The CRC is also received and compared against the SPI_RXCRCR
+ value.
+ If the value does not match, the SPI_FLAG_CRCERR flag is set and an interrupt
+ can be generated when the SPI_IT_ERR interrupt is enabled.
+
+Note:
+-----
+ - It is advised to don't read the calculate CRC values during the communication.
+
+ - When the SPI is in slave mode, be careful to enable CRC calculation only
+ when the clock is stable, that is, when the clock is in the steady state.
+ If not, a wrong CRC calculation may be done. In fact, the CRC is sensitive
+ to the SCK slave input clock as soon as CRCEN is set, and this, whatever
+ the value of the SPE bit.
+
+ - With high bitrate frequencies, be careful when transmitting the CRC.
+ As the number of used CPU cycles has to be as low as possible in the CRC
+ transfer phase, it is forbidden to call software functions in the CRC
+ transmission sequence to avoid errors in the last data and CRC reception.
+ In fact, CRCNEXT bit has to be written before the end of the transmission/reception
+ of the last data.
+
+ - For high bit rate frequencies, it is advised to use the DMA mode to avoid the
+ degradation of the SPI speed performance due to CPU accesses impacting the
+ SPI bandwidth.
+
+ - When the STM8L15x are configured as slaves and the NSS hardware mode is
+ used, the NSS pin needs to be kept low between the data phase and the CRC
+ phase.
+
+ - When the SPI is configured in slave mode with the CRC feature enabled, CRC
+ calculation takes place even if a high level is applied on the NSS pin.
+ This may happen for example in case of a multislave environment where the
+ communication master addresses slaves alternately.
+
+ - Between a slave de-selection (high level on NSS) and a new slave selection
+ (low level on NSS), the CRC value should be cleared on both master and slave
+ sides in order to resynchronize the master and slave for their respective
+ CRC calculation.
+
+ To clear the CRC, follow the procedure below:
+ 1. Disable SPI using the SPI_Cmd() function
+ 2. Disable the CRC calculation using the SPI_CalculateCRC() function.
+ 3. Enable the CRC calculation using the SPI_CalculateCRC() function.
+ 4. Enable SPI using the SPI_Cmd() function.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables the transmit of the CRC value.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @retval None
+ */
+void SPI_TransmitCRC(SPI_TypeDef* SPIx)
+{
+ SPIx->CR2 |= SPI_CR2_CRCNEXT; /* Enable the CRC transmission*/
+}
+
+/**
+ * @brief Enables or disables the CRC value calculation of the transferred bytes.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param NewState Indicates the new state of the SPI CRC value calculation.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void SPI_CalculateCRCCmd(SPI_TypeDef* SPIx, FunctionalState NewState)
+{
+ /* Check function parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* SPI must be disabled for correct operation od Hardware CRC calculation */
+ SPI_Cmd(SPI1, DISABLE);
+
+ if (NewState != DISABLE)
+ {
+ SPIx->CR2 |= SPI_CR2_CRCEN; /* Enable the CRC calculation*/
+ }
+ else
+ {
+ SPIx->CR2 &= (uint8_t)(~SPI_CR2_CRCEN); /* Disable the CRC calculation*/
+ }
+}
+
+/**
+ * @brief Returns the transmit or the receive CRC register value.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param SPI_CRC: Specifies the CRC register to be read.
+ * This parameter can be one of the following values:
+ * @arg SPI_CRC_RX: Select Tx CRC register
+ * @arg SPI_CRC_TX: Select Rx CRC register
+ * @retval The selected CRC register value.
+ */
+uint8_t SPI_GetCRC(SPI_TypeDef* SPIx, SPI_CRC_TypeDef SPI_CRC)
+{
+ uint8_t crcreg = 0;
+
+ /* Check function parameters */
+ assert_param(IS_SPI_CRC(SPI_CRC));
+
+ if (SPI_CRC != SPI_CRC_RX)
+ {
+ crcreg = SPIx->TXCRCR; /* Get the Tx CRC register*/
+ }
+ else
+ {
+ crcreg = SPIx->RXCRCR; /* Get the Rx CRC register*/
+ }
+
+ /* Return the selected CRC register status*/
+ return crcreg;
+}
+
+/**
+ * @brief Reset the Rx CRCR and Tx CRCR registers.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @retval None
+ */
+void SPI_ResetCRC(SPI_TypeDef* SPIx)
+{
+ /* Rx CRCR & Tx CRCR registers are reset when CRCEN (hardware calculation)
+ bit in SPI_CR2 is written to 1 (enable) */
+ SPI_CalculateCRCCmd(SPIx, ENABLE);
+
+ /* Previous function disable the SPI */
+ SPI_Cmd(SPIx, ENABLE);
+}
+
+/**
+ * @brief Returns the CRC Polynomial register value.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @retval uint8_t The CRC Polynomial register value.
+ */
+uint8_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx)
+{
+ return SPIx->CRCPR; /* Return the CRC polynomial register */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Group4 DMA transfers management functions
+ * @brief DMA transfers management functions
+ *
+@verbatim
+ ===============================================================================
+ DMA transfers management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the SPI DMA interface.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param SPI_DMAReq Specifies the SPI DMA transfer request to be enabled or disabled.
+ * This parameter can be one of the following values:
+ * @arg SPI_DMAReq_RX: SPI DMA Rx transfer requests
+ * @arg SPI_DMAReq_TX: SPI DMA Tx transfer requests
+ * @param NewState Indicates the new state of the SPI DMA request.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void SPI_DMACmd(SPI_TypeDef* SPIx, SPI_DMAReq_TypeDef SPI_DMAReq, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ assert_param(IS_SPI_DMAREQ(SPI_DMAReq));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected SPI DMA requests */
+ SPIx->CR3 |= (uint8_t) SPI_DMAReq;
+ }
+ else
+ {
+ /* Disable the selected SPI DMA requests */
+ SPIx->CR3 &= (uint8_t)~SPI_DMAReq;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SPI_Group5 Interrupts and flags management functions
+ * @brief Interrupts and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts and flags management functions
+ ===============================================================================
+
+ This section provides a set of functions allowing to configure the SPI Interrupts
+ sources and check or clear the flags or pending bits status.
+ The user should identify which mode will be used in his application to manage
+ the communication: Polling mode, Interrupt mode or DMA mode.
+
+ Polling Mode
+ =============
+ In Polling Mode, the SPI communication can be managed by 6 flags:
+ 1. SPI_FLAG_TXE: to indicate the status of the transmit buffer register
+ 2. SPI_FLAG_RXNE: to indicate the status of the receive buffer register
+ 3. SPI_FLAG_WKUP: to indicate the state of the Wakeup event.
+ 4. SPI_FLAG_CRCERR: to indicate if a CRC Calculation error occurs
+ 5. SPI_FLAG_MODF: to indicate if a Mode Fault error occurs
+ 6. SPI_FLAG_OVR: to indicate if an Overrun error occurs
+
+ In this Mode it is advised to use the following functions:
+ - FlagStatus SPI_GetFlagStatus(SPI_TypeDef* SPIx, SPI_FLAG_TypeDef SPI_FLAG);
+ - void SPI_ClearFlag(SPI_TypeDef* SPIx, SPI_FLAG_TypeDef SPI_FLAG);
+
+ Interrupt Mode
+ ===============
+ In Interrupt Mode, the SPI communication can be managed by 4 interrupt sources
+ and 6 pending bits:
+ Pending Bits:
+ -------------
+ 1. SPI_IT_TXE: to indicate the status of the transmit buffer register
+ 2. SPI_IT_RXNE: to indicate the status of the receive buffer register
+ 3. SPI_IT_CRCERR: to indicate if a CRC Calculation error occurs
+ 4. SPI_IT_MODF: to indicate if a Mode Fault error occurs
+ 5. SPI_IT_OVR: to indicate if an Overrun error occurs
+ 6. SPI_IT_WKUP: to indicate if an Wake_up event occurs
+ Interrupt Source:
+ -----------------
+ 1. SPI_IT_TXE: specifies the interrupt source for the Tx buffer empty
+ interrupt.
+ 2. SPI_IT_RXNE: specifies the interrupt source for the Rx buffer not
+ empty interrupt.
+ 3. SPI_IT_ERR: specifies the interrupt source for the errors interrupt.
+ 4. SPI_IT_WKUP: specifies the interrupt source for the Wake-up interrupt.
+
+ In this Mode it is advised to use the following functions:
+ - void SPI_ITConfig(SPI_TypeDef* SPIx, SPI_IT_TypeDef SPI_IT, FunctionalState NewState);
+ - ITStatus SPI_GetITStatus(SPI_TypeDef* SPIx, SPI_IT_TypeDef SPI_IT);
+ - void SPI_ClearITPendingBit(SPI_TypeDef* SPIx, SPI_IT_TypeDef SPI_IT);
+
+ DMA Mode
+ ========
+ In DMA Mode, the SPI communication can be managed by 2 DMA Channel requests:
+ 1. SPI_DMAReq_Tx: specifies the Tx buffer DMA transfer request
+ 2. SPI_DMAReq_Rx: specifies the Rx buffer DMA transfer request
+
+ In this Mode it is advised to use the following function:
+ - void SPI_DMACmd(SPI_TypeDef* SPIx, SPI_DMAReq_TypeDef SPI_DMAReq, FunctionalState NewState);
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the specified interrupts.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param SPI_IT Specifies the SPI interrupts sources to be enabled or disabled.
+ * This parameter can be one of the following values:
+ * @arg SPI_IT_TXE: Transmit buffer empty
+ * @arg SPI_IT_RXNE: Receive buffer not empty
+ * @arg SPI_IT_ERR: Error
+ * @arg SPI_IT_WKUP: Wake-up
+ * @param NewState: The new state of the specified SPI interrupts.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void SPI_ITConfig(SPI_TypeDef* SPIx, SPI_IT_TypeDef SPI_IT, FunctionalState NewState)
+{
+ uint8_t itpos = 0;
+ /* Check function parameters */
+ assert_param(IS_SPI_CONFIG_IT(SPI_IT));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Get the SPI IT index */
+ itpos = (uint8_t)((uint8_t)1 << (uint8_t)((uint8_t)SPI_IT & (uint8_t)0x0F));
+
+ if (NewState != DISABLE)
+ {
+ SPIx->CR3 |= itpos; /* Enable interrupt*/
+ }
+ else
+ {
+ SPIx->CR3 &= (uint8_t)(~itpos); /* Disable interrupt*/
+ }
+}
+
+/**
+ * @brief Checks whether the specified SPI flag is set or not.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param SPI_FLAG: Specifies the flag to check.
+ * This parameter can be one of the following values:
+ * @arg SPI_FLAG_BSY: Busy
+ * @arg SPI_FLAG_OVR: Overrun
+ * @arg SPI_FLAG_MODF: Mode fault
+ * @arg SPI_FLAG_CRCERR: CRC error
+ * @arg SPI_FLAG_WKUP: Wake-up
+ * @arg SPI_FLAG_TXE: Transmit buffer empty
+ * @arg SPI_FLAG_RXNE: Receive buffer empty
+ * @retval Indicates the state of SPI_FLAG.
+ * This parameter can be SET or RESET.
+ */
+FlagStatus SPI_GetFlagStatus(SPI_TypeDef* SPIx, SPI_FLAG_TypeDef SPI_FLAG)
+{
+ FlagStatus status = RESET;
+ /* Check parameters */
+ assert_param(IS_SPI_FLAG(SPI_FLAG));
+
+ /* Check the status of the specified SPI flag */
+ if ((SPIx->SR & (uint8_t)SPI_FLAG) != (uint8_t)RESET)
+ {
+ status = SET; /* SPI_FLAG is set */
+ }
+ else
+ {
+ status = RESET; /* SPI_FLAG is reset*/
+ }
+
+ /* Return the SPI_FLAG status */
+ return status;
+}
+
+/**
+ * @brief Clears the SPI flags.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param SPI_FLAG: Specifies the flag to clear.
+ * This parameter can be one of the following values:
+ * @arg SPI_FLAG_CRCERR
+ * @arg SPI_FLAG_WKUP
+ * @note OVR (OverRun Error) interrupt pending bit is cleared by software
+ * sequence: a read operation to SPI_DR register (SPI_ReceiveData()) followed by
+ * a read operation to SPI_SR register (SPI_GetFlagStatus()).
+ * @note MODF (Mode Fault) interrupt pending bit is cleared by software sequence:
+ * a read/write operation to SPI_SR register (SPI_GetFlagStatus()) followed by
+ * a write operation to SPI_CR1 register (SPI_Cmd() to enable the SPI).
+ * @retval None
+ */
+void SPI_ClearFlag(SPI_TypeDef* SPIx, SPI_FLAG_TypeDef SPI_FLAG)
+{
+ assert_param(IS_SPI_CLEAR_FLAG(SPI_FLAG));
+ /* Clear the flag bit */
+ SPIx->SR = (uint8_t)(~SPI_FLAG);
+}
+
+/**
+ * @brief Checks whether the specified interrupt has occurred or not.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param SPI_IT: Specifies the SPI interrupt pending bit to check.
+ * This parameter can be one of the following values:
+ * @arg SPI_IT_CRCERR
+ * @arg SPI_IT_WKUP
+ * @arg SPI_IT_OVR
+ * @arg SPI_IT_MODF
+ * @arg SPI_IT_RXNE
+ * @arg SPI_IT_TXE
+ * @retval Indicates the state of the SPI_IT.
+
+ */
+ITStatus SPI_GetITStatus(SPI_TypeDef* SPIx, SPI_IT_TypeDef SPI_IT)
+{
+ ITStatus pendingbitstatus = RESET;
+ uint8_t itpos = 0;
+ uint8_t itmask1 = 0;
+ uint8_t itmask2 = 0;
+ __IO uint8_t enablestatus = 0;
+ assert_param(IS_SPI_GET_IT(SPI_IT));
+ /* Get the SPI IT index */
+ itpos = (uint8_t)((uint8_t)1 << ((uint8_t)SPI_IT & (uint8_t)0x0F));
+
+ /* Get the SPI IT mask */
+ itmask1 = (uint8_t)((uint8_t)SPI_IT >> (uint8_t)4);
+ /* Set the IT mask */
+ itmask2 = (uint8_t)((uint8_t)1 << itmask1);
+ /* Get the SPI_IT enable bit status */
+ enablestatus = (uint8_t)((uint8_t)SPIx->SR & itmask2);
+ /* Check the status of the specified SPI interrupt */
+ if (((SPIx->CR3 & itpos) != RESET) && enablestatus)
+ {
+ /* SPI_IT is set */
+ pendingbitstatus = SET;
+ }
+ else
+ {
+ /* SPI_IT is reset */
+ pendingbitstatus = RESET;
+ }
+ /* Return the SPI_IT status */
+ return pendingbitstatus;
+}
+
+/**
+ * @brief Clears the interrupt pending bits.
+ * @param SPIx: where x can be 1 to select the specified SPI peripheral.
+ * @param SPI_IT: Specifies the interrupt pending bit to clear.
+ * This parameter can be one of the following values:
+ * @arg SPI_IT_CRCERR
+ * @arg SPI_IT_WKUP
+ * @note OVR (OverRun Error) interrupt pending bit is cleared by software sequence:
+ * a read operation to SPI_DR register (SPI_ReceiveData()) followed by
+ * a read operation to SPI_SR register (SPI_GetITStatus()).
+ * @note MODF (Mode Fault) interrupt pending bit is cleared by software sequence:
+ * a read/write operation to SPI_SR register (SPI_GetITStatus()) followed by
+ * a write operation to SPI_CR1 register (SPI_Cmd() to enable the SPI).
+ * @retval None
+ */
+void SPI_ClearITPendingBit(SPI_TypeDef* SPIx, SPI_IT_TypeDef SPI_IT)
+{
+ uint8_t itpos = 0;
+ assert_param(IS_SPI_CLEAR_IT(SPI_IT));
+
+ /* Clear SPI_IT_CRCERR or SPI_IT_WKUP interrupt pending bits */
+
+ /* Get the SPI pending bit index */
+ itpos = (uint8_t)((uint8_t)1 << (uint8_t)((uint8_t)(SPI_IT & (uint8_t)0xF0) >> 4));
+ /* Clear the pending bit */
+ SPIx->SR = (uint8_t)(~itpos);
+
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_syscfg.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_syscfg.c
new file mode 100644
index 00000000..5c442d1c
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_syscfg.c
@@ -0,0 +1,507 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_syscfg.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the RI and SYSCFG:
+ * - RI configuration
+ * - SYSCFG configuration
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * This driver provides functions to configure the RI and SYSCFG
+ * These functions are split in 2 groups:
+ *
+ * 1. RI configuration: this group includes all needed functions
+ * to configure the RI:
+ * - Routing the TIM1 Input capture channels
+ * - Close and Open the I/O switches
+ * - Close and Open the analog switches
+ * - Configure the internal Pull-up and Pull-down resistors
+ *
+ * 2. SYSCFG configuration: this group includes all needed functions
+ * to configure the SYSCFG:
+ * - Configure the alternate function remapping of some peripherals
+ * such as: USART, SPI, TIMs...
+ * Remapping possibilities depends on the device (low-density,
+ * medium-density or high density) so it is recommended to
+ * refer to the product reference manual.
+ * - Configure the DMA channels remapping of ADC1 and TIM4
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_syscfg.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup SYSCFG
+ * @brief SYSCFG driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup SYSCFG_Private_Functions
+ * @{
+ */
+
+/** @defgroup SYSCFG_Group1 RI configuration
+ * @brief RI configuration
+ *
+@verbatim
+ ===============================================================================
+ RI configuration functions
+ ===============================================================================
+
+ ===================================================================
+ SYSCFG Driver: how to configure RI
+ ===================================================================
+
+ 1. By default, TIM1 Input Capture channels 2 and 3 are connected to the
+ I/O port assigned in the datasheet pinout (default routing).
+ TIM1 Input Capture channels 2 and 3 can be routed by calling
+ SYSCFG_RITIMInputCaptureConfig()
+ Refer to the device reference manual for more details about
+ TIM1 input capture routing
+
+ 2. For more details about using SYSCFG_RIIOSwitchConfig()
+ and SYSCFG_RIAnalogSwitchConfig() with COMP1 and COMP2, refer to
+ comparators driver
+
+ 3. To output the Internal reference voltage VREFINT, configure corresponding
+ GPIO pin in input mode using GPIO_Init() then use SYSCFG_RIIOSwitchConfig()
+
+ 4. To use the internal Pull-up and Pull-down resistors call
+ SYSCFG_RIResistorConfig()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the RI registers to their default reset values.
+ * @param None
+ * @retval None
+ */
+void SYSCFG_RIDeInit(void)
+{
+ RI->ICR1 = RI_ICR1_RESET_VALUE; /*!< Set RI->ICR1 to reset value */
+ RI->ICR2 = RI_ICR2_RESET_VALUE; /*!< Set RI->ICR2 to reset value */
+ RI->IOSR1 = RI_IOSR1_RESET_VALUE; /*!< Set RI->IOSR1 to reset value */
+ RI->IOSR2 = RI_IOSR2_RESET_VALUE; /*!< Set RI->IOSR2 to reset value */
+ RI->IOSR3 = RI_IOSR3_RESET_VALUE; /*!< Set RI->IOSR3 to reset value */
+ RI->IOSR4 = RI_IOSR4_RESET_VALUE; /*!< Set RI->IOSR3 to reset value */
+ RI->ASCR1 = RI_ASCR1_RESET_VALUE; /*!< Set RI->ASCR1 to reset value */
+ RI->ASCR2 = RI_ASCR2_RESET_VALUE; /*!< Set RI->ASCR2 to reset value */
+ RI->RCR = RI_RCR_RESET_VALUE; /*!< Set RI->RCR to reset value */
+}
+
+/**
+ * @brief Configures the routing interface to select which Input Output pin
+ * to be routed to TIM1 Input Capture.
+ * @param RI_InputCapture: selects the TIM1 input capture2 RI_InputCapture_IC2
+ * or the TIM1 input capture3 RI_InputCapture_IC3
+ * @param RI_InputCaptureRouting: selects the value to set in TIM1 Input Capture
+ * routing register ICRx and can be from RI_InputCaptureRouting_0 to
+ * RI_InputCaptureRouting_22.
+ * @retval None.
+ */
+void SYSCFG_RITIMInputCaptureConfig(RI_InputCapture_TypeDef RI_InputCapture,
+ RI_InputCaptureRouting_TypeDef RI_InputCaptureRouting)
+{
+ /* Check the parameters */
+ assert_param(IS_RI_INPUTCAPTURE(RI_InputCapture));
+ assert_param(IS_RI_INPUTCAPTUREROUTING(RI_InputCaptureRouting));
+
+ /* Check whether Input Capture 2 is selected */
+ if (RI_InputCapture == RI_InputCapture_IC2)
+ {
+ /* Set the value in ICR1 register to route TIM input Capture 2 */
+ RI->ICR1 = (uint8_t) RI_InputCaptureRouting;
+ }
+
+ else /* The Input Capture 3 is selected */
+ {
+ /* Set the value in ICR2 register to route TIM input capture 3 */
+ RI->ICR2 = (uint8_t) RI_InputCaptureRouting;
+ }
+}
+
+/**
+ * @brief Enables or disables the Routing Interface Analog switch.
+ * @param RI_AnalogSwitch: Analog Switch
+ * This parameter can be one of the following values:
+ * @arg RI_AnalogSwitch_0: Analog switch 0
+ * @arg RI_AnalogSwitch_1: Analog switch 1
+ * @arg RI_AnalogSwitch_2: Analog switch 2
+ * @arg RI_AnalogSwitch_3: Analog switch 3
+ * @arg RI_AnalogSwitch_4: Analog switch 4
+ * @arg RI_AnalogSwitch_5: Analog switch 5
+ * @arg RI_AnalogSwitch_6: Analog switch 6
+ * @arg RI_AnalogSwitch_7: Analog switch 7
+ * @arg RI_AnalogSwitch_8: Analog switch 8
+ * @arg RI_AnalogSwitch_9: Analog switch 9
+ * @arg RI_AnalogSwitch_10: Analog switch 10
+ * @arg RI_AnalogSwitch_11: Analog switch 11
+ * @arg RI_AnalogSwitch_12: Analog switch 14
+ * @param NewState: new state of the analog switch.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void SYSCFG_RIAnalogSwitchConfig(RI_AnalogSwitch_TypeDef RI_AnalogSwitch,
+ FunctionalState NewState)
+{
+ uint8_t AnalogSwitchRegister, AnalogSwitchIndex = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RI_ANALOGSWITCH(RI_AnalogSwitch));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Get the analog switch register ASCR1 or ASCR2 */
+ AnalogSwitchRegister = (uint8_t) (RI_AnalogSwitch & (uint8_t) 0xF0);
+
+ /* Get the analog switch bit index in ASCRx register */
+ AnalogSwitchIndex = (uint8_t) (RI_AnalogSwitch & (uint8_t) 0x0F);
+
+ if (NewState != DISABLE)
+ {
+ if (AnalogSwitchRegister == (uint8_t) 0x10)
+ {
+ /* Enable the analog switch */
+ RI->ASCR1 |= (uint8_t) ((uint8_t)1 << (uint8_t) AnalogSwitchIndex);
+ }
+ else
+ {
+ /* Enable the analog switch */
+ RI->ASCR2 |= (uint8_t) ((uint8_t)1 << (uint8_t) AnalogSwitchIndex);
+ }
+ }
+ else
+ {
+ if (AnalogSwitchRegister == (uint8_t) 0x10)
+ {
+ /* Disable the analog switch */
+ RI->ASCR1 &= (uint8_t) (~(uint8_t)((uint8_t)1 << AnalogSwitchIndex));
+ }
+ else
+ {
+ /* Disable the analog switch */
+ RI->ASCR2 &= (uint8_t) (~ (uint8_t)((uint8_t)1 << AnalogSwitchIndex));
+ }
+ }
+}
+
+/**
+ * @brief Closes or Opens the routing interface Input Output switches.
+ * @param RI_IOSwitch: can be one of RI_IOSwitch_1..RI_IOSwitch_24
+ * @param NewState: new state of the Input Output Switch.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None.
+ */
+void SYSCFG_RIIOSwitchConfig(RI_IOSwitch_TypeDef RI_IOSwitch,
+ FunctionalState NewState)
+{
+ uint8_t IOSwitchRegister, IOSwitchIndex = 0;
+
+ /* Check the parameters */
+ assert_param(IS_RI_IOSWITCH(RI_IOSwitch));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Get the Input Output switch bit index in IOSRx register */
+ IOSwitchIndex = (uint8_t) (RI_IOSwitch & (uint8_t) 0x0F);
+
+ /* Get the Input Output switch register IOSR1, IOSR2 or IOSR3 */
+ IOSwitchRegister = (uint8_t) (RI_IOSwitch & (uint8_t) 0xF0);
+
+ /* Check whether the Input Output switch control bit is in the IOSR1 register */
+ if (IOSwitchRegister == (uint8_t) 0x10)
+ {
+ if (NewState != DISABLE)
+ {
+ /* Close the Input Output switch */
+ RI->IOSR1 |= (uint8_t) ((uint8_t)1 << IOSwitchIndex);
+ }
+ else
+ {
+ /* Open the Input Output switch */
+ RI->IOSR1 &= (uint8_t) (~ (uint8_t)((uint8_t)1 << IOSwitchIndex));
+ }
+ }
+
+ /* Check whether the Input Output switch control bit is in the IOSR2 register */
+ else if (IOSwitchRegister == (uint8_t) 0x20)
+ {
+ if (NewState != DISABLE)
+ {
+ /* Close the Input Output switch */
+ RI->IOSR2 |= (uint8_t) ((uint8_t)1 << IOSwitchIndex);
+ }
+ else
+ {
+ /* Open the Input Output switch */
+ RI->IOSR2 &= (uint8_t) (~(uint8_t)((uint8_t)1 << IOSwitchIndex));
+ }
+ }
+
+ /* The Input Output switch control bit is in the IOSR3 register */
+ else if (IOSwitchRegister == (uint8_t) 0x30)
+ {
+ if (NewState != DISABLE)
+ {
+ /* Close the Input Output switch */
+ RI->IOSR3 |= (uint8_t) ((uint8_t)1 << IOSwitchIndex);
+ }
+ else
+ {
+ /* Open the Input Output switch */
+ RI->IOSR3 &= (uint8_t) (~ (uint8_t) ((uint8_t) 1 << IOSwitchIndex));
+ }
+ }
+
+ /* The Input Output switch control bit is in the IOSR4 register */
+ else
+ {
+ if (NewState != DISABLE)
+ {
+ /* Close the Input Output switch */
+ RI->IOSR4 |= (uint8_t) ((uint8_t)1 << IOSwitchIndex);
+ }
+ else
+ {
+ /* Open the Input Output switch */
+ RI->IOSR4 &= (uint8_t) (~ (uint8_t) ((uint8_t) 1 << IOSwitchIndex));
+ }
+ }
+}
+
+/**
+ * @brief Configures the Pull-up and Pull-down Resistors
+ * @param RI_Resistor: selects the resistor to connect,
+ * This parameter can be one of the following values:
+ * @arg RI_Resistor_10KPU: 10K pull up
+ * @arg RI_Resistor_400KPU: 400K pull up
+ * @arg RI_Resistor_10KPD: 10K pull down
+ * @arg RI_Resistor_400KPD: 400K pull down
+ * @retval None
+ */
+void SYSCFG_RIResistorConfig(RI_Resistor_TypeDef RI_Resistor, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_RI_RESISTOR(RI_Resistor));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the resistor */
+ RI->RCR |= (uint8_t) RI_Resistor;
+ }
+ else
+ {
+ /* Disable the Resistor */
+ RI->RCR &= (uint8_t) (~RI_Resistor);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SYSCFG_Group2 SYSCFG configuration
+ * @brief SYSCFG configuration
+ *
+@verbatim
+ ===============================================================================
+ SYSCFG configuration functions
+ ===============================================================================
+
+ ===================================================================
+ SYSCFG Driver: how to use it for remapping
+ ===================================================================
+
+ 1. To remap the alternate function of some peripherals (such as: USART,
+ SPI, TIMs...), use SYSCFG_REMAPPinConfig()
+
+ 2. To remap the DMA channels of ADC1 and TIM4, use SYSCFG_REMAPDMAChannelConfig()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the Remapping registers to their default reset values.
+ * @param None
+ * @retval None
+ */
+void SYSCFG_REMAPDeInit(void)
+{
+ /*!< Set RMPCR1 to reset value */
+ SYSCFG->RMPCR1 = SYSCFG_RMPCR1_RESET_VALUE;
+
+ /*!< Set RMPCR2 to reset value */
+ SYSCFG->RMPCR2 = SYSCFG_RMPCR2_RESET_VALUE;
+
+ /*!< Set RMPCR3 to reset value */
+ SYSCFG->RMPCR3 = SYSCFG_RMPCR3_RESET_VALUE;
+}
+
+/**
+ * @brief Changes the mapping of the specified pins.
+ * @param REMAP_Pin: selects the pin to remap.
+ * This parameter can be one of the following values:
+ * @arg REMAP_Pin_USART1TxRxPortA: USART1 Tx- Rx (PC3- PC2) remapping to PA2- PA3
+ * @arg REMAP_Pin_USART1TxRxPortC: USART1 Tx- Rx (PC3- PC2) remapping to PC5- PC6
+ * @arg REMAP_Pin_USART1Clk: USART1 CK (PC4) remapping to PA0
+ * @arg REMAP_Pin_SPI1Full: SPI1 MISO- MOSI- SCK- NSS(PB7- PB6- PB5- PB4)
+ * remapping to PA2- PA3- PC6- PC5
+ * @arg REMAP_Pin_ADC1ExtTRIG1: ADC1 External Trigger 1 (PA6) remapping to PD0
+ * @arg REMAP_Pin_TIM2TRIGPortA: TIM2 Trigger (PB3) remapping to PA4
+ * @arg REMAP_Pin_TIM3TRIGPortA: TIM3 Trigger (PD1) remapping to PA5
+ * @arg REMAP_Pin_TIM2TRIGLSE: TIM2 Trigger remapping to LSE
+ * @arg REMAP_Pin_TIM3TRIGLSE: TIM3 Trigger remapping to LSE
+ * @arg REMAP_Pin_SPI2Full: SPI2 MISO- MOSI- SCK- NSS(PG7- PG6- PG5- PG4)
+ * remapping to PI3- PI2- PI1- PI0
+ * @arg REMAP_Pin_TIM3TRIGPortG: TIM3 Trigger (PD1) remapping to PG3
+ * @arg REMAP_Pin_TIM23BKIN: TIM2 Break Input (PA4) remapping to PG0
+ * and TIM3 Break Input (PA5) remapping to PG1
+ * @arg REMAP_Pin_SPI1PortF: SPI1 MISO- MOSI- SCK- NSS(PB7- PB6- PB5- PB4)
+ * remapping to PF0- PF1- PF2- PF3
+ * @arg REMAP_Pin_USART3TxRxPortF: USART3 Tx- Rx (PG1- PG0) remapping to PF0- PF1
+ * @arg REMAP_Pin_USART3Clk: USART3 CK (PG2) remapping to PF2
+ * @arg REMAP_Pin_TIM3Channel1: TIM3 Channel 1 (PB1) remapping to PI0
+ * @arg REMAP_Pin_TIM3Channel2: TIM3 Channel 2 (PD0) remapping to PI3
+ * @arg REMAP_Pin_CCO: CCO (PC4) remapping to PE2
+ * @arg REMAP_Pin_TIM2Channel1: TIM2 Channel 1 (PB0) remapping to PC5
+ * @arg REMAP_Pin_TIM2Channel2: TIM2 Channel 2 (PB2) remapping to PC6
+ * @param NewState: This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void SYSCFG_REMAPPinConfig(REMAP_Pin_TypeDef REMAP_Pin, FunctionalState NewState)
+{
+ uint8_t regindex = 0;
+ /* Check the parameters */
+ assert_param(IS_REMAP_PIN(REMAP_Pin));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Read register index */
+ regindex = (uint8_t) ((uint16_t) REMAP_Pin >> 8);
+
+ /* Check if REMAP_Pin is in RMPCR1 register */
+ if (regindex == 0x01)
+ {
+ SYSCFG->RMPCR1 &= (uint8_t)((uint8_t)((uint8_t)REMAP_Pin << 4) | (uint8_t)0x0F);
+ if (NewState != DISABLE)
+ {
+ SYSCFG->RMPCR1 |= (uint8_t)((uint16_t)REMAP_Pin & (uint16_t)0x00F0);
+ }
+ }
+ /* Check if REMAP_Pin is in RMPCR2 register */
+ else if (regindex == 0x02)
+ {
+ if (NewState != DISABLE)
+ {
+ SYSCFG->RMPCR2 |= (uint8_t) REMAP_Pin;
+ }
+ else
+ {
+ SYSCFG->RMPCR2 &= (uint8_t)((uint16_t)(~(uint16_t)REMAP_Pin));
+ }
+ }
+ /* REMAP_Pin is in RMPCR3 register */
+ else
+ {
+ if (NewState != DISABLE)
+ {
+ SYSCFG->RMPCR3 |= (uint8_t) REMAP_Pin;
+ }
+ else
+ {
+ SYSCFG->RMPCR3 &= (uint8_t)((uint16_t)(~(uint16_t)REMAP_Pin));
+ }
+ }
+}
+
+/**
+ * @brief Remaps the DMA Channel to the specific peripheral (ADC or TIM4)
+ * @param REMAP_DMAChannel: specifies the DMA Channel to remap.
+ * This parameter can be one of the following values:
+ * @arg REMAP_DMA1Channel_ADC1ToChannel0: ADC1 DMA1 req/ack mapped on DMA1 channel 0
+ * @arg REMAP_DMA1Channel_ADC1ToChannel1: ADC1 DMA1 req/ack mapped on DMA1 channel 1
+ * @arg REMAP_DMA1Channel_ADC1ToChannel2: ADC1 DMA1 req/ack mapped on DMA1 channel 2
+ * @arg REMAP_DMA1Channel_ADC1ToChannel3: ADC1 DMA1 req/ack mapped on DMA1 channel 3
+ * @arg REMAP_DMA1Channel_TIM4ToChannel0: TIM4 DMA1 req/ack mapped on DMA1 channel 0
+ * @arg REMAP_DMA1Channel_TIM4ToChannel1: TIM4 DMA1 req/ack mapped on DMA1 channel 1
+ * @arg REMAP_DMA1Channel_TIM4ToChannel2: TIM4 DMA1 req/ack mapped on DMA1 channel 2
+ * @arg REMAP_DMA1Channel_TIM4ToChannel3: TIM4 DMA1 req/ack mapped on DMA1 channel 3
+ * @retval None
+ */
+void SYSCFG_REMAPDMAChannelConfig(REMAP_DMAChannel_TypeDef REMAP_DMAChannel)
+{
+ /* Check the parameters */
+ assert_param(IS_REMAP_DMACHANNEL(REMAP_DMAChannel));
+
+ /* Check if the TIM4 DMA channel is selected: bits 4 --> 7 are set */
+ if ((REMAP_DMAChannel & 0xF0) != RESET)
+ {
+ /* Reset the TIM4 DMA channels */
+ SYSCFG->RMPCR1 &= (uint8_t) (~SYSCFG_RMPCR1_TIM4DMA_REMAP);
+ }
+ /* ADC DMA channel is selected: bits 4 --> 7 are reset */
+ else
+ {
+ /* Reset the ADC DMA channels */
+ SYSCFG->RMPCR1 &= (uint8_t) (~SYSCFG_RMPCR1_ADC1DMA_REMAP);
+ }
+ /* Set the DMA Channels remapping */
+ SYSCFG->RMPCR1 |= (uint8_t) ((uint8_t)0x0F & REMAP_DMAChannel);
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim1.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim1.c
new file mode 100644
index 00000000..2c278f45
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim1.c
@@ -0,0 +1,2774 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_tim1.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the TIM1 peripheral:
+ * - TimeBase management
+ * - Output Compare management
+ * - Input Capture management
+ * - Interrupts, DMA and flags management
+ * - Clocks management
+ * - Synchronization management
+ * - Specific interface management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * This driver provides functions to configure and initialize the TIM1
+ * peripheral
+ * These functions are split in 7 groups:
+ *
+ * 1. TIM1 TimeBase management: this group includes all needed functions
+ * to configure the TIM Timebase unit:
+ * - Set/Get Prescaler
+ * - Set/Get Autoreload
+ * - Counter modes configuration
+ * - Select the One Pulse mode
+ * - Update Request Configuration
+ * - Update Disable Configuration
+ * - Auto-Preload Configuration
+ * - Enable/Disable the counter
+ *
+ * 2. TIM1 Output Compare management: this group includes all needed
+ * functions to configure the Capture/Compare unit used in Output
+ * compare mode:
+ * - Configure each channel, independently, in Output Compare mode
+ * - Select the output compare modes
+ * - Select the Polarities of each channel
+ * - Set/Get the Capture/Compare register values
+ * - Select the Output Compare Fast mode
+ * - Select the Output Compare Forced mode
+ * - Output Compare-Preload Configuration
+ * - Clear Output Compare Reference
+ * - Select the OCREF Clear signal
+ * - Enable/Disable the Capture/Compare Channels
+ *
+ * 3. TIM1 Input Capture management: this group includes all needed
+ * functions to configure the Capture/Compare unit used in
+ * Input Capture mode:
+ * - Configure each channel in input capture mode
+ * - Configure Channel1/2 in PWM Input mode
+ * - Set the Input Capture Prescaler
+ * - Get the Capture/Compare values
+ *
+ * 4. TIM1 interrupts, DMA and flags management
+ * - Enable/Disable interrupt sources
+ * - Get flags status
+ * - Clear flags/ Pending bits
+ * - Enable/Disable DMA requests
+ * - Configure DMA burst mode
+ * - Select CaptureCompare DMA request
+ *
+ * 5. TIM1 clocks management: this group includes all needed functions
+ * to configure the clock controller unit:
+ * - Select internal/External clock
+ * - Select the external clock mode: ETR(Mode1/Mode2) or TIx
+ *
+ * 6. TIM1 synchronization management: this group includes all needed
+ * functions to configure the Synchronization unit:
+ * - Select Input Trigger
+ * - Select Output Trigger
+ * - Select Master Slave Mode
+ * - ETR Configuration when used as external trigger
+ *
+ * 7. TIM1 specific interface management, this group includes all
+ * needed functions to use the specific TIM1 interface:
+ * - Encoder Interface Configuration
+ * - Select Hall Sensor
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_tim1.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup TIM1
+ * @brief TIM1 driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup TIM1_Private_Functions_Prototypes
+ * @{
+ */
+
+static void TI1_Config(uint8_t TIM1_ICPolarity, uint8_t TIM1_ICSelection,
+ uint8_t TIM1_ICFilter);
+static void TI2_Config(uint8_t TIM1_ICPolarity, uint8_t TIM1_ICSelection,
+ uint8_t TIM1_ICFilter);
+static void TI3_Config(uint8_t TIM1_ICPolarity, uint8_t TIM1_ICSelection,
+ uint8_t TIM1_ICFilter);
+static void TI4_Config(uint8_t TIM1_ICPolarity, uint8_t TIM1_ICSelection,
+ uint8_t TIM1_ICFilter);
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup TIM1_Private_Functions
+ * @{
+ */
+
+/** @defgroup TIM1_Group1 TimeBase management functions
+ * @brief TimeBase management functions
+ *
+@verbatim
+ ===============================================================================
+ TimeBase management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM1 Driver: how to use it in Timing(Time base) Mode
+ ===================================================================
+ To use the Timer in Timing(Time base) mode, the following steps are mandatory:
+
+ 1. Enable TIM1 clock using CLK_PeripheralClockConfig(CLK_Peripheral_TIM1, ENABLE) function.
+
+ 2. Call TIM1_TimeBaseInit() to configure the Time Base unit with the
+ corresponding configuration.
+
+ 3. Enable global interrupts if you need to generate the update interrupt.
+
+ 4. Enable the corresponding interrupt using the function TIM1_ITConfig(TIM1_IT_Update)
+
+ 5. Call the TIM1_Cmd(ENABLE) function to enable the TIM1 counter.
+
+ Note1: All other functions can be used separately to modify, if needed,
+ a specific feature of the Timer.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the TIM1 peripheral registers to their default reset values.
+ * @param None
+ * @retval None
+ */
+void TIM1_DeInit(void)
+{
+ TIM1->CR1 = TIM1_CR1_RESET_VALUE;
+ TIM1->CR2 = TIM1_CR2_RESET_VALUE;
+ TIM1->SMCR = TIM1_SMCR_RESET_VALUE;
+ TIM1->ETR = TIM1_ETR_RESET_VALUE;
+ TIM1->IER = TIM1_IER_RESET_VALUE;
+
+ /* Disable channels */
+ TIM1->CCER1 = TIM1_CCER1_RESET_VALUE;
+ TIM1->CCER2 = TIM1_CCER2_RESET_VALUE;
+ /* Configure channels as inputs: it is necessary if lock level is equal to 2 or 3 */
+ TIM1->CCMR1 = 0x01;
+ TIM1->CCMR2 = 0x01;
+ TIM1->CCMR3 = 0x01;
+ TIM1->CCMR4 = 0x01;
+ /* Then reset channel registers: it also works if lock level is equal to 2 or 3 */
+ TIM1->CCER1 = TIM1_CCER1_RESET_VALUE;
+ TIM1->CCER2 = TIM1_CCER2_RESET_VALUE;
+ TIM1->CCMR1 = TIM1_CCMR1_RESET_VALUE;
+ TIM1->CCMR2 = TIM1_CCMR2_RESET_VALUE;
+ TIM1->CCMR3 = TIM1_CCMR3_RESET_VALUE;
+ TIM1->CCMR4 = TIM1_CCMR4_RESET_VALUE;
+ TIM1->CNTRH = TIM1_CNTRH_RESET_VALUE;
+ TIM1->CNTRL = TIM1_CNTRL_RESET_VALUE;
+ TIM1->PSCRH = TIM1_PSCRH_RESET_VALUE;
+ TIM1->PSCRL = TIM1_PSCRL_RESET_VALUE;
+ TIM1->ARRH = TIM1_ARRH_RESET_VALUE;
+ TIM1->ARRL = TIM1_ARRL_RESET_VALUE;
+ TIM1->CCR1H = TIM1_CCR1H_RESET_VALUE;
+ TIM1->CCR1L = TIM1_CCR1L_RESET_VALUE;
+ TIM1->CCR2H = TIM1_CCR2H_RESET_VALUE;
+ TIM1->CCR2L = TIM1_CCR2L_RESET_VALUE;
+ TIM1->CCR3H = TIM1_CCR3H_RESET_VALUE;
+ TIM1->CCR3L = TIM1_CCR3L_RESET_VALUE;
+ TIM1->CCR4H = TIM1_CCR4H_RESET_VALUE;
+ TIM1->CCR4L = TIM1_CCR4L_RESET_VALUE;
+ TIM1->OISR = TIM1_OISR_RESET_VALUE;
+ TIM1->EGR = 0x01; /* TIM1_EGR_UG */
+ TIM1->DTR = TIM1_DTR_RESET_VALUE;
+ TIM1->BKR = TIM1_BKR_RESET_VALUE;
+ TIM1->RCR = TIM1_RCR_RESET_VALUE;
+ TIM1->SR1 = TIM1_SR1_RESET_VALUE;
+ TIM1->SR2 = TIM1_SR2_RESET_VALUE;
+}
+
+/**
+ * @brief Initializes the TIM1 Time Base Unit according to the specified parameters.
+ * @param TIM1_Prescaler specifies the Prescaler value.
+ * @param TIM1_CounterMode specifies the counter mode from
+ * This parameter can be one of the following values:
+ * @arg TIM1_CounterMode_Up: Counter mode Up
+ * @arg TIM1_CounterMode_Down: Counter mode Down
+ * @arg TIM1_CounterMode_CenterAligned1: Counter mode center aligned
+ * @arg TIM1_CounterMode_CenterAligned2: Counter mode center aligned
+ * @arg TIM1_CounterMode_CenterAligned3: Counter mode center aligned
+ * @param TIM1_Period specifies the Period value.
+ * @param TIM1_RepetitionCounter specifies the Repetition counter value
+ * @retval None
+ */
+void TIM1_TimeBaseInit(uint16_t TIM1_Prescaler,
+ TIM1_CounterMode_TypeDef TIM1_CounterMode,
+ uint16_t TIM1_Period,
+ uint8_t TIM1_RepetitionCounter)
+{
+ /* Check parameters */
+ assert_param(IS_TIM1_COUNTER_MODE(TIM1_CounterMode));
+
+
+ /* Set the Autoreload value */
+ TIM1->ARRH = (uint8_t)(TIM1_Period >> 8);
+ TIM1->ARRL = (uint8_t)(TIM1_Period);
+
+ /* Set the Prescaler value */
+ TIM1->PSCRH = (uint8_t)(TIM1_Prescaler >> 8);
+ TIM1->PSCRL = (uint8_t)(TIM1_Prescaler);
+
+ /* Select the Counter Mode */
+ TIM1->CR1 = (uint8_t)((uint8_t)(TIM1->CR1 & (uint8_t)(~(TIM1_CR1_CMS | TIM1_CR1_DIR)))
+ | (uint8_t)(TIM1_CounterMode));
+
+ /* Set the Repetition Counter value */
+ TIM1->RCR = TIM1_RepetitionCounter;
+
+}
+
+/**
+ * @brief Configures the TIM1 Prescaler.
+ * @param Prescaler specifies the Prescaler Register value
+ * This parameter must be a value between 0x0000 and 0xFFFF
+ * @param TIM1_PSCReloadMode specifies the TIM1 Prescaler Reload mode.
+ * This parameter can be one of the following values
+ * @arg TIM1_PSCReloadMode_Immediate: The Prescaler is loaded immediately.
+ * @arg TIM1_PSCReloadMode_Update: The Prescaler is loaded at the update
+ * event.
+ * @retval None
+ */
+
+void TIM1_PrescalerConfig(uint16_t Prescaler, TIM1_PSCReloadMode_TypeDef TIM1_PSCReloadMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_PRESCALER_RELOAD(TIM1_PSCReloadMode));
+
+ /* Set the Prescaler value */
+ TIM1->PSCRH = (uint8_t)(Prescaler >> 8);
+ TIM1->PSCRL = (uint8_t)(Prescaler);
+
+ /* Set or reset the UG Bit */
+ TIM1->EGR = (uint8_t)TIM1_PSCReloadMode;
+}
+
+/**
+ * @brief Specifies the TIM1 Counter Mode to be used.
+ * @param TIM1_CounterMode specifies the Counter Mode to be used
+ * This parameter can be one of the following values:
+ * @arg TIM1_CounterMode_Up: TIM1 Up Counting Mode
+ * @arg TIM1_CounterMode_Down: TIM1 Down Counting Mode
+ * @arg TIM1_CounterMode_CenterAligned1: TIM1 Center Aligned Mode1
+ * @arg TIM1_CounterMode_CenterAligned2: TIM1 Center Aligned Mode2
+ * @arg IM1_CounterMode_CenterAligned3: TIM1 Center Aligned Mode3
+ * @retval None
+ */
+void TIM1_CounterModeConfig(TIM1_CounterMode_TypeDef TIM1_CounterMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_COUNTER_MODE(TIM1_CounterMode));
+
+
+ /* Reset the CMS and DIR Bits & Set the Counter Mode */
+ TIM1->CR1 = (uint8_t)((uint8_t)(TIM1->CR1 & (uint8_t)((uint8_t)(~TIM1_CR1_CMS) & (uint8_t)(~TIM1_CR1_DIR)))
+ | (uint8_t)TIM1_CounterMode);
+}
+
+/**
+ * @brief Sets the TIM1 Counter Register value.
+ * @param Counter specifies the Counter register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM1_SetCounter(uint16_t Counter)
+{
+ /* Set the Counter Register value */
+ TIM1->CNTRH = (uint8_t)(Counter >> 8);
+ TIM1->CNTRL = (uint8_t)(Counter);
+}
+
+/**
+ * @brief Sets the TIM1 Autoreload Register value.
+ * @param Autoreload specifies the Autoreload register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM1_SetAutoreload(uint16_t Autoreload)
+{
+ /* Set the Autoreload Register value */
+ TIM1->ARRH = (uint8_t)(Autoreload >> 8);
+ TIM1->ARRL = (uint8_t)(Autoreload);
+}
+
+/**
+ * @brief Gets the TIM1 Counter value.
+ * @param None
+ * @retval Counter Register value.
+ */
+uint16_t TIM1_GetCounter(void)
+{
+ /* Get the Counter Register value */
+ uint16_t tmpcntr = 0;
+ uint8_t tmpcntrl = 0, tmpcntrh = 0;
+
+ tmpcntrh = TIM1->CNTRH;
+ tmpcntrl = TIM1->CNTRL;
+
+ tmpcntr = (uint16_t)(tmpcntrl);
+ tmpcntr |= (uint16_t)((uint16_t)tmpcntrh << 8);
+
+ /* Get the Counter Register value */
+ return (uint16_t)tmpcntr;
+}
+
+/**
+ * @brief Gets the TIM1 Prescaler value.
+ * @param None
+ * @retval Prescaler Register value.
+ */
+uint16_t TIM1_GetPrescaler(void)
+{
+ uint16_t tmpreg = 0;
+ tmpreg = (uint16_t)((uint16_t)TIM1->PSCRH << 8);
+ /* Get the Prescaler Register value */
+ return (uint16_t)(tmpreg | TIM1->PSCRL);
+}
+
+/**
+ * @brief Enables or Disables the TIM1 Update event.
+ * @param NewState new state of the TIM1 peripheral Preload register.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_UpdateDisableConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the UDIS Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CR1 |= TIM1_CR1_UDIS;
+ }
+ else
+ {
+ TIM1->CR1 &= (uint8_t)(~TIM1_CR1_UDIS);
+ }
+}
+
+/**
+ * @brief Selects the TIM1 Update Request Interrupt source.
+ * @param TIM1_UpdateSource specifies the Update source.
+ * This parameter can be one of the following values
+ * @arg TIM1_UpdateSource_Regular
+ * @arg TIM1_UpdateSource_Global
+ * @retval None
+ */
+void TIM1_UpdateRequestConfig(TIM1_UpdateSource_TypeDef TIM1_UpdateSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_UPDATE_SOURCE(TIM1_UpdateSource));
+
+ /* Set or Reset the URS Bit */
+ if (TIM1_UpdateSource != TIM1_UpdateSource_Global)
+ {
+ TIM1->CR1 |= TIM1_CR1_URS;
+ }
+ else
+ {
+ TIM1->CR1 &= (uint8_t)(~TIM1_CR1_URS);
+ }
+}
+
+/**
+ * @brief Enables or disables TIM1 peripheral Preload register on ARR.
+ * @param NewState new state of the TIM1 peripheral Preload register.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_ARRPreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the ARPE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CR1 |= TIM1_CR1_ARPE;
+ }
+ else
+ {
+ TIM1->CR1 &= (uint8_t)(~TIM1_CR1_ARPE);
+ }
+}
+
+/**
+ * @brief Selects the TIM1’s One Pulse Mode.
+ * @param TIM1_OPMode specifies the OPM Mode to be used.
+ * This parameter can be one of the following values
+ * @arg TIM1_OPMode_Single
+ * @arg TIM1_OPMode_Repetitive
+ * @retval None
+ */
+void TIM1_SelectOnePulseMode(TIM1_OPMode_TypeDef TIM1_OPMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_OPM_MODE(TIM1_OPMode));
+
+ /* Set or Reset the OPM Bit */
+ if (TIM1_OPMode != TIM1_OPMode_Repetitive)
+ {
+ TIM1->CR1 |= TIM1_CR1_OPM;
+ }
+ else
+ {
+ TIM1->CR1 &= (uint8_t)(~TIM1_CR1_OPM);
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM1 peripheral.
+ * @param NewState new state of the TIM1 peripheral.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_Cmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* set or Reset the CEN Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CR1 |= TIM1_CR1_CEN;
+ }
+ else
+ {
+ TIM1->CR1 &= (uint8_t)(~TIM1_CR1_CEN);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Group2 Output Compare management functions
+ * @brief Output Compare management functions
+ *
+@verbatim
+ ===============================================================================
+ Output Compare management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM1 Driver: how to use it in Output Compare Mode
+ ===================================================================
+ To use the Timer in Output Compare mode, the following steps are mandatory:
+
+ 1. Enable TIM1 clock using CLK_PeripheralClockConfig(CLK_Peripheral_TIM1, ENABLE) function.
+
+ 2. Configure the TIM1 pins in output mode by configuring the corresponding GPIO pins
+
+ 3. Configure the Time base unit as described in the first part of this driver, if needed,
+ otherwise the Timer will run with the default configuration:
+ - Autoreload value = 0xFFFF
+ - Prescaler value = 0x0000
+ - Counter mode = Up counting
+
+ 4. Call TIM1_OCxInit() to configure the channel x with the desired parameters
+ including:
+ - TIM1 Output Compare mode: TIM1_OCMode
+ - TIM1 Output State: TIM1_OutputState
+ - TIM1 Complementary Output State: TIM1_OutputNState
+ - TIM1 Pulse value: TIM1_Pulse
+ - TIM1 Output Compare Polarity : TIM1_OCPolarity
+ - TIM1 Complementary Output Compare Polarity : TIM1_OCNPolarity
+ - TIM1 Output Idle State: TIM1_OCIdleState
+ - TIM1 Complementary Output Idle State: TIM1_OCNIdleState
+
+ 5. Call the TIM1_Cmd(ENABLE) function to enable the TIM1 counter.
+
+ Note1: All other functions can be used separately to modify, if needed,
+ a specific feature of the Timer.
+
+ Note2: If the corresponding interrupt or DMA request are needed, the user should:
+ 1. Enable global interrupts (or the DMA) to use the TIM1 interrupts (or DMA requests).
+ 2. Enable the corresponding interrupt (or DMA request) using the function
+ TIM1_ITConfig(TIM1_IT_CCx) (or TIM1_DMACmd(TIM1_DMASource_CCx))
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the TIM1 Channel1 according to the specified parameters.
+ * @param TIM1_OCMode specifies the Output Compare mode
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCMode_Timing: OC Mode Timing
+ * @arg TIM1_OCMode_Active: OC Mode Active
+ * @arg TIM1_OCMode_Inactive: OC Mode Inactive
+ * @arg TIM1_OCMode_Toggle: OC Mode Toggle
+ * @arg TIM1_OCMode_PWM1: OC Mode PWM1
+ * @arg TIM1_OCMode_PWM2: OC Mode PWM2
+ * @param TIM1_OutputState specifies the Output State
+ * This parameter can be one of the following values:
+ * @arg TIM1_OutputState_Disable: Output state disable
+ * @arg TIM1_OutputState_Enable: Output state enable
+ * @param TIM1_OutputNState specifies the Complementary Output State
+ * This parameter can be one of the following values:
+ * @arg TIM1_OutputNState_Disable: Output N state disable
+ * @arg TIM1_OutputNState_Enable: Output N state enable
+ * @param TIM1_Pulse specifies the Pulse width value.
+ * @param TIM1_OCPolarity specifies the Output Compare Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCPolarity_High: Output Compare active low
+ * @arg TIM1_OCPolarity_Low: Output Compare active high
+ * @param TIM1_OCNPolarity specifies the Complementary Output Compare Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCNPolarity_High: Complementary Output Compare active low
+ * @arg TIM1_OCNPolarity_Low: Complementary Output Compare active high
+ * @param TIM1_OCIdleState specifies the Output Compare Idle State
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCIdleState_Set: Output Compare Idle state set
+ * @arg TIM1_OCIdleState_Reset: Output Compare Idle state reset
+ * @param TIM1_OCNIdleState specifies the Complementary Output Compare Idle State
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCNIdleState_Set: Complementary Output Compare Idle state set
+ * @arg TIM1_OCNIdleState_Reset: Complementary Output Compare Idle state reset
+ * @retval None
+ */
+void TIM1_OC1Init(TIM1_OCMode_TypeDef TIM1_OCMode,
+ TIM1_OutputState_TypeDef TIM1_OutputState,
+ TIM1_OutputNState_TypeDef TIM1_OutputNState,
+ uint16_t TIM1_Pulse,
+ TIM1_OCPolarity_TypeDef TIM1_OCPolarity,
+ TIM1_OCNPolarity_TypeDef TIM1_OCNPolarity,
+ TIM1_OCIdleState_TypeDef TIM1_OCIdleState,
+ TIM1_OCNIdleState_TypeDef TIM1_OCNIdleState)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_OC_MODE(TIM1_OCMode));
+ assert_param(IS_TIM1_OUTPUT_STATE(TIM1_OutputState));
+ assert_param(IS_TIM1_OUTPUTN_STATE(TIM1_OutputNState));
+ assert_param(IS_TIM1_OC_POLARITY(TIM1_OCPolarity));
+ assert_param(IS_TIM1_OCN_POLARITY(TIM1_OCNPolarity));
+ assert_param(IS_TIM1_OCIDLE_STATE(TIM1_OCIdleState));
+ assert_param(IS_TIM1_OCNIDLE_STATE(TIM1_OCNIdleState));
+
+ /* Disable the Channel 1: Reset the CCE Bit, Set the Output State ,
+ the Output N State, the Output Polarity & the Output N Polarity*/
+ TIM1->CCER1 &= (uint8_t)(~(TIM1_CCER1_CC1E | TIM1_CCER1_CC1NE
+ | TIM1_CCER1_CC1P | TIM1_CCER1_CC1NP));
+ /* Set the Output State & Set the Output N State & Set the Output Polarity
+ & Set the Output N Polarity */
+ TIM1->CCER1 |= (uint8_t)((uint8_t)((uint8_t)(TIM1_OutputState & TIM1_CCER1_CC1E)
+ | (uint8_t)(TIM1_OutputNState & TIM1_CCER1_CC1NE))
+ | (uint8_t)( (uint8_t)(TIM1_OCPolarity & TIM1_CCER1_CC1P)
+ | (uint8_t)(TIM1_OCNPolarity & TIM1_CCER1_CC1NP)));
+
+ /* Reset the Output Compare Bits & Set the Output Compare Mode */
+ TIM1->CCMR1 = (uint8_t)((uint8_t)(TIM1->CCMR1 & (uint8_t)(~TIM1_CCMR_OCM))
+ | (uint8_t)TIM1_OCMode);
+
+ /* Reset the Output Idle state & the Output N Idle state bits */
+ TIM1->OISR &= (uint8_t)(~(TIM1_OISR_OIS1 | TIM1_OISR_OIS1N));
+ /* Set the Output Idle state & the Output N Idle state configuration */
+ TIM1->OISR |= (uint8_t)((uint8_t)(TIM1_OCIdleState & TIM1_OISR_OIS1)
+ | (uint8_t)(TIM1_OCNIdleState & TIM1_OISR_OIS1N));
+
+ /* Set the Pulse value */
+ TIM1->CCR1H = (uint8_t)(TIM1_Pulse >> 8);
+ TIM1->CCR1L = (uint8_t)(TIM1_Pulse);
+}
+
+/**
+ * @brief Initializes the TIM1 Channel2 according to the specified parameters.
+ * @param TIM1_OCMode specifies the Output Compare mode
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCMode_Timing: OC Mode Timing
+ * @arg TIM1_OCMode_Active: OC Mode Active
+ * @arg TIM1_OCMode_Inactive: OC Mode Inactive
+ * @arg TIM1_OCMode_Toggle: OC Mode Toggle
+ * @arg TIM1_OCMode_PWM1: OC Mode PWM1
+ * @arg TIM1_OCMode_PWM2: OC Mode PWM2
+ * @param TIM1_OutputState specifies the Output State
+ * This parameter can be one of the following values:
+ * @arg TIM1_OutputState_Disable: Output state disable
+ * @arg TIM1_OutputState_Enable: Output state enable
+ * @param TIM1_OutputNState specifies the Complementary Output State
+ * This parameter can be one of the following values:
+ * @arg TIM1_OutputNState_Disable: Output N state disable
+ * @arg TIM1_OutputNState_Enable: Output N state enable
+ * @param TIM1_Pulse specifies the Pulse width value.
+ * @param TIM1_OCPolarity specifies the Output Compare Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCPolarity_High: Output Compare active low
+ * @arg TIM1_OCPolarity_Low: Output Compare active high
+ * @param TIM1_OCNPolarity specifies the Complementary Output Compare
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCNPolarity_High: Complementary Output Compare active low
+ * @arg TIM1_OCNPolarity_Low: Complementary Output Compare active high
+ * @param TIM1_OCIdleState specifies the Output Compare Idle State
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCIdleState_Set: Output Compare Idle state set
+ * @arg TIM1_OCIdleState_Reset: Output Compare Idle state reset
+ * @param TIM1_OCNIdleState specifies the Complementary Output Compare Idle State
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCNIdleState_Set: Complementary Output Compare Idle state set
+ * @arg TIM1_OCNIdleState_Reset: Complementary Output Compare Idle state reset
+ * @retval None
+ */
+void TIM1_OC2Init(TIM1_OCMode_TypeDef TIM1_OCMode,
+ TIM1_OutputState_TypeDef TIM1_OutputState,
+ TIM1_OutputNState_TypeDef TIM1_OutputNState,
+ uint16_t TIM1_Pulse,
+ TIM1_OCPolarity_TypeDef TIM1_OCPolarity,
+ TIM1_OCNPolarity_TypeDef TIM1_OCNPolarity,
+ TIM1_OCIdleState_TypeDef TIM1_OCIdleState,
+ TIM1_OCNIdleState_TypeDef TIM1_OCNIdleState)
+{
+
+ /* Check the parameters */
+ assert_param(IS_TIM1_OC_MODE(TIM1_OCMode));
+ assert_param(IS_TIM1_OUTPUT_STATE(TIM1_OutputState));
+ assert_param(IS_TIM1_OUTPUTN_STATE(TIM1_OutputNState));
+ assert_param(IS_TIM1_OC_POLARITY(TIM1_OCPolarity));
+ assert_param(IS_TIM1_OCN_POLARITY(TIM1_OCNPolarity));
+ assert_param(IS_TIM1_OCIDLE_STATE(TIM1_OCIdleState));
+ assert_param(IS_TIM1_OCNIDLE_STATE(TIM1_OCNIdleState));
+
+ /* Disable the Channel 1: Reset the CCE Bit, Set the Output State,
+ the Output N State, the Output Polarity & the Output N Polarity*/
+ TIM1->CCER1 &= (uint8_t)(~(TIM1_CCER1_CC2E | TIM1_CCER1_CC2NE | TIM1_CCER1_CC2P | TIM1_CCER1_CC2NP));
+
+ /* Set the Output State & Set the Output N State & Set the Output Polarity & Set the Output N Polarity */
+ TIM1->CCER1 |= (uint8_t)((uint8_t)((uint8_t)(TIM1_OutputState & TIM1_CCER1_CC2E) | (uint8_t)(TIM1_OutputNState & TIM1_CCER1_CC2NE))
+ | (uint8_t) ((uint8_t)(TIM1_OCPolarity & TIM1_CCER1_CC2P) | (uint8_t)(TIM1_OCNPolarity & TIM1_CCER1_CC2NP)));
+
+ /* Reset the Output Compare Bits & Set the Output Compare Mode */
+ TIM1->CCMR2 = (uint8_t)((uint8_t)(TIM1->CCMR2 & (uint8_t)(~TIM1_CCMR_OCM)) | (uint8_t)TIM1_OCMode);
+
+ /* Reset the Output Idle state & the Output N Idle state bits */
+ TIM1->OISR &= (uint8_t)(~(TIM1_OISR_OIS2 | TIM1_OISR_OIS2N));
+ /* Set the Output Idle state & the Output N Idle state configuration */
+ TIM1->OISR |= (uint8_t)((uint8_t)(TIM1_OISR_OIS2 & TIM1_OCIdleState) | (uint8_t)(TIM1_OISR_OIS2N & TIM1_OCNIdleState));
+
+ /* Set the Pulse value */
+ TIM1->CCR2H = (uint8_t)(TIM1_Pulse >> 8);
+ TIM1->CCR2L = (uint8_t)(TIM1_Pulse);
+}
+
+/**
+ * @brief Initializes the TIM1 Channel3 according to the specified parameters.
+ * @param TIM1_OCMode specifies the Output Compare mode
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCMode_Timing: OC Mode Timing
+ * @arg TIM1_OCMode_Active: OC Mode Active
+ * @arg TIM1_OCMode_Inactive: OC Mode Inactive
+ * @arg TIM1_OCMode_Toggle: OC Mode Toggle
+ * @arg TIM1_OCMode_PWM1: OC Mode PWM1
+ * @arg TIM1_OCMode_PWM2: OC Mode PWM2
+ * @param TIM1_OutputState specifies the Output State
+ * This parameter can be one of the following values:
+ * @arg TIM1_OutputState_Disable: Output state disable
+ * @arg TIM1_OutputState_Enable: Output state enable
+ * @param TIM1_OutputNState specifies the Complementary Output State
+ * This parameter can be one of the following values:
+ * @arg TIM1_OutputNState_Disable: Output N state disable
+ * @arg TIM1_OutputNState_Enable: Output N state enable
+ * @param TIM1_Pulse specifies the Pulse width value.
+ * @param TIM1_OCPolarity specifies the Output Compare Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCPolarity_High: Output Compare active low
+ * @arg TIM1_OCPolarity_Low: Output Compare active high
+ * @param TIM1_OCNPolarity specifies the Complementary Output Compare Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCNPolarity_High: Complementary Output Compare active low
+ * @arg TIM1_OCNPolarity_Low: Complementary Output Compare active high
+ * @param TIM1_OCIdleState specifies the Output Compare Idle State
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCIdleState_Set: Output Compare Idle state set
+ * @arg TIM1_OCIdleState_Reset: Output Compare Idle state reset
+ * @param TIM1_OCNIdleState specifies the Complementary Output Compare Idle State
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCNIdleState_Set: Complementary Output Compare Idle state set
+ * @arg TIM1_OCNIdleState_Reset: Complementary Output Compare Idle state reset
+ * @retval None
+ */
+void TIM1_OC3Init(TIM1_OCMode_TypeDef TIM1_OCMode,
+ TIM1_OutputState_TypeDef TIM1_OutputState,
+ TIM1_OutputNState_TypeDef TIM1_OutputNState,
+ uint16_t TIM1_Pulse,
+ TIM1_OCPolarity_TypeDef TIM1_OCPolarity,
+ TIM1_OCNPolarity_TypeDef TIM1_OCNPolarity,
+ TIM1_OCIdleState_TypeDef TIM1_OCIdleState,
+ TIM1_OCNIdleState_TypeDef TIM1_OCNIdleState)
+{
+
+ /* Check the parameters */
+ assert_param(IS_TIM1_OC_MODE(TIM1_OCMode));
+ assert_param(IS_TIM1_OUTPUT_STATE(TIM1_OutputState));
+ assert_param(IS_TIM1_OUTPUTN_STATE(TIM1_OutputNState));
+ assert_param(IS_TIM1_OC_POLARITY(TIM1_OCPolarity));
+ assert_param(IS_TIM1_OCN_POLARITY(TIM1_OCNPolarity));
+ assert_param(IS_TIM1_OCIDLE_STATE(TIM1_OCIdleState));
+ assert_param(IS_TIM1_OCNIDLE_STATE(TIM1_OCNIdleState));
+
+ /* Disable the Channel 1: Reset the CCE Bit, Set the Output State,
+ the Output N State, the Output Polarity & the Output N Polarity */
+ TIM1->CCER2 &= (uint8_t)(~( TIM1_CCER2_CC3E | TIM1_CCER2_CC3NE | TIM1_CCER2_CC3P | TIM1_CCER2_CC3NP));
+
+ /* Set the Output State & Set the Output N State & Set the Output Polarity & Set the Output N Polarity */
+ TIM1->CCER2 |= (uint8_t)((uint8_t)((uint8_t)(TIM1_OutputState & TIM1_CCER2_CC3E) | (uint8_t)(TIM1_OutputNState & TIM1_CCER2_CC3NE))
+ | (uint8_t)((uint8_t)(TIM1_OCPolarity & TIM1_CCER2_CC3P) | (uint8_t)(TIM1_OCNPolarity & TIM1_CCER2_CC3NP)));
+
+ /* Reset the Output Compare Bits & Set the Output Compare Mode */
+ TIM1->CCMR3 = (uint8_t)((uint8_t)(TIM1->CCMR3 & (uint8_t)(~TIM1_CCMR_OCM)) | (uint8_t)TIM1_OCMode);
+
+ /* Reset the Output Idle state & the Output N Idle state bits */
+ TIM1->OISR &= (uint8_t)(~(TIM1_OISR_OIS3 | TIM1_OISR_OIS3N));
+ /* Set the Output Idle state & the Output N Idle state configuration */
+ TIM1->OISR |= (uint8_t)((uint8_t)(TIM1_OISR_OIS3 & TIM1_OCIdleState) | (uint8_t) (TIM1_OISR_OIS3N & TIM1_OCNIdleState));
+
+ /* Set the Pulse value */
+ TIM1->CCR3H = (uint8_t)(TIM1_Pulse >> 8);
+ TIM1->CCR3L = (uint8_t)(TIM1_Pulse);
+}
+
+/**
+ * @brief Configures the Break feature, dead time, Lock level, the OSSI,
+ * and the AOE(automatic output enable).
+ * @param TIM1_OSSIState specifies the OSSIS State
+ * This parameter can be one of the following values:
+ * @arg TIM1_OSSIState_Enable: OSSIS State enabled
+ * @arg TIM1_OSSIState_Disable: OSSIS State disabled
+ * @param TIM1_LockLevel specifies the lock level
+ * This parameter can be one of the following values:
+ * @arg TIM1_LockLevel_Off: No lock level
+ * @arg TIM1_LockLevel_1: Lock level 1
+ * @arg TIM1_LockLevel_2: Lock level 2
+ * @arg TIM1_LockLevel_3: Lock level 3
+ * @param TIM1_DeadTime specifies the dead time value.
+ * @param TIM1_Break specifies the Break state
+ * This parameter can be one of the following values:
+ * @arg TIM1_BreakState_Enable: Break enabled
+ * @arg TIM1_BreakState_Disable: Break disabled
+ * @param TIM1_BreakPolarity specifies the Break polarity
+ * This parameter can be one of the following values:
+ * @arg TIM1_BreakPolarity_Low: Break polarity high
+ * @arg TIM1_BreakPolarity_High: Break polarity low
+ * @param TIM1_AutomaticOutput specifies the Automatic Output configuration
+ * This parameter can be one of the following values:
+ * @arg TIM1_AutomaticOutput_Enable: Automatic Output enabled
+ * @arg TIM1_AutomaticOutput_Disable: Automatic Output disabled
+ * @retval None
+ */
+void TIM1_BDTRConfig(TIM1_OSSIState_TypeDef TIM1_OSSIState,
+ TIM1_LockLevel_TypeDef TIM1_LockLevel,
+ uint8_t TIM1_DeadTime,
+ TIM1_BreakState_TypeDef TIM1_Break,
+ TIM1_BreakPolarity_TypeDef TIM1_BreakPolarity,
+ TIM1_AutomaticOutput_TypeDef TIM1_AutomaticOutput)
+{
+
+ /* Check the parameters */
+ assert_param(IS_TIM1_OSSI_STATE(TIM1_OSSIState));
+ assert_param(IS_TIM1_LOCK_LEVEL(TIM1_LockLevel));
+ assert_param(IS_TIM1_BREAK_STATE(TIM1_Break));
+ assert_param(IS_TIM1_BREAK_POLARITY(TIM1_BreakPolarity));
+ assert_param(IS_TIM1_AUTOMATIC_OUTPUT_STATE(TIM1_AutomaticOutput));
+
+ TIM1->DTR = (uint8_t)(TIM1_DeadTime);
+ /* Set the Lock level, the Break enable Bit and the Polarity, the OSSI State,
+ the dead time value and the Automatic Output Enable Bit */
+
+ TIM1->BKR = (uint8_t)((uint8_t)((uint8_t)TIM1_OSSIState | (uint8_t)TIM1_LockLevel)
+ | (uint8_t)((uint8_t)((uint8_t)TIM1_Break | (uint8_t)TIM1_BreakPolarity)
+ | (uint8_t)TIM1_AutomaticOutput));
+
+}
+
+/**
+ * @brief Enables or disables the TIM1 peripheral Main Outputs.
+ * @param NewState new state of the TIM1 peripheral.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_CtrlPWMOutputs(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the MOE Bit */
+
+ if (NewState != DISABLE)
+ {
+ TIM1->BKR |= TIM1_BKR_MOE;
+ }
+ else
+ {
+ TIM1->BKR &= (uint8_t)(~TIM1_BKR_MOE);
+ }
+}
+
+/**
+ * @brief Selects the TIM1 Output Compare Mode. This function disables the
+ * selected channel before changing the Output Compare Mode.
+ * @note User has to enable this channel using TIM1_CCxCmd and TIM1_CCxNCmd functions.
+ * @param TIM1_Channel specifies the TIM1 Channel.
+ * This parameter can be one of the following values:
+ * @arg TIM1_Channel_1: TIM1 Channel1
+ * @arg TIM1_Channel_2: TIM1 Channel2
+ * @arg TIM1_Channel_3: TIM1 Channel3
+ * @arg TIM1_Channel_4: TIM1 Channel4
+ * @param TIM1_OCMode specifies the TIM1 Output Compare Mode.
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCMode_Timing: OC Mode Timing
+ * @arg TIM1_OCMode_Active: OC Mode Active
+ * @arg TIM1_OCMode_Inactive: OC Mode Inactive
+ * @arg TIM1_OCMode_Toggle: OC Mode Toggle
+ * @arg TIM1_OCMode_PWM1: OC Mode PWM1
+ * @arg TIM1_OCMode_PWM2: OC Mode PWM2
+ * @retval None
+ */
+void TIM1_SelectOCxM(TIM1_Channel_TypeDef TIM1_Channel, TIM1_OCMode_TypeDef TIM1_OCMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_CHANNEL(TIM1_Channel));
+ assert_param(IS_TIM1_OCM(TIM1_OCMode));
+
+ if (TIM1_Channel == TIM1_Channel_1)
+ {
+ /* Disable the Channel 1: Reset the CCE Bit */
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC1E);
+
+ /* Reset the Output Compare Bits & Set the Output Compare Mode */
+ TIM1->CCMR1 = (uint8_t)((uint8_t)(TIM1->CCMR1 & (uint8_t)(~TIM1_CCMR_OCM)) | (uint8_t)TIM1_OCMode);
+ }
+ else if (TIM1_Channel == TIM1_Channel_2)
+ {
+ /* Disable the Channel 2: Reset the CCE Bit */
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC2E);
+
+ /* Reset the Output Compare Bits & Set the Output Compare Mode */
+ TIM1->CCMR2 = (uint8_t)((uint8_t)(TIM1->CCMR2 & (uint8_t)(~TIM1_CCMR_OCM)) | (uint8_t)TIM1_OCMode);
+ }
+ else
+ {
+ /* Disable the Channel 3: Reset the CCE Bit */
+ TIM1->CCER2 &= (uint8_t)(~TIM1_CCER2_CC3E);
+
+ /* Reset the Output Compare Bits & Set the Output Compare Mode */
+ TIM1->CCMR3 = (uint8_t)((uint8_t)(TIM1->CCMR3 & (uint8_t)(~TIM1_CCMR_OCM)) | (uint8_t)TIM1_OCMode);
+
+ }
+}
+
+/**
+ * @brief Sets the TIM1 Capture Compare1 Register value.
+ * @param Compare1 specifies the Capture Compare1 register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM1_SetCompare1(uint16_t Compare1)
+{
+ /* Set the Capture Compare1 Register value */
+ TIM1->CCR1H = (uint8_t)(Compare1 >> 8);
+ TIM1->CCR1L = (uint8_t)(Compare1);
+
+}
+
+/**
+ * @brief Sets the TIM1 Capture Compare2 Register value.
+ * @param Compare2 specifies the Capture Compare2 register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM1_SetCompare2(uint16_t Compare2)
+{
+ /* Set the Capture Compare2 Register value */
+ TIM1->CCR2H = (uint8_t)(Compare2 >> 8);
+ TIM1->CCR2L = (uint8_t)(Compare2);
+}
+
+/**
+ * @brief Sets the TIM1 Capture Compare3 Register value.
+ * @param Compare3 specifies the Capture Compare3 register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM1_SetCompare3(uint16_t Compare3)
+{
+ /* Set the Capture Compare3 Register value */
+ TIM1->CCR3H = (uint8_t)(Compare3 >> 8);
+ TIM1->CCR3L = (uint8_t)(Compare3);
+}
+
+/**
+ * @brief Sets the TIM1 Capture Compare4 Register value.
+ * @param Compare4 specifies the Capture Compare4 register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM1_SetCompare4(uint16_t Compare4)
+{
+ /* Set the Capture Compare4 Register value */
+ TIM1->CCR4H = (uint8_t)(Compare4 >> 8);
+ TIM1->CCR4L = (uint8_t)(Compare4);
+}
+
+/**
+ * @brief Sets or Resets the TIM1 peripheral Capture Compare Preload Control bit.
+ * @param NewState new state of the Capture Compare Preload Control bit.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_CCPreloadControl(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the CCPC Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CR2 |= TIM1_CR2_CCPC;
+ }
+ else
+ {
+ TIM1->CR2 &= (uint8_t)(~TIM1_CR2_CCPC);
+ }
+}
+
+/**
+ * @brief Forces the TIM1 Channel1 output waveform to active or inactive level.
+ * @param TIM1_ForcedAction specifies the forced Action to be set to the output waveform.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ForcedAction_Active: Force active level on OC1REF
+ * @arg TIM1_ForcedAction_Inactive: Force inactive level on OC1REF.
+ * @retval None
+ */
+void TIM1_ForcedOC1Config(TIM1_ForcedAction_TypeDef TIM1_ForcedAction)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_FORCED_ACTION(TIM1_ForcedAction));
+
+ /* Reset the OCM Bits & Configure the Forced output Mode */
+ TIM1->CCMR1 = (uint8_t)((uint8_t)(TIM1->CCMR1 & (uint8_t)(~TIM1_CCMR_OCM)) | (uint8_t)TIM1_ForcedAction);
+}
+
+/**
+ * @brief Forces the TIM1 Channel2 output waveform to active or inactive level.
+ * @param TIM1_ForcedAction specifies the forced Action to be set to the output waveform.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ForcedAction_Active: Force active level on OC2REF
+ * @arg TIM1_ForcedAction_Inactive: Force inactive level on OC2REF.
+ * @retval None
+ */
+void TIM1_ForcedOC2Config(TIM1_ForcedAction_TypeDef TIM1_ForcedAction)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_FORCED_ACTION(TIM1_ForcedAction));
+
+ /* Reset the OCM Bits & Configure the Forced output Mode */
+ TIM1->CCMR2 = (uint8_t)((uint8_t)(TIM1->CCMR2 & (uint8_t)(~TIM1_CCMR_OCM)) | (uint8_t)TIM1_ForcedAction);
+}
+
+/**
+ * @brief Forces the TIM1 Channel3 output waveform to active or inactive level.
+ * @param TIM1_ForcedAction specifies the forced Action to be set to the output waveform.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ForcedAction_Active: Force active level on OC3REF
+ * @arg TIM1_ForcedAction_Inactive: Force inactive level on OC3REF.
+ * @retval None
+ */
+void TIM1_ForcedOC3Config(TIM1_ForcedAction_TypeDef TIM1_ForcedAction)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_FORCED_ACTION(TIM1_ForcedAction));
+
+ /* Reset the OCM Bits */ /* Configure The Forced output Mode */
+ TIM1->CCMR3 = (uint8_t)((uint8_t)(TIM1->CCMR3 & (uint8_t)(~TIM1_CCMR_OCM)) | (uint8_t)TIM1_ForcedAction);
+}
+
+/**
+ * @brief Enables or disables the TIM1 peripheral Preload Register on CCR1.
+ * @param NewState new state of the Capture Compare Preload register.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_OC1PreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC1PE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCMR1 |= TIM1_CCMR_OCxPE;
+ }
+ else
+ {
+ TIM1->CCMR1 &= (uint8_t)(~TIM1_CCMR_OCxPE);
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM1 peripheral Preload Register on CCR2.
+ * @param NewState new state of the Capture Compare Preload register.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_OC2PreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC2PE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCMR2 |= TIM1_CCMR_OCxPE;
+ }
+ else
+ {
+ TIM1->CCMR2 &= (uint8_t)(~TIM1_CCMR_OCxPE);
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM1 peripheral Preload Register on CCR3.
+ * @param NewState new state of the Capture Compare Preload register.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_OC3PreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC3PE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCMR3 |= TIM1_CCMR_OCxPE;
+ }
+ else
+ {
+ TIM1->CCMR3 &= (uint8_t)(~TIM1_CCMR_OCxPE);
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM1 peripheral Preload Register on CCR4.
+ * @param NewState new state of the Capture Compare Preload register.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_OC4PreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC4PE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCMR4 |= TIM1_CCMR_OCxPE;
+ }
+ else
+ {
+ TIM1->CCMR4 &= (uint8_t)(~TIM1_CCMR_OCxPE);
+ }
+}
+
+/**
+ * @brief Configures the TIM1 Capture Compare 1 Fast feature.
+ * @param NewState new state of the Output Compare Fast Enable bit.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_OC1FastConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC1FE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCMR1 |= TIM1_CCMR_OCxFE;
+ }
+ else
+ {
+ TIM1->CCMR1 &= (uint8_t)(~TIM1_CCMR_OCxFE);
+ }
+}
+
+/**
+ * @brief Configures the TIM1 Capture Compare 2 Fast feature.
+ * @param NewState new state of the Output Compare Fast Enable bit.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_OC2FastConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC2FE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCMR2 |= TIM1_CCMR_OCxFE;
+ }
+ else
+ {
+ TIM1->CCMR2 &= (uint8_t)(~TIM1_CCMR_OCxFE);
+ }
+}
+
+/**
+ * @brief Configures the TIM1 Capture Compare 3 Fast feature.
+ * @param NewState new state of the Output Compare Fast Enable bit.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_OC3FastConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC3FE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCMR3 |= TIM1_CCMR_OCxFE;
+ }
+ else
+ {
+ TIM1->CCMR3 &= (uint8_t)(~TIM1_CCMR_OCxFE);
+ }
+}
+
+/**
+ * @brief Clears or safeguards the OC1REF signal.
+ * @param NewState new state of the Output Compare 1 Clear Enable bit.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_ClearOC1Ref(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC1CE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCMR1 |= TIM1_CCMR_OCxCE;
+ }
+ else
+ {
+ TIM1->CCMR1 &= (uint8_t)(~TIM1_CCMR_OCxCE);
+ }
+}
+
+/**
+ * @brief Clears or safeguards the OC2REF signal.
+ * @param NewState new state of the Output Compare 2 Clear Enable bit.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_ClearOC2Ref(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC2CE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCMR2 |= TIM1_CCMR_OCxCE;
+ }
+ else
+ {
+ TIM1->CCMR2 &= (uint8_t)(~TIM1_CCMR_OCxCE);
+ }
+}
+
+/**
+ * @brief Clears or safeguards the OC3REF signal.
+ * @param NewState new state of the Output Compare 3 Clear Enable bit.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_ClearOC3Ref(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC3CE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCMR3 |= TIM1_CCMR_OCxCE;
+ }
+ else
+ {
+ TIM1->CCMR3 &= (uint8_t)(~TIM1_CCMR_OCxCE);
+ }
+}
+
+/**
+ * @brief Clears or safeguards the OC4REF signal.
+ * @param NewState new state of the Output Compare 4 Clear Enable bit.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_ClearOC4Ref(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC4CE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCMR4 |= TIM1_CCMR_OCxCE;
+ }
+ else
+ {
+ TIM1->CCMR4 &= (uint8_t)(~TIM1_CCMR_OCxCE);
+ }
+}
+
+/**
+ * @brief Configures the TIM1 Channel 1 polarity.
+ * @param TIM1_OCPolarity specifies the OC1 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCPolarity_High: Output Compare active low
+ * @arg TIM1_OCPolarity_Low: Output Compare active high
+ * @retval None
+ */
+void TIM1_OC1PolarityConfig(TIM1_OCPolarity_TypeDef TIM1_OCPolarity)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_OC_POLARITY(TIM1_OCPolarity));
+
+ /* Set or Reset the CC1P Bit */
+ if (TIM1_OCPolarity != TIM1_OCPolarity_High)
+ {
+ TIM1->CCER1 |= TIM1_CCER1_CC1P;
+ }
+ else
+ {
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC1P);
+ }
+}
+
+/**
+ * @brief Configures the TIM1 Channel 1N polarity.
+ * @param TIM1_OCNPolarity specifies the OC1N Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCNPolarity_High: Complementary Output Compare active low
+ * @arg TIM1_OCNPolarity_Low: Complementary Output Compare active high
+ * @retval None
+ */
+void TIM1_OC1NPolarityConfig(TIM1_OCNPolarity_TypeDef TIM1_OCNPolarity)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_OCN_POLARITY(TIM1_OCNPolarity));
+
+ /* Set or Reset the CC3P Bit */
+ if (TIM1_OCNPolarity != TIM1_OCNPolarity_High)
+ {
+ TIM1->CCER1 |= TIM1_CCER1_CC1NP;
+ }
+ else
+ {
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC1NP);
+ }
+}
+
+/**
+ * @brief Configures the TIM1 Channel 2 polarity.
+ * @param TIM1_OCPolarity specifies the OC2 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCPolarity_High: Output Compare active low
+ * @arg TIM1_OCPolarity_Low: Output Compare active high
+ * @retval None
+ */
+void TIM1_OC2PolarityConfig(TIM1_OCPolarity_TypeDef TIM1_OCPolarity)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_OC_POLARITY(TIM1_OCPolarity));
+
+ /* Set or Reset the CC2P Bit */
+ if (TIM1_OCPolarity != TIM1_OCPolarity_High)
+ {
+ TIM1->CCER1 |= TIM1_CCER1_CC2P;
+ }
+ else
+ {
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC2P);
+ }
+}
+
+/**
+ * @brief Configures the TIM1 Channel 2N polarity.
+ * @param TIM1_OCNPolarity specifies the OC2N Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCNPolarity_High: Complementary Output Compare active low
+ * @arg TIM1_OCNPolarity_Low: Complementary Output Compare active high
+ * @retval None
+ */
+void TIM1_OC2NPolarityConfig(TIM1_OCNPolarity_TypeDef TIM1_OCNPolarity)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_OCN_POLARITY(TIM1_OCNPolarity));
+
+ /* Set or Reset the CC3P Bit */
+ if (TIM1_OCNPolarity != TIM1_OCNPolarity_High)
+ {
+ TIM1->CCER1 |= TIM1_CCER1_CC2NP;
+ }
+ else
+ {
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC2NP);
+ }
+}
+
+/**
+ * @brief Configures the TIM1 Channel 3 polarity.
+ * @param TIM1_OCPolarity specifies the OC3 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCPolarity_High: Output Compare active low
+ * @arg TIM1_OCPolarity_Low: Output Compare active high
+ * @retval None
+ */
+void TIM1_OC3PolarityConfig(TIM1_OCPolarity_TypeDef TIM1_OCPolarity)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_OC_POLARITY(TIM1_OCPolarity));
+
+ /* Set or Reset the CC3P Bit */
+ if (TIM1_OCPolarity != TIM1_OCPolarity_High)
+ {
+ TIM1->CCER2 |= TIM1_CCER2_CC3P;
+ }
+ else
+ {
+ TIM1->CCER2 &= (uint8_t)(~TIM1_CCER2_CC3P);
+ }
+}
+
+/**
+ * @brief Configures the TIM1 Channel 3N polarity.
+ * @param TIM1_OCNPolarity specifies the OC3N Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCNPolarity_High: Complementary Output Compare active low
+ * @arg TIM1_OCNPolarity_Low: Complementary Output Compare active high
+ * @retval None
+ */
+void TIM1_OC3NPolarityConfig(TIM1_OCNPolarity_TypeDef TIM1_OCNPolarity)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_OCN_POLARITY(TIM1_OCNPolarity));
+
+ /* Set or Reset the CC3P Bit */
+ if (TIM1_OCNPolarity != TIM1_OCNPolarity_High)
+ {
+ TIM1->CCER2 |= TIM1_CCER2_CC3NP;
+ }
+ else
+ {
+ TIM1->CCER2 &= (uint8_t)(~TIM1_CCER2_CC3NP);
+ }
+}
+
+/**
+ * @brief Selects the OCReference Clear source.
+ * @param TIM1_OCReferenceClear: specifies the OCReference Clear source.
+ * This parameter can be one of the following values:
+ * @arg TIM1_OCReferenceClear_ETRF: OCReference Clear source ETR
+ * @arg TIM1_OCReferenceClear_OCREFCLR: OCReference Clear source OCREF
+ * @retval None
+ */
+void TIM1_SelectOCREFClear(TIM1_OCReferenceClear_TypeDef TIM1_OCReferenceClear)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_OCREFERENCECECLEAR_SOURCE(TIM1_OCReferenceClear));
+
+ /* Set the TIM1_OCReferenceClear source */
+ TIM1->SMCR &= (uint8_t) (~TIM1_SMCR_OCCS);
+ TIM1->SMCR |= (uint8_t) TIM1_OCReferenceClear;
+}
+
+/**
+ * @brief Selects the TIM1 peripheral Commutation event.
+ * @param NewState new state of the Commutation event.
+ * This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_SelectCOM(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the CCUS Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CR2 |= TIM1_CR2_CCUS;
+ }
+ else
+ {
+ TIM1->CR2 &= (uint8_t)(~TIM1_CR2_CCUS);
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM1 Capture Compare Channel x (x=1,..,4).
+ * @param TIM1_Channel specifies the TIM1 Channel.
+ * This parameter can be one of the following values:
+ * @arg TIM1_Channel_1: TIM1 Channel1
+ * @arg TIM1_Channel_2: TIM1 Channel2
+ * @arg TIM1_Channel_3: TIM1 Channel3
+ * @arg TIM1_CHANNEL_4: TIM1 Channel4
+ * @param NewState specifies the TIM1 Channel CCxE bit new state.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_CCxCmd(TIM1_Channel_TypeDef TIM1_Channel, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_CHANNEL(TIM1_Channel));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (TIM1_Channel == TIM1_Channel_1)
+ {
+ /* Set or Reset the CC1E Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCER1 |= TIM1_CCER1_CC1E;
+ }
+ else
+ {
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC1E);
+ }
+ }
+ else if (TIM1_Channel == TIM1_Channel_2)
+ {
+ /* Set or Reset the CC2E Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCER1 |= TIM1_CCER1_CC2E;
+ }
+ else
+ {
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC2E);
+ }
+ }
+ else if (TIM1_Channel == TIM1_Channel_3)
+ {
+ /* Set or Reset the CC3E Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCER2 |= TIM1_CCER2_CC3E;
+ }
+ else
+ {
+ TIM1->CCER2 &= (uint8_t)(~TIM1_CCER2_CC3E);
+ }
+ }
+ else
+ {
+ /* Set or Reset the CC4E Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCER2 |= TIM1_CCER2_CC4E;
+ }
+ else
+ {
+ TIM1->CCER2 &= (uint8_t)(~TIM1_CCER2_CC4E);
+ }
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM1 Capture Compare Channel xN (xN=1,..,3).
+ * @param TIM1_Channel specifies the TIM1 Channel.
+ * This parameter can be one of the following values:
+ * @arg TIM1_Channel_1: TIM1 Channel1
+ * @arg TIM1_Channel_2: TIM1 Channel2
+ * @arg TIM1_Channel_3: TIM1 Channel3
+ * @param NewState specifies the TIM1 Channel CCxNE bit new state.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_CCxNCmd(TIM1_Channel_TypeDef TIM1_Channel, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_COMPLEMENTARY_CHANNEL(TIM1_Channel));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (TIM1_Channel == TIM1_Channel_1)
+ {
+ /* Set or Reset the CC1NE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCER1 |= TIM1_CCER1_CC1NE;
+ }
+ else
+ {
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC1NE);
+ }
+ }
+ else if (TIM1_Channel == TIM1_Channel_2)
+ {
+ /* Set or Reset the CC2NE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCER1 |= TIM1_CCER1_CC2NE;
+ }
+ else
+ {
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC2NE);
+ }
+ }
+ else
+ {
+ /* Set or Reset the CC3NE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CCER2 |= TIM1_CCER2_CC3NE;
+ }
+ else
+ {
+ TIM1->CCER2 &= (uint8_t)(~TIM1_CCER2_CC3NE);
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Group3 Input Capture management functions
+ * @brief Input Capture management functions
+ *
+@verbatim
+ ===============================================================================
+ Input Capture management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM1 Driver: how to use it in Input Capture Mode
+ ===================================================================
+ To use the Timer in Input Capture mode, the following steps are mandatory:
+
+ 1. Enable TIM1 clock using CLK_PeripheralClockConfig(CLK_Peripheral_TIM1, ENABLE) function.
+
+ 2. Configure the TIM1 pins in input mode by configuring the corresponding GPIO pins
+
+ 3. Configure the Time base unit as described in the first part of this driver, if needed,
+ otherwise the Timer will run with the default configuration:
+ - Autoreload value = 0xFFFF
+ - Prescaler value = 0x0000
+ - Counter mode = Up counting
+
+ 4. Call TIM1_ICInit() to configure the desired channel to measure only
+ frequency or duty cycle of the input signal using the corresponding configuration:
+ - TIM1 Channel: TIM1_Channel
+ - TIM1 Input Capture polarity: TIM1_ICPolarity
+ - TIM1 Input Capture selection: TIM1_ICSelection
+ - TIM1 Input Capture Prescaler: TIM1_ICPSC
+ - TIM1 Input Capture filter value
+ or,
+ Call TIM1_PWMIConfig() to configure the desired channels with the
+ corresponding configuration and to measure the frequency and the duty
+ cycle of the input signal.
+
+ 5. Enable global interrupts or the DMA to read the measured frequency.
+
+ 6. Enable the corresponding interrupt (or DMA request) to read the captured value,
+ using the function TIM1_ITConfig(TIM1_IT_CCx) (or TIM1_DMACmd(TIM1_DMASource_CCx))
+
+ 7. Call the TIM1_Cmd(ENABLE) function to enable the TIM1 counter.
+
+ 8. Use TIM1_GetCapturex() to read the captured value corresponding to
+ channel x.
+
+ Note1: All other functions can be used separately to modify, if needed,
+ a specific feature of the Timer.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the TIM1 peripheral according to the specified parameters.
+ * @param TIM1_Channel specifies the input capture channel
+ * This parameter can be one of the following values:
+ * @arg TIM1_Channel_1: TIM1 Channel1
+ * @arg TIM1_Channel_2: TIM1 Channel2
+ * @arg TIM1_Channel_3: TIM1 Channel3
+ * @arg TIM1_Channel_4: TIM1 Channel4
+ * @param TIM1_ICPolarity specifies the Input capture polarity
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPolarity_Rising: Input capture polarity rising
+ * @arg TIM1_ICPolarity_Falling: Input capture polarity falling
+ * @param TIM1_ICSelection specifies the Input capture source selection
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICSelection_DirectTI: TIM1 Input x is selected to be connected to ICx.
+ * @arg TIM1_ICSelection_IndirectTI: TIM1 Input x is selected to be connected to ICy.
+ * @arg TIM1_ICSelection_TRGI: TIM1 Input x is selected to be connected to the TRGI
+ * @param TIM1_ICPrescaler specifies the Input capture Prescaler
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM1_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM1_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM1_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @param TIM1_ICFilter specifies the Input capture filter value.
+ * @note If the channel 3 is selected the TIM1_ICSelection_IndirectTI parameter is forbidden.
+ * @note If the channel 4 is selected the TIM1_ICSelection_DirectTI parameter is forbidden.
+ * @retval None
+ */
+
+void TIM1_ICInit(TIM1_Channel_TypeDef TIM1_Channel,
+ TIM1_ICPolarity_TypeDef TIM1_ICPolarity,
+ TIM1_ICSelection_TypeDef TIM1_ICSelection,
+ TIM1_ICPSC_TypeDef TIM1_ICPrescaler,
+ uint8_t TIM1_ICFilter)
+{
+
+ /* Check the parameters */
+ assert_param(IS_TIM1_CHANNEL(TIM1_Channel));
+ assert_param(IS_TIM1_IC_POLARITY(TIM1_ICPolarity));
+ assert_param(IS_TIM1_IC_SELECTION(TIM1_ICSelection));
+ assert_param(IS_TIM1_IC_PRESCALER(TIM1_ICPrescaler));
+ assert_param(IS_TIM1_IC_FILTER(TIM1_ICFilter));
+
+ if (TIM1_Channel == TIM1_Channel_1)
+ {
+ /* TI1 Configuration */
+ TI1_Config(TIM1_ICPolarity, TIM1_ICSelection, TIM1_ICFilter);
+ /* Set the Input Capture Prescaler value */
+ TIM1_SetIC1Prescaler(TIM1_ICPrescaler);
+ }
+ else if (TIM1_Channel == TIM1_Channel_2)
+ {
+ /* TI2 Configuration */
+ TI2_Config(TIM1_ICPolarity, TIM1_ICSelection, TIM1_ICFilter);
+ /* Set the Input Capture Prescaler value */
+ TIM1_SetIC2Prescaler(TIM1_ICPrescaler);
+ }
+ else if (TIM1_Channel == TIM1_Channel_3)
+ {
+ /* TI3 Configuration */
+ TI3_Config(TIM1_ICPolarity, TIM1_ICSelection, TIM1_ICFilter);
+ /* Set the Input Capture Prescaler value */
+ TIM1_SetIC3Prescaler(TIM1_ICPrescaler);
+ }
+ else
+ {
+ /* TI4 Configuration */
+ TI4_Config(TIM1_ICPolarity, TIM1_ICSelection, TIM1_ICFilter);
+ /* Set the Input Capture Prescaler value */
+ TIM1_SetIC4Prescaler(TIM1_ICPrescaler);
+ }
+}
+
+/**
+ * @brief Configures the TIM1 peripheral in PWM Input Mode according to the
+ * specified parameters.
+ * @param TIM1_Channel specifies the input capture channel
+ * This parameter can be one of the following values:
+ * @arg TIM1_Channel_1: TIM1 Channel1
+ * @arg TIM1_Channel_2: TIM1 Channel2
+ * @param TIM1_ICPolarity specifies the Input capture polarity
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPolarity_Rising: Input capture polarity rising
+ * @arg TIM1_ICPolarity_Falling: Input capture polarity falling
+ * @param TIM1_ICSelection specifies the Input capture source selection
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICSelection_DirectTI: TIM1 Input x is selected to be connected to ICx.
+ * @arg TIM1_ICSelection_IndirectTI: TIM1 Input x is selected to be connected to ICy.
+ * @arg TIM1_ICSelection_TRGI: TIM1 Input x is selected to be connected to the TRGI
+ * @param TIM1_ICPrescaler specifies the Input capture Prescaler
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM1_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM1_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM1_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @param TIM1_ICFilter specifies the Input capture filter value.
+ * @retval None
+ */
+void TIM1_PWMIConfig(TIM1_Channel_TypeDef TIM1_Channel,
+ TIM1_ICPolarity_TypeDef TIM1_ICPolarity,
+ TIM1_ICSelection_TypeDef TIM1_ICSelection,
+ TIM1_ICPSC_TypeDef TIM1_ICPrescaler,
+ uint8_t TIM1_ICFilter)
+{
+ TIM1_ICPolarity_TypeDef icpolarity = TIM1_ICPolarity_Rising;
+ TIM1_ICSelection_TypeDef icselection = TIM1_ICSelection_DirectTI;
+
+ /* Check the parameters */
+ assert_param(IS_TIM1_PWMI_CHANNEL(TIM1_Channel));
+ assert_param(IS_TIM1_IC_POLARITY(TIM1_ICPolarity));
+ assert_param(IS_TIM1_IC_SELECTION(TIM1_ICSelection));
+ assert_param(IS_TIM1_IC_PRESCALER(TIM1_ICPrescaler));
+
+ /* Select the Opposite Input Polarity */
+ if (TIM1_ICPolarity != TIM1_ICPolarity_Falling)
+ {
+ icpolarity = TIM1_ICPolarity_Falling;
+ }
+ else
+ {
+ icpolarity = TIM1_ICPolarity_Rising;
+ }
+
+ /* Select the Opposite Input */
+ if (TIM1_ICSelection == TIM1_ICSelection_DirectTI)
+ {
+ icselection = TIM1_ICSelection_IndirectTI;
+ }
+ else
+ {
+ icselection = TIM1_ICSelection_DirectTI;
+ }
+
+ if (TIM1_Channel == TIM1_Channel_1)
+ {
+ /* TI1 Configuration */
+ TI1_Config(TIM1_ICPolarity, TIM1_ICSelection, TIM1_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM1_SetIC1Prescaler(TIM1_ICPrescaler);
+
+ /* TI2 Configuration */
+ TI2_Config(icpolarity, icselection, TIM1_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM1_SetIC2Prescaler(TIM1_ICPrescaler);
+ }
+ else
+ {
+ /* TI2 Configuration */
+ TI2_Config(TIM1_ICPolarity, TIM1_ICSelection, TIM1_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM1_SetIC2Prescaler(TIM1_ICPrescaler);
+
+ /* TI1 Configuration */
+ TI1_Config(icpolarity, icselection, TIM1_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM1_SetIC1Prescaler(TIM1_ICPrescaler);
+ }
+}
+
+/**
+ * @brief Gets the TIM1 Input Capture 1 value.
+ * @param None
+ * @retval Capture Compare 1 Register value.
+ */
+uint16_t TIM1_GetCapture1(void)
+{
+ /* Get the Capture 1 Register value */
+
+ uint16_t tmpccr1 = 0;
+ uint8_t tmpccr1l = 0, tmpccr1h = 0;
+
+ tmpccr1h = TIM1->CCR1H;
+ tmpccr1l = TIM1->CCR1L;
+
+ tmpccr1 = (uint16_t)(tmpccr1l);
+ tmpccr1 |= (uint16_t)((uint16_t)tmpccr1h << 8);
+ /* Get the Capture 1 Register value */
+ return (uint16_t)tmpccr1;
+}
+
+/**
+ * @brief Gets the TIM1 Input Capture 2 value.
+ * @param None
+ * @retval Capture Compare 2 Register value.
+ */
+uint16_t TIM1_GetCapture2(void)
+{
+ /* Get the Capture 2 Register value */
+
+ uint16_t tmpccr2 = 0;
+ uint8_t tmpccr2l = 0, tmpccr2h = 0;
+
+ tmpccr2h = TIM1->CCR2H;
+ tmpccr2l = TIM1->CCR2L;
+
+ tmpccr2 = (uint16_t)(tmpccr2l);
+ tmpccr2 |= (uint16_t)((uint16_t)tmpccr2h << 8);
+ /* Get the Capture 2 Register value */
+ return (uint16_t)tmpccr2;
+}
+
+/**
+ * @brief Gets the TIM1 Input Capture 3 value.
+ * @param None
+ * @retval Capture Compare 3 Register value.
+ */
+uint16_t TIM1_GetCapture3(void)
+{
+ /* Get the Capture 3 Register value */
+ uint16_t tmpccr3 = 0;
+ uint8_t tmpccr3l = 0, tmpccr3h = 0;
+
+ tmpccr3h = TIM1->CCR3H;
+ tmpccr3l = TIM1->CCR3L;
+
+ tmpccr3 = (uint16_t)(tmpccr3l);
+ tmpccr3 |= (uint16_t)((uint16_t)tmpccr3h << 8);
+ /* Get the Capture 3 Register value */
+ return (uint16_t)tmpccr3;
+}
+
+/**
+ * @brief Gets the TIM1 Input Capture 4 value.
+ * @param None
+ * @retval Capture Compare 4 Register value.
+ */
+uint16_t TIM1_GetCapture4(void)
+{
+ /* Get the Capture 4 Register value */
+ uint16_t tmpccr4 = 0;
+ uint8_t tmpccr4l = 0, tmpccr4h = 0;
+
+ tmpccr4h = TIM1->CCR4H;
+ tmpccr4l = TIM1->CCR4L;
+
+ tmpccr4 = (uint16_t)(tmpccr4l);
+ tmpccr4 |= (uint16_t)((uint16_t)tmpccr4h << 8);
+ /* Get the Capture 4 Register value */
+ return (uint16_t)tmpccr4;
+}
+
+/**
+ * @brief Sets the TIM1 Input Capture 1 prescaler.
+ * @param TIM1_IC1Prescaler specifies the Input Capture prescaler new value
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM1_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM1_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM1_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @retval None
+ */
+void TIM1_SetIC1Prescaler(TIM1_ICPSC_TypeDef TIM1_IC1Prescaler)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_IC_PRESCALER(TIM1_IC1Prescaler));
+
+ /* Reset the IC1PSC Bits */ /* Set the IC1PSC value */
+ TIM1->CCMR1 = (uint8_t)((uint8_t)(TIM1->CCMR1 & (uint8_t)(~TIM1_CCMR_ICxPSC)) | (uint8_t)TIM1_IC1Prescaler);
+}
+
+/**
+ * @brief Sets the TIM1 Input Capture 2 prescaler.
+ * @param TIM1_IC2Prescaler specifies the Input Capture prescaler new value
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM1_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM1_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM1_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @retval None
+ */
+void TIM1_SetIC2Prescaler(TIM1_ICPSC_TypeDef TIM1_IC2Prescaler)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_IC_PRESCALER(TIM1_IC2Prescaler));
+
+ /* Reset the IC1PSC Bits */ /* Set the IC1PSC value */
+ TIM1->CCMR2 = (uint8_t)((uint8_t)(TIM1->CCMR2 & (uint8_t)(~TIM1_CCMR_ICxPSC)) | (uint8_t)TIM1_IC2Prescaler);
+}
+
+/**
+ * @brief Sets the TIM1 Input Capture 3 prescaler.
+ * @param TIM1_IC3Prescaler specifies the Input Capture prescaler new value
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM1_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM1_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM1_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @retval None
+ */
+void TIM1_SetIC3Prescaler(TIM1_ICPSC_TypeDef TIM1_IC3Prescaler)
+{
+
+ /* Check the parameters */
+ assert_param(IS_TIM1_IC_PRESCALER(TIM1_IC3Prescaler));
+
+ /* Reset the IC1PSC Bits & Set the IC1PSC value */
+ TIM1->CCMR3 = (uint8_t)((uint8_t)(TIM1->CCMR3 & (uint8_t)(~TIM1_CCMR_ICxPSC)) | (uint8_t)TIM1_IC3Prescaler);
+}
+
+/**
+ * @brief Sets the TIM1 Input Capture 4 prescaler.
+ * @param TIM1_IC4Prescaler specifies the Input Capture prescaler new value
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM1_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM1_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM1_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @retval None
+ */
+void TIM1_SetIC4Prescaler(TIM1_ICPSC_TypeDef TIM1_IC4Prescaler)
+{
+
+ /* Check the parameters */
+ assert_param(IS_TIM1_IC_PRESCALER(TIM1_IC4Prescaler));
+
+ /* Reset the IC1PSC Bits & Set the IC1PSC value */
+ TIM1->CCMR4 = (uint8_t)((uint8_t)(TIM1->CCMR4 & (uint8_t)(~TIM1_CCMR_ICxPSC)) | (uint8_t)TIM1_IC4Prescaler);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Group4 Interrupts DMA and flags management functions
+ * @brief Interrupts, DMA and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts, DMA and flags management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the specified TIM1 interrupts.
+ * @param NewState new state of the TIM1 peripheral.
+ * This parameter can be: ENABLE or DISABLE.
+ * @param TIM1_IT specifies the TIM1 interrupts sources to be enabled or disabled.
+ * This parameter can be any combination of the following values:
+ * @arg TIM1_IT_Update: Update
+ * @arg TIM1_IT_CC1: Capture Compare Channel1
+ * @arg TIM1_IT_CC2: Capture Compare Channel2
+ * @arg TIM1_IT_CC3: Capture Compare Channel3
+ * @arg TIM1_IT_CC4: Capture Compare Channel4
+ * @arg TIM1_IT_COM: Commutation
+ * @arg TIM1_IT_Trigger: Trigger
+ * @arg TIM1_IT_Break: Break
+ * @param NewState new state of the TIM1 peripheral.
+ * @retval None
+ */
+void TIM1_ITConfig(TIM1_IT_TypeDef TIM1_IT, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_IT(TIM1_IT));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the Interrupt sources */
+ TIM1->IER |= (uint8_t)TIM1_IT;
+ }
+ else
+ {
+ /* Disable the Interrupt sources */
+ TIM1->IER &= (uint8_t)(~(uint8_t)TIM1_IT);
+ }
+}
+
+/**
+ * @brief Configures the TIM1 event to be generated by software.
+ * @param TIM1_EventSource specifies the event source.
+ * This parameter can be any combination of the following values:
+ * @arg TIM1_EventSource_Update: Update
+ * @arg TIM1_EventSource_CC1: Capture Compare Channel1
+ * @arg TIM1_EventSource_CC2: Capture Compare Channel2
+ * @arg TIM1_EventSource_CC3: Capture Compare Channel3
+ * @arg TIM1_EventSource_CC4: Capture Compare Channel4
+ * @arg TIM1_EventSource_COM: Commutation
+ * @arg TIM1_EventSource_Trigger: Trigger
+ * @arg TIM1_EventSource_Break: Break
+ * @retval None
+ */
+void TIM1_GenerateEvent(TIM1_EventSource_TypeDef TIM1_EventSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_EVENT_SOURCE(TIM1_EventSource));
+
+ /* Set the event sources */
+ TIM1->EGR = (uint8_t)TIM1_EventSource;
+}
+/**
+ * @brief Checks whether the specified TIM1 flag is set or not.
+ * @param TIM1_FLAG specifies the flag to check.
+ * This parameter can be one of the following values:
+ * @arg TIM1_FLAG_Update: TIM1 update Flag
+ * @arg TIM1_FLAG_CC1: TIM1 Capture Compare 1 Flag
+ * @arg TIM1_FLAG_CC2: TIM1 Capture Compare 2 Flag
+ * @arg TIM1_FLAG_CC3: TIM1 Capture Compare 3 Flag
+ * @arg TIM1_FLAG_CC4: TIM1 Capture Compare 4 Flag
+ * @arg TIM1_FLAG_COM: TIM1 Commutation Flag
+ * @arg TIM1_FLAG_Trigger: TIM1 Trigger Flag
+ * @arg TIM1_FLAG_Break: TIM1 Break Flag
+ * @arg TIM1_FLAG_CC1OF: TIM1 Capture Compare 1 overcapture Flag
+ * @arg TIM1_FLAG_CC2OF: TIM1 Capture Compare 2 overcapture Flag
+ * @arg TIM1_FLAG_CC3OF: TIM1 Capture Compare 3 overcapture Flag
+ * @arg TIM1_FLAG_CC4OF: TIM1 Capture Compare 4 overcapture Flag
+ * @retval FlagStatus The new state of TIM1_FLAG (SET or RESET).
+ */
+FlagStatus TIM1_GetFlagStatus(TIM1_FLAG_TypeDef TIM1_FLAG)
+{
+ FlagStatus bitstatus = RESET;
+ uint8_t tim1_flag_l = 0, tim1_flag_h = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM1_GET_FLAG(TIM1_FLAG));
+
+ tim1_flag_l = (uint8_t)(TIM1->SR1 & (uint8_t)TIM1_FLAG);
+ tim1_flag_h = (uint8_t)(TIM1->SR2 & (uint8_t)((uint16_t)TIM1_FLAG >> 8));
+
+ if ((uint8_t)((uint8_t)tim1_flag_l | (uint8_t)tim1_flag_h) != 0)
+ {
+ bitstatus = SET;
+ }
+ else
+ {
+ bitstatus = RESET;
+ }
+ return (FlagStatus)(bitstatus);
+}
+
+/**
+ * @brief Clears the TIM1’s pending flags.
+ * @param TIM1_FLAG specifies the flag to clear.
+ * This parameter can be one of the following values:
+ * @arg TIM1_FLAG_Update: TIM1 update Flag
+ * @arg TIM1_FLAG_CC1: TIM1 Capture Compare 1 Flag
+ * @arg TIM1_FLAG_CC2: TIM1 Capture Compare 2 Flag
+ * @arg TIM1_FLAG_CC3: TIM1 Capture Compare 3 Flag
+ * @arg TIM1_FLAG_CC4: TIM1 Capture Compare 4 Flag
+ * @arg TIM1_FLAG_COM: TIM1 Commutation Flag
+ * @arg TIM1_FLAG_Trigger: TIM1 Trigger Flag
+ * @arg TIM1_FLAG_Break: TIM1 Break Flag
+ * @arg TIM1_FLAG_CC1OF: TIM1 Capture Compare 1 overcapture Flag
+ * @arg TIM1_FLAG_CC2OF: TIM1 Capture Compare 2 overcapture Flag
+ * @arg TIM1_FLAG_CC3OF: TIM1 Capture Compare 3 overcapture Flag
+ * @arg TIM1_FLAG_CC4OF: TIM1 Capture Compare 4 overcapture Flag
+ * @retval None.
+ */
+void TIM1_ClearFlag(TIM1_FLAG_TypeDef TIM1_FLAG)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_CLEAR_FLAG(TIM1_FLAG));
+
+ /* Clear the flags (rc_w0) clear this bit by writing 0. Writing ‘1’ has no effect*/
+ TIM1->SR1 = (uint8_t)(~(uint8_t)(TIM1_FLAG));
+ TIM1->SR2 = (uint8_t)((uint8_t)(~((uint8_t)((uint16_t)TIM1_FLAG >> 8))) & (uint8_t)0x1E);
+}
+
+/**
+ * @brief Checks whether the TIM1 interrupt has occurred or not.
+ * @param TIM1_IT specifies the TIM1 interrupt source to check.
+ * This parameter can be any combination of the following values:
+ * @arg TIM1_IT_Update: Update
+ * @arg TIM1_IT_CC1: Capture Compare Channel1
+ * @arg TIM1_IT_CC2: Capture Compare Channel2
+ * @arg TIM1_IT_CC3: Capture Compare Channel3
+ * @arg TIM1_IT_CC4: Capture Compare Channel4
+ * @arg TIM1_IT_COM: Commutation
+ * @arg TIM1_IT_Trigger: Trigger
+ * @arg TIM1_IT_Break: Break
+ * @retval ITStatus The new state of the TIM1_IT(SET or RESET).
+ */
+
+ITStatus TIM1_GetITStatus(TIM1_IT_TypeDef TIM1_IT)
+{
+ ITStatus bitstatus = RESET;
+
+ uint8_t TIM1_itStatus = 0x0, TIM1_itEnable = 0x0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM1_GET_IT(TIM1_IT));
+
+ TIM1_itStatus = (uint8_t)(TIM1->SR1 & (uint8_t)TIM1_IT);
+
+ TIM1_itEnable = (uint8_t)(TIM1->IER & (uint8_t)TIM1_IT);
+
+ if ((TIM1_itStatus != (uint8_t)RESET ) && (TIM1_itEnable != (uint8_t)RESET ))
+ {
+ bitstatus = SET;
+ }
+ else
+ {
+ bitstatus = RESET;
+ }
+ return (ITStatus)(bitstatus);
+}
+
+/**
+ * @brief Clears the TIM1's interrupt pending bits.
+ * @param TIM1_IT specifies the pending bit to clear.
+ * This parameter can be any combination of the following values:
+ * @arg TIM1_IT_Update: Update
+ * @arg TIM1_IT_CC1: Capture Compare Channel1
+ * @arg TIM1_IT_CC2: Capture Compare Channel2
+ * @arg TIM1_IT_CC3: Capture Compare Channel3
+ * @arg TIM1_IT_CC4: Capture Compare Channel4
+ * @arg TIM1_IT_COM: Commutation
+ * @arg TIM1_IT_Trigger: Trigger
+ * @arg TIM1_IT_Break: Break
+ * @retval None.
+ */
+void TIM1_ClearITPendingBit(TIM1_IT_TypeDef TIM1_IT)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_IT(TIM1_IT));
+
+ /* Clear the IT pending Bit */
+ TIM1->SR1 = (uint8_t)(~(uint8_t)TIM1_IT);
+}
+
+/**
+ * @brief Configures the TIM1’s DMA interface.
+ * @param TIM1_DMABase: DMA Base address.
+ * @param TIM1_DMABurstLength: DMA Burst length.
+ * @retval None.
+ */
+void TIM1_DMAConfig(TIM1_DMABase_TypeDef TIM1_DMABase,
+ TIM1_DMABurstLength_TypeDef TIM1_DMABurstLength)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_DMABase(TIM1_DMABase));
+ assert_param(IS_TIM1_DMABurstLength(TIM1_DMABurstLength));
+
+ /* Set the DMA Base and the DMA Burst Length */
+ TIM1->DCR1 = (uint8_t)TIM1_DMABase;
+ TIM1->DCR2 = (uint8_t)TIM1_DMABurstLength;
+}
+
+/**
+ * @brief Enables or disables the TIM’s DMA Requests.
+ * @param TIM1_DMASources: specifies the DMA Request sources.
+ * This parameter can be any combination of the following values:
+ * @arg TIM1_DMA_Update: TIM1 update Interrupt source
+ * @arg DMA_Trigger: TIM1 Trigger DMA source
+ * @param NewState new state of the DMA Request sources.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None.
+ */
+void TIM1_DMACmd(TIM1_DMASource_TypeDef TIM1_DMASource, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ assert_param(IS_TIM1_DMA_SOURCE(TIM1_DMASource));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the DMA sources */
+ TIM1->DER |= (uint8_t)TIM1_DMASource;
+ }
+ else
+ {
+ /* Disable the DMA sources */
+ TIM1->DER &= (uint8_t)(~TIM1_DMASource);
+ }
+}
+
+/**
+ * @brief Selects the TIM1 peripheral Capture Compare DMA source.
+ * @param NewState: new state of the Capture Compare DMA source.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_SelectCCDMA(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Set the CCDS Bit */
+ TIM1->CR2 |= TIM1_CR2_CCDS;
+ }
+ else
+ {
+ /* Reset the CCDS Bit */
+ TIM1->CR2 &= (uint8_t)(~TIM1_CR2_CCDS);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Group5 Clocks management functions
+ * @brief Clocks management functions
+ *
+@verbatim
+ ===============================================================================
+ Clocks management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures the TIM1 internal Clock.
+ * @param None
+ * @retval None
+ */
+void TIM1_InternalClockConfig(void)
+{
+ /* Disable slave mode to clock the prescaler directly with the internal clock */
+ TIM1->SMCR &= (uint8_t)(~TIM1_SMCR_SMS);
+}
+
+/**
+ * @brief Configures the TIM1 Trigger as External Clock.
+ * @param TIM1_TIxExternalCLKSource specifies Trigger source.
+ * This parameter can be one of the following values:
+ * @arg TIM1_TIxExternalCLK1Source_TI1: TI1 Edge Detector
+ * @arg TIM1_TIxExternalCLK1Source_TI2: Filtered TIM1 Input 1
+ * @arg TIM1_TIxExternalCLK1Source_TI1ED: Filtered TIM1 Input 2
+ * @param TIM1_ICPolarity specifies the TIx Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPolarity_Rising: Input capture polarity rising
+ * @arg TIM1_ICPolarity_Falling: Input capture polarity falling
+ * @param ICFilter specifies the filter value.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM1_TIxExternalClockConfig(TIM1_TIxExternalCLK1Source_TypeDef TIM1_TIxExternalCLKSource,
+ TIM1_ICPolarity_TypeDef TIM1_ICPolarity,
+ uint8_t ICFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_TIXCLK_SOURCE(TIM1_TIxExternalCLKSource));
+ assert_param(IS_TIM1_IC_POLARITY(TIM1_ICPolarity));
+ assert_param(IS_TIM1_IC_FILTER(ICFilter));
+
+ /* Configure the TIM1 Input Clock Source */
+ if (TIM1_TIxExternalCLKSource == TIM1_TIxExternalCLK1Source_TI2)
+ {
+ TI2_Config(TIM1_ICPolarity, TIM1_ICSelection_DirectTI, ICFilter);
+ }
+ else
+ {
+ TI1_Config(TIM1_ICPolarity, TIM1_ICSelection_DirectTI, ICFilter);
+ }
+
+ /* Select the Trigger source */
+ TIM1_SelectInputTrigger((TIM1_TRGSelection_TypeDef)TIM1_TIxExternalCLKSource);
+
+ /* Select the External clock mode1 */
+ TIM1->SMCR |= (uint8_t)(TIM1_SlaveMode_External1);
+}
+
+/**
+ * @brief Configures the TIM1 External clock Mode1.
+ * @param TIM1_ExtTRGPrescaler specifies the external Trigger Prescaler.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ExtTRGPSC_OFF
+ * @arg TIM1_ExtTRGPSC_DIV2
+ * @arg TIM1_ExtTRGPSC_DIV4
+ * @arg TIM1_ExtTRGPSC_DIV8.
+ * @param TIM1_ExtTRGPolarity specifies the external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ExtTRGPolarity_Inverted
+ * @arg TIM1_ExtTRGPolarity_NonInverted
+ * @param ExtTRGFilter specifies the External Trigger Filter.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM1_ETRClockMode1Config(TIM1_ExtTRGPSC_TypeDef TIM1_ExtTRGPrescaler,
+ TIM1_ExtTRGPolarity_TypeDef TIM1_ExtTRGPolarity,
+ uint8_t ExtTRGFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_EXT_PRESCALER(TIM1_ExtTRGPrescaler));
+ assert_param(IS_TIM1_EXT_POLARITY(TIM1_ExtTRGPolarity));
+ assert_param(IS_TIM1_EXT_TRG_FILTER(ExtTRGFilter));
+
+ /* Configure the ETR Clock source */
+ TIM1_ETRConfig(TIM1_ExtTRGPrescaler, TIM1_ExtTRGPolarity, ExtTRGFilter);
+
+ /* Select the External clock mode1 & Select the Trigger selection : ETRF */
+ TIM1->SMCR = (uint8_t)((uint8_t)(TIM1->SMCR & (uint8_t)(~(TIM1_SMCR_SMS | TIM1_SMCR_TS)))
+ | (uint8_t)((uint8_t)TIM1_SlaveMode_External1 | (uint8_t) TIM1_TRGSelection_ETRF));
+}
+
+/**
+ * @brief Configures the TIM1 External clock Mode2.
+ * @param TIM1_ExtTRGPrescaler specifies the external Trigger Prescaler.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ExtTRGPSC_OFF
+ * @arg TIM1_ExtTRGPSC_DIV2
+ * @arg TIM1_ExtTRGPSC_DIV4
+ * @arg TIM1_ExtTRGPSC_DIV8.
+ * @param TIM1_ExtTRGPolarity specifies the external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ExtTRGPolarity_Inverted
+ * @arg TIM1_ExtTRGPolarity_NonInverted
+ * @param ExtTRGFilter specifies the External Trigger Filter.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM1_ETRClockMode2Config(TIM1_ExtTRGPSC_TypeDef TIM1_ExtTRGPrescaler,
+ TIM1_ExtTRGPolarity_TypeDef TIM1_ExtTRGPolarity,
+ uint8_t ExtTRGFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_EXT_PRESCALER(TIM1_ExtTRGPrescaler));
+ assert_param(IS_TIM1_EXT_POLARITY(TIM1_ExtTRGPolarity));
+
+ /* Configure the ETR Clock source */
+ TIM1_ETRConfig(TIM1_ExtTRGPrescaler, TIM1_ExtTRGPolarity, ExtTRGFilter);
+
+ /* Enable the External clock mode2 */
+ TIM1->ETR |= TIM1_ETR_ECE;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Group6 Synchronization management functions
+ * @brief Synchronization management functions
+ *
+@verbatim
+ ===============================================================================
+ Synchronization management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM1 Driver: how to use it in synchronization Mode
+ ===================================================================
+ Case of two/several Timers
+ **************************
+ 1. If TIM1 is used as master to other timers use the following functions:
+ - TIM1_SelectOutputTrigger()
+ - TIM1_SelectMasterSlaveMode()
+ 2. If TIM1 is used as slave to other timers use the following functions:
+ - TIM1_SelectInputTrigger()
+ - TIM1_SelectSlaveMode()
+
+ Case of Timers and external trigger (TRIG pin)
+ ********************************************
+ 1. Configure the External trigger using TIM1_ETRConfig()
+ 2. Configure the Slave Timer using the following functions:
+ - TIM1_SelectInputTrigger()
+ - TIM1_SelectSlaveMode()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Selects the TIM1 Input Trigger source.
+ * @param TIM1_InputTriggerSource specifies Input Trigger source.
+ * This parameter can be one of the following values:
+ * @arg TIM1_TRGSelection_TIM4
+ * @arg TIM1_TRGSelection_TIM3
+ * @arg TIM1_TRGSelection_TIM2
+ * @arg TIM1_TRGSelection_TI1F_ED: TI1 Edge Detector
+ * @arg TIM1_TRGSelection_TI1FP1: Filtered Timer Input 1
+ * @arg TIM1_TRGSelection_TI2FP2: Filtered Timer Input 2
+ * @arg TIM1_TRGSelection_ETRF: External Trigger input
+ * @retval None
+ */
+void TIM1_SelectInputTrigger(TIM1_TRGSelection_TypeDef TIM1_InputTriggerSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_TRIGGER_SELECTION(TIM1_InputTriggerSource));
+
+ /* Select the Tgigger Source */
+ TIM1->SMCR = (uint8_t)((uint8_t)(TIM1->SMCR & (uint8_t)(~TIM1_SMCR_TS)) | (uint8_t)TIM1_InputTriggerSource);
+}
+
+/**
+ * @brief Selects the TIM1 Trigger Output Mode.
+ * @param TIM1_TRGOSource specifies the Trigger Output source.
+ * This parameter can be one of the following values
+ * @arg TIM1_TRGOSource_Reset
+ * @arg TIM1_TRGOSource_Enable
+ * @arg TIM1_TRGOSource_Update
+ * @arg TIM1_TRGOSource_OC1
+ * @arg TIM1_TRGOSource_OC1REF
+ * @arg TIM1_TRGOSource_OC2REF
+ * @arg TIM1_TRGOSource_OC3REF
+ * @arg TIM1_TRGOSource_OC4REF
+ * @retval None
+ */
+void TIM1_SelectOutputTrigger(TIM1_TRGOSource_TypeDef TIM1_TRGOSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_TRGO_SOURCE(TIM1_TRGOSource));
+ /* Reset the MMS Bits & Select the TRGO source */
+ TIM1->CR2 = (uint8_t)((uint8_t)(TIM1->CR2 & (uint8_t)(~TIM1_CR2_MMS)) | (uint8_t) TIM1_TRGOSource);
+}
+
+/**
+ * @brief Selects the TIM1 Slave Mode.
+ * @param TIM1_SlaveMode specifies the TIM1 Slave Mode.
+ * This parameter can be one of the following values
+ * @arg TIM1_SlaveMode_Reset
+ * @arg TIM1_SlaveMode_Gated
+ * @arg TIM1_SlaveMode_Trigger
+ * @arg TIM1_SlaveMode_External1
+ * @retval None
+ */
+void TIM1_SelectSlaveMode(TIM1_SlaveMode_TypeDef TIM1_SlaveMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_SLAVE_MODE(TIM1_SlaveMode));
+
+ /* Reset the SMS Bits and Select the Slave Mode */
+ TIM1->SMCR = (uint8_t)((uint8_t)(TIM1->SMCR & (uint8_t)(~TIM1_SMCR_SMS)) | (uint8_t)TIM1_SlaveMode);
+
+}
+
+/**
+ * @brief Sets or Resets the TIM1 Master/Slave Mode.
+ * @param NewState new state of the synchronization between TIM1 and its slaves
+ * (through TRGO). This parameter can be ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM1_SelectMasterSlaveMode(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the MSM Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->SMCR |= TIM1_SMCR_MSM;
+ }
+ else
+ {
+ TIM1->SMCR &= (uint8_t)(~TIM1_SMCR_MSM);
+ }
+}
+
+/**
+ * @brief Configures the TIM1 External Trigger.
+ * @param TIM1_ExtTRGPrescaler specifies the external Trigger Prescaler.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ExtTRGPSC_OFF
+ * @arg TIM1_ExtTRGPSC_DIV2
+ * @arg TIM1_ExtTRGPSC_DIV4
+ * @arg TIM1_ExtTRGPSC_DIV8.
+ * @param TIM1_ExtTRGPolarity specifies the external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ExtTRGPolarity_Inverted
+ * @arg TIM1_ExtTRGPolarity_NonInverted
+ * @param ExtTRGFilter specifies the External Trigger Filter.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM1_ETRConfig(TIM1_ExtTRGPSC_TypeDef TIM1_ExtTRGPrescaler,
+ TIM1_ExtTRGPolarity_TypeDef TIM1_ExtTRGPolarity,
+ uint8_t ExtTRGFilter)
+{
+ assert_param(IS_TIM1_EXT_TRG_FILTER(ExtTRGFilter));
+
+ /* Set the Prescaler, the Filter value and the Polarity */
+ TIM1->ETR |= (uint8_t)((uint8_t)((uint8_t) TIM1_ExtTRGPrescaler
+ | (uint8_t) TIM1_ExtTRGPolarity)
+ | (uint8_t) ExtTRGFilter);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM1_Group7 Specific interface management functions
+ * @brief Specific interface management functions
+ *
+@verbatim
+ ===============================================================================
+ Specific interface management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures the TIM1 Encoder Interface.
+ * @param TIM1_EncoderMode specifies the TIM1 Encoder Mode.
+ * This parameter can be one of the following values
+ * @arg TIM1_EncoderMode_TI1: Counter counts on TI1FP1 edge
+ * depending on TI2FP2 level.
+ * @arg TIM1_EncoderMode_TI2: Counter counts on TI2FP2 edge
+ * depending on TI1FP1 level.
+ * @arg TIM1_EncoderMode_TI12: Counter counts on both TI1FP1 and
+ * TI2FP2 edges depending on the level of the other input.
+ * @param TIM1_IC1Polarity specifies the IC1 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPolarity_Rising: Input capture polarity rising
+ * @arg TIM1_ICPolarity_Falling: Input capture polarity falling
+ * @param TIM1_IC2Polarity specifies the IC2 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPolarity_Rising: Input capture polarity rising
+ * @arg TIM1_ICPolarity_Falling: Input capture polarity falling
+ * @retval None
+ */
+void TIM1_EncoderInterfaceConfig(TIM1_EncoderMode_TypeDef TIM1_EncoderMode,
+ TIM1_ICPolarity_TypeDef TIM1_IC1Polarity,
+ TIM1_ICPolarity_TypeDef TIM1_IC2Polarity)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM1_ENCODER_MODE(TIM1_EncoderMode));
+ assert_param(IS_TIM1_IC_POLARITY(TIM1_IC1Polarity));
+ assert_param(IS_TIM1_IC_POLARITY(TIM1_IC2Polarity));
+
+ /* Set the TI1 and the TI2 Polarities */
+ if (TIM1_IC1Polarity != TIM1_ICPolarity_Rising)
+ {
+ TIM1->CCER1 |= TIM1_CCER1_CC1P;
+ }
+ else
+ {
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC1P);
+ }
+
+ if (TIM1_IC2Polarity != TIM1_ICPolarity_Rising)
+ {
+ TIM1->CCER1 |= TIM1_CCER1_CC2P;
+ }
+ else
+ {
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC2P);
+ }
+ /* Set the encoder Mode */
+ TIM1->SMCR = (uint8_t)((uint8_t)(TIM1->SMCR & (uint8_t)(TIM1_SMCR_MSM | TIM1_SMCR_TS)) | (uint8_t) TIM1_EncoderMode);
+
+ /* Select the Capture Compare 1 and the Capture Compare 2 as input */
+ TIM1->CCMR1 = (uint8_t)((uint8_t)(TIM1->CCMR1 & (uint8_t)(~TIM1_CCMR_CCxS)) | (uint8_t) CCMR_TIxDirect_Set);
+ TIM1->CCMR2 = (uint8_t)((uint8_t)(TIM1->CCMR2 & (uint8_t)(~TIM1_CCMR_CCxS)) | (uint8_t) CCMR_TIxDirect_Set);
+
+}
+
+/**
+ * @brief Enables or Disables the TIM’s Hall sensor interface.
+ * @param NewState : The new state of the TIM1 Hall sensor interface.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM1_SelectHallSensor(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the TI1S Bit */
+ if (NewState != DISABLE)
+ {
+ TIM1->CR2 |= TIM1_CR2_TI1S;
+ }
+ else
+ {
+ TIM1->CR2 &= (uint8_t)(~TIM1_CR2_TI1S);
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Configure the TI1 as Input.
+ * @param TIM1_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPolarity_Rising: Input capture polarity rising
+ * @arg TIM1_ICPolarity_Falling: Input capture polarity falling
+ * @param TIM1_ICSelection specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICSelection_DirectTI: TIM1 Input 1 is selected to be connected to IC1.
+ * @arg TIM1_ICSelection_IndirectTI: TIM1 Input 1 is selected to be connected to IC2.
+ * @param TIM1_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TI1_Config(uint8_t TIM1_ICPolarity, uint8_t TIM1_ICSelection, uint8_t TIM1_ICFilter)
+{
+
+ /* Disable the Channel 1: Reset the CCE Bit */
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC1E);
+
+ /* Select the Input and set the filter */
+ TIM1->CCMR1 = (uint8_t)((uint8_t)(TIM1->CCMR1 & (uint8_t)(~( TIM1_CCMR_CCxS | TIM1_CCMR_ICxF)))
+ | (uint8_t)(( (TIM1_ICSelection)) | ((uint8_t)( TIM1_ICFilter << 4))));
+
+
+
+ /* Select the Polarity */
+ if (TIM1_ICPolarity != TIM1_ICPolarity_Rising)
+ {
+ TIM1->CCER1 |= TIM1_CCER1_CC1P;
+ }
+ else
+ {
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC1P);
+ }
+
+ /* Set the CCE Bit */
+ TIM1->CCER1 |= TIM1_CCER1_CC1E;
+}
+
+/**
+ * @brief Configure the TI2 as Input.
+ * @param TIM1_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPolarity_Rising: Input capture polarity rising
+ * @arg TIM1_ICPolarity_Falling: Input capture polarity falling
+ * @param TIM1_ICSelection specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICSelection_DirectTI: TIM1 Input 2 is selected to be connected to IC2.
+ * @arg TIM1_ICSelection_IndirectTI: TIM1 Input 2 is selected to be connected to IC1.
+ * @param TIM1_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TI2_Config(uint8_t TIM1_ICPolarity, uint8_t TIM1_ICSelection, uint8_t TIM1_ICFilter)
+{
+ /* Disable the Channel 2: Reset the CCE Bit */
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC2E);
+
+ /* Select the Input and set the filter */
+ TIM1->CCMR2 = (uint8_t)((uint8_t)(TIM1->CCMR2 & (uint8_t)(~( TIM1_CCMR_CCxS | TIM1_CCMR_ICxF)))
+ | (uint8_t)(( (TIM1_ICSelection)) | ((uint8_t)( TIM1_ICFilter << 4))));
+ /* Select the Polarity */
+ if (TIM1_ICPolarity != TIM1_ICPolarity_Rising)
+ {
+ TIM1->CCER1 |= TIM1_CCER1_CC2P;
+ }
+ else
+ {
+ TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC2P);
+ }
+ /* Set the CCE Bit */
+ TIM1->CCER1 |= TIM1_CCER1_CC2E;
+}
+
+/**
+ * @brief Configure the TI3 as Input.
+ * @param TIM1_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPolarity_Rising: Input capture polarity rising
+ * @arg TIM1_ICPolarity_Falling: Input capture polarity falling
+ * @param TIM1_ICSelection specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICSelection_DirectTI: TIM1 Input 3 is selected to
+ * be connected to IC3.
+ * @param TIM1_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TI3_Config(uint8_t TIM1_ICPolarity, uint8_t TIM1_ICSelection, uint8_t TIM1_ICFilter)
+{
+ /* Disable the Channel 3: Reset the CCE Bit */
+ TIM1->CCER2 &= (uint8_t)(~TIM1_CCER2_CC3E);
+
+ /* Select the Input and set the filter */
+ TIM1->CCMR3 = (uint8_t)((uint8_t)(TIM1->CCMR3 & (uint8_t)(~( TIM1_CCMR_CCxS | TIM1_CCMR_ICxF)))
+ | (uint8_t)(( (TIM1_ICSelection)) | ((uint8_t)( TIM1_ICFilter << 4))));
+
+ /* Select the Polarity */
+ if (TIM1_ICPolarity != TIM1_ICPolarity_Rising)
+ {
+ TIM1->CCER2 |= TIM1_CCER2_CC3P;
+ }
+ else
+ {
+ TIM1->CCER2 &= (uint8_t)(~TIM1_CCER2_CC3P);
+ }
+ /* Set the CCE Bit */
+ TIM1->CCER2 |= TIM1_CCER2_CC3E;
+}
+
+/**
+ * @brief Configure the TI4 as Input.
+ * @param TIM1_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICPolarity_Rising: Input capture polarity rising
+ * @arg TIM1_ICPolarity_Falling: Input capture polarity falling
+ * @param TIM1_ICSelection specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM1_ICSelection_IndirectTI: TIM1 Input 4 is selected to be connected to IC3.
+ * @param TIM1_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TI4_Config(uint8_t TIM1_ICPolarity, uint8_t TIM1_ICSelection, uint8_t TIM1_ICFilter)
+{
+
+ /* Disable the Channel 4: Reset the CCE Bit */
+ TIM1->CCER2 &= (uint8_t)(~TIM1_CCER2_CC4E);
+
+ /* Select the Input and set the filter */
+ TIM1->CCMR4 = (uint8_t)((uint8_t)(TIM1->CCMR4 & (uint8_t)(~( TIM1_CCMR_CCxS | TIM1_CCMR_ICxF)))
+ | (uint8_t)(( (TIM1_ICSelection)) | ((uint8_t)( TIM1_ICFilter << 4))));
+
+ /* Select the Polarity */
+ if (TIM1_ICPolarity != TIM1_ICPolarity_Rising)
+ {
+ TIM1->CCER2 |= TIM1_CCER2_CC4P;
+ }
+ else
+ {
+ TIM1->CCER2 &= (uint8_t)(~TIM1_CCER2_CC4P);
+ }
+
+ /* Set the CCE Bit */
+ TIM1->CCER2 |= TIM1_CCER2_CC4E;
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim2.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim2.c
new file mode 100644
index 00000000..504db78d
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim2.c
@@ -0,0 +1,2154 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_tim2.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the TIM2 peripheral:
+ * - TimeBase management
+ * - Output Compare management
+ * - Input Capture management
+ * - Interrupts, DMA and flags management
+ * - Clocks management
+ * - Synchronization management
+ * - Specific interface management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * This driver provides functions to configure and initialize the TIM2
+ * peripheral
+ * These functions are split in 7 groups:
+ *
+ * 1. TIM2 TimeBase management: this group includes all needed functions
+ * to configure the TIM Timebase unit:
+ * - Set/Get Prescaler
+ * - Set/Get Autoreload
+ * - Counter modes configuration
+ * - Select the One Pulse mode
+ * - Update Request Configuration
+ * - Update Disable Configuration
+ * - Auto-Preload Configuration
+ * - Enable/Disable the counter
+ *
+ * 2. TIM2 Output Compare management: this group includes all needed
+ * functions to configure the Capture/Compare unit used in Output
+ * compare mode:
+ * - Configure each channel, independently, in Output Compare mode
+ * - Select the output compare modes
+ * - Select the Polarities of each channel
+ * - Set/Get the Capture/Compare register values
+ * - Select the Output Compare Fast mode
+ * - Select the Output Compare Forced mode
+ * - Output Compare-Preload Configuration
+ * - Enable/Disable the Capture/Compare Channels
+ *
+ * 3. TIM2 Input Capture management: this group includes all needed
+ * functions to configure the Capture/Compare unit used in
+ * Input Capture mode:
+ * - Configure each channel in input capture mode
+ * - Configure Channel1/2 in PWM Input mode
+ * - Set the Input Capture Prescaler
+ * - Get the Capture/Compare values
+ *
+ * 4. TIM2 interrupts, DMA and flags management
+ * - Enable/Disable interrupt sources
+ * - Get flags status
+ * - Clear flags/ Pending bits
+ * - Enable/Disable DMA requests
+ * - Select CaptureCompare DMA request
+ *
+ * 5. TIM2 clocks management: this group includes all needed functions
+ * to configure the clock controller unit:
+ * - Select internal/External clock
+ * - Select the external clock mode: ETR(Mode1/Mode2) or TIx
+ *
+ * 6. TIM2 synchronization management: this group includes all needed
+ * functions to configure the Synchronization unit:
+ * - Select Input Trigger
+ * - Select Output Trigger
+ * - Select Master Slave Mode
+ * - ETR Configuration when used as external trigger
+ *
+ * 7. TIM2 specific interface management, this group includes all
+ * needed functions to use the specific TIM2 interface:
+ * - Encoder Interface Configuration
+ * - Select Hall Sensor
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_TIM2.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup TIM2
+ * @brief TIM2 driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void TI1_Config(TIM2_ICPolarity_TypeDef TIM2_ICPolarity,
+ TIM2_ICSelection_TypeDef TIM2_ICSelection,
+ uint8_t TIM2_ICFilter);
+static void TI2_Config(TIM2_ICPolarity_TypeDef TIM2_ICPolarity,
+ TIM2_ICSelection_TypeDef TIM2_ICSelection,
+ uint8_t TIM2_ICFilter);
+
+
+/** @defgroup TIM2_Private_Functions
+ * @{
+ */
+
+/** @defgroup TIM2_Group1 TimeBase management functions
+ * @brief TimeBase management functions
+ *
+@verbatim
+ ===============================================================================
+ TimeBase management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM2 Driver: how to use it in Timing(Time base) Mode
+ ===================================================================
+ To use the Timer in Timing(Time base) mode, the following steps are mandatory:
+
+ 1. Enable TIM2 clock using CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, ENABLE) function.
+
+ 2. Call TIM2_TimeBaseInit() to configure the Time Base unit with the
+ corresponding configuration.
+
+ 3. Enable global interrupts if you need to generate the update interrupt.
+
+ 4. Enable the corresponding interrupt using the function TIM2_ITConfig(TIM2_IT_Update)
+
+ 5. Call the TIM2_Cmd(ENABLE) function to enable the TIM2 counter.
+
+ Note1: All other functions can be used separately to modify, if needed,
+ a specific feature of the Timer.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitialize the TIM2 peripheral registers to their default reset values.
+ * @param None
+ * @retval None
+ */
+void TIM2_DeInit(void)
+{
+ TIM2->CR1 = TIM_CR1_RESET_VALUE;
+ TIM2->CR2 = TIM_CR2_RESET_VALUE;
+ TIM2->SMCR = TIM_SMCR_RESET_VALUE;
+ TIM2->ETR = TIM_ETR_RESET_VALUE;
+ TIM2->IER = TIM_IER_RESET_VALUE;
+ TIM2->SR2 = TIM_SR2_RESET_VALUE;
+
+ /* Disable channels */
+ TIM2->CCER1 = TIM_CCER1_RESET_VALUE;
+ /* Configure channels as inputs: it is necessary if lock level is equal to 2 or 3 */
+ TIM2->CCMR1 = 0x01;/*TIM2_ICxSource_TIxFPx */
+ TIM2->CCMR2 = 0x01;/*TIM2_ICxSource_TIxFPx */
+
+ /* Then reset channel registers: it also works if lock level is equal to 2 or 3 */
+ TIM2->CCER1 = TIM_CCER1_RESET_VALUE;
+ TIM2->CCMR1 = TIM_CCMR1_RESET_VALUE;
+ TIM2->CCMR2 = TIM_CCMR2_RESET_VALUE;
+
+ TIM2->CNTRH = TIM_CNTRH_RESET_VALUE;
+ TIM2->CNTRL = TIM_CNTRL_RESET_VALUE;
+
+ TIM2->PSCR = TIM_PSCR_RESET_VALUE;
+
+ TIM2->ARRH = TIM_ARRH_RESET_VALUE;
+ TIM2->ARRL = TIM_ARRL_RESET_VALUE;
+
+ TIM2->CCR1H = TIM_CCR1H_RESET_VALUE;
+ TIM2->CCR1L = TIM_CCR1L_RESET_VALUE;
+ TIM2->CCR2H = TIM_CCR2H_RESET_VALUE;
+ TIM2->CCR2L = TIM_CCR2L_RESET_VALUE;
+
+
+ TIM2->OISR = TIM_OISR_RESET_VALUE;
+ TIM2->EGR = 0x01;/* TIM_EGR_UG */
+ TIM2->BKR = TIM_BKR_RESET_VALUE;
+ TIM2->SR1 = TIM_SR1_RESET_VALUE;
+}
+
+/**
+ * @brief Initializes the TIM2 Time Base Unit according to the specified parameters.
+ * @param TIM2_Prescaler: Prescaler
+ * This parameter can be one of the following values:
+ * @arg TIM2_Prescaler_1: Time base Prescaler = 1 (No effect)
+ * @arg TIM2_Prescaler_2: Time base Prescaler = 2
+ * @arg TIM2_Prescaler_4: Time base Prescaler = 4
+ * @arg TIM2_Prescaler_8: Time base Prescaler = 8
+ * @arg TIM2_Prescaler_16: Time base Prescaler = 16
+ * @arg TIM2_Prescaler_32: Time base Prescaler = 32
+ * @arg TIM2_Prescaler_64: Time base Prescaler = 64
+ * @arg TIM2_Prescaler_128: Time base Prescaler = 128
+ * @param TIM2_CounterMode: Counter mode
+ * This parameter can be one of the following values:
+ * @arg TIM2_CounterMode_Up: Counter Up Mode
+ * @arg TIM2_CounterMode_Down: Counter Down Mode
+ * @arg TIM2_CounterMode_CenterAligned1: Counter Central aligned Mode 1
+ * @arg TIM2_CounterMode_CenterAligned2: Counter Central aligned Mode 2
+ * @arg TIM2_CounterMode_CenterAligned3: Counter Central aligned Mode 3
+ * @param TIM2_Period: This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+
+void TIM2_TimeBaseInit(TIM2_Prescaler_TypeDef TIM2_Prescaler,
+ TIM2_CounterMode_TypeDef TIM2_CounterMode,
+ uint16_t TIM2_Period)
+{
+
+ assert_param(IS_TIM2_PRESCALER(TIM2_Prescaler));
+ assert_param(IS_TIM2_COUNTER_MODE(TIM2_CounterMode));
+
+
+
+ /* Set the Autoreload value */
+ TIM2->ARRH = (uint8_t)(TIM2_Period >> 8) ;
+ TIM2->ARRL = (uint8_t)(TIM2_Period);
+
+ /* Set the Prescaler value */
+ TIM2->PSCR = (uint8_t)(TIM2_Prescaler);
+
+ /* Select the Counter Mode */
+ TIM2->CR1 &= (uint8_t)((uint8_t)(~TIM_CR1_CMS)) & ((uint8_t)(~TIM_CR1_DIR));
+ TIM2->CR1 |= (uint8_t)(TIM2_CounterMode);
+
+ /* Generate an update event to reload the Prescaler value immediately */
+ TIM2->EGR = TIM2_EventSource_Update;
+}
+
+/**
+ * @brief Configures the TIM2 Prescaler.
+ * @param Prescaler: Specifies the Prescaler Register value
+ * This parameter can be one of the following values:
+ * @arg TIM2_Prescaler_1: Time base Prescaler = 1 (No effect)
+ * @arg TIM2_Prescaler_2: Time base Prescaler = 2
+ * @arg TIM2_Prescaler_4: Time base Prescaler = 4
+ * @arg TIM2_Prescaler_8: Time base Prescaler = 8
+ * @arg TIM2_Prescaler_16: Time base Prescaler = 16
+ * @arg TIM2_Prescaler_32: Time base Prescaler = 32
+ * @arg TIM2_Prescaler_64: Time base Prescaler = 64
+ * @arg TIM2_Prescaler_128: Time base Prescaler = 128
+ * @param TIM2_PSCReloadMode: Specifies the TIM2 Prescaler Reload mode.
+ * This parameter can be one of the following values:
+ * @arg TIM2_PSCReloadMode_Update: Prescaler value is reloaded at every update
+ * @arg TIM2_PSCReloadMode_Immediate: Prescaler value is reloaded at every update
+ * @retval None
+ */
+void TIM2_PrescalerConfig(TIM2_Prescaler_TypeDef Prescaler,
+ TIM2_PSCReloadMode_TypeDef TIM2_PSCReloadMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_PRESCALER(Prescaler));
+ assert_param(IS_TIM2_PRESCALER_RELOAD(TIM2_PSCReloadMode));
+
+ /* Set the Prescaler value */
+ TIM2->PSCR = (uint8_t)(Prescaler);
+
+ /* Set or reset the UG Bit */
+ if (TIM2_PSCReloadMode == TIM2_PSCReloadMode_Immediate)
+ {
+ TIM2->EGR |= TIM_EGR_UG ;
+ }
+ else
+ {
+ TIM2->EGR &= (uint8_t)(~TIM_EGR_UG) ;
+ }
+}
+
+/**
+ * @brief Specifies the TIM2 Counter Mode to be used.
+ * @param TIM2_CounterMode: Specifies the Counter Mode to be used
+ * This parameter can be one of the following values:
+ * @arg TIM2_CounterMode_Up: Counter Up Mode
+ * @arg TIM2_CounterMode_Down: Counter Down Mode
+ * @arg TIM2_CounterMode_CenterAligned1: Counter Central aligned Mode 1
+ * @arg TIM2_CounterMode_CenterAligned2: Counter Central aligned Mode 2
+ * @arg TIM2_CounterMode_CenterAligned3: Counter Central aligned Mode 3
+ * @retval None
+ */
+void TIM2_CounterModeConfig(TIM2_CounterMode_TypeDef TIM2_CounterMode)
+{
+ uint8_t tmpcr1 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_COUNTER_MODE(TIM2_CounterMode));
+
+ tmpcr1 = TIM2->CR1;
+
+ /* Reset the CMS and DIR Bits */
+ tmpcr1 &= (uint8_t)((uint8_t)(~TIM_CR1_CMS) & (uint8_t)(~TIM_CR1_DIR));
+
+ /* Set the Counter Mode */
+ tmpcr1 |= (uint8_t)TIM2_CounterMode;
+
+ TIM2->CR1 = tmpcr1;
+}
+
+/**
+ * @brief Sets the TIM2 Counter Register value.
+ * @param Counter: Specifies the Counter register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM2_SetCounter(uint16_t Counter)
+{
+
+ /* Set the Counter Register value */
+ TIM2->CNTRH = (uint8_t)(Counter >> 8);
+ TIM2->CNTRL = (uint8_t)(Counter);
+}
+
+/**
+ * @brief Sets the TIM2 Autoreload Register value.
+ * @param Autoreload: Specifies the Autoreload register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM2_SetAutoreload(uint16_t Autoreload)
+{
+ /* Set the Autoreload Register value */
+ TIM2->ARRH = (uint8_t)(Autoreload >> 8);
+ TIM2->ARRL = (uint8_t)(Autoreload);
+}
+
+/**
+ * @brief Gets the TIM2 Counter value.
+ * @param None
+ * @retval Counter Register value.
+ */
+uint16_t TIM2_GetCounter(void)
+{
+ uint16_t tmpcnt = 0;
+ uint8_t tmpcntrl, tmpcntrh;
+
+ tmpcntrh = TIM2->CNTRH;
+ tmpcntrl = TIM2->CNTRL;
+
+ tmpcnt = (uint16_t)(tmpcntrl);
+ tmpcnt |= (uint16_t)((uint16_t)tmpcntrh << 8);
+ /* Get the Counter Register value */
+ return ((uint16_t)tmpcnt);
+}
+
+/**
+ * @brief Gets the TIM2 Prescaler value.
+ * @param None
+ * @retval TIM2 Prescaler, it can be one of the following values:
+ * - TIM2_Prescaler_1: Time base Prescaler = 1 (No effect)
+ * - TIM2_Prescaler_2: Time base Prescaler = 2
+ * - TIM2_Prescaler_4: Time base Prescaler = 4
+ * - TIM2_Prescaler_8: Time base Prescaler = 8
+ * - TIM2_Prescaler_16: Time base Prescaler = 16
+ * - TIM2_Prescaler_32: Time base Prescaler = 32
+ * - TIM2_Prescaler_64: Time base Prescaler = 64
+ * - TIM2_Prescaler_128: Time base Prescaler = 128
+ */
+TIM2_Prescaler_TypeDef TIM2_GetPrescaler(void)
+{
+ /* Get the Prescaler Register value */
+ return ((TIM2_Prescaler_TypeDef)TIM2->PSCR);
+}
+
+/**
+ * @brief Enables or Disables the TIM2 Update event.
+ * @param NewState: The new state of the TIM2 peripheral Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+
+void TIM2_UpdateDisableConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the UDIS Bit */
+ if (NewState != DISABLE)
+ {
+ TIM2->CR1 |= TIM_CR1_UDIS;
+ }
+ else
+ {
+ TIM2->CR1 &= (uint8_t)(~TIM_CR1_UDIS);
+ }
+}
+
+/**
+ * @brief Selects the TIM2 Update Request Interrupt source.
+ * @param TIM2_UpdateSource: Specifies the Update source.
+ * This parameter can be one of the following values:
+ * @arg TIM2_UpdateSource_Global: Global Update request source
+ * @arg TIM2_UpdateSource_Regular: Regular Update request source
+ * @retval None
+ */
+void TIM2_UpdateRequestConfig(TIM2_UpdateSource_TypeDef TIM2_UpdateSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_UPDATE_SOURCE(TIM2_UpdateSource));
+
+ /* Set or Reset the URS Bit */
+ if (TIM2_UpdateSource == TIM2_UpdateSource_Regular)
+ {
+ TIM2->CR1 |= TIM_CR1_URS ;
+ }
+ else
+ {
+ TIM2->CR1 &= (uint8_t)(~TIM_CR1_URS);
+ }
+}
+
+/**
+ * @brief Enables or disables TIM2 peripheral Preload register on ARR.
+ * @param NewState: The new state of the TIM2 peripheral Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM2_ARRPreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the ARPE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM2->CR1 |= TIM_CR1_ARPE;
+ }
+ else
+ {
+ TIM2->CR1 &= (uint8_t)(~TIM_CR1_ARPE);
+ }
+}
+
+/**
+ * @brief Selects the TIM’s One Pulse Mode.
+ * @param TIM2_OPMode: Specifies the OPM Mode to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM2_OPMode_Single: Single one Pulse mode (OPM Active)
+ * @arg TIM2_OPMode_Repetitive: Single one Pulse mode (OPM Active)
+ * @retval None
+ */
+void TIM2_SelectOnePulseMode(TIM2_OPMode_TypeDef TIM2_OPMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_OPM_MODE(TIM2_OPMode));
+
+ /* Set or Reset the OPM Bit */
+ if (TIM2_OPMode == TIM2_OPMode_Single)
+ {
+ TIM2->CR1 |= TIM_CR1_OPM ;
+ }
+ else
+ {
+ TIM2->CR1 &= (uint8_t)(~TIM_CR1_OPM);
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM2 peripheral.
+ * @param NewState: The new state of the TIM2 peripheral.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM2_Cmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* set or Reset the CEN Bit */
+ if (NewState != DISABLE)
+ {
+ TIM2->CR1 |= TIM_CR1_CEN;
+ }
+ else
+ {
+ TIM2->CR1 &= (uint8_t)(~TIM_CR1_CEN);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Group2 Output Compare management functions
+ * @brief Output Compare management functions
+ *
+@verbatim
+ ===============================================================================
+ Output Compare management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM2 Driver: how to use it in Output Compare Mode
+ ===================================================================
+ To use the Timer in Output Compare mode, the following steps are mandatory:
+
+ 1. Enable TIM2 clock using CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, ENABLE) function.
+
+ 2. Configure the TIM2 pins in output mode by configuring the corresponding GPIO pins
+
+ 3. Configure the Time base unit as described in the first part of this driver, if needed,
+ otherwise the Timer will run with the default configuration:
+ - Autoreload value = 0xFFFF
+ - Prescaler value = 0x0000
+ - Counter mode = Up counting
+
+ 4. Call TIM2_OCxInit() to configure the channel x with the desired parameters
+ including:
+ - TIM2 Output Compare mode: TIM2_OCMode
+ - TIM2 Output State: TIM2_OutputState
+ - TIM2 Pulse value: TIM2_Pulse
+ - TIM2 Output Compare Polarity: TIM2_OCPolarity
+ - TIM2 Output Idle State: TIM2_OCIdleState
+
+ 5. Call the TIM2_Cmd(ENABLE) function to enable the TIM2 counter.
+
+ Note1: All other functions can be used separately to modify, if needed,
+ a specific feature of the Timer.
+
+ Note2: If the corresponding interrupt or DMA request are needed, the user should:
+ 1. Enable global interrupts (or the DMA) to use the TIM2 interrupts (or DMA requests).
+ 2. Enable the corresponding interrupt (or DMA request) using the function
+ TIM2_ITConfig(TIM2_IT_CCx) (or TIM2_DMACmd(TIM2_DMASource_CCx))
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the TIM2 Channel1 according to the specified parameters.
+ * @param TIM2_OCMode: Output Compare Mode
+ * This parameter can be one of the following values:
+ * @arg TIM2_OCMode_Timing: Timing (Frozen) Mode
+ * @arg TIM2_OCMode_Active: Active Mode
+ * @arg TIM2_OCMode_Inactive: Inactive Mode
+ * @arg TIM2_OCMode_Toggle: Toggle Mode
+ * @arg TIM2_OCMode_PWM1: PWM Mode 1
+ * @arg TIM2_OCMode_PWM2: PWM Mode 2
+ * @param TIM2_OutputState: Output state
+ * This parameter can be one of the following values:
+ * @arg TIM2_OutputState_Disable: Output compare State disabled (channel output disabled)
+ * @arg TIM2_OutputState_Enable: Output compare State enabled (channel output enabled)
+ * @param TIM2_Pulse: This parameter must be a value between 0x0000 and 0xFFFF.
+ * @param TIM2_OCPolarity: Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM2_OCPolarity_High: Output compare polarity = High
+ * @arg TIM2_OCPolarity_Low: Output compare polarity = Low
+ * @param TIM2_OCIdleState: Output Compare Idle State
+ * This parameter can be one of the following values:
+ * @arg TIM2_OCIdleState_Reset: Output Compare Idle state = Reset
+ * @arg TIM2_OCIdleState_Set: Output Compare Idle state = Set
+ * @retval None
+ */
+void TIM2_OC1Init(TIM2_OCMode_TypeDef TIM2_OCMode,
+ TIM2_OutputState_TypeDef TIM2_OutputState,
+ uint16_t TIM2_Pulse,
+ TIM2_OCPolarity_TypeDef TIM2_OCPolarity,
+ TIM2_OCIdleState_TypeDef TIM2_OCIdleState)
+{
+ uint8_t tmpccmr1 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_OC_MODE(TIM2_OCMode));
+ assert_param(IS_TIM2_OUTPUT_STATE(TIM2_OutputState));
+ assert_param(IS_TIM2_OC_POLARITY(TIM2_OCPolarity));
+ assert_param(IS_TIM2_OCIDLE_STATE(TIM2_OCIdleState));
+
+ tmpccmr1 = TIM2->CCMR1;
+
+ /* Disable the Channel 1: Reset the CCE Bit */
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E);
+ /* Reset the Output Compare Bits */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Set the Output Compare Mode */
+ tmpccmr1 |= (uint8_t)TIM2_OCMode;
+
+ TIM2->CCMR1 = tmpccmr1;
+
+ /* Set the Output State */
+ if (TIM2_OutputState == TIM2_OutputState_Enable)
+ {
+ TIM2->CCER1 |= TIM_CCER1_CC1E;
+ }
+ else
+ {
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E);
+ }
+
+ /* Set the Output Polarity */
+ if (TIM2_OCPolarity == TIM2_OCPolarity_Low)
+ {
+ TIM2->CCER1 |= TIM_CCER1_CC1P;
+ }
+ else
+ {
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC1P);
+ }
+
+ /* Set the Output Idle state */
+ if (TIM2_OCIdleState == TIM2_OCIdleState_Set)
+ {
+ TIM2->OISR |= TIM_OISR_OIS1;
+ }
+ else
+ {
+ TIM2->OISR &= (uint8_t)(~TIM_OISR_OIS1);
+ }
+
+ /* Set the Pulse value */
+ TIM2->CCR1H = (uint8_t)(TIM2_Pulse >> 8);
+ TIM2->CCR1L = (uint8_t)(TIM2_Pulse);
+}
+
+/**
+ * @brief Initializes the TIM2 Channel2 according to the specified parameters.
+ * @param TIM2_OCMode: Output Compare Mode
+ * This parameter can be one of the following values:
+ * @arg TIM2_OCMode_Timing: Timing (Frozen) Mode
+ * @arg TIM2_OCMode_Active: Active Mode
+ * @arg TIM2_OCMode_Inactive: Inactive Mode
+ * @arg TIM2_OCMode_Toggle: Toggle Mode
+ * @arg TIM2_OCMode_PWM1: PWM Mode 1
+ * @arg TIM2_OCMode_PWM2: PWM Mode 2
+ * @param TIM2_OutputState: Output state
+ * This parameter can be one of the following values:
+ * @arg TIM2_OutputState_Disable: Output compare State disabled (channel output disabled)
+ * @arg TIM2_OutputState_Enable: Output compare State enabled (channel output enabled)
+ * @param TIM2_Pulse: This parameter must be a value between 0x0000 and 0xFFFF.
+ * @param TIM2_OCPolarity: Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM2_OCPolarity_High: Output compare polarity = High
+ * @arg TIM2_OCPolarity_Low: Output compare polarity = Low
+ * @param TIM2_OCIdleState: Output Compare Idle State
+ * This parameter can be one of the following values:
+ * @arg TIM2_OCIdleState_Reset: Output Compare Idle state = Reset
+ * @arg TIM2_OCIdleState_Set: Output Compare Idle state = Set
+ * @retval None
+ */
+void TIM2_OC2Init(TIM2_OCMode_TypeDef TIM2_OCMode,
+ TIM2_OutputState_TypeDef TIM2_OutputState,
+ uint16_t TIM2_Pulse,
+ TIM2_OCPolarity_TypeDef TIM2_OCPolarity,
+ TIM2_OCIdleState_TypeDef TIM2_OCIdleState)
+{
+ uint8_t tmpccmr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_OC_MODE(TIM2_OCMode));
+ assert_param(IS_TIM2_OUTPUT_STATE(TIM2_OutputState));
+ assert_param(IS_TIM2_OC_POLARITY(TIM2_OCPolarity));
+ assert_param(IS_TIM2_OCIDLE_STATE(TIM2_OCIdleState));
+
+ tmpccmr2 = TIM2->CCMR2;
+
+ /* Disable the Channel 2: Reset the CCE Bit */
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E);
+
+ /* Reset the Output Compare Bits */
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Set the Output Compare Mode */
+ tmpccmr2 |= (uint8_t)TIM2_OCMode;
+
+ TIM2->CCMR2 = tmpccmr2;
+
+ /* Set the Output State */
+ if (TIM2_OutputState == TIM2_OutputState_Enable)
+ {
+ TIM2->CCER1 |= TIM_CCER1_CC2E;
+ }
+ else
+ {
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E);
+ }
+
+ /* Set the Output Polarity */
+ if (TIM2_OCPolarity == TIM2_OCPolarity_Low)
+ {
+ TIM2->CCER1 |= TIM_CCER1_CC2P;
+ }
+ else
+ {
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC2P);
+ }
+
+
+ /* Set the Output Idle state */
+ if (TIM2_OCIdleState == TIM2_OCIdleState_Set)
+ {
+ TIM2->OISR |= TIM_OISR_OIS2;
+ }
+ else
+ {
+ TIM2->OISR &= (uint8_t)(~TIM_OISR_OIS2);
+ }
+
+ /* Set the Pulse value */
+ TIM2->CCR2H = (uint8_t)(TIM2_Pulse >> 8);
+ TIM2->CCR2L = (uint8_t)(TIM2_Pulse);
+}
+
+/**
+ * @brief Configures the Break feature, dead time, Lock level, the OSSI,
+ * and the AOE(automatic output enable).
+ * @param TIM2_OSSIState: Off-State Selection for Idle mode states.
+ * This parameter can be one of the following values:
+ * @arg TIM2_OSSIState_Enable: Off-State Selection for Idle mode enabled
+ * @arg TIM2_OSSIState_Disable: Off-State Selection for Idle mode disabled
+ * @param TIM2_LockLevel: Lock level.
+ * This parameter can be one of the following values:
+ * @arg TIM2_LockLevel_Off: Lock option disabled
+ * @arg TIM2_LockLevel_1: Select Lock Level 1
+ * @arg TIM2_LockLevel_2: Select Lock Level 2
+ * @arg TIM2_LockLevel_3: Select Lock Level 3
+ * @param TIM2_BreakState: Break Input enable/disable .
+ * This parameter can be one of the following values:
+ * @arg TIM2_BreakState_Disable: Break State disabled (break option disabled)
+ * @arg TIM2_BreakState_Enable: Break State enabled (break option enabled)
+ * @param TIM2_BreakPolarity: Break Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM2_BreakPolarity_High: if Break, channel polarity = High
+ * @arg TIM2_BreakPolarity_Low: if Break, channel polarity = Low
+ * @param TIM2_AutomaticOutput: TIM2 AOE Bit Set/Reset .
+ * This parameter can be one of the following values:
+ * @arg TIM2_AutomaticOutput_Enable: Automatic Output option enabled
+ * @arg TIM2_AutomaticOutput_Disable: Automatic Output option disabled
+ * @retval None
+ */
+void TIM2_BKRConfig(TIM2_OSSIState_TypeDef TIM2_OSSIState,
+ TIM2_LockLevel_TypeDef TIM2_LockLevel,
+ TIM2_BreakState_TypeDef TIM2_BreakState,
+ TIM2_BreakPolarity_TypeDef TIM2_BreakPolarity,
+ TIM2_AutomaticOutput_TypeDef TIM2_AutomaticOutput)
+
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_OSSI_STATE(TIM2_OSSIState));
+ assert_param(IS_TIM2_LOCK_LEVEL(TIM2_LockLevel));
+ assert_param(IS_TIM2_BREAK_STATE(TIM2_BreakState));
+ assert_param(IS_TIM2_BREAK_POLARITY(TIM2_BreakPolarity));
+ assert_param(IS_TIM2_AUTOMATIC_OUTPUT_STATE(TIM2_AutomaticOutput));
+
+
+
+ /* Set the Lock level, the Break enable Bit and the Polarity, the OSSI State,
+ the dead time value and the Automatic Output Enable Bit */
+ TIM2->BKR = (uint8_t)((uint8_t)((uint8_t)((uint8_t)((uint8_t)TIM2_OSSIState | (uint8_t)TIM2_LockLevel) | \
+ (uint8_t)((uint8_t)TIM2_BreakState | (uint8_t)TIM2_BreakPolarity)) | \
+ TIM2_AutomaticOutput));
+}
+
+/**
+ * @brief Enables or disables the TIM2 peripheral Main Outputs.
+ * @param NewState: The new state of the TIM2 peripheral.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM2_CtrlPWMOutputs(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the MOE Bit */
+
+ if (NewState != DISABLE)
+ {
+ TIM2->BKR |= TIM_BKR_MOE ;
+ }
+ else
+ {
+ TIM2->BKR &= (uint8_t)(~TIM_BKR_MOE) ;
+ }
+}
+
+/**
+ * @brief Selects the TIM2 Output Compare Mode. This function disables the
+ * selected channel before changing the Output Compare Mode. User has to
+ * enable this channel using TIM2_CCxCmd and TIM2_CCxNCmd functions.
+ * @param TIM2_Channel: Specifies the TIM2 Channel.
+ * This parameter can be one of the following values:
+ * @arg TIM2_Channel_1: Channel 1
+ * @arg TIM2_Channel_2: Channel 2
+ * @param TIM2_OCMode: Specifies the TIM2 Output Compare Mode.
+ * This parameter can be one of the following values:
+ * @arg TIM2_OCMode_Timing: Timing (Frozen) Mode
+ * @arg TIM2_OCMode_Active: Active Mode
+ * @arg TIM2_OCMode_Inactive: Inactive Mode
+ * @arg TIM2_OCMode_Toggle: Toggle Mode
+ * @arg TIM2_OCMode_PWM1: PWM Mode 1
+ * @arg TIM2_OCMode_PWM2: PWM Mode 2
+ * @retval None
+ */
+void TIM2_SelectOCxM(TIM2_Channel_TypeDef TIM2_Channel,
+ TIM2_OCMode_TypeDef TIM2_OCMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_CHANNEL(TIM2_Channel));
+ assert_param(IS_TIM2_OCM(TIM2_OCMode));
+
+ if (TIM2_Channel == TIM2_Channel_1)
+ {
+ /* Disable the Channel 1: Reset the CCE Bit */
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E);
+
+ /* Reset the Output Compare Bits */
+ TIM2->CCMR1 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Set the Output Compare Mode */
+ TIM2->CCMR1 |= (uint8_t)TIM2_OCMode;
+ }
+ else /* if (TIM2_Channel == TIM2_Channel_2) */
+ {
+ /* Disable the Channel 2: Reset the CCE Bit */
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E);
+
+ /* Reset the Output Compare Bits */
+ TIM2->CCMR2 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Set the Output Compare Mode */
+ TIM2->CCMR2 |= (uint8_t)TIM2_OCMode;
+ }
+}
+
+/**
+ * @brief Sets the TIM2 Capture Compare1 Register value.
+ * @param Compare: Specifies the Capture Compare1 register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM2_SetCompare1(uint16_t Compare)
+{
+ /* Set the Capture Compare1 Register value */
+ TIM2->CCR1H = (uint8_t)(Compare >> 8);
+ TIM2->CCR1L = (uint8_t)(Compare);
+}
+
+/**
+ * @brief Sets the TIM2 Capture Compare2 Register value.
+ * @param Compare: Specifies the Capture Compare2 register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM2_SetCompare2(uint16_t Compare)
+{
+ /* Set the Capture Compare2 Register value */
+ TIM2->CCR2H = (uint8_t)(Compare >> 8);
+ TIM2->CCR2L = (uint8_t)(Compare);
+}
+
+/**
+ * @brief Forces the TIM2 Channel1 output waveform to active or inactive level.
+ * @param TIM2_ForcedAction: Specifies the forced Action to be set to the output waveform.
+ * This parameter can be one of the following values:
+ * @arg TIM2_ForcedAction_Active: Output Reference is forced low
+ * @arg TIM2_ForcedAction_Inactive: Output Reference is forced high
+ * @retval None
+ */
+void TIM2_ForcedOC1Config(TIM2_ForcedAction_TypeDef TIM2_ForcedAction)
+{
+ uint8_t tmpccmr1 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_FORCED_ACTION(TIM2_ForcedAction));
+
+ tmpccmr1 = TIM2->CCMR1;
+
+ /* Reset the OCM Bits */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Configure The Forced output Mode */
+ tmpccmr1 |= (uint8_t)TIM2_ForcedAction;
+
+ TIM2->CCMR1 = tmpccmr1;
+}
+
+/**
+ * @brief Forces the TIM2 Channel2 output waveform to active or inactive level.
+ * @param TIM2_ForcedAction: Specifies the forced Action to be set to the output waveform.
+ * This parameter can be one of the following values:
+ * @arg TIM2_ForcedAction_Active: Output Reference is forced low
+ * @arg TIM2_ForcedAction_Inactive: Output Reference is forced high
+ * @retval None
+ */
+void TIM2_ForcedOC2Config(TIM2_ForcedAction_TypeDef TIM2_ForcedAction)
+{
+ uint8_t tmpccmr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_FORCED_ACTION(TIM2_ForcedAction));
+
+ tmpccmr2 = TIM2->CCMR2;
+
+ /* Reset the OCM Bits */
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Configure The Forced output Mode */
+ tmpccmr2 |= (uint8_t)TIM2_ForcedAction;
+
+ TIM2->CCMR2 = tmpccmr2;
+}
+
+/**
+ * @brief Enables or disables the TIM2 peripheral Preload Register on CCR1.
+ * @param NewState: The new state of the Capture Compare Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM2_OC1PreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC1PE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM2->CCMR1 |= TIM_CCMR_OCxPE ;
+ }
+ else
+ {
+ TIM2->CCMR1 &= (uint8_t)(~TIM_CCMR_OCxPE) ;
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM2 peripheral Preload Register on CCR2.
+ * @param NewState: The new state of the Capture Compare Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM2_OC2PreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC2PE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM2->CCMR2 |= TIM_CCMR_OCxPE ;
+ }
+ else
+ {
+ TIM2->CCMR2 &= (uint8_t)(~TIM_CCMR_OCxPE) ;
+ }
+}
+
+/**
+ * @brief Configures the TIM2 Capture Compare 1 Fast feature.
+ * @param NewState: The new state of the Output Compare Fast Enable bit.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM2_OC1FastConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC1FE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM2->CCMR1 |= TIM_CCMR_OCxFE ;
+ }
+ else
+ {
+ TIM2->CCMR1 &= (uint8_t)(~TIM_CCMR_OCxFE) ;
+ }
+}
+
+/**
+ * @brief Configures the TIM2 Capture Compare 2 Fast feature.
+ * @param NewState: The new state of the Output Compare Fast Enable bit.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+
+void TIM2_OC2FastConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC2FE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM2->CCMR2 |= TIM_CCMR_OCxFE ;
+ }
+ else
+ {
+ TIM2->CCMR2 &= (uint8_t)(~TIM_CCMR_OCxFE) ;
+ }
+}
+
+/**
+ * @brief Configures the TIM2 Channel 1 polarity.
+ * @param TIM2_OCPolarity: Specifies the OC1 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM2_OCPolarity_High: Output compare polarity = High
+ * @arg TIM2_OCPolarity_Low: Output compare polarity = Low
+ * @retval None
+ */
+void TIM2_OC1PolarityConfig(TIM2_OCPolarity_TypeDef TIM2_OCPolarity)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_OC_POLARITY(TIM2_OCPolarity));
+
+ /* Set or Reset the CC1P Bit */
+ if (TIM2_OCPolarity == TIM2_OCPolarity_Low)
+ {
+ TIM2->CCER1 |= TIM_CCER1_CC1P ;
+ }
+ else
+ {
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC1P) ;
+ }
+}
+
+/**
+ * @brief Configures the TIM2 Channel 2 polarity.
+ * @param TIM2_OCPolarity: Specifies the OC2 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM2_OCPolarity_High: Output compare polarity = High
+ * @arg TIM2_OCPolarity_Low: Output compare polarity = Low
+ * @retval None
+ */
+void TIM2_OC2PolarityConfig(TIM2_OCPolarity_TypeDef TIM2_OCPolarity)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_OC_POLARITY(TIM2_OCPolarity));
+
+ /* Set or Reset the CC2P Bit */
+ if (TIM2_OCPolarity == TIM2_OCPolarity_Low)
+ {
+ TIM2->CCER1 |= TIM_CCER1_CC2P ;
+ }
+ else
+ {
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC2P) ;
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM2 Capture Compare Channel x.
+ * @param TIM2_Channel: Specifies the TIM2 Channel.
+ * This parameter can be one of the following values:
+ * @arg TIM2_Channel_1: Channel 1
+ * @arg TIM2_Channel_2: Channel 2
+ * @param NewState: Specifies the TIM2 Channel CCxE bit new state.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM2_CCxCmd(TIM2_Channel_TypeDef TIM2_Channel,
+ FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_CHANNEL(TIM2_Channel));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (TIM2_Channel == TIM2_Channel_1)
+ {
+ /* Set or Reset the CC1E Bit */
+ if (NewState != DISABLE)
+ {
+ TIM2->CCER1 |= TIM_CCER1_CC1E ;
+ }
+ else
+ {
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E) ;
+ }
+
+ }
+ else /* if (TIM2_Channel == TIM2_Channel_2) */
+ {
+ /* Set or Reset the CC2E Bit */
+ if (NewState != DISABLE)
+ {
+ TIM2->CCER1 |= TIM_CCER1_CC2E;
+ }
+ else
+ {
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E) ;
+ }
+ }
+}
+
+/** @defgroup TIM2_Group3 Input Capture management functions
+ * @brief Input Capture management functions
+ *
+@verbatim
+ ===============================================================================
+ Input Capture management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM2 Driver: how to use it in Input Capture Mode
+ ===================================================================
+ To use the Timer in Input Capture mode, the following steps are mandatory:
+
+ 1. Enable TIM2 clock using CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, ENABLE) function.
+
+ 2. Configure the TIM2 pins in input mode by configuring the corresponding GPIO pins
+
+ 3. Configure the Time base unit as described in the first part of this driver, if needed,
+ otherwise the Timer will run with the default configuration:
+ - Autoreload value = 0xFFFF
+ - Prescaler value = 0x0
+ - Counter mode = Up counting
+
+ 4. Call TIM2_ICInit() to configure the desired channel to measure only
+ frequency or duty cycle of the input signal using the corresponding configuration:
+ - TIM2 Channel: TIM2_Channel
+ - TIM2 Input Capture polarity: TIM2_ICPolarity
+ - TIM2 Input Capture selection: TIM2_ICSelection
+ - TIM2 Input Capture Prescaler: TIM2_ICPSC
+ - TIM2 Input Capture filter value
+ or,
+ Call TIM2_PWMIConfig() to configure the desired channels with the
+ corresponding configuration and to measure the frequency and the duty
+ cycle of the input signal.
+
+ 5. Enable global interrupts or the DMA to read the measured frequency.
+
+ 6. Enable the corresponding interrupt (or DMA request) to read the captured value,
+ using the function TIM2_ITConfig(TIM2_IT_CCx) (or TIM2_DMACmd(TIM2_DMASource_CCx))
+
+ 7. Call the TIM2_Cmd(ENABLE) function to enable the TIM2 counter.
+
+ 8. Use TIM2_GetCapturex() to read the captured value corresponding to
+ channel x.
+
+ Note1: All other functions can be used separately to modify, if needed,
+ a specific feature of the Timer.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the TIM2 peripheral according to the specified parameters.
+ * @param TIM2_Channel: TIM2 Channel
+ * This parameter can be one of the following values:
+ * @arg TIM2_Channel_1: Channel 1
+ * @arg TIM2_Channel_2: Channel 2
+ * @param TIM2_ICPolarity: Input Capture Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM2_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM2_ICSelection: Input Capture Selection
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICSelection_DirectTI: Input Capture mapped on the direct input
+ * @arg TIM2_ICSelection_IndirectTI: Input Capture mapped on the indirect input
+ * @arg TIM2_ICSelection_TRGI: Input Capture mapped on the Trigger Input
+ * @param TIM2_ICPrescaler: Input Capture Prescaler
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM2_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM2_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM2_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @param TIM2_ICFilter: This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+void TIM2_ICInit(TIM2_Channel_TypeDef TIM2_Channel,
+ TIM2_ICPolarity_TypeDef TIM2_ICPolarity,
+ TIM2_ICSelection_TypeDef TIM2_ICSelection,
+ TIM2_ICPSC_TypeDef TIM2_ICPrescaler,
+ uint8_t TIM2_ICFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_CHANNEL(TIM2_Channel));
+
+ if (TIM2_Channel == TIM2_Channel_1)
+ {
+ /* TI1 Configuration */
+ TI1_Config(TIM2_ICPolarity, TIM2_ICSelection, TIM2_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM2_SetIC1Prescaler(TIM2_ICPrescaler);
+ }
+ else /* if (TIM2_Channel == TIM2_Channel_2) */
+ {
+ /* TI2 Configuration */
+ TI2_Config(TIM2_ICPolarity, TIM2_ICSelection, TIM2_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM2_SetIC2Prescaler(TIM2_ICPrescaler);
+ }
+}
+
+/**
+ * @brief Configures the TIM2 peripheral in PWM Input Mode according to the
+ * specified parameters.
+ * @param TIM2_Channel: TIM2 Channel
+ * This parameter can be one of the following values:
+ * @arg TIM2_Channel_1: Channel 1
+ * @arg TIM2_Channel_2: Channel 2
+ * @param TIM2_ICPolarity: Input Capture Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM2_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM2_ICSelection: Input Capture Selection
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICSelection_DirectTI: Input Capture mapped on the direct input
+ * @arg TIM2_ICSelection_IndirectTI: Input Capture mapped on the indirect input
+ * @arg TIM2_ICSelection_TRGI: Input Capture mapped on the Trigger Input
+ * @param TIM2_ICPrescaler: Input Capture Prescaler
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM2_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM2_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM2_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @retval None
+ */
+void TIM2_PWMIConfig(TIM2_Channel_TypeDef TIM2_Channel,
+ TIM2_ICPolarity_TypeDef TIM2_ICPolarity,
+ TIM2_ICSelection_TypeDef TIM2_ICSelection,
+ TIM2_ICPSC_TypeDef TIM2_ICPrescaler,
+ uint8_t TIM2_ICFilter)
+{
+ uint8_t icpolarity = TIM2_ICPolarity_Rising;
+ uint8_t icselection = TIM2_ICSelection_DirectTI;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_CHANNEL(TIM2_Channel));
+
+ /* Select the Opposite Input Polarity */
+ if (TIM2_ICPolarity == TIM2_ICPolarity_Rising)
+ {
+ icpolarity = TIM2_ICPolarity_Falling;
+ }
+ else
+ {
+ icpolarity = TIM2_ICPolarity_Rising;
+ }
+
+ /* Select the Opposite Input */
+ if (TIM2_ICSelection == TIM2_ICSelection_DirectTI)
+ {
+ icselection = TIM2_ICSelection_IndirectTI;
+ }
+ else
+ {
+ icselection = TIM2_ICSelection_DirectTI;
+ }
+
+ if (TIM2_Channel == TIM2_Channel_1)
+ {
+ /* TI1 Configuration */
+ TI1_Config(TIM2_ICPolarity, TIM2_ICSelection,
+ TIM2_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM2_SetIC1Prescaler(TIM2_ICPrescaler);
+
+ /* TI2 Configuration */
+ TI2_Config((TIM2_ICPolarity_TypeDef)icpolarity, (TIM2_ICSelection_TypeDef)icselection, TIM2_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM2_SetIC2Prescaler(TIM2_ICPrescaler);
+ }
+ else
+ {
+ /* TI2 Configuration */
+ TI2_Config(TIM2_ICPolarity, TIM2_ICSelection,
+ TIM2_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM2_SetIC2Prescaler(TIM2_ICPrescaler);
+
+ /* TI1 Configuration */
+ TI1_Config((TIM2_ICPolarity_TypeDef)icpolarity, (TIM2_ICSelection_TypeDef)icselection, TIM2_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM2_SetIC1Prescaler(TIM2_ICPrescaler);
+ }
+}
+
+/**
+ * @brief Gets the TIM2 Input Capture 1 value.
+ * @param None
+ * @retval Capture Compare 1 Register value.
+ */
+uint16_t TIM2_GetCapture1(void)
+{
+ uint16_t tmpccr1 = 0;
+ uint8_t tmpccr1l, tmpccr1h;
+
+ tmpccr1h = TIM2->CCR1H;
+ tmpccr1l = TIM2->CCR1L;
+
+ tmpccr1 = (uint16_t)(tmpccr1l);
+ tmpccr1 |= (uint16_t)((uint16_t)tmpccr1h << 8);
+ /* Get the Capture 1 Register value */
+ return ((uint16_t)tmpccr1);
+}
+
+/**
+ * @brief Gets the TIM2 Input Capture 2 value.
+ * @param None
+ * @retval Capture Compare 2 Register value.
+ */
+uint16_t TIM2_GetCapture2(void)
+{
+ uint16_t tmpccr2 = 0;
+ uint8_t tmpccr2l, tmpccr2h;
+
+ tmpccr2h = TIM2->CCR2H;
+ tmpccr2l = TIM2->CCR2L;
+
+ tmpccr2 = (uint16_t)(tmpccr2l);
+ tmpccr2 |= (uint16_t)((uint16_t)tmpccr2h << 8);
+ /* Get the Capture 2 Register value */
+ return ((uint16_t)tmpccr2);
+}
+
+/**
+ * @brief Sets the TIM2 Input Capture 1 prescaler.
+ * @param TIM2_IC1Prescaler: Specifies the Input Capture prescaler new value
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM2_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM2_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM2_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @retval None
+ */
+void TIM2_SetIC1Prescaler(TIM2_ICPSC_TypeDef TIM2_IC1Prescaler)
+{
+ uint8_t tmpccmr1 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_IC_PRESCALER(TIM2_IC1Prescaler));
+
+ tmpccmr1 = TIM2->CCMR1;
+
+ /* Reset the IC1PSC Bits */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_ICxPSC);
+
+ /* Set the IC1PSC value */
+ tmpccmr1 |= (uint8_t)TIM2_IC1Prescaler;
+
+ TIM2->CCMR1 = tmpccmr1;
+}
+
+/**
+ * @brief Sets the TIM2 Input Capture 2 prescaler.
+ * @param TIM2_IC2Prescaler: Specifies the Input Capture prescaler new value
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM2_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM2_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM2_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @retval None
+ */
+void TIM2_SetIC2Prescaler(TIM2_ICPSC_TypeDef TIM2_IC2Prescaler)
+{
+ uint8_t tmpccmr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_IC_PRESCALER(TIM2_IC2Prescaler));
+
+ tmpccmr2 = TIM2->CCMR2;
+
+ /* Reset the IC2PSC Bits */
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_ICxPSC);
+
+ /* Set the IC2PSC value */
+ tmpccmr2 |= (uint8_t)TIM2_IC2Prescaler;
+
+ TIM2->CCMR2 = tmpccmr2;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Group4 Interrupts DMA and flags management functions
+ * @brief Interrupts, DMA and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts, DMA and flags management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the specified TIM2 interrupts.
+ * @param TIM2_IT: Specifies the TIM2 interrupts sources to be enabled or disabled.
+ * This parameter can be any combination of the following values:
+ * @arg TIM2_IT_Update: Update
+ * @arg TIM2_IT_CC1: Capture Compare Channel1
+ * @arg TIM2_IT_CC2: Capture Compare Channel2
+ * @arg TIM2_IT_Trigger: Trigger
+ * @arg TIM2_IT_Break: Break
+ * @param NewState: The new state of the TIM2 peripheral.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM2_ITConfig(TIM2_IT_TypeDef TIM2_IT, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_IT(TIM2_IT));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the Interrupt sources */
+ TIM2->IER |= (uint8_t)TIM2_IT;
+ }
+ else
+ {
+ /* Disable the Interrupt sources */
+ TIM2->IER &= (uint8_t)(~(uint8_t)TIM2_IT);
+ }
+}
+
+/**
+ * @brief Configures the TIM2 event to be generated by software.
+ * @param TIM2_EventSource: Specifies the event source.
+ * This parameter can be any combination of the following values:
+ * @arg TIM2_EventSource_Update: Update
+ * @arg TIM2_EventSource_CC1: Capture Compare Channel1
+ * @arg TIM2_EventSource_CC2: Capture Compare Channel2
+ * @arg TIM2_EventSource_Trigger: Trigger
+ * @arg TIM2_EventSource_Break: Break
+ * @retval None
+ */
+void TIM2_GenerateEvent(TIM2_EventSource_TypeDef TIM2_EventSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_EVENT_SOURCE((uint8_t)TIM2_EventSource));
+
+ /* Set the event sources */
+ TIM2->EGR |= (uint8_t)TIM2_EventSource;
+}
+
+/**
+ * @brief Checks whether the specified TIM2 flag is set or not.
+ * @param TIM2_FLAG: Specifies the flag to check.
+ * This parameter can be any combination of the following values:
+ * @arg TIM2_FLAG_Update: Update
+ * @arg TIM2_FLAG_CC1: Capture Compare Channel1
+ * @arg TIM2_FLAG_CC2: Capture Compare Channel2
+ * @arg TIM2_FLAG_Trigger: Trigger
+ * @arg TIM2_FLAG_Break: Break
+ * @arg TIM2_FLAG_CC1OF: Capture compare 1 over capture
+ * @arg TIM2_FLAG_CC2OF: Capture compare 2 over capture
+ * @retval FlagStatus: The new state of TIM2_FLAG (SET or RESET)
+ */
+FlagStatus TIM2_GetFlagStatus(TIM2_FLAG_TypeDef TIM2_FLAG)
+{
+ FlagStatus bitstatus = RESET;
+ uint8_t tim2_flag_l = 0, tim2_flag_h = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_GET_FLAG(TIM2_FLAG));
+
+ tim2_flag_l = (uint8_t)(TIM2->SR1 & (uint8_t)(TIM2_FLAG));
+ tim2_flag_h = (uint8_t)(TIM2->SR2 & (uint8_t)((uint16_t)TIM2_FLAG >> 8));
+
+ if ((uint8_t)(tim2_flag_l | tim2_flag_h) != 0)
+ {
+ bitstatus = SET;
+ }
+ else
+ {
+ bitstatus = RESET;
+ }
+ return ((FlagStatus)bitstatus);
+}
+
+/**
+ * @brief Clears the TIM’s pending flags.
+ * @param TIM2_FLAG: Specifies the flag to clear.
+ * This parameter can be any combination of the following values:
+ * @arg TIM2_FLAG_Update: Update
+ * @arg TIM2_FLAG_CC1: Capture Compare Channel1
+ * @arg TIM2_FLAG_CC2: Capture Compare Channel2
+ * @arg TIM2_FLAG_Trigger: Trigger
+ * @arg TIM2_FLAG_Break: Break
+ * @retval None
+ */
+void TIM2_ClearFlag(TIM2_FLAG_TypeDef TIM2_FLAG)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_CLEAR_FLAG((uint16_t)TIM2_FLAG));
+ /* Clear the flags (rc_w0) clear this bit by writing 0. Writing ‘1’ has no effect*/
+ TIM2->SR1 = (uint8_t)(~(uint8_t)(TIM2_FLAG));
+ TIM2->SR2 = (uint8_t)(~(uint8_t)((uint16_t)TIM2_FLAG >> 8));
+}
+
+/**
+ * @brief Checks whether the TIM2 interrupt has occurred or not.
+ * @param TIM2_IT: Specifies the TIM2 interrupt source to check.
+ * This parameter can be any combination of the following values:
+ * @arg TIM2_IT_Update: Update
+ * @arg TIM2_IT_CC1: Capture Compare Channel1
+ * @arg TIM2_IT_CC2: Capture Compare Channel2
+ * @arg TIM2_IT_Trigger: Trigger
+ * @arg TIM2_IT_Break: Break
+ * @retval ITStatus: The new state of the TIM2_IT (SET or RESET)
+ */
+ITStatus TIM2_GetITStatus(TIM2_IT_TypeDef TIM2_IT)
+{
+ ITStatus bitstatus = RESET;
+
+ uint8_t TIM2_itStatus = 0x0, TIM2_itEnable = 0x0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_GET_IT(TIM2_IT));
+
+ TIM2_itStatus = (uint8_t)(TIM2->SR1 & (uint8_t)TIM2_IT);
+
+ TIM2_itEnable = (uint8_t)(TIM2->IER & (uint8_t)TIM2_IT);
+
+ if ((TIM2_itStatus != (uint8_t)RESET ) && (TIM2_itEnable != (uint8_t)RESET))
+ {
+ bitstatus = (ITStatus)SET;
+ }
+ else
+ {
+ bitstatus = (ITStatus)RESET;
+ }
+ return ((ITStatus)bitstatus);
+}
+
+/**
+ * @brief Clears the TIM's interrupt pending bits.
+ * @param TIM2_IT: Specifies the pending bit to clear.
+ * This parameter can be any combination of the following values:
+ * @arg TIM2_IT_Update: Update
+ * @arg TIM2_IT_CC1: Capture Compare Channel1
+ * @arg TIM2_IT_CC2: Capture Compare Channel2
+ * @arg TIM2_IT_Trigger: Trigger
+ * @arg TIM2_IT_Break: Break
+ * @retval None
+ */
+void TIM2_ClearITPendingBit(TIM2_IT_TypeDef TIM2_IT)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_IT(TIM2_IT));
+
+ /* Clear the IT pending Bit */
+ TIM2->SR1 = (uint8_t)(~(uint8_t)TIM2_IT);
+}
+
+/**
+ * @brief Enables or disables the TIM2 DMA Requests.
+ * @param TIM2_DMASource: specifies the DMA Request sources.
+ * This parameter can be any combination of the following values:
+ * @arg TIM2_DMASource_Update: TIM2 DMA Update Request
+ * @arg TIM2_DMASource_CC1: TIM2 DMA CC1 Request
+ * @arg TIM2_DMASource_CC2: TIM2 DMA CC2 Request
+ * @param NewState: new state of the DMA Request sources.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM2_DMACmd( TIM2_DMASource_TypeDef TIM2_DMASource, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ assert_param(IS_TIM2_DMA_SOURCE(TIM2_DMASource));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the DMA sources */
+ TIM2->DER |= TIM2_DMASource;
+ }
+ else
+ {
+ /* Disable the DMA sources */
+ TIM2->DER &= (uint8_t)(~TIM2_DMASource);
+ }
+}
+
+/**
+ * @brief Selects the TIM2 peripheral Capture Compare DMA source.
+ * @param NewState: new state of the Capture Compare DMA source.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM2_SelectCCDMA(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Set the CCDS Bit */
+ TIM2->CR2 |= TIM_CR2_CCDS;
+ }
+ else
+ {
+ /* Reset the CCDS Bit */
+ TIM2->CR2 &= (uint8_t)(~TIM_CR2_CCDS);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Group5 Clocks management functions
+ * @brief Clocks management functions
+ *
+@verbatim
+ ===============================================================================
+ Clocks management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables the TIM2 internal Clock.
+ * @par Parameters:
+ * None
+ * @retval None
+ */
+void TIM2_InternalClockConfig(void)
+{
+ /* Disable slave mode to clock the prescaler directly with the internal clock */
+ TIM2->SMCR &= (uint8_t)(~TIM_SMCR_SMS);
+}
+
+/**
+ * @brief Configures the TIM2 Trigger as External Clock.
+ * @param TIM2_TIxExternalCLKSource: Specifies Trigger source.
+ * This parameter can be one of the following values:
+ * @arg TIM2_TIxExternalCLK1Source_TI1ED: External Clock mode 1 source = TI1ED
+ * @arg TIM2_TIxExternalCLK1Source_TI1: External Clock mode 1 source = TI1
+ * @arg TIM2_TIxExternalCLK1Source_TI2: External Clock mode 1 source = TI2
+ * @param TIM2_ICPolarity: Specifies the TIx Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM2_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param ICFilter: Specifies the filter value.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM2_TIxExternalClockConfig(TIM2_TIxExternalCLK1Source_TypeDef TIM2_TIxExternalCLKSource,
+ TIM2_ICPolarity_TypeDef TIM2_ICPolarity,
+ uint8_t ICFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_TIXCLK_SOURCE(TIM2_TIxExternalCLKSource));
+ assert_param(IS_TIM2_IC_POLARITY(TIM2_ICPolarity));
+ assert_param(IS_TIM2_IC_FILTER(ICFilter));
+
+ /* Configure the TIM2 Input Clock Source */
+ if (TIM2_TIxExternalCLKSource == TIM2_TIxExternalCLK1Source_TI2)
+ {
+ TI2_Config(TIM2_ICPolarity, TIM2_ICSelection_DirectTI, ICFilter);
+ }
+ else
+ {
+ TI1_Config(TIM2_ICPolarity, TIM2_ICSelection_DirectTI, ICFilter);
+ }
+
+ /* Select the Trigger source */
+ TIM2_SelectInputTrigger((TIM2_TRGSelection_TypeDef)TIM2_TIxExternalCLKSource);
+
+ /* Select the External clock mode1 */
+ TIM2->SMCR |= (uint8_t)(TIM2_SlaveMode_External1);
+}
+
+/**
+ * @brief Configures the TIM2 External clock Mode1.
+ * @param TIM2_ExtTRGPrescaler: Specifies the external Trigger Prescaler.
+ * This parameter can be one of the following values:
+ * @arg TIM2_ExtTRGPSC_OFF: No External Trigger prescaler
+ * @arg TIM2_ExtTRGPSC_DIV2: External Trigger prescaler = 2 (ETRP frequency divided by 2)
+ * @arg TIM2_ExtTRGPSC_DIV4: External Trigger prescaler = 4 (ETRP frequency divided by 4)
+ * @arg TIM2_ExtTRGPSC_DIV8: External Trigger prescaler = 8 (ETRP frequency divided by 8)
+ * @param TIM2_ExtTRGPolarity: Specifies the external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM2_ExtTRGPolarity_Inverted: External Trigger Polarity = inverted
+ * @arg TIM2_ExtTRGPolarity_NonInverted: External Trigger Polarity = non inverted
+ * @param ExtTRGFilter: Specifies the External Trigger Filter.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM2_ETRClockMode1Config(TIM2_ExtTRGPSC_TypeDef TIM2_ExtTRGPrescaler,
+ TIM2_ExtTRGPolarity_TypeDef TIM2_ExtTRGPolarity,
+ uint8_t ExtTRGFilter)
+{
+ /* Configure the ETR Clock source */
+ TIM2_ETRConfig(TIM2_ExtTRGPrescaler, TIM2_ExtTRGPolarity, ExtTRGFilter);
+
+ /* Select the External clock mode1 */
+ TIM2->SMCR &= (uint8_t)(~TIM_SMCR_SMS);
+ TIM2->SMCR |= (uint8_t)(TIM2_SlaveMode_External1);
+
+ /* Select the Trigger selection: ETRF */
+ TIM2->SMCR &= (uint8_t)(~TIM_SMCR_TS);
+ TIM2->SMCR |= (uint8_t)((TIM2_TRGSelection_TypeDef)TIM2_TRGSelection_ETRF);
+}
+
+/**
+ * @brief Configures the TIM2 External clock Mode2.
+ * @param TIM2_ExtTRGPrescaler: Specifies the external Trigger Prescaler.
+ * This parameter can be one of the following values:
+ * @arg TIM2_ExtTRGPSC_OFF: No External Trigger prescaler
+ * @arg TIM2_ExtTRGPSC_DIV2: External Trigger prescaler = 2 (ETRP frequency divided by 2)
+ * @arg TIM2_ExtTRGPSC_DIV4: External Trigger prescaler = 4 (ETRP frequency divided by 4)
+ * @arg TIM2_ExtTRGPSC_DIV8: External Trigger prescaler = 8 (ETRP frequency divided by 8)
+ * @param TIM2_ExtTRGPolarity: Specifies the external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM2_ExtTRGPolarity_Inverted: External Trigger Polarity = inverted
+ * @arg TIM2_ExtTRGPolarity_NonInverted: External Trigger Polarity = non inverted
+ * @param ExtTRGFilter: Specifies the External Trigger Filter.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM2_ETRClockMode2Config(TIM2_ExtTRGPSC_TypeDef TIM2_ExtTRGPrescaler,
+ TIM2_ExtTRGPolarity_TypeDef TIM2_ExtTRGPolarity,
+ uint8_t ExtTRGFilter)
+{
+ /* Configure the ETR Clock source */
+ TIM2_ETRConfig(TIM2_ExtTRGPrescaler, TIM2_ExtTRGPolarity, ExtTRGFilter);
+
+ /* Enable the External clock mode2 */
+ TIM2->ETR |= TIM_ETR_ECE ;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Group6 Synchronization management functions
+ * @brief Synchronization management functions
+ *
+@verbatim
+ ===============================================================================
+ Synchronization management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM2 Driver: how to use it in synchronization Mode
+ ===================================================================
+ Case of two/several Timers
+ **************************
+ 1. If TIM2 is used as master to other timers use the following functions:
+ - TIM2_SelectOutputTrigger()
+ - TIM2_SelectMasterSlaveMode()
+ 2. If TIM2 is used as slave to other timers use the following functions:
+ - TIM2_SelectInputTrigger()
+ - TIM2_SelectSlaveMode()
+
+ Case of Timers and external trigger (TRIG pin)
+ ********************************************
+ 1. Configure the External trigger using TIM2_ETRConfig()
+ 2. Configure the Slave Timer using the following functions:
+ - TIM2_SelectInputTrigger()
+ - TIM2_SelectSlaveMode()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Selects the TIM2 Input Trigger source.
+ * @param TIM2_InputTriggerSource: Specifies Input Trigger source.
+ * This parameter can be one of the following values:
+ * @arg TIM2_TRGSelection_TIM4: TRIG Input source = TIM TRIG Output
+ * @arg TIM2_TRGSelection_TIM1: TRIG Input source = TIM TRIG Output
+ * @arg TIM2_TRGSelection_TIM2: TRIG Input source = TIM TRIG Output
+ * @arg TIM2_TRGSelection_TIM2: TRIG Input source = TIM TRIG Output
+ * @arg TIM2_TRGSelection_TI1F_ED: TRIG Input source = TI1F_ED (TI1 Edge Detector)
+ * @arg TIM2_TRGSelection_TI1FP1: TRIG Input source = TI1FP1 (Filtered Timer Input 1)
+ * @arg TIM2_TRGSelection_TI2FP2: TRIG Input source = TI2FP2 (Filtered Timer Input 2)
+ * @arg TIM2_TRGSelection_ETRF: TRIG Input source = ETRF (External Trigger Input )
+ * @retval None
+ */
+void TIM2_SelectInputTrigger(TIM2_TRGSelection_TypeDef TIM2_InputTriggerSource)
+{
+ uint8_t tmpsmcr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_TRIGGER_SELECTION(TIM2_InputTriggerSource));
+
+ tmpsmcr = TIM2->SMCR;
+
+ /* Select the Trigger Source */
+ tmpsmcr &= (uint8_t)(~TIM_SMCR_TS);
+ tmpsmcr |= (uint8_t)TIM2_InputTriggerSource;
+
+ TIM2->SMCR = (uint8_t)tmpsmcr;
+}
+
+/**
+ * @brief Selects the TIM2 Trigger Output Mode.
+ * @param TIM2_TRGOSource: Specifies the Trigger Output source.
+ * This parameter can be one of the following values:
+ * @arg TIM2_TRGOSource_Reset: Trigger Output source = Reset
+ * @arg TIM2_TRGOSource_Enable: Trigger Output source = TIM2 is enabled
+ * @arg TIM2_TRGOSource_Update: Trigger Output source = Update event
+ * @arg TIM2_TRGOSource_OC1: Trigger Output source = output compare channel1
+ * @arg TIM2_TRGOSource_OC1REF: Trigger Output source = output compare channel 1 reference
+ * @arg TIM2_TRGOSource_OC2REF: Trigger Output source = output compare channel 2 reference
+ * @retval None
+ */
+void TIM2_SelectOutputTrigger(TIM2_TRGOSource_TypeDef TIM2_TRGOSource)
+{
+ uint8_t tmpcr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_TRGO_SOURCE(TIM2_TRGOSource));
+
+ tmpcr2 = TIM2->CR2;
+
+ /* Reset the MMS Bits */
+ tmpcr2 &= (uint8_t)(~TIM_CR2_MMS);
+
+ /* Select the TRGO source */
+ tmpcr2 |= (uint8_t)TIM2_TRGOSource;
+
+ TIM2->CR2 = tmpcr2;
+}
+
+/**
+ * @brief Selects the TIM2 Slave Mode.
+ * @param TIM2_SlaveMode: Specifies the TIM2 Slave Mode.
+ * This parameter can be one of the following values:
+ * @arg TIM2_SlaveMode_Reset: Slave Mode Selection = Reset
+ * @arg TIM2_SlaveMode_Gated: Slave Mode Selection = Gated
+ * @arg TIM2_SlaveMode_Trigger: Slave Mode Selection = Trigger
+ * @arg TIM2_SlaveMode_External1: Slave Mode Selection = External 1
+ * @retval None
+ */
+void TIM2_SelectSlaveMode(TIM2_SlaveMode_TypeDef TIM2_SlaveMode)
+{
+ uint8_t tmpsmcr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_SLAVE_MODE(TIM2_SlaveMode));
+
+ tmpsmcr = TIM2->SMCR;
+
+ /* Reset the SMS Bits */
+ tmpsmcr &= (uint8_t)(~TIM_SMCR_SMS);
+
+ /* Select the Slave Mode */
+ tmpsmcr |= (uint8_t)TIM2_SlaveMode;
+
+ TIM2->SMCR = tmpsmcr;
+}
+
+/**
+ * @brief Sets or Resets the TIM2 Master/Slave Mode.
+ * @param NewState: The new state of the synchronization between TIM2 and its slaves (through TRGO).
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM2_SelectMasterSlaveMode(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the MSM Bit */
+ if (NewState != DISABLE)
+ {
+ TIM2->SMCR |= TIM_SMCR_MSM;
+ }
+ else
+ {
+ TIM2->SMCR &= (uint8_t)(~TIM_SMCR_MSM);
+ }
+}
+
+/**
+ * @brief Configures the TIM2 External Trigger.
+ * @param TIM2_ExtTRGPrescaler: Specifies the external Trigger Prescaler.
+ * This parameter can be one of the following values:
+ * @arg TIM2_ExtTRGPSC_OFF: No External Trigger prescaler
+ * @arg TIM2_ExtTRGPSC_DIV2: External Trigger prescaler = 2 (ETRP frequency divided by 2)
+ * @arg TIM2_ExtTRGPSC_DIV4: External Trigger prescaler = 4 (ETRP frequency divided by 4)
+ * @arg TIM2_ExtTRGPSC_DIV8: External Trigger prescaler = 8 (ETRP frequency divided by 8)
+ * @param TIM2_ExtTRGPolarity: Specifies the external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM2_ExtTRGPolarity_Inverted: External Trigger Polarity = inverted
+ * @arg TIM2_ExtTRGPolarity_NonInverted: External Trigger Polarity = non inverted
+ * @param ExtTRGFilter: Specifies the External Trigger Filter.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM2_ETRConfig(TIM2_ExtTRGPSC_TypeDef TIM2_ExtTRGPrescaler,
+ TIM2_ExtTRGPolarity_TypeDef TIM2_ExtTRGPolarity,
+ uint8_t ExtTRGFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM2_EXT_PRESCALER(TIM2_ExtTRGPrescaler));
+ assert_param(IS_TIM2_EXT_POLARITY(TIM2_ExtTRGPolarity));
+ assert_param(IS_TIM2_EXT_FILTER(ExtTRGFilter));
+
+ /* Set the Prescaler, the Filter value and the Polarity */
+ TIM2->ETR |= (uint8_t)((uint8_t)((uint8_t)TIM2_ExtTRGPrescaler | (uint8_t)TIM2_ExtTRGPolarity)
+ | (uint8_t)ExtTRGFilter);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM2_Group7 Specific interface management functions
+ * @brief Specific interface management functions
+ *
+@verbatim
+ ===============================================================================
+ Specific interface management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures the TIM2 Encoder Interface.
+ * @param TIM2_EncoderMode: Specifies the TIM2 Encoder Mode.
+ * This parameter can be one of the following values:
+ * @arg TIM2_EncoderMode_TI1: Encoder mode 1
+ * @arg TIM2_EncoderMode_TI2: Encoder mode 2
+ * @arg TIM2_EncoderMode_TI12: Encoder mode 3
+ * @param TIM2_IC1Polarity: Specifies the IC1 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM2_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM2_IC2Polarity: Specifies the IC2 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM2_ICPolarity_Falling: Input Capture on Falling Edge
+ * @retval None
+ */
+void TIM2_EncoderInterfaceConfig(TIM2_EncoderMode_TypeDef TIM2_EncoderMode,
+ TIM2_ICPolarity_TypeDef TIM2_IC1Polarity,
+ TIM2_ICPolarity_TypeDef TIM2_IC2Polarity)
+{
+ uint8_t tmpsmcr = 0;
+ uint8_t tmpccmr1 = 0;
+ uint8_t tmpccmr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_ENCODER_MODE(TIM2_EncoderMode));
+ assert_param(IS_TIM2_IC_POLARITY(TIM2_IC1Polarity));
+ assert_param(IS_TIM2_IC_POLARITY(TIM2_IC2Polarity));
+
+ tmpsmcr = TIM2->SMCR;
+ tmpccmr1 = TIM2->CCMR1;
+ tmpccmr2 = TIM2->CCMR2;
+
+ /* Set the encoder Mode */
+ tmpsmcr &= (uint8_t)(TIM_SMCR_MSM | TIM_SMCR_TS) ;
+ tmpsmcr |= (uint8_t)TIM2_EncoderMode;
+
+ /* Select the Capture Compare 1 and the Capture Compare 2 as input */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_CCxS);
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_CCxS);
+ tmpccmr1 |= TIM_CCMR_TIxDirect_Set;
+ tmpccmr2 |= TIM_CCMR_TIxDirect_Set;
+
+ /* Set the TI1 and the TI2 Polarities */
+ if (TIM2_IC1Polarity == TIM2_ICPolarity_Falling)
+ {
+ TIM2->CCER1 |= TIM_CCER1_CC1P ;
+ }
+ else
+ {
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC1P) ;
+ }
+
+ if (TIM2_IC2Polarity == TIM2_ICPolarity_Falling)
+ {
+ TIM2->CCER1 |= TIM_CCER1_CC2P ;
+ }
+ else
+ {
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC2P) ;
+ }
+
+ TIM2->SMCR = tmpsmcr;
+ TIM2->CCMR1 = tmpccmr1;
+ TIM2->CCMR2 = tmpccmr2;
+}
+
+/**
+ * @brief Enables or Disables the TIM’s Hall sensor interface.
+ * @param NewState: The new state of the TIM2 Hall sensor interface.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM2_SelectHallSensor(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the TI1S Bit */
+ if (NewState != DISABLE)
+ {
+ TIM2->CR2 |= TIM_CR2_TI1S;
+ }
+ else
+ {
+ TIM2->CR2 &= (uint8_t)(~TIM_CR2_TI1S);
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Configure the TI1 as Input.
+ * @param TIM2_ICPolarity: Input Capture Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM2_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM2_ICSelection: Specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICSelection_DirectTI: Input Capture mapped on the direct input
+ * @arg TIM2_ICSelection_IndirectTI: Input Capture mapped on the indirect input
+ * @arg TIM2_ICSelection_TRGI: Input Capture mapped on the Trigger Input
+ * @param TIM2_ICFilter: Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TI1_Config(TIM2_ICPolarity_TypeDef TIM2_ICPolarity, \
+ TIM2_ICSelection_TypeDef TIM2_ICSelection, \
+ uint8_t TIM2_ICFilter)
+{
+ uint8_t tmpccmr1 = 0;
+ uint8_t tmpicpolarity = TIM2_ICPolarity;
+ tmpccmr1 = TIM2->CCMR1;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_IC_POLARITY(TIM2_ICPolarity));
+ assert_param(IS_TIM2_IC_SELECTION(TIM2_ICSelection));
+ assert_param(IS_TIM2_IC_FILTER(TIM2_ICFilter));
+
+ /* Disable the Channel 1: Reset the CCE Bit */
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E);
+
+ /* Select the Input and set the filter */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_CCxS) & (uint8_t)(~TIM_CCMR_ICxF);
+ tmpccmr1 |= (uint8_t)(((uint8_t)(TIM2_ICSelection)) | ((uint8_t)(TIM2_ICFilter << 4)));
+
+ TIM2->CCMR1 = tmpccmr1;
+
+ /* Select the Polarity */
+ if (tmpicpolarity == (uint8_t)(TIM2_ICPolarity_Falling))
+ {
+ TIM2->CCER1 |= TIM_CCER1_CC1P;
+ }
+ else
+ {
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC1P);
+ }
+
+ /* Set the CCE Bit */
+ TIM2->CCER1 |= TIM_CCER1_CC1E;
+}
+
+/**
+ * @brief Configure the TI2 as Input.
+ * @param TIM2_ICPolarity: Input Capture Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM2_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM2_ICSelection: Specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM2_ICSelection_DirectTI: Input Capture mapped on the direct input
+ * @arg TIM2_ICSelection_IndirectTI: Input Capture mapped on the indirect input
+ * @arg TIM2_ICSelection_TRGI: Input Capture mapped on the Trigger Input
+ * @param TIM2_ICFilter: Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TI2_Config(TIM2_ICPolarity_TypeDef TIM2_ICPolarity,
+ TIM2_ICSelection_TypeDef TIM2_ICSelection,
+ uint8_t TIM2_ICFilter)
+{
+ uint8_t tmpccmr2 = 0;
+ uint8_t tmpicpolarity = TIM2_ICPolarity;
+
+ /* Check the parameters */
+ assert_param(IS_TIM2_IC_POLARITY(TIM2_ICPolarity));
+ assert_param(IS_TIM2_IC_SELECTION(TIM2_ICSelection));
+ assert_param(IS_TIM2_IC_FILTER(TIM2_ICFilter));
+
+ tmpccmr2 = TIM2->CCMR2;
+
+ /* Disable the Channel 2: Reset the CCE Bit */
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E);
+
+ /* Select the Input and set the filter */
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_CCxS) & (uint8_t)(~TIM_CCMR_ICxF);
+ tmpccmr2 |= (uint8_t)(((uint8_t)(TIM2_ICSelection)) | ((uint8_t)(TIM2_ICFilter << 4)));
+
+ TIM2->CCMR2 = tmpccmr2;
+
+ /* Select the Polarity */
+ if (tmpicpolarity == TIM2_ICPolarity_Falling)
+ {
+ TIM2->CCER1 |= TIM_CCER1_CC2P ;
+ }
+ else
+ {
+ TIM2->CCER1 &= (uint8_t)(~TIM_CCER1_CC2P) ;
+ }
+
+ /* Set the CCE Bit */
+ TIM2->CCER1 |= TIM_CCER1_CC2E;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim3.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim3.c
new file mode 100644
index 00000000..317c8cc9
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim3.c
@@ -0,0 +1,2154 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_tim3.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the TIM3 peripheral:
+ * - TimeBase management
+ * - Output Compare management
+ * - Input Capture management
+ * - Interrupts, DMA and flags management
+ * - Clocks management
+ * - Synchronization management
+ * - Specific interface management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * This driver provides functions to configure and initialize the TIM3
+ * peripheral
+ * These functions are split in 7 groups:
+ *
+ * 1. TIM3 TimeBase management: this group includes all needed functions
+ * to configure the TIM Timebase unit:
+ * - Set/Get Prescaler
+ * - Set/Get Autoreload
+ * - Counter modes configuration
+ * - Select the One Pulse mode
+ * - Update Request Configuration
+ * - Update Disable Configuration
+ * - Auto-Preload Configuration
+ * - Enable/Disable the counter
+ *
+ * 2. TIM3 Output Compare management: this group includes all needed
+ * functions to configure the Capture/Compare unit used in Output
+ * compare mode:
+ * - Configure each channel, independently, in Output Compare mode
+ * - Select the output compare modes
+ * - Select the Polarities of each channel
+ * - Set/Get the Capture/Compare register values
+ * - Select the Output Compare Fast mode
+ * - Select the Output Compare Forced mode
+ * - Output Compare-Preload Configuration
+ * - Enable/Disable the Capture/Compare Channels
+ *
+ * 3. TIM3 Input Capture management: this group includes all needed
+ * functions to configure the Capture/Compare unit used in
+ * Input Capture mode:
+ * - Configure each channel in input capture mode
+ * - Configure Channel1/2 in PWM Input mode
+ * - Set the Input Capture Prescaler
+ * - Get the Capture/Compare values
+ *
+ * 4. TIM3 interrupts, DMA and flags management
+ * - Enable/Disable interrupt sources
+ * - Get flags status
+ * - Clear flags/ Pending bits
+ * - Enable/Disable DMA requests
+ * - Select CaptureCompare DMA request
+ *
+ * 5. TIM3 clocks management: this group includes all needed functions
+ * to configure the clock controller unit:
+ * - Select internal/External clock
+ * - Select the external clock mode: ETR(Mode1/Mode2) or TIx
+ *
+ * 6. TIM3 synchronization management: this group includes all needed
+ * functions to configure the Synchronization unit:
+ * - Select Input Trigger
+ * - Select Output Trigger
+ * - Select Master Slave Mode
+ * - ETR Configuration when used as external trigger
+ *
+ * 7. TIM3 specific interface management, this group includes all
+ * needed functions to use the specific TIM3 interface:
+ * - Encoder Interface Configuration
+ * - Select Hall Sensor
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_TIM3.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup TIM3
+ * @brief TIM3 driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void TI1_Config(TIM3_ICPolarity_TypeDef TIM3_ICPolarity,
+ TIM3_ICSelection_TypeDef TIM3_ICSelection,
+ uint8_t TIM3_ICFilter);
+static void TI2_Config(TIM3_ICPolarity_TypeDef TIM3_ICPolarity,
+ TIM3_ICSelection_TypeDef TIM3_ICSelection,
+ uint8_t TIM3_ICFilter);
+
+
+/** @defgroup TIM3_Private_Functions
+ * @{
+ */
+
+/** @defgroup TIM3_Group1 TimeBase management functions
+ * @brief TimeBase management functions
+ *
+@verbatim
+ ===============================================================================
+ TimeBase management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM3 Driver: how to use it in Timing(Time base) Mode
+ ===================================================================
+ To use the Timer in Timing(Time base) mode, the following steps are mandatory:
+
+ 1. Enable TIM3 clock using CLK_PeripheralClockConfig(CLK_Peripheral_TIM3, ENABLE) function.
+
+ 2. Call TIM3_TimeBaseInit() to configure the Time Base unit with the
+ corresponding configuration.
+
+ 3. Enable global interrupts if you need to generate the update interrupt.
+
+ 4. Enable the corresponding interrupt using the function TIM3_ITConfig(TIM3_IT_Update)
+
+ 5. Call the TIM3_Cmd(ENABLE) function to enable the TIM3 counter.
+
+ Note1: All other functions can be used separately to modify, if needed,
+ a specific feature of the Timer.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitialize the TIM3 peripheral registers to their default reset values.
+ * @param None
+ * @retval None
+ */
+void TIM3_DeInit(void)
+{
+ TIM3->CR1 = TIM_CR1_RESET_VALUE;
+ TIM3->CR2 = TIM_CR2_RESET_VALUE;
+ TIM3->SMCR = TIM_SMCR_RESET_VALUE;
+ TIM3->ETR = TIM_ETR_RESET_VALUE;
+ TIM3->IER = TIM_IER_RESET_VALUE;
+ TIM3->SR2 = TIM_SR2_RESET_VALUE;
+
+ /* Disable channels */
+ TIM3->CCER1 = TIM_CCER1_RESET_VALUE;
+ /* Configure channels as inputs: it is necessary if lock level is equal to 2 or 3 */
+ TIM3->CCMR1 = 0x01;/*TIM3_ICxSource_TIxFPx */
+ TIM3->CCMR2 = 0x01;/*TIM3_ICxSource_TIxFPx */
+
+ /* Then reset channel registers: it also works if lock level is equal to 2 or 3 */
+ TIM3->CCER1 = TIM_CCER1_RESET_VALUE;
+ TIM3->CCMR1 = TIM_CCMR1_RESET_VALUE;
+ TIM3->CCMR2 = TIM_CCMR2_RESET_VALUE;
+
+ TIM3->CNTRH = TIM_CNTRH_RESET_VALUE;
+ TIM3->CNTRL = TIM_CNTRL_RESET_VALUE;
+
+ TIM3->PSCR = TIM_PSCR_RESET_VALUE;
+
+ TIM3->ARRH = TIM_ARRH_RESET_VALUE;
+ TIM3->ARRL = TIM_ARRL_RESET_VALUE;
+
+ TIM3->CCR1H = TIM_CCR1H_RESET_VALUE;
+ TIM3->CCR1L = TIM_CCR1L_RESET_VALUE;
+ TIM3->CCR2H = TIM_CCR2H_RESET_VALUE;
+ TIM3->CCR2L = TIM_CCR2L_RESET_VALUE;
+
+
+ TIM3->OISR = TIM_OISR_RESET_VALUE;
+ TIM3->EGR = 0x01;/* TIM_EGR_UG */
+ TIM3->BKR = TIM_BKR_RESET_VALUE;
+ TIM3->SR1 = TIM_SR1_RESET_VALUE;
+}
+
+/**
+ * @brief Initializes the TIM3 Time Base Unit according to the specified parameters.
+ * @param TIM3_Prescaler: Prescaler
+ * This parameter can be one of the following values:
+ * @arg TIM3_Prescaler_1: Time base Prescaler = 1 (No effect)
+ * @arg TIM3_Prescaler_2: Time base Prescaler = 2
+ * @arg TIM3_Prescaler_4: Time base Prescaler = 4
+ * @arg TIM3_Prescaler_8: Time base Prescaler = 8
+ * @arg TIM3_Prescaler_16: Time base Prescaler = 16
+ * @arg TIM3_Prescaler_32: Time base Prescaler = 32
+ * @arg TIM3_Prescaler_64: Time base Prescaler = 64
+ * @arg TIM3_Prescaler_128: Time base Prescaler = 128
+ * @param TIM3_CounterMode: Counter mode
+ * This parameter can be one of the following values:
+ * @arg TIM3_CounterMode_Up: Counter Up Mode
+ * @arg TIM3_CounterMode_Down: Counter Down Mode
+ * @arg TIM3_CounterMode_CenterAligned1: Counter Central aligned Mode 1
+ * @arg TIM3_CounterMode_CenterAligned2: Counter Central aligned Mode 2
+ * @arg TIM3_CounterMode_CenterAligned3: Counter Central aligned Mode 3
+ * @param TIM3_Period: This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+
+void TIM3_TimeBaseInit(TIM3_Prescaler_TypeDef TIM3_Prescaler,
+ TIM3_CounterMode_TypeDef TIM3_CounterMode,
+ uint16_t TIM3_Period)
+{
+
+ assert_param(IS_TIM3_PRESCALER(TIM3_Prescaler));
+ assert_param(IS_TIM3_COUNTER_MODE(TIM3_CounterMode));
+
+
+
+ /* Set the Autoreload value */
+ TIM3->ARRH = (uint8_t)(TIM3_Period >> 8) ;
+ TIM3->ARRL = (uint8_t)(TIM3_Period);
+
+ /* Set the Prescaler value */
+ TIM3->PSCR = (uint8_t)(TIM3_Prescaler);
+
+ /* Select the Counter Mode */
+ TIM3->CR1 &= (uint8_t)((uint8_t)(~TIM_CR1_CMS)) & ((uint8_t)(~TIM_CR1_DIR));
+ TIM3->CR1 |= (uint8_t)(TIM3_CounterMode);
+
+ /* Generate an update event to reload the Prescaler value immediately */
+ TIM3->EGR = TIM3_EventSource_Update;
+}
+
+/**
+ * @brief Configures the TIM3 Prescaler.
+ * @param Prescaler: Specifies the Prescaler Register value
+ * This parameter can be one of the following values:
+ * @arg TIM3_Prescaler_1: Time base Prescaler = 1 (No effect)
+ * @arg TIM3_Prescaler_2: Time base Prescaler = 2
+ * @arg TIM3_Prescaler_4: Time base Prescaler = 4
+ * @arg TIM3_Prescaler_8: Time base Prescaler = 8
+ * @arg TIM3_Prescaler_16: Time base Prescaler = 16
+ * @arg TIM3_Prescaler_32: Time base Prescaler = 32
+ * @arg TIM3_Prescaler_64: Time base Prescaler = 64
+ * @arg TIM3_Prescaler_128: Time base Prescaler = 128
+ * @param TIM3_PSCReloadMode: Specifies the TIM3 Prescaler Reload mode.
+ * This parameter can be one of the following values:
+ * @arg TIM3_PSCReloadMode_Update: Prescaler value is reloaded at every update
+ * @arg TIM3_PSCReloadMode_Immediate: Prescaler value is reloaded at every update
+ * @retval None
+ */
+void TIM3_PrescalerConfig(TIM3_Prescaler_TypeDef Prescaler,
+ TIM3_PSCReloadMode_TypeDef TIM3_PSCReloadMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_PRESCALER(Prescaler));
+ assert_param(IS_TIM3_PRESCALER_RELOAD(TIM3_PSCReloadMode));
+
+ /* Set the Prescaler value */
+ TIM3->PSCR = (uint8_t)(Prescaler);
+
+ /* Set or reset the UG Bit */
+ if (TIM3_PSCReloadMode == TIM3_PSCReloadMode_Immediate)
+ {
+ TIM3->EGR |= TIM_EGR_UG ;
+ }
+ else
+ {
+ TIM3->EGR &= (uint8_t)(~TIM_EGR_UG) ;
+ }
+}
+
+/**
+ * @brief Specifies the TIM3 Counter Mode to be used.
+ * @param TIM3_CounterMode: Specifies the Counter Mode to be used
+ * This parameter can be one of the following values:
+ * @arg TIM3_CounterMode_Up: Counter Up Mode
+ * @arg TIM3_CounterMode_Down: Counter Down Mode
+ * @arg TIM3_CounterMode_CenterAligned1: Counter Central aligned Mode 1
+ * @arg TIM3_CounterMode_CenterAligned2: Counter Central aligned Mode 2
+ * @arg TIM3_CounterMode_CenterAligned3: Counter Central aligned Mode 3
+ * @retval None
+ */
+void TIM3_CounterModeConfig(TIM3_CounterMode_TypeDef TIM3_CounterMode)
+{
+ uint8_t tmpcr1 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_COUNTER_MODE(TIM3_CounterMode));
+
+ tmpcr1 = TIM3->CR1;
+
+ /* Reset the CMS and DIR Bits */
+ tmpcr1 &= (uint8_t)((uint8_t)(~TIM_CR1_CMS) & (uint8_t)(~TIM_CR1_DIR));
+
+ /* Set the Counter Mode */
+ tmpcr1 |= (uint8_t)TIM3_CounterMode;
+
+ TIM3->CR1 = tmpcr1;
+}
+
+/**
+ * @brief Sets the TIM3 Counter Register value.
+ * @param Counter: Specifies the Counter register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM3_SetCounter(uint16_t Counter)
+{
+
+ /* Set the Counter Register value */
+ TIM3->CNTRH = (uint8_t)(Counter >> 8);
+ TIM3->CNTRL = (uint8_t)(Counter);
+}
+
+/**
+ * @brief Sets the TIM3 Autoreload Register value.
+ * @param Autoreload: Specifies the Autoreload register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM3_SetAutoreload(uint16_t Autoreload)
+{
+ /* Set the Autoreload Register value */
+ TIM3->ARRH = (uint8_t)(Autoreload >> 8);
+ TIM3->ARRL = (uint8_t)(Autoreload);
+}
+
+/**
+ * @brief Gets the TIM3 Counter value.
+ * @param None
+ * @retval Counter Register value.
+ */
+uint16_t TIM3_GetCounter(void)
+{
+ uint16_t tmpcnt = 0;
+ uint8_t tmpcntrl, tmpcntrh;
+
+ tmpcntrh = TIM3->CNTRH;
+ tmpcntrl = TIM3->CNTRL;
+
+ tmpcnt = (uint16_t)(tmpcntrl);
+ tmpcnt |= (uint16_t)((uint16_t)tmpcntrh << 8);
+ /* Get the Counter Register value */
+ return ((uint16_t)tmpcnt);
+}
+
+/**
+ * @brief Gets the TIM3 Prescaler value.
+ * @param None
+ * @retval TIM3 Prescaler, it can be one of the following values:
+ * - TIM3_Prescaler_1: Time base Prescaler = 1 (No effect)
+ * - TIM3_Prescaler_2: Time base Prescaler = 2
+ * - TIM3_Prescaler_4: Time base Prescaler = 4
+ * - TIM3_Prescaler_8: Time base Prescaler = 8
+ * - TIM3_Prescaler_16: Time base Prescaler = 16
+ * - TIM3_Prescaler_32: Time base Prescaler = 32
+ * - TIM3_Prescaler_64: Time base Prescaler = 64
+ * - TIM3_Prescaler_128: Time base Prescaler = 128
+ */
+TIM3_Prescaler_TypeDef TIM3_GetPrescaler(void)
+{
+ /* Get the Prescaler Register value */
+ return ((TIM3_Prescaler_TypeDef)TIM3->PSCR);
+}
+
+/**
+ * @brief Enables or Disables the TIM3 Update event.
+ * @param NewState: The new state of the TIM3 peripheral Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+
+void TIM3_UpdateDisableConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the UDIS Bit */
+ if (NewState != DISABLE)
+ {
+ TIM3->CR1 |= TIM_CR1_UDIS;
+ }
+ else
+ {
+ TIM3->CR1 &= (uint8_t)(~TIM_CR1_UDIS);
+ }
+}
+
+/**
+ * @brief Selects the TIM3 Update Request Interrupt source.
+ * @param TIM3_UpdateSource: Specifies the Update source.
+ * This parameter can be one of the following values:
+ * @arg TIM3_UpdateSource_Global: Global Update request source
+ * @arg TIM3_UpdateSource_Regular: Regular Update request source
+ * @retval None
+ */
+void TIM3_UpdateRequestConfig(TIM3_UpdateSource_TypeDef TIM3_UpdateSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_UPDATE_SOURCE(TIM3_UpdateSource));
+
+ /* Set or Reset the URS Bit */
+ if (TIM3_UpdateSource == TIM3_UpdateSource_Regular)
+ {
+ TIM3->CR1 |= TIM_CR1_URS ;
+ }
+ else
+ {
+ TIM3->CR1 &= (uint8_t)(~TIM_CR1_URS);
+ }
+}
+
+/**
+ * @brief Enables or disables TIM3 peripheral Preload register on ARR.
+ * @param NewState: The new state of the TIM3 peripheral Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM3_ARRPreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the ARPE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM3->CR1 |= TIM_CR1_ARPE;
+ }
+ else
+ {
+ TIM3->CR1 &= (uint8_t)(~TIM_CR1_ARPE);
+ }
+}
+
+/**
+ * @brief Selects the TIM’s One Pulse Mode.
+ * @param TIM3_OPMode: Specifies the OPM Mode to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM3_OPMode_Single: Single one Pulse mode (OPM Active)
+ * @arg TIM3_OPMode_Repetitive: Single one Pulse mode (OPM Active)
+ * @retval None
+ */
+void TIM3_SelectOnePulseMode(TIM3_OPMode_TypeDef TIM3_OPMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_OPM_MODE(TIM3_OPMode));
+
+ /* Set or Reset the OPM Bit */
+ if (TIM3_OPMode == TIM3_OPMode_Single)
+ {
+ TIM3->CR1 |= TIM_CR1_OPM ;
+ }
+ else
+ {
+ TIM3->CR1 &= (uint8_t)(~TIM_CR1_OPM);
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM3 peripheral.
+ * @param NewState: The new state of the TIM3 peripheral.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM3_Cmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* set or Reset the CEN Bit */
+ if (NewState != DISABLE)
+ {
+ TIM3->CR1 |= TIM_CR1_CEN;
+ }
+ else
+ {
+ TIM3->CR1 &= (uint8_t)(~TIM_CR1_CEN);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Group2 Output Compare management functions
+ * @brief Output Compare management functions
+ *
+@verbatim
+ ===============================================================================
+ Output Compare management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM3 Driver: how to use it in Output Compare Mode
+ ===================================================================
+ To use the Timer in Output Compare mode, the following steps are mandatory:
+
+ 1. Enable TIM3 clock using CLK_PeripheralClockConfig(CLK_Peripheral_TIM3, ENABLE) function.
+
+ 2. Configure the TIM3 pins in output mode by configuring the corresponding GPIO pins
+
+ 3. Configure the Time base unit as described in the first part of this driver, if needed,
+ otherwise the Timer will run with the default configuration:
+ - Autoreload value = 0xFFFF
+ - Prescaler value = 0x0000
+ - Counter mode = Up counting
+
+ 4. Call TIM3_OCxInit() to configure the channel x with the desired parameters
+ including:
+ - TIM3 Output Compare mode: TIM3_OCMode
+ - TIM3 Output State: TIM3_OutputState
+ - TIM3 Pulse value: TIM3_Pulse
+ - TIM3 Output Compare Polarity: TIM3_OCPolarity
+ - TIM3 Output Idle State: TIM3_OCIdleState
+
+ 5. Call the TIM3_Cmd(ENABLE) function to enable the TIM3 counter.
+
+ Note1: All other functions can be used separately to modify, if needed,
+ a specific feature of the Timer.
+
+ Note2: If the corresponding interrupt or DMA request are needed, the user should:
+ 1. Enable global interrupts (or the DMA) to use the TIM3 interrupts (or DMA requests).
+ 2. Enable the corresponding interrupt (or DMA request) using the function
+ TIM3_ITConfig(TIM3_IT_CCx) (or TIM3_DMACmd(TIM3_DMASource_CCx))
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the TIM3 Channel1 according to the specified parameters.
+ * @param TIM3_OCMode: Output Compare Mode
+ * This parameter can be one of the following values:
+ * @arg TIM3_OCMode_Timing: Timing (Frozen) Mode
+ * @arg TIM3_OCMode_Active: Active Mode
+ * @arg TIM3_OCMode_Inactive: Inactive Mode
+ * @arg TIM3_OCMode_Toggle: Toggle Mode
+ * @arg TIM3_OCMode_PWM1: PWM Mode 1
+ * @arg TIM3_OCMode_PWM2: PWM Mode 2
+ * @param TIM3_OutputState: Output state
+ * This parameter can be one of the following values:
+ * @arg TIM3_OutputState_Disable: Output compare State disabled (channel output disabled)
+ * @arg TIM3_OutputState_Enable: Output compare State enabled (channel output enabled)
+ * @param TIM3_Pulse: This parameter must be a value between 0x0000 and 0xFFFF.
+ * @param TIM3_OCPolarity: Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM3_OCPolarity_High: Output compare polarity = High
+ * @arg TIM3_OCPolarity_Low: Output compare polarity = Low
+ * @param TIM3_OCIdleState: Output Compare Idle State
+ * This parameter can be one of the following values:
+ * @arg TIM3_OCIdleState_Reset: Output Compare Idle state = Reset
+ * @arg TIM3_OCIdleState_Set: Output Compare Idle state = Set
+ * @retval None
+ */
+void TIM3_OC1Init(TIM3_OCMode_TypeDef TIM3_OCMode,
+ TIM3_OutputState_TypeDef TIM3_OutputState,
+ uint16_t TIM3_Pulse,
+ TIM3_OCPolarity_TypeDef TIM3_OCPolarity,
+ TIM3_OCIdleState_TypeDef TIM3_OCIdleState)
+{
+ uint8_t tmpccmr1 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_OC_MODE(TIM3_OCMode));
+ assert_param(IS_TIM3_OUTPUT_STATE(TIM3_OutputState));
+ assert_param(IS_TIM3_OC_POLARITY(TIM3_OCPolarity));
+ assert_param(IS_TIM3_OCIDLE_STATE(TIM3_OCIdleState));
+
+ tmpccmr1 = TIM3->CCMR1;
+
+ /* Disable the Channel 1: Reset the CCE Bit */
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E);
+ /* Reset the Output Compare Bits */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Set the Output Compare Mode */
+ tmpccmr1 |= (uint8_t)TIM3_OCMode;
+
+ TIM3->CCMR1 = tmpccmr1;
+
+ /* Set the Output State */
+ if (TIM3_OutputState == TIM3_OutputState_Enable)
+ {
+ TIM3->CCER1 |= TIM_CCER1_CC1E;
+ }
+ else
+ {
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E);
+ }
+
+ /* Set the Output Polarity */
+ if (TIM3_OCPolarity == TIM3_OCPolarity_Low)
+ {
+ TIM3->CCER1 |= TIM_CCER1_CC1P;
+ }
+ else
+ {
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC1P);
+ }
+
+ /* Set the Output Idle state */
+ if (TIM3_OCIdleState == TIM3_OCIdleState_Set)
+ {
+ TIM3->OISR |= TIM_OISR_OIS1;
+ }
+ else
+ {
+ TIM3->OISR &= (uint8_t)(~TIM_OISR_OIS1);
+ }
+
+ /* Set the Pulse value */
+ TIM3->CCR1H = (uint8_t)(TIM3_Pulse >> 8);
+ TIM3->CCR1L = (uint8_t)(TIM3_Pulse);
+}
+
+/**
+ * @brief Initializes the TIM3 Channel2 according to the specified parameters.
+ * @param TIM3_OCMode: Output Compare Mode
+ * This parameter can be one of the following values:
+ * @arg TIM3_OCMode_Timing: Timing (Frozen) Mode
+ * @arg TIM3_OCMode_Active: Active Mode
+ * @arg TIM3_OCMode_Inactive: Inactive Mode
+ * @arg TIM3_OCMode_Toggle: Toggle Mode
+ * @arg TIM3_OCMode_PWM1: PWM Mode 1
+ * @arg TIM3_OCMode_PWM2: PWM Mode 2
+ * @param TIM3_OutputState: Output state
+ * This parameter can be one of the following values:
+ * @arg TIM3_OutputState_Disable: Output compare State disabled (channel output disabled)
+ * @arg TIM3_OutputState_Enable: Output compare State enabled (channel output enabled)
+ * @param TIM3_Pulse: This parameter must be a value between 0x0000 and 0xFFFF.
+ * @param TIM3_OCPolarity: Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM3_OCPolarity_High: Output compare polarity = High
+ * @arg TIM3_OCPolarity_Low: Output compare polarity = Low
+ * @param TIM3_OCIdleState: Output Compare Idle State
+ * This parameter can be one of the following values:
+ * @arg TIM3_OCIdleState_Reset: Output Compare Idle state = Reset
+ * @arg TIM3_OCIdleState_Set: Output Compare Idle state = Set
+ * @retval None
+ */
+void TIM3_OC2Init(TIM3_OCMode_TypeDef TIM3_OCMode,
+ TIM3_OutputState_TypeDef TIM3_OutputState,
+ uint16_t TIM3_Pulse,
+ TIM3_OCPolarity_TypeDef TIM3_OCPolarity,
+ TIM3_OCIdleState_TypeDef TIM3_OCIdleState)
+{
+ uint8_t tmpccmr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_OC_MODE(TIM3_OCMode));
+ assert_param(IS_TIM3_OUTPUT_STATE(TIM3_OutputState));
+ assert_param(IS_TIM3_OC_POLARITY(TIM3_OCPolarity));
+ assert_param(IS_TIM3_OCIDLE_STATE(TIM3_OCIdleState));
+
+ tmpccmr2 = TIM3->CCMR2;
+
+ /* Disable the Channel 2: Reset the CCE Bit */
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E);
+
+ /* Reset the Output Compare Bits */
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Set the Output Compare Mode */
+ tmpccmr2 |= (uint8_t)TIM3_OCMode;
+
+ TIM3->CCMR2 = tmpccmr2;
+
+ /* Set the Output State */
+ if (TIM3_OutputState == TIM3_OutputState_Enable)
+ {
+ TIM3->CCER1 |= TIM_CCER1_CC2E;
+ }
+ else
+ {
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E);
+ }
+
+ /* Set the Output Polarity */
+ if (TIM3_OCPolarity == TIM3_OCPolarity_Low)
+ {
+ TIM3->CCER1 |= TIM_CCER1_CC2P;
+ }
+ else
+ {
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC2P);
+ }
+
+
+ /* Set the Output Idle state */
+ if (TIM3_OCIdleState == TIM3_OCIdleState_Set)
+ {
+ TIM3->OISR |= TIM_OISR_OIS2;
+ }
+ else
+ {
+ TIM3->OISR &= (uint8_t)(~TIM_OISR_OIS2);
+ }
+
+ /* Set the Pulse value */
+ TIM3->CCR2H = (uint8_t)(TIM3_Pulse >> 8);
+ TIM3->CCR2L = (uint8_t)(TIM3_Pulse);
+}
+
+/**
+ * @brief Configures the Break feature, dead time, Lock level, the OSSI,
+ * and the AOE(automatic output enable).
+ * @param TIM3_OSSIState: Off-State Selection for Idle mode states.
+ * This parameter can be one of the following values:
+ * @arg TIM3_OSSIState_Enable: Off-State Selection for Idle mode enabled
+ * @arg TIM3_OSSIState_Disable: Off-State Selection for Idle mode disabled
+ * @param TIM3_LockLevel: Lock level.
+ * This parameter can be one of the following values:
+ * @arg TIM3_LockLevel_Off: Lock option disabled
+ * @arg TIM3_LockLevel_1: Select Lock Level 1
+ * @arg TIM3_LockLevel_2: Select Lock Level 2
+ * @arg TIM3_LockLevel_3: Select Lock Level 3
+ * @param TIM3_BreakState: Break Input enable/disable .
+ * This parameter can be one of the following values:
+ * @arg TIM3_BreakState_Disable: Break State disabled (break option disabled)
+ * @arg TIM3_BreakState_Enable: Break State enabled (break option enabled)
+ * @param TIM3_BreakPolarity: Break Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM3_BreakPolarity_High: if Break, channel polarity = High
+ * @arg TIM3_BreakPolarity_Low: if Break, channel polarity = Low
+ * @param TIM3_AutomaticOutput: TIM3 AOE Bit Set/Reset .
+ * This parameter can be one of the following values:
+ * @arg TIM3_AutomaticOutput_Enable: Automatic Output option enabled
+ * @arg TIM3_AutomaticOutput_Disable: Automatic Output option disabled
+ * @retval None
+ */
+void TIM3_BKRConfig(TIM3_OSSIState_TypeDef TIM3_OSSIState,
+ TIM3_LockLevel_TypeDef TIM3_LockLevel,
+ TIM3_BreakState_TypeDef TIM3_BreakState,
+ TIM3_BreakPolarity_TypeDef TIM3_BreakPolarity,
+ TIM3_AutomaticOutput_TypeDef TIM3_AutomaticOutput)
+
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_OSSI_STATE(TIM3_OSSIState));
+ assert_param(IS_TIM3_LOCK_LEVEL(TIM3_LockLevel));
+ assert_param(IS_TIM3_BREAK_STATE(TIM3_BreakState));
+ assert_param(IS_TIM3_BREAK_POLARITY(TIM3_BreakPolarity));
+ assert_param(IS_TIM3_AUTOMATIC_OUTPUT_STATE(TIM3_AutomaticOutput));
+
+
+
+ /* Set the Lock level, the Break enable Bit and the Polarity, the OSSI State,
+ the dead time value and the Automatic Output Enable Bit */
+ TIM3->BKR = (uint8_t)((uint8_t)((uint8_t)((uint8_t)((uint8_t)TIM3_OSSIState | (uint8_t)TIM3_LockLevel) | \
+ (uint8_t)((uint8_t)TIM3_BreakState | (uint8_t)TIM3_BreakPolarity)) | \
+ TIM3_AutomaticOutput));
+}
+
+/**
+ * @brief Enables or disables the TIM3 peripheral Main Outputs.
+ * @param NewState: The new state of the TIM3 peripheral.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM3_CtrlPWMOutputs(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the MOE Bit */
+
+ if (NewState != DISABLE)
+ {
+ TIM3->BKR |= TIM_BKR_MOE ;
+ }
+ else
+ {
+ TIM3->BKR &= (uint8_t)(~TIM_BKR_MOE) ;
+ }
+}
+
+/**
+ * @brief Selects the TIM3 Output Compare Mode. This function disables the
+ * selected channel before changing the Output Compare Mode. User has to
+ * enable this channel using TIM3_CCxCmd and TIM3_CCxNCmd functions.
+ * @param TIM3_Channel: Specifies the TIM3 Channel.
+ * This parameter can be one of the following values:
+ * @arg TIM3_Channel_1: Channel 1
+ * @arg TIM3_Channel_2: Channel 2
+ * @param TIM3_OCMode: Specifies the TIM3 Output Compare Mode.
+ * This parameter can be one of the following values:
+ * @arg TIM3_OCMode_Timing: Timing (Frozen) Mode
+ * @arg TIM3_OCMode_Active: Active Mode
+ * @arg TIM3_OCMode_Inactive: Inactive Mode
+ * @arg TIM3_OCMode_Toggle: Toggle Mode
+ * @arg TIM3_OCMode_PWM1: PWM Mode 1
+ * @arg TIM3_OCMode_PWM2: PWM Mode 2
+ * @retval None
+ */
+void TIM3_SelectOCxM(TIM3_Channel_TypeDef TIM3_Channel,
+ TIM3_OCMode_TypeDef TIM3_OCMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_CHANNEL(TIM3_Channel));
+ assert_param(IS_TIM3_OCM(TIM3_OCMode));
+
+ if (TIM3_Channel == TIM3_Channel_1)
+ {
+ /* Disable the Channel 1: Reset the CCE Bit */
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E);
+
+ /* Reset the Output Compare Bits */
+ TIM3->CCMR1 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Set the Output Compare Mode */
+ TIM3->CCMR1 |= (uint8_t)TIM3_OCMode;
+ }
+ else /* if (TIM3_Channel == TIM3_Channel_2) */
+ {
+ /* Disable the Channel 2: Reset the CCE Bit */
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E);
+
+ /* Reset the Output Compare Bits */
+ TIM3->CCMR2 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Set the Output Compare Mode */
+ TIM3->CCMR2 |= (uint8_t)TIM3_OCMode;
+ }
+}
+
+/**
+ * @brief Sets the TIM3 Capture Compare1 Register value.
+ * @param Compare: Specifies the Capture Compare1 register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM3_SetCompare1(uint16_t Compare)
+{
+ /* Set the Capture Compare1 Register value */
+ TIM3->CCR1H = (uint8_t)(Compare >> 8);
+ TIM3->CCR1L = (uint8_t)(Compare);
+}
+
+/**
+ * @brief Sets the TIM3 Capture Compare2 Register value.
+ * @param Compare: Specifies the Capture Compare2 register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM3_SetCompare2(uint16_t Compare)
+{
+ /* Set the Capture Compare2 Register value */
+ TIM3->CCR2H = (uint8_t)(Compare >> 8);
+ TIM3->CCR2L = (uint8_t)(Compare);
+}
+
+/**
+ * @brief Forces the TIM3 Channel1 output waveform to active or inactive level.
+ * @param TIM3_ForcedAction: Specifies the forced Action to be set to the output waveform.
+ * This parameter can be one of the following values:
+ * @arg TIM3_ForcedAction_Active: Output Reference is forced low
+ * @arg TIM3_ForcedAction_Inactive: Output Reference is forced high
+ * @retval None
+ */
+void TIM3_ForcedOC1Config(TIM3_ForcedAction_TypeDef TIM3_ForcedAction)
+{
+ uint8_t tmpccmr1 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_FORCED_ACTION(TIM3_ForcedAction));
+
+ tmpccmr1 = TIM3->CCMR1;
+
+ /* Reset the OCM Bits */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Configure The Forced output Mode */
+ tmpccmr1 |= (uint8_t)TIM3_ForcedAction;
+
+ TIM3->CCMR1 = tmpccmr1;
+}
+
+/**
+ * @brief Forces the TIM3 Channel2 output waveform to active or inactive level.
+ * @param TIM3_ForcedAction: Specifies the forced Action to be set to the output waveform.
+ * This parameter can be one of the following values:
+ * @arg TIM3_ForcedAction_Active: Output Reference is forced low
+ * @arg TIM3_ForcedAction_Inactive: Output Reference is forced high
+ * @retval None
+ */
+void TIM3_ForcedOC2Config(TIM3_ForcedAction_TypeDef TIM3_ForcedAction)
+{
+ uint8_t tmpccmr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_FORCED_ACTION(TIM3_ForcedAction));
+
+ tmpccmr2 = TIM3->CCMR2;
+
+ /* Reset the OCM Bits */
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Configure The Forced output Mode */
+ tmpccmr2 |= (uint8_t)TIM3_ForcedAction;
+
+ TIM3->CCMR2 = tmpccmr2;
+}
+
+/**
+ * @brief Enables or disables the TIM3 peripheral Preload Register on CCR1.
+ * @param NewState: The new state of the Capture Compare Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM3_OC1PreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC1PE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM3->CCMR1 |= TIM_CCMR_OCxPE ;
+ }
+ else
+ {
+ TIM3->CCMR1 &= (uint8_t)(~TIM_CCMR_OCxPE) ;
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM3 peripheral Preload Register on CCR2.
+ * @param NewState: The new state of the Capture Compare Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM3_OC2PreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC2PE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM3->CCMR2 |= TIM_CCMR_OCxPE ;
+ }
+ else
+ {
+ TIM3->CCMR2 &= (uint8_t)(~TIM_CCMR_OCxPE) ;
+ }
+}
+
+/**
+ * @brief Configures the TIM3 Capture Compare 1 Fast feature.
+ * @param NewState: The new state of the Output Compare Fast Enable bit.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM3_OC1FastConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC1FE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM3->CCMR1 |= TIM_CCMR_OCxFE ;
+ }
+ else
+ {
+ TIM3->CCMR1 &= (uint8_t)(~TIM_CCMR_OCxFE) ;
+ }
+}
+
+/**
+ * @brief Configures the TIM3 Capture Compare 2 Fast feature.
+ * @param NewState: The new state of the Output Compare Fast Enable bit.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+
+void TIM3_OC2FastConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC2FE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM3->CCMR2 |= TIM_CCMR_OCxFE ;
+ }
+ else
+ {
+ TIM3->CCMR2 &= (uint8_t)(~TIM_CCMR_OCxFE) ;
+ }
+}
+
+/**
+ * @brief Configures the TIM3 Channel 1 polarity.
+ * @param TIM3_OCPolarity: Specifies the OC1 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM3_OCPolarity_High: Output compare polarity = High
+ * @arg TIM3_OCPolarity_Low: Output compare polarity = Low
+ * @retval None
+ */
+void TIM3_OC1PolarityConfig(TIM3_OCPolarity_TypeDef TIM3_OCPolarity)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_OC_POLARITY(TIM3_OCPolarity));
+
+ /* Set or Reset the CC1P Bit */
+ if (TIM3_OCPolarity == TIM3_OCPolarity_Low)
+ {
+ TIM3->CCER1 |= TIM_CCER1_CC1P ;
+ }
+ else
+ {
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC1P) ;
+ }
+}
+
+/**
+ * @brief Configures the TIM3 Channel 2 polarity.
+ * @param TIM3_OCPolarity: Specifies the OC2 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM3_OCPolarity_High: Output compare polarity = High
+ * @arg TIM3_OCPolarity_Low: Output compare polarity = Low
+ * @retval None
+ */
+void TIM3_OC2PolarityConfig(TIM3_OCPolarity_TypeDef TIM3_OCPolarity)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_OC_POLARITY(TIM3_OCPolarity));
+
+ /* Set or Reset the CC2P Bit */
+ if (TIM3_OCPolarity == TIM3_OCPolarity_Low)
+ {
+ TIM3->CCER1 |= TIM_CCER1_CC2P ;
+ }
+ else
+ {
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC2P) ;
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM3 Capture Compare Channel x.
+ * @param TIM3_Channel: Specifies the TIM3 Channel.
+ * This parameter can be one of the following values:
+ * @arg TIM3_Channel_1: Channel 1
+ * @arg TIM3_Channel_2: Channel 2
+ * @param NewState: Specifies the TIM3 Channel CCxE bit new state.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM3_CCxCmd(TIM3_Channel_TypeDef TIM3_Channel,
+ FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_CHANNEL(TIM3_Channel));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (TIM3_Channel == TIM3_Channel_1)
+ {
+ /* Set or Reset the CC1E Bit */
+ if (NewState != DISABLE)
+ {
+ TIM3->CCER1 |= TIM_CCER1_CC1E ;
+ }
+ else
+ {
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E) ;
+ }
+
+ }
+ else /* if (TIM3_Channel == TIM3_Channel_2) */
+ {
+ /* Set or Reset the CC2E Bit */
+ if (NewState != DISABLE)
+ {
+ TIM3->CCER1 |= TIM_CCER1_CC2E;
+ }
+ else
+ {
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E) ;
+ }
+ }
+}
+
+/** @defgroup TIM3_Group3 Input Capture management functions
+ * @brief Input Capture management functions
+ *
+@verbatim
+ ===============================================================================
+ Input Capture management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM3 Driver: how to use it in Input Capture Mode
+ ===================================================================
+ To use the Timer in Input Capture mode, the following steps are mandatory:
+
+ 1. Enable TIM3 clock using CLK_PeripheralClockConfig(CLK_Peripheral_TIM3, ENABLE) function.
+
+ 2. Configure the TIM3 pins in input mode by configuring the corresponding GPIO pins
+
+ 3. Configure the Time base unit as described in the first part of this driver, if needed,
+ otherwise the Timer will run with the default configuration:
+ - Autoreload value = 0xFFFF
+ - Prescaler value = 0x0
+ - Counter mode = Up counting
+
+ 4. Call TIM3_ICInit() to configure the desired channel to measure only
+ frequency or duty cycle of the input signal using the corresponding configuration:
+ - TIM3 Channel: TIM3_Channel
+ - TIM3 Input Capture polarity: TIM3_ICPolarity
+ - TIM3 Input Capture selection: TIM3_ICSelection
+ - TIM3 Input Capture Prescaler: TIM3_ICPSC
+ - TIM3 Input Capture filter value
+ or,
+ Call TIM3_PWMIConfig() to configure the desired channels with the
+ corresponding configuration and to measure the frequency and the duty
+ cycle of the input signal.
+
+ 5. Enable global interrupts or the DMA to read the measured frequency.
+
+ 6. Enable the corresponding interrupt (or DMA request) to read the captured value,
+ using the function TIM3_ITConfig(TIM3_IT_CCx) (or TIM3_DMACmd(TIM3_DMASource_CCx))
+
+ 7. Call the TIM3_Cmd(ENABLE) function to enable the TIM3 counter.
+
+ 8. Use TIM3_GetCapturex() to read the captured value corresponding to
+ channel x.
+
+ Note1: All other functions can be used separately to modify, if needed,
+ a specific feature of the Timer.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the TIM3 peripheral according to the specified parameters.
+ * @param TIM3_Channel: TIM3 Channel
+ * This parameter can be one of the following values:
+ * @arg TIM3_Channel_1: Channel 1
+ * @arg TIM3_Channel_2: Channel 2
+ * @param TIM3_ICPolarity: Input Capture Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM3_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM3_ICSelection: Input Capture Selection
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICSelection_DirectTI: Input Capture mapped on the direct input
+ * @arg TIM3_ICSelection_IndirectTI: Input Capture mapped on the indirect input
+ * @arg TIM3_ICSelection_TRGI: Input Capture mapped on the Trigger Input
+ * @param TIM3_ICPrescaler: Input Capture Prescaler
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM3_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM3_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM3_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @param TIM3_ICFilter: This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+void TIM3_ICInit(TIM3_Channel_TypeDef TIM3_Channel,
+ TIM3_ICPolarity_TypeDef TIM3_ICPolarity,
+ TIM3_ICSelection_TypeDef TIM3_ICSelection,
+ TIM3_ICPSC_TypeDef TIM3_ICPrescaler,
+ uint8_t TIM3_ICFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_CHANNEL(TIM3_Channel));
+
+ if (TIM3_Channel == TIM3_Channel_1)
+ {
+ /* TI1 Configuration */
+ TI1_Config(TIM3_ICPolarity, TIM3_ICSelection, TIM3_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM3_SetIC1Prescaler(TIM3_ICPrescaler);
+ }
+ else /* if (TIM3_Channel == TIM3_Channel_2) */
+ {
+ /* TI2 Configuration */
+ TI2_Config(TIM3_ICPolarity, TIM3_ICSelection, TIM3_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM3_SetIC2Prescaler(TIM3_ICPrescaler);
+ }
+}
+
+/**
+ * @brief Configures the TIM3 peripheral in PWM Input Mode according to the
+ * specified parameters.
+ * @param TIM3_Channel: TIM3 Channel
+ * This parameter can be one of the following values:
+ * @arg TIM3_Channel_1: Channel 1
+ * @arg TIM3_Channel_2: Channel 2
+ * @param TIM3_ICPolarity: Input Capture Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM3_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM3_ICSelection: Input Capture Selection
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICSelection_DirectTI: Input Capture mapped on the direct input
+ * @arg TIM3_ICSelection_IndirectTI: Input Capture mapped on the indirect input
+ * @arg TIM3_ICSelection_TRGI: Input Capture mapped on the Trigger Input
+ * @param TIM3_ICPrescaler: Input Capture Prescaler
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM3_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM3_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM3_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @retval None
+ */
+void TIM3_PWMIConfig(TIM3_Channel_TypeDef TIM3_Channel,
+ TIM3_ICPolarity_TypeDef TIM3_ICPolarity,
+ TIM3_ICSelection_TypeDef TIM3_ICSelection,
+ TIM3_ICPSC_TypeDef TIM3_ICPrescaler,
+ uint8_t TIM3_ICFilter)
+{
+ uint8_t icpolarity = TIM3_ICPolarity_Rising;
+ uint8_t icselection = TIM3_ICSelection_DirectTI;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_CHANNEL(TIM3_Channel));
+
+ /* Select the Opposite Input Polarity */
+ if (TIM3_ICPolarity == TIM3_ICPolarity_Rising)
+ {
+ icpolarity = TIM3_ICPolarity_Falling;
+ }
+ else
+ {
+ icpolarity = TIM3_ICPolarity_Rising;
+ }
+
+ /* Select the Opposite Input */
+ if (TIM3_ICSelection == TIM3_ICSelection_DirectTI)
+ {
+ icselection = TIM3_ICSelection_IndirectTI;
+ }
+ else
+ {
+ icselection = TIM3_ICSelection_DirectTI;
+ }
+
+ if (TIM3_Channel == TIM3_Channel_1)
+ {
+ /* TI1 Configuration */
+ TI1_Config(TIM3_ICPolarity, TIM3_ICSelection,
+ TIM3_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM3_SetIC1Prescaler(TIM3_ICPrescaler);
+
+ /* TI2 Configuration */
+ TI2_Config((TIM3_ICPolarity_TypeDef)icpolarity, (TIM3_ICSelection_TypeDef)icselection, TIM3_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM3_SetIC2Prescaler(TIM3_ICPrescaler);
+ }
+ else
+ {
+ /* TI2 Configuration */
+ TI2_Config(TIM3_ICPolarity, TIM3_ICSelection,
+ TIM3_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM3_SetIC2Prescaler(TIM3_ICPrescaler);
+
+ /* TI1 Configuration */
+ TI1_Config((TIM3_ICPolarity_TypeDef)icpolarity, (TIM3_ICSelection_TypeDef)icselection, TIM3_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM3_SetIC1Prescaler(TIM3_ICPrescaler);
+ }
+}
+
+/**
+ * @brief Gets the TIM3 Input Capture 1 value.
+ * @param None
+ * @retval Capture Compare 1 Register value.
+ */
+uint16_t TIM3_GetCapture1(void)
+{
+ uint16_t tmpccr1 = 0;
+ uint8_t tmpccr1l, tmpccr1h;
+
+ tmpccr1h = TIM3->CCR1H;
+ tmpccr1l = TIM3->CCR1L;
+
+ tmpccr1 = (uint16_t)(tmpccr1l);
+ tmpccr1 |= (uint16_t)((uint16_t)tmpccr1h << 8);
+ /* Get the Capture 1 Register value */
+ return ((uint16_t)tmpccr1);
+}
+
+/**
+ * @brief Gets the TIM3 Input Capture 2 value.
+ * @param None
+ * @retval Capture Compare 2 Register value.
+ */
+uint16_t TIM3_GetCapture2(void)
+{
+ uint16_t tmpccr2 = 0;
+ uint8_t tmpccr2l, tmpccr2h;
+
+ tmpccr2h = TIM3->CCR2H;
+ tmpccr2l = TIM3->CCR2L;
+
+ tmpccr2 = (uint16_t)(tmpccr2l);
+ tmpccr2 |= (uint16_t)((uint16_t)tmpccr2h << 8);
+ /* Get the Capture 2 Register value */
+ return ((uint16_t)tmpccr2);
+}
+
+/**
+ * @brief Sets the TIM3 Input Capture 1 prescaler.
+ * @param TIM3_IC1Prescaler: Specifies the Input Capture prescaler new value
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM3_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM3_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM3_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @retval None
+ */
+void TIM3_SetIC1Prescaler(TIM3_ICPSC_TypeDef TIM3_IC1Prescaler)
+{
+ uint8_t tmpccmr1 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_IC_PRESCALER(TIM3_IC1Prescaler));
+
+ tmpccmr1 = TIM3->CCMR1;
+
+ /* Reset the IC1PSC Bits */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_ICxPSC);
+
+ /* Set the IC1PSC value */
+ tmpccmr1 |= (uint8_t)TIM3_IC1Prescaler;
+
+ TIM3->CCMR1 = tmpccmr1;
+}
+
+/**
+ * @brief Sets the TIM3 Input Capture 2 prescaler.
+ * @param TIM3_IC2Prescaler: Specifies the Input Capture prescaler new value
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM3_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM3_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM3_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @retval None
+ */
+void TIM3_SetIC2Prescaler(TIM3_ICPSC_TypeDef TIM3_IC2Prescaler)
+{
+ uint8_t tmpccmr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_IC_PRESCALER(TIM3_IC2Prescaler));
+
+ tmpccmr2 = TIM3->CCMR2;
+
+ /* Reset the IC2PSC Bits */
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_ICxPSC);
+
+ /* Set the IC2PSC value */
+ tmpccmr2 |= (uint8_t)TIM3_IC2Prescaler;
+
+ TIM3->CCMR2 = tmpccmr2;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Group4 Interrupts DMA and flags management functions
+ * @brief Interrupts, DMA and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts, DMA and flags management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the specified TIM3 interrupts.
+ * @param TIM3_IT: Specifies the TIM3 interrupts sources to be enabled or disabled.
+ * This parameter can be any combination of the following values:
+ * @arg TIM3_IT_Update: Update
+ * @arg TIM3_IT_CC1: Capture Compare Channel1
+ * @arg TIM3_IT_CC2: Capture Compare Channel2
+ * @arg TIM3_IT_Trigger: Trigger
+ * @arg TIM3_IT_Break: Break
+ * @param NewState: The new state of the TIM3 peripheral.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM3_ITConfig(TIM3_IT_TypeDef TIM3_IT, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_IT(TIM3_IT));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the Interrupt sources */
+ TIM3->IER |= (uint8_t)TIM3_IT;
+ }
+ else
+ {
+ /* Disable the Interrupt sources */
+ TIM3->IER &= (uint8_t)(~(uint8_t)TIM3_IT);
+ }
+}
+
+/**
+ * @brief Configures the TIM3 event to be generated by software.
+ * @param TIM3_EventSource: Specifies the event source.
+ * This parameter can be any combination of the following values:
+ * @arg TIM3_EventSource_Update: Update
+ * @arg TIM3_EventSource_CC1: Capture Compare Channel1
+ * @arg TIM3_EventSource_CC2: Capture Compare Channel2
+ * @arg TIM3_EventSource_Trigger: Trigger
+ * @arg TIM3_EventSource_Break: Break
+ * @retval None
+ */
+void TIM3_GenerateEvent(TIM3_EventSource_TypeDef TIM3_EventSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_EVENT_SOURCE((uint8_t)TIM3_EventSource));
+
+ /* Set the event sources */
+ TIM3->EGR |= (uint8_t)TIM3_EventSource;
+}
+
+/**
+ * @brief Checks whether the specified TIM3 flag is set or not.
+ * @param TIM3_FLAG: Specifies the flag to check.
+ * This parameter can be any combination of the following values:
+ * @arg TIM3_FLAG_Update: Update
+ * @arg TIM3_FLAG_CC1: Capture Compare Channel1
+ * @arg TIM3_FLAG_CC2: Capture Compare Channel2
+ * @arg TIM3_FLAG_Trigger: Trigger
+ * @arg TIM3_FLAG_Break: Break
+ * @arg TIM3_FLAG_CC1OF: Capture compare 1 over capture
+ * @arg TIM3_FLAG_CC2OF: Capture compare 2 over capture
+ * @retval FlagStatus: The new state of TIM3_FLAG (SET or RESET)
+ */
+FlagStatus TIM3_GetFlagStatus(TIM3_FLAG_TypeDef TIM3_FLAG)
+{
+ FlagStatus bitstatus = RESET;
+ uint8_t tim3_flag_l = 0, tim3_flag_h = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_GET_FLAG(TIM3_FLAG));
+
+ tim3_flag_l = (uint8_t)(TIM3->SR1 & (uint8_t)(TIM3_FLAG));
+ tim3_flag_h = (uint8_t)(TIM3->SR2 & (uint8_t)((uint16_t)TIM3_FLAG >> 8));
+
+ if ((uint8_t)(tim3_flag_l | tim3_flag_h) != 0)
+ {
+ bitstatus = SET;
+ }
+ else
+ {
+ bitstatus = RESET;
+ }
+ return ((FlagStatus)bitstatus);
+}
+
+/**
+ * @brief Clears the TIM’s pending flags.
+ * @param TIM3_FLAG: Specifies the flag to clear.
+ * This parameter can be any combination of the following values:
+ * @arg TIM3_FLAG_Update: Update
+ * @arg TIM3_FLAG_CC1: Capture Compare Channel1
+ * @arg TIM3_FLAG_CC2: Capture Compare Channel2
+ * @arg TIM3_FLAG_Trigger: Trigger
+ * @arg TIM3_FLAG_Break: Break
+ * @retval None
+ */
+void TIM3_ClearFlag(TIM3_FLAG_TypeDef TIM3_FLAG)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_CLEAR_FLAG((uint16_t)TIM3_FLAG));
+ /* Clear the flags (rc_w0) clear this bit by writing 0. Writing ‘1’ has no effect*/
+ TIM3->SR1 = (uint8_t)(~(uint8_t)(TIM3_FLAG));
+ TIM3->SR2 = (uint8_t)(~(uint8_t)((uint16_t)TIM3_FLAG >> 8));
+}
+
+/**
+ * @brief Checks whether the TIM3 interrupt has occurred or not.
+ * @param TIM3_IT: Specifies the TIM3 interrupt source to check.
+ * This parameter can be any combination of the following values:
+ * @arg TIM3_IT_Update: Update
+ * @arg TIM3_IT_CC1: Capture Compare Channel1
+ * @arg TIM3_IT_CC2: Capture Compare Channel2
+ * @arg TIM3_IT_Trigger: Trigger
+ * @arg TIM3_IT_Break: Break
+ * @retval ITStatus: The new state of the TIM3_IT (SET or RESET)
+ */
+ITStatus TIM3_GetITStatus(TIM3_IT_TypeDef TIM3_IT)
+{
+ ITStatus bitstatus = RESET;
+
+ uint8_t TIM3_itStatus = 0x0, TIM3_itEnable = 0x0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_GET_IT(TIM3_IT));
+
+ TIM3_itStatus = (uint8_t)(TIM3->SR1 & (uint8_t)TIM3_IT);
+
+ TIM3_itEnable = (uint8_t)(TIM3->IER & (uint8_t)TIM3_IT);
+
+ if ((TIM3_itStatus != (uint8_t)RESET ) && (TIM3_itEnable != (uint8_t)RESET))
+ {
+ bitstatus = (ITStatus)SET;
+ }
+ else
+ {
+ bitstatus = (ITStatus)RESET;
+ }
+ return ((ITStatus)bitstatus);
+}
+
+/**
+ * @brief Clears the TIM's interrupt pending bits.
+ * @param TIM3_IT: Specifies the pending bit to clear.
+ * This parameter can be any combination of the following values:
+ * @arg TIM3_IT_Update: Update
+ * @arg TIM3_IT_CC1: Capture Compare Channel1
+ * @arg TIM3_IT_CC2: Capture Compare Channel2
+ * @arg TIM3_IT_Trigger: Trigger
+ * @arg TIM3_IT_Break: Break
+ * @retval None
+ */
+void TIM3_ClearITPendingBit(TIM3_IT_TypeDef TIM3_IT)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_IT(TIM3_IT));
+
+ /* Clear the IT pending Bit */
+ TIM3->SR1 = (uint8_t)(~(uint8_t)TIM3_IT);
+}
+
+/**
+ * @brief Enables or disables the TIM3 DMA Requests.
+ * @param TIM3_DMASource: specifies the DMA Request sources.
+ * This parameter can be any combination of the following values:
+ * @arg TIM3_DMASource_Update: TIM3 DMA Update Request
+ * @arg TIM3_DMASource_CC1: TIM3 DMA CC1 Request
+ * @arg TIM3_DMASource_CC2: TIM3 DMA CC2 Request
+ * @param NewState: new state of the DMA Request sources.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM3_DMACmd( TIM3_DMASource_TypeDef TIM3_DMASource, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ assert_param(IS_TIM3_DMA_SOURCE(TIM3_DMASource));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the DMA sources */
+ TIM3->DER |= TIM3_DMASource;
+ }
+ else
+ {
+ /* Disable the DMA sources */
+ TIM3->DER &= (uint8_t)(~TIM3_DMASource);
+ }
+}
+
+/**
+ * @brief Selects the TIM3 peripheral Capture Compare DMA source.
+ * @param NewState: new state of the Capture Compare DMA source.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM3_SelectCCDMA(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Set the CCDS Bit */
+ TIM3->CR2 |= TIM_CR2_CCDS;
+ }
+ else
+ {
+ /* Reset the CCDS Bit */
+ TIM3->CR2 &= (uint8_t)(~TIM_CR2_CCDS);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Group5 Clocks management functions
+ * @brief Clocks management functions
+ *
+@verbatim
+ ===============================================================================
+ Clocks management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables the TIM3 internal Clock.
+ * @par Parameters:
+ * None
+ * @retval None
+ */
+void TIM3_InternalClockConfig(void)
+{
+ /* Disable slave mode to clock the prescaler directly with the internal clock */
+ TIM3->SMCR &= (uint8_t)(~TIM_SMCR_SMS);
+}
+
+/**
+ * @brief Configures the TIM3 Trigger as External Clock.
+ * @param TIM3_TIxExternalCLKSource: Specifies Trigger source.
+ * This parameter can be one of the following values:
+ * @arg TIM3_TIxExternalCLK1Source_TI1ED: External Clock mode 1 source = TI1ED
+ * @arg TIM3_TIxExternalCLK1Source_TI1: External Clock mode 1 source = TI1
+ * @arg TIM3_TIxExternalCLK1Source_TI2: External Clock mode 1 source = TI2
+ * @param TIM3_ICPolarity: Specifies the TIx Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM3_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param ICFilter: Specifies the filter value.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM3_TIxExternalClockConfig(TIM3_TIxExternalCLK1Source_TypeDef TIM3_TIxExternalCLKSource,
+ TIM3_ICPolarity_TypeDef TIM3_ICPolarity,
+ uint8_t ICFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_TIXCLK_SOURCE(TIM3_TIxExternalCLKSource));
+ assert_param(IS_TIM3_IC_POLARITY(TIM3_ICPolarity));
+ assert_param(IS_TIM3_IC_FILTER(ICFilter));
+
+ /* Configure the TIM3 Input Clock Source */
+ if (TIM3_TIxExternalCLKSource == TIM3_TIxExternalCLK1Source_TI2)
+ {
+ TI2_Config(TIM3_ICPolarity, TIM3_ICSelection_DirectTI, ICFilter);
+ }
+ else
+ {
+ TI1_Config(TIM3_ICPolarity, TIM3_ICSelection_DirectTI, ICFilter);
+ }
+
+ /* Select the Trigger source */
+ TIM3_SelectInputTrigger((TIM3_TRGSelection_TypeDef)TIM3_TIxExternalCLKSource);
+
+ /* Select the External clock mode1 */
+ TIM3->SMCR |= (uint8_t)(TIM3_SlaveMode_External1);
+}
+
+/**
+ * @brief Configures the TIM3 External clock Mode1.
+ * @param TIM3_ExtTRGPrescaler: Specifies the external Trigger Prescaler.
+ * This parameter can be one of the following values:
+ * @arg TIM3_ExtTRGPSC_OFF: No External Trigger prescaler
+ * @arg TIM3_ExtTRGPSC_DIV2: External Trigger prescaler = 2 (ETRP frequency divided by 2)
+ * @arg TIM3_ExtTRGPSC_DIV4: External Trigger prescaler = 4 (ETRP frequency divided by 4)
+ * @arg TIM3_ExtTRGPSC_DIV8: External Trigger prescaler = 8 (ETRP frequency divided by 8)
+ * @param TIM3_ExtTRGPolarity: Specifies the external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM3_ExtTRGPolarity_Inverted: External Trigger Polarity = inverted
+ * @arg TIM3_ExtTRGPolarity_NonInverted: External Trigger Polarity = non inverted
+ * @param ExtTRGFilter: Specifies the External Trigger Filter.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM3_ETRClockMode1Config(TIM3_ExtTRGPSC_TypeDef TIM3_ExtTRGPrescaler,
+ TIM3_ExtTRGPolarity_TypeDef TIM3_ExtTRGPolarity,
+ uint8_t ExtTRGFilter)
+{
+ /* Configure the ETR Clock source */
+ TIM3_ETRConfig(TIM3_ExtTRGPrescaler, TIM3_ExtTRGPolarity, ExtTRGFilter);
+
+ /* Select the External clock mode1 */
+ TIM3->SMCR &= (uint8_t)(~TIM_SMCR_SMS);
+ TIM3->SMCR |= (uint8_t)(TIM3_SlaveMode_External1);
+
+ /* Select the Trigger selection: ETRF */
+ TIM3->SMCR &= (uint8_t)(~TIM_SMCR_TS);
+ TIM3->SMCR |= (uint8_t)((TIM3_TRGSelection_TypeDef)TIM3_TRGSelection_ETRF);
+}
+
+/**
+ * @brief Configures the TIM3 External clock Mode2.
+ * @param TIM3_ExtTRGPrescaler: Specifies the external Trigger Prescaler.
+ * This parameter can be one of the following values:
+ * @arg TIM3_ExtTRGPSC_OFF: No External Trigger prescaler
+ * @arg TIM3_ExtTRGPSC_DIV2: External Trigger prescaler = 2 (ETRP frequency divided by 2)
+ * @arg TIM3_ExtTRGPSC_DIV4: External Trigger prescaler = 4 (ETRP frequency divided by 4)
+ * @arg TIM3_ExtTRGPSC_DIV8: External Trigger prescaler = 8 (ETRP frequency divided by 8)
+ * @param TIM3_ExtTRGPolarity: Specifies the external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM3_ExtTRGPolarity_Inverted: External Trigger Polarity = inverted
+ * @arg TIM3_ExtTRGPolarity_NonInverted: External Trigger Polarity = non inverted
+ * @param ExtTRGFilter: Specifies the External Trigger Filter.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM3_ETRClockMode2Config(TIM3_ExtTRGPSC_TypeDef TIM3_ExtTRGPrescaler,
+ TIM3_ExtTRGPolarity_TypeDef TIM3_ExtTRGPolarity,
+ uint8_t ExtTRGFilter)
+{
+ /* Configure the ETR Clock source */
+ TIM3_ETRConfig(TIM3_ExtTRGPrescaler, TIM3_ExtTRGPolarity, ExtTRGFilter);
+
+ /* Enable the External clock mode2 */
+ TIM3->ETR |= TIM_ETR_ECE ;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Group6 Synchronization management functions
+ * @brief Synchronization management functions
+ *
+@verbatim
+ ===============================================================================
+ Synchronization management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM3 Driver: how to use it in synchronization Mode
+ ===================================================================
+ Case of two/several Timers
+ **************************
+ 1. If TIM3 is used as master to other timers use the following functions:
+ - TIM3_SelectOutputTrigger()
+ - TIM3_SelectMasterSlaveMode()
+ 2. If TIM3 is used as slave to other timers use the following functions:
+ - TIM3_SelectInputTrigger()
+ - TIM3_SelectSlaveMode()
+
+ Case of Timers and external trigger (TRIG pin)
+ ********************************************
+ 1. Configure the External trigger using TIM3_ETRConfig()
+ 2. Configure the Slave Timer using the following functions:
+ - TIM3_SelectInputTrigger()
+ - TIM3_SelectSlaveMode()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Selects the TIM3 Input Trigger source.
+ * @param TIM3_InputTriggerSource: Specifies Input Trigger source.
+ * This parameter can be one of the following values:
+ * @arg TIM3_TRGSelection_TIM4: TRIG Input source = TIM TRIG Output
+ * @arg TIM3_TRGSelection_TIM1: TRIG Input source = TIM TRIG Output
+ * @arg TIM3_TRGSelection_TIM3: TRIG Input source = TIM TRIG Output
+ * @arg TIM3_TRGSelection_TIM2: TRIG Input source = TIM TRIG Output
+ * @arg TIM3_TRGSelection_TI1F_ED: TRIG Input source = TI1F_ED (TI1 Edge Detector)
+ * @arg TIM3_TRGSelection_TI1FP1: TRIG Input source = TI1FP1 (Filtered Timer Input 1)
+ * @arg TIM3_TRGSelection_TI2FP2: TRIG Input source = TI2FP2 (Filtered Timer Input 2)
+ * @arg TIM3_TRGSelection_ETRF: TRIG Input source = ETRF (External Trigger Input )
+ * @retval None
+ */
+void TIM3_SelectInputTrigger(TIM3_TRGSelection_TypeDef TIM3_InputTriggerSource)
+{
+ uint8_t tmpsmcr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_TRIGGER_SELECTION(TIM3_InputTriggerSource));
+
+ tmpsmcr = TIM3->SMCR;
+
+ /* Select the Trigger Source */
+ tmpsmcr &= (uint8_t)(~TIM_SMCR_TS);
+ tmpsmcr |= (uint8_t)TIM3_InputTriggerSource;
+
+ TIM3->SMCR = (uint8_t)tmpsmcr;
+}
+
+/**
+ * @brief Selects the TIM3 Trigger Output Mode.
+ * @param TIM3_TRGOSource: Specifies the Trigger Output source.
+ * This parameter can be one of the following values:
+ * @arg TIM3_TRGOSource_Reset: Trigger Output source = Reset
+ * @arg TIM3_TRGOSource_Enable: Trigger Output source = TIM3 is enabled
+ * @arg TIM3_TRGOSource_Update: Trigger Output source = Update event
+ * @arg TIM3_TRGOSource_OC1: Trigger Output source = output compare channel1
+ * @arg TIM3_TRGOSource_OC1REF: Trigger Output source = output compare channel 1 reference
+ * @arg TIM3_TRGOSource_OC2REF: Trigger Output source = output compare channel 2 reference
+ * @retval None
+ */
+void TIM3_SelectOutputTrigger(TIM3_TRGOSource_TypeDef TIM3_TRGOSource)
+{
+ uint8_t tmpcr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_TRGO_SOURCE(TIM3_TRGOSource));
+
+ tmpcr2 = TIM3->CR2;
+
+ /* Reset the MMS Bits */
+ tmpcr2 &= (uint8_t)(~TIM_CR2_MMS);
+
+ /* Select the TRGO source */
+ tmpcr2 |= (uint8_t)TIM3_TRGOSource;
+
+ TIM3->CR2 = tmpcr2;
+}
+
+/**
+ * @brief Selects the TIM3 Slave Mode.
+ * @param TIM3_SlaveMode: Specifies the TIM3 Slave Mode.
+ * This parameter can be one of the following values:
+ * @arg TIM3_SlaveMode_Reset: Slave Mode Selection = Reset
+ * @arg TIM3_SlaveMode_Gated: Slave Mode Selection = Gated
+ * @arg TIM3_SlaveMode_Trigger: Slave Mode Selection = Trigger
+ * @arg TIM3_SlaveMode_External1: Slave Mode Selection = External 1
+ * @retval None
+ */
+void TIM3_SelectSlaveMode(TIM3_SlaveMode_TypeDef TIM3_SlaveMode)
+{
+ uint8_t tmpsmcr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_SLAVE_MODE(TIM3_SlaveMode));
+
+ tmpsmcr = TIM3->SMCR;
+
+ /* Reset the SMS Bits */
+ tmpsmcr &= (uint8_t)(~TIM_SMCR_SMS);
+
+ /* Select the Slave Mode */
+ tmpsmcr |= (uint8_t)TIM3_SlaveMode;
+
+ TIM3->SMCR = tmpsmcr;
+}
+
+/**
+ * @brief Sets or Resets the TIM3 Master/Slave Mode.
+ * @param NewState: The new state of the synchronization between TIM3 and its slaves (through TRGO).
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM3_SelectMasterSlaveMode(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the MSM Bit */
+ if (NewState != DISABLE)
+ {
+ TIM3->SMCR |= TIM_SMCR_MSM;
+ }
+ else
+ {
+ TIM3->SMCR &= (uint8_t)(~TIM_SMCR_MSM);
+ }
+}
+
+/**
+ * @brief Configures the TIM3 External Trigger.
+ * @param TIM3_ExtTRGPrescaler: Specifies the external Trigger Prescaler.
+ * This parameter can be one of the following values:
+ * @arg TIM3_ExtTRGPSC_OFF: No External Trigger prescaler
+ * @arg TIM3_ExtTRGPSC_DIV2: External Trigger prescaler = 2 (ETRP frequency divided by 2)
+ * @arg TIM3_ExtTRGPSC_DIV4: External Trigger prescaler = 4 (ETRP frequency divided by 4)
+ * @arg TIM3_ExtTRGPSC_DIV8: External Trigger prescaler = 8 (ETRP frequency divided by 8)
+ * @param TIM3_ExtTRGPolarity: Specifies the external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM3_ExtTRGPolarity_Inverted: External Trigger Polarity = inverted
+ * @arg TIM3_ExtTRGPolarity_NonInverted: External Trigger Polarity = non inverted
+ * @param ExtTRGFilter: Specifies the External Trigger Filter.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM3_ETRConfig(TIM3_ExtTRGPSC_TypeDef TIM3_ExtTRGPrescaler,
+ TIM3_ExtTRGPolarity_TypeDef TIM3_ExtTRGPolarity,
+ uint8_t ExtTRGFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM3_EXT_PRESCALER(TIM3_ExtTRGPrescaler));
+ assert_param(IS_TIM3_EXT_POLARITY(TIM3_ExtTRGPolarity));
+ assert_param(IS_TIM3_EXT_FILTER(ExtTRGFilter));
+
+ /* Set the Prescaler, the Filter value and the Polarity */
+ TIM3->ETR |= (uint8_t)((uint8_t)((uint8_t)TIM3_ExtTRGPrescaler | (uint8_t)TIM3_ExtTRGPolarity)
+ | (uint8_t)ExtTRGFilter);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM3_Group7 Specific interface management functions
+ * @brief Specific interface management functions
+ *
+@verbatim
+ ===============================================================================
+ Specific interface management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures the TIM3 Encoder Interface.
+ * @param TIM3_EncoderMode: Specifies the TIM3 Encoder Mode.
+ * This parameter can be one of the following values:
+ * @arg TIM3_EncoderMode_TI1: Encoder mode 1
+ * @arg TIM3_EncoderMode_TI2: Encoder mode 2
+ * @arg TIM3_EncoderMode_TI12: Encoder mode 3
+ * @param TIM3_IC1Polarity: Specifies the IC1 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM3_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM3_IC2Polarity: Specifies the IC2 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM3_ICPolarity_Falling: Input Capture on Falling Edge
+ * @retval None
+ */
+void TIM3_EncoderInterfaceConfig(TIM3_EncoderMode_TypeDef TIM3_EncoderMode,
+ TIM3_ICPolarity_TypeDef TIM3_IC1Polarity,
+ TIM3_ICPolarity_TypeDef TIM3_IC2Polarity)
+{
+ uint8_t tmpsmcr = 0;
+ uint8_t tmpccmr1 = 0;
+ uint8_t tmpccmr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_ENCODER_MODE(TIM3_EncoderMode));
+ assert_param(IS_TIM3_IC_POLARITY(TIM3_IC1Polarity));
+ assert_param(IS_TIM3_IC_POLARITY(TIM3_IC2Polarity));
+
+ tmpsmcr = TIM3->SMCR;
+ tmpccmr1 = TIM3->CCMR1;
+ tmpccmr2 = TIM3->CCMR2;
+
+ /* Set the encoder Mode */
+ tmpsmcr &= (uint8_t)(TIM_SMCR_MSM | TIM_SMCR_TS) ;
+ tmpsmcr |= (uint8_t)TIM3_EncoderMode;
+
+ /* Select the Capture Compare 1 and the Capture Compare 2 as input */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_CCxS);
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_CCxS);
+ tmpccmr1 |= TIM_CCMR_TIxDirect_Set;
+ tmpccmr2 |= TIM_CCMR_TIxDirect_Set;
+
+ /* Set the TI1 and the TI2 Polarities */
+ if (TIM3_IC1Polarity == TIM3_ICPolarity_Falling)
+ {
+ TIM3->CCER1 |= TIM_CCER1_CC1P ;
+ }
+ else
+ {
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC1P) ;
+ }
+
+ if (TIM3_IC2Polarity == TIM3_ICPolarity_Falling)
+ {
+ TIM3->CCER1 |= TIM_CCER1_CC2P ;
+ }
+ else
+ {
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC2P) ;
+ }
+
+ TIM3->SMCR = tmpsmcr;
+ TIM3->CCMR1 = tmpccmr1;
+ TIM3->CCMR2 = tmpccmr2;
+}
+
+/**
+ * @brief Enables or Disables the TIM’s Hall sensor interface.
+ * @param NewState: The new state of the TIM3 Hall sensor interface.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM3_SelectHallSensor(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the TI1S Bit */
+ if (NewState != DISABLE)
+ {
+ TIM3->CR2 |= TIM_CR2_TI1S;
+ }
+ else
+ {
+ TIM3->CR2 &= (uint8_t)(~TIM_CR2_TI1S);
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Configure the TI1 as Input.
+ * @param TIM3_ICPolarity: Input Capture Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM3_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM3_ICSelection: Specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICSelection_DirectTI: Input Capture mapped on the direct input
+ * @arg TIM3_ICSelection_IndirectTI: Input Capture mapped on the indirect input
+ * @arg TIM3_ICSelection_TRGI: Input Capture mapped on the Trigger Input
+ * @param TIM3_ICFilter: Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TI1_Config(TIM3_ICPolarity_TypeDef TIM3_ICPolarity, \
+ TIM3_ICSelection_TypeDef TIM3_ICSelection, \
+ uint8_t TIM3_ICFilter)
+{
+ uint8_t tmpccmr1 = 0;
+ uint8_t tmpicpolarity = TIM3_ICPolarity;
+ tmpccmr1 = TIM3->CCMR1;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_IC_POLARITY(TIM3_ICPolarity));
+ assert_param(IS_TIM3_IC_SELECTION(TIM3_ICSelection));
+ assert_param(IS_TIM3_IC_FILTER(TIM3_ICFilter));
+
+ /* Disable the Channel 1: Reset the CCE Bit */
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E);
+
+ /* Select the Input and set the filter */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_CCxS) & (uint8_t)(~TIM_CCMR_ICxF);
+ tmpccmr1 |= (uint8_t)(((uint8_t)(TIM3_ICSelection)) | ((uint8_t)(TIM3_ICFilter << 4)));
+
+ TIM3->CCMR1 = tmpccmr1;
+
+ /* Select the Polarity */
+ if (tmpicpolarity == (uint8_t)(TIM3_ICPolarity_Falling))
+ {
+ TIM3->CCER1 |= TIM_CCER1_CC1P;
+ }
+ else
+ {
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC1P);
+ }
+
+ /* Set the CCE Bit */
+ TIM3->CCER1 |= TIM_CCER1_CC1E;
+}
+
+/**
+ * @brief Configure the TI2 as Input.
+ * @param TIM3_ICPolarity: Input Capture Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM3_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM3_ICSelection: Specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM3_ICSelection_DirectTI: Input Capture mapped on the direct input
+ * @arg TIM3_ICSelection_IndirectTI: Input Capture mapped on the indirect input
+ * @arg TIM3_ICSelection_TRGI: Input Capture mapped on the Trigger Input
+ * @param TIM3_ICFilter: Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TI2_Config(TIM3_ICPolarity_TypeDef TIM3_ICPolarity,
+ TIM3_ICSelection_TypeDef TIM3_ICSelection,
+ uint8_t TIM3_ICFilter)
+{
+ uint8_t tmpccmr2 = 0;
+ uint8_t tmpicpolarity = TIM3_ICPolarity;
+
+ /* Check the parameters */
+ assert_param(IS_TIM3_IC_POLARITY(TIM3_ICPolarity));
+ assert_param(IS_TIM3_IC_SELECTION(TIM3_ICSelection));
+ assert_param(IS_TIM3_IC_FILTER(TIM3_ICFilter));
+
+ tmpccmr2 = TIM3->CCMR2;
+
+ /* Disable the Channel 2: Reset the CCE Bit */
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E);
+
+ /* Select the Input and set the filter */
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_CCxS) & (uint8_t)(~TIM_CCMR_ICxF);
+ tmpccmr2 |= (uint8_t)(((uint8_t)(TIM3_ICSelection)) | ((uint8_t)(TIM3_ICFilter << 4)));
+
+ TIM3->CCMR2 = tmpccmr2;
+
+ /* Select the Polarity */
+ if (tmpicpolarity == TIM3_ICPolarity_Falling)
+ {
+ TIM3->CCER1 |= TIM_CCER1_CC2P ;
+ }
+ else
+ {
+ TIM3->CCER1 &= (uint8_t)(~TIM_CCER1_CC2P) ;
+ }
+
+ /* Set the CCE Bit */
+ TIM3->CCER1 |= TIM_CCER1_CC2E;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim4.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim4.c
new file mode 100644
index 00000000..b01445cf
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim4.c
@@ -0,0 +1,762 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_tim4.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the TIM4 peripheral:
+ * - TimeBase management
+ * - Interrupts, DMA and flags management
+ * - Clocks management
+ * - Synchronization management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * This driver provides functions to configure and initialize the TIM4
+ * peripheral
+ * These functions are split in 4 groups:
+ *
+ * 1. TIM4 TimeBase management: this group includes all needed functions
+ * to configure the TIM Timebase unit:
+ * - Set/Get Prescaler
+ * - Set/Get Autoreload
+ * - Select the One Pulse mode
+ * - Update Request Configuration
+ * - Update Disable Configuration
+ * - Auto-Preload Configuration
+ * - Enable/Disable the counter
+ *
+ * 2. TIM4 interrupts, DMA and flags management
+ * - Enable/Disable interrupt sources
+ * - Get flags status
+ * - Clear flags/ Pending bits
+ * - Enable/Disable DMA requests
+ *
+ * 3. TIM4 clocks management: this group includes all needed functions
+ * to configure the clock controller unit:
+ * - Select internal clock
+ *
+ * 4. TIM4 synchronization management: this group includes all needed
+ * functions to configure the Synchronization unit:
+ * - Select Input Trigger
+ * - Select Output Trigger
+ * - Select Master Slave Mode
+ *
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_tim4.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup TIM4
+ * @brief TIM4 driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup TIM4_Private_Functions
+ * @{
+ */
+
+/** @defgroup TIM4_Group1 TimeBase management functions
+ * @brief TimeBase management functions
+ *
+@verbatim
+ ===============================================================================
+ TimeBase management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM4 Driver: how to use it in Timing(Time base) Mode
+ ===================================================================
+ To use the Timer in Timing(Time base) mode, the following steps are mandatory:
+
+ 1. Enable TIM4 clock using CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, ENABLE) function.
+
+ 2. Call TIM4_TimeBaseInit() to configure the Time Base unit with the
+ corresponding configuration.
+
+ 3. Enable global interrupts if you need to generate the update interrupt.
+
+ 4. Enable the corresponding interrupt using the function TIM4_ITConfig(TIM4_IT_Update)
+
+ 5. Call the TIM4_Cmd(ENABLE) function to enable the TIM4 counter.
+
+ Note1: All other functions can be used separately to modify, if needed,
+ a specific feature of the Timer.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the TIM4 peripheral registers to their default reset values.
+ * @param None
+ * @retval None
+ */
+void TIM4_DeInit(void)
+{
+ TIM4->CR1 = TIM4_CR1_RESET_VALUE;
+ TIM4->CR2 = TIM4_CR2_RESET_VALUE;
+ TIM4->SMCR = TIM4_SMCR_RESET_VALUE;
+ TIM4->IER = TIM4_IER_RESET_VALUE;
+ TIM4->CNTR = TIM4_CNTR_RESET_VALUE;
+ TIM4->PSCR = TIM4_PSCR_RESET_VALUE;
+ TIM4->ARR = TIM4_ARR_RESET_VALUE;
+ TIM4->SR1 = TIM4_SR1_RESET_VALUE;
+}
+
+/**
+ * @brief Initializes the TIM4 Time Base Unit according to the specified parameters.
+ * @param TIM4_Prescaler: Prescaler
+ * This parameter can be one of the following values:
+ * @arg TIM4_Prescaler_1: Time base Prescaler = 1 (No effect)
+ * @arg TIM4_Prescaler_2: Time base Prescaler = 2
+ * @arg TIM4_Prescaler_4: Time base Prescaler = 4
+ * @arg TIM4_Prescaler_8: Time base Prescaler = 8
+ * @arg TIM4_Prescaler_16: Time base Prescaler = 16
+ * @arg TIM4_Prescaler_32: Time base Prescaler = 32
+ * @arg TIM4_Prescaler_64: Time base Prescaler = 64
+ * @arg TIM4_Prescaler_128: Time base Prescaler = 128
+ * @arg TIM4_Prescaler_256: Time base Prescaler = 256
+ * @arg TIM4_Prescaler_512: Time base Prescaler = 512
+ * @arg TIM4_Prescaler_1024: Time base Prescaler = 1024
+ * @arg TIM4_Prescaler_2048: Time base Prescaler = 2048
+ * @arg TIM4_Prescaler_4096: Time base Prescaler = 4096
+ * @arg TIM4_Prescaler_8192: Time base Prescaler = 8192
+ * @arg TIM4_Prescaler_16384: Time base Prescaler = 16384
+ * @arg TIM4_Prescaler_32768: Time base Prescaler = 32768
+ * @param TIM4_Period: This parameter must be a value between 0x00 and 0xFF.
+ * @retval None
+ */
+void TIM4_TimeBaseInit(TIM4_Prescaler_TypeDef TIM4_Prescaler,
+ uint8_t TIM4_Period)
+{
+ /* Check TIM4 prescaler value */
+ assert_param(IS_TIM4_Prescaler(TIM4_Prescaler));
+ /* Set the Autoreload value */
+ TIM4->ARR = (uint8_t)(TIM4_Period);
+ /* Set the Prescaler value */
+ TIM4->PSCR = (uint8_t)(TIM4_Prescaler);
+
+ /* Generate an update event to reload the Prescaler value immediately */
+ TIM4->EGR = TIM4_EventSource_Update;
+}
+
+/**
+ * @brief Configures the TIM4 Prescaler.
+ * @param Prescaler: Specifies the Prescaler Register value
+ * This parameter can be one of the following values:
+ * @arg TIM4_Prescaler_1: Time base Prescaler = 1 (No effect)
+ * @arg TIM4_Prescaler_2: Time base Prescaler = 2
+ * @arg TIM4_Prescaler_4: Time base Prescaler = 4
+ * @arg TIM4_Prescaler_8: Time base Prescaler = 8
+ * @arg TIM4_Prescaler_16: Time base Prescaler = 16
+ * @arg TIM4_Prescaler_32: Time base Prescaler = 32
+ * @arg TIM4_Prescaler_64: Time base Prescaler = 64
+ * @arg TIM4_Prescaler_128: Time base Prescaler = 128
+ * @arg TIM4_Prescaler_256: Time base Prescaler = 256
+ * @arg TIM4_Prescaler_512: Time base Prescaler = 512
+ * @arg TIM4_Prescaler_1024: Time base Prescaler = 1024
+ * @arg TIM4_Prescaler_2048: Time base Prescaler = 2048
+ * @arg TIM4_Prescaler_4096: Time base Prescaler = 4096
+ * @arg TIM4_Prescaler_8192: Time base Prescaler = 8192
+ * @arg TIM4_Prescaler_16384: Time base Prescaler = 16384
+ * @arg TIM4_Prescaler_32768: Time base Prescaler = 32768
+ * @param TIM4_PSCReloadMode: Specifies the TIM4 Prescaler Reload mode.
+ * This parameter can be one of the following values:
+ * @arg TIM4_PSCReloadMode_Update: Prescaler value is reloaded at every update
+ * @arg TIM4_PSCReloadMode_Immediate: Prescaler value is reloaded immediately
+ * @retval None
+ */
+void TIM4_PrescalerConfig(TIM4_Prescaler_TypeDef Prescaler,
+ TIM4_PSCReloadMode_TypeDef TIM4_PSCReloadMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM4_Prescaler_RELOAD(TIM4_PSCReloadMode));
+ assert_param(IS_TIM4_Prescaler(Prescaler));
+
+ /* Set the Prescaler value */
+ TIM4->PSCR = (uint8_t) Prescaler;
+
+ /* Set or reset the UG Bit */
+ if (TIM4_PSCReloadMode == TIM4_PSCReloadMode_Immediate)
+ {
+ TIM4->EGR |= TIM4_EGR_UG ;
+ }
+ else
+ {
+ TIM4->EGR &= (uint8_t)(~TIM4_EGR_UG) ;
+ }
+}
+
+/**
+ * @brief Sets the TIM4 Counter Register value.
+ * @param Counter: Specifies the Counter register new value.
+ * This parameter is between 0x00 and 0xFF.
+ * @retval None
+ */
+void TIM4_SetCounter(uint8_t Counter)
+{
+ /* Set the Counter Register value */
+ TIM4->CNTR = (uint8_t)(Counter);
+}
+
+/**
+ * @brief Sets the TIM4 Autoreload Register value.
+ * @param Autoreload: Specifies the Autoreload register new value.
+ * This parameter is between 0x00 and 0xFF.
+ * @retval None
+ */
+void TIM4_SetAutoreload(uint8_t Autoreload)
+{
+ /* Set the Autoreload Register value */
+ TIM4->ARR = (uint8_t)(Autoreload);
+}
+
+/**
+ * @brief Gets the TIM4 Counter value.
+ * @param None
+ * @retval Counter Register value.
+ */
+uint8_t TIM4_GetCounter(void)
+{
+ uint8_t tmpcntr = 0;
+ tmpcntr = TIM4->CNTR;
+ /* Get the Counter Register value */
+ return ((uint8_t)tmpcntr);
+}
+
+/**
+ * @brief Gets the TIM4 Prescaler value.
+ * @param None
+ * @retval TIM4 Prescaler can be one of the following values:
+ * - TIM4_Prescaler_1: Time base Prescaler = 1 (No effect)
+ * - TIM4_Prescaler_2: Time base Prescaler = 2
+ * - TIM4_Prescaler_4: Time base Prescaler = 4
+ * - TIM4_Prescaler_8: Time base Prescaler = 8
+ * - TIM4_Prescaler_16: Time base Prescaler = 16
+ * - TIM4_Prescaler_32: Time base Prescaler = 32
+ * - TIM4_Prescaler_64: Time base Prescaler = 64
+ * - TIM4_Prescaler_128: Time base Prescaler = 128
+ * - TIM4_Prescaler_256: Time base Prescaler = 256
+ * - TIM4_Prescaler_512: Time base Prescaler = 512
+ * - TIM4_Prescaler_1024: Time base Prescaler = 1024
+ * - TIM4_Prescaler_2048: Time base Prescaler = 2048
+ * - TIM4_Prescaler_4096: Time base Prescaler = 4096
+ * - TIM4_Prescaler_8192: Time base Prescaler = 8192
+ * - TIM4_Prescaler_16384: Time base Prescaler = 16384
+ * - TIM4_Prescaler_32768: Time base Prescaler = 32768
+ */
+TIM4_Prescaler_TypeDef TIM4_GetPrescaler(void)
+{
+ /* Get the Prescaler Register value */
+ return ((TIM4_Prescaler_TypeDef)TIM4->PSCR);
+}
+
+/**
+ * @brief Enables or Disables the TIM4 Update event.
+ * @param NewState: The new state of the TIM4 peripheral Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM4_UpdateDisableConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the UDIS Bit */
+ if (NewState != DISABLE)
+ {
+ TIM4->CR1 |= TIM4_CR1_UDIS ;
+ }
+ else
+ {
+ TIM4->CR1 &= (uint8_t)(~TIM4_CR1_UDIS) ;
+ }
+}
+
+/**
+ * @brief Selects the TIM4 Update Request Interrupt source.
+ * @param TIM4_UpdateSource: Specifies the Update source.
+ * This parameter can be one of the following values:
+ * @arg TIM4_UpdateSource_Global: Global Update request source
+ * @arg TIM4_UpdateSource_Regular: Regular Update request source
+ * @retval None
+ */
+void TIM4_UpdateRequestConfig(TIM4_UpdateSource_TypeDef TIM4_UpdateSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM4_UPDATE_SOURCE(TIM4_UpdateSource));
+
+ /* Set or Reset the URS Bit */
+ if (TIM4_UpdateSource == TIM4_UpdateSource_Regular)
+ {
+ TIM4->CR1 |= TIM4_CR1_URS ;
+ }
+ else
+ {
+ TIM4->CR1 &= (uint8_t)(~TIM4_CR1_URS) ;
+ }
+}
+
+/**
+ * @brief Enables or disables TIM4 peripheral Preload register on ARR.
+ * @param NewState: The new state of the TIM4 peripheral Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM4_ARRPreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the ARPE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM4->CR1 |= TIM4_CR1_ARPE ;
+ }
+ else
+ {
+ TIM4->CR1 &= (uint8_t)(~TIM4_CR1_ARPE) ;
+ }
+}
+
+/**
+ * @brief Selects the TIM4’s One Pulse Mode.
+ * @param TIM4_OPMode: Specifies the OPM Mode to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM4_OPMode_Single: Single one Pulse mode (OPM Active)
+ * @arg TIM4_OPMode_Repetitive: Repetitive Pulse mode (OPM inactive)
+ * @retval None
+ */
+void TIM4_SelectOnePulseMode(TIM4_OPMode_TypeDef TIM4_OPMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM4_OPM_MODE(TIM4_OPMode));
+
+ /* Set or Reset the OPM Bit */
+ if (TIM4_OPMode == TIM4_OPMode_Single)
+ {
+ TIM4->CR1 |= TIM4_CR1_OPM ;
+ }
+ else
+ {
+ TIM4->CR1 &= (uint8_t)(~TIM4_CR1_OPM) ;
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM4 peripheral.
+ * @param NewState: The new state of the TIM4 peripheral.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM4_Cmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* set or Reset the CEN Bit */
+ if (NewState != DISABLE)
+ {
+ TIM4->CR1 |= TIM4_CR1_CEN ;
+ }
+ else
+ {
+ TIM4->CR1 &= (uint8_t)(~TIM4_CR1_CEN) ;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM4_Group2 Interrupts DMA and flags management functions
+ * @brief Interrupts, DMA and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts, DMA and flags management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the specified TIM4 interrupts.
+ * @param TIM4_IT: Specifies the TIM4 interrupts sources to be enabled or disabled.
+ * This parameter can be one of the following values:
+ * @arg TIM4_IT_Update: Update
+ * @arg TIM4_IT_Trigger: Trigger
+ * @param NewState: The new state of the TIM4 peripheral.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM4_ITConfig(TIM4_IT_TypeDef TIM4_IT, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM4_IT(TIM4_IT));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the Interrupt sources */
+ TIM4->IER |= (uint8_t)TIM4_IT;
+ }
+ else
+ {
+ /* Disable the Interrupt sources */
+ TIM4->IER &= (uint8_t)(~(uint8_t)TIM4_IT);
+ }
+}
+
+/**
+ * @brief Configures the TIM4 event to be generated by software.
+ * @param TIM4_EventSource: Specifies the event source.
+ * This parameter can be one of the following values:
+ * @arg TIM4_EventSource_Update: Update
+ * @arg TIM4_EventSource_Trigger: Trigger
+ * @retval None
+ */
+void TIM4_GenerateEvent(TIM4_EventSource_TypeDef TIM4_EventSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM4_EVENT_SOURCE((uint8_t)TIM4_EventSource));
+
+ /* Set the event sources */
+ TIM4->EGR |= (uint8_t)TIM4_EventSource;
+}
+
+/**
+ * @brief Checks whether the specified TIM4 flag is set or not.
+ * @param TIM4_FLAG: Specifies the flag to check.
+ * This parameter can be one of the following values:
+ * @arg TIM4_FLAG_Update: Update
+ * @arg TIM4_FLAG_Trigger: Trigger
+ * @retval FlagStatus: The new state of TIM4_FLAG.
+ * This parameter can be SET or RESET.
+ */
+FlagStatus TIM4_GetFlagStatus(TIM4_FLAG_TypeDef TIM4_FLAG)
+{
+ FlagStatus bitstatus = RESET;
+
+ /* Check the parameters */
+ assert_param(IS_TIM4_GET_FLAG(TIM4_FLAG));
+
+ if ((TIM4->SR1 & (uint8_t)TIM4_FLAG) != 0)
+ {
+ bitstatus = SET;
+ }
+ else
+ {
+ bitstatus = RESET;
+ }
+ return ((FlagStatus)bitstatus);
+}
+
+/**
+ * @brief Clears the TIM’s pending flags.
+ * @param TIM4_FLAG: Specifies the flag to clear.
+ * This parameter can be one of the following values:
+ * @arg TIM4_FLAG_Update: Update
+ * @arg TIM4_FLAG_Trigger: Trigger
+ * @retval None
+ */
+void TIM4_ClearFlag(TIM4_FLAG_TypeDef TIM4_FLAG)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM4_CLEAR_FLAG((uint8_t)TIM4_FLAG));
+ /* Clear the flags (rc_w0) clear this bit by writing 0. Writing ‘1’ has no effect*/
+ TIM4->SR1 = (uint8_t)(~((uint8_t)TIM4_FLAG));
+}
+
+/**
+ * @brief Checks whether the TIM4 interrupt has occurred or not.
+ * @param TIM4_IT: Specifies the TIM4 interrupt source to check.
+ * This parameter can be one of the following values:
+ * @arg TIM4_IT_Update: Update
+ * @arg TIM4_IT_Trigger: Trigger
+ * @retval ITStatus: The new state of the TIM4_IT.
+ * This parameter can be SET or RESET
+ */
+
+ITStatus TIM4_GetITStatus(TIM4_IT_TypeDef TIM4_IT)
+{
+ ITStatus bitstatus = RESET;
+
+ uint8_t itStatus = 0x0, itEnable = 0x0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM4_GET_IT(TIM4_IT));
+
+ itStatus = (uint8_t)(TIM4->SR1 & (uint8_t)TIM4_IT);
+
+ itEnable = (uint8_t)(TIM4->IER & (uint8_t)TIM4_IT);
+
+ if ((itStatus != (uint8_t)RESET ) && (itEnable != (uint8_t)RESET ))
+ {
+ bitstatus = (ITStatus)SET;
+ }
+ else
+ {
+ bitstatus = (ITStatus)RESET;
+ }
+ return ((ITStatus)bitstatus);
+}
+
+/**
+ * @brief Clears the TIM4's interrupt pending bits.
+ * @param TIM4_IT: Specifies the pending bit to clear.
+ * This parameter can be one of the following values:
+ * @arg TIM4_IT_Update: Update
+ * @arg TIM4_IT_Trigger: Trigger
+ * @retval None
+ */
+void TIM4_ClearITPendingBit(TIM4_IT_TypeDef TIM4_IT)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM4_IT(TIM4_IT));
+
+ /* Clear the IT pending Bit */
+ TIM4->SR1 = (uint8_t)(~(uint8_t)TIM4_IT);
+}
+
+/**
+ * @brief Enables or disables the TIMx’s DMA Requests.
+ * @param TIM4_DMASources: specifies the DMA Request sources.
+ * This parameter can be one of the following values:
+ * @arg TIM4_DMASource_Update: Update
+ * @param NewState: new state of the DMA Request sources.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM4_DMACmd( TIM4_DMASource_TypeDef TIM4_DMASource, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ assert_param(IS_TIM4_DMA_SOURCE(TIM4_DMASource));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the DMA sources */
+ TIM4->DER |= (uint8_t)TIM4_DMASource;
+ }
+ else
+ {
+ /* Disable the DMA sources */
+ TIM4->DER &= (uint8_t)~TIM4_DMASource;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM4_Group3 Clocks management functions
+ * @brief Clocks management functions
+ *
+@verbatim
+ ===============================================================================
+ Clocks management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables the TIM4 internal Clock.
+ * @param None
+ * @retval None
+ */
+void TIM4_InternalClockConfig(void)
+{
+ /* Disable slave mode to clock the prescaler directly with the internal clock */
+ TIM4->SMCR &= (uint8_t)(~TIM4_SMCR_SMS);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM4_Group4 Synchronization management functions
+ * @brief Synchronization management functions
+ *
+@verbatim
+ ===============================================================================
+ Synchronization management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM4 Driver: how to use it in synchronization Mode
+ ===================================================================
+ Case of two/several Timers
+ **************************
+ 1. If TIM4 is used as master to other timers use the following functions:
+ - TIM4_SelectOutputTrigger()
+ - TIM4_SelectMasterSlaveMode()
+ 2. If TIM4 is used as slave to other timers use the following functions:
+ - TIM4_SelectInputTrigger()
+ - TIM4_SelectSlaveMode()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Selects the TIM4 Input Trigger source.
+ * @param TIM4_InputTriggerSource: Specifies Input Trigger source.
+ * This parameter can be one of the following values:
+ * @arg TIM4_TRGSelection_TIM5: TRIG Input source = TIM5 TRIG Output
+ * @arg TIM4_TRGSelection_TIM1: TRIG Input source = TIM1 TRIG Output
+ * @arg TIM4_TRGSelection_TIM3: TRIG Input source = TIM3 TRIG Output
+ * @arg TIM4_TRGSelection_TIM2: TRIG Input source = TIM2 TRIG Output
+ * @retval None
+ */
+void TIM4_SelectInputTrigger(TIM4_TRGSelection_TypeDef TIM4_InputTriggerSource)
+{
+ uint8_t tmpsmcr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM4_TRIGGER_SELECTION(TIM4_InputTriggerSource));
+
+ tmpsmcr = TIM4->SMCR;
+
+ /* Select the Trigger Source */
+ tmpsmcr &= (uint8_t)(~TIM4_SMCR_TS);
+ tmpsmcr |= (uint8_t)TIM4_InputTriggerSource;
+
+ TIM4->SMCR = (uint8_t)tmpsmcr;
+}
+
+/**
+ * @brief Selects the TIM4 Trigger Output Mode.
+ * @param TIM4_TRGOSource: Specifies the Trigger Output source.
+ * This parameter can be one of the following values:
+ * @arg TIM4_TRGOSource_Reset: Trigger Output source = Reset
+ * @arg TIM4_TRGOSource_Enable: Trigger Output source = TIM4 is enabled
+ * @arg TIM4_TRGOSource_Update: Trigger Output source = Update event
+ * @retval None
+ */
+void TIM4_SelectOutputTrigger(TIM4_TRGOSource_TypeDef TIM4_TRGOSource)
+{
+ uint8_t tmpcr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM4_TRGO_SOURCE(TIM4_TRGOSource));
+
+ tmpcr2 = TIM4->CR2;
+
+ /* Reset the MMS Bits */
+ tmpcr2 &= (uint8_t)(~TIM4_CR2_MMS);
+
+ /* Select the TRGO source */
+ tmpcr2 |= (uint8_t)TIM4_TRGOSource;
+
+ TIM4->CR2 = tmpcr2;
+}
+
+/**
+ * @brief Selects the TIM4 Slave Mode.
+ * @param TIM4_SlaveMode: Specifies the TIM4 Slave Mode.
+ * This parameter can be one of the following values:
+ * @arg TIM4_SlaveMode_Disable: Disable slave mode to clock the prescaler
+ directly with the internal clock
+ * @arg TIM4_SlaveMode_Reset: Slave Mode Selection = Reset
+ * @arg TIM4_SlaveMode_Gated: Slave Mode Selection = Gated
+ * @arg TIM4_SlaveMode_Trigger: Slave Mode Selection = Trigger
+ * @arg TIM4_SlaveMode_External1: Slave Mode Selection = External 1
+ * @retval None
+ */
+void TIM4_SelectSlaveMode(TIM4_SlaveMode_TypeDef TIM4_SlaveMode)
+{
+ uint8_t tmpsmcr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM4_SLAVE_MODE(TIM4_SlaveMode));
+
+ tmpsmcr = TIM4->SMCR;
+
+ /* Reset the SMS Bits */
+ tmpsmcr &= (uint8_t)(~TIM4_SMCR_SMS);
+
+ /* Select the Slave Mode */
+ tmpsmcr |= (uint8_t)TIM4_SlaveMode;
+
+ TIM4->SMCR = tmpsmcr;
+}
+
+/**
+ * @brief Sets or Resets the TIM4 Master/Slave Mode.
+ * @param NewState: The new state of the synchronization between TIM4 and its slaves (through TRGO).
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM4_SelectMasterSlaveMode(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the MSM Bit */
+ if (NewState != DISABLE)
+ {
+ TIM4->SMCR |= TIM4_SMCR_MSM;
+ }
+ else
+ {
+ TIM4->SMCR &= (uint8_t)(~TIM4_SMCR_MSM);
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim5.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim5.c
new file mode 100644
index 00000000..a767a3a5
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_tim5.c
@@ -0,0 +1,2154 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_tim5.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the TIM5 peripheral:
+ * - TimeBase management
+ * - Output Compare management
+ * - Input Capture management
+ * - Interrupts, DMA and flags management
+ * - Clocks management
+ * - Synchronization management
+ * - Specific interface management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * This driver provides functions to configure and initialize the TIM5
+ * peripheral
+ * These functions are split in 7 groups:
+ *
+ * 1. TIM5 TimeBase management: this group includes all needed functions
+ * to configure the TIM Timebase unit:
+ * - Set/Get Prescaler
+ * - Set/Get Autoreload
+ * - Counter modes configuration
+ * - Select the One Pulse mode
+ * - Update Request Configuration
+ * - Update Disable Configuration
+ * - Auto-Preload Configuration
+ * - Enable/Disable the counter
+ *
+ * 2. TIM5 Output Compare management: this group includes all needed
+ * functions to configure the Capture/Compare unit used in Output
+ * compare mode:
+ * - Configure each channel, independently, in Output Compare mode
+ * - Select the output compare modes
+ * - Select the Polarities of each channel
+ * - Set/Get the Capture/Compare register values
+ * - Select the Output Compare Fast mode
+ * - Select the Output Compare Forced mode
+ * - Output Compare-Preload Configuration
+ * - Enable/Disable the Capture/Compare Channels
+ *
+ * 3. TIM5 Input Capture management: this group includes all needed
+ * functions to configure the Capture/Compare unit used in
+ * Input Capture mode:
+ * - Configure each channel in input capture mode
+ * - Configure Channel1/2 in PWM Input mode
+ * - Set the Input Capture Prescaler
+ * - Get the Capture/Compare values
+ *
+ * 4. TIM5 interrupts, DMA and flags management
+ * - Enable/Disable interrupt sources
+ * - Get flags status
+ * - Clear flags/ Pending bits
+ * - Enable/Disable DMA requests
+ * - Select CaptureCompare DMA request
+ *
+ * 5. TIM5 clocks management: this group includes all needed functions
+ * to configure the clock controller unit:
+ * - Select internal/External clock
+ * - Select the external clock mode: ETR(Mode1/Mode2) or TIx
+ *
+ * 6. TIM5 synchronization management: this group includes all needed
+ * functions to configure the Synchronization unit:
+ * - Select Input Trigger
+ * - Select Output Trigger
+ * - Select Master Slave Mode
+ * - ETR Configuration when used as external trigger
+ *
+ * 7. TIM5 specific interface management, this group includes all
+ * needed functions to use the specific TIM5 interface:
+ * - Encoder Interface Configuration
+ * - Select Hall Sensor
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_TIM5.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup TIM5
+ * @brief TIM5 driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void TI1_Config(TIM5_ICPolarity_TypeDef TIM5_ICPolarity,
+ TIM5_ICSelection_TypeDef TIM5_ICSelection,
+ uint8_t TIM5_ICFilter);
+static void TI2_Config(TIM5_ICPolarity_TypeDef TIM5_ICPolarity,
+ TIM5_ICSelection_TypeDef TIM5_ICSelection,
+ uint8_t TIM5_ICFilter);
+
+
+/** @defgroup TIM5_Private_Functions
+ * @{
+ */
+
+/** @defgroup TIM5_Group1 TimeBase management functions
+ * @brief TimeBase management functions
+ *
+@verbatim
+ ===============================================================================
+ TimeBase management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM5 Driver: how to use it in Timing(Time base) Mode
+ ===================================================================
+ To use the Timer in Timing(Time base) mode, the following steps are mandatory:
+
+ 1. Enable TIM5 clock using CLK_PeripheralClockConfig(CLK_Peripheral_TIM5, ENABLE) function.
+
+ 2. Call TIM5_TimeBaseInit() to configure the Time Base unit with the
+ corresponding configuration.
+
+ 3. Enable global interrupts if you need to generate the update interrupt.
+
+ 4. Enable the corresponding interrupt using the function TIM5_ITConfig(TIM5_IT_Update)
+
+ 5. Call the TIM5_Cmd(ENABLE) function to enable the TIM5 counter.
+
+ Note1: All other functions can be used separately to modify, if needed,
+ a specific feature of the Timer.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitialize the TIM5 peripheral registers to their default reset values.
+ * @param None
+ * @retval None
+ */
+void TIM5_DeInit(void)
+{
+ TIM5->CR1 = TIM_CR1_RESET_VALUE;
+ TIM5->CR2 = TIM_CR2_RESET_VALUE;
+ TIM5->SMCR = TIM_SMCR_RESET_VALUE;
+ TIM5->ETR = TIM_ETR_RESET_VALUE;
+ TIM5->IER = TIM_IER_RESET_VALUE;
+ TIM5->SR2 = TIM_SR2_RESET_VALUE;
+
+ /* Disable channels */
+ TIM5->CCER1 = TIM_CCER1_RESET_VALUE;
+ /* Configure channels as inputs: it is necessary if lock level is equal to 2 or 3 */
+ TIM5->CCMR1 = 0x01;/*TIM5_ICxSource_TIxFPx */
+ TIM5->CCMR2 = 0x01;/*TIM5_ICxSource_TIxFPx */
+
+ /* Then reset channel registers: it also works if lock level is equal to 2 or 3 */
+ TIM5->CCER1 = TIM_CCER1_RESET_VALUE;
+ TIM5->CCMR1 = TIM_CCMR1_RESET_VALUE;
+ TIM5->CCMR2 = TIM_CCMR2_RESET_VALUE;
+
+ TIM5->CNTRH = TIM_CNTRH_RESET_VALUE;
+ TIM5->CNTRL = TIM_CNTRL_RESET_VALUE;
+
+ TIM5->PSCR = TIM_PSCR_RESET_VALUE;
+
+ TIM5->ARRH = TIM_ARRH_RESET_VALUE;
+ TIM5->ARRL = TIM_ARRL_RESET_VALUE;
+
+ TIM5->CCR1H = TIM_CCR1H_RESET_VALUE;
+ TIM5->CCR1L = TIM_CCR1L_RESET_VALUE;
+ TIM5->CCR2H = TIM_CCR2H_RESET_VALUE;
+ TIM5->CCR2L = TIM_CCR2L_RESET_VALUE;
+
+
+ TIM5->OISR = TIM_OISR_RESET_VALUE;
+ TIM5->EGR = 0x01;/* TIM_EGR_UG */
+ TIM5->BKR = TIM_BKR_RESET_VALUE;
+ TIM5->SR1 = TIM_SR1_RESET_VALUE;
+}
+
+/**
+ * @brief Initializes the TIM5 Time Base Unit according to the specified parameters.
+ * @param TIM5_Prescaler: Prescaler
+ * This parameter can be one of the following values:
+ * @arg TIM5_Prescaler_1: Time base Prescaler = 1 (No effect)
+ * @arg TIM5_Prescaler_2: Time base Prescaler = 2
+ * @arg TIM5_Prescaler_4: Time base Prescaler = 4
+ * @arg TIM5_Prescaler_8: Time base Prescaler = 8
+ * @arg TIM5_Prescaler_16: Time base Prescaler = 16
+ * @arg TIM5_Prescaler_32: Time base Prescaler = 32
+ * @arg TIM5_Prescaler_64: Time base Prescaler = 64
+ * @arg TIM5_Prescaler_128: Time base Prescaler = 128
+ * @param TIM5_CounterMode: Counter mode
+ * This parameter can be one of the following values:
+ * @arg TIM5_CounterMode_Up: Counter Up Mode
+ * @arg TIM5_CounterMode_Down: Counter Down Mode
+ * @arg TIM5_CounterMode_CenterAligned1: Counter Central aligned Mode 1
+ * @arg TIM5_CounterMode_CenterAligned2: Counter Central aligned Mode 2
+ * @arg TIM5_CounterMode_CenterAligned3: Counter Central aligned Mode 3
+ * @param TIM5_Period: This parameter must be a value between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+
+void TIM5_TimeBaseInit(TIM5_Prescaler_TypeDef TIM5_Prescaler,
+ TIM5_CounterMode_TypeDef TIM5_CounterMode,
+ uint16_t TIM5_Period)
+{
+
+ assert_param(IS_TIM5_PRESCALER(TIM5_Prescaler));
+ assert_param(IS_TIM5_COUNTER_MODE(TIM5_CounterMode));
+
+
+
+ /* Set the Autoreload value */
+ TIM5->ARRH = (uint8_t)(TIM5_Period >> 8) ;
+ TIM5->ARRL = (uint8_t)(TIM5_Period);
+
+ /* Set the Prescaler value */
+ TIM5->PSCR = (uint8_t)(TIM5_Prescaler);
+
+ /* Select the Counter Mode */
+ TIM5->CR1 &= (uint8_t)((uint8_t)(~TIM_CR1_CMS)) & ((uint8_t)(~TIM_CR1_DIR));
+ TIM5->CR1 |= (uint8_t)(TIM5_CounterMode);
+
+ /* Generate an update event to reload the Prescaler value immediately */
+ TIM5->EGR = TIM5_EventSource_Update;
+}
+
+/**
+ * @brief Configures the TIM5 Prescaler.
+ * @param Prescaler: Specifies the Prescaler Register value
+ * This parameter can be one of the following values:
+ * @arg TIM5_Prescaler_1: Time base Prescaler = 1 (No effect)
+ * @arg TIM5_Prescaler_2: Time base Prescaler = 2
+ * @arg TIM5_Prescaler_4: Time base Prescaler = 4
+ * @arg TIM5_Prescaler_8: Time base Prescaler = 8
+ * @arg TIM5_Prescaler_16: Time base Prescaler = 16
+ * @arg TIM5_Prescaler_32: Time base Prescaler = 32
+ * @arg TIM5_Prescaler_64: Time base Prescaler = 64
+ * @arg TIM5_Prescaler_128: Time base Prescaler = 128
+ * @param TIM5_PSCReloadMode: Specifies the TIM5 Prescaler Reload mode.
+ * This parameter can be one of the following values:
+ * @arg TIM5_PSCReloadMode_Update: Prescaler value is reloaded at every update
+ * @arg TIM5_PSCReloadMode_Immediate: Prescaler value is reloaded at every update
+ * @retval None
+ */
+void TIM5_PrescalerConfig(TIM5_Prescaler_TypeDef Prescaler,
+ TIM5_PSCReloadMode_TypeDef TIM5_PSCReloadMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_PRESCALER(Prescaler));
+ assert_param(IS_TIM5_PRESCALER_RELOAD(TIM5_PSCReloadMode));
+
+ /* Set the Prescaler value */
+ TIM5->PSCR = (uint8_t)(Prescaler);
+
+ /* Set or reset the UG Bit */
+ if (TIM5_PSCReloadMode == TIM5_PSCReloadMode_Immediate)
+ {
+ TIM5->EGR |= TIM_EGR_UG ;
+ }
+ else
+ {
+ TIM5->EGR &= (uint8_t)(~TIM_EGR_UG) ;
+ }
+}
+
+/**
+ * @brief Specifies the TIM5 Counter Mode to be used.
+ * @param TIM5_CounterMode: Specifies the Counter Mode to be used
+ * This parameter can be one of the following values:
+ * @arg TIM5_CounterMode_Up: Counter Up Mode
+ * @arg TIM5_CounterMode_Down: Counter Down Mode
+ * @arg TIM5_CounterMode_CenterAligned1: Counter Central aligned Mode 1
+ * @arg TIM5_CounterMode_CenterAligned2: Counter Central aligned Mode 2
+ * @arg TIM5_CounterMode_CenterAligned3: Counter Central aligned Mode 3
+ * @retval None
+ */
+void TIM5_CounterModeConfig(TIM5_CounterMode_TypeDef TIM5_CounterMode)
+{
+ uint8_t tmpcr1 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_COUNTER_MODE(TIM5_CounterMode));
+
+ tmpcr1 = TIM5->CR1;
+
+ /* Reset the CMS and DIR Bits */
+ tmpcr1 &= (uint8_t)((uint8_t)(~TIM_CR1_CMS) & (uint8_t)(~TIM_CR1_DIR));
+
+ /* Set the Counter Mode */
+ tmpcr1 |= (uint8_t)TIM5_CounterMode;
+
+ TIM5->CR1 = tmpcr1;
+}
+
+/**
+ * @brief Sets the TIM5 Counter Register value.
+ * @param Counter: Specifies the Counter register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM5_SetCounter(uint16_t Counter)
+{
+
+ /* Set the Counter Register value */
+ TIM5->CNTRH = (uint8_t)(Counter >> 8);
+ TIM5->CNTRL = (uint8_t)(Counter);
+}
+
+/**
+ * @brief Sets the TIM5 Autoreload Register value.
+ * @param Autoreload: Specifies the Autoreload register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM5_SetAutoreload(uint16_t Autoreload)
+{
+ /* Set the Autoreload Register value */
+ TIM5->ARRH = (uint8_t)(Autoreload >> 8);
+ TIM5->ARRL = (uint8_t)(Autoreload);
+}
+
+/**
+ * @brief Gets the TIM5 Counter value.
+ * @param None
+ * @retval Counter Register value.
+ */
+uint16_t TIM5_GetCounter(void)
+{
+ uint16_t tmpcnt = 0;
+ uint8_t tmpcntrl, tmpcntrh;
+
+ tmpcntrh = TIM5->CNTRH;
+ tmpcntrl = TIM5->CNTRL;
+
+ tmpcnt = (uint16_t)(tmpcntrl);
+ tmpcnt |= (uint16_t)((uint16_t)tmpcntrh << 8);
+ /* Get the Counter Register value */
+ return ((uint16_t)tmpcnt);
+}
+
+/**
+ * @brief Gets the TIM5 Prescaler value.
+ * @param None
+ * @retval TIM5 Prescaler, it can be one of the following values:
+ * - TIM5_Prescaler_1: Time base Prescaler = 1 (No effect)
+ * - TIM5_Prescaler_2: Time base Prescaler = 2
+ * - TIM5_Prescaler_4: Time base Prescaler = 4
+ * - TIM5_Prescaler_8: Time base Prescaler = 8
+ * - TIM5_Prescaler_16: Time base Prescaler = 16
+ * - TIM5_Prescaler_32: Time base Prescaler = 32
+ * - TIM5_Prescaler_64: Time base Prescaler = 64
+ * - TIM5_Prescaler_128: Time base Prescaler = 128
+ */
+TIM5_Prescaler_TypeDef TIM5_GetPrescaler(void)
+{
+ /* Get the Prescaler Register value */
+ return ((TIM5_Prescaler_TypeDef)TIM5->PSCR);
+}
+
+/**
+ * @brief Enables or Disables the TIM5 Update event.
+ * @param NewState: The new state of the TIM5 peripheral Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+
+void TIM5_UpdateDisableConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the UDIS Bit */
+ if (NewState != DISABLE)
+ {
+ TIM5->CR1 |= TIM_CR1_UDIS;
+ }
+ else
+ {
+ TIM5->CR1 &= (uint8_t)(~TIM_CR1_UDIS);
+ }
+}
+
+/**
+ * @brief Selects the TIM5 Update Request Interrupt source.
+ * @param TIM5_UpdateSource: Specifies the Update source.
+ * This parameter can be one of the following values:
+ * @arg TIM5_UpdateSource_Global: Global Update request source
+ * @arg TIM5_UpdateSource_Regular: Regular Update request source
+ * @retval None
+ */
+void TIM5_UpdateRequestConfig(TIM5_UpdateSource_TypeDef TIM5_UpdateSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_UPDATE_SOURCE(TIM5_UpdateSource));
+
+ /* Set or Reset the URS Bit */
+ if (TIM5_UpdateSource == TIM5_UpdateSource_Regular)
+ {
+ TIM5->CR1 |= TIM_CR1_URS ;
+ }
+ else
+ {
+ TIM5->CR1 &= (uint8_t)(~TIM_CR1_URS);
+ }
+}
+
+/**
+ * @brief Enables or disables TIM5 peripheral Preload register on ARR.
+ * @param NewState: The new state of the TIM5 peripheral Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM5_ARRPreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the ARPE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM5->CR1 |= TIM_CR1_ARPE;
+ }
+ else
+ {
+ TIM5->CR1 &= (uint8_t)(~TIM_CR1_ARPE);
+ }
+}
+
+/**
+ * @brief Selects the TIM’s One Pulse Mode.
+ * @param TIM5_OPMode: Specifies the OPM Mode to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM5_OPMode_Single: Single one Pulse mode (OPM Active)
+ * @arg TIM5_OPMode_Repetitive: Single one Pulse mode (OPM Active)
+ * @retval None
+ */
+void TIM5_SelectOnePulseMode(TIM5_OPMode_TypeDef TIM5_OPMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_OPM_MODE(TIM5_OPMode));
+
+ /* Set or Reset the OPM Bit */
+ if (TIM5_OPMode == TIM5_OPMode_Single)
+ {
+ TIM5->CR1 |= TIM_CR1_OPM ;
+ }
+ else
+ {
+ TIM5->CR1 &= (uint8_t)(~TIM_CR1_OPM);
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM5 peripheral.
+ * @param NewState: The new state of the TIM5 peripheral.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM5_Cmd(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* set or Reset the CEN Bit */
+ if (NewState != DISABLE)
+ {
+ TIM5->CR1 |= TIM_CR1_CEN;
+ }
+ else
+ {
+ TIM5->CR1 &= (uint8_t)(~TIM_CR1_CEN);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Group2 Output Compare management functions
+ * @brief Output Compare management functions
+ *
+@verbatim
+ ===============================================================================
+ Output Compare management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM5 Driver: how to use it in Output Compare Mode
+ ===================================================================
+ To use the Timer in Output Compare mode, the following steps are mandatory:
+
+ 1. Enable TIM5 clock using CLK_PeripheralClockConfig(CLK_Peripheral_TIM5, ENABLE) function.
+
+ 2. Configure the TIM5 pins in output mode by configuring the corresponding GPIO pins
+
+ 3. Configure the Time base unit as described in the first part of this driver, if needed,
+ otherwise the Timer will run with the default configuration:
+ - Autoreload value = 0xFFFF
+ - Prescaler value = 0x0000
+ - Counter mode = Up counting
+
+ 4. Call TIM5_OCxInit() to configure the channel x with the desired parameters
+ including:
+ - TIM5 Output Compare mode: TIM5_OCMode
+ - TIM5 Output State: TIM5_OutputState
+ - TIM5 Pulse value: TIM5_Pulse
+ - TIM5 Output Compare Polarity: TIM5_OCPolarity
+ - TIM5 Output Idle State: TIM5_OCIdleState
+
+ 5. Call the TIM5_Cmd(ENABLE) function to enable the TIM5 counter.
+
+ Note1: All other functions can be used separately to modify, if needed,
+ a specific feature of the Timer.
+
+ Note2: If the corresponding interrupt or DMA request are needed, the user should:
+ 1. Enable global interrupts (or the DMA) to use the TIM5 interrupts (or DMA requests).
+ 2. Enable the corresponding interrupt (or DMA request) using the function
+ TIM5_ITConfig(TIM5_IT_CCx) (or TIM5_DMACmd(TIM5_DMASource_CCx))
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the TIM5 Channel1 according to the specified parameters.
+ * @param TIM5_OCMode: Output Compare Mode
+ * This parameter can be one of the following values:
+ * @arg TIM5_OCMode_Timing: Timing (Frozen) Mode
+ * @arg TIM5_OCMode_Active: Active Mode
+ * @arg TIM5_OCMode_Inactive: Inactive Mode
+ * @arg TIM5_OCMode_Toggle: Toggle Mode
+ * @arg TIM5_OCMode_PWM1: PWM Mode 1
+ * @arg TIM5_OCMode_PWM2: PWM Mode 2
+ * @param TIM5_OutputState: Output state
+ * This parameter can be one of the following values:
+ * @arg TIM5_OutputState_Disable: Output compare State disabled (channel output disabled)
+ * @arg TIM5_OutputState_Enable: Output compare State enabled (channel output enabled)
+ * @param TIM5_Pulse: This parameter must be a value between 0x0000 and 0xFFFF.
+ * @param TIM5_OCPolarity: Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM5_OCPolarity_High: Output compare polarity = High
+ * @arg TIM5_OCPolarity_Low: Output compare polarity = Low
+ * @param TIM5_OCIdleState: Output Compare Idle State
+ * This parameter can be one of the following values:
+ * @arg TIM5_OCIdleState_Reset: Output Compare Idle state = Reset
+ * @arg TIM5_OCIdleState_Set: Output Compare Idle state = Set
+ * @retval None
+ */
+void TIM5_OC1Init(TIM5_OCMode_TypeDef TIM5_OCMode,
+ TIM5_OutputState_TypeDef TIM5_OutputState,
+ uint16_t TIM5_Pulse,
+ TIM5_OCPolarity_TypeDef TIM5_OCPolarity,
+ TIM5_OCIdleState_TypeDef TIM5_OCIdleState)
+{
+ uint8_t tmpccmr1 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_OC_MODE(TIM5_OCMode));
+ assert_param(IS_TIM5_OUTPUT_STATE(TIM5_OutputState));
+ assert_param(IS_TIM5_OC_POLARITY(TIM5_OCPolarity));
+ assert_param(IS_TIM5_OCIDLE_STATE(TIM5_OCIdleState));
+
+ tmpccmr1 = TIM5->CCMR1;
+
+ /* Disable the Channel 1: Reset the CCE Bit */
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E);
+ /* Reset the Output Compare Bits */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Set the Output Compare Mode */
+ tmpccmr1 |= (uint8_t)TIM5_OCMode;
+
+ TIM5->CCMR1 = tmpccmr1;
+
+ /* Set the Output State */
+ if (TIM5_OutputState == TIM5_OutputState_Enable)
+ {
+ TIM5->CCER1 |= TIM_CCER1_CC1E;
+ }
+ else
+ {
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E);
+ }
+
+ /* Set the Output Polarity */
+ if (TIM5_OCPolarity == TIM5_OCPolarity_Low)
+ {
+ TIM5->CCER1 |= TIM_CCER1_CC1P;
+ }
+ else
+ {
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC1P);
+ }
+
+ /* Set the Output Idle state */
+ if (TIM5_OCIdleState == TIM5_OCIdleState_Set)
+ {
+ TIM5->OISR |= TIM_OISR_OIS1;
+ }
+ else
+ {
+ TIM5->OISR &= (uint8_t)(~TIM_OISR_OIS1);
+ }
+
+ /* Set the Pulse value */
+ TIM5->CCR1H = (uint8_t)(TIM5_Pulse >> 8);
+ TIM5->CCR1L = (uint8_t)(TIM5_Pulse);
+}
+
+/**
+ * @brief Initializes the TIM5 Channel2 according to the specified parameters.
+ * @param TIM5_OCMode: Output Compare Mode
+ * This parameter can be one of the following values:
+ * @arg TIM5_OCMode_Timing: Timing (Frozen) Mode
+ * @arg TIM5_OCMode_Active: Active Mode
+ * @arg TIM5_OCMode_Inactive: Inactive Mode
+ * @arg TIM5_OCMode_Toggle: Toggle Mode
+ * @arg TIM5_OCMode_PWM1: PWM Mode 1
+ * @arg TIM5_OCMode_PWM2: PWM Mode 2
+ * @param TIM5_OutputState: Output state
+ * This parameter can be one of the following values:
+ * @arg TIM5_OutputState_Disable: Output compare State disabled (channel output disabled)
+ * @arg TIM5_OutputState_Enable: Output compare State enabled (channel output enabled)
+ * @param TIM5_Pulse: This parameter must be a value between 0x0000 and 0xFFFF.
+ * @param TIM5_OCPolarity: Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM5_OCPolarity_High: Output compare polarity = High
+ * @arg TIM5_OCPolarity_Low: Output compare polarity = Low
+ * @param TIM5_OCIdleState: Output Compare Idle State
+ * This parameter can be one of the following values:
+ * @arg TIM5_OCIdleState_Reset: Output Compare Idle state = Reset
+ * @arg TIM5_OCIdleState_Set: Output Compare Idle state = Set
+ * @retval None
+ */
+void TIM5_OC2Init(TIM5_OCMode_TypeDef TIM5_OCMode,
+ TIM5_OutputState_TypeDef TIM5_OutputState,
+ uint16_t TIM5_Pulse,
+ TIM5_OCPolarity_TypeDef TIM5_OCPolarity,
+ TIM5_OCIdleState_TypeDef TIM5_OCIdleState)
+{
+ uint8_t tmpccmr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_OC_MODE(TIM5_OCMode));
+ assert_param(IS_TIM5_OUTPUT_STATE(TIM5_OutputState));
+ assert_param(IS_TIM5_OC_POLARITY(TIM5_OCPolarity));
+ assert_param(IS_TIM5_OCIDLE_STATE(TIM5_OCIdleState));
+
+ tmpccmr2 = TIM5->CCMR2;
+
+ /* Disable the Channel 2: Reset the CCE Bit */
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E);
+
+ /* Reset the Output Compare Bits */
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Set the Output Compare Mode */
+ tmpccmr2 |= (uint8_t)TIM5_OCMode;
+
+ TIM5->CCMR2 = tmpccmr2;
+
+ /* Set the Output State */
+ if (TIM5_OutputState == TIM5_OutputState_Enable)
+ {
+ TIM5->CCER1 |= TIM_CCER1_CC2E;
+ }
+ else
+ {
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E);
+ }
+
+ /* Set the Output Polarity */
+ if (TIM5_OCPolarity == TIM5_OCPolarity_Low)
+ {
+ TIM5->CCER1 |= TIM_CCER1_CC2P;
+ }
+ else
+ {
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC2P);
+ }
+
+
+ /* Set the Output Idle state */
+ if (TIM5_OCIdleState == TIM5_OCIdleState_Set)
+ {
+ TIM5->OISR |= TIM_OISR_OIS2;
+ }
+ else
+ {
+ TIM5->OISR &= (uint8_t)(~TIM_OISR_OIS2);
+ }
+
+ /* Set the Pulse value */
+ TIM5->CCR2H = (uint8_t)(TIM5_Pulse >> 8);
+ TIM5->CCR2L = (uint8_t)(TIM5_Pulse);
+}
+
+/**
+ * @brief Configures the Break feature, dead time, Lock level, the OSSI,
+ * and the AOE(automatic output enable).
+ * @param TIM5_OSSIState: Off-State Selection for Idle mode states.
+ * This parameter can be one of the following values:
+ * @arg TIM5_OSSIState_Enable: Off-State Selection for Idle mode enabled
+ * @arg TIM5_OSSIState_Disable: Off-State Selection for Idle mode disabled
+ * @param TIM5_LockLevel: Lock level.
+ * This parameter can be one of the following values:
+ * @arg TIM5_LockLevel_Off: Lock option disabled
+ * @arg TIM5_LockLevel_1: Select Lock Level 1
+ * @arg TIM5_LockLevel_2: Select Lock Level 2
+ * @arg TIM5_LockLevel_3: Select Lock Level 3
+ * @param TIM5_BreakState: Break Input enable/disable .
+ * This parameter can be one of the following values:
+ * @arg TIM5_BreakState_Disable: Break State disabled (break option disabled)
+ * @arg TIM5_BreakState_Enable: Break State enabled (break option enabled)
+ * @param TIM5_BreakPolarity: Break Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM5_BreakPolarity_High: if Break, channel polarity = High
+ * @arg TIM5_BreakPolarity_Low: if Break, channel polarity = Low
+ * @param TIM5_AutomaticOutput: TIM5 AOE Bit Set/Reset .
+ * This parameter can be one of the following values:
+ * @arg TIM5_AutomaticOutput_Enable: Automatic Output option enabled
+ * @arg TIM5_AutomaticOutput_Disable: Automatic Output option disabled
+ * @retval None
+ */
+void TIM5_BKRConfig(TIM5_OSSIState_TypeDef TIM5_OSSIState,
+ TIM5_LockLevel_TypeDef TIM5_LockLevel,
+ TIM5_BreakState_TypeDef TIM5_BreakState,
+ TIM5_BreakPolarity_TypeDef TIM5_BreakPolarity,
+ TIM5_AutomaticOutput_TypeDef TIM5_AutomaticOutput)
+
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_OSSI_STATE(TIM5_OSSIState));
+ assert_param(IS_TIM5_LOCK_LEVEL(TIM5_LockLevel));
+ assert_param(IS_TIM5_BREAK_STATE(TIM5_BreakState));
+ assert_param(IS_TIM5_BREAK_POLARITY(TIM5_BreakPolarity));
+ assert_param(IS_TIM5_AUTOMATIC_OUTPUT_STATE(TIM5_AutomaticOutput));
+
+
+
+ /* Set the Lock level, the Break enable Bit and the Polarity, the OSSI State,
+ the dead time value and the Automatic Output Enable Bit */
+ TIM5->BKR = (uint8_t)((uint8_t)((uint8_t)((uint8_t)((uint8_t)TIM5_OSSIState | (uint8_t)TIM5_LockLevel) | \
+ (uint8_t)((uint8_t)TIM5_BreakState | (uint8_t)TIM5_BreakPolarity)) | \
+ TIM5_AutomaticOutput));
+}
+
+/**
+ * @brief Enables or disables the TIM5 peripheral Main Outputs.
+ * @param NewState: The new state of the TIM5 peripheral.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM5_CtrlPWMOutputs(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the MOE Bit */
+
+ if (NewState != DISABLE)
+ {
+ TIM5->BKR |= TIM_BKR_MOE ;
+ }
+ else
+ {
+ TIM5->BKR &= (uint8_t)(~TIM_BKR_MOE) ;
+ }
+}
+
+/**
+ * @brief Selects the TIM5 Output Compare Mode. This function disables the
+ * selected channel before changing the Output Compare Mode. User has to
+ * enable this channel using TIM5_CCxCmd and TIM5_CCxNCmd functions.
+ * @param TIM5_Channel: Specifies the TIM5 Channel.
+ * This parameter can be one of the following values:
+ * @arg TIM5_Channel_1: Channel 1
+ * @arg TIM5_Channel_2: Channel 2
+ * @param TIM5_OCMode: Specifies the TIM5 Output Compare Mode.
+ * This parameter can be one of the following values:
+ * @arg TIM5_OCMode_Timing: Timing (Frozen) Mode
+ * @arg TIM5_OCMode_Active: Active Mode
+ * @arg TIM5_OCMode_Inactive: Inactive Mode
+ * @arg TIM5_OCMode_Toggle: Toggle Mode
+ * @arg TIM5_OCMode_PWM1: PWM Mode 1
+ * @arg TIM5_OCMode_PWM2: PWM Mode 2
+ * @retval None
+ */
+void TIM5_SelectOCxM(TIM5_Channel_TypeDef TIM5_Channel,
+ TIM5_OCMode_TypeDef TIM5_OCMode)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_CHANNEL(TIM5_Channel));
+ assert_param(IS_TIM5_OCM(TIM5_OCMode));
+
+ if (TIM5_Channel == TIM5_Channel_1)
+ {
+ /* Disable the Channel 1: Reset the CCE Bit */
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E);
+
+ /* Reset the Output Compare Bits */
+ TIM5->CCMR1 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Set the Output Compare Mode */
+ TIM5->CCMR1 |= (uint8_t)TIM5_OCMode;
+ }
+ else /* if (TIM5_Channel == TIM5_Channel_2) */
+ {
+ /* Disable the Channel 2: Reset the CCE Bit */
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E);
+
+ /* Reset the Output Compare Bits */
+ TIM5->CCMR2 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Set the Output Compare Mode */
+ TIM5->CCMR2 |= (uint8_t)TIM5_OCMode;
+ }
+}
+
+/**
+ * @brief Sets the TIM5 Capture Compare1 Register value.
+ * @param Compare: Specifies the Capture Compare1 register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM5_SetCompare1(uint16_t Compare)
+{
+ /* Set the Capture Compare1 Register value */
+ TIM5->CCR1H = (uint8_t)(Compare >> 8);
+ TIM5->CCR1L = (uint8_t)(Compare);
+}
+
+/**
+ * @brief Sets the TIM5 Capture Compare2 Register value.
+ * @param Compare: Specifies the Capture Compare2 register new value.
+ * This parameter is between 0x0000 and 0xFFFF.
+ * @retval None
+ */
+void TIM5_SetCompare2(uint16_t Compare)
+{
+ /* Set the Capture Compare2 Register value */
+ TIM5->CCR2H = (uint8_t)(Compare >> 8);
+ TIM5->CCR2L = (uint8_t)(Compare);
+}
+
+/**
+ * @brief Forces the TIM5 Channel1 output waveform to active or inactive level.
+ * @param TIM5_ForcedAction: Specifies the forced Action to be set to the output waveform.
+ * This parameter can be one of the following values:
+ * @arg TIM5_ForcedAction_Active: Output Reference is forced low
+ * @arg TIM5_ForcedAction_Inactive: Output Reference is forced high
+ * @retval None
+ */
+void TIM5_ForcedOC1Config(TIM5_ForcedAction_TypeDef TIM5_ForcedAction)
+{
+ uint8_t tmpccmr1 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_FORCED_ACTION(TIM5_ForcedAction));
+
+ tmpccmr1 = TIM5->CCMR1;
+
+ /* Reset the OCM Bits */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Configure The Forced output Mode */
+ tmpccmr1 |= (uint8_t)TIM5_ForcedAction;
+
+ TIM5->CCMR1 = tmpccmr1;
+}
+
+/**
+ * @brief Forces the TIM5 Channel2 output waveform to active or inactive level.
+ * @param TIM5_ForcedAction: Specifies the forced Action to be set to the output waveform.
+ * This parameter can be one of the following values:
+ * @arg TIM5_ForcedAction_Active: Output Reference is forced low
+ * @arg TIM5_ForcedAction_Inactive: Output Reference is forced high
+ * @retval None
+ */
+void TIM5_ForcedOC2Config(TIM5_ForcedAction_TypeDef TIM5_ForcedAction)
+{
+ uint8_t tmpccmr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_FORCED_ACTION(TIM5_ForcedAction));
+
+ tmpccmr2 = TIM5->CCMR2;
+
+ /* Reset the OCM Bits */
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_OCM);
+
+ /* Configure The Forced output Mode */
+ tmpccmr2 |= (uint8_t)TIM5_ForcedAction;
+
+ TIM5->CCMR2 = tmpccmr2;
+}
+
+/**
+ * @brief Enables or disables the TIM5 peripheral Preload Register on CCR1.
+ * @param NewState: The new state of the Capture Compare Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM5_OC1PreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC1PE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM5->CCMR1 |= TIM_CCMR_OCxPE ;
+ }
+ else
+ {
+ TIM5->CCMR1 &= (uint8_t)(~TIM_CCMR_OCxPE) ;
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM5 peripheral Preload Register on CCR2.
+ * @param NewState: The new state of the Capture Compare Preload register.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM5_OC2PreloadConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC2PE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM5->CCMR2 |= TIM_CCMR_OCxPE ;
+ }
+ else
+ {
+ TIM5->CCMR2 &= (uint8_t)(~TIM_CCMR_OCxPE) ;
+ }
+}
+
+/**
+ * @brief Configures the TIM5 Capture Compare 1 Fast feature.
+ * @param NewState: The new state of the Output Compare Fast Enable bit.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM5_OC1FastConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC1FE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM5->CCMR1 |= TIM_CCMR_OCxFE ;
+ }
+ else
+ {
+ TIM5->CCMR1 &= (uint8_t)(~TIM_CCMR_OCxFE) ;
+ }
+}
+
+/**
+ * @brief Configures the TIM5 Capture Compare 2 Fast feature.
+ * @param NewState: The new state of the Output Compare Fast Enable bit.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+
+void TIM5_OC2FastConfig(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the OC2FE Bit */
+ if (NewState != DISABLE)
+ {
+ TIM5->CCMR2 |= TIM_CCMR_OCxFE ;
+ }
+ else
+ {
+ TIM5->CCMR2 &= (uint8_t)(~TIM_CCMR_OCxFE) ;
+ }
+}
+
+/**
+ * @brief Configures the TIM5 Channel 1 polarity.
+ * @param TIM5_OCPolarity: Specifies the OC1 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM5_OCPolarity_High: Output compare polarity = High
+ * @arg TIM5_OCPolarity_Low: Output compare polarity = Low
+ * @retval None
+ */
+void TIM5_OC1PolarityConfig(TIM5_OCPolarity_TypeDef TIM5_OCPolarity)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_OC_POLARITY(TIM5_OCPolarity));
+
+ /* Set or Reset the CC1P Bit */
+ if (TIM5_OCPolarity == TIM5_OCPolarity_Low)
+ {
+ TIM5->CCER1 |= TIM_CCER1_CC1P ;
+ }
+ else
+ {
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC1P) ;
+ }
+}
+
+/**
+ * @brief Configures the TIM5 Channel 2 polarity.
+ * @param TIM5_OCPolarity: Specifies the OC2 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM5_OCPolarity_High: Output compare polarity = High
+ * @arg TIM5_OCPolarity_Low: Output compare polarity = Low
+ * @retval None
+ */
+void TIM5_OC2PolarityConfig(TIM5_OCPolarity_TypeDef TIM5_OCPolarity)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_OC_POLARITY(TIM5_OCPolarity));
+
+ /* Set or Reset the CC2P Bit */
+ if (TIM5_OCPolarity == TIM5_OCPolarity_Low)
+ {
+ TIM5->CCER1 |= TIM_CCER1_CC2P ;
+ }
+ else
+ {
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC2P) ;
+ }
+}
+
+/**
+ * @brief Enables or disables the TIM5 Capture Compare Channel x.
+ * @param TIM5_Channel: Specifies the TIM5 Channel.
+ * This parameter can be one of the following values:
+ * @arg TIM5_Channel_1: Channel 1
+ * @arg TIM5_Channel_2: Channel 2
+ * @param NewState: Specifies the TIM5 Channel CCxE bit new state.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM5_CCxCmd(TIM5_Channel_TypeDef TIM5_Channel,
+ FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_CHANNEL(TIM5_Channel));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (TIM5_Channel == TIM5_Channel_1)
+ {
+ /* Set or Reset the CC1E Bit */
+ if (NewState != DISABLE)
+ {
+ TIM5->CCER1 |= TIM_CCER1_CC1E ;
+ }
+ else
+ {
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E) ;
+ }
+
+ }
+ else /* if (TIM5_Channel == TIM5_Channel_2) */
+ {
+ /* Set or Reset the CC2E Bit */
+ if (NewState != DISABLE)
+ {
+ TIM5->CCER1 |= TIM_CCER1_CC2E;
+ }
+ else
+ {
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E) ;
+ }
+ }
+}
+
+/** @defgroup TIM5_Group3 Input Capture management functions
+ * @brief Input Capture management functions
+ *
+@verbatim
+ ===============================================================================
+ Input Capture management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM5 Driver: how to use it in Input Capture Mode
+ ===================================================================
+ To use the Timer in Input Capture mode, the following steps are mandatory:
+
+ 1. Enable TIM5 clock using CLK_PeripheralClockConfig(CLK_Peripheral_TIM5, ENABLE) function.
+
+ 2. Configure the TIM5 pins in input mode by configuring the corresponding GPIO pins
+
+ 3. Configure the Time base unit as described in the first part of this driver, if needed,
+ otherwise the Timer will run with the default configuration:
+ - Autoreload value = 0xFFFF
+ - Prescaler value = 0x0
+ - Counter mode = Up counting
+
+ 4. Call TIM5_ICInit() to configure the desired channel to measure only
+ frequency or duty cycle of the input signal using the corresponding configuration:
+ - TIM5 Channel: TIM5_Channel
+ - TIM5 Input Capture polarity: TIM5_ICPolarity
+ - TIM5 Input Capture selection: TIM5_ICSelection
+ - TIM5 Input Capture Prescaler: TIM5_ICPSC
+ - TIM5 Input Capture filter value
+ or,
+ Call TIM5_PWMIConfig() to configure the desired channels with the
+ corresponding configuration and to measure the frequency and the duty
+ cycle of the input signal.
+
+ 5. Enable global interrupts or the DMA to read the measured frequency.
+
+ 6. Enable the corresponding interrupt (or DMA request) to read the captured value,
+ using the function TIM5_ITConfig(TIM5_IT_CCx) (or TIM5_DMACmd(TIM5_DMASource_CCx))
+
+ 7. Call the TIM5_Cmd(ENABLE) function to enable the TIM5 counter.
+
+ 8. Use TIM5_GetCapturex() to read the captured value corresponding to
+ channel x.
+
+ Note1: All other functions can be used separately to modify, if needed,
+ a specific feature of the Timer.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the TIM5 peripheral according to the specified parameters.
+ * @param TIM5_Channel: TIM5 Channel
+ * This parameter can be one of the following values:
+ * @arg TIM5_Channel_1: Channel 1
+ * @arg TIM5_Channel_2: Channel 2
+ * @param TIM5_ICPolarity: Input Capture Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM5_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM5_ICSelection: Input Capture Selection
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICSelection_DirectTI: Input Capture mapped on the direct input
+ * @arg TIM5_ICSelection_IndirectTI: Input Capture mapped on the indirect input
+ * @arg TIM5_ICSelection_TRGI: Input Capture mapped on the Trigger Input
+ * @param TIM5_ICPrescaler: Input Capture Prescaler
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM5_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM5_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM5_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @param TIM5_ICFilter: This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+void TIM5_ICInit(TIM5_Channel_TypeDef TIM5_Channel,
+ TIM5_ICPolarity_TypeDef TIM5_ICPolarity,
+ TIM5_ICSelection_TypeDef TIM5_ICSelection,
+ TIM5_ICPSC_TypeDef TIM5_ICPrescaler,
+ uint8_t TIM5_ICFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_CHANNEL(TIM5_Channel));
+
+ if (TIM5_Channel == TIM5_Channel_1)
+ {
+ /* TI1 Configuration */
+ TI1_Config(TIM5_ICPolarity, TIM5_ICSelection, TIM5_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM5_SetIC1Prescaler(TIM5_ICPrescaler);
+ }
+ else /* if (TIM5_Channel == TIM5_Channel_2) */
+ {
+ /* TI2 Configuration */
+ TI2_Config(TIM5_ICPolarity, TIM5_ICSelection, TIM5_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM5_SetIC2Prescaler(TIM5_ICPrescaler);
+ }
+}
+
+/**
+ * @brief Configures the TIM5 peripheral in PWM Input Mode according to the
+ * specified parameters.
+ * @param TIM5_Channel: TIM5 Channel
+ * This parameter can be one of the following values:
+ * @arg TIM5_Channel_1: Channel 1
+ * @arg TIM5_Channel_2: Channel 2
+ * @param TIM5_ICPolarity: Input Capture Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM5_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM5_ICSelection: Input Capture Selection
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICSelection_DirectTI: Input Capture mapped on the direct input
+ * @arg TIM5_ICSelection_IndirectTI: Input Capture mapped on the indirect input
+ * @arg TIM5_ICSelection_TRGI: Input Capture mapped on the Trigger Input
+ * @param TIM5_ICPrescaler: Input Capture Prescaler
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM5_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM5_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM5_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @retval None
+ */
+void TIM5_PWMIConfig(TIM5_Channel_TypeDef TIM5_Channel,
+ TIM5_ICPolarity_TypeDef TIM5_ICPolarity,
+ TIM5_ICSelection_TypeDef TIM5_ICSelection,
+ TIM5_ICPSC_TypeDef TIM5_ICPrescaler,
+ uint8_t TIM5_ICFilter)
+{
+ uint8_t icpolarity = TIM5_ICPolarity_Rising;
+ uint8_t icselection = TIM5_ICSelection_DirectTI;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_CHANNEL(TIM5_Channel));
+
+ /* Select the Opposite Input Polarity */
+ if (TIM5_ICPolarity == TIM5_ICPolarity_Rising)
+ {
+ icpolarity = TIM5_ICPolarity_Falling;
+ }
+ else
+ {
+ icpolarity = TIM5_ICPolarity_Rising;
+ }
+
+ /* Select the Opposite Input */
+ if (TIM5_ICSelection == TIM5_ICSelection_DirectTI)
+ {
+ icselection = TIM5_ICSelection_IndirectTI;
+ }
+ else
+ {
+ icselection = TIM5_ICSelection_DirectTI;
+ }
+
+ if (TIM5_Channel == TIM5_Channel_1)
+ {
+ /* TI1 Configuration */
+ TI1_Config(TIM5_ICPolarity, TIM5_ICSelection,
+ TIM5_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM5_SetIC1Prescaler(TIM5_ICPrescaler);
+
+ /* TI2 Configuration */
+ TI2_Config((TIM5_ICPolarity_TypeDef)icpolarity, (TIM5_ICSelection_TypeDef)icselection, TIM5_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM5_SetIC2Prescaler(TIM5_ICPrescaler);
+ }
+ else
+ {
+ /* TI2 Configuration */
+ TI2_Config(TIM5_ICPolarity, TIM5_ICSelection,
+ TIM5_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM5_SetIC2Prescaler(TIM5_ICPrescaler);
+
+ /* TI1 Configuration */
+ TI1_Config((TIM5_ICPolarity_TypeDef)icpolarity, (TIM5_ICSelection_TypeDef)icselection, TIM5_ICFilter);
+
+ /* Set the Input Capture Prescaler value */
+ TIM5_SetIC1Prescaler(TIM5_ICPrescaler);
+ }
+}
+
+/**
+ * @brief Gets the TIM5 Input Capture 1 value.
+ * @param None
+ * @retval Capture Compare 1 Register value.
+ */
+uint16_t TIM5_GetCapture1(void)
+{
+ uint16_t tmpccr1 = 0;
+ uint8_t tmpccr1l, tmpccr1h;
+
+ tmpccr1h = TIM5->CCR1H;
+ tmpccr1l = TIM5->CCR1L;
+
+ tmpccr1 = (uint16_t)(tmpccr1l);
+ tmpccr1 |= (uint16_t)((uint16_t)tmpccr1h << 8);
+ /* Get the Capture 1 Register value */
+ return ((uint16_t)tmpccr1);
+}
+
+/**
+ * @brief Gets the TIM5 Input Capture 2 value.
+ * @param None
+ * @retval Capture Compare 2 Register value.
+ */
+uint16_t TIM5_GetCapture2(void)
+{
+ uint16_t tmpccr2 = 0;
+ uint8_t tmpccr2l, tmpccr2h;
+
+ tmpccr2h = TIM5->CCR2H;
+ tmpccr2l = TIM5->CCR2L;
+
+ tmpccr2 = (uint16_t)(tmpccr2l);
+ tmpccr2 |= (uint16_t)((uint16_t)tmpccr2h << 8);
+ /* Get the Capture 2 Register value */
+ return ((uint16_t)tmpccr2);
+}
+
+/**
+ * @brief Sets the TIM5 Input Capture 1 prescaler.
+ * @param TIM5_IC1Prescaler: Specifies the Input Capture prescaler new value
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM5_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM5_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM5_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @retval None
+ */
+void TIM5_SetIC1Prescaler(TIM5_ICPSC_TypeDef TIM5_IC1Prescaler)
+{
+ uint8_t tmpccmr1 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_IC_PRESCALER(TIM5_IC1Prescaler));
+
+ tmpccmr1 = TIM5->CCMR1;
+
+ /* Reset the IC1PSC Bits */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_ICxPSC);
+
+ /* Set the IC1PSC value */
+ tmpccmr1 |= (uint8_t)TIM5_IC1Prescaler;
+
+ TIM5->CCMR1 = tmpccmr1;
+}
+
+/**
+ * @brief Sets the TIM5 Input Capture 2 prescaler.
+ * @param TIM5_IC2Prescaler: Specifies the Input Capture prescaler new value
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
+ * @arg TIM5_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
+ * @arg TIM5_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
+ * @arg TIM5_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events)
+ * @retval None
+ */
+void TIM5_SetIC2Prescaler(TIM5_ICPSC_TypeDef TIM5_IC2Prescaler)
+{
+ uint8_t tmpccmr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_IC_PRESCALER(TIM5_IC2Prescaler));
+
+ tmpccmr2 = TIM5->CCMR2;
+
+ /* Reset the IC2PSC Bits */
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_ICxPSC);
+
+ /* Set the IC2PSC value */
+ tmpccmr2 |= (uint8_t)TIM5_IC2Prescaler;
+
+ TIM5->CCMR2 = tmpccmr2;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Group4 Interrupts DMA and flags management functions
+ * @brief Interrupts, DMA and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts, DMA and flags management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the specified TIM5 interrupts.
+ * @param TIM5_IT: Specifies the TIM5 interrupts sources to be enabled or disabled.
+ * This parameter can be any combination of the following values:
+ * @arg TIM5_IT_Update: Update
+ * @arg TIM5_IT_CC1: Capture Compare Channel1
+ * @arg TIM5_IT_CC2: Capture Compare Channel2
+ * @arg TIM5_IT_Trigger: Trigger
+ * @arg TIM5_IT_Break: Break
+ * @param NewState: The new state of the TIM5 peripheral.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM5_ITConfig(TIM5_IT_TypeDef TIM5_IT, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_IT(TIM5_IT));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the Interrupt sources */
+ TIM5->IER |= (uint8_t)TIM5_IT;
+ }
+ else
+ {
+ /* Disable the Interrupt sources */
+ TIM5->IER &= (uint8_t)(~(uint8_t)TIM5_IT);
+ }
+}
+
+/**
+ * @brief Configures the TIM5 event to be generated by software.
+ * @param TIM5_EventSource: Specifies the event source.
+ * This parameter can be any combination of the following values:
+ * @arg TIM5_EventSource_Update: Update
+ * @arg TIM5_EventSource_CC1: Capture Compare Channel1
+ * @arg TIM5_EventSource_CC2: Capture Compare Channel2
+ * @arg TIM5_EventSource_Trigger: Trigger
+ * @arg TIM5_EventSource_Break: Break
+ * @retval None
+ */
+void TIM5_GenerateEvent(TIM5_EventSource_TypeDef TIM5_EventSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_EVENT_SOURCE((uint8_t)TIM5_EventSource));
+
+ /* Set the event sources */
+ TIM5->EGR |= (uint8_t)TIM5_EventSource;
+}
+
+/**
+ * @brief Checks whether the specified TIM5 flag is set or not.
+ * @param TIM5_FLAG: Specifies the flag to check.
+ * This parameter can be any combination of the following values:
+ * @arg TIM5_FLAG_Update: Update
+ * @arg TIM5_FLAG_CC1: Capture Compare Channel1
+ * @arg TIM5_FLAG_CC2: Capture Compare Channel2
+ * @arg TIM5_FLAG_Trigger: Trigger
+ * @arg TIM5_FLAG_Break: Break
+ * @arg TIM5_FLAG_CC1OF: Capture compare 1 over capture
+ * @arg TIM5_FLAG_CC2OF: Capture compare 2 over capture
+ * @retval FlagStatus: The new state of TIM5_FLAG (SET or RESET)
+ */
+FlagStatus TIM5_GetFlagStatus(TIM5_FLAG_TypeDef TIM5_FLAG)
+{
+ FlagStatus bitstatus = RESET;
+ uint8_t tim5_flag_l = 0, tim5_flag_h = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_GET_FLAG(TIM5_FLAG));
+
+ tim5_flag_l = (uint8_t)(TIM5->SR1 & (uint8_t)(TIM5_FLAG));
+ tim5_flag_h = (uint8_t)(TIM5->SR2 & (uint8_t)((uint16_t)TIM5_FLAG >> 8));
+
+ if ((uint8_t)(tim5_flag_l | tim5_flag_h) != 0)
+ {
+ bitstatus = SET;
+ }
+ else
+ {
+ bitstatus = RESET;
+ }
+ return ((FlagStatus)bitstatus);
+}
+
+/**
+ * @brief Clears the TIM’s pending flags.
+ * @param TIM5_FLAG: Specifies the flag to clear.
+ * This parameter can be any combination of the following values:
+ * @arg TIM5_FLAG_Update: Update
+ * @arg TIM5_FLAG_CC1: Capture Compare Channel1
+ * @arg TIM5_FLAG_CC2: Capture Compare Channel2
+ * @arg TIM5_FLAG_Trigger: Trigger
+ * @arg TIM5_FLAG_Break: Break
+ * @retval None
+ */
+void TIM5_ClearFlag(TIM5_FLAG_TypeDef TIM5_FLAG)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_CLEAR_FLAG((uint16_t)TIM5_FLAG));
+ /* Clear the flags (rc_w0) clear this bit by writing 0. Writing ‘1’ has no effect*/
+ TIM5->SR1 = (uint8_t)(~(uint8_t)(TIM5_FLAG));
+ TIM5->SR2 = (uint8_t)(~(uint8_t)((uint16_t)TIM5_FLAG >> 8));
+}
+
+/**
+ * @brief Checks whether the TIM5 interrupt has occurred or not.
+ * @param TIM5_IT: Specifies the TIM5 interrupt source to check.
+ * This parameter can be any combination of the following values:
+ * @arg TIM5_IT_Update: Update
+ * @arg TIM5_IT_CC1: Capture Compare Channel1
+ * @arg TIM5_IT_CC2: Capture Compare Channel2
+ * @arg TIM5_IT_Trigger: Trigger
+ * @arg TIM5_IT_Break: Break
+ * @retval ITStatus: The new state of the TIM5_IT (SET or RESET)
+ */
+ITStatus TIM5_GetITStatus(TIM5_IT_TypeDef TIM5_IT)
+{
+ ITStatus bitstatus = RESET;
+
+ uint8_t TIM5_itStatus = 0x0, TIM5_itEnable = 0x0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_GET_IT(TIM5_IT));
+
+ TIM5_itStatus = (uint8_t)(TIM5->SR1 & (uint8_t)TIM5_IT);
+
+ TIM5_itEnable = (uint8_t)(TIM5->IER & (uint8_t)TIM5_IT);
+
+ if ((TIM5_itStatus != (uint8_t)RESET ) && (TIM5_itEnable != (uint8_t)RESET))
+ {
+ bitstatus = (ITStatus)SET;
+ }
+ else
+ {
+ bitstatus = (ITStatus)RESET;
+ }
+ return ((ITStatus)bitstatus);
+}
+
+/**
+ * @brief Clears the TIM's interrupt pending bits.
+ * @param TIM5_IT: Specifies the pending bit to clear.
+ * This parameter can be any combination of the following values:
+ * @arg TIM5_IT_Update: Update
+ * @arg TIM5_IT_CC1: Capture Compare Channel1
+ * @arg TIM5_IT_CC2: Capture Compare Channel2
+ * @arg TIM5_IT_Trigger: Trigger
+ * @arg TIM5_IT_Break: Break
+ * @retval None
+ */
+void TIM5_ClearITPendingBit(TIM5_IT_TypeDef TIM5_IT)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_IT(TIM5_IT));
+
+ /* Clear the IT pending Bit */
+ TIM5->SR1 = (uint8_t)(~(uint8_t)TIM5_IT);
+}
+
+/**
+ * @brief Enables or disables the TIM5 DMA Requests.
+ * @param TIM5_DMASource: specifies the DMA Request sources.
+ * This parameter can be any combination of the following values:
+ * @arg TIM5_DMASource_Update: TIM5 DMA Update Request
+ * @arg TIM5_DMASource_CC1: TIM5 DMA CC1 Request
+ * @arg TIM5_DMASource_CC2: TIM5 DMA CC2 Request
+ * @param NewState: new state of the DMA Request sources.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM5_DMACmd( TIM5_DMASource_TypeDef TIM5_DMASource, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ assert_param(IS_TIM5_DMA_SOURCE(TIM5_DMASource));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the DMA sources */
+ TIM5->DER |= TIM5_DMASource;
+ }
+ else
+ {
+ /* Disable the DMA sources */
+ TIM5->DER &= (uint8_t)(~TIM5_DMASource);
+ }
+}
+
+/**
+ * @brief Selects the TIM5 peripheral Capture Compare DMA source.
+ * @param NewState: new state of the Capture Compare DMA source.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void TIM5_SelectCCDMA(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Set the CCDS Bit */
+ TIM5->CR2 |= TIM_CR2_CCDS;
+ }
+ else
+ {
+ /* Reset the CCDS Bit */
+ TIM5->CR2 &= (uint8_t)(~TIM_CR2_CCDS);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Group5 Clocks management functions
+ * @brief Clocks management functions
+ *
+@verbatim
+ ===============================================================================
+ Clocks management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables the TIM5 internal Clock.
+ * @par Parameters:
+ * None
+ * @retval None
+ */
+void TIM5_InternalClockConfig(void)
+{
+ /* Disable slave mode to clock the prescaler directly with the internal clock */
+ TIM5->SMCR &= (uint8_t)(~TIM_SMCR_SMS);
+}
+
+/**
+ * @brief Configures the TIM5 Trigger as External Clock.
+ * @param TIM5_TIxExternalCLKSource: Specifies Trigger source.
+ * This parameter can be one of the following values:
+ * @arg TIM5_TIxExternalCLK1Source_TI1ED: External Clock mode 1 source = TI1ED
+ * @arg TIM5_TIxExternalCLK1Source_TI1: External Clock mode 1 source = TI1
+ * @arg TIM5_TIxExternalCLK1Source_TI2: External Clock mode 1 source = TI2
+ * @param TIM5_ICPolarity: Specifies the TIx Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM5_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param ICFilter: Specifies the filter value.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM5_TIxExternalClockConfig(TIM5_TIxExternalCLK1Source_TypeDef TIM5_TIxExternalCLKSource,
+ TIM5_ICPolarity_TypeDef TIM5_ICPolarity,
+ uint8_t ICFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_TIXCLK_SOURCE(TIM5_TIxExternalCLKSource));
+ assert_param(IS_TIM5_IC_POLARITY(TIM5_ICPolarity));
+ assert_param(IS_TIM5_IC_FILTER(ICFilter));
+
+ /* Configure the TIM5 Input Clock Source */
+ if (TIM5_TIxExternalCLKSource == TIM5_TIxExternalCLK1Source_TI2)
+ {
+ TI2_Config(TIM5_ICPolarity, TIM5_ICSelection_DirectTI, ICFilter);
+ }
+ else
+ {
+ TI1_Config(TIM5_ICPolarity, TIM5_ICSelection_DirectTI, ICFilter);
+ }
+
+ /* Select the Trigger source */
+ TIM5_SelectInputTrigger((TIM5_TRGSelection_TypeDef)TIM5_TIxExternalCLKSource);
+
+ /* Select the External clock mode1 */
+ TIM5->SMCR |= (uint8_t)(TIM5_SlaveMode_External1);
+}
+
+/**
+ * @brief Configures the TIM5 External clock Mode1.
+ * @param TIM5_ExtTRGPrescaler: Specifies the external Trigger Prescaler.
+ * This parameter can be one of the following values:
+ * @arg TIM5_ExtTRGPSC_OFF: No External Trigger prescaler
+ * @arg TIM5_ExtTRGPSC_DIV2: External Trigger prescaler = 2 (ETRP frequency divided by 2)
+ * @arg TIM5_ExtTRGPSC_DIV4: External Trigger prescaler = 4 (ETRP frequency divided by 4)
+ * @arg TIM5_ExtTRGPSC_DIV8: External Trigger prescaler = 8 (ETRP frequency divided by 8)
+ * @param TIM5_ExtTRGPolarity: Specifies the external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM5_ExtTRGPolarity_Inverted: External Trigger Polarity = inverted
+ * @arg TIM5_ExtTRGPolarity_NonInverted: External Trigger Polarity = non inverted
+ * @param ExtTRGFilter: Specifies the External Trigger Filter.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM5_ETRClockMode1Config(TIM5_ExtTRGPSC_TypeDef TIM5_ExtTRGPrescaler,
+ TIM5_ExtTRGPolarity_TypeDef TIM5_ExtTRGPolarity,
+ uint8_t ExtTRGFilter)
+{
+ /* Configure the ETR Clock source */
+ TIM5_ETRConfig(TIM5_ExtTRGPrescaler, TIM5_ExtTRGPolarity, ExtTRGFilter);
+
+ /* Select the External clock mode1 */
+ TIM5->SMCR &= (uint8_t)(~TIM_SMCR_SMS);
+ TIM5->SMCR |= (uint8_t)(TIM5_SlaveMode_External1);
+
+ /* Select the Trigger selection: ETRF */
+ TIM5->SMCR &= (uint8_t)(~TIM_SMCR_TS);
+ TIM5->SMCR |= (uint8_t)((TIM5_TRGSelection_TypeDef)TIM5_TRGSelection_ETRF);
+}
+
+/**
+ * @brief Configures the TIM5 External clock Mode2.
+ * @param TIM5_ExtTRGPrescaler: Specifies the external Trigger Prescaler.
+ * This parameter can be one of the following values:
+ * @arg TIM5_ExtTRGPSC_OFF: No External Trigger prescaler
+ * @arg TIM5_ExtTRGPSC_DIV2: External Trigger prescaler = 2 (ETRP frequency divided by 2)
+ * @arg TIM5_ExtTRGPSC_DIV4: External Trigger prescaler = 4 (ETRP frequency divided by 4)
+ * @arg TIM5_ExtTRGPSC_DIV8: External Trigger prescaler = 8 (ETRP frequency divided by 8)
+ * @param TIM5_ExtTRGPolarity: Specifies the external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM5_ExtTRGPolarity_Inverted: External Trigger Polarity = inverted
+ * @arg TIM5_ExtTRGPolarity_NonInverted: External Trigger Polarity = non inverted
+ * @param ExtTRGFilter: Specifies the External Trigger Filter.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM5_ETRClockMode2Config(TIM5_ExtTRGPSC_TypeDef TIM5_ExtTRGPrescaler,
+ TIM5_ExtTRGPolarity_TypeDef TIM5_ExtTRGPolarity,
+ uint8_t ExtTRGFilter)
+{
+ /* Configure the ETR Clock source */
+ TIM5_ETRConfig(TIM5_ExtTRGPrescaler, TIM5_ExtTRGPolarity, ExtTRGFilter);
+
+ /* Enable the External clock mode2 */
+ TIM5->ETR |= TIM_ETR_ECE ;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Group6 Synchronization management functions
+ * @brief Synchronization management functions
+ *
+@verbatim
+ ===============================================================================
+ Synchronization management functions
+ ===============================================================================
+
+ ===================================================================
+ TIM5 Driver: how to use it in synchronization Mode
+ ===================================================================
+ Case of two/several Timers
+ **************************
+ 1. If TIM5 is used as master to other timers use the following functions:
+ - TIM5_SelectOutputTrigger()
+ - TIM5_SelectMasterSlaveMode()
+ 2. If TIM5 is used as slave to other timers use the following functions:
+ - TIM5_SelectInputTrigger()
+ - TIM5_SelectSlaveMode()
+
+ Case of Timers and external trigger (TRIG pin)
+ ********************************************
+ 1. Configure the External trigger using TIM5_ETRConfig()
+ 2. Configure the Slave Timer using the following functions:
+ - TIM5_SelectInputTrigger()
+ - TIM5_SelectSlaveMode()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Selects the TIM5 Input Trigger source.
+ * @param TIM5_InputTriggerSource: Specifies Input Trigger source.
+ * This parameter can be one of the following values:
+ * @arg TIM5_TRGSelection_TIM4: TRIG Input source = TIM TRIG Output
+ * @arg TIM5_TRGSelection_TIM1: TRIG Input source = TIM TRIG Output
+ * @arg TIM5_TRGSelection_TIM3: TRIG Input source = TIM TRIG Output
+ * @arg TIM5_TRGSelection_TIM2: TRIG Input source = TIM TRIG Output
+ * @arg TIM5_TRGSelection_TI1F_ED: TRIG Input source = TI1F_ED (TI1 Edge Detector)
+ * @arg TIM5_TRGSelection_TI1FP1: TRIG Input source = TI1FP1 (Filtered Timer Input 1)
+ * @arg TIM5_TRGSelection_TI2FP2: TRIG Input source = TI2FP2 (Filtered Timer Input 2)
+ * @arg TIM5_TRGSelection_ETRF: TRIG Input source = ETRF (External Trigger Input )
+ * @retval None
+ */
+void TIM5_SelectInputTrigger(TIM5_TRGSelection_TypeDef TIM5_InputTriggerSource)
+{
+ uint8_t tmpsmcr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_TRIGGER_SELECTION(TIM5_InputTriggerSource));
+
+ tmpsmcr = TIM5->SMCR;
+
+ /* Select the Trigger Source */
+ tmpsmcr &= (uint8_t)(~TIM_SMCR_TS);
+ tmpsmcr |= (uint8_t)TIM5_InputTriggerSource;
+
+ TIM5->SMCR = (uint8_t)tmpsmcr;
+}
+
+/**
+ * @brief Selects the TIM5 Trigger Output Mode.
+ * @param TIM5_TRGOSource: Specifies the Trigger Output source.
+ * This parameter can be one of the following values:
+ * @arg TIM5_TRGOSource_Reset: Trigger Output source = Reset
+ * @arg TIM5_TRGOSource_Enable: Trigger Output source = TIM5 is enabled
+ * @arg TIM5_TRGOSource_Update: Trigger Output source = Update event
+ * @arg TIM5_TRGOSource_OC1: Trigger Output source = output compare channel1
+ * @arg TIM5_TRGOSource_OC1REF: Trigger Output source = output compare channel 1 reference
+ * @arg TIM5_TRGOSource_OC2REF: Trigger Output source = output compare channel 2 reference
+ * @retval None
+ */
+void TIM5_SelectOutputTrigger(TIM5_TRGOSource_TypeDef TIM5_TRGOSource)
+{
+ uint8_t tmpcr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_TRGO_SOURCE(TIM5_TRGOSource));
+
+ tmpcr2 = TIM5->CR2;
+
+ /* Reset the MMS Bits */
+ tmpcr2 &= (uint8_t)(~TIM_CR2_MMS);
+
+ /* Select the TRGO source */
+ tmpcr2 |= (uint8_t)TIM5_TRGOSource;
+
+ TIM5->CR2 = tmpcr2;
+}
+
+/**
+ * @brief Selects the TIM5 Slave Mode.
+ * @param TIM5_SlaveMode: Specifies the TIM5 Slave Mode.
+ * This parameter can be one of the following values:
+ * @arg TIM5_SlaveMode_Reset: Slave Mode Selection = Reset
+ * @arg TIM5_SlaveMode_Gated: Slave Mode Selection = Gated
+ * @arg TIM5_SlaveMode_Trigger: Slave Mode Selection = Trigger
+ * @arg TIM5_SlaveMode_External1: Slave Mode Selection = External 1
+ * @retval None
+ */
+void TIM5_SelectSlaveMode(TIM5_SlaveMode_TypeDef TIM5_SlaveMode)
+{
+ uint8_t tmpsmcr = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_SLAVE_MODE(TIM5_SlaveMode));
+
+ tmpsmcr = TIM5->SMCR;
+
+ /* Reset the SMS Bits */
+ tmpsmcr &= (uint8_t)(~TIM_SMCR_SMS);
+
+ /* Select the Slave Mode */
+ tmpsmcr |= (uint8_t)TIM5_SlaveMode;
+
+ TIM5->SMCR = tmpsmcr;
+}
+
+/**
+ * @brief Sets or Resets the TIM5 Master/Slave Mode.
+ * @param NewState: The new state of the synchronization between TIM5 and its slaves (through TRGO).
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM5_SelectMasterSlaveMode(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the MSM Bit */
+ if (NewState != DISABLE)
+ {
+ TIM5->SMCR |= TIM_SMCR_MSM;
+ }
+ else
+ {
+ TIM5->SMCR &= (uint8_t)(~TIM_SMCR_MSM);
+ }
+}
+
+/**
+ * @brief Configures the TIM5 External Trigger.
+ * @param TIM5_ExtTRGPrescaler: Specifies the external Trigger Prescaler.
+ * This parameter can be one of the following values:
+ * @arg TIM5_ExtTRGPSC_OFF: No External Trigger prescaler
+ * @arg TIM5_ExtTRGPSC_DIV2: External Trigger prescaler = 2 (ETRP frequency divided by 2)
+ * @arg TIM5_ExtTRGPSC_DIV4: External Trigger prescaler = 4 (ETRP frequency divided by 4)
+ * @arg TIM5_ExtTRGPSC_DIV8: External Trigger prescaler = 8 (ETRP frequency divided by 8)
+ * @param TIM5_ExtTRGPolarity: Specifies the external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM5_ExtTRGPolarity_Inverted: External Trigger Polarity = inverted
+ * @arg TIM5_ExtTRGPolarity_NonInverted: External Trigger Polarity = non inverted
+ * @param ExtTRGFilter: Specifies the External Trigger Filter.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM5_ETRConfig(TIM5_ExtTRGPSC_TypeDef TIM5_ExtTRGPrescaler,
+ TIM5_ExtTRGPolarity_TypeDef TIM5_ExtTRGPolarity,
+ uint8_t ExtTRGFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM5_EXT_PRESCALER(TIM5_ExtTRGPrescaler));
+ assert_param(IS_TIM5_EXT_POLARITY(TIM5_ExtTRGPolarity));
+ assert_param(IS_TIM5_EXT_FILTER(ExtTRGFilter));
+
+ /* Set the Prescaler, the Filter value and the Polarity */
+ TIM5->ETR |= (uint8_t)((uint8_t)((uint8_t)TIM5_ExtTRGPrescaler | (uint8_t)TIM5_ExtTRGPolarity)
+ | (uint8_t)ExtTRGFilter);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM5_Group7 Specific interface management functions
+ * @brief Specific interface management functions
+ *
+@verbatim
+ ===============================================================================
+ Specific interface management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures the TIM5 Encoder Interface.
+ * @param TIM5_EncoderMode: Specifies the TIM5 Encoder Mode.
+ * This parameter can be one of the following values:
+ * @arg TIM5_EncoderMode_TI1: Encoder mode 1
+ * @arg TIM5_EncoderMode_TI2: Encoder mode 2
+ * @arg TIM5_EncoderMode_TI12: Encoder mode 3
+ * @param TIM5_IC1Polarity: Specifies the IC1 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM5_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM5_IC2Polarity: Specifies the IC2 Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM5_ICPolarity_Falling: Input Capture on Falling Edge
+ * @retval None
+ */
+void TIM5_EncoderInterfaceConfig(TIM5_EncoderMode_TypeDef TIM5_EncoderMode,
+ TIM5_ICPolarity_TypeDef TIM5_IC1Polarity,
+ TIM5_ICPolarity_TypeDef TIM5_IC2Polarity)
+{
+ uint8_t tmpsmcr = 0;
+ uint8_t tmpccmr1 = 0;
+ uint8_t tmpccmr2 = 0;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_ENCODER_MODE(TIM5_EncoderMode));
+ assert_param(IS_TIM5_IC_POLARITY(TIM5_IC1Polarity));
+ assert_param(IS_TIM5_IC_POLARITY(TIM5_IC2Polarity));
+
+ tmpsmcr = TIM5->SMCR;
+ tmpccmr1 = TIM5->CCMR1;
+ tmpccmr2 = TIM5->CCMR2;
+
+ /* Set the encoder Mode */
+ tmpsmcr &= (uint8_t)(TIM_SMCR_MSM | TIM_SMCR_TS) ;
+ tmpsmcr |= (uint8_t)TIM5_EncoderMode;
+
+ /* Select the Capture Compare 1 and the Capture Compare 2 as input */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_CCxS);
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_CCxS);
+ tmpccmr1 |= TIM_CCMR_TIxDirect_Set;
+ tmpccmr2 |= TIM_CCMR_TIxDirect_Set;
+
+ /* Set the TI1 and the TI2 Polarities */
+ if (TIM5_IC1Polarity == TIM5_ICPolarity_Falling)
+ {
+ TIM5->CCER1 |= TIM_CCER1_CC1P ;
+ }
+ else
+ {
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC1P) ;
+ }
+
+ if (TIM5_IC2Polarity == TIM5_ICPolarity_Falling)
+ {
+ TIM5->CCER1 |= TIM_CCER1_CC2P ;
+ }
+ else
+ {
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC2P) ;
+ }
+
+ TIM5->SMCR = tmpsmcr;
+ TIM5->CCMR1 = tmpccmr1;
+ TIM5->CCMR2 = tmpccmr2;
+}
+
+/**
+ * @brief Enables or Disables the TIM’s Hall sensor interface.
+ * @param NewState: The new state of the TIM5 Hall sensor interface.
+ * This parameter can be ENABLE or DISABLE
+ * @retval None
+ */
+void TIM5_SelectHallSensor(FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Set or Reset the TI1S Bit */
+ if (NewState != DISABLE)
+ {
+ TIM5->CR2 |= TIM_CR2_TI1S;
+ }
+ else
+ {
+ TIM5->CR2 &= (uint8_t)(~TIM_CR2_TI1S);
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Configure the TI1 as Input.
+ * @param TIM5_ICPolarity: Input Capture Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM5_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM5_ICSelection: Specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICSelection_DirectTI: Input Capture mapped on the direct input
+ * @arg TIM5_ICSelection_IndirectTI: Input Capture mapped on the indirect input
+ * @arg TIM5_ICSelection_TRGI: Input Capture mapped on the Trigger Input
+ * @param TIM5_ICFilter: Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TI1_Config(TIM5_ICPolarity_TypeDef TIM5_ICPolarity, \
+ TIM5_ICSelection_TypeDef TIM5_ICSelection, \
+ uint8_t TIM5_ICFilter)
+{
+ uint8_t tmpccmr1 = 0;
+ uint8_t tmpicpolarity = TIM5_ICPolarity;
+ tmpccmr1 = TIM5->CCMR1;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_IC_POLARITY(TIM5_ICPolarity));
+ assert_param(IS_TIM5_IC_SELECTION(TIM5_ICSelection));
+ assert_param(IS_TIM5_IC_FILTER(TIM5_ICFilter));
+
+ /* Disable the Channel 1: Reset the CCE Bit */
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC1E);
+
+ /* Select the Input and set the filter */
+ tmpccmr1 &= (uint8_t)(~TIM_CCMR_CCxS) & (uint8_t)(~TIM_CCMR_ICxF);
+ tmpccmr1 |= (uint8_t)(((uint8_t)(TIM5_ICSelection)) | ((uint8_t)(TIM5_ICFilter << 4)));
+
+ TIM5->CCMR1 = tmpccmr1;
+
+ /* Select the Polarity */
+ if (tmpicpolarity == (uint8_t)(TIM5_ICPolarity_Falling))
+ {
+ TIM5->CCER1 |= TIM_CCER1_CC1P;
+ }
+ else
+ {
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC1P);
+ }
+
+ /* Set the CCE Bit */
+ TIM5->CCER1 |= TIM_CCER1_CC1E;
+}
+
+/**
+ * @brief Configure the TI2 as Input.
+ * @param TIM5_ICPolarity: Input Capture Polarity
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICPolarity_Rising: Input Capture on Rising Edge
+ * @arg TIM5_ICPolarity_Falling: Input Capture on Falling Edge
+ * @param TIM5_ICSelection: Specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM5_ICSelection_DirectTI: Input Capture mapped on the direct input
+ * @arg TIM5_ICSelection_IndirectTI: Input Capture mapped on the indirect input
+ * @arg TIM5_ICSelection_TRGI: Input Capture mapped on the Trigger Input
+ * @param TIM5_ICFilter: Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TI2_Config(TIM5_ICPolarity_TypeDef TIM5_ICPolarity,
+ TIM5_ICSelection_TypeDef TIM5_ICSelection,
+ uint8_t TIM5_ICFilter)
+{
+ uint8_t tmpccmr2 = 0;
+ uint8_t tmpicpolarity = TIM5_ICPolarity;
+
+ /* Check the parameters */
+ assert_param(IS_TIM5_IC_POLARITY(TIM5_ICPolarity));
+ assert_param(IS_TIM5_IC_SELECTION(TIM5_ICSelection));
+ assert_param(IS_TIM5_IC_FILTER(TIM5_ICFilter));
+
+ tmpccmr2 = TIM5->CCMR2;
+
+ /* Disable the Channel 2: Reset the CCE Bit */
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC2E);
+
+ /* Select the Input and set the filter */
+ tmpccmr2 &= (uint8_t)(~TIM_CCMR_CCxS) & (uint8_t)(~TIM_CCMR_ICxF);
+ tmpccmr2 |= (uint8_t)(((uint8_t)(TIM5_ICSelection)) | ((uint8_t)(TIM5_ICFilter << 4)));
+
+ TIM5->CCMR2 = tmpccmr2;
+
+ /* Select the Polarity */
+ if (tmpicpolarity == TIM5_ICPolarity_Falling)
+ {
+ TIM5->CCER1 |= TIM_CCER1_CC2P ;
+ }
+ else
+ {
+ TIM5->CCER1 &= (uint8_t)(~TIM_CCER1_CC2P) ;
+ }
+
+ /* Set the CCE Bit */
+ TIM5->CCER1 |= TIM_CCER1_CC2E;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_usart.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_usart.c
new file mode 100644
index 00000000..9c561665
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_usart.c
@@ -0,0 +1,1208 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_usart.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Universal synchronous asynchronous receiver
+ * transmitter (USART):
+ * - Initialization and Configuration
+ * - Data transfers
+ * - Multi-Processor Communication
+ * - Half-duplex mode
+ * - Smartcard mode
+ * - IrDA mode
+ * - DMA transfers management
+ * - Interrupts and flags management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * 1. Enable peripheral clock using CLK_PeripheralClockConfig(CLK_Peripheral_USARTx,
+ * ENABLE) function (Refer to the product datasheet for the available USART
+ * peripherals)
+ *
+ * 2. Enable the external Pull-up on the used USART Pins using the
+ * GPIO_ExternalPullUpConfig() function or an external pull-up equivalent resistor
+ * (RPU = 45 KOhm typical value).
+ *
+ * 3. Program the Baud Rate, Word Length , Stop Bit, Parity and Mode (Receiver/Transmitter)
+ * using the USART_Init() function.
+ *
+ * 4. For synchronous mode, enable the clock and program the polarity,
+ * phase and last bit using the USART_ClockInit() function.
+ *
+ * 5. Enable the corresponding interrupt using the function USART_ITConfig() if you need
+ * to use interrupt mode.
+ *
+ * 6. When using the DMA mode
+ * - Configure the DMA using DMA_Init() function
+ * - Activate the needed channel Request using USART_DMACmd() function
+ *
+ * 7. Enable the USART using the USART_Cmd() function.
+ *
+ * 8. Enable the DMA using the DMA_Cmd() function, when using DMA mode.
+ *
+ * Refer to Multi-Processor, half-duplex, Smartcard, IrDA sub-sections for more details.
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_usart.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup USART
+ * @brief USART driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup USART_Private_Functions
+ * @{
+ */
+
+/** @defgroup USART_Group1 Initialization and Configuration functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Initialization and Configuration functions
+ ===============================================================================
+
+ This subsection provides a set of functions allowing to initialize the USART
+ in asynchronous and in synchronous modes.
+ - For the asynchronous mode only these parameters can be configured:
+ - Baud Rate
+ - Word Length
+ - Stop Bit
+ - Parity: If the parity is enabled, then the MSB bit of the data written
+ in the data register is transmitted but is changed by the parity bit.
+ Depending on the frame length defined by the M bit (8-bits or 9-bits),
+ the possible USART frame formats are as listed in the following table:
+ +-------------------------------------------------------------+
+ | M bit | PCE bit | USART frame |
+ |---------------------|---------------------------------------|
+ | 0 | 0 | | SB | 8 bit data | STB | |
+ |---------|-----------|---------------------------------------|
+ | 0 | 1 | | SB | 7 bit data | PB | STB | |
+ |---------|-----------|---------------------------------------|
+ | 1 | 0 | | SB | 9 bit data | STB | |
+ |---------|-----------|---------------------------------------|
+ | 1 | 1 | | SB | 8 bit data | PB | STB | |
+ +-------------------------------------------------------------+
+ - Receiver/transmitter modes
+
+ The USART_Init() function follows the USART asynchronous configuration procedure
+ (details for the procedure are available in reference manual (RM0031)).
+
+ - For the synchronous mode in addition to the asynchronous mode parameters these
+ parameters should be also configured:
+ - USART Clock Enabled
+ - USART polarity
+ - USART phase
+ - USART LastBit
+
+ These parameters can be configured using the USART_ClockInit() function.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the USART peripheral.
+ * @param USARTx: where x can be 1, 2 or 3 to select the specified USART peripheral.
+ * @retval None
+ */
+void USART_DeInit(USART_TypeDef* USARTx)
+{
+
+ /* Clear the Idle Line Detected bit in the status register by a read
+ to the USART_SR register followed by a Read to the USART_DR register */
+ (void) USARTx->SR;
+ (void) USARTx->DR;
+
+ USARTx->BRR2 = USART_BRR2_RESET_VALUE; /* Set USART_BRR2 to reset value 0x00 */
+ USARTx->BRR1 = USART_BRR1_RESET_VALUE; /* Set USART_BRR1 to reset value 0x00 */
+
+ USARTx->CR1 = USART_CR1_RESET_VALUE; /* Set USART_CR1 to reset value 0x00 */
+ USARTx->CR2 = USART_CR2_RESET_VALUE; /* Set USART_CR2 to reset value 0x00 */
+ USARTx->CR3 = USART_CR3_RESET_VALUE; /* Set USART_CR3 to reset value 0x00 */
+ USARTx->CR4 = USART_CR4_RESET_VALUE; /* Set USART_CR4 to reset value 0x00 */
+}
+
+/**
+ * @brief Initializes the USART according to the specified parameters.
+ * @note Configure in Push Pull or Open Drain mode the Tx pin by setting the
+ * correct I/O Port register according the product package and line
+ * configuration
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param BaudRate: The baudrate.
+ * @param USART_WordLength: the word length
+ * This parameter can be one of the following values:
+ * @arg USART_WordLength_8b: 8 bits Data
+ * @arg USART_WordLength_9b: 9 bits Data
+ * @param USART_StopBits: Stop Bit
+ * This parameter can be one of the following values:
+ * @arg USART_StopBits_1: One stop bit is transmitted at the end of frame
+ * @arg USART_StopBits_2: Two stop bits are transmitted at the end of frame
+ * @arg USART_StopBits_1_5: One and half stop bits
+ * @param USART_Parity: Parity
+ * This parameter can be one of the following values:
+ * @arg USART_Parity_No: No Parity
+ * @arg USART_Parity_Even: Even Parity
+ * @arg USART_Parity_Odd: Odd Parity
+ * @param USART_Mode: Mode
+ * This parameter can be one of the following values:
+ * @arg USART_Mode_Rx: Receive Enable
+ * @arg USART_Mode_Tx: Transmit Enable
+ * @retval None
+ */
+void USART_Init(USART_TypeDef* USARTx, uint32_t BaudRate, USART_WordLength_TypeDef
+ USART_WordLength, USART_StopBits_TypeDef USART_StopBits,
+ USART_Parity_TypeDef USART_Parity, USART_Mode_TypeDef USART_Mode)
+{
+ uint32_t BaudRate_Mantissa = 0;
+
+ /* Check the parameters */
+ assert_param(IS_USART_BAUDRATE(BaudRate));
+
+ assert_param(IS_USART_WORDLENGTH(USART_WordLength));
+
+ assert_param(IS_USART_STOPBITS(USART_StopBits));
+
+ assert_param(IS_USART_PARITY(USART_Parity));
+
+ assert_param(IS_USART_MODE(USART_Mode));
+
+ /* Clear the word length and Parity Control bits */
+ USARTx->CR1 &= (uint8_t)(~(USART_CR1_PCEN | USART_CR1_PS | USART_CR1_M));
+ /* Set the word length bit according to USART_WordLength value */
+ /* Set the Parity Control bit to USART_Parity value */
+ USARTx->CR1 |= (uint8_t)((uint8_t)USART_WordLength | (uint8_t)USART_Parity);
+
+ /* Clear the STOP bits */
+ USARTx->CR3 &= (uint8_t)(~USART_CR3_STOP);
+ /* Set the STOP bits number according to USART_StopBits value */
+ USARTx->CR3 |= (uint8_t)USART_StopBits;
+
+ /* Clear the LSB mantissa of USARTDIV */
+ USARTx->BRR1 &= (uint8_t)(~USART_BRR1_DIVM);
+ /* Clear the MSB mantissa of USARTDIV */
+ USARTx->BRR2 &= (uint8_t)(~USART_BRR2_DIVM);
+ /* Clear the Fraction bits of USARTDIV */
+ USARTx->BRR2 &= (uint8_t)(~USART_BRR2_DIVF);
+
+ BaudRate_Mantissa = (uint32_t)(CLK_GetClockFreq() / BaudRate );
+ /* Set the fraction of USARTDIV */
+ USARTx->BRR2 = (uint8_t)((BaudRate_Mantissa >> (uint8_t)8) & (uint8_t)0xF0);
+ /* Set the MSB mantissa of USARTDIV */
+ USARTx->BRR2 |= (uint8_t)(BaudRate_Mantissa & (uint8_t)0x0F);
+ /* Set the LSB mantissa of USARTDIV */
+ USARTx->BRR1 = (uint8_t)(BaudRate_Mantissa >> (uint8_t)4);
+
+ /* Disable the Transmitter and Receiver */
+ USARTx->CR2 &= (uint8_t)~(USART_CR2_TEN | USART_CR2_REN);
+ /* Set TEN and REN bits according to USART_Mode value */
+ USARTx->CR2 |= (uint8_t)USART_Mode;
+}
+
+/**
+ * @brief Initializes the USART Clock according to the specified parameters.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param USART_Clock: Clock
+ * This parameter can be one of the following values:
+ * @arg USART_Clock_Disable: CK pin disabled
+ * @arg USART_Clock_Enable: CK pin enabled
+ * @param USART_CPOL: Clock Polarity
+ * This parameter can be one of the following values:
+ * @arg USART_CPOL_Low: CK to 0 when idle
+ * @arg USART_CPOL_High: CK to 1 when idle
+ * @param USART_CPHA: Clock Phase
+ * This parameter can be one of the following values:
+ * @arg USART_CPHA_1Edge: The first clock transition is the first data capture edge
+ * @arg USART_CPHA_2Edge: The second clock transition is the first data capture edge
+ * @param USART_LastBit: Last Bit
+ * This parameter can be one of the following values:
+ * @arg USART_LastBit_Disable: The clock pulse of the last data bit is
+ * not output to the SCLK pin
+ * @arg USART_LastBit_Enable: The clock pulse of the last data bit is
+ * output to the SCLK pin
+ * @retval None
+ */
+void USART_ClockInit(USART_TypeDef* USARTx, USART_Clock_TypeDef USART_Clock,
+ USART_CPOL_TypeDef USART_CPOL, USART_CPHA_TypeDef USART_CPHA,
+ USART_LastBit_TypeDef USART_LastBit)
+{
+ /* Check the parameters */
+ assert_param(IS_USART_CLOCK(USART_Clock));
+ assert_param(IS_USART_CPOL(USART_CPOL));
+ assert_param(IS_USART_CPHA(USART_CPHA));
+ assert_param(IS_USART_LASTBIT(USART_LastBit));
+
+ /* Clear the Clock Polarity, lock Phase, Last Bit Clock pulse */
+ USARTx->CR3 &= (uint8_t)~(USART_CR3_CPOL | USART_CR3_CPHA | USART_CR3_LBCL);
+ /* Set the Clock Polarity, lock Phase, Last Bit Clock pulse */
+ USARTx->CR3 |= (uint8_t)((uint8_t)((uint8_t)(USART_CPOL | (uint8_t)USART_CPHA ) | USART_LastBit));
+
+ if (USART_Clock != USART_Clock_Disable)
+ {
+ USARTx->CR3 |= (uint8_t)(USART_CR3_CLKEN); /* Set the Clock Enable bit */
+ }
+ else
+ {
+ USARTx->CR3 &= (uint8_t)(~USART_CR3_CLKEN); /* Clear the Clock Enable bit */
+ }
+}
+
+/**
+ * @brief Enable the USART peripheral.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param NewState: The new state of the USART Communication.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)
+{
+ if (NewState != DISABLE)
+ {
+ USARTx->CR1 &= (uint8_t)(~USART_CR1_USARTD); /**< USART Enable */
+ }
+ else
+ {
+ USARTx->CR1 |= USART_CR1_USARTD; /**< USART Disable (for low power consumption) */
+ }
+}
+
+/**
+ * @brief Sets the system clock prescaler.
+ * @note IrDA Low Power mode or smartcard mode should be enabled
+ * @note This function is related to SmartCard and IrDa mode.
+ * @param USARTx: Select the USARTx peripheral.
+ * @param USART_Prescaler: specifies the prescaler clock.
+ * @note In IrDA Low Power Mode the clock source is divided by the value given
+ * in the register (8 bits)
+ * - 0000 0000 Reserved
+ * - 0000 0001 divides the clock source by 1
+ * - 0000 0010 divides the clock source by 2
+ * - ...
+ * @note In Smart Card Mode the clock source is divided by the value given in the register
+ * (5 significant bits) multiplied by 2
+ * - 0 0000 Reserved
+ * - 0 0001 divides the clock source by 2
+ * - 0 0010 divides the clock source by 4
+ * - 0 0011 divides the clock source by 6
+ * - ...
+ * @retval None
+ */
+void USART_SetPrescaler(USART_TypeDef* USARTx, uint8_t USART_Prescaler)
+{
+ /* Load the USART prescaler value*/
+ USARTx->PSCR = USART_Prescaler;
+}
+
+/**
+ * @brief Transmits break characters.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @retval None
+ */
+void USART_SendBreak(USART_TypeDef* USARTx)
+{
+ USARTx->CR2 |= USART_CR2_SBK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup USART_Group2 Data transfers functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ===============================================================================
+ Data transfers functions
+ ===============================================================================
+
+ This subsection provides a set of functions allowing to manage the USART data
+ transfers.
+
+ During an USART reception, data shifts in least significant bit first through
+ the RX pin. In this mode, the USART_DR register is similar to a buffer (RDR)
+ between the internal bus and the received shift register.
+
+ When a transmission is taking place, a write instruction to the USART_DR register
+ stores the data in the TDR register which is copied in the shift register
+ at the end of the current transmission.
+
+ The read access of the USART_DR register can be done using the USART_ReceiveData8()
+ or USART_ReceiveData9() functions and returns the RDR buffered value. Whereas a write
+ access to the USART_DR can be done using USART_SendData8() or USART_SendData9()
+ functions and stores the written data into TDR buffer.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns the most recent received data by the USART peripheral.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @retval The received data.
+ */
+uint8_t USART_ReceiveData8(USART_TypeDef* USARTx)
+{
+ return USARTx->DR;
+}
+
+/**
+ * @brief Returns the most recent received data by the USART peripheral.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @retval The received data.
+ */
+uint16_t USART_ReceiveData9(USART_TypeDef* USARTx)
+{
+ uint16_t temp = 0;
+
+ temp = ((uint16_t)(((uint16_t)((uint16_t)USARTx->CR1 & (uint16_t)USART_CR1_R8)) << 1));
+ return (uint16_t)( ((uint16_t)((uint16_t)USARTx->DR) | temp) & ((uint16_t)0x01FF));
+}
+
+/**
+ * @brief Transmits 8 bit data through the USART peripheral.
+ * @param Data: The data to transmit.
+ * @retval None
+ */
+void USART_SendData8(USART_TypeDef* USARTx, uint8_t Data)
+{
+ /* Transmit Data */
+ USARTx->DR = Data;
+}
+
+/**
+ * @brief Transmits 9 bit data through the USART peripheral.
+ * @param USARTx: Select the USARTx peripheral.
+ * @param Data: The data to transmit.
+ * This parameter should be lower than 0x1FF.
+ * @retval None
+ */
+void USART_SendData9(USART_TypeDef* USARTx, uint16_t Data)
+{
+ assert_param(IS_USART_DATA_9BITS(Data));
+
+ /* Clear the transmit data bit 8 */
+ USARTx->CR1 &= ((uint8_t)~USART_CR1_T8);
+
+ /* Write the transmit data bit [8] */
+ USARTx->CR1 |= (uint8_t)(((uint8_t)(Data >> 2)) & USART_CR1_T8);
+
+ /* Write the transmit data bit [0:7] */
+ USARTx->DR = (uint8_t)(Data);
+}
+/**
+ * @}
+ */
+
+/** @defgroup USART_Group3 MultiProcessor Communication functions
+ * @brief Multi-Processor Communication functions
+ *
+@verbatim
+ ===============================================================================
+ Multi-Processor Communication functions
+ ===============================================================================
+
+ This subsection provides a set of functions allowing to manage the USART
+ multiprocessor communication.
+
+ For instance one of the USARTs can be the master, its TX output is connected to
+ the RX input of the other USART. The others are slaves, their respective TX outputs
+ are logically ANDed together and connected to the RX input of the master.
+
+ USART multiprocessor communication is possible through the following procedure:
+ 1. Program the Baud rate, Word length = 9 bits, Stop bits, Parity, Mode transmitter
+ or Mode receiver and hardware flow control values using the USART_Init()
+ function.
+ 2. Configures the USART address using the USART_SetAddress() function.
+ 3. Configures the wake up method (USART_WakeUp_IdleLine or USART_WakeUp_AddressMark)
+ using USART_WakeUpConfig() function only for the slaves.
+ 4. Enable the USART using the USART_Cmd() function.
+ 5. Enter the USART slaves in mute mode using USART_ReceiverWakeUpCmd() function.
+
+ The USART Slave exit from mute mode when receiving the wake up condition.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Determines if the USART is in mute mode or not.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param NewState: The new state of the USART mode.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void USART_ReceiverWakeUpCmd(USART_TypeDef* USARTx, FunctionalState NewState)
+{
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the mute mode USART by setting the RWU bit in the CR2 register */
+ USARTx->CR2 |= USART_CR2_RWU;
+ }
+ else
+ {
+ /* Disable the mute mode USART by clearing the RWU bit in the CR1 register */
+ USARTx->CR2 &= ((uint8_t)~USART_CR2_RWU);
+ }
+}
+
+/**
+ * @brief Sets the address of the USART node.
+ * @param USARTx: Select the USARTx peripheral.
+ * @param Address: Indicates the address of the USART node.
+ * This parameter should be lower than 16
+ * @retval None
+ */
+void USART_SetAddress(USART_TypeDef* USARTx, uint8_t USART_Address)
+{
+ /* assert_param for USART_Address */
+ assert_param(IS_USART_ADDRESS(USART_Address));
+
+ /* Clear the USART address */
+ USARTx->CR4 &= ((uint8_t)~USART_CR4_ADD);
+ /* Set the USART address node */
+ USARTx->CR4 |= USART_Address;
+}
+
+/**
+ * @brief Selects the USART WakeUp method.
+ * @param USART_WakeUp: Specifies the USART wakeup method.
+ * This parameter can be one of the following values:
+ * @arg USART_WakeUp_IdleLine: 0x01 Idle Line wake up
+ * @arg USART_WakeUp_AddressMark: 0x02 Address Mark wake up
+ * @retval None
+ */
+void USART_WakeUpConfig(USART_TypeDef* USARTx, USART_WakeUp_TypeDef USART_WakeUp)
+{
+ assert_param(IS_USART_WAKEUP(USART_WakeUp));
+
+ USARTx->CR1 &= ((uint8_t)~USART_CR1_WAKE);
+ USARTx->CR1 |= (uint8_t)USART_WakeUp;
+}
+/**
+ * @}
+ */
+
+/** @defgroup USART_Group4 Halfduplex mode function
+ * @brief Half-duplex mode function
+ *
+@verbatim
+ ===============================================================================
+ Half-duplex mode function
+ ===============================================================================
+
+ This subsection provides a function allowing to manage the USART
+ Half-duplex communication.
+
+ The USART can be configured to follow a single-wire half-duplex protocol where
+ the TX and RX lines are internally connected.
+
+ USART Half duplex communication is possible through the following procedure:
+ 1. Program the Baud rate, Word length, Stop bits, Parity, Mode transmitter
+ or Mode receiver and hardware flow control values using the USART_Init()
+ function.
+ 2. Configures the USART address using the USART_SetAddress() function.
+ 3. Enable the USART using the USART_Cmd() function.
+ 4. Enable the half duplex mode using USART_HalfDuplexCmd() function.
+
+Note:
+----
+ 1. The RX pin is no longer used
+ 2. In Half-duplex mode the following bits must be kept cleared:
+ - CLKEN bits in the USART_CR3 register.
+ - SCEN and IREN bits in the USART_CR5 register.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the USART’s Half Duplex communication.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param NewState new state of the USART Communication.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState NewState)
+{
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ USARTx->CR5 |= USART_CR5_HDSEL; /**< USART Half Duplex Enable */
+ }
+ else
+ {
+ USARTx->CR5 &= (uint8_t)~USART_CR5_HDSEL; /**< USART Half Duplex Disable */
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup USART_Group5 Smartcard mode functions
+ * @brief Smartcard mode functions
+ *
+@verbatim
+ ===============================================================================
+ Smartcard mode functions
+ ===============================================================================
+
+ This subsection provides a set of functions allowing to manage the USART
+ Smartcard communication.
+
+ The Smartcard interface is designed to support asynchronous protocol Smartcards as
+ defined in the ISO 7816-3 standard.
+
+ The USART can provide a clock to the smartcard through the SCLK output.
+ In smartcard mode, SCLK is not associated to the communication but is simply derived
+ from the internal peripheral input clock through a 5-bit prescaler.
+
+ Smartcard communication is possible through the following procedure:
+ 1. Configures the Smartcard Prsecaler using the USART_SetPrescaler() function.
+ 2. Configures the Smartcard Guard Time using the USART_SetGuardTime() function.
+ 3. Program the USART clock using the USART_ClockInit() function as following:
+ - USART Clock enabled
+ - USART CPOL Low
+ - USART CPHA on first edge
+ - USART Last Bit Clock Enabled
+ 4. Program the Smartcard interface using the USART_Init() function as following:
+ - Word Length = 9 Bits
+ - 1.5 Stop Bit
+ - Even parity
+ - BaudRate = 12096 baud
+ - Hardware flow control disabled (RTS and CTS signals)
+ - Tx and Rx enabled
+ 5. Optionally you can enable the parity error interrupt using the USART_ITConfig()
+ function
+ 6. Enable the USART using the USART_Cmd() function.
+ 7. Enable the Smartcard NACK using the USART_SmartCardNACKCmd() function.
+ 8. Enable the Smartcard interface using the USART_SmartCardCmd() function.
+
+ Please refer to the ISO 7816-3 specification for more details.
+
+Note:
+-----
+ 1. It is also possible to choose 0.5 stop bit for receiving but it is recommended
+ to use 1.5 stop bits for both transmitting and receiving to avoid switching
+ between the two configurations.
+ 2. In smartcard mode, the following bits must be kept cleared:
+ - HDSEL and IREN bits in the USART_CR5 register.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the USART Smart Card mode.
+ * @param USARTx: Select the USARTx peripheral.
+ * @param NewState: new state of the Smart Card mode.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState NewState)
+{
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the SC mode by setting the SCEN bit in the CR5 register */
+ USARTx->CR5 |= USART_CR5_SCEN;
+ }
+ else
+ {
+ /* Disable the SC mode by clearing the SCEN bit in the CR5 register */
+ USARTx->CR5 &= ((uint8_t)(~USART_CR5_SCEN));
+ }
+}
+
+/**
+ * @brief Enables or disables NACK transmission.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param NewState: new state of the Smart Card mode.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState NewState)
+{
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the NACK transmission by setting the NACK bit in the CR5 register */
+ USARTx->CR5 |= USART_CR5_NACK;
+ }
+ else
+ {
+ /* Disable the NACK transmission by clearing the NACK bit in the CR5 register */
+ USARTx->CR5 &= ((uint8_t)~(USART_CR5_NACK));
+ }
+}
+
+/**
+ * @brief Sets the specified USART guard time.
+ * @note SmartCard Mode should be Enabled
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param USART_GuardTime: specifies the guard time.
+ * @retval None
+ */
+void USART_SetGuardTime(USART_TypeDef* USARTx, uint8_t USART_GuardTime)
+{
+ /* Set the USART guard time */
+ USARTx->GTR = USART_GuardTime;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup USART_Group6 IrDA mode functions
+ * @brief IrDA mode functions
+ *
+@verbatim
+ ===============================================================================
+ IrDA mode functions
+ ===============================================================================
+
+ This subsection provides a set of functions allowing to manage the USART
+ IrDA communication.
+
+ IrDA is a half duplex communication protocol. If the Transmitter is busy, any data
+ on the IrDA receive line will be ignored by the IrDA decoder and if the Receiver
+ is busy, data on the TX from the USART to IrDA will not be encoded by IrDA.
+ While receiving data, transmission should be avoided as the data to be transmitted
+ could be corrupted.
+
+ IrDA communication is possible through the following procedure:
+ 1. Program the Baud rate, Word length = 8 bits, Stop bits, Parity, Transmitter/Receiver
+ modes and hardware flow control values using the USART_Init() function.
+ 2. Enable the USART using the USART_Cmd() function.
+ 3. Configures the IrDA pulse width by configuring the prescaler using
+ the USART_SetPrescaler() function.
+ 4. Configures the IrDA USART_IrDAMode_LowPower or USART_IrDAMode_Normal mode
+ using the USART_IrDAConfig() function.
+ 5. Enable the IrDA using the USART_IrDACmd() function.
+
+Note:
+-----
+ 1. A pulse of width less than two and greater than one PSC period(s) may or may
+ not be rejected.
+ 2. The receiver set up time should be managed by software. The IrDA physical layer
+ specification specifies a minimum of 10 ms delay between transmission and
+ reception (IrDA is a half duplex protocol).
+ 3. In IrDA mode, the following bits must be kept cleared:
+ - STOP and CLKEN bits in the USART_CR3 register.
+ - SCEN and HDSEL bits in the USART_CR5 register.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configures the USART’s IrDA interface.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param USART_IrDAMode specifies the IrDA mode.
+ * This parameter can be one of the following values:
+ * @arg USART_IrDAMode_Normal: IrDA Normal Mode
+ * @arg USART_IrDAMode_LowPower: IrDA Low Power Mode
+ * @retval None
+ */
+void USART_IrDAConfig(USART_TypeDef* USARTx, USART_IrDAMode_TypeDef USART_IrDAMode)
+{
+ assert_param(IS_USART_IRDAMODE(USART_IrDAMode));
+
+ if (USART_IrDAMode != USART_IrDAMode_Normal)
+ {
+ USARTx->CR5 |= USART_CR5_IRLP;
+ }
+ else
+ {
+ USARTx->CR5 &= ((uint8_t)~USART_CR5_IRLP);
+ }
+}
+
+/**
+ * @brief Enables or disables the USART’s IrDA interface.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param NewState new state of the IrDA mode.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void USART_IrDACmd(USART_TypeDef* USARTx, FunctionalState NewState)
+{
+
+ /* Check parameters */
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the IrDA mode by setting the IREN bit in the CR3 register */
+ USARTx->CR5 |= USART_CR5_IREN;
+ }
+ else
+ {
+ /* Disable the IrDA mode by clearing the IREN bit in the CR3 register */
+ USARTx->CR5 &= ((uint8_t)~USART_CR5_IREN);
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup USART_Group7 DMA transfers management functions
+ * @brief DMA transfers management functions
+ *
+@verbatim
+ ===============================================================================
+ DMA transfers management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Enables or disables the USART DMA interface.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param USART_DMAReq Specifies the USART DMA transfer request to be enabled or disabled.
+ * This parameter can be one of the following values:
+ * @arg USART_DMAReq_TX: Receive DMA request Enable
+ * @arg USART_DMAReq_RX: Transmit DMA request Enable
+ * @param NewState Indicates the new state of the USART DMA request.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void USART_DMACmd(USART_TypeDef* USARTx, USART_DMAReq_TypeDef USART_DMAReq,
+ FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_USART_DMAREQ(USART_DMAReq));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the DMA transfer for selected requests by setting the DMAT and/or
+ DMAR bits in the USART CR5 register */
+ USARTx->CR5 |= (uint8_t) USART_DMAReq;
+ }
+ else
+ {
+ /* Disable the DMA transfer for selected requests by clearing the DMAT and/or
+ DMAR bits in the USART CR5 register */
+ USARTx->CR5 &= (uint8_t)~USART_DMAReq;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup USART_Group8 Interrupts and flags management functions
+ * @brief Interrupts and flags management functions
+ *
+@verbatim
+ ===============================================================================
+ Interrupts and flags management functions
+ ===============================================================================
+
+ This subsection provides a set of functions allowing to configure the USART
+ Interrupts sources, DMA channels requests and check or clear the flags or
+ pending bits status.
+ The user should identify which mode will be used in his application to manage
+ the communication: Polling mode, Interrupt mode or DMA mode.
+
+ Polling Mode
+ =============
+ In Polling Mode, the USART communication can be managed by 9 flags:
+ 1. USART_FLAG_TXE: to indicate the status of the transmit buffer register
+ 2. USART_FLAG_RXNE: to indicate the status of the receive buffer register
+ 3. USART_FLAG_TC: to indicate the status of the transmit operation
+ 4. USART_FLAG_IDLE: to indicate the status of the Idle Line
+ 5. USART_FLAG_SBK: to indicate the status of the Send Break characters
+ 6. USART_FLAG_NE: to indicate if a noise error occur
+ 7. USART_FLAG_FE: to indicate if a frame error occur
+ 8. USART_FLAG_PE: to indicate if a parity error occur
+ 9. USART_FLAG_ORE: to indicate if an Overrun error occur
+
+ In this Mode it is advised to use the following functions:
+ - FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, USART_FLAG_TypeDef USART_FLAG);
+ - void USART_ClearFlag(USART_TypeDef* USARTx, USART_FLAG_TypeDef USART_FLAG);
+
+ Interrupt Mode
+ ===============
+ In Interrupt Mode, the USART communication can be managed by 7 interrupt sources
+ and 6 pending bits:
+
+ Pending Bits:
+ -------------
+ 1. USART_IT_TXE: to indicate the status of the transmit buffer register
+ 2. USART_IT_RXNE: to indicate the status of the receive buffer register
+ 3. USART_IT_TC: to indicate the status of the transmit operation
+ 4. USART_IT_IDLE: to indicate the status of the Idle Line
+ 5. USART_IT_PE: to indicate if a parity error occur
+ 6. USART_IT_OR: to indicate if an Noise flag, overrun error and framing error in
+ multibuffer communication error occur
+
+ Interrupt Source:
+ -----------------
+ 1. USART_IT_TXE: specifies the interrupt source for the Tx buffer empty
+ interrupt.
+ 2. USART_IT_RXNE: specifies the interrupt source for the Rx buffer not
+ empty interrupt.
+ 3. USART_IT_TC: specifies the interrupt source for the Transmit complete
+ interrupt.
+ 4. USART_IT_IDLE: specifies the interrupt source for the Idle Line interrupt.
+ 5. USART_IT_PE: specifies the interrupt source for the parity error interrupt.
+ 6. USART_IT_ERR: specifies the interrupt source for the errors interrupt.
+ 7. USART_IT_OR: specifies the interrupt source for the overrun error interrupt.
+
+ Note: Some parameters are coded in order to use them as interrupt source or
+ ---- as pending bits.
+
+ In this Mode it is advised to use the following functions:
+ - void USART_ITConfig(USART_TypeDef* USARTx, USART_IT_TypeDef USART_IT, FunctionalState
+ NewState);
+ - ITStatus USART_GetITStatus(USART_TypeDef* USARTx, USART_IT_TypeDef USART_IT);
+ - void USART_ClearITPendingBit(USART_TypeDef* USARTx, USART_IT_TypeDef USART_IT);
+
+ DMA Mode
+ ========
+ In DMA Mode, the USART communication can be managed by 2 DMA Channel requests:
+ 1. USART_DMAReq_Tx: specifies the Tx buffer DMA transfer request
+ 2. USART_DMAReq_Rx: specifies the Rx buffer DMA transfer request
+
+ In this Mode it is advised to use the following function:
+ - void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState);
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables or disables the specified USART interrupts.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param USART_IT specifies the USART interrupt sources to be enabled or disabled.
+ * This parameter can be one of the following values:
+ * @arg USART_IT_TXE: Transmit Data Register empty interrupt
+ * @arg USART_IT_TC: Transmission complete interrupt
+ * @arg USART_IT_RXNE: Receive Data register not empty interrupt
+ * @arg USART_IT_OR: Overrun error interrupt
+ * @arg USART_IT_IDLE: Idle line detection interrupt
+ * @arg USART_IT_ERR: Error interrupt
+ * @param NewState new state of the specified USART interrupts.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void USART_ITConfig(USART_TypeDef* USARTx, USART_IT_TypeDef USART_IT, FunctionalState NewState)
+{
+ uint8_t usartreg, itpos = 0x00;
+ assert_param(IS_USART_CONFIG_IT(USART_IT));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* Get the USART register index */
+ usartreg = (uint8_t)((uint16_t)USART_IT >> 0x08);
+ /* Get the USART IT index */
+ itpos = (uint8_t)((uint8_t)1 << (uint8_t)((uint8_t)USART_IT & (uint8_t)0x0F));
+
+ if (NewState != DISABLE)
+ {
+ /**< Enable the Interrupt bits according to USART_IT mask */
+ if (usartreg == 0x01)
+ {
+ USARTx->CR1 |= itpos;
+ }
+ else if (usartreg == 0x05)
+ {
+ USARTx->CR5 |= itpos;
+ }
+ /*uartreg =0x02*/
+ else
+ {
+ USARTx->CR2 |= itpos;
+ }
+ }
+ else
+ {
+ /**< Disable the interrupt bits according to USART_IT mask */
+ if (usartreg == 0x01)
+ {
+ USARTx->CR1 &= (uint8_t)(~itpos);
+ }
+ else if (usartreg == 0x05)
+ {
+ USARTx->CR5 &= (uint8_t)(~itpos);
+ }
+ /*uartreg =0x02*/
+ else
+ {
+ USARTx->CR2 &= (uint8_t)(~itpos);
+ }
+ }
+}
+
+/**
+ * @brief Checks whether the specified USART flag is set or not.
+ * @param USARTx: Select the USARTx peripheral.
+ * @param USART_FLAG specifies the flag to check.
+ * This parameter can be one of the following values:
+ * @arg USART_FLAG_TXE: Transmit Data Register empty
+ * @arg USART_FLAG_TC: Transmission Complete
+ * @arg USART_FLAG_RXNE: Read Data Register Not Empty
+ * @arg USART_FLAG_IDLE: Idle line detected
+ * @arg USART_FLAG_OR: OverRun error
+ * @arg USART_FLAG_NF: Noise error
+ * @arg USART_FLAG_FE: Framing Error
+ * @arg USART_FLAG_PE: Parity Error
+ * @arg USART_FLAG_SBK: Send Break characters
+ * @retval FlagStatus (SET or RESET)
+ */
+FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, USART_FLAG_TypeDef USART_FLAG)
+{
+ FlagStatus status = RESET;
+
+ /* Check parameters */
+ assert_param(IS_USART_FLAG(USART_FLAG));
+
+ if (USART_FLAG == USART_FLAG_SBK)
+ {
+ if ((USARTx->CR2 & (uint8_t)USART_FLAG) != (uint8_t)0x00)
+ {
+ /* USART_FLAG is set*/
+ status = SET;
+ }
+ else
+ {
+ /* USART_FLAG is reset*/
+ status = RESET;
+ }
+ }
+ else
+ {
+ if ((USARTx->SR & (uint8_t)USART_FLAG) != (uint8_t)0x00)
+ {
+ /* USART_FLAG is set*/
+ status = SET;
+ }
+ else
+ {
+ /* USART_FLAG is reset*/
+ status = RESET;
+ }
+ }
+ /* Return the USART_FLAG status*/
+ return status;
+}
+
+/**
+ * @brief Clears the USARTx's pending flags.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param USART_FLAG: specifies the flag to clear.
+ * This parameter can be any combination of the following values:
+ * @arg USART_FLAG_TC: Transmission Complete flag.
+ * @arg USART_FLAG_RXNE: Receive data register not empty flag.
+ * @note PE (Parity error), FE (Framing error), NE (Noise error), OR (OverRun error)
+ * and IDLE (Idle line detected) flags are cleared by software sequence: a read
+ * operation to USART_SR register (USART_GetFlagStatus())followed by a read
+ * operation to USART_DR register(USART_ReceiveData8() or USART_ReceiveData9()).
+ * @note RXNE flag can be also cleared by a read to the USART_DR register
+ * (USART_ReceiveData8()or USART_ReceiveData9()).
+ * @note TC flag can be also cleared by software sequence: a read operation to USART_SR
+ * register (USART_GetFlagStatus()) followed by a write operation to USART_DR
+ * register (USART_SendData8() or USART_SendData9()).
+ * @note TXE flag is cleared only by a write to the USART_DR register
+ * (USART_SendData8() or USART_SendData9()).
+ * @note SBK flag is cleared during the stop bit of break.
+ * @retval None
+ */
+void USART_ClearFlag(USART_TypeDef* USARTx, USART_FLAG_TypeDef USART_FLAG)
+{
+ /* Check the parameters */
+ assert_param(IS_USART_CLEAR_FLAG(USART_FLAG));
+ /*< Clear RXNE or TC flags */
+ USARTx->SR = (uint8_t)((uint16_t)~((uint16_t)USART_FLAG));
+}
+
+/**
+ * @brief Checks whether the specified USART interrupt has occurred or not.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param USART_IT: Specifies the USART interrupt pending bit to check.
+ * This parameter can be one of the following values:
+ * @arg USART_IT_TXE: Transmit Data Register empty interrupt
+ * @arg USART_IT_TC: Transmission complete interrupt
+ * @arg USART_IT_RXNE: Receive Data register not empty interrupt
+ * @arg USART_IT_IDLE: Idle line detection interrupt
+ * @arg USART_IT_OR: OverRun Error interrupt
+ * @arg USART_IT_PE: Parity Error interrupt
+ * @arg USART_IT_FE: Frame Error interrupt
+ * @arg USART_IT_NF: Noise Flag Error interrupt
+ * @retval ITStatus The new state of USART_IT (SET or RESET).
+ */
+ITStatus USART_GetITStatus(USART_TypeDef* USARTx, USART_IT_TypeDef USART_IT)
+{
+ ITStatus pendingbitstatus = RESET;
+ uint8_t temp = 0;
+ uint8_t itpos = 0;
+ uint8_t itmask1 = 0;
+ uint8_t itmask2 = 0;
+ uint8_t enablestatus = 0;
+
+ /* Check parameters */
+ assert_param(IS_USART_GET_IT(USART_IT));
+
+ /* Get the USART IT index */
+ itpos = (uint8_t)((uint8_t)1 << (uint8_t)((uint8_t)USART_IT & (uint8_t)0x0F));
+ /* Get the USART IT index */
+ itmask1 = (uint8_t)((uint8_t)USART_IT >> (uint8_t)4);
+ /* Set the IT mask*/
+ itmask2 = (uint8_t)((uint8_t)1 << itmask1);
+
+ /* Check the status of the specified USART pending bit*/
+ if (USART_IT == USART_IT_PE)
+ {
+ /* Get the USART_IT enable bit status*/
+ enablestatus = (uint8_t)((uint8_t)USARTx->CR1 & itmask2);
+ /* Check the status of the specified USART interrupt*/
+
+ if (((USARTx->SR & itpos) != (uint8_t)0x00) && enablestatus)
+ {
+ /* Interrupt occurred*/
+ pendingbitstatus = SET;
+ }
+ else
+ {
+ /* Interrupt not occurred*/
+ pendingbitstatus = RESET;
+ }
+ }
+
+ else if (USART_IT == USART_IT_OR)
+ {
+ /* Get the USART_IT enable bit status*/
+ enablestatus = (uint8_t)((uint8_t)USARTx->CR2 & itmask2);
+ /* Check the status of the specified USART interrupt*/
+
+ temp = (uint8_t)(USARTx->CR5 & USART_CR5_EIE);
+
+ if (( (USARTx->SR & itpos) != 0x00) && ((enablestatus || temp)))
+ {
+ /* Interrupt occurred*/
+ pendingbitstatus = SET;
+ }
+ else
+ {
+ /* Interrupt not occurred*/
+ pendingbitstatus = RESET;
+ }
+ }
+
+ else
+ {
+ /* Get the USART_IT enable bit status*/
+ enablestatus = (uint8_t)((uint8_t)USARTx->CR2 & itmask2);
+ /* Check the status of the specified USART interrupt*/
+ if (((USARTx->SR & itpos) != (uint8_t)0x00) && enablestatus)
+ {
+ /* Interrupt occurred*/
+ pendingbitstatus = SET;
+ }
+ else
+ {
+ /* Interrupt not occurred*/
+ pendingbitstatus = RESET;
+ }
+ }
+
+ /* Return the USART_IT status*/
+ return pendingbitstatus;
+}
+
+/**
+ * @brief Clears the USARTx’s interrupt pending bits.
+ * @param USARTx: where x can be 1 to select the specified USART peripheral.
+ * @param USART_IT: specifies the interrupt pending bit to clear.
+ * This parameter can be one of the following values:
+ * @arg USART_IT_TC: Transmission complete interrupt.
+ * @note PE (Parity error), FE (Framing error), NE (Noise error),
+ * OR (OverRun error) and IDLE (Idle line detected) pending bits are
+ * cleared by software sequence: a read operation to USART_SR register
+ * (USART_GetITStatus()) followed by a read operation to USART_DR
+ * register (USART_ReceiveData8() or USART_ReceiveData9()).
+ * @note RXNE pending bit can be also cleared by a read to the USART_DR register
+ * (USART_ReceiveData8() or USART_ReceiveData9()).
+ * @note TC (Transmit complete) pending bit can be also cleared by software
+ * sequence: a read operation to USART_SR register (USART_GetITStatus())
+ * followed by a write operation to USART_DR register (USART_SendData8()
+ * or USART_SendData9()).
+ * @note TXE pending bit is cleared only by a write to the USART_DR register
+ * (USART_SendData8() or USART_SendData9()).
+ * @retval None
+ */
+void USART_ClearITPendingBit(USART_TypeDef* USARTx, USART_IT_TypeDef USART_IT)
+{
+ assert_param(IS_USART_CLEAR_IT(USART_IT));
+
+ /*< Clear RXNE or TC pending bit */
+ USARTx->SR &= (uint8_t)(~USART_SR_TC);
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_wfe.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_wfe.c
new file mode 100644
index 00000000..03694476
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_wfe.c
@@ -0,0 +1,348 @@
+/**
+ ******************************************************************************
+ * @file stm8l15x_wfe.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Wait for Event (WFE) peripheral:
+ * - WFE Source configuration and management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * WFE specific features
+ * ===================================================================
+ *
+ * Wait for event mode (WFE) stops the CPU but allows the other peripherals
+ * and interrupt controller to continue running.
+ * This mode is entered from Run mode by executing a WFE instruction.
+ * Peripheral events can be generated by the timers, serial interfaces,
+ * DMA controller, comparators and I/O ports.
+ * These are enabled by using the WFE_WakeUpSourceEventCmd() function.
+ *
+ * When a peripheral event is enabled, the corresponding interrupts are
+ * not served and you have to clear the corresponding flag status.
+ *
+ * There are two ways to wake up the CPU from WFE mode:
+ * - Interrupts: When an interrupt occurs, the CPU wakes up from WFE mode
+ * serves the interrupt then goes back to WFE mode.
+ * - Wake up event: when a wake up event occurs, the CPU wakes up and
+ * resumes processing, in this case and to save time and power consumption
+ * there is no context save/restore activity.
+ *
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_wfe.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+
+/** @defgroup WFE
+ * @brief WFE driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup WFE_Private_Functions
+ * @{
+ */
+
+/** @defgroup WFE_Group1 WFE Source configuration and management functions
+ * @brief WFE Source configuration and management functions
+ *
+@verbatim
+ ===============================================================================
+ WFE Source configuration and management functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitializes the WFE registers to their default reset value.
+ * @param None
+ * @retval None
+ */
+void WFE_DeInit(void)
+{
+ WFE->CR1 = WFE_CRX_RESET_VALUE;
+ WFE->CR2 = WFE_CRX_RESET_VALUE;
+ WFE->CR3 = WFE_CRX_RESET_VALUE;
+ WFE->CR4 = WFE_CRX_RESET_VALUE;
+}
+
+/**
+ * @brief Set the source that can generate the wake-up event.
+ * @param WFE_Source: The wake-up event source .
+ * This parameter can be one of the following values:
+ * @arg WFE_Source_TIM2_EV0: TIM2 Update/Trigger and Break interrupt
+ * @arg WFE_Source_TIM2_EV1: TIM2 Capture/Compare interrupt
+ * @arg WFE_Source_TIM1_EV0: TIM1 Update/Trigger and Break interrupt
+ * @arg WFE_Source_TIM1_EV1: TIM1 Capture/Compare interrupt
+ * @arg WFE_Source_EXTI_EV0: I/O port interrupt from Pins 0
+ * @arg WFE_Source_EXTI_EV1: I/O port interrupt from Pins 1
+ * @arg WFE_Source_EXTI_EV2: I/O port interrupt from Pins 2
+ * @arg WFE_Source_EXTI_EV3: I/O port interrupt from Pins 3
+ * @arg WFE_Source_EXTI_EV4: I/O port interrupt from Pins 4
+ * @arg WFE_Source_EXTI_EV5: I/O port interrupt from Pins 5
+ * @arg WFE_Source_EXTI_EV6: I/O port interrupt from Pins 6
+ * @arg WFE_Source_EXTI_EV7: I/O port interrupt from Pins 7
+ * @arg WFE_Source_EXTI_EVB_G: I/O port interrupt from port B and G
+ * @arg WFE_Source_EXTI_EVD_H: I/O port interrupt from Port D and H
+ * @arg WFE_Source_EXTI_EVE_F: I/O port interrupt from Port E and F
+ * @arg WFE_Source_ADC1_COMP_EV: ADC1, COMP1 and COMP2 interrupts
+ * @arg WFE_Source_TIM3_EV0: TIM3 Update/Trigger and Break interrupt
+ * @arg WFE_Source_TIM3_EV1: TIM3 Capture/Compare interrupt
+ * @arg WFE_Source_TIM4_EV: TIM4 Update and Trigger interrupt
+ * @arg WFE_Source_SPI1_EV: SPI1 Rx and Tx interrupt
+ * @arg WFE_Source_I2C1_EV: I2C1 Rx and Tx interrupt
+ * @arg WFE_Source_USART1_EV: USART1 Rx and Tx interrupt
+ * @arg WFE_Source_DMA1CH01_EV: DMA1 channel 0 and 1 interrupt
+ * @arg WFE_Source_DMA1CH23_EV: DMA1 channel 2 and 3 interrupt
+ * @arg WFE_Source_RTC_CSS_EV: RTC or CSS on LSE event
+ * @arg WFE_Source_SPI2_EV: SPI2 Rx and Tx interrupt
+ * @arg WFE_Source_USART2_EV: USART2 Rx and Tx interrupt
+ * @arg WFE_Source_USART3_EV: USART3 Rx and Tx interrupt
+ * @arg WFE_Source_TIM5_EV0: TIM5 Update/Trigger and Break interrupt
+ * @arg WFE_Source_TIM5_EV1: TIM5 Capture/Compare interrupt
+ * @param NewState : The wake-up new state.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void WFE_WakeUpSourceEventCmd(WFE_Source_TypeDef WFE_Source, FunctionalState NewState)
+{
+ uint8_t register_index = 0;
+ /* Check function parameters */
+ assert_param(IS_WFE_SOURCE(WFE_Source));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ /* The mask is reversed in order to */
+ register_index = (uint8_t)((uint16_t)WFE_Source >> 0x08);
+
+ if (NewState != DISABLE)
+ {
+ switch (register_index)
+ {
+ case 1:
+ WFE->CR1 |= (uint8_t)WFE_Source;
+ break;
+
+ case 2:
+ WFE->CR2 |= (uint8_t)WFE_Source;
+ break;
+
+ case 3:
+ WFE->CR3 |= (uint8_t)WFE_Source;
+ break;
+
+ case 4:
+ WFE->CR4 |= (uint8_t)WFE_Source;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (register_index)
+ {
+ case 1:
+ WFE->CR1 &= (uint8_t)(~(uint8_t)WFE_Source);
+ break;
+
+ case 2:
+ WFE->CR2 &= (uint8_t)(~ (uint8_t)WFE_Source);
+ break;
+
+ case 3:
+ WFE->CR3 &= (uint8_t)(~(uint8_t)WFE_Source);
+ break;
+
+ case 4:
+ WFE->CR4 &= (uint8_t)(~(uint8_t)WFE_Source);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * @brief Gets the status of the specified source event.
+ * @param WFE_Source: The wake-up event source.
+ * This parameter can be one of the following values:
+ * @arg WFE_Source_TIM2_EV0: TIM2 Update/Trigger and Break interrupt
+ * @arg WFE_Source_TIM2_EV1: TIM2 Capture/Compare interrupt
+ * @arg WFE_Source_TIM1_EV0: TIM1 Update/Trigger and Break interrupt
+ * @arg WFE_Source_TIM1_EV1: TIM1 Capture/Compare interrupt
+ * @arg WFE_Source_EXTI_EV0: I/O port interrupt from Pins 0
+ * @arg WFE_Source_EXTI_EV1: I/O port interrupt from Pins 1
+ * @arg WFE_Source_EXTI_EV2: I/O port interrupt from Pins 2
+ * @arg WFE_Source_EXTI_EV3: I/O port interrupt from Pins 3
+ * @arg WFE_Source_EXTI_EV4: I/O port interrupt from Pins 4
+ * @arg WFE_Source_EXTI_EV5: I/O port interrupt from Pins 5
+ * @arg WFE_Source_EXTI_EV6: I/O port interrupt from Pins 6
+ * @arg WFE_Source_EXTI_EV7: I/O port interrupt from Pins 7
+ * @arg WFE_Source_EXTI_EVB_G: I/O port interrupt from port B and G
+ * @arg WFE_Source_EXTI_EVD_H: I/O port interrupt from Port D and H
+ * @arg WFE_Source_EXTI_EVE_F: I/O port interrupt from Port E and F
+ * @arg WFE_Source_ADC1_COMP_EV: ADC1, COMP1 and COMP2 interrupts
+ * @arg WFE_Source_TIM3_EV0: TIM3 Update/Trigger and Break interrupt
+ * @arg WFE_Source_TIM3_EV1: TIM3 Capture/Compare interrupt
+ * @arg WFE_Source_TIM4_EV: TIM4 Update and Trigger interrupt
+ * @arg WFE_Source_SPI1_EV: SPI1 Rx and Tx interrupt
+ * @arg WFE_Source_I2C1_EV: I2C1 Rx and Tx interrupt
+ * @arg WFE_Source_USART1_EV: USART1 Rx and Tx interrupt
+ * @arg WFE_Source_DMA1CH01_EV: DMA1 channel 0 and 1 interrupt
+ * @arg WFE_Source_DMA1CH23_EV: DMA1 channel 2 and 3 interrupt
+ * @arg WFE_Source_RTC_CSS_EV: RTC or CSS on LSE event
+ * @arg WFE_Source_SPI2_EV: SPI2 Rx and Tx interrupt
+ * @arg WFE_Source_USART2_EV: USART2 Rx and Tx interrupt
+ * @arg WFE_Source_USART3_EV: USART3 Rx and Tx interrupt
+ * @arg WFE_Source_TIM5_EV0: TIM5 Update/Trigger and Break interrupt
+ * @arg WFE_Source_TIM5_EV1: TIM5 Capture/Compare interrupt
+ * @retval Source Event state, ENABLE or DISABLE
+ */
+FunctionalState WFE_GetWakeUpSourceEventStatus(WFE_Source_TypeDef WFE_Source)
+{
+ FunctionalState status = DISABLE;
+ /* Check function parameters */
+ assert_param(IS_WFE_SOURCE(WFE_Source));
+
+ switch (WFE_Source)
+ {
+ case WFE_Source_TIM2_EV0:
+ case WFE_Source_TIM2_EV1:
+ case WFE_Source_TIM1_EV0:
+ case WFE_Source_TIM1_EV1:
+ case WFE_Source_EXTI_EV0:
+ case WFE_Source_EXTI_EV1:
+ case WFE_Source_EXTI_EV2:
+ case WFE_Source_EXTI_EV3:
+
+ if ((WFE->CR1 & (uint8_t)WFE_Source) != (uint8_t)0x00)
+ {
+ /* The wake-up event source is enabled*/
+ status = ENABLE;
+ }
+ else
+ {
+ /* The wake-up event source is disabled*/
+ status = DISABLE;
+ }
+ break;
+
+ case WFE_Source_EXTI_EV4:
+ case WFE_Source_EXTI_EV5:
+ case WFE_Source_EXTI_EV6:
+ case WFE_Source_EXTI_EV7:
+ case WFE_Source_EXTI_EVB_G:
+ case WFE_Source_EXTI_EVD_H:
+ case WFE_Source_EXTI_EVE_F:
+ case WFE_Source_ADC1_COMP_EV:
+
+ if ((WFE->CR2 & (uint8_t)WFE_Source) != (uint8_t)0x00)
+ {
+ /* The wake-up event source is enabled*/
+ status = ENABLE;
+ }
+ else
+ {
+ /* The wake-up event source is disabled*/
+ status = DISABLE;
+ }
+ break;
+ case WFE_Source_TIM3_EV0:
+ case WFE_Source_TIM3_EV1:
+ case WFE_Source_TIM4_EV:
+ case WFE_Source_SPI1_EV:
+ case WFE_Source_I2C1_EV:
+ case WFE_Source_USART1_EV:
+ case WFE_Source_DMA1CH01_EV:
+ case WFE_Source_DMA1CH23_EV:
+
+ if ((WFE->CR3 & (uint8_t)WFE_Source) != (uint8_t)0x00)
+ {
+ /* The wake-up event source is enabled*/
+ status = ENABLE;
+ }
+ else
+ {
+ /* The wake-up event source is disabled*/
+ status = DISABLE;
+ }
+ break;
+
+ case WFE_Source_TIM5_EV0:
+ case WFE_Source_TIM5_EV1:
+ case WFE_Source_AES_EV:
+ case WFE_Source_SPI2_EV:
+ case WFE_Source_USART2_EV:
+ case WFE_Source_USART3_EV:
+ case WFE_Source_RTC_CSS_EV:
+
+ if ((WFE->CR4 & (uint8_t)WFE_Source) != (uint8_t)0x00)
+ {
+ /* The wake-up event source is enabled*/
+ status = ENABLE;
+ }
+ else
+ {
+ /* The wake-up event source is disabled*/
+ status = DISABLE;
+ }
+ break;
+ default:
+ break;
+ }
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_wwdg.c b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_wwdg.c
new file mode 100644
index 00000000..3d9d706c
--- /dev/null
+++ b/ports/stm8l/STM8L15x_StdPeriph_Driver/src/stm8l15x_wwdg.c
@@ -0,0 +1,247 @@
+/**
+ ********************************************************************************
+ * @file stm8l15x_wwdg.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Window watchdog (WWDG) peripheral:
+ * - Refresh window and Counter configuration
+ * - WWDG activation
+ * - Couter and software reset management
+ *
+ * @verbatim
+ *
+ * ===================================================================
+ * WWDG features
+ * ===================================================================
+ *
+ * Once enabled the WWDG generates a system reset on expiry of a programmed
+ * time period, unless the program refreshes the counter (downcounter)
+ * before to reach 0x3F value (i.e. a reset is generated when the counter
+ * value rolls over from 0x40 to 0x3F).
+ * An MCU reset is also generated if the counter value is refreshed
+ * before the counter has reached the refresh window value. This
+ * implies that the counter must be refreshed in a limited window.
+ *
+ * Once enabled the WWDG cannot be disabled except by a system reset.
+ *
+ * If the WWDG is activated and the watchdog reset on halt option is
+ * selected (Option byte), then the HALT instruction will generate a reset.
+ *
+ * WWDGF flag in RST_SR register can be used to inform when a WWDG
+ * reset occurs.
+ *
+ * WWDG timeout = (WWDG counter clock) * 12288 * (T[5:0] + 1)
+ *
+ * Min-max timeout value @16 MHz(PCLK1): ~0.768 ms / ~49.152 ms
+ *
+ * ===================================================================
+ * How to use this driver
+ * ===================================================================
+ * 1. Configure the WWDG refresh window using WWDG_SetWindowValue() function
+ *
+ * 2. Set the WWDG counter value and start it using WWDG_Enable() function.
+ * When the WWDG is enabled the counter value should be configured to
+ * a value greater than 0x40 to prevent generating an immediate reset.
+ *
+ * 3. Then the application program must refresh the WWDG counter at regular
+ * intervals during normal operation to prevent an MCU reset, using
+ * WWDG_SetCounter() function. This operation must occur only when
+ * the counter value is lower than the refresh window value,
+ * programmed using WWDG_SetWindowValue().
+ *
+ * @endverbatim
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_wwdg.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Driver
+ * @{
+ */
+/** @defgroup WWDG
+ * @brief WWDG driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define BIT_MASK ((uint8_t)0x7F)
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup WWDG_Private_Functions
+ * @{
+ */
+
+/** @defgroup WWDG_Group1 Refresh window and Counter configuration functions
+ * @brief Refresh window and Counter configuration functions
+ *
+@verbatim
+ ===============================================================================
+ Refresh window and Counter configuration functions
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the WWDG peripheral.
+ * This function set Window Register = WindowValue, Counter Register
+ * according to Counter and \b ENABLE \b WWDG
+ * @param Counter : WWDG counter value
+ * @param WindowValue : specifies the WWDG Window Register, range is 0x00 to 0x7F.
+ * @retval None
+ */
+void WWDG_Init(uint8_t Counter, uint8_t WindowValue)
+{
+ /* Check the parameters */
+ assert_param(IS_WWDG_WINDOW_LIMIT_VALUE(WindowValue));
+
+ WWDG->WR = WWDG_WR_RESET_VALUE;
+ WWDG->CR = (uint8_t)(WWDG_CR_WDGA | Counter);
+ WWDG->WR = (uint8_t)((uint8_t)BIT_MASK & (uint8_t) WindowValue);
+}
+
+/**
+ * @brief Sets the WWDG window value.
+ * @param WindowValue: specifies the window value to be compared to the downcounter.
+ * This parameter value must be lower than 0x80.
+ * @retval None
+ */
+void WWDG_SetWindowValue(uint8_t WindowValue)
+{
+ __IO uint8_t tmpreg = 0;
+
+ /* Check the parameters */
+ assert_param(IS_WWDG_WINDOW_LIMIT_VALUE(WindowValue));
+
+ /* Set W[6:0] bits according to WindowValue value */
+ tmpreg |= (uint8_t) (WindowValue & (uint8_t) BIT_MASK);
+
+ /* Store the new value */
+ WWDG->WR = tmpreg;
+}
+
+/**
+ * @brief Sets the WWDG counter value.
+ * @param Counter: specifies the watchdog counter value.
+ * This parameter must be a number between 0x40 and 0x7F (to prevent generating
+ * an immediate reset)
+ * @retval None
+ */
+void WWDG_SetCounter(uint8_t Counter)
+{
+ /* Check the parameters */
+ assert_param(IS_WWDG_COUNTER_VALUE(Counter));
+
+ /* Write to T[6:0] bits to configure the counter value, no need to do
+ a read-modify-write; writing a 0 to WDGA bit does nothing */
+ WWDG->CR = (uint8_t)(Counter & (uint8_t)BIT_MASK);
+}
+/**
+ * @}
+ */
+
+/** @defgroup WWDG_Group2 WWDG activation function
+ * @brief WWDG activation function
+ *
+@verbatim
+ ===============================================================================
+ WWDG activation function
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables WWDG and load the counter value.
+ * @param Counter: specifies the watchdog counter value.
+ * This parameter must be a number between 0x40 and 0x7F.
+ * @retval None
+ */
+void WWDG_Enable(uint8_t Counter)
+{
+ /* Check the parameters */
+ assert_param(IS_WWDG_COUNTER_VALUE(Counter));
+ WWDG->CR = (uint8_t)(WWDG_CR_WDGA | Counter);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup WWDG_Group3 WWDG counter and software reset management
+ * @brief WWDG counter and software reset management
+ *
+@verbatim
+ ===============================================================================
+ WWDG counter and software reset management
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Gets the WWDG Counter Value.
+ * This value could be used to check if WWDG is in the window, where
+ * refresh is allowed.
+ * @param None
+ * @retval WWDG Counter Value
+ */
+uint8_t WWDG_GetCounter(void)
+{
+ return(WWDG->CR);
+}
+
+/**
+ * @brief Generates immediate WWDG RESET.
+ * @param None
+ * @retval None
+ */
+void WWDG_SWReset(void)
+{
+ WWDG->CR = WWDG_CR_WDGA; /* Activate WWDG, with clearing T6 */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/atomport-asm-cosmic.s b/ports/stm8l/atomport-asm-cosmic.s
new file mode 100644
index 00000000..7e9e2c28
--- /dev/null
+++ b/ports/stm8l/atomport-asm-cosmic.s
@@ -0,0 +1,364 @@
+;
+; Copyright (c) 2010, Atomthreads Project. All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without
+; Modification, are permitted provided that the following conditions
+; are met:
+;
+; 1. Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; 2. Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+; 3. No personal names or organizations' names associated with the
+; Atomthreads project may be used to endorse or promote products
+; derived from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+; TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+; POSSIBILITY OF SUCH DAMAGE.
+;
+
+
+; Cosmic assembler routines
+
+
+; Export functions to other modules
+xdef _archContextSwitch, _archFirstThreadRestore
+
+
+; \b archContextSwitch
+;
+; Architecture-specific context switch routine.
+;
+; Note that interrupts are always locked out when this routine is
+; called. For cooperative switches, the scheduler will have entered
+; a critical region. For preemptions (called from an ISR), the
+; ISR will have disabled interrupts on entry.
+;
+; @param[in] old_tcb_ptr Pointer to the thread being scheduled out
+; @param[in] new_tcb_ptr Pointer to the thread being scheduled in
+;
+; @return None
+;
+; void archContextSwitch (ATOM_TCB *old_tcb_ptr, ATOM_TCB *new_tcb_ptr)
+_archContextSwitch:
+
+ ; Parameter locations (Cosmic calling convention):
+ ; old_tcb_ptr = X register (word-width)
+ ; new_tcb_ptr = stack (word-width)
+
+ ; STM8 CPU Registers:
+ ;
+ ; A, X, Y: Standard working registers
+ ; SP: Stack pointer
+ ; PC: Program counter
+ ; CC: Code condition register
+ ;
+ ; Cosmic compiler virtual registers:
+ ;
+ ; c_x, c_y: Scratch memory areas saved by ISRs
+ ; c_lreg: Scratch memory area only saved by ISRs with @svlreg
+ ;
+ ; If this is a cooperative context switch (a thread has called us
+ ; to schedule itself out), the Cosmic compiler will have saved any
+ ; of the registers which it does not want us to clobber. There are
+ ; no registers which are expected to retain their value across a
+ ; function call, hence for cooperative context switches with this
+ ; compiler we do not actually need to save any registers at all.
+ ;
+ ; If we were called from an interrupt routine (because a thread
+ ; is being preemptively scheduled out), the situation is exactly
+ ; the same. Any ISR which calls out to a subroutine will have
+ ; similarly saved all registers which it needs us not to clobber
+ ; which in the case of this compiler is all registers. Again, we
+ ; do not need to save any registers because no registers are
+ ; expected to be unclobbered by a subroutine. Note that it is
+ ; necessary to add the @svlreg modifier to ISRs which call out to
+ ; the OS in order to force a save of c_lreg. The rest of the CPU
+ ; registers and the c_x and c_y virtual registers are, however,
+ ; always saved by ISRs which call out to C subroutines.
+ ;
+ ; This is an unusual context switch routine, because it does not
+ ; need to actually save any registers. Instead, the act of
+ ; calling this function causes all registers which must not be
+ ; clobbered to be saved on the stack anyway in the case of
+ ; cooperative context switches. For preemptive switches, the
+ ; interrupt service routine which calls out to here also causes
+ ; all registers to be saved in a similar fashion.
+
+ ; We do have to do some work in here though: we need to store
+ ; the current stack pointer to the current thread's TCB, and
+ ; switch in the new thread by taking the stack pointer from
+ ; the new thread's TCB and making that our new stack pointer.
+
+ ; The parameter pointing to the the old TCB (a word-width
+ ; pointer) is still untouched in the X register.
+
+ ; Store current stack pointer as first entry in old_tcb_ptr
+ ldw Y, SP ; Move current stack pointer into Y register
+ ldw (X), Y ; Store current stack pointer at first offset in TCB
+
+
+ ; At this point, all of the current thread's context has been saved
+ ; so we no longer care about keeping the contents of any registers.
+ ; We do still need the first two bytes on the current thread's stack,
+ ; however, which contain new_tcb_ptr (a pointer to the TCB of the
+ ; thread which we wish to switch in).
+ ;
+ ; Our stack frame now contains all registers (if this is a preemptive
+ ; switch due to an interrupt handler) or those registers which the
+ ; calling function did not wish to be clobbered (if this is a
+ ; cooperative context switch). It also contains the return address
+ ; which will be either a function called via an ISR (for preemptive
+ ; switches) or a function called from thread context (for cooperative
+ ; switches). Finally, the stack also contains the aforementioned
+ ; word which is the new_tcb_ptr parameter passed via the stack.
+ ;
+ ; In addition, the thread's stack pointer (after context-save) is
+ ; stored in the thread's TCB.
+
+ ; We are now ready to restore the new thread's context. In most
+ ; architecture ports we would typically switch our stack pointer
+ ; to the new thread's stack pointer, and pop all of its context
+ ; off the stack, before returning to the caller (the original
+ ; caller when the new thread was last scheduled out). In this
+ ; port, however, we do not need to actually restore any
+ ; registers here because none are saved when we switch out (at
+ ; least not by this function). We switch to the new thread's
+ ; stack pointer and then return to the original caller, which
+ ; will restore any registers which had to be saved.
+
+ ; Get the new thread's stack pointer off the TCB (new_tcb_ptr).
+ ; new_tcb_ptr is still stored in the previous thread's stack.
+ ; We are free to use any registers here.
+
+ ; Pull the new_tcb_ptr parameter from the stack into X register
+ ldw X,($3,SP)
+
+ ; Pull the first entry out of new_tcb_ptr (the new thread's
+ ; stack pointer) into X register.
+ ldw X,(X)
+
+ ; Switch our current stack pointer to that of the new thread.
+ ldw SP,X
+
+ ; Normally we would start restoring registers from the new
+ ; thread's stack here, but we don't save/restore any. We're
+ ; almost done.
+
+ ; The return address on the stack will now be the new thread's return
+ ; address - i.e. although we just entered this function from a
+ ; function called by the old thread, now that we have restored the new
+ ; thread's stack, we actually return from this function to wherever
+ ; the new thread was when it was previously scheduled out. This could
+ ; be either a regular C routine if the new thread previously scheduled
+ ; itself out cooperatively, or it could be an ISR if this new thread was
+ ; previously preempted (on exiting the ISR, execution will return to
+ ; wherever the new thread was originally interrupted).
+
+ ; Return to the caller. Note that we always use a regular RET here
+ ; because this is a subroutine regardless of whether we were called
+ ; during an ISR or by a thread cooperatively switching out. The
+ ; difference between RET and IRET on the STM8 architecture is that
+ ; RET only pops the return address off the stack, while IRET also
+ ; pops from the stack all of the CPU registers saved when the ISR
+ ; started, including restoring the interrupt-enable bits from the CC
+ ; register.
+ ;
+ ; It is important that whenever we call this function (whether from
+ ; an ISR for preemptive switches or from thread context for
+ ; cooperative switches) interrupts are always disabled. This means
+ ; that whichever method by which we leave this routine we always
+ ; have to reenable interrupts, so we can use the same context-switch
+ ; routine for preemptive and cooperative switches.
+ ;
+ ; The possible call/return paths are as follows:
+ ;
+ ; Scenario 1 (cooperative -> cooperative):
+ ; Thread A: cooperatively switches out
+ ; * Thread A relinquishes control / cooperatively switches out
+ ; * Interrupts already disabled by kernel for cooperative reschedules
+ ; * Partial register context saved by calling function
+ ; * Call here at thread context
+ ; * Switch to Thread B
+ ; Thread B (was previously cooperatively switched out):
+ ; * Stack context for Thread B contains its return address
+ ; * Return to function which was called at thread context
+ ; * Interrupts are reenabled by CRITICAL_END() call in kernel
+ ; * Return to Thread B application code
+ ;
+ ; Scenario 2 (preemptive -> preemptive):
+ ; Thread A: preemptively switches out
+ ; * ISR occurs
+ ; * Interrupts disabled by CPU at ISR entry (assume no nesting allowed)
+ ; * Full register context saved by CPU at ISR entry
+ ; * Call here at ISR context
+ ; * Switch to Thread B
+ ; Thread B (was previously preemptively switched out):
+ ; * Stack context for Thread B contains its return address
+ ; and all context saved by the CPU on ISR entry
+ ; * Return to function which was called at ISR context
+ ; * Eventually returns to calling ISR which calls IRET
+ ; * IRET performs full register context restore
+ ; * IRET reenables interrupts
+ ; * Return to Thread B application code
+ ;
+ ; Scenario 3 (cooperative -> preemptive):
+ ; Thread A: cooperatively switches out
+ ; * Thread A relinquishes control / cooperatively switches out
+ ; * Interrupts already disabled by kernel for cooperative reschedules
+ ; * Partial register context saved by calling function
+ ; * Call here at thread context
+ ; * Switch to Thread B
+ ; Thread B (was previously preemptively switched out):
+ ; * Stack context for Thread B contains its return address
+ ; and all context saved by the CPU on ISR entry
+ ; * Return to function which was called at ISR context
+ ; * Eventually returns to calling ISR which calls IRET
+ ; * IRET performs full register context restore
+ ; * IRET reenables interrupts
+ ; * Return to Thread B application code
+ ;
+ ; Scenario 4 (preemptive -> cooperative):
+ ; Thread A: preemptively switches out
+ ; * ISR occurs
+ ; * Interrupts disabled by CPU at ISR entry (assume no nesting allowed)
+ ; * Full register context saved by CPU at ISR entry
+ ; * Call here at ISR context
+ ; * Switch to Thread B
+ ; Thread B (was previously cooperatively switched out):
+ ; * Stack context for Thread B contains its return address
+ ; * Return to function which was called at thread context
+ ; * Interrupts are reenabled by CRITICAL_END() call in kernel
+ ; * Return to Thread B application code
+ ;
+ ; The above shows that it does not matter whether we are rescheduling
+ ; from/to thread context or ISR context. It is perfectly valid to
+ ; enter here at ISR context but leave via a thread which previously
+ ; cooperatively switched out because:
+ ; 1. Although the CPU handles ISRs differently by automatically
+ ; stacking all 6 CPU registers, and restoring them on an IRET,
+ ; we handle this because we switch the stack pointer to a
+ ; different thread's stack. Because the stack pointer is
+ ; switched, it does not matter that on entry via ISRs more
+ ; registers are saved on the original thread's stack than entries
+ ; via non-ISRs. Those extra registers will be restored properly
+ ; by an IRET when the thread is eventually scheduled back in
+ ; (which could be a long way off). This assumes that the CPU does
+ ; not have hidden behaviour that occurs on interrupts, and we can
+ ; in fact trick it into leaving via another thread's call stack,
+ ; and performing the IRET much later.
+ ; 2. Although the CPU handles ISRs differently by setting the CC
+ ; register interrupt-enable bits on entry/exit, we handle this
+ ; anyway by always assuming interrupts are disabled on entry
+ ; and exit regardless of the call path.
+
+ ; Return from subroutine
+ ret
+
+
+; \b archFirstThreadRestore
+;
+; Architecture-specific function to restore and start the first thread.
+; This is called by atomOSStart() when the OS is starting. Its job is to
+; restore the context for the first thread and start running at its
+; entry point.
+;
+; All new threads have a stack context pre-initialised with suitable
+; data for being restored by either this function or the normal
+; function used for scheduling threads in, archContextSwitch(). Only
+; the first thread run by the system is launched via this function,
+; after which all other new threads will first be run by
+; archContextSwitch().
+;
+; Typically ports will implement something similar here to the
+; latter half of archContextSwitch(). In this port the context
+; switch does not restore many registers, and instead relies on the
+; fact that returning from any function which called
+; archContextSwitch() will restore any of the necessary registers.
+; For new threads which have never been run there is no calling
+; function which will restore context on return, therefore we
+; do not restore many register values here. It is not necessary
+; for the new threads to have initialised values for the scratch
+; registers A, X and Y or the code condition register CC which
+; leaves SP and PC. SP is restored because this is always needed to
+; switch to a new thread's stack context. It is not necessary to
+; restore PC, because the thread's entry point is in the stack
+; context (when this function returns using RET the PC is
+; automatically changed to the thread's entry point because the
+; entry point is stored in the preinitialised stack).
+;
+; When new threads are started interrupts must be enabled, so there
+; is some scope for enabling interrupts in the CC here. It must be
+; done for all new threads, however, not just the first thread, so
+; we use a different system. We instead use a thread shell routine
+; which all functions run when they are first started, and
+; interrupts are enabled in there. This allows us to avoid having
+; to enable interrupts both in here and in the normal context
+; switch routine (archContextSwitch()). For the normal context
+; switch routine we would otherwise need to pass in notification of
+; and implement special handling for the first time a thread is
+; restored.
+;
+; In summary, first threads do not require a set of CPU registers
+; to be initialised to known values, so we only set SP to the new
+; thread's stack pointer. PC is restored for free because the RET
+; call at the end of this function pops the return address off the
+; stack.
+;
+; Note that you can create more than one thread before starting
+; the OS - only one thread is restored using this function, so
+; all other threads are actually restored by archContextSwitch().
+; This is another reminder that the initial context set up by
+; archThreadContextInit() must look the same whether restored by
+; archFirstThreadRestore() or archContextSwitch().
+;
+; @param[in] new_tcb_ptr Pointer to the thread being scheduled in
+;
+; @return None
+;
+; void archFirstThreadRestore (ATOM_TCB *new_tcb_ptr)
+_archFirstThreadRestore:
+
+ ; Parameter locations:
+ ; new_tcb_ptr = X register (word-width)
+
+ ; As described above, first thread restores in this port do not
+ ; expect any initial register context to be pre-initialised in
+ ; the thread's stack area. The thread's initial stack need only
+ ; contain the thread's initial entry point, and we do not even
+ ; "restore" that within this function. We leave the thread's entry
+ ; point in the stack, and RET at the end of the function pops it
+ ; off and "returns" to the entry point as if we were called from
+ ; there.
+ ;
+ ; The one thing we do need to set in here, though, is the thread's
+ ; stack pointer. This is available from the passed thread TCB
+ ; structure.
+
+ ; Get the new thread's stack pointer off the TCB (new_tcb_ptr).
+ ; new_tcb_ptr is stored in the parameter register X. The stack
+ ; pointer it conveniently located at the top of the TCB so no
+ ; indexing is required to pull it out.
+ ldw X,(X)
+
+ ; Switch our current stack pointer to that of the new thread.
+ ldw SP,X
+
+ ; The "return address" left on the stack now will be the new
+ ; thread's entry point. RET will take us there as if we had
+ ; actually been there before calling this subroutine, whereas
+ ; the return address was actually set up by archThreadContextInit().
+ ret
+
+
+ end
diff --git a/ports/stm8l/atomport-private.h b/ports/stm8l/atomport-private.h
new file mode 100644
index 00000000..7283678b
--- /dev/null
+++ b/ports/stm8l/atomport-private.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010, Kelvin Lawson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. No personal names or organizations' names associated with the
+ * Atomthreads project may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ATOM_PORT_PRIVATE_H
+#define __ATOM_PORT_PRIVATE_H
+
+
+/**
+ * Compiler-specific modifier to prevent some functions from saving
+ * and restoring registers on entry and exit, if the function is
+ * known to never complete (e.g. thread entry points).
+ * Reduces stack usage on supporting compilers.
+ */
+#ifdef __IAR_SYSTEMS_ICC__
+#define NO_REG_SAVE __task
+#else
+#define NO_REG_SAVE
+#endif
+
+/* Function prototypes */
+void archInitSystemTickTimer (void);
+void TIM4_SystemTickISR (void);
+
+#endif /* __ATOM_PORT_PRIVATE_H */
diff --git a/ports/stm8l/atomport-tests.h b/ports/stm8l/atomport-tests.h
new file mode 100644
index 00000000..ca8b29d8
--- /dev/null
+++ b/ports/stm8l/atomport-tests.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010, Kelvin Lawson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. No personal names or organizations' names associated with the
+ * Atomthreads project may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ATOM_PORT_TESTS_H
+#define __ATOM_PORT_TESTS_H
+
+/* Include Atomthreads kernel API */
+#include "atom.h"
+
+/* Prerequisite include for ATOMLOG() macro (via printf) */
+#include
+
+/* Logger macro for viewing test results */
+#define ATOMLOG printf
+
+/*
+ * String location macro: for platforms which need to place strings in
+ * alternative locations. Not used on this platform.
+ */
+#define _STR
+
+/* Default thread stack size (in bytes) */
+#define TEST_THREAD_STACK_SIZE 128
+
+/* Uncomment to enable logging of stack usage to UART */
+#define TESTS_LOG_STACK_USAGE
+
+/**
+ * IAR EWSTM8: Ignore warnings on volatile ordering thrown up
+ * by ATOMLOG() statements in the test modules.
+ */
+#ifdef __IAR_SYSTEMS_ICC__
+#pragma diag_suppress=Pa082
+#endif
+
+
+#endif /* __ATOM_PORT_TESTS_H */
+
diff --git a/ports/stm8l/atomport.c b/ports/stm8l/atomport.c
new file mode 100644
index 00000000..d1ee0965
--- /dev/null
+++ b/ports/stm8l/atomport.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2010, Kelvin Lawson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. No personal names or organizations' names associated with the
+ * Atomthreads project may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "atom.h"
+#include "atomport-private.h"
+#include "stm8l15x.h"
+#if defined(__RCSTM8__)
+#include
+#endif
+
+
+/** Forward declarations */
+static NO_REG_SAVE void thread_shell (void);
+
+
+/**
+ * \b thread_shell
+ *
+ * Shell routine which is used to call all thread entry points.
+ *
+ * This routine is called whenever a new thread is starting, and is
+ * responsible for taking the entry point parameter off the TCB
+ * and passing this into the thread entry point, as well as enabling
+ * interrupts.
+ *
+ * This is an optional function for a port, because interrupts could
+ * be enabled by the first-thread and normal context restore routines,
+ * but that would require special handling in the normal context
+ * switch routine (archContextSwitch()) that is only needed the first
+ * time a thread is started. A much neater method is to direct all
+ * threads through this shell routine first, so that interrupts will
+ * always be enabled at thread startup, and no special first-time-run
+ * handling is required in the context restore routines (i.e. we
+ * don't affect normal context switch times just for the benefit of
+ * the first time a thread is restored by adding extra complication
+ * to the thread restore routines).
+ *
+ * Other ports are free to implement whatever scheme they wish. In
+ * particular if you save all necessary registers (including the
+ * interrupt enable register) on a context switch then you need not
+ * worry about any special requirements for starting threads for the
+ * first time because you can preinitialise the stack context with
+ * a suitable register value that will enable interrupts.
+ *
+ * If the compiler supports it, stack space can be saved by preventing
+ * the function from saving registers on entry. This is because we
+ * are called directly by the context-switch assembler, and know that
+ * threads cannot return from here. The NO_REG_SAVE macro is used to
+ * denote such functions in a compiler-agnostic way, though not all
+ * compilers support it.
+ *
+ * @return None
+ */
+static NO_REG_SAVE void thread_shell (void)
+{
+ ATOM_TCB *curr_tcb;
+
+ /* Get the TCB of the thread being started */
+ curr_tcb = atomCurrentContext();
+
+ /**
+ * Enable interrupts - these will not be enabled when a thread
+ * is first restored.
+ */
+#if defined(__CSMC__)
+ _asm("rim");
+#elif defined(__IAR_SYSTEMS_ICC__)
+ rim();
+#elif defined(__RCSTM8__)
+ _rim_();
+#elif defined(__SDCC_stm8)
+ __asm__("rim");
+#endif
+
+ /* Call the thread entry point */
+ if (curr_tcb && curr_tcb->entry_point)
+ {
+ curr_tcb->entry_point(curr_tcb->entry_param);
+ }
+
+ /* Not reached - threads should never return from the entry point */
+
+}
+
+
+/**
+ * \b archThreadContextInit
+ *
+ * Architecture-specific thread context initialisation routine.
+ *
+ * This function must set up a thread's context ready for restoring
+ * and running the thread via archFirstThreadRestore() or
+ * archContextSwitch().
+ *
+ * (COSMIC & RAISONANCE) On this port we take advantage of the fact
+ * that when the context switch routine is called these compilers will
+ * automatically stack all registers which should not be clobbered.
+ * This means that the context switch need only save and restore the
+ * stack pointer, which is stored in the thread's TCB. Because of
+ * this, it is not necessary to prefill a new thread's stack with any
+ * register values here. The only entry we need to make in the stack
+ * is the thread's entry point - this is not exactly restored when
+ * the thread is context switched in, but rather is popped off the
+ * stack by the context switch routine's RET call. That is used to
+ * direct the program counter to our thread's entry point - we are
+ * faking a return to a caller which never actually existed.
+ *
+ * (IAR) The IAR compiler works around the lack of CPU registers on
+ * STM8 by allocating some space in low SRAM which is used for
+ * "virtual" registers. The compiler uses these like normal CPU
+ * registers, and hence their values must be preserved when
+ * context-switching between threads. Some of these (?b8 to ?b15)
+ * are expected to be preserved by called functions, and hence we
+ * actually need to save/restore those registers (unlike the rest
+ * of the virtual registers and the standard CPU registers). We
+ * therefore must prefill the stack with values for ?b8 to ?b15
+ * here.
+ *
+ * We could pre-initialise the stack so that the RET call goes
+ * directly to the thread entry point, with the thread entry
+ * parameter filled in. On this architecture, however, we use an
+ * outer thread shell routine which is used to call all threads.
+ * The thread entry point and parameter are stored in the thread's
+ * TCB which the thread shell uses to make the actual call to the
+ * entry point. We don't therefore need to store the actual thread
+ * entry and parameter within the stack.
+ *
+ * Note that interrupts must be enabled the first time a thread is
+ * run. On some architectures this might be done by setting an
+ * initial value for the interrupt-enable register within the stack
+ * area. In this port, however, we use the thread shell to enable
+ * interrupts at the start of any thread.
+ *
+ * @param[in] tcb_ptr Pointer to the TCB of the thread being created
+ * @param[in] stack_top Pointer to the top of the new thread's stack
+ * @param[in] entry_point Pointer to the thread entry point function
+ * @param[in] entry_param Parameter to be passed to the thread entry point
+ *
+ * @return None
+ */
+void archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top, void (*entry_point)(uint32_t), uint32_t entry_param)
+{
+ uint8_t *stack_ptr;
+
+ /** Start at stack top */
+ stack_ptr = (uint8_t *)stack_top;
+
+ /**
+ * The thread restore routines will perform a RET which expects to
+ * find the address of the calling routine on the stack. In this case
+ * (the first time a thread is run) we "return" to the entry point for
+ * the thread. That is, we store the thread entry point in the
+ * place that RET will look for the return address: the stack.
+ *
+ * Note that we are using the thread_shell() routine to start all
+ * threads, so we actually store the address of thread_shell()
+ * here. Other ports may store the real thread entry point here
+ * and call it directly from the thread restore routines.
+ *
+ * Because we are filling the stack from top to bottom, this goes
+ * on the stack first (at the top).
+ */
+ *stack_ptr-- = (uint8_t)((uint16_t)thread_shell & 0xFF);
+ *stack_ptr-- = (uint8_t)(((uint16_t)thread_shell >> 8) & 0xFF);
+
+ /**
+ * Because we are using a thread shell which is responsible for
+ * calling the real entry point, it also passes the parameters
+ * to entry point and we need not stack the entry parameter here.
+ *
+ * Other ports may wish to store entry_param in the appropriate
+ * parameter registers when creating a thread's context,
+ * particularly if that port saves those registers anyway.
+ */
+
+ /**
+ * (IAR) Set up initial values for ?b8 to ?b15.
+ */
+#if defined(__IAR_SYSTEMS_ICC__)
+ *stack_ptr-- = 0; // ?b8
+ *stack_ptr-- = 0; // ?b9
+ *stack_ptr-- = 0; // ?b10
+ *stack_ptr-- = 0; // ?b11
+ *stack_ptr-- = 0; // ?b12
+ *stack_ptr-- = 0; // ?b13
+ *stack_ptr-- = 0; // ?b14
+ *stack_ptr-- = 0; // ?b15
+#endif
+
+ /**
+ * (COSMIC & RAISONANCE) We do not initialise any registers via the
+ * initial stack context at all.
+ */
+
+ /**
+ * All thread context has now been initialised. All that is left
+ * is to save the current stack pointer to the thread's TCB so
+ * that it knows where to start looking when the thread is started.
+ */
+ tcb_ptr->sp_save_ptr = stack_ptr;
+
+}
+
+
+/**
+ * \b archInitSystemTickTimer
+ *
+ * Initialise the system tick timer. Uses the STM8's TIM4 facility.
+ *
+ * @return None
+ */
+void archInitSystemTickTimer ( void )
+{
+ /* Enable TIM4 CLK */
+ CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, ENABLE);
+
+ /* TIM4 configuration:
+ - TIM4CLK is set to 2 MHz, the TIM4 Prescaler is equal to 128 so the TIM1 counter
+ clock used is 2 MHz / 128 = 15625 Hz
+ - With 125 000 Hz we can generate time base:
+ max time base is 16.384 ms if TIM4_PERIOD = 255 --> (255 + 1) / 15625 = 16.384 ms
+ min time base is 0.128 ms if TIM4_PERIOD = 1 --> ( 1 + 1) / 15625 = 0.128 ms
+ - In this example we need to generate a time base equal to 10 ms
+ so TIM4_PERIOD = (0.01 * 15625 - 1) = 155 */
+
+ /* Time base configuration */
+ TIM4_TimeBaseInit(TIM4_Prescaler_128, 155);
+ /* Clear TIM4 update flag */
+ TIM4_ClearFlag(TIM4_FLAG_Update);
+ /* Enable update interrupt */
+ TIM4_ITConfig(TIM4_IT_Update, ENABLE);
+ /* enable interrupts */
+ enableInterrupts();
+
+ /* Enable TIM4 */
+ TIM4_Cmd(ENABLE);
+
+}
+
+
+/**
+ *
+ * System tick ISR.
+ *
+ * This is responsible for regularly calling the OS system tick handler.
+ * The system tick handler checks if any timer callbacks are necessary,
+ * and runs the scheduler.
+ *
+ * The CPU automatically saves all registers before calling out to an
+ * interrupt handler like this.
+ *
+ * The system may decide to schedule in a new thread during the call to
+ * atomTimerTick(), in which case the program counter will be redirected
+ * to the new thread's running location during atomIntExit(). This ISR
+ * function will not actually complete until the thread we interrupted is
+ * scheduled back in, at which point the end of this function will be
+ * reached (after atomIntExit()) and the IRET call by the compiler will
+ * return us to the interrupted thread as if we hadn't run any other
+ * thread in the meantime. In other words the interrupted thread can be
+ * scheduled out by atomIntExit() and several threads could run before we
+ * actually reach the end of this function. When this function does
+ * finally complete, the return address (the PC of the thread which was
+ * interrupted) will be on the interrupted thread's stack because it was
+ * saved on there by the CPU when the interrupt triggered.
+ *
+ * As with all interrupts, the ISR should call atomIntEnter() and
+ * atomIntExit() on entry and exit. This serves two purposes:
+ *
+ * a) To notify the OS that it is running in interrupt context
+ * b) To defer the scheduler until after the ISR is completed
+ *
+ * We defer all scheduling decisions until after the ISR has completed
+ * in case the interrupt handler makes more than one thread ready.
+ *
+ * @return None
+ */
+void TIM4_SystemTickISR (void)
+{
+ /* Call the interrupt entry routine */
+ atomIntEnter();
+
+ /* Call the OS system tick handler */
+ atomTimerTick();
+
+ /* Cleat Interrupt Pending bit */
+ TIM4_ClearITPendingBit(TIM4_IT_Update);
+
+ /* Call the interrupt exit routine */
+ atomIntExit(TRUE);
+}
+
+
+/**
+ * \b archSystemTickTimerStop
+ *
+ * Stop the system tick timer. Uses the STM8's TIM4 facility.
+ *
+ * @return None
+ */
+void archSystemTickTimerStop(void)
+{
+ /* Disable TIM4 CLK */
+ CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, DISABLE);
+ /* Disable TIM4 */
+ TIM4_Cmd(DISABLE);
+}
+
+
+/**
+ * \b archSystemTickTimerRestart
+ *
+ * Restart the system tick timer. Uses the STM8's TIM4 facility.
+ *
+ * @return None
+ */
+void archSystemTickTimerRestart(void)
+{
+ /* Enable TIM4 CLK */
+ CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, ENABLE);
+ /* Enable TIM4 */
+ TIM4_Cmd(ENABLE);
+}
+
diff --git a/ports/stm8l/atomport.h b/ports/stm8l/atomport.h
new file mode 100644
index 00000000..9d7c5227
--- /dev/null
+++ b/ports/stm8l/atomport.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2010, Kelvin Lawson. All rights reserved.
+ * Copyright (c) 2016, Dr. Philipp Klaus Krause.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. No personal names or organizations' names associated with the
+ * Atomthreads project may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ATOM_PORT_H
+#define __ATOM_PORT_H
+
+
+#include "stm8l15x.h"
+
+#if defined(__IAR_SYSTEMS_ICC__)
+#include "intrinsics.h"
+#elif defined (__RCSTM8__)
+#include
+#endif
+
+/* Definition of NULL is available from stddef.h on this platform */
+#include
+
+/* Required number of system ticks per second (normally 100 for 10ms tick) */
+#define SYSTEM_TICKS_PER_SEC 100
+
+#define THOUSAND_TIMES_OF_RATE_OF_SYSTEM_TICKS_TO_SLEEP_TICKS 3125
+
+/**
+ * Architecture-specific types.
+ */
+#if defined(__CSMC__) || defined (__RCSTM8__) /* Cosmic and Raisonance do not have the C99 stdint.h header*/
+#define int8_t s8
+#define int16_t s16
+#define int32_t s32
+#define uint8_t u8
+#define uint16_t u16
+#define uint32_t u32
+#else
+#include
+#endif
+#define POINTER void *
+
+/* Size of each stack entry / stack alignment size (8 bits on STM8) */
+#define STACK_ALIGN_SIZE sizeof(uint8_t)
+
+/**
+ * Critical region protection: this should disable interrupts
+ * to protect OS data structures during modification. It must
+ * allow nested calls, which means that interrupts should only
+ * be re-enabled when the outer CRITICAL_END() is reached.
+ */
+
+/* COSMIC: Use inline assembler */
+#if defined(__CSMC__)
+#define CRITICAL_STORE uint8_t ccr
+#define CRITICAL_START() _asm ("push CC\npop a\nld (X),A\nsim", &ccr)
+#define CRITICAL_END() _asm ("ld A,(X)\npush A\npop CC", &ccr)
+
+/* IAR: Use intrinsics */
+#elif defined(__IAR_SYSTEMS_ICC__)
+#define CRITICAL_STORE __istate_t _istate
+#define CRITICAL_START() _istate = __get_interrupt_state(); __disable_interrupt()
+#define CRITICAL_END() __set_interrupt_state(_istate)
+
+/* Raisonance: Use intrinsics */
+#elif defined(__RCSTM8__)
+#define CRITICAL_STORE unsigned char ccr
+#define CRITICAL_START() ccr = _getCC_(); _sim_()
+#define CRITICAL_END() _setCC_(ccr)
+
+/* SDCC: Use custom function */
+#elif defined(__SDCC_stm8)
+uint8_t get_cc(void);
+void set_cc(uint8_t);
+#define CRITICAL_STORE uint8_t ccr
+#define CRITICAL_START() ccr = get_cc(); __asm__("sim")
+#define CRITICAL_END() set_cc(ccr)
+#endif
+
+/* Uncomment to enable stack-checking */
+/* #define ATOM_STACK_CHECKING */
+
+
+#endif /* __ATOM_PORT_H */
diff --git a/ports/stm8l/atomthreads-cosmic.pdb b/ports/stm8l/atomthreads-cosmic.pdb
new file mode 100644
index 00000000..59dbff03
--- /dev/null
+++ b/ports/stm8l/atomthreads-cosmic.pdb
@@ -0,0 +1,39 @@
+[DebugState_v1-Debug.DebugContext]
+DumpRWOnFly1=0
+DumpRWOnFly2=0
+DumpRWOnFly3=0
+DumpRWOnFly4=0
+WatchVariables1=signal!0;step!0;i!0;tcb!0;signals!0;
+FormatWatch1=0
+FormatViewType1=1
+FormatViewAddress1=1
+WatchRWOnFlyTab1=0
+WatchVariables2=
+FormatWatch2=0
+FormatViewType2=1
+FormatViewAddress2=1
+WatchRWOnFlyTab2=0
+WatchVariables3=
+FormatWatch3=0
+FormatViewType3=1
+FormatViewAddress3=1
+WatchRWOnFlyTab3=0
+WatchVariables4=
+FormatWatch4=0
+FormatViewType4=1
+FormatViewAddress4=1
+WatchRWOnFlyTab4=0
+FormatLocals=0
+FormatParameters=0
+[DebugState_v1-Debug.AddOn.St7Registers]
+ActiveTab=2
+[DebugState_v1-Debug.AddOn.St7PeripheralRegister]
+DisplayFormat=1
+ShowPeriphAddress=0
+ShowRegisterAddress=1
+[DebugState_v1-Debug.AddOn.St7McuIcdConf]
+McuName=STM8L151K4
+[DebugState_v1-Debug.AddOn.IcdBreak]
+ICDBreak0=CR:0x00000000,BK1:0x00000000,BK2:0x00000000
+[DebugState_v1-Debug.AddOn.SteppingMode]
+Mode=hardware
diff --git a/ports/stm8l/atomthreads-cosmic.stp b/ports/stm8l/atomthreads-cosmic.stp
new file mode 100644
index 00000000..259c6130
--- /dev/null
+++ b/ports/stm8l/atomthreads-cosmic.stp
@@ -0,0 +1,850 @@
+; STMicroelectronics Project file
+
+[Version]
+Keyword=ST7Project
+Number=1.3
+
+[Project]
+Name=atomthreads-cosmic
+Toolset=STM8 Cosmic
+
+[Config]
+0=Config.0
+1=Config.1
+
+[Config.0]
+ConfigName=Debug
+Target=$(ProjectSFile).elf
+OutputFolder=Debug
+Debug=$(TargetFName)
+
+[Config.1]
+ConfigName=Release
+Target=atomthreads-cosmic.elf
+OutputFolder=Release
+Debug=$(TargetFName)
+
+[Root]
+ElemType=Project
+PathName=atomthreads-cosmic
+Child=Root.Kernel
+Config.0=Root.Config.0
+Config.1=Root.Config.1
+
+[Root.Config.0]
+Settings.0.0=Root.Config.0.Settings.0
+Settings.0.1=Root.Config.0.Settings.1
+Settings.0.2=Root.Config.0.Settings.2
+Settings.0.3=Root.Config.0.Settings.3
+Settings.0.4=Root.Config.0.Settings.4
+Settings.0.5=Root.Config.0.Settings.5
+Settings.0.6=Root.Config.0.Settings.6
+Settings.0.7=Root.Config.0.Settings.7
+Settings.0.8=Root.Config.0.Settings.8
+
+[Root.Config.1]
+Settings.1.0=Root.Config.1.Settings.0
+Settings.1.1=Root.Config.1.Settings.1
+Settings.1.2=Root.Config.1.Settings.2
+Settings.1.3=Root.Config.1.Settings.3
+Settings.1.4=Root.Config.1.Settings.4
+Settings.1.5=Root.Config.1.Settings.5
+Settings.1.6=Root.Config.1.Settings.6
+Settings.1.7=Root.Config.1.Settings.7
+Settings.1.8=Root.Config.1.Settings.8
+
+[Root.Config.0.Settings.0]
+String.6.0=2018,12,31,23,22,15
+String.100.0=ST Assembler Linker
+String.100.1=ST7 Cosmic
+String.100.2=STM8 Cosmic
+String.100.3=ST7 Metrowerks V1.1
+String.100.4=Raisonance
+String.101.0=STM8 Cosmic
+String.102.0=D:\Program Files (x86)\COSMIC\FSE_Compilers\CXSTM8
+String.103.0=
+String.104.0=Hstm8
+String.105.0=Lib
+String.106.0=Debug
+String.107.0=$(ProjectSFile).elf
+Int.108=0
+
+[Root.Config.0.Settings.1]
+String.6.0=2018,12,31,17,27,53
+String.100.0=$(TargetFName)
+String.101.0=
+String.102.0=
+String.103.0=.\;..\..\kernel;stm8l15x_stdperiph_driver\inc;stm8l15x_stdperiph_driver\src;..\..\tests;
+
+[Root.Config.0.Settings.2]
+String.2.0=
+String.6.0=2018,12,31,17,27,53
+String.100.0=STM8L151K4
+
+[Root.Config.0.Settings.3]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 +modsl0 -customDbg +debug -customOpt-no -customC-pp -customLst -l -dATOM_STACK_CHECKING -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2019,1,4,22,4,48
+
+[Root.Config.0.Settings.4]
+String.2.0=Assembling $(InputFile)...
+String.3.0=castm8 -xx -l $(ToolsetIncOpts) -o$(IntermPath)$(InputName).$(ObjectExt) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+
+[Root.Config.0.Settings.5]
+String.2.0=Running Pre-Link step
+String.6.0=2018,12,31,17,27,53
+String.8.0=
+
+[Root.Config.0.Settings.6]
+String.2.0=Running Linker
+String.3.0=clnk $(ToolsetLibOpts) -o $(OutputPath)$(TargetSName).sm8 -fakeInteger -fakeOutFile$(ProjectSFile).elf -fakeRunConv -fakeStartupcrtsi0.sm8 -fakeSemiAutoGen -fakeVectFilestm8_interrupt_vector.c -fakeVectAddr0x8000 -customMapFile -customMapFile-m$(OutputPath)$(TargetSName).map -customMapAddress -customCfgFile$(OutputPath)$(TargetSName).lkf
+String.3.1=cvdwarf $(OutputPath)$(TargetSName).sm8
+String.4.0=$(OutputPath)$(TargetFName)
+String.5.0=
+String.6.0=2019,1,4,22,55,33
+String.100.0=
+String.101.0=crtsi.st7
+String.102.0=+seg .const -b 0x8080 -m 0x3f80 -n .const -it
+String.102.1=+seg .text -a .const -n .text
+String.102.2=+seg .eeprom -b 0x1000 -m 0x400 -n .eeprom
+String.102.3=+seg .bsct -b 0x0 -m 0x100 -n .bsct
+String.102.4=+seg .ubsct -a .bsct -n .ubsct
+String.102.5=+seg .bit -a .ubsct -n .bit -id
+String.102.6=+seg .share -a .bit -n .share -is
+String.102.7=+seg .data -b 0x100 -m 0x4ff -n .data
+String.102.8=+seg .bss -a .data -n .bss
+String.103.0=Code,Constants[0x8080-0xbfff]=.const,.text
+String.103.1=Eeprom[0x1000-0x13ff]=.eeprom
+String.103.2=Zero Page[0x0-0xff]=.bsct,.ubsct,.bit,.share
+String.103.3=Ram[0x100-0x5fe]=.data,.bss
+String.104.0=0x7ff
+String.105.0=libisl0.sm8;libm0.sm8
+Int.0=0
+Int.1=0
+
+[Root.Config.0.Settings.7]
+String.2.0=Running Post-Build step
+String.3.0=chex -o $(OutputPath)$(TargetSName).s19 $(OutputPath)$(TargetSName).sm8
+String.6.0=2018,12,31,17,27,53
+
+[Root.Config.0.Settings.8]
+String.2.0=Performing Custom Build on $(InputFile)
+String.6.0=2018,12,31,17,27,53
+
+[Root.Config.1.Settings.0]
+String.6.0=2018,12,31,17,27,53
+String.100.0=ST Assembler Linker
+String.100.1=ST7 Cosmic
+String.100.2=STM8 Cosmic
+String.100.3=ST7 Metrowerks V1.1
+String.100.4=Raisonance
+String.101.0=STM8 Cosmic
+String.102.0=D:\Program Files (x86)\COSMIC\FSE_Compilers\CXSTM8
+String.103.0=
+String.104.0=Hstm8
+String.105.0=Lib
+String.106.0=Release
+String.107.0=atomthreads-cosmic.elf
+Int.108=0
+
+[Root.Config.1.Settings.1]
+String.6.0=2018,12,31,17,27,53
+String.100.0=$(TargetFName)
+String.101.0=
+String.103.0=.\;..\..\kernel;stm8l15x_stdperiph_driver\inc;stm8l15x_stdperiph_driver\src;..\..\tests;
+
+[Root.Config.1.Settings.2]
+String.2.0=
+String.6.0=2018,12,31,17,27,53
+String.100.0=STM8L151K4
+
+[Root.Config.1.Settings.3]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel +mods0 -customC-pp $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+
+[Root.Config.1.Settings.4]
+String.2.0=Assembling $(InputFile)...
+String.3.0=castm8 $(ToolsetIncOpts) -o$(IntermPath)$(InputName).$(ObjectExt) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+
+[Root.Config.1.Settings.5]
+String.2.0=Running Pre-Link step
+String.6.0=2018,12,31,17,27,53
+
+[Root.Config.1.Settings.6]
+String.2.0=Running Linker
+String.3.0=clnk -fakeRunConv -fakeInteger -fakeSemiAutoGen $(ToolsetLibOpts) -o $(OutputPath)$(TargetSName).sm8 -fakeOutFile$(ProjectSFile).elf -customCfgFile $(OutputPath)$(TargetSName).lkf -fakeVectFilestm8_interrupt_vector.c -fakeStartupcrtsi0.sm8
+String.3.1=cvdwarf $(OutputPath)$(TargetSName).sm8 -fakeVectAddr0x8000
+String.4.0=$(OutputPath)$(TargetFName)
+String.5.0=$(OutputPath)$(TargetSName).map $(OutputPath)$(TargetSName).st7 $(OutputPath)$(TargetSName).s19
+String.6.0=2018,12,31,17,27,53
+String.101.0=crtsi.st7
+String.102.0=+seg .const -b 0x8080 -m 0x3f80 -n .const -it
+String.102.1=+seg .text -a .const -n .text
+String.102.2=+seg .eeprom -b 0x1000 -m 0x400 -n .eeprom
+String.102.3=+seg .bsct -b 0x0 -m 0x100 -n .bsct
+String.102.4=+seg .ubsct -a .bsct -n .ubsct
+String.102.5=+seg .bit -a .ubsct -n .bit -id
+String.102.6=+seg .share -a .bit -n .share -is
+String.102.7=+seg .data -b 0x100 -m 0x4ff -n .data
+String.102.8=+seg .bss -a .data -n .bss
+String.103.0=Code,Constants[0x8080-0xbfff]=.const,.text
+String.103.1=Eeprom[0x1000-0x13ff]=.eeprom
+String.103.2=Zero Page[0x0-0xff]=.bsct,.ubsct,.bit,.share
+String.103.3=Ram[0x100-0x5fe]=.data,.bss
+String.104.0=0x7ff
+Int.0=0
+Int.1=0
+
+[Root.Config.1.Settings.7]
+String.2.0=Running Post-Build step
+String.3.0=chex -o $(OutputPath)$(TargetSName).s19 $(OutputPath)$(TargetSName).sm8
+String.6.0=2018,12,31,17,27,53
+
+[Root.Config.1.Settings.8]
+String.2.0=Performing Custom Build on $(InputFile)
+String.6.0=2018,12,31,17,27,53
+
+[Root.Kernel]
+ElemType=Folder
+PathName=Kernel
+Child=Root.Kernel...\..\kernel\atomtimer.h
+Next=Root.Peripherals
+Config.0=Root.Kernel.Config.0
+Config.1=Root.Kernel.Config.1
+
+[Root.Kernel.Config.0]
+Settings.0.0=Root.Kernel.Config.0.Settings.0
+Settings.0.1=Root.Kernel.Config.0.Settings.1
+Settings.0.2=Root.Kernel.Config.0.Settings.2
+Settings.0.3=Root.Kernel.Config.0.Settings.3
+
+[Root.Kernel.Config.1]
+Settings.1.0=Root.Kernel.Config.1.Settings.0
+Settings.1.1=Root.Kernel.Config.1.Settings.1
+Settings.1.2=Root.Kernel.Config.1.Settings.2
+Settings.1.3=Root.Kernel.Config.1.Settings.3
+
+[Root.Kernel.Config.0.Settings.0]
+String.6.0=2018,12,31,17,29,53
+String.8.0=Debug
+Int.0=0
+Int.1=0
+
+[Root.Kernel.Config.0.Settings.1]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 +modsl0 -customDbg +debug -customOpt-no -customC-pp -customLst -l -dATOM_STACK_CHECKING -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2019,1,4,22,4,48
+
+[Root.Kernel.Config.0.Settings.2]
+String.2.0=Assembling $(InputFile)...
+String.3.0=castm8 -xx -l $(ToolsetIncOpts) -o$(IntermPath)$(InputName).$(ObjectExt) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+
+[Root.Kernel.Config.0.Settings.3]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Kernel.Config.1.Settings.0]
+String.6.0=2018,12,31,17,29,53
+String.8.0=Release
+Int.0=0
+Int.1=0
+
+[Root.Kernel.Config.1.Settings.1]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel +mods0 -customC-pp $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+
+[Root.Kernel.Config.1.Settings.2]
+String.2.0=Assembling $(InputFile)...
+String.3.0=castm8 $(ToolsetIncOpts) -o$(IntermPath)$(InputName).$(ObjectExt) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+
+[Root.Kernel.Config.1.Settings.3]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Kernel...\..\kernel\atomtimer.h]
+ElemType=File
+PathName=..\..\kernel\atomtimer.h
+Next=Root.Kernel...\..\kernel\atomtimer.c
+
+[Root.Kernel...\..\kernel\atomtimer.c]
+ElemType=File
+PathName=..\..\kernel\atomtimer.c
+Next=Root.Kernel...\..\kernel\atomsignal.h
+
+[Root.Kernel...\..\kernel\atomsignal.h]
+ElemType=File
+PathName=..\..\kernel\atomsignal.h
+Next=Root.Kernel...\..\kernel\atomsignal.c
+
+[Root.Kernel...\..\kernel\atomsignal.c]
+ElemType=File
+PathName=..\..\kernel\atomsignal.c
+Next=Root.Kernel...\..\kernel\atomsem.h
+
+[Root.Kernel...\..\kernel\atomsem.h]
+ElemType=File
+PathName=..\..\kernel\atomsem.h
+Next=Root.Kernel...\..\kernel\atomsem.c
+
+[Root.Kernel...\..\kernel\atomsem.c]
+ElemType=File
+PathName=..\..\kernel\atomsem.c
+Next=Root.Kernel...\..\kernel\atomqueue.h
+
+[Root.Kernel...\..\kernel\atomqueue.h]
+ElemType=File
+PathName=..\..\kernel\atomqueue.h
+Next=Root.Kernel...\..\kernel\atomqueue.c
+
+[Root.Kernel...\..\kernel\atomqueue.c]
+ElemType=File
+PathName=..\..\kernel\atomqueue.c
+Next=Root.Kernel...\..\kernel\atommutex.h
+
+[Root.Kernel...\..\kernel\atommutex.h]
+ElemType=File
+PathName=..\..\kernel\atommutex.h
+Next=Root.Kernel...\..\kernel\atommutex.c
+
+[Root.Kernel...\..\kernel\atommutex.c]
+ElemType=File
+PathName=..\..\kernel\atommutex.c
+Next=Root.Kernel...\..\kernel\atomkernel.c
+
+[Root.Kernel...\..\kernel\atomkernel.c]
+ElemType=File
+PathName=..\..\kernel\atomkernel.c
+Next=Root.Kernel...\..\kernel\atom.h
+
+[Root.Kernel...\..\kernel\atom.h]
+ElemType=File
+PathName=..\..\kernel\atom.h
+
+[Root.Peripherals]
+ElemType=Folder
+PathName=Peripherals
+Child=Root.Peripherals.stm8l15x_stdperiph_driver\src\stm8l15x_usart.c
+Next=Root.Port
+Config.0=Root.Peripherals.Config.0
+Config.1=Root.Peripherals.Config.1
+
+[Root.Peripherals.Config.0]
+Settings.0.0=Root.Peripherals.Config.0.Settings.0
+Settings.0.1=Root.Peripherals.Config.0.Settings.1
+Settings.0.2=Root.Peripherals.Config.0.Settings.2
+Settings.0.3=Root.Peripherals.Config.0.Settings.3
+
+[Root.Peripherals.Config.1]
+Settings.1.0=Root.Peripherals.Config.1.Settings.0
+Settings.1.1=Root.Peripherals.Config.1.Settings.1
+Settings.1.2=Root.Peripherals.Config.1.Settings.2
+Settings.1.3=Root.Peripherals.Config.1.Settings.3
+
+[Root.Peripherals.Config.0.Settings.0]
+String.6.0=2018,12,31,17,30,3
+String.8.0=Debug
+Int.0=0
+Int.1=0
+
+[Root.Peripherals.Config.0.Settings.1]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 +modsl0 -customDbg +debug -customOpt-no -customC-pp -customLst -l -dATOM_STACK_CHECKING -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2019,1,4,22,4,48
+
+[Root.Peripherals.Config.0.Settings.2]
+String.2.0=Assembling $(InputFile)...
+String.3.0=castm8 -xx -l $(ToolsetIncOpts) -o$(IntermPath)$(InputName).$(ObjectExt) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+
+[Root.Peripherals.Config.0.Settings.3]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Peripherals.Config.1.Settings.0]
+String.6.0=2018,12,31,17,30,3
+String.8.0=Release
+Int.0=0
+Int.1=0
+
+[Root.Peripherals.Config.1.Settings.1]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel +mods0 -customC-pp $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+
+[Root.Peripherals.Config.1.Settings.2]
+String.2.0=Assembling $(InputFile)...
+String.3.0=castm8 $(ToolsetIncOpts) -o$(IntermPath)$(InputName).$(ObjectExt) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+
+[Root.Peripherals.Config.1.Settings.3]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Peripherals.stm8l15x_stdperiph_driver\src\stm8l15x_usart.c]
+ElemType=File
+PathName=stm8l15x_stdperiph_driver\src\stm8l15x_usart.c
+Next=Root.Peripherals.stm8l15x_stdperiph_driver\src\stm8l15x_tim4.c
+
+[Root.Peripherals.stm8l15x_stdperiph_driver\src\stm8l15x_tim4.c]
+ElemType=File
+PathName=stm8l15x_stdperiph_driver\src\stm8l15x_tim4.c
+Next=Root.Peripherals.stm8l15x_stdperiph_driver\src\stm8l15x_gpio.c
+
+[Root.Peripherals.stm8l15x_stdperiph_driver\src\stm8l15x_gpio.c]
+ElemType=File
+PathName=stm8l15x_stdperiph_driver\src\stm8l15x_gpio.c
+Next=Root.Peripherals.stm8l15x_stdperiph_driver\src\stm8l15x_exti.c
+
+[Root.Peripherals.stm8l15x_stdperiph_driver\src\stm8l15x_exti.c]
+ElemType=File
+PathName=stm8l15x_stdperiph_driver\src\stm8l15x_exti.c
+Next=Root.Peripherals.stm8l15x_stdperiph_driver\src\stm8l15x_clk.c
+
+[Root.Peripherals.stm8l15x_stdperiph_driver\src\stm8l15x_clk.c]
+ElemType=File
+PathName=stm8l15x_stdperiph_driver\src\stm8l15x_clk.c
+Next=Root.Peripherals.stm8l15x_stdperiph_driver\inc\stm8l15x_usart.h
+
+[Root.Peripherals.stm8l15x_stdperiph_driver\inc\stm8l15x_usart.h]
+ElemType=File
+PathName=stm8l15x_stdperiph_driver\inc\stm8l15x_usart.h
+Next=Root.Peripherals.stm8l15x_stdperiph_driver\inc\stm8l15x_tim4.h
+
+[Root.Peripherals.stm8l15x_stdperiph_driver\inc\stm8l15x_tim4.h]
+ElemType=File
+PathName=stm8l15x_stdperiph_driver\inc\stm8l15x_tim4.h
+Next=Root.Peripherals.stm8l15x_stdperiph_driver\inc\stm8l15x_gpio.h
+
+[Root.Peripherals.stm8l15x_stdperiph_driver\inc\stm8l15x_gpio.h]
+ElemType=File
+PathName=stm8l15x_stdperiph_driver\inc\stm8l15x_gpio.h
+Next=Root.Peripherals.stm8l15x_stdperiph_driver\inc\stm8l15x_clk.h
+
+[Root.Peripherals.stm8l15x_stdperiph_driver\inc\stm8l15x_clk.h]
+ElemType=File
+PathName=stm8l15x_stdperiph_driver\inc\stm8l15x_clk.h
+Next=Root.Peripherals.stm8l15x_stdperiph_driver\inc\stm8l15x.h
+
+[Root.Peripherals.stm8l15x_stdperiph_driver\inc\stm8l15x.h]
+ElemType=File
+PathName=stm8l15x_stdperiph_driver\inc\stm8l15x.h
+
+[Root.Port]
+ElemType=Folder
+PathName=Port
+Child=Root.Port...\..\tests\signal3.c
+Config.0=Root.Port.Config.0
+Config.1=Root.Port.Config.1
+
+[Root.Port.Config.0]
+Settings.0.0=Root.Port.Config.0.Settings.0
+Settings.0.1=Root.Port.Config.0.Settings.1
+Settings.0.2=Root.Port.Config.0.Settings.2
+Settings.0.3=Root.Port.Config.0.Settings.3
+
+[Root.Port.Config.1]
+Settings.1.0=Root.Port.Config.1.Settings.0
+Settings.1.1=Root.Port.Config.1.Settings.1
+Settings.1.2=Root.Port.Config.1.Settings.2
+Settings.1.3=Root.Port.Config.1.Settings.3
+
+[Root.Port.Config.0.Settings.0]
+String.6.0=2018,12,31,17,30,8
+String.8.0=Debug
+Int.0=0
+Int.1=0
+
+[Root.Port.Config.0.Settings.1]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 +modsl0 -customDbg +debug -customOpt-no -customC-pp -customLst -l -dATOM_STACK_CHECKING -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2019,1,4,22,4,48
+
+[Root.Port.Config.0.Settings.2]
+String.2.0=Assembling $(InputFile)...
+String.3.0=castm8 -xx -l $(ToolsetIncOpts) -o$(IntermPath)$(InputName).$(ObjectExt) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+
+[Root.Port.Config.0.Settings.3]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Port.Config.1.Settings.0]
+String.6.0=2018,12,31,17,30,8
+String.8.0=Release
+Int.0=0
+Int.1=0
+
+[Root.Port.Config.1.Settings.1]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel +mods0 -customC-pp $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+
+[Root.Port.Config.1.Settings.2]
+String.2.0=Assembling $(InputFile)...
+String.3.0=castm8 $(ToolsetIncOpts) -o$(IntermPath)$(InputName).$(ObjectExt) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+
+[Root.Port.Config.1.Settings.3]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Port...\..\tests\signal3.c]
+ElemType=File
+PathName=..\..\tests\signal3.c
+Next=Root.Port...\..\tests\signal2.c
+
+[Root.Port...\..\tests\signal2.c]
+ElemType=File
+PathName=..\..\tests\signal2.c
+Next=Root.Port...\..\tests\signal1.c
+Config.0=Root.Port...\..\tests\signal2.c.Config.0
+Config.1=Root.Port...\..\tests\signal2.c.Config.1
+
+[Root.Port...\..\tests\signal2.c.Config.0]
+Settings.0.0=Root.Port...\..\tests\signal2.c.Config.0.Settings.0
+Settings.0.1=Root.Port...\..\tests\signal2.c.Config.0.Settings.1
+Settings.0.2=Root.Port...\..\tests\signal2.c.Config.0.Settings.2
+
+[Root.Port...\..\tests\signal2.c.Config.1]
+Settings.1.0=Root.Port...\..\tests\signal2.c.Config.1.Settings.0
+Settings.1.1=Root.Port...\..\tests\signal2.c.Config.1.Settings.1
+Settings.1.2=Root.Port...\..\tests\signal2.c.Config.1.Settings.2
+
+[Root.Port...\..\tests\signal2.c.Config.0.Settings.0]
+String.6.0=2019,1,4,22,56,19
+String.8.0=Debug
+Int.0=1
+Int.1=0
+
+[Root.Port...\..\tests\signal2.c.Config.0.Settings.1]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Port...\..\tests\signal2.c.Config.0.Settings.2]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 +modsl0 -customDbg +debug -customOpt-no -customC-pp -customLst -l -dATOM_STACK_CHECKING -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2019,1,4,22,4,48
+String.8.0=Debug
+
+[Root.Port...\..\tests\signal2.c.Config.1.Settings.0]
+String.6.0=2019,1,4,22,54,29
+String.8.0=Release
+Int.0=0
+Int.1=0
+
+[Root.Port...\..\tests\signal2.c.Config.1.Settings.1]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Port...\..\tests\signal2.c.Config.1.Settings.2]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel +mods0 -customC-pp $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+String.8.0=Release
+
+[Root.Port...\..\tests\signal1.c]
+ElemType=File
+PathName=..\..\tests\signal1.c
+Next=Root.Port...\..\tests\signal5.c
+Config.0=Root.Port...\..\tests\signal1.c.Config.0
+Config.1=Root.Port...\..\tests\signal1.c.Config.1
+
+[Root.Port...\..\tests\signal1.c.Config.0]
+Settings.0.0=Root.Port...\..\tests\signal1.c.Config.0.Settings.0
+Settings.0.1=Root.Port...\..\tests\signal1.c.Config.0.Settings.1
+Settings.0.2=Root.Port...\..\tests\signal1.c.Config.0.Settings.2
+
+[Root.Port...\..\tests\signal1.c.Config.1]
+Settings.1.0=Root.Port...\..\tests\signal1.c.Config.1.Settings.0
+Settings.1.1=Root.Port...\..\tests\signal1.c.Config.1.Settings.1
+Settings.1.2=Root.Port...\..\tests\signal1.c.Config.1.Settings.2
+
+[Root.Port...\..\tests\signal1.c.Config.0.Settings.0]
+String.6.0=2019,1,4,22,55,33
+String.8.0=Debug
+Int.0=1
+Int.1=0
+
+[Root.Port...\..\tests\signal1.c.Config.0.Settings.1]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Port...\..\tests\signal1.c.Config.0.Settings.2]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 +modsl0 -customDbg +debug -customOpt-no -customC-pp -customLst -l -dATOM_STACK_CHECKING -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2019,1,4,22,4,48
+String.8.0=Debug
+
+[Root.Port...\..\tests\signal1.c.Config.1.Settings.0]
+String.6.0=2019,1,4,22,54,29
+String.8.0=Release
+Int.0=0
+Int.1=0
+
+[Root.Port...\..\tests\signal1.c.Config.1.Settings.1]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Port...\..\tests\signal1.c.Config.1.Settings.2]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel +mods0 -customC-pp $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+String.8.0=Release
+
+[Root.Port...\..\tests\signal5.c]
+ElemType=File
+PathName=..\..\tests\signal5.c
+Next=Root.Port...\..\tests\signal4.c
+Config.0=Root.Port...\..\tests\signal5.c.Config.0
+Config.1=Root.Port...\..\tests\signal5.c.Config.1
+
+[Root.Port...\..\tests\signal5.c.Config.0]
+Settings.0.0=Root.Port...\..\tests\signal5.c.Config.0.Settings.0
+Settings.0.1=Root.Port...\..\tests\signal5.c.Config.0.Settings.1
+Settings.0.2=Root.Port...\..\tests\signal5.c.Config.0.Settings.2
+
+[Root.Port...\..\tests\signal5.c.Config.1]
+Settings.1.0=Root.Port...\..\tests\signal5.c.Config.1.Settings.0
+Settings.1.1=Root.Port...\..\tests\signal5.c.Config.1.Settings.1
+Settings.1.2=Root.Port...\..\tests\signal5.c.Config.1.Settings.2
+
+[Root.Port...\..\tests\signal5.c.Config.0.Settings.0]
+String.6.0=2019,1,4,22,53,53
+String.8.0=Debug
+Int.0=1
+Int.1=0
+
+[Root.Port...\..\tests\signal5.c.Config.0.Settings.1]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Port...\..\tests\signal5.c.Config.0.Settings.2]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 +modsl0 -customDbg +debug -customOpt-no -customC-pp -customLst -l -dATOM_STACK_CHECKING -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2019,1,4,22,4,48
+String.8.0=Debug
+
+[Root.Port...\..\tests\signal5.c.Config.1.Settings.0]
+String.6.0=2019,1,4,21,53,7
+String.8.0=Release
+Int.0=0
+Int.1=0
+
+[Root.Port...\..\tests\signal5.c.Config.1.Settings.1]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Port...\..\tests\signal5.c.Config.1.Settings.2]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel +mods0 -customC-pp $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+String.8.0=Release
+
+[Root.Port...\..\tests\signal4.c]
+ElemType=File
+PathName=..\..\tests\signal4.c
+Next=Root.Port...\..\tests\atomtests.h
+Config.0=Root.Port...\..\tests\signal4.c.Config.0
+Config.1=Root.Port...\..\tests\signal4.c.Config.1
+
+[Root.Port...\..\tests\signal4.c.Config.0]
+Settings.0.0=Root.Port...\..\tests\signal4.c.Config.0.Settings.0
+Settings.0.1=Root.Port...\..\tests\signal4.c.Config.0.Settings.1
+Settings.0.2=Root.Port...\..\tests\signal4.c.Config.0.Settings.2
+
+[Root.Port...\..\tests\signal4.c.Config.1]
+Settings.1.0=Root.Port...\..\tests\signal4.c.Config.1.Settings.0
+Settings.1.1=Root.Port...\..\tests\signal4.c.Config.1.Settings.1
+Settings.1.2=Root.Port...\..\tests\signal4.c.Config.1.Settings.2
+
+[Root.Port...\..\tests\signal4.c.Config.0.Settings.0]
+String.6.0=2019,1,4,22,54,54
+String.8.0=Debug
+Int.0=1
+Int.1=0
+
+[Root.Port...\..\tests\signal4.c.Config.0.Settings.1]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Port...\..\tests\signal4.c.Config.0.Settings.2]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 +modsl0 -customDebCompat -customOpt -no +split -customC-pp -customLst -l -dATOM_STACK_CHECKING -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2019,1,4,20,58,35
+String.8.0=Debug
+
+[Root.Port...\..\tests\signal4.c.Config.1.Settings.0]
+String.6.0=2019,1,4,20,57,19
+String.8.0=Release
+Int.0=0
+Int.1=0
+
+[Root.Port...\..\tests\signal4.c.Config.1.Settings.1]
+String.2.0=Performing Custom Build on $(InputFile)
+String.3.0=
+String.4.0=
+String.5.0=
+String.6.0=2018,12,31,17,27,53
+
+[Root.Port...\..\tests\signal4.c.Config.1.Settings.2]
+String.2.0=Compiling $(InputFile)...
+String.3.0=cxstm8 -i..\..\tests -istm8l15x_stdperiph_driver\inc -i..\..\kernel +mods0 -customC-pp $(ToolsetIncOpts) -cl$(IntermPath) -co$(IntermPath) $(InputFile)
+String.4.0=$(IntermPath)$(InputName).$(ObjectExt)
+String.5.0=$(IntermPath)$(InputName).ls
+String.6.0=2018,12,31,17,27,53
+String.8.0=Release
+
+[Root.Port...\..\tests\atomtests.h]
+ElemType=File
+PathName=..\..\tests\atomtests.h
+Next=Root.Port.uart.h
+
+[Root.Port.uart.h]
+ElemType=File
+PathName=uart.h
+Next=Root.Port.uart.c
+
+[Root.Port.uart.c]
+ElemType=File
+PathName=uart.c
+Next=Root.Port.tests-main.c
+
+[Root.Port.tests-main.c]
+ElemType=File
+PathName=tests-main.c
+Next=Root.Port.stm8l15x_it.h
+
+[Root.Port.stm8l15x_it.h]
+ElemType=File
+PathName=stm8l15x_it.h
+Next=Root.Port.stm8l15x_it.c
+
+[Root.Port.stm8l15x_it.c]
+ElemType=File
+PathName=stm8l15x_it.c
+Next=Root.Port.stm8l15x_conf.h
+
+[Root.Port.stm8l15x_conf.h]
+ElemType=File
+PathName=stm8l15x_conf.h
+Next=Root.Port.stm8_interrupt_vector.c
+
+[Root.Port.stm8_interrupt_vector.c]
+ElemType=File
+PathName=stm8_interrupt_vector.c
+Next=Root.Port.atomport-tests.h
+
+[Root.Port.atomport-tests.h]
+ElemType=File
+PathName=atomport-tests.h
+Next=Root.Port.atomport-private.h
+
+[Root.Port.atomport-private.h]
+ElemType=File
+PathName=atomport-private.h
+Next=Root.Port.atomport-asm-cosmic.s
+
+[Root.Port.atomport-asm-cosmic.s]
+ElemType=File
+PathName=atomport-asm-cosmic.s
+Next=Root.Port.atomport.h
+
+[Root.Port.atomport.h]
+ElemType=File
+PathName=atomport.h
+Next=Root.Port.atomport.c
+
+[Root.Port.atomport.c]
+ElemType=File
+PathName=atomport.c
\ No newline at end of file
diff --git a/ports/stm8l/atomthreads-sample-stvd.stw b/ports/stm8l/atomthreads-sample-stvd.stw
new file mode 100644
index 00000000..8181a493
--- /dev/null
+++ b/ports/stm8l/atomthreads-sample-stvd.stw
@@ -0,0 +1,8 @@
+; STMicroelectronics Workspace file
+
+[Version]
+Keyword=ST7Workspace-V0.7
+
+[Project0]
+Filename=atomthreads-cosmic.stp
+Dependencies=
\ No newline at end of file
diff --git a/ports/stm8l/atomthreads-sample-stvd.wdb b/ports/stm8l/atomthreads-sample-stvd.wdb
new file mode 100644
index 00000000..821cf563
--- /dev/null
+++ b/ports/stm8l/atomthreads-sample-stvd.wdb
@@ -0,0 +1,1379 @@
+
+[WorkState_v1_2]
+ptn_Child1=DockState
+ptn_Child2=ToolBarMgr
+
+[WorkState_v1_2.DockState]
+Bars=35
+ScreenCX=3286
+ScreenCY=1080
+ptn_Child1=Bar-0
+ptn_Child2=Bar-1
+ptn_Child3=Bar-2
+ptn_Child4=Bar-3
+ptn_Child5=Bar-4
+ptn_Child6=Bar-5
+ptn_Child7=Bar-6
+ptn_Child8=Bar-7
+ptn_Child9=Bar-8
+ptn_Child10=Bar-9
+ptn_Child11=Bar-10
+ptn_Child12=Bar-11
+ptn_Child13=Bar-12
+ptn_Child14=Bar-13
+ptn_Child15=Bar-14
+ptn_Child16=Bar-15
+ptn_Child17=Bar-16
+ptn_Child18=Bar-17
+ptn_Child19=Bar-18
+ptn_Child20=Bar-19
+ptn_Child21=Bar-20
+ptn_Child22=Bar-21
+ptn_Child23=Bar-22
+ptn_Child24=Bar-23
+ptn_Child25=Bar-24
+ptn_Child26=Bar-25
+ptn_Child27=Bar-26
+ptn_Child28=Bar-27
+ptn_Child29=Bar-28
+ptn_Child30=Bar-29
+ptn_Child31=Bar-30
+ptn_Child32=Bar-31
+ptn_Child33=Bar-32
+ptn_Child34=Bar-33
+ptn_Child35=Bar-34
+
+[WorkState_v1_2.DockState.Bar-0]
+BarID=59419
+Bars=88
+Bar#0=0
+Bar#1=59647
+Bar#2=0
+Bar#3=59392
+Bar#4=59396
+Bar#5=59400
+Bar#6=124939
+Bar#7=0
+Bar#8=124960
+Bar#9=0
+Bar#10=0
+Bar#11=59399
+Bar#12=59398
+Bar#13=59401
+Bar#14=124933
+Bar#15=124938
+Bar#16=0
+Bar#17=0
+Bar#18=32768
+Bar#19=0
+Bar#20=0
+Bar#21=0
+Bar#22=0
+Bar#23=0
+Bar#24=0
+Bar#25=0
+Bar#26=0
+Bar#27=0
+Bar#28=0
+Bar#29=0
+Bar#30=0
+Bar#31=0
+Bar#32=0
+Bar#33=0
+Bar#34=0
+Bar#35=0
+Bar#36=0
+Bar#37=0
+Bar#38=0
+Bar#39=0
+Bar#40=0
+Bar#41=0
+Bar#42=0
+Bar#43=0
+Bar#44=0
+Bar#45=0
+Bar#46=0
+Bar#47=0
+Bar#48=0
+Bar#49=0
+Bar#50=0
+Bar#51=0
+Bar#52=0
+Bar#53=0
+Bar#54=0
+Bar#55=0
+Bar#56=0
+Bar#57=0
+Bar#58=0
+Bar#59=0
+Bar#60=0
+Bar#61=0
+Bar#62=0
+Bar#63=0
+Bar#64=0
+Bar#65=0
+Bar#66=0
+Bar#67=0
+Bar#68=0
+Bar#69=0
+Bar#70=0
+Bar#71=0
+Bar#72=0
+Bar#73=0
+Bar#74=0
+Bar#75=0
+Bar#76=0
+Bar#77=0
+Bar#78=0
+Bar#79=0
+Bar#80=0
+Bar#81=0
+Bar#82=0
+Bar#83=0
+Bar#84=0
+Bar#85=0
+Bar#86=0
+Bar#87=0
+Style=0
+ExStyle=0
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=0
+MRUFloatCX=0
+MRUFloatCY=0
+MRUHorzDockCX=0
+MRUHorzDockCY=0
+MRUVertDockCX=0
+MRUVertDockCY=0
+MRUDockingState=0
+DockingStyle=0
+TypeID=0
+ClassName=
+WindowName=
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-1]
+BarID=32768
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=19
+MRUDockTopPos=44
+MRUDockRightPos=19
+MRUDockBottomPos=44
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=851
+Style=12110
+ExStyle=0
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=150
+MRUVertDockCX=300
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=8192
+TypeID=0
+ClassName=SECControlBar
+WindowName=
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-2]
+BarID=59422
+Bars=13
+Bar#0=0
+Bar#1=0
+Bar#2=8003
+Bar#3=8002
+Bar#4=0
+Bar#5=5707
+Bar#6=5706
+Bar#7=5710
+Bar#8=5704
+Bar#9=5721
+Bar#10=0
+Bar#11=32769
+Bar#12=0
+Style=0
+ExStyle=0
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=0
+MRUFloatCX=0
+MRUFloatCY=0
+MRUHorzDockCX=0
+MRUHorzDockCY=0
+MRUVertDockCX=0
+MRUVertDockCY=0
+MRUDockingState=0
+DockingStyle=0
+TypeID=0
+ClassName=
+WindowName=
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-3]
+BarID=32769
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=19
+MRUDockTopPos=44
+MRUDockRightPos=19
+MRUDockBottomPos=44
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=851
+Style=36686
+ExStyle=0
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=150
+MRUVertDockCX=300
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=32768
+TypeID=0
+ClassName=SECControlBar
+WindowName=
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-4]
+BarID=59420
+Bars=6
+Bar#0=0
+Bar#1=5708
+Bar#2=5720
+Bar#3=0
+Bar#4=32770
+Bar#5=0
+Style=0
+ExStyle=0
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=0
+MRUFloatCX=0
+MRUFloatCY=0
+MRUHorzDockCX=0
+MRUHorzDockCY=0
+MRUVertDockCX=0
+MRUVertDockCY=0
+MRUDockingState=0
+DockingStyle=0
+TypeID=0
+ClassName=
+WindowName=
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-5]
+BarID=32770
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=19
+MRUDockTopPos=44
+MRUDockRightPos=19
+MRUDockBottomPos=44
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=8014
+ExStyle=0
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=180
+MRUVertDockCX=150
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=4096
+TypeID=0
+ClassName=SECControlBar
+WindowName=
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-6]
+BarID=59421
+Bars=12
+Bar#0=0
+Bar#1=0
+Bar#2=5701
+Bar#3=0
+Bar#4=73539
+Bar#5=0
+Bar#6=35103
+Bar#7=35102
+Bar#8=35101
+Bar#9=35100
+Bar#10=32771
+Bar#11=0
+Style=0
+ExStyle=0
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=0
+MRUFloatCX=0
+MRUFloatCY=0
+MRUHorzDockCX=0
+MRUHorzDockCY=0
+MRUVertDockCX=0
+MRUVertDockCY=0
+MRUDockingState=0
+DockingStyle=0
+TypeID=0
+ClassName=
+WindowName=
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-7]
+BarID=32771
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=19
+MRUDockTopPos=44
+MRUDockRightPos=81133643
+MRUDockBottomPos=81252396
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=20302
+ExStyle=0
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=180
+MRUVertDockCX=150
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=16384
+TypeID=0
+ClassName=SECControlBar
+WindowName=
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-8]
+BarID=59647
+MRUWidth=412
+Docking=True
+MRUDockID=59419
+MRUDockLeftPos=-1
+MRUDockTopPos=31
+MRUDockRightPos=1399
+MRUDockBottomPos=62
+MRUFloatStyle=8196
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=12220
+ExStyle=131980
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=429
+MRUFloatCY=27
+MRUHorzDockCX=1400
+MRUHorzDockCY=31
+MRUVertDockCX=72
+MRUVertDockCY=527
+MRUDockingState=0
+DockingStyle=61440
+TypeID=14947
+ClassName=SECMDIMenuBar
+WindowName=Menu bar
+ResourceID=0
+ptn_Child1=ToolBarInfoEx
+
+[WorkState_v1_2.DockState.Bar-8.ToolBarInfoEx]
+Title=Menu bar
+Buttons=BAAAAAAIAACAAAAAAIAADAAAAAAIAAEAAAAAAIAAFAAAAAAIAAGAAAAAAIAAHAAAAAAIAAIAAAAAAIAAJAAAAAAIAAKAAAAAAIAA
+
+[WorkState_v1_2.DockState.Bar-9]
+BarID=59392
+YPos=30
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=-1
+MRUDockTopPos=31
+MRUDockRightPos=147
+MRUDockBottomPos=61
+MRUFloatStyle=8196
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=12212
+ExStyle=131852
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=184352
+MRUFloatCX=0
+MRUFloatCY=0
+MRUHorzDockCX=148
+MRUHorzDockCY=30
+MRUVertDockCX=0
+MRUVertDockCY=0
+MRUDockingState=0
+DockingStyle=61440
+TypeID=14946
+ClassName=SECCustomToolBar
+WindowName=File
+ResourceID=0
+ptn_Child1=ToolBarInfoEx
+
+[WorkState_v1_2.DockState.Bar-9.ToolBarInfoEx]
+Title=File
+Buttons=AABOAAAAAAGPDBAAAAAAAIIBAAAAAAAAAAAAAAAADABOAAAAAAAAAAAAAAAAHABOAAAAAA
+
+[WorkState_v1_2.DockState.Bar-10]
+BarID=59396
+XPos=147
+YPos=30
+MRUWidth=566
+Docking=True
+MRUDockID=59419
+MRUDockLeftPos=147
+MRUDockTopPos=31
+MRUDockRightPos=730
+MRUDockBottomPos=61
+MRUFloatStyle=8196
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=12212
+ExStyle=131852
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=631295
+MRUFloatCX=580
+MRUFloatCY=30
+MRUHorzDockCX=583
+MRUHorzDockCY=30
+MRUVertDockCX=158
+MRUVertDockCY=142
+MRUDockingState=0
+DockingStyle=61440
+TypeID=14946
+ClassName=SECCustomToolBar
+WindowName=Edit
+ResourceID=0
+ptn_Child1=ToolBarInfoEx
+
+[WorkState_v1_2.DockState.Bar-10.ToolBarInfoEx]
+Title=Edit
+Buttons=LCBOAAAAAAMCBOAAAAAAAAAAAAAAAADCBOAAAAAACCBOAAAAAAFCBOAAAAAAAAAAAAAAAAECBOAAAACAGJAAEFEBAAAAAAAAAAAAAAAAPJAIAAAAAAAAAAAAAAAAJAJBAAAAAACAJBAAAAAAIAJBAAAAAAAAJBAAAAAAAAAAAAAAAAKFEBAAAAAALFEBAAAAAAMFEBAAAAAANFEBAAAAAAAAAAAAAAAAOFEBAAAAAA
+
+[WorkState_v1_2.DockState.Bar-11]
+BarID=59397
+Visible=False
+XPos=-3
+MRUWidth=246
+Docking=True
+MRUDockID=59419
+MRUDockLeftPos=1912
+MRUDockTopPos=59
+MRUDockRightPos=2175
+MRUDockBottomPos=89
+MRUFloatStyle=8192
+MRUFloatXPos=1874
+MRUFloatYPos=57
+Style=12213
+ExStyle=131852
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=260
+MRUFloatCY=30
+MRUHorzDockCX=263
+MRUHorzDockCY=30
+MRUVertDockCX=31
+MRUVertDockCY=247
+MRUDockingState=0
+DockingStyle=61440
+TypeID=14946
+ClassName=SECCustomToolBar
+WindowName=View
+ResourceID=0
+ptn_Child1=ToolBarInfoEx
+
+[WorkState_v1_2.DockState.Bar-11.ToolBarInfoEx]
+Title=View
+Buttons=IFGBAAAAAAJFGBAAAAAAAAAAAAAAAAFEGBAAAAAACEPBAAAAAAMBJIAAAAAAMEGBAAAAAAAAAAAAAAAAOEGBAAAAAAKEGBAAAAAALEGBAAAAAAPEGBAAAAAADEPBAAAAAA
+
+[WorkState_v1_2.DockState.Bar-12]
+BarID=59398
+XPos=402
+YPos=60
+MRUWidth=339
+Docking=True
+MRUDockID=59419
+MRUDockLeftPos=402
+MRUDockTopPos=60
+MRUDockRightPos=758
+MRUDockBottomPos=90
+MRUFloatStyle=8196
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=12212
+ExStyle=131852
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=127407
+MRUFloatCX=356
+MRUFloatCY=30
+MRUHorzDockCX=356
+MRUHorzDockCY=30
+MRUVertDockCX=108
+MRUVertDockCY=115
+MRUDockingState=0
+DockingStyle=61440
+TypeID=14946
+ClassName=SECCustomToolBar
+WindowName=Project
+ResourceID=0
+ptn_Child1=ToolBarInfoEx
+
+[WorkState_v1_2.DockState.Bar-12.ToolBarInfoEx]
+Title=Project
+Buttons=KAAIAAAACAEGAAMAAIAAAACAEGAAAAAAAAAAAABBAIAAAAAACBAIAAAAAADBAIAAAAAAAAAAAAAAAAGBAIAAAAAAAAAAAAAAAACHIBAAAAAA
+
+[WorkState_v1_2.DockState.Bar-13]
+BarID=59399
+XPos=0
+YPos=60
+MRUWidth=385
+Docking=True
+MRUDockID=59419
+MRUDockLeftPos=14
+MRUDockTopPos=60
+MRUDockRightPos=416
+MRUDockBottomPos=90
+MRUFloatStyle=8196
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=12212
+ExStyle=131852
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=714187
+MRUFloatCX=402
+MRUFloatCY=30
+MRUHorzDockCX=402
+MRUHorzDockCY=30
+MRUVertDockCX=31
+MRUVertDockCY=387
+MRUDockingState=0
+DockingStyle=61440
+TypeID=14946
+ClassName=SECCustomToolBar
+WindowName=Debug
+ResourceID=0
+ptn_Child1=ToolBarInfoEx
+
+[WorkState_v1_2.DockState.Bar-13.ToolBarInfoEx]
+Title=Debug
+Buttons=HKAIAAAAAAIKAIAAAAAAAAAAAAAAAAADKBAAAAAAAAAAAAAAAAGPKBAAAAAAEPKBAAAAAAFPKBAAAAAAHPKBAAAAAAAAAAAAAAAAMPKBAAAAAAAAAAAAAAAAIPKBAAAAAAJPKBAAAAAANPKBAAAAAAOPKBAAAAAAKPKBAAAAAALPKBAAAAAAAAAAAAAAAABDKBAAAAAA
+
+[WorkState_v1_2.DockState.Bar-14]
+BarID=59400
+XPos=730
+YPos=30
+MRUWidth=23
+Docking=True
+MRUDockID=59419
+MRUDockLeftPos=730
+MRUDockTopPos=30
+MRUDockRightPos=862
+MRUDockBottomPos=60
+MRUFloatStyle=8196
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=12212
+ExStyle=131852
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=184352
+MRUFloatCX=40
+MRUFloatCY=30
+MRUHorzDockCX=132
+MRUHorzDockCY=30
+MRUVertDockCX=31
+MRUVertDockCY=39
+MRUDockingState=0
+DockingStyle=61440
+TypeID=14946
+ClassName=SECCustomToolBar
+WindowName=Debug instrument
+ResourceID=0
+ptn_Child1=ToolBarInfoEx
+
+[WorkState_v1_2.DockState.Bar-14.ToolBarInfoEx]
+Title=Debug instrument
+Buttons=JPAIAAAAAAAFPBAAAAAANEPBAAAAAABFPBAAAAAACFPBAAAAAA
+
+[WorkState_v1_2.DockState.Bar-15]
+BarID=59401
+XPos=758
+YPos=60
+MRUWidth=77
+Docking=True
+MRUDockID=59419
+MRUDockLeftPos=758
+MRUDockTopPos=60
+MRUDockRightPos=829
+MRUDockBottomPos=90
+MRUFloatStyle=8196
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=12212
+ExStyle=131852
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=158405
+MRUFloatCX=94
+MRUFloatCY=30
+MRUHorzDockCX=71
+MRUHorzDockCY=30
+MRUVertDockCX=31
+MRUVertDockCY=88
+MRUDockingState=0
+DockingStyle=61440
+TypeID=14946
+ClassName=SECCustomToolBar
+WindowName=Tools
+ResourceID=0
+ptn_Child1=ToolBarInfoEx
+
+[WorkState_v1_2.DockState.Bar-15.ToolBarInfoEx]
+Title=Tools
+Buttons=AHHBAAAAAABHHBAAAAAAAAAAAAAAAA
+
+[WorkState_v1_2.DockState.Bar-16]
+BarID=59402
+Visible=False
+XPos=-3
+MRUWidth=115
+Docking=True
+MRUDockID=59419
+MRUDockLeftPos=1047
+MRUDockTopPos=59
+MRUDockRightPos=1179
+MRUDockBottomPos=89
+MRUFloatStyle=8192
+MRUFloatXPos=1215
+MRUFloatYPos=190
+Style=12213
+ExStyle=131852
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=129
+MRUFloatCY=30
+MRUHorzDockCX=132
+MRUHorzDockCY=30
+MRUVertDockCX=31
+MRUVertDockCY=127
+MRUDockingState=0
+DockingStyle=61440
+TypeID=14946
+ClassName=SECCustomToolBar
+WindowName=Window
+ResourceID=0
+ptn_Child1=ToolBarInfoEx
+
+[WorkState_v1_2.DockState.Bar-16.ToolBarInfoEx]
+Title=Window
+Buttons=OHIBAAAAAAPHIBAAAAAACDBOAAAAAADDBOAAAAAAEDBOAAAAAA
+
+[WorkState_v1_2.DockState.Bar-17]
+BarID=59403
+Visible=False
+XPos=-3
+MRUWidth=115
+Docking=True
+MRUDockID=59419
+MRUDockLeftPos=378
+MRUDockTopPos=31
+MRUDockRightPos=510
+MRUDockBottomPos=61
+MRUFloatStyle=8196
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=12213
+ExStyle=131852
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=129
+MRUFloatCY=30
+MRUHorzDockCX=132
+MRUHorzDockCY=30
+MRUVertDockCX=31
+MRUVertDockCY=127
+MRUDockingState=0
+DockingStyle=61440
+TypeID=14946
+ClassName=SECCustomToolBar
+WindowName=Help
+ResourceID=0
+ptn_Child1=ToolBarInfoEx
+
+[WorkState_v1_2.DockState.Bar-17.ToolBarInfoEx]
+Title=Help
+Buttons=KDIBAAAAAADEBOAAAAAAAEBOAAAAAAEFPBAAAAAAFFPBAAAAAA
+
+[WorkState_v1_2.DockState.Bar-18]
+BarID=5720
+XPos=1
+YPos=-2
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=1
+MRUDockTopPos=-2
+MRUDockRightPos=299
+MRUDockBottomPos=529
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=8068
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=180
+MRUVertDockCX=298
+MRUVertDockCY=531
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=CProjectWorkspaceWnd
+WindowName=Workspace
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-19]
+BarID=5721
+XPos=936
+YPos=5
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=936
+MRUDockTopPos=5
+MRUDockRightPos=1400
+MRUDockBottomPos=218
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=36756
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=333334
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=464
+MRUHorzDockCY=213
+MRUVertDockCX=300
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=COutputControlBar
+WindowName=Output
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-20]
+BarID=5701
+XPos=5
+YPos=-2
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=5
+MRUDockTopPos=31
+MRUDockRightPos=155
+MRUDockBottomPos=562
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=20356
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=180
+MRUVertDockCX=150
+MRUVertDockCY=531
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=CNewDisassControlBar
+WindowName=Disassembly
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-21]
+BarID=5704
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=14
+MRUDockTopPos=31
+MRUDockRightPos=14
+MRUDockBottomPos=31
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=36612
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=500000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=213
+MRUVertDockCX=300
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=CRegisterControlBar
+WindowName=Registers
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-22]
+BarID=35100
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=19
+MRUDockTopPos=44
+MRUDockRightPos=19
+MRUDockBottomPos=44
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=20356
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=180
+MRUVertDockCX=150
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=CNewDumpControlBar
+WindowName=Memory #1
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-23]
+BarID=35101
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=19
+MRUDockTopPos=44
+MRUDockRightPos=19
+MRUDockBottomPos=44
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=20356
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=180
+MRUVertDockCX=150
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=CNewDumpControlBar
+WindowName=Memory #2
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-24]
+BarID=35102
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=19
+MRUDockTopPos=44
+MRUDockRightPos=19
+MRUDockBottomPos=44
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=20356
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=180
+MRUVertDockCX=150
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=CNewDumpControlBar
+WindowName=Memory #3
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-25]
+BarID=35103
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=19
+MRUDockTopPos=44
+MRUDockRightPos=19
+MRUDockBottomPos=44
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=20356
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=1000000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=180
+MRUVertDockCX=150
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=CNewDumpControlBar
+WindowName=Memory #4
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-26]
+BarID=5708
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=14
+MRUDockTopPos=31
+MRUDockRightPos=14
+MRUDockBottomPos=31
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=8068
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=500000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=180
+MRUVertDockCX=298
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=CSoftBkControlBar
+WindowName=Instruction Breakpoints
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-27]
+BarID=5710
+XPos=1
+YPos=5
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=1
+MRUDockTopPos=5
+MRUDockRightPos=930
+MRUDockBottomPos=218
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=36740
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=666665
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=929
+MRUHorzDockCY=213
+MRUVertDockCX=300
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=CWatchControlBar
+WindowName=Watch
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-28]
+BarID=5706
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=14
+MRUDockTopPos=31
+MRUDockRightPos=14
+MRUDockBottomPos=31
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=36612
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=750000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=213
+MRUVertDockCX=300
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=CStackControlBar
+WindowName=Call Stack
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-29]
+BarID=5707
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=14
+MRUDockTopPos=31
+MRUDockRightPos=14
+MRUDockBottomPos=31
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=36612
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=800000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=213
+MRUVertDockCX=300
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=CLocalsControlBar
+WindowName=Local Variables
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-30]
+BarID=8002
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=14
+MRUDockTopPos=31
+MRUDockRightPos=7864349
+MRUDockBottomPos=465191
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=1084
+Style=36740
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=666665
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=150
+MRUVertDockCX=300
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=CAddedControlBar
+WindowName=Core Registers
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-31]
+BarID=8003
+Visible=False
+XPos=0
+YPos=0
+Docking=True
+MRUDockID=0
+MRUDockLeftPos=14
+MRUDockTopPos=31
+MRUDockRightPos=14
+MRUDockBottomPos=31
+MRUFloatStyle=4
+MRUFloatXPos=-2
+MRUFloatYPos=0
+Style=36740
+ExStyle=69393
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=750000
+MRUFloatCX=300
+MRUFloatCY=180
+MRUHorzDockCX=300
+MRUHorzDockCY=150
+MRUVertDockCX=300
+MRUVertDockCY=180
+MRUDockingState=0
+DockingStyle=61440
+TypeID=0
+ClassName=CAddedControlBar
+WindowName=Peripheral Registers
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-32]
+BarID=59423
+Horz=True
+Floating=True
+XPos=389
+YPos=80
+Bars=3
+Bar#0=0
+Bar#1=59403
+Bar#2=0
+Style=0
+ExStyle=0
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=0
+MRUFloatCX=0
+MRUFloatCY=0
+MRUHorzDockCX=0
+MRUHorzDockCY=0
+MRUVertDockCX=0
+MRUVertDockCY=0
+MRUDockingState=0
+DockingStyle=0
+TypeID=0
+ClassName=
+WindowName=
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-33]
+BarID=59423
+Horz=True
+Floating=True
+XPos=1225
+YPos=213
+Bars=3
+Bar#0=0
+Bar#1=59402
+Bar#2=0
+Style=0
+ExStyle=0
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=0
+MRUFloatCX=0
+MRUFloatCY=0
+MRUHorzDockCX=0
+MRUHorzDockCY=0
+MRUVertDockCX=0
+MRUVertDockCY=0
+MRUDockingState=0
+DockingStyle=0
+TypeID=0
+ClassName=
+WindowName=
+ResourceID=0
+
+[WorkState_v1_2.DockState.Bar-34]
+BarID=59423
+Horz=True
+Floating=True
+XPos=1884
+YPos=80
+Bars=3
+Bar#0=0
+Bar#1=59397
+Bar#2=0
+Style=0
+ExStyle=0
+PrevFloating=False
+MDIChild=False
+AutoHide=False
+AutoHidePinned=False
+LastAlignedDocking=0
+PctWidth=0
+MRUFloatCX=0
+MRUFloatCY=0
+MRUHorzDockCX=0
+MRUHorzDockCY=0
+MRUVertDockCX=0
+MRUVertDockCY=0
+MRUDockingState=0
+DockingStyle=0
+TypeID=0
+ClassName=
+WindowName=
+ResourceID=0
+
+[WorkState_v1_2.ToolBarMgr]
+ToolTips=True
+CoolLook=True
+LargeButtons=False
diff --git a/ports/stm8l/checkres.spy b/ports/stm8l/checkres.spy
new file mode 100644
index 00000000..92017b7f
--- /dev/null
+++ b/ports/stm8l/checkres.spy
@@ -0,0 +1,9 @@
+;
+; ** Welcome to ST Visual Debug SPY System **
+; ** Copyright STMicroelectronics (c) 1999, all rights reserved **
+; Level 1
+; Date 12/31/18
+; Time 22:23:42
+;
+<.\confmenu.cpp:170-22:23:42>
+Error: resource handle has not been restored in .\mainfrm.cpp:3205
diff --git a/ports/stm8l/stm8_interrupt_vector.c b/ports/stm8l/stm8_interrupt_vector.c
new file mode 100644
index 00000000..f8500e3d
--- /dev/null
+++ b/ports/stm8l/stm8_interrupt_vector.c
@@ -0,0 +1,49 @@
+/* BASIC INTERRUPT VECTOR TABLE FOR STM8 devices
+ * Copyright (c) 2013 STMicroelectronics
+ */
+
+
+#include "stm8l15x_it.h"
+
+typedef void @far (*interrupt_handler_t)(void);
+
+struct interrupt_vector {
+ uint8_t interrupt_instruction;
+ interrupt_handler_t interrupt_handler;
+};
+
+struct interrupt_vector const _vectab[] = {
+ {0x82, (interrupt_handler_t)_stext}, /* Reset */
+ {0x82, (interrupt_handler_t)TRAP_IRQHandler}, /* TRAP - Software interrupt */
+ {0x82, (interrupt_handler_t)NonHandledInterrupt}, /* Reserved */
+ {0x82, (interrupt_handler_t)FLASH_IRQHandler}, /* irq1 - FLASH interrupt */
+ {0x82, (interrupt_handler_t)DMA1_CHANNEL0_1_IRQHandler}, /* irq2 - DMA1 channel0 and channel1 interrupt */
+ {0x82, (interrupt_handler_t)DMA1_CHANNEL2_3_IRQHandler}, /* irq3 - DMA1 channel2 and channel3 interrupt */
+ {0x82, (interrupt_handler_t)RTC_CSSLSE_IRQHandler}, /* irq4 - RTC/ CSS on LSE interrupt */
+ {0x82, (interrupt_handler_t)EXTIE_F_PVD_IRQHandler}, /* irq5 - External IT PORTE/F interrupt /PVD interrupt*/
+ {0x82, (interrupt_handler_t)EXTIB_G_IRQHandler}, /* irq6 - External IT PORTB / PORTG interrupt */
+ {0x82, (interrupt_handler_t)EXTID_H_IRQHandler}, /* irq7 - External IT PORTD / PORTH interrupt */
+ {0x82, (interrupt_handler_t)EXTI0_IRQHandler}, /* irq8 - External IT PIN0 interrupt */
+ {0x82, (interrupt_handler_t)EXTI1_IRQHandler}, /* irq9 - External IT PIN1 interrupt */
+ {0x82, (interrupt_handler_t)EXTI2_IRQHandler}, /* irq10 - External IT PIN2 interrupt */
+ {0x82, (interrupt_handler_t)EXTI3_IRQHandler}, /* irq11 - External IT PIN3 interrupt */
+ {0x82, (interrupt_handler_t)EXTI4_IRQHandler}, /* irq12 - External IT PIN4 interrupt */
+ {0x82, (interrupt_handler_t)EXTI5_IRQHandler}, /* irq13 - External IT PIN5 interrupt */
+ {0x82, (interrupt_handler_t)EXTI6_IRQHandler}, /* irq14 - External IT PIN6 interrupt */
+ {0x82, (interrupt_handler_t)EXTI7_IRQHandler}, /* irq15 - External IT PIN7 interrupt */
+ {0x82, (interrupt_handler_t)LCD_AES_IRQHandler}, /* irq16 - LCD / AES interrupt */
+ {0x82, (interrupt_handler_t)SWITCH_CSS_BREAK_DAC_IRQHandler}, /* irq17 - CLK switch/CSS interrupt/ TIM1 Break interrupt / DAC */
+ {0x82, (interrupt_handler_t)ADC1_COMP_IRQHandler}, /* irq18 - ADC1 and Comparator interrupt */
+ {0x82, (interrupt_handler_t)TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler}, /* irq19 - TIM2 Update/Overflow/Trigger/Break / USART2 TX interrupt */
+ {0x82, (interrupt_handler_t)TIM2_CC_USART2_RX_IRQHandler}, /* irq20 - TIM2 Capture/Compare / USART2 RX interrupt */
+ {0x82, (interrupt_handler_t)TIM3_UPD_OVF_TRG_BRK_USART3_TX_IRQHandler}, /* irq21 - TIM3 Update/Overflow/Trigger/Break / USART3 TX interrupt */
+ {0x82, (interrupt_handler_t)TIM3_CC_USART3_RX_IRQHandler}, /* irq22 - TIM3 Capture/Compare /USART3 RX interrupt */
+ {0x82, (interrupt_handler_t)TIM1_UPD_OVF_TRG_COM_IRQHandler}, /* irq23 - TIM1 Update/Overflow/Trigger/Commutation interrupt */
+ {0x82, (interrupt_handler_t)TIM1_CC_IRQHandler}, /* irq24 - TIM1 Capture/Compare interrupt */
+ {0x82, (interrupt_handler_t)TIM4_UPD_OVF_TRG_IRQHandler}, /* irq25 - TIM4 Update/Overflow/Trigger interrupt */
+ {0x82, (interrupt_handler_t)SPI1_IRQHandler}, /* irq26 - SPI1 interrupt */
+ {0x82, (interrupt_handler_t)USART1_TX_TIM5_UPD_OVF_TRG_BRK_IRQHandler}, /* irq27 - USART1 TX / TIM5 Update/Overflow/Trigger/Break interrupt */
+ {0x82, (interrupt_handler_t)USART1_RX_TIM5_CC_IRQHandler}, /* irq28 - USART1 RX / TIM1 Capture/Compare interrupt */
+ {0x82, (interrupt_handler_t)I2C1_SPI2_IRQHandler}, /* irq29 - I2C1 / SPI2 interrupt */
+
+};
diff --git a/ports/stm8l/stm8l15x_conf.h b/ports/stm8l/stm8l15x_conf.h
new file mode 100644
index 00000000..d1a5bfcd
--- /dev/null
+++ b/ports/stm8l/stm8l15x_conf.h
@@ -0,0 +1,91 @@
+/**
+ ******************************************************************************
+ * @file Project/STM8L15x_StdPeriph_Template/stm8l15x_conf.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief Library configuration file.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_CONF_H
+#define __STM8L15x_CONF_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/* Uncomment the line below to enable peripheral header file inclusion */
+//#include "stm8l15x_adc.h"
+//#include "stm8l15x_aes.h"
+//#include "stm8l15x_beep.h"
+#include "stm8l15x_clk.h"
+//#include "stm8l15x_comp.h"
+//#include "stm8l15x_dac.h"
+//#include "stm8l15x_dma.h"
+#include "stm8l15x_exti.h"
+//#include "stm8l15x_flash.h"
+#include "stm8l15x_gpio.h"
+//#include "stm8l15x_i2c.h"
+//#include "stm8l15x_irtim.h"
+//#include "stm8l15x_itc.h"
+//#include "stm8l15x_iwdg.h"
+//#include "stm8l15x_lcd.h"
+//#include "stm8l15x_pwr.h"
+//#include "stm8l15x_rst.h"
+//#include "stm8l15x_rtc.h"
+//#include "stm8l15x_spi.h"
+//#include "stm8l15x_syscfg.h"
+//#include "stm8l15x_tim1.h"
+//#include "stm8l15x_tim2.h"
+//#include "stm8l15x_tim3.h"
+#include "stm8l15x_tim4.h"
+//#include "stm8l15x_tim5.h"
+#include "stm8l15x_usart.h"
+//#include "stm8l15x_wfe.h"
+//#include "stm8l15x_wwdg.h"
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Uncomment the line below to expanse the "assert_param" macro in the
+ Standard Peripheral Library drivers code */
+/* #define USE_FULL_ASSERT (1) */
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef USE_FULL_ASSERT
+
+/**
+ * @brief The assert_param macro is used for function's parameters check.
+ * @param expr: If expr is false, it calls assert_failed function
+ * which reports the name of the source file and the source
+ * line number of the call that failed.
+ * If expr is true, it returns no value.
+ * @retval : None
+ */
+ #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+ void assert_failed(uint8_t* file, uint32_t line);
+#else
+ #define assert_param(expr) ((void)0)
+#endif /* USE_FULL_ASSERT */
+
+#endif /* __STM8L15x_CONF_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm8l/stm8l15x_it.c b/ports/stm8l/stm8l15x_it.c
new file mode 100644
index 00000000..33fdb50c
--- /dev/null
+++ b/ports/stm8l/stm8l15x_it.c
@@ -0,0 +1,418 @@
+/**
+ ******************************************************************************
+ * @file Project/STM8L15x_StdPeriph_Template/stm8l15x_it.c
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief Main Interrupt Service Routines.
+ * This file provides template for all peripherals interrupt service routine.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x_it.h"
+
+/** @addtogroup STM8L15x_StdPeriph_Template
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Public functions ----------------------------------------------------------*/
+
+extern void TIM4_SystemTickISR(void);
+
+#ifdef _COSMIC_
+/**
+ * @brief Dummy interrupt routine
+ * @par Parameters:
+ * None
+ * @retval
+ * None
+*/
+INTERRUPT_HANDLER(NonHandledInterrupt,0)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+#endif
+
+/**
+ * @brief TRAP interrupt routine
+ * @par Parameters:
+ * None
+ * @retval
+ * None
+*/
+INTERRUPT_HANDLER_TRAP(TRAP_IRQHandler)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+/**
+ * @brief FLASH Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(FLASH_IRQHandler,1)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+/**
+ * @brief DMA1 channel0 and channel1 Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(DMA1_CHANNEL0_1_IRQHandler,2)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+/**
+ * @brief DMA1 channel2 and channel3 Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(DMA1_CHANNEL2_3_IRQHandler,3)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+/**
+ * @brief RTC / CSS_LSE Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(RTC_CSSLSE_IRQHandler,4)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+/**
+ * @brief External IT PORTE/F and PVD Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(EXTIE_F_PVD_IRQHandler,5)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief External IT PORTB / PORTG Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(EXTIB_G_IRQHandler,6)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief External IT PORTD /PORTH Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(EXTID_H_IRQHandler,7)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief External IT PIN0 Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(EXTI0_IRQHandler,8)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief External IT PIN1 Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(EXTI1_IRQHandler,9)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief External IT PIN2 Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(EXTI2_IRQHandler,10)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief External IT PIN3 Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(EXTI3_IRQHandler,11)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief External IT PIN4 Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(EXTI4_IRQHandler,12)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief External IT PIN5 Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(EXTI5_IRQHandler,13)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief External IT PIN6 Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(EXTI6_IRQHandler,14)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief External IT PIN7 Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(EXTI7_IRQHandler,15)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+/**
+ * @brief LCD /AES Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(LCD_AES_IRQHandler,16)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+/**
+ * @brief CLK switch/CSS/TIM1 break Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(SWITCH_CSS_BREAK_DAC_IRQHandler,17)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief ADC1/Comparator Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(ADC1_COMP_IRQHandler,18)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief TIM2 Update/Overflow/Trigger/Break /USART2 TX Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler,19)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief Timer2 Capture/Compare / USART2 RX Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(TIM2_CC_USART2_RX_IRQHandler,20)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+
+/**
+ * @brief Timer3 Update/Overflow/Trigger/Break Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(TIM3_UPD_OVF_TRG_BRK_USART3_TX_IRQHandler,21)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+/**
+ * @brief Timer3 Capture/Compare /USART3 RX Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(TIM3_CC_USART3_RX_IRQHandler,22)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+/**
+ * @brief TIM1 Update/Overflow/Trigger/Commutation Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_COM_IRQHandler,23)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+/**
+ * @brief TIM1 Capture/Compare Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(TIM1_CC_IRQHandler,24)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief TIM4 Update/Overflow/Trigger Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(TIM4_UPD_OVF_TRG_IRQHandler,25)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+ TIM4_SystemTickISR();
+}
+/**
+ * @brief SPI1 Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(SPI1_IRQHandler,26)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief USART1 TX / TIM5 Update/Overflow/Trigger/Break Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(USART1_TX_TIM5_UPD_OVF_TRG_BRK_IRQHandler,27)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief USART1 RX / Timer5 Capture/Compare Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(USART1_RX_TIM5_CC_IRQHandler,28)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+
+/**
+ * @brief I2C1 / SPI2 Interrupt routine.
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(I2C1_SPI2_IRQHandler,29)
+{
+ /* In order to detect unexpected events during development,
+ it is recommended to set a breakpoint on the following instruction.
+ */
+}
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
\ No newline at end of file
diff --git a/ports/stm8l/stm8l15x_it.h b/ports/stm8l/stm8l15x_it.h
new file mode 100644
index 00000000..e7ace05c
--- /dev/null
+++ b/ports/stm8l/stm8l15x_it.h
@@ -0,0 +1,79 @@
+/**
+ ******************************************************************************
+ * @file Project/STM8L15x_StdPeriph_Template/stm8l15x_it.h
+ * @author MCD Application Team
+ * @version V1.6.1
+ * @date 30-September-2014
+ * @brief This file contains the headers of the interrupt handlers.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT 2014 STMicroelectronics
+ *
+ * Licensed under MCD-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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM8L15x_IT_H
+#define __STM8L15x_IT_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm8l15x.h"
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+#ifdef _COSMIC_
+ void _stext(void); /* RESET startup routine */
+ INTERRUPT void NonHandledInterrupt(void);
+#endif /* _COSMIC_ */
+
+#ifndef _RAISONANCE_
+ INTERRUPT void TRAP_IRQHandler(void); /* TRAP */
+ INTERRUPT void FLASH_IRQHandler(void); /* FLASH EOP/PG_DIS */
+ INTERRUPT void DMA1_CHANNEL0_1_IRQHandler(void); /* DMA1 Channel0/1*/
+ INTERRUPT void DMA1_CHANNEL2_3_IRQHandler(void); /*DMA1 Channel2/3*/
+ INTERRUPT void RTC_CSSLSE_IRQHandler(void); /* RTC /CSS_LSE */
+ INTERRUPT void EXTIE_F_PVD_IRQHandler(void); /*EXTI PORTE/EXTI PORTF/PVD*/
+ INTERRUPT void EXTIB_G_IRQHandler(void); /* EXTI PORTB / EXTI PORTG */
+ INTERRUPT void EXTID_H_IRQHandler(void); /* EXTI PORTD / EXTI PORTH*/
+ INTERRUPT void EXTI0_IRQHandler(void); /* EXTI PIN0 */
+ INTERRUPT void EXTI1_IRQHandler(void); /* EXTI PIN1 */
+ INTERRUPT void EXTI2_IRQHandler(void); /* EXTI PIN2 */
+ INTERRUPT void EXTI3_IRQHandler(void); /* EXTI PIN3 */
+ INTERRUPT void EXTI4_IRQHandler(void); /* EXTI PIN4 */
+ INTERRUPT void EXTI5_IRQHandler(void); /* EXTI PIN5 */
+ INTERRUPT void EXTI6_IRQHandler(void); /* EXTI PIN6 */
+ INTERRUPT void EXTI7_IRQHandler(void); /* EXTI PIN7 */
+ INTERRUPT void LCD_AES_IRQHandler(void); /* LCD /AES */
+ INTERRUPT void SWITCH_CSS_BREAK_DAC_IRQHandler(void); /* Switch CLK/CSS/TIM1 Break/DAC */
+ INTERRUPT void ADC1_COMP_IRQHandler(void); /*ADC1/COMP*/
+ INTERRUPT void TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler(void); /* TIM2 UPD/OVF/TRG/BRK / USART2 TX */
+ INTERRUPT void TIM2_CC_USART2_RX_IRQHandler(void); /* TIM2 CAP / USART2 RX */
+ INTERRUPT void TIM3_UPD_OVF_TRG_BRK_USART3_TX_IRQHandler(void); /* TIM3 UPD/OVF/TRG/BRK /USART3 TX*/
+ INTERRUPT void TIM3_CC_USART3_RX_IRQHandler(void); /* TIM3 CAP/ USART3 RX */
+ INTERRUPT void TIM1_UPD_OVF_TRG_COM_IRQHandler(void);/* TIM1 UPD/OVF/TRG/COM */
+ INTERRUPT void TIM1_CC_IRQHandler(void);/* TIM1 CAP*/
+ INTERRUPT void TIM4_UPD_OVF_TRG_IRQHandler(void); /* TIM4 UPD/OVF/TRI */
+ INTERRUPT void SPI1_IRQHandler(void); /* SPI1 */
+ INTERRUPT void USART1_TX_TIM5_UPD_OVF_TRG_BRK_IRQHandler(void); /* USART1 TX / TIM5 UPD/OVF/TRG/BRK */
+ INTERRUPT void USART1_RX_TIM5_CC_IRQHandler(void); /* USART1 RX / TIM5 CAP */
+ INTERRUPT void I2C1_SPI2_IRQHandler(void); /* I2C1 / SPI2 */
+#endif /* _RAISONANCE_ */
+
+#endif /* __STM8L15x_IT_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
\ No newline at end of file
diff --git a/ports/stm8l/tests-main.c b/ports/stm8l/tests-main.c
new file mode 100644
index 00000000..9796e54a
--- /dev/null
+++ b/ports/stm8l/tests-main.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2010, Kelvin Lawson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. No personal names or organizations' names associated with the
+ * Atomthreads project may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include
+
+#include "atom.h"
+#include "atomport-private.h"
+#include "atomport-tests.h"
+#include "atomtests.h"
+#include "atomtimer.h"
+#include "uart.h"
+#include "stm8l15x.h"
+
+
+/* Constants */
+
+/*
+ * Idle thread stack size
+ *
+ * This needs to be large enough to handle any interrupt handlers
+ * and callbacks called by interrupt handlers (e.g. user-created
+ * timer callbacks) as well as the saving of all context when
+ * switching away from this thread.
+ *
+ * In this case, the idle stack is allocated on the BSS via the
+ * idle_thread_stack[] byte array.
+ */
+#define IDLE_STACK_SIZE_BYTES 128
+
+
+/*
+ * Main thread stack size
+ *
+ * Note that this is not a required OS kernel thread - you will replace
+ * this with your own application thread.
+ *
+ * In this case the Main thread is responsible for calling out to the
+ * test routines. Once a test routine has finished, the test status is
+ * printed out on the UART and the thread remains running in a loop
+ * flashing a LED.
+ *
+ * The Main thread stack generally needs to be larger than the idle
+ * thread stack, as not only does it need to store interrupt handler
+ * stack saves and context switch saves, but the application main thread
+ * will generally be carrying out more nested function calls and require
+ * stack for application code local variables etc.
+ *
+ * With all OS tests implemented to date on the STM8, the Main thread
+ * stack has not exceeded 384 bytes. To allow all tests to run we set
+ * a minimum main thread stack size of 204 bytes. This may increase in
+ * future as the codebase changes but for the time being is enough to
+ * cope with all of the automated tests.
+ */
+#define MAIN_STACK_SIZE_BYTES 384
+
+
+/*
+ * Startup code stack
+ *
+ * Some stack space is required at initial startup for running the main()
+ * routine. This stack space is only temporarily required at first bootup
+ * and is no longer required as soon as the OS is started. By default
+ * Cosmic sets this to the top of RAM and it grows down from there.
+ *
+ * Because we only need this temporarily you may reuse the area once the
+ * OS is started, and are free to use some area other than the top of RAM.
+ * For convenience we just use the default region here.
+ */
+
+
+/* Local data */
+
+/* Application threads' TCBs */
+static ATOM_TCB main_tcb;
+
+/* Main thread's stack area (large so place outside of the small page0 area on STM8) */
+NEAR static uint8_t main_thread_stack[MAIN_STACK_SIZE_BYTES];
+
+/* Idle thread's stack area (large so place outside of the small page0 area on STM8) */
+NEAR static uint8_t idle_thread_stack[IDLE_STACK_SIZE_BYTES];
+
+
+/* Forward declarations */
+static void main_thread_func (uint32_t param);
+
+
+/**
+ * \b main
+ *
+ * Program entry point.
+ *
+ * Sets up the STM8l hardware resources (system tick timer interrupt) necessary
+ * for the OS to be started. Creates an application thread and starts the OS.
+ *
+ * If the compiler supports it, stack space can be saved by preventing
+ * the function from saving registers on entry. This is because we
+ * are called directly by the C startup assembler, and know that we will
+ * never return from here. The NO_REG_SAVE macro is used to denote such
+ * functions in a compiler-agnostic way, though not all compilers support it.
+ *
+ */
+NO_REG_SAVE void main ( void )
+{
+ int8_t status;
+
+ /**
+ * Note: to protect OS structures and data during initialisation,
+ * interrupts must remain disabled until the first thread
+ * has been restored. They are reenabled at the very end of
+ * the first thread restore, at which point it is safe for a
+ * reschedule to take place.
+ */
+
+ /* Initialise the OS before creating our threads */
+ status = atomOSInit(&idle_thread_stack[0], IDLE_STACK_SIZE_BYTES, TRUE);
+ if (status == ATOM_OK)
+ {
+ /* Enable the system tick timer */
+ archInitSystemTickTimer();
+
+ /* Create an application thread */
+ status = atomThreadCreate(&main_tcb,
+ TEST_THREAD_PRIO, main_thread_func, 0,
+ &main_thread_stack[0],
+ MAIN_STACK_SIZE_BYTES,
+ TRUE);
+ if (status == ATOM_OK)
+ {
+ /**
+ * First application thread successfully created. It is
+ * now possible to start the OS. Execution will not return
+ * from atomOSStart(), which will restore the context of
+ * our application thread and start executing it.
+ *
+ * Note that interrupts are still disabled at this point.
+ * They will be enabled as we restore and execute our first
+ * thread in archFirstThreadRestore().
+ */
+ atomOSStart();
+ }
+ }
+
+ /* There was an error starting the OS if we reach here */
+ while (1)
+ {
+ }
+
+}
+
+
+/**
+ * \b userIdleHook
+ *
+ * This function will be called in a endless loop by entry point of idle thread.
+ *
+ * It must not call any library routines which would cause it to block.
+ *
+ *@return None
+ */
+void userIdleHook(void)
+{
+
+}
+
+/**
+ * \b main_thread_func
+ *
+ * Entry point for main application thread.
+ *
+ * This is the first thread that will be executed when the OS is started.
+ *
+ * @param[in] param Unused (optional thread entry parameter)
+ *
+ * @return None
+ */
+static void main_thread_func (uint32_t param)
+{
+ uint32_t test_status;
+ int sleep_ticks;
+
+ /* Compiler warnings */
+ param = param;
+
+ /* Initialise UART (115200bps) */
+ if (uart_init(115200) != 0)
+ {
+ /* Error initialising UART */
+ }
+
+ /* Put a message out on the UART */
+ printf("Go\n");
+
+ /* Start test. All tests use the same start API. */
+ test_status = test_start();
+
+ /* Check main thread stack usage (if enabled) */
+#ifdef ATOM_STACK_CHECKING
+ if (test_status == 0)
+ {
+ uint32_t used_bytes, free_bytes;
+
+ /* Check idle thread stack usage */
+ if (atomThreadStackCheck (&main_tcb, &used_bytes, &free_bytes) == ATOM_OK)
+ {
+ /* Check the thread did not use up to the end of stack */
+ if (free_bytes == 0)
+ {
+ printf ("Main stack overflow\n");
+ test_status++;
+ }
+
+ /* Log the stack usage */
+#ifdef TESTS_LOG_STACK_USAGE
+ printf ("MainUse:%d\n", (int)used_bytes);
+#endif
+ }
+
+ }
+#endif
+
+ /* Log final status */
+ if (test_status == 0)
+ {
+ printf ("Pass\n");
+ }
+ else
+ {
+ printf ("Fail(%d)\n", (int)test_status);
+ }
+
+ /* Flash LED once per second if passed, very quickly if failed */
+ sleep_ticks = (test_status == 0) ? SYSTEM_TICKS_PER_SEC : (SYSTEM_TICKS_PER_SEC/8);
+
+
+ /* Configure GPIO for flashing the STM8S Discovery LED on GPIO C4 */
+ GPIO_DeInit(GPIOC);
+ GPIO_Init(GPIOC, GPIO_Pin_4, GPIO_Mode_Out_PP_Low_Fast);
+
+ /* Test finished, flash slowly for pass, fast for fail */
+ while (1)
+ {
+
+ /* Toggle LED on pin D0 (Discovery-specific) */
+ GPIO_ToggleBits(GPIOC, GPIO_Pin_4);
+
+ /* Sleep then toggle LED again */
+ atomTimerDelay(sleep_ticks);
+ }
+}
+
diff --git a/ports/stm8l/uart.c b/ports/stm8l/uart.c
new file mode 100644
index 00000000..312629b8
--- /dev/null
+++ b/ports/stm8l/uart.c
@@ -0,0 +1,73 @@
+#include
+#include
+
+#include "stm8l15x.h"
+
+#include "atom.h"
+#include "uart.h"
+
+/*
+ * Initialize the UART to requested baudrate, tx/rx, 8N1.
+ */
+int uart_init(uint32_t baudrate)
+{
+ /* Enable USART clock */
+ CLK_PeripheralClockConfig(CLK_Peripheral_USART1, ENABLE);
+
+ /* Configure USART Tx as alternate function push-pull (software pull up)*/
+ GPIO_ExternalPullUpConfig(GPIOC, GPIO_Pin_3, ENABLE);
+
+ /* Configure USART Rx as alternate function push-pull (software pull up)*/
+ GPIO_ExternalPullUpConfig(GPIOC, GPIO_Pin_2, ENABLE);
+
+ /* USART configuration */
+ USART_Init(USART1, baudrate, USART_WordLength_8b, USART_StopBits_1,
+ USART_Parity_No, (USART_Mode_TypeDef)(USART_Mode_Tx | USART_Mode_Rx));
+ USART_ClearFlag(USART1, USART_FLAG_TC);
+
+ /* Finished */
+ return ATOM_OK;
+}
+
+
+/**
+ * \b uart_putchar
+ *
+ * Write a char out via UART2
+ *
+ * @param[in] c Character to send
+ *
+ * @return Character sent
+ */
+char uart_putchar (char c)
+{
+ /* Convert \n to \r\n */
+ if (c == '\n')
+ putchar('\r');
+
+ USART_ClearFlag(USART1,USART_FLAG_TC);
+ /* Write a character to the USART */
+ USART_SendData8(USART1, c);
+ /* Loop until the end of transmission */
+ while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
+
+ return (c);
+}
+
+
+/* COSMIC: Requires putchar() routine to override stdio */
+#if defined(__CSMC__)
+/**
+ * \b putchar
+ *
+ * Retarget putchar() to use UART2
+ *
+ * @param[in] c Character to send
+ *
+ * @return Character sent
+ */
+char putchar (char c)
+{
+ return (uart_putchar(c));
+}
+#endif /* __CSMC__ */
diff --git a/ports/stm8l/uart.h b/ports/stm8l/uart.h
new file mode 100644
index 00000000..b6ec185a
--- /dev/null
+++ b/ports/stm8l/uart.h
@@ -0,0 +1,9 @@
+
+#include "atom.h"
+
+
+/*
+ * Perform UART startup initialization.
+ */
+int uart_init(uint32_t baudrate);
+
diff --git a/tests/signal1.c b/tests/signal1.c
new file mode 100644
index 00000000..4dd13a7e
--- /dev/null
+++ b/tests/signal1.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2018, Mike Yu. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. No personal names or organizations' names associated with the
+ * Atomthreads project may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "atomsignal.h"
+#include "atomtests.h"
+
+/* Number of test threads */
+#define NUM_TEST_THREADS 1
+
+/* Test OS objects */
+static ATOM_TCB tcb[NUM_TEST_THREADS];
+static test_thread_stack[NUM_TEST_THREADS][TEST_THREAD_STACK_SIZE];
+
+/* Test result tracking */
+static volatile int g_result;
+
+/* Forward declarations */
+static void test_thread_func (uint32_t param);
+
+/**
+ * \b test_start
+ *
+ * Start signal test.
+ *
+ * @retval Number of failures
+ */
+uint32_t test_start (void)
+{
+ int failures;
+
+
+ /* Default to zero failures */
+ failures = 0;
+
+ if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO - 1, test_thread_func, 0,
+ &test_thread_stack[0][0],
+ TEST_THREAD_STACK_SIZE, TRUE) != ATOM_OK)
+ {
+ /* Fail */
+ ATOMLOG (_STR("Error creating test thread 1\n"));
+ failures++;
+ }
+ else
+ {
+ atomTimerDelay(20);
+ if (g_result == 0)
+ {
+ failures++;
+ }
+ }
+
+ /* Check thread stack usage (if enabled) */
+#ifdef ATOM_STACK_CHECKING
+ {
+ uint32_t used_bytes, free_bytes;
+ int thread;
+
+ /* Check all threads */
+ for (thread = 0; thread < NUM_TEST_THREADS; thread++)
+ {
+ /* Check thread stack usage */
+ if (atomThreadStackCheck (&tcb[thread], &used_bytes, &free_bytes) != ATOM_OK)
+ {
+ ATOMLOG (_STR("StackCheck\n"));
+ failures++;
+ }
+ else
+ {
+ /* Check the thread did not use up to the end of stack */
+ if (free_bytes == 0)
+ {
+ ATOMLOG (_STR("StackOverflow %d\n"), thread);
+ failures++;
+ }
+
+ /* Log the stack usage */
+#ifdef TESTS_LOG_STACK_USAGE
+ ATOMLOG (_STR("StackUse:%d\n"), (int)used_bytes);
+#endif
+ }
+ }
+ }
+#endif
+
+ /* Quit */
+ return failures;
+}
+
+/**
+ * \b test_thread_func
+ *
+ * Entry point for test thread.
+ *
+ * @param[in] param Unused (optional thread entry parameter)
+ *
+ * @return None
+ */
+static void test_thread_func (uint32_t param)
+{
+ ATOM_SIGNAL signal;
+ int failures;
+
+ /* Compiler warnings */
+ param = param;
+
+ /* Default to zero failures */
+ failures = 0;
+
+ signal = atomSignalWait(0x01, -1);
+ if (signal.status != ATOM_TIMEOUT)
+ {
+ failures++;
+ }
+ else
+ {
+ g_result = 1;
+ }
+
+ /* Wait forever */
+ while (1)
+ {
+ atomTimerDelay (SYSTEM_TICKS_PER_SEC);
+ }
+}
+
+
diff --git a/tests/signal2.c b/tests/signal2.c
new file mode 100644
index 00000000..b7a582f3
--- /dev/null
+++ b/tests/signal2.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2018, Mike Yu. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. No personal names or organizations' names associated with the
+ * Atomthreads project may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "atomsignal.h"
+#include "atomtests.h"
+
+/* Number of test threads */
+#define NUM_TEST_THREADS 1
+
+/* Test OS objects */
+static ATOM_TCB tcb[NUM_TEST_THREADS];
+static test_thread_stack[NUM_TEST_THREADS][TEST_THREAD_STACK_SIZE];
+
+
+/* Test result tracking */
+static volatile int g_result;
+
+/* Forward declarations */
+static void test_thread_func (uint32_t param);
+
+/**
+ * \b test_start
+ *
+ * Start signal test.
+ *
+ * @retval Number of failures
+ */
+uint32_t test_start (void)
+{
+ int failures;
+
+
+ /* Default to zero failures */
+ failures = 0;
+
+ if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO - 1, test_thread_func, 0,
+ &test_thread_stack[0][0],
+ TEST_THREAD_STACK_SIZE, TRUE) != ATOM_OK)
+ {
+ /* Fail */
+ ATOMLOG (_STR("Error creating test thread 1\n"));
+ failures++;
+ }
+ else
+ {
+ atomTimerDelay(20);
+ atomSignalSet(&tcb[0], 0x01);
+ if (g_result == 0)
+ {
+ failures++;
+ }
+ }
+
+ /* Check thread stack usage (if enabled) */
+#ifdef ATOM_STACK_CHECKING
+ {
+ uint32_t used_bytes, free_bytes;
+ int thread;
+
+ /* Check all threads */
+ for (thread = 0; thread < NUM_TEST_THREADS; thread++)
+ {
+ /* Check thread stack usage */
+ if (atomThreadStackCheck (&tcb[thread], &used_bytes, &free_bytes) != ATOM_OK)
+ {
+ ATOMLOG (_STR("StackCheck\n"));
+ failures++;
+ }
+ else
+ {
+ /* Check the thread did not use up to the end of stack */
+ if (free_bytes == 0)
+ {
+ ATOMLOG (_STR("StackOverflow %d\n"), thread);
+ failures++;
+ }
+
+ /* Log the stack usage */
+#ifdef TESTS_LOG_STACK_USAGE
+ ATOMLOG (_STR("StackUse:%d\n"), (int)used_bytes);
+#endif
+ }
+ }
+ }
+#endif
+
+ /* Quit */
+ return failures;
+}
+
+/**
+ * \b test_thread_func
+ *
+ * Entry point for test thread.
+ *
+ * @param[in] param Unused (optional thread entry parameter)
+ *
+ * @return None
+ */
+static void test_thread_func (uint32_t param)
+{
+ ATOM_SIGNAL signal;
+ int failures;
+
+ /* Compiler warnings */
+ param = param;
+
+ /* Default to zero failures */
+ failures = 0;
+
+ signal = atomSignalWait(0x01, 0);
+ if (signal.status != ATOM_OK)
+ {
+ failures++;
+ }
+ else
+ {
+ if (signal.value == 0x01)
+ {
+ g_result = 1;
+ }
+ }
+ /* Wait forever */
+ while (1)
+ {
+ atomTimerDelay (SYSTEM_TICKS_PER_SEC);
+ }
+}
+
+
+
diff --git a/tests/signal3.c b/tests/signal3.c
new file mode 100644
index 00000000..25af21bf
--- /dev/null
+++ b/tests/signal3.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2018, Mike Yu. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. No personal names or organizations' names associated with the
+ * Atomthreads project may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "atomsignal.h"
+#include "atomtests.h"
+
+/* Number of test threads */
+#define NUM_TEST_THREADS 1
+
+/* Test OS objects */
+static ATOM_TCB tcb[NUM_TEST_THREADS];
+static test_thread_stack[NUM_TEST_THREADS][TEST_THREAD_STACK_SIZE];
+
+/* Test result tracking */
+static volatile int g_result;
+
+/* Forward declarations */
+static void test_thread_func (uint32_t param);
+
+/**
+ * \b test_start
+ *
+ * Start signal test.
+ *
+ * @retval Number of failures
+ */
+uint32_t test_start (void)
+{
+ int failures;
+
+
+ /* Default to zero failures */
+ failures = 0;
+
+ if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO - 1, test_thread_func, 0,
+ &test_thread_stack[0][0],
+ TEST_THREAD_STACK_SIZE, TRUE) != ATOM_OK)
+ {
+ /* Fail */
+ ATOMLOG (_STR("Error creating test thread 1\n"));
+ failures++;
+ }
+ else
+ {
+ atomTimerDelay(20);
+ if (g_result == 0)
+ {
+ failures++;
+ }
+ }
+
+ /* Check thread stack usage (if enabled) */
+#ifdef ATOM_STACK_CHECKING
+ {
+ uint32_t used_bytes, free_bytes;
+ int thread;
+
+ /* Check all threads */
+ for (thread = 0; thread < NUM_TEST_THREADS; thread++)
+ {
+ /* Check thread stack usage */
+ if (atomThreadStackCheck (&tcb[thread], &used_bytes, &free_bytes) != ATOM_OK)
+ {
+ ATOMLOG (_STR("StackCheck\n"));
+ failures++;
+ }
+ else
+ {
+ /* Check the thread did not use up to the end of stack */
+ if (free_bytes == 0)
+ {
+ ATOMLOG (_STR("StackOverflow %d\n"), thread);
+ failures++;
+ }
+
+ /* Log the stack usage */
+#ifdef TESTS_LOG_STACK_USAGE
+ ATOMLOG (_STR("StackUse:%d\n"), (int)used_bytes);
+#endif
+ }
+ }
+ }
+#endif
+
+ /* Quit */
+ return failures;
+}
+
+/**
+ * \b test_thread_func
+ *
+ * Entry point for test thread.
+ *
+ * @param[in] param Unused (optional thread entry parameter)
+ *
+ * @return None
+ */
+static void test_thread_func (uint32_t param)
+{
+ ATOM_SIGNAL signal;
+ int failures;
+
+ /* Compiler warnings */
+ param = param;
+
+ /* Default to zero failures */
+ failures = 0;
+
+ signal = atomSignalWait(0, 20);
+ if (signal.status != ATOM_TIMEOUT)
+ {
+ failures++;
+ }
+ else
+ {
+ g_result = 1;
+ }
+
+ /* Wait forever */
+ while (1)
+ {
+ atomTimerDelay (SYSTEM_TICKS_PER_SEC);
+ }
+}
+
+
+
+
diff --git a/tests/signal4.c b/tests/signal4.c
new file mode 100644
index 00000000..e8df2550
--- /dev/null
+++ b/tests/signal4.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2018, Mike Yu. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. No personal names or organizations' names associated with the
+ * Atomthreads project may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "atomsignal.h"
+#include "atomtests.h"
+
+/* Number of test threads */
+#define NUM_TEST_THREADS 2
+
+/* Test OS objects */
+static ATOM_TCB tcb[NUM_TEST_THREADS];
+static test_thread_stack[NUM_TEST_THREADS][TEST_THREAD_STACK_SIZE];
+
+/* Test result tracking */
+static volatile int g_result;
+
+/* Forward declarations */
+static void test1_thread_func (uint32_t param);
+static void test2_thread_func (uint32_t param);
+
+/**
+ * \b test_start
+ *
+ * Start signal test.
+ *
+ * @retval Number of failures
+ */
+uint32_t test_start (void)
+{
+ int failures;
+
+
+ /* Default to zero failures */
+ failures = 0;
+
+ if (atomThreadCreate(&tcb[0], TEST_THREAD_PRIO - 1, test1_thread_func, 0,
+ &test_thread_stack[0][0],
+ TEST_THREAD_STACK_SIZE, TRUE) != ATOM_OK)
+ {
+ /* Fail */
+ ATOMLOG (_STR("Error creating test thread 1\n"));
+ failures++;
+ }
+ else
+ {
+ if (atomThreadCreate(&tcb[1], TEST_THREAD_PRIO - 1, test2_thread_func, 0,
+ &test_thread_stack[1][0],
+ TEST_THREAD_STACK_SIZE, TRUE) != ATOM_OK)
+ {
+ /* Fail */
+ ATOMLOG (_STR("Error creating test thread 2\n"));
+ failures++;
+ }
+ else
+ {
+ atomTimerDelay(20);
+ atomSignalSet(&tcb[0], 0x02);
+ if (g_result == 0)
+ {
+ failures++;
+ }
+ }
+ }
+
+ /* Check thread stack usage (if enabled) */
+#ifdef ATOM_STACK_CHECKING
+ {
+ uint32_t used_bytes, free_bytes;
+ int thread;
+
+ /* Check all threads */
+ for (thread = 0; thread < NUM_TEST_THREADS; thread++)
+ {
+ /* Check thread stack usage */
+ if (atomThreadStackCheck (&tcb[thread], &used_bytes, &free_bytes) != ATOM_OK)
+ {
+ ATOMLOG (_STR("StackCheck\n"));
+ failures++;
+ }
+ else
+ {
+ /* Check the thread did not use up to the end of stack */
+ if (free_bytes == 0)
+ {
+ ATOMLOG (_STR("StackOverflow %d\n"), thread);
+ failures++;
+ }
+
+ /* Log the stack usage */
+#ifdef TESTS_LOG_STACK_USAGE
+ ATOMLOG (_STR("StackUse:%d\n"), (int)used_bytes);
+#endif
+ }
+ }
+ }
+#endif
+
+ /* Quit */
+ return failures;
+}
+
+
+/**
+ * \b test1_thread_func
+ *
+ * Entry point for test thread 1.
+ *
+ * @param[in] param Unused (optional thread entry parameter)
+ *
+ * @return None
+ */
+static void test1_thread_func (uint32_t param)
+{
+ ATOM_SIGNAL signal;
+ uint8_t step;
+
+ /* Compiler warnings */
+ param = param;
+
+ step = 0;
+
+ while(1)
+ {
+ signal = atomSignalWait(0, 0);
+ if (signal.status == ATOM_OK)
+ {
+ if (signal.value == 0x01)
+ {
+ step = 1;
+ }
+ else if (signal.value == 0x02)
+ {
+ if (step == 1)
+ {
+ g_result = 1;
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * \b test2_thread_func
+ *
+ * Entry point for test thread 2.
+ *
+ * @param[in] param Unused (optional thread entry parameter)
+ *
+ * @return None
+ */
+static void test2_thread_func (uint32_t param)
+{
+ /* Compiler warnings */
+ param = param;
+
+ atomSignalSet (&tcb[0], 0x01);
+
+ /* Wait forever */
+ while (1)
+ {
+ atomTimerDelay (SYSTEM_TICKS_PER_SEC);
+ }
+}
+