[f4392b88] | 1 | /* |
---|
| 2 | * console driver for RTL22xx UARTs |
---|
| 3 | * |
---|
| 4 | * This driver uses the shared console driver in |
---|
| 5 | * ...../libbsp/shared/console.c |
---|
| 6 | * |
---|
| 7 | * If you want the driver to be interrupt driven, you |
---|
| 8 | * need to write the ISR, and in the ISR insert the |
---|
| 9 | * chars into termios's queue. |
---|
[e890774] | 10 | * Copyright (c) By ray <rayx.cn@gmail.com> |
---|
[f4392b88] | 11 | * |
---|
| 12 | * The license and distribution terms for this file may be |
---|
| 13 | * found in the file LICENSE in this distribution or at |
---|
| 14 | * |
---|
[6f1247b] | 15 | * http://www.rtems.com/license/LICENSE. |
---|
[f4392b88] | 16 | * |
---|
| 17 | * |
---|
| 18 | */ |
---|
| 19 | #include <bsp.h> /* Must be before libio.h */ |
---|
| 20 | #include <rtems/libio.h> |
---|
| 21 | #include <termios.h> |
---|
| 22 | #include <rtems/bspIo.h> |
---|
| 23 | |
---|
| 24 | /* Put the CPU (or UART) specific header file #include here */ |
---|
| 25 | #include <lpc22xx.h> |
---|
| 26 | #include "lpc22xx_uart.h" |
---|
| 27 | |
---|
| 28 | #include <libchip/serial.h> |
---|
| 29 | #include <libchip/sersupp.h> |
---|
| 30 | |
---|
| 31 | /* How many serial ports? */ |
---|
| 32 | #define NUM_DEVS 1 |
---|
| 33 | |
---|
| 34 | int uart_poll_read(int minor); |
---|
| 35 | |
---|
| 36 | int dbg_dly; |
---|
| 37 | |
---|
| 38 | /* static function prototypes */ |
---|
| 39 | static int uart_first_open(int major, int minor, void *arg); |
---|
| 40 | static int uart_last_close(int major, int minor, void *arg); |
---|
| 41 | static int uart_read(int minor); |
---|
| 42 | static int uart_write(int minor, const char *buf, int len); |
---|
| 43 | static void uart_init(int minor); |
---|
| 44 | static void uart_write_polled(int minor, char c); |
---|
| 45 | static int uart_set_attributes(int minor, const struct termios *t); |
---|
| 46 | |
---|
| 47 | /* These are used by code in console.c */ |
---|
| 48 | unsigned long Console_Port_Count = NUM_DEVS; |
---|
| 49 | console_data Console_Port_Data[NUM_DEVS]; |
---|
| 50 | |
---|
| 51 | /* rtems console uses the following minor number */ |
---|
| 52 | rtems_device_minor_number Console_Port_Minor = 0; |
---|
| 53 | |
---|
| 54 | /* Pointers to functions for handling the UART. */ |
---|
| 55 | console_fns uart_fns = |
---|
| 56 | { |
---|
| 57 | libchip_serial_default_probe, |
---|
| 58 | uart_first_open, |
---|
| 59 | uart_last_close, |
---|
| 60 | uart_read, |
---|
| 61 | uart_write, |
---|
| 62 | uart_init, |
---|
| 63 | uart_write_polled, /* not used in this driver */ |
---|
| 64 | uart_set_attributes, |
---|
| 65 | FALSE /* TRUE if interrupt driven, FALSE if not. */ |
---|
| 66 | }; |
---|
| 67 | |
---|
| 68 | /* |
---|
| 69 | * There's one item in array for each UART. |
---|
| 70 | * |
---|
| 71 | * Some of these fields are marked "NOT USED". They are not used |
---|
| 72 | * by console.c, but may be used by drivers in libchip |
---|
| 73 | * |
---|
| 74 | */ |
---|
| 75 | console_tbl Console_Port_Tbl[] = { |
---|
| 76 | { |
---|
| 77 | "/dev/console", /* sDeviceName */ |
---|
| 78 | SERIAL_CUSTOM, /* deviceType */ |
---|
| 79 | &uart_fns, /* pDeviceFns */ |
---|
| 80 | NULL, /* deviceProbe */ |
---|
| 81 | NULL, /* pDeviceFlow */ |
---|
| 82 | 0, /* ulMargin - NOT USED */ |
---|
| 83 | 0, /* ulHysteresis - NOT USED */ |
---|
| 84 | NULL, /* pDeviceParams */ |
---|
| 85 | 0, /* ulCtrlPort1 - NOT USED */ |
---|
| 86 | 0, /* ulCtrlPort2 - NOT USED */ |
---|
| 87 | 0, /* ulDataPort - NOT USED */ |
---|
| 88 | NULL, /* getRegister - NOT USED */ |
---|
| 89 | NULL, /* setRegister - NOT USED */ |
---|
| 90 | NULL, /* getData - NOT USED */ |
---|
| 91 | NULL, /* setData - NOT USED */ |
---|
| 92 | 0, /* ulClock - NOT USED */ |
---|
| 93 | 0 /* ulIntVector - NOT USED */ |
---|
| 94 | } |
---|
| 95 | #if 0 |
---|
| 96 | { |
---|
| 97 | "/dev/com1", /* sDeviceName */ |
---|
| 98 | SERIAL_CUSTOM, /* deviceType */ |
---|
| 99 | &uart_fns, /* pDeviceFns */ |
---|
| 100 | NULL, /* deviceProbe */ |
---|
| 101 | NULL, /* pDeviceFlow */ |
---|
| 102 | 0, /* ulMargin - NOT USED */ |
---|
| 103 | 0, /* ulHysteresis - NOT USED */ |
---|
| 104 | NULL, /* pDeviceParams */ |
---|
| 105 | 0, /* ulCtrlPort1 - NOT USED */ |
---|
| 106 | 0, /* ulCtrlPort2 - NOT USED */ |
---|
| 107 | 0, /* ulDataPort - NOT USED */ |
---|
| 108 | NULL, /* getRegister - NOT USED */ |
---|
| 109 | NULL, /* setRegister - NOT USED */ |
---|
| 110 | NULL, /* getData - NOT USED */ |
---|
| 111 | NULL, /* setData - NOT USED */ |
---|
| 112 | 0, /* ulClock - NOT USED */ |
---|
| 113 | 0 /* ulIntVector - NOT USED */ |
---|
| 114 | } |
---|
| 115 | #endif |
---|
| 116 | }; |
---|
| 117 | |
---|
| 118 | /*********************************************************************/ |
---|
| 119 | /* Functions called via termios callbacks (i.e. the ones in uart_fns */ |
---|
| 120 | /*********************************************************************/ |
---|
| 121 | |
---|
| 122 | /* |
---|
| 123 | * This is called the first time each device is opened. If the driver |
---|
| 124 | * is interrupt driven, you should enable interrupts here. Otherwise, |
---|
| 125 | * it's probably safe to do nothing. |
---|
| 126 | * |
---|
| 127 | * Since micromonitor already set up the UART, we do nothing. |
---|
| 128 | */ |
---|
| 129 | static int uart_first_open(int major, int minor, void *arg) |
---|
| 130 | { |
---|
| 131 | return 0; |
---|
| 132 | } |
---|
| 133 | |
---|
| 134 | |
---|
| 135 | /* |
---|
| 136 | * This is called the last time each device is closed. If the driver |
---|
| 137 | * is interrupt driven, you should disable interrupts here. Otherwise, |
---|
| 138 | * it's probably safe to do nothing. |
---|
| 139 | */ |
---|
| 140 | static int uart_last_close(int major, int minor, void *arg) |
---|
| 141 | { |
---|
| 142 | return 0; |
---|
| 143 | } |
---|
| 144 | |
---|
| 145 | |
---|
| 146 | /* |
---|
| 147 | * Read one character from UART. |
---|
| 148 | * |
---|
| 149 | * Return -1 if there's no data, otherwise return |
---|
| 150 | * the character in lowest 8 bits of returned int. |
---|
| 151 | */ |
---|
| 152 | static int uart_read(int minor) |
---|
| 153 | { |
---|
| 154 | char c; |
---|
| 155 | |
---|
| 156 | if (minor == 0) { |
---|
| 157 | if(U0LSR & ULSR_RDR) { |
---|
| 158 | c = U0RBR; |
---|
| 159 | return c; |
---|
| 160 | } else { |
---|
| 161 | return -1; |
---|
| 162 | } |
---|
| 163 | } else if (minor == 1) { |
---|
| 164 | if (U1LSR & ULSR_RDR) { |
---|
| 165 | c = U1RBR; |
---|
| 166 | return c; |
---|
| 167 | } else { |
---|
| 168 | return -1; |
---|
| 169 | } |
---|
| 170 | } else { |
---|
[e890774] | 171 | debug_printk("Unknown console minor number"); |
---|
| 172 | printi(minor); |
---|
[f4392b88] | 173 | return -1; |
---|
| 174 | } |
---|
| 175 | |
---|
| 176 | } |
---|
| 177 | |
---|
| 178 | |
---|
| 179 | /* |
---|
| 180 | * Write buffer to UART |
---|
| 181 | * |
---|
| 182 | * return 1 on success, -1 on error |
---|
| 183 | */ |
---|
| 184 | static int uart_write(int minor, const char *buf, int len) |
---|
| 185 | { |
---|
| 186 | int i; |
---|
| 187 | |
---|
| 188 | if (minor == 0) { |
---|
| 189 | for (i = 0; i < len; i++) { |
---|
| 190 | while(!(U0LSR & ULSR_THRE)) /* wait for TX buffer to empty*/ |
---|
| 191 | continue; /* also either WDOG() or swap()*/ |
---|
| 192 | U0THR = (char) buf[i]; |
---|
| 193 | } |
---|
| 194 | } else if (minor == 1) { |
---|
| 195 | for (i = 0; i < len; i++) { |
---|
| 196 | while(!(U0LSR & ULSR_THRE)) /* wait for TX buffer to empty*/ |
---|
| 197 | continue; /* also either WDOG() or swap()*/ |
---|
| 198 | U0THR = (char) buf[i]; |
---|
| 199 | } |
---|
| 200 | }else { |
---|
[e890774] | 201 | debug_printk("Unknown console minor number"); |
---|
| 202 | printi(minor); |
---|
[f4392b88] | 203 | return -1; |
---|
| 204 | } |
---|
| 205 | |
---|
| 206 | return 1; |
---|
| 207 | } |
---|
| 208 | |
---|
| 209 | |
---|
| 210 | /* Set up the UART. */ |
---|
| 211 | static void uart_init(int minor) |
---|
| 212 | { |
---|
| 213 | #if 0 //init will be done in bspstart.c |
---|
| 214 | int baud=6; |
---|
| 215 | int mode =0x03; |
---|
| 216 | if(minor==0){ |
---|
| 217 | // set port pins for UART0 |
---|
| 218 | PINSEL0 = (PINSEL0 & ~U0_PINMASK) | U0_PINSEL; |
---|
| 219 | |
---|
| 220 | U0IER = 0x00; // disable all interrupts |
---|
| 221 | |
---|
| 222 | // set the baudrate |
---|
| 223 | U0LCR = 1<<7; // select divisor latches |
---|
| 224 | U0DLL = (uint8_t)baud; // set for baud low byte |
---|
| 225 | U0DLM = (uint8_t)(baud >> 8); // set for baud high byte |
---|
| 226 | |
---|
| 227 | // set the number of characters and other |
---|
| 228 | // user specified operating parameters |
---|
| 229 | U0LCR = (mode & ~ULCR_DLAB_ENABLE); |
---|
| 230 | U0FCR = mode>>8; /*fifo mode*/ |
---|
| 231 | |
---|
| 232 | // set port pins for UART1 |
---|
| 233 | PINSEL0 = (PINSEL0 & ~U1_PINMASK) | U1_PINSEL; |
---|
| 234 | |
---|
| 235 | U1IER = 0x00; // disable all interrupts |
---|
| 236 | }else if(minor==1){ |
---|
| 237 | // set the baudrate |
---|
| 238 | U1LCR = ULCR_DLAB_ENABLE; // select divisor latches |
---|
| 239 | U1DLL = (uint8_t)baud; // set for baud low byte |
---|
| 240 | U1DLM = (uint8_t)(baud >> 8); // set for baud high byte |
---|
| 241 | |
---|
| 242 | // set the number of characters and other |
---|
| 243 | // user specified operating parameters |
---|
| 244 | U1LCR = (mode & ~ULCR_DLAB_ENABLE); |
---|
| 245 | U1FCR = mode>>8;/*fifo mode*/ |
---|
| 246 | } |
---|
| 247 | |
---|
| 248 | #endif |
---|
| 249 | } |
---|
| 250 | |
---|
| 251 | /* I'm not sure this is needed for the shared console driver. */ |
---|
| 252 | static void uart_write_polled(int minor, char c) |
---|
| 253 | { |
---|
| 254 | uart_write(minor, &c, 1); |
---|
| 255 | } |
---|
| 256 | |
---|
| 257 | /* This is for setting baud rate, bits, etc. */ |
---|
| 258 | static int uart_set_attributes(int minor, const struct termios *t) |
---|
| 259 | { |
---|
| 260 | return 0; |
---|
| 261 | } |
---|
| 262 | |
---|
| 263 | /***********************************************************************/ |
---|
| 264 | /* |
---|
| 265 | * The following functions are not used by TERMIOS, but other RTEMS |
---|
| 266 | * functions use them instead. |
---|
| 267 | */ |
---|
| 268 | /***********************************************************************/ |
---|
| 269 | /* |
---|
| 270 | * Read from UART. This is used in the exit code, and can't |
---|
| 271 | * rely on interrupts. |
---|
| 272 | */ |
---|
| 273 | int uart_poll_read(int minor) |
---|
| 274 | { |
---|
| 275 | return uart_read(minor); |
---|
| 276 | } |
---|
| 277 | |
---|
| 278 | |
---|
| 279 | /* |
---|
| 280 | * Write a character to the console. This is used by printk() and |
---|
| 281 | * maybe other low level functions. It should not use interrupts or any |
---|
| 282 | * RTEMS system calls. It needs to be very simple |
---|
| 283 | */ |
---|
| 284 | static void _BSP_put_char( char c ) { |
---|
| 285 | uart_write_polled(0, c); |
---|
| 286 | if (c == '\n') { |
---|
| 287 | uart_write_polled(0, '\r'); |
---|
| 288 | } |
---|
| 289 | } |
---|
| 290 | |
---|
| 291 | BSP_output_char_function_type BSP_output_char = _BSP_put_char; |
---|
| 292 | |
---|
| 293 | |
---|
| 294 | |
---|
| 295 | |
---|
| 296 | /**************************************************************************** |
---|
| 297 | * init USART 0¡£8 bit, 1 Stop,No checkout, BPS115200 |
---|
| 298 | ****************************************************************************/ |
---|
| 299 | void UART0_Ini(void) |
---|
| 300 | { |
---|
| 301 | long Fdiv; |
---|
| 302 | int i; |
---|
| 303 | PINSEL0 = 0x00000005; // I/O to UART0 |
---|
| 304 | U0LCR = 0x83; // DLAB = 1 |
---|
| 305 | Fdiv = (Fpclk >>4) / UART_BPS; // configure BPS |
---|
| 306 | U0DLM = Fdiv/256; |
---|
| 307 | U0DLL = Fdiv%256; |
---|
| 308 | U0LCR = 0x03; |
---|
| 309 | |
---|
| 310 | for(i=0;i<10;i++){ |
---|
| 311 | U0THR = 67; //send a C to see if is OK |
---|
| 312 | while( (U0LSR&0x40)==0 ); |
---|
| 313 | } |
---|
| 314 | } |
---|
| 315 | |
---|
| 316 | |
---|
| 317 | /**************************************************************************** |
---|
| 318 | *Send a Byte |
---|
| 319 | ****************************************************************************/ |
---|
| 320 | void UART0_SendByte(char data) |
---|
| 321 | { |
---|
| 322 | U0THR = data; |
---|
| 323 | |
---|
| 324 | while( (U0LSR&0x40)==0 ); |
---|
| 325 | } |
---|
| 326 | |
---|
| 327 | |
---|
| 328 | /**************************************************************************** |
---|
| 329 | *Send a string |
---|
| 330 | ****************************************************************************/ |
---|
| 331 | void UART0_SendStr(char const *str) |
---|
| 332 | { while(1) |
---|
| 333 | { if( *str == '\0' ) break; |
---|
| 334 | UART0_SendByte(*str++); // Send the char |
---|
| 335 | } |
---|
| 336 | } |
---|
| 337 | |
---|
| 338 | debug_printk(char *dg_str) |
---|
| 339 | { |
---|
| 340 | UART0_SendStr(dg_str); |
---|
| 341 | UART0_SendStr("\r\n"); |
---|
| 342 | } |
---|
| 343 | |
---|
| 344 | void printi(unsigned long value) |
---|
| 345 | { |
---|
| 346 | static char istring[9]={0,0,0,0,0,0,0,0,0}; |
---|
| 347 | static char tmp[9]={0,0,0,0,0,0,0,0,0}; |
---|
| 348 | char *sp; |
---|
| 349 | char *tp = tmp; |
---|
| 350 | |
---|
| 351 | long i; |
---|
| 352 | unsigned long v = value; |
---|
| 353 | int index; |
---|
| 354 | |
---|
| 355 | for(index=0;index<9;index++) |
---|
| 356 | istring[index]=tmp[index]=0x0; |
---|
| 357 | |
---|
| 358 | while (v || tp == tmp) |
---|
| 359 | { |
---|
| 360 | i = v % 16; |
---|
| 361 | v = v / 16; |
---|
| 362 | if (i < 10) |
---|
| 363 | *tp++ = i+'0'; |
---|
| 364 | else |
---|
| 365 | *tp++ = i + 'a' - 10; |
---|
| 366 | } |
---|
| 367 | |
---|
| 368 | sp = istring; |
---|
| 369 | while (tp > tmp) |
---|
| 370 | *sp++ = *--tp; |
---|
| 371 | |
---|
| 372 | tp=tmp; |
---|
| 373 | sp=istring; |
---|
| 374 | debug_printk(istring); |
---|
| 375 | |
---|
| 376 | } |
---|