Page 1 of 2

STM32F072C8 I2C hal

Posted: Thu May 14, 2015 7:19 pm
by halba
Hello ChibiOS team,

I am starting to work with your OS v3.0.0p3 on the STM32F072C8 in IAR. So far, everything works well (OS, CAN and SPI are running properly), but now I am trying to get working I2C and I have some problems.

1. When I start the I2C before SPI, SPI do not work:

Code: Select all

  //SPI works
  canStart(&CAND1, &cancfg);
  i2cStart(&I2CD1, &i2cfg1);
  spiStart(&SPID1, &spi1cfg);

  //SPI do not works
  canStart(&CAND1, &cancfg);
  spiStart(&SPID1, &spi1cfg);
  i2cStart(&I2CD1, &i2cfg1);
(I2C behaves in both cases same wrong)

2. I am trying to send 2 bytes to EEPROM (I2C EEPROM address is 0xA0 and two bytes are 0x00, 0xAA). The transfer works well with ST hal (first picture - tek00005), but it sends only one byte with the ChibiOS hal I2C (second picture - tek00006) and the byte (probably I2C address) seems to be also wrong. The HW is for both cases same.
ST hal
ST hal
tek00005.png (18.18 KiB) Viewed 4541 times

ChibiOS hal
ChibiOS hal
tek00006.png (14.29 KiB) Viewed 4541 times

The code for sending the data in ChigiOS is like this:

Code: Select all

uint8_t i2cTxBuffer[2] = {0x00, 0xAA};
uint8_t i2cRxBuffer[8];
uint8_t status = 0;

...

static const I2CConfig i2cfg1 = {
    STM32_TIMINGR_PRESC(0x02) | STM32_TIMINGR_SCLH(0x09) | STM32_TIMINGR_SCLL(0x0E),
    I2C_CR1_PE,
    I2C_CR2_AUTOEND
};

...

  canStart(&CAND1, &cancfg);
  i2cStart(&I2CD1, &i2cfg1);
  spiStart(&SPID1, &spi1cfg);

...

  if(Button[1].flags & BTN_SHORT)
  {
    i2cAcquireBus(&I2CD1);
    status = i2cMasterTransmitTimeout(&I2CD1, 0xA0, i2cTxBuffer, 2, i2cRxBuffer, 8, MS2ST(100));
    i2cReleaseBus(&I2CD1);
    Button[1].flags &= ~(BTN_SHORT);
  }


3. The TIMINGR wasn't set, I must switched the order of the registers initialization in the function i2c_lld_start in os\hal\ports\STM32\LLD\I2Cv2\i2c_lld.c, the TIMINGR before CR1 and CR2:

Code: Select all

  /* Setup I2C parameters.*/
  dp->TIMINGR = i2cp->config->timingr;
 
  /* Reset i2c peripheral, the TCIE bit will be handled separately.*/
  dp->CR1 = i2cp->config->cr1 | I2C_CR1_ERRIE | I2C_CR1_STOPIE |
            I2C_CR1_NACKIE | I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN;

  /* Set slave address field (master mode) */
  dp->CR2 = (i2cp->config->cr2 & ~I2C_CR2_SADD);
Now the register is set properly.

Sorry for bothering you, I am pretty new to your OS so maybe I am just doing something trivial wrongly, but it would be very helpful for me if you can give me some hint at least for the problem number 2 because it is really blocking right now.

Thanks,
halba

Re: STM32F072C8 I2C hal

Posted: Thu May 14, 2015 7:59 pm
by Giovanni
Hi,

It is because I2C and SPI use the same DMA channels so there is a conflict... it is a limitation of the device.

The workaround is to start/stop the colliding drivers and never use them at the same time. The DMA channels are taken by the xxxStart() functions ad freed by the xxxStop() functions.

Giovanni

Re: STM32F072C8 I2C hal

Posted: Sat May 16, 2015 8:47 am
by halba
Hi Giovanni,

Thank you for the hint, it was really helpful. In fact, this device can run I2C1 also on the DMA channels 6 and 7. Anyway, it was little bit tricky to get it working because the DMA hal for the STM32F0 do not support channels 6 and 7 in default so it was necessarily to extend it and also one bit in SYSCFG->CFGR1 register must be set to remap the I2C1 to different DMA channels. Now both peripherals works independently.

halba

Re: STM32F072C8 I2C hal

Posted: Sat May 16, 2015 10:15 am
by Giovanni
Hi,

Yes, I forgot, on some devices manual remapping is required because the peripherals default to non-existent DMA channels.

Giovanni

Re: STM32F072C8 I2C hal

Posted: Sun May 17, 2015 11:41 am
by Giovanni
Hi,

I just added a no-DMA mode for the I2Cv2 driver, you could give it a try.

Giovanni

Re: STM32F072C8 I2C hal

Posted: Thu May 21, 2015 2:00 pm
by halba
Thanks, but I am satisfied with solution with remapping. Maybe later when I will need this DMA channel for another purpose.

Re: STM32F072C8 I2C hal

Posted: Fri May 29, 2015 8:07 am
by DGW
Good afternoon.
I have a conflict, DMA for I2C1 and USART1. Add a line in the file STM32F0xx / hal_lld.s (function hal_lld_init (void))
SYSCFG-> CFGR1 | = SYSCFG_CFGR1_I2C1_DMA_RMP;
and changed the file STM32F0xx/stm32_registry.h
#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) //3)
#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) //2)
It does not work, what else have to change? Thank you.

Re: STM32F072C8 I2C hal

Posted: Fri May 29, 2015 8:20 am
by Giovanni
Hi,

It should be sufficient.

Are those channels already used? (SPI2)
You set the remap bit, is it really set? try doing it from the main after halInit().

Giovanni

Re: STM32F072C8 I2C hal

Posted: Fri May 29, 2015 8:33 am
by DGW
I look in the debugger, the bit is set (in SYSCFG-> CFGR1). The project uses USART1 and I2C1, SPI do not use. Hangs on a line (file ARMCMx/ RVCT/vectors.c)
b _unhandled_exception

Re: STM32F072C8 I2C hal

Posted: Fri May 29, 2015 8:55 am
by Giovanni
I understood the problem.

The DMA driver only supports the first 5 DMA channels, channels 6 and 7 were not present in initial F0 devices. The driver requires an update.

You could copy the missing code in stm32_dma.c from the STM32L1 file (ISRs and missing lines in the DMA streams array).

Giovanni