|
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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // template\template_variant\specific\uart.cpp |
|
15 // pdd for serial ports |
|
16 // assume Modem Control Signals change cause an interrupt |
|
17 // |
|
18 // |
|
19 |
|
20 |
|
21 #include <drivers/comm.h> |
|
22 #include <template_assp.h> |
|
23 #include "iolines.h" |
|
24 #include <e32hal.h> |
|
25 |
|
26 _LIT(KPddName,"Comm.Template"); |
|
27 |
|
28 // needs ldd version.. |
|
29 const TInt KMinimumLddMajorVersion=1; |
|
30 const TInt KMinimumLddMinorVersion=1; |
|
31 const TInt KMinimumLddBuild=122; |
|
32 |
|
33 // |
|
34 // TO DO: (mandatory) |
|
35 // |
|
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): |
|
39 // |
|
40 // EXAMPLE ONLY |
|
41 enum TUartBaudRate |
|
42 { |
|
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 */ |
|
57 }; |
|
58 // EXAMPLE ONLY |
|
59 enum TUartBreak |
|
60 { |
|
61 EUartBreakOff/* =bitmask for turning Break Off */, |
|
62 EUartBreakOn/* =bitmask for turning Break On */ |
|
63 }; |
|
64 // EXAMPLE ONLY |
|
65 enum TUartParity |
|
66 { |
|
67 EUartParityNone/* =bitmask for no Parity */, |
|
68 EUartParityOdd/* =bitmask for odd Parity */, |
|
69 EUartParityEven/* =bitmask for even Parity */ |
|
70 }; |
|
71 // EXAMPLE ONLY |
|
72 enum TUartStopBit |
|
73 { |
|
74 EUartStopBitOne/* =bitmask for one stop bit */, |
|
75 EUartStopBitTwo/* =bitmask for two stop bits */ |
|
76 }; |
|
77 enum TUartDataLength |
|
78 { |
|
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 */ |
|
83 }; |
|
84 |
|
85 // |
|
86 // TO DO: (mandatory) |
|
87 // |
|
88 // Lookup table to convert EPOC baud rates into hardware-specific baud rate values |
|
89 // Unsupported baud rates select the nearest lower rate. |
|
90 // |
|
91 // EXAMPLE ONLY |
|
92 static const TUartBaudRate BaudRate[19] = |
|
93 { |
|
94 EUartBaudRate110,EUartBaudRate110,EUartBaudRate110, |
|
95 EUartBaudRate110,EUartBaudRate150,EUartBaudRate300, |
|
96 EUartBaudRate600,EUartBaudRate1200,EUartBaudRate110, |
|
97 EUartBaudRate110,EUartBaudRate2400,EUartBaudRate110, |
|
98 EUartBaudRate4800,EUartBaudRate110,EUartBaudRate9600, |
|
99 EUartBaudRate19200,EUartBaudRate38400,EUartBaudRate57600, |
|
100 EUartBaudRate115200 |
|
101 }; |
|
102 |
|
103 // |
|
104 // TO DO: (mandatory) |
|
105 // |
|
106 // Lookup table to convert EPOC parity settings into hardware-specific values |
|
107 // |
|
108 // EXAMPLE ONLY |
|
109 static const TUartParity Parity[3] = |
|
110 { |
|
111 EUartParityNone,EUartParityEven,EUartParityOdd |
|
112 }; |
|
113 |
|
114 // |
|
115 // TO DO: (mandatory) |
|
116 // |
|
117 // Lookup table to convert EPOC stop bit values into hardware-specific values |
|
118 // |
|
119 // EXAMPLE ONLY |
|
120 static const TUartStopBit StopBit[2] = |
|
121 { |
|
122 EUartStopBitOne,EUartStopBitTwo |
|
123 }; |
|
124 |
|
125 // |
|
126 // TO DO: (mandatory) |
|
127 // |
|
128 // Lookup table to convert EPOC data bit settings into hardware-specific values |
|
129 // |
|
130 // EXAMPLE ONLY |
|
131 static const TUartDataLength DataLength[4] = |
|
132 { |
|
133 EUartDataLength5,EUartDataLength6, |
|
134 EUartDataLength7,EUartDataLength8 |
|
135 }; |
|
136 |
|
137 |
|
138 |
|
139 class DDriverComm : public DPhysicalDevice |
|
140 { |
|
141 public: |
|
142 DDriverComm(); |
|
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); |
|
147 }; |
|
148 |
|
149 class DCommTemplate : public DComm |
|
150 { |
|
151 public: |
|
152 DCommTemplate(); |
|
153 ~DCommTemplate(); |
|
154 TInt DoCreate(TInt aUnit, const TDesC8* anInfo); |
|
155 public: |
|
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); |
|
169 public: |
|
170 static void Isr(TAny* aPtr); |
|
171 public: |
|
172 TInt iInterruptId; |
|
173 TInt iUnit; |
|
174 TLinAddr iPortAddr; |
|
175 TInt iInInterrupt; |
|
176 TUint iSignals; |
|
177 TDynamicDfcQue* iDfcQ; |
|
178 }; |
|
179 |
|
180 |
|
181 DDriverComm::DDriverComm() |
|
182 // |
|
183 // Constructor |
|
184 // |
|
185 { |
|
186 // |
|
187 // TO DO: (mandatory) |
|
188 // |
|
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 |
|
192 // |
|
193 iVersion=TVersion(KCommsMajorVersionNumber,KCommsMinorVersionNumber,KCommsBuildVersionNumber); |
|
194 } |
|
195 |
|
196 TInt DDriverComm::Install() |
|
197 // |
|
198 // Install the driver |
|
199 // |
|
200 { |
|
201 |
|
202 return SetName(&KPddName); |
|
203 } |
|
204 |
|
205 void GetTemplateCommsCaps(TDes8 &aCaps, TInt aUnit) |
|
206 { |
|
207 TCommCaps2 capsBuf; |
|
208 // |
|
209 // TO DO: (mandatory) |
|
210 // |
|
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 */ |
|
226 // |
|
227 aCaps.FillZ(aCaps.MaxLength()); |
|
228 aCaps=capsBuf.Left(Min(capsBuf.Length(),aCaps.MaxLength())); |
|
229 } |
|
230 |
|
231 void DDriverComm::GetCaps(TDes8 &aDes) const |
|
232 // |
|
233 // Return the drivers capabilities |
|
234 // |
|
235 { |
|
236 GetTemplateCommsCaps(aDes, 0); |
|
237 } |
|
238 |
|
239 TInt DDriverComm::Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion& aVer) |
|
240 // |
|
241 // Create a driver |
|
242 // |
|
243 { |
|
244 DCommTemplate* pD=new DCommTemplate; |
|
245 aChannel=pD; |
|
246 TInt r=KErrNoMemory; |
|
247 if (pD) |
|
248 r=pD->DoCreate(aUnit,anInfo); |
|
249 return r; |
|
250 } |
|
251 |
|
252 TInt DDriverComm::Validate(TInt aUnit, const TDesC8* /*anInfo*/, const TVersion& aVer) |
|
253 // |
|
254 // Validate the requested configuration (Version and Unit) |
|
255 // |
|
256 { |
|
257 if ((!Kern::QueryVersionSupported(iVersion,aVer)) || (!Kern::QueryVersionSupported(aVer,TVersion(KMinimumLddMajorVersion,KMinimumLddMinorVersion,KMinimumLddBuild)))) |
|
258 return KErrNotSupported; |
|
259 // |
|
260 // TO DO: (mandatory) |
|
261 // |
|
262 // Return KErrNotSupported if aUnit is not in the supported range for this driver, KErrNone if it is |
|
263 // |
|
264 return KErrNone; |
|
265 } |
|
266 |
|
267 DCommTemplate::DCommTemplate() |
|
268 // |
|
269 // Constructor |
|
270 // |
|
271 { |
|
272 iInterruptId=-1; // -1 means not bound |
|
273 } |
|
274 |
|
275 DCommTemplate::~DCommTemplate() |
|
276 // |
|
277 // Destructor |
|
278 // |
|
279 { |
|
280 if (iInterruptId>=0) |
|
281 Interrupt::Unbind(iInterruptId); |
|
282 |
|
283 if (iDfcQ) |
|
284 { |
|
285 iDfcQ->Destroy(); |
|
286 } |
|
287 } |
|
288 |
|
289 const TInt KDCommTemplDfcThreadPriority = 24; |
|
290 _LIT(KDCommTemplDfcThread,"DCommTemplDfcThread"); |
|
291 |
|
292 TInt DCommTemplate::DoCreate(TInt aUnit, const TDesC8* /*anInfo*/) |
|
293 // |
|
294 // Sets up the PDD |
|
295 // |
|
296 { |
|
297 iUnit=aUnit; |
|
298 TInt irq=-1; |
|
299 // |
|
300 // TO DO: (mandatory) |
|
301 // |
|
302 // Create own DFC queue |
|
303 TInt r = Kern::DynamicDfcQCreate(iDfcQ, KDCommTemplDfcThreadPriority, KDCommTemplDfcThread); |
|
304 |
|
305 if (r != KErrNone) |
|
306 return r; |
|
307 |
|
308 // Set iPortAddr and irq with the Linear Base address of the UART and the Interrupt ID coresponding to aUnit |
|
309 // |
|
310 |
|
311 // bind to UART interrupt |
|
312 r=Interrupt::Bind(irq,Isr,this); |
|
313 if (r==KErrNone) |
|
314 iInterruptId=irq; |
|
315 |
|
316 // |
|
317 // TO DO: (optional) |
|
318 // |
|
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 |
|
325 // |
|
326 |
|
327 Variant::MarkDebugPortOff(); |
|
328 return r; |
|
329 } |
|
330 |
|
331 TDfcQue* DCommTemplate::DfcQ(TInt aUnit) |
|
332 // |
|
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. |
|
336 // |
|
337 { |
|
338 return aUnit==iUnit ? iDfcQ : NULL; |
|
339 } |
|
340 |
|
341 TInt DCommTemplate::Start() |
|
342 // |
|
343 // Start receiving characters |
|
344 // |
|
345 { |
|
346 iTransmitting=EFalse; // if EnableTransmit() called before Start() |
|
347 |
|
348 // |
|
349 // TO DO: (mandatory) |
|
350 // |
|
351 // Set up hardware registers to enable the UART and switch receive mode on |
|
352 // |
|
353 |
|
354 // if (iUnit!=IR Port) TO DO: (mandatory): Implement |
|
355 { |
|
356 iSignals=Signals(); |
|
357 iLdd->UpdateSignals(iSignals); |
|
358 } |
|
359 |
|
360 // |
|
361 // TO DO: (optional) |
|
362 // |
|
363 // If Unit is IR Port may need to start the IR port |
|
364 // |
|
365 Interrupt::Enable(iInterruptId); |
|
366 return KErrNone; |
|
367 } |
|
368 |
|
369 TBool FinishedTransmitting(TAny* aPtr) |
|
370 { |
|
371 // |
|
372 // TO DO: (mandatory) |
|
373 // |
|
374 // Return ETrue if UART is still transmitting, EFalse Otherwise |
|
375 // |
|
376 return EFalse; // EXAMPLE ONLY |
|
377 } |
|
378 |
|
379 void DCommTemplate::Stop(TStopMode aMode) |
|
380 // |
|
381 // Stop receiving characters |
|
382 // |
|
383 { |
|
384 switch (aMode) |
|
385 { |
|
386 case EStopNormal: |
|
387 case EStopPwrDown: |
|
388 Interrupt::Disable(iInterruptId); |
|
389 iTransmitting=EFalse; |
|
390 |
|
391 // wait for uart to stop tranmitting |
|
392 Kern::PollingWait(FinishedTransmitting,this,3,100); |
|
393 |
|
394 // |
|
395 // TO DO: (optional) |
|
396 // |
|
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 |
|
402 // |
|
403 break; |
|
404 case EStopEmergency: |
|
405 Interrupt::Disable(iInterruptId); |
|
406 iTransmitting=EFalse; |
|
407 break; |
|
408 } |
|
409 // |
|
410 // TO DO: (optional) |
|
411 // |
|
412 // If Unit is IR Port may need to stop the IR port |
|
413 // |
|
414 Variant::MarkDebugPortOff(); |
|
415 } |
|
416 |
|
417 void DCommTemplate::Break(TBool aState) |
|
418 // |
|
419 // Start or stop the uart breaking |
|
420 // |
|
421 { |
|
422 if (aState) |
|
423 { |
|
424 // |
|
425 // TO DO: (mandatory) |
|
426 // |
|
427 // Enable sending a Break (space) condition |
|
428 // |
|
429 } |
|
430 else |
|
431 { |
|
432 // |
|
433 // TO DO: (mandatory) |
|
434 // |
|
435 // Stop sending a Break (space) condition |
|
436 // |
|
437 } |
|
438 } |
|
439 |
|
440 void DCommTemplate::EnableTransmit() |
|
441 // |
|
442 // Start sending characters. |
|
443 // |
|
444 { |
|
445 TBool tx = (TBool)__e32_atomic_swp_ord32(&iTransmitting, 1); |
|
446 if (tx) |
|
447 return; |
|
448 TInt r = 0; |
|
449 while (/* (Transmit FIFO Not full) && */ Kern::PowerGood()) // TO DO: (mandatory): Implement |
|
450 { |
|
451 TInt r=TransmitIsr(); |
|
452 if(r<0) |
|
453 { |
|
454 //no more to send |
|
455 iTransmitting=EFalse; |
|
456 break; |
|
457 } |
|
458 // |
|
459 // TO DO: (mandatory) |
|
460 // |
|
461 // Write transmit character into transmit FIFO or output register |
|
462 // |
|
463 } |
|
464 TInt irq=0; |
|
465 if (!iInInterrupt) // CheckTxBuffer adds a Dfc: can only run from ISR or with NKernel locked |
|
466 { |
|
467 NKern::Lock(); |
|
468 irq=NKern::DisableAllInterrupts(); |
|
469 } |
|
470 CheckTxBuffer(); |
|
471 if (!iInInterrupt) |
|
472 { |
|
473 NKern::RestoreInterrupts(irq); |
|
474 NKern::Unlock(); |
|
475 } |
|
476 // |
|
477 // TO DO: (mandatory) |
|
478 // |
|
479 // Enable transmission of data |
|
480 // |
|
481 if (r>=0) // only enable interrupt if there's more data to send |
|
482 { |
|
483 // |
|
484 // TO DO: (mandatory) |
|
485 // |
|
486 // Enable transmit interrupt in the Hardware (Interrupt::Enable() has already been called in Start()) |
|
487 // |
|
488 } |
|
489 } |
|
490 |
|
491 TUint DCommTemplate::Signals() const |
|
492 // |
|
493 // Read and translate the modem lines |
|
494 // |
|
495 { |
|
496 TUint signals=0; |
|
497 // |
|
498 // TO DO: (mandatory) |
|
499 // |
|
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: |
|
502 // - KSignalDTR, |
|
503 // - KSignalRTS, |
|
504 // - KSignalDSR, |
|
505 // - KSignalCTS, |
|
506 // - KSignalDCD. |
|
507 // |
|
508 return signals; |
|
509 } |
|
510 |
|
511 void DCommTemplate::SetSignals(TUint aSetMask, TUint aClearMask) |
|
512 // |
|
513 // Set signals. |
|
514 // |
|
515 { |
|
516 // |
|
517 // TO DO: (mandatory) |
|
518 // |
|
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: |
|
522 // - KSignalDTR, |
|
523 // - KSignalRTS, |
|
524 // |
|
525 } |
|
526 |
|
527 TInt DCommTemplate::ValidateConfig(const TCommConfigV01 &aConfig) const |
|
528 // |
|
529 // Check a config structure. |
|
530 // |
|
531 { |
|
532 // |
|
533 // TO DO: (mandatory) |
|
534 // |
|
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) |
|
538 /** @see TParity */ |
|
539 // - aConfig.iRate (contains one of EBpsXXX) |
|
540 /** @see TBps */ |
|
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) |
|
548 /** @see TFifo */ |
|
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) |
|
556 /** @see TSir */ |
|
557 // - aConfig.iSIRSettings (contains one of KConfigSIRXXX) |
|
558 // and returns KErrNotSupported if the UART corresponding to iUnit does not support this configuration |
|
559 // |
|
560 return KErrNone; |
|
561 } |
|
562 |
|
563 void DCommTemplate::CheckConfig(TCommConfigV01& aConfig) |
|
564 { |
|
565 // |
|
566 // TO DO: (optional) |
|
567 // |
|
568 // Validates the default configuration that is defined when a channel is first opened |
|
569 // |
|
570 } |
|
571 |
|
572 TInt DCommTemplate::DisableIrqs() |
|
573 // |
|
574 // Disable normal interrupts |
|
575 // |
|
576 { |
|
577 |
|
578 return NKern::DisableInterrupts(1); |
|
579 } |
|
580 |
|
581 void DCommTemplate::RestoreIrqs(TInt aLevel) |
|
582 // |
|
583 // Restore normal interrupts |
|
584 // |
|
585 { |
|
586 |
|
587 NKern::RestoreInterrupts(aLevel); |
|
588 } |
|
589 |
|
590 void DCommTemplate::Configure(TCommConfigV01 &aConfig) |
|
591 // |
|
592 // Configure the UART from aConfig |
|
593 // |
|
594 { |
|
595 Kern::PollingWait(FinishedTransmitting,this,3,100); // wait for uart to stop tranmitting |
|
596 |
|
597 // |
|
598 // TO DO: (optional) |
|
599 // |
|
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. |
|
602 // |
|
603 |
|
604 // |
|
605 // TO DO: (mandatory) |
|
606 // |
|
607 // Set communications parameters such as: |
|
608 // - Baud rate |
|
609 // - Parity |
|
610 // - Stop bits |
|
611 // - Data bits |
|
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 |
|
618 // |
|
619 |
|
620 // |
|
621 // TO DO: (optional) |
|
622 // |
|
623 // If the UART corresponding to iUnit supports IR may need to set up IR transceiver |
|
624 // |
|
625 } |
|
626 |
|
627 void DCommTemplate::Caps(TDes8 &aCaps) const |
|
628 // |
|
629 // return our caps |
|
630 // |
|
631 { |
|
632 GetTemplateCommsCaps(aCaps,iUnit); |
|
633 } |
|
634 |
|
635 void DCommTemplate::Isr(TAny* aPtr) |
|
636 // |
|
637 // Service the UART interrupt |
|
638 // |
|
639 { |
|
640 DCommTemplate& d=*(DCommTemplate*)aPtr; |
|
641 d.iInInterrupt=1; // going in... |
|
642 // TUint portAddr=d.iPortAddr; TO DO: (mandatory): Uncomment this |
|
643 |
|
644 // |
|
645 // TO DO: (mandatory) |
|
646 // |
|
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: |
|
650 // |
|
651 // if((Received character Interrupts) || (Error in received character Interupt)) TO DO: (mandatory): Implement |
|
652 { |
|
653 TUint rx[32]; |
|
654 TUint xon=d.iLdd->iRxXonChar; |
|
655 TUint xoff=d.iLdd->iRxXoffChar; |
|
656 TInt rxi=0; |
|
657 TInt x=0; |
|
658 TUint ch=0; |
|
659 // while((Receive FIFO not empty) && Kern::PowerGood()) TO DO: (mandatory): Implement |
|
660 { |
|
661 TUint regStatus1=0; |
|
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); |
|
666 |
|
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 |
|
670 { |
|
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; |
|
677 } |
|
678 if (ch==xon) |
|
679 x=1; |
|
680 else if (ch==xoff) |
|
681 x=-1; |
|
682 else |
|
683 rx[rxi++]=ch; |
|
684 } |
|
685 d.ReceiveIsr(rx,rxi,x); |
|
686 } |
|
687 // if((Transmitted character Interrupt)) TO DO: (mandatory): Implement |
|
688 { |
|
689 while(/* (Transmit FIFO Not full) && */ Kern::PowerGood()) // TO DO: (mandatory): Implement |
|
690 { |
|
691 TInt r=d.TransmitIsr(); |
|
692 if(r<0) |
|
693 { |
|
694 //no more to send |
|
695 // |
|
696 // TO DO: (mandatory) |
|
697 // |
|
698 // Disable the Transmit Interrupt in Hardware |
|
699 d.iTransmitting=EFalse; |
|
700 break; |
|
701 } |
|
702 // (write transmit character to output FIFO or Data register) TO DO: (mandatory): Implement |
|
703 } |
|
704 d.CheckTxBuffer(); |
|
705 } |
|
706 // if((Modem Signals changed Interrupt)) TO DO: (mandatory): Implement |
|
707 { |
|
708 TUint signals=d.Signals()&KDTEInputSignals; |
|
709 if (signals != d.iSignals) |
|
710 { |
|
711 d.iSignals=signals; |
|
712 d.iLdd->StateIsr(signals); |
|
713 } |
|
714 } |
|
715 d.iInInterrupt=0; // going out... |
|
716 } |
|
717 |
|
718 DECLARE_STANDARD_PDD() |
|
719 { |
|
720 return new DDriverComm; |
|
721 } |
|
722 |