RPI.Environment.Mod 4.8 KB

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