This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMP116: I2C_transfer() no STOP condition in "Task"-context but works in POSIX-context

Part Number: TMP116
Other Parts Discussed in Thread: CC2640R2F,

Hello,

I have a problem with I2C_transfer() communicating with a TMP116. The setup is a custom board with a CC2640R2F on it and i.a. a TMP116 connected via I2C at IOID_29/IOID_30.

The problem is similar to one that was already asked before in this forum but the solution hasn't been published in that thread unfortunately. Click here for related thread.

The code is basically the "i2ctmp" example from TIs SimpleLink example pack (C:\ti\simplelink_cc2640r2_sdk_5_30_00_03\examples\rtos\CC2640R2_LAUNCHXL\drivers\i2ctmp) but adapted into a TI-RTOS-task instead of POSIX-"pthread".

Strangely enough it works fine when calling it from pthread-context. But the rest of my project is structured with "tasks" so I don't really want to use that POSIX-threading.

Here is my code (I packed it all into one .c-file for this post here): 


#define TMP116_REG          			0x0000
#define TMP116_BP_ADDR      			0x48
#define TMP116_LP_ADDR      			0x49

// Read the temperature every 5 minutes (5min * 60 sec/min * 1000 milliseconds/sec)
#define READ_TEMP_TIME					300000

#ifndef SENSORS_TASK_STACK_SIZE
#define SENSORS_TASK_STACK_SIZE       	640
#endif
#ifndef SENSORS_TASK_PRIORITY
#define SENSORS_TASK_PRIORITY       	1
#endif

/*********************************************************************
 * INCLUDES
 */
#include <xdc/runtime/System.h>
#include <xdc/std.h>

#include <stdint.h>
#include <stddef.h>

#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/drivers/I2C.h>

#include "util.h"

/*********************************************************************
 * GLOBAL VARIABLES
 */

// Task configuration
Task_Struct sensorsTask;
#if defined __TI_COMPILER_VERSION__
#pragma DATA_ALIGN(sensorsTaskStack, 8)
#else
#pragma data_alignment=8
#endif
uint8_t sensorsTaskStack[SENSORS_TASK_STACK_SIZE];

// I2C vars
I2C_Handle i2cHandle;
I2C_Params i2cParams;
I2C_Transaction i2cTransaction;
uint16_t sample;
uint16_t temperature;
uint8_t txBuffer[1];
uint8_t rxBuffer[2];

// Clock Structs
static Clock_Struct readTempClock;


/*********************************************************************
 * LOCAL FUNCTIONS
 */

extern void Sensors_createTask();

static void Sensors_init();
static void Sensors_taskFxn();
static void Sensors_readTemp();

/*********************************************************************
 * @fn      Sensors_createTask
 *
 * @brief   Reserves stack and sets priority settings
 */
extern void Sensors_createTask() {
	Task_Params sensorsTaskParams;

	// Configure task
	Task_Params_init(&sensorsTaskParams);
	sensorsTaskParams.stack = sensorsTaskStack;
	sensorsTaskParams.stackSize = SENSORS_TASK_STACK_SIZE;
	sensorsTaskParams.priority = SENSORS_TASK_PRIORITY;

	Task_construct(&sensorsTask, Sensors_taskFxn, &sensorsTaskParams, NULL);
}

/*********************************************************************
 * @fn      Sensors_taskFxn
 *
 * @brief   Sensors-Manager.
 * 			Takes care of all sensors equipped with the Smartpen.
 * 			Until now just the temperature-sensor is implemented.
 */
static void Sensors_taskFxn() {
	// Initialize application
	Sensors_init();
}

/*********************************************************************
 * @fn      Sensors_init
 *
 * @brief   Initializes all Sensor related things.
 * 			Temperature-sensor is using I2C to communicate.
 */
static void Sensors_init() {
	I2C_init();
	I2C_Params_init(&i2cParams);
	i2cParams.bitRate = I2C_400kHz;
	i2cParams.transferMode = I2C_MODE_BLOCKING;
	//	i2cParams.transferCallbackFxn = *Sensors_readTempCompleteCb;

	Util_constructClock(&readTempClock, Sensors_readTemp, 1, READ_TEMP_TIME, 1, 0);
}

/*********************************************************************
 * @fn      Sensors_readTemp
 *
 * @brief   reads the temperature
 */
static void Sensors_readTemp() {
	i2cHandle = I2C_open(0, &i2cParams);
	if (i2cHandle == NULL) {
		System_printf("Error Initializing I2C\n");
		System_flush();
		while (1)
			;
	}
	else {
		System_printf("I2C Initialized!\n");
		System_flush();
	}
	/* Common I2C transaction setup */
	i2cTransaction.writeBuf = txBuffer;
	i2cTransaction.writeCount = 1;
	i2cTransaction.readBuf = rxBuffer;
	i2cTransaction.readCount = 2;

	/*
	 * Determine which I2C sensor is present.
	 * We will prefer sensors in this order: TMP116 (on BoosterPacks),
	 * TMP116 (on-board CC32XX LaunchPads), and last TMP006
	 * (on older CC32XX LaunchPads).
	 */
	/* Try TMP116 values */
	txBuffer[0] = TMP116_REG;
	i2cTransaction.slaveAddress = TMP116_BP_ADDR;
	if (!I2C_transfer(i2cHandle, &i2cTransaction)) {
		System_printf("Not BP TMP116, trying LP TMP116\n");
		System_flush();
		i2cTransaction.slaveAddress = TMP116_LP_ADDR;
		if (!I2C_transfer(i2cHandle, &i2cTransaction)) {
			System_printf("Error. No TMP sensor found!\n");
			System_flush();
			while (1);
		}
	}

	/* Print which TMP is in use */
	if (TMP116_REG == txBuffer[0]) {
		System_printf("Detected TMP116 sensor.\n");
		System_flush();
	}

	I2C_close(i2cHandle);
	System_printf("I2C closed!\n");

}

When calling Sensors_createTask() from main() it will initialize the task and call Sensors_init() when the BIOS has started. Then it will call Sensors_readTemp() through the clock-function initialized in Sensors_init().

In Sensors_readTemp() it will open up the I2C driver which succeeds but when trying to contact the TMP116 it fails.

A colleague of mine then connected an oscilloscope to SDA and SCL and found out that the problem is a missing STOP condition (thats where the related question thread comes in). 

Its a really strange problem and maybe thats not a sensors forum problem but a SYS/BIOS-problem but I hope you can help me.

Kind regards

  • Dear Markus - 

    Moving this to the correct forum to help you out with this SDK issue.  

  • Hello  Markus,

    Can you please provide oscilloscope screenshots of the POSIX implementation versus TI-RTOS?  Can you also attach the main.c to show what is occurring between startup and BIOS_start?  Your Sensors_createTask is fine, however Sensors_taskFxn should loop forever instead of exiting after Sensors_init.  Have you considered further investigating the thread integrity with ROV/Debugging tools?  This may require turning off BIOS in ROM from the tirtos_builds project's .cfg file, which for good measure you might want to compare against the configuration used by the rest of your project (for example, if BIOS.swiEnabled = true;).  You can also refer to the TI-RTOS Kernel User's Guide.  Does behavior change if you use callback mode instead of blocking and post/pend semaphores?  There are examples in the TI Drivers Runtime API I2C.h module.  

    Regards,
    Ryan

  • Hey Ryan,

    thanks for the hint concerning the taskFxn. That was apparently the problem. Easy solution :)

    static void Sensors_taskFxn() 
    {
    	// Initialize application
    	Sensors_init();
    	for (;;) {
    		Sensors_readTemp();
    		Task_sleep(READ_TEMP_TIME);
    	}
    }

    I wanted to restructure that taskFxn anyway but didn't thought that this might have caused the problem.

    Kind Regards