static void setTxDesc(int idx) { enet_bd_struct_t *start = (enet_bd_struct_t *)_driver.tx_desc_start_addr; /* Setup descriptor and clear statuses */ enet_hal_init_txbds(start + idx,idx ==(NUM_OF_RX_RING - 1)); enet_hal_active_txbd(BOARD_DEBUG_ENET_INSTANCE); }
static void updateTxDesc(int idx, uint8_t *buffer, uint16_t length, bool isLast) { volatile enet_bd_struct_t * bdPtr = (enet_bd_struct_t *)(_driver.tx_desc_start_addr + idx * enet_hal_get_bd_size()); bdPtr->length = HTONS(length); /* Set data length*/ bdPtr->buffer = (uint8_t *)HTONL((uint32_t)buffer); /* Set data buffer*/ bdPtr->control |= kEnetTxBdLast;//最終フラグメントのフラグね bdPtr->controlExtend1 |= kEnetTxBdTxInterrupt; bdPtr->controlExtend2 &= ~TX_DESC_UPDATED_MASK; // descriptor not updated by DMA bdPtr->control |= kEnetTxBdTransmitCrc | kEnetTxBdReady; if(isLast){ //これはデスクリプタの終了位置のフラグ bdPtr->control |=kEnetTxBdWrap; } enet_hal_active_txbd(BOARD_DEBUG_ENET_INSTANCE); }
/** \brief Low level init of the MAC and PHY. * * \param[in] netif Pointer to LWIP netif structure */ NyLPC_TBool low_level_init(const unsigned char* i_ethaddr,int i_addr_len) { enet_dev_if_t * enetIfPtr; uint32_t device = BOARD_DEBUG_ENET_INSTANCE; enet_rxbd_config_t rxbdCfg; enet_txbd_config_t txbdCfg; enet_phy_speed_t phy_speed; enet_phy_duplex_t phy_duplex; //RX/TXメモリはデバイス選択時に確保 k64f_init_eth_hardware(); /* Initialize device*/ enetIfPtr = (enet_dev_if_t *)&enetDevIf[device]; enetIfPtr->deviceNumber = device; enetIfPtr->macCfgPtr = &g_enetMacCfg[device]; enetIfPtr->phyCfgPtr = &g_enetPhyCfg[device]; enetIfPtr->macApiPtr = &g_enetMacApi; enetIfPtr->phyApiPtr = (void *)&g_enetPhyApi; //macアドレスのコピー memcpy(enetIfPtr->macCfgPtr->macAddr,(char*)i_ethaddr,i_addr_len); //enetIfPtr->macContextPtrはgetInterface if(ENET_MAC_CONTEXT_BUF!=NULL){ free(ENET_MAC_CONTEXT_BUF); ENET_MAC_CONTEXT_BUF=NULL; } ENET_MAC_CONTEXT_BUF=calloc(1, sizeof(enet_mac_context_t)); if(ENET_MAC_CONTEXT_BUF==NULL){ return NyLPC_TBool_FALSE;//ERR_BUF; } enetIfPtr->macContextPtr = (enet_mac_context_t *)ENET_MAC_CONTEXT_BUF; /* Initialize enet buffers*/ if(!k64f_rx_setup(&rxbdCfg)) { return NyLPC_TBool_FALSE;//ERR_BUF; } /* Initialize enet buffers*/ if(!k64f_tx_setup(&txbdCfg)) { return NyLPC_TBool_FALSE;//ERR_BUF; } /* Initialize enet module*/ if (enet_mac_init(enetIfPtr, &rxbdCfg, &txbdCfg) == kStatus_ENET_Success) { /* Initialize PHY*/ if (enetIfPtr->macCfgPtr->isPhyAutoDiscover) { if (((enet_phy_api_t *)(enetIfPtr->phyApiPtr))->phy_auto_discover(enetIfPtr) != kStatus_PHY_Success) return NyLPC_TBool_FALSE;//ERR_IF; } if (((enet_phy_api_t *)(enetIfPtr->phyApiPtr))->phy_init(enetIfPtr) != kStatus_PHY_Success) return NyLPC_TBool_FALSE;//ERR_IF; enetIfPtr->isInitialized = true; }else{ // TODOETH: cleanup memory return NyLPC_TBool_FALSE;//ERR_IF; } /* Get link information from PHY */ phy_get_link_speed(enetIfPtr, &phy_speed); phy_get_link_duplex(enetIfPtr, &phy_duplex); BW_ENET_RCR_RMII_10T(enetIfPtr->deviceNumber, phy_speed == kEnetSpeed10M ? kEnetCfgSpeed10M : kEnetCfgSpeed100M); BW_ENET_TCR_FDEN(enetIfPtr->deviceNumber, phy_duplex == kEnetFullDuplex ? kEnetCfgFullDuplex : kEnetCfgHalfDuplex); /* Enable Ethernet module*/ enet_hal_config_ethernet(device, true, true); /* Active Receive buffer descriptor must be done after module enable*/ enet_hal_active_rxbd(enetIfPtr->deviceNumber); enet_hal_active_txbd(enetIfPtr->deviceNumber); return NyLPC_TBool_TRUE;//ERR_OK; }
/** \brief Low level output of a packet. Never call this from an * interrupt context, as it may block until TX descriptors * become available. * * \param[in] netif the lwip network interface structure for this netif * \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type) * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent */ static err_t k64f_low_level_output(struct netif *netif, struct pbuf *p) { struct k64f_enetdata *k64f_enet = netif->state; struct pbuf *q; u32_t idx; s32_t dn; uint8_t *psend = NULL, *dst; /* Get free TX buffer index */ idx = k64f_enet->tx_produce_index; /* Check the pbuf chain for payloads that are not 8-byte aligned. If found, a new properly aligned buffer needs to be allocated and the data copied there */ for (q = p; q != NULL; q = q->next) if (((u32_t)q->payload & (TX_BUF_ALIGNMENT - 1)) != 0) break; if (q != NULL) { // Allocate properly aligned buffer psend = (uint8_t*)malloc(p->tot_len); if (NULL == psend) return ERR_MEM; LWIP_ASSERT("k64f_low_level_output: buffer not properly aligned", ((u32_t)psend & (TX_BUF_ALIGNMENT - 1)) == 0); for (q = p, dst = psend; q != NULL; q = q->next) { MEMCPY(dst, q->payload, q->len); dst += q->len; } k64f_enet->txb_aligned[idx] = psend; dn = 1; } else { k64f_enet->txb_aligned[idx] = NULL; dn = (s32_t) pbuf_clen(p); pbuf_ref(p); } /* Wait until enough descriptors are available for the transfer. */ /* THIS WILL BLOCK UNTIL THERE ARE ENOUGH DESCRIPTORS AVAILABLE */ while (dn > k64f_tx_ready(netif)) osSemaphoreWait(k64f_enet->xTXDCountSem.id, osWaitForever); /* Get exclusive access */ sys_mutex_lock(&k64f_enet->TXLockMutex); /* Setup transfers */ q = p; while (dn > 0) { dn--; if (psend != NULL) { k64f_update_txbds(k64f_enet, idx, psend, p->tot_len, 1); k64f_enet->txb[idx] = NULL; LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, ("k64f_low_level_output: aligned packet(%p) sent" " size = %d (index=%d)\n", psend, p->tot_len, idx)); } else { LWIP_ASSERT("k64f_low_level_output: buffer not properly aligned", ((u32_t)q->payload & 0x07) == 0); /* Only save pointer to free on last descriptor */ if (dn == 0) { /* Save size of packet and signal it's ready */ k64f_update_txbds(k64f_enet, idx, q->payload, q->len, 1); k64f_enet->txb[idx] = p; } else { /* Save size of packet, descriptor is not last */ k64f_update_txbds(k64f_enet, idx, q->payload, q->len, 0); k64f_enet->txb[idx] = NULL; } LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, ("k64f_low_level_output: pbuf packet(%p) sent, chain#=%d," " size = %d (index=%d)\n", q->payload, dn, q->len, idx)); } q = q->next; idx = (idx + 1) % ENET_TX_RING_LEN; } k64f_enet->tx_produce_index = idx; enet_hal_active_txbd(BOARD_DEBUG_ENET_INSTANCE_ADDR); LINK_STATS_INC(link.xmit); /* Restore access */ sys_mutex_unlock(&k64f_enet->TXLockMutex); return ERR_OK; }