Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
Fork of Hibernus by
Revision 0:f9a13d4b41f3, committed 2017-09-08
- Comitter:
- BogdanL
- Date:
- Fri Sep 08 18:01:22 2017 +0000
- Commit message:
- First Version of Hibernus Library;
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/Driver_KL05Z.cpp Fri Sep 08 18:01:22 2017 +0000
@@ -0,0 +1,114 @@
+#include "config.h"
+#ifdef KL05Z
+#include "Driver_KL05Z.h"
+#include "hibernus.h"
+Serial pr(USBTX, USBRX);
+volatile unsigned int dummyread1; // Variable used for serialization
+
+//inerrupt triggered by comparator whenever the power drops under the treshold value
+extern "C" void CMP0_IRQHandler() //To make sure the compiler sees handler, need to declare it as extern (https://developer.mbed.org/forum/mbed/topic/419/?page=1#comment-2126)
+{
+ CMP0->SCR |= CMP_SCR_CFF_MASK | CMP_SCR_CFR_MASK; // Clear CMP0 flags
+ dummyread1 = CMP0->SCR; // Read back for serialization
+
+ //call hibernate procedure directly with the three parameters (don't store them in a variable and then call the method with them,
+ //the store procedure changes the stackpointer and the program counter)
+ // pram1 = StackPointer = SP, param2 = LinkRegister = LR, param3 = ProgramCounter = PC
+ // call hibernate(param1, param2, param3) then the voltage drops under the low(hibernate) treshold
+ hibernate((_SP+0x28),*((unsigned int*)(_SP+0x1C)),*((unsigned int*)(_SP+0x20)));
+
+}
+
+extern "C" void LLW_IRQHandler(){ //interrupt triggered to wake up the board from sleep mode
+
+ CMP0->SCR |= CMP_SCR_CFF_MASK | CMP_SCR_CFR_MASK; // Clear CMP0 flags
+ dummyread1 = CMP0->SCR; // Read back for serialization
+ NVIC_ClearPendingIRQ(CMP0_IRQn); // Clear pending CMP0 interrupt so that the CMP_IRQ is not entered
+
+ recovery_no_power_loss(); //check if you are recovering after no power loss, and if so, configure VH interrupt
+}
+
+void Comparator_Setup(){
+
+ NVIC_SetPriority(CMP0_IRQn, 1); // Lower the CMP0 interrupt priority from 0 to 1 (smaller number = higher priority)
+ NVIC_EnableIRQ(CMP0_IRQn); // Enable CMP0 interrupts in NVIC
+
+ SIM->SCGC4 |= SIM_SCGC4_CMP_MASK; // Enable comparator module clock
+ LLWU->ME |= LLWU_ME_WUME1_MASK; // Enable CMP0 as a LLWU source
+ PMC->REGSC |= PMC_REGSC_BGEN_MASK | // Allow bangap buffer in low power operation
+ PMC_REGSC_BGBE_MASK; // Enable bandgap buffer for +1V reference (CMP0_IN6)
+
+ // Comparator in sampled, filtered mode 4B
+ CMP0->CR0 = 0x22; // Hysteresis level 2 (20mV) and 2 consecutive filter samples must agree
+ CMP0->CR1 = 0x00; // Low-speed compare, non-inverted output, use filtered output and disable comparator output pin PTA2
+ CMP0->FPR = 0x01; // Filter sample period = 1 bus clock cycle
+ CMP0->SCR = 0x06; // Disable all interrupts and clear flags
+ CMP0->DACCR = 0x40; // Disable DAC, Vdd is 6-bit reference, threshold set to zero
+ CMP0->MUXCR = 0x3E; // CMP0_IN7 (DAC) to V+ channel and CMP0_IN6 (+1V bandgap) to V- 3E
+}
+
+void Enter_LLS(){
+
+ Comparator_Setup();
+ CMP0->DACCR = 0xDA; // Enable DAC, Vdd is 6-bit reference, threshold set to P3V3 = +2.37V (V_R)
+ CMP0->SCR = 0x16; // Enable rising edge interrupt and clear flags
+ CMP0->CR1 |= CMP_CR1_EN_MASK; // Enable comparator module
+
+ NVIC_EnableIRQ(LLW_IRQn); // Enable LLW interrupts in NVIC
+ MCG->C6 &= ~(MCG_C6_CME_MASK); // DIsable all clock monitors
+ SCB->SCR = 1<<SCB_SCR_SLEEPDEEP_Pos; // Set the SLEEPDEEP bit for stop mode
+
+ SMC->PMPROT = SMC_PMPROT_ALLS_MASK; // Allow LLS power modes
+ SMC->PMCTRL &= ~(SMC_PMCTRL_STOPM_MASK); // Serialisation
+ SMC->PMCTRL = SMC_PMCTRL_STOPM(0x3); // Select LLS as desired power mode
+ dummyread1 = SMC->PMCTRL; // Read back for serialisation
+
+ __WFI(); // Stop executing instructions and enter LLS (wait for interrupt)
+}
+
+void configure_VH_comparator_interrupt(){
+ Comparator_Setup();
+ CMP0->DACCR = 0xDC; // Enable DAC, Vdd is 6-bit reference, threshold set to P3V3 = +2.21V (V_H)
+ CMP0->SCR = 0x0E; // Enable falling edge interrupt and clear flags
+ CMP0->CR1 |= CMP_CR1_EN_MASK; // Enable comparator module
+}
+
+void configure_VR_comparator_interrupt(){
+ CMP0->DACCR = 0xDA; // Enable DAC, Vdd is 6-bit reference, threshold set to P3V3 = +2.37V (V_R)
+ CMP0->SCR = 0x16; // Enable all interrupts and clear flags
+ CMP0->CR1 |= CMP_CR1_EN_MASK; // Enable comparator module
+}
+
+void setFlag(volatile unsigned int* add){
+ const unsigned int set = Flag_set;
+ program_flash(*add,(char*)&set,4); //if the flags are stored in flash, use this line
+}
+
+bool isFlagSet(volatile unsigned int* add){
+ if( *(unsigned int *)(*add) == Flag_set) return true;
+ return false;
+}
+
+void erase_flags_memory(){
+ if(!SaveFlagsInFlash) { //if the flags are stored in RAM, their value have to be clanged to the "erased" value ("Flag_erase")
+ *getFlag_1() = Flag_erase;
+ *getFlag_2() = Flag_erase;
+ *getFlag_3() = Flag_erase;
+ *getFlag_4() = Flag_erase;
+ }else{ //if the flags are stored in Flash, their secvtor have to be erased
+ erase_sector(Flash_Flags_Sector_Start);
+ }
+}
+//erase the flash memory needed to save the whole RAM content
+void erase_flash_secors_for_RAM(){
+ int i;
+ for(i = 2; i<= 2+ramToFlash_sectors_number; i++) //start the erase from the second last block, the first is used for flags
+ erase_sector(flash_end-i*sector_Size);
+}
+
+void copyRamToFlash(){
+ // Erase flash sectors o save the RAM content
+ erase_flash_secors_for_RAM();
+ program_flash(flash_ramSection_start, (char*) RAM_Start, RAM_Size); // Copy all the RAM to flash
+}
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/Driver_KL05Z.h Fri Sep 08 18:01:22 2017 +0000
@@ -0,0 +1,99 @@
+#ifndef CONFIG_H_
+#define CONFIG_H_
+#ifdef KL05Z
+#include "mbed.h"
+#include "FreescaleIAP.h"
+
+#define HasInternalComparator 1 //Set on 1 if there is an internal comparator 0 otherwise
+#define SaveFlagsInFlash 1 //set on 1 if there is enough Flash memory available for the flags to have their own flash sector, 0 otherwise
+ //if there is not enough flash memory, the flags will be saved in RAM memory
+
+// RAM addresses split in 1 KB sectors
+#define RAM_Start 0x1FFFFC00
+#define FLASH_Start 0x00000000
+#define RAM_Size 4096
+#define flash_Size flash_size() //32K flash
+#define sector_Size SECTOR_SIZE //4K sector size
+#define Flash_Flags_Sector_Start (flash_end -1*sector_Size)
+
+#define No_Of_4B_Peripheral_Reg 18
+#define No_Of_1B_Peripheral_Reg 8
+
+const unsigned int REG_Addresses_4B[83] = // Constant peripheral register addresses which are 4 bytes in size
+ {
+ (unsigned int)&FPTA->PDOR,(unsigned int)&FPTA->PDDR,(unsigned int)&FPTB->PDOR,(unsigned int)&FPTB->PDDR,
+ //0x4000F000, 0x4000F014, 0x4000F040, 0x4000F054, // GPIO controller aliased to ox400FF000
+ (unsigned int)&SIM->SOPT1,(unsigned int)&SIM->SOPT1CFG,(unsigned int)&SIM->SOPT2,(unsigned int)&SIM->SOPT4,
+ (unsigned int)&SIM->SOPT5,(unsigned int)&SIM->SOPT7,(unsigned int)&SIM->SCGC4,(unsigned int)&SIM->SCGC5,
+ (unsigned int)&SIM->SCGC6,(unsigned int)&SIM->SCGC7,(unsigned int)&SIM->CLKDIV1,(unsigned int)&SIM->FCFG1,
+ (unsigned int)&SIM->COPC,
+ //0x40047000, 0x40047004, 0x40048004, 0x4004800C, 0x40048010, 0x40048018, 0x40048034, 0x40048038, 0x4004803C, 0x40048040,
+ //0x40048044, 0x4004804C, 0x40048100, // SIM
+ (unsigned int)&PORTA->PCR[0],(unsigned int)&PORTA->PCR[1],(unsigned int)&PORTA->PCR[2],(unsigned int)&PORTA->PCR[3],
+ (unsigned int)&PORTA->PCR[4],(unsigned int)&PORTA->PCR[5],(unsigned int)&PORTA->PCR[6],(unsigned int)&PORTA->PCR[7],
+ (unsigned int)&PORTA->PCR[8],(unsigned int)&PORTA->PCR[9],(unsigned int)&PORTA->PCR[10],(unsigned int)&PORTA->PCR[11],
+ (unsigned int)&PORTA->PCR[12],(unsigned int)&PORTA->PCR[13],(unsigned int)&PORTA->PCR[14],(unsigned int)&PORTA->PCR[15],
+ (unsigned int)&PORTA->PCR[16],(unsigned int)&PORTA->PCR[17],(unsigned int)&PORTA->PCR[18],(unsigned int)&PORTA->PCR[19],
+ (unsigned int)&PORTA->PCR[20],(unsigned int)&PORTA->PCR[21],(unsigned int)&PORTA->PCR[22],(unsigned int)&PORTA->PCR[23],
+ (unsigned int)&PORTA->PCR[24],(unsigned int)&PORTA->PCR[25],(unsigned int)&PORTA->PCR[26],(unsigned int)&PORTA->PCR[27],
+ (unsigned int)&PORTA->PCR[28],(unsigned int)&PORTA->PCR[29],(unsigned int)&PORTA->PCR[30],(unsigned int)&PORTA->PCR[31],
+ //0x40049000, 0x40049004, 0x40049008, 0x4004900C, 0x40049010, 0x40049014, 0x40049018, 0x4004901C, 0x40049020, 0x40049024,
+ //0x40049028, 0x4004902C, 0x40049030, 0x40049034, 0x40049038, 0x4004903C, 0x40049040, 0x40049044, 0x40049048, 0x4004904C,
+ //0x40049050, 0x40049054, 0x40049058, 0x4004905C, 0x40049060, 0x40049064, 0x40049068, 0x4004906C, 0x40049070, 0x40049074,
+ //0x40049078, 0x4004907C, // Port A multiplexing control
+ (unsigned int)&PORTB->PCR[0],(unsigned int)&PORTB->PCR[1],(unsigned int)&PORTB->PCR[2],(unsigned int)&PORTB->PCR[3],
+ (unsigned int)&PORTB->PCR[4],(unsigned int)&PORTB->PCR[5],(unsigned int)&PORTB->PCR[6],(unsigned int)&PORTB->PCR[7],
+ (unsigned int)&PORTB->PCR[8],(unsigned int)&PORTB->PCR[9],(unsigned int)&PORTB->PCR[10],(unsigned int)&PORTB->PCR[11],
+ (unsigned int)&PORTB->PCR[12],(unsigned int)&PORTB->PCR[13],(unsigned int)&PORTB->PCR[14],(unsigned int)&PORTB->PCR[15],
+ (unsigned int)&PORTB->PCR[16],(unsigned int)&PORTB->PCR[17],(unsigned int)&PORTB->PCR[18],(unsigned int)&PORTB->PCR[19],
+ (unsigned int)&PORTB->PCR[20],(unsigned int)&PORTB->PCR[21],(unsigned int)&PORTB->PCR[22],(unsigned int)&PORTB->PCR[23],
+ (unsigned int)&PORTB->PCR[24],(unsigned int)&PORTB->PCR[25],(unsigned int)&PORTB->PCR[26],(unsigned int)&PORTB->PCR[27],
+ (unsigned int)&PORTB->PCR[28],(unsigned int)&PORTB->PCR[29],(unsigned int)&PORTB->PCR[30],(unsigned int)&PORTB->PCR[31],
+ //0x4004A000, 0x4004A004, 0x4004A008, 0x4004A00C, 0x4004A010, 0x4004A014, 0x4004A018, 0x4004A01C, 0x4004A020, 0x4004A024,
+ //0x4004A028, 0x4004A02C, 0x4004A030, 0x4004A034, 0x4004A038, 0x4004A03C, 0x4004A040, 0x4004A044, 0x4004A048, 0x4004A04C,
+ //0x4004A050, 0x4004A054, 0x4004A058, 0x4004A05C, 0x4004A060, 0x4004A064, 0x4004A068, 0x4004A06C, 0x4004A070, 0x4004A074,
+ //0x4004A078, 0x4004A07C, // Port B multiplexing control
+ (unsigned int)&MCM->PLACR,(unsigned int)&MCM->CPO
+ //0xF000300C, 0xF0003040 // MCM
+ };
+
+const unsigned int REG_Addresses_1B[30] = // Constant peripheral register addresses which are 1 byte in size
+ {
+ (unsigned int)&MCG->C1,(unsigned int)&MCG->C2,(unsigned int)&MCG->C3,(unsigned int)&MCG->C4,
+ (unsigned int)&MCG->C6,(unsigned int)&MCG->SC,(unsigned int)&MCG->ATCVH,(unsigned int)&MCG->ATCVL,
+ //0x40064000, 0x40064001, 0x40064002, 0x40064003, 0x40064005, 0x40064008, 0x4006400A, 0x4006400B, // MCG
+ (unsigned int)&OSC0->CR,
+ //0x40065000, // Oscillator
+ (unsigned int)&UART0->BDH,(unsigned int)&UART0->BDL,(unsigned int)&UART0->C1,(unsigned int)&UART0->C2,
+ (unsigned int)&UART0->S1,(unsigned int)&UART0->S2,(unsigned int)&UART0->C3,(unsigned int)&UART0->D,
+ (unsigned int)&UART0->MA1,(unsigned int)&UART0->MA2,(unsigned int)&UART0->C4,(unsigned int)&UART0->C5,
+ //0x4006A000, 0x4006A001, 0x4006A002, 0x4006A003, 0x4006A004, 0x4006A005, 0x4006A006, 0x4006A007, 0x4006A008, 0x4006A009,
+ //0x4006A00A, 0x4006A00B, // UART0
+ (unsigned int)&PMC->LVDSC1,(unsigned int)&PMC->LVDSC2,(unsigned int)&PMC->REGSC,
+ //0x4007D000, 0x4007D001, 0x4007D002, // PMC
+ (unsigned int)&SMC->PMPROT,(unsigned int)&SMC->PMCTRL,(unsigned int)&SMC->STOPCTRL,(unsigned int)&SMC->PMSTAT,
+ //0x4007E000, 0x4007E001, 0x4007E002, 0x4007E003, // SMC
+ (unsigned int)&RCM->RPFC,(unsigned int)&RCM->RPFW
+ //0x4007F004, 0x4007F005 // RCM
+ };
+
+#if HasInternalComparator == 1
+ void configure_VR_comparator_interrupt(void);
+ void configure_VH_comparator_interrupt(void);
+ void Comparator_Setup(void);
+#else
+ extern "C" void FLEX_INT0_IRQHandler(void);
+ extern "C" void FLEX_INT1_IRQHandler(void);
+ void configure_VH_gpio_interrupt(void);
+ void configure_VR_gpio_interrupt(void);
+#endif
+
+void erase_flags_memory(void);
+void restore_flags(void);
+void Enter_LLS(void);
+void setFlag(volatile unsigned int*);
+bool isFlagSet(volatile unsigned int*);
+void copyRamToFlash(void);
+
+#endif
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/Driver_LPC11U24.cpp Fri Sep 08 18:01:22 2017 +0000
@@ -0,0 +1,151 @@
+/** Hibernus Library
+ * University of Southampton 2017
+ *
+ * Open-source liberary that enable any of your Mbed project work with transient enegy sources.
+ * In order to use this library include the "hibernus.h" header file, and use the "Hibernus()" method at the beginning of you main funtion.
+ * For more details and example see the "main.cpp" exampe file, and the attached documnetation
+ *
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+#ifdef LPC11U24
+#include "Driver_LPC11U24.h"
+#include "hibernus.h"
+#include "config.h"
+
+IAP iap;
+Serial pc1(USBTX, USBRX);
+
+void Enter_LLS(){
+ configure_VR_gpio_interrupt();
+
+ LPC_PMU->PCON |= 0x1;
+ LPC_SYSCON->PINTSEL[0] = 0x02; //configure pin P0_2 as interupt source
+ LPC_SYSCON->PDRUNCFG &= ~(1<<1);
+ LPC_SYSCON->STARTERP0 |= (1<<0); //Config chanel as wake up interrupt
+ LPC_SYSCON->PDAWAKECFG &= ~((1<<0)|(1<<1)|(1<<2)|(1<<5)|(1<<7)); //wake up all needed modules after recovering from deepslep mode
+ NVIC_SetPriority(FLEX_INT0_IRQn,0);
+ NVIC_EnableIRQ(FLEX_INT0_IRQn);
+ NVIC_SetPriority(FLEX_INT0_IRQn,0);
+
+ //Go to deep Sleep mode ---->
+ SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; //choose Deep Sleep as power mode
+ __WFI(); // Stop executing instructions and enter Deep Sleep mode
+}
+
+//if there is no internal Coomparator define 2 GPIO interrupts to wake up and sleep
+
+void configure_VR_gpio_interrupt(){
+ LPC_GPIO->DIR[0] |= 1<<2; //set pin P0_2 as input //generate interrupt for VR
+
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16);
+ LPC_IOCON->PIO0_2 = (0x0|(0x2<<3)); //enable pullup
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1<<19); //System enable peripheral clock
+ LPC_SYSCON->PINTSEL[0] = 0x2; //configure interrupt chanel for the GPIO pin is syscon block
+
+ LPC_GPIO_PIN_INT->ISEL &= ~(1<<0); //set the interrupt mode for the pin0 to be Level Sensitive
+ LPC_GPIO_PIN_INT->IENF |= (1<<0); //enable the level sensitive interrupt on pin P0_2
+
+ LPC_SYSCON->STARTERP0 |= (1<<0); //config chanel as wake up interrupt is Syscon block
+
+ __enable_irq();
+ NVIC_EnableIRQ(FLEX_INT0_IRQn);
+ NVIC_SetPriority(FLEX_INT0_IRQn,0); //Set a higher prioroty for wake up interrupt, to be able to interrupt the sleep interrupt
+}
+
+void configure_VH_gpio_interrupt(){
+ LPC_GPIO->DIR[0] |= 1<<8; //set pin P0_8 as input //generate interrupt for VH
+
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16);
+ LPC_IOCON->PIO0_8 = (0x0|(0x2<<3)); //choose first pin function and enable pullup
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1<<19); //System enable peripheral clock
+ LPC_SYSCON->PINTSEL[1] = (uint32_t)8; //configure interrupt chanel for the GPIO pin is syscon block
+
+ LPC_GPIO_PIN_INT->ISEL &= ~(1<<1); //set the interrupt mode for the pin1 to be Level Sensitive
+ LPC_GPIO_PIN_INT->IENF |= (1<<1); //enable the level sensitive interrupt on pin P0_8
+
+ __enable_irq();
+ NVIC_EnableIRQ(FLEX_INT1_IRQn);
+ NVIC_SetPriority(FLEX_INT1_IRQn,2); //Set a lower priority for the sleep interrupt, in order to be possible for the wake up interrupt to interrupt it
+}
+
+//the interrupt triggered by the GPIO/INternal Comparator where the snapshot is saved
+extern "C" void FLEX_INT1_IRQHandler(){ //To make sure the compiler sees handler, need to declare it as extern (https://developer.mbed.org/forum/mbed/topic/419/?page=1#comment-2126)
+ pc1.printf(" ",isFlagSet(getFlag_1()),isFlagSet(getFlag_2()),isFlagSet(getFlag_3()),isFlagSet(getFlag_4()));
+
+ hibernate((_SP+0x40),*(unsigned int*)(_SP+0x34),*(unsigned int*)(_SP+0x38));
+
+ //clear interupt status register
+ LPC_GPIO_PIN_INT->IST |=((1<<0)|(1<<1));
+ //delete any sleep interupts that came during the sleep
+ NVIC_ClearPendingIRQ(FLEX_INT1_IRQn);
+}
+
+//ISR for wakeing up the core and seting the interrupt for Hibernate procedure
+extern "C" void FLEX_INT0_IRQHandler(){ //To make sure the compiler sees handler, need to declare it as extern (https://developer.mbed.org/forum/mbed/topic/419/?page=1#comment-2126)
+ NVIC_ClearPendingIRQ(FLEX_INT0_IRQn);
+
+ recovery_no_power_loss(); //check if you are recovering after no power loss, and if so, configure VH interrupt
+
+ //clear interupt status register
+ LPC_GPIO_PIN_INT->IST |= (1<<0);
+}
+
+//used to restore the flags values from Flash to RAM
+void restore_flags(){
+ if(!SaveFlagsInFlash){
+ *getFlag_1() = *(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset);
+ *getFlag_2() = *(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset+0x4);
+ *getFlag_3() = *(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset+0x8);
+ *getFlag_4() = *(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset+0xC);
+ }
+}
+
+//mark a flag as "SET"
+void setFlag(volatile unsigned int* add){
+ #if SaveFlagsInFlash == 1
+ const unsigned int set = Flag_set;
+ program_flash(*add,(char*)&set,4); //if the flags are stored in flash, use this line
+ #else
+ *add = Flag_set;
+ #endif
+
+}
+
+//check if a flag is SET or CLEAR
+bool isFlagSet(volatile unsigned int* add){
+ #if SaveFlagsInFlash == 1
+ if( *(unsigned int *)(*add) == Flag_set) return true;
+ return false;
+ #else
+ if(*add == Flag_set ) return true;
+ return false;
+ #endif
+}
+
+//Clear the memory area where the flags are saved
+void erase_flags_memory(){
+ #if SaveFlagsInFlash == 0 //if the flags are stored in RAM, their value have to be clanged to the "erased" value ("Flag_erase")
+ *getFlag_1() = Flag_erase;
+ *getFlag_2() = Flag_erase;
+ *getFlag_3() = Flag_erase;
+ *getFlag_4() = Flag_erase;
+ #else //if the flags are stored in Flash, their secvtor have to be erased
+ erase_sector(Flash_Flags_Sector_Start);
+ #endif
+}
+
+//copy the whole content of RAM into the flash
+void copyRamToFlash(){
+ // Erase flash sectors o save the RAM content
+ int g3=iap.prepare(6,7);
+ int g4=iap.erase(6,7);
+
+ // Copy all the RAM to flash
+ int g0 = iap.prepare(6,7);
+ int g1=iap.write((char*)RAM_Start,(char*)flash_ramSection_start,RAM_Size/2);
+ g1+=iap.write((char*)RAM_Start+(RAM_Size/2),(char*)flash_ramSection_start+(RAM_Size/2),(RAM_Size/2));
+}
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/Driver_LPC11U24.h Fri Sep 08 18:01:22 2017 +0000
@@ -0,0 +1,62 @@
+/** Hibernus Library
+ * University of Southampton 2017
+ *
+ * Open-source liberary that enable any of your Mbed project work with transient enegy sources.
+ * In order to use this library include the "hibernus.h" header file, and use the "Hibernus()" method at the beginning of you main funtion.
+ * For more details and example see the "main.cpp" exampe file, and the attached documnetation
+ *
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+#ifndef CONFIG_H_
+#define CONFIG_H_
+#ifdef LPC11U24
+#include "mbed.h"
+#include "IAP.h"
+
+/////for LPC11U24
+#define RAM_Start 0x10000000
+#define FLASH_Start 0x00000000
+#define RAM_Size 8192
+#define flash_Size 32768 //32K flash
+#define sector_Size FLASH_SECTOR_SIZE //4K sector size
+
+#define No_Of_4B_Peripheral_Reg 10
+#define No_Of_1B_Peripheral_Reg 0
+
+const unsigned int REG_Addresses_4B[83] = {
+(unsigned int)&LPC_GPIO_PIN_INT->ISEL, /*!< (@ 0x4004C000) Pin Interrupt Mode register */
+(unsigned int)&LPC_GPIO_PIN_INT->IENR, /*!< (@ 0x4004C004) Pin Interrupt Enable (Rising) register */
+(unsigned int)&LPC_GPIO_PIN_INT->SIENR, /*!< (@ 0x4004C008) Set Pin Interrupt Enable (Rising) register */
+(unsigned int)&LPC_GPIO_PIN_INT->CIENR, /*!< (@ 0x4004C00C) Clear Pin Interrupt Enable (Rising) register */
+(unsigned int)&LPC_GPIO_PIN_INT->IENF, /*!< (@ 0x4004C010) Pin Interrupt Enable Falling Edge / Active Level register */
+(unsigned int)&LPC_GPIO_PIN_INT->SIENF, /*!< (@ 0x4004C014) Set Pin Interrupt Enable Falling Edge / Active Level register */
+(unsigned int)&LPC_GPIO_PIN_INT->CIENF, /*!< (@ 0x4004C018) Clear Pin Interrupt Enable Falling Edge / Active Level address */
+(unsigned int)&LPC_GPIO_PIN_INT->RISE, /*!< (@ 0x4004C01C) Pin Interrupt Rising Edge register */
+(unsigned int)&LPC_GPIO_PIN_INT->FALL, /*!< (@ 0x4004C020) Pin Interrupt Falling Edge register */
+(unsigned int)&LPC_GPIO_PIN_INT->IST,
+};
+
+const unsigned int REG_Addresses_1B[30] = {};
+
+#if HasInternalComparator == 1
+ void configure_VR_comparator_interrupt(void);
+ void configure_VH_comparator_interrupt(void);
+ void Comparator_Setup(void);
+#else
+ extern "C" void FLEX_INT0_IRQHandler(void);
+ extern "C" void FLEX_INT1_IRQHandler(void);
+ void configure_VH_gpio_interrupt(void);
+ void configure_VR_gpio_interrupt(void);
+#endif
+
+void erase_flags_memory(void);
+void restore_flags(void);
+void Enter_LLS(void);
+void setFlag(volatile unsigned int*);
+bool isFlagSet(volatile unsigned int*);
+void copyRamToFlash(void);
+
+#endif
+#endif
+
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Drivers/asm_restore_KL05Z.s Fri Sep 08 18:01:22 2017 +0000 @@ -0,0 +1,12 @@ + AREA asm_func, CODE, READONLY +; Export my_asm function location so that C compiler can find it and link + EXPORT asm_restoree +asm_restoree + + LDR R2, =0x1FFFFC50 // Use R2 as auxiliary register (address of RAM sector 3) + + LDR R1, [R2] // Load R1 with value of R13 (SP) stored in RAM + MOV SP, R1 // Copy value of R1 into R13 (SP) + + BX LR +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Drivers/asm_restore_LPC11U24.s Fri Sep 08 18:01:22 2017 +0000 @@ -0,0 +1,13 @@ + AREA asm_func, CODE, READONLY +; Export my_asm function location so that C compiler can find it and link + EXPORT asm_restore +asm_restore + + LDR R2, =0x10000050 // Use R2 as auxiliary register (address of RAM sector 3) + + LDR R1, [R2] // Load R1 with value of R13 (SP) stored in RAM + MOV SP, R1 // Copy value of R1 into R13 (SP) + + BX LR +END + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config.h Fri Sep 08 18:01:22 2017 +0000 @@ -0,0 +1,4 @@ +#define HasInternalComparator 0 //Set on 1 if there is an internal comparator 0 otherwise +#define SaveFlagsInFlash 0 //set on 1 if there is enough Flash memory available for the flags to have their own flash sector, 0 otherwise + //if there is not enough flash memory, the flags will be saved in RAM memory +#define LPC11U24 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hibernus.cpp Fri Sep 08 18:01:22 2017 +0000
@@ -0,0 +1,249 @@
+/** Hibernus Library
+ * University of Southampton 2017
+ *
+ * Open-source liberary that enable any of your Mbed project work with transient enegy sources.
+ * In order to use this library include the "hibernus.h" header file, and use the "Hibernus()" method at the beginning of you main funtion.
+ * For more details and example see the "main.cpp" exampe file, and the attached documnetation
+ *
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+#include "hibernus.h"
+#include "mbed.h"
+#include "config.h"
+#ifdef LPC11U24
+ #include "Driver_LPC11U24.h"
+#endif
+#ifdef KL05Z
+ #include "Driver_KL05Z.h"
+#endif
+
+//11 variables stored at fixed addresses at the beginning of the RAM
+#if SaveFlagsInFlash == 0
+volatile unsigned int FLAG_1 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset)));// = Flash_Flags_Sector_Start;
+volatile unsigned int FLAG_2 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+ 0x4)));// = Flash_Flags_Sector_Start + 0x4;
+volatile unsigned int FLAG_3 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+ 0x8)));// = Flash_Flags_Sector_Start + 0x8;
+volatile unsigned int FLAG_4 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+ 0xC)));// = Flash_Flags_Sector_Start + 0xC;
+#else
+volatile unsigned int FLAG_1 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset))) = Flash_Flags_Sector_Start;
+volatile unsigned int FLAG_2 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+ 0x4))) = Flash_Flags_Sector_Start + 0x4;
+volatile unsigned int FLAG_3 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+ 0x8))) = Flash_Flags_Sector_Start + 0x8;
+volatile unsigned int FLAG_4 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+ 0xC))) = Flash_Flags_Sector_Start + 0xC;
+#endif
+
+volatile unsigned int CoreReg_SP __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x10)));
+volatile unsigned int CoreReg_LR __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x14)));
+volatile unsigned int CoreReg_PC __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x18)));
+
+volatile unsigned int n __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x1C))); // Variable used for counting in loops (4 bytes) stored at RAM address (RamStart+0x54)
+volatile unsigned char i __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x20))); // Variable used for counting in loops (1 byte) stored at RAM address (RamStart+0x58)
+
+volatile unsigned int *FLASH_ptr_4B __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x24))); // Pointer that points to flash (4 bytes) stored at RAM address (RamStart+0x5C)
+volatile unsigned int *RAM_ptr __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x28))); // Pointer that points to RAM (4 bytes) stored at RAM address (RamStart+0x60)
+// Arrays used to store the contents of the peripheral registers
+volatile unsigned int dum __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x2C))) = 0x1234FFFF;
+volatile unsigned int REG_Array_4B[No_Of_4B_Peripheral_Reg] __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x30)));;
+volatile unsigned char REG_Array_1B[No_Of_1B_Peripheral_Reg] __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x30+4*No_Of_4B_Peripheral_Reg)));;
+
+volatile unsigned int dummyread; // Variable used for serialization
+
+void Hibernus(){
+ //pc1.printf("flags %x %x ",((unsigned int*)(RAM_Start +Fixed_Add_Vars_Offset+ Fixed_Add_Vars_Size))+(int)((RAM_Size-Fixed_Add_Vars_Offset-Fixed_Add_Vars_Size)/4),&dum);
+ #if SaveFlagsInFlash == 0
+ restore_flags();
+ #endif
+
+ if( isFlagSet(&FLAG_2) && isFlagSet(&FLAG_3) && isFlagSet(&FLAG_4)) // Enter this only after complete shut down
+ {
+ erase_flags_memory();
+ setFlag(&FLAG_1);
+ setFlag(&FLAG_4);
+ }
+
+ if(isFlagSet(&FLAG_1)||isFlagSet(&FLAG_2)||isFlagSet(&FLAG_3)||isFlagSet(&FLAG_4))
+ {
+ __enable_irq(); // Enable interrupts
+ Enter_LLS(); // Enter LLS mode
+ }
+
+ if(!isFlagSet(&FLAG_1)) // If *FLAG_1 is not already set (first time waking up)
+ {
+ erase_flags_memory();
+ setFlag(&FLAG_2);
+
+ #if HasInternalComparator == 1
+ configure_VH_comparator_interrupt();
+ #else
+ configure_VH_gpio_interrupt();
+ #endif
+ __enable_irq(); // Enable interrupts
+ }
+ else{
+ if(isFlagSet(&FLAG_4))
+ {
+ #if HasInternalComparator == 1
+ configure_VH_comparator_interrupt();
+ #else
+ configure_VH_gpio_interrupt();
+ #endif
+
+ erase_flags_memory();
+ setFlag(&FLAG_2);
+ restore();
+ }
+ }
+}
+
+void Save_RAM_Regs(){
+ //Copy the peripheral registers to RAM
+ for(n=0; n<No_Of_4B_Peripheral_Reg;n++){
+ REG_Array_4B[n] = *(unsigned int*)REG_Addresses_4B[n];
+ }
+ for(n=0; n<No_Of_1B_Peripheral_Reg;n++){
+ REG_Array_1B[n] = *(unsigned int*)REG_Addresses_1B[n];
+ }
+
+ //copy all the ram to flash
+ copyRamToFlash();
+}
+
+void Restore_Regs(){
+ //Restore peripheral registers from RAM, After the ram content was copied back from flash, after a restore
+ for(n=0; n<No_Of_4B_Peripheral_Reg; n++){
+ *(unsigned int*) REG_Addresses_4B[n] = REG_Array_4B[n];
+ }
+
+ for(i=0; i<No_Of_1B_Peripheral_Reg; i++){
+ *(unsigned char*) REG_Addresses_1B[i] = REG_Array_1B[i];
+ }
+}
+
+void hibernate(volatile unsigned int Rsp, volatile unsigned int Rlr, volatile unsigned int Rpc){
+
+ if(isFlagSet(&FLAG_2)&& isFlagSet(&FLAG_3) && isFlagSet(&FLAG_4)) // Enter this only after complete shut down
+ {
+ erase_flags_memory(); // Erase flash sector used to save the flags
+ setFlag(&FLAG_1);
+ setFlag(&FLAG_4);
+ }
+
+ if(isFlagSet(&FLAG_2))
+ {
+ // Hibernate procedure
+ __disable_irq(); // Disable interrupts
+
+ //save the core registers
+ CoreReg_SP = Rsp; // 40 for hibernate function 38 otherwsie
+ CoreReg_LR = Rlr; // 34 for hibernate function 2C otherwise
+ CoreReg_PC = Rpc; // 38 for hibernate function 30 otherwise
+
+
+ #if HasInternalComparator == 1
+ Save_RAM_Regs();
+
+ setFlag(&FLAG_3);
+ setFlag(&FLAG_4);
+
+ Comparator_Setup();
+ configure_VH_comparator_interrupt();
+ #else
+ setFlag(getFlag_3());
+ setFlag(getFlag_4());
+
+ Save_RAM_Regs();
+ configure_VH_gpio_interrupt();
+ #endif
+
+ __enable_irq(); // Enable interrupts
+
+ Enter_LLS(); // Enter LLS mode
+ }
+}
+
+void restore(){
+ // Restore procedure
+ __disable_irq(); // Disable interrupts
+
+ erase_flags_memory();
+ setFlag(&FLAG_2);
+
+ //Restore peripheral registers
+ Restore_Regs();
+
+ //Restore RAM
+ FLASH_ptr_4B = (unsigned int*) (flash_ramSection_start);
+ RAM_ptr = (unsigned int*) (RAM_Start);
+
+ //Copy RAM until where the pointers and loop variables are stored
+ //divide it by 4 because the copy is done word by word but byte by byte
+ for(n=0; n<(Fixed_Add_Vars_Offset/4); n++){
+ *(RAM_ptr + n) = *(FLASH_ptr_4B + n);
+ }
+
+ //skip the Core reg and fixed address variables
+ FLASH_ptr_4B = (unsigned int*)(flash_ramSection_start +Fixed_Add_Vars_Offset+ Fixed_Add_Vars_Size);
+ RAM_ptr = (unsigned int*)(RAM_Start +Fixed_Add_Vars_Offset+ Fixed_Add_Vars_Size);
+
+ //copy the rest of the RAM
+ //(RAM_Size-Fixed_Add_Vars_Offset-Fixed_Add_Vars_Size) is the siz eof the rest of the ram that have to be copied
+ //divide it by 4 because the copy is done word by word but byte by byte
+ for(n=1; n<(RAM_Size-Fixed_Add_Vars_Offset-Fixed_Add_Vars_Size)/4; n++){
+ *(RAM_ptr + n) = *(FLASH_ptr_4B + n);
+ }
+
+ //copy the 3 core registers from flash o ram
+ CoreReg_SP=*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset+0x10);
+ CoreReg_LR=*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset+0x14);
+ CoreReg_PC=*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset+0x18);
+
+ #if SaveFlagsInFlash == 1 //if the flags are stored in their own flash sector, their default value(the flags address in their flash sector) have to be restored
+ //otherwise, their value has to be unchanged, there is no need for restore
+ FLAG_1 =*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset);
+ FLAG_2 =*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset +0x4);
+ FLAG_3 =*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset +0x8);
+ FLAG_4 =*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset +0xC);
+ #else
+ configure_VH_gpio_interrupt();
+ #endif
+
+ __enable_irq(); // Enable interrupts
+
+ asm_restore(); // Restore the SP
+ _LR = CoreReg_LR; // Restore the LR
+ _PC = CoreReg_PC; // Restore the PC
+}
+
+//use to check if you recover from a sleep without power loss
+//is so, don't restore, and just set the VH interrupt
+void recovery_no_power_loss(){
+
+ if(isFlagSet(getFlag_3())){ // Enter after hibernation with no power loss
+ #if HasInternalComparator == 1
+ configure_VH_comparator_interrupt();
+ #else
+ configure_VH_gpio_interrupt();
+ #endif
+
+ erase_flags_memory(); // Erase flash sector used to save the flags
+ setFlag(getFlag_2());
+
+ __enable_irq(); // Enable interrupts
+ }
+}
+extern "C" volatile unsigned int* getFlag_1(){
+ return &FLAG_1;
+}
+
+extern "C" volatile unsigned int* getFlag_2(){
+ return &FLAG_2;
+}
+
+extern "C" volatile unsigned int* getFlag_3(){
+ return &FLAG_3;
+}
+
+extern "C" volatile unsigned int* getFlag_4(){
+ return &FLAG_4;
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hibernus.h Fri Sep 08 18:01:22 2017 +0000
@@ -0,0 +1,43 @@
+/** Hibernus Library
+ * University of Southampton 2017
+ *
+ * Open-source liberary that enable any of your Mbed project work with transient enegy sources.
+ * In order to use this library include the "hibernus.h" header file, and use the "Hibernus()" method at the beginning of you main funtion.
+ * For more details and example see the "main.cpp" exampe file, and the attached documnetation
+ *
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+#ifndef HIBERNUS_H_
+#define HIBERNUS_H_
+
+#define Fixed_Add_Vars_Offset 0x40 //the Offset added to the first address of RAM, in order to compute the address of first fixed Add variable
+#define Fixed_Add_Vars_Size 0x28 //size of the all fixed address variables (0x28 = 44(dec) = 4Bytes*(4 flags+3CoreReg+4LoopVar))
+#define flash_end (FLASH_Start + flash_Size)
+#define ramToFlash_sectors_number (RAM_Size / sector_Size) //how many flash sectors do we have to erase, before saving the RAM content to flash
+#define flash_ramSection_start (flash_end - RAM_Size-SaveFlagsInFlash *sector_Size)
+
+// Declare register integers for the SP, LR, and PC
+register volatile unsigned int _SP __asm("r13");
+register volatile unsigned int _LR __asm("r14");
+register volatile unsigned int _PC __asm("r15");
+
+// Value written to non-volatile flags to indicate that they are set or not
+#define Flag_set 0xFFFF0000
+#define Flag_erase 0xFFFFFFFF
+
+// Declare external assembly language function (in a *.s file)
+extern "C" void asm_restore(void);
+extern "C" volatile unsigned int* getFlag_1(void);
+extern "C" volatile unsigned int* getFlag_2(void);
+extern "C" volatile unsigned int* getFlag_3(void);
+extern "C" volatile unsigned int* getFlag_4(void);
+
+void Hibernus(void);
+void Save_RAM_Regs(void);
+void Restore_Regs(void);
+void restore(void);
+void hibernate(volatile unsigned int sp, volatile unsigned int lr, volatile unsigned int pc);
+void recovery_no_power_loss(void);
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Fri Sep 08 18:01:22 2017 +0000
@@ -0,0 +1,42 @@
+/** Hibernus Library
+ * University of Southampton 2017
+ *
+ * Open-source liberary that enable any of your Mbed project work with transient enegy sources.
+ * In order to use this library include the "hibernus.h" header file, and use the "Hibernus()" method at the beginning of you main funtion.
+ * For more details and example see the "main.cpp" exampe file, and the attached documnetation
+ *
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+#include "hibernus.h"
+#include "mbed.h"
+
+DigitalOut bit0(LED1);
+DigitalOut bit1(LED2);
+DigitalOut bit2(LED3);
+DigitalOut bit3(LED4);
+
+int main()
+{
+ int c;
+ Hibernus();
+ while(1) // Binary counter
+ {
+ bit0 = 0; bit1 = 0; bit2 = 0; bit3 = 0; for(c = 0; c<2000000; c++); // 0
+ bit0 = 1; bit1 = 0; bit2 = 0; bit3 = 0; for(c = 0; c<2000000; c++); // 1
+ bit0 = 0; bit1 = 1; bit2 = 0; bit3 = 0; for(c = 0; c<2000000; c++); // 2
+ bit0 = 1; bit1 = 1; bit2 = 0; bit3 = 0; for(c = 0; c<2000000; c++); // 3
+ bit0 = 0; bit1 = 0; bit2 = 1; bit3 = 0; for(c = 0; c<2000000; c++); // 4
+ bit0 = 1; bit1 = 0; bit2 = 1; bit3 = 0; for(c = 0; c<2000000; c++); // 5
+ bit0 = 0; bit1 = 1; bit2 = 1; bit3 = 0; for(c = 0; c<2000000; c++); // 6
+ bit0 = 1; bit1 = 1; bit2 = 1; bit3 = 0; for(c = 0; c<2000000; c++); // 7
+ bit0 = 0; bit1 = 0; bit2 = 0; bit3 = 1; for(c = 0; c<2000000; c++); // 8
+ bit0 = 1; bit1 = 0; bit2 = 0; bit3 = 1; for(c = 0; c<2000000; c++); // 9
+ bit0 = 0; bit1 = 1; bit2 = 0; bit3 = 1; for(c = 0; c<2000000; c++); // 10
+ bit0 = 1; bit1 = 1; bit2 = 0; bit3 = 1; for(c = 0; c<2000000; c++); // 11
+ bit0 = 0; bit1 = 0; bit2 = 1; bit3 = 1; for(c = 0; c<2000000; c++); // 12
+ bit0 = 1; bit1 = 0; bit2 = 1; bit3 = 1; for(c = 0; c<2000000; c++); // 13
+ bit0 = 0; bit1 = 1; bit2 = 1; bit3 = 1; for(c = 0; c<2000000; c++); // 14
+ bit0 = 1; bit1 = 1; bit2 = 1; bit3 = 1; for(c = 0; c<2000000; c++); // 15
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri Sep 08 18:01:22 2017 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/mbed_official/code/mbed/builds/a330f0fddbec \ No newline at end of file

