cancel
Showing results for 
Search instead for 
Did you mean: 

printf issue

Lutz_66
Associate II

Hello,

I'm encountering an issue where the printf function is providing an incorrect output for float or double values. The simplified code snippet causing this problem is as follows:

float f = 0.33;

printf("d:%4.2f;\r\n", f);

Upon analyzing the output using a logic analyzer, I initially observe the two bytes \xF0 \x87 followed by "0.33;\r\n", indicating that the "d:" prefix is not matching as expected.

I'm using a STM32L432KCU microcontroller with STM32CubeIDE version 1.14.0. The option to utilize floats with printf is enabled in the settings.

Would appreciate any insights or suggestions to resolve this issue.

Kind Regards
Lutz

 

7 REPLIES 7

This is a topic that's been addressed multiple times. Seem to recall you need to be pulling the right library too.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Pavel A.
Evangelist III

The default Newlib-nano library bundled with CubeIDE ARM toolchain does not support printing floats and some other types. Please refer to CubeIDE user guide.

yes right, it has been reported several times, also that the stack memory is not the right size etc.
But what I notice is that it doesn't crash the first time, but displays the first two characters incorrectly the first time
On the second call the crash occurs
Now I have tested further and the lines

for (int n=0;n<samplenum;n++){

   int len=sprintf(ch_buffer, "d:%7.5lf;%7.5lf;%d\r\n",tx_sin[n],tx_cos[n],tx_ref[n]);
   if(len!=0){HAL_UART_Transmit(&huart2, (uint8_t *)ch_buffer, len, 100);}

}

the arrays are up to 800 elements in size. Regardless of whether the call runs from 0 to 99 or from 0 to 799, the first call for this loop works, i got the right data at the UART and i have no crash.
The second call of the loop also crashes.

All this does not fit into the picture I have read so far. I have understood that it does not work at all. What would be the right library, if I knew that I would have used it and not asked here.

But nevertheless it has to be said that the reports on errors with printf and float are 5 years old and older. As I understand it, they all report a crash, not that it sometimes works.
I hadn't noticed from the reports that it sometimes works, very often and then again not on the second call. That's why I asked.


 

Pavel A.
Evangelist III

The printf in newlib library needs working malloc and also is involved with multi-threading support (even if you don't use it). One of recent toolchains was broken IIRC. Use the latest toolchain of CubeIDE 1.14.1, or older ones (v. 9, 10). Or, find alternative printf, or make your own float formatting function with ecvt(), fcvt().

Hallo, thank you very much for your advice
I recently ran an update, I have version 1.14.1 and the GNU tools are now "GNU Tooles for STM32 (12.3rel1)", which was previously 11

Are these the latest ones or should I install something else

it should then work or do I have to do something else

because I have the problem that the first call of the function "sendCalASCII" works and sends the data to the PC as intended, no matter if smplenum is 100 or 800
The second call I have the crash with the function "sprintf"

if anyone is surprised that
HAL_ADC_Start_DMA(&hadc1, (uint16_t*)buffer, 4);
is located after lines 12, 13, this is supposed to be the case because work is then carried out in parallel
But if anyone has a better idea then let me know

 

 

 

int sendCalASCII(uint16_t samplenum){
	double sin[7]={0};
	double cos[7]={0};
    int ref=0;

    HAL_ADC_Stop_DMA(&hadc1);
    for(int i=0;i<4;i++){buffer[i]=1980;}
    for (int n=0;n<samplenum;n++){
		//HAL_ADC_Start_DMA(&hadc1, (uint16_t*)buffer, 4);
		//HAL_Delay(1);
		ref=(TIM1->CNT);
		sin[1]=0.001*((buffer[0]+buffer[3])/2-1980);
		cos[1]=0.001*((buffer[1]+buffer[2])/2-1980);

		HAL_ADC_Start_DMA(&hadc1, (uint16_t*)buffer, 4);

		sin[0]=coeff[10]; //zuweisen der Konstanten
		cos[0]=coeff[21]; //zuweisen der Konstanten

		for (int i=2;i<=6;i++){
			sin[i]=sin[i-1]*sin[1];  // da es für jeden messwert aufgerufen wird sollte es so am schnellsten sein
			cos[i]=cos[i-1]*cos[1];
		}

		sin[0] += sin[1]*coeff[0] + cos[1]*coeff[1];
		sin[0] += sin[3]*coeff[2] + cos[3]*coeff[3];
		sin[0] += sin[5]*coeff[4] + cos[5]*coeff[5];
		sin[0] += sin[6]*coeff[6] + cos[6]*coeff[7];
		sin[0] += sin[3]*cos[3]*coeff[8];
		sin[0] += sin[5]*cos[5]*coeff[9];

		cos[0] += sin[1]*coeff[11] + cos[1]*coeff[12];
		cos[0] += sin[3]*coeff[13] + cos[3]*coeff[14];
		cos[0] += sin[5]*coeff[15] + cos[5]*coeff[16];
		cos[0] += sin[6]*coeff[17] + cos[6]*coeff[18];
		cos[0] += sin[3]*cos[3]*coeff[19];
		cos[0] += sin[5]*cos[5]*coeff[20];

		tx_sin[n]=sin[0];//*100000;
		tx_cos[n]=cos[0];//*100000;
		tx_ref[n]=ref*10000;
    }
	printf("CAL\r\n");
	printf("%d\r\n",samplenum);
	for (int n=0;n<samplenum;n++){
		//Format d: sin;cos;ref\n
        //int len=sprintf(ch_buffer,"d:%d;%d;%d\r\n",tx_sin[n],tx_cos[n],tx_ref[n]);
		int len=sprintf(ch_buffer,"d:%7.5lf;%7.5lf;%d\r\n",tx_sin[n],tx_cos[n],tx_ref[n]);
		if(len!=0){HAL_UART_Transmit(&huart2, (uint8_t *)ch_buffer, len, 100);}
	}
	printf("END\r\n");
	return 0;
}

 

 

 

 

 

 

Pavel A.
Evangelist III

I have not tested toolchain 12.3 yes but it is supposed to be good (no complaints heard recently). Your code looks quite involved and has DMA. Can you make a small focused test without ADC and DMA, just to verify printf and sprintf?

 

 

yes good idea, I hadn't tried it yet. I understand the background when two things process large amounts of memory that something can go wrong.

I have commented out DMA and tested it, unfortunately the same behavior, in the code line 48 int len=sprintf... the program jumps to the error handler

void HardFault_Handler(void)
{
  /* USER CODE BEGIN HardFault_IRQn 0 */

  /* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
    /* USER CODE END W1_HardFault_IRQn 0 */
  }
}