You've already forked Frequency_Inverter
mirror of
https://github.com/Indemsys/Frequency_Inverter.git
synced 2026-06-14 11:22:09 +00:00
1041 lines
29 KiB
C
1041 lines
29 KiB
C
/*HEADER*********************************************************************
|
|
*
|
|
* Copyright (c) 2008 Freescale Semiconductor;
|
|
* All Rights Reserved
|
|
*
|
|
* Copyright (c) 2004-2008 Embedded Access Inc.;
|
|
* All Rights Reserved
|
|
*
|
|
* Copyright (c) 1989-2008 ARC International;
|
|
* All Rights Reserved
|
|
*
|
|
***************************************************************************
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
**************************************************************************
|
|
*
|
|
* $FileName: int.c$
|
|
* $Version : 3.8.0.1$
|
|
* $Date : Feb-22-2012$
|
|
*
|
|
* Comments:
|
|
*
|
|
* This file contains functions of the Interrupt component.
|
|
*
|
|
*END************************************************************************/
|
|
|
|
#include "mqx_inc.h"
|
|
|
|
#if MQX_USE_INTERRUPTS
|
|
|
|
/*!
|
|
* \brief Default ISR that MQX calls if an unhandled interrupt or exception occurs.
|
|
*
|
|
* This is the default MQX handler of interrupts or expections not hanlded by
|
|
* a specific handler routine. This function changes the state of the active
|
|
* task to UNHANDLED_INT_BLOCKED and blocks it.
|
|
*
|
|
* \param[in] vector_number Parameter that MQX passes to the ISR.
|
|
*
|
|
* \warning Blocks the active task. Do not call this function, use it as a default
|
|
* handler of unhandled interrupts or exceptions.
|
|
*
|
|
* \see _int_install_default_isr
|
|
* \see _int_install_unexpected_isr
|
|
* \see _int_install_exception_isr
|
|
*/
|
|
void _int_default_isr
|
|
(
|
|
pointer vector_number
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
TD_STRUCT_PTR td_ptr;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
|
|
td_ptr = kernel_data->ACTIVE_PTR;
|
|
_KLOGE5(KLOG_int_default_isr, td_ptr, vector_number,
|
|
&vector_number, vector_number);
|
|
|
|
_int_disable();
|
|
if (td_ptr->STATE != UNHANDLED_INT_BLOCKED)
|
|
{
|
|
td_ptr->STATE = UNHANDLED_INT_BLOCKED;
|
|
td_ptr->INFO = (_mqx_uint) vector_number;
|
|
_task_set_error_td_internal(td_ptr, MQX_UNHANDLED_INTERRUPT);
|
|
_QUEUE_UNLINK(td_ptr);
|
|
} /* Endif */
|
|
_int_enable();
|
|
|
|
} /* Endbody */
|
|
|
|
/*!
|
|
* \brief This function disables all interrupts for active task.
|
|
*
|
|
* The _int_disable() function disables all hardware interrupts at priorities up
|
|
* to and including the MQX disable-interrupt level. As a result, no task can
|
|
* interrupt the active task while the active task is running until interrupts
|
|
* are re-enabled with _int_enable(). If the active task blocks while interrupts
|
|
* are disabled, the state of the interrupts (disabled or enabled) depends on
|
|
* the interrupt-disabled state of the next task that MQX makes ready.
|
|
* \n Keep minimum code between calls to _int_disable() and its matching _int_enable().
|
|
* If _int_disable() or _int_enable() are nested, MQX re-enables interrupts only
|
|
* after the number of calls to _int_enable() are equal to the number of calls to
|
|
* _int_disable().
|
|
*
|
|
* \see _int_enable
|
|
*/
|
|
void _int_disable(void)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
|
|
_INT_DISABLE_CODE();
|
|
|
|
} /* Endbody */
|
|
|
|
/*!
|
|
* \brief This function enables all interrupts for active task.
|
|
*
|
|
* This function _int_enable() resets the processor priority to the hardware
|
|
* priority that corresponds to the active task's software priority.
|
|
* Keep minimum code between calls to _int_disable() and its matching
|
|
* _int_enable().
|
|
* \n If _int_disable() or _int_enable() are nested, MQX re-enables interrupts only
|
|
* after the number of calls to _int_enable() are equal to the number of calls to
|
|
* _int_disable().
|
|
*
|
|
* \see _int_disable
|
|
*/
|
|
void _int_enable(void)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
|
|
_INT_ENABLE_CODE();
|
|
|
|
} /* Endbody */
|
|
|
|
/*!
|
|
* \brief Gets a pointer to the default ISR that MQX calls when an unexpected interrupt occurs.
|
|
*
|
|
* This function returns the pointer to current default ISR.
|
|
*
|
|
* \return Pointer to the default ISR for unhandled interrupts.
|
|
* \return NULL (Failure.)
|
|
*
|
|
* \see _int_install_default_isr
|
|
*/
|
|
INT_ISR_FPTR _int_get_default_isr
|
|
(
|
|
void
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
return(kernel_data->DEFAULT_ISR);
|
|
|
|
} /* Endbody */
|
|
|
|
/*!
|
|
* \brief Gets a pointer to the current ISR exception handler for the vector number.
|
|
*
|
|
* The returned exception handler is either a default ISR or an ISR that the
|
|
* application installed with _int_set_exception_handler().
|
|
*
|
|
* \param[in] vector Number of a vector whose exception handler is to be returned.
|
|
*
|
|
* \return Pointer to the current exception handler.
|
|
* \return NULL (Failure.)
|
|
*
|
|
* \warning On failure, calls _task_set_error() to set the task error code.
|
|
*
|
|
* \see _int_set_exception_handler
|
|
* \see _int_exception_isr
|
|
* \see _task_set_error
|
|
*/
|
|
#if !MQX_SPARSE_ISR_TABLE
|
|
|
|
INT_EXCEPTION_FPTR _int_get_exception_handler
|
|
(
|
|
_mqx_uint vector
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
#if MQX_CHECK_ERRORS
|
|
if ( kernel_data->INTERRUPT_TABLE_PTR == NULL )
|
|
{
|
|
_task_set_error(MQX_COMPONENT_DOES_NOT_EXIST);
|
|
return(NULL);
|
|
} /* Endif */
|
|
if ((vector < kernel_data->FIRST_USER_ISR_VECTOR) ||
|
|
(vector > kernel_data->LAST_USER_ISR_VECTOR))
|
|
{
|
|
_task_set_error(MQX_INVALID_VECTORED_INTERRUPT);
|
|
return(NULL);
|
|
}/* Endif */
|
|
#endif
|
|
|
|
vector -= kernel_data->FIRST_USER_ISR_VECTOR;
|
|
return(kernel_data->INTERRUPT_TABLE_PTR[vector].APP_ISR_EXCEPTION_HANDLER);
|
|
|
|
} /* Endbody */
|
|
|
|
#else /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
INT_EXCEPTION_FPTR _int_get_exception_handler
|
|
(
|
|
_mqx_uint vector
|
|
)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
#endif /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
/*!
|
|
* \brief Gets the current ISR for the specified vector.
|
|
*
|
|
* The returned ISR is either a default ISR or an ISR that the application
|
|
* installed with _int_install_isr().
|
|
*
|
|
* \param[in] vector Number of the vector whose ISR is to be returned.
|
|
*
|
|
* \return Pointer to the ISR. (Success.)
|
|
* \return NULL (Failure.)
|
|
*
|
|
* \warning On failure, calls _task_set_error() to set the task error code.
|
|
*
|
|
* \see _int_install_isr
|
|
* \see _int_get_isr_data
|
|
* \see _int_set_isr_data
|
|
* \see _task_set_error
|
|
*/
|
|
#if !MQX_SPARSE_ISR_TABLE
|
|
|
|
INT_ISR_FPTR _int_get_isr
|
|
(
|
|
_mqx_uint vector
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
|
|
#if MQX_CHECK_ERRORS
|
|
if ( kernel_data->INTERRUPT_TABLE_PTR == NULL )
|
|
{
|
|
_task_set_error(MQX_COMPONENT_DOES_NOT_EXIST);
|
|
return(NULL);
|
|
} /* Endif */
|
|
if ((vector < kernel_data->FIRST_USER_ISR_VECTOR) ||
|
|
(vector > kernel_data->LAST_USER_ISR_VECTOR))
|
|
{
|
|
_task_set_error(MQX_INVALID_VECTORED_INTERRUPT);
|
|
return NULL;
|
|
} /* Endif */
|
|
#endif
|
|
|
|
vector -= kernel_data->FIRST_USER_ISR_VECTOR;
|
|
|
|
return(kernel_data->INTERRUPT_TABLE_PTR[vector].APP_ISR);
|
|
|
|
} /* Endbody */
|
|
|
|
#else /* MQX_SPARSE_ISR_TABLE */
|
|
INT_ISR_FPTR _int_get_isr
|
|
(
|
|
_mqx_uint vector
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
INTERRUPT_SPARSE_REC_STRUCT_PTR int_ptr;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
|
|
#if MQX_CHECK_ERRORS
|
|
if ( kernel_data->INTERRUPT_TABLE_PTR == NULL )
|
|
{
|
|
_task_set_error(MQX_COMPONENT_DOES_NOT_EXIST);
|
|
return(NULL);
|
|
} /* Endif */
|
|
if ((vector < kernel_data->FIRST_USER_ISR_VECTOR) ||
|
|
(vector > kernel_data->LAST_USER_ISR_VECTOR))
|
|
{
|
|
_task_set_error(MQX_INVALID_VECTORED_INTERRUPT);
|
|
return NULL;
|
|
} /* Endif */
|
|
#endif
|
|
|
|
_int_disable();
|
|
|
|
int_ptr = kernel_data->INTERRUPT_TABLE_PTR[(vector - kernel_data->FIRST_USER_ISR_VECTOR) >> MQX_SPARSE_ISR_SHIFT];
|
|
|
|
while (int_ptr && int_ptr->VEC_NUM != vector)
|
|
{
|
|
int_ptr = int_ptr->NEXT;
|
|
}
|
|
|
|
_int_enable();
|
|
|
|
return (int_ptr) ? int_ptr->APP_ISR : _int_default_isr;
|
|
|
|
}
|
|
|
|
#endif /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
/*!
|
|
* \brief Retrieves a pointer of the interrupt handler data for the specified
|
|
* vector.
|
|
*
|
|
* When MQX calls _int_kernel_isr() or an application ISR, it passes the data
|
|
* as the first parameter to the ISR.
|
|
* \nISR data can be modified with _int_set_isr_data().
|
|
*
|
|
* \param[in] vector Number of the vector whose ISR data are to be returned.
|
|
*
|
|
* \return Pointer to the ISR data.
|
|
* \return NULL (Failure.)
|
|
*
|
|
* \warning On failure, calls _task_set_error() to set the task error code.
|
|
*
|
|
* \see _int_get_isr
|
|
* \see _int_install_isr
|
|
* \see _int_set_isr_data
|
|
*/
|
|
#if !MQX_SPARSE_ISR_TABLE
|
|
|
|
pointer _int_get_isr_data
|
|
(
|
|
_mqx_uint vector
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
#if MQX_CHECK_ERRORS
|
|
if ( kernel_data->INTERRUPT_TABLE_PTR == NULL )
|
|
{
|
|
_task_set_error(MQX_COMPONENT_DOES_NOT_EXIST);
|
|
return(NULL);
|
|
} /* Endif */
|
|
if ((vector < kernel_data->FIRST_USER_ISR_VECTOR) ||
|
|
(vector > kernel_data->LAST_USER_ISR_VECTOR))
|
|
{
|
|
_task_set_error(MQX_INVALID_VECTORED_INTERRUPT);
|
|
return(NULL);
|
|
}/* Endif */
|
|
#endif
|
|
|
|
vector -= kernel_data->FIRST_USER_ISR_VECTOR;
|
|
return(kernel_data->INTERRUPT_TABLE_PTR[vector].APP_ISR_DATA);
|
|
|
|
} /* Endbody */
|
|
|
|
#else /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
pointer _int_get_isr_data
|
|
(
|
|
_mqx_uint vector
|
|
)
|
|
{
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
INTERRUPT_SPARSE_REC_STRUCT_PTR int_ptr;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
#if MQX_CHECK_ERRORS
|
|
if ( kernel_data->INTERRUPT_TABLE_PTR == NULL )
|
|
{
|
|
_task_set_error(MQX_COMPONENT_DOES_NOT_EXIST);
|
|
return(NULL);
|
|
} /* Endif */
|
|
if ((vector < kernel_data->FIRST_USER_ISR_VECTOR) ||
|
|
(vector > kernel_data->LAST_USER_ISR_VECTOR))
|
|
{
|
|
_task_set_error(MQX_INVALID_VECTORED_INTERRUPT);
|
|
return(NULL);
|
|
}/* Endif */
|
|
#endif
|
|
|
|
_int_disable();
|
|
|
|
int_ptr = kernel_data->INTERRUPT_TABLE_PTR[(vector - kernel_data->FIRST_USER_ISR_VECTOR) >> MQX_SPARSE_ISR_SHIFT];
|
|
|
|
while (int_ptr && int_ptr->VEC_NUM != vector)
|
|
{
|
|
int_ptr = int_ptr->NEXT;
|
|
}
|
|
|
|
_int_enable();
|
|
|
|
return (int_ptr) ? int_ptr->APP_ISR_DATA : NULL;
|
|
}
|
|
|
|
#endif /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
/*!
|
|
* \brief Gets the depth of nesting of the current interrupt stack.
|
|
*
|
|
* \return 0 (An interrupt is not being serviced.)
|
|
* \return 1 (A non-nested interrupt is being serviced.)
|
|
* \return >=2 (A nested interrupt is being serviced.)
|
|
*
|
|
* \see _int_install_isr
|
|
*/
|
|
_mqx_uint _int_get_isr_depth(void)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
return( kernel_data->IN_ISR );
|
|
} /* Endbody */
|
|
|
|
/*!
|
|
* \brief Installs the provided function as the default ISR, called whenever an
|
|
* unhandled interrupt occurs.
|
|
*
|
|
* MQX uses the application-provided default ISR for all interrupts for which
|
|
* the application has not installed an application ISR. The routine handles all
|
|
* unhandled and unexpected interrupts.
|
|
*
|
|
* \param[in] default_isr The new default ISR function.
|
|
*
|
|
* \return Pointer to previous default ISR which was installed before this function was called.
|
|
*
|
|
* \see _int_get_default_isr
|
|
* \see _int_install_isr
|
|
* \see _int_default_isr
|
|
* \see _int_install_exception_isr
|
|
* \see _int_install_unexpected_isr
|
|
*/
|
|
#if !MQX_SPARSE_ISR_TABLE
|
|
|
|
INT_ISR_FPTR _int_install_default_isr
|
|
(
|
|
INT_ISR_FPTR default_isr
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
INT_ISR_FPTR old_default_isr;
|
|
INTERRUPT_TABLE_STRUCT_PTR int_table_ptr;
|
|
_mqx_uint number;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
_KLOGE2(KLOG_int_install_default_isr, default_isr);
|
|
|
|
old_default_isr = kernel_data->DEFAULT_ISR;
|
|
kernel_data->DEFAULT_ISR = default_isr;
|
|
|
|
int_table_ptr = kernel_data->INTERRUPT_TABLE_PTR;
|
|
if (int_table_ptr != NULL)
|
|
{
|
|
number = (kernel_data->LAST_USER_ISR_VECTOR -
|
|
kernel_data->FIRST_USER_ISR_VECTOR) + 1 + 1;
|
|
|
|
while (--number)
|
|
{
|
|
if (int_table_ptr->APP_ISR == old_default_isr)
|
|
{
|
|
int_table_ptr->APP_ISR = default_isr;
|
|
} /* Endif */
|
|
++int_table_ptr;
|
|
} /* Endwhile */
|
|
} /* Endif */
|
|
|
|
_KLOGX2(KLOG_int_install_default_isr, old_default_isr);
|
|
|
|
return(old_default_isr);
|
|
|
|
} /* Endbody */
|
|
|
|
#else /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
INT_ISR_FPTR _int_install_default_isr
|
|
(
|
|
INT_ISR_FPTR default_isr
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
INT_ISR_FPTR old_default_isr;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
_KLOGE2(KLOG_int_install_default_isr, default_isr);
|
|
|
|
old_default_isr = kernel_data->DEFAULT_ISR;
|
|
kernel_data->DEFAULT_ISR = default_isr;
|
|
|
|
_KLOGX2(KLOG_int_install_default_isr, old_default_isr);
|
|
|
|
return(old_default_isr);
|
|
|
|
} /* Endbody */
|
|
|
|
#endif /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
/*!
|
|
* \brief Installs the MQX-provided _int_exception_isr() as the default ISR for
|
|
* unhandled interrupts and exceptions.
|
|
*
|
|
* The exception ISR handler performs the following service when unhandled interrupt occurs:
|
|
* \n a) A task is running
|
|
* \n - If the task has installed an exception handler, this handler is called
|
|
* \n - Otherwise, the task is aborted (_task_abort)
|
|
* \n b) An ISR is running
|
|
* \n - If the ISR has an exception handler installed, then the exception handler
|
|
* is called. Finally, both exception and ISR interrupt frames are removed.
|
|
*
|
|
* \return Pointer to the default exception handler before this function was called.
|
|
*
|
|
* \see _int_get_default_isr
|
|
*/
|
|
INT_ISR_FPTR _int_install_exception_isr
|
|
(
|
|
void
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
kernel_data->FLAGS |= MQX_FLAGS_EXCEPTION_HANDLER_INSTALLED;
|
|
return(_int_install_default_isr(_int_exception_isr));
|
|
|
|
} /* Endbody */
|
|
|
|
/*!
|
|
* \brief Installs the ISR.
|
|
*
|
|
* MQX catches all hardware interrupts in the range specified in _int_init and saves
|
|
* the context of the active task. For these interrupts, the MQX calls the ISR that is
|
|
* stored in the interrupt vector table at the location identified by its interrupt
|
|
* vector number.
|
|
* \n The application defines the ISR data, which can be any constant or pointer value.
|
|
*
|
|
* \param[in] vector Vector number (not the offset) of the interrupt.
|
|
* \param[in] isr_ptr Pointer to the ISR
|
|
* \param[in] isr_data Pointer to the data to be passed as the first parameter to
|
|
* the ISR when an interrupt occurs and the ISR runs
|
|
*
|
|
* \return Pointer to the previous ISR installed for the vector before calling this function.
|
|
* \return NULL (Failure.)
|
|
*
|
|
* \see _int_get_default_isr
|
|
* \see _int_install_default_isr
|
|
* \see _int_get_isr_data
|
|
* \see _int_set_isr_data
|
|
* \see _int_get_isr
|
|
* \see _task_set_error
|
|
*/
|
|
#if !MQX_SPARSE_ISR_TABLE
|
|
|
|
INT_ISR_FPTR _int_install_isr
|
|
(
|
|
_mqx_uint vector,
|
|
INT_ISR_FPTR isr_ptr,
|
|
pointer isr_data
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
INTERRUPT_TABLE_STRUCT_PTR table_ptr;
|
|
INT_ISR_FPTR old_isr_ptr;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
|
|
_KLOGE4(KLOG_int_install_isr, vector, isr_ptr, isr_data);
|
|
|
|
#if MQX_CHECK_ERRORS
|
|
if ( kernel_data->INTERRUPT_TABLE_PTR == NULL )
|
|
{
|
|
_task_set_error(MQX_COMPONENT_DOES_NOT_EXIST);
|
|
return(NULL);
|
|
} /* Endif */
|
|
if ((vector < kernel_data->FIRST_USER_ISR_VECTOR) ||
|
|
(vector > kernel_data->LAST_USER_ISR_VECTOR))
|
|
{
|
|
_task_set_error(MQX_INVALID_VECTORED_INTERRUPT);
|
|
_KLOGX2(KLOG_int_install_isr, NULL);
|
|
return(NULL);
|
|
}/* Endif */
|
|
#endif
|
|
|
|
table_ptr = &kernel_data->INTERRUPT_TABLE_PTR[vector -
|
|
kernel_data->FIRST_USER_ISR_VECTOR];
|
|
|
|
_int_disable();
|
|
old_isr_ptr = table_ptr->APP_ISR;
|
|
table_ptr->APP_ISR = isr_ptr;
|
|
table_ptr->APP_ISR_DATA = isr_data;
|
|
_int_enable();
|
|
|
|
_KLOGX2(KLOG_int_install_isr, old_isr_ptr);
|
|
|
|
return (old_isr_ptr);
|
|
|
|
} /* Endbody */
|
|
|
|
#else /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
INT_ISR_FPTR _int_install_isr
|
|
(
|
|
_mqx_uint vector,
|
|
INT_ISR_FPTR isr_ptr,
|
|
pointer isr_data
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
INTERRUPT_SPARSE_REC_STRUCT_PTR int_ptr;
|
|
INT_ISR_FPTR old_isr_ptr;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
|
|
_KLOGE4(KLOG_int_install_isr, vector, isr_ptr, isr_data);
|
|
|
|
#if MQX_CHECK_ERRORS
|
|
if ( kernel_data->INTERRUPT_TABLE_PTR == NULL )
|
|
{
|
|
_task_set_error(MQX_COMPONENT_DOES_NOT_EXIST);
|
|
return(NULL);
|
|
} /* Endif */
|
|
if ((vector < kernel_data->FIRST_USER_ISR_VECTOR) ||
|
|
(vector > kernel_data->LAST_USER_ISR_VECTOR))
|
|
{
|
|
_task_set_error(MQX_INVALID_VECTORED_INTERRUPT);
|
|
_KLOGX2(KLOG_int_install_isr, NULL);
|
|
return(NULL);
|
|
}/* Endif */
|
|
#endif
|
|
|
|
_int_disable();
|
|
|
|
int_ptr = kernel_data->INTERRUPT_TABLE_PTR[(vector - kernel_data->FIRST_USER_ISR_VECTOR) >> MQX_SPARSE_ISR_SHIFT];
|
|
|
|
while (int_ptr && int_ptr->VEC_NUM != vector)
|
|
{
|
|
int_ptr = int_ptr->NEXT;
|
|
}
|
|
|
|
if (!int_ptr)
|
|
{
|
|
#if MQX_LITE_VERSION_NUMBER
|
|
int_ptr = &sparse_struct;
|
|
#else
|
|
int_ptr = _mem_alloc_system(sizeof(INTERRUPT_SPARSE_REC_STRUCT));
|
|
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
|
|
if (int_ptr == NULL)
|
|
{
|
|
_int_enable();
|
|
_task_set_error(MQX_OUT_OF_MEMORY);
|
|
_KLOGX2(KLOG_int_install_isr, NULL);
|
|
return(NULL);
|
|
}
|
|
#endif /* MQX_CHECK_MEMORY_ALLOCATION_ERRORS */
|
|
_mem_set_type(int_ptr, MEM_TYPE_INTERRUPT_VECTOR);
|
|
#endif /* MQX_LITE_VERSION_NUMBER */
|
|
|
|
int_ptr->NEXT = kernel_data->INTERRUPT_TABLE_PTR[(vector - kernel_data->FIRST_USER_ISR_VECTOR) >> MQX_SPARSE_ISR_SHIFT];
|
|
kernel_data->INTERRUPT_TABLE_PTR[(vector - kernel_data->FIRST_USER_ISR_VECTOR) >> MQX_SPARSE_ISR_SHIFT] = int_ptr;
|
|
|
|
old_isr_ptr = _int_default_isr;
|
|
}
|
|
else
|
|
old_isr_ptr = int_ptr->APP_ISR;
|
|
|
|
int_ptr->VEC_NUM = vector;
|
|
int_ptr->APP_ISR = isr_ptr;
|
|
int_ptr->APP_ISR_DATA = isr_data;
|
|
|
|
_int_enable();
|
|
|
|
_KLOGX2(KLOG_int_install_isr, old_isr_ptr);
|
|
|
|
return (old_isr_ptr);
|
|
|
|
} /* Endbody */
|
|
|
|
#endif /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
/*!
|
|
* \brief Installs the MQX-provided unexpected ISR, _int_unexpected_isr(), for all
|
|
* interrupts that do not have an application-installed ISR.
|
|
*
|
|
* The unexpected ISR handler writes the cause of the unexpected interrupt to the standard
|
|
* I/O stream.
|
|
*
|
|
* \return Pointer to the previous unexpected interrupt ISR before this function was called.
|
|
*
|
|
* \see _int_install_exception_isr
|
|
* \see _int_unexpected_isr
|
|
*/
|
|
INT_ISR_FPTR _int_install_unexpected_isr
|
|
(
|
|
void
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
kernel_data->FLAGS &= ~MQX_FLAGS_EXCEPTION_HANDLER_INSTALLED;
|
|
|
|
return(_int_install_default_isr(_int_unexpected_isr));
|
|
|
|
} /* Endbody */
|
|
|
|
/*!
|
|
* \brief Sets the ISR exception handler for the interrupt vector.
|
|
*
|
|
* This function sets the exception handler for an ISR. When an exception (unhandled
|
|
* interrupt) occurs while the ISR is running, MQX calls the exception handler
|
|
* and terminates the ISR.
|
|
* \n In order to make use of exceptions, an application should install
|
|
* _int_exception_isr() as the MQX default ISR.
|
|
* \n The returned exception handler is either the default handler or one that the
|
|
* application previously installed with _int_set_exception_handler().
|
|
*
|
|
* \param[in] vector Interrupt vector that this exception handler is for.
|
|
* \param[in] error_handler_address Pointer to the exception handler.
|
|
*
|
|
* \return Pointer to the previous exception handler installed for the vector before
|
|
* this function was called.
|
|
* \return NULL (Failure.)
|
|
*
|
|
* \warning On failure, the exception handler is not installed and _task_set_error()
|
|
* is called to set the task error code.
|
|
*
|
|
* \see _int_get_exception_handler
|
|
* \see _int_exception_isr
|
|
* \see _task_set_error
|
|
*/
|
|
#if !MQX_SPARSE_ISR_TABLE
|
|
|
|
INT_EXCEPTION_FPTR _int_set_exception_handler
|
|
(
|
|
_mqx_uint vector,
|
|
INT_EXCEPTION_FPTR error_handler_address
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
INT_EXCEPTION_FPTR old_handler = NULL;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
_KLOGE3(KLOG_int_set_exception_handler, vector, error_handler_address);
|
|
|
|
#if MQX_CHECK_ERRORS
|
|
if ( kernel_data->INTERRUPT_TABLE_PTR == NULL )
|
|
{
|
|
_task_set_error(MQX_COMPONENT_DOES_NOT_EXIST);
|
|
_KLOGX2(KLOG_int_set_exception_handler, NULL);
|
|
return(NULL);
|
|
} /* Endif */
|
|
if ((vector < kernel_data->FIRST_USER_ISR_VECTOR) ||
|
|
(vector > kernel_data->LAST_USER_ISR_VECTOR))
|
|
{
|
|
_task_set_error(MQX_INVALID_VECTORED_INTERRUPT);
|
|
_KLOGX2(KLOG_int_set_exception_handler, NULL);
|
|
return(NULL);
|
|
} /* Endif */
|
|
#endif
|
|
|
|
vector -= kernel_data->FIRST_USER_ISR_VECTOR;
|
|
|
|
old_handler = kernel_data->INTERRUPT_TABLE_PTR[vector].APP_ISR_EXCEPTION_HANDLER;
|
|
kernel_data->INTERRUPT_TABLE_PTR[vector].APP_ISR_EXCEPTION_HANDLER = error_handler_address;
|
|
|
|
_KLOGX2(KLOG_int_set_exception_handler, old_handler);
|
|
return(old_handler);
|
|
} /* Endbody */
|
|
|
|
#else /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
INT_EXCEPTION_FPTR _int_set_exception_handler
|
|
(
|
|
_mqx_uint vector,
|
|
INT_EXCEPTION_FPTR error_handler_address
|
|
)
|
|
{
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
INT_EXCEPTION_FPTR old_handler = NULL;
|
|
INTERRUPT_SPARSE_REC_STRUCT_PTR int_ptr;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
_KLOGE3(KLOG_int_set_exception_handler, vector, error_handler_address);
|
|
|
|
#if MQX_CHECK_ERRORS
|
|
if ( kernel_data->INTERRUPT_TABLE_PTR == NULL )
|
|
{
|
|
_task_set_error(MQX_COMPONENT_DOES_NOT_EXIST);
|
|
_KLOGX2(KLOG_int_set_exception_handler, NULL);
|
|
return (NULL);
|
|
}
|
|
|
|
if ((vector < kernel_data->FIRST_USER_ISR_VECTOR) ||
|
|
(vector > kernel_data->LAST_USER_ISR_VECTOR))
|
|
{
|
|
_task_set_error(MQX_INVALID_VECTORED_INTERRUPT);
|
|
_KLOGX2(KLOG_int_set_exception_handler, NULL);
|
|
return (NULL);
|
|
}
|
|
#endif
|
|
|
|
_int_disable();
|
|
|
|
int_ptr = kernel_data->INTERRUPT_TABLE_PTR[(vector - kernel_data->FIRST_USER_ISR_VECTOR) >> MQX_SPARSE_ISR_SHIFT];
|
|
|
|
while (int_ptr && int_ptr->VEC_NUM != vector)
|
|
{
|
|
int_ptr = int_ptr->NEXT;
|
|
}
|
|
|
|
if (!int_ptr)
|
|
{
|
|
#if MQX_LITE_VERSION_NUMBER
|
|
int_ptr = &sparse_struct;
|
|
#else
|
|
int_ptr = _mem_alloc_system(sizeof(INTERRUPT_SPARSE_REC_STRUCT));
|
|
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
|
|
if (int_ptr == NULL)
|
|
{
|
|
_int_enable();
|
|
_task_set_error(MQX_OUT_OF_MEMORY);
|
|
_KLOGX2(KLOG_int_install_isr, NULL);
|
|
return(NULL);
|
|
}
|
|
#endif /* MQX_CHECK_MEMORY_ALLOCATION_ERRORS */
|
|
_mem_set_type(int_ptr, MEM_TYPE_INTERRUPT_VECTOR);
|
|
#endif /* MQX_LITE_VERSION_NUMBER */
|
|
|
|
int_ptr->NEXT = kernel_data->INTERRUPT_TABLE_PTR[(vector - kernel_data->FIRST_USER_ISR_VECTOR) >> MQX_SPARSE_ISR_SHIFT];
|
|
kernel_data->INTERRUPT_TABLE_PTR[(vector - kernel_data->FIRST_USER_ISR_VECTOR) >> MQX_SPARSE_ISR_SHIFT] = int_ptr;
|
|
|
|
old_handler = NULL;
|
|
}
|
|
else
|
|
old_handler = int_ptr->APP_ISR_EXCEPTION_HANDLER;
|
|
|
|
|
|
int_ptr->VEC_NUM = vector;
|
|
int_ptr->APP_ISR_EXCEPTION_HANDLER = error_handler_address;
|
|
|
|
_int_enable();
|
|
|
|
_KLOGX2(KLOG_int_set_exception_handler, old_handler);
|
|
return (old_handler);
|
|
}
|
|
|
|
#endif /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
/*!
|
|
* \brief Sets the address of the interrupt handler data for the specified vector,
|
|
* and returns the old value.
|
|
*
|
|
* \param[in] vector The interrupt vector that this data is for.
|
|
* \param[in] data Data that MQX passes to the ISR as its first parameter.
|
|
*
|
|
* \return Previous ISR data registred before this function was called.
|
|
* \return NULL (Failure.)
|
|
*
|
|
* \warning On failure, calls _task_set_error() to set the task error code.
|
|
*
|
|
* \see _int_get_isr
|
|
* \see _int_get_isr_data
|
|
*/
|
|
#if !MQX_SPARSE_ISR_TABLE
|
|
|
|
pointer _int_set_isr_data
|
|
(
|
|
_mqx_uint vector,
|
|
pointer data
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
pointer old_data;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
_KLOGE3(KLOG_int_set_isr_data,vector,data);
|
|
|
|
#if MQX_CHECK_ERRORS
|
|
if ( kernel_data->INTERRUPT_TABLE_PTR == NULL )
|
|
{
|
|
_task_set_error(MQX_COMPONENT_DOES_NOT_EXIST);
|
|
_KLOGX2(KLOG_int_set_isr_data,NULL);
|
|
return(NULL);
|
|
} /* Endif */
|
|
if ((vector < kernel_data->FIRST_USER_ISR_VECTOR) ||
|
|
(vector > kernel_data->LAST_USER_ISR_VECTOR))
|
|
{
|
|
_task_set_error(MQX_INVALID_VECTORED_INTERRUPT);
|
|
_KLOGX2(KLOG_int_set_isr_data,NULL);
|
|
return(NULL);
|
|
} /* Endif */
|
|
#endif
|
|
|
|
vector -= (kernel_data->FIRST_USER_ISR_VECTOR);
|
|
|
|
old_data = kernel_data->INTERRUPT_TABLE_PTR[vector].APP_ISR_DATA;
|
|
kernel_data->INTERRUPT_TABLE_PTR[vector].APP_ISR_DATA = data;
|
|
|
|
_KLOGX2(KLOG_int_set_isr_data,old_data);
|
|
return old_data;
|
|
|
|
} /* Endbody */
|
|
|
|
#else /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
pointer _int_set_isr_data
|
|
(
|
|
_mqx_uint vector,
|
|
pointer data
|
|
)
|
|
{
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
pointer old_data = NULL;
|
|
INTERRUPT_SPARSE_REC_STRUCT_PTR int_ptr;
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
_KLOGE3(KLOG_int_set_isr_data,vector,data);
|
|
|
|
#if MQX_CHECK_ERRORS
|
|
if ( kernel_data->INTERRUPT_TABLE_PTR == NULL )
|
|
{
|
|
_task_set_error(MQX_COMPONENT_DOES_NOT_EXIST);
|
|
_KLOGX2(KLOG_int_set_isr_data,NULL);
|
|
return(NULL);
|
|
} /* Endif */
|
|
if ((vector < kernel_data->FIRST_USER_ISR_VECTOR) ||
|
|
(vector > kernel_data->LAST_USER_ISR_VECTOR))
|
|
{
|
|
_task_set_error(MQX_INVALID_VECTORED_INTERRUPT);
|
|
_KLOGX2(KLOG_int_set_isr_data,NULL);
|
|
return(NULL);
|
|
} /* Endif */
|
|
#endif
|
|
|
|
_int_disable();
|
|
|
|
int_ptr = kernel_data->INTERRUPT_TABLE_PTR[(vector - kernel_data->FIRST_USER_ISR_VECTOR) >> MQX_SPARSE_ISR_SHIFT];
|
|
|
|
while (int_ptr && int_ptr->VEC_NUM != vector)
|
|
{
|
|
int_ptr = int_ptr->NEXT;
|
|
}
|
|
|
|
if (int_ptr)
|
|
{
|
|
old_data = int_ptr->APP_ISR_DATA;
|
|
int_ptr->APP_ISR_DATA = data;
|
|
}
|
|
|
|
_int_enable();
|
|
|
|
_KLOGX2(KLOG_int_set_isr_data,old_data);
|
|
return old_data;
|
|
}
|
|
|
|
#endif /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
/*!
|
|
* \brief This function initializes the kernel interrupt table.
|
|
*
|
|
* This function initializes the kernel interrupt table and install default interrupt
|
|
* handler to all interrupt sources. This function is typically called very early
|
|
* during system startup.
|
|
*
|
|
* \param[in] first_user_isr_vector_number The first (lower) user ISR vector number.
|
|
* \param[in] last_user_isr_vector_number The last user ISR vector number.
|
|
*
|
|
* \return MQX_OK (Success.)
|
|
* \return MQX_INVALID_PARAMETER (first_user_isr_vector_number is greater than
|
|
* last_user_isr_vector_number.)
|
|
* \return MQX_OUT_OF_MEMORY (Not enough free memory for the interrupt table.)
|
|
*/
|
|
_mqx_uint _int_init
|
|
(
|
|
_mqx_uint first_user_isr_vector_number,
|
|
_mqx_uint last_user_isr_vector_number
|
|
)
|
|
{ /* Body */
|
|
KERNEL_DATA_STRUCT_PTR kernel_data;
|
|
INTERRUPT_TABLE_STRUCT_PTR int_table_ptr;
|
|
_mqx_uint number;
|
|
|
|
#if MQX_CHECK_ERRORS
|
|
if (last_user_isr_vector_number < first_user_isr_vector_number)
|
|
{
|
|
return MQX_INVALID_PARAMETER;
|
|
} /* Endif */
|
|
#endif
|
|
|
|
_GET_KERNEL_DATA(kernel_data);
|
|
kernel_data->INT_KERNEL_ISR_ADDR = _int_kernel_isr;
|
|
|
|
/* Set the current default ISR for MQX that is called whenever an
|
|
* unhandled interrupt occurs
|
|
*/
|
|
kernel_data->DEFAULT_ISR = _int_default_isr;
|
|
|
|
#if !MQX_SPARSE_ISR_TABLE
|
|
number = last_user_isr_vector_number - first_user_isr_vector_number + 1;
|
|
#else
|
|
number = ((last_user_isr_vector_number - first_user_isr_vector_number + 1) >> MQX_SPARSE_ISR_SHIFT) + 1;
|
|
#endif
|
|
|
|
#ifdef MQX_LITE_VERSION_NUMBER
|
|
int_table_ptr = mqx_static_isr_table;
|
|
#else
|
|
int_table_ptr = _mem_alloc_system_zero((_mem_size)(sizeof(INTERRUPT_TABLE_STRUCT) * number));
|
|
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
|
|
if ( int_table_ptr == NULL )
|
|
{
|
|
return(MQX_OUT_OF_MEMORY);
|
|
}/* Endif */
|
|
#endif /* MQX_CHECK_MEMORY_ALLOCATION_ERRORS */
|
|
|
|
_mem_set_type(int_table_ptr, MEM_TYPE_INTERRUPT_TABLE);
|
|
#endif /* MQX_LITE_VERSION_NUMBER */
|
|
|
|
kernel_data->INTERRUPT_TABLE_PTR = int_table_ptr;
|
|
kernel_data->FIRST_USER_ISR_VECTOR = first_user_isr_vector_number;
|
|
kernel_data->LAST_USER_ISR_VECTOR = last_user_isr_vector_number;
|
|
|
|
#if !MQX_SPARSE_ISR_TABLE
|
|
while (number--)
|
|
{
|
|
int_table_ptr->APP_ISR = _int_default_isr;
|
|
int_table_ptr->APP_ISR_DATA = (pointer)(first_user_isr_vector_number++);
|
|
++int_table_ptr;
|
|
} /* Endwhile */
|
|
#else /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
kernel_data->SPARSE_ISR_COUNT = number;
|
|
kernel_data->SPARSE_ISR_SHIFT = MQX_SPARSE_ISR_SHIFT;
|
|
|
|
while (number--)
|
|
{
|
|
int_table_ptr[number] = NULL;
|
|
}
|
|
|
|
#endif /* MQX_SPARSE_ISR_TABLE */
|
|
|
|
return MQX_OK;
|
|
|
|
} /* Endbody */
|
|
|
|
#endif /* MQX_USE_INTERRUPTS */
|
|
|
|
/* EOF */
|