1、【增加】开启/关闭同步锁功能,保证系统或硬件在出现异常时,EasyLogger依然正常可以工作。

Signed-off-by: armink <armink.ztl@gmail.com>
pull/3/head
armink 11 years ago
parent 2adfe8a479
commit 3f56ade85f

@ -22,3 +22,7 @@
`RVMDK` 下为Keil工程文件 `RVMDK` 下为Keil工程文件
`EWARM` 下为IAR工程文件 `EWARM` 下为IAR工程文件
## 3、其他功能
- 1、新增 RTT断言及硬件异常的钩子的方法使得系统在出现异常时错误日志依然可以被输出或保存。参考 `app\src\app_task.c` 中的 `assert_hook``exception_hook` 方法。

@ -84,8 +84,13 @@ while (0)
if (!(EX)) \ if (!(EX)) \
{ \ { \
volatile char dummy = 0; \ volatile char dummy = 0; \
rt_kprintf("(%s) assert failed at %s:%d \n", #EX, __FUNCTION__, __LINE__);\ if (rt_assert_hook == RT_NULL) \
while (dummy == 0); \ { \
rt_kprintf("(%s) assert failed at %s:%d \n", #EX, __FUNCTION__, __LINE__);\
while (dummy == 0); \
} else { \
rt_assert_hook(#EX, __FUNCTION__, __LINE__); \
} \
} }
/* Macro to check current context */ /* Macro to check current context */

@ -510,6 +510,11 @@ rt_uint32_t rt_strcasecmp(const char *a, const char *b);
void rt_show_version(void); void rt_show_version(void);
#ifdef RT_DEBUG
extern void (*rt_assert_hook)(const char* ex, const char* func, rt_size_t line);
void rt_assert_set_hook(void (*hook)(const char* ex, const char* func, rt_size_t line));
#endif /* RT_DEBUG */
/*@}*/ /*@}*/
#ifdef __cplusplus #ifdef __cplusplus

@ -1249,6 +1249,19 @@ int __rt_ffs(int value)
} }
#endif #endif
#ifdef RT_DEBUG
/* RT_ASSERT(EX)'s hook */
void (*rt_assert_hook)(const char* ex, const char* func, rt_size_t line);
/**
* This function will set a hook function to RT_ASSERT(EX). It will run when the expression is false.
*
* @param hook the hook function
*/
void rt_assert_set_hook(void (*hook)(const char* ex, const char* func, rt_size_t line)) {
rt_assert_hook = hook;
}
#endif /* RT_DEBUG */
#if !defined (RT_USING_NEWLIB) && defined (RT_USING_MINILIBC) && defined (__GNUC__) #if !defined (RT_USING_NEWLIB) && defined (RT_USING_MINILIBC) && defined (__GNUC__)
#include <sys/types.h> #include <sys/types.h>
void *memcpy(void *dest, const void *src, size_t n) __attribute__((weak, alias("rt_memcpy"))); void *memcpy(void *dest, const void *src, size_t n) __attribute__((weak, alias("rt_memcpy")));

@ -32,6 +32,8 @@ static rt_uint8_t thread_sys_monitor_stack[512];
struct rt_thread thread_sys_monitor; struct rt_thread thread_sys_monitor;
static void test_elog(void); static void test_elog(void);
static void assert_hook(const char* ex, const char* func, rt_size_t line);
static rt_err_t exception_hook(void *context);
/** /**
* System monitor thread. * System monitor thread.
@ -90,6 +92,10 @@ void sys_init_thread(void* parameter){
/* set enabled format */ /* set enabled format */
elog_set_fmt(ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME /*| ELOG_FMT_P_INFO*/ | ELOG_FMT_T_INFO | ELOG_FMT_DIR elog_set_fmt(ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME /*| ELOG_FMT_P_INFO*/ | ELOG_FMT_T_INFO | ELOG_FMT_DIR
/*| ELOG_FMT_FUNC*/ | ELOG_FMT_LINE); /*| ELOG_FMT_FUNC*/ | ELOG_FMT_LINE);
/* set hardware exception hook */
rt_hw_exception_install(exception_hook);
/* set RT-Thread assert hook */
rt_assert_set_hook(assert_hook);
/* initialize OK and switch to running status */ /* initialize OK and switch to running status */
set_system_status(SYSTEM_STATUS_RUN); set_system_status(SYSTEM_STATUS_RUN);
} else { } else {
@ -100,6 +106,45 @@ void sys_init_thread(void* parameter){
rt_thread_delete(rt_thread_self()); rt_thread_delete(rt_thread_self());
} }
static void assert_hook(const char* ex, const char* func, rt_size_t line) {
elog_output_lock_enabled(false);
//elog_flash_lock_enabled(false);
elog_a("assert", "(%s) has assert failed at %s:%ld.\n", ex, func, line);
//elog_flash_flush();
while(1);
}
static rt_err_t exception_hook(void *context) {
struct exception_stack_frame {
rt_uint32_t r0;
rt_uint32_t r1;
rt_uint32_t r2;
rt_uint32_t r3;
rt_uint32_t r12;
rt_uint32_t lr;
rt_uint32_t pc;
rt_uint32_t psr;
};
struct exception_stack_frame *exception_stack = (struct exception_stack_frame *) context;
elog_output_lock_enabled(false);
//elog_flash_lock_enabled(false);
elog_e("hw_fault", "psr: 0x%08x", exception_stack->psr);
elog_e("hw_fault", " pc: 0x%08x", exception_stack->pc);
elog_e("hw_fault", " lr: 0x%08x", exception_stack->lr);
elog_e("hw_fault", "r12: 0x%08x", exception_stack->r12);
elog_e("hw_fault", "r03: 0x%08x", exception_stack->r3);
elog_e("hw_fault", "r02: 0x%08x", exception_stack->r2);
elog_e("hw_fault", "r01: 0x%08x", exception_stack->r1);
elog_e("hw_fault", "r00: 0x%08x", exception_stack->r0);
elog_e("hw_fault", "hard fault on thread: %s", rt_thread_self()->name);
//elog_flash_flush();
return RT_EOK;
}
int rt_application_init(void) int rt_application_init(void)
{ {
rt_thread_t init_thread = NULL; rt_thread_t init_thread = NULL;

@ -61,7 +61,7 @@ extern "C" {
/* output newline sign */ /* output newline sign */
#define ELOG_NEWLINE_SIGN "\r\n" #define ELOG_NEWLINE_SIGN "\r\n"
/* EasyLogger software version number */ /* EasyLogger software version number */
#define ELOG_SW_VERSION "0.06.24" #define ELOG_SW_VERSION "0.06.25"
/* EasyLogger assert for developer. */ /* EasyLogger assert for developer. */
#define ELOG_ASSERT(EXPR) \ #define ELOG_ASSERT(EXPR) \
@ -115,6 +115,7 @@ void elog_set_filter_kw(const char *keyword);
void elog_raw(const char *format, ...); void elog_raw(const char *format, ...);
void elog_output(uint8_t level, const char *tag, const char *file, const char *func, void elog_output(uint8_t level, const char *tag, const char *file, const char *func,
const long line, const char *format, ...); const long line, const char *format, ...);
void elog_output_lock_enabled(bool enabled);
#ifndef ELOG_OUTPUT_ENABLE #ifndef ELOG_OUTPUT_ENABLE

@ -40,7 +40,7 @@ extern "C" {
/* EasyLogger flash save plugin's RAM buffer size */ /* EasyLogger flash save plugin's RAM buffer size */
#define ELOG_FLASH_BUF_SIZE 1024 #define ELOG_FLASH_BUF_SIZE 1024
/* EasyLogger flash save plugin's software version number */ /* EasyLogger flash save plugin's software version number */
#define ELOG_FLASH_SW_VERSION "0.06.10" #define ELOG_FLASH_SW_VERSION "0.06.25"
/* elog_flash.c */ /* elog_flash.c */
ElogErrCode elog_flash_init(void); ElogErrCode elog_flash_init(void);
@ -50,6 +50,7 @@ void elog_flash_outout_recent(size_t size);
void elog_flash_set_filter(uint8_t level,const char *tag,const char *keyword); void elog_flash_set_filter(uint8_t level,const char *tag,const char *keyword);
void elog_flash_write(const char *log, size_t size); void elog_flash_write(const char *log, size_t size);
void elog_flash_clean(void); void elog_flash_clean(void);
void elog_flash_lock_enabled(bool enabled);
#ifdef ELOG_FLASH_USING_BUF_MODE #ifdef ELOG_FLASH_USING_BUF_MODE
void elog_flash_flush(void); void elog_flash_flush(void);

@ -46,6 +46,14 @@ static const char *level_output_info[] = {
"D/", "D/",
"V/", "V/",
}; };
/* the output lock enable or disable. default is enable */
static bool output_lock_enabled = true;
/* the output is locked before enable. */
static bool output_is_locked_before_enable = false;
/* the output is locked before disable. */
static bool output_is_locked_before_disable = false;
static void output_lock(void);
static void output_unlock(void);
static bool get_fmt_enabled(size_t set); static bool get_fmt_enabled(size_t set);
/** /**
@ -166,7 +174,7 @@ void elog_raw(const char *format, ...) {
va_start(args, format); va_start(args, format);
/* lock output */ /* lock output */
elog_port_output_lock(); output_lock();
/* package log data to buffer */ /* package log data to buffer */
fmt_result = vsnprintf(log_buf, ELOG_BUF_SIZE, format, args); fmt_result = vsnprintf(log_buf, ELOG_BUF_SIZE, format, args);
@ -225,7 +233,7 @@ void elog_output(uint8_t level, const char *tag, const char *file, const char *f
va_start(args, format); va_start(args, format);
/* lock output */ /* lock output */
elog_port_output_lock(); output_lock();
/* package level info */ /* package level info */
if (get_fmt_enabled(ELOG_FMT_LVL)) { if (get_fmt_enabled(ELOG_FMT_LVL)) {
log_len += elog_strcpy(log_len, log_buf + log_len, level_output_info[level]); log_len += elog_strcpy(log_len, log_buf + log_len, level_output_info[level]);
@ -307,7 +315,7 @@ void elog_output(uint8_t level, const char *tag, const char *file, const char *f
if (!strstr(log_buf, elog.filter.keyword)) { if (!strstr(log_buf, elog.filter.keyword)) {
//TODO 可以考虑采用KMP及朴素模式匹配字符串提升性能 //TODO 可以考虑采用KMP及朴素模式匹配字符串提升性能
/* unlock output */ /* unlock output */
elog_port_output_unlock(); output_unlock();
return; return;
} }
@ -325,7 +333,7 @@ void elog_output(uint8_t level, const char *tag, const char *file, const char *f
elog_port_output(log_buf, log_len); elog_port_output(log_buf, log_len);
/* unlock output */ /* unlock output */
elog_port_output_unlock(); output_unlock();
} }
/** /**
@ -342,3 +350,46 @@ static bool get_fmt_enabled(size_t set) {
return false; return false;
} }
} }
/**
* enable or disable logger output lock
* @note disable this lock is not recommended except you want output system exception log
*
* @param enabled true: enable false: disable
*/
void elog_output_lock_enabled(bool enabled) {
output_lock_enabled = enabled;
/* it will re-lock or re-unlock before output lock enable */
if (output_lock_enabled) {
if (!output_is_locked_before_disable && output_is_locked_before_enable) {
/* the output lock is unlocked before disable, and the lock will unlocking after enable */
elog_port_output_lock();
} else if (output_is_locked_before_disable && !output_is_locked_before_enable) {
/* the output lock is locked before disable, and the lock will locking after enable */
elog_port_output_unlock();
}
}
}
/**
* lock output
*/
static void output_lock(void) {
if (output_lock_enabled) {
elog_port_output_lock();
output_is_locked_before_disable = true;
} else {
output_is_locked_before_enable = true;
}
}
/**
* unlock output
*/
static void output_unlock(void) {
if (output_lock_enabled) {
elog_port_output_unlock();
output_is_locked_before_disable = false;
} else {
output_is_locked_before_enable = false;
}
}

@ -48,6 +48,14 @@ static size_t cur_buf_size = 0;
/* initialize OK flag */ /* initialize OK flag */
static bool init_ok = false; static bool init_ok = false;
/* the flash log buffer lock enable or disable. default is enable */
static bool log_buf_lock_enabled = true;
/* the flash log buffer is locked before enable. */
static bool log_buf_is_locked_before_enable = false;
/* the flash log buffer is locked before disable. */
static bool log_buf_is_locked_before_disable = false;
static void log_buf_lock(void);
static void log_buf_unlock(void);
/** /**
* EasyLogger flash save plugin initialize. * EasyLogger flash save plugin initialize.
@ -94,7 +102,7 @@ void elog_flash_outout(size_t index, size_t size) {
/* must be call this function after initialize OK */ /* must be call this function after initialize OK */
ELOG_ASSERT(init_ok); ELOG_ASSERT(init_ok);
/* lock flash log buffer */ /* lock flash log buffer */
elog_flash_port_lock(); log_buf_lock();
/* Output all flash saved log. It will use filter */ /* Output all flash saved log. It will use filter */
while (true) { while (true) {
if (index + read_size + buf_szie < log_total_size) { if (index + read_size + buf_szie < log_total_size) {
@ -118,7 +126,7 @@ void elog_flash_outout(size_t index, size_t size) {
} }
} }
/* unlock flash log buffer */ /* unlock flash log buffer */
elog_flash_port_unlock(); log_buf_unlock();
} }
/** /**
@ -163,7 +171,7 @@ void elog_flash_write(const char *log, size_t size) {
ELOG_ASSERT(init_ok); ELOG_ASSERT(init_ok);
/* lock flash log buffer */ /* lock flash log buffer */
elog_flash_port_lock(); log_buf_lock();
#ifdef ELOG_FLASH_USING_BUF_MODE #ifdef ELOG_FLASH_USING_BUF_MODE
while (true) { while (true) {
@ -174,11 +182,11 @@ void elog_flash_write(const char *log, size_t size) {
size -= write_size; size -= write_size;
cur_buf_size += write_size; cur_buf_size += write_size;
/* unlock flash log buffer */ /* unlock flash log buffer */
elog_flash_port_unlock(); log_buf_unlock();
/* write all buffered log to flash, cur_buf_size will reset */ /* write all buffered log to flash, cur_buf_size will reset */
elog_flash_flush(); elog_flash_flush();
/* lock flash log buffer */ /* lock flash log buffer */
elog_flash_port_lock(); log_buf_lock();
} else { } else {
memcpy(log_buf + cur_buf_size, log + write_index, size); memcpy(log_buf + cur_buf_size, log + write_index, size);
cur_buf_size += size; cur_buf_size += size;
@ -198,7 +206,7 @@ void elog_flash_write(const char *log, size_t size) {
#endif #endif
/* unlock flash log buffer */ /* unlock flash log buffer */
elog_flash_port_unlock(); log_buf_unlock();
} }
#ifdef ELOG_FLASH_USING_BUF_MODE #ifdef ELOG_FLASH_USING_BUF_MODE
@ -211,7 +219,7 @@ void elog_flash_flush(void) {
/* must be call this function after initialize OK */ /* must be call this function after initialize OK */
ELOG_ASSERT(init_ok); ELOG_ASSERT(init_ok);
/* lock flash log buffer */ /* lock flash log buffer */
elog_flash_port_lock(); log_buf_lock();
/* flash write is word alignment */ /* flash write is word alignment */
if (cur_buf_size % 4 != 0) { if (cur_buf_size % 4 != 0) {
write_overage_size = 4 - (cur_buf_size % 4); write_overage_size = 4 - (cur_buf_size % 4);
@ -223,7 +231,7 @@ void elog_flash_flush(void) {
/* reset position */ /* reset position */
cur_buf_size = 0; cur_buf_size = 0;
/* unlock flash log buffer */ /* unlock flash log buffer */
elog_flash_port_unlock(); log_buf_unlock();
} }
#endif #endif
@ -236,7 +244,7 @@ void elog_flash_clean(void) {
/* must be call this function after initialize OK */ /* must be call this function after initialize OK */
ELOG_ASSERT(init_ok); ELOG_ASSERT(init_ok);
/* lock flash log buffer */ /* lock flash log buffer */
elog_flash_port_lock(); log_buf_lock();
/* clean all log which in flash */ /* clean all log which in flash */
clean_result = flash_log_clean(); clean_result = flash_log_clean();
@ -246,7 +254,7 @@ void elog_flash_clean(void) {
#endif #endif
/* unlock flash log buffer */ /* unlock flash log buffer */
elog_flash_port_unlock(); log_buf_unlock();
if(clean_result == FLASH_NO_ERR) { if(clean_result == FLASH_NO_ERR) {
log_i("All logs which in flash is clean OK."); log_i("All logs which in flash is clean OK.");
@ -254,3 +262,46 @@ void elog_flash_clean(void) {
log_e("Clean logs which in flash has an error!"); log_e("Clean logs which in flash has an error!");
} }
} }
/**
* enable or disable flash plugin lock
* @note disable this lock is not recommended except you want output system exception log
*
* @param enabled true: enable false: disable
*/
void elog_flash_lock_enabled(bool enabled) {
log_buf_lock_enabled = enabled;
/* it will re-lock or re-unlock before log buffer lock enable */
if (log_buf_lock_enabled) {
if (!log_buf_is_locked_before_disable && log_buf_is_locked_before_enable) {
/* the log buffer lock is unlocked before disable, and the lock will unlocking after enable */
elog_flash_port_lock();
} else if (log_buf_is_locked_before_disable && !log_buf_is_locked_before_enable) {
/* the log buffer lock is locked before disable, and the lock will locking after enable */
elog_flash_port_unlock();
}
}
}
/**
* lock flash log buffer
*/
static void log_buf_lock(void) {
if (log_buf_lock_enabled) {
elog_flash_port_lock();
log_buf_is_locked_before_disable = true;
} else {
log_buf_is_locked_before_enable = true;
}
}
/**
* unlock flash log buffer
*/
static void log_buf_unlock(void) {
if (log_buf_lock_enabled) {
elog_flash_port_unlock();
log_buf_is_locked_before_disable = false;
} else {
log_buf_is_locked_before_enable = false;
}
}

Loading…
Cancel
Save