657 строки
		
	
	
	
		
			15 КиБ
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			657 строки
		
	
	
	
		
			15 КиБ
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build stm32,stm32f103xx
 | 
						|
 | 
						|
package machine
 | 
						|
 | 
						|
// Peripheral abstraction layer for the stm32.
 | 
						|
 | 
						|
import (
 | 
						|
	"device/stm32"
 | 
						|
	"runtime/interrupt"
 | 
						|
	"unsafe"
 | 
						|
)
 | 
						|
 | 
						|
func CPUFrequency() uint32 {
 | 
						|
	return 72000000
 | 
						|
}
 | 
						|
 | 
						|
const (
 | 
						|
	PinInput       PinMode = 0 // Input mode
 | 
						|
	PinOutput10MHz PinMode = 1 // Output mode, max speed 10MHz
 | 
						|
	PinOutput2MHz  PinMode = 2 // Output mode, max speed 2MHz
 | 
						|
	PinOutput50MHz PinMode = 3 // Output mode, max speed 50MHz
 | 
						|
	PinOutput      PinMode = PinOutput2MHz
 | 
						|
 | 
						|
	PinInputModeAnalog     PinMode = 0  // Input analog mode
 | 
						|
	PinInputModeFloating   PinMode = 4  // Input floating mode
 | 
						|
	PinInputModePullUpDown PinMode = 8  // Input pull up/down mode
 | 
						|
	PinInputModeReserved   PinMode = 12 // Input mode (reserved)
 | 
						|
 | 
						|
	PinOutputModeGPPushPull   PinMode = 0  // Output mode general purpose push/pull
 | 
						|
	PinOutputModeGPOpenDrain  PinMode = 4  // Output mode general purpose open drain
 | 
						|
	PinOutputModeAltPushPull  PinMode = 8  // Output mode alt. purpose push/pull
 | 
						|
	PinOutputModeAltOpenDrain PinMode = 12 // Output mode alt. purpose open drain
 | 
						|
)
 | 
						|
 | 
						|
// Configure this pin with the given I/O settings.
 | 
						|
// stm32f1xx uses different technique for setting the GPIO pins than the stm32f407
 | 
						|
func (p Pin) Configure(config PinConfig) {
 | 
						|
	// Configure the GPIO pin.
 | 
						|
	p.enableClock()
 | 
						|
	port := p.getPort()
 | 
						|
	pin := uint8(p) % 16
 | 
						|
	pos := (pin % 8) * 4
 | 
						|
	if pin < 8 {
 | 
						|
		port.CRL.ReplaceBits(uint32(config.Mode), 0xf, pos)
 | 
						|
	} else {
 | 
						|
		port.CRH.ReplaceBits(uint32(config.Mode), 0xf, pos)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (p Pin) getPort() *stm32.GPIO_Type {
 | 
						|
	switch p / 16 {
 | 
						|
	case 0:
 | 
						|
		return stm32.GPIOA
 | 
						|
	case 1:
 | 
						|
		return stm32.GPIOB
 | 
						|
	case 2:
 | 
						|
		return stm32.GPIOC
 | 
						|
	case 3:
 | 
						|
		return stm32.GPIOD
 | 
						|
	case 4:
 | 
						|
		return stm32.GPIOE
 | 
						|
	case 5:
 | 
						|
		return stm32.GPIOF
 | 
						|
	case 6:
 | 
						|
		return stm32.GPIOG
 | 
						|
	default:
 | 
						|
		panic("machine: unknown port")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// enableClock enables the clock for this desired GPIO port.
 | 
						|
func (p Pin) enableClock() {
 | 
						|
	switch p / 16 {
 | 
						|
	case 0:
 | 
						|
		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPAEN)
 | 
						|
	case 1:
 | 
						|
		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPBEN)
 | 
						|
	case 2:
 | 
						|
		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPCEN)
 | 
						|
	case 3:
 | 
						|
		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPDEN)
 | 
						|
	case 4:
 | 
						|
		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPEEN)
 | 
						|
	case 5:
 | 
						|
		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPFEN)
 | 
						|
	case 6:
 | 
						|
		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPGEN)
 | 
						|
	default:
 | 
						|
		panic("machine: unknown port")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Enable peripheral clock. Expand to include all the desired peripherals
 | 
						|
func enableAltFuncClock(bus unsafe.Pointer) {
 | 
						|
	if bus == unsafe.Pointer(stm32.USART1) {
 | 
						|
		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)
 | 
						|
	} else if bus == unsafe.Pointer(stm32.USART2) {
 | 
						|
		stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)
 | 
						|
	} else if bus == unsafe.Pointer(stm32.I2C1) {
 | 
						|
		stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN)
 | 
						|
	} else if bus == unsafe.Pointer(stm32.SPI1) {
 | 
						|
		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
//---------- UART related types and code
 | 
						|
 | 
						|
// UART representation
 | 
						|
type UART struct {
 | 
						|
	Buffer    *RingBuffer
 | 
						|
	Bus       *stm32.USART_Type
 | 
						|
	Interrupt interrupt.Interrupt
 | 
						|
}
 | 
						|
 | 
						|
// Configure the TX and RX pins
 | 
						|
func (uart UART) configurePins(config UARTConfig) {
 | 
						|
 | 
						|
	// pins
 | 
						|
	switch config.TX {
 | 
						|
	case UART_ALT_TX_PIN:
 | 
						|
		// use alternate TX/RX pins via AFIO mapping
 | 
						|
		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_AFIOEN)
 | 
						|
		if uart.Bus == stm32.USART1 {
 | 
						|
			stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_USART1_REMAP)
 | 
						|
		} else if uart.Bus == stm32.USART2 {
 | 
						|
			stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_USART2_REMAP)
 | 
						|
		}
 | 
						|
	default:
 | 
						|
		// use standard TX/RX pins PA9 and PA10
 | 
						|
	}
 | 
						|
	config.TX.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
 | 
						|
	config.RX.Configure(PinConfig{Mode: PinInputModeFloating})
 | 
						|
}
 | 
						|
 | 
						|
// Determine the divisor for USARTs to get the given baudrate
 | 
						|
func (uart UART) getBaudRateDivisor(br uint32) uint32 {
 | 
						|
 | 
						|
	// Note: PCLK2 (from APB2) used for USART1 and PCLK1 for USART2, 3, 4, 5
 | 
						|
	var divider uint32
 | 
						|
	if uart.Bus == stm32.USART1 {
 | 
						|
		// first divide by PCLK2 prescaler (div 1) and then desired baudrate
 | 
						|
		divider = CPUFrequency() / br
 | 
						|
	} else {
 | 
						|
		// first divide by PCLK1 prescaler (div 2) and then desired baudrate
 | 
						|
		divider = CPUFrequency() / 2 / br
 | 
						|
	}
 | 
						|
	return divider
 | 
						|
}
 | 
						|
 | 
						|
//---------- SPI related types and code
 | 
						|
 | 
						|
type SPI struct {
 | 
						|
	Bus *stm32.SPI_Type
 | 
						|
}
 | 
						|
 | 
						|
// There are 3 SPI interfaces on the STM32F103xx.
 | 
						|
// Since the first interface is named SPI1, both SPI0 and SPI1 refer to SPI1.
 | 
						|
// TODO: implement SPI2 and SPI3.
 | 
						|
var (
 | 
						|
	SPI1 = SPI{Bus: stm32.SPI1}
 | 
						|
	SPI0 = SPI1
 | 
						|
)
 | 
						|
 | 
						|
// Set baud rate for SPI
 | 
						|
func (spi SPI) getBaudRate(config SPIConfig) uint32 {
 | 
						|
	var conf uint32
 | 
						|
 | 
						|
	// set frequency dependent on PCLK2 prescaler (div 1)
 | 
						|
	switch config.Frequency {
 | 
						|
	case 125000:
 | 
						|
		// Note: impossible to achieve lower frequency with current PCLK2!
 | 
						|
		conf |= stm32.SPI_BaudRatePrescaler_256
 | 
						|
	case 250000:
 | 
						|
		conf |= stm32.SPI_BaudRatePrescaler_256
 | 
						|
	case 500000:
 | 
						|
		conf |= stm32.SPI_BaudRatePrescaler_128
 | 
						|
	case 1000000:
 | 
						|
		conf |= stm32.SPI_BaudRatePrescaler_64
 | 
						|
	case 2000000:
 | 
						|
		conf |= stm32.SPI_BaudRatePrescaler_32
 | 
						|
	case 4000000:
 | 
						|
		conf |= stm32.SPI_BaudRatePrescaler_16
 | 
						|
	case 8000000:
 | 
						|
		conf |= stm32.SPI_BaudRatePrescaler_8
 | 
						|
	default:
 | 
						|
		conf |= stm32.SPI_BaudRatePrescaler_256
 | 
						|
	}
 | 
						|
	return conf
 | 
						|
}
 | 
						|
 | 
						|
// Configure SPI pins for input output and clock
 | 
						|
func (spi SPI) configurePins(config SPIConfig) {
 | 
						|
	config.SCK.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
 | 
						|
	config.SDO.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})
 | 
						|
	config.SDI.Configure(PinConfig{Mode: PinInputModeFloating})
 | 
						|
}
 | 
						|
 | 
						|
//---------- I2C related types and code
 | 
						|
 | 
						|
type I2C struct {
 | 
						|
	Bus *stm32.I2C_Type
 | 
						|
}
 | 
						|
 | 
						|
// There are 2 I2C interfaces on the STM32F103xx.
 | 
						|
// Since the first interface is named I2C1, both I2C0 and I2C1 refer to I2C1.
 | 
						|
// TODO: implement I2C2.
 | 
						|
var (
 | 
						|
	I2C1 = I2C{Bus: stm32.I2C1}
 | 
						|
	I2C0 = I2C1
 | 
						|
)
 | 
						|
 | 
						|
// I2CConfig is used to store config info for I2C.
 | 
						|
type I2CConfig struct {
 | 
						|
	Frequency uint32
 | 
						|
	SCL       Pin
 | 
						|
	SDA       Pin
 | 
						|
}
 | 
						|
 | 
						|
// Configure is intended to setup the I2C interface.
 | 
						|
func (i2c I2C) Configure(config I2CConfig) {
 | 
						|
	// Default I2C bus speed is 100 kHz.
 | 
						|
	if config.Frequency == 0 {
 | 
						|
		config.Frequency = TWI_FREQ_100KHZ
 | 
						|
	}
 | 
						|
 | 
						|
	// enable clock for I2C
 | 
						|
	stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN)
 | 
						|
 | 
						|
	// I2C1 pins
 | 
						|
	switch config.SDA {
 | 
						|
	case PB9:
 | 
						|
		config.SCL = PB8
 | 
						|
		// use alternate I2C1 pins PB8/PB9 via AFIO mapping
 | 
						|
		stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_AFIOEN)
 | 
						|
		stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_I2C1_REMAP)
 | 
						|
	default:
 | 
						|
		// use default I2C1 pins PB6/PB7
 | 
						|
		config.SDA = SDA_PIN
 | 
						|
		config.SCL = SCL_PIN
 | 
						|
	}
 | 
						|
 | 
						|
	config.SDA.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltOpenDrain})
 | 
						|
	config.SCL.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltOpenDrain})
 | 
						|
 | 
						|
	// Disable the selected I2C peripheral to configure
 | 
						|
	i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_PE)
 | 
						|
 | 
						|
	// pclk1 clock speed is main frequency divided by PCLK1 prescaler (div 2)
 | 
						|
	pclk1 := CPUFrequency() / 2
 | 
						|
 | 
						|
	// set freqency range to PCLK1 clock speed in MHz
 | 
						|
	// aka setting the value 36 means to use 36 MHz clock
 | 
						|
	pclk1Mhz := pclk1 / 1000000
 | 
						|
	i2c.Bus.CR2.SetBits(pclk1Mhz)
 | 
						|
 | 
						|
	switch config.Frequency {
 | 
						|
	case TWI_FREQ_100KHZ:
 | 
						|
		// Normal mode speed calculation
 | 
						|
		ccr := pclk1 / (config.Frequency * 2)
 | 
						|
		i2c.Bus.CCR.Set(ccr)
 | 
						|
 | 
						|
		// duty cycle 2
 | 
						|
		i2c.Bus.CCR.ClearBits(stm32.I2C_CCR_DUTY)
 | 
						|
 | 
						|
		// frequency standard mode
 | 
						|
		i2c.Bus.CCR.ClearBits(stm32.I2C_CCR_F_S)
 | 
						|
 | 
						|
		// Set Maximum Rise Time for standard mode
 | 
						|
		i2c.Bus.TRISE.Set(pclk1Mhz)
 | 
						|
 | 
						|
	case TWI_FREQ_400KHZ:
 | 
						|
		// Fast mode speed calculation
 | 
						|
		ccr := pclk1 / (config.Frequency * 3)
 | 
						|
		i2c.Bus.CCR.Set(ccr)
 | 
						|
 | 
						|
		// duty cycle 2
 | 
						|
		i2c.Bus.CCR.ClearBits(stm32.I2C_CCR_DUTY)
 | 
						|
 | 
						|
		// frequency fast mode
 | 
						|
		i2c.Bus.CCR.SetBits(stm32.I2C_CCR_F_S)
 | 
						|
 | 
						|
		// Set Maximum Rise Time for fast mode
 | 
						|
		i2c.Bus.TRISE.Set(((pclk1Mhz * 300) / 1000))
 | 
						|
	}
 | 
						|
 | 
						|
	// re-enable the selected I2C peripheral
 | 
						|
	i2c.Bus.CR1.SetBits(stm32.I2C_CR1_PE)
 | 
						|
}
 | 
						|
 | 
						|
// Tx does a single I2C transaction at the specified address.
 | 
						|
// It clocks out the given address, writes the bytes in w, reads back len(r)
 | 
						|
// bytes and stores them in r, and generates a stop condition on the bus.
 | 
						|
func (i2c I2C) Tx(addr uint16, w, r []byte) error {
 | 
						|
	var err error
 | 
						|
	if len(w) != 0 {
 | 
						|
		// start transmission for writing
 | 
						|
		err = i2c.signalStart()
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		// send address
 | 
						|
		err = i2c.sendAddress(uint8(addr), true)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		for _, b := range w {
 | 
						|
			err = i2c.WriteByte(b)
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		// sending stop here for write
 | 
						|
		err = i2c.signalStop()
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if len(r) != 0 {
 | 
						|
		// re-start transmission for reading
 | 
						|
		err = i2c.signalStart()
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		// 1 byte
 | 
						|
		switch len(r) {
 | 
						|
		case 1:
 | 
						|
			// send address
 | 
						|
			err = i2c.sendAddress(uint8(addr), false)
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			// Disable ACK of received data
 | 
						|
			i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
 | 
						|
 | 
						|
			// clear timeout here
 | 
						|
			timeout := i2cTimeout
 | 
						|
			for !i2c.Bus.SR2.HasBits(stm32.I2C_SR2_MSL | stm32.I2C_SR2_BUSY) {
 | 
						|
				timeout--
 | 
						|
				if timeout == 0 {
 | 
						|
					return errI2CWriteTimeout
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			// Generate stop condition
 | 
						|
			i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
 | 
						|
 | 
						|
			timeout = i2cTimeout
 | 
						|
			for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_RxNE) {
 | 
						|
				timeout--
 | 
						|
				if timeout == 0 {
 | 
						|
					return errI2CReadTimeout
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			// Read and return data byte from I2C data register
 | 
						|
			r[0] = byte(i2c.Bus.DR.Get())
 | 
						|
 | 
						|
			// wait for stop
 | 
						|
			return i2c.waitForStop()
 | 
						|
 | 
						|
		case 2:
 | 
						|
			// enable pos
 | 
						|
			i2c.Bus.CR1.SetBits(stm32.I2C_CR1_POS)
 | 
						|
 | 
						|
			// Enable ACK of received data
 | 
						|
			i2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)
 | 
						|
 | 
						|
			// send address
 | 
						|
			err = i2c.sendAddress(uint8(addr), false)
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			// clear address here
 | 
						|
			timeout := i2cTimeout
 | 
						|
			for !i2c.Bus.SR2.HasBits(stm32.I2C_SR2_MSL | stm32.I2C_SR2_BUSY) {
 | 
						|
				timeout--
 | 
						|
				if timeout == 0 {
 | 
						|
					return errI2CWriteTimeout
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			// Disable ACK of received data
 | 
						|
			i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
 | 
						|
 | 
						|
			// wait for btf. we need a longer timeout here than normal.
 | 
						|
			timeout = 1000
 | 
						|
			for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_BTF) {
 | 
						|
				timeout--
 | 
						|
				if timeout == 0 {
 | 
						|
					return errI2CReadTimeout
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			// Generate stop condition
 | 
						|
			i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
 | 
						|
 | 
						|
			// read the 2 bytes by reading twice.
 | 
						|
			r[0] = byte(i2c.Bus.DR.Get())
 | 
						|
			r[1] = byte(i2c.Bus.DR.Get())
 | 
						|
 | 
						|
			// wait for stop
 | 
						|
			err = i2c.waitForStop()
 | 
						|
 | 
						|
			//disable pos
 | 
						|
			i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS)
 | 
						|
 | 
						|
			return err
 | 
						|
 | 
						|
		case 3:
 | 
						|
			// Enable ACK of received data
 | 
						|
			i2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)
 | 
						|
 | 
						|
			// send address
 | 
						|
			err = i2c.sendAddress(uint8(addr), false)
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			// clear address here
 | 
						|
			timeout := i2cTimeout
 | 
						|
			for !i2c.Bus.SR2.HasBits(stm32.I2C_SR2_MSL | stm32.I2C_SR2_BUSY) {
 | 
						|
				timeout--
 | 
						|
				if timeout == 0 {
 | 
						|
					return errI2CWriteTimeout
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			// Enable ACK of received data
 | 
						|
			i2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)
 | 
						|
 | 
						|
			// wait for btf. we need a longer timeout here than normal.
 | 
						|
			timeout = 1000
 | 
						|
			for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_BTF) {
 | 
						|
				timeout--
 | 
						|
				if timeout == 0 {
 | 
						|
					return errI2CReadTimeout
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			// Disable ACK of received data
 | 
						|
			i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
 | 
						|
 | 
						|
			// read the first byte
 | 
						|
			r[0] = byte(i2c.Bus.DR.Get())
 | 
						|
 | 
						|
			timeout = 1000
 | 
						|
			for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_BTF) {
 | 
						|
				timeout--
 | 
						|
				if timeout == 0 {
 | 
						|
					return errI2CReadTimeout
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			// Generate stop condition
 | 
						|
			i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
 | 
						|
 | 
						|
			// read the last 2 bytes by reading twice.
 | 
						|
			r[1] = byte(i2c.Bus.DR.Get())
 | 
						|
			r[2] = byte(i2c.Bus.DR.Get())
 | 
						|
 | 
						|
			// wait for stop
 | 
						|
			return i2c.waitForStop()
 | 
						|
 | 
						|
		default:
 | 
						|
			// more than 3 bytes of data to read
 | 
						|
 | 
						|
			// send address
 | 
						|
			err = i2c.sendAddress(uint8(addr), false)
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			// clear address here
 | 
						|
			timeout := i2cTimeout
 | 
						|
			for !i2c.Bus.SR2.HasBits(stm32.I2C_SR2_MSL | stm32.I2C_SR2_BUSY) {
 | 
						|
				timeout--
 | 
						|
				if timeout == 0 {
 | 
						|
					return errI2CWriteTimeout
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			for i := 0; i < len(r)-3; i++ {
 | 
						|
				// Enable ACK of received data
 | 
						|
				i2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)
 | 
						|
 | 
						|
				// wait for btf. we need a longer timeout here than normal.
 | 
						|
				timeout = 1000
 | 
						|
				for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_BTF) {
 | 
						|
					timeout--
 | 
						|
					if timeout == 0 {
 | 
						|
						return errI2CReadTimeout
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
				// read the next byte
 | 
						|
				r[i] = byte(i2c.Bus.DR.Get())
 | 
						|
			}
 | 
						|
 | 
						|
			// wait for btf. we need a longer timeout here than normal.
 | 
						|
			timeout = 1000
 | 
						|
			for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_BTF) {
 | 
						|
				timeout--
 | 
						|
				if timeout == 0 {
 | 
						|
					return errI2CReadTimeout
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			// Disable ACK of received data
 | 
						|
			i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
 | 
						|
 | 
						|
			// get third from last byte
 | 
						|
			r[len(r)-3] = byte(i2c.Bus.DR.Get())
 | 
						|
 | 
						|
			// Generate stop condition
 | 
						|
			i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
 | 
						|
 | 
						|
			// get second from last byte
 | 
						|
			r[len(r)-2] = byte(i2c.Bus.DR.Get())
 | 
						|
 | 
						|
			timeout = i2cTimeout
 | 
						|
			for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_RxNE) {
 | 
						|
				timeout--
 | 
						|
				if timeout == 0 {
 | 
						|
					return errI2CReadTimeout
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			// get last byte
 | 
						|
			r[len(r)-1] = byte(i2c.Bus.DR.Get())
 | 
						|
 | 
						|
			// wait for stop
 | 
						|
			return i2c.waitForStop()
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
const i2cTimeout = 500
 | 
						|
 | 
						|
// signalStart sends a start signal.
 | 
						|
func (i2c I2C) signalStart() error {
 | 
						|
	// Wait until I2C is not busy
 | 
						|
	timeout := i2cTimeout
 | 
						|
	for i2c.Bus.SR2.HasBits(stm32.I2C_SR2_BUSY) {
 | 
						|
		timeout--
 | 
						|
		if timeout == 0 {
 | 
						|
			return errI2CSignalStartTimeout
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// clear stop
 | 
						|
	i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_STOP)
 | 
						|
 | 
						|
	// Generate start condition
 | 
						|
	i2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)
 | 
						|
 | 
						|
	// Wait for I2C EV5 aka SB flag.
 | 
						|
	timeout = i2cTimeout
 | 
						|
	for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_SB) {
 | 
						|
		timeout--
 | 
						|
		if timeout == 0 {
 | 
						|
			return errI2CSignalStartTimeout
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// signalStop sends a stop signal and waits for it to succeed.
 | 
						|
func (i2c I2C) signalStop() error {
 | 
						|
	// Generate stop condition
 | 
						|
	i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
 | 
						|
 | 
						|
	// wait for stop
 | 
						|
	return i2c.waitForStop()
 | 
						|
}
 | 
						|
 | 
						|
// waitForStop waits after a stop signal.
 | 
						|
func (i2c I2C) waitForStop() error {
 | 
						|
	// Wait until I2C is stopped
 | 
						|
	timeout := i2cTimeout
 | 
						|
	for i2c.Bus.SR1.HasBits(stm32.I2C_SR1_STOPF) {
 | 
						|
		timeout--
 | 
						|
		if timeout == 0 {
 | 
						|
			return errI2CSignalStopTimeout
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// Send address of device we want to talk to
 | 
						|
func (i2c I2C) sendAddress(address uint8, write bool) error {
 | 
						|
	data := (address << 1)
 | 
						|
	if !write {
 | 
						|
		data |= 1 // set read flag
 | 
						|
	}
 | 
						|
 | 
						|
	i2c.Bus.DR.Set(uint32(data))
 | 
						|
 | 
						|
	// Wait for I2C EV6 event.
 | 
						|
	// Destination device acknowledges address
 | 
						|
	timeout := i2cTimeout
 | 
						|
	if write {
 | 
						|
		// EV6 which is ADDR flag.
 | 
						|
		for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_ADDR) {
 | 
						|
			timeout--
 | 
						|
			if timeout == 0 {
 | 
						|
				return errI2CWriteTimeout
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		timeout = i2cTimeout
 | 
						|
		for !i2c.Bus.SR2.HasBits(stm32.I2C_SR2_MSL | stm32.I2C_SR2_BUSY | stm32.I2C_SR2_TRA) {
 | 
						|
			timeout--
 | 
						|
			if timeout == 0 {
 | 
						|
				return errI2CWriteTimeout
 | 
						|
			}
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		// I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED which is ADDR flag.
 | 
						|
		for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_ADDR) {
 | 
						|
			timeout--
 | 
						|
			if timeout == 0 {
 | 
						|
				return errI2CWriteTimeout
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// WriteByte writes a single byte to the I2C bus.
 | 
						|
func (i2c I2C) WriteByte(data byte) error {
 | 
						|
	// Send data byte
 | 
						|
	i2c.Bus.DR.Set(uint32(data))
 | 
						|
 | 
						|
	// Wait for I2C EV8_2 when data has been physically shifted out and
 | 
						|
	// output on the bus.
 | 
						|
	// I2C_EVENT_MASTER_BYTE_TRANSMITTED is TXE flag.
 | 
						|
	timeout := i2cTimeout
 | 
						|
	for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_TxE) {
 | 
						|
		timeout--
 | 
						|
		if timeout == 0 {
 | 
						|
			return errI2CWriteTimeout
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 |