git subrepo clone https://github.com/libopencm3/libopencm3
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:
65
libopencm3/lib/stm32/f0/Makefile
Normal file
65
libopencm3/lib/stm32/f0/Makefile
Normal 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
|
||||
|
||||
540
libopencm3/lib/stm32/f0/adc.c
Normal file
540
libopencm3/lib/stm32/f0/adc.c
Normal 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);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/**@}*/
|
||||
64
libopencm3/lib/stm32/f0/comparator.c
Normal file
64
libopencm3/lib/stm32/f0/comparator.c
Normal 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;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
156
libopencm3/lib/stm32/f0/flash.c
Normal file
156
libopencm3/lib/stm32/f0/flash.c
Normal 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 © @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. */
|
||||
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
32
libopencm3/lib/stm32/f0/i2c.c
Normal file
32
libopencm3/lib/stm32/f0/i2c.c
Normal 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>
|
||||
|
||||
697
libopencm3/lib/stm32/f0/rcc.c
Normal file
697
libopencm3/lib/stm32/f0/rcc.c
Normal 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;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
31
libopencm3/lib/stm32/f0/syscfg.c
Normal file
31
libopencm3/lib/stm32/f0/syscfg.c
Normal 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>
|
||||
Reference in New Issue
Block a user