mbed library sources
Fork of mbed-src by
targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/system/interrupt/system_interrupt.c
- Committer:
- mbed_official
- Date:
- 2015-07-17
- Revision:
- 592:a274ee790e56
- Parent:
- 579:53297373a894
File content as of revision 592:a274ee790e56:
#include "system_interrupt.h" /** * \brief Check if a interrupt line is pending. * * Checks if the requested interrupt vector is pending. * * \param[in] vector Interrupt vector number to check * * \returns A boolean identifying if the requested interrupt vector is pending. * * \retval true Specified interrupt vector is pending * \retval false Specified interrupt vector is not pending * */ bool system_interrupt_is_pending( const enum system_interrupt_vector vector) { bool result; if (vector >= _SYSTEM_INTERRUPT_EXTERNAL_VECTOR_START) { result = ((NVIC->ISPR[0] & (1 << vector)) != 0); } else if (vector == SYSTEM_INTERRUPT_SYSTICK) { result = ((SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) != 0); } else { Assert(false); result = false; } return result; } /** * \brief Set a interrupt vector as pending. * * Set the requested interrupt vector as pending (i.e issues a software * interrupt request for the specified vector). The software handler will be * handled (if enabled) in a priority order based on vector number and * configured priority settings. * * \param[in] vector Interrupt vector number which is set as pending * * \returns Status code identifying if the vector was successfully set as * pending. * * \retval STATUS_OK If no error was detected * \retval STATUS_INVALID_ARG If an unsupported interrupt vector number was given */ enum status_code system_interrupt_set_pending( const enum system_interrupt_vector vector) { enum status_code status = STATUS_OK; if (vector >= _SYSTEM_INTERRUPT_EXTERNAL_VECTOR_START) { NVIC->ISPR[0] = (1 << vector); } else if (vector == SYSTEM_INTERRUPT_NON_MASKABLE) { /* Note: Because NMI has highest priority it will be executed * immediately after it has been set pending */ SCB->ICSR = SCB_ICSR_NMIPENDSET_Msk; } else if (vector == SYSTEM_INTERRUPT_SYSTICK) { SCB->ICSR = SCB_ICSR_PENDSTSET_Msk; } else { /* The user want to set something unsupported as pending */ Assert(false); status = STATUS_ERR_INVALID_ARG; } return status; } /** * \brief Clear pending interrupt vector. * * Clear a pending interrupt vector, so the software handler is not executed. * * \param[in] vector Interrupt vector number to clear * * \returns A status code identifying if the interrupt pending state was * successfully cleared. * * \retval STATUS_OK If no error was detected * \retval STATUS_INVALID_ARG If an unsupported interrupt vector number was given */ enum status_code system_interrupt_clear_pending( const enum system_interrupt_vector vector) { enum status_code status = STATUS_OK; if (vector >= _SYSTEM_INTERRUPT_EXTERNAL_VECTOR_START) { NVIC->ICPR[0] = (1 << vector); } else if (vector == SYSTEM_INTERRUPT_NON_MASKABLE) { /* Note: Clearing of NMI pending interrupts does not make sense and is * not supported by the device, as it has the highest priority and will * always be executed at the moment it is set */ return STATUS_ERR_INVALID_ARG; } else if (vector == SYSTEM_INTERRUPT_SYSTICK) { SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk; } else { Assert(false); status = STATUS_ERR_INVALID_ARG; } return status; } /** * \brief Set interrupt vector priority level. * * Set the priority level of an external interrupt or exception. * * \param[in] vector Interrupt vector to change * \param[in] priority_level New vector priority level to set * * \returns Status code indicating if the priority level of the interrupt was * successfully set. * * \retval STATUS_OK If no error was detected * \retval STATUS_INVALID_ARG If an unsupported interrupt vector number was given */ enum status_code system_interrupt_set_priority( const enum system_interrupt_vector vector, const enum system_interrupt_priority_level priority_level) { enum status_code status = STATUS_OK; if (vector >= _SYSTEM_INTERRUPT_EXTERNAL_VECTOR_START) { uint8_t register_num = vector / 4; uint8_t priority_pos = ((vector % 4) * 8) + (8 - __NVIC_PRIO_BITS); NVIC->IP[register_num] = (NVIC->IP[register_num] & ~(0x3 << priority_pos)) | (priority_level << priority_pos); } else if (vector == SYSTEM_INTERRUPT_SYSTICK) { SCB->SHP[1] = (priority_level << _SYSTEM_INTERRUPT_SYSTICK_PRI_POS); } else { Assert(false); status = STATUS_ERR_INVALID_ARG; } return status; } /** * \brief Get interrupt vector priority level. * * Retrieves the priority level of the requested external interrupt or exception. * * \param[in] vector Interrupt vector of which the priority level will be read * * \return Currently configured interrupt priority level of the given interrupt * vector. */ enum system_interrupt_priority_level system_interrupt_get_priority( const enum system_interrupt_vector vector) { uint8_t register_num = vector / 4; uint8_t priority_pos = ((vector % 4) * 8) + (8 - __NVIC_PRIO_BITS); enum system_interrupt_priority_level priority = SYSTEM_INTERRUPT_PRIORITY_LEVEL_0; if (vector >= 0) { priority = (enum system_interrupt_priority_level) ((NVIC->IP[register_num] >> priority_pos) & _SYSTEM_INTERRUPT_PRIORITY_MASK); } else if (vector == SYSTEM_INTERRUPT_SYSTICK) { priority = (enum system_interrupt_priority_level) ((SCB->SHP[1] >> _SYSTEM_INTERRUPT_SYSTICK_PRI_POS) & _SYSTEM_INTERRUPT_PRIORITY_MASK); } return priority; }