DSP

uclinux内核的console(1):数据结构

2019-07-13 15:40发布

rev 0.2   快乐虾 http://blog.csdn.net/lights_joy/ lights@hb165.com   本文适用于 ADI bf561 DSP 优视BF561EVB开发板 uclinux-2008r1.5-rc3 (smp patch) Visual DSP++ 5.0 (update 5)   欢迎转载,但请保留作者信息   内核中与console相关的结构体可以分为通用定义与不同体系结构的定义两部分,通用定义与具体的硬件无关,它只是定义了一类硬件的通用参数与接口,不同的体系结构下还需要加上一些特有的东西。

1.1    串口通用定义

1.1.1   uart_ops

这个结构体的定义位于include/linux/serial_core.h,它定义了UART要实现的操作: /*  * This structure describes all the operations that can be  * done on the physical hardware.  */ struct uart_ops {      unsigned int  (*tx_empty)(struct uart_port *);      void     (*set_mctrl)(struct uart_port *, unsigned int mctrl);      unsigned int  (*get_mctrl)(struct uart_port *);      void     (*stop_tx)(struct uart_port *);      void     (*start_tx)(struct uart_port *);      void     (*send_xchar)(struct uart_port *, char ch);      void     (*stop_rx)(struct uart_port *);      void     (*enable_ms)(struct uart_port *);      void     (*break_ctl)(struct uart_port *, int ctl);      int      (*startup)(struct uart_port *);      void     (*shutdown)(struct uart_port *);      void     (*set_termios)(struct uart_port *, struct ktermios *new,                           struct ktermios *old);      void     (*pm)(struct uart_port *, unsigned int state,                     unsigned int oldstate);      int      (*set_wake)(struct uart_port *, unsigned int state);        /*       * Return a string describing the type of the port       */      const char *(*type)(struct uart_port *);        /*       * Release IO and memory resources used by the port.       * This includes iounmap if necessary.       */      void     (*release_port)(struct uart_port *);        /*       * Request IO and memory resources used by the port.       * This includes iomapping the port if necessary.       */      int      (*request_port)(struct uart_port *);      void     (*config_port)(struct uart_port *, int);      int      (*verify_port)(struct uart_port *, struct serial_struct *);      int      (*ioctl)(struct uart_port *, unsigned int, unsigned long); };  

1.1.2   uart_port

这个结构体的定义位于include/linux/serial_core.h,从它的位置可以看出,这是一个与具体硬件无关的结构体,它提供了对UART的描述信息,对于某个具体的UART,可能只使用其中的某些字段。 struct uart_port {      spinlock_t         lock;              /* port lock */      unsigned int       iobase;            /* in/out[bwl] */      unsigned char __iomem  *membase;     /* read/write[bwl] */      unsigned int       irq;          /* irq number */      unsigned int       uartclk;      /* base uart clock */      unsigned int       fifosize;     /* tx fifo size */      unsigned char      x_char;            /* xon/xoff char */      unsigned char      regshift;     /* reg offset shift */      unsigned char      iotype;            /* io access style */      unsigned char      unused1;        unsigned int       read_status_mask;  /* driver specific */      unsigned int       ignore_status_mask;    /* driver specific */      struct uart_info   *info;             /* pointer to parent info */      struct uart_icount icount;            /* statistics */        struct console         *cons;             /* struct console, if any */        upf_t              flags;        unsigned int       mctrl;             /* current modem ctrl settings */      unsigned int       timeout;      /* character-based timeout */      unsigned int       type;              /* port type */      const struct uart_ops  *ops;      unsigned int       custom_divisor;      unsigned int       line;              /* port index */      unsigned long      mapbase;      /* for ioremap */      struct device      *dev;              /* parent device */      unsigned char      hub6;              /* this should be in the 8250 driver */      unsigned char      unused[3];      void          *private_data;         /* generic platform data pointer */ }; 在内核中,没有为uart_port定义独立的变量,它将从属于某个具体的serial_port,对于bf561,它将从属于bfin_serial_port这一结构体。 实际上内核只使用了以下几个成员: l         uartclk这个值将设置为BF561的系统时钟频率,在我的系统中,它将为99M l         ops定义对UART的操作函数,指向bfin_serial_pops这一变量。 l         line串口序号,只有一个串口,恒为0 l         iotypeUPIO_MEM,即直接寄存器访问方式。 l         membase指向UART_THR(0xFFC0 0400),即UART的发送寄存器。 l         mapbasemembase相同。 l         irq内核中中断描述数组(irq_desc)的序号,指UART接收中断(IRQ_UART_RX) l         flags配置为UPF_BOOT_AUTOCONF    

1.2    不同体系结构下的串口定义

1.2.1   bfin_serial_port

这个结构体的定义在include/asm/mach/bfin-serial-5xx.h中: struct bfin_serial_port {         struct uart_port        port;         unsigned int            old_status;          unsigned int lsr; #ifdef CONFIG_SERIAL_BFIN_DMA      int           tx_done;      int           tx_count;      struct circ_buf        rx_dma_buf;      struct timer_list       rx_dma_timer;      int           rx_dma_nrows;      unsigned int       tx_dma_channel;      unsigned int       rx_dma_channel;      struct work_struct tx_dma_workqueue; #endif }; 此结构体在uart_port的基础上,扩充了几个成员。 在内核中,有这样的定义: struct bfin_serial_port bfin_serial_ports[NR_PORTS]; 在这里,NR_PORTS的值为1,对UART的所有操作都将通过这一变量来完成。 需要注意的是rx_dma_timer这个成员,在串口初始化的时候,它将调用          init_timer(&(bfin_serial_ports[i].rx_dma_timer)); 向内核注册一个时钟源。

1.3    console

这个结构体的定义在include/linux/console.h中,它定义了一个console驱动需要提供的信息及其必须实现的一些操作: /*  * The interface for a console, or any other device that wants to capture  * console messages (printer driver?)  *  * If a console driver is marked CON_BOOT then it will be auto-unregistered  * when the first real console is registered.  This is for early-printk drivers.  */   struct console {      char name[16];      void (*write)(struct console *, const char *, unsigned);      int  (*read)(struct console *, char *, unsigned);      struct tty_driver *(*device)(struct console *, int *);      void (*unblank)(void);      int  (*setup)(struct console *, char *);      short    flags;      short    index;      int  cflag;      void *data;      struct   console *next; }; 在内核中,对此结构体初始化为: static struct console bfin_serial_console = {      .name         = BFIN_SERIAL_NAME,   // ttyBF      .write        = bfin_serial_console_write,      .device       = uart_console_device,      .setup        = bfin_serial_console_setup,      .flags        = CON_PRINTBUFFER,      .index        = -1,      .data         = &bfin_serial_reg, }; console中的cflag则保存了串口配置,如CREAD | HUPCL | CLOCAL | B57600 | CS8,使用它即可知道当前的串口配置。 flags的值在初始化完成后则变成了CON_PRINTBUFFER | CON_ENABLED | CON_CONSDEV index的值在初始化完成后变成0,因为只使用serial console 这里值得注意的是setup回调函数,当console初始化时,它需要初始化与此console相关的硬件,此时它将调用setup这一回调函数来完成此工作。

1.4    ktermios

这个结构体用于定义一个终端需要使用的参数: struct ktermios {      tcflag_t c_iflag;               /* input mode flags */      tcflag_t c_oflag;               /* output mode flags */      tcflag_t c_cflag;               /* control mode flags */      tcflag_t c_lflag;               /* local mode flags */      cc_t c_line;                    /* line discipline */      cc_t c_cc[NCCS];                /* control characters */      speed_t c_ispeed;               /* input speed */      speed_t c_ospeed;               /* output speed */ }; 它并没有定义相关的结构体,仅仅用于向bfin_serial_set_termios传递参数。 几个比较重要的值: c_cflag:串口的波特率、校验位、字长这几个参数都通过这个标志来传递。  

1       参考资料

uclinux-2008r1-rc8(bf561)内核的console(1):数据结构2008/5/29  uclinux-2008r1-rc8(bf561)内核的console(2):驱动初始化(2008/5/29) uclinux-2008r1-rc8(bf561)内核的console(3):通过console输出信息(2008/5/29)