Thoughts on the STM32G0 I2C Peripheral Mode

Using RM0444 - dm00371828, for the STM32G0x1 platform

  • Supports Standard Mode, Fast Mode, and Fast Mode Plus
  • Has DMA support
  • Can do multimaster
  • Can do 7/10 bit addressing
  • Multiple 7-bit addresses, "2 addresses, 1 with configurable mask"
  • Supports optional clock stretching
7 bit addrXX
10 bit addrXX
Independent clockX
Wakeup from stopX

32.4.4 talks about clocking requirements.

Probably relevant when doing clock configuration.

32.4.6 talks about initialization

  • You must config + enable I2C peripheral clock

  • You enable the I2C by setting PE bit in I2C_CR1 register

  • When you disable with PE bit, a "software reset" occurs (see 32.4.7)

  • Analog filter is enabled by default, disabled with ANFOFF bit, or use a digital filter with DNF3..0 in the I2C_CR1 register

  • Table 164 talks about tradeoffs between analog/digital

    • Analog is available in stop mode w/ addr wakeup, digital isn't
    • Analog is variable with temp, voltage, etc.
    • Digital is programmable
  • Don't change filter while I2C enabled

  • Table 165 (and preceding text) talks a LOOOOT about timing calculation. This is probably important, but overwhelming

  • Don't change the timing while I2C enabled

Figure 287 is a flow chart of initialization steps. Basically:

  • Turn off I2C_CR1::PE
  • Configure I2C_CR1::ANFOFF and I2C_CR1::DNF
  • Configure I2C_CR1::NOSTRETCH
  • Turn on I2C_CR1::PE

32.4.7 Talks about software reset

  • It has a list of affected bytes
  • You need to keep it low for at least 3 APB cycles to do the software reset. They recommend:
    • Write PE 0
    • Read PE
    • Write PE 1

32.4.8 Talks about data transfer

There is a one byte buffer for each direction, shifted in/out.


  • Data is shifted in
  • On full byte:
    • If RXNE=0, then byte is put in I2C_RXDR
    • If RXNE=1, then clock is stretched until RXNE=0


  • Data is shifted out
  • On empty byte:
    • If TXE=0, then byte is copied from I2C_TXDR
    • If TXE=1, then clock is stretched until TXE=0

HW Transfer Management

  • I2C has a byte counter, enabled by default in master, disabled in slave
  • Controlled through I2C_CR2::SBC bit
  • Number of bytes for counter is I2C_CR2::NBYTES byte.
  • Also has a RELOAD bit for generating TCR flag when you need to load more than 255 bytes
  • You must clear RELOAD on last chunk

When not using RELOAD as a master, you can use AUTOEND to send a stop automatically when transfered. Or you can disable to possibly get a flag/interrupt when you need to START (restart) or STOP w/ software control

Table 166 shows master/slave configurations of SBC, RELOAD, and AUTOEND.

32.4.9 talks about slave mode

  • You must set at least one address
    • Configured with I2C_OAR1 and I2C_OAR2
    • OA1 is 7 bit by default, set in OA1MODE in I2C_OAR1
    • Enabled by OA1EN in I2C_OAR1 register
    • OA2 has masks for matching multiple wildcard'y addresses
    • Mask logic is odd, I don't get it yet.
    • OA2 is always 7 bit
    • OA2 is enabled by setting OA2EN in O2C_OAR2
  • You can enable General Call address by setting GCEN in I2C_CR1
  • You can get a flag or interrupt on address match
  • Usually the slave uses clock stretching. can be disabled
  • If using wildcard addrs, I2C_ISR::ADDCODE can be checked. Also check DIR for direction
  • Must clear ADDR flag to release stretch
  • If you don't stretch, you'll get all kinds of over/underrun error flags set

Figure 290 has a slave initialization flow chart. Preceeding text has some info about what can be updated when.

Figures 291-296 show the data transfer flow when stretching is enabled or not, and when sending or receiving

32.4.10 talks about master mode

Not relevant for now

32.4.11 shows timing calc examples

Probably just look at this when writing the clocking code

32.4.12-32.4.15 talk about SMBus

Not relevant for now

32.4.16 talks about wake from stop

Not relevant for now

32.4.17 talks about error conditions

Main errors:

  • Bus Error (BERR)
  • Arbitration Lost (ARLO)
  • Overrun/Underrun Error (OVR)
  • Packet Error Checking Error (PECERR)
    • SMBus
  • Timeout Error (TIMEOUT)
    • SMBus
  • Alert (ALERT)
    • SMBus

32.4.18 talks about DMA

  • Enable with TXDMAEN/RXDMAEN in the I2C_CR1 register
  • Slave mode: You have to set up the DMA before clearing the ADDR register (TX and RX)

32.4.19 talks about Debug mode

Probably don't care for now

32.5 talks about I2C low power modes

probably don't care for now

32.6 talks about interrupts

Super handy table of mnemonics, what sets flags, what interrupts are paired with flags, how to enable, how to clear, etc.

32.7 is a listing of all the registers



I have a fork of the g0xx hal, which implements a reasonable amount of i2c master capabilities

I probably want to offer:

  • blocking i2c slave (maybe? just for prototyping?)
  • interrupt i2c slave
  • dma i2c slave

I might want to de-macro the driver a bit

Initialization steps

  • initial settings
  • Clear {OA1EN, OA2EN} in I2C_OAR1 and I2C_OAR2
  • Configure:
    • OA1[9:0]
    • OA1MODE
    • OA1EN
    • OA2[6:0]
    • OA2MSK[2:0]
    • OA2EN
    • GCEN
  • Configure SBC in I2C_CR1
  • Enable interrupts and/or DMA in I2C_CR1
    • lol later
  • End