Pushbutton interrupts help

hello there I’ve been trying to learn how to stop a software timer in an ISR of a pushbutton but I cant seem to figure it out. Here is the code I’ve been trying to solve. As you can see my software timer, task1 and task 2 are all working. Any advice on how to make my pushbutton stop the software timer and print a message.

#include <assert.h>
#include <stdio.h>
#include <string.h>

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
#include "semphr.h"

#include "fsl_device_registers.h"
#include "fsl_debug_console.h"
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"

#define SW_TIMER_PERIOD_MS (2000 / portTICK_PERIOD_MS)
#define Task1_PRIORITY (tskIDLE_PRIORITY + 1)
#define Task2_PRIORITY (tskIDLE_PRIORITY + 2)

static void Task1(void *pvParameters);
static void Task2(void *pvParameters);

/* The callback function. */
static void SwTimerCallback(TimerHandle_t xTimer);
volatile bool SW2btn_press = false;


void delay(void)
{
 uint32_t i = 500000U; /*this count wastes appr. 0.5 seconds*/
 while (i--)
 {
 __NOP(); /* No Operation instr. wastes one clock cycle. Note the double score prefix*/
 }
}

void BOARD_SW2_IRQHANDLER(void) {

	uint32_t flags = GPIO_PortGetInterruptFlags(BOARD_SW2_GPIO);
	GPIO_PortClearInterruptFlags(BOARD_SW2_GPIO, flags);
	SW2btn_press = true;
	xTimerStopFromISR( xTimerHandle, &xHigherPriorityTaskWoken );

}

int main(void) {

	 TimerHandle_t SwTimerHandle = NULL;

	 /* Init board hardware. */
	    BOARD_InitBootPins();
	    BOARD_InitBootClocks();
	    BOARD_InitBootPeripherals();
	    BOARD_InitDebugConsole();
	    SystemCoreClockUpdate();

 	    xSemaphore_Task1 = xSemaphoreCreateBinary();
	    xSemaphore_Task2 = xSemaphoreCreateBinary();

	    /* Create the software timer. */
	    SwTimerHandle = xTimerCreate("SwTimer",SW_TIMER_PERIOD_MS,pdTRUE,0,SwTimerCallback);  

	    if (xTaskCreate(Task1, "TASK1", configMINIMAL_STACK_SIZE + 128, NULL, Task1_PRIORITY, NULL) != pdPASS)
	    {
	           PRINTF("Task creation failed!.\r\n");
	           while (1)
	               ;
        }

	    if (xTaskCreate(Task2, "TASK2", configMINIMAL_STACK_SIZE + 128, NULL, Task2_PRIORITY, NULL) != pdPASS)
	    {
	    	    PRINTF("Task creation failed!.\r\n");
	    	    while (1)
	    	        ;
	     }

 	    /* Start timer. */
	    xTimerStart(SwTimerHandle, 0);
	    /* Start scheduling. */
	    vTaskStartScheduler();
	    for (;;)
	        ;
	}

static void SwTimerCallback(TimerHandle_t xTimer)
	{
		BaseType_t xHigherPriorityTaskWoken = pdFALSE;
		PRINTF("ABC\n\n");
		xSemaphoreGiveFromISR(xSemaphore_Task1, &xHigherPriorityTaskWoken);
		portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
	}
	void Task1(void *pvParameters)
	{
		for(;;)
		{
		    xSemaphoreTake(xSemaphore_Task1, portMAX_DELAY);
		    PRINTF("task 1\n\n");
		    xSemaphoreGive(xSemaphore_Task2);
		}
	}

	void Task2(void *pvParameters){
		for(;;)
		{
			xSemaphoreTake(xSemaphore_Task2, portMAX_DELAY);
			PRINTF("task 2\n\n");
			vTaskDelay(pdMS_TO_TICKS(1000));
		}
	}

/*output

  • ABC
  • task 1
  • task 2
  • next i want to press sw2 an interupt will occur. When the interupt occurs it will stop the software timer and print a message
    */

Aside from better using vTaskDelay instead of your delay function what’s the problem ? What is not working as expected or is there a crash ?
Also you ally should define configASSERT and also enable stack overflow checking for development/debugging.
Hint: Please enclose code blocks by 3 tildas (~~~) or backticks (```) for better readability.

when i press my pushbutton(sw2) the software timer should stop and display a message, but nothing happens when i press the button

Oops - SwTimerCallback is a task level callback. It’s NOT called from ISR context.
FreeRTOS timers are software timers managed by a separate task.
Just use xSemaphoreGive in the timer callback. Also try to keep the timer callbacks short (i.e. avoid lengthy operations like debug output) because otherwise they might delay other timers maybe running.

BOARD_SW2_IRQHANDLER seems incomplete. Where is xHigherPriorityTaskWoken defined (and the corresponding portYIELD_FROM_ISR is missing).
Where is the code for intended output on timer stop ?
A common pattern for handling interrupts is signaling a task about the event and do the necessary post-processing there. This also applies to ‘printf’ family functions because they normally can’t be used in ISRs.

i am confused on how i would stop the software timer in my button isr and display a message. Is there a certain line of code i should be using to do this

Well, you correctly stop the timer with xTimerStopFromISR.
I’d append portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
What about adding a 3rd task (I guess it’s just an test application you’re writing) just waiting for another semaphore signaled in addition by the button ISR and then printing something ?

i will add a third task. the problem is i added a print statement to the button isr and the message is not being displayed. If i’m not mistaken by me stopping the software timer and pressing sw2 an interrupt should have been triggered and the message displayed

I guess the PRINTF in the ISR crashed the app. With a debugger your live will be a lot easier. Set a breakpoint in the ISR and simply setup trough the code.
And: Better post exactly the code you’re asking about. The posted ISR code is incomplete.

How would you use the function “xTimerStopFromISR”, to stop the software timer?

Welcome @Rangers :slight_smile:

Exactly, xTimerStopFromISR is used to stop a FreeRTOS software timer from an ISR.
See FreeRTOS - a small footprint, open source and free RTOS scheduler for microcontrollers - xTimerStopFromISR() interrupt safe timer API function description

#include <assert.h>
#include <stdio.h>
#include <string.h>

/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
#include "semphr.h"

/* Freescale includes. */
#include "fsl_device_registers.h"
#include "fsl_debug_console.h"
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"

TaskHandle_t TaskHandle_1;
TaskHandle_t TaskHandle_2;
TaskHandle_t TaskHandle_3;
TaskHandle_t TaskHandle_4;

/* The software timer period. */
#define SW_TIMER_PERIOD_MS (2000 / portTICK_PERIOD_MS)
#define TaskA_PRIORITY (tskIDLE_PRIORITY + 1)
#define TaskB_PRIORITY (tskIDLE_PRIORITY + 1)
#define TaskC_PRIORITY (tskIDLE_PRIORITY + 1)
#define TaskD_PRIORITY (tskIDLE_PRIORITY + 1)

BaseType_t xHigherPriorityTaskWoken = pdTRUE;

volatile bool taskStop = false;
volatile bool taskReset = false;

SemaphoreHandle_t xSemaphore_TaskA;
SemaphoreHandle_t xSemaphore_TaskB;
SemaphoreHandle_t xSemaphore_TaskC;
SemaphoreHandle_t xSemaphore_TaskD;

TickType_t SwTimerHandle;

static void TaskA(void *pvParameters);
static void TaskB(void *pvParameters);
static void TaskC(void *pvParameters);
static void TaskD(void *pvParameters);

static void SwTimerCallback(TimerHandle_t xTimer);

void BOARD_SW2_IRQHANDLER(void)
{
	uint32_t flags = GPIO_PortGetInterruptFlags(BOARD_SW2_GPIO); /*get triggered interrupt flag*/
	GPIO_PortClearInterruptFlags(BOARD_SW2_GPIO, flags); /*clear triggered interrupt flag*/

	taskStop = true;
	PRINTF("\r\nSW2 ISR –EMERGENCY – all operations are suspended!\r\n");


}

void BOARD_SW3_IRQHANDLER(void)
{
	uint32_t flags = GPIO_PortGetInterruptFlags(BOARD_SW3_GPIO); /*get triggered interrupt flag*/
	GPIO_PortClearInterruptFlags(BOARD_SW3_GPIO, flags); /*clear triggered interrupt flag*/

	taskReset = true;
	PRINTF("\r\nSW3 -NORMALsystem operation is resuming...\r\n");


}
int main(void) {

	 TimerHandle_t SwTimerHandle = NULL;

	 /* Init board hardware. */
	    BOARD_InitBootPins();
	    BOARD_InitBootClocks();
	    BOARD_InitBootPeripherals();
	    BOARD_InitDebugConsole();
	    SystemCoreClockUpdate();

	    xSemaphore_TaskA = xSemaphoreCreateBinary();
	    xSemaphore_TaskB = xSemaphoreCreateBinary();
	    xSemaphore_TaskC = xSemaphoreCreateBinary();
	    xSemaphore_TaskD = xSemaphoreCreateBinary();

	    /* Create the software timer. */
	    SwTimerHandle = xTimerCreate("SwTimer",          /* Text name. */
	                                 SW_TIMER_PERIOD_MS, /* Timer period. */
	                                 pdTRUE,             /* Enable auto reload. */
	                                 0,                  /* ID is not used. */
	                                 SwTimerCallback);   /* The callback function. */

	    if (xTaskCreate(TaskA, "TASKA", configMINIMAL_STACK_SIZE + 128, NULL, TaskA_PRIORITY, &TaskHandle_1) != pdPASS)
	       {
	           PRINTF("Task creation failed!.\r\n");
	           while (1)
	               ;
	       }
	    if (xTaskCreate(TaskB, "TASKB", configMINIMAL_STACK_SIZE + 128, NULL, TaskB_PRIORITY, &TaskHandle_2) != pdPASS)
	       {
	           PRINTF("Task creation failed!.\r\n");
	           while (1)
	               ;
	       }
	    if (xTaskCreate(TaskC, "TASKC", configMINIMAL_STACK_SIZE + 128, NULL, TaskC_PRIORITY, &TaskHandle_3) != pdPASS)
	       {
	           PRINTF("Task creation failed!.\r\n");
	           while (1)
	               ;
	       }
	    if (xTaskCreate(TaskD, "TASKD", configMINIMAL_STACK_SIZE + 128, NULL, TaskD_PRIORITY, &TaskHandle_4) != pdPASS)
	    	       {
	    	           PRINTF("Task creation failed!.\r\n");
	    	           while (1)
	    	               ;
	    	       }

	    /* Start timer. */
	    xTimerStart(SwTimerHandle, 0);
	    /* Start scheduling. */
	    vTaskStartScheduler();
	    for (;;)
	        ;
	}

	/*!
	 * @brief Software timer callback.
	 */
	static void SwTimerCallback(TimerHandle_t xTimer)
	{
		PRINTF("\r\nSoftware Timer ISR -Sensors are read");
		xSemaphoreGiveFromISR(xSemaphore_TaskA, &xHigherPriorityTaskWoken);
		portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

	}

	void TaskA(void *pvParameters)
	{
		for(;;)
		{
		    LED_GREEN_ON();
		    LED_BLUE_OFF();
		    LED_RED_OFF();
		    xSemaphoreTake(xSemaphore_TaskA, portMAX_DELAY);
		    PRINTF("\nTask1\n");
		    xSemaphoreGive(xSemaphore_TaskB);
		}
	}

	void TaskB(void *pvParameters)
		{
			for(;;)
			{
			xSemaphoreTake(xSemaphore_TaskB, portMAX_DELAY);
			PRINTF("Task2\n");
			if(taskStop == true)
				{
					xSemaphoreGive(xSemaphore_TaskC);
					taskStop = false;
				}
			}
		}

	void TaskC(void *pvParameters)
		{
			for(;;)
			{
				xHigherPriorityTaskWoken = pdTRUE;
				xSemaphoreTake(xSemaphore_TaskC, portMAX_DELAY);
				vTaskSuspend(TaskHandle_1);
				vTaskSuspend(TaskHandle_2);
				LED_GREEN_TOGGLE();
				LED_RED_ON();

				PRINTF("\r\nTask3-EMERGENCY protocol is being executed...\n");
				PRINTF("RED LIGHT and SOUND ALARM are ON\n");
				PRINTF("Press button SW3 to clear the system and reboot...\n");
				xTimerStopFromISR( SwTimerHandle, &xHigherPriorityTaskWoken );

				if (taskReset == true)
				{
					xSemaphoreGive(xSemaphore_TaskD);
					taskReset = false;
				}
			}
		}

	void TaskD(void *pvParameters)
	{
		for(;;)
		{

			xHigherPriorityTaskWoken = pdTRUE;

			xSemaphoreTake(xSemaphore_TaskD, portMAX_DELAY);
			xTimerResetFromISR( SwTimerHandle, &xHigherPriorityTaskWoken );
			vTaskResume(TaskHandle_1);
			vTaskResume(TaskHandle_2);
		}
	}

This stops the timer but it doesn’t resume the timer when sw3 is pushed; is there something wrong with the code?

There are couple of things you need to fix in this code:

  1. Do no call PRINTF from ISR.
  2. Software timer callbacks are executed in the timer task’s context - you do not need FromISR APIs there:
	static void SwTimerCallback(TimerHandle_t xTimer)
	{
		PRINTF("\r\nSoftware Timer ISR -Sensors are read");
		xSemaphoreGiveFromISR(xSemaphore_TaskA, &xHigherPriorityTaskWoken);
		portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
	}
  1. Do not call FromISR APIs from tasks:
                PRINTF("Press button SW3 to clear the system and reboot...\n");
				xTimerStopFromISR( SwTimerHandle, &xHigherPriorityTaskWoken );

Thanks.