Compare commits
6 commits
master
...
circuitpyt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12d503dc5c | ||
|
|
eb94f53a04 | ||
|
|
3c9df1c731 | ||
|
|
d492d2d4d6 | ||
|
|
9833d4f4fa | ||
|
|
c83e2dcee5 |
4 changed files with 34 additions and 16 deletions
|
|
@ -7,6 +7,7 @@
|
||||||
#ifndef _PICO_CRITICAL_SECTION_H
|
#ifndef _PICO_CRITICAL_SECTION_H
|
||||||
#define _PICO_CRITICAL_SECTION_H
|
#define _PICO_CRITICAL_SECTION_H
|
||||||
|
|
||||||
|
#include "pico.h"
|
||||||
#include "pico/lock_core.h"
|
#include "pico/lock_core.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
@ -58,7 +59,7 @@ void critical_section_init_with_lock_num(critical_section_t *crit_sec, uint lock
|
||||||
*
|
*
|
||||||
* \param crit_sec Pointer to critical_section structure
|
* \param crit_sec Pointer to critical_section structure
|
||||||
*/
|
*/
|
||||||
static inline void critical_section_enter_blocking(critical_section_t *crit_sec) {
|
__force_inline static void critical_section_enter_blocking(critical_section_t *crit_sec) {
|
||||||
crit_sec->save = spin_lock_blocking(crit_sec->spin_lock);
|
crit_sec->save = spin_lock_blocking(crit_sec->spin_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,7 +68,7 @@ static inline void critical_section_enter_blocking(critical_section_t *crit_sec)
|
||||||
*
|
*
|
||||||
* \param crit_sec Pointer to critical_section structure
|
* \param crit_sec Pointer to critical_section structure
|
||||||
*/
|
*/
|
||||||
static inline void critical_section_exit(critical_section_t *crit_sec) {
|
__force_inline static void critical_section_exit(critical_section_t *crit_sec) {
|
||||||
spin_unlock(crit_sec->spin_lock, crit_sec->save);
|
spin_unlock(crit_sec->spin_lock, crit_sec->save);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,12 @@ extern void tight_loop_contents();
|
||||||
#define __noinline __attribute__((noinline))
|
#define __noinline __attribute__((noinline))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __force_inline
|
||||||
|
// don't think it is critical to inline in host mode, and this is simpler than picking the
|
||||||
|
// correct attribute incantation for always_inline on different compiler versions
|
||||||
|
#define __force_inline inline
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef __aligned
|
#ifndef __aligned
|
||||||
#define __aligned(x) __attribute__((aligned(x)))
|
#define __aligned(x) __attribute__((aligned(x)))
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ void powman_timer_set_1khz_tick_source_lposc_with_hz(uint32_t lposc_freq_hz) {
|
||||||
bool was_running = powman_timer_is_running();
|
bool was_running = powman_timer_is_running();
|
||||||
if (was_running) powman_timer_stop();
|
if (was_running) powman_timer_stop();
|
||||||
uint32_t lposc_freq_khz = lposc_freq_hz / 1000;
|
uint32_t lposc_freq_khz = lposc_freq_hz / 1000;
|
||||||
uint32_t lposc_freq_khz_frac16 = (lposc_freq_khz % 1000) * 65536 / 1000;
|
uint32_t lposc_freq_khz_frac16 = (lposc_freq_hz % 1000) * 65536 / 1000;
|
||||||
powman_write(&powman_hw->lposc_freq_khz_int, lposc_freq_khz);
|
powman_write(&powman_hw->lposc_freq_khz_int, lposc_freq_khz);
|
||||||
powman_write(&powman_hw->lposc_freq_khz_frac, lposc_freq_khz_frac16);
|
powman_write(&powman_hw->lposc_freq_khz_frac, lposc_freq_khz_frac16);
|
||||||
powman_set_bits(&powman_hw->timer, POWMAN_TIMER_USE_LPOSC_BITS);
|
powman_set_bits(&powman_hw->timer, POWMAN_TIMER_USE_LPOSC_BITS);
|
||||||
|
|
@ -87,7 +87,7 @@ void powman_timer_set_1khz_tick_source_xosc_with_hz(uint32_t xosc_freq_hz) {
|
||||||
bool was_running = powman_timer_is_running();
|
bool was_running = powman_timer_is_running();
|
||||||
if (was_running) powman_timer_stop();
|
if (was_running) powman_timer_stop();
|
||||||
uint32_t xosc_freq_khz = xosc_freq_hz / 1000;
|
uint32_t xosc_freq_khz = xosc_freq_hz / 1000;
|
||||||
uint32_t xosc_freq_khz_frac16 = (xosc_freq_khz % 1000) * 65536 / 1000;
|
uint32_t xosc_freq_khz_frac16 = (xosc_freq_hz % 1000) * 65536 / 1000;
|
||||||
powman_write(&powman_hw->xosc_freq_khz_int, xosc_freq_khz);
|
powman_write(&powman_hw->xosc_freq_khz_int, xosc_freq_khz);
|
||||||
powman_write(&powman_hw->xosc_freq_khz_frac, xosc_freq_khz_frac16);
|
powman_write(&powman_hw->xosc_freq_khz_frac, xosc_freq_khz_frac16);
|
||||||
powman_set_bits(&powman_hw->timer, POWMAN_TIMER_USE_XOSC_BITS);
|
powman_set_bits(&powman_hw->timer, POWMAN_TIMER_USE_XOSC_BITS);
|
||||||
|
|
@ -125,7 +125,7 @@ void powman_timer_disable_gpio_1hz_sync(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
powman_power_state powman_get_power_state(void) {
|
powman_power_state powman_get_power_state(void) {
|
||||||
uint32_t state_reg = powman_hw->state & POWMAN_STATE_CURRENT_BITS;
|
uint32_t state_reg = ~powman_hw->state & POWMAN_STATE_CURRENT_BITS;
|
||||||
// todo we should have hardware/regs/powman.h values for these
|
// todo we should have hardware/regs/powman.h values for these
|
||||||
static_assert(POWMAN_POWER_DOMAIN_SRAM_BANK1 == 0, "");
|
static_assert(POWMAN_POWER_DOMAIN_SRAM_BANK1 == 0, "");
|
||||||
static_assert(POWMAN_POWER_DOMAIN_SRAM_BANK0 == 1, "");
|
static_assert(POWMAN_POWER_DOMAIN_SRAM_BANK0 == 1, "");
|
||||||
|
|
@ -181,19 +181,30 @@ int powman_set_power_state(powman_power_state state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool powman_configure_wakeup_state(powman_power_state sleep_state, powman_power_state wakeup_state) {
|
bool powman_configure_wakeup_state(powman_power_state sleep_state, powman_power_state wakeup_state) {
|
||||||
// When powman wakes up it can keep the state of the sram0 and sram1 banks. Note, it can't
|
// Must be entering a P1 low-power state (SWCORE OFF).
|
||||||
// explicitly
|
bool valid = !powman_power_state_is_domain_on(sleep_state, POWMAN_POWER_DOMAIN_SWITCHED_CORE);
|
||||||
bool valid = powman_power_state_is_domain_on(wakeup_state, POWMAN_POWER_DOMAIN_XIP_CACHE);
|
// Must be waking up in a P0 state (SWCORE ON).
|
||||||
valid &= powman_power_state_is_domain_on(wakeup_state, POWMAN_POWER_DOMAIN_SWITCHED_CORE);
|
valid &= powman_power_state_is_domain_on(wakeup_state, POWMAN_POWER_DOMAIN_SWITCHED_CORE);
|
||||||
valid &= powman_power_state_is_domain_on(sleep_state, POWMAN_POWER_DOMAIN_SRAM_BANK0) ==
|
powman_power_state current_state = powman_get_power_state();
|
||||||
powman_power_state_is_domain_on(wakeup_state, POWMAN_POWER_DOMAIN_SRAM_BANK0);
|
bool current_sram0 = powman_power_state_is_domain_on(current_state, POWMAN_POWER_DOMAIN_SRAM_BANK0);
|
||||||
valid &= powman_power_state_is_domain_on(sleep_state, POWMAN_POWER_DOMAIN_SRAM_BANK1) ==
|
bool current_sram1 = powman_power_state_is_domain_on(current_state, POWMAN_POWER_DOMAIN_SRAM_BANK1);
|
||||||
powman_power_state_is_domain_on(wakeup_state, POWMAN_POWER_DOMAIN_SRAM_BANK1);
|
bool sleep_sram0 = powman_power_state_is_domain_on(sleep_state, POWMAN_POWER_DOMAIN_SRAM_BANK0);
|
||||||
|
bool sleep_sram1 = powman_power_state_is_domain_on(sleep_state, POWMAN_POWER_DOMAIN_SRAM_BANK1);
|
||||||
|
bool wakeup_sram0 = powman_power_state_is_domain_on(wakeup_state, POWMAN_POWER_DOMAIN_SRAM_BANK0);
|
||||||
|
bool wakeup_sram1 = powman_power_state_is_domain_on(wakeup_state, POWMAN_POWER_DOMAIN_SRAM_BANK1);
|
||||||
|
// Sleep state cannot turn ON SRAM0 or SRAM1 if it is OFF in the current state.
|
||||||
|
if (!current_sram0) valid &= !sleep_sram0;
|
||||||
|
if (!current_sram1) valid &= !sleep_sram1;
|
||||||
|
// Wakeup state cannot turn OFF SRAM0 or SRAM1 if it is ON in the sleep state.
|
||||||
|
if (sleep_sram0) valid &= wakeup_sram0;
|
||||||
|
if (sleep_sram1) valid &= wakeup_sram1;
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
// Prepare power sequencer to power SRAM domains on wakeup.
|
||||||
powman_clear_bits(&powman_hw->seq_cfg, POWMAN_SEQ_CFG_HW_PWRUP_SRAM0_BITS | POWMAN_SEQ_CFG_HW_PWRUP_SRAM1_BITS);
|
powman_clear_bits(&powman_hw->seq_cfg, POWMAN_SEQ_CFG_HW_PWRUP_SRAM0_BITS | POWMAN_SEQ_CFG_HW_PWRUP_SRAM1_BITS);
|
||||||
uint32_t seq_cfg_set = 0;
|
uint32_t seq_cfg_set = 0;
|
||||||
if (!powman_power_state_is_domain_on(sleep_state, POWMAN_POWER_DOMAIN_SRAM_BANK0)) seq_cfg_set |= POWMAN_SEQ_CFG_HW_PWRUP_SRAM0_BITS;
|
// Sequencer SRAM power transitions from sleep to wakeup are: OFF->ON (0), ON->ON (1) and OFF->OFF (1)
|
||||||
if (!powman_power_state_is_domain_on(sleep_state, POWMAN_POWER_DOMAIN_SRAM_BANK1)) seq_cfg_set |= POWMAN_SEQ_CFG_HW_PWRUP_SRAM1_BITS;
|
if (sleep_sram0 == wakeup_sram0) seq_cfg_set |= POWMAN_SEQ_CFG_HW_PWRUP_SRAM0_BITS;
|
||||||
|
if (sleep_sram1 == wakeup_sram1) seq_cfg_set |= POWMAN_SEQ_CFG_HW_PWRUP_SRAM1_BITS;
|
||||||
powman_set_bits(&powman_hw->seq_cfg, seq_cfg_set);
|
powman_set_bits(&powman_hw->seq_cfg, seq_cfg_set);
|
||||||
}
|
}
|
||||||
return valid;
|
return valid;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ embedded_block:
|
||||||
PICOBIN_IMAGE_TYPE_EXE_CPU_AS_BITS(RISCV) | \
|
PICOBIN_IMAGE_TYPE_EXE_CPU_AS_BITS(RISCV) | \
|
||||||
PICOBIN_IMAGE_TYPE_EXE_CHIP_AS_BITS(RP2350) | \
|
PICOBIN_IMAGE_TYPE_EXE_CHIP_AS_BITS(RP2350) | \
|
||||||
CRT0_TBYB_FLAG
|
CRT0_TBYB_FLAG
|
||||||
#elif defined(PICO_RP2040)
|
#elif PICO_RP2040
|
||||||
.hword PICOBIN_IMAGE_TYPE_IMAGE_TYPE_AS_BITS(EXE) | \
|
.hword PICOBIN_IMAGE_TYPE_IMAGE_TYPE_AS_BITS(EXE) | \
|
||||||
PICOBIN_IMAGE_TYPE_EXE_SECURITY_AS_BITS(NS) | \
|
PICOBIN_IMAGE_TYPE_EXE_SECURITY_AS_BITS(NS) | \
|
||||||
PICOBIN_IMAGE_TYPE_EXE_CPU_AS_BITS(ARM) | \
|
PICOBIN_IMAGE_TYPE_EXE_CPU_AS_BITS(ARM) | \
|
||||||
|
|
@ -84,7 +84,7 @@ embedded_block:
|
||||||
.word SRAM_END // stack pointer
|
.word SRAM_END // stack pointer
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PICO_RP2040
|
#if !PICO_RP2040
|
||||||
#if PICO_NO_FLASH
|
#if PICO_NO_FLASH
|
||||||
// If no_flash bin, then include a vector table item
|
// If no_flash bin, then include a vector table item
|
||||||
.byte PICOBIN_BLOCK_ITEM_1BS_VECTOR_TABLE
|
.byte PICOBIN_BLOCK_ITEM_1BS_VECTOR_TABLE
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue