Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 8 of 8

Thread: Yet another post about interrupts.

  1. #1
    Junior Member
    Join Date
    Oct 2016
    Location
    Paris
    Posts
    5

    Yet another post about interrupts.

    Hello,

    I have been a long time lurker of this (great) forum and I have usually found answers by searching old posts but I must admit I am stuck on this one... If anyone can point me in the right direction, I would be very grateful

    I am using a teensy 3.2 to generate a 40khz signal using the IntervalTimer class. I need a very precise timing: each interrupt should not be delayed by more than a few cycles.
    What the interrupt routine does is mostly switching the state of 4 digital pins simultaneously to create 4 similar waves. Yet, I cannot use PWN to do that because I do not generate a perfectly periodical signal: sometime, a given pin may is not be switched depending on other external variables.

    If the teensy do only that, all is fine..

    But then, at the same time, I am driving a SSD1306 screen via I2C (for monitoring). As you have probably guessed, its messes with my interrupt routine and, when communicating with the I2C device, the timer becomes irregular.

    I did set the priority of the IntervalTimer routine to 0 using the setPriority() method and I thought that this would enable my interrupt (it is very short) to get called even during an I2C interrupt. I guess I do not understand how interrupt nesting works !

    I also tried to use the i2c_t3 library instead of Wire and I tried the IRQ and DMA modes. Still no luck... The immediate transfer mode of i2c_t3 does not seem to be working with the adafruit library for SSD1306.

    Does anyone know how I could fix my problem. I do not mind if a i2c transfer sometimes fails.. but I need the timer interrupt to stay fairly regular.

    Thank you !

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,173

  3. #3
    Junior Member
    Join Date
    Oct 2016
    Location
    Paris
    Posts
    5
    Thank you Paul for the link. It is indeed somewhat similar to what I am doing...

    In my case, I can generate the data to output a little bit in advance. So, it seems that my best option might be, as mentioned in the other thread, to buffer some data in advance and use a DMA channel triggered by a timer to set the pins (all 4 output pins on the same port). By using double buffering and chaining two DMA channels, I should be able to create a regular continuous signal.

    Before, I start wasting several hours trying to implement this and understand how DMA works, can you tell me if this strategy can (at least theoretically) works ? If I understand correctly, DMA transfer should make the signal "interrupt proof" w.r.t. I2C since it does not use the processor. However, how long does it take between the end of a DMA transfer and the start on next chained one ? Is is possible that I will miss a tick of the timer (which will be between 40khz and 400Khz) ?

    Thanks!

  4. #4
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,442
    I think, the most important is to understand that even when using the i2c_t3 library with DMA, the endTransmission() function remains blocking. To get a non-blocking i2c send, use the sendTransmission() function which is documented on the i2c_t3 GitHub page.

  5. #5
    Junior Member
    Join Date
    Oct 2016
    Location
    Paris
    Posts
    5
    Yes, I looked at the code of the i2c_t3 library. However, I do not really care that the method is blocking here since I generate the signal from an interrupt. The problem is that, during an i2c transaction, the timer interrupt is sometime delayed. I guess this must happen either because interrupts are currently disabled or because another 0 priority interrupt is already running.

  6. #6
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,442
    That's exactly what is called blocking. That's why I suggested that you do a non blocking transfer which allows your interrupts to launch in time while the i2c transfer would continue in the background.

  7. #7
    Junior Member
    Join Date
    Oct 2016
    Location
    Paris
    Posts
    5
    Quote Originally Posted by Theremingenieur View Post
    That's exactly what is called blocking. That's why I suggested that you do a non blocking transfer which allows your interrupts to launch in time while the i2c transfer would continue in the background.
    Ok! Well, there is something I do not understand So, I tried using i2c_t3 with DMA transfer in non-blocking mode. It is indeed better but there is still an annoying perturbation of the signal...

    On the other hand, I just adapted the DMA + FTM timer approach of the Octo library for a quick test and the signal is perfect (much better than the interrupt generated version, even without i2c interference). So I will use this method (and, in the process, learn how to use DMA).

    Thank you both very much for your help !

  8. #8
    Senior Member
    Join Date
    Dec 2014
    Posts
    253
    The interrupt handler runs with interrupts disabled. Thus, doing anything blocking in that function will cause other same- or lower-priority interrupts to be delayed until the blocking operation is completed. (I think the Teensy library just lumps all interrupts into a single priority level, btw -- letting some interrupt handlers pre-empt other interrupt handlers would not be Arduino compatible.)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •