Skip to main content
ULehm.1
Associate III
October 1, 2021
Question

STM32CubeIDE V1.7.0, modulo arithmetic => Compiler Error?

  • October 1, 2021
  • 4 replies
  • 4603 views

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.

This topic has been closed for replies.

4 replies

KnarfB
Super User
October 1, 2021

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

ULehm.1
ULehm.1Author
Associate III
October 1, 2021

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).

ULehm.1
ULehm.1Author
Associate III
October 1, 2021

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?

Tesla DeLorean
Guru
October 1, 2021

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..

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Tesla DeLorean
Guru
October 1, 2021

Consider the 32-bit DWT->CYCCNT for a coherent/complete number space when you shift and truncate to 16-bit

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
TDK
Super User
October 1, 2021

Compiler error? Or unexpected result? I don’t see any error messages listed.

"If you feel a post has answered your question, please click ""Accept as Solution""."
ULehm.1
ULehm.1Author
Associate III
October 4, 2021

I I thought it was a compiler error/bug, but it was a result of my lack of knowledge about promotion in C (see above)

Piranha
Principal III
October 1, 2021

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.