object pointer hard fault

joe31093 wrote on Tuesday, September 22, 2015:

FreeRTOS V8.1.2, MSP432P401R Demo project, CCS Version: 6.1.0.00104

I am try to make a general C++ class for working with tasks. I have a base class that contains the static function for xTaskCreate, which is used by the derived class when creating the task. The derived class this pointer is passed to xTaskCreate and eventually used by the static function to call a derived class method. But in the call to the derived class method, a hard fault is generated. Anyone have any suggestions on where to look to resolve this issue?

TaskBase.h

class TaskBase {
public:
TaskBase();
virtual ~TaskBase();
virtual void createTask() = 0;
virtual void run();

static void runTask(void* param);

protected:
string m_taskName;
unsigned short m_taskStackSize;
unsigned long m_taskPriority;
unsigned long m_tickDelay;
};

TaskBase.cpp

TaskBase::TaskBase():
m_taskName(“Base”),
m_taskStackSize(512),
m_taskPriority(tskIDLE_PRIORITY + 1),
m_tickDelay(pdMS_TO_TICKS(100))
{
}

TaskBase::~TaskBase()
{
}

void TaskBase::runTask(void* param)
{
TaskBase* basePtr = static_cast<TaskBase*>(param);
if (basePtr != NULL)
basePtr->run();** // HARD FAULT HERE**
}

void TaskBase::run()
{
}

TaskSystemData.h

class TaskSystemData: public TaskBase {
public:
TaskSystemData();
virtual ~TaskSystemData();
virtual void createTask();
virtual void run();

virtual unsigned long getTickDelay() {return m_tickDelay;}

};

TaskSystemData.cpp

TaskSystemData::TaskSystemData()
{
}

TaskSystemData::~TaskSystemData()
{
}

void TaskSystemData::createTask()
{
xTaskCreate((TaskFunction_t) &TaskBase::runTask, // The function that implements the task.
m_taskName.c_str(), // The text name assigned to the task - for debug only as it is not used by the kernel.
m_taskStackSize, // The size of the stack to allocate to the task.
this, // The parameter passed to the task.
m_taskPriority, // The priority assigned to the task.
NULL);
}

void TaskSystemData::run()
{
unsigned long sequenceIndex = 0;
unsigned long sequenceValue = 0;
unsigned long tickDelay = pdMS_TO_TICKS(100);

// more code....

}

main.cpp

// more code...

TaskSystemData systemDataTask;
systemDataTask.createTask();

//Start real time scheduler
vTaskStartScheduler();

heinbali01 wrote on Tuesday, September 22, 2015:

Hi Joe,

Tonight I will try-out what you want to do.

Except for some asterixes that are removed by formatting, the code looks OK to me.

Regards.

heinbali01 wrote on Tuesday, September 22, 2015:

Could you extend the class TaskSystemData with 2 operators:

class TaskSystemData {
public:
    static void* operator new (size_t size)
    {
        return (void*)pvPortMalloc( size );
    }
    static void operator delete(void *p)
    {
        vPortFree( p );
    }

and use new() to create the object:

    TaskSystemData *task;
    
    // Later on...
        task = new TaskSystemData;

I haven’t tried it out yet, the above is just a guess :slight_smile:

Regards, Hein

joe31093 wrote on Tuesday, September 22, 2015:

Hi Hein,

Thanks for the reply. I will give what you suggested a try later today. One thing I did last night that got it working was that I move the TaskSystemData object out of the main function (in to global space) and it worked. I don’t understand why yet. I looked at the registers when it failed and did not get a lot of informaiton from it. Is it a memory map issue?

main.cpp

TaskSystemData systemDataTask;** // moved out of main scope**

int main( void )
{
SystemConfig systemConfig;
systemConfig.setupHardware();
systemConfig.setupClocks();

//TaskSystemData systemDataTask;
systemDataTask.createTask();

// Start real time scheduler
vTaskStartScheduler();

return 0;

}

heinbali01 wrote on Tuesday, September 22, 2015:

That’s it, first you declared it as an automatic variable, it was located in the initial application stack.

After starting the scheduler, there will be a new stack per task, and the initial stack might have become unreliable.

That is why I asked you to try create it with new(). But declaring it as a global variable works as well. As long as the constructor is called (implicitly), and as long as the space is not reused for something else.

Make sure that new and delete always refer to a safe memory allocator, the default usage of malloc()/free() won’t be thread safe.

One more thing is worth telling: when using C++ and GCC, I get a strange error when declaring a static object within a function:

    void foo()
    {
    static CSomeClass someObject;
        // Code using someObject
    }

/../main.cpp:415: undefined reference to `__cxa_guard_acquire'
/../main.cpp:415: undefined reference to `__cxa_guard_release'

As I rarely run into this problem, I just avoid the situation by making the object static in the module:

    static CSomeClass xSomeObject;
    void foo()
    {
        // Code using xSomeObject
    }

Wish you fun with C++ coding!

richard_damon wrote on Wednesday, September 23, 2015:

If you want to look at it, I have just posted some code for a FreeRTOS C++ wrapper library at https://github.com/richard-damon/FreeRTOScpp

It is one I have been using for many years. The documentation needs some work (it if very sparse, but the code is simple so fairly understandable).

As to the gcc guard_acquire / release error, my guess is that gcc is looking for some functions to interface to the RTOS for exclusive access. static variables within a function are not created until the function is first entered, and if you are in a multi-threaded enviroment (like in FreeRTOS with the scheduler running) there is a possible race condition for initializing a local static variable. Many compilers, like gcc, have define a set of functions like these that the RTOS is supposed to define to make this work. (sometimes there is also a hook in malloc/free similar to this to make them safe).

I suppose that ideally, someone would dig through the various compilers documentation for what these functions are, and what the really need to do, and add a file in the portable layer to define them. (Sounds like a great way for a user to provide help back).

rtel wrote on Wednesday, September 23, 2015:

I really must link to this from the FR.o website!

Regards.

joe31093 wrote on Thursday, September 24, 2015:

Thanks for help guys.