-
Notifications
You must be signed in to change notification settings - Fork 0
/
UARTintStr.mod
130 lines (113 loc) · 3.86 KB
/
UARTintStr.mod
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
MODULE UARTintStr;
(**
Oberon RTK Framework
--
UART string output device driver, using interrupts
For example program: https://oberon-rtk.org/examples/uartint/
--
Copyright (c) 2024 Gray, gray@grayraven.org
https://oberon-rtk.org/licences/
**)
IMPORT SYSTEM, MCU := MCU2, UARTdev, TextIO, LEDext, GPIO, Exceptions;
CONST
PutPinNo = 16;
IntDisablePinNo = 17;
TxFifoLvlPinNo = 18;
AwaitPinNo = 19;
IntMask* = {UARTdev.IMSC_TXIM};
IntPrio = 1;
TxFifoLvl* = UARTdev.TXIFLSEL_val_48;
RxFifoLvl* = UARTdev.RXIFLSEL_val_48;
TYPE
UARTint = RECORD
dev: UARTdev.Device;
strAddr: INTEGER;
numChar: INTEGER;
cnt: INTEGER
END;
VAR
uartInt: ARRAY UARTdev.NumUART OF UARTint;
PROCEDURE txFifoLvl[0];
(* for UART 0 only *)
VAR x: INTEGER; ch: CHAR; (* intStatus: SET; *)
BEGIN
SYSTEM.PUT(MCU.SIO_GPIO_OUT_SET, {TxFifoLvlPinNo});
(*
UARTdev.GetIntStatus(uartInt[0].dev, intStatus);
ASSERT(UARTdev.IMSC_TXIM IN intStatus);
UARTdev.ClearInt(uartInt[0].dev, intStatus);
*)
(* refill fifo from watermark level *)
WHILE (uartInt[0].cnt < uartInt[0].numChar) & ~SYSTEM.BIT(uartInt[0].dev.FR, UARTdev.FR_TXFF) DO
SYSTEM.GET(uartInt[0].strAddr, ch);
SYSTEM.PUT(uartInt[0].dev.TDR, ch);
INC(uartInt[0].cnt);
INC(uartInt[0].strAddr)
END;
x := 0; WHILE x < 200 DO INC(x) END;
SYSTEM.PUT(MCU.SIO_GPIO_OUT_CLR, {TxFifoLvlPinNo});
(* if done, disable int *)
IF uartInt[0].cnt = uartInt[0].numChar THEN
SYSTEM.PUT(MCU.SIO_GPIO_OUT_SET, {IntDisablePinNo});
UARTdev.DisableInt(uartInt[0].dev, {UARTdev.IMSC_TXIM});
x := 0; WHILE x < 200 DO INC(x) END;
SYSTEM.PUT(MCU.SIO_GPIO_OUT_CLR, {IntDisablePinNo});
END
END txFifoLvl;
PROCEDURE InstallIntHandlers*(dev: UARTdev.Device);
VAR en: SET;
BEGIN
uartInt[dev.uartNo].dev := dev;
Exceptions.InstallIntHandler(dev.intNo, txFifoLvl);
Exceptions.SetIntPrio(dev.intNo, IntPrio);
en := {dev.intNo}; (* workaround v9.1 *)
Exceptions.EnableInt(en)
END InstallIntHandlers;
PROCEDURE PutString*(dev: TextIO.Device; s: ARRAY OF CHAR; numChar: INTEGER);
VAR dev0: UARTdev.Device; intStatus: SET; cnt, uartNo, x: INTEGER;
BEGIN
dev0 := dev(UARTdev.Device);
uartNo := dev0.uartNo;
IF numChar > LEN(s) THEN numChar := LEN(s) END;
SYSTEM.PUT(MCU.SIO_GPIO_OUT_CLR, {TxFifoLvlPinNo, IntDisablePinNo, AwaitPinNo});
(* don't interfere with int handler, use int enabled hw flag as sentinel *)
UARTdev.GetEnabledInt(dev0, intStatus);
WHILE UARTdev.IMSC_TXIM IN intStatus DO
SYSTEM.PUT(MCU.SIO_GPIO_OUT_SET, {AwaitPinNo});
UARTdev.GetEnabledInt(dev0, intStatus);
END;
SYSTEM.PUT(MCU.SIO_GPIO_OUT_CLR, {AwaitPinNo});
SYSTEM.PUT(MCU.SIO_GPIO_OUT_SET, {PutPinNo});
(* fill tx fifo *)
cnt := 0;
WHILE (cnt < numChar) & ~SYSTEM.BIT(dev0.FR, UARTdev.FR_TXFF) DO
SYSTEM.PUT(dev0.TDR, s[cnt]);
INC(cnt)
END;
x := 0; WHILE x < 200 DO INC(x) END;
(* if any, leave rest to int handler *)
IF cnt < numChar THEN
uartInt[uartNo].strAddr := SYSTEM.ADR(s[cnt]);
uartInt[uartNo].numChar := numChar;
uartInt[uartNo].cnt := cnt;
UARTdev.EnableInt(dev0, {UARTdev.IMSC_TXIM});
(*
UARTdev.GetEnabledInt(dev0, intStatus);
ASSERT(UARTdev.IMSC_TXIM IN intStatus)
*)
END;
SYSTEM.PUT(MCU.SIO_GPIO_OUT_CLR, {PutPinNo})
END PutString;
PROCEDURE init;
(* test init *)
BEGIN
GPIO.SetFunction(PutPinNo, GPIO.Fsio);
GPIO.SetFunction(TxFifoLvlPinNo, GPIO.Fsio);
GPIO.SetFunction(IntDisablePinNo, GPIO.Fsio);
GPIO.SetFunction(AwaitPinNo, GPIO.Fsio);
GPIO.OutputEnable({PutPinNo, IntDisablePinNo, TxFifoLvlPinNo, AwaitPinNo});
SYSTEM.PUT(MCU.SIO_GPIO_OUT_CLR, {PutPinNo, IntDisablePinNo, TxFifoLvlPinNo, AwaitPinNo})
END init;
BEGIN
init
END UARTintStr.