raspi2.pp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. {$IFNDEF FPC_DOTTEDUNITS}
  2. unit raspi2;
  3. {$ENDIF FPC_DOTTEDUNITS}
  4. {$goto on}
  5. {$INLINE ON}
  6. interface
  7. type
  8. TBitvector32 = bitpacked array[0..31] of 0..1;
  9. const
  10. PeripheralBase = $3F000000;
  11. GPFSEL1 = PeripheralBase + $00200004;
  12. GPSET0 = PeripheralBase + $0020001C;
  13. GPCLR0 = PeripheralBase + $00200028;
  14. GPPUD = PeripheralBase + $00200094;
  15. GPPUDCLK0 = PeripheralBase + $00200098;
  16. AUX_ENABLES = PeripheralBase + $00215004;
  17. AUX_MU_IO_REG = PeripheralBase + $00215040;
  18. AUX_MU_IER_REG = PeripheralBase + $00215044;
  19. AUX_MU_IIR_REG = PeripheralBase + $00215048;
  20. AUX_MU_LCR_REG = PeripheralBase + $0021504C;
  21. AUX_MU_MCR_REG = PeripheralBase + $00215050;
  22. AUX_MU_LSR_REG = PeripheralBase + $00215054;
  23. AUX_MU_MSR_REG = PeripheralBase + $00215058;
  24. AUX_MU_SCRATCH = PeripheralBase + $0021505C;
  25. AUX_MU_CNTL_REG = PeripheralBase + $00215060;
  26. AUX_MU_STAT_REG = PeripheralBase + $00215064;
  27. AUX_MU_BAUD_REG = PeripheralBase + $00215068;
  28. implementation
  29. {$IFDEF FPC_DOTTEDUNITS}
  30. uses
  31. EmbeddedApi.ConsoleIO;
  32. {$ELSE FPC_DOTTEDUNITS}
  33. uses
  34. consoleio;
  35. {$ENDIF FPC_DOTTEDUNITS}
  36. procedure _FPC_haltproc; assembler; nostackframe; public name '_haltproc';
  37. asm
  38. .Lhalt:
  39. wfi
  40. b .Lhalt
  41. end;
  42. procedure DUMMY(Count: DWord);
  43. var
  44. i : DWord;
  45. begin
  46. for i := 0 to Count do
  47. begin
  48. asm
  49. nop
  50. end;
  51. end;
  52. end;
  53. procedure PUT32(Address: DWord; Value: DWord); inline;
  54. VAR
  55. p: ^DWord;
  56. begin
  57. p := POINTER (Address);
  58. p^ := Value;
  59. end;
  60. function GET32(Address: DWord) : DWord; inline;
  61. VAR
  62. p: ^DWord;
  63. begin
  64. p := POINTER (Address);
  65. GET32 := p^;
  66. end;
  67. function UARTLCR(): DWord;
  68. begin
  69. UARTLCR := GET32(AUX_MU_LCR_REG);
  70. end;
  71. procedure UARTPuts(C: AnsiChar);
  72. begin
  73. while True do
  74. begin
  75. if (GET32(AUX_MU_LSR_REG) and $20) > 0 then break;
  76. end;
  77. PUT32(AUX_MU_IO_REG, DWord(C));
  78. end;
  79. function UARTGet(): AnsiChar;
  80. begin
  81. while True do
  82. begin
  83. if (GET32(AUX_MU_LSR_REG) and $01) > 0 then break;
  84. end;
  85. UARTGet := AnsiChar(GET32(AUX_MU_IO_REG) and $FF);
  86. end;
  87. procedure UARTFlush();
  88. begin
  89. while True do
  90. begin
  91. if (GET32(AUX_MU_LSR_REG) and $100) > 0 then break;
  92. end;
  93. end;
  94. function RaspiWrite(ACh: AnsiChar; AUserData: pointer): boolean;
  95. begin
  96. UARTPuts(ACh);
  97. RaspiWrite := true;
  98. end;
  99. function RaspiRead(var ACh: AnsiChar; AUserData: pointer): boolean;
  100. begin
  101. if (GET32(AUX_MU_LSR_REG) and $01) > 0 then
  102. begin
  103. ACh := UARTGet();
  104. end else
  105. begin
  106. ACh := #0;
  107. end;
  108. RaspiRead := true;
  109. end;
  110. procedure UARTInit; public name 'UARTInit';
  111. var
  112. ra: dword;
  113. begin
  114. PUT32(AUX_ENABLES, 1);
  115. PUT32(AUX_MU_IER_REG, 0);
  116. PUT32(AUX_MU_CNTL_REG, 0);
  117. PUT32(AUX_MU_LCR_REG, 3);
  118. PUT32(AUX_MU_MCR_REG, 0);
  119. PUT32(AUX_MU_IER_REG, 0);
  120. PUT32(AUX_MU_IIR_REG, $C6);
  121. PUT32(AUX_MU_BAUD_REG, 270);
  122. ra := GET32(GPFSEL1);
  123. ra := ra AND (not (7 shl 12)); // gpio14
  124. ra := ra OR (2 shl 12); // alt5
  125. ra := ra AND (not (7 shl 15)); // gpio15
  126. ra := ra OR (2 shl 15); // alt5
  127. PUT32(GPFSEL1, ra);
  128. PUT32(GPPUD, 0);
  129. Dummy(500);
  130. PUT32(GPPUDCLK0, ((1 shl 14) OR (1 shl 15)));
  131. Dummy(500);
  132. PUT32(GPPUDCLK0, 0);
  133. PUT32(AUX_MU_CNTL_REG, 3);
  134. end;
  135. {$ifndef CUSTOM_ENTRY}
  136. procedure PASCALMAIN; external name 'PASCALMAIN';
  137. var
  138. _stack_top: record end; external name '_stack_top';
  139. { This start makes sure we only execute on core 0 - the others will halt }
  140. procedure _FPC_start; assembler; nostackframe;
  141. label
  142. _start;
  143. asm
  144. .init
  145. .align 16
  146. .globl _start
  147. _start:
  148. // enable fpu
  149. .long 0xee110f50 // mrc p15, 0, r0, c1, c0, 2
  150. orr r0, r0, #0x300000 // single precision
  151. orr r0, r0, #0xC00000 // double precision
  152. .long 0xee010f50 // mcr p15, 0, r0, c1, c0, 2
  153. mov r0, #0x40000000
  154. .long 0xeee80a10 // fmxr fpexc, r0
  155. .long 0xee100fb0 // mrc p15,0,r0,c0,c0,5 - find the core ID
  156. mov r1, #0xFF
  157. ands r1, r1, r0
  158. bne _FPC_haltproc
  159. ldr r0, .L_stack_top
  160. mov sp, r0
  161. bl UARTInit
  162. bl PASCALMAIN
  163. bl _FPC_haltproc
  164. .L_stack_top:
  165. .long _stack_top
  166. .text
  167. end;
  168. {$endif CUSTOM_ENTRY}
  169. begin
  170. OpenIO(Input, @RaspiWrite, @RaspiRead, fmInput, nil);
  171. OpenIO(Output, @RaspiWrite, @RaspiRead, fmOutput, nil);
  172. OpenIO(ErrOutput, @RaspiWrite, @RaspiRead, fmOutput, nil);
  173. OpenIO(StdOut, @RaspiWrite, @RaspiRead, fmOutput, nil);
  174. OpenIO(StdErr, @RaspiWrite, @RaspiRead, fmOutput, nil);
  175. end.