raspi2.pp 4.3 KB

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