paul@0 | 1 | #include "cpu.h" |
paul@0 | 2 | #include "pic32_c.h" |
paul@0 | 3 | |
paul@0 | 4 | |
paul@0 | 5 | |
paul@0 | 6 | /* Basic memory and pin initialisation. */ |
paul@0 | 7 | |
paul@0 | 8 | void init_memory(void) |
paul@0 | 9 | { |
paul@0 | 10 | /* |
paul@0 | 11 | Configure RAM. |
paul@0 | 12 | See: http://microchipdeveloper.com/32bit:mx-arch-exceptions-processor-initialization |
paul@0 | 13 | */ |
paul@0 | 14 | |
paul@0 | 15 | uint32_t config = REG(BMXCON); |
paul@0 | 16 | |
paul@0 | 17 | /* Set zero wait states for address setup. */ |
paul@0 | 18 | |
paul@0 | 19 | config &= ~(1 << 6); /* BMXCON<6> = BMXWSDRM = 0 */ |
paul@0 | 20 | |
paul@0 | 21 | /* Set bus arbitration mode. */ |
paul@0 | 22 | |
paul@0 | 23 | config &= ~0b111; |
paul@0 | 24 | config |= 0b010; /* BMXCON<2:0> = BMXARB<2:0> = 2 */ |
paul@0 | 25 | |
paul@0 | 26 | REG(BMXCON) = config; |
paul@0 | 27 | } |
paul@0 | 28 | |
paul@0 | 29 | void init_pins(void) |
paul@0 | 30 | { |
paul@0 | 31 | /* DEVCFG0<2> also needs setting to 0 before the program is run. */ |
paul@0 | 32 | |
paul@0 | 33 | CLR_REG(CFGCON, 1 << 3); /* CFGCON<3> = JTAGEN = 0 */ |
paul@0 | 34 | } |
paul@0 | 35 | |
paul@0 | 36 | void init_outputs(void) |
paul@0 | 37 | { |
paul@0 | 38 | /* Remove analogue features from pins. */ |
paul@0 | 39 | |
paul@0 | 40 | REG(ANSELA) = 0; |
paul@0 | 41 | REG(ANSELB) = 0; |
paul@0 | 42 | |
paul@0 | 43 | REG(TRISA) = 0; |
paul@0 | 44 | REG(TRISB) = 0; |
paul@0 | 45 | |
paul@0 | 46 | REG(PORTA) = 0; |
paul@0 | 47 | REG(PORTB) = 0; |
paul@0 | 48 | } |
paul@0 | 49 | |
paul@0 | 50 | |
paul@0 | 51 | |
paul@0 | 52 | /* Peripheral pin configuration. */ |
paul@0 | 53 | |
paul@0 | 54 | void config_uart(void) |
paul@0 | 55 | { |
paul@0 | 56 | /* Map U1RX to RPB13. */ |
paul@0 | 57 | |
paul@0 | 58 | REG(U1RXR) = 0b0011; /* U1RXR<3:0> = 0011 (RPB13) */ |
paul@0 | 59 | |
paul@0 | 60 | /* Map U1TX to RPB15. */ |
paul@0 | 61 | |
paul@0 | 62 | REG(RPB15R) = 0b0001; /* RPB15R<3:0> = 0001 (U1TX) */ |
paul@0 | 63 | |
paul@0 | 64 | /* Set RPB13 to input. */ |
paul@0 | 65 | |
paul@0 | 66 | SET_REG(TRISB, 1 << 13); |
paul@0 | 67 | } |
paul@0 | 68 | |
paul@0 | 69 | void lock_config(void) |
paul@0 | 70 | { |
paul@0 | 71 | SET_REG(CFGCON, 1 << 13); /* IOLOCK = 1 */ |
paul@0 | 72 | |
paul@0 | 73 | /* Lock the configuration again. */ |
paul@0 | 74 | |
paul@0 | 75 | REG(SYSKEY) = 0x33333333; |
paul@0 | 76 | } |
paul@0 | 77 | |
paul@0 | 78 | void unlock_config(void) |
paul@0 | 79 | { |
paul@0 | 80 | /* Unlock the configuration register bits. */ |
paul@0 | 81 | |
paul@0 | 82 | REG(SYSKEY) = 0; |
paul@0 | 83 | REG(SYSKEY) = 0xAA996655; |
paul@0 | 84 | REG(SYSKEY) = 0x556699AA; |
paul@0 | 85 | |
paul@0 | 86 | CLR_REG(CFGCON, 1 << 13); /* IOLOCK = 0 */ |
paul@0 | 87 | } |
paul@0 | 88 | |
paul@0 | 89 | |
paul@0 | 90 | |
paul@0 | 91 | /* Convenience operations. */ |
paul@0 | 92 | |
paul@0 | 93 | void interrupts_on(void) |
paul@0 | 94 | { |
paul@0 | 95 | init_interrupts(); |
paul@0 | 96 | enable_interrupts(); |
paul@0 | 97 | handle_error_level(); |
paul@0 | 98 | } |
paul@0 | 99 | |
paul@0 | 100 | |
paul@0 | 101 | |
paul@0 | 102 | /* Peripheral configuration. */ |
paul@0 | 103 | |
paul@0 | 104 | void init_uart(uint8_t pri, uint8_t sub) |
paul@0 | 105 | { |
paul@0 | 106 | CLR_REG(U1MODE, 1 << 15); /* U1MODE<15> = ON = 0 */ |
paul@0 | 107 | REG(U1BRG) = 12; /* U1BRG<15:0> = BRG = (FPB / (16 * baudrate)) - 1 = (24000000 / (16 * 115200)) - 1 = 12 */ |
paul@0 | 108 | |
paul@0 | 109 | /* Disable interrupt and clear flag. */ |
paul@0 | 110 | |
paul@0 | 111 | CLR_REG(IEC1, 1 << 8); /* IEC1<8> = U1RIE = 0 */ |
paul@0 | 112 | CLR_REG(IFS1, 1 << 8); /* IFS1<8> = U1RIF = 0 */ |
paul@0 | 113 | |
paul@0 | 114 | /* Set priorities: U1IP = pri; U1IS = sub */ |
paul@0 | 115 | |
paul@0 | 116 | REG(IPC8) = (REG(IPC8) & ~0b11111) | ((pri & 0b111) << 2) | (sub & 0b11); |
paul@0 | 117 | |
paul@0 | 118 | /* Enable interrupt. */ |
paul@0 | 119 | |
paul@0 | 120 | SET_REG(IEC1, 1 << 8); /* IEC1<8> = U1RIE = 1 */ |
paul@0 | 121 | |
paul@0 | 122 | /* Start UART. */ |
paul@0 | 123 | |
paul@0 | 124 | SET_REG(U1STA, (1 << 12) | (1 << 10)); /* U1STA<12> = URXEN = 1; U1STA<10> = UTXEN = 1 */ |
paul@0 | 125 | SET_REG(U1MODE, 1 << 15); /* U1MODE<15> = ON = 1 */ |
paul@0 | 126 | } |