1 //###########################################################################
2 //
3 // FILE: F2837xD_Gpio.c
4 //
5 // TITLE: GPIO module support functions
6 //
7 //###########################################################################
8 // $TI Release: F2837xD Support Library v3.05.00.00 $
9 // $Release Date: Tue Jun 26 03:15:23 CDT 2018 $
10 // $Copyright:
11 // Copyright (C) 2013-2018 Texas Instruments Incorporated - http://www.ti.com/
12 //
13 // Redistribution and use in source and binary forms, with or without
14 // modification, are permitted provided that the following conditions
15 // are met:
16 //
17 // Redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
19 //
20 // Redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the
23 // distribution.
24 //
25 // Neither the name of Texas Instruments Incorporated nor the names of
26 // its contributors may be used to endorse or promote products derived
27 // from this software without specific prior written permission.
28 //
29 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 // $
41 //###########################################################################
42
43 //
44 // Included Files
45 //
46 #include "F2837xD_device.h"
47 #include "F2837xD_Examples.h"
48
49 //
50 //Low-level functions for GPIO configuration (CPU1 only)
51 //
52
53 #ifdef CPU1
54 //
55 // InitGpio - Sets all pins to be muxed to GPIO in input mode with pull-ups
56 // enabled. Also resets CPU control to CPU1 and disables open
57 // drain and polarity inversion and sets the qualification to
58 // synchronous. Also unlocks all GPIOs. Only one CPU should call
59 // this function.
60 //
InitGpio()61 void InitGpio()
62 {
63 volatile Uint32 *gpioBaseAddr;
64 Uint16 regOffset;
65
66 //
67 //Disable pin locks
68 //
69 EALLOW;
70 GpioCtrlRegs.GPALOCK.all = 0x00000000;
71 GpioCtrlRegs.GPBLOCK.all = 0x00000000;
72 GpioCtrlRegs.GPCLOCK.all = 0x00000000;
73 GpioCtrlRegs.GPDLOCK.all = 0x00000000;
74 GpioCtrlRegs.GPELOCK.all = 0x00000000;
75 GpioCtrlRegs.GPFLOCK.all = 0x00000000;
76
77 //
78 // Fill all registers with zeros. Writing to each register separately
79 // for six GPIO modules would make this function *very* long.
80 // Fortunately, we'd be writing them all with zeros anyway, so this
81 // saves a lot of space.
82 //
83 gpioBaseAddr = (Uint32 *)&GpioCtrlRegs;
84 for (regOffset = 0; regOffset < sizeof(GpioCtrlRegs)/2; regOffset++)
85 {
86 //
87 //Hack to avoid enabling pull-ups on all pins. GPyPUD is offset
88 //0x0C in each register group of 0x40 words. Since this is a
89 //32-bit pointer, the addresses must be divided by 2.
90 //
91 if (regOffset % (0x40/2) != (0x0C/2))
92 {
93 gpioBaseAddr[regOffset] = 0x00000000;
94 }
95 }
96
97 gpioBaseAddr = (Uint32 *)&GpioDataRegs;
98 for (regOffset = 0; regOffset < sizeof(GpioDataRegs)/2; regOffset++)
99 {
100 gpioBaseAddr[regOffset] = 0x00000000;
101 }
102
103 EDIS;
104 }
105
106 //
107 // GPIO_SetupPinMux - Set the peripheral muxing for the specified pin. The
108 // appropriate parameters can be found in the GPIO Muxed
109 // Pins table(4.4) in the datasheet. Use the GPIO index
110 // row (0 to 15) to select a muxing option for the GPIO.
111 //
GPIO_SetupPinMux(Uint16 gpioNumber,Uint16 cpu,Uint16 muxPosition)112 void GPIO_SetupPinMux(Uint16 gpioNumber, Uint16 cpu, Uint16 muxPosition)
113 {
114 volatile Uint32 *gpioBaseAddr;
115 volatile Uint32 *mux, *gmux, *csel;
116 Uint16 pin32, pin16, pin8;
117
118 pin32 = gpioNumber % 32;
119 pin16 = gpioNumber % 16;
120 pin8 = gpioNumber % 8;
121 gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (gpioNumber/32)*GPY_CTRL_OFFSET;
122
123 //
124 //Sanity check for valid cpu and peripheral values
125 //
126 if (cpu > GPIO_MUX_CPU2CLA || muxPosition > 0xF)
127 return;
128
129 //
130 //Create pointers to the appropriate registers. This is a workaround
131 //for the way GPIO registers are defined. The standard definition
132 //in the header file makes it very easy to do named accesses of one
133 //register or bit, but hard to do arbitrary numerical accesses. It's
134 //easier to have an array of GPIO modules with identical registers,
135 //including arrays for multi-register groups like GPyCSEL1-4. But
136 //the header file doesn't define anything we can turn into an array,
137 //so manual pointer arithmetic is used instead.
138 //
139 mux = gpioBaseAddr + GPYMUX + pin32/16;
140 gmux = gpioBaseAddr + GPYGMUX + pin32/16;
141 csel = gpioBaseAddr + GPYCSEL + pin32/8;
142
143 //
144 //Now for the actual function
145 //
146 EALLOW;
147
148 //
149 //To change the muxing, set the peripheral mux to 0/GPIO first to avoid
150 //glitches, then change the group mux, then set the peripheral mux to
151 //its target value. Finally, set the CPU select. This procedure is
152 //described in the TRM. Unfortunately, since we don't know the pin in
153 //advance we can't hardcode a bitfield reference, so there's some
154 //tricky bit twiddling here.
155 //
156 *mux &= ~(0x3UL << (2*pin16));
157 *gmux &= ~(0x3UL << (2*pin16));
158 *gmux |= (Uint32)((muxPosition >> 2) & 0x3UL) << (2*pin16);
159 *mux |= (Uint32)(muxPosition & 0x3UL) << (2*pin16);
160
161 *csel &= ~(0x3L << (4*pin8));
162 *csel |= (Uint32)(cpu & 0x3L) << (4*pin8);
163
164 //
165 //WARNING: This code does not touch the analog mode select registers,
166 //which are needed to give the USB module control of its IOs.
167 //
168 EDIS;
169 }
170
171 //
172 // GPIO_SetupPinOptions - Setup up the GPIO input/output options for the
173 // specified pin.
174 //
175 //The flags are a 16-bit mask produced by ORing together options.
176 //For input pins, the valid flags are:
177 //GPIO_PULLUP Enable pull-up
178 //GPIO_INVERT Enable input polarity inversion
179 //GPIO_SYNC Synchronize the input latch to PLLSYSCLK
180 // (default -- you don't need to specify this)
181 //GPIO_QUAL3 Use 3-sample qualification
182 //GPIO_QUAL6 Use 6-sample qualification
183 //GPIO_ASYNC Do not use synchronization or qualification
184 //(Note: only one of SYNC, QUAL3, QUAL6, or ASYNC is allowed)
185 //
186 //For output pins, the valid flags are:
187 //GPIO_OPENDRAIN Output in open drain mode
188 //GPIO_PULLUP If open drain enabled, also enable the pull-up
189 //and the input qualification flags (SYNC/QUAL3/QUAL6/SYNC) listed above.
190 //
191 //With no flags, the default input state is synchronous with no
192 //pull-up or polarity inversion. The default output state is
193 //the standard digital output.
194 //
GPIO_SetupPinOptions(Uint16 gpioNumber,Uint16 output,Uint16 flags)195 void GPIO_SetupPinOptions(Uint16 gpioNumber, Uint16 output, Uint16 flags)
196 {
197 volatile Uint32 *gpioBaseAddr;
198 volatile Uint32 *dir, *pud, *inv, *odr, *qsel;
199 Uint32 pin32, pin16, pinMask, qual;
200
201 pin32 = gpioNumber % 32;
202 pin16 = gpioNumber % 16;
203 pinMask = 1UL << pin32;
204 gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (gpioNumber/32)*GPY_CTRL_OFFSET;
205
206 //
207 //Create pointers to the appropriate registers. This is a workaround
208 //for the way GPIO registers are defined. The standard definition
209 //in the header file makes it very easy to do named accesses of one
210 //register or bit, but hard to do arbitrary numerical accesses. It's
211 //easier to have an array of GPIO modules with identical registers,
212 //including arrays for multi-register groups like GPyQSEL1-2. But
213 //the header file doesn't define anything we can turn into an array,
214 //so manual pointer arithmetic is used instead.
215 //
216 dir = gpioBaseAddr + GPYDIR;
217 pud = gpioBaseAddr + GPYPUD;
218 inv = gpioBaseAddr + GPYINV;
219 odr = gpioBaseAddr + GPYODR;
220 qsel = gpioBaseAddr + GPYQSEL + pin32/16;
221
222 EALLOW;
223
224 //
225 //Set the data direction
226 //
227 *dir &= ~pinMask;
228 if (output == 1)
229 {
230 //
231 //Output, with optional open drain mode and pull-up
232 //
233 *dir |= pinMask;
234
235 //
236 //Enable open drain if necessary
237 //
238 if (flags & GPIO_OPENDRAIN)
239 {
240 *odr |= pinMask;
241 }
242 else
243 {
244 *odr &= ~pinMask;
245 }
246
247 //
248 //Enable pull-up if necessary. Open drain mode must be active.
249 //
250 if (flags & (GPIO_OPENDRAIN | GPIO_PULLUP))
251 {
252 *pud &= ~pinMask;
253 }
254 else
255 {
256 *pud |= pinMask;
257 }
258 }
259 else
260 {
261 //
262 //Input, with optional pull-up, qualification, and polarity
263 //inversion
264 //
265 *dir &= ~pinMask;
266
267 //
268 //Enable pull-up if necessary
269 //
270 if (flags & GPIO_PULLUP)
271 {
272 *pud &= ~pinMask;
273 }
274 else
275 {
276 *pud |= pinMask;
277 }
278
279 //
280 //Invert polarity if necessary
281 //
282 if (flags & GPIO_INVERT)
283 {
284 *inv |= pinMask;
285 }
286 else
287 {
288 *inv &= ~pinMask;
289 }
290 }
291
292 //
293 //Extract the qualification parameter and load it into the register.
294 //This is also needed for open drain outputs, so we might as well do it
295 //all the time.
296 //
297 qual = (flags & GPIO_ASYNC) / GPIO_QUAL3;
298 *qsel &= ~(0x3L << (2 * pin16));
299 if (qual != 0x0)
300 {
301 *qsel |= qual << (2 * pin16);
302 }
303
304 EDIS;
305 }
306
307 //
308 // GPIO_SetupLock - Enable or disable the GPIO register bit lock for the
309 // specified pin.
310 // The valid flags are:
311 // GPIO_UNLOCK - Unlock the pin setup register bits for
312 // the specified pin
313 // GPIO_LOCK - Lock the pin setup register bits for the
314 // specified pin
315 //
GPIO_SetupLock(Uint16 gpioNumber,Uint16 flags)316 void GPIO_SetupLock(Uint16 gpioNumber, Uint16 flags)
317 {
318 volatile Uint32 *gpioBaseAddr;
319 volatile Uint32 *lock;
320 Uint32 pin32, pinMask;
321
322 pin32 = gpioNumber % 32;
323 pinMask = 1UL << pin32;
324 gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (gpioNumber/32)*GPY_CTRL_OFFSET;
325
326 //
327 //Create pointers to the appropriate registers. This is a workaround
328 //for the way GPIO registers are defined. The standard definition
329 //in the header file makes it very easy to do named accesses of one
330 //register or bit, but hard to do arbitrary numerical accesses. It's
331 //easier to have an array of GPIO modules with identical registers,
332 //including arrays for multi-register groups like GPyQSEL1-2. But
333 //the header file doesn't define anything we can turn into an array,
334 //so manual pointer arithmetic is used instead.
335 //
336 lock = gpioBaseAddr + GPYLOCK;
337
338 EALLOW;
339 if(flags)
340 {
341 //Lock the pin
342 *lock |= pinMask;
343 }
344 else
345 {
346 //Unlock the pin
347 *lock &= ~pinMask;
348 }
349 EDIS;
350 }
351
352 //
353 //External interrupt setup
354 //
GPIO_SetupXINT1Gpio(Uint16 gpioNumber)355 void GPIO_SetupXINT1Gpio(Uint16 gpioNumber)
356 {
357 EALLOW;
358 InputXbarRegs.INPUT4SELECT = gpioNumber; //Set XINT1 source to GPIO-pin
359 EDIS;
360 }
GPIO_SetupXINT2Gpio(Uint16 gpioNumber)361 void GPIO_SetupXINT2Gpio(Uint16 gpioNumber)
362 {
363 EALLOW;
364 InputXbarRegs.INPUT5SELECT = gpioNumber; //Set XINT2 source to GPIO-pin
365 EDIS;
366 }
GPIO_SetupXINT3Gpio(Uint16 gpioNumber)367 void GPIO_SetupXINT3Gpio(Uint16 gpioNumber)
368 {
369 EALLOW;
370 InputXbarRegs.INPUT6SELECT = gpioNumber; //Set XINT3 source to GPIO-pin
371 EDIS;
372 }
GPIO_SetupXINT4Gpio(Uint16 gpioNumber)373 void GPIO_SetupXINT4Gpio(Uint16 gpioNumber)
374 {
375 EALLOW;
376 InputXbarRegs.INPUT13SELECT = gpioNumber; //Set XINT4 source to GPIO-pin
377 EDIS;
378 }
GPIO_SetupXINT5Gpio(Uint16 gpioNumber)379 void GPIO_SetupXINT5Gpio(Uint16 gpioNumber)
380 {
381 EALLOW;
382 InputXbarRegs.INPUT14SELECT = gpioNumber; //Set XINT5 source to GPIO-pin
383 EDIS;
384 }
385
386 //
387 //GPIO_EnableUnbondedIOPullupsFor176Pin - Enable pullups for the unbonded
388 // GPIOs on the 176PTP package:
389 // GPIOs Grp Bits
390 // 95-132 C 31
391 // D 31:0
392 // E 4:0
393 // 134-168 E 31:6
394 // F 8:0
395 //
GPIO_EnableUnbondedIOPullupsFor176Pin()396 void GPIO_EnableUnbondedIOPullupsFor176Pin()
397 {
398 EALLOW;
399 GpioCtrlRegs.GPCPUD.all = ~0x80000000; //GPIO 95
400 GpioCtrlRegs.GPDPUD.all = ~0xFFFFFFF7; //GPIOs 96-127
401 GpioCtrlRegs.GPEPUD.all = ~0xFFFFFFDF; //GPIOs 128-159 except for 133
402 GpioCtrlRegs.GPFPUD.all = ~0x000001FF; //GPIOs 160-168
403 EDIS;
404 }
405
406 //
407 // GPIO_EnableUnbondedIOPullupsFor100Pin - Enable pullups for the unbonded
408 // GPIOs on the 100PZ package:
409 // GPIOs Grp Bits
410 // 0-1 A 1:0
411 // 5-9 A 9:5
412 // 22-40 A 31:22
413 // B 8:0
414 // 44-57 B 25:12
415 // 67-68 C 4:3
416 // 74-77 C 13:10
417 // 79-83 C 19:15
418 // 93-168 C 31:29
419 // D 31:0
420 // E 31:0
421 // F 8:0
422 //
GPIO_EnableUnbondedIOPullupsFor100Pin()423 void GPIO_EnableUnbondedIOPullupsFor100Pin()
424 {
425 EALLOW;
426 GpioCtrlRegs.GPAPUD.all = ~0xFFC003E3; //GPIOs 0-1, 5-9, 22-31
427 GpioCtrlRegs.GPBPUD.all = ~0x03FFF1FF; //GPIOs 32-40, 44-57
428 GpioCtrlRegs.GPCPUD.all = ~0xE10FBC18; //GPIOs 67-68, 74-77, 79-83, 93-95
429 GpioCtrlRegs.GPDPUD.all = ~0xFFFFFFF7; //GPIOs 96-127
430 GpioCtrlRegs.GPEPUD.all = ~0xFFFFFFFF; //GPIOs 128-159
431 GpioCtrlRegs.GPFPUD.all = ~0x000001FF; //GPIOs 160-168
432 EDIS;
433 }
434
435 //
436 // GPIO_EnableUnbondedIOPullups - InitSysCtrl would call this function
437 // this takes care of enabling IO pullups.
438 //
GPIO_EnableUnbondedIOPullups()439 void GPIO_EnableUnbondedIOPullups()
440 {
441 //
442 //bits 8-10 have pin count
443 //
444 unsigned char pin_count = ((DevCfgRegs.PARTIDL.all & 0x00000700) >> 8) ;
445
446 //
447 //5 = 100 pin
448 //6 = 176 pin
449 //7 = 337 pin
450 //
451 if(pin_count == 5)
452 {
453 GPIO_EnableUnbondedIOPullupsFor100Pin();
454 }
455 else if (pin_count == 6)
456 {
457 GPIO_EnableUnbondedIOPullupsFor176Pin();
458 }
459 else
460 {
461 //do nothing - this is 337 pin package
462 }
463 }
464
465 #endif //CPU1
466
467 //
468 // GPIO_ReadPin - Read the GPyDAT register bit for the specified pin. Note that
469 // this returns the actual state of the pin, not the state of
470 // the output latch.
471 //
GPIO_ReadPin(Uint16 gpioNumber)472 Uint16 GPIO_ReadPin(Uint16 gpioNumber)
473 {
474 volatile Uint32 *gpioDataReg;
475 Uint16 pinVal;
476
477 gpioDataReg = (volatile Uint32 *)&GpioDataRegs + (gpioNumber/32)*GPY_DATA_OFFSET;
478 pinVal = (gpioDataReg[GPYDAT] >> (gpioNumber % 32)) & 0x1;
479
480 return pinVal;
481 }
482
483 //
484 // GPIO_WritePin - Set the GPyDAT register bit for the specified pin.
485 //
GPIO_WritePin(Uint16 gpioNumber,Uint16 outVal)486 void GPIO_WritePin(Uint16 gpioNumber, Uint16 outVal)
487 {
488 volatile Uint32 *gpioDataReg;
489 Uint32 pinMask;
490
491 gpioDataReg = (volatile Uint32 *)&GpioDataRegs + (gpioNumber/32)*GPY_DATA_OFFSET;
492 pinMask = 1UL << (gpioNumber % 32);
493
494 if (outVal == 0)
495 {
496 gpioDataReg[GPYCLEAR] = pinMask;
497 }
498 else
499 {
500 gpioDataReg[GPYSET] = pinMask;
501 }
502 }
503
504 //
505 // End of file
506 //
507