diff --git a/epicardium/modules/pmic.c b/epicardium/modules/pmic.c index af336fe749491b1fd14868a05df8b5796c056101..33022bcb22e7972a110f3420debf26121069b71d 100644 --- a/epicardium/modules/pmic.c +++ b/epicardium/modules/pmic.c @@ -10,6 +10,9 @@ #include "mxc_sys.h" #include "mxc_pins.h" #include "adc.h" +#include "simo.h" +#include "lp.h" +#include "max86150.h" #include "FreeRTOS.h" #include "task.h" @@ -289,6 +292,150 @@ static void vPmicTimerCb(TimerHandle_t xTimer) xTaskNotify(pmic_task_id, PMIC_NOTIFY_MONITOR, eSetBits); } +uint32_t old_clkcn; + +void switchToHIRC(void) { + old_clkcn = MXC_GCR->clkcn; + MXC_GCR->clkcn &= ~(MXC_S_GCR_CLKCN_PSC_DIV128); + MXC_GCR->clkcn |= MXC_S_GCR_CLKCN_PSC_DIV4; + MXC_GCR->clkcn |= MXC_F_GCR_CLKCN_HIRC_EN; + + MXC_SETFIELD(MXC_GCR->clkcn, MXC_F_GCR_CLKCN_CLKSEL, MXC_S_GCR_CLKCN_CLKSEL_HIRC); + + // Disable unused clocks + while(!(MXC_GCR->clkcn & MXC_F_GCR_CLKCN_CKRDY)); // Wait for the switch to occur + MXC_GCR->clkcn &= ~(MXC_F_GCR_CLKCN_HIRC96M_EN); + + SystemCoreClockUpdate(); +} + +void deepsleep(void) { + SIMO_setVregO_B(810); // Reduce VCOREB to 0.81v + LP_FastWakeupEnable(); + LP_EnterDeepSleepMode(); + SIMO_setVregO_B(1000); // Restore VCOREB to 1v +} + +uint32_t old_perckcn0, old_perckcn1; +void turnOffClocks(void) +{ + old_perckcn0 = MXC_GCR->perckcn0; + old_perckcn1 = MXC_GCR->perckcn1; + + // Allow the USB Switch to be turned off in deepsleep and backup modes + LP_USBSWLPDisable(); + + // Disable all peripheral clocks except GPIO0 (needed for interrupt wakeup) + MXC_GCR->perckcn0 = 0xFFFFFFFE; + MXC_GCR->perckcn1 = 0xFFFFFFFF; +} + +void turnOnClocks(void) +{ + MXC_GCR->perckcn0 = old_perckcn0; + MXC_GCR->perckcn1 = old_perckcn1; +} + +void gpio_low_power(void) +{ + const gpio_cfg_t pins_low_power[] = { + {PORT_0, PIN_0, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // FLash + {PORT_0, PIN_1, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // Flash + {PORT_0, PIN_2, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // Flash + {PORT_0, PIN_3, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // Flash + {PORT_0, PIN_4, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // Flash + {PORT_0, PIN_5, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // Flash + {PORT_0, PIN_6, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // I2C 3.3V + {PORT_0, PIN_7, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // I2C 3.3V + {PORT_0, PIN_8, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // Motor + {PORT_0, PIN_9, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // UART TX + {PORT_0, PIN_10, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // UART RX + {PORT_0, PIN_11, GPIO_FUNC_IN, GPIO_PAD_PULL_DOWN}, // BMA400 interrupt + // 0, 12: PMIC IRQ + {PORT_0, PIN_13, GPIO_FUNC_IN, GPIO_PAD_NONE}, // BHI160 interrupt, not sure if PP + // 0, 14: PMIC I2C + // 0, 15: PMIC I2C + {PORT_0, PIN_16, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // PMIC AMUX + {PORT_0, PIN_17, GPIO_FUNC_IN, GPIO_PAD_PULL_DOWN}, // SOA GPIO + // 0, 18: ECG AOUT + // 0, 19: 32 kHz + // 0, 20: WB 1 + // 0, 21: WB 2 + // 0, 22: WB 3 + {PORT_0, PIN_23, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // IR-LED + {PORT_0, PIN_24, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // display SS + {PORT_0, PIN_25, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // display MOSI + {PORT_0, PIN_26, GPIO_FUNC_IN, GPIO_PAD_PULL_DOWN}, // SOA GPIO + {PORT_0, PIN_27, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // display SCK + {PORT_0, PIN_28, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // Backlight + // 0, 29: WB 4 + // 0, 30: PMIC power hold + {PORT_0, PIN_31, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // ECG switch + + {PORT_1, PIN_0, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // SDHC + {PORT_1, PIN_1, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // SDHC + {PORT_1, PIN_2, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // SDHC + {PORT_1, PIN_3, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // SDHC + {PORT_1, PIN_4, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // SDHC + {PORT_1, PIN_5, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // SDHC + {PORT_1, PIN_6, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // display RS + {PORT_1, PIN_7, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // Portexpander interrupt + {PORT_1, PIN_8, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // ECG CS TODO: better out high + {PORT_1, PIN_9, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // ECG SDI + {PORT_1, PIN_10, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // ECG SDO + {PORT_1, PIN_11, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // ECG SCK + {PORT_1, PIN_11, GPIO_FUNC_IN, GPIO_PAD_PULL_UP}, // ECG INT + {PORT_1, PIN_13, GPIO_FUNC_IN, GPIO_PAD_NONE}, // PPG Interrupt + {PORT_1, PIN_14, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // LEDs + {PORT_1, PIN_15, GPIO_FUNC_OUT, GPIO_PAD_NONE}, // LEDs + + }; + + const unsigned int num_pins = (sizeof(pins_low_power) / sizeof(gpio_cfg_t)); + int i; + for (i = 0; i < num_pins; i++) { + GPIO_OutClr(&pins_low_power[i]); + GPIO_Config(&pins_low_power[i]); + } + + epic_disp_backlight(0); +} + +void GPIOWAKE_IRQHandler(void) +{ +} + +void powersave(void) +{ + LOG_WARN("pmic", "Powersave"); +#if 1 + max86150_begin(); + max86150_getINT1(); + max86150_getINT2(); + max86150_shutDown(); +#endif + if(MAX77650_setEN_SBB2(0b100)){ + //printf("turn off ok\n"); + LOG_WARN("pmic", "turn off ok"); + } else { + //printf("turn off fail\n"); + LOG_WARN("pmic", "turn off fail"); + } + core1_stop(); + MAX77650_getINT_GLBL(); + gpio_low_power(); + turnOffClocks(); + switchToHIRC(); + __SEV(); + __WFE(); + deepsleep(); + turnOnClocks(); + MXC_GCR->clkcn = old_clkcn; + while(!(MXC_GCR->clkcn & MXC_F_GCR_CLKCN_CKRDY)); // Wait for the switch to occur + SystemCoreClockUpdate(); + if(MAX77650_setEN_SBB2(0b110)) printf("turn on ok\n"); + //while(1); +} void vPmicTask(void *pvParameters) { pmic_task_id = xTaskGetCurrentTaskHandle(); @@ -326,7 +473,12 @@ void vPmicTask(void *pvParameters) if (button_start_tick != 0 && duration > pdMS_TO_TICKS(1000)) { LOG_WARN("pmic", "Poweroff"); - MAX77650_setSFT_RST(0x2); + powersave(); + powersave(); + //while(1); + card10_reset(); + + //MAX77650_setSFT_RST(0x2); } if (reason & PMIC_NOTIFY_IRQ) { diff --git a/lib/card10/card10.c b/lib/card10/card10.c index 306d9f4d7c0ac720145f991072ce61475d3bf528..31b50511530e94218a1d9ed3ba66dcacddfda0ab 100644 --- a/lib/card10/card10.c +++ b/lib/card10/card10.c @@ -29,6 +29,10 @@ const gpio_cfg_t bhi_interrupt_pin = { PORT_0, PIN_13, GPIO_FUNC_IN, GPIO_PAD_PULL_UP }; +static const gpio_cfg_t pwr_hold_pin = { + PORT_0, PIN_30, GPIO_FUNC_OUT, GPIO_PAD_NONE +}; + void card10_init(void) { printf("card10 init...\n"); @@ -41,6 +45,9 @@ void card10_init(void) I2C_Init(MXC_I2C1_BUS0, I2C_FAST_MODE, NULL); GPIO_Init(); + GPIO_Config(&pwr_hold_pin); + GPIO_OutSet(&pwr_hold_pin); + pmic_init(); pmic_set_led(0, 0); diff --git a/lib/card10/pmic.c b/lib/card10/pmic.c index e60cf81ab034cb11f61d64a758a024080ca7ba18..3050496b3a2996241fa5f01f95f10f2d507cd269 100644 --- a/lib/card10/pmic.c +++ b/lib/card10/pmic.c @@ -1,5 +1,6 @@ #include "i2c.h" #include "pmic.h" +#include "lp.h" #include "MAX77650-Arduino-Library.h" #include <stdint.h> #include <stdio.h> @@ -45,7 +46,7 @@ void pmic_init(void) //MAX77650_setTV_SBB2(0b110100); //Set output Voltage of SBB2 to 5.0V MAX77650_setTV_SBB2(0b010010); //Set output Voltage of SBB2 to 3.3V #endif - MAX77650_setADE_SBB2(0b0); //Disable Active Discharge at SBB2 Output + MAX77650_setADE_SBB2(0b1); //Enable Active Discharge at SBB2 Output MAX77650_setEN_SBB2( 0b110); //Enable SBB2 is on irrespective of FPS whenever the on/off controller is in its "On via Software" or "On via On/Off Controller" states @@ -90,10 +91,12 @@ void pmic_init(void) ); NVIC_EnableIRQ((IRQn_Type)MXC_GPIO_GET_IRQ(pmic_interrupt_pin.port)); + LP_EnableGPIOWakeup(&pmic_interrupt_pin); /* Setup power button interrupt */ MAX77650_setINT_M_GLBL(~(MAX77650_INT_nEN_R | MAX77650_INT_nEN_F)); /* Clear existing interrupts */ MAX77650_getINT_GLBL(); + MAX77650_setSBIA_LPM(true); } __attribute__((weak)) void pmic_interrupt_callback(void *_) diff --git a/lib/card10/portexpander.c b/lib/card10/portexpander.c index 52eb88975a660306f540567b55abe56dc53e6151..8145982d90eaf11a1a951e908aa4b2815d5316bd 100644 --- a/lib/card10/portexpander.c +++ b/lib/card10/portexpander.c @@ -179,6 +179,7 @@ uint8_t portexpander_in_get(uint8_t mask) portexpander_read(PE_C_INPUT_PORT, &buf); } + printf("portexpander_in_get(%02x) => %02x => %02x\n", mask, buf, buf & mask); return buf & mask; } diff --git a/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Source/system_max32665.c b/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Source/system_max32665.c index 569913e28af4439a31babb26ab84e558ef1bc7ac..90c4f0a09f17feae9407db920b5e0b3ed2a3c1ce 100644 --- a/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Source/system_max32665.c +++ b/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Source/system_max32665.c @@ -169,7 +169,6 @@ __weak void SystemInit(void) MXC_GPIO0->vssel |= (1UL << 20) | (1UL << 21) | (1UL << 22) | (1UL << 29); // Wristband MXC_GPIO0->vssel |= (1UL << 17) | (1UL << 23) | (1UL << 28); // GPIO to TOP MXC_GPIO0->vssel |= (1UL << 24) | (1UL << 25) | (1UL << 26) | (1UL << 27); // SPI to TOP - MXC_GPIO0->vssel |= (1UL << 31); // ECG Switch MXC_GPIO0->ps |= 0xFFFFFFFF; MXC_GPIO0->pad_cfg1 |= 0xFFFFFFFF; @@ -178,7 +177,7 @@ __weak void SystemInit(void) // All GPIO on port 1 to 1.8 V first MXC_GPIO1->vssel = 0; MXC_GPIO1->vssel |= (1UL << 0) | (1UL << 1) | (1UL << 2) | (1UL << 3) | (1UL << 4) | (1UL << 5); // SDHC - MXC_GPIO1->vssel |= (1 << 6) | (1 << 7); // GPIO to TOP + MXC_GPIO1->vssel |= (1 << 6); // GPIO to TOP MXC_GPIO1->vssel |= (1 << 14) | (1 << 15); // GPIO for RGB LEDs #if BOARD_EVKIT