-
RTT LOG功能实现
首先要将rtt文件加入工程,如下
新建一个sdk_config.h加入工程,并加入以下内容
#ifndef SDK_CONFIG_H
#define SDK_CONFIG_H
#define STM_MODULE_ENABLED(module) \
((defined(module ## _ENABLED) && (module ## _ENABLED)) ? 1 : 0)
// <<< Use Configuration Wizard in Context Menu >>>\n
//##############################################################################################################################################
// 以下是nRF_Segger_RTT仿真器打印配置
//##############################################################################################################################################
// <h> nRF_Segger_RTT仿真器打印配置菜单
//==========================================================
// <h> segger_rtt - SEGGER RTT
//==========================================================
// <o> SEGGER_RTT_CONFIG_BUFFER_SIZE_UP - Size of upstream buffer.
// <i> Note that either @ref NRF_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE
// <i> or this value is actually used. It depends on which one is bigger.
#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_UP
#define SEGGER_RTT_CONFIG_BUFFER_SIZE_UP 512
#endif
// <o> SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS - Maximum number of upstream buffers.
#ifndef SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS
#define SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS 2
#endif
// <o> SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN - Size of downstream buffer.
#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN
#define SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN 16
#endif
// <o> SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS - Maximum number of downstream buffers.
#ifndef SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS
#define SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS 2
#endif
// <o> SEGGER_RTT_CONFIG_DEFAULT_MODE - RTT behavior if the buffer is full.
// <i> The following modes are supported:
// <i> - SKIP - Do not block, output nothing.
// <i> - TRIM - Do not block, output as much as fits.
// <i> - BLOCK - Wait until there is space in the buffer.
// <0=> SKIP
// <1=> TRIM
// <2=> BLOCK_IF_FIFO_FULL
#ifndef SEGGER_RTT_CONFIG_DEFAULT_MODE
#define SEGGER_RTT_CONFIG_DEFAULT_MODE 0
#endif
// </h>
//==========================================================
// </h>
//==========================================================
// <h> DEBUG配置
// <q> DEBUG使能
#ifndef DEBUG_ENABLED
#define DEBUG_ENABLED 1
#endif
// <q> ASSERT参数检查使能
#ifndef USE_FULL_ASSERT
#define USE_FULL_ASSERT 1
#endif
// </h>
// <<< end of configuration section >>>
#endif //SDK_CONFIG_H
新建一个stm_log.h加入工程,并加入以下内容
#include "sdk_config.h"
#include "SEGGER_RTT.h"
#include "stdio.h"
#ifndef STM_LOG_H__
#define STM_LOG_H__
#ifdef __cplusplus
extern "C" {
#endif
#if STM_MODULE_ENABLED(DEBUG)
/**
* @brief RTT打印宏
* @note
* - 最多不能超过128个字符否则出错
*/
#define NRF_LOG_INFO(fmt,args...) \
do \
{ \
sprintf(_SEGGER_RTT.aUp->pBuffer,fmt,##args); \
SEGGER_RTT_WriteString(0, _SEGGER_RTT.aUp->pBuffer); \
SEGGER_RTT_WriteString(0,"\r\n"); \
}while(0)
#define NRF_LOG_DEBUG(fmt,args...) \
do \
{ \
sprintf(_SEGGER_RTT.aUp->pBuffer,fmt,##args); \
SEGGER_RTT_WriteString(0, _SEGGER_RTT.aUp->pBuffer); \
}while(0)
#define RTT_INIT() \
SEGGER_RTT_Init()
#else
#define NRF_LOG_INFO(fmt,args...) ((void)0)
#define NRF_LOG_DEBUG(fmt,args...) ((void)0)
#define RTT_INIT() ((void)0)
#endif
#ifdef __cplusplus
}
#endif
#endif
在主函数中调用RTT_INIT()宏进行初时化RTT打印,调用NRF_LOG_INFO宏就可以打印信息
/**
* @brief 主函数,程序的入口
*
*
* @param None
* @retval int:不用理会,对于嵌入式系统,永远都不会返回
*/
int main(void)
{
//------------初时化RTT打印--------------------------
RTT_INIT();
NRF_LOG_INFO("program is running!");
//--------独立看门狗配置-----------------------------------
IWDG_Configuration(); /*!<配置并启动独立看门狗功能*/
for(;;)
{
IWDG_ReloadCounter(); /*!< 喂狗*/
}
}
-
ASSERT功能实现
将sdk_config.h中的USE_FULL_ASSERT宏值设置成1,DEBUG_ENABLED也设成1
// <h> DEBUG配置
// <q> DEBUG使能
#ifndef DEBUG_ENABLED
#define DEBUG_ENABLED 1
#endif
// <q> ASSERT参数检查使能
#ifndef USE_FULL_ASSERT
#define USE_FULL_ASSERT 1
#endif
// </h>
在assert_failed函数中加入打印
#if USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
NRF_LOG_INFO("file path is %s,line=%d\n",file,line);
while(1);
}
#endif
在stm32f10x_conf.h中修改成以下内容
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function which reports
* the name of the source file and the source line number of the call
* that failed. If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#define ASSERT(expr) assert_param(expr)
#define APP_ERROR_CHECK(expr) \
do \
{ \
if(expr) \
{ \
NRF_LOG_INFO("error code %d",expr); \
assert_param(0); \
} \
}while(0)
#else
#define assert_param(expr) ((void)0)
#define APP_ERROR_CHECK(expr) ((void)0)
#define ASSERT(expr) ((void)0)
#endif /* USE_FULL_ASSERT */
在主函数中可以调用ASSERT宏测试一下
在主函数中可以调用APP_ERROR_CHECK宏测试一下
-
HardFault_Handler打印信息实现
新建一个error_handler.c文件,加入以下内容
#include "error_handler.h"
#include "stm_log.h"
#if DEBUG_ENABLED
/* Private typedef -----------------------------------------------------------*/
enum { r0, r1, r2, r3, r12, lr, pc, psr};
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
extern __IO uint16_t ADC_InjectedConvertedValueTab[32];
uint32_t Index = 0;
/* Private function prototypes -----------------------------------------------*/
void Hard_Fault_Handler(uint32_t stack[]);
/* Private functions ---------------------------------------------------------*/
static void printUsageErrorMsg(uint32_t CFSRValue)
{
NRF_LOG_INFO("Usage fault: ");
CFSRValue >>= 16; // right shift to lsb
if((CFSRValue & (1<<9)) != 0) {
NRF_LOG_INFO("Divide by zero ");
}
if((CFSRValue & (1<<8)) != 0) {
NRF_LOG_INFO("Unaligned access ");
}
}
static void printBusFaultErrorMsg(uint32_t CFSRValue)
{
NRF_LOG_INFO("Bus fault: ");
CFSRValue = ((CFSRValue & 0x0000FF00) >> 8); // mask and right shift to lsb
}
static void printMemoryManagementErrorMsg(uint32_t CFSRValue)
{
NRF_LOG_INFO("Memory Management fault: ");
CFSRValue &= 0x000000FF; // mask just mem faults
}
static void stackDump(uint32_t stack[])
{
NRF_LOG_INFO("R0 = 0x%08x", stack[r0]);
NRF_LOG_INFO("R1 = 0x%08x", stack[r1]);
NRF_LOG_INFO("R2 = 0x%08x", stack[r2]);
NRF_LOG_INFO("R3 = 0x%08x", stack[r3]);
NRF_LOG_INFO("R12 = 0x%08x", stack[r12]);
NRF_LOG_INFO("LR = 0x%08x", stack[lr]);
NRF_LOG_INFO("PC = 0x%08x", stack[pc]);
NRF_LOG_INFO("PSR = 0x%08x", stack[psr]);
}
void Hard_Fault_Handler(uint32_t stack[])
{
//if((CoreDebug->DHCSR & 0x01) != 0) {
NRF_LOG_INFO("In Hard Fault Handler");
NRF_LOG_INFO("SCB->HFSR = 0x%08x", SCB->HFSR);
if ((SCB->HFSR & (1 << 30)) != 0) {
NRF_LOG_INFO("Forced Hard Fault");
NRF_LOG_INFO("SCB->CFSR = 0x%08x", SCB->CFSR );
if((SCB->CFSR & 0xFFFF0000) != 0) {
printUsageErrorMsg(SCB->CFSR);
}
if((SCB->CFSR & 0xFF00) != 0) {
printBusFaultErrorMsg(SCB->CFSR);
}
if((SCB->CFSR & 0xFF) != 0) {
printMemoryManagementErrorMsg(SCB->CFSR);
}
}
stackDump(stack);
__ASM volatile("BKPT #01");
//}
}
__ASM void HardFault_Handler_a(void)
{
IMPORT Hard_Fault_Handler
TST lr, #4
ITE EQ
MRSEQ r0, MSP
MRSNE r0, PSP
B Hard_Fault_Handler
}
#endif
在stm32f10x_it.c中的HardFault_Handler中断函数加入以下内容
/**
* @brief This function handles Hard Fault exception.
* @param None
* @retval None
*/
void HardFault_Handler(void)
{
/* Go to infinite loop when Hard Fault exception occurs */
#if DEBUG_ENABLED
HardFault_Handler_a();
#else
NVIC_SystemReset();
#endif
}
在主函数中测试一下,现使用一个空指针操作来演示出错打印
DEMO下载地址:
https://download.csdn.net/download/mygod2008ok/11959924