MDK+硬件仿真器实现debugprintf()-stm32
MDK开启半主机模式-需要SWO线(换言之,需要使用JTAG接线),当目标板脱离仿真器(jlink/ulink)单独运行时,不能使用半主机模式
在部署生产应用程序或进行任何性能测量之前,始终记住禁用调试模式;
关于 microlib:使用微库的话,不会使用半主机模式.
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);
USART1->DR = (u8) ch;
return ch;
microlib 是缺省 C 库的备选库。 它用于必须在极少量内存环境下运行的深层嵌入式应用程序。 这些应用程序不在操作系统中运行。microlib 不会尝试成为符合标准的 ISO C 库。
microlib 进行了高度优化以使代码变得很小。 它的功能比缺省 C 库少,并且根本不具备某些 ISO C 特性。某些库函数的运行速度也比较慢,例如,memcpy()
log.csdn.net/andrewgithub/article/details/75270258
不使用微库:
方法2.仍然使用标准库,在主程序添加下面代码:
//#pragma import(__use_no_semihosting_swi) /*ARMv7 之前的 ARM 处理器使用 SVC 指令 (以前称为 SWI 指令)进行半主机调用*/
#pragma import(__use_no_semihosting) /*ARMv6-M 或 ARMv7-M (如 Cortex™-M1 或 Cortex-M3 处理器使用 BKPT 指令来实现半主机*/
struct __FILE
{
int handle;
};
FILE __stdout;
_sys_exit(int x)
{
x = x;
}
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);
USART1->DR = (u8) ch;
return ch;
}
int fgetc(FILE *f)
{
int ch;
#if 0
while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET) ;
ch = USART_ReceiveData(USART1);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
USART_SendData(USART1, (uint8_t) ch);
#endif
while( USART1->SR&(1<<5))== RESET) ;
ch=USART1->DR;
return ch;
}
关于半主机:
正常情况下启用 C 库中的函数,如 printf() 和 scanf(),需要目标系统上配备屏幕和键盘。
半主机是用于 ARM 目标的一种机制,可将来自应用程序代码的输入/输出请求传送至运行调试器的主机。而不是目标系统配置的键盘和屏幕。半主机模式必须使用仿真器调试
ARMv7 之前的 ARM 处理器使用 SVC 指令 (以前称为 SWI 指令)进行半主机调用。 但是,如果要为 ARMv6-M 或 ARMv7-M (如 Cortex™-M1 或 Cortex-M3 处理器)进行编译,请使用 BKPT 指令来实现半主机。简单的来说,半主机模式就是通过仿真器实现开发板在电脑上的输入和输出。和半主机模式功能相同的是ITM调试机制。
MDK+硬件仿真器实现debugprintf()-stm32
1MDK工程设置如下
2其中stm32debug.ini文件内容为
/******************************************************************************/
/* STM32DBG.INI: STM32 Debugger Initialization File */
/******************************************************************************/
// <<< Use Configuration Wizard in Context Menu >>> //
/******************************************************************************/
/* This file is part of the uVision/ARM development tools. */
/* Copyright (c) 2005-2007 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. */
/******************************************************************************/
FUNC void DebugSetup (void) {
// <h> Debug MCU Configuration
// <o1.0> DBG_SLEEP <i> Debug Sleep Mode
// <o1.1> DBG_STOP <i> Debug Stop Mode
// <o1.2> DBG_STANDBY <i> Debug Standby Mode
// <o1.5> TRACE_IOEN <i> Trace I/O Enable
// <o1.6..7> TRACE_MODE <i> Trace Mode
// <0=> Asynchronous
// <1=> Synchronous: TRACEDATA Size 1
// <2=> Synchronous: TRACEDATA Size 2
// <3=> Synchronous: TRACEDATA Size 4
// <o1.8> DBG_IWDG_STOP <i> Independant Watchdog Stopped when Core is halted
// <o1.9> DBG_WWDG_STOP <i> Window Watchdog Stopped when Core is halted
// <o1.10> DBG_TIM1_STOP <i> Timer 1 Stopped when Core is halted
// <o1.11> DBG_TIM2_STOP <i> Timer 2 Stopped when Core is halted
// <o1.12> DBG_TIM3_STOP <i> Timer 3 Stopped when Core is halted
// <o1.13> DBG_TIM4_STOP <i> Timer 4 Stopped when Core is halted
// <o1.14> DBG_CAN_STOP <i> CAN Stopped when Core is halted
// </h>
_WDWORD(0xE0042004, 0x00000027); // DBGMCU_CR
_WDWORD(0xE000ED08, 0x20000000); // Setup Vector Table Offset Register
}
DebugSetup(); // Debugger Setup
3项目工程加载retarget.c或者debugprint.c,其中retarget.c内容如下
#include <stdio.h>
#include "stm32f10x.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)
{
return ITM_SendChar(ch);
}
volatile int32_t ITM_RxBuffer;
int fgetc(FILE *f)
{
while (ITM_CheckChar() != 1) __NOP();
return (ITM_ReceiveChar());
}
int ferror(FILE *f)
{
/* Your implementation of ferror */
return EOF;
}
void _ttywrch(int c)
{
fputc(c, 0);
}
int __backspace()
{
return 0;
}
void _sys_exit(int return_code)
{
label:
goto label; /* endless loop */
}
debugprint.c内容如下:
#include <stdio.h>
#define ITM_Port8(n) (*((volatile unsigned char *)(0xE0000000+4*n)))
#define ITM_Port16(n) (*((volatile unsigned short*)(0xE0000000+4*n)))
#define ITM_Port32(n) (*((volatile unsigned long *)(0xE0000000+4*n)))
#define DEMCR (*((volatile unsigned long *)(0xE000EDFC)))
#define TRCENA 0x01000000
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;
int fputc(int ch, FILE *f)
{
if (DEMCR & TRCENA)
{
while (ITM_Port32(0) == 0);
ITM_Port8(0) = ch;
}
return(ch);
}
4包含头文件#include <stdio.h>,并调用printf
5在debug中打开输出仿真:View-serial-debug(printf)
Cortex-M,包括 ARMv6-M 和 ARMv7-M ,使用 BKPT 0xAB 指令作为半主机接口。如果发现程序死机,而且导致死机的指令是 BKPT 0xAB ,那么应当考虑程序中是否使用了半主机接口,半主机接口只能在调试状态下使用,正常运行情况下使用会引起异常,然后跳转到异常处理函数处,很多程序的异常处理程序是个死循环,看起来就像死机了。
http://blog.csdn.net/zoomdy/article/details/79117163