• Join
  • Sign In with my.TI Login
Texas Instruments
  • Products
  • Applications
  • Tools & Software
  • Support & Community
  • Sample & Buy
  • About TI
Sample & Purchase Cart Sample & Purchase Cart
  • Search
  • Advanced
TI E2E™ Community
  • Support Forums
  • Blogs
  • Groups
  • Videos
  • 简体中文
  • More ...
TI Home » TI E2E Community » Support Forums » Microcontrollers » Stellaris® ARM® Microcontrollers » Stellaris® ARM® LM3S Microcontrollers Forum » I2C not working on LM3S9B90
Share
Stellaris® ARM® Microcontrollers
  • Forum
Options
  • Subscribe via RSS
Helpful Stellaris® LM4F Series Links
  • LM4F Series
  • Stellaris PinMux Utility
  • Stellaris® LM4F120 LaunchPad
  • LM4F MCU Applications
  • LM4F MCU Video
  • ARM Cortex-M4F Whitepaper
  • Stellaris MCU Brochure
  • LM4F232 Eval Kit
  • I2C not working on LM3S9B90

    I2C not working on LM3S9B90

    • sakul
      Posted by sakul
      on Feb 27 2010 16:20 PM
      Prodigy230 points
      Hey all!

      I've been trying to get the I2C to work but failed. Any ideas highly appreciated.

      I want to use the 2nd channel (I2C1) as a master, but cannot even see a single motion on the pins.
      The pins + PCB themselves are OK, I checked via port toggles - all fine. Pullups are where they should be.

      And - to add an info about me and my skill-level: I had no trouble at all writing an I2C interrupt/state machine driver from scratch on ARM7

      Here is my code:

      Code:


       

      somewhere 
      else in advance this line was called: 

      SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_12MHZ);

      then , the init part

      SysCtlPeripheralEnable
      (SYSCTL_PERIPH_GPIOG); 
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ); 
      GPIOPinTypeI2C(SYSCTL_PERIPH_GPIOG, GPIO_PIN_1); 
      GPIOPinTypeI2C(SYSCTL_PERIPH_GPIOJ, GPIO_PIN_0); 
      SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1); 
      I2CMasterInitExpClk(I2C1_MASTER_BASE, SysCtlClockGet(), 0);

      and 
      the very first data sequence does not give any changes on the line and Busy always stays true

      // SEND START 
      I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, address,0) I2CMasterDataPut(I2C1_MASTER_BASE,*data++);
      I2CMasterControl(I2C1_MASTER_BASE,I2C_MASTER_CMD_BURST_SEND_START);

      no signal change, lines remain 1>
      btw: PCB checked -> OK>

      //THIS REMAINS TRUE FOREVER
      while(I2CMasterBusy(I2C1_MASTER_BASE) 







      an interesting fact about the toggle test I made:

      After the toggles, I tried to revert the pintype through these calls to OD with pullup:

      Code:


       
      GPIOPinTypeI2C
      (SYSCTL_PERIPH_GPIOG, GPIO_PIN_1); 
      GPIOPinTypeI2C(SYSCTL_PERIPH_GPIOJ, GPIO_PIN_0); 








      After all, I am surprisingly stuck, so any help would be REALLLY welcome

      cheers
      sakul
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • jrmymllr49452
      Posted by jrmymllr49452
      on Feb 27 2010 18:41 PM
      Expert2110 points
      I had a similar problem with I2S. I was about ready to pull my hair out. Check this out, it could be the problem: you have to configure what pin gets the specific function. So, for example, this sets up I2S to use pin PD6 for the TxSCK:

      GPIOPinConfigure(GPIO_PD6_I2S0TXSCK);

      I believe the #defines you want to pass to the function are in gpio.h. Good luck.
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • sakul
      Posted by sakul
      on Feb 28 2010 08:02 AM
      Prodigy230 points
      Many thanx for that hint

      firstly, it made me quite optimistic to get my problem fixed, as I got the impression, that this code is really mandatory to get it to work and was omitted up to now.

      and secondly, it upset me, because if a manufacturer supplies such a thick libray, it should be more clear when to use what. I was quite sure, the call to
      GPIOPinTypeI2C(SYSCTL_PERIPH_GPIOG, GPIO_PIN_1)
      would be sufficient to set the pin to what I expected.

      Anyway, so I immediately went to add these calls.
      At first, I inspected the source and it stated it for "Tempest Class only"

      So I checked the class first with the CLASS_xxx macros - and yes - Tempest - OK so far.

      these where the extra lines I added:

      GPIOPinConfigure(GPIO_PG1_I2C1SDA);
      GPIOPinConfigure(GPIO_PJ0_I2C1SCL);

      (btw: yes you were right, the defines were where you expected them)

      (and a remark: no call to that function found in the I2C Master sample I had that was supplied by LMI)

      then, when stepping thru , STILL NOT A SINGLE MOTION. the code still stays within the I2CMasterBusy and never gets ready.

      Just to check, I set the PC to the next I2C Write call and then consequently ended up in a hard fault.

      so still really stuck ;((


      But despite the failure, MANY MANY thanx jrmymllr for this good suggestion.

      be well
      sakul

      PS:

      Maybe we'll have only to wait until Easter sunday falls on Pentecost and it'll work fine then ....
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • jrmymllr49452
      Posted by jrmymllr49452
      on Feb 28 2010 20:23 PM
      Expert2110 points
      Hmmm, if you're getting a hard fault be sure you're using the correct defines in the SysCtlPeripheralEnable functions. Upon glancing at your code, it looks like you are, but you are right...this driver library can be *very* tricky sometimes. I spent literally 2-3 days once because I was using the wrong defines for some PWM function. Stupid mistake, yes, although the ASSERT macro would have warned me had I been using them. I also would think that a function like GPIOPinTypeI2C would be enough to make that pin do it's thing, but not so.

      Have you tried studying an I2C example in the "boards" directory in Stellarisware? I'm not sure if there is one, but that has saved me several times. I don't see one in the 9B92 examples, but maybe a 6965 does. They're pretty similar.

      Unfortunately I've never used I2C so I'm just taking some educated guesses. Debugging code on these things can be frustrating! Probably because they're more complex than my low end favorite, PICs.
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • TI Alex
      Posted by TI Alex
      on Mar 01 2010 18:27 PM
      Expert8210 points
      Hi sakul,

      I have played around with I2C1 a little bit and I have some suggestions for you.

      1) By default, pins PJ0 and PG1 are NOT configured for I2C. Just in case your wondering, the "GPIOPinTypeI2C()" function sets the pin up from a GPIO perspective, but it doesn't setup the proper internal MUX connections. To do this properly, you have to use the "set_pinout.c" and "set_pintout.h" functions. These are available in StellarisWare.

      Assuming you have StellarisWare installed, you can find those files in the following directory:

      ".../StellarisWare/boards/dk-lm3s9b96/drivers"

      Add them to your project and then you will have to use the "PinoutSet()" function. To use this for the LM3S9B90, you need to globally define "SIMPLE_PINOUT_SET" to let the compiler know to only execute part of the "PinoutSet()" function (this is because it has some code that is specific to the lm3s9b96 which will execute if you don’t define SIMPLE_PINOUT_SET) . Then in your main function (before you enable the peripherals) call the "PinoutSet()" function.

      This will properly configure the pins. Be sure to still call the "GPIOPinTypeI2C()".


      2) Also, you should try using the

      Code:


       SysCtlPeripheralReset(SYSCTL_PERIPH_I2C1);





      function after you initialize the I2C1 peripheral. This guarantees that the peripheral device is in a known state.

      Hope this helps,

      Alex

      Post edited by: TI Alex, at: 2010/03/01 18:31

      Post edited by: TI Alex, at: 2010/03/01 18:32

      Post edited by: TI Alex, at: 2010/03/01 18:32
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • sakul
      Posted by sakul
      on Mar 02 2010 02:32 AM
      Prodigy230 points


      Thanx, yes I looked closely at the samples in the complete Stellaris package (544 MB)
      I DID NOT FIND A SINGLE CALL to GPIOPinConfigure() there that dealt with I2C. Very surprising.
      Eg some for ETH, but none for I2C




      Many thanx for your post too, but you left me quite confused after having inspected the pinout sample.

      I understand that this one deals primarily with EPI related stuff where an external A/D bus shall be used.

      This is not he case here. I was expecting that GPIOPinConfigure() would properly set the muxes ......

      Post edited by: sakul, at: 2010/03/02 07:51
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Sue Cozart
      Posted by Sue Cozart
      on Mar 02 2010 10:53 AM
      Mastermind49810 points
      Hi Sakul,
      I'm sorry for your confusion and frustration. We don't have an example for the I2C on the 9B90 board because you can't use I2C on this board. Right now, the way we set things up, the examples that are included with a board can all be run and tested on the board, and I2C doesn't fit that description on the 9B90 board. We have recognized this weakness, especially in light of the Tempest products requiring the GPIOPinConfigure() call that is not in examples from previous devices. We have developed a plan to create an examples directory that includes simple code examples such as your customer requires with clear comments. Obviously it will take us some time to create all of these examples, but over time this will address this concern.

      I think what Alex was trying to tell you is that the set_pinout.c function provides an example of how to configure the pins on the device. Much of it is specifically concerned with the DK-LM3S9B96 board and its daughter boards, but if you look down at line 1170, you can see an example of how to configure an entire device. If you don't want to configure the entire device, but only the 2 I2C1 pins, I would recommend just adding the necessary GPIOPinConfigure() calls into your code.

      I would also suggest reviewing the App Note on Pin Muxing AN-01275.

      Regards,
      Sue
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • sakul
      Posted by sakul
      on Mar 02 2010 11:35 AM
      Prodigy230 points
      Sue,

      thanx for now. The tempest call for PinConfiguration is meanwhile included, as I stated in one of the posts above. But still no success. As our hardware - by chance - includes both I2C0 terminals to the outer world, I gave them a try as well, but failed too.

      So right now I have the impression that weak documentation paires here perfectly with a dumb thing I am overseing... eg maybe I killed my I2C slave .. so I can wait for an ACK til judgement day...


      I will again post an exact listing of what I've been doing tomorrow.

      O btw - does the I2C engine need interrupts in any form? Up to now I never took care of them as I wanted a simple example.
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • TI Alex
      Posted by TI Alex
      on Mar 02 2010 16:29 PM
      Expert8210 points
      sakul,

      I did not use any interrupts when I got the I2C1 to work. And I should have clairified yesterday, be sure to actaully modify the pins you want to use.

      Here I changed PortG from:

      //
      // GPIO Port G pins
      //
      HWREG(GPIO_PORTG_BASE + GPIO_O_PCTL) = GPIO_PCTL_PG0_EPI0S13 |
      GPIO_PCTL_PG1_EPI0S14 |
      GPIO_PCTL_PG7_EPI0S31;

      To

      //
      // GPIO Port G pins
      //
      HWREG(GPIO_PORTG_BASE + GPIO_O_PCTL) = GPIO_PCTL_PG0_EPI0S13 |
      GPIO_PCTL_PG1_I2C1SDA |
      GPIO_PCTL_PG7_EPI0S31;



      and Port J from:

      //
      // GPIO Port J pins
      //
      HWREG(GPIO_PORTJ_BASE + GPIO_O_PCTL) = GPIO_PCTL_PJ0_EPI0S16 |
      GPIO_PCTL_PJ1_EPI0S17 |
      GPIO_PCTL_PJ2_EPI0S18 |
      GPIO_PCTL_PJ3_EPI0S19 |
      GPIO_PCTL_PJ4_EPI0S28 |
      GPIO_PCTL_PJ5_EPI0S29 |
      GPIO_PCTL_PJ6_EPI0S30;


      To

      //
      // GPIO Port J pins
      //
      HWREG(GPIO_PORTJ_BASE + GPIO_O_PCTL) = GPIO_PCTL_PJ0_I2C1SCL |
      GPIO_PCTL_PJ1_EPI0S17 |
      GPIO_PCTL_PJ2_EPI0S18 |
      GPIO_PCTL_PJ3_EPI0S19 |
      GPIO_PCTL_PJ4_EPI0S28 |
      GPIO_PCTL_PJ5_EPI0S29 |
      GPIO_PCTL_PJ6_EPI0S30;


      If that still doesn't work, I would recommend trying some external pullups and see if that clears the flag.

      Alex
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • sakul
      Posted by sakul
      on Mar 03 2010 10:51 AM
      Prodigy230 points
      Hello again.

      as I wrote, I turned to I2C0 to see if I can get any motion there, but still none. Added 2 pullups of course. I wonder what sort of moronism will finally turn out to be my fault ...

      anyway ... I decided to remove the I2C slave device in order to remove another error-source. The assumption I took is that the initial SEND of the first byte should always take place, then AFTER the first byte the master oughta wait for the acknowledge-bit - that would never come in this special case. So I decided to go into a loop of resets and sending the first byte again.

      So first question: is the idea right - in general?

      Does the first transfer take place after I2C_MASTER_CMD_BURST_SEND_START or I2C_MASTER_CMD_SINGLE_SEND (tried both w.o. success)


      To aid the debugging, I added a 1 khz square wave that gives me here a perfect trigger condition.
      But I never see the smallest motion on the I2C0 channel. What else ? any suggestions ?


      Attached is the ENTIRE CODE I step thru after reset. There is nothing else hidden elsewhere.


      #define LED_ON GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3,0);
      #define LED_OFF GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3,GPIO_PIN_3);
      int main (void)
      {
      SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_12MHZ);
      SysCtlDelay(800000); // just a short delay

      // Just as DBG Aid
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
      GPIOPinTypeGPIOOutputOD(GPIO_PORTF_BASE,GPIO_PIN_3);

      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
      SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);

      GPIOPinTypeI2C(SYSCTL_PERIPH_GPIOB, GPIO_PIN_3|GPIO_PIN_2);
      //->GPIODirModeSet
      // sets GPIO_O_DIR + GPIO_O_AFSEL
      //->GPIOPadConfigSet
      // sets all the pin params

      GPIOPinConfigure(GPIO_PB2_I2C0SCL); //0x00010801 Port 1 , shift 8, value 1
      GPIOPinConfigure(GPIO_PB3_I2C0SDA); //0x00010c01 Port 1 , shift 12, value 1
      // Sets the GPIO_O_PCTL Register

      I2CMasterInitExpClk(I2C0_MASTER_BASE, SysCtlClockGet(), 0);

      AGAIN:
      LED_ON; SysCtlDelay(5000L);
      LED_OFF; SysCtlDelay(5000L);
      SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);

      I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, 0x70, false); // Set the slave address + SEND direction
      I2CMasterDataPut(I2C0_MASTER_BASE,42); // Write a dummy data byte to the port
      I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);// Start the transfer.

      goto AGAIN;

      Post edited by: sakul, at: 2010/03/03 17:49
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • sakul
      Posted by sakul
      on Mar 04 2010 05:51 AM
      Prodigy230 points
      Hello again. The state is still really infuriating. No motion at the pins at all
      A deeper inspection of the Stellaris sources showed this:

      >3200 c/cpp Files , a total of >0.5 GB

      2 files contained GPIO_O_PCTL and a total of 22 files came with GPIOPinConfigure and there there was no direct access to 0x52c. (always omitting the driver sources themselves)
      None of the examples dealt with I2C.

      So in the end, as a Tempest user, the examples really do not help.
      All I am kindly asking for is an ultra-simple piece of code (less or around maybe 10-15 lines of code) to get the I2C signal lines to move for the first time.

      If you take a look at the post above, just half a page of code .. can the situation ever be easier for a support engineer to directly lay hands on the error?
      Meanwhile we tried a second board with the same results.
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • TI Alex
      Posted by TI Alex
      on Mar 04 2010 09:12 AM
      Expert8210 points
      sakul,

      I do see a minor bug that might fix your problems.

      GPIOPinTypeI2C(SYSCTL_PERIPH_GPIOB, GPIO_PIN_2 | GPIO_PIN_3);

      should be:

      GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3);

      If that doesn't work, you can try the internal loopback mode. In loopback mode, the SDA and SCL signals from the master and slave modules are tied together.

      Here is some code you can try to use the loopback mode to test the I2C0:

      unsigned long ulSlaveReceive = 0;

      //
      // Turn on I2S0 and reset to a known state
      //
      SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
      SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);

      //
      // Enable loopback
      //
      HWREG(I2C0_MASTER_BASE + I2C_O_MCR) = 0x01;

      //
      // Configure the PortB pins for I2C0
      //
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
      GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3);

      //
      // Enable and Initalize MASTER/SLAVE
      //
      I2CMasterEnable(I2C0_MASTER_BASE);
      I2CMasterInitExpClk(I2C0_MASTER_BASE, SysCtlClockGet(), false);
      I2CSlaveEnable(I2C0_SLAVE_BASE);
      I2CSlaveInit(I2C0_SLAVE_BASE, 0x3C);

      //
      // Set the slave address, and set the Master to Transmit mode
      //
      I2CMasterSlaveAddrSet(I2C0_MASTER_BASE, 0x3C, false);

      //
      // Place the character to be sent in the data register
      //
      I2CMasterDataPut(I2C0_MASTER_BASE, 'J');

      //
      // Initiate the send of the character from Master to Slave
      //
      I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);

      //
      // Wait until the slave has received the character.
      //
      while(!(I2CSlaveStatus(I2C0_SLAVE_BASE) & I2C_SCSR_RREQ)){}

      //
      // Read the character from the slave.
      //
      ulSlaveReceive = I2CSlaveDataGet(I2C0_SLAVE_BASE);

      //
      // Delay until transmission completes
      //
      while(I2CMasterBusy(I2C0_MASTER_BASE))
      {
      }

      if(ulSlaveReceive == 'J')
      {
      /* Success */
      while(1){}
      }
      else
      {
      /* Failure */
      while(1){}
      }


      Regards,

      Alex
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • sakul
      Posted by sakul
      on Mar 04 2010 09:43 AM
      Prodigy230 points
      Alex,

      first of all many thanx for your thorough inspection of my sources. You are right , but so was my code too, I just for whatever reason ruined it while pasting.

      so my initial code fragment was OK. And it is obviously still not working.

      Many thanx for the loopback idea. I gave it a try for the 0 channel - and - guess what - working. I got my 'J' without any problems, and even was capable to modify the program to get a 'N'.

      So at least, at the end of this day, we have secure proof that I am at least some sort of a member of the hominoidea superfamily.

      thank you !
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • sakul
      Posted by sakul
      on Mar 09 2010 05:12 AM
      Prodigy230 points
      this topis is still open, there is no sulition yet ;(
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • jrmymllr49452
      Posted by jrmymllr49452
      on Mar 09 2010 07:30 AM
      Expert2110 points
      sakul wrote:
      this topis is still open, there is no sulition yet ;(

      That is really frustrating. If I were you, I'd open a case with TI. Someone will contact you directly. I've used it before, although it ended up that I mistakenly used the wrong #define.
      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    123
    TI E2E™ Community
    • Support Forums
    • Blogs
    • Videos
    • Groups
    • Site Support & Feedback
    • Settings
    TI E2E™ Community Groups
    • TI University Program
    • Make the Switch
    • Microcontroller Projects
    • Motor Drive & Control
    Other Communities
    • Deyisupport
    • Designsomething.org
    • beagleboard.org
    • TI on Element 14
    • TI on TechXchangeSM
    Other Technical & Support Resources
    • WEBENCH® Design Center
    • Product Information Centers
    • Technical Documents
    • TI Design Network
    • TI Technical Articles
    • TI Training

    All content and materials on this site are provided "as is". TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with regard to these materials, including but not limited to all implied warranties and conditions of merchantability, fitness for a particular purpose, title and non-infringement of any third party intellectual property right. TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with respect to these materials. No license, either express or implied, by estoppel or otherwise, is granted by TI. Use of the information on this site may require a license from a third party, or a license from TI.

    Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms of Use of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms of Use of this site. TI, its suppliers and providers of content reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.

    Follow Us Texas Instruments on Facebook Texas Instruments on Twitter Texas Instruments on LinkedIn Texas Instruments on Google+
    TI Worldwide | Contact Us | my.TI Login | Site Map | Corporate Citizenship | mobile m.ti.com (Mobile Version)

    TI is a global semiconductor design and manufacturing company. Innovate with 100,000+ analog ICs and
    embedded processors, along with software, tools and the industry’s largest sales/support staff.

    © Copyright 1995-2013 Texas Instruments Incorporated. All rights reserved.
    Trademarks | Privacy Policy | Terms of Use