<div dir="ltr">Andre,<div>Thanks for submitting this. I think we need one minor change: </div><div>Could you remove the include and the call to init the mcp23008 driver?</div><div><br></div><div>After your code is in the tree, I will propose a patch to allow execution of application specific driver init functions that can be called from the BSP i2c and SPI driver init functions.</div><div>Thanks,</div><div>Alan</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Dec 10, 2014 at 5:14 AM, Andre Marques <span dir="ltr"><<a href="mailto:andre.lousa.marques@gmail.com" target="_blank">andre.lousa.marques@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This patch addresses gedare's comments regardig coding conventions and a few other issues.<br>
As to Pavel's concerns on the interrupt handling I currently lack the time to address them properly, but when possible I and possibly Alan will have a look at that and on the new I2C framework.<br>
---<br>
 c/src/lib/libbsp/arm/raspberrypi/Makefile.am       |  11 +-<br>
 c/src/lib/libbsp/arm/raspberrypi/<a href="http://configure.ac" target="_blank">configure.ac</a>      |  12 +<br>
 c/src/lib/libbsp/arm/raspberrypi/gpio/gpio.c       | 727 +++++++++++++++++++++<br>
 c/src/lib/libbsp/arm/raspberrypi/i2c/i2c.c         | 480 ++++++++++++++<br>
 c/src/lib/libbsp/arm/raspberrypi/i2c/i2c_init.c    |  84 +++<br>
 c/src/lib/libbsp/arm/raspberrypi/i2c/spi.c         | 608 +++++++++++++++++<br>
 c/src/lib/libbsp/arm/raspberrypi/i2c/spi_init.c    |  85 +++<br>
 c/src/lib/libbsp/arm/raspberrypi/include/gpio.h    | 210 ++++++<br>
 c/src/lib/libbsp/arm/raspberrypi/include/i2c.h     | 183 ++++++<br>
 c/src/lib/libbsp/arm/raspberrypi/include/irq.h     |   6 +-<br>
 .../libbsp/arm/raspberrypi/include/raspberrypi.h   |  79 ++-<br>
 c/src/lib/libbsp/arm/raspberrypi/irq/irq.c         | 103 ++-<br>
 c/src/lib/libbsp/arm/raspberrypi/<a href="http://preinstall.am" target="_blank">preinstall.am</a>     |   8 +<br>
 .../lib/libbsp/arm/raspberrypi/startup/bspstart.c  |  17 +-<br>
 14 files changed, 2591 insertions(+), 22 deletions(-)<br>
 create mode 100644 c/src/lib/libbsp/arm/raspberrypi/gpio/gpio.c<br>
 create mode 100644 c/src/lib/libbsp/arm/raspberrypi/i2c/i2c.c<br>
 create mode 100644 c/src/lib/libbsp/arm/raspberrypi/i2c/i2c_init.c<br>
 create mode 100644 c/src/lib/libbsp/arm/raspberrypi/i2c/spi.c<br>
 create mode 100644 c/src/lib/libbsp/arm/raspberrypi/i2c/spi_init.c<br>
 create mode 100644 c/src/lib/libbsp/arm/raspberrypi/include/gpio.h<br>
 create mode 100644 c/src/lib/libbsp/arm/raspberrypi/include/i2c.h<br>
<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/Makefile.am b/c/src/lib/libbsp/arm/raspberrypi/Makefile.am<br>
index ed134fa..9363bc4 100644<br>
--- a/c/src/lib/libbsp/arm/raspberrypi/Makefile.am<br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/Makefile.am<br>
@@ -44,6 +44,8 @@ include_bsp_HEADERS += include/irq.h<br>
 include_bsp_HEADERS += include/mmu.h<br>
 include_bsp_HEADERS += include/usart.h<br>
 include_bsp_HEADERS += include/raspberrypi.h<br>
+include_bsp_HEADERS += include/gpio.h<br>
+include_bsp_HEADERS += include/i2c.h<br>
<br>
 include_libcpu_HEADERS = ../../../libcpu/arm/shared/include/cache_.h \<br>
     ../../../libcpu/arm/shared/include/arm-cp15.h<br>
@@ -79,7 +81,6 @@ libbsp_a_SOURCES += ../../shared/bspclean.c<br>
 libbsp_a_SOURCES += ../../shared/bspgetworkarea.c<br>
 libbsp_a_SOURCES += ../../shared/bsplibc.c<br>
 libbsp_a_SOURCES += ../../shared/bsppost.c<br>
-libbsp_a_SOURCES += ../../shared/bsppredriverhook.c<br>
 libbsp_a_SOURCES += ../../shared/bsppretaskinghook.c<br>
 libbsp_a_SOURCES += ../../shared/cpucounterread.c<br>
 libbsp_a_SOURCES += ../../shared/cpucounterdiff.c<br>
@@ -118,11 +119,19 @@ libbsp_a_SOURCES += clock/clockdrv.c ../../../shared/clockdrv_shell.h<br>
 # Timer<br>
 libbsp_a_SOURCES += misc/timer.c<br>
<br>
+# GPIO<br>
+<br>
+libbsp_a_SOURCES += gpio/gpio.c<br>
+<br>
 # RTC<br>
<br>
 # SSP<br>
<br>
 # I2C<br>
+libbsp_a_SOURCES += i2c/i2c.c<br>
+libbsp_a_SOURCES += i2c/i2c_init.c<br>
+libbsp_a_SOURCES += i2c/spi.c<br>
+libbsp_a_SOURCES += i2c/spi_init.c<br>
<br>
 # Cache<br>
 libbsp_a_SOURCES += ../../../libcpu/shared/src/cache_manager.c<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/<a href="http://configure.ac" target="_blank">configure.ac</a> b/c/src/lib/libbsp/arm/raspberrypi/<a href="http://configure.ac" target="_blank">configure.ac</a><br>
index 9bd6883..92fa903 100644<br>
--- a/c/src/lib/libbsp/arm/raspberrypi/<a href="http://configure.ac" target="_blank">configure.ac</a><br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/<a href="http://configure.ac" target="_blank">configure.ac</a><br>
@@ -24,6 +24,18 @@ AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes")<br>
 RTEMS_BSPOPTS_SET([BSP_START_RESET_VECTOR],[*],[])<br>
 RTEMS_BSPOPTS_HELP([BSP_START_RESET_VECTOR],[reset vector address for BSP start])<br>
<br>
+RTEMS_BSPOPTS_SET([I2C_IO_MODE],[*],[1])<br>
+RTEMS_BSPOPTS_HELP([I2C_IO_MODE],[Define to 1 to use interrupt-driven I/O with the Raspberry Pi I2C bus. If defined to other value the access will be polled-driven.])<br>
+<br>
+RTEMS_BSPOPTS_SET([SPI_IO_MODE],[*],[1])<br>
+RTEMS_BSPOPTS_HELP([SPI_IO_MODE],[Define to 1 to use interrupt-driven I/O with the Raspberry Pi SPI bus. If defined to other value the access will be polled-driven.])<br>
+<br>
+RTEMS_BSPOPTS_SET([BSP_ENABLE_SPI],[*],[0])<br>
+RTEMS_BSPOPTS_HELP([BSP_ENABLE_SPI],[Define to 1 to use the SPI bus. This will register the bus in /dev/spi and also any device driver mentioned in i2c/spi_init.c .])<br>
+<br>
+RTEMS_BSPOPTS_SET([BSP_ENABLE_I2C],[*],[0])<br>
+RTEMS_BSPOPTS_HELP([BSP_ENABLE_I2C],[Define to 1 to use the I2C bus. This will register the bus in /dev/i2c and also any device driver mentioned in i2c/i2c_init.c .])<br>
+<br>
 RTEMS_BSP_CLEANUP_OPTIONS(0, 0)<br>
 RTEMS_BSP_LINKCMDS<br>
<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/gpio/gpio.c b/c/src/lib/libbsp/arm/raspberrypi/gpio/gpio.c<br>
new file mode 100644<br>
index 0000000..40ac3b0<br>
--- /dev/null<br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/gpio/gpio.c<br>
@@ -0,0 +1,727 @@<br>
+/**<br>
+ * @file gpio.c<br>
+ *<br>
+ * @ingroup raspberrypi_gpio<br>
+ *<br>
+ * @brief Support for the Raspberry PI GPIO.<br>
+ */<br>
+<br>
+/*<br>
+ *  Copyright (c) 2014 Andre Marques <andre.lousa.marques at <a href="http://gmail.com" target="_blank">gmail.com</a>><br>
+ *<br>
+ *  The license and distribution terms for this file may be<br>
+ *  found in the file LICENSE in this distribution or at<br>
+ *  <a href="http://www.rtems.org/license/LICENSE" target="_blank">http://www.rtems.org/license/LICENSE</a>.<br>
+ */<br>
+<br>
+#include <bsp/raspberrypi.h><br>
+#include <bsp/irq.h><br>
+#include <bsp/gpio.h><br>
+#include <assert.h><br>
+<br>
+/* Calculates a bitmask to assign an alternate function to a given pin. */<br>
+#define SELECT_PIN_FUNCTION(fn, pn) (fn << ((pn % 10) * 3))<br>
+<br>
+static bool is_initialized = false;<br>
+<br>
+rpi_gpio_pin gpio_pin[GPIO_PIN_COUNT];<br>
+<br>
+/**<br>
+ * @brief Waits a number of CPU cycles.<br>
+ *<br>
+ * @param[in] cycles The number of CPU cycles to wait.<br>
+ *<br>
+ */<br>
+static void arm_delay (int cycles)<br>
+{<br>
+  int i;<br>
+<br>
+  for ( i = 0; i < cycles; i++ ) {<br>
+    asm volatile ("nop");<br>
+  }<br>
+}<br>
+<br>
+/**<br>
+ * @brief Initializes the GPIO API and sets every pin as NOT_USED.<br>
+ *        If the API has already been initialized silently exits.<br>
+ */<br>
+void gpio_initialize(void)<br>
+{<br>
+  int i;<br>
+<br>
+  if ( is_initialized ) {<br>
+    return;<br>
+  }<br>
+<br>
+  is_initialized = true;<br>
+<br>
+  for ( i = 0; i < GPIO_PIN_COUNT; i++ ) {<br>
+    gpio_pin[i].pin_type = NOT_USED;<br>
+    gpio_pin[i].enabled_interrupt = NONE;<br>
+<br>
+    gpio_pin[i].h_args.debouncing_tick_count = 0;<br>
+  }<br>
+}<br>
+<br>
+/**<br>
+ * @brief Gives an output GPIO pin the logical value of 1.<br>
+ *<br>
+ * @param[in] pin The Raspberry Pi GPIO pin label number (not is position<br>
+ *            on the header).<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin was set successfully.<br>
+ * @retval RTEMS_NOT_CONFIGURED The received pin is not configured<br>
+ *                              as an digital output.<br>
+ */<br>
+rtems_status_code gpio_set(int pin)<br>
+{<br>
+  assert( pin >= 0 && pin < GPIO_PIN_COUNT );<br>
+<br>
+  if ( gpio_pin[pin - 1].pin_type != DIGITAL_OUTPUT ) {<br>
+    return RTEMS_NOT_CONFIGURED;<br>
+  }<br>
+<br>
+  BCM2835_REG(BCM2835_GPIO_GPSET0) = (1 << pin);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Gives an output GPIO pin the logical value of 0.<br>
+ *<br>
+ * @param[in] pin The Raspberry Pi GPIO pin label number (not is position<br>
+ *            on the header).<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin was cleared successfully.<br>
+ * @retval RTEMS_NOT_CONFIGURED The received pin is not configured<br>
+ *                              as an digital output.<br>
+ */<br>
+rtems_status_code gpio_clear(int pin)<br>
+{<br>
+  assert( pin >= 0 && pin < GPIO_PIN_COUNT );<br>
+<br>
+  if ( gpio_pin[pin - 1].pin_type != DIGITAL_OUTPUT ) {<br>
+    return RTEMS_NOT_CONFIGURED;<br>
+  }<br>
+<br>
+  BCM2835_REG(BCM2835_GPIO_GPCLR0) = (1 << pin);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Gets the value (level) of a GPIO input pin.<br>
+ *<br>
+ * @param[in] pin The Raspberry Pi GPIO pin label number (not is position<br>
+ *            on the header).<br>
+ *<br>
+ * @retval The function returns 0 or 1 depending on the pin current<br>
+ *         logical value.<br>
+ */<br>
+int gpio_get_value(int pin)<br>
+{<br>
+  assert( pin >= 0 && pin < GPIO_PIN_COUNT );<br>
+<br>
+  return (BCM2835_REG(BCM2835_GPIO_GPLEV0) & (1 << pin));<br>
+}<br>
+<br>
+/**<br>
+ * @brief Configures a GPIO pin to perform a certain function.<br>
+ *<br>
+ * @param[in] pin The Raspberry Pi GPIO pin label number (not is position<br>
+ *            on the header).<br>
+ * @param[in] type The new function of the pin.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin was configured successfully.<br>
+ * @retval RTEMS_RESOURCE_IN_USE The received pin is already being used.<br>
+ */<br>
+rtems_status_code gpio_select_pin(int pin, rpi_pin type)<br>
+{<br>
+  assert( pin >= 0 && pin < GPIO_PIN_COUNT );<br>
+<br>
+  /* Calculate the pin function select register address. */<br>
+  volatile unsigned int *pin_addr = (unsigned int *)BCM2835_GPIO_REGS_BASE +<br>
+                                    (pin / 10);<br>
+<br>
+  /* If the pin is already being used returns with an error. */<br>
+  if ( gpio_pin[pin - 1].pin_type != NOT_USED ) {<br>
+    return RTEMS_RESOURCE_IN_USE;<br>
+  }<br>
+<br>
+  /* Sets pin function select bits.*/<br>
+  if ( type == DIGITAL_INPUT ) {<br>
+    *(pin_addr) &= ~SELECT_PIN_FUNCTION(7, pin);<br>
+  }<br>
+  else {<br>
+    *(pin_addr) |= SELECT_PIN_FUNCTION(type, pin);<br>
+  }<br>
+<br>
+  /* If the alternate function was successfuly assigned to the pin,<br>
+   * record that information on the gpio_pin structure. */<br>
+  gpio_pin[pin - 1].pin_type = type;<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Configures the pull resistor setting of an array of GPIO pins.<br>
+ *<br>
+ * @param[in] pins Array of Raspberry Pi GPIO pin label numbers (not their<br>
+ *            position on the header).<br>
+ * @param[in] pin_count Number of pins on the @var pins array.<br>
+ * @param[in] mode The pull resistor mode.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pull resistor successfully configured.<br>
+ * @retval RTEMS_NOT_DEFINED Unknown pull resistor mode.<br>
+ */<br>
+static rtems_status_code<br>
+set_input_mode(int *pins, int pin_count, int pin_mask, rpi_gpio_input_mode mode)<br>
+{<br>
+  int i;<br>
+<br>
+  /* Set control signal. */<br>
+  switch ( mode ) {<br>
+    case PULL_UP:<br>
+      BCM2835_REG(BCM2835_GPIO_GPPUD) = (1 << 1);<br>
+      break;<br>
+<br>
+    case PULL_DOWN:<br>
+      BCM2835_REG(BCM2835_GPIO_GPPUD) = (1 << 0);<br>
+      break;<br>
+<br>
+    case NO_PULL_RESISTOR:<br>
+      BCM2835_REG(BCM2835_GPIO_GPPUD) = 0;<br>
+      break;<br>
+<br>
+    default:<br>
+      return RTEMS_NOT_DEFINED;<br>
+  }<br>
+<br>
+  /* Wait 150 cyles, as per BCM2835 documentation. */<br>
+  arm_delay(150);<br>
+<br>
+  /* Setup clock for the control signal. */<br>
+  BCM2835_REG(BCM2835_GPIO_GPPUDCLK0) = pin_mask;<br>
+<br>
+  arm_delay(150);<br>
+<br>
+  /* Remove the control signal. */<br>
+  BCM2835_REG(BCM2835_GPIO_GPPUD) = 0;<br>
+<br>
+  /* Remove the clock. */<br>
+  BCM2835_REG(BCM2835_GPIO_GPPUDCLK0) = 0;<br>
+<br>
+  /* If the operation was successful, record that information<br>
+   * on the gpio_pin structure so it can be recalled later. */<br>
+  for ( i = 0; i < pin_count; i++ ) {<br>
+    gpio_pin[pins[i] - 1].input_mode = mode;<br>
+  }<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Configures a single GPIO pin pull resistor.<br>
+ *<br>
+ * @param[in] pin Raspberry Pi GPIO pin label number (not its position<br>
+ *            on the header).<br>
+ * @param[in] mode The pull resistor mode.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pull resistor successfully configured.<br>
+ * @retval RTEMS_NOT_DEFINED @see set_input_mode().<br>
+ */<br>
+rtems_status_code gpio_input_mode(int pin, rpi_gpio_input_mode mode)<br>
+{<br>
+  assert( pin >= 0 && pin < GPIO_PIN_COUNT );<br>
+<br>
+  int pin_mask = (1 << pin);<br>
+  int pins[1];<br>
+<br>
+  /* If the desired actuation mode is already set, silently exits. */<br>
+  if ( gpio_pin[pin - 1].input_mode == mode ) {<br>
+    return RTEMS_SUCCESSFUL;<br>
+  }<br>
+<br>
+  pins[0] = pin;<br>
+<br>
+  return set_input_mode(pins, 1, pin_mask, mode);<br>
+}<br>
+<br>
+/**<br>
+ * @brief Sets the same pull-up/down resistors actuation mode to multiple GPIO<br>
+ *        input pins. There is a maximum number of 32 pins per call,<br>
+ *        which is enough for Raspberry Pi models A and B (17 GPIOs on<br>
+ *        P1 GPIO header) and also model B+ (28 GPIOs on J8 GPIO header).<br>
+ *<br>
+ * @param[in] pins Array of Raspberry Pi GPIO pin label numbers<br>
+ *                 (not their position on the header).<br>
+ * @param[in] pin_count Number of pins on the @var pins array.<br>
+ * @param[in] mode The pull resistor mode.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pull resistor successfully configured.<br>
+ * @retval RTEMS_INVALID_ID Unknown pull resistor mode.<br>
+ */<br>
+rtems_status_code<br>
+gpio_setup_input_mode(int *pins, int pin_count, rpi_gpio_input_mode mode)<br>
+{<br>
+  uint32_t pin_mask = 0;<br>
+  int diff_mode_counter = 0;<br>
+  int i;<br>
+<br>
+  if ( pin_count > GPIO_EXTERNAL_TOP_PIN ) {<br>
+    return RTEMS_INVALID_ID;<br>
+  }<br>
+<br>
+  /* Cycle through the given pins to check if this operation will have an effect<br>
+   * on the resistor actuation mode of any one of the pins.<br>
+   * Every pin that currently uses a different pull resistor mode sets a bit<br>
+   * in its corresponding place on a bitmask. If the mode for a pin will not<br>
+   * change then the diff_mode_counter variable is increased. */<br>
+  for ( i = 0; i < pin_count; i++ ) {<br>
+    assert( pins[i] >= 0 && pins[i] < GPIO_PIN_COUNT );<br>
+<br>
+    if ( gpio_pin[pins[i] - 1].input_mode != mode ) {<br>
+      pin_mask |= (1 << pins[i]);<br>
+    }<br>
+    else {<br>
+      ++diff_mode_counter;<br>
+    }<br>
+  }<br>
+<br>
+  /* If no pin will have its resistor mode changed silently exits, avoiding an<br>
+   * unnecessary access to the Rasberry Pi memory registers. */<br>
+  if ( diff_mode_counter == 0 ) {<br>
+    return RTEMS_SUCCESSFUL;<br>
+  }<br>
+<br>
+  return set_input_mode(pins, pin_count, pin_mask, mode);<br>
+}<br>
+<br>
+/**<br>
+ * @brief Disables a GPIO pin on the APiI, making it available to be used<br>
+ *        by anyone on the system.<br>
+ *<br>
+ * @param[in] dev_pin Raspberry Pi GPIO pin label number (not its position<br>
+ *            on the header).<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin successfully disabled on the API.<br>
+ * @retval RTEMS_UNSATISFIED Could not disable an ative interrupt on this pin,<br>
+ *                           @see gpio_disable_interrupt(),<br>
+ */<br>
+rtems_status_code gpio_disable_pin(int dev_pin)<br>
+{<br>
+  rtems_status_code sc = RTEMS_SUCCESSFUL;<br>
+  rpi_gpio_pin *pin;<br>
+<br>
+  assert( dev_pin >= 1 && dev_pin <= GPIO_PIN_COUNT );<br>
+<br>
+  pin = &gpio_pin[dev_pin - 1];<br>
+<br>
+  pin->pin_type = NOT_USED;<br>
+<br>
+  /* If the pin has an enabled interrupt then remove the handler. */<br>
+  if ( pin->enabled_interrupt != NONE ) {<br>
+    sc = gpio_disable_interrupt(dev_pin);<br>
+  }<br>
+<br>
+  return sc;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Setups a JTAG interface using the P1 GPIO pin header<br>
+ *        for the models A/B and J8 header on the B+.<br>
+ *        The following pins should be unused before calling this function:<br>
+ *        GPIO 4, 22, 24, 25 and 27.<br>
+ *<br>
+ * @param[in] dev_pin Raspberry Pi GPIO pin label number (not its position<br>
+ *            on the header).<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL JTAG interface successfully configured.<br>
+ * @retval RTEMS_RESOURCE_IN_USE At least one of the required pins is currently<br>
+ *                               occupied, @see gpio_select_pin().<br>
+ */<br>
+rtems_status_code gpio_select_jtag(void)<br>
+{<br>
+  rtems_status_code sc;<br>
+<br>
+  /* Setup gpio 4 alt5 ARM_TDI. */<br>
+  if ( (sc = gpio_select_pin(4, ALT_FUNC_5)) != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+  }<br>
+<br>
+  /* Setup gpio 22 alt4 ARM_TRST. */<br>
+  if ( (sc = gpio_select_pin(22, ALT_FUNC_4)) != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+  }<br>
+<br>
+  /* Setup gpio 24 alt4 ARM_TDO. */<br>
+  if ( (sc = gpio_select_pin(24, ALT_FUNC_4)) != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+  }<br>
+<br>
+  /* Setup gpio 25 alt4 ARM_TCK. */<br>
+  if ( (sc = gpio_select_pin(25, ALT_FUNC_4)) != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+  }<br>
+<br>
+  /* Setup gpio 27 alt4 ARM_TMS. */<br>
+  if ( (sc = gpio_select_pin(27, ALT_FUNC_4)) != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+  }<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Setups a SPI interface using the P1 GPIO pin header<br>
+ *        for the models A/B and J8 header on the B+.<br>
+ *        The following pins should be unused before calling this function:<br>
+ *        GPIO 7, 8, 9, 10 and 11.<br>
+ *<br>
+ * @param[in] dev_pin Raspberry Pi GPIO pin label number (not its position<br>
+ *            on the header).<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL SPI interface successfully configured.<br>
+ * @retval RTEMS_RESOURCE_IN_USE At least one of the required pins is currently<br>
+ *                               occupied, @see gpio_select_pin().<br>
+ */<br>
+rtems_status_code gpio_select_spi_p1(void)<br>
+{<br>
+  rtems_status_code sc;<br>
+<br>
+  /* SPI master 0 MISO data line. */<br>
+  if ( (sc = gpio_select_pin(9, ALT_FUNC_0)) != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+  }<br>
+<br>
+  /* SPI master 0 MOSI data line. */<br>
+  if ( (sc = gpio_select_pin(10, ALT_FUNC_0)) != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+  }<br>
+<br>
+  /* SPI master 0 SCLK clock line. */<br>
+  if ( (sc = gpio_select_pin(11, ALT_FUNC_0)) != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+  }<br>
+<br>
+  /* SPI master 0 CE_0 chip enable line. */<br>
+  if ( (sc = gpio_select_pin(8, ALT_FUNC_0)) != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+  }<br>
+<br>
+  /* SPI master 0 CE_1 chip enable line. */<br>
+  if ( (sc = gpio_select_pin(7, ALT_FUNC_0)) != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+  }<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Setups a I2C interface using the P1 GPIO pin header<br>
+ *        for the models A/B and J8 header on the B+.<br>
+ *        The following pins should be unused before calling this function:<br>
+ *        GPIO 2 and 3.<br>
+ *<br>
+ * @param[in] dev_pin Raspberry Pi GPIO pin label number (not its position<br>
+ *            on the header).<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL JTAG interface successfully configured.<br>
+ * @retval RTEMS_RESOURCE_IN_USE At least one of the required pins is currently<br>
+ *                               occupied, @see gpio_select_pin().<br>
+ */<br>
+rtems_status_code gpio_select_i2c_p1_rev2(void)<br>
+{<br>
+  rtems_status_code sc;<br>
+  int pins[] = {2,3};<br>
+<br>
+  /* I2C BSC1 SDA data line. */<br>
+  if ( (sc = gpio_select_pin(2, ALT_FUNC_0)) != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+  }<br>
+<br>
+  /* I2C BSC1 SCL clock line. */<br>
+  if ( (sc = gpio_select_pin(3, ALT_FUNC_0)) != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+  }<br>
+<br>
+  /* Enable pins 2 and 3 pull-up resistors. */<br>
+  if ( (sc = gpio_setup_input_mode(pins, 2, PULL_UP)) != RTEMS_SUCCESSFUL ) {<br>
+    return sc;<br>
+  }<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief De-bounces a switch by requiring a certain time to pass between<br>
+ *        interrupts. Any interrupt fired too close to the last will be<br>
+ *        ignored as it is probably the result of a involuntary switch/button<br>
+ *        bounce after being released.<br>
+ *<br>
+ * @param[in] dev_pin Raspberry Pi GPIO pin label number (not its position<br>
+ *            on the header).<br>
+ *<br>
+ * @retval 0 Interrupt is likely provoked by a user press on the switch.<br>
+ * @retval -1 Interrupt was generated too close to the last one.<br>
+ *            Probably a switch bounce.<br>
+ */<br>
+static int debounce_switch(int dev_pin)<br>
+{<br>
+  rtems_interval time;<br>
+  rpi_gpio_pin *pin;<br>
+<br>
+  assert( dev_pin >= 1 && dev_pin <= GPIO_PIN_COUNT );<br>
+<br>
+  pin = &gpio_pin[dev_pin - 1];<br>
+<br>
+  time = rtems_clock_get_ticks_since_boot();<br>
+<br>
+  if ( (time - pin->h_args.last_isr_tick) < pin->h_args.debouncing_tick_count ) {<br>
+    return -1;<br>
+  }<br>
+<br>
+  pin->h_args.last_isr_tick = time;<br>
+<br>
+  return 0;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Generic ISR that clears the event register on the Raspberry Pi and<br>
+ *        calls an user defined ISR.<br>
+ *<br>
+ * @param[in] arg Void pointer to a handler_arguments structure.<br>
+ */<br>
+static void generic_handler(void* arg)<br>
+{<br>
+  handler_arguments* handler_args;<br>
+  int rv = 0;<br>
+  int pin = 0;<br>
+<br>
+  handler_args = (handler_arguments*) arg;<br>
+<br>
+  pin = handler_args->pin_number;<br>
+<br>
+  /*  If the interrupt was generated by the pin attached to this ISR clear it. */<br>
+  if ( BCM2835_REG(BCM2835_GPIO_GPEDS0) & (1 << pin) ) {<br>
+    BCM2835_REG(BCM2835_GPIO_GPEDS0) &= (1 << pin);<br>
+  }<br>
+  /* If not lets the next ISR process the interrupt. */<br>
+  else {<br>
+    return;<br>
+  }<br>
+<br>
+  /* If this pin has the deboucing function attached, call it. */<br>
+  if ( handler_args->debouncing_tick_count > 0 ) {<br>
+    rv = debounce_switch(pin);<br>
+<br>
+    if ( rv < 0 ) {<br>
+      return;<br>
+    }<br>
+  }<br>
+<br>
+  /* Call the user's ISR. */<br>
+  (handler_args->handler) ();<br>
+}<br>
+<br>
+/**<br>
+ * @brief Defines for a GPIO input pin the number of clock ticks that must pass<br>
+ *        before an generated interrupt is garanteed to be generated by the user<br>
+ *        and not by a bouncing switch/button.<br>
+ *<br>
+ * @param[in] dev_pin Raspberry Pi GPIO pin label number (not its position<br>
+ *            on the header).<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL De-bounce function successfully attached to the pin.<br>
+ * @retval RTEMS_NOT_CONFIGURED The current pin is not configured as a digital<br>
+ *                              input, hence it can not be connected to a switch.<br>
+ */<br>
+rtems_status_code gpio_debounce_switch(int dev_pin, int ticks)<br>
+{<br>
+  assert( dev_pin >= 1 && dev_pin <= GPIO_PIN_COUNT );<br>
+<br>
+  if ( gpio_pin[dev_pin - 1].pin_type != DIGITAL_INPUT ) {<br>
+    return RTEMS_NOT_CONFIGURED;<br>
+  }<br>
+<br>
+  gpio_pin[dev_pin - 1].h_args.debouncing_tick_count = ticks;<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Enables interrupts to be generated on a given GPIO pin.<br>
+ *        When fired that interrupt will call the given handler.<br>
+ *<br>
+ * @param[in] dev_pin Raspberry Pi GPIO pin label number (not its position<br>
+ *            on the header).<br>
+ * @param[in] interrupt Type of interrupt to enable for the pin.<br>
+ * @param[in] handler Pointer to a function that will be called every time<br>
+ *                    @var interrupt is generated. This function must have<br>
+ *                    no receiving parameters and return void.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Interrupt successfully enabled for this pin.<br>
+ * @retval RTEMS_UNSATISFIED Could not replace the currently active<br>
+ *                           interrupt on this pin.<br>
+ */<br>
+rtems_status_code gpio_enable_interrupt(<br>
+int dev_pin,<br>
+gpio_interrupt interrupt,<br>
+void (*handler)(void)<br>
+)<br>
+{<br>
+  rtems_status_code sc;<br>
+  rpi_gpio_pin *pin;<br>
+<br>
+  assert( dev_pin >= 1 && dev_pin <= GPIO_EXTERNAL_TOP_PIN );<br>
+<br>
+  pin = &gpio_pin[dev_pin - 1];<br>
+<br>
+  /* If the pin already has an enabled interrupt removes it first,<br>
+   * as well as its handler. */<br>
+  if ( pin->enabled_interrupt != NONE ) {<br>
+    sc = gpio_disable_interrupt(dev_pin);<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      return RTEMS_UNSATISFIED;<br>
+    }<br>
+  }<br>
+<br>
+  pin->h_args.pin_number = dev_pin;<br>
+  pin->h_args.handler = handler;<br>
+<br>
+  pin->h_args.last_isr_tick = rtems_clock_get_ticks_since_boot();<br>
+<br>
+  /* Installs the generic_handler, which will call the user handler received<br>
+   * a parameter. */<br>
+  sc = rtems_interrupt_handler_install(BCM2835_IRQ_ID_GPIO_0,<br>
+                                       NULL,<br>
+                                       RTEMS_INTERRUPT_SHARED,<br>
+                                       (rtems_interrupt_handler) generic_handler,<br>
+                                       &(pin->h_args));<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  switch ( interrupt ) {<br>
+    case FALLING_EDGE:<br>
+      /* Enables asynchronous falling edge detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPAFEN0) |= (1 << dev_pin);<br>
+      break;<br>
+<br>
+    case RISING_EDGE:<br>
+      /* Enables asynchronous rising edge detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPAREN0) |= (1 << dev_pin);<br>
+      break;<br>
+<br>
+    case BOTH_EDGES:<br>
+      /* Enables asynchronous falling edge detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPAFEN0) |= (1 << dev_pin);<br>
+<br>
+      /* Enables asynchronous rising edge detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPAREN0) |= (1 << dev_pin);<br>
+      break;<br>
+<br>
+    case LOW_LEVEL:<br>
+      /* Enables pin low level detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPLEN0) |= (1 << dev_pin);<br>
+      break;<br>
+<br>
+    case HIGH_LEVEL:<br>
+      /* Enables pin high level detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPHEN0) |= (1 << dev_pin);<br>
+      break;<br>
+<br>
+    case BOTH_LEVELS:<br>
+      /* Enables pin low level detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPLEN0) |= (1 << dev_pin);<br>
+<br>
+      /* Enables pin high level detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPHEN0) |= (1 << dev_pin);<br>
+      break;<br>
+<br>
+    case NONE:<br>
+      return RTEMS_SUCCESSFUL;<br>
+  }<br>
+<br>
+  pin->enabled_interrupt = interrupt;<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Stops interrupts from being generated from a given GPIO pin<br>
+ *        and removes the corresponding handler.<br>
+ *<br>
+ * @param[in] dev_pin Raspberry Pi GPIO pin label number (not its position<br>
+ *            on the header).<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Interrupt successfully disabled for this pin.<br>
+ * @retval RTEMS_UNSATISFIED Could not remove the current interrupt handler or<br>
+ *                           could not recognise the current active interrupt<br>
+ *                           on this pin.<br>
+ */<br>
+rtems_status_code gpio_disable_interrupt(int dev_pin)<br>
+{<br>
+  rtems_status_code sc;<br>
+  rpi_gpio_pin *pin;<br>
+<br>
+  assert( dev_pin >= 1 && dev_pin <= GPIO_EXTERNAL_TOP_PIN );<br>
+<br>
+  pin = &gpio_pin[dev_pin - 1];<br>
+<br>
+  switch ( pin->enabled_interrupt ) {<br>
+    case FALLING_EDGE:<br>
+      /* Disables asynchronous falling edge detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPAFEN0) &= ~(1 << dev_pin);<br>
+      break;<br>
+<br>
+    case RISING_EDGE:<br>
+      /* Disables asynchronous rising edge detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPAREN0) &= ~(1 << dev_pin);<br>
+      break;<br>
+<br>
+    case BOTH_EDGES:<br>
+      /* Disables asynchronous falling edge detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPAFEN0) &= ~(1 << dev_pin);<br>
+<br>
+      /* Disables asynchronous rising edge detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPAREN0) &= ~(1 << dev_pin);<br>
+      break;<br>
+<br>
+    case LOW_LEVEL:<br>
+      /* Disables pin low level detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPLEN0) &= ~(1 << dev_pin);<br>
+      break;<br>
+<br>
+    case HIGH_LEVEL:<br>
+      /* Disables pin high level detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPHEN0) &= ~(1 << dev_pin);<br>
+      break;<br>
+<br>
+    case BOTH_LEVELS:<br>
+      /* Disables pin low level detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPLEN0) &= ~(1 << dev_pin);<br>
+<br>
+      /* Disables pin high level detection. */<br>
+      BCM2835_REG(BCM2835_GPIO_GPHEN0) &= ~(1 << dev_pin);<br>
+      break;<br>
+<br>
+    case NONE:<br>
+      return RTEMS_SUCCESSFUL;<br>
+  }<br>
+<br>
+  /* Removes the handler. */<br>
+  sc = rtems_interrupt_handler_remove(BCM2835_IRQ_ID_GPIO_0,<br>
+                                      (rtems_interrupt_handler) generic_handler,<br>
+                                      &(pin->h_args));<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  pin->enabled_interrupt = NONE;<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/i2c/i2c.c b/c/src/lib/libbsp/arm/raspberrypi/i2c/i2c.c<br>
new file mode 100644<br>
index 0000000..13c33ad<br>
--- /dev/null<br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/i2c/i2c.c<br>
@@ -0,0 +1,480 @@<br>
+/**<br>
+ * @file i2c.c<br>
+ *<br>
+ * @ingroup raspberrypi_i2c<br>
+ *<br>
+ * @brief Support for the I2C bus on the Raspberry Pi GPIO P1 header (model A/B)<br>
+ *        and GPIO J8 header on model B+.<br>
+ */<br>
+<br>
+/*<br>
+ *  Copyright (c) 2014 Andre Marques <andre.lousa.marques at <a href="http://gmail.com" target="_blank">gmail.com</a>><br>
+ *<br>
+ *  The license and distribution terms for this file may be<br>
+ *  found in the file LICENSE in this distribution or at<br>
+ *  <a href="http://www.rtems.org/license/LICENSE" target="_blank">http://www.rtems.org/license/LICENSE</a>.<br>
+ */<br>
+<br>
+/*<br>
+ * TODO:<br>
+ * - Clock stretching (currently using default values)<br>
+ * - 10-bit addressing<br>
+ * - Falling/Rising edge delays (currently using default values)<br>
+ */<br>
+<br>
+#include <bsp.h><br>
+#include <bsp/raspberrypi.h><br>
+#include <bsp/gpio.h><br>
+#include <bsp/irq.h><br>
+#include <bsp/i2c.h><br>
+#include <assert.h><br>
+<br>
+/**<br>
+ * @brief Calculates a clock divider to be used with the BSC core clock rate<br>
+ *        to set a I2C clock rate the closest (<=) to a desired frequency.<br>
+ *<br>
+ * @param[in] clock_hz The desired clock frequency for the I2C bus operation.<br>
+ * @param[out] clock_divider Pointer to a variable where the calculated<br>
+ *                          clock divider will be stored.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Successfully calculated a valid clock divider.<br>
+ * @retval RTEMS_INVALID_NUMBER The resulting clock divider is invalid, due to<br>
+ *                              an invalid BSC_CORE_CLOCK_HZ<br>
+ *                              or clock_hz value.<br>
+ */<br>
+static rtems_status_code<br>
+bcm2835_i2c_calculate_clock_divider(uint32_t clock_hz, uint16_t *clock_divider)<br>
+{<br>
+  uint16_t divider;<br>
+  uint32_t clock_rate;<br>
+<br>
+  assert( clock_hz > 0 );<br>
+<br>
+  /* Calculates an initial clock divider. */<br>
+  divider = BSC_CORE_CLK_HZ / clock_hz;<br>
+<br>
+  clock_rate = BSC_CORE_CLK_HZ / divider;<br>
+<br>
+  /* If the resulting clock rate is greater than desired, try the next greater<br>
+   * divider. */<br>
+  while ( clock_rate > clock_hz ) {<br>
+    ++divider;<br>
+<br>
+    clock_rate = BSC_CORE_CLK_HZ / divider;<br>
+  }<br>
+<br>
+  *clock_divider = divider;<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Set the I2C bus clock divider.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ * @param[in] tfr_mode Pointer to a libi2c API transfer mode data structure.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Successfully setup the bus transfer mode as desired.<br>
+ * @retval RTEMS_INVALID_NUMBER @see bcm2835_i2c_calculate_clock_divider().<br>
+ */<br>
+static rtems_status_code bcm2835_i2c_set_tfr_mode(<br>
+rtems_libi2c_bus_t *bushdl,<br>
+const rtems_libi2c_tfr_mode_t *tfr_mode<br>
+)<br>
+{<br>
+  rtems_status_code sc;<br>
+  uint16_t clock_divider;<br>
+<br>
+  /* Calculate the most appropriate clock divider. */<br>
+  sc = bcm2835_i2c_calculate_clock_divider(tfr_mode->baudrate, &clock_divider);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    return sc;<br>
+  }<br>
+<br>
+  /* Set clock divider. */<br>
+  BCM2835_REG(BCM2835_I2C_DIV) = clock_divider;<br>
+<br>
+  return sc;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Reads/writes to/from the I2C bus.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ * @param[in] rd_buf Read buffer. If not NULL the function will read from<br>
+ *                   the bus and store the read on this buffer.<br>
+ * @param[in] wr_buf Write buffer. If not NULL the function will write the<br>
+ *                   contents of this buffer to the bus.<br>
+ * @param[in] buffer_size Size of the non-NULL buffer.<br>
+ *<br>
+ * @retval -1 Could not send/receive data to/from the bus.<br>
+ * @retval >=0 The number of bytes read/written.<br>
+ */<br>
+static int bcm2835_i2c_read_write(<br>
+rtems_libi2c_bus_t * bushdl,<br>
+unsigned char *rd_buf,<br>
+const unsigned char *wr_buf,<br>
+int buffer_size<br>
+)<br>
+{<br>
+  bcm2835_i2c_softc_t *softc_ptr = &(((bcm2835_i2c_desc_t *)(bushdl))->softc);<br>
+<br>
+  uint32_t bytes_sent = buffer_size;<br>
+<br>
+  /* Since there is a maximum of 0xFFFF packets per transfer<br>
+   * (size of the DLEN register), count how many transfers will be<br>
+   * needed and adjust each transfer size accordingly. */<br>
+  int transfer_count = (buffer_size + 0xFFFE) / 0xFFFF;<br>
+  uint16_t dlen_buffer_size;<br>
+<br>
+  do {<br>
+    if ( transfer_count > 1 ) {<br>
+      dlen_buffer_size = 0xFFFF;<br>
+    }<br>
+    else {<br>
+      dlen_buffer_size = (buffer_size & 0xFFFF);<br>
+    }<br>
+<br>
+    /* Set the DLEN register, which specifies how many data packets<br>
+     * will be transferred. */<br>
+    BCM2835_REG(BCM2835_I2C_DLEN) = dlen_buffer_size;<br>
+<br>
+    /* Clear the acknowledgment and clock stretching error status. */<br>
+    BCM2835_REG(BCM2835_I2C_S) |= (3 << 8);<br>
+<br>
+    /* While there is data to transfer. */<br>
+    while ( dlen_buffer_size >= 1 ) {<br>
+      /* If writing. */<br>
+      if ( rd_buf == NULL ) {<br>
+<br>
+        /* If transfer is not active, send start bit. */<br>
+        if( (BCM2835_REG(BCM2835_I2C_S) & (1 << 0)) == 0 )<br>
+          BCM2835_REG(BCM2835_I2C_C) |= (1 << 7);<br>
+<br>
+        /* If using the I2C bus in interrupt-driven mode. */<br>
+        if ( I2C_IO_MODE == 1 ) {<br>
+<br>
+          /* Generate interrupts on the TXW bit condition. */<br>
+          BCM2835_REG(BCM2835_I2C_C) |= (1 << 9);<br>
+<br>
+          if (<br>
+            rtems_semaphore_obtain(softc_ptr->irq_sema_id, RTEMS_WAIT, 50) !=<br>
+            RTEMS_SUCCESSFUL<br>
+          ) {<br>
+            return -1;<br>
+          }<br>
+        }<br>
+<br>
+        /* If using the bus in polling mode. */<br>
+        else {<br>
+          /* Poll TXW bit until there is space available to write. */<br>
+          while ( (BCM2835_REG(BCM2835_I2C_S) & (1 << 2)) == 0 ) {<br>
+            ;<br>
+          }<br>
+        }<br>
+<br>
+        /* Write data to the TX FIFO. */<br>
+        BCM2835_REG(BCM2835_I2C_FIFO) = (*(uint8_t *)wr_buf);<br>
+<br>
+        ++wr_buf;<br>
+<br>
+        /* Check for acknowledgment or clock stretching errors. */<br>
+        if (<br>
+          (BCM2835_REG(BCM2835_I2C_S) & (1 << 8)) ||<br>
+          (BCM2835_REG(BCM2835_I2C_S) & (1 << 9))<br>
+        ) {<br>
+          return -1;<br>
+        }<br>
+      }<br>
+      /* If reading. */<br>
+      else {<br>
+        /* Send start bit. Before any read a libi2c_send_addr call should be<br>
+         * made signaling a read operation. */<br>
+        BCM2835_REG(BCM2835_I2C_C) |= (1 << 7);<br>
+<br>
+        /* Check for an acknowledgment error. */<br>
+        if ( (BCM2835_REG(BCM2835_I2C_S) & (1 << 8)) != 0 ) {<br>
+          return -1;<br>
+        }<br>
+<br>
+        /* Poll RXD bit until there is data on the RX FIFO to read. */<br>
+        while ( (BCM2835_REG(BCM2835_I2C_S) & (1 << 5)) == 0 ) {<br>
+          ;<br>
+        }<br>
+<br>
+        /* Read data from the RX FIFO. */<br>
+        (*(uint8_t *)rd_buf) = BCM2835_REG(BCM2835_I2C_FIFO) & 0xFF;<br>
+<br>
+        ++rd_buf;<br>
+<br>
+        /* Check for acknowledgment or clock stretching errors. */<br>
+        if (<br>
+          (BCM2835_REG(BCM2835_I2C_S) & (1 << 8)) ||<br>
+          (BCM2835_REG(BCM2835_I2C_S) & (1 << 9))<br>
+        ) {<br>
+          return -1;<br>
+        }<br>
+      }<br>
+<br>
+      --dlen_buffer_size;<br>
+      --transfer_count;<br>
+      --buffer_size;<br>
+    }<br>
+  } while ( transfer_count > 0 );<br>
+<br>
+  /* If using the I2C bus in interrupt-driven mode. */<br>
+  if ( I2C_IO_MODE == 1 ) {<br>
+    /* Generate interrupts on the DONE bit condition. */<br>
+    BCM2835_REG(BCM2835_I2C_C) |= (1 << 8);<br>
+<br>
+    if (<br>
+      rtems_semaphore_obtain(softc_ptr->irq_sema_id, RTEMS_WAIT, 50) !=<br>
+      RTEMS_SUCCESSFUL<br>
+    ) {<br>
+      return -1;<br>
+    }<br>
+  }<br>
+  /* If using the bus in polling mode. */<br>
+  else {<br>
+    /* Poll DONE bit until data has been sent. */<br>
+    while ( (BCM2835_REG(BCM2835_I2C_S) & (1 << 1)) == 0 ) {<br>
+      ;<br>
+    }<br>
+  }<br>
+<br>
+  bytes_sent -= buffer_size;<br>
+<br>
+  return bytes_sent;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Handler function that is called on any I2C interrupt.<br>
+ *<br>
+ *        There are 3 situations that can generate an interrupt:<br>
+ *<br>
+ *        1. Transfer (read/write) complete;<br>
+ *        2. The TX FIFO has space for more data (during a write transfer);<br>
+ *        3. The RX FIFO is full.<br>
+ *<br>
+ *        Because the I2C FIFO has a 16 byte size, the 3. situation is not<br>
+ *        as useful to many applications as knowing that at least 1 byte can<br>
+ *        be read from the RX FIFO. For that reason this information is<br>
+ *        got through polling the RXD bit even in interrupt-driven mode.<br>
+ *<br>
+ *        This leaves only 2 interrupts to be caught. At any given time<br>
+ *        when no I2C bus transfer is taking place no I2C interrupts are<br>
+ *        generated, and they do they are only enabled one at a time:<br>
+ *<br>
+ *        - When trying to write, the 2. interrupt is enabled to signal that<br>
+ *          data can be written on the TX FIFO, avoiding data loss in case<br>
+ *          it is full. When caught the handler disables that interrupt from<br>
+ *          being generated and releases the irq semaphore, which will allow<br>
+ *          the transfer process to continue (by writing to the TX FIFO);<br>
+ *<br>
+ *        - When the transfer is done on Raspberry side, the 1. interrupt is<br>
+ *          enabled for the device to signal it has finished the transfer as<br>
+ *          well. When caught the handler disables that interrupt from being<br>
+ *          generated and releases the irq semaphore, marking the end of the<br>
+ *          transfer.<br>
+ *<br>
+ * @param[in] arg Void pointer to the bus data structure.<br>
+ */<br>
+static void i2c_handler(void* arg)<br>
+{<br>
+  bcm2835_i2c_softc_t *softc_ptr = (bcm2835_i2c_softc_t *) arg;<br>
+<br>
+  /* If the current enabled interrupt is on the TXW condition, disable it. */<br>
+  if ( (BCM2835_REG(BCM2835_I2C_C) & (1 << 9)) ) {<br>
+    BCM2835_REG(BCM2835_I2C_C) &= ~(1 << 9);<br>
+  }<br>
+  /* If the current enabled interrupt is on the DONE condition, disable it. */<br>
+  else if ( (BCM2835_REG(BCM2835_I2C_C) & (1 << 8)) ) {<br>
+    BCM2835_REG(BCM2835_I2C_C) &= ~(1 << 8);<br>
+<br>
+    /* Release the irq semaphore. */<br>
+    rtems_semaphore_release(softc_ptr->irq_sema_id);<br>
+  }<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function to initialize the I2C bus.<br>
+ *        This function is used by the libi2c API.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL SPI bus successfully initialized.<br>
+ * @retval Any other status code @see rtems_semaphore_create() and<br>
+ *         @see rtems_interrupt_handler_install().<br>
+ */<br>
+rtems_status_code bcm2835_i2c_init(rtems_libi2c_bus_t * bushdl)<br>
+{<br>
+  bcm2835_i2c_softc_t *softc_ptr = &(((bcm2835_i2c_desc_t *)(bushdl))->softc);<br>
+  rtems_status_code sc = RTEMS_SUCCESSFUL;<br>
+<br>
+  if ( softc_ptr->initialized == 1 ) {<br>
+    return sc;<br>
+  }<br>
+<br>
+  softc_ptr->initialized = 1;<br>
+<br>
+  /* Enable the I2C BSC interface. */<br>
+  BCM2835_REG(BCM2835_I2C_C) |= (1 << 15);<br>
+<br>
+  /* If the access to the bus is configured to be interrupt-driven. */<br>
+  if ( I2C_IO_MODE == 1 ) {<br>
+    sc = rtems_semaphore_create(rtems_build_name('i','2','c','s'),<br>
+                                0,<br>
+                                RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE,<br>
+                                0,<br>
+                                &softc_ptr->irq_sema_id<br>
+                               );<br>
+<br>
+    sc = rtems_interrupt_handler_install(BCM2835_IRQ_ID_I2C,<br>
+                                         NULL,<br>
+                                         RTEMS_INTERRUPT_UNIQUE,<br>
+                                         (rtems_interrupt_handler) i2c_handler,<br>
+                                         softc_ptr<br>
+                                        );<br>
+  }<br>
+<br>
+  return sc;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function that would send a start condition over the I2C bus.<br>
+ *        Because of the way the BSC controller implements the I2C protocol, the<br>
+ *        start sequence is sent whenever appropriate in bcm2835_i2c_read_write.<br>
+ *        Instead this function clears the bus FIFOS before each new data<br>
+ *        transfer.<br>
+ *        This function is used by the libi2c API.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL<br>
+ */<br>
+rtems_status_code bcm2835_i2c_send_start(rtems_libi2c_bus_t * bushdl)<br>
+{<br>
+  /* Clear FIFOs. */<br>
+  BCM2835_REG(BCM2835_I2C_C) |= (3 << 4);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function that would send a stop condition over the I2C bus,<br>
+ *        however the BSC controller send this condition automatically when the<br>
+ *        DLEN (data length - the number of bytes to be transferred) register<br>
+ *        value reaches 0.<br>
+ *        For that reason, it is here just to satisfy, the libi2c API,<br>
+ *         which requires this function.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL<br>
+ */<br>
+rtems_status_code bcm2835_i2c_stop(rtems_libi2c_bus_t * bushdl)<br>
+{<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function which addresses a I2C device.<br>
+ *        This function is used by the libi2c API.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ * @param[in] addr Address of a connected I2C device<br>
+ * @param[in] rw Defines the nature of the transfer which will take place with<br>
+ *               the addressed device - 0 to write and 1 to read.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL The device has been successfully addressed.<br>
+ */<br>
+rtems_status_code<br>
+bcm2835_i2c_send_addr(rtems_libi2c_bus_t * bushdl, uint32_t addr, int rw)<br>
+{<br>
+  /* Address slave device. */<br>
+  BCM2835_REG(BCM2835_I2C_A) = addr;<br>
+<br>
+  /* Set read/write bit.<br>
+   * If writing. */<br>
+  if ( rw == 0 ) {<br>
+    BCM2835_REG(BCM2835_I2C_C) &= ~(1 << 0);<br>
+  }<br>
+  /* If reading. */<br>
+  else {<br>
+    BCM2835_REG(BCM2835_I2C_C) |= (1 << 0);<br>
+  }<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function that reads a number of bytes from the I2C bus<br>
+ *        on to a buffer.<br>
+ *        This function is used by the libi2c API.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ * @param[in] bytes Buffer where the data read from the bus will be stored.<br>
+ * @param[in] nbytes Number of bytes to be read from the bus<br>
+ *                   to the bytes buffer.<br>
+ *<br>
+ * @retval @see bcm2835_i2c_read_write().<br>
+ */<br>
+int bcm2835_i2c_read_bytes(<br>
+rtems_libi2c_bus_t * bushdl,<br>
+unsigned char *bytes,<br>
+int nbytes<br>
+)<br>
+{<br>
+  return bcm2835_i2c_read_write(bushdl, bytes, NULL, nbytes);<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function that writes a number of bytes from a buffer<br>
+ *        to the I2C bus.<br>
+ *        This function is used by the libi2c API.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ * @param[in] bytes Buffer with data to send through the bus.<br>
+ * @param[in] nbytes Number of bytes to be written from the bytes buffer<br>
+                     to the bus.<br>
+ *<br>
+ * @retval @see bcm2835_i2c_read_write().<br>
+ */<br>
+int bcm2835_i2c_write_bytes(<br>
+rtems_libi2c_bus_t * bushdl,<br>
+unsigned char *bytes,<br>
+int nbytes<br>
+)<br>
+{<br>
+  return bcm2835_i2c_read_write(bushdl, NULL, bytes, nbytes);<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function that is used to perform ioctl<br>
+ *        operations on the bus. Currently only setups<br>
+ *        the bus transfer mode, namely the bus clock divider.<br>
+ *        This function is used by the libi2c API.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ * @param[in] cmd IOCTL request command.<br>
+ * @param[in] arg Arguments needed to fulfill the requested IOCTL command.<br>
+ *<br>
+ * @retval -1 Unknown request command.<br>
+ * @retval >=0 @see bcm2835_i2c_set_tfr_mode().<br>
+ */<br>
+int bcm2835_i2c_ioctl(rtems_libi2c_bus_t * bushdl, int cmd, void *arg)<br>
+{<br>
+  switch ( cmd ) {<br>
+    case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:<br>
+<br>
+      return bcm2835_i2c_set_tfr_mode(bushdl,<br>
+                                      (const rtems_libi2c_tfr_mode_t *)arg<br>
+                                     );<br>
+<br>
+    default:<br>
+      return -1;<br>
+  }<br>
+<br>
+  return 0;<br>
+}<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/i2c/i2c_init.c b/c/src/lib/libbsp/arm/raspberrypi/i2c/i2c_init.c<br>
new file mode 100644<br>
index 0000000..3a68407<br>
--- /dev/null<br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/i2c/i2c_init.c<br>
@@ -0,0 +1,84 @@<br>
+/**<br>
+ * @file i2c_init.c<br>
+ *<br>
+ * @ingroup raspberrypi_i2c<br>
+ *<br>
+ * @brief Raspberry Pi I2C bus initialization.<br>
+ */<br>
+<br>
+/*<br>
+ *  Copyright (c) 2014 Andre Marques <andre.lousa.marques at <a href="http://gmail.com" target="_blank">gmail.com</a>><br>
+ *<br>
+ *  The license and distribution terms for this file may be<br>
+ *  found in the file LICENSE in this distribution or at<br>
+ *  <a href="http://www.rtems.org/license/LICENSE" target="_blank">http://www.rtems.org/license/LICENSE</a>.<br>
+ */<br>
+<br>
+#include <bsp/raspberrypi.h><br>
+#include <bsp/gpio.h><br>
+#include <bsp/i2c.h><br>
+<br>
+#include <libchip/mcp23008.h><br>
+<br>
+static rtems_libi2c_bus_ops_t bcm2835_i2c_ops = {<br>
+  init:             bcm2835_i2c_init,<br>
+  send_start:       bcm2835_i2c_send_start,<br>
+  send_stop:        bcm2835_i2c_stop,<br>
+  send_addr:        bcm2835_i2c_send_addr,<br>
+  read_bytes:       bcm2835_i2c_read_bytes,<br>
+  write_bytes:      bcm2835_i2c_write_bytes,<br>
+  ioctl:            bcm2835_i2c_ioctl<br>
+};<br>
+<br>
+static bcm2835_i2c_desc_t bcm2835_i2c_bus_desc = {<br>
+  {<br>
+    ops:            &bcm2835_i2c_ops,<br>
+    size:           sizeof(bcm2835_i2c_bus_desc)<br>
+  },<br>
+  {<br>
+    initialized:    0<br>
+  }<br>
+};<br>
+<br>
+/* Register drivers here for all the devices<br>
+ * which require access to the I2C bus.<br>
+ *<br>
+ * The libi2c function "rtems_libi2c_register_drv" must be used to<br>
+ * register each device driver, using the received i2c bus number.<br>
+ *<br>
+ * This function returns 0 on success. */<br>
+int BSP_i2c_register_drivers(int i2c_bus_number)<br>
+{<br>
+  int rv = 0;<br>
+<br>
+  rv = rtems_libi2c_register_drv("mcp23008", &i2c_mcp23008_drv_t, i2c_bus_number, MCP23008_ADDR);<br>
+<br>
+  return rv;<br>
+}<br>
+<br>
+int BSP_i2c_init(void)<br>
+{<br>
+  int rv;<br>
+<br>
+  /* Initialize the libi2c API. */<br>
+  rtems_libi2c_initialize ();<br>
+<br>
+  /* Enable the I2C interface on the Raspberry Pi P1 GPIO header. */<br>
+  gpio_initialize ();<br>
+<br>
+  if ( gpio_select_i2c_p1_rev2() < 0 ) {<br>
+    return RTEMS_RESOURCE_IN_USE;<br>
+  }<br>
+<br>
+  /* Register the I2C bus. */<br>
+  rv = rtems_libi2c_register_bus("/dev/i2c", &(bcm2835_i2c_bus_desc.bus_desc));<br>
+<br>
+  if ( rv < 0 ) {<br>
+    return -rv;<br>
+  }<br>
+<br>
+  /* Register SPI device drivers. */<br>
+  rv =  BSP_i2c_register_drivers(rv);<br>
+<br>
+  return 0;<br>
+}<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/i2c/spi.c b/c/src/lib/libbsp/arm/raspberrypi/i2c/spi.c<br>
new file mode 100644<br>
index 0000000..96b6db0<br>
--- /dev/null<br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/i2c/spi.c<br>
@@ -0,0 +1,608 @@<br>
+/**<br>
+ * @file spi.c<br>
+ *<br>
+ * @ingroup raspberrypi_i2c<br>
+ *<br>
+ * @brief Support for the SPI bus on the Raspberry Pi GPIO P1 header (model A/B)<br>
+ *        and GPIO J8 header on model B+.<br>
+ */<br>
+<br>
+/*<br>
+ *  Copyright (c) 2014 Andre Marques <andre.lousa.marques at <a href="http://gmail.com" target="_blank">gmail.com</a>><br>
+ *<br>
+ *  The license and distribution terms for this file may be<br>
+ *  found in the file LICENSE in this distribution or at<br>
+ *  <a href="http://www.rtems.org/license/LICENSE" target="_blank">http://www.rtems.org/license/LICENSE</a>.<br>
+ */<br>
+<br>
+/*<br>
+ * STATUS:<br>
+ * - Bi-directional mode untested<br>
+ * - Write-only devices not supported<br>
+ */<br>
+<br>
+#include <bsp.h><br>
+#include <bsp/raspberrypi.h><br>
+#include <bsp/gpio.h><br>
+#include <bsp/irq.h><br>
+#include <bsp/i2c.h><br>
+#include <assert.h><br>
+<br>
+/**<br>
+ * @brief Calculates a clock divider to be used with the GPU core clock rate<br>
+ *        to set a SPI clock rate the closest (<=) to a desired frequency.<br>
+ *<br>
+ * @param[in] clock_hz The desired clock frequency for the SPI bus operation.<br>
+ * @param[out] clock_divider Pointer to a variable where the calculated<br>
+ *                          clock divider will be stored.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Successfully calculated a valid clock divider.<br>
+ * @retval RTEMS_INVALID_NUMBER The resulting clock divider is invalid, due to<br>
+ *                              an invalid GPU_CORE_CLOCK_RATE<br>
+ *                              or clock_hz value.<br>
+ */<br>
+static rtems_status_code<br>
+bcm2835_spi_calculate_clock_divider(uint32_t clock_hz, uint16_t *clock_divider)<br>
+{<br>
+  uint16_t divider;<br>
+  uint32_t clock_rate;<br>
+<br>
+  assert( clock_hz > 0 );<br>
+<br>
+  /* Calculates an initial clock divider. */<br>
+  divider = GPU_CORE_CLOCK_RATE / clock_hz;<br>
+<br>
+  /* Because the divider must be a power of two (as per the BCM2835 datasheet),<br>
+   * calculate the next greater power of two. */<br>
+  --divider;<br>
+<br>
+  divider |= (divider >> 1);<br>
+  divider |= (divider >> 2);<br>
+  divider |= (divider >> 4);<br>
+  divider |= (divider >> 8);<br>
+<br>
+  ++divider;<br>
+<br>
+  clock_rate = GPU_CORE_CLOCK_RATE / divider;<br>
+<br>
+  /* If the resulting clock rate is greater than the desired frequency,<br>
+   * try the next greater power of two divider. */<br>
+  while ( clock_rate > clock_hz ) {<br>
+    divider = (divider << 1);<br>
+<br>
+    clock_rate = GPU_CORE_CLOCK_RATE / divider;<br>
+  }<br>
+<br>
+  *clock_divider = divider;<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Set the SPI bus transfer mode.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ * @param[in] tfr_mode Pointer to a libi2c API transfer mode data structure.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Successfully setup the bus transfer mode as desired.<br>
+ * @retval RTEMS_INVALID_NUMBER This can have two meanings:<br>
+ *                              1. The specified number of bytes per char is not<br>
+ *                                 8, 16, 24 or 32;<br>
+ *                              2. @see bcm2835_spi_calculate_clock_divider()<br>
+ */<br>
+static rtems_status_code bcm2835_spi_set_tfr_mode(<br>
+rtems_libi2c_bus_t *bushdl,<br>
+const rtems_libi2c_tfr_mode_t *tfr_mode<br>
+)<br>
+{<br>
+  bcm2835_spi_softc_t *softc_ptr = &(((bcm2835_spi_desc_t *)(bushdl))->softc);<br>
+  rtems_status_code sc = RTEMS_SUCCESSFUL;<br>
+  uint16_t clock_divider;<br>
+<br>
+  /* Set the dummy character. */<br>
+  softc_ptr->dummy_char = tfr_mode->idle_char;<br>
+<br>
+  /* Calculate the most appropriate clock divider. */<br>
+  sc = bcm2835_spi_calculate_clock_divider(tfr_mode->baudrate, &clock_divider);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    return sc;<br>
+  }<br>
+<br>
+  /* Set the bus clock divider. */<br>
+  BCM2835_REG(BCM2835_SPI_CLK) = clock_divider;<br>
+<br>
+  /* Calculate how many bytes each character has.<br>
+   * Only multiples of 8 bits are accepted for the transaction. */<br>
+  switch ( tfr_mode->bits_per_char ) {<br>
+    case 8:<br>
+    case 16:<br>
+    case 24:<br>
+    case 32:<br>
+      softc_ptr->bytes_per_char = tfr_mode->bits_per_char / 8;<br>
+      break;<br>
+<br>
+    default:<br>
+      return RTEMS_INVALID_NUMBER;<br>
+  }<br>
+<br>
+  /* Check the data mode (most or least significant bit first) and calculate<br>
+   * the correcting bit shift value to apply on the data before sending. */<br>
+  if ( tfr_mode->lsb_first ) {<br>
+    softc_ptr->bit_shift = 32 - tfr_mode->bits_per_char;<br>
+  }<br>
+  /* If MSB first. */<br>
+  else {<br>
+    softc_ptr->bit_shift = 0;<br>
+  }<br>
+<br>
+  /* Set SPI clock polarity.<br>
+   * If clock_inv is TRUE, the clock is active high.*/<br>
+  if ( tfr_mode->clock_inv ) {<br>
+    /* Rest state of clock is low. */<br>
+    BCM2835_REG(BCM2835_SPI_CS) &= ~(1 << 3);<br>
+  }<br>
+  else {<br>
+    /* Rest state of clock is high. */<br>
+    BCM2835_REG(BCM2835_SPI_CS) |= (1 << 3);<br>
+  }<br>
+<br>
+  /* Set SPI clock phase.<br>
+   * If clock_phs is true, clock starts toggling<br>
+   * at the start of the data transfer. */<br>
+  if ( tfr_mode->clock_phs ) {<br>
+    /* First SCLK transition at beginning of data bit. */<br>
+    BCM2835_REG(BCM2835_SPI_CS) |= (1 << 2);<br>
+  }<br>
+  else {<br>
+    /* First SCLK transition at middle of data bit. */<br>
+    BCM2835_REG(BCM2835_SPI_CS) &= ~(1 << 2);<br>
+  }<br>
+<br>
+  return sc;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Reads/writes to/from the SPI bus.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ * @param[in] rd_buf Read buffer. If not NULL the function will read from<br>
+ *                   the bus and store the read on this buffer.<br>
+ * @param[in] wr_buf Write buffer. If not NULL the function will write the<br>
+ *                   contents of this buffer to the bus.<br>
+ * @param[in] buffer_size Size of the non-NULL buffer.<br>
+ *<br>
+ * @retval -1 Could not send/receive data to/from the bus.<br>
+ * @retval >=0 The number of bytes read/written.<br>
+ */<br>
+static int bcm2835_spi_read_write(<br>
+rtems_libi2c_bus_t * bushdl,<br>
+unsigned char *rd_buf,<br>
+const unsigned char *wr_buf,<br>
+int buffer_size<br>
+)<br>
+{<br>
+  bcm2835_spi_softc_t *softc_ptr = &(((bcm2835_spi_desc_t *)(bushdl))->softc);<br>
+<br>
+  uint8_t bytes_per_char = softc_ptr->bytes_per_char;<br>
+  uint8_t bit_shift =  softc_ptr->bit_shift;<br>
+  uint32_t dummy_char = softc_ptr->dummy_char;<br>
+<br>
+  uint32_t bytes_sent = buffer_size;<br>
+  uint32_t fifo_data;<br>
+<br>
+  /* Clear SPI bus FIFOs. */<br>
+  BCM2835_REG(BCM2835_SPI_CS) |= (3 << 4);<br>
+<br>
+  /* Set SPI transfer active. */<br>
+  BCM2835_REG(BCM2835_SPI_CS) |= (1 << 7);<br>
+<br>
+  /* If using the SPI bus in interrupt-driven mode. */<br>
+  if ( SPI_IO_MODE == 1 ) {<br>
+    softc_ptr->irq_write = 1;<br>
+<br>
+    BCM2835_REG(BCM2835_SPI_CS) |= (1 << 9);<br>
+<br>
+    if (<br>
+      rtems_semaphore_obtain(softc_ptr->irq_sema_id, RTEMS_WAIT, 50) !=<br>
+      RTEMS_SUCCESSFUL<br>
+    ) {<br>
+      return -1;<br>
+    }<br>
+  }<br>
+  /* If using the bus in polling mode. */<br>
+  else {<br>
+    /* Poll TXD bit until there is space to write at least one byte<br>
+     * on the TX FIFO. */<br>
+    while ( (BCM2835_REG(BCM2835_SPI_CS) & (1 << 18)) == 0 ) {<br>
+      ;<br>
+    }<br>
+  }<br>
+<br>
+  /* While there is data to be transferred. */<br>
+  while ( buffer_size >= bytes_per_char ) {<br>
+    /* If reading from the bus, send a dummy character to the device. */<br>
+    if ( rd_buf != NULL ) {<br>
+      BCM2835_REG(BCM2835_SPI_FIFO) = dummy_char;<br>
+    }<br>
+    /* If writing to the bus, move the buffer data to the TX FIFO. */<br>
+    else {<br>
+      switch ( bytes_per_char ) {<br>
+        case 1:<br>
+          BCM2835_REG(BCM2835_SPI_FIFO) = (((*wr_buf) & 0xFF) << bit_shift);<br>
+          break;<br>
+<br>
+        case 2:<br>
+          BCM2835_REG(BCM2835_SPI_FIFO) = (((*wr_buf) & 0xFFFF) << bit_shift);<br>
+          break;<br>
+<br>
+        case 3:<br>
+          BCM2835_REG(BCM2835_SPI_FIFO) = (((*wr_buf) & 0xFFFFFF) << bit_shift);<br>
+          break;<br>
+<br>
+        case 4:<br>
+          BCM2835_REG(BCM2835_SPI_FIFO) = ((*wr_buf) << bit_shift);<br>
+          break;<br>
+<br>
+        default:<br>
+          return -1;<br>
+      }<br>
+<br>
+      wr_buf += bytes_per_char;<br>
+<br>
+      buffer_size -= bytes_per_char;<br>
+    }<br>
+<br>
+    /* If using bi-directional SPI. */<br>
+    if ( softc_ptr->bidirectional == 1 ) {<br>
+      /* Change bus direction to read from the slave device. */<br>
+      BCM2835_REG(BCM2835_SPI_CS) |= (1 << 12);<br>
+    }<br>
+<br>
+    /* If using the SPI bus in interrupt-driven mode. */<br>
+    if ( SPI_IO_MODE == 1 ) {<br>
+      softc_ptr->irq_write = 0;<br>
+<br>
+      BCM2835_REG(BCM2835_SPI_CS) |= (1 << 9);<br>
+<br>
+      if (<br>
+        rtems_semaphore_obtain(softc_ptr->irq_sema_id, RTEMS_WAIT, 50) !=<br>
+        RTEMS_SUCCESSFUL<br>
+      ) {<br>
+        return -1;<br>
+      }<br>
+    }<br>
+    /* If using the bus in polling mode. */<br>
+    else {<br>
+      /* Poll the Done bit until the data transfer is complete. */<br>
+      while ( (BCM2835_REG(BCM2835_SPI_CS) & (1 << 16)) == 0 ) {<br>
+        ;<br>
+      }<br>
+<br>
+      /* Poll the RXD bit until there is at least one byte<br>
+       * on the RX FIFO to be read. */<br>
+      while ( (BCM2835_REG(BCM2835_SPI_CS) & (1 << 17)) == 0 ) {<br>
+        ;<br>
+      }<br>
+    }<br>
+<br>
+    /* If writing to the bus, read the dummy char sent by the slave device. */<br>
+    if ( rd_buf == NULL ) {<br>
+      fifo_data = BCM2835_REG(BCM2835_SPI_FIFO) & 0xFF;<br>
+    }<br>
+<br>
+    /* If reading from the bus, retrieve data from the RX FIFO and<br>
+     * store it on the buffer. */<br>
+    if ( rd_buf != NULL ) {<br>
+      switch ( bytes_per_char ) {<br>
+        case 1:<br>
+          fifo_data = BCM2835_REG(BCM2835_SPI_FIFO) & 0xFF;<br>
+          (*rd_buf) = (fifo_data >> bit_shift);<br>
+          break;<br>
+<br>
+        case 2:<br>
+          fifo_data = BCM2835_REG(BCM2835_SPI_FIFO) & 0xFFFF;<br>
+          (*rd_buf) = (fifo_data >> bit_shift);<br>
+          break;<br>
+<br>
+        case 3:<br>
+          fifo_data = BCM2835_REG(BCM2835_SPI_FIFO) & 0xFFFFFF;<br>
+          (*rd_buf) = (fifo_data >> bit_shift);<br>
+          break;<br>
+<br>
+        case 4:<br>
+          fifo_data = BCM2835_REG(BCM2835_SPI_FIFO);<br>
+          (*rd_buf) = (fifo_data >> bit_shift);<br>
+          break;<br>
+<br>
+        default:<br>
+          return -1;<br>
+      }<br>
+<br>
+      rd_buf += bytes_per_char;<br>
+<br>
+      buffer_size -= bytes_per_char;<br>
+    }<br>
+<br>
+    /* If using bi-directional SPI. */<br>
+    if ( softc_ptr->bidirectional == 1 ) {<br>
+      /* Restore bus direction to write to the slave. */<br>
+      BCM2835_REG(BCM2835_SPI_CS) &= ~(1 << 12);<br>
+    }<br>
+  }<br>
+<br>
+  /* If using the SPI bus in interrupt-driven mode. */<br>
+  if ( SPI_IO_MODE == 1 ) {<br>
+    softc_ptr->irq_write = 1;<br>
+<br>
+    BCM2835_REG(BCM2835_SPI_CS) |= (1 << 9);<br>
+<br>
+    if (<br>
+      rtems_semaphore_obtain(softc_ptr->irq_sema_id, RTEMS_WAIT, 50) !=<br>
+      RTEMS_SUCCESSFUL<br>
+    ) {<br>
+      return -1;<br>
+    }<br>
+  }<br>
+  /* If using the bus in polling mode. */<br>
+  else {<br>
+    /* Poll the Done bit until the data transfer is complete. */<br>
+    while ( (BCM2835_REG(BCM2835_SPI_CS) & (1 << 16)) == 0 ) {<br>
+      ;<br>
+    }<br>
+  }<br>
+<br>
+  bytes_sent -= buffer_size;<br>
+<br>
+  return bytes_sent;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Handler function that is called on any SPI interrupt.<br>
+ *<br>
+ *        There are 2 situations that can generate an interrupt:<br>
+ *<br>
+ *        1. Transfer (read/write) complete;<br>
+ *        2. RX FIFO full.<br>
+ *<br>
+ *        Because the 2. situation is not useful to many applications,<br>
+ *        the only interrupt that is generated and handled is the<br>
+ *        transfer complete interrupt.<br>
+ *<br>
+ *        The objective of the handler is then, depending on the transfer<br>
+ *        context (reading or writing on the bus), to check if there is enough<br>
+ *        space available on the TX FIFO to send data over the bus (if writing)<br>
+ *        or if the slave device has sent enough data to be fetched from the<br>
+ *        RX FIFO (if reading).<br>
+ *<br>
+ *        When any of these two conditions occur, disables further interrupts<br>
+ *        to be generated and releases a irq semaphore which will allow the<br>
+ *        following transfer to proceed.<br>
+ *<br>
+ * @param[in] arg Void pointer to the bus data structure.<br>
+ */<br>
+static void spi_handler(void* arg)<br>
+{<br>
+  bcm2835_spi_softc_t *softc_ptr = (bcm2835_spi_softc_t *) arg;<br>
+<br>
+  /* If waiting to write to the bus, expect the TXD bit to be set, or<br>
+   * if waiting to read from the bus, expect the RXD bit to be set<br>
+   * before releasing the irq semaphore. */<br>
+  if (<br>
+    ( softc_ptr->irq_write == 1 && (BCM2835_REG(BCM2835_SPI_CS) & (1 << 18)) != 0 ) ||<br>
+    ( softc_ptr->irq_write == 0 && (BCM2835_REG(BCM2835_SPI_CS) & (1 << 17)) != 0 )<br>
+  ) {<br>
+    /* Disable the SPI interrupt generation when a transfer is complete. */<br>
+    BCM2835_REG(BCM2835_SPI_CS) &= ~(1 << 9);<br>
+<br>
+    /* Release the irq semaphore. */<br>
+    rtems_semaphore_release(softc_ptr->irq_sema_id);<br>
+  }<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function to initialize the SPI bus.<br>
+ *        This function is used by the libi2c API.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL SPI bus successfully initialized.<br>
+ * @retval Any other status code @see rtems_semaphore_create() and<br>
+ *         @see rtems_interrupt_handler_install().<br>
+ */<br>
+rtems_status_code bcm2835_spi_init(rtems_libi2c_bus_t * bushdl)<br>
+{<br>
+  bcm2835_spi_softc_t *softc_ptr = &(((bcm2835_spi_desc_t *)(bushdl))->softc);<br>
+  rtems_status_code sc = RTEMS_SUCCESSFUL;<br>
+<br>
+  if ( softc_ptr->initialized == 1 ) {<br>
+    return sc;<br>
+  }<br>
+<br>
+  softc_ptr->initialized = 1;<br>
+<br>
+  /* TODO: This should be set on the device driver itself and configured<br>
+   * during the bus transfer mode setup or another ioctl request. */<br>
+  softc_ptr->bidirectional = 0;<br>
+<br>
+  /* If using the SPI bus in interrupt-driven mode. */<br>
+  if ( SPI_IO_MODE == 1 ) {<br>
+    sc = rtems_semaphore_create(rtems_build_name('s','p','i','s'),<br>
+                                0,<br>
+                                RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE,<br>
+                                0,<br>
+                                &softc_ptr->irq_sema_id<br>
+                               );<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+    }<br>
+<br>
+    sc = rtems_interrupt_handler_install(BCM2835_IRQ_ID_SPI,<br>
+                                         NULL,<br>
+                                         RTEMS_INTERRUPT_UNIQUE,<br>
+                                         (rtems_interrupt_handler) spi_handler,<br>
+                                         softc_ptr<br>
+                                        );<br>
+  }<br>
+<br>
+  return sc;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function that would send a start condition over an I2C bus.<br>
+ *        As it is not required to access a SPI bus it is here just to satisfy<br>
+ *        the libi2c API, which requires this function.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL<br>
+ */<br>
+rtems_status_code bcm2835_spi_send_start(rtems_libi2c_bus_t * bushdl)<br>
+{<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function that terminates a SPI transfer.<br>
+ *        It stops the SPI transfer and unselects the current SPI slave device.<br>
+ *        This function is used by the libi2c API.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL The slave device has been successfully unselected.<br>
+ * @retval RTEMS_INVALID_ADDRESS The stored slave address is neither 0 or 1.<br>
+ */<br>
+rtems_status_code bcm2835_spi_stop(rtems_libi2c_bus_t * bushdl)<br>
+{<br>
+  bcm2835_spi_softc_t *softc_ptr = &(((bcm2835_spi_desc_t *)(bushdl))->softc);<br>
+<br>
+  uint32_t addr = softc_ptr->current_slave_addr;<br>
+  uint32_t chip_select_bit = 21 + addr;<br>
+<br>
+  /* Set SPI transfer as not active. */<br>
+  BCM2835_REG(BCM2835_SPI_CS) &= ~(1 << 7);<br>
+<br>
+  /* Unselect the active SPI slave. */<br>
+  switch ( addr ) {<br>
+    case 0:<br>
+    case 1:<br>
+      BCM2835_REG(BCM2835_SPI_CS) |= (1 << chip_select_bit);<br>
+<br>
+      break;<br>
+<br>
+    default:<br>
+      return RTEMS_INVALID_ADDRESS;<br>
+  }<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function which addresses a SPI slave device.<br>
+ *        This function is used by the libi2c API.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ * @param[in] addr SPI slave select line address (0 for CE0 or 1 for CE1).<br>
+ * @param[in] rw This values is unnecessary to address a SPI device and its<br>
+ *               presence here is only to fulfill a libi2c requirement.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL The slave device has been successfully addressed.<br>
+ * @retval RTEMS_INVALID_ADDRESS The received address is neither 0 or 1.<br>
+ */<br>
+rtems_status_code<br>
+bcm2835_spi_send_addr(rtems_libi2c_bus_t * bushdl, uint32_t addr, int rw)<br>
+{<br>
+  bcm2835_spi_softc_t *softc_ptr = &(((bcm2835_spi_desc_t *)(bushdl))->softc);<br>
+<br>
+  /* Calculates the bit corresponding to the received address<br>
+   * on the SPI control register. */<br>
+  uint32_t chip_select_bit = 21 + addr;<br>
+<br>
+  /* Save which slave will be currently addressed,<br>
+   * so it can be unselected later. */<br>
+  softc_ptr->current_slave_addr = addr;<br>
+<br>
+  /* Select one of the two available SPI slave address lines. */<br>
+  switch ( addr ) {<br>
+    case 0:<br>
+    case 1:<br>
+      BCM2835_REG(BCM2835_SPI_CS) &= ~(1 << chip_select_bit);<br>
+      break;<br>
+<br>
+    default:<br>
+      return RTEMS_INVALID_ADDRESS;<br>
+  }<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function that reads a number of bytes from the SPI bus<br>
+ *        on to a buffer.<br>
+ *        This function is used by the libi2c API.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ * @param[in] bytes Buffer where the data read from the bus will be stored.<br>
+ * @param[in] nbytes Number of bytes to be read from the bus to the bytes buffer.<br>
+ *<br>
+ * @retval @see bcm2835_spi_read_write().<br>
+ */<br>
+int bcm2835_spi_read_bytes(<br>
+rtems_libi2c_bus_t * bushdl,<br>
+unsigned char *bytes,<br>
+int nbytes<br>
+)<br>
+{<br>
+  return bcm2835_spi_read_write(bushdl, bytes, NULL, nbytes);<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function that writes a number of bytes from a buffer<br>
+ *        to the SPI bus.<br>
+ *        This function is used by the libi2c API.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ * @param[in] bytes Buffer with data to send over the SPI bus.<br>
+ * @param[in] nbytes Number of bytes to be written from the bytes buffer<br>
+                     to the bus.<br>
+ *<br>
+ * @retval @see bcm2835_spi_read_write().<br>
+ */<br>
+int bcm2835_spi_write_bytes(<br>
+rtems_libi2c_bus_t * bushdl,<br>
+unsigned char *bytes,<br>
+int nbytes<br>
+)<br>
+{<br>
+  return bcm2835_spi_read_write(bushdl, NULL, bytes, nbytes);<br>
+}<br>
+<br>
+/**<br>
+ * @brief Low level function that is used to perform ioctl<br>
+ *        operations on the bus. Currently only setups<br>
+ *        the bus transfer mode.<br>
+ *        This function is used by the libi2c API.<br>
+ *<br>
+ * @param[in] bushdl Pointer to the libi2c API bus driver data structure.<br>
+ * @param[in] cmd IOCTL request command.<br>
+ * @param[in] arg Arguments needed to fulfill the requested IOCTL command.<br>
+ *<br>
+ * @retval -1 Unknown request command.<br>
+ * @retval >=0 @see bcm2835_spi_set_tfr_mode().<br>
+ */<br>
+int bcm2835_spi_ioctl(rtems_libi2c_bus_t * bushdl, int cmd, void *arg)<br>
+{<br>
+  switch ( cmd ) {<br>
+    case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:<br>
+<br>
+      return bcm2835_spi_set_tfr_mode(bushdl,<br>
+                                      (const rtems_libi2c_tfr_mode_t *)arg<br>
+                                     );<br>
+<br>
+    default:<br>
+      return -1;<br>
+  }<br>
+<br>
+  return 0;<br>
+}<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/i2c/spi_init.c b/c/src/lib/libbsp/arm/raspberrypi/i2c/spi_init.c<br>
new file mode 100644<br>
index 0000000..1e1a6cc<br>
--- /dev/null<br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/i2c/spi_init.c<br>
@@ -0,0 +1,85 @@<br>
+/**<br>
+ * @file spi_init.c<br>
+ *<br>
+ * @ingroup raspberrypi_i2c<br>
+ *<br>
+ * @brief Raspberry Pi SPI bus initialization.<br>
+ */<br>
+<br>
+/*<br>
+ *  Copyright (c) 2014 Andre Marques <andre.lousa.marques at <a href="http://gmail.com" target="_blank">gmail.com</a>><br>
+ *<br>
+ *  The license and distribution terms for this file may be<br>
+ *  found in the file LICENSE in this distribution or at<br>
+ *  <a href="http://www.rtems.org/license/LICENSE" target="_blank">http://www.rtems.org/license/LICENSE</a>.<br>
+ */<br>
+<br>
+#include <bsp/raspberrypi.h><br>
+#include <bsp/gpio.h><br>
+#include <bsp/i2c.h><br>
+<br>
+static rtems_libi2c_bus_ops_t bcm2835_spi_ops = {<br>
+  init:        bcm2835_spi_init,<br>
+  send_start:  bcm2835_spi_send_start,<br>
+  send_stop:   bcm2835_spi_stop,<br>
+  send_addr:   bcm2835_spi_send_addr,<br>
+  read_bytes:  bcm2835_spi_read_bytes,<br>
+  write_bytes: bcm2835_spi_write_bytes,<br>
+  ioctl:       bcm2835_spi_ioctl<br>
+};<br>
+<br>
+static bcm2835_spi_desc_t bcm2835_spi_bus_desc = {<br>
+  {<br>
+    ops:  &bcm2835_spi_ops,<br>
+    size: sizeof(bcm2835_spi_bus_desc)<br>
+  },<br>
+  {<br>
+    initialized:    0<br>
+  }<br>
+};<br>
+<br>
+/* Register drivers here for all the devices<br>
+ * which require access to the SPI bus.<br>
+ *<br>
+ * The libi2c function "rtems_libi2c_register_drv" must be used to<br>
+ * register each device driver, using the received spi bus number.<br>
+ *<br>
+ * This function returns 0 on success. */<br>
+int BSP_spi_register_drivers(int spi_bus_number)<br>
+{<br>
+  int rv = 0;<br>
+<br>
+  return rv;<br>
+}<br>
+<br>
+int BSP_spi_init(void)<br>
+{<br>
+  int rv;<br>
+<br>
+  /* Initialize the libi2c API. */<br>
+  rtems_libi2c_initialize ();<br>
+<br>
+  /* Enable the SPI interface on the Raspberry Pi P1 GPIO header. */<br>
+  gpio_initialize ();<br>
+<br>
+  if ( gpio_select_spi_p1() < 0 ) {<br>
+    return RTEMS_RESOURCE_IN_USE;<br>
+  }<br>
+<br>
+  /* Clear SPI control register and clear SPI FIFOs. */<br>
+  BCM2835_REG(BCM2835_SPI_CS) = 0x0000030;<br>
+<br>
+  /* Register the SPI bus. */<br>
+  rv = rtems_libi2c_register_bus("/dev/spi", &(bcm2835_spi_bus_desc.bus_desc));<br>
+<br>
+  if ( rv < 0 ) {<br>
+    return rv;<br>
+  }<br>
+<br>
+  /* Register SPI device drivers. */<br>
+  rv =  BSP_spi_register_drivers(rv);<br>
+<br>
+  return rv;<br>
+}<br>
+<br>
+<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/include/gpio.h b/c/src/lib/libbsp/arm/raspberrypi/include/gpio.h<br>
new file mode 100644<br>
index 0000000..d8c8b08<br>
--- /dev/null<br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/include/gpio.h<br>
@@ -0,0 +1,210 @@<br>
+/**<br>
+ * @file gpio.h<br>
+ *<br>
+ * @ingroup raspberrypi_gpio<br>
+ *<br>
+ * @brief Raspberry Pi specific GPIO definitions.<br>
+ */<br>
+<br>
+/*<br>
+ *  Copyright (c) 2014 Andre Marques <andre.lousa.marques at <a href="http://gmail.com" target="_blank">gmail.com</a>><br>
+ *<br>
+ *  The license and distribution terms for this file may be<br>
+ *  found in the file LICENSE in this distribution or at<br>
+ *  <a href="http://www.rtems.org/license/LICENSE" target="_blank">http://www.rtems.org/license/LICENSE</a>.<br>
+ */<br>
+<br>
+#ifndef LIBBSP_ARM_RASPBERRYPI_GPIO_H<br>
+#define LIBBSP_ARM_RASPBERRYPI_GPIO_H<br>
+<br>
+#include <rtems.h><br>
+<br>
+#ifdef __cplusplus<br>
+extern "C" {<br>
+#endif /* __cplusplus */<br>
+<br>
+/**<br>
+ * @brief  Number of total GPIOS on the Raspberry Pi,<br>
+ *         including inaccessible ones.<br>
+ */<br>
+#define GPIO_PIN_COUNT 54<br>
+<br>
+/**<br>
+ * @brief  Highest GPIO index directly accessible on the Raspberry Pi board.<br>
+ */<br>
+#define GPIO_EXTERNAL_TOP_PIN 32<br>
+<br>
+/**<br>
+ * @brief The set of possible configurations for a GPIO pull-up resistor.<br>
+ *<br>
+ * Enumerated type to define the possible pull-up resistor configuratons<br>
+ * for an input pin.<br>
+ */<br>
+typedef enum<br>
+{<br>
+  PULL_UP=1,<br>
+  PULL_DOWN,<br>
+  NO_PULL_RESISTOR<br>
+} rpi_gpio_input_mode;<br>
+<br>
+/**<br>
+ * @brief The set of possible functions a pin can have.<br>
+ *<br>
+ * Enumerated type to define a pin function.<br>
+ */<br>
+typedef enum<br>
+{<br>
+  DIGITAL_INPUT=0,<br>
+  DIGITAL_OUTPUT,<br>
+  ALT_FUNC_5,<br>
+  ALT_FUNC_4,<br>
+  ALT_FUNC_0,<br>
+  ALT_FUNC_1,<br>
+  ALT_FUNC_2,<br>
+  ALT_FUNC_3,<br>
+<br>
+  NOT_USED<br>
+} rpi_pin;<br>
+<br>
+/**<br>
+ * @brief The set of possible interrupts an input pin can generate.<br>
+ *<br>
+ * Enumerated type to define an input pin interrupt.<br>
+ */<br>
+typedef enum<br>
+{<br>
+  FALLING_EDGE,<br>
+  RISING_EDGE,<br>
+  BOTH_EDGES,<br>
+  LOW_LEVEL,<br>
+  HIGH_LEVEL,<br>
+  BOTH_LEVELS,<br>
+  NONE<br>
+} gpio_interrupt;<br>
+<br>
+/**<br>
+ * @brief Object containing relevant information to a interrupt handler.<br>
+ *<br>
+ * Encapsulates relevant data for a GPIO interrupt handler.<br>
+ */<br>
+typedef struct<br>
+{<br>
+  int pin_number;<br>
+<br>
+  void (*handler) (void);<br>
+<br>
+  int debouncing_tick_count;<br>
+<br>
+  rtems_interval last_isr_tick;<br>
+<br>
+} handler_arguments;<br>
+<br>
+/**<br>
+ * @brief Object containing information on a GPIO pin.<br>
+ *<br>
+ * Encapsulates relevant data about a GPIO pin.<br>
+ */<br>
+typedef struct<br>
+{<br>
+  /* The pin type */<br>
+  rpi_pin pin_type;<br>
+<br>
+  /* Interrupt handler arguments*/<br>
+  handler_arguments h_args;<br>
+<br>
+  gpio_interrupt enabled_interrupt;<br>
+<br>
+  /* GPIO input pin mode. */<br>
+  rpi_gpio_input_mode input_mode;<br>
+<br>
+} rpi_gpio_pin;<br>
+<br>
+/** @} */<br>
+<br>
+/**<br>
+ * @name gpio Usage<br>
+ *<br>
+ * @{<br>
+ */<br>
+<br>
+/**<br>
+ * @brief Initializes the GPIO API.<br>
+ */<br>
+extern void gpio_initialize(void);<br>
+<br>
+/**<br>
+ * @brief Turns on the given pin.<br>
+ */<br>
+extern rtems_status_code gpio_set(int pin);<br>
+<br>
+/**<br>
+ * @brief Turns off the given pin.<br>
+ */<br>
+extern rtems_status_code gpio_clear(int pin);<br>
+<br>
+/**<br>
+ * @brief Returns the current value of a GPIO pin.<br>
+ */<br>
+extern int gpio_get_value(int pin);<br>
+<br>
+/**<br>
+ * @brief Selects a GPIO pin for a specific function.<br>
+ */<br>
+extern rtems_status_code gpio_select_pin(int pin, rpi_pin type);<br>
+<br>
+/**<br>
+ * @brief Setups a JTAG pin configuration.<br>
+ */<br>
+extern rtems_status_code gpio_select_jtag(void);<br>
+<br>
+/**<br>
+ * @brief Setups the SPI interface on the RPI P1 GPIO header.<br>
+ */<br>
+extern rtems_status_code gpio_select_spi_p1(void);<br>
+<br>
+/**<br>
+ * @brief Setups the I2C interface on the main (P1) GPIO pin header (rev2).<br>
+ */<br>
+extern rtems_status_code gpio_select_i2c_p1_rev2(void);<br>
+<br>
+/**<br>
+ * @brief Configures a input GPIO pin pull-up resistor.<br>
+ */<br>
+extern rtems_status_code gpio_input_mode(int pin, rpi_gpio_input_mode mode);<br>
+<br>
+/**<br>
+ * @brief Configures several input GPIO pins to the same pull-up resistor setup.<br>
+ */<br>
+extern rtems_status_code<br>
+gpio_setup_input_mode(int *pin, int pin_count, rpi_gpio_input_mode mode);<br>
+<br>
+/**<br>
+ * @brief Discards any configuration made on this pin.<br>
+ */<br>
+extern rtems_status_code gpio_disable_pin(int dev_pin);<br>
+<br>
+/**<br>
+ * @brief Debouces a switch by requiring a number of clock ticks to<br>
+ *        pass between interruts.<br>
+ */<br>
+extern rtems_status_code gpio_debounce_switch(int pin, int ticks);<br>
+<br>
+/**<br>
+ * @brief Enables interrupts on the given GPIO pin.<br>
+ */<br>
+extern rtems_status_code gpio_enable_interrupt(<br>
+int dev_pin,<br>
+gpio_interrupt interrupt,<br>
+void (*handler) (void)<br>
+);<br>
+<br>
+/**<br>
+ * @brief Disables any interrupt enabled on the given GPIO pin.<br>
+ */<br>
+extern rtems_status_code gpio_disable_interrupt(int dev_pin);<br>
+<br>
+#ifdef __cplusplus<br>
+}<br>
+#endif /* __cplusplus */<br>
+<br>
+#endif /* LIBBSP_ARM_RASPBERRYPI_GPIO_H */<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/include/i2c.h b/c/src/lib/libbsp/arm/raspberrypi/include/i2c.h<br>
new file mode 100644<br>
index 0000000..3224048<br>
--- /dev/null<br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/include/i2c.h<br>
@@ -0,0 +1,183 @@<br>
+/**<br>
+ * @file i2c.h<br>
+ *<br>
+ * @ingroup raspberrypi_i2c<br>
+ *<br>
+ * @brief Raspberry Pi specific I2C and SPI definitions.<br>
+ */<br>
+<br>
+/*<br>
+ *  Copyright (c) 2014 Andre Marques <andre.lousa.marques at <a href="http://gmail.com" target="_blank">gmail.com</a>><br>
+ *<br>
+ *  The license and distribution terms for this file may be<br>
+ *  found in the file LICENSE in this distribution or at<br>
+ *  <a href="http://www.rtems.org/license/LICENSE" target="_blank">http://www.rtems.org/license/LICENSE</a>.<br>
+ */<br>
+<br>
+#ifndef LIBBSP_ARM_RASPBERRYPI_I2C_H<br>
+#define LIBBSP_ARM_RASPBERRYPI_I2C_H<br>
+<br>
+#include <rtems/libi2c.h><br>
+<br>
+/**<br>
+ * @name SPI constants.<br>
+ *<br>
+ * @{<br>
+ */<br>
+<br>
+/**<br>
+ * @brief  GPU processor core clock rate in Hz.<br>
+ *<br>
+ * Unless configured otherwise on a "config.txt" file present on the SD card<br>
+ * the GPU defaults to 250 MHz. Currently only 250 MHz is supported.<br>
+ */<br>
+<br>
+/* TODO: It would be nice if this value could be probed at startup, probably<br>
+ *       using the Mailbox interface since the usual way of setting this on<br>
+ *       the hardware is through a "config.txt" text file on the SD card.<br>
+ *       Having this setup on the <a href="http://configure.ac" target="_blank">configure.ac</a> script would require changing<br>
+ *       the same setting on two different places. */<br>
+#define GPU_CORE_CLOCK_RATE 250000000<br>
+<br>
+/** @} */<br>
+<br>
+/**<br>
+ * @name  SPI data structures.<br>
+ *<br>
+ * @{<br>
+ */<br>
+<br>
+/**<br>
+ * @brief Object containing the SPI bus configuration settings.<br>
+ *<br>
+ * Encapsulates the current SPI bus configuration.<br>
+ */<br>
+typedef struct {<br>
+  int                 initialized;<br>
+  uint8_t             bytes_per_char;<br>
+<br>
+  /* Shift to be applied on data transfers with<br>
+   * least significative bit first (LSB) devices. */<br>
+  uint8_t             bit_shift;<br>
+  uint32_t            dummy_char;<br>
+<br>
+  /* If set to 0 uses 3-wire SPI, with 2 separate data lines (MOSI and MISO),<br>
+   * if set to 1 uses 2-wire SPI, where the MOSI data line doubles as the<br>
+   * slave out (SO) and slave in (SI) data lines. */<br>
+  int                 bidirectional;<br>
+  uint32_t            current_slave_addr;<br>
+  rtems_id            irq_sema_id;<br>
+  int                 irq_write;<br>
+} bcm2835_spi_softc_t;<br>
+<br>
+typedef struct {<br>
+  rtems_libi2c_bus_t  bus_desc;<br>
+  bcm2835_spi_softc_t softc;<br>
+} bcm2835_spi_desc_t;<br>
+<br>
+/** @} */<br>
+<br>
+/**<br>
+ * @name  SPI directives.<br>
+ *<br>
+ * @{<br>
+ */<br>
+<br>
+rtems_status_code bcm2835_spi_init(rtems_libi2c_bus_t * bushdl);<br>
+<br>
+rtems_status_code bcm2835_spi_send_start(rtems_libi2c_bus_t * bushdl);<br>
+<br>
+rtems_status_code bcm2835_spi_stop(rtems_libi2c_bus_t * bushdl);<br>
+<br>
+rtems_status_code<br>
+bcm2835_spi_send_addr(rtems_libi2c_bus_t * bushdl, uint32_t addr, int rw);<br>
+<br>
+int bcm2835_spi_read_bytes(<br>
+rtems_libi2c_bus_t * bushdl,<br>
+unsigned char *bytes,<br>
+int nbytes<br>
+);<br>
+<br>
+int bcm2835_spi_write_bytes(<br>
+rtems_libi2c_bus_t * bushdl,<br>
+unsigned char *bytes,<br>
+int nbytes);<br>
+<br>
+int bcm2835_spi_ioctl(rtems_libi2c_bus_t * bushdl, int cmd, void *arg);<br>
+<br>
+int BSP_spi_register_drivers(int spi_bus_number);<br>
+<br>
+int BSP_spi_init(void);<br>
+<br>
+/** @} */<br>
+<br>
+/**<br>
+ * @name  I2C constants.<br>
+ *<br>
+ * @{<br>
+ */<br>
+<br>
+<br>
+/**<br>
+ * @brief  BSC controller core clock rate in Hz.<br>
+ *<br>
+ * This is set to 150 MHz as per the BCM2835 datasheet.<br>
+ */<br>
+#define BSC_CORE_CLK_HZ 150000000<br>
+<br>
+/** @} */<br>
+<br>
+/**<br>
+ * @name  I2C data structures.<br>
+ *<br>
+ * @{<br>
+ */<br>
+<br>
+typedef struct {<br>
+  int                 initialized;<br>
+  rtems_id            irq_sema_id;<br>
+} bcm2835_i2c_softc_t;<br>
+<br>
+typedef struct {<br>
+  rtems_libi2c_bus_t  bus_desc;<br>
+  bcm2835_i2c_softc_t softc;<br>
+} bcm2835_i2c_desc_t;<br>
+<br>
+/** @} */<br>
+<br>
+/**<br>
+ * @name  I2C directives.<br>
+ *<br>
+ * @{<br>
+ */<br>
+<br>
+rtems_status_code bcm2835_i2c_init(rtems_libi2c_bus_t * bushdl);<br>
+<br>
+rtems_status_code bcm2835_i2c_send_start(rtems_libi2c_bus_t * bushdl);<br>
+<br>
+rtems_status_code bcm2835_i2c_stop(rtems_libi2c_bus_t * bushdl);<br>
+<br>
+rtems_status_code<br>
+bcm2835_i2c_send_addr(rtems_libi2c_bus_t * bushdl, uint32_t addr, int rw);<br>
+<br>
+int bcm2835_i2c_read_bytes(<br>
+rtems_libi2c_bus_t * bushdl,<br>
+unsigned char *bytes,<br>
+int nbytes<br>
+);<br>
+<br>
+int bcm2835_i2c_write_bytes(<br>
+rtems_libi2c_bus_t * bushdl,<br>
+unsigned char *bytes,<br>
+int nbytes<br>
+);<br>
+<br>
+int bcm2835_i2c_ioctl(rtems_libi2c_bus_t * bushdl, int cmd, void *arg);<br>
+<br>
+int BSP_i2c_register_drivers(int i2c_bus_number);<br>
+<br>
+int BSP_i2c_init(void);<br>
+<br>
+/** @} */<br>
+<br>
+#endif /* LIBBSP_ARM_RASPBERRYPI_I2C_H */<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/include/irq.h b/c/src/lib/libbsp/arm/raspberrypi/include/irq.h<br>
index 8436c2d..fb5f90e 100644<br>
--- a/c/src/lib/libbsp/arm/raspberrypi/include/irq.h<br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/include/irq.h<br>
@@ -1,5 +1,5 @@<br>
 /**<br>
- * @file<br>
+ * @file irq.h<br>
  *<br>
  * @ingroup raspberrypi_interrupt<br>
  *<br>
@@ -7,7 +7,8 @@<br>
  */<br>
<br>
 /**<br>
- * Copyright (c) 2013 Alan Cudmore<br>
+ *  Copyright (c) 2014 Andre Marques <andre.lousa.marques at <a href="http://gmail.com" target="_blank">gmail.com</a>><br>
+ *  Copyright (c) 2013 Alan Cudmore<br>
  *<br>
  *  The license and distribution terms for this file may be<br>
  *  found in the file LICENSE in this distribution or at<br>
@@ -62,6 +63,7 @@<br>
<br>
 #define BSP_IRQ_COUNT               (BCM2835_INTC_TOTAL_IRQ)<br>
<br>
+rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector);<br>
<br>
 void raspberrypi_set_exception_handler(Arm_symbolic_exception_name exception,<br>
                                          void (*handler)(void));<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/include/raspberrypi.h b/c/src/lib/libbsp/arm/raspberrypi/include/raspberrypi.h<br>
index 4cc7eec..2e902c6 100644<br>
--- a/c/src/lib/libbsp/arm/raspberrypi/include/raspberrypi.h<br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/include/raspberrypi.h<br>
@@ -1,6 +1,5 @@<br>
-<br>
 /**<br>
- * @file<br>
+ * @file raspberrypi.h<br>
  *<br>
  * @ingroup raspberrypi_reg<br>
  *<br>
@@ -8,7 +7,8 @@<br>
  */<br>
<br>
 /*<br>
- * Copyright (c) 2013 Alan Cudmore.<br>
+ *  Copyright (c) 2014 Andre Marques <andre.lousa.marques at <a href="http://gmail.com" target="_blank">gmail.com</a>><br>
+ *  Copyright (c) 2013 Alan Cudmore.<br>
  *<br>
  *  The license and distribution terms for this file may be<br>
  *  found in the file LICENSE in this distribution or at<br>
@@ -79,8 +79,16 @@<br>
 #define BCM2835_GPIO_GPFSEL1     (BCM2835_GPIO_REGS_BASE+0x04)<br>
 #define BCM2835_GPIO_GPSET0      (BCM2835_GPIO_REGS_BASE+0x1C)<br>
 #define BCM2835_GPIO_GPCLR0      (BCM2835_GPIO_REGS_BASE+0x28)<br>
+#define BCM2835_GPIO_GPLEV0      (BCM2835_GPIO_REGS_BASE+0x34)<br>
+#define BCM2835_GPIO_GPEDS0      (BCM2835_GPIO_REGS_BASE+0x40)<br>
+#define BCM2835_GPIO_GPREN0      (BCM2835_GPIO_REGS_BASE+0x4C)<br>
+#define BCM2835_GPIO_GPFEN0      (BCM2835_GPIO_REGS_BASE+0x58)<br>
+#define BCM2835_GPIO_GPHEN0      (BCM2835_GPIO_REGS_BASE+0x64)<br>
+#define BCM2835_GPIO_GPLEN0      (BCM2835_GPIO_REGS_BASE+0x70)<br>
+#define BCM2835_GPIO_GPAREN0     (BCM2835_GPIO_REGS_BASE+0x7C)<br>
+#define BCM2835_GPIO_GPAFEN0     (BCM2835_GPIO_REGS_BASE+0x88)<br>
 #define BCM2835_GPIO_GPPUD       (BCM2835_GPIO_REGS_BASE+0x94)<br>
-#define BCM2835_GPIO_GPPUDCLK0   (BCM2835_GPIO_REGS_BASE+0x98)<br>
+#define BCM2835_GPIO_GPPUDCLK0   (BCM2835_GPIO_REGS_BASE+0x98)<br>
<br>
 /** @} */<br>
<br>
@@ -107,14 +115,12 @@<br>
<br>
 /** @} */<br>
<br>
-<br>
 /**<br>
  * @name UART 0 (PL011) Registers<br>
  *<br>
  * @{<br>
  */<br>
<br>
-<br>
 #define BCM2835_UART0_BASE       (0x20201000)<br>
<br>
 #define BCM2835_UART0_DR         (BCM2835_UART0_BASE+0x00)<br>
@@ -145,9 +151,68 @@<br>
 #define BCM2835_UART0_ICR_RX    0x10<br>
 #define BCM2835_UART0_ICR_TX    0x20<br>
<br>
+/** @} */<br>
+<br>
+/**<br>
+ * @name I2C (BSC) Registers<br>
+ *<br>
+ * @{<br>
+ */<br>
+<br>
+#define BCM2835_I2C_BASE           (0x20804000)<br>
+<br>
+#define BCM2835_I2C_C              (BCM2835_I2C_BASE+0x00)<br>
+#define BCM2835_I2C_S              (BCM2835_I2C_BASE+0x04)<br>
+#define BCM2835_I2C_DLEN           (BCM2835_I2C_BASE+0x08)<br>
+#define BCM2835_I2C_A              (BCM2835_I2C_BASE+0x0C)<br>
+#define BCM2835_I2C_FIFO           (BCM2835_I2C_BASE+0x10)<br>
+#define BCM2835_I2C_DIV            (BCM2835_I2C_BASE+0x14)<br>
+#define BCM2835_I2C_DEL            (BCM2835_I2C_BASE+0x18)<br>
+#define BCM2835_I2C_CLKT           (BCM2835_I2C_BASE+0x1C)<br>
<br>
 /** @} */<br>
<br>
+/**<br>
+ * @name SPI Registers<br>
+ *<br>
+ * @{<br>
+ */<br>
+<br>
+#define BCM2835_SPI_BASE           (0x20204000)<br>
+<br>
+#define BCM2835_SPI_CS             (BCM2835_SPI_BASE+0x00)<br>
+#define BCM2835_SPI_FIFO           (BCM2835_SPI_BASE+0x04)<br>
+#define BCM2835_SPI_CLK            (BCM2835_SPI_BASE+0x08)<br>
+#define BCM2835_SPI_DLEN           (BCM2835_SPI_BASE+0x0C)<br>
+#define BCM2835_SPI_LTOH           (BCM2835_SPI_BASE+0x10)<br>
+#define BCM2835_SPI_DC             (BCM2835_SPI_BASE+0x14)<br>
+<br>
+/** @} */<br>
+<br>
+/**<br>
+ * @name I2C/SPI slave BSC Registers<br>
+ *<br>
+ * @{<br>
+ */<br>
+<br>
+#define BCM2835_I2C_SPI_BASE       (0x20214000)<br>
+<br>
+#define BCM2835_I2C_SPI_DR         (BCM2835_I2C_SPI_BASE+0x00)<br>
+#define BCM2835_I2C_SPI_RSR        (BCM2835_I2C_SPI_BASE+0x04)<br>
+#define BCM2835_I2C_SPI_SLV        (BCM2835_I2C_SPI_BASE+0x08)<br>
+#define BCM2835_I2C_SPI_CR         (BCM2835_I2C_SPI_BASE+0x0C)<br>
+#define BCM2835_I2C_SPI_FR         (BCM2835_I2C_SPI_BASE+0x10)<br>
+#define BCM2835_I2C_SPI_IFLS       (BCM2835_I2C_SPI_BASE+0x14)<br>
+#define BCM2835_I2C_SPI_IMSC       (BCM2835_I2C_SPI_BASE+0x18)<br>
+#define BCM2835_I2C_SPI_RIS        (BCM2835_I2C_SPI_BASE+0x1C)<br>
+#define BCM2835_I2C_SPI_MIS        (BCM2835_I2C_SPI_BASE+0x20)<br>
+#define BCM2835_I2C_SPI_ICR        (BCM2835_I2C_SPI_BASE+0x24)<br>
+#define BCM2835_I2C_SPI_DMACR      (BCM2835_I2C_SPI_BASE+0x28)<br>
+#define BCM2835_I2C_SPI_TDR        (BCM2835_I2C_SPI_BASE+0x2C)<br>
+#define BCM2835_I2C_SPI_GPUSTAT    (BCM2835_I2C_SPI_BASE+0x30)<br>
+#define BCM2835_I2C_SPI_HCTRL      (BCM2835_I2C_SPI_BASE+0x34)<br>
+<br>
+/** @} */<br>
<br>
 /**<br>
  * @name IRQ Registers<br>
@@ -170,7 +235,6 @@<br>
<br>
 /** @} */<br>
<br>
-<br>
 /**<br>
  * @name GPU Timer Registers<br>
  *<br>
@@ -194,7 +258,6 @@<br>
<br>
 /** @} */<br>
<br>
-<br>
 /** @} */<br>
<br>
 #endif /* LIBBSP_ARM_RASPBERRYPI_RASPBERRYPI_H */<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c b/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c<br>
index 4132ef9..c2c7d89 100644<br>
--- a/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c<br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c<br>
@@ -1,5 +1,5 @@<br>
 /**<br>
- * @file<br>
+ * @file irq.c<br>
  *<br>
  * @ingroup raspberrypi_interrupt<br>
  *<br>
@@ -7,6 +7,8 @@<br>
  */<br>
<br>
 /*<br>
+ * Copyright (c) 2014 Andre Marques <andre.lousa.marques at <a href="http://gmail.com" target="_blank">gmail.com</a>><br>
+ *<br>
  * Copyright (c) 2009<br>
  * embedded brains GmbH<br>
  * Obere Lagerstr. 30<br>
@@ -52,22 +54,47 @@ void bsp_interrupt_dispatch(void)<br>
   rtems_vector_number vector = 255;<br>
<br>
   /* ARM timer */<br>
-  if (BCM2835_REG(BCM2835_IRQ_BASIC) && 0x1)<br>
+  if ( BCM2835_REG(BCM2835_IRQ_BASIC) & 0x1 )<br>
   {<br>
       vector = BCM2835_IRQ_ID_TIMER_0;<br>
-<br>
   }<br>
   /* UART 0 */<br>
-  else if ( BCM2835_REG(BCM2835_IRQ_BASIC) && BCM2835_BIT(19))<br>
+  else if ( BCM2835_REG(BCM2835_IRQ_BASIC) & BCM2835_BIT(19) )<br>
   {<br>
       vector = BCM2835_IRQ_ID_UART;<br>
   }<br>
+  /* GPIO 0*/<br>
+  else if ( BCM2835_REG(BCM2835_IRQ_PENDING2) & BCM2835_BIT(17) )<br>
+  {<br>
+      vector = BCM2835_IRQ_ID_GPIO_0;<br>
+  }<br>
+  else if ( BCM2835_REG(BCM2835_IRQ_PENDING2) & BCM2835_BIT(18) )<br>
+  {<br>
+      vector = BCM2835_IRQ_ID_GPIO_1;<br>
+  }<br>
+  else if ( BCM2835_REG(BCM2835_IRQ_PENDING2) & BCM2835_BIT(19) )<br>
+  {<br>
+      vector = BCM2835_IRQ_ID_GPIO_2;<br>
+  }<br>
+  else if ( BCM2835_REG(BCM2835_IRQ_PENDING2) & BCM2835_BIT(20) )<br>
+  {<br>
+      vector = BCM2835_IRQ_ID_GPIO_3;<br>
+  }<br>
+  /* I2C */<br>
+  else if ( BCM2835_REG(BCM2835_IRQ_PENDING2) & BCM2835_BIT(21) )<br>
+  {<br>
+      vector = BCM2835_IRQ_ID_I2C;<br>
+  }<br>
+  /* SPI */<br>
+  else if ( BCM2835_REG(BCM2835_IRQ_PENDING2) & BCM2835_BIT(22) )<br>
+  {<br>
+      vector = BCM2835_IRQ_ID_SPI;<br>
+  }<br>
<br>
   if ( vector < 255 )<br>
   {<br>
       bsp_interrupt_handler_dispatch(vector);<br>
   }<br>
-<br>
 }<br>
<br>
 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)<br>
@@ -76,7 +103,7 @@ rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)<br>
<br>
   rtems_interrupt_disable(level);<br>
<br>
-   /* ARM Timer */<br>
+  /* ARM Timer */<br>
   if ( vector == BCM2835_IRQ_ID_TIMER_0 )<br>
   {<br>
       BCM2835_REG(BCM2835_IRQ_ENABLE_BASIC) = 0x1;<br>
@@ -85,8 +112,38 @@ rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)<br>
   else if ( vector == BCM2835_IRQ_ID_UART )<br>
   {<br>
       BCM2835_REG(BCM2835_IRQ_ENABLE2) =  BCM2835_BIT(25);<br>
-<br>
   }<br>
+  /* GPIO 0 */<br>
+  else if ( vector == BCM2835_IRQ_ID_GPIO_0 )<br>
+  {<br>
+      BCM2835_REG(BCM2835_IRQ_ENABLE2) = BCM2835_BIT(17);<br>
+  }<br>
+  /* GPIO 1 */<br>
+  else if ( vector == BCM2835_IRQ_ID_GPIO_1 )<br>
+  {<br>
+      BCM2835_REG(BCM2835_IRQ_ENABLE2) = BCM2835_BIT(18);<br>
+  }<br>
+  /* GPIO 2 */<br>
+  else if ( vector == BCM2835_IRQ_ID_GPIO_2 )<br>
+  {<br>
+      BCM2835_REG(BCM2835_IRQ_ENABLE2) = BCM2835_BIT(19);<br>
+  }<br>
+  /* GPIO 3 */<br>
+  else if ( vector == BCM2835_IRQ_ID_GPIO_3 )<br>
+  {<br>
+      BCM2835_REG(BCM2835_IRQ_ENABLE2) = BCM2835_BIT(20);<br>
+  }<br>
+  /* I2C */<br>
+  else if ( vector == BCM2835_IRQ_ID_I2C )<br>
+  {<br>
+      BCM2835_REG(BCM2835_IRQ_ENABLE2) = BCM2835_BIT(21);<br>
+  }<br>
+  /* SPI */<br>
+  else if ( vector == BCM2835_IRQ_ID_SPI )<br>
+  {<br>
+      BCM2835_REG(BCM2835_IRQ_ENABLE2) = BCM2835_BIT(22);<br>
+  }<br>
+<br>
   rtems_interrupt_enable(level);<br>
<br>
   return RTEMS_SUCCESSFUL;<br>
@@ -106,12 +163,42 @@ rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)<br>
   {<br>
       BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(25);<br>
   }<br>
+  /* GPIO 0 */<br>
+  else if ( vector == BCM2835_IRQ_ID_GPIO_0 )<br>
+  {<br>
+      BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(17);<br>
+  }<br>
+  /* GPIO 1 */<br>
+  else if ( vector == BCM2835_IRQ_ID_GPIO_1 )<br>
+  {<br>
+      BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(18);<br>
+  }<br>
+  /* GPIO 2 */<br>
+  else if ( vector == BCM2835_IRQ_ID_GPIO_2 )<br>
+  {<br>
+      BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(19);<br>
+  }<br>
+  /* GPIO 3 */<br>
+  else if ( vector == BCM2835_IRQ_ID_GPIO_3 )<br>
+  {<br>
+      BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(20);<br>
+  }<br>
+  /* I2C */<br>
+  else if ( vector == BCM2835_IRQ_ID_I2C )<br>
+  {<br>
+      BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(21);<br>
+  }<br>
+  /* SPI */<br>
+  else if ( vector == BCM2835_IRQ_ID_SPI )<br>
+  {<br>
+      BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(22);<br>
+  }<br>
+<br>
   rtems_interrupt_enable(level);<br>
<br>
   return RTEMS_SUCCESSFUL;<br>
 }<br>
<br>
-<br>
 void bsp_interrupt_handler_default(rtems_vector_number vector)<br>
 {<br>
     printk("spurious interrupt: %u\n", vector);<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/<a href="http://preinstall.am" target="_blank">preinstall.am</a> b/c/src/lib/libbsp/arm/raspberrypi/<a href="http://preinstall.am" target="_blank">preinstall.am</a><br>
index 70259e2..f9a87e0 100644<br>
--- a/c/src/lib/libbsp/arm/raspberrypi/<a href="http://preinstall.am" target="_blank">preinstall.am</a><br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/<a href="http://preinstall.am" target="_blank">preinstall.am</a><br>
@@ -130,6 +130,14 @@ $(PROJECT_INCLUDE)/bsp/raspberrypi.h: include/raspberrypi.h $(PROJECT_INCLUDE)/b<br>
        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/raspberrypi.h<br>
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/raspberrypi.h<br>
<br>
+$(PROJECT_INCLUDE)/bsp/gpio.h: include/gpio.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)<br>
+       $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/gpio.h<br>
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/gpio.h<br>
+<br>
+$(PROJECT_INCLUDE)/bsp/i2c.h: include/i2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)<br>
+       $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/i2c.h<br>
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/i2c.h<br>
+<br>
 $(PROJECT_INCLUDE)/libcpu/cache_.h: ../../../libcpu/arm/shared/include/cache_.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)<br>
        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/cache_.h<br>
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/cache_.h<br>
diff --git a/c/src/lib/libbsp/arm/raspberrypi/startup/bspstart.c b/c/src/lib/libbsp/arm/raspberrypi/startup/bspstart.c<br>
index c5786bf..5ca6612 100644<br>
--- a/c/src/lib/libbsp/arm/raspberrypi/startup/bspstart.c<br>
+++ b/c/src/lib/libbsp/arm/raspberrypi/startup/bspstart.c<br>
@@ -1,5 +1,5 @@<br>
 /**<br>
- * @file<br>
+ * @file bspstart.c<br>
  *<br>
  * @ingroup arm_start<br>
  *<br>
@@ -7,7 +7,8 @@<br>
  */<br>
<br>
 /*<br>
- * Copyright (c) 2013 by Alan Cudmore<br>
+ *  Copyright (c) 2014 Andre Marques <andre.lousa.marques at <a href="http://gmail.com" target="_blank">gmail.com</a>><br>
+ *  Copyright (c) 2013 by Alan Cudmore<br>
  *<br>
  *  The license and distribution terms for this file may be<br>
  *  found in the file LICENSE in this distribution or at<br>
@@ -22,8 +23,18 @@<br>
 #include <bsp/linker-symbols.h><br>
 #include <bsp/stackalloc.h><br>
 #include <bsp/raspberrypi.h><br>
+#include <bsp/i2c.h><br>
+<br>
+void bsp_predriver_hook(void)<br>
+{<br>
+  if ( BSP_ENABLE_SPI == 1 )<br>
+    BSP_spi_init();<br>
+<br>
+  if ( BSP_ENABLE_I2C == 1 )<br>
+    BSP_i2c_init();<br>
+}<br>
<br>
 void bsp_start(void)<br>
 {<br>
-    bsp_interrupt_initialize();<br>
+  bsp_interrupt_initialize();<br>
 }<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.0.4<br>
<br>
</font></span></blockquote></div><br></div>