From 1dc7d758f96dd2b9bd7b03f01ca032d68b696cf0 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 2 Nov 2014 10:14:39 +0000 Subject: fish --- libopencm3/lib/stm32/f3/Makefile | 50 ++ libopencm3/lib/stm32/f3/adc.c | 1150 +++++++++++++++++++++++++ libopencm3/lib/stm32/f3/crc.c | 33 + libopencm3/lib/stm32/f3/dac.c | 31 + libopencm3/lib/stm32/f3/dma.c | 31 + libopencm3/lib/stm32/f3/flash.c | 63 ++ libopencm3/lib/stm32/f3/i2c.c | 486 +++++++++++ libopencm3/lib/stm32/f3/iwdg.c | 31 + libopencm3/lib/stm32/f3/libopencm3_stm32f3.ld | 106 +++ libopencm3/lib/stm32/f3/pwr.c | 40 + libopencm3/lib/stm32/f3/rcc.c | 465 ++++++++++ libopencm3/lib/stm32/f3/rtc.c | 38 + libopencm3/lib/stm32/f3/spi.c | 31 + libopencm3/lib/stm32/f3/timer.c | 33 + libopencm3/lib/stm32/f3/usart.c | 140 +++ libopencm3/lib/stm32/f3/vector_chipset.c | 27 + 16 files changed, 2755 insertions(+) create mode 100644 libopencm3/lib/stm32/f3/Makefile create mode 100644 libopencm3/lib/stm32/f3/adc.c create mode 100644 libopencm3/lib/stm32/f3/crc.c create mode 100644 libopencm3/lib/stm32/f3/dac.c create mode 100644 libopencm3/lib/stm32/f3/dma.c create mode 100644 libopencm3/lib/stm32/f3/flash.c create mode 100644 libopencm3/lib/stm32/f3/i2c.c create mode 100644 libopencm3/lib/stm32/f3/iwdg.c create mode 100644 libopencm3/lib/stm32/f3/libopencm3_stm32f3.ld create mode 100644 libopencm3/lib/stm32/f3/pwr.c create mode 100644 libopencm3/lib/stm32/f3/rcc.c create mode 100644 libopencm3/lib/stm32/f3/rtc.c create mode 100644 libopencm3/lib/stm32/f3/spi.c create mode 100644 libopencm3/lib/stm32/f3/timer.c create mode 100644 libopencm3/lib/stm32/f3/usart.c create mode 100644 libopencm3/lib/stm32/f3/vector_chipset.c (limited to 'libopencm3/lib/stm32/f3') diff --git a/libopencm3/lib/stm32/f3/Makefile b/libopencm3/lib/stm32/f3/Makefile new file mode 100644 index 0000000..5ef282a --- /dev/null +++ b/libopencm3/lib/stm32/f3/Makefile @@ -0,0 +1,50 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This library is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this library. If not, see . +## + +LIBNAME = libopencm3_stm32f3 +SRCLIBDIR ?= ../.. + +FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16 +PREFIX ?= arm-none-eabi + +CC = $(PREFIX)-gcc +AR = $(PREFIX)-ar +CFLAGS = -Os -g \ + -Wall -Wextra -Wimplicit-function-declaration \ + -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes \ + -Wundef -Wshadow \ + -I../../../include -fno-common \ + -mcpu=cortex-m4 -mthumb $(FP_FLAGS) -Wstrict-prototypes \ + -ffunction-sections -fdata-sections -MD -DSTM32F3 + +ARFLAGS = rcs + +OBJS = rcc.o adc.o i2c.o usart.o dma.o flash.o + +OBJS += gpio_common_all.o gpio_common_f0234.o \ + dac_common_all.o usart_common_all.o crc_common_all.o\ + iwdg_common_all.o spi_common_all.o dma_common_l1f013.o\ + timer_common_all.o timer_common_f234.o flash_common_f234.o \ + flash.o exti_common_all.o rcc_common_all.o spi_common_f03.o + +OBJS += usb.o usb_control.o usb_standard.o usb_f103.o + +VPATH += ../../usb:../:../../cm3:../common + +include ../../Makefile.include diff --git a/libopencm3/lib/stm32/f3/adc.c b/libopencm3/lib/stm32/f3/adc.c new file mode 100644 index 0000000..805bf2e --- /dev/null +++ b/libopencm3/lib/stm32/f3/adc.c @@ -0,0 +1,1150 @@ +/** @defgroup adc_file ADC + * + * @ingroup STM32F3xx + * + * @brief libopencm3 STM32F3xx Analog to Digital Converters + * + * @author @htmlonly © @endhtmlonly 2012 + * Ken Sarkies + * + * @date 30 August 2012 + * + * This library supports the A/D Converter Control System in the STM32 series + * of ARM Cortex Microcontrollers by ST Microelectronics. + * + * Devices can have up to three A/D converters each with their own set of + * registers. However all the A/D converters share a common clock which is + * prescaled from the APB2 clock by default by a minimum factor of 2 to a + * maximum of 8. The ADC resolution can be set to 12, 10, 8 or 6 bits. + * + * Each A/D converter has up to 19 channels: + * @li On ADC1 the analog channels 16 is internally connected to the + * temperature sensor, channel 17 to VREFINT, and channel 18 + * to VBATT. + * @li On ADC2 and ADC3 the analog channels 16 - 18 are not used. + * + * The conversions can occur as a one-off conversion whereby the process stops + * once conversion is complete. The conversions can also be continuous wherein + * a new conversion starts immediately the previous conversion has ended. + * + * Conversion can occur as a single channel conversion or a scan of a group of + * channels in either continuous or one-off mode. If more than one channel is + * converted in a scan group, DMA must be used to transfer the data as there is + * only one result register available. An interrupt can be set to occur at the + * end* + * of conversion, which occurs after all channels have been scanned. + * + * A discontinuous mode allows a subgroup of group of a channels to be + * converted in bursts of a given length. + * + * Injected conversions allow a second group of channels to be converted + * separately from the regular group. An interrupt can be set to occur at the + * end of conversion, which occurs after all channels have been scanned. + * + * @section adc_f3_api_ex Basic ADC Handling API. + * + * Example 1: Simple single channel conversion polled. Enable the peripheral + * clock and ADC, reset ADC and set the prescaler divider. Set multiple mode to + * independent. + * + * @code + * gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO1); + * rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN); + * adc_set_clk_prescale(RCC_CFGR_ADCPRE_BY2); + * adc_disable_scan_mode(ADC1); + * adc_set_single_conversion_mode(ADC1); + * adc_set_sample_time(ADC1, ADC_CHANNEL0, ADC_SMPR1_SMP_1DOT5CYC); + * uint8_t channels[] = ADC_CHANNEL0; + * adc_set_regular_sequence(ADC1, 1, channels); + * adc_set_multi_mode(ADC_CCR_MULTI_INDEPENDENT); + * adc_power_on(ADC1); + * adc_start_conversion_regular(ADC1); + * while (! adc_eoc(ADC1)); + * reg16 = adc_read_regular(ADC1); + * @endcode + * + * LGPL License Terms @ref lgpl_license + */ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Ken Sarkies + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + +/**@{*/ + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Off + * + * Turn off the ADC to reduce power consumption to a few microamps. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base +*/ + +void adc_off(uint32_t adc) +{ + ADC_CR(adc) &= ~ADC_CR_ADEN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable Analog Watchdog for Regular Conversions + * + * The analog watchdog allows the monitoring of an analog signal between two + * threshold levels. The thresholds must be preset. Comparison is done before + * data alignment takes place, so the thresholds are left-aligned. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_enable_analog_watchdog_regular(uint32_t adc) +{ + ADC_CFGR(adc) |= ADC_CFGR_AWD1EN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable Analog Watchdog for Regular Conversions + * + * The analog watchdog allows the monitoring of an analog signal between two + * threshold levels. The thresholds must be preset. Comparison is done before + * data alignment takes place, so the thresholds are left-aligned. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ +void adc_disable_analog_watchdog_regular(uint32_t adc) +{ + ADC_CFGR(adc) &= ~ADC_CFGR_AWD1EN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable Analog Watchdog for Injected Conversions + * + * The analog watchdog allows the monitoring of an analog signal between two + * threshold levels. The thresholds must be preset. Comparison is done before + * data alignment takes place, so the thresholds are left-aligned. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_enable_analog_watchdog_injected(uint32_t adc) +{ + ADC_CFGR(adc) |= ADC_CFGR_JAWD1EN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable Analog Watchdog for Injected Conversions + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_disable_analog_watchdog_injected(uint32_t adc) +{ + ADC_CFGR(adc) &= ~ADC_CFGR_JAWD1EN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable Discontinuous Mode for Regular Conversions + * + * In this mode the ADC converts, on each trigger, a subgroup of up to 8 of the + * defined regular channel group. The subgroup is defined by the number of + * consecutive channels to be converted. After a subgroup has been converted + * the next trigger will start conversion of the immediately following subgroup + * of the same length or until the whole group has all been converted. When the + * whole group has been converted, the next trigger will restart conversion of + * the subgroup at the beginning of the whole group. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base @param[in] length Unsigned int8. Number of channels in the + * group @ref adc_cr1_discnum + */ + +void adc_enable_discontinuous_mode_regular(uint32_t adc, uint8_t length) +{ + if ((length-1) > 7) { + return; + } + ADC_CFGR(adc) |= ADC_CFGR_DISCEN; + ADC_CFGR(adc) |= ((length-1) << ADC_CFGR_DISCNUM_SHIFT); +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable Discontinuous Mode for Regular Conversions + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_disable_discontinuous_mode_regular(uint32_t adc) +{ + ADC_CFGR(adc) &= ~ADC_CFGR_DISCEN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable Discontinuous Mode for Injected Conversions + * + * In this mode the ADC converts sequentially one channel of the defined group + * of injected channels, cycling back to the first channel in the group once + * the entire group has been converted. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_enable_discontinuous_mode_injected(uint32_t adc) +{ + ADC_CFGR(adc) |= ADC_CFGR_JDISCEN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable Discontinuous Mode for Injected Conversions + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_disable_discontinuous_mode_injected(uint32_t adc) +{ + ADC_CFGR(adc) &= ~ADC_CFGR_JDISCEN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable Automatic Injected Conversions + * + * The ADC converts a defined injected group of channels immediately after the + * regular channels have been converted. The external trigger on the injected + * channels is disabled as required. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_enable_automatic_injected_group_conversion(uint32_t adc) +{ + adc_disable_external_trigger_injected(adc); + ADC_CFGR(adc) |= ADC_CFGR_JAUTO; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable Automatic Injected Conversions + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_disable_automatic_injected_group_conversion(uint32_t adc) +{ + ADC_CFGR(adc) &= ~ADC_CFGR_JAUTO; +} +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable Analog Watchdog for All Regular and/or Injected Channels + * + * The analog watchdog allows the monitoring of an analog signal between two + * threshold levels. The thresholds must be preset. Comparison is done before + * data alignment takes place, so the thresholds are left-aligned. + * + * @note The analog watchdog must be enabled for either or both of the regular + * or injected channels. If neither are enabled, the analog watchdog feature + * will be disabled. + * + * @ref adc_enable_analog_watchdog_injected, @ref + * adc_enable_analog_watchdog_regular. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_enable_analog_watchdog_on_all_channels(uint32_t adc) +{ + ADC_CFGR(adc) &= ~ADC_CFGR_AWD1SGL; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable Analog Watchdog for a Selected Channel + * + * The analog watchdog allows the monitoring of an analog signal between two + * threshold levels. The thresholds must be preset. Comparison is done before + * data alignment takes place, so the thresholds are left-aligned. + * + * @note The analog watchdog must be enabled for either or both of the regular + * or injected channels. If neither are enabled, the analog watchdog feature + * will be disabled. If both are enabled, the same channel number is monitored + * @ref adc_enable_analog_watchdog_injected, @ref + * adc_enable_analog_watchdog_regular. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + * @param[in] channel Unsigned int8. ADC channel numbe + * @ref adc_watchdog_channel + */ + +void adc_enable_analog_watchdog_on_selected_channel(uint32_t adc, + uint8_t channel) +{ + uint32_t reg32; + + reg32 = (ADC_CFGR(adc) & ~ADC_CFGR_AWD1CH_MASK); /* Clear bit [4:0]. */ + if (channel < 18) { + reg32 |= channel; + } + ADC_CFGR(adc) = reg32; + ADC_CFGR(adc) |= ADC_CFGR_AWD1SGL; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set Scan Mode + * + * In this mode a conversion consists of a scan of the predefined set of + * channels, regular and injected, each channel conversion immediately + * following the previous one. It can use single, continuous or discontinuous + * mode. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +/* +void adc_enable_scan_mode(uint32_t adc) +{ + ADC_CR1(adc) |= ADC_CR1_SCAN; +} +*/ + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable Scan Mode + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +/* +void adc_disable_scan_mode(uint32_t adc) +{ + ADC_CR1(adc) &= ~ADC_CR1_SCAN; +} +*/ + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable Injected End-Of-Conversion Interrupt + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_enable_eoc_interrupt_injected(uint32_t adc) +{ + ADC_IER(adc) |= ADC_IER_JEOCIE; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable Injected End-Of-Conversion Interrupt + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_disable_eoc_interrupt_injected(uint32_t adc) +{ + ADC_IER(adc) &= ~ADC_IER_JEOCIE; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable Analog Watchdog Interrupt + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_enable_all_awd_interrupt(uint32_t adc) +{ + ADC_IER(adc) |= ADC_IER_AWD1IE; + ADC_IER(adc) |= ADC_IER_AWD2IE; + ADC_IER(adc) |= ADC_IER_AWD3IE; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable Analog Watchdog Interrupt + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_disable_all_awd_interrupt(uint32_t adc) +{ + ADC_IER(adc) &= ~ADC_IER_AWD1IE; + ADC_IER(adc) &= ~ADC_IER_AWD2IE; + ADC_IER(adc) &= ~ADC_IER_AWD3IE; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable Regular End-Of-Conversion Interrupt + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_enable_eoc_interrupt(uint32_t adc) +{ + ADC_IER(adc) |= ADC_IER_EOCIE; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable Regular End-Of-Conversion Interrupt + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_disable_eoc_interrupt(uint32_t adc) +{ + ADC_IER(adc) &= ~ADC_IER_EOCIE; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Software Triggered Conversion on Regular Channels + * + * This starts conversion on a set of defined regular channels. It is cleared + * by hardware once conversion starts. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_start_conversion_regular(uint32_t adc) +{ + /* Start conversion on regular channels. */ + ADC_CR(adc) |= ADC_CR_ADSTART; + + /* Wait until the ADC starts the conversion. */ + while (ADC_CR(adc) & ADC_CR_ADSTART); +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Software Triggered Conversion on Injected Channels + * + * This starts conversion on a set of defined injected channels. It is cleared + * by hardware once conversion starts. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_start_conversion_injected(uint32_t adc) +{ + /* Start conversion on injected channels. */ + ADC_CR(adc) |= ADC_CR_JADSTART; + + /* Wait until the ADC starts the conversion. */ + while (ADC_CR(adc) & ADC_CR_JADSTART); +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set the Data as Left Aligned + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_set_left_aligned(uint32_t adc) +{ + ADC_CFGR(adc) |= ADC_CFGR_ALIGN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set the Data as Right Aligned + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_set_right_aligned(uint32_t adc) +{ + ADC_CFGR(adc) &= ~ADC_CFGR_ALIGN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable DMA Transfers + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + */ + +void adc_enable_dma(uint32_t adc) +{ + ADC_CFGR(adc) |= ADC_CFGR_DMAEN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable DMA Transfers + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + */ + +void adc_disable_dma(uint32_t adc) +{ + ADC_CFGR(adc) &= ~ADC_CFGR_DMAEN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable Continuous Conversion Mode + * + * In this mode the ADC starts a new conversion of a single channel or a channel + * group immediately following completion of the previous channel group + * conversion. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + */ + +void adc_set_continuous_conversion_mode(uint32_t adc) +{ + ADC_CFGR(adc) |= ADC_CFGR_CONT; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable Single Conversion Mode + * + * In this mode the ADC performs a conversion of one channel or a channel group + * and stops. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + */ + +void adc_set_single_conversion_mode(uint32_t adc) +{ + ADC_CFGR(adc) &= ~ADC_CFGR_CONT; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set the Sample Time for a Single Channel + * + * The sampling time can be selected in ADC clock cycles from 1.5 to 239.5. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + * @param[in] channel Unsigned int8. ADC Channel integer 0..18 or from + * @ref adc_channel + * @param[in] time Unsigned int8. Sampling time selection from + * @ref adc_sample_rg + */ + +void adc_set_sample_time(uint32_t adc, uint8_t channel, uint8_t time) +{ + uint32_t reg32; + + if (channel < 10) { + reg32 = ADC_SMPR2(adc); + reg32 &= ~(0x7 << (channel * 3)); + reg32 |= (time << (channel * 3)); + ADC_SMPR2(adc) = reg32; + } else { + reg32 = ADC_SMPR1(adc); + reg32 &= ~(0x7 << ((channel - 10) * 3)); + reg32 |= (time << ((channel - 10) * 3)); + ADC_SMPR1(adc) = reg32; + } +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set the Sample Time for All Channels + * + * The sampling time can be selected in ADC clock cycles from 1.5 to 239.5, + * same for all channels. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + * @param[in] time Unsigned int8. Sampling time selection from + * @ref adc_sample_rg + */ + +void adc_set_sample_time_on_all_channels(uint32_t adc, uint8_t time) +{ + uint8_t i; + uint32_t reg32 = 0; + + for (i = 0; i <= 9; i++) { + reg32 |= (time << (i * 3)); + } + ADC_SMPR2(adc) = reg32; + + for (i = 10; i <= 17; i++) { + reg32 |= (time << ((i - 10) * 3)); + } + ADC_SMPR1(adc) = reg32; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set Analog Watchdog Upper Threshold + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + * @param[in] threshold Unsigned int8. Upper threshold value + */ + +void adc_set_watchdog_high_threshold(uint32_t adc, uint8_t threshold) +{ + uint32_t reg32 = 0; + + reg32 |= (threshold << 16); + reg32 &= ~0xff00ffff; /* Clear all bits above 8. */ + ADC_TR1(adc) = reg32; + ADC_TR2(adc) = reg32; + ADC_TR3(adc) = reg32; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set Analog Watchdog Lower Threshold + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + * @param[in] threshold Unsigned int8. Lower threshold value + */ + +void adc_set_watchdog_low_threshold(uint32_t adc, uint8_t threshold) +{ + uint32_t reg32 = 0; + + reg32 = (uint32_t)threshold; + reg32 &= ~0xffffff00; /* Clear all bits above 8. */ + ADC_TR1(adc) = reg32; + ADC_TR2(adc) = reg32; + ADC_TR3(adc) = reg32; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set a Regular Channel Conversion Sequence + * + * Define a sequence of channels to be converted as a regular group with a + * length from 1 to 16 channels. If this is called during conversion, the + * current conversion is reset and conversion begins again with the newly + * defined group. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + * @param[in] length Unsigned int8. Number of channels in the group. + * @param[in] channel Unsigned int8[]. Set of channels in sequence, integers + * 0..18. + */ + +void adc_set_regular_sequence(uint32_t adc, uint8_t length, uint8_t channel[]) +{ + uint32_t reg32_1 = 0, reg32_2 = 0, reg32_3 = 0, reg32_4 = 0; + uint8_t i = 0; + + /* Maximum sequence length is 16 channels. */ + if (length > 16) { + return; + } + + for (i = 1; i <= length; i++) { + if (i <= 4) { + reg32_1 |= (channel[i - 1] << (i * 6)); + } + if ((i > 4) & (i <= 9)) { + reg32_2 |= (channel[i - 1] << ((i - 4 - 1) * 6)); + } + if ((i > 9) & (i <= 14)) { + reg32_3 |= (channel[i - 1] << ((i - 9 - 1) * 6)); + } + if ((i > 14) & (i <= 16)) { + reg32_4 |= (channel[i - 1] << ((i - 14 - 1) * 6)); + } + } + reg32_1 |= ((length - 1) << ADC_SQR1_L_LSB); + + ADC_SQR1(adc) = reg32_1; + ADC_SQR2(adc) = reg32_2; + ADC_SQR3(adc) = reg32_3; + ADC_SQR4(adc) = reg32_4; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set an Injected Channel Conversion Sequence + * + * Defines a sequence of channels to be converted as an injected group with a + * length from 1 to 4 channels. If this is called during conversion, the current + * conversion is reset and conversion begins again with the newly defined group. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + * @param[in] length Unsigned int8. Number of channels in the group. + * @param[in] channel Unsigned int8[]. Set of channels in sequence, integers + * 0..18 + */ + +void adc_set_injected_sequence(uint32_t adc, uint8_t length, uint8_t channel[]) +{ + uint32_t reg32 = 0; + uint8_t i = 0; + + /* Maximum sequence length is 4 channels. Minimum sequence is 1.*/ + if ((length - 1) > 3) { + return; + } + + for (i = 0; i < length; i++) { + reg32 |= ADC_JSQR_JSQ_VAL(4 - i, channel[length - i - 1]); + } + + reg32 |= ADC_JSQR_JL_VAL(length); + + ADC_JSQR(adc) = reg32; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Read the End-of-Conversion Flag + * + * This flag is set after all channels of a regular or injected group have been + * converted. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + * @returns bool. End of conversion flag. + */ + +bool adc_eoc(uint32_t adc) +{ + return ((ADC_ISR(adc) & ADC_ISR_EOC) != 0); +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Read the End-of-Conversion Flag for Injected Conversion + * + * This flag is set after all channels of an injected group have been + * converted. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + * @returns bool. End of conversion flag. + */ + +bool adc_eoc_injected(uint32_t adc) +{ + return ((ADC_ISR(adc) & ADC_ISR_JEOC) != 0); +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Read from the Regular Conversion Result Register + * + * The result read back is 12 bits, right or left aligned within the first + * 16 bits. For ADC1 only, the higher 16 bits will hold the result from ADC2 if + * an appropriate dual mode has been set @see adc_set_dual_mode. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + * @returns Unsigned int32 conversion result. + */ + +uint32_t adc_read_regular(uint32_t adc) +{ + return ADC_DR(adc); +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Read from an Injected Conversion Result Register + * + * The result read back from the selected injected result register (one of four) + * is 12 bits, right or left aligned within the first 16 bits. The result can + * have a negative value if the injected channel offset has been set @see + * adc_set_injected_offset. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + * @param[in] reg Unsigned int8. Register number (1 ... 4). + * @returns Unsigned int32 conversion result. + */ + +uint32_t adc_read_injected(uint32_t adc, uint8_t reg) +{ + switch (reg) { + case 1: + return ADC_JDR1(adc); + case 2: + return ADC_JDR2(adc); + case 3: + return ADC_JDR3(adc); + case 4: + return ADC_JDR4(adc); + } + return 0; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set the Injected Channel Data Offset + * + * This value is subtracted from the injected channel results after conversion + * is complete, and can result in negative results. A separate value can be + * specified for each injected data register. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + * @param[in] reg Unsigned int8. Register number (1 ... 4). + * @param[in] offset Unsigned int32. +*/ + +void adc_set_injected_offset(uint32_t adc, uint8_t reg, uint32_t offset) +{ + switch (reg) { + case 1: + ADC_OFR1(adc) |= ADC_OFR1_OFFSET1_EN; + ADC_OFR1(adc) |= offset; + break; + case 2: + ADC_OFR2(adc) |= ADC_OFR2_OFFSET2_EN; + ADC_OFR2(adc) |= offset; + break; + case 3: + ADC_OFR3(adc) |= ADC_OFR3_OFFSET3_EN; + ADC_OFR3(adc) |= offset; + break; + case 4: + ADC_OFR4(adc) |= ADC_OFR4_OFFSET4_EN; + ADC_OFR4(adc) |= offset; + break; + } +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Power On + * + * If the ADC is in power-down mode then it is powered up. The application + * needs to wait a time of about 3 microseconds for stabilization before using + * the ADC. If the ADC is already on this function call will have no effect. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_power_on(uint32_t adc) +{ + ADC_CR(adc) |= ADC_CR_ADEN; +} + + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set Clock Prescale + * + * The ADC clock taken from the APB2 clock can be scaled down by 2, 4, 6 or 8. + * + * @param[in] prescale Unsigned int32. Prescale value for ADC Clock @ref + * adc_ccr_adcpre +*/ + +void adc_set_clk_prescale(uint32_t prescale) +{ + uint32_t reg32 = ((ADC_CCR & ~ADC_CCR_CKMODE_MASK) | prescale); + ADC_CCR = reg32; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set Dual/Triple Mode + * + * The multiple mode uses ADC1 as master, ADC2 and optionally ADC3 in a slave + * arrangement. This setting is applied to ADC1 only. + * + * The various modes possible are described in the reference manual. + * + * @param[in] mode Unsigned int32. Multiple mode selection from @ref + * adc_multi_mode +*/ + +void adc_set_multi_mode(uint32_t mode) +{ + ADC_CCR |= mode; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable an External Trigger for Regular Channels + * + * This enables an external trigger for set of defined regular channels, and + * sets the polarity of the trigger event: rising or falling edge or both. Note + * that if the trigger polarity is zero, triggering is disabled. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + * @param[in] trigger Unsigned int32. Trigger identifier + * @ref adc_trigger_regular + * @param[in] polarity Unsigned int32. Trigger polarity @ref + * adc_trigger_polarity_regular + */ + +void adc_enable_external_trigger_regular(uint32_t adc, uint32_t trigger, + uint32_t polarity) +{ + uint32_t reg32 = ADC_CFGR(adc); + + reg32 &= ~(ADC_CFGR_EXTSEL_MASK | ADC_CFGR_EXTEN_MASK); + reg32 |= (trigger | polarity); + ADC_CFGR(adc) = reg32; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable an External Trigger for Regular Channels + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + */ + +void adc_disable_external_trigger_regular(uint32_t adc) +{ + ADC_CFGR(adc) &= ~ADC_CFGR_EXTEN_MASK; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable an External Trigger for Injected Channels + * + * This enables an external trigger for set of defined injected channels, and + * sets the polarity of the trigger event: rising or falling edge or both. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + * @param[in] trigger Unsigned int8. Trigger identifier + * @ref adc_trigger_injected + * @param[in] polarity Unsigned int32. Trigger polarity + * @ref adc_trigger_polarity_injected +*/ + +void adc_enable_external_trigger_injected(uint32_t adc, uint32_t trigger, + uint32_t polarity) +{ + uint32_t reg32 = ADC_JSQR(adc); + + reg32 &= ~(ADC_JSQR_JEXTSEL_MASK | ADC_JSQR_JEXTEN_MASK); + reg32 |= (trigger | polarity); + ADC_JSQR(adc) = reg32; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable an External Trigger for Injected Channels + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_disable_external_trigger_injected(uint32_t adc) +{ + ADC_JSQR(adc) &= ~ADC_JSQR_JEXTEN_MASK; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set Resolution + * + * ADC Resolution can be reduced from 12 bits to 10, 8 or 6 bits for a + * corresponding reduction in conversion time (resolution + 3 ADC clock cycles). + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + * @param[in] resolution Unsigned int8. Resolution value @ref adc_cr1_res + */ + +void adc_set_resolution(uint32_t adc, uint16_t resolution) +{ + uint32_t reg32 = ADC_CFGR(adc); + + reg32 &= ~ADC_CFGR_RES_MASK; + reg32 |= resolution; + ADC_CFGR(adc) = reg32; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable the Overrun Interrupt + * + * The overrun interrupt is generated when data is not read from a result + * register before the next conversion is written. If DMA is enabled, all + * transfers are terminated and any conversion sequence is aborted. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_enable_overrun_interrupt(uint32_t adc) +{ + ADC_IER(adc) |= ADC_IER_OVRIE; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable the Overrun Interrupt + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_disable_overrun_interrupt(uint32_t adc) +{ + ADC_IER(adc) &= ~ADC_IER_OVRIE; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Read the Overrun Flag + * + * The overrun flag is set when data is not read from a result register before + * the next conversion is written. If DMA is enabled, all transfers are + * terminated and any conversion sequence is aborted. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + * @returns Unsigned int32 conversion result. + */ + +bool adc_get_overrun_flag(uint32_t adc) +{ + return ADC_ISR(adc) & ADC_ISR_OVR; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Clear Overrun Flags + * + * The overrun flag is cleared. Note that if an overrun occurs, DMA is + * terminated. + * The flag must be cleared and the DMA stream and ADC reinitialised to resume + * conversions (see the reference manual). + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + * @returns Unsigned int32 conversion result. + */ + +void adc_clear_overrun_flag(uint32_t adc) +{ +/* need to write zero to clear this */ + ADC_ISR(adc) &= ~ADC_ISR_OVR; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable an EOC for Each Conversion + * + * The EOC is set after each conversion in a sequence rather than at the end of + * the sequence. Overrun detection is enabled only if DMA is enabled. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + */ + +void adc_eoc_after_each(uint32_t adc) +{ + ADC_ISR(adc) |= ADC_ISR_EOS; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable the EOC for Each Conversion + * + * The EOC is set at the end of each sequence rather than after each conversion + * in the sequence. Overrun detection is enabled always. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_eoc_after_group(uint32_t adc) +{ + ADC_ISR(adc) &= ~ADC_ISR_EOS; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set DMA to Continue + * + * This must be set to allow DMA to continue to operate after the last + * conversion in the DMA sequence. This allows DMA to be used in continuous + * circular mode. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +/* +void adc_set_dma_continue(uint32_t adc) +{ + ADC_CR2(adc) |= ADC_CR2_DDS; +} +*/ + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Set DMA to Terminate + * + * This must be set to allow DMA to terminate after the last conversion in the + * DMA sequence. This can avoid overrun errors. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + */ + +/* +void adc_set_dma_terminate(uint32_t adc) +{ + ADC_CR2(adc) &= ~ADC_CR2_DDS; +} +*/ + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Read the Analog Watchdog Flag + * + * This flag is set when the converted voltage crosses the high or low + * thresholds. + * + * @param[in] adc Unsigned int32. ADC block register address base + * @ref adc_reg_base + * @returns bool. AWD flag. + */ + +bool adc_awd(uint32_t adc) +{ + return (ADC_ISR(adc) & ADC_ISR_AWD1) && + (ADC_ISR(adc) & ADC_ISR_AWD2) && + (ADC_ISR(adc) & ADC_ISR_AWD3); +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Enable The Temperature Sensor + * + * This enables both the sensor and the reference voltage measurements on + * channels + * 16 and 17. These are only available on ADC1 channel 16 and 17 respectively. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_enable_temperature_sensor() +{ + ADC_CCR |= ADC_CCR_TSEN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief ADC Disable The Temperature Sensor + * + * Disabling this will reduce power consumption from the sensor and the + * reference voltage measurements. + * + * @param[in] adc Unsigned int32. ADC block register address base @ref + * adc_reg_base + */ + +void adc_disable_temperature_sensor() +{ + ADC_CCR &= ~ADC_CCR_TSEN; +} + +/*---------------------------------------------------------------------------*/ + +/**@}*/ + diff --git a/libopencm3/lib/stm32/f3/crc.c b/libopencm3/lib/stm32/f3/crc.c new file mode 100644 index 0000000..eb3c14b --- /dev/null +++ b/libopencm3/lib/stm32/f3/crc.c @@ -0,0 +1,33 @@ +/** @defgroup crc_file CRC + * + * @ingroup STM32F3xx + * + * @brief libopencm3 STM32F3xx CRC + * + * @version 1.0.0 + * + * @date 15 October 2012 + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + + diff --git a/libopencm3/lib/stm32/f3/dac.c b/libopencm3/lib/stm32/f3/dac.c new file mode 100644 index 0000000..2d8021e --- /dev/null +++ b/libopencm3/lib/stm32/f3/dac.c @@ -0,0 +1,31 @@ +/** @defgroup dac_file DAC + * + * @ingroup STM32F3xx + * + * @brief libopencm3 STM32F3xx DAC + * + * @version 1.0.0 + * + * @date 18 August 2012 + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include diff --git a/libopencm3/lib/stm32/f3/dma.c b/libopencm3/lib/stm32/f3/dma.c new file mode 100644 index 0000000..c5d82b1 --- /dev/null +++ b/libopencm3/lib/stm32/f3/dma.c @@ -0,0 +1,31 @@ +/** @defgroup dma_file DMA + * + * @ingroup STM32F3xx + * + * @brief libopencm3 STM32F3xx Direct Memory Access + * + * @version 1.0.0 + * + * @date 11 July 2013 + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include diff --git a/libopencm3/lib/stm32/f3/flash.c b/libopencm3/lib/stm32/f3/flash.c new file mode 100644 index 0000000..d157aca --- /dev/null +++ b/libopencm3/lib/stm32/f3/flash.c @@ -0,0 +1,63 @@ +/** @defgroup flash_file FLASH + * + * @ingroup STM32F3xx + * + * @brief libopencm3 STM32F3xx FLASH + * + * @version 1.0.0 + * + * @author @htmlonly © @endhtmlonly 2010 + * Thomas Otto + * @author @htmlonly © @endhtmlonly 2010 + * Mark Butler + * + * @date 14 January 2014 + * + * This library supports the FLASH memory controller in the STM32F3 + * series of ARM Cortex Microcontrollers by ST Microelectronics. + * + * For the STM32F3xx, accessing FLASH memory is described in + * section 3 of the STM32F3xx Reference Manual. + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Thomas Otto + * Copyright (C) 2010 Mark Butler + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ +/**@{*/ + +/**@{*/ + +#include + +/*---------------------------------------------------------------------------*/ +/** @brief Clear All Status Flags + +Clears program error, end of operation, busy flags. +*/ + +void flash_clear_status_flags(void) +{ + flash_clear_pgperr_flag(); + flash_clear_eop_flag(); + flash_clear_bsy_flag(); +} +/**@}*/ + diff --git a/libopencm3/lib/stm32/f3/i2c.c b/libopencm3/lib/stm32/f3/i2c.c new file mode 100644 index 0000000..b5d39cf --- /dev/null +++ b/libopencm3/lib/stm32/f3/i2c.c @@ -0,0 +1,486 @@ +/** @defgroup i2c_file I2C + * + * @ingroup STM32F3xx + * + * @brief libopencm3 STM32F3xx I2C + * + * @version 1.0.0 + * + * @date 15 October 2012 + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include + +/**@{*/ + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Reset. + * + * The I2C peripheral and all its associated configuration registers are placed + * in the reset condition. The reset is effected via the RCC peripheral reset + * system. + * + * @param[in] i2c Unsigned int32. I2C peripheral identifier @ref i2c_reg_base. + */ + +void i2c_reset(uint32_t i2c) +{ + switch (i2c) { + case I2C1: + rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST); + rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST); + break; + case I2C2: + rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST); + rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_I2C2RST); + break; + } +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Peripheral Enable. + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + */ + +void i2c_peripheral_enable(uint32_t i2c) +{ + I2C_CR1(i2c) |= I2C_CR1_PE; +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Peripheral Disable. + * + * This must not be reset while in Master mode until a communication has + * finished. In Slave mode, the peripheral is disabled only after communication + * has ended. + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + */ + +void i2c_peripheral_disable(uint32_t i2c) +{ + I2C_CR1(i2c) &= ~I2C_CR1_PE; +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Send Start Condition. + * + * If in Master mode this will cause a restart condition to occur at the end of + * the current transmission. If in Slave mode, this will initiate a start + * condition when the current bus activity is completed. + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + */ + +void i2c_send_start(uint32_t i2c) +{ + I2C_CR2(i2c) |= I2C_CR2_START; +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Send Stop Condition. + * + * After the current byte transfer this will initiate a stop condition if in + * Master mode, or simply release the bus if in Slave mode. + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + */ + +void i2c_send_stop(uint32_t i2c) +{ + I2C_CR2(i2c) |= I2C_CR2_STOP; +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Clear Stop Flag. + * + * Clear the "Send Stop" flag in the I2C config register + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + */ +void i2c_clear_stop(uint32_t i2c) +{ + I2C_ICR(i2c) |= I2C_ICR_STOPCF; +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Set the 7 bit Slave Address for the Peripheral. + * + * This sets an address for Slave mode operation, in 7 bit form. + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + * @param[in] slave Unsigned int8. Slave address 0...127. + */ + +void i2c_set_own_7bit_slave_address(uint32_t i2c, uint8_t slave) +{ + I2C_OAR1(i2c) = (uint16_t)(slave << 1); + I2C_OAR1(i2c) &= ~I2C_OAR1_OA1MODE; + I2C_OAR1(i2c) |= (1 << 14); /* Datasheet: always keep 1 by software. */ +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Set the 10 bit Slave Address for the Peripheral. + * + * This sets an address for Slave mode operation, in 10 bit form. + * + * @todo add "I2C_OAR1(i2c) |= (1 << 14);" as above + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + * @param[in] slave Unsigned int16. Slave address 0...1023. + */ + +void i2c_set_own_10bit_slave_address(uint32_t i2c, uint16_t slave) +{ + I2C_OAR1(i2c) = (uint16_t)(I2C_OAR1_OA1MODE | slave); +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Send Data. + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + * @param[in] data Unsigned int8. Byte to send. + */ + +void i2c_send_data(uint32_t i2c, uint8_t data) +{ + I2C_TXDR(i2c) = data; +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Get Data. + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + */ +uint8_t i2c_get_data(uint32_t i2c) +{ + return I2C_RXDR(i2c) & 0xff; +} + +void i2c_enable_analog_filter(uint32_t i2c) +{ + I2C_CR1(i2c) &= ~I2C_CR1_ANFOFF; +} + +void i2c_disable_analog_filter(uint32_t i2c) +{ + I2C_CR1(i2c) |= I2C_CR1_ANFOFF; +} + +void i2c_set_digital_filter(uint32_t i2c, uint8_t dnf_setting) +{ + I2C_CR1(i2c) = (I2C_CR1(i2c) & ~I2C_CR1_DNF_MASK) | dnf_setting; +} + +/* t_presc= (presc+1)*t_i2cclk */ +void i2c_set_prescaler(uint32_t i2c, uint8_t presc) +{ + I2C_TIMINGR(i2c) = (I2C_TIMINGR(i2c) & ~I2C_TIMINGR_PRESC_MASK) | + (presc << I2C_TIMINGR_PRESC_SHIFT); +} + +void i2c_set_data_setup_time(uint32_t i2c, uint8_t s_time) +{ + I2C_TIMINGR(i2c) = (I2C_TIMINGR(i2c) & ~I2C_TIMINGR_SCLDEL_MASK) | + (s_time << I2C_TIMINGR_SCLDEL_SHIFT); +} + +void i2c_set_data_hold_time(uint32_t i2c, uint8_t h_time) +{ + I2C_TIMINGR(i2c) = (I2C_TIMINGR(i2c) & ~I2C_TIMINGR_SDADEL_MASK) | + (h_time << I2C_TIMINGR_SDADEL_SHIFT); +} + +void i2c_set_scl_high_period(uint32_t i2c, uint8_t period) +{ + I2C_TIMINGR(i2c) = (I2C_TIMINGR(i2c) & ~I2C_TIMINGR_SCLH_MASK) | + (period << I2C_TIMINGR_SCLH_SHIFT); +} + +void i2c_set_scl_low_period(uint32_t i2c, uint8_t period) +{ + I2C_TIMINGR(i2c) = (I2C_TIMINGR(i2c) & ~I2C_TIMINGR_SCLL_MASK) | + (period << I2C_TIMINGR_SCLL_SHIFT); +} + +void i2c_enable_stretching(uint32_t i2c) +{ + I2C_CR1(i2c) &= ~I2C_CR1_NOSTRETCH; +} + +void i2c_disable_stretching(uint32_t i2c) +{ + I2C_CR1(i2c) |= I2C_CR1_NOSTRETCH; +} + +void i2c_100khz_i2cclk8mhz(uint32_t i2c) +{ + i2c_set_prescaler(i2c, 1); + i2c_set_scl_low_period(i2c, 0x13); + i2c_set_scl_high_period(i2c, 0xF); + i2c_set_data_hold_time(i2c, 0x2); + i2c_set_data_setup_time(i2c, 0x4); +} + +void i2c_set_7bit_addr_mode(uint32_t i2c) +{ + I2C_CR2(i2c) &= ~I2C_CR2_ADD10; +} + +void i2c_set_10bit_addr_mode(uint32_t i2c) +{ + I2C_CR2(i2c) |= I2C_CR2_ADD10; +} + +void i2c_set_7bit_address(uint32_t i2c, uint8_t addr) +{ + I2C_CR2(i2c) = (I2C_CR2(i2c) & ~I2C_CR2_SADD_7BIT_MASK) | + ((addr & 0x7F) << I2C_CR2_SADD_7BIT_SHIFT); +} + +void i2c_set_10bit_address(uint32_t i2c, uint16_t addr) +{ + I2C_CR2(i2c) = (I2C_CR2(i2c) & ~I2C_CR2_SADD_10BIT_MASK) | + ((addr & 0x3FF) << I2C_CR2_SADD_10BIT_SHIFT); +} + +void i2c_set_write_transfer_dir(uint32_t i2c) +{ + I2C_CR2(i2c) &= ~I2C_CR2_RD_WRN; +} + +void i2c_set_read_transfer_dir(uint32_t i2c) +{ + I2C_CR2(i2c) |= I2C_CR2_RD_WRN; +} + +void i2c_set_bytes_to_transfer(uint32_t i2c, uint32_t n_bytes) +{ + I2C_CR2(i2c) = (I2C_CR2(i2c) & ~I2C_CR2_NBYTES_MASK) | + (n_bytes << I2C_CR2_NBYTES_SHIFT); +} + +uint8_t i2c_is_start(uint32_t i2c) +{ + if ((I2C_CR2(i2c) & I2C_CR2_START) != 0) { + return 1; + } + + return 0; +} + +void i2c_enable_autoend(uint32_t i2c) +{ + I2C_CR2(i2c) |= I2C_CR2_AUTOEND; +} + +void i2c_disable_autoend(uint32_t i2c) +{ + I2C_CR2(i2c) &= ~I2C_CR2_AUTOEND; +} + +uint8_t i2c_nack(uint32_t i2c) +{ + if ((I2C_ISR(i2c) & I2C_ISR_NACKF) != 0) { + return 1; + } + + return 0; +} + +uint8_t i2c_busy(uint32_t i2c) +{ + if ((I2C_ISR(i2c) & I2C_ISR_BUSY) != 0) { + return 1; + } + + return 0; +} + +uint8_t i2c_transmit_int_status(uint32_t i2c) +{ + if ((I2C_ISR(i2c) & I2C_ISR_TXIS) != 0) { + return 1; + } + + return 0; +} + +uint8_t i2c_transfer_complete(uint32_t i2c) +{ + if ((I2C_ISR(i2c) & I2C_ISR_TC) != 0) { + return 1; + } + + return 0; +} + +uint8_t i2c_received_data(uint32_t i2c) +{ + if ((I2C_ISR(i2c) & I2C_ISR_RXNE) != 0) { + return 1; + } + + return 0; +} + + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Enable Interrupt + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + * @param[in] interrupt Unsigned int32. Interrupt to enable. + */ +void i2c_enable_interrupt(uint32_t i2c, uint32_t interrupt) +{ + I2C_CR1(i2c) |= interrupt; +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Disable Interrupt + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + * @param[in] interrupt Unsigned int32. Interrupt to disable. + */ +void i2c_disable_interrupt(uint32_t i2c, uint32_t interrupt) +{ + I2C_CR1(i2c) &= ~interrupt; +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Enable reception DMA + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + */ +void i2c_enable_rxdma(uint32_t i2c) +{ + I2C_CR1(i2c) |= I2C_CR1_RXDMAEN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Disable reception DMA + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + */ +void i2c_disable_rxdma(uint32_t i2c) +{ + I2C_CR1(i2c) &= ~I2C_CR1_RXDMAEN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Enable transmission DMA + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + */ +void i2c_enable_txdma(uint32_t i2c) +{ + I2C_CR1(i2c) |= I2C_CR1_TXDMAEN; +} + +/*---------------------------------------------------------------------------*/ +/** @brief I2C Disable transmission DMA + * + * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. + */ +void i2c_disable_txdma(uint32_t i2c) +{ + I2C_CR1(i2c) &= ~I2C_CR1_TXDMAEN; +} + +void write_i2c(uint32_t i2c, uint8_t i2c_addr, uint8_t reg, uint8_t size, + uint8_t *data) +{ + int wait; + int i; + while (i2c_busy(i2c) == 1); + while (i2c_is_start(i2c) == 1); + /*Setting transfer properties*/ + i2c_set_bytes_to_transfer(i2c, size + 1); + i2c_set_7bit_address(i2c, (i2c_addr & 0x7F)); + i2c_set_write_transfer_dir(i2c); + i2c_enable_autoend(i2c); + /*start transfer*/ + i2c_send_start(i2c); + + wait = true; + while (wait) { + if (i2c_transmit_int_status(i2c)) { + wait = false; + } + while (i2c_nack(i2c)); + } + + i2c_send_data(i2c, reg); + for (i = 0; i < size; i++) { + wait = true; + while (wait) { + if (i2c_transmit_int_status(i2c)) { + wait = false; + } + while (i2c_nack(i2c)); + } + i2c_send_data(i2c, data[i]); + } +} + +void read_i2c(uint32_t i2c, uint8_t i2c_addr, uint8_t reg, uint8_t size, + uint8_t *data) +{ + int wait; + int i; + while (i2c_busy(i2c) == 1); + while (i2c_is_start(i2c) == 1); + /*Setting transfer properties*/ + i2c_set_bytes_to_transfer(i2c, 1); + i2c_set_7bit_address(i2c, i2c_addr); + i2c_set_write_transfer_dir(i2c); + i2c_disable_autoend(i2c); + /*start transfer*/ + i2c_send_start(i2c); + + wait = true; + while (wait) { + if (i2c_transmit_int_status(i2c)) { + wait = false; + } + while (i2c_nack(i2c)); /* Some error */ + } + i2c_send_data(i2c, reg); + + while (i2c_is_start(i2c) == 1); + /*Setting transfer properties*/ + i2c_set_bytes_to_transfer(i2c, size); + i2c_set_7bit_address(i2c, i2c_addr); + i2c_set_read_transfer_dir(i2c); + i2c_enable_autoend(i2c); + /*start transfer*/ + i2c_send_start(i2c); + + for (i = 0; i < size; i++) { + while (i2c_received_data(i2c) == 0); + data[i] = i2c_get_data(i2c); + } +} + +/**@}*/ diff --git a/libopencm3/lib/stm32/f3/iwdg.c b/libopencm3/lib/stm32/f3/iwdg.c new file mode 100644 index 0000000..cf0045c --- /dev/null +++ b/libopencm3/lib/stm32/f3/iwdg.c @@ -0,0 +1,31 @@ +/** @defgroup iwdg_file IWDG + * + * @ingroup STM32F3xx + * + * @brief libopencm3 STM32F3xx Independent Watchdog Timer + * + * @version 1.0.0 + * + * @date 18 August 2012 + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include diff --git a/libopencm3/lib/stm32/f3/libopencm3_stm32f3.ld b/libopencm3/lib/stm32/f3/libopencm3_stm32f3.ld new file mode 100644 index 0000000..3fc2ccb --- /dev/null +++ b/libopencm3/lib/stm32/f3/libopencm3_stm32f3.ld @@ -0,0 +1,106 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/* Generic linker script for STM32 targets using libopencm3. */ + +/* Memory regions must be defined in the ld script which includes this one. */ + +/* Enforce emmition of the vector table. */ +EXTERN (vector_table) + +/* Define the entry point of the output file. */ +ENTRY(reset_handler) + +/* Define sections. */ +SECTIONS +{ + .text : { + *(.vectors) /* Vector table */ + *(.text*) /* Program code */ + . = ALIGN(4); + *(.rodata*) /* Read-only data */ + . = ALIGN(4); + } >rom + + /* C++ Static constructors/destructors, also used for __attribute__ + * ((constructor)) and the likes */ + .preinit_array : { + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + } >rom + .init_array : { + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + } >rom + .fini_array : { + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + } >rom + + /* + * Another section used by C++ stuff, appears when using newlib with + * 64bit (long long) printf support + */ + .ARM.extab : { + *(.ARM.extab*) + } >rom + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >rom + + . = ALIGN(4); + _etext = .; + + .data : { + _data = .; + *(.data*) /* Read-write initialized data */ + . = ALIGN(4); + _edata = .; + } >ram AT >rom + _data_loadaddr = LOADADDR(.data); + + .bss : { + *(.bss*) /* Read-write zero initialized data */ + *(COMMON) + . = ALIGN(4); + _ebss = .; + } >ram + + /* + * The .eh_frame section appears to be used for C++ exception handling. + * You may need to fix this if you're using C++. + */ + /DISCARD/ : { *(.eh_frame) } + + . = ALIGN(4); + end = .; +} + +PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); + diff --git a/libopencm3/lib/stm32/f3/pwr.c b/libopencm3/lib/stm32/f3/pwr.c new file mode 100644 index 0000000..3c1a84b --- /dev/null +++ b/libopencm3/lib/stm32/f3/pwr.c @@ -0,0 +1,40 @@ +/** @defgroup pwr_file PWR + * + * @ingroup STM32F3xx + * + * @brief libopencm3 STM32F3xx Power Control + * + * @author @htmlonly © @endhtmlonly 2014 + * Ken Sarkies + * + * @date 13 January 2014 + * + * @version 1.0.0 + * + * @date 11 July 2013 + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2014 Ken Sarkies + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + + diff --git a/libopencm3/lib/stm32/f3/rcc.c b/libopencm3/lib/stm32/f3/rcc.c new file mode 100644 index 0000000..8291a2b --- /dev/null +++ b/libopencm3/lib/stm32/f3/rcc.c @@ -0,0 +1,465 @@ +/** @defgroup rcc_file RCC + * + * @ingroup STM32F3xx + * + * @brief libopencm3 STM32F3xx Reset and Clock Control + * + * @version 1.0.0 + * + * @date 11 July 2013 + * + * LGPL License Terms @ref lgpl_license + */ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Federico Ruiz-Ugalde + * Copyright (C) 2009 Uwe Hermann + * Copyright (C) 2010 Thomas Otto + * Modified by 2013 Fernando Cortes (stm32f3) + * Modified by 2013 Guillermo Rivera (stm32f3) + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ +/**@{*/ + +#include +#include +#include +#include + +/* Set the default ppre1 and ppre2 peripheral clock frequencies after reset. */ +uint32_t rcc_ppre1_frequency = 8000000; +uint32_t rcc_ppre2_frequency = 8000000; + +const clock_scale_t hsi_8mhz[CLOCK_END] = { + { /* 44MHz */ + .pll = RCC_CFGR_PLLMUL_PLL_IN_CLK_X11, + .pllsrc = RCC_CFGR_PLLSRC_HSI_DIV2, + .hpre = RCC_CFGR_HPRE_DIV_NONE, + .ppre1 = RCC_CFGR_PPRE1_DIV_2, + .ppre2 = RCC_CFGR_PPRE2_DIV_NONE, + .power_save = 1, + .flash_config = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_1WS, + .apb1_frequency = 22000000, + .apb2_frequency = 44000000, + }, + { /* 48MHz */ + .pll = RCC_CFGR_PLLMUL_PLL_IN_CLK_X12, + .pllsrc = RCC_CFGR_PLLSRC_HSI_DIV2, + .hpre = RCC_CFGR_HPRE_DIV_NONE, + .ppre1 = RCC_CFGR_PPRE1_DIV_2, + .ppre2 = RCC_CFGR_PPRE2_DIV_NONE, + .power_save = 1, + .flash_config = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_1WS, + .apb1_frequency = 24000000, + .apb2_frequency = 48000000, + }, + { /* 64MHz */ + .pll = RCC_CFGR_PLLMUL_PLL_IN_CLK_X16, + .pllsrc = RCC_CFGR_PLLSRC_HSI_DIV2, + .hpre = RCC_CFGR_HPRE_DIV_NONE, + .ppre1 = RCC_CFGR_PPRE1_DIV_2, + .ppre2 = RCC_CFGR_PPRE2_DIV_NONE, + .power_save = 1, + .flash_config = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_2WS, + .apb1_frequency = 32000000, + .apb2_frequency = 64000000, + } +}; + +void rcc_osc_ready_int_clear(enum osc osc) +{ + switch (osc) { + case PLL: + RCC_CIR |= RCC_CIR_PLLRDYC; + break; + case HSE: + RCC_CIR |= RCC_CIR_HSERDYC; + break; + case HSI: + RCC_CIR |= RCC_CIR_HSIRDYC; + break; + case LSE: + RCC_CIR |= RCC_CIR_LSERDYC; + break; + case LSI: + RCC_CIR |= RCC_CIR_LSIRDYC; + break; + } +} + +void rcc_osc_ready_int_enable(enum osc osc) +{ + switch (osc) { + case PLL: + RCC_CIR |= RCC_CIR_PLLRDYIE; + break; + case HSE: + RCC_CIR |= RCC_CIR_HSERDYIE; + break; + case HSI: + RCC_CIR |= RCC_CIR_HSIRDYIE; + break; + case LSE: + RCC_CIR |= RCC_CIR_LSERDYIE; + break; + case LSI: + RCC_CIR |= RCC_CIR_LSIRDYIE; + break; + } +} + +void rcc_osc_ready_int_disable(enum osc osc) +{ + switch (osc) { + case PLL: + RCC_CIR &= ~RCC_CIR_PLLRDYIE; + break; + case HSE: + RCC_CIR &= ~RCC_CIR_HSERDYIE; + break; + case HSI: + RCC_CIR &= ~RCC_CIR_HSIRDYIE; + break; + case LSE: + RCC_CIR &= ~RCC_CIR_LSERDYIE; + break; + case LSI: + RCC_CIR &= ~RCC_CIR_LSIRDYIE; + break; + } +} + +int rcc_osc_ready_int_flag(enum osc osc) +{ + switch (osc) { + case PLL: + return ((RCC_CIR & RCC_CIR_PLLRDYF) != 0); + break; + case HSE: + return ((RCC_CIR & RCC_CIR_HSERDYF) != 0); + break; + case HSI: + return ((RCC_CIR & RCC_CIR_HSIRDYF) != 0); + break; + case LSE: + return ((RCC_CIR & RCC_CIR_LSERDYF) != 0); + break; + case LSI: + return ((RCC_CIR & RCC_CIR_LSIRDYF) != 0); + break; + } + + cm3_assert_not_reached(); +} + +void rcc_css_int_clear(void) +{ + RCC_CIR |= RCC_CIR_CSSC; +} + +int rcc_css_int_flag(void) +{ + return ((RCC_CIR & RCC_CIR_CSSF) != 0); +} + +void rcc_wait_for_osc_ready(enum osc osc) +{ + switch (osc) { + case PLL: + while ((RCC_CR & RCC_CR_PLLRDY) == 0); + break; + case HSE: + while ((RCC_CR & RCC_CR_HSERDY) == 0); + break; + case HSI: + while ((RCC_CR & RCC_CR_HSIRDY) == 0); + break; + case LSE: + while ((RCC_BDCR & RCC_BDCR_LSERDY) == 0); + break; + case LSI: + while ((RCC_CSR & RCC_CSR_LSIRDY) == 0); + break; + } +} + + +void rcc_wait_for_osc_not_ready(enum osc osc) +{ + switch (osc) { + case PLL: + while ((RCC_CR & RCC_CR_PLLRDY) != 0); + break; + case HSE: + while ((RCC_CR & RCC_CR_HSERDY) != 0); + break; + case HSI: + while ((RCC_CR & RCC_CR_HSIRDY) != 0); + break; + case LSE: + while ((RCC_BDCR & RCC_BDCR_LSERDY) != 0); + break; + case LSI: + while ((RCC_CSR & RCC_CSR_LSIRDY) != 0); + break; + } +} + +void rcc_wait_for_sysclk_status(enum osc osc) +{ + switch (osc) { + case PLL: + while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_PLL); + break; + case HSE: + while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_HSE); + break; + case HSI: + while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_HSI); + break; + default: + /* Shouldn't be reached. */ + break; + } +} + +void rcc_osc_on(enum osc osc) +{ + switch (osc) { + case PLL: + RCC_CR |= RCC_CR_PLLON; + break; + case HSE: + RCC_CR |= RCC_CR_HSEON; + break; + case HSI: + RCC_CR |= RCC_CR_HSION; + break; + case LSE: + RCC_BDCR |= RCC_BDCR_LSEON; + break; + case LSI: + RCC_CSR |= RCC_CSR_LSION; + break; + } +} + +void rcc_osc_off(enum osc osc) +{ + switch (osc) { + case PLL: + RCC_CR &= ~RCC_CR_PLLON; + break; + case HSE: + RCC_CR &= ~RCC_CR_HSEON; + break; + case HSI: + RCC_CR &= ~RCC_CR_HSION; + break; + case LSE: + RCC_BDCR &= ~RCC_BDCR_LSEON; + break; + case LSI: + RCC_CSR &= ~RCC_CSR_LSION; + break; + } +} + +void rcc_css_enable(void) +{ + RCC_CR |= RCC_CR_CSSON; +} + +void rcc_css_disable(void) +{ + RCC_CR &= ~RCC_CR_CSSON; +} + +void rcc_osc_bypass_enable(enum osc osc) +{ + switch (osc) { + case HSE: + RCC_CR |= RCC_CR_HSEBYP; + break; + case LSE: + RCC_BDCR |= RCC_BDCR_LSEBYP; + break; + case PLL: + case HSI: + case LSI: + /* Do nothing, only HSE/LSE allowed here. */ + break; + } +} + +void rcc_osc_bypass_disable(enum osc osc) +{ + switch (osc) { + case HSE: + RCC_CR &= ~RCC_CR_HSEBYP; + break; + case LSE: + RCC_BDCR &= ~RCC_BDCR_LSEBYP; + break; + case PLL: + case HSI: + case LSI: + /* Do nothing, only HSE/LSE allowed here. */ + break; + } +} + +void rcc_set_sysclk_source(uint32_t clk) +{ + uint32_t reg32; + + reg32 = RCC_CFGR; + reg32 &= ~((1 << 1) | (1 << 0)); + RCC_CFGR = (reg32 | clk); +} + +void rcc_set_pll_source(uint32_t pllsrc) +{ + uint32_t reg32; + + reg32 = RCC_CFGR; + reg32 &= ~RCC_CFGR_PLLSRC; + RCC_CFGR = (reg32 | (pllsrc << 16)); +} + +void rcc_set_ppre2(uint32_t ppre2) +{ + uint32_t reg32; + + reg32 = RCC_CFGR; + reg32 &= ~((1 << 13) | (1 << 14) | (1 << 15)); + RCC_CFGR = (reg32 | (ppre2 << 11)); +} + +void rcc_set_ppre1(uint32_t ppre1) +{ + uint32_t reg32; + + reg32 = RCC_CFGR; + reg32 &= ~((1 << 10) | (1 << 11) | (1 << 12)); + RCC_CFGR = (reg32 | (ppre1 << 8)); +} + +void rcc_set_hpre(uint32_t hpre) +{ + uint32_t reg32; + + reg32 = RCC_CFGR; + reg32 &= ~((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7)); + RCC_CFGR = (reg32 | (hpre << 4)); +} + + +void rcc_set_main_pll_hsi(uint32_t pll) +{ + RCC_CFGR = (~RCC_CFGR_PLLMUL_MASK & RCC_CFGR) | + (pll << RCC_CFGR_PLLMUL_SHIFT); +} + + +uint32_t rcc_get_system_clock_source(void) +{ + /* Return the clock source which is used as system clock. */ + return (RCC_CFGR & 0x000c) >> 2; +} + + +void rcc_clock_setup_hsi(const clock_scale_t *clock) +{ + /* Enable internal high-speed oscillator. */ + rcc_osc_on(HSI); + rcc_wait_for_osc_ready(HSI); + /* Select HSI as SYSCLK source. */ + rcc_set_sysclk_source(RCC_CFGR_SW_HSI); /* XXX: se cayo */ + rcc_wait_for_sysclk_status(HSI); + + rcc_osc_off(PLL); + rcc_wait_for_osc_not_ready(PLL); + rcc_set_pll_source(clock->pllsrc); + rcc_set_main_pll_hsi(clock->pll); + /* Enable PLL oscillator and wait for it to stabilize. */ + rcc_osc_on(PLL); + rcc_wait_for_osc_ready(PLL); + /* + * Set prescalers for AHB, ADC, ABP1, ABP2. + * Do this before touching the PLL (TODO: why?). + */ + rcc_set_hpre(clock->hpre); + rcc_set_ppre2(clock->ppre2); + rcc_set_ppre1(clock->ppre1); + /* Configure flash settings. */ + flash_set_ws(clock->flash_config); + /* Select PLL as SYSCLK source. */ + rcc_set_sysclk_source(RCC_CFGR_SW_PLL); /* XXX: se cayo */ + /* Wait for PLL clock to be selected. */ + rcc_wait_for_sysclk_status(PLL); + + /* Set the peripheral clock frequencies used. */ + rcc_ppre1_frequency = clock->apb1_frequency; + rcc_ppre2_frequency = clock->apb2_frequency; +} + + +void rcc_backupdomain_reset(void) +{ + /* Set the backup domain software reset. */ + RCC_BDCR |= RCC_BDCR_BDRST; + + /* Clear the backup domain software reset. */ + RCC_BDCR &= ~RCC_BDCR_BDRST; +} + +void rcc_set_i2c_clock_hsi(uint32_t i2c) +{ + if (i2c == I2C1) { + RCC_CFGR3 &= ~RCC_CFGR3_I2C1SW; + } + if (i2c == I2C2) { + RCC_CFGR3 &= ~RCC_CFGR3_I2C2SW; + } +} + +void rcc_set_i2c_clock_sysclk(uint32_t i2c) +{ + if (i2c == I2C1) { + RCC_CFGR3 |= RCC_CFGR3_I2C1SW; + } + if (i2c == I2C2) { + RCC_CFGR3 |= RCC_CFGR3_I2C2SW; + } +} + +uint32_t rcc_get_i2c_clocks(void) +{ + return RCC_CFGR3 & (RCC_CFGR3_I2C1SW | RCC_CFGR3_I2C2SW); +} + +void rcc_usb_prescale_1_5(void) +{ + RCC_CFGR &= ~RCC_CFGR_USBPRES; +} + +void rcc_usb_prescale_1(void) +{ + RCC_CFGR |= RCC_CFGR_USBPRES; +} +/**@}*/ + diff --git a/libopencm3/lib/stm32/f3/rtc.c b/libopencm3/lib/stm32/f3/rtc.c new file mode 100644 index 0000000..f332765 --- /dev/null +++ b/libopencm3/lib/stm32/f3/rtc.c @@ -0,0 +1,38 @@ +/** @defgroup rtc_file RTC + * + * @ingroup STM32F3xx + * + * @brief libopencm3 STM32F3xx Real Time Clock + * + * @version 1.0.0 + * + * @author @htmlonly © @endhtmlonly 2014 + * Ken Sarkies + * + * @date 13 January 2014 + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2014 Ken Sarkies + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + + diff --git a/libopencm3/lib/stm32/f3/spi.c b/libopencm3/lib/stm32/f3/spi.c new file mode 100644 index 0000000..3dcc524 --- /dev/null +++ b/libopencm3/lib/stm32/f3/spi.c @@ -0,0 +1,31 @@ +/** @defgroup spi_file SPI + +@ingroup STM32F3xx + +@brief libopencm3 STM32F3xx SPI + +@version 1.0.0 + +@date 20 February 2014 + +LGPL License Terms @ref lgpl_license +*/ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include diff --git a/libopencm3/lib/stm32/f3/timer.c b/libopencm3/lib/stm32/f3/timer.c new file mode 100644 index 0000000..0e9ac3d --- /dev/null +++ b/libopencm3/lib/stm32/f3/timer.c @@ -0,0 +1,33 @@ +/** @defgroup timer_file TIMER + * + * @ingroup STM32F3xx + * + * @brief libopencm3 STM32F3xx Timers + * + * @version 1.0.0 + * + * @date 11 July 2013 + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + + diff --git a/libopencm3/lib/stm32/f3/usart.c b/libopencm3/lib/stm32/f3/usart.c new file mode 100644 index 0000000..305ae72 --- /dev/null +++ b/libopencm3/lib/stm32/f3/usart.c @@ -0,0 +1,140 @@ +/** @defgroup usart_file USART + * + * @ingroup STM32F3xx + * + * @brief libopencm3 STM32F3xx USART + * + * @version 1.0.0 + * + * @date 30 August 2012 + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + +/*---------------------------------------------------------------------------*/ +/** @brief USART Send a Data Word. + * + * @param[in] usart unsigned 32 bit. USART block register address base @ref + * usart_reg_base + * @param[in] data unsigned 16 bit. + */ + +void usart_send(uint32_t usart, uint16_t data) +{ + /* Send data. */ + USART_TDR(usart) = (data & USART_TDR_MASK); +} + +/*---------------------------------------------------------------------------*/ +/** @brief USART Read a Received Data Word. + * + * If parity is enabled the MSB (bit 7 or 8 depending on the word length) is + * the parity bit. + * + * @param[in] usart unsigned 32 bit. USART block register address base @ref + * usart_reg_base + * @returns unsigned 16 bit data word. + */ + +uint16_t usart_recv(uint32_t usart) +{ + /* Receive data. */ + return USART_RDR(usart) & USART_RDR_MASK; +} + +/*---------------------------------------------------------------------------*/ +/** @brief USART Wait for Transmit Data Buffer Empty + * + * Blocks until the transmit data buffer becomes empty and is ready to accept + * the next data word. + * + * @param[in] usart unsigned 32 bit. USART block register address base @ref + * usart_reg_base + */ + +void usart_wait_send_ready(uint32_t usart) +{ + /* Wait until the data has been transferred into the shift register. */ + while ((USART_ISR(usart) & USART_ISR_TXE) == 0); +} + +/*---------------------------------------------------------------------------*/ +/** @brief USART Wait for Received Data Available + * + * Blocks until the receive data buffer holds a valid received data word. + * + * @param[in] usart unsigned 32 bit. USART block register address base @ref + * usart_reg_base + */ + +void usart_wait_recv_ready(uint32_t usart) +{ + /* Wait until the data is ready to be received. */ + while ((USART_ISR(usart) & USART_ISR_RXNE) == 0); +} + +/*---------------------------------------------------------------------------*/ +/** @brief USART Read a Status Flag. + * + * @param[in] usart unsigned 32 bit. USART block register address base @ref + * usart_reg_base + * @param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags. + * @returns boolean: flag set. + */ + +bool usart_get_flag(uint32_t usart, uint32_t flag) +{ + return ((USART_ISR(usart) & flag) != 0); +} + +/*---------------------------------------------------------------------------*/ +/** @brief USART Return Interrupt Source. + * + * Returns true if the specified interrupt flag (IDLE, RXNE, TC, TXE or OE) was + * set and the interrupt was enabled. If the specified flag is not an interrupt + * flag, the function returns false. + * + * @todo These are the most important interrupts likely to be used. Others + * relating to LIN break, and error conditions in multibuffer communication, + * need to be added for completeness. + * + * @param[in] usart unsigned 32 bit. USART block register address base @ref + * usart_reg_base + * @param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags. + * @returns boolean: flag and interrupt enable both set. + */ + +bool usart_get_interrupt_source(uint32_t usart, uint32_t flag) +{ + uint32_t flag_set = (USART_ISR(usart) & flag); + /* IDLE, RXNE, TC, TXE interrupts */ + if ((flag >= USART_ISR_IDLE) && (flag <= USART_ISR_TXE)) { + return ((flag_set & USART_CR1(usart)) != 0); + /* Overrun error */ + } else if (flag == USART_ISR_ORE) { + return flag_set && (USART_CR3(usart) & USART_CR3_CTSIE); + } + + return false; +} + +/**@}*/ diff --git a/libopencm3/lib/stm32/f3/vector_chipset.c b/libopencm3/lib/stm32/f3/vector_chipset.c new file mode 100644 index 0000000..145be05 --- /dev/null +++ b/libopencm3/lib/stm32/f3/vector_chipset.c @@ -0,0 +1,27 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Piotr Esden-Tempski + * Copyright (C) 2011 Fergus Noble + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + +static void pre_main(void) +{ + /* Enable access to Floating-Point coprocessor. */ + SCB_CPACR |= SCB_CPACR_FULL * (SCB_CPACR_CP10 | SCB_CPACR_CP11); +} -- cgit v1.2.3