Update contrib.
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // template\template_variant\specific\uart.cpp
15 // pdd for serial ports
16 // assume Modem Control Signals change cause an interrupt
21 #include <drivers/comm.h>
22 #include <template_assp.h>
26 _LIT(KPddName,"Comm.Template");
28 // needs ldd version..
29 const TInt KMinimumLddMajorVersion=1;
30 const TInt KMinimumLddMinorVersion=1;
31 const TInt KMinimumLddBuild=122;
36 // Define here the UART enumeration data for the serial ports.
37 // It is a good idea to define each enumerated value as a bit mask that can be written to (or OR-ed or AND-ed to)
38 // a hardware register to provide the configuration option desired (the following are EXAMPLES ONLY):
43 EUartBaudRate115200/* =bitmask for 115200 Baud */,
44 EUartBaudRate76800/* =bitmask for 76800 Baud */,
45 EUartBaudRate57600/* =bitmask for 57600 Baud */,
46 EUartBaudRate38400/* =bitmask for 38400 Baud */,
47 EUartBaudRate19200/* =bitmask for 19200 Baud */,
48 EUartBaudRate14400/* =bitmask for 14400 Baud */,
49 EUartBaudRate9600/* =bitmask for 9600 Baud */,
50 EUartBaudRate4800/* =bitmask for 4800 Baud */,
51 EUartBaudRate2400/* =bitmask for 2400 Baud */,
52 EUartBaudRate1200/* =bitmask for 1200 Baud */,
53 EUartBaudRate600/* =bitmask for 600 Baud */,
54 EUartBaudRate300/* =bitmask for 300 Baud */,
55 EUartBaudRate150/* =bitmask for 150 Baud */,
56 EUartBaudRate110/* =bitmask for 110 Baud */
61 EUartBreakOff/* =bitmask for turning Break Off */,
62 EUartBreakOn/* =bitmask for turning Break On */
67 EUartParityNone/* =bitmask for no Parity */,
68 EUartParityOdd/* =bitmask for odd Parity */,
69 EUartParityEven/* =bitmask for even Parity */
74 EUartStopBitOne/* =bitmask for one stop bit */,
75 EUartStopBitTwo/* =bitmask for two stop bits */
79 EUartDataLength5/* =bitmask for five data bits */,
80 EUartDataLength6/* =bitmask for six data bits */,
81 EUartDataLength7/* =bitmask for seven data bits */,
82 EUartDataLength8/* =bitmask for eight data bits */
88 // Lookup table to convert EPOC baud rates into hardware-specific baud rate values
89 // Unsupported baud rates select the nearest lower rate.
92 static const TUartBaudRate BaudRate[19] =
94 EUartBaudRate110,EUartBaudRate110,EUartBaudRate110,
95 EUartBaudRate110,EUartBaudRate150,EUartBaudRate300,
96 EUartBaudRate600,EUartBaudRate1200,EUartBaudRate110,
97 EUartBaudRate110,EUartBaudRate2400,EUartBaudRate110,
98 EUartBaudRate4800,EUartBaudRate110,EUartBaudRate9600,
99 EUartBaudRate19200,EUartBaudRate38400,EUartBaudRate57600,
104 // TO DO: (mandatory)
106 // Lookup table to convert EPOC parity settings into hardware-specific values
109 static const TUartParity Parity[3] =
111 EUartParityNone,EUartParityEven,EUartParityOdd
115 // TO DO: (mandatory)
117 // Lookup table to convert EPOC stop bit values into hardware-specific values
120 static const TUartStopBit StopBit[2] =
122 EUartStopBitOne,EUartStopBitTwo
126 // TO DO: (mandatory)
128 // Lookup table to convert EPOC data bit settings into hardware-specific values
131 static const TUartDataLength DataLength[4] =
133 EUartDataLength5,EUartDataLength6,
134 EUartDataLength7,EUartDataLength8
139 class DDriverComm : public DPhysicalDevice
143 virtual TInt Install();
144 virtual void GetCaps(TDes8 &aDes) const;
145 virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion &aVer);
146 virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer);
149 class DCommTemplate : public DComm
154 TInt DoCreate(TInt aUnit, const TDesC8* anInfo);
156 virtual TInt Start();
157 virtual void Stop(TStopMode aMode);
158 virtual void Break(TBool aState);
159 virtual void EnableTransmit();
160 virtual TUint Signals() const;
161 virtual void SetSignals(TUint aSetMask,TUint aClearMask);
162 virtual TInt ValidateConfig(const TCommConfigV01 &aConfig) const;
163 virtual void Configure(TCommConfigV01 &aConfig);
164 virtual void Caps(TDes8 &aCaps) const;
165 virtual TInt DisableIrqs();
166 virtual void RestoreIrqs(TInt aIrq);
167 virtual TDfcQue* DfcQ(TInt aUnit);
168 virtual void CheckConfig(TCommConfigV01& aConfig);
170 static void Isr(TAny* aPtr);
177 TDynamicDfcQue* iDfcQ;
181 DDriverComm::DDriverComm()
187 // TO DO: (mandatory)
189 // Set up iUnitMask with the number of Units (Serial Ports) supported by this PDD,
190 // 1 bit set per Unit supported e.g.:
191 // iUnitsMask=0x7; -> supports units 0, 1, 2
193 iVersion=TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber);
196 TInt DDriverComm::Install()
198 // Install the driver
202 return SetName(&KPddName);
205 void GetTemplateCommsCaps(TDes8 &aCaps, TInt aUnit)
209 // TO DO: (mandatory)
211 // Fill in the Caps structure with the relevant information for this Unit, e.g
212 // TCommCapsV02 &c=capsBuf();
213 // c.iRate=(OR in as many KCapsBpsXXX as bit rates supported);
214 // c.iDataBits=(OR in as many KCapsDataXXX as data length configuration supported);
215 // c.iStopBits=(OR in as many KCapsStopXXX as the number of stop bits configurations supported);
216 // c.iParity=(OR in as many KCapsParityXXX as parity configuration supported);
217 // c.iHandshake=(OR in all KCapsObeyXXXSupported, KCapsSendXXXSupported, KCapsFailXXXSupported, KCapsFreeXXXSupported
218 // as required for this Unit's configuration);.
219 // c.iSignals=(OR in as many KCapsSignalXXXSupported as Modem control signals controllable by this Unit);
220 // c.iSIR=(0 or OR in as many KCapsSIRXXX as IR bit rates supported);
221 // c.iNotificationCaps=(OR in as many KNotifyXXXSupported as notifications supported by this Unit);
222 // c.iFifo=(0 or KCapsHasFifo);
223 // c.iRoleCaps=(0 or KCapsRoleSwitchSupported);
224 // c.iFlowControlCaps=(0 or KCapsFlowControlStatusSupported);
225 /** @see TCommCapsV02 */
227 aCaps.FillZ(aCaps.MaxLength());
228 aCaps=capsBuf.Left(Min(capsBuf.Length(),aCaps.MaxLength()));
231 void DDriverComm::GetCaps(TDes8 &aDes) const
233 // Return the drivers capabilities
236 GetTemplateCommsCaps(aDes, 0);
239 TInt DDriverComm::Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion& aVer)
244 DCommTemplate* pD=new DCommTemplate;
248 r=pD->DoCreate(aUnit,anInfo);
252 TInt DDriverComm::Validate(TInt aUnit, const TDesC8* /*anInfo*/, const TVersion& aVer)
254 // Validate the requested configuration (Version and Unit)
257 if ((!Kern::QueryVersionSupported(iVersion,aVer)) || (!Kern::QueryVersionSupported(aVer,TVersion(KMinimumLddMajorVersion,KMinimumLddMinorVersion,KMinimumLddBuild))))
258 return KErrNotSupported;
260 // TO DO: (mandatory)
262 // Return KErrNotSupported if aUnit is not in the supported range for this driver, KErrNone if it is
267 DCommTemplate::DCommTemplate()
272 iInterruptId=-1; // -1 means not bound
275 DCommTemplate::~DCommTemplate()
281 Interrupt::Unbind(iInterruptId);
289 const TInt KDCommTemplDfcThreadPriority = 24;
290 _LIT(KDCommTemplDfcThread,"DCommTemplDfcThread");
292 TInt DCommTemplate::DoCreate(TInt aUnit, const TDesC8* /*anInfo*/)
300 // TO DO: (mandatory)
302 // Create own DFC queue
303 TInt r = Kern::DynamicDfcQCreate(iDfcQ, KDCommTemplDfcThreadPriority, KDCommTemplDfcThread);
308 // Set iPortAddr and irq with the Linear Base address of the UART and the Interrupt ID coresponding to aUnit
311 // bind to UART interrupt
312 r=Interrupt::Bind(irq,Isr,this);
319 // Any other setting up of UART hardware registers, required for:
320 // - Disabling the UART operation
321 // - disabling all UART Interrupts
322 // - clearing all Rx errors
323 // - clearing all UART interrupts
324 // - de-activating output Modem Control signals
327 Variant::MarkDebugPortOff();
331 TDfcQue* DCommTemplate::DfcQ(TInt aUnit)
333 // Return the DFC queue to be used for this device
334 // For UARTs just use the standard low priority DFC queue
335 // For Serial PC cards, use the PC card controller thread for the socket in question.
338 return aUnit==iUnit ? iDfcQ : NULL;
341 TInt DCommTemplate::Start()
343 // Start receiving characters
346 iTransmitting=EFalse; // if EnableTransmit() called before Start()
349 // TO DO: (mandatory)
351 // Set up hardware registers to enable the UART and switch receive mode on
354 // if (iUnit!=IR Port) TO DO: (mandatory): Implement
357 iLdd->UpdateSignals(iSignals);
363 // If Unit is IR Port may need to start the IR port
365 Interrupt::Enable(iInterruptId);
369 TBool FinishedTransmitting(TAny* aPtr)
372 // TO DO: (mandatory)
374 // Return ETrue if UART is still transmitting, EFalse Otherwise
376 return EFalse; // EXAMPLE ONLY
379 void DCommTemplate::Stop(TStopMode aMode)
381 // Stop receiving characters
388 Interrupt::Disable(iInterruptId);
389 iTransmitting=EFalse;
391 // wait for uart to stop tranmitting
392 Kern::PollingWait(FinishedTransmitting,this,3,100);
397 // Any other setting up of UART hardware registers, required for:
398 // - Disabling the UART operation
399 // - disabling all UART Interrupts
400 // - disabling Transmit and Receive pathes
401 // - clearing all UART interrupts
405 Interrupt::Disable(iInterruptId);
406 iTransmitting=EFalse;
412 // If Unit is IR Port may need to stop the IR port
414 Variant::MarkDebugPortOff();
417 void DCommTemplate::Break(TBool aState)
419 // Start or stop the uart breaking
425 // TO DO: (mandatory)
427 // Enable sending a Break (space) condition
433 // TO DO: (mandatory)
435 // Stop sending a Break (space) condition
440 void DCommTemplate::EnableTransmit()
442 // Start sending characters.
445 TBool tx = (TBool)__e32_atomic_swp_ord32(&iTransmitting, 1);
449 while (/* (Transmit FIFO Not full) && */ Kern::PowerGood()) // TO DO: (mandatory): Implement
451 TInt r=TransmitIsr();
455 iTransmitting=EFalse;
459 // TO DO: (mandatory)
461 // Write transmit character into transmit FIFO or output register
465 if (!iInInterrupt) // CheckTxBuffer adds a Dfc: can only run from ISR or with NKernel locked
468 irq=NKern::DisableAllInterrupts();
473 NKern::RestoreInterrupts(irq);
477 // TO DO: (mandatory)
479 // Enable transmission of data
481 if (r>=0) // only enable interrupt if there's more data to send
484 // TO DO: (mandatory)
486 // Enable transmit interrupt in the Hardware (Interrupt::Enable() has already been called in Start())
491 TUint DCommTemplate::Signals() const
493 // Read and translate the modem lines
498 // TO DO: (mandatory)
500 // If the UART corresponding to iUnit supports Modem Control Signals, read them and return a bitmask with one or
501 // more of the following OR-ed in:
511 void DCommTemplate::SetSignals(TUint aSetMask, TUint aClearMask)
517 // TO DO: (mandatory)
519 // If the UART corresponding to iUnit supports Modem Control Signals, converts the flags in aSetMask and aClearMask
520 // into hardware-specific bitmasks to write to the UART modem/handshake output register(s).
521 // aSetMask, aClearMask will have one or more of the following OR-ed in:
527 TInt DCommTemplate::ValidateConfig(const TCommConfigV01 &aConfig) const
529 // Check a config structure.
533 // TO DO: (mandatory)
535 // Checks the the options in aConfig are supported by the UART corresponding to iUnit
536 // May need to check:
537 // - aConfig.iParity (contains one of EParityXXX)
539 // - aConfig.iRate (contains one of EBpsXXX)
541 // - aConfig.iDataBits (contains one of EDataXXX)
542 /** @see TDataBits */
543 // - aConfig.iStopBits (contains one of EStopXXX)
544 /** @see TDataBits */
545 // - aConfig.iHandshake (contains one of KConfigObeyXXX or KConfigSendXXX or KConfigFailXXX or KConfigFreeXXX)
546 // - aConfig.iParityError (contains KConfigParityErrorFail or KConfigParityErrorIgnore or KConfigParityErrorReplaceChar)
547 // - aConfig.iFifo (contains ether EFifoEnable or EFifoDisable)
549 // - aConfig.iSpecialRate (may contain a rate not listed under TBps)
550 // - aConfig.iTerminatorCount (conatains number of special characters used as terminators)
551 // - aConfig.iTerminator[] (contains a list of special characters which can be used as terminators)
552 // - aConfig.iXonChar (contains the character used as XON - software flow control)
553 // - aConfig.iXoffChar (contains the character used as XOFF - software flow control)
554 // - aConfig.iParityErrorChar (contains the character used to replace bytes received with a parity error)
555 // - aConfig.iSIREnable (contains either ESIREnable or ESIRDisable)
557 // - aConfig.iSIRSettings (contains one of KConfigSIRXXX)
558 // and returns KErrNotSupported if the UART corresponding to iUnit does not support this configuration
563 void DCommTemplate::CheckConfig(TCommConfigV01& aConfig)
568 // Validates the default configuration that is defined when a channel is first opened
572 TInt DCommTemplate::DisableIrqs()
574 // Disable normal interrupts
578 return NKern::DisableInterrupts(1);
581 void DCommTemplate::RestoreIrqs(TInt aLevel)
583 // Restore normal interrupts
587 NKern::RestoreInterrupts(aLevel);
590 void DCommTemplate::Configure(TCommConfigV01 &aConfig)
592 // Configure the UART from aConfig
595 Kern::PollingWait(FinishedTransmitting,this,3,100); // wait for uart to stop tranmitting
600 // Ensure Tx, Rx and the UART are disabled and disable sending Break (space) condition.
601 // May need to modify clocks settings, pin functions etc.
605 // TO DO: (mandatory)
607 // Set communications parameters such as:
612 // These can be obtained from aConfig using the look-up tables above, e.g.
613 // TUint baudRate=BaudRate[aConfig.iRate];
614 // TUint parity=Parity[aConfig.iParity];
615 // TUint stopBits=StopBit[aConfig.iStopBits];
616 // TUint dataBits=DataLength[aConfig.iDataBits];
617 // Write these to the appropriate hardware registers using iPortAddr to identify which ste of register to modify
623 // If the UART corresponding to iUnit supports IR may need to set up IR transceiver
627 void DCommTemplate::Caps(TDes8 &aCaps) const
632 GetTemplateCommsCaps(aCaps,iUnit);
635 void DCommTemplate::Isr(TAny* aPtr)
637 // Service the UART interrupt
640 DCommTemplate& d=*(DCommTemplate*)aPtr;
641 d.iInInterrupt=1; // going in...
642 // TUint portAddr=d.iPortAddr; TO DO: (mandatory): Uncomment this
645 // TO DO: (mandatory)
647 // Read the interrupt source register to determine if it is a Receive, Transmit or Modem Signals change interrupt.
648 // If required also, clear interrupts at the source.
649 // Then process the interrupt condition as in the following pseudo-code extract:
651 // if((Received character Interrupts) || (Error in received character Interupt)) TO DO: (mandatory): Implement
654 TUint xon=d.iLdd->iRxXonChar;
655 TUint xoff=d.iLdd->iRxXoffChar;
659 // while((Receive FIFO not empty) && Kern::PowerGood()) TO DO: (mandatory): Implement
662 // NOTE: for some hardware the order the following 2 operations is performed may have to be reversed
663 // if(Error in received character interrupt) TO DO: (mandatory): Implement
664 // regStatus1=(Read receive error bitmask off appropriate register);
665 // ch=(Read received character);
667 // coverity[dead_error_condition]
668 // The next line should be reachable when this template file is edited for use
669 if(regStatus1!=0) // if error in this character
671 // if (ch & (Parity Error)) TO DO: (mandatory): Implement
672 ch|=KReceiveIsrParityError;
673 // if (ch & (Framing Error)) TO DO: (mandatory): Implement
674 ch|=KReceiveIsrFrameError;
675 // if (ch & (Overrun)) TO DO: (mandatory): Implement
676 ch|=KReceiveIsrOverrunError;
685 d.ReceiveIsr(rx,rxi,x);
687 // if((Transmitted character Interrupt)) TO DO: (mandatory): Implement
689 while(/* (Transmit FIFO Not full) && */ Kern::PowerGood()) // TO DO: (mandatory): Implement
691 TInt r=d.TransmitIsr();
696 // TO DO: (mandatory)
698 // Disable the Transmit Interrupt in Hardware
699 d.iTransmitting=EFalse;
702 // (write transmit character to output FIFO or Data register) TO DO: (mandatory): Implement
706 // if((Modem Signals changed Interrupt)) TO DO: (mandatory): Implement
708 TUint signals=d.Signals()&KDTEInputSignals;
709 if (signals != d.iSignals)
712 d.iLdd->StateIsr(signals);
715 d.iInInterrupt=0; // going out...
718 DECLARE_STANDARD_PDD()
720 return new DDriverComm;