]> begriffs open source - cmsis/blob - CMSIS/DoxyGen/Driver/src/operation.md
Doc: Clean up of CMSIS-Driver docs, incl. change to markdown.
[cmsis] / CMSIS / DoxyGen / Driver / src / operation.md
1 # Theory of Operation {#theoryOperation}
2
3 [TOC]
4
5 This section gives an overview of the general operation of CMSIS-Drivers. It explains the \ref DriverFunctions that are
6 common in all CMSIS-Drivers along with the \ref CallSequence. The topic \ref Data_Xfer_Functions describes how data
7 read/write operations to the peripheral are implemented.
8
9 Each CMSIS-Driver defines an \ref AccessStruct for calling the various driver functions and each peripheral (that is accessed
10 via a CMSIS-Driver) has one \ref DriverInstances "Driver Instance".
11
12
13 ## Common Driver Functions {#DriverFunctions}
14
15 Each CMSIS-Driver contains these functions:
16
17  - `GetVersion`: can be called at any time to obtain version information of the driver interface.
18
19  - `GetCapabilities`: can be called at any time to obtain capabilities of the driver interface.
20
21  - `Initialize`: must be called before powering the peripheral using `PowerControl`. This function performs the following:
22      - allocate I/O resources.
23      - register an optional `SignalEvent` callback function.
24
25  - `SignalEvent`: is an optional callback function that is registered with the `Initialize` function. This callback
26    function is initiated from interrupt service routines and indicates hardware events or the completion of a data block
27    transfer operation.
28
29  - `PowerControl`: Controls the power profile of the peripheral and needs to be called after `Initialize`. Typically, three
30    power options are available (see \ref ARM_POWER_STATE):
31      - `ARM_POWER_FULL`: Peripheral is turned on and fully operational. The driver initializes the peripheral registers, interrupts, and (optionally) DMA.
32      - `ARM_POWER_LOW` : (optional) Peripheral is in low power mode and partially operational; usually, it can detect
33        external events and wake-up.
34      - `ARM_POWER_OFF`: Peripheral is turned off and not operational (pending operations are terminated). This is the state
35        after device reset.
36
37  - `Uninitialize`: Complementary function to Initialize. Releases the I/O pin resources used by the interface.
38
39  - `Control`: Several drivers provide a control function to configure communication parameters or execute miscellaneous
40    control functions.
41
42 The section \ref CallSequence contains more information on the operation of each function. Additional functions are specific
43 to each driver interface and are described in the individual sections of each driver.
44
45 ## Cortex-M Processor Mode {#ProcessorMode}
46
47 The CMSIS-Driver functions access peripherals and interrupts and are designed to execute in **Privileged** mode.
48 When calling CMSIS-Driver functions from RTOS threads, it should be ensure that these threads execute in **Privileged** mode.
49
50
51 ## Function Call Sequence {#CallSequence}
52
53 For normal operation of the driver, the API functions `GetVersion`, `GetCapabilities`, `Initialize`, `PowerControl`, `Uninitialize` are called in the following order:
54
55 \msc
56  a [label="", textcolor="indigo", linecolor="indigo", arclinecolor="indigo"],
57  b [label="", textcolor="blue", linecolor="blue", arclinecolor="blue"];
58
59  a rbox a [label="Middleware", linecolor="indigo"],
60  b rbox b [label="Driver", linecolor="blue"];
61  --- [label="Verify API version"];
62  a=>b [label="GetVersion ()", textcolor="gray", linecolor="gray"];
63  --- [label="Obtain driver features"];
64  a=>b [label="GetCapabilities (...)", textcolor="gray", linecolor="gray"];
65  ---  [label="Setup software resources"];
66  a=>b [label="Initialize (...)", textcolor="red", linecolor="red"];
67  --- [label="Setup the peripheral"];
68  a=>b  [label="PowerControl (ARM_POWER_FULL)", textcolor="red", linecolor="red"];
69  --- [label="Operate with the peripheral"];
70  a=>b [label="Data Transfer Functions"];
71  a<=b  [label="SignalEvent (...)"];
72  --- [label="Wait for external hardware events"];
73  a=>b  [label="PowerControl (ARM_POWER_LOW)"];
74  a<=b  [label="SignalEvent (...)"];
75  --- [label="Stop working with peripheral"];
76  a=>b [label="PowerControl (ARM_POWER_OFF)", textcolor="red", linecolor="red"];
77  a=>b [label="Uninitialize (...)", textcolor="red", linecolor="red"];
78 \endmsc
79
80 The functions `GetVersion` and `GetCapabilities` can be called any time to obtain the required information from the driver.
81 These functions return always the same information.
82
83
84 ### Start Sequence {#CS_start}
85
86 To start working with a peripheral the functions `Initialize` and `PowerControl` need to be called in this order:
87 ```c
88   drv->Initialize (...);                 // Allocate I/O pins
89   drv->PowerControl (ARM_POWER_FULL);    // Power up peripheral, setup IRQ/DMA
90 ```
91
92 - `Initialize` typically allocates the I/O resources (pins) for the peripheral. The function can be called multiple times;
93   if the I/O resources are already initialized it performs no operation and just returns with \ref ARM_DRIVER_OK.
94 - `PowerControl` (`ARM_POWER_FULL`) sets the peripheral registers including interrupt (NVIC) and optionally DMA.
95   The function can be called multiple times; if the registers are already set it performs no operation and just returns with \ref ARM_DRIVER_OK.
96
97 ### Stop Sequence {#CS_stop}
98
99 To stop working with a peripheral the functions `PowerControl` and `Uninitialize` need to be called in this order:
100 ```c
101   drv->PowerControl (ARM_POWER_OFF);     // Terminate any pending transfers, reset IRQ/DMA, power off peripheral
102   drv->Uninitialize (...);               // Release I/O pins
103 ```
104
105 The functions `PowerControl` and `Uninitialize` always execute and can be used to put the peripheral into a **Safe State**,
106 for example after any data transmission errors.  To restart the peripheral in a error condition, you should first execute
107 the \ref CS_stop and then the \ref CS_start.
108
109 - `PowerControl` (`ARM_POWER_OFF`) terminates any pending data transfers with the peripheral, disables the peripheral and leaves it in a defined mode (typically the reset state).
110     - when DMA is used it is disabled (including the interrupts)
111     - peripheral interrupts are disabled on NVIC level
112     - the peripheral is reset using a dedicated reset mechanism (if available) or by clearing the peripheral registers
113     - pending peripheral interrupts are cleared on NVIC level
114     - driver variables are cleared
115 - `Uninitialize` always releases I/O pin resources.
116
117 ##  Shared I/O Pins {#Share_IO}
118
119 All CMSIS-Driver provide a \ref CS_start and \ref CS_stop. Therefore two different drivers can share the same I/O pins, for example UART1 and SPI1 can have overlapping I/O pins. In this case the communication channels can be used as shown below:
120
121 ```c
122   SPI1drv->Initialize (...);                // Start SPI1
123   SPI1drv->PowerControl (ARM_POWER_FULL);
124    ...                                      // Do operations with SPI1
125   SPI1drv->PowerControl (ARM_POWER_OFF);    // Stop SPI1
126   SPI1drv->Uninitialize ();
127    ...
128   USART1drv->Initialize (...);              // Start USART1
129   USART1drv->PowerControl (ARM_POWER_FULL);
130    ...                                      // Do operations with USART1
131   USART1drv->PowerControl (ARM_POWER_OFF);  // Stop USART1
132   USART1drv->Uninitialize ();
133 ```
134
135 ## Data Transfer Functions {#Data_Xfer_Functions}
136
137 A CMSIS-Driver implements non-blocking functions to transfer data to a peripheral. This means that the driver configures the
138 read or write access to the peripheral and instantly returns to the calling application.  The function names for data
139 transfer end with:
140  - `Send` to write data to a peripheral.
141  - `Receive` to read data from a peripheral.
142  - `Transfer` to indicate combined read/write operations to a peripheral.
143
144 During a data transfer, the application can query the number of transferred data items using functions named
145 <b>Get<i>xxx</i>Count</b>. On completion of a data transfer, the driver calls a callback function with a specific event code.
146
147 During the data exchange with the peripheral, the application can decide to:
148  - Wait (using an RTOS scheduler) for the callback completion event. The RTOS is controlled by the application code which
149    makes the driver itself RTOS independent.
150  - Use polling functions that return the number of transferred data items to show progress information or partly read or fill
151    data transfer buffers.
152  - Prepare another data transfer buffer for the next data transfer.
153
154 The following diagram shows the basic communication flow when using the `_Send` function in an application.
155
156 ![Non-blocking Send Function](./images/Non_blocking_transmit_small.png)
157
158 ## Access Struct {#AccessStruct}
159
160 A CMSIS-Driver publishes an \ref AccessStruct with the data type name `ARM_DRIVER_xxxx` that gives to access the driver
161 functions.
162
163 **Code Example:** Function Access of the SPI driver
164 ```c
165 typedef struct _ARM_DRIVER_SPI {
166   ARM_DRIVER_VERSION   (*GetVersion)      (void);
167   ARM_SPI_CAPABILITIES (*GetCapabilities) (void);
168   int32_t              (*Initialize)      (ARM_SPI_SignalEvent_t cb_event);
169   int32_t              (*Uninitialize)    (void);
170   int32_t              (*PowerControl)    (ARM_POWER_STATE state);
171   int32_t              (*Send)            (const void *data, uint32_t num);
172   int32_t              (*Receive)         (      void *data, uint32_t num);
173   int32_t              (*Transfer)        (const void *data_out, void *data_in, uint32_t num);
174   uint32_t             (*GetDataCount)    (void);
175   int32_t              (*Control)         (uint32_t control, uint32_t arg);
176   ARM_SPI_STATUS       (*GetStatus)       (void);
177 } const ARM_DRIVER_SPI;
178 ```
179
180 ### Driver Instances {#DriverInstances}
181
182 A device may offer several peripherals of the same type. For such devices, the CMSIS-Driver publishes multiple instances
183 of the \ref AccessStruct. The name of each driver instance reflects the names of the peripheral available in the device.
184
185 **Code Example:** \ref AccessStruct for three SPIs in a microcontroller device.
186 ```c
187 ARM_DRIVER_SPI Driver_SPI1;     // access functions for SPI1 interface
188 ARM_DRIVER_SPI Driver_SPI2;     // access functions for SPI2 interface
189 ARM_DRIVER_SPI Driver_SPI3;     // access functions for SPI3 interface
190 ```
191
192 The access functions can be passed to middleware to specify the driver instance that the middleware should use for communication.
193
194 **Naming Convention**
195
196 The access structs need to follow this naming convention: the keyword `Driver` followed by an underscore `_`, the interface
197 name `IFNAME` (usually in upper case letters), and the instance number `n`. Here's the full list of access struct names for
198 all drivers (n to be replaced with the actual instance number):
199 ```c
200 Driver_CANn
201 Driver_ETH_MACn
202 Driver_ETH_PHYn
203 Driver_Flashn
204 Driver_GPIOn
205 Driver_I2Cn
206 Driver_MCIn
207 Driver_NANDn
208 Driver_SAIn
209 Driver_SPIn
210 Driver_Storagen
211 Driver_USARTn
212 Driver_USBDn
213 Driver_USBHn
214 Driver_WiFin
215 ```
216
217
218 **Example:**
219 ```c
220 void init_middleware (ARM_DRIVER_SPI *Drv_spi) ...
221 \\ inside the middleware the SPI driver functions are called with:
222 \\   Drv_spi->function (...);
223 ```
224
225 ```c
226 \\ setup middleware
227 init_middleware (&Driver_SPI1);      // connect middleware to SPI1 interface
228   :
229 init_middleware (&Driver_SPI2);      // connect middleware to SPI2 interface
230 ```
231
232 ## CMSIS-Driver Files {#cmsis_driver_files}
233
234 The API of each CMSIS-Driver peripheral is published in a corresponding header file in the directory `.\CMSIS\Driver\Include\` It is recommended to include such header file in the implementation file of the CMSIS-Driver.
235
236 Template files are available to simplify the development of a CMSIS-Driver. These are code skeletons that provide the structure of a CMSIS-Driver. They are available in the directory`.\CMSIS\Driver\DriverTemplates\`. You can also refer to working \ref listOfImplementations "CMSIS-Driver Implementations" to see how CMSIS-Drivers get implemented on real devices.
237
238 The table below summarizes the API header and template files for CMSIS-Driver interfaces, with links to GitHub and API references.
239
240
241 | Header File          | Template File            | API Reference
242 :----------------------|:-------------------------|:-----------------------
243 [Driver_Common.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_Common.h)| Not applicable | \ref common_drv_gr
244 [Driver_CAN.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_CAN.h)      | [Driver_CAN.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_CAN.c) |\ref can_interface_gr
245 [Driver_ETH.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_ETH.h)      | - |\ref eth_interface_gr
246 [Driver_ETH_MAC.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_ETH_MAC.h)  | [Driver_ETH_MAC.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_ETH_MAC.c) | \ref eth_mac_interface_gr
247 [Driver_ETH_PHY.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_ETH_MAC.h)  | [Driver_ETH_PHY.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_ETH_PHY.c) | \ref eth_phy_interface_gr
248 [Driver_Flash.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_Flash.h)  | [Driver_Flash.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_Flash.c) | \ref flash_interface_gr
249 [Driver_GPIO.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_GPIO.h)  | [Driver_GPIO.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_GPIO.c) | \ref gpio_interface_gr
250 [Driver_I2C.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_I2C.h)  | [Driver_I2C.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_I2C.c) | \ref i2c_interface_gr
251 [Driver_MCI.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_MCI.h)  | [Driver_MCI.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_MCI.c) | \ref mci_interface_gr
252 [Driver_NAND.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_NAND.h)  | [Driver_NAND.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_NAND.c) | \ref nand_interface_gr
253 [Driver_SAI.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_SAI.h)  | [Driver_SAI.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_SAI.c) | \ref sai_interface_gr
254 [Driver_SPI.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_SPI.h)  | [Driver_SPI.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_SPI.c) | \ref spi_interface_gr
255 [Driver_Storage.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_Storage.h)  | [Driver_Storage.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_Storage.c) | \ref storage_interface_gr
256 [Driver_USART.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_USART.h)  | [Driver_USART.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_USART.c) | \ref usart_interface_gr
257 [Driver_USB.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_USB.h)  | - | \ref usb_interface_gr
258 [Driver_USBD.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_USBD.h)  | [Driver_USBD.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_USBD.c) | \ref usbd_interface_gr
259 [Driver_USBH.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_USBH.h)  | [Driver_USBH.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_USBH.c) | \ref usbh_interface_gr
260 [Driver_WiFi.h](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/Include/Driver_WiFi.h)  | [Driver_WiFi.c](https://github.com/ARM-software/CMSIS_6/blob/main/CMSIS/Driver/DriverTemplates/Driver_WiFi.c) | \ref wifi_interface_gr
261
262 ## Driver Configuration {#DriverConfiguration}
263
264 For a device family, the drivers may be configurable, but the configuration of the drivers itself is not part of the CMSIS-Driver
265 specification.
266
267 ## Code Example {#CodeExample}
268
269 The following example code shows the usage of the SPI interface.
270
271 \include SPI_Demo.c