/******************************************************************************
* File Name : stm32f2xx_it.c
*******************************************************************************/
#ifdef SDK
#include "SDK_Common.h"
#include "SDK_it.h"
#include "stm32f4xx_it.h"
#else
#include "Common.h"
#include "GKI_lib.h"
#include "TM_UARTDriver.h"
#include "TM_PioDef.h"
#include "TM_TimerControl.h"
#include "TM_FlashManager.h"
#include "stm32f4xx_it.h"
#endif

#define GPIO_ISR(x) TM_GPIO_ISR(x)


// UART Registers
static USART_TypeDef * UART[2]={
    ((USART_TypeDef *) USART1_BASE),
    ((USART_TypeDef *) USART2_BASE)
};


//--------------------------------------------
// Globals
//--------------------------------------------
uint32 DmaDelay=1000;   // was 800

#if defined(CUSTOM_AVDTP) || CUSTOM_AUDIO_WM8904
extern void avdtp_IsrRxChan5(tTM_InterruptSource src);
#ifdef CUSTOM_I2S
extern void avdtp_IsrTxChan5(tTM_InterruptSource src);
#endif
extern uint16 AT_UartRxCallBack2(uint8 * pData, uint16 length);
#endif

// Error Counts
u32 MainRxError_Transfer=0;
u32 MainRxError_FIFO=0;
u32 MainRxError_DirectMode=0;
u32 HciRxError_Transfer=0;
u32 HciRxError_FIFO=0;
u32 HciRxError_DirectMode=0;

// ENABLE_HARDFAULT_DIAGNOSIS
u32 DebugReference=0;
u32 DebugReferenceID=0;


#define MAIN    0
#define HCI     1

// forward prototypes
void USART_IRQHandler(uint16 u);



#define PANIC(x)    __set_MSP(*(vu32*) FM_APP_VECTORS); GKI_putstring("\r\n");  \
                    GKI_putstring(x); GKI_putstring("\r\n");  while (1);



/******************************************************************************/
/*            Cortex-M4 Processor Exceptions Handlers                         */
/******************************************************************************/

/**
  * @brief   This function handles NMI exception.
  * @param  None
  * @retval None
  */
void NMI_Handler(void)
{
  PANIC("NMI_Handler");
}

/**
  * @brief  This function handles Hard Fault exception.
  * @param  None
  * @retval None
  */
void HardFault_Handler(void)
{
#ifdef ENABLE_HARDFAULT_DIAGNOSIS
  __set_MSP(*(vu32*) FM_APP_VECTORS);
  static char msg[64];
  sprintf(msg, "\r\nHardFault: %d (%d)\r\n", DebugReference, DebugReferenceID);
  GKI_putstring(msg);
#else
  PANIC("HardFault");
#endif
  while (1)
  {
  }
}

/**
  * @brief  This function handles Memory Manage exception.
  * @param  None
  * @retval None
  */
void MemManage_Handler(void)
{
  /* Go to infinite loop when Memory Manage exception occurs */
  PANIC("MemManage");
  while (1)
  {
  }
}

/**
  * @brief  This function handles Bus Fault exception.
  * @param  None
  * @retval None
  */
void BusFault_Handler(void)
{
  /* Go to infinite loop when Bus Fault exception occurs */
  PANIC("BusFault");
  while (1)
  {
  }
}

/**
  * @brief  This function handles Usage Fault exception.
  * @param  None
  * @retval None
  */
void UsageFault_Handler(void)
{
  /* Go to infinite loop when Usage Fault exception occurs */
  PANIC("UsageFault");
  while (1)
  {
  }
}

/**
  * @brief  This function handles SVCall exception.
  * @param  None
  * @retval None
  */
void SVC_Handler(void)
{
}

/**
  * @brief  This function handles Debug Monitor exception.
  * @param  None
  * @retval None
  */
void DebugMon_Handler(void)
{
}

/**
  * @brief  This function handles PendSVC exception.
  * @param  None
  * @retval None
  */
void PendSV_Handler(void)
{
}

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
    extern void ISR_Calibrate(void);
    ISR_Calibrate();
}



/*******************************************************************************
* Function Name  : EXTI0_IRQHandler
*******************************************************************************/
void EXTI0_IRQHandler(void)
{
    if (EXTI_GetFlagStatus(EXTI_Line0)) {
        EXTI_ClearITPendingBit(EXTI_Line0);
        GPIO_ISR(0);
    }
}

/*******************************************************************************
* Function Name  : EXTI1_IRQHandler
*******************************************************************************/
// Used by the Main Uart
void EXTI1_IRQHandler(void)
{
	if (EXTI_GetFlagStatus(EXTI_Line1)) {
        EXTI_ClearITPendingBit(EXTI_Line1);
        GPIO_ISR(1);
    }
}

/*******************************************************************************
* Function Name  : EXTI2_IRQHandler
* Description    : This function handles External interrupt Line 2 request.
*                  A RFCOMM buffer has been released, HciRxPool
*******************************************************************************/
// Used by the HCI Uart
void EXTI2_IRQHandler(void)
{
    IsrSrcStat[HCI].SWI++;
    NVIC_InitTypeDef   NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel                   = EXTI2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TM_ExtPriority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = DISABLE;
    NVIC_Init(&NVIC_InitStructure);
#ifdef DEBUG_DMA
    TM_ResetPio(3);
#endif
    if (TM_DmaRxCount(eTM_HciUart))  {
        TM_UartHciRxHandler(eTM_HciUart, TM_IntSrc_SWI);
    }
}

/*******************************************************************************
* Function Name  : EXTI3_IRQHandler
*******************************************************************************/
void EXTI3_IRQHandler(void)
{
    IsrSrcStat[MAIN].SWI++;
    NVIC_InitTypeDef   NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel                   = EXTI3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TM_ExtPriority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = DISABLE;
    NVIC_Init(&NVIC_InitStructure);
#ifdef DEBUG_DMA
    TM_ResetPio(2);
#endif
#if 0
    extern uint16 gDataLeftInDmaCnt;
    uint16 now_dma_rx_cnt;
    now_dma_rx_cnt = TM_DmaRxCount(eTM_MainUart);
    if(now_dma_rx_cnt){
          if(now_dma_rx_cnt == gDataLeftInDmaCnt){
              TM_UartMainRxHandler(eTM_MainUart, TM_IntSrc_IDLE);
          }
          else
          {
              TM_UartMainRxHandler(eTM_MainUart, TM_IntSrc_SWI);
          }
    }
#else
    if (TM_DmaRxCount(eTM_MainUart)) {
        TM_UartMainRxHandler(eTM_MainUart, TM_IntSrc_SWI);
    }
#endif
}

/*******************************************************************************
* Function Name  : EXTI4_IRQHandler
*******************************************************************************/
void EXTI4_IRQHandler(void)
{
    if (EXTI_GetFlagStatus(EXTI_Line4)) {
        EXTI_ClearITPendingBit(EXTI_Line4);
        GPIO_ISR(4);
    }
}


/*******************************************************************************
* Function Name  : EXTI9_5_IRQHandler
*******************************************************************************/
void EXTI9_5_IRQHandler(void)
{
    uint32 extline, i;

    for (i=5; i<=9; i++) {
        extline = 1<<i;
        if (EXTI_GetFlagStatus(extline)) {
            EXTI_ClearITPendingBit(extline);
            GPIO_ISR(i);
            break;
        }
    }
}

/*******************************************************************************
* Function Name  : EXTI15_10_IRQHandler
* Description    : This function handles External lines 15 to 10 interrupt request.
*******************************************************************************/
void EXTI15_10_IRQHandler(void)
{
    uint32 extline, i;

    for (i=10; i<=15; i++) {
        extline = 1<<i;
        if (EXTI_GetFlagStatus(extline)) {
            EXTI_ClearITPendingBit(extline);
            GPIO_ISR(i);
            break;
        }
    }
}

#ifdef HFP_SCO_OVER_HCI
void AdcDmaService(tTM_InterruptSource src);
#endif
#if defined(BT43S) || defined(BT53S)
#define HFP_PCM_BUFFER_SIZE 256
extern uint8 hfp_receive_buffer[HFP_PCM_BUFFER_SIZE];
extern uint8 hfp_transmit_buffer[HFP_PCM_BUFFER_SIZE];
#endif

#ifdef CUSTOM_AUDIO_SOURCE
void avdtp_SendDmaService(tTM_InterruptSource src);
#endif
void DMA1_Stream2_IRQHandler(void)
{ 
	/* Transfer complete interrupt */
	if (DMA_GetFlagStatus(DMA1_Stream2, DMA_FLAG_TCIF2) != RESET)
	{
		/* Clear the Interrupt flag */
		DMA_ClearFlag(DMA1_Stream2, DMA_FLAG_TCIF2);
#if defined(HFP_SCO_OVER_HCI) && (defined(BT43S)||defined(BT53S))
		AdcDmaService(TM_IntSrc_FULL);
#elif defined(CUSTOM_AUDIO_SOURCE) && (defined(BT43S) || defined(BT53S))
		avdtp_SendDmaService(TM_IntSrc_FULL);
#endif
	}

	/* Half Transfer complete interrupt */
	if (DMA_GetFlagStatus(DMA1_Stream2, DMA_FLAG_HTIF2) != RESET)
	{
		/* Clear the Interrupt flag */
		DMA_ClearFlag(DMA1_Stream2, DMA_FLAG_HTIF2);    
#if defined(HFP_SCO_OVER_HCI) && (defined(BT43S)||defined(BT53S))
		AdcDmaService(TM_IntSrc_HALF);
#elif defined(CUSTOM_AUDIO_SOURCE) && (defined(BT43S) || defined(BT53S))
		avdtp_SendDmaService(TM_IntSrc_HALF);
#endif
	}

}

void DMA1_Stream3_IRQHandler(void)
{ 
	/* Transfer complete interrupt */
	if (DMA_GetFlagStatus(DMA1_Stream3, DMA_FLAG_TCIF3) != RESET)
	{
		/* Clear the Interrupt flag */
		DMA_ClearFlag(DMA1_Stream3, DMA_FLAG_TCIF3);
#if defined(HFP_SCO_OVER_HCI) && !defined(BT43S) && !defined(BT53S)
		AdcDmaService(TM_IntSrc_FULL);
#elif defined(CUSTOM_AUDIO_SOURCE) && defined(BT24)
		avdtp_SendDmaService(TM_IntSrc_FULL);
#endif
	}

	/* Half Transfer complete interrupt */
	if (DMA_GetFlagStatus(DMA1_Stream3, DMA_FLAG_HTIF3) != RESET)
	{
		/* Clear the Interrupt flag */
		DMA_ClearFlag(DMA1_Stream3, DMA_FLAG_HTIF3);    
#if defined(HFP_SCO_OVER_HCI) && !defined(BT43S) && !defined(BT53S)
		AdcDmaService(TM_IntSrc_HALF);
#elif defined(CUSTOM_AUDIO_SOURCE) && defined(BT24)
		avdtp_SendDmaService(TM_IntSrc_HALF);
#endif
	}
}

#ifdef CUSTOM_AVDTP
void DMA1_Stream4_IRQHandler(void)
{	
	/* Transfer complete interrupt */
	if (DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_TCIF4) != RESET)
	{
		/* Clear the Interrupt flag */
		DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_TCIF4);
#if !defined(BT43S) && !defined(BT53S)
        avdtp_IsrTxChan5(TM_IntSrc_FULL);
#endif
	}

	/* Half Transfer complete interrupt */
	if (DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_HTIF4) != RESET)
	{
		/* Clear the Interrupt flag */
		DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_HTIF4); 
#if !defined(BT43S) && !defined(BT53S)
        avdtp_IsrTxChan5(TM_IntSrc_HALF);        
#endif
	}
}
#endif

/*******************************************************************************
* Function Name  : DMA Stream IRQ Handler
* Description    : Handles HCI USART2 Rx DMA
*******************************************************************************/
void DMA1_Stream5_IRQHandler(void)
{
    bool fFull=false;
    bool fHalf=false;

    // Streamx half transfer complete interrupt
    if (DMA_GetITStatus(DMA1_Stream5, DMA_IT_HTIF5)) {
        fHalf = true;
        IsrSrcStat[HCI].HALF++;
    }

    // Streamx transfer complete interrupt
    if (DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5)) {
        fFull = true;
        IsrSrcStat[HCI].FULL++;
    }

    if (fHalf && fFull) {
        IsrSrcStat[HCI].DOUBLE++;
    }

    if (fHalf || fFull) {
        DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_HTIF5);
        DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);
        TM_UartRxHandler(eTM_USART2, TM_IntSrc_FULL);
        //return;
    }

    // Streamx transfer error interrupt
    if (DMA_GetITStatus(DMA1_Stream5, DMA_IT_TEIF5)) {
        IsrSrcStat[HCI].ERR++;
        HciRxError_Transfer++;
        DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TEIF5);
    }

    // Streamx FIFO error interrupt
    if (DMA_GetITStatus(DMA1_Stream5, DMA_IT_FEIF5)) {
        IsrSrcStat[HCI].ERR++;
        HciRxError_FIFO++;
        DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_FEIF5);
    }

    // Streamx direct mode error interrupt
    if (DMA_GetITStatus(DMA1_Stream5, DMA_IT_DMEIF5)) {
        IsrSrcStat[HCI].ERR++;
        HciRxError_DirectMode++;
        DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_DMEIF5);
    }
}





/*******************************************************************************
* Function Name  : DmaWaitMicro
* Description    : Wait for HCI Tx DMA
*******************************************************************************/
#ifdef SEGMENT_TX_DMA
static void DmaWaitMicro(uint32 MicroSec)
{
    u16 PreScale;
    u16 Period;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    RCC_ClocksTypeDef RCC_Clocks;

    // Enable TIM10 clock
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10, ENABLE);

    // Determine timer settings for char timeout
    RCC_GetClocksFreq(&RCC_Clocks);
    PreScale = RCC_Clocks.PCLK2_Frequency / 1000000;
    Period   = PreScale / MicroSec;

    // Set TIM10 timer period 1 sec
    TIM_TimeBaseInitStruct.TIM_Prescaler                    = PreScale-1;
    TIM_TimeBaseInitStruct.TIM_CounterMode                  = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period                       = MicroSec;
    TIM_TimeBaseInitStruct.TIM_ClockDivision                = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter            = 0;
    TIM_TimeBaseInit(TIM10, &TIM_TimeBaseInitStruct);

    // Setup channel
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel                      = TIM1_UP_TIM10_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = TM_LowestPriority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority           = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // Turn on interrupts and timer
    TIM_ClearITPendingBit(TIM10, TIM_FLAG_Update);          // Clear update interrupt bit
    TIM_ITConfig(TIM10, TIM_FLAG_Update, ENABLE);           // Enable update interrupt
    TIM_Cmd(TIM10, ENABLE);                                 // Start timer
}
#endif



/*******************************************************************************
* Function Name  : DMA Stream IRQ Handler
* Description    : Handles HCI USART2 Tx DMA
*******************************************************************************/
void DMA1_Stream6_IRQHandler(void)
{
#ifdef SEGMENT_TX_DMA_DEBUG_PIO
    static bool initialized=false;
    if (!initialized) {
        TM_SetPioAsOutput(SEGMENT_TX_DMA_DEBUG_PIO);
        TM_ResetPio(SEGMENT_TX_DMA_DEBUG_PIO);
        initialized = true;
    }
#endif
    if (DMA_GetITStatus(DMA1_Stream6, DMA_IT_TCIF6)) {
        DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);
#ifdef SEGMENT_TX_DMA
        HciDmaRec.pData += HciDmaRec.SendLength;
        HciDmaRec.TotalLength -= HciDmaRec.SendLength;
        if (HciDmaRec.TotalLength>0)
        {
            DmaWaitMicro(DmaDelay);
#ifdef SEGMENT_TX_DMA_DEBUG_PIO
            TM_SetPio(SEGMENT_TX_DMA_DEBUG_PIO);
#endif
        }
        else {
            TM_DmaSendComplete(eTM_USART2);
        }
#else
        TM_DmaSendComplete(eTM_USART2);
#endif
    }
}

#ifdef CUSTOM_AVDTP
void DMA1_Stream7_IRQHandler(void)
{ 
	/* Transfer complete interrupt */
	if (DMA_GetFlagStatus(DMA1_Stream7, DMA_FLAG_TCIF7) != RESET)
	{
		/* Clear the Interrupt flag */
		DMA_ClearFlag(DMA1_Stream7, DMA_FLAG_TCIF7);
#if defined(BT43S) || defined(BT53S) 
	avdtp_IsrTxChan5(TM_IntSrc_FULL);
#endif
	}

	/* Half Transfer complete interrupt */
	if (DMA_GetFlagStatus(DMA1_Stream7, DMA_FLAG_HTIF7) != RESET)
	{
		/* Clear the Interrupt flag */
		DMA_ClearFlag(DMA1_Stream7, DMA_FLAG_HTIF7);    
#if defined(BT43S) || defined(BT53S)
	avdtp_IsrTxChan5(TM_IntSrc_HALF);
#endif
	}
}
#endif

/*******************************************************************************
* Function Name  : DMA2_Stream2_IRQHandler
* Description    : Handle Main USART1 Rx DMA
*******************************************************************************/
void DMA2_Stream2_IRQHandler(void)
{
    bool fFull=false;
    bool fHalf=false;

    // Streamx half transfer complete interrupt
    if (DMA_GetITStatus(DMA2_Stream2, DMA_IT_HTIF2)) {
        fHalf = true;
        IsrSrcStat[MAIN].HALF++;
    }

    // Streamx transfer complete interrupt
    if (DMA_GetITStatus(DMA2_Stream2, DMA_IT_TCIF2)) {
        fFull = true;
        IsrSrcStat[MAIN].FULL++;
    }

    if (fHalf && fFull) {
        IsrSrcStat[MAIN].DOUBLE++;
    }

    if (fHalf || fFull) {
        DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_HTIF2);
        DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TCIF2);
        TM_UartRxHandler(eTM_USART1, TM_IntSrc_FULL);
        return;
    }

    // Streamx transfer error interrupt
    if (DMA_GetITStatus(DMA2_Stream2, DMA_IT_TEIF2)) {
        IsrSrcStat[MAIN].ERR++;
        MainRxError_Transfer++;
        DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TEIF2);
    }

    // Streamx FIFO error interrupt
    if (DMA_GetITStatus(DMA2_Stream2, DMA_IT_FEIF2)) {
        IsrSrcStat[MAIN].ERR++;
        MainRxError_FIFO++;
        DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_FEIF2);
    }

    // Streamx direct mode error interrupt
    if (DMA_GetITStatus(DMA2_Stream2, DMA_IT_DMEIF2)) {
        IsrSrcStat[MAIN].ERR++;
        MainRxError_DirectMode++;
        DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_DMEIF2);
    }
}



/*******************************************************************************
* Function Name  : DMA2_Stream7_IRQHandler
* Description    : Handle Main USART1 Tx DMA Complete
*******************************************************************************/
void DMA2_Stream7_IRQHandler(void)
{
    if (DMA_GetITStatus(DMA2_Stream7, DMA_IT_TCIF7)) {
        DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF7);
        TM_DmaSendComplete(eTM_USART1);
    }
}




/*******************************************************************************
* Function Name  : USART_SetCharTimeout
* Platform       : Cortex M3
* Description    : Setup TIM1 for char timeout
*******************************************************************************/
void USART_SetCharTimeout(void)
{
    static uint8 state=0;

    if (state==0)
    {
        long Bits = AT_UART_DEFAULT_TIMEOUT;
        long Baud = AT_UART_DEFAULT_BAUDRATE;
        long Freq;
        long Clk;

        if (Bits<=16) {
            // No timer needed for char timeout
            state = 2;
        }
        else {
            // Determine timer settings for char timeout
            TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
            RCC_ClocksTypeDef RCC_Clocks;
            RCC_GetClocksFreq(&RCC_Clocks);
            Bits -= 16;
            Clk = RCC_Clocks.PCLK2_Frequency; // RCC_Clocks.SYSCLK_Frequency;
            Freq = Clk / Baud;

            // Set TIM1 timer period 1 sec
            TIM_TimeBaseInitStruct.TIM_Prescaler            = Freq-1;
            TIM_TimeBaseInitStruct.TIM_CounterMode          = TIM_CounterMode_Up;
            TIM_TimeBaseInitStruct.TIM_Period               = Bits;
            TIM_TimeBaseInitStruct.TIM_ClockDivision        = TIM_CKD_DIV1;
            TIM_TimeBaseInitStruct.TIM_RepetitionCounter    = 0;
            TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct);

            // Setup channel
            NVIC_InitTypeDef NVIC_InitStructure;
            NVIC_InitStructure.NVIC_IRQChannel                      = TIM1_UP_TIM10_IRQn;
            NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = TM_LowestPriority;
            NVIC_InitStructure.NVIC_IRQChannelSubPriority           = 0;
            NVIC_InitStructure.NVIC_IRQChannelCmd                   = ENABLE;
            NVIC_Init(&NVIC_InitStructure);

            TIM_ClearITPendingBit(TIM1, TIM_FLAG_Update);       // Clear update interrupt bit
            TIM_ITConfig(TIM1, TIM_FLAG_Update, ENABLE);        // Enable update interrupt

            state = 1;
        }
    }

    // Enable timer counting for char timeout
    if (state==1)
    {
        TIM1->CNT = 0;
        TIM_Cmd(TIM1, ENABLE);
    }

    // No additional char timeout needed
    else if (state==2)
    {
        TM_UartMainRxHandler(eTM_MainUart, TM_IntSrc_IDLE);
        //GKI_YieldFromISR();
    }
}


/*******************************************************************************
* Function Name  : TIM1_UP_TIM10_IRQHandler - Used for char and DMA seg timeout
* Description    : Up timer used for char and DMA seg timeout.
*******************************************************************************/
void TIM1_UP_TIM10_IRQHandler(void)
{
    // Handle TIM1
    if (TIM_GetITStatus(TIM1, TIM_IT_Update)) {
        TIM_ClearITPendingBit(TIM1, TIM_FLAG_Update);
        TIM_Cmd(TIM1, DISABLE);
        // Character timeout
        TM_UartMainRxHandler(eTM_MainUart, TM_IntSrc_IDLE);
    }

    // Handle TIM10
    if (TIM_GetITStatus(TIM10, TIM_IT_Update)) {
        TIM_ClearITPendingBit(TIM10, TIM_FLAG_Update);
        TIM_Cmd(TIM10, DISABLE);
#ifdef SEGMENT_TX_DMA_DEBUG_PIO
        TM_ResetPio(SEGMENT_TX_DMA_DEBUG_PIO);
#endif
#ifdef SEGMENT_TX_DMA
        HciDmaRec.SendLength = HciDmaRec.TotalLength;
        GKI_dma_StartTxDma(eTM_USART2, HciDmaRec.pData, HciDmaRec.SendLength);
#endif
    }
}


uint16 gCount;
uint16 rxIdleTimeout=0;

extern volatile uint8 SMP_DEBUG;
extern uint8 EncyptedData[16];
volatile uint8 SMP_DEBUG2 = 0;

/*******************************************************************************
* Function Name  : USART_IRQHandler - Main and HCI Uart
* Description    : This function handles USART global interrupt request.
*******************************************************************************/
void USART_IRQHandler(uint16 u)
{
    uint16          StatusRegister, DataRegister;
    uint16          Count;

    // Read status register
    StatusRegister = UART[u]->SR;

    //---------------------------------------------------------
    //  Idle line detection - Main Uart
    //---------------------------------------------------------
    if (USART_GetITStatus(UART[u], USART_IT_IDLE))
    {
        IsrSrcStat[u].IDLE++;
        DataRegister = UART[u]->DR;  // Clear status flags
        Count = TM_DmaRxCount(u);
		#ifdef LE_STK
		if(SMP_DEBUG && (u == eTM_HciUart)){
			uint8 data[64] = {0};
			TM_CopyDmaBuf2(u, data, Count);
			#ifdef LE_SM_DEBUG_CONFIG
			PRINT_MEM_HEX("Le encyption return-> ", data, Count);
			#endif
			memcpy(EncyptedData, data+7, 16);
			SMP_DEBUG = 0;
		}
		#endif
        if (Count)
        {   // Handle Rx message
            if (u==eTM_MainUart) {
                rxIdleTimeout++;
                TM_UartMainRxHandler(u, TM_IntSrc_IDLE);
            }
            else {
                TM_UartHciRxHandler(u, TM_IntSrc_IDLE);
            }
        }
    }

    //---------------------------------------------------------
    //  Transmit Data Register empty / Transmission complete
    //---------------------------------------------------------
    else if (USART_GetITStatus(UART[u], USART_IT_TXE) ||
             USART_GetITStatus(UART[u], USART_IT_TC))
    {
        IsrSrcStat[u].RXNE++;
        TM_UartTxHandler(u);

        // Clear status flags
        DataRegister = UART[u]->DR;
    }

    //---------------------------------------------------------
    //  CTS change detected
    //---------------------------------------------------------
    else if (USART_GetITStatus(UART[u], USART_IT_CTS))
    {
        USART_ClearFlag(UART[u], USART_FLAG_CTS);
    }

    //---------------------------------------------------------
    //  Rx Buffer Not Empty (Full) - Main Uart
    //---------------------------------------------------------
#ifndef CUSTOM_USE_RXNE
    else if (USART_GetITStatus(UART[u], USART_IT_RXNE))
    {
        DataRegister = UART[u]->DR;  // Clear status flags
        Count = TM_DmaRxCount(u);
        if (Count)
        {   // Handle Rx message
            if (u==eTM_MainUart) {
                //USART_SetCharTimeout();

                TM_UartMainRxHandler(u, TM_IntSrc_FULL);
                //USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
            }
            else {
                TM_UartHciRxHandler(u, TM_IntSrc_FULL);
            }
        }
    }
#endif

    //---------------------------------------------------------
    //  We shouldn't be here -- Clear status flags
    //---------------------------------------------------------
    else  {
        IsrSrcStat[u].ERR++;
       // DataRegister = UART[u]->DR;
    }

    //testcode
    gCount = Count;
}

/*******************************************************************************
* Function Name  : USART1_IRQHandler - Main Uart
* Description    : This function handles USART1 global interrupt request.
*******************************************************************************/
void USART1_IRQHandler(void)
{
#ifndef CUSTOM_I2S
    USART_IRQHandler(eTM_USART1);
#else
#define UART_RX_BUF_SIZE 200
    uint16 u=eTM_MainUart;
    //uint16 StatusRegister;
    uint16 DataRegister;
    static uint8  charbuf[UART_RX_BUF_SIZE];
    static uint16 buflen=0;

    //---------------------------------------------------------
    //  Handle RXNE
    //---------------------------------------------------------
    if (USART_GetITStatus(USART1, USART_IT_RXNE))
    {
        while ((UART[u]->SR & USART_FLAG_RXNE) && (buflen < UART_RX_BUF_SIZE)) {
            charbuf[buflen++] = UART[u]->DR;
        }
        if (buflen>=UART_RX_BUF_SIZE)  {
            AT_UartRxCallBack2(charbuf, buflen);
            buflen = 0;
        }
        USART_ITConfig(UART[u], USART_IT_IDLE, ENABLE);
    }


    //---------------------------------------------------------
    //  Idle line detection - Main Uart
    //  Handle RX full
    //---------------------------------------------------------
    if (USART_GetITStatus(USART1, USART_IT_IDLE))
    {
        if (buflen>0) {
            AT_UartRxCallBack2(charbuf, buflen);
            buflen = 0;
        }
        USART_ITConfig(UART[u], USART_IT_IDLE, DISABLE);
    }


    //---------------------------------------------------------
    //  Transmit Data Register empty / Transmission complete
    //---------------------------------------------------------
    else if (USART_GetITStatus(UART[u], USART_IT_TXE) ||
             USART_GetITStatus(UART[u], USART_IT_TC))
    {
        TM_UartTxHandler(u);
        // Clear status flags
        DataRegister = UART[u]->DR;
    }

    //---------------------------------------------------------
    //  CTS change detected
    //---------------------------------------------------------
    else if (USART_GetITStatus(UART[u], USART_IT_CTS))
    {
        USART_ClearFlag(UART[u], USART_FLAG_CTS);
    }


    //---------------------------------------------------------
    //  We shouldn't be here -- Clear status flags
    //---------------------------------------------------------
    else  {
        DataRegister = UART[u]->DR;
    }
#endif
}


/*******************************************************************************
* Function Name  : USART2_IRQHandler - HCI Uart
* Description    : This function handles USART2 global interrupt request.
*******************************************************************************/
void USART2_IRQHandler(void)
{
    USART_IRQHandler(eTM_USART2);
}




/*******************************************************************************
* Function Name  : TIM2_IRQHandler
* Description    : This function handles TIM2 global interrupt request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
volatile uint8 entropy_pool[64];
uint8 entrop_fetching_idx;
uint8 entrop_input_idx;
void get_info_from_entropy_pool(uint8 *buf, uint8 len)
{
	uint8 idx;
	for(uint8 i=0; i<len; i++){
	  	idx = (i + entrop_fetching_idx) & 0x3f;
		*(buf+i) = entropy_pool[idx];
	}
	entrop_fetching_idx = idx;
}
void TIM2_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
    {
        // Clear TIM2 Capture Compare1 interrupt pending bit
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
        TM_TimeoutIsrRTS();

		uint32 temp = TIM2->CNT;
		entropy_pool[entrop_input_idx] = temp & 0x000000ff;
		entrop_input_idx = (entrop_input_idx+1) & 0x3f;
    }
}


/*******************************************************************************
* Function Name  : SPI2_IRQHandler
*******************************************************************************/
void SPI2_IRQHandler(void) // Master - Receive
{
#ifndef SDK
#ifndef CUSTOM_LITE
    extern uint32 spiIsr;
    extern uint32 spiIsrNE;

#ifndef CUSTOM_I2S
    if (SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_RXNE) == SET)
    {
        spiIsrNE++;
        TM_SpiHandler();
    }
    else {
        spiIsr++;
        TM_SpiHandler();
    }
#endif // CUSTOM_I2S
#endif // CUSTOM_LITE
#endif // SDK
}


/*******************************************************************************
* Watchdog handler
*******************************************************************************/
void WWDG_IRQHandler(void)
{
    GKI_WatchdogISR();
}

/******************************************************************************/
/*                 STM32F4xx Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f429_439xx.s).                                               */
/******************************************************************************/

/**
  * @brief  This function handles PPP interrupt request.
  * @param  None
  * @retval None
  */
/*void PPP_IRQHandler(void)
{
}*/


/**
  * @}
  */


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
