Hey all, I have a very strange problem. It sounds to me that this is a known problem, but I cannot find any solutions to it.
Here is my setup:
Host: Win7 PC, plenty of RAM.
Target: STM32F303RE Cortex M4 @ 64 MHz, on Nucleo32 board with Integrated ST-LINK 2.1
Toolchain: uVision V5.16a
I've made a C/C++ project so I've set the __CPLUSPLUS and --cpp flag and control in uVision.
All builds well.
The problem is during runtime. The processor ends up in a hardfault handler after a few C++ object instantiantions. Two of them to be precise. Now, I'm sort of new to C++ details and inner workings, but it sounds like I have the same problem as this bloke: stackoverflow.com/.../segmentation-fault-caused-avoided-by-changing-source-file-order-in-makefile
Though there is no solution found. Here is the gist of my program which demonstrates the problem: This first section of code "appears" to run well, until the section block I've separated out for your attention.
#include "main.h" #include "stm32f30x.h" #include "stdint.h" #include "stdio.h" #include "string.h" #include "math.h" #include "usart.h" #include "can.h" #include "utils.h" #include "led.h" #include "i2c.h" #include "sabertooth.h" #include "FuzzyRule.h" #include "FuzzyComposition.h" #include "Fuzzy.h" #include "FuzzyRuleConsequent.h" #include "FuzzyOutput.h" #include "FuzzyInput.h" #include "FuzzyIO.h" #include "FuzzySet.h" #include "FuzzyRuleAntecedent.h" Fuzzy* fuzzy = new Fuzzy(); int main(void) { /************************************* * Input 1 ************************************/ // Two "crossing ramp" sets for rowWidth i.e. "tolerance" of the row FuzzyInput* rowWidth = new FuzzyInput(1); FuzzySet* lowTolerance = new FuzzySet(0.0f, 0.0f, 0.0f, 120.0f); rowWidth->addFuzzySet(lowTolerance); FuzzySet* highTolerance = new FuzzySet(0.0f, 120.0f, 120.0f, 120.0f); rowWidth->addFuzzySet(highTolerance); fuzzy->addFuzzyInput(rowWidth); USART1_puts("row width added as fuzzy input.."); /************************************* * Input 2 ************************************/ // Five Sets for "difference between R and L distances" FuzzyInput* distDiff = new FuzzyInput(2); FuzzySet* tooFarRight = new FuzzySet(-60.0f, -60.0f, -54.0f, -30.0f); distDiff->addFuzzySet(tooFarRight); FuzzySet* right = new FuzzySet(-54.0f, -30.0f, -30.0f, 0.0f); distDiff->addFuzzySet(right); FuzzySet* centered = new FuzzySet(-30.0f, 0.0f, 0.0f, 30.0f); distDiff->addFuzzySet(centered); FuzzySet* left = new FuzzySet(0.0f, 30.0f, 30.0f, 54.0f); distDiff->addFuzzySet(left); FuzzySet* tooFarLeft = new FuzzySet(30.0f, 54.0f, 60.0f, 60.0f); distDiff->addFuzzySet(tooFarLeft); fuzzy->addFuzzyInput(distDiff); USART1_puts("centering dist added as fuzzy input..."); /************************************* * Output 1 ************************************/ FuzzyOutput* motorSpeedDiff = new FuzzyOutput(1); // Seven sets for steering modes to take (close ones narrow far ones wider) FuzzySet* hardRight = new FuzzySet(-30.0f, -30.0f, -30.0f, -15.0f); motorSpeedDiff->addFuzzySet(hardRight); USART1_puts("\thardRight"); FuzzySet* lightRight = new FuzzySet(-15.0f, -5.0f, -5.0f, 0.0f); motorSpeedDiff->addFuzzySet(lightRight); USART1_puts("\tlightRight");
This is the last serial message I see in the terminal "lightRight" Hard fault occurs in next call to new FuzzySet()below this line.
FuzzySet* nomRight = new FuzzySet(-30.0f, -15.0f, -15.0f, -5.0f); motorSpeedDiff->addFuzzySet(nomRight); USART1_puts("\tnomRight"); FuzzySet* lightLeft = new FuzzySet(0.0f, 5.0f, 5.0f, 15.0f); motorSpeedDiff->addFuzzySet(lightLeft); USART1_puts("\tlightLeft"); FuzzySet* goStraight = new FuzzySet(-5.0f, 0.0f, 0.0f, 5.0f); motorSpeedDiff->addFuzzySet(goStraight); USART1_puts("\tgoStraight"); FuzzySet* nomLeft = new FuzzySet(5.0f, 15.0f, 15.0f, 30.0f); motorSpeedDiff->addFuzzySet(nomLeft); USART1_puts("\tnomLeft"); FuzzySet* hardLeft = new FuzzySet(15.0f, 30.0f, 30.0f, 30.0f); motorSpeedDiff->addFuzzySet(hardLeft); USART1_puts("\thardLeft"); fuzzy->addFuzzyOutput(motorSpeedDiff); USART1_puts("motor steering added as fuzzy output"); lotsMoreSetupCode(); while(1) { USART1_puts("Done!"); stop(1); // Blink LED forever } }
Here is the constructor found in FuzzySet.cpp: (Part of a fuzzy logic library I did not write) This SAME program runs well on an Arduino, but not this processor. Compiler difference?
FuzzySet::FuzzySet(){ } FuzzySet::FuzzySet(float a, float b, float c, float d){ this->a = a; this->b = b; this->c = c; this->d = d; this->pertinence = 0.0; }
It sounds like something to do with static variables being accessed by other staticly declared functions in other contexts.
But I have nothing declared static.
Any ideas on what is actually happening?
I've set up the nice hard fault handler which prints register info, but apparently the error occurs even before main(). So going to the assembly code when things get jumbled doesn't seem useful.
How to go about repairing this?
Out of heap?
"OS function invoked from constructor...?"
There is no OS, and as you can see, constructor doesn't ask much.
"Data corruption in C++ runtime library...?"
In the Fuzzy Logic Library? Would this be a KEIL issue? Or a configuration issue?
"Out of heap?"
How to check for this? Is there a way to increase the heap to do a quick test?
Fuzzy* fuzzy = new Fuzzy();
Why not either have fuzzy be a non-dynamic object, or wait until inside main() with allocating it?
How have you verified that your setup can call new?