MAX11300 是一款功能豐富的資料採集晶片,除了 ADC 和 DAC 功能外,也整合了 GPIO 控制功能。本文除了探討 GPIO 的基本操作,更進一步分析其在工業 I/O 子系統中的應用,特別是如何透過 Linux 核心提供的 IIO 框架實作資料採集和控制。理解這些底層機制對於開發和除錯根據 MAX11300 的嵌入式系統至關重要,能有效提升系統效能和穩定性。
MAX11300 GPIO 控制器的實作與解析
MAX11300 是一款多功能的數模轉換器,內建 GPIO 功能。本文將探討 MAX11300 GPIO 控制器的實作細節,包括其初始化、輸入輸出組態、以及資料讀寫等關鍵功能。
GPIO 初始化流程
在 MAX11300 驅動程式中,GPIO 控制器的初始化由 max11300_gpio_init 函式負責。該函式主要完成以下任務:
- 設定
gpiochip結構的各項屬性,如標籤、GPIO 數量、父裝置等。 - 指定 GPIO 操作的回呼函式,包括
direction_input、direction_output、get和set。 - 初始化 GPIO 鎖,以確保對 GPIO 操作的互斥存取。
- 註冊
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);
}
內容解密:
- 檢查
st->num_gpios是否為零,若是則直接傳回,避免無謂的初始化。 - 設定
gpiochip的標籤為 “gpio-max11300”,並指定其父裝置為st->dev。 - 設定 GPIO 操作的回呼函式,分別對應輸入輸出組態、資料讀寫等功能。
- 初始化
st->gpio_lock,以確保對 GPIO 操作的執行緒安全。 - 呼叫
gpiochip_add_data將gpiochip註冊到核心。
GPIO 輸入輸出組態
MAX11300 的 GPIO 輸入輸出組態由 max11300_gpio_direction_input 和 max11300_gpio_direction_output 兩個函式負責。這些函式主要完成以下任務:
- 設定 GPIO 腳位的模式(輸入或輸出)。
- 組態相關的暫存器,以控制 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 的輸入電壓門檻,並將腳位組態為 GPI 模式。
- 在輸出組態函式中,設定輸出高電平,並將腳位組態為 GPO 模式。
- 使用互斥鎖確保對 GPIO 操作的執行緒安全。
GPIO 資料讀寫
MAX11300 的 GPIO 資料讀寫由 max11300_gpio_get 和 max11300_gpio_set 兩個函式負責。這些函式主要完成以下任務:
- 讀取或設定 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);
}
內容解密:
- 在讀取函式中,從相關暫存器讀取 GPIO 的值,並傳回。
- 在寫入函式中,根據給定的值設定 GPIO 的輸出。
- 使用互斥鎖確保對 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;
// 其他模式的組態
}
}
#### 內容解密:
此段程式碼迴圈遍歷所有埠,根據不同的埠模式進行相應的組態。主要涉及以下步驟:
- 根據埠模式選擇合適的組態邏輯。
- 計算暫存器地址和組態值。
- 寫入暫存器以完成組態。
- 使用
dev_info記錄除錯資訊。
讀寫操作
驅動程式提供了max11300_read_adc和max11300_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資料。主要步驟包括:
- 判斷通道是否為輸出通道以及工作模式。
- 根據工作模式選擇合適的讀取邏輯(單端或差分)。
- 呼叫底層暫存器讀取函式取得資料。
- 傳回資料或錯誤碼。
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暫存器。主要步驟包括:
- 檢查通道是否為輸出通道。
- 加鎖以確保執行緒安全。
- 呼叫底層暫存器寫入函式完成資料寫入。
- 解鎖並傳回結果。
通道設定
驅動程式為不同的工作模式定義了相應的通道設定函式,如max11300_setup_port_5_mode、max11300_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;
// ...
}
#### 內容解密:
此類別函式負責設定特定工作模式下的通道屬性。主要包括:
- 設定通道型別為電壓。
- 設定通道索引和地址。
- 設定輸出屬性和其他相關屬性。
- 定義通道的掃描型別和副檔名稱。