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
|
/*
* 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: fgpio_intr.c
* Date: 2022-02-10 14:53:42
* LastEditTime: 2022-02-18 08:25:29
* Description: This files is for GPIO interrupt function implementation
*
* Modify History:
* Ver Who Date Changes
* ----- ------ -------- --------------------------------------
* 1.0 zhugengyu 2022-3-1 init commit
*/
/***************************** Include Files *********************************/
#include "fdebug.h"
#include "fparameters.h"
#include "fgpio_hw.h"
#include "fgpio.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
#define FGPIO_DEBUG_TAG "FGPIO-INTR"
#define FGPIO_ERROR(format, ...) FT_DEBUG_PRINT_E(FGPIO_DEBUG_TAG, format, ##__VA_ARGS__)
#define FGPIO_WARN(format, ...) FT_DEBUG_PRINT_W(FGPIO_DEBUG_TAG, format, ##__VA_ARGS__)
#define FGPIO_INFO(format, ...) FT_DEBUG_PRINT_I(FGPIO_DEBUG_TAG, format, ##__VA_ARGS__)
#define FGPIO_DEBUG(format, ...) FT_DEBUG_PRINT_D(FGPIO_DEBUG_TAG, format, ##__VA_ARGS__)
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
/*****************************************************************************/
/**
* @name: FGpioGetInterruptMask
* @msg: 获取GPIO A组引脚的中断屏蔽位
* @return {*}
* @param {FGpio} *instance, GPIO控制器实例
* @param {u32} *mask, 返回的GPIO A组引脚中断屏蔽位
* @param {u32} *enabled, 返回的GPIO A组中断使能位
* @note 获取的是A组所有Pin的中断屏蔽位和中断使能位
*/
void FGpioGetInterruptMask(FGpio *const instance, u32 *mask, u32 *enabled)
{
FASSERT(instance);
FASSERT(instance->is_ready == FT_COMPONENT_IS_READY);
uintptr base_addr = instance->config.base_addr;
if (NULL != mask)
{
*mask = FGpioReadReg32(base_addr, FGPIO_INTMASK_OFFSET);
}
if (NULL != enabled)
{
*enabled = FGpioReadReg32(base_addr, FGPIO_INTEN_OFFSET);
}
return;
}
/**
* @name: FGpioSetInterruptMask
* @msg: 设置GPIO A组引脚的中断屏蔽位
* @return {*}
* @param {FGpioPin} *pin, GPIO引脚实例
* @param {boolean} enable, TRUE表示使能GPIO引脚中断,FALSE表示去使能GPIO引脚中断
* @note index对应的引脚必须为A组引脚,B组引脚不支持中断
*/
void FGpioSetInterruptMask(FGpioPin *const pin, boolean enable)
{
FASSERT(pin);
FGpio *const instance = pin->instance;
FASSERT(instance);
FASSERT(instance->is_ready == FT_COMPONENT_IS_READY);
uintptr base_addr = instance->config.base_addr;
u32 mask_bits = 0;
u32 enable_bits = 0;
FGpioPinId index = pin->index;
#if defined(FGPIO_VERSION_1) /* FT2000-4, D2000 */
if (FGPIO_PORT_B == index.port)
{
FGPIO_ERROR("None interrupt support for PORT-B !!!");
return;
}
#endif
if (FGPIO_DIR_OUTPUT == FGpioGetDirection(pin))
{
FGPIO_ERROR("None interrupt support for output GPIO !!!");
return;
}
FGpioGetInterruptMask(instance, &mask_bits, &enable_bits);
if (TRUE == enable)
{
mask_bits &= ~BIT(index.pin); /* not mask: 0 */
enable_bits |= BIT(index.pin); /* enable pin irq: 1 */
}
else
{
mask_bits |= BIT(index.pin); /* mask: 1 */
enable_bits &= ~BIT(index.pin); /* disable pin irq: 0 */
}
FGpioWriteReg32(base_addr, FGPIO_INTMASK_OFFSET, mask_bits);
FGpioWriteReg32(base_addr, FGPIO_INTEN_OFFSET, enable_bits);
return;
}
/**
* @name: FGpioGetInterruptType
* @msg: 获取GPIO A组引脚的中断类型和中断极性
* @return {*}
* @param {FGpio} *instance, GPIO控制器实例
* @param {u32} *levels, GPIO A组引脚中断电平类型
* @param {u32} *polarity, GPIO A组引脚中断极性类型
* @note 获取的是A组所有Pin的电平和极性
*/
void FGpioGetInterruptType(FGpio *const instance, u32 *levels, u32 *polarity)
{
FASSERT(instance);
FASSERT(instance->is_ready == FT_COMPONENT_IS_READY);
uintptr base_addr = instance->config.base_addr;
if (NULL != levels)
{
*levels = FGpioReadReg32(base_addr, FGPIO_INTTYPE_LEVEL_OFFSET);
}
if (NULL != polarity)
{
*polarity = FGpioReadReg32(base_addr, FGPIO_INTTYPE_LEVEL_OFFSET);
}
return;
}
/**
* @name: FGpioSetInterruptType
* @msg: 设置GPIO引脚的中断类型
* @return {*}
* @param {FGpioPin} *pin, GPIO引脚实例
* @param {FGpioIrqType} type, GPIO引脚中断触发类型
* @note index对应的引脚必须为A组引脚,B组引脚不支持中断
*/
void FGpioSetInterruptType(FGpioPin *const pin, const FGpioIrqType type)
{
FASSERT(pin);
FGpio *const instance = pin->instance;
FASSERT(instance);
FASSERT(instance->is_ready == FT_COMPONENT_IS_READY);
uintptr base_addr = instance->config.base_addr;
u32 level = 0;
u32 polarity = 0;
FGpioPinId index = pin->index;
#if defined(FGPIO_VERSION_1) /* FT2000-4, D2000 */
if (FGPIO_PORT_B == index.port)
{
FGPIO_ERROR("None interrupt support for PORT-B !!!");
return;
}
#endif
FGpioGetInterruptType(instance, &level, &polarity);
switch (type)
{
case FGPIO_IRQ_TYPE_EDGE_FALLING:
level |= BIT(index.pin); /* 边沿敏感型 */
polarity &= ~BIT(index.pin); /* 下降沿或低电平 */
break;
case FGPIO_IRQ_TYPE_EDGE_RISING:
level |= BIT(index.pin); /* 边沿敏感型 */
polarity |= BIT(index.pin); /* 上升沿或高电平 */
break;
case FGPIO_IRQ_TYPE_LEVEL_LOW:
level &= ~BIT(index.pin); /* 电平敏感型 */
polarity &= ~BIT(index.pin); /* 下降沿或低电平 */
break;
case FGPIO_IRQ_TYPE_LEVEL_HIGH:
level &= ~BIT(index.pin); /* 电平敏感型 */
polarity |= BIT(index.pin); /* 上升沿或高电平 */
break;
default:
break;
}
FGpioWriteReg32(base_addr, FGPIO_INTTYPE_LEVEL_OFFSET, level);
FGpioWriteReg32(base_addr, FGPIO_INT_POLARITY_OFFSET, polarity);
return;
}
/**
* @name: FGpioInterruptHandler
* @msg: GPIO中断处理函数
* @return {*}
* @param {s32} vector, 中断输入参数1
* @param {void} *param, 中断输入参数2
* @note 需要用户将此函数注册到Interrtup上,使能GPIO中断才能生效
*/
void FGpioInterruptHandler(s32 vector, void *param)
{
FGpio *const instance = (FGpio * const)param;
FGpioPin *pin = NULL;
FASSERT(instance);
int loop;
uintptr base_addr = instance->config.base_addr;
u32 status = FGpioReadReg32(base_addr, FGPIO_INTSTATUS_OFFSET);
u32 raw_status = FGpioReadReg32(base_addr, FGPIO_RAW_INTSTATUS_OFFSET);
#if defined(FGPIO_VERSION_2) /* E2000 gpio 3 ~ 5 */
FASSERT_MSG(FGPIO_WITH_PIN_IRQ < instance->config.instance_id, "handle interrupt through pin !!!")
#endif
FGPIO_INFO("status: 0x%x, raw_status: 0x%x", status, raw_status);
for (loop = FGPIO_PIN_0; loop < FGPIO_PIN_NUM; loop++)
{
if (status & BIT(loop))
{
pin = instance->pins[FGPIO_PORT_A][loop];
if (NULL == pin)
continue;
if (pin->irq_cb)
{
pin->irq_cb(0U, pin->irq_cb_params);
/* disable pin interrupt after triggered */
if (TRUE == pin->irq_one_time)
{
FGpioSetInterruptMask(pin, FALSE);
}
}
else
{
FGPIO_WARN("no irq handler callback for GPIO-%d-A-%d",
instance->config.instance_id,
loop);
}
}
}
/* clear interrupt status */
FGpioWriteReg32(base_addr, FGPIO_PORTA_EOI_OFFSET, status);
return;
}
#if defined(FGPIO_VERSION_2) /* E2000 GPIO 0 ~ 2 */
/**
* @name: FGpioPinInterruptHandler
* @msg: GPIO引脚中断处理函数
* @return {NONE}
* @param {s32} vector, 中断输入参数1
* @param {void} *param, 中断输入参数2
*/
void FGpioPinInterruptHandler(s32 vector, void *param)
{
FGpioPin *const pin = (FGpioPin * const)param;
FASSERT(pin);
FGpio *const instance = pin->instance;
FASSERT(instance);
uintptr base_addr = instance->config.base_addr;
u32 status = FGpioReadReg32(base_addr, FGPIO_INTSTATUS_OFFSET);
u32 raw_status = FGpioReadReg32(base_addr, FGPIO_RAW_INTSTATUS_OFFSET);
FGPIO_INFO("status: 0x%x, raw_status: 0x%x", status, raw_status);
if (pin->irq_cb)
{
pin->irq_cb(0U, pin->irq_cb_params);
/* disable pin interrupt after triggered */
if (TRUE == pin->irq_one_time)
{
FGpioSetInterruptMask(pin, FALSE);
}
}
else
{
FGPIO_WARN("no irq handler callback for GPIO-%d-A-%d",
pin->index.ctrl,
pin->index.pin);
}
/* clear interrupt status */
FGpioWriteReg32(base_addr, FGPIO_PORTA_EOI_OFFSET, status);
return;
}
#endif
/**
* @name: FGpioRegisterInterruptCB
* @msg: 注册GPIO引脚中断回调函数
* @return {*}
* @param {FGpioPin} pin, GPIO引脚实例
* @param {FGpioInterruptCallback} cb, GPIO引脚中断回调函数
* @param {void} *cb_param, GPIO引脚中断回调函数输入参数
* @param {boolean} irq_one_time, TRUE表示引脚中断触发一次后自动关闭中断,用于电平敏感中断
* @note 注册的回调函数在FGpioInterruptHandler中被调用
*/
void FGpioRegisterInterruptCB(FGpioPin *const pin, FGpioInterruptCallback cb, void *cb_param, boolean irq_one_time)
{
FASSERT(pin);
pin->irq_cb = cb;
pin->irq_cb_params = cb_param;
pin->irq_one_time = irq_one_time;
return;
}
|