返回文章列表

MAX11300 GPIO 與工業I/O子系統驅動解析

本文深入解析 MAX11300 驅動程式中 GPIO 與工業 I/O 子系統的實作細節,包含 GPIO 初始化流程、輸入輸出組態、資料讀寫,以及工業 I/O 子系統中的埠組態、ADC/DAC 資料讀寫和通道設定。文章詳細說明瞭驅動程式如何與 Linux 核心互動,以及如何透過 iio_dev

嵌入式系統 驅動程式開發

MAX11300 是一款功能豐富的資料採集晶片,除了 ADC 和 DAC 功能外,也整合了 GPIO 控制功能。本文除了探討 GPIO 的基本操作,更進一步分析其在工業 I/O 子系統中的應用,特別是如何透過 Linux 核心提供的 IIO 框架實作資料採集和控制。理解這些底層機制對於開發和除錯根據 MAX11300 的嵌入式系統至關重要,能有效提升系統效能和穩定性。

MAX11300 GPIO 控制器的實作與解析

MAX11300 是一款多功能的數模轉換器,內建 GPIO 功能。本文將探討 MAX11300 GPIO 控制器的實作細節,包括其初始化、輸入輸出組態、以及資料讀寫等關鍵功能。

GPIO 初始化流程

在 MAX11300 驅動程式中,GPIO 控制器的初始化由 max11300_gpio_init 函式負責。該函式主要完成以下任務:

  1. 設定 gpiochip 結構的各項屬性,如標籤、GPIO 數量、父裝置等。
  2. 指定 GPIO 操作的回呼函式,包括 direction_inputdirection_outputgetset
  3. 初始化 GPIO 鎖,以確保對 GPIO 操作的互斥存取。
  4. 註冊 gpiochip 到核心。

程式碼解析

static int max11300_gpio_init(struct max11300_state *st)
{
    if (!st->num_gpios)
        return 0;

    st->gpiochip.label = "gpio-max11300";
    st->gpiochip.base = -1;
    st->gpiochip.ngpio = st->num_gpios;
    st->gpiochip.parent = st->dev;
    st->gpiochip.can_sleep = true;
    st->gpiochip.direction_input = max11300_gpio_direction_input;
    st->gpiochip.direction_output = max11300_gpio_direction_output;
    st->gpiochip.get = max11300_gpio_get;
    st->gpiochip.set = max11300_gpio_set;
    st->gpiochip.owner = THIS_MODULE;

    mutex_init(&st->gpio_lock);

    return gpiochip_add_data(&st->gpiochip, st);
}

內容解密:

  1. 檢查 st->num_gpios 是否為零,若是則直接傳回,避免無謂的初始化。
  2. 設定 gpiochip 的標籤為 “gpio-max11300”,並指定其父裝置為 st->dev
  3. 設定 GPIO 操作的回呼函式,分別對應輸入輸出組態、資料讀寫等功能。
  4. 初始化 st->gpio_lock,以確保對 GPIO 操作的執行緒安全。
  5. 呼叫 gpiochip_add_datagpiochip 註冊到核心。

GPIO 輸入輸出組態

MAX11300 的 GPIO 輸入輸出組態由 max11300_gpio_direction_inputmax11300_gpio_direction_output 兩個函式負責。這些函式主要完成以下任務:

  1. 設定 GPIO 腳位的模式(輸入或輸出)。
  2. 組態相關的暫存器,以控制 GPIO 的行為。

程式碼解析

static int max11300_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
    struct max11300_state *st = gpiochip_get_data(chip);
    int ret;
    u8 reg;
    u16 port_mode, val;

    mutex_lock(&st->gpio_lock);

    // 設定邏輯 1 的輸入電壓門檻為 2.5V 以上
    val = 0x0fff;
    reg = PORT_DAC_DATA_BASE_ADDRESS + st->gpio_offset[offset];
    ret = st->ops->reg_write(st, reg, val);

    // 組態腳位為 GPI 模式
    reg = PORT_CFG_BASE_ADDRESS + st->gpio_offset[offset];
    port_mode = (1 << 12);
    ret = st->ops->reg_write(st, reg, port_mode);

    mutex_unlock(&st->gpio_lock);
    return ret;
}

static int max11300_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value)
{
    struct max11300_state *st = gpiochip_get_data(chip);
    int ret;
    u8 reg;
    u16 port_mode, val;

    mutex_lock(&st->gpio_lock);

    // 設定輸出高電平為 3.3V
    val = 0x0547;
    reg = PORT_DAC_DATA_BASE_ADDRESS + st->gpio_offset[offset];
    ret = st->ops->reg_write(st, reg, val);

    // 組態腳位為 GPO 模式
    reg = PORT_CFG_BASE_ADDRESS + st->gpio_offset[offset];
    port_mode = (3 << 12);
    ret = st->ops->reg_write(st, reg, port_mode);

    mutex_unlock(&st->gpio_lock);
    max11300_gpio_set(chip, offset, value);
    return ret;
}

內容解密:

  1. 在輸入組態函式中,設定邏輯 1 的輸入電壓門檻,並將腳位組態為 GPI 模式。
  2. 在輸出組態函式中,設定輸出高電平,並將腳位組態為 GPO 模式。
  3. 使用互斥鎖確保對 GPIO 操作的執行緒安全。

GPIO 資料讀寫

MAX11300 的 GPIO 資料讀寫由 max11300_gpio_getmax11300_gpio_set 兩個函式負責。這些函式主要完成以下任務:

  1. 讀取或設定 GPIO 腳位的值。

程式碼解析

static int max11300_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
    struct max11300_state *st = gpiochip_get_data(chip);
    int ret;
    u8 reg;
    unsigned int val;

    mutex_lock(&st->gpio_lock);

    reg = GPI_DATA_15_TO_0_ADDRESS;
    ret = st->ops->reg_read(st, reg, &read_val);
    val = (int) read_val;

    if (val & BIT(st->gpio_offset[offset]))
        val = 1;
    else
        val = 0;

    mutex_unlock(&st->gpio_lock);
    return val;
}

static void max11300_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
    struct max11300_state *st = gpiochip_get_data(chip);
    u8 reg;
    unsigned int val = 0;

    mutex_lock(&st->gpio_lock);

    if (value == 1)
        val |= BIT(st->gpio_offset[offset]);
    else
        val &= ~BIT(st->gpio_offset[offset]);

    reg = (st->gpio_offset[offset] > 0x0F) ? GPO_DATA_19_TO_16_ADDRESS : GPO_DATA_15_TO_0_ADDRESS;
    st->ops->reg_write(st, reg, val);

    mutex_unlock(&st->gpio_lock);
}

內容解密:

  1. 在讀取函式中,從相關暫存器讀取 GPIO 的值,並傳回。
  2. 在寫入函式中,根據給定的值設定 GPIO 的輸出。
  3. 使用互斥鎖確保對 GPIO 操作的執行緒安全。

工業I/O子系統中MAX11300驅動程式的實作與分析

MAX11300是一款高度整合的資料採集系統,具有多種工作模式和可組態的埠。本文將探討MAX11300驅動程式在工業I/O子系統中的實作,重點分析其組態、讀寫操作以及通道設定的細節。

MAX11300驅動程式的核心功能

MAX11300驅動程式的核心功能包括組態裝置埠、讀取ADC資料以及寫入DAC資料。驅動程式透過iio_dev結構體與工業I/O子系統互動,實作使用者空間與硬體之間的資料交換。

埠組態

驅動程式根據不同的埠模式(PORT_MODE_5至PORT_MODE_10)進行相應的組態。每種模式對應不同的硬體操作和資料處理方式。組態過程涉及暫存器寫入和引數設定,如ADC參考電壓、DAC範圍等。

for (i = 0; i < st->num_ports; i++) {
    switch (st->port_modes[i]) {
        case PORT_MODE_5:
        case PORT_MODE_6:
            // 組態PORT_MODE_5和PORT_MODE_6
            reg = PORT_CFG_BASE_ADDRESS + i;
            adc_reference = st->adc_reference[i];
            port_mode = (st->port_modes[i] << 12);
            dac_range = (st->dac_range[i] << 8);
            // ...
            break;
        // 其他模式的組態
    }
}

#### 內容解密:

此段程式碼迴圈遍歷所有埠,根據不同的埠模式進行相應的組態。主要涉及以下步驟:

  1. 根據埠模式選擇合適的組態邏輯。
  2. 計算暫存器地址和組態值。
  3. 寫入暫存器以完成組態。
  4. 使用dev_info記錄除錯資訊。

讀寫操作

驅動程式提供了max11300_read_adcmax11300_write_dac兩個函式,分別用於讀取ADC資料和寫入DAC資料。

ADC讀取

static int max11300_read_adc(struct iio_dev *iio_dev,
                             struct iio_chan_spec const *chan,
                             int *val, int *val2, long m)
{
    // ...
    switch (m) {
        case IIO_CHAN_INFO_RAW:
            if (!chan->output && ((chan->address == PORT_MODE_7) || (chan->address == PORT_MODE_6))) {
                ret = st->ops->reg_read(st, reg, &read_val_se);
                // ...
            }
            // ...
            break;
        default:
            ret = -EINVAL;
    }
    // ...
}

#### 內容解密:

此函式根據通道屬性和工作模式讀取ADC資料。主要步驟包括:

  1. 判斷通道是否為輸出通道以及工作模式。
  2. 根據工作模式選擇合適的讀取邏輯(單端或差分)。
  3. 呼叫底層暫存器讀取函式取得資料。
  4. 傳回資料或錯誤碼。

DAC寫入

static int max11300_write_dac(struct iio_dev *iio_dev, struct iio_chan_spec const *chan,
                              int val, int val2, long mask)
{
    // ...
    switch (mask) {
        case IIO_CHAN_INFO_RAW:
            if (!chan->output)
                return -EINVAL;
            mutex_lock(&iio_dev->mlock);
            ret = st->ops->reg_write(st, reg, val);
            mutex_unlock(&iio_dev->mlock);
            break;
        default:
            return -EINVAL;
    }
    return ret;
}

#### 內容解密:

此函式將使用者提供的資料寫入DAC暫存器。主要步驟包括:

  1. 檢查通道是否為輸出通道。
  2. 加鎖以確保執行緒安全。
  3. 呼叫底層暫存器寫入函式完成資料寫入。
  4. 解鎖並傳回結果。

通道設定

驅動程式為不同的工作模式定義了相應的通道設定函式,如max11300_setup_port_5_modemax11300_setup_port_7_mode等。這些函式初始化iio_chan_spec結構體,定義了通道的屬性,如型別、索引、輸出屬性等。

static void max11300_setup_port_5_mode(struct iio_dev *iio_dev,
                                       struct iio_chan_spec *chan, bool output,
                                       unsigned int id, unsigned long port_mode)
{
    chan->type = IIO_VOLTAGE;
    chan->indexed = 1;
    chan->address = port_mode;
    chan->output = output;
    chan->channel = id;
    // ...
}

#### 內容解密:

此類別函式負責設定特定工作模式下的通道屬性。主要包括:

  1. 設定通道型別為電壓。
  2. 設定通道索引和地址。
  3. 設定輸出屬性和其他相關屬性。
  4. 定義通道的掃描型別和副檔名稱。