Jump to content
I2Cdevlib Forums
dingari

ICM-20948 DMP load error

Recommended Posts

Hi, I'm trying to flash the DMP image to an ICM-20948 to use the built-in sensor fusion. I've adapted my source code to use the code from the "Embedded MotionDriver (eMD) ICM-20948 v.1.0 for Nucleo Board" functions. I'm using nRF52832 to talk to ICM-20948 through I2C. My problem is twofold:

1) The transfer of the DMP firmware (dmp3a) sometimes fails. The ICM-20948 NACKs a byte (strangely it always seems to be a packet in memory bank 19 or 30), and then I have to power-cycle the chip to get an ACK from any register read/write.

2) In the cases where the DMP firmware transfer is successful, the verification routine fails. The bytes that my device reads back to compare to the firmware bytes are just all zeroes.

For reference, this is the firmware upload routine from the MotionDriver source code:

int inv_icm20948_firmware_load(struct inv_icm20948 * s, const unsigned char *data_start, unsigned short size_start, unsigned short load_addr)
{ 
    int write_size;
    int result;
    unsigned short memaddr;
    const unsigned char *data;
    unsigned short size;
    unsigned char data_cmp[INV_MAX_SERIAL_READ];
    int flag = 0;

    if(s->base_state.firmware_loaded)
        return 0;
        
    // Write DMP memory
    data = data_start;
    size = size_start;
    memaddr = load_addr;
    while (size > 0) {
        write_size = min(size, INV_MAX_SERIAL_WRITE);
        if ((memaddr & 0xff) + write_size > 0x100) {
            // Moved across a bank
            write_size = (memaddr & 0xff) + write_size - 0x100;
        }
        result = inv_icm20948_write_mems(s, memaddr, write_size, (unsigned char *)data);
        if (result)
            return result;

        data += write_size;
        size -= write_size;
        memaddr += write_size;
    }

    // Verify DMP memory

    data = data_start;
    size = size_start;
    memaddr = load_addr;
    while (size > 0) {
        write_size = min(size, INV_MAX_SERIAL_READ);
        if ((memaddr & 0xff) + write_size > 0x100) {
            // Moved across a bank
            write_size = (memaddr & 0xff) + write_size - 0x100;
        }
        result = inv_icm20948_read_mems(s, memaddr, write_size, data_cmp);
        if (result)
            flag++; // Error, DMP not written correctly
        if (memcmp(data_cmp, data, write_size))
            return -1;
        data += write_size;
        size -= write_size;
        memaddr += write_size;
    }

#if defined(WIN32)   
    //if(!flag)
      // inv_log("DMP Firmware was updated successfully..\r\n");
#endif

    return 0;
}

I've looked at the I2C lines on a scope, and the bytes are successfully written to the ICM-20948, but somehow they are not making it to the DMP memory. I've attached a screenshot of the NACK event (third byte).

I assume the following constants are suitable for the ICM-20948:

#define DMP_LOAD_START 0x90

#define REG_MEM_START_ADDR      (BANK_0 | 0x7C)
#define REG_MEM_R_W             (BANK_0 | 0x7D)
#define REG_MEM_BANK_SEL        (BANK_0 | 0x7E)

NewFile1.png

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×