#include "eth_drv_etherlib.h" #include #include #include "cmsis_os2.h" #include "mac_drv.h" #include "phy_drv/phy_common.h" #include #include // ------------------------------------- // --------- Ethernet buffers ---------- // ------------------------------------- #define ETH_BUFFER_SIZE (1536UL) uint8_t ETHBuffer[(ETH_RX_DESC_CNT + ETH_TX_DESC_CNT) * ETH_BUFFER_SIZE] __attribute__((section(".ETHBufferSection"))); /* Ethernet Receive Buffers */ struct { ETHHW_State ETHState; ETHHW_DescFull DMARxDscrTab[ETH_RX_DESC_CNT]; ETHHW_DescFull DMATxDscrTab[ETH_TX_DESC_CNT]; } ETHStateAndDesc __attribute__((section(".ETHStateAndDecripSection"))); // ------------------------------------- // ---------- Global objects ----------- // ------------------------------------- static EthIODef ioDef; static osTimerId_t eventTmr; int ethdrv_send(EthIODef *io, MsgQueue *mq); int ethdrv_read(); static void process_phy_event(); static int ethdrv_trigger_link_change_int(EthIODef * io) { process_phy_event(); return 0; } static void process_phy_event() { PHY_Event evt = phy_get_event(); // get event if (evt != PHYEVENT_NO_EVENT) { if (ioDef.llLinkChg != NULL) { int up = evt == PHYEVENT_AUTONEGOTIATION_DONE; // link properties uint16_t speed = 0; bool duplex = false; // if link is up, then set link properties accordingly if (up) { const PHY_LinkStatus * status = phy_get_link_status(); bool fe = status->speed == PHY_LS_100Mbps; duplex = status->type == PHY_LT_FULL_DUPLEX; ETHHW_SetLinkProperties(ETH, fe, duplex); // convert "Fast Ethernet" to numerical speed value speed = (status->speed == PHY_LS_100Mbps) ? 100 : 10; } // invoke link change notification callback ioDef.llLinkChg(&ioDef, up, speed, duplex); } } } static void event_check_tmr_cb(void * arg) { process_phy_event(); } void ethdrv_init() { // ------- Ethernet MAC initialization ----- ETHHW_InitOpts opts = { .statePtr = &(ETHStateAndDesc.ETHState), .rxRingLen = ETH_RX_DESC_CNT, .bufPtr = ETHBuffer, .rxRingPtr = (uint8_t *)ETHStateAndDesc.DMARxDscrTab, .txRingLen = ETH_TX_DESC_CNT, .txRingPtr = (uint8_t *)ETHStateAndDesc.DMATxDscrTab, .blockSize = ETH_BUFFER_SIZE, .mac = {ETH_MAC_ADDR0, ETH_MAC_ADDR1, ETH_MAC_ADDR2, ETH_MAC_ADDR3, ETH_MAC_ADDR4, ETH_MAC_ADDR5}}; ETHHW_Init(ETH, &opts); ETHHW_Start(ETH); // -------- IODef initialization ----------- memset(&ioDef, 0, sizeof(EthIODef)); ioDef.llTxTrigger = ethdrv_send; ioDef.llRxRead = ethdrv_read; ioDef.llTrigLinkChg = ethdrv_trigger_link_change_int; // -------- Start loop that periodically pools PHY interrupts eventTmr = osTimerNew(event_check_tmr_cb, osTimerPeriodic, NULL, NULL); osTimerStart(eventTmr, 1000); } int ethdrv_read() { ETHHW_ProcessRx(ETH); return 0; } int ETHHW_ReadCallback(ETHHW_EventDesc *evt) { // packet reception if (evt->type != ETHHW_EVT_RX_READ) { return 0; } // allocate raw buffer RawPckt pckt; uint16_t size = evt->data.rx.size; uint8_t *plBuf = dynmem_alloc(size); if (plBuf == NULL) { MSG("malloc failed in ethdrv_input()!"); return 0; // processing failed } // fill-in packet data pckt.payload = plBuf; pckt.size = size; pckt.ext.rx.time_s = evt->data.rx.ts_s; pckt.ext.rx.time_ns = evt->data.rx.ts_ns; // copy data memcpy(pckt.payload, evt->data.rx.payload, size); // copy payload if (ioDef.llRxStore != NULL) { ioDef.llRxStore(&ioDef, &pckt); } return ETHHW_RET_RX_PROCESSED; } int ETHHW_EventCallback(ETHHW_EventDesc *evt) { if (evt->type == ETHHW_EVT_RX_NOTFY) { if (ioDef.llRxNotify != NULL) { ioDef.llRxNotify(&ioDef); } } return 0; // unhandled event } int ethdrv_output(const RawPckt *pckt) { // check if timestamping is demanded uint8_t opts = ETHHW_TXOPT_NONE; bool tsEn = (pckt->ext.tx.txTsCb != NULL); ETHHW_OptArg_TxTsCap optArg; if (tsEn) { opts = ETHHW_TXOPT_CAPTURE_TS; optArg.txTsCbPtr = (uint32_t)pckt->ext.tx.txTsCb; optArg.tag = pckt->ext.tx.arg; } // transmit ETHHW_Transmit(ETH, pckt->payload, pckt->size, opts, &optArg); return 0; } int ethdrv_send(EthIODef *io, MsgQueue *mq) { uint32_t bytes_sent = 0; if (mq_avail(mq) > 0) { RawPckt pckt = mq_top(mq); mq_pop(mq); int ret = ethdrv_output(&pckt); if (ret != 0) { MSG("Tx ERROR!\n"); } bytes_sent += pckt.size; dynmem_free(pckt.payload); //MSGraw("TX\r\n"); } return (int)bytes_sent; } EthIODef *ethdrv_get() { return &ioDef; } // ------------- void ETH_IRQHandler() { ETHHW_ISR(ETH); }