1. 程式人生 > >Etherlab原始碼解析----master狀態機

Etherlab原始碼解析----master狀態機

Etherlab掃描和配置從站均由狀態機相關程式碼完成,本文介紹其基本工作原理。

1、ec_fsm_master 結構體

ec_fsm_master是一個狀態機實現過程中非常重要的結構體:

struct ec_fsm_master {
    ec_master_t *master; /**< master the FSM runs on */
    ec_datagram_t *datagram; /**< datagram used in the state machine */
    unsigned int retries; /**< retries on datagram timeout. */
void (*state)(ec_fsm_master_t *); /**< master state function */ ...... };

其中:
(1) 結構體成員*datagram為一個報文指標,指向master->fsm_datagram;
(2) 結構體成員(*state)為函式指標,狀態切換中指向不同的狀態機函式。

2、狀態機報文

狀態機使用master結構體的成員fsm_datagram作為狀態機實現的載體。

2.1 初始化報文

在master.c中的ec_master_init()函式中完成fsm_datagram的初始化和分配記憶體空間:

int ec_master_init(ec_master_t *master, /**< EtherCAT master */
        )
{
   ......

   // init state machine datagram
   ec_datagram_init(&master->fsm_datagram);
   ret = ec_datagram_prealloc(&master->fsm_datagram, EC_MAX_DATA_SIZE);  

   ......

}

2.2 指標賦值

在Fsm_master.c檔案的ec_fsm_master_init()函式中將ec_fsm_master的結構體成員*datagram指向fsm_datagram:

void ec_fsm_master_init(
        )
{
    fsm->master = master;
    fsm->datagram = datagram; //指向fsm_datagram

    ......    
}

2.3 填充報文

在狀態機函式中給fsm_datagram賦值,例如在ec_fsm_master_state_start()中讀130暫存器的報文:
void ec_fsm_master_state_start(
ec_fsm_master_t fsm /*< Master state machine. */
)
{
fsm->idle = 1;
ec_datagram_brd(fsm->datagram, 0x0130, 2); //fsm_datagram為廣播讀130暫存器報文。
}

2.4 傳送報文

在ec_master_idle_thread()函式中放入傳送佇列併發送出去:

   if (fsm_exec) {
      ec_master_queue_datagram(master, &master->fsm_datagram);
   }
   ecrt_master_send(master);

通過wireshark抓包工具抓到對應的報文如下:
這裡寫圖片描述

3、函式呼叫關係

以IDLE狀態為例,狀態機週期性呼叫關係如下所示:
這裡寫圖片描述
其中ec_master_idle_thread()的呼叫週期與系統滴答頻率有關:

// send interval in IDLE phase
ec_master_set_send_interval(master, 1000000 / HZ);

4、子狀態機

fsm_master狀態機包含若干子狀態機,例如從站掃描子狀態機,當Etherlab掃描從站時,主狀態機將一直停留在ec_fsm_master_state_scan_slave子狀態,直到掃描完成,在此期間,狀態機實際執行的是Fsm_slave_scan.c中的各函式(掃描從站)。