+++ /dev/null
-/*****************************************************************************\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