mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-18 19:44:00 +00:00
machine: make sure DMA buffers do not escape unnecessarily
Writing the pointer of a buffer to memory-mapped I/O will normally cause it to escape, which forces the compiler to heap-allocate the buffer. But we do know how long the value stays alive, so we can tell the compiler to keep it alive exactly until it is not needed anymore - and tell it to not treat the pointer-to-uintptr cast as escaping.
This commit is contained in:
committed by
Ron Evans
parent
5ae8fd1f6f
commit
b203314c2f
@@ -145,7 +145,9 @@ func (a *ADC) Get() uint16 {
|
||||
nrf.SAADC.CH[0].PSELP.Set(pwmPin)
|
||||
|
||||
// Destination for sample result.
|
||||
nrf.SAADC.RESULT.PTR.Set(uint32(uintptr(unsafe.Pointer(&rawValue))))
|
||||
// Note: rawValue doesn't need to be kept alive for the GC, since the
|
||||
// volatile read later will force it to stay alive.
|
||||
nrf.SAADC.RESULT.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(&rawValue))))
|
||||
nrf.SAADC.RESULT.MAXCNT.Set(1) // One sample
|
||||
|
||||
// Start tasks.
|
||||
@@ -312,7 +314,7 @@ func (spi *SPI) Tx(w, r []byte) error {
|
||||
if nr > spiMaxBufferSize {
|
||||
nr = spiMaxBufferSize
|
||||
}
|
||||
spi.Bus.RXD.PTR.Set(uint32(uintptr(unsafe.Pointer(&r[0]))))
|
||||
spi.Bus.RXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(r)))))
|
||||
r = r[nr:]
|
||||
}
|
||||
spi.Bus.RXD.MAXCNT.Set(nr)
|
||||
@@ -323,7 +325,7 @@ func (spi *SPI) Tx(w, r []byte) error {
|
||||
if nw > spiMaxBufferSize {
|
||||
nw = spiMaxBufferSize
|
||||
}
|
||||
spi.Bus.TXD.PTR.Set(uint32(uintptr(unsafe.Pointer(&w[0]))))
|
||||
spi.Bus.TXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(w)))))
|
||||
w = w[nw:]
|
||||
}
|
||||
spi.Bus.TXD.MAXCNT.Set(nw)
|
||||
@@ -337,6 +339,11 @@ func (spi *SPI) Tx(w, r []byte) error {
|
||||
spi.Bus.EVENTS_END.Set(0)
|
||||
}
|
||||
|
||||
// Make sure the w and r buffers stay alive for the GC until this point,
|
||||
// since they are used by the hardware but not otherwise visible.
|
||||
keepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(r)))
|
||||
keepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(w)))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user