Skip to content

Commit 761a1d9

Browse files
Tomasz BursztykaAnas Nashif
authored andcommitted
api: Add asynchronous call support to SPI API
Adding a struct k_poll_signal parameter to driver's API unique exposed function. If not NULL, the call will be handled as asynchronous and will return right after the transaction has started, on the contrary of current logic where is waits for the transaction to finish (= synchronous). In order to save stack, let's move the device pointer to struct spi_config. So the call is still at a maximum of 4 parameters. Adapting spi_dw.c and spi driver sample to the change so it still builts. Signed-off-by: Tomasz Bursztyka <[email protected]>
1 parent b983847 commit 761a1d9

File tree

3 files changed

+116
-30
lines changed

3 files changed

+116
-30
lines changed

drivers/spi/spi_dw.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -250,18 +250,17 @@ static int spi_dw_configure(const struct spi_dw_config *info,
250250
return 0;
251251
}
252252

253-
static int spi_dw_transceive(struct device *dev,
254-
struct spi_config *config,
253+
static int spi_dw_transceive(struct spi_config *config,
255254
const struct spi_buf **tx_bufs,
256255
struct spi_buf **rx_bufs)
257256
{
258-
const struct spi_dw_config *info = dev->config->config_info;
259-
struct spi_dw_data *spi = dev->driver_data;
257+
const struct spi_dw_config *info = config->dev->config->config_info;
258+
struct spi_dw_data *spi = config->dev->driver_data;
260259
u32_t rx_thsld = DW_SPI_RXFTLR_DFLT;
261260
u32_t imask = DW_SPI_IMR_UNMASK;
262261
int ret = 0;
263262

264-
SYS_LOG_DBG("%p, %p, %p", dev, tx_bufs, rx_bufs);
263+
SYS_LOG_DBG("%p, %p, %p", config->dev, tx_bufs, rx_bufs);
265264

266265
/* Check status */
267266
if (test_bit_ssienr(info->regs) || test_bit_sr_busy(info->regs)) {

include/spi.h

Lines changed: 104 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ struct spi_cs_control {
124124
/**
125125
* @brief SPI controller configuration structure
126126
*
127+
* dev is a valid pointer to an actual SPI device
127128
* frequency is the bus frequency in Hertz
128129
* operation is a bit field with the following parts:
129130
* operational mode [ 0 ] - master or slave.
@@ -139,9 +140,12 @@ struct spi_cs_control {
139140
* emulated through a gpio line, or NULL otherwise.
140141
*/
141142
struct spi_config {
143+
struct device *dev;
144+
142145
u32_t frequency;
143146
u16_t operation;
144147
u16_t slave;
148+
145149
struct spi_cs_control *cs;
146150
};
147151

@@ -163,25 +167,36 @@ struct spi_buf {
163167
* @brief Callback API for I/O
164168
* See spi_transceive() for argument descriptions
165169
*/
166-
typedef int (*spi_api_io)(struct device *dev,
167-
struct spi_config *config,
170+
typedef int (*spi_api_io)(struct spi_config *config,
168171
const struct spi_buf **tx_bufs,
169172
struct spi_buf **rx_bufs);
170173

174+
/**
175+
* @typedef spi_api_io
176+
* @brief Callback API for asynchronous I/O
177+
* See spi_transceive_async() for argument descriptions
178+
*/
179+
typedef int (*spi_api_io_async)(struct spi_config *config,
180+
const struct spi_buf **tx_bufs,
181+
struct spi_buf **rx_bufs,
182+
struct k_poll_signal *async);
183+
171184
/**
172185
* @brief SPI driver API
173186
* This is the mandatory API any SPI driver needs to expose.
174187
*/
175188
struct spi_driver_api {
176189
spi_api_io transceive;
190+
#ifdef CONFIG_POLL
191+
spi_api_io_async transceive_async;
192+
#endif
177193
};
178194

179195
/**
180196
* @brief Read/write the specified amount of data from the SPI driver.
181197
*
182198
* Note: This function is synchronous.
183199
*
184-
* @param dev is a valid pointer to an actual SPI device
185200
* @param config Pointer to a valid spi_config structure instance.
186201
* @param tx_bufs NULL terminated buffer array where data to be sent
187202
* originates from, or NULL if none.
@@ -190,57 +205,129 @@ struct spi_driver_api {
190205
*
191206
* @retval 0 If successful, negative errno code otherwise.
192207
*/
193-
static inline int spi_transceive(struct device *dev,
194-
struct spi_config *config,
208+
static inline int spi_transceive(struct spi_config *config,
195209
const struct spi_buf **tx_bufs,
196210
struct spi_buf **rx_bufs)
197211
{
198-
const struct spi_driver_api *api = dev->driver_api;
212+
const struct spi_driver_api *api = config->dev->driver_api;
199213

200-
return api->transceive(dev, config, tx_bufs, rx_bufs);
214+
return api->transceive(config, tx_bufs, rx_bufs);
201215
}
202216

203217
/**
204218
* @brief Read the specified amount of data from the SPI driver.
205219
*
206220
* Note: This function is synchronous.
207221
*
208-
* @param dev is a valid pointer to an actual SPI device
209222
* @param config Pointer to a valid spi_config structure instance.
210223
* @param rx_bufs NULL terminated buffer array where data to be read
211224
* will be written to.
212225
*
213226
* @retval 0 If successful, negative errno code otherwise.
214227
*/
215-
static inline int spi_read(struct device *dev,
216-
struct spi_config *config,
228+
static inline int spi_read(struct spi_config *config,
217229
struct spi_buf **rx_bufs)
218230
{
219-
const struct spi_driver_api *api = dev->driver_api;
231+
const struct spi_driver_api *api = config->dev->driver_api;
220232

221-
return api->transceive(dev, config, NULL, rx_bufs);
233+
return api->transceive(config, NULL, rx_bufs);
222234
}
223235

224236
/**
225237
* @brief Write the specified amount of data from the SPI driver.
226238
*
227239
* Note: This function is synchronous.
228240
*
229-
* @param dev is a valid pointer to an actual SPI device
230241
* @param config Pointer to a valid spi_config structure instance.
231242
* @param tx_bufs NULL terminated buffer array where data to be sent
232243
* originates from.
233244
*
234245
* @retval 0 If successful, negative errno code otherwise.
235246
*/
236-
static inline int spi_write(struct device *dev,
237-
struct spi_config *config,
247+
static inline int spi_write(struct spi_config *config,
238248
const struct spi_buf **tx_bufs)
239249
{
240-
const struct spi_driver_api *api = dev->driver_api;
250+
const struct spi_driver_api *api = config->dev->driver_api;
251+
252+
return api->transceive(config, tx_bufs, NULL);
253+
}
254+
255+
#ifdef CONFIG_POLL
256+
/**
257+
* @brief Read/write the specified amount of data from the SPI driver.
258+
*
259+
* Note: This function is asynchronous.
260+
*
261+
* @param config Pointer to a valid spi_config structure instance.
262+
* @param tx_bufs NULL terminated buffer array where data to be sent
263+
* originates from, or NULL if none.
264+
* @param rx_bufs NULL terminated buffer array where data to be read
265+
* will be written to, or NULL if none.
266+
* @param async A pointer to a valid and ready to be signaled
267+
* struct k_poll_signal. (Note: if NULL this function will not
268+
* notify the end of the transaction, and whether it went
269+
* successfully or not).
270+
*
271+
* @retval 0 If successful, negative errno code otherwise.
272+
*/
273+
static inline int spi_transceive_async(struct spi_config *config,
274+
const struct spi_buf **tx_bufs,
275+
struct spi_buf **rx_bufs,
276+
struct k_poll_signal *async)
277+
{
278+
const struct spi_driver_api *api = config->dev->driver_api;
279+
280+
return api->transceive_async(config, tx_bufs, rx_bufs, async);
281+
}
282+
283+
/**
284+
* @brief Read the specified amount of data from the SPI driver.
285+
*
286+
* Note: This function is asynchronous.
287+
*
288+
* @param config Pointer to a valid spi_config structure instance.
289+
* @param rx_bufs NULL terminated buffer array where data to be read
290+
* will be written to.
291+
* @param async A pointer to a valid and ready to be signaled
292+
* struct k_poll_signal. (Note: if NULL this function will not
293+
* notify the end of the transaction, and whether it went
294+
* successfully or not).
295+
*
296+
* @retval 0 If successful, negative errno code otherwise.
297+
*/
298+
static inline int spi_read_async(struct spi_config *config,
299+
struct spi_buf **rx_bufs,
300+
struct k_poll_signal *async)
301+
{
302+
const struct spi_driver_api *api = config->dev->driver_api;
303+
304+
return api->transceive_async(config, NULL, rx_bufs, async);
305+
}
306+
307+
/**
308+
* @brief Write the specified amount of data from the SPI driver.
309+
*
310+
* Note: This function is asynchronous.
311+
*
312+
* @param config Pointer to a valid spi_config structure instance.
313+
* @param tx_bufs NULL terminated buffer array where data to be sent
314+
* originates from.
315+
* @param async A pointer to a valid and ready to be signaled
316+
* struct k_poll_signal. (Note: if NULL this function will not
317+
* notify the end of the transaction, and whether it went
318+
* successfully or not).
319+
*
320+
* @retval 0 If successful, negative errno code otherwise.
321+
*/
322+
static inline int spi_write_async(struct spi_config *config,
323+
const struct spi_buf **tx_bufs,
324+
struct k_poll_signal *async)
325+
{
326+
const struct spi_driver_api *api = config->dev->driver_api;
241327

242-
return api->transceive(dev, config, tx_bufs, NULL);
328+
return api->transceive_async(config, tx_bufs, NULL, async);
243329
}
330+
#endif /* CONFIG_POLL */
244331

245332
#ifdef __cplusplus
246333
}

samples/drivers/spi/src/spi.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ struct spi_config spi_fast = {
7272
.cs = SPI_CS,
7373
};
7474

75-
struct device *spi_dev;
76-
7775
static int cs_ctrl_gpio_config(struct spi_cs_control *cs)
7876
{
7977
if (cs) {
@@ -102,7 +100,7 @@ static int spi_complete_loop(struct spi_config *spi_conf)
102100
struct spi_buf *rx_bufs[] = { &rx, NULL };
103101
int ret;
104102

105-
ret = spi_transceive(spi_dev, spi_conf, tx_bufs, rx_bufs);
103+
ret = spi_transceive(spi_conf, tx_bufs, rx_bufs);
106104
if (ret) {
107105
SYS_LOG_ERR("Code %d", ret);
108106
return -1;
@@ -133,7 +131,7 @@ static int spi_rx_half_start(struct spi_config *spi_conf)
133131

134132
memset(buffer_rx, 0, BUF_SIZE);
135133

136-
ret = spi_transceive(spi_dev, spi_conf, tx_bufs, rx_bufs);
134+
ret = spi_transceive(spi_conf, tx_bufs, rx_bufs);
137135
if (ret) {
138136
SYS_LOG_ERR("Code %d", ret);
139137
return -1;
@@ -167,7 +165,7 @@ static int spi_rx_half_end(struct spi_config *spi_conf)
167165

168166
memset(buffer_rx, 0, BUF_SIZE);
169167

170-
ret = spi_transceive(spi_dev, spi_conf, tx_bufs, rx_bufs);
168+
ret = spi_transceive(spi_conf, tx_bufs, rx_bufs);
171169
if (ret) {
172170
SYS_LOG_ERR("Code %d", ret);
173171
return -1;
@@ -206,7 +204,7 @@ static int spi_rx_every_4(struct spi_config *spi_conf)
206204

207205
memset(buffer_rx, 0, BUF_SIZE);
208206

209-
ret = spi_transceive(spi_dev, spi_conf, tx_bufs, rx_bufs);
207+
ret = spi_transceive(spi_conf, tx_bufs, rx_bufs);
210208
if (ret) {
211209
SYS_LOG_ERR("Code %d", ret);
212210
return -1;
@@ -231,12 +229,14 @@ void main(void)
231229
return;
232230
}
233231

234-
spi_dev = device_get_binding(SPI_DRV_NAME);
235-
if (!spi_dev) {
232+
spi_slow.dev = device_get_binding(SPI_DRV_NAME);
233+
if (!spi_slow.dev) {
236234
SYS_LOG_ERR("Cannot find %s!\n", SPI_DRV_NAME);
237235
return;
238236
}
239237

238+
spi_fast.dev = spi_slow.dev;
239+
240240
if (spi_complete_loop(&spi_slow) ||
241241
spi_rx_half_start(&spi_slow) ||
242242
spi_rx_half_end(&spi_slow) ||

0 commit comments

Comments
 (0)