uartgba.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. /*
  2. * Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. */
  32. /*
  33. * $Log$
  34. * Revision 1.5 2008/08/11 06:59:13 haraldkipp
  35. * BSD types replaced by stdint types (feature request #1282721).
  36. *
  37. * Revision 1.4 2007/08/29 07:43:52 haraldkipp
  38. * Documentation updated and corrected.
  39. *
  40. * Revision 1.3 2005/10/24 17:59:19 haraldkipp
  41. * Use correct header file, arm, not gba.
  42. *
  43. * Revision 1.2 2005/08/02 17:46:45 haraldkipp
  44. * Major API documentation update.
  45. *
  46. * Revision 1.1 2005/07/26 18:02:26 haraldkipp
  47. * Moved from dev.
  48. *
  49. * Revision 1.1 2005/04/05 18:01:43 haraldkipp
  50. * This code is buggy! Anyone willing to help?
  51. *
  52. */
  53. #include <sys/atom.h>
  54. #include <sys/event.h>
  55. #include <sys/timer.h>
  56. #include <dev/irqreg.h>
  57. #include <arch/arm.h>
  58. #include <dev/usart.h>
  59. #include <stdio.h>
  60. /*!
  61. * \addtogroup xgUartGba
  62. */
  63. /*@{*/
  64. /* \brief ASCII code for software flow control, starts transmitter. */
  65. #define ASCII_XON 0x11
  66. /* \brief ASCII code for software flow control, stops transmitter. */
  67. #define ASCII_XOFF 0x13
  68. /* \brief XON transmit pending flag. */
  69. #define XON_PENDING 0x10
  70. /* \brief XOFF transmit pending flag. */
  71. #define XOFF_PENDING 0x20
  72. /* \brief XOFF sent flag. */
  73. #define XOFF_SENT 0x40
  74. /* \brief XOFF received flag. */
  75. #define XOFF_RCVD 0x80
  76. /*!
  77. * \brief Receiver error flags.
  78. */
  79. //static ureg_t rx_errors;
  80. /*!
  81. * \brief Enables software flow control if not equal zero.
  82. */
  83. static ureg_t flow_control;
  84. static volatile ureg_t tx_stop = 1;
  85. static USARTDCB dcb_uart;
  86. /*
  87. * \brief USART0 transmit data register empty interrupt handler.
  88. *
  89. * \param arg Pointer to the transmitter ring buffer.
  90. */
  91. static void GbaUartTxEmpty(RINGBUF * rbf)
  92. {
  93. register uint8_t *cp = rbf->rbf_tail;
  94. /*
  95. * Process pending software flow controls first.
  96. */
  97. if (flow_control & (XON_PENDING | XOFF_PENDING)) {
  98. if (flow_control & XON_PENDING) {
  99. outw(REG_SIODATA8, ASCII_XOFF);
  100. flow_control |= XOFF_SENT;
  101. } else {
  102. outw(REG_SIODATA8, ASCII_XON);
  103. flow_control &= ~XOFF_SENT;
  104. }
  105. flow_control &= ~(XON_PENDING | XOFF_PENDING);
  106. return;
  107. }
  108. if (flow_control & XOFF_RCVD) {
  109. /*
  110. * If XOFF has been received, we disable the transmit interrupts
  111. * and return without sending anything.
  112. */
  113. tx_stop = 1;
  114. outw(REG_SIOCNT, inw(REG_SIOCNT) & ~SIO_SEND_ENA);
  115. return;
  116. }
  117. if (rbf->rbf_cnt) {
  118. rbf->rbf_cnt--;
  119. /*
  120. * Start transmission of the next character.
  121. */
  122. outw(REG_SIODATA8, *cp);
  123. /*
  124. * Wrap around the buffer pointer if we reached its end.
  125. */
  126. if (++cp == rbf->rbf_last) {
  127. cp = rbf->rbf_start;
  128. }
  129. rbf->rbf_tail = cp;
  130. if (rbf->rbf_cnt == rbf->rbf_lwm) {
  131. NutEventPostFromIrq(&rbf->rbf_que);
  132. NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_WRITE);
  133. }
  134. }
  135. /*
  136. * Nothing left to transmit, disable interrupt.
  137. */
  138. else {
  139. tx_stop = 1;
  140. outw(REG_SIOCNT, (inw(REG_SIOCNT) & ~SIO_SEND_ENA) | SIO_TX_FULL);
  141. rbf->rbf_cnt = 0;
  142. NutEventPostFromIrq(&rbf->rbf_que);
  143. NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_WRITE);
  144. }
  145. }
  146. /*
  147. * \brief USART0 receive complete interrupt handler.
  148. *
  149. *
  150. * \param arg Pointer to the receiver ring buffer.
  151. */
  152. static void GbaUartRxFull(RINGBUF * rbf)
  153. {
  154. register size_t cnt;
  155. register uint8_t ch;
  156. /*
  157. * We read the received character as early as possible to avoid overflows
  158. * caused by interrupt latency. However, reading the error flags must come
  159. * first, because reading the ATmega128 data register clears the status.
  160. */
  161. //TODO rx_errors |= inb(UCSRnA);
  162. ch = (uint8_t) inw(REG_SIODATA8);
  163. /*
  164. * Handle software handshake. We have to do this before checking the
  165. * buffer, because flow control must work in write-only mode, where
  166. * there is no receive buffer.
  167. */
  168. if (flow_control) {
  169. /* XOFF character disables transmit interrupts. */
  170. if (ch == ASCII_XOFF) {
  171. tx_stop = 1;
  172. outw(REG_SIOCNT, inw(REG_SIOCNT) & ~SIO_SEND_ENA);
  173. flow_control |= XOFF_RCVD;
  174. return;
  175. }
  176. /* XON enables transmit interrupts. */
  177. else if (ch == ASCII_XON) {
  178. tx_stop = 0; //TODO
  179. outw(REG_SIOCNT, inw(REG_SIOCNT) | SIO_SEND_ENA);
  180. flow_control &= ~XOFF_RCVD;
  181. return;
  182. }
  183. }
  184. /*
  185. * Check buffer overflow.
  186. */
  187. cnt = rbf->rbf_cnt;
  188. if (cnt >= rbf->rbf_siz) {
  189. //TODO rx_errors |= _BV(DOR);
  190. return;
  191. }
  192. /* Wake up waiting threads if this is the first byte in the buffer. */
  193. if (cnt++ == 0) {
  194. NutEventPostFromIrq(&rbf->rbf_que);
  195. NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_READ);
  196. }
  197. /*
  198. * Check the high watermark for software handshake. If the number of
  199. * buffered bytes is above this mark, then send XOFF.
  200. */
  201. else if (flow_control) {
  202. if (cnt >= rbf->rbf_hwm) {
  203. if ((flow_control & XOFF_SENT) == 0) {
  204. if (inw(REG_SIOCNT) & SIO_TX_FULL) {
  205. flow_control |= XOFF_PENDING;
  206. } else {
  207. outw(REG_SIODATA8, ASCII_XOFF);
  208. flow_control |= XOFF_SENT;
  209. flow_control &= ~XOFF_PENDING;
  210. }
  211. }
  212. }
  213. }
  214. /*
  215. * Store the character and increment and the ring buffer pointer.
  216. */
  217. *rbf->rbf_head++ = ch;
  218. if (rbf->rbf_head == rbf->rbf_last) {
  219. rbf->rbf_head = rbf->rbf_start;
  220. }
  221. /* Update the ring buffer counter. */
  222. rbf->rbf_cnt = cnt;
  223. }
  224. static void GbaUartIsr(void *arg)
  225. {
  226. /* Clear interrupt. */
  227. outw(REG_IF, INT_SIO);
  228. if ((inw(REG_SIOCNT) & SIO_RX_EMPTY) == 0) {
  229. GbaUartRxFull(&((USARTDCB *) arg)->dcb_rx_rbf);
  230. }
  231. if ((inw(REG_SIOCNT) & SIO_TX_FULL) == 0) {
  232. GbaUartTxEmpty(&((USARTDCB *) arg)->dcb_tx_rbf);
  233. }
  234. }
  235. /*!
  236. * \brief Carefully enable USART hardware functions.
  237. *
  238. * Always enabale transmitter and receiver, even on read-only or
  239. * write-only mode. So we can support software flow control.
  240. */
  241. static void GbaUartEnable(void)
  242. {
  243. NutEnterCritical();
  244. //TODO outb(UCSRnB, _BV(RXCIE) | _BV(UDRIE) | _BV(RXEN) | _BV(TXEN));
  245. NutExitCritical();
  246. }
  247. /*!
  248. * \brief Carefully disable USART hardware functions.
  249. */
  250. static void GbaUartDisable(void)
  251. {
  252. /*
  253. * Disable USART interrupts.
  254. */
  255. //TODO NutEnterCritical();
  256. //TODO cbi(UCSRnB, RXCIE);
  257. //TODO cbi(UCSRnB, TXCIE);
  258. //TODO cbi(UCSRnB, UDRIE);
  259. //TODO NutExitCritical();
  260. /*
  261. * Allow incoming or outgoing character to finish.
  262. */
  263. //TODO NutDelay(10);
  264. /*
  265. * Disable USART transmit and receive.
  266. */
  267. //TODO cbi(UCSRnB, RXEN);
  268. //TODO cbi(UCSRnB, TXEN);
  269. }
  270. /*!
  271. * \brief Query the USART hardware for the selected speed.
  272. *
  273. * This function is called by ioctl function of the upper level USART
  274. * driver through the USARTDCB jump table.
  275. *
  276. * \return The currently selected baudrate.
  277. */
  278. static uint32_t GbaUartGetSpeed(void)
  279. {
  280. uint16_t sv = inw(REG_SIOCNT);
  281. if ((sv & SIO_BAUD_115200) == SIO_BAUD_115200) {
  282. return 115200UL;
  283. }
  284. if ((sv & SIO_BAUD_57600) == SIO_BAUD_57600) {
  285. return 57600UL;
  286. }
  287. if ((sv & SIO_BAUD_38400) == SIO_BAUD_38400) {
  288. return 38400L;
  289. }
  290. return 9600UL;
  291. }
  292. /*!
  293. * \brief Set the USART hardware bit rate.
  294. *
  295. * This function is called by ioctl function of the upper level USART
  296. * driver through the USARTDCB jump table.
  297. *
  298. * \param rate Number of bits per second.
  299. *
  300. * \return 0 on success, -1 otherwise.
  301. */
  302. static int GbaUartSetSpeed(uint32_t rate)
  303. {
  304. uint16_t sv;
  305. GbaUartDisable();
  306. sv = inw(REG_SIOCNT) & ~SIO_BAUD_115200;
  307. if (rate == 115200) {
  308. sv |= SIO_BAUD_115200;
  309. } else {
  310. if (rate == 57600) {
  311. sv |= SIO_BAUD_57600;
  312. } else if (rate == 38400) {
  313. sv |= SIO_BAUD_38400;
  314. }
  315. }
  316. outw(REG_SIOCNT, sv);
  317. GbaUartEnable();
  318. return 0;
  319. }
  320. /*!
  321. * \brief Query the USART hardware for the number of data bits.
  322. *
  323. * This function is called by ioctl function of the upper level USART
  324. * driver through the USARTDCB jump table.
  325. *
  326. * \return The number of data bits set.
  327. */
  328. static uint8_t GbaUartGetDataBits(void)
  329. {
  330. return 8;
  331. }
  332. /*!
  333. * \brief Set the USART hardware to the number of data bits.
  334. *
  335. * This function is called by ioctl function of the upper level USART
  336. * driver through the USARTDCB jump table.
  337. *
  338. * \return 0 on success, -1 otherwise.
  339. */
  340. static int GbaUartSetDataBits(uint8_t bits)
  341. {
  342. GbaUartDisable();
  343. GbaUartEnable();
  344. /*
  345. * Verify the result.
  346. */
  347. if (GbaUartGetDataBits() != bits) {
  348. return -1;
  349. }
  350. return 0;
  351. }
  352. /*!
  353. * \brief Query the USART hardware for the parity mode.
  354. *
  355. * This routine is called by ioctl function of the upper level USART
  356. * driver through the USARTDCB jump table.
  357. *
  358. * \return Parity mode, either 0 (disabled), 1 (odd) or 2 (even).
  359. */
  360. static uint8_t GbaUartGetParity(void)
  361. {
  362. return 0;
  363. }
  364. /*!
  365. * \brief Set the USART hardware to the specified parity mode.
  366. *
  367. * This routine is called by ioctl function of the upper level USART
  368. * driver through the USARTDCB jump table.
  369. *
  370. * \param mode 0 (disabled), 1 (odd) or 2 (even)
  371. *
  372. * \return 0 on success, -1 otherwise.
  373. */
  374. static int GbaUartSetParity(uint8_t mode)
  375. {
  376. GbaUartDisable();
  377. GbaUartEnable();
  378. /*
  379. * Verify the result.
  380. */
  381. if (GbaUartGetParity() != mode) {
  382. return -1;
  383. }
  384. return 0;
  385. }
  386. /*!
  387. * \brief Query the USART hardware for the number of stop bits.
  388. *
  389. * This routine is called by ioctl function of the upper level USART
  390. * driver through the USARTDCB jump table.
  391. *
  392. * \return The number of stop bits set, either 1 or 2.
  393. */
  394. static uint8_t GbaUartGetStopBits(void)
  395. {
  396. return 1;
  397. }
  398. /*!
  399. * \brief Set the USART hardware to the number of stop bits.
  400. *
  401. * This routine is called by ioctl function of the upper level USART
  402. * driver through the USARTDCB jump table.
  403. *
  404. * \return 0 on success, -1 otherwise.
  405. */
  406. static int GbaUartSetStopBits(uint8_t bits)
  407. {
  408. GbaUartDisable();
  409. GbaUartEnable();
  410. /*
  411. * Verify the result.
  412. */
  413. if (GbaUartGetStopBits() != bits) {
  414. return -1;
  415. }
  416. return 0;
  417. }
  418. /*!
  419. * \brief Query the USART hardware status.
  420. *
  421. * \return Status flags.
  422. */
  423. static uint32_t GbaUartGetStatus(void)
  424. {
  425. uint32_t rc = 0;
  426. /*
  427. * Set receiver error flags.
  428. */
  429. /*
  430. * Determine software handshake status. The flow control status may
  431. * change during interrupt, but this doesn't really hurt us.
  432. */
  433. if (flow_control) {
  434. if (flow_control & XOFF_SENT) {
  435. rc |= UART_RXDISABLED;
  436. }
  437. if (flow_control & XOFF_RCVD) {
  438. rc |= UART_TXDISABLED;
  439. }
  440. }
  441. /*
  442. * If transmitter and receiver haven't been detected disabled by any
  443. * of the checks above, then they are probably enabled.
  444. */
  445. if ((rc & UART_RXDISABLED) == 0) {
  446. rc |= UART_RXENABLED;
  447. }
  448. if ((rc & UART_TXDISABLED) == 0) {
  449. rc |= UART_TXENABLED;
  450. }
  451. return rc;
  452. }
  453. /*!
  454. * \brief Set the USART hardware status.
  455. *
  456. * \param flags Status flags.
  457. *
  458. * \return 0 on success, -1 otherwise.
  459. */
  460. static int GbaUartSetStatus(uint32_t flags)
  461. {
  462. /*
  463. * Process software handshake control.
  464. */
  465. if (flow_control) {
  466. /* Access to the flow control status must be atomic. */
  467. NutEnterCritical();
  468. /*
  469. * Enabling or disabling the receiver means to behave like
  470. * having sent a XON or XOFF character resp.
  471. */
  472. if (flags & UART_RXENABLED) {
  473. flow_control &= ~XOFF_SENT;
  474. } else if (flags & UART_RXDISABLED) {
  475. flow_control |= XOFF_SENT;
  476. }
  477. /*
  478. * Enabling or disabling the transmitter means to behave like
  479. * having received a XON or XOFF character resp.
  480. */
  481. if (flags & UART_TXENABLED) {
  482. flow_control &= ~XOFF_RCVD;
  483. } else if (flags & UART_TXDISABLED) {
  484. flow_control |= XOFF_RCVD;
  485. }
  486. NutExitCritical();
  487. }
  488. /*
  489. * Verify the result.
  490. */
  491. if ((GbaUartGetStatus() & ~UART_ERRORS) != flags) {
  492. return -1;
  493. }
  494. return 0;
  495. }
  496. /*!
  497. * \brief Query the USART hardware for synchronous mode.
  498. *
  499. * This function is called by ioctl function of the upper level USART
  500. * driver through the USARTDCB jump table.
  501. *
  502. * \return Or-ed combination of \ref UART_SYNC, \ref UART_MASTER,
  503. * \ref UART_NCLOCK and \ref UART_HIGHSPEED.
  504. */
  505. static uint8_t GbaUartGetClockMode(void)
  506. {
  507. return 0;
  508. }
  509. /*!
  510. * \brief Set asynchronous or synchronous mode.
  511. *
  512. * This function is called by ioctl function of the upper level USART
  513. * driver through the USARTDCB jump table.
  514. *
  515. * \param mode Must be an or-ed combination of USART_SYNC, USART_MASTER,
  516. * USART_NCLOCK and USART_HIGHSPEED.
  517. *
  518. * \return 0 on success, -1 otherwise.
  519. */
  520. static int GbaUartSetClockMode(uint8_t mode)
  521. {
  522. /*
  523. * Verify the result.
  524. */
  525. if (GbaUartGetClockMode() != mode) {
  526. return -1;
  527. }
  528. return 0;
  529. }
  530. /*!
  531. * \brief Query flow control mode.
  532. *
  533. * This routine is called by ioctl function of the upper level USART
  534. * driver through the USARTDCB jump table.
  535. *
  536. * \return See UsartIOCtl().
  537. */
  538. static uint32_t GbaUartGetFlowControl(void)
  539. {
  540. uint32_t rc = 0;
  541. if (flow_control) {
  542. rc |= USART_MF_XONXOFF;
  543. } else {
  544. rc &= ~USART_MF_XONXOFF;
  545. }
  546. return rc;
  547. }
  548. /*!
  549. * \brief Set flow control mode.
  550. *
  551. * This function is called by ioctl function of the upper level USART
  552. * driver through the USARTDCB jump table.
  553. *
  554. * \param flags See UsartIOCtl().
  555. *
  556. * \return 0 on success, -1 otherwise.
  557. */
  558. static int GbaUartSetFlowControl(uint32_t flags)
  559. {
  560. /*
  561. * Set software handshake mode.
  562. */
  563. if (flags & USART_MF_XONXOFF) {
  564. if (flow_control == 0) {
  565. NutEnterCritical();
  566. flow_control = 1 | XOFF_SENT; /* force XON to be sent on next read */
  567. NutExitCritical();
  568. }
  569. } else {
  570. NutEnterCritical();
  571. flow_control = 0;
  572. NutExitCritical();
  573. }
  574. /*
  575. * Verify the result.
  576. */
  577. if (GbaUartGetFlowControl() != flags) {
  578. return -1;
  579. }
  580. return 0;
  581. }
  582. /*!
  583. * \brief Start the USART transmitter hardware.
  584. *
  585. * The upper level USART driver will call this function through the
  586. * USARTDCB jump table each time it added one or more bytes to the
  587. * transmit buffer.
  588. */
  589. static void GbaUartTxStart(void)
  590. {
  591. RINGBUF *rbf = &dcb_uart.dcb_tx_rbf;
  592. register uint8_t *cp = rbf->rbf_tail;
  593. NutEnterCritical();
  594. if(tx_stop) {
  595. if (rbf->rbf_cnt) {
  596. rbf->rbf_cnt--;
  597. outw(REG_SIODATA8, *cp);
  598. if (++cp == rbf->rbf_last) {
  599. cp = rbf->rbf_start;
  600. }
  601. rbf->rbf_tail = cp;
  602. tx_stop = 0;
  603. }
  604. }
  605. outw(REG_SIOCNT, inw(REG_SIOCNT) | SIO_SEND_ENA);
  606. NutExitCritical();
  607. }
  608. /*!
  609. * \brief Start the USART receiver hardware.
  610. *
  611. * The upper level USART driver will call this function through the
  612. * USARTDCB jump table each time it removed enough bytes from the
  613. * receive buffer. Enough means, that the number of bytes left in
  614. * the buffer is below the low watermark.
  615. */
  616. static void GbaUartRxStart(void)
  617. {
  618. /*
  619. * Do any required software flow control.
  620. */
  621. NutEnterCritical();
  622. if (flow_control && (flow_control & XOFF_SENT) != 0) {
  623. if (inw(REG_SIOCNT) & SIO_TX_FULL) {
  624. flow_control |= XON_PENDING;
  625. } else {
  626. outw(REG_SIODATA8, ASCII_XON);
  627. flow_control &= ~XON_PENDING;
  628. }
  629. flow_control &= ~(XOFF_SENT | XOFF_PENDING);
  630. }
  631. outw(REG_SIOCNT, inw(REG_SIOCNT) | SIO_RECV_ENA);
  632. NutExitCritical();
  633. }
  634. /*
  635. * \brief Initialize the USART hardware driver.
  636. *
  637. * This function is called during device registration by the upper level
  638. * USART driver through the USARTDCB jump table.
  639. *
  640. * \return 0 on success, -1 otherwise.
  641. */
  642. static int GbaUartInit(void)
  643. {
  644. int rc;
  645. /*
  646. * Activate MBV2 UART mode by setting SC low and SD high for at
  647. * least 50 milliseconds.
  648. */
  649. outw(REG_RCNT, 0x8032);
  650. NutSleep(100);
  651. /* Disable master interrupt. */
  652. outw(REG_IME, 0);
  653. /* Register our interrupt service. */
  654. if((rc = NutRegisterIrqHandler(&sig_SIO, GbaUartIsr, &dcb_uart)) == 0) {
  655. /* Enable UART mode. */
  656. outw(REG_RCNT, 0x0000);
  657. /* Set UART mode */
  658. outw(REG_SIOCNT, SIO_IRQ_ENA | SIO_MODE_UART | SIO_DATA_8BIT | SIO_BAUD_38400);
  659. /* Clear receive/transmit */
  660. outw(REG_SIOCNT, inw(REG_SIOCNT) | SIO_RX_EMPTY | SIO_TX_FULL);
  661. /* Enable FIFO. */
  662. //outw(REG_SIOCNT, inw(REG_SIOCNT) | SIO_FIFO_ENA);
  663. /* Enable SIO interrupts. */
  664. outw(REG_IE, inw(REG_IE) | INT_SIO);
  665. }
  666. printf("I[%04X]", inw(REG_SIOCNT));
  667. /* Enable master interrupt. */
  668. outw(REG_IME, 1);
  669. return rc;
  670. }
  671. /*
  672. * \brief Deinitialize the USART hardware driver.
  673. *
  674. * This function is called during device deregistration by the upper
  675. * level USART driver through the USARTDCB jump table.
  676. *
  677. * \return 0 on success, -1 otherwise.
  678. */
  679. static int GbaUartDeinit(void)
  680. {
  681. /* Deregister receive and transmit interrupts. */
  682. NutRegisterIrqHandler(&sig_SIO, 0, 0);
  683. return 0;
  684. }
  685. #if 1
  686. /*!
  687. * \brief UART0 device control block structure.
  688. */
  689. static USARTDCB dcb_uart = {
  690. 0, /* dcb_modeflags */
  691. 0, /* dcb_statusflags */
  692. 0, /* dcb_rtimeout */
  693. 0, /* dcb_wtimeout */
  694. {0, 0, 0, 0, 0, 0, 0, 0}, /* dcb_tx_rbf */
  695. {0, 0, 0, 0, 0, 0, 0, 0}, /* dcb_rx_rbf */
  696. 0, /* dbc_last_eol */
  697. GbaUartInit, /* dcb_init */
  698. GbaUartDeinit, /* dcb_deinit */
  699. GbaUartTxStart, /* dcb_tx_start */
  700. GbaUartRxStart, /* dcb_rx_start */
  701. GbaUartSetFlowControl, /* dcb_set_flow_control */
  702. GbaUartGetFlowControl, /* dcb_get_flow_control */
  703. GbaUartSetSpeed, /* dcb_set_speed */
  704. GbaUartGetSpeed, /* dcb_get_speed */
  705. GbaUartSetDataBits, /* dcb_set_data_bits */
  706. GbaUartGetDataBits, /* dcb_get_data_bits */
  707. GbaUartSetParity, /* dcb_set_parity */
  708. GbaUartGetParity, /* dcb_get_parity */
  709. GbaUartSetStopBits, /* dcb_set_stop_bits */
  710. GbaUartGetStopBits, /* dcb_get_stop_bits */
  711. GbaUartSetStatus, /* dcb_set_status */
  712. GbaUartGetStatus, /* dcb_get_status */
  713. GbaUartSetClockMode, /* dcb_set_clock_mode */
  714. GbaUartGetClockMode, /* dcb_get_clock_mode */
  715. };
  716. /*!
  717. * \name AVR USART0 Device
  718. */
  719. /*@{*/
  720. /*!
  721. * \brief USART0 device information structure.
  722. *
  723. * An application must pass a pointer to this structure to
  724. * NutRegisterDevice() before using the serial communication
  725. * driver of the AVR's on-chip USART0.
  726. *
  727. * The device is named \b uart0.
  728. *
  729. * \showinitializer
  730. */
  731. NUTDEVICE devUartGba = {
  732. 0, /* Pointer to next device, dev_next. */
  733. {'u', 'a', 'r', 't', '0', 0, 0, 0, 0}, /* Unique device name, dev_name. */
  734. IFTYP_CHAR, /* Type of device, dev_type. */
  735. 0, /* Base address, dev_base (not used). */
  736. 0, /* First interrupt number, dev_irq (not used). */
  737. 0, /* Interface control block, dev_icb (not used). */
  738. &dcb_uart, /* Driver control block, dev_dcb. */
  739. UsartInit, /* Driver initialization routine, dev_init. */
  740. UsartIOCtl, /* Driver specific control function, dev_ioctl. */
  741. UsartRead, /* Read from device, dev_read. */
  742. UsartWrite, /* Write to device, dev_write. */
  743. UsartOpen, /* Open a device or file, dev_open. */
  744. UsartClose, /* Close a device or file, dev_close. */
  745. UsartSize, /* Request file size, dev_size. */
  746. UsartSelect, /* Select function, dev_select */
  747. };
  748. #endif
  749. /*@}*/
  750. /*@}*/