1 /*
2 *
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Change Logs:
6 * Date Author Notes
7 * 2020-09-05 DongBowen first version
8 */
9
10 #include <rtthread.h>
11 #include "rthw.h"
12
13 #include "drv_gpio.h"
14 #include "hc32l196_sysctrl.h"
15
16 #ifdef RT_USING_PIN
17 #ifdef BSP_USING_GPIO
18
19 #define __GPIO_PORT(pin) (((pin) & 0xf0) * 4)
20 #define __GPIO_PORT_L(pin) (__GPIO_PORT(pin))
21 #define __GPIO_PORT_H(pin) ((__GPIO_PORT(pin) & 0xff) + 0x1000)
22 #define PE0_PIN (4 * 15)
23 #define GPIO_PORT(pin) (en_gpio_port_t)((pin) < PE0_PIN ? __GPIO_PORT_L((pin)) : __GPIO_PORT_H((pin)))
24 #define GPIO_PIN(pin) (en_gpio_pin_t)((pin) & 0x0f)
25
26 /* Port: PA-PF, Pin: 0-15 */
27 #define PIN_MAX_NUM (6 * 16)
28
29 #define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
30
31 static struct rt_pin_irq_hdr pin_irq_hdr_tab[PIN_MAX_NUM];
32
33 #define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
34
_pin_mode(rt_device_t dev,rt_base_t pin,rt_uint8_t mode)35 static void _pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
36 {
37 en_gpio_port_t gpio_port;
38 en_gpio_pin_t gpio_pin;
39 stc_gpio_cfg_t gpio_cfg;
40
41 if (pin >= PIN_MAX_NUM)
42 {
43 return;
44 }
45
46 gpio_port = GPIO_PORT(pin);
47 gpio_pin = GPIO_PIN(pin);
48
49 gpio_cfg.bOutputVal = 0;
50 gpio_cfg.enDrv = GpioDrvH;
51 gpio_cfg.enPu = GpioPuDisable;
52 gpio_cfg.enPd = GpioPdDisable;
53 gpio_cfg.enOD = GpioOdDisable;
54 gpio_cfg.enCtrlMode = GpioAHB;
55
56 switch (mode)
57 {
58 case PIN_MODE_OUTPUT:
59 gpio_cfg.enDir = GpioDirOut;
60 break;
61 case PIN_MODE_INPUT:
62 gpio_cfg.enDir = GpioDirIn;
63 break;
64 case PIN_MODE_INPUT_PULLUP:
65 gpio_cfg.enDir = GpioDirIn;
66 gpio_cfg.enPu = GpioPuEnable;
67 break;
68 case PIN_MODE_INPUT_PULLDOWN:
69 gpio_cfg.enDir = GpioDirIn;
70 gpio_cfg.enPd = GpioPdEnable;
71 break;
72 case PIN_MODE_OUTPUT_OD:
73 gpio_cfg.enDir = GpioDirOut;
74 gpio_cfg.enOD = GpioOdEnable;
75 break;
76 default:
77 break;
78 }
79
80 Gpio_Init(gpio_port, gpio_pin, &gpio_cfg);
81 }
82
_pin_write(rt_device_t dev,rt_base_t pin,rt_uint8_t value)83 static void _pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
84 {
85 en_gpio_port_t gpio_port;
86 en_gpio_pin_t gpio_pin;
87
88 if (pin >= PIN_MAX_NUM)
89 {
90 return;
91 }
92
93 gpio_port = GPIO_PORT(pin);
94 gpio_pin = GPIO_PIN(pin);
95
96 if (PIN_LOW == value)
97 {
98 Gpio_ClrIO(gpio_port, gpio_pin);
99 }
100 else
101 {
102 Gpio_SetIO(gpio_port, gpio_pin);
103 }
104 }
105
_pin_read(rt_device_t dev,rt_base_t pin)106 static rt_ssize_t _pin_read(rt_device_t dev, rt_base_t pin)
107 {
108 en_gpio_port_t gpio_port;
109 en_gpio_pin_t gpio_pin;
110
111 if (pin >= PIN_MAX_NUM)
112 {
113 return -RT_EINVAL;
114 }
115
116 gpio_port = GPIO_PORT(pin);
117 gpio_pin = GPIO_PIN(pin);
118
119 return Gpio_GetInputIO(gpio_port, gpio_pin) ? PIN_HIGH : PIN_LOW;
120 }
121
_pin_attach_irq(struct rt_device * device,rt_base_t pin,rt_uint8_t mode,void (* hdr)(void * args),void * args)122 static rt_err_t _pin_attach_irq(struct rt_device *device,
123 rt_base_t pin,
124 rt_uint8_t mode,
125 void (*hdr)(void *args),
126 void *args)
127 {
128 rt_base_t level;
129
130 if (pin >= PIN_MAX_NUM)
131 {
132 return -RT_ENOSYS;
133 }
134
135 level = rt_hw_interrupt_disable();
136 if (pin_irq_hdr_tab[pin].pin == pin &&
137 pin_irq_hdr_tab[pin].mode == mode &&
138 pin_irq_hdr_tab[pin].hdr == hdr &&
139 pin_irq_hdr_tab[pin].args == args)
140 {
141 rt_hw_interrupt_enable(level);
142 return RT_EOK;
143 }
144 pin_irq_hdr_tab[pin].pin = pin;
145 pin_irq_hdr_tab[pin].mode = mode;
146 pin_irq_hdr_tab[pin].hdr = hdr;
147 pin_irq_hdr_tab[pin].args = args;
148 rt_hw_interrupt_enable(level);
149 return RT_EOK;
150 }
151
_pin_detach_irq(struct rt_device * device,rt_base_t pin)152 static rt_err_t _pin_detach_irq(struct rt_device *device, rt_base_t pin)
153 {
154 rt_base_t level;
155
156 if (pin >= PIN_MAX_NUM)
157 {
158 return -RT_ENOSYS;
159 }
160
161 level = rt_hw_interrupt_disable();
162 pin_irq_hdr_tab[pin].mode = 0;
163 pin_irq_hdr_tab[pin].hdr = RT_NULL;
164 pin_irq_hdr_tab[pin].args = RT_NULL;
165 rt_hw_interrupt_enable(level);
166 return RT_EOK;
167 }
168
get_irqn(rt_base_t pin)169 static IRQn_Type get_irqn(rt_base_t pin)
170 {
171 en_gpio_port_t gpio_port;
172 IRQn_Type irqn = (IRQn_Type)0xff;
173
174 if (pin >= PIN_MAX_NUM)
175 {
176 return irqn;
177 }
178
179 gpio_port = GPIO_PORT(pin);
180 switch (gpio_port)
181 {
182 case GpioPortA:
183 irqn = PORTA_IRQn;
184 break;
185 case GpioPortB:
186 irqn = PORTB_IRQn;
187 break;
188 case GpioPortC:
189 case GpioPortE:
190 irqn = PORTC_E_IRQn;
191 break;
192 case GpioPortD:
193 case GpioPortF:
194 irqn = PORTD_F_IRQn;
195 break;
196 }
197
198 return irqn;
199 }
200
_pin_irq_enable(struct rt_device * device,rt_base_t pin,rt_uint8_t enabled)201 static rt_err_t _pin_irq_enable(struct rt_device *device,
202 rt_base_t pin,
203 rt_uint8_t enabled)
204 {
205 rt_base_t level = 0;
206 en_gpio_port_t gpio_port;
207 en_gpio_pin_t gpio_pin;
208 IRQn_Type irqn;
209
210 if (pin >= PIN_MAX_NUM)
211 {
212 return -RT_ENOSYS;
213 }
214
215 gpio_port = GPIO_PORT(pin);
216 gpio_pin = GPIO_PIN(pin);
217 irqn = get_irqn(pin);
218
219 if (enabled == PIN_IRQ_ENABLE)
220 {
221 switch (pin_irq_hdr_tab[pin].mode)
222 {
223 case PIN_IRQ_MODE_RISING:
224 Gpio_EnableIrq(gpio_port, gpio_pin, GpioIrqRising);
225 break;
226 case PIN_IRQ_MODE_FALLING:
227 Gpio_EnableIrq(gpio_port, gpio_pin, GpioIrqFalling);
228 break;
229 case PIN_IRQ_MODE_RISING_FALLING:
230 Gpio_EnableIrq(gpio_port, gpio_pin, GpioIrqRising);
231 Gpio_EnableIrq(gpio_port, gpio_pin, GpioIrqFalling);
232 break;
233 case PIN_IRQ_MODE_HIGH_LEVEL:
234 Gpio_EnableIrq(gpio_port, gpio_pin, GpioIrqHigh);
235 break;
236 case PIN_IRQ_MODE_LOW_LEVEL:
237 Gpio_EnableIrq(gpio_port, gpio_pin, GpioIrqLow);
238 break;
239 default:
240 return -RT_EINVAL;
241 }
242
243 level = rt_hw_interrupt_disable();
244 NVIC_ClearPendingIRQ(irqn);
245 NVIC_EnableIRQ(irqn);
246 rt_hw_interrupt_enable(level);
247 }
248 else if (enabled == PIN_IRQ_DISABLE)
249 {
250 switch (pin_irq_hdr_tab[pin].mode)
251 {
252 case PIN_IRQ_MODE_RISING:
253 Gpio_DisableIrq(gpio_port, gpio_pin, GpioIrqRising);
254 break;
255 case PIN_IRQ_MODE_FALLING:
256 Gpio_DisableIrq(gpio_port, gpio_pin, GpioIrqFalling);
257 break;
258 case PIN_IRQ_MODE_RISING_FALLING:
259 Gpio_DisableIrq(gpio_port, gpio_pin, GpioIrqRising);
260 Gpio_DisableIrq(gpio_port, gpio_pin, GpioIrqFalling);
261 break;
262 case PIN_IRQ_MODE_HIGH_LEVEL:
263 Gpio_DisableIrq(gpio_port, gpio_pin, GpioIrqHigh);
264 break;
265 case PIN_IRQ_MODE_LOW_LEVEL:
266 Gpio_DisableIrq(gpio_port, gpio_pin, GpioIrqLow);
267 break;
268 default:
269 break;
270 }
271
272 level = rt_hw_interrupt_disable();
273 NVIC_ClearPendingIRQ(irqn);
274 NVIC_DisableIRQ(irqn);
275 rt_hw_interrupt_enable(level);
276 }
277 else
278 {
279 return -RT_ENOSYS;
280 }
281 return RT_EOK;
282 }
283
284 const static struct rt_pin_ops _pin_ops =
285 {
286 .pin_mode = _pin_mode,
287 .pin_write = _pin_write,
288 .pin_read = _pin_read,
289 .pin_attach_irq = _pin_attach_irq,
290 .pin_detach_irq = _pin_detach_irq,
291 .pin_irq_enable = _pin_irq_enable,
292 };
293
pin_isr(en_gpio_port_t gpio_port)294 static void pin_isr(en_gpio_port_t gpio_port)
295 {
296 en_gpio_pin_t gpio_pin = GpioPin0;
297 int pin = __GET_PIN(gpio_port, 0);
298
299 for (; gpio_pin <= GpioPin15; gpio_pin++, pin++)
300 {
301 if (Gpio_GetIrqStatus(gpio_port, gpio_pin))
302 {
303 if (pin_irq_hdr_tab[pin].hdr)
304 {
305 pin_irq_hdr_tab[pin].hdr(pin_irq_hdr_tab[pin].args);
306 }
307 Gpio_ClearIrq(gpio_port, gpio_pin);
308 }
309 }
310 }
311
PortA_IRQHandler(void)312 void PortA_IRQHandler(void)
313 {
314 rt_interrupt_enter();
315 pin_isr(GpioPortA);
316 rt_interrupt_leave();
317 }
318
PortB_IRQHandler(void)319 void PortB_IRQHandler(void)
320 {
321 rt_interrupt_enter();
322 pin_isr(GpioPortB);
323 rt_interrupt_leave();
324 }
325
PortC_IRQHandler(void)326 void PortC_IRQHandler(void)
327 {
328 rt_interrupt_enter();
329 pin_isr(GpioPortC);
330 rt_interrupt_leave();
331 }
332
PortD_IRQHandler(void)333 void PortD_IRQHandler(void)
334 {
335 rt_interrupt_enter();
336 pin_isr(GpioPortD);
337 rt_interrupt_leave();
338 }
339
PortE_IRQHandler(void)340 void PortE_IRQHandler(void)
341 {
342 rt_interrupt_enter();
343 pin_isr(GpioPortE);
344 rt_interrupt_leave();
345 }
346
PortF_IRQHandler(void)347 void PortF_IRQHandler(void)
348 {
349 rt_interrupt_enter();
350 pin_isr(GpioPortF);
351 rt_interrupt_leave();
352 }
353
rt_hw_pin_init(void)354 int rt_hw_pin_init(void)
355 {
356 Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
357 return rt_device_pin_register("pin", &_pin_ops, RT_NULL);
358 }
359 INIT_BOARD_EXPORT(rt_hw_pin_init);
360
361 #endif /* BSP_USING_GPIO */
362 #endif /* RT_USING_PIN */
363