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++);
}
}
文章评论(0条评论)
登录后参与讨论