#define MAX_TRANSFER_UNIT 1500 /* take in account oversized frames */
#define PBUF_LEN_MAX MAX_TRANSFER_UNIT
-#define MAX_RX_PBUF_ALLOC 10
+#define MAX_RX_PBUF_ALLOC 15 /* no need to limit it here -> better to do it in lwipopts.h */
#define MIN_PKT_LEN 60
/* Define those to better describe the network interface. */
struct rxch rxch;
#if !NO_SYS
sys_sem_t goRX;
+ uint32_t waitTicksForPHYAneg;
#endif
};
if(postInitialized) {
return FAILURE;
}
-
+ int8_t retVal = SUCCESS;
struct netif *netif = &hdkNetIF[instNum];
u8_t mac_addr[MAC_ADDR_LEN] = RPP_MAC_ADDR;
netif_set_default(netif);
-#if !NO_SYS
hdkif = (struct hdkif *) netif->state;
+#if !NO_SYS
/* ----- freeRTOS elements ----- */
/* TODO: rewrite these to functions from sys_arch.* for compatibility with other systems then freeRTOS */
/* semaphore blocking receive task (rpp_eth_recv_raw) from receive operation, till RX interrupt occurs and notify it */
vSemaphoreCreateBinary(hdkif->goRX);
/* run task rpp_eth_recv_raw */
- xTaskCreate( rpp_eth_recv_raw, "RXHandler", 500, netif, 1, NULL );
+ xTaskCreate( rpp_eth_recv_raw, "RXHandler", 500, netif, 0, NULL );
/* ----- end - freeRTOS ----- */
#endif /* !NO_SYS */
+ if(rpp_eth_linkstat(hdkif->inst_num))
+ {
+ rpp_sci_printf((const char *)"cable connected\r\n");
#if STATIC_IP_ADDRESS
- netif_set_up(netif);
+ netif_set_up(netif);
#elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
- if(dhcp_start(netif) != ERR_OK)
- {
+ if(dhcp_start(netif) != ERR_OK)
+ {
#ifdef DEBUG
- rpp_sci_printf((const char *) "dhcp mem err\r\n");
+ rpp_sci_printf((const char *) "dhcp mem err\r\n");
#endif
- return DHCP_MEM_ERR;
- }
+ return DHCP_MEM_ERR;
+ }
#ifdef DEBUG
- rpp_sci_printf((const char *) "binding DHCP\r");
+ rpp_sci_printf((const char *) "binding DHCP\r");
#endif
- while((netif->dhcp->state != DHCP_BOUND) && (dhcpBindWait--));
+ while((netif->dhcp->state != DHCP_BOUND) && (dhcpBindWait--));
#ifdef DEBUG
- if(!dhcpBindWait)
- rpp_sci_printf((const char *) "dhcp binding timeout...\r\n");
+ if(!dhcpBindWait)
+ rpp_sci_printf((const char *) "dhcp binding timeout...\r\n");
#endif
#else /* LWIP_DHCP-LWIP_AUTOIP FIXME: there should be some kind of waiting till ip is assigned */
- autoip_start(netif);
+ autoip_start(netif);
#endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
-#ifdef DEBUG/*
- rpp_sci_printf((const char *) "Address: ");
- rpp_eth_printIPDecimal(netif->ip_addr);
- rpp_sci_printf((const char *) "\r\nNetmask: ");
- rpp_eth_printIPDecimal(netif->netmask);
- rpp_sci_printf((const char *) "\r\nGateway: ");
- rpp_eth_printIPDecimal(netif->gw);
- rpp_sci_printf((const char *) "\r\n");*/
- /* rpp_eth_print_IPAddr(instNum); */
+#ifdef DEBUG
+ rpp_sci_printf((const char *) "Address: ");
+ rpp_eth_printIPDecimal(netif->ip_addr);
+ rpp_sci_printf((const char *) "\r\nNetmask: ");
+ rpp_eth_printIPDecimal(netif->netmask);
+ rpp_sci_printf((const char *) "\r\nGateway: ");
+ rpp_eth_printIPDecimal(netif->gw);
+ rpp_sci_printf((const char *) "\r\n");
+ /* rpp_eth_print_IPAddr(instNum); */
#endif
+ }
+ else
+ {
+ rpp_sci_printf((const char *)"cable not connected\r\n");
+ retVal = PHY_LINK_DOWN;
+ }
/* ----- end - lwIP stuff ----- */
postInitialized = TRUE;
- return SUCCESS;
+ return retVal;
}
err_t rpp_eth_lwip_init(struct netif *netif)
/*netif->num = instNum; - auto-initiated when netif_add is called */
/* netif->state contained instNum, we replace it with corresponding hdkif */
- netif->state = &hdkif_data[instNum];
+ struct hdkif *hdkif = &hdkif_data[instNum];
+ netif->state = hdkif;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
+
+ hdkif->waitTicksForPHYAneg = 4000;
+
/*
* Initialize the snmp variables and counters inside the struct netif.
* The last argument should be replaced with your link speed, in units
*/
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
- netif->input = ethernet_input;
/* We directly use etharp_output() here to save a function call.
* You can instead declare yo_SKIP_TO_HWur own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
err_t rpp_eth_hw_init_postInit(struct netif *netif)
{
+ volatile unsigned int autonegFinishWait = 0x3FFFFFFF; /* for 80MHz aproximately 13s */
uint16_t regContent;
uint32_t num_bd, pbuf_cnt = 0;
volatile struct emac_tx_bd *curr_txbd, *last_txbd;
rxch->active_head = (volatile struct emac_rx_bd*)(curr_txbd);
rxch->free_head = NULL;
rxch->freed_pbuf_len = 0;
- num_bd = ((SIZE_EMAC_CTRL_RAM >> 1) / sizeof(struct emac_rx_bd));
+ num_bd = ((SIZE_EMAC_CTRL_RAM >> 1) / sizeof(struct emac_rx_bd)); /* when using 20B emac_bd structs, u can allocate one more ;) (405 together rx and tx and there is still 12 bytes remaining) */
curr_rxbd = rxch->active_head;
last_rxbd = curr_rxbd;
*/
while(pbuf_cnt < MAX_RX_PBUF_ALLOC) {
p = pbuf_alloc(PBUF_RAW, PBUF_LEN_MAX, PBUF_POOL);
- pbuf_cnt++;
if(p != NULL) {
/* write the descriptors if there are enough numbers to hold the pbuf*/
/* free the allocated pbuf if no free descriptors are left */
else {
pbuf_free(p);
- pbuf_cnt--;
break;
}
}
else {
- pbuf_cnt--;
break;
}
+ pbuf_cnt++;
}
last_rxbd->next = NULL;
+#ifdef DEBUG
+ rpp_sci_printf((const char *) "last_rxbd: 0x%x\r\n",last_rxbd);
+#endif
rxch->active_tail = last_rxbd;
+ num_bd = (((uint32_t)rxch->active_tail - (uint32_t)rxch->active_head) / sizeof(struct emac_rx_bd) + 1);
+#ifdef DEBUG
+ rpp_sci_printf((const char *) "num of filled bds: %d\r\nnum of pbufs: %d\r\n", num_bd, pbuf_cnt);
+#endif
+
/* for flow control - there could be set an interrupt when we reach preset amount of receive descriptors remaining - see RXBUFFERFLOWEN */
- EMACNumFreeBufSet(hdkif->emac_base, CHANNEL, pbuf_cnt);
+ EMACNumFreeBufSet(hdkif->emac_base, CHANNEL, num_bd);
/* set header descriptor pointers - this shows EMAC which descriptor is beginning one for writing received frames/packets */
EMACRxHdrDescPtrWrite(hdkif->emac_base, (uint32_t)rxch->active_head, CHANNEL);
for (regContent = 0; regContent < 8; regContent++) /* i..channel_number */
EMACMACAddrSet(hdkif->emac_base, regContent, hdkif->mac_addr, EMAC_MACADDR_NO_MATCH_NO_FILTER);
- /* wait for autonegotiation to be done - FIXME: add waitTicks type waiting */
- while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE);
+ /* wait for autonegotiation to be done - XXX: autoneg still don't have to be done, you need to check if LINK is up in user app, using eth api fnc or netif api fnc */
+#if !NO_SYS
+ uint32_t timeToWake = hdkif->waitTicksForPHYAneg + sys_jiffies();
+ while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE && timeToWake > sys_jiffies())vTaskDelay(20); /* XXX: if init is not done at the startup, this might cause troubles */
+#else
+ while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE && autonegFinishWait--); /* wait till aneg done */
+#endif
#ifdef DEBUG
- rpp_sci_printf((const char *) "aneg finished \r\n");
+ if(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) != FALSE)
+ rpp_sci_printf((const char *) "aneg finished \r\n");
+ else
+ rpp_sci_printf((const char *) "aneg timeout \r\n");
#endif
/* check if phy link is up - it is when autoneg was completed succesfully */
err_t rpp_eth_send(struct netif * netif, struct pbuf *p)
{
+ err_t retVal = SUCCESS;
SYS_ARCH_DECL_PROTECT(lev);
/**
pbuf_ref(p);
/* call the actual transmit function */
- rpp_eth_send_raw(netif, p);
+ retVal = rpp_eth_send_raw(netif, p);
/* Return to prior interrupt state and return. */
SYS_ARCH_UNPROTECT(lev);
- return SUCCESS;
+ return retVal;
}
err_t rpp_eth_send_raw(struct netif *netif, struct pbuf *p)
volatile struct emac_tx_bd *curr_bd, *active_head, *bd_end;
struct hdkif *hdkif;
struct txch *txch;
+ err_t retVal = SUCCESS;
hdkif = (struct hdkif *) netif->state;
txch = &(hdkif->txch);
txch->active_tail = bd_end;
- return SUCCESS;
+ return retVal;
}
void rpp_eth_recv_raw(void *arg)
for(;;)
{
sys_arch_sem_wait(&(hdkif->goRX), 0);
+ /* TODO: this place is candidate for LINKINT polling (if not solved through interrupt later) */
+ //xSemaphoreTake( hdkif->goRX, 0 );
#endif
/* Get the bd which contains the earliest filled data */
processed_bd = curr_bd;
ex_len += pbuf->len;
curr_bd = curr_bd->next;
+ /* XXX: curr_bd here could be NULL */
} while((processed_bd->flags_pktlen & EMAC_DSC_FLAG_EOP) != EMAC_DSC_FLAG_EOP);
/**
* from the upper layer
*/
rxch->freed_pbuf_len += len_to_alloc;
- new_pbuf = pbuf_alloc(PBUF_RAW, (rxch->freed_pbuf_len), PBUF_POOL);
+#if !NO_SYS
+ /* if there is not enough pbufs predefined, we need application to process them and return them back to pool -> YIELD */
+ /* XXX: this is not fixed in NO_SYS version - problem is when curr_bd is set to NULL (see above), and we don't obtain new_pbuf
+ * from pool, then in *bd pointing to NULL might be such values (EMAC_DSC_FLAG_SOP == 1 &| EMAC_DSC_FLAG_OWNER == 0), that we
+ * stay cycling around */
+ do
+ {
+#endif
+ new_pbuf = pbuf_alloc(PBUF_RAW, (rxch->freed_pbuf_len), PBUF_POOL);
+#if !NO_SYS
+ if(new_pbuf != NULL)
+ break;
+ else
+ taskYIELD();
+ }while(1);
+#endif
/* Write the descriptors with the pbuf info till either of them expires */
if(new_pbuf != NULL)
{
curr_bd->bufptr = (uint8_t *)(q->payload);
- /* no support for buf_offset. RXBUFFEROFFEST register is 0 */
+ /* no support for buf_offset. RXBUFFEROFFSET register is 0 */
curr_bd->bufoff_len = (q->len) & 0xFFFF;
curr_bd->flags_pktlen = EMAC_DSC_FLAG_OWNER;