Skip to main content
Visitor II
March 9, 2021
Solved

Semaphore in C++

  • March 9, 2021
  • 2 replies
  • 976 views

I have a problem with operating the traffic light from the class method - every time the program crashes at that point.

Here is a simplified example for understanding what I'm writing about:

Class:

class IO_control
{
int num;
 
public:
 osSemaphoreId semaphoreHandle;
 int *outputs; 
 IO_control(int num,int outputs,osSemaphoreId semaphoreHandle);
 virtual ~IO_control();
 
 void SetOutputs();
 void UnsetOutputs();
};
 
 
/***********************************************/
 
 
IO_control::IO_control(int num, int *outputs,osSemaphoreId semaphoreHandle)
{
 this->num = num;
 this->outputs = outputs;
 this->semaphoreHandle = semaphoreHandle;
}
 
IO_control::~IO_control(){}
 
void IO_control::SetOutputs()
{
 osSemaphoreWait(semaphoreHandle, osWaitForever);
 *outputs |= num;
 osSemaphoreRelease(semaphoreHandle);
}
 
void IO_control::UnsetOutputs()
{
 osSemaphoreWait(semaphoreHandle, osWaitForever);
 *outputs &= ~(num);
 osSemaphoreRelease(semaphoreHandle);
}

I have three tasks that fight over one variable i_o_CAN.data_out, specifically four instances of the class + sending a message

two set it - the third copies it to the CAN message

typedef struct can_I_O_struct
 {
 union
 {
 int data_out;
 uint8_t out_arr[4];
 };
 
 union
 {
 int data_in;
 uint8_t in_arr[4];
 };
 } I_O_struct_can;
 
 
 I_O_struct_can i_o_CAN;
 
 osSemaphoreId CAN_IO_semaphoreHandle;
 
 IO_control out1(1,&i_o_CAN.data_out,CAN_IO_semaphoreHandle);
 IO_control out2(2,&i_o_CAN.data_out,CAN_IO_semaphoreHandle);
 IO_control out3(3,&i_o_CAN.data_out,CAN_IO_semaphoreHandle);
 IO_control out4(4,&i_o_CAN.data_out,CAN_IO_semaphoreHandle);
 
 void Task01(void const * argument)
 {
 for(;;)
 {
 out1.SetOutputs();
 osDelay(50);
 out1.UnsetOutputs();
 osDelay(1000);
 out2.SetOutputs();
 osDelay(50);
 out2.UnsetOutputs();
 osDelay(1000);
 }
 }
 
 
 void Task02(void const * argument)
 {
 for(;;)
 {
 out3.SetOutputs();
 osDelay(50);
 out3.UnsetOutputs();
 osDelay(2000);
 out4.SetOutputs();
 osDelay(50);
 out4.UnsetOutputs();
 osDelay(2000);
 }
 }
 
 void TaskCAN_Tx(void const * argument)
 {
 int tmp = 0;
 TxHeader2.StdId = 0x180;
 TxHeader2.DLC = 4;
 for(;;)
 {
 osSemaphoreWait(CAN_IO_semaphoreHandle, osWaitForever);
 if (i_o_CAN.data_out != tmp)
 {
 tmp = i_o_regs_can.data_out;
 TxData2[0] = i_o_CAN.out_arr[0];
 TxData2[1] = i_o_CAN.out_arr[1];
 TxData2[2] = i_o_CAN.out_arr[2];
 TxData2[3] = i_o_CAN.out_arr[3]; 
 if (HAL_CAN_AddTxMessage (&hcan2, &TxHeader2, TxData2, &TxMailbox2)!= HAL_OK)
 {
 Error_Handler ();
 } 
 }
 osSemaphoreRelease(CAN_IO_semaphoreHandle);
 }
 }

when I adjust it so that I operate the traffic lights directly from the tasks, it works

void IO_control::SetOutputs()
{
 *outputs |= num;
}
 
void IO_control::UnsetOutputs()
{
 *outputs &= ~(num);
}
 
//////////////////////////////////////////////////////////////////////
 
 void Task01(void const * argument)
 {
 for(;;)
 {
 osSemaphoreWait(CAN_IO_semaphoreHandle, osWaitForever);
 out1.SetOutputs();
 osSemaphoreRelease(CAN_IO_semaphoreHandle);
 osDelay(50);
 osSemaphoreWait(CAN_IO_semaphoreHandle, osWaitForever);
 out1.UnsetOutputs();
 osSemaphoreRelease(CAN_IO_semaphoreHandle);
 osDelay(1000);
 osSemaphoreWait(CAN_IO_semaphoreHandle, osWaitForever);
 out2.SetOutputs();
 osSemaphoreRelease(CAN_IO_semaphoreHandle);
 osDelay(50);
 osSemaphoreWait(CAN_IO_semaphoreHandle, osWaitForever);
 out2.UnsetOutputs();
 osSemaphoreRelease(CAN_IO_semaphoreHandle);
 osDelay(1000);
 }
 }

but in reality it's not that simple and I need to access the traffic light from insatnaci - in addition, it's a lot of useless code

    This topic has been closed for replies.
    Best answer by LUrba.1

    STM32F205

    but the problem is not related to hardware or freertos

    I've found that it's a matter of C++ and bad passing of the reference to the class.

    This is a functional solution:

    class IO_control {
     int num;
     
     public:
     osSemaphoreId & semaphoreHandle;
     int * outputs;
     IO_control (int num, int * outputs, osSemaphoreId & semaphoreHandle);
     virtual ~IO_control();
     
     void SetOutputs();
     void UnsetOutputs();
    };
    /***********************************************/
    IO_control::IO_control (int _num, int * _outputs, osSemaphoreId & _semaphoreHandle) :
     num(_num), semaphoreHandle(_semaphoreHandle), outputs(_outputs) {
    }

    2 replies

    Technical Moderator
    March 12, 2021

    Hi @Luděk Urbani�?​ ,

    Which product please?

    -Amel

    LUrba.1AuthorAnswer
    Visitor II
    March 13, 2021

    STM32F205

    but the problem is not related to hardware or freertos

    I've found that it's a matter of C++ and bad passing of the reference to the class.

    This is a functional solution:

    class IO_control {
     int num;
     
     public:
     osSemaphoreId & semaphoreHandle;
     int * outputs;
     IO_control (int num, int * outputs, osSemaphoreId & semaphoreHandle);
     virtual ~IO_control();
     
     void SetOutputs();
     void UnsetOutputs();
    };
    /***********************************************/
    IO_control::IO_control (int _num, int * _outputs, osSemaphoreId & _semaphoreHandle) :
     num(_num), semaphoreHandle(_semaphoreHandle), outputs(_outputs) {
    }