npmx drivers

I am using a STM32 with the NPMX drivers.

I am having a few issues and wanted to see if there are recommendations.

Issue 1:

disabling the interrupts does not seem to work

	// Clear all events before enabling interrupts, just in case other interrupt source was configured before.
	for (uint32_t i = 0; i < NPMX_EVENT_GROUP_COUNT; i++) {
	        npmx_err = npmx_core_event_interrupt_disable(&npm1300_instance, (npmx_event_group_t)i, NPMX_EVENT_GROUP_ALL_EVENTS_MASK);
	        if(npmx_err == NPMX_SUCCESS)
	        {
	        		printf("Event Cleared\n");
	        		osDelay(100);
	        }

the above code comes from the PORTING Guide.

when i run that block it looks like it never reaches the NPMX_SUCCESS

I have attached the I2C transactions

it looks like it is writing 0x00 and not 0xFF as I would expect.

Issue 2:

I am trying to set a GPIO as an Interrupt.

	npmx_error_t ret;
	npmx_gpio_t *npmx_gpio_struct;

	// Set GPIO 3 as GPIO Interrupt.
	//
	npmx_gpio_struct = npmx_gpio_get(&npm1300_instance, 3);

	ret = npmx_gpio_mode_set(&npmx_gpio_struct, NPMX_GPIO_MODE_OUTPUT_IRQ);

when i run this it does not look like I get the Index of 3 and I cannot tell about the pointer to the I2C Instance

then the call to npmx_gpio_mode_set throws a hard Fault.

I have tried it with declaring a separate npmx_gpio_t structure and inline declaration like the porting guide.  They both throw faults.

which I guess I should ask if the init function call from the porting guide

static npmx_error_t my_i2c_write_function(void * p_context, uint32_t register_address, uint8_t * p_data, size_t num_of_bytes);
static npmx_error_t my_i2c_read_function(void * p_context, uint32_t register_address, uint8_t * p_data, size_t num_of_bytes);


static void my_npmx_initialization_function(void)
{
    npm1300_backend.p_read = my_i2c_read_function;
    npm1300_backend.p_write = my_i2c_write_function;
    npm1300_backend.p_context = NULL; // Optional context for our use

    npmx_error_t npmx_err = npmx_core_init(&npm1300_instance, &npm1300_backend, NULL, true);
    // TODO: Verify that npmx_err == NPMX_SUCCESS
}

should give me a I2C like this

it appears to write 0x05 and 0x09, then read 0x00.

is this expected from the init Function?

I am looking more into it, but any guidance can help

Parents Reply Children
  • I am having trouble with the correct STM32 HAL I2C calls for TX and RX.  I believe I have the TX working correctly because I call to clear all interrupts and it appears to work.  the RX might still be an issue.  in the npmx_core_inti() function it looks like it needs to read several registers if you set "Restore Values" to True.  but i only get one read for the ADCCONFIG, but nothing else.  how many reads of registers should there be?
    adc, ntc, charge, discharge, ship.

    Is there any more guidance on the preferred function calls to write to registers? do you

    need to call npmx_xxx_get() for any specific function before calling npmx_xxx_set()?

  • There is no point in using any of the npmx functions as long as the I2C read/write functions are not properly implemented. If you struggle with the implementation, I could give some guidance based on your current code, or at least a reference to STM32 documentation I should use to implement this.

    > but i only get one read for the ADCCONFIG, but nothing else.

    I suspect that the I2C read function returns an error which makes it the first and the last read as the init function will terminate on any communication error. That's why I asked you to check the init return code.

  • i have the I2C working now.  so my only issue is how to use the npmx drivers correctly.

    it turns out I needed to do a conversion from the STM HAL I2C error return status to the npmx_error_t enumeration. so i was returning the correct enum in the I2C read write functions.

    I believe I am starting to understand the nPMX drivers.  

    for example, would this be the correct way to enable vbat to auto measure every second in single measurement mode:

    // Enable VBAT auto measure every 1 second in single measurement mode
        npmx_adc_config_t adc_conf;
        adc_conf.vbat_burst =0;									//Set ADCCONFIG VBAT BURST to SINGLEMODE
        adc_conf.vbat_auto = 1;									//set ADCONFIG VBAT AUTO to Trigger measurement every 1 Second
        npmx_adc_t * adc = npmx_adc_get(&npm1300_instance, 0);
        ret =  npmx_adc_config_set(adc, &adc_conf);
    I have many questions about just the basic order of configuring things and use of correct masks for enabling/disabling charger, creating callbacks correctly, ....

    I guess I will keep trying and open a ticket if I run into issues.

    thanks for your help

  • Good to hear you've solved the I2C issues. Yes, using npmx drivers is not very straight-forward as it allows much finer tuning of different parameters, etc. But that's the appeal of the bare-metal flavour of drivers for many, for simplicity you could use our Zephyr native drivers.

    To help you get through the learning curve on npmx if you continue this way, we have built docs, e.g. here's the page on ADC since you're trying to get some measurements now: https://nordicsemiconductor.github.io/npmx/drivers/adc/index.html

    On the front page of these docs we've also linked https://github.com/NordicSemiconductor/npmx-zephyr where you can find various npmx usage examples. The samples are integrated into the Zephyr environment, but the way the npmx APIs are used does not change based on the environment, so those could be copied (with some adjustments to your use case) if found useful.

  • I have everything "working" but i have a few issues and questions.
    Let me describe my configuration:

    I have a STM32 running FreeRTOS.  I have the PMIC configured for the ADC to automeasure every 1 Second.  all USB, VBAT, ADC, Charger will generate an Interrupt on GPIO3 from the PMIC.
    The STM has a ISR that simply sets a flag the an interrupt occured.

    I have one thread that runs this:

      for(;;)
      {
    	printf("\n myTask01 \n"); //WRC print Task
    
    	if (pmic_interrupt) {
    		  npmx_core_interrupt(&npm1300_instance);
    		  npmx_core_proc(&npm1300_instance);
    		  pmic_interrupt = false;
    		  osDelay(1000);
    	  }
    

    I have a second code that runs the Fuel Gauge

      for(;;)
      {
    	printf("\n myTask02 \n"); //WRC print Task
    	fuel_gauge_update(&npm1300_instance);
    	osDelay(1000);
      }
    

    I have been playing with thread priorities and delay numbers, but i cant get a consistent result.

    The first task sometimes reports the battery voltage or events if I pull the USB.  like this:

    myTask01

    Battery: 4125 mV.

    State: VBUS_CONNECTED_CHARGING_CC.

    State: BATTERY_CONNECTED.

    but most of the time it only prints

    myTask01

    so i know it is entering the task, but not reading the ADC for VBAT.

    either missing the interrupt or the threads are not allotted enough time

    the Fuel Gauge task only prints

    myTask02

    Constant current charging

    Reading ADC measurements failed.

    V: -0.000, I: 0.000, T: -0.00, SoC: 0.00, TTE: nan, TTF: nan

    I guess my questions are

    what is the timing needed for each task to complete the PMIC and Fuel Gauge procedures?

    any thought on why I always get "adc failed" in the Fuel Gauge?

    do i need to configure the ADC different?

Related