]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_A5_SAMA5D2x_Xplained_IAR/AtmelFiles/drivers/cortex-a/cp15_pmu.c
Add SAMA5D2 Xplained IAR demo.
[freertos] / FreeRTOS / Demo / CORTEX_A5_SAMA5D2x_Xplained_IAR / AtmelFiles / drivers / cortex-a / cp15_pmu.c
diff --git a/FreeRTOS/Demo/CORTEX_A5_SAMA5D2x_Xplained_IAR/AtmelFiles/drivers/cortex-a/cp15_pmu.c b/FreeRTOS/Demo/CORTEX_A5_SAMA5D2x_Xplained_IAR/AtmelFiles/drivers/cortex-a/cp15_pmu.c
new file mode 100644 (file)
index 0000000..d48023e
--- /dev/null
@@ -0,0 +1,252 @@
+/* ----------------------------------------------------------------------------\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
+/** \file */\r
+\r
+/*----------------------------------------------------------------------------\r
+ *        Headers\r
+ *----------------------------------------------------------------------------*/\r
+\r
+#include "chip.h"\r
+\r
+#if defined(__ICCARM__)\r
+#include <intrinsics.h>\r
+#endif\r
+\r
+#include "cortex-a/cp15_pmu.h"\r
+\r
+#include <assert.h>\r
+\r
+/*----------------------------------------------------------------------------\r
+ *        Global functions\r
+ *----------------------------------------------------------------------------*/\r
+\r
+/**\r
+ * \brief Resets the counter and enables/disables all counters including PMCCNTR.\r
+ * \param ResetCounterType  CounterType: Performance or Cycle counter\r
+ */\r
+static void cp15_pmu_control(uint8_t ResetCounterType, uint8_t EnableCounter)\r
+{\r
+       uint32_t PMU_Value = 0;\r
+\r
+       asm("mrc     p15, 0, %0, c9, c12, 0":"=r"(PMU_Value));\r
+       PMU_Value |= ((ResetCounterType << 1) | EnableCounter);\r
+       asm("mcr     p15, 0, %0, c9, c12, 0": :"r"(PMU_Value));\r
+}\r
+\r
+/**\r
+ * \brief Select Cycle Count divider\r
+ * \param Divider  0 for increment of counter at every single cycle or 1 for at every 64th cycle\r
+ */\r
+static void cp15_cycle_count_divider(uint8_t Divider)\r
+{\r
+       uint32_t PMU_Value = 0;\r
+       assert((Divider > 1 ? 0 : 1));\r
+       asm("mrc     p15, 0, %0, c9, c12, 0":"=r"(PMU_Value));\r
+       PMU_Value |= (Divider << 3);\r
+       asm("mcr     p15, 0, %0, c9, c12, 0": :"r"(PMU_Value));\r
+}\r
+\r
+/**\r
+ * \brief Enables PMCCNTR.\r
+ */\r
+static void cp15_enable_PMCNT(void)\r
+{\r
+       uint32_t CNT_Value = 0;\r
+       asm("mrc     p15, 0, %0, c9, c12, 1":"=r"(CNT_Value));\r
+       CNT_Value |= (uint32_t) ((1 << CP15_PMCNTENSET));\r
+       asm("mcr     p15, 0, %0, c9, c12, 1": :"r"(CNT_Value));\r
+}\r
+\r
+/**\r
+ * \brief Enables PMCCNTR.\r
+ */\r
+static void cp15_enable_counter(uint8_t Counter)\r
+{\r
+       uint32_t CNT_Value = 0;\r
+       asm("mrc     p15, 0, %0, c9, c12, 1":"=r"(CNT_Value));\r
+       CNT_Value |= Counter;\r
+       asm("mcr     p15, 0, %0, c9, c12, 1": :"r"(CNT_Value));\r
+}\r
+\r
+/**\r
+ * \brief Disables/clear PMCCNTR.\r
+ * \param Counter  0 or 1 to selct counter\r
+ */\r
+\r
+static void cp15_clear_PMCNT(void)\r
+{\r
+       uint32_t CNT_Value = 0;\r
+       asm("mrc     p15, 0, %0, c9, c12, 2":"=r"(CNT_Value));\r
+       CNT_Value |= (uint32_t) (1 << CP15_PMCNTENCLEAR);\r
+       asm("mcr     p15, 0, %0, c9, c12, 2": :"r"(CNT_Value));\r
+}\r
+\r
+/**\r
+ * \brief Disables/Enables overflow flag.\r
+ * \param Enable  Enables or disables the flag option\r
+ * \param ClearCounterFlag  selects the counter flag to clear\r
+ */\r
+void cp15_overflow_status(uint8_t Enable, uint8_t ClearCounterFlag)\r
+{\r
+       uint32_t OFW_Value = 0;\r
+       asm("mrc     p15, 0, %0, c9, c12, 3":"=r"(OFW_Value));\r
+       OFW_Value |= ((Enable << 31) | ClearCounterFlag);\r
+       asm("mcr     p15, 0, %0, c9, c12, 3": :"r"(OFW_Value));\r
+}\r
+\r
+/**\r
+ * \brief Disables/Enables overflow flag.\r
+ * \param EventCounter  Counter of the events\r
+ */\r
+uint32_t cp15_read_overflow_status(uint8_t EventCounter)\r
+{\r
+       uint32_t OFW_Value = 0;\r
+       asm("mrc     p15, 0, %0, c9, c12, 3":"=r"(OFW_Value));\r
+       OFW_Value = ((OFW_Value & EventCounter) >> (EventCounter - 1));\r
+       return OFW_Value;\r
+}\r
+\r
+/**\r
+ * \brief Increments the count of a performance monitor count register.\r
+ * \param IncrCounter  0 or 1  counters\r
+ */\r
+void cp15_soft_incr(uint8_t IncrCounter)\r
+{\r
+       uint32_t INRC_Value = 0;\r
+       asm("mrc     p15, 0, %0, c9, c12, 4":"=r"(INRC_Value));\r
+       INRC_Value |= IncrCounter;\r
+       asm("mcr     p15, 0, %0, c9, c12, 4": :"r"(INRC_Value));\r
+}\r
+\r
+/**\r
+ * \brief Increments the count of a performance monitor count register.\r
+ * \param EventType  Select Event Type\r
+ * \param Counter  0 or 1  counters\r
+ */\r
+static void cp15_select_event(PerfEventType EventType, uint8_t Counter)\r
+{\r
+       uint32_t CounterSelect = 0;\r
+       assert((Counter == 1) || (Counter == 2));\r
+       CounterSelect = (Counter & 0x1F);\r
+       asm("mcr     p15, 0, %0, c9, c12, 5": :"r"(CounterSelect));\r
+       CounterSelect = (EventType & 0xFF);\r
+       asm("mcr     p15, 0, %0, c9, c13, 1": :"r"(CounterSelect));\r
+       // PMXEVTYPER\r
+       asm("mrc     p15, 0, %0, c9, c13, 1":"=r"(CounterSelect));\r
+       // PMXEVTYPER\r
+}\r
+\r
+/**\r
+ * \brief Enables USER mode\r
+ */\r
+void cp15_enable_user_mode(void)\r
+{\r
+       uint8_t Value = 1;\r
+       asm("mcr     p15, 0, %0, c9, c14, 0": :"r"(Value));\r
+}\r
+\r
+/**\r
+ * \brief Enables Oveflows interrupt\r
+ * \param Enable  Enables the Interrupt\r
+ * \param Counter  0 or 1  counters\r
+ */\r
+void cp15_enable_interrupt(uint8_t Enable, uint8_t Counter)\r
+{\r
+       uint32_t ITE_Value = 0;\r
+       ITE_Value |= ((Enable << 31) | Counter);\r
+       asm("mcr     p15, 0, %0, c9, c14, 1": :"r"(ITE_Value));\r
+}\r
+\r
+/**\r
+ * \brief Disables Oveflows interrupt\r
+ * \param Disable  Disables the Interrupt\r
+ * \param Counter  0 or 1  counters\r
+ */\r
+void cp15_disable_interrupt(uint8_t Disable, uint8_t Counter)\r
+{\r
+       uint32_t ITE_Value = 0;\r
+       ITE_Value |= ((Disable << 31) | Counter);\r
+       asm("mcr     p15, 0, %0, c9, c14, 2": :"r"(ITE_Value));\r
+}\r
+\r
+/**\r
+ * \brief Initialize Cycle counter with Divider 64\r
+ */\r
+uint32_t cp15_init_cycle_counter(void)\r
+{\r
+       uint32_t value;\r
+       cp15_clear_PMCNT();\r
+       cp15_enable_PMCNT();\r
+       cp15_overflow_status(true, CP15_BothCounter);\r
+       cp15_cycle_count_divider(CP15_CountDivider64);\r
+       cp15_pmu_control(CP15_ResetCycCounter, true);\r
+\r
+       asm("mrc     p15, 0, %0, c9, c13, 0":"=r"(value));\r
+       return value;\r
+\r
+}\r
+\r
+/**\r
+ * \brief Initialize Performance monitor counter with Divider 64\r
+ * \param Event  Event type\r
+ * \param Counter  0 or 1  counters\r
+ */\r
+\r
+void cp15_init_perf_counter(PerfEventType Event, uint8_t Counter)\r
+{\r
+       cp15_pmu_control(CP15_ResetPerCounter, true);\r
+       cp15_select_event(Event, Counter);\r
+       cp15_overflow_status(false, CP15_BothCounter);\r
+       cp15_enable_counter(Counter);\r
+}\r
+\r
+/**\r
+ * \brief gives total number of event count\r
+ * \param Counter  0 or 1  counters\r
+ */\r
+uint32_t cp15_count_evt(uint8_t Counter)\r
+{\r
+       uint32_t value;\r
+       asm("mcr     p15, 0, %0, c9, c12, 5": :"r"(Counter));\r
+       asm("mrc     p15, 0, %0, c9, c13, 2":"=r"(value));\r
+       // PMXEVTYPER\r
+       return (value);\r
+}\r
+\r
+/**\r
+ * \brief gives total number of cycle count\r
+\r
+ */\r
+uint32_t cp15_get_cycle_counter(void)\r
+{\r
+       uint32_t value;\r
+       asm("mrc     p15, 0, %0, c9, c13, 0":"=r"(value));\r
+       return value;\r
+}\r