LOGO パソコン制御をもっと気軽に  
電子制御をもっと気楽に

低速CPUクロックによる省電力化

Arduino RP2040 2026/01/10

CPUクロックを 2MHz,4MHz,12MHz,40MHz,80MHz,120MHz に設定できます。
PowerSaveHelper.hppに書いてある電流値は Waveshare RP2040Zero でのtypeCの実測値です
download ZIP( 14Kbyte )

Viewer

PowerSaveHelper/src/Pico_sleep/rosc.c
/*
 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
#if defined(ARDUINO_ARCH_RP2040)

#include "pico.h"

// For MHZ definitions etc
#include "hardware/clocks.h"
#include "pico_rosc.h"

// Given a ROSC delay stage code, return the next-numerically-higher code.
// Top result bit is set when called on maximum ROSC code.
uint32_t next_rosc_code(uint32_t code) {
    return ((code | 0x08888888u) + 1u) & 0xf7777777u;
}

uint rosc_find_freq(uint32_t low_mhz, uint32_t high_mhz) {
    // TODO: This could be a lot better
    rosc_set_div(1);
    for (uint32_t code = 0; code <= 0x77777777u; code = next_rosc_code(code)) {
        rosc_set_freq(code);
        uint rosc_mhz = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC) / 1000;
        if ((rosc_mhz >= low_mhz) && (rosc_mhz <= high_mhz)) {
            return rosc_mhz;
        }
    }
    return 0;
}

void rosc_set_div(uint32_t div) {
    assert(div <= 31 && div >= 1);
    rosc_write(&rosc_hw->div, ROSC_DIV_VALUE_PASS + div);
}

void rosc_set_freq(uint32_t code) {
    rosc_write(&rosc_hw->freqa, (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB) | (code & 0xffffu));
    rosc_write(&rosc_hw->freqb, (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB) | (code >> 16u));
}

void rosc_set_range(uint range) {
    // Range should use enumvals from the headers and thus have the password correct
    rosc_write(&rosc_hw->ctrl, (ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB) | range);
}

void rosc_disable(void) {
    uint32_t tmp = rosc_hw->ctrl;
    tmp &= (~ROSC_CTRL_ENABLE_BITS);
    tmp |= (ROSC_CTRL_ENABLE_VALUE_DISABLE << ROSC_CTRL_ENABLE_LSB);
    rosc_write(&rosc_hw->ctrl, tmp);
    // Wait for stable to go away
    while(rosc_hw->status & ROSC_STATUS_STABLE_BITS);
}

void rosc_enable(void)
{
    uint32_t tmp = rosc_hw->ctrl;
    tmp &= (~ROSC_CTRL_ENABLE_BITS);
    tmp |= (ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB);
    rosc_write(&rosc_hw->ctrl, tmp);
    // Wait for stable
    while ((rosc_hw->status & ROSC_STATUS_STABLE_BITS) != ROSC_STATUS_STABLE_BITS);
}

void rosc_set_dormant(void) {
    // WARNING: This stops the rosc until woken up by an irq
    rosc_write(&rosc_hw->dormant, ROSC_DORMANT_VALUE_DORMANT);
    // Wait for it to become stable once woken up
    while(!(rosc_hw->status & ROSC_STATUS_STABLE_BITS));
}
#endif /* ARDUINO_ARCH_RP2040 */
CPU is RP2040 group
CPU is RP2040
Setup done

CPU 12MHz Cu=  1
PLL_SYS :     0KHz
PLL_USB :     0KHz
ROSC    :     0KHz
XOSC    : 12000KHz
CLK_REF : 12002KHz
CLK_SYS : 12000KHz  <-- 12MHz
CLK_PERI: 12002KHz
CLK_USB :     0KHz
CLK_ADC :     0KHz
CLK_RTC :     0Hz

CPU 40MHz Cu=  2
PLL_SYS : 40000KHz  <-- PLL_SYSが動作している
PLL_USB :     0KHz
ROSC    :     0KHz
XOSC    : 12000KHz
CLK_REF : 12002KHz
CLK_SYS : 40000KHz  <-- 40MHz
CLK_PERI: 12002KHz
CLK_USB :     0KHz
CLK_ADC :     0KHz
CLK_RTC :     0Hz

CPU 2MHz Cu=  3
PLL_SYS :     0KHz
PLL_USB :     0KHz
ROSC    :     0KHz
XOSC    : 12000KHz
CLK_REF :  4002KHz
CLK_SYS :  2000KHz  <-- 2MHz
CLK_PERI: 12000KHz
CLK_USB :     0KHz
CLK_ADC :     0KHz
CLK_RTC :     0Hz

シーブイデブ e-mail:mnakatani@cvdev-jp.com