// GPIO enum { PERIPHERAL_BASE = 0xFE000000, GPFSEL0 = PERIPHERAL_BASE + 0x200000, GPSET0 = PERIPHERAL_BASE + 0x20001C, GPCLR0 = PERIPHERAL_BASE + 0x200028, GPPUPPDN0 = PERIPHERAL_BASE + 0x2000E4 }; enum { GPIO_MAX_PIN = 53, GPIO_FUNCTION_ALT5 = 2, }; enum { Pull_None = 0, }; void mmio_write(long reg, unsigned int val) { *(volatile unsigned int *)reg = val; } unsigned int mmio_read(long reg) { return *(volatile unsigned int *)reg; } unsigned int gpio_call(unsigned int pin_number, unsigned int value, unsigned int base, unsigned int field_size, unsigned int field_max) { unsigned int field_mask = (1 << field_size) - 1; if (pin_number > field_max) return 0; if (value > field_mask) return 0; unsigned int num_fields = 32 / field_size; unsigned int reg = base + ((pin_number / num_fields) * 4); unsigned int shift = (pin_number % num_fields) * field_size; unsigned int curval = mmio_read(reg); curval &= ~(field_mask << shift); curval |= value << shift; mmio_write(reg, curval); return 1; } unsigned int gpio_set (unsigned int pin_number, unsigned int value) { return gpio_call(pin_number, value, GPSET0, 1, GPIO_MAX_PIN); } unsigned int gpio_clear (unsigned int pin_number, unsigned int value) { return gpio_call(pin_number, value, GPCLR0, 1, GPIO_MAX_PIN); } unsigned int gpio_pull (unsigned int pin_number, unsigned int value) { return gpio_call(pin_number, value, GPPUPPDN0, 2, GPIO_MAX_PIN); } unsigned int gpio_function(unsigned int pin_number, unsigned int value) { return gpio_call(pin_number, value, GPFSEL0, 3, GPIO_MAX_PIN); } void gpio_useAsAlt5(unsigned int pin_number) { gpio_pull(pin_number, Pull_None); gpio_function(pin_number, GPIO_FUNCTION_ALT5); } // UART enum { AUX_BASE = PERIPHERAL_BASE + 0x215000, AUX_ENABLES = AUX_BASE + 4, AUX_MU_IO_REG = AUX_BASE + 64, AUX_MU_IER_REG = AUX_BASE + 68, AUX_MU_IIR_REG = AUX_BASE + 72, AUX_MU_LCR_REG = AUX_BASE + 76, AUX_MU_MCR_REG = AUX_BASE + 80, AUX_MU_LSR_REG = AUX_BASE + 84, AUX_MU_CNTL_REG = AUX_BASE + 96, AUX_MU_BAUD_REG = AUX_BASE + 104, AUX_UART_CLOCK = 500000000, UART_MAX_QUEUE = 16 * 1024 }; #define AUX_MU_BAUD(baud) ((AUX_UART_CLOCK/(baud*8))-1) void uart_init() { mmio_write(AUX_ENABLES, 1); //enable UART1 mmio_write(AUX_MU_IER_REG, 0); mmio_write(AUX_MU_CNTL_REG, 0); mmio_write(AUX_MU_LCR_REG, 3); //8 bits mmio_write(AUX_MU_MCR_REG, 0); mmio_write(AUX_MU_IER_REG, 0); mmio_write(AUX_MU_IIR_REG, 0xC6); //disable interrupts mmio_write(AUX_MU_BAUD_REG, AUX_MU_BAUD(115200)); gpio_useAsAlt5(14); gpio_useAsAlt5(15); mmio_write(AUX_MU_CNTL_REG, 3); //enable RX/TX } unsigned int uart_isWriteByteReady() { return mmio_read(AUX_MU_LSR_REG) & 0x20; } void uart_writeByteBlockingActual(unsigned char ch) { while (!uart_isWriteByteReady()); mmio_write(AUX_MU_IO_REG, (unsigned int)ch); } void uart_writeText(char *buffer) { while (*buffer) { if (*buffer == '\n') uart_writeByteBlockingActual('\r'); uart_writeByteBlockingActual(*buffer++); } }