/var/www/restricted/ssh/stm32/www/stm32circle/ STM CircleOS forum / STM32 Primer 2 Extension connector - I2C problems

Username:     
Password:     
             

Forum

# 1   2009-06-19 16:10:51 STM32 Primer 2 Extension connector - I2C problems

Craig
Member
Registered: 2009-06-03
Posts: 12

STM32 Primer 2 Extension connector - I2C problems

Hello,

I am trying to use the Primer 2's extension connector pins 3 and 4 to communicate with an FPGA on another board using I2C.

I have written a Circle OS application to enable I2C1 and test the I2C read operation, however i am not getting any signals on the  exension connector, not even a START.

Below is the application code:

Application Initialisation function:

enum MENU_code Application_Ini ( void )
    {
    // Ensure that the current OS version is recent enough
    if(strcmp(UTIL_GetVersion(), NEEDEDVERSION) < 0)
        {
        return MsgVersion();
        }


    // TODO: Write your application initialization function here.
   
     
  // Configure the GPIO ports as alternate functions (PB6,7)
  GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);
   
  // Enable I2C1 clock (low speed APB1 peripheral clock)
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
   
  // Enable GPIO B clock (high speed APB2 peripheral clock)
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
   
  // First, initialise and configure the I2C1 peripheral
 
  // Declare an I2C_InitTypeDef structure, with I2C_InitStructure variable
  I2C_InitTypeDef I2C_InitStructure;
 
  // Fill the variable with allowed values of member structure
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;  //only effects fast mode
  I2C_InitStructure.I2C_OwnAddress1 = 0x03A2;
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  I2C_InitStructure.I2C_ClockSpeed = 100000;        // just as an example
 
  // Initialise the I2C peripheral
  I2C_Init(I2C1, &I2C_InitStructure);
 
  // Now enable I2C peripheral
  I2C_Cmd(I2C1, ENABLE);
 
  // I2C1 can now be used through a set of specific I2C functions
      const char msg[] = "Init ok";
 
   
    DRAW_DisplayString( 1, 7, msg, sizeof(msg)); // X, Y, string, length

    return MENU_CONTINUE_COMMAND;
    }


Are there any obvious mistakes or special considerations to take when writing the
Application Handler function?

Any help would be greatly appreciated!

Offline

 

# 2   2009-06-20 15:22:45 STM32 Primer 2 Extension connector - I2C problems

Francis
Administrator
From: France-Grenoble
Registered: 2007-07-09
Posts: 890

Re: STM32 Primer 2 Extension connector - I2C problems

I believe that you missesd the GPIO pins initialization.

Offline

 

# 3   2009-06-22 13:38:31 STM32 Primer 2 Extension connector - I2C problems

Craig
Member
Registered: 2009-06-03
Posts: 12

Re: STM32 Primer 2 Extension connector - I2C problems

Thanks for your help, I have configured the GPIO pins and the RCC now, however there are still no I2C signals seen on the external connector pins when using a logic analyser.  I am aiming to view anything on the pins to begin with.

I cannot think of anything i am missing

Code:

APPLICATION INITIALISATION

// RCC SYSTEM CLOCK CONFIG ----------------------------------------------------/
   
    {

    /* RCC system reset(for debug purpose) */
    RCC_DeInit();

    /* Enable HSE */
    RCC_HSEConfig(RCC_HSE_ON);

    /* Wait till HSE is ready */
    HSEStartUpStatus = RCC_WaitForHSEStartUp();

    if(HSEStartUpStatus == SUCCESS)
    {
        /* Enable Prefetch Buffer */
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

        /* Flash 2 wait state */
        FLASH_SetLatency(FLASH_Latency_2);
   
        /* HCLK = SYSCLK */
        RCC_HCLKConfig(RCC_SYSCLK_Div1);
 
        /* PCLK2 = HCLK */
        RCC_PCLK2Config(RCC_HCLK_Div1);

        /* PCLK1 = HCLK/2 */
        RCC_PCLK1Config(RCC_HCLK_Div2);
   
        /* PLLCLK = 8MHz * 9 = 72 MHz */
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
   
        /* Enable PLL */
        RCC_PLLCmd(ENABLE);

        /* Wait till PLL is ready */
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
        {
        }

        /* Select PLL as system clock source */
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

        /* Wait till PLL is used as system clock source */
        while(RCC_GetSYSCLKSource() != 0x08)
        {
        }
    }
/* Enable peripheral clocks --------------------------------------------------*/
    /* Enable I2C1 clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    /* Enable GPIOB clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
}

   
// GPIO CONFIGURATION --------------------------------------------------------/

  // Configure all GPIOB in open drain AF mode (for different I2C levels)
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; 
  // Initialise the GPIOB Peripheral
    GPIO_Init(GPIOB, &GPIO_InitStructure);
  // Configure the GPIO ports as alternate functions (PB6,7)
    GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);

// I2C CONFIGURATION ---------------------------------------------------------/

  // Declare an I2C_InitTypeDef structure, with I2C_InitStructure variable
    I2C_InitTypeDef I2C_InitStructure; 
  // Fill the variable with allowed values of member structure
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;  //only effects fast mode
    I2C_InitStructure.I2C_OwnAddress1 = 0x03A2;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 100000;       
  // Initialise the I2C1 peripheral
    I2C_Init(I2C1, &I2C_InitStructure);
  // Enable I2C1 peripheral
    I2C_Cmd(I2C1, ENABLE);

APPLICATION HANDLER

  // Master generates START condition to start communication
  I2C_GenerateSTART(I2C1, ENABLE);
 
  // Specify the 7 bit address of the slave FPGA 0x40 to communicate with (as a transmitter)
  I2C_Send7bitAddress(I2C1, 0x20, I2C_Direction_Transmitter);
 
  // Select the internal register address of the Version register 24 in the FPGA
  I2C_SendData(I2C1, 24);
 
  // Send STOP condition on I2C1
  I2C_GenerateSTOP(I2C1, ENABLE);
 



I apologise if these questions have obvious answers, I am a student working on a project.
Thanks

Offline

 

# 4   2009-06-22 15:40:45 STM32 Primer 2 Extension connector - I2C problems

Jierre
Member
Registered: 2009-04-21
Posts: 14

Re: STM32 Primer 2 Extension connector - I2C problems

Hi !

* Have you pulled up your SDA or SCL lines ?

* You should wait between your operation on the I2C bus. There are some flags to check to be sure that the operation has been done.

For example after your start you should put that :

Code:

while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) );

Offline

 

# 5   2009-06-23 06:20:42 STM32 Primer 2 Extension connector - I2C problems

Francis
Administrator
From: France-Grenoble
Registered: 2007-07-09
Posts: 890

Re: STM32 Primer 2 Extension connector - I2C problems

I suggest you look at the MEMSTOLCD example. It is not done for the Primers (but for the Raisonance' Reva board), but it manages the I2c controller to access the MEMS. I should be easy to adapt it to your case.

Offline

 

# 6   2009-06-24 10:13:33 STM32 Primer 2 Extension connector - I2C problems

Craig
Member
Registered: 2009-06-03
Posts: 12

Re: STM32 Primer 2 Extension connector - I2C problems

Thank you very much for the help!

I have carefully looked at the MEMSTOLCD example, and used it as a base for my I2C operation.  I have also initialised the RCC, GPIO and I2C, however i am still having problems when using the application in Circle OS.  The problem occurs after the START is generated, the program sticks in the

   while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

and cannot get past it.

Is this because the START is not generated because i have not pulled up the I2c pins PB6 and PB7?

If so, how do I go about pulling up these pins?  Should it be done externally with 4.7k ohm resistors?  Or with a function for the GPIOs? 
Or is it possible to use a different GPIO pin set up, such as Push-Pull to achieve the I2C operation?

Thanks again!

Offline

 

# 7   2009-06-24 12:31:32 STM32 Primer 2 Extension connector - I2C problems

Jierre
Member
Registered: 2009-04-21
Posts: 14

Re: STM32 Primer 2 Extension connector - I2C problems

Hi !

Your problem probably come indeed of the fact that you don't put pull up resistors.
It is something you do on the hardware. You put one resistor (4.7k should be ok) between your line and VCC.

Good luck but you seem pretty close ;-)

Offline

 

# 8   2009-06-24 14:19:44 STM32 Primer 2 Extension connector - I2C problems

Craig
Member
Registered: 2009-06-03
Posts: 12

Re: STM32 Primer 2 Extension connector - I2C problems

I have pulled up the SCL and SDA lines with 4k7 resistors, and checked this with an oscilloscope, but still no luck un running the application! sad

Here is the Circle OS application code i am using.  The application gets stuck just after the START is generated.  I can't see anything I have missed!

Code:

/* Includes ------------------------------------------------------------------*/
#include "circle_api.h"

/* Private defines -----------------------------------------------------------*/

// The following should be the minimal CircleOS version needed by your application
#define NEEDEDVERSION "V 1.5"

/* Private variables ---------------------------------------------------------*/
    
/* Private functions ---------------------------------------------------------*/
enum MENU_code MsgVersion(void);

/* Public variables ----------------------------------------------------------*/

const char Application_Name[8+1] = {"I2C Test"};      // Max 8 characters

/*******************************************************************************
* Function Name  : Application_Ini
* Description    : Initialization function of Circle_App. This function will
*                  be called only once by CircleOS.
* Input          : None
* Return         : MENU_CONTINUE_COMMAND
*******************************************************************************/
enum MENU_code Application_Ini ( void )
    {
    // Ensure that the current OS version is recent enough
    if(strcmp(UTIL_GetVersion(), NEEDEDVERSION) < 0)
        {
        return MsgVersion();
        }

    // TODO: Write your application initialization function here.
  
// RCC SYSTEM CLOCK CONFIG ----------------------------------------------------/
  { 
    
      ErrorStatus HSEStartUpStatus;
      /* RCC system reset(for debug purpose) */
      RCC_DeInit();

      /* Enable HSE */
      RCC_HSEConfig(RCC_HSE_ON);

      /* Wait till HSE is ready */
      HSEStartUpStatus = RCC_WaitForHSEStartUp();

      if(HSEStartUpStatus == SUCCESS)
         {
         /* HCLK = SYSCLK */
         RCC_HCLKConfig(RCC_SYSCLK_Div1); 

         /* PCLK2 = HCLK */
         RCC_PCLK2Config(RCC_HCLK_Div2); 

         /* PCLK1 = HCLK/2 */
         RCC_PCLK1Config(RCC_HCLK_Div2);

         /* Flash 2 wait state */
         FLASH_SetLatency(FLASH_Latency_2);
         /* Enable Prefetch Buffer */
         FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

         /* PLLCLK = 8MHz * 9 = 72 MHz */
         RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

         /* Enable PLL */ 
         RCC_PLLCmd(ENABLE);

         /* Wait till PLL is ready */
         while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
            {
            }

         /* Select PLL as system clock source */
         RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

         /* Wait till PLL is used as system clock source */
         while(RCC_GetSYSCLKSource() != 0x08)
            {
            }
         }
  
     /* Enable GPIOs clock */
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
      /* Enable I2C1 clock */
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);
     
  }
   
// GPIO CONFIGURATION --------------------------------------------------------/

  // Configure all GPIOB in open drain AF mode (for different I2C levels)
  // and Initialise
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;  
    GPIO_Init(GPIOB, &GPIO_InitStructure);

// I2C CONFIGURATION ---------------------------------------------------------/
  
  // Enable I2C1 peripheral
    I2C_Cmd(I2C1, ENABLE);  
  // Configure I2C
    I2C_InitTypeDef I2C_InitStructure;  
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;  //only effects fast mode
    I2C_InitStructure.I2C_OwnAddress1 = 0xA0;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 100000; 
  // Initialise the I2C1 peripheral after enabling it 
    I2C_Init(I2C1, &I2C_InitStructure);

  // I2C1 can now be used through a set of specific I2C functions
      
      const char msg[] = "Init ok";  
    DRAW_DisplayString( 2, 90, msg, sizeof(msg)); // X, Y, string, length

    return MENU_CONTINUE_COMMAND;
    }

/*******************************************************************************
* Function Name  : Application_Handler
* Description    : Management of the Circle_App.
*
* Input          : None
* Return         : MENU_CONTINUE
*******************************************************************************/
enum MENU_code Application_Handler ( void )
    {
    
    // TODO: Write your application handling here.
    
    const char msg[] = "Display here";
    DRAW_DisplayString( 10, 70, msg, sizeof(msg)); // X, Y, string, length
    

  // Circle OS I2C Application Test - To read from a Read Only register specified 
  // in the FPGA.
    
  
  // Using specific I2C functions, execute a combined message protocol
  // to read from the Read Only Version register in the FPGA.
  
  // Master generates START condition to start communication
  I2C_GenerateSTART(I2C1, ENABLE);

   // Test on EV5 and clear it 
   
   while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
       
   // APPLICATION GETS STUCK HERE - CANNOT EXIT APPLICATION

 
    const char help2[] = "exitEV5while"; 
    DRAW_DisplayString( 15, 15, help2, sizeof(help2)); 

   // Send FPGA address for write
   I2C_Send7bitAddress(I2C1, 0x20, I2C_Direction_Transmitter);

   // Test on EV6 and clear it
   while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
 
   const char help3[] = "afterEV6while"; 
    DRAW_DisplayString( 15, 25, help3, sizeof(help3)); 
   
   // Clear EV6 by setting again the PE bit
   I2C_Cmd(I2C1, ENABLE);

   // Send the FPGA's internal address to write to (24,hex 0x18)
   I2C_SendData(I2C1, 0x18);

   // Test on EV8 and clear it
   while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

   // Send START condition a second time
   I2C_GenerateSTART(I2C1, ENABLE);

   // Test on EV5 and clear it
   while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

   // Send FPGA address for read
   I2C_Send7bitAddress(I2C1, 0x20, I2C_Direction_Receiver);

   // Test on EV6 and clear it
   while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
       
   // For single data transfer - disable ACK before reading the data
   I2C_AcknowledgeConfig(I2C1, DISABLE);
   
   // Test on EV7 and clear it
   while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
  
  // Read the data just received from the FPGA on I2C1
  u8 ReceivedData;
  ReceivedData = I2C_ReceiveData(I2C1);
  
  // Send STOP condition on I2C1
  I2C_GenerateSTOP(I2C1, ENABLE);
  
  // Enable Acknowledgement to be ready for another reception
  I2C_AcknowledgeConfig(I2C1, ENABLE);
  
  // Using CircleOS Display the received data on the STM32 Primer 2

  DRAW_DisplayString( 10, 60, ReceivedData, sizeof(ReceivedData)); // X, Y, string, length

      
#if 1      
   if ( BUTTON_GetState() == BUTTON_PUSHED )
      {
      BUTTON_WaitForRelease();
      return MENU_Quit();
      }
#endif   


  //       This routine will get called repeatedly by CircleOS, until we
  //       return MENU_LEAVE 

    return MENU_CONTINUE;   // Returning MENU_LEAVE will quit to CircleOS
    }

I have tried everything I can think of but, as a beginner to I2C and application writing, perhaps there is something i am doing wrong!

Offline

 

# 9   2009-06-24 14:58:54 STM32 Primer 2 Extension connector - I2C problems

Francis
Administrator
From: France-Grenoble
Registered: 2007-07-09
Posts: 890

Re: STM32 Primer 2 Extension connector - I2C problems

I remember we encountered some problems with I2C in CircleOS when accessing the audio device. The solution we found consisted in disabling the timer2 interrupt during the I2C access. At the end, we moved the code into the timer2 interrupt handler (MEMS_Handler) to avoid any interrupt, and it works. Not very satisfying... We thought that the issue was caused by the audio device, but the problem could be more general.

Offline

 

# 10   2009-12-23 14:33:16 STM32 Primer 2 Extension connector - I2C problems

godmode
New member
Registered: 2009-12-23
Posts: 3

Re: STM32 Primer 2 Extension connector - I2C problems

I had got the same issue - no signals on SDA and SCL.
To solve the problem you need to put:
I2C_DeInit(I2C1);
before starting to configure your I2C, I would suggest to put it after I2C_InitTypeDef I2C_InitStructure; and before rest of configuration.
You should have your signals now!

Offline

 

Board footer