@@ -119,13 +119,36 @@ STATIC void GPIOA2IntHandler (void);
119119STATIC void GPIOA3IntHandler (void );
120120STATIC void EXTI_Handler (uint port );
121121STATIC void pin_obj_configure (const pin_obj_t * self );
122+ STATIC void pin_get_hibernate_pin_and_idx (const pin_obj_t * self , uint * wake_pin , uint * idx );
122123STATIC void pin_extint_enable (mp_obj_t self_in );
123124STATIC void pin_extint_disable (mp_obj_t self_in );
124125
126+ /******************************************************************************
127+ DEFINE CONSTANTS
128+ ******************************************************************************/
129+ #define PYBPIN_NUM_WAKE_PINS (6)
130+ #define PYBPIN_WAKES_NOT (-1)
131+
132+ /******************************************************************************
133+ DEFINE TYPES
134+ ******************************************************************************/
135+ typedef struct {
136+ bool active ;
137+ int8_t lpds ;
138+ int8_t hib ;
139+ } pybpin_wake_pin_t ;
140+
125141/******************************************************************************
126142DECLARE PRIVATE DATA
127143******************************************************************************/
128144STATIC const mp_cb_methods_t pin_cb_methods ;
145+ STATIC pybpin_wake_pin_t pybpin_wake_pin [PYBPIN_NUM_WAKE_PINS ] =
146+ { {.active = false, .lpds = PYBPIN_WAKES_NOT , .hib = PYBPIN_WAKES_NOT },
147+ {.active = false, .lpds = PYBPIN_WAKES_NOT , .hib = PYBPIN_WAKES_NOT },
148+ {.active = false, .lpds = PYBPIN_WAKES_NOT , .hib = PYBPIN_WAKES_NOT },
149+ {.active = false, .lpds = PYBPIN_WAKES_NOT , .hib = PYBPIN_WAKES_NOT },
150+ {.active = false, .lpds = PYBPIN_WAKES_NOT , .hib = PYBPIN_WAKES_NOT },
151+ {.active = false, .lpds = PYBPIN_WAKES_NOT , .hib = PYBPIN_WAKES_NOT } } ;
129152
130153/******************************************************************************
131154 DEFINE PUBLIC FUNCTIONS
@@ -248,14 +271,83 @@ STATIC void pin_obj_configure (const pin_obj_t *self) {
248271 MAP_PinConfigSet (self -> pin_num , self -> strength , self -> type );
249272}
250273
274+ STATIC void pin_get_hibernate_pin_and_idx (const pin_obj_t * self , uint * hib_pin , uint * idx ) {
275+ // pin_num is actually : (package_pin - 1)
276+ switch (self -> pin_num ) {
277+ case 56 : // GPIO2
278+ * hib_pin = PRCM_HIB_GPIO2 ;
279+ * idx = 0 ;
280+ break ;
281+ case 58 : // GPIO4
282+ * hib_pin = PRCM_HIB_GPIO4 ;
283+ * idx = 1 ;
284+ break ;
285+ case 3 : // GPIO13
286+ * hib_pin = PRCM_HIB_GPIO13 ;
287+ * idx = 2 ;
288+ break ;
289+ case 7 : // GPIO17
290+ * hib_pin = PRCM_HIB_GPIO17 ;
291+ * idx = 3 ;
292+ break ;
293+ case 1 : // GPIO11
294+ * hib_pin = PRCM_HIB_GPIO11 ;
295+ * idx = 4 ;
296+ break ;
297+ case 16 : // GPIO24
298+ * hib_pin = PRCM_HIB_GPIO24 ;
299+ * idx = 5 ;
300+ break ;
301+ default :
302+ * idx = 0xFF ;
303+ break ;
304+ }
305+ }
306+
251307STATIC void pin_extint_enable (mp_obj_t self_in ) {
252- pin_obj_t * self = self_in ;
253- MAP_GPIOIntClear (self -> port , self -> bit );
254- MAP_GPIOIntEnable (self -> port , self -> bit );
308+ const pin_obj_t * self = self_in ;
309+ uint hib_pin , idx ;
310+
311+ pin_get_hibernate_pin_and_idx (self , & hib_pin , & idx );
312+ if (idx < PYBPIN_NUM_WAKE_PINS ) {
313+ if (pybpin_wake_pin [idx ].lpds != PYBPIN_WAKES_NOT ) {
314+ // enable GPIO as a wake source during LPDS
315+ MAP_PRCMLPDSWakeUpGPIOSelect (idx , pybpin_wake_pin [idx ].lpds );
316+ MAP_PRCMLPDSWakeupSourceEnable (PRCM_LPDS_GPIO );
317+ }
318+
319+ if (pybpin_wake_pin [idx ].hib != PYBPIN_WAKES_NOT ) {
320+ // enable GPIO as a wake source during hibernate
321+ MAP_PRCMHibernateWakeUpGPIOSelect (hib_pin , pybpin_wake_pin [idx ].hib );
322+ MAP_PRCMHibernateWakeupSourceEnable (hib_pin );
323+ }
324+ else {
325+ MAP_PRCMHibernateWakeupSourceDisable (hib_pin );
326+ }
327+ }
328+ // if idx is invalid, the the pin supports active_idle interrupts for sure
329+ if (idx >= PYBPIN_NUM_WAKE_PINS || pybpin_wake_pin [idx ].active ) {
330+ MAP_GPIOIntClear (self -> port , self -> bit );
331+ MAP_GPIOIntEnable (self -> port , self -> bit );
332+ }
255333}
256334
257335STATIC void pin_extint_disable (mp_obj_t self_in ) {
258- pin_obj_t * self = self_in ;
336+ const pin_obj_t * self = self_in ;
337+ uint hib_pin , idx ;
338+
339+ pin_get_hibernate_pin_and_idx (self , & hib_pin , & idx );
340+ if (idx < PYBPIN_NUM_WAKE_PINS ) {
341+ if (pybpin_wake_pin [idx ].lpds != PYBPIN_WAKES_NOT ) {
342+ // disable GPIO as a wake source during LPDS
343+ MAP_PRCMLPDSWakeupSourceDisable (PRCM_LPDS_GPIO );
344+ }
345+ if (pybpin_wake_pin [idx ].hib != PYBPIN_WAKES_NOT ) {
346+ // disable GPIO as a wake source during hibernate
347+ MAP_PRCMHibernateWakeupSourceDisable (hib_pin );
348+ }
349+ }
350+ // not need to check for the active flag, it's safe to disable it anyway
259351 MAP_GPIOIntDisable (self -> port , self -> bit );
260352}
261353
@@ -534,35 +626,20 @@ STATIC mp_obj_t pin_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map
534626 nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , mpexception_value_invalid_arguments ));
535627 }
536628
537- if (args [4 ].u_int & PYB_PWR_MODE_LPDS ) {
538- uint wake_pin ;
539- uint wake_mode ;
540- // pin_num is actually : (package_pin - 1)
541- switch (self -> pin_num ) {
542- case 56 : // GPIO2
543- wake_pin = PRCM_LPDS_GPIO2 ;
544- break ;
545- case 58 : // GPIO4
546- wake_pin = PRCM_LPDS_GPIO4 ;
547- break ;
548- case 3 : // GPIO13
549- wake_pin = PRCM_LPDS_GPIO13 ;
550- break ;
551- case 7 : // GPIO17
552- wake_pin = PRCM_LPDS_GPIO17 ;
553- break ;
554- case 1 : // GPIO11
555- wake_pin = PRCM_LPDS_GPIO11 ;
556- break ;
557- case 16 : // GPIO24
558- wake_pin = PRCM_LPDS_GPIO24 ;
559- break ;
560- default :
561- nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , mpexception_value_invalid_arguments ));
562- break ;
563- }
629+ uint pwrmode = args [4 ].u_int ;
630+ if (pwrmode > (PYB_PWR_MODE_ACTIVE | PYB_PWR_MODE_LPDS | PYB_PWR_MODE_HIBERNATE )) {
631+ goto invalid_args ;
632+ }
564633
565- // intmodes are different in LDPS
634+ // get the wake info from this pin
635+ uint hib_pin , idx ;
636+ pin_get_hibernate_pin_and_idx ((const pin_obj_t * )self , & hib_pin , & idx );
637+ if (pwrmode & PYB_PWR_MODE_LPDS ) {
638+ if (idx >= PYBPIN_NUM_WAKE_PINS ) {
639+ goto invalid_args ;
640+ }
641+ // wake modes are different in LDPS
642+ uint wake_mode ;
566643 switch (intmode ) {
567644 case GPIO_FALLING_EDGE :
568645 wake_mode = PRCM_LPDS_FALL_EDGE ;
@@ -577,44 +654,32 @@ STATIC mp_obj_t pin_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map
577654 wake_mode = PRCM_LPDS_HIGH_LEVEL ;
578655 break ;
579656 default :
580- nlr_raise ( mp_obj_new_exception_msg ( & mp_type_ValueError , mpexception_value_invalid_arguments )) ;
657+ goto invalid_args ;
581658 break ;
582659 }
583660
584- // enable GPIO as a wake source during LPDS
585- MAP_PRCMLPDSWakeUpGPIOSelect ( wake_pin , wake_mode );
586- MAP_PRCMLPDSWakeupSourceEnable ( PRCM_LPDS_GPIO ) ;
587- }
661+ // first clear the lpds value from all wake-able pins
662+ for ( uint i = 0 ; i < PYBPIN_NUM_WAKE_PINS ; i ++ ) {
663+ pybpin_wake_pin [ i ]. lpds = PYBPIN_WAKES_NOT ;
664+ }
588665
589- if (args [4 ].u_int & PYB_PWR_MODE_HIBERNATE ) {
590- uint wake_pin ;
591- uint wake_mode ;
592- // pin_num is actually : (package_pin - 1)
593- switch (self -> pin_num ) {
594- case 56 : // GPIO2
595- wake_pin = PRCM_HIB_GPIO2 ;
596- break ;
597- case 58 : // GPIO4
598- wake_pin = PRCM_HIB_GPIO4 ;
599- break ;
600- case 3 : // GPIO13
601- wake_pin = PRCM_HIB_GPIO13 ;
602- break ;
603- case 7 : // GPIO17
604- wake_pin = PRCM_HIB_GPIO17 ;
605- break ;
606- case 1 : // GPIO11
607- wake_pin = PRCM_HIB_GPIO11 ;
608- break ;
609- case 16 : // GPIO24
610- wake_pin = PRCM_HIB_GPIO24 ;
611- break ;
612- default :
613- nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , mpexception_value_invalid_arguments ));
614- break ;
666+ // enable this pin as a wake-up source during LPDS
667+ pybpin_wake_pin [idx ].lpds = wake_mode ;
668+ }
669+ else {
670+ // this pin was the previous LPDS wake source, so disable it completely
671+ if (pybpin_wake_pin [idx ].lpds != PYBPIN_WAKES_NOT ) {
672+ MAP_PRCMLPDSWakeupSourceDisable (PRCM_LPDS_GPIO );
615673 }
674+ pybpin_wake_pin [idx ].lpds = PYBPIN_WAKES_NOT ;
675+ }
616676
617- // intmodes are bit different in hibernate
677+ if (pwrmode & PYB_PWR_MODE_HIBERNATE ) {
678+ if (idx >= PYBPIN_NUM_WAKE_PINS ) {
679+ goto invalid_args ;
680+ }
681+ // wake modes are different in hibernate
682+ uint wake_mode ;
618683 switch (intmode ) {
619684 case GPIO_FALLING_EDGE :
620685 wake_mode = PRCM_HIB_FALL_EDGE ;
@@ -629,26 +694,44 @@ STATIC mp_obj_t pin_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map
629694 wake_mode = PRCM_HIB_HIGH_LEVEL ;
630695 break ;
631696 default :
632- nlr_raise ( mp_obj_new_exception_msg ( & mp_type_ValueError , mpexception_value_invalid_arguments )) ;
697+ goto invalid_args ;
633698 break ;
634699 }
635700
636- // enable GPIO as a wake source during hibernate
637- MAP_PRCMHibernateWakeUpGPIOSelect (wake_pin , wake_mode );
638- MAP_PRCMHibernateWakeupSourceEnable (wake_pin );
701+ // enable this pin as wake-up source during hibernate
702+ pybpin_wake_pin [idx ].hib = wake_mode ;
703+ }
704+ else {
705+ pybpin_wake_pin [idx ].hib = PYBPIN_WAKES_NOT ;
639706 }
640707
641708 // we need to update the callback atomically, so we disable the
642709 // interrupt before we update anything.
643710 pin_extint_disable (self );
644- // register the interrupt
645- pin_extint_register ((pin_obj_t * )self , intmode , priority );
646- // create the callback
711+ if (pwrmode & PYB_PWR_MODE_ACTIVE ) {
712+ // register the interrupt
713+ pin_extint_register ((pin_obj_t * )self , intmode , priority );
714+ if (idx < PYBPIN_NUM_WAKE_PINS ) {
715+ pybpin_wake_pin [idx ].active = true;
716+ }
717+ }
718+ else if (idx < PYBPIN_NUM_WAKE_PINS ) {
719+ pybpin_wake_pin [idx ].active = false;
720+ }
721+
722+ // all checks have passed, now we can create the callback
647723 self -> callback = mpcallback_new (self , args [1 ].u_obj , & pin_cb_methods );
724+ if (pwrmode & PYB_PWR_MODE_LPDS ) {
725+ pybsleep_set_gpio_lpds_callback (self -> callback );
726+ }
727+
648728 // enable the interrupt just before leaving
649729 pin_extint_enable (self );
650730 }
651731 return self -> callback ;
732+
733+ invalid_args :
734+ nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , mpexception_value_invalid_arguments ));
652735}
653736STATIC MP_DEFINE_CONST_FUN_OBJ_KW (pin_callback_obj , 1 , pin_callback );
654737
0 commit comments