cancel
Showing results for 
Search instead for 
Did you mean: 

Freertos and HAL external interrupts

rolly loysney
Associate II
Posted on November 09, 2017 at 15:39

Hello,

I'm using stm32l496.

i'm trying to control LEDs with pwm through freeRTOS and using external Interrupts (gpio buttons)

i have some questions :

  i have some tasks looping while(1) to detect my input GPIO  and launch PWM timer :

void TASK(void)

{

while(1)

{

        if(HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_1) == GPIO_PIN_SET)

         {

            HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1);

            while(HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_1) == GPIO_PIN_SET) 

               {

                  __HAL_TIM_SET_COMPARE(&htim16, TIM_CHANNEL_1, 2000);

                  osDelay(200);;

                  __HAL_TIM_SET_COMPARE(&htim16, TIM_CHANNEL_1, 0);

                  osDelay(200);

}

}

}

i'm using 10 tasks like this to activate leds on demand.

Sometimes, the PWM led doesn't start though.

i guess there is better way using External Interrupts right ?

When i use external input EXTI0_IRQHandler() to do same task

it crashes freertos.

when i use the

EXTI0_IRQHandler()

without freertos activated, in another project, it works.

How to correctly use external interrupts with freertos ? or correctly launch my timers within tasks ?

I guess my program is too much time consuming and it lags...

Thank you

#gpio-interrupt #pwm #freertos+hal
4 REPLIES 4
Zt Liu
Senior III
Posted on November 10, 2017 at 05:14

Hi, rolly!

You should use TaskNotification

()

or TaskNotificationFromISR(), in the terminology of freeRTOS. (or osSignalSet if you use CMSIS OS API).

Please have a look at following document.

http://www.freertos.org/Documentation/161204_Mastering_the_FreeRTOS_Real_Time_Kernel-A_Hands-On_Tutorial_Guide.pdf

 ,Chapter 9.

Also, if you are porting freeRTOS to CMSIS-OS, you may also take a look at some ST-Examples like

'Your Cube Folders'\STM32Cube_FW_L4_V1.8.0\Projects\STM32L496ZG-Nucleo\Applications\FreeRTOS\FreeRTOS_SignalFromISR

Signals or TaskNotify is the most efficient way to trigger a task, without the need of an intermediate communication object!

Good Luck!

.Zt

Posted on November 10, 2017 at 10:50

Thank you ZhiTai !

I've check that Application folder.

actually i'm starting my task like this :

xTaskCreate(

TASK

, 'IRQPwmLedShow1', configMINIMAL_STACK_SIZE, //AR_GAUCHE

NULL, tskIDLE_PRIORITY + 1, &xLedIRQPwmHandler1);

....

while(1)

{

vTaskResume(xLedPwmHandler1);

...

}

When you mention 'TaskNotification()

 

or TaskNotificationFromISR()' 

you mean    xTaskNotifyGive() xTaskNotify()  and  vTaskNotifyGiveFromISR()  ?

External hardware interrupt (

EXTI0_IRQHandler) is same as software ISR ? 

I just want to start a task when i push a button.

Thank you for your help

Posted on November 11, 2017 at 02:40

Suppose you port your freeRTOS successfully.

Try the following codes, pretty mush the same as the example in chapter 9 of the ref book I gave you.

 /* The tasks to be created. */

static void vHandlerTask( void *pvParameters );

/* Stores the handle of the task to which interrupt processing is deferred. */

static TaskHandle_t xTaskHandler = NULL;

int main(void)

{   

   /*your initialization codes*/

   /* Create the 'handler' task, which is the task to which interrupt

   processing is deferred, and so is the task that will be synchronized

   with the interrupt.*/

   xTaskCreate( vHandlerTask, 'Handler', 128, NULL, 3, &xTaskHandler );

   /* Start the scheduler so the created tasks start executing. */

   vTaskStartScheduler();

}

static void vHandlerTask( void *pvParameters )

{

   uint32_t ulNotifyValue;

   for(;;)

   {

       /* Wait to receive a notification sent directly to this task from the interrupt handler. */

      ulNotifyValue = ulTaskNotifyTake(pdTRUE, 0xFFFFFFFF);

      if(ulNotifyValue != 0)

      {

         /*Your task job here*/

         BSP_LED_Toggle(LED1);

      }

   }

}

/*Your general GPIO_EXTI Callbacks here*/

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

   /* The xHigherPriorityTaskWoken parameter must be initialized to pdFALSE */  

   BaseType_t xHigherPriorityTaskWoken;

   xHigherPriorityTaskWoken = pdFALSE;

   

   /* your user button callback here*/

   if(GPIO_Pin == USER_BTN_PIN)

   {

      /* Send the notification directly to the task handler*/

      vTaskNotifyGiveFromISR( xTaskHandler, &xHigherPriorityTaskWoken );

      /*If xHigherPriorityTaskWoken was set to pdTRUE inside vTaskNotifyGiveFromISR()

        then calling portYIELD_FROM_ISR() will request a context switch. */

      portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

   }   

}

It works in my Discovery F412.

You may also use oscilloscope to check the time between the button push and the trigger of your task.

Good Luck, rolly!

.Zt

ranran
Senior II

Hello,

I have the same issue, and I tried the above suggestion, but nothing change.

I am not sure why freeRTOS fail to receive interrupt(?).

Any ideas ?

Ran