|
@@ -0,0 +1,143 @@
|
|
|
|
+(* Raspberry Pi environment *)
|
|
|
|
+(* Copyright (C) Florian Negele *)
|
|
|
|
+
|
|
|
|
+MODULE Environment;
|
|
|
|
+
|
|
|
|
+IMPORT SYSTEM, Activities, CPU, HeapManager, Interrupts, Trace, Processors;
|
|
|
|
+
|
|
|
|
+CONST Running = 0; Halting = 1; Resetting = 2;
|
|
|
|
+
|
|
|
|
+VAR heap: HeapManager.Heap;
|
|
|
|
+VAR clock := 0: LONGINT;
|
|
|
|
+VAR status* := Running: WORD;
|
|
|
|
+VAR uartInterruptInstalled := 0: SIZE;
|
|
|
|
+VAR timerInterruptInstalled := 0: SIZE;
|
|
|
|
+VAR uartInterrupt: Interrupts.Interrupt;
|
|
|
|
+VAR previousTimerHandler := NIL: CPU.InterruptHandler;
|
|
|
|
+VAR name- EXTERN "_environment": ARRAY MAX (SIZE) OF CHAR;
|
|
|
|
+
|
|
|
|
+PROCEDURE {NORETURN} Abort-;
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ Trace.StackFrames (2, 8, SIZE OF ADDRESS * 20);
|
|
|
|
+ IF SYSTEM.GetActivity () = NIL THEN Exit (Resetting) END;
|
|
|
|
+ Activities.TerminateCurrentActivity;
|
|
|
|
+END Abort;
|
|
|
|
+
|
|
|
|
+PROCEDURE Allocate- (size: SIZE): ADDRESS;
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ RETURN HeapManager.Allocate (size, heap);
|
|
|
|
+END Allocate;
|
|
|
|
+
|
|
|
|
+PROCEDURE Deallocate- (address: ADDRESS);
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ HeapManager.Deallocate (address, heap);
|
|
|
|
+END Deallocate;
|
|
|
|
+
|
|
|
|
+PROCEDURE Write- (character: CHAR);
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ WHILE CPU.TXFF IN CPU.ReadMask (CPU.UART_FR) DO END;
|
|
|
|
+ CPU.WriteWord (CPU.UART_DR, ORD (character));
|
|
|
|
+END Write;
|
|
|
|
+
|
|
|
|
+PROCEDURE Read- (VAR character: CHAR): BOOLEAN;
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ WHILE CPU.RXFE IN CPU.ReadMask (CPU.UART_FR) DO
|
|
|
|
+ IF CAS (uartInterruptInstalled, 0, 1) = 0 THEN
|
|
|
|
+ Interrupts.Install (uartInterrupt, CPU.IRQ);
|
|
|
|
+ END;
|
|
|
|
+ CPU.WriteMask (CPU.IRQEnable2, {25});
|
|
|
|
+ Interrupts.Await (uartInterrupt);
|
|
|
|
+ IF status # Running THEN RETURN FALSE END;
|
|
|
|
+ END;
|
|
|
|
+ character := CHR (CPU.ReadWord (CPU.UART_DR));
|
|
|
|
+ Write (character); RETURN TRUE;
|
|
|
|
+END Read;
|
|
|
|
+
|
|
|
|
+PROCEDURE Flush-;
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ REPEAT UNTIL CPU.TXFE IN CPU.ReadMask (CPU.UART_FR);
|
|
|
|
+END Flush
|
|
|
|
+
|
|
|
|
+PROCEDURE Sleep- (milliseconds: LONGINT);
|
|
|
|
+VAR interrupt: Interrupts.Interrupt;
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ ASSERT (milliseconds >= 0);
|
|
|
|
+ IF CAS (timerInterruptInstalled, 0, 1) = 0 THEN
|
|
|
|
+ previousTimerHandler := CPU.InstallInterrupt (HandleTimer, CPU.IRQ);
|
|
|
|
+ CPU.WriteWord (CPU.STC1, CPU.ReadWord (CPU.STCLO) + 1000);
|
|
|
|
+ CPU.WriteMask (CPU.IRQEnable1, {1});
|
|
|
|
+ END;
|
|
|
|
+ Interrupts.Install (interrupt, CPU.IRQ); INC (milliseconds, clock);
|
|
|
|
+ WHILE clock - milliseconds < 0 DO Interrupts.Await (interrupt) END;
|
|
|
|
+END Sleep;
|
|
|
|
+
|
|
|
|
+PROCEDURE HandleTimer (index: SIZE);
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ IF previousTimerHandler # NIL THEN previousTimerHandler (index) END;
|
|
|
|
+ IF 1 IN CPU.ReadMask (CPU.STCS) THEN
|
|
|
|
+ CPU.WriteWord (CPU.STC1, CPU.ReadWord (CPU.STCLO) + 1000);
|
|
|
|
+ CPU.WriteMask (CPU.STCS, {1}); INC (clock);
|
|
|
|
+ CPU.WriteMask (CPU.IRQEnable1, {1});
|
|
|
|
+ END;
|
|
|
|
+END HandleTimer;
|
|
|
|
+
|
|
|
|
+PROCEDURE LED- (status: BOOLEAN);
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ CPU.Mask (CPU.GPFSEL1, {18});
|
|
|
|
+ IF status THEN CPU.WriteMask (CPU.GPSET1, {15}) ELSE CPU.WriteMask (CPU.GPCLR1, {15}) END;
|
|
|
|
+END LED;
|
|
|
|
+
|
|
|
|
+PROCEDURE Halt*;
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ IF CAS (status, Running, Halting) # Running THEN RETURN END;
|
|
|
|
+ Trace.String ("system: halting..."); Trace.Ln;
|
|
|
|
+ IF uartInterruptInstalled # 0 THEN CPU.WriteMask (CPU.IRQDisable2, {25}); Interrupts.Cancel (uartInterrupt) END;
|
|
|
|
+ IF timerInterruptInstalled # 0 THEN CPU.WriteMask (CPU.IRQDisable1, {1}) END;
|
|
|
|
+END Halt;
|
|
|
|
+
|
|
|
|
+PROCEDURE Reset*;
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ Halt;
|
|
|
|
+ ASSERT (CAS (status, Halting, Resetting) = Halting);
|
|
|
|
+END Reset;
|
|
|
|
+
|
|
|
|
+PROCEDURE {NORETURN} Exit- (status: WORD);
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ Trace.String ("system: ");
|
|
|
|
+ IF status = Resetting THEN Trace.String ("resetting..."); Trace.Ln; Flush; CPU.Reset END;
|
|
|
|
+ Trace.String ("ready for power off or reset"); Trace.Ln; Flush; CPU.Halt;
|
|
|
|
+END Exit;
|
|
|
|
+
|
|
|
|
+PROCEDURE Initialize-;
|
|
|
|
+CONST BaudRate = 115200;
|
|
|
|
+VAR heapStart EXTERN "_heap_start": ADDRESS;
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ SYSTEM.SetActivity (NIL);
|
|
|
|
+ CPU.Initialize; LED (TRUE);
|
|
|
|
+ CPU.WriteMask (CPU.UART_CR, {CPU.UARTEN});
|
|
|
|
+ CPU.Unmask (CPU.GPPUD, {CPU.PUD}); CPU.Delay (150);
|
|
|
|
+ CPU.Mask (CPU.GPPUDCLK0, {14, 15}); CPU.Delay (150);
|
|
|
|
+ CPU.WriteMask (CPU.GPPUDCLK0, {});
|
|
|
|
+ CPU.WriteMask (CPU.UART_ICR, {1, 4..10});
|
|
|
|
+ CPU.WriteWord (CPU.UART_IBRD, CPU.FUARTCLK DIV (16 * BaudRate));
|
|
|
|
+ CPU.WriteWord (CPU.UART_FBRD, (CPU.FUARTCLK MOD (16 * BaudRate)) * 64 DIV (16 * BaudRate));
|
|
|
|
+ CPU.WriteMask (CPU.UART_LCRH, CPU.WLEN8);
|
|
|
|
+ CPU.WriteMask (CPU.UART_IMSC, {CPU.RXIM});
|
|
|
|
+ CPU.WriteMask (CPU.UART_CR, {CPU.UARTEN, CPU.TXE, CPU.RXE});
|
|
|
|
+ CPU.IdentityMapMemory; CPU.EnableMemoryManagementUnit;
|
|
|
|
+ HeapManager.Initialize (heap, heapStart, CPU.MemorySize);
|
|
|
|
+END Initialize;
|
|
|
|
+
|
|
|
|
+PROCEDURE Terminate-;
|
|
|
|
+BEGIN {UNCOOPERATIVE, UNCHECKED}
|
|
|
|
+ Interrupts.Terminate;
|
|
|
|
+ LED (FALSE);
|
|
|
|
+END Terminate;
|
|
|
|
+
|
|
|
|
+BEGIN {UNCHECKED}
|
|
|
|
+ Trace.String ("Version "); Trace.String (SYSTEM.Date); Trace.String (" (");
|
|
|
|
+ Trace.Int (CPU.MemorySize DIV (1024 * 1024), 0); Trace.String (" MB RAM, GC, ");
|
|
|
|
+ Trace.String ("GC, ");
|
|
|
|
+ Trace.Int (Processors.count, 0); Trace.String (" CPU");
|
|
|
|
+ IF Processors.count > 1 THEN Trace.Char ('s') END; Trace.Char (')'); Trace.Ln;
|
|
|
|
+END Environment.
|