diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_MICRO/startup_stm32f10x_md.s b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_MICRO/startup_stm32f10x_md.s
new file mode 100644
index 0000000000..3f86c837d9
--- /dev/null
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_MICRO/startup_stm32f10x_md.s
@@ -0,0 +1,313 @@
+;******************** (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.
+;* <<< Use Configuration Wizard in Context Menu >>>
+;*******************************************************************************
+; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
+; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+;*******************************************************************************
+
+; Amount of memory (in bytes) allocated for Stack
+; Tailor this value to your application needs
+; Stack Configuration
+; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
+;
+
+Stack_Size EQU 0x00000400
+
+ AREA STACK, NOINIT, READWRITE, ALIGN=3
+ EXPORT __initial_sp
+
+Stack_Mem SPACE Stack_Size
+
+__initial_sp EQU 0x20000000 ; Top of RAM
+
+
+; Heap Configuration
+; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
+;
+
+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
+
+ PRESERVE8
+ THUMB
+
+
+; Vector Table Mapped to Address 0 at Reset
+ AREA RESET, DATA, READONLY
+ EXPORT __Vectors
+ EXPORT __Vectors_End
+ EXPORT __Vectors_Size
+
+__Vectors DCD __initial_sp ; Top of Stack
+ DCD Reset_Handler ; Reset Handler
+ DCD NMI_Handler ; NMI Handler
+ DCD HardFault_Handler ; Hard Fault Handler
+ DCD MemManage_Handler ; MPU Fault Handler
+ DCD BusFault_Handler ; Bus Fault Handler
+ DCD UsageFault_Handler ; Usage Fault Handler
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD SVC_Handler ; SVCall Handler
+ DCD DebugMon_Handler ; Debug Monitor Handler
+ DCD 0 ; Reserved
+ DCD PendSV_Handler ; PendSV Handler
+ DCD SysTick_Handler ; SysTick Handler
+
+ ; External Interrupts
+ DCD WWDG_IRQHandler ; Window Watchdog
+ DCD PVD_IRQHandler ; PVD through EXTI Line detect
+ DCD TAMPER_IRQHandler ; Tamper
+ DCD RTC_IRQHandler ; RTC
+ DCD FLASH_IRQHandler ; Flash
+ DCD RCC_IRQHandler ; RCC
+ DCD EXTI0_IRQHandler ; EXTI Line 0
+ DCD EXTI1_IRQHandler ; EXTI Line 1
+ DCD EXTI2_IRQHandler ; EXTI Line 2
+ DCD EXTI3_IRQHandler ; EXTI Line 3
+ DCD EXTI4_IRQHandler ; EXTI Line 4
+ DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1
+ DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2
+ DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3
+ DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4
+ DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5
+ DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6
+ DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7
+ DCD ADC1_2_IRQHandler ; ADC1_2
+ DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX
+ DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0
+ DCD CAN1_RX1_IRQHandler ; CAN1 RX1
+ DCD CAN1_SCE_IRQHandler ; CAN1 SCE
+ DCD EXTI9_5_IRQHandler ; EXTI Line 9..5
+ DCD TIM1_BRK_IRQHandler ; TIM1 Break
+ DCD TIM1_UP_IRQHandler ; TIM1 Update
+ DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation
+ DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
+ DCD TIM2_IRQHandler ; TIM2
+ DCD TIM3_IRQHandler ; TIM3
+ DCD TIM4_IRQHandler ; TIM4
+ DCD I2C1_EV_IRQHandler ; I2C1 Event
+ DCD I2C1_ER_IRQHandler ; I2C1 Error
+ DCD I2C2_EV_IRQHandler ; I2C2 Event
+ DCD I2C2_ER_IRQHandler ; I2C2 Error
+ DCD SPI1_IRQHandler ; SPI1
+ DCD SPI2_IRQHandler ; SPI2
+ DCD USART1_IRQHandler ; USART1
+ DCD USART2_IRQHandler ; USART2
+ DCD USART3_IRQHandler ; USART3
+ DCD EXTI15_10_IRQHandler ; EXTI Line 15..10
+ DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line
+ DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
+__Vectors_End
+
+__Vectors_Size EQU __Vectors_End - __Vectors
+
+ AREA |.text|, CODE, READONLY
+
+; Reset handler
+Reset_Handler PROC
+ EXPORT Reset_Handler [WEAK]
+ IMPORT __main
+ IMPORT SystemInit
+ LDR R0, =SystemInit
+ BLX R0
+ LDR R0, =__main
+ BX R0
+ ENDP
+
+; Dummy Exception Handlers (infinite loops which can be modified)
+
+NMI_Handler PROC
+ EXPORT NMI_Handler [WEAK]
+ B .
+ ENDP
+HardFault_Handler\
+ PROC
+ EXPORT HardFault_Handler [WEAK]
+ B .
+ ENDP
+MemManage_Handler\
+ PROC
+ EXPORT MemManage_Handler [WEAK]
+ B .
+ ENDP
+BusFault_Handler\
+ PROC
+ EXPORT BusFault_Handler [WEAK]
+ B .
+ ENDP
+UsageFault_Handler\
+ PROC
+ EXPORT UsageFault_Handler [WEAK]
+ B .
+ ENDP
+SVC_Handler PROC
+ EXPORT SVC_Handler [WEAK]
+ B .
+ ENDP
+DebugMon_Handler\
+ PROC
+ EXPORT DebugMon_Handler [WEAK]
+ B .
+ ENDP
+PendSV_Handler PROC
+ EXPORT PendSV_Handler [WEAK]
+ B .
+ ENDP
+SysTick_Handler PROC
+ EXPORT SysTick_Handler [WEAK]
+ B .
+ ENDP
+
+Default_Handler PROC
+
+ EXPORT WWDG_IRQHandler [WEAK]
+ EXPORT PVD_IRQHandler [WEAK]
+ EXPORT TAMPER_IRQHandler [WEAK]
+ EXPORT RTC_IRQHandler [WEAK]
+ EXPORT FLASH_IRQHandler [WEAK]
+ EXPORT RCC_IRQHandler [WEAK]
+ EXPORT EXTI0_IRQHandler [WEAK]
+ EXPORT EXTI1_IRQHandler [WEAK]
+ EXPORT EXTI2_IRQHandler [WEAK]
+ EXPORT EXTI3_IRQHandler [WEAK]
+ EXPORT EXTI4_IRQHandler [WEAK]
+ EXPORT DMA1_Channel1_IRQHandler [WEAK]
+ EXPORT DMA1_Channel2_IRQHandler [WEAK]
+ EXPORT DMA1_Channel3_IRQHandler [WEAK]
+ EXPORT DMA1_Channel4_IRQHandler [WEAK]
+ EXPORT DMA1_Channel5_IRQHandler [WEAK]
+ EXPORT DMA1_Channel6_IRQHandler [WEAK]
+ EXPORT DMA1_Channel7_IRQHandler [WEAK]
+ EXPORT ADC1_2_IRQHandler [WEAK]
+ EXPORT USB_HP_CAN1_TX_IRQHandler [WEAK]
+ EXPORT USB_LP_CAN1_RX0_IRQHandler [WEAK]
+ EXPORT CAN1_RX1_IRQHandler [WEAK]
+ EXPORT CAN1_SCE_IRQHandler [WEAK]
+ EXPORT EXTI9_5_IRQHandler [WEAK]
+ EXPORT TIM1_BRK_IRQHandler [WEAK]
+ EXPORT TIM1_UP_IRQHandler [WEAK]
+ EXPORT TIM1_TRG_COM_IRQHandler [WEAK]
+ EXPORT TIM1_CC_IRQHandler [WEAK]
+ EXPORT TIM2_IRQHandler [WEAK]
+ EXPORT TIM3_IRQHandler [WEAK]
+ EXPORT TIM4_IRQHandler [WEAK]
+ EXPORT I2C1_EV_IRQHandler [WEAK]
+ EXPORT I2C1_ER_IRQHandler [WEAK]
+ EXPORT I2C2_EV_IRQHandler [WEAK]
+ EXPORT I2C2_ER_IRQHandler [WEAK]
+ EXPORT SPI1_IRQHandler [WEAK]
+ EXPORT SPI2_IRQHandler [WEAK]
+ EXPORT USART1_IRQHandler [WEAK]
+ EXPORT USART2_IRQHandler [WEAK]
+ EXPORT USART3_IRQHandler [WEAK]
+ EXPORT EXTI15_10_IRQHandler [WEAK]
+ EXPORT RTCAlarm_IRQHandler [WEAK]
+ EXPORT USBWakeUp_IRQHandler [WEAK]
+
+WWDG_IRQHandler
+PVD_IRQHandler
+TAMPER_IRQHandler
+RTC_IRQHandler
+FLASH_IRQHandler
+RCC_IRQHandler
+EXTI0_IRQHandler
+EXTI1_IRQHandler
+EXTI2_IRQHandler
+EXTI3_IRQHandler
+EXTI4_IRQHandler
+DMA1_Channel1_IRQHandler
+DMA1_Channel2_IRQHandler
+DMA1_Channel3_IRQHandler
+DMA1_Channel4_IRQHandler
+DMA1_Channel5_IRQHandler
+DMA1_Channel6_IRQHandler
+DMA1_Channel7_IRQHandler
+ADC1_2_IRQHandler
+USB_HP_CAN1_TX_IRQHandler
+USB_LP_CAN1_RX0_IRQHandler
+CAN1_RX1_IRQHandler
+CAN1_SCE_IRQHandler
+EXTI9_5_IRQHandler
+TIM1_BRK_IRQHandler
+TIM1_UP_IRQHandler
+TIM1_TRG_COM_IRQHandler
+TIM1_CC_IRQHandler
+TIM2_IRQHandler
+TIM3_IRQHandler
+TIM4_IRQHandler
+I2C1_EV_IRQHandler
+I2C1_ER_IRQHandler
+I2C2_EV_IRQHandler
+I2C2_ER_IRQHandler
+SPI1_IRQHandler
+SPI2_IRQHandler
+USART1_IRQHandler
+USART2_IRQHandler
+USART3_IRQHandler
+EXTI15_10_IRQHandler
+RTCAlarm_IRQHandler
+USBWakeUp_IRQHandler
+
+ B .
+
+ 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*****
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_MICRO/stm32f10x.sct b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_MICRO/stm32f10x.sct
new file mode 100644
index 0000000000..63c847a5f7
--- /dev/null
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_MICRO/stm32f10x.sct
@@ -0,0 +1,19 @@
+; *************************************************************
+; *** Scatter-Loading Description File generated by uVision ***
+; *************************************************************
+
+LR_IROM1 0x08000000 0x20000 { ; load region size_region (128K)
+
+ ER_IROM1 0x08000000 0x20000 { ; load address = execution address
+ *.o (RESET, +First)
+ *(InRoot$$Sections)
+ .ANY (+RO)
+ }
+
+ ; 59 vectors (16 core + 43 peripheral) * 4 bytes = 236 bytes to reserve (0xEC)
+ RW_IRAM1 (0x20000000+0xEC) (0x5000-0xEC) { ; RW data
+ .ANY (+RW +ZI)
+ }
+
+}
+
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_MICRO/sys.cpp b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_MICRO/sys.cpp
new file mode 100644
index 0000000000..2f1024ace8
--- /dev/null
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_MICRO/sys.cpp
@@ -0,0 +1,31 @@
+/* mbed Microcontroller Library - stackheap
+ * Copyright (C) 2009-2011 ARM Limited. All rights reserved.
+ *
+ * Setup a fixed single stack/heap memory model,
+ * between the top of the RW/ZI region and the stackpointer
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+
+extern char Image$$RW_IRAM1$$ZI$$Limit[];
+
+extern __value_in_regs struct __initial_stackheap __user_setup_stackheap(uint32_t R0, uint32_t R1, uint32_t R2, uint32_t R3) {
+ uint32_t zi_limit = (uint32_t)Image$$RW_IRAM1$$ZI$$Limit;
+ uint32_t sp_limit = __current_sp();
+
+ zi_limit = (zi_limit + 7) & ~0x7; // ensure zi_limit is 8-byte aligned
+
+ struct __initial_stackheap r;
+ r.heap_base = zi_limit;
+ r.heap_limit = sp_limit;
+ return r;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_STD/stm32f10x.sct b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_STD/stm32f10x.sct
index 94923dc97b..63c847a5f7 100644
--- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_STD/stm32f10x.sct
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F103RB/TOOLCHAIN_ARM_STD/stm32f10x.sct
@@ -2,17 +2,18 @@
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
-LR_IROM1 0x08000000 0x00010000 { ; load region size_region
- ER_IROM1 0x08000000 0x00010000 { ; load address = execution address
+LR_IROM1 0x08000000 0x20000 { ; load region size_region (128K)
+
+ ER_IROM1 0x08000000 0x20000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
- ;RW_IRAM1 0x20000000 0x00005000 { ; RW data
+
; 59 vectors (16 core + 43 peripheral) * 4 bytes = 236 bytes to reserve (0xEC)
- ; 20KB - 0xEC = 0x5000 - 0xEC = 0x4F14 bytes after reserved area
- RW_IRAM1 0x200000EC 0x00004F14 { ; RW data
+ RW_IRAM1 (0x20000000+0xEC) (0x5000-0xEC) { ; RW data
.ANY (+RW +ZI)
}
+
}
diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/analogin_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/analogin_api.c
new file mode 100644
index 0000000000..5e3dbbaadb
--- /dev/null
+++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/analogin_api.c
@@ -0,0 +1,104 @@
+/* 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.
+ */
+//==============================================================================
+// STM32F103
+//==============================================================================
+#include "analogin_api.h"
+#include "wait_api.h"
+
+#if DEVICE_ANALOGIN
+
+#include "cmsis.h"
+#include "pinmap.h"
+#include "error.h"
+
+static const PinMap PinMap_ADC[] = {
+ {PA_0, ADC_1, STM_PIN_DATA(GPIO_Mode_AIN, 0)},
+ {PA_1, ADC_1, STM_PIN_DATA(GPIO_Mode_AIN, 0)},
+ {PA_4, ADC_1, STM_PIN_DATA(GPIO_Mode_AIN, 0)},
+ {PB_0, ADC_2, STM_PIN_DATA(GPIO_Mode_AIN, 0)},
+ {PC_1, ADC_2, STM_PIN_DATA(GPIO_Mode_AIN, 0)},
+ {PC_0, ADC_2, STM_PIN_DATA(GPIO_Mode_AIN, 0)},
+ {NC, NC, 0}
+};
+
+void analogin_init(analogin_t *obj, PinName pin) {
+
+ ADC_TypeDef *adc;
+ ADC_InitTypeDef ADC_InitStructure;
+
+ // Get the peripheral name (ADC_1, ADC_2...) from the pin and assign it to the object
+ obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
+
+ if (obj->adc == (ADCName)NC) {
+ error("ADC pin mapping failed");
+ }
+
+ // Get ADC registers structure address
+ adc = (ADC_TypeDef *)(obj->adc);
+
+ // Enable ADC clock
+ RCC_ADCCLKConfig(RCC_PCLK2_Div4);
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2, ENABLE);
+
+ // Configure GPIO
+ pinmap_pinout(pin, PinMap_ADC);
+
+ // Configure ADC
+ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
+ ADC_InitStructure.ADC_ScanConvMode = DISABLE;
+ ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
+ ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
+ ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
+ ADC_InitStructure.ADC_NbrOfChannel = 1;
+ ADC_Init(adc, &ADC_InitStructure);
+
+ // Configure ADC channel
+ if (pin == PA_0) { ADC_RegularChannelConfig(adc, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5); }
+ if (pin == PA_1) { ADC_RegularChannelConfig(adc, ADC_Channel_1, 1, ADC_SampleTime_7Cycles5); }
+ if (pin == PA_4) { ADC_RegularChannelConfig(adc, ADC_Channel_4, 1, ADC_SampleTime_7Cycles5); }
+ if (pin == PB_0) { ADC_RegularChannelConfig(adc, ADC_Channel_8, 1, ADC_SampleTime_7Cycles5); }
+ if (pin == PC_1) { ADC_RegularChannelConfig(adc, ADC_Channel_11, 1, ADC_SampleTime_7Cycles5); }
+ if (pin == PC_0) { ADC_RegularChannelConfig(adc, ADC_Channel_10, 1, ADC_SampleTime_7Cycles5); }
+
+ // Enable ADC
+ ADC_Cmd(adc, ENABLE);
+
+ // Calibrate ADC
+ ADC_ResetCalibration(adc);
+ while(ADC_GetResetCalibrationStatus(adc));
+ ADC_StartCalibration(adc);
+ while(ADC_GetCalibrationStatus(adc));
+}
+
+static inline uint16_t adc_read(analogin_t *obj) {
+ // Get ADC registers structure address
+ ADC_TypeDef *adc = (ADC_TypeDef *)(obj->adc);
+ ADC_SoftwareStartConvCmd(adc, ENABLE); // Start conversion
+ while(ADC_GetFlagStatus(adc, ADC_FLAG_EOC) == RESET); // Wait end of conversion
+ return(ADC_GetConversionValue(adc)); // Get conversion value
+}
+
+uint16_t analogin_read_u16(analogin_t *obj) {
+ return(adc_read(obj));
+}
+
+float analogin_read(analogin_t *obj) {
+ uint16_t value = adc_read(obj);
+ return (float)value * (1.0f / (float)0xFFF); // 12 bits range
+}
+
+#endif
diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h
index 22c7e4a498..a0a07061a3 100644
--- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h
+++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h
@@ -22,15 +22,15 @@
#define DEVICE_INTERRUPTIN 0
-#define DEVICE_ANALOGIN 0
+#define DEVICE_ANALOGIN 1
#define DEVICE_ANALOGOUT 0
-#define DEVICE_SERIAL 0
+#define DEVICE_SERIAL 1
#define DEVICE_I2C 0
#define DEVICE_I2CSLAVE 0
-#define DEVICE_SPI 0
+#define DEVICE_SPI 1
#define DEVICE_SPISLAVE 0
#define DEVICE_RTC 0
diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/serial_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/serial_api.c
new file mode 100644
index 0000000000..0385485d6e
--- /dev/null
+++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/serial_api.c
@@ -0,0 +1,310 @@
+/* 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.
+ */
+//==============================================================================
+// STM32F103
+//==============================================================================
+#include "serial_api.h"
+#include "cmsis.h"
+#include "pinmap.h"
+#include "error.h"
+#include
+
+/******************************************************************************
+ * 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)},
+ {NC, NC, 0}
+};
+
+static const PinMap PinMap_UART_RX[] = {
+ {PA_10, UART_1, STM_PIN_DATA(GPIO_Mode_IN_FLOATING, 0)},
+ {PA_3, UART_2, STM_PIN_DATA(GPIO_Mode_IN_FLOATING, 0)},
+ {NC, NC, 0}
+};
+
+#define UART_NUM (2)
+
+static uint32_t serial_irq_ids[UART_NUM] = {0};
+
+static uart_irq_handler irq_handler;
+
+int stdio_uart_inited = 0;
+serial_t stdio_uart;
+
+void serial_init(serial_t *obj, PinName tx, PinName rx) {
+
+ USART_TypeDef *usart;
+ USART_InitTypeDef USART_InitStructure;
+
+ // 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);
+
+ // Get the peripheral name (UART_1, UART_2, ...) from the pin and assign it to the object
+ obj->uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
+
+ 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);
+ }
+ if (obj->uart == UART_2) {
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
+ }
+
+ // Configure the UART pins
+ pinmap_pinout(tx, PinMap_UART_TX);
+ pinmap_pinout(rx, PinMap_UART_RX);
+
+ // Configure UART
+ obj->baudrate = 9600;
+ obj->databits = USART_WordLength_8b;
+ 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);
+
+ // The index is used by irq
+ if (obj->uart == UART_1) obj->index = 0;
+ if (obj->uart == UART_2) obj->index = 1;
+
+ // For stdio management
+ if (obj->uart == STDIO_UART) {
+ stdio_uart_inited = 1;
+ memcpy(&stdio_uart, obj, sizeof(serial_t));
+ }
+
+}
+
+void serial_free(serial_t *obj) {
+ serial_irq_ids[obj->index] = 0;
+}
+
+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);
+}
+
+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;
+ }
+ else {
+ obj->databits = USART_WordLength_9b;
+ }
+
+ switch (parity) {
+ case ParityOdd:
+ case ParityForced0:
+ obj->parity = USART_Parity_Odd;
+ break;
+ case ParityEven:
+ case ParityForced1:
+ obj->parity = USART_Parity_Even;
+ break;
+ default: // ParityNone
+ obj->parity = USART_Parity_No;
+ break;
+ }
+
+ if (stop_bits == 2) {
+ obj->stopbits = USART_StopBits_2;
+ }
+ else {
+ 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);
+}
+
+/******************************************************************************
+ * INTERRUPTS HANDLING
+ ******************************************************************************/
+
+// not api
+void uart1_irq(void) {
+ USART_TypeDef *usart = (USART_TypeDef *)UART_1;
+ if (serial_irq_ids[0] != 0) {
+ if (USART_GetITStatus(usart, USART_IT_TXE) != RESET) {
+ irq_handler(serial_irq_ids[0], TxIrq);
+ }
+ if (USART_GetITStatus(usart, USART_IT_RXNE) != RESET) {
+ irq_handler(serial_irq_ids[0], RxIrq);
+ }
+ }
+}
+
+// not api
+void uart2_irq(void) {
+ USART_TypeDef *usart = (USART_TypeDef *)UART_2;
+ if (serial_irq_ids[1] != 0) {
+ if (USART_GetITStatus(usart, USART_IT_TXE) != RESET) {
+ irq_handler(serial_irq_ids[1], TxIrq);
+ }
+ if (USART_GetITStatus(usart, USART_IT_RXNE) != RESET) {
+ irq_handler(serial_irq_ids[1], RxIrq);
+ }
+ }
+}
+
+void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
+ irq_handler = handler;
+ serial_irq_ids[obj->index] = id;
+}
+
+void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
+ IRQn_Type irq_n = (IRQn_Type)0;
+ uint32_t vector = 0;
+ USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
+
+ if (obj->uart == UART_1) {
+ irq_n = USART1_IRQn;
+ vector = (uint32_t)&uart1_irq;
+ }
+
+ if (obj->uart == UART_2) {
+ irq_n = USART2_IRQn;
+ vector = (uint32_t)&uart2_irq;
+ }
+
+ if (enable) {
+
+ if (irq == RxIrq) {
+ USART_ITConfig(usart, USART_IT_RXNE, ENABLE);
+ }
+ else { // TxIrq
+ USART_ITConfig(usart, USART_IT_TXE, ENABLE);
+ }
+
+ NVIC_SetVector(irq_n, vector);
+ NVIC_EnableIRQ(irq_n);
+
+ } else { // disable
+
+ int all_disabled = 0;
+
+ if (irq == RxIrq) {
+ USART_ITConfig(usart, USART_IT_RXNE, DISABLE);
+ // Check if TxIrq is disabled too
+ if ((usart->CR1 & USART_CR1_TXEIE) == 0) all_disabled = 1;
+ }
+ else { // TxIrq
+ USART_ITConfig(usart, USART_IT_TXE, DISABLE);
+ // Check if RxIrq is disabled too
+ if ((usart->CR1 & USART_CR1_RXNEIE) == 0) all_disabled = 1;
+ }
+
+ if (all_disabled) NVIC_DisableIRQ(irq_n);
+
+ }
+}
+
+/******************************************************************************
+ * READ/WRITE
+ ******************************************************************************/
+
+int serial_getc(serial_t *obj) {
+ USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
+ while (!serial_readable(obj));
+ return (int)(USART_ReceiveData(usart));
+}
+
+void serial_putc(serial_t *obj, int c) {
+ USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
+ while (!serial_writable(obj));
+ USART_SendData(usart, (uint16_t)c);
+}
+
+int serial_readable(serial_t *obj) {
+ int status;
+ USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
+ // Check if data is received
+ status = ((USART_GetFlagStatus(usart, USART_FLAG_RXNE) != RESET) ? 1 : 0);
+ return status;
+}
+
+int serial_writable(serial_t *obj) {
+ int status;
+ USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
+ // Check if data is transmitted
+ status = ((USART_GetFlagStatus(usart, USART_FLAG_TXE) != RESET) ? 1 : 0);
+ return status;
+}
+
+void serial_clear(serial_t *obj) {
+ USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
+ USART_ClearFlag(usart, USART_FLAG_TXE);
+ USART_ClearFlag(usart, USART_FLAG_RXNE);
+}
+
+void serial_pinout_tx(PinName tx) {
+ pinmap_pinout(tx, PinMap_UART_TX);
+}
+
+void serial_break_set(serial_t *obj) {
+ USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
+ USART_SendBreak(usart);
+}
+
+void serial_break_clear(serial_t *obj) {
+}
diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/spi_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/spi_api.c
new file mode 100644
index 0000000000..512034d4d2
--- /dev/null
+++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/spi_api.c
@@ -0,0 +1,281 @@
+/* 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.
+ */
+//==============================================================================
+// STM32F103
+//==============================================================================
+#include "spi_api.h"
+
+#if DEVICE_SPI
+
+#include
+#include "cmsis.h"
+#include "pinmap.h"
+#include "error.h"
+
+static const PinMap PinMap_SPI_MOSI[] = {
+ {PA_7, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
+ {PB_5, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 1)}, // Remap
+ {NC, NC, 0}
+};
+
+static const PinMap PinMap_SPI_MISO[] = {
+ {PA_6, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
+ {PB_4, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 1)}, // Remap
+ {NC, NC, 0}
+};
+
+static const PinMap PinMap_SPI_SCLK[] = {
+ {PA_5, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)},
+ {PB_3, SPI_1, STM_PIN_DATA(GPIO_Mode_AF_PP, 1)}, // Remap
+ {NC, NC, 0}
+};
+
+// 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
+ {NC, NC, 0}
+};
+
+void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
+
+ SPI_TypeDef *spi;
+ SPI_InitTypeDef SPI_InitStructure;
+
+ // 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);
+ SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
+ SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
+
+ SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
+ SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
+
+ obj->spi = (SPIName)pinmap_merge(spi_data, spi_cntl);
+
+ 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) {
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
+ }
+ if (obj->spi == SPI_2) {
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
+ }
+
+ // Configure the SPI pins
+ pinmap_pinout(mosi, PinMap_SPI_MOSI);
+ pinmap_pinout(miso, PinMap_SPI_MISO);
+ pinmap_pinout(sclk, PinMap_SPI_SCLK);
+
+ // Save new values
+ obj->bits = SPI_DataSize_8b;
+ obj->cpol = SPI_CPOL_Low;
+ obj->cpha = SPI_CPHA_1Edge;
+ obj->br_presc = SPI_BaudRatePrescaler_64; // Closest to 1MHz (72MHz/64 = 1.125MHz)
+
+ if (ssel == NC) { // Master
+ obj->mode = SPI_Mode_Master;
+ obj->nss = SPI_NSS_Soft;
+ }
+ else { // Slave
+ pinmap_pinout(ssel, PinMap_SPI_SSEL);
+ obj->mode = SPI_Mode_Slave;
+ obj->nss = SPI_NSS_Hard;
+ }
+
+ // 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);
+}
+
+void spi_free(spi_t *obj) {
+ SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
+ 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;
+
+ // Save new values
+
+ if (bits == 8) {
+ obj->bits = SPI_DataSize_8b;
+ }
+ else {
+ obj->bits = SPI_DataSize_16b;
+ }
+
+ switch (mode) {
+ case 0:
+ obj->cpol = SPI_CPOL_Low;
+ obj->cpha = SPI_CPHA_1Edge;
+ break;
+ case 1:
+ obj->cpol = SPI_CPOL_Low;
+ obj->cpha = SPI_CPHA_2Edge;
+ break;
+ case 2:
+ obj->cpol = SPI_CPOL_High;
+ obj->cpha = SPI_CPHA_1Edge;
+ break;
+ default:
+ obj->cpol = SPI_CPOL_High;
+ obj->cpha = SPI_CPHA_2Edge;
+ break;
+ }
+
+ if (slave == 0) {
+ obj->mode = SPI_Mode_Master;
+ obj->nss = SPI_NSS_Soft;
+ }
+ else {
+ obj->mode = SPI_Mode_Slave;
+ 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);
+}
+
+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;
+
+ // Choose the baud rate divisor (between 2 and 256)
+ uint32_t divisor = PCLK / hz;
+
+ // Find the nearest power-of-2
+ divisor = (divisor > 0 ? divisor-1 : 0);
+ divisor |= divisor >> 1;
+ divisor |= divisor >> 2;
+ divisor |= divisor >> 4;
+ divisor |= divisor >> 8;
+ divisor |= divisor >> 16;
+ divisor++;
+
+ uint32_t baud_rate = __builtin_ffs(divisor) - 2;
+
+ // 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);
+}
+
+static inline int ssp_readable(spi_t *obj) {
+ int status;
+ SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
+ // Check if data is received
+ status = ((SPI_I2S_GetFlagStatus(spi, SPI_I2S_FLAG_RXNE) != RESET) ? 1 : 0);
+ return status;
+}
+
+static inline int ssp_writeable(spi_t *obj) {
+ int status;
+ SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
+ // Check if data is transmitted
+ status = ((SPI_I2S_GetFlagStatus(spi, SPI_I2S_FLAG_TXE) != RESET) ? 1 : 0);
+ return status;
+}
+
+static inline void ssp_write(spi_t *obj, int value) {
+ SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
+ while (!ssp_writeable(obj));
+ SPI_I2S_SendData(spi, (uint16_t)value);
+}
+
+static inline int ssp_read(spi_t *obj) {
+ SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
+ while (!ssp_readable(obj));
+ return (int)SPI_I2S_ReceiveData(spi);
+}
+
+static inline int ssp_busy(spi_t *obj) {
+ int status;
+ SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
+ status = ((SPI_I2S_GetFlagStatus(spi, SPI_I2S_FLAG_BSY) != RESET) ? 1 : 0);
+ return status;
+}
+
+int spi_master_write(spi_t *obj, int value) {
+ ssp_write(obj, value);
+ return ssp_read(obj);
+}
+
+int spi_slave_receive(spi_t *obj) {
+ return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
+};
+
+int spi_slave_read(spi_t *obj) {
+ SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
+ return (int)SPI_I2S_ReceiveData(spi);
+}
+
+void spi_slave_write(spi_t *obj, int value) {
+ SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
+ while (!ssp_writeable(obj));
+ SPI_I2S_SendData(spi, (uint16_t)value);
+}
+
+int spi_busy(spi_t *obj) {
+ return ssp_busy(obj);
+}
+
+#endif