lpc17xx_usart.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352
  1. /*
  2. * Copyright (C) 2012 by Ole Reinhardt (ole.reinhardt@embedded-it.de)
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. */
  34. /*
  35. * \verbatim
  36. * $Id: $
  37. * \endverbatim
  38. */
  39. #include <inttypes.h>
  40. #include <cfg/clock.h>
  41. #include <sys/timer.h>
  42. #include <dev/irqreg.h>
  43. #include <dev/usart.h>
  44. #if defined(MCU_LPC176x)
  45. #include <arch/cm3/nxp/lpc176x.h>
  46. #include <arch/cm3/nxp/lpc176x_clk.h>
  47. #include <arch/cm3/nxp/lpc176x_gpio.h>
  48. #elif defined(MCU_LPC177x_8x)
  49. #include <arch/cm3/nxp/lpc177x_8x.h>
  50. #include <arch/cm3/nxp/lpc177x_8x_clk.h>
  51. #include <arch/cm3/nxp/lpc177x_8x_gpio.h>
  52. #elif defined(MCU_LPC407x_8x)
  53. #include <arch/cm3/nxp/lpc407x_8x.h>
  54. #include <arch/cm3/nxp/lpc407x_8x_clk.h>
  55. #include <arch/cm3/nxp/lpc177x_8x_gpio.h>
  56. #else
  57. #warning "Unknown LPC familiy"
  58. #endif
  59. #include <arch/cm3/nxp/lpc17xx_usart.h>
  60. #if defined(UART_DMA_TXCHANNEL) || defined(UART_DMA_RXCHANNEL)
  61. #include <arch/cm3/nxp/lpc17xx_gpdma.h>
  62. #endif
  63. /*!
  64. * \addtogroup xgNutArchArmLpc17xxUsart
  65. */
  66. /*@{*/
  67. #if defined(UART_XONXOFF_CONTROL)
  68. /* \brief ASCII code for software flow control, starts transmitter. */
  69. #define ASCII_XON 0x11
  70. /* \brief ASCII code for software flow control, stops transmitter. */
  71. #define ASCII_XOFF 0x13
  72. /* \brief XON transmit pending flag. */
  73. #define XON_PENDING 0x10
  74. /* \brief XOFF transmit pending flag. */
  75. #define XOFF_PENDING 0x20
  76. /* \brief XOFF sent flag. */
  77. #define XOFF_SENT 0x40
  78. /* \brief XOFF received flag. */
  79. #define XOFF_RCVD 0x80
  80. #endif
  81. /* USART default speed if not preset by nutconfig */
  82. #ifndef USART_INIT_BAUTRATE
  83. #define USART_INIT_BAUTRATE USART_INITSPEED
  84. #endif
  85. #define NutUartIrqEnable NutIrqEnable
  86. #define NutUartIrqDisable NutIrqDisable
  87. /*!
  88. * \brief Receiver error flags.
  89. */
  90. static uint16_t rx_errors = 0;
  91. #if defined(US_MODE_HWHANDSHAKE)
  92. /*!
  93. * \brief Enables RTS control if not equal zero.
  94. *
  95. * This variable exists only if the hardware configuration defines a
  96. * port bit to control the RTS signal.
  97. */
  98. static uint_fast8_t rts_control = 0;
  99. /*!
  100. * \brief Enables CTS sense if not equal zero.
  101. *
  102. * This variable exists only if the hardware configuration defines a
  103. * port bit to sense the CTS signal.
  104. */
  105. static uint_fast8_t cts_sense = 0;
  106. #endif
  107. #if defined(UART_XONXOFF_CONTROL)
  108. /*!
  109. * \brief Handles local software flow control.
  110. *
  111. * This variable exists only if the hardware configuration defines a
  112. * software flow control support.
  113. */
  114. static uint_fast8_t flow_control = 0;
  115. #endif
  116. #if defined(UART_DMA_TXCHANNEL) || defined(UART_DMA_RXCHANNEL)
  117. /*!
  118. * \brief Handles local DMA block read/write control.
  119. *
  120. */
  121. static uint_fast8_t block_control;
  122. #define BC_RD_EN 0x01
  123. #define BC_WR_EN 0x02
  124. #endif
  125. #if 0 // TODO: DMA
  126. #ifdef UART_DMA_TXCHANNEL
  127. static void Lpc17xxUsartDmaTxIrq(void* arg)
  128. {
  129. NutEventPost(arg);
  130. NutSelectWakeupFromIrq();
  131. }
  132. #endif
  133. #ifdef UART_DMA_RXCHANNEL
  134. static void Lpc17xxUsartDmaRxIrq(void* arg)
  135. {
  136. NutEventPost(arg);
  137. NutSelectWakeupFromIrq();
  138. }
  139. #endif
  140. #endif
  141. /*
  142. * \brief USARTn transmitter ready interrupt handler.
  143. *
  144. * \param rbf Pointer to the transmitter ring buffer.
  145. */
  146. static void Lpc17xxUsartTxReady(RINGBUF * rbf, uint32_t lsr)
  147. {
  148. register uint8_t *cp = rbf->rbf_tail;
  149. #ifdef UART_DMA_TXCHANNEL
  150. // TODO: Implement DMA support
  151. #endif
  152. #if defined(UART_XONXOFF_CONTROL)
  153. /*
  154. * Process pending software flow controls first.
  155. */
  156. if (flow_control & (XON_PENDING | XOFF_PENDING)) {
  157. if (flow_control & XON_PENDING) {
  158. /* Send XOFF */
  159. USARTn->THR = ASCII_XOFF;
  160. flow_control |= XOFF_SENT;
  161. } else {
  162. /* Send XON */
  163. USARTn->THR = ASCII_XON;
  164. flow_control &= ~XOFF_SENT;
  165. }
  166. flow_control &= ~(XON_PENDING | XOFF_PENDING);
  167. return;
  168. }
  169. if (flow_control & XOFF_RCVD) {
  170. /*
  171. * If XOFF has been received, we disable the transmit interrupts
  172. * and return without sending anything.
  173. */
  174. /* Disable transmitter and transmitter interrupt */
  175. USARTn->TER = 0;
  176. CM3BBCLR(USARTnBase, LPC_UART_TypeDef, IER, UART_IER_THREINT_EN_POS);
  177. return;
  178. }
  179. #endif
  180. /*
  181. * Check if we have more bytes to transmit anf if there is still space in the TX FIFO
  182. */
  183. while ((rbf->rbf_cnt) && (USARTn->LSR & UART_LSR_THRE)) {
  184. /*
  185. * If CTS has been disabled, we disable the transmit interrupts,
  186. * enable CTS interrupts and return without sending anything.
  187. */
  188. // TODO: CTS handling in here
  189. /* Start transmission of the next character. */
  190. USARTn->THR = *cp;
  191. /* Decrement the number of available bytes in the buffer. */
  192. rbf->rbf_cnt--;
  193. /* Wrap around the buffer pointer if we reached its end. */
  194. if (++cp == rbf->rbf_last) {
  195. cp = rbf->rbf_start;
  196. }
  197. rbf->rbf_tail = cp;
  198. /* Send an event if we reached the low watermark. */
  199. if (rbf->rbf_cnt == rbf->rbf_lwm) {
  200. NutEventPostFromIrq(&rbf->rbf_que);
  201. NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_WRITE);
  202. }
  203. }
  204. if ( rbf->rbf_cnt==0) {
  205. /* Nothing left to transmit: Disable transmit interrupts. */
  206. CM3BBCLR(USARTnBase, LPC_UART_TypeDef, IER, UART_IER_THREINT_EN_POS);
  207. NutEventPostFromIrq(&rbf->rbf_que);
  208. NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_WRITE);
  209. }
  210. }
  211. /*
  212. * \brief USARTn receiver ready interrupt handler.
  213. *
  214. *
  215. * \param rbf Pointer to the receiver ring buffer.
  216. */
  217. static void Lpc17xxUsartRxReady(RINGBUF * rbf, uint32_t lsr)
  218. {
  219. register size_t cnt;
  220. register uint8_t ch;
  221. #ifdef UART_DMA_RXCHANNEL
  222. // TODO: Implement DMA support
  223. #endif
  224. while (lsr & UART_LSR_RDR) {
  225. /*
  226. * We read the received character as early as possible to avoid overflows
  227. * caused by interrupt latency.
  228. */
  229. ch = USARTn->RBR & UART_RBR_MASK;
  230. /* Collect receiver errors. */
  231. rx_errors |= lsr & (UART_LSR_OE | UART_LSR_PE | UART_LSR_FE | UART_LSR_BI);
  232. #if defined(UART_XONXOFF_CONTROL)
  233. /*
  234. * Handle software handshake. We have to do this before checking the
  235. * buffer, because flow control must work in write-only mode, where
  236. * there is no receive buffer.
  237. */
  238. if (flow_control) {
  239. /* XOFF character disables transmit interrupts. */
  240. if (ch == ASCII_XOFF) {
  241. /* Disable transmitter and transmitter interrupt */
  242. USARTn->TER = 0;
  243. CM3BBCLR(USARTnBase, LPC_UART_TypeDef, IER, UART_IER_THREINT_EN_POS);
  244. flow_control |= XOFF_RCVD;
  245. return;
  246. }
  247. /* XON enables transmit interrupts. */
  248. else if (ch == ASCII_XON) {
  249. /* Disable transmitter and transmitter interrupt */
  250. USARTn->TER = UART_TER_TXEN;
  251. CM3BBSET(USARTnBase, LPC_UART_TypeDef, IER, UART_IER_THREINT_EN_POS);
  252. flow_control &= ~XOFF_RCVD;
  253. return;
  254. }
  255. }
  256. #endif
  257. /*
  258. * Check buffer overflow.
  259. */
  260. cnt = rbf->rbf_cnt;
  261. if (cnt >= rbf->rbf_siz) {
  262. // TODO: We use the same flag like when we got a FIFO overrun error
  263. rx_errors |= UART_LSR_OE;
  264. return;
  265. }
  266. /* Wake up waiting threads if this is the first byte in the buffer. */
  267. if (cnt++ == 0) {
  268. NutEventPostFromIrq(&rbf->rbf_que);
  269. NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_READ);
  270. }
  271. #if defined(UART_XONXOFF_CONTROL)
  272. /*
  273. * Check the high watermark for software handshake. If the number of
  274. * buffered bytes is equal or above this mark, then send XOFF.
  275. */
  276. else if (flow_control) {
  277. if(cnt >= rbf->rbf_hwm) {
  278. if((flow_control & XOFF_SENT) == 0) {
  279. /* Check it TX on and space in the FIFO, then send xoff */
  280. if ((CM3BBGET(USARTnBase, LPC_UART_TypeDef, IER, UART_IER_THREINT_EN_POS)) &&
  281. (lsr & UART_LSR_THRE)) {
  282. USARTn->THR = ASCII_XOFF;
  283. flow_control |= XOFF_SENT;
  284. flow_control &= ~XOFF_PENDING;
  285. } else {
  286. flow_control |= XOFF_PENDING;
  287. }
  288. }
  289. }
  290. }
  291. #endif
  292. #ifdef US_MODE_HWHANDSHAKE
  293. /*
  294. * Check the high watermark for hardware handshake. If the number of
  295. * buffered bytes is above this mark, then disable RTS.
  296. */
  297. else if (rts_control && cnt >= rbf->rbf_hwm) {
  298. // TODO: Disable RTS
  299. // USARTn->CR3 |= USART_CR3_RTSE;
  300. }
  301. #endif
  302. /*
  303. * Store the character and increment and the ring buffer pointer.
  304. */
  305. *rbf->rbf_head++ = ch;
  306. if (rbf->rbf_head == rbf->rbf_last) {
  307. rbf->rbf_head = rbf->rbf_start;
  308. }
  309. /* Update the ring buffer counter. */
  310. rbf->rbf_cnt = cnt;
  311. /* update the LSR shadow variable */
  312. lsr = USARTn->LSR;
  313. }
  314. }
  315. /*!
  316. * \brief USART interrupt handler.
  317. *
  318. * \param arg Pointer to the device specific control block.
  319. */
  320. static void Lpc17xxUsartInterrupt(void *arg)
  321. {
  322. USARTDCB *dcb = (USARTDCB *) arg;
  323. /* Read line status and interrupt identification register */
  324. uint32_t iir = USARTn->IIR & UART_IIR_INTID_MASK;
  325. uint32_t intid = iir & UART_IIR_INTID_MASK;
  326. uint32_t lsr = USARTn->LSR;
  327. if (intid == UART_IIR_INTID_RLS) {
  328. // TODO: Implement Line Status
  329. // Lpc17xxUsartRxLineStatus(&dcb->dcb_rx_rbf);
  330. } else
  331. /* Test for byte received or character timeout */
  332. if ((intid == UART_IIR_INTID_RDA) || (intid == UART_IIR_INTID_CTI)) {
  333. Lpc17xxUsartRxReady(&dcb->dcb_rx_rbf, lsr);
  334. } else
  335. /* Test for next byte can be transmitted (transmit holding is empty) */
  336. if (intid == UART_IIR_INTID_THRE) {
  337. Lpc17xxUsartTxReady(&dcb->dcb_tx_rbf, lsr);
  338. }
  339. }
  340. /*!
  341. * \brief Carefully enable USART hardware functions.
  342. *
  343. * Always enabale transmitter and receiver, even on read-only or
  344. * write-only mode. So we can support software flow control.
  345. */
  346. static void Lpc17xxUsartEnable(void)
  347. {
  348. /* Enable UART transmitter. The receiver can not be enabled seperately on
  349. the LPC architecture. We just could disable the RX FIFOs, is this a
  350. good idea?
  351. */
  352. USARTn->TER = UART_TER_TXEN;
  353. /* Enable Usart Interrupts */
  354. NutUartIrqEnable(&SigUSART);
  355. }
  356. /*!
  357. * \brief Carefully disable USART hardware functions.
  358. *
  359. * TODO: Beschreibung anpassen
  360. * This routine is called before changing cruical settings like
  361. * baudrate, frame format etc.
  362. *
  363. * The previous version uses a 10ms delay to make sure, that any
  364. * incoming or outgoing character is processed. However, this time
  365. * depends on the baudrate.
  366. *
  367. * In fact we do not need to take care of incoming characters,
  368. * when changing such settings.
  369. *
  370. * For outgoing characters however, settings may be changed on
  371. * the fly and we should wait, until the last character transmitted
  372. * with the old settings has left the shift register. While TXRDY
  373. * is set when the holding register is empty, TXEMPTY is set when the
  374. * shift register is empty. The bad news is, that both are zero, if
  375. * the transmitter is disabled. We are not able to determine this
  376. * state. So we check TXRDY first and, if set, wait for any character
  377. * currently in the shift register.
  378. */
  379. static void Lpc17xxUsartDisable(void)
  380. {
  381. /* Disable Usart Interrupts*/
  382. NutUartIrqDisable(&SigUSART);
  383. /* If the transmitter is enabled, wait until all bits had been shifted out. */
  384. if (USARTn->TER & UART_TER_TXEN) {
  385. while ((USARTn->LSR & UART_LSR_TEMT) == 0);
  386. }
  387. /* Disable Transmitter, receiver can not be disabled on the LPC
  388. architecture. We just could disable the RX FIFOs, is this a good idea?
  389. */
  390. USARTn->TER = 0;
  391. }
  392. /*!
  393. * \brief Query the USART hardware for the selected speed.
  394. *
  395. * This function is called by ioctl function of the upper level USART
  396. * driver through the USARTDCB jump table.
  397. *
  398. * \return The currently selected baudrate.
  399. */
  400. static uint32_t Lpc17xxUsartGetSpeed(void)
  401. {
  402. uint32_t clk = 0;
  403. // TODO: Implement!
  404. return clk;
  405. }
  406. /*!
  407. * \brief Set the USART hardware bit rate.
  408. *
  409. * This function is called by ioctl function of the upper level USART
  410. * driver through the USARTDCB jump table.
  411. *
  412. * \param rate Number of bits per second.
  413. *
  414. * \return 0 on success, -1 otherwise.
  415. */
  416. static int Lpc17xxUsartSetSpeed(uint32_t baudrate)
  417. {
  418. uint32_t uart_clock;
  419. uint32_t calcBaudrate = 0;
  420. uint32_t temp = 0;
  421. uint32_t mulFracDiv, dividerAddFracDiv;
  422. uint32_t diviser = 0 ;
  423. uint32_t bestm = 1;
  424. uint32_t bestd = 0;
  425. uint32_t best_divisor = 0;
  426. uint32_t relativeError = 0;
  427. uint32_t best_error = 100000;
  428. /* get UART block clock */
  429. uart_clock = NutArchClockGet(NUT_HWCLK_PCLK);
  430. #if defined(MCU_LPC176x)
  431. if ((LPC_UART_TypeDef*)USARTn == LPC_UART0) {
  432. uart_clock /= Lpc176x_PclkDivGet(CLKPWR_PCLKSEL_UART0);
  433. } else
  434. if ((LPC_UART1_TypeDef*)USARTn == LPC_UART1) {
  435. uart_clock /= Lpc176x_PclkDivGet(CLKPWR_PCLKSEL_UART1);
  436. } else
  437. if ((LPC_UART_TypeDef*)USARTn == LPC_UART2) {
  438. uart_clock /= Lpc176x_PclkDivGet(CLKPWR_PCLKSEL_UART2);
  439. } else
  440. if ((LPC_UART_TypeDef*)USARTn == LPC_UART3) {
  441. uart_clock /= Lpc176x_PclkDivGet(CLKPWR_PCLKSEL_UART3);
  442. }
  443. #endif
  444. uart_clock = uart_clock >> 4; /* div by 16 */
  445. /* Baudrate calculation is done according the following formula:
  446. BaudRate= uart_clock * (mulFracDiv/(mulFracDiv+dividerAddFracDiv) / (16 * (DLL)
  447. To avoid floating point calculation the formulae is adjusted with the
  448. multiply and divide method.
  449. The value of mulFracDiv and dividerAddFracDiv should comply to the following expressions:
  450. 0 < mulFracDiv <= 15, 0 <= dividerAddFracDiv <= 15
  451. */
  452. for (mulFracDiv = 1 ; mulFracDiv <= 15 ;mulFracDiv++)
  453. {
  454. for (dividerAddFracDiv = 0 ; dividerAddFracDiv <= 15 ;dividerAddFracDiv++)
  455. {
  456. temp = (mulFracDiv * uart_clock) / ((mulFracDiv + dividerAddFracDiv));
  457. diviser = temp / baudrate;
  458. if ((temp % baudrate) > (baudrate / 2))
  459. diviser++;
  460. if (diviser > 2 && diviser < 65536)
  461. {
  462. calcBaudrate = temp / diviser;
  463. if (calcBaudrate <= baudrate) {
  464. relativeError = baudrate - calcBaudrate;
  465. } else {
  466. relativeError = calcBaudrate - baudrate;
  467. }
  468. if ((relativeError < best_error))
  469. {
  470. bestm = mulFracDiv ;
  471. bestd = dividerAddFracDiv;
  472. best_divisor = diviser;
  473. best_error = relativeError;
  474. if (relativeError == 0) {
  475. break;
  476. }
  477. }
  478. }
  479. }
  480. if (relativeError == 0) {
  481. break;
  482. }
  483. }
  484. Lpc17xxUsartDisable();
  485. if (best_error < ((baudrate * UART_ACCEPTED_BAUDRATE_ERROR) / 100)) {
  486. /* Set DLAB bit */
  487. CM3BBSET(USARTnBase, LPC_UART_TypeDef, LCR, UART_LCR_DLAB_EN_POS);
  488. USARTn->DLM = UART_LOAD_DLM(best_divisor);
  489. USARTn->DLL = UART_LOAD_DLL(best_divisor);
  490. /* Reset DLAB bit */
  491. CM3BBCLR(USARTnBase, LPC_UART_TypeDef, LCR, UART_LCR_DLAB_EN_POS);
  492. USARTn->FDR = (UART_FDR_MULVAL(bestm) | UART_FDR_DIVADDVAL(bestd)) & UART_FDR_BITMASK;
  493. } else {
  494. return -1;
  495. }
  496. Lpc17xxUsartEnable();
  497. return 0;
  498. }
  499. /*!
  500. * \brief Query the USART hardware for the number of data bits.
  501. *
  502. * This function is called by ioctl function of the upper level USART
  503. * driver through the USARTDCB jump table.
  504. *
  505. * \return The number of data bits set.
  506. */
  507. static uint8_t Lpc17xxUsartGetDataBits(void)
  508. {
  509. uint32_t lcr = USARTn->LCR;
  510. switch(lcr & UART_LCR_WLEN_BITMASK) {
  511. case UART_LCR_WLEN5: return 5;
  512. case UART_LCR_WLEN6: return 6;
  513. case UART_LCR_WLEN7: return 7;
  514. case UART_LCR_WLEN8: return 8;
  515. }
  516. return 0;
  517. }
  518. /*!
  519. * \brief Set the USART hardware to the number of data bits.
  520. *
  521. * This function is called by ioctl function of the upper level USART
  522. * driver through the USARTDCB jump table.
  523. *
  524. * \return 0 on success, -1 otherwise.
  525. */
  526. static int Lpc17xxUsartSetDataBits(uint8_t bits)
  527. {
  528. int rc = 0;
  529. uint32_t lcr;
  530. Lpc17xxUsartDisable();
  531. lcr = USARTn->LCR & ~UART_LCR_WLEN_BITMASK;
  532. switch (bits)
  533. {
  534. case 5:
  535. lcr |= UART_LCR_WLEN5;
  536. break;
  537. case 6:
  538. lcr |= UART_LCR_WLEN6;
  539. break;
  540. case 7:
  541. lcr |= UART_LCR_WLEN7;
  542. break;
  543. case 8:
  544. lcr |= UART_LCR_WLEN8;
  545. break;
  546. default:
  547. Lpc17xxUsartEnable();
  548. return -1;
  549. }
  550. USARTn->LCR = lcr & UART_LCR_BITMASK;
  551. Lpc17xxUsartEnable();
  552. return rc;
  553. }
  554. /*!
  555. * \brief Query the USART hardware for the parity mode.
  556. *
  557. * This routine is called by ioctl function of the upper level USART
  558. * driver through the USARTDCB jump table.
  559. *
  560. * \return Parity mode, either 0 (disabled), 1 (odd), 2 (even), 3 (mark) or 4 (space)
  561. */
  562. static uint8_t Lpc17xxUsartGetParity(void)
  563. {
  564. uint32_t lcr = USARTn->LCR;
  565. switch(lcr & UART_LCR_PARITY_BITMASK) {
  566. case UART_LCR_PARITY_EN | UART_LCR_PARITY_ODD: return 1;
  567. case UART_LCR_PARITY_EN | UART_LCR_PARITY_EVEN: return 2;
  568. case UART_LCR_PARITY_EN | UART_LCR_PARITY_F_1: return 3;
  569. case UART_LCR_PARITY_EN | UART_LCR_PARITY_F_0: return 4;
  570. default:
  571. return 0;
  572. }
  573. return 0;
  574. }
  575. /*!
  576. * \brief Set the USART hardware to the specified parity mode.
  577. *
  578. * This routine is called by ioctl function of the upper level USART
  579. * driver through the USARTDCB jump table.
  580. *
  581. * \param mode 0 (disabled), 1 (odd), 2 (even) 3 (mark) or 4(space)
  582. *
  583. * \return 0 on success, -1 otherwise.
  584. */
  585. static int Lpc17xxUsartSetParity(uint8_t mode)
  586. {
  587. uint32_t lcr;
  588. Lpc17xxUsartDisable();
  589. lcr = USARTn->LCR & ~UART_LCR_PARITY_BITMASK;
  590. switch (mode) {
  591. case 0:
  592. /* Parity disabled, do nothing */
  593. break;
  594. case 1:
  595. lcr |= UART_LCR_PARITY_EN | UART_LCR_PARITY_ODD;
  596. break;
  597. case 2:
  598. lcr |= UART_LCR_PARITY_EN | UART_LCR_PARITY_EVEN;
  599. break;
  600. case 3:
  601. lcr |= UART_LCR_PARITY_EN | UART_LCR_PARITY_F_1;
  602. break;
  603. case 4:
  604. lcr |= UART_LCR_PARITY_EN | UART_LCR_PARITY_F_0;
  605. break;
  606. default:
  607. Lpc17xxUsartEnable();
  608. return -1;
  609. }
  610. USARTn->LCR = lcr & UART_LCR_BITMASK;
  611. Lpc17xxUsartEnable();
  612. return 0;
  613. }
  614. /*!
  615. * \brief Query the USART hardware for the number of stop bits.
  616. *
  617. * This routine is called by ioctl function of the upper level USART
  618. * driver through the USARTDCB jump table.
  619. *
  620. * \return The number of stop bits set, either 1, 2 or 3 (1.5 bits).
  621. */
  622. static uint8_t Lpc17xxUsartGetStopBits(void)
  623. {
  624. uint32_t lcr = USARTn->LCR;
  625. if (lcr & UART_LCR_STOPBIT_SEL) {
  626. if ((lcr & UART_LCR_WLEN_BITMASK) == UART_LCR_WLEN5) {
  627. return 3;
  628. } else {
  629. return 2;
  630. }
  631. } else {
  632. return 1;
  633. }
  634. }
  635. /*!
  636. * \brief Set the USART hardware to the number of stop bits.
  637. *
  638. * This routine is called by ioctl function of the upper level USART
  639. * driver through the USARTDCB jump table.
  640. *
  641. * \param bits The number of stop bits set, either 1, 2 or 3 (1.5 bits).
  642. *
  643. * \return 0 on success, -1 otherwise.
  644. */
  645. static int Lpc17xxUsartSetStopBits(uint8_t bits)
  646. {
  647. Lpc17xxUsartDisable();
  648. switch (bits) {
  649. case 1:
  650. CM3BBCLR(USARTnBase, LPC_UART_TypeDef, LCR, UART_LCR_STOPBIT_SEL_POS);
  651. break;
  652. case 2:
  653. CM3BBSET(USARTnBase, LPC_UART_TypeDef, LCR, UART_LCR_STOPBIT_SEL_POS);
  654. break;
  655. case 3:
  656. if ((USARTn->LCR & UART_LCR_WLEN_BITMASK) == UART_LCR_WLEN5) {
  657. CM3BBSET(USARTnBase, LPC_UART_TypeDef, LCR, UART_LCR_STOPBIT_SEL_POS);
  658. } else {
  659. Lpc17xxUsartEnable();
  660. return -1;
  661. }
  662. break;
  663. default:
  664. Lpc17xxUsartEnable();
  665. return -1;
  666. }
  667. Lpc17xxUsartEnable();
  668. return 0;
  669. }
  670. /*!
  671. * \brief Query the USART hardware status.
  672. *
  673. * \return Status flags.
  674. */
  675. static uint32_t Lpc17xxUsartGetStatus(void)
  676. {
  677. uint32_t rc = 0;
  678. /*
  679. * Set receiver error flags.
  680. */
  681. if ((rx_errors & UART_LSR_FE) != 0) {
  682. rc |= UART_FRAMINGERROR;
  683. }
  684. if ((rx_errors & UART_LSR_OE) != 0) {
  685. rc |= UART_OVERRUNERROR;
  686. }
  687. if ((rx_errors & UART_LSR_PE) != 0) {
  688. rc |= UART_PARITYERROR;
  689. }
  690. #if defined(UART_XONXOFF_CONTROL)
  691. /*
  692. * Determine software handshake status. The flow control status may
  693. * change during interrupt, but this doesn't really hurt us.
  694. */
  695. if (flow_control) {
  696. if (flow_control & XOFF_SENT) {
  697. rc |= UART_RXDISABLED;
  698. }
  699. if (flow_control & XOFF_RCVD) {
  700. rc |= UART_TXDISABLED;
  701. }
  702. }
  703. #endif
  704. /*
  705. * Determine hardware handshake control status.
  706. */
  707. #if defined(US_MODE_HWHANDSHAKE)
  708. // TODO: reflect RTS state
  709. #endif
  710. /*
  711. * Determine hardware handshake sense status.
  712. */
  713. #if defined(US_MODE_HWHANDSHAKE)
  714. // TODO: reflect CTS state
  715. #endif
  716. /*
  717. * If transmitter and receiver haven't been detected disabled by any
  718. * of the checks above, then they are probably enabled.
  719. */
  720. if ((rc & UART_RXDISABLED) == 0) {
  721. rc |= UART_RXENABLED;
  722. }
  723. if ((rc & UART_TXDISABLED) == 0) {
  724. rc |= UART_TXENABLED;
  725. }
  726. return rc;
  727. }
  728. /*!
  729. * \brief Set the USART hardware status.
  730. *
  731. * \param flags Status flags.
  732. *
  733. * \return 0 on success, -1 otherwise.
  734. */
  735. static int Lpc17xxUsartSetStatus(uint32_t flags)
  736. {
  737. int rc = 0;
  738. /*
  739. * Process software handshake control.
  740. */
  741. #if defined(UART_XONXOFF_CONTROL)
  742. if (flow_control) {
  743. /* Access to the flow control status must be atomic. */
  744. NutUartIrqDisable(&SigUSART);
  745. /*
  746. * Enabling or disabling the receiver means to behave like
  747. * having sent a XON or XOFF character resp.
  748. */
  749. if (flags & UART_RXENABLED) {
  750. flow_control &= ~XOFF_SENT;
  751. } else if (flags & UART_RXDISABLED) {
  752. flow_control |= XOFF_SENT;
  753. }
  754. /*
  755. * Enabling or disabling the transmitter means to behave like
  756. * having received a XON or XOFF character resp.
  757. */
  758. if (flags & UART_TXENABLED) {
  759. flow_control &= ~XOFF_RCVD;
  760. } else if (flags & UART_TXDISABLED) {
  761. flow_control |= XOFF_RCVD;
  762. }
  763. NutUartIrqEnable(&SigUSART);
  764. }
  765. #endif
  766. /*
  767. * Clear USART receive errors.
  768. */
  769. if (flags & UART_ERRORS) {
  770. /* Clear errors by reading the line status register */
  771. (volatile uint32_t)USARTn->LSR;
  772. }
  773. /*
  774. * Verify the result.
  775. */
  776. if ((Lpc17xxUsartGetStatus() & ~UART_ERRORS) != flags) rc = -1;
  777. return rc;
  778. }
  779. /*!
  780. * \brief Query the USART hardware for synchronous mode.
  781. *
  782. * This function is called by ioctl function of the upper level USART
  783. * driver through the USARTDCB jump table.
  784. *
  785. * Not implemented for the LPC17xx USART. Always returns 0.
  786. *
  787. * \return Or-ed combination of \ref UART_SYNC, \ref UART_MASTER,
  788. * \ref UART_NCLOCK and \ref UART_HIGHSPEED.
  789. */
  790. uint8_t Lpc17xxUsartGetClockMode(void)
  791. {
  792. return 0;
  793. }
  794. /*!
  795. * \brief Set asynchronous or synchronous mode.
  796. *
  797. * This function is called by ioctl function of the upper level USART
  798. * driver through the USARTDCB jump table.
  799. *
  800. * Not implemented for the LPC17xx USART. Always returns -1.
  801. *
  802. * \param mode Must be an or-ed combination of USART_SYNC, USART_MASTER,
  803. * USART_NCLOCK and USART_HIGHSPEED.
  804. *
  805. * \return 0 on success, -1 otherwise.
  806. */
  807. static int Lpc17xxUsartSetClockMode(uint8_t mode)
  808. {
  809. return -1;
  810. }
  811. /*!
  812. * \brief Query flow control mode.
  813. *
  814. * This routine is called by ioctl function of the upper level USART
  815. * driver through the USARTDCB jump table.
  816. *
  817. * \return See UsartIOCtl().
  818. */
  819. static uint32_t Lpc17xxUsartGetFlowControl(void)
  820. {
  821. uint32_t rc = 0;
  822. // TODO: Implement more flow control
  823. #if defined(UART_XONXOFF_CONTROL)
  824. if (flow_control) {
  825. rc |= USART_MF_XONXOFF;
  826. } else {
  827. rc &= ~USART_MF_XONXOFF;
  828. }
  829. #endif
  830. #ifdef UART_DMA_RXCHANNEL
  831. if (block_control & BC_RD_EN)
  832. rc |= USART_MF_BLOCKREAD;
  833. else
  834. rc &= ~USART_MF_BLOCKREAD;
  835. #endif
  836. #ifdef UART_DMA_TXCHANNEL
  837. if (block_control & BC_WR_EN)
  838. rc |= USART_MF_BLOCKWRITE;
  839. else
  840. rc &= ~USART_MF_BLOCKWRITE;
  841. #endif
  842. return rc;
  843. }
  844. /*!
  845. * \brief Set flow control mode.
  846. *
  847. * This function is called by ioctl function of the upper level USART
  848. * driver through the USARTDCB jump table.
  849. *
  850. * \param flags See UsartIOCtl().
  851. *
  852. * \return 0 on success, -1 otherwise.
  853. */
  854. static int Lpc17xxUsartSetFlowControl(uint32_t flags)
  855. {
  856. // TODO: Implement more flow control
  857. #if defined(UART_XONXOFF_CONTROL)
  858. NutUartIrqDisable(&SigUSART);
  859. /*
  860. * Set software handshake mode.
  861. */
  862. if (flags & USART_MF_XONXOFF) {
  863. if(flow_control == 0) {
  864. flow_control = 1 | XOFF_SENT; /* force XON to be sent on next read */
  865. }
  866. } else {
  867. flow_control = 0;
  868. }
  869. NutUartIrqEnable(&SigUSART);
  870. #endif
  871. #ifdef UART_DMA_RXCHANNEL
  872. /* Setup block mode */
  873. if( flags & USART_MF_BLOCKREAD) {
  874. block_control |= BC_RD_EN;
  875. }
  876. else {
  877. block_control &= ~BC_RD_EN;
  878. }
  879. #endif
  880. #ifdef UART_DMA_TXCHANNEL
  881. if( flags & USART_MF_BLOCKWRITE) {
  882. block_control |= BC_WR_EN;
  883. }
  884. else {
  885. block_control &= ~BC_WR_EN;
  886. }
  887. #endif
  888. return 0;
  889. }
  890. /*!
  891. * \brief Start the USART transmitter hardware.
  892. *
  893. * The upper level USART driver will call this function through the
  894. * USARTDCB jump table each time it added one or more bytes to the
  895. * transmit buffer.
  896. */
  897. static void Lpc17xxUsartTxStart(void)
  898. {
  899. register uint8_t *cp;
  900. /* Enable transmit interrupts. */
  901. CM3BBSET(USARTnBase, LPC_UART_TypeDef, IER, UART_IER_THREINT_EN_POS);
  902. USARTn->TER = UART_TER_TXEN;
  903. /*
  904. * Check if we have any bytes to transmit. Send out first byte if there is space in the FIFO
  905. */
  906. NutEnterCritical();
  907. cp = DcbUSART.dcb_tx_rbf.rbf_tail;
  908. if ((DcbUSART.dcb_tx_rbf.rbf_cnt) && (USARTn->LSR & UART_LSR_THRE)) {
  909. /*
  910. * If CTS has been disabled, we disable the transmit interrupts,
  911. * enable CTS interrupts and return without sending anything.
  912. */
  913. // TODO: CTS handling in here
  914. /* Start transmission of the next character. */
  915. USARTn->THR = *cp;
  916. /* Decrement the number of available bytes in the buffer. */
  917. DcbUSART.dcb_tx_rbf.rbf_cnt--;
  918. /* Wrap around the buffer pointer if we reached its end. */
  919. if (++cp == DcbUSART.dcb_tx_rbf.rbf_last) {
  920. cp = DcbUSART.dcb_tx_rbf.rbf_start;
  921. }
  922. DcbUSART.dcb_tx_rbf.rbf_tail = cp;
  923. /* Send an event if we reached the low watermark. */
  924. if (DcbUSART.dcb_tx_rbf.rbf_cnt == DcbUSART.dcb_tx_rbf.rbf_lwm) {
  925. NutExitCritical(); /* Exit critical section _before_ posting to the event queues */
  926. NutEventPostAsync(&DcbUSART.dcb_tx_rbf.rbf_que);
  927. NutSelectWakeup(DcbUSART.dcb_tx_rbf.wq_list, WQ_FLAG_WRITE);
  928. } else {
  929. NutExitCritical();
  930. }
  931. }
  932. }
  933. /*!
  934. * \brief Start the USART receiver hardware.
  935. *
  936. * The upper level USART driver will call this function through the
  937. * USARTDCB jump table each time it removed enough bytes from the
  938. * receive buffer. Enough means, that the number of bytes left in
  939. * the buffer is below the low watermark.
  940. */
  941. static void Lpc17xxUsartRxStart(void)
  942. {
  943. #if defined(UART_XONXOFF_CONTROL)
  944. /*
  945. * Do any required software flow control.
  946. */
  947. if (flow_control && (flow_control & XOFF_SENT) != 0) {
  948. NutUartIrqDisable(&SigUSART);
  949. /* Check if the transmit holding register is empty */
  950. if (USARTn->LSR & UART_LSR_THRE) {
  951. USARTn->THR = ASCII_XON;
  952. flow_control &= ~XON_PENDING;
  953. } else {
  954. flow_control |= XON_PENDING;
  955. }
  956. flow_control &= ~(XOFF_SENT | XOFF_PENDING);
  957. NutUartIrqEnable(&SigUSART);
  958. }
  959. #endif
  960. /* Enable receive interrupts. */
  961. CM3BBSET(USARTnBase, LPC_UART_TypeDef, IER, UART_IER_RBRINT_EN_POS);
  962. }
  963. /*
  964. * \brief Initialize the USART hardware driver.
  965. *
  966. * This function is called during device registration by the upper level
  967. * USART driver through the USARTDCB jump table.
  968. *
  969. * \return 0 on success, -1 otherwise.
  970. */
  971. static int Lpc17xxUsartInit(void)
  972. {
  973. volatile uint32_t tmp;
  974. /*
  975. * Register receive and transmit interrupts.
  976. */
  977. if (NutRegisterIrqHandler(&SigUSART, Lpc17xxUsartInterrupt, &DcbUSART)) {
  978. return -1;
  979. }
  980. /* Enable UART clock and power */
  981. #if defined(MCU_LPC176x)
  982. if((LPC_UART_TypeDef*)USARTn == LPC_UART0) {
  983. SysCtlPeripheralClkEnable(CLKPWR_PCONP_PCUART0);
  984. } else
  985. if((LPC_UART1_TypeDef*)USARTn == LPC_UART1) {
  986. SysCtlPeripheralClkEnable(CLKPWR_PCONP_PCUART1);
  987. } else
  988. if((LPC_UART_TypeDef*)USARTn == LPC_UART2) {
  989. SysCtlPeripheralClkEnable(CLKPWR_PCONP_PCUART2);
  990. } else
  991. if((LPC_UART_TypeDef*)USARTn == LPC_UART3) {
  992. SysCtlPeripheralClkEnable(CLKPWR_PCONP_PCUART3);
  993. }
  994. #elif defined(MCU_LPC177x_8x) || defined(MCU_LPC407x_8x)
  995. if((LPC_UART_TypeDef*)USARTn == LPC_UART0) {
  996. SysCtlPeripheralClkEnable(CLKPWR_PCONP_PCUART0);
  997. SysCtlPeripheralResetEnable(CLKPWR_RSTCON0_UART0);
  998. SysCtlPeripheralResetDisable(CLKPWR_RSTCON0_UART0);
  999. } else
  1000. if((LPC_UART1_TypeDef*)USARTn == LPC_UART1) {
  1001. SysCtlPeripheralClkEnable(CLKPWR_PCONP_PCUART1);
  1002. SysCtlPeripheralResetEnable(CLKPWR_RSTCON0_UART1);
  1003. SysCtlPeripheralResetDisable(CLKPWR_RSTCON0_UART1);
  1004. } else
  1005. if((LPC_UART_TypeDef*)USARTn == LPC_UART2) {
  1006. SysCtlPeripheralClkEnable(CLKPWR_PCONP_PCUART2);
  1007. SysCtlPeripheralResetEnable(CLKPWR_RSTCON0_UART2);
  1008. SysCtlPeripheralResetDisable(CLKPWR_RSTCON0_UART2);
  1009. } else
  1010. if((LPC_UART_TypeDef*)USARTn == LPC_UART3) {
  1011. SysCtlPeripheralClkEnable(CLKPWR_PCONP_PCUART3);
  1012. SysCtlPeripheralResetEnable(CLKPWR_RSTCON0_UART3);
  1013. SysCtlPeripheralResetDisable(CLKPWR_RSTCON0_UART3);
  1014. }
  1015. #endif
  1016. /* Disable IRQs */
  1017. USARTn->IER = 0;
  1018. /* Clear FIFOs */
  1019. USARTn->FCR = UART_FCR_FIFO_EN | UART_FCR_RX_RS | UART_FCR_TX_RS | UART_FCR_TRG_LEV2;
  1020. /* Dummy reading */
  1021. while (USARTn->LSR & UART_LSR_RDR) {
  1022. tmp = USARTn->RBR;
  1023. }
  1024. /* Enable transmitter */
  1025. USARTn->TER = UART_TER_TXEN;
  1026. /* Wait for current transmit complete */
  1027. while (!(USARTn->LSR & UART_LSR_THRE));
  1028. /* Disable transmitter */
  1029. USARTn->TER = 0;
  1030. /* Set LCR to default state */
  1031. USARTn->LCR = 0;
  1032. /* Set ACR to default state */
  1033. USARTn->ACR = 0;
  1034. #if defined(MCU_LPC176x)
  1035. if((LPC_UART1_TypeDef*)USARTn == LPC_UART1) {
  1036. /* Set RS485 control to default state */
  1037. ((LPC_UART1_TypeDef*)USARTn)->RS485CTRL = 0;
  1038. /* Set RS485 delay timer to default state */
  1039. ((LPC_UART1_TypeDef*)USARTn)->RS485DLY = 0;
  1040. /* Set RS485 addr match to default state */
  1041. ((LPC_UART1_TypeDef*)USARTn)->ADRMATCH = 0;
  1042. }
  1043. #elif defined(MCU_LPC177x_8x) || defined(MCU_LPC407x_8x)
  1044. /* Set RS485 control to default state */
  1045. USARTn->RS485CTRL = 0;
  1046. /* Set RS485 delay timer to default state */
  1047. USARTn->RS485DLY = 0;
  1048. /* Set RS485 addr match to default state */
  1049. USARTn->ADRMATCH = 0;
  1050. #endif
  1051. /* Dummy reading to clear bits */
  1052. tmp = USARTn->LSR;
  1053. if(((LPC_UART1_TypeDef *)USARTn) == LPC_UART1) {
  1054. /* Set Modem Control to default state */
  1055. ((LPC_UART1_TypeDef *)USARTn)->MCR = 0;
  1056. /* Dummy Reading to Clear Status */
  1057. tmp = ((LPC_UART1_TypeDef *)USARTn)->MSR;
  1058. }
  1059. #if defined(MCU_LPC177x_8x) || defined(MCU_LPC407x_8x)
  1060. if(((LPC_UART4_TypeDef *)USARTn) == LPC_UART4) {
  1061. /* Set IrDA to default state for all UART other than UART1 */
  1062. ((LPC_UART4_TypeDef *)USARTn)->ICR = 0;
  1063. }
  1064. #endif
  1065. /* Configure USART Tx as alternate function push-pull */
  1066. GpioPinConfigSet( TX_GPIO_PORT, TX_GPIO_PIN, TX_GPIO_PIN_CFG);
  1067. /* Configure USART Rx as input floating */
  1068. GpioPinConfigSet( RX_GPIO_PORT, RX_GPIO_PIN, RX_GPIO_PIN_CFG);
  1069. #if defined(RTS_GPIO_PORT) && defined(RTS_GPIO_PIN)
  1070. /* Configure USART RTS as alternate function push-pull */
  1071. GpioPinConfigSet( RTS_GPIO_PORT, RTS_GPIO_PIN, RTS_GPIO_PIN_CFG);
  1072. #endif
  1073. #if defined(CTS_GPIO_PORT) && defined(CTS_GPIO_PIN)
  1074. /* Configure USART CTS as input floating */
  1075. GpioPinConfigSet( CTS_GPIO_PORT, CTS_GPIO_PIN, CTS_GPIO_PIN_CFG);
  1076. #endif
  1077. /* Configure UART communication parameters */
  1078. Lpc17xxUsartSetSpeed(USART_INIT_BAUTRATE);
  1079. Lpc17xxUsartSetDataBits(8);
  1080. Lpc17xxUsartSetStopBits(1);
  1081. Lpc17xxUsartSetParity(0);
  1082. /* Enable additional features */
  1083. #ifdef USART_HWFLOWCTRL
  1084. // TODO: Implement GPIO based hardware handshake for UARTS without full modem handshake */
  1085. if ((LPC_UART1_TypeDef *) USARTn == LPC_UART1) {
  1086. /* Enable hardware handshake options */
  1087. tmp = 0;
  1088. #if defined(RTS_GPIO_PORT) && defined(RTS_GPIO_PIN)
  1089. tmp |= UART1_MCR_AUTO_RTS_EN;
  1090. #endif
  1091. #if defined(CTS_GPIO_PORT) && defined(CTS_GPIO_PIN)
  1092. tmp |= UART1_MCR_AUTO_CTS_EN;
  1093. #endif
  1094. ((LPC_UART1_TypeDef *)USARTn)->MCR = tmp;
  1095. }
  1096. #endif
  1097. #ifdef USART_MODE_IRDA
  1098. // TODO: Further IRDA feature configuration
  1099. if(((LPC_UART4_TypeDef *)USARTn) == LPC_UART4) {
  1100. /* Set IrDA to default state for all UART other than UART1 */
  1101. USARTn->ICR = UART_ICR_IRDAEN;
  1102. }
  1103. #endif
  1104. NutIrqEnable(&SigUSART);
  1105. return 0;
  1106. }
  1107. /*
  1108. * \brief Deinitialize the USART hardware driver.
  1109. *
  1110. * This function is called during device deregistration by the upper
  1111. * level USART driver through the USARTDCB jump table.
  1112. *
  1113. * \return 0 on success, -1 otherwise.
  1114. */
  1115. static int Lpc17xxUsartDeinit(void)
  1116. {
  1117. /* Disable IRQs */
  1118. USARTn->IER = 0;
  1119. /* Disable interrupts */
  1120. NutIrqDisable(&SigUSART);
  1121. /* Deregister receive and transmit interrupts. */
  1122. NutRegisterIrqHandler(&SigUSART, 0, 0);
  1123. /* Disable UART clock and power */
  1124. #if defined(MCU_LPC176x)
  1125. if((LPC_UART_TypeDef*)USARTn == LPC_UART0) {
  1126. SysCtlPeripheralClkDisable(CLKPWR_PCONP_PCUART0);
  1127. } else
  1128. if((LPC_UART1_TypeDef*)USARTn == LPC_UART1) {
  1129. SysCtlPeripheralClkDisable(CLKPWR_PCONP_PCUART1);
  1130. } else
  1131. if((LPC_UART_TypeDef*)USARTn == LPC_UART2) {
  1132. SysCtlPeripheralClkDisable(CLKPWR_PCONP_PCUART2);
  1133. } else
  1134. if((LPC_UART_TypeDef*)USARTn == LPC_UART3) {
  1135. SysCtlPeripheralClkDisable(CLKPWR_PCONP_PCUART3);
  1136. }
  1137. #elif defined(MCU_LPC177x_8x) || defined(MCU_LPC407x_8x)
  1138. if((LPC_UART_TypeDef*)USARTn == LPC_UART0) {
  1139. SysCtlPeripheralResetEnable(CLKPWR_RSTCON0_UART0);
  1140. SysCtlPeripheralResetDisable(CLKPWR_RSTCON0_UART0);
  1141. SysCtlPeripheralClkDisable(CLKPWR_PCONP_PCUART0);
  1142. } else
  1143. if((LPC_UART1_TypeDef *)USARTn == LPC_UART1) {
  1144. SysCtlPeripheralResetEnable(CLKPWR_RSTCON0_UART1);
  1145. SysCtlPeripheralResetDisable(CLKPWR_RSTCON0_UART1);
  1146. SysCtlPeripheralClkDisable(CLKPWR_PCONP_PCUART1);
  1147. } else
  1148. if((LPC_UART_TypeDef*)USARTn == LPC_UART2) {
  1149. SysCtlPeripheralResetEnable(CLKPWR_RSTCON0_UART2);
  1150. SysCtlPeripheralResetDisable(CLKPWR_RSTCON0_UART2);
  1151. SysCtlPeripheralClkDisable(CLKPWR_PCONP_PCUART2);
  1152. } else
  1153. if((LPC_UART_TypeDef*)USARTn == LPC_UART3) {
  1154. SysCtlPeripheralResetEnable(CLKPWR_RSTCON0_UART3);
  1155. SysCtlPeripheralResetDisable(CLKPWR_RSTCON0_UART3);
  1156. SysCtlPeripheralClkDisable(CLKPWR_PCONP_PCUART3);
  1157. }
  1158. #endif
  1159. return 0;
  1160. }
  1161. /*@}*/