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/rf/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 @note By default, this IRQ handler is probably disabled in
61 projectconfig.h (see GPIO_ENABLE_IRQ0), but you can use
62 the code below as a model to implement this interrupt
63 handler in an appropriate place in your project.
65 /**************************************************************************/
66 #if defined GPIO_ENABLE_IRQ0
67 void PIOINT0_IRQHandler(void)
71 regVal
= gpioIntStatus(0, 1);
80 /**************************************************************************/
82 @brief IRQ Handler for GPIO port 1 (currently checks pin 1.1)
84 /**************************************************************************/
85 #if defined GPIO_ENABLE_IRQ1
86 void PIOINT1_IRQHandler(void)
90 #if defined CFG_ALTRESET && CFG_ALTRESET_PORT == 1
91 regVal
= gpioIntStatus(CFG_ALTRESET_PORT
, CFG_ALTRESET_PIN
);
94 // Cause a reset and wait
100 // Check for interrupt on 1.8
101 regVal
= gpioIntStatus(1, 8);
109 regVal
= gpioIntStatus(1, 1);
120 /**************************************************************************/
122 @brief IRQ Handler for GPIO port 2 (currently checks pin 2.1)
124 @note By default, this IRQ handler is probably disabled in
125 projectconfig.h (see GPIO_ENABLE_IRQ2), but you can use
126 the code below as a model to implement this interrupt
127 handler in an appropriate place in your project.
129 /**************************************************************************/
130 #if defined GPIO_ENABLE_IRQ2
131 void PIOINT2_IRQHandler(void)
135 regVal
= gpioIntStatus(2, 1);
144 /**************************************************************************/
146 @brief IRQ Handler for GPIO port 3 (currently checks pin 3.1)
148 @note By default, this IRQ handler is probably disabled in
149 projectconfig.h (see GPIO_ENABLE_IRQ3), but you can use
150 the code below as a model to implement this interrupt
151 handler in an appropriate place in your project.
153 /**************************************************************************/
154 #if defined GPIO_ENABLE_IRQ3
155 void PIOINT3_IRQHandler(void)
159 regVal
= gpioIntStatus(3, 1);
168 /**************************************************************************/
170 @brief Initialises GPIO and enables the GPIO interrupt
171 handler for all GPIO ports.
173 /**************************************************************************/
176 /* Enable AHB clock to the GPIO domain. */
177 SCB_SYSAHBCLKCTRL
|= (SCB_SYSAHBCLKCTRL_GPIO
);
179 /* Set up NVIC when I/O pins are configured as external interrupts. */
180 NVIC_EnableIRQ(EINT0_IRQn
);
181 NVIC_EnableIRQ(EINT1_IRQn
);
182 NVIC_EnableIRQ(EINT2_IRQn
);
183 NVIC_EnableIRQ(EINT3_IRQn
);
185 /* Set initialisation flag */
186 _gpioInitialised
= true;
191 /**************************************************************************/
193 @brief Sets the direction (input/output) for a specific port pin
196 The port number (0..3)
198 The bit position (0..11)
200 The pin direction (gpioDirection_Input or
201 gpioDirection_Output)
203 /**************************************************************************/
204 void gpioSetDir (uint32_t portNum
, uint32_t bitPos
, gpioDirection_t dir
)
206 if (!_gpioInitialised
) gpioInit();
208 // Get the appropriate register (handled this way to optimise code size)
209 REG32
*gpiodir
= &GPIO_GPIO0DIR
;
213 gpiodir
= &GPIO_GPIO0DIR
;
216 gpiodir
= &GPIO_GPIO1DIR
;
219 gpiodir
= &GPIO_GPIO2DIR
;
222 gpiodir
= &GPIO_GPIO3DIR
;
227 dir
== gpioDirection_Output
? (*gpiodir
|= (1 << bitPos
)) : (*gpiodir
&= ~(1 << bitPos
));
230 /**************************************************************************/
232 @brief Sets the interrupt sense, event, etc.
235 The port number (0..3)
237 The bit position (0..31)
239 Whether the interrupt should be configured as edge or level
242 Whether one edge or both trigger an interrupt.
244 Whether the rising or the falling edge (high or low)
245 should be used to trigger the interrupt.
252 // Set GPIO1.8 to input
253 gpioSetDir(1, 8, gpioDirection_Input);
254 // Disable the internal pullup/down resistor on P1.8
255 gpioSetPullup (&IOCON_PIO1_8, gpioPullupMode_Inactive);
256 // Setup an interrupt on GPIO1.8
257 gpioSetInterrupt(1, // Port
259 gpioInterruptSense_Edge, // Edge/Level Sensitive
260 gpioInterruptEdge_Single, // Single/Double Edge
261 gpioInterruptEvent_ActiveHigh); // Rising/Falling
262 // Enable the interrupt
266 /**************************************************************************/
267 void gpioSetInterrupt (uint32_t portNum
, uint32_t bitPos
, gpioInterruptSense_t sense
, gpioInterruptEdge_t edge
, gpioInterruptEvent_t event
)
269 if (!_gpioInitialised
) gpioInit();
271 // Get the appropriate register (handled this way to optimise code size)
272 REG32
*gpiois
= &GPIO_GPIO0IS
; // Interrupt sense (edge or level sensitive)
273 REG32
*gpioibe
= &GPIO_GPIO0IBE
; // Interrupt both edges (0 = int controlled by GPIOIEV, 1 = both edges trigger interrupt)
274 REG32
*gpioiev
= &GPIO_GPIO0IEV
; // 0 = falling edge or low, 1 = rising edge or high (depending on GPIOIS)
278 gpiois
= &GPIO_GPIO0IS
;
279 gpioibe
= &GPIO_GPIO0IBE
;
280 gpioiev
= &GPIO_GPIO0IEV
;
283 gpiois
= &GPIO_GPIO1IS
;
284 gpioibe
= &GPIO_GPIO1IBE
;
285 gpioiev
= &GPIO_GPIO1IEV
;
288 gpiois
= &GPIO_GPIO2IS
;
289 gpioibe
= &GPIO_GPIO2IBE
;
290 gpioiev
= &GPIO_GPIO2IEV
;
293 gpiois
= &GPIO_GPIO3IS
;
294 gpioibe
= &GPIO_GPIO3IBE
;
295 gpioiev
= &GPIO_GPIO3IEV
;
299 if (sense
== gpioInterruptSense_Edge
)
301 *gpiois
&= ~(0x1<<bitPos
);
302 edge
== gpioInterruptEdge_Single
? (*gpioibe
&= ~(0x1<<bitPos
)) : (*gpioibe
|= (0x1<<bitPos
));
306 *gpiois
|= (0x1<<bitPos
);
309 event
== gpioInterruptEvent_ActiveLow
? (*gpioiev
&= ~(0x1<<bitPos
)) : (*gpioiev
|= (0x1<<bitPos
));
314 /**************************************************************************/
316 @brief Enables the interrupt mask for a specific port pin
319 The port number (0..3)
321 The bit position (0..31)
323 /**************************************************************************/
324 void gpioIntEnable (uint32_t portNum
, uint32_t bitPos
)
326 if (!_gpioInitialised
) gpioInit();
331 GPIO_GPIO0IE
|= (0x1<<bitPos
);
334 GPIO_GPIO1IE
|= (0x1<<bitPos
);
337 GPIO_GPIO2IE
|= (0x1<<bitPos
);
340 GPIO_GPIO3IE
|= (0x1<<bitPos
);
348 /**************************************************************************/
350 @brief Disables the interrupt mask for a specific port pin
353 The port number (0..3)
355 The bit position (0..31)
357 /**************************************************************************/
358 void gpioIntDisable (uint32_t portNum
, uint32_t bitPos
)
360 if (!_gpioInitialised
) gpioInit();
365 GPIO_GPIO0IE
&= ~(0x1<<bitPos
);
368 GPIO_GPIO1IE
&= ~(0x1<<bitPos
);
371 GPIO_GPIO2IE
&= ~(0x1<<bitPos
);
374 GPIO_GPIO3IE
&= ~(0x1<<bitPos
);
382 /**************************************************************************/
384 @brief Gets the interrupt status for a specific port pin
387 The port number (0..3)
389 The bit position (0..31)
391 @return The interrupt status for the specified port pin (0..1)
393 /**************************************************************************/
394 uint32_t gpioIntStatus (uint32_t portNum
, uint32_t bitPos
)
396 if (!_gpioInitialised
) gpioInit();
403 if (GPIO_GPIO0MIS
& (0x1<<bitPos
))
409 if (GPIO_GPIO1MIS
& (0x1<<bitPos
))
415 if (GPIO_GPIO2MIS
& (0x1<<bitPos
))
421 if (GPIO_GPIO3MIS
& (0x1<<bitPos
))
432 /**************************************************************************/
434 @brief Clears the interrupt for a port pin
437 The port number (0..3)
439 The bit position (0..31)
441 /**************************************************************************/
442 void gpioIntClear (uint32_t portNum
, uint32_t bitPos
)
444 if (!_gpioInitialised
) gpioInit();
449 GPIO_GPIO0IC
|= (0x1<<bitPos
);
452 GPIO_GPIO1IC
|= (0x1<<bitPos
);
455 GPIO_GPIO2IC
|= (0x1<<bitPos
);
458 GPIO_GPIO3IC
|= (0x1<<bitPos
);
466 /**************************************************************************/
468 @brief Configures the internal pullup/down resistor for GPIO pins
469 (only relevant for pins configured as inputs)
472 A pointer to the IOCON registry value corresponding to
473 the pin you wish to change (for example: &IOCON_PIO2_0
476 The 'mode' that the pin should be set to, which must be
477 correspond to a value defined in gpioPullupMode_t
479 @warning By default, all GPIO pins have the internal pull-up
480 resistor enabled. This may cause unusual behaviour if
481 care isn't taken to set the internal resistor to an
489 // Set GPIO1.8 to input
490 gpioSetDir(1, 8, gpioDirection_Input);
491 // Disable the internal pullup/down resistor on P1.8
492 gpioSetPullup(&IOCON_PIO1_8, gpioPullupMode_Inactive);
495 /**************************************************************************/
496 void gpioSetPullup (volatile uint32_t *ioconReg
, gpioPullupMode_t mode
)
498 if (!_gpioInitialised
) gpioInit();
500 // ToDo: Disable interrupts while we are doing this?
502 *ioconReg
&= ~(IOCON_COMMON_MODE_MASK
);
505 // ToDo: Re-enable interrupts?