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 + -
显示快捷键?