如何開發Linux驅動程序
一般情況下都會有現成的驅動程序,不需要從零開始開發驅動程序。所以Linux驅動開發主要分為兩個步驟:1.讀得懂驅動程序;2.寫的了核心功能。
?
發送中斷處理程序
發送中斷處理函數在/drivers/serial/samsung.c的s3c24xx_serial_tx_chars
?
循環緩沖
struct circ_buf {
??? char *buf;
??? int head;
??? int tail;
};
存數據的時候移動head,取數據的時候移動tail。
static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id){ //判斷發送流控 struct s3c24xx_uart_port *ourport = id;struct uart_port *port = &ourport->port;if(port->x_char){ //是否有發送流控字符//寫入流控字符wr_regb(port, S3C2410_UTXH, port->x_char);//修改發送計數port->icount.tx++;//清除流控字符port->x_char = 0;return IRQ_HANDLED; //中斷處理完成 }//判斷數據發送struct circ_buf *xmit = &port->state->xmit;if(uart_circ_empty(xmit) || uart_tx_stopped(port)){ //是否循環緩沖為空或者串口停止發送 s3c24xx_serial_stop_tx(port);return IRQ_HANDLED; //中斷處理完成 }//循環發送數據int count = 256;while(!uart_circ_empty(xmit) && (count-- > 0)){ //是否循環緩沖不為空并且發送數據小于256字節//判斷循環緩沖if(rd_regl(port, S3C2410_UFSTAT) & (1<<14)){ //是否循環緩沖已滿break;}//寫入發送數據wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);//移動緩沖位置xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); //循環移動尾部//修改發送計數port->icount.tx++;}//喚醒阻塞進程if(uart_circ_chars_pending(xmit) < 256){ //是否循環緩沖數目小于256 uart_write_wakeup(port);}//關閉發送使能if(uart_circ_empty(xmit)){ //是否循環緩沖為空 s3c24xx_serial_stop_tx(port);}return IRQ_HANDLED; //中斷處理完成 }
?
接收中斷處理程序
接收中斷處理函數在/drivers/serial/samsung.c的s3c24xx_serial_rx_chars
?
static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id){//循環接收數據struct s3c24xx_uart_port *ourport = dev_id;struct uart_port *port = &ourport->port;int max_count = 64;while((max_count--) > 0){ //是否接收數據小于64字節//判斷接收緩沖unsigned int ufstat;ufstat = rd_regl(port, S3C2410_UFSTAT);if((ufstat & 0x3F) == 0){ //是否接收緩沖為空break;}//讀取錯誤狀態unsigned int uerstat;uerstat = rd_regl(port, S3C2410_UERSTAT);//讀取接收數據unsigned int ch;ch = rd_regb(port, S3C2410_URXH);//寫入接收緩沖 uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, TTY_NORMAL);}//寫入線路規程struct tty_struct *tty = port->state->port.tty;tty_flip_buffer_push(tty);return IRQ_HANDLED; //中斷處理完成 }
?