c++ class with task and timer

azz-zza
Posts: 45
Joined: Tue Sep 17, 2019 2:58 am

c++ class with task and timer

Postby azz-zza » Mon Mar 09, 2020 9:59 pm

//added code tag
Hello,

im attempting to incorporate the task and the timer creation into c++ class. And, predictably, this is not working for me.
I appreciate your feedback:

Code: Select all


#ifndef _ZAP_H
#define _ZAP_H
#include <Outlet.h>

class Zap : public Outlet {
  private:
	int _channel = 1 ; //CHANNEL 1
	//int DATA_PIN = 4;
	EventGroupHandle_t _evntgrp ;
	int _time_bit ; // = BIT0 ;
	TickType_t _t_outlet_cycle_ticks = 10000; //t_outlet_cycle/portTICK_RATE_MS ;
	int _stackDepth = 2048;

 protected:
	TimerHandle_t _handle;

 public:
	Zap( int pin, EventGroupHandle_t evgrp, int time_bit,  const char* TaskName, int ch=0, TickType_t cycle_ms = 10000 );
	static void 	stTask(void* param) ;
	void 			ToggleTask();
	void 			callback();
};

#endif // _ZAP_H
< ----- zap.cpp -------->

Code: Select all

#include "zap.h"

#define BLUE_PIN GPIO_NUM_2

// put into the common.h
const bool ON = true;
const bool OFF = false;

void Zap::callback() {
	xEventGroupSetBits(_evntgrp,_time_bit);
	Serial.println("Callback executed");
};


static void stTimerCallback(TimerHandle_t handle) {
		Zap* me = static_cast<Zap*>(pvTimerGetTimerID(handle));
		me->callback();
}

Zap::Zap(int pin, EventGroupHandle_t evgrp, int time_bit, const char* TaskName, int ch, TickType_t cycle_ms ) : Outlet (pin) {
	assert( cycle_ms >= 10000) ;
	assert( pin >=0 );
	assert( ch >= 0 );

	_evntgrp = evgrp;
	_time_bit  = time_bit ;
	_channel = ch ;
	_t_outlet_cycle_ticks = cycle_ms ;
	xTaskCreate(&Zap::stTask,(const char*)TaskName,_stackDepth,this,NULL,NULL);
	Serial.println("Task Created");
	_handle = 	xTimerCreate("Timer_name", _t_outlet_cycle_ticks, ON, this, &stTimerCallback);
	Serial.println("Timer created");
};

void Zap::stTask( void* param ) {
	static_cast<Zap *>(param)->ToggleTask();
};

void Zap::ToggleTask() {

	EventBits_t bits;
	bool _switch = OFF;
	time_t now;

	Serial.print("ToggleTask ");

	while (1) {
//		ESP_LOGI(TAG,"printTask starts, %lld \n", esp_timer_get_time());
        gpio_set_level(BLUE_PIN,0);
		Serial.println("in ToggleTask");
		bits = xEventGroupWaitBits(_evntgrp,_time_bit,pdTRUE, pdFAIL,pdMS_TO_TICKS(15000));
		Serial.printf("bits set  - %d \n",bits);
		if (bits == 1) {
//			ESP_LOGI(TAG,"Bits received with value = %d",TIME_BIT);
            Serial.printf("Bits received with value = %d \n",_time_bit);
			xEventGroupClearBits(_evntgrp,_time_bit);
//			ESP_LOGI(TAG,"BIT cleared");
//			// switch it ON after the first ( start + wait) run
			_switch = ( _switch == ON) ? OFF: ON ;
			toggle(_channel,_switch);
            gpio_set_level(BLUE_PIN,0);
			time(&now);
			Serial.printf(" %s, OUTLETTASK, Switch is set to - %d \n",ctime(&now),_switch);
//
		} else {
//			ESP_LOGI(TAG, " NO bits received");
			Serial.printf("OUTLETTASK, No bits received = %d \n",bits);
		}
		Serial.println(".. going back into while()");
	}
};

< -------- main.cpp ------- >

Code: Select all

void setup() {


	Serial.begin(115200);
	delay(3000);
//	Create event Group for use by all tasks
	eventGroup = xEventGroupCreate(); //check if NULL NOT returned.
	if (eventGroup == NULL) {
		printf("Event group was not created \n");
		Serial.println("Event group was not created");
	}
	Serial.println(" entering setup_tasks");

	Zap outlet(DATA_PIN, eventGroup,bit_time, "Task UNO") ;// (DATA_PIN, &eventGroup, bit_time, CHANNEL , 20000); 


and the log is attached.
Attachments
unnamed.png
unnamed.png (12.21 KiB) Viewed 4786 times
Last edited by azz-zza on Thu Mar 26, 2020 5:16 am, edited 1 time in total.

cryptkeeper
Posts: 3
Joined: Thu Mar 05, 2020 5:33 pm

Re: c++ class with task and timer

Postby cryptkeeper » Tue Mar 10, 2020 12:27 am

Hi,

Code: Select all

void setup() {

...

Zap outlet(DATA_PIN, eventGroup,bit_time, "Task UNO") ;// (DATA_PIN, &eventGroup, bit_time, CHANNEL , 20000);

}
You're creating the object "outlet" on the stack within the scope of the setup() function. When the function exits, all local ( stack ) created objects will be destroyed. If the task starts afterwards, it will try to access now invalid memory on the stack. Here is a short explanation:

https://stackoverflow.com/questions/100 ... 2#10081022

azz-zza
Posts: 45
Joined: Tue Sep 17, 2019 2:58 am

Re: c++ class with task and timer

Postby azz-zza » Thu Mar 26, 2020 5:14 am

Cryptkeeper,
thank you for the suggestion. Unfortunately it didn't solve the problem. and the code fails with slightly different error.

Code: Select all

setup():
...
 Serial.println(" entering setup_tasks");
 Serial.println (xTaskGetSchedulerState());
 Zap* outlet = new Zap(DATA_PIN, &eventGroup,bit_time, "Task UNO") ;
queue.c lines 1444 to 1447:

Code: Select all

	#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
	{
		configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
	}
	#endif

xTaskGetSchedulerState returns code "2" == taskSCHEDULER_RUNNING.
xTicksToWait, i suspect !=0, but i'm not entirely sure where to check.

Zap constructor is

Code: Select all

Zap::Zap(int pin, EventGroupHandle_t evgrp, int time_bit, const char* TaskName, int ch, TickType_t cycle_ms ) : Outlet (pin) {
	assert( cycle_ms >= 10000) ;
	assert( pin >=0 );
	assert( ch >= 0 );

	_evntgrp = evgrp;
	_time_bit  = time_bit ;
	_channel = ch ;
	_t_outlet_cycle_ticks = cycle_ms ;
	xTaskCreate(&Zap::stTask,(const char*)TaskName,_stackDepth,this,NULL,NULL);
	Serial.println("Task Created");
//	vTaskStartScheduler();
//	Serial.println("Task Scheduler Started");
	_handle = 	xTimerCreate("Timer_name", _t_outlet_cycle_ticks, ON, this, &stTimerCallback);
//				xTimerCreate(name_, period_, reload, this, func);
	Serial.println("Timer created");
};
Attachments
Screenshot_2020-03-26_01-06-15.png
Screenshot_2020-03-26_01-06-15.png (18.81 KiB) Viewed 4453 times

Who is online

Users browsing this forum: No registered users and 88 guests