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调试机制。

有关ITM调试机制可以参考这里http://www.douban.com/note/248637026/

 

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


posted on 2014-11-05 13:12  杰瑞鼠  阅读(2108)  评论(0编辑  收藏  举报