RPI.Environment.Mod 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. (* Raspberry Pi environment *)
  2. (* Copyright (C) Florian Negele *)
  3. MODULE Environment;
  4. IMPORT SYSTEM, Activities, CPU, HeapManager, Interrupts, Trace, Processors, Timer;
  5. CONST Running* = 0; ShuttingDown* = 1; Rebooting* = 2;
  6. VAR heap: HeapManager.Heap;
  7. VAR clock := 0: LONGINT;
  8. VAR frequency: Timer.Counter;
  9. VAR status* := Running: WORD;
  10. VAR uartInterruptInstalled := 0: SIZE;
  11. VAR timerInterruptInstalled := 0: SIZE;
  12. VAR uartInterrupt: Interrupts.Interrupt;
  13. VAR previousTimerHandler := NIL: CPU.InterruptHandler;
  14. PROCEDURE {NORETURN} Abort-;
  15. BEGIN {UNCOOPERATIVE, UNCHECKED}
  16. IF SYSTEM.GetActivity () # NIL THEN Activities.TerminateCurrentActivity END;
  17. Activities.TerminateCurrentActivity;
  18. END Abort;
  19. PROCEDURE Allocate- (size: SIZE): ADDRESS;
  20. BEGIN {UNCOOPERATIVE, UNCHECKED}
  21. RETURN HeapManager.Allocate (size, heap);
  22. END Allocate;
  23. PROCEDURE Deallocate- (address: ADDRESS);
  24. BEGIN {UNCOOPERATIVE, UNCHECKED}
  25. HeapManager.Deallocate (address, heap);
  26. END Deallocate;
  27. PROCEDURE Write- (character: CHAR);
  28. BEGIN {UNCOOPERATIVE, UNCHECKED}
  29. WHILE CPU.TXFF IN CPU.ReadMask (CPU.UART_FR) DO END;
  30. CPU.WriteWord (CPU.UART_DR, ORD (character));
  31. END Write;
  32. PROCEDURE Read- (VAR character: CHAR): BOOLEAN;
  33. BEGIN {UNCOOPERATIVE, UNCHECKED}
  34. WHILE CPU.RXFE IN CPU.ReadMask (CPU.UART_FR) DO
  35. IF CAS (uartInterruptInstalled, 0, 1) = 0 THEN
  36. Interrupts.Install (uartInterrupt, CPU.IRQ);
  37. END;
  38. CPU.WriteMask (CPU.IRQEnable2, {25});
  39. Interrupts.Await (uartInterrupt);
  40. IF status # Running THEN RETURN FALSE END;
  41. END;
  42. character := CHR (CPU.ReadWord (CPU.UART_DR));
  43. Write (character); RETURN TRUE;
  44. END Read;
  45. PROCEDURE Flush-;
  46. BEGIN {UNCOOPERATIVE, UNCHECKED}
  47. REPEAT UNTIL CPU.TXFE IN CPU.ReadMask (CPU.UART_FR);
  48. END Flush;
  49. PROCEDURE GetString- (CONST name: ARRAY OF CHAR; VAR result: ARRAY OF CHAR);
  50. BEGIN {UNCOOPERATIVE, UNCHECKED}
  51. result[0] := 0X
  52. END GetString;
  53. PROCEDURE Clock- (): LONGINT;
  54. BEGIN RETURN Timer.GetCounter () DIV frequency;
  55. END Clock;
  56. PROCEDURE Sleep- (milliseconds: LONGINT);
  57. VAR interrupt: Interrupts.Interrupt;
  58. BEGIN {UNCOOPERATIVE, UNCHECKED}
  59. ASSERT (milliseconds >= 0);
  60. IF CAS (timerInterruptInstalled, 0, 1) = 0 THEN
  61. previousTimerHandler := CPU.InstallInterrupt (HandleTimer, CPU.IRQ);
  62. CPU.WriteWord (CPU.STC1, CPU.ReadWord (CPU.STCLO) + 1000);
  63. CPU.WriteMask (CPU.IRQEnable1, {1});
  64. END;
  65. Interrupts.Install (interrupt, CPU.IRQ); INC (milliseconds, clock);
  66. WHILE clock - milliseconds < 0 DO Interrupts.Await (interrupt) END;
  67. END Sleep;
  68. PROCEDURE HandleTimer (index: SIZE);
  69. BEGIN {UNCOOPERATIVE, UNCHECKED}
  70. IF previousTimerHandler # NIL THEN previousTimerHandler (index) END;
  71. IF 1 IN CPU.ReadMask (CPU.STCS) THEN
  72. CPU.WriteWord (CPU.STC1, CPU.ReadWord (CPU.STCLO) + 1000);
  73. CPU.WriteMask (CPU.STCS, {1}); INC (clock);
  74. CPU.WriteMask (CPU.IRQEnable1, {1});
  75. END;
  76. END HandleTimer;
  77. PROCEDURE LED- (status: BOOLEAN);
  78. BEGIN {UNCOOPERATIVE, UNCHECKED}
  79. CPU.Mask (CPU.GPFSEL1, {18});
  80. IF status THEN CPU.WriteMask (CPU.GPSET1, {15}) ELSE CPU.WriteMask (CPU.GPCLR1, {15}) END;
  81. END LED;
  82. PROCEDURE Shutdown*;
  83. BEGIN {UNCOOPERATIVE, UNCHECKED}
  84. IF CAS (status, Running, ShuttingDown) # Running THEN RETURN END;
  85. Trace.StringLn ("system: shutting down...");
  86. IF uartInterruptInstalled # 0 THEN CPU.WriteMask (CPU.IRQDisable2, {25}); Interrupts.Cancel (uartInterrupt) END;
  87. IF timerInterruptInstalled # 0 THEN CPU.WriteMask (CPU.IRQDisable1, {1}) END;
  88. END Shutdown;
  89. PROCEDURE Reboot*;
  90. BEGIN {UNCOOPERATIVE, UNCHECKED}
  91. Shutdown;
  92. ASSERT (CAS (status, ShuttingDown, Rebooting) = ShuttingDown);
  93. END Reboot;
  94. PROCEDURE {NORETURN} Exit- (status: WORD);
  95. BEGIN {UNCOOPERATIVE, UNCHECKED}
  96. Trace.String ("system: ");
  97. IF status = Rebooting THEN Trace.StringLn ("rebooting..."); CPU.Reset END;
  98. Trace.StringLn ("ready for power off or restart"); Flush; CPU.Halt;
  99. END Exit;
  100. PROCEDURE InitTrace;
  101. CONST BaudRate = 115200;
  102. BEGIN {UNCOOPERATIVE, UNCHECKED}
  103. CPU.WriteMask (CPU.UART_CR, {CPU.UARTEN});
  104. CPU.Unmask (CPU.GPPUD, {CPU.PUD}); CPU.Delay (150);
  105. CPU.Mask (CPU.GPPUDCLK0, {14, 15}); CPU.Delay (150);
  106. CPU.WriteMask (CPU.GPPUDCLK0, {});
  107. CPU.WriteMask (CPU.UART_ICR, {1, 4..10});
  108. CPU.WriteWord (CPU.UART_IBRD, CPU.FUARTCLK DIV (16 * BaudRate));
  109. CPU.WriteWord (CPU.UART_FBRD, (CPU.FUARTCLK MOD (16 * BaudRate)) * 64 DIV (16 * BaudRate));
  110. CPU.WriteMask (CPU.UART_LCRH, CPU.WLEN8);
  111. CPU.WriteMask (CPU.UART_IMSC, {CPU.RXIM});
  112. CPU.WriteMask (CPU.UART_CR, {CPU.UARTEN, CPU.TXE, CPU.RXE});
  113. Trace.Init; Trace.Char := Write;
  114. END InitTrace;
  115. PROCEDURE Initialize-;
  116. BEGIN {UNCOOPERATIVE, UNCHECKED}
  117. SYSTEM.SetActivity (NIL);
  118. CPU.Initialize; LED (TRUE); InitTrace;
  119. frequency := Timer.GetFrequency () DIV 1000;
  120. CPU.IdentityMapMemory; CPU.EnableMemoryManagementUnit;
  121. HeapManager.Initialize (heap, ADDRESS OF KernelEnd, CPU.MemorySize);
  122. END Initialize;
  123. PROCEDURE Terminate-;
  124. BEGIN {UNCOOPERATIVE, UNCHECKED}
  125. Interrupts.Terminate;
  126. LED (FALSE);
  127. END Terminate;
  128. PROCEDURE {NOPAF, INITIAL, FIXED(8000H)} KernelBegin;
  129. CODE
  130. MOV SP, #8000H
  131. END KernelBegin;
  132. PROCEDURE {NOPAF, FINAL, ALIGNED(32)} KernelEnd;
  133. CODE
  134. END KernelEnd;
  135. BEGIN {UNCHECKED}
  136. Trace.String ("Version "); Trace.String (SYSTEM.Date); Trace.String (" (");
  137. Trace.Int (CPU.MemorySize DIV (1024 * 1024), 0); Trace.String (" MB RAM, GC, ");
  138. Trace.String ("GC, ");
  139. Trace.Int (Processors.count, 0); Trace.String (" CPU");
  140. IF Processors.count > 1 THEN Trace.Char ('s') END; Trace.Char (')'); Trace.Ln;
  141. END Environment.