]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_MPU_CEC_MEC_17xx_51xx_Keil_GCC/peripheral_library/interrupt/interrupt_api.c
Updated name of CORTEX_MPU_CEC_MEC_17xx_Keil_GCC to CORTEX_MPU_CEC_MEC_17xx_51xx_Keil...
[freertos] / FreeRTOS / Demo / CORTEX_MPU_CEC_MEC_17xx_51xx_Keil_GCC / peripheral_library / interrupt / interrupt_api.c
diff --git a/FreeRTOS/Demo/CORTEX_MPU_CEC_MEC_17xx_51xx_Keil_GCC/peripheral_library/interrupt/interrupt_api.c b/FreeRTOS/Demo/CORTEX_MPU_CEC_MEC_17xx_51xx_Keil_GCC/peripheral_library/interrupt/interrupt_api.c
new file mode 100644 (file)
index 0000000..aadadde
--- /dev/null
@@ -0,0 +1,449 @@
+/*****************************************************************************\r
+* © 2015 Microchip Technology Inc. and its subsidiaries.\r
+* You may use this software and any derivatives exclusively with\r
+* Microchip products.\r
+* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS".\r
+* NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,\r
+* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,\r
+* AND FITNESS FOR A PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP\r
+* PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.\r
+* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,\r
+* INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND\r
+* WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS\r
+* BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.\r
+* TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL\r
+* CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF\r
+* FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.\r
+* MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE\r
+* OF THESE TERMS.\r
+******************************************************************************\r
+\r
+Version Control Information (Perforce)\r
+******************************************************************************\r
+$Revision: #1 $ \r
+$DateTime: 2016/09/22 08:03:49 $ \r
+$Author: pramans $\r
+Last Change: Renamed ecia_init to interrupt_init\r
+******************************************************************************/\r
+/** @file interrupt_api.c\r
+* \brief Interrupt APIs Source File\r
+* \author jvasanth\r
+* \r
+* This file implements the Interrupt Source file  \r
+******************************************************************************/\r
+\r
+/** @defgroup Interrupt\r
+ *  @{\r
+ */\r
\r
+#include "common_lib.h"\r
+#include "interrupt.h"\r
+#include "..\pcr\pcr.h"\r
+\r
+static uint8_t interrupt_is_girq_direct(uint8_t girq_num);\r
+\r
+/* ------------------------------------------------------------------------------- */\r
+/*                  NVIC,ECIA Routing Policy for Direct Mode                       */\r
+/* ------------------------------------------------------------------------------- */\r
+/* In Direct Mode, some interrupts could be configured to be used as aggregated.\r
+ * Configuration:\r
+ *      1. Always set ECS Interrupt Direct enable bit.         \r
+ *      2. If GIRQn aggregated set Block Enable bit.\r
+ *      3. If GIRQn direct then clear Block Enable bit and enable individual NVIC inputs.\r
+ *  Switching issues:\r
+ *  Aggregate enable/disable requires set/clear single GIRQn bit in GIRQ Block En/Clr registers.\r
+ *  Also requires set/clear of individual NVIC Enables.\r
+ *  \r
+ * Note: interrupt_is_girq_direct() internal function uses this policy to detect \r
+ * if any interrupt is configured as direct or aggregated\r
+*/\r
+\r
+/** Initialize EC Interrupt Aggregator\r
+ * @param mode 1 - Direct Map mode, 0 - Fully Aggregated Mode \r
+ * @param girq_bitmask - BitMask of GIRQ to be configured as aggregated \r
+ *                     This parameter is only applicable in direct mode.\r
+ * @note All GPIO's and wake capable sources are always \r
+ * aggregated! GPIO's interrupts will still work in direct mode.\r
+ * Block wakes are not be routed to the processor in direct \r
+ * mode. \r
+ * Note2: This function disables and enables global interrupt \r
+ */\r
+void interrupt_init(uint8_t mode, uint32_t girq_bitmask)\r
+{\r
+    uint32_t isave;\r
+       \r
+    isave = __get_PRIMASK();\r
+    __disable_irq();\r
+               \r
+    //Clear Sleep for Interrupt block\r
+    pcr_sleep_enable(PCR_INT, 0);\r
+\r
+    interrupt_mode_set(mode);\r
+\r
+    p_interrupt_ecia_girqs_enable_reset();        \r
+    \r
+    p_interrupt_nvic_enpend_clr();\r
+       \r
+    p_interrupt_nvic_priorities_default_set();\r
+    \r
+    if (mode)\r
+    {//If direct mode, enable specific GIRQs to be aggregated\r
+        p_interrupt_ecia_block_enable_bitmask_set(girq_bitmask);\r
+    }\r
+       \r
+    if (!isave) {\r
+        __enable_irq();\r
+    }\r
+}\r
+\r
+/** Set interrupt routing mode to aggregated or direct. \r
+ * @param mode 1 = Direct (except GPIO & wake), 0 = All Aggregated \r
+ * @note In direct mode, one could enable certain GIRQs as aggregated using \r
+ * p_interrupt_ecia_block_enable_set function\r
+ */\r
+void interrupt_mode_set(uint8_t mode)\r
+{\r
+    if (mode) \r
+       {\r
+               p_interrupt_ecia_block_enable_all_clr();        \r
+    } \r
+       else \r
+       {\r
+               p_interrupt_ecia_block_enable_all_set();        \r
+    }\r
+               \r
+    p_interrupt_control_set(mode);\r
+}\r
+\r
+/** Clears all individual interrupts Enables and Source in ECIA,\r
+ *  and Clears all NVIC external enables and pending bits  \r
+ */\r
+void interrupt_reset(void)\r
+{      \r
+    p_interrupt_ecia_girqs_enable_reset();\r
+    p_interrupt_ecia_girqs_source_reset();     \r
+\r
+    p_interrupt_nvic_enpend_clr();\r
+}\r
+\r
+/** Enables interrupt for a device \r
+ * @param dev_iroute - source IROUTING information  \r
+ * @note This function disables and enables global interrupt \r
+ */\r
+void interrupt_device_enable(uint32_t dev_iroute)\r
+{\r
+    uint32_t isave;\r
+    IRQn_Type nvic_num;\r
+    uint8_t girq_num;\r
+    uint8_t ia_bitpos;\r
+    \r
+    girq_num = (uint8_t)(dev_iroute >> (ECIA_GIRQ_ID_BITPOS)) & 0x1Fu;\r
+    ia_bitpos = (uint8_t)(dev_iroute >> (ECIA_GIRQ_BIT_BITPOS)) & 0x1Fu;    \r
+    \r
+    if (interrupt_is_girq_direct(girq_num)) \r
+    { // GIRQ is hooked direct        \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_NVIC_ID_BITPOS)) & 0xFFul);\r
+    } \r
+    else \r
+    { // GIRQ is aggregated        \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_IA_NVIC_ID_BITPOS)) & 0xFFul);\r
+    }\r
+    \r
+    isave = __get_PRIMASK();\r
+    __disable_irq();\r
+\r
+    NVIC_EnableIRQ(nvic_num);\r
+    p_interrupt_ecia_girq_enable_set(girq_num, ia_bitpos);    \r
+    __DSB();                                           \r
+\r
+    if (!isave) {\r
+        __enable_irq();\r
+    }\r
+}\r
+\r
+\r
+/** Disables interrupt for a device\r
+ * @param dev_iroute - source IROUTING information  \r
+ * @note This function disables and enables global interrupt \r
+ */\r
+void interrupt_device_disable(uint32_t dev_iroute)\r
+{\r
+    uint32_t isave;\r
+    IRQn_Type nvic_num;\r
+    uint8_t girq_num;\r
+    uint8_t ia_bitpos;\r
+\r
+    girq_num = (uint8_t)(dev_iroute >> (ECIA_GIRQ_ID_BITPOS)) & 0x1Fu;\r
+    ia_bitpos = (uint8_t)(dev_iroute >> (ECIA_GIRQ_BIT_BITPOS)) & 0x1Fu;    \r
+    \r
+    isave = __get_PRIMASK();\r
+    __disable_irq();\r
+    \r
+    if (interrupt_is_girq_direct(girq_num)) \r
+    { // GIRQ is hooked direct        \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_NVIC_ID_BITPOS)) & 0xFFul);\r
+        NVIC_DisableIRQ(nvic_num);\r
+    }   \r
+        \r
+    p_interrupt_ecia_girq_enable_clr(girq_num, ia_bitpos);    \r
+    __DSB();                                           \r
+\r
+    if (!isave) {\r
+        __enable_irq();\r
+    }\r
+}\r
+\r
+/** ecia_is_girq_direct - Return true if GIRQn sources can be directly \r
+ * connected to the NVIC - based on ECS->INTERRUPT_CONTROL and GIRQ block enable\r
+ * @param girq_num - enum MEC_GIRQ_IDS\r
+ * @return 1 if GIRQn sources can be directly routed to the NVIC, else 0\r
+ */\r
+static uint8_t interrupt_is_girq_direct(uint8_t girq_num)\r
+{    \r
+    uint32_t bpos;\r
+    uint8_t retVal;\r
+    uint8_t girq_block_enabled;\r
+    \r
+    retVal = 0;\r
+    \r
+    bpos = (girq_num & 0x1Fu) + 8u;\r
+    \r
+    if ((ECIA_GIRQ_DIRECT_BITMAP) & (1ul << bpos)) \r
+    {        \r
+        if (p_interrupt_control_get())                \r
+        {// direct NVIC enabled\r
+           \r
+            girq_block_enabled = p_interrupt_ecia_block_enable_get(girq_num);\r
+            \r
+            if (!girq_block_enabled)\r
+            {\r
+                retVal = 1;\r
+            }\r
+        }\r
+    }\r
+    return retVal;\r
+}\r
+\r
+\r
+/* ------------------------------------------------------------------------------- */\r
+/*                  ECIA APIs using device IROUTE() as input                       */ \r
+/* ------------------------------------------------------------------------------- */\r
+\r
+/** Clear Source in the ECIA for the device  \r
+ * @param devi - device IROUTING value  \r
+ */\r
+void interrupt_device_ecia_source_clear(const uint32_t dev_iroute)\r
+{    \r
+    uint8_t girq_num;\r
+    uint8_t ia_bit_pos;\r
+    \r
+    girq_num = (uint8_t)(dev_iroute >> (ECIA_GIRQ_ID_BITPOS)) & 0x1Fu;\r
+    ia_bit_pos = (uint8_t)(dev_iroute >> (ECIA_GIRQ_BIT_BITPOS)) & 0x1Fu;           \r
+            \r
+    p_interrupt_ecia_girq_source_clr(girq_num, ia_bit_pos);        \r
+    __DSB();\r
+}\r
+\r
+/** Get the Source bit in the ECIA for the device  \r
+ * @param devi - device IROUTING value  \r
+ * @return 0 if source bit not set; else non-zero value\r
+ */\r
+uint32_t interrupt_device_ecia_source_get(const uint32_t dev_iroute)\r
+{    \r
+    uint8_t girq_num;\r
+    uint8_t ia_bit_pos;\r
+    uint8_t retVal;\r
+    \r
+    girq_num = (uint8_t)(dev_iroute >> (ECIA_GIRQ_ID_BITPOS)) & 0x1Fu;\r
+    ia_bit_pos = (uint8_t)(dev_iroute >> (ECIA_GIRQ_BIT_BITPOS)) & 0x1Fu;           \r
+            \r
+    retVal = p_interrupt_ecia_girq_source_get(girq_num, ia_bit_pos);        \r
+    return retVal;\r
+}\r
+\r
+/** Get the Result bit in the ECIA for the device  \r
+ * @param devi - device IROUTING value  \r
+ * @return 0 if result bit not set; else non-zero value\r
+ */\r
+uint32_t interrupt_device_ecia_result_get(const uint32_t dev_iroute)\r
+{    \r
+    uint8_t girq_num;\r
+    uint8_t ia_bit_pos;\r
+    uint8_t retVal;\r
+    \r
+    girq_num = (uint8_t)(dev_iroute >> (ECIA_GIRQ_ID_BITPOS)) & 0x1Fu;\r
+    ia_bit_pos = (uint8_t)(dev_iroute >> (ECIA_GIRQ_BIT_BITPOS)) & 0x1Fu;           \r
+            \r
+    retVal = p_interrupt_ecia_girq_result_get(girq_num, ia_bit_pos);        \r
+    return retVal;\r
+}\r
+\r
+/* ------------------------------------------------------------------------------- */\r
+/*                  NVIC APIs using device IROUTE() as input                       */ \r
+/* ------------------------------------------------------------------------------- */\r
+/* Note that if the device interrupt is aggregated, then these APIs would affect the \r
+ * NVIC corresponding to the aggregated GIRQ \r
+ */\r
+\r
+/**  Enable/Disable the NVIC (in the NVIC controller) for the device\r
+ * @param dev_iroute : source IROUTING information (encoded in a uint32_t)\r
+ * @param en_flag : 1 = Enable the NVIC IRQ, 0 = Disable the NVIC IRQ \r
+ * @note 1. Recommended to use interrupt_device_enable, interrupt_device_disable\r
+ * to enable/disable interrupts for the device, since those APIs configure ECIA as well\r
+ * 2. This function disables and enables global interrupt    \r
+ */\r
+void interrupt_device_nvic_enable(uint32_t dev_iroute, uint8_t en_flag)\r
+{\r
+    uint32_t isave;\r
+    IRQn_Type nvic_num;\r
+               \r
+    if (p_interrupt_control_get())        \r
+    { // direct                                \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_NVIC_ID_BITPOS)) & 0xFFul);                                                \r
+    } \r
+    else // fully aggregated\r
+    {                          \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_IA_NVIC_ID_BITPOS)) & 0xFFul);\r
+    }\r
+    \r
+    isave = __get_PRIMASK();\r
+    __disable_irq();\r
+    \r
+    p_interrupt_nvic_enable(nvic_num, en_flag);                \r
+   \r
+    if (!isave) {\r
+        __enable_irq();\r
+    }\r
+}\r
+\r
+\r
+/** Set NVIC priority for specified peripheral interrupt \r
+ * @param dev_iroute - source IROUTING information (encoded in a uint32_t)\r
+ * @param nvic_pri - NVIC Priority\r
+ * @note If ECIA is in aggregated mode, the priority affects all interrupt \r
+ * sources in the GIRQ. \r
+ */\r
+void interrupt_device_nvic_priority_set(const uint32_t dev_iroute, const uint8_t nvic_pri)\r
+{\r
+    IRQn_Type nvic_num;\r
+       \r
+    if (p_interrupt_control_get())        \r
+    { // direct                                \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_NVIC_ID_BITPOS)) & 0xFFul);                                                \r
+    } \r
+    else // fully aggregated\r
+    {                          \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_IA_NVIC_ID_BITPOS)) & 0xFFul);\r
+    }\r
+               \r
+    NVIC_SetPriority(nvic_num, (uint32_t)nvic_pri);\r
+}\r
+\r
+/** Return NVIC priority for the device's interrupt\r
+ * @param dev_iroute - source IROUTING information \r
+ * @return uint32_t  NVIC priority \r
+ */\r
+uint32_t interrupt_device_nvic_priority_get(const uint32_t dev_iroute)\r
+{\r
+    IRQn_Type nvic_num;\r
+       uint32_t nvic_priority;\r
+    \r
+    if (p_interrupt_control_get())        \r
+    { // direct                                \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_NVIC_ID_BITPOS)) & 0xFFul);                                                \r
+    } \r
+    else // fully aggregated\r
+    {                          \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_IA_NVIC_ID_BITPOS)) & 0xFFul);\r
+    }\r
+    \r
+    nvic_priority = NVIC_GetPriority(nvic_num);\r
+               \r
+    return nvic_priority;\r
+}\r
+\r
+\r
+/** Return NVIC pending for the device\r
+ * @param dev_iroute - source IROUTING information \r
+ * @return uint8_t 0(not pending), 1 (pending in NVIC) \r
+ *  \r
+ */\r
+uint8_t interrupt_device_nvic_pending_get(const uint32_t dev_iroute)\r
+{\r
+    IRQn_Type nvic_num;\r
+    uint8_t nvic_pending;\r
+    \r
+    if (p_interrupt_control_get())        \r
+    { // direct                                \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_NVIC_ID_BITPOS)) & 0xFFul);                                                \r
+    } \r
+    else // fully aggregated\r
+    {                          \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_IA_NVIC_ID_BITPOS)) & 0xFFul);\r
+    }\r
+    \r
+    nvic_pending = (uint8_t)(NVIC_GetPendingIRQ(nvic_num));\r
+               \r
+    return nvic_pending;\r
+}\r
+\r
+\r
+/** Set NVIC pending for interrupt source\r
+ * @param dev_iroute - source IROUTING information   \r
+ */\r
+void interrupt_device_nvic_pending_set(const uint32_t dev_iroute)\r
+{\r
+    IRQn_Type nvic_num;    \r
+    \r
+    if (p_interrupt_control_get())        \r
+    { // direct                                \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_NVIC_ID_BITPOS)) & 0xFFul);                                                \r
+    } \r
+    else // fully aggregated\r
+    {                          \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_IA_NVIC_ID_BITPOS)) & 0xFFul);\r
+    }\r
+    \r
+    NVIC_SetPendingIRQ(nvic_num);   \r
+}\r
+\r
+/** Clears NVIC pending for interrupt source\r
+ * @param dev_iroute - source IROUTING information \r
+ * @return uint8_t 0(not pending), 1 (pending in NVIC) - before clear \r
+ * @note This function disables and enables global interrupt  \r
+ */\r
+uint8_t interrupt_device_nvic_pending_clear(const uint32_t dev_iroute)\r
+{\r
+    uint32_t was_masked;\r
+    IRQn_Type nvic_num;\r
+    uint8_t pending;\r
+    \r
+    if (p_interrupt_control_get())        \r
+    { // direct                                \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_NVIC_ID_BITPOS)) & 0xFFul);                                                \r
+    } \r
+    else // fully aggregated\r
+    {                          \r
+        nvic_num = (IRQn_Type)((dev_iroute >> (ECIA_IA_NVIC_ID_BITPOS)) & 0xFFul);\r
+    }\r
+    \r
+    was_masked = __get_PRIMASK();\r
+    __disable_irq();\r
+    \r
+    pending = (uint8_t)(NVIC_GetPendingIRQ(nvic_num));\r
+\r
+    NVIC_ClearPendingIRQ(nvic_num);\r
+    __DSB();\r
+    \r
+    if (!was_masked) {\r
+        __enable_irq();\r
+    }\r
+               \r
+    return pending;\r
+}\r
+\r
+/* ------------------------------------------------------------------------------- */\r
+\r
+/* end interrupt_api.c */\r
+/**   @}\r
+ */\r