Math lib

blubb
Posts: 116
Joined: Mon Jun 22, 2015 5:35 am

Math lib

Postby blubb » Thu Aug 13, 2015 7:40 am

I'm currently re-writing a firmware that previously ran on an ATmega328. I want it to run on an ESP module (plus Wifi/webserver). The problem is, a part of it uses a lot of math functions. Only single precision is needed, so on the Atmel chip I could simply use the avr-gcc compiler which had a lib for that. In detail, we use sin, cos, asin, acos, atan2, fmod and hypot.
Will we eventually get an official math lib from Espressif? Compiling with -lm currently does not work. The compiler tries to put everything into RAM...
ESP8266 is a powerful chip and I would expect to be able to do anything I did with the (rather slow and very limited) ATmega.

datltq
Posts: 7
Joined: Wed Jun 10, 2015 2:55 pm

Re: Math lib

Postby datltq » Thu Aug 13, 2015 3:08 pm

Hi,

I did not use the non-RTOS SDK but recently updated of RTOS one include an irom version of libm. I think the non-RTOS SDK should be the same.


https://github.com/espressif/esp_iot_rtos_sdk/

NEW VERSION: 1.0.4

1. memory optimize;
2. add irom version libm.a: libmirom.a;


Dat.

blubb
Posts: 116
Joined: Mon Jun 22, 2015 5:35 am

Re: Math lib

Postby blubb » Thu Aug 13, 2015 8:25 pm

Thanks! That is great news.

There are two problems. The first is, M_PI is not defined. It's not a real issue, of course. Some C compilers don't do this.

The second problem concerns fmod.

Please try to compile

Code: Select all

double ICACHE_FLASH_ATTR test(void) {
        return fmod(-10, 3);
}


Error message:

Code: Select all

/opt/Espressif/esp_iot_sdk_v1.3.0/lib/libmirom.a(lib_a-e_fmod.o):(.irom0.literal+0x0): undefined reference to `__ieee754_remainder'
/opt/Espressif/esp_iot_sdk_v1.3.0/lib/libmirom.a(lib_a-e_fmod.o): In function `__ieee754_fmod':
/home/wjg/Workspace/esp-open-sdk/crosstool-NG/.build/src/newlib-2.0.0/newlib/libm/math/e_fmod.c:38: undefined reference to `__ieee754_remainder'


I don't know if this is the result of mixing the libs or if the problem exists in the RTOS-SDK as well. Maybe someone can try that?

Until that I have to implement fmod myself, which luckily is not too hard.

So my request to Espressif would be: Please fix fmod and include libmirom.a in the standard SDK. :)

eriksl
Posts: 159
Joined: Fri May 22, 2015 6:22 pm

Re: Math lib

Postby eriksl » Thu Aug 13, 2015 10:46 pm

I had exactly the same problem (also porting from atmega328p).

The math library IS available and it works, the problem is that everything ends up in iram which fills up before you know it.

So what needs to be done is a math library that has all/most symbols in irom. Do we have volunteers?

I ended up collecting source code replacements for the functions I needed and compiled them myself, including the irom region directive, problem solved...

blubb
Posts: 116
Joined: Mon Jun 22, 2015 5:35 am

Re: Math lib

Postby blubb » Fri Aug 14, 2015 2:04 am

Erik, try libmirom.a from the RTOS-SDK. Apart from the broken fmod and missing M_PI it's working fine here. Calculations are done correctly.
https://github.com/espressif/esp_iot_rt ... libmirom.a

datltq
Posts: 7
Joined: Wed Jun 10, 2015 2:55 pm

Re: Math lib

Postby datltq » Fri Aug 14, 2015 11:25 am

There also ports worth trying:

https://github.com/anakod/esp_microc
https://github.com/SuperHouse/esp-open-rtos (newlib with patch for threadsafe)

In the latest RTOS SDK, text are placed in IROM section by default. It's a nice thing :D

eriksl
Posts: 159
Joined: Fri May 22, 2015 6:22 pm

Re: Math lib

Postby eriksl » Fri Aug 14, 2015 5:23 pm

Bleh, I don't want an RTOS microcontroller. I want a real proper microcontroller with interrupts, hardware registers etc. The scheduling of threads I can do happily myself, no bloatware needed.

The moving of read only constants to irom sounds interesting. I believe nodemcu already does something like that. What I understand from it, is that you need to install an exception handler (in a very dirty way), because the esp8266 doesn't allow the flash to be used for read only data, and throws an execption. I can find the exception handler in the nodemcu code, but it doesn't seem to do anything but ignoring the exception. I'd expect a piece of emulation code, so I don't really understand, maybe somebody can explain this to me...?

By default all data (read write, read only, static or auto) ends up in dram, just like on Atmel.

dkinzer
Posts: 52
Joined: Fri Jul 31, 2015 7:37 am

Re: Math lib

Postby dkinzer » Sat Aug 15, 2015 7:32 am

eriksl wrote:[...] the esp8266 doesn't allow the flash to be used for read only data, and throws an execption.
I believe that this assertion is incorrect. I have several const data tables in Flash in my application. The only caveat is that you can't access such data directly unless every element happens to be 32-bit aligned and is a multiple of 32-bits in size. I handle this in my app by using some helper routines (similar to the __LPM_xxx() macros for the AVR) to access the elements of the data. Inside the routines, all reads are done on 32-bit boundaries and in multiples of 32-bits irrespective of the alignment and size of the data being requested.
Don Kinzer
Beaverton, OR, USA

eriksl
Posts: 159
Joined: Fri May 22, 2015 6:22 pm

Re: Math lib

Postby eriksl » Sat Aug 15, 2015 3:04 pm

I am going to try this out :D Thanks!

So if I would define a struct that is a multiple of 32 bits in size and that elements that are also multiples of 32 bits and I'd make an array of it, it would work? Maybe that's something we can leave to the compiler by specifying alignment and padding requirements.

It does seem a bit cumbersome for arbitrary character strings, though, which take up the largest part of my dram.

dkinzer
Posts: 52
Joined: Fri Jul 31, 2015 7:37 am

Re: Math lib

Postby dkinzer » Sat Aug 15, 2015 10:53 pm

eriksl wrote:It does seem a bit cumbersome for arbitrary character strings, though, which take up the largest part of my dram.
As I mentioned, I use helper routines to retrieve read-only data from Flash. I have specialized routines for byte, word, and dword values as well as a routine to copy an arbitrary byte stream from an arbitrary address. An adaptation of the latter routine appears below and the others can be derived from it. The code below was not compiled so there may be some errors in it but the concept should be clear.

Code: Select all

void ICACHE_FLASH_ATTR
flashReadData(const void *addr, void *bufp, uint16_t cnt)
{
    if ((bufp == NULL) || (cnt == 0))
        return;

    // reads from Flash must be done on 32-bit word boundaries
    uint16_t part;
    uint32_t ofst = (uint32_t)addr & 0x03;
    uint8_t *datap = bufp;
    union { uint32_t d; uint8_t b[4]; } data;
    const char *p = (const char *)addr;

    if (ofst)
    {
        // copy the bytes from the first partial word
        if ((part = 4 - ofst) > cnt)
            part = cnt;
        cnt -= part;
        data.d = *(uint32_t *)(p - ofst);
        p += part;
        while (part--)
            *datap++ = data.b[ofst++];
    }

    // copy the remainder of the data
    while (cnt)
    {
        if ((part = cnt) > 4)
            part = 4;
        data.d = *(uint32_t *)p;
        p += part;
        cnt -= part;
        ofst = 0;
        while (part--)
            *datap++ = data.b[ofst++];
    }
}
Don Kinzer
Beaverton, OR, USA

Who is online

Users browsing this forum: No registered users and 54 guests