mirror of https://github.com/ARMmbed/mbed-os.git
Fix GPIO implementation
parent
b6c2306e4e
commit
d51db9039c
|
@ -103,7 +103,7 @@ typedef enum {
|
||||||
PullDown = InputPullDown,
|
PullDown = InputPullDown,
|
||||||
OpenDrain = WiredAnd,
|
OpenDrain = WiredAnd,
|
||||||
PullNone = PushPull,
|
PullNone = PushPull,
|
||||||
PullDefault = PullUp
|
PullDefault = PushPull
|
||||||
} PinMode;
|
} PinMode;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -102,7 +102,7 @@ typedef enum {
|
||||||
PullDown = InputPullDown,
|
PullDown = InputPullDown,
|
||||||
OpenDrain = WiredAnd,
|
OpenDrain = WiredAnd,
|
||||||
PullNone = PushPull,
|
PullNone = PushPull,
|
||||||
PullDefault = PullUp
|
PullDefault = PushPull
|
||||||
} PinMode;
|
} PinMode;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -102,7 +102,7 @@ typedef enum {
|
||||||
PullDown = InputPullDown,
|
PullDown = InputPullDown,
|
||||||
OpenDrain = WiredAnd,
|
OpenDrain = WiredAnd,
|
||||||
PullNone = PushPull,
|
PullNone = PushPull,
|
||||||
PullDefault = PullUp
|
PullDefault = PushPull
|
||||||
} PinMode;
|
} PinMode;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -102,7 +102,7 @@ typedef enum {
|
||||||
PullDown = InputPullDown,
|
PullDown = InputPullDown,
|
||||||
OpenDrain = WiredAnd,
|
OpenDrain = WiredAnd,
|
||||||
PullNone = PushPull,
|
PullNone = PushPull,
|
||||||
PullDefault = PullUp
|
PullDefault = PushPull
|
||||||
} PinMode;
|
} PinMode;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -102,7 +102,7 @@ typedef enum {
|
||||||
PullDown = InputPullDown,
|
PullDown = InputPullDown,
|
||||||
OpenDrain = WiredAnd,
|
OpenDrain = WiredAnd,
|
||||||
PullNone = PushPull,
|
PullNone = PushPull,
|
||||||
PullDefault = PullUp
|
PullDefault = PushPull
|
||||||
} PinMode;
|
} PinMode;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -19,9 +19,28 @@
|
||||||
#include "mbed_assert.h"
|
#include "mbed_assert.h"
|
||||||
#include "sleepmodes.h"
|
#include "sleepmodes.h"
|
||||||
|
|
||||||
uint8_t gpio_get_index(gpio_t *obj)
|
|
||||||
|
void gpio_write(gpio_t *obj, int value)
|
||||||
{
|
{
|
||||||
return 0;
|
if (value) {
|
||||||
|
GPIO_PinOutSet((GPIO_Port_TypeDef)(obj->pin >> 4 & 0xF), obj->pin & 0xF); // Pin number encoded in first four bits of obj->pin
|
||||||
|
} else {
|
||||||
|
GPIO_PinOutClear((GPIO_Port_TypeDef)(obj->pin >> 4 & 0xF), obj->pin & 0xF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int gpio_read(gpio_t *obj)
|
||||||
|
{
|
||||||
|
if (obj->dir == PIN_INPUT) {
|
||||||
|
return GPIO_PinInGet((GPIO_Port_TypeDef)(obj->pin >> 4 & 0xF), obj->pin & 0xF); // Pin number encoded in first four bits of obj->pin
|
||||||
|
} else {
|
||||||
|
return GPIO_PinOutGet((GPIO_Port_TypeDef)(obj->pin >> 4 & 0xF), obj->pin & 0xF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int gpio_is_connected(const gpio_t *obj)
|
||||||
|
{
|
||||||
|
return (obj->pin | 0xFFFFFF00 )!= (PinName)NC;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -44,25 +63,49 @@ void gpio_init(gpio_t *obj, PinName pin)
|
||||||
obj->pin = pin;
|
obj->pin = pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_pin_enable(gpio_t *obj, uint8_t enable)
|
|
||||||
{
|
|
||||||
if (enable) {
|
|
||||||
pin_mode(obj->pin, obj->mode);
|
|
||||||
} else {
|
|
||||||
pin_mode(obj->pin, Disabled); // TODO_LP return mode to default value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||||
{
|
{
|
||||||
|
if(obj->dir == PIN_INPUT) {
|
||||||
|
switch(mode) {
|
||||||
|
case PullDefault:
|
||||||
|
mode = Input;
|
||||||
|
break;
|
||||||
|
case PullUp:
|
||||||
|
mode = InputPullUp;
|
||||||
|
break;
|
||||||
|
case PullDown:
|
||||||
|
mode = InputPullDown;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Handle DOUT setting
|
||||||
|
if((mode & 0x10) != 0) {
|
||||||
|
//Set DOUT
|
||||||
|
GPIO->P[(obj->pin >> 4) & 0xF].DOUTSET = 1 << (obj->pin & 0xF);
|
||||||
|
} else {
|
||||||
|
//Clear DOUT
|
||||||
|
GPIO->P[(obj->pin >> 4) & 0xF].DOUTCLR = 1 << (obj->pin & 0xF);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch(mode) {
|
||||||
|
case PullDefault:
|
||||||
|
mode = PushPull;
|
||||||
|
break;
|
||||||
|
case PullUp:
|
||||||
|
mode = WiredAndPullUp;
|
||||||
|
break;
|
||||||
|
case PullDown:
|
||||||
|
mode = WiredOrPullDown;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
obj->mode = mode; // Update object
|
obj->mode = mode; // Update object
|
||||||
pin_mode(obj->pin, mode); // Update register
|
pin_mode(obj->pin, mode); // Update register
|
||||||
|
|
||||||
//Handle pullup for input
|
|
||||||
if(mode == InputPullUp) {
|
|
||||||
//Set DOUT
|
|
||||||
GPIO->P[(obj->pin >> 4) & 0xF].DOUTSET = 1 << (obj->pin & 0xF);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used by DigitalInOut to set correct mode when direction is set
|
// Used by DigitalInOut to set correct mode when direction is set
|
||||||
|
@ -78,4 +121,3 @@ void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ __STATIC_INLINE uint32_t countTrailingZeros(uint32_t mask)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uint32_t channel_ids[NUM_GPIO_CHANNELS] = { 0 }; // Relates pin number with interrupt action id
|
static uint32_t channel_ids[NUM_GPIO_CHANNELS] = { 0 }; // Relates pin number with interrupt action id
|
||||||
static uint32_t channel_ports[NUM_GPIO_CHANNELS] = { 0 };
|
static uint8_t channel_ports[NUM_GPIO_CHANNELS/2] = { 0 }; // Storing 2 ports in each uint8
|
||||||
static gpio_irq_handler irq_handler;
|
static gpio_irq_handler irq_handler;
|
||||||
static void GPIOINT_IRQDispatcher(uint32_t iflags);
|
static void GPIOINT_IRQDispatcher(uint32_t iflags);
|
||||||
|
|
||||||
|
@ -57,7 +57,9 @@ static void handle_interrupt_in(uint8_t pin)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t isRise = GPIO_PinInGet(channel_ports[pin], pin);
|
//we are storing two ports in each uint8, so we must aquire the one we want.
|
||||||
|
// If pin is odd, the port is encoded in the 4 most significant bits. If pin is even, the port is encoded in the 4 least significant bits
|
||||||
|
uint8_t isRise = GPIO_PinInGet((pin & 0x1) ? channel_ports[(pin>>1) & 0x7] >> 4 & 0xF : channel_ports[(pin>>1) & 0x7] & 0xF, pin);
|
||||||
|
|
||||||
// Get trigger event
|
// Get trigger event
|
||||||
gpio_irq_event event = IRQ_NONE;
|
gpio_irq_event event = IRQ_NONE;
|
||||||
|
@ -77,40 +79,39 @@ void gpio_irq_preinit(gpio_irq_t *obj, PinName pin)
|
||||||
/* Pin and port index encoded in one uint32.
|
/* Pin and port index encoded in one uint32.
|
||||||
* The four least significant bits represent the pin number
|
* The four least significant bits represent the pin number
|
||||||
* The remaining bits represent the port number */
|
* The remaining bits represent the port number */
|
||||||
obj->pin = pin & 0xF;
|
obj->pin = pin;
|
||||||
obj->port = pin >> 4;
|
|
||||||
obj->risingEdge = 0;
|
obj->risingEdge = 0;
|
||||||
obj->fallingEdge = 0;
|
obj->fallingEdge = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
|
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
|
||||||
{
|
{
|
||||||
/* Init pins */
|
// Init pins
|
||||||
gpio_irq_preinit(obj, pin);
|
gpio_irq_preinit(obj, pin);
|
||||||
/* Initialize GPIO interrupt dispatcher */
|
// Initialize GPIO interrupt dispatcher
|
||||||
NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
|
NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
|
||||||
NVIC_EnableIRQ(GPIO_ODD_IRQn);
|
NVIC_EnableIRQ(GPIO_ODD_IRQn);
|
||||||
NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
|
NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
|
||||||
NVIC_EnableIRQ(GPIO_EVEN_IRQn);
|
NVIC_EnableIRQ(GPIO_EVEN_IRQn);
|
||||||
|
|
||||||
/* Relate pin to interrupt action id */
|
/* Relate pin to interrupt action id */
|
||||||
channel_ids[obj->pin] = id;
|
channel_ids[obj->pin & 0xF] = id;
|
||||||
/* Relate the pin number to a port */
|
|
||||||
channel_ports[obj->pin] = obj->port;
|
// Relate the pin number to a port. If pin in is odd store in the 4 most significant bits, if pin is even store in the 4 least significant bits
|
||||||
|
channel_ports[(obj->pin >> 1) & 0x7] = (obj->pin & 0x1) ? (channel_ports[(obj->pin >> 1) & 0x7] & 0x0F) | (obj->pin & 0xF0) : (channel_ports[(obj->pin >> 1) & 0x7] & 0xF0) | ((obj->pin >> 4) & 0xF);
|
||||||
/* Save pointer to handler */
|
/* Save pointer to handler */
|
||||||
irq_handler = handler;
|
irq_handler = handler;
|
||||||
|
|
||||||
pin_mode(obj->pin | (obj->port << 4), Input);
|
pin_mode(obj->pin, Input);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_irq_free(gpio_irq_t *obj)
|
void gpio_irq_free(gpio_irq_t *obj)
|
||||||
{
|
{
|
||||||
// Destructor
|
// Destructor
|
||||||
channel_ids[obj->pin] = 0;
|
channel_ids[obj->pin & 0xF] = 0;
|
||||||
gpio_irq_disable(obj); // Disable interrupt channel
|
gpio_irq_disable(obj); // Disable interrupt channel
|
||||||
pin_mode(obj->pin | (obj->port << 4), Disabled); // Disable input pin
|
pin_mode(obj->pin, Disabled); // Disable input pin
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
|
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
|
||||||
|
@ -132,7 +133,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
|
||||||
bool was_disabled = false;
|
bool was_disabled = false;
|
||||||
if(GPIO->IEN == 0) was_disabled = true;
|
if(GPIO->IEN == 0) was_disabled = true;
|
||||||
|
|
||||||
GPIO_IntConfig(obj->port, obj->pin, obj->risingEdge, obj->fallingEdge, obj->risingEdge || obj->fallingEdge);
|
GPIO_IntConfig((GPIO_Port_TypeDef)(obj->pin >> 4 & 0xF), obj->pin &0xF, obj->risingEdge, obj->fallingEdge, obj->risingEdge || obj->fallingEdge);
|
||||||
if ((GPIO->IEN != 0) && (obj->risingEdge || obj->fallingEdge) && was_disabled) {
|
if ((GPIO->IEN != 0) && (obj->risingEdge || obj->fallingEdge) && was_disabled) {
|
||||||
blockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
|
blockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
|
||||||
}
|
}
|
||||||
|
@ -141,12 +142,12 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
|
||||||
inline void gpio_irq_enable(gpio_irq_t *obj)
|
inline void gpio_irq_enable(gpio_irq_t *obj)
|
||||||
{
|
{
|
||||||
if(GPIO->IEN == 0) blockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
|
if(GPIO->IEN == 0) blockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
|
||||||
GPIO_IntEnable(1 << obj->pin); // pin mask for pins to enable
|
GPIO_IntEnable(1 << obj->pin & 0xF); // pin mask for pins to enable
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void gpio_irq_disable(gpio_irq_t *obj)
|
inline void gpio_irq_disable(gpio_irq_t *obj)
|
||||||
{
|
{
|
||||||
GPIO_IntDisable(1 << obj->pin); // pin mask for pins to disable
|
GPIO_IntDisable(1 << obj->pin & 0xF); // pin mask for pins to disable
|
||||||
if(GPIO->IEN == 0) unblockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
|
if(GPIO->IEN == 0) unblockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,14 +188,13 @@ static void GPIOINT_IRQDispatcher(uint32_t iflags)
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void GPIO_EVEN_IRQHandler(void)
|
void GPIO_EVEN_IRQHandler(void)
|
||||||
{
|
{
|
||||||
uint32_t iflags;
|
uint32_t iflags;
|
||||||
|
/* Get all even interrupts */
|
||||||
|
iflags = GPIO_IntGetEnabled() & 0x00005555;
|
||||||
|
|
||||||
/* Get all even interrupts. */
|
/* Clean only even interrupts.*/
|
||||||
iflags = GPIO_IntGetEnabled() & 0x00005555;
|
|
||||||
|
|
||||||
/* Clean only even interrupts. */
|
|
||||||
GPIO_IntClear(iflags);
|
GPIO_IntClear(iflags);
|
||||||
|
|
||||||
GPIOINT_IRQDispatcher(iflags);
|
GPIOINT_IRQDispatcher(iflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,14 +207,13 @@ void GPIO_EVEN_IRQHandler(void)
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void GPIO_ODD_IRQHandler(void)
|
void GPIO_ODD_IRQHandler(void)
|
||||||
{
|
{
|
||||||
uint32_t iflags;
|
uint32_t iflags;
|
||||||
|
|
||||||
/* Get all odd interrupts. */
|
/* Get all odd interrupts by */
|
||||||
iflags = GPIO_IntGetEnabled() & 0x0000AAAA;
|
iflags = GPIO_IntGetEnabled() & 0x0000AAAA;
|
||||||
|
|
||||||
/* Clean only even interrupts. */
|
/* Clean only even interrupts.*/
|
||||||
GPIO_IntClear(iflags);
|
GPIO_IntClear(iflags);
|
||||||
|
|
||||||
GPIOINT_IRQDispatcher(iflags);
|
GPIOINT_IRQDispatcher(iflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
/* mbed Microcontroller Library
|
|
||||||
* Copyright (c) 2006-2013 ARM Limited
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
#ifndef MBED_GPIO_OBJECT_H
|
|
||||||
#define MBED_GPIO_OBJECT_H
|
|
||||||
|
|
||||||
#include "em_gpio.h"
|
|
||||||
#include "PinNames.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PinName pin;
|
|
||||||
PinMode mode;
|
|
||||||
PinDirection dir;
|
|
||||||
} gpio_t;
|
|
||||||
|
|
||||||
static inline void gpio_write(gpio_t *obj, int value)
|
|
||||||
{
|
|
||||||
if (value) {
|
|
||||||
GPIO_PinOutSet((GPIO_Port_TypeDef)((obj->pin >> 4) & 0xF), obj->pin & 0xF); // Pin number encoded in first four bits of obj->pin
|
|
||||||
} else {
|
|
||||||
GPIO_PinOutClear((GPIO_Port_TypeDef)((obj->pin >> 4) & 0xF), obj->pin & 0xF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int gpio_read(gpio_t *obj)
|
|
||||||
{
|
|
||||||
if (obj->dir == PIN_INPUT) {
|
|
||||||
return GPIO_PinInGet((GPIO_Port_TypeDef)((obj->pin >> 4) & 0xF), obj->pin & 0xF); // Pin number encoded in first four bits of obj->pin
|
|
||||||
} else {
|
|
||||||
return GPIO_PinOutGet((GPIO_Port_TypeDef)((obj->pin >> 4) & 0xF), obj->pin & 0xF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int gpio_is_connected(const gpio_t *obj)
|
|
||||||
{
|
|
||||||
return obj->pin != (PinName)NC;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -28,6 +28,12 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PinName pin:8;
|
||||||
|
PinMode mode:6;
|
||||||
|
PinDirection dir:2;
|
||||||
|
} gpio_t;
|
||||||
|
|
||||||
#if DEVICE_ANALOGIN
|
#if DEVICE_ANALOGIN
|
||||||
struct analogin_s {
|
struct analogin_s {
|
||||||
ADC_TypeDef *adc;
|
ADC_TypeDef *adc;
|
||||||
|
@ -79,10 +85,9 @@ struct pwmout_s {
|
||||||
|
|
||||||
#if DEVICE_INTERRUPTIN
|
#if DEVICE_INTERRUPTIN
|
||||||
struct gpio_irq_s {
|
struct gpio_irq_s {
|
||||||
uint32_t port;
|
PinName pin:8; // Pin number 4 least significant bits, port number 4 most significant bits
|
||||||
PinName pin;
|
uint32_t risingEdge:1;
|
||||||
uint32_t risingEdge;
|
uint32_t fallingEdge:1;
|
||||||
uint32_t fallingEdge;
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -137,7 +142,6 @@ typedef enum {
|
||||||
} sleepstate_enum;
|
} sleepstate_enum;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "gpio_object.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue