Example #1
0
/**
 * This function with either place the packet into the Stellaris transmit fifo,
 * or will place the packet in the interface PBUF Queue for subsequent
 * transmission when the transmitter becomes idle.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
 * @return ERR_OK if the packet could be sent
 *         an err_t value if the packet couldn't be sent
 *
 */
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
	err_t status;

	// Bump the reference count on the pbuf to prevent it from being
	// freed till we are done with it.  
	pbuf_ref(p);

	// Prevent from simultaneously writing to ETH TX FIFO    	
	xSemaphoreTake(ETHTxAccessMutex[0], ( portTickType ) portMAX_DELAY);

	// If Semaphore was given previously -> take it
	while (xSemaphoreTake(ETHTxBinSemaphore[0], ( portTickType ) 0) == pdTRUE)
		;

	// If the transmitter is idle, send the pbuf now.
	if (((HWREG(ETH_BASE + MAC_O_TR) & MAC_TR_NEWTX) == 0))
	{
		// Send packet via eth controller
		status = low_level_transmit(netif, p);
	}
	else
	{
		LWIP_DEBUGF(CORTEX_DEBUG, ("low_level_output: Ethernet transmitter busy\n"));
		// Enable generating transmit interrupt for eth. controller
		EthernetIntEnable(ETH_BASE, ETH_INT_TX);

		// Waiting for finishing transmitting from interrupt routine
		xSemaphoreTake(ETHTxBinSemaphore[0], ( portTickType ) portMAX_DELAY);

		// Send packet via eth controller
		status = low_level_transmit(netif, p);

		// Disable generating transmit interrupt for eth. controller
		EthernetIntDisable(ETH_BASE, ETH_INT_TX);
	}

	// Release mutex
	xSemaphoreGive(ETHTxAccessMutex[0]);
	//pf	vTaskDelay(10 / portTICK_RATE_MS);

	pbuf_free(p);

	return status;
}
Example #2
0
/*..........................................................................*/
void eth_driver_write(void) {
    if ((ETH->TR & MAC_TR_NEWTX) == 0) {                  /* TX fifo empty? */
        struct pbuf *p = l_txq.get();
        if (p != NULL) {                        /* pbuf found in the queue? */
            low_level_transmit(p);
            pbuf_free(p);        /* free the pbuf, lwIP knows nothing of it */
        }
    }
}
Example #3
0
/**
 * Process tx and rx packets at the low-level interrupt.
 *
 * Should be called from the Stellaris Ethernet Interrupt Handler.  This
 * function will read packets from the Stellaris Ethernet fifo and place them
 * into a pbuf queue.  If the transmitter is idle and there is at least one packet
 * on the transmit queue, it will place it in the transmit fifo and start the
 * transmitter.
 *
 */
void
stellarisif_interrupt(struct netif *netif)
{
  struct ethernetif *ethernetif;
  struct pbuf *p;

  /* setup pointer to the if state data */
  ethernetif = netif->state;

  /**
   * Process the transmit and receive queues as long as there is receive
   * data available
   *
   */
  p = low_level_receive(netif);
  while(p != NULL) {
    /* Add the rx packet to the rx queue */
    if(!enqueue_packet(p, &ethernetif->rxq)) {
      /* Could not place the packet on the queue, bail out. */
      pbuf_free(p);
      break;
    }

    /* Check if TX fifo is empty and packet available */
    if((HWREG(ETH_BASE + MAC_O_TR) & MAC_TR_NEWTX) == 0) {
      p = dequeue_packet(&ethernetif->txq);
      if(p != NULL) {
        low_level_transmit(netif, p);
      }
    }

    /* Read another packet from the RX fifo */
    p = low_level_receive(netif);
  }

  /* One more check of the transmit queue/fifo */
  if((HWREG(ETH_BASE + MAC_O_TR) & MAC_TR_NEWTX) == 0) {
    p = dequeue_packet(&ethernetif->txq);
    if(p != NULL) {
      low_level_transmit(netif, p);
    }
  }
}
Example #4
0
/**
 * This function with either place the packet into the Stellaris transmit fifo,
 * or will place the packet in the interface PBUF Queue for subsequent
 * transmission when the transmitter becomes idle.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
 * @return ERR_OK if the packet could be sent
 *         an err_t value if the packet couldn't be sent
 *
 */
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
	LWIP_DRIVER_DATA* drv_data = (LWIP_DRIVER_DATA*)netif;
	MAC_Type* mac = (MAC_Type*)netif->state;
	SYS_ARCH_DECL_PROTECT(lev);

	/**
	 * This entire function must run within a "critical section" to preserve
	 * the integrity of the transmit pbuf queue.
	 *
	 */
	SYS_ARCH_PROTECT(lev);

	/**
	 * Bump the reference count on the pbuf to prevent it from being
	 * freed till we are done with it.
	 *
	 */
	pbuf_ref(p);

	/**
	 * If the transmitter is idle, and there is nothing on the queue,
	 * send the pbuf now.
	 *
	 */
	if (PBUF_QUEUE_EMPTY(&drv_data->txq) && ((mac->MACTR & MAC_TR_NEWTX) == 0))
	{
		low_level_transmit(netif, p);
	}

	/* Otherwise place the pbuf on the transmit queue. */
	else
	{
		/* Add to transmit packet queue */
		if (!enqueue_packet(p, &drv_data->txq))
		{
			/* if no room on the queue, free the pbuf reference and return error. */
			pbuf_free(p);
			SYS_ARCH_UNPROTECT(lev);
			return (ERR_MEM);
		}
	}

	/* Return to prior interrupt state and return. */
	SYS_ARCH_UNPROTECT(lev);
	return (ERR_OK);
}
Example #5
0
/*
 * This function will either write the pbuf into the Stellaris TX FIFO,
 * or will put the packet in the TX queue of pbufs for subsequent
 * transmission when the transmitter becomes idle.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @param p the pbuf to send
 * @return ERR_OK if the packet could be sent
 *         an err_t value if the packet couldn't be sent
 *
 */
static err_t ethernetif_output(struct netif *netif, struct pbuf *p) {
    if (l_txq.isEmpty() &&                      /* nothing in the TX queue? */
        ((ETH->TR & MAC_TR_NEWTX) == 0))                       /* TX empty? */
    {
        low_level_transmit(p);                  /* send the pbuf right away */
        /* the pbuf will be freed by the lwIP code */
    }
    else {                 /* otherwise post the pbuf to the transmit queue */
        if (l_txq.put(p)) {             /*could the TX queue take the pbuf? */
            pbuf_ref(p);     /* reference the pbuf to spare it from freeing */
        }
        else {                                      /* no room in the queue */
            /* the pbuf will be freed by the lwIP code */
            return ERR_MEM;
        }
    }
    return ERR_OK;
}
Example #6
0
/*..........................................................................*/
void eth_driver_read(void) {
    struct pbuf *p = low_level_receive();
    if (p != NULL) {                  /* new packet received into the pbuf? */
        if (ethernet_input(p, &l_netif) != ERR_OK) {   /* pbuf not handled? */
            LWIP_DEBUGF(NETIF_DEBUG, ("eth_driver_input: input error\n"));
            pbuf_free(p);                                  /* free the pbuf */
        }

        /* try to output a packet if TX fifo is empty and pbuf is available */
        if ((ETH->TR & MAC_TR_NEWTX) == 0) {
            p = l_txq.get();
            if (p != NULL) {
                low_level_transmit(p);
                pbuf_free(p);    /* free the pbuf, lwIP knows nothing of it */
            }
        }
    }

    ETH->IM |= ETH_INT_RX;                    /* re-enable the RX interrupt */
}