📄 quicc_smc2.c
字号:
//=============================================================================
//####UNSUPPORTEDBEGIN####
//
// -------------------------------------------
// This source file has been contributed to eCos/Red Hat. It may have been
// changed slightly to provide an interface consistent with those of other
// files.
//
// The functionality and contents of this file is supplied "AS IS"
// without any form of support and will not necessarily be kept up
// to date by Red Hat.
//
// The style of programming used in this file may not comply with the
// eCos programming guidelines. Please do not use as a base for other
// files.
//
// All inquiries about this file, or the functionality provided by it,
// should be directed to the 'ecos-discuss' mailing list (see
// http://ecos.sourceware.org/ecos/intouch.html for details).
//
// Contributed by: Kevin Hester <khester@opticworks.com>
// Maintained by: <Unmaintained>
// See also:
// Motorola's "Example Software Initializing the SMC as a UART" package
// (smc2.zip) at:
// http://www.mot.com/SPS/RISC/netcomm/tools/index.html#MPC860_table
// -------------------------------------------
//
//####UNSUPPORTEDEND####
//=============================================================================
/*-------------------------------------------------------------------------
* FILENAME: smc2.c
*
* DESCRIPTION:
*
* The code in this module provides echo capability on SMC2. It's
* intent is to provide the beginnings of a debug port that is
* mostly compiler independent. If an ASCII terminal is connected
* at 9600,N,8,1 on Port 2 (PB3) on the ADS board with no hardware
* control, characters typed on the keyboard will be received by
* SMC2 and echoed back out the RS232 port to the ASCII terminal.
* This function was designed and tested on an ADS860
* 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) MPC860 Users Manual
* 2) PowerPC Microprocessor Family: The Programming Environments for
* 32-Bit Microprocessors
*
* HISTORY:
*
* 27 APR 98 jay initial release
*
*-------------------------------------------------------------------------*/
#include <cyg/hal/quicc_smc2.h>
#include "ppc_860.h"
/***********************/
/* Global Declarations */
/***********************/
static EPPC *IMMR; /* IMMR base pointer */
static BDRINGS *RxTxBD; /* buffer descriptors base pointer */
static LB *SMC2Buffers; /* SMC2 base pointers */
/*---------------------*/
/* Function Prototypes */
/*---------------------*/
//static char SMC2Poll(void);
static void InitBDs(void);
//static void EchoChar(void);
static unsigned long GetIMMR(void);
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: cyg_smc2_init
*
* DESCRIPTION:
*
* EXTERNAL EFFECT:
*
* PARAMETERS: None
*
* RETURNS: None
*
*---------------------------------------------------------------------------*/
void cyg_smc2_init(unsigned long baudRate)
{
unsigned long *bcsr1;
unsigned long clockRate = 20 * 1000 * 1000; // 20Mhz
unsigned long divider = clockRate / (baudRate * 16) - 1;
/*------------------------*/
/* Establish IMMR pointer */
/*------------------------*/
IMMR = (EPPC *)(GetIMMR() & 0xFFFF0000); /* MPC8xx internal register
map */
/*-----------------------------------------------*/
/* Enable RS232 interface on ADS board via BCSR1 */
/* Get the base address of BCSR */
/*-----------------------------------------------*/
bcsr1 = (unsigned long *) ((IMMR->memc_br1 & 0xffff0000) + 4);
*bcsr1 &= ~(1 << 18); // turn on RS232 port 2
/*-----------------------*/
/* Allow SMC2 TX, RX out */
/*-----------------------*/
IMMR->pip_pbpar |= (0x0C00);
IMMR->pip_pbdir &= 0xF3FF;
/*------------------------------------------------*/
/* Set Baud Rate to 9600 for 40MHz System Clock. */
/* Enable BRG Count. */
/*------------------------------------------------*/
IMMR->brgc2 = ((divider << 1) | 0x10000);
IMMR->si_simode &= ~(0xF0000000); /* SCM2: NMSI mode */
IMMR->si_simode |= 0x10000000; /* SCM2: Tx/Rx Clocks are BRG2 */
/*--------------------*/
/* Initialize the BDs */
/*--------------------*/
InitBDs(); /* before setting up info depending on RxTxBD below */
IMMR->smc_regs[SMC2_REG].smc_smce = 0xFF; /* Clear any pending events */
/*----------------------------------------*/
/* Set RXBD table start at Dual Port +800 */
/*----------------------------------------*/
IMMR->PRAM[PAGE4].pg.other.smc_dsp2.psmc2.u2.rbase = (unsigned short) (unsigned) &RxTxBD->RxBD;
/*----------------------------------------*/
/* Set TXBD table start at Dual Port +808 */
/*----------------------------------------*/
IMMR->PRAM[PAGE4].pg.other.smc_dsp2.psmc2.u2.tbase = (unsigned short) (unsigned) &RxTxBD->TxBD;
/*--------------------------------------*/
/* Set RFCR,TFCR -- Rx,Tx Function Code */
/* Normal Operation and Motorola byte */
/* ordering */
/*--------------------------------------*/
IMMR->PRAM[PAGE4].pg.other.smc_dsp2.psmc2.u2.rfcr = 0x18;
IMMR->PRAM[PAGE4].pg.other.smc_dsp2.psmc2.u2.tfcr = 0x18;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Protocol Specific Parameters */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*---------------------------*/
/* MRBLR = MAX buffer length */
/*---------------------------*/
IMMR->PRAM[PAGE4].pg.other.smc_dsp2.psmc2.u2.mrblr = 1;
/*------------------------------------*/
/* MAX_IDL = Disable MAX Idle Feature */
/*------------------------------------*/
IMMR->PRAM[PAGE4].pg.other.smc_dsp2.psmc2.u2.max_idl = 0;
/*-------------------------------------*/
/* BRKEC = No break condition occurred */
/*-------------------------------------*/
IMMR->PRAM[PAGE4].pg.other.smc_dsp2.psmc2.u2.brkec = 0;
/*---------------------------------------*/
/* BRKCR = 1 break char sent on top XMIT */
/*---------------------------------------*/
IMMR->PRAM[PAGE4].pg.other.smc_dsp2.psmc2.u2.brkcr = 1;
/* InitBDs() used to be here - no harm in doing this again */
IMMR->smc_regs[SMC2_REG].smc_smce = 0xFF; /* Clear any pending events */
/*--------------------------------------------------*/
/* SMC_SMCM = Mask all interrupts, use polling mode */
/*--------------------------------------------------*/
IMMR->smc_regs[SMC2_REG].smc_smcm = 0;
IMMR->cpmi_cicr = 0; /* Disable all CPM interrups */
IMMR->cpmi_cipr = 0xFFFFFFFF; /* Clear all pending interrupt events */
IMMR->cpmi_cimr = 0; /* Mask all event interrupts */
/*------------------------------------*/
/* 8-bit mode, no parity, 1 stop-bit */
/* UART SMC Mode */
/* Normal operation (no loopback), */
/* SMC Transmitter/Receiver Enabled */
/*------------------------------------*/
IMMR->smc_regs[SMC2_REG].smc_smcmr = 0x4823;
/*---------------------------------------*/
/* Initialize Rx and Tx Params for SMC2: */
/* Spin until cpcr flag is cleared */
/*---------------------------------------*/
for(IMMR->cp_cr = 0x00d1; IMMR->cp_cr & 0x0001;) ;
}
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: InitBDs
*
* DESCRIPTION: This function initializes the Tx and Rx Buffer Descriptors.
*
* EXTERNAL EFFECT: RxTxBD
*
* PARAMETERS: None
*
* RETURNS: None
*
*---------------------------------------------------------------------------*/
static void InitBDs(void)
{
/*--------------------------------------------------------------------*/
/* We add 64 bytes to the start of the buffer descriptors because */
/* this code was also tested on the monitor version of SDS debugger. */
/* The monitor program on our target uses 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. */
/*--------------------------------------------------------------------*/
/*----------------------------------*/
/* Get pointer to BD area on DP RAM */
/*----------------------------------*/
RxTxBD = (BDRINGS *)(IMMR->qcp_or_ud.ud.udata_bd + 64);
/*-------------------------------------------------------------------*/
/* Establish the buffer pool in Dual Port RAM. We do this because the*/
/* pool size is only 2 bytes (1 for Rx and 1 for Tx) and to avoid */
/* disabling data cache for the memory region where BufferPool would */
/* reside. The CPM does not recognize data in buffer pools once it */
/* been cached. It's acesses are direct through DMA to external */
/* memory. */
/*-------------------------------------------------------------------*/
SMC2Buffers = (LB *)(IMMR->qcp_or_ud.ud.udata_bd + 80);
/*-----------------------------------*/
/* Setup Receiver Buffer Descriptors */
/*-----------------------------------*/
RxTxBD->RxBD.bd_cstatus = 0xA000; /* Enable, Last BD */
RxTxBD->RxBD.bd_length = 1;
RxTxBD->RxBD.bd_addr = &(SMC2Buffers->RxBuffer);
/*--------------------------------------*/
/* Setup Transmitter Buffer Descriptors */
/*--------------------------------------*/
RxTxBD->TxBD.bd_cstatus = 0x2000; /* Buffer not yet ready; Last BD */
RxTxBD->TxBD.bd_length = 1;
RxTxBD->TxBD.bd_addr = &(SMC2Buffers->TxBuffer);
} /* END InitBDs */
#if 0 // static unused function. -jskov 19990122
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: EchoChar
*
* DESCRIPTION: This function facilitates the echoing of a received character.
*
* EXTERNAL EFFECT: RxTxBD
*
* PARAMETERS: None
*
* RETURNS: None
*
*---------------------------------------------------------------------------*/
static void EchoChar(void)
{
char mych;
mych = cyg_smc2_getchar();
cyg_smc2_putchar(mych);
} /* end EchoChar */
#endif
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: cyg_smc2_putchar
*
* DESCRIPTION: Output a character to SMC2
*
* EXTERNAL EFFECT: RxTxBD
*
* PARAMETERS: ch - input character
*
* RETURNS: None
*
*---------------------------------------------------------------------------*/
void cyg_smc2_putchar(char ch)
{
/*-----------------------------------*/
/* Loop until transmission completed */
/*-----------------------------------*/
while (RxTxBD->TxBD.bd_cstatus & 0x8000);
/*------------*/
/* Store data */
/*------------*/
*(RxTxBD->TxBD.bd_addr) = ch;
RxTxBD->TxBD.bd_length = 1;
/*---------------*/
/* Set Ready bit */
/*---------------*/
RxTxBD->TxBD.bd_cstatus |= 0x8000;
}
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: cyg_smc2_getchar
*
* DESCRIPTION: Get a character from SMC2
*
* EXTERNAL EFFECT: RxTxBD
*
* PARAMETERS: NONE
*
* RETURNS: A character from SMC2
*
*---------------------------------------------------------------------------*/
char cyg_smc2_getchar(void)
{
char ch; /* output character from SMC2 */
/*--------------------*/
/* Loop if RxBD empty */
/*--------------------*/
while (RxTxBD->RxBD.bd_cstatus & 0x8000);
/*--------------*/
/* Receive data */
/*--------------*/
ch = *(RxTxBD->RxBD.bd_addr);
/*----------------------*/
/* Set Buffer Empty bit */
/*----------------------*/
RxTxBD->RxBD.bd_cstatus |= 0x8000;
return ch;
}
#if 0 // static unused function. -jskov 19990122
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: SMC2Poll
*
* DESCRIPTION: Poll SMC2 RxBD and check to see if a character was received
*
* EXTERNAL EFFECT: NONE
*
* PARAMETERS: NONE
*
* RETURNS: A one if there is a character available in the receive buffer,
* else zero.
*
*---------------------------------------------------------------------------*/
static char SMC2Poll(void)
{
return (RxTxBD->RxBD.bd_cstatus & 0x8000) ? 0 : 1;
} /* END SMC2Poll */
#endif
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: GetIMMR
*
* DESCRIPTION: Returns current value in the IMMR register.
*
* EXTERNAL EFFECT: NONE
*
* PARAMETERS: NONE
*
* RETURNS: The IMMR value in r3. The compiler uses r3 as the register
* containing the return value.
*
*---------------------------------------------------------------------------*/
static unsigned long GetIMMR(void)
{
unsigned long ret;
asm volatile (" mfspr %0,638 " : "=r" (ret)); /* IMMR is spr #638 */
return ret;
}
/* EOF hal/powerpc/fads/quicc_smc2.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -