cancel
Showing results for 
Search instead for 
Did you mean: 

keil uVision4 problem with C++ code

angeletti
Associate II
Posted on October 14, 2013 at 23:32

Hi guys,

I'm trying to use printf function with C++ code. The code is working but only first 11 characters are successfully written. any ideas? that's the code:


/* Includes ------------------------------------------------------------------*/

#include ''stm32f0xx.h''

#include <stdio.h>

#include <stddef.h>

#include <string.h>


/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/

/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

volatile
uint32_t msTicks;


/* Function prototypes -----------------------------------------------*/

void
SysTick_Handler(
void
);

void
Delay (uint32_t dlyTicks);


void
USART1_Init(
void
);

void
USART1_IRQHandler(
void
);

/* Functions ---------------------------------------------------------*/


/*

SysTick handler

*/

void
SysTick_Handler(
void
) {

msTicks++;

}


/*

Function to provide delay (in mSec)

*/

void
Delay (uint32_t delayTicks) { 

uint32_t currentTicks;


currentTicks = msTicks;

while
((msTicks - currentTicks) < delayTicks);

}


/*

USART1 Tx PA.9, Rx PA.10 gpio clock interrupt configuration

*/

void
USART1_Init(
void
) {

USART_InitTypeDef USART_InitStructure;

GPIO_InitTypeDef GPIO_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;


// configuring clock sources for USART1

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);


GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);

GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);


/* Configure USART1 pins: Rx and Tx ----------------------------*/

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

GPIO_Init(GPIOA, &GPIO_InitStructure);


/* Enable USART1 IRQ */

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPriority = 3;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);


USART_InitStructure.USART_BaudRate = 115200;

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


// enabling USART1

USART_Cmd(USART1,ENABLE);


// enable incoming data interrupt

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

}


/*

USART1 interrupt handler

*/

void
USART1_IRQHandler(
void
) {

volatile
uint8_t data = 0x00;


if
(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {

data = USART_ReceiveData(USART1);


printf
(
''Received character: %c\n''
, data);

}

}

/**

* @brief Main program.

* @param None

* @retval None

*/

int
main(
void
) {

SystemCoreClockUpdate(); 
/* Get Core Clock Frequency */

if
(SysTick_Config(SystemCoreClock / 1000)) { 
/* SysTick 1 msec interrupts */

while
(1); 
/* Capture error */

}


USART1_Init();


printf
(
''System clock: %u MHz\n''
, SystemCoreClock / 1000000);


/*

ENDLESS LOOP BEGIN

*/

while
(1) {

printf
(
''I'm alive...\n''
);

Delay(1000);

}


return
(0);

}


#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\r\n'', file, line) */


/* Infinite loop */

while
(1)

{

}

}

#endif

and this is the modified retarget.c


/******************************************************************************/

/* RETARGET.C: 'Retarget' layer for target-dependent low level functions */

/******************************************************************************/

/* This file is part of the uVision/ARM development tools. */

/* Copyright (c) 2005 Keil Software. All rights reserved. */

/* This software may only be used under the terms of a valid, current, */

/* end user licence from KEIL for a compatible version of KEIL software */

/* development tools. Nothing else gives you the right to use this software. */

/******************************************************************************/


#include ''stm32f0xx.h''

#include <stdio.h>

#include <time.h>

#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) {

/* Transmit the character using USART1 */

USART_SendData(USART1, (uint8_t) ch);


/* Wait until transmit finishes */

while
(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) {}


return
ch;

}


int
fgetc
(
FILE
*f) {

uint8_t data = 0x00;


if
(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

data = USART_ReceiveData(USART1);


return
data;

}



int
ferror
(
FILE
*f) {

/* Your implementation of ferror */

return
EOF;

}



void
_ttywrch(
int
ch) {

/* Transmit the character using USART1 */

USART_SendData(USART1, (uint8_t) ch);


/* Wait until transmit finishes */

while
(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) {}

}



void
_sys_exit(
int
return_code) {

while
(1); 
/* endless loop */

}

#stm32f0-stm32f0discovery-usart
6 REPLIES 6
Posted on October 15, 2013 at 00:10

C++, looks an awful lot like plain C. If the file is foo.cpp consider if it is mangling function names. Check the .MAP file.

Are you sure your SysTick handler is being called, what if you don't call the delay function?

Perhaps you might also want to front test for TXE rather than back test it? And doing a printf() under interrupt is also perhaps rather ill advised.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
angeletti
Associate II
Posted on October 15, 2013 at 00:19

I'm aware of printf behaviour inside an interrupt, that's only for debugging purposes. I've tried to remove Delay but nothing changed, the strange thing is that the same code works perfectly in c (if a move fputc from retarget to main file).

I'm not a pro with c++, what I should check in MAP file?

Posted on October 15, 2013 at 00:26

That it hasn't mangled your handler/function names? And consequently had no linkage in the vector table.

So if you stop the code in the debugger where exactly is it stuck?

I'm not a C++ user at all.

http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
angeletti
Associate II
Posted on October 18, 2013 at 14:46

the problem seems to be in SysTick_handler, like if the code is unable to handle interrupts. Any one knows if in C++ interrupts must be managed in a different way?

Posted on October 18, 2013 at 15:32

Any one knows if in C++ interrupts must be managed in a different way?

No, but they must be named correctly. Which is often why they'd be in a C file like stm32f4xx_it.c

It's why you have directives like 'extern ''C''' or cdecl/__cdecl

It's not a problem unique to Keil, or ARM

http://www.keil.com/support/docs/3223.htm

http://www.keil.com/support/man/docs/armlib/armlib_CJABFDDJ.htm

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
angeletti
Associate II
Posted on October 18, 2013 at 15:40

Clive1, thank you very much! I've previously modified every external call with the extern ''C'' statement but not the SysTick_handler... Now everything works!