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: FreescaleIAP mbed
Revision 0:57ca0bfdc2d8, committed 2017-09-01
- Comitter:
- BogdanL
- Date:
- Fri Sep 01 14:37:15 2017 +0000
- Commit message:
- First version of the Hibernus Library. V1.0
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FreescaleIAP.lib Fri Sep 01 14:37:15 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/Sissors/code/FreescaleIAP/#ab8a833a25eb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/asm_restore.s Fri Sep 01 14:37:15 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_restore +asm_restore + + 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/config.cpp Fri Sep 01 14:37:15 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
+ */
+#include "config.h"
+#include "hibernus.h"
+
+volatile unsigned int dummyread; // Variable used for serialization
+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
+ dummyread = CMP0->SCR; // Read back for serialization
+
+
+ if(isFlagSet(getFlag_2())&& isFlagSet(getFlag_3()) && isFlagSet(getFlag_4())){ // Enter this only after complete shut down
+ erase_flags_memory(); // Erase flash sector used to save the flags
+ setFlag(getFlag_1());
+ setFlag(getFlag_4());
+ }
+
+ if(isFlagSet(getFlag_2())){ // Hibernate procedure
+ __disable_irq(); // Disable interrupts
+
+ volatile unsigned int sp1=(_SP+0x28), lr1= *(unsigned int*)(_SP+0x1C), pc1=*(unsigned int*)(_SP+0x20);
+ // 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;
+
+ Save_RAM_Regs();
+
+ setFlag(getFlag_3());
+ setFlag(getFlag_4());
+
+ Comparator_Setup();
+ 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
+
+ __enable_irq(); // Enable interrupts
+
+ Enter_LLS(); // Enter LLS mode
+ }
+}
+
+extern "C" void LLW_IRQHandler(){
+
+ CMP0->SCR |= CMP_SCR_CFF_MASK | CMP_SCR_CFR_MASK; // Clear CMP0 flags
+ dummyread = CMP0->SCR; // Read back for serialization
+ NVIC_ClearPendingIRQ(CMP0_IRQn); // Clear pending CMP0 interrupt so that the CMP_IRQ is not entered
+
+ if(isFlagSet(getFlag_3())){ // Enter after hibernation with no power loss
+ 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
+
+ erase_flags_memory(); // Erase flash sector used to save the flags
+ setFlag(getFlag_2());
+
+ __enable_irq(); // Enable interrupts
+ }
+}
+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
+ dummyread = 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 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_flash_secors_for_RAM(){
+ int i;
+ for(i = 2; i<= 2+ramToFlash_sectors_number; i++) //start the erase from the 3rd last block, the first 2 are used for flags and peripheral registers
+ erase_sector(flash_end-i*sector_Size);
+}
+
+void erase_flags_memory(){
+ if(!SaveFlagsInFlash) {
+ *getFlag_1() = Flag_erase;
+ *getFlag_2() = Flag_erase;
+ *getFlag_3() = Flag_erase;
+ *getFlag_4() = Flag_erase;
+ }else{
+ erase_sector(Flash_Flags_Sector_Start);
+ }
+}
+
+void copyRamToFlash(){
+ // Erase flash sectors o save the RAM content
+ erase_flash_secors_for_RAM();
+ program_flash(flash_ramSection_start, (char*) RAM_1_Address, RAM_Size); // Copy all the RAM to flash
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/config.h Fri Sep 01 14:37:15 2017 +0000
@@ -0,0 +1,111 @@
+/** 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 "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_1_Address 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 19
+#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
+ };
+
+
+extern "C" void FLEX_INT0_IRQHandler(void);
+extern "C" void FLEX_INT1_IRQHandler(void);
+
+#if HasInternalComparator == 1
+ void configure_VH_comparator_interrupt(void);
+#else
+ void configure_VH_gpio_interrupt(void);
+ void configure_VR_gpio_interrupt(void);
+#endif
+
+void Comparator_Setup(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 14:37:15 2017 +0000
@@ -0,0 +1,182 @@
+/** 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))) = Flash_Flags_Sector_Start;
+volatile unsigned int FLAG_2 __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+ 0x4))) = Flash_Flags_Sector_Start + 0x4;
+volatile unsigned int FLAG_3 __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+ 0x8))) = Flash_Flags_Sector_Start + 0x8;
+volatile unsigned int FLAG_4 __attribute__((at(RAM_1_Address+Fixed_Add_Vars_Offset+ 0xC))) = Flash_Flags_Sector_Start + 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)));;
+
+Serial pc1(USBTX, USBRX);
+void Hibernus(){
+ #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 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
+ #if HasInternalComparator == 1
+ configure_VH_comparator_interrupt();
+ #else
+ configure_VH_gpio_interrupt();
+ #endif
+
+ __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 14:37:15 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 14:37:15 2017 +0000
@@ -0,0 +1,46 @@
+/** 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(PTB11);
+DigitalOut bit1(PTA5);
+DigitalOut bit2(PTA7);
+DigitalOut bit3(PTA6);
+
+Serial pc(USBTX, USBRX);
+
+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 14:37:15 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/a330f0fddbec \ No newline at end of file