uart.c 7.4 KB

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