github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_stm32_i2c_reva.go (about)

     1  //go:build stm32f4 || stm32f1
     2  
     3  package machine
     4  
     5  // I2C implementation for 'older' STM32 MCUs, including the F1 and F4 series
     6  // of MCUs.
     7  
     8  import (
     9  	"device/stm32"
    10  	"unsafe"
    11  )
    12  
    13  const (
    14  	flagOVR     = 0x00010800
    15  	flagAF      = 0x00010400
    16  	flagARLO    = 0x00010200
    17  	flagBERR    = 0x00010100
    18  	flagTXE     = 0x00010080
    19  	flagRXNE    = 0x00010040
    20  	flagSTOPF   = 0x00010010
    21  	flagADD10   = 0x00010008
    22  	flagBTF     = 0x00010004
    23  	flagADDR    = 0x00010002
    24  	flagSB      = 0x00010001
    25  	flagDUALF   = 0x00100080
    26  	flagGENCALL = 0x00100010
    27  	flagTRA     = 0x00100004
    28  	flagBUSY    = 0x00100002
    29  	flagMSL     = 0x00100001
    30  )
    31  
    32  func (i2c *I2C) hasFlag(flag uint32) bool {
    33  	const mask = 0x0000FFFF
    34  	if uint8(flag>>16) == 1 {
    35  		return i2c.Bus.SR1.HasBits(flag & mask)
    36  	} else {
    37  		return i2c.Bus.SR2.HasBits(flag & mask)
    38  	}
    39  }
    40  
    41  func (i2c *I2C) clearFlag(flag uint32) {
    42  	const mask = 0x0000FFFF
    43  	i2c.Bus.SR1.Set(^(flag & mask))
    44  }
    45  
    46  // clearFlagADDR reads both status registers to clear any pending ADDR flags.
    47  func (i2c *I2C) clearFlagADDR() {
    48  	i2c.Bus.SR1.Get()
    49  	i2c.Bus.SR2.Get()
    50  }
    51  
    52  func (i2c *I2C) waitForFlag(flag uint32, set bool) bool {
    53  	const tryMax = 10000
    54  	hasFlag := false
    55  	for i := 0; !hasFlag && i < tryMax; i++ {
    56  		hasFlag = i2c.hasFlag(flag) == set
    57  	}
    58  	return hasFlag
    59  }
    60  
    61  func (i2c *I2C) waitForFlagOrError(flag uint32, set bool) bool {
    62  	const tryMax = 10000
    63  	hasFlag := false
    64  	for i := 0; !hasFlag && i < tryMax; i++ {
    65  		if hasFlag = i2c.hasFlag(flag) == set; !hasFlag {
    66  			// check for ACK failure
    67  			if i2c.hasFlag(flagAF) {
    68  				// generate stop condition
    69  				i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
    70  				// clear pending flags
    71  				i2c.clearFlag(flagAF)
    72  				return false
    73  			} else if i2c.hasFlag(flagSTOPF) {
    74  				// clear stop flag
    75  				i2c.clearFlag(flagSTOPF)
    76  				return false
    77  			}
    78  		}
    79  	}
    80  	return hasFlag
    81  }
    82  
    83  type transferOption uint32
    84  
    85  const (
    86  	frameFirst        = 0x00000001
    87  	frameFirstAndNext = 0x00000002
    88  	frameNext         = 0x00000004
    89  	frameFirstAndLast = 0x00000008
    90  	frameLastNoStop   = 0x00000010
    91  	frameLast         = 0x00000020
    92  	frameNoOption     = 0xFFFF0000
    93  )
    94  
    95  // I2C fast mode (Fm) duty cycle
    96  const (
    97  	DutyCycle2    = 0
    98  	DutyCycle16x9 = 1
    99  )
   100  
   101  // I2CConfig is used to store config info for I2C.
   102  type I2CConfig struct {
   103  	Frequency uint32
   104  	SCL       Pin
   105  	SDA       Pin
   106  	DutyCycle uint8
   107  }
   108  
   109  // Configure is intended to setup the STM32 I2C interface.
   110  func (i2c *I2C) Configure(config I2CConfig) error {
   111  
   112  	// The following is the required sequence in controller mode.
   113  	// 1. Program the peripheral input clock in I2C_CR2 Register in order to
   114  	//    generate correct timings
   115  	// 2. Configure the clock control registers
   116  	// 3. Configure the rise time register
   117  	// 4. Program the I2C_CR1 register to enable the peripheral
   118  	// 5. Set the START bit in the I2C_CR1 register to generate a Start condition
   119  
   120  	// disable I2C interface before any configuration changes
   121  	i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_PE)
   122  
   123  	// reset I2C bus
   124  	i2c.Bus.CR1.SetBits(stm32.I2C_CR1_SWRST)
   125  	i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_SWRST)
   126  
   127  	// enable clock for I2C
   128  	enableAltFuncClock(unsafe.Pointer(i2c.Bus))
   129  
   130  	// init pins
   131  	if config.SCL == 0 && config.SDA == 0 {
   132  		config.SCL = I2C0_SCL_PIN
   133  		config.SDA = I2C0_SDA_PIN
   134  	}
   135  	i2c.configurePins(config)
   136  
   137  	// default to 100 kHz (Sm, standard mode) if no frequency is set
   138  	if config.Frequency == 0 {
   139  		config.Frequency = 100 * KHz
   140  	}
   141  
   142  	// configure I2C input clock
   143  	i2c.Bus.CR2.SetBits(i2c.getFreqRange(config))
   144  
   145  	// configure rise time
   146  	i2c.Bus.TRISE.Set(i2c.getRiseTime(config))
   147  
   148  	// configure clock control
   149  	i2c.Bus.CCR.Set(i2c.getSpeed(config))
   150  
   151  	// disable GeneralCall and NoStretch modes
   152  	i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ENGC | stm32.I2C_CR1_NOSTRETCH)
   153  
   154  	// enable I2C interface
   155  	i2c.Bus.CR1.SetBits(stm32.I2C_CR1_PE)
   156  
   157  	return nil
   158  }
   159  
   160  // SetBaudRate sets the communication speed for I2C.
   161  func (i2c *I2C) SetBaudRate(br uint32) error {
   162  	// TODO: implement
   163  	return errI2CNotImplemented
   164  }
   165  
   166  func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
   167  
   168  	if err := i2c.controllerTransmit(addr, w); nil != err {
   169  		return err
   170  	}
   171  
   172  	if len(r) > 0 {
   173  		if err := i2c.controllerReceive(addr, r); nil != err {
   174  			return err
   175  		}
   176  	}
   177  
   178  	return nil
   179  }
   180  
   181  func (i2c *I2C) controllerTransmit(addr uint16, w []byte) error {
   182  
   183  	if !i2c.waitForFlag(flagBUSY, false) {
   184  		return errI2CBusReadyTimeout
   185  	}
   186  
   187  	// disable POS
   188  	i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS)
   189  
   190  	pos := 0
   191  	rem := len(w)
   192  
   193  	// send peripheral address
   194  	if err := i2c.controllerRequestWrite(addr, frameNoOption); nil != err {
   195  		return err
   196  	}
   197  
   198  	// clear ADDR flag
   199  	i2c.clearFlagADDR()
   200  
   201  	for rem > 0 {
   202  		// wait for TXE flag set
   203  		if !i2c.waitForFlagOrError(flagTXE, true) {
   204  			return errI2CAckExpected
   205  		}
   206  
   207  		// write data to DR
   208  		i2c.Bus.DR.Set(uint32(w[pos]))
   209  		// update counters
   210  		pos++
   211  		rem--
   212  
   213  		if i2c.hasFlag(flagBTF) && rem != 0 {
   214  			// write data to DR
   215  			i2c.Bus.DR.Set(uint32(w[pos]))
   216  			// update counters
   217  			pos++
   218  			rem--
   219  		}
   220  
   221  		// wait for transfer finished flag BTF set
   222  		if !i2c.waitForFlagOrError(flagBTF, true) {
   223  			return errI2CWriteTimeout
   224  		}
   225  	}
   226  
   227  	// generate stop condition
   228  	i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
   229  
   230  	return nil
   231  }
   232  
   233  func (i2c *I2C) controllerRequestWrite(addr uint16, option transferOption) error {
   234  
   235  	if frameFirstAndLast == option || frameFirst == option || frameNoOption == option {
   236  		// generate start condition
   237  		i2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)
   238  	} else if false /* (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) */ {
   239  		// generate restart condition
   240  		i2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)
   241  	}
   242  
   243  	// ensure start bit is set
   244  	if !i2c.waitForFlag(flagSB, true) {
   245  		return errI2CSignalStartTimeout
   246  	}
   247  
   248  	// send peripheral address
   249  	i2c.Bus.DR.Set(uint32(addr) << 1)
   250  
   251  	// wait for address ACK from peripheral
   252  	if !i2c.waitForFlagOrError(flagADDR, true) {
   253  		return errI2CSignalStartTimeout
   254  	}
   255  
   256  	return nil
   257  }
   258  
   259  func (i2c *I2C) controllerReceive(addr uint16, r []byte) error {
   260  
   261  	if !i2c.waitForFlag(flagBUSY, false) {
   262  		return errI2CBusReadyTimeout
   263  	}
   264  
   265  	// disable POS
   266  	i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS)
   267  
   268  	pos := 0
   269  	rem := len(r)
   270  
   271  	// send peripheral address
   272  	if err := i2c.controllerRequestRead(addr, frameNoOption); nil != err {
   273  		return err
   274  	}
   275  
   276  	switch rem {
   277  	case 0:
   278  		// clear ADDR flag
   279  		i2c.clearFlagADDR()
   280  		// generate stop condition
   281  		i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
   282  
   283  	case 1:
   284  		// disable ACK
   285  		i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
   286  		// clear ADDR flag
   287  		i2c.clearFlagADDR()
   288  		// generate stop condition
   289  		i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
   290  
   291  	case 2:
   292  		// disable ACK
   293  		i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
   294  		// enable POS
   295  		i2c.Bus.CR1.SetBits(stm32.I2C_CR1_POS)
   296  		// clear ADDR flag
   297  		i2c.clearFlagADDR()
   298  
   299  	default:
   300  		// enable ACK
   301  		i2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)
   302  		// clear ADDR flag
   303  		i2c.clearFlagADDR()
   304  	}
   305  
   306  	for rem > 0 {
   307  		switch rem {
   308  		case 1:
   309  			// wait until RXNE flag is set
   310  			if !i2c.waitForFlagOrError(flagRXNE, true) {
   311  				return errI2CReadTimeout
   312  			}
   313  
   314  			// read data from DR
   315  			r[pos] = byte(i2c.Bus.DR.Get())
   316  
   317  			// update counters
   318  			pos++
   319  			rem--
   320  
   321  		case 2:
   322  			// wait until transfer finished flag BTF is set
   323  			if !i2c.waitForFlag(flagBTF, true) {
   324  				return errI2CReadTimeout
   325  			}
   326  
   327  			// generate stop condition
   328  			i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
   329  
   330  			// read data from DR
   331  			r[pos] = byte(i2c.Bus.DR.Get())
   332  
   333  			// update counters
   334  			pos++
   335  			rem--
   336  
   337  			// read data from DR
   338  			r[pos] = byte(i2c.Bus.DR.Get())
   339  
   340  			// update counters
   341  			pos++
   342  			rem--
   343  
   344  		case 3:
   345  			// wait until transfer finished flag BTF is set
   346  			if !i2c.waitForFlag(flagBTF, true) {
   347  				return errI2CReadTimeout
   348  			}
   349  
   350  			// disable ACK
   351  			i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
   352  
   353  			// read data from DR
   354  			r[pos] = byte(i2c.Bus.DR.Get())
   355  
   356  			// update counters
   357  			pos++
   358  			rem--
   359  
   360  			// wait until transfer finished flag BTF is set
   361  			if !i2c.waitForFlag(flagBTF, true) {
   362  				return errI2CReadTimeout
   363  			}
   364  
   365  			// generate stop condition
   366  			i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
   367  
   368  			// read data from DR
   369  			r[pos] = byte(i2c.Bus.DR.Get())
   370  
   371  			// update counters
   372  			pos++
   373  			rem--
   374  
   375  			// read data from DR
   376  			r[pos] = byte(i2c.Bus.DR.Get())
   377  
   378  			// update counters
   379  			pos++
   380  			rem--
   381  
   382  		default:
   383  			// wait until RXNE flag is set
   384  			if !i2c.waitForFlagOrError(flagRXNE, true) {
   385  				return errI2CReadTimeout
   386  			}
   387  
   388  			// read data from DR
   389  			r[pos] = byte(i2c.Bus.DR.Get())
   390  
   391  			// update counters
   392  			pos++
   393  			rem--
   394  
   395  			if i2c.hasFlag(flagBTF) {
   396  				// read data from DR
   397  				r[pos] = byte(i2c.Bus.DR.Get())
   398  
   399  				// update counters
   400  				pos++
   401  				rem--
   402  			}
   403  		}
   404  	}
   405  
   406  	return nil
   407  }
   408  
   409  func (i2c *I2C) controllerRequestRead(addr uint16, option transferOption) error {
   410  
   411  	// enable ACK
   412  	i2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)
   413  
   414  	if frameFirstAndLast == option || frameFirst == option || frameNoOption == option {
   415  		// generate start condition
   416  		i2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)
   417  	} else if false /* (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) */ {
   418  		// generate restart condition
   419  		i2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)
   420  	}
   421  
   422  	// ensure start bit is set
   423  	if !i2c.waitForFlag(flagSB, true) {
   424  		return errI2CSignalStartTimeout
   425  	}
   426  
   427  	// send peripheral address
   428  	i2c.Bus.DR.Set(uint32(addr)<<1 | 1)
   429  
   430  	// wait for address ACK from peripheral
   431  	if !i2c.waitForFlagOrError(flagADDR, true) {
   432  		return errI2CSignalStartTimeout
   433  	}
   434  
   435  	return nil
   436  }