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