EtherCAT使用と解析-ethercatシステムカーネルモジュールのロードと初期化操作


linuxシステムにethercatシステムをインストール完了し、NIC MACと駆動を構成した後、sudo/etc/initを実行する.d/ethercat startはethercatシステムを起動し、このスクリプトでは本質的に2つのモジュールが呼び出されます.1つはマスタモジュールec_です.master.ko、一つは駆動モジュールec_generic.ko(ドライバモジュール部分についてはプロファイルのDEVICE_MODULESタイプによって決まりますが、ここでは一般的にgenericを選択します).
ec_master.ko:
このモジュールの初期化関数は./master/module.c/ec_init_module,このモジュールはethercatのマスタモジュールであり,主にethercatスレーブ情報の格納,domainsドメインの管理,スレーブ構成の管理などethercatシステムに関するリソースの管理,/etc/sysconfig/ethercatで構成されたMASTER 0_DEVICEはこのモジュールパラメータとしてマスタモジュールに伝達され、最終的にマスタモジュールとなるmacはネットワークアドレス、すなわちmaster->macsを使用する.マスタモジュールの初期化関数を順番に理解します.主に以下の部分があります.
1.文字デバイスの作成:文字デバイスを作成する目的は、アプリケーション層にインタフェースを提供し、アプリケーション層がカーネルを呼び出す機能を容易にすることです.作成された文字デバイスは、/dev/EtherCATx(/dev/EtherCAT 0、/dev/EtherCAT 1とすることができます.作成された文字デバイスは、マスタ局の数だけ作成されます)です.具体的な作成手順は、次のとおりです.
int alloc_の使用chrdev_region(dev_t *dev,unsigned baseminor,unsigned count,const char *name);動的申請設備番号;
class_の使用createとdevice_createおよび上記申請したデバイスは、文字デバイス/dev/EtherCATを直接作成することができます.
2.マスタ構造の作成と初期化:
各MACアドレスは1つのマスタ空間に対応し、各マスタに対応する構造体は.master/master.hのec_master構造体、構造体は以下の通りです.
struct ec_master 
{
    unsigned int index; /**< Index.      (       ec_master   mac  ) */

	/*          ,          ,      1 */
	unsigned int reserved; /**< \a True, if the master is in use. */

    ec_cdev_t cdev; /**< Master character device.        */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
    struct device *class_device; /**< Master class device. ec_master  /dev       */
#else
    struct class_device *class_device; /**< Master class device. */
#endif

#ifdef EC_RTDM
    ec_rtdm_dev_t rtdm_dev; /**< RTDM device. */
#endif

    struct semaphore master_sem; /**< Master semaphore. sema_init(&master->master_sem, 1);         */

    ec_device_t devices[EC_MAX_NUM_DEVICES]; /**< EtherCAT devices. EtherCAT        */
    const uint8_t *macs[EC_MAX_NUM_DEVICES]; /**< Device MAC addresses.    mac  , 0    1       */
#if EC_MAX_NUM_DEVICES > 1
    unsigned int num_devices; /**< Number of devices. Access this always via
                                ec_master_num_devices(), because it may be
                                optimized! 
                                  mac    ,  mac      devices,      mac  2,    1 */
#endif
    struct semaphore device_sem; /**< Device semaphore.        ,          */
    ec_device_stats_t device_stats; /**< Device statistics.          */

	/*      ,          (    、         ),                               (fsm->state)   。 */
    ec_fsm_master_t fsm; /**< Master state machine. */
    ec_datagram_t fsm_datagram; /**< Datagram used for state machines.            */
	
	/** Master phase.        */
    ec_master_phase_t phase; 

	/*       ,    0,                   ,  1 */
    unsigned int active; /**< Master has been activated. */

	/*         , config_changed      1,config_changed    DC ,     configs     */
	unsigned int config_changed; /**< The configuration changed. */
	
	/*             0,               */
    unsigned int injection_seq_fsm; /**< Datagram injection sequence number for the FSM side. FSM          。 */
	/*             0,               */
	unsigned int injection_seq_rt; /**< Datagram injection sequence number for the realtime side. */

	/*   ethercat     ,                ,        ethercat      ,          。 ec_master_init         NULL,  ,        ec_slave_t  ,          */
    ec_slave_t *slaves; /**< Array of slaves on the bus. */

	/*  ec_master_init         0,            (    )          */
    unsigned int slave_count; /**< Number of slaves on the bus. */

    /* Configuration applied by the application.             ,      ecrt_master_slave_config()                  configs    */
	/*               list_head  ,          ,       ec_slave_config_t(  configs     )  , ec_slave_config_t       list_head,                 ,                  */
    struct list_head configs; /**< List of slave configurations.  */

	struct list_head domains; /**< List of domains.    (      ) */

	/*             ,  ecrt_master_application_time()  ioctl     ,      linux         ,           ,   examples/dc_user/main.c cycle_task() */
    u64 app_time; /**< Time of the last ecrt_master_sync() call. */

	/*            */
    u64 app_start_time; /**< Application start time. */

	/*         ,         ,                ,                      */
    u8 has_app_time; /**< Application time is valid. */

	/* master/master.c/ec_master_find_dc_ref_clock()         fpwr  , 0x0910(4Byte)                              */
    ec_datagram_t ref_sync_datagram; /**< Datagram used for synchronizing the reference clock to the master clock. */

	/* master/master.c/ec_master_find_dc_ref_clock()         frmw  ,             , 0x0910(4Byte)     */
	ec_datagram_t sync_datagram; /**< Datagram used for DC drift compensation. */
    ec_datagram_t sync_mon_datagram; /**< Datagram used for DC synchronisation monitoring.                 */

	/*                   ,      ,                                    */
	ec_slave_config_t *dc_ref_config; /**< Application-selected DC reference clock slave config. */

	/*            ,  dc_ref_config          DC  ,       dc_ref_config         ,  ,  ethercat                  DC             ,                          */
	ec_slave_t *dc_ref_clock; /**< DC reference clock slave. */

	/*                 , allow_scan          , scan_sem     
	            :1.        (           ) */
    unsigned int scan_busy; /**< Current scan state. */

	/*         ,ec_master_init        ,           ,       ec_master_init()     1,       ,        ,  allow_scan  0,      ec_master_leave_operation_phase()    1 */
    unsigned int allow_scan; /**< \a True, if slave scanning is allowed. */
	
    struct semaphore scan_sem; /**< Semaphore protecting the \a scan_busy
                                 variable and the \a allow_scan flag.    ,  scan_busy allow_scan    */
    wait_queue_head_t scan_queue; /**< Queue for processes that wait for slave scanning.              */

    unsigned int config_busy; /**< State of slave configuration. */
    struct semaphore config_sem; /**< Semaphore protecting the \a config_busy
                                   variable and the allow_config flag. */
    wait_queue_head_t config_queue; /**< Queue for processes that wait for
                                      slave configuration. */

	/**
	 *	                。                ,      read  ,                    ec_datagram_t->data 。                         (            ); */
    struct list_head datagram_queue; /**< Datagram queue. */

	/*        ec_master_init()   index    0,         ,           ;
	         datagram_index   uint8_t,       255,   ethercat          ? */
    uint8_t datagram_index; /**< Current datagram index. */

    struct list_head ext_datagram_queue; /**< Queue for non-application datagrams. */
    struct semaphore ext_queue_sem; /**< Semaphore protecting the ext_datagram_queue. */

	/*                           ,         , */
    ec_datagram_t ext_datagram_ring[EC_EXT_RING_SIZE]; /**< External datagram ring.            ext-xx*/

	/*                          ,      ec_datagram_t  ,      SDO   ,                  sdo_requests SDO     ,                        ,                ec_datagram_t         */
    unsigned int ext_ring_idx_rt; /**< Index in external datagram ring for RT side. */
    unsigned int ext_ring_idx_fsm; /**< Index in external datagram ring for FSM side. */

	/*     ecrt_master_send()   (ms) */
    unsigned int send_interval; /**< Interval(ms) between two calls to ecrt_master_send(). */

	/*                     ,            ,               */
    size_t max_queue_size; /**< Maximum size of datagram queue */

	/*           */
    ec_slave_t *fsm_slave; /**< Slave that is queried next for FSM exec.      FSM        */

	/*          ,      ethercat/master/fsm_slave.h/ec_fsm_slave_t  ,               ,                               ,       ;                        ,       。 */
    struct list_head fsm_exec_list; /**< Slave FSM execution list.      ,     master/fsm_slave.h/.c  */
	/*             ,      fsm_exec_list   */
	unsigned int fsm_exec_count; /**< Number of entries in execution list. */


    unsigned int debug_level; /**< Master debug level. */
    ec_stats_t stats; /**< Cyclic statistics. */

	/**
	 *	         ,                 ec_master_idle_thread()   ;                  ec_master_operation_thread()       */
    struct task_struct *thread; /**< Master thread.     ,master.c       NULL */

#ifdef EC_EOE
    struct task_struct *eoe_thread; /**< EoE thread. */
    struct list_head eoe_handlers; /**< Ethernet over EtherCAT handlers. */
#endif

    struct semaphore io_sem; /**< Semaphore used in \a IDLE phase.            */

	//       ,          
	/*     NULL,   master.c/ec_master_internal_send_cb     */
    void (*send_cb)(void *); /**< Current send datagrams callback. */

	/*     NULL,   master.c/ec_master_internal_receive_cb     */
	void (*receive_cb)(void *); /**< Current receive datagrams callback. */

	/*     NULL,       (ec_master  )   */
	void *cb_data; /**< Current callback data. */
	
    void (*app_send_cb)(void *); /**< Application's send datagrams callback.     NULL */
    void (*app_receive_cb)(void *); /**< Application's receive datagrams callback.     NULL */
    void *app_cb_data; /**< Application callback data.     NULL */

    struct list_head sii_requests; /**< SII write requests.            */

    wait_queue_head_t request_queue; /**< Wait queue for external requests from user space.   init_waitqueue_head()           */
};

次に./master/master.c/ec_master_Init()関数は単一のマスタ構造体の初期化を行い,初期化内容は煩雑であり,その後の操作と結びつけて理解することが望ましい.この章ではこれ以上述べない.
 
ec_generic.ko:
このモジュールの初期化関数は./devices/generic.c/ec_gen_init_module()関数.この関数にはinit_があります.Netチェーンテーブル、このチェーンテーブルはカーネル空間の中で、すべてのNICデバイスを指しています.フィルタリングARPHRD_ETHERイーサネットカードのnetdevは、その後、これらのネットワークカード情報をマスタ局登録時に使用されるMACアドレスと照合して抽出し、照合が正常であればマスタ局をネットワーク装置に接続する、すなわちmaster->devices[0]->devは、照合されたnetdev構造体を指す(基本的にマスタ局に関連するnet_deviceタイプ構造体は、その構造情報を指す).マスタを使用してマスタとネットワーク機器をマッチングした後、ネットワーク通信を行うために、PF_を採用したソケットを申請する必要があるPACKETプロトコルファミリーの元のソケットは、元のソケットは、データフレームの送受信を行う際に完全なデータフレームであり、すなわち、受信したデータフレームは、ターゲットMAC+ソースMACおよびデータフレームタイプのような情報を含む.
ec_のロードgeneric.koモジュールは、ネットワーク構成が完了すると、マスタ局がネットワークデバイスを使用して通信することができ、ec_generic.koモジュールの初期化の最後に、ホスト局の送信、受信のコールバック関数を設定し、ホスト局を空き段階に切り替えた(これまでホスト局は孤児段階だった).次に、プライマリ・ステーションのアイドル・スレッド関数を開きます./master/master.c/ec_master_idle_thread().