📄 uart485.c
字号:
#include "board.h"
#include "sdev.h"
#include "bspspec.h"
#include "uart485.h"
#ifndef EN_485RECV
#error Must define EN_485RECV in xxx8xx.h
#endif
#ifndef EN_485SEND
#error Must define EN_485SEND in xxx8xx.h
#endif
/* Rx BD Flags */
#define UART_RX_CON (1<<(15-4))
#define UART_RX_ADDRESS (1<<(15-5))
#define UART_RX_ID (1<<(15-7))
#define UART_RX_AM (1<<(15-8))
#define UART_RX_BR (1<<(15-10))
#define UART_FRAME_ERR (1<<(15-11))
#define UART_PARITY_ERR (1<<(15-12))
#define UART_OVERRUN (1<<(15-14))
#define UART_CD_ERR (1<<(15-15))
/* Tx BD Flags */
#define UART_TX_CR (1<<(15-4))
#define UART_TX_ADDRESS (1<<(15-5))
#define UART_PREAMBLE (1<<(15-7))
#define UART_TX_NS (1<<(15-8))
//#define BD_LAST (1 << (15-4))
#define SCCM_GLR (1L<<(15-3))
#define SCCM_GLT (1L<<(15-4))
#define SCCM_AB (1L<<(15-6))
#define SCCM_IDL (1L<<(15-7))
#define SCCM_GRA (1L<<(15-8))
#define SCCM_BRKE (1L<<(15-9))
#define SCCM_BRKS (1L<<(15-10))
#define SCCM_CCR (1L<<(15-12))
#define SCCM_BSY (1L<<(15-13))
#define SCCM_TX (1L<<(15-14))
#define SCCM_RX (1L)
#define NORMAL_UART 0x0
#define MANUL_MULTI 0x0400
#define AUTO_MULTI 0x0c00
/* #define PARITY_EN 0x0010 */
#define PARITY_NO 0
#define RECV_ODD 0
#define RECV_LOW 0x4
#define RECV_EVEN 0x8
#define RECV_HIGH 0xc
#define SEND_ODD 0
#define SEND_LOW 0x1
#define SEND_EVEN 0x2
#define SEND_HIGH 0x3
#ifdef param
#undef param
#endif
#ifdef regs
#undef regs
#endif
#define param(ch) (pda->pram[ch].scc.pscc.u)
#define regs(ch) (pda->Scc_regs[ch])
static void SccUartStopOp(SccUart485CfgStruct *pCfg)
{
PDA *pda= (PDA *)(GetIMMR() & IO_MAP_MASK);
CPM_CMD(STOP_TX|((pCfg->ch*4)<<4));
regs(pCfg->ch).scc_gsmra&=~0x00000030;/*disable tx_rx*/
}
static void SccUartStartOp(SccUart485CfgStruct *pCfg)
{
PDA *pda= (PDA *)(GetIMMR() & IO_MAP_MASK);
CPM_CMD(INIT_RX_TX_PARAMS|((pCfg->ch*4)<<4));
regs(pCfg->ch).scc_gsmra |= 0x00000030;/*enable tx_rx*/
}
static void SccUartClearBuf(DataBufStruct *pData)
{
int i;
pData->CurRecvBD=pData->CurSendBD=0;
for(i=0;i<pData->MaxRecvBD;i++)
pData->pBaseRecvBD[i].status = BD_EMPTY|BD_INTR;
if(i>0)pData->pBaseRecvBD[i-1].status |= BD_WRAP;
for(i=0;i<pData->MaxSendBD;i++)
pData->pBaseSendBD[i].status = BD_INTR|BD_LAST;
if(i>0)pData->pBaseSendBD[i-1].status |= BD_WRAP;
}
static void SccUartIsr(void* pDataBuf)
{
USHORT starBD,tempstate;
USHORT Events;
PDA *pda=(PDA *)(GetIMMR() & IO_MAP_MASK);
DataBufStruct *pData=(DataBufStruct *)pDataBuf;
SccUart485CfgStruct *pCfg =(SccUart485CfgStruct *)(pData+1);
Events = regs(pCfg->ch).scc_scce;
regs(pCfg->ch).scc_scce = Events;
if((Events & SCCM_BRKS) || (Events & SCCM_BSY )
|| (Events & SCCM_RX))
{
pData->DrvInfo.TotalRecvInt++;
if( (pData->RecvEv!=NULL) && (pData->RecvTid!=NULL) )
{
ev_send(pData->RecvTid,pData->RecvEv);
}
}
if (Events & SCCM_TX)
{
pData->DrvInfo.TotalSendInt++;
if( (pData->SendEv!=NULL) && (pData->SendTid!=NULL) )
{
ev_send(pData->SendTid,pData->SendEv);
}
#ifdef EN_485RECV
EN_485RECV;
#endif
}
}/* End of UartIsr */
static void SccUartInit(void *pDataBuf, SccUart485CfgStruct *cfg )
{
ULONG tt;
int i,clkdiv;
USHORT temp_ushort;
BuffDescType *temp_bufdes;
char *pRecvBuf,*pSendBuf;
PDA *pda = (PDA *)(GetIMMR() & IO_MAP_MASK);
DataBufStruct* pData=(DataBufStruct *)pDataBuf;
SccUart485CfgStruct* pCfg =(SccUart485CfgStruct *)(pData+1);
int BrgClk=BspCpuClkRate()*1000000;
/*-------------------------<< Initial data >>-------------------------------*/
memmove(pCfg,cfg,sizeof(*cfg));
memset(pData, 0, sizeof(DataBufStruct));
pCfg->ch=(cfg->ch&0x3);
pData->MaxRecvBD=pCfg->MaxRecvBD;
pData->MaxSendBD=pCfg->MaxSendBD;
pData->MaxBufLen=pCfg->MaxSendBufLen;
pData->RecvErrMask=UART_FRAME_ERR|UART_PARITY_ERR|UART_OVERRUN|UART_CD_ERR;
pData->SendErrMask=0;
pData->UncachedBuffer=pRecvBuf=pCfg->UncachedBuffer;
pSendBuf=(char*)(pRecvBuf+( pData->MaxRecvBD)*(pCfg->MaxRecvBufLen));
/*-------------------------<< stop SCCx operation >>----------------------*/
SccUartStopOp(pCfg);
if(pCfg->BaudRate > BrgClk/16 )pCfg->BaudRate=BrgClk/16;
else if(pCfg->BaudRate < BrgClk/(16*16*4096))
pCfg->BaudRate=BrgClk/(256*4096);
clkdiv = (BspCpuClkRate()*1000000)/(16*pCfg->BaudRate) - 1;
if(clkdiv >= 4096)
clkdiv=(((BspCpuClkRate()*1000000)/(16*16*pCfg->BaudRate)-1)<<1) | 1;
else
clkdiv <<= 1;
*(&pda->brgc1+pCfg->BRG)|=(1L<<(31-14)); /*reset*//*brgclk=40MHZ */
*(&pda->brgc1+pCfg->BRG)=(1L<<(31-15))+clkdiv;
/*----------------------<< init SCCx >>-----------------------------------*/
param(pCfg->ch).mrblr=pCfg->MaxRecvBufLen;//pData->MaxBufLen;
param(pCfg->ch).rfcr=0x18;
param(pCfg->ch).tfcr=0x18;
param(pCfg->ch).max_idl=pCfg->MaxIdle; /* disable max idl function */
param(pCfg->ch).brkec=0;
param(pCfg->ch).brkcr=2; /* break counter */
param(pCfg->ch).parec=0;
param(pCfg->ch).frmer=0;
param(pCfg->ch).nosec=0;
param(pCfg->ch).uaddr1=pCfg->Uaddr1;
param(pCfg->ch).uaddr2=pCfg->Uaddr2;
for(i=0;i<8;param(pCfg->ch).cc[i]=0x8000,i++);
param(pCfg->ch).rccm=0xc0ff;
/* rx */
temp_ushort=(unsigned short)dpram_alloc(0,pData->MaxRecvBD*BD_LEN);
param(pCfg->ch).rbase = temp_ushort-0X2000;
temp_bufdes=pData->pBaseRecvBD=(BuffDescType *)((char *)pda + temp_ushort);
for(i=0;i<pData->MaxRecvBD;i++)
{
temp_bufdes[i].status=BD_EMPTY|BD_INTR;
temp_bufdes[i].length=0;
temp_bufdes[i].address=pRecvBuf+i*pCfg->MaxRecvBufLen;
}
if(i>0)temp_bufdes[i-1].status|=BD_WRAP;
/* tx */
temp_ushort=(unsigned short)dpram_alloc(0,pData->MaxSendBD*BD_LEN);
param(pCfg->ch).tbase = temp_ushort-0X2000;
temp_bufdes=pData->pBaseSendBD=(BuffDescType *)((char *)pda+temp_ushort);
for(i=0;i<pData->MaxSendBD;i++)
{
temp_bufdes[i].status=BD_INTR|UART_TX_CR;
temp_bufdes[i].length=pData->MaxBufLen;
temp_bufdes[i].address=pSendBuf+i*pData->MaxBufLen;
}
if(i>0)temp_bufdes[i-1].status|=BD_WRAP;
regs(pCfg->ch).scc_gsmra=0x00028004;
regs(pCfg->ch).scc_gsmrb=0x00000060;
regs(pCfg->ch).scc_psmr=0x3000|pCfg->UartMode|pCfg->Pen|pCfg->RecvPM|pCfg->SendPM;
regs(pCfg->ch).scc_scce=0xFFFF;
regs(pCfg->ch).scc_todr=0x0;
regs(pCfg->ch).scc_dsr=0x7e7E;
regs(pCfg->ch).scc_sccm=SCCM_BRKS|SCCM_BSY|SCCM_TX|SCCM_RX;
pda->dma_sdcr=1;
SPLX(pda->si_sicr &=( ~(0x3fL<<((pCfg->ch)*8)) );)
SPLX(pda->si_sicr|=(cfg->BRG*8+cfg->BRG)<<((pCfg->ch)*8);)
SPLX(pda->cpmi_cimr|=(EN_SCC1 >> pCfg->ch); )
SPLX(pda->cpmi_cipr|=(CLR_SCC1 >> pCfg->ch);)
SPLX(pda->cpmi_cicr|=CPM_EN_INTS|0x1b0000;)
SPLX(CpmIsrAddHandler(V_SCC1-pCfg->ch,SccUartIsr,(void *)pDataBuf);)
SccUartStartOp(pCfg);
}
static int SccUartRead(void *pDataBuf,void *pBuf, int MaxLen)
{
return BDRead(pDataBuf,pBuf,MaxLen);
}
static int LocalBDWrite(void *pDataBuf, char *pBuf, int Len,unsigned short statusmask,
unsigned short statusvalu)
{
int i;
DataBufStruct* Ttemp=(DataBufStruct *)pDataBuf;
char *temp=(char *)(Ttemp->pBaseSendBD[Ttemp->CurSendBD].address);
Ttemp->DrvInfo.SendTryNum++;
Ttemp->DrvInfo.SendPerNum++;
Ttemp->DrvInfo.TotalSendByte+=Len;
for(i=0;i<Len;i++)temp[i]=pBuf[i];
Ttemp->pBaseSendBD[Ttemp->CurSendBD].length=Len;
Ttemp->pBaseSendBD[Ttemp->CurSendBD].status &= (~(Ttemp->SendErrMask|statusmask));
statusvalu &= statusmask;
Ttemp->pBaseSendBD[Ttemp->CurSendBD].status |= (BD_READY|statusvalu);
Ttemp->CurSendBD=(Ttemp->CurSendBD+1)%Ttemp->MaxSendBD;
return Len;
}
static int SccUartWrite(void *pDataBuf,void *pBuf, int MaxLen)
{
int ret,delay;
DataBufStruct *pData=(DataBufStruct *)pDataBuf;
ret=BDCntrl(pDataBuf,SDC_GET_EMPTY_SEND_BD_NUM,NULL,0);
if(ret<0)return ret;
if((ret!=pData->MaxSendBD)||(ret<2)) return SDE_DEV_BUSY;
if(MaxLen <= 1 || (MaxLen-1) >pData->MaxBufLen)return SDE_PACKET_LEN;
#ifdef EN_485SEND
EN_485SEND;
#endif
LocalBDWrite(pDataBuf,pBuf,1,0x1400,0x0400);
ret=LocalBDWrite(pDataBuf,((char*)pBuf)+1,MaxLen-1,0x1400,0x1000);
return ret;
}
static int SccUartCntrl(void *pDataBuf, int cmd, void *pParam, int maxlen)
{
int i,clkdiv;
ULONG temp_ulong;
SccUart485CfgStruct cfg;
PDA *pda= (PDA *)(GetIMMR() & IO_MAP_MASK);
DataBufStruct *pData=(DataBufStruct *)pDataBuf;
SccUart485CfgStruct *pCfg =(SccUart485CfgStruct *)(pData+1);
int ret=BDCntrl(pDataBuf, cmd, pParam, maxlen);
if(ret!=SDE_UNKNOW_CMD)return ret;
switch(cmd)
{
case SDC_REINIT:
SccUartStopOp(pCfg);
dpram_dealloc(0,(char*)pData->pBaseRecvBD,BD_LEN*pData->MaxRecvBD);
dpram_dealloc(0,(char*)pData->pBaseSendBD,BD_LEN*pData->MaxSendBD);
SccUartInit(pDataBuf,pCfg);
SccUartStartOp(pCfg);
break;
case SDC_SEND_BREAK_485:
CPM_CMD(STOP_TX|((pCfg->ch*4)<<4));
CPM_CMD(RESTART_TX|((pCfg->ch*4)<<4));
break;
#ifdef EN_485SEND
case SDC_ENABLE485SEND:
EN_485SEND;
break;
#endif
#ifdef EN_485RECV
case SDC_ENABLE485RECV:
EN_485RECV;
break;
#endif
case SDC_SET_BAUDRATE_485:
pCfg->BaudRate=*(int *)pParam;
SccUartStopOp(pCfg);
clkdiv = (BspCpuClkRate()*1000000)/(16*pCfg->BaudRate) - 1;
if(clkdiv >= 4096)
clkdiv=(((BspCpuClkRate()*1000000)/(256*pCfg->BaudRate)-1)<<1)|1;
else
clkdiv <<= 1;
*(&pda->brgc1+pCfg->BRG)|=(1L<<(31-14));
*(&pda->brgc1+pCfg->BRG)=(1L<<(31-15))+clkdiv; /* brgclk=40MHZ */
SccUartClearBuf(pData);
SccUartStartOp(pCfg);
break;
default:
return SDE_UNKNOW_CMD;
}/* end of switch(cmd) */
return 0;
}
char *SccUartBspInit(int DEV, char *FreeMemPtr, SccUart485CfgStruct *cfg)
{
cfg->UncachedBuffer
=AllocUncachedBuffer(cfg->MaxRecvBD*cfg->MaxRecvBufLen+cfg->MaxSendBD*cfg->MaxSendBufLen,4);
cfg->UartMode=MANUL_MULTI;
cfg->Pen=PARITY_NO;
cfg->RecvPM=RECV_LOW;
cfg->SendPM=SEND_ODD;
cfg->Uaddr1=0;
cfg->Uaddr2=0;
InstallSD(DEV,SccUartRead,SccUartWrite,SccUartCntrl,FreeMemPtr);
SccUartInit(FreeMemPtr, cfg);
FreeMemPtr += sizeof(DataBufStruct)+sizeof(SccUart485CfgStruct);
memcpy(FreeMemPtr,"*SccUart",8);
FreeMemPtr += 8;
return FreeMemPtr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -