Zynq.Uart.Mos 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. MODULE Uart;
  2. (**
  3. AUTHOR: Alexey Morozov, HighDim GmbH, 2013
  4. PURPOSE: implementation of the driver for Xilinx Zynq UART PS controller
  5. *)
  6. IMPORT
  7. SYSTEM, Platform := MinosPlatform;
  8. CONST
  9. DefaultBaudrate* = 115200; (** defauilt UART baudrate *)
  10. (*! TO BE REMOVED (BEGIN) a workaround for problem with linking Platform (duplicated section) *)
  11. UartBaseAddr* = [ADDRESS(0E0000000H),ADDRESS(0E0001000H)]; (* base address for all UART controllers present in the system *)
  12. UartModemPinsConnected* = [FALSE,FALSE];
  13. (*! TO BE REMOVED (END) *)
  14. (** Register offsets for the UART controller *)
  15. XUARTPS_CR_OFFSET = 000H; (** Control Register [8:0] *)
  16. XUARTPS_MR_OFFSET = 004H; (* Mode Register [9:0] *)
  17. XUARTPS_IER_OFFSET = 008H; (* Interrupt Enable [12:0] *)
  18. XUARTPS_IDR_OFFSET = 00CH; (* Interrupt Disable [12:0] *)
  19. XUARTPS_IMR_OFFSET = 010H; (* Interrupt Mask [12:0] *)
  20. XUARTPS_ISR_OFFSET = 014H; (* Interrupt Status [12:0]*)
  21. XUARTPS_BAUDGEN_OFFSET = 018H; (* Baud Rate Generator [15:0] *)
  22. XUARTPS_RXTOUT_OFFSET = 01CH; (* RX Timeout [7:0] *)
  23. XUARTPS_RXWM_OFFSET = 020H; (* RX FIFO Trigger Level [5:0] *)
  24. XUARTPS_MODEMCR_OFFSET = 024H; (* Modem Control [5:0] *)
  25. XUARTPS_MODEMSR_OFFSET = 028H; (* Modem Status [8:0] *)
  26. XUARTPS_SR_OFFSET = 02CH; (* Channel Status [14:0] *)
  27. XUARTPS_FIFO_OFFSET = 030H; (* FIFO [7:0] *)
  28. XUARTPS_BAUDDIV_OFFSET = 034H; (* Baud Rate Divider [7:0] *)
  29. XUARTPS_FLOWDEL_OFFSET = 038H; (* Flow Delay [5:0] *)
  30. XUARTPS_TXWM_OFFSET = 044H; (* TX FIFO Trigger Level [5:0] *)
  31. (* Control Register Bit Definition
  32. The Control register (CR) controls the major functions of the device.
  33. *)
  34. XUARTPS_CR_STOPBRK = 000000100H; (* Stop transmission of break *)
  35. XUARTPS_CR_STARTBRK = 000000080H; (* Set break *)
  36. XUARTPS_CR_TORST = 000000040H; (* RX timeout counter restart *)
  37. XUARTPS_CR_TX_DIS = 000000020H; (* TX disabled. *)
  38. XUARTPS_CR_TX_EN = 000000010H; (* TX enabled *)
  39. XUARTPS_CR_RX_DIS = 000000008H; (* RX disabled. *)
  40. XUARTPS_CR_RX_EN = 000000004H; (* RX enabled *)
  41. XUARTPS_CR_EN_DIS_MASK = 00000003CH; (* Enable/disable Mask *)
  42. XUARTPS_CR_TXRST = 000000002H; (* TX logic reset *)
  43. XUARTPS_CR_RXRST = 000000001H; (* RX logic reset *)
  44. (* Mode Register Bit Definition
  45. The mode register (MR) defines the mode of transfer as well as the data
  46. format. If this register is modified during transmission or reception,
  47. data validity cannot be guaranteed.
  48. *)
  49. XUARTPS_MR_CCLK = 000000400H; (* Input clock selection *)
  50. XUARTPS_MR_CHMODE_R_LOOP = 000000300H; (* Remote loopback mode *)
  51. XUARTPS_MR_CHMODE_L_LOOP = 000000200H; (* Local loopback mode *)
  52. XUARTPS_MR_CHMODE_ECHO = 000000100H; (* Auto echo mode *)
  53. XUARTPS_MR_CHMODE_NORM = 000000000H; (* Normal mode *)
  54. XUARTPS_MR_CHMODE_SHIFT = 8; (* Mode shift *)
  55. XUARTPS_MR_CHMODE_MASK = 000000300H; (* Mode mask *)
  56. XUARTPS_MR_STOPMODE_2_BIT = 000000080H; (* 2 stop bits *)
  57. XUARTPS_MR_STOPMODE_1_5_BIT = 000000040H; (* 1.5 stop bits *)
  58. XUARTPS_MR_STOPMODE_1_BIT = 000000000H; (* 1 stop bit *)
  59. XUARTPS_MR_STOPMODE_SHIFT = 6; (* Stop bits shift *)
  60. XUARTPS_MR_STOPMODE_MASK = 0000000A0H; (* Stop bits mask *)
  61. XUARTPS_MR_PARITY_NONE = 000000020H; (* No parity mode *)
  62. XUARTPS_MR_PARITY_MARK = 000000018H; (* Mark parity mode *)
  63. XUARTPS_MR_PARITY_SPACE = 000000010H; (* Space parity mode *)
  64. XUARTPS_MR_PARITY_ODD = 000000008H; (* Odd parity mode *)
  65. XUARTPS_MR_PARITY_EVEN = 000000000H; (* Even parity mode *)
  66. XUARTPS_MR_PARITY_SHIFT = 3; (* Parity setting shift *)
  67. XUARTPS_MR_PARITY_MASK = 000000038H; (* Parity mask *)
  68. XUARTPS_MR_CHARLEN_6_BIT = 000000006H; (* 6 bits data *)
  69. XUARTPS_MR_CHARLEN_7_BIT = 000000004H; (* 7 bits data *)
  70. XUARTPS_MR_CHARLEN_8_BIT = 000000000H; (* 8 bits data *)
  71. XUARTPS_MR_CHARLEN_SHIFT = 1; (* Data Length shift *)
  72. XUARTPS_MR_CHARLEN_MASK = 000000006H; (* Data length mask *)
  73. XUARTPS_MR_CLKSEL = 000000001H; (* Input clock selection *)
  74. (** Interrupt Registers
  75. Interrupt control logic uses the interrupt enable register (IER) and the
  76. interrupt disable register (IDR) to set the value of the bits in the
  77. interrupt mask register (IMR). The IMR determines whether to pass an
  78. interrupt to the interrupt status register (ISR).
  79. Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an
  80. interrupt. IMR and ISR are read only, and IER and IDR are write only.
  81. Reading either IER or IDR returns 0x00.
  82. All four registers have the same bit definitions.
  83. *)
  84. XUARTPS_IXR_TOVR = 000001000H; (** Tx FIFO Overflow interrupt *)
  85. XUARTPS_IXR_TNFUL = 000000800H; (** Tx FIFO Nearly Full interrupt *)
  86. XUARTPS_IXR_TTRIG = 000000400H; (** Tx Trig interrupt *)
  87. XUARTPS_IXR_DMS = 000000200H; (** Modem status change interrupt *)
  88. XUARTPS_IXR_TOUT = 000000100H; (** Timeout error interrupt *)
  89. XUARTPS_IXR_PARITY = 000000080H; (** Parity error interrupt *)
  90. XUARTPS_IXR_FRAMING = 000000040H; (** Framing error interrupt *)
  91. XUARTPS_IXR_OVER = 000000020H; (** Overrun error interrupt *)
  92. XUARTPS_IXR_TXFULL = 000000010H; (** TX FIFO full interrupt. *)
  93. XUARTPS_IXR_TXEMPTY = 000000008H; (** TX FIFO empty interrupt. *)
  94. XUARTPS_IXR_RXFULL = 000000004H; (** RX FIFO full interrupt. *)
  95. XUARTPS_IXR_RXEMPTY = 000000002H; (** RX FIFO empty interrupt. *)
  96. XUARTPS_IXR_RXOVR = 000000001H; (** RX FIFO trigger interrupt. *)
  97. XUARTPS_IXR_MASK = 000001FFFH; (** Valid bit mask *)
  98. (** Channel Status Register
  99. The channel status register (CSR) is provided to enable the control logic
  100. to monitor the status of bits in the channel interrupt status register,
  101. even if these are masked out by the interrupt mask register.
  102. *)
  103. XUARTPS_SR_TNFUL = 000004000H; (** TX FIFO Nearly Full Status *)
  104. XUARTPS_SR_TTRIG = 000002000H; (** TX FIFO Trigger Status *)
  105. XUARTPS_SR_FLOWDEL = 000001000H; (** RX FIFO fill over flow delay *)
  106. XUARTPS_SR_TACTIVE = 000000800H; (** TX active *)
  107. XUARTPS_SR_RACTIVE = 000000400H; (** RX active *)
  108. XUARTPS_SR_DMS = 000000200H; (** Delta modem status change *)
  109. XUARTPS_SR_TOUT = 000000100H; (** RX timeout *)
  110. XUARTPS_SR_PARITY = 000000080H; (** RX parity error *)
  111. XUARTPS_SR_FRAME = 000000040H; (** RX frame error *)
  112. XUARTPS_SR_OVER = 000000020H; (** RX overflow error *)
  113. XUARTPS_SR_TXFULL = 000000010H; (** TX FIFO full *)
  114. XUARTPS_SR_TXEMPTY = 000000008H; (** TX FIFO empty *)
  115. XUARTPS_SR_RXFULL = 000000004H; (** RX FIFO full *)
  116. XUARTPS_SR_RXEMPTY = 000000002H; (** RX FIFO empty *)
  117. XUARTPS_SR_RXOVR = 000000001H; (** RX FIFO fill over trigger *)
  118. (* The following constant defines the amount of error that is allowed for
  119. a specified baud rate. This error is the difference between the actual
  120. baud rate that will be generated using the specified clock and the
  121. desired baud rate.
  122. *)
  123. XUARTPS_MAX_BAUD_ERROR_RATE = 3; (* max % error allowed *)
  124. TYPE
  125. (** Configuration information about a controller used for initializing UartPs controller *)
  126. UartPsCfg* = RECORD
  127. baseAddr*: ADDRESS; (** base address *)
  128. inputClockHz*: LONGINT; (** controller input clock rate in Hz *)
  129. modemPinsConnected*: BOOLEAN; (** TRUE if modem pins connected via MIO or EMIO *)
  130. END;
  131. (** UART controller descriptor *)
  132. Uart* = RECORD
  133. cfg-: UartPsCfg;
  134. baudrate-: LONGINT; (** current baudrate value *)
  135. intrEnabled-: BOOLEAN; (** TRUE if TX/RX interrupt handling is enabled, FALSE by default *)
  136. END;
  137. UartPtr* = POINTER TO Uart;
  138. VAR
  139. uarts-: ARRAY 2 OF UartPtr; (*uarts-: POINTER TO ARRAY OF UartPtr;*) (*! array allocation is not yet supported *)
  140. (**
  141. Initialize a UART controller given its configuration information
  142. *)
  143. PROCEDURE Init*(VAR uart: Uart; CONST cfg: UartPsCfg);
  144. VAR
  145. res: LONGINT;
  146. BEGIN
  147. uart.cfg := cfg;
  148. (* disable all UART interrupts *)
  149. SYSTEM.PUT32(uart.cfg.baseAddr+XUARTPS_IDR_OFFSET,0FFFFFFFFH);
  150. uart.intrEnabled := FALSE;
  151. (* Set the default baudrate *)
  152. SetBaudrate(uart,DefaultBaudrate,res);
  153. END Init;
  154. (**
  155. Set UART baudrate
  156. res: error code, 0 in case of success
  157. *)
  158. PROCEDURE SetBaudrate*(VAR uart: Uart; CONST baudrate: LONGINT; VAR res: LONGINT);
  159. VAR
  160. reg: SET;
  161. inputClk: LONGINT;
  162. valBAUDDIV, valBRGR, calcBaudrate, baudError: LONGINT;
  163. bestError, bestBRGR, bestBAUDDIV: LONGINT;
  164. BEGIN
  165. (*
  166. Make sure the baud rate is not impossilby large.
  167. Fastest possible baud rate is Input Clock / 2
  168. *)
  169. IF baudrate*2 > uart.cfg.inputClockHz THEN res := 1; RETURN; END;
  170. inputClk := uart.cfg.inputClockHz;
  171. (* Check whether the input clock is divided by 8 *)
  172. reg := SYSTEM.VAL(SET,SYSTEM.GET32(uart.cfg.baseAddr+XUARTPS_MR_OFFSET));
  173. IF XUARTPS_MR_CLKSEL IN reg THEN
  174. inputClk := inputClk DIV 8;
  175. END;
  176. (* Determine the Baud divider. It can be 4 to 254.
  177. Loop through all possible combinations *)
  178. bestError := MAX(LONGINT);
  179. FOR valBAUDDIV := 4 TO 255 DO
  180. (* Calculate the value for BRGR register *)
  181. valBRGR := inputClk DIV (baudrate * (valBAUDDIV + 1));
  182. (* Calculate the baud rate from the BRGR value *)
  183. calcBaudrate := inputClk DIV (valBRGR * (valBAUDDIV + 1));
  184. (* Avoid unsigned integer underflow *)
  185. IF baudrate > calcBaudrate THEN
  186. baudError := baudrate - calcBaudrate;
  187. ELSE
  188. baudError := calcBaudrate - baudrate;
  189. END;
  190. (*
  191. Find the calculated baud rate closest to requested baud rate.
  192. *)
  193. IF baudError < bestError THEN
  194. bestBRGR := valBRGR;
  195. bestBAUDDIV := valBAUDDIV;
  196. bestError := baudError;
  197. END;
  198. INC(valBAUDDIV);
  199. END;
  200. (*
  201. Make sure the best error is not too large.
  202. *)
  203. IF (bestError * 100) DIV baudrate > XUARTPS_MAX_BAUD_ERROR_RATE THEN (* baudrate error *)
  204. res := 1; RETURN;
  205. END;
  206. (*
  207. Disable TX and RX to avoid glitches when setting the baud rate.
  208. *)
  209. Enable(uart,FALSE);
  210. (* write baudrate settings *)
  211. SYSTEM.PUT32(uart.cfg.baseAddr+XUARTPS_BAUDGEN_OFFSET,bestBRGR);
  212. SYSTEM.PUT32(uart.cfg.baseAddr+XUARTPS_BAUDDIV_OFFSET,bestBAUDDIV);
  213. Enable(uart,TRUE);
  214. uart.baudrate := baudrate;
  215. END SetBaudrate;
  216. (** Enable/Disable the transmitter and receiver of the UART *)
  217. PROCEDURE Enable*(CONST uart: Uart; enable: BOOLEAN);
  218. VAR reg: SET;
  219. BEGIN
  220. reg := SYSTEM.VAL(SET,SYSTEM.GET32(uart.cfg.baseAddr+XUARTPS_CR_OFFSET)) - SYSTEM.VAL(SET,XUARTPS_CR_EN_DIS_MASK);
  221. IF enable THEN
  222. reg := reg + SYSTEM.VAL(SET,XUARTPS_CR_RX_EN) + SYSTEM.VAL(SET,XUARTPS_CR_TX_EN);
  223. ELSE
  224. reg := reg + SYSTEM.VAL(SET,XUARTPS_CR_RX_DIS) + SYSTEM.VAL(SET,XUARTPS_CR_TX_DIS);
  225. END;
  226. SYSTEM.PUT32(uart.cfg.baseAddr+XUARTPS_CR_OFFSET,reg);
  227. END Enable;
  228. (**
  229. Send data to the UART
  230. *)
  231. PROCEDURE Send*(CONST uart: Uart; CONST buf: ARRAY OF CHAR; offs, len: LONGINT; propagate: BOOLEAN; VAR res: LONGINT);
  232. VAR csr: SET;
  233. BEGIN
  234. res := 0;
  235. IF uart.intrEnabled THEN
  236. (*
  237. Disable the UART transmit interrupts to allow this call to stop a
  238. previous operation that may be interrupt driven.
  239. *)
  240. SYSTEM.PUT32(uart.cfg.baseAddr+XUARTPS_IDR_OFFSET,XUARTPS_IXR_TXEMPTY+XUARTPS_IXR_TXFULL);
  241. HALT(100); (*! Not yet implemented! *)
  242. ELSE
  243. WHILE len > 0 DO
  244. csr := SYSTEM.VAL(SET,SYSTEM.GET32(uart.cfg.baseAddr+XUARTPS_SR_OFFSET)); (* current state of Channel Status Register *)
  245. IF csr * SYSTEM.VAL(SET,XUARTPS_SR_TXFULL) # SYSTEM.VAL(SET,XUARTPS_SR_TXFULL) THEN (* there is place for at minimum one byte in TX FIFO *)
  246. SYSTEM.PUT32(uart.cfg.baseAddr+XUARTPS_FIFO_OFFSET,ORD(buf[offs]));
  247. INC(offs); DEC(len);
  248. IF (len > 0) & (csr * SYSTEM.VAL(SET,XUARTPS_SR_TNFUL) # SYSTEM.VAL(SET,XUARTPS_SR_TNFUL)) THEN (* there is place for at minimum two bytes in TX FIFO *)
  249. SYSTEM.PUT32(uart.cfg.baseAddr+XUARTPS_FIFO_OFFSET,ORD(buf[offs]));
  250. INC(offs); DEC(len);
  251. END;
  252. END;
  253. END;
  254. END;
  255. END Send;
  256. (**
  257. Receive data from the UART
  258. *)
  259. PROCEDURE Receive*(CONST uart: Uart; VAR buf: ARRAY OF CHAR; offs, size, min: LONGINT; VAR len, res: LONGINT);
  260. BEGIN
  261. res := 0;
  262. len := 0;
  263. min := MIN(size,min);
  264. WHILE (min > 0) OR (Available(uart) > 0) DO
  265. WHILE (size > 0) & (SYSTEM.VAL(SET,SYSTEM.GET32(uart.cfg.baseAddr+XUARTPS_SR_OFFSET)) * SYSTEM.VAL(SET,XUARTPS_SR_RXEMPTY) # SYSTEM.VAL(SET,XUARTPS_SR_RXEMPTY)) DO
  266. buf[offs] := CHR(SYSTEM.GET32(uart.cfg.baseAddr+XUARTPS_FIFO_OFFSET));
  267. DEC(min); DEC(size); INC(offs); INC(len);
  268. END;
  269. END;
  270. END Receive;
  271. (** Send a single character to the UART
  272. Remarks:
  273. blocks until the transmit buffer is not full
  274. *)
  275. PROCEDURE SendChar*(CONST uart: Uart; ch: CHAR; VAR res: LONGINT);
  276. BEGIN
  277. (* Wait until there is space in TX FIFO *)
  278. WHILE SYSTEM.VAL(SET,SYSTEM.GET32(uart.cfg.baseAddr+XUARTPS_SR_OFFSET)) * SYSTEM.VAL(SET,XUARTPS_SR_TXFULL) = SYSTEM.VAL(SET,XUARTPS_SR_TXFULL) DO
  279. END;
  280. (* Write the byte into the TX FIFO *)
  281. SYSTEM.PUT32(uart.cfg.baseAddr+XUARTPS_FIFO_OFFSET,ORD(ch));
  282. END SendChar;
  283. (** Receive a single character from UART
  284. Remarks:
  285. blocks until a character is available
  286. *)
  287. PROCEDURE ReceiveChar*(CONST uart: Uart; VAR res: LONGINT): CHAR;
  288. BEGIN
  289. (* wait until data is available *)
  290. WHILE SYSTEM.VAL(SET,SYSTEM.GET32(uart.cfg.baseAddr+XUARTPS_SR_OFFSET)) * SYSTEM.VAL(SET,XUARTPS_SR_RXEMPTY) = SYSTEM.VAL(SET,XUARTPS_SR_RXEMPTY) DO
  291. END;
  292. RETURN CHR(SYSTEM.GET32(uart.cfg.baseAddr+XUARTPS_FIFO_OFFSET));
  293. END ReceiveChar;
  294. (** Returns number of bytes available in the receive buffer *)
  295. PROCEDURE Available*(CONST uart: Uart): LONGINT;
  296. BEGIN
  297. IF uart.intrEnabled THEN
  298. HALT(100); (*! Not yet implemented! *)
  299. ELSIF SYSTEM.VAL(SET,SYSTEM.GET32(uart.cfg.baseAddr+XUARTPS_SR_OFFSET)) * SYSTEM.VAL(SET,XUARTPS_SR_RXEMPTY) # SYSTEM.VAL(SET,XUARTPS_SR_RXEMPTY) THEN
  300. RETURN 1;
  301. ELSE
  302. RETURN 0;
  303. END;
  304. END Available;
  305. (**
  306. Install all UART controllers present in the system (according to the constants set in Platform); to be called by the Kernel
  307. *)
  308. PROCEDURE Install*;
  309. VAR
  310. cfg: UartPsCfg;
  311. i, res: LONGINT;
  312. BEGIN
  313. (*NEW(uarts,LEN(Platform.UartBaseAddr,0));*) (*! array allocation is not yet supported *)
  314. FOR i := 0 TO LEN((*Platform.*)UartBaseAddr,0)-1 DO
  315. NEW(uarts[i]);
  316. cfg.baseAddr := (*Platform.*)UartBaseAddr[i];
  317. cfg.inputClockHz := Platform.UartInputClockHz;
  318. cfg.modemPinsConnected := (*Platform.*)UartModemPinsConnected[i];
  319. Init(uarts[i]^,cfg);
  320. SetBaudrate(uarts[i]^,115200,res);
  321. Enable(uarts[i]^,FALSE); (* disable *)
  322. END;
  323. (* enable only UART used for kernel output *)
  324. IF Platform.KernelOutputUart >= 0 THEN
  325. Enable(uarts[Platform.KernelOutputUart]^,TRUE);
  326. END;
  327. END Install;
  328. END Uart.