How to run two tasks simultaneously with stm32f750n8h6

now i have changed to this,

void StartDefaultTask(void argument)
{
/
USER CODE BEGIN 5 /
/
Infinite loop */

while(1)
{

  if(HAL_GPIO_ReadPin(ADC1_DRDY_GPIO_Port,ADC1_DRDY_Pin)==0)
  {
	  //			IS_ADC_DRDY = 0;
	  __disable_irq();
	  ADC_DRDY_ISR();
	  __enable_irq();

  }

still, this is also wrong, please send your email and will share the whole code and let me know your feedback. i am really tired of this.

Where is that task BLOCKING to wait for the signal and let the other task run.

You need to read about the basics of how tasks work. Look at how a Semaphore works for instance.

A computer only does one thing at a time, so the code needs to let the OS know it doesn’t need to be running at the moment, so it knows it can give time elsewhere.

As @richard-damon pointed, you need to understand what blocking means in FreeRTOS. I’d strongly recommend reading this book - https://www.freertos.org/fr-content-src/uploads/2018/07/161204_Mastering_the_FreeRTOS_Real_Time_Kernel-A_Hands-On_Tutorial_Guide.pdf

One way to do is to use task notification. The following pseudo code tries to explain the idea -

static TaskHandle_t xADCReaderTaskHandle = NULL;

void ADCReaderTask( void * pvParams )
{
    ( void ) pvParams;

    for( ; ; )
    {
        /* Wait for a notification from the ISR. The CPU will be
         * free to execute other tasks till a notification is
         * received. Block indefinitely (without a timeout, so no
         * need to check the function's return value) to wait for a
         * notification. NOTE!  Real applications should not block
         * indefinitely, but instead time out occasionally in order
         * to handle error conditions that may prevent the interrupt
         * from sending any more notifications. */
        ulTaskNotifyTake( pdTRUE,          /* Clear the notification value before exiting. */
                          portMAX_DELAY ); /* Block indefinitely. */

        /* Read the ADC and process the value. */
    }
}
/*-----------------------------------------------------------*/

void ADCReadyISR( void )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    /* Notify the task that the ADC is ready. */
    vTaskNotifyGiveFromISR( xADCReaderTaskHandle, &xHigherPriorityTaskWoken );

    /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch
     * should be performed to ensure the interrupt returns directly to the highest
     * priority task.  The macro used for this purpose is dependent on the port in
     * use and may be called portEND_SWITCHING_ISR(). */
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
/*-----------------------------------------------------------*/

Thanks for the reply, yes as richard-damon said I am trying to block and release with semaphore. So will let you know the status.

As you meant task notification is notified whether the interrupt is raised or not.
is that right.??
If so interrupt was raised from the callback function means so how can i notify with ISR, i didn’t get it clearly.

Where did I say that? Read the documentation of ulTaskNotifyTake. You can also use xTaskNotifyWait.

This line is not clear. Please elaborate (is possible with code).

First, sorry for the inconvenience. I thought it’s like that i will explain what actually i am doing to read the ADC data and then how i am running two ADCs.

  1. Using ADS1256 IC with SPI communication of port2(SPI2) and here waiting for DRDY pin to go LOW,
  2. Using TIM2 for microsecond delay.
  3. Once DRDY goes LOW, read the analog data and converted it into a voltage value.
  4. Similarly for ADC2, with port4 (SPI4) and TIM3 for micro second delay.

while coming to simultaneous run, keeping both ADCs in one task like default task it’s running successfully. but in separate tasks, it’s stuck in the DRDY pin to go LOW while debugging.
so i kept ADC1 in default task with semophoreAcquire() & release and then task2 with another ADC2 without semophoreAquire(), the result was same. so now i am reading the book which you suggested try to work on ulTaskNotifyTake API.

Can you elaborate what are you trying to achieve? If you want to make sure that only one task interacts with ADC at a time, you can acquire mutex before reading it and release afterwards. Something like -

void ADC1ReaderTask( void * pvParams )
{
    ( void ) pvParams;

    for( ; ; )
    {
        /*
         * 1. Acquire mutex.
         * 2. Read ADC1.
         * 3. Release mutex.
         * 4. Process the value.
         */
    }
}
/*-----------------------------------------------------------*/

void ADC2ReaderTask( void * pvParams )
{
    ( void ) pvParams;

    for( ; ; )
    {
        /*
         * 1. Acquire mutex.
         * 2. Read ADC2.
         * 3. Release mutex.
         * 4. Process the value.
         */
    }
}
/*-----------------------------------------------------------*/

Can you put your code in a GitHub repo and share link?

If you have two data ready interrupt, you will need two data ready semaphores, one for each, and each task waits on its semaphore Which will be given in the appropriate ISR when it detects the data ready interrupt for that channel.

Actually, i am using two sensors called differential pressure sensor and pressure sensor and need both pressure sensor values at a time, that’s why i am trying to achieve the two ADC reading simultaneously, I hope you understand.

i have uploaded necessary files to GitHub and please have a look and let me know if need anything more.

And what triggers the ADC to start its sampling and converting? THAT is what you need to be as simultaneous as possible.

If you have an external signal triggering the conversion, if it goes into the two ADCs they will be simultaneous. (And you need two ADC to do what you want, not two channels of one chip).

If you are using a SPI triggered conversion, you will need to try to trigger the sending of the SPI command to start the conversion as close as possible with each other. The STM provided SPI driver probably doesn’t do a good job at this.

The reading of the data after it is converted isn’t critical timing, it just needs to be done before the next sample occurs, unless you have a time critical requirement between making and using the measurement.

Thanks for the reply, i tried with only one, let me try with two semaphore and will update the status.

When each ADC data ready pin goes low then it triggers the each ADC to read the sample and conversion.

No, here i am using TWO same (ADS1256) ADCs so i have data ready pin for each independently.
when it gets low based on that each ADC reading starts.

Reading the code you shared, it seems like you have 2 ADCs connected over SPI and you are trying to communicate with them simultaneously.

Please do the following and share results:

  1. Update the task definitions to the following and share resutls:
void StartDefaultTask(void *argument)
{
    for(;;)
    {
        while(HAL_GPIO_ReadPin(DRDY_GPIO_Port,DRDY_Pin));
        if(HAL_GPIO_ReadPin(DRDY_GPIO_Port, DRDY_Pin) == 0)
        {
            __disable_irq();
            ADC_DRDY_ISR();
            __enable_irq();
        }
    }
}

void StartTask02(void *argument)
{
    for(;;)
    {
        while(HAL_GPIO_ReadPin(ADC2_DRDY_GPIO_Port,ADC2_DRDY_Pin));
        if(HAL_GPIO_ReadPin(ADC2_DRDY_GPIO_Port, ADC2_DRDY_Pin) == 0)
        {
            __disable_irq();
            ads1256_drdy_isr();
            __enable_irq();
        }
    }
}

To narrow down the problem, I’d suggest to remove all the prints and verify by putting a breakpoint.

  1. If the above does not work, run these tasks one at a time i.e. first comment out StartDefaultTask and test and then comment out StartTask02 and test.

  2. If the tasks work one at a time, then put read both the ADCs in one task and see if it works-

void StartDefaultTask(void *argument)
{
    for(;;)
    {
        while(HAL_GPIO_ReadPin(DRDY_GPIO_Port,DRDY_Pin));
        if(HAL_GPIO_ReadPin(DRDY_GPIO_Port, DRDY_Pin) == 0)
        {
            __disable_irq();
            ADC_DRDY_ISR();
            __enable_irq();
        }

        while(HAL_GPIO_ReadPin(ADC2_DRDY_GPIO_Port,ADC2_DRDY_Pin));
        if(HAL_GPIO_ReadPin(ADC2_DRDY_GPIO_Port, ADC2_DRDY_Pin) == 0)
        {
            __disable_irq();
            ads1256_drdy_isr();
            __enable_irq();
        }
    }
}

Thanks for the reply,

its already worked when i kept both in one task but kept in two independent tasks its not work.
Ok, will test it and let know the result.

  1. When i try both in different tasks it gives me hard fault errors like this

    here i comment all the print functions accept two in both.
  2. Commenting task1 and run task2 same result as hard fault error.
  3. Commenting task2 and run task1 results as successfully running.

Also, i tried the mutex concept in that also control stuck in IRQ() function check.
so is that an interrupt problem.??

Did you run the exact code that I shared? Did you also try the scenario 3?

Share the callstack also for the hard fault.

Yes.

i already its working and also just now i checked with the code which you shared its working.

but the thing is i need to run multiple tasks like

  1. task1 is dedicated for ADC1
  2. task2 is dedicated for ADC2
  3. task3 is dedicated to RELAYS operation
  4. task4 is dedicated to Nextion Display
  5. task5 is dedicated to UART
  6. task6 is dedicated to RTC
    so as i said before I tried by kept both ADC1 and ADC2 in task1 it’s working and when I add the RELAYS operation some data are lost and ADC reading was stuck.
    Then i planned to run both ADCs with different tasks and after that, you know the whole drama.

Sorry, didn’t get what you asking, is that like the previous call to a hard fault.??

From your previous description, it seems like you get hard fault when you run task2. Please take the complete screenshot of the IDE and share when you hard fault.