2018-03-08 07:29 AM
Hi all,
I'm developing an application (PROJECT) for a STM8S208RB (128k flash) t
hat was using around 100kB of flash and I
have added recently a new library (LIBRARY) that has increased memory usage up yo 120kBof flash
.I had an issue because of this event that has been solved. More info in here:
https://community.st.com/message/188751
In the new library I have a function that reads a frequency in Hz (
IE: 208064
) andthen print it in MHz (IE: 208.064 Hz):
void disp_freq_mhz(void)
{ uint32_t frequency; uint16_t mhz_num, khz_num;frequency = frequency_hz; // frequency_hz
is a global variable (uint32_t)
mhz_num = (uint16_t)(frequency/1000);
khz_num = (uint16_t)(frequency%1000);printf (' %03d.%03d MHz', mhz_num, khz_num);
}
The problem is sometimes
the division and/or modulus operations returns an erroneous value.
I have been debugging this error with STVD in the following way:
mhz_num = (uint16_t)(frequency/1000);
khz_num = (uint16_t)(frequency%1000);if(khz_num != 64 || mhz
_num != 208
) return;This is one reading of the variables involved in the function during one stop (the erroneous values are not always the same):
frequency_hz = 208064
frequency = 208064
mhz_num = 208
khz_num = 872 // sometimes it is 640, but most of the time the erroneous value is 872
Result of printf -> ' 208.872 MHz '
Has anybody any idea of why is failing this arithmetic operations?
Thanks all of you in advance,
Guillermo,
#uint16_t #uint32_t #basic-arithmeticSolved! Go to Solution.
2018-03-12 03:27 AM
Guillermo Corrales wrote:
I've tried to disable and re-enable interrupts during the division and rest operations and it seems to fix the issue ..
Best regards,
Guillermo.
make sure all your interrupt routines have the @svlreg keyword
@svlreg @interrupt myIntRoutine() ..
and see if that fixes the problem.
2018-03-08 07:54 AM
>>
Has anybody any idea of why is failing this arithmetic operations?
I'd hazard that it is doing 16-bit arithmetic.
Use 1000L instead of 1000, or explicitly cast things to force the math to 32-bit BEFORE converting in to 16-bit.
Inspect the code output by the compiler to understand the nuances of what has been created.
2018-03-08 08:55 AM
very difficult to imagine that the compiler would get something this simple wrong.
with that said, if you suspect that the compiler isn't doing its job, there are ways around it.
for example, I often simply use my own routine to convert numbers to strings:
//convert tmp to string
vRAM[7=0; //null terminated string
vRAM[6]=(tmp % 10) + '0'; tmp /= 10;
vRAM[5]=(tmp % 10) + '0'; tmp /= 10;
vRAM[4]=(tmp % 10) + '0'; tmp /= 10;
vRAM[3]='.'; //vRAM[3]=(tmp % 10) + '0'; tmp /= 10;
vRAM[2]=(tmp % 10) + '0'; tmp /= 10;
vRAM[1]=(tmp % 10) + '0'; tmp /= 10;
vRAM[0]=(tmp % 10) + '0'; tmp /= 10;
or if you want to go down your path.
f_khz = frequency / 1000; //khz unit
f_hz = frequency - f_khz * 1000; //hz unit
or other ways of getting around.
2018-03-08 09:30 AM
Hi Clive,
Thank you so much for your fast response.
I think it's not an 16-bit arithmetic issue:
- I tried to cast 1000 to uint32_t before the division / modulus with the same result:
mhz_num = (uint16_t)(frequency/1000); ==
mhz_num = (uint16_t)(frequency/((uint32_t)1000)); in my case
khz_num = (uint16_t)(frequency%1000); ==
khz_num
= (uint16_t)(frequency%((uint32_t)1000)) in my case
- I have tried to use 1000L instead of 1000, with identical result.
Do you have another idea?
Thanks you in advance,
Guillermo,
2018-03-08 09:46 AM
Look at the generated code, then you'll understand what the CPU is being told to do.
You're trying to determine if it is trying to use the quotient/remainder from a single computation, fold constants, etc. Try with optimization on/off, and with the problem code contained to a small and reproducible example.
If there is a bug with the compiler's code generator or libraries you'd want to submit that to the compiler vendor.
2018-03-09 12:08 AM
Hello,
I have built and simulated your example and I get the expected values
If your application fails ''sometimes'' (meaning that doing exactly the same sequence of commands you get sometimes one result, sometimes another), the problem is probably due to some runtime issue, like stack overflow or interrupts corrupting something.
Regards,
Luca
2018-03-09 01:22 PM
I can confirm luca's experience. similarly, I ran OP's code over randomly generated values. and over 10 million runs, all the results are as expected. no error of any kind.
as if that needs to be confirmed,
2018-03-09 01:44 PM
The OP's issue is with the COSMIC STM8 compiler
I'd be suspicious of the code generation, and stack/heap/static corruption.
In the first case some static inspection of the code would provide some insight.
If the code looks to be inherently correct it could be separated out and run independently of the surrounding code/application.
I'd printf('%ld %ld\n', frequency, frequency_hz); in the error case to confirm the input conditions, especially for the potential of the global variable being modified.
Generally chip and compiler bugs would be harder to manifest than this.
2018-03-09 02:03 PM
still, it is difficult to imagine that cosmic would get something this simple wrong - that compiler is widely used and if they got this wrong, it would be widely reported.
on the flip side, compiler bugs are very easy to find, especially for newbies,
2018-03-09 03:07 PM
well, the same code running on a stm8s003 / cosmic has shown no sign of failure after 2+ hours.