📄 uarthw_c55xx_mcbsp.c
字号:
/*
* Copyright 2003 by Texas Instruments Incorporated.
* All rights reserved. Property of Texas Instruments Incorporated.
* Restricted rights to use, duplicate or disclose this code are
* granted through contract.
*
*/
/* "@(#) DDK 1.11.00.00 11-04-03 (ddk-b13)" */
/*
* ======== uarthw_c55xx_mcbsp.c ========
*/
#include <std.h>
#include <hwi.h>
#include <iom.h>
#include <csl_mcbsp.h>
#include <csl_irq.h>
#include <csl_dma.h>
#include <uarthw_mcbsp.h>
static Int setupDma(MdUns *rxBuf, MdUns *txBuf, UARTHW_MCBSP_Params *params);
static Int setupMcbsp(UARTHW_MCBSP_Params *params);
static void enable(MdUns *txBuf);
static void rxIsr(void);
static void txIsr(void);
static MCBSP_Handle hMcbsp;
static DMA_Handle hDmaRx;
static DMA_Handle hDmaTx;
UARTHW_MCBSP_Params defaultParams = {
MCBSP_PORT0, /* mcbspId */
DMA_CHA4, /* dmaRxId */
DMA_CHA5, /* dmaTxId */
200000000, /* mcbspClkIn (200MHz)*/
115200, /* baud rate */
{
{
UARTHW_MCBSP_IER_MASK_DEFAULT,
UARTHW_MCBSP_IER_MASK_DEFAULT
},
{
UARTHW_MCBSP_IER_MASK_DEFAULT,
UARTHW_MCBSP_IER_MASK_DEFAULT
}
}
};
/*
* ======== UARTHW_MCBSP_start ========
*/
Int UARTHW_MCBSP_start(MdUns *rxBuf, MdUns *txBuf,
UARTHW_MCBSP_Params *params)
{
Int status;
Int rxId, txId;
HWI_Attrs hwiAttrs;
if (params == NULL) {
params = &defaultParams;
}
status = setupMcbsp(params);
if (status < 0) {
return (status);
}
status = setupDma(rxBuf, txBuf, params);
if (status < 0) {
return (status);
}
/* Obtain Interrupt IDs for Tx and Rx DMAs */
rxId = DMA_getEventId(hDmaRx);
txId = DMA_getEventId(hDmaTx);
/* plug in the ISR */
hwiAttrs.ier0mask = params->intrMask.rxIerMask[0];
hwiAttrs.ier1mask = params->intrMask.rxIerMask[1];
hwiAttrs.arg = NULL;
HWI_dispatchPlug(rxId, (Fxn)rxIsr, &hwiAttrs);
hwiAttrs.ier0mask = params->intrMask.txIerMask[0];
hwiAttrs.ier1mask = params->intrMask.txIerMask[1];
HWI_dispatchPlug(txId, (Fxn)txIsr, &hwiAttrs);
IRQ_enable(rxId);
IRQ_enable(txId);
enable(txBuf);
return (IOM_COMPLETED);
}
/*
* ======== setupDma =======
*/
static Int setupDma(MdUns *rxBuf, MdUns *txBuf, UARTHW_MCBSP_Params *params)
{
Uns dmaTxSynEvt, dmaRxSynEvt;
Uint32 dmaTxDest, dmaRxSrc;
LgUns tempAdd;
DMA_Config dmaTxCfg; /* Tx Config Structure */
DMA_Config dmaRxCfg; /* Rx Config Structure */
DMA_FSET(DMAGCR,FREE,0);
hDmaRx = DMA_open(params->dmaRxId,DMA_OPEN_RESET);
hDmaTx = DMA_open(params->dmaTxId,DMA_OPEN_RESET);
//Initialize structures
DMA_getConfig(hDmaRx, &dmaRxCfg);
DMA_getConfig(hDmaTx, &dmaTxCfg);
//Tx Side DMA specific configuration
dmaTxCfg.dmacsdp =
DMA_FMK(DMACSDP,DST,DMA_DMACSDP_DST_PERIPH) |
DMA_FMK(DMACSDP,SRC,DMA_DMACSDP_SRC_DARAM) |
DMA_FMK(DMACSDP,DATATYPE,DMA_DMACSDP_DATATYPE_16BIT) ;
dmaTxCfg.dmaccr =
DMA_FMK(DMACCR,DSTAMODE,DMA_DMACCR_DSTAMODE_CONST) |
DMA_FMK(DMACCR,SRCAMODE,DMA_DMACCR_SRCAMODE_POSTINC) |
DMA_FMK(DMACCR,ENDPROG,DMA_DMACCR_ENDPROG_OFF) |
DMA_FMK(DMACCR,REPEAT,DMA_DMACCR_REPEAT_ON) |
DMA_FMK(DMACCR,AUTOINIT,DMA_DMACCR_AUTOINIT_ON) |
DMA_FMK(DMACCR,EN,DMA_DMACCR_EN_STOP) |
DMA_FMK(DMACCR,PRIO,DMA_DMACCR_PRIO_HI) |
DMA_FMK(DMACCR,FS,DMA_DMACCR_FS_DISABLE) ;
dmaTxCfg.dmacicr =
DMA_FMK(DMACICR,HALFIE,DMA_DMACICR_HALFIE_ON) |
DMA_FMK(DMACICR,FRAMEIE,DMA_DMACICR_FRAMEIE_ON) ;
dmaTxCfg.dmacfi = 0x0000;
dmaTxCfg.dmacei = 0x0000;
dmaTxCfg.dmacen = 2 * UARTHW_MCBSP_TxPKTBITS;
dmaTxCfg.dmacfn = 1;
/* Rx Side DMA specific configuration */
dmaRxCfg.dmacsdp =
DMA_FMK(DMACSDP,DST,DMA_DMACSDP_DST_DARAM) |
DMA_FMK(DMACSDP,SRC,DMA_DMACSDP_SRC_PERIPH) |
DMA_FMK(DMACSDP,DATATYPE,DMA_DMACSDP_DATATYPE_16BIT) ;
dmaRxCfg.dmaccr =
DMA_FMK(DMACCR,DSTAMODE,DMA_DMACCR_DSTAMODE_POSTINC) |
DMA_FMK(DMACCR,SRCAMODE,DMA_DMACCR_SRCAMODE_CONST) |
DMA_FMK(DMACCR,ENDPROG,DMA_DMACCR_ENDPROG_OFF) |
DMA_FMK(DMACCR,REPEAT,DMA_DMACCR_REPEAT_ON) |
DMA_FMK(DMACCR,AUTOINIT,DMA_DMACCR_AUTOINIT_ON) |
DMA_FMK(DMACCR,EN,DMA_DMACCR_EN_STOP) |
DMA_FMK(DMACCR,PRIO,DMA_DMACCR_PRIO_HI) |
DMA_FMK(DMACCR,FS,DMA_DMACCR_FS_DISABLE) ;
dmaRxCfg.dmacicr =
DMA_FMK(DMACICR,HALFIE,DMA_DMACICR_HALFIE_ON) |
DMA_FMK(DMACICR,FRAMEIE,DMA_DMACICR_FRAMEIE_ON) ;
dmaRxCfg.dmacfi = 0x0;
dmaRxCfg.dmacei = 0x0;
dmaRxCfg.dmacen = 2 * UARTHW_MCBSP_RxPKTBITS;
dmaRxCfg.dmacfn = 1;
//Check to see which MCBSP port is being used
if (params->mcbspId == MCBSP_PORT2) {
dmaRxSynEvt = DMA_DMACCR_SYNC_REVT2;
dmaTxSynEvt = DMA_DMACCR_SYNC_XEVT2;
dmaTxDest = MCBSP_ADDR(DXR12) << 1;
dmaRxSrc = MCBSP_ADDR(DRR12) << 1;
}
else if (params->mcbspId == MCBSP_PORT1) {
dmaRxSynEvt = DMA_DMACCR_SYNC_REVT1;
dmaTxSynEvt = DMA_DMACCR_SYNC_XEVT1;
dmaTxDest = MCBSP_ADDR(DXR11) << 1;
dmaRxSrc = MCBSP_ADDR(DRR11) << 1;
}
else {
dmaRxSynEvt = DMA_DMACCR_SYNC_REVT0;
dmaTxSynEvt = DMA_DMACCR_SYNC_XEVT0;
dmaTxDest = MCBSP_ADDR(DXR10) << 1;
dmaRxSrc = MCBSP_ADDR(DRR10) << 1;
}
if (hDmaTx == INV || hDmaRx == INV) {
return (IOM_EBADIO);
}
/* Setup Tx Side addresses based on MCBSP port */
dmaTxCfg.dmacdsal = (DMA_AdrPtr)(dmaTxDest & 0xFFFF);
dmaTxCfg.dmacdsau = ((dmaTxDest >> 15) & 0xFFFF);
/* Need '<< 1' for byte addressing */
tempAdd = (LgUns)(&txBuf[0]) << 1;
dmaTxCfg.dmacssal = (DMA_AdrPtr)(tempAdd & 0xFFFF);
dmaTxCfg.dmacssau = ((tempAdd >> 15) & 0xFFFF);
dmaTxCfg.dmaccr |=
DMA_FMK(DMACCR,SYNC,dmaTxSynEvt);
DMA_config(hDmaTx,&dmaTxCfg);
/* Setup Rx Side addresses based on MCBSP port */
dmaRxCfg.dmacssal = (DMA_AdrPtr)(dmaRxSrc & 0xFFFF);
dmaRxCfg.dmacssau = ((dmaRxSrc >> 15) & 0xFFFF);
/* Need '<< 1' for byte addressing */
tempAdd = (LgUns)(&rxBuf[0]) << 1;
dmaRxCfg.dmacdsal = (DMA_AdrPtr)(tempAdd & 0xFFFF);
dmaRxCfg.dmacdsau = ((tempAdd >> 15) & 0xFFFF);
dmaRxCfg.dmaccr |=
DMA_FMK(DMACCR,SYNC,dmaRxSynEvt);
DMA_config(hDmaRx,&dmaRxCfg);
/* Configure DMA to be free running */
DMA_FSET(DMAGCR,FREE,1);
return(IOM_COMPLETED);
}
/*
* ======== setupMcbsp ========
* This function is used to setup the McBSP port chosen with the initial
* settings based on parity, stopbits, databits,baudrates chosen.
*/
static Int setupMcbsp(UARTHW_MCBSP_Params *params)
{
Uns clkdv;
MCBSP_Config mcbspCfg; /*MCBSP Config Structure*/
hMcbsp = MCBSP_open(params->mcbspId, MCBSP_OPEN_RESET);
if (hMcbsp == INV) {
return (IOM_EBADIO);
}
/* Initialize MCBSP Structure */
MCBSP_getConfig(hMcbsp, &mcbspCfg);
/* Setup MCBSP Regs */
mcbspCfg.pcr =
MCBSP_FMK(PCR,XIOEN,MCBSP_PCR_XIOEN_SP) |
MCBSP_FMK(PCR,RIOEN,MCBSP_PCR_RIOEN_SP) |
MCBSP_FMK(PCR,FSXM,MCBSP_PCR_FSXM_INTERNAL) |
MCBSP_FMK(PCR,FSRM,MCBSP_PCR_FSRM_EXTERNAL) |
MCBSP_FMK(PCR,CLKXM,MCBSP_PCR_CLKXM_OUTPUT) |
MCBSP_FMK(PCR,CLKRM,MCBSP_PCR_CLKRM_OUTPUT) |
MCBSP_FMK(PCR,DXSTAT,MCBSP_PCR_DXSTAT_0) |
MCBSP_FMK(PCR,FSXP,MCBSP_PCR_FSXP_ACTIVELOW) |
MCBSP_FMK(PCR,FSRP,MCBSP_PCR_FSRP_ACTIVELOW) |
MCBSP_FMK(PCR,CLKXP,MCBSP_PCR_CLKXP_RISING) |
MCBSP_FMK(PCR,CLKRP,MCBSP_PCR_CLKRP_FALLING) ;
/*
* Here we compute the bit rate of the McBSP. Each UART bit is
* represented by 16 McBSP bits.
*/
clkdv = (Uns)(params->mcbspClkIn / (params->baud * 16));
/* clkdv is max 8-bits long, so make sure we didn't overflow ... */
if (clkdv > 0xff) {
return (IOM_EBADARGS);
}
mcbspCfg.srgr1 =
MCBSP_FMK(SRGR1,CLKGDV,MCBSP_SRGR1_CLKGDV_OF(clkdv)) |
MCBSP_FMK(SRGR1,FWID,MCBSP_SRGR1_FWID_OF(0)) ;
mcbspCfg.srgr2 =
MCBSP_FMK(SRGR2,GSYNC,MCBSP_SRGR2_GSYNC_FREE) |
MCBSP_FMK(SRGR2,CLKSP,MCBSP_SRGR2_CLKSP_RISING) |
MCBSP_FMK(SRGR2,CLKSM,MCBSP_SRGR2_CLKSM_INTERNAL) |
MCBSP_FMK(SRGR2,FSGM,MCBSP_SRGR2_FSGM_DXR2XSR) ;
//Want DUAL Phase to account for Half stop bits
mcbspCfg.xcr1 =
MCBSP_FMK(XCR1,XFRLEN1,MCBSP_XCR1_XFRLEN1_OF(8)) |
MCBSP_FMK(XCR1,XWDLEN1,MCBSP_XCR1_XWDLEN1_16BIT) ;
mcbspCfg.xcr2 =
MCBSP_FMK(XCR2,XPHASE,MCBSP_XCR2_XPHASE_DUAL) |
MCBSP_FMK(XCR2,XFRLEN2,MCBSP_XCR2_XFRLEN2_OF(1)) |
MCBSP_FMK(XCR2,XWDLEN2,MCBSP_XCR2_XWDLEN2_8BIT) |
MCBSP_FMK(XCR2,XCOMPAND,MCBSP_XCR2_XCOMPAND_MSB) |
MCBSP_FMK(XCR2,XFIG,MCBSP_XCR2_XFIG_NO) |
MCBSP_FMK(XCR2,XDATDLY,MCBSP_XCR2_XDATDLY_0BIT) ;
mcbspCfg.rcr1 =
MCBSP_FMK(RCR1,RFRLEN1,MCBSP_RCR1_RFRLEN1_OF(8)) |
MCBSP_FMK(RCR1,RWDLEN1,MCBSP_RCR1_RWDLEN1_16BIT) ;
mcbspCfg.rcr2 =
MCBSP_FMK(RCR2,RPHASE,MCBSP_RCR2_RPHASE_DUAL) |
MCBSP_FMK(RCR2,RFRLEN2,MCBSP_RCR2_RFRLEN2_OF(0)) |
MCBSP_FMK(RCR2,RWDLEN2,MCBSP_RCR2_RWDLEN2_8BIT) |
MCBSP_FMK(RCR2,RCOMPAND,MCBSP_RCR2_RCOMPAND_MSB) |
MCBSP_FMK(RCR2,RFIG,MCBSP_RCR2_RFIG_NO) |
MCBSP_FMK(RCR2,RDATDLY,MCBSP_RCR2_RDATDLY_1BIT) ;
mcbspCfg.spcr1 =
MCBSP_FMK(SPCR1,DLB,MCBSP_SPCR1_DLB_OFF) |
MCBSP_FMK(SPCR1,RJUST,MCBSP_SPCR1_RJUST_RZF) |
MCBSP_FMK(SPCR1,CLKSTP,MCBSP_SPCR1_CLKSTP_DISABLE) |
MCBSP_FMK(SPCR1,DXENA,MCBSP_SPCR1_DEFAULT) |
MCBSP_FMK(SPCR1,RINTM,MCBSP_SPCR1_RINTM_RRDY) |
MCBSP_FMK(SPCR1,RRST,MCBSP_SPCR1_RRST_DISABLE) ;
mcbspCfg.spcr2 =
MCBSP_FMK(SPCR2,FREE,MCBSP_SPCR2_FREE_NO) |
MCBSP_FMK(SPCR2,SOFT,MCBSP_SPCR2_SOFT_YES) |
MCBSP_FMK(SPCR2,FRST,MCBSP_SPCR2_DEFAULT) |
MCBSP_FMK(SPCR2,GRST,MCBSP_SPCR2_DEFAULT) |
MCBSP_FMK(SPCR2,XINTM, MCBSP_SPCR2_XINTM_XRDY) |
MCBSP_FMK(SPCR2,XSYNCERR,MCBSP_SPCR2_XSYNCERR_NO) ;
/* Assign structure to handle */
MCBSP_config(hMcbsp, &mcbspCfg);
return (IOM_COMPLETED);
}
/*
* ======== enable ========
* This function is used to enable the McBSP and start DMA
*/
static void enable(MdUns *txBuf)
{
/* Start transmit and receive DMA channels */
DMA_start(hDmaTx);
DMA_start(hDmaRx);
/* Start the MCBSP and Sample Rate Generator */
MCBSP_start(hMcbsp, MCBSP_SRGR_START, 0xFFFF);
/* Take MCBSP receive and transmit out of reset */
MCBSP_start(hMcbsp, MCBSP_XMIT_START | MCBSP_RCV_START, 0xFFFF);
}
/*
* ======== rxIsr ========
* This function will clear the DMA CSR and call the upper layer ISR
*/
static void rxIsr(void)
{
volatile Uns temp;
temp = DMA_RGETH(hDmaRx, DMACSR); /* DMA_RGET clears interrupt flag */
UARTHW_MCBSP_dmaRxIsr(); /* Calling the upper layer ISR */
}
/*
* ======== txIsr ========
* This function will clear the DMA CSR and call the upper layer ISR
*/
static void txIsr(void)
{
volatile Uns temp;
temp = DMA_RGETH(hDmaTx, DMACSR); /* DMA_RGET clears interrupt flag*/
UARTHW_MCBSP_dmaTxIsr(); /* Calling the upper layer ISR */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -