/** * \brief Initialize the allocated buffer lists for GMAC driver to transfer data. * Must be invoked after gmac_dev_init() but before RX/TX starts. * * \note If input address is not 8-byte aligned, the address is automatically * adjusted and the list size is reduced by one. * * \param p_gmac Pointer to GMAC instance. * \param p_gmac_dev Pointer to GMAC device instance. * \param p_dev_mm Pointer to the GMAC memory management control block. * \param p_tx_cb Pointer to allocated TX callback list. * * \return GMAC_OK or GMAC_PARAM. */ static uint8_t gmac_init_mem(Gmac* p_gmac, gmac_device_t* p_gmac_dev, gmac_dev_mem_t* p_dev_mm, gmac_dev_tx_cb_t* p_tx_cb) { if (p_dev_mm->us_rx_size <= 1 || p_dev_mm->us_tx_size <= 1 || p_tx_cb == NULL) { return GMAC_PARAM; } /* Assign RX buffers */ if (((uint32_t) p_dev_mm->p_rx_buffer & 0x7) || ((uint32_t) p_dev_mm->p_rx_dscr & 0x7)) { p_dev_mm->us_rx_size--; } p_gmac_dev->p_rx_buffer = (uint8_t *) ((uint32_t) p_dev_mm->p_rx_buffer & 0xFFFFFFF8); p_gmac_dev->p_rx_dscr = (gmac_rx_descriptor_t *) ((uint32_t) p_dev_mm->p_rx_dscr & 0xFFFFFFF8); p_gmac_dev->us_rx_list_size = p_dev_mm->us_rx_size; /* Assign TX buffers */ if (((uint32_t) p_dev_mm->p_tx_buffer & 0x7) || ((uint32_t) p_dev_mm->p_tx_dscr & 0x7)) { p_dev_mm->us_tx_size--; } p_gmac_dev->p_tx_buffer = (uint8_t *) ((uint32_t) p_dev_mm->p_tx_buffer & 0xFFFFFFF8); p_gmac_dev->p_tx_dscr = (gmac_tx_descriptor_t *) ((uint32_t) p_dev_mm->p_tx_dscr & 0xFFFFFFF8); p_gmac_dev->us_tx_list_size = p_dev_mm->us_tx_size; p_gmac_dev->func_tx_cb_list = p_tx_cb; /* Reset TX & RX */ gmac_reset_rx_mem(p_gmac_dev); gmac_reset_tx_mem(p_gmac_dev); /* Enable Rx and Tx, plus the statistics register */ gmac_enable_transmit(p_gmac, true); gmac_enable_receive(p_gmac, true); gmac_enable_statistics_write(p_gmac, true); /* Set up the interrupts for transmission and errors */ gmac_enable_interrupt(p_gmac, GMAC_IER_RXUBR | /* Enable receive used bit read interrupt. */ GMAC_IER_TUR | /* Enable transmit underrun interrupt. */ GMAC_IER_RLEX | /* Enable retry limit exceeded interrupt. */ GMAC_IER_TFC | /* Enable transmit buffers exhausted in mid-frame interrupt. */ GMAC_IER_TCOMP | /* Enable transmit complete interrupt. */ GMAC_IER_ROVR | /* Enable receive overrun interrupt. */ GMAC_IER_HRESP | /* Enable Hresp not OK interrupt. */ GMAC_IER_PFNZ | /* Enable pause frame received interrupt. */ GMAC_IER_PTZ); /* Enable pause time zero interrupt. */ return GMAC_OK; }
/** * \brief Register/Clear RX callback. Callback will be invoked after the next received * frame. * * When gmac_dev_read() returns GMAC_RX_NULL, the application task calls * gmac_dev_set_rx_callback() to register func_rx_cb() callback and enters suspend state. * The callback is in charge to resume the task once a new frame has been * received. The next time gmac_dev_read() is called, it will be successful. * * This function is usually invoked from the RX callback itself with NULL * callback, to unregister. Once the callback has resumed the application task, * there is no need to invoke the callback again. * * \param p_gmac_dev Pointer to the GMAC device instance. * \param func_tx_cb Receive callback function. */ void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev, gmac_dev_tx_cb_t func_rx_cb) { Gmac *p_hw = p_gmac_dev->p_hw; if (func_rx_cb == NULL) { gmac_disable_interrupt(p_hw, GMAC_IDR_RCOMP); p_gmac_dev->func_rx_cb = NULL; } else { p_gmac_dev->func_rx_cb = func_rx_cb; gmac_enable_interrupt(p_hw, GMAC_IER_RCOMP); } }
static void gmac_init_queue(Gmac* p_gmac, gmac_device_t* p_gmac_dev) { gmac_dev_mem_t gmac_dev_mm; /* Clear interrupts */ gmac_get_priority_interrupt_status(p_gmac, GMAC_QUE_2); gmac_get_priority_interrupt_status(p_gmac, GMAC_QUE_1); gmac_set_tx_priority_queue(p_gmac, (uint32_t)&gs_tx_desc_null, GMAC_QUE_2); gmac_set_tx_priority_queue(p_gmac, (uint32_t)&gs_tx_desc_null, GMAC_QUE_1); gmac_set_rx_priority_queue(p_gmac, (uint32_t)&gs_rx_desc_null, GMAC_QUE_2); gmac_set_rx_priority_queue(p_gmac, (uint32_t)&gs_rx_desc_null, GMAC_QUE_1); /* Clear interrupts */ gmac_get_interrupt_status(p_gmac); /* Fill in GMAC device memory management */ gmac_dev_mm.p_rx_buffer = gs_uc_rx_buffer; gmac_dev_mm.p_rx_dscr = gs_rx_desc; gmac_dev_mm.us_rx_size = GMAC_RX_BUFFERS; gmac_dev_mm.p_tx_buffer = gs_uc_tx_buffer; gmac_dev_mm.p_tx_dscr = gs_tx_desc; gmac_dev_mm.us_tx_size = GMAC_TX_BUFFERS; gmac_init_mem(p_gmac_dev, GMAC_QUE_0, &gmac_dev_mm, gs_tx_callback); /* Enable Rx and Tx, plus the statistics register */ gmac_enable_transmit(p_gmac, true); gmac_enable_receive(p_gmac, true); gmac_enable_statistics_write(p_gmac, true); /* Set up the interrupts for transmission and errors */ gmac_enable_interrupt(p_gmac, GMAC_IER_RLEX | /* Enable retry limit exceeded interrupt. */ GMAC_IER_RCOMP | /* Enable receive complete interrupt. */ GMAC_IER_RXUBR | /* Enable receive used bit read interrupt. */ GMAC_IER_ROVR | /* Enable receive overrun interrupt. */ GMAC_IER_TCOMP | /* Enable transmit complete interrupt. */ GMAC_IER_TUR | /* Enable transmit underrun interrupt. */ GMAC_IER_TFC | /* Enable transmit buffers exhausted in mid-frame interrupt. */ GMAC_IER_HRESP | /* Enable Hresp not OK interrupt. */ GMAC_IER_PFNZ | /* Enable pause frame received interrupt. */ GMAC_IER_PTZ); /* Enable pause time zero interrupt. */ }
/** * \brief Register/Clear RX callback. Callback will be invoked after the next received * frame. * * When gmac_dev_read() returns GMAC_RX_NULL, the application task calls * gmac_dev_set_rx_callback() to register func_rx_cb() callback and enters suspend state. * The callback is in charge to resume the task once a new frame has been * received. The next time gmac_dev_read() is called, it will be successful. * * This function is usually invoked from the RX callback itself with NULL * callback, to unregister. Once the callback has resumed the application task, * there is no need to invoke the callback again. * * \param p_gmac_dev Pointer to the GMAC device instance. * \param func_tx_cb Receive callback function. */ void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev, gmac_quelist_t queue_idx, gmac_dev_tx_cb_t func_rx_cb) { Gmac *p_hw = p_gmac_dev->p_hw; if (func_rx_cb == NULL) { if(queue_idx == GMAC_QUE_0) { gmac_disable_interrupt(p_hw, GMAC_IDR_RCOMP); } else { gmac_disable_priority_interrupt(p_hw, GMAC_IER_RCOMP, queue_idx); } p_gmac_dev->gmac_queue_list[queue_idx].func_rx_cb = NULL; } else { p_gmac_dev->gmac_queue_list[queue_idx].func_rx_cb = func_rx_cb; if(queue_idx == GMAC_QUE_0) { gmac_enable_interrupt(p_hw, GMAC_IER_RCOMP); } else { gmac_enable_priority_interrupt(p_hw, GMAC_IER_RCOMP, queue_idx); } } }