analogdevicesinc / TMC-API

TRINAMIC's IC API

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Assumed datatype in CAST_Sn_TO_S32 in Macros.h

PMTaylor opened this issue · comments

Hi there,
using Arduino, and the datatype the compiler assumes is too short (int?) for the operation if the shift is bigger than 16.

Seems to work as intended as
"#define CAST_Sn_TO_S32(value, n) ((value) | (((value) & (1L<<((n)-1)))? ~((0x1L<<(n))-1) : 0 ))"
but i'm far from a good C programmer.

Hello,

yes, the Arduino's int datatype has only 16 bits.

Am i understanding you correctly, that the CAST_Sn_TO_S32 macro is showing the bigger-than-16 shift warning?

Yes a warning is show. More importantly, the shifts fail to produce the correct result with the macro as written. Explicitly defining the type of the "1" and "0x1" constants as "uint32", or "unsigned long" here seems appropriate.

So something like this should work then:
#define CAST_Sn_TO_S32(value, n) ((value) | (((value) & ((uint32_t)1<<((n)-1)))? ~(((uint32_t)1<<(n))-1) : 0 ))

Once we've tested everything on our end we will integrate that fix. Thanks for the report 👍

This issue looks like its similar to the compiler warning I'm getting today:

Compiling src/TMC5130/TMC5130.c.o
src/TMC5130/TMC5130.c: In function 'tmc5130_writeDatagram':
src/TMC5130/TMC5130.c:22:22: warning: left shift count >= width of type [-Wshift-count-overflow]
  int32_t value = (x1 << 24) | (x2 << 16) | (x3 << 8) | x4;
                      ^
src/TMC5130/TMC5130.c:22:35: warning: left shift count >= width of type [-Wshift-count-overflow]
  int32_t value = (x1 << 24) | (x2 << 16) | (x3 << 8) | x4;

Would you agree?

I've done this to fix it:

// Writes (x1 << 24) | (x2 << 16) | (x3 << 8) | x4 to the given address
void tmc5130_writeDatagram(TMC5130TypeDef *tmc5130, uint8_t address, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4)
{
	uint8_t data[5] = { address | TMC5130_WRITE_BIT, x1, x2, x3, x4 };
	tmc5130_readWriteArray(tmc5130->config->channel, &data[0], 5);

	int32_t value = ((uint32_t)x1 << 24) | ((uint32_t)x2 << 16) | (x3 << 8) | x4;

	// Write to the shadow register and mark the register dirty
	address = TMC_ADDRESS(address);
	tmc5130->config->shadowRegister[address] = value;
	tmc5130->registerAccess[address] |= TMC_ACCESS_DIRTY;
}

and this:

int32_t tmc5130_readInt(TMC5130TypeDef *tmc5130, uint8_t address)
{
	address = TMC_ADDRESS(address);

	// register not readable -> shadow register copy
	if(!TMC_IS_READABLE(tmc5130->registerAccess[address]))
		return tmc5130->config->shadowRegister[address];

	uint8_t data[5] = { 0, 0, 0, 0, 0 };

	data[0] = address;
	tmc5130_readWriteArray(tmc5130->config->channel, &data[0], 5);

	data[0] = address;
	tmc5130_readWriteArray(tmc5130->config->channel, &data[0], 5);

	return ((uint32_t)data[1] << 24) | ((uint32_t)data[2] << 16) | (data[3] << 8) | data[4];
}

Fixed in commit b17de70