# FreeRTOS and GPIO interrupt handler

**URL:** <https://forums.freertos.org/t/freertos-and-gpio-interrupt-handler/6817>\
**Category:** Kernel\
**Created:** [November 2, 2017, 9:45pm UTC](https://forums.freertos.org/t/freertos-and-gpio-interrupt-handler/6817 "2017-11-02T21:45:32Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [November 2, 2017, 9:45pm UTC](https://forums.freertos.org/t/freertos-and-gpio-interrupt-handler/6817/1 "2017-11-02T21:45:32Z")

</div>

**[k1mgy](https://sourceforge.net/u/k1mgy/)** wrote on [Thursday, November 02, 2017](https://sourceforge.net/p/freertos/discussion/382005/thread/92ff6ffe/#1327):

AT91SAMG  
Atmel Studio  
ASF  
FreeRTOS 8.0.9

To service a touch screen, I’ve established a GPIO line configured to fire an interrupt service routine when the screen is touched. This will then cause certain actions to occur based on the touch event.

Communications with the touch screen is accomplished through the SPI bus. I don’t want to re-write my HAL to use the FreeRTOS SPI driver.

Is it legal to handle interrupts outside of FreeRTOS? By outside, I mean that the ISR is not managed by the FreeRTOS scheduler.

Are there any reason to do this differently, and if so, can you suggest something?

ps: the ISR fires and seems to work fine with a simple FreeRTOS task list. The ISR does not eat up much time, however.

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [November 3, 2017, 1:31am UTC](https://forums.freertos.org/t/freertos-and-gpio-interrupt-handler/6817/2 "2017-11-03T01:31:14Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Friday, November 03, 2017](https://sourceforge.net/p/freertos/discussion/382005/thread/92ff6ffe/#1327/bc9b):

FreeRTOS doesn’t manage the interrupts, but there are rules on how you  
use the API from inside an interrupt service routine. Roughly the rules  
are:

- don’t call an API function that does not end in 'FromISR" from inside  
an ISR.

- don’t call any API function from an interrupt that has a priority  
above configMAX\_SYSCALL\_INTERRUPT\_PRIORITY.

I would recommend reading the book that is provided as a free PDF  
download: [http://www.freertos.org/Documentation/RTOS\_book.html](http://www.freertos.org/Documentation/RTOS_book.html) and the  
following page: [http://www.freertos.org/RTOS-Cortex-M3-M4.html](http://www.freertos.org/RTOS-Cortex-M3-M4.html)

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [November 6, 2017, 4:45pm UTC](https://forums.freertos.org/t/freertos-and-gpio-interrupt-handler/6817/3 "2017-11-06T16:45:08Z")

</div>

**[k1mgy](https://sourceforge.net/u/k1mgy/)** wrote on [Monday, November 06, 2017](https://sourceforge.net/p/freertos/discussion/382005/thread/92ff6ffe/#61b4):

Thank you. I read the material on interrupts. I’m including the relevant code below.

My processor is the AT91SAMG55 (ARM Cortex-M4). The data sheet tells me that priority 0 is the highest (opposite of most other devices). What I can’t fathom is the maximum number of interrupt priorities available. It’s either a 4 or 8 bit register… but there are some complexities. Maybe this doesn’t matter. Uncertain how this plays into the FreeRTOS event priority scheme or even if these are related. _ **For now I am going to assume that the priority scheme relies on the CPU and therefore that 0 has the highest priority.** _

Questions:

1.\*\* configMAX\_PRIORITIES\*\* is set to 5 in FreeRTOSConfig.h. Is this the setting to establish the max number of priorities available on the device? It’s unclear from the description of this setting. For now, since priority 0 = max on the CPU, I have set **#tskIDLE\_PRIORITY** to 5 (assuming for the moment that 5 is the lowest).

1. Are interrupts turned off at any time during running of the scheduler? It appears at first glance this is so, as my GPIO interrupt handler is not triggered during scheduler execution.

2. For now, I have set up a simple boolean token that will, I hope, prevent any conflict between two timer tasks from accessing the SPI buss at the same time. A task that needs access to the SPI must get the token. If it does not, then any SPI calls within the task are disallowed. I’m concerned however that two timer-based tasks might request the token simultaneously. Hopefully these will not clash. I’d rather use a FreeRTOS-based token that guarantees its integrity. Any suggestions?

Priority constants:

```auto
#define tskIDLE_PRIORITY ( ( UBaseType_t ) 5U )
#define TOUCHPARSE_TASK_PRIORITY ( 1 )
#define TOUCHPARSE_STACK_SIZE (1024/sizeof(portSTACK_TYPE))

#define ADC_CONVERT_TASK_PRIORITY ( 3 )
#define ADC_CONVERT_STACK_SIZE (1024/sizeof(portSTACK_TYPE))

#define SCREEN_UPDATE_TASK_PRIORITY ( 2 )
#define SCREEN_UPDATE_STACK_SIZE (1024/sizeof(portSTACK_TYPE))

// task definitions
#define TASK_MONITOR_STACK_SIZE (1024/sizeof(portSTACK_TYPE))
#define TASK_MONITOR_STACK_PRIORITY (tskIDLE_PRIORITY)

#define TASK_LED_STACK_SIZE (1024/sizeof(portSTACK_TYPE))
#define TASK_LED_STACK_PRIORITY (tskIDLE_PRIORITY)

// global
bool GpuReadToken;

bool GetGPUReadToken(void)
{
    if (!GpuReadToken)
        GpuReadToken=true;
    return(GpuReadToken);
}

void ClearGPUReadToken(void)
{
    GpuReadToken=false;
}

--
main.c:

    /* Create task to monitor processor activity */
    if (xTaskCreate(task_mon, "Monitor", TASK_MONITOR_STACK_SIZE, NULL,
                    TASK_MONITOR_STACK_PRIORITY, NULL) != pdPASS)
    {
        printf("Failed to create task_mon task\r\n");
    }

    // Create task to make led blink
    if (xTaskCreate(task_led, "Led", TASK_LED_STACK_SIZE, NULL,
                    TASK_LED_STACK_PRIORITY, NULL) != pdPASS)
    {
        printf("Failed to create test led task\r\n");
    }

    if (xTaskCreate(TouchParse, "TouchParse", TOUCHPARSE_STACK_SIZE, NULL,
                    TOUCHPARSE_TASK_PRIORITY, NULL) != pdPASS)
    {
        printf("Failed to create adc_conv task\r\n");
    }

    if (xTaskCreate(adc_conv, "ADC Convert", ADC_CONVERT_STACK_SIZE, NULL,
                    ADC_CONVERT_TASK_PRIORITY, NULL) != pdPASS)
    {
        printf("Failed to create adc_conv task\r\n");
    }

    if (xTaskCreate(ScreenUpdate, "Screen Update", SCREEN_UPDATE_STACK_SIZE, NULL,
                    SCREEN_UPDATE_TASK_PRIORITY, NULL) != pdPASS)
    {
        printf("Failed to create ScreenUpdate task\r\n");
    }

-- callbacks --
void TouchParse(void *pvParameters)
{
    static portCHAR szList[256];
    UNUSED(pvParameters);

    for (;;)
    {
        if (GetGPUReadToken())
        {
            // SPI CALL
            tag_touched = Ft_Gpu_Hal_Rd32(phost, REG_TOUCH_TAG) & 0xFF;
            ClearGPUReadToken();
        }

        // valid press
        if (tag_touched>0 && tag_touched<99)
        {
            printf("***TP: Valid tag_touched[%i]\n\r",tag_touched);
            Play_Sound(0x23,255);
            vTaskDelay(50);
            Stop_Sound();
            vTaskDelay(450);
            sprintf(cUtilStr,"Touched [%i]\0",tag_touched);
        }
        vTaskDelay(250);	// 250mS
    }
}

void ScreenUpdate(void *pvParameters)
{

    UNUSED(pvParameters);
    for (;;)
    {
        if (GetGPUReadToken())
        {
            // SPI CALL
            BaseScreen();
            ClearGPUReadToken();
        }
        is_conversion_done = false;
        adc_start_software_conversion(ADC);
        vTaskDelay(1000);
    }
}

```

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [November 6, 2017, 5:30pm UTC](https://forums.freertos.org/t/freertos-and-gpio-interrupt-handler/6817/4 "2017-11-06T17:30:17Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Monday, November 06, 2017](https://sourceforge.net/p/freertos/discussion/382005/thread/92ff6ffe/#61b4/1e77):

> My processor is the AT91SAMG55 (ARM Cortex-M4). The data sheet tells me  
> that priority 0 is the highest (opposite of most other devices).

That is always the case for a Cortex-M device. What is different  
between devices is the number of interrupt priorities.

> **[RTOS for ARM Cortex-M](https://www.freertos.org/RTOS-Cortex-M3-M4.html)**
>
> Setting RTOS interrupt priorities on a ARM Cortex-M microcontroller

> What I  
> can’t fathom is the maximum number of interrupt priorities available.  
> It’s either a 4 or 8 bit register…

Write 0xff into one of the 8-bit priority registers, then read the value  
back again, that will tell you how many bits are implemented by the  
device - bits that are not implemented are read back as 0. If you use  
the latest head revision of FreeRTOS, from SVN, then it will do that for  
you and assert() if you have it set wrong.

> Questions:
> 
> 1._configMAX\_PRIORITIES_ is set to 5 in FreeRTOSConfig.h. Is this the  
> setting to establish the max number of priorities available on the  
> device?

No. It is nothing to do with the hardware.

> **[FreeRTOS - The Free RTOS configuration constants and configuration options -...](https://www.freertos.org/a00110.html#configMAX_PRIORITIES)**
>
> FreeRTOS is a portable, open source, mini Real Time kernel. A free RTOS for small embedded systems. This page describes and explains the constants used to configure FreeRTOS.

I would recommend investing a short time in reading the free to download  
FreeRTOS book. [Free RTOS Book and Reference Manual](http://www.freertos.org/Documentation/RTOS_book.html)

> It’s unclear from the description of this setting. For now,  
> since priority 0 = max on the CPU, I have set _#tskIDLE\_PRIORITY_ to 5  
> (assuming for the moment that 5 is the lowest).

Do not edit any constants that do not start with ‘config’. Your system  
is not going to work otherwise.

> 1. 
> 
> ```
> Are interrupts turned off at any time during running of the
> scheduler? It appears at first glance this is so, as my GPIO
> interrupt handler is not triggered during scheduler execution.
> 
> ```

What do you mean by ‘scheduler execution’? Do you mean while some of  
the FreeRTOS functions are executing? Or do you just mean when the RTOS  
is running user tasks?

> 1. 
> 
> ```
> For now, I have set up a simple boolean token that will, I hope,
> prevent any conflict between two timer tasks from accessing the SPI
> buss at the same time. A task that needs access to the SPI must get
> the token. If it does not, then any SPI calls within the task are
> disallowed. I'm concerned however that two timer-based tasks might
> request the token simultaneously. Hopefully these will not clash.
> I'd rather use a FreeRTOS-based token that guarantees its integrity.
> Any suggestions?
> 
> ```

My biggest suggestion is to read the book referenced above, or, as a  
very minimum, some of the pages on the website.
