@@ -318,7 +318,7 @@ const (
318318// the change parameter is ignored and can be set to any value (such as 0).
319319// If the pin is already configured with a callback, you must first unset
320320// this pins interrupt before you can set a new callback.
321- func (p Pin ) SetInterrupt (change PinChange , callback func (Pin )) ( err error ) {
321+ func (p Pin ) SetInterrupt (change PinChange , callback func (Pin )) error {
322322 if p >= maxPin {
323323 return ErrInvalidInputPin
324324 }
@@ -342,10 +342,10 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) (err error) {
342342 pinCallbacks [p ] = callback
343343
344344 onceSetupPinInterrupt .Do (func () {
345- err = setupPinInterrupt ()
345+ setupPinInterruptErr = setupPinInterrupt ()
346346 })
347- if err != nil {
348- return err
347+ if setupPinInterruptErr != nil {
348+ return setupPinInterruptErr
349349 }
350350
351351 p .pinReg ().Set (
@@ -358,34 +358,40 @@ func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) (err error) {
358358var (
359359 pinCallbacks [maxPin ]func (Pin )
360360 onceSetupPinInterrupt sync.Once
361+ setupPinInterruptErr error
361362)
362363
363364func setupPinInterrupt () error {
364365 esp .DPORT .SetPRO_GPIO_INTERRUPT_MAP_PRO_GPIO_INTERRUPT_PRO_MAP (cpuInterruptFromPin )
365- return interrupt .New (cpuInterruptFromPin , func (interrupt.Interrupt ) {
366- // Read and immediately clear interrupt status bits.
367- // Clearing before processing is critical for edge-triggered CPU
368- // interrupts: any new GPIO events that arrive during callback
369- // execution will set fresh STATUS bits, generating a new edge
370- // on the CPU interrupt line so they are not lost.
371- status := esp .GPIO .STATUS .Get ()
372- status1 := esp .GPIO .STATUS1 .Get ()
373- esp .GPIO .STATUS_W1TC .Set (status )
374- esp .GPIO .STATUS1_W1TC .Set (status1 )
375-
376- // Check status for GPIO0-31
377- for i , mask := 0 , uint32 (1 ); i < 32 ; i , mask = i + 1 , mask << 1 {
378- if (status & mask ) != 0 && pinCallbacks [i ] != nil {
379- pinCallbacks [i ](Pin (i ))
380- }
366+ return interrupt .New (cpuInterruptFromPin , handleGPIOInterrupt ).Enable ()
367+ }
368+
369+ // handleGPIOInterrupt is the GPIO pin change interrupt handler. It must be a
370+ // plain function (not a closure) because interrupt.New is a compiler intrinsic
371+ // that does not support closures.
372+ func handleGPIOInterrupt (interrupt.Interrupt ) {
373+ // Read and immediately clear interrupt status bits.
374+ // Clearing before processing is critical for edge-triggered CPU
375+ // interrupts: any new GPIO events that arrive during callback
376+ // execution will set fresh STATUS bits, generating a new edge
377+ // on the CPU interrupt line so they are not lost.
378+ status := esp .GPIO .STATUS .Get ()
379+ status1 := esp .GPIO .STATUS1 .Get ()
380+ esp .GPIO .STATUS_W1TC .Set (status )
381+ esp .GPIO .STATUS1_W1TC .Set (status1 )
382+
383+ // Check status for GPIO0-31
384+ for i , mask := 0 , uint32 (1 ); i < 32 ; i , mask = i + 1 , mask << 1 {
385+ if (status & mask ) != 0 && pinCallbacks [i ] != nil {
386+ pinCallbacks [i ](Pin (i ))
381387 }
382- // Check status for GPIO32-39
383- for i , mask := 32 , uint32 ( 1 ); i < maxPin ; i , mask = i + 1 , mask << 1 {
384- if ( status1 & mask ) != 0 && pinCallbacks [ i ] != nil {
385- pinCallbacks [i ]( Pin ( i ))
386- }
388+ }
389+ // Check status for GPIO32-39
390+ for i , mask := 32 , uint32 ( 1 ); i < maxPin ; i , mask = i + 1 , mask << 1 {
391+ if ( status1 & mask ) != 0 && pinCallbacks [i ] != nil {
392+ pinCallbacks [ i ]( Pin ( i ))
387393 }
388- }). Enable ()
394+ }
389395}
390396
391397var DefaultUART = UART0
@@ -395,22 +401,22 @@ var (
395401 _UART0 = UART {
396402 Bus : esp .UART0 ,
397403 Buffer : NewRingBuffer (),
398- TXRXSignal : 14 ,
399- RTSCTSSignal : 15 ,
404+ txrxSignal : 14 ,
405+ rtsctsSignal : 15 ,
400406 }
401407 UART1 = & _UART1
402408 _UART1 = UART {
403409 Bus : esp .UART1 ,
404410 Buffer : NewRingBuffer (),
405- TXRXSignal : 17 ,
406- RTSCTSSignal : 18 ,
411+ txrxSignal : 17 ,
412+ rtsctsSignal : 18 ,
407413 }
408414 UART2 = & _UART2
409415 _UART2 = UART {
410416 Bus : esp .UART2 ,
411417 Buffer : NewRingBuffer (),
412- TXRXSignal : 198 ,
413- RTSCTSSignal : 199 ,
418+ txrxSignal : 198 ,
419+ rtsctsSignal : 199 ,
414420 }
415421
416422 onceUart = sync.Once {}
@@ -435,16 +441,17 @@ const uartInterrupts = esp.UART_INT_ENA_RXFIFO_FULL_INT_ENA |
435441 esp .UART_INT_ENA_GLITCH_DET_INT_ENA
436442
437443type UART struct {
438- Bus * esp.UART_Type
439- Buffer * RingBuffer
440- TXRXSignal uint32
441- RTSCTSSignal uint32
442- ParityErrorDetected bool
443- DataErrorDetected bool
444- DataOverflowDetected bool
444+ Bus * esp.UART_Type
445+ Buffer * RingBuffer
446+
447+ txrxSignal uint32
448+ rtsctsSignal uint32
449+ parityErrorDetected bool
450+ dataErrorDetected bool
451+ dataOverflowDetected bool
445452}
446453
447- func (uart * UART ) Configure (config UARTConfig ) {
454+ func (uart * UART ) Configure (config UARTConfig ) error {
448455 if config .BaudRate == 0 {
449456 config .BaudRate = 115200
450457 }
@@ -457,6 +464,8 @@ func (uart *UART) Configure(config UARTConfig) {
457464 // the IO MUX to the USB-serial bridge. Re-routing them through the GPIO
458465 // matrix is unnecessary and can break RX, so we keep the bootloader setup
459466 // which is exactly what makes the boot log and greeting appear.
467+ // We still fall through to configure baud rate, interrupts, and the RX
468+ // FIFO even when pins are already wired.
460469 if config .TX == 0 && config .RX == 0 {
461470 switch uart .Bus {
462471 case esp .UART0 :
@@ -474,33 +483,35 @@ func (uart *UART) Configure(config UARTConfig) {
474483 uart .Bus .CLKDIV .Set (peripheralClock / config .BaudRate )
475484
476485 if config .RX != NoPin {
477- config .RX .configure (PinConfig {Mode : PinInputPullup }, uart .TXRXSignal )
486+ config .RX .configure (PinConfig {Mode : PinInputPullup }, uart .txrxSignal )
478487 if config .InvertRX {
479- inFunc (uart .TXRXSignal ).Set (esp .GPIO_FUNC_IN_SEL_CFG_SEL | uint32 (config .RX )<< esp .GPIO_FUNC_IN_SEL_CFG_IN_SEL_Pos | esp .GPIO_FUNC_IN_SEL_CFG_IN_INV_SEL )
488+ inFunc (uart .txrxSignal ).Set (esp .GPIO_FUNC_IN_SEL_CFG_SEL | uint32 (config .RX )<< esp .GPIO_FUNC_IN_SEL_CFG_IN_SEL_Pos | esp .GPIO_FUNC_IN_SEL_CFG_IN_INV_SEL )
480489 } else {
481- inFunc (uart .TXRXSignal ).Set (esp .GPIO_FUNC_IN_SEL_CFG_SEL | uint32 (config .RX )<< esp .GPIO_FUNC_IN_SEL_CFG_IN_SEL_Pos )
490+ inFunc (uart .txrxSignal ).Set (esp .GPIO_FUNC_IN_SEL_CFG_SEL | uint32 (config .RX )<< esp .GPIO_FUNC_IN_SEL_CFG_IN_SEL_Pos )
482491 }
483492 }
484493
485494 if config .TX != NoPin {
486- config .TX .configure (PinConfig {Mode : PinOutput }, uart .TXRXSignal )
495+ config .TX .configure (PinConfig {Mode : PinOutput }, uart .txrxSignal )
487496 if config .InvertTX {
488- config .TX .outFunc ().Set (uart .TXRXSignal | esp .GPIO_FUNC_OUT_SEL_CFG_INV_SEL )
497+ config .TX .outFunc ().Set (uart .txrxSignal | esp .GPIO_FUNC_OUT_SEL_CFG_INV_SEL )
489498 } else {
490- config .TX .outFunc ().Set (uart .TXRXSignal )
499+ config .TX .outFunc ().Set (uart .txrxSignal )
491500 }
492501 }
493502
494503 if config .RTS != NoPin {
495- config .RTS .configure (PinConfig {Mode : PinOutput }, uart .RTSCTSSignal )
504+ config .RTS .configure (PinConfig {Mode : PinOutput }, uart .rtsctsSignal )
496505 }
497506
498507 if config .CTS != NoPin {
499- config .CTS .configure (PinConfig {Mode : PinInputPullup }, uart .RTSCTSSignal )
508+ config .CTS .configure (PinConfig {Mode : PinInputPullup }, uart .rtsctsSignal )
500509 }
501510
502511 uart .configureInterrupt ()
503512 uart .enableReceiver ()
513+
514+ return nil
504515}
505516
506517func (uart * UART ) configureInterrupt () {
@@ -551,21 +562,21 @@ func (uart *UART) serveInterrupt() {
551562 // register, due to a silicon erratum. This mirrors writeByte.
552563 b := (* volatile .Register8 )(unsafe .Add (unsafe .Pointer (uart .Bus ), 0x200C0000 )).Get ()
553564 if ! uart .Buffer .Put (b ) {
554- uart .DataOverflowDetected = true
565+ uart .dataOverflowDetected = true
555566 }
556567 }
557568 }
558569 if interruptFlag & esp .UART_INT_ENA_PARITY_ERR_INT_ENA > 0 {
559- uart .ParityErrorDetected = true
570+ uart .parityErrorDetected = true
560571 }
561572 if interruptFlag & esp .UART_INT_ENA_FRM_ERR_INT_ENA != 0 {
562- uart .DataErrorDetected = true
573+ uart .dataErrorDetected = true
563574 }
564575 if interruptFlag & esp .UART_INT_ENA_RXFIFO_OVF_INT_ENA != 0 {
565- uart .DataOverflowDetected = true
576+ uart .dataOverflowDetected = true
566577 }
567578 if interruptFlag & esp .UART_INT_ENA_GLITCH_DET_INT_ENA != 0 {
568- uart .DataErrorDetected = true
579+ uart .dataErrorDetected = true
569580 }
570581
571582 // Clear the interrupt status bits.
0 commit comments