215 lines
9.6 KiB
C#
215 lines
9.6 KiB
C#
//
|
|
// Copyright (c) 2010-2018 Antmicro
|
|
//
|
|
// This file is licensed under the MIT License.
|
|
// Full license text is available in 'licenses/MIT.txt'.
|
|
//
|
|
using System.Collections.Generic;
|
|
using Antmicro.Renode.Peripherals.Bus;
|
|
using Antmicro.Renode.Core.Structure.Registers;
|
|
using Antmicro.Renode.Core;
|
|
using Antmicro.Renode.Logging;
|
|
|
|
namespace Antmicro.Renode.Peripherals.UART
|
|
{
|
|
public class ESP32_UART : UARTBase, IDoubleWordPeripheral, IBytePeripheral, IKnownSize
|
|
{
|
|
public ESP32_UART(Machine machine) : base(machine)
|
|
{
|
|
IRQ = new GPIO();
|
|
var registersMap = new Dictionary<long, DoubleWordRegister>
|
|
{
|
|
{(long)Registers.FIFO, new DoubleWordRegister(this)
|
|
.WithValueField(0, 8, writeCallback: (_, value) => this.TransmitCharacter((byte)value),
|
|
valueProviderCallback: _ => {
|
|
if(!TryGetCharacter(out var character))
|
|
{
|
|
this.Log(LogLevel.Warning, "Trying to read from an empty FIFO.");
|
|
}
|
|
return character;
|
|
})
|
|
},
|
|
{(long)Registers.INT_ENA, new DoubleWordRegister(this)
|
|
.WithFlag(0, FieldMode.Write, name: "UART_RXFIFO_FULL_INT_ENA")
|
|
},
|
|
{(long)Registers.INT_CLR, new DoubleWordRegister(this)
|
|
.WithValueField(0, 32, FieldMode.Write) // Temporary hack
|
|
},
|
|
{(long)Registers.RX_FILT, new DoubleWordRegister(this)
|
|
.WithValueField(0, 8, FieldMode.Read | FieldMode.Write, name: "GLITCH_FILT") // when input pulse width is lower than this value, the pulse is ignored.
|
|
.WithFlag(8, FieldMode.Read | FieldMode.Write, name: "GLITCH_FILT_EN") // Set this bit to enable Rx signal filter.
|
|
},
|
|
{(long)Registers.STATUS, new DoubleWordRegister(this)
|
|
.WithValueField(0, 10, FieldMode.Read, name: "RXFIFO_CNT")
|
|
.WithFlag(13, FieldMode.Read, name: "UART_DSRN")
|
|
.WithFlag(14, FieldMode.Read, valueProviderCallback: (_) => true, name: "UART_CTSN")
|
|
.WithFlag(15, FieldMode.Read, valueProviderCallback: (_) => true, name: "UART_RXD")
|
|
.WithValueField(16, 10, FieldMode.Read, name: "TXFIFO_CNT")
|
|
.WithFlag(29, FieldMode.Read, valueProviderCallback: (_) => true, name: "UART_DTRN")
|
|
.WithFlag(30, FieldMode.Read, valueProviderCallback: (_) => true, name: "UART_RTSN")
|
|
.WithFlag(31, FieldMode.Read, valueProviderCallback: (_) => true, name: "UART_TXD")
|
|
},
|
|
{(long)Registers.CONF0, new DoubleWordRegister(this)
|
|
.WithFlag(0, FieldMode.Write, name: "UART_PARITY")
|
|
.WithFlag(1, FieldMode.Write, name: "UART_PARITY_EN")
|
|
.WithValueField(2, 2, FieldMode.Read, name: "UART_BIT_NUM")
|
|
.WithValueField(4, 2, FieldMode.Read, name: "UART_STOPBIT_NUM")
|
|
.WithFlag(17, FieldMode.Write, name: "UART_RXFIFO_RST")
|
|
.WithFlag(18, FieldMode.Write, name: "UART_TXFIFO_RST")
|
|
.WithFlag(26, FieldMode.Write, name: "UART_ERR_WR_MASK")
|
|
.WithFlag(27, FieldMode.Write, name: "UART_AUTOBAUD_EN")
|
|
},
|
|
{(long)Registers.CONF1, new DoubleWordRegister(this)
|
|
.WithValueField(0, 10, FieldMode.Read | FieldMode.Write, name: "RXFIFO_FULL_THRHD") // It will produce rxfifo_full_int interrupt when receiver receives more data than this register value.
|
|
.WithValueField(10, 10, FieldMode.Read | FieldMode.Write, name: "TXFIFO_EMPTY_THRHD") // It will produce txfifo_empty_int interrupt when the data amount in Tx-FIFO is less than this register value.
|
|
.WithFlag(20, FieldMode.Read | FieldMode.Write, name: "DIS_RX_DAT_OVF") // Disable UART Rx data overflow detect.
|
|
.WithFlag(21, FieldMode.Read | FieldMode.Write, name: "RX_TOUT_FLOW_DIS") // Set this bit to stop accumulating idle_cnt when hardware flow control works.
|
|
.WithFlag(22, FieldMode.Read | FieldMode.Write, name: "RX_FLOW_EN") // This is the flow enable bit for UART receiver.
|
|
.WithFlag(23, FieldMode.Read | FieldMode.Write, name: "RX_TOUT_EN") // This is the enble bit for uart receiver's timeout function.
|
|
},
|
|
{(long)Registers.RXD_CNT, new DoubleWordRegister(this)
|
|
.WithValueField(0, 10, FieldMode.Read, name: "RXD_EDGE_CNT") // This register stores the count of rxd edge change. It is used in baud rate-detect process.
|
|
},
|
|
{(long)Registers.CLKDIV, new DoubleWordRegister(this)
|
|
.WithValueField(0, 12, FieldMode.Read | FieldMode.Write, name: "CLKDIV") // Clock divider configuration
|
|
.WithValueField(20, 4, FieldMode.Read | FieldMode.Write, name: "FRAG") // The decimal part of the frequency divider factor.
|
|
},
|
|
{(long)Registers.CLK_CONF, new DoubleWordRegister(this)
|
|
.WithValueField(0, 6, FieldMode.Read | FieldMode.Write, name: "SCLK_DIV_B") // The denominator of the frequency divider factor.
|
|
.WithValueField(6, 6, FieldMode.Read | FieldMode.Write, name: "SCLK_DIV_A") // The numerator of the frequency divider factor.
|
|
.WithValueField(12, 8, FieldMode.Read | FieldMode.Write, name: "SCLK_DIV_NUM") // The integral part of the frequency divider factor.
|
|
.WithValueField(20, 2, FieldMode.Read | FieldMode.Write, name: "SCLK_SEL") // UART clock source select. 1: 80Mhz, 2: 8Mhz, 3: XTAL.
|
|
.WithFlag(22, FieldMode.Read | FieldMode.Write, name: "SCLK_EN") // Set this bit to enable UART Tx/Rx clock.
|
|
.WithFlag(23, FieldMode.Read | FieldMode.Write, name: "RST_CORE") // Write 1 then write 0 to this bit, reset UART Tx/Rx.
|
|
.WithFlag(24, FieldMode.Read | FieldMode.Write, name: "TX_SCLK_EN") // Set this bit to enable UART Tx clock.
|
|
.WithFlag(25, FieldMode.Read | FieldMode.Write, name: "RX_SCLK_EN") // Set this bit to enable UART Rx clock.
|
|
.WithFlag(26, FieldMode.Read | FieldMode.Write, name: "TX_RST_CORE") // Write 1 then write 0 to this bit, reset UART Tx.
|
|
.WithFlag(27, FieldMode.Read | FieldMode.Write, name: "RX_RST_CORE") // Write 1 then write 0 to this bit, reset UART Rx.
|
|
},
|
|
};
|
|
|
|
registers = new DoubleWordRegisterCollection(this, registersMap);
|
|
}
|
|
|
|
public uint ReadDoubleWord(long offset)
|
|
{
|
|
return registers.Read(offset);
|
|
}
|
|
|
|
public byte ReadByte(long offset)
|
|
{
|
|
if (offset % 4 != 0)
|
|
{
|
|
// in the current configuration, only the lowest byte
|
|
// contains a meaningful data
|
|
return 0;
|
|
}
|
|
return (byte)ReadDoubleWord(offset);
|
|
}
|
|
|
|
public override void Reset()
|
|
{
|
|
base.Reset();
|
|
registers.Reset();
|
|
|
|
UpdateInterrupts();
|
|
}
|
|
|
|
public void WriteDoubleWord(long offset, uint value)
|
|
{
|
|
registers.Write(offset, value);
|
|
}
|
|
|
|
public void WriteByte(long offset, byte value)
|
|
{
|
|
if (offset % 4 != 0)
|
|
{
|
|
// in the current configuration, only the lowest byte
|
|
// contains a meaningful data
|
|
return;
|
|
}
|
|
|
|
WriteDoubleWord(offset, value);
|
|
}
|
|
|
|
public long Size => 0x100;
|
|
|
|
public GPIO IRQ { get; private set; }
|
|
|
|
public override Bits StopBits => Bits.One;
|
|
|
|
public override Parity ParityBit => Parity.None;
|
|
|
|
public override uint BaudRate => 115200;
|
|
|
|
protected override void CharWritten()
|
|
{
|
|
UpdateInterrupts();
|
|
}
|
|
|
|
protected override void QueueEmptied()
|
|
{
|
|
UpdateInterrupts();
|
|
}
|
|
|
|
private void UpdateInterrupts()
|
|
{
|
|
IRQ.Set(false);
|
|
}
|
|
|
|
private IFlagRegisterField rxEventEnabled;
|
|
private IFlagRegisterField rxEventPending;
|
|
private readonly DoubleWordRegisterCollection registers;
|
|
|
|
private enum Registers : long
|
|
{
|
|
// FIFO Configuration
|
|
FIFO = 0x00,
|
|
MEM_CONF = 0x60,
|
|
|
|
// UART interrupt register
|
|
INT_RAW = 0x04,
|
|
INT_ST = 0x08,
|
|
INT_ENA = 0x0c,
|
|
INT_CLR = 0x10,
|
|
|
|
// Configuration register
|
|
CLKDIV = 0x14,
|
|
RX_FILT = 0x18,
|
|
CONF0 = 0x20,
|
|
CONF1 = 0x24,
|
|
FLOW_CONF = 0x34,
|
|
SLEEP_CONF = 0x38,
|
|
SWFC_CONF0 = 0x3c,
|
|
SWFC_CONF1 = 0x40,
|
|
TXBRK_CONF = 0x44,
|
|
IDLE_CONF = 0x48,
|
|
RS485_CONF = 0x4c,
|
|
CLK_CONF = 0x78,
|
|
|
|
// Status register
|
|
STATUS = 0x1c,
|
|
MEM_TX_STATUS = 0x64,
|
|
MEM_RX_STATUS = 0x68,
|
|
FSM_STATUS = 0x6c,
|
|
|
|
// Autobaud register
|
|
LOWPULSE = 0x28,
|
|
HIGHPULSE = 0x2c,
|
|
RXD_CNT = 0x30,
|
|
POSPULSE = 0x70,
|
|
NEGPULSE = 0x74,
|
|
|
|
// Escape sequence selection configuration
|
|
AT_CMD_PRECNT = 0x50,
|
|
AT_CMD_POSTCNT = 0x54,
|
|
AT_CMD_GAPTOUT = 0x58,
|
|
AT_CMD_CHAR = 0x5c,
|
|
|
|
// Version
|
|
DATE = 0x7c,
|
|
ID = 0x80,
|
|
}
|
|
}
|
|
}
|