Hello everyone,I just started to study ARM this week and i was trying to retarget printf to make it work with UART. After many tries, it just started to work magically as i put the stdin and stdout lines(#16 &17) out of the main function scope. What's the reason behind it? Is it something Keil related? Is it due to the some rules of C, memory issues or stdio.h? By the way, even if i put those lines in the main function scope, it's working in debugger mode. But it stops at command BKPK 0xAB line but i'm not at that level to understand if that means something.
Thank you for your time!
#include "stm32f4xx.h" // Device header #include "core_cm4.h" #include <stdio.h> //system clock is 8Mhz //APB1 clock tree-> 8*2 Mhz=16Mhz for usart3 void USART3_Init(void); void USART3_Write(int cc); char USART3_Read(void); void delayMs(volatile int delay); void blinkBlueInit(void); void blinkBlue(int blinkNumber); FILE __stdin; FILE __stdout; int main(void) { blinkBlueInit(); USART3_Init(); char tempr; int number=0; printf("hello. please enter a number; "); while(1){ scanf("%d",&number); blinkBlue(number+48); } } void USART3_Init(void){ RCC->APB1ENR |= 0x40000; //USART3 APB1 clock enabled RCC->AHB1ENR|=0x8; //GPIOD clock enabled (also included in blinkBlue() ) GPIOD->AFR[1] = 0x7; //PD8=USART3_TX ---> AF7 SET GPIOD->MODER |= 0x20000;//Pd8 usart3 Tx set as alternate function GPIOD->AFR[1] |= 0x70;//PD9=USART3_RX ---> AF7 SET GPIOD->MODER |= 0x80000;//Pd9 usart3 Rx set as alternate function USART3->BRR=1666 ;//? USART3->CR1 = 0x0008; //TE enabled USART3->CR1 |= 0x0004; //RE enabled USART3->CR1 |= 0x2000; //UE=1 //M=0 default 1 Start bit, 8 Data bits, n Stop bit //CR2->STOP=0 1 STOP BIT } void USART3_Write(int cc){ while ( !(USART3->SR & 0x0080)){} USART3->DR= cc & 0xFF; if (cc == '\r') { while ( !(USART3->SR & 0x0080)){} USART3->DR= '\n' & 0xFF; } } char USART3_Read(void){ while ( !(USART3->SR & 0x0020)){} return USART3->DR; } void delayMs(volatile int delay){ volatile int i; for(;delay>0;delay--){ for(i=0;i<1597;i++){} } } void blinkBlueInit(void){ RCC->AHB1ENR|=0x8; //GPIOD GPIOD->MODER|=0x40000000; //MODER PD15 set as output } void blinkBlue(int blinkNumber){ blinkNumber -=48; for(;blinkNumber>0;blinkNumber--){ GPIOD->BSRR=0x00008000; delayMs(250); GPIOD->BSRR=0x80000000; delayMs(250); } } int fputc(int c, FILE *stream) { USART3_Write(c); return c; } int fgetc(FILE *stream) { char c = USART3_Read(); USART3_Write(c); //Terminal echo return c; }
BKPT is an assembly command for a breakpoint.
See the BKPT 0xAB section of this article for suggestions
http://www.keil.com/support/docs/3614.htm
I suggest going to Project -> Options For Target -> Target tab, and checking 'use microlib" see:
www.keil.com/.../uv4_dg_adstarg.htm
Read more about semihosting here:
http://www.keil.com/support/man/docs/armcc/armcc_pge1358787046598.htm
www.keil.com/.../microlib.asp