Linux中SPI驅動調試總結

轉載於:https://blog.csdn.net/mike8825/article/details/50762023

 

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控制器驅動初始化時的時鐘是多少,通信的時候就用多少)
     },
};

可參考

http://blog.csdn.net/vanbreaker/article/details/7733476

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

http://blog.csdn.net/mike8825/article/details/51335582

 

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引腳變爲高阻狀態

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章