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.

How To: Init I2C on the LM4F232

Hello,

We had a a bit of a hard time getting the right combination of inits and pin assignements to get the I2C port on the EK-LM4F232 board to work.  But this code did the trick:

 

----------------------------------------

void InitI2C1()

{

    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

 

    GPIOPinConfigure(GPIO_PA6_I2C1SCL);  //Setup Mux

    GPIOPinConfigure(GPIO_PA7_I2C1SDA);

    GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7); //Set up direction

 

    //Reconfigure for correct operation

    GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_6, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

    GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD);

 

    I2CMasterInitExpClk(I2C1_MASTER_BASE, SysCtlClockGet(), false);

 

    IntEnable(INT_I2C1);

    I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, SLAVE_ADDRESS, false);

    I2CMasterIntEnableEx(I2C1_MASTER_BASE,I2C_MASTER_INT_DATA | I2C_MASTER_INT_TIMEOUT); }

 

 

  • Thanks this - we too had "bit" of difficulty.  We used same pins as you - although our device is LM4F231 (64 pin MCU).  Our coding bit different - may be useful to you/others...  Note: we did not employ I2C interrupts during our test/verification of this code and we did not find any benefit from GPIOPadConfigSet() calls...  We correctly configured & transacted with an 8 bit GPIO expander via I2C...

            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        
            GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
            ROM_GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);   
       
            ROM_GPIOPinConfigure(GPIO_PA6_I2C1SCL);   
            ROM_GPIOPinConfigure(GPIO_PA7_I2C1SDA);

            ROM_I2CMasterInitExpClk(I2C1_MASTER_BASE, ROM_SysCtlClockGet(), false);
            ROM_SysCtlDelay(10000);  // delay mandatory here - otherwise portion of SlaveAddrSet() lost! 
       
            ROM_I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, 0x20, false); // Write
            ROM_I2CMasterDataPut(I2C1_MASTER_BASE, 0x1); // Mode Cntl:
            // Initiate send of character from Master to Slave
            ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);
     
            while(ROM_I2CMasterBusy(I2C1_MASTER_BASE))  {}

            ROM_I2CMasterDataPut(I2C1_MASTER_BASE, 0x3);  // bits 0,1 In - rest Out
            ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
           
            while(ROM_I2CMasterBusy(I2C1_MASTER_BASE))  {}

    Further note: past several DRL-SW-User Guides direct this GPIOPinType Usage when the target MCU is M4F, Blizzard.

    12.2.2.28 GPIOPinTypeI2CSCL

    Configures pin(s) for use as SCL by the I2C peripheral.

    Prototype:

    void

    GPIOPinTypeI2CSCL(unsigned long ulPort,

    unsigned char ucPins)

    Parameters:  ulPort   is the base address of the GPIO port.

    ucPins is the bit-packed representation of the pin(s).

    Description:   The I2C pins must be properly configured for the I2C peripheral to function correctly. This function provides the proper configuration for the SCL pin(s).   The pin(s) are specified using a bit-packed byte, where each bit that is set identifies the pin to be accessed, and where bit 0 of the byte represents GPIO port pin 0, bit 1 represents GPIO port pin 1, and so on.

    Note:  This function should only be used for Blizzard-class devices. It cannot be used to turn any pin into an I2C SCL pin; it only configures an I2C SCL pin for proper operation. Devices with flexible pin muxing also require a  GPIOPinConfigure()  function call.

  • Thanks for sharing, guys!

  • Thank you. This post was very, very helpful.

  • Sir - thanks your kind comment - appreciation makes effort worthwhile...

  • Hi Mike, 
    I'm still having issues running the I2C code on my LM4F232. I've tried to run the one you posted, but no luck. With the following code, I am getting at least an SDA signal out, but no SCL. I've tried different ways on setting up the SCL pin, and still get nothing:
    void

     
    i2c(void)
    {

    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);

    //

       

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //

    I2CMasterEnable(I2C1_MASTER_BASE);
      
      delay();
        ROM_GPIOPinConfigure(GPIO_PA7_I2C1SDA);
        ROM_GPIOPinConfigure(GPIO_PA6_I2C1SCL); //Setup Mux

    GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7); //Set up direction

    GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_6, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

    GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);


    //   //Sets Clock Rate of I2C - 100kbps

     I2CMasterInitExpClk(I2C1_MASTER_BASE, SysCtlClockGet(),false);

      

    //Set Slave Address

       

    I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, SLAVE_ADDRESS, false);       
    //

                 

    // Place the data to be sent in the data register

                 

    I2CMasterDataPut(I2C1_MASTER_BASE, 0xFF);
                 
        
    //

         

    I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);
  • Hi Gregory,

    Remove your GPIOPinTypeI2C and GPIOPadConfigSet functions and instead use the lines that cb1 shows above:

            GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
            ROM_GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);    

    The PinType functions configure the pads for proper operation for the peripheral and makes the PadConfigSet function unnecessary.  

    Regards,

    Sue

  • Sue, Thank you so much for helping me with this. So far, if I follow your direction, this is what I get:

     

    I'm using the LM4 eval board, what value of Pull Up should I use?

     

    void i2c(void)
    {
            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
           ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

           

            GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
            ROM_GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
            ROM_GPIOPinConfigure(GPIO_PA6_I2C1SCL);
            ROM_GPIOPinConfigure(GPIO_PA7_I2C1SDA);
            ROM_I2CMasterInitExpClk(I2C1_MASTER_BASE, ROM_SysCtlClockGet(), false);

        

    I2CMasterEnable(I2C1_MASTER_BASE);
        delay();
     

       

    //Sets Clock Rate of I2C - 100kbps

       

    I2CMasterInitExpClk(I2C1_MASTER_BASE, SysCtlClockGet(), false);

           

    //

       

    //

       

    //Set Slave Address

       

    I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, SLAVE_ADDRESS, false);

                     

    //

                 

    // Place the data to be sent in the data register

                 

    //

                 

    I2CMasterDataPut(I2C1_MASTER_BASE, 0xFF);

     

                 

    I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);

    }

  • Hi Gregory,

    4.7 kOhms or 10 kOhms should work fine.

    Regards,

    Sue

  • Hi Sue,

     

    Here is my variant code:

            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);

            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);


    GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);   ------- I've tried both ways GPIOPinTypeI2CSCL() and GPIOPinTypeI2C()

            ROM_GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);


            ROM_GPIOPinConfigure(GPIO_PA6_I2C1SCL);

            ROM_GPIOPinConfigure(GPIO_PA7_I2C1SDA);


    // I added in the Pading, because it seemed to help on SDA.  

    GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);


            ROM_I2CMasterInitExpClk(I2C1_MASTER_BASE, ROM_SysCtlClockGet(), false);

            ROM_SysCtlDelay(10000); 

    // delay mandatory here - otherwise portion of SlaveAddrSet() lost!

           //Reconfigure for correct operation


            ROM_I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, 0x20, false);

    // Write

            ROM_I2CMasterDataPut(I2C1_MASTER_BASE, 0x1);

    // Mode Cntl:

           // Initiate send of character from Master to Slave

    ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);


           delay();

            ROM_I2CMasterDataPut(I2C1_MASTER_BASE, 0x3); 

    // bits 0,1 In - rest Out

    ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);


    ===================================================

    The issue is that SCL will not clock. My goal is to at least get something out on SDA and SCL at the same time. I'm using a LM4F232H5QD Evaluation board. I've tried pull up resistors, and still, SCL will not clock. I've nothing on the other end of my I2C, but a scope. Once I get both SDA and SCL working, I'm planning on connecting a bus monitor for debug.

          

     

  • Gregory,

    You should not use the GPIOPadConfigSet function on the SDA pin.  If you look at the code in gpio.c for the GPIOPinTypeI2C, you can see that the proper GPIOPadConfigSet function is already included:

    //
    // Set the pad(s) for open-drain operation with a weak pull-up.
    //
    GPIOPadConfigSet(ulPort, ucPins, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD_WPU);

    Your statement would not allow the SDA pin to operate correctly, because you do not specify open drain functionality.

    The GPIOPinTypeI2CSCL is used for the SCL pin on the LM4F devices because the open drain functionality is not used on this pin.

    As for why the SCL pin is not outputting a clock, 

    1. Have you verified that no other function is assigned to PA6?
    2. What is your external pull-up value?
    This is not related to why SCL is not clocking, but you should follow cb1's example of using a while statement after the start instead of the delay that you have in your code.
    Regards,
    Sue
  • Hi - am the author of the I2C code extract you've just posted.  Sorry for your trouble.  This exact code has worked now on some 15 LX4F231Q5HR - 64 pin MCUs.  Believe we ran it also on early Eval boards - as you list.  I wrote as we could not get I2C to work until we added GPIOPinTypeI2CSCL().  (and that came directly from the TI SW-DRL-UG.) 

    Suppose that it's possible that other code runs on your board - and "undoes" the I2C code.   Am fearful of your undefined "delay();" should you exit that loop early - or too late (there is a timeout w/in this i2C engine) you will harm the transaction

    Always like to confirm connections/beliefs - suspect that converting these same pins from I2C to simple GPIO - and then toggling both - would eliminate connection and other unexpected modification and/or seizure of these pins.  We pulled both up w/4K7 to 3V3.  I would properly "ohm out" connection from board's edge to actual MCU pin should tips listed not get you, "on Air."   Good luck...  Kindly try & report - I'll expunge if this is the issue...

    *** Update: Sometimes pays "not" to drink your own Kool-Aid...  Possibly the delay placed just following ROM_I2CMasterInitExpClk() in my code extract is confounding!  Recall our MCU is bit different than yours (although M4F) and running @ 50MHz w/25MHz external xtal.  During our early battle w/I2C - we needed this delay.  As I recall - later on it seemed not so important.  Should be simple matter to comment out - shrink or expand - and observe...

    *** Update 2: Since you indicate "more padding needed" suspect that your pull-ups may be too high - or that some form of pin contention is at play.  W/simple 4K7 pull-ups our signals (SCL and SDA) are sharp, robust, and travel good 12-15" to our remote I2C slave.  Without a storage scope - don't expect to "catch or view" the 2 single (SDA) bits of Slave Adr and the Put data.  (0x20 and 0x01)  Even the higher freq SCL may not "persist" long enough to be readily visible/evident...  (unless you "capture/store"...)

  • Thank you all for your help.

    It is working, as of this morning. I switched from Port A to Port B, and for some reason, it works. I didn't change much, except switching the Ports.

    I've hadn't had the chance to ohm the pins back to the M4, but it's worth a try to see why Port A wasn't working.

     

    cb1, thank you for posting your original code. I learned about the ROM functions through your post, and it also helped with troubleshooting the i2c peripheral. I'm also finding that my delay(); is enough to not allow for bus time out. However the while (ROM_I2CMasterBusy(I2C1_MASTER_BASE) is a better choice, and I will be implementing it into my code structure.

    Sue and cb1, thank you for your quick responses, as I've waited days for tech support, only to hit a dead end before. You jumping right in, was a big relief, as talking to someone is help within itself.

    As soon as I get a working code for my board, I will come back and share it.

    -----------------------------

    Initiating I2C

    -----------------------------

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    I2CMasterIntEnable(I2C0_MASTER_BASE);        

    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);

    ROM_GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

    ROM_GPIOPinConfigure(GPIO_PB2_I2C0SCL);

    ROM_GPIOPinConfigure(GPIO_PB3_I2C0SDA);

    GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_2, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);   <<<<<<<<<<<  These PAD configs seem to help in my case.

    GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_3, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD_WPU);

    ROM_I2CMasterInitExpClk(I2C0_MASTER_BASE, ROM_SysCtlClockGet(), false);

  • Gregory Oelfke said:
    GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_3, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);

    Appreciate the Kudos - however, with regard to the above,  "Danger, Will Robinson!"  (strong msg to follow)  You should NOT do this - I2C is meant to be Open Drain - unless "PIN_TYPE_STD" is Open Drain compliant - you will CAUSE data contention between Stellaris & your Slave device.  Not good for either!  (and you risk the further wrath of Ms. Sue...)   

    *** Update: Willing to hazard the guess that you persist w/ "pad" due to mis-marked, mis-read or misapplied pull-up Rs!   (if too high in R waveform will "fuzz.")  The SDA line must regularly shift between output & input - (and does so nicely/automatically) - if you give the pin the chance!     Configuring away from this well-conceived O.D. I2C design "begs" for trouble...

  • Found this in the LM4F232 chip documentation:

     

    "...the SCL pin must not be configured as an open-drain signal, although the internal circuitry causes it to act as if it were an open drain signal."

    No issues as of yet, but I will keep a look out.

    If anyone knows how to do a repeated start using the API functions, that would be helpful!

  • GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);

    This function is in full agreement (and most appropriate) with both SW-DRL-UG-8555 and our M4F data sheet - we have found no benefit from the pad function.  Several thousand I2C transactions - testing for LOS (loss of signal) - over more than 10 different pcbs - over range of temp & vibration.  (i.e. shake/bake)

    No observed - nor measured harm to either M4F MCU or multiple I2C Slave devices.  Remain uncomfortable w/GPIO_PIN_TYPE_STD until specifically blessed by chip maker...  Will be illuminating when you "connect" to real-world device...  (cb1 retreats from this course)

  • Hi Sue,

    My I2C is working now on Port B, and I have  code that can read an address value from a slave. However, I'm running into I2CMasterDataGet (I2C0_MASTER_BASE); bringing back only one byte and it is the last one. I've included  I2CMasterBusy (I2C0_MASTER_BASE); before and have tried it afterwards. When I call these two together, I am still receiving the same byte, but I can see on my monitor, that there is more than one byte being sent. It appears the I2CMasterDataGet (I2C0_MASTER_BASE);is reading the last byte. I should be able to call Master Data get more than once, to receive all bytes, but am having no luck. Is there a way I can loop Master Data Get and read back the two bytes sent?

     

    Thank you

     

     

  • Hi cb1,

    I'm curious.

    Where did you found a 64pins of LM4F?

    Here in Italy it's seems to be not yet available.

    Thanks,

    Ivo

  • @Ivo   (all others - kindly divert)

    Pretty good "get" your part - you must be detail guy.  Firm/this guy have long relationship w/TI and "reasonable" volume.  (don't ask)  I was among 1st to "squawk like crazy about dreadful (to be kind) GPIO/Package on LMI M3 release.  New M4 pretty much solved.  Our parts directly from TI...

    Make the best business case you can to local TI group.  (or - advance pay "Net Jet" round trip for 2 - NYC-Roma - gets you this guy, 64QFP TI M4 on board & 1/2 day consulting...)    

  • cb1,

    Thanks for the answer.

    Any support from TI is denied to me and Italian distributors do not support anymore ... I work in Maxim.

    My B.U is interested in LM4 64pins for develop a demo of our device but today it's seems to be impossible.

    I hope it will be available soon or i will migrate to other M4 ...

    In the meantime I'm working with EK, but I can't wait more!!

    Thanks for your comments!

    Ivo

  • Hello all, and thanks for the discussion.

    I'm going to be implementing I2C soon on this part. Based on all the discussion, what is the final recommended way to configure the I2C pins for this part and initiate a Master transaction? I see the example in the StellarisWare manual but this thread brings up some other recommendations. So is there a summary of all this that you would recommend I use?

    --Derek

  • "Final, recommended," wreaks of (officialdom Only) - clearly not this reporter.  Code I provided worked - continues to work - across mix of M3s - M4 - both in the field and in the lab. 

    We have employed advanced (i.e. higher res. ADCs) and GPIO extenders - and our own unique/advanced character & graphic LCD modules - as our primary I2C targets...

    Others must proclaim, "Final/recommended."

  • Gregory Oelfke said:
    My I2C is working now on Port B, and I have  code that can read an address value from a slave. However, I'm running into I2CMasterDataGet (I2C0_MASTER_BASE); bringing back only one byte and it is the last one.

    Hi Greg,

    I have exactly the same problem you describe in that I can only read the last byte back each time (I know two are being Tx from the slave for each data request it is sent from the Master).  Did you solve your problem ?  I also tried using burst receive mode with

    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT)

    to no avail.

    regards

    Peter

  • I found my problem.  I wasn't using BURST mode properly.  I can now read two consecutive bytes from the slave.  I am now including the code I used to get it working OK in case somebody else has problems using BURST mode. I am not including the pin setup code which you can find explained in the relevant user guides.

    I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, SLAVE_I2C_DEVICE_SLAVE_ADDRESS, true);

    // Tell the master to read data.
    //
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
    while(I2CMasterBusy(I2C0_MASTER_BASE)) {}

    // Read the 1st byte of data from the master.

    ulDataRx[0] = I2CMasterDataGet(I2C0_MASTER_BASE);

    // loop on the following three lines of code to request nth byte of data in the burst
    //I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
    //while(I2CMasterBusy(I2C0_MASTER_BASE)) {}
    //ulDataRx[n] = I2CMasterDataGet(I2C0_MASTER_BASE);

    //request the final (in this case 2nd byte of data) in the burst
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    while(I2CMasterBusy(I2C0_MASTER_BASE)) {}
    //read the final (in this case 2nd byte of data) in the burst
    ulDataRx[1] = I2CMasterDataGet(I2C0_MASTER_BASE);

  • Hi Peter,

     

    Sorry I didn't get a chance to respond earlier to your post. It wouldy seem that you have found a solution to your situation.

    What I believe BURST mode is, is another way of saying REPEATED start. It took me a while to get the order of function calls right, but here is my code structure below as follows. If you look at what makes up a repeated start, then you can put the fucntion calls in sequence. However, I found that delays helped. Not sure if they are needed, but alas, not sure if anyone really knows how these things work at times.

    Good Luck,

    Greg  

    int

    i2c_string

    (

    unsigned char addr)

    {

    ROM_I2CMasterSlaveAddrSet(I2C3_MASTER_BASE, SLAVE_ADDRESS, false);

    // Write Address Set

    ROM_I2CMasterDataPut(I2C3_MASTER_BASE, addr);

    // Places data to write

    ROM_I2CMasterControl(I2C3_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

    // Initiate send of character from Master to Slave


    ROM_SysCtlDelay(10000); 

    // delay mandatory here - otherwise portion of SlaveAddrSet() lost!

    ROM_I2CMasterSlaveAddrSet(I2C3_MASTER_BASE, SLAVE_ADDRESS, true);

    // Write Address Set

    ROM_I2CMasterControl(I2C3_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

    // Initiate send of character from Master to Slave


    ROM_SysCtlDelay(10000); 

    // delay mandatory here - otherwise portion of SlaveAddrSet() lost!

    while(I2CMasterBusy(I2C3_MASTER_BASE));

    {}

    value0 =

    I2CMasterDataGet(I2C3_MASTER_BASE);

       i = 0;

    while (i != value0 )

        {

            ROM_I2CMasterControl(I2C3_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);

    // Initiate send of character from Master to Slave

        ROM_SysCtlDelay(10000); 

    // delay mandatory here - otherwise portion of SlaveAddrSet() lost!

    while(I2CMasterBusy(I2C3_MASTER_BASE));

    {}


    string[i] = I2CMasterDataGet(I2C3_MASTER_BASE);

    ++i;

    }

    ROM_I2CMasterControl(I2C3_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);

    // Initiate send of character from Master to Slave

    return (value0);

  • Hello,

    I've been struggling for a few days now trying to get any I2C port running on the EK-LM4F232 eval board, with very little success.

    When I try using the code you've posted (I've also tried the other code samples in this thread), I seem to get no activity on either the PA6 or PA7 pins.  My expectation is that I should be able to use the functions MasterSlaveAddrSet, MasterDataPut, I2CMasterControl, and at the very least see something happening on my clock line (PA6) with an oscilloscope.   Am I wrong in assuming this?

    One other thing I want to confirm are the macros for GPIO_PA7_I2C1SDA and GPIO_PA6_I2C1SCL.  Are these evaluating to 0x30000000 and 0x03000000 and placing them into the GPIOA_PCTL register? I ask because my header file doesn't seem to have those specific names, instead, they are named GPIO_PCTL_PA7_I2C1SDA and GPIO_PCTL_PA6_I2C1SCL.

    Thanks for your help!

  • Have you included pin_map.h - located w/in driverlib?   This is where both GPIO_PA7_I2CSDA and other reside.

    Depending upon your IDE - inclusion of your MCUs model number LM4F232 may be bit tricky.  You must correctly specify your MCU for pin_map.h to find/decode.

    File pin_map.h is HUGE - and segregated by MCU.   Seems that you're not listing or including linkage to this file correctly.

    2nd post - this very thread - listed code our group (and > 20 follow on post readers) have used with success.  Be sure you've included pull up Rs on both I2C lines - and that your slave device is powered.  Pay special attention to the GPIOPinType for the SCL line.  (1st post in this thread appears to have miscued...)

  • Hi Drew,

    I will try and help you the best I can. If I may, the pins that I used for I2C communication are PD0 and PD1. One thing you might want to look out for, is seeing if anything else is using the pins you've selected on the board. I know this from experience as I had to cut the traces from PA0 and PA1 to the debug chip, as I needed to use them and the chip was keeping the line high.

    Below is how I set up my I2C pins:

    // Initialize the I2C IO module.

                     UARTStdioInit(0);

                     ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C3);

                     ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);              

    I2CMasterIntEnable(I2C3_MASTER_BASE);               

    GPIOPinTypeI2CSCL(GPIO_PORTD_BASE, GPIO_PIN_0);

                    ROM_GPIOPinTypeI2C(GPIO_PORTD_BASE, GPIO_PIN_1);

                    ROM_GPIOPinConfigure(GPIO_PD0_I2C3SCL);

                    ROM_GPIOPinConfigure(GPIO_PD1_I2C3SDA);                     

    GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_PIN_1, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD_WPU);

                    ROM_I2CMasterInitExpClk(I2C3_MASTER_BASE, ROM_SysCtlClockGet(), false);

                    ROM_SysCtlDelay(10000); // delay

  • Seems to be some debate re: "GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_PIN_1, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD_WPU);"

    I2C code I developed (2nd post this thread) did not include - and has worked well w/ multiple LX4F MCUs and long run (6+ months) a variety of I2C Slaves with consistent success.  My belief is that GPIOPinType and GPIOPinConfigure properly manage the set-up/config of the I2C pins.

    Here's a reprint of TI's Sue Cozart's post (7th from top - this thread):

    Hi Gregory,

    Remove your GPIOPinTypeI2C and GPIOPadConfigSet functions and instead use the lines that cb1 shows above:

            GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
            ROM_GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);    

    The PinType functions configure the pads for proper operation for the peripheral and makes the PadConfigSet function unnecessary.  

    Regards,

    Sue

    Your advice re: "sanctity - no competing usage of chosen pins" is spot on - always should be confirmed...  And pull-up Rs are required - both I2C lines should be test/verified as logic "1" prior to any attempted I2C transaction...

  • Thanks to both of you for responding so quickly (and detailed!)

    cb1- you caught both of my issues right away.  pin_map.h was included, but I fell victim to my own naivety by failing to add the predefined PART_LM4F232HQ5D symbol to the project...  That fixed that issue, and then realized my pull up resistors were off as well.  Now have I2C functionality using the code in this thread. 

    (note: I have not included calls to GPIOPadConfigSet)

    Thanks again!

  • Drew - good for you - congrats on your persistence & attention to detail.

    Its possible that "GPIOPadConfigSet()" may be required for the newest, most exotic I2C speed-mode.  But I certainly would never start there.

    These ARM MCUs have extraordinary power & flexibility - but demand great, "attention to detail" - and serious review of MCU datasheet & SW-DRL-UG... 

    Also suggest that you avoid the complications always inherent w/interrupts - until you have the basics of your chosen peripherals test/verified.  KISS remains the best route to a "safe harbor..."

  • Sir,

    How do I make the I2C work at 3.4 mbps. I have been trying to do it by setting all the bits mentioned, but for some reason it is not working. Please help.

  • @Arvind

    If you can send the code that you are using it would be rather useful. Also are you using a TM4C123 or TM4C129 device, StellarisWare or TIVAWare, the information would be very much useful

    Amit

  • I am using TM4C123 device.My code is rather long.But the initialisation for I2C are in the include files and in the main function.

    //******************************************************************************
    //
    // i2s_demo.c - Example program for playing wav files from an SD card.
    //
    // Copyright (c) 2009-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 10636 of the DK-LM3S9D96 Firmware Package.
    //
    //******************************************************************************

    #include <string.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "driverlib/flash.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/udma.h"
    #include "driverlib/systick.h"
    #include "utils/ustdlib.h"
    #include "driverlib/ff.h"
    #include "driverlib/diskio.h"
    #include "utils/uartstdio.h"
    #include "inc/hw_i2c.h"
    #include "driverlib/i2c.h"
    #define I2C_MCS_HS 0x00000010 // High-Speed Enable
    #define I2C_MTPR_HS 0x00000080 // High-Speed Enable
    #define I2C_PP_HS 0x00000001 // High-Speed Capable
    #ifdef DEBUG
    void
    __error__(char *pcFilename, unsigned long ulLine)
    {
    }
    #endif

    #define SLAVE_ADDRESS 0x4D

    unsigned int data_9Bit[2] ={4095, 0};
    unsigned long conv;


    //! This example application demonstrates playing wav files from an SD card that
    //! is formatted with a FAT file system. The application will only look in the
    //! root directory of the SD card and display all files that are found. Files
    //! can be selected to show their format and then played if the application
    //! determines that they are a valid .wav file. Only PCM format (uncompressed)
    //! files may be played.
    //!
    //! For additional details about FatFs, see the following site:
    //! http://elm-chan.org/fsw/ff/00index_e.html
    //
    //******************************************************************************

    unsigned char value1, value2;
    unsigned int flag=1;

    void dac_dec_data(unsigned int value)
    {

    value1 = value/256;
    value2 = value%256;


    if(flag==1)
    {
    I2CMasterDataPut(I2C0_MASTER_BASE, 4095/256);
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);

    while(I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }
    I2CMasterDataPut(I2C0_MASTER_BASE, 4095%256);
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }
    flag=0;


    }
    else
    {

    //will display constant dac value
    I2CMasterDataPut(I2C0_MASTER_BASE, value1);
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);

    while(I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }
    I2CMasterDataPut(I2C0_MASTER_BASE, value2);
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }
    }
    }


    //******************************************************************************
    //
    // The following are data structures used by FatFs.
    //
    //******************************************************************************
    static FATFS g_sFatFs;
    static DIR g_sDirObject;
    static FILINFO g_sFileInfo;
    static FIL g_sFileObject;

    //******************************************************************************
    //
    // The number of SysTick ticks per second.
    //
    //******************************************************************************
    #define TICKS_PER_SECOND 100

    //******************************************************************************
    //
    // Storage for the filename listbox widget string table.
    //
    //******************************************************************************
    #define NUM_LIST_STRINGS 48
    const char *g_ppcDirListStrings[NUM_LIST_STRINGS];

    //******************************************************************************
    //
    // Storage for the names of the files in the current directory. Filenames
    // are stored in format "filename.ext".
    //
    //******************************************************************************
    #define MAX_FILENAME_STRING_LEN (8 + 1 + 3 + 1)
    char g_pcFilenames[NUM_LIST_STRINGS][MAX_FILENAME_STRING_LEN];


    //******************************************************************************
    //
    // Buffer management and flags.
    //
    //******************************************************************************
    #define AUDIO_BUFFER_SIZE 4096
    static unsigned char g_pucBuffer[AUDIO_BUFFER_SIZE];
    unsigned long g_ulMaxBufferSize;

    //
    // Flags used in the g_ulFlags global variable.
    //
    #define BUFFER_BOTTOM_EMPTY 0x00000001
    #define BUFFER_TOP_EMPTY 0x00000002
    #define BUFFER_PLAYING 0x00000004
    static volatile unsigned long g_ulFlags;

    //
    // Globals used to track playback position.
    //
    static unsigned long g_ulBytesRemaining;
    static unsigned short g_usMinutes;
    static unsigned short g_usSeconds;

    //******************************************************************************
    //
    // Handler for buffers being released.
    //
    //******************************************************************************


    //******************************************************************************
    //
    // Basic wav file RIFF header information used to open and read a wav file.
    //
    //******************************************************************************
    #define RIFF_CHUNK_ID_RIFF 0x46464952
    #define RIFF_CHUNK_ID_FMT 0x20746d66
    #define RIFF_CHUNK_ID_DATA 0x61746164

    #define RIFF_TAG_WAVE 0x45564157

    #define RIFF_FORMAT_UNKNOWN 0x0000
    #define RIFF_FORMAT_PCM 0x0001
    #define RIFF_FORMAT_MSADPCM 0x0002
    #define RIFF_FORMAT_IMAADPCM 0x0011

    //******************************************************************************
    //
    // The wav file header information.
    //
    //******************************************************************************

    void SysTickHandler(void)
    {
    SysTickIntDisable();
    disk_timerproc();
    SysTickIntEnable();
    }


    void
    InitConsole(void)
    {

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);


    /* Make the UART pins be peripheral controlled. */
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    //
    // Initialize the UART for console I/O.
    //
    UARTStdioInit(0);
    UARTprintf("hi");
    }

    typedef struct
    {
    //
    // Sample rate in bytes per second.
    //
    unsigned long ulSampleRate;

    //
    // The average byte rate for the wav file.
    //
    unsigned long ulAvgByteRate;

    //
    // The size of the wav data in the file.
    //
    unsigned long ulDataSize;

    //
    // The number of bits per sample.
    //
    unsigned short usBitsPerSample;

    //
    // The wav file format.
    //
    unsigned short usFormat;

    //
    // The number of audio channels.
    //
    unsigned short usNumChannels;
    }
    tWaveHeader;
    static tWaveHeader g_sWaveHeader;

    //******************************************************************************
    //
    // This function can be used to test if a file is a wav file or not and will
    // also return the wav file header information in the pWaveHeader structure.
    // If the file is a wav file then the psFileObject pointer will contain an
    // open file pointer to the wave file ready to be passed into the WavePlay()
    // function.
    //
    //******************************************************************************

    FRESULT
    WaveOpen(FIL *psFileObject, const char *pcFileName, tWaveHeader *pWaveHeader)
    {
    unsigned long *pulBuffer;
    unsigned short *pusBuffer;
    unsigned long ulChunkSize;
    unsigned short usCount;
    unsigned long ulBytesPerSample;
    FRESULT Result;

    pulBuffer = (unsigned long *)g_pucBuffer;
    pusBuffer = (unsigned short *)g_pucBuffer;

    Result = f_open(psFileObject, pcFileName, FA_READ);
    if(Result != FR_OK)
    {
    UARTprintf("1.Result=%d\nERROR Opening!!!",Result);
    return(Result);
    }

    //
    // Read the first 12 bytes.
    //
    Result = f_read(psFileObject, g_pucBuffer, 12, &usCount);
    if(Result != FR_OK)
    {
    UARTprintf("1.Result=%d\nERROR Reading!!!",Result);
    f_close(psFileObject);
    return(Result);
    }


    UARTprintf("Byte 1: %d\n",g_pucBuffer[0]);

    //
    // Look for RIFF tag.
    //
    if((pulBuffer[0] != RIFF_CHUNK_ID_RIFF) || (pulBuffer[2] != RIFF_TAG_WAVE))
    {
    UARTprintf("could not read RIF /n");
    f_close(psFileObject);
    return(FR_INVALID_NAME);
    }

    //
    // Read the next chunk header.
    //
    Result = f_read(psFileObject, g_pucBuffer, 8, &usCount);
    if(Result != FR_OK)
    {
    f_close(psFileObject);
    return(Result);
    }
    //UARTprintf("9.Result=%d\n",Result);
    if(pulBuffer[0] != RIFF_CHUNK_ID_FMT)
    {
    f_close(psFileObject);
    return(FR_INVALID_NAME);
    }

    //
    // Read the format chunk size.
    //

    ulChunkSize = pulBuffer[1];

    if(ulChunkSize > 16)
    {
    f_close(psFileObject);
    return(FR_INVALID_NAME);
    }

    //
    // Read the next chunk header.
    //
    Result = f_read(psFileObject, g_pucBuffer, ulChunkSize, &usCount);
    if(Result != FR_OK)
    {

    f_close(psFileObject);
    return(Result);
    }
    UARTprintf("10.Result=%d\n",Result);

    pWaveHeader->usFormat = pusBuffer[0];
    pWaveHeader->usNumChannels = pusBuffer[1];
    pWaveHeader->ulSampleRate = pulBuffer[1];
    pWaveHeader->ulAvgByteRate = pulBuffer[2];
    pWaveHeader->usBitsPerSample = pusBuffer[7];

    ulBytesPerSample = (pWaveHeader->usBitsPerSample *
    pWaveHeader->usNumChannels) >> 3;

    //
    // Only mono and stereo supported.
    //
    if(pWaveHeader->usNumChannels > 2)
    {
    f_close(psFileObject);
    return(FR_INVALID_NAME);
    }

    //
    // Read the next chunk header.
    //
    Result = f_read(psFileObject, g_pucBuffer, 8, &usCount);
    if(Result != FR_OK)
    {
    f_close(psFileObject);
    return(Result);
    }
    //UARTprintf("g_pucBuffer%d\n",g_pucBuffer);


    if(pulBuffer[0] != RIFF_CHUNK_ID_DATA)
    {
    f_close(psFileObject);
    return(Result);
    }

    //
    // Save the size of the data.
    //
    pWaveHeader->ulDataSize = pulBuffer[1];
    UARTprintf("11.pulBuffer[1]=%d\n",pulBuffer[1]);

    g_usSeconds = pWaveHeader->ulDataSize/pWaveHeader->ulAvgByteRate;
    g_usMinutes = g_usSeconds/60;
    g_usSeconds -= g_usMinutes*60;
    UARTprintf("12.g_usMinutes=%d\n",g_usMinutes);
    UARTprintf("13.g_usSeconds=%d\n",g_usSeconds);


    unsigned int i;
    unsigned int counter=0;

    for(counter = 0;counter <=pulBuffer[1];counter=counter+3)
    {

    Result = f_read(psFileObject, g_pucBuffer, 1, &usCount);
    if(Result != FR_OK)
    {
    UARTprintf("1.Result=%d\nERROR Reading!!!",Result);
    f_close(psFileObject);
    return(Result);
    }
    // UARTprintf("%d",counter);
    // UARTprintf(" = %d\n",g_pucBuffer[0]);
    // UARTprintf("%d",counter+1);
    // UARTprintf(" = %d\n",g_pucBuffer[1]);
    //tBoolean u=00001111;
    //g_pucBuffer[0]=g_pucBuffer[0]&&u;

    g_pucBuffer[1]=0;
    conv=(g_pucBuffer[1]<<8)+(g_pucBuffer[0]);
    //conv=conv&0xFFF0;
    conv=conv<<1;
    //conv=conv&0x0FFF;
    //UARTprintf(" = %d\n",conv);
    dac_dec_data(conv);
    }


    WaveClose(psFileObject);
    return(FR_OK);

    }

    //******************************************************************************
    //
    // This closes out the wav file.
    //
    //******************************************************************************
    void
    WaveClose(FIL *psFileObject)
    {
    //
    // Close out the file.
    //

    UARTprintf("I closed file");
    f_close(psFileObject);
    }


    //******************************************************************************
    //
    // This function will handle stopping the playback of audio. It will not do
    // this immediately but will defer stopping audio at a later time. This allows
    // this function to be called from an interrupt handler.
    //
    //******************************************************************************
    void
    WaveStop(void)
    {
    //
    // Stop playing audio.
    //
    g_ulFlags &= ~BUFFER_PLAYING;
    }


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

    //******************************************************************************
    //
    // The program main function. It performs initialization, then handles wav
    // file playback.
    //
    //******************************************************************************
    int
    main(void)
    {

    /*Set the clocking to run at 20Mhz from the crystal of 8MHz using PLL*/
    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);


    InitConsole();
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    I2CMasterDisable(I2C0_MASTER_BASE);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    // SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    InitConsole();
    /*Configure SysTick for a 100Hz interrupt. The FatFs driver wants a 10 milliseconds interrupt.*/
    SysTickPeriodSet(SysCtlClockGet() / 100);
    SysTickIntRegister(SysTickHandler);
    SysTickEnable();
    SysTickIntEnable();
    /*Enable global interupts*/
    IntMasterEnable();


    FRESULT fresult;

    //I2C initialization
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3);
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE,GPIO_PIN_2);
    I2CMasterInitExpClk(I2C0_MASTER_BASE, SysCtlClockGet(), true);//true for 400kbps mode, false for 100kbps mode
    I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, SLAVE_ADDRESS, false);

    UARTprintf("MOUNT initialize!!!\n");


    fresult = f_mount(0, &g_sFatFs);
    if(fresult != FR_OK)
    {

    UARTprintf("1.fresult=%d\nERROR MOUNT!!!",fresult);
    }

    //
    // Not playing anything right now.
    //
    g_ulFlags = 0;

    UARTprintf("going to play song");
    if(WaveOpen(&g_sFileObject, "song1.wav",&g_sWaveHeader) == FR_OK)
    {
    UARTprintf("I did everything ! Bye \n");
    }


    }

  • @Arvaind

    A few things to start with on HS Mode from Tiva-I2C perspective

    1. The I2CMasterInitExpClk will set the HS Mode, only of the I2C_PP and I2C_PC Register has HSMODE bit set. Please do make sure both bits are set to 1

    2. In the code example I do not see a Stop Condition being put for the I2C Peripheral

    3. The comment mentioned the System Clock to be 20MHz, but the API call would be setting it to 80MHz. The HS Mode will not be set for any frequency less than 40MHz. This is more for you to check otherwise the programming sequence may not hold good.

    On the I2C Specification before you send the Slave Address you need to send the Preamble, which is not the case in your code as the Slave Address is not written again. The I2C Preamble is 00001XXX where XXX is a master code that you have to decide if your system is a multi-master system. Typically the I2C specification requires XXX=000 to be reserved for test and diagnostic, you may want to use something else as the Master Code.

    You would have to re-arrange the code here to remove the

    I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, SLAVE_ADDRESS, false);

    from the main loop and change the dac_dec_data as well to do the following

    #define I2C_HS_PREAMBLE 0000100

    void dac_dec_data(unsigned int value)
    {

    value1 = value/256;
    value2 = value%256;

    I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, I2C_HSPREAMBLE, true);

    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_HS_MASTER_CODE_SEND);

    while(I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }

    I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, SLAVE_ADDRESS, false);

    if(flag==1)
    {


    I2CMasterDataPut(I2C0_MASTER_BASE, 4095/256);
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);

    while(I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }
    I2CMasterDataPut(I2C0_MASTER_BASE, 4095%256);
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }
    flag=0;


    }
    else
    {

    //will display constant dac value
    I2CMasterDataPut(I2C0_MASTER_BASE, value1);
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);

    while(I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }
    I2CMasterDataPut(I2C0_MASTER_BASE, value2);
    I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    while(I2CMasterBusy(I2C0_MASTER_BASE))
    {
    }
    }
    }

    Amit

  • Thank you sir.

    Will take care to do the above..