/**
  **********************************************************************************
             Copyright(c) 2021 China Core Co. Ltd.
                      All Rights Reserved
  **********************************************************************************
  * @file    can_hal.c
  * @author  Product application department
  * @version V1.0
  * @date    2021.09.28
  * @brief   CAN模块HAL层驱动.
  *
  @verbatim
  ===================================================================================
                                  ##### 更新 #####
  ===================================================================================
  [..] 更新时间:
  [..] 更新人:
  [..] 更新内容:
        1. nothing.
  @endverbatim
*/

#include "can_hal.h"
#include "sys.h"  
#include "debug.h"

#define CAN_MAX_NUM   1

/*** 全局变量定义 ***************************************************************/
/*** 全局变量定义 ***************************************************************/
/**@ volatile
  *@{
  */

/**@
  *@}
  */

/**@ static
  *@{
  */
static CAN_HandleTypeDef *g_hcan[CAN_MAX_NUM];
/**@
  *@}
  */
/*** 常量定义 *******************************************************************/
/**@ const
  *@{
  */
/**@
  *@}
  */
/**
  *@brief 将DRV层状态转化为HAL层的状态.
  *-
  *@param[in] DrvStatus驱动层状态，参见@ref DRV_IIC_StatusTypeDef
  *@retval @ref HAL_StatusTypeDef
  */
static HAL_StatusTypeDef DrvStatusToHalStatus(DRV_CAN_StatusTypeDef DrvStatus)
{
    switch(DrvStatus)
    {
        case DRV_CAN_OK:
        {
            return(HAL_OK);
        }

        case DRV_CAN_ERROR:
        {
            return(HAL_ERROR);
        }

        case DRV_CAN_BUSY:
        {
            return(HAL_BUSY);
        }

        case DRV_CAN_TIMEOUT:
        {
            return(HAL_TIMEOUT);
        }
    }
}

/**
  * @brief  Initializes the CAN MSP.
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
  *         the configuration information for the specified CAN.  
  * @retval None
  */
__weak void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
    
}

/**
  *@brief 恢复CAN模块到初始状态.
  *
  @param[in] hcan  指向CAN_HandleTypeDef结构体的指针,此结构体包含了CAN模块的配置信息;
  *@retval @ref HAL_StatusTypeDef
  */
HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef *hcan)
{
    hcan->State = HAL_CAN_STATE_BUSY;

    /**/
    DRV_CAN_DeInit(hcan->Instance);

    hcan->pRxMsg = NULL;
    hcan->pTxMsg = NULL;
    
    hcan->ErrorCode = HAL_CAN_ERROR_NONE;
    hcan->State = HAL_CAN_STATE_RESET;
	
	  
	  if ((hcan->Init.TransmitInterrupt == ENABLE) || (hcan->Init.ReceiveInterrupt == ENABLE))
		{
				NVIC_DisableIRQ(CAN1_BUF32_63_IRQn);
				NVIC_DisableIRQ(CAN1_BUF16_31_IRQn);
				NVIC_DisableIRQ(CAN1_BUF12_15_IRQn);
				NVIC_DisableIRQ(CAN1_BUF08_11_IRQn);
				NVIC_DisableIRQ(CAN1_BUF04_07_IRQn);
				NVIC_DisableIRQ(CAN1_BUF00_03_IRQn);
		}

    return(HAL_OK);
}

/**
  * @brief  Initializes the CAN peripheral according to the specified
  *         parameters in the CAN_InitStruct.
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
  *         the configuration information for the specified CAN.  
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef* hcan)
{
    HAL_StatusTypeDef st;
    /* Check CAN handle */
    if(hcan == NULL)
    {
        return HAL_ERROR;
    }
  
    if(hcan->State == HAL_CAN_STATE_RESET)
    {
        HAL_CAN_MspInit(hcan);
    }

    /* Initialize the CAN state*/
    hcan->State = HAL_CAN_STATE_BUSY;
    
    st = DrvStatusToHalStatus(DRV_CAN_Init(hcan->Instance, &hcan->Init));
    if (st != HAL_OK)
    {
        return st;
    }
    
    if (hcan->Instance == CAN1)
    {
        g_hcan[0] = hcan;
    }
    else 
    {
        return HAL_ERROR;
    }
    if ((hcan->Init.TransmitInterrupt == ENABLE) || (hcan->Init.ReceiveInterrupt == ENABLE))
	{
		NVIC_Init(3, 3, CAN1_BUF32_63_IRQn, 3);
		NVIC_Init(3, 3, CAN1_BUF16_31_IRQn, 3);
		NVIC_Init(3, 3, CAN1_BUF12_15_IRQn, 3);
		NVIC_Init(3, 3, CAN1_BUF08_11_IRQn, 3);
		NVIC_Init(3, 3, CAN1_BUF04_07_IRQn, 3);
		NVIC_Init(3, 3, CAN1_BUF00_03_IRQn, 3);
	}
    hcan->ErrorCode = HAL_CAN_ERROR_NONE;
    hcan->State = HAL_CAN_STATE_READY;
    
    return(HAL_OK);
}


/**
  *@brief 通过指定的CAN端口发送数据.
  *
  @param[in] hspi  指向CAN_HandleTypeDef结构体的指针,此结构体包含了CAN模块的配置信息;
  @param[in] pData   待发送数据指针;
  @param[in] Size     待发送数据长度;
  @param[in] Timeout 超时时间;
  *@retval @ref HAL_StatusTypeDef
  */
HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout)
{
    HAL_StatusTypeDef st;    

    if(hcan->State != HAL_CAN_STATE_READY)
    {
        return(HAL_ERROR);
    }

    hcan->State = HAL_CAN_STATE_BUSY_TX;
    hcan->ErrorCode = HAL_CAN_ERROR_NONE;
    
    st = DrvStatusToHalStatus(DRV_CAN_TransmitBytes(hcan->Instance, hcan->pTxMsg, Timeout));
    if (st != HAL_OK)
    {
        return st;
    }   

    hcan->State = HAL_CAN_STATE_READY;
  
    return(HAL_OK);
}

/**
  *@brief 通过指定的CAN端口中断发送数据.
  *
  @param[in] hspi  指向CAN_HandleTypeDef结构体的指针,此结构体包含了CAN模块的配置信息;
  @param[in] pData   待发送数据指针;
  @param[in] Size     待发送数据长度;
  @param[in] Timeout 超时时间;
  *@retval @ref HAL_StatusTypeDef
  */
HAL_StatusTypeDef HAL_CAN_TransmitIT(CAN_HandleTypeDef *hcan, uint32_t Timeout)
{
    HAL_StatusTypeDef st;    

    if(hcan->State != HAL_CAN_STATE_READY)
    {
        return(HAL_ERROR);
    }

    hcan->State = HAL_CAN_STATE_BUSY_TX;
    hcan->ErrorCode = HAL_CAN_ERROR_NONE;
    
    st = DrvStatusToHalStatus(DRV_CAN_TransmitBytesIT(hcan->Instance, hcan->pTxMsg, Timeout));
    if (st != HAL_OK)
    {
        return st;
    }   

    hcan->State = HAL_CAN_STATE_READY;
  
    return(HAL_OK);
}

/**
  *@brief 通过指定的CAN端口接收数据.
  *
  @param[in] hspi  指向CAN_HandleTypeDef结构体的指针,此结构体包含了CAN模块的配置信息;
  @param[in] pData   待发送数据指针;
  @param[in] Size     待发送数据长度;
  @param[in] Timeout 超时时间;
  *@retval @ref HAL_StatusTypeDef
  */
HAL_StatusTypeDef HAL_CAN_Receive(CAN_HandleTypeDef *hcan, uint32_t Timeout)
{
    HAL_StatusTypeDef st;    

    if(hcan->State != HAL_CAN_STATE_READY)
    {
        return(HAL_ERROR);
    }

    hcan->State = HAL_CAN_STATE_BUSY_TX;
    hcan->ErrorCode = HAL_CAN_ERROR_NONE;
    
    if (hcan->Init.FEN == ENABLE)
    {
        st = DrvStatusToHalStatus(DRV_CAN_FIFO_ReceiveBytes(hcan->Instance, hcan->pRxMsg, hcan->RxSize, Timeout));
    }
    else
    {
        st = DrvStatusToHalStatus(DRV_CAN_ReceiveBytes(hcan->Instance, hcan->pRxMsg, hcan->RxSize, Timeout));
    }
    
    if (st != HAL_OK)
    {
        return st;
    }   

    hcan->State = HAL_CAN_STATE_READY;
  
    return(HAL_OK);
}


/**
  *@brief 通过指定的CAN端口接收数据.
  *
  @param[in] hspi    指向CAN_HandleTypeDef结构体的指针,此结构体包含了CAN模块的配置信息;
  @param[in] pData   待发送数据指针;
  @param[in] Size    待发送数据长度;
  @param[in] Timeout 超时时间;
  *@retval @ref HAL_StatusTypeDef
  */
HAL_StatusTypeDef HAL_CAN_ReceiveIT(CAN_HandleTypeDef *hcan, uint32_t Timeout)
{
    HAL_StatusTypeDef st;    

    if(hcan->State != HAL_CAN_STATE_READY)
    {
        return(HAL_ERROR);
    }

    hcan->State = HAL_CAN_STATE_BUSY_TX;
    hcan->ErrorCode = HAL_CAN_ERROR_NONE;
		
    //printf("hcan->Init.FEN = %d\r\n", hcan->Init.FEN);
		
    if (hcan->Init.FEN == ENABLE)
    {
        st = DrvStatusToHalStatus(DRV_CAN_FIFO_ReceiveBytesIT(hcan->Instance, hcan->pRxMsg, hcan->RxSize, Timeout));
    }
    else
    {
        st = DrvStatusToHalStatus(DRV_CAN_ReceiveBytesIT(hcan->Instance, hcan->pRxMsg, hcan->RxSize, Timeout));
    }
    
    if (st != HAL_OK)
    {
        return st;
    }   

    hcan->State = HAL_CAN_STATE_READY;
  
    return(HAL_OK);
}

/**
  * @brief CAN1中断服务函数.
  *
  * @param [in] 
  * @return
  * - NONE
  * @note
  * @warning
  */
void HAL_CAN_IRQHandler(uint8_t can_channel)
{
    uint32_t mb_int_flag0 = 0;
    uint32_t mb_int_flag1 = 0;
    mb_int_flag0 = _can_get_mb0_31_int_flag(g_hcan[can_channel]->Instance);
    mb_int_flag1 = _can_get_mb32_63_int_flag(g_hcan[can_channel]->Instance);
    
	/*如果中断源是MB*/
    if (mb_int_flag0 || mb_int_flag1)
    {
        if (g_hcan[can_channel]->MBIsrCallback != NULL)
        {
            g_hcan[can_channel]->MBIsrCallback((void*)g_hcan[can_channel]);
        }
        else
        {
            _can_clr_mb0_31_int_flag(g_hcan[can_channel]->Instance, mb_int_flag0);
            _can_clr_mb32_63_int_flag(g_hcan[can_channel]->Instance, mb_int_flag1);
        }
	}
    /*handle bus off interrupt*/
    if (_can_get_buss_off_int_flag(g_hcan[can_channel]->Instance))
    {
        _can_clr_buss_off_int_flag(g_hcan[can_channel]->Instance);
        if (g_hcan[can_channel]->BOFFCallback != NULL)
        {
            g_hcan[can_channel]->BOFFCallback((void*)g_hcan[can_channel]);
        }
    }
    /*handle receive warning interrupt*/
    if (_can_get_rwrn_int_flag(g_hcan[can_channel]->Instance))
    {
        _can_clr_rwrn_int_flag(g_hcan[can_channel]->Instance);
        if (g_hcan[can_channel]->RwrnCallback != NULL)
        {
            g_hcan[can_channel]->RwrnCallback((void*)g_hcan[can_channel]);
        }        
    }    
    /*handle transmit warning interrupt*/
    if (_can_get_twrn_int_flag(g_hcan[can_channel]->Instance))
    {
        _can_clr_twrn_int_flag(g_hcan[can_channel]->Instance);
        if (g_hcan[can_channel]->TwrnCallback != NULL)
        {
            g_hcan[can_channel]->TwrnCallback((void*)g_hcan[can_channel]);
        }        
    } 
    /*handle error interrupt*/
    if (_can_get_err_int_flag(g_hcan[can_channel]->Instance))
    {
        _can_clr_err_int_flag(g_hcan[can_channel]->Instance);
        if (g_hcan[can_channel]->ErrCallback != NULL)
        {
            g_hcan[can_channel]->ErrCallback((void*)g_hcan[can_channel]);
        }        
    } 
    
}


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