1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
|
/*
* Copyright (C) 2017-2024 Alibaba Group Holding Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file wj_adc.c
* @brief CSI Source File for ADC Driver
* @version V1.0
* @date 2020-03-05
******************************************************************************/
#include <string.h>
#include <drv/adc.h>
#include <drv/irq.h>
#include <drv/tick.h>
static void wj_adc_irqhandler(void *args)
{
///< TODO:获取ADC中断的状态
///< TODO:清除ADC中断
///< TODO:根据ADC的中断状态处理中断
}
void wj_adc_dma_event_cb(csi_dma_ch_t *dma, csi_dma_event_t event, void *arg)
{
csi_adc_t *adc;
adc = (csi_adc_t *)dma->parent;
if (event == DMA_EVENT_TRANSFER_DONE) {
///< 关闭DMA通道
csi_dma_ch_stop(dma);
adc->num = 0U;
adc->state.readable = 1U;
if (adc->callback) {
soc_dcache_clean_invalid_range((unsigned long)adc->data, adc->num * 4U);
///< 执行ADC DMA传输完成的用户回调函数
adc->callback(adc, ADC_EVENT_CONVERT_COMPLETE, adc->arg);
}
}
}
static csi_error_t wj_adc_start_intr(csi_adc_t *adc)
{
///< 使能ADC的中断控制器中对应的中断
csi_irq_enable((uint32_t)adc->dev.irq_num);
///< TODO:使能ADC的中断
///< TODO:打开ADC控制器
return CSI_OK;
}
static csi_error_t wj_adc_start_dma(csi_adc_t *adc)
{
csi_dma_ch_config_t config;
config.src_inc = DMA_ADDR_CONSTANT;
config.dst_inc = DMA_ADDR_INC;
config.src_tw = DMA_DATA_WIDTH_32_BITS;
config.dst_tw = DMA_DATA_WIDTH_32_BITS;
config.group_len = 4U;
config.trans_dir = DMA_PERH2MEM;
config.handshake = 81U;
///< 配置ADC的DMA通道
csi_dma_ch_config(adc->dma, &config);
///< 禁止中断控制器对应的中断
csi_irq_disable((uint32_t)adc->dev.irq_num);
soc_dcache_clean_invalid_range((unsigned long)adc->data, adc->num * 4U);
///< TODO:调用csi_dma_ch_start接口打开ADC的DMA通道
///< TODO:打开ADC
return CSI_OK;
}
static csi_error_t wj_adc_stop_intr(csi_adc_t *adc)
{
csi_error_t ret = CSI_OK;
///< TODO:关闭ADC的中断
///< TODO:关闭ADC
return ret;
}
static csi_error_t wj_adc_stop_dma(csi_adc_t *adc)
{
csi_error_t ret = CSI_OK;
///< TODO:关闭ADC
return ret;
}
csi_error_t csi_adc_init(csi_adc_t *adc, uint32_t idx)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
csi_error_t ret = CSI_OK;
adc->priv = 0U;
///< 获取中断号、基地址等相关信息
if (target_get(DEV_WJ_ADC_TAG, idx, &adc->dev) != CSI_OK) {
ret = CSI_ERROR;
} else {
adc->state.writeable = 1U;
adc->state.readable = 1U;
adc->state.error = 0U;
adc->callback = NULL;
adc->arg = NULL;
adc->data = NULL;
adc->dma = NULL;
adc->start = NULL;
adc->stop = NULL;
///< TODO:关闭ADC控制器
///< TODO:打开ADC控制器
}
return ret;
}
void csi_adc_uninit(csi_adc_t *adc)
{
CSI_PARAM_CHK_NORETVAL(adc);
///< TODO:关闭ADC所有的通道
///< TODO:关闭ADC控制器
}
csi_error_t csi_adc_set_buffer(csi_adc_t *adc, uint32_t *data, uint32_t num)
{
csi_error_t ret = CSI_OK;
CSI_PARAM_CHK(adc, CSI_ERROR);
CSI_PARAM_CHK(data, CSI_ERROR);
CSI_PARAM_CHK(num, CSI_ERROR);
if (num == 0U) {
ret = CSI_ERROR;
} else {
adc->data = data;
adc->num = num;
ret = CSI_OK;
}
return ret;
}
csi_error_t csi_adc_start(csi_adc_t *adc)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
csi_error_t ret = CSI_OK;
if (adc->state.readable == 0U) {
ret = CSI_BUSY;
return ret;
}
if (adc->state.writeable == 0U) {
ret = CSI_BUSY;
return ret;
}
///< TODO:打开ADC控制器
return ret;
}
csi_error_t csi_adc_stop(csi_adc_t *adc)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
csi_error_t ret = CSI_OK;
///< TODO:关闭ADC
adc->state.readable = 1U;
adc->state.writeable = 1U;
adc->data = NULL;
adc->num = 0U;
return ret;
}
csi_error_t csi_adc_channel_enable(csi_adc_t *adc, uint8_t ch_id, bool is_enable)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
csi_error_t ret = CSI_OK;
if (is_enable) {
///< TODO:选择ADC的通道
} else {
///< TODO:关闭指定的ADC通道
}
return ret;
}
csi_error_t csi_adc_channel_sampling_time(csi_adc_t *adc, uint8_t ch_id, uint16_t clock_num)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
return CSI_UNSUPPORTED;
}
csi_error_t csi_adc_sampling_time(csi_adc_t *adc, uint16_t clock_num)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
csi_error_t ret = CSI_OK;
///< TODO:设置ADC的采样时间
return ret;
}
uint32_t csi_adc_freq_div(csi_adc_t *adc, uint32_t div)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
uint32_t ret = 0;
///< TODO:设置ADC的分频
///< TODO:获取ADC分频后使用的频率ret,需要用户自己获取ret
return ret;
}
int32_t csi_adc_read(csi_adc_t *adc)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
int32_t ret = CSI_OK;
///< TODO:在一定时间内ADC读数据的标志位不为0,否则超时退出
///< TODO:读数据寄存器获取ADC转换的数据到ret
return ret;
}
csi_error_t csi_adc_get_state(csi_adc_t *adc, csi_state_t *state)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
*state = adc->state;
return CSI_OK;
}
uint32_t csi_adc_get_freq(csi_adc_t *adc)
{
CSI_PARAM_CHK(adc, 0U);
uint32_t freq = 0U;
///< TODO:获取ADC的分频div
///< TODO:获取ADC分频后使用的频率freq
return freq;
}
csi_error_t csi_adc_attach_callback(csi_adc_t *adc, void *callback, void *arg)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
CSI_PARAM_CHK(callback, CSI_ERROR);
adc->callback = callback;
adc->arg = arg;
adc->start = wj_adc_start_intr;
adc->stop = wj_adc_stop_intr;
///< 注册ADC的中断服务函数,使能中断控制器对应的中断
csi_irq_attach((uint32_t)adc->dev.irq_num, &wj_adc_irqhandler, &adc->dev);
csi_irq_enable((uint32_t)adc->dev.irq_num);
return CSI_OK;
}
void csi_adc_detach_callback(csi_adc_t *adc)
{
CSI_PARAM_CHK_NORETVAL(adc);
adc->callback = NULL;
adc->arg = NULL;
adc->start = NULL;
adc->stop = NULL;
///< 禁止中断控制器对应的中断
csi_irq_disable((uint32_t)adc->dev.irq_num);
}
csi_error_t csi_adc_start_async(csi_adc_t *adc)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
csi_error_t ret = CSI_OK;
if ((adc->data == NULL) || (adc->num == 0U)) {
ret = CSI_ERROR;
return ret;
}
/* rx buffer not full */
if (adc->state.readable == 0U) {
ret = CSI_BUSY;
return ret;
}
/* last conversion existed */
if (adc->state.writeable == 0U) {
ret = CSI_ERROR;
return ret;
}
if (adc->start) {
///< 执行ADC中断或者DMA传输完成中断回调函数
adc->start(adc);
}
return ret;
}
csi_error_t csi_adc_stop_async(csi_adc_t *adc)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
csi_error_t ret = CSI_OK;
if (adc->stop) {
adc->stop(adc);
adc->state.readable = 1U;
adc->state.writeable = 1U;
adc->data = NULL;
adc->num = 0U;
} else {
ret = CSI_ERROR;
}
return ret;
}
csi_error_t csi_adc_continue_mode(csi_adc_t *adc, bool is_enable)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
if (is_enable) {
///< TODO:设置ADC为continue模式
} else {
///< TODO:设置ADC为single模式
}
///< TODO:打开ADC的等待模式
return CSI_OK;
}
csi_error_t csi_adc_link_dma(csi_adc_t *adc, csi_dma_ch_t *dma)
{
CSI_PARAM_CHK(adc, CSI_ERROR);
csi_error_t ret = CSI_OK;
if (dma != NULL) {
dma->parent = adc;
///< 申请DMA通道
ret = csi_dma_ch_alloc(dma, -1, -1);
if (ret == CSI_OK) {
///< ADC DMA模式传输完成中断服务函数的注册
csi_dma_ch_attach_callback(dma, wj_adc_dma_event_cb, NULL);
adc->dma = dma;
adc->start = wj_adc_start_dma;
adc->stop = wj_adc_stop_dma;
} else {
dma->parent = NULL;
}
} else {
if (adc->dma) {
///< 释放DMA通道,注销ADC DMA模式传输完成中断服务函数
csi_dma_ch_free(adc->dma);
csi_dma_ch_detach_callback(adc->dma);
adc->dma = NULL;
}
if (adc->callback != NULL) {
adc->start = wj_adc_start_intr;
adc->stop = wj_adc_stop_intr;
} else {
adc->start = NULL;
adc->stop = NULL;
}
}
return ret;
}
#ifdef CONFIG_PM
csi_error_t dw_adc_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action)
{
CSI_PARAM_CHK(dev, CSI_ERROR);
csi_error_t ret = CSI_OK;
csi_pm_dev_t *pm_dev = &dev->pm_dev;
wj_adc_regs_t *adc_base = (wj_adc_regs_t *)dev->reg_base;
switch (action) {
case PM_DEV_SUSPEND:
///< TODO:恢复ADC寄存器
break;
case PM_DEV_RESUME:
///< TODO:保存ADC寄存器
break;
default:
ret = CSI_ERROR;
break;
}
return ret;
}
csi_error_t csi_adc_enable_pm(csi_adc_t *adc)
{
///< TODO:注册ADC低功耗处理函数dw_adc_pm_action
}
void csi_adc_disable_pm(csi_adc_t *adc)
{
csi_pm_dev_unregister(&adc->dev);
}
#endif
|