Idea for FTM Application - Is a Race Condition Possible?

Status
Not open for further replies.

gfvalvo

Well-known member
Hi All.

As I was thinking about a solution to a question posted in another thread, I wondered if it would be possible to extend the input capture capability of a T3.2/5/6’s FTM to 32-bit values (from the FTM hardware’s 16 bits). My simplistic idea (untested code below) is to increment a variable representing the upper 16 bits every time the counter overflows (TOF flag). This would happen in the FTM ISR along with checking the CHF flag.

The only way I can think that this scheme would screw up is if an input edge was detected capturing the counter value right when it became 0x0000 but for some reason the TOF flag wasn’t yet set. I don’t think this scenario would happen if it is guaranteed that TOF will be set in the same clock cycle as CHF when a counter value of 0x0000 is captured. But, I can’t find a definitive statement one way or the other in the datasheet.

Anyone have any insight here?

Thanks.

Code:
#include "Arduino.h"

volatile bool newData = false;
volatile uint32_t capturedCount;

void setup() {
  const uint8_t triggerInput = 3;

  Serial.begin(115200);
  delay(2000);
  Serial.println("Starting");

  pinMode(triggerInput, INPUT);

  FTM1_SC = 0;
  FTM1_MODE = FTM_MODE_WPDIS;
  FTM1_CNT = 0000;      // Reset counter
  FTM1_MOD = 0xFFFF;       // Terminal count
  FTM1_CNTIN = 0;         // Counter reload value

  *portConfigRegister(triggerInput) = PORT_PCR_MUX(3);  // FTM1 Ch 0 pin - PTA12
  FTM1_C0SC = FTM_CSC_ELSA;   // FTM1 Ch0 capture on rising edge

  FTM1_SC &= ~FTM_SC_TOF;      // Force read-modify-write, clear TOF flag
  FTM1_C0SC &= ~FTM_CSC_CHF;  // Force read-modify-write, clear CHF flag
  FTM1_SC |= FTM_SC_TOIE;     // enable overflow interrupt
  FTM1_C0SC |= FTM_CSC_CHIE;  // enable channel interrupt

  //NVIC_SET_PRIORITY(IRQ_FTM1, 0); // should we change FTM1 interrupt priority?
  NVIC_ENABLE_IRQ(IRQ_FTM1);        // Enable FTM1 interrupts

  FTM1_SC = FTM_SC_CLKS(1); // run from sys clk, prescaler = 1
}

void loop() {
  uint32_t localCounter;

  if (newData) {
    noInterrupts();
    newData = false;
    localCounter = capturedCount;
    interrupts();
    Serial.print("New Count Captured: ");
    Serial.println(localCounter);
  }
}

void ftm1_isr() {
  static uint32_t upperWord = 0;

  if (FTM1_SC & FTM_SC_TOF) {
    upperWord += 0x10000;       // increment upper 16 bits
    FTM1_SC &= ~FTM_SC_TOF;      // Force read-modify-write, clear TOF flag
  }

  if (FTM1_C0SC & FTM_CSC_CHF) {
    capturedCount = upperWord | FTM1_C0V;   // captured 32-bit word
    FTM1_C0SC &= ~FTM_CSC_CHF;    // Force read-modify-write, clear channel flag
    newData = true;
  }
}
 
Last edited:
Status
Not open for further replies.
Back
Top