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

📄 post.c

📁 这项工程将让您把自己的MP3播放器平台
💻 C
字号:
//++
//post.c - power on self test routines
//
//        COPYRIGHT (C) 2005 BY SPARE TIME GIZMOS, MILPITAS CA, USA.
// 1636 Fallen Leaf Drive / Milpitas CA 95035 USA / info@SpareTimeGizmos.com
//
// This file is part of the Spare Time Gizmos MP3 Player firmware.  This firmware
// 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 firmware 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.
//
//DESCRIPTION:
//
//   The self test functions currently built in to the firmware are:
//
//	#1 - CPU (P68C668) failure
//	#2 - Flash ROM checksum fail
//
//
//REVISION HISTORY:
// dd-mmm-yy    who     description
// 15-May-05	RLA	New file.
// 13-Oct-05	RLA	Add the RAMSize() function.
//--

// Include files...
#include <stdio.h>		// needed so DBGOUT(()) can find printf!
#include "standard.h"		// standard types - BYTE, WORD, BOOL, etc
#include "reg66x.h"		// declarations for Philips 89C66x processors
#include "player.h"		// project wide (hardware configuration) declarations
#include "timer.h"		// define the DELAYUS() macro...
#include "post.h"		// POST codes for Fail()


//++
//   This function will calculate the checksum of the program EPROM.  The 
// checksum is calculated so that the 16 bit unsigned sum of all the bytes
// in the ROM, _including_ the checksum in the last two bytes, is equal to
// the last two bytes.  This slightly arcane algorithm is used because it
// gives the same value for the checksum as the Data I/O EEPROM programmer.
//
//   Since the checksum is included in itself, we have to go to some lengths
// to prevent the checksum value from affecting its own calculation.  The way
// that's done is to actually use the last _four_ bytes of the ROM - the last
// two contain the checksum and the two before that contain the complement of
// each byte in the checksum.  The sum of a byte and its complement is always
// 0x0100, and since there are two such bytes, adding a checksum to the ROM in
// this way always adds 0x0200 to the original checksum _regardless_ of what
// the actual checksum value may be.  The ROMCKSUM program that's used to
// calculate and store the checksum in the .HEX file takes this into account,
// so we can simply ignore the whole issue here.
//--
PUBLIC WORD ROMChecksum (WORD cbROM)
{
  // cbROM is the size of the system EEPROM, in bytes (e.g. 8192 or 32768)...
  WORD wChecksum;	// checksum accumulator
  WORD pcROM;		// pointer to bytes in ROM

  // Just sum up all the bytes, igoring overflows...  Pretty easy.
  for (wChecksum = pcROM = 0;  pcROM != cbROM;  ++pcROM) {
    wChecksum += * (PCBYTE) pcROM;
    //   If the ROM size is 32K, then believe it or not the WDT will time out
    // before we can finish our checksum.  It's too much overhead to reset the
    // WDT for every single byte, but we can do it every 4K or so...
    //if ((pcROM & 0xFFF) == 0) ResetWDT();
  }

  //DBGOUT(("ROMChecksum: wChecksum=0x%04X, ROM=0x%04X, cbROM=%u ...\n",
  //  wChecksum, *((PCWORD) (cbROM-2)), cbROM));

  return wChecksum;
}


//++
//   This routine will size the external data RAM on this 8051.  It's not a
// memory test in any way, and you shouldn't assume the memory works just
// because you get a number back from this routine. It's also a non-destructive
// test and restores the original RAM contents before it returns.
//
//   Notice that this implicitly assumes that RAM is contiguous and can be 
// addressed starting from location zero - if external RAM is mapped to
// another address or is non-contiguous, you're out of luck.  Also note that
// it returns zero if no external RAM can be found; in the unlikely event that
// we actually have 64K of RAM, you'll only get back 65535!
//--
PUBLIC WORD RAMSize (void)
{
  WORD cbRAM = 0;  WORD T1;
  //   The algorithm is pretty simple - just modify a pair of bytes in external
  // RAM until we find a word which can't be modified and then stop.  We could
  // test every pair of bytes, but in the interest of expediency we assume that
  // memory occurs in multiples of 256 bytes and only test every page.  Note that
  // some microprocessors, notably the 89C66x family, have RAMs that are not
  // multiples of 1K bytes (e.g. the 89C668 actually has 7936 bytes of "external"
  // RAM).
  //
  //   This routine has a few limitations, the most important of which is that
  // it won't work correctly for memory which is incompletely decoded (for example,
  // an 8K external SRAM where A15, A14 and A13 are unconnected).  That isn't a
  // problem for any of the embedded MCU's we're currently using.
  do {
    T1 = *((WORD volatile XDATA *) cbRAM);
    *((WORD volatile XDATA *) cbRAM) = 0xA55A;
    if (*((WORD volatile XDATA *) cbRAM) != 0xA55A) break;
    *((WORD volatile XDATA *) cbRAM) = T1;
    cbRAM += 256;
  } while (cbRAM != 0);
  return cbRAM;
}


#ifdef UNUSED
//++
//   This routine performs a very simple test of external SRAM.  External RAM
// is assumed to be mapped starting from address 0 and thru cbRAM-1.  Pass 1
// of this test simply writes every pair of RAM bytes with its address and the
// next pair with the complement of its address.  Pass 2 reads back and verifies
// the data from pass 1.  If the SRAM fails, then error code PC_XRAM is POSTed.
//--
PUBLIC BOOL RAMTest (WORD cbRAM)
{
  WORD pxRAM = cbRAM;  WORD nCount=0;  BOOL fPass = TRUE;

  // Pass 1...
  for (pxRAM = 0;  pxRAM != cbRAM;  pxRAM += 2) {
    *((PXWORD) pxRAM) =  pxRAM;  pxRAM += 2;
    *((PXWORD) pxRAM) = ~pxRAM;
  }

  // Pass 2...
  for (pxRAM = 0;  pxRAM != cbRAM;  pxRAM += 2) {
    if (*((PXWORD) pxRAM) !=  pxRAM) {
      //DBGOUT(("RAM failure, addr=0x%04x, data=0x%04x\n", pxRAM, *((PXWORD) pxRAM)));
      fPass = FALSE;
    }
    pxRAM += 2;
    if (*((PXWORD) pxRAM) != ~pxRAM) {
      //DBGOUT(("RAM failure, addr=0x%04x, data=0x%04x\n", pxRAM, *((PXWORD) pxRAM)));
      fPass = FALSE;
    }
  }

  return fPass;
}
#endif


//++
//   Blink the single player diagnostic LED.  Notice that this is a "terminal"
// routine - it disables interrupts and never returns control to the caller.
// It's used for debugging and in the case of POST failures...
//--
//   Note that we want to use the DELAYUS macro here, not the more convenient
// DelayMS() subroutine, because the latter depends on timer 2 being initialized
// and working correctly.  The DELAYUS macro generates a programmed delay loop
// directly inline and doesn't depend on anything else working...
#define SHORT_PAUSE {WORD j;  for (j = 2000;  j != 0;  --j) DELAYUS(100); }
#define LONG_PAUSE  {WORD j;  for (j = 15000;  j != 0;  --j) DELAYUS(100); }
PUBLIC void BlinkLED (BYTE nCode)
{
  BYTE nCount;
  INT_OFF;
  while (1) {
    for (nCount = nCode;  nCount > 0;  --nCount) {
      LED_ON;  SHORT_PAUSE;  LED_OFF;  SHORT_PAUSE;
    }
    LONG_PAUSE;
  }
}


//++
//--
PUBLIC void POST (BYTE nCode, BOOL fContinue)
{
  // In the debug version, print a textual description of the error code...
#ifdef DEBUG
  //   If a CPU failure occurs then the serial port has not been initialized
  // and we can't use DBGOUT - it would just hang forever!
  if (nCode == PC_CPU) goto BLINK;
  DBGOUT(("??FAIL: (%bu) ", nCode));
  switch (nCode) {
    case PC_CPU:	DBGOUT(("CPU failure"));			break;
    case PC_CHECKSUM:	DBGOUT(("ROM checksum error"));			break;
    case PC_SRAM:       DBGOUT(("Internal SRAM failure"));              break;
    case PC_STA013:	DBGOUT(("STA013 failure"));			break;
    case PC_DISPLAY:	DBGOUT(("Display (VFD or LCD) failure"));	break;
  }
  DBGOUT((" ...\n"));
#endif
  if (fContinue) return;
  DBGOUT(("\nSYSTEM HALTED.  POWER CYCLE TO RESTART ...\n\n"));
#ifdef DEBUG
BLINK:
#endif
  BlinkLED(nCode);  HALT;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -