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

Thread: Teensy 4.0 Interrupt missing using TeensyTimerTool and Serial.print

  1. #1
    Junior Member
    Join Date
    Mar 2021
    Posts
    7

    Teensy 4.0 Interrupt missing using TeensyTimerTool and Serial.print

    Hi

    I discovered the following situation:
    - There is an interrupt missing, when I combine a "1" micro second interrupt and a Serial.print. Take a look at the picture.
    - with the delay it is possible to move the position.
    - taking out the print command all interrupts show up

    I downloaded: https://github.com/luni64/TeensyTimerTool
    using PeriodicTimer t1(PIT);

    Compliling for: Teensy 4.0, 600MHz, fast
    - the frequency and option have no influence

    I'm convinced the problem is somewhere in the timer or print lib. Unfourtuntely I have no clue how to fix that.



    Andre
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	SCR07.PNG 
Views:	8 
Size:	46.3 KB 
ID:	28755  
    Attached Files Attached Files

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,189
    just to see ...Change:
    Code:
    volatile uint16_t  writeIdx;
     // ...
    void loop() {
      cli();
      int16_t widx = (int16_t)writeIdx;
      sei();
    //...
    to, this since it is already volatile, and 32 bit copies are atomic:
    Code:
    volatile uint32_t  writeIdx;
     // ...
    void loop() {
      //cli();
      int32_t widx = writeIdx;
      //sei();
    //...
    Disabling interrupts might be causing trouble?

    Also if really provably a problem perhaps a variation of:
    Code:
    FASTRUN void captureData() {
      digitalWriteFast(MONITOR_OUT1, HIGH);
    
    // just for testing - enough time for scope detect
        delayNanoseconds(500);
    
      digitalWriteFast(MONITOR_OUT1, LOW);
    }

  3. #3
    Junior Member
    Join Date
    Mar 2021
    Posts
    7
    I just tried your hints
    - taking out the cli and sei has no influence on the situation but is basicly a good hint
    - the scope capture is with peek detect and 100 MHz bandwidth and digital 300MHz so I don't believe it is a measureing problem

    an additional delay of a 100ns in the interrupt roution like
    ...
    delayNanoseconds(100);
    digitalWriteFast(MONITOR_OUT1, LOW);

    brings up even more missing interrupts.

    I also shorten the longest path through the interrupt, because it must not be done in the interrupt
    idleCnt =0;
    if (bitDetect){
    bitDetect =false;
    if (bitMask){
    if (bitValue){
    byteValue |= bitMask;
    }
    bitMask >>=1;
    }else{
    uint8_t state = S_IDLE_DETECT;
    if (bitValue){
    state |= S_ACK;
    }
    // if (!(streamState & S_ADDRESS)){
    // if (byteValue & 0x01){
    // byteRwAdr = S_R_W;
    // }
    // byteValue >>=1;
    // }
    // state |= byteRwAdr;
    // byteRwAdr |= S_ADDRESS;
    uint16_t idx = writeIdx;
    stateBuffer[idx] = streamState = state;
    // stateBuffer[idx] = state;
    // streamState = state | byteRwAdr;
    valueBuffer[idx++] = byteValue;
    if (idx >= BUFFER_SIZE){
    idx =0;
    }
    writeIdx = idx;

    bitMask =0x80;
    byteValue = 0;
    }
    }

    unfortunately with no positive effect on the problem.

  4. #4
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,849
    Just a guess without testing: Per default the PIT runs at 24MHz only. This can generate some relatively large bus sync waiting times. So 1MHz interrupt rate together with your relatively large code in the ISR might simply be too high? Can you use one of the TMRs instead? They run at 150Mhz which should reduce the effect. If this doesn't help I can have a closer look later today.

  5. #5
    Junior Member
    Join Date
    Mar 2021
    Posts
    7
    Thanks, it is a good advise to use the TMR source. It runs now without glitches.

    I assume it has something to do with the IO structure using the timer and serial port.

    As a "nice" sideeffect now I have to define 2000 kHz to get a 1 us interrupt.

    Sofar I would say thank you for the hints and major problme solved.

    Andre

  6. #6
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,849
    Quote Originally Posted by andreobi View Post
    Thanks, it is a good advise to use the TMR source. It runs now without glitches.
    I assume it has something to do with the IO structure using the timer and serial port.
    Probably not. Due to the architecture of the chip the internal busses need some time to sync data. This adds some waiting time at the end of the ISR. The larger the difference of the frequency of the CPU to that of the peripheral, the longer this may take. If the ISR time plus the waiting time gets longer than the time between two interrupts you can run into issues.

    By default the PIT runs at 24MHz the TMRs at 150MHz. You can also switch the PIT to 150MHz in the config file if you want to give it a try.


    As a "nice" sideeffect now I have to define 2000 kHz to get a 1 us interrupt.
    Actually that should not happen. It should give you 2MHz interrupt frequency. Can you post a minimal example showing that effect?

  7. #7
    Junior Member
    Join Date
    Mar 2021
    Posts
    7
    Basicly I changed the serial output to Serial1 for easier pin access.
    I set the interrupt timing to 1000kHz. CPU 600MHz, and PeriodicTimer t1(TMR3);
    on the snapshot you can see that the interrrupt (yellow) schifts when the start bit of the uart happens, but this must be in a specific timeposition of the interrupt, so it won't shift always.

    I'll simplify the code on Wednesday.
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	SCR08.PNG 
Views:	8 
Size:	57.8 KB 
ID:	28762  

  8. #8
    Junior Member
    Join Date
    Mar 2021
    Posts
    7
    My assumption is: the serial interrupt is preparing the next byte to send ( this seems to take upto 530ns) and the timer interrupt happend in that time. So the timer interrupt handling is delayed. If the delay is to huge it will show up as a missing interrupt.

    The other topic is the time, a typical period is 1.71 us.

  9. #9
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,189
    Quote Originally Posted by andreobi View Post
    I just tried your hints
    - taking out the cli and sei has no influence on the situation but is basicly a good hint
    - the scope capture is with peek detect and 100 MHz bandwidth and digital 300MHz so I don't believe it is a measureing problem

    an additional delay of a 100ns in the interrupt roution like
    ...
    delayNanoseconds(100);
    digitalWriteFast(MONITOR_OUT1, LOW);

    brings up even more missing interrupts.

    I also shorten the longest path through the interrupt, because it must not be done in the interrupt
    ...

    unfortunately with no positive effect on the problem.
    @luni got you to a solution!

    But what the suggestion in post #2 was : replace ALL _isr code with just the indicated lines, not ADD the delay.

    At 1 MHz there are less than 600 cycles available - and then adding in the details on bus timing etc ... the guess was the _isr() was being serviced when the next one triggered and was missed.

  10. #10
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,849
    Quote Originally Posted by andreobi View Post
    My assumption is: the serial interrupt is preparing the next byte to send ( this seems to take upto 530ns) and the timer interrupt happend in that time. So the timer interrupt handling is delayed. If the delay is to huge it will show up as a missing interrupt.
    Makes sense. Did you try increasing the priority of the timer interrupt?

    Quote Originally Posted by andreobi View Post
    The other topic is the time, a typical period is 1.71 us.
    Also makes sense. If you look at the TimerTool config file you see that the TMR runs with the default prescaler of 128. (see here: https://github.com/luni64/TeensyTime...nfig.h#L42-L58)

    With this setting you get:
    1/150MHz * 128 = 0.853Ás per timer tick. Your 1MHz setting ends up in a timer overflow setting of two ticks -> 2 * 0.853Ás = 1,71Ás

    Set the prescaler to PSC_1 to get a better granularity at high frequencies (1/150MHz = 6.66ns)

  11. #11
    Junior Member
    Join Date
    Mar 2021
    Posts
    7
    I think I got a solution for me

    - I changed to timer GTP1, it is muche more pecise for higher frequency
    - and I also lift up the interrupt priority, so the timer comes ahead the serial communication

  12. #12
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,849
    Good to hear that it works for you now. Have fun with the TimerTool

Posting Permissions

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