I2C code on nRF connect SDK

Hi, 

I read the link https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/nrfx/drivers/twis/driver.html and updated periodic_sync example as attached below. 

But I am unable to see Request from the Master. I checked connections, addresses and all.

4807.prj.conf 

/*
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/types.h>
#include <zephyr.h>
#include <sys/byteorder.h>
#include <sys/printk.h>

#include <device.h>
#include <devicetree.h>
#include <drivers/gpio.h>
#include <bluetooth/bluetooth.h>
#include <dk_buttons_and_leds.h>
#include <device.h>
#include <soc.h>
#include <dk_buttons_and_leds.h>
#include <drivers/uart.h>
#include <drivers/i2c.h>
#include <nrfx_twi.h>
#include <nrfx_twis.h>
#include <devicetree.h>
#include <stdio.h>
#include <irq.h>
#include <settings/settings.h>

#define twi	DT_LABEL(DT_ALIAS(i2c0))
uint8_t txBufferI2C[96];

#define SLAVE_ADDR (0x70 >> 1U)
#define DT_NORDIC_NRF_TWIS_I2C_0_IRQ_0 3
#define DT_NORDIC_NRF_TWIS_I2C_0_IRQ_0_PRIORITY 0

typedef nrfx_twis_t nrf_drv_twis_t;
static const nrfx_twis_t m_twis = NRFX_TWIS_INSTANCE(0);
const struct device *i2c_dev;

#define TIMEOUT_SYNC_CREATE K_SECONDS(10)
#define NAME_LEN            30

static bool         per_adv_found;
static bt_addr_le_t per_addr;
static uint8_t      per_sid;

static K_SEM_DEFINE(sem_per_adv, 0, 1);
static K_SEM_DEFINE(sem_per_sync, 0, 1);
static K_SEM_DEFINE(sem_per_sync_lost, 0, 1);

/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)

#if DT_NODE_HAS_STATUS(LED0_NODE, okay)
#define HAS_LED     0
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
#define BLINK_ONOFF K_MSEC(500)

static struct k_work_delayable blink_work;
static bool                  led_is_on;

static void blink_timeout(struct k_work *work)
{
	led_is_on = !led_is_on;
	gpio_pin_set(led.port, led.pin, (int)led_is_on);

	k_work_schedule(&blink_work, BLINK_ONOFF);
}
#endif

static bool data_cb(struct bt_data *data, void *user_data)
{
	char *name = user_data;
	uint8_t len;

        printk("\ndata_cb = %x len=%d",data->type,data->data_len);
        memcpy(&txBufferI2C,&(data->type), 4); //add just to test so remove it
        
	switch (data->type) 
        {
            case BT_DATA_NAME_SHORTENED:
            case BT_DATA_NAME_COMPLETE:
      		len = MIN(data->data_len, NAME_LEN - 1);
      		memcpy(name, data->data, len);
      		name[len] = '\0';
      		return false;
            
            case BT_DATA_MANUFACTURER_DATA:
                   //printk("AAAAAAAAAAAAAAAAAAAAGGGG %d %s\n", data->data_len, data->data);
                   return true;

      	    default:
      		return true;
	}
}

static const char *phy2str(uint8_t phy)
{
	switch (phy) {
	case 0: return "No packets";
	case BT_GAP_LE_PHY_1M: return "LE 1M";
	case BT_GAP_LE_PHY_2M: return "LE 2M";
	case BT_GAP_LE_PHY_CODED: return "LE Coded";
	default: return "Unknown";
	}
}

static void scan_recv(const struct bt_le_scan_recv_info *info,
		      struct net_buf_simple *buf)
{
	char le_addr[BT_ADDR_LE_STR_LEN];
	char name[NAME_LEN];

	(void)memset(name, 0, sizeof(name));
       
printk("\nscan_recv with len=%d, size=%d ",buf->len, buf->size);
	bt_data_parse(buf, data_cb, name);

	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
        if (info->adv_type == 5)
          printk("\n[DEVICE]: %s, AD evt type %u, Tx Pwr: %i, RSSI %i %s C:%u S:%u D:%u SR:%u E:%u Prim: %s, Secn: %s, Interval: 0x%04x (%u ms), SID: %u \n",
	       le_addr, info->adv_type, info->tx_power, info->rssi, name,
	       (info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0,
	       (info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0,
	       (info->adv_props & BT_GAP_ADV_PROP_DIRECTED) != 0,
	       (info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0,
	       (info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0,
	       phy2str(info->primary_phy), phy2str(info->secondary_phy),
	       info->interval, info->interval * 5 / 4, info->sid);

	if (!per_adv_found && info->interval) {
		per_adv_found = true;

		per_sid = info->sid;
		bt_addr_le_copy(&per_addr, info->addr);

		k_sem_give(&sem_per_adv);
	}
}

static struct bt_le_scan_cb scan_callbacks = {
	.recv = scan_recv,
};

static void sync_cb(struct bt_le_per_adv_sync *sync,
		    struct bt_le_per_adv_sync_synced_info *info)
{
	char le_addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));

	printk("\nsync_cb: PER_ADV_SYNC[%u]: [DEVICE]: %s synced, "
	       "Interval 0x%04x (%u ms), PHY %s\n",
	       bt_le_per_adv_sync_get_index(sync), le_addr,
	       info->interval, info->interval * 5 / 4, phy2str(info->phy));

	k_sem_give(&sem_per_sync);
}

static void term_cb(struct bt_le_per_adv_sync *sync,
		    const struct bt_le_per_adv_sync_term_info *info)
{
	char le_addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));

	printk("\nterm_cb: PER_ADV_SYNC[%u]: [DEVICE]: %s sync terminated\n",
	       bt_le_per_adv_sync_get_index(sync), le_addr);

	k_sem_give(&sem_per_sync_lost);
}

static void recv_cb(struct bt_le_per_adv_sync *sync,
		    const struct bt_le_per_adv_sync_recv_info *info,
		    struct net_buf_simple *buf)
{
	char le_addr[BT_ADDR_LE_STR_LEN];
	//char data_str[255];

	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
        if (buf->data[1] == BT_DATA_ASHISH)
        {
            //bin2hex(buf->data, buf->len, data_str, sizeof(data_str));
            memcpy(&txBufferI2C,&(buf->data[2]), (buf->len)-1);

            printk("\n recv_cb: PER_ADV_SYNC[%u]: [DEVICE]: %s, tx_power %i, "
	       "RSSI %i, CTE %u, data length %u, data-type=%x \n",
	       bt_le_per_adv_sync_get_index(sync), le_addr, info->tx_power,
	       info->rssi, info->cte_type, buf->len,buf->data[1]);
            printk("\n msg_data %x %x %x %x %x %x %x %x %x %x",buf->data[2],buf->data[3],buf->data[4],buf->data[5],buf->data[6],buf->data[7],buf->data[8],buf->data[9],buf->data[10],buf->data[11]);
        }
        else
        {
            printk("\n recv_cb: PER_ADV_SYNC[%u]: [DEVICE]: %s, tx_power %i, "
	       "RSSI %i, CTE %u, data length %u, data-type=%x \n",
	       bt_le_per_adv_sync_get_index(sync), le_addr, info->tx_power,
	       info->rssi, info->cte_type, buf->len,buf->data[1]);
        }
}
static struct bt_le_per_adv_sync_cb sync_callbacks = {
	.synced = sync_cb,
	.term = term_cb,
	.recv = recv_cb
};

static void twis_event_handler(nrfx_twis_evt_t const * const p_event)
{
printk("twis_event_handler\n");
    switch (p_event->type)
    {
        case NRFX_TWIS_EVT_READ_REQ:
        printk("NRFX_TWIS_EVT_READ_REQ\n");
            if (p_event->data.buf_req)
            {
               (void)nrfx_twis_tx_prepare((nrfx_twis_t const *)&m_twis, &txBufferI2C[0], sizeof(txBufferI2C));
            }
            break;
        case NRFX_TWIS_EVT_READ_DONE:
        printk("NRFX_TWIS_EVT_READ_DONE\n");
// always keep last message in buffer, in case off I2C crc failure, on next I2C poll same data transmitted 
            break;
        case NRFX_TWIS_EVT_WRITE_REQ:
            printk("NRFX_TWIS_EVT_WRITE_REQ\n");
            break;
        case NRFX_TWIS_EVT_WRITE_DONE:
             printk("NRFX_TWIS_EVT_WRITE_DONE\n");
            break;

        case NRFX_TWIS_EVT_READ_ERROR:
        case NRFX_TWIS_EVT_WRITE_ERROR:
        case NRFX_TWIS_EVT_GENERAL_ERROR:
            printk("NRFX_TWIS_EVT_GENERAL_ERROR\n");
            break;
        default:
 printk("DEFAULT\n");
            break;
    }
}

int I2CSlave_init(void)
{
  int err;

  IRQ_CONNECT(DT_NORDIC_NRF_TWIS_I2C_0_IRQ_0, DT_NORDIC_NRF_TWIS_I2C_0_IRQ_0_PRIORITY, 
              nrfx_isr, nrfx_twis_0_irq_handler, 0);
 
  nrfx_twis_config_t config;
  config.addr[0] = SLAVE_ADDR;
  config.addr[1] = 0;
  config.scl = 27;
  config.scl_pull = NRF_GPIO_PIN_NOPULL;
  config.sda = 26;
  config.sda_pull = NRF_GPIO_PIN_NOPULL;
  config.interrupt_priority = 0; // Highest

  err = nrfx_twis_init(&m_twis, &config, twis_event_handler);
  nrfx_twis_enable(&m_twis);
  return err;
}


void main(void)
{
	struct bt_le_per_adv_sync_param sync_create_param;
	struct bt_le_per_adv_sync *sync;
	int err;

	printk("\nStarting Periodic Advertising Synchronization Demo\n");

        /*i2c_dev = device_get_binding(DT_LABEL(DT_NODELABEL(i2c0)));
	if (!i2c_dev) {
		printk("I2C: Device driver not found.\n");
		//return;
	}*/


#if (HAS_LED)
	printk("\nChecking LED device...");
	if (!device_is_ready(led.port)) {
		printk("\nfailed.\n");
		return;
	}
	printk("\ndone.\n");

	printk("\nConfiguring GPIO pin...");
	err = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
	if (err) {
		printk("\nfailed.\n");
		return;
	}
	printk("\ndone.\n");

	k_work_init_delayable(&blink_work, blink_timeout);
#endif /* HAS_LED */

        err = I2CSlave_init();
	if (err != NRFX_SUCCESS) {
             printk("I2C init failed (err %d)\n", err);
             return;
	}

	/* Initialize the Bluetooth Subsystem */
	err = bt_enable(NULL);
	if (err) {
		printk("\nBluetooth init failed (err %d)\n", err);
		return;
	}

	printk("\nScan callbacks register...");
	bt_le_scan_cb_register(&scan_callbacks);
	printk("\nsuccess.\n");

	printk("\nPeriodic Advertising callbacks register...");
	bt_le_per_adv_sync_cb_register(&sync_callbacks);
	printk("\nSuccess.\n");




	printk("\nStart scanning...");
	err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, NULL);
	if (err) {
		printk("\nfailed (err %d)\n", err);
		return;
	}
	printk("\nsuccess.\n");

	do {
#if (HAS_LED)
		struct k_work_sync work_sync;

		printk("\nStart blinking LED...\n");
		led_is_on = false;
		gpio_pin_set(led.port, led.pin, (int)led_is_on);
		k_work_schedule(&blink_work, BLINK_ONOFF);
#endif /* HAS_LED */

		printk("\nWaiting for periodic advertising...\n");
		per_adv_found = false;
		err = k_sem_take(&sem_per_adv, K_FOREVER);
		if (err) {
			printk("\nfailed (err %d)\n", err);
			return;
		}
		printk("\nFound periodic advertising.\n");

		printk("\nCreating Periodic Advertising Sync...");
		bt_addr_le_copy(&sync_create_param.addr, &per_addr);
		sync_create_param.options = 0;
		sync_create_param.sid = per_sid;
		sync_create_param.skip = 0;
		sync_create_param.timeout = 0xa;
		err = bt_le_per_adv_sync_create(&sync_create_param, &sync);
		if (err) {
			printk("\nfailed (err %d)\n", err);
			return;
		}
		printk("\nsuccess.\n");

		printk("\nWaiting for periodic sync...\n");
		err = k_sem_take(&sem_per_sync, TIMEOUT_SYNC_CREATE);
		if (err) {
			printk("\nfailed (err %d)\n", err);

			printk("\nDeleting Periodic Advertising Sync...");
			err = bt_le_per_adv_sync_delete(sync);
			if (err) {
				printk("\nfailed (err %d)\n", err);
				return;
			}
			continue;
		}
		printk("\nPeriodic sync established.\n");

#if (HAS_LED)
		printk("\nStop blinking LED.\n");
		k_work_cancel_delayable_sync(&blink_work, &work_sync);

		/* Keep LED on */
		led_is_on = true;
		gpio_pin_set(led.port, led.pin, (int)led_is_on);
#endif /* HAS_LED */

		printk("\nWaiting for periodic sync lost...\n");
		err = k_sem_take(&sem_per_sync_lost, K_FOREVER);
		if (err) {
			printk("\nfailed (err %d)\n", err);
			return;
		}
		printk("\nPeriodic sync lost.\n");


	} while (true);
}
 3324.nrf52dk_nrf52832.overlay

Can you please verify from your end or provide me some hint what could I miss?

I checked using Saleae logic analyzer and see it is always nak.

Parents Reply
  • Hi Oivind, Thanks for the link, it explains this well.

    I tried to implement the same example to check, but it does not work for me on nrf52832. Can you please check it in the added zip file?

    I get the error at Master side as:

    I2C device 1: i2c nRF52832 addr 0x28
    00>
    00> I2C Master: Slave ADDR: 0x28 SCL: 31, SDA: 30, CLK(Hz): 100000
    00>
    00>
    00> [00:00:00.336,364] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    00> twi return code 4294967291
    00>
    00>
    00> [00:00:01.336,608] <err> i2c_nrfx_twim: Error 0x0BAE0001 occurred for message 0
    00> twi return code 4294967291
    00>

    And on the Saleae, it is 

    write to 0x28 nak
    read to 0x28 nak
    write to 0x28 nak
    read to 0x28 nak
    write to 0x28 nak
    read to 0x28 nak
    write to 0x28 nak
    read to 0x28 nak
    write to 0x28 nak
    read to 0x28 nak

    blinky-twim-and-twis.zip

Children
No Data
Related