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.

MSP430F5528 I2C Drivers with TI-RTOS

Other Parts Discussed in Thread: MSP430F5528, MSP430WARE

Hello,

I've been able to setup the TI-RTOS for use with the MSP540F5528, but I'm having trouble getting the I2C driver working. When I call I2C_transfer() the device locks up. I have an older firmware that doesn't use the TI-RTOS but the I2C interface works correctly and the hardware has all be verified (I2C lines with pull-up resistors, etc.).

I'm using the following tools:

  • CodeComposer Studio v6.0.1.00040 
  • TI-RTOS for MSP430 v2.10.01.38
  • XDC Tool Core v3.30.05.60

My project has the following files:

  • Board.h
  • MSP430F5528.h
  • MSP430F5528.c
  • empty.c
  • empty.cfg

I'll post what I believe to be the relevant code for my problem, but let me know if I need to post anything else.

____MSP430F5528.h____

/*!
 *  @def    MSP430F5528_I2CName
 *  @brief  Enum of I2C names on the MSP430F5528 dev board
 */
typedef enum MSP430F5528_I2CName {
    MSP430F5528_I2CB0 = 0,
    MSP430F5528_I2CB1 = 1,

    MSP430F5528_I2CCOUNT
} MSP430F5528_I2CName;

/*!
* @brief Initialize board specific I2C settings
*
* This function initializes the board specific I2C settings and then calls
* the I2C_init API to initialize the I2C module.
*
* The I2C peripherals controlled by the I2C module are determined by the
* I2C_config variable.
*/
extern void MSP430F5528_initI2C(void);

____MSP430F5528.c____

/*
 *  =============================== I2C ===============================
 */
/* Place into subsections to allow the TI linker to remove items properly */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_SECTION(I2C_config, ".const:I2C_config")
#pragma DATA_SECTION(i2cUSCIBHWAttrs, ".const:i2cUSCIBHWAttrs")
#endif

#include <ti/drivers/I2C.h>
#include <ti/drivers/i2c/I2CUSCIB.h>


/* I2C objects */
I2CUSCIB_Object i2cUSCIBObjects[MSP430F5528_I2CCOUNT];

/* I2C configuration structure */
const I2CUSCIB_HWAttrs i2cUSCIBHWAttrs[MSP430F5528_I2CCOUNT] = {
	{
		USCI_B0_BASE,
		USCI_B_I2C_CLOCKSOURCE_SMCLK
	},
	{
		USCI_B1_BASE,
		USCI_B_I2C_CLOCKSOURCE_SMCLK
	}
};

const I2C_Config I2C_config[] = {
	{
		&I2CUSCIB_fxnTable,
		&i2cUSCIBObjects[0],
		&i2cUSCIBHWAttrs[0]
	},
	{
		&I2CUSCIB_fxnTable,
		&i2cUSCIBObjects[1],
		&i2cUSCIBHWAttrs[1]
	},
	{NULL, NULL, NULL}
};



/*
 *  ======== MSP430F5528_initI2C ========
 */
void MSP430F5528_initI2C(void)
{
    GPIO_setAsPeripheralModuleFunctionInputPin(
        GPIO_PORT_P4,
        GPIO_PIN1 | GPIO_PIN2);

    I2C_init();
}

____Board.h____

#include "MSP430F5528.h"

#define Board_initI2C               MSP430F5528_initI2C

#define Board_I2C0                  MSP430F5528_I2CB0
#define Board_I2C1                  MSP430F5528_I2CB1
#define Board_I2C_FDC1004           MSP430F5528_I2CB1

____empty.c____

/*
 *  ======== empty.c ========
 */
/* XDCtools Header files */
#include <xdc/std.h>
#include <xdc/cfg/global.h>
#include <xdc/runtime/System.h>

/* BIOS Header files */
#include <ti/sysbios/BIOS.h>

/* TI-RTOS Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/I2C.h>

/* Board Header file */
#include "Board.h"

/*
 *  ======== heartBeatFxn ========
 *  Toggle the Board_LED0. The Task_sleep is determined by arg0 which
 *  is configured for the heartBeat Task instance.
 */
Void heartBeatFxn(UArg arg0, UArg arg1)
{
    while (1) {
        Task_sleep((unsigned int)arg0);
        GPIO_toggle(Board_LED_GRN);
        GPIO_toggle(Board_LED_RED);
	}
}

void i2cFxn(){
	 // Test I2C interface
	    I2C_Handle i2c;
	    I2C_Params i2cParams;
	    I2C_Params_init(&i2cParams);
	    i2cParams.bitRate = I2C_400kHz;
	    i2cParams.transferMode = I2C_MODE_BLOCKING;
	    i2cParams.transferCallbackFxn = NULL;
	    i2c = I2C_open(Board_I2C1, &i2cParams);
	    if (i2c == NULL) {
	     /* Error opening I2C */
	        System_printf("Opening I2C failed...\n");
	        /* SysMin will only print to the console when you call flush or exit */
	        System_flush();
	    }

	    I2C_Transaction i2cTransaction;
	    UChar writeBuffer[1] = 0xFF;
	    UChar readBuffer[2] = {0,0};
	    Bool transferOK;
	    i2cTransaction.slaveAddress = 0x50; /* 7-bit peripheral slave address */
	    i2cTransaction.writeBuf = writeBuffer; /* Buffer to be written */
	    i2cTransaction.writeCount = 1; /* Number of bytes to be written */
	    i2cTransaction.readBuf = readBuffer; /* Buffer to be read */
	    i2cTransaction.readCount = 2; /* Number of bytes to be read */
	    System_printf("Starting the transfer\n");
	    System_flush();
	    transferOK = I2C_transfer(i2c, &i2cTransaction); /* Perform I2C transfer */
	    if (!transferOK) {
	     /* I2C bus fault */
	        System_printf("Reading device ID failed...\n");
	        /* SysMin will only print to the console when you call flush or exit */
	        System_flush();
	    }
	    else{

	       System_printf("Reading 0xFF = %u\n", readBuffer[0]);
	       /* SysMin will only print to the console when you call flush or exit */
	       System_flush();
	    }
}

/*
 *  ======== main ========
 */
int main(void)
{
    /* Call board init functions. */
    Board_initGeneral();
    Board_initGPIO();
    Board_initI2C();

    /* Turn on user LED */
    GPIO_write(Board_LED_GRN, Board_LED_ON);
    GPIO_write(Board_LED_RED, Board_LED_OFF);

    System_printf("Starting the example\n");
    System_flush();

    /* Start BIOS */
    BIOS_start();

    return (0);
}

____.empty.cfg____

/*
 *  ======== empty.cfg ========
 */

/* ================ General configuration ================ */
var Defaults = xdc.useModule('xdc.runtime.Defaults');
var Diags = xdc.useModule('xdc.runtime.Diags');
var Error = xdc.useModule('xdc.runtime.Error');
var Log = xdc.useModule('xdc.runtime.Log');
var Main = xdc.useModule('xdc.runtime.Main');
var Memory = xdc.useModule('xdc.runtime.Memory');
var System = xdc.useModule('xdc.runtime.System');
var Text = xdc.useModule('xdc.runtime.Text');

var BIOS = xdc.useModule('ti.sysbios.BIOS');
var Clock = xdc.useModule('ti.sysbios.knl.Clock');
var Task = xdc.useModule('ti.sysbios.knl.Task');
var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem');
//var FatFS = xdc.useModule('ti.sysbios.fatfs.FatFS');

/*
 *  Program.stack is ignored with IAR. Use the project options in
 *  IAR Embedded Workbench to alter the system stack size.
 */
if (!Program.build.target.$name.match(/iar/)) {
    /*
     *  Reducing the system stack size (used by ISRs and Swis) to reduce
     *  RAM usage.
     */
    Program.stack = 0x300;
}

/* ================ System configuration ================ */
var SysMin = xdc.useModule('xdc.runtime.SysMin');
System.SupportProxy = SysMin;
SysMin.bufSize = 128;

/* ================ Logging configuration ================ */
var LoggingSetup = xdc.useModule('ti.uia.sysbios.LoggingSetup');
LoggingSetup.loadLoggerSize = 128;
LoggingSetup.mainLoggerSize = 256;
LoggingSetup.sysbiosLoggerSize = 256;

/* ================ Kernel configuration ================ */
/* Use Custom library */
var BIOS = xdc.useModule('ti.sysbios.BIOS');
BIOS.libType = BIOS.LibType_Custom;
BIOS.logsEnabled = true;
BIOS.assertsEnabled = true;
BIOS.heapSize = 512;

var task0Params = new Task.Params();
task0Params.instance.name = "heartBeat";
task0Params.arg0 = 1000;
task0Params.stackSize = 512;
task0Params.priority = 2;
Program.global.heartBeatTask = Task.create("&heartBeatFxn", task0Params);

/* ================ Driver configuration ================ */
var TIRTOS = xdc.useModule('ti.tirtos.TIRTOS');
TIRTOS.useGPIO = true;
TIRTOS.useI2C = true;
var task1Params = new Task.Params();
task1Params.instance.name = "i2cTsk";
Program.global.i2cTsk = Task.create("&i2cFxn", task1Params);
var hwi0Params = new Hwi.Params();
hwi0Params.instance.name = "hwi0";
hwi0Params.arg = 1;
Program.global.hwi0 = Hwi.create(45, "&I2CUSCIB_hwiIntFxn", hwi0Params);

Please let me know if there's anything that looks incorrect!

Thank you,

Blair

  • Hi Blair,

    I think the problem lies in your pin mux configuration.  Checking the datasheet, I saw Port 4 pins can be multiplexed to many different peripherals so PMAP APIs are used to assign the desired function.  You need to add something like the following (remember to edit to meet your requirements!!):

    const uint8_t port_mapping[] = {
        //Port P4:
        PM_UCB1SDA,
        PM_UCB1CLK,
        PM_NONE,
        PM_NONE,
        PM_NONE,
        PM_NONE,
        PM_NONE,
        PM_NONE
    };
    
    PMAP_initPortsParam initPortsParam = {0};
    initPortsParam.portMapping = port_mapping;
    initPortsParam.PxMAPy = (uint8_t  *)&P4MAP01;
    initPortsParam.numberOfPorts = 1;
    initPortsParam.portMapReconfigure = PMAP_DISABLE_RECONFIGURATION;
    PMAP_initPorts(PMAP_CTRL_BASE, &initPortsParam);
    

    Hope this helps,

    -- Emmanuel

  • Hi Emmanuel,

    Thanks for the advice! I'll give that a try. Would the PMAP calls belong in the initI2c function or somewhere else?

    Regards,

    Blair

  • Hi Blair,

    Yes, they should be with the regular pin mux configuration in initI2C

    Regards,
    -- Emmanuel
  • Hi Emmanuel,

    Which header files do I need to include for the PMAP functions? Just copying the code in I cannot compile it and I can't find any reference to the PMAP functions in the TI-RTOS or SYS/BIOS guides.

    Another question, wouldn't this line accomplish the same thing as what you recommended but with the TI-RTOS GPIO functions?

    GPIO_setAsPeripheralModuleFunctionInputPin( GPIO_PORT_P4, GPIO_PIN1 | GPIO_PIN2);

    Thanks!

    Regards,
    Blair

  • Hi Blair,

    The PMAP functions are not part of TI-RTOS, they are specific to MSP430 devices and are part of MSP430ware driverlib.  TI-RTOS already adds these files to your include path (as well as the driverlib library), you need only add "#include <pmap.h>" to the top of your board.c file to use the APIs.  

    Blair Conner said:

    Another question, wouldn't this line accomplish the same thing as what you recommended but with the TI-RTOS GPIO functions?

    GPIO_setAsPeripheralModuleFunctionInputPin( GPIO_PORT_P4, GPIO_PIN1 | GPIO_PIN2);

    No, the API above will only put the pin in peripheral mode (rather than a regular GPIO pin), you need to use the PMAP APIs to assign which peripheral function you want on a particular pin.  I think it would be good for you to take a peek at section 13 of the Family Users Guide (link).

    Regards,

    -- Emmanuel

  • Thank you for the link. I'll read through that this morning. When I add the "pmap.h" file I still get a compilation error and warning. 

    • "PMAP_initPortsParam" is undefined
    • "PMAP_initPorts" declared implicitly

    I used Notepad++ to search through ccs's include files for these functions but wasn't able to find them. Looking through "pmap.h", I only see a single function defined "PMAP_configurePorts". 

  • Hi Blair,

    I just noticed that the code I posted is for a later version of MSP430ware (1.97.00.47).  The code for the version shipped in TI-RTOS (1.80.01.03) will look more like this:

    const uint8_t port_mapping[] = {
        //Port P4:
        PM_UCB1SDA,
        PM_UCB1CLK,
        PM_NONE,
        PM_NONE,
        PM_NONE,
        PM_NONE,
        PM_NONE,
        PM_NONE
    };
    
    PMAP_configurePorts(PMAP_CTRL_BASE, 
                        (const uint8_t*)port_mapping, 
                        (uint8_t*)&P4MAP01,
                        1, 
                        PMAP_DISABLE_RECONFIGURATION);
    

    Hope this helps,

    -- Emmanuel