Skip to main content
Explorer II
March 12, 2024
Question

printf issue

  • March 12, 2024
  • 4 replies
  • 1884 views

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

 

    This topic has been closed for replies.

    4 replies

    Graduate II
    March 12, 2024

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

    Lutz_66Author
    Explorer II
    March 12, 2024

    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.


     

    Super User
    March 12, 2024

    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.

    Super User
    March 13, 2024

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

    Lutz_66Author
    Explorer II
    March 14, 2024

    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;
    }

     

     

     

     

     

     

    Super User
    March 14, 2024

    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?

     

     

    Lutz_66Author
    Explorer II
    March 14, 2024

    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 */
     }
    }