This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM263P4-Q1: Using FreeRTOS API Before "HW Interrupt as needed"

Part Number: AM263P4-Q1

Hello,

Our FreeRTOS runs as intended but I am reviewing the information here:

AM263Px MCU+ SDK: FreeRTOS usage guidelines

As advised, we create a single run once initial task then call vTaskStartScheduler(). In the initial task callback we create other periodic tasks and also configure and enable MCAN interrupts. Therefore we configure and enable interrupts AFTER calling vTaskStartScheduler().

However, in the doument:

image.png

 In other words, "Before using FreeRTOS APIs in your application, you need to do HW interrupt as needed."

Because we configure and enable interrupts after using the FreeRTOS API, I don't think we strictly meet this guidline but I suppose it depends on your intention behind this guidline.

  • Do you mean a particular interrupt, e.g. The interrupt for SysCfg Clock? or do you mean all interrupts?
  • If all interrupts, what's the rationale behind this guideline?
  • Does "HW interrupt as needed" mean configure and enable?

Thank you.

  • Hi Kier,

    I believe the intent of the author of the documentation was to convey:

    • The phrase "Initialize cache, MPU, HW interrupt as needed" primarily refers to initializing the core hardware interrupt controller architecture (the VIM / HwiP module) and configuring the OS Tick Timer interrupt, rather than enabling your specific application-level peripherals (like MCAN).
    • Before you call any FreeRTOS API or start the scheduler, the system's hardware interrupt controller must be in a known, clean state. Crucially, the porting layer needs one hardware timer configured to fire at configTICK_RATE_HZ to feed the FreeRTOS tick counter.
    • "Configure interrupt as needed" means configure and initialize the setup, but not necessarily enable global or peripheral interrupts.
      When you initialize the hardware interrupt platform (HwiP_init()), the system configures the vector table and internal structures. However, global interrupts should remain disabled until the OS is stable. In fact, if you globally enable application peripheral interrupts before vTaskStartScheduler(), you run a massive risk: an external MCAN event could trigger an ISR that attempts to call a FreeRTOS API (like xSemaphoreGiveFromISR), causing an immediate system crash or kernel panic because the scheduler structures do not exist yet.

    Regards,
    Shaunak

  • Hi Shaunak,

    Many thanks for the reply.

    I checked our application's current sequence of execution in more detail.

    System_init()
        Dpl_init()
            HwiP_init()
            ClockP_init() // Configure timer and interrupt for RTOS
            HwiP_enable()
                
    xTaskCreateStatic() // Run once init task
    
    vTaskStartScheduler()
    
    init_task_callback()
        HwiP_construct() for MCAN.
        MCAN_enableIntr() for MCAN.
        xTaskCreateStatic() // Periodic tasks
        
        vTaskDelete(NULL);

    From your points, I think the bottom line is that we are in OK shape except for HwiP_enable(). Specifically, your third point is saying that I should move from line 5 (auto enable in SysCfg) to line 15 (after periodic task creation), is that correct?

  • Hi,

    Let me check and get back

    Regards,
    Shaunak

  • Hi Kier,

    I had another analysis and I think that HwiP_enable() should stay exactly where it is at line 5, inside Dpl_init(), before vTaskStartScheduler(). 

    My point applied only to peripheral-specific interrupt registration, HwiP_construct() for MCAN + MCAN_enableIntr(). It did not apply to the global HwiP_enable() call. That call is part of system-level init and must complete before the scheduler starts.

    I confirmed from source files at: source/kernel/nortos/dpl/r5/HwiP_armv7r_vim.c (the actual HwiP_init() implementation, lines ~300-313):

    HwiP_enableFIQ();
    /* dont enable IRQ, enable it after
    * all init is to make sure any pending peripheral interrupt status bits from old runs are cleared
    * before interrupts are eanbled.
    *
    * This allows to reload the binary without power cycling the whole SOC
    */
    /* HwiP_enable(); */

    HwiP_init() enables FIQ, but deliberately does not enable IRQ. The IRQ-enable line is commented out on purpose. That's why your flow has a separate, explicit HwiP_enable() call after ClockP_init().

    Interesting side note: source/kernel/dpl/HwiP.h lines 279-289 doc-comments HwiP_init() as if it "Enables global interrupts" and "initializes and enables both FIQ and IRQ"  that comment is confusing. The .c implementation confirms IRQ enable is deferred to the explicit HwiP_enable() call.

    Given that:
    - HwiP_init() → sets up VIM infra + enables FIQ only (not IRQ)
    - ClockP_init() → configures the RTI tick timer and registers its ISR via HwiP_construct() (but does not itself enable global IRQ)
    - HwiP_enable() → is the call that actually unmasks IRQ globally

    If you moved HwiP_enable() to line 15 (after vTaskStartScheduler() has already been called at line 9), then:
    - The tick timer interrupt would never fire between scheduler start and line 15. FreeRTOS's scheduler relies on that tick ISR to drive time slicing, so this would effectively stall preemption/timing from scheduler start.
    - Worse, in practice you'd never even reach line 15 in a well-formed way, because init_task_callback() is already running under the scheduler as the first task if IRQ is still globally disabled at that point, any blocking calls that depend on the tick (delays, timeouts, semaphore waits with timeout) inside that same task would misbehave before you got there.

    So line 5 is correct and required.

    To summarize, your original sequence, exactly as written, is fully correct. No changes needed, including HwiP_enable() at line 5.

    Regards,
    Shaunak

  • Many thanks for the detailed reply.

    Nothing for me to do, what a result!