Hi. I'm a newbie coding for an STM32F4 Discovery board. I'm working with some modified sample code and when I try to debug it, I'm getting stuck at "BKPT 0XAB", and I can't progress any further.
Can someone help me understand what causes this and how I can fix it?
You're probably using printf or putchar without providing any code to "retarget" that functionality to your board/processor. Adapt as required
C:\Keil474\ARM\Boards\ST\STM3240G-EVAL\Blinky\Retarget.c
/*---------------------------------------------------------------------------- * Name: Retarget.c * Purpose: 'Retarget' layer for target-dependent low level functions * Note(s): *---------------------------------------------------------------------------- * This file is part of the uVision/ARM development tools. * 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. * * This software is supplied "AS IS" without warranties of any kind. * * Copyright (c) 2011 Keil - An ARM Company. All rights reserved. *----------------------------------------------------------------------------*/ #include <stdio.h> #include <rt_misc.h> #include "Serial.h" #pragma import(__use_no_semihosting_swi) struct __FILE { int handle; /* Add whatever you need here */ }; FILE __stdout; FILE __stdin; int fputc(int c, FILE *f) { return (SER_PutChar(c)); } int fgetc(FILE *f) { return (SER_GetChar()); } int ferror(FILE *f) { /* Your implementation of ferror */ return EOF; } void _ttywrch(int c) { SER_PutChar(c); } void _sys_exit(int return_code) { label: goto label; /* endless loop */ }
C:\Keil474\ARM\Boards\ST\STM3240G-EVAL\Blinky\Serial.c
/*---------------------------------------------------------------------------- * Name: Serial.c * Purpose: Low level serial routines * Note(s): *---------------------------------------------------------------------------- * This file is part of the uVision/ARM development tools. * 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. * * This software is supplied "AS IS" without warranties of any kind. * * Copyright (c) 2004-2011 Keil - An ARM Company. All rights reserved. *----------------------------------------------------------------------------*/ #include <stm32f4xx.h> /* STM32F4xx Definitions */ #include "Serial.h" #ifdef __DBG_ITM volatile int32_t ITM_RxBuffer; #endif /*----------------------------------------------------------------------------- * SER_Init: Initialize Serial Interface *----------------------------------------------------------------------------*/ void SER_Init (void) { #ifdef __DBG_ITM ITM_RxBuffer = ITM_RXBUFFER_EMPTY; #else RCC->APB1ENR |= (1UL << 19); /* Enable USART4 clock */ RCC->APB2ENR |= (1UL << 0); /* Enable AFIO clock */ RCC->AHB1ENR |= (1UL << 2); /* Enable GPIOC clock */ GPIOC->MODER &= 0xFF0FFFFF; GPIOC->MODER |= 0x00A00000; GPIOC->AFR[1] |= 0x00008800; /* PC10 UART4_Tx, PC11 UART4_Rx (AF8) */ /* Configure UART4: 115200 baud @ 42MHz, 8 bits, 1 stop bit, no parity */ UART4->BRR = (22 << 4) | 12; UART4->CR3 = 0x0000; UART4->CR2 = 0x0000; UART4->CR1 = 0x200C; #endif } /*----------------------------------------------------------------------------- * SER_PutChar: Write a character to Serial Port *----------------------------------------------------------------------------*/ int32_t SER_PutChar (int32_t ch) { #ifdef __DBG_ITM int i; ITM_SendChar (ch & 0xFF); for (i = 10000; i; i--); #else while (!(UART4->SR & 0x0080)); UART4->DR = (ch & 0xFF); #endif return (ch); } /*----------------------------------------------------------------------------- * SER_GetChar: Read a character from Serial Port *----------------------------------------------------------------------------*/ int32_t SER_GetChar (void) { #ifdef __DBG_ITM if (ITM_CheckChar()) return ITM_ReceiveChar(); #else if (UART4->SR & 0x0020) return (UART4->DR); #endif return (-1); } /*----------------------------------------------------------------------------- * end of file *----------------------------------------------------------------------------*/
The code does indeed use printf().
However, as far as I can tell, it's set up correctly.
The code has this snippet:
int fputc(int c, FILE *stream) { return(ITM_SendChar(c)); }
...which is all I thought was needed (code-wise) - according to:
armcortexm.blogs.upv.es/.../
Is there something else I need to do?
#pragma import(__use_no_semihosting_swi)
Look at what's in the retarget file as functions to replace the libraries versions.
This project doesn't use any retarget files. The snippet I showed earlier is in main.c.
As for the Include line, if I add that, then upon build, I get the following errors:
.\Objects\Template.axf: Error: L6915E: Library reports error: __use_no_semihosting_swi was requested, but _sys_exit was referenced .\Objects\Template.axf: Error: L6915E: Library reports error: __use_no_semihosting_swi was requested, but _sys_open was referenced .\Objects\Template.axf: Error: L6915E: Library reports error: __use_no_semihosting_swi was requested, but _ttywrch was referenced
Okay, I found the retarget.c file and by adding that to the project, I get rid of the errors I listed above. However, now I get different errors:
.\Objects\Template.axf: Error: L6200E: Symbol __stdout multiply defined (by main.o and retarget.o). .\Objects\Template.axf: Error: L6200E: Symbol __stdin multiply defined (by main.o and retarget.o). .\Objects\Template.axf: Error: L6200E: Symbol fputc multiply defined (by main.o and retarget.o). .\Objects\Template.axf: Error: L6200E: Symbol fgetc multiply defined (by main.o and retarget.o). .\Objects\Template.axf: Error: L6200E: Symbol ferror multiply defined (by main.o and retarget.o). .\Objects\Template.axf: Error: L6200E: Symbol _ttywrch multiply defined (by main.o and retarget.o). .\Objects\Template.axf: Error: L6200E: Symbol _sys_exit multiply defined (by main.o and retarget.o).
What is the correct way to address this?
To only have ONE instance of those functions?
Remove the ones from main.c
That's just it - there wasn't a set of duplicates there, other than the fputc() snippet I showed you earlier.
So I took out the Include for retarget.c, and just copied over the snippets for _ttywrch and _sys_exit.
That got rid of the other errors and gave me:
Source\Main.c(395): warning: #223-D: function "sendchar" declared implicitly .\Objects\Template.axf: Error: L6218E: Undefined symbol sendchar (referred from main.o).
So I commented out the sendchar() line out of _ttywrch, hoping that it wasn't necessary.
That leaves me with the sole error of:
.\Objects\Template.axf: Error: L6915E: Library reports error: __use_no_semihosting_swi was requested, but _sys_open was referenced
_sys_open doesn't appear in main.c, so I'm not sure where this is coming from.
p.s. Thank you for staying with me and trying to help. From the perspective of someone new to this, I'm sure you can understand how frustrating this issue is for me.
Ok, but just be clear you shouldn't be #include'ing .C files, this will charge the ownership to the file doing the #include, you simply add the .C file to the project.
If you don't want to add files to the project, you'd paste something like this directly into the primary source file.
//****************************************************************************** // Hosting of stdio functionality through ITM/SWV //****************************************************************************** #include <stdio.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) { ITM_SendChar(ch); return(ch); } int fgetc(FILE *f) { char ch = 0; return((int)ch); } int ferror(FILE *f) { /* Your implementation of ferror */ return EOF; } void _ttywrch(int ch) { ITM_SendChar(ch); } void _sys_exit(int return_code) { label: goto label; /* endless loop */ } //******************************************************************************
When using SWV via the trace set up you must set the frequency of the processor correctly for the data to show up in the Serial Debug (printf) tab.