Zynq.PsSerials.Mod 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. (**
  2. AUTHOR: Timothee Martiel, Alexey Morozov
  3. PURPOSE: A2 Serials interface for Zynq PS UARTs
  4. *)
  5. MODULE PsSerials;
  6. IMPORT Platform, BootConfig, Modules, Strings, PsUartMin, PsUart, Serials, Objects, Machine;
  7. TYPE
  8. Port = OBJECT (Serials.Port)
  9. VAR
  10. uart: PsUart.UartController;
  11. recvLocked := FALSE : BOOLEAN;
  12. sendLocked := FALSE : BOOLEAN;
  13. PROCEDURE & Init (id: PsUart.UartId);
  14. BEGIN
  15. uart := PsUart.GetUart(id);
  16. ASSERT(uart # NIL);
  17. END Init;
  18. PROCEDURE Open (bps, data, parity, stop : LONGINT; VAR res: WORD);
  19. BEGIN{EXCLUSIVE}
  20. PsUart.Open(uart, bps, data, parity, stop, res);
  21. END Open;
  22. PROCEDURE Close;
  23. BEGIN{EXCLUSIVE}
  24. PsUart.Close(uart);
  25. END Close;
  26. PROCEDURE BusyLoopCallback(VAR res: WORD): BOOLEAN;
  27. BEGIN
  28. IF uart.open THEN
  29. Objects.Yield;
  30. RETURN TRUE;
  31. ELSE
  32. res := Serials.Closed;
  33. RETURN FALSE;
  34. END;
  35. END BusyLoopCallback;
  36. PROCEDURE BusyLoopCallback0(VAR res: WORD): BOOLEAN;
  37. BEGIN
  38. IF uart.open THEN
  39. RETURN TRUE;
  40. ELSE
  41. res := Serials.Closed;
  42. RETURN FALSE;
  43. END;
  44. END BusyLoopCallback0;
  45. (* This method can be safely used for trace output *)
  46. PROCEDURE SendChar(char: CHAR; VAR res: WORD);
  47. BEGIN
  48. (*! use BusyLoopCallback0 method to make sure no low-level lock is acquired here - required when used as trace output *)
  49. PsUart.SendChar(uart, char, TRUE, BusyLoopCallback0, res);
  50. END SendChar;
  51. (*! This method must not be used for trace output - danger of a dead lock! *)
  52. PROCEDURE Send(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD);
  53. BEGIN
  54. Machine.AcquireObject(sendLocked);
  55. PsUart.Send(uart, buf, ofs, len, propagate, BusyLoopCallback, res);
  56. FINALLY
  57. Machine.ReleaseObject(sendLocked);
  58. END Send;
  59. PROCEDURE ReceiveChar(VAR char: CHAR; VAR res: WORD);
  60. BEGIN
  61. Machine.AcquireObject(recvLocked);
  62. char := PsUart.ReceiveChar(uart, BusyLoopCallback, res);
  63. FINALLY
  64. Machine.ReleaseObject(recvLocked);
  65. END ReceiveChar;
  66. PROCEDURE Receive(VAR buf: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len: LONGINT; VAR res: WORD);
  67. BEGIN
  68. Machine.AcquireObject(recvLocked);
  69. PsUart.Receive(uart, buf, ofs, size, min, len, BusyLoopCallback, res);
  70. FINALLY
  71. Machine.ReleaseObject(recvLocked);
  72. END Receive;
  73. PROCEDURE Available(): LONGINT;
  74. BEGIN
  75. RETURN PsUart.Available(uart);
  76. END Available;
  77. PROCEDURE GetPortState(VAR openstat : BOOLEAN; VAR bps, data, parity, stop : LONGINT);
  78. BEGIN{EXCLUSIVE}
  79. openstat := uart.open;
  80. bps := uart.bps;
  81. data := uart.data;
  82. parity := uart.parity;
  83. stop := uart.stop;
  84. END GetPortState;
  85. END Port;
  86. VAR
  87. ports: ARRAY 2 OF Port;
  88. PROCEDURE Init;
  89. VAR
  90. i: SIZE;
  91. clk: PsUart.ClockFrequency; res: WORD;
  92. name, desc: ARRAY 32 OF CHAR;
  93. tracePort: SIZE;
  94. BEGIN
  95. clk := BootConfig.GetIntValue("UartInputClockHz");
  96. FOR i := 0 TO LEN(Platform.UartBase,0)-1 DO
  97. PsUart.Install(i, Platform.UartBase[i], clk, res);
  98. END;
  99. (* if one of PS UART's is used for tracing, make the corresponding port open to allow trace output via PsUartMin *)
  100. tracePort := BootConfig.GetIntValue("TracePort");
  101. IF (tracePort >= 1) & (tracePort <= LEN(Platform.UartBase,0)) THEN
  102. PsUart.Open(PsUart.GetUart(tracePort-1), BootConfig.GetIntValue("TraceBPS"),PsUartMin.DefaultDataBits,PsUartMin.DefaultParity,PsUartMin.DefaultStop, res);
  103. ELSE tracePort := -1;
  104. END;
  105. FOR i := 0 TO LEN(ports) - 1 DO
  106. NEW(ports[i], i);
  107. name := "UART";
  108. Strings.AppendInt(name, i+1);
  109. desc := "Zynq PS UART";
  110. Strings.AppendInt(desc, i);
  111. Serials.RegisterOnboardPort(i+1, ports[i], name, desc);
  112. END;
  113. IF tracePort >= 0 THEN
  114. (* switch from PsUartMin to port-based trace output *)
  115. Serials.SetTracePort(tracePort, BootConfig.GetIntValue("TraceBPS"),PsUartMin.DefaultDataBits,PsUartMin.DefaultParity,PsUartMin.DefaultStop, res);
  116. END;
  117. Modules.InstallTermHandler(Cleanup)
  118. END Init;
  119. PROCEDURE Cleanup;
  120. VAR i: SIZE;
  121. BEGIN
  122. FOR i := 0 TO LEN(ports) - 1 DO
  123. IF ports[i] # NIL THEN Serials.UnRegisterPort(ports[i]) END
  124. END
  125. END Cleanup;
  126. BEGIN
  127. Init
  128. END PsSerials.