UDS协议栈的开发和测试对于刚刚接触UDS协议的开发人员来说,不但需要阅读大量的标准文档,短时间内很难理解透彻,标准协议栈代码的编写更加困难,刚入门又没有快捷简单的测试工具帮助加快理解和验证,使得UDS诊断开发对于一般的初创公司或者小型企业来说,是一个比较难跨越的门槛。一般的企业通过购买专业的软件工具和专业的培训服务来获取UDS诊断开发和测试的技术。本文的目的是通过简单快捷的UDS上位机软件测试界面,有助于帮助开发者加快UDS协议栈的理解和开发测试,能够帮助开发者快速的掌握UDS开发和测试的一般过程和方法。
首先贴出网络层协议源码:
namespace Uds
{
public class uds_trans
{
public enum AddressingModes
{
Physical_Addressing,
Functional_Addressing,
}
private int id;
///
/// UDS默认填充字节
///
public byte fill_byte = 0x55;
public int tx_id;
public int rx_id;
public int test_id;
/*
** Frame types arranged in numericalorder for efficient switch statement
** jump tables.
*/
private enum FrameType
{
TX_SF = 0, /* Single Frame */
TX_FF = 1, /* First Frame */
TX_CF = 2, /* Consecutive Frame */
TX_FC = 3 /* Flow Control Frame */
};
/*
** Masks for the PCI(Protcol ControlInformation) byte.
** The MS bit contains the frame type.
** The LS bit is mapped differently,depending on frame type, as follows:
** SF: DL (number of diagnostic bytes NOT including the PCI byte; only the
** 3 LS bits are used).
** FF: XDL (extended data length; always be 0.)
** CF: Sequence number,4 bits, max value:15.
** FC: Flow Status. The value of FS shall be set to zero that means that
** the tester is ready to receive a maximum number of CF.
*/
private enum PCI /* Don't change thesevalues, these must be */
{
/* MS bits - Frame Type */
FRAME_TYPE_MASK = 0xF0,
SF_TPDU = 0x00, /* Single frame */
FF_TPDU = 0x10, /* First frame */
CF_TPDU = 0x20, /* Consecutive frame */
FC_TPDU = 0x30, /* Flow control frame */
FC_OVFL_PDU = 0x32, /* Flow control frame */
/* LS bits - SF_DL */
SF_DL_MAX_BYTES = 0x07, /* SF Max Data Length */
SF_DL_MASK = 0x07, /* number diagnostic data bytes */
SF_DL_MASK_LONG = 0x0F, /* change to check the 4 bits for testing,number diagnostic data bytes */
/* LS bits - FF_DL */
FF_EX_DL_MASK = 0x0F, /*Extended data length */
/* LS bits - CF_SN */
CF_SN_MASK = 0x0F, /* Sequence number mask */
CF_SN_MAX_VALUE = 0x0F, /* Max value of sequence number */
/* LS bits - FC Saatus */
FC_STATUS_CONTINUE = 0x00, /* Flow control frame, CONTINUE */
FC_STATUS_WAIT = 0x01, /* Flow control frame, WAIT */
FC_STATUS_OVERFLOW = 0x02, /* Flow control frame, OVERFLOW */
FC_STATUS_MASK = 0x0F,
};
private int N_As = 25;
private int N_Ar = 25;
private int N_Bs = 75;
private int N_Br;
private int N_Cr = 150;
private int N_Cs;
private int FC_BS_MAX_VALUE = 0;
private int FC_ST_MIN_VALUE = 5;
private int CF_SN_MAX_VALUE = 15;
private int SF_DL_MAX_BYTES = 7;
/*
** Time to wait for the tester to senda FC frame in response
** to a FF(wait for flow control frametime out).
** N_As + N_Bs = 25 +75 = 100ms
*/
private int FC_WAIT_TIMEOUT;//N_As +N_Bs + 50;
/*
** wait for Consecutive frame time out
** N_Cr < 150ms
*/
private int CF_WAIT_TIMEOUT;//N_Cr; //(N_Cr- 10))
private int RX_MAX_TP_BYTES = 0xFFF;
public uds_trans()
{
can_rx_info.frame = new byte[8];
can_tx_info.frame = new byte[8];
FC_WAIT_TIMEOUT = N_As + N_Bs + 50;/* N_As + N_Bs + 50 */
CF_WAIT_TIMEOUT = N_Cr; /* (N_Cr - 10)) */
}
private readonly intbeginning_seq_number = 1;
private readonly int TPCI_Byte = 0;
private readonly int DL_Byte = 1;
private readonly int BS_Byte = 1;
private readonly int STminByte = 2;
private class tx_info
{
public bool tx_rx_idle = false;
public bool tx_fc_tpdu = false;
public bool tx_last_frame_error = false;
public bool tx_wait_fc = false;
public bool tx_in_progress = false;
public int tx_block_size = 0; /* BS(Block Size) in a flow ControlFrame */
public int tx_stmin_time = 20;
public int tx_cf_stmin_wait_time =20; /* STmin Time in Flow Control Frame*/
public int tx_fc_wait_time =0; /* Wait for FC when has sentFF */
public int lenght;
public int offset;
public int next_seq_num;
public byte[] buffer;
public byte[] frame;
}
private class rx_info
{
public bool rx_in_progress = false;
public bool rx_msg_rcvd =false; /* if the message has neverbeen received to be used by application level software */
public bool tx_aborted = false;
public int rx_cf_wait_time = 0;
public boolrx_fc_wait_timeout_disable = false;
public bool rx_overflow = false;
public int lenght;
public int offset;
public int next_seq_num;
public byte[] buffer;
public byte[] frame;
}
private tx_info can_tx_info = newtx_info();
private rx_info can_rx_info = newrx_info();
#region Event
public class FarmsEventArgs : EventArgs
{
public int id = 0;
public int dlc = 0;
public byte[] dat = new byte[8];
public long time = 0;
public override string ToString()
{
time %= 1000000;
returnid.ToString("X3") + " "
+dlc.ToString("X1") + " "
+ dat.HexToStrings("") + " "
+ (time /1000).ToString() + "." + (time % 1000).ToString("d3");
}
}
public class RxMsgEventArgs : EventArgs
{
public int id = 0;
public byte[] dat;
public long time = 0;
public RxMsgEventArgs(int lenght)
{
dat = new byte[lenght];
}
public override string ToString()
{
time %= 1000000;
returnid.ToString("X3") + " "
+dat.HexToStrings(" ") + " "
+ (time /1000).ToString() + "." + (time % 1000).ToString("d3");
}
}
public class ErrorEventArgs : EventArgs
{
public string error;
public override string ToString()
{
return error;
}
}
///
/// UDS 传输层发送一帧事件
///
public event EventHandler EventTxFarms;
///
/// UDS 传输层接收一帧事件
///
public event EventHandler EventRxFarms;
///
/// UDS 传输层接收完成事件
///
public event EventHandler EventRxMsgs;
///
/// UDS 传输层错误事件
///
public event EventHandler EventError;
private void TxFarmsEvent(int id,byte[] dat, int dlc, long time)
{
if (EventTxFarms != null)
{
FarmsEventArgs e_args = newFarmsEventArgs();
e_args.id = id;
e_args.dlc = dlc;
e_args.time = time;
Array.Copy(dat, e_args.dat,dlc);
EventTxFarms(this, e_args);
}
}
private void RxFarmsEvent(int id,byte[] dat, int dlc, long time)
{
if (EventRxFarms != null)
{
FarmsEventArgs e_args = newFarmsEventArgs();
e_args.id = id;
e_args.dlc = dlc;
e_args.time = time;
Array.Copy(dat, e_args.dat,dlc);
EventRxFarms(this, e_args);
}
}
private void RxMsgEvent(int id, byte[]dat)
{
if (EventRxMsgs != null)
{
int lenght = dat.Length;
RxMsgEventArgs e_rx_msg_args =new RxMsgEventArgs(lenght);
e_rx_msg_args.id = id;
Array.Copy(dat,e_rx_msg_args.dat, lenght);
EventRxMsgs(this,e_rx_msg_args);
}
}
private void RrrorEvent(string strings)
{
if (EventError != null)
{
ErrorEventArgs e_args = newErrorEventArgs();
e_args.error = strings;
EventError(this, e_args);
}
}
public delegate bool CanWriteData(intid, byte[] dat, int dlc, out long time);
public delegate bool CanReadData(outint id, ref byte[] dat, out int dlc, out long time);
///
/// 利用委托发送一帧数据
///
public CanWriteData WriteData;
///
/// 利用委托接收一帧数据
///
public CanReadData ReadData;
#endregion
#region Trans Thread
Thread testerPresent_thread;
private void testerPresent_Thread()
{
while (true)
{
long time;
if (WriteData != null&& WriteData(test_id, new byte[] { 0x02, 0x3E, 0x80, 0x00, 0x00, 0x00,0x00, 0x00 }, 8, out time) == true)
{
Thread.Sleep(3000);
}
}
}
private bool tester = false;
///
/// 诊断保持
///
public bool testerPresentCheckd
{
set
{
tester = value;
if (tester)
{
testerPresent_thread = newThread(new ThreadStart(testerPresent_Thread));
testerPresent_thread.Start();
}
else
{
if (testerPresent_thread !=null && testerPresent_thread.IsAlive)
{
testerPresent_thread.Abort();
}
}
}
get
{
return tester;
}
}
Thread trans_thread;
private void CanTrans_Thread()
{
long oldTime = DateTime.Now.Ticks;
while (true)
{
long cnt;
int id;
int dlc;
long time;
byte[] dat = new byte[8];
while (true)
{
bool rx_frame = false;
while (ReadData != null&& ReadData(out id, ref dat, out dlc, out time) == true)
{
if (id == rx_id&& dlc == 8)
{
if(can_rx_info.rx_in_progress && dat[0] == 0x02 && dat[1] == 0x7F&& dat[3] == 0x78)
{
can_rx_info.rx_cf_wait_time = 5000;
break;
}
Array.Copy(dat,can_rx_info.frame, 8);
RxFarmsEvent(id,dat, dlc, time);
rx_frame = true;
break;
}
}
long nowTime =DateTime.Now.Ticks;
cnt = nowTime - oldTime;
if (cnt > 10000 ||rx_frame)
{
oldTime = nowTime;
break;
}
else if(!can_tx_info.tx_in_progress && !can_rx_info.rx_in_progress) //UDS空闲,释放进程
{
Thread.Sleep(1);
}
}
CanTrans_Manage((int)(cnt +5000) / 10000);
}
}
///
/// UDS 传输层开启
///
public void Start()
{
trans_thread = new Thread(newThreadStart(CanTrans_Thread));
trans_thread.Priority =ThreadPriority.Highest;
trans_thread.Start();
}
///
/// UDS 传输层关闭
///
public void Stop()
{
if (trans_thread != null &&trans_thread.IsAlive)
{
trans_thread.Abort();
}
testerPresentCheckd = false;
}
#endregion
private byte[] tx_msg = new byte[0];
///
/// 发送信息
///
///
///
///
public bool CanTrans_TxMsg(AddressingModesmode, byte[] msg)
{
if (msg.Length == 0)
{
RrrorEvent("-->Error:Tx Msg Length Is Zero");
return false;
}
if (msg.Length > RX_MAX_TP_BYTES- 2)
{
RrrorEvent("-->Error:Tx Msg Length > RX_MAX_TP_BYTES");
return false;
}
if (tx_msg.Length != 0)
{
RrrorEvent("-->Error:Tx Msg ing");
return false;
}
if (mode ==AddressingModes.Physical_Addressing)
{
id = tx_id;
}
else
{
id = test_id;
}
tx_msg = msg;
tx_msg = new byte[msg.Length];
Array.Copy(msg, tx_msg,msg.Length);
return true;
}
///
/// 发送信息
///
///
///
///
public boolCanTrans_TxMsg(AddressingModes mode, string strings)
{
return CanTrans_TxMsg(mode,strings.StringToHex());
}
private void CanTrans_TxMsg()
{
if (tx_msg.Length == 0)
{
return;
}
/*
** Set the tx_in_progress bit...itwill be cleared when TX is done.
*/
can_tx_info.tx_in_progress = true;
can_tx_info.tx_last_frame_error =false;
/*
** Assign fields in the controlstructure to initiate TX, then TX the
** appropriate frame type.
*/
can_tx_info.offset = 0;
can_tx_info.lenght = tx_msg.Length;
can_tx_info.buffer = newbyte[tx_msg.Length];
Array.Copy(tx_msg,can_tx_info.buffer, can_tx_info.lenght);
can_tx_info.offset = 0;
tx_msg = new byte[0];
if (can_tx_info.lenght <= SF_DL_MAX_BYTES)
{
CanTrans_TxFrame(FrameType.TX_SF);
}
else
{
CanTrans_TxFrame(FrameType.TX_FF);
}
}
private void CanTrans_TxFrame(FrameTypeframe_type)
{
int tx_farme_index = 0;
int tx_data_bytes = 0;
if (can_tx_info.tx_last_frame_error== false)
{
can_tx_info.frame = new byte[8]{ fill_byte, fill_byte, fill_byte, fill_byte, fill_byte, fill_byte, fill_byte,fill_byte };
/*
** Place control bytes into theframe.
*/
switch (frame_type)
{
case FrameType.TX_SF: /*single frame */
can_tx_info.frame[TPCI_Byte] = (byte)((byte)PCI.SF_TPDU |can_tx_info.lenght);
tx_data_bytes =can_tx_info.lenght;
tx_farme_index = 1;
break;
case FrameType.TX_FF: /* first frame */
can_tx_info.frame[TPCI_Byte] = (byte)((byte)PCI.FF_TPDU |(can_tx_info.lenght >> 8) & 0x0F);
can_tx_info.frame[DL_Byte] = (byte)(can_tx_info.lenght & 0xFF);
tx_data_bytes = SF_DL_MAX_BYTES- 1;
tx_farme_index = 2;
can_tx_info.next_seq_num = beginning_seq_number;
can_rx_info.rx_fc_wait_timeout_disable = false;
break;
case FrameType.TX_CF: /*conscutive frame */
can_tx_info.frame[TPCI_Byte] = (byte)((byte)PCI.CF_TPDU |can_tx_info.next_seq_num);
tx_farme_index = 1;
tx_data_bytes = (can_tx_info.lenght -can_tx_info.offset);
if (tx_data_bytes >SF_DL_MAX_BYTES)
{
tx_data_bytes =SF_DL_MAX_BYTES;
}
can_tx_info.next_seq_num = (can_tx_info.next_seq_num + 1) %(CF_SN_MAX_VALUE + 1);
break;
case FrameType.TX_FC: /*single frame */
if(can_rx_info.rx_overflow == true)
{
can_tx_info.frame[TPCI_Byte] = (byte)PCI.FC_OVFL_PDU;
}
else
{
can_tx_info.frame[TPCI_Byte] = (byte)PCI.FC_TPDU;
}
can_tx_info.frame[BS_Byte] = (byte)FC_BS_MAX_VALUE;
can_tx_info.frame[STminByte] = (byte)FC_ST_MIN_VALUE;
tx_data_bytes = 0;
break;
default:
return;
}
while (tx_data_bytes != 0)
{
can_tx_info.frame[tx_farme_index++] =can_tx_info.buffer[can_tx_info.offset++];
tx_data_bytes--;
}
}
long time;
if (WriteData != null &&WriteData(id, can_tx_info.frame, 8, out time) == true)
{
TxFarmsEvent(id,can_tx_info.frame, 8, time);
can_tx_info.tx_last_frame_error= false;
can_rx_info.frame[TPCI_Byte] =0;
/*
** Verify if the data has beencompletely transfered. If not, set flag to
** transfer CF frames. (For FCframes, s_cantp_tx_info is not used and there
** should not be a CF frameafter a FC frame.)
*/
if (can_tx_info.lenght >can_tx_info.offset && frame_type != FrameType.TX_FC)
{
can_tx_info.tx_in_progress =true;
if (frame_type ==FrameType.TX_FF)
{
can_tx_info.tx_wait_fc= true;
can_tx_info.tx_fc_wait_time = FC_WAIT_TIMEOUT; /* start flow controlwait timer */
}
}
else
{
can_tx_info.tx_in_progress= false;
}
}
else
{
/* user specific action incasetransmission request is not successful */
can_tx_info.tx_last_frame_error= true;
}
}
private void CanTrans_Manage(int tick)
{
CanTrans_TxMsg();
CanTrans_Counter(tick);
/*
** If new message has beenreceived, process it.
*/
if (can_rx_info.frame[TPCI_Byte] !=0)
{
CanTrans_RxStateAnalyse();
/*clear first rx frame byte tocheck a new frame next time*/
can_rx_info.frame[TPCI_Byte] =0;
}
if (can_tx_info.tx_in_progress
&&!can_tx_info.tx_wait_fc
)
{
if (0x00 ==can_tx_info.tx_block_size)
{
/* st_min time, receivedfrom tester*/
if (0x00 ==can_tx_info.tx_stmin_time)
{
CanTrans_TxFrame(FrameType.TX_CF);
}
else
{
/* st_min time,received from tester is not 0 */
if (0x00 ==can_tx_info.tx_cf_stmin_wait_time)
{
CanTrans_TxFrame(FrameType.TX_CF);
can_tx_info.tx_cf_stmin_wait_time = can_tx_info.tx_stmin_time;
}
}
}
else if (can_tx_info.tx_block_size> 1)
{
if (0x00 ==can_tx_info.tx_stmin_time)
{
CanTrans_TxFrame(FrameType.TX_CF);
if(!can_tx_info.tx_last_frame_error)
{
can_tx_info.tx_block_size--;
}
}
else
{
if (0x00 ==can_tx_info.tx_cf_stmin_wait_time)
{
CanTrans_TxFrame(FrameType.TX_CF);
if(!can_tx_info.tx_last_frame_error)
{
can_tx_info.tx_block_size--;
}
/* start stmintime,interval of consecutive frame */
can_tx_info.tx_cf_stmin_wait_time = can_tx_info.tx_stmin_time;
}
}
if(can_tx_info.tx_block_size <= 1)
{
can_tx_info.tx_wait_fc= true;
/* start flow controlwait timer */
can_tx_info.tx_fc_wait_time = FC_WAIT_TIMEOUT;
}
}
}
else if (can_tx_info.tx_fc_tpdu)
{
CanTrans_TxFrame(FrameType.TX_FC);
can_tx_info.tx_fc_tpdu = false;
/*start to counter the CF waittime*/
can_rx_info.rx_cf_wait_time =CF_WAIT_TIMEOUT;
}
if (can_tx_info.tx_in_progress
&&can_tx_info.tx_wait_fc
)
{
/* wait for flow control frametime out! */
if (can_tx_info.tx_fc_wait_time == 0)
{
can_tx_info.tx_in_progress= false;
can_tx_info.tx_wait_fc =false;
can_tx_info.tx_last_frame_error = false;
RrrorEvent("-->Error: Wait For FlowControl Frame Time Out");
}
}
if (can_rx_info.rx_in_progress ==true
&&!can_tx_info.tx_fc_tpdu
)
{
if (0x00 == can_rx_info.rx_cf_wait_time)
{
can_rx_info.tx_aborted =true;
/*
** wait for consecutiveframe Time out,abort Rx.
*/
can_rx_info.rx_in_progress= false;
/*
** When Time out occurs,ECU has to send negative
** resp(71) for the firstframe.First frame is already copied in to
** g_cantp_can_rx_info.msgbuffer but message length is not yet copied.
** So assign data length asFirst Frame length and set RX_MSG_RCVD
** flag.This flag indicatesto a new message has come.
*/
can_rx_info.lenght =SF_DL_MAX_BYTES - 1;
can_rx_info.rx_msg_rcvd =true;
RrrorEvent("-->Error: Ecu Tx Aborted");
}
}
if (can_rx_info.rx_msg_rcvd ==true)
{
can_rx_info.rx_msg_rcvd =false;
if (can_rx_info.tx_aborted ==false)
{
RxMsgEvent(rx_id,can_rx_info.buffer);
}
can_rx_info.tx_aborted = false;
}
}
private void CanTrans_Counter(int tick)
{
/* interval of consecutive frame,STmin = 10ms, separation time */
if(can_tx_info.tx_cf_stmin_wait_time > 0)
{
if(can_tx_info.tx_cf_stmin_wait_time > tick)
{
can_tx_info.tx_cf_stmin_wait_time -= tick;
}
else
{
can_tx_info.tx_cf_stmin_wait_time = 0;
}
}
/* N_Bs, flow control frame waittime out, 75ms*/
if (can_tx_info.tx_fc_wait_time> 0)
{
if (can_tx_info.tx_fc_wait_time> tick)
{
can_tx_info.tx_fc_wait_time-= tick;
}
else
{
can_tx_info.tx_fc_wait_time= 0;
can_rx_info.rx_fc_wait_timeout_disable = true;
}
}
/* N_Cr,consecutive frame wait timeout, 75ms*/
if (can_rx_info.rx_cf_wait_time> tick)
{
can_rx_info.rx_cf_wait_time -=tick;
}
else
{
can_rx_info.rx_cf_wait_time =0;
}
}
private void CanTrans_RxStateAnalyse()
{
PCI flow_control_sts;
int data_length = 0x00;
/* single frame */
if ((can_rx_info.frame[TPCI_Byte]& (byte)PCI.FRAME_TYPE_MASK) == (byte)PCI.SF_TPDU)
{
/* As per 15765-2 network layerspec when SF_DL is 0 or greater
** than 7, just ignore it.
*/
data_length =(can_rx_info.frame[TPCI_Byte] & (byte)PCI.SF_DL_MASK_LONG);
can_tx_info.tx_in_progress = false;
can_tx_info.tx_wait_fc = false;
can_rx_info.rx_in_progress =false;
can_tx_info.tx_last_frame_error= false;
if ((data_length == 0)
|| (data_length > SF_DL_MAX_BYTES)
)
{
return;
}
can_rx_info.lenght =data_length;
can_rx_info.buffer = newbyte[can_rx_info.lenght];
/*
** Copy the frame to the RXbuffer. Clear the RX_IN_PROGRESS bit
** (SF frame) will abortmulti-frame transfer.
*/
Array.Copy(can_rx_info.frame,1, can_rx_info.buffer, 0, can_rx_info.lenght);
can_rx_info.rx_msg_rcvd = true;
}
/* first frame */
else if((can_rx_info.frame[TPCI_Byte] & (byte)PCI.FRAME_TYPE_MASK) ==(byte)PCI.FF_TPDU)
{
data_length = ((int)(can_rx_info.frame[TPCI_Byte]& (byte)PCI.FF_EX_DL_MASK) << 8)
+can_rx_info.frame[DL_Byte];
can_rx_info.rx_fc_wait_timeout_disable = false;
can_rx_info.lenght =data_length;
can_rx_info.buffer = newbyte[can_rx_info.lenght];
/*
** Clear the RX buffer, copyfirst frame to RX buffer and initiate RX.
*/
Array.Copy(can_rx_info.frame,2, can_rx_info.buffer, 0, SF_DL_MAX_BYTES - 1);
can_rx_info.next_seq_num =beginning_seq_number;
can_rx_info.offset =SF_DL_MAX_BYTES - 1;
can_tx_info.tx_in_progress =false;
can_tx_info.tx_wait_fc = false;
can_rx_info.rx_in_progress =true;
/* set flag to send flowcontrol frame */
can_tx_info.tx_fc_tpdu = true;
}
/* Consecutive Frame */
else if((((can_rx_info.frame[TPCI_Byte] & (byte)PCI.FRAME_TYPE_MASK) ==(byte)PCI.CF_TPDU)
/* Don't accept consecutiveframe until flow control frame sent by ECU */
&&(!can_tx_info.tx_fc_tpdu)
/* Don't accept consecutiveframe if we are sending CF*/
&&(!can_tx_info.tx_in_progress))
)
{
/*
** Ignore frame unless RX inprogress.
*/
if (can_rx_info.rx_in_progress)
{
/*
** Verify the sequencenumber is as expected.
*/
if((can_rx_info.frame[TPCI_Byte] & (byte)PCI.CF_SN_MASK) ==can_rx_info.next_seq_num)
{
data_length =can_rx_info.lenght - can_rx_info.offset;
/*
** Last frame in message?
*/
if (data_length <=SF_DL_MAX_BYTES)
{
Array.Copy(can_rx_info.frame, 1,can_rx_info.buffer, can_rx_info.offset, data_length);
can_rx_info.rx_in_progress = false;
can_rx_info.rx_msg_rcvd = true;
}
else
{
/*
** not the lastframe,copy bytes to RX buffer and
** continue RXing.
*/
Array.Copy(can_rx_info.frame, 1, can_rx_info.buffer, can_rx_info.offset,SF_DL_MAX_BYTES);
can_rx_info.next_seq_num = (can_rx_info.next_seq_num + 1) %(CF_SN_MAX_VALUE + 1);
can_rx_info.offset += SF_DL_MAX_BYTES;
can_rx_info.rx_cf_wait_time = CF_WAIT_TIMEOUT;
}
}
else
{
/*
** Invalid sequence number...abort Rx.Asa diagnostic measure,
** consideration wasgiven to send an FC frame here, but not done.
*/
can_rx_info.rx_in_progress = false;
/*
** When Invalidsequence number is received, ECU has to send
** negative resp forthe first frame.so set RX_MSG_RCVD flag.
** This flag indicatesto DiagManager as new message has come.
*/
can_rx_info.tx_aborted= true;
can_rx_info.rx_msg_rcvd= true;
RrrorEvent("-->Error: Ecu Invalid Sequence Number");
}
}
}
/* flow control frame */
else if((can_rx_info.frame[TPCI_Byte] & (byte)PCI.FRAME_TYPE_MASK) ==(byte)PCI.FC_TPDU)
{
if (can_tx_info.tx_wait_fc)
{
/*
** Receive Flow Status(FS) forTransmiting the CF Frames.
** The value of FS shall be setto zero that means that the
** tester is ready to receive amaximum number of CF.
*/
flow_control_sts =PCI.FC_STATUS_CONTINUE;
if((can_rx_info.frame[TPCI_Byte] & (byte)PCI.FC_STATUS_MASK) != 0x00)
{
/* Flow Status(FS)
** 0: Continue to send(CTS)
** 1: wait(WT)
** 2: Overflow(OVFLW)
*/
flow_control_sts =(PCI)(can_rx_info.frame[TPCI_Byte] & (byte)PCI.FC_STATUS_MASK);
}
/*
** Receive the BS and STmin time for Transmiting the CF Frames.
*/
if(can_rx_info.frame[BS_Byte] != 0x00)
{
can_tx_info.tx_block_size= can_rx_info.frame[BS_Byte] + 1;
}
else
{
can_tx_info.tx_block_size = 0x00;
}
if ((can_rx_info.frame[STminByte]& 0x7F) != 0x00)
{
/*
** Valid Range forSTMin timeout is 0 - 127ms.
*/
can_tx_info.tx_stmin_time = (can_rx_info.frame[STminByte] & 0x7F) +5; /* extend the delay time */
}
else
{
can_tx_info.tx_stmin_time = 20;
}
if ((flow_control_sts ==PCI.FC_STATUS_CONTINUE)
&&(can_rx_info.rx_fc_wait_timeout_disable == false)
)
{
can_tx_info.tx_wait_fc= false;
can_tx_info.tx_fc_wait_time = 0;
}
else if (flow_control_sts== PCI.FC_STATUS_WAIT)
{
can_tx_info.tx_fc_wait_time = FC_WAIT_TIMEOUT; /* if wait, we will wait another time */
}
else if (flow_control_sts ==PCI.FC_STATUS_OVERFLOW)
{
/* do nothing here, ifover flow, we will stop sending
any message until wegot new cmd */
can_tx_info.tx_fc_wait_time= 1; /* exit after 10ms */
RrrorEvent("-->Error: Ecu Buff Over Flow");
}
else
{
/* do nothing here, ifover flow, we will stop sending
any message until wegot new cmd */
can_tx_info.tx_fc_wait_time = 1; /* exit after 10ms */
}
}
}
}
}
}