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
|
/*
* Copyright : (C) 2022 Phytium Information Technology, Inc.
* All Rights Reserved.
*
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
* either version 1.0 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the Phytium Public License for more details.
*
*
* FilePath: fddma_intr.c
* Date: 2022-02-10 14:53:42
* LastEditTime: 2022-02-18 08:24:47
* Description: This files is for ddma interrupt implementation
*
* Modify History:
* Ver Who Date Changes
* ----- ------ -------- --------------------------------------
* 1.0 Zhugengyu 2022/5/13 init commit
*/
/***************************** Include Files *********************************/
#include <string.h>
#include "fkernel.h"
#include "fparameters.h"
#include "fassert.h"
#include "fdebug.h"
#include "fddma_hw.h"
#include "fddma.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/************************** Variable Definitions *****************************/
/***************** Macros (Inline Functions) Definitions *********************/
#define FDDMA_DEBUG_TAG "DDMA-INTR"
#define FDDMA_ERROR(format, ...) FT_DEBUG_PRINT_E(FDDMA_DEBUG_TAG, format, ##__VA_ARGS__)
#define FDDMA_WARN(format, ...) FT_DEBUG_PRINT_W(FDDMA_DEBUG_TAG, format, ##__VA_ARGS__)
#define FDDMA_INFO(format, ...) FT_DEBUG_PRINT_I(FDDMA_DEBUG_TAG, format, ##__VA_ARGS__)
#define FDDMA_DEBUG(format, ...) FT_DEBUG_PRINT_D(FDDMA_DEBUG_TAG, format, ##__VA_ARGS__)
#define FDDMA_CALL_EVT_HANDLER(express, dma_chan, args) \
if (express) \
{ \
express(dma_chan, args); \
}
/************************** Function Prototypes ******************************/
/****************************************************************************/
/**
* @name: FDdmaChanIrqHandler
* @msg: DDMA通道中断处理函数
* @return {*}
* @param {FDdma} *instance, DDMA实例
* @param {FDdmaChanIndex} chan_idx, DDMA通道号
*/
static void FDdmaChanIrqHandler(FDdma *const instance, FDdmaChanIndex chan_idx)
{
FASSERT(instance && instance->chan[chan_idx]);
FDdmaChan *const dma_chan = instance->chan[chan_idx];
uintptr base_addr = instance->config.base_addr;
u32 status = FDdmaReadChanStatus(base_addr, chan_idx);
FDDMA_INFO("chan-%d irq status: 0x%x", chan_idx, status);
FDDMA_CALL_EVT_HANDLER(dma_chan->evt_handler[FDDMA_CHAN_EVT_REQ_DONE], dma_chan,
dma_chan->evt_handler_args[FDDMA_CHAN_EVT_REQ_DONE]);
if (FDDMA_CHAN_STS_FIFO_EMPTY & status)
{
FDDMA_CALL_EVT_HANDLER(dma_chan->evt_handler[FDDMA_CHAN_EVT_FIFO_EMPTY], dma_chan,
dma_chan->evt_handler_args[FDDMA_CHAN_EVT_FIFO_EMPTY]);
}
if (FDDMA_CHAN_STS_FIFO_FULL & status)
{
FDDMA_CALL_EVT_HANDLER(dma_chan->evt_handler[FDDMA_CHAN_EVT_FIFO_FULL], dma_chan,
dma_chan->evt_handler_args[FDDMA_CHAN_EVT_FIFO_FULL]);
}
/* submit queued descriptor after processing the completed ones */
return;
}
/**
* @name: FDdmaIrqHandler
* @msg: DDMA中断处理函数
* @return {无}
* @param {s32} vector
* @param {void} *param, 输入参数
*/
void FDdmaIrqHandler(s32 vector, void *args)
{
FASSERT(NULL != args);
FDdma *const instance = (FDdma * const)args;
uintptr base_addr = instance->config.base_addr;
u32 status = FDdmaReadStatus(base_addr);
u32 chan;
FDDMA_INFO("ddma irq 0x%x", status);
FDdmaDisableGlobalIrq(base_addr); /* disable interrupt from occur again */
/* poll, clear and process every chanel interrupt status */
for (chan = FDDMA_CHAN_0; chan < FDDMA_NUM_OF_CHAN; chan++)
{
if (0 == (FDDMA_STA_CHAN_REQ_DONE(chan) & status))
continue;
FDDMA_INFO("handle chan %d", chan);
FDdmaClearChanIrq(base_addr, chan); /* clear interrupt status */
FDdmaChanIrqHandler(instance, chan); /* channel interrupt handle */
}
FDdmaEnableGlobalIrq(base_addr); /* re-enable interrupt */
return;
}
/**
* @name: FDdmaRegisterChanEvtHandler
* @msg: 注册DDMA通道中断响应事件函数
* @return {无}
* @param {FDdmaChan} *dma_chan, DDMA通道
* @param {FDdmaChanEvt} evt, 中断事件
* @param {FDdmaChanEvtHandler} handler, 中断响应事件函数
* @param {void} *handler_arg, 中断响应事件函数输入参数
*/
void FDdmaRegisterChanEvtHandler(FDdmaChan *const dma_chan, FDdmaChanEvt evt, FDdmaChanEvtHandler handler, void *handler_arg)
{
FASSERT(dma_chan);
dma_chan->evt_handler[evt] = handler;
dma_chan->evt_handler_args[evt] = handler_arg;
return;
}
|