📄 trace_buffer.c
字号:
/*
** Copyright (C) 2006 Tamir Michael
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include "general_definitions.h"
#include "trace_buffer.h"
#include "system_messages.h"
#include "rtos_services.h"
#pragma warning disable = 177 // disable the 'code unreachable' warning
// WAR STORY
// the contents of the trace buffer are not set to '0' (by the compiler) to allow post-crash analysis
#pragma NOINIT
static int8s s_trace_buffer[TRACE_BUFFER_SIZE] ;
#pragma INIT
static int8u s_mask ;
static int8u s_buffer_marker = 0 ;
extern int32u volatile g_tick_count ;
void trace_buffer_init()
{
switch (TRACE_BUFFER_SIZE)
{
case 8:
{
s_mask = 0x07 ;
break ;
}
case 16:
{
s_mask = 0x0F ;
break ;
}
case 32:
{
s_mask = 0x1F ;
break ;
}
case 128:
{
s_mask = 0x07F ;
// WAR STORY
// 0x07F = 127 (the top index in the trace buffer) = 111 1111. once 's_buffer_marker'
// overflows to 128 (1000 0000) the '&' operation at 'trace_buffer_insert' will put
// it back on 0. if is faster than checking an overflow using an 'if' statement.
break ;
}
case 256:
{
s_mask = 0x0FF ;
break ;
}
default:
software_error("%s %s %d", resolve_system_message(ERR_TRACE_BUFFER_INVALID_SIZE), __FILE__, __LINE__ ) ;
}
// WAR STORY
// the contexts of the trace buffer are not set to '0' (during buffer initialization) to allow post-crash analysis
// given the positioning of the end of buffer marker, this is not needed at all unless a 'crash' (a condition requiring analysis) occurs before the buffer
// wraps around for the first time. in that case, invalid data might still remain in the buffer.
}
void trace_buffer_insert(int8s a_code)
{
int8u l_interrupts_status ;
if (a_code == TRACE_BUFFER_END_MARKER)
{
software_warning("%s %d %s %d", resolve_system_message(ERR_TRACE_BUFFER_INVALID_CODE), a_code, __FILE__, __LINE__ ) ;
}
rtos_save_and_disable_interrupts(&l_interrupts_status) ; // prevent (among other disasters) a context switch while the trace buffer is accessed
// the buffer will overwrite old values once exceeding its storage capacity
s_trace_buffer[s_buffer_marker++] = (int8s)(g_tick_count & 0xFF) ; // low byte of first time stamp word
s_buffer_marker &= s_mask ; // this '&' operation will overflow the buffer once it exceeds from its upper index
s_trace_buffer[s_buffer_marker++] = (int8s)((g_tick_count & 0xFF00)>>8) ; // high byte of first time stamp word
s_buffer_marker &= s_mask ; // this '&' operation will overflow the buffer once it exceeds from its upper index
s_trace_buffer[s_buffer_marker++] = a_code ; // action code provided by the user
s_buffer_marker &= s_mask ; // this '&' operation will overflow the buffer once it exceeds from its upper index
s_trace_buffer[s_buffer_marker] = TRACE_BUFFER_END_MARKER ; // add an 'end of buffer' marker
rtos_restore_interrupts(l_interrupts_status) ;
}
void trace_buffer_flush()
{
memset(s_trace_buffer, '\0', MAX_QUEUE_ELEMENTS) ;
}
void trace_buffer_transmit()
{
// transmit interface is target specific. use to send contents of the trace buffer to a monitoring system (for
// example: by USB, CAN, Ethernet...) this implementation uses USB
// no need to disable interrupts here. all variables are interrupt safe as are the USB module calls.
int8u l_interrupts_status ;
// the order in which the contents of the buffer are sent must not be compromised by a task switch
// otherwise, crash analysis may in impossible
rtos_save_and_disable_interrupts(&l_interrupts_status) ;
rtos_restore_interrupts(l_interrupts_status) ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -