Need help with FTM settings

Ok, I think I got it. The ISR code you have doesn't clear the interrupt flag, so the interrupt code get's called over and over again in an infinite loop.

If you've only enabled the timer overflow interrupt, you'll want the first line in the ISR to clear the flag by writing a 0 to the TOF bit:

Code:
FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0) | FTM_SC_TOIE;

If some of the channel interrupts are enabled (in the FTM0_CxSC regs), you'll need more code to determine which interrupt flag is set.
 
Hey, thank you guys for your great support!

It finally works flawlessly. Though I knew I had to clear that flag, I was messing with the wrong registers.

Actually, it just needed this line at the begining of the ISR:

Code:
void ftm0_isr(void)
{
    FTM0_SC &= ~FTM_SC_TOF;
    //..
}

Now I kindly ask you few more questions:

(1) - it's ok to rely on this interrupt only for the entire program flow (hence no main() content)?

I don't need any asynchronous operations, I may check ADC/GPIO/serial from within this triggered ISR. But what if the FTM timer fails? Do I have to activate an watch-dog or something (I guess Teensy have a hw built-in one)?

(2) - if I have to turn off all the channels (FTM0_CnV = 0) due to a hardware alarm (overcurrent/overvoltage), the interrupt would continue to trigger the ISR, right? (as the overflow is related to FTM0_MOD only).

(3) - how to make sure there's no other (ghost) interrupts to create an extra overhead? I wont use delay(), milis() and such (just ADC and Serial).
 
it's ok to rely on this interrupt only for the entire program flow (hence no main() content)?
Yep :)
A watchdog is a good idea. But it's unlikely the FTM will fail

if I have to turn off all the channels (FTM0_CnV = 0) due to a hardware alarm (overcurrent/overvoltage), the interrupt would continue to trigger the ISR, right?
You'd have to try it. I don't know anything about the FTM registers really

how to make sure there's no other (ghost) interrupts to create an extra overhead?
Just set your interrupt to the highest priority ;)
 
A watchdog is a good idea. But it's unlikely the FTM will fail.

Ok, then I rely on Paul's good job. ;)

Just set your interrupt to the highest priority.

I guess I should learn more about interrupts. What "highest priority actually mean? I know about priority ranking, but how it works exactly?

A lower priority interrupt would NEVER disturb a higher priority one? Its workflow will be cut (or just paused) when a higher priority interrupt is firing?
 
Could someone try to run this code:

Code:
const uint8_t pinLED = 13; // built-in LED
uint8_t LED_ON = true;
uint32_t iCounter = 0;

void setup(void)
{
Serial.begin(38400);
pinMode(pinLED, OUTPUT);
// FTM0 init
FTM0_POL = 0;  
FTM0_OUTMASK = 0xFF; 
FTM0_SC = 0x00;
FTM0_CNT = 0x00;
FTM0_CNTIN = 0; // Counter initial value
FTM0_C2SC = FTM_CSC_ELSB | FTM_CSC_MSB;
FTM0_C3SC = FTM_CSC_ELSB | FTM_CSC_MSB;
FTM0_MOD = 3000;
FTM0_C2V = 100; 
FTM0_C3V = 200; 
CORE_PIN9_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; 
CORE_PIN10_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
NVIC_SET_PRIORITY(IRQ_FTM0, 64); 
NVIC_ENABLE_IRQ(IRQ_FTM0);
FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0) | FTM_SC_TOIE; // update status register
FTM0_OUTMASK = 0xF3; // enable only FTM0_CH2 and FTM0_CH3 channels 
}



void ftm0_isr(void) 
{
FTM0_SC &= ~FTM_SC_TOF; // clear the interrupt overflow flag
iCounter ++; // time base counter
if (iCounter >= 8000) // 1 second
    {
    iCounter = 0;
    Serial.println(">");
    if (LED_ON == true) { digitalWriteFast(pinLED, HIGH); }
    else { digitalWriteFast(pinLED, LOW); }
    LED_ON = !LED_ON;
    }
}

void loop(void) { 
//Serial.println(">"); 
}

The Serial.print doesn't seems to work. What could be the reason?
 
It works for me.
I did change the baud rate to 9600 though. Although it appears to work on 38400 as well

Also on the topic of interrupts I believe you are correct. The lower the priority number the high the priority of the interrupt

As a bit of trivia you can use the K20's GPIOx_PTOR register to toggle a pin's output like so:
Code:
GPIOC_PTOR |= 1<<5; // Toggle LED
 
Last edited:
It works for me.
I did change the baud rate to 9600 though. Although it appears to work on 38400 as well

Something strange is happening here.

At first (with my full code), it was the ADC not working (not reading the input voltage). Anyway, the serial was working just fine.

I cleaned up everything except the code above and now the Serial is not working anymore.

It must be something with my laptop's serial (USB) IRQ (by the way, I'm using linux (xubuntu). What OS were you using?).

But what could be the reason of ADC malfunction?

Also on the topic of interrupts I believe you are correct. The lower the priority number the high the priority of the interrupt

I was wondering what's happening if a lower priority ISR is running then a higher priority one is triggering. The CPU abort the lower priority ISR?

As a bit of trivia you can use the K20's GPIOx_PTOR register to toggle a pin's output like so:
Code:
GPIOC_PTOR |= 1<<5; // Toggle LED

That's cool, thanks for sharing! I guess I'm going to read the whole K20's reference manual.
 
I was trying to play with these statements:

Code:
NVIC_SET_PRIORITY(IRQ_UART0_LON, 32); 
NVIC_SET_PRIORITY(IRQ_UART0_STATUS, 64); 
NVIC_SET_PRIORITY(IRQ_UART0_ERROR, 96); 
NVIC_SET_PRIORITY(IRQ_FTM0, 128); 

NVIC_ENABLE_IRQ(IRQ_UART0_LON); 
NVIC_ENABLE_IRQ(IRQ_UART0_STATUS); 
NVIC_ENABLE_IRQ(IRQ_UART0_ERROR); 
NVIC_ENABLE_IRQ(IRQ_FTM0);

It randomly works by firing the Serial.print for EXACTLY four times then it won't print anymore (even after power on reset or USB port change).

Could anyone explain the meaning of these "IRQ_UART0_LON", "IRQ_UART0_STATUS" and "IRQ_UART0_ERROR"? I've tried a lot of combinations (changing the priority rankings, enabling/disabling one or another) with no luck.
 
Could anyone explain the meaning of these "IRQ_UART0_LON", "IRQ_UART0_STATUS" and "IRQ_UART0_ERROR"?

The UART can generate interrupts for many different reasons.

From a software-only perspective, the ideal would be a separate interrupt vector for every individual case. But each separate interrupt vector has a hardware cost. So instead, Freescale (and pretty much all the semiconductor companies) design their chips so several conditions trigger the same interrupt. This reduces the hardware cost, but it means you have to add code inside the interrupt to read status bits to determine which condition actually caused the interrupt.

As a sort of middle ground, Freescale created 3 physical interrupt vectors, instead of only 1. This allows your code to be more efficient. The status interrupt is the main one you'd normally use. Teensyduino's code for Serial1, Serial2, Serial3 uses only this one and never the error or lon ones. Even within the status interrupt, you have to check if the interrupt was caused by transmit, receive, transmit complete, etc.

The error interrupt is used for a variety of error conditions. The idea is if you want to detect these errors and do something special, your code that normally handles data doesn't need to spend extra time checking for the error status. Instead, you'll get a separate interrupt. Likewise, if you're implementing the complex lonworks protocol, all that extra stuff has its own interrupt, so you don't need to burden your main data handling interrupt with extra work.
 
Thank you very much for your comprehensive explanations, Paul. That means those interrupts have nothing to do with the Serial (print) process?

In the mean time, I found out that when I'm using both ADC channels (each one in readContinuos mode) it only reads "0". Except that, everything works fine. ;)
 
Thank you very much for your comprehensive explanations, Paul. That means those interrupts have nothing to do with the Serial (print) process?

When asking these sorts of questions, small details matter. For example, when you ask "to do with the Serial (print) process?", the word "Serial" is capitalized. Normally on Teensy that means USB virtual serial. We also have Serial1, Serial2, Serial3.

Maybe I'll write another lengthy reply here later this week. Consider your question and use of technical keywords wisely.
 
Sorry, I was referring to Serial.print() function (USB virtual serial).

I didn't find any reference to virtual serial in K20 manual hence I don't know the difference. I thought the PC drivers emulate the serial port though.

Btw, if I change the Teensy emulation (to anything but serial, like "raw hid" or "keyb+mouse+joy") the serial communication (oops, the Serial.print()!) works. The problem is I can't communicate with the board outside Arduino environment as the PC can't find the ttyACM0 port anymore.

Is there any documentation about these various Teensy emulations?
 
But what could be the reason of ADC malfunction?
I couldn't possibly say without some example code

What OS were you using?
Ubuntu with XFCE installed. So basically xubuntu

I was wondering what's happening if a lower priority ISR is running then a higher priority one is triggering. The CPU abort the lower priority ISR?
It won't abort it. It'll just service the higher priority interrupt there and then and after completion return back to the lower priority ISR

Can you run the terminal command 'lsusb' and post your results along with 'dmesg | grep tty'
Ensuring your teensy is plugged in
 
Thank you very much for your time (especially for being a xfce fan. ;) ).

The ADC problem is gone: I was trying to read an analog pin not allocated to ADC_1 (noob).

It won't abort it. It'll just service the higher priority interrupt there and then and after completion return back to the lower priority ISR.

Ok, I got it. Anyway, I'll stick with one ISR only (the one triggered by FTM0) as I'm not doing any asynchronous stuff.

Btw, I've read that priority "0" is assigned to systick's IRQ by default but I didn't noticed any problem when I've assigned "0" to FTM0 IRQ (not with 16, 32, 48.. 128 though). Am I becoming paranoid?!
 
XFCE is great. I'm really not a fan of unity that ubuntu has chosen to go with

Btw, I've read that priority "0" is assigned to systick's IRQ by default
You're very observant!

If you do wish to lower the priority of this use:
Code:
SCB_SHPR3 = 0x20200000;  // Systick = priority 32 (defaults to zero)
 
I'm trying to do the same thing. I need to change the carrier frequency and duty cycle real time. I'm using the Arduino IDE with a Teensy 4.1 and can't compile this code, I must be missing a library or header file. Can you show the complete working code?
 
Back
Top