1 /* 2 * A demonstration of various PIC32 peripherals. 3 * 4 * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 21 #include "pic32_c.h" 22 #include "init.h" 23 #include "debug.h" 24 25 static const char message1[] = "Hello!\r\n"; 26 static const char message2[] = "Again!\r\n"; 27 static int uart_echo = 0; 28 29 30 31 static void blink(uint32_t delay, uint32_t port, uint32_t pins) 32 { 33 uint32_t counter; 34 35 /* Clear outputs (LED). */ 36 37 CLR_REG(port, pins); 38 39 while (1) 40 { 41 counter = delay; 42 43 while (counter--) __asm__(""); /* retain loop */ 44 45 /* Invert outputs (LED). */ 46 47 INV_REG(port, pins); 48 } 49 } 50 51 void main(void) 52 { 53 init_memory(); 54 init_pins(); 55 init_outputs(); 56 57 unlock_config(); 58 config_uart(); 59 lock_config(); 60 61 init_dma(); 62 63 /* Initiate DMA on the Timer2 interrupt. Since the channel is not 64 auto-enabled, it must be explicitly enabled upon completion. */ 65 66 dma_init(0, 3); 67 dma_set_interrupt(0, T2, 1); 68 dma_set_transfer(0, PHYSICAL((uint32_t) message1), sizeof(message1) - 1, 69 HW_PHYSICAL(UART_REG(1, UxTXREG)), 1, 70 1); 71 72 /* Enable DMA on the preceding channel's completion, with OC1 initiating 73 transfers, raising a transfer completion interrupt to be handled. */ 74 75 dma_init(1, 3); 76 dma_set_chaining(1, dma_chain_previous); 77 dma_set_interrupt(1, OC1, 1); 78 dma_set_transfer(1, PHYSICAL((uint32_t) message2), sizeof(message2) - 1, 79 HW_PHYSICAL(UART_REG(1, UxTXREG)), 1, 80 1); 81 dma_init_interrupt(1, 0b00001000, 7, 3); 82 83 /* Configure a timer for the first DMA channel whose interrupt condition 84 drives the transfer but is not handled (having a lower priority than the 85 CPU. */ 86 87 timer_init(2, 0b111, 60000); 88 timer_init_interrupt(2, 1, 3); 89 timer_on(2); 90 91 /* Configure a timer for the output compare unit below. */ 92 93 timer_init(3, 0b111, 20000); 94 timer_on(3); 95 96 /* Configure output compare in dual compare (continuous output) mode using 97 Timer3 as time base. The interrupt condition drives the second DMA 98 channel but is not handled (having a lower priority than the CPU). */ 99 100 oc_init(1, 0b101, 3); 101 oc_set_pulse(1, 10000); 102 oc_set_pulse_end(1, 20000); 103 oc_init_interrupt(1, 1, 3); 104 oc_on(1); 105 106 /* Set UART interrupt priority above CPU priority to process events. */ 107 108 uart_init(1, 115200); 109 uart_init_interrupt(1, UxRIF, 7, 3); 110 uart_on(1); 111 112 interrupts_on(); 113 114 blink(3 << 24, PORTA, 1 << 3); 115 } 116 117 void exception_handler(void) 118 { 119 blink(3 << 12, PORTA, 1 << 3); 120 } 121 122 void interrupt_handler(void) 123 { 124 uint32_t ifs, val; 125 126 /* Check for a UART receive interrupt condition (UxRIF). */ 127 128 ifs = REG(UARTIFS) & UART_INT_FLAGS(1, UxRIF); 129 130 if (ifs) 131 { 132 /* Clear the UART interrupt condition. */ 133 134 CLR_REG(UARTIFS, ifs); 135 136 /* Write the received data back. */ 137 138 while (REG(UART_REG(1, UxSTA)) & 1) 139 { 140 val = REG(UART_REG(1, UxRXREG)); 141 if (uart_echo) 142 uart_write((char) val); 143 144 /* Initiate transfer upon receiving a particular character. */ 145 146 if (val == '0') 147 dma_on(0); 148 } 149 } 150 151 /* Check for a DMA interrupt condition (CHBCIF). */ 152 153 ifs = REG(DMAIFS) & DMA_INT_FLAGS(1, 1); 154 155 if (ifs) 156 { 157 INV_REG(PORTA, 1 << 2); 158 CLR_REG(DMA_REG(0, DCHxINT), 0b11111111); 159 CLR_REG(DMAIFS, ifs); 160 161 dma_on(0); 162 } 163 }