gateway.cxgate
来自「CAN 网关原代码,汽车电子中的总线网关」· CXGATE 代码 · 共 517 行 · 第 1/2 页
CXGATE
517 行
}
/* handles timeout situations */
void GatewayRxTimeout(tRxFrmDescr *rframe_p) {
#if (GATEWAY_TX_FRM_CNT>0)
/* check whether the fail bit feature is enabled */
if (rframe_p->RxToutFailEn) {
/* set the fail bit */
BitAssign(1,rframe_p->RxToutFailPos,TxTable[((tSignalDestDescr*)(rframe_p->pSignalDescr+1))->frame_no].Data);
}
#endif
/* check whether the timeout function counter is running */
if (rframe_p->RxToutCntr) {
/* decrement the counter */
rframe_p->RxToutCntr--;
/* check whether the counter has overflown */
if (rframe_p->RxToutCntr==0) {
/* reload the counter */
rframe_p->RxToutCntr=rframe_p->RxToutReload;
/* call the Rx Timeout Handler */
RxTimeoutHandler(rframe_p);
}
}
}
/* this routines services periodic interrupt from the PIT */
/* it schedules transmissions of periodic frames and watches for timeouts */
interrupt void GatewayTick(void) {
static unsigned char counter=0;
tRxFrmDescr *rframe_p;
tTxFrmDescr *tframe_p;
#if (defined(DO_LM))
LM_START(0);
#endif
PIT.pittf.byte = PTF0; /* clear the interrupt flag */
/* process periodic Tx */
#if (GATEWAY_TX_FRM_CNT>0)
tframe_p = TxTable;
while (tframe_p<(TxTable+GATEWAY_TX_FRM_CNT)) {
/* check the prescaller */
if ((counter&(0xE0|(tframe_p->TxTimerPrescaler)))==counter) {
/* check if the timer is running */
if (tframe_p->TxTimer.counter) {
/* decrease the timer */
tframe_p->TxTimer.counter--;
/* check if the timer has overflown */
if (tframe_p->TxTimer.counter==0) {
/* reload the timer */
tframe_p->TxTimer.counter=tframe_p->TxTimer.load_value;
/* transmit the frame */
FrameTransmit(tframe_p);
}
}
}
tframe_p++;
}
#endif
#if (GATEWAY_RX_FRM_CNT>0)
rframe_p = RxTable;
#if (GATEWAY_LIN_NODE_CNT==0) /* there are no Lin nodes, process all the Rx timers */
while (rframe_p<(RxTable+GATEWAY_RX_FRM_CNT)) {
#else /* there are Lin nodes in the system, process only Rx timers up to the first Lin Rx frame */
while (rframe_p<(NodeDescrs[FIRST_LIN_NODE].rx_idx_start_p)) {
#endif
/* check the prescaller */
if ((counter&(0xE0|(rframe_p->RxTimerPrescaler)))==counter) {
/* check if the timer is running */
if (rframe_p->RxTimer.counter) {
/* decrease the timer */
rframe_p->RxTimer.counter--;
/* check if the timer has overflown */
if (rframe_p->RxTimer.counter==0) {
/* reload the timer */
rframe_p->RxTimer.counter=rframe_p->RxTimer.load_value;
/* call the Rx timeout processing */
GatewayRxTimeout(rframe_p);
}
}
}
rframe_p++;
}
#if (GATEWAY_LIN_NODE_CNT>0) /* there are Lin nodes; process timeouts for lin nodes now */
while (rframe_p<(RxTable+GATEWAY_RX_FRM_CNT)) {
/* check the prescaller */
if ((counter&(0xE0|(rframe_p->RxTimerPrescaler)))==counter) {
/* check if the timer is running */
if (rframe_p->RxTimer.counter) {
/* decrease the timer */
rframe_p->RxTimer.counter--;
/* check if the timer has overflown */
if (rframe_p->RxTimer.counter==0) {
tNodeDescr *node; /* local node descriptor pointer */
/* reload the timer */
rframe_p->RxTimer.counter=rframe_p->RxTimer.load_value;
/* find the node this frame belongs to */
node = &NodeDescrs[FIRST_LIN_NODE];
#if (GATEWAY_LIN_NODE_CNT>1) /* no need to search in case of 1 Lin node */
while ((node+1)<(NodeDescrs+sizeof(NodeDescrs)/sizeof(tNodeDescr))) {
if (rframe_p<((node+1)->rx_idx_start_p)) {
/* first frame belonging to the next node is above the pointer, i.e. node points to the correct node descriptor now */
break;
} else {
node++;
}
}
#endif
/* schedule this frame for processing */
/* store pointer to the frame to be transmitted into the Tx buffer of the appropriate node */
node->TxBuffer[node->TxBufferAdd]=(void*)rframe_p;
/* increment the index */
node->TxBufferAdd++;
/* wrap around end of the buffer if neccessary */
if (node->TxBufferAdd>=node->TxBufferSize) node->TxBufferAdd=0;
if ((((tLINnode*)(node->periph_addr))->state)==idleState) LinFrameSetup(node);
}
}
}
rframe_p++;
}
#endif
#endif
/* increment the main counter */
counter++;
/* if the lowest nibble is 10 clear it and increment nibble 1 */
if ((counter&0x0f)==10) {
counter&=0xf0;
counter+=0x10;
}
#if (defined(DO_LM))
LM_STOP(0);
#endif
}
/* transmits frame */
/* input is frame number (index into the TxTable) */
void FrameTransmit(tTxFrmDescr *frame_p) {
/* if the frame is not scheduled for transmission yet, schedule it */
if (frame_p->TxScheduled==0) {
tNodeDescr *node;
/* indicate that the frame is now scheduled */
frame_p->TxScheduled=1;
/* get the Tx node number */
node = &NodeDescrs[frame_p->node];
/* store pointer to the frame to be transmitted into the Tx buffer of the appropriate node */
node->TxBuffer[node->TxBufferAdd]=frame_p;
/* increment the index */
node->TxBufferAdd++;
/* wrap around end of the buffer if neccessary */
if (node->TxBufferAdd>=node->TxBufferSize) node->TxBufferAdd=0;
/* check inf the Tx timer is running */
if (frame_p->TxTimer.counter!=0) {
/* restart the timer */
frame_p->TxTimer.counter=frame_p->TxTimer.load_value;
}
/* enable interrupts from the given peripheral */
switch (node->periph_type) {
/* MsCan peripheral */
case (MsCan):
/* enable interrupts from Tx buffer empty flags */
((tMSCAN*)(node->periph_addr))->cantier.byte=TXEIE0|TXEIE1|TXEIE2;
break;
/* virtual Lin peripheral */
case (Lin):
if ((((tLINnode*)(node->periph_addr))->state)==idleState) LinFrameSetup(node);
break;
/* add service of other node interface types here */
}
}
}
/* service routine of MsCan Tx empty interrupt */
/* if the data pointer is NULL the routine will copy 4 words from address 0 - no harm done */
interrupt void MsCanTxEmptyIsr(tNodeDescr * node) {
#if (defined(DO_LM))
LM_START(2);
#endif
/* check whether there is any frame to be transmitted */
if ((node->TxBufferTake)!=(node->TxBufferAdd)) {
/* transmit the first frame in the buffer */
tTxFrmDescr* frame_p;
unsigned int *dest_buffer;
/* select the first empty Tx buffer */
((tMSCAN*)(node->periph_addr))->cantbsel.byte = ((tMSCAN*)(node->periph_addr))->cantflg.byte;
/* create a local copy of pointer to the frame to be transmitted */
frame_p = node->TxBuffer[node->TxBufferTake];
/* create local copy of pointer to the Tx data buffer */
dest_buffer = ((unsigned int *)(((tMSCAN*)(node->periph_addr))->txbuf.dsr));
/* copy data */
*(dest_buffer+0) = *(((unsigned int *)(frame_p->Data))+0);
*(dest_buffer+1) = *(((unsigned int *)(frame_p->Data))+1);
*(dest_buffer+2) = *(((unsigned int *)(frame_p->Data))+2);
*(dest_buffer+3) = *(((unsigned int *)(frame_p->Data))+3);
/* copy identifier */
((tMSCAN*)(node->periph_addr))->txbuf.id.w[0] = (frame_p->ID)<<5; /* need to align the frame ID to the MSB */
/* copy the number of bytes to transmit */
((tMSCAN*)(node->periph_addr))->txbuf.dlr.byte = frame_p->DataSize;
/* mark the frame as transmitted */
frame_p->TxScheduled=0;
/* transmit the buffer */
((tMSCAN*)(node->periph_addr))->cantflg.byte = ((tMSCAN*)(node->periph_addr))->cantbsel.byte;
/* advance the TxBuffer index */
(node->TxBufferTake)++;
/* wrap around end of the buffer if neccessary */
if ((node->TxBufferTake)>=(node->TxBufferSize)) node->TxBufferTake=0;
} else {
/* there are no frames to transmit, disable Tx interrupts */
((tMSCAN*)(node->periph_addr))->cantier.byte=0;
}
#if (defined(DO_LM))
LM_STOP(2);
#endif
}
/* service routine of MsCan Rx full interrupt */
/* incomming frames are processed in this routine */
interrupt void MsCanRxFullIsr(tNodeDescr *node) {
tRxFrmDescr *frame_p;
tMSCAN *MsCanp;
#if (defined(DO_LM))
LM_START(1);
#endif
/* create local pointer to the MsCan peripheral */
MsCanp = ((tMSCAN*)(node->periph_addr));
/* find the frame number */
frame_p=RxFindFrmId((MsCanp->rxbuf.id.w[0])>>5,node);
/* if frame found, process it, otherwise ignore it */
if (frame_p!=NULL) {
/* check data size */
if (MsCanp->rxbuf.dlr.byte < frame_p->DataSize) {
/* did not receive enough data */
RxInvalidHandler(frame_p, node);
} else {
/* frame is received -> reload RxTimer */
frame_p->RxTimer.counter=frame_p->RxTimer.load_value;
/* and the timeout counter */
frame_p->RxToutCntr=frame_p->RxToutReload;
#if (GATEWAY_TX_FRM_CNT>0)
/* if the fail bit is enabed */
if (frame_p->RxToutFailEn) {
/* clear the fail bit */
BitAssign(0,frame_p->RxToutFailPos,TxTable[((tSignalDestDescr*)(frame_p->pSignalDescr+1))->frame_no].Data);
}
/* copy data into their destinations */
CopySignals(MsCanp->rxbuf.dsr, frame_p);
#endif
/* call RxHandler */
RxHandler(frame_p,node);
}
}
/* release the Rx buffer */
((tMSCAN*)(node->periph_addr))->canrflg.byte=RXF;
#if (defined(DO_LM))
LM_STOP(1);
#endif
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?