KW41z Freertos I2C Error kStatus_I2C_Addr_Nak

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

KW41z Freertos I2C Error kStatus_I2C_Addr_Nak

2,660 Views
lschoenfeld
Contributor III

Dear,

 

I'm using the KW41Z and have connected a digital magnetic Encoder KMA36 via I2C. When I do the initialization, I send several times 4 Bytes via I2C. In some cases I get an error Status_I2C_Addr_Nak from the RTOS function I2C_RTOS_Transfer(). Attached you'll find a trace from the I2C communication. There you can see that the clock for the NAK is missing.

 

The controller has integrated I2C modules. How can this occur?

 

Regards

Lothar

Labels (1)
0 Kudos
25 Replies

2,104 Views
lschoenfeld
Contributor III

Dear Estephania,

please have a look at my comment from the 06.08.19. You can see that I'm using RTOS function from your SDK to do I2C communication. When I'm using this SDK RTOS function I get problems with the I2C communication. You can see that your SDK RTOS I2C function are using non blocking function. So the blocking  should'nt be the problem.

I'm using your RTOS function and get problems with I2C when I implement it in your RTOS example from your SDK. What's wrong in this case?

When I'm using a simple driver example I didn't get any problem.

I didn't understand what you mean with " intrusive to the Bluetooth Le timing stacks".

I didn't see the fault in my application.

Regards

Lothar

0 Kudos

2,104 Views
estephania_mart
NXP TechSupport
NXP TechSupport

Hello,

The RTOS functionality you are using comes from the FreeRTOS implementations of the driver device. 

In the Bluetooth LE stack there are several task working, and there are some tasks that must not be interrupted and the code has a special structure that you will not find in the simple driver examples.

What I meant with intrusive, it's that the Bluetooth LE protocol follows certain timings and processes to work correctly according to its specification, if you add a blocking task that might work for your peripherals but not for Bluetooth LE you might have some faults or errors.

There are several documents explaining more about this such as the BLE Application Developer's Guide or Connectivity Framework Reference Manual or you can even check the Bluetooth LE core specification

Also, are you sure that the pins you are using are not being reconfigured in the Bluetooth LE example code you are using ? If you set the functionality of your pins but those are later reconfigured, you will have those issues.

Regards,

Estephania

0 Kudos

2,104 Views
lschoenfeld
Contributor III

Dear Estephania,

I didn't implement any blocking task. I use your I2C RTOS function.

Also no reconfiguration of the portpin or I2C interface happen.

I think the conversation is going in the wrong direction.

My question at the beginning of this conversation was "How can it be that a clock puls get missing while I2C communication"? The controller has separate integrated I2C units. Unfortunatley I didn't get any concrete information.

Regards

Lothar

0 Kudos

2,106 Views
estephania_mart
NXP TechSupport
NXP TechSupport

Hello,

If you are completely sure that you are not being intrusive to the system when adding your task, did you checked and verified that the pin you are using it's not being over written in a part of the example or it's being reconfigured correctly in case you are using the low power functionalities?

Regards

0 Kudos

2,106 Views
lschoenfeld
Contributor III

Hello,

yes I'm completely sure. No reconfiguratin or pin over writing exist.

The error happen only when I send several times 4 Bytes via I2C as described in my message from 01.08.2019.

Did you try to reproduce the error?

Regards

Lothar

0 Kudos

2,106 Views
estephania_mart
NXP TechSupport
NXP TechSupport

Hello,

I do not have your same encoder, I can set up an I2C but I need to know exactly what are you configuring (pins) when and when are you calling the function in order to fully recreate in on my side. I have worked with the I2C previously with this device and this behavior has not happened before and no one else has reported it yet but you.

I can try checking your code, I do not know how long it will take me due to the current load of work, yet, i can check it out.

Also, maybe you are running out memory to think of something else, you can further debug it with the following definitions

#define gUsePanic_c 1
#define MEM_TRACKING
#define MEM_STATISTICS
#define MEM_DEBUG
#define MEM_DEBUG_OUT_OF_MEMORY

Regards

0 Kudos

2,104 Views
lschoenfeld
Contributor III

Dear Estephania,

attached you'll find the code for the kma36 and I2C. I'm not able to send you the complete project.

Thank you for the information about further debug.

Regards

Lothar

#define I2C0_MASTER          ((I2C_Type *) I2C0_BASE)
#define I2C0_MASTER_CLK_SRC  (I2C0_CLK_SRC)
#define I2C0_BAUDRATE        (100000)
#define KMA36_I2C_ADDRESS   0x59 /**< Linear Encoder Default Address */
#define KMA36_SLP    (0x80)
#define KMA36_LIN    (0x20)
#define KMA36_CNT    (0x10)
#define KMA36_PWR    (0x08)
#define KMA36_SPD    (0x04)
#define KMA36_OVSC    (0x03)
#define KMA36_OS2    (0x00)
#define KMA36_OS4    (0x01)
#define KMA36_OS8    (0x02)
#define KMA36_OS32    (0x03)
#define KMA36_MIN_RESOLUTION 1
#define KMA36_MAX_RESOLUTION 32768

typedef struct {
 i2c_rtos_handle_t *handle; /**< I2C device the sensor is connected to */
 uint8_t addr;  /**< the slave address on the I2C bus */
 bool initialized; /**< status eq. true if initialized */
} kma36_t;
typedef enum kma36_status_tag{
 kma36_status_ok = 0,
 kma36_status_i2c_transfer_error = -1,
 kma36_status_crc_error = -2,
 kma36_status_parameter_fault = -3,
 kma36_status_dev_fault = -4,
 kma36_status_init_fault = -5
}kma36_status_t;
typedef enum kma36_oversampling_tag{
 kma36_oversampling_2 = 0,
 kma36_oversampling_4 = 1,
 kma36_oversampling_8 = 2,
 kma36_oversampling_32 = 3
}kma36_oversampling_t;

static i2c_rtos_handle_t *i2c0_handle;
static kma36_t kma36_dev;
static uint16_t uint16_kma36_ma;
static uint32_t uint32_kma36_ilc;
static uint8_t uint8_kma36_kconf;
static uint16_t uint16_kma36_kres;
void BleApp_Init(void)
{
...
BOARD_InitI2C0();
i2c0_handle = i2c_rtos_init_master(I2C0_MASTER, I2C0_MASTER_CLK_SRC, I2C0_BAUDRATE);
...
memset(&kma36_dev, 0, sizeof(kma36_dev));
kma36_init(&kma36_dev, i2c0_handle, KMA36_I2C_ADDRESS);
kma36_set_enable_counter(&kma36_dev);
kma36_write_config(&kma36_dev);
kma36_set_enable_linear(&kma36_dev);
kma36_write_config(&kma36_dev);
kma36_set_resolution(&kma36_dev, 0x8000);
kma36_write_config(&kma36_dev);
kma36_set_accuracy(&kma36_dev, kma36_oversampling_2);
kma36_write_config(&kma36_dev);
...
}
void BOARD_InitI2C0(void)
{
 CLOCK_EnableClock(kCLOCK_PortC);
 /* PTC16, PTC19 configured as I2C0_SCL, I2C0_SDA */
 const port_pin_config_t ptc16_pin_d5_config = {
  kPORT_PullUp,
  kPORT_SlowSlewRate,
  kPORT_PassiveFilterDisable,
  kPORT_LowDriveStrength,
  kPORT_MuxAlt3,
 };
 PORT_SetPinConfig(I2C0_PORT, I2C0_SCL_PIN, &ptc16_pin_d5_config);
 const port_pin_config_t ptc19_pin_c5_config = {
  kPORT_PullUp,
  kPORT_SlowSlewRate,
  kPORT_PassiveFilterDisable,
  kPORT_LowDriveStrength,
  kPORT_MuxAlt3,
 };
 PORT_SetPinConfig(I2C0_PORT, I2C0_SDA_PIN, &ptc19_pin_c5_config);
}
i2c_rtos_handle_t *i2c_rtos_init_master(I2C_Type* dev, uint32_t clk_src,
       uint32_t baudrate)
{
 status_t status;
 i2c_master_config_t masterConfig;
 uint32_t sourceClock = 0;
 I2C_MasterGetDefaultConfig(&masterConfig);
 masterConfig.baudRate_Bps = baudrate;
 sourceClock = CLOCK_GetFreq(clk_src);
 if (dev == I2C0_MASTER){
  if (i2c0_initialized == true) {
   return NULL;
  }
  status = I2C_RTOS_Init(&handle_i2c0, dev, &masterConfig, sourceClock);
  if (status == kStatus_Success) {
   i2c0_initialized = true;
   return &handle_i2c0;
  } else {
   return NULL;
  }
 }
 else if (dev == I2C1_MASTER){
  if (i2c1_initialized == true) {
   return NULL;
  }
  status = I2C_RTOS_Init(&handle_i2c1, dev, &masterConfig, sourceClock);
  if (status == kStatus_Success) {
   i2c1_initialized = true;
   return &handle_i2c1;
  } else {
   return NULL;
  }
 }
 return NULL;
}

int8_t kma36_init(kma36_t* dev, i2c_rtos_handle_t* handle, uint8_t address)
{
 int8_t int8_Stat = kma36_status_ok;
 /* write device descriptor */
 dev->handle = handle;
 dev->addr = address;
 if(dev->initialized == false) {
  int8_Stat = kma36_read_regs(dev, kma36_register_read_kresel);        // Read Magnetic angle, Incremental linear and Configuration register
  if(int8_Stat == kma36_status_ok) {
   dev->initialized = true;
  }
  else{
   int8_Stat = kma36_status_i2c_transfer_error;
  }
 }
 return int8_Stat;
}
int8_t kma36_set_enable_counter(kma36_t* dev)
{
 int8_t int8_Stat = kma36_status_ok;
    if(dev->handle != NULL) {
     if(dev->initialized == true) {
      uint8_kma36_kconf |= KMA36_CNT;
     }
     else {
      int8_Stat = kma36_status_init_fault;
     }
    }
    else {
  int8_Stat = kma36_status_dev_fault;
    }
 return int8_Stat;
}
int8_t kma36_set_enable_linear(kma36_t* dev)
{
 int8_t int8_Stat = kma36_status_ok;
    if(dev->handle != NULL) {
     if(dev->initialized == true) {
      uint8_kma36_kconf |= KMA36_LIN;
     }
     else {
      int8_Stat = kma36_status_init_fault;
     }
    }
    else {
  int8_Stat = kma36_status_dev_fault;
    }
 return int8_Stat;
}
int8_t kma36_set_resolution(kma36_t* dev, uint16_t uint16_Resolution)
{
 int8_t int8_Stat = kma36_status_ok;
    if(dev->handle != NULL) {
     if(dev->initialized == true) {
      if((uint16_Resolution >= KMA36_MIN_RESOLUTION) && (uint16_Resolution <= KMA36_MAX_RESOLUTION)) {
       uint16_kma36_kres = uint16_Resolution;
      }
      else {
       int8_Stat = kma36_status_parameter_fault;
      }
     }
     else {
      int8_Stat = kma36_status_init_fault;
     }
    }
    else {
  int8_Stat = kma36_status_dev_fault;
    }
 return int8_Stat;
}
int8_t kma36_set_accuracy(kma36_t* dev, kma36_oversampling_t os)
{
 int8_t int8_Stat = kma36_status_ok;
    if(dev->handle != NULL) {
     if(dev->initialized == true) {
      uint8_kma36_kconf &= ~KMA36_OVSC;
      switch(os) {
    case kma36_oversampling_2:
     uint8_kma36_kconf |= KMA36_OS2;
     break;
    case kma36_oversampling_4:
     uint8_kma36_kconf |= KMA36_OS4;
     break;
    case kma36_oversampling_8:
     uint8_kma36_kconf |= KMA36_OS8;
     break;
    case kma36_oversampling_32:
     uint8_kma36_kconf |= KMA36_OS32;
     break;
    default :
     int8_Stat = kma36_status_parameter_fault;
     break;
      }
     }
     else {
      int8_Stat = kma36_status_init_fault;
     }
    }
    else {
  int8_Stat = kma36_status_dev_fault;
    }
 return int8_Stat;
}
int8_t kma36_write_config(kma36_t* dev)
{
 int8_t int8_Stat = kma36_status_ok;
    if(dev->handle != NULL) {
     if(dev->initialized == true) {
      int8_Stat = kma36_write_regs(dev);
     }
     else {
      int8_Stat = kma36_status_init_fault;
     }
    }
    else {
  int8_Stat = kma36_status_dev_fault;
    }
 return int8_Stat;
}
uint8_t kma36_compute_crc(uint8_t* write_regs)
{
 uint8_t uint8_Result;
 uint8_Result = write_regs[0] + write_regs[1] + write_regs[2];
 uint8_Result = 0xFF - uint8_Result + 0x01;
 return uint8_Result;
}
int8_t kma36_write_regs(kma36_t* dev)
{
 int8_t int8_Stat = kma36_status_ok;
 uint8_t uint8_Tx_Buf[4];
    if(dev->handle != NULL) {
     if(dev->initialized == true) {
      uint8_Tx_Buf[0] = uint8_kma36_kconf;
      uint8_Tx_Buf[1] = (uint8_t)(uint16_kma36_kres >> 8);
      uint8_Tx_Buf[2] = (uint8_t)(uint16_kma36_kres & 0xFF);
      uint8_Tx_Buf[3] = kma36_compute_crc(uint8_Tx_Buf);
         if (i2c_rtos_write_regs_no_subaddress(dev->handle, dev->addr, (uint8_t*)uint8_Tx_Buf, 4) != 4) {
       int8_Stat = kma36_status_i2c_transfer_error;
         }
     }
     else {
      int8_Stat = kma36_status_init_fault;
     }
    }
    else {
  int8_Stat = kma36_status_dev_fault;
    }
 return int8_Stat;
}
int i2c_rtos_write_regs_no_subaddress(i2c_rtos_handle_t *handle, uint8_t address, uint8_t *data, int length)
{
 int8_t int8_Retval = 0;
 status_t status;
 memset(&transfer, 0, sizeof(transfer));
 transfer.slaveAddress = address;
 transfer.direction = kI2C_Write;
 transfer.subaddress = 0;
 transfer.subaddressSize = 0;
 transfer.data = (uint8_t*)data;
 transfer.dataSize = length;
 transfer.flags = kI2C_TransferDefaultFlag;
 status = I2C_RTOS_Transfer(handle, &transfer);
 if (status == kStatus_Success) {
  int8_Retval = length;
 }
 return int8_Retval;
}
0 Kudos

2,104 Views
estephania_mart
NXP TechSupport
NXP TechSupport

Hello,

According to your definitions and the behavior you are experiencing about having issues in the fourth transmission, maybe your problem it's regarding your memory.

Did you tried using the definitions I mentioned ? Are you considering the memory you have available in the example you are using ? The example you are using has a special bootloader, the Bluetooth LE stack, the application plus your complete buffers.

Regards,
Estephania

0 Kudos

2,104 Views
lschoenfeld
Contributor III

Dear Estephania,

I couldn't detect any memory issues. The heap has a maximum load of 70%. When the problem occur the bootloader is not active. I've implemented the folowing bootloader: frdmkw41z_wireless_examples_framework_bootloader_otap_bm

Regards

Lothar

0 Kudos

2,104 Views
estephania_mart
NXP TechSupport
NXP TechSupport

Hello,

It will depend on how you are working with the OTA example, if you are using the internal storage, still the OTAP Bootloader image occupies the first part of the flash memory. In the current implementation it has a reserved area of 1/32 of the flash size regardless of the actual size of the image.


The OTAP Bootloader is configured to not overwrite itself so any image sent over the air must not contain the Bootloader application in the reserved section.

pastedImage_1.png

Are you considering it ?

Regards,

Estephania

0 Kudos

2,102 Views
lschoenfeld
Contributor III

Dear Estephania,

I do not have any problem with the bootloader! Please could we come back to the  problemwith the I2C missing clock pulse.

Regards

Lothar

0 Kudos

2,102 Views
estephania_mart
NXP TechSupport
NXP TechSupport

hello,

I mentioned the bootloader as that it's limiting your flash size, and I was not sure you were considering all those elements combined with the stack size.

Which it's the connection interval you set ? Which Bluetooth LE timings did you set in your example ?

Regards,

Estephania

0 Kudos

2,102 Views
lschoenfeld
Contributor III

Dear Estephania,

in the message from the 06.08. I told you that no communication is active while the error occur. So there is also no problem with the BLE timing.

Please could you try to retrace the I2C clock missing problem with your hardware.

Regards

Lothar

0 Kudos

2,102 Views
estephania_mart
NXP TechSupport
NXP TechSupport

Hello,

Sorry for the late reply, we have been under a great load of work lately.

As I do not have your hardware the demo used for the test was based in talking to another board. The I2C clock was not lost neither the Bluetooth LE communication.

The implementation was made using the serial manager to ensure the communication both wired and wireless.

A guide it's being made on how to add this implementation, still , something that was noticed during the test was that in some cases there was not enough heap for the semaphores to be created and work correctly as well as a limitation in the semaphores that could be added to the project.

While the guide it's ready, could you please verify those elements in your side?

Regards,
Estephania

0 Kudos

2,102 Views
lschoenfeld
Contributor III

Dear Estephania,


we also have some workload and so I decide to implement a workaround. Since then the missing clock pulse didn't occur.

Many thanks for the support.

Regards

Lothar

0 Kudos

2,102 Views
estephania_mart
NXP TechSupport
NXP TechSupport

Hello,

sorry for the delay, still, I'll post here the post whenever it is ready.

Regards ,

Estephania

0 Kudos

2,104 Views
lschoenfeld
Contributor III

Dear Estephania,

thanks for your explanation.

There is no problem with the BLE communication. In my case a clock pulse get missing and so I get a NAK instead of an ACK when I send some I2C data. No BLE communication happens while this error occur.

Do you have any other idea?

Regards

Lothar

0 Kudos

2,104 Views
estephania_mart
NXP TechSupport
NXP TechSupport

Hello,

Just to try to corner the case, if you use one of the driver examples , do you have the same issue ?

Regards,

Estephania

0 Kudos

2,104 Views
lschoenfeld
Contributor III

Dear Estephania,

as suggest I let run a driver example frdmkw41z_driver_examples_i2c_interrupt_transfer.

The problem didn't occure.

What modification are necessary to let the bluetooth example work without the error above.

Regards

0 Kudos

2,104 Views
estephania_mart
NXP TechSupport
NXP TechSupport

Hello,

You will need to modify your implementation of the I2C and be careful not to use any blocking task that might interfere with the Bluetooth LE stack.

The best choice for you it's to check the BLE Application Developer's Guide , as you will find more information of the stack structure and needed elements to consider and how you should manage your tasks.

Regards,

Estephania

0 Kudos