WebSockets_Generic Library. Now supporting nRF52, SAMD, DUE, STM32 (LAN8742A), etc

Working libraries, libraries being ported and related hardware
Post Reply
khoih-prog
Posts: 102
Joined: Thu Feb 27, 2020 7:54 am
Location: Toronto

WebSockets_Generic Library. Now supporting nRF52, SAMD, DUE, STM32 (LAN8742A), etc

Post by khoih-prog »

https://github.com/khoih-prog/WebSockets_Generic

How To Install Using Arduino Library Manager

Current Release

Why do we need this library

Many Web services require WebSockets library , which is so far written only for ESP8266/ESP32 boards. The ESP boards rely on this Markus Sattler's WebSockets library to connect to Alexa via Sinric or SinricPro skills.

This library is based on and modified from WebSockets library to provide support to many boards such as Teensy (4.1, 4.0, 3.x, LC), Arduino SAMD21, Adafruit SAMD21/SAMD51, nRF52, STM32, etc. and enable those boards to use WebSockets services, including voice-control Alexa along with Blynk. The WebSockets can be used with ESP's WiFi, WiFiNINA, W5x00 and ENC28J60 Ethernet.

Please see illustrating examples.

New in v2.2.1

1. Bump up to sync with v2.2.1 of original WebSockets library

New in v2.1.3

1. Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc..
2. Add support to SAM51 (Itsy-Bitsy M4, Metro M4, Grand Central M4, Feather M4 Express, etc.).
3. Add support to SAMD21 (ZERO, MKR, NANO_33_IOT, M0, M0 Pro, AdaFruit CIRCUITPLAYGROUND_EXPRESS, etc.).
4. Add support to Teensy (4.1, 4.0, 3.x, LC).
5. Add support to SAM DUE.


How to use

In your code, select one of the currently supported network connection from the following list:

1. NETWORK_ESP8266_ASYNC for ESP8266 Async
2. NETWORK_W5100 for W5x00 Ethernet
3. NETWORK_ENC28J60 for ENC28J60 Ethernet
4. NETWORK_ESP32 for ESP32 WiFi
5. NETWORK_ESP32_ETH for ESP32 Ethernet
6. NETWORK_WIFININA for WiFiNINA

then add

Code: Select all

#define WEBSOCKETS_NETWORK_TYPE
before

Code: Select all

#include <WebSocketsClient_Generic.h>

Example Generic_WebSocketServer_W5500

Code: Select all

#define _WEBSOCKETS_LOGLEVEL_     3
#define WEBSOCKETS_NETWORK_TYPE   NETWORK_W5100

#include <WebSocketsServer_Generic.h>

WebSocketsServer webSocket = WebSocketsServer(81);

uint8_t mac[6] =  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0A };

// Select the IP address according to your local network
IPAddress ip(192, 168, 2, 222);

// Only for W5100
#define SDCARD_CS       4

void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
{
  switch (type)
  {
    case WStype_DISCONNECTED:
      //Serial.println( "[" + String(num) + ] Disconnected!");
      break;
    case WStype_CONNECTED:
      {
        Serial.println( "[" + String(num) + ] Connected!");
        //IPAddress ip = webSocket.remoteIP(num);
        //Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);

        // send message to client
        webSocket.sendTXT(num, "Connected");
      }
      break;
    case WStype_TEXT:
      Serial.println( "[" + String(num) + ] get Text: " + String((char *) payload));

      // send message to client
      webSocket.sendTXT(num, "message here");

      // send data to all connected clients
       webSocket.broadcastTXT("message here");
      break;
    case WStype_BIN:
      Serial.println( "[" + String(num) + ] get binary length: " + String(length));
      
      //hexdump(payload, length);

      // send message to client
      // webSocket.sendBIN(num, payload, length);
      break;

      default:
        break;
  }
}

void setup()
{
  pinMode(SDCARD_CS, OUTPUT);
  digitalWrite(SDCARD_CS, HIGH); // Deselect the SD card
  
  // Serial.begin(921600);
  Serial.begin(115200);
  while (!Serial);

  Serial.println("\nStart Generic_WebSocketServer_W5500");

  for (uint8_t t = 4; t > 0; t--)
  {
    Serial.println("[SETUP] BOOT WAIT " + String(t));
    Serial.flush();
    delay(1000);
  }

  // start the ethernet connection and the server:
  // Use Static IP
  Ethernet.begin(mac, ip);
  //Configure IP address via DHCP
  //Ethernet.begin(mac);

  // server address, port and URL
  Serial.print("WebSockets Server IP address: ");
  Serial.println(Ethernet.localIP());
  
  webSocket.begin();
  webSocket.onEvent(webSocketEvent);
}

void loop()
{
  webSocket.loop();
}

Debug Terminal Output when running nRF52_Blynk_W5500_Alexa

You can see the Adafruit NRF52840_FEATHER Express board, with W5500 Ethernet shield, connects to Blynk using BlynkEthernet_WM Library

It also uses WebSockets_Generic library to communicate with SINRIC skills, and Alexa, to control a relay using Alexa voice control via Amazon Alexa phone APP

Code: Select all

Start nRF52_Blynk_W5500_Alexa using W5x00_Shield on NRF52840_FEATHER
LittleFS Flag read = 0xd0d04321
Flag read = 0xd0d04321
No doubleResetDetected
Saving DOUBLERESETDETECTOR_FLAG to DRD file : 0xd0d01234
Saving DRD file OK
SetFlag write = 0xd0d01234
[881] ======= Start Default Config Data =======
[881] Hdr=NonSSL,BName=Air-Control
[881] Svr=account.duckdns.org,Tok=token1
[881] Svr1=blynk-cloud.com,Tok1=<<my real Blynk auth>>
[882] Prt=8080,SIP=
[882] LoadCfgFile 
[883] OK
[883] ======= Start Stored Config Data =======
[883] Hdr=W5X00,BName=Air-Control
[883] Svr=account.duckdns.org,Tok=****
[884] Svr1=blynk-cloud.com,Tok1=****
[884] Prt=8080,SIP=
[884] CCSum=0x262e,RCSum=0x262e
[886] LoadCredFile 
[886] ChkCrR: Buffer allocated, sz=37
[886] ChkCrR:pdata=****,len=36
[886] ChkCrR:pdata=****,len=24
[886] OK
[887] CrCCsum=ea7,CrRCsum=ea7
[887] Buffer freed
[887] Valid Stored Dynamic Data
[889] LoadCredFile 
[889] CrR:pdata=****,len=36
[889] CrR:pdata=****,len=24
[889] OK
[889] CrCCsum=ea7,CrRCsum=ea7
[890] Hdr=W5X00,BName=Air-Control
[890] Svr=account.duckdns.org,Tok=****
[890] Svr1=blynk-cloud.com,Tok1=****
[890] Prt=8080,SIP=
[890] MAC:FE-F8-E0-CB-D0-BD
_pinCS = 0
W5100 init, using SS_PIN_DEFAULT = 10, new ss_pin = 10, W5100Class::ss_pin = 10
W5100::init: W5500, SSIZE =4096
[2577] IP:192.168.2.89
[2577] bg: noConfigPortal = true
[2577] bg: noConfigPortal = true
[2577] bg:ECon.TryB
[2577] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v0.6.1 on Arduino

[2578] BlynkArduinoClient.connect: Connecting to account.duckdns.org:8080
[2687] Ready (ping: 3ms).
[2754] Connected to Blynk Server = account.duckdns.org, Token = ****
[2754] bg:EBCon

Your stored Credentials :
SINRIC API Key = ****
Device_ID1 = ****
[WSc] Service connected to sinric.com at url: /
Waiting for commands from sinric.com ...
Stop doubleResetDetecting
Saving to DRD file : 0xd0d04321
Saving DRD file OK
LittleFS Flag read = 0xd0d04321
ClearFlag write = 0xd0d04321
[WSc] get text: {"deviceId":"****","action":"setPowerState","value":"ON"}
Turn on for unknown device id: ****
[WSc] get text: {"deviceId":"****","action":"setPowerState","value":"OFF"}
Turn off for unknown device id: ****
[WSc] get text: {"action":"test","sender":"web"}
[WSc] received test command from sinric.com
[WSc] get text: {"action":"test","sender":"web"}
[WSc] received test command from sinric.com
[WSc] get text: {"deviceId":"****","action":"setPowerState","value":"ON"}
Turn on device id: ****
[WSc] get text: {"deviceId":"****","action":"setPowerState","value":"OFF"}
Turn off Device ID: ****
Last edited by khoih-prog on Sun Feb 07, 2021 8:22 am, edited 1 time in total.
mrburnette
Posts: 633
Joined: Thu Dec 19, 2019 1:23 am
Answers: 7

Re: WebSockets_Generic Library. Now supporting nRF52, SAMD, DUE, STM32, etc

Post by mrburnette »

+1
Well done.
khoih-prog
Posts: 102
Joined: Thu Feb 27, 2020 7:54 am
Location: Toronto

Re: WebSockets_Generic Library. Now supporting nRF52, SAMD, DUE, STM32, etc

Post by khoih-prog »

New in v2.3.1

1. Sync with v2.3.1 of original WebSockets Library
2. Add support to ENC28J60 using EthernetENC Library
3. Add and update examples

New in v2.2.3

1. Add support to all STM32F/L/H/G/WB/MP1 (Nucleo-144 NUCLEO_F767ZI, Nucleo-64 NUCLEO_L053R8, etc.)
2. Add support to Seeeduino SAMD21/SAMD51 boards (SEEED_WIO_TERMINAL, SEEED_FEMTO_M0, SEEED_XIAO_M0, Wio_Lite_MG126, WIO_GPS_BOARD, SEEEDUINO_ZERO, SEEEDUINO_LORAWAN, SEEED_GROVE_UI_WIRELESS, etc.)
3. Add support to W5x00's Ethernet2, Ethernet3, EthernetLarge Libraries.
4. Add sample Packages_Patches for STM32 stm32 Nucleo-144 NUCLEO_F767ZI, Nucleo-64 NUCLEO_L053R8)
5. Add Packages' Patches and Ethernet Library Patches.

New in v2.2.2

1. Add support to Teensy boards, such as Teensy 4.1, 4.0. 3.6, 3.5, 3.2/3.1, 3.0, LC.
2. Add support to STM32 (Nucleo-144, Nucleo-64, Nucleo-32, Discovery, STM32F1, STM32F3, STM32F4, STM32H7, STM32L0, etc.).
3. Add support to SAM DUE
4. Add WebSocketServer examples to those supported boards.


===============================

Debug Terminal Output when running Generic_Ethernet_Speaker example on STM32F7 Nucleo-144 NUCLEO_F767ZI with W5500 Ethernet using Ethernet2 Library

You can see the NUCLEO_F767ZI board, with W5500 Ethernet using Ethernet2 Library, connects to SinricPro service using SinricPro_Generic Library

It also uses this WebSockets_Generic Library to communicate with SinricPro service, to control a Speaker with a Sinric Pro phone APP

Code: Select all

Starting Generic_Ethernet_Speaker on NUCLEO_F767ZI
Index = 0
Connected!
[Ethernet]: IP-Address is 192.168.2.84
[SRP] Creating new device. No current DeviceId = 123456789012345678901234
[SRP] add(): Adding DeviceId = 123456789012345678901234
[SRP] begin(): App-Key = 12345678-1234-1234-1234-123456789012
[SRP] begin(): App-Secret = 12345678-1234-1234-1234-123456789012-12345678-1234-1234-1234-123456789012
[SRP] Websocket: Connecting to WebSocket Server:  ws.sinric.pro
Websocket: headers:
appkey:12345678-1234-1234-1234-123456789012
deviceids:123456789012345678901234
restoredevicestates:false
ip:192.168.2.84
mac:DE:AD:BE:EF:FE:01
platform:NUCLEO_F767ZI
version:2.7.0
Connected to SinricPro

[SRP] handleReceiveQueue(): Message(s) in receiveQueue = 1
[SRP] handleReceiveQueue(): Valid Signature. Processing message...
[SRP] extractTimestamp(): Got Timestamp = 1601879732
[SRP] handleReceiveQueue(): Message(s) in receiveQueue = 1
[SRP] handleReceiveQueue(): Valid Signature. Processing message...
[SRP] extractTimestamp(): Got Timestamp = 1601879782
[SRP] handleRequest(): handling request
{
  "header": {
    "payloadVersion": 2,
    "signatureVersion": 1
  },
  "payload": {
    "action": "setVolume",
    "clientId": "sinricpro-web",
    "createdAt": 1601879782,
    "deviceAttributes": [],
    "deviceId": "123456789012345678901234",
    "replyToken": "7c989b3f-84aa-4462-8f3d-1a29c04c7df0",
    "type": "request",
    "value": {
      "volume": 45
    }
  },
  "signature": {
    "HMAC": "J27eUYEZJ+pQyzG5uC1+w/2jz8SKGU4LcP5snSb0KF4="
  }
}
Volume set to: 45
[SRP] handleSendQueue(): Sending Number of Message(s) in sendQueue = 1
{
  "header": {
    "payloadVersion": 2,
    "signatureVersion": 1
  },
  "payload": {
    "action": "setVolume",
    "clientId": "sinricpro-web",
    "createdAt": 1601879782,
    "deviceId": "123456789012345678901234",
    "message": "OK",
    "replyToken": "7c989b3f-84aa-4462-8f3d-1a29c04c7df0",
    "success": true,
    "type": "response",
    "value": {
      "volume": 45
    }
  },
  "signature": {
    "HMAC": "mYoFZxZ//yKd3BU/TWs56rKoM+lcdZsxVs1ql0/1XM4="
  }
}
[SRP] handleSendQueue: Sending to WebSocket
[SRP] handleSendQueue(): Message sent.
[SRP] handleReceiveQueue(): Message(s) in receiveQueue = 1
[SRP] handleReceiveQueue(): Valid Signature. Processing message...
[SRP] extractTimestamp(): Got Timestamp = 1601879790
[SRP] handleRequest(): handling request
{
  "header": {
    "payloadVersion": 2,
    "signatureVersion": 1
  },
  "payload": {
    "action": "setPowerState",
    "clientId": "sinricpro-web",
    "createdAt": 1601879790,
    "deviceAttributes": [],
    "deviceId": "123456789012345678901234",
    "replyToken": "0069ff67-31ee-4e6e-a647-a054617a2061",
    "type": "request",
    "value": {
      "state": "Off"
    }
  },
  "signature": {
    "HMAC": "kx6ZtXl1DUNMIXCmlcBO5ni8NN9w1CLaM8hSIESM9fM="
  }
}
Speaker turned off
[SRP] handleSendQueue(): Sending Number of Message(s) in sendQueue = 1
{
  "header": {
    "payloadVersion": 2,
    "signatureVersion": 1
  },
  "payload": {
    "action": "setPowerState",
    "clientId": "sinricpro-web",
    "createdAt": 1601879790,
    "deviceId": "123456789012345678901234",
    "message": "OK",
    "replyToken": "0069ff67-31ee-4e6e-a647-a054617a2061",
    "success": true,
    "type": "response",
    "value": {
      "state": "Off"
    }
  },
  "signature": {
    "HMAC": "qiI38SI0ulIJKXR/R/Zm9n6Uhd3HlNmX2vto9DkDah8="
  }
}
[SRP] handleSendQueue: Sending to WebSocket
[SRP] handleSendQueue(): Message sent.
[SRP] handleReceiveQueue(): Message(s) in receiveQueue = 1
[SRP] handleReceiveQueue(): Valid Signature. Processing message...
[SRP] extractTimestamp(): Got Timestamp = 1601879793
[SRP] handleRequest(): handling request
{
  "header": {
    "payloadVersion": 2,
    "signatureVersion": 1
  },
  "payload": {
    "action": "setPowerState",
    "clientId": "sinricpro-web",
    "createdAt": 1601879793,
    "deviceAttributes": [],
    "deviceId": "123456789012345678901234",
    "replyToken": "d4d1d50c-9c44-40fa-943c-84c40c0d7550",
    "type": "request",
    "value": {
      "state": "On"
    }
  },
  "signature": {
    "HMAC": "49poW0mpG3CZUs8UJ48EF6eAw8mz09jcfGRy2Xob86w="
  }
}
Speaker turned on
[SRP] handleSendQueue(): Sending Number of Message(s) in sendQueue = 1
{
  "header": {
    "payloadVersion": 2,
    "signatureVersion": 1
  },
  "payload": {
    "action": "setPowerState",
    "clientId": "sinricpro-web",
    "createdAt": 1601879793,
    "deviceId": "123456789012345678901234",
    "message": "OK",
    "replyToken": "d4d1d50c-9c44-40fa-943c-84c40c0d7550",
    "success": true,
    "type": "response",
    "value": {
      "state": "On"
    }
  },
  "signature": {
    "HMAC": "msDcqzA0tGgzJOB0uAeaiIEFvPSQ3ACTZPmk+lMty5o="
  }
}
[SRP] handleSendQueue: Sending to WebSocket
[SRP] handleSendQueue(): Message sent.
khoih-prog
Posts: 102
Joined: Thu Feb 27, 2020 7:54 am
Location: Toronto

Re: WebSockets_Generic Library. Now supporting nRF52, SAMD, DUE, STM32, etc

Post by khoih-prog »

Major Release v2.4.0

1. Add support to Teensy 4.1 using NativeEthernet.
2. Add support to STM32F/L/H/G/WB/MP1 using built-in LAN8742A.
3. Sync with v2.3.4 of original WebSockets library
4. Add Teensy, Teensy 4.1 NativeEthernet and STM32 LAN8742A examples.
5. Fix bugs in and optimize examples.

Release v2.3.4

1. Add SSL support to boards using WiFiNINA (Nano-33-IoT, etc.)
2. Add SSL support to boards using Realtek RTL8720DN WiFi and Seeed_Arduino_rpcWiFi (WIO_Terminal, etc.)
3. Upgrade WS and WSS examples.

Release v2.3.3
1. Fix compile errors for boards (nRF52, SAMD, etc.) using libraries with lib64, such as EthernetWebServer
2. Fix SeeedStudio SEEED_WIO_TERMINAL compile errors.
3. Add file to SeeedStudio SAMD Packages' Patches.
4. Fix compiler warnings for duplications in WS_LOG with WiFiWebServer

Release v2.3.2

1. Add support to Realtek RTL8720DN WiFi using Seeed_Arduino_rpcWiFi and Seeed_Arduino_rpcUnified libraries. This RTL8720DN supports Dual-Band 2.4GHz / 5GHz Wi-Fi (802.11 a/b/g/n) as well as BLE/BLE 5.0 and is currently used in SeeedStudio SEEED_WIO_TERMINAL.
2. Add examples for SeeedStudio SEEED_WIO_TERMINAL and update all examples
3. Add Version string definition
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: WebSockets_Generic Library. Now supporting nRF52, SAMD, DUE, STM32 (LAN8742A), etc

Post by stevestrong »

Hi @khoih-prog ,

I see there are two websocket libraries in your repo:
1 - WebSockets_Generic - based on https://github.com/Links2004/arduinoWebSockets
and
2 - WebSockets2_Generic - based on https://github.com/gilmaimon/ArduinoWebsockets

If I understood correctly, the second supports websockets server functionality, the first not.

Are there more differences between them?
What about resources usage like RAM and flash? Which one is more lightweight?

I ask this because I would like to have websockets with STM32F103 and F4 families connected to a W5500 module using minimal resources.
Which library would you recommend?
khoih-prog
Posts: 102
Joined: Thu Feb 27, 2020 7:54 am
Location: Toronto

Re: WebSockets_Generic Library. Now supporting nRF52, SAMD, DUE, STM32 (LAN8742A), etc

Post by khoih-prog »

Hi @stevestrong

Thanks for your interests in the libraries about which you understand correctly that only the ESP32/ESP8266 WS Server is working correctly on WebSockets_Generic.
What about resources usage like RAM and flash? Which one is more lightweight?
The resources usage are very similar, IMHO, the difference is only several hundred bytes, without carefully checking yet, between

1. Generic_WebSocketClient_W5500

Code: Select all

Sketch uses 40440 bytes (30%) of program storage space. Maximum is 131072 bytes.
Global variables use 1880 bytes (9%) of dynamic memory, leaving 18600 bytes for local variables. Maximum is 20480 bytes.
2. STM32-Ethernet-Client

Code: Select all

Sketch uses 40776 bytes (31%) of program storage space. Maximum is 131072 bytes.
Global variables use 1284 bytes (6%) of dynamic memory, leaving 19196 bytes for local variables. Maximum is 20480 bytes.
when compiled for STMF103CB

It's really difficult to correctly suggest one without knowing all the details of your use case. But I personally prefer the latter for future expansion (WS Server, non-blocking WS Server, etc.)
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: WebSockets_Generic Library. Now supporting nRF52, SAMD, DUE, STM32 (LAN8742A), etc

Post by stevestrong »

I am interested in WebSocket server running on STM32F407 generic.
I tried this library: https://github.com/gilmaimon/ArduinoWebsockets which has the same author as your WebSockets2_generic libary, and I though that the libraries would be similar, but I got the websocket server example compiled to 113kB flash size.
Could you share with me the entire Arduino message (with verbose on)? I probably miss some optimization parameters.

I will try later your WebSockets2_generic libary,
khoih-prog
Posts: 102
Joined: Thu Feb 27, 2020 7:54 am
Location: Toronto

Re: WebSockets_Generic Library. Now supporting nRF52, SAMD, DUE, STM32 (LAN8742A), etc

Post by khoih-prog »

STM32-Ethernet-Client, compiled for Generic STM32F407VE,

Code: Select all

Sketch uses 43856 bytes (8%) of program storage space. Maximum is 524288 bytes.
Global variables use 1380 bytes (1%) of dynamic memory, leaving 129692 bytes for local variables. Maximum is 131072 bytes.
The file is too large and is zipped and attached.
Attachments
WebSocket2_Generic_STM32_Compile_STM32F4_Forum Post.zip
(4.59 KiB) Downloaded 345 times
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: WebSockets_Generic Library. Now supporting nRF52, SAMD, DUE, STM32 (LAN8742A), etc

Post by stevestrong »

Thanks for the info, I was missing the linker directive:

Code: Select all

-specs=nano.specs
Now I also get code size around 45kB.
khoih-prog
Posts: 102
Joined: Thu Feb 27, 2020 7:54 am
Location: Toronto

Re: WebSockets_Generic Library. Now supporting nRF52, SAMD, DUE, STM32 (LAN8742A), etc

Post by khoih-prog »

So glad that you found out and fixed the obese code size issue. I still can't imagine that linker directive has so much effect.

More info about that linker directive can be found at What are “nosys”, “nano”, “rdimon” terms when using ARM GCC and the file nano.specs for STM32

Code: Select all

%rename link                nano_link
%rename link_gcc_c_sequence                nano_link_gcc_c_sequence
%rename cpp_unique_options		nano_cpp_unique_options

*cpp_unique_options:
-isystem =/include/newlib-nano %(nano_cpp_unique_options)

*nano_libc:
-lc_nano

*nano_libgloss:
%{specs=rdimon.specs:-lrdimon_nano} %{specs=nosys.specs:-lnosys}

*link_gcc_c_sequence:
%(nano_link_gcc_c_sequence) --start-group %G %(nano_libc) %(nano_libgloss) --end-group

*link:
%(nano_link) %:replace-outfile(-lc -lc_nano) %:replace-outfile(-lg -lg_nano) %:replace-outfile(-lrdimon -lrdimon_nano) %:replace-outfile(-lstdc++ -lstdc++_nano) %:replace-outfile(-lsupc++ -lsupc++_nano)

*lib:
%{!shared:%{g*:-lg_nano} %{!p:%{!pg:-lc_nano}}%{p:-lc_p}%{pg:-lc_p}}
And from Nano libraries usage
To use newlib-nano, users should provide additional gcc link time option --specs=nano.specs; Nano.specs also handles two additional gcc libraries: libstdc++_s.a and libsupc++_s.a, which are optimized for code size.
Post Reply

Return to “Libraries & Hardware”