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

📄 dm90x0.c

📁 這是一個實時嵌入式作業系統 實作了MCS51 ARM等MCU
💻 C
📖 第 1 页 / 共 4 页
字号:
 * Description: *   An interrupt was received indicating the availability of a new RX packet * * Parameters: *   dm9x  - Reference to the driver state structure * * Returned Value: *   None * * Assumptions: * ****************************************************************************/static void dm9x_receive(struct dm9x_driver_s *dm9x){  union rx_desc_u rx;  boolean bchecksumready;  uint8   mdrah;  uint8   mdral;  uint8   rxbyte;  nvdbg("Packet received\n");  do    {      /* Store the value of memory data read address register */      mdrah = getreg(DM9X_MDRAH);      mdral = getreg(DM9X_MDRAL);      getreg(DM9X_MRCMDX);       /* Dummy read */      rxbyte = (uint8)DM9X_DATA; /* Get the most up-to-date data */      /* Packet ready for receive check */      bchecksumready = dm9x_rxchecksumready(rxbyte);      if (!bchecksumready)        {          break;        }      /* A packet is ready now. Get status/length */      DM9X_INDEX = DM9X_MRCMD; /* set read ptr ++ */      /* Read packet status & length */      dm9x->dm_read((uint8*)&rx, 4);      /* Check if any errors were reported by the hardware */      if (rx.desc.rx_status & 0xbf)        {          /* Bad RX packet... update statistics */#if defined(CONFIG_DM9X_STATS)          if (rx.desc.rx_status & 0x01)             {              dm9x->dm_nrxfifoerrors++;              ndbg("RX FIFO error: %d\n", dm9x->dm_nrxfifoerrors);            }          if (rx.desc.rx_status & 0x02)             {              dm9x->dm_nrxcrcerrors++;              ndbg("RX CRC error: %d\n", dm9x->dm_nrxcrcerrors);            }          if (rx.desc.rx_status & 0x80)             {              dm9x->dm_nrxlengtherrors++;              ndbg("RX length error: %d\n", dm9x->dm_nrxlengtherrors);            }          if (rx.desc.rx_status & 0x08)            {              dm9x->dm_nphyserrors++;              ndbg("Physical Layer error: %d\n", dm9x->dm_nphyserrors);            }#else          ndbg("Received packet with errors: %02x\n", rx.desc.rx_status);#endif          /* Drop this packet and continue to check the next packet */          dm9x->dm_discard(rx.desc.rx_len);        }      /* Also check if the packet is a valid size for the uIP configuration */      else if (rx.desc.rx_len < UIP_LLH_LEN || rx.desc.rx_len > (CONFIG_NET_BUFSIZE + 2))        {#if defined(CONFIG_DM9X_STATS)          dm9x->dm_nrxlengtherrors++;          ndbg("RX length error: %d\n", dm9x->dm_nrxlengtherrors);#endif          /* Drop this packet and continue to check the next packet */          dm9x->dm_discard(rx.desc.rx_len);        }      else        {          /* Good packet... Copy the packet data out of SRAM and pass it one to uIP */          dm9x->dm_dev.d_len = rx.desc.rx_len;          dm9x->dm_read(dm9x->dm_dev.d_buf, rx.desc.rx_len);          /* We only accept IP packets of the configured type and ARP packets */#ifdef CONFIG_NET_IPv6          if (BUF->type == HTONS(UIP_ETHTYPE_IP6))#else          if (BUF->type == HTONS(UIP_ETHTYPE_IP))#endif            {              uip_arp_ipin();              uip_input(&dm9x->dm_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.              */              if (dm9x->dm_dev.d_len > 0)                {                  uip_arp_out(&dm9x->dm_dev);                  dm9x_transmit(dm9x);                }            }          else if (BUF->type == htons(UIP_ETHTYPE_ARP))            {              uip_arp_arpin(&dm9x->dm_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.              */              if (dm9x->dm_dev.d_len > 0)                {                  dm9x_transmit(dm9x);                }            }        }#if defined(CONFIG_DM9X_STATS)      dm9x->dm_nrxpackets++;      dm9x->dm_nrxbytes += rx.desc.rx_len;#endif      dm9x->ncrxpackets++;    }  while ((rxbyte & 0x01) == DM9X_PKTRDY && dm9x->ncrxpackets < DM9X_CRXTHRES);  nvdbg("All RX packets processed\n");}/**************************************************************************** * Function: dm9x_txdone * * Description: *   An interrupt was received indicating that the last TX packet(s) is done * * Parameters: *   dm9x  - Reference to the driver state structure * * Returned Value: *   None * * Assumptions: * ****************************************************************************/static void dm9x_txdone(struct dm9x_driver_s *dm9x){  int  nsr;  nvdbg("TX done\n");  /* Another packet has completed transmission.  Decrement the count of   * of pending TX transmissions.   */  nsr = getreg(DM9X_NETS);  if (nsr & DM9X_NETS_TX1END)    {      if (dm9x->dm_ntxpending)        {          dm9x->dm_ntxpending--;        }      else        {          ndbg("Bad TX count (TX1END)\n");        }    }  if (nsr & DM9X_NETS_TX2END)    {      if (dm9x->dm_ntxpending)        {          dm9x->dm_ntxpending--;        }      else        {          ndbg("Bad TX count (TX2END)\n");        }    }  /* Cancel the TX timeout */  if (dm9x->dm_ntxpending == 0)    {      wd_cancel(dm9x->dm_txtimeout);    }  /* Then poll uIP for new XMIT data */  (void)uip_poll(&dm9x->dm_dev, dm9x_uiptxpoll);}/**************************************************************************** * Function: dm9x_interrupt * * Description: *   DM90x0 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 dm9x_interrupt(int irq, FAR void *context){#if CONFIG_DM9X_NINTERFACES == 1  register struct dm9x_driver_s *dm9x = &g_dm9x[0];#else# error "Additional logic needed to support multiple interfaces"#endif  uint8 isr;  uint8 save;  int i;  /* Save previous register address */  save = (uint8)DM9X_INDEX;  /* Disable all DM90x0 interrupts */  putreg(DM9X_IMR, DM9X_IMRDISABLE);   /* Get and clear the DM90x0 interrupt status bits */  isr = getreg(DM9X_ISR);  putreg(DM9X_ISR, isr);  nvdbg("Interrupt status: %02x\n", isr);  /* Check for link status change */  if (isr & DM9X_INT_LNKCHG)    {      /* Wait up to 0.5s for link OK */      for (i = 0; i < 500; i++)        {          dm9x_phyread(dm9x,0x1);          if (dm9x_phyread(dm9x,0x1) & 0x4) /*Link OK*/            {              /* Wait to get detected speed */              for (i = 0; i < 200; i++)                {                  up_mdelay(1);                }              /* Set the new network speed */              if (dm9x_phyread(dm9x, 0) & 0x2000)                {                  dm9x->dm_b100M = TRUE;                }              else                {                  dm9x->dm_b100M = FALSE;                }              break;            }          up_mdelay(1);        }      ndbg("delay: %dmS speed: %s\n", i, dm9x->dm_b100M ? "100M" : "10M");     } /* Check if we received an incoming packet */ if (isr & DM9X_INT_PR)    {      dm9x_receive(dm9x);    } /* Check if we are able to transmit a packet */ if (isr & DM9X_INT_PT)    {      dm9x_txdone(dm9x);    }  /* If the number of consecutive receive packets exceeds a threshold,    * then disable the RX interrupt.   */  if (dm9x->ncrxpackets >= DM9X_CRXTHRES)    {      /* Eanble all DM90x0 interrupts EXCEPT for RX */      putreg(DM9X_IMR, DM9X_IMRRXDISABLE);    }  else    {      /* Enable all DM90x0 interrupts */      putreg(DM9X_IMR, DM9X_IMRENABLE);    }  /* Restore previous register address */  DM9X_INDEX = save;  return OK;}/**************************************************************************** * Function: dm9x_txtimeout * * Description: *   Our TX watchdog timed out.  Called from the timer interrupt handler. *   The last TX never completed.  Reset the DM90x0 and start again. * * Parameters: *   argc - The number of available arguments *   arg  - The first argument * * Returned Value: *   None * * Assumptions: * ****************************************************************************/static void dm9x_txtimeout(int argc, uint32 arg, ...){  struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)arg;  ndbg("TX timeout\n");  /* Increment statistics and dump debug info */#if defined(CONFIG_DM9X_STATS)  dm9x->dm_ntxtimeouts++;  dm9x->dm_ntxerrors++;#endif  ndbg("  TX packet count:           %d\n", dm9x->dm_ntxpending); #if defined(CONFIG_DM9X_STATS)  ndbg("  TX timeouts:               %d\n", dm9x->dm_ntxtimeouts); #endif  ndbg("  TX read pointer address:   0x%02x:%02x\n",       getreg(DM9X_TRPAH), getreg(DM9X_TRPAL));  ndbg("  Memory data write address: 0x%02x:%02x (DM9010)\n",       getreg(DM9X_MDWAH), getreg(DM9X_MDWAL));  /* Then reset the DM90x0 */  dm9x_reset(dm9x);  /* Then poll uIP for new XMIT data */  (void)uip_poll(&dm9x->dm_dev, dm9x_uiptxpoll);}/**************************************************************************** * Function: dm9x_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 dm9x_polltimer(int argc, uint32 arg, ...){  struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)arg;  /* If the number of contiguous RX packets exceeds a threshold, reset the counter and   * re-enable RX interrupts   */  if (dm9x->ncrxpackets >= DM9X_CRXTHRES)    {      dm9x->ncrxpackets = 0;      putreg(DM9X_IMR, DM9X_IMRENABLE);    }  /* Check if there is room in the DM90x0 to hold another packet.  In 100M mode,   * that can be 2 packets, otherwise it is a single packet.   */  if (dm9x->dm_ntxpending < 1 || (dm9x->dm_b100M && dm9x->dm_ntxpending < 2))    {      /* If so, update TCP timing states and poll uIP for new XMIT data */      (void)uip_timer(&dm9x->dm_dev, dm9x_uiptxpoll, DM6X_POLLHSEC);    }  /* Setup the watchdog poll timer again */  (void)wd_start(dm9x->dm_txpoll, DM6X_WDDELAY, dm9x_polltimer, 1, arg);}/**************************************************************************** * Function: dm9x_phymode * * Description: *   Configure the PHY operating mode * * Parameters: *   dm9x  - Reference to the driver state structure * * Returned Value: *   None *

⌨️ 快捷键说明

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