@@ -121,13 +121,13 @@ and rebuilding.
121
121
122
122
5 . [ Device driver examples] ( ./TUTORIAL.md#5-device-driver-examples )
123
123
124
- 5.1 [ The IORead mechnaism ] ( ./TUTORIAL.md#51-the-ioread-mechanism )
124
+ 5.1 [ Using the IORead mechnanism ] ( ./TUTORIAL.md#51-using -the-ioread-mechanism )
125
125
126
126
5.1.1 [ A UART driver example] ( ./TUTORIAL.md#511-a-uart-driver-example )
127
127
128
- 5.2 [ Using a coro to poll hardware ] ( ./TUTORIAL.md#52-using-a-coro-to-poll-hardware )
128
+ 5.2 [ Writing IORead device drivers ] ( ./TUTORIAL.md#52-writing-ioread-device-drivers )
129
129
130
- 5.3 [ Using IORead to poll hardware ] ( ./TUTORIAL.md#53-using-ioread-to-poll-hardware )
130
+ 5.3 [ Polling hardware without IORead ] ( ./TUTORIAL.md#53-polling-hardware-without-ioread )
131
131
132
132
5.4 [ A complete example: aremote.py] ( ./TUTORIAL.md#54-a-complete-example-aremotepy )
133
133
A driver for an IR remote control receiver.
@@ -216,6 +216,7 @@ results by accessing Pyboard hardware.
216
216
11 . ` auart_hd.py ` Use of the Pyboard UART to communicate with a device using a
217
217
half-duplex protocol. Suits devices such as those using the 'AT' modem command
218
218
set.
219
+ 12 . ` iorw.py ` Demo of a read/write device driver using the IORead mechanism.
219
220
220
221
** Test Programs**
221
222
@@ -1012,11 +1013,11 @@ acquire data. In the case of a driver written in Python this must be done by
1012
1013
having a coro which does this periodically. This may present problems if there
1013
1014
is a requirement for rapid polling owing to the round-robin nature of uasyncio
1014
1015
scheduling: the coro will compete for execution with others. There are two
1015
- solutions to this. One is to use the experimental version of uasyncio presented
1016
- [ here ] ( ./FASTPOLL.md ) .
1016
+ solutions to this. The official solution is to delegate polling to the
1017
+ scheduler using the IORead mechanism. This is currently subject to limitations .
1017
1018
1018
- The other potential solution is to delegate the polling to the scheduler using
1019
- the IORead mechanism. This is unsupported for Python drivers: see section 5.3 .
1019
+ An alternative is to use the experimental version of uasyncio presented
1020
+ [ here ] ( ./FASTPOLL.md ) .
1020
1021
1021
1022
Note that where a very repeatable polling interval is required, it should be
1022
1023
done using a hardware timer with a hard interrupt callback. For "very"
@@ -1044,7 +1045,7 @@ which offers a means of reducing this latency for critical tasks.
1044
1045
1045
1046
###### [ Contents] ( ./TUTORIAL.md#contents )
1046
1047
1047
- ## 5.1 The IORead Mechanism
1048
+ ## 5.1 Using the IORead Mechanism
1048
1049
1049
1050
This can be illustrated using a Pyboard UART. The following code sample
1050
1051
demonstrates concurrent I/O on one UART. To run, link Pyboard pins X1 and X2
@@ -1073,19 +1074,20 @@ loop.create_task(receiver())
1073
1074
loop.run_forever()
1074
1075
```
1075
1076
1076
- The supporting code may be found in ` __init__.py ` in the uasyncio library.
1077
+ The supporting code may be found in ` __init__.py ` in the ` uasyncio ` library.
1077
1078
The mechanism works because the device driver (written in C) implements the
1078
- following methods: ` ioctl ` , ` read ` , ` write ` , ` readline ` and ` close ` . See
1079
- section 5.3 for further discussion.
1079
+ following methods: ` ioctl ` , ` read ` , ` readline ` and ` write ` . See
1080
+ [ section 5.2] ( ./TUTORIAL.md#52-writing-ioread-device-drivers ) for details on
1081
+ how such drivers may be written in Python.
1080
1082
1081
1083
A UART can receive data at any time. The IORead mechanism checks for pending
1082
1084
incoming characters whenever the scheduler has control. When a coro is running
1083
1085
an interrupt service routine buffers incoming characters; these will be removed
1084
1086
when the coro yields to the scheduler. Consequently UART applications should be
1085
- designed such that all coros minimise blocking periods to avoid buffer
1086
- overflows and data loss. This can be ameliorated by using a larger UART read
1087
- buffer or a lower baudrate. Alternatively hardware flow control will provide a
1088
- solution if the data source supports it.
1087
+ designed such that coros minimise the time between yielding to the scheduler to
1088
+ avoid buffer overflows and data loss. This can be ameliorated by using a larger
1089
+ UART read buffer or a lower baudrate. Alternatively hardware flow control will
1090
+ provide a solution if the data source supports it.
1089
1091
1090
1092
### 5.1.1 A UART driver example
1091
1093
@@ -1111,7 +1113,72 @@ returned. See the code comments for more details.
1111
1113
1112
1114
###### [ Contents] ( ./TUTORIAL.md#contents )
1113
1115
1114
- ## 5.2 Using a coro to poll hardware
1116
+ ## 5.2 Writing IORead device drivers
1117
+
1118
+ The ` IORead ` mechanism is provided to support I/O to stream devices. Its
1119
+ typical use is to support streaming I/O devices such as UARTs and sockets. The
1120
+ mechanism may be employed by drivers of any device which needs to be polled:
1121
+ the polling is delegated to the scheduler which uses ` select ` to schedule the
1122
+ handlers for any devices which are ready. This is more efficient than running
1123
+ multiple coros each polling a device.
1124
+
1125
+ It should be noted that currently the task polling I/O devices effectively runs
1126
+ in round-robin fashion along with other coroutines. This is arguably sub
1127
+ optimal: [ see this GitHub RFC] ( https://github.com/micropython/micropython/issues/2664 ) .
1128
+
1129
+ A device driver capable of employing the IORead mechanism may support
1130
+ ` StreamReader ` , ` StreamWriter ` instances or both. A readable device must
1131
+ provide at least one of the following methods. Note that these are synchronous
1132
+ methods. The ` ioctl ` method (see below) ensures that they are only called if
1133
+ data is available. The methods should return as fast as possible with as much
1134
+ data as is available.
1135
+
1136
+ ` readline() ` Return as many characters as are available up to and including any
1137
+ newline character. Required if you intend to use ` StreamReader.readline() `
1138
+ ` read(n) ` Return as many characters as are available but no more than ` n ` .
1139
+ Required if you plan to use ` StreamReader.read() ` or
1140
+ ` StreamReader.readexactly() `
1141
+
1142
+ A writeable driver must provide this synchronous method:
1143
+ ` write ` Args ` buf ` , ` off ` , ` sz ` . Arguments:
1144
+ ` buf ` is the buffer to write.
1145
+ ` off ` is the offset into the buffer of the first character to write.
1146
+ ` sz ` is the requested number of characters to write.
1147
+ It should return immediately. The return value is the number of characters
1148
+ actually written (may well be 1 if the device is slow). The ` ioctl ` method
1149
+ ensures that this is only called if the device is ready to accept data.
1150
+
1151
+ All devices must provide an ` ioctl ` method which polls the hardware to
1152
+ determine its ready status. A typical example for a read/write driver is:
1153
+
1154
+ ``` python
1155
+ MP_STREAM_POLL_RD = const(1 )
1156
+ MP_STREAM_POLL_WR = const(4 )
1157
+ MP_STREAM_POLL = const(3 )
1158
+ MP_STREAM_ERROR = const(- 1 )
1159
+
1160
+ def ioctl (self , req , arg ): # see ports/stm32/uart.c
1161
+ ret = MP_STREAM_ERROR
1162
+ if req == MP_STREAM_POLL :
1163
+ ret = 0
1164
+ if arg & MP_STREAM_POLL_RD :
1165
+ if hardware_has_at_least_one_char_to_read:
1166
+ ret |= MP_STREAM_POLL_RD
1167
+ if arg & MP_STREAM_POLL_WR :
1168
+ if hardware_can_accept_at_least_one_write_character:
1169
+ ret |= MP_STREAM_POLL_WR
1170
+ return ret
1171
+ ```
1172
+
1173
+ The demo program ` iorw.py ` illustrates a complete example. Note that, at the
1174
+ time of writing there is a bug in ` uasyncio ` which prevents this from woking.
1175
+ See [ this GitHub thread] ( https://github.com/micropython/micropython/pull/3836#issuecomment-397317408 ) .
1176
+ The workround is to write two separate drivers, one read-only and the other
1177
+ write-only.
1178
+
1179
+ ###### [ Contents] ( ./TUTORIAL.md#contents )
1180
+
1181
+ ## 5.3 Polling hardware without IORead
1115
1182
1116
1183
This is a simple approach, but is only appropriate to hardware which is to be
1117
1184
polled at a relatively low rate. This is for two reasons. Firstly the variable
@@ -1193,21 +1260,6 @@ loop.run_until_complete(run())
1193
1260
1194
1261
###### [ Contents] ( ./TUTORIAL.md#contents )
1195
1262
1196
- ## 5.3 Using IORead to poll hardware
1197
-
1198
- The uasyncio ` IORead ` class is provided to support IO to stream devices. It
1199
- may be employed by drivers of devices which need to be polled: the polling will
1200
- be delegated to the scheduler which uses ` select ` to schedule the first
1201
- stream or device driver to be ready. This is more efficient, and offers lower
1202
- latency, than running multiple coros each polling a device.
1203
-
1204
- At the time of writing firmware support for using this mechanism in device
1205
- drivers written in Python has not been implemented, and the final comment to
1206
- [ this] ( https://github.com/micropython/micropython/issues/2664 ) issue suggests
1207
- that it may never be done. So streaming device drivers must be written in C.
1208
-
1209
- ###### [ Contents] ( ./TUTORIAL.md#contents )
1210
-
1211
1263
## 5.4 A complete example: aremote.py
1212
1264
1213
1265
This may be found in the ` nec_ir ` directory. Its use is documented
0 commit comments