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.

Dependencies:   FreescaleIAP mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hibernus.cpp Source File

hibernus.cpp

00001 /**    Hibernus Library
00002  *     University of Southampton 2017
00003  *
00004  *      Open-source liberary that enable any of your Mbed project work with transient enegy sources.
00005  *      In order to use this library include the "hibernus.h" header file, and use the "Hibernus()" method at the beginning of you main funtion.
00006  *      For more details and example see the "main.cpp" exampe file, and the attached documnetation
00007  *
00008  *
00009  *     Released under the MIT License: http://mbed.org/license/mit
00010  */
00011  
00012 #include "hibernus.h"
00013 #include "mbed.h"
00014 #include "config.h"
00015 
00016 //11 variables stored at fixed addresses at the beginning of the RAM
00017 volatile unsigned int FLAG_1 __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset))) = Flash_Flags_Sector_Start;
00018 volatile unsigned int FLAG_2 __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+ 0x4))) = Flash_Flags_Sector_Start + 0x4;
00019 volatile unsigned int FLAG_3 __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+ 0x8))) = Flash_Flags_Sector_Start + 0x8;
00020 volatile unsigned int FLAG_4 __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+ 0xC))) = Flash_Flags_Sector_Start + 0xC;
00021 
00022 volatile unsigned int CoreReg_SP __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+0x10)));
00023 volatile unsigned int CoreReg_LR __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+0x14)));
00024 volatile unsigned int CoreReg_PC __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+0x18)));
00025 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)
00026 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)
00027 
00028 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)
00029 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)
00030 
00031 // Arrays used to store the contents of the peripheral registers
00032 volatile unsigned int REG_Array_4B[No_Of_4B_Peripheral_Reg]     __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+0x2C)));;         
00033 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)));;
00034 
00035 Serial pc1(USBTX, USBRX);
00036 void Hibernus(){
00037     #if SaveFlagsInFlash == 0
00038         restore_flags();
00039     #endif
00040     
00041     if( isFlagSet(&FLAG_2) && isFlagSet(&FLAG_3) && isFlagSet(&FLAG_4))  // Enter this only after complete shut down
00042   { 
00043         erase_flags_memory();   
00044         setFlag(&FLAG_1);
00045         setFlag(&FLAG_4);
00046    }
00047         
00048     if(isFlagSet(&FLAG_1)||isFlagSet(&FLAG_2)||isFlagSet(&FLAG_3)||isFlagSet(&FLAG_4))
00049     {   
00050     __enable_irq();     // Enable interrupts
00051     Enter_LLS();        // Enter LLS mode
00052   }
00053         
00054     if(!isFlagSet(&FLAG_1)) // If *FLAG_1 is not already set (first time waking up)
00055   {
00056         erase_flags_memory();
00057         setFlag(&FLAG_2);
00058             
00059         #if HasInternalComparator == 1
00060                 configure_VH_comparator_interrupt();
00061         #else
00062                 configure_VH_gpio_interrupt();
00063         #endif
00064     __enable_irq();     // Enable interrupts
00065   }
00066   else{
00067         if(isFlagSet(&FLAG_4))
00068         { 
00069         #if HasInternalComparator == 1
00070                 configure_VH_comparator_interrupt();
00071         #else
00072                 configure_VH_gpio_interrupt();
00073         #endif
00074             
00075             erase_flags_memory();
00076             setFlag(&FLAG_2);
00077             restore();
00078      }
00079   }
00080 }
00081 
00082 void Save_RAM_Regs(){  
00083     //Copy the peripheral registers to RAM
00084     for(n=0; n<No_Of_4B_Peripheral_Reg;n++){
00085         REG_Array_4B[n] = *(unsigned int*)REG_Addresses_4B[n];
00086     }
00087     for(n=0; n<No_Of_1B_Peripheral_Reg;n++){
00088         REG_Array_1B[n] = *(unsigned int*)REG_Addresses_1B[n];
00089     }
00090     
00091     //copy all the ram to flash
00092     copyRamToFlash();
00093 }
00094 
00095 void Restore_Regs(){ 
00096     //Restore peripheral registers from RAM, After the ram content was copied back from flash, after a restore
00097     for(n=0; n<No_Of_4B_Peripheral_Reg; n++){
00098         *(unsigned int*) REG_Addresses_4B[n] = REG_Array_4B[n];
00099     }
00100     
00101     for(i=0; i<No_Of_1B_Peripheral_Reg; i++){
00102         *(unsigned char*) REG_Addresses_1B[i] = REG_Array_1B[i];
00103     }
00104 }
00105 
00106 void restore(){
00107     // Restore procedure
00108     __disable_irq();     // Disable interrupts
00109  
00110     erase_flags_memory();
00111     setFlag(&FLAG_2); 
00112 
00113     //Restore peripheral registers  
00114     Restore_Regs();     
00115                 
00116     //Restore RAM
00117   FLASH_ptr_4B = (unsigned int*) (flash_ramSection_start);       
00118   RAM_ptr      = (unsigned int*) (RAM_1_Address);
00119     
00120     //Copy RAM until where the pointers and loop variables are stored
00121     //divide it by 4 because the copy is done word by word but byte by byte
00122   for(n=0; n<(Fixed_Add_Vars_Offset/4); n++){                                
00123         *(RAM_ptr + n) = *(FLASH_ptr_4B + n);
00124     }
00125     
00126     //skip the Core reg and fixed address variables
00127     FLASH_ptr_4B = (unsigned int*)(flash_ramSection_start +Fixed_Add_Vars_Offset+ Fixed_Add_Vars_Size);
00128     RAM_ptr = (unsigned int*)(RAM_1_Address +Fixed_Add_Vars_Offset+ Fixed_Add_Vars_Size);
00129     
00130     //copy the rest of the RAM
00131     //(RAM_Size-Fixed_Add_Vars_Offset-Fixed_Add_Vars_Size) is the siz eof the rest of the ram that have to be copied
00132     //divide it by 4 because the copy is done word by word but byte by byte
00133      for(n=0; n<(RAM_Size-Fixed_Add_Vars_Offset-Fixed_Add_Vars_Size)/4; n++){                                
00134         *(RAM_ptr + n) = *(FLASH_ptr_4B + n);
00135   }
00136      
00137     //copy the 3 core registers from flash o ram
00138     CoreReg_SP=*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset+0x10);
00139     CoreReg_LR=*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset+0x14);
00140     CoreReg_PC=*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset+0x18);
00141                                 
00142     //Configure the iterrupt for VH/Hibernate
00143     #if HasInternalComparator == 1
00144             configure_VH_comparator_interrupt();
00145     #else
00146             configure_VH_gpio_interrupt();
00147     #endif
00148         
00149     __enable_irq();     // Enable interrupts 
00150 
00151     asm_restore();          // Restore the value of SP                        
00152     _LR = CoreReg_LR;     // Restore the value of LR
00153   _PC = CoreReg_PC;     // Restore the value of PC
00154 }
00155 
00156 extern "C" volatile unsigned int* getFlag_1(){
00157     return &FLAG_1;
00158 }
00159 
00160 extern "C" volatile unsigned int* getFlag_2(){
00161     return &FLAG_2;
00162 }
00163 
00164 extern "C" volatile unsigned int* getFlag_3(){
00165     return &FLAG_3;
00166 }
00167 
00168 extern "C" volatile unsigned int* getFlag_4(){
00169     return &FLAG_4;
00170 }
00171 
00172 extern "C" volatile unsigned int* getCore_SP(){
00173     return &CoreReg_SP;
00174 }
00175 
00176 extern "C" volatile unsigned int* getCore_PC(){
00177     return &CoreReg_PC;
00178 }
00179 
00180 extern "C" volatile unsigned int* getCore_LR(){
00181     return &CoreReg_LR;
00182 }