
#ifndef J1939_TP_C_
#define J1939_TP_C_

#include"j1939_queue.h"
#include"j1939.h"
//#include "RTE_APP.h"
#include "j1939_tools.h"
//函数声明
J1939Result J1939_TpCM_RTS(J1939Context* J1939_PAGED context, J1939TpSession* J1939_PAGED tx_session);
J1939Result J1939_TpCM_CTS(J1939Context* J1939_PAGED context, J1939TpSession* J1939_PAGED rx_session);
J1939Result J1939_TpCM_Abort(J1939Context* J1939_PAGED context, uint8_T dest_addr, uint32_T pgn,uint8_T source_addr);
J1939Result J1939_TpCM_EndAck(J1939Context* J1939_PAGED context, J1939TpSession* J1939_PAGED rx_session);
J1939Result J1939_TpCM_BAM(J1939Context* J1939_PAGED context, J1939TpSession* J1939_PAGED tx_session);
J1939Result J1939_TpCM_CTS_Resend(J1939Context* J1939_PAGED context, J1939TpSession* J1939_PAGED rx_session);

/*****************************************************************************
 *函数名称:J1939_TpTxSessionCreate
 *函数功能:J1939创建发送TPSession
 *参    数:J1939Context* J1939_PAGED context   J1939内容指针
 *         const J1939TxMsg* J1939_PAGED msg要发送J1939信息指针
 *返 回 值:J1939_OK成功,其他失败
 *作    者:Admin
 *修订信息:
 ******************************************************************************/
J1939Result J1939_TpTxSessionCreate(J1939Context* J1939_PAGED context, const J1939Msg* J1939_PAGED msg)
{
	//OS_CPU_SR cpu_sr = 0;
	uint32_T now_tick = get_tick_count();
	//检查参数
	if ((context == NULL) && (msg == NULL))
	{
		return J1939_PTR_NULL;
	}

	if (context->tp_tx_session.is_open == TRUE)
	{
		return J1939_TP_TX_SESSION_BUSY;
	}

	context->tp_tx_session.msg.id.value = msg->id.value;
	context->tp_tx_session.msg.pgn = msg->pgn;

	//判断长度
	if (msg->msg_len > msg->msg_max_len)
	{
		context->tp_tx_session.msg.msg_len = msg->msg_max_len;
	}
	else
	{
		context->tp_tx_session.msg.msg_len = msg->msg_len;
	}

	context->tp_tx_session.msg.dest_addr = msg->dest_addr;
	context->tp_tx_session.msg.source_addr = msg->source_addr;

	J1939_BufferCopy( context->tp_tx_session.msg.data,  msg->data, context->tp_tx_session.msg.msg_len);

	//更新状态
	context->tp_tx_session.frame_cnt = (uint8_T) ((context->tp_tx_session.msg.msg_len + 6) / 7);
	context->tp_tx_session.last_tick = now_tick;
	context->tp_tx_session.start_frame = 1;
	context->tp_tx_session.frame_index = 1;
	context->tp_tx_session.end_frame = context->tp_tx_session.frame_cnt;
	context->tp_tx_session.status = kTp_RTS;
	context->tp_tx_session.is_open = TRUE;
//	if (msg->dest_addr == 0xFF)
//	{
//		context->tp_tx_session.time_out = J1939_BAM_TX_TIME_INTERVAL;
//		context->tp_tx_session.is_bam = TRUE;
//	}
//	else
	{
		context->tp_tx_session.time_out = J1939_T3_TIMEOUT;
		context->tp_tx_session.is_bam = FALSE;
	}
	return J1939_OK;
}
/*****************************************************************************
 *函数名称:J1939_TpTxSessionDestroy
 *函数功能:销毁J1939发送TPSession
 *参    数:J1939TpSession* J1939_PAGED session
 *返 回 值:J1939_OK成功,其他失败
 *作    者:Admin
 *修订信息:
 ******************************************************************************/
void J1939_TpTxSessionDestroy(J1939TpSession* J1939_PAGED session)
{
    //OS_CPU_SR cpu_sr=0;
    //检查参数
    if(session == NULL)
    {
        return;
    }

    
    if(session->is_open == FALSE)
    {
       
        return;
    }
    //清缓存
    session->is_bam = 0;
	session->frame_cnt = 0; 
	session->max_tx_frame_num = 0;
	session->frame_index = 0; 
	session->frame_err_flag = 0;
	session->start_frame = 0;
	session->end_frame = 0;
	session->last_tick = 0;
	session->time_out = 0;
    session->msg.id.value = 0;
    session->msg.pgn = 0;
	session->msg.dest_addr = 0;
	session->msg.source_addr = 0;
	session->msg.msg_len = 0;
    session->is_open = FALSE;
    session->status =  kTp_IDLE;
    return;   
    
}

/*****************************************************************************
*函数名称:J1939_TpTxFrameData
*函数功能:J1939通过TP发送多包CAN数据帧
*参    数:J1939Context* J1939_PAGED context   J1939内容指针
*        J1939TpSession* J1939_PAGED session
*返 回 值:J1939_OK成功,其他失败
*作    者:Admin
*修订信息:
******************************************************************************/
J1939Result J1939_TpTxFrameData(J1939Context* J1939_PAGED context,J1939TpSession* J1939_PAGED session)
{
	J1939CanFrame frame;

	//传参错误
	if ((context == NULL) || (session == NULL))
	{
		return J1939_PTR_NULL;
	}

	frame.id.Bits.NA = 0;
#if 0
    if(session->msg.source_addr!=0xF4)
    {
      frame.id.Bits.P = J1939_MSG_DEFAULT_PRI;
    }else
    {
	frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
    }
#else
    frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
#endif
    
	frame.id.Bits.R = 0;
	frame.id.Bits.DP = GET_PGN_DP(J1939_PGN_TP_DATA);
	frame.id.Bits.PF = GET_PGN_PF(J1939_PGN_TP_DATA);
	frame.id.Bits.PS = session->msg.dest_addr;
	frame.id.Bits.SA = session->msg.source_addr;
    frame.mode = kCanExtendMode;
    J1939_BufferSet( &frame.data[0], 0xFF ,8);
	if ((session->frame_index > 0) && (session->frame_index < session->frame_cnt + 1))
	{
		//帧长度判断
		if (session->frame_index != session->frame_cnt)
		{
			frame.data_len = J1939_CAN_FRAME_DATA_LEN;
		}
		//最后一帧
		else
		{
			frame.data_len = session->msg.msg_len - ((uint16_T)session->frame_index - 1) * 7 + 1;
			if (frame.data_len > J1939_CAN_FRAME_DATA_LEN)
			{
				frame.data_len = J1939_CAN_FRAME_DATA_LEN;
			}
		}

		frame.data[0] = session->frame_index;
		J1939_BufferCopy( &frame.data[1],  (session->msg.data + ((uint16_T)session->frame_index - 1) * 7), frame.data_len - 1);
		if (frame.data_len < J1939_CAN_FRAME_DATA_LEN)
		{
			frame.data_len = J1939_CAN_FRAME_DATA_LEN;
                }
		//DT发送完成
		if (session->frame_index == session->frame_cnt)
		{
			if (session->is_bam == TRUE)
			{
				(void)J1939_TpTxSessionDestroy(session);
				session->status = kTp_IDLE;
			}
			else
			{
				//等待ENDACK
				session->status = kTp_END;
			}
		}
		else
		{
			if (session->is_bam == TRUE)
			{
				session->frame_index++;
			}
			else
			{
				//DT未发送完成，等待CTS
				if (session->frame_index == session->end_frame)
				{
					session->time_out = J1939_T3_TIMEOUT;
					session->status = kTp_CTS;
				}
				else
				{
					session->frame_index++;
				}
			}
		}
		return J1939_PushCanFrameToQueue(&context->tx_frame_tmp_queue, &frame);
	}
	else//帧编号异常，结束通信
	{
		(void)J1939_TpTxSessionDestroy(session);
		session->status = kTp_ABORT;
		return J1939_TP_FRAME_NUM_ERROR;
	}
}
/*****************************************************************************
*函数名称:J1939_TpTxStatusUpdate
*函数功能:通过接收到的消息命令来更新发送TP状态
*参    数:J1939Context* J1939_PAGED context   J1939内容指针
*         const J1939CanFrame* J1939_PAGED rx_frame 接收到CAN数据帧的指针
*返 回 值:J1939_OK成功,其他失败
*作    者:Admin
*修订信息:
******************************************************************************/
void J1939_TpTxStatusUpdate(J1939Context* J1939_PAGED context,const J1939CanFrame* J1939_PAGED frame)
{
    //uint16_T byte_cnt = 0;
    uint32_T pgn = 0;
    uint32_T now_tick = get_tick_count();
    
	//传参错误
    if((context == NULL)||(frame == NULL))
    {
        return;
    }
    if(context->tp_tx_session.is_open == FALSE)
    {
        return;
    }
    
    //byte_cnt = ((uint16_T)frame->data[2] << 8) + frame->data[1];
    pgn = ((uint32_T)frame->data[7]<<16)+((uint16_T)frame->data[6]<<8)+frame->data[5];
     
   if((context->tp_tx_session.msg.dest_addr != frame->id.Bits.SA)||
      (context->tp_tx_session.msg.pgn != pgn))
   {
        return;
   }

    switch(frame->data[0])
    {
    	//CTS报文
        case J1939_TP_CM_CTS:
            context->tp_tx_session.last_tick = now_tick;
            context->tp_tx_session.time_out =  J1939_TP_DATA_TX_TIME_INTERVAL;
            context->tp_tx_session.start_frame = frame->data[2];
            context->tp_tx_session.frame_index = context->tp_tx_session.start_frame;
            context->tp_tx_session.end_frame = frame->data[2] + frame->data[1] - 1;
            if(context->tp_tx_session.end_frame > context->tp_tx_session.frame_cnt)
            {
                context->tp_tx_session.end_frame = context->tp_tx_session.frame_cnt;
            }
            if(context->tp_tx_session.status == kTp_CTS)
            {
                context->tp_tx_session.status = kTp_DT;
            }
        break;
        //CM_END 报文
        case J1939_TP_CM_END:
            if(context->tp_tx_session.frame_cnt == frame->data[3])
            {   
                J1939_TpTxSessionDestroy(&context->tp_tx_session);
			    context->tp_tx_session.status = kTp_IDLE;
            }
        break;
        //取消
        case J1939_TP_CM_ABORT:  
            J1939_TpTxSessionDestroy(&context->tp_tx_session);
            context->tp_tx_session.status = kTp_ABORT;
        break;
        default:

        break;
    }
}
/*****************************************************************************
*函数名称:J1939_TPTxMsg
*函数功能:发送TP过程
*参    数:J1939Context* J1939_PAGED context   J1939内容指针
*返 回 值:J1939_OK成功,其他失败
*作    者:Admin
*修订信息:
******************************************************************************/
J1939Result J1939_TPTxMsg(J1939Context* J1939_PAGED context)
{
    J1939Result result = J1939_OK;
    uint32_T tick_elap = 0;
    uint32_T now_tick = get_tick_count();
    
    //检查参数
    if(context == NULL)
    {
        return J1939_PTR_NULL;
    }
    //会话未开启
    if(context->tp_tx_session.is_open == FALSE)
    {
        return J1939_TP_TX_SESSION_NOT_OPEN;
    }

    switch(context->tp_tx_session.status)
    {
        case kTp_IDLE:
            break;
            
            //发送RTS
        case kTp_RTS:
            if(context->tp_tx_session.is_bam == TRUE) 
            {//广播
            	result = J1939_TpCM_BAM(context, &context->tp_tx_session);
               context->tp_tx_session.status = kTp_DT; 
            } 
            else 
            {//特定目标
            	result = J1939_TpCM_RTS(context, &context->tp_tx_session);
                context->tp_tx_session.status = kTp_CTS;
            }
            break;
            
            //等待CTS
        case kTp_CTS:
        	//超时计数
            tick_elap = get_interval_by_tick(context->tp_tx_session.last_tick, now_tick);
            if(tick_elap >= context->tp_tx_session.time_out)
            {
            	J1939_TpTxSessionDestroy(&context->tp_tx_session);
            	context->tp_tx_session.status = kTp_ABORT;
                result = J1939_WAIT_CTS_TIMEOUT;
            }
            break;
        case kTp_DT:
        	//超时计数
            tick_elap = get_interval_by_tick(context->tp_tx_session.last_tick, now_tick);
            if(tick_elap >= context->tp_tx_session.time_out)
            {
                context->tp_tx_session.last_tick = now_tick; 
                if(context->tp_tx_session.is_bam == TRUE) 
                {
                    context->tp_tx_session.time_out = J1939_BAM_TX_TIME_INTERVAL;
                }
                else
                {
                    context->tp_tx_session.time_out = J1939_TP_DATA_TX_TIME_INTERVAL;
                }
                result = J1939_TpTxFrameData(context,&context->tp_tx_session);
            }
            break;
        case kTp_END:
        	//超时计数
            tick_elap = get_interval_by_tick(context->tp_tx_session.last_tick, now_tick);
            if(tick_elap >= context->tp_tx_session.time_out)
            {
            	J1939_TpTxSessionDestroy(&context->tp_tx_session);
            	context->tp_tx_session.status = kTp_ABORT;
                return J1939_WAIT_ENDACK_TIMEOUT;
            }
            break;
            
        case kTp_ABORT:  
            J1939_TpTxSessionDestroy(&context->tp_tx_session); 
			context->tp_tx_session.status = kTp_IDLE;
            break;
                        
        default:
            break;
    }
    return result;
}
/*****************************************************************************
*函数名称:J1939_SearchFreeRxTpSession
*函数功能:J1939根据源地址查找对应的TPSession
*参    数:const J1939Context* J1939_PAGED context J1939内容指针
*         uint8_T addr
*返 回 值:0xFF表示没有查到,其他值为TP号
*作    者:Admin
*修订信息:
******************************************************************************/
uint8_T J1939_SearchFreeRxTpSession(const J1939Context* J1939_PAGED context, uint8_T addr)
{
    uint8_T  i = 0;

    //检查参数
    if(context == NULL)
    {
        return 0xFF;
    }

    for(i=0; i < J1939_TP_RX_SESSION_NUM; i++)
    {
        if((context->tp_rx_session[i].is_open == TRUE)&&
        (context->tp_rx_session[i].msg.source_addr == addr))
        {
            return i;
        }
    }
    return 0xFF;
}
/*****************************************************************************
*函数名称:J1939_GetFreeRxTpSession
*函数功能:获取J1939没有使用过的TPSession
*参    数:const J1939Context* J1939_PAGED context J1939内容指针
*返 回 值:0xFF表示没有查到,其他值为TP号
*作    者:Admin
*修订信息:
******************************************************************************/
uint8_T J1939_GetFreeRxTpSession(const J1939Context* J1939_PAGED context)
{
     uint8_T  i = 0;

     for(i=0; i < J1939_TP_RX_SESSION_NUM; i++)
     {
        if(context->tp_rx_session[i].is_open == FALSE)
        {
            return i;
        }
     }
     return 0xFF;
}
/*****************************************************************************
*函数名称:J1939_RxTpSessionDestroy
*函数功能:释放J1939使用过的TPSession
*参    数:const J1939Context* J1939_PAGED context J1939内容指针
*         uint8_T tp_index tp编号
*返 回 值:无
*作    者:Admin
*修订信息:
******************************************************************************/
J1939Result J1939_RxTpSessionCreate(J1939Context* J1939_PAGED context, uint8_T tp_index,const J1939CanFrame* J1939_PAGED rx_frame)
{
    uint16_T byte_num = 0;//字节数
	uint8_T frame_num = 0;//帧数
    uint32_T pgn = 0;
	uint32_T now_tick = get_tick_count();

	//检查参数
	if ((context == NULL) || (rx_frame == NULL))
	{
		return J1939_PTR_NULL;
	}
	if (tp_index >= J1939_TP_RX_SESSION_NUM)
	{
		return J1939_TP_RX_SESSION_FULL;
	}

	byte_num = ((uint16_T) rx_frame->data[2] << 8) + rx_frame->data[1];
	frame_num = rx_frame->data[3];
	pgn = ((uint32_T) rx_frame->data[7] << 16) + ((uint16_T) rx_frame->data[6] << 8) + rx_frame->data[5];
	if (byte_num > context->rx_msg_max_len)
	{
		return J1939_MSG_LEN_TO_LONG;
	}

	//每帧CAN数据长度为7
	if (frame_num != ((byte_num + 6) / 7))
	{
		return J1939_TP_FRAME_NUM_ERROR;
	}

	context->tp_rx_session[tp_index].is_open = TRUE;
	context->tp_rx_session[tp_index].msg.pgn = pgn;
	context->tp_rx_session[tp_index].msg.msg_len = byte_num;
	context->tp_rx_session[tp_index].msg.source_addr = rx_frame->id.Bits.SA;
	context->tp_rx_session[tp_index].msg.dest_addr = rx_frame->id.Bits.PS;
		
	context->tp_rx_session[tp_index].msg.id.Bits.DP = 0;
	context->tp_rx_session[tp_index].msg.id.Bits.R = 0;
	//优先级
	context->tp_rx_session[tp_index].msg.id.Bits.P = J1939_MSG_DEFAULT_PRI;
	context->tp_rx_session[tp_index].msg.id.Bits.NA = 0; //空
	context->tp_rx_session[tp_index].msg.id.Bits.PF = GET_PGN_PF(pgn); //PF
	context->tp_rx_session[tp_index].msg.id.Bits.PS = rx_frame->id.Bits.PS;
	context->tp_rx_session[tp_index].msg.id.Bits.SA = rx_frame->id.Bits.SA;
	
	context->tp_rx_session[tp_index].last_tick = now_tick;
	context->tp_rx_session[tp_index].start_frame = 1;
	context->tp_rx_session[tp_index].frame_index = 1;
	//总帧数
	context->tp_rx_session[tp_index].frame_cnt = frame_num;
	//最大发送能力
	context->tp_rx_session[tp_index].max_tx_frame_num = rx_frame->data[4];
	if (context->tp_rx_session[tp_index].frame_cnt > J1939_TP_DT_MAX_CNT)
	{
		context->tp_rx_session[tp_index].end_frame = context->tp_rx_session[tp_index].start_frame + J1939_TP_DT_MAX_CNT - 1;
	}
	else
	{
		context->tp_rx_session[tp_index].end_frame = context->tp_rx_session[tp_index].frame_cnt;
	}

	//广播
	if (rx_frame->id.Bits.PS == 0xFF)
	{
		context->tp_rx_session[tp_index].is_bam = TRUE;
		context->tp_rx_session[tp_index].time_out = J1939_T1_TIMEOUT;
	}
	//非广播
	else
	{
		context->tp_rx_session[tp_index].is_bam = FALSE;
		context->tp_rx_session[tp_index].time_out = J1939_T2_TIMEOUT;
	}

	//转到接收状态
	context->tp_rx_session[tp_index].status = kTp_DT;

	return J1939_OK;
}
/*****************************************************************************
*函数名称:J1939_RxTpSessionDestroy
*函数功能:释放J1939使用过的TPSession
*参    数:J1939TpSession* J1939_PAGED rx_session
*返 回 值:无
*作    者:Admin
*修订信息:
******************************************************************************/
void J1939_RxTpSessionDestroy(J1939TpSession* J1939_PAGED rx_session)
{
	//检查参数
    if(rx_session == NULL)
    {
        return;
    }
    
	rx_session->is_bam = 0;
	rx_session->frame_cnt = 0; 
	rx_session->max_tx_frame_num = 0;
	rx_session->frame_index = 0; 
	rx_session->frame_err_flag = 0;
	rx_session->start_frame = 0;
	rx_session->end_frame = 0;
	rx_session->last_tick = 0;
	rx_session->time_out = 0;
    rx_session->msg.id.value = 0;
    rx_session->msg.pgn = 0;
	rx_session->msg.dest_addr = 0;
	rx_session->msg.source_addr = 0;
	rx_session->msg.msg_len = 0;
	rx_session->resendTick = 0;
	memset(rx_session->frame_recved_flag,0,sizeof(rx_session->frame_recved_flag));
    
    rx_session->is_open = FALSE;
    rx_session->status =kTp_IDLE;
}
/*****************************************************************************
 *函数名称:J1939_TpRxStatusUpdate
 *函数功能:TP接收状态更新
 *参    数:J1939Context* J1939_PAGED context   J1939内容指针
 *返 回 值:无
 *作    者:Admin
 *修订信息:
 ******************************************************************************/
static J1939Result J1939_TpRxSessionRequestResend(J1939Context* J1939_PAGED context,J1939TpSession* J1939_PAGED session, uint8_T lossFrameId);
void J1939_TpRxStatusUpdate(J1939Context* J1939_PAGED context)
{
	uint8_T tp_index = 0;
	uint32_T tick_elap = 0;
	uint32_T now_tick = get_tick_count();

	//检查参数
	if (context == NULL)
	{
		return;
	}

	for (tp_index = 0; tp_index < J1939_TP_RX_SESSION_NUM; tp_index++)
	{
		if (context->tp_rx_session[tp_index].is_open == TRUE)
		{
			switch (context->tp_rx_session[tp_index].status)
			{
				case kTp_DT://数据接收超时
					tick_elap = get_interval_by_tick(context->tp_rx_session[tp_index].last_tick, now_tick);//超时计数
					if (tick_elap > context->tp_rx_session[tp_index].time_out)
					{
					    if(context->tp_rx_session[tp_index].is_bam == FALSE) 
					    {
					        (void) J1939_TpCM_Abort(context, context->tp_rx_session[tp_index].msg.source_addr, context->tp_rx_session[tp_index].msg.pgn,context->tp_rx_session[tp_index].msg.dest_addr);
					    }
					    
						context->tp_rx_session[tp_index].status = kTp_ABORT;
					}
					//20ms没有收到对端响应重新请求一次重发
					else if((tick_elap > J1939_CTS_RESEND_TIMEOUT) && ((now_tick - context->tp_rx_session[tp_index].resendTick) > J1939_CTS_RESEND_TIMEOUT))
					{
						J1939_TpRxSessionRequestResend(context, &context->tp_rx_session[tp_index],context->tp_rx_session[tp_index].start_frame);
					}
				break;
					//接收结束
				case kTp_END:
				    J1939_RxTpSessionDestroy(&context->tp_rx_session[tp_index]);//释放接收TP
					context->tp_rx_session[tp_index].status = kTp_IDLE;
				break;
				//出错
				case kTp_ABORT:
					//释放接收TP
				    J1939_RxTpSessionDestroy(&context->tp_rx_session[tp_index]);
					context->tp_rx_session[tp_index].status = kTp_IDLE;
				break;
				default:
				break;
			}
		}
	}
}

/**
 * @brief       检测有没有收齐，没有收齐就返回缺失最小的帧ID
 * @param[in]   J1939TpSession* J1939_PAGED session
 * @param[out]  uint8_T *lossFrameId
 * @return      J1939Result
 * @retval      J1939_OK:正常  !J1939_OK:错误
 * @par         修改日志:
 * Date                Author     Description           \n
 * 2023-09-11           JHC        创建初始版本          \n
*/
static J1939Result J1939_TpRxSessionCheckFrameCollection(J1939TpSession* J1939_PAGED session, uint8_T startCheckID, uint8_T endCheckID, uint8_T *lossFrameId)
{
	uint8_T i = 0;

	for(i=startCheckID;i<endCheckID;i++)
	{
		if(session->frame_recved_flag[i-1] == 0)
		{
			if(lossFrameId){*lossFrameId = i;}
			return J1939_ERR;
		}
	}

	return J1939_OK;
}

static J1939Result J1939_TpRxSessionRequestResend(J1939Context* J1939_PAGED context,J1939TpSession* J1939_PAGED session, uint8_T lossFrameId)
{
	J1939Result result = J1939_OK;
	session->start_frame = lossFrameId;
	session->frame_index = lossFrameId;
	if(session->frame_cnt - session->end_frame > J1939_TP_DT_MAX_CNT)
	{
		session->end_frame = session->start_frame + J1939_TP_DT_MAX_CNT-1;
	}
	else
	{
		session->end_frame = session->frame_cnt;
	}
	session->resendTick = get_tick_count();
	result = J1939_TpCM_CTS_Resend(context, session);
	//printf("lossFrameId=0x%x,cnt=0x%x,resendID=0x%x,0x%x\r\n",lossFrameId,session->frame_cnt,session->start_frame,session->end_frame);
	return result;
}

/*****************************************************************************
*函数名称:J1939_TpRxFrameData
*函数功能:J1939通过TP接收多包CAN数据帧
*参    数:J1939Context* J1939_PAGED context   J1939内容指针
*       J1939TpSession* J1939_PAGED session接收TP指针
*         const J1939CanFrame* J1939_PAGED rx_frame 接收到CAN数据帧的指针
*返 回 值:J1939_OK成功,其他失败
*作    者:Admin
*修订信息:
******************************************************************************/
J1939Result J1939_TpRxFrameData(J1939Context* J1939_PAGED context,J1939TpSession* J1939_PAGED session,const J1939CanFrame* J1939_PAGED frame)
{
   uint32_T now_tick = get_tick_count();
   J1939Result result = J1939_OK;

   //检查参数
   if((context == NULL)||(session == NULL)||(frame == NULL))
   {
          return J1939_PTR_NULL;
   }
   if(session->is_open == FALSE)
   {
          return J1939_TP_RX_SESSION_NOT_OPEN;
   }
   if(session->status != kTp_DT)
   {
          return J1939_ERR;
   }

    if((frame->data[0] <= session->end_frame)&&
       (frame->data[0] >= session->start_frame)&&
       (frame->data[0] > 0))
    {   
		uint8_T data_num = 0;//数据数
		uint16_T msg_write_index = 0;//消息索引
		//更新时间
        session->last_tick = now_tick;
		session->resendTick = now_tick;
        session->time_out = J1939_T1_TIMEOUT;
		//检查消息长度
		data_num = frame->data_len;
		if(data_num > J1939_CAN_FRAME_DATA_LEN)
		{
			data_num =  J1939_CAN_FRAME_DATA_LEN;
		}
		if(data_num == 0)
		{
			data_num = 1;
		}
		msg_write_index = ((uint16_T)frame->data[0]-1)*7;
		//数据长度检查
		if((msg_write_index >= context->rx_msg_max_len)||((msg_write_index+data_num) >= context->rx_msg_max_len))
		{   if(session->is_bam == FALSE) 
			{
				(void)J1939_TpCM_Abort(context,session->msg.dest_addr,session->msg.pgn,session->msg.source_addr);
			}
			//释放接收TP
			J1939_RxTpSessionDestroy(session);
			session->status = kTp_ABORT;
			//printf("abort,msg_write_index=%d,rx_msg_max_len=%d,dataNum=%d",msg_write_index,context->rx_msg_max_len,data_num);
			return J1939_MSG_FULL;
		}
		
		//避免重复数据拷贝
		if(session->frame_recved_flag[frame->data[0]-1] == 0)
		{
			//数据拷贝
			(void)J1939_BufferCopy(&session->msg.data[msg_write_index],&frame->data[1], data_num-1);
			//index从1开始
			session->frame_recved_flag[frame->data[0]-1] = 1;
			session->frame_index=frame->data[0]-1;
		}

		//检测到多帧最后一帧
		if(frame->data[0] == session->frame_cnt)
		{   		
			uint8_T lossFrameId = 0;
			J1939_TpRxSessionCheckFrameCollection(session,1,session->frame_cnt,&lossFrameId);
			//非广播
			if(session->is_bam == FALSE) 
			{
				if(session->frame_err_flag == 1)
				{
					//出错
					session->frame_err_flag = 0;
					result = J1939_TP_FRAME_NUM_ERROR;
					session->status = kTp_ABORT;
				}
				else if(lossFrameId != 0) 
				{
					result = J1939_TpRxSessionRequestResend(context,session,lossFrameId);
				}
				else 
				{   
					(void)J1939_TpCM_EndAck(context, session);
					result = J1939_PushRxMsgToQueue(&context->rx_msg_queue,&session->msg);
					//清除已接收标志
					memset(session->frame_recved_flag,0,sizeof(session->frame_recved_flag));
					session->status = kTp_END;
				}
			}
			else//广播
			{
				if(session->frame_err_flag == 1) 
				{
					//出错
					session->frame_err_flag = 0;
					result = J1939_TP_FRAME_NUM_ERROR;
					session->status = kTp_ABORT;
				}
				else 
				{   //完成
					if(lossFrameId == 0)
					{
						result = J1939_PushRxMsgToQueue(&context->rx_msg_queue,&session->msg);
						memset(session->frame_recved_flag,0,sizeof(session->frame_recved_flag));
						session->status = kTp_END;
					}
				}
			
			}
			return result;
		}
		else if((frame->data[0] < session->frame_cnt)&&
				(frame->data[0] == session->end_frame))//未完成，发送CTS
		{
			uint8_T lossFrameId = 0;
			J1939_TpRxSessionCheckFrameCollection(session,session->start_frame,session->end_frame,&lossFrameId);
			//非广播 
			if(session->is_bam == FALSE)
			{
				//出错 
				if(session->frame_err_flag == 1)
				{
					//出错
					session->frame_err_flag = 0;
					result = J1939_TP_FRAME_NUM_ERROR;
					session->status = kTp_ABORT;
				}
				else if(lossFrameId != 0) 
				{
					result = J1939_TpRxSessionRequestResend(context,session,lossFrameId);
				}
				else 
				{   //接着传输
					session->start_frame = session->end_frame + 1;
					session->frame_index = session->start_frame;
					if(session->frame_cnt - session->end_frame > J1939_TP_DT_MAX_CNT)
					{
						session->end_frame = session->start_frame + J1939_TP_DT_MAX_CNT-1;
					}
					else
					{
						session->end_frame = session->frame_cnt;
					}
					result = J1939_TpCM_CTS(context, session); 
				}
			}
			else
			{
				//广播
				if(session->frame_err_flag == 1) 
				{
					//出错
					session->frame_err_flag = 0;
					session->status = kTp_ABORT;
					result = J1939_TP_FRAME_NUM_ERROR;	
				}
			
			}
			return result;
		}
        
    }
    else//数据帧有误
    {
		//现在不许保序接收了，这个flag也不需要置位了只要是内容合理的都可以收进去
        //session->frame_err_flag = 1;
		//printf("frame error,sessionCnt=0x%x,frame->data[0]=0x%x,startFrame=0x%x,endFrame=0x%x\r\n",session->frame_cnt,frame->data[0],session->start_frame,session->end_frame);
        return J1939_TP_FRAME_NUM_ERROR;
    }
    return J1939_OK;
}
/*****************************************************************************
 *函数名称:J1939_TPRxMsg
 *函数功能:J1939TP接收消息
 *参    数:J1939Context* J1939_PAGED context   J1939内容指针
 *返 回 值:无
 *作    者:Admin
 *修订信息:
 ******************************************************************************/
J1939Result J1939_TPRxMsg(J1939Context* J1939_PAGED context)
{
	J1939Result result = J1939_OK;
	uint32_T pgn = 0;
	uint8_T tp_index = 0;
	J1939CanFrame rx_frame;
	int32_t ret = 0;

	//检查参数
	if (context == NULL)
	{
		return J1939_PTR_NULL;
	}

	//更新状态
	J1939_TpRxStatusUpdate(context);
	do
	{
		//加锁，尽量保证原子，代码重构改用do while
		pthread_mutex_lock(&context->rx_frame_tmp_queue.mutex);
		ret = J1939_PopCanFrameFromQueue(&context->rx_frame_tmp_queue, &rx_frame);
		pthread_mutex_unlock(&context->rx_frame_tmp_queue.mutex);
		if(ret == J1939_OK)
		{
			if ((rx_frame.id.Bits.PF == GET_PGN_PF(J1939_PGN_TP_CM)) &&
				((rx_frame.id.Bits.PS == context->tp_tx_session.msg.source_addr)||((rx_frame.id.Bits.PS == 0x80))||(rx_frame.id.Bits.PS == 0xFF)) &&
				((rx_frame.id.Bits.P == J1939_TP_CM_DEFAULT_PRI)||(rx_frame.id.Bits.P == J1939_MSG_DEFAULT_PRI))&&
				(rx_frame.mode == kCanExtendMode))
			{
				switch (rx_frame.data[0])
				{
					case J1939_TP_CM_RTS:
					pgn = ((uint32_T) rx_frame.data[7] << 16) + ((uint16_T) rx_frame.data[6] << 8) + rx_frame.data[5];
					//查找对应地址的TP是否正在使用
					tp_index = J1939_GetFreeRxTpSession(context);
					if (tp_index < J1939_TP_RX_SESSION_NUM)//查找到了
						{
							if ((J1939_RxTpSessionCreate(context, tp_index, &rx_frame) == J1939_OK)&&(rx_frame.id.Bits.PS != 0xFF))
						{
							result = J1939_TpCM_CTS(context, &context->tp_rx_session[tp_index]);
						}
							
						}
						else//没有查到,使用空闲的TP
						{
							tp_index = J1939_GetFreeRxTpSession(context);
						}
					break;
					
					case J1939_TP_CM_BAM:
						pgn = ((uint32_T) rx_frame.data[7] << 16) + ((uint16_T) rx_frame.data[6] << 8) + rx_frame.data[5];
						//查找对应地址的TP是否正在使用
						tp_index = J1939_SearchFreeRxTpSession(context, rx_frame.id.Bits.SA);
						if (tp_index < J1939_TP_RX_SESSION_NUM)//查找到了
						{
							//上次PGN与本次不同，则结束上次PGN连接,pgn相同不用发送结束命令
							if ((context->tp_rx_session[tp_index].msg.pgn != pgn)&&(rx_frame.id.Bits.PS != 0xFF))
							{
								(void)J1939_TpCM_Abort(context, rx_frame.id.Bits.SA, pgn,rx_frame.id.Bits.PS);
							}
							J1939_RxTpSessionDestroy(&context->tp_rx_session[tp_index]);//释放接收TP
						}
						else//没有查到,使用空闲的TP
						{
							tp_index = J1939_GetFreeRxTpSession(context);
						}
						//创建新连接
						if ((J1939_RxTpSessionCreate(context, tp_index, &rx_frame) == J1939_OK)&&(rx_frame.id.Bits.PS != 0xFF))
						{
							result = J1939_TpCM_CTS(context, &context->tp_rx_session[tp_index]);
						}
						else//接收TP已满
						{
							if(rx_frame.id.Bits.PS != 0xFF) 
							{
								(void)J1939_TpCM_Abort(context, rx_frame.id.Bits.SA, pgn,rx_frame.id.Bits.PS); 
							}
							result = J1939_TP_RX_SESSION_FULL;
						}

					break;
					case J1939_TP_CM_CTS:
					case J1939_TP_CM_END:
					case J1939_TP_CM_ABORT:
						J1939_TpTxStatusUpdate(context, &rx_frame);
					break;
					default:

					break;
				}
			}
			else if ((rx_frame.id.Bits.PF == GET_PGN_PF(J1939_PGN_TP_DATA)) &&
					((rx_frame.id.Bits.PS == context->device_param.addr)||(rx_frame.id.Bits.PS == 0x80)||(rx_frame.id.Bits.PS == 0xFF)) &&
					((rx_frame.id.Bits.P == J1939_TP_CM_DEFAULT_PRI)||(rx_frame.id.Bits.P == J1939_MSG_DEFAULT_PRI)))//TP中的数据报文
			{

				tp_index = J1939_SearchFreeRxTpSession(context, rx_frame.id.Bits.SA);
				if (tp_index < J1939_TP_RX_SESSION_NUM)//存在对应TP
				{
					result = J1939_TpRxFrameData(context, &context->tp_rx_session[tp_index], &rx_frame);
				}
				else
				{
					result = J1939_TP_RX_SESSION_NOT_EXIST;
				}
			}
			else//其他报文
			{
				result = J1939_PushCanFrameToQueue(&context->rx_frame_queue, &rx_frame);
			}
		}
	} while (ret == J1939_OK);
	
#if 0
	while (J1939_PopCanFrameFromQueue(&context->rx_frame_tmp_queue, &rx_frame) == J1939_OK)
	{
		if ((rx_frame.id.Bits.PF == GET_PGN_PF(J1939_PGN_TP_CM)) &&
			((rx_frame.id.Bits.PS == context->tp_tx_session.msg.source_addr)||((rx_frame.id.Bits.PS == 0x80))||(rx_frame.id.Bits.PS == 0xFF)) &&
			((rx_frame.id.Bits.P == J1939_TP_CM_DEFAULT_PRI)||(rx_frame.id.Bits.P == J1939_MSG_DEFAULT_PRI))&&
			(rx_frame.mode == kCanExtendMode))
		{
			switch (rx_frame.data[0])
			{
				case J1939_TP_CM_RTS:
                 pgn = ((uint32_T) rx_frame.data[7] << 16) + ((uint16_T) rx_frame.data[6] << 8) + rx_frame.data[5];
				//查找对应地址的TP是否正在使用
				tp_index = J1939_GetFreeRxTpSession(context);
                  if (tp_index < J1939_TP_RX_SESSION_NUM)//查找到了
					{
						if ((J1939_RxTpSessionCreate(context, tp_index, &rx_frame) == J1939_OK)&&(rx_frame.id.Bits.PS != 0xFF))
					{
						result = J1939_TpCM_CTS(context, &context->tp_rx_session[tp_index]);
					}
						
					}
					else//没有查到,使用空闲的TP
					{
						tp_index = J1939_GetFreeRxTpSession(context);
					}
                  break;
                  
				case J1939_TP_CM_BAM:
					pgn = ((uint32_T) rx_frame.data[7] << 16) + ((uint16_T) rx_frame.data[6] << 8) + rx_frame.data[5];
					//查找对应地址的TP是否正在使用
					tp_index = J1939_SearchFreeRxTpSession(context, rx_frame.id.Bits.SA);
					if (tp_index < J1939_TP_RX_SESSION_NUM)//查找到了
					{
						//上次PGN与本次不同，则结束上次PGN连接,pgn相同不用发送结束命令
						if ((context->tp_rx_session[tp_index].msg.pgn != pgn)&&(rx_frame.id.Bits.PS != 0xFF))
						{
							(void)J1939_TpCM_Abort(context, rx_frame.id.Bits.SA, pgn,rx_frame.id.Bits.PS);
						}
						J1939_RxTpSessionDestroy(&context->tp_rx_session[tp_index]);//释放接收TP
					}
					else//没有查到,使用空闲的TP
					{
						tp_index = J1939_GetFreeRxTpSession(context);
					}
					//创建新连接
					if ((J1939_RxTpSessionCreate(context, tp_index, &rx_frame) == J1939_OK)&&(rx_frame.id.Bits.PS != 0xFF))
					{
						result = J1939_TpCM_CTS(context, &context->tp_rx_session[tp_index]);
					}
					else//接收TP已满
					{
					     if(rx_frame.id.Bits.PS != 0xFF) 
					     {
					        (void)J1939_TpCM_Abort(context, rx_frame.id.Bits.SA, pgn,rx_frame.id.Bits.PS); 
					     }
						result = J1939_TP_RX_SESSION_FULL;
					}

				break;
				case J1939_TP_CM_CTS:
				case J1939_TP_CM_END:
				case J1939_TP_CM_ABORT:
					J1939_TpTxStatusUpdate(context, &rx_frame);
				break;
				default:

				break;
			}
		}
		else if ((rx_frame.id.Bits.PF == GET_PGN_PF(J1939_PGN_TP_DATA)) &&
				((rx_frame.id.Bits.PS == context->device_param.addr)||(rx_frame.id.Bits.PS == 0x80)||(rx_frame.id.Bits.PS == 0xFF)) &&
				((rx_frame.id.Bits.P == J1939_TP_CM_DEFAULT_PRI)||(rx_frame.id.Bits.P == J1939_MSG_DEFAULT_PRI)))//TP中的数据报文
		{

			tp_index = J1939_SearchFreeRxTpSession(context, rx_frame.id.Bits.SA);
			if (tp_index < J1939_TP_RX_SESSION_NUM)//存在对应TP
			{
				result = J1939_TpRxFrameData(context, &context->tp_rx_session[tp_index], &rx_frame);
			}
			else
			{
				result = J1939_TP_RX_SESSION_NOT_EXIST;
			}
		}
		else//其他报文
		{
			result = J1939_PushCanFrameToQueue(&context->rx_frame_queue, &rx_frame);
		}
	}
#endif
	return result;
}


/*****************************************************************************
 *函数名称:J1939_TpCM_RTS
 *函数功能:连接模式下的请求发送
 *参    数:J1939Context* J1939_PAGED context   J1939内容指针
 *         J1939TpSession* J1939_PAGED tx_session  发送TP指针
 *返 回 值:J1939_OK成功,其他失败
 *作    者:Admin
 *修订信息:
 ******************************************************************************/
J1939Result J1939_TpCM_RTS(J1939Context* J1939_PAGED context, J1939TpSession* J1939_PAGED tx_session)
{
	J1939CanFrame frame;
	uint32_T now_tick = get_tick_count();

	//检查参数
	if ((context == NULL) || (tx_session == NULL))
	{
		return J1939_PTR_NULL;
	}
	if (tx_session->is_open == FALSE)
	{
		return J1939_TP_TX_SESSION_NOT_OPEN;
	}
	if (tx_session->is_bam == TRUE)
	{
		return J1939_OK;
	}

	//缓存清0
	J1939_BufferSet((uint8_T*) &frame, 0, sizeof(J1939CanFrame));

	frame.id.Bits.NA = 0;
#if 0
    if(tx_session->msg.source_addr != 0xF4)
    {
        frame.id.Bits.P = J1939_MSG_DEFAULT_PRI;
    }else
    {
        frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
    }
#else
    frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
#endif
	frame.id.Bits.R = 0;
	frame.id.Bits.DP = GET_PGN_DP(J1939_PGN_TP_CM);
	frame.id.Bits.PF = GET_PGN_PF(J1939_PGN_TP_CM);
	frame.id.Bits.PS = tx_session->msg.dest_addr;
	frame.id.Bits.SA = tx_session->msg.source_addr;
	frame.mode = kCanExtendMode;
	frame.data_len = 8;
	frame.data[0] = J1939_TP_CM_RTS;
	frame.data[1] = (uint8_T) (tx_session->msg.msg_len);
	frame.data[2] = (uint8_T) (tx_session->msg.msg_len >> 8);
	frame.data[3] = tx_session->frame_cnt;
	frame.data[4] = 0xFF;
	frame.data[5] = (uint8_T) (tx_session->msg.pgn);
	frame.data[6] = (uint8_T) (tx_session->msg.pgn >> 8);
	frame.data[7] = (uint8_T) (tx_session->msg.pgn >> 16);
	tx_session->last_tick = now_tick;
	tx_session->time_out = J1939_T3_TIMEOUT;
	return J1939_PushCanFrameToQueue(&context->tx_frame_tmp_queue, &frame);
}
/*****************************************************************************
 *函数名称:J1939_TpCM_CTS
 *函数功能:连接模式下的准备发送
 *参    数:J1939Context* J1939_PAGED context   J1939内容指针
 *         J1939TpSession* J1939_PAGED rx_session  接收TP指针
 *返 回 值:J1939_OK成功,其他失败
 *作    者:Admin
 *修订信息:
 ******************************************************************************/
J1939Result J1939_TpCM_CTS(J1939Context* J1939_PAGED context, J1939TpSession* J1939_PAGED rx_session)
{
	J1939CanFrame frame;
	uint32_T now_tick = get_tick_count();

	//检查参数
	if ((context == NULL) || (rx_session == NULL))
	{
		return J1939_PTR_NULL;
	}
	if (rx_session->is_open == FALSE)
	{
		return J1939_TP_RX_SESSION_NOT_OPEN;
	}
	if (rx_session->is_bam == TRUE)
	{
		return J1939_OK;
	}

	//缓存清0
	J1939_BufferSet((uint8_T*) &frame, 0, sizeof(J1939CanFrame));

	frame.id.Bits.NA = 0;
#if 0
    if(rx_session->msg.source_addr!=0xF4)
    {
        frame.id.Bits.P = J1939_MSG_DEFAULT_PRI;
    }else
    {
        frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
    }
#else
    frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
#endif
    
	frame.id.Bits.R = 0;
	frame.id.Bits.DP = GET_PGN_DP(J1939_PGN_TP_CM);
	frame.id.Bits.PF = GET_PGN_PF(J1939_PGN_TP_CM);
	frame.id.Bits.PS = rx_session->msg.source_addr;
	frame.id.Bits.SA = rx_session->msg.dest_addr;
	frame.mode = kCanExtendMode;
	frame.data_len = 8;
	frame.data[0] = J1939_TP_CM_CTS;
	frame.data[1] = rx_session->end_frame - rx_session->start_frame + 1;
	frame.data[2] = rx_session->start_frame;
	frame.data[3] = 0xFF;
	frame.data[4] = 0xFF;
	frame.data[5] = (uint8_T) (rx_session->msg.pgn);
	frame.data[6] = (uint8_T) (rx_session->msg.pgn >> 8);
	frame.data[7] = (uint8_T) (rx_session->msg.pgn >> 16);
	rx_session->last_tick = now_tick;
	rx_session->time_out = J1939_T2_TIMEOUT;
	rx_session->status = kTp_DT;
	return J1939_PushCanFrameToQueue(&context->tx_frame_tmp_queue, &frame);
}

J1939Result J1939_TpCM_CTS_Resend(J1939Context* J1939_PAGED context, J1939TpSession* J1939_PAGED rx_session)
{
	J1939CanFrame frame;
	uint32_T now_tick = get_tick_count();

	//检查参数
	if ((context == NULL) || (rx_session == NULL))
	{
		return J1939_PTR_NULL;
	}
	if (rx_session->is_open == FALSE)
	{
		return J1939_TP_RX_SESSION_NOT_OPEN;
	}
	if (rx_session->is_bam == TRUE)
	{
		return J1939_OK;
	}

	//缓存清0
	J1939_BufferSet((uint8_T*) &frame, 0, sizeof(J1939CanFrame));

	frame.id.Bits.NA = 0;
#if 0
    if(rx_session->msg.source_addr!=0xF4)
    {
        frame.id.Bits.P = J1939_MSG_DEFAULT_PRI;
    }else
    {
        frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
    }
#else
    frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
#endif
    
	frame.id.Bits.R = 0;
	frame.id.Bits.DP = GET_PGN_DP(J1939_PGN_TP_CM);
	frame.id.Bits.PF = GET_PGN_PF(J1939_PGN_TP_CM);
	frame.id.Bits.PS = rx_session->msg.source_addr;
	frame.id.Bits.SA = rx_session->msg.dest_addr;
	frame.mode = kCanExtendMode;
	frame.data_len = 8;
	frame.data[0] = J1939_TP_CM_CTS;
	frame.data[1] = rx_session->end_frame - rx_session->start_frame + 1;
	frame.data[2] = rx_session->start_frame;
	frame.data[3] = 0xFF;
	frame.data[4] = 0xFF;
	frame.data[5] = (uint8_T) (rx_session->msg.pgn);
	frame.data[6] = (uint8_T) (rx_session->msg.pgn >> 8);
	frame.data[7] = (uint8_T) (rx_session->msg.pgn >> 16);
	//rx_session->last_tick = now_tick;
	rx_session->time_out = J1939_T2_TIMEOUT;
	rx_session->status = kTp_DT;
	return J1939_PushCanFrameToQueue(&context->tx_frame_tmp_queue, &frame);
}
/*****************************************************************************
 *函数名称:J1939_TpCM_Abort
 *函数功能:放弃连接
 *参    数:J1939Context* J1939_PAGED context   J1939内容指针
 *       uint8_T dest_addr目标地址
 *       uint32_T pgn  PGN
 *返 回 值:J1939_OK成功,其他失败
 *作    者:Admin
 *修订信息:
 ******************************************************************************/
J1939Result J1939_TpCM_Abort(J1939Context* J1939_PAGED context, uint8_T dest_addr, uint32_T pgn ,uint8_T source_addr)
{
	J1939CanFrame frame;

	//检查参数
	if (context == NULL)
	{
		return J1939_PTR_NULL;
	}

	//缓存清0
	J1939_BufferSet((uint8_T*) &frame, 0, sizeof(J1939CanFrame));

	frame.id.Bits.NA = 0;

#if 0
    if(source_addr!=0xF4)
    {
        frame.id.Bits.P = J1939_MSG_DEFAULT_PRI;
    }else
    {
        frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
    }
#else
    frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
#endif
    
	frame.id.Bits.R = 0;
	frame.id.Bits.DP = GET_PGN_DP(J1939_PGN_TP_CM);
	frame.id.Bits.PF = GET_PGN_PF(J1939_PGN_TP_CM);
	frame.id.Bits.PS = dest_addr;
	frame.id.Bits.SA = source_addr;
    frame.mode = kCanExtendMode;
	frame.data_len = 8;
	frame.data[0] = J1939_TP_CM_ABORT;
	frame.data[1] = 0xFF;
	frame.data[2] = 0xFF;
	frame.data[3] = 0xFF;
	frame.data[4] = 0xFF;
	frame.data[5] = (uint8_T) pgn;
	frame.data[6] = (uint8_T) (pgn >> 8);
	frame.data[7] = (uint8_T) (pgn >> 16);
	return J1939_PushCanFrameToQueue(&context->tx_frame_tmp_queue, &frame);
}
/*****************************************************************************
 *函数名称:J1939_TpCM_EndAck
 *函数功能:消息结束应答
 *参    数:J1939Context* J1939_PAGED context   J1939内容指针
 *         J1939TpSession* J1939_PAGED rx_session  接收TP指针
 *返 回 值:J1939_OK成功,其他失败
 *作    者:Admin
 *修订信息:
 ******************************************************************************/
J1939Result J1939_TpCM_EndAck(J1939Context* J1939_PAGED context, J1939TpSession* J1939_PAGED rx_session)
{
	J1939CanFrame frame;
	uint32_T now_tick = get_tick_count();

	//检查参数
	if ((context == NULL) || (rx_session == NULL))
	{
		return J1939_PTR_NULL;
	}
	if (rx_session->is_open == FALSE)
	{
		return J1939_TP_RX_SESSION_NOT_OPEN;
	}
	if (rx_session->is_bam == TRUE)
	{
		return J1939_OK;
	}

	//缓存清0
	J1939_BufferSet((uint8_T*) &frame, 0, sizeof(J1939CanFrame));

	frame.id.Bits.NA = 0;
#if 0
    if(rx_session->msg.source_addr!=0xF4)
    {
        frame.id.Bits.P = J1939_MSG_DEFAULT_PRI;
    }else
    {
        frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
    }
#else
    frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
#endif
	frame.id.Bits.R = 0;
	frame.id.Bits.DP = GET_PGN_DP(J1939_PGN_TP_CM);
	frame.id.Bits.PF = GET_PGN_PF(J1939_PGN_TP_CM);
	frame.id.Bits.PS = rx_session->msg.source_addr;
	frame.id.Bits.SA = rx_session->msg.dest_addr;
	frame.mode = kCanExtendMode;
	frame.data_len = 8;
	frame.data[0] = J1939_TP_CM_END;
	frame.data[1] = (uint8_T) rx_session->msg.msg_len;
	frame.data[2] = (uint8_T) (rx_session->msg.msg_len >> 8);
	frame.data[3] = rx_session->frame_cnt;
	frame.data[4] = 0xFF;
	frame.data[5] = (uint8_T) (rx_session->msg.pgn);
	frame.data[6] = (uint8_T) (rx_session->msg.pgn >> 8);
	frame.data[7] = (uint8_T) (rx_session->msg.pgn >> 16);
	rx_session->last_tick = now_tick;
	rx_session->time_out = J1939_T2_TIMEOUT;
	return J1939_PushCanFrameToQueue(&context->tx_frame_tmp_queue, &frame);
}
/*****************************************************************************
 *函数名称:J1939_TpCM_BAM
 *函数功能:广播公告消息
 *参    数:J1939Context* J1939_PAGED context   J1939内容指针
 *      J1939TpSession* J1939_PAGED tx_session   发送TP指针
 *返 回 值:J1939_OK成功,其他失败
 *作    者:Admin
 *修订信息:
 ******************************************************************************/
J1939Result J1939_TpCM_BAM(J1939Context* J1939_PAGED context, J1939TpSession* J1939_PAGED tx_session)
{
	J1939CanFrame frame;
	uint32_T now_tick = get_tick_count();

	//检查参数
	if ((context == NULL) || (tx_session == NULL))
	{
		return J1939_PTR_NULL;
	}
	if (tx_session->is_open == FALSE)
	{
		return J1939_TP_TX_SESSION_NOT_OPEN;
	}
	if (tx_session->is_bam == FALSE)
	{
		return J1939_OK;
	}

	//缓存清0
	J1939_BufferSet((uint8_T*) &frame, 0, sizeof(J1939CanFrame));

	frame.id.Bits.NA = 0;
#if 0
    if(tx_session->msg.source_addr!=0xF4)
    {
        frame.id.Bits.P = J1939_MSG_DEFAULT_PRI;
    }else
    {
        frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
    }
#else
    frame.id.Bits.P = J1939_TP_CM_DEFAULT_PRI;
#endif
    
	frame.id.Bits.R = 0;
	frame.id.Bits.DP = GET_PGN_DP(J1939_PGN_TP_CM);
	frame.id.Bits.PF = GET_PGN_PF(J1939_PGN_TP_CM);
	if (frame.id.Bits.PF < 240)
	{
		frame.id.Bits.PS = 0xFF;
	}
	else
	{
		frame.id.Bits.PS = GET_PGN_PS(J1939_PGN_TP_CM);
	}
	//写发送数据
	frame.id.Bits.SA = tx_session->msg.source_addr;
    frame.mode = kCanExtendMode;
	frame.data_len = J1939_CAN_FRAME_DATA_LEN;
	frame.data[0] = J1939_TP_CM_BAM;
	frame.data[1] = (uint8_T) tx_session->msg.msg_len;
	frame.data[2] = (uint8_T) (tx_session->msg.msg_len >> 8);
	frame.data[3] = tx_session->frame_cnt;
	frame.data[4] = 0xFF;
	frame.data[5] = (uint8_T) (tx_session->msg.pgn);
	frame.data[6] = (uint8_T) (tx_session->msg.pgn >> 8);
	frame.data[7] = (uint8_T) (tx_session->msg.pgn >> 16);
	tx_session->last_tick = now_tick;
	//50ms发送一次
	tx_session->time_out = J1939_BAM_TX_TIME_INTERVAL;
	tx_session->status = kTp_DT;
	//压入队列
	return J1939_PushCanFrameToQueue(&context->tx_frame_tmp_queue, &frame);
}

#endif
