Page 1 of 1

i2c problem win stm32F412

Posted: Wed Aug 26, 2020 6:27 pm
by enrico.dallavia
Hello,
I'm stuck with a problem with i2c, it seems the chibios 20.3.1 is not producing any signal from i2c1 (pin PB7 and PB8). They are configured as: alternate(4), high speed, opendrain.
But every attempt give me -2 as status and i2cGetErrors is 4

Code: Select all

static const I2CConfig i2ccfg = {
OPMODE_I2C,
400000,
FAST_DUTY_CYCLE_2,
};

static THD_FUNCTION(reader_thread, arg) {
 
  chRegSetThreadName("reader");
 
  (void)arg;

  uint8_t txbuf[2];
  uint8_t rxbuf[2];

  txbuf[0] = 0x00;
  txbuf[1] = 0x00;

  chThdSleepMilliseconds(1000);

  chprintf(chout, "entrato lettura\r\n");
 
  chThdSleepMilliseconds(1000);

  sysinterval_t tmo = TIME_MS2I(100);

  i2caddr_t addr = 0xA1;
   
  i2cStart(&I2CD1,&i2ccfg);

  chprintf(chout, "partito driver i2c: %d\r\n",I2CD1.state);

  chThdSleepMilliseconds(1000);
 
  while(true) {

    chprintf(chout, "invio richiesta\r\n");
    chThdSleepMilliseconds(100);

    i2cAcquireBus(&I2CD1);
   
    msg_t status = i2cMasterTransmit(&I2CD1, addr, txbuf, 1, rxbuf, 0);

    i2cReleaseBus(&I2CD1);
   
    chprintf(chout, "risultato: %d [%d]\r\n", status, i2cGetErrors(&I2CD1));

    chThdSleepMilliseconds(1000);
  }
}


What it bother me is that if I use the CubeMxIDE with STM primitives, I've got both the signals on the pin and the correct answer from the eeprom I'm trying to access

Code: Select all

uint8_t data[10];

  char buff[64];
  /* Infinite loop */
  for(;;)
  {
     HAL_UART_Transmit(&huart6, "i2cTest\r\n", strlen("i2cTest\r\n"),10);
     data[0] = 0xFA;

     if (HAL_I2C_Master_Transmit(&hi2c1, 0xA0, data, 1, HAL_MAX_DELAY) == HAL_OK) {
        for(int i = 0; i < 6; i+=1) {
           if( HAL_I2C_Master_Receive(&hi2c1, 0xA1, &data[i], 1, HAL_MAX_DELAY) == HAL_OK) {
           } else {
              HAL_UART_Transmit(&huart6, "receive fails\r\n", strlen("receive fails\r\n"),10);
           }
        }

        sprintf(buff,"%x %x %x %x %x %x\n\r", data[0], data[1], data[2], data[3], data[4], data[5]);

        HAL_UART_Transmit(&huart6, buff, strlen(buff),10);
     } else {
        HAL_UART_Transmit(&huart6, "transmit fails\r\n", strlen("transmit fails\r\n"),10);
     }


     osDelay(1000);
  }


The other periphericals enabled in chconf is the USART6 and USB_OTG (and they works fine). The clock is configured exactly as CubeMx.
I have used few years ago chibios 3 for reading from i2c with an STM32F429 and the settings for the pin / initialization of the driver / writing are almost the same. Could it be another settings I'm not aware of for this board? I've already searched inside the forum for some idea (I've disabled most of the other peripherical to avoid dma conflict, check for correct pin assignment, ecc)
I would rather not to switch to CubeMxIde because I find Chibios more easy to work with.
Any help / suggestion would be very appreciate.

ps: if the pin is wrongly configured, is there any means to check them at runtime (like a variable where I can check the bitmask for the correctness)?

Thanks

Enrico

Re: i2c problem win stm32F412

Posted: Wed Aug 26, 2020 6:34 pm
by Giovanni
You may inspect the GPIO registers and verify settings, also make sure you have NOT assigned the same peripheral function to multiple pins. Also verify the address, "A1" is not valid, you need to pass only the 7 address bits aligned to right without the RW bit.

Giovanni

Re: i2c problem win stm32F412

Posted: Thu Aug 27, 2020 9:09 am
by enrico.dallavia
Good morning.
Thank you Giovanni for the useful tips, indeed the problem was the address!
After looking in the primitive STM32/LLD/I2Cv1/hal_i2c_lld.c I found out that the i2c address is composed by shifting left by 1 the original address I gave to the API function.

Code: Select all

msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
                                      const uint8_t *txbuf, size_t txbytes,
                                      uint8_t *rxbuf, size_t rxbytes,
                                      sysinterval_t timeout) {
  I2C_TypeDef *dp = i2cp->i2c;
  systime_t start, end;
  msg_t msg;

#if defined(STM32F1XX_I2C)
  osalDbgCheck((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL)));
#endif

  /* Resetting error flags for this transfer.*/
  i2cp->errors = I2C_NO_ERROR;

  /* Initializes driver fields, LSB = 0 -> transmit.*/
 i2cp->addr = (addr << 1);
 
  .............


On the other side, the STM primitive from CubeMx, take the address as it as, and only perform a binary AND to set the R/W bit

Code: Select all

if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT)
  {
    /* Send slave address */
    hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress);
  }


where I2C_7BIT_ADD_WRITE is a #define as follows

Code: Select all

#define I2C_OAR1_ADD0  0x01
#define I2C_7BIT_ADD_WRITE(__ADDRESS__)                    ((uint8_t)((__ADDRESS__) & (uint8_t)(~I2C_OAR1_ADD0)))
#define I2C_7BIT_ADD_READ(__ADDRESS__)                     ((uint8_t)((__ADDRESS__) | I2C_OAR1_ADD0))


So I can't take the same address I wrote in CubeMx on ChibiOS.
Changing my address to 0x50 do the trick! And now I'm happily reading the data from the eeprom with ChibiOS!

THANKS for the help

Enrico