|
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-B97BAC2E-04E3-4979-BACE-9C46BADE912E" xml:lang="en"><title>Deferred |
|
13 Function Calls</title><shortdesc>This document describes how Deferred Function Calls are used to |
|
14 implement asynchronous requests.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
15 <section id="GUID-1F20014A-5F1E-48B3-AEB8-ED1922452A84"> |
|
16 <title>Deferred function calls</title> <p>Asynchronous request processing |
|
17 is normally done in a Deferred Function Call (DFC). The second stage of interrupt |
|
18 handling is deferred to run as a DFC, which runs in a non-critical context. </p> <p>Different |
|
19 asynchronous requests can be handled using a single or multiple DFCs. The |
|
20 number of DFCs to be created must be decided when the driver is designed. |
|
21 For example, a driver that handles at a time an asynchronous receive request |
|
22 and a transmit request would create two DFCs each for receive and transmit. </p> |
|
23 </section> |
|
24 <section id="GUID-5439E26D-754A-46F3-B607-D229BF5B8A8C"><title>Creation</title> <p>DFCs |
|
25 are created using <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita"><apiname>TDfc</apiname></xref> objects. </p> <p>The DFC is initialised |
|
26 with a DFC callback function, a pointer to an object to be passed to the callback |
|
27 function, and a priority. It can also provide the DFC queue to be used by |
|
28 this DFC at the time of construction. </p> <codeblock id="GUID-B3918CAB-F168-5992-BFA9-868648D07083" xml:space="preserve">TDfc iRxDfc; |
|
29 iRxDfc(RxDataDfc,this,1); |
|
30 or |
|
31 iRxDfc(RxDataDfc,this,iDfcQ,1);</codeblock></section> |
|
32 <section id="GUID-886457DF-0DB5-4447-BC9B-EB43060A5C6B"><title>Queuing</title> <p>To |
|
33 initiate the process of DFC functionality, the DFC object must be queued to |
|
34 the DFC queue associated with the Kernel thread. </p> <p>Before adding the |
|
35 DFC to a DFC queue of the thread, it must be associated with the queue (<xref href="GUID-24B2FEDB-9273-351F-A1C6-6F5F91BF83B7.dita"><apiname>TDfcQue</apiname></xref>) |
|
36 object. This can be either done at the time of construction, or can be set |
|
37 later, by calling <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-E3458CD4-7A1C-3FBD-A7FB-488A9C92AE42"><apiname>TDfc::SetDfcQ()</apiname></xref>. </p> <codeblock id="GUID-B57B1C37-A1A5-5C85-AED8-FDD8DBE84280" xml:space="preserve">... |
|
38 // Associate the Tx and Rx DFCs with the same queue set to receive |
|
39 // the client messages for this driver. SetDfcQ() sets up the DFC |
|
40 // queue for the DFCs constructed for Tx and Rx |
|
41 // |
|
42 iRxDfc.SetDfcQ(iDfcQ); |
|
43 ...</codeblock> <p> <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-18073EBB-D91B-3AC8-87A2-424AEDD4D7A4"><apiname> TDfc::Add()</apiname></xref> or <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-F6F0C858-8EB2-387B-AE1A-F04B51CE4CED"><apiname>TDfc::Enque()</apiname></xref> is |
|
44 used to add the DFC object to the DFC queue. From an ISR, <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-18073EBB-D91B-3AC8-87A2-424AEDD4D7A4"><apiname>TDfc::Add()</apiname></xref> is |
|
45 used. From a thread, <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-F6F0C858-8EB2-387B-AE1A-F04B51CE4CED"><apiname>TDfc::Enque()</apiname></xref> is used. If preemption |
|
46 is disabled, <codeph>TDfc::Add()</codeph> could also be used. </p> <codeblock id="GUID-9FBB6881-4BA9-534E-86C7-3A0167E9159C" xml:space="preserve">// TDfc::Add() will queue an IDFC or a DFC from an ISR. This function |
|
47 // is the only way to queue an IDFC and is the only way to queue a |
|
48 // DFC from an ISR. To queue a DFC from an IDFC or a thread either |
|
49 // TDfc::Enque() or TDfc::DoEnque() should be used. This function |
|
50 // does nothing if the IDFC/DFC is already queued. |
|
51 // |
|
52 iRxDfc.Add(); |
|
53 </codeblock></section> |
|
54 <section id="GUID-E0B9073A-1554-4085-BE24-E27633B7EDF2"><title>Callback function</title> <p>The |
|
55 DFC callback function is a static function called when a DFC is executed. |
|
56 A pointer to this function is provided at the time of DFC object creation. |
|
57 This function implements the deferred functionality of an asynchronous request, |
|
58 such as reading or writing data from or to an I/O peripheral. It would then |
|
59 either complete the request or start another operation. </p> <codeblock id="GUID-5682EDE1-8397-592D-82CE-78DF11487512" xml:space="preserve">static void RxDataDfc(TAny* aPtr);</codeblock></section> |
|
60 <section id="GUID-A57C3C99-3032-48CD-A800-E9EE7DCDF4E3"><title>Cancellation</title> <p>A |
|
61 DFC function must be cancelled while cleaning up resources, for example, when |
|
62 closing the channel. The function <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-9851B90B-8D05-3C86-B083-44C4564AC140"><apiname>TDfc::Cancel()</apiname></xref> cancels |
|
63 the DFC if it is already queued. It does nothing if a DFC is not queued. It |
|
64 must be called to avoid orphaned DFCs. </p> <codeblock id="GUID-CD926E3D-13E8-51C4-B224-8150FD4D70DB" xml:space="preserve">... |
|
65 // If it is a Transmit request, cancel the Transmit DFC. |
|
66 // TDfc::Cancel() cancels the DFC if it is already queued. It |
|
67 // does nothing if DFC is not queued. |
|
68 // |
|
69 iTxDfc.Cancel(); |
|
70 ...</codeblock></section> |
|
71 </conbody></concept> |