|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74" xml:lang="en"><title>Channel |
|
13 Implementation</title><shortdesc>Describes how to implement <codeph>DComm</codeph> to drive a serial |
|
14 port hardware.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
15 <p>A physical channel defines the interface between the logical device and |
|
16 the physical device. The Serial Port Driver physical channel interface is |
|
17 defined by the <codeph>DComm</codeph> class. </p> |
|
18 <p>The <codeph>DComm</codeph> class is defined in: <filepath>...\e32\include\drivers\comm.h</filepath>, |
|
19 which is exported to <filepath>epoc32\include\drivers</filepath>: </p> |
|
20 <codeblock id="GUID-F9E58262-51AA-5A58-A113-3FA994F00156" xml:space="preserve">class DComm : public DBase |
|
21 { |
|
22 public: |
|
23 virtual TInt Start() =0; |
|
24 virtual void Stop(TStopMode aMode) =0; |
|
25 virtual void Break(TBool aState) =0; |
|
26 virtual void EnableTransmit() =0; |
|
27 virtual TUint Signals() const =0; |
|
28 virtual void SetSignals(TUint aSetMask,TUint aClearMask) =0; |
|
29 virtual TInt ValidateConfig(const TCommConfigV01 &aConfig) const =0; |
|
30 virtual void Configure(TCommConfigV01 &aConfig) =0; |
|
31 virtual void Caps(TDes8 &aCaps) const =0; |
|
32 virtual void CheckConfig(TCommConfigV01& aConfig)=0; |
|
33 virtual TInt DisableIrqs()=0; |
|
34 virtual void RestoreIrqs(TInt aIrq)=0; |
|
35 virtual TDfcQue* DfcQ(TInt aUnit)=0; |
|
36 inline TBool PowerGood(); |
|
37 inline void SetCurrent(TInt aCurrent); |
|
38 inline void ReceiveIsr(TUint* aChar, TInt aCount, TInt aXonXoff); |
|
39 inline TInt TransmitIsr();inline void CheckTxBuffer(); |
|
40 inline void StateIsr(TUint aSignals); |
|
41 inline TBool Transmitting(); |
|
42 public: |
|
43 DChannelComm *iLdd; |
|
44 TBool iTransmitting; |
|
45 }; |
|
46 </codeblock> |
|
47 <p>Note that <codeph>DComm</codeph> defines the minimum set of functions to |
|
48 be used by the LDD. A real physical channel object, typically, requires the |
|
49 addition of an interrupt handler, some DFC callback routines (if these are |
|
50 not handled in the LDD itself) and various other state variables. </p> |
|
51 <section id="GUID-B0D61B54-EDF3-4804-9B1E-370C36E01708"><title>DCommVariant constructor</title> <p>Implement the constructor |
|
52 for the channel object. Since there is no unit number argument, the constructor |
|
53 is limited to initialising only those members that are common across all possible |
|
54 channels, with no access to any specific hardware. </p> </section> |
|
55 <section id="GUID-550681C3-F1A6-4298-BAA5-C6F2D9D61624"><title>DCommVariant destructor</title> <p>Implement the destructor |
|
56 for the channel object. It should release any hardware and Symbian platform |
|
57 resources that have been allocated to the driver, typically unbinding the |
|
58 UART interrupt ISR, and any private DFCs that are still in use. The destructor |
|
59 merely unbinds the interrupt as no channel specific DFCs are active at destructor |
|
60 invocation. </p> </section> |
|
61 <section id="GUID-8254536B-E938-4B86-A735-798DD03E3456"><title>DoCreate()</title> <p>Implement the <codeph>DoCreate()</codeph> channel |
|
62 initialisation function for the UART driver. In general, defining a <codeph>DoCreate()</codeph> function |
|
63 is not mandated by the device driver framework but is useful for drivers that |
|
64 make use of unit numbers. This is called by the factory object’s <xref href="GUID-6DE69F29-45B0-5E62-AA13-DA4041B1BC46.dita#GUID-6DE69F29-45B0-5E62-AA13-DA4041B1BC46/GUID-48EF94F9-ACBC-58DA-9F0E-4034E56C6C74">Create()</xref> function after the device object’s allocation has succeeded. </p> <p>Typical |
|
65 operations performed by this function are to setup any channel specific hardware |
|
66 states and bind the driver’s ISR to the (possibly channel specific) interrupt |
|
67 channel, as well as enabling the UART hardware itself. However, since the <xref href="GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74.dita#GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74/GUID-0CAA6D27-FE2E-5569-8747-EB3D4976E7FD">Start()</xref> function |
|
68 has not yet been called, it should not enable the UART interrupts/poll routines |
|
69 which would actively buffer incoming data; any data I/O requests should be |
|
70 discarded until the driver’s <xref href="GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74.dita#GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74/GUID-0CAA6D27-FE2E-5569-8747-EB3D4976E7FD">Start()</xref> routine |
|
71 has been called. </p> </section> |
|
72 <section id="GUID-0CAA6D27-FE2E-5569-8747-EB3D4976E7FD"><title>Start()</title> <p> Implement |
|
73 the <codeph>Start()</codeph> function. This should enable the driver’s receive |
|
74 path.</p><p> Received characters are placed in the LDD upstream buffer, either |
|
75 by the interrupt handler routine, or by a polling routine that tests for the |
|
76 existence of received characters (and their associated error state). This |
|
77 is done by calling the LDD’s <codeph>ReceiveIsr()</codeph> routine, with a |
|
78 pointer to the buffered characters, a count and a flag indicating whether |
|
79 the XON or XOFF flow control characters have been received.</p><p>The function |
|
80 is called by the LDD when the owning thread opens the device channel. It should |
|
81 complete any UART data I/O enabling that has not already been performed in |
|
82 the <codeph>DoCreate()</codeph> function, i.e. the enabling of UART receive |
|
83 interrupt processing as a minimum. After this function returns, it is expected |
|
84 that incoming data will be placed in a (local) buffer and passed upstream |
|
85 to the LDD, until <xref href="GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74.dita#GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74/GUID-9428082D-581D-530B-8838-1DBF6D0EB8E7">Stop()</xref> is |
|
86 invoked. Note that since there may have been line activity prior to this call, |
|
87 it may be necessary to reset the UART state, as we do not want to report errors/states |
|
88 that may have occurred before the UART was (logically) enabled.</p></section> |
|
89 <section id="GUID-9428082D-581D-530B-8838-1DBF6D0EB8E7"><title>Stop()</title><p>Implement |
|
90 the <codeph>Stop()</codeph> function. This should disable the driver’s transmit |
|
91 and receive paths. </p><p>Depending on the type of stop requested, i.e. emergency |
|
92 power down, or otherwise, <codeph>Stop()</codeph> may not wait for the UART |
|
93 to finish transmitting any characters stored in the transmit FIFO queue. All |
|
94 receive paths are stopped instantly and any characters that may be in the |
|
95 receive FIFO queue are ignored. </p><p>The function is called by the LDD when |
|
96 the owning thread closes the device channel. At this point, the UART device |
|
97 should revert to the state in which all data I/O requests are ignored or failed. |
|
98 To save OS resources the natural method to accomplish this is to disable the |
|
99 UART interrupt processing or disable the UART itself. It may also be necessary |
|
100 to cancel any DFCs queued, so that event notifications are not sent to the |
|
101 LDD after it has requested an end to I/O. </p></section> |
|
102 <section id="GUID-5E4B6533-75F5-47FB-A4DF-55FAA1E1B973"><title>DfcQ()</title><p>Implement the <codeph>DfcQ()</codeph> function. |
|
103 This should return the DFC queue on which the LDD will install its DFCs. Usually |
|
104 the standard low priority kernel DFC queue 0 is returned. </p></section> |
|
105 <section id="GUID-ADC89B5B-0E29-4723-92E6-A6F1A5604710"><title>Break()</title><p>Implement the <codeph>Break()</codeph> function. |
|
106 This starts or ends a BREAK condition on the wire. </p><p>This operation is |
|
107 explicitly requested by the owning thread through the LDD. A break state requires |
|
108 the forcing of the line into an abnormal state, which violates standard data |
|
109 format timings (a form of out of band signalling), and is detected by the |
|
110 remote device and is usually used to force it to cycle through its baud rate |
|
111 detection modes. Forcing a break state requires that the PDD explicitly set |
|
112 some state in the UART hardware. </p></section> |
|
113 <section id="GUID-82A259A7-54F7-536A-B829-31C0AF3C5C81"><title>Signals()</title><p>Implement |
|
114 the <codeph>Signals()</codeph> function. This returns the state of the flow |
|
115 and MODEM control inputs, ie. DCD, DSR, CTS and RI (if implemented on the |
|
116 device itself). This function is called by the LDD to return the state of |
|
117 all the handshaking lines so that it can decide whether further data I/O operations |
|
118 are allowed. </p></section> |
|
119 <section id="GUID-492D86E5-BEEF-4408-B6E0-6DDA1244CA74"><title>SetSignals()</title><p>Implement the <codeph>SetSignals()</codeph> function. |
|
120 This controls the state of the flow and MODEM control outputs. It is used |
|
121 by the LDD to control MODEM handshaking and line failure detection, and can |
|
122 be invoked in response to a specific user request to change the handshake |
|
123 signal’s state, or when the LDD itself decides that the output lines states |
|
124 should be changed in response to some transfer state (e.g. requesting no further |
|
125 transmissions if buffer availability runs low). </p></section> |
|
126 <section id="GUID-CB1FA26C-5D29-50ED-AF40-8CC579AF776F"><title>Caps()</title><p>Implement |
|
127 the <codeph>Caps()</codeph> function. This returns the driver supported configurations: |
|
128 speed, format, and handshaking. </p><p>It is called by the LDD in response |
|
129 to a user request for the device's capabilities. The PDD must fill a <xref href="GUID-98A18771-CA6D-3B68-8784-449CDBEC3D88.dita"><apiname>TCommCapsV02</apiname></xref> object, |
|
130 with the capabilities for that port. </p><p>The object is defined in <filepath>d32comm.h</filepath>: </p><codeblock id="GUID-A95D8753-E574-5C86-85DC-6AA10F635612" xml:space="preserve">class TCommCapsV01 |
|
131 { |
|
132 public: |
|
133 TUint iRate; |
|
134 TUint iDataBits; |
|
135 TUint iStopBits; |
|
136 TUint iParity; |
|
137 TUint iHandshake; |
|
138 TUint iSignals; |
|
139 TUint iFifo; |
|
140 TUint iSIR; |
|
141 }; |
|
142 |
|
143 class TCommCapsV02 : public TCommCapsV01 |
|
144 { |
|
145 public: |
|
146 TUint iNotificationCaps; |
|
147 TUint iRoleCaps; |
|
148 TUint iFlowControlCaps; |
|
149 };</codeblock> <p>The base object, <xref href="GUID-BDBB61A7-18BC-3C85-A258-77D8B16621AD.dita"><apiname>TCommCapsV01</apiname></xref>, defines |
|
150 capabilities in terms of: </p> <ul> |
|
151 <li id="GUID-7AE03D23-1013-5522-B219-23153E1B7798"><p>data rate </p> </li> |
|
152 <li id="GUID-E2FBD4C1-B704-592A-B3A2-1BCFFC7E5451"><p>word format (i.e. parity, |
|
153 data bits, stop bits) </p> </li> |
|
154 <li id="GUID-525050DD-8ACE-5580-BDF7-3717295D704E"><p>flow control lines </p> </li> |
|
155 <li id="GUID-B5DBE4E6-8184-522A-856A-9BD17E76FF33"><p>MODEM control lines </p> </li> |
|
156 <li id="GUID-62ACC296-4B9B-59D3-8531-480E04264FE0"><p>IrDA support. </p> </li> |
|
157 </ul> <p>Each attribute range is passed as a bitfield of possible settings, |
|
158 all assumed to be orthogonal, i.e. each attribute can assume all the values |
|
159 independently of the other attributes. </p> <p>The attribute bitfields are |
|
160 defined in <filepath>d32comm.h</filepath>. </p> <p>The <codeph>iSIR</codeph> attribute |
|
161 in <xref href="GUID-BDBB61A7-18BC-3C85-A258-77D8B16621AD.dita"><apiname>TCommCapsV01</apiname></xref> indicates whether the port can support |
|
162 slow infrared protocol. </p> <p>The <codeph>iNotificationCaps</codeph> attribute |
|
163 in <xref href="GUID-98A18771-CA6D-3B68-8784-449CDBEC3D88.dita"><apiname>TCommCapsV02</apiname></xref> allows the driver to describe its ability |
|
164 to report asynchronous events, if requested to do so by the client thread. |
|
165 The only useful applications seem to be to report data arrival and handshake |
|
166 line status change, although fields exist for other capabilities. </p> <p>The <codeph>iRoleCaps</codeph> attribute |
|
167 in <xref href="GUID-98A18771-CA6D-3B68-8784-449CDBEC3D88.dita"><apiname>TCommCapsV02</apiname></xref> is intended to indicate that the device |
|
168 is capable of acting as a DCE as well as a DTE, i.e. that the port can be |
|
169 configured to act like a MODEM port. This essentially reverses the normal |
|
170 I/O of the status lines, and could add functionality such as ring indication. |
|
171 Normal UART devices will never need to change this field from the default, |
|
172 i.e. DTE device personality. </p> <p>The <codeph>iFlowControlCaps</codeph> field |
|
173 in <xref href="GUID-98A18771-CA6D-3B68-8784-449CDBEC3D88.dita"><apiname>TCommCapsV02</apiname></xref> is unused and should be set to 0. </p> <p>The <codeph>iHandshake</codeph> field |
|
174 in <xref href="GUID-BDBB61A7-18BC-3C85-A258-77D8B16621AD.dita"><apiname>TCommCapsV01</apiname></xref> describes the flow control signal support |
|
175 on the device. Input signals have attributes “Obey” and “Fail” e.g. ObeyCts, |
|
176 FailCts. Output signals have only the “Free” attribute, which indicates they |
|
177 can be driven (via a call to <xref href="GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74.dita#GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74/GUID-82A259A7-54F7-536A-B829-31C0AF3C5C81">Signals()</xref>) |
|
178 to any state, independent of the internal state of the UART, i.e. they are |
|
179 entirely under LDD control. The Fail attribute implies that the LDD will deem |
|
180 operations to have failed if an input line thus labelled becomes disasserted. |
|
181 This means that the PDD can report these signal states asynchronously. If, |
|
182 for example, a change in CTS state can generate an interrupt, then the PDD |
|
183 should report it as possessing both Obey and Fail attributes, whereas if the |
|
184 DCD line cannot generate an asynchronous event, it should merely present itself |
|
185 as “Obey”. If the line is unimplemented then neither attribute should be reported. </p> </section> |
|
186 <section id="GUID-DA860E4A-4240-4C16-B1C0-5E9B7C96F9E8"><title>Configure()</title> <p>Implement the <codeph>Configure()</codeph> function. |
|
187 This configures the UART device according to the configuration data passed |
|
188 into the function. </p> <p>Configuration data is encapsulated by a <xref href="GUID-0CBAE946-AB8E-3114-89FC-9591125C4BDC.dita"><apiname>TCommConfigV02</apiname></xref> object: </p> <codeblock id="GUID-275DAD25-9EF9-5084-A82B-8E2392CB14E8" xml:space="preserve">class TCommConfigV01 |
|
189 { |
|
190 public: |
|
191 TBps iRate; |
|
192 TDataBits iDataBits; |
|
193 TStopBits iStopBits; |
|
194 TParity iParity; |
|
195 TUint iHandshake; |
|
196 TUint iParityError; |
|
197 TUint iFifo; |
|
198 TInt iSpecialRate; |
|
199 TInt iTerminatorCount; |
|
200 TText8 iTerminator[KConfigMaxTerminators]; |
|
201 TText8 iXonChar; |
|
202 TText8 iXoffChar; |
|
203 TText8 iParityErrorChar; |
|
204 TSir iSIREnable; |
|
205 TUint iSIRSettings; |
|
206 }; |
|
207 |
|
208 class TCommConfigV02: public TCommConfigV01 |
|
209 { |
|
210 public: |
|
211 TInt iTxShutdownTimeout; |
|
212 }; |
|
213 </codeblock> <p>This function is called by the LDD when the physical channel |
|
214 is opened. The default configuration is set by the LDD when the <codeph>Dcomm</codeph> object |
|
215 is constructed, but the user can override the configuration with a <codeph>SetConfig</codeph> request |
|
216 on the opened channel. The configuration is described by specifying a set |
|
217 of individual capability attributes from the supported ranges returned in |
|
218 the <xref href="GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74.dita#GUID-AB9175EB-1B61-5341-B6B9-5613A7862D74/GUID-CB1FA26C-5D29-50ED-AF40-8CC579AF776F">Caps()</xref> call. </p> <p>Note |
|
219 that the <codeph>iTerminatorCount</codeph>, the <codeph>iTerminatorArray</codeph> and<codeph> iSpecialRate</codeph> are |
|
220 currently unused. The <codeph>iParityErrorChar</codeph> replaces the character |
|
221 that the UART determined had a parity violation. This can be used to send |
|
222 a prearranged escape character to the upstream LDD. </p> </section> |
|
223 <section id="GUID-509C63E0-09D9-48F1-8ECB-F18377B73E8A"><title>CheckConfig()</title> <p>Implement the <codeph>CheckConfig()</codeph> function. |
|
224 This is used by autosensing UARTs to pass detected configuration upstream |
|
225 to the LDD. This is called by the LDD when it creates the initial channel |
|
226 to allow the autosensed state to override any default it has set. If the UART |
|
227 device cannot perform autosensing, and most cannot, then the <codeph>CheckConfig()</codeph> function |
|
228 should leave the parameter buffer unchanged. </p> </section> |
|
229 <section id="GUID-6F26F95A-7115-4E07-BA72-7AEF75DC2912"><title>ValidateConfig()</title> <p>Implement the <codeph>ValidateConfig()</codeph> function. |
|
230 This returns true if the specified configuration is supported by the driver. |
|
231 This should never return false if the correct capabilities have been setup, |
|
232 but may be used to check for cases where, for example, a specific set of attributes |
|
233 cannot be applied together. As an example, a data format word size may not |
|
234 be generated for some specific baud rate. </p> </section> |
|
235 <section id="GUID-10FB213C-47B3-4CFF-AB2B-5868AE4531E0"><title>DisableIrqs()</title> <p>Implement the <codeph>DisableIrqs()</codeph> function. |
|
236 This is called by the LDD to disable (all) interrupts during critical sections, |
|
237 for example, during LDD buffer manipulation. It calls the kernel utility to |
|
238 perform the task. </p> </section> |
|
239 <section id="GUID-BFE0DF32-3D2A-4D86-8BEE-6EB5AF32C3BB"><title>RestoreIrqs()</title> <p>Implement the <codeph>RestoreIrqs()</codeph> function, |
|
240 called by the LDD to enable (all) interrupts after critical sections have |
|
241 completed. Calls the kernel utility to perform the task. </p> </section> |
|
242 <section id="GUID-96B9D6FE-1E2C-45C0-B7F4-E5CF9B5BD802"><title>EnableTransmit()</title> <p>Implement the <codeph>EnableTransmit()</codeph> function. |
|
243 This initialises the UART transmit hardware, and the transmit ISR code path. |
|
244 This function can be called from the ISR (on receipt of an unblocking XON |
|
245 character), or to start a transmission of a LDD originated data buffer. It |
|
246 causes the UART to generate Tx service interrupts as it finishes transmitting |
|
247 a FIFOs worth of data, so that the entire buffer (passed by the LDD) can be |
|
248 sent under interrupt control. </p> </section> |
|
249 <section id="GUID-593C5E94-A188-48C4-BB02-07268735270A"><title>Data handling routines</title> <p>Implement the main data |
|
250 handling routines. These are entirely dependent on the UART hardware interface |
|
251 and cannot therefore be described generally. They are typically driven by |
|
252 the interrupt service routine as asynchronous events from the UART (eg. data |
|
253 received, finished transmission of data, change in handshaking/flow control |
|
254 inputs) occur. </p> <p>The main ISR is typically driven by an interrupt multiplexed |
|
255 from all the sources in the UART. The ISR, therefore, needs to determine which |
|
256 of the interrupt sources requires attention. Since the most critical source |
|
257 is the data received state, as this requires that the data is processed before |
|
258 following data overwrites earlier data, then this is usually the signal to |
|
259 be checked first. To avoid wasting time, the error state of the data is also |
|
260 checked – data that has bad parity or framing must be noted as such. Typically |
|
261 the receive path will save the currently available data into a temporary buffer, |
|
262 and queue a DFC to process the data further at a later time, when more client |
|
263 thread context is available (though this is a function of the LDD). The receive |
|
264 ISRr just passes the location of the ISR buffer into an LDD function which |
|
265 queues a DFC to process it. </p> <p>The transmit path, called when the transmit |
|
266 FIFO contents drop below a programmable number, merely requests more data |
|
267 from the LDD. If there is none available it disables the transmit interrupt |
|
268 so as to prevent further requests when there is no data to be sent. Further |
|
269 data to transmit will cause the transmit FIFO empty interrupt to be re-enabled. |
|
270 Hence the start of any transmission is always performed on an explicit start |
|
271 request from the LDD and then continues under PDD interrupt control until |
|
272 the source data is exhausted. </p> <p>The status notification path is present |
|
273 to inform the upstream LDD of changes in the input status signals (MODEM and |
|
274 flow control status). The UART can generate interrupts when any input handshake |
|
275 line changes state – the ISR merely reads the current state and queues a handler |
|
276 DFC so that the LDD can be informed. The LDD is responsible for determining |
|
277 what status change has occurred and dealing with it. </p> </section> |
|
278 </conbody></concept> |