Nuttx驅(qū)動(dòng)機(jī)制

Nuttx相關(guān)的歷史文章:

介紹

Nuttx支持多種設(shè)備驅(qū)動(dòng)嗜价,包括:

  • 字符設(shè)備驅(qū)動(dòng)约谈,比如串口設(shè)備、觸摸屏設(shè)備、ADC/DAC锅铅、PWM、CAN晾嘶、正交編碼器幽邓、Timer、RTC撤蟆、Watchdog奕塑、Keyboard/Keypad等;
  • 塊設(shè)備驅(qū)動(dòng)家肯;
  • 其他特殊設(shè)備驅(qū)動(dòng)龄砰,比如Ethernet、SPI讨衣、I2C换棚、Frame Buffer、LCD反镇、MTD固蚤、SDIO、USB等歹茶;

總體來(lái)說(shuō)夕玩,Nuttx中的驅(qū)動(dòng)機(jī)制相對(duì)來(lái)說(shuō)比較簡(jiǎn)單,它并沒(méi)有提供像Linux系統(tǒng)那樣復(fù)雜的驅(qū)動(dòng)模型機(jī)制惊豺,比如Device燎孟、Driver、Bus扮叨、Class等缤弦。Nuttx只是簡(jiǎn)單的通過(guò)驅(qū)動(dòng)注冊(cè)接口,將驅(qū)動(dòng)注冊(cè)進(jìn)文件系統(tǒng)中彻磁,并實(shí)現(xiàn)file_operations操作函數(shù)集碍沐,上層應(yīng)用便能通過(guò)標(biāo)準(zhǔn)的系統(tǒng)調(diào)用,進(jìn)而調(diào)用到低層的驅(qū)動(dòng)衷蜓。

我將以字符設(shè)備驅(qū)動(dòng)來(lái)闡述整個(gè)驅(qū)動(dòng)的機(jī)制累提。

數(shù)據(jù)結(jié)構(gòu)與接口

數(shù)據(jù)結(jié)構(gòu)

應(yīng)用層通過(guò)系統(tǒng)調(diào)用來(lái)訪問(wèn)驅(qū)動(dòng):系統(tǒng)調(diào)用->vfs->驅(qū)動(dòng),因此首先需要了解一下磁浇,驅(qū)動(dòng)注冊(cè)進(jìn)文件系統(tǒng)時(shí)所涉及到的數(shù)據(jù)結(jié)構(gòu)斋陪。數(shù)據(jù)結(jié)構(gòu)的相關(guān)定義在include/nuttx/fs/fs.h文件中。
首先,驅(qū)動(dòng)注冊(cè)后无虚,會(huì)創(chuàng)建一個(gè)inode缔赠,對(duì)應(yīng)到設(shè)備文件上:

/* This structure represents one inode in the Nuttx pseudo-file system */

struct inode
{
  FAR struct inode *i_peer;     /* Link to same level inode */
  FAR struct inode *i_child;    /* Link to lower level inode */
  int16_t           i_crefs;    /* References to inode */
  uint16_t          i_flags;    /* Flags for inode */
  union inode_ops_u u;          /* Inode operations */
#ifdef CONFIG_FILE_MODE
  mode_t            i_mode;     /* Access mode flags */
#endif
  FAR void         *i_private;  /* Per inode driver private data */
  char              i_name[1];  /* Name of inode (variable) */
};

其中i_flags字段用于標(biāo)記該inode對(duì)應(yīng)的為什么文件,典型的有驅(qū)動(dòng)友题、消息隊(duì)列等嗤堰,專門有宏定義來(lái)設(shè)置或者判斷這個(gè)字段是否為驅(qū)動(dòng)文件:

#define INODE_IS_DRIVER(i)    INODE_IS_TYPE(i,FSNODEFLAG_TYPE_DRIVER)

#define INODE_SET_DRIVER(i)   INODE_SET_TYPE(i,FSNODEFLAG_TYPE_DRIVER)

struct inode結(jié)構(gòu)體中inode_ops_u用于描述操作函數(shù)集,這個(gè)字段是一個(gè)聯(lián)合體度宦,可以是字符設(shè)備驅(qū)動(dòng)踢匣、塊設(shè)備驅(qū)動(dòng)、掛載點(diǎn)等的操作函數(shù)集戈抄。驅(qū)動(dòng)操作函數(shù)集如下:

struct file_operations
{
  /* The device driver open method differs from the mountpoint open method */

  int     (*open)(FAR struct file *filep);

  /* The following methods must be identical in signature and position because
   * the struct file_operations and struct mountp_operations are treated like
   * unions.
   */

  int     (*close)(FAR struct file *filep);
  ssize_t (*read)(FAR struct file *filep, FAR char *buffer, size_t buflen);
  ssize_t (*write)(FAR struct file *filep, FAR const char *buffer, size_t buflen);
  off_t   (*seek)(FAR struct file *filep, off_t offset, int whence);
  int     (*ioctl)(FAR struct file *filep, int cmd, unsigned long arg);

  /* The two structures need not be common after this point */

#ifndef CONFIG_DISABLE_POLL
  int     (*poll)(FAR struct file *filep, struct pollfd *fds, bool setup);
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  int     (*unlink)(FAR struct inode *inode);
#endif
};

這個(gè)函數(shù)集离唬,由低層的驅(qū)動(dòng)來(lái)實(shí)現(xiàn),并且設(shè)置進(jìn)設(shè)備文件對(duì)應(yīng)的inode中划鸽,當(dāng)系統(tǒng)調(diào)用操作設(shè)備文件時(shí)输莺,便能根據(jù)設(shè)備文件對(duì)應(yīng)的inode來(lái)找到對(duì)應(yīng)的函數(shù)了。

接口
驅(qū)動(dòng)注冊(cè)的時(shí)候裸诽,會(huì)調(diào)用register_driver()接口:

/****************************************************************************
 * Name: register_driver
 *
 * Description:
 *   Register a character driver inode the pseudo file system.
 *
 * Input parameters:
 *   path - The path to the inode to create
 *   fops - The file operations structure
 *   mode - inmode priviledges (not used)
 *   priv - Private, user data that will be associated with the inode.
 *
 * Returned Value:
 *   Zero on success (with the inode point in 'inode'); A negated errno
 *   value is returned on a failure (all error values returned by
 *   inode_reserve):
 *
 *   EINVAL - 'path' is invalid for this operation
 *   EEXIST - An inode already exists at 'path'
 *   ENOMEM - Failed to allocate in-memory resources for the operation
 *
 ****************************************************************************/

int register_driver(FAR const char *path, FAR const struct file_operations *fops,
                    mode_t mode, FAR void *priv)
{
  FAR struct inode *node;
  int ret;

  /* Insert a dummy node -- we need to hold the inode semaphore because we
   * will have a momentarily bad structure.
   */

  inode_semtake();
  ret = inode_reserve(path, &node);
  if (ret >= 0)
    {
      /* We have it, now populate it with driver specific information.
       * NOTE that the initial reference count on the new inode is zero.
       */

      INODE_SET_DRIVER(node);

      node->u.i_ops   = fops;
#ifdef CONFIG_FILE_MODE
      node->i_mode    = mode;
#endif
      node->i_private = priv;
      ret             = OK;
    }

  inode_semgive();
  return ret;
}

這個(gè)接口完成以下幾個(gè)操作:

  1. 根據(jù)path(一般對(duì)應(yīng)設(shè)備文件模闲,比如/dev/xxxx),來(lái)查找是否存在對(duì)應(yīng)的inode崭捍,如果沒(méi)有的話尸折,那為path創(chuàng)建一個(gè)inode;
  2. 將實(shí)際驅(qū)動(dòng)實(shí)現(xiàn)的struct file_operations fops更新到path對(duì)應(yīng)的inode中,此外還設(shè)置權(quán)限殷蛇;
  3. priv數(shù)據(jù)設(shè)置進(jìn)inode中实夹,這個(gè)一般存放驅(qū)動(dòng)的私有數(shù)據(jù);

ADC驅(qū)動(dòng)

下面將以一個(gè)實(shí)際的驅(qū)動(dòng)粒梦,ADC驅(qū)動(dòng)亮航,來(lái)分析一下流程。
在Nuttx的驅(qū)動(dòng)代碼中匀们,你會(huì)發(fā)現(xiàn)經(jīng)常會(huì)把驅(qū)動(dòng)分成兩部分缴淋,一個(gè)是upper half,一個(gè)是lower half

  • upper half:上半部分提供了應(yīng)用程序級(jí)的通用接口泄朴,也就是實(shí)現(xiàn)了file_operations中的函數(shù)集重抖,比如針對(duì)ADC驅(qū)動(dòng),專門有drivers/analog/adc.c來(lái)描述上半部分的操作祖灰,這個(gè)對(duì)于所有的ADC設(shè)備都是相同的钟沛;
  • lower half:下半部分基于特定平臺(tái)的驅(qū)動(dòng)程序,用于實(shí)現(xiàn)硬件級(jí)的控制局扶,比如寄存器的操作等恨统。arch/arm/src/lpc43xx/lpc43_adc.c文件實(shí)現(xiàn)了特定的硬件驅(qū)動(dòng)叁扫;

整體的框架如下圖所示:


adc驅(qū)動(dòng)框架
  • 芯片相關(guān),代表了lower half畜埋,針對(duì)硬件的實(shí)際操作莫绣,并且在中斷處理函數(shù)中,會(huì)去回調(diào)upper half的回調(diào)函數(shù)悠鞍⊥米郏可以在這個(gè)回調(diào)函數(shù)中做一些處理,比如通過(guò)消息隊(duì)列的機(jī)制狞玛,統(tǒng)治上層應(yīng)用已經(jīng)收到了數(shù)據(jù);
  • 通用框架涧窒,代表了upper half心肪,對(duì)接上層的系統(tǒng)調(diào)用,并且在實(shí)現(xiàn)file_operations函數(shù)集的時(shí)候纠吴,會(huì)去調(diào)用lower half的接口硬鞍;
  • 板級(jí)部分,這個(gè)部分其實(shí)是將upper halflower half進(jìn)行綁定戴已,建立連接并注冊(cè)進(jìn)文件系統(tǒng)中固该,這個(gè)接口最終會(huì)在系統(tǒng)boot的階段調(diào)用;

具體的驅(qū)動(dòng)代碼就不貼了糖儡。
其他的驅(qū)動(dòng)實(shí)現(xiàn)伐坏,機(jī)制都大體類似蒂培,分成兩部分婆瓜,上半部分對(duì)接應(yīng)用系統(tǒng)調(diào)用,下半部分對(duì)應(yīng)實(shí)際的低層硬件操作偶摔,這種分層是一種合理的做法金闽,上半部分做成通用的框架纯露,不需要改動(dòng),下半部分針對(duì)不同硬件實(shí)現(xiàn)具體的操作接口即可了代芜。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末埠褪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子挤庇,更是在濱河造成了極大的恐慌钞速,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嫡秕,死亡現(xiàn)場(chǎng)離奇詭異玉工,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)淘菩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門遵班,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)屠升,“玉大人,你說(shuō)我怎么就攤上這事狭郑「古” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵翰萨,是天一觀的道長(zhǎng)脏答。 經(jīng)常有香客問(wèn)我,道長(zhǎng)亩鬼,這世上最難降的妖魔是什么殖告? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮雳锋,結(jié)果婚禮上黄绩,老公的妹妹穿的比我還像新娘。我一直安慰自己玷过,他們只是感情好爽丹,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著辛蚊,像睡著了一般粤蝎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上袋马,一...
    開(kāi)封第一講書(shū)人閱讀 52,682評(píng)論 1 312
  • 那天初澎,我揣著相機(jī)與錄音,去河邊找鬼虑凛。 笑死谤狡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的卧檐。 我是一名探鬼主播墓懂,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼霉囚!你這毒婦竟也來(lái)了捕仔?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤盈罐,失蹤者是張志新(化名)和其女友劉穎榜跌,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體盅粪,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡钓葫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了票顾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片础浮。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡帆调,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出豆同,到底是詐尸還是另有隱情番刊,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布影锈,位于F島的核電站芹务,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏鸭廷。R本人自食惡果不足惜枣抱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辆床。 院中可真熱鬧佳晶,春花似錦、人聲如沸佛吓。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)维雇。三九已至,卻和暖如春晒他,著一層夾襖步出監(jiān)牢的瞬間吱型,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工陨仅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留津滞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓灼伤,卻偏偏與公主長(zhǎng)得像触徐,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子狐赡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容