LPC_Uart.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /*************************************************************************
  2. *
  3. * Used with ICCARM and AARM.
  4. *
  5. * (c) Copyright IAR Systems 2003
  6. *
  7. * File name : LPC_Uart.c
  8. * Description : Define API for UART
  9. *
  10. * History :
  11. * 1. Data: July 13, 2004
  12. * Author: Shawn Zhang
  13. * Description: Create the basic function
  14. *
  15. * 2. Data: August 09, 2004
  16. * Author: Shawn Zhang
  17. * Description: Integrate two method :- by polling and by interrupt, user
  18. * could select it.
  19. *
  20. * 3. Data: August 17, 2004
  21. * Author: Shawn Zhang
  22. * Description: 1) Repair the bug about Tx ring buffer.
  23. * 2) Repair the bug about ReadTxBuf function and ISR.
  24. *
  25. * 4. Data : Oct 9, 2004
  26. * Author : Stanimir Bonev
  27. * Description : Modify some function and interface
  28. *
  29. * $Revision: 1.1 $
  30. **************************************************************************/
  31. #include "LPC_Uart.h"
  32. // Define globe variable
  33. LPC_Uart_Config_t Uart0Config = {BD9600, WordLength8, false, false, ParitySelOdd,
  34. false, true, FIFORXLEV2, IER_RBR | IER_RLS,
  35. INTERRUPT_MODE,};
  36. LPC_Uart_Config_t Uart1Config = {BD9600, WordLength8, false, false, ParitySelOdd,
  37. false, true, FIFORXLEV2, IER_RBR | IER_RLS,
  38. INTERRUPT_MODE,};
  39. /*************************************************************************
  40. * Function Name: UART_InitUartBuf
  41. * Parameters: LPC_Uart_Buffer_t *pUartBuf
  42. * Return: void
  43. *
  44. * Description: Initialize Rx & Tx buffer, which is used when adopting interrupt method
  45. *
  46. *************************************************************************/
  47. void UART_InitUartBuf (LPC_Uart_Buffer_t *pUartBuf)
  48. {
  49. pUartBuf->RxHeadPoint=0;
  50. pUartBuf->RxTailPoint=0;
  51. pUartBuf->TxHeadPoint=0;
  52. pUartBuf->TxTailPoint=0;
  53. pUartBuf->RxCount=0;
  54. pUartBuf->TxCount=0;
  55. pUartBuf->RxFlag=0;
  56. }
  57. /*************************************************************************
  58. * Function Name: UART_Init
  59. * Parameters: LPC_UartChanel_t DevNum
  60. *
  61. * Return: int
  62. * 0: sucess
  63. * 1: fail
  64. * Description: Initialize Uart, configure baut rate, frame format and FIFO
  65. *
  66. *************************************************************************/
  67. int UART_Init (LPC_UartChanel_t DevNum)
  68. {
  69. unsigned long Divisor, Frame, FIFO;
  70. LPC_Uart_Config_t *pConfig;
  71. if ( DevNum == UART0 )
  72. pConfig = &Uart0Config;
  73. else
  74. pConfig = &Uart1Config;
  75. if ((pConfig->BaudRate == 0) || (pConfig->BaudRate > BD115200))
  76. return 0;
  77. // baut rate
  78. Divisor = (SYS_GetFpclk() >>4) / pConfig->BaudRate; // Divisor = pclk / (16*bautrate)
  79. // frame format
  80. Frame = pConfig->WordLenth;
  81. if ( pConfig->TwoStopBitsSelect )
  82. Frame |= ( 1<<LCR_STOPBITSEL_BIT );
  83. if ( pConfig->ParityEnable )
  84. {
  85. Frame |= ( 1<<LCR_PARITYENBALE_BIT );
  86. Frame |= ( pConfig->ParitySelect<<LCR_PARITYSEL_BIT );
  87. }
  88. if ( pConfig->BreakEnable )
  89. Frame |= ( 1<<LCR_BREAKCONTROL_BIT );
  90. // FIFO
  91. if ( pConfig->FIFOEnable )
  92. FIFO = ((pConfig->FIFORxTriggerLevel & 0x3)<<6) | 0x1;
  93. // Method Mode
  94. if ( pConfig->MethodMode == INTERRUPT_MODE )
  95. UART_InitUartBuf (&pConfig->UartBuffer);
  96. if ( DevNum == UART0 )
  97. {
  98. // Set baut rate
  99. U0LCR_bit.DLAB = true; // DLAB = 1
  100. U0DLM = Divisor >> 8;
  101. U0DLL = Divisor;
  102. // Set frame format
  103. U0LCR = Frame; // DLAB = 0
  104. // Set FIFO
  105. U0FCR = FIFO;
  106. // Set Interrupt Enable Register
  107. U0IER = pConfig->InterruptEnable & 0x5;
  108. // Enable TxD0 and RxD0, bit 0~3=0101
  109. // PINSEL0 |= 0x05;
  110. PINSEL0_bit.P0_0 = 0x1;
  111. PINSEL0_bit.P0_1 = 0x1;
  112. }
  113. else if ( DevNum == UART1 )
  114. {
  115. // Set baut rate
  116. U1LCR_bit.DLAB = true; // DLAB = 1
  117. U1DLM = Divisor>>8;
  118. U1DLL = Divisor & 0xff;
  119. // Set frame format
  120. U1LCR = Frame; // DLAB =0
  121. /* Set FIFO */
  122. U1FCR = FIFO;
  123. // Set Interrupt Enable Register
  124. U1IER = pConfig->InterruptEnable & 0x5;
  125. // Enable TxD0 and RxD0, bit 16~19=0101
  126. // PINSEL0 |= 0x50000;
  127. PINSEL0_bit.P0_8 = 0x1;
  128. PINSEL0_bit.P0_9 = 0x1;
  129. }
  130. else
  131. return 1;
  132. return 0;
  133. }
  134. /*************************************************************************
  135. * Function Name: UART_PutCharByPolling
  136. * Parameters: LPC_UartChanel_t DevNum
  137. * char ch
  138. * Return: void
  139. *
  140. *
  141. * Description: Send character by polling LSR register
  142. *
  143. *************************************************************************/
  144. void UART_PutCharByPolling (LPC_UartChanel_t DevNum, char ch)
  145. {
  146. if ( DevNum == UART0 )
  147. {
  148. while(!U0LSR_bit.THRE);
  149. U0THR = ch;
  150. }
  151. else
  152. {
  153. while(!U1LSR_bit.THRE);
  154. U1THR = ch;
  155. }
  156. }
  157. /*************************************************************************
  158. * Function Name: UART_PutStringByPolling
  159. * Parameters: LPC_UartChanel_t DevNum
  160. * char *Buf
  161. * Return: int : send character count
  162. *
  163. *
  164. * Description: Send a string by using polling method
  165. *
  166. *************************************************************************/
  167. int UART_PutStringByPolling(LPC_UartChanel_t DevNum, char *Buf)
  168. {
  169. char *pBuf = Buf ;
  170. int SendCount = 0;
  171. while (*pBuf)
  172. {
  173. UART_PutCharByPolling(DevNum, *pBuf++);
  174. ++SendCount;
  175. }
  176. return (SendCount);
  177. }
  178. /*************************************************************************
  179. * Function Name: UART_GetCharByPolling
  180. * Parameters: LPC_UartChanel_t DevNum
  181. * Return: char
  182. *
  183. * Description: Receive a character from Uart by polling LSR register
  184. *
  185. *************************************************************************/
  186. char UART_GetCharByPolling (LPC_UartChanel_t DevNum)
  187. {
  188. if ( DevNum == UART0 )
  189. {
  190. while (!U0LSR_bit.DR);
  191. return (U0RBR);
  192. }
  193. while (!U1LSR_bit.DR);
  194. return (U1RBR);
  195. }
  196. /*************************************************************************
  197. * Function Name: UART_PutStringByInterrupt
  198. * Parameters: LPC_UartChanel_t DevNum
  199. * char *Buf
  200. * Return: int : send character count
  201. *
  202. * Description: Send a string into Uart Buffer.
  203. * Then Uart will send buffer data in its IRQ subroutine.
  204. *
  205. *************************************************************************/
  206. int UART_PutStringByInterrupt (LPC_UartChanel_t DevNum, char *Buf)
  207. {
  208. char *pBuf = Buf, ch;
  209. LPC_Uart_Buffer_t *pUartBuf;
  210. int SendCount = 0;
  211. unsigned long IntFlagsHold;
  212. if ( DevNum == UART0 )
  213. pUartBuf = &Uart0Config.UartBuffer;
  214. else
  215. pUartBuf = &Uart1Config.UartBuffer;
  216. while (*pBuf)
  217. {
  218. // if FIFO is full pending here, wait for send characters
  219. if (pUartBuf->TxCount >= TXBUFSIZE)
  220. {
  221. break;
  222. }
  223. ch = *pBuf & 0xff;
  224. pUartBuf->TxBuf[pUartBuf->TxTailPoint] = ch;
  225. pUartBuf->TxTailPoint = (pUartBuf->TxTailPoint+1)%TXBUFSIZE;
  226. IntFlagsHold = disable_IRQ();
  227. pUartBuf->TxCount++;
  228. restore_IRQ(IntFlagsHold);
  229. SendCount++;
  230. pBuf++;
  231. }
  232. if (DevNum == UART0)
  233. U0IER |= IER_THRE;
  234. else
  235. U1IER |= IER_THRE;
  236. return SendCount;
  237. }
  238. /*************************************************************************
  239. * Function Name: UART_GetCharByInterrupt
  240. * Parameters: LPC_UartChanel_t DevNum, char *ch
  241. * Return: 0 - Rx FIFO is empty
  242. * 1 - valid char
  243. * Description: Get character from Uart Port by making use of interrupt. At same time,
  244. * the received data will be stored into its buffer.
  245. *
  246. *************************************************************************/
  247. char UART_GetCharByInterrupt (LPC_UartChanel_t DevNum, char* Buf)
  248. {
  249. LPC_Uart_Buffer_t *pUartBuf;
  250. unsigned long IntFlagsHold;
  251. if (DevNum == UART0)
  252. {
  253. pUartBuf = &Uart0Config.UartBuffer;
  254. }
  255. else
  256. {
  257. pUartBuf = &Uart1Config.UartBuffer;
  258. }
  259. if (pUartBuf->RxCount == 0)
  260. return 0;
  261. *Buf = pUartBuf->RxBuf[pUartBuf->RxHeadPoint];
  262. pUartBuf->RxHeadPoint = (pUartBuf->RxHeadPoint+1)%RXBUFSIZE;
  263. IntFlagsHold = disable_IRQ();
  264. pUartBuf->RxCount--;
  265. restore_IRQ(IntFlagsHold);
  266. return 1;
  267. }
  268. /*************************************************************************
  269. * Function Name: UART_PutString
  270. * Parameters: LPC_UartChanel_t DevNum
  271. * char *Buf
  272. * Return: int : send character count
  273. *
  274. *
  275. * Description: Send a string
  276. *
  277. *************************************************************************/
  278. int UART_PutString(LPC_UartChanel_t DevNum, char *Buf)
  279. {
  280. LPC_Uart_MethodMode_t MethodMode;
  281. if ( DevNum == UART0 )
  282. MethodMode = Uart0Config.MethodMode;
  283. else
  284. MethodMode = Uart1Config.MethodMode;
  285. if (MethodMode)
  286. // interrupt method
  287. return(UART_PutStringByInterrupt(DevNum, Buf));
  288. // Polling method
  289. return(UART_PutStringByPolling(DevNum, Buf));
  290. }
  291. /*************************************************************************
  292. * Function Name: UART_GetChar
  293. * Parameters: LPC_UartChanel_t DevNum
  294. *
  295. * Return: char
  296. *
  297. * Description: Receive a character from Uart.
  298. *
  299. *************************************************************************/
  300. char UART_GetChar(LPC_UartChanel_t DevNum)
  301. {
  302. LPC_Uart_MethodMode_t MethodMode;
  303. char ch;
  304. if ( DevNum == UART0 )
  305. MethodMode = Uart0Config.MethodMode;
  306. else
  307. MethodMode = Uart1Config.MethodMode;
  308. if (MethodMode)
  309. {
  310. // interrupt method
  311. while(!UART_GetCharByInterrupt(DevNum,&ch));
  312. return(ch);
  313. }
  314. // Polling method
  315. return(UART_GetCharByPolling(DevNum));
  316. }
  317. /*************************************************************************
  318. * Function Name: UART_ReadTxBuf
  319. * Parameters: LPC_Uart_Buffer_t *pUartBuf
  320. * char *ch
  321. * Return: int : 1 one character or more
  322. * 0 no character in buffer, means current Txcount = 0
  323. *
  324. * Description: Read a character from to Uart Buffer, which is only used by IRQ subroutine.
  325. *
  326. *************************************************************************/
  327. #pragma inline
  328. static int UART_ReadTxBuf (LPC_Uart_Buffer_t *pUartBuf, char *ch)
  329. {
  330. if (pUartBuf->TxCount == 0)
  331. return 0;
  332. *ch = pUartBuf->TxBuf[pUartBuf->TxHeadPoint];
  333. pUartBuf->TxHeadPoint = (pUartBuf->TxHeadPoint+1)%TXBUFSIZE;
  334. pUartBuf->TxCount--;
  335. return 1;
  336. }
  337. /*************************************************************************
  338. * Function Name: UART0_ISR
  339. * Parameters: void
  340. * Return: void
  341. *
  342. * Description: Uart0 interrupt subroutine
  343. *
  344. *************************************************************************/
  345. void UART0_ISR (void)
  346. {
  347. int i;
  348. char temp;
  349. LPC_Uart_Buffer_t *pUartBuf = &Uart0Config.UartBuffer;
  350. switch((U0IIR>>1)&0x7)
  351. {
  352. case IIR_THRE: // continue sending data
  353. // Check for Transmitter FIFO enable
  354. if (Uart0Config.FIFOEnable)
  355. // when FIFO is enable load FIFODEEP bytes
  356. i = FIFODEEP;
  357. else
  358. // when FIFO is disable load 1 byte
  359. i = 1;
  360. do
  361. {
  362. // Check for software FIFO state and load data into transmitter hold register
  363. // disable interups imediatly aftre write when FIFO is empty
  364. if(!UART_ReadTxBuf(pUartBuf, (char*)&U0THR) || (pUartBuf->TxCount == 0))
  365. {
  366. // Disable interrup when FIFO is empty
  367. U0IER_bit.THREIE = false;
  368. break;
  369. }
  370. }
  371. while(--i);
  372. break;
  373. case IIR_RSL: // error manage
  374. temp = U0LSR;
  375. pUartBuf->RxFlag |= temp & 0x9E;
  376. break;
  377. case IIR_RDA: // receive data
  378. case IIR_CTI: // time out
  379. pUartBuf->RxBuf[pUartBuf->RxTailPoint] = U0RBR;
  380. pUartBuf->RxTailPoint = (pUartBuf->RxTailPoint+1)%RXBUFSIZE;
  381. // overflow
  382. if (++pUartBuf->RxCount > RXBUFSIZE)
  383. {
  384. pUartBuf->RxHeadPoint = pUartBuf->RxTailPoint;
  385. pUartBuf->RxFlag |= RC_FIFO_OVERRUN_ERR;
  386. }
  387. break;
  388. default:
  389. break;
  390. }
  391. VICVectAddr = 0; // Clear interrupt in VIC.
  392. }
  393. /*************************************************************************
  394. * Function Name: UART1_ISR
  395. * Parameters: void
  396. * Return: void
  397. *
  398. * Description: Uart1 interrupt subroutine
  399. *
  400. *************************************************************************/
  401. void UART1_ISR (void)
  402. {
  403. int i;
  404. char temp;
  405. LPC_Uart_Buffer_t *pUartBuf = &Uart1Config.UartBuffer;
  406. switch((U1IIR>>1)&0x7)
  407. {
  408. case IIR_THRE: // continue sending data
  409. // Check for Transmitter FIFO enable
  410. if (Uart1Config.FIFOEnable)
  411. // when FIFO is enable load FIFODEEP bytes
  412. i = FIFODEEP;
  413. else
  414. // when FIFO is disable load 1 byte
  415. i = 1;
  416. do
  417. {
  418. // Check for software FIFO state and load data into transmitter hold register
  419. // disable interups imediatly aftre write when FIFO is empty
  420. if(!UART_ReadTxBuf(pUartBuf, (char*)&U1THR) || (pUartBuf->TxCount == 0))
  421. {
  422. // Disable interrup when FIFO is empty
  423. U1IER_bit.THREIE = false;
  424. break;
  425. }
  426. }
  427. while(--i);
  428. break;
  429. case IIR_RSL: // error manage
  430. temp = U1LSR;
  431. pUartBuf->RxFlag |= temp & 0x9E;
  432. break;
  433. case IIR_RDA: // receive data
  434. case IIR_CTI: // time out
  435. pUartBuf->RxBuf[pUartBuf->RxTailPoint] = U1RBR;
  436. if (++pUartBuf->RxCount > RXBUFSIZE)
  437. {
  438. pUartBuf->RxFlag |= RC_FIFO_OVERRUN_ERR;
  439. }
  440. pUartBuf->RxTailPoint = (pUartBuf->RxTailPoint+1)%RXBUFSIZE;
  441. break;
  442. default:
  443. break;
  444. }
  445. VICVectAddr = 0; // Clear interrupt in VIC.
  446. }