imx28evk i2c driver in slave mode

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

imx28evk i2c driver in slave mode

Jump to solution
3,559 Views
ZaheerAhmad
Contributor II

Hi,

I am implementing i2c slave functionality and facing some problem at very initial level.

I have configured;

The slave address in I2C Control Register 1,

Set the slave mode in I2C Control Register 0 by clearing the "MASTER_MODE" bit

Enable the slave search engine by setting "SLAVE_ADDRESS_ENABLE" bit in I2C Control Register 0

Enable "SLAVE_IRQ_EN" bit in I2C Control Register 1

And run the module by setting "RUN"  bit in I2C Control Register 0


After the above configuration, I am able to get the start condition on bus and the status register shows that the i2c searching engine in busy "SLAVE_SEARCHING". But it does not generate the "SLAVE_IRQ" interrupt. By looking the bus state, the master is sending start + address but on slave side, it recognize the start condition and make the bus busy but does not received the address byte.

My question is, do I need to configure the DMA in this case so that it can receive the address byte?

The i2c controller on imx28evk runs in three modes, PIO, PIO queue and DMA mode.

Which mode is used in case of slave functionality?

Is there any reference code available in Linux of WinCE BSP for the i2c slave functionality?

Regards,

Zaheer

Labels (1)
1 Solution
1,554 Views
PeterChan
NXP Employee
NXP Employee

Dear Zaheer,

Here is my i2c slave mode test code for i.MX28 EVK board to receive and send arbitrary number of bytes. It is based on BSP L2.6.35_10.12. After patching, the i2c slave test option can be enabled in the kernel configuration.

Device Driver

  I2C support

    I2C Hardware Bus support --->

      [*] MXS I2C SLAVE test

On my MX28 EVK, i2c1 is connected to the i2c0 externally. The i2c0 acts as the master and i2c1 acts as slave. The steps to test the i2c bus is as below:

// prepare i2c slave for receive

$ cd /sys/devices/platform/mxs-i2c-slave.1

$ cat test &

// send data from i2c master

$ cd /sys/devices/platform/mxs-i2c.0

$ echo 7 > test

// prepare i2c slave for send

$ cd /sys/devices/platform/mxs-i2c-slave.1

$ echo 5 > test &

// read data from i2c master

$ cd /sys/devices/platform/mxs-i2c.0

$ cat test

In this patch, the address byte is received in PIO mode and the i2c IRQ handler determine whether this transaction is a i2c read or write. For i2c slave write (master read), it simply setup a dma descriptor to send the number of wanted bytes. For i2c slave read (master write), a dma descriptor is setup to receive 1 byte. Whenever dma complete irq, the received byte is copied to the destination buffer and then setup another dma descriptor to receive the next byte. The i2c slave receive always ends with an i2c early terminate irq. After an i2c slave transfer complete, Both i2c device and its dma channel are reset.

Due to the i.MX28 errata #2836, the i2c slave is not suitable for high data throughput connection.

Hope the above information can help you.

Regards,

Peter

View solution in original post

5 Replies
1,555 Views
PeterChan
NXP Employee
NXP Employee

Dear Zaheer,

Here is my i2c slave mode test code for i.MX28 EVK board to receive and send arbitrary number of bytes. It is based on BSP L2.6.35_10.12. After patching, the i2c slave test option can be enabled in the kernel configuration.

Device Driver

  I2C support

    I2C Hardware Bus support --->

      [*] MXS I2C SLAVE test

On my MX28 EVK, i2c1 is connected to the i2c0 externally. The i2c0 acts as the master and i2c1 acts as slave. The steps to test the i2c bus is as below:

// prepare i2c slave for receive

$ cd /sys/devices/platform/mxs-i2c-slave.1

$ cat test &

// send data from i2c master

$ cd /sys/devices/platform/mxs-i2c.0

$ echo 7 > test

// prepare i2c slave for send

$ cd /sys/devices/platform/mxs-i2c-slave.1

$ echo 5 > test &

// read data from i2c master

$ cd /sys/devices/platform/mxs-i2c.0

$ cat test

In this patch, the address byte is received in PIO mode and the i2c IRQ handler determine whether this transaction is a i2c read or write. For i2c slave write (master read), it simply setup a dma descriptor to send the number of wanted bytes. For i2c slave read (master write), a dma descriptor is setup to receive 1 byte. Whenever dma complete irq, the received byte is copied to the destination buffer and then setup another dma descriptor to receive the next byte. The i2c slave receive always ends with an i2c early terminate irq. After an i2c slave transfer complete, Both i2c device and its dma channel are reset.

Due to the i.MX28 errata #2836, the i2c slave is not suitable for high data throughput connection.

Hope the above information can help you.

Regards,

Peter

1,554 Views
zeeshanaslam
Contributor I

I have also tried slave TX/RX using PIO mode instead of dma mode, using following mechanism to Tx data through I2C_DATA register:

                        /* Wait for HW_I2C_DEBUG0_DMA_REQ bit to get set*/

                        while(I2C_DRIVER_CHECK_DMA_REQ(i2c_base_address) == 0);

                        /*  Send Data Byte*/

                        I2C_DRIVER_SEND_DATA(i2c_base_address, data);

                        /* Clear DMA REQ bits. */

                        I2C_DRIVER_CLEAR_DMA_REQ(i2c_base_address);

For master mode, this scheme works but for slave only first 4 bytes are transmitted, after that nothing is transmitted nor i2c_debug0_dma_req gets set. Please confirm if this is limitation with pio in slave mode??

Regards,

Zeeshan Aslam


0 Kudos
1,554 Views
PeterChan
NXP Employee
NXP Employee

Hello Zeeshan,

0xFF or any dummy byte is not expected to receive in the i2c slave receive process.

In the i2c slave receive process, the i2c block is setup by clearing these bits: (DIRECTION, MASTER_MODE, RETAIN_CLOCK, CLOCK_HELD) in the HW_I2C_CTRL0 registers. The purpose is to hold the i2c clock until the software driver is ready to receive the data. The DIRECTION bit must be clear in advance or the i2c block will not receive data correctly. Because of chip errata #2836, APBX do not flush out the remaining data in FIFO after the DMA transaction is abruptly terminated by the i2c master. Thus, the i2c slave needs to receive its data byte by byte such that no data can remain in FIFO. In i2c slave ISR, a dma descriptor is setup to receive 1 byte and i2c acknowledge is sent as soon as the dma channel has started. After a data byte is received, both i2c dma channel interrupt and i2c data engine complete interrupt occur. In this patch, i2c data engine complete interrupt is ignored and the data is fetched to the destination buffer in the i2c dma channel interrupt handling. After that, another i2c dma descriptor is kicked off to receive the next data byte. The process continue until the master terminates the transaction or the slave do not acknowledge this byte due to destination buffer full. Please notice that through out the whole i2c slave receive process, the i2c block is not reset until the transaction ends or receive error has occurred.

No slave address match IRQ is probably due to the i2c timing register setting. I use these i2c timing register values for i2c running at 100kHz and 400kHz.

/* 100KHz Timing at 24MHz APBX */

HW_I2C_TIMING0 = 0x00800030;

HW_I2C_TIMING1 = 0x00800030;

HW_I2C_TIMING2 = 0x00400030;

/* 400KHz Timing at 24MHz APBX */

HW_I2C_TIMING0 = 0x001E0007;

HW_I2C_TIMING1 = 0x001E000F;

HW_I2C_TIMING2 = 0x0015000D;

I haven't tried the i2c slave TX/RX using PIO mode before. I guess the no i2c_debug0_dma_req issue is probably due to the master has terminated the transaction due to no i2c acknowledge from slave. You can check this via oscilloscope.

Regards,

Peter

0 Kudos
1,554 Views
zeeshanaslam
Contributor I

I am working on this issue. I have success with slave TX in dma mode but I am facing some issues, particularly with slave RX functionality.

I set the following configuration in dma descriptor for slave receive:

CTRL0_XFER_COUNT = 1

CTRL0_RETAIN_CLOCK = 1 (on all but last byte of expected transaction size)

CTRL0_ACKNOWLEDGE = 1

CTRL0_RUN = 1

and

pio_words = 1, wait4endcmd=1, decsem=1, irq = 1,dma_cmd = 0x1, len = 1

I implement the receive process as follows: After determining its master write request from I2C_STAT register, I setup the dma desc. as described above, reset the dma channel # 6 (APB dma and i2c blocks are already reset) and start the dma channel (writing command address to NXTCMD register and incrementing semaphore by 1) but I incorrectly receive 0xFF (slave address is 0x43), also sometimes there is no activity on dma channel and i2c bus at all and RUN is not cleared. On dma interrupt when I try to receive next byte after setting dma desc. in same way and again resetting (?) and starting the dma channel , again no activity on dma and bus remains busy.  The point to say here is that if I am following correct configuration sequence for receive processing then why do I get 0xFF as first byte (when my slave address is 0x43 and first byte to receive is 0xAA) and dma and i2c bus stalls with no activity on second iteration (2nd byte). Am I expected to receive the first dummy byte (0xFF) or am I missing/doing something wrong in receive processing sequence/state machine described above. In any case no further bytes are received. If I2C data_completion and early_irq interrupts are to be enabled, what I am expected to do as part of these interrupt handling apart from keep clearing them after each byte receive.

I seem to have duplicated everything in mx28_i2c_slave_demo.patch and tried quite a few other things as well but have not been able to get the things working as cleanly as they should.

Slave is transmitting successfully with similar configuration and processing sequence. Please try to elaborate process for receiving I2C bytes in a bit detail if there is something missing so that we can figure out what's going wrong.

One more thing, 'sometimes' i2c slave doesn't generate address match interrupt slave_irq on first attempt when I send a transfer request from Aardvark master and sometimes I have to try 2 or 3 times to succeed. Why start condition is not being detected on first attempt every time on bus (known issue?) or may be issue with Aardvark master? I have I2C_CTRL0 = 0x00040000 (slave address search enabled) at start up.

Thanks much!!

Regards,

Zeeshan



0 Kudos
1,554 Views
ZaheerAhmad
Contributor II

Hello Peter,

Thanks a lot for the details. The information is very helpful for me, specially the patch file you have attached.

Thanks again.

Regards,

Zaheer

0 Kudos