MAX11300 是一款多功能工業 I/O 晶片,具備 ADC、DAC 和 GPIO 等功能。本文分析其 Linux 驅動程式,著重於裝置樹的埠組態、I/O 通道分配,以及不同工作模式的設定。驅動程式利用 max11300_alloc_ports 函式,根據裝置樹中各埠的組態屬性,設定對應的 ADC、DAC 或 GPIO 模式。針對 ADC 和 DAC,驅動程式會讀取參考電壓、取樣率等引數;而 GPIO 則會記錄埠編號和模式,供後續操作使用。此外,max11300_setup_port_8_mode 等函式則負責設定 IIO 通道規格,例如通道型別、資料格式和位元組序等。理解這些核心功能,有助於開發者更有效地整合 MAX11300 至工業 I/O 系統。
MAX11300 工業I/O子系統驅動分析與實作
MAX11300是一款高度可組態的工業I/O裝置,支援多種工作模式,包括ADC、DAC、GPIO等功能。本文將深入分析其驅動程式的實作,特別是在工業I/O子系統中的整合。
MAX11300 埠組態與I/O通道分配
驅動程式透過max11300_alloc_ports函式來分配並組態I/O通道。此函式會遍歷裝置樹中的子節點,並根據每個埠的組態屬性進行相應的設定。
程式碼解析
static int max11300_alloc_ports(struct max11300_state *st)
{
unsigned int i, curr_port = 0, num_ports = st->num_ports, port_mode_6_count = 0, offset = 0;
struct iio_dev *iio_dev = iio_priv_to_dev(st);
struct iio_chan_spec *ports;
struct fwnode_handle *child;
u32 reg, tmp;
int ret;
device_for_each_child_node(st->dev, child) {
ret = fwnode_property_read_u32(child, "reg", ®);
if (ret || reg >= ARRAY_SIZE(st->port_modes))
continue;
ret = fwnode_property_read_u32(child, "port-mode", &tmp);
if (!ret)
st->port_modes[reg] = tmp;
else {
dev_info(st->dev, "port mode is not found\n");
continue;
}
// 根據不同的埠模式進行相應的屬性讀取與設定
switch (st->port_modes[reg]) {
case PORT_MODE_7:
// 設定ADC相關屬性
break;
case PORT_MODE_8:
// 設定ADC相關屬性及負輸入通道
ret = fwnode_property_read_u32(child, "negative-input", &tmp);
if (!ret)
st->adc_negative_port[reg] = tmp;
else {
dev_info(st->dev, "Bad value for negative ADC channel\n");
return -EINVAL;
}
break;
case PORT_MODE_9: case PORT_MODE_10:
// 設定ADC相關屬性
break;
case PORT_MODE_5: case PORT_MODE_6:
// 設定DAC相關屬性
if ((st->port_modes[reg]) == PORT_MODE_6) {
port_mode_6_count++;
dev_info(st->dev, "there are %d channels in mode_6\n", port_mode_6_count);
}
break;
case PORT_MODE_1:
// 設定GPIO輸入模式
st->gpio_offset[offset] = reg;
st->gpio_offset_mode[offset] = PORT_MODE_1;
offset++;
st->num_gpios++;
break;
case PORT_MODE_3:
// 設定GPIO輸出模式
st->gpio_offset[offset] = reg;
st->gpio_offset_mode[offset] = PORT_MODE_3;
offset++;
st->num_gpios++;
break;
}
}
}
內容解密:
- 裝置樹遍歷:使用
device_for_each_child_node宏遍歷裝置樹中的每個子節點,並讀取reg屬性以確定埠編號。 - 埠模式設定:根據
port-mode屬性設定埠的工作模式,並根據不同模式讀取相應的組態屬性。 - ADC/DAC屬性設定:針對不同的埠模式,讀取並設定相關的ADC或DAC屬性,如參考電壓、取樣率等。
- GPIO組態:將組態為GPIO模式的埠進行編號並儲存其模式,用於後續的GPIO操作。
IIO通道規格設定
max11300_setup_port_8_mode函式用於設定特定埠模式下的IIO通道規格。
程式碼解析
static void max11300_setup_port_8_mode(struct iio_dev *iio_dev,
struct iio_chan_spec *chan, bool output,
unsigned id, unsigned id2,
unsigned int port_mode)
{
chan->type = IIO_VOLTAGE;
chan->differential = 1;
chan->address = port_mode;
chan->indexed = 1;
chan->output = output;
chan->channel = id;
chan->channel2 = id2;
chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
chan->scan_type.sign = 's';
chan->scan_type.realbits = 12;
chan->scan_type.storagebits = 16;
chan->scan_type.endianness = IIO_BE;
chan->extend_name = "mode_8_ADC";
}
內容解密:
- 通道型別設定:將通道型別設為
IIO_VOLTAGE,並標記為差分模式。 - 位元組儲存設定:設定資料儲存格式為大端序(
IIO_BE),實際位元數為12位,儲存位元數為16位。 - 通道資訊遮罩:設定
info_mask_separate以支援原始資料讀取。 - 副檔名稱:為通道設定副檔名稱,以便於識別其功能。
MAX11300 多埠轉換器驅動程式解析
MAX11300 是一款由 Maxim 提供的多功能、多埠轉換器,廣泛應用於工業自動化、資料採集等領域。本文將深入分析 MAX11300 的 Linux 驅動程式原始碼,探討其核心功能實作、裝置初始化流程以及 IIO 子系統的整合。
驅動程式核心結構
MAX11300 驅動程式的核心結構主要包括以下幾個部分:
- 裝置結構體 (
struct max11300_state):用於儲存裝置的相關資訊,如裝置指標、操作函式集等。 - IIO 裝置結構體 (
struct iio_dev):代表一個 IIO 裝置,包含了裝置的通道資訊、操作介面等。 - 通道設定函式 (
max11300_setup_port_*_mode):根據不同的埠模式(PORT_MODE_*)設定通道屬性。
裝置初始化流程
MAX11300 裝置的初始化流程主要在 max11300_probe 函式中完成,主要步驟包括:
- 分配 IIO 裝置記憶體:使用
devm_iio_device_alloc分配 IIO 裝置結構體記憶體。 - 初始化裝置結構體:將裝置指標、操作函式集等資訊儲存到
struct max11300_state中。 - 重設裝置:透過寫入
DCR_ADDRESS暫存器,將裝置重設為預設狀態。 - 讀取裝置 ID:讀取裝置 ID 以驗證裝置是否正常。
- 組態 DACREF 和 ADCCTL:設定 DACREF 和 ADCCTL 暫存器,以組態裝置的工作模式。
- 組態 IIO 通道:呼叫
max11300_alloc_ports和max11300_set_port_modes組態 IIO 通道屬性。
程式碼實作
int max11300_probe(struct device *dev, const char *name, const struct max11300_rw_ops *ops)
{
// ...
/* 分配 IIO 裝置記憶體 */
iio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!iio_dev)
return -ENOMEM;
/* 初始化裝置結構體 */
st = iio_priv(iio_dev);
st->dev = dev;
st->ops = ops;
// ...
/* 重設裝置 */
reg = DCR_ADDRESS;
write_val = RESET;
ret = ops->reg_write(st, reg, write_val);
if (ret != 0)
goto error;
// ...
/* 組態 IIO 通道 */
ret = max11300_alloc_ports(st);
if (ret)
goto error;
ret = max11300_set_port_modes(st);
if (ret)
goto error_reset_device;
// ...
}
內容解密:
max11300_probe函式是裝置驅動程式的核心入口點,負責初始化 MAX11300 裝置。- 使用
devm_iio_device_alloc分配 IIO 裝置記憶體,並將裝置指標和操作函式集儲存到struct max11300_state中。 - 重設裝置並讀取裝置 ID 以驗證裝置是否正常。
- 組態 DACREF 和 ADCCTL 暫存器,以設定裝置的工作模式。
- 呼叫
max11300_alloc_ports和max11300_set_port_modes組態 IIO 通道屬性。
IIO 子系統整合
MAX11300 驅動程式透過 IIO 子系統提供與使用者空間的介面,主要涉及以下幾個方面:
- IIO 裝置註冊:使用
iio_device_register將 IIO 裝置註冊到 IIO 子系統中。 - 通道屬性組態:透過
max11300_alloc_ports和max11300_set_port_modes組態通道屬性,如通道型別、方向等。
程式碼實作
int max11300_alloc_ports(struct max11300_state *st)
{
// ...
/* 組態通道屬性 */
for (i = 0; i < num_ports; i++) {
switch (st->port_modes[i]) {
case PORT_MODE_5:
max11300_setup_port_5_mode(iio_dev, &ports[curr_port], true, i, PORT_MODE_5);
curr_port++;
break;
// ...
}
}
// ...
}
內容解密:
max11300_alloc_ports函式負責組態 IIO 通道的屬性。- 根據不同的埠模式(PORT_MODE_*),呼叫相應的通道設定函式(如
max11300_setup_port_5_mode)來設定通道屬性。 - 將組態好的通道屬性儲存到
struct iio_chan_spec結構體中。
工業I/O子系統中的GPIO控制與MAX11300裝置驅動驗證
在工業I/O子系統中,GPIO(General Purpose Input/Output)控制是重要的介面之一。Linux核心提供了libgpiod函式庫來與GPIO字元裝置互動,取代了從Linux 4.8開始被棄用的GPIO sysfs介面。本章節將介紹如何使用libgpiod工具來控制GPIO,並以MAX11300裝置驅動為例進行驗證。
安裝libgpiod函式庫和工具
首先,需要在Raspberry Pi上安裝libgpiod函式庫和工具。透過以下指令可以完成安裝:
sudo apt-get install gpiod libgpiod-dev libgpiod-doc
安裝完成後,可以使用libgpiod提供的六個命令列工具來存取GPIO驅動程式:
gpiodetect:列出系統中所有gpiochips的名稱、標籤和GPIO線路數量。gpioinfo:列出指定gpiochips的所有線路名稱、消費者、方向、活動狀態和其他旗標。gpioget:讀取指定GPIO線路的值。gpioset:設定指定GPIO線路的值。gpiofind:根據線路名稱查詢gpiochip名稱和線路偏移。gpiomon:等待GPIO線路上的事件,並指定要監控的事件。
MAX11300裝置驅動驗證
載入模組:首先,需要載入MAX11300裝置驅動模組。
insmod max11300-base.ko insmod max11300.ko載入後,核心日誌將顯示MAX11300裝置的初始化過程,包括裝置ID的讀取和各通道的組態。
檢查裝置檔案:載入模組後,MAX11300裝置將在
/sys/bus/iio/devices/目錄下建立對應的裝置檔案。cd /sys/bus/iio/devices/iio:device0 ls列表中將顯示與MAX11300裝置相關的各個通道檔案,例如
in_voltage0_mode_7_ADC_raw和out_voltage2_mode_5_DAC_raw。DAC輸出與ADC讀取驗證:將port2(DAC)連線到port0(ADC),並進行以下操作:
- 寫入DAC值:這將設定DAC輸出值,核心日誌將顯示相關的暫存器操作。
echo 500 > out_voltage2_mode_5_DAC_raw - 讀取ADC值:這將讀取ADC的值,理論上應該接近於之前設定的DAC值(500)。
cat in_voltage0_mode_7_ADC_raw
- 寫入DAC值:
程式碼解密:
上述步驟涉及的核心程式碼主要包括MAX11300裝置驅動的實作,涵蓋了SPI通訊、暫存器組態以及I/O操作的實作。具體來說:
max11300_probe()函式:負責初始化MAX11300裝置,包括讀取裝置ID、組態各個通道的工作模式等。out_voltage2_mode_5_DAC_raw和in_voltage0_mode_7_ADC_raw檔案操作:對應於DAC輸出和ADC讀取的操作,分別呼叫驅動程式中的寫DAC暫存器和讀ADC暫存器的函式。
透過以上實驗和程式碼分析,可以驗證MAX11300裝置驅動的正確性和libgpiod工具的有效性,為工業I/O子系統的開發和除錯提供了有力的支援。