Zynq.PsSerials.Mod 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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. recvLock := FALSE : BOOLEAN;
  12. sendLock := FALSE : BOOLEAN;
  13. PROCEDURE & Init (id: LONGINT);
  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 used for trace output *)
  46. PROCEDURE SendChar(char: CHAR; VAR res: WORD);
  47. BEGIN
  48. Machine.AcquireObject(sendLock);
  49. (*! use BusyLoopCallback0 method to make sure no low-level lock is acquired here - required when used as trace output *)
  50. PsUart.SendChar(uart, char, TRUE, BusyLoopCallback0, res);
  51. FINALLY
  52. Machine.ReleaseObject(sendLock);
  53. END SendChar;
  54. (*! This method must not be used for trace output! *)
  55. PROCEDURE Send(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD);
  56. BEGIN
  57. Machine.AcquireObject(sendLock);
  58. PsUart.Send(uart, buf, ofs, len, propagate, BusyLoopCallback, res);
  59. FINALLY
  60. Machine.ReleaseObject(sendLock);
  61. END Send;
  62. PROCEDURE ReceiveChar(VAR char: CHAR; VAR res: WORD);
  63. BEGIN
  64. Machine.AcquireObject(recvLock);
  65. char := PsUart.ReceiveChar(uart, BusyLoopCallback, res);
  66. FINALLY
  67. Machine.ReleaseObject(recvLock);
  68. END ReceiveChar;
  69. PROCEDURE Receive(VAR buf: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len: LONGINT; VAR res: WORD);
  70. BEGIN
  71. Machine.AcquireObject(recvLock);
  72. PsUart.Receive(uart, buf, ofs, size, min, len, BusyLoopCallback, res);
  73. FINALLY
  74. Machine.ReleaseObject(recvLock);
  75. END Receive;
  76. PROCEDURE Available(): LONGINT;
  77. BEGIN{EXCLUSIVE}
  78. RETURN PsUart.Available(uart);
  79. END Available;
  80. PROCEDURE GetPortState(VAR openstat : BOOLEAN; VAR bps, data, parity, stop : LONGINT);
  81. BEGIN{EXCLUSIVE}
  82. openstat := uart.open;
  83. bps := uart.bps;
  84. data := uart.data;
  85. parity := uart.parity;
  86. stop := uart.stop;
  87. END GetPortState;
  88. END Port;
  89. VAR
  90. ports: ARRAY 2 OF Port;
  91. PROCEDURE Init;
  92. VAR
  93. i, clk: LONGINT; res: WORD;
  94. name, desc: ARRAY 32 OF CHAR;
  95. tracePort: LONGINT;
  96. BEGIN
  97. clk := BootConfig.GetIntValue("UartInputClockHz");
  98. FOR i := 0 TO LEN(Platform.UartBase,0)-1 DO
  99. PsUart.Install(i, Platform.UartBase[i], clk, res);
  100. END;
  101. (* if one of PS UART's is used for tracing, make the corresponding port open to allow trace output via PsUartMin *)
  102. tracePort := BootConfig.GetIntValue("TracePort");
  103. IF (tracePort >= 1) & (tracePort <= LEN(Platform.UartBase,0)) THEN
  104. PsUart.Open(PsUart.GetUart(tracePort-1), BootConfig.GetIntValue("TraceBPS"),PsUartMin.DefaultDataBits,PsUartMin.DefaultParity,PsUartMin.DefaultStop, res);
  105. ELSE tracePort := -1;
  106. END;
  107. FOR i := 0 TO LEN(ports) - 1 DO
  108. NEW(ports[i], i);
  109. name := "UART";
  110. Strings.AppendInt(name, i+1);
  111. desc := "Zynq PS UART";
  112. Strings.AppendInt(desc, i);
  113. Serials.RegisterOnboardPort(i+1, ports[i], name, desc);
  114. END;
  115. IF tracePort >= 0 THEN
  116. (* switch from PsUartMin to port-based trace output *)
  117. Serials.SetTracePort(tracePort, BootConfig.GetIntValue("TraceBPS"),PsUartMin.DefaultDataBits,PsUartMin.DefaultParity,PsUartMin.DefaultStop, res);
  118. END;
  119. Modules.InstallTermHandler(Cleanup)
  120. END Init;
  121. PROCEDURE Cleanup;
  122. VAR i: LONGINT;
  123. BEGIN
  124. FOR i := 0 TO LEN(ports) - 1 DO
  125. IF ports[i] # NIL THEN Serials.UnRegisterPort(ports[i]) END
  126. END
  127. END Cleanup;
  128. BEGIN
  129. Init
  130. END PsSerials.