mbed library with additional peripherals for ST F401 board

Fork of mbed-src by mbed official

This mbed LIB has additional peripherals for ST F401 board

  • UART2 : PA_3 rx, PA_2 tx
  • UART3 : PC_7 rx, PC_6 tx
  • I2C2 : PB_3 SDA, PB_10 SCL
  • I2C3 : PB_4 SDA, PA_8 SCL

Files at this revision

API Documentation at this revision

Comitter:
mbed_official
Date:
Thu Dec 12 10:45:05 2013 +0000
Parent:
55:3b765ca737a5
Child:
57:c7e83bc5e387
Commit message:
Synchronized with git revision bd51e4eb73a1706f1d5379ec5cebcbd6d978cb4f

Full URL: https://github.com/mbedmicro/mbed/commit/bd51e4eb73a1706f1d5379ec5cebcbd6d978cb4f/

[NUCLEO_F103RB] Add I2C master, code cleanup, ...

Changed in this revision

targets/cmsis/TARGET_NXP/TARGET_LPC408X/TOOLCHAIN_ARM_STD/LPC407X_8X.sct Show annotated file Show diff for this revision Revisions of this file
targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_MICRO/startup_stm32f10x_md.s Show annotated file Show diff for this revision Revisions of this file
targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_STD/startup_stm32f10x_md.s Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/PeripheralNames.h Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/PinNames.h Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/analogin_api.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/objects.h Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/pwmout_api.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/serial_api.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/spi_api.c Show annotated file Show diff for this revision Revisions of this file
--- a/targets/cmsis/TARGET_NXP/TARGET_LPC408X/TOOLCHAIN_ARM_STD/LPC407X_8X.sct	Mon Dec 09 11:15:04 2013 +0000
+++ b/targets/cmsis/TARGET_NXP/TARGET_LPC408X/TOOLCHAIN_ARM_STD/LPC407X_8X.sct	Thu Dec 12 10:45:05 2013 +0000
@@ -6,7 +6,9 @@
   ER_IROM1 0x00000000 0x00080000  {  ; load address = execution address
    *.o (RESET, +First)
    *(InRoot$$Sections)
-   .ANY (+RO)
+   *.o (+RO-CODE)                    ; forces all CODE to IFLASH
+   .ANY2 (+RO-DATA)                  ; prioritizes DATA in IFLASH before SPIFI
+   .ANY (+RO)                        ; remaining RO
   }
   RW_IRAM1 0x100000E8 0x0000FF18  {  ; RW data
    .ANY (+RW +ZI)
@@ -21,7 +23,8 @@
 
 LR_IROM2 0x28000000 0x01000000  {
   ER_IROM2 0x28000000 0x01000000  {  ; load address = execution address
-    .ANY (+RO)
+    .ANY1 (+RO-DATA)                 ; all DATA not fitting in IFLASH
+    .ANY (SPIFI_MEM)                 ; DATA tagged as SPIFI_MEM
   }
 }
 
--- a/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_MICRO/startup_stm32f10x_md.s	Mon Dec 09 11:15:04 2013 +0000
+++ b/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_MICRO/startup_stm32f10x_md.s	Thu Dec 12 10:45:05 2013 +0000
@@ -1,19 +1,7 @@
-;******************** (C) COPYRIGHT 2011 STMicroelectronics ********************
+;*******************************************************************************
 ;* File Name          : startup_stm32f10x_md.s
-;* Author             : MCD Application Team
-;* Version            : V3.5.0
-;* Date               : 11-March-2011
 ;* Description        : STM32F10x Medium Density Devices vector table for MDK-ARM 
-;*                      toolchain.  
-;*                      This module performs:
-;*                      - Set the initial SP
-;*                      - Set the initial PC == Reset_Handler
-;*                      - Set the vector table entries with the exceptions ISR address
-;*                      - Configure the clock system
-;*                      - Branches to __main in the C library (which eventually
-;*                        calls main()).
-;*                      After Reset the CortexM3 processor is in Thread mode,
-;*                      priority is Privileged, and the Stack is set to Main.
+;*                      toolchain + ARM_MICRO compiler
 ;* <<< Use Configuration Wizard in Context Menu >>>   
 ;*******************************************************************************
 ; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
@@ -33,6 +21,8 @@
 Stack_Size      EQU     0x00000400
 
                 AREA    STACK, NOINIT, READWRITE, ALIGN=3
+                EXPORT  __initial_sp
+                
 Stack_Mem       SPACE   Stack_Size
 __initial_sp    EQU     0x20005000 ; Top of RAM
 
@@ -41,9 +31,12 @@
 ;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
 ; </h>
 
-Heap_Size       EQU     0x00000200
+Heap_Size       EQU     0x00000000
 
                 AREA    HEAP, NOINIT, READWRITE, ALIGN=3
+                EXPORT  __heap_base
+                EXPORT  __heap_limit
+                
 __heap_base
 Heap_Mem        SPACE   Heap_Size
 __heap_limit
@@ -275,33 +268,4 @@
                 ENDP
 
                 ALIGN
-
-;*******************************************************************************
-; User Stack and Heap initialization
-;*******************************************************************************
-                 IF      :DEF:__MICROLIB           
-                
-                 EXPORT  __initial_sp
-                 EXPORT  __heap_base
-                 EXPORT  __heap_limit
-                
-                 ELSE
-                
-                 IMPORT  __use_two_region_memory
-                 EXPORT  __user_initial_stackheap
-                 
-__user_initial_stackheap
-
-                 LDR     R0, =  Heap_Mem
-                 LDR     R1, =(Stack_Mem + Stack_Size)
-                 LDR     R2, = (Heap_Mem +  Heap_Size)
-                 LDR     R3, = Stack_Mem
-                 BX      LR
-
-                 ALIGN
-
-                 ENDIF
-
-                 END
-
-;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE*****
+                END
--- a/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_STD/startup_stm32f10x_md.s	Mon Dec 09 11:15:04 2013 +0000
+++ b/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_STD/startup_stm32f10x_md.s	Thu Dec 12 10:45:05 2013 +0000
@@ -1,19 +1,7 @@
-;******************** (C) COPYRIGHT 2011 STMicroelectronics ********************
+;*******************************************************************************
 ;* File Name          : startup_stm32f10x_md.s
-;* Author             : MCD Application Team
-;* Version            : V3.5.0
-;* Date               : 11-March-2011
 ;* Description        : STM32F10x Medium Density Devices vector table for MDK-ARM 
-;*                      toolchain.  
-;*                      This module performs:
-;*                      - Set the initial SP
-;*                      - Set the initial PC == Reset_Handler
-;*                      - Set the vector table entries with the exceptions ISR address
-;*                      - Configure the clock system
-;*                      - Branches to __main in the C library (which eventually
-;*                        calls main()).
-;*                      After Reset the CortexM3 processor is in Thread mode,
-;*                      priority is Privileged, and the Stack is set to Main.
+;*                      toolchain + ARM_STD compiler
 ;* <<< Use Configuration Wizard in Context Menu >>>   
 ;*******************************************************************************
 ; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
@@ -24,30 +12,8 @@
 ; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
 ;*******************************************************************************
 
-; Amount of memory (in bytes) allocated for Stack
-; Tailor this value to your application needs
-; <h> Stack Configuration
-;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
-; </h>
-
-Stack_Size      EQU     0x00000400
-
-                AREA    STACK, NOINIT, READWRITE, ALIGN=3
-Stack_Mem       SPACE   Stack_Size
 __initial_sp    EQU     0x20005000 ; Top of RAM
 
-
-; <h> Heap Configuration
-;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
-; </h>
-
-Heap_Size       EQU     0x00000200
-
-                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
-__heap_base
-Heap_Mem        SPACE   Heap_Size
-__heap_limit
-
                 PRESERVE8
                 THUMB
 
@@ -275,33 +241,4 @@
                 ENDP
 
                 ALIGN
-
-;*******************************************************************************
-; User Stack and Heap initialization
-;*******************************************************************************
-                 IF      :DEF:__MICROLIB           
-                
-                 EXPORT  __initial_sp
-                 EXPORT  __heap_base
-                 EXPORT  __heap_limit
-                
-                 ELSE
-                
-                 IMPORT  __use_two_region_memory
-                 EXPORT  __user_initial_stackheap
-                 
-__user_initial_stackheap
-
-                 LDR     R0, =  Heap_Mem
-                 LDR     R1, =(Stack_Mem + Stack_Size)
-                 LDR     R2, = (Heap_Mem +  Heap_Size)
-                 LDR     R3, = Stack_Mem
-                 BX      LR
-
-                 ALIGN
-
-                 ENDIF
-
-                 END
-
-;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE*****
+                END
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/PeripheralNames.h	Mon Dec 09 11:15:04 2013 +0000
+++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/PeripheralNames.h	Thu Dec 12 10:45:05 2013 +0000
@@ -32,8 +32,8 @@
     UART_2 = (int)USART2_BASE
 } UARTName;
 
-#define STDIO_UART_TX  UART_TX
-#define STDIO_UART_RX  UART_RX
+#define STDIO_UART_TX  PA_2
+#define STDIO_UART_RX  PA_3
 #define STDIO_UART     UART_2
 
 typedef enum {
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/PinNames.h	Mon Dec 09 11:15:04 2013 +0000
+++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/PinNames.h	Thu Dec 12 10:45:05 2013 +0000
@@ -88,45 +88,10 @@
   PC_14 = 0x2E,
   PC_15 = 0x2F,
 
-  PD_0  = 0x30,
-  PD_1  = 0x31,
   PD_2  = 0x32,
-  PD_3  = 0x33,
-  PD_4  = 0x34,
-  PD_5  = 0x35,
-  PD_6  = 0x36,
-  PD_7  = 0x37,
   PD_8  = 0x38,
-  PD_9  = 0x39,
-  PD_10 = 0x3A,
-  PD_11 = 0x3B,
-  PD_12 = 0x3C,
-  PD_13 = 0x3D,
-  PD_14 = 0x3E,
-  PD_15 = 0x3F,
 
-  PE_0  = 0x40,
-  PE_1  = 0x41,
-  PE_2  = 0x42,
-  PE_3  = 0x43,
-  PE_4  = 0x44,
-  PE_5  = 0x45,
-  PE_6  = 0x46,
-  PE_7  = 0x47,
-  PE_8  = 0x48,
-  PE_9  = 0x49,
-  PE_10 = 0x4A,
-  PE_11 = 0x4B,
-  PE_12 = 0x4C,
-  PE_13 = 0x4D,
-  PE_14 = 0x4E,
-  PE_15 = 0x4F,
-
-  //--------------------
-  // NUCLEO_F103RB board
-  //--------------------
-
-  // Arduino connectors
+  // Arduino connector namings
   A0          = PA_0,
   A1          = PA_1,
   A2          = PA_4,
@@ -150,15 +115,21 @@
   D14         = PB_9,
   D15         = PB_8,
 
+  // Generic signals namings
+  LED1        = PA_5,
+  LED2        = PA_5,
+  LED3        = PA_5,  
+  LED4        = PA_5,  
   USER_BUTTON = PC_13,
-  UART_TX     = PA_2,
-  UART_RX     = PA_3,
-
-  // mbed mandatory namings
-  LED1 = PA_5,
-  LED2 = PA_5,
-  LED3 = PA_5,  
-  LED4 = PA_5,
+  SERIAL_TX   = PA_2,
+  SERIAL_RX   = PA_3,
+  I2C_SCL     = PB_8,
+  I2C_SDA     = PB_9,
+  SPI_MOSI    = PA_7,
+  SPI_MISO    = PA_6,
+  SPI_SCK     = PA_5,
+  SPI_CS      = PB_6,
+  PWM_OUT     = PB_3,
   
   // Not connected
   NC = (int)0xFFFFFFFF
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/analogin_api.c	Mon Dec 09 11:15:04 2013 +0000
+++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/analogin_api.c	Thu Dec 12 10:45:05 2013 +0000
@@ -13,9 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-//==============================================================================
-// STM32F103
-//============================================================================== 
 #include "analogin_api.h"
 #include "wait_api.h"
 
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h	Mon Dec 09 11:15:04 2013 +0000
+++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h	Thu Dec 12 10:45:05 2013 +0000
@@ -27,7 +27,7 @@
 
 #define DEVICE_SERIAL           1
 
-#define DEVICE_I2C              0
+#define DEVICE_I2C              1
 #define DEVICE_I2CSLAVE         0
 
 #define DEVICE_SPI              1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c	Thu Dec 12 10:45:05 2013 +0000
@@ -0,0 +1,321 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "i2c_api.h"
+
+#if DEVICE_I2C
+
+#include "cmsis.h"
+#include "pinmap.h"
+#include "error.h"
+
+/* Timeout values for flags and events waiting loops. These timeouts are
+   not based on accurate values, they just guarantee that the application will 
+   not remain stuck if the I2C communication is corrupted. */   
+#define FLAG_TIMEOUT ((int)0x1000)
+#define LONG_TIMEOUT ((int)0x8000)
+
+// Functions exit codes
+#define EXIT_OK      (0)
+#define EXIT_FAIL    (1)
+#define EXIT_TIMEOUT (0xFFFFFFFF)
+
+static const PinMap PinMap_I2C_SDA[] = {
+    //{PB_7,  I2C_1, STM_PIN_DATA(GPIO_Mode_AF_OD, 0)}, // Cannot be used due to TIM4
+    {PB_9,  I2C_1, STM_PIN_DATA(GPIO_Mode_AF_OD, 7)}, // GPIO_Remap_I2C1
+    {NC,    NC,    0}
+};
+
+static const PinMap PinMap_I2C_SCL[] = {
+    //{PB_6,  I2C_1, STM_PIN_DATA(GPIO_Mode_AF_OD, 0)}, // // Cannot be used due to TIM4
+    {PB_8,  I2C_1, STM_PIN_DATA(GPIO_Mode_AF_OD, 7)}, // GPIO_Remap_I2C1
+    {NC,    NC,    0}
+};
+
+void i2c_init(i2c_t *obj, PinName sda, PinName scl) {  
+    // Determine the I2C to use
+    I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
+    I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
+
+    obj->i2c = (I2CName)pinmap_merge(i2c_sda, i2c_scl);
+    
+    if (obj->i2c == (I2CName)NC) {
+        error("I2C pin mapping failed");
+    }
+
+    // Enable I2C clock
+    if (obj->i2c == I2C_1) {    
+        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
+    }
+    if (obj->i2c == I2C_2) {
+        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
+    }
+
+    // Configure I2C pins
+    pinmap_pinout(sda, PinMap_I2C_SDA);
+    pinmap_pinout(scl, PinMap_I2C_SCL);
+    pin_mode(sda, OpenDrain);
+    pin_mode(scl, OpenDrain);
+    
+    // Reset to clear pending flags if any
+    i2c_reset(obj);
+    
+    // I2C configuration
+    i2c_frequency(obj, 100000); // 100 kHz per default    
+}
+
+void i2c_frequency(i2c_t *obj, int hz) {
+    I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
+    I2C_InitTypeDef I2C_InitStructure;
+  
+    if ((hz != 0) && (hz <= 400000)) {
+        // I2C configuration
+        I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
+        I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
+        I2C_InitStructure.I2C_OwnAddress1 = 0;
+        I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
+        I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
+        I2C_InitStructure.I2C_ClockSpeed = hz;
+        I2C_Cmd(i2c, ENABLE);
+        I2C_Init(i2c, &I2C_InitStructure);  
+    }
+}
+
+inline int i2c_start(i2c_t *obj) {
+    I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
+    int timeout;
+  
+    I2C_ClearFlag(i2c, I2C_FLAG_AF); // Clear Acknowledge failure flag
+  
+    // Generate the START condition
+    I2C_GenerateSTART(i2c, ENABLE);  
+  
+    // Wait the START condition has been correctly sent
+    timeout = FLAG_TIMEOUT;
+    //while (I2C_CheckEvent(i2c, I2C_EVENT_MASTER_MODE_SELECT) == ERROR) {
+    while (I2C_GetFlagStatus(i2c, I2C_FLAG_SB) == RESET) {
+      if ((timeout--) == 0) {
+          return EXIT_TIMEOUT;
+      }
+    }
+    
+    return EXIT_OK;
+}
+
+inline int i2c_stop(i2c_t *obj) {
+    I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
+    I2C_GenerateSTOP(i2c, ENABLE);
+    return EXIT_OK;
+}
+
+int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
+    I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
+    int timeout;
+    int count;
+    int value;
+  
+    if (length == 0) return 0;
+
+/*
+    // Wait until the bus is not busy anymore
+    timeout = LONG_TIMEOUT;
+    while (I2C_GetFlagStatus(i2c, I2C_FLAG_BUSY) == SET) {
+        if ((timeout--) == 0) {
+            return EXIT_TIMEOUT;
+        }
+    }
+*/
+  
+    i2c_start(obj);
+
+    // Send slave address for read
+    I2C_Send7bitAddress(i2c, address, I2C_Direction_Receiver);  
+
+    // Wait address is acknowledged
+    timeout = FLAG_TIMEOUT;
+    while (I2C_CheckEvent(i2c, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) == ERROR) {
+      if ((timeout--) == 0) {
+          return EXIT_TIMEOUT;
+      }
+    }
+    
+    // Read all bytes except last one
+    for (count = 0; count < (length - 1); count++) {
+        value = i2c_byte_read(obj, 0);
+        data[count] = (char)value;
+    }
+    
+    // If not repeated start, send stop.
+    // Warning: must be done BEFORE the data is read.
+    if (stop) {
+        i2c_stop(obj);
+    }
+
+    // Read the last byte
+    value = i2c_byte_read(obj, 1);
+    data[count] = (char)value;
+    
+    return length;
+}
+
+int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
+    I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
+    int timeout;
+    int count;
+  
+    if (length == 0) return 0;
+
+/*
+    // Wait until the bus is not busy anymore
+    timeout = LONG_TIMEOUT;
+    while (I2C_GetFlagStatus(i2c, I2C_FLAG_BUSY) == SET) {
+        if ((timeout--) == 0) {
+            return EXIT_TIMEOUT;
+        }
+    }
+*/
+
+    i2c_start(obj);
+
+    // Send slave address for write
+    I2C_Send7bitAddress(i2c, address, I2C_Direction_Transmitter);
+  
+    // Wait address is acknowledged
+    timeout = FLAG_TIMEOUT;
+    while (I2C_CheckEvent(i2c, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == ERROR) {
+      if ((timeout--) == 0) {
+          return EXIT_TIMEOUT;
+      }
+    }
+
+    for (count = 0; count < length; count++) {
+        if (i2c_byte_write(obj, data[count]) != EXIT_OK) {
+            return EXIT_FAIL;
+        }
+    }
+
+    // If not repeated start, send stop.
+    if (stop) {
+        i2c_stop(obj);
+    }
+
+    return count;
+}
+
+int i2c_byte_read(i2c_t *obj, int last) {
+    I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
+    uint8_t data;
+    int timeout;
+  
+    if (last) {
+        // Don't acknowledge the last byte
+        I2C_AcknowledgeConfig(i2c, DISABLE);
+    } else {
+        // Acknowledge the byte
+        I2C_AcknowledgeConfig(i2c, ENABLE);
+    }
+
+    // Wait until the byte is received
+    timeout = FLAG_TIMEOUT;
+    while (I2C_GetFlagStatus(i2c, I2C_FLAG_RXNE) == RESET) {
+      if ((timeout--) == 0) {
+          return EXIT_TIMEOUT;
+      }
+    }
+
+    data = I2C_ReceiveData(i2c);
+    
+    return (int)data;
+}
+
+int i2c_byte_write(i2c_t *obj, int data) {
+    I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
+    int timeout;
+
+    I2C_SendData(i2c, (uint8_t)data);
+
+    // Wait until the byte is transmitted
+    timeout = FLAG_TIMEOUT;  
+    //while (I2C_CheckEvent(i2c, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR) {
+    while ((I2C_GetFlagStatus(i2c, I2C_FLAG_TXE) == RESET) &&
+           (I2C_GetFlagStatus(i2c, I2C_FLAG_BTF) == RESET)) {
+        if ((timeout--) == 0) {
+            return EXIT_TIMEOUT;
+        }
+    }
+    
+    return EXIT_OK;
+}
+
+void i2c_reset(i2c_t *obj) {
+    if (obj->i2c == I2C_1) {    
+        RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
+        RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
+    }
+    if (obj->i2c == I2C_2) {
+        RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, ENABLE);
+        RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE);      
+    }
+}
+
+#if DEVICE_I2CSLAVE
+
+void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
+    I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
+    uint16_t tmpreg;
+  
+    // Get the old register value
+    tmpreg = i2c->OAR1;
+    // Reset address bits
+    tmpreg &= 0xFC00;
+    // Set new address
+    tmpreg |= (uint16_t)((uint16_t)address & (uint16_t)0x00FE); // 7-bits
+    // Store the new register value
+    i2c->OAR1 = tmpreg;
+}
+
+void i2c_slave_mode(i2c_t *obj, int enable_slave) {
+    // Nothing to do
+}
+
+#define        NoData         0
+#define        ReadAddressed  1
+#define        WriteGeneral   2
+#define        WriteAddressed 3
+
+int i2c_slave_receive(i2c_t *obj) {
+    //I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
+    int retval = NoData;
+    //int status;
+  
+    //if (I2C_GetFlagStatus(i2c, I2C_FLAG_GENCALL) == SET) retval = WriteGeneral;
+    
+    //status = I2C_GetLastEvent(i2c);
+  
+    return(retval);
+}
+
+int i2c_slave_read(i2c_t *obj, char *data, int length) {
+    return 0;
+}
+
+int i2c_slave_write(i2c_t *obj, const char *data, int length) {
+    return 0;
+}
+
+
+#endif // DEVICE_I2CSLAVE
+
+#endif // DEVICE_I2C
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/objects.h	Mon Dec 09 11:15:04 2013 +0000
+++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/objects.h	Thu Dec 12 10:45:05 2013 +0000
@@ -65,7 +65,6 @@
 
 struct i2c_s {
     I2CName  i2c;
-    uint32_t clk_speed;
 };
 
 struct pwmout_s {
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/pwmout_api.c	Mon Dec 09 11:15:04 2013 +0000
+++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/pwmout_api.c	Thu Dec 12 10:45:05 2013 +0000
@@ -22,24 +22,17 @@
 // Only TIM2 and TIM3 can be used (TIM1 and TIM4 are used by the us_ticker)
 static const PinMap PinMap_PWM[] = {
     // TIM2
-    {PA_2,  PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM2_CH3 OK
-    {PA_3,  PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM2_CH4 OK
+    {PA_2,  PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM2_CH3 - ARDUINO D1 (extra)
+    {PA_3,  PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM2_CH4 - ARDUINO D0 (extra)
     // TIM2 remap
-    {PA_15, PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 5)}, // TIM2r_CH1 FAIL
-    {PB_3,  PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 5)}, // TIM2r_CH2 FAIL - ARDUINO D3
-    {PB_10, PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 5)}, // TIM2r_CH3 OK - ARDUINO D6
-    {PB_11, PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 5)}, // TIM2r_CH4 OK
+    {PB_3,  PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 5)}, // TIM2r_CH2 - ARDUINO D3
+    {PB_10, PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 5)}, // TIM2r_CH3 - ARDUINO D6
     // TIM3
-    {PA_6,  PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM3_CH1 OK
-    {PA_7,  PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM3_CH2 OK - ARDUINO D11
-    {PB_1,  PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM3_CH4 OK
+    {PA_6,  PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM3_CH1 - ARDUINO D12 (extra)
+    {PA_7,  PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM3_CH2 - ARDUINO D11
     // TIM3 remap
-    {PB_4,  PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 6)}, // TIM3r_CH1 FAIL - ARDUINO D5
-    {PC_6,  PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 6)}, // TIM3r_CH1 OK
-    {PC_7,  PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 6)}, // TIM3r_CH2 OK - ARDUINO D9
-    {PB_5,  PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 6)}, // TIM3r_CH2 FAIL - Bug confirmed in ES
-    {PC_8,  PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 6)}, // TIM3r_CH3 OK
-    {PC_9,  PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 6)}, // TIM3r_CH4 OK
+    {PB_4,  PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 6)}, // TIM3r_CH1 - ARDUINO D5
+    {PC_7,  PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 6)}, // TIM3r_CH2 - ARDUINO D9
     {NC,    NC,    0}
 };
 
@@ -90,22 +83,26 @@
     TIM_OCInitStructure.TIM_Pulse = obj->pulse;
     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
 
-    if ((obj->pin == PA_6) || (obj->pin == PA_15) || (obj->pin == PB_4) || (obj->pin == PC_6)) { // TIM Channel 1
+    // TIM Channel 1
+    if ((obj->pin == PA_6) || (obj->pin == PB_4)) {
         TIM_OC1PreloadConfig(tim, TIM_OCPreload_Enable);
         TIM_OC1Init(tim, &TIM_OCInitStructure);
     }
 
-    if ((obj->pin == PA_7) || (obj->pin == PB_3) || (obj->pin == PB_5) || (obj->pin == PC_7)) { // TIM Channel 2
+    // TIM Channel 2    
+    if ((obj->pin == PA_7) || (obj->pin == PB_3) || (obj->pin == PC_7)) {
         TIM_OC2PreloadConfig(tim, TIM_OCPreload_Enable);
         TIM_OC2Init(tim, &TIM_OCInitStructure);
     }
 
-    if ((obj->pin == PA_2) || (obj->pin == PB_10) || (obj->pin == PC_8)) { // TIM Channel 3
+    // TIM Channel 3    
+    if ((obj->pin == PA_2) || (obj->pin == PB_10)) {
         TIM_OC3PreloadConfig(tim, TIM_OCPreload_Enable);
         TIM_OC3Init(tim, &TIM_OCInitStructure);
     }
 
-    if ((obj->pin == PA_3) || (obj->pin == PB_1) || (obj->pin == PB_11) || (obj->pin == PC_9)) { // TIM Channel 4
+    // TIM Channel 4
+    if (obj->pin == PA_3) {
         TIM_OC4PreloadConfig(tim, TIM_OCPreload_Enable);
         TIM_OC4Init(tim, &TIM_OCInitStructure);
     }
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/serial_api.c	Mon Dec 09 11:15:04 2013 +0000
+++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/serial_api.c	Thu Dec 12 10:45:05 2013 +0000
@@ -13,19 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-//==============================================================================
-// STM32F103
-//==============================================================================  
 #include "serial_api.h"
 #include "cmsis.h"
 #include "pinmap.h"
 #include "error.h"
 #include <string.h>
 
-/******************************************************************************
- * INITIALIZATION
- ******************************************************************************/
-
 static const PinMap PinMap_UART_TX[] = {
     {PA_9,  UART_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
     {PA_2,  UART_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
@@ -47,11 +40,24 @@
 int stdio_uart_inited = 0;
 serial_t stdio_uart;
 
-void serial_init(serial_t *obj, PinName tx, PinName rx) {
-    
-    USART_TypeDef *usart;
+static void init_usart(serial_t *obj) {
+    USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
     USART_InitTypeDef USART_InitStructure;
   
+    USART_Cmd(usart, DISABLE);
+
+    USART_InitStructure.USART_BaudRate = obj->baudrate;
+    USART_InitStructure.USART_WordLength = obj->databits;
+    USART_InitStructure.USART_StopBits = obj->stopbits;
+    USART_InitStructure.USART_Parity = obj->parity;
+    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
+    USART_Init(usart, &USART_InitStructure);
+    
+    USART_Cmd(usart, ENABLE);
+}
+
+void serial_init(serial_t *obj, PinName tx, PinName rx) {  
     // Determine the UART to use (UART_1, UART_2, ...)
     UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
     UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
@@ -62,10 +68,7 @@
     if (obj->uart == (UARTName)NC) {
         error("Serial pinout mapping failed");
     }
-    
-    // Get UART registers structure address
-    usart = (USART_TypeDef *)(obj->uart);
-  
+
     // Enable USART clock
     if (obj->uart == UART_1) {
         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); 
@@ -84,15 +87,7 @@
     obj->stopbits = USART_StopBits_1;
     obj->parity = USART_Parity_No;    
 
-    USART_InitStructure.USART_BaudRate = obj->baudrate;
-    USART_InitStructure.USART_WordLength = obj->databits;
-    USART_InitStructure.USART_StopBits = obj->stopbits;
-    USART_InitStructure.USART_Parity = obj->parity;
-    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
-    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
-    USART_Init(usart, &USART_InitStructure);
-    
-    USART_Cmd(usart, ENABLE);
+    init_usart(obj);
 
     // The index is used by irq
     if (obj->uart == UART_1) obj->index = 0;
@@ -111,31 +106,11 @@
 }
 
 void serial_baud(serial_t *obj, int baudrate) {
-    USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
-    USART_InitTypeDef USART_InitStructure;
-    
-    // Save new value
     obj->baudrate = baudrate;
-
-    USART_Cmd(usart, DISABLE);
-
-    USART_InitStructure.USART_BaudRate = obj->baudrate;
-    USART_InitStructure.USART_WordLength = obj->databits;
-    USART_InitStructure.USART_StopBits = obj->stopbits;
-    USART_InitStructure.USART_Parity = obj->parity;
-    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
-    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
-    USART_Init(usart, &USART_InitStructure);
-    
-    USART_Cmd(usart, ENABLE);
+    init_usart(obj);
 }
 
 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
-    USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
-    USART_InitTypeDef USART_InitStructure;
-
-    // Save new values
-  
     if (data_bits == 8) {
         obj->databits = USART_WordLength_8b;
     }
@@ -164,17 +139,7 @@
         obj->stopbits = USART_StopBits_1;
     }
 
-    USART_Cmd(usart, DISABLE);
-      
-    USART_InitStructure.USART_BaudRate = obj->baudrate;
-    USART_InitStructure.USART_WordLength = obj->databits;
-    USART_InitStructure.USART_StopBits = obj->stopbits;
-    USART_InitStructure.USART_Parity = obj->parity;
-    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
-    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
-    USART_Init(usart, &USART_InitStructure);
-    
-    USART_Cmd(usart, ENABLE);
+    init_usart(obj);
 }
 
 /******************************************************************************
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/spi_api.c	Mon Dec 09 11:15:04 2013 +0000
+++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/spi_api.c	Thu Dec 12 10:45:05 2013 +0000
@@ -13,9 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-//==============================================================================
-// STM32F103
-//==============================================================================
 #include "spi_api.h"
 
 #if DEVICE_SPI
@@ -45,16 +42,33 @@
 
 // Only used in Slave mode
 static const PinMap PinMap_SPI_SSEL[] = {
-    {PA_4,  SPI_1, STM_PIN_DATA(GPIO_Mode_IN_FLOATING, 0)},
-    {PA_15, SPI_1, STM_PIN_DATA(GPIO_Mode_IN_FLOATING, 1)}, // Remap
+    {PB_6,  SPI_1, STM_PIN_DATA(GPIO_Mode_IN_FLOATING, 0)}, // Generic IO, not real H/W NSS pin
+    //{PA_4,  SPI_1, STM_PIN_DATA(GPIO_Mode_IN_FLOATING, 0)},
+    //{PA_15, SPI_1, STM_PIN_DATA(GPIO_Mode_IN_FLOATING, 1)}, // Remap
     {NC,    NC,    0}
 };
 
-void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
+static void init_spi(spi_t *obj) {
+    SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
+    SPI_InitTypeDef SPI_InitStructure;
+
+    SPI_Cmd(spi, DISABLE);
 
-    SPI_TypeDef *spi;
-    SPI_InitTypeDef SPI_InitStructure;
-  
+    SPI_InitStructure.SPI_Mode = obj->mode;
+    SPI_InitStructure.SPI_NSS = obj->nss;    
+    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;    
+    SPI_InitStructure.SPI_DataSize = obj->bits;
+    SPI_InitStructure.SPI_CPOL = obj->cpol;
+    SPI_InitStructure.SPI_CPHA = obj->cpha;    
+    SPI_InitStructure.SPI_BaudRatePrescaler = obj->br_presc;
+    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
+    SPI_InitStructure.SPI_CRCPolynomial = 7;
+    SPI_Init(spi, &SPI_InitStructure);
+
+    SPI_Cmd(spi, ENABLE);
+}
+
+void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
     // Determine the SPI to use
     SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
     SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
@@ -69,9 +83,6 @@
     if (obj->spi == (SPIName)NC) {
         error("SPI pinout mapping failed");
     }
-
-    // Get SPI registers structure address
-    spi = (SPI_TypeDef *)(obj->spi);
     
     // Enable SPI clock
     if (obj->spi == SPI_1) {
@@ -99,22 +110,10 @@
     else { // Slave
         pinmap_pinout(ssel, PinMap_SPI_SSEL);
         obj->mode = SPI_Mode_Slave;
-        obj->nss = SPI_NSS_Hard;
+        obj->nss = SPI_NSS_Soft;
     }
 
-    // SPI configuration    
-    SPI_InitStructure.SPI_Mode = obj->mode;
-    SPI_InitStructure.SPI_NSS = obj->nss;    
-    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;    
-    SPI_InitStructure.SPI_DataSize = obj->bits;
-    SPI_InitStructure.SPI_CPOL = obj->cpol;
-    SPI_InitStructure.SPI_CPHA = obj->cpha;    
-    SPI_InitStructure.SPI_BaudRatePrescaler = obj->br_presc;
-    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
-    SPI_InitStructure.SPI_CRCPolynomial = 7;
-    SPI_Init(spi, &SPI_InitStructure);
-
-    SPI_Cmd(spi, ENABLE);    
+    init_spi(obj);
 }
 
 void spi_free(spi_t *obj) {
@@ -122,12 +121,8 @@
     SPI_I2S_DeInit(spi);
 }
 
-void spi_format(spi_t *obj, int bits, int mode, int slave) {
-    SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
-    SPI_InitTypeDef SPI_InitStructure;
-
+void spi_format(spi_t *obj, int bits, int mode, int slave) {  
     // Save new values
-  
     if (bits == 8) {
         obj->bits = SPI_DataSize_8b;
     }
@@ -163,26 +158,10 @@
         obj->nss = SPI_NSS_Hard;      
     }
     
-    SPI_Cmd(spi, DISABLE);
-
-    SPI_InitStructure.SPI_Mode = obj->mode;
-    SPI_InitStructure.SPI_NSS = obj->nss;    
-    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;    
-    SPI_InitStructure.SPI_DataSize = obj->bits;
-    SPI_InitStructure.SPI_CPOL = obj->cpol;
-    SPI_InitStructure.SPI_CPHA = obj->cpha;    
-    SPI_InitStructure.SPI_BaudRatePrescaler = obj->br_presc;
-    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
-    SPI_InitStructure.SPI_CRCPolynomial = 7;    
-    SPI_Init(spi, &SPI_InitStructure);
-
-    SPI_Cmd(spi, ENABLE);
+    init_spi(obj);
 }
 
 void spi_frequency(spi_t *obj, int hz) {
-    SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
-    SPI_InitTypeDef SPI_InitStructure;
-
     // Get SPI clock frequency
     uint32_t PCLK = SystemCoreClock >> 1;
 
@@ -203,20 +182,7 @@
     // Save new value
     obj->br_presc = ((baud_rate > 7) ? (7 << 3) : (baud_rate << 3));
  
-    SPI_Cmd(spi, DISABLE);
-    
-    SPI_InitStructure.SPI_Mode = obj->mode;
-    SPI_InitStructure.SPI_NSS = obj->nss;    
-    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;    
-    SPI_InitStructure.SPI_DataSize = obj->bits;
-    SPI_InitStructure.SPI_CPOL = obj->cpol;
-    SPI_InitStructure.SPI_CPHA = obj->cpha;    
-    SPI_InitStructure.SPI_BaudRatePrescaler = obj->br_presc;
-    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
-    SPI_InitStructure.SPI_CRCPolynomial = 7;    
-    SPI_Init(spi, &SPI_InitStructure);
-
-    SPI_Cmd(spi, ENABLE);
+    init_spi(obj);
 }
 
 static inline int ssp_readable(spi_t *obj) {