📄 serial_se3208_2.c
字号:
#include <linux/types.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/string.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#define UART0_NAME "uart0"
#define UART0_MAJOR 206
#define UATR0_MINOR
#define USTAT_OVERRUN_ERROR_BIT 0x00000001
#define USTAT_PARITY_ERR0R_BIT 0x00000002
#define USTAT_FRAME_ERR0R_BIT 0x00000004
#define USTAT_BREAK_DETECT_BIT 0x00000008
#define USTAT_RX_EMPTY_BIT 0x00000010
#define USTAT_TX_HOLD_BIT 0x00000020
#define USTAT_TX_EMPTY_BIT 0x00000040
#define USTAT_RX_FIFO_BIT 0x00000F00
#define USTAT_TX_FIFO_BIT 0x0000F000
static DECLARE_WAIT_QUEUE_HEAD(rx_queue);
static DECLARE_WAIT_QUEUE_HEAD(tx_queue);
static devfs_handle_t devfs_handle, devfs_uart0_dir;
static char *dev_iduart0 = UART0_NAME;
#define BUFSIZE 128
#define FIFOSIZE 16
#define TIMEOUT 10
unsigned char uart0_rx_buf[BUFSIZE];
static char uart0_tx_buf[BUFSIZE];
size_t rx_buf_count, rx_user_count;
size_t tx_buf_count, tx_user_count;
static ssize_t uart0_read(struct file *filp, char *buf, size_t count, loff_t *l)
{
char *user_buf=buf;
rx_buf_count=0;
rx_user_count=count;
while(rx_user_count>0){
if (*USTAT0 & USTAT_RX_EMPTY_BIT){
uart0_rx_buf[rx_buf_count]=*URXB0;
rx_buf_count++;
}else{
interruptible_sleep_on_timeout(&rx_queue, TIMEOUT);
}
if (rx_user_count>BUFSIZE && rx_buf_count==BUFSIZE){
copy_to_user(user_buf, &uart0_rx_buf, BUFSIZE);
user_buf+=BUFSIZE;
rx_buf_count=0;
rx_user_count-=BUFSIZE;
}else if (rx_user_count==rx_buf_count){
copy_to_user(user_buf, &uart0_rx_buf, rx_user_count);
rx_user_count=0;
rx_buf_count=0;
}
}
return count;
}
static ssize_t uart0_write(struct file *filp, const char *buf, size_t count, loff_t *l)
{
char *user_buf=buf;
int i,j=0;
tx_buf_count=0;
tx_user_count=count;
while(tx_user_count>0){
if (tx_user_count>BUFSIZE){
copy_from_user(&uart0_tx_buf, user_buf, BUFSIZE);
user_buf+=BUFSIZE;
tx_buf_count=BUFSIZE;
j=0;
tx_user_count-=BUFSIZE;
}else if (tx_user_count<=BUFSIZE){
copy_from_user(&uart0_tx_buf, user_buf, tx_user_count);
tx_buf_count=tx_user_count;
j=0;
tx_user_count=0;
}
while (tx_buf_count>0){
if (tx_buf_count>FIFOSIZE){
for(i=0;i<FIFOSIZE;i++){
*UTXB0=uart0_tx_buf[j];
j++;
}
tx_buf_count-=FIFOSIZE;
}else if (tx_buf_count<=FIFOSIZE){
for(i=0;i<tx_buf_count;i++){
*UTXB0=uart0_tx_buf[j];
j++;
}
tx_buf_count-=tx_buf_count;
}
interruptible_sleep_on(&tx_queue);
}
}
return count;
}
unsigned int uart0_poll(struct file *filp, struct poll_table_struct *poll_talbe)
{
return 0;
}
static void uart0_tx(int irq, void *dev_idledflash, struct pt_regs *regs)
{
wake_up_interruptible(&tx_queue);
}
static void uart0_rx(int irq, void *dev_idledflash, struct pt_regs *regs)
{
wake_up_interruptible(&rx_queue);
}
static int uart0_open(struct inode *inode, struct file *filp)
{
int ret;
MOD_INC_USE_COUNT;
if ((ret = request_irq(IRQ_UART0RX, uart0_rx,
0, "uart0_rx", dev_iduart0)))
{
printk("uart0_rx_init: failed to register IRQ_UART0RX\n");
free_irq(IRQ_UART0RX, dev_iduart0);
return ret;
}
if((ret=request_irq(IRQ_UART0TX,uart0_tx,
0,"uart0_tx", dev_iduart0)))
{
printk("uart0_tx_init: failed to register IRQ_UART0TX\n");
free_irq(IRQ_UART0TX, dev_iduart0);
return ret;
}
disable_irq(IRQ_UART0RX);
disable_irq(IRQ_UART0TX);
*UCON0=0x0211;
// *UCON0=0x0281; /*loopback*/
// *UBDR0=0x017F; // 1843200/16/(383+1)=300
// *UBDR0=0x00BF; // 1843200/16/(191+1)=600
// *UBDR0=0x005F; // 1843200/16/(95+1)=1200
// *UBDR0=0x002F; // 1843200/16/(47+1)=2400
// *UBDR0=0x0017; // 1843200/16/(23+1)=4800
// *UBDR0=0x000B; // 1843200/16/(11+1)=9600
// *UBDR0=0x0005; // 1843200/16/(5+1)=19200
*UBDR0=0x0002; // 1843200/16/(2+1)=38400
// *UBDR0=0x0001; // 1843200/16/(1+1)=57600
// *UBDR0=0x0000; // 1843200/16/(0+1)=115200
init_waitqueue_head(&rx_queue);
init_waitqueue_head(&tx_queue);
enable_irq(IRQ_UART0RX);
enable_irq(IRQ_UART0TX);
return 0;
}
static int uart0_release(struct inode *inode, struct file *filp)
{
free_irq(IRQ_UART0TX, dev_iduart0);
free_irq(IRQ_UART0RX, dev_iduart0);
*UCON0=0x0000;
MOD_DEC_USE_COUNT;
return 0;
}
static struct file_operations uart0_fops = {
read: uart0_read,
write: uart0_write,
poll: uart0_poll,
ioctl: NULL,
open: uart0_open,
release: uart0_release,
};
int __init uart0_init(void)
{
int ret;
if ((ret=devfs_register_chrdev(UART0_MAJOR, UART0_NAME, &uart0_fops))!=0)
{
printk("registering of " UART0_NAME " is failed\n");
return ret;
}
devfs_uart0_dir = devfs_mk_dir(NULL, "uart0", NULL);
devfs_handle = devfs_register(devfs_uart0_dir, "uart0",
DEVFS_FL_DEFAULT,
UART0_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR,
&uart0_fops, NULL);
printk("uart0 initialized\n");
return 0;
}
void __exit uart0_cleanup(void)
{
devfs_unregister_chrdev(UART0_MAJOR, UART0_NAME);
printk("uart0 removed\n");
}
module_init(uart0_init);
module_exit(uart0_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -