1 /**************************************************************************/
4 @author K. Townsend (microBuilder.eu)
10 Controls the general purpose digital IO.
14 Software License Agreement (BSD License)
16 Copyright (c) 2010, microBuilder SARL
19 Redistribution and use in source and binary forms, with or without
20 modification, are permitted provided that the following conditions are met:
21 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
23 2. Redistributions in binary form must reproduce the above copyright
24 notice, this list of conditions and the following disclaimer in the
25 documentation and/or other materials provided with the distribution.
26 3. Neither the name of the copyright holders nor the
27 names of its contributors may be used to endorse or promote products
28 derived from this software without specific prior written permission.
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
31 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 /**************************************************************************/
46 #include "drivers/chibi/chb_drvr.h"
47 volatile uint32_t chibi_counter
= 0;
51 #include "core/cpu/cpu.h"
54 static bool _gpioInitialised
= false;
56 /**************************************************************************/
58 @brief IRQ Handler for GPIO port 0 (currently checks pin 0.1)
60 /**************************************************************************/
61 void PIOINT0_IRQHandler(void)
65 regVal
= gpioIntStatus(0, 1);
73 /**************************************************************************/
75 @brief IRQ Handler for GPIO port 1 (currently checks pin 1.1)
77 /**************************************************************************/
78 void PIOINT1_IRQHandler(void)
82 #if defined CFG_ALTRESET && CFG_ALTRESET_PORT == 1
83 regVal
= gpioIntStatus(CFG_ALTRESET_PORT
, CFG_ALTRESET_PIN
);
86 // Cause a reset and wait
92 // Check for interrupt on 1.8
93 regVal
= gpioIntStatus(1, 8);
101 regVal
= gpioIntStatus(1, 1);
111 /**************************************************************************/
113 @brief IRQ Handler for GPIO port 2 (currently checks pin 2.1)
115 /**************************************************************************/
116 void PIOINT2_IRQHandler(void)
120 regVal
= gpioIntStatus(2, 1);
128 /**************************************************************************/
130 @brief IRQ Handler for GPIO port 3 (currently checks pin 3.1)
132 /**************************************************************************/
133 void PIOINT3_IRQHandler(void)
137 regVal
= gpioIntStatus(3, 1);
145 /**************************************************************************/
147 @brief Initialises GPIO and enables the GPIO interrupt
148 handler for all GPIO ports.
150 /**************************************************************************/
153 /* Enable AHB clock to the GPIO domain. */
154 SCB_SYSAHBCLKCTRL
|= (SCB_SYSAHBCLKCTRL_GPIO
);
156 /* Set up NVIC when I/O pins are configured as external interrupts. */
157 NVIC_EnableIRQ(EINT0_IRQn
);
158 NVIC_EnableIRQ(EINT1_IRQn
);
159 NVIC_EnableIRQ(EINT2_IRQn
);
160 NVIC_EnableIRQ(EINT3_IRQn
);
162 /* Set initialisation flag */
163 _gpioInitialised
= true;
168 /**************************************************************************/
170 @brief Sets the direction (input/output) for a specific port pin
173 The port number (0..3)
175 The bit position (0..11)
177 The pin direction (gpioDirection_Input or
178 gpioDirection_Output)
180 /**************************************************************************/
181 void gpioSetDir (uint32_t portNum
, uint32_t bitPos
, gpioDirection_t dir
)
183 if (!_gpioInitialised
) gpioInit();
185 // Get the appropriate register (handled this way to optimise code size)
186 REG32
*gpiodir
= &GPIO_GPIO0DIR
;
190 gpiodir
= &GPIO_GPIO0DIR
;
193 gpiodir
= &GPIO_GPIO1DIR
;
196 gpiodir
= &GPIO_GPIO2DIR
;
199 gpiodir
= &GPIO_GPIO3DIR
;
204 dir
== gpioDirection_Output
? (*gpiodir
|= (1 << bitPos
)) : (*gpiodir
&= ~(1 << bitPos
));
207 /**************************************************************************/
209 @brief Gets the value for a specific port pin
212 The port number (0..3)
214 The bit position (0..31)
216 @return The current value for the specified port pin (0..1)
218 /**************************************************************************/
219 uint32_t gpioGetValue (uint32_t portNum
, uint32_t bitPos
)
221 if (!_gpioInitialised
) gpioInit();
228 value
= (GPIO_GPIO0DATA
& (1 << bitPos
)) ? 1 : 0;
231 value
= (GPIO_GPIO1DATA
& (1 << bitPos
)) ? 1 : 0;
234 value
= (GPIO_GPIO2DATA
& (1 << bitPos
)) ? 1 : 0;
237 value
= (GPIO_GPIO3DATA
& (1 << bitPos
)) ? 1 : 0;
246 /**************************************************************************/
248 @brief Sets the value for a specific port pin (only relevant when a
249 pin is configured as output).
252 The port number (0..3)
254 The bit position (0..31)
256 The value to set for the specified bit (0..1). 0 will set
257 the pin low and 1 will set the pin high.
259 /**************************************************************************/
260 void gpioSetValue (uint32_t portNum
, uint32_t bitPos
, uint32_t bitVal
)
262 if (!_gpioInitialised
) gpioInit();
264 // Get the appropriate register (handled this way to optimise code size)
265 REG32
*gpiodata
= &GPIO_GPIO0DATA
;
269 gpiodata
= &GPIO_GPIO0DATA
;
272 gpiodata
= &GPIO_GPIO1DATA
;
275 gpiodata
= &GPIO_GPIO2DATA
;
278 gpiodata
= &GPIO_GPIO3DATA
;
283 bitVal
== 1 ? (*gpiodata
|= (1 << bitPos
)) : (*gpiodata
&= ~(1 << bitPos
));
286 /**************************************************************************/
288 @brief Sets the interrupt sense, event, etc.
291 The port number (0..3)
293 The bit position (0..31)
295 Whether the interrupt should be configured as edge or level
298 Whether one edge or both trigger an interrupt.
300 Whether the rising or the falling edge (high or low)
301 should be used to trigger the interrupt.
308 // Set GPIO1.8 to input
309 gpioSetDir(1, 8, gpioDirection_Input);
310 // Disable the internal pullup/down resistor on P1.8
311 gpioSetPullup (&IOCON_PIO1_8, gpioPullupMode_Inactive);
312 // Setup an interrupt on GPIO1.8
313 gpioSetInterrupt(1, // Port
315 gpioInterruptSense_Edge, // Edge/Level Sensitive
316 gpioInterruptEdge_Single, // Single/Double Edge
317 gpioInterruptEvent_ActiveHigh); // Rising/Falling
318 // Enable the interrupt
322 /**************************************************************************/
323 void gpioSetInterrupt (uint32_t portNum
, uint32_t bitPos
, gpioInterruptSense_t sense
, gpioInterruptEdge_t edge
, gpioInterruptEvent_t event
)
325 if (!_gpioInitialised
) gpioInit();
327 // Get the appropriate register (handled this way to optimise code size)
328 REG32
*gpiois
= &GPIO_GPIO0IS
; // Interrupt sense (edge or level sensitive)
329 REG32
*gpioibe
= &GPIO_GPIO0IBE
; // Interrupt both edges (0 = int controlled by GPIOIEV, 1 = both edges trigger interrupt)
330 REG32
*gpioiev
= &GPIO_GPIO0IEV
; // 0 = falling edge or low, 1 = rising edge or high (depending on GPIOIS)
334 gpiois
= &GPIO_GPIO0IS
;
335 gpioibe
= &GPIO_GPIO0IBE
;
336 gpioiev
= &GPIO_GPIO0IEV
;
339 gpiois
= &GPIO_GPIO1IS
;
340 gpioibe
= &GPIO_GPIO1IBE
;
341 gpioiev
= &GPIO_GPIO1IEV
;
344 gpiois
= &GPIO_GPIO2IS
;
345 gpioibe
= &GPIO_GPIO2IBE
;
346 gpioiev
= &GPIO_GPIO2IEV
;
349 gpiois
= &GPIO_GPIO3IS
;
350 gpioibe
= &GPIO_GPIO3IBE
;
351 gpioiev
= &GPIO_GPIO3IEV
;
356 if (sense
== gpioInterruptSense_Edge
)
358 *gpiois
&= ~(0x1<<bitPos
);
359 edge
== gpioInterruptEdge_Single
? (*gpioibe
&= ~(0x1<<bitPos
)) : (*gpioibe
|= (0x1<<bitPos
));
363 *gpiois
|= (0x1<<bitPos
);
366 event
== gpioInterruptEvent_ActiveHigh
? (*gpioiev
&= ~(0x1<<bitPos
)) : (*gpioiev
|= (0x1<<bitPos
));
371 /**************************************************************************/
373 @brief Enables the interrupt mask for a specific port pin
376 The port number (0..3)
378 The bit position (0..31)
380 /**************************************************************************/
381 void gpioIntEnable (uint32_t portNum
, uint32_t bitPos
)
383 if (!_gpioInitialised
) gpioInit();
388 GPIO_GPIO0IE
|= (0x1<<bitPos
);
391 GPIO_GPIO1IE
|= (0x1<<bitPos
);
394 GPIO_GPIO2IE
|= (0x1<<bitPos
);
397 GPIO_GPIO3IE
|= (0x1<<bitPos
);
405 /**************************************************************************/
407 @brief Disables the interrupt mask for a specific port pin
410 The port number (0..3)
412 The bit position (0..31)
414 /**************************************************************************/
415 void gpioIntDisable (uint32_t portNum
, uint32_t bitPos
)
417 if (!_gpioInitialised
) gpioInit();
422 GPIO_GPIO0IE
&= ~(0x1<<bitPos
);
425 GPIO_GPIO1IE
&= ~(0x1<<bitPos
);
428 GPIO_GPIO2IE
&= ~(0x1<<bitPos
);
431 GPIO_GPIO3IE
&= ~(0x1<<bitPos
);
439 /**************************************************************************/
441 @brief Gets the interrupt status for a specific port pin
444 The port number (0..3)
446 The bit position (0..31)
448 @return The interrupt status for the specified port pin (0..1)
450 /**************************************************************************/
451 uint32_t gpioIntStatus (uint32_t portNum
, uint32_t bitPos
)
453 if (!_gpioInitialised
) gpioInit();
460 if (GPIO_GPIO0MIS
& (0x1<<bitPos
))
466 if (GPIO_GPIO1MIS
& (0x1<<bitPos
))
472 if (GPIO_GPIO2MIS
& (0x1<<bitPos
))
478 if (GPIO_GPIO3MIS
& (0x1<<bitPos
))
489 /**************************************************************************/
491 @brief Clears the interrupt for a port pin
494 The port number (0..3)
496 The bit position (0..31)
498 /**************************************************************************/
499 void gpioIntClear (uint32_t portNum
, uint32_t bitPos
)
501 if (!_gpioInitialised
) gpioInit();
506 GPIO_GPIO0IC
|= (0x1<<bitPos
);
509 GPIO_GPIO1IC
|= (0x1<<bitPos
);
512 GPIO_GPIO2IC
|= (0x1<<bitPos
);
515 GPIO_GPIO3IC
|= (0x1<<bitPos
);
523 /**************************************************************************/
525 @brief Configures the internal pullup/down resistor for GPIO pins
526 (only relevant for pins configured as inputs)
529 A pointer to the IOCON registry value corresponding to
530 the pin you wish to change (for example: &IOCON_PIO2_0
533 The 'mode' that the pin should be set to, which must be
534 correspond to a value defined in gpioPullupMode_t
536 @warning By default, all GPIO pins have the internal pull-up
537 resistor enabled. This may cause unusual behaviour if
538 care isn't taken to set the internal resistor to an
546 // Set GPIO1.8 to input
547 gpioSetDir(1, 8, gpioDirection_Input);
548 // Disable the internal pullup/down resistor on P1.8
549 gpioSetPullup(&IOCON_PIO1_8, gpioPullupMode_Inactive);
552 /**************************************************************************/
553 void gpioSetPullup (volatile uint32_t *ioconReg
, gpioPullupMode_t mode
)
555 if (!_gpioInitialised
) gpioInit();
557 // ToDo: Disable interrupts while we are doing this?
559 *ioconReg
&= ~(IOCON_COMMON_MODE_MASK
);
562 // ToDo: Re-enable interrupts?