Skip to main content

PPP

Point-to-Point Protocol (PPP) is a serial-link protocol that dates back to dial-up Internet and is still the standard way to bring a cellular modem onto a TCP/IP network. Even on small IoT designs, PPP is what gives you a real IP stack — and a TLS-secured connection — instead of trading raw AT-command payloads with the modem.

PPP doesn't use a MAC address — the link is point-to-point, not Ethernet.

NuGet packages: GHIElectronics.TinyCLR.Devices.Network, GHIElectronics.TinyCLR.Devices.Uart, GHIElectronics.TinyCLR.Devices.Gpio, GHIElectronics.TinyCLR.Pins.

Connecting via a cellular modem

The example below targets the LTE IoT 2 click module on an SCM20260D Dev Board. The same code has been tested with the SIMCOM SIM900 and NimbeLink Skywire cellular modems.

using System.Text;
using System.Threading;
using GHIElectronics.TinyCLR.Devices.Gpio;
using GHIElectronics.TinyCLR.Devices.Network;
using GHIElectronics.TinyCLR.Devices.Uart;
using GHIElectronics.TinyCLR.Pins;
using System.Diagnostics;

bool linkReady = false;

// Reset the modem.
var reset = GpioController.GetDefault().OpenPin(SC20260.GpioPin.PI8);
reset.SetDriveMode(GpioPinDriveMode.Output);

reset.Write(GpioPinValue.High);
Thread.Sleep(200);
reset.Write(GpioPinValue.Low);
Thread.Sleep(7000); // Wait for the modem to initialize.

InitSimCard();
StartPpp();

void InitSimCard(){
var serial = UartController.FromName(SC20260.UartPort.Uart8);
var uartSetting = new UartSetting(){
BaudRate = 115200,
DataBits = 8,
Parity = UartParity.None,
StopBits = UartStopBitCount.One,
Handshaking = UartHandshake.None,
};
serial.SetActiveSettings(uartSetting);
serial.Enable();

while (!SendAT(serial, "AT")) { }

// Define PDP contexts for several carriers.
SendAT(serial, "AT+CGDCONT=1,\"IP\",\"h2g2\""); // Google Fi
SendAT(serial, "AT+CGDCONT=2,\"IP\",\"telargo.t-mobile.com\""); // T-Mobile
SendAT(serial, "AT+CGDCONT=3,\"IP\",\"fast.t-mobile.com\""); // T-Mobile
SendAT(serial, "AT+CGDCONT=4,\"IPV4V6\",\"NIMBLINK.GW12.VZWENTP\""); // NimbeLink

// Dial out. The "1" matches PDP context 1 (Google Fi) defined above.
SendAT(serial, "ATDT*99***1#");

Debug.WriteLine("Ready to start PPP");
}

void StartPpp(){
var networkController = NetworkController.FromName(SC20260.NetworkController.Ppp);

var networkInterfaceSetting = new PppNetworkInterfaceSettings(){
AuthenticationType = PppAuthenticationType.Pap,
Username = "",
Password = "",
};

var networkCommunicationInterfaceSettings = new UartNetworkCommunicationInterfaceSettings(){
ApiName = SC20260.UartPort.Uart8,
BaudRate = 115200,
DataBits = 8,
Parity = UartParity.None,
StopBits = UartStopBitCount.One,
Handshaking = UartHandshake.None,
};

networkController.SetInterfaceSettings(networkInterfaceSetting);
networkController.SetCommunicationInterfaceSettings(networkCommunicationInterfaceSettings);
networkController.SetAsDefaultController();

networkController.NetworkAddressChanged += NetworkController_NetworkAddressChanged;
networkController.NetworkLinkConnectedChanged += NetworkController_NetworkLinkConnectedChanged;

networkController.Enable();

while (!linkReady) { }
// Network is now ready to use.
}

void NetworkController_NetworkLinkConnectedChanged(NetworkController sender, NetworkLinkConnectedChangedEventArgs e){
Debug.WriteLine(e.Connected ? "Link connected" : "Link disconnected");
}

void NetworkController_NetworkAddressChanged(NetworkController sender, NetworkAddressChangedEventArgs e){
var ipProperties = sender.GetIPProperties();
var address = ipProperties.Address.GetAddressBytes();

Debug.WriteLine("IP: " + address[0] + "." + address[1] + "." + address[2] + "." + address[3]);

linkReady = address[0] != 0;
}

bool SendAT(UartController port, string command){
command += "\r";

var sendBuffer = Encoding.UTF8.GetBytes(command);
var readBuffer = new byte[256];
var read = 0;
var count = 10;

port.Write(sendBuffer, 0, sendBuffer.Length);

while (count-- > 0){
Thread.Sleep(100);
read += port.Read(readBuffer, read, readBuffer.Length - read);

var response = new string(Encoding.UTF8.GetChars(readBuffer, 0, read));

if (response.IndexOf("OK") != -1 || response.IndexOf("CONNECT") != -1)
{
Debug.WriteLine(" " + response);
return true;
}
}
return false;
}

Command mode and data mode

While PPP is running, the modem is in data mode — every byte over the serial link is a PPP frame. To send AT commands (signal strength, network status, etc.) you need to put the modem back into command mode with the +++ escape sequence.

Switching to command mode — send +++ as three bytes with no other characters within one second before or after, and all three bytes sent within one second of each other. The modem replies with OK and stops processing PPP frames.

note

Don't send \r or \n after +++ — unlike normal AT commands, the escape sequence has no line terminator.

Switching back to data mode — send ATO and wait for the response CONNECT 150000000. After that, the serial link is back in PPP mode.

To do this in code, suspend the network controller (so TinyCLR releases the UART), reuse the UART manually, then resume the controller when you're done:

// PPP is connected — suspend it to take over the UART.
networkController.Suspend();

var serial = UartController.FromName(SC20260.UartPort.Uart8);
serial.SetActiveSettings(115200, 8, UartParity.None, UartStopBitCount.One, UartHandshake.None);
serial.Enable();

Thread.Sleep(1000);

SendAT(serial, "+++"); // Enter command mode.
Thread.Sleep(1000);

SendAT(serial, "AT+CSQ"); // Example: check signal strength.

SendAT(serial, "ATO"); // Re-enter PPP data mode. Wait for "CONNECT 150000000".

serial.Dispose(); // Release the UART so PPP can resume on it.

networkController.Resume();

// Network is back online.

The SendAT helper used here is the same one defined in the main example above.

Security

PPP over a cellular link is encrypted end-to-end by TinyCLR — TLS and other crypto run on the SITCore processor before data hits the UART going to the modem. See the Cellular page → Security for the full explanation.

API reference

NamespaceDescription
GHIElectronics.TinyCLR.Devices.NetworkNetwork interface controller (PPP configuration)
GHIElectronics.TinyCLR.Devices.UartUART controller (underlying PPP transport)