1 /*
2 * Copyright (C) 2017-2024 Alibaba Group Holding Limited
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 /******************************************************************************
20 * @file dw_spi.c
21 * @brief
22 * @version
23 * @date 2020-02-11
24 ******************************************************************************/
25
26 #include <string.h>
27
28 #include <drv/spi.h>
29 #include <drv/irq.h>
30 #include <drv/tick.h>
31 #include <drv/porting.h>
32
33 ///< TODO:SPI_CTRLR0_TMOD_Msk需要根据实际情况进行设置
34 #define SPI_CTRLR0_TMOD_Msk 3U << 8U ///< 设置SPI模式的寄存器对应的位的掩码
35 ///< TODO:SPI_CTRLR0_TMOD_RX和SPI_CTRLR0_TMOD_TX需要根据实际情况进行设置
36 #define SPI_CTRLR0_TMOD_RX 2U << 8U ///< SPI发送模式
37 #define SPI_CTRLR0_TMOD_TX 1U << 8U ///< SPI发送模式
38
39 static csi_error_t dw_spi_send_intr(csi_spi_t *spi, const void *data, uint32_t size);
40 static csi_error_t dw_spi_receive_intr(csi_spi_t *spi, void *data, uint32_t size);
41 static csi_error_t dw_spi_send_receive_intr(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t num);
42
dw_spi_irqhandler(void * args)43 static void dw_spi_irqhandler(void *args)
44 {
45
46 ///< TODO:获取SPI中断的状态
47
48 ///< TODO:根据SPI中断的状态进行接收数据的处理,在接收完成后关闭中断;调用用户回调函数
49
50 ///< TODO:根据SPI中断的状态进行关闭中断,发送数据的处理;调用用户回调函数
51
52 ///< TODO:根据SPI中断的状态进行异常中断的处理,并清除中断,调用用户回调函数
53
54 }
55
dw_spi_dma_event_cb(csi_dma_ch_t * dma,csi_dma_event_t event,void * arg)56 static void dw_spi_dma_event_cb(csi_dma_ch_t *dma, csi_dma_event_t event, void *arg)
57 {
58 csi_spi_t *spi = (csi_spi_t *)dma->parent;
59 uint32_t mode = 0U;
60
61 ///< TODO:获取SPI传输数据的模式mode:发送模式/接收模式/发送&接收模式
62
63 if (event == DMA_EVENT_TRANSFER_DONE) {
64 /* process end of transmit */
65 if ((spi->tx_dma != NULL) && (spi->tx_dma->ch_id == dma->ch_id)) {
66 ///< 关闭DMA通道
67 csi_dma_ch_stop(dma);
68
69 ///< TODO:关闭DMA发送使能
70
71 ///< TODO:如果SPI的BUSY在一定时间内处于空闲状态下
72 spi->state.writeable = 1U;
73 spi->tx_size = 0U;
74
75 if ((mode & SPI_CTRLR0_TMOD_Msk) == SPI_CTRLR0_TMOD_TX) {
76 ///< TODO:设置发送FIFO的触发级别为0
77
78 if (spi->callback) {
79 ///< 调用用户回调函数
80 spi->callback(spi, SPI_EVENT_SEND_COMPLETE, spi->arg);
81 }
82 } else {
83 if (spi->state.readable == 1U) {
84 ///< 调用用户回调函数
85 spi->callback(spi, SPI_EVENT_SEND_RECEIVE_COMPLETE, spi->arg);
86 }
87 }
88 } else if ((spi->rx_dma != NULL) && (spi->rx_dma->ch_id == dma->ch_id)) {
89 ///< 关闭DMA通道
90 ///< TODO:关闭SPI接收DMA
91 ///< TODO:设置接收FIFO的触发级别为0
92 ///< TODO:设置接收数据的大小为0
93
94 spi->state.readable = 1U;
95 spi->rx_size = 0U;
96
97 if ((mode & SPI_CTRLR0_TMOD_Msk) == SPI_CTRLR0_TMOD_RX) {
98 if (spi->callback) {
99 ///< 调用用户回调函数
100 spi->callback(spi, SPI_EVENT_RECEIVE_COMPLETE, spi->arg);
101 }
102 } else {
103 if (spi->state.writeable == 1U) {
104 ///< 调用用户回调函数
105 spi->callback(spi, SPI_EVENT_SEND_RECEIVE_COMPLETE, spi->arg);
106 }
107 }
108 }
109 }
110 }
111
csi_spi_init(csi_spi_t * spi,uint32_t idx)112 csi_error_t csi_spi_init(csi_spi_t *spi, uint32_t idx)
113 {
114 CSI_PARAM_CHK(spi, CSI_ERROR);
115
116 csi_error_t ret = CSI_OK;
117
118 ///< 获取中断号、基地址等相关信息
119 if (target_get(DEV_DW_SPI_TAG, idx, &spi->dev) != CSI_OK) {
120 ret = CSI_ERROR;
121 } else {
122 spi->state.writeable = 1U;
123 spi->state.readable = 1U;
124 spi->state.error = 0U;
125 spi->send = NULL;
126 spi->receive = NULL;
127 spi->send_receive = NULL;
128 spi->rx_dma = NULL;
129 spi->tx_dma = NULL;
130 spi->rx_data = NULL;
131 spi->tx_data = NULL;
132 spi->callback = NULL;
133 spi->arg = NULL;
134 spi->priv = 0;
135
136 ///< TODO:关闭SPI所有的中断
137 ///< TODO:关闭SPI
138
139 }
140
141 return ret;
142 }
143
csi_spi_uninit(csi_spi_t * spi)144 void csi_spi_uninit(csi_spi_t *spi)
145 {
146 CSI_PARAM_CHK_NORETVAL(spi);
147
148 ///< TODO:复位SPI使用到的寄存器
149
150 ///< 禁止中断控制器对应的中断,注销中断服务函数
151 csi_irq_disable((uint32_t)spi->dev.irq_num);
152 csi_irq_detach((uint32_t)spi->dev.irq_num);
153 }
154
csi_spi_attach_callback(csi_spi_t * spi,void * callback,void * arg)155 csi_error_t csi_spi_attach_callback(csi_spi_t *spi, void *callback, void *arg)
156 {
157 CSI_PARAM_CHK(spi, CSI_ERROR);
158 CSI_PARAM_CHK(callback, CSI_ERROR);
159
160 ///< 注册用户回调函数
161 spi->callback = callback;
162 spi->arg = arg;
163 spi->send = NULL;
164 spi->receive = NULL;
165 spi->send_receive = NULL;
166
167 return CSI_OK;
168 }
169
170
csi_spi_detach_callback(csi_spi_t * spi)171 void csi_spi_detach_callback(csi_spi_t *spi)
172 {
173 CSI_PARAM_CHK_NORETVAL(spi);
174
175 ///< 注销用户回调函数
176 spi->callback = NULL;
177 spi->arg = NULL;
178 spi->send = NULL;
179 spi->receive = NULL;
180 spi->send_receive = NULL;
181 }
182
183
csi_spi_mode(csi_spi_t * spi,csi_spi_mode_t mode)184 csi_error_t csi_spi_mode(csi_spi_t *spi, csi_spi_mode_t mode)
185 {
186 CSI_PARAM_CHK(spi, CSI_ERROR);
187
188 csi_error_t ret = CSI_OK;
189
190 switch (mode) {
191 case SPI_MASTER:
192 ///< TODO:设置SPI为主机模式
193 break;
194
195 case SPI_SLAVE:
196 ///< TODO:设置SPI为从机模式
197 break;
198
199 default:
200 ret = CSI_ERROR;
201 break;
202 }
203
204 return ret;
205 }
206
csi_spi_cp_format(csi_spi_t * spi,csi_spi_cp_format_t format)207 csi_error_t csi_spi_cp_format(csi_spi_t *spi, csi_spi_cp_format_t format)
208 {
209 CSI_PARAM_CHK(spi, CSI_ERROR);
210
211 csi_error_t ret = CSI_OK;
212
213 switch (format) {
214 case SPI_FORMAT_CPOL0_CPHA0:
215 ///< TODO:设置SPI时钟的极性
216 ///< TODO:设置SPI时钟的相位
217 break;
218
219 case SPI_FORMAT_CPOL0_CPHA1:
220 ///< TODO:设置SPI时钟的极性
221 ///< TODO:设置SPI时钟的相位
222 break;
223
224 case SPI_FORMAT_CPOL1_CPHA0:
225 ///< TODO:设置SPI时钟的极性
226 ///< TODO:设置SPI时钟的相位
227 break;
228
229 case SPI_FORMAT_CPOL1_CPHA1:
230 ///< TODO:设置SPI时钟的极性
231 ///< TODO:设置SPI时钟的相位
232 break;
233
234 default:
235 ret = CSI_ERROR;
236 break;
237 }
238
239 return ret;
240 }
241
csi_spi_baud(csi_spi_t * spi,uint32_t baud)242 uint32_t csi_spi_baud(csi_spi_t *spi, uint32_t baud)
243 {
244 CSI_PARAM_CHK(spi, CSI_ERROR);
245 CSI_PARAM_CHK(baud, CSI_ERROR);
246
247 uint32_t freq = 0U;
248
249 ///< TODO:根据SPI工作频率设置传输频率(baud)
250 ///< TODO:获取SPI时钟的分频div
251 ///< TODO:根据分频div获取SPI实际传输的频率
252
253 return freq;
254
255 }
256
csi_spi_frame_len(csi_spi_t * spi,csi_spi_frame_len_t length)257 csi_error_t csi_spi_frame_len(csi_spi_t *spi, csi_spi_frame_len_t length)
258 {
259 CSI_PARAM_CHK(spi, CSI_ERROR);
260
261 csi_error_t ret = CSI_OK;
262
263 if ((length < SPI_FRAME_LEN_4) || (length > SPI_FRAME_LEN_16)) {
264 ret = CSI_ERROR;
265 } else {
266 ///< TODO:设置SPI数据帧的大小
267 }
268
269 return ret;
270 }
271
csi_spi_send(csi_spi_t * spi,const void * data,uint32_t size,uint32_t timeout)272 int32_t csi_spi_send(csi_spi_t *spi, const void *data, uint32_t size, uint32_t timeout)
273 {
274 CSI_PARAM_CHK(spi, CSI_ERROR);
275 CSI_PARAM_CHK(data, CSI_ERROR);
276 CSI_PARAM_CHK(size, CSI_ERROR);
277
278 int32_t ret = CSI_OK;
279
280 if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) {
281 ret = CSI_BUSY;
282 return ret;
283 }
284
285 spi->state.writeable = 0U;
286
287 ///< TODO:关闭SPI
288 ///< TODO:设置SPI为发送模式
289 ///< TODO:设置SPI发送FIFO的阈值
290 ///< TODO:打开SPI
291
292
293 ///< TODO:轮询发送数据,超时则超时退出
294 ///< TODO:发送完成后在一定时间内判断发送FIFO是否为空,空则退出,不空则超时退出
295 ///< TODO:发送完成后在一定时间内判断SPI BUSY是否为0,0则退出,不为0则超时退出
296
297 spi->state.writeable = 1U;
298
299 return ret;
300 }
301
csi_spi_send_async(csi_spi_t * spi,const void * data,uint32_t size)302 csi_error_t csi_spi_send_async(csi_spi_t *spi, const void *data, uint32_t size)
303 {
304 CSI_PARAM_CHK(spi, CSI_ERROR);
305 CSI_PARAM_CHK(data, CSI_ERROR);
306 CSI_PARAM_CHK(size, CSI_ERROR);
307
308 csi_error_t ret = CSI_OK;
309
310 if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) {
311 ret = CSI_BUSY;
312 }
313
314 if ((ret == CSI_OK) && (spi->callback != NULL)) {
315 if (spi->send) {
316 spi->state.writeable = 0U;
317 ///< TODO:调用spi->send发送数据
318 } else {
319 spi->state.writeable = 0U;
320 ///< 注册SPI的中断服务函数,使能中断控制器对应的中断
321 csi_irq_attach((uint32_t)spi->dev.irq_num, &dw_spi_irqhandler, &spi->dev);
322 csi_irq_enable((uint32_t)spi->dev.irq_num);
323 ///< TODO:调用dw_spi_send_intr中断模式发送数据
324 }
325 } else {
326 ret = CSI_ERROR;
327 }
328
329 return ret;
330 }
331
dw_spi_send_intr(csi_spi_t * spi,const void * data,uint32_t size)332 static csi_error_t dw_spi_send_intr(csi_spi_t *spi, const void *data, uint32_t size)
333 {
334 csi_error_t ret = CSI_OK;
335 spi->tx_data = (uint8_t *)data;
336
337 ///< TODO:关闭SPI
338 ///< TODO:设置SPI为发送模式
339 ///< TODO:设置SPI发送FIFO的阈值
340 ///< TODO:打开SPI
341 ///< TODO:打开SPI发送FIFO空中断
342
343 return ret;
344 }
345
dw_spi_send_dma(csi_spi_t * spi,const void * data,uint32_t size)346 static csi_error_t dw_spi_send_dma(csi_spi_t *spi, const void *data, uint32_t size)
347 {
348 CSI_PARAM_CHK(spi, CSI_ERROR);
349 CSI_PARAM_CHK(data, CSI_ERROR);
350 CSI_PARAM_CHK(size, CSI_ERROR);
351
352 csi_dma_ch_config_t config;
353 csi_dma_ch_t *dma_ch;
354 csi_error_t ret = CSI_OK;
355
356 dma_ch = (csi_dma_ch_t *)spi->tx_dma;
357 spi->tx_data = (uint8_t *)data;
358 memset(&config, 0, sizeof(csi_dma_ch_config_t));
359
360 ///< TODO:配置DMA的config.src_tw和config.dst_tw
361 config.src_inc = DMA_ADDR_INC;
362 config.dst_inc = DMA_ADDR_CONSTANT;
363 config.trans_dir = DMA_MEM2PERH;
364 ///< TODO:配置SPI的硬件握手号config.handshake
365
366 ///< 配置DMA通道
367 csi_dma_ch_config(dma_ch, &config);
368
369 ///< TODO:关闭SPI
370 ///< TODO:设置SPI为发送模式
371 ///< TODO:使能SPI发送DMA
372
373 soc_dcache_clean_invalid_range((unsigned long)spi->tx_data, size);
374 ///< TODO:调用csi_dma_ch_start打开SPI发送数据的DMA通道
375
376 ///< TODO:打开SPI
377
378 return ret;
379 }
380
csi_spi_receive(csi_spi_t * spi,void * data,uint32_t size,uint32_t timeout)381 int32_t csi_spi_receive(csi_spi_t *spi, void *data, uint32_t size, uint32_t timeout)
382 {
383 CSI_PARAM_CHK(spi, CSI_ERROR);
384 CSI_PARAM_CHK(data, CSI_ERROR);
385 CSI_PARAM_CHK(size, CSI_ERROR);
386
387 int32_t ret = CSI_OK;
388
389 if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) {
390 ret = CSI_BUSY;
391 return ret;
392 }
393
394 spi->state.readable = 0U;
395 spi->rx_data = (uint8_t *)data;
396
397 ///< 关闭SPI
398 ///< 设置SPI为接收模式
399 ///< 设置SPI接收数据的大小
400 ///< 打开SPI
401
402 ///< TODO:轮询接收数据,超时则超时退出
403 ///< TODO:接收完成后再一定时间内判断SPI BUSY是否为0,为0则退出,不为0则超时退出
404
405 spi->state.readable = 1U;
406
407 return ret;
408 }
409
410
csi_spi_receive_async(csi_spi_t * spi,void * data,uint32_t size)411 csi_error_t csi_spi_receive_async(csi_spi_t *spi, void *data, uint32_t size)
412 {
413 CSI_PARAM_CHK(spi, CSI_ERROR);
414 CSI_PARAM_CHK(data, CSI_ERROR);
415 CSI_PARAM_CHK(size, CSI_ERROR);
416
417 csi_error_t ret = CSI_OK;
418
419 if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) {
420 ret = CSI_BUSY;
421 } else {
422
423 if ((ret == CSI_OK) && (spi->callback != NULL)) {
424 if (spi->receive) {
425 spi->state.readable = 0U;
426 ret = spi->receive(spi, data, size);
427 } else {
428 spi->state.readable = 0U;
429 ///< 注册SPI的中断服务函数,使能中断控制器对应的中断
430 csi_irq_attach((uint32_t)spi->dev.irq_num, &dw_spi_irqhandler, &spi->dev);
431 csi_irq_enable((uint32_t)spi->dev.irq_num);
432 ///< 调用dw_spi_receive_intr中断模式接收数据
433 ret = dw_spi_receive_intr(spi, data, size);
434 }
435 } else {
436 ret = CSI_ERROR;
437 }
438 }
439
440 return ret;
441 }
442
dw_spi_receive_intr(csi_spi_t * spi,void * data,uint32_t size)443 static csi_error_t dw_spi_receive_intr(csi_spi_t *spi, void *data, uint32_t size)
444 {
445 csi_error_t ret = CSI_OK;
446
447 spi->rx_data = (uint8_t *)data;
448
449 ///< TODO:关闭SPI
450 ///< TODO:设置SPI为接收模式
451 ///< TODO:设置SPI接收数据的大小
452 ///< TODO:设置SPI接收FIFO的阈值
453 ///< TODO:打开SPI
454 ///< TODO:打开SPI接收FIFO满中断
455
456 ///< TODO:如果SPI工作在主机模式下
457 ///< TODO:写SPI数据寄存器为0
458
459 return ret;
460 }
461
dw_spi_receive_dma(csi_spi_t * spi,void * data,uint32_t size)462 static csi_error_t dw_spi_receive_dma(csi_spi_t *spi, void *data, uint32_t size)
463 {
464 csi_dma_ch_config_t config;
465 csi_dma_ch_t *dma_ch;
466 csi_error_t ret = CSI_OK;
467
468 dma_ch = (csi_dma_ch_t *)spi->rx_dma;
469 spi->rx_data = (uint8_t *)data;
470 memset(&config, 0, sizeof(csi_dma_ch_config_t));
471
472 ///< TODO:配置DMA的config.src_tw和config.dst_tw
473 config.src_inc = DMA_ADDR_CONSTANT;
474 config.dst_inc = DMA_ADDR_INC;
475 config.trans_dir = DMA_PERH2MEM;
476 ///< TODO:配置SPI的硬件握手号config.handshake
477
478 ///< 配置DMA通道
479 csi_dma_ch_config(dma_ch, &config);
480
481 ///< TODO:关闭SPI
482 ///< TODO:设置SPI为接收模式
483 ///< TODO:设置SPI接收数据的大小
484 ///< TODO:设置SPI接收FIFO的触发级别
485 ///< TODO:使能SPI接收DMA
486
487 soc_dcache_clean_invalid_range((unsigned long)spi->rx_data, size);
488 ///< TODO:调用csi_dma_ch_start打开SPI接收数据的DMA通道
489
490 ///< TODO:打开SPI
491
492 ///< TODO:如果SPI工作在主机模式下
493 ///< TODO:写SPI数据寄存器为0
494
495 return ret;
496 }
497
csi_spi_send_receive(csi_spi_t * spi,const void * data_out,void * data_in,uint32_t size,uint32_t timeout)498 int32_t csi_spi_send_receive(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size, uint32_t timeout)
499 {
500 CSI_PARAM_CHK(spi, CSI_ERROR);
501 CSI_PARAM_CHK(data_out, CSI_ERROR);
502 CSI_PARAM_CHK(data_in, CSI_ERROR);
503 CSI_PARAM_CHK(size, CSI_ERROR);
504
505 int32_t ret = CSI_OK;
506
507 if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) {
508 ret = CSI_BUSY;
509 return ret;
510 }
511
512 spi->state.writeable = 0U;
513 spi->state.readable = 0U;
514
515 ///< TODO:关闭SPI
516 ///< TODO:设置SPI为发送和接收模式
517 ///< TODO:设置SPI发送FIFO的阈值
518 ///< TODO:设置SPI接收FIFO的阈值
519 ///< TODO:打开SPI
520
521 ///< TODO:轮询发送数据
522 ///< TODO:轮询接收数据
523 ///< TODO:超时退出
524 ///< TODO:在一定时间内判断SPI的BUSY是否为0,为0退出,否则超时退出
525
526 spi->state.writeable = 1U;
527 spi->state.readable = 1U;
528
529 return ret;
530 }
531
532
csi_spi_send_receive_async(csi_spi_t * spi,const void * data_out,void * data_in,uint32_t size)533 csi_error_t csi_spi_send_receive_async(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size)
534 {
535 CSI_PARAM_CHK(spi, CSI_ERROR);
536 CSI_PARAM_CHK(data_out, CSI_ERROR);
537 CSI_PARAM_CHK(data_in, CSI_ERROR);
538 CSI_PARAM_CHK(size, CSI_ERROR);
539
540 csi_error_t ret = CSI_OK;
541
542 if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) {
543 ret = CSI_BUSY;
544 }
545
546 if ((ret == CSI_OK) && (spi->callback != NULL)) {
547 if (spi->send_receive) {
548 spi->state.readable = 0U;
549 spi->state.writeable = 0U;
550 ret = spi->send_receive(spi, data_out, data_in, size);
551 } else {
552 spi->state.readable = 0U;
553 spi->state.writeable = 0U;
554 ///< 注册SPI的中断服务函数,使能中断控制器对应的中断
555 csi_irq_attach((uint32_t)spi->dev.irq_num, &dw_spi_irqhandler, &spi->dev);
556 csi_irq_enable((uint32_t)spi->dev.irq_num);
557 ///< 调用dw_spi_send_receive_intr中断模式发送接收数据
558 ret = dw_spi_send_receive_intr(spi, data_out, data_in, size);
559 }
560 } else {
561 ret = CSI_ERROR;
562 }
563
564 return ret;
565 }
566
dw_spi_send_receive_intr(csi_spi_t * spi,const void * data_out,void * data_in,uint32_t size)567 static csi_error_t dw_spi_send_receive_intr(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size)
568 {
569 csi_error_t ret = CSI_OK;
570
571 spi->tx_data = (uint8_t *)data_out;
572 spi->rx_data = (uint8_t *)data_in;
573
574 ///< TODO:关闭SPI
575 ///< TODO:设置SPI为发送接收模式
576 ///< TODO:设置接收数据的大小
577 ///< TODO:设置发送FIFO的阈值
578 ///< TODO:设置接收FIFO的阈值
579 ///< TODO:打开SPI
580 ///< TODO:打开SPI接收FIFO满中断
581 ///< TODO:打开SPI发送FIFO空中断
582
583 return ret;
584 }
585
dw_spi_send_receive_dma(csi_spi_t * spi,const void * data_out,void * data_in,uint32_t size)586 static csi_error_t dw_spi_send_receive_dma(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size)
587 {
588 csi_dma_ch_config_t config;
589 csi_dma_ch_t *dma_ch;
590 csi_error_t ret = CSI_OK;
591 spi->tx_data = (uint8_t *)data_out;
592 memset(&config, 0, sizeof(csi_dma_ch_config_t));
593
594 ///< TODO:配置DMA的config.src_tw和config.dst_tw
595
596 spi->rx_data = (uint8_t *)data_in;
597
598 dma_ch = (csi_dma_ch_t *)spi->tx_dma;
599 config.src_inc = DMA_ADDR_INC;
600 config.dst_inc = DMA_ADDR_CONSTANT;
601 config.trans_dir = DMA_MEM2PERH;
602 ///< TODO:配置SPI的硬件握手号config.handshake
603
604 ///< 配置发送DMA通道
605 csi_dma_ch_config(dma_ch, &config);
606
607 dma_ch = (csi_dma_ch_t *)spi->rx_dma;
608 config.src_inc = DMA_ADDR_CONSTANT;
609 config.dst_inc = DMA_ADDR_INC;
610 config.trans_dir = DMA_PERH2MEM;
611 ///< TODO:配置SPI的硬件握手号config.handshake
612
613 ///< 配置接收DMA通道
614 csi_dma_ch_config(dma_ch, &config);
615
616 ///< TODO:关闭SPI
617 ///< TODO:设置SPI为发送接收模式
618 ///< TODO:设置SPI接收数据的大小
619 ///< TODO:设置SPI接收数据FIFO的触发级别
620 ///< TODO:使能SPI接收DMA
621 ///< TODO:使能SPI发送DMA
622
623 ///< 打开发送接收的DMA通道
624
625 soc_dcache_clean_invalid_range((unsigned long)spi->tx_data, size);
626 soc_dcache_clean_invalid_range((unsigned long)spi->rx_data, size);
627 ///< TODO:调用csi_dma_ch_start打开SPI接收数据的DMA通道
628 ///< TODO:调用csi_dma_ch_start打开SPI发送数据的DMA通道
629
630 ///< TODO:打开SPI
631 return ret;
632 }
633
csi_spi_get_state(csi_spi_t * spi,csi_state_t * state)634 csi_error_t csi_spi_get_state(csi_spi_t *spi, csi_state_t *state)
635 {
636 CSI_PARAM_CHK(spi, CSI_ERROR);
637 CSI_PARAM_CHK(state, CSI_ERROR);
638
639 *state = spi->state;
640 return CSI_OK;
641 }
642
csi_spi_link_dma(csi_spi_t * spi,csi_dma_ch_t * tx_dma,csi_dma_ch_t * rx_dma)643 csi_error_t csi_spi_link_dma(csi_spi_t *spi, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma)
644 {
645 CSI_PARAM_CHK(spi, CSI_ERROR);
646
647 csi_error_t ret = CSI_OK;
648
649 if (tx_dma != NULL) {
650 tx_dma->parent = spi;
651 ///< 申请DMA通道
652 ret = csi_dma_ch_alloc(tx_dma, -1, -1);
653
654 if (ret == CSI_OK) {
655 ///< 注册DMA传输完成中断回调服务函数
656 csi_dma_ch_attach_callback(tx_dma, dw_spi_dma_event_cb, NULL);
657 spi->tx_dma = tx_dma;
658 spi->send = dw_spi_send_dma;
659 } else {
660 tx_dma->parent = NULL;
661 }
662 } else {
663 if (spi->tx_dma) {
664 ///< 注销DMA传输完成中断回调服务函数,释放DMA通道
665 csi_dma_ch_detach_callback(spi->tx_dma);
666 csi_dma_ch_free(spi->tx_dma);
667 spi->tx_dma = NULL;
668 }
669
670 spi->send = NULL;
671 }
672
673 if (ret == CSI_OK) {
674 if (rx_dma != NULL) {
675 rx_dma->parent = spi;
676 ///< 申请DMA通道
677 ret = csi_dma_ch_alloc(rx_dma, -1, -1);
678
679 if (ret == CSI_OK) {
680 ///< 注册DMA传输完成中断回调服务函数
681 csi_dma_ch_attach_callback(rx_dma, dw_spi_dma_event_cb, NULL);
682 spi->rx_dma = rx_dma;
683 ///< 调用DMA接收函数开启DMA的接收
684 spi->receive = dw_spi_receive_dma;
685 } else {
686 rx_dma->parent = NULL;
687 }
688 } else {
689 if (spi->rx_dma) {
690 ///< 注销DMA传输完成中断回调服务函数,释放DMA通道
691 csi_dma_ch_detach_callback(spi->rx_dma);
692 csi_dma_ch_free(spi->rx_dma);
693 spi->rx_dma = NULL;
694 }
695
696 spi->receive = NULL;
697 }
698 }
699
700
701 if (ret == CSI_OK) {
702 if ((tx_dma != NULL) && (rx_dma != NULL)) {
703 ///< 调用DMA发送接收函数开启DMA的发送接收
704 spi->send_receive = dw_spi_send_receive_dma;
705 } else {
706 spi->send_receive = NULL;
707 }
708 }
709
710 return ret;
711 }
712
csi_spi_select_slave(csi_spi_t * spi,uint32_t slave_num)713 void csi_spi_select_slave(csi_spi_t *spi, uint32_t slave_num)
714 {
715 CSI_PARAM_CHK_NORETVAL(spi);
716
717 ///< TODO:使能SPI的从机
718 }
719
720 #ifdef CONFIG_PM
dw_spi_pm_action(csi_dev_t * dev,csi_pm_dev_action_t action)721 csi_error_t dw_spi_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action)
722 {
723 CSI_PARAM_CHK(dev, CSI_ERROR);
724
725 csi_error_t ret = CSI_OK;
726 csi_pm_dev_t *pm_dev = &dev->pm_dev;
727
728 switch (action) {
729 case PM_DEV_SUSPEND:
730 ///< TODO:恢复SPI寄存器
731 break;
732
733 case PM_DEV_RESUME:
734 ///< TODO:保存SPI寄存器
735 break;
736
737 default:
738 ret = CSI_ERROR;
739 break;
740 }
741
742 return ret;
743 }
744
csi_spi_enable_pm(csi_spi_t * spi)745 csi_error_t csi_spi_enable_pm(csi_spi_t *spi)
746 {
747 ///< TODO:注册WDT低功耗处理函数dw_spi_pm_action
748 }
749
csi_spi_disable_pm(csi_spi_t * spi)750 void csi_spi_disable_pm(csi_spi_t *spi)
751 {
752 csi_pm_dev_unregister(&spi->dev);
753 }
754 #endif
755