subrepo:
  subdir:   "libopencm3"
  merged:   "f5813a54"
upstream:
  origin:   "https://github.com/libopencm3/libopencm3"
  branch:   "master"
  commit:   "f5813a54"
git-subrepo:
  version:  "0.4.3"
  origin:   "???"
  commit:   "???"
This commit is contained in:
2021-09-30 16:34:10 +03:00
parent 1a441e5806
commit 244fdbc35c
1125 changed files with 185440 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
##
## This file is part of the libopencm3 project.
##
## Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
##
## 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 <http://www.gnu.org/licenses/>.
##
LIBNAME = libopencm3_stm32f0
SRCLIBDIR ?= ../..
CC = $(PREFIX)gcc
AR = $(PREFIX)ar
TGT_CFLAGS = -Os \
-Wall -Wextra -Wimplicit-function-declaration \
-Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes \
-Wundef -Wshadow \
-I../../../include -fno-common \
-mcpu=cortex-m0 $(FP_FLAGS) -mthumb -Wstrict-prototypes \
-ffunction-sections -fdata-sections -MD -DSTM32F0
TGT_CFLAGS += $(DEBUG_FLAGS)
TGT_CFLAGS += $(STANDARD_FLAGS)
ARFLAGS = rcs
OBJS += adc.o adc_common_v2.o
OBJS += can.o
OBJS += comparator.o
OBJS += crc_common_all.o crc_v2.o
OBJS += crs_common_all.o
OBJS += dac_common_all.o dac_common_v1.o
OBJS += desig_common_all.o desig_common_v1.o
OBJS += dma_common_l1f013.o dma_common_csel.o
OBJS += exti_common_all.o
OBJS += flash.o flash_common_all.o flash_common_f.o flash_common_f01.o
OBJS += gpio_common_all.o gpio_common_f0234.o
OBJS += iwdg_common_all.o
OBJS += i2c_common_v2.o
OBJS += pwr_common_v1.o
OBJS += rcc.o rcc_common_all.o
OBJS += rtc_common_l1f024.o
OBJS += spi_common_all.o spi_common_v2.o
OBJS += timer_common_all.o timer_common_f0234.o
OBJS += usart_common_all.o usart_common_v2.o
OBJS += usb.o usb_control.o usb_standard.o usb_msc.o
OBJS += usb_hid.o
OBJS += usb_audio.o usb_cdc.o usb_midi.o
OBJS += st_usbfs_core.o st_usbfs_v2.o
VPATH += ../../usb:../:../../cm3:../common
include ../../Makefile.include

View File

@@ -0,0 +1,540 @@
/** @addtogroup adc_file ADC peripheral API
* @ingroup peripheral_apis
*
* based on F3 file
*
* @date 14 July 2013
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/cm3/assert.h>
#include <libopencm3/stm32/adc.h>
/**@{*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
* @defgroup adc_api_opmode ADC Operation mode API
* @ingroup adc_file
*
* @brief ADC Result API
*
*@{*/
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable Discontinuous Mode for Regular Conversions
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_enable_discontinuous_mode(uint32_t adc)
{
ADC_CFGR1(adc) |= ADC_CFGR1_DISCEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable Discontinuous Mode for Regular Conversions
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_disable_discontinuous_mode(uint32_t adc)
{
ADC_CFGR1(adc) &= ~ADC_CFGR1_DISCEN;
}
/*---------------------------------------------------------------------------*/
/** ADC Set operation mode
*
* There are some operation modes, common for entire stm32 branch. In the text
* the braces are describing result to single trigger event. The trigger event
* is described by character T in the description. The ADC is configured to
* convert list of inputs [0, 1, 2, 3]. In Grouped modes, there is used group
* size of 2 conversions in the examples
*
* @li @c ADC_MODE_SEQUENTIAL: T(0) T(1) T(2) T(3)[EOSEQ] T(0) T(1) T(2) ...
*
* In this mode, after the trigger event a single channel is converted and the
* next channel in the list is prepared to convert on next trigger edge.
*
* @note This mode can be emulated by ADC_MODE_GROUPED with group size
* of 1.
*
* @li @c ADC_MODE_SCAN: T(0123)[EOSEQ] T(0123)[EOSEQ] T(0123)[EOSEQ]
*
* In this mode, after the trigger event, all channels will be converted once,
* storing results sequentially.
*
* @note The DMA must be configured properly for more than single channel to
* convert.
*
* @li @c ADC_MODE_SCAN_INFINITE: T(0123[EOSEQ]0123[EOSEQ]0123[EOSEQ]...)
*
* In this mode, after the trigger event, all channels from the list are
* converted. At the end of list, the conversion continues from the beginning.
*
* @note The DMA must be configured properly to operate in this mode.@par
*
* @li @c ADC_MODE_GROUPED: T(12) T(34)[EOSEQ] T(12) T(34)[EOSEQ] T(12)
*
* In this mode, after the trigger event, a specified group size of channels
* are converted. If the end of channel list occurs, the EOSEQ is generated
* and on the next trigger it wraps to the beginning.
*
* @note The DMA must be configured properly to operate on more than single
* channel conversion groups.
*
* @warning not all families supports all modes of operation of ADC.
*
*/
/*---------------------------------------------------------------------------*/
/** @brief ADC Set conversion operation mode
*
* @note on SEQUENTIAL mode, the trigger event is necessary to start conversion.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] opmode ADC operation mode
*/
void adc_set_operation_mode(uint32_t adc, enum adc_opmode opmode)
{
switch (opmode) {
case ADC_MODE_SEQUENTIAL:
ADC_CFGR1(adc) &= ~ADC_CFGR1_CONT;
ADC_CFGR1(adc) |= ADC_CFGR1_DISCEN;
break;
case ADC_MODE_SCAN:
ADC_CFGR1(adc) &= ~(ADC_CFGR1_CONT | ADC_CFGR1_DISCEN);
break;
case ADC_MODE_SCAN_INFINITE:
ADC_CFGR1(adc) &= ~ADC_CFGR1_DISCEN;
ADC_CFGR1(adc) |= ADC_CFGR1_CONT;
break;
}
}
/**@}*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
* @defgroup adc_api_trigger ADC Trigger API
* @ingroup adc_file
*
* @brief ADC Trigger API
*
*@{*/
/*---------------------------------------------------------------------------*/
/** @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 base address (@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)
{
ADC_CFGR1(adc) = (ADC_CFGR1(adc) & ~ADC_CFGR1_EXTSEL) | trigger;
ADC_CFGR1(adc) = (ADC_CFGR1(adc) & ~ADC_CFGR1_EXTEN_MASK) | polarity;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable an External Trigger for Regular Channels
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_disable_external_trigger_regular(uint32_t adc)
{
ADC_CFGR1(adc) &= ~ADC_CFGR1_EXTEN_MASK;
}
/**@}*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
* @defgroup adc_api_interrupts ADC Interrupt configuration API
* @ingroup adc_file
*
* @brief ADC Interrupt configuration API
*
*@{*/
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable Analog Watchdog Interrupt
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_enable_watchdog_interrupt(uint32_t adc)
{
ADC_IER(adc) |= ADC_IER_AWD1IE;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable Regular End-Of-Conversion Interrupt
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_disable_watchdog_interrupt(uint32_t adc)
{
ADC_IER(adc) &= ~ADC_IER_AWD1IE;
}
/*---------------------------------------------------------------------------*/
/** @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 base address (@ref adc_reg_base)
* @returns bool true, if the signal is out of defined analog range.
*/
bool adc_get_watchdog_flag(uint32_t adc)
{
return ADC_ISR(adc) & ADC_ISR_AWD1;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Clear Analog Watchdog Flag
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_clear_watchdog_flag(uint32_t adc)
{
ADC_ISR(adc) = ADC_ISR_AWD1;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable Regular End-Of-Conversion Sequence Interrupt
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_enable_eoc_sequence_interrupt(uint32_t adc)
{
ADC_IER(adc) |= ADC_IER_EOSEQIE;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable Regular End-Of-Conversion Sequence Interrupt
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_disable_eoc_sequence_interrupt(uint32_t adc)
{
ADC_IER(adc) &= ~ADC_IER_EOSEQIE;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Read the Regular End-Of-Conversion Sequence Flag
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
bool adc_get_eoc_sequence_flag(uint32_t adc)
{
return ADC_ISR(adc) & ADC_ISR_EOSEQ;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Clear Regular End-Of-Conversion Sequence Flag
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_clear_eoc_sequence_flag(uint32_t adc)
{
ADC_ISR(adc) = ADC_ISR_EOSEQ;
}
/**@}*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
* @defgroup adc_api_config ADC Basic configuration API
* @ingroup adc_file
*
* @brief ADC Basic configuration API
*
*@{*/
/*---------------------------------------------------------------------------*/
/** @brief ADC Set Clock Source
*
* The ADC clock taken from the many sources.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] source Unsigned int32. Source (@ref adc_api_clksource)
*/
void adc_set_clk_source(uint32_t adc, uint32_t source)
{
ADC_CFGR2(adc) = ((ADC_CFGR2(adc) & ~ADC_CFGR2_CKMODE) | source);
}
/*---------------------------------------------------------------------------*/
/** @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 18 channels. If this is called during conversion, the
* current conversion is reset and conversion begins again with the newly
* defined group.
*
* @warning This core doesn't support the random order of ADC conversions.
* The channel list must be ordered by channel number.
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] length Unsigned int8. Number of channels in the group.
* @param[in] channel Unsigned int8[]. Set of channels to convert, integers
* 0..18.
*/
void adc_set_regular_sequence(uint32_t adc, uint8_t length, uint8_t channel[])
{
uint32_t reg32 = 0;
uint8_t i = 0;
bool stepup = false, stepdn = false;
if (length == 0) {
ADC_CHSELR(adc) = 0;
return;
}
reg32 |= (1 << channel[0]);
for (i = 1; i < length; i++) {
reg32 |= (1 << channel[i]);
stepup |= channel[i-1] < channel[i];
stepdn |= channel[i-1] > channel[i];
}
/* Check, if the channel list is in order */
if (stepup && stepdn) {
cm3_assert_not_reached();
}
/* Update the scan direction flag */
if (stepdn) {
ADC_CFGR1(adc) |= ADC_CFGR1_SCANDIR;
} else {
ADC_CFGR1(adc) &= ~ADC_CFGR1_SCANDIR;
}
ADC_CHSELR(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 base address (@ref adc_reg_base)
* @param[in] time Unsigned int8. Sampling time selection (@ref adc_api_smptime)
*/
void adc_set_sample_time_on_all_channels(uint32_t adc, uint8_t time)
{
ADC_SMPR(adc) = time & ADC_SMPR_SMP;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable The VBat Sensor
*
* This enables the battery voltage measurements on channel 17.
*/
void adc_enable_vbat_sensor(void)
{
ADC_CCR(ADC1) |= ADC_CCR_VBATEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable The VBat Sensor
*
* Disabling this will reduce power consumption from the battery voltage
* measurement.
*/
void adc_disable_vbat_sensor(void)
{
ADC_CCR(ADC1) &= ~ADC_CCR_VBATEN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Start the calibration procedure
* @deprecated Replaced by adc_calibrate/_async/is_calibrating
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_calibrate_start(uint32_t adc)
{
ADC_CR(adc) = ADC_CR_ADCAL;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Wait to finish the ADC calibration procedure
* @deprecated Replaced by adc_calibrate/_async/is_calibrating
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_calibrate_wait_finish(uint32_t adc)
{
while (ADC_CR(adc) & ADC_CR_ADCAL);
}
/**@}*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
* @defgroup adc_api_wdg ADC Analog watchdog API
* @ingroup adc_file
*
* @brief ADC analog watchdog API definitions.
*
* The analog watchdog allows the monitoring of an analog signal between two
* threshold levels. The thresholds must be preset. Analog watchdog is disabled
* by default.
*
* @warning Comparison is done before data alignment takes place, so the
* thresholds are left-aligned.
*
* Example 1: Enable watchdog checking on all channels
*
* @code
* // in configuration
* adc_enable_analog_watchdog_on_all_channels(ADC1);
* adc_set_watchdog_high_threshold(ADC1, 0xE00);
* adc_set_watchdog_low_threshold(ADC1, 0x200);
*
* // in the main application thread
* if (adc_get_watchdog_flag(ADC1)) {
* // the converted signal is out of AWD ranges
* adc_clear_watchdog_flag(ADC1);
* }
* @endcode
*
* Example 2: Enable watchdog checking on channel 5
*
* @code
* // in configuration
* adc_enable_analog_watchdog_on_selected_channel(ADC1,5);
* adc_set_watchdog_high_threshold(ADC1, 0xE00);
* adc_set_watchdog_low_threshold(ADC1, 0x200);
*
* // in the main application thread
* if (adc_get_watchdog_flag(ADC1)) {
* // the converted signal is out of AWD ranges
* adc_clear_watchdog_flag(ADC1);
* }
* @endcode
*@{*/
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable Analog Watchdog for All Channels
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_enable_analog_watchdog_on_all_channels(uint32_t adc)
{
ADC_CFGR1(adc) |= ADC_CFGR1_AWD1EN;
ADC_CFGR1(adc) &= ~ADC_CFGR1_AWD1SGL;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Enable Analog Watchdog for a Selected Channel
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] chan Unsigned int8. ADC channel number @ref adc_api_channel
*/
void adc_enable_analog_watchdog_on_selected_channel(uint32_t adc, uint8_t chan)
{
ADC_CFGR1(adc) = (ADC_CFGR1(adc) & ~ADC_CFGR1_AWD1CH) |
ADC_CFGR1_AWD1CH_VAL(chan);
ADC_CFGR1(adc) |= ADC_CFGR1_AWD1EN | ADC_CFGR1_AWD1SGL;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Disable Analog Watchdog
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
*/
void adc_disable_analog_watchdog(uint32_t adc)
{
ADC_CFGR1(adc) &= ~ADC_CFGR1_AWD1EN;
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Set Analog Watchdog Upper Threshold
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] threshold Upper threshold value
*/
void adc_set_watchdog_high_threshold(uint32_t adc, uint16_t threshold)
{
ADC_TR1(adc) = (ADC_TR1(adc) & ~ADC_TR1_HT) | ADC_TR1_HT_VAL(threshold);
}
/*---------------------------------------------------------------------------*/
/** @brief ADC Set Analog Watchdog Lower Threshold
*
* @param[in] adc Unsigned int32. ADC base address (@ref adc_reg_base)
* @param[in] threshold Lower threshold value
*/
void adc_set_watchdog_low_threshold(uint32_t adc, uint16_t threshold)
{
ADC_TR1(adc) = (ADC_TR1(adc) & ~ADC_TR1_LT) | ADC_TR1_LT_VAL(threshold);
}
/**@}*/
/*---------------------------------------------------------------------------*/
/**@}*/

View File

@@ -0,0 +1,64 @@
/** @defgroup comp_file COMP
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx COMP</b>
*
* @version 1.0.0
*
* @date 10 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 <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/comparator.h>
void comp_enable(uint8_t id)
{
COMP_CSR(id) |= COMP_CSR_EN;
}
void comp_disable(uint8_t id)
{
COMP_CSR(id) &= ~COMP_CSR_EN;
}
void comp_select_input(uint8_t id, uint32_t input)
{
COMP_CSR(id) = (COMP_CSR(id) & ~COMP_CSR_INSEL) | input;
}
void comp_select_output(uint8_t id, uint32_t output)
{
COMP_CSR(id) = (COMP_CSR(id) & ~COMP_CSR_OUTSEL) | output;
}
void comp_select_hyst(uint8_t id, uint32_t hyst)
{
COMP_CSR(id) = (COMP_CSR(id) & ~COMP_CSR_HYST) | hyst;
}
void comp_select_speed(uint8_t id, uint32_t speed)
{
COMP_CSR(id) = (COMP_CSR(id) & ~COMP_CSR_SPEED) | speed;
}
/**@}*/

View File

@@ -0,0 +1,156 @@
/** @defgroup flash_file FLASH peripheral API
*
* @ingroup peripheral_apis
*
* @brief <b>libopencm3 STM32F05x FLASH</b>
*
* @version 1.0.0
*
* @author @htmlonly &copy; @endhtmlonly 2013
* Frantisek Burian <BuFran@seznam.cz>
*
* @date 14 January 2014
*
* For the STM32F05x, accessing FLASH memory is described in
* section 3 of the STM32F05x Reference Manual.
*
* FLASH memory may be used for data storage as well as code, and may be
* programmatically modified. Note that for firmware upload the STM32F1xx
* provides a built-in bootloader in system memory that can be entered from a
* running program.
*
* FLASH must first be unlocked before programming. In this module a write to
* FLASH is a blocking operation until the end-of-operation flag is asserted.
*
* @note: don't forget to lock it again when all operations are complete.
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/flash.h>
/*---------------------------------------------------------------------------*/
/** @brief Clear All Status Flags
Program error, end of operation, write protect error, busy.
*/
void flash_clear_status_flags(void)
{
flash_clear_pgerr_flag();
flash_clear_eop_flag();
flash_clear_wrprterr_flag();
}
/*---------------------------------------------------------------------------*/
/** @brief Read All Status Flags
The programming error, end of operation, write protect error and busy flags
are returned in the order of appearance in the status register.
@returns uint32_t. bit 0: busy, bit 2: programming error, bit 4: write protect
error, bit 5: end of operation.
*/
uint32_t flash_get_status_flags(void)
{
return FLASH_SR & (FLASH_SR_PGERR |
FLASH_SR_EOP |
FLASH_SR_WRPRTERR |
FLASH_SR_BSY);
}
/*---------------------------------------------------------------------------*/
/** @brief Program a Half Word to FLASH
This performs all operations necessary to program a 16 bit word to FLASH memory.
The program error flag should be checked separately for the event that memory
was not properly erased.
Status bit polling is used to detect end of operation.
@param[in] address Full address of flash half word to be programmed.
@param[in] data half word to write
*/
void flash_program_half_word(uint32_t address, uint16_t data)
{
flash_wait_for_last_operation();
FLASH_CR |= FLASH_CR_PG;
MMIO16(address) = data;
flash_wait_for_last_operation();
FLASH_CR &= ~FLASH_CR_PG;
}
/*---------------------------------------------------------------------------*/
/** @brief Erase a Page of FLASH
This performs all operations necessary to erase a page in FLASH memory.
The page should be checked to ensure that it was properly erased. A page must
first be fully erased before attempting to program it.
Note that the page sizes differ between devices. See the reference manual or
the FLASH programming manual for details.
@param[in] page_address Full address of flash page to be erased.
*/
void flash_erase_page(uint32_t page_address)
{
flash_wait_for_last_operation();
FLASH_CR |= FLASH_CR_PER;
FLASH_AR = page_address;
FLASH_CR |= FLASH_CR_STRT;
flash_wait_for_last_operation();
FLASH_CR &= ~FLASH_CR_PER;
}
/*---------------------------------------------------------------------------*/
/** @brief Erase All FLASH
This performs all operations necessary to erase all user pages in the FLASH
memory. The information block is unaffected.
*/
void flash_erase_all_pages(void)
{
flash_wait_for_last_operation();
FLASH_CR |= FLASH_CR_MER; /* Enable mass erase. */
FLASH_CR |= FLASH_CR_STRT; /* Trigger the erase. */
flash_wait_for_last_operation();
FLASH_CR &= ~FLASH_CR_MER; /* Disable mass erase. */
}
/**@}*/

View File

@@ -0,0 +1,32 @@
/** @defgroup i2c_file I2C
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx I2C</b>
*
* @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 <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/i2c.h>

View File

@@ -0,0 +1,697 @@
/** @defgroup rcc_file RCC peripheral API
*
* @ingroup peripheral_apis
*
* @brief <b>libopencm3 STM32F0xx Reset and Clock Control</b>
*
* @version 1.0.0
*
* @date 29 Jun 2013
*
* This library supports the Reset and Clock Control System in the STM32F0xx
* series of ARM Cortex Microcontrollers by ST Microelectronics.
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Federico Ruiz-Ugalde <memeruiz at gmail dot com>
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/cm3/assert.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/flash.h>
#include <libopencm3/stm32/i2c.h>
/* Set the default clock frequencies */
uint32_t rcc_ahb_frequency = 8000000; /* 8MHz after reset */
uint32_t rcc_apb1_frequency = 8000000; /* 8MHz after reset */
/*---------------------------------------------------------------------------*/
/** @brief RCC Clear the Oscillator Ready Interrupt Flag
*
* Clear the interrupt flag that was set when a clock oscillator became ready
* to use.
*
* @param osc Oscillator ID
*/
void rcc_osc_ready_int_clear(enum rcc_osc osc)
{
switch (osc) {
case RCC_HSI48:
RCC_CIR |= RCC_CIR_HSI48RDYC;
break;
case RCC_HSI14:
RCC_CIR |= RCC_CIR_HSI14RDYC;
break;
case RCC_HSI:
RCC_CIR |= RCC_CIR_HSIRDYC;
break;
case RCC_HSE:
RCC_CIR |= RCC_CIR_HSERDYC;
break;
case RCC_PLL:
RCC_CIR |= RCC_CIR_PLLRDYC;
break;
case RCC_LSE:
RCC_CIR |= RCC_CIR_LSERDYC;
break;
case RCC_LSI:
RCC_CIR |= RCC_CIR_LSIRDYC;
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Enable the Oscillator Ready Interrupt
*
* @param osc Oscillator ID
*/
void rcc_osc_ready_int_enable(enum rcc_osc osc)
{
switch (osc) {
case RCC_HSI48:
RCC_CIR |= RCC_CIR_HSI48RDYIE;
break;
case RCC_HSI14:
RCC_CIR |= RCC_CIR_HSI14RDYIE;
break;
case RCC_HSI:
RCC_CIR |= RCC_CIR_HSIRDYIE;
break;
case RCC_HSE:
RCC_CIR |= RCC_CIR_HSERDYIE;
break;
case RCC_PLL:
RCC_CIR |= RCC_CIR_PLLRDYIE;
break;
case RCC_LSE:
RCC_CIR |= RCC_CIR_LSERDYIE;
break;
case RCC_LSI:
RCC_CIR |= RCC_CIR_LSIRDYIE;
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Disable the Oscillator Ready Interrupt
*
* @param osc Oscillator ID
*/
void rcc_osc_ready_int_disable(enum rcc_osc osc)
{
switch (osc) {
case RCC_HSI48:
RCC_CIR &= ~RCC_CIR_HSI48RDYC;
break;
case RCC_HSI14:
RCC_CIR &= ~RCC_CIR_HSI14RDYC;
break;
case RCC_HSI:
RCC_CIR &= ~RCC_CIR_HSIRDYC;
break;
case RCC_HSE:
RCC_CIR &= ~RCC_CIR_HSERDYC;
break;
case RCC_PLL:
RCC_CIR &= ~RCC_CIR_PLLRDYC;
break;
case RCC_LSE:
RCC_CIR &= ~RCC_CIR_LSERDYC;
break;
case RCC_LSI:
RCC_CIR &= ~RCC_CIR_LSIRDYC;
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Read the Oscillator Ready Interrupt Flag
*
* @param osc Oscillator ID
* @returns int. Boolean value for flag set.
*/
int rcc_osc_ready_int_flag(enum rcc_osc osc)
{
switch (osc) {
case RCC_HSI48:
return (RCC_CIR & RCC_CIR_HSI48RDYF) != 0;
break;
case RCC_HSI14:
return (RCC_CIR & RCC_CIR_HSI14RDYF) != 0;
break;
case RCC_HSI:
return (RCC_CIR & RCC_CIR_HSIRDYF) != 0;
break;
case RCC_HSE:
return (RCC_CIR & RCC_CIR_HSERDYF) != 0;
break;
case RCC_PLL:
return (RCC_CIR & RCC_CIR_PLLRDYF) != 0;
break;
case RCC_LSE:
return (RCC_CIR & RCC_CIR_LSERDYF) != 0;
break;
case RCC_LSI:
return (RCC_CIR & RCC_CIR_LSIRDYF) != 0;
break;
}
cm3_assert_not_reached();
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Clear the Clock Security System Interrupt Flag
*/
void rcc_css_int_clear(void)
{
RCC_CIR |= RCC_CIR_CSSC;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Read the Clock Security System Interrupt Flag
*
* @returns int. Boolean value for flag set.
*/
int rcc_css_int_flag(void)
{
return ((RCC_CIR & RCC_CIR_CSSF) != 0);
}
bool rcc_is_osc_ready(enum rcc_osc osc)
{
switch (osc) {
case RCC_HSI48:
return RCC_CR2 & RCC_CR2_HSI48RDY;
case RCC_HSI14:
return RCC_CR2 & RCC_CR2_HSI14RDY;
case RCC_HSI:
return RCC_CR & RCC_CR_HSIRDY;
case RCC_HSE:
return RCC_CR & RCC_CR_HSERDY;
case RCC_PLL:
return RCC_CR & RCC_CR_PLLRDY;
case RCC_LSE:
return RCC_BDCR & RCC_BDCR_LSERDY;
case RCC_LSI:
return RCC_CSR & RCC_CSR_LSIRDY;
}
return false;
}
void rcc_wait_for_osc_ready(enum rcc_osc osc)
{
while (!rcc_is_osc_ready(osc));
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Turn on an Oscillator.
*
* Enable an oscillator and power on. Each oscillator requires an amount of
* time to settle to a usable state. Refer to datasheets for time delay
* information. A status flag is available to indicate when the oscillator
* becomes ready (see @ref rcc_osc_ready_int_flag and @ref
* rcc_wait_for_osc_ready).
*
* @param osc Oscillator ID
*/
void rcc_osc_on(enum rcc_osc osc)
{
switch (osc) {
case RCC_HSI48:
RCC_CR2 |= RCC_CR2_HSI48ON;
break;
case RCC_HSI14:
RCC_CR2 |= RCC_CR2_HSI14ON;
break;
case RCC_HSI:
RCC_CR |= RCC_CR_HSION;
break;
case RCC_HSE:
RCC_CR |= RCC_CR_HSEON;
break;
case RCC_LSE:
RCC_BDCR |= RCC_BDCR_LSEON;
break;
case RCC_LSI:
RCC_CSR |= RCC_CSR_LSION;
break;
case RCC_PLL:
RCC_CR |= RCC_CR_PLLON;
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Turn off an Oscillator.
*
* Disable an oscillator and power off.
*
* @note An oscillator cannot be turned off if it is selected as the system
* clock.
*
* @param osc Oscillator ID
*/
void rcc_osc_off(enum rcc_osc osc)
{
switch (osc) {
case RCC_HSI48:
RCC_CR2 &= ~RCC_CR2_HSI48ON;
break;
case RCC_HSI14:
RCC_CR2 &= ~RCC_CR2_HSI14ON;
break;
case RCC_HSI:
RCC_CR &= ~RCC_CR_HSION;
break;
case RCC_HSE:
RCC_CR &= ~RCC_CR_HSEON;
break;
case RCC_LSE:
RCC_BDCR &= ~RCC_BDCR_LSEON;
break;
case RCC_LSI:
RCC_CSR &= ~RCC_CSR_LSION;
break;
case RCC_PLL:
/* don't do anything */
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Enable the Clock Security System.
*/
void rcc_css_enable(void)
{
RCC_CR |= RCC_CR_CSSON;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Disable the Clock Security System.
*/
void rcc_css_disable(void)
{
RCC_CR &= ~RCC_CR_CSSON;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Set the Source for the System Clock.
*
* @param clk Oscillator ID. Only HSE, LSE and PLL have
* effect.
*/
void rcc_set_sysclk_source(enum rcc_osc clk)
{
switch (clk) {
case RCC_HSI:
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_HSI;
break;
case RCC_HSE:
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_HSE;
break;
case RCC_PLL:
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_PLL;
break;
case RCC_HSI48:
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_HSI48;
break;
case RCC_LSI:
case RCC_LSE:
case RCC_HSI14:
/* do nothing */
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Set the Source for the USB Clock.
*
* @param clk Oscillator ID. Only HSI48 or PLL have
* effect.
*/
void rcc_set_usbclk_source(enum rcc_osc clk)
{
switch (clk) {
case RCC_PLL:
RCC_CFGR3 |= RCC_CFGR3_USBSW;
break;
case RCC_HSI48:
RCC_CFGR3 &= ~RCC_CFGR3_USBSW;
break;
case RCC_HSI:
case RCC_HSE:
case RCC_LSI:
case RCC_LSE:
case RCC_HSI14:
/* do nothing */
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Enable the RTC clock
*/
void rcc_enable_rtc_clock(void)
{
RCC_BDCR |= RCC_BDCR_RTCEN;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Disable the RTC clock
*/
void rcc_disable_rtc_clock(void)
{
RCC_BDCR &= ~RCC_BDCR_RTCEN;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Set the Source for the RTC clock
@param[in] clk RTC clock source. Only HSE/32, LSE and LSI.
*/
void rcc_set_rtc_clock_source(enum rcc_osc clk)
{
switch (clk) {
case RCC_HSE:
RCC_BDCR = (RCC_BDCR & ~RCC_BDCR_RTCSEL) | RCC_BDCR_RTCSEL_HSE;
break;
case RCC_LSE:
RCC_BDCR = (RCC_BDCR & ~RCC_BDCR_RTCSEL) | RCC_BDCR_RTCSEL_LSE;
break;
case RCC_LSI:
RCC_BDCR = (RCC_BDCR & ~RCC_BDCR_RTCSEL) | RCC_BDCR_RTCSEL_LSI;
break;
default:
/* do nothing */
break;
}
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Set the PLL Multiplication Factor.
*
* @note This only has effect when the PLL is disabled.
*
* @param[in] mul Unsigned int32. PLL multiplication factor @ref rcc_cfgr_pmf
*/
void rcc_set_pll_multiplication_factor(uint32_t mul)
{
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_PLLMUL) | mul;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Set the PLL Clock Source.
@note This only has effect when the PLL is disabled.
@param[in] pllsrc Unsigned int32. PLL clock source @ref rcc_cfgr_pcs
*/
void rcc_set_pll_source(uint32_t pllsrc)
{
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_PLLSRC) |
(pllsrc << 16);
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Set the HSE Frequency Divider used as PLL Clock Source.
@note This only has effect when the PLL is disabled.
@param[in] pllxtpre Unsigned int32. HSE division factor @ref rcc_cfgr_hsepre
*/
void rcc_set_pllxtpre(uint32_t pllxtpre)
{
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_PLLXTPRE) |
(pllxtpre << 17);
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Set the APB Prescale Factor.
*
* @param[in] ppre Unsigned int32. APB prescale factor @ref rcc_cfgr_apb1pre
*/
void rcc_set_ppre(uint32_t ppre)
{
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_PPRE) | ppre;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Set the AHB Prescale Factor.
*
* @param[in] hpre Unsigned int32. AHB prescale factor @ref rcc_cfgr_ahbpre
*/
void rcc_set_hpre(uint32_t hpre)
{
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_HPRE) | hpre;
}
/**
* Set PLL Source pre-divider **CAUTION**.
* On F03x and F05, prediv only applies to HSE source. On others, this
* is _after_ source selection. See also f3.
* @param[in] prediv division by prediv+1 @ref rcc_cfgr2_prediv
*/
void rcc_set_prediv(uint32_t prediv)
{
RCC_CFGR2 = (RCC_CFGR2 & ~RCC_CFGR2_PREDIV) | prediv;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Get the System Clock Source.
*
* @returns current system clock source
*/
enum rcc_osc rcc_system_clock_source(void)
{
/* Return the clock source which is used as system clock. */
switch (RCC_CFGR & RCC_CFGR_SWS) {
case RCC_CFGR_SWS_HSI:
return RCC_HSI;
case RCC_CFGR_SWS_HSE:
return RCC_HSE;
case RCC_CFGR_SWS_PLL:
return RCC_PLL;
case RCC_CFGR_SWS_HSI48:
return RCC_HSI48;
}
cm3_assert_not_reached();
}
void rcc_set_i2c_clock_hsi(uint32_t i2c)
{
if (i2c == I2C1) {
RCC_CFGR3 &= ~RCC_CFGR3_I2C1SW;
}
}
void rcc_set_i2c_clock_sysclk(uint32_t i2c)
{
if (i2c == I2C1) {
RCC_CFGR3 |= RCC_CFGR3_I2C1SW;
}
}
uint32_t rcc_get_i2c_clocks(void)
{
return RCC_CFGR3 & RCC_CFGR3_I2C1SW;
}
/*---------------------------------------------------------------------------*/
/** @brief RCC Get the USB Clock Source.
*
* @returns Currently selected USB clock source
*/
enum rcc_osc rcc_usb_clock_source(void)
{
return (RCC_CFGR3 & RCC_CFGR3_USBSW) ? RCC_PLL : RCC_HSI48;
}
/**
* Set System Clock PLL at 48MHz from HSE at 8MHz.
*/
void rcc_clock_setup_in_hse_8mhz_out_48mhz(void)
{
rcc_osc_on(RCC_HSE);
rcc_wait_for_osc_ready(RCC_HSE);
rcc_set_sysclk_source(RCC_HSE);
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
rcc_set_ppre(RCC_CFGR_PPRE_NODIV);
flash_prefetch_enable();
flash_set_ws(FLASH_ACR_LATENCY_024_048MHZ);
/* PLL: 8MHz * 6 = 48MHz */
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_MUL6);
rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_CLK);
rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK);
rcc_osc_on(RCC_PLL);
rcc_wait_for_osc_ready(RCC_PLL);
rcc_set_sysclk_source(RCC_PLL);
rcc_apb1_frequency = 48000000;
rcc_ahb_frequency = 48000000;
}
/**
* Set System Clock PLL at 48MHz from HSI
*/
void rcc_clock_setup_in_hsi_out_48mhz(void)
{
rcc_osc_on(RCC_HSI);
rcc_wait_for_osc_ready(RCC_HSI);
rcc_set_sysclk_source(RCC_HSI);
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
rcc_set_ppre(RCC_CFGR_PPRE_NODIV);
flash_prefetch_enable();
flash_set_ws(FLASH_ACR_LATENCY_024_048MHZ);
/* 8MHz * 12 / 2 = 48MHz */
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_MUL12);
rcc_set_pll_source(RCC_CFGR_PLLSRC_HSI_CLK_DIV2);
rcc_osc_on(RCC_PLL);
rcc_wait_for_osc_ready(RCC_PLL);
rcc_set_sysclk_source(RCC_PLL);
rcc_apb1_frequency = 48000000;
rcc_ahb_frequency = 48000000;
}
/**
* Set System Clock HSI48 at 48MHz
*/
void rcc_clock_setup_in_hsi48_out_48mhz(void)
{
rcc_osc_on(RCC_HSI48);
rcc_wait_for_osc_ready(RCC_HSI48);
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
rcc_set_ppre(RCC_CFGR_PPRE_NODIV);
flash_prefetch_enable();
flash_set_ws(FLASH_ACR_LATENCY_024_048MHZ);
rcc_set_sysclk_source(RCC_HSI48);
rcc_apb1_frequency = 48000000;
rcc_ahb_frequency = 48000000;
}
static uint32_t rcc_get_usart_clksel_freq(uint8_t shift) {
uint8_t clksel = (RCC_CFGR3 >> shift) & RCC_CFGR3_USARTxSW_MASK;
uint8_t hpre = (RCC_CFGR >> RCC_CFGR_HPRE_SHIFT) & RCC_CFGR_HPRE_MASK;
switch (clksel) {
case RCC_CFGR3_USART1SW_PCLK:
return rcc_apb1_frequency;
case RCC_CFGR3_USART1SW_SYSCLK:
return rcc_ahb_frequency * rcc_get_div_from_hpre(hpre);
case RCC_CFGR3_USART1SW_HSI:
return 8000000U;
}
cm3_assert_not_reached();
}
/*---------------------------------------------------------------------------*/
/** @brief Get the peripheral clock speed for the USART at base specified.
* @param usart Base address of USART to get clock frequency for.
*/
uint32_t rcc_get_usart_clk_freq(uint32_t usart)
{
if (usart == USART1_BASE) {
return rcc_get_usart_clksel_freq(RCC_CFGR3_USART1SW_SHIFT);
} else if (usart == USART2_BASE) {
return rcc_get_usart_clksel_freq(RCC_CFGR3_USART2SW_SHIFT);
} else if (usart == USART3_BASE) {
return rcc_get_usart_clksel_freq(RCC_CFGR3_USART3SW_SHIFT);
} else {
return rcc_apb1_frequency;
}
}
/*---------------------------------------------------------------------------*/
/** @brief Get the peripheral clock speed for the Timer at base specified.
* @param timer Base address of TIM to get clock frequency for.
*/
uint32_t rcc_get_timer_clk_freq(uint32_t timer __attribute__((unused)))
{
uint8_t ppre = (RCC_CFGR >> RCC_CFGR_PPRE_SHIFT) & RCC_CFGR_PPRE_MASK;
return (ppre == RCC_CFGR_PPRE_NODIV) ? rcc_apb1_frequency
: 2 * rcc_apb1_frequency;
}
/*---------------------------------------------------------------------------*/
/** @brief Get the peripheral clock speed for the I2C device at base specified.
* @param i2c Base address of I2C to get clock frequency for.
*/
uint32_t rcc_get_i2c_clk_freq(uint32_t i2c)
{
if (i2c == I2C1_BASE) {
if (RCC_CFGR3 & RCC_CFGR3_I2C1SW) {
uint8_t hpre = (RCC_CFGR >> RCC_CFGR_HPRE_SHIFT) & RCC_CFGR_HPRE_MASK;
return rcc_ahb_frequency * rcc_get_div_from_hpre(hpre);
} else {
return 8000000U;
}
} else {
return rcc_apb1_frequency;
}
}
/*---------------------------------------------------------------------------*/
/** @brief Get the peripheral clock speed for the SPI device at base specified.
* @param spi Base address of SPI device to get clock frequency for (e.g. SPI1_BASE).
*/
uint32_t rcc_get_spi_clk_freq(uint32_t spi __attribute__((unused))) {
return rcc_apb1_frequency;
}
/**@}*/

View File

@@ -0,0 +1,31 @@
/** @defgroup syscfg_file SYSCFG
*
* @ingroup STM32F0xx
*
* @brief <b>libopencm3 STM32F0xx SYSCFG</b>
*
* @version 1.0.0
*
* @date 10 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 <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/syscfg.h>