前言
本博客记录了使用STM32F105RB时在FreeRTOS系统下如何移植EasyLogger。
用到的软件有:keil5、J_Link RTT Viewer
参考链接
移植步骤
一、EasyLogger
1.下载
2.将下载的压缩包解压
解压之后会有以下几个文件,其中主要用到的是./easylogger中的内容
3.将它移植到需要用到的工程目录中
4.打开工程,将./easylogger/port/以及./easylogger/src中的.c文件添加进工程
这里我只添加了./port中的.c文件以及./src中必要添加的文件
同时添加头文件路径
至此,EasyLogger已经移植成功,但在使用前还需进行一些必要的配置。
5.配置elog_cfg.h
这里我直接放代码了,需要改动的地方可以去开头参考链接1的博客了解;
/*
* This file is part of the EasyLogger Library.
*
* Copyright (c) 2015-2016, Armink, <armink.ztl@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Function: It is the configure head file for this library.
* Created on: 2015-07-30
*/
#ifndef _ELOG_CFG_H_
#define _ELOG_CFG_H_
/*---------------------------------------------------------------------------*/
/* enable log output. */
#define ELOG_OUTPUT_ENABLE
/* setting static output log level. range: from ELOG_LVL_ASSERT to ELOG_LVL_VERBOSE */
#define ELOG_OUTPUT_LVL ELOG_LVL_VERBOSE
/* enable assert check */
#define ELOG_ASSERT_ENABLE
/* buffer size for every line's log */
#define ELOG_LINE_BUF_SIZE 1024
/* output line number max length */
#define ELOG_LINE_NUM_MAX_LEN 5
/* output filter's tag max length */
#define ELOG_FILTER_TAG_MAX_LEN 30
/* output filter's keyword max length */
#define ELOG_FILTER_KW_MAX_LEN 16
/* output filter's tag level max num */
#define ELOG_FILTER_TAG_LVL_MAX_NUM 5
/* output newline sign */
#define ELOG_NEWLINE_SIGN "\r\n"
/*---------------------------------------------------------------------------*/
/* enable log color */
#define ELOG_COLOR_ENABLE
/* change the some level logs to not default color if you want */
#define ELOG_COLOR_ASSERT (F_MAGENTA B_NULL S_NORMAL)
#define ELOG_COLOR_ERROR (F_RED B_NULL S_NORMAL)
#define ELOG_COLOR_WARN (F_YELLOW B_NULL S_NORMAL)
#define ELOG_COLOR_INFO (F_CYAN B_NULL S_NORMAL)
#define ELOG_COLOR_DEBUG (F_GREEN B_NULL S_NORMAL)
#define ELOG_COLOR_VERBOSE (F_BLUE B_NULL S_NORMAL)
/*---------------------------------------------------------------------------*/
/* enable log fmt */
/* comment it if you don't want to output them at all */
#define ELOG_FMT_USING_FUNC
#define ELOG_FMT_USING_DIR
#define ELOG_FMT_USING_LINE
/*---------------------------------------------------------------------------*/
/* enable asynchronous output mode */
//#define ELOG_ASYNC_OUTPUT_ENABLE
/* the highest output level for async mode, other level will sync output */
#define ELOG_ASYNC_OUTPUT_LVL ELOG_LVL_ASSERT
/* buffer size for asynchronous output mode */
#define ELOG_ASYNC_OUTPUT_BUF_SIZE (ELOG_LINE_BUF_SIZE * 10)
/* each asynchronous output's log which must end with newline sign */
#define ELOG_ASYNC_LINE_OUTPUT
/* asynchronous output mode using POSIX pthread implementation */
#define ELOG_ASYNC_OUTPUT_USING_PTHREAD
/*---------------------------------------------------------------------------*/
/* enable buffered output mode */
//#define ELOG_BUF_OUTPUT_ENABLE
/* buffer size for buffered output mode */
#define ELOG_BUF_OUTPUT_BUF_SIZE (ELOG_LINE_BUF_SIZE * 10)
#endif /* _ELOG_CFG_H_ */
6.配置elog_port.c
我这里配置的代码与参考链接1的内容有些许不同,可以自行选择参考
注意:在此处编译可能会报错,原因是我头文件中引入了RTT的头文件,如果你是打算跟我用同一个日志打印工具那这里就不影响,可以继续跟着我一步步配置,如果你不打算用RTT,那可以把RTT的头文件删除。
/*
* This file is part of the EasyLogger Library.
*
* Copyright (c) 2015, Armink, <armink.ztl@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Function: Portable interface for each platform.
* Created on: 2015-04-28
*/
#include <elog.h>
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "SEGGER_RTT.h"
#include "SEGGER_RTT_Conf.h"
//! 日志互斥信号量句柄
static SemaphoreHandle_t LogMutexSemaphore = NULL;
/**
* EasyLogger port initialize
*
* @return result
*/
ElogErrCode elog_port_init(void) {
ElogErrCode result = ELOG_NO_ERR;
/* add your code here */
//! 创建互斥信号值
LogMutexSemaphore = xSemaphoreCreateMutex();
if (LogMutexSemaphore == NULL) {
printf("elog sem create fail\r\n");
result = ELOG_SEM_FAIL; //!< 注意:ElogErrCode 枚举中没有这个类型,需要添加一个错误类型
}
return result;
}
/**
* EasyLogger port deinitialize
*
*/
void elog_port_deinit(void) {
/* add your code here */
}
/**
* output log port interface
*
* @param log output of log
* @param size log size
*/
void elog_port_output(const char *log, size_t size) {
/* add your code here */
//! %s 表示字符串输出,
//! .<十进制数> 是精度控制格式符,输出字符时表示输出字符的位数,
//! 在精度控制时,小数点后的十进制数可以使用 * 来占位,
//! 在后面提供一个变量作为精度控制的具体值
SEGGER_RTT_Write(0, log, size);
}
/**
* output lock
*/
void elog_port_output_lock(void) {
/* add your code here */
if (NULL != LogMutexSemaphore)
{
xSemaphoreTake(LogMutexSemaphore, portMAX_DELAY); //!< 等待互斥信号量
}
}
/**
* output unlock
*/
void elog_port_output_unlock(void) {
/* add your code here */
if (NULL != LogMutexSemaphore)
{
xSemaphoreGive(LogMutexSemaphore); //!< 发送互斥信号量
}
}
/**
* get current time interface
*
* @return current time
*/
const char *elog_port_get_time(void) {
/* add your code here */
static char cur_system_time[16] = { 0 };
#if (INCLUDE_xTaskGetSchedulerState == 1 )
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
#endif
TickType_t tick = xTaskGetTickCount();
snprintf(cur_system_time, 16, "%d.%.3d", (tick / configTICK_RATE_HZ), tick % configTICK_RATE_HZ);
#if (INCLUDE_xTaskGetSchedulerState == 1 )
}
#endif
return cur_system_time;
}
/**
* get current process name interface
*
* @return current process name
*/
const char *elog_port_get_p_info(void) {
/* add your code here */
return "";
}
/**
* get current thread name interface
*
* @return current thread name
*/
const char *elog_port_get_t_info(void) {
/* add your code here */
#if (INCLUDE_xTaskGetSchedulerState == 1 )
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
#endif
return pcTaskGetName(xTaskGetCurrentTaskHandle());
#if (INCLUDE_xTaskGetSchedulerState == 1 )
}
#endif
return "";
}
/**
* init easylogger,这个函数是我们自己添加的,便于用户直接调用,需要在elog.h中添加声明
*/
void easylogger_init(void)
{
/* init Easylogger */
elog_init();
/* set EasyLogger log format */
elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_ALL);
elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TIME | ELOG_FMT_T_INFO);
elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_T_INFO);
elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL);
elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_ALL & ~ELOG_FMT_FUNC);
/*Eenbale color*/
elog_set_text_color_enabled(true);
/* start EasyLogger */
elog_start();
}
至此关于EasyLogger的改动已经结束了,接下来将进行RTT的配置
二、配置J-Link RTT Viewer
1.下载J-Link全家桶
去J-Link官网下载合适的版本
SEGGER - The Embedded Experts - Downloads - J-Link / J-Trace
下载后安装后就有J-Link全家桶了
我们一会要用的就是红框中的程序,但在此之前要进行一些配置
2.添加RTT进工程
在安装的全家桶中找到这个文件夹
进去后点击RTT
解压
解压后得到以下内容
将他们全部拷贝到keil5工程目录下,并将.c文件添加进工程中
并且添加头文件路径
至此,RTT也移植完成了,接下来将进行使用RTT打印日志信息
三、打印日志
1.在main文件中编写测试代码
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdlib.h>
#include "FreeRTOS.h"
#include "task.h"
#include "elog.h"
#define THREAD_STACKSIZE 1024
#define DEFAULT_THREAD_PRIO 2
TaskHandle_t task1_handler = NULL;
TaskHandle_t task2_handler = NULL;
void test(void *parameter)
{
int *hh = (int *)parameter;
while(1)
{
log_a("%d: Hello EasyLogger!", *hh);
log_e("%d: Hello EasyLogger!", *hh);
log_w("%d: Hello EasyLogger!", *hh);
log_i("%d: Hello EasyLogger!", *hh);
log_d("%d: Hello EasyLogger!", *hh);
log_v("%d: Hello EasyLogger!", *hh);
vTaskDelay(1/portTICK_PERIOD_MS);
}
}
void main_task(void *p)
{
int testNum = 1;
xTaskCreate(test, ( const char * const)"task1", THREAD_STACKSIZE, (void *)&testNum, DEFAULT_THREAD_PRIO, &task1_handler);
int testNum1 = 2;
xTaskCreate(test, ( const char * const)"task2", THREAD_STACKSIZE, (void *)&testNum1, DEFAULT_THREAD_PRIO, &task2_handler);
//sys_thread_new("system_init_thread", system_init_thread, &i, THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
vTaskDelete(NULL);
}
int main(void)
{
easylogger_init();
TaskHandle_t xHandle = NULL;
xTaskCreate(main_task, "main_task", THREAD_STACKSIZE, NULL, DEFAULT_THREAD_PRIO, &xHandle);
vTaskStartScheduler();
while (1);
return 0;
}
编译下载,并且J-Link不要断开
2.打开RTT Viewer
打开后进行以下操作
第二步时选择自己对应的板子型号
配置之后就可以正常显示日志内容啦
四、最后再说一下怎么使用elog打印函数
总结
这是本人在学习移植elog时总结的笔记,也是我的第一篇博客,如有不全,希望谅解与补充,若对你有帮助,还请留下一个赞以示鼓励呀!