📄 hdlcint.c
字号:
/*-----------------------------------------------------------------------------
*
* FILE: hdlcint.c
** DESCRIPTION:
*
* Exercises SCC2 HDLC transmit/receive functions, using RX interrupts. This
* program sends 8 HDLC frames, with each frame comtaining a different data
* pattern. SCC2 will receive all 8 frames and then the external interrupt
* will be vectored to. In this interrupt, all 8 Rx frames will be checked
* against it's corresponding Tx frame. It also checks for Rx errors. If any
* errors or mismatches exist then the Ethernet LED on the ADS 821/860 board
* will be flashed. If the transfer of data was successful the LED stay lit
* constantly.
*
* For a high level explanation, please refer to the applications document for
* this example which is included in the Zip file you received. If you are
* interested in a ADS 860 development/evaluation system, please contact your
* local sales representative.
*
*
* NOTES <<<IMPORTANT: PLEASE READ>>>:
** 1) Specifically Designed to run on 821/860 ADS board.
** 2) DISABLE Data Cache for pages containing Rx/Tx buffers.
** 3) If you want to operate in External Loopback Mode:
* Connect Pins: P13-A3 to P13-A4
* Set the DIAG bits in the GSMR Low Register to turn internal
* loopback off
** 4) In Internal or External Loopback Mode, the driver tests the
* transmitted information against the received and turns on the
* ETH LED on the ADS board if there is an exact match. If there is not
* a match, then the ETH LED will flash.
** 5) This driver also takes an external interrupt on a full HDLC
* packet reception. If the interrupt handler does not see Received
* Full status (RXF) in the SCC Event register, then it turns on the
* ETH LED to signal an error condition.
*
* 6) If this program is run under BDM, you must first clear the EXTIE bit
* in the DER. Otherwise, the interrupt from the SCC will trap you back
* into the debugger.
** REFERENCES:
*
* 1) MPC860 Users Manual
* 2) PowerPC Microprocessor Family: The Programming Environments for
* 32-Bit Microprocessors
*
* HISTORY:
** 7/31/96 saw Initial version.
* 2/20/97 sgj Adapted to HDLC from IRDa.
* 8/22/97 sgj Debugged and completed.
* 11/20/97 jay Complete Modification and Documented
*
*-----------------------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>
#include "netcomm.h" /* global defines */
#include "mpc860.h" /* IMMR definitions and declarations */
#include "hdlcint.h" /* Local header file */
#include "masks860.h" /* Global masks header file */
/***********************/
/* Global Declarations */
/***********************/
EPPC *IMMR; /* IMMR base pointer */
BDRINGS *RxTxBD; /* buffer descriptors base pointer */
/*--------------------------------------------------------*/
/* Set of Data Buffers for HDLC Receive and Transmit Data */
/* The Rx buffer pools will take up the first 8 buffers */
/* and the Tx buffer pools will take up the last 8. */
/*--------------------------------------------------------*/
LB BufferPool[NUM_RXBDS+NUM_TXBDS];
/*---------------------------------------------------------*/
/* Status parameters of the receive and transmit processes */
/*---------------------------------------------------------*/
UHWORD RxGood; /* Successful RX flag */
UBYTE RxProcIndex; /* keeps track of next BD to process */
/*-----------------------------------------------------*//* Interrupt Handler Code to be moved to Address 0x500 */
/*-----------------------------------------------------*/extern UWORD ExtIntTable[];
/***********************/
/* Function Prototypes */
/***********************/
void InterruptInit(UWORD *, UWORD[]);
void InitBDs(void);
void SCC2HInit(void);
void ExtIntHandler(UWORD);
void Main(void);
void LoadTxBuffers(void);
UHWORD BDEmpty(UHWORD);
UHWORD LastBD(UHWORD);
void Ethled(UHWORD);
void FlashEthled(void);
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: main
*
* DESCRIPTION:
*
* This is the main function for the HDLC example code.
*
* EXTERNAL EFFECT:
*
* PARAMETERS: None
*
* RETURNS: None
*
*---------------------------------------------------------------------------*/
void Main()
{
RxGood = TRUE; /* initialize as good */
RxProcIndex = 0; /* initialize */
/*------------------------*/
/* Establish IMMR pointer */
/*------------------------*/
IMMR = (EPPC *)(GetIMMR() & 0xFFFF0000); /* MPC8xx internal register
map */
/*--------------------------------------------------------*/ /* Place External Interrupt Handler Code to Address 0x500 */
/*--------------------------------------------------------*/ InterruptInit((UWORD *) EXT_INT_VECTOR, ExtIntTable);
/***********************************************************/
/* Establish base pointer for Tx and Rx buffer descriptors */
/***********************************************************/
/*-----------------------------------------------------------------------*/
/* I am adding 64 bytes to the start of the buffer descriptors because */
/* I have a monitor program on my target that is using most of the first */
/* 64 bytes for buffer descriptors. If you are not using the SDS monitor */
/* with Motorola's ADS development board, you can delete 64 below and */
/* start at the beginning of this particular block of Dual Port RAM. */
/*-----------------------------------------------------------------------*/
RxTxBD = (BDRINGS *)(IMMR->udata_bd + 64); /* Get pointer to BD area
on DPRAM */
/*------------------------------------------------*/
/* Load the Tx buffer pool with the test patterns */
/*------------------------------------------------*/
LoadTxBuffers();
/*------------------------------------------------------------------------*/
/* This function defines a number of buffers for an RX and TX buffer pool,*/
/* but does not attempt to manage memory. It just uses the first half */
/* of the BD pool for RX and the second half for TX. */
/*------------------------------------------------------------------------*/
InitBDs(); /* Initialize RX and TX BDs */
/*---------------------------------------------------------------------*/
/* Initialize and enable SCC2 in HDLC mode, internal loopback, and for */
/* External Interrupt */
/*---------------------------------------------------------------------*/
SCC2HInit();
/*------------------------------------------------------------------*/
/* Come in to the loop and wait until all frames have been sent and */
/* received. The Ethernet LED on the ADS board will stay lit until */
/* all frames have been received and checked. If there were any */
/* errors the LED will flash. This action is initiated in the */
/* interrupt handler where the checking takes place. */
/*------------------------------------------------------------------*/
while (1)
{
/*-----------------------------------------------------------------*/
/* stay in this tight loop if the transfer of data was successful. */
/* If there wasn't success, stay in a tight loop in the external */
/* interrupt handler. */
/*-----------------------------------------------------------------*/
while (RxGood == TRUE)
{
/*-------------------------------------------------------*/
/* Turn On Ethernet LED to indicate error-free reception */
/*-------------------------------------------------------*/
Ethled(ON);
}
}
} /* End Main */
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: InitBDs
*
* DESCRIPTION:
*
* Initializes BD rings to point RX BDs to first half of buffer pool and TX BDs
* to second half of buffer pool. This function also initializes the buffer
* descriptors control and data length fields. It also ensures that transmit
* and recieve functions are disabled before buffer descriptors are initialized.
*
* EXTERNAL EFFECTS: Disable Tx/Rx functions. Changes BDs in dual port ram.
*
* PARAMETERS: None
*
* RETURNS: None
*
*-----------------------------------------------------------------------------*/
void InitBDs()
{
UHWORD index;
/*--------------------------------------------------------------------*/
/* First let's ensure the SCC2 functions are off while we program the */
/* buffer descriptors and the parameter ram. */
/*--------------------------------------------------------------------*/
/*----------------------------------------------------------------*/
/* Clear the ENT/ENR bits in the GSMR -- disable Transmit/Receive */
/*----------------------------------------------------------------*/
IMMR->scc_regs[SCC2_REG].scc_gsmr_l &= 0xFFFFFFCF;
/*--------------------------------------*/
/* Issue Init Stop TX Command for SCC2. */
/*--------------------------------------*/
while ((IMMR->cp_cr & CPCR_FLG) != READY_TO_RX_CMD);
IMMR->cp_cr = CPCR_STOP_TX |
CPCR_SCC2_CH |
CPCR_FLG; /* ISSUE COMMAND */
while ((IMMR->cp_cr & CPCR_FLG) != READY_TO_RX_CMD);
/*-------------------*/ /* Initialize RxBDs. */
/*-------------------*/ for (index = 0; index < NUM_RXBDS; index++)
{
/*--------------------------*/
/* Allocate Receive Buffers */
/*--------------------------*/
RxTxBD->RxBD[index].bd_addr = (UBYTE *)&BufferPool[index];
RxTxBD->RxBD[index].bd_length = 0; /* reset */
if( index != (NUM_RXBDS-1) )
{
RxTxBD->RxBD[index].bd_cstatus = 0x8000; /* Empty */
}
else
{
/*-------------------------------------------------*/ /* Last RX BD. Set the empty and the Interrupt bit */
/*-------------------------------------------------*/ RxTxBD->RxBD[index].bd_cstatus = 0xB000;
}
}
/*-------------------*/ /* Initialize TxBDs. */
/*-------------------*/ for (index=0; index < NUM_TXBDS; index++)
{
/*---------------------------------------------------------------------*/
/* load the buffer length - 2 bytes because the SCC will need to write */
/* the two CRC bytes to Rx buffer. */
/*---------------------------------------------------------------------*/
RxTxBD->TxBD[index].bd_length = (BUFFER_SIZE-2);
/*--------------------------------------------------------*/
/* load the address of the data buffer in external memory */
/*--------------------------------------------------------*/
RxTxBD->TxBD[index].bd_addr = (UBYTE *)&BufferPool[FIRST_TX_BUF+index];
if( index != (NUM_TXBDS-1) )
{
/*---------------------------------*/
/* Set Ready, Tx CRC, and Last bit */
/*---------------------------------*/
RxTxBD->TxBD[index].bd_cstatus = 0x8C00;
}
else
{
/*-----------------------------------------------*/
/* Set Ready, Tx CRC, Last bit, and the Wrap bit */
/*-----------------------------------------------*/
RxTxBD->TxBD[index].bd_cstatus = 0xAC00;
}
}
} /* end InitBDs */
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: LoadTxBuffers
*
* DESCRIPTION:
*
* This function will load all 8 Tx buffers with the following data patterns:
*
* Buffer 1: 0x55
* Buffer 2: 0xAA
* Buffer 3: 0x00
* Buffer 4: 0xFF
* Buffer 5: Increasing Walking Ones
* Buffer 6: Decreasing Walking Ones
* Buffer 7: Increment from 0
* Buffer 8: Decrement from 255
*
* Each Tx buffer is loaded with 2 bytes of address, followed by 254 bytes of
* pattern bytes. Only 252 bytes of pattern bytes are loaded into the receive
* buffer because the receive channel will also write 2 byte CRC. The total
* number of bytes loaded into the receive buffer will be 2 address bytes + 252
* pattern bytes + 2 bytes of CRC. This gives a total of 256 bytes which is the
* size the receive buffer needs to be.
*
* EXTERNAL EFFECTS:
*
* BufferPool
*
* PARAMETERS: none
*
* RETURNS: none
*
*-----------------------------------------------------------------------------*/
void LoadTxBuffers()
{
UHWORD index, pattern;
/*----------------*/
/* Load 254 0x55s */
/*----------------*/
/*-------------------------------------------------------------------------*/
/* First load the destination addr in the first two bytes of the buffer. */
/* What could follow would be the control field. I'm not going to load */
/* it here because this is a simple example and I don't need to process it.*/
/*-------------------------------------------------------------------------*/
BufferPool[FIRST_TX_BUF][0] = (STADDR%256); /* Load the low byte first */
BufferPool[FIRST_TX_BUF][1] = (STADDR/256); /* Load the high byte */
for (index = 2; index < BUFFER_SIZE; index++)
{
BufferPool[FIRST_TX_BUF][index] = 0x55;
}
/*----------------*/
/* Load 254 0xAAs */
/*----------------*/
/*--------------------------------*/
/* Load the destination address */
/*--------------------------------*/
BufferPool[FIRST_TX_BUF+1][0] = (STADDR%256); /* Load the low byte first */
BufferPool[FIRST_TX_BUF+1][1] = (STADDR/256); /* Load the high byte */
for (index = 2; index < BUFFER_SIZE; index++)
{
BufferPool[FIRST_TX_BUF+1][index] = 0xAA;
}
/*----------------*/
/* Load 254 0x00s */
/*----------------*/
/*--------------------------------*/
/* Load the destination address */
/*--------------------------------*/
BufferPool[FIRST_TX_BUF+2][0] = (STADDR%256); /* Load the low byte first */
BufferPool[FIRST_TX_BUF+2][1] = (STADDR/256); /* Load the high byte */
for (index = 2; index < BUFFER_SIZE; index++)
{
BufferPool[FIRST_TX_BUF+2][index] = 0x00;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -