PIC32 tickless mode

jalegre2003 wrote on Wednesday, June 28, 2017:

Hello. I’m using FreeRTOS 9.0 with my own implementation of tickless ide mode because there is still not a default one available for the PIC32.
This implementation is based on the example provided here: http://www.freertos.org/low-power-tickless-rtos.html

In my case, the only thing that will wake up the micro from sleep is receiving data through an UART port. In the UART’s ISR, some …ISR() functions are to be called, so the UART interrupt priority is kept below configMAX_SYSCALL_INTERRUPT_PRIORITY. Besides, I use the assembly wrapper to call the interrupt handler.

Everything works ok in “normal” mode but, when entering sleep mode, the micro doesn’t wake up when receiving UART data.
In the code I realize that there is a call to “portDISABLE_INTERRUPTS” (in the example code it’s based on, the call is made to “disable_interrupts”). I know it’s necessary due to “…Further, it is necessary for the portSUPPRESS_TICKS_AND_SLEEP() function to create a small critical section between the tick source being stopped and the microcontroller entering the sleep state…”
After disabling the interrupts, the micro enters into sleep mode so no interrupt (below configMAX_SYSCALL_INTERRUPT_PRIORITY) can wake up the micro.

Can the interrupts be safely re-enabled just before entering sleep mode? Otherwise, which available solutions are available to handle this issue?
If I re-enable the interrupts before going to sleep, everything (appears to) work.

This is the part of the code I refer to:

/* Define the function that is called by portSUPPRESS_TICKS_AND_SLEEP(). */
void vApplicationSleep( TickType_t xExpectedIdleTime )
{
unsigned long ulLowPowerTimeBeforeSleep, ulLowPowerTimeAfterSleep;
eSleepModeStatus eSleepStatus;

    /* Read the current time from a time source that will remain operational
    while the microcontroller is in a low power state. */
    ulLowPowerTimeBeforeSleep = ulGetExternalTime();

    /* Stop the timer that is generating the tick interrupt. */
    prvStopTickInterruptTimer();

** This is where interrupts get disabled **

    /* Enter a critical section that will not effect interrupts bringing the MCU
    out of sleep mode. */
    disable_interrupts();

    /* Ensure it is still ok to enter the sleep mode. */
    eSleepStatus = eTaskConfirmSleepModeStatus();

    if( eSleepStatus == eAbortSleep )
    {
        /* A task has been moved out of the Blocked state since this macro was
        executed, or a context siwth is being held pending.  Do not enter a
        sleep state.  Restart the tick and exit the critical section. */
        prvStartTickInterruptTimer();
        enable_interrupts();
    }
    else
    {
        if( eSleepStatus == eNoTasksWaitingTimeout )
        {

** My code always enters here. So it goes to sleep with interrupts disabled **

            /* It is not necessary to configure an interrupt to bring the
            microcontroller out of its low power state at a fixed time in the
            future. */
            prvSleep();
        }

Thanks in advance.

rtel wrote on Wednesday, June 28, 2017:

I think there needs to be some form of critical section to ensure the
system is in a known state when you come out of sleep mode. On the
Cortex-M, which is what the code you copied was written for, disabling
interrupts does not prevent the device exiting sleep mode, but does
prevent the interrupt actually executing until the now woken MCU
re-enables them. Is there an equivalent on the PIC32? Without it I
think this code will become much more complex as the interrupt entry and
exit code may need to be enhanced to detect when an interrupt brought
the MCU out of sleep and defer the interrupt’s processing until exiting
sleep has been cleaned up.

jalegre2003 wrote on Monday, July 03, 2017:

In PIC32, disabling interrupts prevents the device from exiting sleep mode.

Apart from the fact that the interrupt entry/exit code should be much more complex I think it’s not possible to implement the tickless mode in this case beacuse interrupts have to be enabled at some time before entering sleep mode and, in the time between that and entering sleep mode, an interrupt could be received which could result in, for example, a task being unblocked, but the scheduler is suspended and the device is just going to enter into sleep mode so that task won’t get unblocked until the next interrupt wakes up the device.

Has someone successfully implemented tickless mode in PIC32?
For me it’s mandatory in this project to be able to use low power with FreeRTOS/PIC32. I see that it has been a long time since tickless mode was implemented in FreeRTOS. Is there any plans/dates about when FreeRTOS engineers will release it for PIC32?

Thank you.

rtel wrote on Monday, July 03, 2017:

From the manual:

8.13.1 Interrupt Operation in Sleep Mode
During Sleep mode, the interrupt controller will only recognize interrupts from peripherals that
can operate in Sleep mode. Peripherals such as RTCC, Change Notice, External Interrupts, ADC
and SPI Slave can continue to operate in Sleep mode and interrupts from these peripherals can
be used to wake up the device. An interrupt with its Interrupt Enable bit set may switch the device
to either Run or Idle mode, subject to its Interrupt Enable bit status and priority level. An interrupt
event with its Interrupt Enable bit cleared or a priority of zero will not be recognized by the interrupt
controller and cannot change device status. If the priority of the interrupt request is higher
than the current processor priority level, the device will switch to Run mode and processor will
execute the corresponding interrupt request. If the proximity timer is enabled and the pending
interrupt priority is less than the temporal proximity priority, the processor does not remain in
sleep. It transitions to idle and then goes to run, once the TPT times out. If the priority of the interrupt
request is less than, or equal to, the current processor priority level, the device will switch to
Idle mode and the processor will remain halted.

jalegre2003 wrote on Tuesday, July 04, 2017:

Hello. I don’t really understand what you want to say with that quotation from the manual.
As it states …If the priority of the interrupt request is higher
than the current processor priority level, the device will switch to Run mode and processor will
execute the corresponding interrupt request…

I think that “portDISABLE_INTERRUPTS” sets the current processor priority level to be above the interrupts “managed” by FreeRTOS (those which priority is under “configMAX_SYSCALL_INTERRUPT_PRIORITY”). So, the (masked) interrupt will not wake the processor from the sleep mode.

From the PIC32 manual “Chapter 10. Power saving modes”:

10.4.1 Wake-up from Sleep mode or Idle mode on Peripheral Interrupt
Any source of interrupt that is individually enabled using the corresponding Interrupt Enabled (IE)
control bit in the IECx register, and is operational in the current power-saving mode, will be able
to wake the processor from Sleep mode or an idle mode. When the device wakes up, one of the
following events will occur based on the interrupt priority:
* If the assigned priority for the interrupt is less than or equal to the current CPU priority, the
CPU will remain halted and the device enters or remains in an idle mode.**
• If the assigned priority level for the interrupt source is greater than the current CPU priority,
the device will wake up and the CPU will jump to the corresponding interrupt vector. Upon
completion of the ISR, CPU will start executing the next instruction after the WAIT
instruction.*

Have you shown that quotation to confirm that it is not possible to wake the processor up from an interrupt/ISR which makes use of FreeRTOS calls, or am I missing something?