Nano Every Board - TCB1 timer as I/P Pulse width Measurement Mode from Pin D3/Port PF5

i am trying use TCB1 in "pulse width meaurement" mode, with the pulse being routed from pin D3 to EVENT SYSTEM PERIPHERAL via Channel 4 to end user of event TCB1. the TCB1 is configured for Positive edge trigger start

I am generating the pulse manually and hence the negative edge of the pulse might take longer to occur and the TCB1.CNT is bound to overflow... but, here the Software crashes and has to be reset to start again. i have taken care of the overflow case also via ISR, but, still have the problem of crash. Any help is appreciated.



#include <megaAVR_TimerInterrupt.h>
#include <megaAVR_TimerInterrupt.hpp>
#include <megaAVR_ISR_Timer.h>
#include <megaAVR_ISR_Timer.hpp>

 #include <SoftwareSerial.h>

 
// variables , FLAGS ;
static bool timerb0_OVRFL_FLAG = false ;
static bool timerb1_OVRFL_FLAG = false ;
static bool timerb2_OVRFL_FLAG = false ;
unsigned int loopycounty = 0  ;
               
                static unsigned int timerb1FREQ_CNT  ;
                static bool Status_Flag_b1_freqcnt ;
                
              
                static unsigned int timerb1DUTY_CNT  ;
                static bool Status_Flag_b1_dutycnt ;
                
           
void setup() 
{
  // put your setup code here, to run once:


  


PORTA.DIR = 0x01 ;
PORTA.OUT = 0x0 ;

PORTB.DIR = 0x07 ;
PORTB.OUT = 0x0 ;

PORTC.DIR = 0x40 ;
PORTC.OUT = 0x0 ;

PORTD.DIR = 0x07 ;
PORTD.OUT = 0x0 ;

// port E all are i/ps so no initial value needed

PORTF.DIR = 0x10 ;
PORTF.OUT = 0x0 ;



// initialize serial communication at 9600 bits per second: 
    Serial.begin(9600); 

    while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
     

     /* Disable interrupts */
 cli();//stop interrupts


// Timers TCB1

TCB1.CTRLB = 0x04 ;
TCB1.EVCTRL = 0x01 ;

TCB1.INTCTRL = 0x01 ;
TCB1.CNT = 0 ;




// EVSYS Drivers


EVSYS.CHANNEL4 = 0x4D ;




EVSYS.USERTCB1 = 0x05 ; // TCB1 to CH4




sei();//allow interrupts  


}




void loop() 
{
  // put your main code here, to run repeatedly:
  TCB1.CTRLA = 0x01 ;

  do
  {
    
    
    
    if(timerb1_OVRFL_FLAG)
    {
      timerb1_OVRFL_FLAG = false ;
      Serial.print("\n\t Timer B1 overflowed");
    }
    



    

    
    if((Status_Flag_b1_freqcnt) && (Status_Flag_b1_dutycnt))
    {
      Status_Flag_b1_freqcnt = false ;
      Status_Flag_b1_dutycnt = false ;
      //Serial.print("\n\t Timer B1 Freq - ") ;
      //Serial.print(timerb1FREQ_CNT) ;
      Serial.print("\n\t Timer B1 Duty - ") ;
      Serial.print(timerb1DUTY_CNT) ;
      TCB1.INTCTRL = 0x01 ;
    }

    
      
    delay(1000) ;
    loopycounty += 1 ;
    Serial.print("\n\t ARDUINO NANO EVERY is looping now    ");
    Serial.print(loopycounty) ;
  }while (1) ;
  
  

}


ISR(TCB1_OVF_vect)
{
 TCB1.INTCTRL = 0x00 ;
 timerb1_OVRFL_FLAG = true ;
 PORTA.OUT = 0x01 ;  // USING THIS PIN to signal interrupt occurrence for debug only
}

ISR(TCB1_CAPT_vect)
{
      TCB1.INTCTRL = 0x00 ;
      
      //timerb1FREQ_CNT = TCB1.CNT ;
      timerb1DUTY_CNT = TCB1.CCMP ;
      PORTA.OUT = 0x01 ;  // USING THIS PIN to signal interrupt occurrence for debug only
      
      Status_Flag_b1_freqcnt = true ;
      Status_Flag_b1_dutycnt = true ;

      
}

I’m not familiar with the libraries you called, but I have a few hints:

-1 Are you sure it shouldn’t be --.cpp?

-2 Type B timers in the Nano Every have only one interrupt line. In FRQPW mode it’s triggered by the second rising edge of the event. Overflow is not registered.

-3 As overflow is not registered the number in TCB1.CNT may be lower than the number in TCB1.CCMP at the time of the interrupt. This may cause the calculation to go wrong.

-4 The clock of the TCB’s is, by Arduino standard, taken from the TCA, pulses at 4 microseconds, making maximum counting time 262 milliseconds.


Further comments on the program you posted:

-6 Apparently files --.hpp do exist. I haven’t found the ones you called yet.

-7 You didn’t use the Auto Format. If the listing looks strange after using Auto Format there’s something wrong, might be as simple as a missing semicolon or parenthesis.

-8 Why timerb0_OVRFL_FLAG and timerb2_OVRFL_FLAG?

-9 Why static? Static is meant for local variables.

In setup():

-10 For better readability, use PORTB.DIR = 0b00000111 instead of PORTB.DIR = 0x07. Three months from now you may be puzzled “what did I mean?”

-11 PORTB.OUT = 0 is superfluous, the RESET did that for you.

-12 while (!Serial) is superfluous, the Nano Every doesn’t have a native USB.

-13 cli() and sei() are superfluous, Arduino IDE standard allows no interrupts till the end of setup().

-14 To avoid unwanted interrupts you better reset the flag in the flag register before enabling them, they might be triggered already and become effective when interrupts are enabled at the end of setup().

-15 TCB1.INTCTRL = 1 is superfluous, you’re doing that at the start of loop().

-16 TCB1.CNT = 0 is superfluous, both in PW mode (mode = 0x04) and FRQPW mode (you talk about dutycycle) the counter is zero’ed when the first edge occurs.

In loop():

-17 TCB1.CTRLA = 1 is superfluous, Arduino IDE standard sets all 4 TCBs for PWM at 50%, enabled, TCB0 and TCB1 can be connected to an output when analogWrite(.,.) is called with the appropriate pin number.

-18 TCB1.INTCTRL = 1 is used two more times, but never made zero. What did you want it to do?

-19 What did you want while(1) to do?

ISRs:

-20 The purpose of libraries is to take tasks from the user. If necessary they may contain ISRs because the maker of that library knows many users don’t want or lack the knowledge to write them. Still you wrote two ISRs.

-21 Neither TCB1_OVF_vect nor TCB1_CAPT_vect will be recognized by the compiler, only TCB1_INT_vect is known.

-22 How did you want to calculate a dutycycle?

Compilation errors:

-23 I had to remove the libraries to get some results from the compiler. Nothing was missing because of this removal, apparently they aren’t needed.

-24 PORTB.DIR doesn’t exist. None of those port registers exist.

-25 The compiler detected those non-existent interrupt vectors and warns for them.

-26 The compiler warns for unused variables.

You’ve got quite a to-do list here. I’m sorry to sound negative.

Next time: do try to compile. The errors and warnings can be useful.

Thanks stitech for going thru and the comments. Here below are some of my answers:

  1. Are you sure it shouldn’t be --.cpp? maybe ur right, but, it compiles and throws no errors - either way i dont use any API resources from those libraries except the basic register definitions already availble in the Arduino core for the ATMEGA 4809 uC

2)Type B timers in the Nano Every have only one interrupt line. In FRQPW mode it’s triggered by the second rising edge of the event. Overflow is not registered. - i am using the i/p capture pulse width mode - but end result agreed, maybe overflow is not registered in this mode too.

3)As overflow is not registered the number in TCB1.CNT may be lower than the number in TCB1.CCMP at the time of the interrupt. This may cause the calculation to go wrong. - Yes agree as overflow is not registered and i expect this behaviour. But, the problem i am facing is the SW crashes on the 1st pulse positive edge occurence and the execution doesnt even reach the interrupt. I am grappling with the crash scenario here for which i seek help
4) The clock of the TCB’s is, by Arduino standard, taken from the TCA, pulses at 4 microseconds, making maximum counting time 262 milliseconds. - My driver code directly uses the CLKPER option which shud be 16 Mhz to the TCB1.CNT register. i am not using the TCA CLK tick for TCB1. so i expect multiple overflows b4 the falling edge of the pulse occurs. But, the TCB1 peripheral seems to be causing a crash on overflow, which is ridiculous behaviour by a uC....

I missed the do of the do..while loop before. This explains point 19.

This do..while loop creates an endless loop, but you set TCB1INTCTRL outside that loop. This shouldn’t crash the controller.

You try to switch the timer on and off with TCB1.INTCTRL. Chances are that while TCB1.INTCTRL is off, the interrupt flag in TCB1.INTFLAGS is set, as the timer keeps running. That flag will be passed to the interruptcontroller at the moment TCB1.INTCTRL is set. This shouldn’t crash the controller.

The compiler warnings about the ISRs are exactly that: warnings. They don’t stop the compiling, but the ISRs are not compiled either.

What will crash the controller is the fact that an interrupt occurs with no ISR. Unused interrupt vectors divert to the RESET vector.

Thanks for the detailed look into code. My prime approach currently is to make the TCB1 technically work.
So,ur coding improvements points are well taken and will address them later.

points 14 , 21 , 25 are immediate to address for me and will do it right away
point 24 - portb.dir exists in the atmeag4809 - every board controller. chk in user guide
point 23 - yes agreed, i dont use any of these, they are legacy code file carry over will remove them
point 17 - of course arduino standard sets it, but, i will override some of the settings and not call those APIs from the arduino core. Typically TIMER A and TCB3 i cant touch as they are basic needed to arduino core and timing functions. TCB1,2,3 i can use as long as i dont call APIs from arduino core that use them differently
Point 18 - INTCTRL is made 0 in ISR itself but, problem for the crash maybe the ISRs themselves are not available as u pointed out in point 21. my trust is that when i fix ur point 21(ISR) the crash shud stop.

let me try point 21 1st and see what happens!!

Yes exactly, ur point 21 - "my ISRs are not there" is the prime suspect as per ur hint.... this is exactly what i see happen on the board - when the 1st pulse occurs it starightaway crashes!!

ur right if the ISRs are not there, the uC can crash. Let me chk this and hopefully my problem gets solved

You’re right. Both the datasheet and iom4809.h say that PORTB.DIR should exist. Still: I got a compiler error about it.

Stranger still: it accepted PORTA.DIR without complaint.

I need to think long and hard about this.

You apparently didn’t receive the warnings about the ISRs. Maybe you should turn on ‘verbose’ (File => Preferences).

Maybe compilers are generated by AI tools from Google, Microsoft, etc on a lighter side... :rofl:

let me try the verbose setting.
software tools will be radically influenced by AI already, these are all the effects to expect...in our world
20 years ago a compiler wud never generate final object code file w/o "an intended ISR by coder"

but, nowadays compilers might treat coder's portions of code as optional :rofl:

I don’t agree with your ‘optional’. My take on it is: ‘name not recognized’. And a warning was issued, you just didn’t read it.

Yes, point 21 - finally works when fixed. the ISR was missing and the uC was crashing.

Thanks for the gr8 help stitech by patiently going thru and trying my code

Stitech need help. i just fixed the ISR topic last week and went ahead and suddenly today all the Nano Every Projects are throwing errors of the PORTX.DIR/OUT statements.. they were even compiling until this afternoon and they suddenly stopped.. i am clueless, any help

this happened to u as well when u compiled my code last week a encountered the errors... Now my compiler is throwing it too...what is the problem with IDE? why cant it be stable...

On my computer it didn’t compile either.

It did compile after I changed the emulation setting: Tools => Registers emulation
it should read “None(ATMEGA4809)”.
If not, click and change it.

It looks like an update has happened, losing this setting.

will try this, thanks

Now tried this on IDE 2.X and it worked...

How does this change happen uncontrolled any ways to prevent it

I posted this question myself, I was referred to this:

No, you can’t protect yourself from things like this.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.