This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Some questions about nRF53 and nRF Connect SDK

Hello Nordic Team,

as a newbie in the Nordic world, I have been reading the nRF Connect SDK and Zephyr documentation as well as testing some of the samples on my nRF5340DK. However, I still have some (mainly conceptual) questions:

  1. Power management
    According to the Product Specification, there are three modes of operation: System On (run, idle(constant latency, low power)), System Off and Force-Off (only for the Network Core).

    1. How can I switch between the different states? If i understood correctly, for the old SDK (nRF SDK5), Softdevice provided the necessary functions. Now with nRF Connect SDK, we have Zephyr-Power Management but also the possibility to modify the registers directly (e.g. TASKS_CONSTLAT, TASKS_LOWPWR, SYSTEMOFF). Unfortunately, I cannot quite understand how to procede and the difference between the two methods.

      Please correct any of the following assumptions, if I am wrong.
      -> Using Zephyr, we first retrieve the device struct with device_get_binding(). With that method we can then individually set the state of any CPU/peripheral defined in the device tree.
      -> By directly using the registers, we can make the core state idle-low power or idle-constant latency. This means, that we are setting all peripherals and the cpu in the same state at the same time.

      Is it enough with e.g. NRF_POWER->TASKS_CONSTLAT? Are there any examples of directly modifying the registers?
      Does Zephyr have any equivalent API for that?

    2. The function k_cpu_idle, makes the CPU idle. Are there any other ways to make the CPU Idle (e.g. running WFI or WFE instructions)?

    3. In sample zephyr/samples/boards/nrf/system_off, the UART is set to different power modes using the function pm_device_state_set().
      I noticed that the state is set using the defines from zephyr/include/pm/device.h: PM_DEVICE_STATE_ACTIVE, PM_DEVICE_STATE_LOW_POWER, PM_DEVICE_STATE_SUSPEND, PM_DEVICE_STATE_FORCE_SUSPEND, PM_DEVICE_STATE_OFF.
      Do these states really correspond to the modes of operation described in the Product Specification? If so, how?

  2. Working with a dual core
    1. I assume that both CPUs start at the same time after a power up. Using NETWORK.FORCEOFF we can decide that the network core does not start after a reset.
      Can the prj.conf or KConfig files be somehow modified to replicate the behaviour of NETWORK.FORCEOFF from the very beginning?. This means, that the network core would never start, not even after a power up.

Sorry if some of the questions do not make much sense. I am still processing so much information!
Many thanks in advance! Slight smile

Parents
  • Hi,

    1. Yes on nRF53 you have System ON, System OFF, and Force OFF for the network core.
      In System ON the CPU can be running or it can be idle, and the sub-mode "constant latency" can be enabled or disabled. Constant latency keeps some of the high frequency clocks running, so that going from idle to run mode happens faster, i.e. CPU ready to execute code faster when it wakes up.
      1.  
        • The chip enters system off with the PM_STATE_SOFT_OFF as shown in the system_off sample.
        • The chip is always in system ON, if nothing else is specified
        • I don't see any references to Constant Latency in zephyr, so I would assume that you will have to write to the TASKS_CONSTLAT register. I will have to check.
        • You control the power state of the peripherals using device_get_binding(). The only relevant power modes for the peripherals are either PM_DEVICE_STATE_LOW_POWER or PM_DEVICE_STATE_ACTIVE, as far as I know.
        • I would not control the state of the CPU with device_get_binding(). Because the CPU really does not have any "states", in that sense. Either it's executing code or it waits in a WFE state, and this is controlled by Zephyr. System OFF is referring the complete state of the chip, not just the CPU. And in constant latency mode, you keep some HF clocks running, but the CPU operation/state is basically the same as in "low power" mode.
      2. Correct. I guess you can use __WFE(), but that is not recommended. k_cpu_idle is basically a WFE in the end, but it checks some things before going to WFE. That's part of how zephyr handles CPU idle, and it should always be used. Of course there are other functions you can use to put the CPU to sleep, e.g. k_msleep to specify a sleep period, or just let the thread run to the end I.e. If you don't have a for-loop at the end of main(), zephyr will automatically put the CPU to idle, and wait for other threads to wake it up. So, you are not required to have a main loop, as in the old SDK.
      3. Since zephyr is used by many different platforms there are lots of states that are not relevant to the nRF53. The only relevant states is ACTIVE and LOW_POWER, and possibly OFF, as far as I know. But these are peripheral states, not CPU/system states. And the states are more in the higher layer/driver context, not so much at the hardware layer, which is documented in the PS.
    2. There are no KConfig options for NETWORK.FORCEOFF, but it would have to be set during code initialization anyways. Of course it would be possible to turn off the network core a bit earlier in the process before it enters main if a config option was implemented, but I guess you can do that yourself as well if you want, by editing the startup files.

     Hope that answers some of your questions. Feel free to ask more if something is unclear.

Reply
  • Hi,

    1. Yes on nRF53 you have System ON, System OFF, and Force OFF for the network core.
      In System ON the CPU can be running or it can be idle, and the sub-mode "constant latency" can be enabled or disabled. Constant latency keeps some of the high frequency clocks running, so that going from idle to run mode happens faster, i.e. CPU ready to execute code faster when it wakes up.
      1.  
        • The chip enters system off with the PM_STATE_SOFT_OFF as shown in the system_off sample.
        • The chip is always in system ON, if nothing else is specified
        • I don't see any references to Constant Latency in zephyr, so I would assume that you will have to write to the TASKS_CONSTLAT register. I will have to check.
        • You control the power state of the peripherals using device_get_binding(). The only relevant power modes for the peripherals are either PM_DEVICE_STATE_LOW_POWER or PM_DEVICE_STATE_ACTIVE, as far as I know.
        • I would not control the state of the CPU with device_get_binding(). Because the CPU really does not have any "states", in that sense. Either it's executing code or it waits in a WFE state, and this is controlled by Zephyr. System OFF is referring the complete state of the chip, not just the CPU. And in constant latency mode, you keep some HF clocks running, but the CPU operation/state is basically the same as in "low power" mode.
      2. Correct. I guess you can use __WFE(), but that is not recommended. k_cpu_idle is basically a WFE in the end, but it checks some things before going to WFE. That's part of how zephyr handles CPU idle, and it should always be used. Of course there are other functions you can use to put the CPU to sleep, e.g. k_msleep to specify a sleep period, or just let the thread run to the end I.e. If you don't have a for-loop at the end of main(), zephyr will automatically put the CPU to idle, and wait for other threads to wake it up. So, you are not required to have a main loop, as in the old SDK.
      3. Since zephyr is used by many different platforms there are lots of states that are not relevant to the nRF53. The only relevant states is ACTIVE and LOW_POWER, and possibly OFF, as far as I know. But these are peripheral states, not CPU/system states. And the states are more in the higher layer/driver context, not so much at the hardware layer, which is documented in the PS.
    2. There are no KConfig options for NETWORK.FORCEOFF, but it would have to be set during code initialization anyways. Of course it would be possible to turn off the network core a bit earlier in the process before it enters main if a config option was implemented, but I guess you can do that yourself as well if you want, by editing the startup files.

     Hope that answers some of your questions. Feel free to ask more if something is unclear.

Children
  • Hi Stian,

    thank you for your answers.

    I have some follow-up questions:

    1. I don't see any references to Constant Latency in zephyr, so I would assume that you will have to write to the TASKS_CONSTLAT register. I will have to check.
      In the code below, I set the system first in the Constant Latency and later in the Low Power submode.

       //CPU and all peripherals are Idle
            NRF_POWER_NS->TASKS_CONSTLAT = 0x0001;     //Set system in power submode Constant Latency
            
            [some other code]
            NRF_POWER_NS->TASKS_CONSTLAT = 0x0000;     //Deactivate submode Constant Latency
            NRF_POWER_NS->TASKS_LOWPWR = 0x0001;       //Set system in power submode Low Power

    The product specification states that "In System ON mode, when the CPU and all peripherals are IDLE, the system can reside in one of two power submodes." (Chapter 4.1.1 - Power Submodes).
    What would happen if either of the submodes was set while the CPU and/or all peripherals are not in IDLE? Does an error occur? Is there any function/register to check that the submode was set successfully?

    2. You control the power state of the peripherals using device_get_binding(). The only relevant power modes for the peripherals are either PM_DEVICE_STATE_LOW_POWER or PM_DEVICE_STATE_ACTIVE, as far as I know.

    The product specification states that "peripherals can be in an idle and run state" (Chapter 4.1 - System ON Mode).
    I assume that PM_DEVICE_STATE_ACTIVE corresponds to the run state and PM_DEVICE_STATE_LOW_POWER to the idle state.

    Thanks again.

  • Hello

    1. The TASKS_xx registers can only be written 1 (not 0), and it can not be read to see the status of the register.

      So in this case, you write to TASKS_CONSTLAT to enable constant latency, and to TASKS_LOWPWR to disable constant latency. You code should look like this:
      NRF_POWER_NS->TASKS_CONSTLAT = 1;     //Set system in power submode Constant Latency
      [some other code]
      NRF_POWER_NS->TASKS_LOWPWR = 1;       //Deactivate submode Constant Latency and set system in power submode Low Power
      The CPU itself is used to execute the code above, so the CPU will never be "idle" when the chip changes from LOWPWR to CONSTLAT or vice versa. The system state is changed immediately when the CPU writes to one of the two TASKS_xx registers.

      You do not need to call LOWPWR every time the chip is going to sleep. You should look at this as: either CONSTLAT is enabled, or it's not.

      I can try to explain the following statement: "In System ON mode, when the CPU and all peripherals are IDLE, the system can reside in one of two power submodes."

      If we first consider the LOWPWR scenario:
      - The CPU is idle, clocks and most resources are turned off
      - An interrupt occurs
      - The clocks and resources needed for the CPU to run is started. This takes some time
      - The CPU executes code requested by the interrupt
      - When it finishes, the CPU goes back to idle (WFE)
      - Clocks and resources are turned off.

      Then the CONSTLAT scenario:
      - The CPU is idle. Clocks and resources needed by the CPU are still running
      - An interrupt occurs
      - The CPU executes code requested by the interrupt immediately.
      - When it finishes, the CPU goes back to idle (WFE)

      So, what the statement means is that CONSTLAT will not have any effect if the CPU is already running, because the resources that CONSTLAT is keeping alive is always running when the CPU is executing code. That's why we are talking about CONSTLAT as a mode the chip will reside in when being in idle.

      Anyways, CPU being idle or not is handled by the Zephyr OS, and is not something the developer should worry too much about. The questions you should ask regarding Constant Latency being enabled or not is the following:

      - Does my code have very strict timing requirements that actually need constant latency mode?
      - And, am I willing to sacrifice the low idle current?

      If not, you do not need to worry about either the CONSTLAT or the LOWPWR register.
    2. Yes, peripherals can be in idle or run state. They are in idle when only the ENABLE register is set to 1, and in run state when e.g. the RX line is waiting for incoming data. This is the low layer hardware specification of being in "active" vs "idle" mode.

      However, the zephyr LOW_POWER vs ACTIVE state is not always directly translatable to the hardware modes. It really depends on the peripheral being used. For most peripherals LOW_POWER actually means "disabled" (i.e. ENABLE register = 0), because there are no reason to keep the device enabled if it is not being used. For some peripherals ACTIVE means that it is waiting for incoming data (e.g. UART and SPI slave), while peripherals that initiates the transaction (like SPI/TWI master), does not need to keep any RX lines active, so then ACTIVE just means that the peripheral is initialized and ready to be used, and might not necessarily consume any current.

      But yes, in general I would say that this statement is correct: "I assume that PM_DEVICE_STATE_ACTIVE corresponds to the run state and PM_DEVICE_STATE_LOW_POWER to the idle state."
Related