Page 1 of 1

STM32L433 and I2C

Posted: Thu Oct 04, 2018 6:18 pm
by dflogeras
Hi,

I'm playing with the STM32L433-Nucleo64 board. As I mentioned in a previous thread, I'm using the STM32L443xx in my board.h since 433 isn't in the registry but shares almost everything with the 443 with the exception of missing the AES peripheral which I'm not touching.

I'm using ChibiOS_18

All has been going well, I've been playing with an SPI lcd screen, and using the (LP)UARTS and new PAL/EXTI drivers.

I enabled I2C1, set it up to clock from HSI16 and used the timing values from the RM based on a 16Mhz clock.

Code: Select all

#define STM32_I2C1SEL                       STM32_I2C1SEL_HSI16
...
#define STM32_I2C_USE_I2C1                  TRUE
#define STM32_I2C_USE_I2C2                  FALSE
#define STM32_I2C_USE_I2C3                  FALSE
#define STM32_I2C_BUSY_TIMEOUT              50
#define STM32_I2C_I2C1_RX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 7)
#define STM32_I2C_I2C1_TX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 6)
#define STM32_I2C_I2C1_IRQ_PRIORITY         5
#define STM32_I2C_I2C1_DMA_PRIORITY         3


then attempt read 128 bytes from an EEPROM by running the following:

Code: Select all

static std::array< uint8_t, 128 > data;
static std::array< uint8_t, 2 > cmd;
...
int main( void ) {
  palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_PUPDR_PULLUP |
                           PAL_STM32_OSPEED_HIGH);
  palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_PUPDR_PULLUP |
                           PAL_STM32_OSPEED_HIGH);

  i2cStart(&I2CD1, &i2cconfig);

  cmd[0] = 0;
  cmd[1] = 0;
 
  auto msg = i2cMasterTransmitTimeout( &I2CD1, 0xa0, &cmd[0], sizeof(cmd),
                                       &data[0], sizeof(data),
                                       TIME_MS2I( 50 ));
  while( 1 ) { chThdSleepMilliseconds(500); }
}


When it reaches the point in os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c where it writes CR2 (line 195 in function i2c_lld_setup_tx_transfer()) the wheels completely come off and openOCD loses contact with the target.

I'm not sure what I might be doing wrong, I tried the obvious, I enabled the DBG checks that are usually the first line of defense but didn't see anything. There doesn't seem to be a DMA conflict, and moreover, I've disabled all my other code and I2C1 should be the only peripheral started right now.

Any hints are appreciated.
Dave

Re: STM32L433 and I2C

Posted: Thu Oct 04, 2018 6:20 pm
by dflogeras
Forgot this, like I said I pulled it right out of the RM (although curiously CUBE gets a different answer)

Code: Select all

static const I2CConfig i2cconfig = {
  STM32_TIMINGR_PRESC(0U) |
  STM32_TIMINGR_SCLDEL(1U) | STM32_TIMINGR_SDADEL(0U) |
  STM32_TIMINGR_SCLH(6U)  | STM32_TIMINGR_SCLL(10U),
  0,
  0
};

Re: STM32L433 and I2C

Posted: Thu Oct 04, 2018 7:43 pm
by dflogeras
Found my issue, I failed to start the HSI16 clock in mcuconf.h

Would it be possible to add a compile time check for this?

Re: STM32L433 and I2C

Posted: Fri Oct 05, 2018 7:43 am
by Giovanni
It would be possible, it is better if you post requests on the appropriate forum (change request or bug reports) or it will be likely lost in the noise.

Giovanni

Re: STM32L433 and I2C

Posted: Fri Oct 05, 2018 11:31 am
by dflogeras
Thanks Giovanni, will do

In case anyone else finds this thread in the future and sees the above config, it was also necessary to add OPENDRAIN as follows

Code: Select all

  palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_PUPDR_PULLUP |
                           PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_OSPEED_HIGH);
  palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_PUPDR_PULLUP |
                           PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_OSPEED_HIGH);                           


finally, in this project I am _only_ using HSI16 to drive the I2C. No system clocks are derived from it, I only am using MSI. I will probably write to the EEPROM at a VERY low duty cycle. I was wondering if it is advisable to turn off/on the HSI16 oscillator between uses to save some power?

Code: Select all


    RCC->CR |= RCC_CR_HSION;
    while ((RCC->CR & RCC_CR_HSIRDY) == 0) { }
     
    i2cStart( &I2Cd1, &myconfig );
    //do the transfers
    i2cStop( &I2CD1 );
    RCC->CR &= ~RCC_CR_HSION;