uart.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  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. /*static uint8_t uart_lookupratio(float f_fr) {
  10. uint16_t errors[72]={0,67,71,77,83,91,100,111,125,
  11. 133,143,154,167,182,200,214,222,231,
  12. 250,267,273,286,300,308,333,357,364,
  13. 375,385,400,417,429,444,455,462,467,
  14. 500,533,538,545,556,571,583,600,615,
  15. 625,636,643,667,692,700,714,727,733,
  16. 750,769,778,786,800,818,833,846,857,
  17. 867,875,889,900,909,917,923,929,933};
  18. uint8_t ratios[72]={0x10,0xf1,0xe1,0xd1,0xc1,0xb1,0xa1,0x91,0x81,
  19. 0xf2,0x71,0xd2,0x61,0xb2,0x51,0xe3,0x92,0xd3,
  20. 0x41,0xf4,0xb3,0x72,0xa3,0xd4,0x31,0xe5,0xb4,
  21. 0x83,0xd5,0x52,0xc5,0x73,0x94,0xb5,0xd6,0xf7,
  22. 0x21,0xf8,0xd7,0xb6,0x95,0x74,0xc7,0x53,0xd8,
  23. 0x85,0xb7,0xe9,0x32,0xd9,0xa7,0x75,0xb8,0xfb,
  24. 0x43,0xda,0x97,0xeb,0x54,0xb9,0x65,0xdb,0x76,
  25. 0xfd,0x87,0x98,0xa9,0xba,0xcb,0xdc,0xed,0xfe};
  26. int fr = (f_fr-1)*1000;
  27. int i=0, i_result=0;
  28. int err=0, lasterr=1000;
  29. for(i=0; i<72; i++) {
  30. if(fr<errors[i]) {
  31. err=errors[i]-fr;
  32. } else {
  33. err=fr-errors[i];
  34. }
  35. if(err<lasterr) {
  36. i_result=i;
  37. lasterr=err;
  38. }
  39. }
  40. return ratios[i_result];
  41. }
  42. */
  43. /*static uint32_t baud2divisor(unsigned int baudrate) {
  44. uint32_t int_ratio;
  45. uint32_t error;
  46. uint32_t dl=0;
  47. float f_ratio;
  48. float f_fr;
  49. float f_dl;
  50. float f_pclk = (float)CONFIG_CPU_FREQUENCY / CONFIG_UART_PCLKDIV;
  51. uint8_t fract_ratio;
  52. f_ratio=(f_pclk / 16 / baudrate);
  53. int_ratio = (int)f_ratio;
  54. error=(f_ratio*1000)-(int_ratio*1000);
  55. if(error>990) {
  56. int_ratio++;
  57. } else if(error>10) {
  58. f_fr=1.5;
  59. f_dl=f_pclk / (16 * baudrate * (f_fr));
  60. dl = (int)f_dl;
  61. f_fr=f_pclk / (16 * baudrate * dl);
  62. fract_ratio = uart_lookupratio(f_fr);
  63. }
  64. if(!dl) {
  65. return int_ratio;
  66. } else {
  67. return ((fract_ratio<<16)&0xff0000) | dl;
  68. }
  69. }
  70. */
  71. //static char txbuf[1 << CONFIG_UART_TX_BUF_SHIFT];
  72. static volatile unsigned int read_idx, write_idx;
  73. void uart_putc( char c )
  74. {
  75. if ( c == '\n' )
  76. {
  77. uart_putc( '\r' );
  78. }
  79. while ( !( UART_REGS->LSR & ( 0x20 ) ) );
  80. UART_REGS->THR = c;
  81. }
  82. /* Polling version only */
  83. unsigned char uart_getc( void )
  84. {
  85. /* wait for character */
  86. while ( !( BITBANG( UART_REGS->LSR, 0 ) ) ) ;
  87. return UART_REGS->RBR;
  88. }
  89. /* Returns true if a char is ready */
  90. unsigned char uart_gotc( void )
  91. {
  92. return BITBANG( UART_REGS->LSR, 0 );
  93. }
  94. void uart_init( void )
  95. {
  96. uint32_t div;
  97. /* Turn on power to UART */
  98. BITBANG( LPC_SC->PCONP, UART_PCONBIT ) = 1;
  99. /* UART clock = CPU clock - this block is reduced at compile-time */
  100. if ( CONFIG_UART_PCLKDIV == 1 )
  101. {
  102. BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
  103. BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0;
  104. }
  105. else if ( CONFIG_UART_PCLKDIV == 2 )
  106. {
  107. BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
  108. BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1;
  109. }
  110. else if ( CONFIG_UART_PCLKDIV == 4 )
  111. {
  112. BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
  113. BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0;
  114. }
  115. else // Fallback: Divide by 8
  116. {
  117. BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
  118. BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1;
  119. }
  120. /* set baud rate - no fractional stuff for now */
  121. UART_REGS->LCR = BV( 7 ) | 3; // always 8n1
  122. div = 0xF80022; //0x850004; // baud2divisor(CONFIG_UART_BAUDRATE);
  123. UART_REGS->DLL = div & 0xff;
  124. UART_REGS->DLM = ( div >> 8 ) & 0xff;
  125. BITBANG( UART_REGS->LCR, 7 ) = 0;
  126. if ( div & 0xff0000 )
  127. {
  128. UART_REGS->FDR = ( div >> 16 ) & 0xff;
  129. }
  130. /* reset and enable FIFO */
  131. UART_REGS->FCR = BV( 0 );
  132. UART_REGS->THR = '?';
  133. }
  134. /* --- generic code below --- */
  135. void uart_puthex( uint8_t num )
  136. {
  137. uint8_t tmp;
  138. tmp = ( num & 0xf0 ) >> 4;
  139. if ( tmp < 10 )
  140. {
  141. uart_putc( '0' + tmp );
  142. }
  143. else
  144. {
  145. uart_putc( 'a' + tmp - 10 );
  146. }
  147. tmp = num & 0x0f;
  148. if ( tmp < 10 )
  149. {
  150. uart_putc( '0' + tmp );
  151. }
  152. else
  153. {
  154. uart_putc( 'a' + tmp - 10 );
  155. }
  156. }
  157. void uart_trace( void *ptr, uint16_t start, uint16_t len )
  158. {
  159. uint16_t i;
  160. uint8_t j;
  161. uint8_t ch;
  162. uint8_t *data = ptr;
  163. data += start;
  164. for ( i = 0; i < len; i += 16 )
  165. {
  166. uart_puthex( start >> 8 );
  167. uart_puthex( start & 0xff );
  168. uart_putc( '|' );
  169. uart_putc( ' ' );
  170. for ( j = 0; j < 16; j++ )
  171. {
  172. if ( i + j < len )
  173. {
  174. ch = *( data + j );
  175. uart_puthex( ch );
  176. }
  177. else
  178. {
  179. uart_putc( ' ' );
  180. uart_putc( ' ' );
  181. }
  182. uart_putc( ' ' );
  183. }
  184. uart_putc( '|' );
  185. for ( j = 0; j < 16; j++ )
  186. {
  187. if ( i + j < len )
  188. {
  189. ch = *( data++ );
  190. if ( ch < 32 || ch > 0x7e )
  191. {
  192. ch = '.';
  193. }
  194. uart_putc( ch );
  195. }
  196. else
  197. {
  198. uart_putc( ' ' );
  199. }
  200. }
  201. uart_putc( '|' );
  202. uart_putcrlf();
  203. start += 16;
  204. }
  205. }
  206. void uart_flush( void )
  207. {
  208. while ( read_idx != write_idx ) ;
  209. }
  210. void uart_puts( const char *text )
  211. {
  212. while ( *text )
  213. {
  214. uart_putc( *text++ );
  215. }
  216. }