FreeRTOS: Interrupts on SAM4S

Hi I’m working for the first time with FreeRTOS using a testboard from Atmel (ATSAM4S-XPRO) with the ARM processor SAM4SD32C (Atmel Studio 7.0, FreeRTOS 9.0) and port ARM_CM3. http://www.microchip.com/DevelopmentTools/ProductDetails.aspx?PartNO=ATSAM4S-XPRO I tried to implement an example using interrupts and binary semaphores: ~~~ //Declarations and definitions SemaphoreHandlet xInterruptSemaphore; void pinedgehandler(const uint32t id, const uint32t index); void vInterrupt_Task(void *pvParameters); //****************************INTERRUPT TASKS************************// //Interrupt function called when a button is pressed void pinedgehandler(const uint32t id, const uint32t index) { if ((id == IDPIOA) && (index == PIOPA2)){ print_str(“Interrupt detected”);
    BaseType_t xHigherPriorityTaskWoken;
    xHigherPriorityTaskWoken = pdFALSE;

    if(xInterrupt_Semaphore != NULL){
        xSemaphoreGiveFromISR( xInterrupt_Semaphore, &xHigherPriorityTaskWoken );   
    }
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

}
} //Task released by the interrupt function void vInterruptTask(void *pvParameters){ for(;;){ //Check Semaphore if(xInterruptSemaphore != NULL){ BaseTypet semtaken = xSemaphoreTake( xInterruptSemaphore, pdMSTO_TICKS(10000) );
        if(sem_taken == pdPASS){
            print_str("Interrupt Task processed");
        }
        else{
            print_str("No Interrupt in 10s");
        }
    }
}
} //****************************END INTERRUPT TASKS************************// //Part of main int main (void) { …
//Create semaphore
xInterrupt_Semaphore = xSemaphoreCreateBinary();

if(xInterrupt_Semaphore != NULL){

        //Create Task releasd by the interrupt function
        xTaskCreate(vInterrupt_Task,"Interrupt Task",configMINIMAL_STACK_SIZE+1000,NULL,2, &vInterrupt_Task_id);


        //Configure Interrupt on Pin PA2 (button) with interrupt function "pin_edge_handler"
        pio_handler_set(PIOA, ID_PIOA, PIO_PA2, PIO_IT_FALL_EDGE, pin_edge_handler);
        //Start Interrupt
        pio_enable_interrupt(PIOA, PIO_PA2);
        NVIC_EnableIRQ(PIOA_IRQn);
}
vTaskStartScheduler(); } ~~~ This does not work, the programm jumps to the following code in the portmacro.h when I press the interrupt button for the first time: ~~~ uint32_t ulNewBASEPRI;
__asm volatile
(
    "   mov %0, %1                                              n" 
    "   msr basepri, %0                                         n" 
    "   isb                                                     n" 
    "   dsb                                                     n" 
    :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
);
} ~~~ Pressing the button further times has no effect, the debugger says that I didn’t return to the interrupt task. As soon as I delete the “xSemaphoreGiveFromISR” line, it works and I can enter the interrupt task several times. Any idea? Thanks! Sebastian

FreeRTOS: Interrupts on SAM4S

I might be wrong, but isn’t SAM4S a Cortex-M4 ? In this case you’re bettter off using the ARM_CM4 port.

FreeRTOS: Interrupts on SAM4S

Cortex-M3 devices always use the /source/[compiler]/ARM_CM3 port. Cortex-M4 devices that do NOT have an MPU use the same port layer as Cortex-M3 devices. Cortex-M4 devices that DO have an MPU use the /source/[compiler]/ARM_CM4F port layer. Cortex-M7 devices that have an r0p1 core use the /source/[compiler]/ARM_CM7/r0p1 port layer. All other Cortex-M7 devices use the same port layer as Cortex-M4 FPU devices.

FreeRTOS: Interrupts on SAM4S

What happens if you take the call to print_str() out of the ISR? Printing in interrupts is normally a really bad idea, unless you are 100% sure of the print() functions implementation (the print function must use a very tiny stack, be thread safe, not mess with interrupts, etc.).

FreeRTOS: Interrupts on SAM4S

According to this threat: https://sourceforge.net/p/freertos/discussion/382005/thread/b8ca2d6e/?limit=25#470f the Sam4S is a Cortex-M4, but there is no ARMCM4 port. I can use the ARMCM4F if I enable the floating point unit. I’ve disabled the FPU, so I’m using the ARM_CM3 But I’ve found the problem: http://www.freertos.org/RTOS-Cortex-M3-M4.html I need to set a priority fo the interrupt. So I’ve added one line: ~~~ //Interrupt konfigurieren piohandlerset(PIOA, IDPIOA, PIOPA2, PIOITFALLEDGE, pinedgehandler); //Set priority ** piohandlersetpriority(PIOA, PIOAIRQn, 170);** //Interrupt am Pin PA2 starten (Button) pioenableinterrupt(PIOA, PIOPA2); NVICEnableIRQ(PIOAIRQn); ~~~ But I don’t understand why only priority values between 170 and 255 work. In my FreeRTOS config file: ~~~ /* The lowest interrupt priority that can be used in a call to a “set priority” function. */

define configLIBRARYLOWESTINTERRUPT_PRIORITY 0x0f

/* The highest interrupt priority that can be used by any interrupt service routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER PRIORITY THAN THIS! (higher priorities are lower numeric values. */

define configLIBRARYMAXSYSCALLINTERRUPTPRIORITY 10

/* Interrupt priorities used by the kernel port layer itself. These are generic to all Cortex-M ports, and do not rely on any particular library functions. */

define configKERNELINTERRUPTPRIORITY ( configLIBRARYLOWESTINTERRUPTPRIORITY << (8 – configPRIOBITS) )

/* !!!! configMAXSYSCALLINTERRUPT_PRIORITY must not be set to zero !!!! See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */

define configMAXSYSCALLINTERRUPTPRIORITY ( configLIBRARYMAXSYSCALLINTERRUPTPRIORITY << (8 – configPRIOBITS) )

~~~ configPRIO_BITS is 4 Shifted with 0: 10<<4 = 10100000 = 160 0x0f<<4 = 11110000 = 240 Shifted with 1: 10<<4 = 10101111 = 175 0x0f<<4 = 11111111 = 255 In my opinion, 175 should be the limit and not 170. Sebastian

FreeRTOS: Interrupts on SAM4S

Already tried, didn’t change. I know the print() function is not a good idea, it is just for testing at the moment.

FreeRTOS: Interrupts on SAM4S

Does the piohandlerset_priority() expect the interrupt to be specified in the shifted on non-shifted way – as described on the http://www.freertos.org/RTOS-Cortex-M3-M4.html page you liked to. Are you using a recent version of FreeRTOS? The more recent the more assert()s there are to catch priority configuration issues. I would recommend using the head revision from SVN as I think that will catch just about all misconfigurations now – assuming configASSERT() is defined.

FreeRTOS: Interrupts on SAM4S

configAsssert is defined: ~~~

define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }

~~~ taskDISABLEINTERRUPTS() is linked to: ~~~ portFORCEINLINE static void vPortRaiseBASEPRI( void ) { uint32_t ulNewBASEPRI;
__asm volatile
(
    "   mov %0, %1                                              n" 
    "   msr basepri, %0                                         n" 
    "   isb                                                     n" 
    "   dsb                                                     n" 
    :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
);
} ~~~ That answers the question why I land in this section. I’m using FreeRTOS 9.0.0. The piohandlersetpriority(): ~~~ … NVIC->IP[(uint32t)(IRQn)] = ((priority << (8 – __NVICPRIOBITS)) & 0xff); } /* set Priority for device specific Interrupts */ … ~~~ That solves the problem. The interrupt priority is already shifted, so I need to enter values between 10 and 15. 170 is probably because of an overflow. Thanks for the help. Sebastian