Zynq.PsUartMin.Mod 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. MODULE PsUartMin;
  2. (**
  3. AUTHOR: Alexey Morozov, Timothee Martiel, HighDim GmbH, 2013-2017
  4. PURPOSE: minimal driver implementation for Xilinx Zynq UART PS controller
  5. *)
  6. IMPORT SYSTEM;
  7. CONST
  8. (** Parity types - compatible with A2 Serials *)
  9. ParNo* = 0; ParOdd* = 1; ParEven* = 2; ParMark* = 3; ParSpace* = 4;
  10. (** Stop bits - compatible with A2 Serials *)
  11. Stop1* = 1; Stop2* = 2; Stop1dot5* = 3;
  12. (** Error codes - compatible with A2 Serials *)
  13. Ok* = 0;
  14. Closed* = -1;
  15. PortInUse* = 1; NoSuchPort* = 2; WrongBPS* = 3; WrongData* = 4; WrongParity* = 5; WrongStop* = 6;
  16. (* Default settings *)
  17. DefaultBPS* = 115200; DefaultDataBits* = 8; DefaultParity* = ParNo; DefaultStop* = Stop1;
  18. NumUarts* = 2; (** number of supported UART controllers *)
  19. (* Control Register Bit Definition
  20. The Control register (CR) controls the major functions of the device.
  21. *)
  22. XUARTPS_CR_STOPBRK* = 8; (* Stop transmission of break *)
  23. XUARTPS_CR_STARTBRK* = 7; (* Set break *)
  24. XUARTPS_CR_TORST* = 6; (* RX timeout counter restart *)
  25. XUARTPS_CR_TX_DIS* = 5; (* TX disabled. *)
  26. XUARTPS_CR_TX_EN* = 4; (* TX enabled *)
  27. XUARTPS_CR_RX_DIS* = 3; (* RX disabled. *)
  28. XUARTPS_CR_RX_EN* = 2; (* RX enabled *)
  29. XUARTPS_CR_EN_DIS_MASK* = {2..5}; (* Enable/disable Mask *)
  30. XUARTPS_CR_TXRST* = 1; (* TX logic reset *)
  31. XUARTPS_CR_RXRST* = 0; (* RX logic reset *)
  32. (* Mode Register Bit Definition
  33. The mode register (MR) defines the mode of transfer as well as the data
  34. format. If this register is modified during transmission or reception,
  35. data validity cannot be guaranteed.
  36. *)
  37. XUARTPS_MR_CHMODE_R_LOOP = {8,9}; (* Remote loopback mode *)
  38. XUARTPS_MR_CHMODE_L_LOOP = {9}; (* Local loopback mode *)
  39. XUARTPS_MR_CHMODE_ECHO = {8}; (* Auto echo mode *)
  40. XUARTPS_MR_CHMODE_NORM = {}; (* Normal mode *)
  41. XUARTPS_MR_CHMODE_SHIFT = 8; (* Mode shift *)
  42. XUARTPS_MR_CHMODE_MASK = {8..9}; (* Mode mask *)
  43. XUARTPS_MR_STOPMODE_2 = {7}; (* 2 stop bits *)
  44. XUARTPS_MR_STOPMODE_1_5 = {6}; (* 1.5 stop bits *)
  45. XUARTPS_MR_STOPMODE_1 = {}; (* 1 stop bit *)
  46. XUARTPS_MR_STOPMODE_SHIFT = 6; (* Stop bits shift *)
  47. XUARTPS_MR_STOPMODE_MASK = {6..7}; (* Stop bits mask *)
  48. XUARTPS_MR_PARITY_NONE = {5}; (* No parity mode *)
  49. XUARTPS_MR_PARITY_MARK = {3,4}; (* Mark parity mode *)
  50. XUARTPS_MR_PARITY_SPACE = {4}; (* Space parity mode *)
  51. XUARTPS_MR_PARITY_ODD = {3}; (* Odd parity mode *)
  52. XUARTPS_MR_PARITY_EVEN = {}; (* Even parity mode *)
  53. XUARTPS_MR_PARITY_SHIFT = 3; (* Parity setting shift *)
  54. XUARTPS_MR_PARITY_MASK = {3..5}; (* Parity mask *)
  55. XUARTPS_MR_CHARLEN_6 = {1,2}; (* 6 bits data *)
  56. XUARTPS_MR_CHARLEN_7 = {2}; (* 7 bits data *)
  57. XUARTPS_MR_CHARLEN_8 = {}; (* 8 bits data *)
  58. XUARTPS_MR_CHARLEN_SHIFT = 1; (* Data Length shift *)
  59. XUARTPS_MR_CHARLEN_MASK = {1..2}; (* Data length mask *)
  60. XUARTPS_MR_CLKSEL_BIT = 0; (* Input clock selection *)
  61. (** Interrupt Registers
  62. Interrupt control logic uses the interrupt enable register (IER) and the
  63. interrupt disable register (IDR) to set the value of the bits in the
  64. interrupt mask register (IMR). The IMR determines whether to pass an
  65. interrupt to the interrupt status register (ISR).
  66. Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an
  67. interrupt. IMR and ISR are read only, and IER and IDR are write only.
  68. Reading either IER or IDR returns 0x00.
  69. All four registers have the same bit definitions.
  70. *)
  71. XUARTPS_IXR_RBRK = 13; (** Rx FIFO break detect interrupt *)
  72. XUARTPS_IXR_TOVR* = 12; (** Tx FIFO Overflow interrupt *)
  73. XUARTPS_IXR_TNFUL* = 11; (** Tx FIFO Nearly Full interrupt *)
  74. XUARTPS_IXR_TTRIG* = 10; (** Tx Trig interrupt *)
  75. XUARTPS_IXR_DMS* = 9; (** Modem status change interrupt *)
  76. XUARTPS_IXR_TOUT* = 8; (** Timeout error interrupt *)
  77. XUARTPS_IXR_PARITY* = 7; (** Parity error interrupt *)
  78. XUARTPS_IXR_FRAMING* = 6; (** Framing error interrupt *)
  79. XUARTPS_IXR_OVER* = 5; (** Overrun error interrupt *)
  80. XUARTPS_IXR_TXFULL* = 4; (** TX FIFO full interrupt. *)
  81. XUARTPS_IXR_TXEMPTY* = 3; (** TX FIFO empty interrupt. *)
  82. XUARTPS_IXR_RXFULL* = 2; (** RX FIFO full interrupt. *)
  83. XUARTPS_IXR_RXEMPTY* = 1; (** RX FIFO empty interrupt. *)
  84. XUARTPS_IXR_RXOVR* = 0; (** RX FIFO trigger interrupt. *)
  85. XUARTPS_IXR_MASK* = {0..13}; (** Valid bit mask *)
  86. (** Channel Status Register
  87. The channel status register (CSR) is provided to enable the control logic
  88. to monitor the status of bits in the channel interrupt status register,
  89. even if these are masked out by the interrupt mask register.
  90. *)
  91. XUARTPS_SR_TNFUL* = 14; (** TX FIFO Nearly Full Status *)
  92. XUARTPS_SR_TTRIG* = 13; (** TX FIFO Trigger Status *)
  93. XUARTPS_SR_FLOWDEL* = 12; (** RX FIFO fill over flow delay *)
  94. XUARTPS_SR_TACTIVE* = 11; (** TX active *)
  95. XUARTPS_SR_RACTIVE* = 10; (** RX active *)
  96. XUARTPS_SR_DMS* = 9; (** Delta modem status change *)
  97. XUARTPS_SR_TOUT* = 8; (** RX timeout *)
  98. XUARTPS_SR_PARITY* = 7; (** RX parity error *)
  99. XUARTPS_SR_FRAME* = 6; (** RX frame error *)
  100. XUARTPS_SR_OVER* = 5; (** RX overflow error *)
  101. XUARTPS_SR_TXFULL* = 4; (** TX FIFO full *)
  102. XUARTPS_SR_TXEMPTY* = 3; (** TX FIFO empty *)
  103. XUARTPS_SR_RXFULL* = 2; (** RX FIFO full *)
  104. XUARTPS_SR_RXEMPTY* = 1; (** RX FIFO empty *)
  105. XUARTPS_SR_RXOVR* = 0; (** RX FIFO fill over trigger *)
  106. (*
  107. Modem Control register
  108. *)
  109. XUARTPS_MODEMCR_FCM = 5;
  110. XUARTPS_MODEMCR_RTS = 1;
  111. XUARTPS_MODEMCR_DTR = 0;
  112. (*
  113. Modem Status register
  114. *)
  115. XUARTPS_MODEMSR_FCMS = 8;
  116. XUARTPS_MODEMSR_DCD = 7;
  117. XUARTPS_MODEMSR_RI = 6;
  118. XUARTPS_MODEMSR_DSR = 5;
  119. XUARTPS_MODEMSR_CTS = 4;
  120. XUARTPS_MODEMSR_DCDX = 3;
  121. XUARTPS_MODEMSR_RIX = 2;
  122. XUARTPS_MODEMSR_DSRX = 1;
  123. XUARTPS_MODEMSR_CTSX = 0;
  124. (* The following constant defines the amount of error that is allowed for
  125. a specified baud rate. This error is the difference between the actual
  126. baud rate that will be generated using the specified clock and the
  127. desired baud rate.
  128. *)
  129. XUARTPS_MAX_BAUD_ERROR_RATE = 3; (* max % error allowed *)
  130. TYPE
  131. (*
  132. (* Register offsets for the UART controller *)
  133. XUARTPS_CR_OFFSET = 0x0000; (* Control Register [8:0] *)
  134. XUARTPS_MR_OFFSET = 0x0004; (* Mode Register [9:0] *)
  135. XUARTPS_IER_OFFSET = 0x0008; (* Interrupt Enable [12:0] *)
  136. XUARTPS_IDR_OFFSET = 0x000C; (* Interrupt Disable [12:0] *)
  137. XUARTPS_IMR_OFFSET = 0x0010; (* Interrupt Mask [12:0] *)
  138. XUARTPS_ISR_OFFSET = 0x0014; (* Interrupt Status [12:0]*)
  139. XUARTPS_BAUDGEN_OFFSET = 0x0018; (* Baud Rate Generator [15:0] *)
  140. XUARTPS_RXTOUT_OFFSET = 0x001C; (* RX Timeout [7:0] *)
  141. XUARTPS_RXWM_OFFSET = 0x0020; (* RX FIFO Trigger Level [5:0] *)
  142. XUARTPS_MODEMCR_OFFSET = 0x0024; (* Modem Control [5:0] *)
  143. XUARTPS_MODEMSR_OFFSET = 0x0028; (* Modem Status [8:0] *)
  144. XUARTPS_SR_OFFSET = 0x002C; (* Channel Status [14:0] *)
  145. XUARTPS_FIFO_OFFSET = 0x0030; (* FIFO [7:0] *)
  146. XUARTPS_BAUDDIV_OFFSET = 0x0034; (* Baud Rate Divider [7:0] *)
  147. XUARTPS_FLOWDEL_OFFSET = 0x0038; (* Flow Delay [5:0] *)
  148. XUARTPS_TXWM_OFFSET = 0x0044; (* TX FIFO Trigger Level [5:0] *)
  149. XUARTPS_RXBS_OFFSET = 0x0048; (* RX FIFO Byte Status [11:0] *)
  150. *)
  151. UartRegisters* = POINTER {UNSAFE, UNTRACED} TO RECORD
  152. cr*, mr*, ier*, idr*, imr*, isr*: SET;
  153. baudgen*, rxtout*, rxwm*: LONGINT;
  154. modemcr*, modemsr*: SET;
  155. sr*: SET;
  156. fifo*: LONGINT;
  157. bauddiv*, flowdel*: LONGINT;
  158. padding2: ARRAY 2 OF LONGINT;
  159. txwm*: LONGINT;
  160. END;
  161. BusyLoopCallback* = PROCEDURE{DELEGATE}(VAR res: LONGINT): BOOLEAN;
  162. VAR
  163. uarts: ARRAY NumUarts OF UartRegisters;
  164. inputClocks: ARRAY NumUarts OF LONGINT;
  165. (**
  166. Install a UART controller
  167. uart: ID (0-based index) of the UART controller to install
  168. base: controller base address
  169. inputClock: controller input clock in Hz
  170. res: returned error code, 0 in case of success
  171. *)
  172. PROCEDURE Install* (uart: LONGINT; base: ADDRESS; inputClock: LONGINT; VAR res: LONGINT);
  173. BEGIN
  174. IF (uart < 0) OR (uart >= LEN(uarts)) THEN
  175. res := NoSuchPort; RETURN;
  176. END;
  177. res := Ok;
  178. uarts[uart] := base;
  179. inputClocks[uart] := inputClock;
  180. Reset(uarts[uart]);
  181. ASSERT(SetBps(uarts[uart],DefaultBPS,res));
  182. ASSERT(SetDataBits(uarts[uart],DefaultDataBits,res));
  183. ASSERT(SetParity(uarts[uart],DefaultParity,res));
  184. ASSERT(SetStopBits(uarts[uart],DefaultStop,res));
  185. END Install;
  186. (**
  187. Get UART controller with a given ID
  188. *)
  189. PROCEDURE GetUart*(uart: LONGINT): UartRegisters;
  190. BEGIN
  191. IF (uart >= 0) & (uart < LEN(uarts)) THEN
  192. RETURN uarts[uart];
  193. ELSE RETURN NIL;
  194. END;
  195. END GetUart;
  196. (**
  197. Enable/Disable the UART controller
  198. enable: TRUE for enabling
  199. *)
  200. PROCEDURE Enable*(uart: UartRegisters; enable: BOOLEAN);
  201. BEGIN
  202. IF enable THEN
  203. uart.cr := uart.cr * SET(-XUARTPS_CR_EN_DIS_MASK) + {XUARTPS_CR_RX_EN, XUARTPS_CR_TX_EN};
  204. ELSE
  205. uart.cr := uart.cr * SET(-XUARTPS_CR_EN_DIS_MASK) + {XUARTPS_CR_RX_DIS, XUARTPS_CR_TX_DIS};
  206. END;
  207. END Enable;
  208. (**
  209. Reset the controller
  210. *)
  211. PROCEDURE Reset*(uart: UartRegisters);
  212. BEGIN
  213. (* disable all UART interrupts *)
  214. uart.idr := XUARTPS_IXR_MASK;
  215. (* disable RX/TX *)
  216. uart.cr := {XUARTPS_CR_RX_DIS, XUARTPS_CR_TX_DIS};
  217. (* software reset of RX and TX - this clears the FIFO. *)
  218. uart.cr := {XUARTPS_CR_RXRST, XUARTPS_CR_TXRST};
  219. (*! this makes the controller crazy when executed within PsUart.Open
  220. (* clear status flags - SW reset will not clear sticky flags *)
  221. uart.isr := XUARTPS_IXR_MASK;*)
  222. (* set CR to its default value *)
  223. uart.cr := {XUARTPS_CR_RX_DIS, XUARTPS_CR_TX_DIS, XUARTPS_CR_STOPBRK};
  224. END Reset;
  225. (*
  226. Setup baudrate in bps
  227. *)
  228. PROCEDURE SetBps*(uart: UartRegisters; baudrate: LONGINT; VAR res: LONGINT): BOOLEAN;
  229. VAR
  230. i, clock: LONGINT;
  231. valBAUDDIV, valBRGR, calcBaudrate, baudError: LONGINT;
  232. bestError, bestBRGR, bestBAUDDIV: LONGINT;
  233. BEGIN
  234. i := 0;
  235. WHILE (i < LEN(uarts)) & (uarts[i] # uart) DO INC(i); END;
  236. ASSERT(i < LEN(uarts));
  237. clock := inputClocks[i];
  238. (*
  239. Make sure the baud rate is not impossilby large.
  240. Fastest possible baud rate is Input Clock / 2
  241. *)
  242. IF (baudrate <= 0) OR (baudrate*2 > clock) THEN
  243. res := NoSuchPort; RETURN FALSE;
  244. END;
  245. (* Check whether the input clock is divided by 8 *)
  246. IF XUARTPS_MR_CLKSEL_BIT IN uart.mr THEN
  247. clock := clock DIV 8;
  248. END;
  249. (* Determine the Baud divider. It can be 4 to 254.
  250. Loop through all possible combinations *)
  251. bestError := MAX(LONGINT);
  252. FOR valBAUDDIV := 4 TO 255 DO
  253. (* Calculate the value for BRGR register *)
  254. valBRGR := clock DIV (baudrate * (valBAUDDIV + 1));
  255. IF valBRGR > 0 THEN
  256. (* Calculate the baud rate from the BRGR value *)
  257. calcBaudrate := clock DIV (valBRGR * (valBAUDDIV + 1));
  258. (* Avoid unsigned integer underflow *)
  259. IF baudrate > calcBaudrate THEN
  260. baudError := baudrate - calcBaudrate;
  261. ELSE
  262. baudError := calcBaudrate - baudrate;
  263. END;
  264. (*
  265. Find the calculated baud rate closest to requested baud rate.
  266. *)
  267. IF baudError < bestError THEN
  268. bestBRGR := valBRGR;
  269. bestBAUDDIV := valBAUDDIV;
  270. bestError := baudError;
  271. END;
  272. END;
  273. INC(valBAUDDIV);
  274. END;
  275. (*
  276. Make sure the best error is not too large.
  277. *)
  278. IF (bestError * 100) DIV baudrate > XUARTPS_MAX_BAUD_ERROR_RATE THEN (* baudrate error *)
  279. res := WrongBPS; RETURN FALSE;
  280. END;
  281. (* write baudrate settings *)
  282. uart.baudgen := bestBRGR;
  283. uart.bauddiv := bestBAUDDIV;
  284. res := Ok;
  285. RETURN TRUE
  286. END SetBps;
  287. (**
  288. Set number of data bits
  289. *)
  290. PROCEDURE SetDataBits*(uart: UartRegisters; dataBits: LONGINT; VAR res: LONGINT): BOOLEAN;
  291. VAR reg: SET;
  292. BEGIN
  293. CASE dataBits OF
  294. 6: reg := XUARTPS_MR_CHARLEN_6;
  295. |7: reg := XUARTPS_MR_CHARLEN_7;
  296. |8: reg := XUARTPS_MR_CHARLEN_8;
  297. ELSE
  298. res := WrongData; RETURN FALSE;
  299. END;
  300. uart.mr := uart.mr * SET(-XUARTPS_MR_CHARLEN_MASK) + reg;
  301. res := Ok;
  302. RETURN TRUE
  303. END SetDataBits;
  304. (**
  305. Setup parity check type
  306. *)
  307. PROCEDURE SetParity*(uart: UartRegisters; parityType: LONGINT; VAR res: LONGINT): BOOLEAN;
  308. VAR reg: SET;
  309. BEGIN
  310. CASE parityType OF
  311. ParNo: reg := XUARTPS_MR_PARITY_NONE;
  312. |ParEven: reg := XUARTPS_MR_PARITY_EVEN;
  313. |ParOdd: reg := XUARTPS_MR_PARITY_ODD;
  314. |ParMark: reg := XUARTPS_MR_PARITY_MARK;
  315. |ParSpace: reg := XUARTPS_MR_PARITY_SPACE;
  316. ELSE
  317. res := WrongParity; RETURN FALSE;
  318. END;
  319. uart.mr := uart.mr * SET(-XUARTPS_MR_PARITY_MASK) + reg;
  320. res := Ok;
  321. RETURN TRUE
  322. END SetParity;
  323. (**
  324. Setup number of stop bits
  325. *)
  326. PROCEDURE SetStopBits*(uart: UartRegisters; stopBits: LONGINT; VAR res: LONGINT): BOOLEAN;
  327. VAR reg: SET;
  328. BEGIN
  329. CASE stopBits OF
  330. Stop1: reg := XUARTPS_MR_STOPMODE_1;
  331. |Stop2: reg := XUARTPS_MR_STOPMODE_2;
  332. |Stop1dot5: reg := XUARTPS_MR_STOPMODE_1_5;
  333. ELSE
  334. res := WrongStop; RETURN FALSE;
  335. END;
  336. uart.mr := uart.mr * SET(-XUARTPS_MR_STOPMODE_MASK) + reg;
  337. res := Ok;
  338. RETURN TRUE
  339. END SetStopBits;
  340. (**
  341. Send a single character to the UART
  342. ch: character to send
  343. propagate: TRUE for flushing the TX FIFO buffer
  344. res: error code, 0 in case of success
  345. *)
  346. PROCEDURE SendChar*(uart: UartRegisters; ch: CHAR; propagate: BOOLEAN; onBusy: BusyLoopCallback; VAR res: LONGINT);
  347. BEGIN
  348. (* Wait until TX FIFO is not full *)
  349. WHILE (XUARTPS_CR_TX_EN IN uart.cr) & (XUARTPS_SR_TXFULL IN uart.sr) DO
  350. IF (onBusy # NIL) & ~onBusy(res) THEN RETURN; END;
  351. END;
  352. IF (XUARTPS_CR_TX_EN IN uart.cr) THEN
  353. uart.fifo := ORD(ch);
  354. IF propagate THEN (* flush the FIFO *)
  355. WHILE (XUARTPS_CR_TX_EN IN uart.cr) & ~(XUARTPS_SR_TXEMPTY IN uart.sr) DO
  356. IF (onBusy # NIL) & ~onBusy(res) THEN RETURN; END;
  357. END;
  358. END;
  359. IF (XUARTPS_CR_TX_EN IN uart.cr) THEN res := Ok; ELSE res := Closed; END;
  360. ELSE res := Closed;
  361. END;
  362. END SendChar;
  363. (**
  364. Receive a single character from UART
  365. res: error code, 0 in case of success
  366. Remarks: blocks until a character is available
  367. *)
  368. PROCEDURE ReceiveChar*(uart: UartRegisters; onBusy: BusyLoopCallback; VAR res: LONGINT): CHAR;
  369. BEGIN
  370. (* wait until data is available *)
  371. WHILE (XUARTPS_CR_RX_EN IN uart.cr) & (XUARTPS_SR_RXEMPTY IN uart.sr) DO
  372. IF (onBusy # NIL) & ~onBusy(res) THEN RETURN 0X; END;
  373. END;
  374. IF (XUARTPS_CR_RX_EN IN uart.cr) THEN
  375. res := Ok; RETURN CHR(uart.fifo);
  376. ELSE
  377. res := Closed; RETURN 0X;
  378. END;
  379. END ReceiveChar;
  380. (**
  381. Returns number of bytes available in the receive FIFO of the UART controller
  382. res: error code, 0 in case of success
  383. *)
  384. PROCEDURE Available*(uart: UartRegisters): LONGINT;
  385. BEGIN
  386. IF ~(XUARTPS_SR_RXEMPTY IN uart.sr) THEN
  387. RETURN 1;
  388. END;
  389. RETURN 0;
  390. END Available;
  391. END PsUartMin.