Files
timely-reference/firmware/Bsp/Drivers/LowPower.cpp
2020-07-05 17:27:22 -07:00

121 lines
3.2 KiB
C++

/*
* Copyright (C) 2019 Max Regan
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "Bsp/SystemTime.h"
#include "Bsp/Drivers/LowPower.h"
#include "Bsp/macros.h"
#include "Mcu.h"
uint32_t wakeups = 0;
namespace BSP {
using BSP::ReturnCode;
GpioPin *LowPower::m_timing_pin = nullptr;
ReturnCode LowPower::init()
{
m_timing_pin = nullptr;
return ReturnCode::OK;
}
ReturnCode LowPower::init(GpioPin &timing_pin)
{
m_timing_pin = &timing_pin;
m_timing_pin->write(0);
return ReturnCode::OK;
}
ReturnCode LowPower::enable_debug()
{
/* Enable Clocks */
// FIXME for all boards
// SET(RCC->APB2ENR, RCC_APB2ENR_DBGEN);
// SET(RCC->APB2SMENR, RCC_APB2SMENR_DBGSMEN);
SET(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
SET(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
SET(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
return ReturnCode::OK;
}
ReturnCode LowPower::disable_debug()
{
CLR(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
CLR(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
CLR(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
#if defined(STM32L0XX)
CLR(RCC->APB2SMENR, RCC_APB2SMENR_DBGSMEN);
#elif defined(STM32L4XX)
#else
#error "Unsupported device type"
#endif
return ReturnCode::OK;
}
ReturnCode LowPower::sleep()
{
// TODO: unimplemented
return ReturnCode::FAIL;
}
ReturnCode LowPower::stop()
{
#if defined(STM32L0XX)
SET(PWR->CR, PWR_CR_CWUF); // clear wakeup flag
while(PWR->CSR & PWR_CSR_WUF) {};
// Enter stop mode when the CPU enters deepsleep
CLR(PWR->CR, PWR_CR_PDDS);
#elif defined(STM32L4XX)
SET(PWR->SCR, PWR_SCR_CWUF1); // clear wakeup flag
while(PWR->SR1 & PWR_SR1_WUF1) {};
// Enter stop mode 1 when the CPU enters deepsleep
SET_TO(PWR->CR1, PWR_CR1_LPMS, 1 << PWR_CR1_LPMS_Pos);
#else
#error "Unsupported device type"
#endif
CLR(RCC->CFGR, RCC_CFGR_STOPWUCK); // MSI oscillator is wake-up from stop clock
SET(SCB->SCR, SCB_SCR_SLEEPDEEP_Msk); // low-power mode = stop mode
if (m_timing_pin != nullptr) {
m_timing_pin->write(1);
__WFI(); // enter low-power mode (Wake from interrupt)
m_timing_pin->write(0);
} else{
__WFI();
}
wakeups++;
return ReturnCode::OK;
}
}