📄 uart.c
字号:
termios_stopped_com1 = 0; } termios_tx_active_com1 = 0; termios_ttyp_com1 = ttyp; termios_tx_hold_com1 = 0; termios_tx_hold_valid_com1 = 0; } else { uart_data[uart].ioMode = p->device.outputUsesInterrupts; if(uart_data[uart].hwFlow) { val = uread(uart, MSR); termios_stopped_com2 = (val & CTS) ? 0 : 1; } else { termios_stopped_com2 = 0; } termios_tx_active_com2 = 0; termios_ttyp_com2 = ttyp; termios_tx_hold_com2 = 0; termios_tx_hold_valid_com2 = 0; } return;}intBSP_uart_termios_read_com1(int uart){ int off = (int)0; char buf[40]; /* read bytes */ while (( off < sizeof(buf) ) && ( uread(BSP_UART_COM1, LSR) & DR )) { buf[off++] = uread(BSP_UART_COM1, RBR); } /* write out data */ if ( off > 0 ) { rtems_termios_enqueue_raw_characters(termios_ttyp_com1, buf, off); } /* enable receive interrupts */ uart_data[BSP_UART_COM1].ier |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE); uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier); return ( EOF );}intBSP_uart_termios_read_com2(int uart){ int off = (int)0; char buf[40]; /* read current byte */ while (( off < sizeof(buf) ) && ( uread(BSP_UART_COM2, LSR) & DR )) { buf[off++] = uread(BSP_UART_COM2, RBR); } /* write out data */ if ( off > 0 ) { rtems_termios_enqueue_raw_characters(termios_ttyp_com2, buf, off); } /* enable receive interrupts */ uart_data[BSP_UART_COM2].ier |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE); uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier); return ( EOF );}intBSP_uart_termios_write_com1(int minor, const char *buf, int len){ assert(buf != NULL); if(len <= 0) { return 0; } /* If there TX buffer is busy - something is royally screwed up */ assert((uread(BSP_UART_COM1, LSR) & THRE) != 0); if(termios_stopped_com1) { /* CTS low */ termios_tx_hold_com1 = *buf; termios_tx_hold_valid_com1 = 1; return 0; } /* Write character */ uwrite(BSP_UART_COM1, THR, *buf & 0xff); /* Enable interrupts if necessary */ if ( !termios_tx_active_com1 ) { termios_tx_active_com1 = 1; uart_data[BSP_UART_COM1].ier |= TRANSMIT_ENABLE; uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier); } return 0;}intBSP_uart_termios_write_com2(int minor, const char *buf, int len){ assert(buf != NULL); if(len <= 0) { return 0; } /* If there TX buffer is busy - something is royally screwed up */ assert((uread(BSP_UART_COM2, LSR) & THRE) != 0); if(termios_stopped_com2) { /* CTS low */ termios_tx_hold_com2 = *buf; termios_tx_hold_valid_com2 = 1; return 0; } /* Write character */ uwrite(BSP_UART_COM2, THR, *buf & 0xff); /* Enable interrupts if necessary */ if ( !termios_tx_active_com2 ) { termios_tx_active_com2 = 1; uart_data[BSP_UART_COM2].ier |= TRANSMIT_ENABLE; uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier); } return 0;}voidBSP_uart_termios_isr_com1(void){ unsigned char buf[40]; unsigned char val; int off, ret, vect; off = 0; for(;;) { vect = uread(BSP_UART_COM1, IIR) & 0xf; switch(vect) { case MODEM_STATUS : val = uread(BSP_UART_COM1, MSR); if(uart_data[BSP_UART_COM1].hwFlow) { if(val & CTS) { /* CTS high */ termios_stopped_com1 = 0; if(termios_tx_hold_valid_com1) { termios_tx_hold_valid_com1 = 0; BSP_uart_termios_write_com1(0, &termios_tx_hold_com1, 1); } } else { /* CTS low */ termios_stopped_com1 = 1; } } break; case NO_MORE_INTR : /* No more interrupts */ if(off != 0) { /* Update rx buffer */ if( driver_input_handler_com1 ) { driver_input_handler_com1( termios_ttyp_com1, (char *)buf, off ); } else { /* Update rx buffer */ rtems_termios_enqueue_raw_characters(termios_ttyp_com1, (char *)buf, off ); } } return; case TRANSMITTER_HODING_REGISTER_EMPTY : /* * TX holding empty: we have to disable these interrupts * if there is nothing more to send. */ /* If nothing else to send disable interrupts */ ret = rtems_termios_dequeue_characters(termios_ttyp_com1, 1); if ( ret == 0 ) { termios_tx_active_com1 = 0; uart_data[BSP_UART_COM1].ier &= ~(TRANSMIT_ENABLE); uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier); } break; case RECEIVER_DATA_AVAIL : case CHARACTER_TIMEOUT_INDICATION: if ( uart_data[BSP_UART_COM1].ioMode == TERMIOS_TASK_DRIVEN ) { /* ensure interrupts are enabled */ if ( uart_data[BSP_UART_COM1].ier & RECEIVE_ENABLE ) { /* disable interrupts and notify termios */ uart_data[BSP_UART_COM1].ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE); uwrite(BSP_UART_COM1, IER, uart_data[BSP_UART_COM1].ier); rtems_termios_rxirq_occured(termios_ttyp_com1); } } else { /* RX data ready */ assert(off < sizeof(buf)); buf[off++] = uread(BSP_UART_COM1, RBR); } break; case RECEIVER_ERROR: /* RX error: eat character */ uartError(BSP_UART_COM1); break; default: /* Should not happen */ assert(0); return; } }} voidBSP_uart_termios_isr_com2(){ unsigned char buf[40]; unsigned char val; int off, ret, vect; off = 0; for(;;) { vect = uread(BSP_UART_COM2, IIR) & 0xf; switch(vect) { case MODEM_STATUS : val = uread(BSP_UART_COM2, MSR); if(uart_data[BSP_UART_COM2].hwFlow) { if(val & CTS) { /* CTS high */ termios_stopped_com2 = 0; if(termios_tx_hold_valid_com2) { termios_tx_hold_valid_com2 = 0; BSP_uart_termios_write_com2(0, &termios_tx_hold_com2, 1); } } else { /* CTS low */ termios_stopped_com2 = 1; } } break; case NO_MORE_INTR : /* No more interrupts */ if(off != 0) { /* Update rx buffer */ if( driver_input_handler_com2 ) { driver_input_handler_com2( termios_ttyp_com2, (char *)buf, off ); } else { rtems_termios_enqueue_raw_characters(termios_ttyp_com2, (char *)buf, off); } } return; case TRANSMITTER_HODING_REGISTER_EMPTY : /* * TX holding empty: we have to disable these interrupts * if there is nothing more to send. */ /* If nothing else to send disable interrupts */ ret = rtems_termios_dequeue_characters(termios_ttyp_com2, 1); if ( ret == 0 ) { termios_tx_active_com2 = 0; uart_data[BSP_UART_COM2].ier &= ~(TRANSMIT_ENABLE); uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier); } break; case RECEIVER_DATA_AVAIL : case CHARACTER_TIMEOUT_INDICATION: if ( uart_data[BSP_UART_COM2].ioMode == TERMIOS_TASK_DRIVEN ) { /* ensure interrupts are enabled */ if ( uart_data[BSP_UART_COM2].ier & RECEIVE_ENABLE ) { /* disable interrupts and notify termios */ uart_data[BSP_UART_COM2].ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE); uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier); rtems_termios_rxirq_occured(termios_ttyp_com2); } } else { /* RX data ready */ assert(off < sizeof(buf)); buf[off++] = uread(BSP_UART_COM2, RBR); } break; case RECEIVER_ERROR: /* RX error: eat character */ uartError(BSP_UART_COM2); break; default: /* Should not happen */ assert(0); return; } }} /* ================= GDB support ===================*/ static int sav[4] __attribute__ ((unused));/* * Interrupt service routine for COM1 - all, * it does it check whether ^C is received * if yes it will flip TF bit before returning * Note: it should be installed as raw interrupt * handler */asm (".p2align 4");asm (".text");asm (".globl BSP_uart_dbgisr_com1");asm ("BSP_uart_dbgisr_com1:");asm (" movl %eax, sav"); /* Save eax */asm (" movl %ebx, sav + 4"); /* Save ebx */asm (" movl %edx, sav + 8"); /* Save edx */asm (" movl $0, %ebx"); /* Clear flag *//* * We know that only receive related interrupts * are available, eat chars */asm ("uart_dbgisr_com1_1:");asm (" movw $0x3FD, %dx");asm (" inb %dx, %al"); /* Read LSR */asm (" andb $1, %al");asm (" cmpb $0, %al");asm (" je uart_dbgisr_com1_2");asm (" movw $0x3F8, %dx");asm (" inb %dx, %al"); /* Get input character */asm (" cmpb $3, %al");asm (" jne uart_dbgisr_com1_1");/* ^C received, set flag */ asm (" movl $1, %ebx");asm (" jmp uart_dbgisr_com1_1");/* All chars read */asm ("uart_dbgisr_com1_2:");/* If flag is set we have to tweak TF */asm (" cmpl $0, %ebx");asm (" je uart_dbgisr_com1_3");/* Flag is set */asm (" movl sav+4, %ebx"); /* Restore ebx */asm (" movl sav+8, %edx"); /* Restore edx *//* Set TF bit */asm (" popl %eax"); /* Pop eip */asm (" movl %eax, sav + 4"); /* Save it */asm (" popl %eax"); /* Pop cs */asm (" movl %eax, sav + 8"); /* Save it */asm (" popl %eax"); /* Pop flags */asm (" orl $0x100, %eax"); /* Modify it */asm (" pushl %eax"); /* Push it back */asm (" movl sav+8, %eax"); /* Put back cs */asm (" pushl %eax");asm (" movl sav+4, %eax"); /* Put back eip */asm (" pushl %eax");/* Acknowledge IRQ */asm (" movb $0x20, %al");asm (" outb %al, $0x20");asm (" movl sav, %eax"); /* Restore eax */asm (" iret"); /* Done *//* Flag is not set */asm("uart_dbgisr_com1_3:");asm (" movl sav+4, %ebx"); /* Restore ebx */asm (" movl sav+8, %edx"); /* Restore edx *//* Acknowledge irq */asm (" movb $0x20, %al");asm (" outb %al, $0x20");asm (" movl sav, %eax"); /* Restore eax */asm (" iret"); /* Done *//* * Interrupt service routine for COM2 - all, * it does it check whether ^C is received * if yes it will flip TF bit before returning * Note: it has to be installed as raw interrupt * handler */asm (".p2align 4");asm (".text");asm (".globl BSP_uart_dbgisr_com2");asm ("BSP_uart_dbgisr_com2:");asm (" movl %eax, sav"); /* Save eax */asm (" movl %ebx, sav + 4"); /* Save ebx */asm (" movl %edx, sav + 8"); /* Save edx */asm (" movl $0, %ebx"); /* Clear flag *//* * We know that only receive related interrupts * are available, eat chars */asm ("uart_dbgisr_com2_1:");asm (" movw $0x2FD, %dx");asm (" inb %dx, %al"); /* Read LSR */asm (" andb $1, %al");asm (" cmpb $0, %al");asm (" je uart_dbgisr_com2_2");asm (" movw $0x2F8, %dx");asm (" inb %dx, %al"); /* Get input character */asm (" cmpb $3, %al");asm (" jne uart_dbgisr_com2_1");/* ^C received, set flag */ asm (" movl $1, %ebx");asm (" jmp uart_dbgisr_com2_1");/* All chars read */asm ("uart_dbgisr_com2_2:");/* If flag is set we have to tweak TF */asm (" cmpl $0, %ebx");asm (" je uart_dbgisr_com2_3");/* Flag is set */asm (" movl sav+4, %ebx"); /* Restore ebx */asm (" movl sav+8, %edx"); /* Restore edx *//* Set TF bit */asm (" popl %eax"); /* Pop eip */asm (" movl %eax, sav + 4"); /* Save it */asm (" popl %eax"); /* Pop cs */asm (" movl %eax, sav + 8"); /* Save it */asm (" popl %eax"); /* Pop flags */asm (" orl $0x100, %eax"); /* Modify it */asm (" pushl %eax"); /* Push it back */asm (" movl sav+8, %eax"); /* Put back cs */asm (" pushl %eax");asm (" movl sav+4, %eax"); /* Put back eip */asm (" pushl %eax");/* Acknowledge IRQ */asm (" movb $0x20, %al");asm (" outb %al, $0x20");asm (" movl sav, %eax"); /* Restore eax */asm (" iret"); /* Done *//* Flag is not set */asm("uart_dbgisr_com2_3:");asm (" movl sav+4, %ebx"); /* Restore ebx */asm (" movl sav+8, %edx"); /* Restore edx *//* Acknowledge irq */asm (" movb $0x20, %al");asm (" outb %al, $0x20");asm (" movl sav, %eax"); /* Restore eax */asm (" iret"); /* Done */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -