Merge pull request #5665 from dhalbert/frequencyio-fix
add a frequencyin_reset() for VM restart
This commit is contained in:
commit
574039391e
@ -54,12 +54,33 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static frequencyio_frequencyin_obj_t *active_frequencyins[TC_INST_NUM];
|
static frequencyio_frequencyin_obj_t *active_frequencyins[TC_INST_NUM];
|
||||||
volatile uint8_t reference_tc = 0xff;
|
volatile uint8_t reference_tc;
|
||||||
#ifdef SAM_D5X_E5X
|
#ifdef SAM_D5X_E5X
|
||||||
static uint8_t dpll_gclk;
|
static uint8_t dpll_gclk;
|
||||||
|
|
||||||
|
#if !BOARD_HAS_CRYSTAL
|
||||||
|
static uint8_t osculp32k_gclk;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void frequencyin_emergency_cancel_capture(uint8_t index) {
|
#endif
|
||||||
|
|
||||||
|
void frequencyin_reset(void) {
|
||||||
|
for (uint8_t i = 0; i < TC_INST_NUM; i++) {
|
||||||
|
active_frequencyins[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
reference_tc = 0xff;
|
||||||
|
#ifdef SAM_D5X_E5X
|
||||||
|
dpll_gclk = 0xff;
|
||||||
|
|
||||||
|
#if !BOARD_HAS_CRYSTAL
|
||||||
|
osculp32k_gclk = 0xff;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void frequencyin_emergency_cancel_capture(uint8_t index) {
|
||||||
frequencyio_frequencyin_obj_t* self = active_frequencyins[index];
|
frequencyio_frequencyin_obj_t* self = active_frequencyins[index];
|
||||||
|
|
||||||
NVIC_DisableIRQ(self->TC_IRQ);
|
NVIC_DisableIRQ(self->TC_IRQ);
|
||||||
@ -93,7 +114,7 @@ void frequencyin_interrupt_handler(uint8_t index) {
|
|||||||
|
|
||||||
uint64_t current_ns = common_hal_time_monotonic_ns();
|
uint64_t current_ns = common_hal_time_monotonic_ns();
|
||||||
|
|
||||||
for (uint8_t i = 0; i <= (TC_INST_NUM - 1); i++) {
|
for (uint8_t i = 0; i < TC_INST_NUM; i++) {
|
||||||
if (active_frequencyins[i] != NULL) {
|
if (active_frequencyins[i] != NULL) {
|
||||||
frequencyio_frequencyin_obj_t* self = active_frequencyins[i];
|
frequencyio_frequencyin_obj_t* self = active_frequencyins[i];
|
||||||
Tc* tc = tc_insts[self->tc_index];
|
Tc* tc = tc_insts[self->tc_index];
|
||||||
@ -143,7 +164,7 @@ void frequencyin_interrupt_handler(uint8_t index) {
|
|||||||
ref_tc->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF;
|
ref_tc->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void frequencyin_reference_tc_init() {
|
static void frequencyin_reference_tc_init(void) {
|
||||||
if (reference_tc == 0xff) {
|
if (reference_tc == 0xff) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -154,9 +175,6 @@ void frequencyin_reference_tc_init() {
|
|||||||
// use the DPLL we setup so that the reference_tc and freqin_tc(s)
|
// use the DPLL we setup so that the reference_tc and freqin_tc(s)
|
||||||
// are using the same clock frequency.
|
// are using the same clock frequency.
|
||||||
#ifdef SAM_D5X_E5X
|
#ifdef SAM_D5X_E5X
|
||||||
if (dpll_gclk == 0xff) {
|
|
||||||
frequencyin_samd51_start_dpll();
|
|
||||||
}
|
|
||||||
set_timer_handler(true, reference_tc, TC_HANDLER_FREQUENCYIN);
|
set_timer_handler(true, reference_tc, TC_HANDLER_FREQUENCYIN);
|
||||||
turn_on_clocks(true, reference_tc, dpll_gclk);
|
turn_on_clocks(true, reference_tc, dpll_gclk);
|
||||||
#endif
|
#endif
|
||||||
@ -178,7 +196,7 @@ void frequencyin_reference_tc_init() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool frequencyin_reference_tc_enabled() {
|
static bool frequencyin_reference_tc_enabled(void) {
|
||||||
if (reference_tc == 0xff) {
|
if (reference_tc == 0xff) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -186,7 +204,7 @@ bool frequencyin_reference_tc_enabled() {
|
|||||||
return tc->COUNT16.CTRLA.bit.ENABLE;
|
return tc->COUNT16.CTRLA.bit.ENABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void frequencyin_reference_tc_enable(bool enable) {
|
static void frequencyin_reference_tc_enable(bool enable) {
|
||||||
if (reference_tc == 0xff) {
|
if (reference_tc == 0xff) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -195,56 +213,69 @@ void frequencyin_reference_tc_enable(bool enable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SAM_D5X_E5X
|
#ifdef SAM_D5X_E5X
|
||||||
void frequencyin_samd51_start_dpll() {
|
static bool frequencyin_samd51_start_dpll(void) {
|
||||||
if (clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
|
if (clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t free_gclk = find_free_gclk(1);
|
dpll_gclk = find_free_gclk(1);
|
||||||
if (free_gclk == 0xff) {
|
if (dpll_gclk == 0xff) {
|
||||||
dpll_gclk = 0xff;
|
return false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL1].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(free_gclk);
|
|
||||||
// TC4-7 can only have a max of 100MHz source
|
// TC4-7 can only have a max of 100MHz source
|
||||||
// DPLL1 frequency equation with [X]OSC32K as source: 98.304MHz = 32768(2999 + 1 + 0/32)
|
// DPLL1 frequency equation with [X]OSC32K as source: 98.304MHz = 32768(2999 + 1 + 0/32)
|
||||||
// Will also enable the Lock Bypass due to low-frequency sources causing DPLL unlocks
|
// Will also enable the Lock Bypass due to low-frequency sources causing DPLL unlocks
|
||||||
// as outlined in the Errata (1.12.1)
|
// as outlined in the Errata (1.12.1)
|
||||||
OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0) | OSCCTRL_DPLLRATIO_LDR(2999);
|
OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0) | OSCCTRL_DPLLRATIO_LDR(2999);
|
||||||
#if BOARD_HAS_CRYSTAL
|
|
||||||
// we can use XOSC32K directly as the source
|
|
||||||
OSC32KCTRL->XOSC32K.bit.EN32K = 1;
|
|
||||||
OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK(1) | OSCCTRL_DPLLCTRLB_LBYPASS;
|
|
||||||
#else
|
|
||||||
// can't use OSCULP32K directly; need to setup a GCLK as a reference,
|
|
||||||
// which must be done in samd/clocks.c to avoid waiting for sync
|
|
||||||
return;
|
|
||||||
//OSC32KCTRL->OSCULP32K.bit.EN32K = 1;
|
|
||||||
//OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK(0);
|
|
||||||
#endif
|
|
||||||
OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
|
|
||||||
|
|
||||||
|
#if BOARD_HAS_CRYSTAL
|
||||||
|
// we can use XOSC32K directly as the source. It has already been initialized in clocks.c
|
||||||
|
OSCCTRL->Dpll[1].DPLLCTRLB.reg =
|
||||||
|
OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC32_Val) | OSCCTRL_DPLLCTRLB_LBYPASS;
|
||||||
|
#else
|
||||||
|
// We can't use OSCULP32K directly. Set up a GCLK controlled by it
|
||||||
|
// Then use that GCLK as the reference oscillator for the DPLL.
|
||||||
|
osculp32k_gclk = find_free_gclk(1);
|
||||||
|
if (osculp32k_gclk == 0xff) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
enable_clock_generator(osculp32k_gclk, GCLK_GENCTRL_SRC_OSCULP32K_Val, 1);
|
||||||
|
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL1].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(OSCCTRL_GCLK_ID_FDPLL1);
|
||||||
|
OSCCTRL->Dpll[1].DPLLCTRLB.reg =
|
||||||
|
OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_GCLK_Val) | OSCCTRL_DPLLCTRLB_LBYPASS;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
|
||||||
while (!(OSCCTRL->Dpll[1].DPLLSTATUS.bit.LOCK || OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY)) {}
|
while (!(OSCCTRL->Dpll[1].DPLLSTATUS.bit.LOCK || OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY)) {}
|
||||||
enable_clock_generator(free_gclk, GCLK_GENCTRL_SRC_DPLL1_Val, 1);
|
|
||||||
dpll_gclk = free_gclk;
|
enable_clock_generator(dpll_gclk, GCLK_GENCTRL_SRC_DPLL1_Val, 1);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void frequencyin_samd51_stop_dpll() {
|
static void frequencyin_samd51_stop_dpll(void) {
|
||||||
if (!clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
|
if (!clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dpll_gclk != 0xff) {
|
||||||
disable_clock_generator(dpll_gclk);
|
disable_clock_generator(dpll_gclk);
|
||||||
|
dpll_gclk = 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !BOARD_HAS_CRYSTAL
|
||||||
|
if (osculp32k_gclk != 0xff) {
|
||||||
|
disable_clock_generator(osculp32k_gclk);
|
||||||
|
osculp32k_gclk = 0xff;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL1].reg = 0;
|
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL1].reg = 0;
|
||||||
OSCCTRL->Dpll[1].DPLLCTRLA.reg = 0;
|
OSCCTRL->Dpll[1].DPLLCTRLA.reg = 0;
|
||||||
OSCCTRL->Dpll[1].DPLLRATIO.reg = 0;
|
OSCCTRL->Dpll[1].DPLLRATIO.reg = 0;
|
||||||
OSCCTRL->Dpll[1].DPLLCTRLB.reg = 0;
|
OSCCTRL->Dpll[1].DPLLCTRLB.reg = 0;
|
||||||
|
|
||||||
while (OSCCTRL->Dpll[1].DPLLSYNCBUSY.bit.ENABLE) {
|
while (OSCCTRL->Dpll[1].DPLLSYNCBUSY.bit.ENABLE) {
|
||||||
}
|
}
|
||||||
dpll_gclk = 0xff;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -421,7 +452,7 @@ void common_hal_frequencyio_frequencyin_deinit(frequencyio_frequencyin_obj_t* se
|
|||||||
self->pin = NO_PIN;
|
self->pin = NO_PIN;
|
||||||
|
|
||||||
bool check_active = false;
|
bool check_active = false;
|
||||||
for (uint8_t i = 0; i <= (TC_INST_NUM - 1); i++) {
|
for (uint8_t i = 0; i < TC_INST_NUM; i++) {
|
||||||
if (active_frequencyins[i] != NULL) {
|
if (active_frequencyins[i] != NULL) {
|
||||||
check_active = true;
|
check_active = true;
|
||||||
}
|
}
|
||||||
|
@ -46,14 +46,7 @@ typedef struct {
|
|||||||
} frequencyio_frequencyin_obj_t;
|
} frequencyio_frequencyin_obj_t;
|
||||||
|
|
||||||
void frequencyin_interrupt_handler(uint8_t index);
|
void frequencyin_interrupt_handler(uint8_t index);
|
||||||
void frequencyin_emergency_cancel_capture(uint8_t index);
|
void frequencyin_reset(void);
|
||||||
void frequencyin_reference_tc_init(void);
|
|
||||||
void frequencyin_reference_tc_enable(bool enable);
|
|
||||||
bool frequencyin_reference_tc_enabled(void);
|
|
||||||
#ifdef SAM_D5X_E5X
|
|
||||||
void frequencyin_samd51_start_dpll(void);
|
|
||||||
void frequencyin_samd51_stop_dpll(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_FREQUENCYIO_FREQUENCYIN_H
|
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_FREQUENCYIO_FREQUENCYIN_H
|
||||||
|
@ -71,6 +71,10 @@
|
|||||||
#include "common-hal/busio/__init__.h"
|
#include "common-hal/busio/__init__.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CIRCUITPY_FREQUENCYIO
|
||||||
|
#include "common-hal/frequencyio/FrequencyIn.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "common-hal/microcontroller/Pin.h"
|
#include "common-hal/microcontroller/Pin.h"
|
||||||
|
|
||||||
#if CIRCUITPY_PULSEIO
|
#if CIRCUITPY_PULSEIO
|
||||||
@ -388,6 +392,10 @@ void reset_port(void) {
|
|||||||
i2sout_reset();
|
i2sout_reset();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CIRCUITPY_FREQUENCYIO
|
||||||
|
frequencyin_reset();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CIRCUITPY_TOUCHIO && CIRCUITPY_TOUCHIO_USE_NATIVE
|
#if CIRCUITPY_TOUCHIO && CIRCUITPY_TOUCHIO_USE_NATIVE
|
||||||
touchin_reset();
|
touchin_reset();
|
||||||
#endif
|
#endif
|
||||||
@ -399,7 +407,7 @@ void reset_port(void) {
|
|||||||
#if CIRCUITPY_PWMIO
|
#if CIRCUITPY_PWMIO
|
||||||
pwmout_reset();
|
pwmout_reset();
|
||||||
#endif
|
#endif
|
||||||
#if CIRCUITPY_PWMIO || CIRCUITPY_AUDIOIO
|
#if CIRCUITPY_PWMIO || CIRCUITPY_AUDIOIO || CIRCUITPY_FREQUENCYIO
|
||||||
reset_timers();
|
reset_timers();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user