1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-08-28 qiyu first version
9 */
10 #include <rthw.h>
11 #include "drv_gpio.h"
12 #include "F2837xD_device.h"
13 #include "F28x_Project.h" // Device Headerfile and Examples Include File
14 #ifdef RT_USING_PIN
15
16 // the gpio pin number for each port is 32, while it is 16 for ARM
17 #define PIN_NUM(port, no) (((((port) & 0xFu) << 5) | ((no) & 0x1F)))
18 #define PIN_PORT(pin) ((rt_uint16_t)(((pin) >> 5) & 0xFu))
19 #define PIN_NO(pin) ((rt_uint16_t)((pin) & 0x1Fu))
20
21 #define PIN_c28x_PORT(pin) (volatile Uint32 *)&GpioDataRegs + (PIN_PORT(pin))*GPY_DATA_OFFSET
22 #define PIN_c28x_PIN(pin) ((rt_uint32_t)(1u << PIN_NO(pin)))
23
24 #define PIN_c28x_PORT_MAX 6 /* gpioA to GPIOF in total*/
25 #define PIN_IRQ_MAX 5 /* XINT1 to XINT5 in total */
26
27 static rt_err_t c28x_pin_attach_irq(struct rt_device *device, rt_base_t pin,
28 rt_uint8_t mode, void (*hdr)(void *args), void *args);
29 static rt_err_t c28x_pin_dettach_irq(struct rt_device *device, rt_base_t pin);
30 static rt_err_t c28x_pin_irq_enable(struct rt_device *device, rt_base_t pin,
31 rt_uint8_t enabled);
32
c28x_pin_get(const char * name)33 static rt_base_t c28x_pin_get(const char *name)
34 {
35 int hw_pin_num = 0;
36 int i, name_len;
37
38 name_len = rt_strlen(name);
39
40 if ((name_len < 3) || (name_len >= 7))
41 {
42 return -RT_EINVAL;
43 }
44 /*
45 * PX.y
46 */
47 if ((name[0] != 'P') || (name[2] != '.'))
48 {
49 return -RT_EINVAL;
50 }
51
52 for (i = 3; i < name_len; i++)
53 {
54 hw_pin_num *= 10;
55 hw_pin_num += name[i] - '0';
56 }
57 return hw_pin_num;
58 }
59
c28x_pin_write(rt_device_t dev,rt_base_t pin,rt_uint8_t value)60 static void c28x_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
61 {
62 volatile Uint32 *gpioDataReg;
63 Uint32 pinMask;
64 if (PIN_PORT(pin) < PIN_c28x_PORT_MAX)
65 {
66 gpioDataReg = PIN_c28x_PORT(pin);
67 pinMask = 1UL << (PIN_NO(pin));
68 if (value == 0)
69 {
70 gpioDataReg[GPYCLEAR] = pinMask;
71 }
72 else
73 {
74 gpioDataReg[GPYSET] = pinMask;
75 }
76 }
77 }
78
c28x_pin_read(rt_device_t dev,rt_base_t pin)79 static rt_ssize_t c28x_pin_read(rt_device_t dev, rt_base_t pin)
80 {
81 volatile Uint32 *gpioDataReg;
82 rt_ssize_t value = PIN_LOW;
83
84 if (PIN_PORT(pin) < PIN_c28x_PORT_MAX)
85 {
86 gpioDataReg = PIN_c28x_PORT(pin);
87 value = (gpioDataReg[GPYDAT] >> PIN_NO(pin)) & 0x1;
88 }
89
90 return value;
91 }
92
c28x_pin_mode(rt_device_t dev,rt_base_t pin,rt_uint8_t mode)93 static void c28x_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
94 {
95 volatile Uint32 *gpioBaseAddr;
96 volatile Uint32 *dir, *pud, *odr;
97 if (PIN_PORT(pin) >= PIN_c28x_PORT_MAX)
98 {
99 return;
100 }
101 rt_uint32_t pinMask;
102 pinMask = 1UL << PIN_NO(pin);
103 gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (PIN_PORT(pin))*GPY_CTRL_OFFSET;
104
105 dir = gpioBaseAddr + GPYDIR;
106 pud = gpioBaseAddr + GPYPUD;
107 odr = gpioBaseAddr + GPYODR;
108
109 EALLOW;
110 if (mode == PIN_MODE_OUTPUT)
111 {
112 *dir |= pinMask;
113 }
114 else if (mode == PIN_MODE_INPUT)
115 {
116 *dir &= ~pinMask;
117 }
118 else if (mode == PIN_MODE_INPUT_PULLUP)
119 {
120 *dir &= ~pinMask;
121 *pud &= ~pinMask;
122 }
123 else if (mode == PIN_MODE_INPUT_PULLDOWN)
124 {
125 /* input setting: pull down. */
126 *dir &= ~pinMask;
127 *pud |= pinMask;
128 }
129 else if (mode == PIN_MODE_OUTPUT_OD)
130 {
131 /* output setting: od. */
132 *dir |= pinMask;
133 *odr |= pinMask;
134 }
135 EDIS;
136 }
137
138 const static struct rt_pin_ops _c28x_pin_ops =
139 {
140 c28x_pin_mode,
141 c28x_pin_write,
142 c28x_pin_read,
143 c28x_pin_attach_irq,
144 c28x_pin_dettach_irq,
145 c28x_pin_irq_enable,
146 c28x_pin_get,
147 };
148
rt_hw_pin_init(void)149 int rt_hw_pin_init(void)
150 {
151 return rt_device_pin_register("pin", &_c28x_pin_ops, RT_NULL);
152 }
153
154 static struct rt_pin_irq_hdr pin_irq_hdr_tab[] =
155 {
156 {-1, 0, RT_NULL, RT_NULL},
157 {-1, 0, RT_NULL, RT_NULL},
158 {-1, 0, RT_NULL, RT_NULL},
159 {-1, 0, RT_NULL, RT_NULL},
160 {-1, 0, RT_NULL, RT_NULL},
161 };
162
163 static rt_int16_t pin_irq_xint_tab[] =
164 {
165 BSP_XINT1_PIN,
166 BSP_XINT2_PIN,
167 BSP_XINT3_PIN,
168 BSP_XINT4_PIN,
169 BSP_XINT5_PIN
170 };
get_irq_index(rt_uint32_t pin)171 rt_inline rt_int32_t get_irq_index(rt_uint32_t pin)
172 {
173 int i;
174 for(i = 0 ; i < PIN_IRQ_MAX ; i++)
175 {
176 if(pin_irq_xint_tab[i] == pin)
177 {
178 return i;
179 }
180 }
181 return -1;
182 }
183
184 #define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
185
c28x_pin_attach_irq(struct rt_device * device,rt_base_t pin,rt_uint8_t mode,void (* hdr)(void * args),void * args)186 static rt_err_t c28x_pin_attach_irq(struct rt_device *device, rt_base_t pin,
187 rt_uint8_t mode, void (*hdr)(void *args), void *args)
188 {
189 rt_base_t level;
190 rt_int32_t irqindex = -1;
191
192 if (PIN_PORT(pin) >= PIN_c28x_PORT_MAX)
193 {
194 return -RT_ENOSYS;
195 }
196 irqindex = get_irq_index(pin);
197 level = rt_hw_interrupt_disable();
198 if (pin_irq_hdr_tab[irqindex].pin == pin &&
199 pin_irq_hdr_tab[irqindex].hdr == hdr &&
200 pin_irq_hdr_tab[irqindex].mode == mode &&
201 pin_irq_hdr_tab[irqindex].args == args)
202 {
203 rt_hw_interrupt_enable(level);
204 return RT_EOK;
205 }
206 if (pin_irq_hdr_tab[irqindex].pin != -1)
207 {
208 rt_hw_interrupt_enable(level);
209 return -RT_EBUSY;
210 }
211 pin_irq_hdr_tab[irqindex].pin = pin;
212 pin_irq_hdr_tab[irqindex].hdr = hdr;
213 pin_irq_hdr_tab[irqindex].mode = mode;
214 pin_irq_hdr_tab[irqindex].args = args;
215 rt_hw_interrupt_enable(level);
216
217 return RT_EOK;
218 }
219
c28x_pin_dettach_irq(struct rt_device * device,rt_base_t pin)220 static rt_err_t c28x_pin_dettach_irq(struct rt_device *device, rt_base_t pin)
221 {
222 rt_base_t level;
223 rt_int32_t irqindex = -1;
224 rt_uint16_t i;
225 if (PIN_PORT(pin) >= PIN_c28x_PORT_MAX)
226 {
227 return -RT_ENOSYS;
228 }
229
230 for(i = 0 ; i < PIN_IRQ_MAX ; i++)
231 {
232 if(pin_irq_hdr_tab[i].pin == pin)
233 {
234 irqindex = i;
235 break;
236 }
237 }
238 if (irqindex == -1)
239 {
240 return -RT_ENOSYS;
241 }
242 level = rt_hw_interrupt_disable();
243 pin_irq_hdr_tab[irqindex].pin = -1;
244 pin_irq_hdr_tab[irqindex].hdr = RT_NULL;
245 pin_irq_hdr_tab[irqindex].mode = 0;
246 pin_irq_hdr_tab[irqindex].args = RT_NULL;
247 rt_hw_interrupt_enable(level);
248
249 return RT_EOK;
250 }
251
c28x_pin_irq_enable(struct rt_device * device,rt_base_t pin,rt_uint8_t enabled)252 static rt_err_t c28x_pin_irq_enable(struct rt_device *device, rt_base_t pin,
253 rt_uint8_t enabled)
254 {
255 rt_base_t level;
256 rt_int32_t irqindex = -1;
257 rt_uint16_t channel;
258 rt_uint16_t edge_mode,pin_mode;
259
260 if (PIN_PORT(pin) >= PIN_c28x_PORT_MAX)
261 {
262 return -RT_ENOSYS;
263 }
264
265 irqindex = get_irq_index(pin);
266
267 /* irqindex+1 = channel*/
268 if (irqindex < 0 || irqindex >= PIN_IRQ_MAX)
269 {
270 return -RT_ENOSYS;
271 }
272
273 if (enabled == PIN_IRQ_ENABLE)
274 {
275 level = rt_hw_interrupt_disable();
276
277 if (pin_irq_hdr_tab[irqindex].pin == -1)
278 {
279 rt_hw_interrupt_enable(level);
280 return -RT_ENOSYS;
281 }
282
283 /*
284 * 1. set the edge mode of interrupt triggering
285 * 2. set the GPIO mode
286 * 3. enable XINT channel and set the input source
287 */
288 channel = irqindex+1;
289 switch (pin_irq_hdr_tab[irqindex].mode)
290 {
291 case PIN_IRQ_MODE_RISING:
292 edge_mode = 1;
293 pin_mode = PIN_MODE_INPUT_PULLDOWN;
294 break;
295 case PIN_IRQ_MODE_FALLING:
296 edge_mode = 0;
297 pin_mode = PIN_MODE_INPUT_PULLUP;
298 break;
299 case PIN_IRQ_MODE_RISING_FALLING:
300 edge_mode = 3;
301 pin_mode = PIN_MODE_INPUT;
302 break;
303 }
304 if(channel == 1)
305 {
306 XintRegs.XINT1CR.bit.ENABLE = 1; // Enable XINT1
307 EALLOW;
308 InputXbarRegs.INPUT4SELECT = pin; //Set XINT1 source to GPIO-pin
309 EDIS;
310 XintRegs.XINT1CR.bit.POLARITY = edge_mode; // Falling edge interrupt
311 }
312 else if(channel == 2)
313 {
314 XintRegs.XINT2CR.bit.ENABLE = 1; // Enable XINT2
315 EALLOW;
316 InputXbarRegs.INPUT5SELECT = pin; //Set XINT1 source to GPIO-pin
317 EDIS;
318 XintRegs.XINT2CR.bit.POLARITY = edge_mode; // Falling edge interrupt
319 }
320 else if(channel == 3)
321 {
322 XintRegs.XINT3CR.bit.ENABLE = 1; // Enable XINT2
323 EALLOW;
324 InputXbarRegs.INPUT6SELECT = pin; //Set XINT1 source to GPIO-pin
325 EDIS;
326 XintRegs.XINT3CR.bit.POLARITY = edge_mode; // Falling edge interrupt
327 }
328 else if(channel == 4)
329 {
330 XintRegs.XINT4CR.bit.ENABLE = 1; // Enable XINT2
331 EALLOW;
332 InputXbarRegs.INPUT13SELECT = pin; //Set XINT1 source to GPIO-pin
333 EDIS;
334 XintRegs.XINT4CR.bit.POLARITY = edge_mode; // Falling edge interrupt
335 }
336 else if(channel == 5)
337 {
338 XintRegs.XINT5CR.bit.ENABLE = 1; // Enable XINT2
339 EALLOW;
340 InputXbarRegs.INPUT14SELECT = pin; //Set XINT1 source to GPIO-pin
341 EDIS;
342 XintRegs.XINT5CR.bit.POLARITY = edge_mode; // Falling edge interrupt
343 }
344
345 c28x_pin_mode(device, pin, pin_mode);
346 rt_hw_interrupt_enable(level);
347 }
348 else if (enabled == PIN_IRQ_DISABLE)
349 {
350 level = rt_hw_interrupt_disable();
351 channel = irqindex+1;
352 /*
353 * TODO modify this simpler
354 */
355 if(channel == 1)
356 {
357 XintRegs.XINT1CR.bit.ENABLE = 0; // Disable XINT1
358 }
359 else if(channel == 2)
360 {
361 XintRegs.XINT2CR.bit.ENABLE = 0; // Disable XINT2
362 }
363 else if(channel == 3)
364 {
365 XintRegs.XINT3CR.bit.ENABLE = 0; // Disable XINT2
366 }
367 else if(channel == 4)
368 {
369 XintRegs.XINT4CR.bit.ENABLE = 0; // Disable XINT2
370 }
371 else if(channel == 5)
372 {
373 XintRegs.XINT5CR.bit.ENABLE = 0; // Disable XINT2
374 }
375 rt_hw_interrupt_enable(level);
376 }
377 else
378 {
379 return -RT_ENOSYS;
380 }
381
382 return RT_EOK;
383 }
384
385 void GPIO_XINT_Callback(rt_int16_t XINT_number);
386
XINT1_Handler(void)387 interrupt void XINT1_Handler(void)
388 {
389 rt_interrupt_enter();
390 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
391 GPIO_XINT_Callback(1);
392 rt_interrupt_leave();
393 }
394
XINT2_Handler(void)395 interrupt void XINT2_Handler(void)
396 {
397 rt_interrupt_enter();
398 GPIO_XINT_Callback(2);
399 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
400 rt_interrupt_leave();
401 }
402
XINT3_Handler(void)403 interrupt void XINT3_Handler(void)
404 {
405 rt_interrupt_enter();
406 GPIO_XINT_Callback(3);
407 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
408 rt_interrupt_leave();
409 }
410
XINT4_Handler(void)411 interrupt void XINT4_Handler(void)
412 {
413 rt_interrupt_enter();
414 GPIO_XINT_Callback(4);
415 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
416 rt_interrupt_leave();
417 }
418
XINT5_Handler(void)419 interrupt void XINT5_Handler(void)
420 {
421 rt_interrupt_enter();
422 GPIO_XINT_Callback(5);
423 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
424 rt_interrupt_leave();
425 }
426
GPIO_XINT_Callback(rt_int16_t XINT_number)427 void GPIO_XINT_Callback(rt_int16_t XINT_number)
428 {
429 rt_int32_t irqindex = XINT_number - 1;
430 if(pin_irq_hdr_tab[irqindex].hdr)
431 {
432 pin_irq_hdr_tab[irqindex].hdr(pin_irq_hdr_tab[irqindex].args);
433 }
434 }
435
436 #endif /* RT_USING_PIN */
437
438
439
440