Skip to content

Commit

Permalink
Demonstrate proper configuration of GPIO prior to standby.
Browse files Browse the repository at this point in the history
  • Loading branch information
Baoshi committed Sep 23, 2023
1 parent f62719f commit e44c7f4
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 37 deletions.
2 changes: 1 addition & 1 deletion examples/standby_autowake/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
47 changes: 35 additions & 12 deletions examples/standby_autowake/standby_autowake.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand All @@ -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;
Expand Down
18 changes: 10 additions & 8 deletions examples/standby_btn/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
54 changes: 38 additions & 16 deletions examples/standby_btn/standby_btn.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit e44c7f4

Please sign in to comment.