nrf: add I2C timeout
This commit adds I2C timeouts for nrf51 and nrf52 (but not yet for others like nrf52840). Tested on the PineTime, where I now got a timeout instead of hanging and resetting due to a watchdog reset.
Этот коммит содержится в:
		
							родитель
							
								
									a7b205c26c
								
							
						
					
					
						коммит
						14ddba8519
					
				
					 2 изменённых файлов: 25 добавлений и 2 удалений
				
			
		| 
						 | 
					@ -203,6 +203,8 @@ func (uart *UART) handleInterrupt(interrupt.Interrupt) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const i2cTimeout = 0xffff // this is around 29ms on a nrf52
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// I2CConfig is used to store config info for I2C.
 | 
					// I2CConfig is used to store config info for I2C.
 | 
				
			||||||
type I2CConfig struct {
 | 
					type I2CConfig struct {
 | 
				
			||||||
	Frequency uint32
 | 
						Frequency uint32
 | 
				
			||||||
| 
						 | 
					@ -261,11 +263,17 @@ func (i2c *I2C) Configure(config I2CConfig) error {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// signalStop sends a stop signal to the I2C peripheral and waits for confirmation.
 | 
					// signalStop sends a stop signal to the I2C peripheral and waits for confirmation.
 | 
				
			||||||
func (i2c *I2C) signalStop() {
 | 
					func (i2c *I2C) signalStop() error {
 | 
				
			||||||
 | 
						tries := 0
 | 
				
			||||||
	i2c.Bus.TASKS_STOP.Set(1)
 | 
						i2c.Bus.TASKS_STOP.Set(1)
 | 
				
			||||||
	for i2c.Bus.EVENTS_STOPPED.Get() == 0 {
 | 
						for i2c.Bus.EVENTS_STOPPED.Get() == 0 {
 | 
				
			||||||
 | 
							tries++
 | 
				
			||||||
 | 
							if tries >= i2cTimeout {
 | 
				
			||||||
 | 
								return errI2CSignalStopTimeout
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	i2c.Bus.EVENTS_STOPPED.Set(0)
 | 
						i2c.Bus.EVENTS_STOPPED.Set(0)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var rngStarted = false
 | 
					var rngStarted = false
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,12 +72,17 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(r) == 0 {
 | 
						if len(r) == 0 {
 | 
				
			||||||
		// Stop the I2C transaction after the write.
 | 
							// Stop the I2C transaction after the write.
 | 
				
			||||||
		i2c.signalStop()
 | 
							err = i2c.signalStop()
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// The last byte read has already stopped the transaction, via
 | 
							// The last byte read has already stopped the transaction, via
 | 
				
			||||||
		// TWI_SHORTS_BB_STOP. But we still need to wait until we receive the
 | 
							// TWI_SHORTS_BB_STOP. But we still need to wait until we receive the
 | 
				
			||||||
		// STOPPED event.
 | 
							// STOPPED event.
 | 
				
			||||||
 | 
							tries := 0
 | 
				
			||||||
		for i2c.Bus.EVENTS_STOPPED.Get() == 0 {
 | 
							for i2c.Bus.EVENTS_STOPPED.Get() == 0 {
 | 
				
			||||||
 | 
								tries++
 | 
				
			||||||
 | 
								if tries >= i2cTimeout {
 | 
				
			||||||
 | 
									return errI2CSignalStopTimeout
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		i2c.Bus.EVENTS_STOPPED.Set(0)
 | 
							i2c.Bus.EVENTS_STOPPED.Set(0)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -87,12 +92,17 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// writeByte writes a single byte to the I2C bus and waits for confirmation.
 | 
					// writeByte writes a single byte to the I2C bus and waits for confirmation.
 | 
				
			||||||
func (i2c *I2C) writeByte(data byte) error {
 | 
					func (i2c *I2C) writeByte(data byte) error {
 | 
				
			||||||
 | 
						tries := 0
 | 
				
			||||||
	i2c.Bus.TXD.Set(uint32(data))
 | 
						i2c.Bus.TXD.Set(uint32(data))
 | 
				
			||||||
	for i2c.Bus.EVENTS_TXDSENT.Get() == 0 {
 | 
						for i2c.Bus.EVENTS_TXDSENT.Get() == 0 {
 | 
				
			||||||
		if e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 {
 | 
							if e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 {
 | 
				
			||||||
			i2c.Bus.EVENTS_ERROR.Set(0)
 | 
								i2c.Bus.EVENTS_ERROR.Set(0)
 | 
				
			||||||
			return errI2CBusError
 | 
								return errI2CBusError
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							tries++
 | 
				
			||||||
 | 
							if tries >= i2cTimeout {
 | 
				
			||||||
 | 
								return errI2CWriteTimeout
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	i2c.Bus.EVENTS_TXDSENT.Set(0)
 | 
						i2c.Bus.EVENTS_TXDSENT.Set(0)
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
| 
						 | 
					@ -100,11 +110,16 @@ func (i2c *I2C) writeByte(data byte) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// readByte reads a single byte from the I2C bus when it is ready.
 | 
					// readByte reads a single byte from the I2C bus when it is ready.
 | 
				
			||||||
func (i2c *I2C) readByte() (byte, error) {
 | 
					func (i2c *I2C) readByte() (byte, error) {
 | 
				
			||||||
 | 
						tries := 0
 | 
				
			||||||
	for i2c.Bus.EVENTS_RXDREADY.Get() == 0 {
 | 
						for i2c.Bus.EVENTS_RXDREADY.Get() == 0 {
 | 
				
			||||||
		if e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 {
 | 
							if e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 {
 | 
				
			||||||
			i2c.Bus.EVENTS_ERROR.Set(0)
 | 
								i2c.Bus.EVENTS_ERROR.Set(0)
 | 
				
			||||||
			return 0, errI2CBusError
 | 
								return 0, errI2CBusError
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							tries++
 | 
				
			||||||
 | 
							if tries >= i2cTimeout {
 | 
				
			||||||
 | 
								return 0, errI2CReadTimeout
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	i2c.Bus.EVENTS_RXDREADY.Set(0)
 | 
						i2c.Bus.EVENTS_RXDREADY.Set(0)
 | 
				
			||||||
	return byte(i2c.Bus.RXD.Get()), nil
 | 
						return byte(i2c.Bus.RXD.Get()), nil
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче