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;
|
||||
|
||||
typedef enum {
|
||||
/* Input pull mode */
|
||||
PullNone = 0,
|
||||
PullDown,
|
||||
PullUp,
|
||||
|
||||
PushPull,
|
||||
/* I/O mode */
|
||||
InputOnly,
|
||||
PushPullOutput,
|
||||
OpenDrain,
|
||||
Quasi,
|
||||
QuasiBidirectional,
|
||||
|
||||
PullDefault = PullUp,
|
||||
/* Default input pull mode */
|
||||
PullDefault = PullUp
|
||||
} PinMode;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -51,6 +51,9 @@ void gpio_init(gpio_t *obj, PinName pin)
|
|||
}
|
||||
|
||||
obj->mask = gpio_set(pin);
|
||||
/* Default mode/direction */
|
||||
obj->mode = PullUp;
|
||||
obj->direction = PIN_INPUT;
|
||||
}
|
||||
|
||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||
|
@ -58,8 +61,45 @@ void gpio_mode(gpio_t *obj, PinMode mode)
|
|||
if (obj->pin == (PinName) NC) {
|
||||
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)
|
||||
|
@ -67,25 +107,36 @@ void gpio_dir(gpio_t *obj, PinDirection direction)
|
|||
if (obj->pin == (PinName) NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
|
||||
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 (direction) {
|
||||
case PIN_INPUT:
|
||||
mode_intern = GPIO_MODE_INPUT;
|
||||
break;
|
||||
|
||||
case PIN_OUTPUT:
|
||||
mode_intern = GPIO_MODE_OUTPUT;
|
||||
|
||||
obj->direction = direction;
|
||||
|
||||
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;
|
||||
|
||||
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. */
|
||||
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;
|
||||
|
||||
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
|
||||
|
||||
typedef struct {
|
||||
PinName pin;
|
||||
uint32_t mask;
|
||||
PinName pin;
|
||||
uint32_t mask;
|
||||
PinDirection direction;
|
||||
PinMode mode;
|
||||
} gpio_t;
|
||||
|
||||
static inline void gpio_write(gpio_t *obj, int value)
|
||||
|
|
|
@ -41,31 +41,40 @@ void pin_mode(PinName pin, PinMode mode)
|
|||
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
||||
|
||||
uint32_t mode_intern = GPIO_MODE_INPUT;
|
||||
|
||||
|
||||
switch (mode) {
|
||||
case PullUp:
|
||||
case InputOnly:
|
||||
mode_intern = GPIO_MODE_INPUT;
|
||||
break;
|
||||
|
||||
case PullDown:
|
||||
case PullNone:
|
||||
// NOTE: Not support
|
||||
return;
|
||||
|
||||
case PushPull:
|
||||
|
||||
case PushPullOutput:
|
||||
mode_intern = GPIO_MODE_OUTPUT;
|
||||
break;
|
||||
|
||||
|
||||
case OpenDrain:
|
||||
mode_intern = GPIO_MODE_OPEN_DRAIN;
|
||||
break;
|
||||
|
||||
case Quasi:
|
||||
|
||||
case QuasiBidirectional:
|
||||
mode_intern = GPIO_MODE_QUASI;
|
||||
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);
|
||||
|
||||
/* 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)
|
||||
|
|
|
@ -55,15 +55,19 @@ typedef enum {
|
|||
} PinDirection;
|
||||
|
||||
typedef enum {
|
||||
/* Input pull mode */
|
||||
PullNone = 0,
|
||||
PullDown,
|
||||
PullUp,
|
||||
|
||||
PushPull,
|
||||
/* I/O mode */
|
||||
InputOnly,
|
||||
PushPullOutput,
|
||||
OpenDrain,
|
||||
Quasi,
|
||||
QuasiBidirectional,
|
||||
|
||||
PullDefault = PullUp,
|
||||
/* Default input pull mode */
|
||||
PullDefault = PullUp
|
||||
} PinMode;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -51,6 +51,9 @@ void gpio_init(gpio_t *obj, PinName pin)
|
|||
}
|
||||
|
||||
obj->mask = gpio_set(pin);
|
||||
/* Default mode/direction */
|
||||
obj->mode = PullUp;
|
||||
obj->direction = PIN_INPUT;
|
||||
}
|
||||
|
||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||
|
@ -58,8 +61,45 @@ void gpio_mode(gpio_t *obj, PinMode mode)
|
|||
if (obj->pin == (PinName) NC) {
|
||||
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)
|
||||
|
@ -67,25 +107,36 @@ void gpio_dir(gpio_t *obj, PinDirection direction)
|
|||
if (obj->pin == (PinName) NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
|
||||
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 (direction) {
|
||||
case PIN_INPUT:
|
||||
mode_intern = GPIO_MODE_INPUT;
|
||||
break;
|
||||
|
||||
case PIN_OUTPUT:
|
||||
mode_intern = GPIO_MODE_OUTPUT;
|
||||
|
||||
obj->direction = direction;
|
||||
|
||||
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;
|
||||
|
||||
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. */
|
||||
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;
|
||||
|
||||
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
|
||||
|
||||
typedef struct {
|
||||
PinName pin;
|
||||
uint32_t mask;
|
||||
PinName pin;
|
||||
uint32_t mask;
|
||||
PinDirection direction;
|
||||
PinMode mode;
|
||||
} gpio_t;
|
||||
|
||||
static inline void gpio_write(gpio_t *obj, int value)
|
||||
|
|
|
@ -55,29 +55,38 @@ void pin_mode(PinName pin, PinMode mode)
|
|||
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
||||
|
||||
uint32_t mode_intern = GPIO_MODE_INPUT;
|
||||
|
||||
|
||||
switch (mode) {
|
||||
case PullUp:
|
||||
case InputOnly:
|
||||
mode_intern = GPIO_MODE_INPUT;
|
||||
break;
|
||||
|
||||
case PullDown:
|
||||
case PullNone:
|
||||
// NOTE: Not support
|
||||
return;
|
||||
|
||||
case PushPull:
|
||||
|
||||
case PushPullOutput:
|
||||
mode_intern = GPIO_MODE_OUTPUT;
|
||||
break;
|
||||
|
||||
|
||||
case OpenDrain:
|
||||
mode_intern = GPIO_MODE_OPEN_DRAIN;
|
||||
break;
|
||||
|
||||
case Quasi:
|
||||
|
||||
case QuasiBidirectional:
|
||||
mode_intern = GPIO_MODE_QUASI;
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
|
||||
typedef enum {
|
||||
/* Input pull mode */
|
||||
PullNone = 0,
|
||||
PullDown,
|
||||
PullUp,
|
||||
|
||||
PushPull,
|
||||
/* I/O mode */
|
||||
InputOnly,
|
||||
PushPullOutput,
|
||||
OpenDrain,
|
||||
Quasi,
|
||||
QuasiBidirectional,
|
||||
|
||||
PullDefault = PullUp,
|
||||
/* Default input pull mode */
|
||||
PullDefault = PullUp
|
||||
} PinMode;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -51,6 +51,9 @@ void gpio_init(gpio_t *obj, PinName pin)
|
|||
}
|
||||
|
||||
obj->mask = gpio_set(pin);
|
||||
/* Default mode/direction */
|
||||
obj->mode = PullUp;
|
||||
obj->direction = PIN_INPUT;
|
||||
}
|
||||
|
||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||
|
@ -59,7 +62,44 @@ void gpio_mode(gpio_t *obj, PinMode mode)
|
|||
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)
|
||||
|
@ -68,24 +108,35 @@ void gpio_dir(gpio_t *obj, PinDirection direction)
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
|
||||
uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
|
||||
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
||||
obj->direction = direction;
|
||||
|
||||
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;
|
||||
|
||||
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. */
|
||||
if (obj->direction == PIN_INPUT) {
|
||||
gpio_write(obj, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
switch (direction) {
|
||||
case PIN_INPUT:
|
||||
mode_intern = GPIO_MODE_INPUT;
|
||||
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;
|
||||
|
||||
case PIN_OUTPUT:
|
||||
mode_intern = GPIO_MODE_OUTPUT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern);
|
||||
pin_mode(obj->pin, obj->mode);
|
||||
}
|
||||
|
|
|
@ -28,8 +28,10 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
typedef struct {
|
||||
PinName pin;
|
||||
uint32_t mask;
|
||||
PinName pin;
|
||||
uint32_t mask;
|
||||
PinDirection direction;
|
||||
PinMode mode;
|
||||
} gpio_t;
|
||||
|
||||
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;
|
||||
|
||||
switch (mode) {
|
||||
case PullUp:
|
||||
mode_intern = GPIO_MODE_INPUT;
|
||||
break;
|
||||
case InputOnly:
|
||||
mode_intern = GPIO_MODE_INPUT;
|
||||
break;
|
||||
|
||||
case PullDown:
|
||||
case PullNone:
|
||||
// NOTE: Not support
|
||||
return;
|
||||
case PushPullOutput:
|
||||
mode_intern = GPIO_MODE_OUTPUT;
|
||||
break;
|
||||
|
||||
case PushPull:
|
||||
mode_intern = GPIO_MODE_OUTPUT;
|
||||
break;
|
||||
case OpenDrain:
|
||||
mode_intern = GPIO_MODE_OPEN_DRAIN;
|
||||
break;
|
||||
|
||||
case OpenDrain:
|
||||
mode_intern = GPIO_MODE_OPEN_DRAIN;
|
||||
break;
|
||||
case QuasiBidirectional:
|
||||
mode_intern = GPIO_MODE_QUASI;
|
||||
break;
|
||||
|
||||
case Quasi:
|
||||
mode_intern = GPIO_MODE_QUASI;
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
|
||||
typedef enum {
|
||||
/* Input pull mode */
|
||||
PullNone = 0,
|
||||
PullDown,
|
||||
PullUp,
|
||||
|
||||
PushPull,
|
||||
/* I/O mode */
|
||||
InputOnly,
|
||||
PushPullOutput,
|
||||
OpenDrain,
|
||||
Quasi,
|
||||
|
||||
PullDefault = PullUp,
|
||||
/* Default input pull mode */
|
||||
PullDefault = PullUp
|
||||
} PinMode;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -48,6 +48,9 @@ void gpio_init(gpio_t *obj, PinName pin)
|
|||
}
|
||||
|
||||
obj->mask = gpio_set(pin);
|
||||
/* Default mode/direction */
|
||||
obj->mode = PullUp;
|
||||
obj->direction = PIN_INPUT;
|
||||
}
|
||||
|
||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||
|
@ -55,8 +58,37 @@ void gpio_mode(gpio_t *obj, PinMode mode)
|
|||
if (obj->pin == (PinName) NC) {
|
||||
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)
|
||||
|
@ -64,25 +96,28 @@ void gpio_dir(gpio_t *obj, PinDirection direction)
|
|||
if (obj->pin == (PinName) NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
|
||||
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 (direction) {
|
||||
case PIN_INPUT:
|
||||
mode_intern = GPIO_PMD_INPUT;
|
||||
|
||||
obj->direction = direction;
|
||||
|
||||
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;
|
||||
|
||||
case PIN_OUTPUT:
|
||||
mode_intern = GPIO_PMD_OUTPUT;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
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
|
||||
|
||||
typedef struct {
|
||||
PinName pin;
|
||||
uint32_t mask;
|
||||
PinName pin;
|
||||
uint32_t mask;
|
||||
PinDirection direction;
|
||||
PinMode mode;
|
||||
} gpio_t;
|
||||
|
||||
static inline void gpio_write(gpio_t *obj, int value)
|
||||
|
|
|
@ -44,30 +44,35 @@ void pin_mode(PinName pin, PinMode mode)
|
|||
uint32_t port_index = NU_PINNAME_TO_PORT(pin);
|
||||
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
||||
|
||||
uint32_t mode_intern = GPIO_PMD_INPUT;
|
||||
|
||||
uint32_t mode_intern;
|
||||
|
||||
switch (mode) {
|
||||
case PullUp:
|
||||
case InputOnly:
|
||||
mode_intern = GPIO_PMD_INPUT;
|
||||
break;
|
||||
|
||||
case PullDown:
|
||||
case PullNone:
|
||||
// NOTE: Not support
|
||||
return;
|
||||
|
||||
case PushPull:
|
||||
|
||||
case PushPullOutput:
|
||||
mode_intern = GPIO_PMD_OUTPUT;
|
||||
break;
|
||||
|
||||
|
||||
case OpenDrain:
|
||||
mode_intern = GPIO_PMD_OPEN_DRAIN;
|
||||
break;
|
||||
|
||||
case Quasi:
|
||||
// NOTE: Not support
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
|
||||
typedef enum {
|
||||
/* Input pull mode */
|
||||
PullNone = 0,
|
||||
PullDown,
|
||||
PullUp,
|
||||
|
||||
PushPull,
|
||||
/* I/O mode */
|
||||
InputOnly,
|
||||
PushPullOutput,
|
||||
OpenDrain,
|
||||
Quasi,
|
||||
QuasiBidirectional,
|
||||
|
||||
PullDefault = PullUp,
|
||||
/* Default input pull mode */
|
||||
PullDefault = PullUp
|
||||
} PinMode;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -51,6 +51,9 @@ void gpio_init(gpio_t *obj, PinName pin)
|
|||
}
|
||||
|
||||
obj->mask = gpio_set(pin);
|
||||
/* Default mode/direction */
|
||||
obj->mode = PullUp;
|
||||
obj->direction = PIN_INPUT;
|
||||
}
|
||||
|
||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||
|
@ -58,8 +61,45 @@ void gpio_mode(gpio_t *obj, PinMode mode)
|
|||
if (obj->pin == (PinName) NC) {
|
||||
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)
|
||||
|
@ -67,25 +107,36 @@ void gpio_dir(gpio_t *obj, PinDirection direction)
|
|||
if (obj->pin == (PinName) NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
|
||||
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 (direction) {
|
||||
case PIN_INPUT:
|
||||
mode_intern = GPIO_MODE_INPUT;
|
||||
break;
|
||||
|
||||
case PIN_OUTPUT:
|
||||
mode_intern = GPIO_MODE_OUTPUT;
|
||||
|
||||
obj->direction = direction;
|
||||
|
||||
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;
|
||||
|
||||
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. */
|
||||
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;
|
||||
|
||||
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
|
||||
|
||||
typedef struct {
|
||||
PinName pin;
|
||||
uint32_t mask;
|
||||
PinName pin;
|
||||
uint32_t mask;
|
||||
PinDirection direction;
|
||||
PinMode mode;
|
||||
} gpio_t;
|
||||
|
||||
static inline void gpio_write(gpio_t *obj, int value)
|
||||
|
|
|
@ -54,30 +54,39 @@ void pin_mode(PinName pin, PinMode mode)
|
|||
uint32_t port_index = NU_PINNAME_TO_PORT(pin);
|
||||
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
|
||||
|
||||
uint32_t mode_intern = GPIO_MODE_INPUT;
|
||||
|
||||
uint32_t mode_intern;
|
||||
|
||||
switch (mode) {
|
||||
case PullUp:
|
||||
case InputOnly:
|
||||
mode_intern = GPIO_MODE_INPUT;
|
||||
break;
|
||||
|
||||
case PullDown:
|
||||
case PullNone:
|
||||
// NOTE: Not support
|
||||
return;
|
||||
|
||||
case PushPull:
|
||||
|
||||
case PushPullOutput:
|
||||
mode_intern = GPIO_MODE_OUTPUT;
|
||||
break;
|
||||
|
||||
|
||||
case OpenDrain:
|
||||
mode_intern = GPIO_MODE_OPEN_DRAIN;
|
||||
break;
|
||||
|
||||
case Quasi:
|
||||
|
||||
case QuasiBidirectional:
|
||||
mode_intern = GPIO_MODE_QUASI;
|
||||
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);
|
||||
|
||||
/* 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