1.1 --- a/cpu.S Mon Oct 22 19:12:33 2018 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,174 +0,0 @@
1.4 -/*
1.5 - * PIC32 microcontroller interrupt handling code.
1.6 - *
1.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
1.8 - *
1.9 - * This program is free software: you can redistribute it and/or modify
1.10 - * it under the terms of the GNU General Public License as published by
1.11 - * the Free Software Foundation, either version 3 of the License, or
1.12 - * (at your option) any later version.
1.13 - *
1.14 - * This program is distributed in the hope that it will be useful,
1.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 - * GNU General Public License for more details.
1.18 - *
1.19 - * You should have received a copy of the GNU General Public License
1.20 - * along with this program. If not, see <http://www.gnu.org/licenses/>.
1.21 - */
1.22 -
1.23 -#include "mips.h"
1.24 -#include "pic32.h"
1.25 -#include "cpu.h"
1.26 -
1.27 -.globl enable_interrupts
1.28 -.globl handle_error_level
1.29 -.globl init_interrupts
1.30 -.extern exception_handler
1.31 -.extern interrupt_handler
1.32 -
1.33 -/* Put general routines in the text section. */
1.34 -
1.35 -.text
1.36 -
1.37 -/*
1.38 -Clear the error and exception status flags, making interrupts and exceptions
1.39 -possible.
1.40 -*/
1.41 -
1.42 -handle_error_level:
1.43 - mfc0 $t3, CP0_STATUS
1.44 -
1.45 - /* Clear error level and exception level. */
1.46 -
1.47 - li $t4, ~(STATUS_ERL | STATUS_EXL)
1.48 - and $t3, $t3, $t4
1.49 - mtc0 $t3, CP0_STATUS
1.50 -
1.51 - jr $ra
1.52 - nop
1.53 -
1.54 -/* Enable interrupts and direct interrupt requests to non-bootloader vectors. */
1.55 -
1.56 -enable_interrupts:
1.57 - mfc0 $t3, CP0_STATUS
1.58 -
1.59 - /* Clear interrupt priority bits. */
1.60 -
1.61 - li $t4, ~STATUS_IRQ
1.62 - and $t3, $t3, $t4
1.63 -
1.64 - /* Set interrupt priority. */
1.65 -
1.66 - ori $t3, $t3, (CPU_INT_PRIORITY << STATUS_IRQ_SHIFT)
1.67 -
1.68 - /* CP0_STATUS &= ~STATUS_BEV (use non-bootloader vectors) */
1.69 -
1.70 - li $t4, ~STATUS_BEV
1.71 - and $t3, $t3, $t4
1.72 -
1.73 - /* Enable interrupts. */
1.74 -
1.75 - ori $t3, $t3, STATUS_IE
1.76 - mtc0 $t3, CP0_STATUS
1.77 -
1.78 - jr $ra
1.79 - nop
1.80 -
1.81 -/* Initialise the interrupt system parameters. */
1.82 -
1.83 -init_interrupts:
1.84 - /* Clear debug mode. */
1.85 -
1.86 - mfc0 $t3, CP0_DEBUG
1.87 - li $t4, ~DEBUG_DM
1.88 - and $t3, $t3, $t4
1.89 - mtc0 $t3, CP0_DEBUG
1.90 -
1.91 - /* Update the exception base. */
1.92 -
1.93 - mfc0 $t3, CP0_STATUS
1.94 - li $t4, STATUS_BEV /* BEV = 1 or EBASE cannot be set */
1.95 - or $t3, $t3, $t4
1.96 - mtc0 $t3, CP0_STATUS
1.97 -
1.98 - la $t3, ebase
1.99 - mtc0 $t3, CP0_EBASE
1.100 -
1.101 - /* Set vector spacing. */
1.102 -
1.103 - li $t3, 0x20 /* Must be non-zero or the CPU gets upset */
1.104 - mtc0 $t3, CP0_INTCTL
1.105 -
1.106 - li $t3, CAUSE_IV /* IV = 1 (use EBASE+0x200 for interrupts) */
1.107 - mtc0 $t3, CP0_CAUSE
1.108 -
1.109 - jr $ra
1.110 - nop
1.111 -
1.112 -
1.113 -
1.114 -/* Exception servicing, positioned at EBASE at the start of program memory. */
1.115 -
1.116 -.section .vectors, "a"
1.117 -
1.118 -/* TLB error servicing. */
1.119 -
1.120 -ebase:
1.121 -tlb_handler:
1.122 - j exception_handler
1.123 - nop
1.124 -
1.125 -
1.126 -
1.127 -/* General exception servicing. */
1.128 -
1.129 -.org 0x180
1.130 -
1.131 -exc_handler:
1.132 - j exception_handler
1.133 - nop
1.134 -
1.135 -
1.136 -
1.137 -/* Interrupt servicing. */
1.138 -
1.139 -.org 0x200
1.140 -.set noat
1.141 -
1.142 -#define IRQ_STACK_LIMIT (KSEG0_BASE + IRQ_STACK_SIZE)
1.143 -#define IRQ_STACK_TOP (IRQ_STACK_LIMIT - 32 * 4)
1.144 -
1.145 -int_handler:
1.146 -
1.147 - /* Store affected registers from IRQ_STACK_LIMIT - 4 downwards. */
1.148 -
1.149 - lui $k0, %hi(IRQ_STACK_LIMIT)
1.150 - ori $k0, $k0, %lo(IRQ_STACK_LIMIT)
1.151 -
1.152 - .irp reg, \
1.153 - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 \
1.154 - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \
1.155 - 28, 29, 30, 31
1.156 - sw $\reg, -(\reg * 4)($k0)
1.157 - .endr
1.158 -
1.159 - /* Switch to the IRQ stack. */
1.160 -
1.161 - lui $sp, %hi(IRQ_STACK_TOP)
1.162 - ori $sp, $sp, %lo(IRQ_STACK_TOP)
1.163 -
1.164 - jal interrupt_handler
1.165 - nop
1.166 -
1.167 - /* Restore affected registers. */
1.168 -
1.169 - .irp reg, \
1.170 - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 \
1.171 - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \
1.172 - 28, 29, 30, 31
1.173 - lw $\reg, -(\reg * 4)($k0)
1.174 - .endr
1.175 -
1.176 - eret
1.177 - nop
2.1 --- a/cpu.h Mon Oct 22 19:12:33 2018 +0200
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,35 +0,0 @@
2.4 -/*
2.5 - * PIC32 microcontroller interrupt handling code.
2.6 - *
2.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
2.8 - *
2.9 - * This program is free software: you can redistribute it and/or modify
2.10 - * it under the terms of the GNU General Public License as published by
2.11 - * the Free Software Foundation, either version 3 of the License, or
2.12 - * (at your option) any later version.
2.13 - *
2.14 - * This program is distributed in the hope that it will be useful,
2.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
2.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.17 - * GNU General Public License for more details.
2.18 - *
2.19 - * You should have received a copy of the GNU General Public License
2.20 - * along with this program. If not, see <http://www.gnu.org/licenses/>.
2.21 - */
2.22 -
2.23 -#ifndef __CPU_H__
2.24 -#define __CPU_H__
2.25 -
2.26 -#define CPU_INT_PRIORITY 3
2.27 -
2.28 -#ifndef __ASSEMBLER__
2.29 -
2.30 -/* Specific operations. */
2.31 -
2.32 -void enable_interrupts(void);
2.33 -void handle_error_level(void);
2.34 -void init_interrupts(void);
2.35 -
2.36 -#endif /* __ASSEMBLER__ */
2.37 -
2.38 -#endif /* __CPU_H__ */
3.1 --- a/debug.c Mon Oct 22 19:12:33 2018 +0200
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,108 +0,0 @@
3.4 -/*
3.5 - * Some simple debugging functions.
3.6 - *
3.7 - * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
3.8 - *
3.9 - * This program is free software: you can redistribute it and/or modify
3.10 - * it under the terms of the GNU General Public License as published by
3.11 - * the Free Software Foundation, either version 3 of the License, or
3.12 - * (at your option) any later version.
3.13 - *
3.14 - * This program is distributed in the hope that it will be useful,
3.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.17 - * GNU General Public License for more details.
3.18 - *
3.19 - * You should have received a copy of the GNU General Public License
3.20 - * along with this program. If not, see <http://www.gnu.org/licenses/>.
3.21 - */
3.22 -
3.23 -#include "pic32_c.h"
3.24 -#include "debug.h"
3.25 -
3.26 -/* Register output functions using UART1. */
3.27 -
3.28 -void rbits(uint32_t reg)
3.29 -{
3.30 - bits(REG(reg), 4);
3.31 -}
3.32 -
3.33 -void rhex(uint32_t reg)
3.34 -{
3.35 - hex(REG(reg), 4);
3.36 -}
3.37 -
3.38 -/* Value output functions using UART1. */
3.39 -
3.40 -void bits(uint32_t val, int bytes)
3.41 -{
3.42 - uint32_t mask;
3.43 -
3.44 - for (mask = (1 << 31); mask; mask >>= 1)
3.45 - if (val & mask)
3.46 - uart_write('1');
3.47 - else
3.48 - uart_write('0');
3.49 -}
3.50 -
3.51 -void hex(uint32_t val, int bytes)
3.52 -{
3.53 - uint32_t mask;
3.54 - uint8_t digit, shift, start = bytes * 8 - 4;
3.55 -
3.56 - for (mask = (0b1111 << start), shift = start; mask; mask >>= 4, shift -= 4)
3.57 - {
3.58 - digit = (val & mask) >> shift;
3.59 - if (digit > 9)
3.60 - uart_write('A' + digit - 10);
3.61 - else
3.62 - uart_write('0' + digit);
3.63 - }
3.64 -}
3.65 -
3.66 -
3.67 -
3.68 -/* General input/output functions. */
3.69 -
3.70 -int uart_can_read(int uart)
3.71 -{
3.72 - return REG(UART_REG(uart, UxSTA)) & 1;
3.73 -}
3.74 -
3.75 -char uart_read_char(int uart)
3.76 -{
3.77 - return (char) REG(UART_REG(uart, UxRXREG));
3.78 -}
3.79 -
3.80 -int uart_can_write(int uart)
3.81 -{
3.82 - return !(REG(UART_REG(uart, UxSTA)) & (1 << 9)); /* UTXBF (buffer full) */
3.83 -}
3.84 -
3.85 -void uart_write_char(int uart, char c)
3.86 -{
3.87 - while (!uart_can_write(uart)); /* busy loop */
3.88 -
3.89 - REG(UART_REG(uart, UxTXREG)) = c;
3.90 -}
3.91 -
3.92 -
3.93 -
3.94 -/* Functions using UART1. */
3.95 -
3.96 -void uart_write(char c)
3.97 -{
3.98 - uart_write_char(1, c);
3.99 -}
3.100 -
3.101 -void uart_write_nl(void)
3.102 -{
3.103 - uart_write('\r');
3.104 - uart_write('\n');
3.105 -}
3.106 -
3.107 -void uart_write_string(const char *s)
3.108 -{
3.109 - while (*s)
3.110 - uart_write(*s++);
3.111 -}
4.1 --- a/debug.h Mon Oct 22 19:12:33 2018 +0200
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,46 +0,0 @@
4.4 -/*
4.5 - * Some simple debugging functions.
4.6 - *
4.7 - * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
4.8 - *
4.9 - * This program is free software: you can redistribute it and/or modify
4.10 - * it under the terms of the GNU General Public License as published by
4.11 - * the Free Software Foundation, either version 3 of the License, or
4.12 - * (at your option) any later version.
4.13 - *
4.14 - * This program is distributed in the hope that it will be useful,
4.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.17 - * GNU General Public License for more details.
4.18 - *
4.19 - * You should have received a copy of the GNU General Public License
4.20 - * along with this program. If not, see <http://www.gnu.org/licenses/>.
4.21 - */
4.22 -
4.23 -#ifndef __DEBUG_H__
4.24 -#define __DEBUG_H__
4.25 -
4.26 -/* Register output functions using UART1. */
4.27 -
4.28 -void rbits(uint32_t reg);
4.29 -void rhex(uint32_t reg);
4.30 -
4.31 -/* Value output functions using UART1. */
4.32 -
4.33 -void bits(uint32_t val, int bytes);
4.34 -void hex(uint32_t val, int bytes);
4.35 -
4.36 -/* General input/output functions. */
4.37 -
4.38 -int uart_can_read(int uart);
4.39 -char uart_read_char(int uart);
4.40 -int uart_can_write(int uart);
4.41 -void uart_write_char(int uart, char c);
4.42 -
4.43 -/* Functions using UART1. */
4.44 -
4.45 -void uart_write(char c);
4.46 -void uart_write_nl(void);
4.47 -void uart_write_string(const char *s);
4.48 -
4.49 -#endif /* __DEBUG_H__ */
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/include/cpu.h Mon Oct 22 21:44:02 2018 +0200
5.3 @@ -0,0 +1,35 @@
5.4 +/*
5.5 + * PIC32 microcontroller interrupt handling code.
5.6 + *
5.7 + * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
5.8 + *
5.9 + * This program is free software: you can redistribute it and/or modify
5.10 + * it under the terms of the GNU General Public License as published by
5.11 + * the Free Software Foundation, either version 3 of the License, or
5.12 + * (at your option) any later version.
5.13 + *
5.14 + * This program is distributed in the hope that it will be useful,
5.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.17 + * GNU General Public License for more details.
5.18 + *
5.19 + * You should have received a copy of the GNU General Public License
5.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
5.21 + */
5.22 +
5.23 +#ifndef __CPU_H__
5.24 +#define __CPU_H__
5.25 +
5.26 +#define CPU_INT_PRIORITY 3
5.27 +
5.28 +#ifndef __ASSEMBLER__
5.29 +
5.30 +/* Specific operations. */
5.31 +
5.32 +void enable_interrupts(void);
5.33 +void handle_error_level(void);
5.34 +void init_interrupts(void);
5.35 +
5.36 +#endif /* __ASSEMBLER__ */
5.37 +
5.38 +#endif /* __CPU_H__ */
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/include/debug.h Mon Oct 22 21:44:02 2018 +0200
6.3 @@ -0,0 +1,46 @@
6.4 +/*
6.5 + * Some simple debugging functions.
6.6 + *
6.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
6.8 + *
6.9 + * This program is free software: you can redistribute it and/or modify
6.10 + * it under the terms of the GNU General Public License as published by
6.11 + * the Free Software Foundation, either version 3 of the License, or
6.12 + * (at your option) any later version.
6.13 + *
6.14 + * This program is distributed in the hope that it will be useful,
6.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.17 + * GNU General Public License for more details.
6.18 + *
6.19 + * You should have received a copy of the GNU General Public License
6.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
6.21 + */
6.22 +
6.23 +#ifndef __DEBUG_H__
6.24 +#define __DEBUG_H__
6.25 +
6.26 +/* Register output functions using UART1. */
6.27 +
6.28 +void rbits(uint32_t reg);
6.29 +void rhex(uint32_t reg);
6.30 +
6.31 +/* Value output functions using UART1. */
6.32 +
6.33 +void bits(uint32_t val, int bytes);
6.34 +void hex(uint32_t val, int bytes);
6.35 +
6.36 +/* General input/output functions. */
6.37 +
6.38 +int uart_can_read(int uart);
6.39 +char uart_read_char(int uart);
6.40 +int uart_can_write(int uart);
6.41 +void uart_write_char(int uart, char c);
6.42 +
6.43 +/* Functions using UART1. */
6.44 +
6.45 +void uart_write(char c);
6.46 +void uart_write_nl(void);
6.47 +void uart_write_string(const char *s);
6.48 +
6.49 +#endif /* __DEBUG_H__ */
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/include/init.h Mon Oct 22 21:44:02 2018 +0200
7.3 @@ -0,0 +1,164 @@
7.4 +/*
7.5 + * PIC32 peripheral configuration and initialisation.
7.6 + *
7.7 + * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
7.8 + *
7.9 + * This program is free software: you can redistribute it and/or modify
7.10 + * it under the terms of the GNU General Public License as published by
7.11 + * the Free Software Foundation, either version 3 of the License, or
7.12 + * (at your option) any later version.
7.13 + *
7.14 + * This program is distributed in the hope that it will be useful,
7.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.17 + * GNU General Public License for more details.
7.18 + *
7.19 + * You should have received a copy of the GNU General Public License
7.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
7.21 + */
7.22 +
7.23 +#ifndef __INIT_H__
7.24 +#define __INIT_H__
7.25 +
7.26 +#include "pic32_c.h"
7.27 +
7.28 +
7.29 +
7.30 +/* Basic initialisation. */
7.31 +
7.32 +void init_memory(void);
7.33 +void init_pins(void);
7.34 +void init_outputs(void);
7.35 +
7.36 +
7.37 +
7.38 +/* Peripheral pin configuration. */
7.39 +
7.40 +void lock_config(void);
7.41 +void unlock_config(void);
7.42 +
7.43 +
7.44 +
7.45 +/* Convenience operations. */
7.46 +
7.47 +void interrupts_on(void);
7.48 +
7.49 +
7.50 +
7.51 +/* DMA configuration. */
7.52 +
7.53 +void init_dma(void);
7.54 +
7.55 +void dma_init(int channel, uint8_t pri);
7.56 +
7.57 +void dma_init_interrupt(int channel, uint8_t conditions,
7.58 + uint8_t pri, uint8_t sub);
7.59 +
7.60 +void dma_off(int channel);
7.61 +
7.62 +void dma_on(int channel);
7.63 +
7.64 +void dma_set_auto_enable(int channel, int enable);
7.65 +
7.66 +void dma_set_chaining(int channel, enum dma_chain chain);
7.67 +
7.68 +void dma_set_enable(int channel, int enable);
7.69 +
7.70 +void dma_set_interrupt(int channel, uint8_t int_num, int enable);
7.71 +
7.72 +void dma_set_interrupt_enable(int channel, int enable);
7.73 +
7.74 +void dma_set_receive_events(int channel, int enable);
7.75 +
7.76 +void dma_set_transfer(int channel,
7.77 + uint32_t source_start_address, uint16_t source_size,
7.78 + uint32_t destination_start_address, uint16_t destination_size,
7.79 + uint16_t cell_size);
7.80 +
7.81 +int DMA_INT_FLAGS(int channel, uint8_t flags);
7.82 +
7.83 +uint32_t DMA_IPC_PRI(int channel, uint8_t pri, uint8_t sub);
7.84 +
7.85 +
7.86 +
7.87 +/* External interrupt configuration. */
7.88 +
7.89 +void int_init_interrupt(int int_num, uint8_t pri, uint8_t sub);
7.90 +
7.91 +int INT_INT_FLAGS(int int_num, uint8_t flags);
7.92 +
7.93 +uint32_t INT_IPC_PRI(int int_num, uint8_t pri, uint8_t sub);
7.94 +uint32_t INT_IPC_REG(int int_num);
7.95 +
7.96 +
7.97 +
7.98 +/* Output compare configuration. */
7.99 +
7.100 +void oc_init(int unit, uint8_t mode, int timer);
7.101 +
7.102 +void oc_init_interrupt(int unit, uint8_t pri, uint8_t sub);
7.103 +
7.104 +void oc_on(int unit);
7.105 +
7.106 +void oc_set_pulse(int unit, uint32_t start);
7.107 +
7.108 +void oc_set_pulse_end(int unit, uint32_t end);
7.109 +
7.110 +int OC_INT_FLAGS(int unit, uint8_t flags);
7.111 +
7.112 +uint32_t OC_IPC_PRI(int unit, uint8_t pri, uint8_t sub);
7.113 +uint32_t OC_IPC_REG(int unit);
7.114 +
7.115 +
7.116 +
7.117 +/* Parallel mode configuration. */
7.118 +
7.119 +void init_pm(void);
7.120 +
7.121 +void pm_init(int port, uint8_t mode);
7.122 +
7.123 +void pm_init_interrupt(int port, uint8_t pri, uint8_t sub);
7.124 +
7.125 +void pm_off(int port);
7.126 +
7.127 +void pm_on(int port);
7.128 +
7.129 +void pm_set_output(int port, int write_enable, int read_enable);
7.130 +
7.131 +int PM_INT_FLAGS(int port, uint8_t flags);
7.132 +
7.133 +uint32_t PM_IPC_PRI(int port, uint8_t pri, uint8_t sub);
7.134 +uint32_t PM_IPC_REG(int port);
7.135 +
7.136 +
7.137 +
7.138 +/* Timer configuration. */
7.139 +
7.140 +void timer_init(int timer, uint8_t prescale, uint16_t limit);
7.141 +
7.142 +void timer_init_interrupt(int timer, uint8_t pri, uint8_t sub);
7.143 +
7.144 +void timer_on(int timer);
7.145 +
7.146 +int TIMER_INT_FLAGS(int timer, uint8_t flags);
7.147 +
7.148 +uint32_t TIMER_IPC_PRI(int timer, uint8_t pri, uint8_t sub);
7.149 +uint32_t TIMER_IPC_REG(int timer);
7.150 +
7.151 +
7.152 +
7.153 +/* UART configuration. */
7.154 +
7.155 +void uart_init(int uart, uint32_t baudrate);
7.156 +
7.157 +void uart_init_interrupt(int uart, uint8_t conditions,
7.158 + uint8_t pri, uint8_t sub);
7.159 +
7.160 +void uart_on(int uart);
7.161 +
7.162 +int UART_INT_FLAGS(int uart, uint8_t flags);
7.163 +
7.164 +uint32_t UART_IPC_PRI(int uart, uint8_t pri, uint8_t sub);
7.165 +uint32_t UART_IPC_REG(int uart);
7.166 +
7.167 +#endif /* __INIT_H__ */
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/include/mips.h Mon Oct 22 21:44:02 2018 +0200
8.3 @@ -0,0 +1,63 @@
8.4 +#ifndef __MIPS_H__
8.5 +#define __MIPS_H__
8.6 +
8.7 +#define KSEG0_BASE 0x80000000
8.8 +#define KSEG1_BASE 0xA0000000
8.9 +
8.10 +#define CP0_INDEX $0
8.11 +#define CP0_ENTRYLO0 $2
8.12 +#define CP0_ENTRYLO1 $3
8.13 +#define CP0_CONTEXT $4
8.14 +#define CP0_PAGEMASK $5
8.15 +#define CP0_WIRED $6
8.16 +#define CP0_BADVADDR $8
8.17 +#define CP0_COUNT $9
8.18 +#define CP0_ENTRYHI $10
8.19 +#define CP0_COMPARE $11
8.20 +#define CP0_STATUS $12
8.21 +#define CP0_INTCTL $12, 1
8.22 +#define CP0_CAUSE $13
8.23 +#define CP0_EPC $14
8.24 +#define CP0_EBASE $15, 1
8.25 +#define CP0_CONFIG $16
8.26 +#define CP0_WATCHLO $18
8.27 +#define CP0_DEBUG $23
8.28 +#define CP0_TAGLO $28
8.29 +#define CP0_TAGHI $29
8.30 +#define CP0_ERROREPC $30, 0
8.31 +
8.32 +#define STATUS_CP0 0x10000000
8.33 +#define STATUS_BEV 0x00400000
8.34 +
8.35 +#define STATUS_IRQ 0x0000fc00
8.36 +#define STATUS_IRQ_SHIFT 10
8.37 +
8.38 +#define STATUS_UM 0x00000010
8.39 +#define STATUS_ERL 0x00000004
8.40 +#define STATUS_EXL 0x00000002
8.41 +#define STATUS_IE 0x00000001
8.42 +
8.43 +#define CAUSE_IV 0x00800000
8.44 +
8.45 +#define EBASE_MASK 0x3ffff000
8.46 +
8.47 +#define INTCTL_MASK 0x000003e0
8.48 +
8.49 +#define DEBUG_DM 0x40000000
8.50 +
8.51 +#define TLB_CACHED 0x00000018
8.52 +#define TLB_UNCACHED 0x00000010
8.53 +#define TLB_DIRTY 0x00000004
8.54 +#define TLB_VALID 0x00000002
8.55 +#define TLB_GLOBAL 0x00000001
8.56 +
8.57 +#define TLB_READ (TLB_CACHED | TLB_VALID)
8.58 +#define TLB_WRITE (TLB_CACHED | TLB_DIRTY | TLB_VALID)
8.59 +#define TLB_ALL_READ (TLB_CACHED | TLB_VALID | TLB_GLOBAL)
8.60 +#define TLB_ALL_WRITE (TLB_CACHED | TLB_DIRTY | TLB_VALID | TLB_GLOBAL)
8.61 +
8.62 +#define CONFIG_K0 0x00000007
8.63 +#define CONFIG_K0_UNCACHED 2
8.64 +#define CONFIG_K0_CACHABLE_NONCOHERENT 3
8.65 +
8.66 +#endif /* __MIPS_H__ */
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/include/pic32.h Mon Oct 22 21:44:02 2018 +0200
9.3 @@ -0,0 +1,382 @@
9.4 +/*
9.5 + * PIC32 peripheral descriptions.
9.6 + *
9.7 + * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
9.8 + *
9.9 + * This program is free software: you can redistribute it and/or modify
9.10 + * it under the terms of the GNU General Public License as published by
9.11 + * the Free Software Foundation, either version 3 of the License, or
9.12 + * (at your option) any later version.
9.13 + *
9.14 + * This program is distributed in the hope that it will be useful,
9.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9.17 + * GNU General Public License for more details.
9.18 + *
9.19 + * You should have received a copy of the GNU General Public License
9.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
9.21 + */
9.22 +
9.23 +#ifndef __PIC32_H__
9.24 +#define __PIC32_H__
9.25 +
9.26 +/* Peripheral addresses.
9.27 + * See...
9.28 + * TABLE 4-1: SFR MEMORYMAP
9.29 + * TABLE 11-3: PORTA REGISTER MAP
9.30 + * PIC32MX1XX/2XX 28/36/44-pin Family Data Sheet
9.31 + */
9.32 +
9.33 +#define OSCCON 0xBF80F000
9.34 +#define REFOCON 0xBF80F020
9.35 +#define REFOTRIM 0xBF80F030
9.36 +#define CFGCON 0xBF80F200
9.37 +#define SYSKEY 0xBF80F230
9.38 +
9.39 +#define INT2R 0xBF80FA08
9.40 +#define U1RXR 0xBF80FA50
9.41 +
9.42 +#define RPA0R 0xBF80FB00
9.43 +#define RPA1R 0xBF80FB04
9.44 +#define RPA2R 0xBF80FB08
9.45 +#define RPA3R 0xBF80FB0C
9.46 +#define RPA4R 0xBF80FB10
9.47 +#define RPB0R 0xBF80FB2C
9.48 +#define RPB1R 0xBF80FB30
9.49 +#define RPB2R 0xBF80FB34
9.50 +#define RPB3R 0xBF80FB38
9.51 +#define RPB4R 0xBF80FB3C
9.52 +#define RPB5R 0xBF80FB40
9.53 +#define RPB10R 0xBF80FB54
9.54 +#define RPB15R 0xBF80FB68
9.55 +
9.56 +#define INTCON 0xBF881000
9.57 +#define IFS0 0xBF881030
9.58 +#define IFS1 0xBF881040
9.59 +#define IEC0 0xBF881060
9.60 +#define IEC1 0xBF881070
9.61 +#define IPC0 0xBF881090
9.62 +#define IPC1 0xBF8810A0
9.63 +#define IPC2 0xBF8810B0
9.64 +#define IPC3 0xBF8810C0
9.65 +#define IPC4 0xBF8810D0
9.66 +#define IPC5 0xBF8810E0
9.67 +#define IPC6 0xBF8810F0
9.68 +#define IPC7 0xBF881100
9.69 +#define IPC8 0xBF881110
9.70 +#define IPC9 0xBF881120
9.71 +#define IPC10 0xBF881130
9.72 +
9.73 +#define BMXCON 0xBF882000
9.74 +#define BMXDKPBA 0xBF882010
9.75 +#define BMXDUDBA 0xBF882020
9.76 +#define BMXDUPBA 0xBF882030
9.77 +#define BMXDRMSZ 0xBF882040
9.78 +
9.79 +#define ANSELA 0xBF886000
9.80 +#define TRISA 0xBF886010
9.81 +#define PORTA 0xBF886020
9.82 +#define LATA 0xBF886030
9.83 +#define ODCA 0xBF886040
9.84 +#define ANSELB 0xBF886100
9.85 +#define TRISB 0xBF886110
9.86 +#define PORTB 0xBF886120
9.87 +#define LATB 0xBF886130
9.88 +#define ODCB 0xBF886140
9.89 +
9.90 +/* DEVCFG conveniences. */
9.91 +
9.92 +#define DEVCFG1_UNUSED 0xff7fcbd8 /* exclude FWDTWINSZ, WINDIS, WDTPS, FCKSM, POSCMOD, IESO */
9.93 +
9.94 +#define DEVCFG1_FWDTEN_OFF (0 << 23)
9.95 +#define DEVCFG1_FWDTEN_ON (1 << 23)
9.96 +
9.97 +#define DEVCFG1_FPBDIV_1 (0b00 << 12)
9.98 +#define DEVCFG1_FPBDIV_2 (0b01 << 12)
9.99 +#define DEVCFG1_FPBDIV_4 (0b10 << 12)
9.100 +#define DEVCFG1_FPBDIV_8 (0b11 << 12)
9.101 +
9.102 +#define DEVCFG1_OSCIOFNC_ON (0 << 10)
9.103 +#define DEVCFG1_OSCIOFNC_OFF (1 << 10)
9.104 +
9.105 +#define DEVCFG1_FSOSCEN_OFF (0 << 5)
9.106 +#define DEVCFG1_FSOSCEN_ON (1 << 5)
9.107 +
9.108 +#define DEVCFG1_FNOSC_FRC (0b000)
9.109 +#define DEVCFG1_FNOSC_FRCDIV_PLL (0b001)
9.110 +#define DEVCFG1_FNOSC_FRCDIV (0b111)
9.111 +
9.112 +#define DEVCFG2_UNUSED 0xfff8ff88 /* exclude UPLLEN, UPLLIDIV */
9.113 +
9.114 +#define DEVCFG2_FPLLODIV_1 (0b000 << 16)
9.115 +#define DEVCFG2_FPLLODIV_2 (0b001 << 16)
9.116 +#define DEVCFG2_FPLLODIV_4 (0b010 << 16)
9.117 +#define DEVCFG2_FPLLODIV_8 (0b011 << 16)
9.118 +#define DEVCFG2_FPLLODIV_16 (0b100 << 16)
9.119 +#define DEVCFG2_FPLLODIV_32 (0b101 << 16)
9.120 +#define DEVCFG2_FPLLODIV_64 (0b110 << 16)
9.121 +#define DEVCFG2_FPLLODIV_128 (0b111 << 16)
9.122 +
9.123 +#define DEVCFG2_FPLLMUL_15 (0b000 << 4)
9.124 +#define DEVCFG2_FPLLMUL_16 (0b001 << 4)
9.125 +#define DEVCFG2_FPLLMUL_17 (0b010 << 4)
9.126 +#define DEVCFG2_FPLLMUL_18 (0b011 << 4)
9.127 +#define DEVCFG2_FPLLMUL_19 (0b100 << 4)
9.128 +#define DEVCFG2_FPLLMUL_20 (0b101 << 4)
9.129 +#define DEVCFG2_FPLLMUL_21 (0b110 << 4)
9.130 +#define DEVCFG2_FPLLMUL_24 (0b111 << 4)
9.131 +
9.132 +#define DEVCFG2_FPLLIDIV_1 (0b000)
9.133 +#define DEVCFG2_FPLLIDIV_2 (0b001)
9.134 +#define DEVCFG2_FPLLIDIV_3 (0b010)
9.135 +#define DEVCFG2_FPLLIDIV_4 (0b011)
9.136 +#define DEVCFG2_FPLLIDIV_5 (0b100)
9.137 +#define DEVCFG2_FPLLIDIV_6 (0b101)
9.138 +#define DEVCFG2_FPLLIDIV_10 (0b110)
9.139 +#define DEVCFG2_FPLLIDIV_12 (0b111)
9.140 +
9.141 +/* DMA conveniences. */
9.142 +
9.143 +#define DMACON 0xBF883000
9.144 +#define DCH0CON 0xBF883060
9.145 +#define DCH1CON 0xBF883120
9.146 +#define DCH2CON 0xBF8831E0
9.147 +#define DCH3CON 0xBF8832A0
9.148 +
9.149 +#define DCHMIN 0
9.150 +#define DCHMAX 3
9.151 +#define DCHBASE DCH0CON
9.152 +#define DCHSTEP (DCH1CON - DCH0CON)
9.153 +
9.154 +#define DCHxCON 0x00
9.155 +#define DCHxECON 0x10
9.156 +#define DCHxINT 0x20
9.157 +#define DCHxSSA 0x30
9.158 +#define DCHxDSA 0x40
9.159 +#define DCHxSSIZ 0x50
9.160 +#define DCHxDSIZ 0x60
9.161 +#define DCHxSPTR 0x70
9.162 +#define DCHxDPTR 0x80
9.163 +#define DCHxCSIZ 0x90
9.164 +#define DCHxCPTR 0xA0
9.165 +#define DCHxDAT 0xB0
9.166 +
9.167 +#define DMAIEC IEC1
9.168 +
9.169 +#define DCHxIE 1
9.170 +
9.171 +#define DMAIFS IFS1
9.172 +
9.173 +#define DCHxIF 1
9.174 +
9.175 +#define DMAINTBASE 28
9.176 +
9.177 +#define DMAIPC IPC10
9.178 +#define DCHIPCBASE 0
9.179 +#define DCHIPCSTEP 8
9.180 +
9.181 +/* External interrupt conveniences. */
9.182 +
9.183 +#define INTMIN 0
9.184 +#define INTMAX 4
9.185 +
9.186 +#define INTIEC IEC0
9.187 +
9.188 +#define INTxIE 1
9.189 +
9.190 +#define INTIFS IFS0
9.191 +
9.192 +#define INTxIF 1
9.193 +
9.194 +#define INTINTBASE 3
9.195 +#define INTINTSTEP 5
9.196 +
9.197 +#define INT0IPC IPC0
9.198 +#define INT1IPC IPC1
9.199 +#define INT2IPC IPC2
9.200 +#define INT3IPC IPC3
9.201 +#define INT4IPC IPC4
9.202 +#define INTIPCBASE 24
9.203 +
9.204 +/* Output compare conveniences. */
9.205 +
9.206 +#define OC1CON 0xBF803000
9.207 +#define OC2CON 0xBF803200
9.208 +#define OC3CON 0xBF803400
9.209 +#define OC4CON 0xBF803600
9.210 +#define OC5CON 0xBF803800
9.211 +
9.212 +#define OCMIN 1
9.213 +#define OCMAX 5
9.214 +#define OCBASE OC1CON
9.215 +#define OCSTEP (OC2CON - OC1CON)
9.216 +
9.217 +#define OCxCON 0x00
9.218 +#define OCxR 0x10
9.219 +#define OCxRS 0x20
9.220 +
9.221 +#define OCIEC IEC0
9.222 +
9.223 +#define OCxIE 1
9.224 +
9.225 +#define OCIFS IFS0
9.226 +
9.227 +#define OCxIF 1
9.228 +
9.229 +#define OCINTBASE 7
9.230 +#define OCINTSTEP 5
9.231 +
9.232 +#define OC1IPC IPC1
9.233 +#define OC2IPC IPC2
9.234 +#define OC3IPC IPC3
9.235 +#define OC4IPC IPC4
9.236 +#define OC5IPC IPC5
9.237 +#define OCIPCBASE 16
9.238 +
9.239 +/* Parallel mode conveniences. */
9.240 +
9.241 +#define PMCON 0xBF807000
9.242 +
9.243 +#define PMxCON 0x00
9.244 +#define PMxMODE 0x10
9.245 +#define PMxADDR 0x20
9.246 +#define PMxDOUT 0x30
9.247 +#define PMxDIN 0x40
9.248 +#define PMxAEN 0x50
9.249 +#define PMxSTAT 0x60
9.250 +
9.251 +#define PMMIN 0
9.252 +#define PMMAX 0
9.253 +#define PMBASE PMCON
9.254 +#define PMSTEP 0
9.255 +
9.256 +#define PMIEC IEC1
9.257 +
9.258 +#define PMxIE 1
9.259 +#define PMxEIE 2
9.260 +
9.261 +#define PMIFS IFS1
9.262 +
9.263 +#define PMxIF 1
9.264 +#define PMxEIF 2
9.265 +
9.266 +#define PMINTBASE 16
9.267 +#define PMINTSTEP 0
9.268 +
9.269 +#define PMIPC IPC8
9.270 +#define PMIPCBASE 24
9.271 +
9.272 +/* Timer conveniences. */
9.273 +
9.274 +#define T1CON 0xBF800600
9.275 +#define T2CON 0xBF800800
9.276 +#define T3CON 0xBF800A00
9.277 +#define T4CON 0xBF800C00
9.278 +#define T5CON 0xBF800E00
9.279 +
9.280 +#define TIMERMIN 1
9.281 +#define TIMERMAX 5
9.282 +#define TIMERBASE T1CON
9.283 +#define TIMERSTEP (T2CON - T1CON)
9.284 +
9.285 +#define TxCON 0x00
9.286 +#define TMRx 0x10
9.287 +#define PRx 0x20
9.288 +
9.289 +#define TIMERIEC IEC0
9.290 +
9.291 +#define TxIE 1
9.292 +
9.293 +#define TIMERIFS IEC0
9.294 +
9.295 +#define TxIF 1
9.296 +
9.297 +#define TIMERINTBASE 4
9.298 +#define TIMERINTSTEP 5
9.299 +
9.300 +#define TIMER1IPC IPC1
9.301 +#define TIMER2IPC IPC2
9.302 +#define TIMER3IPC IPC3
9.303 +#define TIMER4IPC IPC4
9.304 +#define TIMER5IPC IPC5
9.305 +#define TIMERIPCBASE 0
9.306 +
9.307 +/* UART conveniences. */
9.308 +
9.309 +#define U1MODE 0xBF806000
9.310 +#define U2MODE 0xBF806200
9.311 +
9.312 +#define UARTMIN 1
9.313 +#define UARTMAX 2
9.314 +#define UARTBASE U1MODE
9.315 +#define UARTSTEP (U2MODE - U1MODE)
9.316 +
9.317 +#define UxMODE 0x00
9.318 +#define UxSTA 0x10
9.319 +#define UxTXREG 0x20
9.320 +#define UxRXREG 0x30
9.321 +#define UxBRG 0x40
9.322 +
9.323 +#define UARTIEC IEC1
9.324 +
9.325 +#define UxEIE 1
9.326 +#define UxRIE 2
9.327 +#define UxTIE 4
9.328 +
9.329 +#define UARTIFS IFS1
9.330 +
9.331 +#define UxEIF 1
9.332 +#define UxRIF 2
9.333 +#define UxTIF 4
9.334 +
9.335 +#define UARTINTBASE 7
9.336 +#define UARTINTSTEP 14
9.337 +
9.338 +#define UART1IPC IPC8
9.339 +#define UART1IPCBASE 0
9.340 +#define UART2IPC IPC9
9.341 +#define UART2IPCBASE 8
9.342 +
9.343 +/* Interrupt numbers.
9.344 + * See...
9.345 + * TABLE 7-1: INTERRUPT IRQ, VECTOR AND BIT LOCATION
9.346 + * PIC32MX1XX/2XX 28/36/44-pin Family Data Sheet
9.347 + */
9.348 +
9.349 +#define DMA0 60
9.350 +#define DMA1 61
9.351 +#define DMA2 62
9.352 +#define DMA3 63
9.353 +#define INT0 3
9.354 +#define INT1 8
9.355 +#define INT2 13
9.356 +#define INT3 18
9.357 +#define INT4 23
9.358 +#define OC1 7
9.359 +#define OC2 12
9.360 +#define OC3 17
9.361 +#define OC4 22
9.362 +#define OC5 27
9.363 +#define PMP 48
9.364 +#define PMPE 49
9.365 +#define T1 4
9.366 +#define T2 9
9.367 +#define T3 14
9.368 +#define T4 19
9.369 +#define T5 24
9.370 +#define U1RX 40
9.371 +#define U1TX 41
9.372 +#define U2RX 54
9.373 +#define U2TX 55
9.374 +
9.375 +/* Address modifiers.
9.376 + * See...
9.377 + * 11.2 CLR, SET and INV Registers
9.378 + * PIC32MX1XX/2XX 28/36/44-pin Family Data Sheet
9.379 + */
9.380 +
9.381 +#define CLR 0x4
9.382 +#define SET 0x8
9.383 +#define INV 0xC
9.384 +
9.385 +#endif /* __PIC32_H__ */
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/include/pic32_c.h Mon Oct 22 21:44:02 2018 +0200
10.3 @@ -0,0 +1,110 @@
10.4 +/*
10.5 + * PIC32 peripheral access utilities.
10.6 + *
10.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
10.8 + *
10.9 + * This program is free software: you can redistribute it and/or modify
10.10 + * it under the terms of the GNU General Public License as published by
10.11 + * the Free Software Foundation, either version 3 of the License, or
10.12 + * (at your option) any later version.
10.13 + *
10.14 + * This program is distributed in the hope that it will be useful,
10.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10.17 + * GNU General Public License for more details.
10.18 + *
10.19 + * You should have received a copy of the GNU General Public License
10.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
10.21 + */
10.22 +
10.23 +#ifndef __ASSEMBLER__
10.24 +
10.25 +#ifndef __PIC32_C_H__
10.26 +#define __PIC32_C_H__
10.27 +
10.28 +#include <stdint.h>
10.29 +#include "mips.h"
10.30 +#include "pic32.h"
10.31 +
10.32 +
10.33 +
10.34 +/* Access. */
10.35 +
10.36 +#define REG(mem) *((volatile uint32_t *) (mem))
10.37 +
10.38 +
10.39 +
10.40 +/* Bit clearing, setting and inverting. */
10.41 +
10.42 +static inline void CLR_REG(uint32_t mem, uint32_t val)
10.43 +{
10.44 + REG(mem + CLR) = val;
10.45 +}
10.46 +
10.47 +static inline void SET_REG(uint32_t mem, uint32_t val)
10.48 +{
10.49 + REG(mem + SET) = val;
10.50 +}
10.51 +
10.52 +static inline void INV_REG(uint32_t mem, uint32_t val)
10.53 +{
10.54 + REG(mem + INV) = val;
10.55 +}
10.56 +
10.57 +
10.58 +
10.59 +/* Address translation. */
10.60 +
10.61 +static inline uint32_t PHYSICAL(uint32_t addr)
10.62 +{
10.63 + return ((uint32_t) addr) - KSEG0_BASE;
10.64 +}
10.65 +
10.66 +static inline uint32_t HW_PHYSICAL(uint32_t addr)
10.67 +{
10.68 + return ((uint32_t) addr) - KSEG1_BASE;
10.69 +}
10.70 +
10.71 +
10.72 +
10.73 +/* Register collection access. */
10.74 +
10.75 +static inline uint32_t DMA_REG(int channel, uint32_t reg)
10.76 +{
10.77 + return DCHBASE + reg + (channel - DCHMIN) * DCHSTEP;
10.78 +}
10.79 +
10.80 +static inline uint32_t OC_REG(int unit, uint32_t reg)
10.81 +{
10.82 + return OCBASE + reg + (unit - OCMIN) * OCSTEP;
10.83 +}
10.84 +
10.85 +static inline uint32_t PM_REG(int port, uint32_t reg)
10.86 +{
10.87 + return PMBASE + reg + (port - PMMIN) * PMSTEP;
10.88 +}
10.89 +
10.90 +static inline uint32_t TIMER_REG(int timer, uint32_t reg)
10.91 +{
10.92 + return TIMERBASE + reg + (timer - TIMERMIN) * TIMERSTEP;
10.93 +}
10.94 +
10.95 +static inline uint32_t UART_REG(int uart, uint32_t reg)
10.96 +{
10.97 + return UARTBASE + reg + (uart - UARTMIN) * UARTSTEP;
10.98 +}
10.99 +
10.100 +
10.101 +
10.102 +/* Convenience types. */
10.103 +
10.104 +enum dma_chain
10.105 +{
10.106 + dma_chain_none,
10.107 + dma_chain_next,
10.108 + dma_chain_previous,
10.109 +};
10.110 +
10.111 +#endif /* __PIC32_C_H__ */
10.112 +
10.113 +#endif /* __ASSEMBLER__ */
11.1 --- a/init.c Mon Oct 22 19:12:33 2018 +0200
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,715 +0,0 @@
11.4 -/*
11.5 - * PIC32 peripheral configuration and initialisation.
11.6 - *
11.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
11.8 - *
11.9 - * This program is free software: you can redistribute it and/or modify
11.10 - * it under the terms of the GNU General Public License as published by
11.11 - * the Free Software Foundation, either version 3 of the License, or
11.12 - * (at your option) any later version.
11.13 - *
11.14 - * This program is distributed in the hope that it will be useful,
11.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
11.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11.17 - * GNU General Public License for more details.
11.18 - *
11.19 - * You should have received a copy of the GNU General Public License
11.20 - * along with this program. If not, see <http://www.gnu.org/licenses/>.
11.21 - */
11.22 -
11.23 -#include "cpu.h"
11.24 -#include "pic32_c.h"
11.25 -#include "init.h"
11.26 -
11.27 -/* Application-specific configuration. */
11.28 -
11.29 -#include "devconfig.h"
11.30 -
11.31 -
11.32 -
11.33 -/* Basic memory and pin initialisation. */
11.34 -
11.35 -void init_memory(void)
11.36 -{
11.37 - /*
11.38 - Configure RAM.
11.39 - See: http://microchipdeveloper.com/32bit:mx-arch-exceptions-processor-initialization
11.40 - */
11.41 -
11.42 - uint32_t config = REG(BMXCON);
11.43 -
11.44 - /* Set zero wait states for address setup. */
11.45 -
11.46 - config &= ~(1 << 6); /* BMXCON<6> = BMXWSDRM = 0 */
11.47 -
11.48 - /* Set bus arbitration mode. */
11.49 -
11.50 - config &= ~0b111;
11.51 - config |= 0b010; /* BMXCON<2:0> = BMXARB<2:0> = 2 */
11.52 -
11.53 - REG(BMXCON) = config;
11.54 -}
11.55 -
11.56 -void init_pins(void)
11.57 -{
11.58 - /* DEVCFG0<2> also needs setting to 0 before the program is run. */
11.59 -
11.60 - CLR_REG(CFGCON, 1 << 3); /* CFGCON<3> = JTAGEN = 0 */
11.61 -}
11.62 -
11.63 -void init_outputs(void)
11.64 -{
11.65 - /* Remove analogue features from pins. */
11.66 -
11.67 - REG(ANSELA) = 0;
11.68 - REG(ANSELB) = 0;
11.69 -
11.70 - /* Set pins as outputs. */
11.71 -
11.72 - REG(TRISA) = 0;
11.73 - REG(TRISB) = 0;
11.74 -
11.75 - /* Clear outputs. */
11.76 -
11.77 - REG(PORTA) = 0;
11.78 - REG(PORTB) = 0;
11.79 -}
11.80 -
11.81 -
11.82 -
11.83 -/* Peripheral pin configuration. */
11.84 -
11.85 -void lock_config(void)
11.86 -{
11.87 - SET_REG(CFGCON, 1 << 13); /* IOLOCK = 1 */
11.88 -
11.89 - /* Lock the configuration again. */
11.90 -
11.91 - REG(SYSKEY) = 0x33333333;
11.92 -}
11.93 -
11.94 -void unlock_config(void)
11.95 -{
11.96 - /* Unlock the configuration register bits. */
11.97 -
11.98 - REG(SYSKEY) = 0;
11.99 - REG(SYSKEY) = 0xAA996655;
11.100 - REG(SYSKEY) = 0x556699AA;
11.101 -
11.102 - CLR_REG(CFGCON, 1 << 13); /* IOLOCK = 0 */
11.103 -}
11.104 -
11.105 -
11.106 -
11.107 -/* Convenience operations. */
11.108 -
11.109 -void interrupts_on(void)
11.110 -{
11.111 - init_interrupts();
11.112 - enable_interrupts();
11.113 - handle_error_level();
11.114 -}
11.115 -
11.116 -
11.117 -
11.118 -/* DMA configuration. */
11.119 -
11.120 -void init_dma(void)
11.121 -{
11.122 - /* Disable DMA interrupts (DMAxIE). */
11.123 -
11.124 - CLR_REG(DMAIEC, 0b1111 << DMAINTBASE);
11.125 -
11.126 - /* Clear DMA interrupt flags (DMAxIF). */
11.127 -
11.128 - CLR_REG(DMAIFS, 0b1111 << DMAINTBASE);
11.129 -
11.130 - /* Enable DMA. */
11.131 -
11.132 - SET_REG(DMACON, 1 << 15);
11.133 -}
11.134 -
11.135 -/* Initialise the given channel. */
11.136 -
11.137 -void dma_init(int channel, uint8_t pri)
11.138 -{
11.139 - if ((channel < DCHMIN) || (channel > DCHMAX))
11.140 - return;
11.141 -
11.142 - /* Initialise a channel. */
11.143 -
11.144 - REG(DMA_REG(channel, DCHxCON)) = pri & 0b11;
11.145 - REG(DMA_REG(channel, DCHxECON)) = 0;
11.146 - REG(DMA_REG(channel, DCHxINT)) = 0;
11.147 -}
11.148 -
11.149 -/* Set the channel repeated enable mode, enabling it again when a block transfer
11.150 - completes. The documentation describes this as auto-enable. */
11.151 -
11.152 -void dma_set_auto_enable(int channel, int enable)
11.153 -{
11.154 - (enable ? SET_REG : CLR_REG)(DMA_REG(channel, DCHxCON), 1 << 4);
11.155 -}
11.156 -
11.157 -/* Set the channel chaining mode. */
11.158 -
11.159 -void dma_set_chaining(int channel, enum dma_chain chain)
11.160 -{
11.161 - (chain != dma_chain_none ?
11.162 - SET_REG : CLR_REG)(DMA_REG(channel, DCHxCON), 1 << 5);
11.163 -
11.164 - (chain == dma_chain_next ?
11.165 - SET_REG : CLR_REG)(DMA_REG(channel, DCHxCON), 1 << 8);
11.166 -}
11.167 -
11.168 -/* Configure a channel's initiation interrupt. */
11.169 -
11.170 -void dma_set_interrupt(int channel, uint8_t int_num, int enable)
11.171 -{
11.172 - if ((channel < DCHMIN) || (channel > DCHMAX))
11.173 - return;
11.174 -
11.175 - /* Allow an interrupt to trigger the transfer. */
11.176 -
11.177 - REG(DMA_REG(channel, DCHxECON)) = (int_num << 8) |
11.178 - ((enable ? 1 : 0) << 4);
11.179 -}
11.180 -
11.181 -/* Configure only the channel's initiation interrupt status. */
11.182 -
11.183 -void dma_set_interrupt_enable(int channel, int enable)
11.184 -{
11.185 - if ((channel < DCHMIN) || (channel > DCHMAX))
11.186 - return;
11.187 -
11.188 - (enable ? SET_REG : CLR_REG)(DMA_REG(channel, DCHxECON), 1 << 4);
11.189 -}
11.190 -
11.191 -/* Permit the channel to register events while disabled or suspended. A
11.192 - suspended channel is one that is enabled but where the DMA peripheral
11.193 - has been suspended. */
11.194 -
11.195 -void dma_set_receive_events(int channel, int enable)
11.196 -{
11.197 - (enable ? SET_REG : CLR_REG)(DMA_REG(channel, DCHxCON), 1 << 6);
11.198 -}
11.199 -
11.200 -/* Set a channel's transfer parameters. */
11.201 -
11.202 -void dma_set_transfer(int channel,
11.203 - uint32_t source_start_address, uint16_t source_size,
11.204 - uint32_t destination_start_address, uint16_t destination_size,
11.205 - uint16_t cell_size)
11.206 -{
11.207 - if ((channel < DCHMIN) || (channel > DCHMAX))
11.208 - return;
11.209 -
11.210 - REG(DMA_REG(channel, DCHxSSIZ)) = source_size;
11.211 - REG(DMA_REG(channel, DCHxSSA)) = source_start_address;
11.212 - REG(DMA_REG(channel, DCHxDSIZ)) = destination_size;
11.213 - REG(DMA_REG(channel, DCHxDSA)) = destination_start_address;
11.214 - REG(DMA_REG(channel, DCHxCSIZ)) = cell_size;
11.215 -}
11.216 -
11.217 -/* Configure interrupts caused by the channel. */
11.218 -
11.219 -void dma_init_interrupt(int channel, uint8_t conditions,
11.220 - uint8_t pri, uint8_t sub)
11.221 -{
11.222 - if ((channel < DCHMIN) || (channel > DCHMAX))
11.223 - return;
11.224 -
11.225 - /* Disable channel interrupt and clear interrupt flag. */
11.226 -
11.227 - CLR_REG(DMAIEC, DMA_INT_FLAGS(channel, 1));
11.228 - CLR_REG(DMAIFS, DMA_INT_FLAGS(channel, 1));
11.229 -
11.230 - /* Produce an interrupt for the provided conditions. */
11.231 -
11.232 - REG(DMA_REG(channel, DCHxINT)) = conditions << 16;
11.233 -
11.234 - /* Set interrupt priorities. */
11.235 -
11.236 - REG(DMAIPC) = (REG(DMAIPC) &
11.237 - ~(DMA_IPC_PRI(channel, 7, 3))) |
11.238 - DMA_IPC_PRI(channel, pri, sub);
11.239 -
11.240 - /* Enable interrupt. */
11.241 -
11.242 - SET_REG(DMAIEC, DMA_INT_FLAGS(channel, 1));
11.243 -}
11.244 -
11.245 -/* Enable or disable the channel. */
11.246 -
11.247 -void dma_set_enable(int channel, int enable)
11.248 -{
11.249 - if ((channel < DCHMIN) || (channel > DCHMAX))
11.250 - return;
11.251 -
11.252 - (enable ? SET_REG : CLR_REG)(DMA_REG(channel, DCHxCON), 1 << 7);
11.253 -}
11.254 -
11.255 -/* Disable a DMA channel. */
11.256 -
11.257 -void dma_off(int channel)
11.258 -{
11.259 - dma_set_enable(channel, 0);
11.260 -}
11.261 -
11.262 -/* Enable a DMA channel. */
11.263 -
11.264 -void dma_on(int channel)
11.265 -{
11.266 - dma_set_enable(channel, 1);
11.267 -}
11.268 -
11.269 -
11.270 -
11.271 -/* External interrupt initialisation. */
11.272 -
11.273 -void int_init_interrupt(int int_num, uint8_t pri, uint8_t sub)
11.274 -{
11.275 - if ((int_num < INTMIN) || (int_num > INTMAX))
11.276 - return;
11.277 -
11.278 - /* Disable interrupt and clear interrupt flag. */
11.279 -
11.280 - CLR_REG(INTIEC, INT_INT_FLAGS(int_num, INTxIE));
11.281 - CLR_REG(INTIFS, INT_INT_FLAGS(int_num, INTxIF));
11.282 -
11.283 - /* Set interrupt priorities. */
11.284 -
11.285 - REG(INT_IPC_REG(int_num)) = (REG(INT_IPC_REG(int_num)) &
11.286 - ~(INT_IPC_PRI(int_num, 7, 3))) |
11.287 - INT_IPC_PRI(int_num, pri, sub);
11.288 -
11.289 - /* Enable interrupt. */
11.290 -
11.291 - SET_REG(INTIEC, INT_INT_FLAGS(int_num, INTxIE));
11.292 -}
11.293 -
11.294 -
11.295 -
11.296 -/* Output compare configuration. */
11.297 -
11.298 -void oc_init(int unit, uint8_t mode, int timer)
11.299 -{
11.300 - if ((unit < OCMIN) || (unit > OCMAX))
11.301 - return;
11.302 -
11.303 - REG(OC_REG(unit, OCxCON)) = (timer == 3 ? (1 << 3) : 0) | (mode & 0b111);
11.304 -}
11.305 -
11.306 -/* Set the start value for the pulse. */
11.307 -
11.308 -void oc_set_pulse(int unit, uint32_t start)
11.309 -{
11.310 - if ((unit < OCMIN) || (unit > OCMAX))
11.311 - return;
11.312 -
11.313 - REG(OC_REG(unit, OCxR)) = start;
11.314 -}
11.315 -
11.316 -/* Set the end value for the pulse. */
11.317 -
11.318 -void oc_set_pulse_end(int unit, uint32_t end)
11.319 -{
11.320 - if ((unit < OCMIN) || (unit > OCMAX))
11.321 - return;
11.322 -
11.323 - REG(OC_REG(unit, OCxRS)) = end;
11.324 -}
11.325 -
11.326 -/* Configure interrupts caused by the unit. */
11.327 -
11.328 -void oc_init_interrupt(int unit, uint8_t pri, uint8_t sub)
11.329 -{
11.330 - if ((unit < OCMIN) || (unit > OCMAX))
11.331 - return;
11.332 -
11.333 - /* Disable interrupt and clear interrupt flag. */
11.334 -
11.335 - CLR_REG(OCIEC, OC_INT_FLAGS(unit, OCxIE));
11.336 - CLR_REG(OCIFS, OC_INT_FLAGS(unit, OCxIF));
11.337 -
11.338 - /* Set interrupt priorities. */
11.339 -
11.340 - REG(OC_IPC_REG(unit)) = (REG(OC_IPC_REG(unit)) &
11.341 - ~(OC_IPC_PRI(unit, 7, 3))) |
11.342 - OC_IPC_PRI(unit, pri, sub);
11.343 -
11.344 - /* Enable interrupt. */
11.345 -
11.346 - SET_REG(OCIEC, OC_INT_FLAGS(unit, OCxIE));
11.347 -}
11.348 -
11.349 -/* Enable a unit. */
11.350 -
11.351 -void oc_on(int unit)
11.352 -{
11.353 - if ((unit < OCMIN) || (unit > OCMAX))
11.354 - return;
11.355 -
11.356 - SET_REG(OC_REG(unit, OCxCON), 1 << 15);
11.357 -}
11.358 -
11.359 -
11.360 -
11.361 -/* Parallel mode configuration. */
11.362 -
11.363 -void init_pm(void)
11.364 -{
11.365 - int i;
11.366 -
11.367 - /* Disable PM interrupts (PMxIE). */
11.368 -
11.369 - CLR_REG(PMIEC, 0b11 << PMINTBASE);
11.370 -
11.371 - /* Clear PM interrupt flags (PMxIF). */
11.372 -
11.373 - CLR_REG(PMIFS, 0b11 << PMINTBASE);
11.374 -
11.375 - /* Disable PM for configuration. */
11.376 -
11.377 - for (i = PMMIN; i <= PMMAX; i++)
11.378 - REG(PM_REG(i, PMxCON)) = 0;
11.379 -}
11.380 -
11.381 -/* Configure the parallel mode. */
11.382 -
11.383 -void pm_init(int port, uint8_t mode)
11.384 -{
11.385 - if ((port < PMMIN) || (port > PMMAX))
11.386 - return;
11.387 -
11.388 - REG(PM_REG(port, PMxMODE)) = (mode & 0b11) << 8;
11.389 - REG(PM_REG(port, PMxAEN)) = 0;
11.390 - REG(PM_REG(port, PMxADDR)) = 0;
11.391 -}
11.392 -
11.393 -/* Configure output signals. */
11.394 -
11.395 -void pm_set_output(int port, int write_enable, int read_enable)
11.396 -{
11.397 - if ((port < PMMIN) || (port > PMMAX))
11.398 - return;
11.399 -
11.400 - REG(PM_REG(port, PMxCON)) = (write_enable ? (1 << 9) : 0) |
11.401 - (read_enable ? (1 << 8) : 0) |
11.402 - (1 << 1); /* WRSP: PMENB active high */
11.403 -}
11.404 -
11.405 -/* Configure interrupts caused by parallel mode. */
11.406 -
11.407 -void pm_init_interrupt(int port, uint8_t pri, uint8_t sub)
11.408 -{
11.409 - if ((port < PMMIN) || (port > PMMAX))
11.410 - return;
11.411 -
11.412 - /* Disable interrupt and clear interrupt flag. */
11.413 -
11.414 - CLR_REG(PMIEC, PM_INT_FLAGS(port, PMxIE));
11.415 - CLR_REG(PMIFS, PM_INT_FLAGS(port, PMxIF));
11.416 -
11.417 - /* Set interrupt priorities. */
11.418 -
11.419 - REG(PM_IPC_REG(port)) = (REG(PM_IPC_REG(port)) &
11.420 - ~(PM_IPC_PRI(port, 7, 3))) |
11.421 - PM_IPC_PRI(port, pri, sub);
11.422 -
11.423 - /* Enable interrupt. */
11.424 -
11.425 - SET_REG(PMIEC, PM_INT_FLAGS(port, PMxIE));
11.426 -}
11.427 -
11.428 -/* Enable parallel mode. */
11.429 -
11.430 -void pm_on(int port)
11.431 -{
11.432 - if ((port < PMMIN) || (port > PMMAX))
11.433 - return;
11.434 -
11.435 - SET_REG(PM_REG(port, PMxCON), 1 << 15);
11.436 -}
11.437 -
11.438 -/* Disable parallel mode. */
11.439 -
11.440 -void pm_off(int port)
11.441 -{
11.442 - if ((port < PMMIN) || (port > PMMAX))
11.443 - return;
11.444 -
11.445 - CLR_REG(PM_REG(port, PMxCON), 1 << 15);
11.446 -}
11.447 -
11.448 -
11.449 -
11.450 -
11.451 -/* Timer configuration. */
11.452 -
11.453 -void timer_init(int timer, uint8_t prescale, uint16_t limit)
11.454 -{
11.455 - /* NOTE: Should convert from the real prescale value. */
11.456 -
11.457 - REG(TIMER_REG(timer, TxCON)) = (prescale & 0b111) << 4;
11.458 - REG(TIMER_REG(timer, TMRx)) = 0;
11.459 - REG(TIMER_REG(timer, PRx)) = limit;
11.460 -}
11.461 -
11.462 -/* Configure interrupts caused by the timer. */
11.463 -
11.464 -void timer_init_interrupt(int timer, uint8_t pri, uint8_t sub)
11.465 -{
11.466 - if ((timer < TIMERMIN) || (timer > TIMERMAX))
11.467 - return;
11.468 -
11.469 - /* Disable interrupt and clear interrupt flag. */
11.470 -
11.471 - CLR_REG(TIMERIEC, TIMER_INT_FLAGS(timer, TxIE));
11.472 - CLR_REG(TIMERIFS, TIMER_INT_FLAGS(timer, TxIF));
11.473 -
11.474 - /* Set interrupt priorities. */
11.475 -
11.476 - REG(TIMER_IPC_REG(timer)) = (REG(TIMER_IPC_REG(timer)) &
11.477 - ~(TIMER_IPC_PRI(timer, 7, 3))) |
11.478 - TIMER_IPC_PRI(timer, pri, sub);
11.479 -
11.480 - /* Enable interrupt. */
11.481 -
11.482 - SET_REG(TIMERIEC, TIMER_INT_FLAGS(timer, TxIE));
11.483 -}
11.484 -
11.485 -/* Enable a timer. */
11.486 -
11.487 -void timer_on(int timer)
11.488 -{
11.489 - if ((timer < TIMERMIN) || (timer > TIMERMAX))
11.490 - return;
11.491 -
11.492 - SET_REG(TIMER_REG(timer, TxCON), 1 << 15);
11.493 -}
11.494 -
11.495 -
11.496 -
11.497 -/* UART configuration. */
11.498 -
11.499 -void uart_init(int uart, uint32_t baudrate)
11.500 -{
11.501 - /* FPB is configured in the devconfig.h file and set in the start.S file. */
11.502 -
11.503 - if ((uart < UARTMIN) || (uart > UARTMAX))
11.504 - return;
11.505 -
11.506 - /* Disable the UART (ON). */
11.507 -
11.508 - CLR_REG(UART_REG(uart, UxMODE), 1 << 15);
11.509 -
11.510 - /* Set the baud rate. For example:
11.511 -
11.512 - UxBRG<15:0> = BRG
11.513 - = (FPB / (16 * baudrate)) - 1
11.514 - = (24000000 / (16 * 115200)) - 1
11.515 - = 12
11.516 - */
11.517 -
11.518 - REG(UART_REG(uart, UxBRG)) = (FPB / (16 * baudrate)) - 1;
11.519 -}
11.520 -
11.521 -/* Configure interrupts caused by the UART. */
11.522 -
11.523 -void uart_init_interrupt(int uart, uint8_t conditions,
11.524 - uint8_t pri, uint8_t sub)
11.525 -{
11.526 - if ((uart < UARTMIN) || (uart > UARTMAX))
11.527 - return;
11.528 -
11.529 - /* Disable interrupts and clear interrupt flags. */
11.530 -
11.531 - CLR_REG(UARTIEC, UART_INT_FLAGS(uart, UxTIE | UxRIE | UxEIE));
11.532 - CLR_REG(UARTIFS, UART_INT_FLAGS(uart, UxTIF | UxRIF | UxEIF));
11.533 -
11.534 - /* Set priorities: UxIP = pri; UxIS = sub */
11.535 -
11.536 - REG(UART_IPC_REG(uart)) = (REG(UART_IPC_REG(uart)) &
11.537 - ~UART_IPC_PRI(uart, 7, 3)) |
11.538 - UART_IPC_PRI(uart, pri, sub);
11.539 -
11.540 - /* Enable interrupts. */
11.541 -
11.542 - SET_REG(UARTIEC, UART_INT_FLAGS(uart, conditions));
11.543 -}
11.544 -
11.545 -/* Enable a UART. */
11.546 -
11.547 -void uart_on(int uart)
11.548 -{
11.549 - if ((uart < UARTMIN) || (uart > UARTMAX))
11.550 - return;
11.551 -
11.552 - /* Enable receive (URXEN) and transmit (UTXEN). */
11.553 -
11.554 - SET_REG(UART_REG(uart, UxSTA), (1 << 12) | (1 << 10));
11.555 -
11.556 - /* Start UART. */
11.557 -
11.558 - SET_REG(UART_REG(uart, UxMODE), 1 << 15);
11.559 -}
11.560 -
11.561 -
11.562 -
11.563 -/* Utility functions. */
11.564 -
11.565 -/* Return encoded interrupt priorities. */
11.566 -
11.567 -static uint8_t PRI(uint8_t pri, uint8_t sub)
11.568 -{
11.569 - return ((pri & 0b111) << 2) | (sub & 0b11);
11.570 -}
11.571 -
11.572 -/* Return the DMA interrupt flags for combining with a register. */
11.573 -
11.574 -int DMA_INT_FLAGS(int channel, uint8_t flags)
11.575 -{
11.576 - return (flags & 0b1) << (DMAINTBASE + (channel - DCHMIN));
11.577 -}
11.578 -
11.579 -/* Return encoded DMA interrupt priorities for combining with a register. */
11.580 -
11.581 -uint32_t DMA_IPC_PRI(int channel, uint8_t pri, uint8_t sub)
11.582 -{
11.583 - return PRI(pri, sub) << (DCHIPCBASE + (channel - DCHMIN) * DCHIPCSTEP);
11.584 -}
11.585 -
11.586 -/* Return encoded external interrupt priorities for combining with a register. */
11.587 -
11.588 -uint32_t INT_IPC_PRI(int int_num, uint8_t pri, uint8_t sub)
11.589 -{
11.590 - (void) int_num;
11.591 - return PRI(pri, sub) << INTIPCBASE;
11.592 -}
11.593 -
11.594 -/* Return the external interrupt priorities register. */
11.595 -
11.596 -uint32_t INT_IPC_REG(int int_num)
11.597 -{
11.598 - switch (int_num)
11.599 - {
11.600 - case 0: return INT0IPC;
11.601 - case 1: return INT1IPC;
11.602 - case 2: return INT2IPC;
11.603 - case 3: return INT3IPC;
11.604 - case 4: return INT4IPC;
11.605 - default: return 0; /* should not occur */
11.606 - }
11.607 -}
11.608 -
11.609 -/* Return the external interrupt flags for combining with a register. */
11.610 -
11.611 -int INT_INT_FLAGS(int int_num, uint8_t flags)
11.612 -{
11.613 - return (flags & 0b1) << (INTINTBASE + (int_num - INTMIN) * INTINTSTEP);
11.614 -}
11.615 -
11.616 -/* Return encoded output compare interrupt priorities for combining with a register. */
11.617 -
11.618 -uint32_t OC_IPC_PRI(int unit, uint8_t pri, uint8_t sub)
11.619 -{
11.620 - (void) unit;
11.621 - return PRI(pri, sub) << OCIPCBASE;
11.622 -}
11.623 -
11.624 -/* Return the output compare interrupt priorities register. */
11.625 -
11.626 -uint32_t OC_IPC_REG(int unit)
11.627 -{
11.628 - switch (unit)
11.629 - {
11.630 - case 1: return OC1IPC;
11.631 - case 2: return OC2IPC;
11.632 - case 3: return OC3IPC;
11.633 - case 4: return OC4IPC;
11.634 - case 5: return OC5IPC;
11.635 - default: return 0; /* should not occur */
11.636 - }
11.637 -}
11.638 -
11.639 -/* Return the output compare interrupt flags for combining with a register. */
11.640 -
11.641 -int OC_INT_FLAGS(int unit, uint8_t flags)
11.642 -{
11.643 - return (flags & 0b1) << (OCINTBASE + (unit - OCMIN) * OCINTSTEP);
11.644 -}
11.645 -
11.646 -/* Return encoded parallel mode interrupt priorities for combining with a register. */
11.647 -
11.648 -uint32_t PM_IPC_PRI(int port, uint8_t pri, uint8_t sub)
11.649 -{
11.650 - (void) port;
11.651 - return PRI(pri, sub) << PMIPCBASE;
11.652 -}
11.653 -
11.654 -/* Return the parallel mode interrupt priorities register. */
11.655 -
11.656 -uint32_t PM_IPC_REG(int port)
11.657 -{
11.658 - (void) port;
11.659 - return PMIPC;
11.660 -}
11.661 -
11.662 -/* Return the parallel mode interrupt flags for combining with a register. */
11.663 -
11.664 -int PM_INT_FLAGS(int port, uint8_t flags)
11.665 -{
11.666 - return (flags & 0b11) << (PMINTBASE + (port - PMMIN) * PMINTSTEP);
11.667 -}
11.668 -
11.669 -/* Return encoded timer interrupt priorities for combining with a register. */
11.670 -
11.671 -uint32_t TIMER_IPC_PRI(int timer, uint8_t pri, uint8_t sub)
11.672 -{
11.673 - (void) timer;
11.674 - return PRI(pri, sub) << TIMERIPCBASE;
11.675 -}
11.676 -
11.677 -/* Return the timer interrupt priorities register. */
11.678 -
11.679 -uint32_t TIMER_IPC_REG(int timer)
11.680 -{
11.681 - switch (timer)
11.682 - {
11.683 - case 1: return TIMER1IPC;
11.684 - case 2: return TIMER2IPC;
11.685 - case 3: return TIMER3IPC;
11.686 - case 4: return TIMER4IPC;
11.687 - case 5: return TIMER5IPC;
11.688 - default: return 0; /* should not occur */
11.689 - }
11.690 -}
11.691 -
11.692 -/* Return the timer interrupt flags for combining with a register. */
11.693 -
11.694 -int TIMER_INT_FLAGS(int timer, uint8_t flags)
11.695 -{
11.696 - return (flags & 0b1) << (TIMERINTBASE + (timer - TIMERMIN) * TIMERINTSTEP);
11.697 -}
11.698 -
11.699 -/* Return encoded UART interrupt priorities for combining with a register. */
11.700 -
11.701 -uint32_t UART_IPC_PRI(int uart, uint8_t pri, uint8_t sub)
11.702 -{
11.703 - return PRI(pri, sub) << (uart == 1 ? UART1IPCBASE : UART2IPCBASE);
11.704 -}
11.705 -
11.706 -/* Return the UART interrupt priorities register. */
11.707 -
11.708 -uint32_t UART_IPC_REG(int uart)
11.709 -{
11.710 - return uart == 1 ? UART1IPC : UART2IPC;
11.711 -}
11.712 -
11.713 -/* Return the UART interrupt flags for combining with a register. */
11.714 -
11.715 -int UART_INT_FLAGS(int uart, uint8_t flags)
11.716 -{
11.717 - return (flags & 0b111) << (UARTINTBASE + (uart - UARTMIN) * UARTINTSTEP);
11.718 -}
12.1 --- a/init.h Mon Oct 22 19:12:33 2018 +0200
12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
12.3 @@ -1,164 +0,0 @@
12.4 -/*
12.5 - * PIC32 peripheral configuration and initialisation.
12.6 - *
12.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
12.8 - *
12.9 - * This program is free software: you can redistribute it and/or modify
12.10 - * it under the terms of the GNU General Public License as published by
12.11 - * the Free Software Foundation, either version 3 of the License, or
12.12 - * (at your option) any later version.
12.13 - *
12.14 - * This program is distributed in the hope that it will be useful,
12.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
12.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12.17 - * GNU General Public License for more details.
12.18 - *
12.19 - * You should have received a copy of the GNU General Public License
12.20 - * along with this program. If not, see <http://www.gnu.org/licenses/>.
12.21 - */
12.22 -
12.23 -#ifndef __INIT_H__
12.24 -#define __INIT_H__
12.25 -
12.26 -#include "pic32_c.h"
12.27 -
12.28 -
12.29 -
12.30 -/* Basic initialisation. */
12.31 -
12.32 -void init_memory(void);
12.33 -void init_pins(void);
12.34 -void init_outputs(void);
12.35 -
12.36 -
12.37 -
12.38 -/* Peripheral pin configuration. */
12.39 -
12.40 -void lock_config(void);
12.41 -void unlock_config(void);
12.42 -
12.43 -
12.44 -
12.45 -/* Convenience operations. */
12.46 -
12.47 -void interrupts_on(void);
12.48 -
12.49 -
12.50 -
12.51 -/* DMA configuration. */
12.52 -
12.53 -void init_dma(void);
12.54 -
12.55 -void dma_init(int channel, uint8_t pri);
12.56 -
12.57 -void dma_init_interrupt(int channel, uint8_t conditions,
12.58 - uint8_t pri, uint8_t sub);
12.59 -
12.60 -void dma_off(int channel);
12.61 -
12.62 -void dma_on(int channel);
12.63 -
12.64 -void dma_set_auto_enable(int channel, int enable);
12.65 -
12.66 -void dma_set_chaining(int channel, enum dma_chain chain);
12.67 -
12.68 -void dma_set_enable(int channel, int enable);
12.69 -
12.70 -void dma_set_interrupt(int channel, uint8_t int_num, int enable);
12.71 -
12.72 -void dma_set_interrupt_enable(int channel, int enable);
12.73 -
12.74 -void dma_set_receive_events(int channel, int enable);
12.75 -
12.76 -void dma_set_transfer(int channel,
12.77 - uint32_t source_start_address, uint16_t source_size,
12.78 - uint32_t destination_start_address, uint16_t destination_size,
12.79 - uint16_t cell_size);
12.80 -
12.81 -int DMA_INT_FLAGS(int channel, uint8_t flags);
12.82 -
12.83 -uint32_t DMA_IPC_PRI(int channel, uint8_t pri, uint8_t sub);
12.84 -
12.85 -
12.86 -
12.87 -/* External interrupt configuration. */
12.88 -
12.89 -void int_init_interrupt(int int_num, uint8_t pri, uint8_t sub);
12.90 -
12.91 -int INT_INT_FLAGS(int int_num, uint8_t flags);
12.92 -
12.93 -uint32_t INT_IPC_PRI(int int_num, uint8_t pri, uint8_t sub);
12.94 -uint32_t INT_IPC_REG(int int_num);
12.95 -
12.96 -
12.97 -
12.98 -/* Output compare configuration. */
12.99 -
12.100 -void oc_init(int unit, uint8_t mode, int timer);
12.101 -
12.102 -void oc_init_interrupt(int unit, uint8_t pri, uint8_t sub);
12.103 -
12.104 -void oc_on(int unit);
12.105 -
12.106 -void oc_set_pulse(int unit, uint32_t start);
12.107 -
12.108 -void oc_set_pulse_end(int unit, uint32_t end);
12.109 -
12.110 -int OC_INT_FLAGS(int unit, uint8_t flags);
12.111 -
12.112 -uint32_t OC_IPC_PRI(int unit, uint8_t pri, uint8_t sub);
12.113 -uint32_t OC_IPC_REG(int unit);
12.114 -
12.115 -
12.116 -
12.117 -/* Parallel mode configuration. */
12.118 -
12.119 -void init_pm(void);
12.120 -
12.121 -void pm_init(int port, uint8_t mode);
12.122 -
12.123 -void pm_init_interrupt(int port, uint8_t pri, uint8_t sub);
12.124 -
12.125 -void pm_off(int port);
12.126 -
12.127 -void pm_on(int port);
12.128 -
12.129 -void pm_set_output(int port, int write_enable, int read_enable);
12.130 -
12.131 -int PM_INT_FLAGS(int port, uint8_t flags);
12.132 -
12.133 -uint32_t PM_IPC_PRI(int port, uint8_t pri, uint8_t sub);
12.134 -uint32_t PM_IPC_REG(int port);
12.135 -
12.136 -
12.137 -
12.138 -/* Timer configuration. */
12.139 -
12.140 -void timer_init(int timer, uint8_t prescale, uint16_t limit);
12.141 -
12.142 -void timer_init_interrupt(int timer, uint8_t pri, uint8_t sub);
12.143 -
12.144 -void timer_on(int timer);
12.145 -
12.146 -int TIMER_INT_FLAGS(int timer, uint8_t flags);
12.147 -
12.148 -uint32_t TIMER_IPC_PRI(int timer, uint8_t pri, uint8_t sub);
12.149 -uint32_t TIMER_IPC_REG(int timer);
12.150 -
12.151 -
12.152 -
12.153 -/* UART configuration. */
12.154 -
12.155 -void uart_init(int uart, uint32_t baudrate);
12.156 -
12.157 -void uart_init_interrupt(int uart, uint8_t conditions,
12.158 - uint8_t pri, uint8_t sub);
12.159 -
12.160 -void uart_on(int uart);
12.161 -
12.162 -int UART_INT_FLAGS(int uart, uint8_t flags);
12.163 -
12.164 -uint32_t UART_IPC_PRI(int uart, uint8_t pri, uint8_t sub);
12.165 -uint32_t UART_IPC_REG(int uart);
12.166 -
12.167 -#endif /* __INIT_H__ */
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/lib/cpu.S Mon Oct 22 21:44:02 2018 +0200
13.3 @@ -0,0 +1,174 @@
13.4 +/*
13.5 + * PIC32 microcontroller interrupt handling code.
13.6 + *
13.7 + * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
13.8 + *
13.9 + * This program is free software: you can redistribute it and/or modify
13.10 + * it under the terms of the GNU General Public License as published by
13.11 + * the Free Software Foundation, either version 3 of the License, or
13.12 + * (at your option) any later version.
13.13 + *
13.14 + * This program is distributed in the hope that it will be useful,
13.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13.17 + * GNU General Public License for more details.
13.18 + *
13.19 + * You should have received a copy of the GNU General Public License
13.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
13.21 + */
13.22 +
13.23 +#include "mips.h"
13.24 +#include "pic32.h"
13.25 +#include "cpu.h"
13.26 +
13.27 +.globl enable_interrupts
13.28 +.globl handle_error_level
13.29 +.globl init_interrupts
13.30 +.extern exception_handler
13.31 +.extern interrupt_handler
13.32 +
13.33 +/* Put general routines in the text section. */
13.34 +
13.35 +.text
13.36 +
13.37 +/*
13.38 +Clear the error and exception status flags, making interrupts and exceptions
13.39 +possible.
13.40 +*/
13.41 +
13.42 +handle_error_level:
13.43 + mfc0 $t3, CP0_STATUS
13.44 +
13.45 + /* Clear error level and exception level. */
13.46 +
13.47 + li $t4, ~(STATUS_ERL | STATUS_EXL)
13.48 + and $t3, $t3, $t4
13.49 + mtc0 $t3, CP0_STATUS
13.50 +
13.51 + jr $ra
13.52 + nop
13.53 +
13.54 +/* Enable interrupts and direct interrupt requests to non-bootloader vectors. */
13.55 +
13.56 +enable_interrupts:
13.57 + mfc0 $t3, CP0_STATUS
13.58 +
13.59 + /* Clear interrupt priority bits. */
13.60 +
13.61 + li $t4, ~STATUS_IRQ
13.62 + and $t3, $t3, $t4
13.63 +
13.64 + /* Set interrupt priority. */
13.65 +
13.66 + ori $t3, $t3, (CPU_INT_PRIORITY << STATUS_IRQ_SHIFT)
13.67 +
13.68 + /* CP0_STATUS &= ~STATUS_BEV (use non-bootloader vectors) */
13.69 +
13.70 + li $t4, ~STATUS_BEV
13.71 + and $t3, $t3, $t4
13.72 +
13.73 + /* Enable interrupts. */
13.74 +
13.75 + ori $t3, $t3, STATUS_IE
13.76 + mtc0 $t3, CP0_STATUS
13.77 +
13.78 + jr $ra
13.79 + nop
13.80 +
13.81 +/* Initialise the interrupt system parameters. */
13.82 +
13.83 +init_interrupts:
13.84 + /* Clear debug mode. */
13.85 +
13.86 + mfc0 $t3, CP0_DEBUG
13.87 + li $t4, ~DEBUG_DM
13.88 + and $t3, $t3, $t4
13.89 + mtc0 $t3, CP0_DEBUG
13.90 +
13.91 + /* Update the exception base. */
13.92 +
13.93 + mfc0 $t3, CP0_STATUS
13.94 + li $t4, STATUS_BEV /* BEV = 1 or EBASE cannot be set */
13.95 + or $t3, $t3, $t4
13.96 + mtc0 $t3, CP0_STATUS
13.97 +
13.98 + la $t3, ebase
13.99 + mtc0 $t3, CP0_EBASE
13.100 +
13.101 + /* Set vector spacing. */
13.102 +
13.103 + li $t3, 0x20 /* Must be non-zero or the CPU gets upset */
13.104 + mtc0 $t3, CP0_INTCTL
13.105 +
13.106 + li $t3, CAUSE_IV /* IV = 1 (use EBASE+0x200 for interrupts) */
13.107 + mtc0 $t3, CP0_CAUSE
13.108 +
13.109 + jr $ra
13.110 + nop
13.111 +
13.112 +
13.113 +
13.114 +/* Exception servicing, positioned at EBASE at the start of program memory. */
13.115 +
13.116 +.section .vectors, "a"
13.117 +
13.118 +/* TLB error servicing. */
13.119 +
13.120 +ebase:
13.121 +tlb_handler:
13.122 + j exception_handler
13.123 + nop
13.124 +
13.125 +
13.126 +
13.127 +/* General exception servicing. */
13.128 +
13.129 +.org 0x180
13.130 +
13.131 +exc_handler:
13.132 + j exception_handler
13.133 + nop
13.134 +
13.135 +
13.136 +
13.137 +/* Interrupt servicing. */
13.138 +
13.139 +.org 0x200
13.140 +.set noat
13.141 +
13.142 +#define IRQ_STACK_LIMIT (KSEG0_BASE + IRQ_STACK_SIZE)
13.143 +#define IRQ_STACK_TOP (IRQ_STACK_LIMIT - 32 * 4)
13.144 +
13.145 +int_handler:
13.146 +
13.147 + /* Store affected registers from IRQ_STACK_LIMIT - 4 downwards. */
13.148 +
13.149 + lui $k0, %hi(IRQ_STACK_LIMIT)
13.150 + ori $k0, $k0, %lo(IRQ_STACK_LIMIT)
13.151 +
13.152 + .irp reg, \
13.153 + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 \
13.154 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \
13.155 + 28, 29, 30, 31
13.156 + sw $\reg, -(\reg * 4)($k0)
13.157 + .endr
13.158 +
13.159 + /* Switch to the IRQ stack. */
13.160 +
13.161 + lui $sp, %hi(IRQ_STACK_TOP)
13.162 + ori $sp, $sp, %lo(IRQ_STACK_TOP)
13.163 +
13.164 + jal interrupt_handler
13.165 + nop
13.166 +
13.167 + /* Restore affected registers. */
13.168 +
13.169 + .irp reg, \
13.170 + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 \
13.171 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \
13.172 + 28, 29, 30, 31
13.173 + lw $\reg, -(\reg * 4)($k0)
13.174 + .endr
13.175 +
13.176 + eret
13.177 + nop
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/lib/debug.c Mon Oct 22 21:44:02 2018 +0200
14.3 @@ -0,0 +1,108 @@
14.4 +/*
14.5 + * Some simple debugging functions.
14.6 + *
14.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
14.8 + *
14.9 + * This program is free software: you can redistribute it and/or modify
14.10 + * it under the terms of the GNU General Public License as published by
14.11 + * the Free Software Foundation, either version 3 of the License, or
14.12 + * (at your option) any later version.
14.13 + *
14.14 + * This program is distributed in the hope that it will be useful,
14.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14.17 + * GNU General Public License for more details.
14.18 + *
14.19 + * You should have received a copy of the GNU General Public License
14.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
14.21 + */
14.22 +
14.23 +#include "pic32_c.h"
14.24 +#include "debug.h"
14.25 +
14.26 +/* Register output functions using UART1. */
14.27 +
14.28 +void rbits(uint32_t reg)
14.29 +{
14.30 + bits(REG(reg), 4);
14.31 +}
14.32 +
14.33 +void rhex(uint32_t reg)
14.34 +{
14.35 + hex(REG(reg), 4);
14.36 +}
14.37 +
14.38 +/* Value output functions using UART1. */
14.39 +
14.40 +void bits(uint32_t val, int bytes)
14.41 +{
14.42 + uint32_t mask;
14.43 +
14.44 + for (mask = (1 << 31); mask; mask >>= 1)
14.45 + if (val & mask)
14.46 + uart_write('1');
14.47 + else
14.48 + uart_write('0');
14.49 +}
14.50 +
14.51 +void hex(uint32_t val, int bytes)
14.52 +{
14.53 + uint32_t mask;
14.54 + uint8_t digit, shift, start = bytes * 8 - 4;
14.55 +
14.56 + for (mask = (0b1111 << start), shift = start; mask; mask >>= 4, shift -= 4)
14.57 + {
14.58 + digit = (val & mask) >> shift;
14.59 + if (digit > 9)
14.60 + uart_write('A' + digit - 10);
14.61 + else
14.62 + uart_write('0' + digit);
14.63 + }
14.64 +}
14.65 +
14.66 +
14.67 +
14.68 +/* General input/output functions. */
14.69 +
14.70 +int uart_can_read(int uart)
14.71 +{
14.72 + return REG(UART_REG(uart, UxSTA)) & 1;
14.73 +}
14.74 +
14.75 +char uart_read_char(int uart)
14.76 +{
14.77 + return (char) REG(UART_REG(uart, UxRXREG));
14.78 +}
14.79 +
14.80 +int uart_can_write(int uart)
14.81 +{
14.82 + return !(REG(UART_REG(uart, UxSTA)) & (1 << 9)); /* UTXBF (buffer full) */
14.83 +}
14.84 +
14.85 +void uart_write_char(int uart, char c)
14.86 +{
14.87 + while (!uart_can_write(uart)); /* busy loop */
14.88 +
14.89 + REG(UART_REG(uart, UxTXREG)) = c;
14.90 +}
14.91 +
14.92 +
14.93 +
14.94 +/* Functions using UART1. */
14.95 +
14.96 +void uart_write(char c)
14.97 +{
14.98 + uart_write_char(1, c);
14.99 +}
14.100 +
14.101 +void uart_write_nl(void)
14.102 +{
14.103 + uart_write('\r');
14.104 + uart_write('\n');
14.105 +}
14.106 +
14.107 +void uart_write_string(const char *s)
14.108 +{
14.109 + while (*s)
14.110 + uart_write(*s++);
14.111 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/lib/init.c Mon Oct 22 21:44:02 2018 +0200
15.3 @@ -0,0 +1,715 @@
15.4 +/*
15.5 + * PIC32 peripheral configuration and initialisation.
15.6 + *
15.7 + * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
15.8 + *
15.9 + * This program is free software: you can redistribute it and/or modify
15.10 + * it under the terms of the GNU General Public License as published by
15.11 + * the Free Software Foundation, either version 3 of the License, or
15.12 + * (at your option) any later version.
15.13 + *
15.14 + * This program is distributed in the hope that it will be useful,
15.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
15.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15.17 + * GNU General Public License for more details.
15.18 + *
15.19 + * You should have received a copy of the GNU General Public License
15.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
15.21 + */
15.22 +
15.23 +#include "cpu.h"
15.24 +#include "pic32_c.h"
15.25 +#include "init.h"
15.26 +
15.27 +/* Application-specific configuration. */
15.28 +
15.29 +#include "devconfig.h"
15.30 +
15.31 +
15.32 +
15.33 +/* Basic memory and pin initialisation. */
15.34 +
15.35 +void init_memory(void)
15.36 +{
15.37 + /*
15.38 + Configure RAM.
15.39 + See: http://microchipdeveloper.com/32bit:mx-arch-exceptions-processor-initialization
15.40 + */
15.41 +
15.42 + uint32_t config = REG(BMXCON);
15.43 +
15.44 + /* Set zero wait states for address setup. */
15.45 +
15.46 + config &= ~(1 << 6); /* BMXCON<6> = BMXWSDRM = 0 */
15.47 +
15.48 + /* Set bus arbitration mode. */
15.49 +
15.50 + config &= ~0b111;
15.51 + config |= 0b010; /* BMXCON<2:0> = BMXARB<2:0> = 2 */
15.52 +
15.53 + REG(BMXCON) = config;
15.54 +}
15.55 +
15.56 +void init_pins(void)
15.57 +{
15.58 + /* DEVCFG0<2> also needs setting to 0 before the program is run. */
15.59 +
15.60 + CLR_REG(CFGCON, 1 << 3); /* CFGCON<3> = JTAGEN = 0 */
15.61 +}
15.62 +
15.63 +void init_outputs(void)
15.64 +{
15.65 + /* Remove analogue features from pins. */
15.66 +
15.67 + REG(ANSELA) = 0;
15.68 + REG(ANSELB) = 0;
15.69 +
15.70 + /* Set pins as outputs. */
15.71 +
15.72 + REG(TRISA) = 0;
15.73 + REG(TRISB) = 0;
15.74 +
15.75 + /* Clear outputs. */
15.76 +
15.77 + REG(PORTA) = 0;
15.78 + REG(PORTB) = 0;
15.79 +}
15.80 +
15.81 +
15.82 +
15.83 +/* Peripheral pin configuration. */
15.84 +
15.85 +void lock_config(void)
15.86 +{
15.87 + SET_REG(CFGCON, 1 << 13); /* IOLOCK = 1 */
15.88 +
15.89 + /* Lock the configuration again. */
15.90 +
15.91 + REG(SYSKEY) = 0x33333333;
15.92 +}
15.93 +
15.94 +void unlock_config(void)
15.95 +{
15.96 + /* Unlock the configuration register bits. */
15.97 +
15.98 + REG(SYSKEY) = 0;
15.99 + REG(SYSKEY) = 0xAA996655;
15.100 + REG(SYSKEY) = 0x556699AA;
15.101 +
15.102 + CLR_REG(CFGCON, 1 << 13); /* IOLOCK = 0 */
15.103 +}
15.104 +
15.105 +
15.106 +
15.107 +/* Convenience operations. */
15.108 +
15.109 +void interrupts_on(void)
15.110 +{
15.111 + init_interrupts();
15.112 + enable_interrupts();
15.113 + handle_error_level();
15.114 +}
15.115 +
15.116 +
15.117 +
15.118 +/* DMA configuration. */
15.119 +
15.120 +void init_dma(void)
15.121 +{
15.122 + /* Disable DMA interrupts (DMAxIE). */
15.123 +
15.124 + CLR_REG(DMAIEC, 0b1111 << DMAINTBASE);
15.125 +
15.126 + /* Clear DMA interrupt flags (DMAxIF). */
15.127 +
15.128 + CLR_REG(DMAIFS, 0b1111 << DMAINTBASE);
15.129 +
15.130 + /* Enable DMA. */
15.131 +
15.132 + SET_REG(DMACON, 1 << 15);
15.133 +}
15.134 +
15.135 +/* Initialise the given channel. */
15.136 +
15.137 +void dma_init(int channel, uint8_t pri)
15.138 +{
15.139 + if ((channel < DCHMIN) || (channel > DCHMAX))
15.140 + return;
15.141 +
15.142 + /* Initialise a channel. */
15.143 +
15.144 + REG(DMA_REG(channel, DCHxCON)) = pri & 0b11;
15.145 + REG(DMA_REG(channel, DCHxECON)) = 0;
15.146 + REG(DMA_REG(channel, DCHxINT)) = 0;
15.147 +}
15.148 +
15.149 +/* Set the channel repeated enable mode, enabling it again when a block transfer
15.150 + completes. The documentation describes this as auto-enable. */
15.151 +
15.152 +void dma_set_auto_enable(int channel, int enable)
15.153 +{
15.154 + (enable ? SET_REG : CLR_REG)(DMA_REG(channel, DCHxCON), 1 << 4);
15.155 +}
15.156 +
15.157 +/* Set the channel chaining mode. */
15.158 +
15.159 +void dma_set_chaining(int channel, enum dma_chain chain)
15.160 +{
15.161 + (chain != dma_chain_none ?
15.162 + SET_REG : CLR_REG)(DMA_REG(channel, DCHxCON), 1 << 5);
15.163 +
15.164 + (chain == dma_chain_next ?
15.165 + SET_REG : CLR_REG)(DMA_REG(channel, DCHxCON), 1 << 8);
15.166 +}
15.167 +
15.168 +/* Configure a channel's initiation interrupt. */
15.169 +
15.170 +void dma_set_interrupt(int channel, uint8_t int_num, int enable)
15.171 +{
15.172 + if ((channel < DCHMIN) || (channel > DCHMAX))
15.173 + return;
15.174 +
15.175 + /* Allow an interrupt to trigger the transfer. */
15.176 +
15.177 + REG(DMA_REG(channel, DCHxECON)) = (int_num << 8) |
15.178 + ((enable ? 1 : 0) << 4);
15.179 +}
15.180 +
15.181 +/* Configure only the channel's initiation interrupt status. */
15.182 +
15.183 +void dma_set_interrupt_enable(int channel, int enable)
15.184 +{
15.185 + if ((channel < DCHMIN) || (channel > DCHMAX))
15.186 + return;
15.187 +
15.188 + (enable ? SET_REG : CLR_REG)(DMA_REG(channel, DCHxECON), 1 << 4);
15.189 +}
15.190 +
15.191 +/* Permit the channel to register events while disabled or suspended. A
15.192 + suspended channel is one that is enabled but where the DMA peripheral
15.193 + has been suspended. */
15.194 +
15.195 +void dma_set_receive_events(int channel, int enable)
15.196 +{
15.197 + (enable ? SET_REG : CLR_REG)(DMA_REG(channel, DCHxCON), 1 << 6);
15.198 +}
15.199 +
15.200 +/* Set a channel's transfer parameters. */
15.201 +
15.202 +void dma_set_transfer(int channel,
15.203 + uint32_t source_start_address, uint16_t source_size,
15.204 + uint32_t destination_start_address, uint16_t destination_size,
15.205 + uint16_t cell_size)
15.206 +{
15.207 + if ((channel < DCHMIN) || (channel > DCHMAX))
15.208 + return;
15.209 +
15.210 + REG(DMA_REG(channel, DCHxSSIZ)) = source_size;
15.211 + REG(DMA_REG(channel, DCHxSSA)) = source_start_address;
15.212 + REG(DMA_REG(channel, DCHxDSIZ)) = destination_size;
15.213 + REG(DMA_REG(channel, DCHxDSA)) = destination_start_address;
15.214 + REG(DMA_REG(channel, DCHxCSIZ)) = cell_size;
15.215 +}
15.216 +
15.217 +/* Configure interrupts caused by the channel. */
15.218 +
15.219 +void dma_init_interrupt(int channel, uint8_t conditions,
15.220 + uint8_t pri, uint8_t sub)
15.221 +{
15.222 + if ((channel < DCHMIN) || (channel > DCHMAX))
15.223 + return;
15.224 +
15.225 + /* Disable channel interrupt and clear interrupt flag. */
15.226 +
15.227 + CLR_REG(DMAIEC, DMA_INT_FLAGS(channel, 1));
15.228 + CLR_REG(DMAIFS, DMA_INT_FLAGS(channel, 1));
15.229 +
15.230 + /* Produce an interrupt for the provided conditions. */
15.231 +
15.232 + REG(DMA_REG(channel, DCHxINT)) = conditions << 16;
15.233 +
15.234 + /* Set interrupt priorities. */
15.235 +
15.236 + REG(DMAIPC) = (REG(DMAIPC) &
15.237 + ~(DMA_IPC_PRI(channel, 7, 3))) |
15.238 + DMA_IPC_PRI(channel, pri, sub);
15.239 +
15.240 + /* Enable interrupt. */
15.241 +
15.242 + SET_REG(DMAIEC, DMA_INT_FLAGS(channel, 1));
15.243 +}
15.244 +
15.245 +/* Enable or disable the channel. */
15.246 +
15.247 +void dma_set_enable(int channel, int enable)
15.248 +{
15.249 + if ((channel < DCHMIN) || (channel > DCHMAX))
15.250 + return;
15.251 +
15.252 + (enable ? SET_REG : CLR_REG)(DMA_REG(channel, DCHxCON), 1 << 7);
15.253 +}
15.254 +
15.255 +/* Disable a DMA channel. */
15.256 +
15.257 +void dma_off(int channel)
15.258 +{
15.259 + dma_set_enable(channel, 0);
15.260 +}
15.261 +
15.262 +/* Enable a DMA channel. */
15.263 +
15.264 +void dma_on(int channel)
15.265 +{
15.266 + dma_set_enable(channel, 1);
15.267 +}
15.268 +
15.269 +
15.270 +
15.271 +/* External interrupt initialisation. */
15.272 +
15.273 +void int_init_interrupt(int int_num, uint8_t pri, uint8_t sub)
15.274 +{
15.275 + if ((int_num < INTMIN) || (int_num > INTMAX))
15.276 + return;
15.277 +
15.278 + /* Disable interrupt and clear interrupt flag. */
15.279 +
15.280 + CLR_REG(INTIEC, INT_INT_FLAGS(int_num, INTxIE));
15.281 + CLR_REG(INTIFS, INT_INT_FLAGS(int_num, INTxIF));
15.282 +
15.283 + /* Set interrupt priorities. */
15.284 +
15.285 + REG(INT_IPC_REG(int_num)) = (REG(INT_IPC_REG(int_num)) &
15.286 + ~(INT_IPC_PRI(int_num, 7, 3))) |
15.287 + INT_IPC_PRI(int_num, pri, sub);
15.288 +
15.289 + /* Enable interrupt. */
15.290 +
15.291 + SET_REG(INTIEC, INT_INT_FLAGS(int_num, INTxIE));
15.292 +}
15.293 +
15.294 +
15.295 +
15.296 +/* Output compare configuration. */
15.297 +
15.298 +void oc_init(int unit, uint8_t mode, int timer)
15.299 +{
15.300 + if ((unit < OCMIN) || (unit > OCMAX))
15.301 + return;
15.302 +
15.303 + REG(OC_REG(unit, OCxCON)) = (timer == 3 ? (1 << 3) : 0) | (mode & 0b111);
15.304 +}
15.305 +
15.306 +/* Set the start value for the pulse. */
15.307 +
15.308 +void oc_set_pulse(int unit, uint32_t start)
15.309 +{
15.310 + if ((unit < OCMIN) || (unit > OCMAX))
15.311 + return;
15.312 +
15.313 + REG(OC_REG(unit, OCxR)) = start;
15.314 +}
15.315 +
15.316 +/* Set the end value for the pulse. */
15.317 +
15.318 +void oc_set_pulse_end(int unit, uint32_t end)
15.319 +{
15.320 + if ((unit < OCMIN) || (unit > OCMAX))
15.321 + return;
15.322 +
15.323 + REG(OC_REG(unit, OCxRS)) = end;
15.324 +}
15.325 +
15.326 +/* Configure interrupts caused by the unit. */
15.327 +
15.328 +void oc_init_interrupt(int unit, uint8_t pri, uint8_t sub)
15.329 +{
15.330 + if ((unit < OCMIN) || (unit > OCMAX))
15.331 + return;
15.332 +
15.333 + /* Disable interrupt and clear interrupt flag. */
15.334 +
15.335 + CLR_REG(OCIEC, OC_INT_FLAGS(unit, OCxIE));
15.336 + CLR_REG(OCIFS, OC_INT_FLAGS(unit, OCxIF));
15.337 +
15.338 + /* Set interrupt priorities. */
15.339 +
15.340 + REG(OC_IPC_REG(unit)) = (REG(OC_IPC_REG(unit)) &
15.341 + ~(OC_IPC_PRI(unit, 7, 3))) |
15.342 + OC_IPC_PRI(unit, pri, sub);
15.343 +
15.344 + /* Enable interrupt. */
15.345 +
15.346 + SET_REG(OCIEC, OC_INT_FLAGS(unit, OCxIE));
15.347 +}
15.348 +
15.349 +/* Enable a unit. */
15.350 +
15.351 +void oc_on(int unit)
15.352 +{
15.353 + if ((unit < OCMIN) || (unit > OCMAX))
15.354 + return;
15.355 +
15.356 + SET_REG(OC_REG(unit, OCxCON), 1 << 15);
15.357 +}
15.358 +
15.359 +
15.360 +
15.361 +/* Parallel mode configuration. */
15.362 +
15.363 +void init_pm(void)
15.364 +{
15.365 + int i;
15.366 +
15.367 + /* Disable PM interrupts (PMxIE). */
15.368 +
15.369 + CLR_REG(PMIEC, 0b11 << PMINTBASE);
15.370 +
15.371 + /* Clear PM interrupt flags (PMxIF). */
15.372 +
15.373 + CLR_REG(PMIFS, 0b11 << PMINTBASE);
15.374 +
15.375 + /* Disable PM for configuration. */
15.376 +
15.377 + for (i = PMMIN; i <= PMMAX; i++)
15.378 + REG(PM_REG(i, PMxCON)) = 0;
15.379 +}
15.380 +
15.381 +/* Configure the parallel mode. */
15.382 +
15.383 +void pm_init(int port, uint8_t mode)
15.384 +{
15.385 + if ((port < PMMIN) || (port > PMMAX))
15.386 + return;
15.387 +
15.388 + REG(PM_REG(port, PMxMODE)) = (mode & 0b11) << 8;
15.389 + REG(PM_REG(port, PMxAEN)) = 0;
15.390 + REG(PM_REG(port, PMxADDR)) = 0;
15.391 +}
15.392 +
15.393 +/* Configure output signals. */
15.394 +
15.395 +void pm_set_output(int port, int write_enable, int read_enable)
15.396 +{
15.397 + if ((port < PMMIN) || (port > PMMAX))
15.398 + return;
15.399 +
15.400 + REG(PM_REG(port, PMxCON)) = (write_enable ? (1 << 9) : 0) |
15.401 + (read_enable ? (1 << 8) : 0) |
15.402 + (1 << 1); /* WRSP: PMENB active high */
15.403 +}
15.404 +
15.405 +/* Configure interrupts caused by parallel mode. */
15.406 +
15.407 +void pm_init_interrupt(int port, uint8_t pri, uint8_t sub)
15.408 +{
15.409 + if ((port < PMMIN) || (port > PMMAX))
15.410 + return;
15.411 +
15.412 + /* Disable interrupt and clear interrupt flag. */
15.413 +
15.414 + CLR_REG(PMIEC, PM_INT_FLAGS(port, PMxIE));
15.415 + CLR_REG(PMIFS, PM_INT_FLAGS(port, PMxIF));
15.416 +
15.417 + /* Set interrupt priorities. */
15.418 +
15.419 + REG(PM_IPC_REG(port)) = (REG(PM_IPC_REG(port)) &
15.420 + ~(PM_IPC_PRI(port, 7, 3))) |
15.421 + PM_IPC_PRI(port, pri, sub);
15.422 +
15.423 + /* Enable interrupt. */
15.424 +
15.425 + SET_REG(PMIEC, PM_INT_FLAGS(port, PMxIE));
15.426 +}
15.427 +
15.428 +/* Enable parallel mode. */
15.429 +
15.430 +void pm_on(int port)
15.431 +{
15.432 + if ((port < PMMIN) || (port > PMMAX))
15.433 + return;
15.434 +
15.435 + SET_REG(PM_REG(port, PMxCON), 1 << 15);
15.436 +}
15.437 +
15.438 +/* Disable parallel mode. */
15.439 +
15.440 +void pm_off(int port)
15.441 +{
15.442 + if ((port < PMMIN) || (port > PMMAX))
15.443 + return;
15.444 +
15.445 + CLR_REG(PM_REG(port, PMxCON), 1 << 15);
15.446 +}
15.447 +
15.448 +
15.449 +
15.450 +
15.451 +/* Timer configuration. */
15.452 +
15.453 +void timer_init(int timer, uint8_t prescale, uint16_t limit)
15.454 +{
15.455 + /* NOTE: Should convert from the real prescale value. */
15.456 +
15.457 + REG(TIMER_REG(timer, TxCON)) = (prescale & 0b111) << 4;
15.458 + REG(TIMER_REG(timer, TMRx)) = 0;
15.459 + REG(TIMER_REG(timer, PRx)) = limit;
15.460 +}
15.461 +
15.462 +/* Configure interrupts caused by the timer. */
15.463 +
15.464 +void timer_init_interrupt(int timer, uint8_t pri, uint8_t sub)
15.465 +{
15.466 + if ((timer < TIMERMIN) || (timer > TIMERMAX))
15.467 + return;
15.468 +
15.469 + /* Disable interrupt and clear interrupt flag. */
15.470 +
15.471 + CLR_REG(TIMERIEC, TIMER_INT_FLAGS(timer, TxIE));
15.472 + CLR_REG(TIMERIFS, TIMER_INT_FLAGS(timer, TxIF));
15.473 +
15.474 + /* Set interrupt priorities. */
15.475 +
15.476 + REG(TIMER_IPC_REG(timer)) = (REG(TIMER_IPC_REG(timer)) &
15.477 + ~(TIMER_IPC_PRI(timer, 7, 3))) |
15.478 + TIMER_IPC_PRI(timer, pri, sub);
15.479 +
15.480 + /* Enable interrupt. */
15.481 +
15.482 + SET_REG(TIMERIEC, TIMER_INT_FLAGS(timer, TxIE));
15.483 +}
15.484 +
15.485 +/* Enable a timer. */
15.486 +
15.487 +void timer_on(int timer)
15.488 +{
15.489 + if ((timer < TIMERMIN) || (timer > TIMERMAX))
15.490 + return;
15.491 +
15.492 + SET_REG(TIMER_REG(timer, TxCON), 1 << 15);
15.493 +}
15.494 +
15.495 +
15.496 +
15.497 +/* UART configuration. */
15.498 +
15.499 +void uart_init(int uart, uint32_t baudrate)
15.500 +{
15.501 + /* FPB is configured in the devconfig.h file and set in the start.S file. */
15.502 +
15.503 + if ((uart < UARTMIN) || (uart > UARTMAX))
15.504 + return;
15.505 +
15.506 + /* Disable the UART (ON). */
15.507 +
15.508 + CLR_REG(UART_REG(uart, UxMODE), 1 << 15);
15.509 +
15.510 + /* Set the baud rate. For example:
15.511 +
15.512 + UxBRG<15:0> = BRG
15.513 + = (FPB / (16 * baudrate)) - 1
15.514 + = (24000000 / (16 * 115200)) - 1
15.515 + = 12
15.516 + */
15.517 +
15.518 + REG(UART_REG(uart, UxBRG)) = (FPB / (16 * baudrate)) - 1;
15.519 +}
15.520 +
15.521 +/* Configure interrupts caused by the UART. */
15.522 +
15.523 +void uart_init_interrupt(int uart, uint8_t conditions,
15.524 + uint8_t pri, uint8_t sub)
15.525 +{
15.526 + if ((uart < UARTMIN) || (uart > UARTMAX))
15.527 + return;
15.528 +
15.529 + /* Disable interrupts and clear interrupt flags. */
15.530 +
15.531 + CLR_REG(UARTIEC, UART_INT_FLAGS(uart, UxTIE | UxRIE | UxEIE));
15.532 + CLR_REG(UARTIFS, UART_INT_FLAGS(uart, UxTIF | UxRIF | UxEIF));
15.533 +
15.534 + /* Set priorities: UxIP = pri; UxIS = sub */
15.535 +
15.536 + REG(UART_IPC_REG(uart)) = (REG(UART_IPC_REG(uart)) &
15.537 + ~UART_IPC_PRI(uart, 7, 3)) |
15.538 + UART_IPC_PRI(uart, pri, sub);
15.539 +
15.540 + /* Enable interrupts. */
15.541 +
15.542 + SET_REG(UARTIEC, UART_INT_FLAGS(uart, conditions));
15.543 +}
15.544 +
15.545 +/* Enable a UART. */
15.546 +
15.547 +void uart_on(int uart)
15.548 +{
15.549 + if ((uart < UARTMIN) || (uart > UARTMAX))
15.550 + return;
15.551 +
15.552 + /* Enable receive (URXEN) and transmit (UTXEN). */
15.553 +
15.554 + SET_REG(UART_REG(uart, UxSTA), (1 << 12) | (1 << 10));
15.555 +
15.556 + /* Start UART. */
15.557 +
15.558 + SET_REG(UART_REG(uart, UxMODE), 1 << 15);
15.559 +}
15.560 +
15.561 +
15.562 +
15.563 +/* Utility functions. */
15.564 +
15.565 +/* Return encoded interrupt priorities. */
15.566 +
15.567 +static uint8_t PRI(uint8_t pri, uint8_t sub)
15.568 +{
15.569 + return ((pri & 0b111) << 2) | (sub & 0b11);
15.570 +}
15.571 +
15.572 +/* Return the DMA interrupt flags for combining with a register. */
15.573 +
15.574 +int DMA_INT_FLAGS(int channel, uint8_t flags)
15.575 +{
15.576 + return (flags & 0b1) << (DMAINTBASE + (channel - DCHMIN));
15.577 +}
15.578 +
15.579 +/* Return encoded DMA interrupt priorities for combining with a register. */
15.580 +
15.581 +uint32_t DMA_IPC_PRI(int channel, uint8_t pri, uint8_t sub)
15.582 +{
15.583 + return PRI(pri, sub) << (DCHIPCBASE + (channel - DCHMIN) * DCHIPCSTEP);
15.584 +}
15.585 +
15.586 +/* Return encoded external interrupt priorities for combining with a register. */
15.587 +
15.588 +uint32_t INT_IPC_PRI(int int_num, uint8_t pri, uint8_t sub)
15.589 +{
15.590 + (void) int_num;
15.591 + return PRI(pri, sub) << INTIPCBASE;
15.592 +}
15.593 +
15.594 +/* Return the external interrupt priorities register. */
15.595 +
15.596 +uint32_t INT_IPC_REG(int int_num)
15.597 +{
15.598 + switch (int_num)
15.599 + {
15.600 + case 0: return INT0IPC;
15.601 + case 1: return INT1IPC;
15.602 + case 2: return INT2IPC;
15.603 + case 3: return INT3IPC;
15.604 + case 4: return INT4IPC;
15.605 + default: return 0; /* should not occur */
15.606 + }
15.607 +}
15.608 +
15.609 +/* Return the external interrupt flags for combining with a register. */
15.610 +
15.611 +int INT_INT_FLAGS(int int_num, uint8_t flags)
15.612 +{
15.613 + return (flags & 0b1) << (INTINTBASE + (int_num - INTMIN) * INTINTSTEP);
15.614 +}
15.615 +
15.616 +/* Return encoded output compare interrupt priorities for combining with a register. */
15.617 +
15.618 +uint32_t OC_IPC_PRI(int unit, uint8_t pri, uint8_t sub)
15.619 +{
15.620 + (void) unit;
15.621 + return PRI(pri, sub) << OCIPCBASE;
15.622 +}
15.623 +
15.624 +/* Return the output compare interrupt priorities register. */
15.625 +
15.626 +uint32_t OC_IPC_REG(int unit)
15.627 +{
15.628 + switch (unit)
15.629 + {
15.630 + case 1: return OC1IPC;
15.631 + case 2: return OC2IPC;
15.632 + case 3: return OC3IPC;
15.633 + case 4: return OC4IPC;
15.634 + case 5: return OC5IPC;
15.635 + default: return 0; /* should not occur */
15.636 + }
15.637 +}
15.638 +
15.639 +/* Return the output compare interrupt flags for combining with a register. */
15.640 +
15.641 +int OC_INT_FLAGS(int unit, uint8_t flags)
15.642 +{
15.643 + return (flags & 0b1) << (OCINTBASE + (unit - OCMIN) * OCINTSTEP);
15.644 +}
15.645 +
15.646 +/* Return encoded parallel mode interrupt priorities for combining with a register. */
15.647 +
15.648 +uint32_t PM_IPC_PRI(int port, uint8_t pri, uint8_t sub)
15.649 +{
15.650 + (void) port;
15.651 + return PRI(pri, sub) << PMIPCBASE;
15.652 +}
15.653 +
15.654 +/* Return the parallel mode interrupt priorities register. */
15.655 +
15.656 +uint32_t PM_IPC_REG(int port)
15.657 +{
15.658 + (void) port;
15.659 + return PMIPC;
15.660 +}
15.661 +
15.662 +/* Return the parallel mode interrupt flags for combining with a register. */
15.663 +
15.664 +int PM_INT_FLAGS(int port, uint8_t flags)
15.665 +{
15.666 + return (flags & 0b11) << (PMINTBASE + (port - PMMIN) * PMINTSTEP);
15.667 +}
15.668 +
15.669 +/* Return encoded timer interrupt priorities for combining with a register. */
15.670 +
15.671 +uint32_t TIMER_IPC_PRI(int timer, uint8_t pri, uint8_t sub)
15.672 +{
15.673 + (void) timer;
15.674 + return PRI(pri, sub) << TIMERIPCBASE;
15.675 +}
15.676 +
15.677 +/* Return the timer interrupt priorities register. */
15.678 +
15.679 +uint32_t TIMER_IPC_REG(int timer)
15.680 +{
15.681 + switch (timer)
15.682 + {
15.683 + case 1: return TIMER1IPC;
15.684 + case 2: return TIMER2IPC;
15.685 + case 3: return TIMER3IPC;
15.686 + case 4: return TIMER4IPC;
15.687 + case 5: return TIMER5IPC;
15.688 + default: return 0; /* should not occur */
15.689 + }
15.690 +}
15.691 +
15.692 +/* Return the timer interrupt flags for combining with a register. */
15.693 +
15.694 +int TIMER_INT_FLAGS(int timer, uint8_t flags)
15.695 +{
15.696 + return (flags & 0b1) << (TIMERINTBASE + (timer - TIMERMIN) * TIMERINTSTEP);
15.697 +}
15.698 +
15.699 +/* Return encoded UART interrupt priorities for combining with a register. */
15.700 +
15.701 +uint32_t UART_IPC_PRI(int uart, uint8_t pri, uint8_t sub)
15.702 +{
15.703 + return PRI(pri, sub) << (uart == 1 ? UART1IPCBASE : UART2IPCBASE);
15.704 +}
15.705 +
15.706 +/* Return the UART interrupt priorities register. */
15.707 +
15.708 +uint32_t UART_IPC_REG(int uart)
15.709 +{
15.710 + return uart == 1 ? UART1IPC : UART2IPC;
15.711 +}
15.712 +
15.713 +/* Return the UART interrupt flags for combining with a register. */
15.714 +
15.715 +int UART_INT_FLAGS(int uart, uint8_t flags)
15.716 +{
15.717 + return (flags & 0b111) << (UARTINTBASE + (uart - UARTMIN) * UARTINTSTEP);
15.718 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/lib/payload.ld Mon Oct 22 21:44:02 2018 +0200
16.3 @@ -0,0 +1,70 @@
16.4 +OUTPUT_ARCH(mips)
16.5 +ENTRY(_start)
16.6 +
16.7 +IRQ_STACK_SIZE = 256;
16.8 +
16.9 +/* See...
16.10 + * FIGURE 4-5: MEMORY MAP ON RESET FOR PIC32MX170/270 DEVICES (64 KB RAM, 256 KB FLASH)
16.11 + * PIC32MX1XX/2XX 28/36/44-pin Family Data Sheet
16.12 + */
16.13 +
16.14 +MEMORY
16.15 +{
16.16 + kseg0_boot_mem (rx) : ORIGIN = 0x9FC00000, LENGTH = 0xBF0
16.17 + kseg0_program_mem (rx) : ORIGIN = 0x9D000000, LENGTH = 0x40000
16.18 + kseg0_data_mem (w!x) : ORIGIN = 0x80000000, LENGTH = 0x10000
16.19 + physical_boot_mem (rx) : ORIGIN = 0x1FC00000, LENGTH = 0xBF0
16.20 + physical_program_mem (rx) : ORIGIN = 0x1D000000, LENGTH = 0x40000
16.21 + physical_data_mem (w!x) : ORIGIN = 0x00000000, LENGTH = 0x10000
16.22 + sfrs : ORIGIN = 0xBF800000, LENGTH = 0x100000
16.23 + configsfrs : ORIGIN = 0xBFC00BF0, LENGTH = 0x10
16.24 + config3 : ORIGIN = 0xBFC00BF0, LENGTH = 0x4
16.25 + config2 : ORIGIN = 0xBFC00BF4, LENGTH = 0x4
16.26 + config1 : ORIGIN = 0xBFC00BF8, LENGTH = 0x4
16.27 + config0 : ORIGIN = 0xBFC00BFC, LENGTH = 0x4
16.28 + physical_config3 : ORIGIN = 0x3FC00BF0, LENGTH = 0x4
16.29 + physical_config2 : ORIGIN = 0x3FC00BF4, LENGTH = 0x4
16.30 + physical_config1 : ORIGIN = 0x3FC00BF8, LENGTH = 0x4
16.31 + physical_config0 : ORIGIN = 0x3FC00BFC, LENGTH = 0x4
16.32 +}
16.33 +
16.34 +SECTIONS
16.35 +{
16.36 + /* Boot program. */
16.37 +
16.38 + .boot : { *(.boot*) } > kseg0_boot_mem AT > physical_boot_mem
16.39 +
16.40 + /* Exception/interrupt vectors and general program code. */
16.41 +
16.42 + .vectors : { *(.vectors*) } > kseg0_program_mem AT > physical_program_mem
16.43 + .text : { *(.text*) } > kseg0_program_mem AT > physical_program_mem
16.44 +
16.45 + /* Reserve space at the bottom of RAM for the IRQ stack. */
16.46 +
16.47 + .irqstack : {
16.48 + . += IRQ_STACK_SIZE;
16.49 + } > kseg0_data_mem AT > physical_data_mem
16.50 +
16.51 + /* Add other data after the IRQ stack. */
16.52 +
16.53 + .bss : { *(.bss*) } > kseg0_data_mem AT > physical_data_mem
16.54 + .data : { *(.data*) } > kseg0_data_mem AT > physical_data_mem
16.55 +
16.56 + /* Store constant data in program memory. */
16.57 +
16.58 + .rodata : { *(.rodata*) } > kseg0_program_mem AT > physical_program_mem
16.59 + .got : {
16.60 + _gp = ALIGN(16);
16.61 + *(.got*)
16.62 + } > kseg0_program_mem AT > physical_program_mem
16.63 +
16.64 + /* Device configuration registers to be flashed. */
16.65 +
16.66 + .devcfg0 : { *(.devcfg0) } > config0 AT > physical_config0
16.67 + .devcfg1 : { *(.devcfg1) } > config1 AT > physical_config1
16.68 + .devcfg2 : { *(.devcfg2) } > config2 AT > physical_config2
16.69 +
16.70 + /* Discard things that might overwrite useful data. */
16.71 +
16.72 + /DISCARD/ : { *(.reginfo) *(.MIPS.abiflags) *(.pdr) *(.gnu.attributes) *(.comment) }
16.73 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/lib/start.S Mon Oct 22 21:44:02 2018 +0200
17.3 @@ -0,0 +1,83 @@
17.4 +/*
17.5 + * PIC32 microcontroller initialisation code.
17.6 + *
17.7 + * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
17.8 + *
17.9 + * This program is free software: you can redistribute it and/or modify
17.10 + * it under the terms of the GNU General Public License as published by
17.11 + * the Free Software Foundation, either version 3 of the License, or
17.12 + * (at your option) any later version.
17.13 + *
17.14 + * This program is distributed in the hope that it will be useful,
17.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17.17 + * GNU General Public License for more details.
17.18 + *
17.19 + * You should have received a copy of the GNU General Public License
17.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
17.21 + */
17.22 +
17.23 +#include "mips.h"
17.24 +#include "pic32.h"
17.25 +
17.26 +/* Application-specific configuration. */
17.27 +
17.28 +#include "devconfig.h"
17.29 +
17.30 +/* Disable JTAG functionality on pins. */
17.31 +
17.32 +.section .devcfg0, "a"
17.33 +.word 0xfffffffb /* DEVCFG0<2> = JTAGEN = 0 */
17.34 +
17.35 +/* Select oscillator, pin usage, watchdog timer and peripheral clock divider. */
17.36 +
17.37 +.section .devcfg1, "a"
17.38 +.word (DEVCFG1_UNUSED | DEVCFG1_CONFIG)
17.39 +
17.40 +/* Set clock dividers and multiplier. */
17.41 +
17.42 +.section .devcfg2, "a"
17.43 +.word (DEVCFG2_UNUSED | DEVCFG2_CONFIG)
17.44 +
17.45 +/* The start routine is placed at the boot location. */
17.46 +
17.47 +.section .boot, "a"
17.48 +
17.49 +.globl _start
17.50 +.extern main
17.51 +
17.52 +_start:
17.53 + /* Enable caching. */
17.54 +
17.55 + mfc0 $v1, CP0_CONFIG
17.56 + li $t8, ~CONFIG_K0
17.57 + and $v1, $v1, $t8
17.58 + ori $v1, $v1, CONFIG_K0_CACHABLE_NONCOHERENT
17.59 + mtc0 $v1, CP0_CONFIG
17.60 + nop
17.61 +
17.62 + /* Get the RAM size. */
17.63 +
17.64 + la $v1, BMXDRMSZ
17.65 + lw $t0, 0($v1)
17.66 +
17.67 + /* Initialise the stack pointer. */
17.68 +
17.69 + li $v1, KSEG0_BASE
17.70 + addu $sp, $t0, $v1 /* sp = KSEG0_BASE + RAM size */
17.71 +
17.72 + /* Initialise the globals pointer. */
17.73 +
17.74 + lui $gp, %hi(_GLOBAL_OFFSET_TABLE_)
17.75 + ori $gp, $gp, %lo(_GLOBAL_OFFSET_TABLE_)
17.76 +
17.77 + /*
17.78 + Jump to the main program. Since the boot code is separate from the
17.79 + other code, the address cannot be obtained via the GOT.
17.80 + ("relocation truncated to fit: R_MIPS_PC16 against `main'")
17.81 + */
17.82 +
17.83 + lui $t9, %hi(main)
17.84 + ori $t9, $t9, %lo(main)
17.85 + jr $t9
17.86 + nop
18.1 --- a/mips.h Mon Oct 22 19:12:33 2018 +0200
18.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
18.3 @@ -1,63 +0,0 @@
18.4 -#ifndef __MIPS_H__
18.5 -#define __MIPS_H__
18.6 -
18.7 -#define KSEG0_BASE 0x80000000
18.8 -#define KSEG1_BASE 0xA0000000
18.9 -
18.10 -#define CP0_INDEX $0
18.11 -#define CP0_ENTRYLO0 $2
18.12 -#define CP0_ENTRYLO1 $3
18.13 -#define CP0_CONTEXT $4
18.14 -#define CP0_PAGEMASK $5
18.15 -#define CP0_WIRED $6
18.16 -#define CP0_BADVADDR $8
18.17 -#define CP0_COUNT $9
18.18 -#define CP0_ENTRYHI $10
18.19 -#define CP0_COMPARE $11
18.20 -#define CP0_STATUS $12
18.21 -#define CP0_INTCTL $12, 1
18.22 -#define CP0_CAUSE $13
18.23 -#define CP0_EPC $14
18.24 -#define CP0_EBASE $15, 1
18.25 -#define CP0_CONFIG $16
18.26 -#define CP0_WATCHLO $18
18.27 -#define CP0_DEBUG $23
18.28 -#define CP0_TAGLO $28
18.29 -#define CP0_TAGHI $29
18.30 -#define CP0_ERROREPC $30, 0
18.31 -
18.32 -#define STATUS_CP0 0x10000000
18.33 -#define STATUS_BEV 0x00400000
18.34 -
18.35 -#define STATUS_IRQ 0x0000fc00
18.36 -#define STATUS_IRQ_SHIFT 10
18.37 -
18.38 -#define STATUS_UM 0x00000010
18.39 -#define STATUS_ERL 0x00000004
18.40 -#define STATUS_EXL 0x00000002
18.41 -#define STATUS_IE 0x00000001
18.42 -
18.43 -#define CAUSE_IV 0x00800000
18.44 -
18.45 -#define EBASE_MASK 0x3ffff000
18.46 -
18.47 -#define INTCTL_MASK 0x000003e0
18.48 -
18.49 -#define DEBUG_DM 0x40000000
18.50 -
18.51 -#define TLB_CACHED 0x00000018
18.52 -#define TLB_UNCACHED 0x00000010
18.53 -#define TLB_DIRTY 0x00000004
18.54 -#define TLB_VALID 0x00000002
18.55 -#define TLB_GLOBAL 0x00000001
18.56 -
18.57 -#define TLB_READ (TLB_CACHED | TLB_VALID)
18.58 -#define TLB_WRITE (TLB_CACHED | TLB_DIRTY | TLB_VALID)
18.59 -#define TLB_ALL_READ (TLB_CACHED | TLB_VALID | TLB_GLOBAL)
18.60 -#define TLB_ALL_WRITE (TLB_CACHED | TLB_DIRTY | TLB_VALID | TLB_GLOBAL)
18.61 -
18.62 -#define CONFIG_K0 0x00000007
18.63 -#define CONFIG_K0_UNCACHED 2
18.64 -#define CONFIG_K0_CACHABLE_NONCOHERENT 3
18.65 -
18.66 -#endif /* __MIPS_H__ */
19.1 --- a/mk/common.mk Mon Oct 22 19:12:33 2018 +0200
19.2 +++ b/mk/common.mk Mon Oct 22 21:44:02 2018 +0200
19.3 @@ -23,6 +23,11 @@
19.4 OBJCOPY=$(ARCH)-objcopy
19.5 OBJDUMP=$(ARCH)-objdump
19.6
19.7 +# These paths are relative to each example directory.
19.8 +
19.9 +INCDIR = ../../include
19.10 +LIBDIR = ../../lib
19.11 +
19.12 # NOTE: -O2 is actually needed to prevent memcpy references, whereas probably
19.13 # NOTE: one of the -f{freestanding, no-hosted, no-builtin} options should work.
19.14 # NOTE: See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56888
19.15 @@ -31,21 +36,21 @@
19.16 -fno-unit-at-a-time -fno-zero-initialized-in-bss \
19.17 -ffreestanding -fno-hosted -fno-builtin \
19.18 -march=mips32 \
19.19 - -I. -I../..
19.20 + -I. \
19.21 + -I$(INCDIR)
19.22 LDFLAGS = -nostdlib -EL
19.23
19.24 # Ordering of objects is important and cannot be left to replacement rules.
19.25 -# These are relative to each example directory.
19.26
19.27 -START_SRC = ../../start.S
19.28 -START_OBJ = ../../start.o
19.29 +START_SRC = $(LIBDIR)/start.S
19.30 +START_OBJ = $(LIBDIR)/start.o
19.31
19.32 # Application-specific files appear after the above but before those below in
19.33 # the application Makefiles.
19.34
19.35 -COMMON_SRC = ../../init.c ../../debug.c ../../cpu.S
19.36 -COMMON_OBJ = ../../init.o ../../debug.o ../../cpu.o
19.37 +COMMON_SRC = $(LIBDIR)/init.c $(LIBDIR)/debug.c $(LIBDIR)/cpu.S
19.38 +COMMON_OBJ = $(LIBDIR)/init.o $(LIBDIR)/debug.o $(LIBDIR)/cpu.o
19.39
19.40 # Common linker script.
19.41
19.42 -SCRIPT = ../../payload.ld
19.43 +SCRIPT = $(LIBDIR)/payload.ld
20.1 --- a/payload.ld Mon Oct 22 19:12:33 2018 +0200
20.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
20.3 @@ -1,70 +0,0 @@
20.4 -OUTPUT_ARCH(mips)
20.5 -ENTRY(_start)
20.6 -
20.7 -IRQ_STACK_SIZE = 256;
20.8 -
20.9 -/* See...
20.10 - * FIGURE 4-5: MEMORY MAP ON RESET FOR PIC32MX170/270 DEVICES (64 KB RAM, 256 KB FLASH)
20.11 - * PIC32MX1XX/2XX 28/36/44-pin Family Data Sheet
20.12 - */
20.13 -
20.14 -MEMORY
20.15 -{
20.16 - kseg0_boot_mem (rx) : ORIGIN = 0x9FC00000, LENGTH = 0xBF0
20.17 - kseg0_program_mem (rx) : ORIGIN = 0x9D000000, LENGTH = 0x40000
20.18 - kseg0_data_mem (w!x) : ORIGIN = 0x80000000, LENGTH = 0x10000
20.19 - physical_boot_mem (rx) : ORIGIN = 0x1FC00000, LENGTH = 0xBF0
20.20 - physical_program_mem (rx) : ORIGIN = 0x1D000000, LENGTH = 0x40000
20.21 - physical_data_mem (w!x) : ORIGIN = 0x00000000, LENGTH = 0x10000
20.22 - sfrs : ORIGIN = 0xBF800000, LENGTH = 0x100000
20.23 - configsfrs : ORIGIN = 0xBFC00BF0, LENGTH = 0x10
20.24 - config3 : ORIGIN = 0xBFC00BF0, LENGTH = 0x4
20.25 - config2 : ORIGIN = 0xBFC00BF4, LENGTH = 0x4
20.26 - config1 : ORIGIN = 0xBFC00BF8, LENGTH = 0x4
20.27 - config0 : ORIGIN = 0xBFC00BFC, LENGTH = 0x4
20.28 - physical_config3 : ORIGIN = 0x3FC00BF0, LENGTH = 0x4
20.29 - physical_config2 : ORIGIN = 0x3FC00BF4, LENGTH = 0x4
20.30 - physical_config1 : ORIGIN = 0x3FC00BF8, LENGTH = 0x4
20.31 - physical_config0 : ORIGIN = 0x3FC00BFC, LENGTH = 0x4
20.32 -}
20.33 -
20.34 -SECTIONS
20.35 -{
20.36 - /* Boot program. */
20.37 -
20.38 - .boot : { *(.boot*) } > kseg0_boot_mem AT > physical_boot_mem
20.39 -
20.40 - /* Exception/interrupt vectors and general program code. */
20.41 -
20.42 - .vectors : { *(.vectors*) } > kseg0_program_mem AT > physical_program_mem
20.43 - .text : { *(.text*) } > kseg0_program_mem AT > physical_program_mem
20.44 -
20.45 - /* Reserve space at the bottom of RAM for the IRQ stack. */
20.46 -
20.47 - .irqstack : {
20.48 - . += IRQ_STACK_SIZE;
20.49 - } > kseg0_data_mem AT > physical_data_mem
20.50 -
20.51 - /* Add other data after the IRQ stack. */
20.52 -
20.53 - .bss : { *(.bss*) } > kseg0_data_mem AT > physical_data_mem
20.54 - .data : { *(.data*) } > kseg0_data_mem AT > physical_data_mem
20.55 -
20.56 - /* Store constant data in program memory. */
20.57 -
20.58 - .rodata : { *(.rodata*) } > kseg0_program_mem AT > physical_program_mem
20.59 - .got : {
20.60 - _gp = ALIGN(16);
20.61 - *(.got*)
20.62 - } > kseg0_program_mem AT > physical_program_mem
20.63 -
20.64 - /* Device configuration registers to be flashed. */
20.65 -
20.66 - .devcfg0 : { *(.devcfg0) } > config0 AT > physical_config0
20.67 - .devcfg1 : { *(.devcfg1) } > config1 AT > physical_config1
20.68 - .devcfg2 : { *(.devcfg2) } > config2 AT > physical_config2
20.69 -
20.70 - /* Discard things that might overwrite useful data. */
20.71 -
20.72 - /DISCARD/ : { *(.reginfo) *(.MIPS.abiflags) *(.pdr) *(.gnu.attributes) *(.comment) }
20.73 -}
21.1 --- a/pic32.h Mon Oct 22 19:12:33 2018 +0200
21.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
21.3 @@ -1,382 +0,0 @@
21.4 -/*
21.5 - * PIC32 peripheral descriptions.
21.6 - *
21.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
21.8 - *
21.9 - * This program is free software: you can redistribute it and/or modify
21.10 - * it under the terms of the GNU General Public License as published by
21.11 - * the Free Software Foundation, either version 3 of the License, or
21.12 - * (at your option) any later version.
21.13 - *
21.14 - * This program is distributed in the hope that it will be useful,
21.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
21.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21.17 - * GNU General Public License for more details.
21.18 - *
21.19 - * You should have received a copy of the GNU General Public License
21.20 - * along with this program. If not, see <http://www.gnu.org/licenses/>.
21.21 - */
21.22 -
21.23 -#ifndef __PIC32_H__
21.24 -#define __PIC32_H__
21.25 -
21.26 -/* Peripheral addresses.
21.27 - * See...
21.28 - * TABLE 4-1: SFR MEMORYMAP
21.29 - * TABLE 11-3: PORTA REGISTER MAP
21.30 - * PIC32MX1XX/2XX 28/36/44-pin Family Data Sheet
21.31 - */
21.32 -
21.33 -#define OSCCON 0xBF80F000
21.34 -#define REFOCON 0xBF80F020
21.35 -#define REFOTRIM 0xBF80F030
21.36 -#define CFGCON 0xBF80F200
21.37 -#define SYSKEY 0xBF80F230
21.38 -
21.39 -#define INT2R 0xBF80FA08
21.40 -#define U1RXR 0xBF80FA50
21.41 -
21.42 -#define RPA0R 0xBF80FB00
21.43 -#define RPA1R 0xBF80FB04
21.44 -#define RPA2R 0xBF80FB08
21.45 -#define RPA3R 0xBF80FB0C
21.46 -#define RPA4R 0xBF80FB10
21.47 -#define RPB0R 0xBF80FB2C
21.48 -#define RPB1R 0xBF80FB30
21.49 -#define RPB2R 0xBF80FB34
21.50 -#define RPB3R 0xBF80FB38
21.51 -#define RPB4R 0xBF80FB3C
21.52 -#define RPB5R 0xBF80FB40
21.53 -#define RPB10R 0xBF80FB54
21.54 -#define RPB15R 0xBF80FB68
21.55 -
21.56 -#define INTCON 0xBF881000
21.57 -#define IFS0 0xBF881030
21.58 -#define IFS1 0xBF881040
21.59 -#define IEC0 0xBF881060
21.60 -#define IEC1 0xBF881070
21.61 -#define IPC0 0xBF881090
21.62 -#define IPC1 0xBF8810A0
21.63 -#define IPC2 0xBF8810B0
21.64 -#define IPC3 0xBF8810C0
21.65 -#define IPC4 0xBF8810D0
21.66 -#define IPC5 0xBF8810E0
21.67 -#define IPC6 0xBF8810F0
21.68 -#define IPC7 0xBF881100
21.69 -#define IPC8 0xBF881110
21.70 -#define IPC9 0xBF881120
21.71 -#define IPC10 0xBF881130
21.72 -
21.73 -#define BMXCON 0xBF882000
21.74 -#define BMXDKPBA 0xBF882010
21.75 -#define BMXDUDBA 0xBF882020
21.76 -#define BMXDUPBA 0xBF882030
21.77 -#define BMXDRMSZ 0xBF882040
21.78 -
21.79 -#define ANSELA 0xBF886000
21.80 -#define TRISA 0xBF886010
21.81 -#define PORTA 0xBF886020
21.82 -#define LATA 0xBF886030
21.83 -#define ODCA 0xBF886040
21.84 -#define ANSELB 0xBF886100
21.85 -#define TRISB 0xBF886110
21.86 -#define PORTB 0xBF886120
21.87 -#define LATB 0xBF886130
21.88 -#define ODCB 0xBF886140
21.89 -
21.90 -/* DEVCFG conveniences. */
21.91 -
21.92 -#define DEVCFG1_UNUSED 0xff7fcbd8 /* exclude FWDTWINSZ, WINDIS, WDTPS, FCKSM, POSCMOD, IESO */
21.93 -
21.94 -#define DEVCFG1_FWDTEN_OFF (0 << 23)
21.95 -#define DEVCFG1_FWDTEN_ON (1 << 23)
21.96 -
21.97 -#define DEVCFG1_FPBDIV_1 (0b00 << 12)
21.98 -#define DEVCFG1_FPBDIV_2 (0b01 << 12)
21.99 -#define DEVCFG1_FPBDIV_4 (0b10 << 12)
21.100 -#define DEVCFG1_FPBDIV_8 (0b11 << 12)
21.101 -
21.102 -#define DEVCFG1_OSCIOFNC_ON (0 << 10)
21.103 -#define DEVCFG1_OSCIOFNC_OFF (1 << 10)
21.104 -
21.105 -#define DEVCFG1_FSOSCEN_OFF (0 << 5)
21.106 -#define DEVCFG1_FSOSCEN_ON (1 << 5)
21.107 -
21.108 -#define DEVCFG1_FNOSC_FRC (0b000)
21.109 -#define DEVCFG1_FNOSC_FRCDIV_PLL (0b001)
21.110 -#define DEVCFG1_FNOSC_FRCDIV (0b111)
21.111 -
21.112 -#define DEVCFG2_UNUSED 0xfff8ff88 /* exclude UPLLEN, UPLLIDIV */
21.113 -
21.114 -#define DEVCFG2_FPLLODIV_1 (0b000 << 16)
21.115 -#define DEVCFG2_FPLLODIV_2 (0b001 << 16)
21.116 -#define DEVCFG2_FPLLODIV_4 (0b010 << 16)
21.117 -#define DEVCFG2_FPLLODIV_8 (0b011 << 16)
21.118 -#define DEVCFG2_FPLLODIV_16 (0b100 << 16)
21.119 -#define DEVCFG2_FPLLODIV_32 (0b101 << 16)
21.120 -#define DEVCFG2_FPLLODIV_64 (0b110 << 16)
21.121 -#define DEVCFG2_FPLLODIV_128 (0b111 << 16)
21.122 -
21.123 -#define DEVCFG2_FPLLMUL_15 (0b000 << 4)
21.124 -#define DEVCFG2_FPLLMUL_16 (0b001 << 4)
21.125 -#define DEVCFG2_FPLLMUL_17 (0b010 << 4)
21.126 -#define DEVCFG2_FPLLMUL_18 (0b011 << 4)
21.127 -#define DEVCFG2_FPLLMUL_19 (0b100 << 4)
21.128 -#define DEVCFG2_FPLLMUL_20 (0b101 << 4)
21.129 -#define DEVCFG2_FPLLMUL_21 (0b110 << 4)
21.130 -#define DEVCFG2_FPLLMUL_24 (0b111 << 4)
21.131 -
21.132 -#define DEVCFG2_FPLLIDIV_1 (0b000)
21.133 -#define DEVCFG2_FPLLIDIV_2 (0b001)
21.134 -#define DEVCFG2_FPLLIDIV_3 (0b010)
21.135 -#define DEVCFG2_FPLLIDIV_4 (0b011)
21.136 -#define DEVCFG2_FPLLIDIV_5 (0b100)
21.137 -#define DEVCFG2_FPLLIDIV_6 (0b101)
21.138 -#define DEVCFG2_FPLLIDIV_10 (0b110)
21.139 -#define DEVCFG2_FPLLIDIV_12 (0b111)
21.140 -
21.141 -/* DMA conveniences. */
21.142 -
21.143 -#define DMACON 0xBF883000
21.144 -#define DCH0CON 0xBF883060
21.145 -#define DCH1CON 0xBF883120
21.146 -#define DCH2CON 0xBF8831E0
21.147 -#define DCH3CON 0xBF8832A0
21.148 -
21.149 -#define DCHMIN 0
21.150 -#define DCHMAX 3
21.151 -#define DCHBASE DCH0CON
21.152 -#define DCHSTEP (DCH1CON - DCH0CON)
21.153 -
21.154 -#define DCHxCON 0x00
21.155 -#define DCHxECON 0x10
21.156 -#define DCHxINT 0x20
21.157 -#define DCHxSSA 0x30
21.158 -#define DCHxDSA 0x40
21.159 -#define DCHxSSIZ 0x50
21.160 -#define DCHxDSIZ 0x60
21.161 -#define DCHxSPTR 0x70
21.162 -#define DCHxDPTR 0x80
21.163 -#define DCHxCSIZ 0x90
21.164 -#define DCHxCPTR 0xA0
21.165 -#define DCHxDAT 0xB0
21.166 -
21.167 -#define DMAIEC IEC1
21.168 -
21.169 -#define DCHxIE 1
21.170 -
21.171 -#define DMAIFS IFS1
21.172 -
21.173 -#define DCHxIF 1
21.174 -
21.175 -#define DMAINTBASE 28
21.176 -
21.177 -#define DMAIPC IPC10
21.178 -#define DCHIPCBASE 0
21.179 -#define DCHIPCSTEP 8
21.180 -
21.181 -/* External interrupt conveniences. */
21.182 -
21.183 -#define INTMIN 0
21.184 -#define INTMAX 4
21.185 -
21.186 -#define INTIEC IEC0
21.187 -
21.188 -#define INTxIE 1
21.189 -
21.190 -#define INTIFS IFS0
21.191 -
21.192 -#define INTxIF 1
21.193 -
21.194 -#define INTINTBASE 3
21.195 -#define INTINTSTEP 5
21.196 -
21.197 -#define INT0IPC IPC0
21.198 -#define INT1IPC IPC1
21.199 -#define INT2IPC IPC2
21.200 -#define INT3IPC IPC3
21.201 -#define INT4IPC IPC4
21.202 -#define INTIPCBASE 24
21.203 -
21.204 -/* Output compare conveniences. */
21.205 -
21.206 -#define OC1CON 0xBF803000
21.207 -#define OC2CON 0xBF803200
21.208 -#define OC3CON 0xBF803400
21.209 -#define OC4CON 0xBF803600
21.210 -#define OC5CON 0xBF803800
21.211 -
21.212 -#define OCMIN 1
21.213 -#define OCMAX 5
21.214 -#define OCBASE OC1CON
21.215 -#define OCSTEP (OC2CON - OC1CON)
21.216 -
21.217 -#define OCxCON 0x00
21.218 -#define OCxR 0x10
21.219 -#define OCxRS 0x20
21.220 -
21.221 -#define OCIEC IEC0
21.222 -
21.223 -#define OCxIE 1
21.224 -
21.225 -#define OCIFS IFS0
21.226 -
21.227 -#define OCxIF 1
21.228 -
21.229 -#define OCINTBASE 7
21.230 -#define OCINTSTEP 5
21.231 -
21.232 -#define OC1IPC IPC1
21.233 -#define OC2IPC IPC2
21.234 -#define OC3IPC IPC3
21.235 -#define OC4IPC IPC4
21.236 -#define OC5IPC IPC5
21.237 -#define OCIPCBASE 16
21.238 -
21.239 -/* Parallel mode conveniences. */
21.240 -
21.241 -#define PMCON 0xBF807000
21.242 -
21.243 -#define PMxCON 0x00
21.244 -#define PMxMODE 0x10
21.245 -#define PMxADDR 0x20
21.246 -#define PMxDOUT 0x30
21.247 -#define PMxDIN 0x40
21.248 -#define PMxAEN 0x50
21.249 -#define PMxSTAT 0x60
21.250 -
21.251 -#define PMMIN 0
21.252 -#define PMMAX 0
21.253 -#define PMBASE PMCON
21.254 -#define PMSTEP 0
21.255 -
21.256 -#define PMIEC IEC1
21.257 -
21.258 -#define PMxIE 1
21.259 -#define PMxEIE 2
21.260 -
21.261 -#define PMIFS IFS1
21.262 -
21.263 -#define PMxIF 1
21.264 -#define PMxEIF 2
21.265 -
21.266 -#define PMINTBASE 16
21.267 -#define PMINTSTEP 0
21.268 -
21.269 -#define PMIPC IPC8
21.270 -#define PMIPCBASE 24
21.271 -
21.272 -/* Timer conveniences. */
21.273 -
21.274 -#define T1CON 0xBF800600
21.275 -#define T2CON 0xBF800800
21.276 -#define T3CON 0xBF800A00
21.277 -#define T4CON 0xBF800C00
21.278 -#define T5CON 0xBF800E00
21.279 -
21.280 -#define TIMERMIN 1
21.281 -#define TIMERMAX 5
21.282 -#define TIMERBASE T1CON
21.283 -#define TIMERSTEP (T2CON - T1CON)
21.284 -
21.285 -#define TxCON 0x00
21.286 -#define TMRx 0x10
21.287 -#define PRx 0x20
21.288 -
21.289 -#define TIMERIEC IEC0
21.290 -
21.291 -#define TxIE 1
21.292 -
21.293 -#define TIMERIFS IEC0
21.294 -
21.295 -#define TxIF 1
21.296 -
21.297 -#define TIMERINTBASE 4
21.298 -#define TIMERINTSTEP 5
21.299 -
21.300 -#define TIMER1IPC IPC1
21.301 -#define TIMER2IPC IPC2
21.302 -#define TIMER3IPC IPC3
21.303 -#define TIMER4IPC IPC4
21.304 -#define TIMER5IPC IPC5
21.305 -#define TIMERIPCBASE 0
21.306 -
21.307 -/* UART conveniences. */
21.308 -
21.309 -#define U1MODE 0xBF806000
21.310 -#define U2MODE 0xBF806200
21.311 -
21.312 -#define UARTMIN 1
21.313 -#define UARTMAX 2
21.314 -#define UARTBASE U1MODE
21.315 -#define UARTSTEP (U2MODE - U1MODE)
21.316 -
21.317 -#define UxMODE 0x00
21.318 -#define UxSTA 0x10
21.319 -#define UxTXREG 0x20
21.320 -#define UxRXREG 0x30
21.321 -#define UxBRG 0x40
21.322 -
21.323 -#define UARTIEC IEC1
21.324 -
21.325 -#define UxEIE 1
21.326 -#define UxRIE 2
21.327 -#define UxTIE 4
21.328 -
21.329 -#define UARTIFS IFS1
21.330 -
21.331 -#define UxEIF 1
21.332 -#define UxRIF 2
21.333 -#define UxTIF 4
21.334 -
21.335 -#define UARTINTBASE 7
21.336 -#define UARTINTSTEP 14
21.337 -
21.338 -#define UART1IPC IPC8
21.339 -#define UART1IPCBASE 0
21.340 -#define UART2IPC IPC9
21.341 -#define UART2IPCBASE 8
21.342 -
21.343 -/* Interrupt numbers.
21.344 - * See...
21.345 - * TABLE 7-1: INTERRUPT IRQ, VECTOR AND BIT LOCATION
21.346 - * PIC32MX1XX/2XX 28/36/44-pin Family Data Sheet
21.347 - */
21.348 -
21.349 -#define DMA0 60
21.350 -#define DMA1 61
21.351 -#define DMA2 62
21.352 -#define DMA3 63
21.353 -#define INT0 3
21.354 -#define INT1 8
21.355 -#define INT2 13
21.356 -#define INT3 18
21.357 -#define INT4 23
21.358 -#define OC1 7
21.359 -#define OC2 12
21.360 -#define OC3 17
21.361 -#define OC4 22
21.362 -#define OC5 27
21.363 -#define PMP 48
21.364 -#define PMPE 49
21.365 -#define T1 4
21.366 -#define T2 9
21.367 -#define T3 14
21.368 -#define T4 19
21.369 -#define T5 24
21.370 -#define U1RX 40
21.371 -#define U1TX 41
21.372 -#define U2RX 54
21.373 -#define U2TX 55
21.374 -
21.375 -/* Address modifiers.
21.376 - * See...
21.377 - * 11.2 CLR, SET and INV Registers
21.378 - * PIC32MX1XX/2XX 28/36/44-pin Family Data Sheet
21.379 - */
21.380 -
21.381 -#define CLR 0x4
21.382 -#define SET 0x8
21.383 -#define INV 0xC
21.384 -
21.385 -#endif /* __PIC32_H__ */
22.1 --- a/pic32_c.h Mon Oct 22 19:12:33 2018 +0200
22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
22.3 @@ -1,110 +0,0 @@
22.4 -/*
22.5 - * PIC32 peripheral access utilities.
22.6 - *
22.7 - * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
22.8 - *
22.9 - * This program is free software: you can redistribute it and/or modify
22.10 - * it under the terms of the GNU General Public License as published by
22.11 - * the Free Software Foundation, either version 3 of the License, or
22.12 - * (at your option) any later version.
22.13 - *
22.14 - * This program is distributed in the hope that it will be useful,
22.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
22.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22.17 - * GNU General Public License for more details.
22.18 - *
22.19 - * You should have received a copy of the GNU General Public License
22.20 - * along with this program. If not, see <http://www.gnu.org/licenses/>.
22.21 - */
22.22 -
22.23 -#ifndef __ASSEMBLER__
22.24 -
22.25 -#ifndef __PIC32_C_H__
22.26 -#define __PIC32_C_H__
22.27 -
22.28 -#include <stdint.h>
22.29 -#include "mips.h"
22.30 -#include "pic32.h"
22.31 -
22.32 -
22.33 -
22.34 -/* Access. */
22.35 -
22.36 -#define REG(mem) *((volatile uint32_t *) (mem))
22.37 -
22.38 -
22.39 -
22.40 -/* Bit clearing, setting and inverting. */
22.41 -
22.42 -static inline void CLR_REG(uint32_t mem, uint32_t val)
22.43 -{
22.44 - REG(mem + CLR) = val;
22.45 -}
22.46 -
22.47 -static inline void SET_REG(uint32_t mem, uint32_t val)
22.48 -{
22.49 - REG(mem + SET) = val;
22.50 -}
22.51 -
22.52 -static inline void INV_REG(uint32_t mem, uint32_t val)
22.53 -{
22.54 - REG(mem + INV) = val;
22.55 -}
22.56 -
22.57 -
22.58 -
22.59 -/* Address translation. */
22.60 -
22.61 -static inline uint32_t PHYSICAL(uint32_t addr)
22.62 -{
22.63 - return ((uint32_t) addr) - KSEG0_BASE;
22.64 -}
22.65 -
22.66 -static inline uint32_t HW_PHYSICAL(uint32_t addr)
22.67 -{
22.68 - return ((uint32_t) addr) - KSEG1_BASE;
22.69 -}
22.70 -
22.71 -
22.72 -
22.73 -/* Register collection access. */
22.74 -
22.75 -static inline uint32_t DMA_REG(int channel, uint32_t reg)
22.76 -{
22.77 - return DCHBASE + reg + (channel - DCHMIN) * DCHSTEP;
22.78 -}
22.79 -
22.80 -static inline uint32_t OC_REG(int unit, uint32_t reg)
22.81 -{
22.82 - return OCBASE + reg + (unit - OCMIN) * OCSTEP;
22.83 -}
22.84 -
22.85 -static inline uint32_t PM_REG(int port, uint32_t reg)
22.86 -{
22.87 - return PMBASE + reg + (port - PMMIN) * PMSTEP;
22.88 -}
22.89 -
22.90 -static inline uint32_t TIMER_REG(int timer, uint32_t reg)
22.91 -{
22.92 - return TIMERBASE + reg + (timer - TIMERMIN) * TIMERSTEP;
22.93 -}
22.94 -
22.95 -static inline uint32_t UART_REG(int uart, uint32_t reg)
22.96 -{
22.97 - return UARTBASE + reg + (uart - UARTMIN) * UARTSTEP;
22.98 -}
22.99 -
22.100 -
22.101 -
22.102 -/* Convenience types. */
22.103 -
22.104 -enum dma_chain
22.105 -{
22.106 - dma_chain_none,
22.107 - dma_chain_next,
22.108 - dma_chain_previous,
22.109 -};
22.110 -
22.111 -#endif /* __PIC32_C_H__ */
22.112 -
22.113 -#endif /* __ASSEMBLER__ */
23.1 --- a/start.S Mon Oct 22 19:12:33 2018 +0200
23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
23.3 @@ -1,83 +0,0 @@
23.4 -/*
23.5 - * PIC32 microcontroller initialisation code.
23.6 - *
23.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
23.8 - *
23.9 - * This program is free software: you can redistribute it and/or modify
23.10 - * it under the terms of the GNU General Public License as published by
23.11 - * the Free Software Foundation, either version 3 of the License, or
23.12 - * (at your option) any later version.
23.13 - *
23.14 - * This program is distributed in the hope that it will be useful,
23.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
23.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23.17 - * GNU General Public License for more details.
23.18 - *
23.19 - * You should have received a copy of the GNU General Public License
23.20 - * along with this program. If not, see <http://www.gnu.org/licenses/>.
23.21 - */
23.22 -
23.23 -#include "mips.h"
23.24 -#include "pic32.h"
23.25 -
23.26 -/* Application-specific configuration. */
23.27 -
23.28 -#include "devconfig.h"
23.29 -
23.30 -/* Disable JTAG functionality on pins. */
23.31 -
23.32 -.section .devcfg0, "a"
23.33 -.word 0xfffffffb /* DEVCFG0<2> = JTAGEN = 0 */
23.34 -
23.35 -/* Select oscillator, pin usage, watchdog timer and peripheral clock divider. */
23.36 -
23.37 -.section .devcfg1, "a"
23.38 -.word (DEVCFG1_UNUSED | DEVCFG1_CONFIG)
23.39 -
23.40 -/* Set clock dividers and multiplier. */
23.41 -
23.42 -.section .devcfg2, "a"
23.43 -.word (DEVCFG2_UNUSED | DEVCFG2_CONFIG)
23.44 -
23.45 -/* The start routine is placed at the boot location. */
23.46 -
23.47 -.section .boot, "a"
23.48 -
23.49 -.globl _start
23.50 -.extern main
23.51 -
23.52 -_start:
23.53 - /* Enable caching. */
23.54 -
23.55 - mfc0 $v1, CP0_CONFIG
23.56 - li $t8, ~CONFIG_K0
23.57 - and $v1, $v1, $t8
23.58 - ori $v1, $v1, CONFIG_K0_CACHABLE_NONCOHERENT
23.59 - mtc0 $v1, CP0_CONFIG
23.60 - nop
23.61 -
23.62 - /* Get the RAM size. */
23.63 -
23.64 - la $v1, BMXDRMSZ
23.65 - lw $t0, 0($v1)
23.66 -
23.67 - /* Initialise the stack pointer. */
23.68 -
23.69 - li $v1, KSEG0_BASE
23.70 - addu $sp, $t0, $v1 /* sp = KSEG0_BASE + RAM size */
23.71 -
23.72 - /* Initialise the globals pointer. */
23.73 -
23.74 - lui $gp, %hi(_GLOBAL_OFFSET_TABLE_)
23.75 - ori $gp, $gp, %lo(_GLOBAL_OFFSET_TABLE_)
23.76 -
23.77 - /*
23.78 - Jump to the main program. Since the boot code is separate from the
23.79 - other code, the address cannot be obtained via the GOT.
23.80 - ("relocation truncated to fit: R_MIPS_PC16 against `main'")
23.81 - */
23.82 -
23.83 - lui $t9, %hi(main)
23.84 - ori $t9, $t9, %lo(main)
23.85 - jr $t9
23.86 - nop