# HG changeset patch # User Paul Boddie # Date 1540315054 -7200 # Node ID d00ca7551358958605b63c85c66c2b630bf2d2da # Parent 06aa97e33e1e84722475a42d19a982d6bca86b7c Experiment with interleaved DMA channels. diff -r 06aa97e33e1e -r d00ca7551358 examples/demo/main.c --- a/examples/demo/main.c Tue Oct 23 19:09:04 2018 +0200 +++ b/examples/demo/main.c Tue Oct 23 19:17:34 2018 +0200 @@ -24,7 +24,21 @@ #include "main.h" static const char message1[] = "Hello!\r\n"; -static const char message2[] = "Again!\r\n"; + +#define CELLSIZE4 + +#ifdef CELLSIZE1 +static const char message2[] = "Adoc gi,hlo\r"; +static const char message3[] = "n neaan el!\n"; +#define CELLSIZE 1 +#endif + +#ifdef CELLSIZE4 +static const char message2[] = "And agahell"; +static const char message3[] = "oncein, o!\r\n"; +#define CELLSIZE 4 +#endif + static int uart_echo; @@ -71,32 +85,45 @@ /* Peripheral relationships: - Timer2 -> DMA0: message1 -> U1TXREG + Timer3 -> OC1 -> DMA0: message2 -> U1TXREG + ___/ + / + Timer2 -> DMA1: message1 -> U1TXREG \___ \ - Timer3 -> OC1 -> DMA1: message2 -> U1TXREG + Timer3 -> OC1 -> DMA2: message3 -> U1TXREG */ + /* Enable DMA on the next channel's completion, with OC1 initiating + transfers, raising a transfer completion interrupt to be handled. */ + + dma_init(0, 2); + dma_set_chaining(0, dma_chain_next); + dma_set_interrupt(0, OC1, 1); + dma_set_transfer(0, PHYSICAL((uint32_t) message2), sizeof(message2) - 1, + HW_PHYSICAL(UART_REG(1, UxTXREG)), 1, + CELLSIZE); + /* Initiate DMA on the Timer2 interrupt. Since the channel is not auto-enabled, it must be explicitly enabled elsewhere (when a UART interrupt is handled). */ - dma_init(0, 3); - dma_set_interrupt(0, T2, 1); - dma_set_transfer(0, PHYSICAL((uint32_t) message1), sizeof(message1) - 1, + dma_init(1, 3); + dma_set_interrupt(1, T2, 1); + dma_set_transfer(1, PHYSICAL((uint32_t) message1), sizeof(message1) - 1, HW_PHYSICAL(UART_REG(1, UxTXREG)), 1, 1); /* Enable DMA on the preceding channel's completion, with OC1 initiating transfers, raising a transfer completion interrupt to be handled. */ - dma_init(1, 3); - dma_set_chaining(1, dma_chain_previous); - dma_set_interrupt(1, OC1, 1); - dma_set_transfer(1, PHYSICAL((uint32_t) message2), sizeof(message2) - 1, + dma_init(2, 2); + dma_set_chaining(2, dma_chain_previous); + dma_set_interrupt(2, OC1, 1); + dma_set_transfer(2, PHYSICAL((uint32_t) message3), sizeof(message3) - 1, HW_PHYSICAL(UART_REG(1, UxTXREG)), 1, - 1); - dma_init_interrupt(1, 0b00001000, 7, 3); + CELLSIZE); + dma_init_interrupt(2, 0b00001000, 7, 3); /* Configure a timer for the first DMA channel whose interrupt condition drives the transfer. The interrupt itself does not need to be enabled. */ @@ -165,19 +192,19 @@ /* Initiate transfer upon receiving a particular character. */ if (val == '0') - dma_on(0); + dma_on(1); } } /* Check for a DMA interrupt condition (CHBCIF). */ - ifs = REG(DMAIFS) & DMA_INT_FLAGS(1, DCHxIF); + ifs = REG(DMAIFS) & DMA_INT_FLAGS(2, DCHxIF); if (ifs) { uart_write_string("CHBCIF\r\n"); INV_REG(PORTA, 1 << 2); - CLR_REG(DMA_REG(1, DCHxINT), 0b11111111); + CLR_REG(DMA_REG(2, DCHxINT), 0b11111111); CLR_REG(DMAIFS, ifs); } }