@@ -5,6 +5,8 @@ package machine
55
66import (
77 "device/esp"
8+ "device/riscv"
9+ "errors"
810 "runtime/interrupt"
911 "runtime/volatile"
1012 "sync"
@@ -214,18 +216,269 @@ func setupPinInterrupt() error {
214216 }).Enable ()
215217}
216218
217- var DefaultUART = UART0
218-
219219var (
220+ DefaultUART = UART0
221+
220222 UART0 = & _UART0
221223 _UART0 = UART {Bus : esp .UART0 , Buffer : NewRingBuffer ()}
222224 UART1 = & _UART1
223225 _UART1 = UART {Bus : esp .UART1 , Buffer : NewRingBuffer ()}
226+
227+ onceUart = sync.Once {}
228+ errSamePins = errors .New ("UART: invalid pin combination" )
229+ errWrongUART = errors .New ("UART: unsupported UARTn" )
230+ errWrongBitSize = errors .New ("UART: invalid data size" )
231+ errWrongStopBitSize = errors .New ("UART: invalid bit size" )
224232)
225233
226234type UART struct {
227- Bus * esp.UART_Type
228- Buffer * RingBuffer
235+ Bus * esp.UART_Type
236+ Buffer * RingBuffer
237+ ParityErrorDetected bool // set when parity error detected
238+ DataErrorDetected bool // set when data corruption detected
239+ DataOverflowDetected bool // set when data overflow detected in UART FIFO buffer or RingBuffer
240+ }
241+
242+ type UARTStopBits int
243+
244+ const (
245+ UARTStopBits_Default UARTStopBits = iota
246+ UARTStopBits_1
247+ UARTStopBits_1_5
248+ UARTStopBits_2
249+ )
250+
251+ const (
252+ defaultDataBits = 8
253+ defaultStopBit = 1
254+ defaultParity = ParityNone
255+
256+ uartInterrupts = esp .UART_INT_ENA_RXFIFO_FULL_INT_ENA |
257+ esp .UART_INT_ENA_PARITY_ERR_INT_ENA |
258+ esp .UART_INT_ENA_FRM_ERR_INT_ENA |
259+ esp .UART_INT_ENA_RXFIFO_OVF_INT_ENA |
260+ esp .UART_INT_ENA_GLITCH_DET_INT_ENA
261+
262+ pplClockFreq = 80e6
263+ )
264+
265+ type registerSet struct {
266+ interruptMapReg * volatile.Register32
267+ uartClockBitMask uint32
268+ gpioMatrixSignal uint32
269+ }
270+
271+ func (uart * UART ) Configure (config UARTConfig ) error {
272+ if config .BaudRate == 0 {
273+ config .BaudRate = 115200
274+ }
275+ if config .TX == config .RX {
276+ return errSamePins
277+ }
278+ switch {
279+ case uart .Bus == esp .UART0 :
280+ return uart .configure (config , registerSet {
281+ interruptMapReg : & esp .INTERRUPT_CORE0 .UART_INTR_MAP ,
282+ uartClockBitMask : esp .SYSTEM_PERIP_CLK_EN0_UART_CLK_EN ,
283+ gpioMatrixSignal : 6 ,
284+ })
285+ case uart .Bus == esp .UART1 :
286+ return uart .configure (config , registerSet {
287+ interruptMapReg : & esp .INTERRUPT_CORE0 .UART1_INTR_MAP ,
288+ uartClockBitMask : esp .SYSTEM_PERIP_CLK_EN0_UART1_CLK_EN ,
289+ gpioMatrixSignal : 9 ,
290+ })
291+ }
292+ return errWrongUART
293+ }
294+
295+ func (uart * UART ) configure (config UARTConfig , regs registerSet ) error {
296+
297+ initUARTClock (uart .Bus , regs )
298+
299+ // - disbale TX/RX clock to make sure the UART transmitter or receiver is not at work during configuration
300+ uart .Bus .SetCLK_CONF_TX_SCLK_EN (0 )
301+ uart .Bus .SetCLK_CONF_RX_SCLK_EN (0 )
302+
303+ // Configure static registers (Ref: Configuring URATn Communication)
304+
305+ // - default clock source: 1=APB_CLK, 2=FOSC_CLK, 3=XTAL_CLK
306+ uart .Bus .SetCLK_CONF_SCLK_SEL (1 )
307+ // reset divisor of the divider via UART_SCLK_DIV_NUM, UART_SCLK_DIV_A, and UART_SCLK_DIV_B
308+ uart .Bus .SetCLK_CONF_SCLK_DIV_NUM (0 )
309+ uart .Bus .SetCLK_CONF_SCLK_DIV_A (0 )
310+ uart .Bus .SetCLK_CONF_SCLK_DIV_B (0 )
311+
312+ // - the baud rate
313+ uart .SetBaudRate (config .BaudRate )
314+ // - the data format
315+ uart .SetFormat (defaultDataBits , defaultStopBit , defaultParity )
316+ // - set UART mode
317+ uart .Bus .SetRS485_CONF_RS485_EN (0 )
318+ uart .Bus .SetRS485_CONF_RS485TX_RX_EN (0 )
319+ uart .Bus .SetRS485_CONF_RS485RXBY_TX_EN (0 )
320+ uart .Bus .SetCONF0_IRDA_EN (0 )
321+ // - disable hw-flow control
322+ uart .Bus .SetCONF0_TX_FLOW_EN (0 )
323+ uart .Bus .SetCONF1_RX_FLOW_EN (0 )
324+
325+ // synchronize values into Core Clock
326+ uart .Bus .SetID_REG_UPDATE (1 )
327+
328+ uart .setupPins (config , regs )
329+ uart .configureInterrupt (regs .interruptMapReg )
330+ uart .enableTransmitter ()
331+ uart .enableReceiver ()
332+
333+ // Start TX/RX
334+ uart .Bus .SetCLK_CONF_TX_SCLK_EN (1 )
335+ uart .Bus .SetCLK_CONF_RX_SCLK_EN (1 )
336+ return nil
337+ }
338+
339+ func (uart * UART ) SetFormat (dataBits , stopBits int , parity UARTParity ) error {
340+ if dataBits < 5 {
341+ return errWrongBitSize
342+ }
343+ if stopBits > 1 {
344+ return errWrongStopBitSize
345+ }
346+ // - data length
347+ uart .Bus .SetCONF0_BIT_NUM (uint32 (dataBits - 5 ))
348+ // - stop bit
349+ uart .Bus .SetCONF0_STOP_BIT_NUM (uint32 (stopBits ))
350+ // - parity check
351+ switch parity {
352+ case ParityNone :
353+ uart .Bus .SetCONF0_PARITY_EN (0 )
354+ case ParityEven :
355+ uart .Bus .SetCONF0_PARITY_EN (1 )
356+ uart .Bus .SetCONF0_PARITY (0 )
357+ case ParityOdd :
358+ uart .Bus .SetCONF0_PARITY_EN (1 )
359+ uart .Bus .SetCONF0_PARITY (1 )
360+ }
361+ return nil
362+ }
363+
364+ func initUARTClock (bus * esp.UART_Type , regs registerSet ) {
365+ uartClock := & esp .SYSTEM .PERIP_CLK_EN0
366+ uartClockReset := & esp .SYSTEM .PERIP_RST_EN0
367+
368+ // Initialize/reset URATn (Ref: Initializing URATn)
369+ // - enable the clock for UART RAM
370+ uartClock .SetBits (esp .SYSTEM_PERIP_CLK_EN0_UART_MEM_CLK_EN )
371+ // - enable APB_CLK for UARTn
372+ uartClock .SetBits (regs .uartClockBitMask )
373+ // - reset sequence
374+ uartClockReset .ClearBits (regs .uartClockBitMask )
375+ bus .SetCLK_CONF_RST_CORE (1 )
376+ uartClockReset .SetBits (regs .uartClockBitMask )
377+ uartClockReset .ClearBits (regs .uartClockBitMask )
378+ bus .SetCLK_CONF_RST_CORE (0 )
379+ // synchronize core register
380+ bus .SetID_REG_UPDATE (0 )
381+ // enable RTC clock
382+ esp .RTC_CNTL .SetRTC_CLK_CONF_DIG_CLK8M_EN (1 )
383+ // wait for Core Clock to ready for configuration
384+ for bus .GetID_REG_UPDATE () > 0 {
385+ riscv .Asm ("nop" )
386+ }
387+ }
388+
389+ func (uart * UART ) SetBaudRate (baudRate uint32 ) {
390+ // based on esp-idf
391+ max_div := uint32 ((1 << 12 ) - 1 )
392+ sclk_div := (pplClockFreq + (max_div * baudRate ) - 1 ) / (max_div * baudRate )
393+ clk_div := (pplClockFreq << 4 ) / (baudRate * sclk_div )
394+ uart .Bus .SetCLKDIV (clk_div >> 4 )
395+ uart .Bus .SetCLKDIV_FRAG (clk_div & 0xf )
396+ uart .Bus .SetCLK_CONF_SCLK_DIV_NUM (sclk_div - 1 )
397+ }
398+
399+ func (uart * UART ) setupPins (config UARTConfig , regs registerSet ) {
400+ config .RX .Configure (PinConfig {Mode : PinInputPullup })
401+ config .TX .Configure (PinConfig {Mode : PinInputPullup })
402+
403+ // link TX with GPIO signal X (technical reference manual 5.10) (this is not interrupt signal!)
404+ config .TX .outFunc ().Set (regs .gpioMatrixSignal )
405+ // link RX with GPIO signal X and route signals via GPIO matrix (GPIO_SIGn_IN_SEL 0x40)
406+ inFunc (regs .gpioMatrixSignal ).Set (esp .GPIO_FUNC_IN_SEL_CFG_SIG_IN_SEL | uint32 (config .RX ))
407+ }
408+
409+ func (uart * UART ) configureInterrupt (intrMapReg * volatile.Register32 ) { // Disable all UART interrupts
410+ // Disable all UART interrupts
411+ uart .Bus .INT_ENA .ClearBits (0x0ffff )
412+
413+ intrMapReg .Set (7 )
414+ onceUart .Do (func () {
415+ _ = interrupt .New (7 , func (i interrupt.Interrupt ) {
416+ UART0 .serveInterrupt (0 )
417+ UART1 .serveInterrupt (1 )
418+ }).Enable ()
419+ })
420+ }
421+
422+ func (uart * UART ) serveInterrupt (num int ) {
423+ // get interrupt status
424+ interrutFlag := uart .Bus .INT_ST .Get ()
425+ if (interrutFlag & uartInterrupts ) == 0 {
426+ return
427+ }
428+
429+ // block UART interrupts while processing
430+ uart .Bus .INT_ENA .ClearBits (uartInterrupts )
431+
432+ if interrutFlag & esp .UART_INT_ENA_RXFIFO_FULL_INT_ENA > 0 {
433+ for uart .Bus .GetSTATUS_RXFIFO_CNT () > 0 {
434+ b := uart .Bus .GetFIFO_RXFIFO_RD_BYTE ()
435+ if ! uart .Buffer .Put (byte (b & 0xff )) {
436+ uart .DataOverflowDetected = true
437+ }
438+ }
439+ }
440+ if interrutFlag & esp .UART_INT_ENA_PARITY_ERR_INT_ENA > 0 {
441+ uart .ParityErrorDetected = true
442+ }
443+ if 0 != interrutFlag & esp .UART_INT_ENA_FRM_ERR_INT_ENA {
444+ uart .DataErrorDetected = true
445+ }
446+ if 0 != interrutFlag & esp .UART_INT_ENA_RXFIFO_OVF_INT_ENA {
447+ uart .DataOverflowDetected = true
448+ }
449+ if 0 != interrutFlag & esp .UART_INT_ENA_GLITCH_DET_INT_ENA {
450+ uart .DataErrorDetected = true
451+ }
452+
453+ // Clear the UART interrupt status
454+ uart .Bus .INT_CLR .SetBits (interrutFlag )
455+ uart .Bus .INT_CLR .ClearBits (interrutFlag )
456+ // Enable interrupts
457+ uart .Bus .INT_ENA .Set (uartInterrupts )
458+ }
459+
460+ const uart_empty_thresh_default = 10
461+
462+ func (uart * UART ) enableTransmitter () {
463+ uart .Bus .SetCONF0_TXFIFO_RST (1 )
464+ uart .Bus .SetCONF0_TXFIFO_RST (0 )
465+ // TXINFO empty threshold is when txfifo_empty_int interrupt produced after the amount of data in Tx-FIFO is less than this register value.
466+ uart .Bus .SetCONF1_TXFIFO_EMPTY_THRHD (uart_empty_thresh_default )
467+ // we are not using interrut on TX since write we are waiting for FIFO to have space.
468+ // uart.Bus.INT_ENA.SetBits(esp.UART_INT_ENA_TXFIFO_EMPTY_INT_ENA)
469+ }
470+
471+ func (uart * UART ) enableReceiver () {
472+ uart .Bus .SetCONF0_RXFIFO_RST (1 )
473+ uart .Bus .SetCONF0_RXFIFO_RST (0 )
474+ // using value 1 so that we can start populate ring buffer with data as we get it
475+ uart .Bus .SetCONF1_RXFIFO_FULL_THRHD (1 )
476+ // enable interrupts for:
477+ uart .Bus .SetINT_ENA_RXFIFO_FULL_INT_ENA (1 )
478+ uart .Bus .SetINT_ENA_FRM_ERR_INT_ENA (1 )
479+ uart .Bus .SetINT_ENA_PARITY_ERR_INT_ENA (1 )
480+ uart .Bus .SetINT_ENA_GLITCH_DET_INT_ENA (1 )
481+ uart .Bus .SetINT_ENA_RXFIFO_OVF_INT_ENA (1 )
229482}
230483
231484func (uart * UART ) WriteByte (b byte ) error {
0 commit comments