⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c5471_ethernet.c

📁 這是一個實時嵌入式作業系統 實作了MCS51 ARM等MCU
💻 C
📖 第 1 页 / 共 5 页
字号:
          /* If the above function invocation resulted in data that should be           * sent out on the network, the field  d_len will set to a value > 0.           * Send that data now if ESM has let go of the RX descriptor giving us           * access rights to submit another Ethernet frame.           */          if (dev->d_len > 0 &&             (EIM_TXDESC_OWN_HOST & getreg32(c5471->c_rxcpudesc)) == 0)            {              uip_arp_out(dev);              c5471_transmit(c5471);            }        }      else if (BUF->type == HTONS(UIP_ETHTYPE_ARP))        {          uip_arp_arpin(dev);          /* If the above function invocation resulted in data that should be           * sent out on the network, the field  d_len will set to a value > 0.           * Send that data now if ESM has let go of the RX descriptor giving us           * access rights to submit another Ethernet frame.           */          if (dev->d_len > 0 &&             (EIM_TXDESC_OWN_HOST & getreg32(c5471->c_rxcpudesc)) == 0)            {              c5471_transmit(c5471);            }        }    }#ifdef CONFIG_C5471_NET_STATS  else    {      /* Increment the count of dropped packets */      ndbg("Too big! packetlen: %d\n", packetlen);      c5471->c_rxdropped++;    }#endif}/**************************************************************************** * Function: c5471_txstatus * * Description: *   An interrupt was received indicating that the last TX packet(s) is done * * Parameters: *   c5471  - Reference to the driver state structure * * Returned Value: *   None * * Assumptions: * ****************************************************************************/#ifdef CONFIG_C5471_NET_STATSstatic void c5471_txstatus(struct c5471_driver_s *c5471){  uint32 desc = c5471->c_lastdescstart;  uint32 txstatus;  /* Walk that last packet we just sent to collect xmit status bits. */  txstatus = 0;  if (c5471->c_lastdescstart && c5471->c_lastdescend)    {      for (;;)        {          txstatus |= (getreg32(desc) & EIM_RXDESC_STATUSMASK);          if (desc == c5471->c_lastdescend)            {              break;            }          /* This packet is made up of several descriptors, find next one in chain. */          if (EIM_RXDESC_WRAP_NEXT & getreg32(c5471->c_rxcpudesc))            {              /* Loop back around to base of descriptor queue. */              desc = getreg32(EIM_CPU_RXBA) + EIM_RAM_START;            }          else            {              desc += 2 * sizeof(uint32);            }        }    }  if (txstatus)    {      if ((txstatus & EIM_RXDESC_MISS) != 0)        {          c5471->c_txmiss++;          nvdbg("c_txmiss: %d\n", c5471->c_txmiss);        }      if ((txstatus & EIM_RXDESC_VLAN) != 0)        {          c5471->c_txvlan++;          nvdbg("c_txvlan: %d\n", c5471->c_txvlan);        }      if ((txstatus & EIM_RXDESC_LFRAME) != 0)        {          c5471->c_txlframe++;          nvdbg("c_txlframe: %d\n", c5471->c_txlframe);        }      if ((txstatus & EIM_RXDESC_SFRAME) != 0)        {          c5471->c_txsframe++;          nvdbg("c_txsframe: %d\n", c5471->c_txsframe);        }      if ((txstatus & EIM_RXDESC_CRCERROR) != 0)        {          c5471->c_txcrc++;          nvdbg("c_txcrc: %d\n", c5471->c_txcrc);        }      if ((txstatus & EIM_RXDESC_OVERRUN) != 0)        {          c5471->c_txoverrun++;          nvdbg("c_txoverrun: %d\n", c5471->c_txoverrun);        }      if ((txstatus & EIM_RXDESC_OVERRUN) != 0)        {          c5471->c_txalign++;          nvdbg("c_txalign: %d\n", c5471->c_txalign);        }    }}#endif/**************************************************************************** * Function: c5471_txdone * * Description: *   An interrupt was received indicating that the last TX packet(s) is done * * Parameters: *   c5471  - Reference to the driver state structure * * Returned Value: *   None * * Assumptions: * ****************************************************************************/static void c5471_txdone(struct c5471_driver_s *c5471){  /* If no further xmits are pending, then cancel the TX timeout */  wd_cancel(c5471->c_txtimeout);  /* Then poll uIP for new XMIT data */  (void)uip_poll(&c5471->c_dev, c5471_uiptxpoll);}/**************************************************************************** * Function: c5471_interrupt * * Description: *   Hardware interrupt handler * * Parameters: *   irq     - Number of the IRQ that generated the interrupt *   context - Interrupt register state save info (architecture-specific) * * Returned Value: *   OK on success * * Assumptions: * ****************************************************************************/static int c5471_interrupt(int irq, FAR void *context){#if CONFIG_C5471_NET_NINTERFACES == 1  register struct c5471_driver_s *c5471 = &g_c5471[0];#else# error "Additional logic needed to support multiple interfaces"#endif  /* Get and clear interrupt status bits */  c5471->c_eimstatus = getreg32(EIM_STATUS);  /* Handle interrupts according to status bit settings */  /* Check if we received an incoming packet, if so, call c5471_receive() */  if ((EIM_STATUS_CPU_TX & c5471->c_eimstatus) != 0)    {      /* An incoming packet has been received by the EIM from the network and       * the interrupt associated with EIM's CPU TX queue has been asserted. It       * is the EIM's CPU TX queue that we need to read from to get those       * packets.  We use this terminology to stay consistent with the Orion       * documentation.       */#ifdef CONFIG_C5471_NET_STATS      /* Check for RX errors */      c5471_rxstatus(c5471);#endif      /* Process the received packet */      c5471_receive(c5471);    }  /* Check is a packet transmission just completed.  If so, call c5471_txdone */  if ((EIM_STATUS_CPU_RX & c5471->c_eimstatus) != 0)    {      /* An outgoing packet has been processed by the EIM and the interrupt       * associated with EIM's CPU RX que has been asserted. It is the EIM's       * CPU RX queue that we put packets on to send them *out*. TWe use this       * terminology to stay consistent with the Orion documentation.       */#ifdef CONFIG_C5471_NET_STATS      /* Check for TX errors */      c5471_txstatus(c5471);#endif      /* Handle the transmission done event */      c5471_txdone(c5471);    }  /* Enable Ethernet interrupts (perhaps excluding the TX done interrupt if    * there are no pending transmissions.   */  return OK;}/**************************************************************************** * Function: c5471_txtimeout * * Description: *   Our TX watchdog timed out.  Called from the timer interrupt handler. *   The last TX never completed.  Reset the hardware and start again. * * Parameters: *   argc - The number of available arguments *   arg  - The first argument * * Returned Value: *   None * * Assumptions: * ****************************************************************************/static void c5471_txtimeout(int argc, uint32 arg, ...){  struct c5471_driver_s *c5471 = (struct c5471_driver_s *)arg;  /* Increment statistics */#ifdef CONFIG_C5471_NET_STATS  c5471->c_txtimeouts++;  nvdbg("c_txtimeouts: %d\n", c5471->c_txtimeouts);#endif  /* Then try to restart the hardware */  c5471_ifdown(&c5471->c_dev);  c5471_ifup(&c5471->c_dev);  /* Then poll uIP for new XMIT data */  (void)uip_poll(&c5471->c_dev, c5471_uiptxpoll);}/**************************************************************************** * Function: c5471_polltimer * * Description: *   Periodic timer handler.  Called from the timer interrupt handler. * * Parameters: *   argc - The number of available arguments *   arg  - The first argument * * Returned Value: *   None * * Assumptions: * ****************************************************************************/static void c5471_polltimer(int argc, uint32 arg, ...){  struct c5471_driver_s *c5471 = (struct c5471_driver_s *)arg;  /* Check if the ESM has let go of the RX descriptor giving us access rights   * to submit another Ethernet frame.   */  if ((EIM_TXDESC_OWN_HOST & getreg32(c5471->c_rxcpudesc)) == 0)    {      /* If so, update TCP timing states and poll uIP for new XMIT data */      (void)uip_timer(&c5471->c_dev, c5471_uiptxpoll, C5471_POLLHSEC);    }  /* Setup the watchdog poll timer again */  (void)wd_start(c5471->c_txpoll, C5471_WDDELAY, c5471_polltimer, 1, arg);}/**************************************************************************** * Function: c5471_ifup * * Description: *   NuttX Callback: Bring up the Ethernet interface when an IP address is *   provided  * * Parameters: *   dev  - Reference to the NuttX driver state structure * * Returned Value: *   None * * Assumptions: *   The user has assigned a MAC to the driver * ****************************************************************************/static int c5471_ifup(struct uip_driver_s *dev){  struct c5471_driver_s *c5471 = (struct c5471_driver_s *)dev->d_private;  volatile uint32 clearbits;  ndbg("Bringing up: %d.%d.%d.%d\n",       dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff,       (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 );  /* Initilize Ethernet interface */  c5471_reset(c5471);  /* Assign the MAC to the device */  c5471_macassign(c5471);  /* Clear pending interrupts by reading the EIM status register */  clearbits = getreg32(EIM_STATUS);  /* Enable interrupts going from EIM Module to Interrupt Module. */  putreg32(((getreg32(EIM_INTEN) | EIM_INTEN_CPU_TX|EIM_INTEN_CPU_RX)), EIM_INTEN);  /* Next, go on-line. According to the C547X documentation the enables have to   * occur in this order to insure proper operation; ESM first then the ENET.   */  putreg32((getreg32(EIM_CTRL) | EIM_CTRL_ESM_EN), EIM_CTRL);   /* enable ESM */  putreg32((getreg32(ENET0_MODE) | ENET_MODE_ENABLE), ENET0_MODE); /* enable ENET */  up_mdelay(100);  /* Set and activate a timer process */  (void)wd_start(c5471->c_txpoll, C5471_WDDELAY, c5471_polltimer, 1, (uint32)c5471);  /* Enable the Ethernet interrupt */  c5471->c_bifup = TRUE;  up_enable_irq(C5471_IRQ_ETHER);  return OK;}/**************************************************************************** * Function: c5471_ifdown * * Description: *   NuttX Callback: Stop the interface. * * Parameters: *   dev  - Reference to the NuttX driver state structure * * Returned Value: *   None * * Assumptions: * ****************************************************************************/static int c5471_ifdown(struct uip_driver_s *dev){  struct c5471_driver_s *c5471 = (struct c5471_driver_s *)dev->d_private;  irqstate_t flags;  ndbg("Stopping\n");  /* Disable the Ethernet interrupt */  flags = irqsave();  up_disable_irq(C5471_IRQ_ETHER);  /* Disable interrupts going from EIM Module to Interrupt Module. */  putreg32((getreg32(EIM_INTEN) & ~(EIM_INTEN_CPU_TX|EIM_INTEN_CPU_RX)), EIM_INTEN);  /* Disable ENET */  putreg32((getreg32(ENET0_MODE) & ~ENET_MODE_ENABLE), ENET0_MODE); /* disable ENET */  /* Disable ESM */  putreg32((getreg32(EIM_CTRL) & ~EIM_CTRL_ESM_EN), EIM_CTRL);  /* disable ESM */  /* Cancel the TX poll timer and TX timeout timers */  wd_cancel(c5471->c_txpoll);  wd_cancel(c5471->c_txtimeout);  /* Reset the device */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -