raspiuart.pp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. {
  2. Copyright (c) 1998-2022 by the Free Pascal development team
  3. Raspberry Pi 3/4 UART0 support
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit raspiuart;
  18. {-
  19. The Raspberry Pi 3 and 4 use an ARM PL011 UART, but requires
  20. some configuration of the clock via the GPIO before you
  21. can set the baud rate of the UART and to connect the GPIO
  22. pins for TX/RX
  23. -}
  24. interface
  25. procedure UARTInit(BaseAddr: DWord); public name 'UARTInit';
  26. procedure UARTPuts(BaseAddr: DWord; C: Char);
  27. function UARTGet(BaseAddr: DWord): Char;
  28. procedure UARTFlush(BaseAddr: DWord);
  29. implementation
  30. uses
  31. mailbox, mmio, gpio;
  32. const
  33. { UART offsets from PeripheralBase }
  34. UART0_DR = $00201000;
  35. UART0_FR = $00201018;
  36. UART0_IBRD = $00201024;
  37. UART0_FBRD = $00201028;
  38. UART0_LCRH = $0020102C;
  39. UART0_CR = $00201030;
  40. UART0_IMSC = $00201038;
  41. UART0_ICR = $00201044;
  42. procedure SetClockRate(BaseAddr: DWord);
  43. begin
  44. MBox[0] := 9*4;
  45. MBox[1] := MBOX_REQUEST;
  46. MBox[2] := MBOX_TAG_SETCLKRATE;
  47. MBox[3] := 12;
  48. MBox[4] := 8;
  49. MBox[5] := 2;
  50. MBox[6] := 4000000; { 4 Mhz }
  51. MBox[7] := 0; { Clear turbo flag }
  52. MBox[8] := MBOX_TAG_LAST;
  53. MailboxCall(BaseAddr, MBOX_CH_PROP);
  54. end;
  55. procedure UARTInit(BaseAddr: DWord); public name 'UARTInit';
  56. var
  57. ra: DWord;
  58. begin
  59. { Turn off the UART first }
  60. PUT32(BaseAddr + UART0_CR, 0);
  61. SetClockRate(BaseAddr);
  62. { map UART0 to GPIO pins }
  63. ra := GET32(GPFSEL1);
  64. ra := ra AND (not (7 shl 12));
  65. ra := ra OR (4 shl 12);
  66. PUT32(GPFSEL1, ra);
  67. PUT32(GPPUD, 0);
  68. DUMMY(150);
  69. { Enable pins 14 and 15 }
  70. ra := ((1 shl 14) or (1 shl 15));
  71. PUT32(GPPUDCLK0, ra);
  72. DUMMY(150);
  73. { Flush GPIO setup }
  74. PUT32(GPPUDCLK0, 0);
  75. { Clear interrupts }
  76. PUT32(BaseAddr + UART0_ICR, $7FF);
  77. { 115200 baud }
  78. PUT32(BaseAddr + UART0_IBRD, 2);
  79. PUT32(BaseAddr + UART0_FBRD, $B);
  80. { 8n1, enable FIFO }
  81. PUT32(BaseAddr + UART0_LCRH, ($7 shl 4));
  82. { Enable rx and tx }
  83. PUT32(BaseAddr + UART0_CR, $301);
  84. end;
  85. procedure UARTPuts(BaseAddr: DWord; C: Char);
  86. begin
  87. while True do
  88. begin
  89. DUMMY(1);
  90. if (GET32(BaseAddr + UART0_FR) and $20) = 0 then break;
  91. end;
  92. PUT32(BaseAddr + UART0_DR, DWord(C));
  93. end;
  94. function UARTGet(BaseAddr: DWord): Char;
  95. begin
  96. while True do
  97. begin
  98. DUMMY(1);
  99. if (GET32(BaseAddr + UART0_FR) and $10) = 0 then break;
  100. end;
  101. UARTGet := Char(GET32(BaseAddr + UART0_DR));
  102. end;
  103. procedure UARTFlush(BaseAddr: DWord);
  104. begin
  105. PUT32(BaseAddr + UART0_LCRH, (1 shl 4));
  106. end;
  107. end.