SGM58031是一款低功耗、高精度的16位Σ-Δ型I2C接口ADC芯片,廣泛應(yīng)用于工業(yè)采集、消費(fèi)電子、醫(yī)療設(shè)備等場(chǎng)景。在Linux 6.1系統(tǒng)下適配該芯片驅(qū)動(dòng)時(shí),常遇到“iio_trigger_alloc ID錯(cuò)誤”“remove函數(shù)返回值不兼容”“I2C驅(qū)動(dòng)超時(shí)”“i2ctool讀取值跳變不真實(shí)”“ADC采樣值無(wú)變化”等問(wèn)題。本文結(jié)合實(shí)戰(zhàn)調(diào)試經(jīng)驗(yàn),從芯片基礎(chǔ)特性、Linux 6.1驅(qū)動(dòng)適配、編譯排錯(cuò)、設(shè)備樹(shù)配置、驅(qū)動(dòng)節(jié)點(diǎn)操作、寄存器讀取、實(shí)戰(zhàn)調(diào)試維度,系統(tǒng)講解SGM58031的全流程調(diào)試方法。

一、SGM58031芯片基礎(chǔ)特性
1.1通道特性

SGM58031支持單端/差分輸入模式,核心輸入通道配置如下:
?差分通道:AIN0(+)-AIN1(-)、AIN0(+)-AIN3(-)、AIN1(+)-AIN3(-)、AIN2(+)-AIN3(-),適用于高精度小信號(hào)采集;
?單端通道:AIN0-GND、AIN1-GND、AIN2-GND、AIN3-GND,參考地為芯片GND;
?輸入范圍:由內(nèi)部PGA(可編程增益放大器)和參考電壓共同決定,具體見(jiàn)下表。
1.2增益配置(與數(shù)據(jù)手冊(cè)一致)
SGM58031內(nèi)置可編程增益放大器(PGA),增益檔位由CONFIG寄存器的PGA位段配置,核心檔位與滿(mǎn)量程(FS)對(duì)應(yīng)關(guān)系如下(基于內(nèi)部參考電壓):
| PGA Setting | 對(duì)應(yīng)量程(FS, V) | 適用場(chǎng)景 |
| 2/3 | ±6.144V | 大信號(hào)采集(最大輸入范圍) |
| 1 | ±4.096V | 大信號(hào)采集 |
| 2 | ±2.048V | 中等信號(hào)采集 |
| 4 | ±1.024V | 小信號(hào)采集 |
| 8 | ±0.512V | 微伏級(jí)小信號(hào)高精度采集 |
| 16 | ±0.256V | 超小信號(hào)高精度采集 |
注:模擬輸入電壓不得超過(guò)滿(mǎn)量程限制,否則會(huì)導(dǎo)致ADC飽和,采樣值固定為±32767。
1.3核心寄存器說(shuō)明
SGM58031的寄存器地址寬度為8位,數(shù)據(jù)寬度為16位,核心寄存器功能如下:
| 寄存器地址 | 名稱(chēng) | 核心功能 |
| 0x00 | CONV_REG | 存儲(chǔ)最新16位ADC轉(zhuǎn)換結(jié)果,只讀 |
| 0x01 | CONFIG_REG | 配置采樣模式、增益、采樣率、通道選擇、轉(zhuǎn)換模式(單次/連續(xù)),讀寫(xiě) |
| 0x02 | LOW_THRESH | 低閾值寄存器,用于比較器功能配置 |
| 0x03 | HIGH_THRESH | 高閾值寄存器,用于比較器功能配置 |
| 0x04 | CONFIG2 | 擴(kuò)展配置寄存器,配置參考電壓、休眠模式等 |
| 0x05 | ID_REG | 芯片ID寄存器,固定值0x5803(只讀,用于識(shí)別芯片) |
二、Linux 6.1驅(qū)動(dòng)適配篇:核心API兼容修改
Linux 6.1內(nèi)核對(duì)IIO子系統(tǒng)的部分API做了調(diào)整,SGM58031驅(qū)動(dòng)需針對(duì)性修改以適配,核心修改點(diǎn)包含以下兩項(xiàng):
2.1 iio_trigger_alloc ID參數(shù)錯(cuò)誤修復(fù)
問(wèn)題現(xiàn)象
編譯過(guò)程中出現(xiàn)類(lèi)似報(bào)錯(cuò):
error: invalid argumenttypeforiio_trigger_alloc, expected deviceidtypebut got xxx
報(bào)錯(cuò)原因是Linux 6.1對(duì)devm_iio_trigger_alloc的dev%d參數(shù)要求使用iio_device_id(indio_dev)獲取合法設(shè)備ID,而非自定義數(shù)值。
修復(fù)代碼
// 僅修改ID參數(shù),保留原有邏輯data->trig = devm_iio_trigger_alloc(dev,"%s-dev%d", indio_dev->name, iio_device_id(indio_dev));
2.2 remove函數(shù)返回值調(diào)整為void類(lèi)型
問(wèn)題現(xiàn)象
編譯時(shí)出現(xiàn)返回值不兼容報(bào)錯(cuò):
error: conflicting typesfor'sgm58031_remove'; have'int(struct i2c_client *)'but expected'void(struct i2c_client *)'
修復(fù)代碼
staticvoidsgm58031_remove(struct i2c_client *client){dev_info(&client->dev,"SGM58031 driver unloadedn");}
配套修改:驅(qū)動(dòng)注冊(cè)結(jié)構(gòu)體
staticstructi2c_driver sgm58031_driver = { .driver = { .name ="sgm58031", .of_match_table = sgm58031_of_match, }, .probe = sgm58031_probe, .remove= sgm58031_remove,// 匹配void類(lèi)型的remove函數(shù) .id_table = sgm58031_id,};module_i2c_driver(sgm58031_driver);
三、編譯篇:驅(qū)動(dòng)編譯報(bào)錯(cuò)排查與解決
3.1常見(jiàn)編譯報(bào)錯(cuò)類(lèi)型及解決思路
1.函數(shù)指針類(lèi)型不兼容:incompatible pointer type 'sgm58031_read_raw'
?解決方式:確保回調(diào)函數(shù)簽名與IIO子系統(tǒng)要求一致。
2.Linux 6.1特有報(bào)錯(cuò):
?iio_trigger_alloc ID錯(cuò)誤:使用iio_device_id(indio_dev)替換自定義ID參數(shù);
?remove函數(shù)返回值不兼容:將remove函數(shù)調(diào)整為void類(lèi)型,無(wú)返回值。
四、設(shè)備樹(shù)篇:I2C與SGM58031配置詳解
4.1 I2C控制器配置(以RK3588的i2c4為例)
&i2c4 { status ="okay"; pinctrl-names ="default"; pinctrl-0= <&i2c8m2_xfer>; clock-frequency = <100000>;
sgm58031@48{ compatible ="sgmicro,sgm58031"; reg = <0x48>; default-gain = <0>; // 默認(rèn)增益1倍(對(duì)應(yīng)±4.096V量程) status ="okay"; };};
4.2引腳配置(pinctrl)與內(nèi)部上拉
i2c8m2_xfer: i2c8m2-xfer { rockchip,pins = ? ? ? <1?RK_PD6?9?&pcfg_pull_up_smt>, // SCL引腳,開(kāi)啟內(nèi)部上拉 <1?RK_PD7?9?&pcfg_pull_up_smt> // SDA引腳,開(kāi)啟內(nèi)部上拉 >;};
4.3引腳占用檢查
通過(guò)以下命令查看引腳復(fù)用狀態(tài),確認(rèn)I2C引腳未被其他外設(shè)占用:
cat/sys/kernel/debug/gpiocat/sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins
五、驅(qū)動(dòng)節(jié)點(diǎn)操作與配置(sysfs接口)
SGM58031驅(qū)動(dòng)適配Linux IIO子系統(tǒng)后,所有配置和采樣操作均可通過(guò)/sys/bus/iio/devices/iio:device1/下的sysfs節(jié)點(diǎn)完成,以下是核心節(jié)點(diǎn)的操作方法:
5.1查看設(shè)備基本信息
# 進(jìn)入設(shè)備目錄cd/sys/bus/iio/devices/iio:device1/# 查看設(shè)備名稱(chēng)(確認(rèn)驅(qū)動(dòng)匹配成功)catname# 輸出:sgm58031
5.2讀取ADC采樣原始值
SGM58031提供4個(gè)差分通道和4個(gè)單端通道的原始采樣值,讀取方式如下:
# 讀取差分通道0(AIN0-AIN1)原始值catin_voltage0-voltage1_raw# 讀取單端通道0(AIN0-GND)原始值catin_voltage4_raw# 讀取單端通道1(AIN1-GND)原始值catin_voltage5_raw# 讀取單端通道2(AIN2-GND)原始值catin_voltage6_raw# 讀取單端通道3(AIN3-GND)原始值catin_voltage7_raw
注:原始值為16位有符號(hào)整數(shù),需結(jié)合增益(scale)換算為實(shí)際電壓。
5.3配置增益(量程)
增益(scale)決定ADC的輸入量程,操作方式如下:
# 查看支持的增益值(僅可寫(xiě)入這些值)catin_voltage_scale_available# 輸出:6144 4096 2048 1024 512 256(對(duì)應(yīng)PGA設(shè)置2/3、1、2、4、8、16)# 配置單端通道0(AIN0-GND)的增益為±4.096V(對(duì)應(yīng)值4096)echo4096 > in_voltage4_scale# 驗(yàn)證配置結(jié)果catin_voltage4_scale# 輸出:4.096000000(驅(qū)動(dòng)自動(dòng)換算為mV/LSB)
注:所有通道的增益配置是全局生效的,修改任意通道的scale節(jié)點(diǎn),所有通道的量程都會(huì)同步更新。
5.4設(shè)置采樣率
采樣率決定ADC的轉(zhuǎn)換速度,操作方式如下:
# 查看支持的采樣率catsampling_frequency_available# 輸出:6 12 25 50 100 200 400 800 960(單位:SPS)# 設(shè)置采樣率為100SPSecho100 > sampling_frequency# 驗(yàn)證配置結(jié)果catsampling_frequency# 輸出:100
5.5配置比較器功能
比較器用于觸發(fā)中斷,當(dāng)采樣值超出閾值時(shí)觸發(fā),操作方式如下:
# 設(shè)置比較器低閾值(十進(jìn)制16位值)echo128> comp_low_thresh# 設(shè)置比較器高閾值(十進(jìn)制16位值)echo256> comp_high_thresh# 配置比較器觸發(fā)隊(duì)列(0=1次超閾值觸發(fā),1=2次,2=4次,3=禁用)echo0> comp_queue
5.6設(shè)置轉(zhuǎn)換模式與特殊功能
# 設(shè)置轉(zhuǎn)換模式:0=連續(xù)轉(zhuǎn)換,1=單次轉(zhuǎn)換echo0> conv_mode# 配置外部參考電壓:0=內(nèi)部參考,1=外部參考(需硬件支持)echo0> ext_ref# 配置斷線檢測(cè)(Burnout):0=關(guān)閉,1=開(kāi)啟(用于檢測(cè)傳感器斷線)echo0> burnout# 配置I2C總線泄漏阻斷:0=關(guān)閉,1=開(kāi)啟(提升總線穩(wěn)定性)echo0> bus_leakage
六、寄存器篇:精準(zhǔn)讀取(內(nèi)核打印vs i2ctool)
6.1 i2ctool讀取寄存器值跳變、不真實(shí)的核心原因
核心原因是SGM58031單個(gè)寄存器地址存儲(chǔ)16位數(shù)據(jù),但i2ctool默認(rèn)按8位讀取,拆分讀取過(guò)程中易獲取無(wú)效值;輔助原因是i2ctool無(wú)鎖保護(hù),與驅(qū)動(dòng)并發(fā)讀寫(xiě)時(shí)會(huì)讀取到“半寫(xiě)”狀態(tài)的值,進(jìn)一步加劇數(shù)值跳變。
6.2解決方案:內(nèi)核驅(qū)動(dòng)中打印寄存器值
6.2.1內(nèi)核讀取函數(shù)(集成Linux 6.1適配,保留原有邏輯)
int readreg(struct iio_dev *indio_dev){ intval; struct sgm58031_data *data= iio_priv(indio_dev); u16 read_config = regmap_read(data->regmap, SGM58031_REG_CONFIG, &val);if(read_config 0) {dev_err(&data->client->dev,"Failed to read config: %dn", read_config);returnread_config;} printk("xsc config: 0x%02xn",val); read_config = regmap_read(data->regmap,2, &val);if(read_config 0) {dev_err(&data->client->dev,"Failed to read config: %dn", read_config);returnread_config;} printk("xsc 2: 0x%02xn",val); read_config = regmap_read(data->regmap,3, &val);if(read_config 0) {dev_err(&data->client->dev,"Failed to read config: %dn", read_config);returnread_config;} printk("xsc 3: 0x%02xn",val); read_config = regmap_read(data->regmap,4, &val);if(read_config 0) {dev_err(&data->client->dev,"Failed to read config: %dn", read_config);returnread_config;} printk("xsc 4: 0x%02xn",val); read_config = regmap_read(data->regmap,5, &val);if(read_config 0) {dev_err(&data->client->dev,"Failed to read config: %dn", read_config);returnread_config;} printk("xsc 5: 0x%02xn",val); read_config = regmap_read(data->regmap,0, &val);if(read_config 0) {dev_err(&data->client->dev,"Failed to read config: %dn", read_config);returnread_config;} printk("xsc 0: 0x%02xn",val); return0;}// probe函數(shù)中集成Linux 6.1的trigger修復(fù)static int sgm58031_probe(struct i2c_client *client, conststruct i2c_device_id *id){ // 原有probe邏輯 struct iio_dev *indio_dev = devm_iio_device_alloc(&client->dev, sizeof(struct sgm58031_data)); struct sgm58031_data *data= iio_priv(indio_dev);
// Linux 6.1 trigger修復(fù) data->trig = devm_iio_trigger_alloc(&client->dev,"%s-dev%d", indio_dev->name, iio_device_id(indio_dev)); // 調(diào)用寄存器讀取函數(shù) readreg(indio_dev); // 后續(xù)邏輯 return0;}// void類(lèi)型remove函數(shù)static void sgm58031_remove(struct i2c_client *client){dev_info(&client->dev,"SGM58031 driver unloadedn");}
6.2.2查看內(nèi)核打印日志
通過(guò)以下命令查看寄存器打印結(jié)果:
dmesg-w | grep"xsc"
輸出示例:
[ 650.016361]xsc config:0x4298[ 650.016400] xsc2:0x8000[ 650.016409] xsc3:0x7fff[ 650.016415] xsc4:0x00[ 650.016422] xsc5:0x80
6.3 i2ctool與內(nèi)核打印的核心對(duì)比
| 維度 | i2ctool(i2cget) | 內(nèi)核printk + regmap_read |
| 讀取寬度 | 默認(rèn)8位,易拆分/截?cái)?6位值 | 原生16位,匹配芯片架構(gòu) |
| 并發(fā)保護(hù) | 無(wú)鎖機(jī)制,數(shù)值易跳變 | 帶mutex_lock互斥鎖,讀取原子化 |
| 適用場(chǎng)景 | 快速驗(yàn)證設(shè)備是否在線 | 精準(zhǔn)調(diào)試寄存器配置 |
七、調(diào)試篇:從現(xiàn)象到根因(實(shí)戰(zhàn)案例)
7.1案例1:I2C驅(qū)動(dòng)超時(shí)
核心原因與解決方式
1.外部無(wú)上拉電阻:在SDA、SCL引腳各添加4.7kΩ上拉電阻,連接至3.3V電源;
2.內(nèi)部上拉未配置:在設(shè)備樹(shù)pinctrl節(jié)點(diǎn)中配置&pcfg_pull_up_smt屬性;
3.引腳占用:檢查設(shè)備樹(shù)中其他節(jié)點(diǎn)的pinctrl配置,修改或禁用占用I2C引腳的節(jié)點(diǎn)。
7.2案例2:i2ctool讀取值跳變
核心原因:SGM58031單個(gè)地址存儲(chǔ)16位值,i2ctool默認(rèn)按8位讀取,拆分讀取易獲取無(wú)效值;
解決方案:使用內(nèi)核函數(shù)readreg讀取寄存器值,通過(guò)regmap_read獲取完整16位值,避免數(shù)值跳變問(wèn)題。
7.3案例3:ADC采樣值始終無(wú)變化
現(xiàn)象
驅(qū)動(dòng)加載正常、I2C通訊無(wú)異常,但改變輸入電壓后,CONV_REG(0x00)的采樣值始終固定,無(wú)任何變化。
排查過(guò)程
1.寄存器配置核查:讀取CONFIG_REG確認(rèn)通道選擇、增益、轉(zhuǎn)換模式(連續(xù)模式)配置正確;
2.時(shí)序分析:通過(guò)邏輯分析儀抓取I2C時(shí)序,確認(rèn)寄存器讀寫(xiě)時(shí)序、ADC轉(zhuǎn)換時(shí)序符合數(shù)據(jù)手冊(cè)要求;
3.硬件核查:最終發(fā)現(xiàn)ADC輸入引腳未有效連接待測(cè)電壓(焊接虛焊/杜邦線接觸不良),導(dǎo)致ADC輸入端無(wú)電平變化,采樣值固定。
解決方式
1.檢查ADC輸入引腳焊接狀態(tài),重新焊接確保接觸良好;
2.確認(rèn)待測(cè)電壓源正常輸出,且通過(guò)合適的限流/分壓電路連接至ADC輸入引腳;
3.驗(yàn)證:調(diào)整待測(cè)電壓,讀取CONV_REG值隨電壓變化,確認(rèn)問(wèn)題解決。
注意事項(xiàng)
ADC采樣值無(wú)變化是調(diào)試中高頻問(wèn)題,優(yōu)先排查硬件連接(輸入引腳、參考電壓、GND),再核查寄存器配置和時(shí)序,避免過(guò)度聚焦軟件問(wèn)題而忽略基礎(chǔ)硬件故障。
八、避坑指南:高頻錯(cuò)誤總結(jié)
1.Linux 6.1適配:
?iio_trigger_alloc:采用iio_device_id(indio_dev)獲取合法設(shè)備ID;
?remove函數(shù):調(diào)整為void類(lèi)型,無(wú)返回值。
2.I2C超時(shí):按“外部上拉電阻→內(nèi)部上拉配置→引腳占用”的順序排查解決。
3.寄存器讀取:放棄i2ctool裸操作,使用readreg函數(shù)讀取,保證數(shù)據(jù)準(zhǔn)確性。
4.設(shè)備樹(shù)配置:確保I2C控制器、設(shè)備節(jié)點(diǎn)的status屬性均配置為"okay",引腳配置與硬件實(shí)際接線一致。
5.ADC采樣值無(wú)變化:優(yōu)先核查輸入引腳硬件連接,再排查寄存器配置和時(shí)序。
6.增益配置:嚴(yán)格遵循數(shù)據(jù)手冊(cè)的PGA Setting與滿(mǎn)量程對(duì)應(yīng)關(guān)系,避免因量程不匹配導(dǎo)致采樣飽和或精度不足。
7.sysfs操作:增益配置需寫(xiě)入in_voltage_scale_available中的合法值,采樣率需匹配支持的SPS檔位,避免配置不生效。
九、總結(jié)
SGM58031在Linux 6.1下的調(diào)試核心要點(diǎn)為:
1.內(nèi)核API適配:僅修改iio_trigger_alloc參數(shù)和remove函數(shù)返回值,保留驅(qū)動(dòng)核心邏輯;
2.硬件基礎(chǔ):掌握芯片通道、增益、寄存器特性,為調(diào)試提供理論依據(jù);
3.驅(qū)動(dòng)操作:通過(guò)sysfs節(jié)點(diǎn)完成采樣讀取、增益配置、采樣率設(shè)置等操作,無(wú)需修改內(nèi)核代碼;
4.故障排查:按“硬件連接→I2C通訊→寄存器配置→軟件邏輯”的順序排查,優(yōu)先解決基礎(chǔ)硬件問(wèn)題;
5.寄存器讀取:通過(guò)內(nèi)核驅(qū)動(dòng)內(nèi)的regmap_read接口讀取,規(guī)避i2ctool的8位讀取缺陷。
該調(diào)試思路可遷移至其他16位寄存器架構(gòu)的I2C外設(shè),為同類(lèi)ADC芯片的驅(qū)動(dòng)適配和調(diào)試提供參考。
審核編輯 黃宇
-
寄存器
+關(guān)注
關(guān)注
31文章
5608瀏覽量
129957 -
adc
+關(guān)注
關(guān)注
100文章
7511瀏覽量
555906
發(fā)布評(píng)論請(qǐng)先 登錄
RK806中斷處理流程深度解析:從架構(gòu)到調(diào)試實(shí)戰(zhàn)
從“能用”到“懂原理”:ARMv8寄存器架構(gòu)深度拆解
什么是(UID)寄存器
嵌入式系統(tǒng)必懂的 20 個(gè)寄存器
浮點(diǎn)寄存器的添加
NVMe高速傳輸之?dāng)[脫XDMA設(shè)計(jì)32:寄存器功能驗(yàn)證與分析2
?SN74HCT595 8位移位寄存器技術(shù)解析與應(yīng)用指南
TPIC6595 8位功率移位寄存器技術(shù)文檔摘要
?TLC6C5912 12通道移位寄存器LED驅(qū)動(dòng)器技術(shù)文檔總結(jié)
SN74LV595B-EP低噪聲8位移位寄存器技術(shù)解析與應(yīng)用指南
使用寄存器點(diǎn)亮LED燈
MAX7312 2線接口、16位、輸入/輸出端口擴(kuò)展器,帶有中斷和熱插入保護(hù)技術(shù)手冊(cè)
通過(guò)I2C總線從源讀取所有PDO,但在HPI規(guī)范中找不到相應(yīng)的寄存器,為什么?
MAX25069怎么通過(guò)I2C修改寄存器?
如何用C語(yǔ)言操作寄存器——瑞薩RA系列FSP庫(kù)開(kāi)發(fā)實(shí)戰(zhàn)指南(10)
實(shí)戰(zhàn)指南:SGM58031 ADC從寄存器到驅(qū)動(dòng)的全流程調(diào)試(含Linux 6.1適配、編譯報(bào)錯(cuò)、I2C超時(shí)與寄存器精準(zhǔn)讀取)
評(píng)論