How to use SPIDEV driver on iMX6UL EVK

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

How to use SPIDEV driver on iMX6UL EVK

跳至解决方案
10,104 次查看
arnaudne
Contributor II

Hi everyone,

My setup is the following :

  • iMX6UL-EVK
  • Yocto Project 2.1.1 Krogoth based distribution
  • Ubuntu 16.04 development computer
  • Saleae Logic Analyzer

I would like to be able to use spidev driver to communicate with some sensors from a user-space application.

I managed to get the /dev/spidev3.0 showing up (thanks to answer on this topic), but I can't write anything on the bus.

I am using the following command :

echo hello > /dev/spidev3.0

I then verified with my logic analyzer (on Arduino header J1704), nothing happens...

I also tested with spidev_test.c, and even by shorting MISO and MOSI pins I do not get the desired output :

spi mode: 0x0

bits per word: 8

max speed: 500000 Hz (500 KHz)

RX | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | ............................

Can anyone help me ?

Thank you in advance.

Arnaud

标签 (2)
1 解答
4,921 次查看
LuisCasado
NXP Employee
NXP Employee

Hi Arnaud,

You need to populate and remove some resistors. Review in the schematic the resistors :  R1724, R1725, R1726, R1727, R1731,R1633, R1634, R1635, R1636

Luis

在原帖中查看解决方案

7 回复数
4,921 次查看
neil3
Contributor II

Hi Arnaud,

Thanks for posting your example device tree file, it helped me to get up and running :-)

A minor point and fairly easy to spot but line 39 is missing a '6', it should be:

MX6UL_PAD_ENET2_TX_EN__ECSPI4_MOSI      0x100b1

Neil

0 项奖励
回复
4,922 次查看
LuisCasado
NXP Employee
NXP Employee

Hi Arnaud,

You need to populate and remove some resistors. Review in the schematic the resistors :  R1724, R1725, R1726, R1727, R1731,R1633, R1634, R1635, R1636

Luis

4,921 次查看
arnaudne
Contributor II

Hi Luis,

Thank you for your quick answer !

I moved resistors R1633, R1634, R1635, R1636 to R1724, R1725, R1726, R1727 and it works like a charm.

I did not change R1731 though.

I still have to handle the CS line as it does not toggle but I think it is due to a misconfiguration in my device tree :

&ecspi4 {

  #address-cells = <1>;

  #size-cells = <0>;

  fsl,spi-num-chipselects = <1>;

  cs-gpios = <0>;

  pinctrl-names = "default";

  pinctrl-0 = <&pinctrl_ecspi4>;

  status = "okay";

  spidev@0x00 {

    compatible = "spidev";

    spi-max-frequency = <20000000>;

    reg = <0>;

  };

};

I am pretty new to Embedded Linux development, and device-trees, but I think that the variable cs-gpios is wrong ?

--------------------------------------------------------------------------------------------------------------------------------------------------------

Updated: Following Luis answer permitted me to get the CS pin to work, I put the updated device tree right below.

If anyone is interested in the modifications I had to make to make the spidev work on iMX6UL-EVK :

1 - Device tree (I used Yocto Project)

I disabled fec2, which is Ethernet PHY 2 as it cannot be used anymore in this configuration

#include "imx6ul-14x14-evk.dts"

/ {

  spi3 {

    status = "okay";

  };

};

&fec2 {

    status = "disabled";

};

&ecspi4 {

  #address-cells = <1>;

  #size-cells = <0>;

  fsl,spi-num-chipselects = <1>;

  cs-gpios = <&gpio2 15 0>;

  pinctrl-names = "default";

  pinctrl-0 = <&pinctrl_ecspi4>;

  status = "okay";

  spidev@0x00 {

    compatible = "spidev";

    spi-max-frequency = <80000000>;

    reg = <0>;

  };

};

&iomuxc {

    pinctrl-names = "default";

    pinctrl-0 = <&pinctrl_hog_1>;

    imx6ul-evk {

    pinctrl_ecspi4: ecspi4grp {

        fsl,pins = <

        MX6UL_PAD_ENET2_TX_CLK__ECSPI4_MISO     0x100b1

        MXUL_PAD_ENET2_TX_EN__ECSPI4_MOSI      0x100b1

        MX6UL_PAD_ENET2_TX_DATA1__ECSPI4_SCLK   0x100b1

        MX6UL_PAD_ENET2_RX_ER__ECSPI4_SS0       0x10b0

        >;

    };

  };

};

2 - Move  resistors R1633, R1634, R1635, R1636 to R1724, R1725, R1726, R1727. These resistors are near J1703 and on the back of the board (in the middle).

3 - Compile spidev_test.c for the iMX6UL and use it as following (remember to short MISO and MOSI pins) :

./a.out -s 1000000 -v

-s indicates the speed in Hz, here 1MHz.

-v is verbose mode (use -h to see all options)

Thank you , and (cf. on this topic) again. I will have a look into CS pin handling tomorrow.

Arnaud

4,921 次查看
LuisCasado
NXP Employee
NXP Employee

Hello Arnaud,

Try :

&ecspi4 {

               fsl,spi-num-chipselects = <1>;

               cs-gpios = <&gpio2 15 0>;

               pinctrl-names = "default";

               pinctrl-0 = <&pinctrl_ecspi4>;

               status = "okay";

               spidev0: spi@0 {

                              reg = <0>;

                              compatible = "spidev";

                              spi-max-frequency = <1000000>;

               };

};

….

                              pinctrl_ecspi4: ecspi4grp {

                                             fsl,pins = <

                                                            MX6UL_PAD_ENET2_RX_ER__GPIO2_IO15            0x10b0

                                                            MX6UL_PAD_ENET2_TX_EN__ECSPI4_MOSI         0x100b1

                                                            MX6UL_PAD_ENET2_TX_DATA1__ECSPI4_SCLK    0x100b1

                                                            MX6UL_PAD_ENET2_TX_CLK__ECSPI4_MISO        0x100b1

                                             >;

                              };

Luis

4,921 次查看
arnaudne
Contributor II

Thank you Luis for your answer,

It works like a charm ! CS Pin is now properly toggled.

However, I still have a problem with the CS handling in the spidev driver. This is my method (SPI interface is configured elsewhere) :

IOBus_Error SPI::message(const unsigned char *txBuffer, unsigned char *rxBuffer, ssize_t &length, long flags) {

    IOBus_Error error = IOBus_Error_None;

    int status;

    if (handle <= 0) openHandle();

    // Build transfer

    struct spi_ioc_transfer    transfer;

    memset(&transfer, 0, sizeof(spi_ioc_transfer));

    transfer.tx_buf = (unsigned long)&txBuffer[0];

    transfer.rx_buf = (unsigned long)&rxBuffer[0];

    transfer.len = length;

    transfer.delay_usecs = 0;

    transfer.speed_hz = configuration.speed;

    transfer.bits_per_word = configuration.bits;

    transfer.cs_change = flags & SPI_Flag_CSChange;

    // Execute transfers

    status = ioctl(handle, SPI_IOC_MESSAGE(1), &transfer);

    // Check for errors

    if ( status < 0) return IOBus_Error_Write;

    return IOBus_Error_None;

}

For example, I want to read one byte at the address 0x24 of my device, so my buffers are the following :

txBuffer = {0x24, 0x00}

rxBuffer = {0x00, 0x00}

cs_change is set to 0 and length to 2

When I use my logic analyzer, I can see that the CS line is pulled up between the 0x24 and 0x00 bytes causing my device not to answer.

I then tried to use 16 bits per word in the SPI configuration to keep the CS line low, and it worked. But it is certainly not the way it has to be handled...

I also tried to set cs_change to 1 but it did not change anything on the CS line. And as I am aware of, cs_change must be 0 to let the CS line unselected between transfers.

Here is a capture of the wrong output on my logic analyzer :

wrong_cs.png

And this is a capture of the wanted output using 16 bits per word, we can see that in this case my device correctly answers (0x05 is the value I was waiting for) :

right_cs.png

What am I doing wrong ?

-----------------------------------------------------------------------------------------------------------------------------------------------------

Thanks Luis for your help with the device-tree, I will update my previous comment to reflect the configuration you just gave to me.

I still have another questions about the device-tree configuration:

  • You are using MX6UL_PAD_ENET2_RX_ER__GPIO2_IO15, is it different from MX6UL_PAD_ENET2_RX_ER__ECSPI4_SS0 ? From what I see in the pinfunc file, their input_reg and mux_mode are not the same, will it impact the
  • Can I use any (free) GPIO as CS pin do I have to use one labeled as ECSPI4_SSx ?
  • What does the hexadecimal number after pin declaration means, and how can I determine the right value to use ? (0x10b0, 0x100b1)

Thanks in advance,

Arnaud

0 项奖励
回复
4,921 次查看
LuisCasado
NXP Employee
NXP Employee

Hello,

  • Each PAD has a BALL number, Canonical name and NET name in the schematic.
    • ECSPI4_SS0 = ENET2_RXER = ENET2_RX_ER (Canonical) = D16 (BALL)  And that pin can have the GPIO function GPIO2.IO15 (Check Reference Manual)
  • Check the SPIDEV binding documentation:

o   https://www.kernel.org/doc/Documentation/devicetree/bindings/spi/spi-bus.txt

o   You can select GPIO or native CS.

  • The value is the PIN configuration value. In this case, the value in the register SW_PAD_CTL_PAD_ENET2_RX_ER SW PAD Control Register.

Luis

0 项奖励
回复
4,921 次查看
arnaudne
Contributor II

Thank you for your answer, it makes sense to me now.

I used MX6UL_PAD_ENET2_RX_ER__GPIO2_IO15 instead of MX6UL_PAD_ENET2_RX_ER__ECSPI4_SS0 in my device tree, and the CS pin behavior is now perfect.

Thanks again,

Arnaud

0 项奖励
回复