0
mirror of https://github.com/Indemsys/Frequency_Inverter.git synced 2026-06-14 11:22:09 +00:00
Files
2022-01-04 12:22:53 +02:00

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 */