⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trace_buffer.c

📁 嵌入式操作系统EOS(Embedded OperatingSystem)是一种用途广泛的系统软件
💻 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 + -