@@ -49,7 +49,7 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {
4949
5050 // Configure for a single shot to perform both write and read (as applicable)
5151 if len (w ) != 0 {
52- i2c .Bus .TXD .PTR .Set (uint32 (uintptr (unsafe .Pointer (& w [0 ]))))
52+ i2c .Bus .TXD .PTR .Set (uint32 (unsafeNoEscape (unsafe .Pointer (& w [0 ]))))
5353 i2c .Bus .TXD .MAXCNT .Set (uint32 (len (w )))
5454
5555 // If no read, immediately signal stop after TX
@@ -58,7 +58,7 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {
5858 }
5959 }
6060 if len (r ) != 0 {
61- i2c .Bus .RXD .PTR .Set (uint32 (uintptr (unsafe .Pointer (& r [0 ]))))
61+ i2c .Bus .RXD .PTR .Set (uint32 (unsafeNoEscape (unsafe .Pointer (& r [0 ]))))
6262 i2c .Bus .RXD .MAXCNT .Set (uint32 (len (r )))
6363
6464 // Auto-start Rx after Tx and Stop after Rx
@@ -89,6 +89,15 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {
8989 }
9090 }
9191
92+ // Make sure the w and r buffers stay alive until this point, so they won't
93+ // be garbage collected while the buffers are used by the hardware.
94+ if len (w ) > 0 {
95+ keepAliveNoEscape (unsafe .Pointer (& w [0 ]))
96+ }
97+ if len (r ) > 0 {
98+ keepAliveNoEscape (unsafe .Pointer (& r [0 ]))
99+ }
100+
92101 return
93102}
94103
@@ -117,7 +126,7 @@ func (i2c *I2C) Listen(addr uint8) error {
117126//
118127// For request events, the caller MUST call `Reply` to avoid hanging the i2c bus indefinitely.
119128func (i2c * I2C ) WaitForEvent (buf []byte ) (evt I2CTargetEvent , count int , err error ) {
120- i2c .BusT .RXD .PTR .Set (uint32 (uintptr (unsafe .Pointer (& buf [0 ]))))
129+ i2c .BusT .RXD .PTR .Set (uint32 (unsafeNoEscape (unsafe .Pointer (& buf [0 ]))))
121130 i2c .BusT .RXD .MAXCNT .Set (uint32 (len (buf )))
122131
123132 i2c .BusT .TASKS_PREPARERX .Set (nrf .TWIS_TASKS_PREPARERX_TASKS_PREPARERX_Trigger )
@@ -134,6 +143,10 @@ func (i2c *I2C) WaitForEvent(buf []byte) (evt I2CTargetEvent, count int, err err
134143 }
135144 }
136145
146+ // Make sure buf stays alive until this point, so it won't be garbage
147+ // collected while it is used by the hardware.
148+ keepAliveNoEscape (unsafe .Pointer (& buf [0 ]))
149+
137150 count = 0
138151 evt = I2CFinish
139152 err = nil
@@ -163,7 +176,7 @@ func (i2c *I2C) WaitForEvent(buf []byte) (evt I2CTargetEvent, count int, err err
163176
164177// Reply supplies the response data the controller.
165178func (i2c * I2C ) Reply (buf []byte ) error {
166- i2c .BusT .TXD .PTR .Set (uint32 (uintptr (unsafe .Pointer (& buf [0 ]))))
179+ i2c .BusT .TXD .PTR .Set (uint32 (unsafeNoEscape (unsafe .Pointer (& buf [0 ]))))
167180 i2c .BusT .TXD .MAXCNT .Set (uint32 (len (buf )))
168181
169182 i2c .BusT .EVENTS_STOPPED .Set (0 )
@@ -180,6 +193,10 @@ func (i2c *I2C) Reply(buf []byte) error {
180193 }
181194 }
182195
196+ // Make sure the buffer stays alive until this point, so it won't be garbage
197+ // collected while it is used by the hardware.
198+ keepAliveNoEscape (unsafe .Pointer (& buf [0 ]))
199+
183200 i2c .BusT .EVENTS_STOPPED .Set (0 )
184201
185202 return nil
0 commit comments