#define UART0_BPS 9600 #define UART0_RXBUF_SIZE 32 #define UART0_TXBUF_SIZE 32 #define UART_NO_ERR 0 #define UART_TX_EMPTY 1 extern void uart0_init (void); extern void uart0_putc (uint8_t c); extern void uart0_puts (uint8_t *pbuf, uint16_t len); extern uint8_t uart0_getc (void); typedef struct { OS_SEM rx_sem; // Rx信号量 uint16_t rx_cnt; // Rx缓冲中字符数 uint8_t *rx_pi; // 指向下一字符将被插入的位置 uint8_t *rx_po; // 指向下一字符将被提取的位置 uint8_t rx_buf[UART0_RXBUF_SIZE]; // Rx缓冲 OS_SEM tx_sem; // Tx信号量 uint16_t tx_cnt; // Tx缓冲中字符数 uint8_t *tx_pi; // 指向下一字符将被插入的位置 uint8_t *tx_po; // 指向下一字符将被提取的位置 uint8_t tx_buf[UART0_TXBUF_SIZE]; // Tx缓冲 uint8_t tx_busy; // Tx忙标志 } UART0_BUF; static UART0_BUF uart0_buf; static UART0_BUF *pbuf0 = &uart0_buf; void uart0_putrx (uint8_t c) { if (pbuf0->rx_cnt < UART0_RXBUF_SIZE) { pbuf0->rx_cnt++; *pbuf0->rx_pi++ = c; if(pbuf0->rx_pi == &pbuf0->rx_buf[UART0_RXBUF_SIZE]) { pbuf0->rx_pi = &pbuf0->rx_buf[0]; } isr_sem_send (pbuf0->rx_sem); } } uint8_t uart0_gettx (uint8_t *perr) { uint8_t c; if (pbuf0->tx_cnt > 0) { pbuf0->tx_cnt--; c = *pbuf0->tx_po++; if (pbuf0->tx_po == &pbuf0->tx_buf[UART0_TXBUF_SIZE]) { pbuf0->tx_po = &pbuf0->tx_buf[0]; } isr_sem_send (pbuf0->tx_sem); *perr = UART_NO_ERR; return (c); } else { *perr = UART_TX_EMPTY; return (0); } } void uart0_proc (void) __irq { uint8_t iir, c; uint8_t i, err; while (((iir = U0IIR) & 0x01) ==0) { switch (iir & 0x0E) { case 0x04: case 0x0C: for (i=0; i<16; i++) { if ((U0LSR & 0x01)==0) break; uart0_putrx (U0RBR); } break; case 0x02: for (i=0; i<16; i++) { c = uart0_gettx (&err); if (err == UART_NO_ERR) { U0THR = c; } else { pbuf0->tx_busy = 0; break; } } break; } } VICVectAddr = 0x00; } void uart0_init (void) { PINSEL0 &= 0xFFFFFFF0; PINSEL0 |= 0x00000005; U0LCR = 0x83; U0DLM = (FPCLK / 16) / UART0_BPS / 256; U0DLL = (FPCLK / 16) / UART0_BPS % 256; U0LCR = 0x03; U0FCR = 0x87; U0IER = 0x03; pbuf0->rx_cnt = 0; pbuf0->rx_pi = &pbuf0->rx_buf[0]; pbuf0->rx_po = &pbuf0->rx_buf[0]; os_sem_init (pbuf0->rx_sem, 0); pbuf0->tx_cnt = 0; pbuf0->tx_pi = &pbuf0->tx_buf[0]; pbuf0->tx_po = &pbuf0->tx_buf[0]; os_sem_init (pbuf0->tx_sem, UART0_TXBUF_SIZE); pbuf0->tx_busy = 0; VICVectCntl0 = 0x26; VICVectAddr0 = (uint32_t)uart0_proc; VICIntEnable|= 0x40; } uint8_t uart0_getc (void) { uint8_t c; os_sem_wait (pbuf0->rx_sem, 0xFFFF); irq_lock (); pbuf0->rx_cnt--; c = *pbuf0->rx_po++; if (pbuf0->rx_po == &pbuf0->rx_buf[UART0_RXBUF_SIZE]) { pbuf0->rx_po = &pbuf0->rx_buf[0]; } irq_unlock (); return (c); } void uart0_putc (uint8_t c) { os_sem_wait (pbuf0->tx_sem, 0xFFFF); irq_lock (); pbuf0->tx_cnt++; *pbuf0->tx_pi++ = c; if (pbuf0->tx_pi == &pbuf0->tx_buf[UART0_TXBUF_SIZE]) { pbuf0->tx_pi = &pbuf0->tx_buf[0]; } if (pbuf0->tx_busy == 0) { pbuf0->tx_busy = 1; pbuf0->tx_cnt--; c = *pbuf0->tx_po++; if (pbuf0->tx_po == &pbuf0->tx_buf[UART0_TXBUF_SIZE]) { pbuf0->tx_po = &pbuf0->tx_buf[0]; } os_sem_send (pbuf0->tx_sem); U0THR = c; } irq_unlock (); } void uart0_puts (uint8_t *pbuf, uint16_t len) { while (len--) { uart0_putc (*pbuf++); } }
|