📄 uart.c
字号:
/*
* uart.c - uart api & driver
*
* Author: li ming <admin@lumit.org>
* Date: 2008-4-16
* Copyleft: http://www.lumit.org
*/
#include "uart.h"
#include "led.h"
#include "irq.h"
/* define the relative gpio register */
#define SYSCFG 0x03FF0000
#define UART0_BASE (SYSCFG + 0xD000)
#define UART1_BASE (SYSCFG + 0xE000)
#define UART0_ULCON (*((volatile unsigned *)(UART0_BASE+0x00)))
#define UART0_UCON (*((volatile unsigned *)(UART0_BASE+0x04)))
/* Line control register bits */
#define ULCON 0x00
#define UCON 0x04
#define USTAT 0x08
#define UTXBUF 0x0C
#define URXBUF 0x10
#define UBRDIV 0x14
/* UART Control Register bits */
#define ULCR8bits (3)
#define ULCRS1StopBit (0)
#define ULCRNoParity (0)
/* UART Status Register bits */
#define USROverrun (1 << 0)
#define USRParity (1 << 1)
#define USRFraming (1 << 2)
#define USRBreak (1 << 3)
#define USRDTR (1 << 4)
#define USRRxData (1 << 5)
#define USRTxHoldEmpty (1 << 6)
#define USRTxEmpty (1 << 7)
/* default baud rate value */
#define BAUD_9600 (162 << 4)
#define BAUD_19200 (80 << 4)
#define BAUD_38400 (40 << 4)
#define BAUD_57600 (26 << 4)
#define BAUD_115200 (13 << 4)
/* UART primitives */
#define GET_STATUS(p) (*(volatile unsigned *)((p) + USTAT))
#define RX_DATA(s) ((s) & USRRxData)
#define GET_CHAR(p) (*(volatile unsigned *)((p) + URXBUF))
#define TX_READY(s) ((s) & USRTxHoldEmpty)
#define PUT_CHAR(p,c) (*(unsigned *)((p) + UTXBUF) = (unsigned )(c))
/* ************************************************************************ */
int uart0_init(void)
{
//PUT_CHAR(UART0_BASE, 0x0);
/* Set port for 8 bit, one stop, no parity */
*(volatile unsigned *)(UART0_BASE + ULCON) = ULCR8bits;
*(volatile unsigned *)(UART0_BASE + UBRDIV) = BAUD_19200;
return 0;
}
static void (*uart0_irq_hooker)(void) = 0;
static char recv_buff[1024];
static char send_buff[1024];
static int recv_data_offset = 0;
static int recv_getchar_offset = 0;
static int send_data_offset = 0;
static int send_putchar_offset = 0;
int uart0_putchar(char ch)
{
#if 0
/* read tx ready flag, when =1 break */
while ( TX_READY(GET_STATUS(UART0_BASE))==0)
;
PUT_CHAR(UART0_BASE, ch);
return 0;
#endif
/* append ch to buff */
send_buff[send_putchar_offset++] = ch;
/* enable tx interrupt */
PUT_CHAR(UART0_BASE, 0x0);
*(volatile unsigned *)(UART0_BASE + UCON) |= (0x1 << 3);
return 0;
}
char uart0_getchar(void)
{
#if 0
char ch;
while ( (RX_DATA(GET_STATUS(UART0_BASE)))==0 )
;
ch = GET_CHAR(UART0_BASE);
return ch;
#endif
if( recv_getchar_offset < recv_data_offset )
return recv_buff[recv_getchar_offset++];
return 0;
}
void uart0_install_irq_hooker( void (*hooker)(void) )
{
uart0_irq_hooker = hooker;
}
void uart0_recv_irq_handler(void)
{
/* recv the tdata */
recv_buff[recv_data_offset++] = GET_CHAR(UART0_BASE);
led_on(2);
led_off(2);
return;
}
void uart0_send_irq_handler(void)
{
if( send_data_offset < send_putchar_offset )
PUT_CHAR(UART0_BASE, send_buff[send_data_offset++]);
led_on(3);
led_off(3);
return ;
}
int uart0_enable_recv_irq(void)
{
/* register irq no.5 to a handler */
request_irq(5, uart0_recv_irq_handler);
/* set rx mode as interrupt */
*(volatile unsigned *)(UART0_BASE + UCON) |= 0x01;
/* enable rx interrupt */
*(volatile unsigned *)(UART0_BASE + UCON) |= 0x04;
return 0;
}
int uart0_enable_send_irq(void)
{
/* register irq no.4 to a handler */
request_irq(4, uart0_send_irq_handler);
/* enable tx interrupt */
*(volatile unsigned *)(UART0_BASE + UCON) |= (0x1 << 3);
return 0;
}
int uart0_test(void)
{
char ch;
uart0_init();
while(1)
{
ch = uart0_getchar();
if( ch == '\r' ) // 0x0d
{
//uart0_putchar('\r');
uart0_putchar('\n');
//continue;
}
if( ch == '\b' ) // 0x08
{
uart0_putchar('\b');
uart0_putchar(' ');
//uart0_putchar('\b');
//continue;
}
if( ch != 0 )
uart0_putchar(ch);
}
}
/* ************************************************************************ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -