Zynq.Uart.Mos 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969
  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, Board, Device, Interrupts, UartConstants, Trace;
  8. CONST
  9. DefaultBaudrate* = 115200; (** defauilt UART baudrate *)
  10. UartNb* = 2;
  11. UartBaseAddr0* = ADDRESS(0E0000000H);
  12. UartBaseAddr1* = ADDRESS(0E0001000H); (* base address for all UART controllers present in the system *)
  13. UartModemPinsConnected0* = FALSE;
  14. UartModemPinsConnected1* = FALSE;
  15. UartInputClockHz* = Board.UartInputClockHz;
  16. (** Register offsets for the UART controller *)
  17. XUARTPS_CR_OFFSET = 000H; (** Control Register [8:0] *)
  18. XUARTPS_MR_OFFSET = 004H; (* Mode Register [9:0] *)
  19. XUARTPS_IER_OFFSET = 008H; (* Interrupt Enable [12:0] *)
  20. XUARTPS_IDR_OFFSET = 00CH; (* Interrupt Disable [12:0] *)
  21. XUARTPS_IMR_OFFSET = 010H; (* Interrupt Mask [12:0] *)
  22. XUARTPS_ISR_OFFSET = 014H; (* Interrupt Status [12:0]*)
  23. XUARTPS_BAUDGEN_OFFSET = 018H; (* Baud Rate Generator [15:0] *)
  24. XUARTPS_RXTOUT_OFFSET = 01CH; (* RX Timeout [7:0] *)
  25. XUARTPS_RXWM_OFFSET = 020H; (* RX FIFO Trigger Level [5:0] *)
  26. XUARTPS_MODEMCR_OFFSET = 024H; (* Modem Control [5:0] *)
  27. XUARTPS_MODEMSR_OFFSET = 028H; (* Modem Status [8:0] *)
  28. XUARTPS_SR_OFFSET = 02CH; (* Channel Status [14:0] *)
  29. XUARTPS_FIFO_OFFSET = 030H; (* FIFO [7:0] *)
  30. XUARTPS_BAUDDIV_OFFSET = 034H; (* Baud Rate Divider [7:0] *)
  31. XUARTPS_FLOWDEL_OFFSET = 038H; (* Flow Delay [5:0] *)
  32. XUARTPS_TXWM_OFFSET = 044H; (* TX FIFO Trigger Level [5:0] *)
  33. (* Control Register Bit Definition
  34. The Control register (CR) controls the major functions of the device.
  35. *)
  36. XUARTPS_CR_STOPBRK = 000000100H; (* Stop transmission of break *)
  37. XUARTPS_CR_STARTBRK = 000000080H; (* Set break *)
  38. XUARTPS_CR_TORST = 000000040H; (* RX timeout counter restart *)
  39. XUARTPS_CR_TX_DIS = 000000020H; (* TX disabled. *)
  40. XUARTPS_CR_TX_EN = 000000010H; (* TX enabled *)
  41. XUARTPS_CR_RX_DIS = 000000008H; (* RX disabled. *)
  42. XUARTPS_CR_RX_EN = 000000004H; (* RX enabled *)
  43. XUARTPS_CR_EN_DIS_MASK = 00000003CH; (* Enable/disable Mask *)
  44. XUARTPS_CR_TXRST = 000000002H; (* TX logic reset *)
  45. XUARTPS_CR_RXRST = 000000001H; (* RX logic reset *)
  46. CTRLSTOPBRK = 8; (* Stop transmission of break *)
  47. CTRLSTARTBRK = 7; (* Set break *)
  48. CTRLTORST = 6; (* RX timeout counter restart *)
  49. CTRLTX_DIS = 5; (* TX disabled. *)
  50. CTRLTX_EN = 4; (* TX enabled *)
  51. CTRLRX_DIS = 3; (* RX disabled. *)
  52. CTRLRX_EN = 2; (* RX enabled *)
  53. CTRLTXRST = 1; (* TX logic reset *)
  54. CTRLRXRST = 0; (* RX logic reset *)
  55. (* Mode Register Bit Definition
  56. The mode register (MR) defines the mode of transfer as well as the data
  57. format. If this register is modified during transmission or reception,
  58. data validity cannot be guaranteed.
  59. *)
  60. XUARTPS_MR_CCLK = 000000400H; (* Input clock selection *)
  61. XUARTPS_MR_CHMODE_R_LOOP = 000000300H; (* Remote loopback mode *)
  62. XUARTPS_MR_CHMODE_L_LOOP = 000000200H; (* Local loopback mode *)
  63. XUARTPS_MR_CHMODE_ECHO = 000000100H; (* Auto echo mode *)
  64. XUARTPS_MR_CHMODE_NORM = 000000000H; (* Normal mode *)
  65. XUARTPS_MR_CHMODE_SHIFT = 8; (* Mode shift *)
  66. XUARTPS_MR_CHMODE_MASK = 000000300H; (* Mode mask *)
  67. XUARTPS_MR_STOPMODE_2_BIT = 000000080H; (* 2 stop bits *)
  68. XUARTPS_MR_STOPMODE_1_5_BIT = 000000040H; (* 1.5 stop bits *)
  69. XUARTPS_MR_STOPMODE_1_BIT = 000000000H; (* 1 stop bit *)
  70. XUARTPS_MR_STOPMODE_SHIFT = 6; (* Stop bits shift *)
  71. XUARTPS_MR_STOPMODE_MASK = 0000000A0H; (* Stop bits mask *)
  72. XUARTPS_MR_PARITY_NONE = 000000020H; (* No parity mode *)
  73. XUARTPS_MR_PARITY_MARK = 000000018H; (* Mark parity mode *)
  74. XUARTPS_MR_PARITY_SPACE = 000000010H; (* Space parity mode *)
  75. XUARTPS_MR_PARITY_ODD = 000000008H; (* Odd parity mode *)
  76. XUARTPS_MR_PARITY_EVEN = 000000000H; (* Even parity mode *)
  77. XUARTPS_MR_PARITY_SHIFT = 3; (* Parity setting shift *)
  78. XUARTPS_MR_PARITY_MASK = 000000038H; (* Parity mask *)
  79. XUARTPS_MR_CHARLEN_6_BIT = 000000006H; (* 6 bits data *)
  80. XUARTPS_MR_CHARLEN_7_BIT = 000000004H; (* 7 bits data *)
  81. XUARTPS_MR_CHARLEN_8_BIT = 000000000H; (* 8 bits data *)
  82. XUARTPS_MR_CHARLEN_SHIFT = 1; (* Data Length shift *)
  83. XUARTPS_MR_CHARLEN_MASK = 000000006H; (* Data length mask *)
  84. XUARTPS_MR_CLKSEL = 000000001H; (* Input clock selection *)
  85. (** Interrupt Registers
  86. Interrupt control logic uses the interrupt enable register (IER) and the
  87. interrupt disable register (IDR) to set the value of the bits in the
  88. interrupt mask register (IMR). The IMR determines whether to pass an
  89. interrupt to the interrupt status register (ISR).
  90. Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an
  91. interrupt. IMR and ISR are read only, and IER and IDR are write only.
  92. Reading either IER or IDR returns 0x00.
  93. All four registers have the same bit definitions.
  94. *)
  95. XUARTPS_IXR_TOVR = 000001000H; (** Tx FIFO Overflow interrupt *)
  96. XUARTPS_IXR_TNFUL = 000000800H; (** Tx FIFO Nearly Full interrupt *)
  97. XUARTPS_IXR_TTRIG = 000000400H; (** Tx Trig interrupt *)
  98. XUARTPS_IXR_DMS = 000000200H; (** Modem status change interrupt *)
  99. XUARTPS_IXR_TOUT = 000000100H; (** Timeout error interrupt *)
  100. XUARTPS_IXR_PARITY = 000000080H; (** Parity error interrupt *)
  101. XUARTPS_IXR_FRAMING = 000000040H; (** Framing error interrupt *)
  102. XUARTPS_IXR_OVER = 000000020H; (** Overrun error interrupt *)
  103. XUARTPS_IXR_TXFULL = 000000010H; (** TX FIFO full interrupt. *)
  104. XUARTPS_IXR_TXEMPTY = 000000008H; (** TX FIFO empty interrupt. *)
  105. XUARTPS_IXR_RXFULL = 000000004H; (** RX FIFO full interrupt. *)
  106. XUARTPS_IXR_RXEMPTY = 000000002H; (** RX FIFO empty interrupt. *)
  107. XUARTPS_IXR_RXOVR = 000000001H; (** RX FIFO trigger interrupt. *)
  108. IRQTOVR = 12; (** Tx FIFO Overflow interrupt *)
  109. IRQTNFUL = 11; (** Tx FIFO Nearly Full interrupt *)
  110. IRQTTRIG = 10; (** Tx Trig interrupt *)
  111. IRQDMS = 9; (** Modem status change interrupt *)
  112. IRQTOUT = 8; (** Timeout error interrupt *)
  113. IRQPARITY = 7; (** Parity error interrupt *)
  114. IRQFRAMING = 6; (** Framing error interrupt *)
  115. IRQOVER = 5; (** Overrun error interrupt *)
  116. IRQTXFULL = 4; (** TX FIFO full interrupt. *)
  117. IRQTXEMPTY = 3; (** TX FIFO empty interrupt. *)
  118. IRQRXFULL = 2; (** RX FIFO full interrupt. *)
  119. IRQRXEMPTY = 1; (** RX FIFO empty interrupt. *)
  120. IRQRXFIFO = 0; (** RX FIFO trigger interrupt. *)
  121. XUARTPS_IXR_MASK = 000001FFFH; (** Valid bit mask *)
  122. (** Channel Status Register
  123. The channel status register (CSR) is provided to enable the control logic
  124. to monitor the status of bits in the channel interrupt status register,
  125. even if these are masked out by the interrupt mask register.
  126. *)
  127. XUARTPS_SR_TNFUL = 000004000H; (** TX FIFO Nearly Full Status *)
  128. XUARTPS_SR_TTRIG = 000002000H; (** TX FIFO Trigger Status *)
  129. XUARTPS_SR_FLOWDEL = 000001000H; (** RX FIFO fill over flow delay *)
  130. XUARTPS_SR_TACTIVE = 000000800H; (** TX active *)
  131. XUARTPS_SR_RACTIVE = 000000400H; (** RX active *)
  132. XUARTPS_SR_DMS = 000000200H; (** Delta modem status change *)
  133. XUARTPS_SR_TOUT = 000000100H; (** RX timeout *)
  134. XUARTPS_SR_PARITY = 000000080H; (** RX parity error *)
  135. XUARTPS_SR_FRAME = 000000040H; (** RX frame error *)
  136. XUARTPS_SR_OVER = 000000020H; (** RX overflow error *)
  137. XUARTPS_SR_TXFULL = 000000010H; (** TX FIFO full *)
  138. XUARTPS_SR_TXEMPTY = 000000008H; (** TX FIFO empty *)
  139. XUARTPS_SR_RXFULL = 000000004H; (** RX FIFO full *)
  140. XUARTPS_SR_RXEMPTY = 000000002H; (** RX FIFO empty *)
  141. XUARTPS_SR_RXOVR = 000000001H; (** RX FIFO fill over trigger *)
  142. SR_TNFUL = 14; (** TX FIFO Nearly Full Status *)
  143. SR_TTRIG = 13; (** TX FIFO Trigger Status *)
  144. SR_FLOWDEL = 12; (** RX FIFO fill over flow delay *)
  145. SR_TACTIVE = 11; (** TX active *)
  146. SR_RACTIVE = 10; (** RX active *)
  147. SR_DMS = 9; (** Delta modem status change *)
  148. SR_TOUT = 8; (** RX timeout *)
  149. SR_PARITY = 7; (** RX parity error *)
  150. SR_FRAME = 6; (** RX frame error *)
  151. SR_OVER = 5; (** RX overflow error *)
  152. SR_TXFULL = 4; (** TX FIFO full *)
  153. SR_TXEMPTY = 3; (** TX FIFO empty *)
  154. SR_RXFULL = 2; (** RX FIFO full *)
  155. SR_RXEMPTY = 1; (** RX FIFO empty *)
  156. SR_RXOVR = 0; (** RX FIFO fill over trigger *)
  157. (* The following constant defines the amount of error that is allowed for
  158. a specified baud rate. This error is the difference between the actual
  159. baud rate that will be generated using the specified clock and the
  160. desired baud rate.
  161. *)
  162. XUARTPS_MAX_BAUD_ERROR_RATE = 3; (* max % error allowed *)
  163. UARTBUFLEN = 2048;
  164. PSUART0 = 0;
  165. PSUART1 = 1;
  166. TYPE
  167. UARTBuffer = ARRAY UARTBUFLEN OF SYSTEM.BYTE;
  168. UartDesc* = RECORD ( Device.DeviceDesc )
  169. id: LONGINT;
  170. baseAddr: LONGINT; (* Adress of Base register *)
  171. clockFrequency: LONGINT; (* the clock used for the UART *)
  172. in, out, oin, oout: LONGINT; (* And and Out index in in (in, out) and outbuffer (oin, oout) *)
  173. baudrate: LONGINT; (* Baudrate *)
  174. parity: LONGINT; (* Parity *)
  175. databits: LONGINT; (* Number of data bits *)
  176. trace: BOOLEAN; (* shall debug output be printed via Log? *)
  177. open: BOOLEAN; (* Is the uart already initialised and open? *)
  178. irqCnt: LONGINT;
  179. irqEnabled: BOOLEAN; (* true, if this UART is handled by interrupts *)
  180. inbuffer, outbuffer: UARTBuffer; (* receive and sendbuffer *)
  181. timeoutActive : BOOLEAN; (* if the timeout counter has been set *)
  182. txIrqActive : BOOLEAN;
  183. END;
  184. UartCfg = RECORD
  185. addr : LONGINT;
  186. clock : LONGINT;
  187. END;
  188. Uart* = POINTER TO UartDesc;
  189. VAR
  190. uarts: ARRAY 2 OF Uart;
  191. (**
  192. Initialize a UART controller given its configuration information
  193. *)
  194. PROCEDURE Init*( VAR uart: Uart; CONST cfg: UartCfg);
  195. VAR
  196. res: LONGINT;
  197. BEGIN
  198. uart.baseAddr := cfg.addr;
  199. uart.clockFrequency := cfg.clock;
  200. (* disable all UART interrupts *)
  201. SYSTEM.PUT32( uart.baseAddr+XUARTPS_IDR_OFFSET, 0FFFFFFFFH );
  202. uart.irqEnabled := FALSE;
  203. (* Set the default baudrate *)
  204. (*Trace.StringLn("Entering SetBaudrate.");
  205. SetBaudrate( uart, DefaultBaudrate, res);*)
  206. END Init;
  207. PROCEDURE DoIrq( CONST no : LONGINT );
  208. VAR
  209. uart : Uart;
  210. reg, ireg : SET;
  211. cnt : LONGINT;
  212. tort : BOOLEAN;
  213. BEGIN
  214. tort := FALSE;
  215. IF ( GetUartByIndex( no, uart )) THEN
  216. (* check the timout flag and the fifo flag first *)
  217. SYSTEM.GET( uart.baseAddr+XUARTPS_ISR_OFFSET, ireg );
  218. IF (IRQRXFIFO IN ireg ) OR (IRQTOUT IN ireg ) THEN
  219. SYSTEM.GET( uart.baseAddr+XUARTPS_SR_OFFSET, reg );
  220. WHILE ( ~(SR_RXEMPTY IN reg )) DO
  221. uart.inbuffer[ uart.in ] := CHR( SYSTEM.GET32( uart.baseAddr+XUARTPS_FIFO_OFFSET ));
  222. uart.in := ( uart.in + 1 ) MOD UARTBUFLEN;
  223. SYSTEM.GET( uart.baseAddr+XUARTPS_SR_OFFSET, reg );
  224. END;
  225. (* clear the flags now *)
  226. uart.timeoutActive := FALSE;
  227. END;
  228. IF ( IRQTXEMPTY IN ireg ) THEN
  229. cnt := 0;
  230. (* there is still data in the TX buffer, send it to the FIFO *)
  231. WHILE ( uart.oin # uart.oout ) & ( cnt < 60 ) DO
  232. SYSTEM.PUT32( uart.baseAddr+XUARTPS_FIFO_OFFSET, ORD(uart.outbuffer[uart.oout]) );
  233. uart.oout:= ( uart.oout+1 ) MOD UARTBUFLEN;
  234. INC( cnt )
  235. END;
  236. (* Trace.String("d");*)
  237. IF ( uart.oin = uart.oout ) THEN
  238. (* set the flag to get the TX monitor to check the FIFO again *)
  239. uart.txIrqActive := FALSE;
  240. (* disable the TX interrupt *)
  241. SYSTEM.GET( uart.baseAddr+ XUARTPS_IER_OFFSET, reg );
  242. reg := reg - { IRQTXEMPTY };
  243. SYSTEM.PUT( uart.baseAddr+ XUARTPS_IER_OFFSET, reg );
  244. (* Trace.String("(di)"); *)
  245. END;
  246. END;
  247. SYSTEM.PUT( uart.baseAddr+XUARTPS_ISR_OFFSET, ireg );
  248. END;
  249. END DoIrq;
  250. PROCEDURE PSUartIrqHandler( irq: LONGINT );
  251. BEGIN
  252. (* check the IRQ source *)
  253. IF ( irq = Interrupts.PSUART0IRQ ) THEN
  254. DoIrq( 0 );
  255. ELSIF ( irq = Interrupts.PSUART1IRQ ) THEN
  256. DoIrq( 1 );
  257. ELSE
  258. Trace.StringLn("PSUart: Unknown IRQ call!");
  259. END;
  260. END PSUartIrqHandler;
  261. (**
  262. Set UART baudrate
  263. res: error code, 0 in case of success
  264. *)
  265. PROCEDURE SetBaudrate*( VAR uart: Uart; CONST baudrate: LONGINT; VAR res: LONGINT );
  266. VAR
  267. reg: SET;
  268. inputClk: LONGINT;
  269. valBAUDDIV, valBRGR, calcBaudrate, baudError: LONGINT;
  270. bestError, bestBRGR, bestBAUDDIV: LONGINT;
  271. BEGIN
  272. bestError := MAX(LONGINT);(*1000;*)
  273. (*
  274. Make sure the baud rate is not impossilby large.
  275. Fastest possible baud rate is Input Clock / 2
  276. *)
  277. Trace.String("Entering SetBaudrate : "); Trace.Int( baudrate, 10 ); Trace.Ln;
  278. IF baudrate*2 > uart.clockFrequency THEN res := 1; RETURN; END;
  279. inputClk := uart.clockFrequency;
  280. Trace.String("Input Clock is : "); Trace.Int( inputClk, 10 ); Trace.Ln;
  281. (* Check whether the input clock is divided by 8 *)
  282. SYSTEM.GET( uart.baseAddr+XUARTPS_MR_OFFSET, reg );
  283. IF XUARTPS_MR_CLKSEL IN reg THEN
  284. Trace.StringLn("Input Clock is Divided by 8");
  285. inputClk := inputClk DIV 8;
  286. END;
  287. (* Determine the Baud divider. It can be 4 to 254.
  288. Loop through all possible combinations *)
  289. FOR valBAUDDIV := 4 TO 255 DO
  290. (* Calculate the value for BRGR register *)
  291. valBRGR := inputClk DIV (baudrate * (valBAUDDIV + 1));
  292. IF ( valBRGR > 0 ) THEN
  293. (* Calculate the baud rate from the BRGR value *)
  294. calcBaudrate := inputClk DIV (valBRGR * (valBAUDDIV + 1));
  295. (* Avoid unsigned integer underflow *)
  296. IF baudrate > calcBaudrate THEN
  297. baudError := baudrate - calcBaudrate;
  298. ELSE
  299. baudError := calcBaudrate - baudrate;
  300. END;
  301. (*
  302. Find the calculated baud rate closest to requested baud rate.
  303. *)
  304. IF baudError < bestError THEN
  305. bestBRGR := valBRGR;
  306. bestBAUDDIV := valBAUDDIV;
  307. bestError := baudError;
  308. END;
  309. END;
  310. END;
  311. (*
  312. Make sure the best error is not too large.
  313. *)
  314. IF (bestError * 100) DIV baudrate > XUARTPS_MAX_BAUD_ERROR_RATE THEN (* baudrate error *)
  315. Trace.String("Baud Error : "); Trace.Int(( bestError *100 ) DIV baudrate, 3 ); Trace.StringLn("; Bailing out, Error too large.");
  316. res := 1; RETURN;
  317. END;
  318. (*
  319. Disable TX and RX to avoid glitches when setting the baud rate.
  320. *)
  321. Trace.String("CD : "); Trace.Int( bestBRGR, 10 ); Trace.Ln;
  322. Trace.String("DIV : "); Trace.Int( bestBAUDDIV, 10 ); Trace.Ln;
  323. Trace.String("Actual baudrate: "); Trace.Int(inputClk DIV (bestBRGR * (bestBAUDDIV + 1)), 0); Trace.Ln;
  324. (* INVESTIGATE: Unclear why this works for UART1, but not for UART0 *)
  325. IF ( uart.id # 0 ) THEN
  326. Enable( uart, FALSE );
  327. END;
  328. (* write baudrate settings *)
  329. SYSTEM.PUT( uart.baseAddr+XUARTPS_BAUDGEN_OFFSET, bestBRGR );
  330. SYSTEM.PUT( uart.baseAddr+XUARTPS_BAUDDIV_OFFSET, bestBAUDDIV );
  331. IF ( uart.id # 0 ) THEN
  332. Enable( uart, TRUE );
  333. END;
  334. uart.baudrate := baudrate;
  335. END SetBaudrate;
  336. (** Enable/Disable the transmitter and receiver of the UART *)
  337. PROCEDURE Enable*( CONST uart: Uart; enable: BOOLEAN );
  338. VAR reg: SET;
  339. tmp : LONGINT;
  340. BEGIN
  341. SYSTEM.GET(uart.baseAddr+XUARTPS_CR_OFFSET, reg );
  342. IF enable THEN
  343. reg := reg + { CTRLTX_EN, CTRLRX_EN } - { CTRLTX_DIS, CTRLRX_DIS };
  344. ELSE
  345. reg := reg + { CTRLTX_DIS, CTRLRX_DIS } - { CTRLTX_EN, CTRLRX_EN };
  346. END;
  347. SYSTEM.PUT( uart.baseAddr+XUARTPS_CR_OFFSET, reg );
  348. (* set the timeout counter of the UART to 255, used for transfering small amount of data to the buffer before the FIFO trigger level is reached *)
  349. SYSTEM.PUT( uart.baseAddr+XUARTPS_RXTOUT_OFFSET, 255 );
  350. END Enable;
  351. (* select the UART by index, return TRUE if successful *)
  352. PROCEDURE GetUartByIndex( CONST no : LONGINT; VAR uart : Uart ) : BOOLEAN;
  353. VAR
  354. ret : BOOLEAN;
  355. BEGIN
  356. uart := NIL;
  357. ret := FALSE;
  358. IF ( no = 0 ) OR ( no = 1 ) THEN
  359. uart := uarts[ no ];
  360. ret := TRUE;
  361. END;
  362. RETURN ret;
  363. END GetUartByIndex;
  364. PROCEDURE EnableIrqMode*( CONST no : LONGINT; FifoLevel : LONGINT );
  365. VAR
  366. reg : SET;
  367. uart : Uart;
  368. BEGIN
  369. IF ( GetUartByIndex( no, uart )) THEN
  370. IF ( uart.id = 0 ) THEN
  371. Interrupts.EnableIrq( Interrupts.PSUART0IRQ );
  372. ELSE
  373. Interrupts.EnableIrq( Interrupts.PSUART1IRQ );
  374. END;
  375. (* set the fifo RX trigger level to 32 *)
  376. SYSTEM.PUT( uart.baseAddr+XUARTPS_RXWM_OFFSET, 32 );
  377. (* set the bits in the enable register *)
  378. SYSTEM.PUT( uart.baseAddr+ XUARTPS_IER_OFFSET, { IRQTOUT, IRQRXFIFO } );
  379. (* read back the mask register *)
  380. SYSTEM.GET( uart.baseAddr+ XUARTPS_IMR_OFFSET, reg );
  381. Trace.String("Uart IRQ Mask : "); Trace.Bits( reg, 0, 32 ); Trace.Ln;
  382. (* clear the interrupt status register *)
  383. SYSTEM.GET( uart.baseAddr+ XUARTPS_ISR_OFFSET, reg );
  384. reg := reg - { IRQTOUT, IRQRXFIFO };
  385. SYSTEM.PUT( uart.baseAddr+ XUARTPS_ISR_OFFSET, reg );
  386. Trace.String("Writing back Status Reg with : "); Trace.Bits( reg, 0, 32 ); Trace.Ln;
  387. (* setup the timeout counter on the IRQ register *)
  388. END;
  389. END EnableIrqMode;
  390. PROCEDURE ShowIrqStatus*(CONST no : LONGINT );
  391. VAR
  392. reg : SET;
  393. uart : Uart;
  394. BEGIN
  395. IF ( GetUartByIndex( no, uart )) THEN
  396. SYSTEM.GET( uart.baseAddr+XUARTPS_ISR_OFFSET, reg );
  397. Trace.String("IRQ Status ("); Trace.Int( no, 1 ); Trace.String(") : "); Trace.Bits( reg, 0, 32 ); Trace.Ln;
  398. SYSTEM.GET( uart.baseAddr+ XUARTPS_IER_OFFSET, reg );
  399. Trace.String("IRQ Enable ("); Trace.Int( no, 1 ); Trace.String(") : "); Trace.Bits( reg, 0, 32 ); Trace.Ln;
  400. SYSTEM.GET( uart.baseAddr+ XUARTPS_IDR_OFFSET, reg );
  401. Trace.String("IRQ Disable("); Trace.Int( no, 1 ); Trace.String(") : "); Trace.Bits( reg, 0, 32 ); Trace.Ln;
  402. SYSTEM.GET( uart.baseAddr+ XUARTPS_IMR_OFFSET, reg );
  403. Trace.String("IRQ Mask ("); Trace.Int( no, 1 ); Trace.String(") : "); Trace.Bits( reg, 0, 32 ); Trace.Ln;
  404. END;
  405. END ShowIrqStatus;
  406. PROCEDURE ShowUartSettings*( CONST no : LONGINT );
  407. CONST
  408. OFF = 16;
  409. VAR
  410. uart : Uart;
  411. reg : SET;
  412. cd, bdiv : LONGINT;
  413. sampleClk, baudClk : REAL;
  414. BEGIN
  415. IF ( GetUartByIndex( no, uart )) THEN
  416. SYSTEM.GET( uart.baseAddr+XUARTPS_BAUDGEN_OFFSET , cd );
  417. SYSTEM.GET( uart.baseAddr+XUARTPS_BAUDDIV_OFFSET , bdiv );
  418. SYSTEM.GET( uart.baseAddr+XUARTPS_CR_OFFSET, reg );
  419. sampleClk := UartInputClockHz / bdiv;
  420. baudClk := UartInputClockHz / ( cd * ( bdiv + 1));
  421. Trace.Ln;
  422. Trace.Ln;
  423. Trace.StringLn("*** PS UART Settings ***");
  424. Trace.Ln;
  425. Trace.StringA("Uart No", OFF, TRUE ); Trace.Int( no, 1 ); Trace.Ln;
  426. Trace.StringA("TX Enable", OFF, TRUE ); Trace.Bits( reg, CTRLTX_EN, 1 ); Trace.Ln;
  427. Trace.StringA("TX Disable", OFF, TRUE ); Trace.Bits( reg, CTRLTX_DIS, 1 ); Trace.Ln;
  428. Trace.StringA("RX Enable", OFF, TRUE ); Trace.Bits( reg, CTRLRX_EN, 1 ); Trace.Ln;
  429. Trace.StringA("RX Disable", OFF, TRUE ); Trace.Bits( reg, CTRLRX_DIS, 1 ); Trace.Ln;
  430. Trace.StringA("TX TO Rst", OFF, TRUE ); Trace.Bits( reg, CTRLTORST, 1); Trace.Ln;
  431. Trace.StringA("CD Value", OFF, TRUE ); Trace.Int( cd, 8 ); Trace.Ln;
  432. Trace.StringA("BD Value", OFF, TRUE ); Trace.Int( bdiv, 8 ); Trace.Ln;
  433. Trace.StringA("Sample Clk [Hz]", OFF, TRUE ); Trace.Real( sampleClk, 0, 8 ); Trace.Ln;
  434. Trace.StringA("Baud Clk [Hz]", OFF, TRUE ); Trace.Real( baudClk, 0, 8 ); Trace.Ln;
  435. Trace.Ln;
  436. END;
  437. END ShowUartSettings;
  438. (**
  439. Send data to the UART
  440. *)
  441. PROCEDURE Send*(CONST uart: Uart; CONST buf: ARRAY OF CHAR; offs, len: LONGINT; propagate: BOOLEAN; VAR res: LONGINT);
  442. VAR csr: SET;
  443. BEGIN
  444. res := 0;
  445. IF uart.irqEnabled THEN
  446. (*
  447. Disable the UART transmit interrupts to allow this call to stop a
  448. previous operation that may be interrupt driven.
  449. *)
  450. SYSTEM.PUT32(uart.baseAddr+XUARTPS_IDR_OFFSET,XUARTPS_IXR_TXEMPTY+XUARTPS_IXR_TXFULL);
  451. HALT(100); (*! Not yet implemented! *)
  452. ELSE
  453. WHILE len > 0 DO
  454. csr := SYSTEM.VAL(SET,SYSTEM.GET32(uart.baseAddr+XUARTPS_SR_OFFSET)); (* current state of Channel Status Register *)
  455. 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 *)
  456. SYSTEM.PUT32(uart.baseAddr+XUARTPS_FIFO_OFFSET,ORD(buf[offs]));
  457. INC(offs); DEC(len);
  458. 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 *)
  459. SYSTEM.PUT32(uart.baseAddr+XUARTPS_FIFO_OFFSET,ORD(buf[offs]));
  460. INC(offs); DEC(len);
  461. END;
  462. END;
  463. END;
  464. END;
  465. END Send;
  466. (**
  467. Receive data from the UART
  468. *)
  469. PROCEDURE Receive*(CONST uart: Uart; VAR buf: ARRAY OF CHAR; offs, size, min: LONGINT; VAR len, res: LONGINT);
  470. BEGIN
  471. res := 0;
  472. len := 0;
  473. min := MIN(size,min);
  474. WHILE (min > 0) OR UartAvailable(uart) DO
  475. WHILE (size > 0) & (SYSTEM.VAL(SET,SYSTEM.GET32(uart.baseAddr+XUARTPS_SR_OFFSET)) * SYSTEM.VAL(SET,XUARTPS_SR_RXEMPTY) # SYSTEM.VAL(SET,XUARTPS_SR_RXEMPTY)) DO
  476. buf[offs] := CHR(SYSTEM.GET32(uart.baseAddr+XUARTPS_FIFO_OFFSET));
  477. DEC(min); DEC(size); INC(offs); INC(len);
  478. END;
  479. END;
  480. END Receive;
  481. (** Send a single character to the UART
  482. Remarks:
  483. blocks until the transmit buffer is not full
  484. *)
  485. PROCEDURE SendChar*(CONST uart: Uart; ch: CHAR; VAR res: LONGINT);
  486. BEGIN
  487. (* Wait until there is space in TX FIFO *)
  488. WHILE SYSTEM.VAL(SET,SYSTEM.GET32(uart.baseAddr+XUARTPS_SR_OFFSET)) * SYSTEM.VAL(SET,XUARTPS_SR_TXFULL) = SYSTEM.VAL(SET,XUARTPS_SR_TXFULL) DO
  489. END;
  490. (* Write the byte into the TX FIFO *)
  491. SYSTEM.PUT32( uart.baseAddr+XUARTPS_FIFO_OFFSET,ORD(ch));
  492. END SendChar;
  493. (** Receive a single character from UART
  494. Remarks:
  495. blocks until a character is available
  496. *)
  497. PROCEDURE ReceiveChar*( CONST uart: Uart; VAR res: LONGINT ): CHAR;
  498. BEGIN
  499. (* wait until data is available *)
  500. WHILE SYSTEM.VAL(SET,SYSTEM.GET32(uart.baseAddr+XUARTPS_SR_OFFSET)) * SYSTEM.VAL(SET,XUARTPS_SR_RXEMPTY) = SYSTEM.VAL(SET,XUARTPS_SR_RXEMPTY) DO
  501. END;
  502. RETURN CHR(SYSTEM.GET32(uart.baseAddr+XUARTPS_FIFO_OFFSET));
  503. END ReceiveChar;
  504. (** Returns TRUE if there is at least 1 char in the receive buffer *)
  505. PROCEDURE UartAvailable*(CONST uart: Uart): BOOLEAN;
  506. VAR
  507. reg : SET;
  508. BEGIN
  509. SYSTEM.GET( uart.baseAddr+XUARTPS_SR_OFFSET, reg );
  510. IF ( SR_RXEMPTY IN reg ) THEN
  511. RETURN FALSE;
  512. ELSE
  513. RETURN TRUE;
  514. END;
  515. END UartAvailable;
  516. (* close the device *)
  517. PROCEDURE Close(dev: Device.Device);
  518. BEGIN
  519. Trace.String("In Uart close, adr : "); Trace.Hex( dev(Uart).baseAddr, -8 ); Trace.String(", id is : "); Trace.Int( dev(Uart).id, 2 ); Trace.Ln;
  520. IF dev(Uart).open = TRUE THEN
  521. Enable( dev(Uart), FALSE );
  522. dev(Uart).open := FALSE
  523. END
  524. END Close;
  525. (* Bytes available for read *)
  526. PROCEDURE Available( dev: Device.Device ): LONGINT;
  527. BEGIN
  528. (*DoUart( dev(Uart));*)
  529. RETURN (dev(Uart).in - dev(Uart).out) MOD UARTBUFLEN;
  530. END Available;
  531. (* Get the number of bytes that are free in the send buffer *)
  532. PROCEDURE Free( dev: Device.Device ): LONGINT;
  533. VAR
  534. avail: LONGINT;
  535. BEGIN
  536. avail := UARTBUFLEN - 1 - ((dev(Uart).oin - dev(Uart).oout) MOD UARTBUFLEN );
  537. RETURN avail
  538. END Free;
  539. PROCEDURE Write( dev: Device.Device; CONST buf: ARRAY OF SYSTEM.BYTE; ofs: LONGINT; VAR len: LONGINT );
  540. VAR
  541. end, free: LONGINT;
  542. uart: Uart;
  543. BEGIN
  544. IF (len > 0) & (ofs >= 0) THEN
  545. uart := dev(Uart);
  546. free := Free(dev);
  547. IF free < len THEN len := free END;
  548. end := ofs + len;
  549. WHILE ofs < end DO
  550. uart.outbuffer[ uart.oin ] := buf[ ofs ];
  551. uart.oin := ( uart.oin + 1 ) MOD UARTBUFLEN;
  552. INC( ofs )
  553. END;
  554. ELSE
  555. len := 0
  556. END;
  557. (* HACK
  558. DoUart( uart );
  559. *)
  560. END Write;
  561. PROCEDURE Read( dev: Device.Device; VAR buf: ARRAY OF SYSTEM.BYTE; ofs: LONGINT; VAR len: LONGINT );
  562. VAR
  563. end, available: LONGINT;
  564. uart: Uart;
  565. BEGIN
  566. (* HACK
  567. uart := dev(Uart);
  568. DoUart( uart );
  569. *)
  570. IF (len > 0) & (ofs >= 0) THEN
  571. uart := dev(Uart);
  572. available := Available(dev);
  573. IF available < len THEN len := available END;
  574. end := ofs + len;
  575. WHILE ofs < end DO
  576. buf[ofs] := uart.inbuffer[ uart.out ];
  577. uart.out := ( uart.out + 1 ) MOD UARTBUFLEN;
  578. INC( ofs )
  579. END;
  580. ELSE
  581. len := 0
  582. END
  583. END Read;
  584. PROCEDURE Flush( dev: Device.Device );
  585. VAR
  586. base: LONGINT;
  587. value : SET;
  588. BEGIN
  589. base := dev(Uart).baseAddr;
  590. Trace.String("*** Entering Flush : "); Trace.Hex( base, -8 ); Trace.Ln;
  591. REPEAT UNTIL Free( dev(Uart) ) = UARTBUFLEN - 1;
  592. REPEAT SYSTEM.GET( base+XUARTPS_SR_OFFSET, value ) UNTIL SR_TXEMPTY IN value;
  593. END Flush;
  594. PROCEDURE EmptyFifo( CONST no : LONGINT );
  595. VAR
  596. used, res: LONGINT;
  597. uart : Uart;
  598. BEGIN
  599. IF ( GetUartByIndex( no, uart )) THEN
  600. IF ( UartAvailable( uart )) THEN
  601. used := ( uart.in - uart.out ) MOD UARTBUFLEN;
  602. IF used < UARTBUFLEN - 1 THEN
  603. uart.inbuffer[ uart.in ] := ReceiveChar( uart, res );
  604. uart.in := ( uart.in + 1 ) MOD UARTBUFLEN;
  605. INC(used)
  606. END;
  607. END;
  608. END;
  609. END EmptyFifo;
  610. PROCEDURE CheckRxFifo( uart: Uart);
  611. VAR
  612. reg : SET;
  613. BEGIN
  614. IF ( UartAvailable( uart ) ) & ~uart.timeoutActive THEN
  615. (* Trace.String("(cr)"); *)
  616. (* if there is a char in the FIFO, set the timeout counter to IRQ on timeout *)
  617. SYSTEM.GET( uart.baseAddr+XUARTPS_CR_OFFSET, reg );
  618. reg := reg + { CTRLTORST };
  619. SYSTEM.PUT( uart.baseAddr+XUARTPS_CR_OFFSET, reg );
  620. uart.timeoutActive := TRUE;
  621. END;
  622. END CheckRxFifo;
  623. PROCEDURE CheckTxBuffer( uart : Uart );
  624. VAR
  625. reg : SET;
  626. BEGIN
  627. (* Trace.String("(ct)"); *)
  628. IF ( uart.oin # uart.oout ) & ( ~uart.txIrqActive ) THEN
  629. (* there is data in the buffer, arm the IRQ to trigger on empty TX FIFO *)
  630. SYSTEM.GET( uart.baseAddr+ XUARTPS_IER_OFFSET, reg );
  631. reg := reg + { IRQTXEMPTY };
  632. SYSTEM.PUT( uart.baseAddr+ XUARTPS_IER_OFFSET, reg );
  633. (* Trace.String("(ei)"); *)
  634. uart.txIrqActive := TRUE;
  635. UartHandler( uart, 2 );
  636. END;
  637. END CheckTxBuffer;
  638. PROCEDURE UartHandler( uart: Uart; CONST size : LONGINT );
  639. VAR
  640. res, k: LONGINT;
  641. BEGIN
  642. INC( uart.irqCnt );
  643. k := 0;
  644. WHILE ( uart.oin # uart.oout ) & ( k < size ) DO
  645. (*
  646. SendChar( uart, uart.outbuffer[uart.oout], res ); (* put to fifo *)
  647. Trace.String("out="); Trace.Hex( uart.out , -8 ); Trace.Ln;
  648. Trace.String("add="); Trace.Hex( ADDRESSOF( uart.outbuffer ), -8 ); Trace.Ln;
  649. *)
  650. SYSTEM.PUT32( uart.baseAddr+XUARTPS_FIFO_OFFSET, ORD( uart.outbuffer[ uart.oout ] ));
  651. uart.oout:= ( uart.oout+1 ) MOD UARTBUFLEN;
  652. INC(k)
  653. END;
  654. END UartHandler;
  655. PROCEDURE Command( dev: Device.Device; cmd, param: LONGINT; VAR res: LONGINT );
  656. VAR
  657. reg: SET;
  658. uart: Uart;
  659. BEGIN
  660. res := 0;
  661. uart := dev(Uart);
  662. CASE cmd OF
  663. UartConstants.SETBAUDRATE: uart.baudrate := param
  664. | UartConstants.SETPARITY: uart.parity := param
  665. | UartConstants.SETDATABITS: uart.databits := param
  666. END
  667. END Command;
  668. PROCEDURE DoUartCheck*();
  669. VAR
  670. uart : Uart;
  671. BEGIN
  672. CheckRxFifo( uarts[0] );
  673. CheckTxBuffer( uarts[0] );
  674. CheckRxFifo( uarts[1] );
  675. CheckTxBuffer( uarts[1] );
  676. END DoUartCheck;
  677. PROCEDURE Open( dev: Device.Device );
  678. VAR
  679. uart: Uart;
  680. res: LONGINT;
  681. BEGIN
  682. Trace.StringLn("Entering Open().");
  683. uart := dev(Uart);
  684. Trace.String("Open is trying to open id : "); Trace.Int( uart.id, 2); Trace.String(", "); Trace.Hex( uart.baseAddr, -8 ); Trace.Ln;
  685. IF ( uart = NIL ) THEN Trace.StringLn("Uart.Open( dev ) is nil"); END;
  686. IF ( uart.open ) THEN Trace.StringLn("Uart.Open( dev ) is open"); END;
  687. IF (uart # NIL) & (~uart.open) THEN
  688. Trace.StringLn("Setting baudrate and opening Uart.");
  689. (* reset the pointers to the ring buffer *)
  690. uart.in := 0;
  691. uart.out := 0;
  692. uart.oin := 0;
  693. uart.oout := 0;
  694. SetBaudrate( uart, uart.baudrate, res );
  695. Enable( uart, TRUE );
  696. uart.open := TRUE;
  697. ELSE
  698. Trace.StringLn("Uart.Open(dev) failed.");
  699. END
  700. END Open;
  701. (**
  702. Install all UART controllers present in the system (according to the constants set in Platform); to be called by the Kernel
  703. *)
  704. PROCEDURE Install*;
  705. VAR
  706. cfg: UartCfg;
  707. i, res: LONGINT;
  708. BEGIN
  709. Trace.StringLn("Entering UART install");
  710. FOR i := 0 TO UartNb-1 DO
  711. Trace.String("Init PSUART "); Trace.Int( i, 1 ); Trace.Ln;
  712. NEW( uarts[i] );
  713. (* init the object with the base initializer *)
  714. Device.InitDevice( uarts[ i ] );
  715. (* assign the function calls *)
  716. uarts[ i ].Open := Open;
  717. uarts[ i ].Close := Close;
  718. uarts[ i ].Write := Write;
  719. uarts[ i ].Read := Read;
  720. uarts[ i ].Available := Available;
  721. uarts[ i ].Free := Free;
  722. uarts[ i ].Command := Command;
  723. uarts[ i ].Flush := Flush;
  724. uarts[ i ].id := i;
  725. uarts[ i ].in := 0;
  726. uarts[ i ].out := 0;
  727. uarts[ i ].oin := 0;
  728. uarts[ i ].oout := 0;
  729. uarts[ i ].timeoutActive := FALSE;
  730. uarts[ i ].txIrqActive := FALSE;
  731. IF i = 0 THEN
  732. cfg.addr := UartBaseAddr0;
  733. ELSE
  734. cfg.addr := UartBaseAddr1;
  735. END;
  736. cfg.clock := UartInputClockHz;
  737. Trace.StringLn("Entering Init for PSUART");
  738. Init( uarts[i], cfg );
  739. Trace.StringLn("Exit Init().");
  740. (*IF ( i # 0 ) THEN
  741. SetBaudrate( uarts[i], 115200, res );
  742. Enable( uarts[i], FALSE ); (* disable *)
  743. uarts[ i ].open := FALSE;
  744. END;*)
  745. END;
  746. Interrupts.InstallHandler( PSUartIrqHandler, Interrupts.PSUART0IRQ );
  747. Interrupts.InstallHandler( PSUartIrqHandler, Interrupts.PSUART1IRQ );
  748. Device.Install( uarts[ PSUART0 ], "PSUART0" );
  749. Device.Install( uarts[ PSUART1 ], "PSUART1" );
  750. END Install;
  751. PROCEDURE Show*();
  752. BEGIN
  753. ShowUartSettings( 0 );
  754. ShowIrqStatus( 0 );
  755. ShowUartSettings( 1 );
  756. ShowIrqStatus( 1 );
  757. END Show;
  758. BEGIN
  759. END Uart.
  760. Uart.Show