mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-02 20:19:34 +01:00
146 lines
3.5 KiB
ObjectPascal
146 lines
3.5 KiB
ObjectPascal
{
|
|
Copyright (c) 1998-2022 by the Free Pascal development team
|
|
|
|
Raspberry Pi 3/4 UART0 support
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
****************************************************************************
|
|
}
|
|
{$IFNDEF FPC_DOTTEDUNITS}
|
|
unit raspiuart;
|
|
{$ENDIF FPC_DOTTEDUNITS}
|
|
|
|
{-
|
|
The Raspberry Pi 3 and 4 use an ARM PL011 UART, but requires
|
|
some configuration of the clock via the GPIO before you
|
|
can set the baud rate of the UART and to connect the GPIO
|
|
pins for TX/RX
|
|
-}
|
|
|
|
interface
|
|
|
|
procedure UARTInit(BaseAddr: DWord); public name 'UARTInit';
|
|
procedure UARTPuts(BaseAddr: DWord; C: AnsiChar);
|
|
function UARTGet(BaseAddr: DWord): AnsiChar;
|
|
procedure UARTFlush(BaseAddr: DWord);
|
|
|
|
implementation
|
|
|
|
{$IFDEF FPC_DOTTEDUNITS}
|
|
uses
|
|
EmbeddedApi.mailbox, EmbeddedApi.mmio, EmbeddedApi.gpio;
|
|
{$ELSE FPC_DOTTEDUNITS}
|
|
uses
|
|
mailbox, mmio, gpio;
|
|
{$ENDIF FPC_DOTTEDUNITS}
|
|
|
|
const
|
|
{ UART offsets from PeripheralBase }
|
|
UART0_DR = $00201000;
|
|
UART0_FR = $00201018;
|
|
UART0_IBRD = $00201024;
|
|
UART0_FBRD = $00201028;
|
|
UART0_LCRH = $0020102C;
|
|
UART0_CR = $00201030;
|
|
UART0_IMSC = $00201038;
|
|
UART0_ICR = $00201044;
|
|
|
|
procedure SetClockRate(BaseAddr: DWord);
|
|
begin
|
|
MBox[0] := 9*4;
|
|
MBox[1] := MBOX_REQUEST;
|
|
MBox[2] := MBOX_TAG_SETCLKRATE;
|
|
MBox[3] := 12;
|
|
MBox[4] := 8;
|
|
MBox[5] := 2;
|
|
MBox[6] := 4000000; { 4 Mhz }
|
|
MBox[7] := 0; { Clear turbo flag }
|
|
MBox[8] := MBOX_TAG_LAST;
|
|
|
|
MailboxCall(BaseAddr, MBOX_CH_PROP);
|
|
end;
|
|
|
|
procedure UARTInit(BaseAddr: DWord); public name 'UARTInit';
|
|
var
|
|
ra: DWord;
|
|
begin
|
|
{ Turn off the UART first }
|
|
PUT32(BaseAddr + UART0_CR, 0);
|
|
|
|
SetClockRate(BaseAddr);
|
|
|
|
{ map UART0 to GPIO pins }
|
|
ra := GET32(GPFSEL1);
|
|
ra := ra AND (not (7 shl 12));
|
|
ra := ra OR (4 shl 12);
|
|
PUT32(GPFSEL1, ra);
|
|
|
|
PUT32(GPPUD, 0);
|
|
|
|
DUMMY(150);
|
|
|
|
{ Enable pins 14 and 15 }
|
|
ra := ((1 shl 14) or (1 shl 15));
|
|
PUT32(GPPUDCLK0, ra);
|
|
|
|
DUMMY(150);
|
|
|
|
{ Flush GPIO setup }
|
|
PUT32(GPPUDCLK0, 0);
|
|
|
|
{ Clear interrupts }
|
|
PUT32(BaseAddr + UART0_ICR, $7FF);
|
|
|
|
{ 115200 baud }
|
|
PUT32(BaseAddr + UART0_IBRD, 2);
|
|
PUT32(BaseAddr + UART0_FBRD, $B);
|
|
|
|
{ 8n1, enable FIFO }
|
|
PUT32(BaseAddr + UART0_LCRH, ($7 shl 4));
|
|
|
|
{ Enable rx and tx }
|
|
PUT32(BaseAddr + UART0_CR, $301);
|
|
end;
|
|
|
|
procedure UARTPuts(BaseAddr: DWord; C: AnsiChar);
|
|
begin
|
|
while True do
|
|
begin
|
|
DUMMY(1);
|
|
if (GET32(BaseAddr + UART0_FR) and $20) = 0 then break;
|
|
end;
|
|
|
|
PUT32(BaseAddr + UART0_DR, DWord(C));
|
|
end;
|
|
|
|
function UARTGet(BaseAddr: DWord): AnsiChar;
|
|
begin
|
|
while True do
|
|
begin
|
|
DUMMY(1);
|
|
if (GET32(BaseAddr + UART0_FR) and $10) = 0 then break;
|
|
end;
|
|
|
|
UARTGet := AnsiChar(GET32(BaseAddr + UART0_DR));
|
|
end;
|
|
|
|
procedure UARTFlush(BaseAddr: DWord);
|
|
begin
|
|
PUT32(BaseAddr + UART0_LCRH, (1 shl 4));
|
|
end;
|
|
|
|
end.
|