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.