mirror of
https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials.git
synced 2024-11-17 21:25:52 +00:00
124 lines
3.9 KiB
C
124 lines
3.9 KiB
C
/*
|
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation
|
|
* files (the "Software"), to deal in the Software without
|
|
* restriction, including without limitation the rights to use, copy,
|
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
* of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
*/
|
|
|
|
#include "gpio.h"
|
|
#include "mbox.h"
|
|
#include "sprintf.h"
|
|
|
|
/* PL011 UART registers */
|
|
#define UART0_DR ((volatile unsigned int*)(MMIO_BASE+0x00201000))
|
|
#define UART0_FR ((volatile unsigned int*)(MMIO_BASE+0x00201018))
|
|
#define UART0_IBRD ((volatile unsigned int*)(MMIO_BASE+0x00201024))
|
|
#define UART0_FBRD ((volatile unsigned int*)(MMIO_BASE+0x00201028))
|
|
#define UART0_LCRH ((volatile unsigned int*)(MMIO_BASE+0x0020102C))
|
|
#define UART0_CR ((volatile unsigned int*)(MMIO_BASE+0x00201030))
|
|
#define UART0_IMSC ((volatile unsigned int*)(MMIO_BASE+0x00201038))
|
|
#define UART0_ICR ((volatile unsigned int*)(MMIO_BASE+0x00201044))
|
|
|
|
// get address from linker
|
|
extern volatile unsigned char _end;
|
|
|
|
/**
|
|
* Set baud rate and characteristics (115200 8N1) and map to GPIO
|
|
*/
|
|
void uart_init()
|
|
{
|
|
register unsigned int r;
|
|
|
|
/* initialize UART */
|
|
*UART0_CR = 0; // turn off UART0
|
|
|
|
/* set up clock for consistent divisor values */
|
|
mbox[0] = 8*4;
|
|
mbox[1] = MBOX_REQUEST;
|
|
mbox[2] = MBOX_TAG_SETCLKRATE; // set clock rate
|
|
mbox[3] = 12;
|
|
mbox[4] = 8;
|
|
mbox[5] = 2; // UART clock
|
|
mbox[6] = 4000000; // 4Mhz
|
|
mbox[7] = MBOX_TAG_LAST;
|
|
mbox_call(MBOX_CH_PROP);
|
|
|
|
/* map UART0 to GPIO pins */
|
|
r=*GPFSEL1;
|
|
r&=~((7<<12)|(7<<15)); // gpio14, gpio15
|
|
r|=(4<<12)|(4<<15); // alt0
|
|
*GPFSEL1 = r;
|
|
*GPPUD = 0; // enable pins 14 and 15
|
|
r=150; while(r--) { asm volatile("nop"); }
|
|
*GPPUDCLK0 = (1<<14)|(1<<15);
|
|
r=150; while(r--) { asm volatile("nop"); }
|
|
*GPPUDCLK0 = 0; // flush GPIO setup
|
|
|
|
*UART0_ICR = 0x7FF; // clear interrupts
|
|
*UART0_IBRD = 2; // 115200 baud
|
|
*UART0_FBRD = 0xB;
|
|
*UART0_LCRH = 0b11<<5; // 8n1
|
|
*UART0_CR = 0x301; // enable Tx, Rx, FIFO
|
|
}
|
|
|
|
/**
|
|
* Send a character
|
|
*/
|
|
void uart_send(unsigned int c) {
|
|
/* wait until we can send */
|
|
do{asm volatile("nop");}while(*UART0_FR&0x20);
|
|
/* write the character to the buffer */
|
|
*UART0_DR=c;
|
|
}
|
|
|
|
/**
|
|
* Receive a character
|
|
*/
|
|
char uart_getc() {
|
|
char r;
|
|
/* wait until something is in the buffer */
|
|
do{asm volatile("nop");}while(*UART0_FR&0x10);
|
|
/* read it and return */
|
|
r=(char)(*UART0_DR);
|
|
/* convert carrige return to newline */
|
|
return r=='\r'?'\n':r;
|
|
}
|
|
|
|
/**
|
|
* Display a string
|
|
*/
|
|
void printf(char *fmt, ...) {
|
|
__builtin_va_list args;
|
|
__builtin_va_start(args, fmt);
|
|
// we don't have memory allocation yet, so we
|
|
// simply place our string after our code
|
|
char *s = (char*)&_end;
|
|
// use sprintf to format our string
|
|
vsprintf(s,fmt,args);
|
|
// print out as usual
|
|
while(*s) {
|
|
/* convert newline to carrige return + newline */
|
|
if(*s=='\n')
|
|
uart_send('\r');
|
|
uart_send(*s++);
|
|
}
|
|
}
|