]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blobdiff - rpp/src/rpp/gio.c
Make the RPP layer thread safe
[pes-rpp/rpp-lib.git] / rpp / src / rpp / gio.c
index 81bac3d7cc3c3b8fa40e99113f2d24b7ae05e884..8c83c484e1462e28a28ab6328c6e3d2d93fea238 100644 (file)
@@ -1,42 +1,88 @@
-/*
- * gio.c
+/* Copyright (C) 2013-2015 Czech Technical University in Prague
+ * Authors:
+ *     - Michal Horn <hornmich@fel.cvut.cz>
+ *     - Michal Sojka <sojkam1@fel.cvut.cz>
+ *
+ * This document contains proprietary information belonging to Czech
+ * Technical University in Prague. Passing on and copying of this
+ * document, and communication of its contents is not permitted
+ * without prior written authorization.
  *
- *  Created on: 29.10.2014
- *      Author: Michal Horn
  */
 
+#include "base.h"
 #include "rpp/gio.h"
+#include "drv/gio_tab.h"
+#include "rpp/mutex.h"
+
+RPP_MUTEX_DEFINE(mutex_gio);
+
+static uint32_t ports_initialized = 0;
 
-static boolean_t gioa_initialized = FALSE;
-static boolean_t giob_initialized = FALSE;
-static boolean_t nhet_initialized = FALSE;
+/* Configuration consistency check */
+STATIC_ASSERT(RPP_GIO_PORT_GIOA == (1 << GIO_PORT_GIOA) &&
+                         RPP_GIO_PORT_GIOB == (1 << GIO_PORT_GIOB) &&
+                         RPP_GIO_PORT_NHET1 == (1 << GIO_PORT_HET1),
+                         Port_configuration_is_not_consistent);
 
-int8_t rpp_gio_init(uint32_t ports)
+int8_t rpp_gio_init(uint32_t init_ports)
 {
-       uint8_t pin = 0;
-
-       if (ports & RPP_GIO_PORT_GIOA && !gioa_initialized) {
-               gioREG->GCR0 = 1;   // Bring GIO out of reset
-               for (pin = PIN_MAP_GIOA_BEGIN; pin <= PIN_MAP_GIOA_END; pin++) {
-                       hal_gpio_pin_conf(pin_map[pin].pin_desc);
-               }
-               gioa_initialized = TRUE;
-       }
+       enum pin_name pin;
+       if (!RPP_MUTEX_INIT(mutex_gio))
+               return FAILURE;
 
-       if (ports & RPP_GIO_PORT_GIOB && !giob_initialized) {
-               gioREG->GCR0 = 1;   // Bring GIO out of reset
-               for (pin = PIN_MAP_GIOB_BEGIN; pin <= PIN_MAP_GIOB_END; pin++) {
-                       hal_gpio_pin_conf(pin_map[pin].pin_desc);
-               }
-               giob_initialized = TRUE;
-       }
+       gioREG->GCR0 = 1;   // Bring GIO out of reset
 
-       if (ports & RPP_GIO_PORT_NHET1 && nhet_initialized) {
-               for (pin = PIN_MAP_HET1_BEGIN; pin <= PIN_MAP_HET1_END; pin++) {
-                       hal_gpio_pin_conf(pin_map[pin].pin_desc);
-               }
-               nhet_initialized = TRUE;
+       for (pin = (enum pin_name)0; pin < _PIN_COUNT; pin++) {
+               int port_num = gio_port(gio_table[pin].pin_dsc);
+               if ((init_ports & (1 << port_num)) &&
+                       !(ports_initialized & (1 << port_num)))
+                       gio_setup(gio_table[pin].pin_dsc);
        }
 
+       ports_initialized |= init_ports;
+
+       return SUCCESS;
+}
+
+int8_t rpp_gio_set(enum pin_name pin, boolean_t value)
+{
+       if (ports_initialized == 0 || pin >= _PIN_COUNT || pin < 0)
+               return FAILURE;
+
+       gio_tab_set(pin, value);        /* Thread safe */
+       return SUCCESS;
+}
+
+int8_t rpp_gio_get(enum pin_name pin)
+{
+       if (ports_initialized == 0 || pin >= _PIN_COUNT || pin < 0)
+               return FAILURE;
+
+       boolean_t ret_val = gio_tab_get(pin) ? 1 : 0; /* Thread safe */
+
+       return ret_val;
+}
+
+int8_t rpp_gio_setup(enum pin_name pin, enum rpp_gio_io io, enum rpp_gio_in_mode in_mode,
+                                        boolean_t open_drain)
+{
+       if (ports_initialized == 0 || pin >= _PIN_COUNT || pin < 0)
+               return FAILURE;
+
+       uint32_t mode_flags[] = {
+               [RPP_GIO_MODE_PULLDIS]  = GIO_PIN_CONF_MODE_PDIS,
+               [RPP_GIO_MODE_PULLUP]   = GIO_PIN_CONF_MODE_PU | GIO_PIN_CONF_MODE_PEN,
+               [RPP_GIO_MODE_PULLDOWN] = GIO_PIN_CONF_MODE_PD | GIO_PIN_CONF_MODE_PEN,
+       };
+       uint32_t dsc = gio_table[pin].pin_dsc & ~GIO_PIN_CONF_MASK;
+       dsc |= (io == RPP_GIO_OUT) ? GIO_PIN_CONF_DIR_OUT : GIO_PIN_CONF_DIR_IN;
+       dsc |= mode_flags[in_mode];
+       dsc |= open_drain ? GIO_PIN_CONF_OD_ON : GIO_PIN_CONF_OD_OFF;
+
+       RPP_MUTEX_LOCK(mutex_gio);
+       gio_setup(dsc);
+       RPP_MUTEX_UNLOCK(mutex_gio);
+
        return SUCCESS;
 }