<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > linux設(shè)備模型之uart驅(qū)動架構(gòu)分析

          linux設(shè)備模型之uart驅(qū)動架構(gòu)分析

          作者: 時間:2016-10-08 來源:網(wǎng)絡(luò) 收藏

          五: uart_add_one_port()操作

          本文引用地址:http://www.ex-cimer.com/article/201610/305916.htm

          在前面提到。在對uart設(shè)備文件過程中。會將操作轉(zhuǎn)換到對應(yīng)的port上,這個port跟uart_driver是怎么關(guān)聯(lián)起來的呢?這就是uart_add_ont_port()的主要工作了。

          顧名思義,這個函數(shù)是在uart_driver增加一個port.代碼如下:

          int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)

          {

          struct uart_state *state;

          int ret = 0;

          struct device *tty_dev;

          BUG_ON(in_interrupt());

          if (port->line >= drv->nr)

          return -EINVAL;

          state = drv->state + port->line;

          mutex_lock(port_mutex);

          mutex_lock(state->mutex);

          if (state->port) {

          ret = -EINVAL;

          goto out;

          }

          state->port = port;

          state->pm_state = -1;

          port->cons = drv->cons;

          port->info = state->info;

          /*

          * If this port is a console, then the spinlock is already

          * initialised.

          */

          if (!(uart_console(port) (port->cons->flags CON_ENABLED))) {

          spin_lock_init(port->lock);

          lockdep_set_class(port->lock, port_lock_key);

          }

          uart_configure_port(drv, state, port);

          /*

          * Register the port whether it's detected or not. This allows

          * setserial to be used to alter this ports parameters.

          */

          tty_dev = tty_register_device(drv->tty_driver, port->line, port->dev);

          if (likely(!IS_ERR(tty_dev))) {

          device_can_wakeup(tty_dev) = 1;

          device_set_wakeup_enable(tty_dev, 0);

          } else

          printk(KERN_ERR Cannot register tty device on line %dn,

          port->line);

          /*

          * Ensure UPF_DEAD is not set.

          */

          port->flags = ~UPF_DEAD;

          out:

          mutex_unlock(state->mutex);

          mutex_unlock(port_mutex);

          return ret;

          }

          首先這個函數(shù)不能在中斷環(huán)境中使用。 Uart_port->line就是對uart設(shè)備文件序號。它對應(yīng)的也就是uart_driver->state數(shù)組中的uart_port->line項。

          它主要初始化對應(yīng)uart_driver->state項。接著調(diào)用uart_configure_port()進行port的自動配置。然后注冊tty_device.如果用戶空間運行了udev或者已經(jīng)配置好了hotplug.就會在/dev下自動生成設(shè)備文件了。

          操作流程圖如下所示:

          六:設(shè)備節(jié)點的open操作

          在用戶空間執(zhí)行open操作的時候,就會執(zhí)行uart_ops->open. Uart_ops的定義如下:

          static const struct tty_operations uart_ops = {

          .open = uart_open,

          .close = uart_close,

          .write = uart_write,

          .put_char = uart_put_char,

          .flush_chars = uart_flush_chars,

          .write_room = uart_write_room,

          .chars_in_buffer= uart_chars_in_buffer,

          .flush_buffer = uart_flush_buffer,

          .ioctl = uart_ioctl,

          .throttle = uart_throttle,

          .unthrottle = uart_unthrottle,

          .send_xchar = uart_send_xchar,

          .set_termios = uart_set_termios,

          .stop = uart_stop,

          .start = uart_start,

          .hangup = uart_hangup,

          .break_ctl = uart_break_ctl,

          .wait_until_sent= uart_wait_until_sent,

          #ifdef CONFIG_PROC_FS

          .read_proc = uart_read_proc,

          #endif

          .tiocmget = uart_tiocmget,

          .tiocmset = uart_tiocmset,

          };

          對應(yīng)open的操作接口為uart_open.代碼如下:

          static int uart_open(struct tty_struct *tty, struct file *filp)

          {

          struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state;

          struct uart_state *state;

          int retval, line = tty->index;

          BUG_ON(!kernel_locked());

          pr_debug(uart_open(%d) calledn, line);

          /*

          * tty->driver->num won't change, so we won't fail here with

          * tty->driver_data set to something non-NULL (and therefore

          * we won't get caught by uart_close())。

          */

          retval = -ENODEV;

          if (line >= tty->driver->num)

          goto fail;

          /*

          * We take the semaphore inside uart_get to guarantee that we won't

          * be re-entered while allocating the info structure, or while we

          * request any IRQs that the driver may need. This also has the nice

          * side-effect that it delays the action of uart_hangup, so we can

          * guarantee that info->tty will always contain something reasonable.

          */

          state = uart_get(drv, line);

          if (IS_ERR(state)) {

          retval = PTR_ERR(state);

          goto fail;

          }

          /*

          * Once we set tty->driver_data here, we are guaranteed that

          * uart_close() will decrement the driver module use count.

          * Any failures from here onwards should not touch the count.

          */

          tty->driver_data = state;

          tty->low_latency = (state->port->flags UPF_LOW_LATENCY) ? 1 : 0;



          關(guān)鍵詞:

          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();