uart.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /*
  2. uart.c: UART access routines
  3. */
  4. #include <arm/NXP/LPC17xx/LPC17xx.h>
  5. #include "bits.h"
  6. #include "config.h"
  7. #include "uart.h"
  8. #include "led.h"
  9. /* A few symbols to make this code work for all four UARTs */
  10. #if defined(CONFIG_UART_NUM) && CONFIG_UART_NUM == 0
  11. # define UART_PCONBIT 3
  12. # define UART_PCLKREG PCLKSEL0
  13. # define UART_PCLKBIT 6
  14. # define UART_REGS LPC_UART0
  15. # define UART_HANDLER UART0_IRQHandler
  16. # define UART_IRQ UART0_IRQn
  17. #elif CONFIG_UART_NUM == 1
  18. # define UART_PCONBIT 4
  19. # define UART_PCLKREG PCLKSEL0
  20. # define UART_PCLKBIT 8
  21. # define UART_REGS LPC_UART1
  22. # define UART_HANDLER UART1_IRQHandler
  23. # define UART_IRQ UART1_IRQn
  24. #elif CONFIG_UART_NUM == 2
  25. # define UART_PCONBIT 24
  26. # define UART_PCLKREG PCLKSEL1
  27. # define UART_PCLKBIT 16
  28. # define UART_REGS LPC_UART2
  29. # define UART_HANDLER UART2_IRQHandler
  30. # define UART_IRQ UART2_IRQn
  31. #elif CONFIG_UART_NUM == 3
  32. # define UART_PCONBIT 25
  33. # define UART_PCLKREG PCLKSEL1
  34. # define UART_PCLKBIT 18
  35. # define UART_REGS LPC_UART3
  36. # define UART_HANDLER UART3_IRQHandler
  37. # define UART_IRQ UART3_IRQn
  38. #else
  39. # error CONFIG_UART_NUM is not set or has an invalid value!
  40. #endif
  41. static uint8_t uart_lookupratio( float f_fr )
  42. {
  43. uint16_t errors[72] = {0, 67, 71, 77, 83, 91, 100, 111, 125,
  44. 133, 143, 154, 167, 182, 200, 214, 222, 231,
  45. 250, 267, 273, 286, 300, 308, 333, 357, 364,
  46. 375, 385, 400, 417, 429, 444, 455, 462, 467,
  47. 500, 533, 538, 545, 556, 571, 583, 600, 615,
  48. 625, 636, 643, 667, 692, 700, 714, 727, 733,
  49. 750, 769, 778, 786, 800, 818, 833, 846, 857,
  50. 867, 875, 889, 900, 909, 917, 923, 929, 933
  51. };
  52. uint8_t ratios[72] = {0x10, 0xf1, 0xe1, 0xd1, 0xc1, 0xb1, 0xa1, 0x91, 0x81,
  53. 0xf2, 0x71, 0xd2, 0x61, 0xb2, 0x51, 0xe3, 0x92, 0xd3,
  54. 0x41, 0xf4, 0xb3, 0x72, 0xa3, 0xd4, 0x31, 0xe5, 0xb4,
  55. 0x83, 0xd5, 0x52, 0xc5, 0x73, 0x94, 0xb5, 0xd6, 0xf7,
  56. 0x21, 0xf8, 0xd7, 0xb6, 0x95, 0x74, 0xc7, 0x53, 0xd8,
  57. 0x85, 0xb7, 0xe9, 0x32, 0xd9, 0xa7, 0x75, 0xb8, 0xfb,
  58. 0x43, 0xda, 0x97, 0xeb, 0x54, 0xb9, 0x65, 0xdb, 0x76,
  59. 0xfd, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe
  60. };
  61. int fr = ( f_fr - 1 ) * 1000;
  62. int i = 0, i_result = 0;
  63. int err = 0, lasterr = 1000;
  64. for ( i = 0; i < 72; i++ )
  65. {
  66. if ( fr < errors[i] )
  67. {
  68. err = errors[i] - fr;
  69. }
  70. else
  71. {
  72. err = fr - errors[i];
  73. }
  74. if ( err < lasterr )
  75. {
  76. i_result = i;
  77. lasterr = err;
  78. }
  79. }
  80. return ratios[i_result];
  81. }
  82. static uint32_t baud2divisor( unsigned int baudrate )
  83. {
  84. uint32_t int_ratio;
  85. uint32_t error;
  86. uint32_t dl = 0;
  87. float f_ratio;
  88. float f_fr;
  89. float f_dl;
  90. float f_pclk = ( float )CONFIG_CPU_FREQUENCY / CONFIG_UART_PCLKDIV;
  91. uint8_t fract_ratio;
  92. f_ratio = ( f_pclk / 16 / baudrate );
  93. int_ratio = ( int )f_ratio;
  94. error = ( f_ratio * 1000 ) - ( int_ratio * 1000 );
  95. if ( error > 990 )
  96. {
  97. int_ratio++;
  98. }
  99. else if ( error > 10 )
  100. {
  101. f_fr = 1.5;
  102. f_dl = f_pclk / ( 16 * baudrate * ( f_fr ) );
  103. dl = ( int )f_dl;
  104. f_fr = f_pclk / ( 16 * baudrate * dl );
  105. fract_ratio = uart_lookupratio( f_fr );
  106. }
  107. if ( !dl )
  108. {
  109. return int_ratio;
  110. }
  111. else
  112. {
  113. return ( ( fract_ratio << 16 ) & 0xff0000 ) | dl;
  114. }
  115. }
  116. static char txbuf[1 << CONFIG_UART_TX_BUF_SHIFT];
  117. static volatile unsigned int read_idx, write_idx;
  118. void UART_HANDLER( void )
  119. {
  120. int iir = UART_REGS->IIR;
  121. if ( !( iir & 1 ) )
  122. {
  123. /* Interrupt is pending */
  124. switch ( iir & 14 )
  125. {
  126. #if CONFIG_UART_NUM == 1
  127. case 0: /* modem status */
  128. ( void ) UART_REGS->MSR; // dummy read to clear
  129. break;
  130. #endif
  131. case 2: /* THR empty - send */
  132. if ( read_idx != write_idx )
  133. {
  134. int maxchars = 16;
  135. while ( read_idx != write_idx && --maxchars > 0 )
  136. {
  137. UART_REGS->THR = ( unsigned char )txbuf[read_idx];
  138. read_idx = ( read_idx + 1 ) & ( sizeof( txbuf ) - 1 );
  139. }
  140. if ( read_idx == write_idx )
  141. {
  142. /* buffer empty - turn off THRE interrupt */
  143. BITBAND( UART_REGS->IER, 1 ) = 0;
  144. }
  145. }
  146. break;
  147. case 12: /* RX timeout */
  148. case 4: /* data received - not implemented yet */
  149. ( void ) UART_REGS->RBR; // dummy read to clear
  150. break;
  151. case 6: /* RX error */
  152. ( void ) UART_REGS->LSR; // dummy read to clear
  153. default: break;
  154. }
  155. }
  156. }
  157. void uart_putc( char c )
  158. {
  159. if ( c == '\n' )
  160. {
  161. uart_putc( '\r' );
  162. }
  163. unsigned int tmp = ( write_idx + 1 ) & ( sizeof( txbuf ) - 1 ) ;
  164. if ( read_idx == write_idx && ( BITBAND( UART_REGS->LSR, 5 ) ) )
  165. {
  166. /* buffer empty, THR empty -> send immediately */
  167. UART_REGS->THR = ( unsigned char )c;
  168. }
  169. else
  170. {
  171. #ifdef CONFIG_UART_DEADLOCKABLE
  172. while ( tmp == read_idx ) ;
  173. #endif
  174. BITBAND( UART_REGS->IER, 1 ) = 0; // turn off UART interrupt
  175. txbuf[write_idx] = c;
  176. write_idx = tmp;
  177. BITBAND( UART_REGS->IER, 1 ) = 1;
  178. }
  179. }
  180. /* Polling version only */
  181. unsigned char uart_getc( void )
  182. {
  183. /* wait for character */
  184. while ( !( BITBAND( UART_REGS->LSR, 0 ) ) ) ;
  185. return UART_REGS->RBR;
  186. }
  187. /* Returns true if a char is ready */
  188. unsigned char uart_gotc( void )
  189. {
  190. return BITBAND( UART_REGS->LSR, 0 );
  191. }
  192. void uart_init( void )
  193. {
  194. uint32_t div;
  195. /* Turn on power to UART */
  196. BITBAND( LPC_SC->PCONP, UART_PCONBIT ) = 1;
  197. /* UART clock = CPU clock - this block is reduced at compile-time */
  198. if ( CONFIG_UART_PCLKDIV == 1 )
  199. {
  200. BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
  201. BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0;
  202. }
  203. else if ( CONFIG_UART_PCLKDIV == 2 )
  204. {
  205. BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
  206. BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1;
  207. }
  208. else if ( CONFIG_UART_PCLKDIV == 4 )
  209. {
  210. BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
  211. BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0;
  212. }
  213. else // Fallback: Divide by 8
  214. {
  215. BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
  216. BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1;
  217. }
  218. /* set baud rate - no fractional stuff for now */
  219. UART_REGS->LCR = BV( 7 ) | 3; // always 8n1
  220. div = baud2divisor( CONFIG_UART_BAUDRATE );
  221. UART_REGS->DLL = div & 0xff;
  222. UART_REGS->DLM = ( div >> 8 ) & 0xff;
  223. BITBAND( UART_REGS->LCR, 7 ) = 0;
  224. if ( div & 0xff0000 )
  225. {
  226. UART_REGS->FDR = ( div >> 16 ) & 0xff;
  227. }
  228. /* reset and enable FIFO */
  229. UART_REGS->FCR = BV( 0 );
  230. /* enable transmit interrupt */
  231. BITBAND( UART_REGS->IER, 1 ) = 1;
  232. NVIC_EnableIRQ( UART_IRQ );
  233. UART_REGS->THR = '?';
  234. }
  235. /* --- generic code below --- */
  236. void uart_puthex( uint8_t num )
  237. {
  238. uint8_t tmp;
  239. tmp = ( num & 0xf0 ) >> 4;
  240. if ( tmp < 10 )
  241. {
  242. uart_putc( '0' + tmp );
  243. }
  244. else
  245. {
  246. uart_putc( 'a' + tmp - 10 );
  247. }
  248. tmp = num & 0x0f;
  249. if ( tmp < 10 )
  250. {
  251. uart_putc( '0' + tmp );
  252. }
  253. else
  254. {
  255. uart_putc( 'a' + tmp - 10 );
  256. }
  257. }
  258. void uart_trace( void *ptr, uint16_t start, uint16_t len, uint32_t addr )
  259. {
  260. uint16_t i;
  261. uint8_t j;
  262. uint8_t ch;
  263. uint8_t *data = ptr;
  264. data += start;
  265. for ( i = 0; i < len; i += 16 )
  266. {
  267. uart_puthex( ( addr + start ) >> 16 );
  268. uart_puthex( ( ( addr + start ) >> 8 ) & 0xff );
  269. uart_puthex( ( addr + start ) & 0xff );
  270. uart_putc( '|' );
  271. uart_putc( ' ' );
  272. for ( j = 0; j < 16; j++ )
  273. {
  274. if ( i + j < len )
  275. {
  276. ch = *( data + j );
  277. uart_puthex( ch );
  278. }
  279. else
  280. {
  281. uart_putc( ' ' );
  282. uart_putc( ' ' );
  283. }
  284. uart_putc( ' ' );
  285. }
  286. uart_putc( '|' );
  287. for ( j = 0; j < 16; j++ )
  288. {
  289. if ( i + j < len )
  290. {
  291. ch = *( data++ );
  292. if ( ch < 32 || ch > 0x7e )
  293. {
  294. ch = '.';
  295. }
  296. uart_putc( ch );
  297. }
  298. else
  299. {
  300. uart_putc( ' ' );
  301. }
  302. }
  303. uart_putc( '|' );
  304. uart_putcrlf();
  305. start += 16;
  306. }
  307. }
  308. void uart_flush( void )
  309. {
  310. while ( read_idx != write_idx ) ;
  311. }
  312. void uart_puts( const char *text )
  313. {
  314. while ( *text )
  315. {
  316. uart_putc( *text++ );
  317. }
  318. }