Help with SHIPHOLD Pressed and Released Events on NPM1300 + STM32L4 + npmx

Hi All, 

I'm currently working with a custom board using the NPM1300 and STM32L4, alongside the npmx drivers. I'm trying to capture both pressed and released events from the SHIPHOLD button, but I'm running into an issue.

If only one of the events is enabled, all works as expected:

  • The NPM1300 drives its interrupt GPIO high.
  • This triggers an interrupt on the STM32L4 (rising edge).
  • In the ISR, I call npmx_core_interrupt(&m_pmic);
  • Then in the main loop, I call npmx_core_proc(&m_pmic);
  • This successfully clears the NPM1300 interrupt and invokes the appropriate callback.

However, when both events are enabled simultaneously:

pmx_core_event_interrupt_enable(&m_pmic, NPMX_EVENT_GROUP_SHIPHOLD, 
                                 NPMX_EVENT_GROUP_SHIPHOLD_PRESSED_MASK | 
                                 NPMX_EVENT_GROUP_SHIPHOLD_RELEASED_MASK);

The first button press works correctly: the interrupt pin goes high, npmx_core_interrupt() is called, followed by npmx_core_proc(), and the callback is triggered as expected.

But after that, the NPM1300 interrupt pin remains high, preventing further interrupts from being registered on the STM32 side (interrupt on rising edge). It seems like the interrupt flag on the PMIC isn't being cleared properly after the first event when both are enabled.

As I understand it, npmx_core_proc() should clear all the pending interrupt flags and report back the mask— is that correct?

I’ve reviewed the one-button example, but it uses gpio_init_callback() instead of the interrupt-handling functions from npmx_core.c, so it’s hard to compare directly.

For reference, here’s my callback and initialization code:


static void button_callback(npmx_instance_t *p_pm, npmx_callback_type_t type, uint8_t mask)
{
    // Toggle LED
    HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin);
}

void configure_pmic()
{
	if (npmx_core_init(&m_pmic, &backend, NULL, false) != NPMX_SUCCESS) {
		// Initialization failed
		while (1) {
			HAL_GPIO_TogglePin(LED_R_GPIO_Port, LED_R_Pin);
			HAL_Delay(200);
		}
	}

	// Ship hold configuration
	npmx_ship_config_t ship_config = {
		.time = NPMX_SHIP_TIME_3008_MS, /* SHPHLD must be held low for 3008 ms to exit from the ship or hibernate mode. */
		.inverted_polarity = false /* Button is active in the LOW state. */
	};

	// Get the ship hold instance
	m_ship_inst = npmx_ship_get(&m_pmic, 0);

	// Set the configuration
	npmx_ship_config_set(m_ship_inst, &ship_config);

	// Register button_callback to NPMX_CALLBACK_TYPE_EVENT_SHIPHOLD event
	npmx_core_register_cb(&m_pmic, button_callback, NPMX_CALLBACK_TYPE_EVENT_SHIPHOLD);

	// Inti PMIC GPIO01 as an interrupt output pin
	m_gpio_init = npmx_gpio_get(&m_pmic, 1);
	npmx_gpio_mode_set(m_gpio_init, NPMX_GPIO_MODE_OUTPUT_IRQ);


	//npmx_core_event_interrupt_enable(&pmic, NPMX_EVENT_GROUP_SHIPHOLD, ((1<<NPMX_EVENT_GROUP_SHIPHOLD_PRESSED_MASK) | (1<<NPMX_EVENT_GROUP_SHIPHOLD_RELEASED_MASK)));
	// If only pressed or release set works as expected
	npmx_core_event_interrupt_enable(&m_pmic, NPMX_EVENT_GROUP_SHIPHOLD, NPMX_EVENT_GROUP_SHIPHOLD_PRESSED_MASK);
	npmx_core_event_interrupt_enable(&m_pmic, NPMX_EVENT_GROUP_SHIPHOLD, NPMX_EVENT_GROUP_SHIPHOLD_RELEASED_MASK);
}

// Called form the STM32 ISR
void pmic_post_int()
{
	npmx_core_interrupt(&m_pmic);
}

int main(void) {
  configure_pmic();
  
  while (1) {
	  npmx_core_proc(&m_pmic);
	  ...
	  }
}


Any insights, suggestions, or examples on how to handle both SHIPHOLD events correctly would be greatly appreciated.

Many thanks for considering my request.

Related