c++armembeddedatmelstudiosamd21

'ClassName' and 'ClassInstance' was not declared in this scope


I am attempting to program an Atmel SAM D21 microcontroller using C++ in Atmel Studio. I'm trying to create periodic hardware interrupts using one of the on-chip timers.

I created Timer4 class to set up the timer from main.cpp. I tried to create a Timer4 instance called MyTimer4 in the main function, but it says

'Timer4' was not declared in this scope 
'MyTimer4' was not declared in this scope

I've seen many similar discussions pointing to incorrect/circular #includes. But, I don't seem to see the same problem on my own. Any ideas?


Main.cpp

#include "timerSAMD21.h"
#include "sam.h"

void SampleADC(void)
{

}

int main(void)
{
    SystemInit();

    Timer4 MyTimer4;

    MyTimer4.setRate(1000);
    MyTimer4.onEvent(SampleADC);
    MyTimer4.start;
}

timerSAMD21.h

#ifdef TIMERSAMD21_H
#define TIMERSAMD21_H

#include "tc.h"
#include "tc4.h"
#include "gclk.h"

typedef void (*voidFuncPtr)(void);

class Timer4
{

public:

    Timer4() {};
    void setRate(int frequency);
    void start(void);
    void end(void);
    void onEvent(voidFuncPtr funcOnEvent); 

private:

    void configure(int frequency);
    void enable(void);
    void disable(void);
    void reset(void);
};

#endif

timerSAMD21.cpp

#include "timerSAMD21.h"

voidFuncPtr callback = NULL;

void Timer4::setRate(int frequency) {
    configure(frequency);
}

void Timer4::start(void) {
    enable();
}

void Timer4::end(void) {
    disable();
    reset();
}

void Timer4::configure(int frequency) {
    //Configuration code here. Removed for Stack Overflow.
}

void Timer4::enable(void){
    REG_TC4_CTRLA |= TC_CTRLA_ENABLE;  //Enable timer
    while (TC4->COUNT8.STATUS.bit.SYNCBUSY);
}

void Timer4::disable(void) {
    REG_TC4_CTRLA &= ~TC_CTRLA_ENABLE;
    while (TC4->COUNT8.STATUS.bit.SYNCBUSY);  
}

void Timer4::reset(void) {
    REG_TC4_CTRLA = TC_CTRLA_SWRST;
    while (TC4->COUNT8.STATUS.bit.SYNCBUSY);
    while (TC4->COUNT8.CTRLA.bit.SWRST);

}

void Timer4::onEvent(voidFuncPtr funcOnEvent){
    callback = funcOnEvent;
}

#ifdef __cplusplus
extern "C" {
#endif

void IRQHandlerTimer4(void) {
    if (callback != NULL) 
    {
        callback();
    }

    REG_TC4_INTFLAG = TC_INTFLAG_MC0;
}

#ifdef __cplusplus
}
#endif

Solution

  • (Note: Making an answer in order to get this out of the list of unanswered questions. Miles seems to have decided not to answer and I do not consider the problem a typo.)

    The way you attempt to prevent the reinclusion of your header is causing it to only make the content of the header visible if the guard-macro happens to be defined already, which it of course never is.

    In order to fix this, change the

    #ifdef TIMERSAMD21_H
    #define TIMERSAMD21_H
    

    into

    #ifndef TIMERSAMD21_H
    #define TIMERSAMD21_H
    

    This will first keep the header content visible the first time it is included.
    It will then define the guard macro, which will prevent the header content from being compiled a second time in the same translation unit, i.e. code file.