MT7688 坑爹的 SPI Master 半双工全双工问题
MTK的東西便宜是真的便宜,好用也相對比較好用,但是總有那么幾個地方,讓人用著心里就窩火,就MT76x8來說,第一個窩火的地方就是啟動跳線選擇,非得把串口用作啟動跳線,導(dǎo)致調(diào)試起來非常麻煩,第二個就是本文要說的SPI問題,此問題分析和測試了很久,主要是關(guān)于spi 半雙工和全雙工的問題。
首先,來看下datesheet關(guān)于SPI Master的描述:
一共就這么幾個寄存器:
關(guān)于半雙工和全雙工的描述在SPI_MASTER的BIT10
僅僅只有more_buf_mode=1時,全雙工才有效;
關(guān)于more_buf_mode的描述如下:
即當(dāng)more_buf_mode = 0時,spi控制器的傳輸數(shù)據(jù)域最多有2個字節(jié),等于1時,最多有8個字節(jié);此處為什么寫傳輸數(shù)據(jù)域,不是最多發(fā)送字節(jié)數(shù),繼續(xù)看關(guān)于more_buf_mode的描述
等于0,即只能工作于半雙工模式;等于1,可以選擇半雙工,也可以全雙工;此處我們只分析1的情況,因?yàn)?傳輸?shù)臄?shù)據(jù)是在太少了;
等于1 及 半雙工時:SPI_OP_ADDR 寄存器也用作了數(shù)據(jù)寄存器,加上D0-D8幾個,一共9個寄存器,因此最多一次發(fā)送36個字節(jié),接收時將循環(huán)覆蓋D0-D7;
等于1 及 全雙工時,D0-D3用于發(fā)送,D4-D7用于接收;
以上文檔關(guān)于寄存器及功能的描述,非常正常,看不出什么問題所在。
下面,將結(jié)合代碼以及邏輯分析儀來繼續(xù)深入查探虛實(shí):
SPI Master驅(qū)動代碼位于drivers/spi/mt-7621.c
static int mt7621_spi_transfer_one_message(struct spi_master *master,struct spi_message *m) {struct spi_device *spi = m->spi;int cs = spi->chip_select;return mt7621_spi_transfer_half_duplex(master, m); }代碼中只實(shí)現(xiàn)了半雙工模式,而我們現(xiàn)在是要分析全雙工,因此需要修改驅(qū)動,配置為全雙工,MT7688的SPI控制器只有一個,但是有2個片選,SPI_CS0用于系統(tǒng)SPI flash,這個我們不能動;另一個SPI_CS1 我們可以用來測試全雙工;
兩個片選,復(fù)用一個控制器,復(fù)用一個驅(qū)動,因此我們可以根據(jù)片選的情況來確定傳輸方式,給CS1配置為全雙工傳輸;
static int mt7621_spi_transfer_one_message(struct spi_master *master,struct spi_message *m) {struct spi_device *spi = m->spi;int cs = spi->chip_select;if(cs == 0)return mt7621_spi_transfer_half_duplex(master, m);if(cs == 1)return mt7621_spi_transfer_full_duplex(master, m); }具體的full_deplex函數(shù)就不貼了,其實(shí)主要就是修改SPI_MASTER的BIT10,重寫一個reset函數(shù)用于full_deplex就行了,還有就是注意full_deplex 的if (WARN_ON(rx_len > 16)) ,一次傳輸長度的判斷,全雙工應(yīng)該是最多16個字節(jié)
static void mt7621_spi_reset_full(struct mt7621_spi *rs) {u32 master = mt7621_spi_read(rs, MT7621_SPI_MASTER);master |= 7 << 29;master |= 1 << 2;//master &= ~(1 << 10);master |= (1 << 10);mt7621_spi_write(rs, MT7621_SPI_MASTER, master); }至此,驅(qū)動已沒什么好分析的了。
最后就剩下SPI應(yīng)用層使用了,有兩種方式:
第一,直接write;第二,ioctl方式
我想既然是全雙工,肯定是想要得到回復(fù)的數(shù)據(jù)了,因此選用ioctl方式,其主要就是這么一個結(jié)構(gòu)體
struct spi_ioc_transfer tr ={.tx_buf = (unsigned long) TxBuf,.rx_buf = (unsigned long) RxBuf,.len =len,.delay_usecs = delay, };txbuf和rxbuf的長度要相等,len為單個tx或者rx的長度,delay為兩次msg傳輸?shù)拈g隔
可是運(yùn)行后,通過邏輯分析儀抓到的波形,跟發(fā)送的數(shù)據(jù)卻對不上,此處不便貼邏輯分析儀的圖,以文字方式描述一下,
其區(qū)別在于,在每發(fā)送的字節(jié)后面都多發(fā)了個0x00,
這個0x00明顯不是應(yīng)用的數(shù)據(jù),看驅(qū)動,也沒有發(fā)現(xiàn)主動會多發(fā)數(shù)據(jù)的地方,那么這應(yīng)該就是spi master自己發(fā)出去的;
換種方式再次驗(yàn)證一下猜想,將rx_buf = NULL,即只發(fā)不讀,相當(dāng)于于直接write,此后再抓波形,發(fā)現(xiàn)0x00沒有了;
應(yīng)用換成直接write,抓到的波形跟rx_buf=NULL的結(jié)果一樣;
到此我們可以肯定多發(fā)的0x00是控制器自己發(fā)出的;
再來一次確定性的驗(yàn)證:應(yīng)用直接read,只讀數(shù)據(jù)我們看看有沒有波形,結(jié)果抓到的數(shù)據(jù)發(fā)送全部是0x00,這個00肯定就是控制器為了讀取spi的數(shù)據(jù),自動發(fā)送的,這是由spi的傳輸機(jī)制來決定的,在SCK的跳變處發(fā)送或者讀取數(shù)據(jù);
到此,我們可以看出MT7688的SPI控制器的“特殊”之處。
當(dāng)然這個特點(diǎn),對于使用LCD等只需要接受數(shù)據(jù)的slave來說,沒有影響;但是對于 其他有雙向數(shù)據(jù)交互的設(shè)備,將導(dǎo)致數(shù)據(jù)錯亂;剛好我也是因?yàn)樵谑褂胹pi加密芯片時,發(fā)現(xiàn)此問題的;
對于雙向交互的設(shè)備來說,MT7688只能使用spi-gpio來模擬了,其限制在于時鐘速度沒有硬件SPI快,只適合低速設(shè)備。
總結(jié),此問題搞了幾天,也算是一個教訓(xùn),光看文檔和代碼是看不出問題的,通過邏輯分析儀直接就可以看出,再結(jié)合代碼測試,定位問題所在。因此結(jié)合各種調(diào)試工具,可以加快分析問題的速度。
?
?
總結(jié)
以上是生活随笔為你收集整理的MT7688 坑爹的 SPI Master 半双工全双工问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MT7628/MT7688 修改串口2作
- 下一篇: 项目中用到的语音识别方案 硬件/软件相关