/*****************************************************************************
* FILENAME: smc.c
*
* DESCRIPTION:
*
* The code in this module provides echo capability on SMC1. It's
* intent is to provide the beginnings of a debug port that is
* mostly compiler independent. If an ASCII terminal is connected
* at 38400, N, 8, 1 on port 2(PB3) on the ADS board with no hardware
* control, characters typed on the keyboard will be received by
* SMC1 and echoed back out the RS232 port to the ASCII terminal.
* This function was designed and tested on an ADS850 development board.
* Note that if a different baud rate is required, there is a header
* file on the netcomm website under the General Software category
* that is labelled "Asynchronous Baud Rate Tables".
* REFERENCES:
*
* 1)MPC850 Users Manual
*
* HISTORY:
*
* 15 Dec 2007 steven initial release
*
*------------------------------------------------------------------------------*/
#include "vxWorks.h"
#include "ppc860Siu.h"
#include "ppc860Cpm.h"
#include "ppc860Sio.h"
#include "smc.h"
/*--------------------
* Global definition *
*-------------------*/
int RxIndex = 0; /* the index of next receive BD */
UINT32 immBase; /* the base of internal memory map */
LB *Smc1Buffer; /* Rx and Tx Buffer*/
BDRINGS *RxTxBD; /* Rx and Tx BD */
/*----------------------
* Routine Declaration *
*----------------------*/
void SMC1Init();
void InitBDs();
UBYTE Smc1Poll();
void EchoChar();
UBYTE Smc1GetChar();
void Smc1PutChar(UBYTE ch);
/*---------------
* get the immr *
*--------------*/
UINT32 GetIMMR()
{
__asm__("mfspr 3, 638");
__asm__("rlwinm 3, 3, 0, 0, 15");
}
/* the beginning of the program */
int main()
{
immBase = GetIMMR();
/* set Rx and Tx BD to dpr */
RxTxBD = (BDRINGS *)(immBase + 0x2000 + 64);
/* set Rx and Tx Buffers to dpr */
Smc1Buffer = (LB *)(immBase + 0x2000 + 64 + sizeof(BDRINGS) + 64);
SMC1Init();
while (1)
{
if (Smc1Poll())
EchoChar();
}
return 0;
}
/* initiate SMC1 to UART */
void SMC1Init()
{
/* set SDMA's RAID */
*MPC860_SDCR(immBase) = SDCR_RAID_BR5; /* set RISC arbitrator ID field to U-bus priority 5 */
/* set PBPAR's SMRxD1 and SMTxD1 */
*MPC860_PBPAR(immBase) |= 0xc0; /* set pb24, 25 peripheral function */
*MPC860_PBDIR(immBase) &= 0xf33f; /* peripheral function 0, 25 SMTXD1, 24 SMRXD1 */
/* set BRGC3's CD 48M / (16 * 38400) - 1 = 77 */
/* *MPC860_BRGC3(immBase) &= 0xFFFFE001; /* enable BRGC3 and set CD 1249(asynchronize) */
/* *MPC860_BRGC3(immBase) |= (48000000/(38400 * 16)) << 1;
/* set SIMODE's SMC1CS */
*MPC860_SIMODE(immBase) = 0x00002000; /* set to non multiple mode */
*MPC860_SIMODE(immBase) &= 0xFFFF8FFF;
/* *MPC860_SIMODE(immBase) |= MPC860_SIMODE_SMC1_BRG3; /* connect to brg3 */
*SMC_RBASE(immBase + 0x3e80) = (UHWORD) RxTxBD->RxBD; /* set SMC1 rBD */
*SMC_TBASE(immBase + 0x3e80) = (UHWORD) &RxTxBD->TxBD; /* set SMC1 tBD */
/* set SMC1 Parameter RAM's TFCR */
*SMC_RFCR(immBase + 0x3e80) = 0x10; /* ppc big endian mode */
*SMC_TFCR(immBase + 0x3e80) = 0x10; /* ppc big endian mode */
/* set CPCR */
*MPC860_CPCR(immBase) = 0x0091 ;
/* set UART parameter BRKLN */
*SMC_MRBLR(immBase + 0x3e80) = 1;
*SMC_MAX_IDL(immBase + 0x3e80) = 0; /*set last received break length 0*/
*SMC_BRKEC(immBase + 0x3e80) = 0; /* */
*SMC_BRKCR(immBase + 0x3e80) = 1; /* */
InitBDs();
/* initial event register SMCE1 */
*MPC860_SMCE1(immBase) = 0xff;
/* initial mask register SMCM1 */
*MPC860_SMCM1(immBase) = 0x17;
/* configure CP interrup register */
*MPC860_CICR(immBase) = 0;
/* clear all pending interrupt events*/
*MPC860_CIPR(immBase) = 0xffffffff;
/* initial interrupt register CIMR */
*MPC860_CIMR(immBase) |= 0x10;
/*------------------------------------*/
/* 8-bit mode, no parity, 1 stop-bit */
/* UART SMC Mode */
/* Normal operation (no loopback), */
/* SMC Transmitter/Receiver Enabled */
/*------------------------------------*/
*MPC860_SMCMR1(immBase) = 0x4820;
*MPC860_SMCMR1(immBase) = 0x4823;
}
/* initiate Rx and Tx BD */
void InitBDs()
{
int i;
for(i = 0; i < SIZE; i++)
{
/* set RxBD to empty */
RxTxBD->RxBD[i].status = 0x8000;
RxTxBD->RxBD[i].length = 1;
RxTxBD->RxBD[i].addr =(UBYTE *) &(Smc1Buffer->RxBuffer[i]);
}
/* set wrap bit */
RxTxBD->RxBD[SIZE - 1].status = 0xa000;
/* set wrap bit */
RxTxBD->TxBD.status = 0x2000;
RxTxBD->TxBD.length = 1;
RxTxBD->TxBD.addr =(UBYTE *) &(Smc1Buffer->TxBuffer);
}
/* poll the receive buffer */
UBYTE Smc1Poll()
{
if (RxTxBD->RxBD[RxIndex].status & 0x8000)
return 0;
else
return 1;
}
/* receive and transmit char */
void EchoChar()
{
UBYTE data;
data = Smc1GetChar();
Smc1PutChar(data);
}
/* receive char continuously */
UBYTE Smc1GetChar()
{
UBYTE ch;
while(RxTxBD->RxBD[RxIndex].status & 0x8000)
{
}
ch = *(RxTxBD->RxBD[RxIndex].addr);
RxTxBD->RxBD[RxIndex].status |= 0x8000;
RxIndex = (RxIndex + 1) % SIZE;
return ch;
}
/* transmit char */
void Smc1PutChar(UBYTE ch)
{
while(RxTxBD->TxBD.status & 0x8000)
{
}
*(RxTxBD->TxBD.addr) = ch;
RxTxBD->TxBD.length = 1;
RxTxBD->TxBD.status |= 0x8000;
}