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
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 }
Generated on Thu Jul 28 2022 06:18:24 by 1.7.2