This library allows any user to use their Mbed project with a transient energy source( e.g. windturbine, solar power).
This library allows any user to use their Mbed project with a transient energy source( e.g. windturbine, solar power). You can do this by simply import the "hibernus.h" header file, and call the "Hibernus()" method at the beginning of you main program. In case of a power loss the state of your programm will be saved to the nonvolatile memory and it will be resumed from the same point as soon as there is enough power for the board to run properly. If the power drops down, the internal capacitance of the system is used to save a snapshot of your program into the flash memory, and the board goes in a low power mode (sleep or deepsleep). In order to detect a power loss, the library uses an analog comparator which can be internal (eg Freescale KL 05Z has an internal comparator which can be used ), or external (on LPC11U24 there is no internal comparator) via a GPIO interrupt. For more details see the code comments and the attached example main.cpp file.
This library use "IAP" library, in order to write the required data to the flash nonvolatile memory.
The library can be easily adapted to work with other boards, from different manufactures, which have support for Mbed. In order to adapt this library and use it on your board, the write to flash methods have to be changed. Some changes listed below are required because of the platform dependent parameters of each board. All required changes have to be applied to the "config.h" and "config.cpp" files.
- The "erase_flags_memory()", "copyRamToFlash()", "restore_flags()", "setFlag()" and " isFlagSet()" methods have to be modified in order to use the right Flash IAP of your board.
- The wake up and hibernate interrupts have to be modified in order to be trigghered when the voltage drops down or rise. If you use an internal comparator, it should trigger and interrupt whenever the power drops(e.g see CMP0_IRQHandler() method writtend for KL05Z at https://developer.mbed.org/users/BogdanL/code/Hibernus-KL05Z/ ) . At that time a snapshot have to be saved and the board sent to sleep. Another interrupt have to be triggered when the power comes back(see "LLW_IRQHandler()" at https://developer.mbed.org/users/BogdanL/code/Hibernus-KL05Z ) . This have to wake up the board and resume de computation. In you use an external comparator two GPIO interrupts are used. One of them (for LPC11U24 see "FLEX_INT1_IRQHandler()" ) is used to save the snapshot when the power drops down, and the other one (for LPC11U24 see "FLEX_INT0_IRQHandler()" ) is used to wake up the board.
- For each board, the right Sleep mode have to be chosen. Also the interrups and the comparator have to be properly set, in order to be triggered as desired. For a good example see "configure_VR_gpio_interrupt()" and "configure_VH_gpio_interrupt()" that are used to set up the Restore and Hibernate interrupts on LPC11U24 board, that uses an external comparator.
- In the "config.h" file, the two arrays, "REG_Addresses_4B[]" and "REG_Addresses_4B[]" have to be populated with the addresses of the 1 Byte and 4Bytes peripheral registers that are used by your project. Different boards have different modules that use different peripheral registers. The addresses of the registers can be found in the Reference Manual of each board, and will be used in order to save and later restore the content of the registers. Also the number of used registers, "No_Of_4B_Peripheral_Reg", No_Of_1B_Peripheral_Reg, have to be updated with the correct number of used registers.
- At the top of "config.h" header file, specific board parameters have to be fixed: RAM start address(RAM_1_Address), Flash start address(FLASH_Start), RAM size(RAM_Size), Flash size(flash_Size) and the flash sector size(sector_Size).
Revision 0:697a3b20c1d1, committed 2017-09-01
- Comitter:
- BogdanL
- Date:
- Fri Sep 01 15:27:34 2017 +0000
- Commit message:
- first version of Hibernus Library. V1.0
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IAP.lib Fri Sep 01 15:27:34 2017 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/okano/code/IAP/#c8bf974ecb33
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asm_restore.s Fri Sep 01 15:27:34 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.cpp Fri Sep 01 15:27:34 2017 +0000 @@ -0,0 +1,172 @@ +/** 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 "config.h" +#include "hibernus.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())); + + if(isFlagSet(getFlag_2())&& isFlagSet(getFlag_3()) && isFlagSet(getFlag_4())) // Enter this only after complete shut down + { + erase_flags_memory(); + setFlag(getFlag_1()); + setFlag(getFlag_4()); + } + if(isFlagSet(getFlag_2())) + { // Hibernate procedure + __disable_irq(); + + unsigned int regs = *(unsigned int*)(_SP+0x1C); + volatile unsigned int sp1=(_SP+0x40), lr1= *(unsigned int*)(_SP+0x34), pc1=*(unsigned int*)(_SP+0x38); + // Save previous SP value from main // 0x40 for hibernate function 38 otherwsie + *getCore_SP() = sp1; + + // Save previous LR value from main// 34 for hibernate function 2C otherwise + *getCore_LR() = lr1; + + // Save previous PC value from main // 38 for hibernate function 30 otherwise + *getCore_PC() = pc1; + + setFlag(getFlag_3()); + setFlag(getFlag_4()); + + Save_RAM_Regs(); + + configure_VR_gpio_interrupt(); + + __enable_irq(); + + Enter_LLS(); // Enter LLS mode + } + + //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); + if(isFlagSet(getFlag_3())) // Enter after hibernation with no power loss + { + configure_VH_gpio_interrupt(); + erase_flags_memory(); + setFlag(getFlag_2()); + __enable_irq(); // Enable interrupts + } + + //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); + } +} + +//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_1_Address,(char*)flash_ramSection_start,RAM_Size/2); + g1+=iap.write((char*)RAM_1_Address+(RAM_Size/2),(char*)flash_ramSection_start+(RAM_Size/2),(RAM_Size/2)); +} + +//Clear the memory area where the flags are saved +void erase_flags_memory(){ + if(!SaveFlagsInFlash) { + *getFlag_1() = Flag_erase; + *getFlag_2() = Flag_erase; + *getFlag_3() = Flag_erase; + *getFlag_4() = Flag_erase; + } +} + +//mark a flag as "SET" +void setFlag(volatile unsigned int* add){ + *add = Flag_set; +} + +//check if a flag is SET or CLEAR +bool isFlagSet(volatile unsigned int* add){ + if(*add == Flag_set ) return true; + return false; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config.h Fri Sep 01 15:27:34 2017 +0000 @@ -0,0 +1,59 @@ +/** 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_ +#include "mbed.h" +#include "IAP.h" + +#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 + +/////for LPC11U24 +#define RAM_1_Address 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] = {}; + +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); + +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 + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hibernus.cpp Fri Sep 01 15:27:34 2017 +0000 @@ -0,0 +1,169 @@ +/** 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" + +//11 variables stored at fixed addresses at the beginning of the RAM +volatile unsigned int FLAG_1 __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset))); +volatile unsigned int FLAG_2 __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+ 0x4))); +volatile unsigned int FLAG_3 __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+ 0x8))); +volatile unsigned int FLAG_4 __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+ 0xC))); + +volatile unsigned int CoreReg_SP __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+0x10))); +volatile unsigned int CoreReg_LR __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+0x14))); +volatile unsigned int CoreReg_PC __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+0x18))); +volatile unsigned int n __attribute__((at(RAM_1_Address+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_1_Address+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_1_Address+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_1_Address+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 REG_Array_4B[No_Of_4B_Peripheral_Reg] __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+0x2C)));; +volatile unsigned char REG_Array_1B[No_Of_1B_Peripheral_Reg] __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+0x2C+4*No_Of_4B_Peripheral_Reg)));; + +volatile unsigned int dummyread; // Variable used for serialization + +void Hibernus(){ + restore_flags(); + + 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); + + configure_VH_gpio_interrupt(); + __enable_irq(); // Enable interrupts + } + else{ + if(isFlagSet(&FLAG_4)) + { + configure_VH_gpio_interrupt(); + 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]; + } + + // 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 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_1_Address); + + //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_1_Address +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=0; 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); + + //Configure the iterrupt for VH/Hibernate + configure_VH_gpio_interrupt(); + __enable_irq(); // Enable interrupts + + asm_restore(); // Restore the value of SP + _LR = CoreReg_LR; // Restore the value of LR + _PC = CoreReg_PC; // Restore the value of PC +} + +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; +} + +extern "C" volatile unsigned int* getCore_SP(){ + return &CoreReg_SP; +} + +extern "C" volatile unsigned int* getCore_PC(){ + return &CoreReg_PC; +} + +extern "C" volatile unsigned int* getCore_LR(){ + return &CoreReg_LR; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hibernus.h Fri Sep 01 15:27:34 2017 +0000 @@ -0,0 +1,45 @@ +/** 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 0x2C //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) + +// 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); +extern "C" volatile unsigned int* getCore_SP(void); +extern "C" volatile unsigned int* getCore_LR(void); +extern "C" volatile unsigned int* getCore_PC(void); + +void Hibernus(void); +void Save_RAM_Regs(void); +void Restore_Regs(void); +void restore(void); +void hibernate(void); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Sep 01 15:27:34 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 + */ +#include "hibernus.h" +#include "config.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 01 15:27:34 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/64910690c574 \ No newline at end of file