cancel
Showing results for 
Search instead for 
Did you mean: 

Retargeting stdio to USART1

avinash_elec
Associate III
Posted on August 02, 2011 at 04:56

Hello,

I have USART1 configured properly and running. I am using the following code to write to the USART1

[code]

USART_SendData(USART1,'A');

/* Loop until the end of transmission */

while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

[/code]

The above code is working.

The problem is coming when I am trying to retarget the output of printf() to USART1

Following is the code to overide the fputc() function

[code]

/**

  * @brief  Retargets the C library printf function to the USART.

  * @param  None

  * @retval None

  */

int fputc(int ch, FILE *f)

{

      /* Place your implementation of fputc here */

      /* e.g. write a character to the USART */

      USART_SendData(USART1,(uint8_t)ch);

    /* Loop until the end of transmission */

      while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

      return ch;

}

[/code]

But when ever I am trying to use printf() the USART start sending NULL's repeatedly.

Tool Chain: RV Compiler on Keil RVMDK (demo)

Any help is appreciated!

12 REPLIES 12
cyril2399
Associate II
Posted on August 02, 2011 at 11:52

Hello,

have you tried with fprintf()?

trevor23
Associate III
Posted on August 02, 2011 at 13:27

I don't use Keil but I suspect it is putchar (or putc or similar) that you override not fputc.

Posted on August 02, 2011 at 20:45

Using this?

#pragma import(__use_no_semihosting_swi)

Probably want to implement _ttywrch() too.

The smarter approach to outputting would probably be to check that the TX buffer is empty first, rather than that the transmission is complete afterward, which is guaranteed to waste the maximal amount of time.

Try looking at the example retargeting code in the Keil directory

\Keil\ARM\Boards\Keil\MCBSTM32\Blinky (or one of the others)

For any of this to work, you must ensure the clocks and serial ports are initialized very early on, and at least before you use printf(), puts(), putchar(), etc.

If you change the system clocks, you'll have to revisit the baud rate settings afterward. Having the wrong rates can result in odd characters appearing on the terminal.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
avinash_elec
Associate III
Posted on August 03, 2011 at 12:59

Hello,

I am using the following startup file

startup_stm32f10x_hd.s

It calls the SystemInit() function (which is in system_stm32f10x.c file)

The above function sets up the PLL, System Clock, APB1 and APB2 clocks (all to maximum)

So my clock is correctly configured. Also I have set up USART1 before calling printf()

My USART1 is correctly configured as the following code to write to USART1 is working

while(1)

    {

        USART_SendData(USART1,'A');

        //Loop until the end of transmission

          while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

        Delay();

        USART_SendData(USART1,'B');

        //Loop until the end of transmission

          while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

        Delay();

    }

avinash_elec
Associate III
Posted on August 26, 2011 at 14:53

Hello,

I got the problem solved just by linking against the

http://www.keil.com/arm/microlib.asp

instead of the standard C library.

I just went to Project Options then in the Target Tab under ''Code Generation'' I selected ''Use MicroLIB''

guillaume2
Associate II
Posted on January 29, 2013 at 14:22

Hello guys, I have the same problem I tried all options described before but no way. My example works great with simple USART_SendData(USART1, 0x49); // Send 'I' but when I want to redirect printf it doesn't works. If somebody could help me, I 'll become crazy!

Thanks a lot

my example:

int putcharx(int ch)

 

{

 

  while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

 

  USART_SendData(USART1, (uint8_t)ch);

 

  return ch; 

 

end the big while:

 while (1) {

 

if (LEDOn) {

 

      LEDOn = 0;

 

      LED_On (num);                         /* Turn specified LED on          */

 

    }

 

 

 

    if (LEDOff) {

 

      LEDOff = 0;

 

      LED_Off (num);                        /* Turn specified LED off         */

 

 

 

      num += dir;                           /* Change LED number              */

 

      

 

      if (dir == 1 && num == max_num)  {

 

        dir = -1;                           /* Change direction to down       */

 

      ADC3_StartCnv();  

 

  val=ADC3_GetVal(); 

 

 //while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // Wait for Empty

 

 //USART_SendData(USART1, 0x49); // Send 'I'  

 

  printf(''TOTO'');

 

 

 

  test=test+0;  

 

 }

 

      else if (num == 0) {

 

        dir =  1;                           /* Change direction to up         */

 

      }

 

    }

 

  

 

    

 

  }

 

Posted on January 29, 2013 at 15:30

putcharX ?

// STM32 Keil printf USART1 (Tx PA.9, Rx PA.10) STM32F4 Discovery - sourcer32@gmail.com
// Use MicroLIB checked in options
#include <
stdio.h
>
#include <
stdlib.h
>
#include ''stm32f4_discovery.h''
/**************************************************************************************/
void RCC_Configuration(void)
{
/* --------------------------- System Clocks Configuration -----------------*/
/* USART1 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*-------------------------- GPIO Configuration ----------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Connect USART pins to AF */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); // USART1_TX
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); // USART1_RX
}
/**************************************************************************************/
void USART1_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
/* USARTx configuration ------------------------------------------------------*/
/* USARTx configured as follow:
- BaudRate = 9600 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
/**************************************************************************************/
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
USART1_Configuration();
while(1)
{
printf(''Hello World!

'');
}
while(1); // Don't want to exit
}
//******************************************************************************
// Hosting of stdio functionality through USART1
//******************************************************************************
#include <
rt_misc.h
>
#pragma import(__use_no_semihosting_swi)
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;
int fputc(int ch, FILE *f)
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, ch);
return(ch);
}
int fgetc(FILE *f)
{
char ch;
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
ch = USART_ReceiveData(USART1);
return((int)ch);
}
int ferror(FILE *f)
{
/* Your implementation of ferror */
return EOF;
}
void _ttywrch(int ch)
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, ch);
}
void _sys_exit(int return_code)
{
label: goto label; /* endless loop */
}
/**************************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d

'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
//******************************************************************************

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
guillaume2
Associate II
Posted on January 29, 2013 at 16:11

Thank you clive1, 

I am sure I have tested this solution before without success but putcharX was a mistake for sure now it works. I don't understand clearly why now but it works.

Thanks a lot again

akil
Associate
Posted on February 29, 2016 at 07:49

Hello,

Im trying to retarget the C library printf function to the USART using arm-none-eabi toolchain on Ubuntu. Where and how do I get <rt_misc.h> header?