Find the answer to your Linux question:
Results 1 to 2 of 2
i have written a minimal uart driver for 2.6 kernel (code attached). it doesnot provide any operations like baudrate ,data format settings . it chooses a fixed baud rate and ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Sep 2008
    Posts
    1

    problem with uart driver


    i have written a minimal uart driver for 2.6 kernel (code attached). it doesnot provide any operations like baudrate ,data format settings .

    it chooses a fixed baud rate and data format during module initilization.it doesnot perform any flow control. it is for small data transfer over loop back null modem serial connection

    1)Now the problem that i am facing is even though i have chosen 8 bytes from 0x3f8(uart register address) as my port address and the request for this region doesnot show any error. but when i try writing to the associated /dev/myuart node i get a read/write error. (i hav also changed permissions of node to 666).

    when i checked /proc/ioports that address is registered for some module called "serial".

    but when i do a lsmod i dont find any node named serial!

    am i missing something crucial??

    2) Another help that i require is how do i utilize all the functions that my uart provide through the device node??
    i mean i want to know the corresponding userspace functions for my uart functions.
    HTML Code:
    #include <linux/console.h>
    #include <linux/platform_device.h>
    #include <linux/tty.h>
    #include <linux/tty_flip.h>
    #include <linux/serial_core.h>
    #include <linux/serial.h>
    #include <asm/irq.h>
    #include <asm/io.h>
    
    
    #define VUART_MAJOR 62
    #define VUART_MINOR 0
    #define VUART_PORTS 1
    #define MYSERIAL    30
    
    #define BASE                0x3f8
    #define VUART_REGISTER_SPACE  0x8
    
    #define VUART_IRQ       4
    #define VUART_FIFO_SIZE 14
    #define VUART_CLK_FREQ  16000000
    
    #define VUART_TX_FULL   0x20
    #define VUART_RX_EMPTY  0x01
    
    #define RX_INT_ENABLE   0x01
    #define SET_DLAB	0x80
    #define DATA_BITS	0x03           //8 data bits
    #define STOP_BITS	0xFB	       //1 stop bit
    #define PARITY		0xF7	       //no parity bit
    #define LOOPBACK	0x10  
    
    #define ENABLE_FIFO	0x01
    #define FIFO_SIZE	0xC0	      //FIFO size 14 bytes
    
    #define TRUE  1
    #define FALSE 0
    
    
    static void vuart_putc(struct uart_port *port,unsigned char c)
    	{
    		while(__raw_readb(port->membase+5)&VUART_TX_FULL);
    
    		__raw_writeb(c,port->membase);
    		
    	}
    
    static unsigned char vuart_getc(struct uart_port * port)
    	{
    		while(!(__raw_readb(port->membase+5)&VUART_RX_EMPTY));
    
    		return(__raw_readb(port->membase));
    	}
    
    static unsigned char vuart_status(struct uart_port *port)
    	{
    		return(__raw_readb(port->membase+6));
    	}
    
    static int vuart_request_port(struct uart_port *port)
    	{        
    
    	        if(!request_mem_region(port->membase,VUART_REGISTER_SPACE,"MyUART"))
    			{
                             printk("<1>parlelport: cannot reserve 0x378\n");
    			  return -EBUSY;
    			}
    				//hardware uart setup here.
    		__raw_writeb(RX_INT_ENABLE,port->membase+1); //enable interrupt
    		
    		//set dlab bit
                    
                    __raw_writeb(SET_DLAB,port->membase+3);
               
                    //set baud rate by setting the DLL and DLM to 1200 bps
                    __raw_writeb(0x60,port->membase);  //dll
    		
    		__raw_writeb(0x00,port->membase+1); //dlm
    
    		//clear dlab bit
    		
    		__raw_writeb(0x00,port->membase+3);
    
    		//set required data format 
    		__raw_writeb((DATA_BITS & STOP_BITS & PARITY),port->membase+3);
    
     
    		//set loop back bit in MCR
    		__raw_writeb(LOOPBACK,port->membase+4);
    
    		//set FIFO SIZE
    		__raw_writeb((ENABLE_FIFO|FIFO_SIZE),port->membase+2);
    
    
    		return 0;
    	}
    
    static void vuart_release_port(struct uart_port *port)
    	{
    		release_mem_region(port->membase,VUART_REGISTER_SPACE);
    	}
    
    static void vuart_config_port(struct uart_port *port,int flags)
    	{
    		if(flags & UART_CONFIG_TYPE && vuart_request_port(port)==0)
    			port->type=MYSERIAL;
    	}
    
    static irqreturn_t vuart_rxint(int irq,void *dev_id)
    	{
    		struct uart_port *port=(struct uart_port *) dev_id;
    		struct tty_struct *tty=port->info->tty;
    
    		unsigned int status,data;
    	        if((__raw_readb(port->membase+2) & 0x0F)==0x04)  //check the interrupt status reg to see if bytes available to be read
    			{
    
    				do{
    					/* read data */
    					data=vuart_getc(port);
    					status=vuart_status(port);
    					/*despatch to tty layer*/
    					tty_insert_flip_char(tty,data,status);
    		  		  }while (__raw_readb(port->membase+5)&VUART_RX_EMPTY);
    
    				tty_flip_buffer_push(tty);
    			}
    
    
    		return IRQ_HANDLED;
    	}
    
    static int vuart_startup(struct uart_port *port)
    	{
    		int retval=0;
    
    		/*request irq*/
    		if((retval=request_irq(port->irq,vuart_rxint,0,"vuart",(void*)port)))
    			return retval;
    		return retval;
    	}
    
    static void vuart_shutdown(struct uart_port *port)
    	{
    		free_irq(port->irq,port);
    	}
    
    static const char * vuart_type(struct uart_port *port)
    	{
    		return port->type == MYSERIAL ? "vuart" : NULL;
    	}
    
    static void vuart_start_tx(struct uart_port *port)
    	{
    		while(1)
    			{
    				vuart_putc(port,port->info->xmit.buf[port->info->xmit.tail]);
    				//adjust tail of uart buffer
    				port->info->xmit.tail=(port->info->xmit.tail+1)&(UART_XMIT_SIZE-1);
    
    				port->icount.tx++;
    
    				if(uart_circ_empty(&port->info->xmit))break;
    			}
    	}
    /*uart operation structure*/
    static struct uart_ops vuart_ops={
    	.start_tx     =vuart_start_tx,
    	.startup      =vuart_startup,
    	.shutdown     =vuart_shutdown,
    	.type         =vuart_type,
    	.config_port  =vuart_config_port,
    	.request_port =vuart_request_port,
    	.release_port =vuart_release_port,
    	};
    
    static struct uart_driver vuart_driver={
    	.owner=THIS_MODULE,
    	.driver_name="myserial",
    	.dev_name="myuart",
    	.major=VUART_MAJOR,
    	.minor=VUART_MINOR,
    	.nr=VUART_PORTS,
    	};
    
    
    
    /* Parameters  of each supported USB_UART port */
    static struct  uart_port vuart_port = {
            	.mapbase  = BASE,
    	        .iotype   = UPIO_MEM,           /* Memory mapped */
    	        .irq      = VUART_IRQ,      /* IRQ */
    			//.uartclk  = VUART_CLK_FREQ, /* Clock HZ */
    			//.fifosize = VUART_FIFO_SIZE, /* Size of the FIFO */
    			.ops      = &vuart_ops,      /* UART operations */
    			//.flags    = UPF_BOOT_AUTOCONF, /* UART port flag */
    			.line     = 0,                  /* UART port number */
    	};
    
    
    static int __init vuart_init(void)
    	{
    		int ret;
    		
    		ret=uart_register_driver(&vuart_driver);
    
    		if(ret) {
    			pr_err("<1>:couldnot register uart driver\n");
    			goto OVER;
    			}
    		ret=uart_add_one_port(&vuart_driver,&vuart_port);
    		
    		if(ret) {
    			pr_err("<1>:could not add port\n");
    			goto deregister;
    			}
    		
    
    		printk ("Module  loaded\n");
    			return 0;
    
    
    	deregister:	uart_unregister_driver(&vuart_driver);
    	OVER:		return ret;
    		
    	}
    
    static void __exit vuart_exit(void)
    	{
    		uart_remove_one_port(&vuart_driver,&vuart_port);
    		uart_unregister_driver(&vuart_driver);
    	}
    MODULE_LICENSE("GPL");
    module_init(vuart_init);
    module_exit(vuart_exit);

  2. #2
    Just Joined!
    Join Date
    May 2009
    Posts
    1

    serial fix

    hi you are right the next step that you must to do is disable serial drivers /dev/ttyS0 y /dev/ttyS1. You can use setserial program for doing this.




    Quote Originally Posted by vivekmrathod View Post
    i have written a minimal uart driver for 2.6 kernel (code attached). it doesnot provide any operations like baudrate ,data format settings .

    it chooses a fixed baud rate and data format during module initilization.it doesnot perform any flow control. it is for small data transfer over loop back null modem serial connection

    1)Now the problem that i am facing is even though i have chosen 8 bytes from 0x3f8(uart register address) as my port address and the request for this region doesnot show any error. but when i try writing to the associated /dev/myuart node i get a read/write error. (i hav also changed permissions of node to 666).

    when i checked /proc/ioports that address is registered for some module called "serial".

    but when i do a lsmod i dont find any node named serial!

    am i missing something crucial??

    2) Another help that i require is how do i utilize all the functions that my uart provide through the device node??
    i mean i want to know the corresponding userspace functions for my uart functions.
    HTML Code:
    #include <linux/console.h>
    #include <linux/platform_device.h>
    #include <linux/tty.h>
    #include <linux/tty_flip.h>
    #include <linux/serial_core.h>
    #include <linux/serial.h>
    #include <asm/irq.h>
    #include <asm/io.h>
    
    
    #define VUART_MAJOR 62
    #define VUART_MINOR 0
    #define VUART_PORTS 1
    #define MYSERIAL    30
    
    #define BASE                0x3f8
    #define VUART_REGISTER_SPACE  0x8
    
    #define VUART_IRQ       4
    #define VUART_FIFO_SIZE 14
    #define VUART_CLK_FREQ  16000000
    
    #define VUART_TX_FULL   0x20
    #define VUART_RX_EMPTY  0x01
    
    #define RX_INT_ENABLE   0x01
    #define SET_DLAB	0x80
    #define DATA_BITS	0x03           //8 data bits
    #define STOP_BITS	0xFB	       //1 stop bit
    #define PARITY		0xF7	       //no parity bit
    #define LOOPBACK	0x10  
    
    #define ENABLE_FIFO	0x01
    #define FIFO_SIZE	0xC0	      //FIFO size 14 bytes
    
    #define TRUE  1
    #define FALSE 0
    
    
    static void vuart_putc(struct uart_port *port,unsigned char c)
    	{
    		while(__raw_readb(port->membase+5)&VUART_TX_FULL);
    
    		__raw_writeb(c,port->membase);
    		
    	}
    
    static unsigned char vuart_getc(struct uart_port * port)
    	{
    		while(!(__raw_readb(port->membase+5)&VUART_RX_EMPTY));
    
    		return(__raw_readb(port->membase));
    	}
    
    static unsigned char vuart_status(struct uart_port *port)
    	{
    		return(__raw_readb(port->membase+6));
    	}
    
    static int vuart_request_port(struct uart_port *port)
    	{        
    
    	        if(!request_mem_region(port->membase,VUART_REGISTER_SPACE,"MyUART"))
    			{
                             printk("<1>parlelport: cannot reserve 0x378\n");
    			  return -EBUSY;
    			}
    				//hardware uart setup here.
    		__raw_writeb(RX_INT_ENABLE,port->membase+1); //enable interrupt
    		
    		//set dlab bit
                    
                    __raw_writeb(SET_DLAB,port->membase+3);
               
                    //set baud rate by setting the DLL and DLM to 1200 bps
                    __raw_writeb(0x60,port->membase);  //dll
    		
    		__raw_writeb(0x00,port->membase+1); //dlm
    
    		//clear dlab bit
    		
    		__raw_writeb(0x00,port->membase+3);
    
    		//set required data format 
    		__raw_writeb((DATA_BITS & STOP_BITS & PARITY),port->membase+3);
    
     
    		//set loop back bit in MCR
    		__raw_writeb(LOOPBACK,port->membase+4);
    
    		//set FIFO SIZE
    		__raw_writeb((ENABLE_FIFO|FIFO_SIZE),port->membase+2);
    
    
    		return 0;
    	}
    
    static void vuart_release_port(struct uart_port *port)
    	{
    		release_mem_region(port->membase,VUART_REGISTER_SPACE);
    	}
    
    static void vuart_config_port(struct uart_port *port,int flags)
    	{
    		if(flags & UART_CONFIG_TYPE && vuart_request_port(port)==0)
    			port->type=MYSERIAL;
    	}
    
    static irqreturn_t vuart_rxint(int irq,void *dev_id)
    	{
    		struct uart_port *port=(struct uart_port *) dev_id;
    		struct tty_struct *tty=port->info->tty;
    
    		unsigned int status,data;
    	        if((__raw_readb(port->membase+2) & 0x0F)==0x04)  //check the interrupt status reg to see if bytes available to be read
    			{
    
    				do{
    					/* read data */
    					data=vuart_getc(port);
    					status=vuart_status(port);
    					/*despatch to tty layer*/
    					tty_insert_flip_char(tty,data,status);
    		  		  }while (__raw_readb(port->membase+5)&VUART_RX_EMPTY);
    
    				tty_flip_buffer_push(tty);
    			}
    
    
    		return IRQ_HANDLED;
    	}
    
    static int vuart_startup(struct uart_port *port)
    	{
    		int retval=0;
    
    		/*request irq*/
    		if((retval=request_irq(port->irq,vuart_rxint,0,"vuart",(void*)port)))
    			return retval;
    		return retval;
    	}
    
    static void vuart_shutdown(struct uart_port *port)
    	{
    		free_irq(port->irq,port);
    	}
    
    static const char * vuart_type(struct uart_port *port)
    	{
    		return port->type == MYSERIAL ? "vuart" : NULL;
    	}
    
    static void vuart_start_tx(struct uart_port *port)
    	{
    		while(1)
    			{
    				vuart_putc(port,port->info->xmit.buf[port->info->xmit.tail]);
    				//adjust tail of uart buffer
    				port->info->xmit.tail=(port->info->xmit.tail+1)&(UART_XMIT_SIZE-1);
    
    				port->icount.tx++;
    
    				if(uart_circ_empty(&port->info->xmit))break;
    			}
    	}
    /*uart operation structure*/
    static struct uart_ops vuart_ops={
    	.start_tx     =vuart_start_tx,
    	.startup      =vuart_startup,
    	.shutdown     =vuart_shutdown,
    	.type         =vuart_type,
    	.config_port  =vuart_config_port,
    	.request_port =vuart_request_port,
    	.release_port =vuart_release_port,
    	};
    
    static struct uart_driver vuart_driver={
    	.owner=THIS_MODULE,
    	.driver_name="myserial",
    	.dev_name="myuart",
    	.major=VUART_MAJOR,
    	.minor=VUART_MINOR,
    	.nr=VUART_PORTS,
    	};
    
    
    
    /* Parameters  of each supported USB_UART port */
    static struct  uart_port vuart_port = {
            	.mapbase  = BASE,
    	        .iotype   = UPIO_MEM,           /* Memory mapped */
    	        .irq      = VUART_IRQ,      /* IRQ */
    			//.uartclk  = VUART_CLK_FREQ, /* Clock HZ */
    			//.fifosize = VUART_FIFO_SIZE, /* Size of the FIFO */
    			.ops      = &vuart_ops,      /* UART operations */
    			//.flags    = UPF_BOOT_AUTOCONF, /* UART port flag */
    			.line     = 0,                  /* UART port number */
    	};
    
    
    static int __init vuart_init(void)
    	{
    		int ret;
    		
    		ret=uart_register_driver(&vuart_driver);
    
    		if(ret) {
    			pr_err("<1>:couldnot register uart driver\n");
    			goto OVER;
    			}
    		ret=uart_add_one_port(&vuart_driver,&vuart_port);
    		
    		if(ret) {
    			pr_err("<1>:could not add port\n");
    			goto deregister;
    			}
    		
    
    		printk ("Module  loaded\n");
    			return 0;
    
    
    	deregister:	uart_unregister_driver(&vuart_driver);
    	OVER:		return ret;
    		
    	}
    
    static void __exit vuart_exit(void)
    	{
    		uart_remove_one_port(&vuart_driver,&vuart_port);
    		uart_unregister_driver(&vuart_driver);
    	}
    MODULE_LICENSE("GPL");
    module_init(vuart_init);
    module_exit(vuart_exit);

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •