We want to use nRF5340 in our future products and now I’m in the middle of experimenting with this device (using an nRF5340DK). Nordic Connect SDK and Zephyr are out of our scope. I’ve already successfully built a base system in which I can put custom programs (FWs) to either core (APP/NET). The next step would be putting FreeRTOS on the MCU. Power consumption in idle mode is also very important. I’ve a few questions, could you please help me out?
-1) I don’t want to play with secure/nonsecure modes, SPU, TrustZone etc, I simply need both the APP and NET cores without any “protection” etc (all secure mode). As I’ve seen in the most recent FreeRTOS release (202112.00) secure mode is also supported. I don’t know how mature the port (Cortex-M33) is?
-2) can I put the latest release both on APP and NET cores? At first glance I haven’t seen anything that’d prevent FreeRTOS from running on the NET core too;
-3) energy consumption is crucial on APP core, there’ll be days the APP processor is doing nothing. Power save modes that cause a reset when exit are not suitable, I believe, because they’d reset FreeRTOS itself too. Some kind of WFI/WFE sleep is necessary, I’ve seen traces of it in port.c. If all other conditions are met (unused peripherals, pins etc are all off by the firmware etc), is tickless sleep or the regular sleep better? The FW has to preserve the correct system time during the entire sleep;
UPDATE1: I think I don’t need TrustZone, but need the entire APP CPU run in secure mode to have access to everything. Under FreeRTOS/Source/portable/GCC/ARM_CM33_NTZ/ there’s no ‘secure’ directory, only non_secure. I’ve just compiled with this and doesn’t seem to run, but had no time to debug it yet, maybe I’m doing wrong (e.g. my malloc can be faulty). Nevertheless it’s suspicious to me, I want secure but I’m compiling non_secure Some lines from the config:
Yes, you should be able to as long as you partition the memory correctly.
Tickless idle support has macros that you can override to put your MCU in whatever sleep mode you want. This page provides more details on tickless idle support - Tickless Low power features in FreeRTOS
If you really want the lowest power mode, do not try to use the FreeRTOS tick as your clock time time-base, but the processor’s RTC to provide that capability. This allows you to put the processor into the lighter sleep modes that restart the processor where it left off.
Don’t be afraid of the reset exiting modes if you can afford the longer response time for rebooting the system. This might be true for one of the cores, letting the other handle the quick response, and the other coming up slower to handle a bigger load if needed.
Tickless idle tends to be better for shorter sleeps, where you are expecting to be woken up in the near future, you want to wake up quick, but don’t need to handle every tick on the way, and can accept the timing error of tickless idle (or use a different counter that lets it stay accurate)
For a longer sleep, you can go into a “real” sleep mode, (which will also be ‘tick-less’, but more than just idle), these will incur more delay to wake up (and often a power hit if it happens too soon). This becomes the tuning problem.
keep M33’s SysTick peripheral as kernel systick which performs task switching;
1.1 (my idea) set configTICK_RATE_HZ to a reasonbly low value (e.g. 100) to prevent too frequent wakeups from WFI/WFE sleeps;
set up an RTC which is always running to keep proper absolute system time
(by the way, this is what we do in our 8-bit MCU project, those RTCs with an external crystal can go very low in terms of energy consumption);
our FW must preserve its internal state during sleep, so using a reset-exiting sleep would clear the SRAM. nRF5340 has ‘RAM retention’ feature in its VMC peripheral. I guess if I specify RAM blocks, they can preserve precious state variables between two resets, am I right?
Can you try to use some physical indication like toggling an LED to see till what point the control reaches when the code appears to be not working? Is it possible that the MCU is entering sleep mode and never waking up?
And this never executes, therefore ulCompleteTickPeriods remains zero and the scheduler will start again the sleep (I believe). The else branch executes once in a second, but it’s okay, since my RTC is programmed to generate 1 IRQ/s, so in these cases the sleep is interrupted by my RTC and ulCompleteTickPeriods seems to be fine.
The APP core is running at 64MHz.
At the moment I don’t have any idea why portNVIC_SYSTICK_COUNT_FLAG_BIT flag isn’t set, and why does it get set if being run in a debugger (Segger Ozone)?
nRF5340 shuts down the HFCLK clock during WFI, so the MCU (including SysTick peripheral) doesn’t get clock, therefore stops. Nordic Devzone topics suggest to use an RTC instead of SysTick to work around the situation.
(I suppose other Cortex M33-based MCUs keep the SysTick powered on even in WFI, at least this is what I’ve learnt from vPortSuppressTicksAndSleep implementation. I also suppose a lot of tests were performed on other Cortex M33 machines and they passed.)
I’m going to patch my FreeRTOS in the future to use RTC for systick instead of SysTick peripheral. And the whole tickless idle logic also has to be recreated…
Sure. And vPortSuppressTicksAndSleep must also rewritten, because RTC works a bit differently than SysTick. (Or create a new function and use by portSUPPRESS_TICKS_AND_SLEEP). Oh, vPortSuppressTicksAndSleep is also weak. So many ways to do the task
By the way, what are your experiences with other Cortex M33 MCUs? Is this SysTick issue specific to nRF5340?
The ST Implementations of the M33 have additional registers to decide how much is shut down on a WFI instruction. On default it is only a CPU halt and nothing more, but you can put it up to shutting down everything and only recover on RTC interrupt via reset vector. I expect this is how most manufacturers have done it.
I am surprised to hear that Nordic does not seem to have a CPU halt only configuration.