MPLABX math.h error . (1510) non-reentrant function "___fleq" appears in multiple call graphs and has been duplicated by the compiler - pic

Im working on a project about active power and reactive power measurement kit with using PIC16F877A MCU. In the code, I use pow, sqrt and cos functions which are included in math.h library. when I execute the code I get these errors.
CLEAN SUCCESSFUL (total time: 104ms)
make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make[1]: Entering directory 'C:/Users/BATUHAN/Desktop/bitirme/bitirme.X'
make -f nbproject/Makefile-default.mk dist/default/production/bitirme.X.production.hex
make[2]: Entering directory 'C:/Users/BATUHAN/Desktop/bitirme/bitirme.X'
"D:\Program Files\Microchip\xc8\v2.32\bin\xc8-cc.exe" -mcpu=16F877A -c -mdfp="D:/Program Files/Microchip/MPLABX/v5.50/packs/Microchip/PIC16Fxxx_DFP/1.2.33/xc8" -fno-short-double -fno-short-float -O0 -fasmfile -maddrqual=ignore -xassembler-with-cpp -mwarn=-3 -Wa,-a -DXPRJ_default=default -msummary=-psect,-class,+mem,-hex,-file -ginhx32 -Wl,--data-init -mno-keep-startup -mno-osccal -mno-resetbits -mno-save-resetbits -mno-download -mno-stackcall -std=c99 -gdwarf-3 -mstack=compiled:auto:auto -o build/default/production/main.p1 main.c
::: advisory: (2049) C99 compliant libraries are currently not available for baseline or mid-range devices, or for enhanced mid-range devices using a reentrant stack; using C90 libraries
main.c:72:20: warning: implicit conversion loses floating-point precision: 'double' to 'float' [-Wconversion]
pf=cos(pf_timer);
~^~~~~~~~~~~~~
main.c:77:20: warning: implicit conversion loses floating-point precision: 'double' to 'float' [-Wconversion]
pf=cos(360 - pf_timer); //guc faktoru degeri
~^~~~~~~~~~~~~~~~~~~
main.c:87:20: warning: implicit conversion loses floating-point precision: 'double' to 'float' [-Wconversion]
pf=cos(pf_timer);
~^~~~~~~~~~~~~
main.c:92:20: warning: implicit conversion loses floating-point precision: 'double' to 'float' [-Wconversion]
pf=cos(360 - pf_timer); //guc faktoru degeri
~^~~~~~~~~~~~~~~~~~~
main.c:132:25: warning: implicit conversion loses floating-point precision: 'double' to 'float' [-Wconversion]
CRMS = CRMS + pow(((ADC_Value*5/1024 - 2.5)/0.185),2); //akimin karesi alinarak toplaniyor
~ ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.c:139:25: warning: implicit conversion loses floating-point precision: 'double' to 'float' [-Wconversion]
VRMS = VRMS + pow((((ADC_Value*5/1024)-2.5)*325),2); //gerilimin karesi alinarak toplaniyor
~ ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.c:147:24: warning: implicit conversion loses floating-point precision: 'double' to 'float' [-Wconversion]
CRMS = sqrt(CRMS); //ve kare koku alinarak rms akim degeri hesaplaniyor
~ ^~~~~~~~~~
main.c:149:24: warning: implicit conversion loses floating-point precision: 'double' to 'float' [-Wconversion]
VRMS = sqrt(VRMS); //ve kare koku alinarak rms voltaj degeri hesaplaniyor
~ ^~~~~~~~~~
8 warnings generated.
"D:\Program Files\Microchip\xc8\v2.32\bin\xc8-cc.exe" -mcpu=16F877A -Wl,-Map=dist/default/production/bitirme.X.production.map -DXPRJ_default=default -Wl,--defsym=__MPLAB_BUILD=1 -mdfp="D:/Program Files/Microchip/MPLABX/v5.50/packs/Microchip/PIC16Fxxx_DFP/1.2.33/xc8" -fno-short-double -fno-short-float -O0 -fasmfile -maddrqual=ignore -xassembler-with-cpp -mwarn=-3 -Wa,-a -msummary=-psect,-class,+mem,-hex,-file -ginhx32 -Wl,--data-init -mno-keep-startup -mno-osccal -mno-resetbits -mno-save-resetbits -mno-download -mno-stackcall -std=c99 -gdwarf-3 -mstack=compiled:auto:auto -Wl,--memorysummary,dist/default/production/memoryfile.xml -o dist/default/production/bitirme.X.production.elf build/default/production/main.p1
::: advisory: (2049) C99 compliant libraries are currently not available for baseline or mid-range devices, or for enhanced mid-range devices using a reentrant stack; using C90 libraries
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\fleq.c:4:: advisory: (1510) non-reentrant function "___fleq" appears in multiple call graphs and has been duplicated by the compiler
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\flge.c:4:: advisory: (1510) non-reentrant function "___flge" appears in multiple call graphs and has been duplicated by the compiler
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\flneg.c:15:: advisory: (1510) non-reentrant function "___flneg" appears in multiple call graphs and has been duplicated by the compiler
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\fltol.c:43:: advisory: (1510) non-reentrant function "___fltol" appears in multiple call graphs and has been duplicated by the compiler
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\sprcadd.c:10:: advisory: (1510) non-reentrant function "___fladd" appears in multiple call graphs and has been duplicated by the compiler
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\sprcadd.c:242:: advisory: (1510) non-reentrant function "___flsub" appears in multiple call graphs and has been duplicated by the compiler
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\sprcdiv.c:8:: advisory: (1510) non-reentrant function "___fldiv" appears in multiple call graphs and has been duplicated by the compiler
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\sprcmul.c:8:: advisory: (1510) non-reentrant function "___flmul" appears in multiple call graphs and has been duplicated by the compiler
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\Umul8_16.c:4:: advisory: (1510) non-reentrant function "__Umul8_16" appears in multiple call graphs and has been duplicated by the compiler
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\xxtofl.c:10:: advisory: (1510) non-reentrant function "___xxtofl" appears in multiple call graphs and has been duplicated by the compiler
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\evalpoly.c:4:: advisory: (1510) non-reentrant function "_eval_poly" appears in multiple call graphs and has been duplicated by the compiler
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\floor.c:13:: advisory: (1510) non-reentrant function "_floor" appears in multiple call graphs and has been duplicated by the compiler
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\frexp.c:254:: advisory: (1510) non-reentrant function "_frexp" appears in multiple call graphs and has been duplicated by the compiler
D:\Program Files\Microchip\xc8\v2.32\pic\sources\c90\common\sprcdiv.c:185:: error: (1360) no space for auto/param _main$903
(908) exit status = 1
nbproject/Makefile-default.mk:138: recipe for target 'dist/default/production/bitirme.X.production.hex' failed
make[2]: Leaving directory 'C:/Users/BATUHAN/Desktop/bitirme/bitirme.X'
nbproject/Makefile-default.mk:91: recipe for target '.build-conf' failed
make[1]: Leaving directory 'C:/Users/BATUHAN/Desktop/bitirme/bitirme.X'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed
make[2]: *** [dist/default/production/bitirme.X.production.hex] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
BUİLD FAILED (exit value 2, total time: 5s)
I couldn't solve these errors
THE CODE I WROTE
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = ON // Data EEPROM Memory Code Protection bit (Data EEPROM code-protected)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = ON // Flash Program Memory Code Protection bit (All program memory code-protected)
#define _XTAL_FREQ 20000000
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define ADC_Current RA0
#define ADC_Volt RA1
#define VZCD RB0
#define CZCD RB4
float pf_timer=0;
float pf=0;
float ADC_Value = 0;
float CRMS, VRMS, Current, Volt = 0;
int Rms_Count=0;
float Q=0, P=0;
_Bool timer_bit=0;
_Bool counter_bit=0;
_Bool pf_bit=1;
_Bool LEAD_LAG=0;
void __interrupt() KESME(void)
{
//TMR1 KESMESI
if(TMR1IF)
{
TMR1IF=0;
TMR1=15535;
timer_bit = timer_bit^1;
}
//INT (RB0) KESMESI
if(INTF)
{
INTF=0;
pf_bit=1;
pf_timer = TMR1;
}
//PORTB KESMESI
if(RBIF==1 && RB4==1 && pf_bit==1)
{
RBIF=0;
pf_bit=0;
if(TMR1 >= pf_timer)
{
pf_timer = TMR1 - pf_timer;
pf_timer = pf_timer*360/50000;
if(pf_timer <= 90)
{
pf=cos(pf_timer);
LEAD_LAG=0;
}
else if(pf_timer >= 270)
{
pf=cos(360 - pf_timer);
LEAD_LAG=1;
}
}
else if(TMR1 < pf_timer)
{
pf_timer =65535 - pf_timer + TMR1;
pf_timer = pf_timer*360/50000;
if(pf_timer <= 90)
{
pf=cos(pf_timer);
LEAD_LAG=0;
}
else if(pf_timer >= 270)
{
pf=cos(360 - pf_timer);
LEAD_LAG=1;
}
}
}
}
void main(void)
{
TRISA = 0XFF;
PORTA = 0X00;
TRISB = 0XFF;
PORTB = 0X00;
//ADC KONFIGURASYON BITLERI
ADCON0=0b01000001;
ADCON1=0b10000000;
//TIMER-1 KONFIGURASYON BITLERI
TMR1=15535;
INTCON=0b11011000;
INTEDG=1;
T1CON=0b00011110;
TMR1IE=1;
TMR1IF=0;
TMR1ON=1;
while(1)
{
//AKIM VE GERILIM OLCUMU
if(timer_bit)
{
counter_bit=0;
Rms_Count += 1;
ADCON0bits.CHS0=0;
GO_DONE = 1;
while(GO_DONE);
ADC_Value = (ADRESH*256 + ADRESL);
CRMS = CRMS + pow(((ADC_Value*5/1024 - 2.5)/0.185),2);
ADCON0bits.CHS0=1;
GO_DONE = 1;
while(GO_DONE);
ADC_Value = (ADRESH*256 + ADRESL);
VRMS = VRMS + pow((((ADC_Value*5/1024)-2.5)*325),2);
}
else if(!timer_bit)
{
if(!counter_bit)
{
CRMS = CRMS / Rms_Count;
CRMS = sqrt(CRMS);
VRMS = VRMS / Rms_Count;
VRMS = sqrt(VRMS);
Volt = VRMS;
Current = CRMS;
}
counter_bit=1;
CRMS=0;
Rms_Count=0;
VRMS=0;
}
}
return;
}
I tried switch to C90 standarts and nothing changed. How can I solve this problem.

Well, it looks like there is not much and clear information on what libraries the XC8 compiler supports specifically for the mid-range devices. The only brief information I could find in Microchip Developer Help site it is mentioned that:
Ensure that you are also using the C99 libraries as shown in the following figure, but note that currently, C99 compliant libraries are only available for projects targeting PIC18 devices and targeting Enhanced Mid-range devices that are using the compiled (non-reentrant) stack model.
However as the advisory states:
C99 compliant libraries are currently not available for baseline or mid-range devices, or for enhanced mid-range devices using a reentrant stack
Considering this advise, it sholdn't be used neither baseline nor mid-range nor enhanced mid-range devices for the projects that use C99 compliant libraries as in your case. Baseline, mid-range and enhanced mid-range devices are any of those whose name starts with PIC10, PIC12* and PIC16 prefixes respectively.
So the road to take for your situation is to pick an advanced model of 8-bit PIC controllers, any model that starts with PIC18 prefix in its name should work. However I would recommend you relatively newer products. For example, instead of buying a PIC18F4550 which is relatively old, you can buy a PIC18F45K50 which is newer than it and may have some enhancements.
Now let me answer your other questions you asked in the comments:
Which PIC18F do you recommend to do enough for my project. In the circuitry there are 4-5 I/O pins and I will add a 2x16 LCD.
Well for this kind of requirement a model like PIC18F14K50 should do the job for your project since it has 20 pins. Or you can go with a 25K20 or a 25K22 both of which have 28 pins which would suffice for your requirement.
if I put the source codes of cos() and sqrt() functions and remove the #include <math.h>, will I still have the same architectural problem.
I am not sure for that since the problem here is the usage of reentrant or software stack which is a type of dynamically allocated memory for functions. Knowing this, I can say that if those functions are compiled with software stack model by XC8 then it will not work for PIC16F877A at all. As a matter of fact I see a conflict between the advisory of compiler and the quoted explanation from Microchip developer site regarding the usage of reentrant stack model. The advise of the compiler is kind of unclear on whether the reentrant stack model can be used with the enhanced mid-range devices, while in the developer site it stated kind of contrary. This encourages us to see the Compiled Stack and the Software stack definitions in the XC8 compiler manual.
Compiled Stack (Reentrant)
A compiled stack is one or more areas of memory that are designated for automatic storage duration objects. Objects allocated space in the compiled stack are assigned a static address which can be accessed via a compiler-allocated symbol. This is the most efficient way of accessing stack-based objects, since it does not use a stack pointer.
Software Stack (Non-reentrant)
A software stack is a dynamic allocation of memory that is used for automatic storage duration objects and which is indirectly accessed via a stack pointer. Although access of objects on a software stack can be slower, functions which use a software stack are reentrant. This form of stack is available only for Enhanced Mid-range and PIC18 devices.
Which clearly states that reentrant functions are only available for enhanced mid-range and PIC18 devices.
Finally if you can avoid using the same functions both in the main and in the interrupt, perhaps you can go with your PIC16F877A and compiler compiles your code with compiled stack model. Because the compiler duplicate the functions when they are used in both main and interrupt and this triggers the compilation of reentrant function stack model.

TL;DR Basically you're out of memory. Compiled code doesn't fit into your uCs memory.
The main problem is that the cos() function you're using the interrupt is duplicated by the compiler because it appears both in main code and the interrupt, and your uC supports only compiled stack model which doesn't support function reentrancy.
Unfortunately it doesn't end here. It appears that cos() calls other library functions, like a chain reaction. These are all floating point functions, which have high memory footprints. And now these heavy floating point functions (which are many) are also duplicated, and they don't fit into the memory of your uC. This can be either RAM or Flash memory shortage, or both.
Try to remove cos() (or any other floating point function) from your ISR by changing your program logic.
Warnings are not directly related with your compile error. You may go to project properties menu in MPLAB. Here you will see Link in C Library option under XC8 Global Options -> XC8 Linker -> Runtime. Select C90 instead of C99. You may also try using floating point version of the library functions, like using cosf() instead of cos(), but these may not be available on C90. Or you can manually cast to float to get rid of warnings.

Related

How to force alignment of uint8_t to be 1 byte in avr-gcc (GCC) 5.4.0

I use a file_enum.h header in my projects, which uses the linker to enumerate my source files. I use this to identify assertion failures on platforms which may only have numeric output (ie. a product using 7-seg displays).
My file_enum.h contains:
static volatile uint8_t __attribute__((section(".file_enum"))) file_number;
#define FILE_ENUM ((uint8_t)(intptr_t)(&file_number))
This works fine, and I can see which file = which number in my .map output.
Recently after upgrading to Buster I now have avr-gcc (GCC) 5.4.0, which for some reason uses 2 byte alignment for uint8_t (despite being an 8-bit platform).
This means I can now only enumerate 128 files, also my FILE_ENUM equates to the address shown in the map file +1 due to endianess.
I have tried, without success:
static volatile uint8_t __attribute__((section(".file_enum"),aligned(1))) file_number;
Is there a way to force 1-byte alignment for uint8_t, or, is there a better way to enumerate source files?

Flags mapping of tasking compiler with GCC compiler

I am working on GCC compiler. I have previously worked on tasking compiler where most of the flags are different.
Can someone help me to map below mentioned flags of tasking with GCC.
-t (section information is listed on list file)
--emit-locals = -equ (emit equ symbol to object file)
-wa-ogs (short and long option names to assembler)
--tasking-sfr (compiler includes regcpu.sfr and assembler includes regcpu.def)
--language = -gcc,-volatile,+strings (enable number of GCC extensions, don't optimization across volatile access, disable const check for string lateral)
--switch = auto (which code must be generated for switch statement)
--align = 0 (compiler aligns variables and function to minimum alignment)
--default-near-size = 8 (compiler allocates objects smaller than or equal to threshold memory in __near memory)
--default-a0-size = 0 (compiler will never use __a0 memory)
--default-a1-size = 0 (compiler will never use __a1 memory)
--tradeoff =4 (whether used optimization should optimize for more speed/smaller code size)
--source (merge c source code with assembly code in output file)

ld: 32-bit RIP relative reference out of range in simple gcc program

related to "ld: 32-bit RIP relative reference out of range" on Mac OSX but not solved and in a more complex context. the relevant computer(s) have >32GB of RAM.
static const int K=1024;
static const int M=K*K;
static const int G=K*M;
const int MC = G;
void donada(float *rvec, const int MC) { rvec[MC-1]= 1.0; return; }
float notused[1][MC]; // 4GB, ramp up with first index
float used[MC]; // 4GB
int main() {
donada( used, MC );
donada( notused[1], MC );
}
and gcc -Wall -o test test.cc. compiling this program not on osx yields
ld: 32-bit RIP relative reference out of range (4294967395 max is
+/-2GB): from _main (0x100000F92) to _used (0x200001000) in '_main' from /var/folders/yl/8gp3pgbn1l562ywg_q86rk6800\ 00z9/T/test-b3bebf.o
for architecture x86_64
on linux, there is a similar error
test.cc:(.text+0x18): relocation truncated to fit: R_X86_64_32 against symbol `used' defined in .bss section in /tmp/ccqcNh2C.o
I first thought compiler flag -Os would fix this, but it does not. It would be appropriate for gcc or clang to provide a more suggestive error message.
the relevant computer(s) have >32GB of RAM.
That's actually not very relevant. The issue is that 64-bit GCC defaults to -mcmodel=small, and you are trying to access data that is 4GiB away from its base symbol, which is not comatible with the small model.
From documentation:
-mcmodel=small
Generate code for the small code model: the program and its symbols
must be linked in the lower 2 GB of the address space. Pointers are 64 bits.
Programs can be statically or dynamically linked. This is the default code model.
-mcmodel=medium
Generate code for the medium model: The program is linked in the lower 2 GB
of the address space. Small symbols are also placed there.
Symbols with sizes larger than -mlarge-data-threshold are put into large data
or bss sections and can be located above 2GB.
Programs can be statically or dynamically linked.
-mcmodel=large
Generate code for the large model: This model makes no assumptions about addresses
and sizes of sections.
To correctly link your program, you need to use -mcmodel=large.
However note that this is not well tested (almost nobody does that), and that all code you (statically) link into your program will need to be built that way.
It is probably much better to dynamically allocate your arrays instead.
I first thought compiler flag -Os would fix this
It can't: -Os minimizes code size. Your program is that you are forcing the compiler to allocate very large contiguous data array. There is nothing the compiler could optimize for size there.

How can I enable UnAligned Access for ARM NEON in LLVM compiler?

What is the flag to enable unaligned memory access for ARM NEON in LLVM compiler.
I was testing my ARM NEON intrinsic program in Xcode. I am accessing data from unaligned memory:
char TempMemory[32] = {0};
char * pTempMem = TempMemory;
pTempMem += 7;
int32x2_t i32x2_value = vld1_lane_s32((int32_t const *) pTempMem, i32x2_offset, 0);
Equivalent assembly for the intrinsic should be VLD1.32 {d0[0]}, [pTempMem], but the compiler align it to next multiple of 32 and access data. Because of that, my program is not working fine.
So, How can I enable unaligned access in LLVM compiler?
This isn't actually a NEON problem, it's a C problem, and the issue is:
vld1_lane_s32((int32_t const *) pTempMem , i32x2_offset, 0);
Casting a pointer is a message to the compiler saying "hey, I know this looks bad, but trust me, I really know what I'm doing". Converting a pointer to type A to a pointer to type B, if the pointer does not have suitable alignment for type B, gives undefined behaviour. Therefore the compiler is free to assume that the argument to vld_1_lane_s32 is always 32-bit aligned because there's no valid way it couldn't be (and you've promised you know what you're doing), so it emits the instruction with the alignment hint.
Now, you could fiddle around with options in an attempt to get a different kind of undefined behaviour that matches what you want, but that's just bodging around the problem rather than fixing it. That the underlying NEON instruction set can support unaligned accesses doesn't affect the C language's definition of and restrictions around data alignment.
I'm not familiar with how clever LLVM is, so I'm not sure if simply omitting the pointer cast would work (technically, C permits converting char * to any other type of data pointer, so it should be able to sort out the alignment itself). Otherwise, the solution is to use an appropriate vld*_u8 operation to load the data into the vector via the correct type, then cast that with vreinterpret_s32_u8 once it's in the register.

How to reference segment beginning and size from C code

I am porting a program for an ARM chip from a IAR compiler to gcc.
In the original code, IAR specific operators such as __segment_begin and __segment_size are used to obtain the beginning and size respectively of certain memory segments.
Is there any way to do the same thing with GCC? I've searched the GCC manual but was unable to find anything relevant.
More details:
The memory segments in question have to be in fixed locations so that the program can interface correctly with certain peripherals on the chip. The original code uses the __segment_begin operator to get the address of this memory and the __segment_size to ensure that it doesn't overflow this memory.
I can achieve the same functionality by adding variables to indicate the start and end of these memory segments but if GCC had similar operators that would help minimise the amount of compiler dependent code I end up having to write and maintain.
What about the linker's flag --section-start? Which I read is supported here.
An example on how to use it can be found on the AVR Freaks Forum:
const char __attribute__((section (".honk"))) ProjString[16] = "MY PROJECT V1.1";
You will then have to add to the linker's options: -Wl,--section-start=.honk=address.
Modern versions of GCC will declare two variables for each segment, namely __start_MY_SEGMENT and __stop_MY_SEGMENT. To use these variables, you need to declare them as externs with the desired type. Following that, you and then use the '&' operator to get the address of the start and end of that segment.
extern uint8_t __start_MY_SEGMENT;
extern uint8_t __stop_MY_SEGMENT;
#define MY_SEGMENT_LEN (&__stop_MY_SEGMENT - &__start_MY_SEGMENT)

Resources