mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Revision:
188:bcfe06ba3d64
Parent:
181:57724642e740
--- a/targets/TARGET_NUVOTON/TARGET_M451/gpio_api.c	Thu Sep 06 13:40:20 2018 +0100
+++ b/targets/TARGET_NUVOTON/TARGET_M451/gpio_api.c	Thu Nov 08 11:46:34 2018 +0000
@@ -51,6 +51,9 @@
     }
 
     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 @@
     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 @@
     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);
 }