1. 程式人生 > >Linux中SPI驅動除錯總結

Linux中SPI驅動除錯總結

1.先了解一下spi協議的基本資訊,包括spi的工作原理,4中不同模式的區別。

2.新增spi裝置

static struct spi_board_info   xxxxx_spi0_board[] = {
     [0] = {
              .modalias = "xxxx",                      //裝置名字
              .bus_num = 0,                              //裝置在第幾個spi控制器上
              .chip_select = 0,                           //片選號,用於區別其他從裝置
              .mode = 0,                                    ///傳輸模式
              .max_speed_hz = 2*1000*1000,  //最大工作頻率(在我除錯的平臺上這個設定無效,spi控制器驅動初始化時的時鐘是多少,通訊的時候就用多少)
     },
};

可參考

3.核心中spi程式設計模板,核心中有許多的spi驅動可供參考(driver/spi/*)

4在除錯的時候,先用示波器量一下每跟訊號線的訊號是否正常。

 spi的波形如下圖,不同的工作模式略有不同,但萬變不離其宗。

   CS(片選)(平常是高電平,通訊時被拉低) 

   CLK(時鐘) 測量clk的頻率是否為設定值

   MOSI(主機輸出從機輸入)

   MISO(主機輸入從機輸出)

  4.1有些晶片要通過拉高或拉低某一引腳來作為主機或從機,這個要看晶片手冊。

       4.2之前遇到一種情況,CS沒有訊號,居然發現晶片的CS引腳沒有連線到CPU上,晶片怎麼可能正常工作呢。

       4.3MISO讀回來的資料全部是0

                  4.3.1通過示波器量出來的訊號也的確是0,檢視晶片手冊才知道,原來這個引腳被設定成高阻態了,要拉高另一個引腳才能作為MISO功能。

                  4.3.2根據晶片手冊,要讀一個暫存器的值,只有發幾個特定的位元組過去,然後接著讀就可以了,可是讀回來的值全部是零。從晶片手冊中,讀暫存器的值的時序為下圖

程式碼是這樣實現的

int xxx_spi_read(unsigned int addr, unsigned int *val, size_t len)

{

    struct spi_device *spi =xxx_spi;

    struct spi_message message;

    struct spi_transfer x[3];

    int status;

    u8 write_buf[5];

    u8 read_buf[4];


    write_buf[0] =(len == 4) ? xxxx_SPI_CMD_32_READ : xxxx_SPI_CMD_16_READ;

    write_buf[1] = (addr & 0xff000000) >> 24;

    write_buf[2] = (addr & 0x00ff0000) >> 16;

    write_buf[3] = (addr & 0x0000ff00) >> 8;

    write_buf[4] = (addr & 0x000000ff) >> 0;


    spi_message_init(&message);

    memset(x, 0, sizeof(x));


    x[0].len = 5;//(1+4)

    x[0].tx_buf = write_buf; //命令+地址

    spi_message_add_tail(&x[0], &message);


    x[1].len = 4;//4

    x[1].tx_buf = write_buf; //dummy(任意位元組)

    spi_message_add_tail(&x[1], &message);


    x[2].len = len;

    x[2].rx_buf = read_buf;  //接收資料

    spi_message_add_tail(&x[2], &message);


    status = spi_sync(spi, &message);


    if (len == 4)

        *val = read_buf[3] | read_buf[2] << 8 | read_buf[1] << 16 |

            read_buf[0] << 24;

    else

        *val = read_buf[1] | read_buf[0] << 8;


    return status;

}

重複跑這段程式碼,發現第二個spi_transfer發過去的全部是0,x[1].tx_buf = write_buf,明明不是0啊。也就是說第二個和第三個spi_transfer的資料全部丟失。於是就用一個spi_transfer來實現傳輸,改動如下

int xxx_spi_read(unsigned int addr, unsigned int *val, size_t len)

{

struct spi_device *spi = xxxx_spi;

struct spi_message message;

struct spi_transfer x[1];

int status;

u8 write_buf[13];

u8 read_buf[13];


write_buf[0] =(len == 4) ? xxxx_SPI_CMD_32_READ : xxxx_SPI_CMD_16_READ;

write_buf[1] = (addr & 0xff000000) >> 24;

write_buf[2] = (addr & 0x00ff0000) >> 16;

write_buf[3] = (addr & 0x0000ff00) >> 8;

write_buf[4] = (addr & 0x000000ff) >> 0;


spi_message_init(&message);

memset(x, 0, sizeof(x));


x[0].len = 9+len;

x[0].tx_buf = write_buf;

x[0].rx_buf = read_buf;

spi_message_add_tail(&x[0], &message);

status = spi_sync(spi, &message);


if (len == 4)

*val = read_buf[12] | read_buf[11] << 8 | read_buf[10] << 16 |

read_buf[9] << 24;  //接收到的第10個位元組有效

else

*val = read_buf[10] | read_buf[9] << 8;


return status;

}

一個message只有一個transfer,讀回來的資料就正常了。這個給spi控制器驅動實現有關,也就是晶片廠商沒做好適配造成對的。

     4.4寫暫存器的訊號正常,也有應答訊號,但讀不了資料。感覺訊號都對了,但通訊還是有問題,覺得很不合理。於是,將晶片上的電源引腳測量了一遍,發現問題了,某一路電源沒有供電(硬體的同事設計的電路),將這一路電源供電上,通訊就沒有問題了。

     4.5在imx平臺上,spi的管腳可以功能複用。比如,第一路spi可以多路gpio供選擇(如下圖),硬體上連線到了那幾個gpio上,就需要在裝置樹上新增相應的資訊,具體的可參考對應的pdf。

     4.6在除錯一個降噪模組時,發現每次發過去的訊號,應答波形總是不對。這裡,剛開始傳送的第一個位元組為0x05,通過示波器測量出的波形為

       由於這裡的spi設定為工作模式為0,那麼在資料在CLK的上升沿有效,根據協議讀取的資料為1010 000B,就是0xA0。可是0x05,對應的二進位制為0000 0101B,原來這裡反過來了。說好的高位先傳輸呢,直接跟cpu廠商那邊的工作人員聯絡一下,原來高位或低位先傳輸是可以配置的。配置對傳輸方式後,發出的訊號如下,接受到的應答訊號也正常了。

     4.7與上圖相比,在每傳輸完一個位元組後,spi的時鐘會有一定的延時,這中波形與上圖也是一樣的。

 

 4.9當波形正確,晶片仍不正常工作時,這時要檢測一下硬體電路了。

以上圖為例,要注意的就有以上幾點

 6腳需要用100k到220k的電阻來上拉或下拉

 9腳需要供電

 12腳通過高低電平來選擇主從模式

 17腳晶片處在主機模式下,該引腳可復位MPU.從機模式先,高低電平來決定工作模式

 18腳要連線到地,如果拉高就可以讓spi引腳變為高阻狀態

這些在晶片工作不正常時,都是需要認真檢查的。

相關推薦

LinuxSPI驅動除錯總結

1.先了解一下spi協議的基本資訊,包括spi的工作原理,4中不同模式的區別。 2.新增spi裝置 static struct spi_board_info   xxxxx_spi0_board[] = {      [0] = {               .

關於LinuxLVM的使用總結

總結 play http 利用 重啟 界面 分區類型 圖文 結構 首先借鑒一段圖文,如下:LVM是邏輯盤卷管理(LogicalVolumeManager)的簡稱,它是Linux環境下對磁盤分區進行管理的一種機制,LVM是建立在硬盤和 分區之上的一個邏輯層,來提高磁盤分區管理

linuxshell if 判斷總結

UNIX Shell 裡面比較字元寫法 -eq     等於;              -ne    不等於; -gt    大於;   &

電池驅動除錯總結,電池服務+電量計驅動+除錯方法

1.概述: Android電池服務,用來監聽核心上報的電池事件,並將最新的電池資料上報給系統,系統收到新資料後會去更新電池顯示狀態、剩餘電量等資訊。如果收到過溫報警和低電報警,系統會自動觸發關機流程,保護電池和機器不受到危害。 Android電池服務的啟動和執行流程: And

Linux的指令碼程式設計總結

使用者管理 新增使用者 useradd sxt01 所有的系統賬戶都是在home目錄下的 drwx------ 2 sxt01 sxt01 4096 Dec 10 06:38 sxt01 可以去home目錄下去進行查詢 對於兩個賬戶共享同樣的東西,可以通過建立組的形式,讓兩個

電池驅動除錯總結

1.概述:  Android電池服務,用來監聽核心上報的電池事件,並將最新的電池資料上報給系統,系統收到新資料後會去更新電池顯示狀態、剩餘電量等資訊。如果收到過溫報警和低電報警,系統會自動觸發關機流程,保護電池和機器不受到危害。  Android電池服務的啟動和執行流程:&nbs

初次動手編寫驅動——LED在linux驅動

今天第一次自己嘗試編寫驅動,看了這麼長時間視訊,第一次動手,編寫的是簡單的LED的程式。從簡單到複雜一個一個來。 編寫驅動的順序是先從註冊函式和解除安裝函式起始: static int led_init() {cdev_init(&cdev, &led_fo

linuxvim常用命令總結

      linux中vi和vim文字編輯器 1.分類:     1)linux中全屏編輯器是Vim、Emacs等,linux分為全屏文字編輯器、行編輯器。   2)按執行介面分類,字元介面編輯器和圖形介面編輯器。常見的字元介面編輯器是         vi、vim、E

Linuxnvme驅動詳解

NVMe離不開PCIe,NVMe SSD是PCIe的endpoint。PCIe是x86平臺上一種流行的bus匯流排,由於其Plug and Play的特性,目前很多外設都通過PCI Bus與Host通訊,甚至不少CPU的整合外設都通過PCI Bus連線,如APIC等。  NV

[MTK] BT驅動除錯總結

首先在init.Project.rc裡面找例如找fm bt wifi gps等等。。。    # STP, WMT, GPS, FM and BT Driver    insmod /system/lib/modules/mtk_stp_core.ko    insmod

Linux系統SPI驅動學習筆記(一)

  SPI是"Serial Peripheral Interface" 的縮寫,是一種四線制的同步序列通訊介面,用來連線微控制器、感測器、儲存裝置,SPI裝置分為主裝置和從裝置兩種,用於通訊和控制的四根線分別是: CS    片選訊號SCK  時鐘訊號MISO  主裝置的

SPI/I2S除錯總結

SPI晶片:W25Q16   I2S晶片:AK4386   主晶片:STM32F105 1.查詢標誌位:          1)while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);//檢查傳送是否完成   

linux的man命令總結

前言 我們在學習linux的時候肯定會遇到自己不懂的命令、函式、協議、檔案,以前的我會直接去百度相關用法,而從來不會去使用最最基本的man命令,這個linux中自帶的man,真的是簡單粗暴,今天就來

Linuxtar的用法總結

-c: 建立壓縮檔案 -x:解壓 -t:檢視內容 -r:向壓縮歸檔檔案末尾追加檔案 -u:更新原壓縮包中的檔案 這五個是獨立的命令,壓縮解壓都要用到其中一個,可以和別的命令連用但只能用其中一個。下面的引數是根據需要在壓縮或解壓檔案時可選的。 -z:有gzip屬性的 -j:有bz2屬性的 -Z:有compre

slvi驅動除錯總結

Slvi驅動除錯總結本篇是繼音訊基本知識介紹後,4G專案中除錯過程中遇到的一些問題總結好奇是進步的原動力 目錄Slvi驅動除錯總結        11 模擬spi通訊問題        32 msleep和mdelay        32-1 系統資源        32-2

SPI,MCP2515除錯總結

MCP2515是一SPI轉CAN匯流排的晶片,對於CPU來說,CPU就是主裝置,SPI就是從裝置,所以在核心裡,MCP2515就是一個SPI裝置,而SPI裝置在核心中的結構是對應的,是一個spi控制器對應一個SPI裝置,也就是一個spi_master對應一個spi裝置,而

Linuxspi驅動開發(2)

Linux下spi驅動開發之m25p10驅動測試 目標:在華清遠見的FS_S5PC100平臺上編寫一個簡單的spi驅動模組,在probe階段實現對m25p10的ID號探測、flash擦除、flash狀態讀取、flash寫入、flash讀取等操作。程式碼已經經過測試,運行於

Linux 核心 SPI驅動收發函式API

傳送字串 static int spi_write_bytes(struct spi_device *spi, unsigned char *txbuf, int txlen) { int ret = 0; struct spi_messa

龍芯1c上實現基於linuxspi驅動經驗

本文主要分享如何在龍芯1c上實現linux下的spi驅動。 這裡假設已經對spi有一定了解,不瞭解的自己百度。 使用硬體SPI 基礎 百度上已經有很多關於linux下spi驅動的文章,講得很好很全。比如:linux下spi驅動分為三層——SPI核心層、SPI控制器層、SPI

Linux系統spi驅動程式分析---(一)

說明:本文將分析Linux-2.6.17原始碼中的spi驅動程式,其內容為本人閱讀原始碼後的一些理解。由於本人水平有限,所以內容可能比較雜亂零散,權當個人筆記記錄之用。而以下內容均以powerpc架構為例說明。 在Linux系統中,spi驅動的設計採用了分層設計模式的思想