Быстрее TimerOne с Teensy 4.0 (600 МГц)

У меня есть teensy 4.0, работающая на частоте 600 МГц и обладающая двойным супермасштабированием (т. е. иногда может выполнять две инструкции за такт). Мне нужно, чтобы прерывание происходило быстрее, чем каждую микросекунду. Я подсчитал, что процессор может выполнять мой код на такой скорости с некоторыми разумными накладными расходами. Можно ли настроить TimerOne (или аналогичный) для создания прерываний чаще одного раза в микросекунду?

Заранее спасибо.

, 👍1

Обсуждение

Вы про библиотеку TimerOne или про сам таймер?, @chrisl

@chrisl хорошо, я использовал библиотеку TimerOne, но если единственный способ получить более быстрое прерывание - не использовать эту библиотеку, то меня это устраивает., @Jachdich

https://forum.pjrc.com/, @Juraj


2 ответа


2

Для этого можно использовать TeensyTimerTool. Он предоставляет общий интерфейс для аппаратных таймеров (TMR, GPT, PIT) и 20 программных таймеров. Поскольку соединение периферийных устройств таймера с ядром ARM довольно неэффективно, программные таймеры могут лучше подходить для прерываний менее микросекунды. Если вы предпочитаете аппаратные таймеры, я предлагаю использовать таймер GPT (также поддерживается библиотекой). Вы можете настроить его на использование тактовой частоты 150 МГц вместо стандартной тактовой частоты 24 МГц. Таким образом, что-то вроде частоты прерывания 2 МГц должно быть возможным.

Документацию можно найти здесь: https://github.com/luni64/TeensyTimerTool/wiki

,

0

У меня была похожая проблема с Teensy 3.5. Я обнаружил, что использование «Таймера периодического прерывания (PIT)»; позвольте мне генерировать прерывания каждые 300 нс. Я полагаю, что с Teensy 4.0 должна быть возможность генерировать прерывание каждые 100 нс. Вот код, который работает у меня на Teensy 3.5: с комментариями на французском языке и некоторыми ссылками в комментариях. Я проверяю сигнал на осциллографе.

// ex00305_Timer_pit0_isr_rapid.ino
/*

FONCTIONNE TRES BIEN

Le signal n'est pas très stable, mais acceptable.
J'imagine que d'autres routines d'interruption perturbe la précision, comme la routine millis()

L'instruction suivante améliore la stabilité. visiblement.
NVIC_SET_PRIORITY(IRQ_PIT_CH0, 0);

Le but est de tester l'utilisation du Timer1 .c.f
/home/bg/Arduino/Teensy/Teensy_3_5_manual_K64P144M120SF5RM.pdf
Page 1083, Chapter 41 : "Periodic Interrupt Timer (PIT)"

Pour la gestion des timers PIT, c.f.
====================================
https://github.com/loglow/PITimer/blob/master/PITimer.cpp

********************************************************************************** */

#define PINOUT1 34
#define LEDRED  24
#define LEDYELLOW  25
#define LEDGREEN  26

volatile byte bEtat = 0;

void setup() {
    //============
    pinMode(PINOUT1, OUTPUT);
    digitalWriteFast(PINOUT1, HIGH);

    pinMode(33, OUTPUT);
    pinMode(34, OUTPUT);
    pinMode(LEDRED, OUTPUT);  digitalWriteFast(LEDRED, LOW);
    pinMode(LEDYELLOW, OUTPUT);  digitalWriteFast(LEDYELLOW, LOW);
    pinMode(LEDGREEN, OUTPUT);  digitalWriteFast(LEDGREEN, LOW);

    //если (SIM_SCGC6_PIT == 0b100000000000000000000000) digitalWriteFast(LEDYELLOW, HIGH);
    SIM_SCGC6 |= SIM_SCGC6_PIT; // См. страницу 317. PIT Clock Gate Control SIM_SCGC6_PIT == 0b100000000000000000000000

    // См.: /home/bg/.arduino15/packages/teensy/hardware/avr/1.58.1/cores/teensy3/kinetis.h
    // #define NVIC_ENABLE_IRQ(n) (*(( Летучие uint32_t *)0xE000E100 + ((n) >> 5)) = (1 << ((n) & 31)))
    // включаем прерывание IRQ
    NVIC_SET_PRIORITY(IRQ_PIT_CH0, 0); // Высший приоритет, чтобы не беспокоить другие прерывания. Улучшение заметно!
    NVIC_ENABLE_IRQ(IRQ_PIT_CH0);
    PIT_TCTRL0 = 3; // 0b011; // разрешаем прерывания Таймера 0; запуск таймера 0 IRQ_PIT_CH0 == 48 Dans #elif определено(__MK64FX512__)
    //если (IRQ_PIT_CH0 == 48) digitalWriteFast(LEDGREEN, HIGH);

    // Стирание флага таймера, чтобы разрешить другие прерывания, необходимо завершить работу
    PIT_TFLG0 = 1;

    // Порядок инструкций по важности !
    //"""""""""""""""""""""""" """"""""""""""""""""
    PIT_MCR = 0;  // включаем PIT
    //PIT_LDVAL0 = 600-1; // == таймер настройки 10 микросекунд 0 для xxx циклов Fréqu = 60 МГц dt = 16,666 нс
    //PIT_LDVAL0 = 120-1; // == 2-секундные микрофоны
    //PIT_LDVAL0 = 60-1; // == 1 секундный микрофон
    //PIT_LDVAL0 = 30-1; // == 500 нс
    //PIT_LDVAL0 = 24-1; // == 400 нс
    //PIT_LDVAL0 = 21-1; // == 350 нс
    //PIT_LDVAL0 = 20-1; // == 333 нс
    //PIT_LDVAL0 = 18-1; // == 300 нс
    PIT_LDVAL0 = 120-1;
} // настраивать

void loop() {
    //===========
} // петля

void pit0_isr() {  // См. mk20dx128.c
    //===============
    // Надеюсь, что смогу продержаться некоторое время

    // Очистим флаг таймера, чтобы разрешить дальнейшие прерывания
    // Doit être неправильно дебютирует в рутине !!!
    PIT_TFLG0 = 1;

    if (bEtat) {
        digitalWriteFast(PINOUT1, HIGH);
        //digitalWriteFast(LEDRED, HIGH);
        bEtat = 0;
    }
    else {
        bEtat = 1;
        digitalWriteFast(PINOUT1, LOW);
        //digitalWriteFast(LEDRED, LOW);
    }

} //pit0_isr
,