forgotten files
authorJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 24 Jan 2019 23:46:07 +0000 (01:46 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 24 Jan 2019 23:46:07 +0000 (01:46 +0200)
install [new file with mode: 0755]
src/asm.h [new file with mode: 0644]
src/gpio.h [new file with mode: 0644]
src/serial.c [new file with mode: 0644]
src/serial.h [new file with mode: 0644]
src/uart.h [new file with mode: 0644]

diff --git a/install b/install
new file mode 100755 (executable)
index 0000000..837479c
--- /dev/null
+++ b/install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+mount /media/usbmass && \
+       cp rpikern.bin /media/usbmass/kernel7.img && \
+       umount /media/usbmass && sync
diff --git a/src/asm.h b/src/asm.h
new file mode 100644 (file)
index 0000000..61d29ac
--- /dev/null
+++ b/src/asm.h
@@ -0,0 +1,13 @@
+#ifndef ASM_H_
+#define ASM_H_
+
+#define enable_intr()  asm volatile ("cpsie i")
+#define disable_intr() asm volatile ("cpsid i")
+#define mem_barrier()  asm volatile ("dmb" ::: "memory")
+
+#define delay(x)  asm volatile ( \
+               "0: subs %0, %0, #1\n\t" \
+               "bne 0b\n\t" \
+               :: "r"(x) : "cc")
+
+#endif /* ASM_H_ */
diff --git a/src/gpio.h b/src/gpio.h
new file mode 100644 (file)
index 0000000..19ca6c3
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef GPIO_H_
+#define GPIO_H_
+
+#include "asm.h"
+
+#define GPIO_BASE      0x3f200000
+#define GPIO_REG(x)    (*(volatile uint32_t*)(GPIO_BASE | (x)))
+
+/* function select */
+#define REG_GPFSEL(x)  GPIO_REG((x) << 2)
+#define REG_GPFSEL0            GPIO_REG(0x00)
+#define REG_GPFSEL1            GPIO_REG(0x04)
+#define REG_GPFSEL2            GPIO_REG(0x08)
+#define REG_GPFSEL3            GPIO_REG(0x0c)
+#define REG_GPFSEL4            GPIO_REG(0x10)
+#define REG_GPFSEL5            GPIO_REG(0x14)
+/* pin output set */
+#define REG_GPSET0             GPIO_REG(0x1c)
+#define REG_GPSET1             GPIO_REG(0x20)
+/* pin output clear */
+#define REG_GPCLR0             GPIO_REG(0x28)
+#define REG_GPCLR1             GPIO_REG(0x2c)
+/* pin level */
+#define REG_GPLEV0             GPIO_REG(0x34)
+#define REG_GPLEV1             GPIO_REG(0x38)
+/* pin event detect status */
+#define REG_GPEDS0             GPIO_REG(0x40)
+#define REG_GPEDS1             GPIO_REG(0x44)
+/* pin rising edge detect enable */
+#define REG_GPREN0             GPIO_REG(0x4c)
+#define REG_GPREN1             GPIO_REG(0x50)
+/* pin falling edge detect enable */
+#define REG_GPFEN0             GPIO_REG(0x58)
+#define REG_GPFEN1             GPIO_REG(0x5c)
+/* pin high detect enable */
+#define REG_GPHEN0             GPIO_REG(0x64)
+#define REG_GPHEN1             GPIO_REG(0x68)
+/* pin low detect enable */
+#define REG_GPLEN0             GPIO_REG(0x70)
+#define REG_GPLEN1             GPIO_REG(0x74)
+/* pin async rising edge detect */
+#define REG_GPAREN0            GPIO_REG(0x7c)
+#define REG_GPAREN1            GPIO_REG(0x80)
+/* pin async falling edge detect */
+#define REG_GPAFEN0            GPIO_REG(0x88)
+#define REG_GPAFEN1            GPIO_REG(0x8c)
+/* pin pull-up/down enable */
+#define REG_GPPUD              GPIO_REG(0x94)
+/* pin pull-up/down enable clock */
+#define REG_GPPUDCLK0  GPIO_REG(0x98)
+#define REG_GPPUDCLK1  GPIO_REG(0x9c)
+
+/* function select bits */
+#define FSEL_IN                0
+#define FSEL_OUT       1
+#define FSEL_ALT0      4
+#define FSEL_ALT1      5
+#define FSEL_ALT2      6
+#define FSEL_ALT3      7
+#define FSEL_ALT4      3
+#define FSEL_ALT5      2
+
+/* pull-up/down bits */
+#define PUD_DISABLE    0
+#define PUD_DOWN       1
+#define PUD_UP         2
+
+static inline void gpio_fsel(int x, int f)
+{
+       static const unsigned int fseltab[54][2] = {
+               {0, 0}, {0, 3}, {0, 6}, {0, 9}, {0, 12}, {0, 15}, {0, 18}, {0, 21}, {0, 24}, {0, 27},
+               {4, 0}, {4, 3}, {4, 6}, {4, 9}, {4, 12}, {4, 15}, {4, 18}, {4, 21}, {4, 24}, {4, 27},
+               {8, 0}, {8, 3}, {8, 6}, {8, 9}, {8, 12}, {8, 15}, {8, 18}, {8, 21}, {8, 24}, {8, 27},
+               {12, 0}, {12, 3}, {12, 6}, {12, 9}, {12, 12}, {12, 15}, {12, 18}, {12, 21}, {12, 24}, {12, 27},
+               {16, 0}, {16, 3}, {16, 6}, {16, 9}, {16, 12}, {16, 15}, {16, 18}, {16, 21}, {16, 24}, {16, 27},
+               {20, 0}, {20, 3}, {20, 6}, {20, 9}
+       };
+       uint32_t val;
+
+       if(x <= 53) {
+               val = f << fseltab[x][1];
+               *(volatile uint32_t*)(GPIO_BASE | fseltab[x][0]) = val;
+       }
+}
+
+static inline void gpio_pullups(uint32_t mask0, uint32_t mask1, int state)
+{
+       REG_GPPUD = state;
+       delay(150);
+
+       if(mask0) REG_GPPUDCLK0 = mask0;
+       if(mask1) REG_GPPUDCLK1 = mask1;
+       delay(150);
+
+       if(mask0) REG_GPPUDCLK0 = 0;
+       if(mask1) REG_GPPUDCLK1 = 0;
+}
+
+#endif /* GPIO_H_ */
diff --git a/src/serial.c b/src/serial.c
new file mode 100644 (file)
index 0000000..ddd5923
--- /dev/null
@@ -0,0 +1,54 @@
+#include <stdint.h>
+#include "serial.h"
+#include "uart.h"
+#include "gpio.h"
+
+/* baud rate: BAUDDIV = (UART_CLK / (16 * baud)) */
+#define UART_CLK       3000000
+
+void init_serial(int baud)
+{
+       uint32_t bdiv_fp6;
+
+       REG_CR = 0;             /* disable UART */
+
+       /* disable pullups for GPIO 14 & 15 */
+       gpio_pullups(0xc000, 0, PUD_DISABLE);
+
+       REG_ICR = 0;    /* clear pending interrupts */
+
+       /* calculate baud rate divisor */
+       bdiv_fp6 = (UART_CLK << 6) / (16 * baud);
+       REG_IBRD = (bdiv_fp6 >> 6) & 0xffff;    /* 16 bits integer part */
+       REG_FBRD = bdiv_fp6 & 0x3f;             /* 6 bits fractional precision */
+
+       /* line control: fifo enable, 8n1 */
+       REG_LCRH = LCRH_FIFOEN | LCRH_8BITS;
+       /* mask all interrupts */
+       REG_IMSC = I_CTS | I_RX | I_TX | I_RTIME | I_FRM | I_PAR | I_BRK | I_OVR;
+
+       /* enable UART RX&TX */
+       REG_CR = CR_UARTEN | CR_TXEN | CR_RXEN;
+}
+
+void ser_putchar(int c)
+{
+       while(REG_FR & FR_TXFF);
+       REG_DR = c & 0xff;
+}
+
+int ser_getchar(void)
+{
+       while(REG_FR & FR_RXFE);
+       return REG_DR & 0xff;
+}
+
+void ser_printstr(const char *s)
+{
+       while(*s) {
+               if(*s == '\n') {
+                       ser_putchar('\r');
+               }
+               ser_putchar(*s++);
+       }
+}
diff --git a/src/serial.h b/src/serial.h
new file mode 100644 (file)
index 0000000..785457e
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef SERIAL_H_
+#define SERIAL_H_
+
+void init_serial(int baud);
+
+void ser_putchar(int c);
+int ser_getchar(void);
+
+void ser_printstr(const char *s);
+
+#endif /* SERIAL_H_ */
diff --git a/src/uart.h b/src/uart.h
new file mode 100644 (file)
index 0000000..ade162e
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef UART_PL011_H_
+#define UART_PL011_H_
+
+#define UART0_BASE             0x3f201000
+#define UART0_REG(x)   *(volatile uint32_t*)(UART0_BASE | (x))
+
+#define REG_DR         UART0_REG(0x00) /* data register */
+#define REG_RSRECR     UART0_REG(0x04) /* receive status & error clear */
+#define REG_FR         UART0_REG(0x18) /* flag register */
+#define REG_IBRD       UART0_REG(0x24) /* integer baud rate divisor (low 16 bits) */
+#define REG_FBRD       UART0_REG(0x28) /* fractional baud rate divisor (low 6 (six) bits) */
+#define REG_LCRH       UART0_REG(0x2c) /* line control */
+#define REG_CR         UART0_REG(0x30) /* control register */
+#define REG_IFLS       UART0_REG(0x34) /* interrupt FIFO level select */
+#define REG_IMSC       UART0_REG(0x38) /* interrupt mask set clear */
+#define REG_RIS                UART0_REG(0x3c) /* raw interrupt status */
+#define REG_MIS                UART0_REG(0x40) /* masked interrupt status */
+#define REG_ICR                UART0_REG(0x44) /* interrupt clear */
+
+/* error bits in REG_DR */
+#define DR_FRM 0x0100
+#define DR_PAR 0x0200
+#define DR_BRK 0x0400
+#define DR_OVR 0x0800
+
+/* receive status error bits */
+#define RCR_FRM        0x01
+#define RCR_PAR        0x02
+#define RCR_BRK        0x04
+#define RCR_OVR        0x08
+
+/* flag register bits */
+#define FR_CTS 0x01
+#define FR_BUSY        0x08
+#define FR_RXFE        0x10    /* receive FIFO empty */
+#define FR_TXFF        0x20    /* transmit FIFO full */
+#define FR_RXFF        0x40    /* receive FIFO full */
+#define FR_TXFE        0x80    /* transmit FIFO empty */
+
+/* line control register bits */
+#define LCRH_BRK               0x01    /* send break */
+#define LCRH_PAREN             0x02
+#define LCRH_PAREVEN   0x04
+#define LCRH_STOP2             0x08
+#define LCRH_FIFOEN            0x10
+#define LCRH_8BITS             0x60
+#define LCRH_7BITS             0x40
+#define LCRH_STICKPAR  0x80    /* ? */
+
+/* control register bits */
+#define CR_UARTEN              0x0001
+#define CR_LOOPEN              0x0080
+#define CR_TXEN                        0x0100
+#define CR_RXEN                        0x0200
+#define CR_RTS                 0x0800
+#define CR_RTSEN               0x4000
+#define CR_CTSEN               0x8000
+
+/* interrupt bits for IMSC, RIS, ICR */
+#define I_CTS          0x0002
+#define I_RX           0x0010
+#define I_TX           0x0020
+#define I_RTIME                0x0040
+#define I_FRM          0x0080
+#define I_PAR          0x0100
+#define I_BRK          0x0200
+#define I_OVR          0x0400
+
+#endif /* UART_PL011_H_ */