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.