STM32CubeIDE V1.7.0, modulo arithmetic => Compiler Error?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-10-01 5:41 AM
Since 25 years I use functions or macros like
#define usTimeRead() ((int16_t) (SysTick->VAL >> 1))
#define usTimePlus(TP, US) ((int16_t) TP - ((int16_t) US * (int16_t) 85))
#define usTimePast(TP) (((int16_t) TP - usTimeRead()) > (int16_t) 0)
to create timeouts or to do periodical jobs on 16bit MCUs.
Porting them to STM32G4, the following code should result in a 100us square wave generated at pin B6.
int main(void) {
sysConfigMCU();
/* Loop */
int16_t tp = usTimeRead();
for(;;) {
GPIOB->BSRR = ((uint16_t)0x0040);
tp = usTimePlus(tp, 100);
for ( ; !usTimePast(tp); );
GPIOB->BRR = ((uint16_t)0x0040);
tp = usTimePlus(tp, 100);
for ( ; !usTimePast(tp); );
}
}
This doesn't work - I have to change the macro usTimePast(TP) assigning the difference to temporary variable to get the program running correctly.
#define usTimePast(TP) ((tmp = (int16_t) TP - usTimeRead()) > (int16_t) 0)
I've simulated this behaviour with TDM-GCC with the same result - for values like
usTimeRead() == -32703 and tp == 32735 the compare in usTimePast(TP) will produce differnt results depending on weather the difference of the left side of compare will be assinged to a temporary variable or not!
Using Microsoft Visual Studio will prodece in both cases (with and without aasigning the difference to a temporary variable) the behaviour i know from 16bit MCUs and their compilers.
- Labels:
-
STM32CubeIDE
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-10-01 6:46 AM
What is the type of tmp?
> Using Microsoft Visual Studio will prodece in both cases
Really?
#include <stdint.h>
#include <stdio.h>
int main(void)
{
printf("%d\n", (int16_t)32767 - (int16_t)(-32767));
int16_t tmp;
printf("%d\n", tmp = (int16_t)32767 - (int16_t)(-32767) );
}
yields different results (65534 rsp. -2).
For me, using usigned data types is much easier because a clean modulus computation is involved.
hth
KnarfB
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-10-01 7:03 AM
SysTick is a 24 bit unsigned down counter, and it's not even full-span in most use cases.
Typically people use maximal, free-running, 16 or 32-bit up counters. And don't precompute the target, but rather compute the delta time and see if that exceeds the elapsed time..
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-10-01 8:04 AM
tmp's type is also int16_t.
Tests with Microsoft Visual Studio has been done by a friend - he reported, the output signal will not toggle in the data file like in my data file,
when cnt24b reaches -32703.
# usTick cnt24b nextTp output
: : : :
32699 -32700 -32701 0
32700 -32701 -32701 0
32701 -32702 -32701 0 <===
32702 -32703 32735 10000
32703 -32704 32635 0
32704 -32705 32535 10000
32705 -32706 32435 0
32706 -32707 32335 10000
32707 -32708 32235 0
32708 -32709 32135 10000
32709 -32710 32035 0
32710 -32711 31935 10000
I will check using unsigned arithmetic next week (the compare has to be a signed compare).
Inspired by yout test I will also check, if casting the difference of two int16_t again to int16_t will also solve the problem -
yout test implies, that the difference of two int16_t isn' t treaded as an int16_t (at least, when an underflow or overflow
has been ocured).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-10-01 8:16 AM
Compiler error? Or unexpected result? I don’t see any error messages listed.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-10-01 8:23 AM
Ok - casting the difference again to int16_t is enough to get the same behaviour like assigning the difference to an int16_t temporary variable!
Wth STM32 compiler as well as with the TDM-GCC compiler.
It seems, the difference of two int16_t does not have to be an int16_t?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-10-01 8:32 AM
Right, the difference is an int, this is integer promotion in C. By casting or assigning it to an int16_t, the result gets truncated to int16_t.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-10-01 9:01 AM
Consider the 32-bit DWT->CYCCNT for a coherent/complete number space when you shift and truncate to 16-bit
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-10-01 1:04 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-10-01 3:20 PM
This math will only be correct on underflows, when SysTick period is set to a multiple of 2^17 clock cycles, which is almost never the case.
int16_t tp = usTimeRead();
tp = usTimePlus(tp, 100);
for ( ; !usTimePast(tp); );
The loop is effectively a simple while loop. And the whole logic can be implemented as a single (probably static inline) function to not have to repeat the same set of code lines over and over again.
