1 #include "pic32_c.h" 2 #include "init.h" 3 #include "debug.h" 4 5 static const char message1[] = "Hello!\r\n"; 6 static const char message2[] = "Again!\r\n"; 7 static int uart_echo = 0; 8 9 static void blink(uint32_t delay, uint32_t port, uint32_t pins) 10 { 11 uint32_t counter; 12 13 /* Clear outputs (LED). */ 14 15 CLR_REG(port, pins); 16 17 while (1) 18 { 19 counter = delay; 20 21 while (counter--) __asm__(""); /* retain loop */ 22 23 /* Invert outputs (LED). */ 24 25 INV_REG(port, pins); 26 } 27 } 28 29 void main(void) 30 { 31 init_memory(); 32 init_pins(); 33 init_outputs(); 34 35 unlock_config(); 36 config_uart(); 37 lock_config(); 38 39 init_dma(); 40 41 /* Initiate DMA on the Timer2 interrupt. Since the channel is not 42 auto-enabled, it must be explicitly enabled upon completion. */ 43 44 dma_init(0, 3); 45 dma_set_interrupt(0, T2, 1); 46 dma_set_transfer(0, PHYSICAL((uint32_t) message1), sizeof(message1) - 1, 47 HW_PHYSICAL(UART_REG(1, UxTXREG)), 1, 48 1); 49 50 /* Enable DMA on the preceding channel's completion, with OC1 initiating 51 transfers, raising a transfer completion interrupt to be handled. */ 52 53 dma_init(1, 3); 54 dma_set_chaining(1, dma_chain_previous); 55 dma_set_interrupt(1, OC1, 1); 56 dma_set_transfer(1, PHYSICAL((uint32_t) message2), sizeof(message2) - 1, 57 HW_PHYSICAL(UART_REG(1, UxTXREG)), 1, 58 1); 59 dma_init_interrupt(1, 0b00001000, 7, 3); 60 61 /* Configure a timer for the first DMA channel whose interrupt condition 62 drives the transfer but is not handled (having a lower priority than the 63 CPU. */ 64 65 timer_init(2, 0b111, 60000); 66 timer_init_interrupt(2, 1, 3); 67 timer_on(2); 68 69 /* Configure a timer for the output compare unit below. */ 70 71 timer_init(3, 0b111, 20000); 72 timer_on(3); 73 74 /* Configure output compare in dual compare (continuous output) mode using 75 Timer3 as time base. The interrupt condition drives the second DMA 76 channel but is not handled (having a lower priority than the CPU). */ 77 78 oc_init(1, 0b101, 3); 79 oc_set_pulse(1, 10000); 80 oc_set_pulse_end(1, 20000); 81 oc_init_interrupt(1, 1, 3); 82 oc_on(1); 83 84 /* Set UART interrupt priority above CPU priority to process events. */ 85 86 uart_init(1, 115200); 87 uart_init_interrupt(1, UxRIF, 7, 3); 88 uart_on(1); 89 90 interrupts_on(); 91 92 blink(3 << 24, PORTA, 1 << 3); 93 } 94 95 void exception_handler(void) 96 { 97 blink(3 << 12, PORTA, 1 << 3); 98 } 99 100 void interrupt_handler(void) 101 { 102 uint32_t ifs, val; 103 104 /* Check for a UART receive interrupt condition (UxRIF). */ 105 106 ifs = REG(UARTIFS) & UART_INT_FLAGS(1, UxRIF); 107 108 if (ifs) 109 { 110 /* Clear the UART interrupt condition. */ 111 112 CLR_REG(UARTIFS, ifs); 113 114 /* Write the received data back. */ 115 116 while (REG(UART_REG(1, UxSTA)) & 1) 117 { 118 val = REG(UART_REG(1, UxRXREG)); 119 if (uart_echo) 120 uart_write((char) val); 121 122 /* Initiate transfer upon receiving a particular character. */ 123 124 if (val == '0') 125 dma_on(0); 126 } 127 } 128 129 /* Check for a DMA interrupt condition (CHBCIF). */ 130 131 ifs = REG(DMAIFS) & DMA_INT_FLAGS(1, 1); 132 133 if (ifs) 134 { 135 INV_REG(PORTA, 1 << 2); 136 CLR_REG(DMA_REG(0, DCHxINT), 0b11111111); 137 CLR_REG(DMAIFS, ifs); 138 139 dma_on(0); 140 } 141 }