Bogdan Lazarescu / Mbed 2 deprecated Hibernus

Dependencies:   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 #include "hibernus.h"
00012 #include "mbed.h"
00013 #include "config.h"
00014 #ifdef LPC11U24
00015         #include "Driver_LPC11U24.h"
00016 #endif
00017 #ifdef KL05Z
00018         #include "Driver_KL05Z.h"
00019 #endif
00020 
00021 //11 variables stored at fixed addresses at the beginning of the RAM
00022 #if SaveFlagsInFlash == 0
00023 volatile unsigned int FLAG_1 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset)));// = Flash_Flags_Sector_Start;
00024 volatile unsigned int FLAG_2 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+ 0x4)));// = Flash_Flags_Sector_Start + 0x4;
00025 volatile unsigned int FLAG_3 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+ 0x8)));// = Flash_Flags_Sector_Start + 0x8;
00026 volatile unsigned int FLAG_4 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+ 0xC)));// = Flash_Flags_Sector_Start + 0xC;
00027 #else
00028 volatile unsigned int FLAG_1 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset))) = Flash_Flags_Sector_Start;
00029 volatile unsigned int FLAG_2 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+ 0x4))) = Flash_Flags_Sector_Start + 0x4;
00030 volatile unsigned int FLAG_3 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+ 0x8))) = Flash_Flags_Sector_Start + 0x8;
00031 volatile unsigned int FLAG_4 __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+ 0xC))) = Flash_Flags_Sector_Start + 0xC;
00032 #endif
00033 
00034 volatile unsigned int CoreReg_SP __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x10)));
00035 volatile unsigned int CoreReg_LR __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x14)));
00036 volatile unsigned int CoreReg_PC __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x18)));
00037     
00038 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)
00039 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)
00040 
00041 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)
00042 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)
00043 // Arrays used to store the contents of the peripheral registers
00044 volatile unsigned int dum   __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x2C))) = 0x1234FFFF;
00045 volatile unsigned int REG_Array_4B[No_Of_4B_Peripheral_Reg]     __attribute__((at(RAM_Start+Fixed_Add_Vars_Offset+0x30)));;         
00046 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)));;
00047 
00048 volatile unsigned int dummyread;      // Variable used for serialization
00049 
00050 void Hibernus(){
00051     //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);
00052     #if SaveFlagsInFlash == 0
00053         restore_flags();
00054     #endif
00055     
00056     if( isFlagSet(&FLAG_2) && isFlagSet(&FLAG_3) && isFlagSet(&FLAG_4))  // Enter this only after complete shut down
00057   { 
00058         erase_flags_memory();   
00059         setFlag(&FLAG_1);
00060         setFlag(&FLAG_4);
00061    }
00062         
00063     if(isFlagSet(&FLAG_1)||isFlagSet(&FLAG_2)||isFlagSet(&FLAG_3)||isFlagSet(&FLAG_4))
00064     {   
00065     __enable_irq();     // Enable interrupts
00066     Enter_LLS();        // Enter LLS mode
00067   }
00068         
00069     if(!isFlagSet(&FLAG_1)) // If *FLAG_1 is not already set (first time waking up)
00070   {
00071         erase_flags_memory();
00072         setFlag(&FLAG_2);
00073             
00074         #if HasInternalComparator == 1
00075                 configure_VH_comparator_interrupt();
00076         #else
00077                 configure_VH_gpio_interrupt();
00078         #endif
00079     __enable_irq();     // Enable interrupts
00080   }
00081   else{
00082         if(isFlagSet(&FLAG_4))
00083         { 
00084         #if HasInternalComparator == 1
00085                 configure_VH_comparator_interrupt();
00086         #else
00087                 configure_VH_gpio_interrupt();
00088         #endif
00089             
00090             erase_flags_memory();
00091             setFlag(&FLAG_2);
00092             restore();
00093      }
00094   }
00095 }
00096 
00097 void Save_RAM_Regs(){  
00098     //Copy the peripheral registers to RAM
00099     for(n=0; n<No_Of_4B_Peripheral_Reg;n++){
00100         REG_Array_4B[n] = *(unsigned int*)REG_Addresses_4B[n];
00101     }
00102     for(n=0; n<No_Of_1B_Peripheral_Reg;n++){
00103         REG_Array_1B[n] = *(unsigned int*)REG_Addresses_1B[n];
00104     }
00105     
00106     //copy all the ram to flash
00107     copyRamToFlash();
00108 }
00109 
00110 void Restore_Regs(){ 
00111     //Restore peripheral registers from RAM, After the ram content was copied back from flash, after a restore
00112     for(n=0; n<No_Of_4B_Peripheral_Reg; n++){
00113         *(unsigned int*) REG_Addresses_4B[n] = REG_Array_4B[n];
00114     }
00115     
00116     for(i=0; i<No_Of_1B_Peripheral_Reg; i++){
00117         *(unsigned char*) REG_Addresses_1B[i] = REG_Array_1B[i];
00118     }
00119 }
00120 
00121 void hibernate(volatile unsigned int Rsp, volatile unsigned int Rlr, volatile unsigned int Rpc){
00122     
00123     if(isFlagSet(&FLAG_2)&& isFlagSet(&FLAG_3) && isFlagSet(&FLAG_4))  // Enter this only after complete shut down
00124     {
00125       erase_flags_memory();                                                     // Erase flash sector used to save the flags 
00126             setFlag(&FLAG_1);
00127             setFlag(&FLAG_4);
00128    }
00129     
00130         if(isFlagSet(&FLAG_2))
00131     { 
00132             // Hibernate procedure           
00133       __disable_irq();     // Disable interrupts
00134     
00135             //save the core registers
00136             CoreReg_SP = Rsp;      // 40 for hibernate function 38 otherwsie
00137             CoreReg_LR = Rlr;      // 34 for hibernate function 2C otherwise
00138             CoreReg_PC = Rpc;      // 38 for hibernate function 30 otherwise
00139         
00140       
00141             #if HasInternalComparator == 1
00142                 Save_RAM_Regs();
00143 
00144                 setFlag(&FLAG_3);
00145                 setFlag(&FLAG_4);
00146             
00147                 Comparator_Setup();
00148                 configure_VH_comparator_interrupt();
00149             #else
00150             setFlag(getFlag_3());
00151             setFlag(getFlag_4());
00152             
00153       Save_RAM_Regs();
00154                 configure_VH_gpio_interrupt();
00155             #endif
00156                                         
00157       __enable_irq();     // Enable interrupts
00158                                 
00159       Enter_LLS();        // Enter LLS mode
00160         }
00161 }
00162 
00163 void restore(){
00164     // Restore procedure
00165     __disable_irq();     // Disable interrupts
00166  
00167     erase_flags_memory();
00168     setFlag(&FLAG_2); 
00169 
00170     //Restore peripheral registers  
00171     Restore_Regs();
00172   
00173     //Restore RAM
00174   FLASH_ptr_4B = (unsigned int*) (flash_ramSection_start);       
00175   RAM_ptr      = (unsigned int*) (RAM_Start);
00176     
00177     //Copy RAM until where the pointers and loop variables are stored
00178     //divide it by 4 because the copy is done word by word but byte by byte
00179   for(n=0; n<(Fixed_Add_Vars_Offset/4); n++){                                
00180         *(RAM_ptr + n) = *(FLASH_ptr_4B + n);
00181     }   
00182     
00183   //skip the Core reg and fixed address variables
00184     FLASH_ptr_4B = (unsigned int*)(flash_ramSection_start +Fixed_Add_Vars_Offset+ Fixed_Add_Vars_Size);
00185     RAM_ptr = (unsigned int*)(RAM_Start +Fixed_Add_Vars_Offset+ Fixed_Add_Vars_Size); 
00186     
00187   //copy the rest of the RAM
00188     //(RAM_Size-Fixed_Add_Vars_Offset-Fixed_Add_Vars_Size) is the siz eof the rest of the ram that have to be copied
00189     //divide it by 4 because the copy is done word by word but byte by byte
00190      for(n=1; n<(RAM_Size-Fixed_Add_Vars_Offset-Fixed_Add_Vars_Size)/4; n++){                                
00191         *(RAM_ptr + n) = *(FLASH_ptr_4B + n);
00192   }
00193      
00194   //copy the 3 core registers from flash o ram
00195     CoreReg_SP=*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset+0x10);
00196     CoreReg_LR=*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset+0x14);
00197     CoreReg_PC=*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset+0x18);
00198     
00199     #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
00200                                                                 //otherwise, their value has to be unchanged, there is no need for restore
00201         FLAG_1 =*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset);
00202         FLAG_2 =*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset +0x4);
00203         FLAG_3 =*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset +0x8);
00204         FLAG_4 =*(unsigned int*)(flash_ramSection_start+Fixed_Add_Vars_Offset +0xC);
00205     #else
00206         configure_VH_gpio_interrupt();
00207     #endif  
00208                     
00209   __enable_irq();     // Enable interrupts 
00210                         
00211   asm_restore();         // Restore the SP                        
00212   _LR = CoreReg_LR;    // Restore the LR                       
00213   _PC = CoreReg_PC;    // Restore the PC
00214 }
00215 
00216 //use to check if you recover from a sleep without power loss
00217 //is so, don't restore, and just set the VH interrupt
00218 void recovery_no_power_loss(){
00219     
00220         if(isFlagSet(getFlag_3())){   // Enter after hibernation with no power loss                        
00221             #if HasInternalComparator == 1
00222                 configure_VH_comparator_interrupt();
00223             #else
00224                 configure_VH_gpio_interrupt();
00225             #endif
00226             
00227             erase_flags_memory();  // Erase flash sector used to save the flags 
00228             setFlag(getFlag_2());
00229             
00230       __enable_irq();     // Enable interrupts
00231     }
00232 }
00233 extern "C" volatile unsigned int* getFlag_1(){
00234     return &FLAG_1;
00235 }
00236 
00237 extern "C" volatile unsigned int* getFlag_2(){
00238     return &FLAG_2;
00239 }
00240 
00241 extern "C" volatile unsigned int* getFlag_3(){
00242     return &FLAG_3;
00243 }
00244 
00245 extern "C" volatile unsigned int* getFlag_4(){
00246     return &FLAG_4;
00247 }
00248 
00249