# HG changeset patch # User george.norton # Date 1278002773 -3600 # Node ID cdb163c0843f0c1060e595635251e79d7bccaf98 # Parent 2905910218dbe17c8a7b3aaeefa4b2a950386377 Initial contribution of the euart driver by Accenture. Known issues ============ When the FIFO is enabled we seem to get some dropped characters, as a temporary workaround a polling mode is enabled. diff -r 2905910218db -r cdb163c0843f omap3530/bld.inf --- a/omap3530/bld.inf Tue Apr 20 17:13:01 2010 +0100 +++ b/omap3530/bld.inf Thu Jul 01 17:46:13 2010 +0100 @@ -32,6 +32,7 @@ // #include "omap3530_drivers/prm/bld.inf" #include "omap3530_drivers/uart/bld.inf" #include "omap3530_drivers/usbcc/bld.inf" +#include "omap3530_drivers/euart/bld.inf" #include "shared/monitor/bld.inf" #include "shared/mstick/bld.inf" #include "shared/serialkeyb/bld.inf" diff -r 2905910218db -r cdb163c0843f omap3530/omap3530_drivers/euart/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omap3530/omap3530_drivers/euart/bld.inf Thu Jul 01 17:46:13 2010 +0100 @@ -0,0 +1,7 @@ +// omap3530/omap3530_drivers/euart/bld.inf + +PRJ_PLATFORMS +ARMV5 + +PRJ_MMPFILES +euart diff -r 2905910218db -r cdb163c0843f omap3530/omap3530_drivers/euart/euart.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omap3530/omap3530_drivers/euart/euart.cpp Thu Jul 01 17:46:13 2010 +0100 @@ -0,0 +1,557 @@ +// This component and the accompanying materials are made available +// under the terms of the License "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Accenture +// +// Contributors: +// +// Description: +// \sf\adaptation\beagleboard\omap3530\omap3530_drivers\euart\euart.cpp +// pdd for serial ports +// assume Modem Control Signals change cause an interrupt +// +// + +#include +#include +#include "euart.h" + +#define TX_POLLING_HACK + +_LIT(KPddName,"Comm.Beagle"); +using namespace Omap3530Uart; + +DDriverComm::DDriverComm() +// +// Constructor +// + { + iUnitsMask=0x7; + iVersion=TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber); + } + +TInt DDriverComm::Install() +// +// Install the driver +// + { + return SetName(&KPddName); + } + +void GetTemplateCommsCaps(TDes8 &aCaps, TInt aUnit) + { + TCommCaps2 capsBuf; + + // Fill in the Caps structure with the relevant information for this Unit, e.g + TCommCapsV02 &c=capsBuf(); + c.iRate=KCapsBps1200|KCapsBps2400|KCapsBps4800|KCapsBps9600|KCapsBps19200|KCapsBps38400| + KCapsBps57600|KCapsBps115200|KCapsBps230400|KCapsBps460800|KCapsBps4000000; + + c.iDataBits=KCapsData5|KCapsData6|KCapsData7|KCapsData8; + c.iStopBits=KCapsStop1|KCapsStop2; + c.iParity=KCapsParityNone|KCapsParityEven|KCapsParityOdd|KCapsParityMark|KCapsParitySpace; + c.iHandshake=0; //(OR in all KCapsObeyXXXSupported, KCapsSendXXXSupported, KCapsFailXXXSupported, KCapsFreeXXXSupported + // as required for this Unit's configuration);. + c.iSignals=0; //(OR in as many KCapsSignalXXXSupported as Modem control signals controllable by this Unit); + c.iSIR=0; //(0 or OR in as many KCapsSIRXXX as IR bit rates supported); + c.iNotificationCaps=0; //(OR in as many KNotifyXXXSupported as notifications supported by this Unit); + c.iFifo=0; //(0 or KCapsHasFifo); + c.iRoleCaps=0; //(0 or KCapsRoleSwitchSupported); + c.iFlowControlCaps=0; //(0 or KCapsFlowControlStatusSupported); + /** @see TCommCapsV02 */ + + aCaps=capsBuf.Left(Min(capsBuf.Length(),aCaps.MaxLength())); + } + +void DDriverComm::GetCaps(TDes8 &aDes) const +// +// Return the drivers capabilities +// + { + GetTemplateCommsCaps(aDes, 0); + } + +TInt DDriverComm::Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion& aVer) +// +// Create a driver +// + { + DCommBeagle* pD=new DCommBeagle; + aChannel=pD; + TInt r=KErrNoMemory; + if (pD) + r=pD->DoCreate(aUnit,anInfo); + return r; + } + +TInt DDriverComm::Validate(TInt aUnit, const TDesC8* /*anInfo*/, const TVersion& aVer) +// +// Validate the requested configuration (Version and Unit) +// + { + if ((!Kern::QueryVersionSupported(iVersion,aVer)) || (!Kern::QueryVersionSupported(aVer,TVersion(KMinimumLddMajorVersion,KMinimumLddMinorVersion,KMinimumLddBuild)))) + return KErrNotSupported; + + if(aUnit<0 || aUnit >2) + return KErrNotSupported; + + return KErrNone; + } + +DCommBeagle::DCommBeagle() +// +// Constructor +// + { + gData=0; + iInterruptId=-1; // -1 means not bound + } + +DCommBeagle::~DCommBeagle() +// +// Destructor +// + { + if (iInterruptId>=0) + Interrupt::Unbind(iInterruptId); + + if (iDfcQ) + { + iDfcQ->Destroy(); + } + } + +const TInt KDCommBeagleDfcThreadPriority = 24; +_LIT(KDCommBeagleDfcThread,"DCommBeagleDfcThread"); + +TInt DCommBeagle::DoCreate(TInt aUnit, const TDesC8* /*anInfo*/) +// +// Sets up the PDD +// + { + iUnit=aUnit; + + // Create own DFC queue + TInt r = Kern::DynamicDfcQCreate(iDfcQ, KDCommBeagleDfcThreadPriority, KDCommBeagleDfcThread); + + if (r != KErrNone) + return r; + + // Set iPortAddr and irq with the Linear Base address of the UART and the Interrupt ID coresponding to aUnit + iUart = new TUart((TUartNumber)aUnit); + Prcm::SetClockState(iUart->PrcmInterfaceClk(), Prcm::EClkOn); + Prcm::SetClockState(iUart->PrcmFunctionClk(), Prcm::EClkOn); + + // bind to UART interrupt + r=Interrupt::Bind(iUart->InterruptId(),Isr,this); + if (r==KErrNone) + iInterruptId=iUart->InterruptId(); + return r; + } + +TDfcQue* DCommBeagle::DfcQ(TInt aUnit) +// +// Return the DFC queue to be used for this device +// For UARTs just use the standard low priority DFC queue +// For Serial PC cards, use the PC card controller thread for the socket in question. +// + { + return aUnit==iUnit ? iDfcQ : NULL; + } + +TInt DCommBeagle::Start() +// +// Start receiving characters +// + { + if(iUnit == Kern::SuperPage().iDebugPort) + Variant::MarkDebugPortOff(); + + iTransmitting=EFalse; // if EnableTransmit() called before Start() + + if(iUart==NULL) + { + return KErrNotReady; + } + iSignals=Signals(); + iLdd->UpdateSignals(iSignals); + + Interrupt::Enable(iInterruptId); + iUart->EnableInterrupt(TUart::EIntRhr); + return KErrNone; + } + +TBool FinishedTransmitting(TAny* aPtr) + { + DCommBeagle* self = (DCommBeagle*)aPtr; + if(self->iUart==NULL) + { + return ETrue; + } + + if(!self->iUart->TxFifoEmpty()) + { + return EFalse; + } + return ETrue; + } + +void DCommBeagle::Stop(TStopMode aMode) +// +// Stop receiving characters +// + { + switch (aMode) + { + case EStopNormal: + case EStopPwrDown: + iUart->DisableInterrupt(TUart::EIntRhr); + iUart->DisableInterrupt(TUart::EIntThr); + Interrupt::Disable(iInterruptId); + + // wait for uart to stop tranmitting + Kern::PollingWait(FinishedTransmitting,this,3,100); + + iTransmitting=EFalse; + + iUart->Disable(); + Prcm::SetClockState(iUart->PrcmFunctionClk(), Prcm::EClkOff); + break; + case EStopEmergency: + iUart->DisableInterrupt(TUart::EIntRhr); + iUart->DisableInterrupt(TUart::EIntThr); + Interrupt::Disable(iInterruptId); + iTransmitting=EFalse; + break; + } + } + +void DCommBeagle::Break(TBool aState) +// +// Start or stop the uart breaking +// + { + if (aState) + { + // + // TO DO: (mandatory) + // + // Enable sending a Break (space) condition + // + } + else + { + // + // TO DO: (mandatory) + // + // Stop sending a Break (space) condition + // + } + } + +void DCommBeagle::EnableTransmit() +// +// Start sending characters. +// + { + TBool tx=(TBool)NKern::SafeSwap((TAny*)ETrue,(TAny*&)iTransmitting); + if (tx) + { + return; + } + TInt r = 0; + #ifdef TX_POLLING_HACK + while (Kern::PowerGood()) + #else + while (Kern::PowerGood() && !iUart->TxFifoFull()) + #endif + { + r=TransmitIsr(); + if(r<0) + { + //no more to send + iTransmitting=EFalse; + break; + } + #ifdef TX_POLLING_HACK + while(iUart->TxFifoFull()); + #endif + iUart->Write(r); + } + TInt irq=0; + if (!iInInterrupt) // CheckTxBuffer adds a Dfc: can only run from ISR or with NKernel locked + { + NKern::Lock(); + irq=NKern::DisableAllInterrupts(); + } + CheckTxBuffer(); + if (!iInInterrupt) + { + NKern::RestoreInterrupts(irq); + NKern::Unlock(); + } + if (r>=0) // only enable interrupt if there's more data to send + { + iUart->EnableInterrupt(TUart::EIntThr); + } + } + +TUint DCommBeagle::Signals() const +// +// Read and translate the modem lines +// + { + TUint signals=0; + // + // TO DO: (mandatory) + // + // If the UART corresponding to iUnit supports Modem Control Signals, read them and return a bitmask with one or + // more of the following OR-ed in: + // - KSignalDTR, + // - KSignalRTS, + // - KSignalDSR, + // - KSignalCTS, + // - KSignalDCD. + // + return signals; + } + +void DCommBeagle::SetSignals(TUint aSetMask, TUint aClearMask) +// +// Set signals. +// + { + // + // TO DO: (mandatory) + // + // If the UART corresponding to iUnit supports Modem Control Signals, converts the flags in aSetMask and aClearMask + // into hardware-specific bitmasks to write to the UART modem/handshake output register(s). + // aSetMask, aClearMask will have one or more of the following OR-ed in: + // - KSignalDTR, + // - KSignalRTS, + // + } + +TInt DCommBeagle::ValidateConfig(const TCommConfigV01 &aConfig) const +// +// Check a config structure. +// + { + // + // TO DO: (mandatory) + // + // Checks the the options in aConfig are supported by the UART corresponding to iUnit + // May need to check: + // - aConfig.iParity (contains one of EParityXXX) + /** @see TParity */ + // - aConfig.iRate (contains one of EBpsXXX) + /** @see TBps */ + // - aConfig.iDataBits (contains one of EDataXXX) + /** @see TDataBits */ + // - aConfig.iStopBits (contains one of EStopXXX) + /** @see TDataBits */ + // - aConfig.iHandshake (contains one of KConfigObeyXXX or KConfigSendXXX or KConfigFailXXX or KConfigFreeXXX) + // - aConfig.iParityError (contains KConfigParityErrorFail or KConfigParityErrorIgnore or KConfigParityErrorReplaceChar) + // - aConfig.iFifo (contains ether EFifoEnable or EFifoDisable) + /** @see TFifo */ + // - aConfig.iSpecialRate (may contain a rate not listed under TBps) + // - aConfig.iTerminatorCount (conatains number of special characters used as terminators) + // - aConfig.iTerminator[] (contains a list of special characters which can be used as terminators) + // - aConfig.iXonChar (contains the character used as XON - software flow control) + // - aConfig.iXoffChar (contains the character used as XOFF - software flow control) + // - aConfig.iParityErrorChar (contains the character used to replace bytes received with a parity error) + // - aConfig.iSIREnable (contains either ESIREnable or ESIRDisable) + /** @see TSir */ + // - aConfig.iSIRSettings (contains one of KConfigSIRXXX) + // and returns KErrNotSupported if the UART corresponding to iUnit does not support this configuration + // + return KErrNone; + } + +void DCommBeagle::CheckConfig(TCommConfigV01& aConfig) + { + // + // TO DO: (optional) + // + // Validates the default configuration that is defined when a channel is first opened + // + } + +TInt DCommBeagle::DisableIrqs() +// +// Disable normal interrupts +// + { + + return NKern::DisableInterrupts(1); + } + +void DCommBeagle::RestoreIrqs(TInt aLevel) +// +// Restore normal interrupts +// + { + + NKern::RestoreInterrupts(aLevel); + } + +void DCommBeagle::Configure(TCommConfigV01 &aConfig) +// +// Configure the UART from aConfig +// + { + Kern::PollingWait(FinishedTransmitting,this,3,100); // wait for uart to stop tranmitting + iUart->Disable(); + + iUart->Init(); + iUart->DefineMode(TUart::EUart); + + switch(aConfig.iRate) + { + case EBps1200: + iUart->SetBaud(TUart::E1200); + break; + case EBps2400: + iUart->SetBaud(TUart::E2400); + break; + case EBps4800: + iUart->SetBaud(TUart::E4800); + break; + case EBps9600: + iUart->SetBaud(TUart::E9600); + break; + case EBps19200: + iUart->SetBaud(TUart::E19200); + break; + case EBps38400: + iUart->SetBaud(TUart::E38400); + break; + case EBps57600: + iUart->SetBaud(TUart::E57600); + break; + case EBps460800: + iUart->SetBaud(TUart::E460800); + break; + case EBps115200: + default: + iUart->SetBaud(TUart::E115200); + } + + TUart::TDataBits databits = (TUart::TDataBits)aConfig.iDataBits; + TUart::TStopBits stopbits; + switch(aConfig.iStopBits) + { + case EStop2: + stopbits=TUart::E2Stop; + break; + case EStop1: + default: + stopbits=TUart::E1Stop; + } + + TUart::TParity parity; + switch(aConfig.iParity) + { + case EParityEven: + parity=TUart::EEven; + break; + case EParityOdd: + parity=TUart::EOdd; + break; + case EParityMark: + parity=TUart::EMark; + break; + case EParitySpace: + parity=TUart::ESpace; + break; + case EParityNone: + default: + parity=TUart::ENone; + } + + iUart->SetDataFormat(databits, stopbits, parity); + iUart->EnableFifo(TUart::EEnabled, TUart::ETrigger8, TUart::ETrigger8); + + iUart->Enable(); + } + +void DCommBeagle::Caps(TDes8 &aCaps) const +// +// return our caps +// + { + GetTemplateCommsCaps(aCaps,iUnit); + } + +void DCommBeagle::Isr(TAny* aPtr) +// +// Service the UART interrupt +// + { + DCommBeagle& d=*(DCommBeagle*)aPtr; + d.iInInterrupt=1; // going in... + TUint xon=d.iLdd->iRxXonChar; + TUint xoff=d.iLdd->iRxXoffChar; + + // Read the interrupt source register to determine if it is a Receive, Transmit or Modem Signals change interrupt. + // If required also, clear interrupts at the source. + // Then process the interrupt condition as in the following pseudo-code extract: + // + TUint interruptId = IIR::iMem.Read(*(d.iUart)); + TUint interruptEn = IER::iMem.Read(*(d.iUart)); + + if((interruptId & IIR::IT_TYPE::ETHR) && (interruptEn & IER::THR_IT::KMask) ) + { + while(Kern::PowerGood() && !d.iUart->TxFifoFull()) + { + TInt r=d.TransmitIsr(); + if(r<0) + { + // Disable the Transmit Interrupt in Hardware + d.iUart->DisableInterrupt(TUart::EIntThr); + d.iTransmitting=EFalse; + break; + } + d.iUart->Write(r); + } + d.CheckTxBuffer(); + } + + if((interruptId & IIR::IT_TYPE::ERHR) && (interruptEn & IER::RHR_IT::KMask) ) + { + TUint rx[32]; + TInt rxi=0; + TInt x=0; + + while(!d.iUart->RxFifoEmpty() && rxi<32) + { + TUint ch = d.iUart->Read(); + if (ch==xon) + x=1; + else if (ch==xoff) + x=-1; + else + rx[rxi++]=ch; + } + d.ReceiveIsr(rx,rxi,x); + } + + if((interruptId & IIR::IT_TYPE::EModem) && (interruptEn & IER::MODEM_STS_IT::KMask) ) + { + TUint signals=d.Signals()&KDTEInputSignals; + if (signals != d.iSignals) + { + d.iSignals=signals; + d.iLdd->StateIsr(signals); + } + } + d.iInInterrupt=0; // going out... + } + +DECLARE_STANDARD_PDD() + { + return new DDriverComm; + } diff -r 2905910218db -r cdb163c0843f omap3530/omap3530_drivers/euart/euart.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omap3530/omap3530_drivers/euart/euart.h Thu Jul 01 17:46:13 2010 +0100 @@ -0,0 +1,71 @@ +/* +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Accenture +* +* Contributors: +* +* Description: Minimalistic serial driver +* +*/ + +#ifndef _BEAGLE_SERIAL_H +#define _BEAGLE_SERIAL_H + +#include +#include +#include +#include + +const TInt KMinimumLddMajorVersion=1; +const TInt KMinimumLddMinorVersion=1; +const TInt KMinimumLddBuild=122; + +class DDriverComm : public DPhysicalDevice + { +public: + DDriverComm(); + virtual TInt Install(); + virtual void GetCaps(TDes8 &aDes) const; + virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion &aVer); + virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer); + }; + +class DCommBeagle : public DComm + { +public: + DCommBeagle(); + ~DCommBeagle(); + TInt DoCreate(TInt aUnit, const TDesC8* anInfo); +public: + virtual TInt Start(); + virtual void Stop(TStopMode aMode); + virtual void Break(TBool aState); + virtual void EnableTransmit(); + virtual TUint Signals() const; + virtual void SetSignals(TUint aSetMask,TUint aClearMask); + virtual TInt ValidateConfig(const TCommConfigV01 &aConfig) const; + virtual void Configure(TCommConfigV01 &aConfig); + virtual void Caps(TDes8 &aCaps) const; + virtual TInt DisableIrqs(); + virtual void RestoreIrqs(TInt aIrq); + virtual TDfcQue* DfcQ(TInt aUnit); + virtual void CheckConfig(TCommConfigV01& aConfig); +public: + static void Isr(TAny* aPtr); +public: + TInt iInterruptId; + TInt iUnit; + TLinAddr iPortAddr; + TInt iInInterrupt; + TUint iSignals; + TDynamicDfcQue* iDfcQ; + Omap3530Uart::TUart* iUart; + TInt gData; + }; + +#endif diff -r 2905910218db -r cdb163c0843f omap3530/omap3530_drivers/euart/euart.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omap3530/omap3530_drivers/euart/euart.mmp Thu Jul 01 17:46:13 2010 +0100 @@ -0,0 +1,37 @@ +// This component and the accompanying materials are made available +// under the terms of the License "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Accenture +// +// Contributors: +// +// Description: +// omap3530\omap3530_drivers\euart\euart.mmp +// +// + +#include "beagle/variant.mmh" +#include +#include "kernel/kern_ext.mmh" + +target AsspTarget(euart,pdd) +targettype pdd +romtarget euart.pdd + +systeminclude . +systeminclude +/include/assp/omap3530_assp +systeminclude +/include/platform/drivers + +sourcepath . +source euart.cpp + +library AsspTarget(kaomap3530,lib) AsspTarget(uart,lib) VariantTarget(ecust,lib) AsspTarget(prcm,lib) + +uid 0 0x1000015b + +VENDORID 0x70000001 + +capability all