mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #7941 from OpenNuvoton/nuvoton_fix_gpio_mode_mapping
Nuvoton: Fix GPIO mode mappingpull/7970/merge
commit
815683c2bd
|
@ -94,15 +94,19 @@ typedef enum {
|
||||||
} PinDirection;
|
} PinDirection;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
/* Input pull mode */
|
||||||
PullNone = 0,
|
PullNone = 0,
|
||||||
PullDown,
|
PullDown,
|
||||||
PullUp,
|
PullUp,
|
||||||
|
|
||||||
PushPull,
|
/* I/O mode */
|
||||||
|
InputOnly,
|
||||||
|
PushPullOutput,
|
||||||
OpenDrain,
|
OpenDrain,
|
||||||
Quasi,
|
QuasiBidirectional,
|
||||||
|
|
||||||
PullDefault = PullUp,
|
/* Default input pull mode */
|
||||||
|
PullDefault = PullUp
|
||||||
} PinMode;
|
} PinMode;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -51,6 +51,9 @@ void gpio_init(gpio_t *obj, PinName pin)
|
||||||
}
|
}
|
||||||
|
|
||||||
obj->mask = gpio_set(pin);
|
obj->mask = gpio_set(pin);
|
||||||
|
/* Default mode/direction */
|
||||||
|
obj->mode = PullUp;
|
||||||
|
obj->direction = PIN_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||||
|
@ -59,7 +62,44 @@ void gpio_mode(gpio_t *obj, PinMode mode)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pin_mode(obj->pin, mode);
|
switch (mode) {
|
||||||
|
case PullNone:
|
||||||
|
case PullDown:
|
||||||
|
case PullUp:
|
||||||
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
|
* We translate to input-only/push-pull output I/O mode dependent on direction. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QuasiBidirectional:
|
||||||
|
/* With quasi-bidirectional I/O mode, before digital input function is performed,
|
||||||
|
* the corresponding bit in GPIOx_DOUT must be set to 1. */
|
||||||
|
obj->mode = QuasiBidirectional;
|
||||||
|
if (obj->direction == PIN_INPUT) {
|
||||||
|
gpio_write(obj, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InputOnly:
|
||||||
|
case PushPullOutput:
|
||||||
|
/* We may meet contradictory I/O mode/direction configuration. Favor I/O mode
|
||||||
|
* in the gpio_mode call here. */
|
||||||
|
if (mode == InputOnly) {
|
||||||
|
obj->direction = PIN_INPUT;
|
||||||
|
obj->mode = InputOnly;
|
||||||
|
} else {
|
||||||
|
obj->direction = PIN_OUTPUT;
|
||||||
|
obj->mode = PushPullOutput;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Allow for configuring other I/O modes directly */
|
||||||
|
obj->mode = mode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_mode(obj->pin, obj->mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_dir(gpio_t *obj, PinDirection direction)
|
void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||||
|
@ -68,24 +108,35 @@ void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
|
obj->direction = direction;
|
||||||
uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
|
|
||||||
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
|
||||||
|
|
||||||
uint32_t mode_intern = GPIO_MODE_INPUT;
|
switch (obj->mode) {
|
||||||
|
case PullNone:
|
||||||
switch (direction) {
|
case PullDown:
|
||||||
case PIN_INPUT:
|
case PullUp:
|
||||||
mode_intern = GPIO_MODE_INPUT;
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
|
* We translate to input-only/push-pull output I/O mode dependent on direction. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PIN_OUTPUT:
|
case QuasiBidirectional:
|
||||||
mode_intern = GPIO_MODE_OUTPUT;
|
/* With quasi-bidirectional I/O mode, before digital input function is performed,
|
||||||
|
* the corresponding bit in GPIOx_DOUT must be set to 1. */
|
||||||
|
if (obj->direction == PIN_INPUT) {
|
||||||
|
gpio_write(obj, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InputOnly:
|
||||||
|
case PushPullOutput:
|
||||||
|
/* We may meet contradictory I/O mode/direction configuration. Favor direction
|
||||||
|
* in the gpio_dir call here. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
pin_mode(obj->pin, obj->mode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,10 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PinName pin;
|
PinName pin;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
|
PinDirection direction;
|
||||||
|
PinMode mode;
|
||||||
} gpio_t;
|
} gpio_t;
|
||||||
|
|
||||||
static inline void gpio_write(gpio_t *obj, int value)
|
static inline void gpio_write(gpio_t *obj, int value)
|
||||||
|
|
|
@ -43,16 +43,11 @@ void pin_mode(PinName pin, PinMode mode)
|
||||||
uint32_t mode_intern = GPIO_MODE_INPUT;
|
uint32_t mode_intern = GPIO_MODE_INPUT;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case PullUp:
|
case InputOnly:
|
||||||
mode_intern = GPIO_MODE_INPUT;
|
mode_intern = GPIO_MODE_INPUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PullDown:
|
case PushPullOutput:
|
||||||
case PullNone:
|
|
||||||
// NOTE: Not support
|
|
||||||
return;
|
|
||||||
|
|
||||||
case PushPull:
|
|
||||||
mode_intern = GPIO_MODE_OUTPUT;
|
mode_intern = GPIO_MODE_OUTPUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -60,12 +55,26 @@ void pin_mode(PinName pin, PinMode mode)
|
||||||
mode_intern = GPIO_MODE_OPEN_DRAIN;
|
mode_intern = GPIO_MODE_OPEN_DRAIN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Quasi:
|
case QuasiBidirectional:
|
||||||
mode_intern = GPIO_MODE_QUASI;
|
mode_intern = GPIO_MODE_QUASI;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
|
* We expect upper layer would have translated input pull mode/direction
|
||||||
|
* to I/O mode */
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
||||||
|
|
||||||
|
/* Invalid combinations of PinMode/PinDirection
|
||||||
|
*
|
||||||
|
* We assume developer would avoid the following combinations of PinMode/PinDirection
|
||||||
|
* which are invalid:
|
||||||
|
* 1. InputOnly/PIN_OUTPUT
|
||||||
|
* 2. PushPullOutput/PIN_INPUT
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
|
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
|
||||||
|
|
|
@ -55,15 +55,19 @@ typedef enum {
|
||||||
} PinDirection;
|
} PinDirection;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
/* Input pull mode */
|
||||||
PullNone = 0,
|
PullNone = 0,
|
||||||
PullDown,
|
PullDown,
|
||||||
PullUp,
|
PullUp,
|
||||||
|
|
||||||
PushPull,
|
/* I/O mode */
|
||||||
|
InputOnly,
|
||||||
|
PushPullOutput,
|
||||||
OpenDrain,
|
OpenDrain,
|
||||||
Quasi,
|
QuasiBidirectional,
|
||||||
|
|
||||||
PullDefault = PullUp,
|
/* Default input pull mode */
|
||||||
|
PullDefault = PullUp
|
||||||
} PinMode;
|
} PinMode;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -51,6 +51,9 @@ void gpio_init(gpio_t *obj, PinName pin)
|
||||||
}
|
}
|
||||||
|
|
||||||
obj->mask = gpio_set(pin);
|
obj->mask = gpio_set(pin);
|
||||||
|
/* Default mode/direction */
|
||||||
|
obj->mode = PullUp;
|
||||||
|
obj->direction = PIN_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||||
|
@ -59,7 +62,44 @@ void gpio_mode(gpio_t *obj, PinMode mode)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pin_mode(obj->pin, mode);
|
switch (mode) {
|
||||||
|
case PullNone:
|
||||||
|
case PullDown:
|
||||||
|
case PullUp:
|
||||||
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
|
* We translate to input-only/push-pull output I/O mode dependent on direction. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QuasiBidirectional:
|
||||||
|
/* With quasi-bidirectional I/O mode, before digital input function is performed,
|
||||||
|
* the corresponding bit in GPIOx_DOUT must be set to 1. */
|
||||||
|
obj->mode = QuasiBidirectional;
|
||||||
|
if (obj->direction == PIN_INPUT) {
|
||||||
|
gpio_write(obj, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InputOnly:
|
||||||
|
case PushPullOutput:
|
||||||
|
/* We may meet contradictory I/O mode/direction configuration. Favor I/O mode
|
||||||
|
* in the gpio_mode call here. */
|
||||||
|
if (mode == InputOnly) {
|
||||||
|
obj->direction = PIN_INPUT;
|
||||||
|
obj->mode = InputOnly;
|
||||||
|
} else {
|
||||||
|
obj->direction = PIN_OUTPUT;
|
||||||
|
obj->mode = PushPullOutput;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Allow for configuring other I/O modes directly */
|
||||||
|
obj->mode = mode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_mode(obj->pin, obj->mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_dir(gpio_t *obj, PinDirection direction)
|
void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||||
|
@ -68,24 +108,35 @@ void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
|
obj->direction = direction;
|
||||||
uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
|
|
||||||
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
|
||||||
|
|
||||||
uint32_t mode_intern = GPIO_MODE_INPUT;
|
switch (obj->mode) {
|
||||||
|
case PullNone:
|
||||||
switch (direction) {
|
case PullDown:
|
||||||
case PIN_INPUT:
|
case PullUp:
|
||||||
mode_intern = GPIO_MODE_INPUT;
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
|
* We translate to input-only/push-pull output I/O mode dependent on direction. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PIN_OUTPUT:
|
case QuasiBidirectional:
|
||||||
mode_intern = GPIO_MODE_OUTPUT;
|
/* With quasi-bidirectional I/O mode, before digital input function is performed,
|
||||||
|
* the corresponding bit in GPIOx_DOUT must be set to 1. */
|
||||||
|
if (obj->direction == PIN_INPUT) {
|
||||||
|
gpio_write(obj, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InputOnly:
|
||||||
|
case PushPullOutput:
|
||||||
|
/* We may meet contradictory I/O mode/direction configuration. Favor direction
|
||||||
|
* in the gpio_dir call here. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
pin_mode(obj->pin, obj->mode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,10 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PinName pin;
|
PinName pin;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
|
PinDirection direction;
|
||||||
|
PinMode mode;
|
||||||
} gpio_t;
|
} gpio_t;
|
||||||
|
|
||||||
static inline void gpio_write(gpio_t *obj, int value)
|
static inline void gpio_write(gpio_t *obj, int value)
|
||||||
|
|
|
@ -57,16 +57,11 @@ void pin_mode(PinName pin, PinMode mode)
|
||||||
uint32_t mode_intern = GPIO_MODE_INPUT;
|
uint32_t mode_intern = GPIO_MODE_INPUT;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case PullUp:
|
case InputOnly:
|
||||||
mode_intern = GPIO_MODE_INPUT;
|
mode_intern = GPIO_MODE_INPUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PullDown:
|
case PushPullOutput:
|
||||||
case PullNone:
|
|
||||||
// NOTE: Not support
|
|
||||||
return;
|
|
||||||
|
|
||||||
case PushPull:
|
|
||||||
mode_intern = GPIO_MODE_OUTPUT;
|
mode_intern = GPIO_MODE_OUTPUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -74,10 +69,24 @@ void pin_mode(PinName pin, PinMode mode)
|
||||||
mode_intern = GPIO_MODE_OPEN_DRAIN;
|
mode_intern = GPIO_MODE_OPEN_DRAIN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Quasi:
|
case QuasiBidirectional:
|
||||||
mode_intern = GPIO_MODE_QUASI;
|
mode_intern = GPIO_MODE_QUASI;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
|
* We expect upper layer would have translated input pull mode/direction
|
||||||
|
* to I/O mode */
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
||||||
|
|
||||||
|
/* Invalid combinations of PinMode/PinDirection
|
||||||
|
*
|
||||||
|
* We assume developer would avoid the following combinations of PinMode/PinDirection
|
||||||
|
* which are invalid:
|
||||||
|
* 1. InputOnly/PIN_OUTPUT
|
||||||
|
* 2. PushPullOutput/PIN_INPUT
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,15 +55,19 @@ typedef enum {
|
||||||
} PinDirection;
|
} PinDirection;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
/* Input pull mode */
|
||||||
PullNone = 0,
|
PullNone = 0,
|
||||||
PullDown,
|
PullDown,
|
||||||
PullUp,
|
PullUp,
|
||||||
|
|
||||||
PushPull,
|
/* I/O mode */
|
||||||
|
InputOnly,
|
||||||
|
PushPullOutput,
|
||||||
OpenDrain,
|
OpenDrain,
|
||||||
Quasi,
|
QuasiBidirectional,
|
||||||
|
|
||||||
PullDefault = PullUp,
|
/* Default input pull mode */
|
||||||
|
PullDefault = PullUp
|
||||||
} PinMode;
|
} PinMode;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -51,6 +51,9 @@ void gpio_init(gpio_t *obj, PinName pin)
|
||||||
}
|
}
|
||||||
|
|
||||||
obj->mask = gpio_set(pin);
|
obj->mask = gpio_set(pin);
|
||||||
|
/* Default mode/direction */
|
||||||
|
obj->mode = PullUp;
|
||||||
|
obj->direction = PIN_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||||
|
@ -59,7 +62,44 @@ void gpio_mode(gpio_t *obj, PinMode mode)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pin_mode(obj->pin, mode);
|
switch (mode) {
|
||||||
|
case PullNone:
|
||||||
|
case PullDown:
|
||||||
|
case PullUp:
|
||||||
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
|
* We translate to input-only/push-pull output I/O mode dependent on direction. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QuasiBidirectional:
|
||||||
|
/* With quasi-bidirectional I/O mode, before digital input function is performed,
|
||||||
|
* the corresponding bit in GPIOx_DOUT must be set to 1. */
|
||||||
|
obj->mode = QuasiBidirectional;
|
||||||
|
if (obj->direction == PIN_INPUT) {
|
||||||
|
gpio_write(obj, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InputOnly:
|
||||||
|
case PushPullOutput:
|
||||||
|
/* We may meet contradictory I/O mode/direction configuration. Favor I/O mode
|
||||||
|
* in the gpio_mode call here. */
|
||||||
|
if (mode == InputOnly) {
|
||||||
|
obj->direction = PIN_INPUT;
|
||||||
|
obj->mode = InputOnly;
|
||||||
|
} else {
|
||||||
|
obj->direction = PIN_OUTPUT;
|
||||||
|
obj->mode = PushPullOutput;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Allow for configuring other I/O modes directly */
|
||||||
|
obj->mode = mode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_mode(obj->pin, obj->mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_dir(gpio_t *obj, PinDirection direction)
|
void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||||
|
@ -68,24 +108,35 @@ void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
|
obj->direction = direction;
|
||||||
uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
|
|
||||||
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
|
||||||
|
|
||||||
uint32_t mode_intern = GPIO_MODE_INPUT;
|
switch (obj->mode) {
|
||||||
|
case PullNone:
|
||||||
|
case PullDown:
|
||||||
|
case PullUp:
|
||||||
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
|
* We translate to input-only/push-pull output I/O mode dependent on direction. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
|
break;
|
||||||
|
|
||||||
switch (direction) {
|
case QuasiBidirectional:
|
||||||
case PIN_INPUT:
|
/* With quasi-bidirectional I/O mode, before digital input function is performed,
|
||||||
mode_intern = GPIO_MODE_INPUT;
|
* the corresponding bit in GPIOx_DOUT must be set to 1. */
|
||||||
break;
|
if (obj->direction == PIN_INPUT) {
|
||||||
|
gpio_write(obj, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case PIN_OUTPUT:
|
case InputOnly:
|
||||||
mode_intern = GPIO_MODE_OUTPUT;
|
case PushPullOutput:
|
||||||
break;
|
/* We may meet contradictory I/O mode/direction configuration. Favor direction
|
||||||
|
* in the gpio_dir call here. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
pin_mode(obj->pin, obj->mode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,10 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PinName pin;
|
PinName pin;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
|
PinDirection direction;
|
||||||
|
PinMode mode;
|
||||||
} gpio_t;
|
} gpio_t;
|
||||||
|
|
||||||
static inline void gpio_write(gpio_t *obj, int value)
|
static inline void gpio_write(gpio_t *obj, int value)
|
||||||
|
|
|
@ -47,27 +47,36 @@ void pin_mode(PinName pin, PinMode mode)
|
||||||
uint32_t mode_intern = GPIO_MODE_INPUT;
|
uint32_t mode_intern = GPIO_MODE_INPUT;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case PullUp:
|
case InputOnly:
|
||||||
mode_intern = GPIO_MODE_INPUT;
|
mode_intern = GPIO_MODE_INPUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PullDown:
|
case PushPullOutput:
|
||||||
case PullNone:
|
mode_intern = GPIO_MODE_OUTPUT;
|
||||||
// NOTE: Not support
|
break;
|
||||||
return;
|
|
||||||
|
|
||||||
case PushPull:
|
case OpenDrain:
|
||||||
mode_intern = GPIO_MODE_OUTPUT;
|
mode_intern = GPIO_MODE_OPEN_DRAIN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OpenDrain:
|
case QuasiBidirectional:
|
||||||
mode_intern = GPIO_MODE_OPEN_DRAIN;
|
mode_intern = GPIO_MODE_QUASI;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Quasi:
|
default:
|
||||||
mode_intern = GPIO_MODE_QUASI;
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
break;
|
* We expect upper layer would have translated input pull mode/direction
|
||||||
|
* to I/O mode */
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
||||||
|
|
||||||
|
/* Invalid combinations of PinMode/PinDirection
|
||||||
|
*
|
||||||
|
* We assume developer would avoid the following combinations of PinMode/PinDirection
|
||||||
|
* which are invalid:
|
||||||
|
* 1. InputOnly/PIN_OUTPUT
|
||||||
|
* 2. PushPullOutput/PIN_INPUT
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,15 +55,18 @@ typedef enum {
|
||||||
} PinDirection;
|
} PinDirection;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
/* Input pull mode */
|
||||||
PullNone = 0,
|
PullNone = 0,
|
||||||
PullDown,
|
PullDown,
|
||||||
PullUp,
|
PullUp,
|
||||||
|
|
||||||
PushPull,
|
/* I/O mode */
|
||||||
|
InputOnly,
|
||||||
|
PushPullOutput,
|
||||||
OpenDrain,
|
OpenDrain,
|
||||||
Quasi,
|
|
||||||
|
|
||||||
PullDefault = PullUp,
|
/* Default input pull mode */
|
||||||
|
PullDefault = PullUp
|
||||||
} PinMode;
|
} PinMode;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -48,6 +48,9 @@ void gpio_init(gpio_t *obj, PinName pin)
|
||||||
}
|
}
|
||||||
|
|
||||||
obj->mask = gpio_set(pin);
|
obj->mask = gpio_set(pin);
|
||||||
|
/* Default mode/direction */
|
||||||
|
obj->mode = PullUp;
|
||||||
|
obj->direction = PIN_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||||
|
@ -56,7 +59,36 @@ void gpio_mode(gpio_t *obj, PinMode mode)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pin_mode(obj->pin, mode);
|
switch (mode) {
|
||||||
|
case PullNone:
|
||||||
|
case PullDown:
|
||||||
|
case PullUp:
|
||||||
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
|
* We translate to input-only/push-pull output I/O mode dependent on direction. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case InputOnly:
|
||||||
|
case PushPullOutput:
|
||||||
|
/* We may meet contradictory I/O mode/direction configuration. Favor I/O mode
|
||||||
|
* in the gpio_mode call here. */
|
||||||
|
if (mode == InputOnly) {
|
||||||
|
obj->direction = PIN_INPUT;
|
||||||
|
obj->mode = InputOnly;
|
||||||
|
} else {
|
||||||
|
obj->direction = PIN_OUTPUT;
|
||||||
|
obj->mode = PushPullOutput;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Allow for configuring other I/O modes directly */
|
||||||
|
obj->mode = mode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_mode(obj->pin, obj->mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_dir(gpio_t *obj, PinDirection direction)
|
void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||||
|
@ -65,24 +97,27 @@ void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
|
obj->direction = direction;
|
||||||
uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
|
|
||||||
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
|
||||||
|
|
||||||
uint32_t mode_intern = GPIO_PMD_INPUT;
|
switch (obj->mode) {
|
||||||
|
case PullNone:
|
||||||
switch (direction) {
|
case PullDown:
|
||||||
case PIN_INPUT:
|
case PullUp:
|
||||||
mode_intern = GPIO_PMD_INPUT;
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
|
* We translate to input-only/push-pull output I/O mode dependent on direction. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PIN_OUTPUT:
|
case InputOnly:
|
||||||
mode_intern = GPIO_PMD_OUTPUT;
|
case PushPullOutput:
|
||||||
|
/* We may meet contradictory I/O mode/direction configuration. Favor direction
|
||||||
|
* in the gpio_dir call here. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
pin_mode(obj->pin, obj->mode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,10 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PinName pin;
|
PinName pin;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
|
PinDirection direction;
|
||||||
|
PinMode mode;
|
||||||
} gpio_t;
|
} gpio_t;
|
||||||
|
|
||||||
static inline void gpio_write(gpio_t *obj, int value)
|
static inline void gpio_write(gpio_t *obj, int value)
|
||||||
|
|
|
@ -44,19 +44,14 @@ void pin_mode(PinName pin, PinMode mode)
|
||||||
uint32_t port_index = NU_PINNAME_TO_PORT(pin);
|
uint32_t port_index = NU_PINNAME_TO_PORT(pin);
|
||||||
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
||||||
|
|
||||||
uint32_t mode_intern = GPIO_PMD_INPUT;
|
uint32_t mode_intern;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case PullUp:
|
case InputOnly:
|
||||||
mode_intern = GPIO_PMD_INPUT;
|
mode_intern = GPIO_PMD_INPUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PullDown:
|
case PushPullOutput:
|
||||||
case PullNone:
|
|
||||||
// NOTE: Not support
|
|
||||||
return;
|
|
||||||
|
|
||||||
case PushPull:
|
|
||||||
mode_intern = GPIO_PMD_OUTPUT;
|
mode_intern = GPIO_PMD_OUTPUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -64,10 +59,20 @@ void pin_mode(PinName pin, PinMode mode)
|
||||||
mode_intern = GPIO_PMD_OPEN_DRAIN;
|
mode_intern = GPIO_PMD_OPEN_DRAIN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Quasi:
|
default:
|
||||||
// NOTE: Not support
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
break;
|
* We expect upper layer would have translated input pull mode/direction
|
||||||
|
* to I/O mode */
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
||||||
|
|
||||||
|
/* Invalid combinations of PinMode/PinDirection
|
||||||
|
*
|
||||||
|
* We assume developer would avoid the following combinations of PinMode/PinDirection
|
||||||
|
* which are invalid:
|
||||||
|
* 1. InputOnly/PIN_OUTPUT
|
||||||
|
* 2. PushPullOutput/PIN_INPUT
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,15 +55,19 @@ typedef enum {
|
||||||
} PinDirection;
|
} PinDirection;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
/* Input pull mode */
|
||||||
PullNone = 0,
|
PullNone = 0,
|
||||||
PullDown,
|
PullDown,
|
||||||
PullUp,
|
PullUp,
|
||||||
|
|
||||||
PushPull,
|
/* I/O mode */
|
||||||
|
InputOnly,
|
||||||
|
PushPullOutput,
|
||||||
OpenDrain,
|
OpenDrain,
|
||||||
Quasi,
|
QuasiBidirectional,
|
||||||
|
|
||||||
PullDefault = PullUp,
|
/* Default input pull mode */
|
||||||
|
PullDefault = PullUp
|
||||||
} PinMode;
|
} PinMode;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -51,6 +51,9 @@ void gpio_init(gpio_t *obj, PinName pin)
|
||||||
}
|
}
|
||||||
|
|
||||||
obj->mask = gpio_set(pin);
|
obj->mask = gpio_set(pin);
|
||||||
|
/* Default mode/direction */
|
||||||
|
obj->mode = PullUp;
|
||||||
|
obj->direction = PIN_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||||
|
@ -59,7 +62,44 @@ void gpio_mode(gpio_t *obj, PinMode mode)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pin_mode(obj->pin, mode);
|
switch (mode) {
|
||||||
|
case PullNone:
|
||||||
|
case PullDown:
|
||||||
|
case PullUp:
|
||||||
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
|
* We translate to input-only/push-pull output I/O mode dependent on direction. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QuasiBidirectional:
|
||||||
|
/* With quasi-bidirectional I/O mode, before digital input function is performed,
|
||||||
|
* the corresponding bit in GPIOx_DOUT must be set to 1. */
|
||||||
|
obj->mode = QuasiBidirectional;
|
||||||
|
if (obj->direction == PIN_INPUT) {
|
||||||
|
gpio_write(obj, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InputOnly:
|
||||||
|
case PushPullOutput:
|
||||||
|
/* We may meet contradictory I/O mode/direction configuration. Favor I/O mode
|
||||||
|
* in the gpio_mode call here. */
|
||||||
|
if (mode == InputOnly) {
|
||||||
|
obj->direction = PIN_INPUT;
|
||||||
|
obj->mode = InputOnly;
|
||||||
|
} else {
|
||||||
|
obj->direction = PIN_OUTPUT;
|
||||||
|
obj->mode = PushPullOutput;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Allow for configuring other I/O modes directly */
|
||||||
|
obj->mode = mode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_mode(obj->pin, obj->mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_dir(gpio_t *obj, PinDirection direction)
|
void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||||
|
@ -68,24 +108,35 @@ void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
|
obj->direction = direction;
|
||||||
uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
|
|
||||||
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
|
||||||
|
|
||||||
uint32_t mode_intern = GPIO_MODE_INPUT;
|
switch (obj->mode) {
|
||||||
|
case PullNone:
|
||||||
switch (direction) {
|
case PullDown:
|
||||||
case PIN_INPUT:
|
case PullUp:
|
||||||
mode_intern = GPIO_MODE_INPUT;
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
|
* We translate to input-only/push-pull output I/O mode dependent on direction. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PIN_OUTPUT:
|
case QuasiBidirectional:
|
||||||
mode_intern = GPIO_MODE_OUTPUT;
|
/* With quasi-bidirectional I/O mode, before digital input function is performed,
|
||||||
|
* the corresponding bit in GPIOx_DOUT must be set to 1. */
|
||||||
|
if (obj->direction == PIN_INPUT) {
|
||||||
|
gpio_write(obj, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InputOnly:
|
||||||
|
case PushPullOutput:
|
||||||
|
/* We may meet contradictory I/O mode/direction configuration. Favor direction
|
||||||
|
* in the gpio_dir call here. */
|
||||||
|
obj->mode = (obj->direction == PIN_INPUT) ? InputOnly : PushPullOutput;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
pin_mode(obj->pin, obj->mode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,10 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PinName pin;
|
PinName pin;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
|
PinDirection direction;
|
||||||
|
PinMode mode;
|
||||||
} gpio_t;
|
} gpio_t;
|
||||||
|
|
||||||
static inline void gpio_write(gpio_t *obj, int value)
|
static inline void gpio_write(gpio_t *obj, int value)
|
||||||
|
|
|
@ -54,19 +54,14 @@ void pin_mode(PinName pin, PinMode mode)
|
||||||
uint32_t port_index = NU_PINNAME_TO_PORT(pin);
|
uint32_t port_index = NU_PINNAME_TO_PORT(pin);
|
||||||
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
||||||
|
|
||||||
uint32_t mode_intern = GPIO_MODE_INPUT;
|
uint32_t mode_intern;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case PullUp:
|
case InputOnly:
|
||||||
mode_intern = GPIO_MODE_INPUT;
|
mode_intern = GPIO_MODE_INPUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PullDown:
|
case PushPullOutput:
|
||||||
case PullNone:
|
|
||||||
// NOTE: Not support
|
|
||||||
return;
|
|
||||||
|
|
||||||
case PushPull:
|
|
||||||
mode_intern = GPIO_MODE_OUTPUT;
|
mode_intern = GPIO_MODE_OUTPUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -74,10 +69,24 @@ void pin_mode(PinName pin, PinMode mode)
|
||||||
mode_intern = GPIO_MODE_OPEN_DRAIN;
|
mode_intern = GPIO_MODE_OPEN_DRAIN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Quasi:
|
case QuasiBidirectional:
|
||||||
mode_intern = GPIO_MODE_QUASI;
|
mode_intern = GPIO_MODE_QUASI;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* H/W doesn't support separate configuration for input pull mode/direction.
|
||||||
|
* We expect upper layer would have translated input pull mode/direction
|
||||||
|
* to I/O mode */
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
||||||
|
|
||||||
|
/* Invalid combinations of PinMode/PinDirection
|
||||||
|
*
|
||||||
|
* We assume developer would avoid the following combinations of PinMode/PinDirection
|
||||||
|
* which are invalid:
|
||||||
|
* 1. InputOnly/PIN_OUTPUT
|
||||||
|
* 2. PushPullOutput/PIN_INPUT
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue