[SOLVED] I2C2 on STM32F103C8T6 and HWire

Generic boards that are not Maple or Maple mini clones, and don't contain the additional USB reset hardware
Winnie_The_Pooh
Posts: 5
Joined: Mon Oct 24, 2016 10:31 am

Re: I2C2 on STM32F103C8T6 and HWire

Post by Winnie_The_Pooh » Tue Jun 20, 2017 12:09 pm

When I was debugging some lib code - I take this code to my prog and debug this part as usual code.

luca_stm32
Posts: 17
Joined: Wed Apr 26, 2017 12:39 pm

Re: I2C2 on STM32F103C8T6 and HWire

Post by luca_stm32 » Tue Jun 20, 2017 12:56 pm

@Roger
I used the same hardware: Blue Pill and EEProm connected on I2C2 (pins PB10 and PB11).
In Arduino IDE, if I choose Tools->Board->Generic STM32F103C Series, the scketch doesn't work (it stucks as soon as it tryes to send data on I2C2. In particular, it doesn't pass H2Wire.endTransmission() that is the function that make the transmission start).

In Arduino IDE, if I choose Tools->Board->Maple Mini the scketch works as expected.

Important: in both cases I used the same hardware!
Now I'm trying to print STM32 registers to see differences. I noticed that using "Generic STM32F103C Series", the SR2 register of I2C2 is 2 (busy) as soon I configure the pheripheral.
If I use "Maple Mini", the SR2 register is 0.

Here is the code I'm using:

Code: Select all

//#include <Wire.h>
#include <HardWire.h>
 
#define EEPROM_ADDRESS 0x50    //Address of 24LC256 eeprom chip
//Declare the instance that the users of the library can use
//TwoWire Wire(SCL, SDA, SOFT_STANDARD);  
//TwoWire Wire2(PB10, PB11, SOFT_STANDARD);

HardWire H2Wire(2, I2C_FAST_MODE); // I2C2
//HardWire H1Wire(1, I2C_FAST_MODE); // I2C2

void setup(void)
{
  Serial.begin(115200);
  delay(10000);
  Serial.println("EEPROM Test");
  //Wire2.begin();
  
  H2Wire.begin();

  Serial.println("I2C2:");
  Serial.print("CR1: ");
  Serial.println(I2C2->regs->CR1, HEX);
  Serial.print("CR2: ");
  Serial.println(I2C2->regs->CR2, HEX);
  Serial.print("OAR1: ");
  Serial.println(I2C2->regs->OAR1, HEX);
  Serial.print("OAR2: ");
  Serial.println(I2C2->regs->OAR2, HEX);
  Serial.print("DR: ");
  Serial.println(I2C2->regs->DR, HEX);
  Serial.print("SR1: ");
  Serial.println(I2C2->regs->SR1, HEX);
  Serial.print("SR2: ");
  Serial.println(I2C2->regs->SR2, HEX);
  Serial.print("CCR: ");
  Serial.println(I2C2->regs->CCR, HEX);
  Serial.print("TRISE: ");
  Serial.println(I2C2->regs->TRISE, HEX);  

  Serial.print("PORTB CRL: ");
  Serial.println(GPIOB->regs->CRL, HEX);  
  Serial.print("PORTB CRH: ");
  Serial.println(GPIOB->regs->CRH, HEX); 
  Serial.print("PORTB ODR: ");
  Serial.println(GPIOB->regs->ODR, HEX);
  Serial.print("PORTB BSRR: ");
  Serial.println(GPIOB->regs->BSRR, HEX); 
  Serial.print("PORTB BRR: ");
  Serial.println(GPIOB->regs->BRR, HEX); 

  int address = 0;
 
  writeEEPROM(EEPROM_ADDRESS, address, 0x55);
  while(1){
  Serial.print(readEEPROM(EEPROM_ADDRESS, address), HEX);
  Serial.print(" ");
  address++;
  delay(1000);    
  }
}
 
void loop(){}
 
void writeEEPROM(int deviceaddress, int16_t eeaddress, uint8_t data ) 
{
//  Wire2.beginTransmission(deviceaddress);
//  Wire2.write((int)(eeaddress >> 8));   // MSB
//  Wire2.write((int)(eeaddress & 0xFF)); // LSB
//  Wire2.write(data);
//  Wire2.endTransmission();
  
  H2Wire.beginTransmission(deviceaddress);
  H2Wire.write((int)(eeaddress >> 8));   // MSB
  H2Wire.write((int)(eeaddress & 0xFF)); // LSB
  H2Wire.write(data);
  H2Wire.endTransmission();
 
  delay(5);
}
 
uint8_t readEEPROM(int deviceaddress, uint16_t eeaddress ) 
{
  uint8_t rdata = 0xFF;
 
//  Wire2.beginTransmission(deviceaddress);
//  Wire2.write((int)(eeaddress >> 8));   // MSB
//  Wire2.write((int)(eeaddress & 0xFF)); // LSB
//  Wire2.endTransmission();
//  Wire2.requestFrom(deviceaddress,1);

  H2Wire.beginTransmission(deviceaddress);
  H2Wire.write((int)(eeaddress >> 8));   // MSB
  H2Wire.write((int)(eeaddress & 0xFF)); // LSB
  H2Wire.endTransmission();
  H2Wire.requestFrom(deviceaddress,1);
 
//  if (Wire2.available()) rdata = Wire2.read();
  if (H2Wire.available()) rdata = H2Wire.read();

  return rdata;
}
Luca.

stevestrong
Posts: 1502
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: I2C2 on STM32F103C8T6 and HWire

Post by stevestrong » Tue Jun 20, 2017 2:10 pm

How and where do you define the I2C pins to be used for HardWire instance?
This could make the difference between boards.
I suggest to use always the PXY notation (PA2, PB10) instead of raw numbers (like 2, 33, etc) to make it more generally usable.

luca_stm32
Posts: 17
Joined: Wed Apr 26, 2017 12:39 pm

Re: I2C2 on STM32F103C8T6 and HWire

Post by luca_stm32 » Tue Jun 20, 2017 2:29 pm

Hi Stevestrong.
I use the function:

Code: Select all

HardWire H2Wire(2, I2C_FAST_MODE); // I2C2
The definition of the pins are in STM32F1\cores\maple\libmaple directory in file i2c_f1.c line 40

static i2c_dev i2c2 = I2C_DEV_OLD(2, &gpiob, 11, 10);

In the same file, pins are configured.

A note: in files i2c.c (on the same directory) I found the initialization of i2c (function i2c_master_enable):

Code: Select all

void i2c_master_enable(i2c_dev *dev, uint32 flags) {
    /* PE must be disabled to configure the device */
    ASSERT(!(dev->regs->CR1 & I2C_CR1_PE));

    /* Ugh */
    _i2c_handle_remap(dev, flags);

    /* Reset the bus. Clock out any hung slaves. */
    if (flags & I2C_BUS_RESET) {
        i2c_bus_reset(dev);
    }

    /* Turn on clock and set GPIO modes */
    i2c_init(dev);
    i2c_config_gpios(dev);
I noticed that first is performed a i2c_bus_reset (if necessary) and then the i2c_config_gpios, but i2c_bus_reset function calls i2c_master_release_bus where gpio pins are configured. Could it be better first configure pins and then use them? (sorry for my bad english...).

Another thing always in i2c_f1.c file: in function i2c_config_gpios seems like only alternate function (AF) pins are managed, or I miss something?


Luca.

stevestrong
Posts: 1502
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: I2C2 on STM32F103C8T6 and HWire

Post by stevestrong » Tue Jun 20, 2017 3:14 pm

Yeah, it seems that i2c has a couple of overlapping function calls...
Alternative function mapping does not take place because the dev_flags does not contain the remap flag.
And I2C2 cannot be remapped, it is fixed to PB10/11.

And yes, it seems that the reset should come only before init and GPIO config. This looks like a bug!

So the correct sequence should be:

Code: Select all

     /* Turn on clock and set GPIO modes */
    i2c_init(dev);
    i2c_config_gpios(dev);

    /* Reset the bus. Clock out any hung slaves. */
    if (flags & I2C_BUS_RESET) {
        i2c_bus_reset(dev);
    }

User avatar
Pito
Posts: 1498
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: I2C2 on STM32F103C8T6 and HWire

Post by Pito » Tue Jun 20, 2017 4:56 pm

Try to compile for the MapleM and flash it to the BluePill. I bet it will work.
It could be the BP variant has got a bug in some defines (compare BP and MM variants).
Pukao Hats Cleaning Services Ltd.

zmemw16
Posts: 1369
Joined: Wed Jul 08, 2015 2:09 pm
Location: St Annes, Lancs,UK

Re: I2C2 on STM32F103C8T6 and HWire

Post by zmemw16 » Tue Jun 20, 2017 5:53 pm

thought i'd posted this already
constructor has a defaulted parameter for the mode

Code: Select all

HardWire HWire(2, I2C_FAST_MODE); // I2C2
HardWire HWire(2); // I2C2 slow mode
srp

stevestrong
Posts: 1502
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: I2C2 on STM32F103C8T6 and HWire

Post by stevestrong » Tue Jun 20, 2017 7:07 pm

zmemw16 wrote:
Tue Jun 20, 2017 5:53 pm
thought i'd posted this already
constructor has a defaulted parameter for the mode

Code: Select all

HardWire HWire(2, I2C_FAST_MODE); // I2C2
HardWire HWire(2); // I2C2 slow mode
srp
This is already taken into account by Luca, see couple of post above.

In the first instance, I would build the project for BP and MM ad then compare the MAP files.
Second, I would generate ASM files and compare the content for BP and MM.

luca_stm32
Posts: 17
Joined: Wed Apr 26, 2017 12:39 pm

Re: I2C2 on STM32F103C8T6 and HWire

Post by luca_stm32 » Tue Jun 20, 2017 7:54 pm

@Pito
This is exactly what I did. I compiled the sketch for MM and worked.

@Stevestrong
Yes, compare the MAP files generated for MM and BP is what I would like to do.
I would like also to correct the initialization of I2C.

Luca.

User avatar
RogerClark
Posts: 6675
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: I2C2 on STM32F103C8T6 and HWire

Post by RogerClark » Tue Jun 20, 2017 10:40 pm

If you uploaded using USB Serial to both boards the code should be this same, as the only difference between them should be the USB enumeration control

Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 1 guest