I2C Adapter Driver debugging Summary

Source: Internet
Author: User

Address: http://blog.csdn.net/coder_jack/article/details/6419903

Send a start and stop command consecutively for the following test:

1. Send the start command to address an existing device, receive the ACK, and then send the Stop command. Everything is normal and the Stop waveform is displayed.

2. Send the start command to address a non-existing slave device. If no response is received, send the Stop command to release the bus and the waveform of the bus release cannot be seen. Only the check results show that the SCL is always low, and the SDA is always high!

(There is no latency between the two commands in the above test. If you want to add a latency, you can use Log instead, because the test found that a udelay is about 25 ms, this event is too long. It takes about 60 microseconds to print a character)

If the I2C adapter does not receive the slaver response after issuing the start command and slaver address, THE TFe flag of the adapter is 0. That is, the sending buffer has always had data to be sent. It seems that this flag will not set to 1 when no response from the device is received.

Why can't the last byte be read during continuous reading?

It is tested that this problem does not occur when the log is opened, so it can be confirmed that the delay at a specific location is insufficient.

By observing the waveform through the oscilloscope, we can see that the last byte has been read, and the Stop waveform is also displayed, therefore, it is determined that the last byte has not entered the FIFO before the last read of RX-FIFO. Therefore, when sending a stop request, the sending buffer is determined to be null. If it is not null, the delay is delayed until it is null to ensure that all the read content can enter the rx fifo so as to avoid the problem.

When a start command is issued to address an existing slaver and the flag is read, a response from the slave device is received, and then a Stop command is sent, no corresponding waveform is generated for the stop operation. This causes the bus to remain busy (The SDA status remains low, and the SCL status remains high). Even after the reset adapter, the bus is still busy, and I began to doubt whether the reset function has taken place. Even the reset of the motherboard does not work. Only after the Board is powered off can it be removed from the busy state.

This damn problem!

Answer: when addressing a device and reading data from the device, the device controls the SDA line. When data transmission is not started, the SDA will be dropped from the device, and the bus will be busy. The device will receive a nack as a sign to release the SDA line. If you do not give this Nack, this is not available unless the device reset or power-off is enabled, or you can power off the entire board! Okay. What else can I do? Of course, you can also read a byte from the device, give it a nack, and then stop. Why bother to stop .... Haha! The problem is solved!

If the start + Read is not addressed to the slave device, the SDA is high, the SCL is low and then immediately execute the Stop command to find that this command can not be issued, will be placed in the TX--FIFO! However, if you use the soft reset adapter, you can release the bus!

After start + read, if it is addressed to the slave device, the SDA is low, and the SCL is low, stop cannot be executed immediately. If you execute stop, no results will be found, when the execution is complete, the SDA is low and the SCL is high! If the soft reset adapter cannot be used to release the bus, I understand it as follows: Stop can be correctly executed, and both lines will be pulled up, But SDA will be pulled down immediately from the device, because the slave device does not receive the signal to release the bus (an NACK) at this time the bus deadlock occurs, the only way is to read the slave device and give a nack and then stop

After start + write, if it is not addressable to the slave device, the SDA is high, and the SCL is low, the Stop command cannot be issued, because the TX--FIFO is always not empty (you can also see that the value of the ic_txflr register is always 1 )! In this case, soft reset can be used to release the bus.

After start + write, if the addressing is reached from the device, the SDA is high, and the SCL is low, the stop can be issued normally !!!!!

There is another problem that has plagued me for a long time. There are two FIFO In the I2C adapter, namely tx fifo and Rx FIFO. The former is used to buffer all pending commands sent to the adapter, this includes reading from the device and writing from the device. For the adapter we are currently working on, it is the eight cmd commands, S0 ~ S7:

S0: idle

S1: Send start and one byte

S2: write one byte

S3: write one byte and send stop

S4: read one byte and send an ACK

S5: read one byte and send an nack

S6: read one byte and send an NACK and send stop

S7: Send stop

Any of the eight commands will be sent to tx fifo for processing. S4, S5, and S6 are used to read data from slaver, when any of the three items is executed, a byte will be read from slaver and placed in the rx fifo, and the count counter of the rx fifo will increase by 1. After reading a data from the rx fifo, this counter will be reduced by 1.

In the driver, I use this counter as the marker for reading rx fifo. When the number of data in the rx fifo buffer exceeds the set threshold, I will read the buffer continuously, every time I read a value, I will check the counter and know that the value of this counter has changed to 0. According to this idea, the driver can run normally. However, due to other debugging problems, I suddenly found that during the single-step debugging through trace, the driver could not read data from slaver, the same Code can be executed continuously without any problems. It is a bad idea that data cannot be read only when a single step is executed! Then I connected the oscilloscope and found that slaver data could not be read at all, because every time I run any command of S4, S5, and S6 in a single step, I saw a waveform, and it is the correct waveform! Visible data can be read. Why didn't the driver get the data? One-step tracking finds that when the driver wants to read RX
In FIFO mode, the value of the above counter is checked first. When the value is greater than 0, it indicates the data to be read in FIFO mode. However, in a single step, the value is always 0, the program will think that the FIFO is empty and thus give up reading. Is there a problem with the counter? We can see a waveform just now, which indicates that there should be data in the FIFO, then I can try to forcibly read the FIFO through the Counter Check. No data exists in tnnd and FIFO! Where did the data go?

The Code is the same. I did not perform single-step debugging, but ran the program. The result is still completely correct. It seems that the problem can only occur in single-step debugging. However, the logic of single-step execution is exactly the same as that of one-breath execution. Why can't data be read? I began to wonder if this adapter had any internal mechanism to change this counter? The only difference between one step and one breath is the latency of one step. To verify this idea, I added a latency function after each read command S4, S5, and S6 to simulate the single-step action, I have set the delay time to 3 seconds! Then we will test the single-step and single-step execution separately. Mom, there is still such a problem. Now it seems that there will be a problem as long as the trace is executed in a single step, as long as there is no single-step interference, the program can be correctly executed no matter whether it is added or delayed, no matter it is not on the trace! What is tricky about this Trace Step?

......

One day later ....

At noon, the boss invited me and rubbed it again... Well, it's time to work harder ....

When I wrote this document, I suddenly couldn't remember how I suddenly thought of the crux of the problem .... Forget it. You don't want to. Just give it a conclusion.

When debugging with trace, we can see the values of all registers, which of course is read by trace from the corresponding address. This includes the FIFO register. When we perform one step, the trace refresh (READS) All the registers once, that is, no step is taken, trace reads the first-in-first-out register, which causes the first-in-first-out counter to be reduced by 1 and the first pointer of the first-in-first-out queue to be removed. That is, in a single step, the FIFO will be read by the trace. Of course, our program cannot read the desired results!

Through solving this problem, we will have a new understanding of trace! In fact, trace is really a good thing! Haha!

20110515 supplement:

Yesterday I found another problem in the test: When start is addressing a device that does not exist, the program is correct during the first execution, and the second execution will fail, according to the log, the logic of the program should be different from that of the first execution. This is not the case. After careful troubleshooting, we find that, during the second execution of the program, the logic is to receive the ACK code segment, and the Nack mark has been generated by observing the register. This indicates that the hardware is correct, because the Code takes snapshots of the register containing ack immediately after the start command is issued, and at that time, ACK or Nack may not be created, so when the program judges the ACK status later, it will use the old photo, of course, there will be an error. Therefore, this snapshot should be created after Ack is created. The problem is that when the first eight clock pulses of the Start waveform (address bit and R/W Bit) how long will it take to generate 9th (about ACK) pulses? Considering that the nine pulses are controlled by the master, that is to say, the master will not deliberately extend 9th cycles to wait for the slaver! That means the cycle of the 9th pulses will be the same as that of the first eight cycles. The maximum frequency of I2C is 400 kHz, generally, a device can work at least kHz, so it can be calculated as kHz. In this case, the maximum waiting time is about 10 us.

After setting the latency after the statr command, the program is normal!

20110519 supplement:

Yesterday, I had been solving a problem. When I repeatedly called the I2C transmission function, I found that there was always a latency of more than Ms between the two calls, after carefully checking the program flow, it is found that the delay set in the Code is not enough to cause the delay between two data transmissions. Each complete transmission ends with a start, it can be understood that there is a total latency in the data transmission process, but the current latency occurs between the previous stop and the next start, which is strange, presumably it should not be caused by the adapter, because the BSP-test code is currently being debugged, because the interrupt and FIFO modes are used, and the test runs in single task mode, therefore, in order to simulate program scheduling, I made an endless loop in the code to simulate the program to call up the CPU. The damn loop uses a global variable to terminate the loop. After each start, it will call this dead loop to start simulating the abandonment of the CPU, when I2C comes to the TX-FIFO is empty interrupt (or other interrupt) after entering the interrupt processing function, in this function, the I2C Stop command will eventually be executed to end this transmission. At this time, the above global variables will be modified before the end of the interrupt callback function, which can lead to the termination of the endless loop, this is the write of this endless loop.

Static wait_flag = 1;

Void i2c_wait_event_timeout (u32 count)

{

U32 I = 0;

Do

{

Mdelay (100 );

If (I ++> = count)

Break;

} While (wait_flag );

}

The wait_flag will be set to 0 in the interrupt callback function. In this way, when the Interrupt Processing ends, the CPU will be simulated and the wait function will continue to be executed, then, you have to wait until mdelay is fully completed before you can exit. This is the problem. Assume that mdelay is executed for 100 ms. When mdelay is executed for 1 ms, it will interrupt the processing function, and then return to the wait function after the interrupt processing function is completed, of course, the while will be executed after the remaining Ms execution is complete, so this time will produce a delay, from the external point of view is that my stop waveform has been sent out, but the data processing function (i2c_do_xfer (...)) it's not over yet!

The solution is simple: Give the mdelay parameter smaller, such as 1, or simply don't want mdelay, as shown below:

Static wait_flag = 1;

Void i2c_wait_event_timeout (u32 count)

{

U32 I = 0;

Do

{

If (I ++> = count)

Break;

} While (wait_flag );

}

In this case, as long as the external parameters (count) are given large enough, the required latency can still be reached, this delay function can also exit without waiting when the stop is called (the wait_flag is changed to 0 in the last interrupt!

I guess till today, this damn I2C should be okay .... Haha

// ================================================ ====================================

201109011609

Supplement:

One problem I 've been so depressed is why all the I2C operations were completed in the interrupt handler in the i2c-s3c2410.c. I always thought this was inappropriate, because we generally require that the interrupt processing function be as short as possible and exit quickly, we will push a large amount of time-consuming work to the end using methods similar to the work queue, in order to get a high response speed of the system. When I see that 2410 has completed all the functions in the interrupt callback function, I am depressed and want to know that the maximum speed of I2C is 400 K, the CPU speed is several hundred megabytes. If the I2C read/write operation is completed in the interrupt processing function, will it not cause a serious bottleneck? Considering that if we add peripherals such as G-sensor that need to frequently call the I2C driver, isn't the whole system slow down? I am troubled by this problem for a long time, because my I2C driver was written by referring to this driver, so I have to solve this problem!

Today, I started to think about this question again. I studied it carefully against the code of 2410. It seems that it is still like that. Indeed, all read and write operations are completed within the interrupt callback function .....

Suddenly, a flash of lightning... Hit one of my brain cells...

I am suddenly enlightened! The interrupt processing function does complete all the read and write operations. But aren't these read and write operations performed on the registers of the controller? Is that the operation on RX-FIFO and TX-FIFO? Can these operations be completed in a short time? The so-called read/write operation is either to empty the RX-FIFO read, or write the TX-FIFO full, and then interrupt the processing function to end. This FIFO is only 8-level deep, 11-bit wide, and the read/write time is negligible. When the interrupt processing function exits, the I2C controller completes the real time-consuming data sending and receiving... It has nothing to do with CPU ....

I finally figured it out, nnd. Now I found that I forgot what the Controller was doing... I thought that data sending and receiving would occur during the interrupt processing process... Careless... Sometimes this brain is just a small bend .... Shame... It's really a tough time for me...

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.