原创 slump的串口驱动

2009-11-24 16:41 1587 12 12 分类: MCU/ 嵌入式
slump的串口驱动,编码风格和思想很好。贴在这里做个记录,学习哈,希望slump不要介意。
////////////////////////////////////////////////////////////////////

#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++);    
    }
}

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
12
关闭 站长推荐上一条 /3 下一条