blob: 0071eadae386a607e065479ef679cf56bb9ad380 [file] [log] [blame]
/*****************************************************************************
* (c) 2014 Microchip Technology Inc. and its subsidiaries.
* You may use this software and any derivatives exclusively with
* Microchip products.
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS".
* NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP
* PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.
* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
* INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
* WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
* BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.
* TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
* CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF
* FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
* MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE
* OF THESE TERMS.
*****************************************************************************/
/** @file girq23.c
*Interrupt service routines for MIPS using vanilla GCC and MCHP XC32
*/
/** @defgroup MEC14xx ISR
* @{
*/
#include "appcfg.h"
#include "platform.h"
#include "MEC14xx/mec14xx.h"
#include "MEC14xx/mec14xx_girqs.h"
#include "MEC14xx/mec14xx_gpio.h"
#include "MEC14xx/mec14xx_bbled.h"
#include "MEC14xx/mec14xx_trace_func.h"
typedef void (* GIRQ23_FPVU8)(uint8_t);
#if GIRQ23_DISAGG == 0
/*
* FreeRTOS ISR for HW timer used as RTOS tick.
* Implemented in MEC14xx FreeRTOS porting layer, port_asm.S
* It save/restores CPU context and clears HW timer interrupt
* status in JTVIC. On each timer tick it checks if any task
* requires service. If yes then it triggers the PendSV low
* priority software interrupt.
* Issue:
* When aggregated girq23_isr save CPU context but this context
* is not the same as a FreeRTOS context save. If the RTOS timer
* is active then girq23_isr would call vPortTickInterruptHandler
* which uses FreeRTOS portSAVE_CONTEXT macro to save RTOS + CPU
* context. At this point you have two context saves on the stack.
* There is a problem:
* vPortTickInterruptHandler does not return but exits using
* portRESTORE_CONTEXT. This means the context save performed
* by aggregated girq23_isr is left on the stack. Eventually
* a stack overflow will occur.
*
* Solutions:
* 1. vPortTickInterruptHandler must be modified to handle scan
* GIRQ23 Result bits and all the respective handler. All
* other GIRQ23 source are called as hook functions.
*
* 2. Do not use vPortTickInterruptHandler.
* Modify girq23_isr here to use FreeRTOS portSAVE_CONTEXT
* and portRESTORE_CONTEXT macros.
* If RTOS timer is active interrupt then call vPortIncrementTick
* as vPortTickInterruptHandler does.
* For all other GIRQ23 sources call the respective handlers.
*
* NOTE: for both of the above solutions a we must either:
* A. Service one source only resulting in GIRQ23 firing multiple
* times if more than one source is active.
* B. Service all active sources with RTOS Timer checked first.
*
* We will implement 1A with a single hook for all other sources.
*
*/
extern void vPortIncrementTick(void);
void girq23_dflt_handler(uint8_t inum)
{
JTVIC_GIRQ->REGS[MEC14xx_GIRQ23_ID].EN_CLR = (1ul << inum);
JTVIC_GIRQ->REGS[MEC14xx_GIRQ23_ID].SOURCE = (1ul << inum);
}
void __attribute__((weak)) rtos_tmr_handler(uint8_t inum)
{
(void) inum;
JTVIC_GIRQ->REGS[MEC14xx_GIRQ23_ID].SOURCE = (1ul << 4);
}
const GIRQ23_FPVU8 girq23_htable[GIRQ23_NUM_SOURCES] =
{
girq23_dflt_handler, /* btmr0_handler, */
girq23_dflt_handler, /* btmr1_handler, */
girq23_dflt_handler, /* btmr2_handler, */
girq23_dflt_handler, /* btmr3_handler, */
vPortIncrementTick,
girq23_dflt_handler, /* hib_tmr_handler, */
girq23_dflt_handler, /* week_tmr_handler, */
girq23_dflt_handler, /* week_tmr_handler, */
girq23_dflt_handler, /* week_tmr_handler, */
girq23_dflt_handler, /* week_tmr_handler, */
girq23_dflt_handler, /* week_tmr_handler, */
girq23_dflt_handler, /* vci_handler, */
girq23_dflt_handler, /* vci_handler, */
girq23_dflt_handler, /* vci_handler, */
};
/* Called by FreeRTOS vPortTickInterruptHandler(girq23_isr)
* after saving FreeRTOS context
*/
void girq23_handler(void)
{
uint32_t d;
uint8_t bitpos;
d = JTVIC_GIRQ->REGS[MEC14xx_GIRQ23_ID].RESULT & (GIRQ23_SRC_MASK);
while ( 0 != d )
{
bitpos = 31 - ((uint8_t)__builtin_clz(d) & 0x1F);
(girq23_htable[bitpos])(bitpos);
d &= ~(1ul << bitpos);
}
}
void __attribute__((weak, interrupt, nomips16, section(".girqs")))
girq23_isr(void)
{
uint32_t d;
uint8_t bitpos;
d = JTVIC_GIRQ->REGS[MEC14xx_GIRQ23_ID].RESULT & (GIRQ23_SRC_MASK);
while ( 0 != d )
{
bitpos = 31 - ((uint8_t)__builtin_clz(d) & 0x1F);
(girq23_htable[bitpos])(bitpos);
d &= ~(1ul << bitpos);
}
}
#else
/* 16-bit Basic Timer 0 */
void __attribute__((weak, interrupt, nomips16))
girq23_b0(void)
{
JTVIC_GIRQ->REGS[MEC14xx_GIRQ23_ID].SOURCE = (1ul << 0);
}
/* 16-bit Basic Timer 1 */
void __attribute__((weak, interrupt, nomips16))
girq23_b1(void)
{
jtvic_dis_clr_source(MEC14xx_GIRQ23_ID, 1, TRUE);
}
/* 16-bit Basic Timer 2 */
void __attribute__((weak, interrupt, nomips16))
girq23_b2(void)
{
jtvic_dis_clr_source(MEC14xx_GIRQ23_ID, 2, TRUE);
}
/* 16-bit Basic Timer 3 */
void __attribute__((weak, interrupt, nomips16))
girq23_b3(void)
{
jtvic_dis_clr_source(MEC14xx_GIRQ23_ID, 3, TRUE);
}
/* RTOS Timer */
void __attribute__((weak, interrupt, nomips16))
girq23_b4(void)
{
JTVIC_GIRQ->REGS[MEC14xx_GIRQ23_ID].SOURCE = (1ul << 4);
}
/* Hibernation Timer */
void __attribute__((weak, interrupt, nomips16))
girq23_b5(void)
{
jtvic_dis_clr_source(MEC14xx_GIRQ23_ID, 5, TRUE);
}
/* Week Alarm */
void __attribute__((weak, interrupt, nomips16))
girq23_b6(void)
{
jtvic_dis_clr_source(MEC14xx_GIRQ23_ID, 6, TRUE);
}
/* Sub-Week Alarm */
void __attribute__((weak, interrupt, nomips16))
girq23_b7(void)
{
jtvic_dis_clr_source(MEC14xx_GIRQ23_ID, 7, TRUE);
}
/* Week Alarm One Second */
void __attribute__((weak, interrupt, nomips16))
girq23_b8(void)
{
jtvic_dis_clr_source(MEC14xx_GIRQ23_ID, 8, TRUE);
}
/* Week Alarm Sub Second */
void __attribute__((weak, interrupt, nomips16))
girq23_b9(void)
{
jtvic_dis_clr_source(MEC14xx_GIRQ23_ID, 9, TRUE);
}
/* Week Alarm System Power Present Pin */
void __attribute__((weak, interrupt, nomips16))
girq23_b10(void)
{
jtvic_dis_clr_source(MEC14xx_GIRQ23_ID, 10, TRUE);
}
/* VCI OVRD Input */
void __attribute__((weak, interrupt, nomips16))
girq23_b11(void)
{
jtvic_dis_clr_source(MEC14xx_GIRQ23_ID, 11, TRUE);
}
/* VCI IN0 */
void __attribute__((weak, interrupt, nomips16))
girq23_b12(void)
{
jtvic_dis_clr_source(MEC14xx_GIRQ23_ID, 12, TRUE);
}
/* VCI IN1 */
void __attribute__((weak, interrupt, nomips16))
girq23_b13(void)
{
jtvic_dis_clr_source(MEC14xx_GIRQ23_ID, 13, TRUE);
}
#endif
/* end girq23.c */
/** @}
*/