1.1 --- a/Makefile Sat Oct 20 19:19:30 2018 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,75 +0,0 @@
1.4 -# Makefile - Build the PIC32 deployment payload
1.5 -#
1.6 -# Copyright (C) 2015, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
1.7 -# Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>
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 -ARCH = mipsel-linux-gnu
1.23 -CC = $(ARCH)-gcc
1.24 -LD = $(ARCH)-ld
1.25 -NM = $(ARCH)-nm
1.26 -OBJCOPY=$(ARCH)-objcopy
1.27 -OBJDUMP=$(ARCH)-objdump
1.28 -
1.29 -# NOTE: -O2 is actually needed to prevent memcpy references, whereas probably
1.30 -# NOTE: one of the -f{freestanding, no-hosted, no-builtin} options should work.
1.31 -# NOTE: See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56888
1.32 -
1.33 -CFLAGS = -O2 -Wall \
1.34 - -fno-unit-at-a-time -fno-zero-initialized-in-bss \
1.35 - -ffreestanding -fno-hosted -fno-builtin \
1.36 - -march=mips32
1.37 -LDFLAGS = -nostdlib -EL
1.38 -
1.39 -TARGET = payload.elf
1.40 -DUMP = $(TARGET:.elf=.dump)
1.41 -MAP = $(TARGET:.elf=.map)
1.42 -SCRIPT = $(TARGET:.elf=.ld)
1.43 -
1.44 -HEX = $(TARGET:.elf=.hex)
1.45 -SREC = $(TARGET:.elf=.srec)
1.46 -
1.47 -# Ordering of objects is important and cannot be left to replacement rules.
1.48 -
1.49 -SRC = start.S main.c init.c debug.c cpu.S
1.50 -OBJ = start.o main.o init.o debug.o cpu.o
1.51 -
1.52 -.PHONY: all clean distclean
1.53 -
1.54 -all: $(HEX) $(SREC)
1.55 -
1.56 -clean:
1.57 - rm -f $(OBJ) $(TARGET) $(HEX) $(SREC) $(DUMP) *.map
1.58 -
1.59 -distclean: clean
1.60 - echo "Nothing else to clean."
1.61 -
1.62 -$(HEX): $(TARGET)
1.63 - $(OBJCOPY) -O ihex $(TARGET) $(HEX)
1.64 -
1.65 -$(SREC): $(TARGET)
1.66 - $(OBJCOPY) -O srec $(TARGET) $(SREC)
1.67 -
1.68 -$(TARGET): $(OBJ)
1.69 - $(LD) $(LDFLAGS) -T $(SCRIPT) $(OBJ) -o $@
1.70 - $(OBJDUMP) -D $(TARGET) > $(DUMP)
1.71 - $(OBJDUMP) -h $(TARGET) > $(MAP)
1.72 - $(NM) -n $(TARGET) > System.map
1.73 -
1.74 -.c.o:
1.75 - $(CC) -c $(CFLAGS) $< -o $@
1.76 -
1.77 -.S.o:
1.78 - $(CC) -c $(CFLAGS) $< -o $@
2.1 --- a/debug.c Sat Oct 20 19:19:30 2018 +0200
2.2 +++ b/debug.c Sat Oct 20 19:24:34 2018 +0200
2.3 @@ -20,14 +20,21 @@
2.4 #include "pic32_c.h"
2.5 #include "debug.h"
2.6
2.7 +/* Register output functions using UART1. */
2.8 +
2.9 +void rbits(uint32_t reg)
2.10 +{
2.11 + bits(REG(reg), 4);
2.12 +}
2.13 +
2.14 +void rhex(uint32_t reg)
2.15 +{
2.16 + hex(REG(reg), 4);
2.17 +}
2.18 +
2.19 /* Value output functions using UART1. */
2.20
2.21 -void bits(uint32_t reg)
2.22 -{
2.23 - vbits(REG(reg));
2.24 -}
2.25 -
2.26 -void vbits(uint32_t val)
2.27 +void bits(uint32_t val, int bytes)
2.28 {
2.29 uint32_t mask;
2.30
2.31 @@ -36,17 +43,14 @@
2.32 uart_write('1');
2.33 else
2.34 uart_write('0');
2.35 -
2.36 - uart_write('\r');
2.37 - uart_write('\n');
2.38 }
2.39
2.40 -void vhex(uint32_t val)
2.41 +void hex(uint32_t val, int bytes)
2.42 {
2.43 uint32_t mask;
2.44 - uint8_t digit, shift;
2.45 + uint8_t digit, shift, start = bytes * 8 - 4;
2.46
2.47 - for (mask = (0b1111 << 28), shift = 28; mask; mask >>= 4, shift -= 4)
2.48 + for (mask = (0b1111 << start), shift = start; mask; mask >>= 4, shift -= 4)
2.49 {
2.50 digit = (val & mask) >> shift;
2.51 if (digit > 9)
2.52 @@ -54,9 +58,6 @@
2.53 else
2.54 uart_write('0' + digit);
2.55 }
2.56 -
2.57 - uart_write('\r');
2.58 - uart_write('\n');
2.59 }
2.60
2.61
2.62 @@ -94,6 +95,12 @@
2.63 uart_write_char(1, c);
2.64 }
2.65
2.66 +void uart_write_nl(void)
2.67 +{
2.68 + uart_write('\r');
2.69 + uart_write('\n');
2.70 +}
2.71 +
2.72 void uart_write_string(const char *s)
2.73 {
2.74 while (*s)
3.1 --- a/debug.h Sat Oct 20 19:19:30 2018 +0200
3.2 +++ b/debug.h Sat Oct 20 19:24:34 2018 +0200
3.3 @@ -20,11 +20,15 @@
3.4 #ifndef __DEBUG_H__
3.5 #define __DEBUG_H__
3.6
3.7 +/* Register output functions using UART1. */
3.8 +
3.9 +void rbits(uint32_t reg);
3.10 +void rhex(uint32_t reg);
3.11 +
3.12 /* Value output functions using UART1. */
3.13
3.14 -void bits(uint32_t reg);
3.15 -void vbits(uint32_t val);
3.16 -void vhex(uint32_t val);
3.17 +void bits(uint32_t val, int bytes);
3.18 +void hex(uint32_t val, int bytes);
3.19
3.20 /* General input/output functions. */
3.21
3.22 @@ -36,6 +40,7 @@
3.23 /* Functions using UART1. */
3.24
3.25 void uart_write(char c);
3.26 +void uart_write_nl(void);
3.27 void uart_write_string(const char *s);
3.28
3.29 #endif /* __DEBUG_H__ */
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/examples/demo/Makefile Sat Oct 20 19:24:34 2018 +0200
4.3 @@ -0,0 +1,33 @@
4.4 +# Makefile - Build the PIC32 deployment payload
4.5 +#
4.6 +# Copyright (C) 2015, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
4.7 +# Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>
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 +include ../../mk/common.mk
4.23 +
4.24 +TARGET = demo.elf
4.25 +DUMP = $(TARGET:.elf=.dump)
4.26 +MAP = $(TARGET:.elf=.map)
4.27 +
4.28 +HEX = $(TARGET:.elf=.hex)
4.29 +SREC = $(TARGET:.elf=.srec)
4.30 +
4.31 +# Ordering of objects is important and cannot be left to replacement rules.
4.32 +
4.33 +SRC = $(START_SRC) main.c $(COMMON_SRC)
4.34 +OBJ = $(START_OBJ) main.o $(COMMON_OBJ)
4.35 +
4.36 +include ../../mk/rules.mk
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/examples/demo/main.c Sat Oct 20 19:24:34 2018 +0200
5.3 @@ -0,0 +1,197 @@
5.4 +/*
5.5 + * A demonstration of various PIC32 peripherals.
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 +
5.24 +#include "pic32_c.h"
5.25 +#include "init.h"
5.26 +#include "debug.h"
5.27 +#include "main.h"
5.28 +
5.29 +static const char message1[] = "Hello!\r\n";
5.30 +static const char message2[] = "Again!\r\n";
5.31 +static int uart_echo;
5.32 +
5.33 +
5.34 +
5.35 +/* Blink an attached LED with delays implemented using a loop. */
5.36 +
5.37 +static void blink(uint32_t delay, uint32_t port, uint32_t pins)
5.38 +{
5.39 + uint32_t counter;
5.40 +
5.41 + /* Clear outputs (LED). */
5.42 +
5.43 + CLR_REG(port, pins);
5.44 +
5.45 + while (1)
5.46 + {
5.47 + counter = delay;
5.48 +
5.49 + while (counter--) __asm__(""); /* retain loop */
5.50 +
5.51 + /* Invert outputs (LED). */
5.52 +
5.53 + INV_REG(port, pins);
5.54 + }
5.55 +}
5.56 +
5.57 +
5.58 +
5.59 +/* Main program. */
5.60 +
5.61 +void main(void)
5.62 +{
5.63 + uart_echo = 0;
5.64 +
5.65 + init_memory();
5.66 + init_pins();
5.67 + init_outputs();
5.68 +
5.69 + unlock_config();
5.70 + config_uart();
5.71 + lock_config();
5.72 +
5.73 + init_dma();
5.74 +
5.75 + /* Initiate DMA on the Timer2 interrupt. Since the channel is not
5.76 + auto-enabled, it must be explicitly enabled elsewhere (when a UART
5.77 + interrupt is handled). */
5.78 +
5.79 + dma_init(0, 3);
5.80 + dma_set_interrupt(0, T2, 1);
5.81 + dma_set_transfer(0, PHYSICAL((uint32_t) message1), sizeof(message1) - 1,
5.82 + HW_PHYSICAL(UART_REG(1, UxTXREG)), 1,
5.83 + 1);
5.84 +
5.85 + /* Enable DMA on the preceding channel's completion, with OC1 initiating
5.86 + transfers, raising a transfer completion interrupt to be handled. */
5.87 +
5.88 + dma_init(1, 3);
5.89 + dma_set_chaining(1, dma_chain_previous);
5.90 + dma_set_interrupt(1, OC1, 1);
5.91 + dma_set_transfer(1, PHYSICAL((uint32_t) message2), sizeof(message2) - 1,
5.92 + HW_PHYSICAL(UART_REG(1, UxTXREG)), 1,
5.93 + 1);
5.94 + dma_init_interrupt(1, 0b00001000, 7, 3);
5.95 +
5.96 + /* Configure a timer for the first DMA channel whose interrupt condition
5.97 + drives the transfer but is not handled (having a lower priority than the
5.98 + CPU. */
5.99 +
5.100 + timer_init(2, 0b111, 60000);
5.101 + timer_init_interrupt(2, 1, 3);
5.102 + timer_on(2);
5.103 +
5.104 + /* Configure a timer for the output compare unit below. */
5.105 +
5.106 + timer_init(3, 0b111, 20000);
5.107 + timer_on(3);
5.108 +
5.109 + /* Configure output compare in dual compare (continuous output) mode using
5.110 + Timer3 as time base. The interrupt condition drives the second DMA
5.111 + channel but is not handled (having a lower priority than the CPU). */
5.112 +
5.113 + oc_init(1, 0b101, 3);
5.114 + oc_set_pulse(1, 10000);
5.115 + oc_set_pulse_end(1, 20000);
5.116 + oc_init_interrupt(1, 1, 3);
5.117 + oc_on(1);
5.118 +
5.119 + /* Set UART interrupt priority above CPU priority to process events and to
5.120 + enable the first DMA channel. */
5.121 +
5.122 + uart_init(1, 115200);
5.123 + uart_init_interrupt(1, UxRIF, 7, 3);
5.124 + uart_on(1);
5.125 +
5.126 + interrupts_on();
5.127 +
5.128 + blink(3 << 24, PORTA, 1 << 3);
5.129 +}
5.130 +
5.131 +
5.132 +
5.133 +/* Exception and interrupt handlers. */
5.134 +
5.135 +void exception_handler(void)
5.136 +{
5.137 + blink(3 << 12, PORTA, 1 << 3);
5.138 +}
5.139 +
5.140 +void interrupt_handler(void)
5.141 +{
5.142 + uint32_t ifs;
5.143 + char val;
5.144 +
5.145 + /* Check for a UART receive interrupt condition (UxRIF). */
5.146 +
5.147 + ifs = REG(UARTIFS) & UART_INT_FLAGS(1, UxRIF);
5.148 +
5.149 + if (ifs)
5.150 + {
5.151 + /* Clear the UART interrupt condition. */
5.152 +
5.153 + CLR_REG(UARTIFS, ifs);
5.154 +
5.155 + /* Write the received data back. */
5.156 +
5.157 + while (uart_can_read(1))
5.158 + {
5.159 + val = uart_read_char(1);
5.160 + if (uart_echo)
5.161 + uart_write_char(1, val);
5.162 +
5.163 + /* Initiate transfer upon receiving a particular character. */
5.164 +
5.165 + if (val == '0')
5.166 + dma_on(0);
5.167 + }
5.168 + }
5.169 +
5.170 + /* Check for a DMA interrupt condition (CHBCIF). */
5.171 +
5.172 + ifs = REG(DMAIFS) & DMA_INT_FLAGS(1, DCHxIF);
5.173 +
5.174 + if (ifs)
5.175 + {
5.176 + uart_write_string("CHBCIF\r\n");
5.177 + INV_REG(PORTA, 1 << 2);
5.178 + CLR_REG(DMA_REG(1, DCHxINT), 0b11111111);
5.179 + CLR_REG(DMAIFS, ifs);
5.180 + }
5.181 +}
5.182 +
5.183 +
5.184 +
5.185 +/* Peripheral pin configuration. */
5.186 +
5.187 +void config_uart(void)
5.188 +{
5.189 + /* Map U1RX to RPB13. */
5.190 +
5.191 + REG(U1RXR) = 0b0011; /* U1RXR<3:0> = 0011 (RPB13) */
5.192 +
5.193 + /* Map U1TX to RPB15. */
5.194 +
5.195 + REG(RPB15R) = 0b0001; /* RPB15R<3:0> = 0001 (U1TX) */
5.196 +
5.197 + /* Set RPB13 to input. */
5.198 +
5.199 + SET_REG(TRISB, 1 << 13);
5.200 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/examples/demo/main.h Sat Oct 20 19:24:34 2018 +0200
6.3 @@ -0,0 +1,27 @@
6.4 +/*
6.5 + * A demonstration of various PIC32 peripherals.
6.6 + *
6.7 + * Copyright (C) 2017, 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 __MAIN_H__
6.24 +#define __MAIN_H__
6.25 +
6.26 +/* Peripheral pin configuration. */
6.27 +
6.28 +void config_uart(void);
6.29 +
6.30 +#endif /* __MAIN_H__ */
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/examples/vga/Makefile Sat Oct 20 19:24:34 2018 +0200
7.3 @@ -0,0 +1,33 @@
7.4 +# Makefile - Build the PIC32 deployment payload
7.5 +#
7.6 +# Copyright (C) 2015, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
7.7 +# Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>
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 +include ../../mk/common.mk
7.23 +
7.24 +TARGET = vga.elf
7.25 +DUMP = $(TARGET:.elf=.dump)
7.26 +MAP = $(TARGET:.elf=.map)
7.27 +
7.28 +HEX = $(TARGET:.elf=.hex)
7.29 +SREC = $(TARGET:.elf=.srec)
7.30 +
7.31 +# Ordering of objects is important and cannot be left to replacement rules.
7.32 +
7.33 +SRC = $(START_SRC) main.c $(COMMON_SRC)
7.34 +OBJ = $(START_OBJ) main.o $(COMMON_OBJ)
7.35 +
7.36 +include ../../mk/rules.mk
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/examples/vga/main.c Sat Oct 20 19:24:34 2018 +0200
8.3 @@ -0,0 +1,297 @@
8.4 +/*
8.5 + * Generate a VGA signal using a PIC32 microcontroller.
8.6 + *
8.7 + * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
8.8 + *
8.9 + * This program is free software: you can redistribute it and/or modify
8.10 + * it under the terms of the GNU General Public License as published by
8.11 + * the Free Software Foundation, either version 3 of the License, or
8.12 + * (at your option) any later version.
8.13 + *
8.14 + * This program is distributed in the hope that it will be useful,
8.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.17 + * GNU General Public License for more details.
8.18 + *
8.19 + * You should have received a copy of the GNU General Public License
8.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
8.21 + */
8.22 +
8.23 +
8.24 +#include "pic32_c.h"
8.25 +#include "init.h"
8.26 +#include "debug.h"
8.27 +#include "main.h"
8.28 +#include "vga.h"
8.29 +
8.30 +
8.31 +
8.32 +/* Display state. */
8.33 +
8.34 +static void (*state_handler)(void);
8.35 +static uint32_t line;
8.36 +
8.37 +/* Pixel data. */
8.38 +
8.39 +static uint8_t linedata[LINE_LENGTH];
8.40 +static const uint8_t zerodata[ZERO_LENGTH] = {0};
8.41 +
8.42 +
8.43 +
8.44 +static void test_linedata(void)
8.45 +{
8.46 + int i;
8.47 +
8.48 + for (i = 0; i < LINE_LENGTH; i++)
8.49 + linedata[i] = (i % 2) ? 0xff : 0x00;
8.50 +}
8.51 +
8.52 +/* Blink an attached LED with delays implemented using a loop. */
8.53 +
8.54 +static void blink(uint32_t delay, uint32_t port, uint32_t pins)
8.55 +{
8.56 + uint32_t counter;
8.57 + int i;
8.58 +
8.59 + /* Clear outputs (LED). */
8.60 +
8.61 + CLR_REG(port, pins);
8.62 +
8.63 + while (1)
8.64 + {
8.65 + counter = delay;
8.66 +
8.67 + while (counter--) __asm__(""); /* retain loop */
8.68 +
8.69 + /* Invert outputs (LED). */
8.70 +
8.71 + INV_REG(port, pins);
8.72 + for (i = 0; i < LINE_LENGTH; i++)
8.73 + hex(linedata[i], 1);
8.74 + uart_write_nl();
8.75 + }
8.76 +}
8.77 +
8.78 +
8.79 +
8.80 +/* Main program. */
8.81 +
8.82 +void main(void)
8.83 +{
8.84 + line = 0;
8.85 + state_handler = vbp_active;
8.86 + test_linedata();
8.87 +
8.88 + init_memory();
8.89 + init_pins();
8.90 + init_outputs();
8.91 +
8.92 + unlock_config();
8.93 + config_oc();
8.94 + config_uart();
8.95 + lock_config();
8.96 +
8.97 + init_dma();
8.98 +
8.99 + /* Initiate DMA on the Timer2 interrupt transferring line data to the first
8.100 + byte of PORTB. Do not enable the channel for initiation until the visible
8.101 + region is about to start. */
8.102 +
8.103 + dma_init(0, 3);
8.104 + dma_set_auto_enable(0, 1);
8.105 + dma_set_interrupt(0, T2, 1);
8.106 + dma_set_transfer(0, PHYSICAL((uint32_t) linedata), LINE_LENGTH,
8.107 + HW_PHYSICAL(PORTB), 1,
8.108 + LINE_LENGTH);
8.109 + dma_init_interrupt(0, 0b00001000, 1, 3);
8.110 +
8.111 + /* Enable DMA on the preceding channel's completion, with this also
8.112 + initiating transfers. */
8.113 +
8.114 + dma_init(1, 3);
8.115 + dma_set_chaining(1, dma_chain_previous);
8.116 + dma_set_interrupt(1, DMA0, 1);
8.117 + dma_set_transfer(1, PHYSICAL((uint32_t) zerodata), ZERO_LENGTH,
8.118 + HW_PHYSICAL(PORTB), 1,
8.119 + ZERO_LENGTH);
8.120 + dma_set_receive_events(1, 1);
8.121 +
8.122 + /* Configure a timer for the horizontal sync. The timer has no prescaling
8.123 + (0). */
8.124 +
8.125 + timer_init(2, 0, HFREQ_LIMIT);
8.126 + timer_on(2);
8.127 +
8.128 + /* Horizontal sync. */
8.129 +
8.130 + /* Configure output compare in dual compare (continuous output) mode using
8.131 + Timer2 as time base. The interrupt condition drives the first DMA channel
8.132 + but is not handled (having a lower priority than the CPU). */
8.133 +
8.134 + oc_init(1, 0b101, 2);
8.135 + oc_set_pulse(1, HSYNC_END);
8.136 + oc_set_pulse_end(1, HSYNC_START);
8.137 + oc_init_interrupt(1, 7, 3);
8.138 + oc_on(1);
8.139 +
8.140 + /* Vertical sync. */
8.141 +
8.142 + /* Configure output compare in single compare (output driven low) mode using
8.143 + Timer2 as time base. The unit is enabled later. It is only really used to
8.144 + achieve precisely-timed level transitions in hardware. */
8.145 +
8.146 + oc_init(2, 0b010, 2);
8.147 + oc_set_pulse(2, 0);
8.148 +
8.149 + uart_init(1, 115200);
8.150 + uart_on(1);
8.151 +
8.152 + interrupts_on();
8.153 +
8.154 + blink(3 << 24, PORTA, 1 << 3);
8.155 +}
8.156 +
8.157 +
8.158 +
8.159 +/* Exception and interrupt handlers. */
8.160 +
8.161 +void exception_handler(void)
8.162 +{
8.163 + blink(3 << 12, PORTA, 1 << 3);
8.164 +}
8.165 +
8.166 +void interrupt_handler(void)
8.167 +{
8.168 + uint32_t ifs;
8.169 +
8.170 + /* Check for a OC1 interrupt condition. */
8.171 +
8.172 + ifs = REG(OCIFS) & OC_INT_FLAGS(1, OCxIF);
8.173 +
8.174 + if (ifs)
8.175 + {
8.176 + line += 1;
8.177 + state_handler();
8.178 + CLR_REG(OCIFS, ifs);
8.179 + }
8.180 +}
8.181 +
8.182 +
8.183 +
8.184 +/* Vertical back porch region. */
8.185 +
8.186 +void vbp_active(void)
8.187 +{
8.188 + if (line < VISIBLE_START)
8.189 + return;
8.190 +
8.191 + /* Enter the visible region. */
8.192 +
8.193 + state_handler = visible_active;
8.194 +
8.195 + /* NOTE: Set the line address. */
8.196 +
8.197 + /* Enable the channel for the next line. */
8.198 +
8.199 + dma_on(0);
8.200 +}
8.201 +
8.202 +/* Visible region. */
8.203 +
8.204 +void visible_active(void)
8.205 +{
8.206 + uint32_t ifs;
8.207 +
8.208 + /* Remove any DMA interrupt condition (CHBCIF). */
8.209 +
8.210 + ifs = REG(DMAIFS) & DMA_INT_FLAGS(0, DCHxIF);
8.211 +
8.212 + if (ifs)
8.213 + {
8.214 + CLR_REG(DMA_REG(0, DCHxINT), 0b11111111);
8.215 + CLR_REG(DMAIFS, ifs);
8.216 + INV_REG(PORTA, 1 << 2);
8.217 + }
8.218 +
8.219 + if (line < VFP_START)
8.220 + {
8.221 + /* NOTE: Update the line address and handle wraparound. */
8.222 +
8.223 + return;
8.224 + }
8.225 +
8.226 + /* End the visible region. */
8.227 +
8.228 + state_handler = vfp_active;
8.229 +
8.230 + /* Disable the channel for the next line. */
8.231 +
8.232 + dma_off(0);
8.233 +}
8.234 +
8.235 +/* Vertical front porch region. */
8.236 +
8.237 +void vfp_active(void)
8.238 +{
8.239 + if (line < VSYNC_START)
8.240 + return;
8.241 +
8.242 + /* Enter the vertical sync region. */
8.243 +
8.244 + state_handler = vsync_active;
8.245 +
8.246 + /* Bring vsync low (single compare, output driven low) when the next line
8.247 + starts. */
8.248 +
8.249 + oc_init(2, 0b010, 2);
8.250 + oc_on(2);
8.251 +}
8.252 +
8.253 +/* Vertical sync region. */
8.254 +
8.255 +void vsync_active(void)
8.256 +{
8.257 + if (line < VSYNC_END)
8.258 + return;
8.259 +
8.260 + /* Start again at the top of the display. */
8.261 +
8.262 + line = 0;
8.263 + state_handler = vbp_active;
8.264 +
8.265 + /* Bring vsync high (single compare, output driven high) when the next line
8.266 + starts. */
8.267 +
8.268 + oc_init(2, 0b001, 2);
8.269 + oc_on(2);
8.270 +}
8.271 +
8.272 +
8.273 +
8.274 +/* Peripheral pin configuration. */
8.275 +
8.276 +void config_oc(void)
8.277 +{
8.278 + /* Map OC1 to RPA0. */
8.279 +
8.280 + REG(RPA0R) = 0b0101; /* RPA0R<3:0> = 0101 (OC1) */
8.281 +
8.282 + /* Map OC2 to RPA1. */
8.283 +
8.284 + REG(RPA1R) = 0b0101; /* RPA1R<3:0> = 0101 (OC2) */
8.285 +}
8.286 +
8.287 +void config_uart(void)
8.288 +{
8.289 + /* Map U1RX to RPB13. */
8.290 +
8.291 + REG(U1RXR) = 0b0011; /* U1RXR<3:0> = 0011 (RPB13) */
8.292 +
8.293 + /* Map U1TX to RPB15. */
8.294 +
8.295 + REG(RPB15R) = 0b0001; /* RPB15R<3:0> = 0001 (U1TX) */
8.296 +
8.297 + /* Set RPB13 to input. */
8.298 +
8.299 + SET_REG(TRISB, 1 << 13);
8.300 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/examples/vga/main.h Sat Oct 20 19:24:34 2018 +0200
9.3 @@ -0,0 +1,35 @@
9.4 +/*
9.5 + * Generate a VGA signal using a PIC32 microcontroller.
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 __MAIN_H__
9.24 +#define __MAIN_H__
9.25 +
9.26 +/* Peripheral pin configuration. */
9.27 +
9.28 +void config_oc(void);
9.29 +void config_uart(void);
9.30 +
9.31 +/* Display state handlers. */
9.32 +
9.33 +void vbp_active(void);
9.34 +void visible_active(void);
9.35 +void vfp_active(void);
9.36 +void vsync_active(void);
9.37 +
9.38 +#endif /* __MAIN_H__ */
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/examples/vga/vga.h Sat Oct 20 19:24:34 2018 +0200
10.3 @@ -0,0 +1,55 @@
10.4 +/*
10.5 + * Generate a VGA signal using a PIC32 microcontroller.
10.6 + *
10.7 + * Copyright (C) 2017, 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 __VGA_H__
10.24 +#define __VGA_H__
10.25 +
10.26 +#define LINE_LENGTH 160 /* pixels */
10.27 +#define LINE_COUNT 256 /* distinct display lines */
10.28 +
10.29 +#define ZERO_LENGTH 1 /* pixels */
10.30 +
10.31 +/* 24MHz cycle measurements. */
10.32 +
10.33 +#define HFREQ_LIMIT 643
10.34 +#define HSYNC_START 460
10.35 +#define HSYNC_LIMIT 64
10.36 +#define HSYNC_END (HSYNC_START + HSYNC_LIMIT)
10.37 +
10.38 +/* Horizontal lines, back porch end. */
10.39 +
10.40 +#define VISIBLE_START 70
10.41 +#define VFP_START (VISIBLE_START + 2 * LINE_COUNT)
10.42 +
10.43 +/* Horizontal lines, front porch end. */
10.44 +
10.45 +#define VSYNC_START 620
10.46 +
10.47 +/* Horizontal lines, back porch start. */
10.48 +
10.49 +#define VSYNC_END 622
10.50 +
10.51 +#define SCREEN_BASE 256
10.52 +#define SCREEN_SIZE (40 * 1024)
10.53 +#define SCREEN_LIMIT (SCREEN_BASE + SCREEN_SIZE)
10.54 +
10.55 +#define SCREEN_BASE_KSEG0 (KSEG0_BASE + SCREEN_BASE)
10.56 +#define SCREEN_LIMIT_KSEG0 (KSEG0_BASE + SCREEN_LIMIT)
10.57 +
10.58 +#endif /* __VGA_H__ */
11.1 --- a/main.c Sat Oct 20 19:19:30 2018 +0200
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,195 +0,0 @@
11.4 -/*
11.5 - * A demonstration of various PIC32 peripherals.
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 -
11.24 -#include "pic32_c.h"
11.25 -#include "init.h"
11.26 -#include "debug.h"
11.27 -#include "main.h"
11.28 -
11.29 -static const char message1[] = "Hello!\r\n";
11.30 -static const char message2[] = "Again!\r\n";
11.31 -static int uart_echo = 0;
11.32 -
11.33 -
11.34 -
11.35 -/* Blink an attached LED with delays implemented using a loop. */
11.36 -
11.37 -static void blink(uint32_t delay, uint32_t port, uint32_t pins)
11.38 -{
11.39 - uint32_t counter;
11.40 -
11.41 - /* Clear outputs (LED). */
11.42 -
11.43 - CLR_REG(port, pins);
11.44 -
11.45 - while (1)
11.46 - {
11.47 - counter = delay;
11.48 -
11.49 - while (counter--) __asm__(""); /* retain loop */
11.50 -
11.51 - /* Invert outputs (LED). */
11.52 -
11.53 - INV_REG(port, pins);
11.54 - }
11.55 -}
11.56 -
11.57 -
11.58 -
11.59 -/* Main program. */
11.60 -
11.61 -void main(void)
11.62 -{
11.63 - init_memory();
11.64 - init_pins();
11.65 - init_outputs();
11.66 -
11.67 - unlock_config();
11.68 - config_uart();
11.69 - lock_config();
11.70 -
11.71 - init_dma();
11.72 -
11.73 - /* Initiate DMA on the Timer2 interrupt. Since the channel is not
11.74 - auto-enabled, it must be explicitly enabled elsewhere (when a UART
11.75 - interrupt is handled). */
11.76 -
11.77 - dma_init(0, 3);
11.78 - dma_set_interrupt(0, T2, 1);
11.79 - dma_set_transfer(0, PHYSICAL((uint32_t) message1), sizeof(message1) - 1,
11.80 - HW_PHYSICAL(UART_REG(1, UxTXREG)), 1,
11.81 - 1);
11.82 -
11.83 - /* Enable DMA on the preceding channel's completion, with OC1 initiating
11.84 - transfers, raising a transfer completion interrupt to be handled. */
11.85 -
11.86 - dma_init(1, 3);
11.87 - dma_set_chaining(1, dma_chain_previous);
11.88 - dma_set_interrupt(1, OC1, 1);
11.89 - dma_set_transfer(1, PHYSICAL((uint32_t) message2), sizeof(message2) - 1,
11.90 - HW_PHYSICAL(UART_REG(1, UxTXREG)), 1,
11.91 - 1);
11.92 - dma_init_interrupt(1, 0b00001000, 7, 3);
11.93 -
11.94 - /* Configure a timer for the first DMA channel whose interrupt condition
11.95 - drives the transfer but is not handled (having a lower priority than the
11.96 - CPU. */
11.97 -
11.98 - timer_init(2, 0b111, 60000);
11.99 - timer_init_interrupt(2, 1, 3);
11.100 - timer_on(2);
11.101 -
11.102 - /* Configure a timer for the output compare unit below. */
11.103 -
11.104 - timer_init(3, 0b111, 20000);
11.105 - timer_on(3);
11.106 -
11.107 - /* Configure output compare in dual compare (continuous output) mode using
11.108 - Timer3 as time base. The interrupt condition drives the second DMA
11.109 - channel but is not handled (having a lower priority than the CPU). */
11.110 -
11.111 - oc_init(1, 0b101, 3);
11.112 - oc_set_pulse(1, 10000);
11.113 - oc_set_pulse_end(1, 20000);
11.114 - oc_init_interrupt(1, 1, 3);
11.115 - oc_on(1);
11.116 -
11.117 - /* Set UART interrupt priority above CPU priority to process events and to
11.118 - enable the first DMA channel. */
11.119 -
11.120 - uart_init(1, 115200);
11.121 - uart_init_interrupt(1, UxRIF, 7, 3);
11.122 - uart_on(1);
11.123 -
11.124 - interrupts_on();
11.125 -
11.126 - blink(3 << 24, PORTA, 1 << 3);
11.127 -}
11.128 -
11.129 -
11.130 -
11.131 -/* Exception and interrupt handlers. */
11.132 -
11.133 -void exception_handler(void)
11.134 -{
11.135 - blink(3 << 12, PORTA, 1 << 3);
11.136 -}
11.137 -
11.138 -void interrupt_handler(void)
11.139 -{
11.140 - uint32_t ifs;
11.141 - char val;
11.142 -
11.143 - /* Check for a UART receive interrupt condition (UxRIF). */
11.144 -
11.145 - ifs = REG(UARTIFS) & UART_INT_FLAGS(1, UxRIF);
11.146 -
11.147 - if (ifs)
11.148 - {
11.149 - /* Clear the UART interrupt condition. */
11.150 -
11.151 - CLR_REG(UARTIFS, ifs);
11.152 -
11.153 - /* Write the received data back. */
11.154 -
11.155 - while (uart_can_read(1))
11.156 - {
11.157 - val = uart_read_char(1);
11.158 - if (uart_echo)
11.159 - uart_write_char(1, val);
11.160 -
11.161 - /* Initiate transfer upon receiving a particular character. */
11.162 -
11.163 - if (val == '0')
11.164 - dma_on(0);
11.165 - }
11.166 - }
11.167 -
11.168 - /* Check for a DMA interrupt condition (CHBCIF). */
11.169 -
11.170 - ifs = REG(DMAIFS) & DMA_INT_FLAGS(1, 1);
11.171 -
11.172 - if (ifs)
11.173 - {
11.174 - uart_write_string("CHBCIF\r\n");
11.175 - INV_REG(PORTA, 1 << 2);
11.176 - CLR_REG(DMA_REG(1, DCHxINT), 0b11111111);
11.177 - CLR_REG(DMAIFS, ifs);
11.178 - }
11.179 -}
11.180 -
11.181 -
11.182 -
11.183 -/* Peripheral pin configuration. */
11.184 -
11.185 -void config_uart(void)
11.186 -{
11.187 - /* Map U1RX to RPB13. */
11.188 -
11.189 - REG(U1RXR) = 0b0011; /* U1RXR<3:0> = 0011 (RPB13) */
11.190 -
11.191 - /* Map U1TX to RPB15. */
11.192 -
11.193 - REG(RPB15R) = 0b0001; /* RPB15R<3:0> = 0001 (U1TX) */
11.194 -
11.195 - /* Set RPB13 to input. */
11.196 -
11.197 - SET_REG(TRISB, 1 << 13);
11.198 -}
12.1 --- a/main.h Sat Oct 20 19:19:30 2018 +0200
12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
12.3 @@ -1,27 +0,0 @@
12.4 -/*
12.5 - * A demonstration of various PIC32 peripherals.
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 __MAIN_H__
12.24 -#define __MAIN_H__
12.25 -
12.26 -/* Peripheral pin configuration. */
12.27 -
12.28 -void config_uart(void);
12.29 -
12.30 -#endif /* __MAIN_H__ */
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/mk/common.mk Sat Oct 20 19:24:34 2018 +0200
13.3 @@ -0,0 +1,51 @@
13.4 +# Makefile - Common definitions for building PIC32 deployment payloads
13.5 +#
13.6 +# Copyright (C) 2015, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
13.7 +# Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>
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 +ARCH = mipsel-linux-gnu
13.23 +CC = $(ARCH)-gcc
13.24 +LD = $(ARCH)-ld
13.25 +NM = $(ARCH)-nm
13.26 +OBJCOPY=$(ARCH)-objcopy
13.27 +OBJDUMP=$(ARCH)-objdump
13.28 +
13.29 +# NOTE: -O2 is actually needed to prevent memcpy references, whereas probably
13.30 +# NOTE: one of the -f{freestanding, no-hosted, no-builtin} options should work.
13.31 +# NOTE: See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56888
13.32 +
13.33 +CFLAGS = -O2 -Wall \
13.34 + -fno-unit-at-a-time -fno-zero-initialized-in-bss \
13.35 + -ffreestanding -fno-hosted -fno-builtin \
13.36 + -march=mips32 \
13.37 + -I../..
13.38 +LDFLAGS = -nostdlib -EL
13.39 +
13.40 +# Ordering of objects is important and cannot be left to replacement rules.
13.41 +# These are relative to each example directory.
13.42 +
13.43 +START_SRC = ../../start.S
13.44 +START_OBJ = ../../start.o
13.45 +
13.46 +# Application-specific files appear after the above but before those below in
13.47 +# the application Makefiles.
13.48 +
13.49 +COMMON_SRC = ../../init.c ../../debug.c ../../cpu.S
13.50 +COMMON_OBJ = ../../init.o ../../debug.o ../../cpu.o
13.51 +
13.52 +# Common linker script.
13.53 +
13.54 +SCRIPT = ../../payload.ld
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/mk/rules.mk Sat Oct 20 19:24:34 2018 +0200
14.3 @@ -0,0 +1,45 @@
14.4 +# Makefile - Rules for building PIC32 deployment payloads
14.5 +#
14.6 +# Copyright (C) 2015, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
14.7 +# Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>
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 +.PHONY: all clean distclean
14.23 +
14.24 +all: $(HEX) $(SREC)
14.25 +
14.26 +clean:
14.27 + rm -f $(OBJ) $(TARGET) $(HEX) $(SREC) $(DUMP) *.map
14.28 +
14.29 +distclean: clean
14.30 + echo "Nothing else to clean."
14.31 +
14.32 +$(HEX): $(TARGET)
14.33 + $(OBJCOPY) -O ihex $(TARGET) $(HEX)
14.34 +
14.35 +$(SREC): $(TARGET)
14.36 + $(OBJCOPY) -O srec $(TARGET) $(SREC)
14.37 +
14.38 +$(TARGET): $(OBJ)
14.39 + $(LD) $(LDFLAGS) -T $(SCRIPT) $(OBJ) -o $@
14.40 + $(OBJDUMP) -D $(TARGET) > $(DUMP)
14.41 + $(OBJDUMP) -h $(TARGET) > $(MAP)
14.42 + $(NM) -n $(TARGET) > System.map
14.43 +
14.44 +.c.o:
14.45 + $(CC) -c $(CFLAGS) $< -o $@
14.46 +
14.47 +.S.o:
14.48 + $(CC) -c $(CFLAGS) $< -o $@