A core-dump implementation for PIC18 devices with on-chip Ethernet controller.

by Isaac Marino Bavaresco

This is file "dumper.cpp".

//==============================================================================
/*
 Copyright (c) 2008-2010, Isaac Marino Bavaresco
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Neither the name of the author nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY
 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//==============================================================================
// isaacbavaresco@yahoo.com.br
//==============================================================================
/*

This program reads a core-dump generated by my routines for PIC18 micro-controllers
(http://www.piclist.com/techref/member/IMB-yahoo-J86/core-dump-PIC18FxxJ6x.htm)
and prints a (more or less) human-readable report.

The dump-file structure is:

Offset      Contents
---------   --------------
0000        STATUS
0001        WREG
0002        FSR0L
0003        FSR0H
0004        RCON
0005        STKPTR

0006-0062   HARDWARE STACK
0063-1062   RAM

*/
//==============================================================================
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
//==============================================================================
// Struct to hold the critical registers which saved first in the core-dump.
typedef struct
    {
    unsigned char   STATUS;
    unsigned char   WREG;
    unsigned char   FSR0L;
    unsigned char   FSR0H;
    unsigned char   RCON;
    unsigned char   STKPTR;
    } TS_Registers;
//==============================================================================
// Array to hold the hardware stack, which is the second data group saved.
typedef unsigned char TA_HardwareStack[31][3];
//==============================================================================
int Dump( int Handle )
    {
    TS_Registers        Registers;
    TA_HardwareStack    HardwareStack;
    unsigned char       RAM[4*1024];
    unsigned int        i, j;

    // Read the critical register values
    if( read( Handle, &Registers, sizeof Registers ) != sizeof Registers )
        {
        printf( "\nFailure reading file!\n\n" );
        return 2;
        }

    // Read the contents of the hardware stack.
    if( read( Handle, &HardwareStack, sizeof HardwareStack ) != sizeof HardwareStack )
        {
        printf( "\nFailure reading file!\n\n" );
        return 2;
        }

    // Read the remaining of the fila, which holds the MCU's RAM memory.
    if( read( Handle, RAM, sizeof RAM ) != sizeof RAM )
        {
        printf( "\nFailure reading file!\n\n" );
        return 2;
        }

    // Copy the registers saved first back to their correct RAM addresses.
    RAM[0xfd8]  = Registers.STATUS;
    RAM[0xfe8]  = Registers.WREG;
    RAM[0xfe9]  = Registers.FSR0L;
    RAM[0xfea]  = Registers.FSR0H;
    RAM[0xffc]  = Registers.STKPTR;

    // Print the contents of the RAM.
    for( i = 0; i < sizeof RAM; i += 16 )
        {
        printf( "%03X ", i );
        for( j = 0; j < 16; j++ )
            printf( " %02X", RAM[i + j] );

        printf( "  " );

        for( j = 0; j < 16; j++ )
            if( RAM[i + j] < 32 || RAM[i + j] > 126 )
                printf( "." );
            else
                printf( "%c", RAM[i + j] );
        printf( "\n" );
        }

    // Print the contents of the hardware stack.
    printf( "\nHardware Stack:\n\n" );
    for( i = 0; i < sizeof HardwareStack / sizeof HardwareStack[0]; i++ )
        {
        j = HardwareStack[i][0] | HardwareStack[i][1] << 8 | HardwareStack[i][2] << 16;
        printf( "%2u - %06X\n", sizeof HardwareStack / sizeof HardwareStack[0] - i, j );
        }
    // The level 0 of the hardware stack doesn't exist really, it is hard-coded to zero.
    printf( " 0 - 000000\n" );

//    printf( "\nSuccess!\n\n" );

    return 0;
    }
//==============================================================================
int main( int ArgC, char *ArgV[] )
    {
    int Handle;
    int Aux;

    if( ArgC < 2 )
        {
        printf( "\nLacking file name!\n\n" );
        return 3;
        }
/*
    else if( ArgC == 3 )
        {
        }
    else
        {
        printf( "\nExcess arguments!\n\n" );
        return 3;
        }
*/

    if(( Handle = open( ArgV[1], O_RDONLY | O_BINARY )) < 0 )
        {
        printf( "\nFailure opening file %s!\n\n", ArgV[1] );
        return 1;
        }

    Aux = Dump( Handle );

    close( Handle );

    return Aux;
    }
//==============================================================================