FreeCalypso > hg > freecalypso-sw
comparison gsm-fw/serial/uart.c @ 143:afceeeb2cba1
Our nuc-fw is destined to become gsm-fw, so I went ahead and did the big hg mv
| author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
|---|---|
| date | Tue, 12 Nov 2013 05:35:48 +0000 |
| parents | nuc-fw/serial/uart.c@22c8199e08af |
| children |
comparison
equal
deleted
inserted
replaced
| 142:15d5977390c2 | 143:afceeeb2cba1 |
|---|---|
| 1 /******************************************************************************* | |
| 2 * | |
| 3 * UART.C | |
| 4 * | |
| 5 * This module allows to use the UARTs of chipset 1.5 in interrupt mode for | |
| 6 * the Receive side and in polling mode for the Transmit side. | |
| 7 * The driver calls a user's function when characters are received. | |
| 8 * | |
| 9 * (C) Texas Instruments 1999 | |
| 10 * | |
| 11 ******************************************************************************/ | |
| 12 | |
| 13 #include "../include/config.h" | |
| 14 #include "../include/sys_types.h" | |
| 15 | |
| 16 #include "serialswitch.h" | |
| 17 #include "uart.h" | |
| 18 | |
| 19 #include <string.h> | |
| 20 | |
| 21 #include "../bsp/mem.h" | |
| 22 | |
| 23 #if (BOARD != 34) | |
| 24 /* | |
| 25 * Needed to reset and restart the sleep timer in case of incoming characters. | |
| 26 */ | |
| 27 | |
| 28 extern SYS_BOOL uart_sleep_timer_enabled; | |
| 29 #endif | |
| 30 | |
| 31 #define BUFFER_SIZE (512) /* In bytes. */ | |
| 32 #define FIFO_SIZE (64) /* In bytes. */ | |
| 33 | |
| 34 #define STX 0x02 | |
| 35 #define DLE 0x10 | |
| 36 | |
| 37 /* | |
| 38 * TLR is used to program the RX FIFO trigger levels. FCR[7:4] are not used. | |
| 39 */ | |
| 40 | |
| 41 #define RX_FIFO_TRIGGER_LEVEL (12 << 4) | |
| 42 | |
| 43 | |
| 44 /* | |
| 45 * 16750 addresses. Registers accessed when LCR[7] = 0. | |
| 46 */ | |
| 47 | |
| 48 #define RHR (0x00) /* Rx buffer register - Read access */ | |
| 49 #define THR (0x00) /* Tx holding register - Write access */ | |
| 50 #define IER (0x01) /* Interrupt enable register */ | |
| 51 | |
| 52 /* | |
| 53 * 16750 addresses. Registers accessed when LCR[7] = 1. | |
| 54 */ | |
| 55 | |
| 56 #define DLL (0x00) /* Divisor latch (LSB) */ | |
| 57 #define DLM (0x01) /* Divisor latch (MSB) */ | |
| 58 | |
| 59 | |
| 60 /* | |
| 61 * EFR is accessed when LCR[7:0] = 0xBF. | |
| 62 */ | |
| 63 | |
| 64 #define EFR (0x02) /* Enhanced feature register */ | |
| 65 | |
| 66 | |
| 67 /* | |
| 68 * 16750 addresses. Bit 5 of the FCR register is accessed when LCR[7] = 1. | |
| 69 */ | |
| 70 | |
| 71 #define IIR (0x02) /* Interrupt ident. register - Read only */ | |
| 72 #define FCR (0x02) /* FIFO control register - Write only */ | |
| 73 #define LCR (0x03) /* Line control register */ | |
| 74 #define MCR (0x04) /* Modem control register */ | |
| 75 #define LSR (0x05) /* Line status register */ | |
| 76 #define MSR (0x06) /* Modem status register */ | |
| 77 #define TCR (0x06) /* Transmission control register */ | |
| 78 #define TLR (0x07) /* Trigger level register */ | |
| 79 #define MDR1 (0x08) /* Mode definition register 1 */ | |
| 80 #define SCR (0x10) /* Supplementary Control register */ | |
| 81 #define SSR (0x11) /* Supplementary Status register */ | |
| 82 | |
| 83 | |
| 84 /* | |
| 85 * Supplementary control register. | |
| 86 */ | |
| 87 | |
| 88 #define TX_EMPTY_CTL_IT (0x08) | |
| 89 #define RX_CTS_WAKE_UP_ENABLE_BIT (4) /* Use RESET_BIT and SET_BIT macros. */ | |
| 90 | |
| 91 /* | |
| 92 * Enhanced feature register. | |
| 93 */ | |
| 94 | |
| 95 #define ENHANCED_FEATURE_BIT (4) /* Use RESET_BIT and SET_BIT macros. */ | |
| 96 | |
| 97 /* | |
| 98 * Mode definition register 1. | |
| 99 */ | |
| 100 | |
| 101 #define UART_MODE (0x00) | |
| 102 #define SIR_MODE (0x01) | |
| 103 #define UART_MODE_AUTOBAUDING (0x02) /* Reserved in UART/IrDA. */ | |
| 104 #define RESET_DEFAULT_STATE (0x07) | |
| 105 #define IR_SLEEP_DISABLED (0x00) | |
| 106 #define IR_SLEEP_ENABLED (0x08) | |
| 107 #define SIR_TX_WITHOUT_ACREG2 (0x00) /* Reserved in UART/modem. */ | |
| 108 #define SIR_TX_WITH_ACREG2 (0x20) /* Reserved in UART/modem. */ | |
| 109 #define FRAME_LENGTH_METHOD (0x00) /* Reserved in UART/modem. */ | |
| 110 #define EOT_BIT_METHOD (0x80) /* Reserved in UART/modem. */ | |
| 111 | |
| 112 /* | |
| 113 * Supplementary Status Register | |
| 114 */ | |
| 115 | |
| 116 #define TX_FIFO_FULL (0x01) | |
| 117 | |
| 118 | |
| 119 /* | |
| 120 * Interrupt enable register. | |
| 121 */ | |
| 122 | |
| 123 #define ERBI (0x01) /* Enable received data available interrupt */ | |
| 124 #define ETBEI (0x02) /* Enable transmitter holding register empty interrupt */ | |
| 125 #define ELSI (0x04) /* Enable receiver line status interrupt */ | |
| 126 #define EDSSI (0x08) /* Enable modem status interrupt */ | |
| 127 #define IER_SLEEP (0x10) /* Enable sleep mode */ | |
| 128 | |
| 129 /* | |
| 130 * Modem control register. | |
| 131 */ | |
| 132 | |
| 133 #define MDTR (0x01) /* Data terminal ready. */ | |
| 134 #define MRTS (0x02) /* Request to send. */ | |
| 135 #define TCR_TLR_BIT (6) | |
| 136 | |
| 137 /* | |
| 138 * Line status register. | |
| 139 */ | |
| 140 | |
| 141 #define DR (0x01) /* Data ready */ | |
| 142 #define OE (0x02) /* Overrun error */ | |
| 143 #define PE (0x04) /* Parity error */ | |
| 144 #define FE (0x08) /* Framing error */ | |
| 145 #define BI (0x10) /* Break interrupt */ | |
| 146 #define THRE (0x20) /* Transmitter holding register (FIFO empty) */ | |
| 147 #define TEMT (0x40) /* Transmitter empty (FIFO and TSR both empty) */ | |
| 148 | |
| 149 /* | |
| 150 * Interrupt identification register. | |
| 151 * Bit 0 is set to 0 if an IT is pending. | |
| 152 * Bits 1 and 2 are used to identify the IT. | |
| 153 */ | |
| 154 | |
| 155 #define IIR_BITS_USED (0x07) | |
| 156 #define IT_NOT_PENDING (0x01) | |
| 157 #define RX_DATA (0x04) | |
| 158 #define TX_EMPTY (0x02) | |
| 159 #define MODEM_STATUS (0x00) | |
| 160 | |
| 161 /* | |
| 162 * Line control register. | |
| 163 */ | |
| 164 | |
| 165 #define WLS_5 (0x00) /* Word length: 5 bits */ | |
| 166 #define WLS_6 (0x01) /* Word length: 6 bits */ | |
| 167 #define WLS_7 (0x02) /* Word length: 7 bits */ | |
| 168 #define WLS_8 (0x03) /* Word length: 8 bits */ | |
| 169 #define STB (0x04) /* Number of stop bits: 0: 1, 1: 1,5 or 2 */ | |
| 170 #define PEN (0x08) /* Parity enable */ | |
| 171 #define EPS (0x10) /* Even parity select */ | |
| 172 #define BREAK_CONTROL (0x40) /* Enable a break condition */ | |
| 173 #define DLAB (0x80) /* Divisor latch access bit */ | |
| 174 #define DIV_EN_BIT (7) | |
| 175 | |
| 176 /* | |
| 177 * FIFO control register. | |
| 178 */ | |
| 179 | |
| 180 #define FIFO_ENABLE (0x01) | |
| 181 #define RX_FIFO_RESET (0x02) | |
| 182 #define TX_FIFO_RESET (0x04) | |
| 183 | |
| 184 /* | |
| 185 * These macros allow to read and write a UART register. | |
| 186 */ | |
| 187 | |
| 188 #define READ_UART_REGISTER(UART,REG) \ | |
| 189 *((volatile SYS_UWORD8 *) ((UART)->base_address + (REG))) | |
| 190 | |
| 191 #define WRITE_UART_REGISTER(UART,REG,VALUE) \ | |
| 192 *((volatile SYS_UWORD8 *) ((UART)->base_address + (REG))) = (VALUE) | |
| 193 | |
| 194 #define RESET_BIT(UART,REG,BIT) \ | |
| 195 (WRITE_UART_REGISTER ( \ | |
| 196 UART, REG, READ_UART_REGISTER (UART, REG) & ~(1 << (BIT)))) | |
| 197 | |
| 198 #define SET_BIT(UART,REG,BIT) \ | |
| 199 (WRITE_UART_REGISTER ( \ | |
| 200 UART, REG, READ_UART_REGISTER (UART, REG) | (1 << (BIT)))) | |
| 201 | |
| 202 /* | |
| 203 * These macros allow to enable or disable the wake-up interrupt. | |
| 204 */ | |
| 205 | |
| 206 #define ENABLE_WAKEUP_INTERRUPT(UART) \ | |
| 207 SET_BIT(UART, SCR, RX_CTS_WAKE_UP_ENABLE_BIT); | |
| 208 | |
| 209 #define DISABLE_WAKEUP_INTERRUPT(UART) \ | |
| 210 RESET_BIT(UART, SCR, RX_CTS_WAKE_UP_ENABLE_BIT); | |
| 211 | |
| 212 | |
| 213 /* | |
| 214 * This macro allows to know if the RX buffer is full. It must be called only | |
| 215 * from the RX interrupt handler. If it is called from the application, the | |
| 216 * rx_in pointer may be updated if a RX interrupt occurs. | |
| 217 */ | |
| 218 | |
| 219 #define RX_BUFFER_FULL(UART) \ | |
| 220 (((UART)->rx_in == (UART)->rx_out - 1) || \ | |
| 221 ((UART)->rx_in == (UART)->rx_out + BUFFER_SIZE - 1)) | |
| 222 | |
| 223 | |
| 224 /* | |
| 225 * This allows monitor the last 32 inbound buffers gotten from the RX FIFO. | |
| 226 */ | |
| 227 | |
| 228 //#define UART_RX_BUFFER_DUMP | |
| 229 | |
| 230 #ifdef UART_RX_BUFFER_DUMP | |
| 231 struct { | |
| 232 char rx_buffer[(BUFFER_SIZE + 1) << 5]; | |
| 233 char *rx_in; | |
| 234 int errors_count; | |
| 235 int wrong_interrupt_status; | |
| 236 } uart_rx_buffer_dump = {0}; | |
| 237 #endif | |
| 238 | |
| 239 | |
| 240 typedef struct s_uart { | |
| 241 | |
| 242 SYS_UWORD32 base_address; | |
| 243 | |
| 244 /* | |
| 245 * Buffers management. | |
| 246 */ | |
| 247 | |
| 248 char rx_buffer[BUFFER_SIZE + 1]; | |
| 249 char *rx_in; | |
| 250 char *rx_out; | |
| 251 void (*callback_function) (void); | |
| 252 | |
| 253 /* | |
| 254 * Errors counters. | |
| 255 */ | |
| 256 | |
| 257 SYS_UWORD32 framing_error; | |
| 258 SYS_UWORD32 parity_error; | |
| 259 SYS_UWORD32 overrun_error; | |
| 260 | |
| 261 /* | |
| 262 * Framing flags. | |
| 263 */ | |
| 264 | |
| 265 SYS_BOOL dle_detected; | |
| 266 SYS_BOOL inframe; | |
| 267 SYS_BOOL encapsulation_flag; | |
| 268 unsigned char frame_length; | |
| 269 | |
| 270 } t_uart; | |
| 271 | |
| 272 static t_uart uart_parameter[NUMBER_OF_TR_UART]; | |
| 273 | |
| 274 static const SYS_UWORD32 base_address[NUMBER_OF_TR_UART] = | |
| 275 { | |
| 276 MEM_UART_IRDA, | |
| 277 MEM_UART_MODEM | |
| 278 #if (CHIPSET == 12) | |
| 279 , MEM_UART_MODEM2 | |
| 280 #endif | |
| 281 }; | |
| 282 | |
| 283 | |
| 284 /* | |
| 285 * DLL (LSB) and DLH (MSB) registers values using the 13 MHz clock. | |
| 286 */ | |
| 287 | |
| 288 static const SYS_UWORD8 dll[] = | |
| 289 { | |
| 290 2, /* 406250 baud. */ | |
| 291 7, /* 115200 baud. */ | |
| 292 14, /* 57600 baud. */ | |
| 293 21, /* 38400 baud. */ | |
| 294 24, /* 33900 baud. */ | |
| 295 28, /* 28800 baud. */ | |
| 296 42, /* 19200 baud. */ | |
| 297 56, /* 14400 baud. */ | |
| 298 84, /* 9600 baud. */ | |
| 299 169, /* 4800 baud. */ | |
| 300 83, /* 2400 baud. */ | |
| 301 165, /* 1200 baud. */ | |
| 302 74, /* 600 baud. */ | |
| 303 148, /* 300 baud. */ | |
| 304 40, /* 150 baud. */ | |
| 305 81 /* 75 baud. */ | |
| 306 }; | |
| 307 | |
| 308 static const SYS_UWORD8 dlh[] = | |
| 309 { | |
| 310 0, /* 406250 baud. */ | |
| 311 0, /* 115200 baud. */ | |
| 312 0, /* 57600 baud. */ | |
| 313 0, /* 38400 baud. */ | |
| 314 0, /* 33900 baud. */ | |
| 315 0, /* 28800 baud. */ | |
| 316 0, /* 19200 baud. */ | |
| 317 0, /* 14400 baud. */ | |
| 318 0, /* 9600 baud. */ | |
| 319 0, /* 4800 baud. */ | |
| 320 1, /* 2400 baud. */ | |
| 321 2, /* 1200 baud. */ | |
| 322 5, /* 600 baud. */ | |
| 323 10, /* 300 baud. */ | |
| 324 21, /* 150 baud. */ | |
| 325 42 /* 75 baud. */ | |
| 326 }; | |
| 327 | |
| 328 | |
| 329 /******************************************************************************* | |
| 330 * | |
| 331 * read_rx_fifo | |
| 332 * | |
| 333 * Purpose : Check the bytes written into the RX FIFO. Characters are not | |
| 334 * written in the RX buffer if it is full. The HISR is called if | |
| 335 * enough characters are received. | |
| 336 * | |
| 337 * Arguments: In : uart: pointer on UART structure. | |
| 338 * Out: none | |
| 339 * | |
| 340 * Returns : none | |
| 341 * | |
| 342 ******************************************************************************/ | |
| 343 | |
| 344 static void | |
| 345 read_rx_fifo (t_uart *uart) | |
| 346 { | |
| 347 volatile SYS_UWORD8 status; | |
| 348 int error_detected; | |
| 349 SYS_UWORD8 char_received; | |
| 350 | |
| 351 #if (BOARD != 34) | |
| 352 /* | |
| 353 * Since new characters have been received, the sleep timer is reset then | |
| 354 * restarted preventing the system to enter deep-sleep for a new period of | |
| 355 * time. | |
| 356 */ | |
| 357 | |
| 358 SER_activate_timer_hisr (); | |
| 359 uart_sleep_timer_enabled = 1; | |
| 360 #endif | |
| 361 | |
| 362 status = READ_UART_REGISTER (uart, LSR); | |
| 363 | |
| 364 while (status & DR) { /* While RX FIFO is not empty... */ | |
| 365 | |
| 366 error_detected = 0; | |
| 367 | |
| 368 char_received = READ_UART_REGISTER (uart, RHR); | |
| 369 | |
| 370 /* | |
| 371 * Check if an error (overrun, parity, framing or break) is associated with the | |
| 372 * received data. If there is an error the byte is not copied into the | |
| 373 * RX buffer. | |
| 374 */ | |
| 375 | |
| 376 if (status & (OE | PE | FE | BI)) { | |
| 377 | |
| 378 if (status & PE) | |
| 379 uart->parity_error++; | |
| 380 | |
| 381 if (status & FE) | |
| 382 uart->framing_error++; | |
| 383 | |
| 384 if (status & OE) | |
| 385 uart->overrun_error++; | |
| 386 | |
| 387 error_detected = 1; | |
| 388 } | |
| 389 | |
| 390 /* | |
| 391 * If there is no error the byte is copied into the RX | |
| 392 * buffer if it is not full. | |
| 393 */ | |
| 394 | |
| 395 if (!error_detected && !RX_BUFFER_FULL (uart)) { | |
| 396 | |
| 397 *(uart->rx_in++) = char_received; | |
| 398 | |
| 399 if (uart->rx_in == &(uart->rx_buffer[0]) + BUFFER_SIZE + 1) | |
| 400 uart->rx_in = &(uart->rx_buffer[0]); | |
| 401 | |
| 402 #ifdef UART_RX_BUFFER_DUMP | |
| 403 *(uart_rx_buffer_dump.rx_in)++ = char_received; | |
| 404 | |
| 405 if (uart_rx_buffer_dump.rx_in == uart_rx_buffer_dump.rx_buffer + sizeof (uart_rx_buffer_dump.rx_buffer)) | |
| 406 uart_rx_buffer_dump.rx_in = uart_rx_buffer_dump.rx_buffer; | |
| 407 } | |
| 408 else { | |
| 409 uart_rx_buffer_dump.errors_count++; | |
| 410 #endif | |
| 411 } | |
| 412 | |
| 413 status = READ_UART_REGISTER (uart, LSR); | |
| 414 } | |
| 415 | |
| 416 /* | |
| 417 * Call the user's function. | |
| 418 */ | |
| 419 | |
| 420 if (uart->callback_function != NULL) | |
| 421 (*(uart->callback_function)) (); | |
| 422 } | |
| 423 | |
| 424 /******************************************************************************* | |
| 425 * | |
| 426 * initialize_uart_sleep | |
| 427 * | |
| 428 * Purpose : Performs basic UART hardware initialization including sleep mode. | |
| 429 * | |
| 430 * Arguments: In : uart_id : UART id. | |
| 431 * Out: none | |
| 432 * | |
| 433 * Returns: none | |
| 434 * | |
| 435 * Warning: Parameters are not verified. | |
| 436 * | |
| 437 ******************************************************************************/ | |
| 438 | |
| 439 void | |
| 440 initialize_uart_sleep (T_tr_UartId uart_id) | |
| 441 { | |
| 442 t_uart *uart; | |
| 443 int index; | |
| 444 SYS_UWORD8 dummy; | |
| 445 | |
| 446 for (index = 0; index < NUMBER_OF_TR_UART; index++) | |
| 447 uart_parameter[index].base_address = base_address[index]; | |
| 448 | |
| 449 uart = &(uart_parameter[uart_id]); | |
| 450 | |
| 451 /* | |
| 452 * Mask all interrupts causes and disable sleep mode. | |
| 453 */ | |
| 454 | |
| 455 WRITE_UART_REGISTER (uart, IER, 0x00); | |
| 456 | |
| 457 /* | |
| 458 * Reset UART mode configuration. | |
| 459 */ | |
| 460 | |
| 461 WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE); | |
| 462 | |
| 463 /* | |
| 464 * LCR[7:0] = 0xBF to allow to access EFR | |
| 465 * EFR[4] = 1 to allow to program IER[4]. | |
| 466 */ | |
| 467 | |
| 468 WRITE_UART_REGISTER (uart, LCR, 0xBF); | |
| 469 SET_BIT (uart, EFR, ENHANCED_FEATURE_BIT); | |
| 470 WRITE_UART_REGISTER (uart, LCR, 0x83); | |
| 471 | |
| 472 /* | |
| 473 * Enable FIFO and reset them. | |
| 474 */ | |
| 475 | |
| 476 WRITE_UART_REGISTER (uart, FCR, FIFO_ENABLE | | |
| 477 RX_FIFO_RESET | | |
| 478 TX_FIFO_RESET); | |
| 479 | |
| 480 /* | |
| 481 * Program the baud generator (dummy 115200). | |
| 482 */ | |
| 483 | |
| 484 WRITE_UART_REGISTER (uart, DLL, 0x07); | |
| 485 WRITE_UART_REGISTER (uart, DLM, 0x00); | |
| 486 | |
| 487 /* | |
| 488 * LCR[7] = 0 to allow to access IER and RHR - normal mode. | |
| 489 */ | |
| 490 | |
| 491 RESET_BIT (uart, LCR, DIV_EN_BIT); | |
| 492 | |
| 493 /* | |
| 494 * Select UART mode. | |
| 495 */ | |
| 496 | |
| 497 WRITE_UART_REGISTER (uart, MDR1, UART_MODE); | |
| 498 | |
| 499 /* | |
| 500 * Clear Interrupt and check that Rx FIFO is empty. | |
| 501 */ | |
| 502 | |
| 503 dummy = READ_UART_REGISTER (uart, IIR); | |
| 504 | |
| 505 while (READ_UART_REGISTER (uart, LSR) & DR) | |
| 506 dummy = READ_UART_REGISTER (uart, RHR); | |
| 507 | |
| 508 #if ((CHIPSET != 5) && (CHIPSET != 6)) | |
| 509 /* | |
| 510 * Enable sleep mode. | |
| 511 */ | |
| 512 | |
| 513 WRITE_UART_REGISTER (uart, IER, IER_SLEEP); | |
| 514 #endif | |
| 515 } | |
| 516 | |
| 517 | |
| 518 /******************************************************************************* | |
| 519 * | |
| 520 * UA_Init | |
| 521 * | |
| 522 * Purpose : Initializes the module and the UART. | |
| 523 * | |
| 524 * Arguments: In : uart_id : UART id. | |
| 525 * baudrate: baud rate selected. | |
| 526 * callback: user's function called characters are received. | |
| 527 * Out: none | |
| 528 * | |
| 529 * Returns: none | |
| 530 * | |
| 531 * Warning: Parameters are not verified. | |
| 532 * | |
| 533 ******************************************************************************/ | |
| 534 | |
| 535 void | |
| 536 UA_Init (T_tr_UartId uart_id, | |
| 537 T_tr_Baudrate baudrate, | |
| 538 void (callback_function (void))) | |
| 539 { | |
| 540 t_uart *uart; | |
| 541 int index; | |
| 542 | |
| 543 #ifdef UART_RX_BUFFER_DUMP | |
| 544 uart_rx_buffer_dump.rx_in = uart_rx_buffer_dump.rx_buffer; | |
| 545 #endif | |
| 546 | |
| 547 for (index = 0; index < NUMBER_OF_TR_UART; index++) | |
| 548 uart_parameter[index].base_address = base_address[index]; | |
| 549 | |
| 550 uart = &(uart_parameter[uart_id]); | |
| 551 | |
| 552 uart->rx_in = &(uart->rx_buffer[0]); | |
| 553 uart->rx_out = &(uart->rx_buffer[0]); | |
| 554 | |
| 555 uart->callback_function = callback_function; | |
| 556 | |
| 557 uart->framing_error = 0; | |
| 558 uart->parity_error = 0; | |
| 559 uart->overrun_error = 0; | |
| 560 | |
| 561 uart->dle_detected = 0; | |
| 562 uart->inframe = 0; | |
| 563 uart->encapsulation_flag = 0; | |
| 564 uart->frame_length = 0; | |
| 565 | |
| 566 /* | |
| 567 * Mask all interrupts causes and disable sleep mode. | |
| 568 */ | |
| 569 | |
| 570 WRITE_UART_REGISTER (uart, IER, 0x00); | |
| 571 | |
| 572 /* | |
| 573 * Reset UART mode configuration. | |
| 574 */ | |
| 575 | |
| 576 WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE | | |
| 577 IR_SLEEP_DISABLED | | |
| 578 SIR_TX_WITHOUT_ACREG2 | | |
| 579 FRAME_LENGTH_METHOD); | |
| 580 | |
| 581 /* | |
| 582 * FIFO configuration. | |
| 583 * EFR[4] = 1 to allow to program FCR[5:4] and MCR[7:5]. | |
| 584 */ | |
| 585 | |
| 586 WRITE_UART_REGISTER (uart, LCR, 0xBF); | |
| 587 SET_BIT (uart, EFR, ENHANCED_FEATURE_BIT); | |
| 588 | |
| 589 /* | |
| 590 * Select the word length, the number of stop bits , the parity and set | |
| 591 * LCR[7] (DLAB) to allow to program FCR, DLL and DLM. | |
| 592 */ | |
| 593 | |
| 594 WRITE_UART_REGISTER (uart, LCR, WLS_8 | DLAB); | |
| 595 | |
| 596 /* | |
| 597 * Program the trigger levels. | |
| 598 * MCR[6] must be set to 1. | |
| 599 */ | |
| 600 | |
| 601 SET_BIT (uart, MCR, TCR_TLR_BIT); | |
| 602 WRITE_UART_REGISTER (uart, TCR, 0x0F); | |
| 603 WRITE_UART_REGISTER ( | |
| 604 uart, TLR, RX_FIFO_TRIGGER_LEVEL); | |
| 605 | |
| 606 /* | |
| 607 * Program the FIFO control register. Bit 0 must be set when other FCR bits | |
| 608 * are written to or they are not programmed. | |
| 609 * FCR is a write-only register. It will not be modified. | |
| 610 */ | |
| 611 | |
| 612 WRITE_UART_REGISTER (uart, FCR, FIFO_ENABLE | | |
| 613 RX_FIFO_RESET | /* self cleared */ | |
| 614 TX_FIFO_RESET); /* self cleared */ | |
| 615 | |
| 616 /* | |
| 617 * Program the baud generator. | |
| 618 */ | |
| 619 | |
| 620 WRITE_UART_REGISTER (uart, DLL, dll[baudrate]); | |
| 621 WRITE_UART_REGISTER (uart, DLM, dlh[baudrate]); | |
| 622 | |
| 623 | |
| 624 /* | |
| 625 * Reset LCR[7] (DLAB) to have access to the RBR, THR and IER registers. | |
| 626 */ | |
| 627 | |
| 628 WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB); | |
| 629 | |
| 630 | |
| 631 /* | |
| 632 * Select UART mode. | |
| 633 */ | |
| 634 | |
| 635 WRITE_UART_REGISTER (uart, MDR1, UART_MODE | | |
| 636 IR_SLEEP_DISABLED | | |
| 637 SIR_TX_WITHOUT_ACREG2 | | |
| 638 FRAME_LENGTH_METHOD); | |
| 639 | |
| 640 #if ((CHIPSET == 5) || (CHIPSET == 6)) | |
| 641 /* | |
| 642 * Unmask RX interrupt | |
| 643 */ | |
| 644 | |
| 645 WRITE_UART_REGISTER (uart, IER, ERBI); | |
| 646 #else | |
| 647 /* | |
| 648 * Unmask RX interrupt and allow sleep mode. | |
| 649 */ | |
| 650 | |
| 651 WRITE_UART_REGISTER (uart, IER, ERBI | IER_SLEEP); | |
| 652 #endif | |
| 653 } | |
| 654 | |
| 655 /******************************************************************************* | |
| 656 * | |
| 657 * UA_ReadNChars | |
| 658 * | |
| 659 * Purpose : Reads N characters from the RX buffer. | |
| 660 * | |
| 661 * Arguments: In : uart_id : UART id. | |
| 662 * buffer : buffer address where the characters are | |
| 663 * copied. | |
| 664 * chars_to_read: number of characters to read. | |
| 665 * Out: none | |
| 666 * | |
| 667 * Returns : The number of characters read. | |
| 668 * | |
| 669 * Warning: Parameters are not verified. | |
| 670 * | |
| 671 ******************************************************************************/ | |
| 672 | |
| 673 SYS_UWORD32 | |
| 674 UA_ReadNChars (T_tr_UartId uart_id, | |
| 675 char *buffer, | |
| 676 SYS_UWORD32 chars_to_read) | |
| 677 { | |
| 678 SYS_UWORD32 chars_in_rx_buffer; | |
| 679 SYS_UWORD32 chars_to_copy; | |
| 680 SYS_UWORD32 chars_written; | |
| 681 char *rx_in; | |
| 682 t_uart *uart; | |
| 683 | |
| 684 uart = &(uart_parameter[uart_id]); | |
| 685 | |
| 686 /* | |
| 687 * A copy of the rx_in pointer is used because it may be updated by | |
| 688 * the interrupt handler. | |
| 689 * Get the number of bytes available in the RX buffer. | |
| 690 */ | |
| 691 | |
| 692 rx_in = uart->rx_in; | |
| 693 | |
| 694 if (uart->rx_out <= rx_in) | |
| 695 chars_in_rx_buffer = (SYS_UWORD32) (rx_in - uart->rx_out); | |
| 696 else | |
| 697 chars_in_rx_buffer = (SYS_UWORD32) (rx_in - uart->rx_out + BUFFER_SIZE + 1); | |
| 698 | |
| 699 /* | |
| 700 * No more bytes than those received may be written in the output buffer. | |
| 701 */ | |
| 702 | |
| 703 if (chars_in_rx_buffer >= chars_to_read) | |
| 704 chars_to_copy = chars_to_read; | |
| 705 else | |
| 706 chars_to_copy = chars_in_rx_buffer; | |
| 707 | |
| 708 chars_written = chars_to_copy; | |
| 709 | |
| 710 /* | |
| 711 * Write the received bytes in the output buffer. | |
| 712 */ | |
| 713 | |
| 714 while (chars_to_copy) { | |
| 715 | |
| 716 *(buffer++) = *(uart->rx_out++); | |
| 717 chars_to_copy--; | |
| 718 | |
| 719 if (uart->rx_out == &(uart->rx_buffer[0]) + BUFFER_SIZE + 1) | |
| 720 uart->rx_out = &(uart->rx_buffer[0]); | |
| 721 } | |
| 722 | |
| 723 return (chars_written); | |
| 724 } | |
| 725 | |
| 726 /******************************************************************************* | |
| 727 * | |
| 728 * UA_ReadNBytes | |
| 729 * | |
| 730 * Purpose : Reads and destuff N bytes from the RX buffer. | |
| 731 * | |
| 732 * Arguments: In : uart_id : UART id. | |
| 733 * buffer : buffer address where the bytes are copied. | |
| 734 * chars_to_read: number of bytes to read. | |
| 735 * Out: eof_detected : indicates if an EOF has been detected. Possible | |
| 736 * values are: | |
| 737 * - 0: EOF not detected, | |
| 738 * - 1: EOF detected and no more bytes left, | |
| 739 * - 2: EOF not detected and more bytes left. | |
| 740 * Users must invoke this function one more | |
| 741 * time in order to get those remaining | |
| 742 * bytes, | |
| 743 * - 3: EOF detected and more bytes left. Users | |
| 744 * must invoke this function one more time | |
| 745 * in order to get those remaining bytes. | |
| 746 * | |
| 747 * Returns : The number of bytes read. | |
| 748 * | |
| 749 * Warning: Parameters are not verified. | |
| 750 * | |
| 751 ******************************************************************************/ | |
| 752 | |
| 753 SYS_UWORD32 | |
| 754 UA_ReadNBytes (T_tr_UartId uart_id, | |
| 755 char *buffer_p, | |
| 756 SYS_UWORD32 bytes_to_read, | |
| 757 SYS_BOOL *eof_detected_p) | |
| 758 { | |
| 759 SYS_UWORD32 bytes_written; | |
| 760 SYS_UWORD32 bytes_in_rx_buffer; | |
| 761 SYS_UWORD32 bytes_to_process; | |
| 762 t_uart *uart_p; | |
| 763 char *rx_in_p; | |
| 764 | |
| 765 bytes_written = 0; | |
| 766 uart_p = &(uart_parameter[uart_id]); | |
| 767 | |
| 768 /* | |
| 769 * A copy of the rx_in pointer is used because it may be updated by | |
| 770 * the interrupt handler. | |
| 771 * Get the number of bytes available in the RX buffer. | |
| 772 */ | |
| 773 | |
| 774 rx_in_p = uart_p->rx_in; | |
| 775 | |
| 776 if (uart_p->rx_out <= rx_in_p) | |
| 777 bytes_in_rx_buffer = (SYS_UWORD32) (rx_in_p - uart_p->rx_out); | |
| 778 else | |
| 779 bytes_in_rx_buffer = (SYS_UWORD32) (rx_in_p - uart_p->rx_out + BUFFER_SIZE + 1); | |
| 780 | |
| 781 /* | |
| 782 * No more bytes than those received may be processed and then written | |
| 783 * in the output buffer. | |
| 784 */ | |
| 785 | |
| 786 if (bytes_in_rx_buffer > bytes_to_read) { | |
| 787 bytes_to_process = bytes_to_read; | |
| 788 | |
| 789 /* | |
| 790 * More bytes left. Users must invoke this function one more time | |
| 791 * in order to get those remaining bytes. | |
| 792 */ | |
| 793 | |
| 794 *eof_detected_p = 2; | |
| 795 } | |
| 796 else { | |
| 797 bytes_to_process = bytes_in_rx_buffer; | |
| 798 | |
| 799 /* | |
| 800 * No more bytes left. | |
| 801 */ | |
| 802 | |
| 803 *eof_detected_p = 0; | |
| 804 } | |
| 805 | |
| 806 /* | |
| 807 * Perform the byte destuffing and then write the "valid" received bytes in | |
| 808 * the output buffer. | |
| 809 */ | |
| 810 | |
| 811 while ((bytes_to_process) && !(*eof_detected_p & 0x01)) { | |
| 812 | |
| 813 switch (*(uart_p->rx_out)) { | |
| 814 | |
| 815 /* | |
| 816 * Current byte is DLE. | |
| 817 */ | |
| 818 | |
| 819 case DLE: | |
| 820 | |
| 821 if (!uart_p->dle_detected) { | |
| 822 | |
| 823 /* | |
| 824 * No DLE previously detected => | |
| 825 * Skip the current byte and set the flag. | |
| 826 */ | |
| 827 | |
| 828 uart_p->dle_detected = 1; | |
| 829 uart_p->rx_out++; | |
| 830 } | |
| 831 | |
| 832 else { /* if (uart_p->dle_detected) */ | |
| 833 | |
| 834 if (uart_p->inframe) { | |
| 835 | |
| 836 /* | |
| 837 * DLE previously detected AND currently inside of a frame => | |
| 838 * Copy the current byte in the output buffer, reset the flag | |
| 839 * and increase the frame length. | |
| 840 */ | |
| 841 | |
| 842 uart_p->dle_detected = 0; | |
| 843 uart_p->frame_length++; | |
| 844 *(buffer_p++) = *(uart_p->rx_out++); | |
| 845 bytes_written++; | |
| 846 } | |
| 847 | |
| 848 else { /* if (!uart_p->inframe) */ | |
| 849 | |
| 850 /* | |
| 851 * DLE previously detected AND currently outside of a frame => | |
| 852 * Skip the current byte. | |
| 853 */ | |
| 854 | |
| 855 uart_p->rx_out++; | |
| 856 } | |
| 857 } | |
| 858 | |
| 859 break; /* case DLE */ | |
| 860 | |
| 861 /* | |
| 862 * Current byte is STX. | |
| 863 */ | |
| 864 | |
| 865 case STX: | |
| 866 | |
| 867 if ((!uart_p->dle_detected) && (uart_p->inframe)) { | |
| 868 | |
| 869 /* | |
| 870 * No DLE previously detected AND currently inside of a frame. | |
| 871 */ | |
| 872 | |
| 873 if (uart_p->frame_length) { | |
| 874 | |
| 875 /* | |
| 876 * Frame length is not zero (End of Frame) => | |
| 877 * Skip the current byte and set the flags (EOF). | |
| 878 */ | |
| 879 | |
| 880 uart_p->inframe = 0; | |
| 881 uart_p->frame_length = 0; | |
| 882 uart_p->rx_out++; | |
| 883 | |
| 884 /* | |
| 885 * More bytes left. | |
| 886 */ | |
| 887 | |
| 888 if ((*eof_detected_p == 0) && (bytes_to_process)) | |
| 889 *eof_detected_p = 2; | |
| 890 | |
| 891 /* | |
| 892 * EOF detected. | |
| 893 */ | |
| 894 | |
| 895 (*eof_detected_p)++; | |
| 896 } | |
| 897 | |
| 898 else { /* if (!uart_p->frame_length) */ | |
| 899 | |
| 900 /* | |
| 901 * Frame length is zero (STX followed by another STX = | |
| 902 * Synchro lost but start of a new frame) => | |
| 903 * Skip the current byte and keep the flag set. | |
| 904 */ | |
| 905 | |
| 906 uart_p->rx_out++; | |
| 907 } | |
| 908 } | |
| 909 | |
| 910 else if ((!uart_p->dle_detected) && (!uart_p->inframe)) { | |
| 911 | |
| 912 /* | |
| 913 * No DLE previously detected AND currently outside of a | |
| 914 * frame (Start of Frame) => | |
| 915 * Skip the current byte and set the flag. | |
| 916 */ | |
| 917 | |
| 918 uart_p->inframe = 1; | |
| 919 uart_p->rx_out++; | |
| 920 } | |
| 921 | |
| 922 else if ((uart_p->dle_detected) && (uart_p->inframe)) { | |
| 923 | |
| 924 /* | |
| 925 * DLE previously detected AND currently inside of a frame => | |
| 926 * Copy the current byte in the output buffer, reset the flag | |
| 927 * and increase the frame length. | |
| 928 */ | |
| 929 | |
| 930 uart_p->dle_detected = 0; | |
| 931 uart_p->frame_length++; | |
| 932 *(buffer_p++) = *(uart_p->rx_out++); | |
| 933 bytes_written++; | |
| 934 } | |
| 935 | |
| 936 else if ((uart_p->dle_detected) && (!uart_p->inframe)) { | |
| 937 | |
| 938 /* | |
| 939 * DLE previously detected AND currently outside of a frame => | |
| 940 * Skip the current byte and reset the flag. | |
| 941 */ | |
| 942 | |
| 943 uart_p->dle_detected = 0; | |
| 944 uart_p->rx_out++; | |
| 945 } | |
| 946 | |
| 947 break; /* case STX */ | |
| 948 | |
| 949 /* | |
| 950 * Current byte is neither DLE nor STX. | |
| 951 */ | |
| 952 | |
| 953 default: | |
| 954 | |
| 955 if (uart_p->inframe) { | |
| 956 | |
| 957 /* | |
| 958 * Currently inside of a frame => | |
| 959 * Copy the current byte in the output buffer and increase | |
| 960 * the frame length. | |
| 961 */ | |
| 962 | |
| 963 uart_p->frame_length++; | |
| 964 *(buffer_p++) = *(uart_p->rx_out++); | |
| 965 bytes_written++; | |
| 966 } | |
| 967 | |
| 968 else { /* if (!uart_p->inframe) */ | |
| 969 | |
| 970 /* | |
| 971 * Currently outside of a frame => | |
| 972 * Skip the current byte. | |
| 973 */ | |
| 974 | |
| 975 uart_p->rx_out++; | |
| 976 } | |
| 977 | |
| 978 break; /* default */ | |
| 979 } | |
| 980 | |
| 981 if (uart_p->rx_out == &(uart_p->rx_buffer[0]) + BUFFER_SIZE + 1) | |
| 982 uart_p->rx_out = &(uart_p->rx_buffer[0]); | |
| 983 | |
| 984 bytes_to_process--; | |
| 985 } | |
| 986 | |
| 987 return (bytes_written); | |
| 988 } | |
| 989 | |
| 990 | |
| 991 /******************************************************************************* | |
| 992 * | |
| 993 * UA_WriteNChars | |
| 994 * | |
| 995 * Purpose : Writes N characters in the TX FIFO. | |
| 996 * | |
| 997 * Arguments: In : uart_id : UART id. | |
| 998 * buffer : buffer address from which characters are | |
| 999 * written. | |
| 1000 * bytes_to_write: number of bytes to write. | |
| 1001 * Out: none | |
| 1002 * | |
| 1003 * Returns : Number of bytes written. | |
| 1004 * | |
| 1005 * Warning: Parameters are not verified. | |
| 1006 * | |
| 1007 ******************************************************************************/ | |
| 1008 | |
| 1009 SYS_UWORD32 | |
| 1010 UA_WriteNChars (T_tr_UartId uart_id, | |
| 1011 char *buffer, | |
| 1012 SYS_UWORD32 chars_to_write) | |
| 1013 { | |
| 1014 SYS_UWORD32 chars_in_tx_fifo; | |
| 1015 SYS_UWORD32 chars_written; | |
| 1016 t_uart *uart; | |
| 1017 | |
| 1018 chars_written = 0; | |
| 1019 uart = &(uart_parameter[uart_id]); | |
| 1020 | |
| 1021 #if ((CHIPSET != 5) && (CHIPSET != 6)) | |
| 1022 /* | |
| 1023 * Disable sleep mode. | |
| 1024 */ | |
| 1025 | |
| 1026 WRITE_UART_REGISTER ( | |
| 1027 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); | |
| 1028 #endif | |
| 1029 | |
| 1030 /* | |
| 1031 * Copy the input buffer to the TX FIFO. | |
| 1032 * Ulyssse Bug #44: TX FIFO full status bit (SSR[1]) is corrupted during | |
| 1033 * one period of Bclock => Workaround S/W. | |
| 1034 * Write in TX FIFO only if FIFO is empty instead of writing in TX FIFO | |
| 1035 * while FIFO is not full. | |
| 1036 */ | |
| 1037 | |
| 1038 if (READ_UART_REGISTER (uart, LSR) & THRE) { | |
| 1039 | |
| 1040 chars_in_tx_fifo = 0; | |
| 1041 | |
| 1042 while ((chars_written < chars_to_write) && | |
| 1043 (chars_in_tx_fifo < FIFO_SIZE)) { | |
| 1044 | |
| 1045 WRITE_UART_REGISTER (uart, THR, *(buffer++)); | |
| 1046 chars_written++; | |
| 1047 chars_in_tx_fifo++; | |
| 1048 } | |
| 1049 } | |
| 1050 | |
| 1051 #if ((CHIPSET != 5) && (CHIPSET != 6)) | |
| 1052 /* | |
| 1053 * Re-enable sleep mode. | |
| 1054 */ | |
| 1055 | |
| 1056 WRITE_UART_REGISTER ( | |
| 1057 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP); | |
| 1058 #endif | |
| 1059 | |
| 1060 return (chars_written); | |
| 1061 } | |
| 1062 | |
| 1063 | |
| 1064 /******************************************************************************* | |
| 1065 * | |
| 1066 * UA_EncapsulateNChars | |
| 1067 * | |
| 1068 * Purpose : Writes N characters in the TX FIFO in encapsulating them with 2 | |
| 1069 * STX bytes (one at the beginning and one at the end). | |
| 1070 * | |
| 1071 * Arguments: In : uart_id : UART id. | |
| 1072 * buffer : buffer address from which characters are | |
| 1073 * written. | |
| 1074 * chars_to_write: number of chars to write. | |
| 1075 * Out: none | |
| 1076 * | |
| 1077 * Returns : Number of chars written. | |
| 1078 * | |
| 1079 * Warning: Parameters are not verified. | |
| 1080 * | |
| 1081 ******************************************************************************/ | |
| 1082 | |
| 1083 SYS_UWORD32 | |
| 1084 UA_EncapsulateNChars (T_tr_UartId uart_id, | |
| 1085 char *buffer, | |
| 1086 SYS_UWORD32 chars_to_write) | |
| 1087 { | |
| 1088 SYS_UWORD32 chars_written; | |
| 1089 SYS_UWORD32 chars_in_tx_fifo; | |
| 1090 t_uart *uart; | |
| 1091 | |
| 1092 chars_written = 0; | |
| 1093 uart = &(uart_parameter[uart_id]); | |
| 1094 | |
| 1095 #if ((CHIPSET != 5) && (CHIPSET != 6)) | |
| 1096 /* | |
| 1097 * Disable sleep mode. | |
| 1098 */ | |
| 1099 | |
| 1100 WRITE_UART_REGISTER ( | |
| 1101 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); | |
| 1102 #endif | |
| 1103 | |
| 1104 /* | |
| 1105 * Copy the input buffer to the TX FIFO. | |
| 1106 * Ulyssse Bug #44: TX FIFO full status bit (SSR[1]) is corrupted during | |
| 1107 * one period of Bclock => Workaround S/W. | |
| 1108 * Write in TX FIFO only if FIFO is empty instead of writing in TX FIFO | |
| 1109 * while FIFO is not full. | |
| 1110 */ | |
| 1111 | |
| 1112 if (READ_UART_REGISTER (uart, LSR) & THRE) { | |
| 1113 | |
| 1114 chars_in_tx_fifo = 0; | |
| 1115 | |
| 1116 /* | |
| 1117 * Check if the message has been already encapsulated. | |
| 1118 */ | |
| 1119 | |
| 1120 if (!uart->encapsulation_flag) { | |
| 1121 /* | |
| 1122 * Write STX in the TX FIFO and set the flag. | |
| 1123 */ | |
| 1124 | |
| 1125 WRITE_UART_REGISTER (uart, THR, STX); | |
| 1126 chars_in_tx_fifo++; | |
| 1127 uart->encapsulation_flag = 1; | |
| 1128 } | |
| 1129 | |
| 1130 /* | |
| 1131 * Keep one char margin in the TX FIFO for the last STX. | |
| 1132 */ | |
| 1133 | |
| 1134 while ((chars_written < chars_to_write) && | |
| 1135 (chars_in_tx_fifo < (FIFO_SIZE-1))) { | |
| 1136 | |
| 1137 WRITE_UART_REGISTER (uart, THR, *(buffer++)); | |
| 1138 chars_written++; | |
| 1139 chars_in_tx_fifo++; | |
| 1140 } | |
| 1141 | |
| 1142 /* | |
| 1143 * Append STX byte at the end if the frame is complete. | |
| 1144 */ | |
| 1145 | |
| 1146 if (chars_written == chars_to_write) { | |
| 1147 | |
| 1148 /* | |
| 1149 * Write STX in the TX FIFO and reset the flag. | |
| 1150 */ | |
| 1151 | |
| 1152 WRITE_UART_REGISTER (uart, THR, STX); | |
| 1153 uart->encapsulation_flag = 0; | |
| 1154 } | |
| 1155 } | |
| 1156 | |
| 1157 #if ((CHIPSET != 5) && (CHIPSET != 6)) | |
| 1158 /* | |
| 1159 * Re-enable sleep mode. | |
| 1160 */ | |
| 1161 | |
| 1162 WRITE_UART_REGISTER ( | |
| 1163 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP); | |
| 1164 #endif | |
| 1165 | |
| 1166 return (chars_written); | |
| 1167 } | |
| 1168 | |
| 1169 | |
| 1170 /******************************************************************************* | |
| 1171 * | |
| 1172 * UA_WriteNBytes | |
| 1173 * | |
| 1174 * Purpose : Writes N bytes in the TX FIFO in encapsulating with 2 STX bytes | |
| 1175 * at the beginning and the end of the frame, and in making byte | |
| 1176 * stuffing. | |
| 1177 * | |
| 1178 * Arguments: In : uart_id : UART id. | |
| 1179 * buffer : buffer address from which bytes are | |
| 1180 * written. | |
| 1181 * bytes_to_write: number of bytes to write. | |
| 1182 * Out: none | |
| 1183 * | |
| 1184 * Returns : Number of bytes written. | |
| 1185 * | |
| 1186 * Warning: Parameters are not verified. | |
| 1187 * | |
| 1188 ******************************************************************************/ | |
| 1189 | |
| 1190 SYS_UWORD32 | |
| 1191 UA_WriteNBytes (T_tr_UartId uart_id, | |
| 1192 SYS_UWORD8 *buffer, | |
| 1193 SYS_UWORD32 bytes_to_write) | |
| 1194 { | |
| 1195 SYS_UWORD32 bytes_written; | |
| 1196 SYS_UWORD32 bytes_in_tx_fifo; | |
| 1197 t_uart *uart; | |
| 1198 | |
| 1199 bytes_written = 0; | |
| 1200 uart = &(uart_parameter[uart_id]); | |
| 1201 | |
| 1202 #if ((CHIPSET != 5) && (CHIPSET != 6)) | |
| 1203 /* | |
| 1204 * Disable sleep mode. | |
| 1205 */ | |
| 1206 | |
| 1207 WRITE_UART_REGISTER ( | |
| 1208 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); | |
| 1209 #endif | |
| 1210 | |
| 1211 /* | |
| 1212 * Copy the input buffer to the TX FIFO. | |
| 1213 * Ulyssse Bug #44: TX FIFO full status bit (SSR[1]) is corrupted during | |
| 1214 * one period of Bclock => Workaround S/W. | |
| 1215 * Write in TX FIFO only if FIFO is empty instead of writing in TX FIFO | |
| 1216 * while FIFO is not full. | |
| 1217 */ | |
| 1218 | |
| 1219 if (READ_UART_REGISTER (uart, LSR) & THRE) { | |
| 1220 | |
| 1221 bytes_in_tx_fifo = 0; | |
| 1222 | |
| 1223 /* | |
| 1224 * Check if the message has been already encapsulated. | |
| 1225 */ | |
| 1226 | |
| 1227 if (!uart->encapsulation_flag) { | |
| 1228 | |
| 1229 /* | |
| 1230 * Write STX in the TX FIFO and set the flag. | |
| 1231 */ | |
| 1232 | |
| 1233 WRITE_UART_REGISTER (uart, THR, STX); | |
| 1234 bytes_in_tx_fifo++; | |
| 1235 uart->encapsulation_flag = 1; | |
| 1236 } | |
| 1237 | |
| 1238 /* | |
| 1239 * Keep 2 chars margin in the FIFO, one for the stuffing (if necessary) | |
| 1240 * and one for the last STX. | |
| 1241 */ | |
| 1242 | |
| 1243 while ((bytes_written < bytes_to_write) && | |
| 1244 (bytes_in_tx_fifo < (FIFO_SIZE-2))) { | |
| 1245 | |
| 1246 /* | |
| 1247 * Check for STX or DLE in order to perform the stuffing. | |
| 1248 */ | |
| 1249 | |
| 1250 if ((*(buffer) == STX) || (*(buffer) == DLE)) { | |
| 1251 | |
| 1252 /* | |
| 1253 * Write DLE in the TX FIFO. | |
| 1254 */ | |
| 1255 | |
| 1256 WRITE_UART_REGISTER (uart, THR, DLE); | |
| 1257 bytes_in_tx_fifo++; | |
| 1258 } | |
| 1259 | |
| 1260 WRITE_UART_REGISTER (uart, THR, *(buffer++)); | |
| 1261 bytes_written++; | |
| 1262 bytes_in_tx_fifo++; | |
| 1263 } | |
| 1264 | |
| 1265 /* | |
| 1266 * Append STX byte at the end if the frame is complete. | |
| 1267 */ | |
| 1268 | |
| 1269 if (bytes_written == bytes_to_write) { | |
| 1270 | |
| 1271 /* | |
| 1272 * Write STX in the TX FIFO and reset the flag. | |
| 1273 */ | |
| 1274 | |
| 1275 WRITE_UART_REGISTER (uart, THR, STX); | |
| 1276 uart->encapsulation_flag = 0; | |
| 1277 } | |
| 1278 } | |
| 1279 | |
| 1280 #if ((CHIPSET != 5) && (CHIPSET != 6)) | |
| 1281 /* | |
| 1282 * Re-enable sleep mode. | |
| 1283 */ | |
| 1284 | |
| 1285 WRITE_UART_REGISTER ( | |
| 1286 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP); | |
| 1287 #endif | |
| 1288 | |
| 1289 return (bytes_written); | |
| 1290 } | |
| 1291 | |
| 1292 | |
| 1293 /******************************************************************************* | |
| 1294 * | |
| 1295 * UA_WriteChar | |
| 1296 * | |
| 1297 * Purpose : Writes a character in the TX FIFO. | |
| 1298 * | |
| 1299 * Arguments: In : uart: UART id. | |
| 1300 * character | |
| 1301 * Out: none | |
| 1302 * | |
| 1303 * Returns : none | |
| 1304 * | |
| 1305 * Warning: Parameters are not verified. | |
| 1306 * | |
| 1307 ******************************************************************************/ | |
| 1308 | |
| 1309 void | |
| 1310 UA_WriteChar (T_tr_UartId uart_id, | |
| 1311 char character) | |
| 1312 { | |
| 1313 (void) UA_WriteNChars (uart_id, &character, 1); | |
| 1314 } | |
| 1315 | |
| 1316 /******************************************************************************* | |
| 1317 * | |
| 1318 * UA_WriteString | |
| 1319 * | |
| 1320 * Purpose : Writes a null terminated string in the TX FIFO. | |
| 1321 * | |
| 1322 * Arguments: In : uart_id: UART id. | |
| 1323 * buffer : buffer address from which characters are written. | |
| 1324 * Out: none | |
| 1325 * | |
| 1326 * Returns : none | |
| 1327 * | |
| 1328 * Warning: Parameters are not verified. | |
| 1329 * | |
| 1330 ******************************************************************************/ | |
| 1331 | |
| 1332 void | |
| 1333 UA_WriteString (T_tr_UartId uart_id, | |
| 1334 char *buffer) | |
| 1335 { | |
| 1336 (void) UA_WriteNChars (uart_id, buffer, strlen (buffer)); | |
| 1337 } | |
| 1338 | |
| 1339 /******************************************************************************* | |
| 1340 * | |
| 1341 * UA_EnterSleep | |
| 1342 * | |
| 1343 * Purpose : Checks if UART is ready to enter Deep Sleep. If ready, enables | |
| 1344 * wake-up interrupt. | |
| 1345 * | |
| 1346 * Arguments: In : uart_id : UART id. | |
| 1347 * Out: none | |
| 1348 * | |
| 1349 * Returns: 0 : Deep Sleep is not possible. | |
| 1350 * >= 1 : Deep Sleep is possible. | |
| 1351 * | |
| 1352 * Warning: Parameters are not verified. | |
| 1353 * | |
| 1354 ******************************************************************************/ | |
| 1355 | |
| 1356 SYS_BOOL | |
| 1357 UA_EnterSleep (T_tr_UartId uart_id) | |
| 1358 { | |
| 1359 t_uart *uart; | |
| 1360 SYS_BOOL deep_sleep; | |
| 1361 volatile SYS_UWORD8 status; | |
| 1362 | |
| 1363 uart = &(uart_parameter[uart_id]); | |
| 1364 deep_sleep = 0; | |
| 1365 | |
| 1366 /* | |
| 1367 * Check if RX & TX FIFOs are both empty | |
| 1368 */ | |
| 1369 | |
| 1370 status = READ_UART_REGISTER (uart, LSR); | |
| 1371 | |
| 1372 if (!(status & DR) && | |
| 1373 (status & TEMT)) { | |
| 1374 | |
| 1375 #if ((CHIPSET != 5) && (CHIPSET != 6)) | |
| 1376 /* | |
| 1377 * Disable sleep mode. | |
| 1378 */ | |
| 1379 | |
| 1380 WRITE_UART_REGISTER ( | |
| 1381 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); | |
| 1382 #endif | |
| 1383 | |
| 1384 /* | |
| 1385 * Mask RX interrupt. | |
| 1386 */ | |
| 1387 | |
| 1388 WRITE_UART_REGISTER ( | |
| 1389 uart, IER, READ_UART_REGISTER (uart, IER) & ~ERBI); | |
| 1390 | |
| 1391 /* | |
| 1392 * Enable the wake-up interrupt. | |
| 1393 */ | |
| 1394 | |
| 1395 ENABLE_WAKEUP_INTERRUPT (uart); | |
| 1396 | |
| 1397 deep_sleep = 1; | |
| 1398 } | |
| 1399 | |
| 1400 return (deep_sleep); | |
| 1401 } | |
| 1402 | |
| 1403 /******************************************************************************* | |
| 1404 * | |
| 1405 * UA_WakeUp | |
| 1406 * | |
| 1407 * Purpose : Wakes up UART after Deep Sleep. | |
| 1408 * | |
| 1409 * Arguments: In : uart_id : UART id. | |
| 1410 * Out: none | |
| 1411 * | |
| 1412 * Returns: none | |
| 1413 * | |
| 1414 * Warning: Parameters are not verified. | |
| 1415 * | |
| 1416 ******************************************************************************/ | |
| 1417 | |
| 1418 void | |
| 1419 UA_WakeUp (T_tr_UartId uart_id) | |
| 1420 { | |
| 1421 t_uart *uart; | |
| 1422 | |
| 1423 uart = &(uart_parameter[uart_id]); | |
| 1424 | |
| 1425 /* | |
| 1426 * Disable the wake-up interrupt. | |
| 1427 */ | |
| 1428 | |
| 1429 DISABLE_WAKEUP_INTERRUPT (uart); | |
| 1430 | |
| 1431 /* | |
| 1432 * Unmask RX interrupts. | |
| 1433 */ | |
| 1434 | |
| 1435 WRITE_UART_REGISTER ( | |
| 1436 uart, IER, READ_UART_REGISTER (uart, IER) | ERBI); | |
| 1437 | |
| 1438 #if ((CHIPSET != 5) && (CHIPSET != 6)) | |
| 1439 /* | |
| 1440 * Allow sleep mode. | |
| 1441 */ | |
| 1442 | |
| 1443 WRITE_UART_REGISTER ( | |
| 1444 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP); | |
| 1445 #endif | |
| 1446 } | |
| 1447 | |
| 1448 /******************************************************************************* | |
| 1449 * | |
| 1450 * UA_InterruptHandler | |
| 1451 * | |
| 1452 * Purpose : Interrupt handler. | |
| 1453 * | |
| 1454 * Arguments: In : uart_id : origin of interrupt | |
| 1455 * interrupt_status: source of interrupt | |
| 1456 * Out: none | |
| 1457 * | |
| 1458 * Returns : none | |
| 1459 * | |
| 1460 ******************************************************************************/ | |
| 1461 | |
| 1462 void | |
| 1463 UA_InterruptHandler (T_tr_UartId uart_id, | |
| 1464 SYS_UWORD8 interrupt_status) | |
| 1465 { | |
| 1466 t_uart *uart; | |
| 1467 | |
| 1468 uart = &(uart_parameter[uart_id]); | |
| 1469 | |
| 1470 switch (interrupt_status) { | |
| 1471 | |
| 1472 case RX_DATA: | |
| 1473 | |
| 1474 read_rx_fifo (uart); | |
| 1475 | |
| 1476 break; | |
| 1477 | |
| 1478 default: | |
| 1479 | |
| 1480 #ifdef UART_RX_BUFFER_DUMP | |
| 1481 uart_rx_buffer_dump.wrong_interrupt_status++; | |
| 1482 #endif | |
| 1483 | |
| 1484 /* No Processing */ | |
| 1485 | |
| 1486 break; | |
| 1487 } | |
| 1488 } |
