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

Thread: Teensy4.0 | TimerOne Library issue

  1. #1

    Teensy4.0 | TimerOne Library issue

    Board:- Teensy 4.0
    Teensyduino:- 1.51
    TimerOne Library:- https://github.com/PaulStoffregen/TimerOne

    I created simple Blink code

    Code:
    #include <TimerOne.h>
    
    const int led = LED_BUILTIN;  // the pin with a LED
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(115200);
      pinMode(led, OUTPUT);
      Timer1.initialize(100000);
      Timer1.attachInterrupt(blinkLED); // blinkLED to run every 0.10 seconds
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    }
    
    // The interrupt will blink the LED, and keep
    // track of how many times it has blinked.
    int ledState = LOW;
    volatile unsigned long blinkCount = 0; // use volatile for shared variables
    
    unsigned long guTime1, guTime2 = 0;
    void blinkLED(void)
    {
      guTime2 = micros();
      if (ledState == LOW) {
        ledState = HIGH;
        blinkCount = blinkCount + 1;  // increase when LED turns on
      } else {
        ledState = LOW;
      }
      digitalWrite(led, ledState);
      Serial.println(guTime2-guTime1);
      guTime1 = guTime2;
    }
    This only works properly with 150 MHz and 24 Mhz. This is not working with 600 MHz selection.

  2. #2
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    Yep it looks like, at 600mhz the slowest the code shows, the timer one code shows:
    Code:
    void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
    	setPeriod(microseconds);
        }
        void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
    	uint32_t period = (float)F_BUS_ACTUAL * (float)microseconds * 0.0000005f;
    	uint32_t prescale = 0;
    	while (period > 32767) {
    		period = period >> 1;
    		if (++prescale > 7) {
    			prescale = 7;	// when F_BUS is 150 MHz, longest
    			period = 32767; // period is 55922 us (~17.9 Hz)
    			break;
    		}
    	}

  3. #3
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    @Frank - I think what he is noticing is if you run at 150 MHz, the serial Output shows:
    Code:
    100001
    100001
    100001
    100001
    100001
    Or a 10th of a second
    But at 600 MHz you see
    Code:
    55923
    55924
    55923
    55923
    55923

  4. #4
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,878
    Yes, seen this after I hit "send"

  5. #5
    Quote Originally Posted by KurtE View Post
    Yep it looks like, at 600mhz the slowest the code shows, the timer one code shows:
    Code:
    void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
    	setPeriod(microseconds);
        }
        void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
    	uint32_t period = (float)F_BUS_ACTUAL * (float)microseconds * 0.0000005f;
    	uint32_t prescale = 0;
    	while (period > 32767) {
    		period = period >> 1;
    		if (++prescale > 7) {
    			prescale = 7;	// when F_BUS is 150 MHz, longest
    			period = 32767; // period is 55922 us (~17.9 Hz)
    			break;
    		}
    	}
    I see so with 600 MHz Smallest we can setup is 55922 us?

  6. #6
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    I believe that is the longest period you can specify at 600Mhz, which is reflected in your output.

    Of course you do have other alternatives, like use the Interval Timer library.

  7. #7
    Quote Originally Posted by KurtE View Post
    I believe that is the longest period you can specify at 600Mhz, which is reflected in your output.

    Of course you do have other alternatives, like use the Interval Timer library.
    Yes, I was using that and thought TimerOne might be better options for Interrupt priority set and all.
    Do we have any list of default interrupt priorities for Teensy 4.0?

  8. #8
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    I believe they all start out at priority 128. You can use priority method on your interrupt handler to set them to something else.

    You might also be able to use @luni's TeensyTimerTool stuff, to create a timer. I don't think he has any code directly in this timer code to set an Interrupt priority, but maybe, else maybe can somehow ask the class for something that will get you back to the ISR number?

  9. #9
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    896
    Here the link to the TeensyTimerTool stuff: https://github.com/luni64/TeensyTimerTool It currently handles FTM, GPT, QUAD timers and a software timer (PIT is under construction). It doesn't touch the interrupt priority (currently) so, you can easily set that from outside the framework with the usual call to NVIC_SET_PRIORITY

  10. #10
    Quote Originally Posted by luni View Post
    Here the link to the TeensyTimerTool stuff: https://github.com/luni64/TeensyTimerTool It currently handles FTM, GPT, QUAD timers and a software timer (PIT is under construction). It doesn't touch the interrupt priority (currently) so, you can easily set that from outside the framework with the usual call to NVIC_SET_PRIORITY
    Thank you Kurt and Luni, I was not aware about this library. Let me look into detail for this one.
    Do we have the any list for Teensy 4 INTERRUPT NAME list?. I checked interrupt.c

  11. #11
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    896
    You probably mean the IRQ numbers? They are in imxrt.h for the Teensy 4. If you want to change the priority for say the GPT1 timer module to 48 you'd do a

    Code:
    NVIC_SET_PRIORITY(IRQ_GPT1, 48);
    Here a copy of the numbers:

    Code:
    enum IRQ_NUMBER_t {
            IRQ_DMA_CH0 =           0,
            IRQ_DMA_CH1 =           1,
            IRQ_DMA_CH2 =           2,
            IRQ_DMA_CH3 =           3,
            IRQ_DMA_CH4 =           4,
            IRQ_DMA_CH5 =           5,
            IRQ_DMA_CH6 =           6,
            IRQ_DMA_CH7 =           7,
            IRQ_DMA_CH8 =           8,
            IRQ_DMA_CH9 =           9,
            IRQ_DMA_CH10 =          10,
            IRQ_DMA_CH11 =          11,
            IRQ_DMA_CH12 =          12,
            IRQ_DMA_CH13 =          13,
            IRQ_DMA_CH14 =          14,
            IRQ_DMA_CH15 =          15,
            IRQ_DMA_ERROR =         16,
            IRQ_CTI0 =              17,
            IRQ_CTI1 =              18,
            IRQ_CORE_ERROR =        19, // TODO - name?
            IRQ_LPUART1 =           20,
            IRQ_LPUART2 =           21,
            IRQ_LPUART3 =           22,
            IRQ_LPUART4 =           23,
            IRQ_LPUART5 =           24,
            IRQ_LPUART6 =           25,
            IRQ_LPUART7 =           26,
            IRQ_LPUART8 =           27,
            IRQ_LPI2C1 =            28,
            IRQ_LPI2C2 =            29,
            IRQ_LPI2C3 =            30,
            IRQ_LPI2C4 =            31,
            IRQ_LPSPI1 =            32,
            IRQ_LPSPI2 =            33,
            IRQ_LPSPI3 =            34,
            IRQ_LPSPI4 =            35,
            IRQ_CAN1 =              36,
            IRQ_CAN2 =              37,
            IRQ_ADDR_ERR =          38, // TODO: name?
            IRQ_KPP =               39,
            IRQ_TSC_DIG =           40,
            IRQ_GPR_IRQ =           41,
            IRQ_LCDIF =             42,
            IRQ_CSI =               43,
            IRQ_PXP =               44,
            IRQ_WDOG2 =             45,
            IRQ_SNVS_IRQ =          46,
            IRQ_SNVS_SECURITY =     47,
            IRQ_SNVS_ONOFF =        48,
            IRQ_CSU =               49,
            IRQ_DCP0 =              50, // TODO: ???
            IRQ_DCP1 =              51, // TODO: ???
            IRQ_DCP2 =              52, // TODO: ???
            IRQ_TRNG =              53,
            IRQ_SJC_IRQ =           54,
            IRQ_BEE =               55,
            IRQ_SAI1 =              56,
            IRQ_SAI2 =              57,
            IRQ_SAI3_RX =           58,
            IRQ_SAI3_TX =           59,
            IRQ_SPDIF =             60,
            IRQ_BROWNOUT0 =         61,
            IRQ_Reserved1 =         62,
            IRQ_TEMPERATURE =       63,
            IRQ_TEMPERATURE_PANIC = 64,
            IRQ_USBPHY0 =           65,
            IRQ_USBPHY1 =           66,
            IRQ_ADC1 =              67,
            IRQ_ADC2 =              68,
            IRQ_DCDC =              69,
            IRQ_SOFTWARE =          70,
            IRQ_Reserved2 =         71,
            IRQ_GPIO1_INT0 =        72,
            IRQ_GPIO1_INT1 =        73,
            IRQ_GPIO1_INT2 =        74,
            IRQ_GPIO1_INT3 =        75,
            IRQ_GPIO1_INT4 =        76,
            IRQ_GPIO1_INT5 =        77,
            IRQ_GPIO1_INT6 =        78,
            IRQ_GPIO1_INT7 =        79,
            IRQ_GPIO1_0_15 =        80,
            IRQ_GPIO1_16_31 =       81,
            IRQ_GPIO2_0_15 =        82,
            IRQ_GPIO2_16_31 =       83,
            IRQ_GPIO3_0_15 =        84,
            IRQ_GPIO3_16_31 =       85,
            IRQ_GPIO4_0_15 =        86,
            IRQ_GPIO4_16_31 =       87,
            IRQ_GPIO5_0_15 =        88,
            IRQ_GPIO5_16_31 =       89,
            IRQ_FLEXIO1 =           90,
            IRQ_FLEXIO2 =           91,
            IRQ_WDOG1 =             92,
            IRQ_RTWDOG =            93,
            IRQ_EWM =               94,
            IRQ_CCM1 =              95,
            IRQ_CCM2 =              96,
            IRQ_GPC =               97,
            IRQ_SRC =               98,
            IRQ_Reserved3 =         99,
            IRQ_GPT1 =              100,
            IRQ_GPT2 =              101,
            IRQ_FLEXPWM1_0 =        102,
            IRQ_FLEXPWM1_1 =        103,
            IRQ_FLEXPWM1_2 =        104,
            IRQ_FLEXPWM1_3 =        105,
            IRQ_FLEXPWM1_FAULT =    106,
            IRQ_FLEXSPI2 =          107, // RT1060 only
            IRQ_FLEXSPI =           108,
            IRQ_SEMC =              109,
            IRQ_SDHC1 =             110,
            IRQ_SDHC2 =             111,
            IRQ_USB2 =              112,
            IRQ_USB1 =              113,
            IRQ_ENET =              114,
            IRQ_ENET_TIMER =        115,
            IRQ_XBAR1_01 =          116,
            IRQ_XBAR1_23 =          117,
            IRQ_ADC_ETC0 =          118,
            IRQ_ADC_ETC1 =          119,
            IRQ_ADC_ETC2 =          120,
            IRQ_ADC_ETC_ERR =       121,
            IRQ_PIT =               122,
            IRQ_ACMP0 =             123,
            IRQ_ACMP1 =             124,
            IRQ_ACMP2 =             125,
            IRQ_ACMP3 =             126,
            IRQ_Reserved4 =         127,
            IRQ_Reserved5 =         128,
            IRQ_ENC1 =              129,
            IRQ_ENC2 =              130,
            IRQ_ENC3 =              131,
            IRQ_ENC4 =              132,
            IRQ_QTIMER1 =           133,
            IRQ_QTIMER2 =           134,
            IRQ_QTIMER3 =           135,
            IRQ_QTIMER4 =           136,
            IRQ_FLEXPWM2_0 =        137,
            IRQ_FLEXPWM2_1 =        138,
            IRQ_FLEXPWM2_2 =        139,
            IRQ_FLEXPWM2_3 =        140,
            IRQ_FLEXPWM2_FAULT =    141,
            IRQ_FLEXPWM3_0 =        142,
            IRQ_FLEXPWM3_1 =        143,
            IRQ_FLEXPWM3_2 =        144,
            IRQ_FLEXPWM3_3 =        145,
            IRQ_FLEXPWM3_FAULT =    146,
            IRQ_FLEXPWM4_0 =        147,
            IRQ_FLEXPWM4_1 =        148,
            IRQ_FLEXPWM4_2 =        149,
            IRQ_FLEXPWM4_3 =        150,
            IRQ_FLEXPWM4_FAULT =    151,
            IRQ_ENET2 =             152, // RT1060 only
            IRQ_ENET2_TIMER =       153, // RT1060 only
            IRQ_CAN3 =              154, // RT1060 only
            IRQ_Reserved6 =         155,
            IRQ_FLEXIO3 =           156, // RT1060 only
            IRQ_GPIO6789 =          157, // RT1060 only
            IRQ_SJC_DEBUG =         158,
            IRQ_NMI_WAKEUP =        159
    };

  12. #12
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,878
    You can use the name from the list above, too.

  13. #13
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,632
    @luni - was also wondering if it would make sense in one or more of your classes to have a method which returns the IRQ number associated with that object?
    And/Or have a method like IntervalTImer (priority) where if appropriate they could set the underlying Interrupt handlers IRQ priority?

  14. #14
    Quote Originally Posted by KurtE View Post
    @luni - was also wondering if it would make sense in one or more of your classes to have a method which returns the IRQ number associated with that object?
    And/Or have a method like IntervalTImer (priority) where if appropriate they could set the underlying Interrupt handlers IRQ priority?
    That would be really good if we can get that return back so we can make sure to setup numbers. Right now I am using one Digital Pin interrupt and IntervalTimer so let me find out which one is suitable for me from above list.

  15. #15
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    896
    Technically this would be possible, but it might be confusing for the average user.

    • The priority is not bound to the actual timer but to its parent module. I.e. for a T4 all PITs or all 4 Timers of a TMR module have the same priority. (BTW, for the PITs this changed from the T3x where each IntervalTimer had its own priority).
    • If you use a timer from the pool you don't even know from which module this timer comes. Setting the priority might be even more confusing
    • The library also provides software timers which don't have a settable priority at all

    The design goal of the library was to provide an easy to use and generic interface to basic functionality of the timers. But of course I'm willing to improve the interface. Any input on how the interface should look like would be welcome. Anyway, here an example how to set the priority for a GPT1 based timer. Adaption to the other modules (FTM, TMR) is straight forward.

    Code:
    #include "TeensyTimerTool.h"
    using namespace TeensyTimerTool;
    
    void toggle()
    {
      digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));
    }
    
    PeriodicTimer t1(GPT1);
    
    void setup()
    {
      pinMode(LED_BUILTIN,OUTPUT);
    
      t1.begin(toggle, 100'000);
      NVIC_SET_PRIORITY(IRQ_GPT1, 16);
    }
    
    void loop()
    {
    }

Posting Permissions

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