Use on STM32L432KC
Dependencies: LPC1114_WakeInterruptIn
Fork of WakeUp by
Revision 7:bb411115f814, committed 2014-07-23
- Comitter:
- Sissors
- Date:
- Wed Jul 23 19:54:52 2014 +0000
- Parent:
- 6:815bef56e136
- Child:
- 8:8d9a6ac0fba8
- Commit message:
- Added NUCLEO F030R8
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Device/WakeUp_KLxxZ.cpp Wed Jul 23 19:54:52 2014 +0000 @@ -0,0 +1,115 @@ +#if defined(TARGET_KLXX) || defined(TARGET_K20D5M) + +#include "WakeUp.h" +#include "us_ticker_api.h" + +FunctionPointer WakeUp::callback; +float WakeUp::cycles_per_ms = 1.0; + +static uint16_t remainder_count; +static uint32_t oldvector; +static uint8_t oldPSR; + +void restore(void); + +void WakeUp::set_ms(uint32_t ms) +{ + /* Clock the timer */ + SIM->SCGC5 |= 0x1u; + + //Check if it is running, in that case, store current values + remainder_count = 0; + if (NVIC_GetVector(LPTimer_IRQn) != (uint32_t)WakeUp::irq_handler) { + oldvector = NVIC_GetVector(LPTimer_IRQn); + oldPSR = LPTMR0->PSR; + + if (LPTMR0->CSR & LPTMR_CSR_TIE_MASK) { + //Write first to sync value + LPTMR0->CNR = 0; + uint16_t countval = LPTMR0->CNR; + if (countval < LPTMR0->CMR) + remainder_count = countval - LPTMR0->CMR; + } + } + + LPTMR0->CSR = 0; + + if (ms != 0) { + //Clock from the 1kHz LPO + LPTMR0->PSR = LPTMR_PSR_PCS(1); + + /* Set interrupt handler */ + NVIC_SetVector(LPTimer_IRQn, (uint32_t)WakeUp::irq_handler); + NVIC_EnableIRQ(LPTimer_IRQn); + + uint32_t counts = (uint32_t)((float)ms * cycles_per_ms); + + //If no prescaler is needed + if (counts <= 0xFFFF) + LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK; + else { //Otherwise increase prescaler until it fits + counts >>= 1; + uint32_t prescaler = 0; + while (counts > 0xFFFF) { + counts >>= 1; + prescaler++; + } + LPTMR0->PSR |= LPTMR_PSR_PRESCALE(prescaler); + } + LPTMR0->CMR = counts; + + LPTMR0->CSR = LPTMR_CSR_TIE_MASK; + LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; + } else { + restore(); + } + +} + + +void WakeUp::irq_handler(void) +{ + // write 1 to TCF to clear the LPT timer compare flag + LPTMR0->CSR |= LPTMR_CSR_TCF_MASK; + restore(); + callback.call(); +} + +void WakeUp::calibrate(void) +{ + wait_us(1); //Otherwise next wait might overwrite our settings + cycles_per_ms = 1.0; + set_ms(1100); + wait_ms(100); + + //Write first to sync value + LPTMR0->CNR = 0; + uint32_t ticks = LPTMR0->CNR; + cycles_per_ms = ticks / 100.0; + set_ms(0); +} + +void restore(void){ + /* Reset */ + LPTMR0->CSR = 0; + + /* Set interrupt handler */ + NVIC_SetVector(LPTimer_IRQn, oldvector); + NVIC_EnableIRQ(LPTimer_IRQn); + + /* Clock at (1)MHz -> (1)tick/us */ + LPTMR0->PSR = oldPSR; + + if (remainder_count) { + /* Set the compare register */ + LPTMR0->CMR = remainder_count; + + /* Enable interrupt */ + LPTMR0->CSR |= LPTMR_CSR_TIE_MASK; + + /* Start the timer */ + LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; + } +} + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Device/WakeUp_LPC11u24.cpp Wed Jul 23 19:54:52 2014 +0000 @@ -0,0 +1,63 @@ +/** +Due to lack of another option for the LPC11u24 the watchdog timer is used as wakeup source. +Since if the reset on watchdog event bit is set, I cannot remove it again, this means if you also got watchdog code running +the most likely result is that it just resets your board. +**/ + + +#ifdef TARGET_LPC11U24 + +#include "WakeUp.h" + +FunctionPointer WakeUp::callback; +float WakeUp::cycles_per_ms = 5.0; + +void WakeUp::set_ms(uint32_t ms) +{ + if (ms != 0) { + LPC_SYSCON->SYSAHBCLKCTRL |= 0x8000; + LPC_SYSCON->PDRUNCFG &= ~(1<<6); + LPC_SYSCON->PDSLEEPCFG &= ~(1<<6); + LPC_SYSCON->STARTERP1 |= 1<<12; + + //Set oscillator for 20kHz = 5kHz after divide by 4 in WDT + LPC_SYSCON->WDTOSCCTRL = 14 | (1<<5); + + LPC_WWDT->MOD = 1; //Enable WDT + LPC_WWDT->TC = (uint32_t)((float)ms * cycles_per_ms); + LPC_WWDT->CLKSEL = 1; //WDTOSC + LPC_WWDT->WARNINT = 0; + + NVIC_SetVector(WDT_IRQn, (uint32_t)WakeUp::irq_handler); + + //Feeeeeed me + LPC_WWDT->FEED = 0xAA; + LPC_WWDT->FEED = 0x55; + + NVIC_EnableIRQ(WDT_IRQn); + } else + NVIC_DisableIRQ(WDT_IRQn); + +} + +void WakeUp::irq_handler(void) +{ + LPC_WWDT->MOD = 1<<3; + callback.call(); +} + +void WakeUp::calibrate(void) +{ + cycles_per_ms = 5.0; + set_ms(1100); + wait_ms(10); //Give time to sync + uint32_t count1 = LPC_WWDT->TV; + wait_ms(100); + uint32_t count2 = LPC_WWDT->TV; + set_ms(0); + count1 = count1 - count2; + + cycles_per_ms = count1 / 100.0; +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Device/WakeUp_LPC812.cpp Wed Jul 23 19:54:52 2014 +0000 @@ -0,0 +1,74 @@ +#ifdef TARGET_LPC812 + +#include "WakeUp.h" + +FunctionPointer WakeUp::callback; +float WakeUp::cycles_per_ms = 10.0; + +void WakeUp::set_ms(uint32_t ms) +{ + //Enable clock to register interface: + LPC_SYSCON->SYSAHBCLKCTRL |= 1<<9; + + //Clear the counter: + LPC_WKT->CTRL |= 1<<2; + if (ms != 0) { + //Enable clock to register interface: + LPC_SYSCON->SYSAHBCLKCTRL |= 1<<9; + + //Set 10kHz timer as source, and just to be sure clear status bit + LPC_WKT->CTRL = 3; + + //Enable the 10kHz timer + LPC_PMU->DPDCTRL |= (1<<2) | (1<<3); + + //Set interrupts + NVIC_SetVector(WKT_IRQn, (uint32_t)WakeUp::irq_handler); + NVIC_EnableIRQ(WKT_IRQn); + + //Load the timer + LPC_WKT->COUNT = (uint32_t)((float)ms * cycles_per_ms); + + } else { + //Disable clock to register interface: + LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<9); + + //Disable the 10kHz timer + LPC_PMU->DPDCTRL &= ~((1<<2) | (1<<3)); + } +} + +void WakeUp::irq_handler(void) +{ + //Clear status + LPC_WKT->CTRL |= 2; + + //Disable clock to register interface: + LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<9); + + //Disable the 10kHz timer + LPC_PMU->DPDCTRL &= ~((1<<2) | (1<<3)); + + callback.call(); +} + +void WakeUp::calibrate(void) +{ + cycles_per_ms = 10.0; + set_ms(1100); + wait_ms(100); + + uint32_t prevread = LPC_WKT->COUNT; + uint32_t read = LPC_WKT->COUNT; + while( read != prevread) { + prevread = read; + read = LPC_WKT->COUNT; + } + + uint32_t ticks = 11000 - read; + + cycles_per_ms = ticks / 100.0; + set_ms(0); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Device/WakeUp_NUCLEO_F030.cpp Wed Jul 23 19:54:52 2014 +0000 @@ -0,0 +1,91 @@ +#ifdef TARGET_NUCLEO_F030R8 + +#include "WakeUp.h" +#include "rtc_api.h" +#include "stm32f0xx_rtc.h" + +FunctionPointer WakeUp::callback; + +void WakeUp::set_ms(uint32_t ms) +{ + if (!rtc_isenabled()) //Make sure RTC is running + rtc_init(); + + //Alarm must be disabled to change anything + PWR_BackupAccessCmd(ENABLE); + RTC_AlarmCmd(RTC_Alarm_A, DISABLE); + + if (ms == 0) { //Just disable alarm + PWR_BackupAccessCmd(DISABLE); + return; + } + + //RTC prescaler + calculate how many sub-seconds should be added + uint32_t prescaler = (RTC->PRER & 0x7FFF) + 1; + uint32_t subsecsadd = ((ms % 1000) * prescaler) / 1000; + + if ((ms < 1000) && (subsecsadd < 2)) + subsecsadd = 2; //At least 2 subsecs delay to be sure interrupt is called + + //Get current time + uint32_t subsecs = RTC->SSR; + time_t secs = rtc_read(); + + //Calculate alarm values + //Subseconds is countdown, so substract the 'added' sub-seconds and prevent underflow + if (subsecs < subsecsadd) { + subsecs += prescaler; + secs++; + } + subsecs -= subsecsadd; + + //Set seconds correctly + secs += ms / 1000; + struct tm *timeinfo = localtime(&secs); + + RTC_AlarmTypeDef alarmStruct; + alarmStruct.RTC_AlarmTime.RTC_Hours = timeinfo->tm_hour; + alarmStruct.RTC_AlarmTime.RTC_Minutes = timeinfo->tm_min; + alarmStruct.RTC_AlarmTime.RTC_Seconds = timeinfo->tm_sec; + alarmStruct.RTC_AlarmTime.RTC_H12 = RTC_HourFormat_24; + alarmStruct.RTC_AlarmMask = RTC_AlarmMask_None; + alarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date; + alarmStruct.RTC_AlarmDateWeekDay = timeinfo->tm_mday; + + //Enable EXTI interrupt of the RTC + EXTI_InitTypeDef extiStruct; + extiStruct.EXTI_Line = EXTI_Line17; + extiStruct.EXTI_Mode = EXTI_Mode_Interrupt; + extiStruct.EXTI_Trigger = EXTI_Trigger_Rising; + extiStruct.EXTI_LineCmd = ENABLE; + + //Enable RTC interrupt + RTC_AlarmSubSecondConfig(RTC_Alarm_A, subsecs, RTC_AlarmSubSecondMask_None); + RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &alarmStruct); + RTC_AlarmCmd(RTC_Alarm_A, ENABLE); + RTC_ITConfig(RTC_IT_ALRA, ENABLE); + PWR_BackupAccessCmd(DISABLE); + + //Enable everything else + EXTI_Init(&extiStruct); + NVIC_SetVector(RTC_IRQn, (uint32_t)WakeUp::irq_handler); + NVIC_EnableIRQ(RTC_IRQn); +} + + +void WakeUp::irq_handler(void) +{ + //Clear RTC + EXTI interrupt flags + PWR_BackupAccessCmd(ENABLE); + RTC_ClearFlag(RTC_FLAG_ALRAF); + EXTI_ClearFlag(EXTI_Line17); + PWR_BackupAccessCmd(DISABLE); + callback.call(); +} + +void WakeUp::calibrate(void) +{ + //RTC, we assume it is accurate enough without calibration +} + +#endif
--- a/WakeUp_KLxxZ.cpp Sat Jul 12 19:17:51 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -#if defined(TARGET_KLXX) || defined(TARGET_K20D50M) - -#include "WakeUp.h" -#include "us_ticker_api.h" - -FunctionPointer WakeUp::callback; -float WakeUp::cycles_per_ms = 1.0; - -static uint16_t remainder_count; -static uint32_t oldvector; -static uint8_t oldPSR; - -void restore(void); - -void WakeUp::set_ms(uint32_t ms) -{ - /* Clock the timer */ - SIM->SCGC5 |= 0x1u; - - //Check if it is running, in that case, store current values - remainder_count = 0; - if (NVIC_GetVector(LPTimer_IRQn) != (uint32_t)WakeUp::irq_handler) { - oldvector = NVIC_GetVector(LPTimer_IRQn); - oldPSR = LPTMR0->PSR; - - if (LPTMR0->CSR & LPTMR_CSR_TIE_MASK) { - //Write first to sync value - LPTMR0->CNR = 0; - uint16_t countval = LPTMR0->CNR; - if (countval < LPTMR0->CMR) - remainder_count = countval - LPTMR0->CMR; - } - } - - LPTMR0->CSR = 0; - - if (ms != 0) { - //Clock from the 1kHz LPO - LPTMR0->PSR = LPTMR_PSR_PCS(1); - - /* Set interrupt handler */ - NVIC_SetVector(LPTimer_IRQn, (uint32_t)WakeUp::irq_handler); - NVIC_EnableIRQ(LPTimer_IRQn); - - uint32_t counts = (uint32_t)((float)ms * cycles_per_ms); - - //If no prescaler is needed - if (counts <= 0xFFFF) - LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK; - else { //Otherwise increase prescaler until it fits - counts >>= 1; - uint32_t prescaler = 0; - while (counts > 0xFFFF) { - counts >>= 1; - prescaler++; - } - LPTMR0->PSR |= LPTMR_PSR_PRESCALE(prescaler); - } - LPTMR0->CMR = counts; - - LPTMR0->CSR = LPTMR_CSR_TIE_MASK; - LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; - } else { - restore(); - } - -} - - -void WakeUp::irq_handler(void) -{ - // write 1 to TCF to clear the LPT timer compare flag - LPTMR0->CSR |= LPTMR_CSR_TCF_MASK; - restore(); - callback.call(); -} - -void WakeUp::calibrate(void) -{ - wait_us(1); //Otherwise next wait might overwrite our settings - cycles_per_ms = 1.0; - set_ms(1100); - wait_ms(100); - - //Write first to sync value - LPTMR0->CNR = 0; - uint32_t ticks = LPTMR0->CNR; - cycles_per_ms = ticks / 100.0; - set_ms(0); -} - -void restore(void){ - /* Reset */ - LPTMR0->CSR = 0; - - /* Set interrupt handler */ - NVIC_SetVector(LPTimer_IRQn, oldvector); - NVIC_EnableIRQ(LPTimer_IRQn); - - /* Clock at (1)MHz -> (1)tick/us */ - LPTMR0->PSR = oldPSR; - - if (remainder_count) { - /* Set the compare register */ - LPTMR0->CMR = remainder_count; - - /* Enable interrupt */ - LPTMR0->CSR |= LPTMR_CSR_TIE_MASK; - - /* Start the timer */ - LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; - } -} - - - - - - -#endif \ No newline at end of file
--- a/WakeUp_LPC11u24.cpp Sat Jul 12 19:17:51 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/** -Due to lack of another option for the LPC11u24 the watchdog timer is used as wakeup source. -Since if the reset on watchdog event bit is set, I cannot remove it again, this means if you also got watchdog code running -the most likely result is that it just resets your board. -**/ - - -#ifdef TARGET_LPC11U24 - -#include "WakeUp.h" - -FunctionPointer WakeUp::callback; -float WakeUp::cycles_per_ms = 5.0; - -void WakeUp::set_ms(uint32_t ms) -{ - if (ms != 0) { - LPC_SYSCON->SYSAHBCLKCTRL |= 0x8000; - LPC_SYSCON->PDRUNCFG &= ~(1<<6); - LPC_SYSCON->PDSLEEPCFG &= ~(1<<6); - LPC_SYSCON->STARTERP1 |= 1<<12; - - //Set oscillator for 20kHz = 5kHz after divide by 4 in WDT - LPC_SYSCON->WDTOSCCTRL = 14 | (1<<5); - - LPC_WWDT->MOD = 1; //Enable WDT - LPC_WWDT->TC = (uint32_t)((float)ms * cycles_per_ms); - LPC_WWDT->CLKSEL = 1; //WDTOSC - LPC_WWDT->WARNINT = 0; - - NVIC_SetVector(WDT_IRQn, (uint32_t)WakeUp::irq_handler); - - //Feeeeeed me - LPC_WWDT->FEED = 0xAA; - LPC_WWDT->FEED = 0x55; - - NVIC_EnableIRQ(WDT_IRQn); - } else - NVIC_DisableIRQ(WDT_IRQn); - -} - -void WakeUp::irq_handler(void) -{ - LPC_WWDT->MOD = 1<<3; - callback.call(); -} - -void WakeUp::calibrate(void) -{ - cycles_per_ms = 5.0; - set_ms(1100); - wait_ms(10); //Give time to sync - uint32_t count1 = LPC_WWDT->TV; - wait_ms(100); - uint32_t count2 = LPC_WWDT->TV; - set_ms(0); - count1 = count1 - count2; - - cycles_per_ms = count1 / 100.0; -} - -#endif
--- a/WakeUp_LPC812.cpp Sat Jul 12 19:17:51 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -#ifdef TARGET_LPC812 - -#include "WakeUp.h" - -FunctionPointer WakeUp::callback; -float WakeUp::cycles_per_ms = 10.0; - -void WakeUp::set_ms(uint32_t ms) -{ - //Enable clock to register interface: - LPC_SYSCON->SYSAHBCLKCTRL |= 1<<9; - - //Clear the counter: - LPC_WKT->CTRL |= 1<<2; - if (ms != 0) { - //Enable clock to register interface: - LPC_SYSCON->SYSAHBCLKCTRL |= 1<<9; - - //Set 10kHz timer as source, and just to be sure clear status bit - LPC_WKT->CTRL = 3; - - //Enable the 10kHz timer - LPC_PMU->DPDCTRL |= (1<<2) | (1<<3); - - //Set interrupts - NVIC_SetVector(WKT_IRQn, (uint32_t)WakeUp::irq_handler); - NVIC_EnableIRQ(WKT_IRQn); - - //Load the timer - LPC_WKT->COUNT = (uint32_t)((float)ms * cycles_per_ms); - - } else { - //Disable clock to register interface: - LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<9); - - //Disable the 10kHz timer - LPC_PMU->DPDCTRL &= ~((1<<2) | (1<<3)); - } -} - -void WakeUp::irq_handler(void) -{ - //Clear status - LPC_WKT->CTRL |= 2; - - //Disable clock to register interface: - LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<9); - - //Disable the 10kHz timer - LPC_PMU->DPDCTRL &= ~((1<<2) | (1<<3)); - - callback.call(); -} - -void WakeUp::calibrate(void) -{ - cycles_per_ms = 10.0; - set_ms(1100); - wait_ms(100); - - uint32_t prevread = LPC_WKT->COUNT; - uint32_t read = LPC_WKT->COUNT; - while( read != prevread) { - prevread = read; - read = LPC_WKT->COUNT; - } - - uint32_t ticks = 11000 - read; - - cycles_per_ms = ticks / 100.0; - set_ms(0); -} - -#endif