/** * Send the data p over interface netif * * @param netif the netif to send the data * @param p the pbuf containing the data * @return An error code */ static err_t eth_output(struct netif *netif, struct pbuf *p) { /* Wait for previous DMA (one could also implement queueing here...) */ while (dma_running) ; /* * Free the memory */ if (active_dma != NULL) { pbuf_free(active_dma); #ifdef DEBUG_MALLOC UARTprintf("%x %d free, %s:%d;\r\n", active_dma, debug_ctr++, __FILE__, __LINE__); #endif } active_dma = p; dma_running = 1; /* Reserve the pbuf so that it is not free()d */ pbuf_ref(p); char *buf = p->payload; int len = p->len; uint16_t *len_buf = (uint16_t*)buf; *len_buf = len - PBUF_LINK_HLEN; len += 2; /** * If this enters the infinite loop, the buffer is not correctly aligned! */ if (((unsigned long) buf & 3) != 0) for (;;) ; /* Ensure that DMA sends all the data (and up to 3 bytes garbage extra) */ while ((len & 3) != 0) len++; /* * Configure the TX DMA channel to transfer the packet buffer. */ uDMAChannelTransferSet(UDMA_CHANNEL_ETH0TX, UDMA_MODE_AUTO, buf, (void *) (ETH_BASE + MAC_O_DATA), len >> 2); /* * Enable the Ethernet Transmit DMA channel. */ uDMAChannelEnable(UDMA_CHANNEL_ETH0TX); /* * Issue a software request to start the channel running. */ uDMAChannelRequest(UDMA_CHANNEL_ETH0TX); return ERR_OK; }
//***************************************************************************** // // Configure the SysTick and SysTick interrupt with a period of 1 second. // //***************************************************************************** int main(void) { uint16_t i; // // Set the clocking to run directly from the external crystal/oscillator. // (no ext 32k osc, no internal osc) // SysCtrlClockSet(false, false, SYS_CTRL_SYSDIV_32MHZ); // // Set IO clock to the same as system clock // SysCtrlIOClockSet(SYS_CTRL_SYSDIV_32MHZ); // // Set up the serial console to use for displaying messages. This is // just for this example program and is not needed for Systick operation. // InitConsole(); // // Display the setup on the console. // UARTprintf("DMA SW example mem to mem!\n"); // // Fill Source buffer with some data // for(i=0; i<256; i++) { ucSourceBuffer[i] = '0' + (i % 10); } // // Enable the uDMA controller. // uDMAEnable(); // // Set the base for the channel control table. // uDMAControlBaseSet(&ucDMAControlTable[0]); // // No attributes must be set for a software-based transfer. // The attributes are cleared by default, but are explicitly cleared // here, in case they were set elsewhere. // uDMAChannelAttributeDisable(UDMA_CH30_SW, UDMA_ATTR_ALL); // // Now set up the characteristics of the transfer for // 8-bit data size, with source and destination increments // in bytes, and a byte-wise buffer copy. A bus arbitration // size of 8 is used. // uDMAChannelControlSet(UDMA_CH30_SW | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_8 | UDMA_ARB_8); // // The transfer buffers and transfer size are now configured. // The transfer uses AUTO mode, which means that the // transfer automatically runs to completion after the first // request. // uDMAChannelTransferSet(UDMA_CH30_SW | UDMA_PRI_SELECT, UDMA_MODE_AUTO, ucSourceBuffer, ucDestBuffer, sizeof(ucDestBuffer)); // // Enable Interrupt for DMA // IntEnable(INT_UDMA); // // Finally, the channel must be enabled. Because this is a // software-initiated transfer, a request must also be made. // The request starts the transfer. // uDMAChannelEnable(UDMA_CH30_SW); uDMAChannelRequest(UDMA_CH30_SW); // // Put cpu to sleep and wait for interrupt (when DMA transfer is done) // SysCtrlSleep(); // // Loop forever while the SysTick runs. // while(1) { } }