mirror of https://github.com/ARMmbed/mbed-os.git
Add analogin, serial and spi support for NUCLEO_F103RB
parent
70dd0d891e
commit
415ac34b56
|
@ -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
|
||||||
|
; <h> Stack Configuration
|
||||||
|
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||||
|
; </h>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
; <h> Heap Configuration
|
||||||
|
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||||
|
; </h>
|
||||||
|
|
||||||
|
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*****
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -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 <rt_misc.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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
|
|
@ -2,17 +2,18 @@
|
||||||
; *** Scatter-Loading Description File generated by uVision ***
|
; *** Scatter-Loading Description File generated by uVision ***
|
||||||
; *************************************************************
|
; *************************************************************
|
||||||
|
|
||||||
LR_IROM1 0x08000000 0x00010000 { ; load region size_region
|
LR_IROM1 0x08000000 0x20000 { ; load region size_region (128K)
|
||||||
ER_IROM1 0x08000000 0x00010000 { ; load address = execution address
|
|
||||||
|
ER_IROM1 0x08000000 0x20000 { ; load address = execution address
|
||||||
*.o (RESET, +First)
|
*.o (RESET, +First)
|
||||||
*(InRoot$$Sections)
|
*(InRoot$$Sections)
|
||||||
.ANY (+RO)
|
.ANY (+RO)
|
||||||
}
|
}
|
||||||
;RW_IRAM1 0x20000000 0x00005000 { ; RW data
|
|
||||||
; 59 vectors (16 core + 43 peripheral) * 4 bytes = 236 bytes to reserve (0xEC)
|
; 59 vectors (16 core + 43 peripheral) * 4 bytes = 236 bytes to reserve (0xEC)
|
||||||
; 20KB - 0xEC = 0x5000 - 0xEC = 0x4F14 bytes after reserved area
|
RW_IRAM1 (0x20000000+0xEC) (0x5000-0xEC) { ; RW data
|
||||||
RW_IRAM1 0x200000EC 0x00004F14 { ; RW data
|
|
||||||
.ANY (+RW +ZI)
|
.ANY (+RW +ZI)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -22,15 +22,15 @@
|
||||||
|
|
||||||
#define DEVICE_INTERRUPTIN 0
|
#define DEVICE_INTERRUPTIN 0
|
||||||
|
|
||||||
#define DEVICE_ANALOGIN 0
|
#define DEVICE_ANALOGIN 1
|
||||||
#define DEVICE_ANALOGOUT 0
|
#define DEVICE_ANALOGOUT 0
|
||||||
|
|
||||||
#define DEVICE_SERIAL 0
|
#define DEVICE_SERIAL 1
|
||||||
|
|
||||||
#define DEVICE_I2C 0
|
#define DEVICE_I2C 0
|
||||||
#define DEVICE_I2CSLAVE 0
|
#define DEVICE_I2CSLAVE 0
|
||||||
|
|
||||||
#define DEVICE_SPI 0
|
#define DEVICE_SPI 1
|
||||||
#define DEVICE_SPISLAVE 0
|
#define DEVICE_SPISLAVE 0
|
||||||
|
|
||||||
#define DEVICE_RTC 0
|
#define DEVICE_RTC 0
|
||||||
|
|
|
@ -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 <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)},
|
||||||
|
{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) {
|
||||||
|
}
|
|
@ -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 <math.h>
|
||||||
|
#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
|
Loading…
Reference in New Issue