The linking error is definitely from you compiling it for x86 / x64.
I have personally tried to compile GMP for ESP8266 (xtensa-lx106) some time ago and have not succeeded. While it possible to get the libgmp.a
compiled properly (after a tiny but of Makefile hacking, config.h massaging and a very long ./configure
command that has all the esp8266-specific build flags), it immediately overflowed the available IRAM in the ESP8266. I have not looked further at it since then. I can publish my current state when I can.
This seems like a big red flag. There should be no 2048 bit long continuous numbers in the… USB PD protocol. Perhaps you need to construct a 2048 bit long message, made out of individual bytes or some individual integers in them. In that case you want a struct
definition if the layout of which field is where is known beforehand.
// define datastructure
typedef struct {
uint32_t some_field_1;
int16_t power;
uint8_t byte_coded[64];
float what_even_is_this;
//...
} weird_usb_pd_message;
// create message and fill data
weird_usb_pd_message my_msg;
my_msg.some_field_1 = 12345;
my_msg.power = 999;
const uint8_t x[64] = { 0xab, 0xcd, 0xef};
memcpy(&my_msg.byte_coded, x, sizeof(x));
// send off..
If the structure is not known beforehand or very dynamic, a simple byte buffer (uint8_t usb_msg[256];
) can be used in which you can push elements into (e.g., a byte, a 16-bit short, a 32-bit int, a float, another byte array / structure, etc.), that at the end of all operations may have 2048 bits in it. In that case you can write the logic yourself (essentially memcpy()s and boundary checks) or even use a premade library like https://github.com/helins/byte_buffer.cpp.
ubyte_t main_arr[64] ;
byte_buffer b( main_arr, 64 ) ;
// push some data into it
b.putr< int >( 42 ) ;
b.putr< char >( 'a' ) ;
b.putr< float >( 42.42 ) ;
// main_arr now has b.position() bytes written to it
In the case that you are absolutely sure you need to do arithmetic (plus, minus, multiply, divide, modulus, exponentiation, inverted-modulo, GCD, …) on a 2048 bit number, and gmp-mini doesn’t cut in, the next best is to use the mbedTLS library. The library features a general “big int” sublibrary that you can freely use, mbedtls_mpi
and all. It compiles for all platforms with very minimal configuration / integration for the target, only if you want it.
For example:
[env:nodemcuv2]
platform = espressif8266
board = nodemcuv2
framework = arduino
monitor_speed = 115200
; activate Bignum support in mbedTLS
build_flags =
-DMBEDTLS_BIGNUM_C
; slightly older mbedTLS version
; but has integration with ESP8266's RNG and network interface
lib_deps =
https://github.com/TerpDAC/mbedtls-esp8266-arduino.git
#include <Arduino.h>
#include <mbedtls/bignum.h>
void setup() {
Serial.begin(115200);
}
void print_mpi(mbedtls_mpi* num, const char* name) {
size_t resultStrLen = 0;
static char resultStr[512];
mbedtls_mpi_write_string(num, 10, resultStr, sizeof(resultStr), &resultStrLen);
Serial.print(name);
Serial.print(": ");
Serial.print((const char*)resultStr);
Serial.println();
}
void loop() {
mbedtls_mpi a, b, result;
mbedtls_mpi_init(&a);
mbedtls_mpi_init(&b);
mbedtls_mpi_init(&result);
// read big decimal number from string
mbedtls_mpi_read_string(&a, 10, "12345678999999999999999");
// read big hexadecimal number from string
mbedtls_mpi_read_string(&b, 16, "ABCDEF123456789ABCDEF123");
// multiply them
mbedtls_mpi_mul_mpi(&result, &a, &b);
// print all out
print_mpi(&a, "A");
print_mpi(&b, "B");
print_mpi(&result, "A * B");
// free memory
mbedtls_mpi_free(&a);
mbedtls_mpi_free(&b);
mbedtls_mpi_free(&result);
Serial.println("============ CALCULATION DONE ====================");
delay(5000);
}
A: 12345678999999999999999
B: 53170895453873139248688722211
A * B: 656430807416077083886558964441722395860751311277789
============ CALCULATION DONE ====================