FreeRTOS and GPIO interrupt handler

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.

FreeRTOS and GPIO interrupt handler

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 configMAXSYSCALLINTERRUPT_PRIORITY.
I would recommend reading the book that is provided as a free PDF download: http://www.freertos.org/Documentation/RTOS_book.html and the following page: http://www.freertos.org/RTOS-Cortex-M3-M4.html

FreeRTOS and GPIO interrupt handler

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: ~~~

define tskIDLEPRIORITY ( ( UBaseTypet ) 5U )

define TOUCHPARSETASKPRIORITY ( 1 )

define TOUCHPARSESTACKSIZE (1024/sizeof(portSTACK_TYPE))

define ADCCONVERTTASK_PRIORITY ( 3 )

define ADCCONVERTSTACKSIZE (1024/sizeof(portSTACKTYPE))

define SCREENUPDATETASK_PRIORITY ( 2 )

define SCREENUPDATESTACKSIZE (1024/sizeof(portSTACKTYPE))

// task definitions

define TASKMONITORSTACKSIZE (1024/sizeof(portSTACKTYPE))

define TASKMONITORSTACKPRIORITY (tskIDLEPRIORITY)

define TASKLEDSTACKSIZE (1024/sizeof(portSTACKTYPE))

define TASKLEDSTACKPRIORITY (tskIDLEPRIORITY)

// 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 taskrn");
}

// 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 taskrn");
}

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

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

if (xTaskCreate(ScreenUpdate, "Screen Update", SCREEN_UPDATE_STACK_SIZE, NULL,
                SCREEN_UPDATE_TASK_PRIORITY, NULL) != pdPASS)
{
    printf("Failed to create ScreenUpdate taskrn");
}
— 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]nr",tag_touched);
        Play_Sound(0x23,255);
        vTaskDelay(50);
        Stop_Sound();
        vTaskDelay(450);
        sprintf(cUtilStr,"Touched [%i]",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);
}
} ~~~

FreeRTOS and GPIO interrupt handler

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. http://www.freertos.org/RTOS-Cortex-M3-M4.html
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. http://www.freertos.org/a00110.html#configMAX_PRIORITIES I would recommend investing a short time in reading the free to download FreeRTOS book. 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?
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?
My biggest suggestion is to read the book referenced above, or, as a very minimum, some of the pages on the website.