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.

Variable scope question

I'm have some issues understanding what is going on in the below code.  When I run the first code block i get a valid return value in rdac from an I2C device.  The returned value checks out with the parts data sheet.  Here is the code that works.

//*****************************************************************************
//
// interrupts.c - Interrupt preemption and tail-chaining example.
//
// Copyright (c) 2012-2013 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
// 
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 1.1 of the EK-TM4C123GXL Firmware Package.
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_nvic.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "driverlib/i2c.h"


uint32_t rdac;

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif


//*****************************************************************************
//
// I2C ISR
//
//*****************************************************************************
void I2C_ISR()
{



	I2CMasterIntClear(I2C1_BASE);
}






//*****************************************************************************
//
// Get RDAC Value
//
//*****************************************************************************
int GetRDAC()
{
	uint32_t value;

    //
    // Send I2C read instruction
    //
    I2CMasterDataPut(I2C1_BASE, 0x08);	// MSB read command
    I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    while(I2CMasterBusy(I2C1_BASE));

    I2CMasterDataPut(I2C1_BASE, 0x00);	// LSB read command
    I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    while(I2CMasterBusy(I2C1_BASE));

    //
    // Read RDAC reg
    //
    I2CMasterSlaveAddrSet(I2C1_BASE, 0x2F, true);


    I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
    while(I2CMasterBusy(I2C1_BASE));

    value = (I2CMasterDataGet(I2C1_BASE)) << 8;

    I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    while(I2CMasterBusy(I2C1_BASE));

    value += I2CMasterDataGet(I2C1_BASE);


    SysCtlDelay(100);


	return value;
}



int main(void)
{

	rdac = 0;


    //
    // Enable lazy stacking for interrupt handlers.  This allows floating-point
    // instructions to be used within interrupt handlers, but at the expense of
    // extra stack usage.
    //
    FPULazyStackingEnable();

    //
    // Set the clocking to run directly from the crystal.
    //
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    //SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);



    //
    // Enable GPIOA and set pins to I2C1
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
    GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
    GPIOPinConfigure(GPIO_PA6_I2C1SCL);
    GPIOPinConfigure(GPIO_PA7_I2C1SDA);


    //
    // Setup I2C1
    //

    I2CMasterInitExpClk(I2C1_BASE, SysCtlClockGet(), false);
    I2CMasterSlaveAddrSet(I2C1_BASE, 0x2F, false);




    //
    // Enable interrupts to the processor.
    //
    ROM_IntMasterEnable();









    //
    // Loop forever.
    //
    while(1)
    {


    	rdac = GetRDAC();

    	SysCtlDelay(1);


        for(;;){}


    }
}

When I comment out the

SysCtlDelay(1);

instruction and immediately hit the for loop after the GetRDAC() function CCS shows 0 for rdac in the watch window.  When I have the delay in i get the valid value as expected.  The rdac variable is a global variable.  Why can't the value be seen in watch without the delay?  This may be a dumb question, but I would like some guidance regarding this if possible so if I am making a dumb mistake I can correct it. 

Also, this is a working I2C conafiguration for the Tiva C launchpad (TM4C123GH6PMI) so feel free to use it.  It configures I2C1.

Thanks,

Rob

  • Robbie Valentine said:

    When I comment out the

    SysCtlDelay(1);

    instruction and immediately hit the for loop after the GetRDAC() function CCS shows 0 for rdac in the watch window.  When I have the delay in i get the valid value as expected.

    I suspect this has more to do with the device/hardware rather than the tools, and that the SysCtlDelay, for some reason, is required before the variable gets udpated to the correct value. If you step through the assembly code in CCS it might give you a better understanding of exactly which instruction is updating the value of the variable and where in the sequence of code that is happening.

    As to why the SysCtlDelay is required (if that is really the case) I think the folks in the TivaWare forum would be in a better position to answer that.