ubxlib: ASSERTION FAIL with Zephyr and MIA-M10Q

Hello, I am trying ubxlib on a custom device based on NRF52832-CIAA. The module is connected via I2C (pins 11-12) at address 0x42. I also have control of reset (RESET_N).

I have a very simple application that toggles the reset pin (I tried to remove this but I saw same behavior) and then performs the following operations:

   if (0 != (err = uPortInit())) {
    LOG_ERR("uPortInit failed %d", err);
    return err;
  }

  if (0 != (err = uPortI2cInit())) {
    LOG_ERR("uPortI2cInit failed %d", err);
    return err;
  }

  if (0 != (err = uDeviceInit())) {
    LOG_ERR("uDeviceInit failed %d", err);
    return err;
  }

  if (0 != (err = uDeviceOpen(NULL, &ubx_device_handle))) {
    LOG_ERR("uDeviceOpen failed %d", err);
    return err;
  }

  uGnssPwrOn(&ubx_device_handle);

  uGnssVersionType_t version;

  if (0 != (err = uGnssInfoGetVersions(&ubx_device_handle, &version))) {
    LOG_ERR("uDeviceOpen failed %d", err);
    return err;
  }

  LOG_INF("GNSS ver: %s", version.ver);
  LOG_INF("GNSS fw: %s", version.fw);
  LOG_INF("GNSS hw: %s", version.hw);
  LOG_INF("GNSS prot: %s", version.prot);
  LOG_INF("GNSS mod: %s", version.mod);

  uGnssPwrOff(&ubx_device_handle);

I configured the device via dts:

	gps {
		status = "okay";
		compatible = "u-blox,ubxlib-device-gnss";
		transport-type = "i2c0";
		i2c-already-open;
		i2c-address = <0x42>;
		module-type = "U_GNSS_MODULE_TYPE_M10";
	};

I enabled i2c0 via dts too…

When I run my application I get an assertion the the nordic HAL.

00> *** Booting nRF Connect SDK v2.5.1 ***
00> U_PORT_BOARD_CFG: using GNSS device "gps" from the device tree, module-type 2 with pin-enable-power -1, pin-data-ready -1...
00> U_PORT_BOARD_CFG: ...GNSS on I2C 0, i2c-address 66, i2c-clock-hertz 100000, i2c-already-open.
00> U_GNSS: initialising with ENABLE_POWER pin not connected, transport type I2C.
00> U_GNSS: sent command b5 62 0a 06 00 00 10 3a.
00> U_GNSS: decoded UBX response 0x0a 0x06: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [body 120 byte(s)].
00> U_GNSS: sent command b5 62 06 04 04 00 00 00 09 00 17 76.
00> ASSERTION FAIL [((((p_instance->drv_inst_idx) == NRFX_TWIM0_INST_IDX) && (((p_xfer_desc->primary_length) < (1U << 8)) && ((p_xfer_desc->secondary_length) < (1U << 8)))) || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0)] @ WEST_TOPDIR/modules/hal/nordic/nrfx/drivers/src/nrfx_twim.c:593
00> [00:00:01.407,531] <err> os: r0/a1:  0x00000004  r1/a2:  0x00000251  r2/a3:  0x00000000
00> [00:00:01.408,142] <err> os: r3/a4:  0x00000251 r12/ip:  0x0000000a r14/lr:  0x00023c03
00> [00:00:01.408,721] <err> os:  xpsr:  0x41000000
00> [00:00:01.409,149] <err> os: Faulting instruction address (r15/pc): 0x0002be8c
00> [00:00:01.409,698] <err> os: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0
00> [00:00:01.410,217] <err> os: Current thread: 0x200026e0 (main)
00> [00:00:01.415,740] <err> os: Halting system

It’s a bit puzzling because I see that 1st command is sent correctly and seem to get a valid answer (that should mean that I2C communication is ok) and the 2nd one generate a low-level issue.

We tested the I2C and it seems that the HW connection is OK but if there’s something else I should check, I’ll be happy to provide any information you may need.

About this issue

  • Original URL
  • State: closed
  • Created 5 months ago
  • Comments: 43 (19 by maintainers)

Most upvoted comments

The change is now on master here, see commit https://github.com/u-blox/ubxlib/commit/93e3ccae2c194781cdd216b0720e0147a4824d0f. I will delete the preview branch sometime next week. Will close this issue now: please feel free to re-open, or open a new issue, if there is more to discuss.

I tested it on my setup and it works perfectly. Thank you again for the good work!

@RobMeades Thank you, I’ll try to test this ASAP.

Find here:

https://github.com/u-blox/ubxlib/tree/preview_port_i2c_spi_segment_size_rmea

…a preview branch that introduces maxSegmentSize for both the uDeviceCfgI2c_t and uDeviceCfgSpi_t structures. I have tested it with a segment size of 32 bytes and it seems to work fine but I have not tested it on a device that actually has a HW limitation yet (nRF52832). .dts/.overlay entries i2c-max-segment-size and spi-max-segment-size will be obeyed.

If you have the time, please give it a spin for I2C on nRF52832 and see if it resolves your problem. All feedback welcomed.

Assuming it works for you I will get it reviewed internally and then pushed out to master here and will delete the preview branch some time after that.

Yep, that was my dumb mistake 😃 Thank you for your support @RobMeades

From this question on the Nordic forums comes this useful comparison table which includes the width of the MAXCNT variable of EasyDMA (in bits) for each peripheral of each nRF52 series MCU:

image

It is a bit weird that the limiting value is on nRF52832, but anyway, the limitation applies for I2C, UART and SPI. I doubt that it is an application-level issue for UART since the Zephyr function on the send-end of the UART is k_fifo_put(), i.e. there should be a FIFO in the way, but it will be an issue for both I2C and SPI.

Thinking out load, assuming nRF52832 works for your application, we would probably end up adding uPortI2cSetMaxSegmentSize()/uPortI2cGetMaxSegmentSize()/uPortSpiSetMaxSegmentSize()/uPortSpiGetMaxSegmentSize(), with 0 meaning “none” [the default, which would also apply for the non-Zephyr platforms]. uDeviceCfgI2c_t and uDeviceCfgSpi_t would both gain a maxSegmentSize parameter on the end, which would default to zero for those who don’t populate it; this parameter would come through in the .dts file as i2c-max-segment-size and spi-max-segment-size and uDeviceOpen() would call the relevant new port function to set it up.

How i2c_transfer() ends up being called ref. max segment size for the uPortI2cControllerSendReceive() case would need some care, otherwise it doesn’t look too difficult to do and we could add an nRF52832-based board to the ubxlib test system to test it.

@ValterMinute “I need to write a 256 bytes command and I split it in two 128 bytes writes (with start and stop) or instead of reading 300 bytes in a single read transaction I perform 3…”

I’d probably decompose I2C transactions. Some like the Arduino AVR had a 32-byte buffer, but not sure where that came from, but could just have been a composition buffer, that was accumulated and then flushed. With I2C you’re likely sharing with others, so holding the bus excessively might be undesirable for a number of reasons.

Out-bound (to receiver) the maximal UBX packet is 1000 bytes, from the receiver it can be much larger for diagnostic and RXM type messages, which can notionally get to 6-8 KB. RTCM3 around 1024, SPARTN don’t recall off the top of my head, but no more than 1.5KB

Personally, I’d probably opt to take data in a piecemeal manner, feeding that into a parser/demuxer with a deeper frame buffer, and skip packets exceeding client side buffering limits. Plus the ability to push data requests into the receiver.

I can’t say I’ve seen the 0xFFFF size reporting, but the LA trace looks compelling, seen other reports on the forum for getting 0x8000. One could decompose to smaller transfer, and then recheck the pending length.

I think that since the module I2C interface works as a data stream splitting one long read/write in multiple ones shouldn’t be an issue. Is that true?

It is, but I’d kinda hoped Zephyr would be the level that did that, rather than the “application” having to do it. If ubxlib has to do it then a concept of what that length is needs to come from somewhere and we need to test it (currently the “lowest” we go in the test system is nRF52833). Also, it seems the problem is not limited to I2C, we would have to do the same thing for UART and [I guess?] SPI.

Before going any further, I suggest we prove that you have a viable way forward with the 64 kbytes RAM limitation by persisting with U_GNSS_MSG_TEMPORARY_BUFFER_LENGTH_BYTES=128 and getting everything running; then we can decide the best way forward.

Ok, I see a small progress here:

00> *** Booting nRF Connect SDK v2.5.2 ***
00> U_PORT_BOARD_CFG: using GNSS device "gps" from the device tree, module-type 2 with pin-enable-power -1, pin-data-ready -1...
00> U_PORT_BOARD_CFG: ...GNSS on I2C 0, i2c-address 66, i2c-clock-hertz 100000, i2c-already-open.
00> U_GNSS: initialising with ENABLE_POWER pin not connected, transport type I2C.
00> U_GNSS: sent command b5 62 0a 06 00 00 10 3a.
00> U_GNSS: decoded UBX response 0x0a 0x06: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [body 120 byte(s)].
00> U_GNSS: sent command b5 62 06 04 04 00 00 00 09 00 17 76.
00> U_GNSS: sent command b5 62 0a 06 00 00 10 3a.
00> U_GNSS: decoded UBX response 0x0a 0x06: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [body 120 byte(s)].
00> [00:00:02.390,014] <err> gnss: uDeviceOpen failed -5

Now I need to figure out error -5 😃 but probably first I’ll need to limit the size of transaction on I2C bus. I think I can do that in u_port_i2c.c, but that would probably need an additional CONFIG.

I see that receive size is actually limited to 256 here:

Purely an implementation matter in order that the code works nicely with SPI as well: you could try making that 255?

I was thinking about that 😃 maybe 128 (just in case underlying layer complains with buffer alignment).

thank you for your patience 😃

NP, I quite like puzzles, and this is definitely one of those: very weird indeed.

I think we need to find out which of those parameters in the ASSERTION FAIL it is asserting on. If a debugger is not an option, could you maybe hack nrfconnectsdk-v2.5.1\modules\hal\nordic\nrfx\drivers\src\nrfx_twim.c to print them all out on entry to nrfx_twim_xfer(), so something like the following (with the ### just to make the prints stand out):

nrfx_err_t nrfx_twim_xfer(nrfx_twim_t           const * p_instance,
                          nrfx_twim_xfer_desc_t const * p_xfer_desc,
                          uint32_t                      flags)
{
    printf("### p_instance %p, p_xfer_desc %p.\n", p_instance, p_xfer_desc);
    if (p_instance != NULL) {
        printf("### drv_inst_idx %d.\n", p_instance->drv_inst_idx);
    }
    if (p_xfer_desc != NULL) {
        printf("### primary_length %d, secondary_length %d.\n", p_xfer_desc->primary_length, p_xfer_desc->secondary_length);
    }
    NRFX_ASSERT(TWIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
                                     p_xfer_desc->primary_length,
                                     p_xfer_desc->secondary_length));

…and post the debug output here?

I tried with the debugger, but all the values seemed OK every time I reached the BP, then the system froze… I’ll try adding the message. TY for the suggestion

heap mem pool size to 8K

Just to be certain, I guess you changed the heap mem pool size by modifying the parameter CONFIG_HEAP_MEM_POOL_SIZE in your prj.conf?

Yes. I tried increasing it up to 16K, but with no luck.

Hi @RobMeades. I added the uGnssPowerOn call for debugging (I was executing it step by step) and it was left there by mistake. I removed it. I had error -6 (ENOMEM) before, so I increased main stack thread to 8K (this code is called from main) and heap mem pool size to 8K (error -6 stop happening) and then 16K but I still get the same behavior. I also tried to reset the chip (I can control reset pin), but this also doesn’t seem to solve the issue.