mirror of
https://github.com/meshtastic/firmware.git
synced 2025-02-01 02:09:57 +00:00
Posthumous tronkination
This commit is contained in:
parent
a0dd7b43d5
commit
a05b009379
@ -7,8 +7,8 @@
|
||||
#ifndef _HARDWARE_ROSC_H_
|
||||
#define _HARDWARE_ROSC_H_
|
||||
|
||||
#include "pico.h"
|
||||
#include "hardware/structs/rosc.h"
|
||||
#include "pico.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -68,15 +68,18 @@ uint rosc_find_freq(uint32_t low_mhz, uint32_t high_mhz);
|
||||
|
||||
void rosc_set_div(uint32_t div);
|
||||
|
||||
inline static void rosc_clear_bad_write(void) {
|
||||
inline static void rosc_clear_bad_write(void)
|
||||
{
|
||||
hw_clear_bits(&rosc_hw->status, ROSC_STATUS_BADWRITE_BITS);
|
||||
}
|
||||
|
||||
inline static bool rosc_write_okay(void) {
|
||||
inline static bool rosc_write_okay(void)
|
||||
{
|
||||
return !(rosc_hw->status & ROSC_STATUS_BADWRITE_BITS);
|
||||
}
|
||||
|
||||
inline static void rosc_write(io_rw_32 *addr, uint32_t value) {
|
||||
inline static void rosc_write(io_rw_32 *addr, uint32_t value)
|
||||
{
|
||||
rosc_clear_bad_write();
|
||||
assert(rosc_write_okay());
|
||||
*addr = value;
|
||||
|
@ -12,11 +12,13 @@
|
||||
|
||||
// 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) {
|
||||
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) {
|
||||
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)) {
|
||||
@ -29,33 +31,40 @@ uint rosc_find_freq(uint32_t low_mhz, uint32_t high_mhz) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rosc_set_div(uint32_t div) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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);
|
||||
while (rosc_hw->status & ROSC_STATUS_STABLE_BITS)
|
||||
;
|
||||
}
|
||||
|
||||
void rosc_set_dormant(void) {
|
||||
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));
|
||||
while (!(rosc_hw->status & ROSC_STATUS_STABLE_BITS))
|
||||
;
|
||||
}
|
@ -2,9 +2,9 @@
|
||||
#include "hardware/xosc.h"
|
||||
#include <hardware/clocks.h>
|
||||
#include <hardware/pll.h>
|
||||
#include <pico/sleep.h>
|
||||
#include <pico/stdlib.h>
|
||||
#include <pico/unique_id.h>
|
||||
#include <pico/sleep.h>
|
||||
|
||||
void setBluetoothEnable(bool enable)
|
||||
{
|
||||
@ -13,11 +13,13 @@ void setBluetoothEnable(bool enable)
|
||||
|
||||
static bool awake;
|
||||
|
||||
static void sleep_callback(void) {
|
||||
static void sleep_callback(void)
|
||||
{
|
||||
awake = true;
|
||||
}
|
||||
|
||||
void epoch_to_datetime(time_t epoch, datetime_t *dt) {
|
||||
void epoch_to_datetime(time_t epoch, datetime_t *dt)
|
||||
{
|
||||
struct tm *tm_info;
|
||||
|
||||
tm_info = gmtime(&epoch);
|
||||
|
@ -7,8 +7,8 @@
|
||||
#ifndef _PICO_SLEEP_H_
|
||||
#define _PICO_SLEEP_H_
|
||||
|
||||
#include "pico.h"
|
||||
#include "hardware/rtc.h"
|
||||
#include "pico.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -30,11 +30,7 @@ extern "C" {
|
||||
* \include hello_sleep.c
|
||||
|
||||
*/
|
||||
typedef enum {
|
||||
DORMANT_SOURCE_NONE,
|
||||
DORMANT_SOURCE_XOSC,
|
||||
DORMANT_SOURCE_ROSC
|
||||
} dormant_source_t;
|
||||
typedef enum { DORMANT_SOURCE_NONE, DORMANT_SOURCE_XOSC, DORMANT_SOURCE_ROSC } dormant_source_t;
|
||||
|
||||
/*! \brief Set all clock sources to the the dormant clock source to prepare for sleep.
|
||||
* \ingroup hardware_sleep
|
||||
@ -46,14 +42,16 @@ void sleep_run_from_dormant_source(dormant_source_t dormant_source);
|
||||
/*! \brief Set the dormant clock source to be the crystal oscillator
|
||||
* \ingroup hardware_sleep
|
||||
*/
|
||||
static inline void sleep_run_from_xosc(void) {
|
||||
static inline void sleep_run_from_xosc(void)
|
||||
{
|
||||
sleep_run_from_dormant_source(DORMANT_SOURCE_XOSC);
|
||||
}
|
||||
|
||||
/*! \brief Set the dormant clock source to be the ring oscillator
|
||||
* \ingroup hardware_sleep
|
||||
*/
|
||||
static inline void sleep_run_from_rosc(void) {
|
||||
static inline void sleep_run_from_rosc(void)
|
||||
{
|
||||
sleep_run_from_dormant_source(DORMANT_SOURCE_ROSC);
|
||||
}
|
||||
|
||||
@ -85,7 +83,8 @@ void sleep_goto_dormant_until_pin(uint gpio_pin, bool edge, bool high);
|
||||
*
|
||||
* \param gpio_pin The pin to provide the wake up
|
||||
*/
|
||||
static inline void sleep_goto_dormant_until_edge_high(uint gpio_pin) {
|
||||
static inline void sleep_goto_dormant_until_edge_high(uint gpio_pin)
|
||||
{
|
||||
sleep_goto_dormant_until_pin(gpio_pin, true, true);
|
||||
}
|
||||
|
||||
@ -96,7 +95,8 @@ static inline void sleep_goto_dormant_until_edge_high(uint gpio_pin) {
|
||||
*
|
||||
* \param gpio_pin The pin to provide the wake up
|
||||
*/
|
||||
static inline void sleep_goto_dormant_until_level_high(uint gpio_pin) {
|
||||
static inline void sleep_goto_dormant_until_level_high(uint gpio_pin)
|
||||
{
|
||||
sleep_goto_dormant_until_pin(gpio_pin, false, true);
|
||||
}
|
||||
|
||||
|
@ -6,15 +6,15 @@
|
||||
|
||||
#include "pico.h"
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/sleep.h"
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "hardware/rtc.h"
|
||||
#include "hardware/pll.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include "hardware/xosc.h"
|
||||
#include "hardware/rosc.h"
|
||||
#include "hardware/pll.h"
|
||||
#include "hardware/regs/io_bank0.h"
|
||||
#include "hardware/rosc.h"
|
||||
#include "hardware/rtc.h"
|
||||
#include "hardware/xosc.h"
|
||||
// For __wfi
|
||||
#include "hardware/sync.h"
|
||||
// For scb_hw so we can enable deep sleep
|
||||
@ -29,41 +29,37 @@
|
||||
// block. For example you could keep clk_rtc running. Some destinations (proc0 and proc1 wakeup logic)
|
||||
// can't be stopped in sleep mode otherwise there wouldn't be enough logic to wake up again.
|
||||
|
||||
|
||||
// TODO: Optionally, memories can also be powered down.
|
||||
|
||||
static dormant_source_t _dormant_source;
|
||||
|
||||
bool dormant_source_valid(dormant_source_t dormant_source) {
|
||||
bool dormant_source_valid(dormant_source_t dormant_source)
|
||||
{
|
||||
return (dormant_source == DORMANT_SOURCE_XOSC) || (dormant_source == DORMANT_SOURCE_ROSC);
|
||||
}
|
||||
|
||||
// In order to go into dormant mode we need to be running from a stoppable clock source:
|
||||
// either the xosc or rosc with no PLLs running. This means we disable the USB and ADC clocks
|
||||
// and all PLLs
|
||||
void sleep_run_from_dormant_source(dormant_source_t dormant_source) {
|
||||
void sleep_run_from_dormant_source(dormant_source_t dormant_source)
|
||||
{
|
||||
assert(dormant_source_valid(dormant_source));
|
||||
_dormant_source = dormant_source;
|
||||
|
||||
// FIXME: Just defining average rosc freq here.
|
||||
uint src_hz = (dormant_source == DORMANT_SOURCE_XOSC) ? XOSC_HZ : 6.5 * MHZ;
|
||||
uint clk_ref_src = (dormant_source == DORMANT_SOURCE_XOSC) ?
|
||||
CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC :
|
||||
CLOCKS_CLK_REF_CTRL_SRC_VALUE_ROSC_CLKSRC_PH;
|
||||
uint clk_ref_src = (dormant_source == DORMANT_SOURCE_XOSC) ? CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC
|
||||
: CLOCKS_CLK_REF_CTRL_SRC_VALUE_ROSC_CLKSRC_PH;
|
||||
|
||||
// CLK_REF = XOSC or ROSC
|
||||
clock_configure(clk_ref,
|
||||
clk_ref_src,
|
||||
clock_configure(clk_ref, clk_ref_src,
|
||||
0, // No aux mux
|
||||
src_hz,
|
||||
src_hz);
|
||||
src_hz, src_hz);
|
||||
|
||||
// CLK SYS = CLK_REF
|
||||
clock_configure(clk_sys,
|
||||
CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF,
|
||||
clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF,
|
||||
0, // Using glitchless mux
|
||||
src_hz,
|
||||
src_hz);
|
||||
src_hz, src_hz);
|
||||
|
||||
// CLK USB = 0MHz
|
||||
clock_stop(clk_usb);
|
||||
@ -72,22 +68,15 @@ void sleep_run_from_dormant_source(dormant_source_t dormant_source) {
|
||||
clock_stop(clk_adc);
|
||||
|
||||
// CLK RTC = ideally XOSC (12MHz) / 256 = 46875Hz but could be rosc
|
||||
uint clk_rtc_src = (dormant_source == DORMANT_SOURCE_XOSC) ?
|
||||
CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC :
|
||||
CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH;
|
||||
uint clk_rtc_src = (dormant_source == DORMANT_SOURCE_XOSC) ? CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC
|
||||
: CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH;
|
||||
|
||||
clock_configure(clk_rtc,
|
||||
0, // No GLMUX
|
||||
clk_rtc_src,
|
||||
src_hz,
|
||||
46875);
|
||||
clk_rtc_src, src_hz, 46875);
|
||||
|
||||
// CLK PERI = clk_sys. Used as reference clock for Peripherals. No dividers so just select and enable
|
||||
clock_configure(clk_peri,
|
||||
0,
|
||||
CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS,
|
||||
src_hz,
|
||||
src_hz);
|
||||
clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS, src_hz, src_hz);
|
||||
|
||||
pll_deinit(pll_sys);
|
||||
pll_deinit(pll_usb);
|
||||
@ -107,7 +96,8 @@ void sleep_run_from_dormant_source(dormant_source_t dormant_source) {
|
||||
}
|
||||
|
||||
// Go to sleep until woken up by the RTC
|
||||
void sleep_goto_sleep_until(datetime_t *t, rtc_callback_t callback) {
|
||||
void sleep_goto_sleep_until(datetime_t *t, rtc_callback_t callback)
|
||||
{
|
||||
// We should have already called the sleep_run_from_dormant_source function
|
||||
assert(dormant_source_valid(_dormant_source));
|
||||
|
||||
@ -125,7 +115,8 @@ void sleep_goto_sleep_until(datetime_t *t, rtc_callback_t callback) {
|
||||
__wfi();
|
||||
}
|
||||
|
||||
static void _go_dormant(void) {
|
||||
static void _go_dormant(void)
|
||||
{
|
||||
assert(dormant_source_valid(_dormant_source));
|
||||
|
||||
if (_dormant_source == DORMANT_SOURCE_XOSC) {
|
||||
@ -135,7 +126,8 @@ static void _go_dormant(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void sleep_goto_dormant_until_pin(uint gpio_pin, bool edge, bool high) {
|
||||
void sleep_goto_dormant_until_pin(uint gpio_pin, bool edge, bool high)
|
||||
{
|
||||
bool low = !high;
|
||||
bool level = !edge;
|
||||
|
||||
@ -144,10 +136,14 @@ void sleep_goto_dormant_until_pin(uint gpio_pin, bool edge, bool high) {
|
||||
|
||||
uint32_t event = 0;
|
||||
|
||||
if (level && low) event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_LEVEL_LOW_BITS;
|
||||
if (level && high) event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_LEVEL_HIGH_BITS;
|
||||
if (edge && high) event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_EDGE_HIGH_BITS;
|
||||
if (edge && low) event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_EDGE_LOW_BITS;
|
||||
if (level && low)
|
||||
event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_LEVEL_LOW_BITS;
|
||||
if (level && high)
|
||||
event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_LEVEL_HIGH_BITS;
|
||||
if (edge && high)
|
||||
event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_EDGE_HIGH_BITS;
|
||||
if (edge && low)
|
||||
event = IO_BANK0_DORMANT_WAKE_INTE0_GPIO0_EDGE_LOW_BITS;
|
||||
|
||||
gpio_set_dormant_irq_enabled(gpio_pin, event, true);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user