From e44c7f40c297c76ed6d457cb85977f01742cab8a Mon Sep 17 00:00:00 2001 From: Baoshi <baoshi@pancake.local> Date: Sat, 23 Sep 2023 14:00:11 +0800 Subject: [PATCH] Demonstrate proper configuration of GPIO prior to standby. --- examples/standby_autowake/README.md | 2 +- examples/standby_autowake/standby_autowake.c | 47 ++++++++++++----- examples/standby_btn/README.md | 18 ++++--- examples/standby_btn/standby_btn.c | 54 ++++++++++++++------ 4 files changed, 84 insertions(+), 37 deletions(-) diff --git a/examples/standby_autowake/README.md b/examples/standby_autowake/README.md index 65e1f12..2fe3d12 100644 --- a/examples/standby_autowake/README.md +++ b/examples/standby_autowake/README.md @@ -6,7 +6,7 @@ This example serves to show how to put the CH32V003 into its lowest power state Power consumption should be around 10uA. -GPIO must be put into input pull-up / pull-down mode to have standby current reduced. +Refer to the standby_btn example for GPIO settings. Based on the groundwork of Marek M. diff --git a/examples/standby_autowake/standby_autowake.c b/examples/standby_autowake/standby_autowake.c index d08effb..9e41489 100644 --- a/examples/standby_autowake/standby_autowake.c +++ b/examples/standby_autowake/standby_autowake.c @@ -3,12 +3,6 @@ #include "ch32v003fun.h" #include <stdio.h> -/* somehow this ISR won't get called?? -void AWU_IRQHandler( void ) __attribute__((interrupt)); -void AWU_IRQHandler( void ) { - GPIOD->OUTDR ^= (1 << 4); -} -*/ int main() { @@ -23,12 +17,41 @@ int main() // Set all GPIOs to input pull up RCC->APB2PCENR |= RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD; - GPIOA->CFGLR = 0b10001000100010001000100010001000; - GPIOA->OUTDR = 0b11111111; - GPIOC->CFGLR = 0b10001000100010001000100010001000; - GPIOC->OUTDR = 0b11111111; - GPIOD->CFGLR = 0b10001000100010001000100010001000; - GPIOD->OUTDR = 0b11111111; + // GPIOA: Set to output + GPIOA->CFGLR = (GPIO_CNF_IN_PUPD<<(4*2)) | + (GPIO_CNF_IN_PUPD<<(4*1)); + GPIOA->BSHR = GPIO_BSHR_BS2 | GPIO_BSHR_BR1; + GPIOC->CFGLR = (GPIO_CNF_IN_PUPD<<(4*7)) | + (GPIO_CNF_IN_PUPD<<(4*6)) | + (GPIO_CNF_IN_PUPD<<(4*5)) | + (GPIO_CNF_IN_PUPD<<(4*4)) | + (GPIO_CNF_IN_PUPD<<(4*3)) | + (GPIO_CNF_IN_PUPD<<(4*2)) | + (GPIO_CNF_IN_PUPD<<(4*1)) | + (GPIO_CNF_IN_PUPD<<(4*0)); + GPIOC->BSHR = GPIO_BSHR_BS7 | + GPIO_BSHR_BS6 | + GPIO_BSHR_BS5 | + GPIO_BSHR_BS4 | + GPIO_BSHR_BS3 | + GPIO_BSHR_BS2 | + GPIO_BSHR_BS1 | + GPIO_BSHR_BS0; + GPIOD->CFGLR = (GPIO_CNF_IN_PUPD<<(4*7)) | + (GPIO_CNF_IN_PUPD<<(4*6)) | + (GPIO_CNF_IN_PUPD<<(4*5)) | + (GPIO_CNF_IN_PUPD<<(4*4)) | + (GPIO_CNF_IN_PUPD<<(4*3)) | + (GPIO_CNF_IN_PUPD<<(4*2)) | + (GPIO_CNF_IN_PUPD<<(4*0)); + GPIOD->BSHR = GPIO_BSHR_BS7 | + GPIO_BSHR_BS6 | + GPIO_BSHR_BS5 | + GPIO_BSHR_BS4 | + GPIO_BSHR_BS3 | + GPIO_BSHR_BS2 | + GPIO_BSHR_BS0; + // enable power interface module clock RCC->APB1PCENR |= RCC_APB1Periph_PWR; diff --git a/examples/standby_btn/README.md b/examples/standby_btn/README.md index 0e1a067..4b6421c 100644 --- a/examples/standby_btn/README.md +++ b/examples/standby_btn/README.md @@ -4,19 +4,21 @@ This example serves to show how to put the CH32V003 into its lowest power state (standby) and have it wake with a button press. -Power consumption should be around 10uA. +Power consumption should be around 9uA. To enter 10uA standby mode you must perform these steps: -1. Put all GPIOs in input mode (thus no output state can be preserved). -2. Enable AFIO clock and set AFIO_EXTICR to the wakeup channel. -3. Configure EXTI event. -4. Set PWR_CTLR_PDDS bit in PWR_CTLR (Setting PWREN in RCC_APB1PCENR is not required hum?) -5. Set SLEEPDEEP bit in PFIC_SCTLR -6. Call __WFE() to enter standby mode. +1. GPIOs other than the wake up pin can be set to either input or output mode (see notes). +2. Set GPIO(s) for wake up to input mode with appropriate pull up/down. +3. Enable AFIO clock and set AFIO_EXTICR to the wakeup channel. +4. Configure EXTI event. +5. Set PWR_CTLR_PDDS bit in PWR_CTLR (Setting PWREN in RCC_APB1PCENR is not required hum?) +6. Set SLEEPDEEP bit in PFIC_SCTLR +7. Call __WFE() to enter standby mode. Note: -* All GPIOs must be in input pull-up or pull-down mode before entering standby. Input floating mode result in 100uA current. +* GPIOs in output mode will retain state during standby. +* GPIO if set to input mode must have internal or external pulling resistor. Floating input pin will cause 100uA standby current. * Once CH32V003 enters standby mode, it won't respond to any SWDIO command, therefor cannot be reprogrammed. User must provide a way to have the processor stay awake for reprogramming, e.g. some delay at startup. * Debug circuitry will consume power. If minichlink terminal is active (including immediately after flashing), standby current will stay around 1.2mA until power cycle. diff --git a/examples/standby_btn/standby_btn.c b/examples/standby_btn/standby_btn.c index 658e057..be6c99b 100644 --- a/examples/standby_btn/standby_btn.c +++ b/examples/standby_btn/standby_btn.c @@ -3,38 +3,60 @@ #include "ch32v003fun.h" #include <stdio.h> -void EXTI7_0_IRQHandler( void ) __attribute__((interrupt)); -void EXTI7_0_IRQHandler( void ) { - //GPIOD->OUTDR ^= (1 << 4); -} - - int main() { SystemInit(); - + // This delay gives us some time to reprogram the device. // Otherwise if the device enters standby mode we can't // program it any more. Delay_Ms(5000); printf("\n\nlow power example\n\n"); - - // Set all GPIOs to input pull up RCC->APB2PCENR |= RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD; - GPIOA->CFGLR = 0b10001000100010001000100010001000; - GPIOA->OUTDR = 0b11111111; - GPIOC->CFGLR = 0b10001000100010001000100010001000; - GPIOC->OUTDR = 0b11111111; - GPIOD->CFGLR = 0b10001000100010001000100010001000; - GPIOD->OUTDR = 0b00000100; + // GPIOA: Set to output + GPIOA->CFGLR = ((GPIO_CNF_OUT_PP | GPIO_Speed_2MHz)<<(4*2)) | + ((GPIO_CNF_OUT_PP | GPIO_Speed_2MHz)<<(4*1)); + GPIOA->BSHR = GPIO_BSHR_BS2 | GPIO_BSHR_BR1; + // GPIOC: Set to input with mixed pull-up / pull-down + GPIOC->CFGLR = (GPIO_CNF_IN_PUPD<<(4*7)) | + (GPIO_CNF_IN_PUPD<<(4*6)) | + (GPIO_CNF_IN_PUPD<<(4*5)) | + (GPIO_CNF_IN_PUPD<<(4*4)) | + (GPIO_CNF_IN_PUPD<<(4*3)) | + (GPIO_CNF_IN_PUPD<<(4*2)) | + (GPIO_CNF_IN_PUPD<<(4*1)) | + (GPIO_CNF_IN_PUPD<<(4*0)); + GPIOC->BSHR = GPIO_BSHR_BS7 | + GPIO_BSHR_BR6 | + GPIO_BSHR_BS5 | + GPIO_BSHR_BR4 | + GPIO_BSHR_BS3 | + GPIO_BSHR_BR2 | + GPIO_BSHR_BS1 | + GPIO_BSHR_BR0; + // GPIOD: D2 set to input pull-up + GPIOD->CFGLR = (GPIO_CNF_IN_PUPD<<(4*7)) | + (GPIO_CNF_IN_PUPD<<(4*6)) | + (GPIO_CNF_IN_PUPD<<(4*5)) | + (GPIO_CNF_IN_PUPD<<(4*4)) | + (GPIO_CNF_IN_PUPD<<(4*3)) | + (GPIO_CNF_IN_PUPD<<(4*2)) | + (GPIO_CNF_IN_PUPD<<(4*0)); + GPIOD->BSHR = GPIO_BSHR_BR7 | + GPIO_BSHR_BS6 | + GPIO_BSHR_BR5 | + GPIO_BSHR_BS4 | + GPIO_BSHR_BR3 | + GPIO_BSHR_BS2 | + GPIO_BSHR_BR0; // AFIO is needed for EXTI RCC->APB2PCENR |= RCC_AFIOEN; // assign pin 2 interrupt from portD (0b11) to EXTI channel 2 - AFIO->EXTICR |= (uint32_t)(0b11 << (2 * 2)); + AFIO->EXTICR |= (uint32_t)(0b11 << (2*2)); // enable line2 interrupt event EXTI->EVENR |= EXTI_Line2; -- GitLab