]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_A5_SAMA5D2x_Xplained_IAR/AtmelFiles/drivers/peripherals/tc.c
Add SAMA5D2 Xplained IAR demo.
[freertos] / FreeRTOS / Demo / CORTEX_A5_SAMA5D2x_Xplained_IAR / AtmelFiles / drivers / peripherals / tc.c
diff --git a/FreeRTOS/Demo/CORTEX_A5_SAMA5D2x_Xplained_IAR/AtmelFiles/drivers/peripherals/tc.c b/FreeRTOS/Demo/CORTEX_A5_SAMA5D2x_Xplained_IAR/AtmelFiles/drivers/peripherals/tc.c
new file mode 100644 (file)
index 0000000..b1907f0
--- /dev/null
@@ -0,0 +1,228 @@
+/* ----------------------------------------------------------------------------\r
+ *         SAM Software Package License\r
+ * ----------------------------------------------------------------------------\r
+ * Copyright (c) 2015, Atmel Corporation\r
+ *\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the disclaimer below.\r
+ *\r
+ * Atmel's name may not be used to endorse or promote products derived from\r
+ * this software without specific prior written permission.\r
+ *\r
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ * ----------------------------------------------------------------------------\r
+ */\r
+\r
+/** \addtogroup tc_module\r
+ * \section Purpose\r
+ * The TC driver provides the Interface to configure the Timer Counter (TC).\r
+ *\r
+ * \section Usage\r
+ * <ul>\r
+ *  <li> Optionally, use tc_find_mck_divisor() to let the program find the best\r
+ *     TCCLKS field value automatically.</li>\r
+ *  <li> Configure a Timer Counter in the desired mode using tc_configure().</li>\r
+ *  <li> Start or stop the timer clock using tc_start() and tc_stop().</li>\r
+ *  </li>\r
+ * </ul>\r
+ * For more accurate information, please look at the TC section of the Datasheet.\r
+ *\r
+ * Related files :\n\r
+ * \ref tc.c\n\r
+ * \ref tc.h.\n\r
+*/\r
+\r
+/**\r
+*  \file\r
+*\r
+*  \section Purpose\r
+*\r
+*  Interface for configuring and using Timer Counter (TC) peripherals.\r
+*\r
+*  \section Usage\r
+*  -# Optionally, use tc_find_mck_divisor() to let the program find the best\r
+*     TCCLKS field value automatically.\r
+*  -# Configure a Timer Counter in the desired mode using tc_configure().\r
+*  -# Start or stop the timer clock using tc_start() and tc_stop().\r
+*/\r
+\r
+/**\r
+ * \file\r
+ *\r
+ * Implementation of Timer Counter (TC).\r
+ *\r
+ */\r
+\r
+/*------------------------------------------------------------------------------\r
+ *         Headers\r
+ *------------------------------------------------------------------------------*/\r
+\r
+#include "chip.h"\r
+#include "peripherals/tc.h"\r
+#include "peripherals/pmc.h"\r
+\r
+#include <assert.h>\r
+\r
+/*------------------------------------------------------------------------------\r
+ *         Global functions\r
+ *------------------------------------------------------------------------------*/\r
+\r
+/**\r
+ * \brief Configures a Timer Counter Channel\r
+ *\r
+ * Configures a Timer Counter to operate in the given mode. Timer is stopped\r
+ * after configuration and must be restarted with tc_start(). All the\r
+ * interrupts of the timer are also disabled.\r
+ *\r
+ * \param pTc  Pointer to a Tc instance.\r
+ * \param channel Channel number.\r
+ * \param mode  Operating mode (TC_CMR value).\r
+ */\r
+void tc_configure(Tc * pTc, uint32_t channel, uint32_t mode)\r
+{\r
+       volatile TcChannel *pTcCh;\r
+\r
+       assert(channel <\r
+              (sizeof (pTc->TC_CHANNEL) / sizeof (pTc->TC_CHANNEL[0])));\r
+       pTcCh = pTc->TC_CHANNEL + channel;\r
+\r
+       /*  Disable TC clock */\r
+       pTcCh->TC_CCR = TC_CCR_CLKDIS;\r
+\r
+       /*  Disable interrupts */\r
+       pTcCh->TC_IDR = 0xFFFFFFFF;\r
+\r
+       /*  Clear status register */\r
+       pTcCh->TC_SR;\r
+\r
+       /*  Set mode */\r
+       pTcCh->TC_CMR = mode;\r
+}\r
+\r
+/**\r
+ * \brief Reset and Start the TC Channel\r
+ *\r
+ * Enables the timer clock and performs a software reset to start the counting.\r
+ *\r
+ * \param pTc  Pointer to a Tc instance.\r
+ * \param channel Channel number.\r
+ */\r
+void tc_start(Tc * pTc, uint32_t channel)\r
+{\r
+       volatile TcChannel *pTcCh;\r
+\r
+       assert(channel <\r
+              (sizeof (pTc->TC_CHANNEL) / sizeof (pTc->TC_CHANNEL[0])));\r
+\r
+       pTcCh = pTc->TC_CHANNEL + channel;\r
+       pTcCh->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;\r
+       pTcCh->TC_IER = TC_IER_COVFS;\r
+}\r
+\r
+/**\r
+ * \brief Stop TC Channel\r
+ *\r
+ * Disables the timer clock, stopping the counting.\r
+ *\r
+ * \param pTc     Pointer to a Tc instance.\r
+ * \param channel Channel number.\r
+ */\r
+void tc_stop(Tc * pTc, uint32_t channel)\r
+{\r
+       volatile TcChannel *pTcCh;\r
+\r
+       assert(channel <\r
+              (sizeof (pTc->TC_CHANNEL) / sizeof (pTc->TC_CHANNEL[0])));\r
+\r
+       pTcCh = pTc->TC_CHANNEL + channel;\r
+       pTcCh->TC_CCR = TC_CCR_CLKDIS;\r
+       pTcCh->TC_IDR = TC_IER_COVFS;\r
+}\r
+\r
+/**\r
+ * \brief Enables TC channel interrupts\r
+ *\r
+ * \param tc Pointer to Tc instance\r
+ * \param channel Channel number\r
+ * \param mask mask of interrupts to enable\r
+ */\r
+void tc_enable_it(Tc* tc, uint32_t channel, uint32_t mask)\r
+{\r
+       assert(channel < (sizeof (tc->TC_CHANNEL) / sizeof (tc->TC_CHANNEL[0])));\r
+       tc->TC_CHANNEL[channel].TC_IER = mask;\r
+}\r
+\r
+/**\r
+ * \brief Find best MCK divisor\r
+ *\r
+ * Finds the best MCK divisor given the timer frequency and MCK. The result\r
+ * is guaranteed to satisfy the following equation:\r
+ * \code\r
+ *   (MCK / (DIV * 65536)) <= freq <= (MCK / DIV)\r
+ * \endcode\r
+ * with DIV being the highest possible value.\r
+ *\r
+ * \param freq  Desired timer freq.\r
+ * \param div  Divisor value.\r
+ * \param tc_clks  TCCLKS field value for divisor.\r
+ *\r
+ * \return 1 if a proper divisor has been found, otherwise 0.\r
+ */\r
+uint32_t tc_find_mck_divisor (uint32_t freq, uint32_t * div,\r
+                                 uint32_t * tc_clks)\r
+{\r
+       const uint32_t periph_clock = pmc_get_peripheral_clock(ID_TC0);\r
+       const uint32_t available_freqs[5] = {periph_clock >> 1, periph_clock >> 3, periph_clock >> 5, periph_clock >> 7, 32768};\r
+\r
+       int i = 0;\r
+       for (i = 0; i < 5; ++i)\r
+       {\r
+               uint32_t tmp = freq << 1;\r
+               if (tmp > available_freqs[i])\r
+                       break;\r
+       }\r
+\r
+       i = (i == 5 ? i-1 : i);\r
+\r
+       /*  Store results */\r
+       if (div) {\r
+               *div = periph_clock / available_freqs[i];\r
+       }\r
+       if (tc_clks) {\r
+               *tc_clks = i;\r
+       }\r
+\r
+       return 1;\r
+}\r
+\r
+uint32_t tc_get_status(Tc* tc, uint32_t channel_num)\r
+{\r
+       return tc->TC_CHANNEL[channel_num].TC_SR;\r
+}\r
+\r
+\r
+void tc_trigger_on_freq(Tc* tc, uint32_t channel_num, uint32_t freq)\r
+{\r
+       uint32_t div = 0;\r
+       uint32_t tcclks = 0;\r
+       uint32_t tc_id = get_tc_id_from_addr(tc);\r
+       TcChannel* channel = &tc->TC_CHANNEL[channel_num];\r
+\r
+       tc_find_mck_divisor(freq, &div, &tcclks);\r
+       tc_configure(tc, channel_num, tcclks | TC_CMR_CPCTRG);\r
+       channel->TC_RC = (pmc_get_peripheral_clock(tc_id) / div) / freq;\r
+}\r