Merge branch 'silicon-errata' into advanced

Implements the recommended workarounds for numerous silicon errata,
reducing power consumption and preventing freezes and hard faults.

Tested-by: Alex Maestas <git@se30.xyz>
Tested-by: Matheus Afonso Martins Moreira <matheus.a.m.moreira@gmail.com>
Tested-on-hardware-by: Alex Maestas <git@se30.xyz>
Tested-on-hardware-by: Matheus Afonso Martins Moreira <matheus.a.m.moreira@gmail.com>
Reviewed-by: Wesley Aptekar-Cassels <me@wesleyac.com>
Reviewed-by: Matheus Afonso Martins Moreira <matheus.a.m.moreira@gmail.com>
Signed-off-by: Matheus Afonso Martins Moreira <matheus.a.m.moreira@gmail.com>
GitHub-Pull-Request: https://github.com/joeycastillo/Sensor-Watch/pull/340
GitHub-Related-Issue: https://github.com/joeycastillo/Sensor-Watch/issues/361
GitHub-Related-Issue: https://github.com/joeycastillo/Sensor-Watch/issues/359
Reference: https://ww1.microchip.com/downloads/aemDocuments/documents/MCU32/ProductDocuments/Errata/SAM-L22-Family-Silicon-Errata-and-Data-Sheet-Clarification-DS80000782.pdf
This commit is contained in:
Matheus Afonso Martins Moreira
2024-03-05 01:28:12 -03:00
10 changed files with 63 additions and 7 deletions

View File

@@ -22,6 +22,8 @@
* SOFTWARE.
*/
#include "hpl_systick_config.h"
#include "watch_extint.h"
// this warning only appears when you `make BOARD=OSO-SWAT-A1-02`. it's annoying,
@@ -158,14 +160,20 @@ void watch_enter_sleep_mode(void) {
// disable brownout detector interrupt, which could inadvertently wake us up.
SUPC->INTENCLR.bit.BOD33DET = 1;
// per Microchip datasheet clarification DS80000782,
// work around silicon erratum 1.8.4 by disabling the SysTick interrupt, which is
// enabled as part of driver init, before going to sleep.
SysTick->CTRL = SysTick->CTRL & ~(CONF_SYSTICK_TICKINT << SysTick_CTRL_TICKINT_Pos);
// disable all pins
_watch_disable_all_pins_except_rtc();
// enter standby (4); we basically hang out here until an interrupt wakes us.
sleep(4);
// and we awake! re-enable the brownout detector
// and we awake! re-enable the brownout detector and SysTick interrupt
SUPC->INTENSET.bit.BOD33DET = 1;
SysTick->CTRL = SysTick->CTRL | (CONF_SYSTICK_TICKINT << SysTick_CTRL_TICKINT_Pos);
// call app_setup so the app can re-enable everything we disabled.
app_setup();

View File

@@ -35,6 +35,12 @@ void _watch_init(void) {
// Use switching regulator for lower power consumption.
SUPC->VREG.bit.SEL = 1;
// per Microchip datasheet clarification DS80000782,
// work around silicon erratum 1.7.2, which causes the microcontroller to lock up on leaving standby:
// request that the voltage regulator run in standby, and also that it switch to PL0.
SUPC->VREG.bit.RUNSTDBY = 1;
SUPC->VREG.bit.STDBYPL0 = 1;
while(!SUPC->STATUS.bit.VREGRDY); // wait for voltage regulator to become ready
// check the battery voltage...
@@ -106,12 +112,21 @@ int getentropy(void *buf, size_t buflen) {
}
}
hri_trng_clear_CTRLA_ENABLE_bit(TRNG);
watch_disable_TRNG();
hri_mclk_clear_APBCMASK_TRNG_bit(MCLK);
return 0;
}
void watch_disable_TRNG() {
// per Microchip datasheet clarification DS80000782,
// silicon erratum 1.16.1 indicates that the TRNG may leave internal components powered after being disabled.
// the workaround is to disable the TRNG by clearing the control register, twice.
hri_trng_write_CTRLA_reg(TRNG, 0);
hri_trng_write_CTRLA_reg(TRNG, 0);
}
void _watch_enable_tcc(void) {
// clock TCC0 with the main clock (8 MHz) and enable the peripheral clock.
hri_gclk_write_PCHCTRL_reg(GCLK, TCC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK0_Val | GCLK_PCHCTRL_CHEN);