Using TWIM with NCS

I'm using an nRF52840 and porting an old Firmware from nRF5 SDK to NCS.

I am using TWIM to communicate with a Peripheral and I want to continue to do this so I can eventually use the PPI with this.

I've been following this example to get basic TWIM working with NCS but I am having some issues with the interrupt and handler.

My code looks like this (I've removed all logging and error checking just to make things easier to read):

void PowerOnInit(void)
{

    IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_TWIM_INST_GET(1)), IRQ_PRIO_LOWEST, NRFX_TWIM_INST_HANDLER_GET(1), 0, 0);

}

void I2C_Init()
{
nrfx_err_t err_code;
    nrfx_twim_config_t twim_config = NRFX_TWIM_DEFAULT_CONFIG(SCL_PIN, SDA_PIN);
nrfx_twim_init(&twim_instance, &twim_config, I2CHandler, NULL);
nrfx_twim_enable(&twim_instance);
}

void I2C_ReadBlock(uint8_t p_device_address, uint8_t p_reg_address, uint8_t *p_data, uint8_t p_number_of_bytes)
{
nrfx_twim_xfer_desc_t xfer_desc = {.address = p_device_address,
                                       .type = NRFX_TWIM_XFER_TXRX,
                                       .primary_length = 1,
                                       .p_primary_buf = &p_reg_address,
                                       .secondary_length = p_number_of_bytes,
                                       .p_secondary_buf = p_data};


    nrfx_twim_xfer(&twim_instance, &xfer_desc, 0);
}

void I2C_WriteBlock(uint8_t p_device_address, uint8_t p_reg_address, uint8_t *p_data, uint8_t p_number_of_bytes)
{

    uint8_t buffer[HAL_I2C_WRITE_BUFFER_SIZE];

if (p_number_of_bytes > (HAL_I2C_WRITE_BUFFER_SIZE - 1U))
    {
        return;
    }

buffer[0] = p_reg_address;
memcpy(&buffer[1], p_data, p_number_of_bytes);

nrfx_twim_xfer_desc_t xfer_desc = {.address = p_device_address,
                                       .type = NRFX_TWIM_XFER_TX,
                                       .primary_length = p_number_of_bytes + 1,
                                       .p_primary_buf = buffer,
                                       .secondary_length = 0,
                                       .p_secondary_buf = NULL};

    nrfx_twim_xfer(&twim_instance, &xfer_desc, 0);
}

My `proj.conf` has:

CONFIG_NRFX_TWIM1=y

I've also tried with and without this in my device tree:

&i2c1 {
    status = "okay";
    compatible = "nordic,nrf-twim";
    pinctrl-0 = <&i2c_master_dummy>;
    pinctrl-names = "default";
};

Everything compiles and appears to initialise fine but as soon as I try to transfer, I get an MPU Fault:

[00:00:10.524,444] <err> os: ***** MPU FAULT *****
[00:00:10.524,475] <err> os: Instruction Access Violation
[00:00:10.524,475] <err> os: r0/a1: 0x00000000 r1/a2: 0x00000000 r2/a3: 0x00000001
[00:00:10.524,505] <err> os: r3/a4: 0x200008a0 r12/ip: 0x00000001 r14/lr: 0x0000608b
[00:00:10.524,536] <err> os: xpsr: 0x61000000
[00:00:10.524,536] <err> os: Faulting instruction address (r15/pc): 0x40010206
[00:00:10.524,566] <err> os: >>> ZEPHYR FATAL ERROR 20: Unknown error on CPU 0
[00:00:10.524,597] <err> os: Current thread: 0x200008a0 (unknown)
[00:00:11.592,956] <err> os: Halting system

If I pass a handler, but do not call IRQ_CONNECT, then I get the following error:

[00:00:10.431,823] <err> os: Unhandled IRQn: 4
[00:00:10.431,854] <err> os: >>> ZEPHYR FATAL ERROR 1: Unhandled interrupt on CPU 0
[00:00:10.431,884] <err> os: Current thread: 0x20001418 (unknown)
[00:00:11.058,197] <err> os: Halting system

Which makes sense.

If I do not call IRQ_CONNECT and pass a NULL handler, then I do not get the fault and I can successfully read and write data - but I think this is blocking mode and the handler would be nice to check for NACKS & set flags etc.

Any ideas why this is not working? What I have done seems to match the example as far as I can see.

Related