Rename stm32 lib folders to be consistent with include
This commit is contained in:
61
lib/stm32/f1/Makefile
Normal file
61
lib/stm32/f1/Makefile
Normal file
@@ -0,0 +1,61 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## This program is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program 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 General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_stm32f1
|
||||
|
||||
PREFIX ?= arm-none-eabi
|
||||
#PREFIX ?= arm-elf
|
||||
CC = $(PREFIX)-gcc
|
||||
AR = $(PREFIX)-ar
|
||||
CFLAGS = -Os -g -Wall -Wextra -I../../include -fno-common \
|
||||
-mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DSTM32F1
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
OBJS = vector.o rcc.o gpio.o usart.o adc.o spi.o flash.o nvic.o \
|
||||
rtc.o i2c.o dma.o systick.o exti.o scb.o ethernet.o \
|
||||
usb_f103.o usb.o usb_control.o usb_standard.o can.o \
|
||||
timer.o usb_f107.o
|
||||
|
||||
VPATH += ../usb:../stm32_common
|
||||
|
||||
# Be silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1)
|
||||
Q := @
|
||||
endif
|
||||
|
||||
all: $(LIBNAME).a
|
||||
|
||||
$(LIBNAME).a: $(OBJS)
|
||||
@printf " AR $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
%.o: %.c
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
@printf " CLEAN lib/stm32f1\n"
|
||||
$(Q)rm -f *.o *.d
|
||||
$(Q)rm -f $(LIBNAME).a
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
-include $(OBJS:.o=.d)
|
||||
|
||||
375
lib/stm32/f1/adc.c
Normal file
375
lib/stm32/f1/adc.c
Normal file
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2009 Edward Cheeseman <evbuilder@users.sourceforge.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Basic ADC handling API.
|
||||
*
|
||||
* Examples:
|
||||
* rcc_peripheral_enable_clock(&RCC_APB2ENR, ADC1EN);
|
||||
* rcc_peripheral_disable_clock(&RCC_APB2ENR, ADC1EN);
|
||||
* rcc_peripheral_reset(&RCC_APB2RSTR, ADC1RST);
|
||||
* rcc_peripheral_clear_reset(&RCC_APB2RSTR, ADC1RST);
|
||||
*
|
||||
* rcc_set_adc_clk(ADC_PRE_PLCK2_DIV2);
|
||||
* adc_set_mode(ADC1, TODO);
|
||||
* reg16 = adc_read(ADC1, ADC_CH_0);
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/f1/adc.h>
|
||||
|
||||
void rcc_set_adc_clk(u32 prescaler)
|
||||
{
|
||||
/* TODO */
|
||||
|
||||
/* FIXME: QUICK HACK to prevent compiler warnings. */
|
||||
prescaler = prescaler;
|
||||
}
|
||||
|
||||
void adc_set_mode(u32 block, /* TODO */ u8 mode)
|
||||
{
|
||||
/* TODO */
|
||||
|
||||
/* FIXME: QUICK HACK to prevent compiler warnings. */
|
||||
block = block;
|
||||
mode = mode;
|
||||
}
|
||||
|
||||
void adc_read(u32 block, u32 channel)
|
||||
{
|
||||
/* TODO */
|
||||
|
||||
/* FIXME: QUICK HACK to prevent compiler warnings. */
|
||||
block = block;
|
||||
channel = channel;
|
||||
}
|
||||
|
||||
void adc_enable_analog_watchdog_regular(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_AWDEN;
|
||||
}
|
||||
|
||||
void adc_disable_analog_watchdog_regular(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_AWDEN;
|
||||
}
|
||||
|
||||
void adc_enable_analog_watchdog_injected(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_JAWDEN;
|
||||
}
|
||||
|
||||
void adc_disable_analog_watchdog_injected(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_JAWDEN;
|
||||
}
|
||||
|
||||
void adc_enable_discontinous_mode_regular(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_DISCEN;
|
||||
}
|
||||
|
||||
void adc_disable_discontinous_mode_regular(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_DISCEN;
|
||||
}
|
||||
|
||||
void adc_enable_discontinous_mode_injected(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_JDISCEN;
|
||||
}
|
||||
|
||||
void adc_disable_discontinous_mode_injected(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_JDISCEN;
|
||||
}
|
||||
|
||||
void adc_enable_automatic_injected_group_conversion(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_JAUTO;
|
||||
}
|
||||
|
||||
void adc_disable_automatic_injected_group_conversion(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_JAUTO;
|
||||
}
|
||||
|
||||
void adc_enable_analog_watchdog_on_all_channels(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_AWDSGL;
|
||||
}
|
||||
|
||||
void adc_enable_analog_watchdog_on_selected_channel(u32 adc, u8 channel)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = (ADC_CR1(adc) & 0xffffffe0); /* Clear bits [4:0]. */
|
||||
if (channel < 18)
|
||||
reg32 |= channel;
|
||||
ADC_CR1(adc) = reg32;
|
||||
ADC_CR1(adc) &= ~ADC_CR1_AWDSGL;
|
||||
}
|
||||
|
||||
void adc_enable_scan_mode(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_SCAN;
|
||||
}
|
||||
|
||||
void adc_disable_scan_mode(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_SCAN;
|
||||
}
|
||||
|
||||
void adc_enable_jeoc_interrupt(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_JEOCIE;
|
||||
}
|
||||
|
||||
void adc_disable_jeoc_interrupt(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_JEOCIE;
|
||||
}
|
||||
|
||||
void adc_enable_awd_interrupt(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_AWDIE;
|
||||
}
|
||||
|
||||
void adc_disable_awd_interrupt(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_AWDIE;
|
||||
}
|
||||
|
||||
void adc_enable_eoc_interrupt(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_EOCIE;
|
||||
}
|
||||
|
||||
void adc_disable_eoc_interrupt(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_EOCIE;
|
||||
}
|
||||
|
||||
void adc_enable_temperature_sensor(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) |= ADC_CR2_TSVREFE;
|
||||
}
|
||||
|
||||
void adc_disable_temperature_sensor(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) &= ~ADC_CR2_TSVREFE;
|
||||
}
|
||||
|
||||
void adc_start_conversion_regular(u32 adc)
|
||||
{
|
||||
/* start conversion on regular channels */
|
||||
ADC_CR2(adc) |= ADC_CR2_SWSTART;
|
||||
|
||||
/* wait til the ADC starts the conversion */
|
||||
while (ADC_CR2(adc) & ADC_CR2_SWSTART);
|
||||
}
|
||||
|
||||
void adc_start_conversion_injected(u32 adc)
|
||||
{
|
||||
/* start conversion on injected channels */
|
||||
ADC_CR2(adc) |= ADC_CR2_JSWSTART;
|
||||
|
||||
/* wait til the ADC starts the conversion */
|
||||
while (ADC_CR2(adc) & ADC_CR2_JSWSTART);
|
||||
}
|
||||
|
||||
void adc_enable_external_trigger_regular(u32 adc, u8 trigger)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = (ADC_CR2(adc) & 0xfff1ffff); /* Clear bits [19:17]. */
|
||||
if (trigger < 8)
|
||||
reg32 |= (trigger << ADC_CR2_EXTSEL_LSB);
|
||||
ADC_CR2(adc) = reg32;
|
||||
ADC_CR2(adc) |= ADC_CR2_EXTTRIG;
|
||||
}
|
||||
|
||||
void adc_disable_external_trigger_regular(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) &= ~ADC_CR2_EXTTRIG;
|
||||
}
|
||||
|
||||
void adc_enable_external_trigger_injected(u32 adc, u8 trigger)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = (ADC_CR2(adc) & 0xffff8fff); /* Clear bits [12:14]. */
|
||||
if (trigger < 8)
|
||||
reg32 |= (trigger << ADC_CR2_JEXTSEL_LSB);
|
||||
ADC_CR2(adc) = reg32;
|
||||
ADC_CR2(adc) |= ADC_CR2_JEXTTRIG;
|
||||
}
|
||||
|
||||
void adc_disable_external_trigger_injected(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) &= ~ADC_CR2_JEXTTRIG;
|
||||
}
|
||||
|
||||
void adc_set_left_aligned(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) |= ADC_CR2_ALIGN;
|
||||
}
|
||||
|
||||
void adc_set_right_aligned(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) &= ~ADC_CR2_ALIGN;
|
||||
}
|
||||
|
||||
void adc_enable_dma(u32 adc)
|
||||
{
|
||||
if ((adc == ADC1) | (adc==ADC3))
|
||||
ADC_CR2(adc) |= ADC_CR2_DMA;
|
||||
}
|
||||
|
||||
void adc_disable_dma(u32 adc)
|
||||
{
|
||||
if ((adc == ADC1) | (adc==ADC3))
|
||||
ADC_CR2(adc) &= ~ADC_CR2_DMA;
|
||||
}
|
||||
|
||||
void adc_reset_calibration(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) |= ADC_CR2_RSTCAL;
|
||||
while (ADC_CR2(adc) & ADC_CR2_RSTCAL);
|
||||
}
|
||||
|
||||
void adc_calibration(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) |= ADC_CR2_CAL;
|
||||
while (ADC_CR2(adc) & ADC_CR2_CAL);
|
||||
}
|
||||
|
||||
void adc_set_continous_conversion_mode(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) |= ADC_CR2_CONT;
|
||||
}
|
||||
|
||||
void adc_set_single_conversion_mode(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) &= ~ADC_CR2_CONT;
|
||||
}
|
||||
|
||||
void adc_on(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) |= ADC_CR2_ADON;
|
||||
}
|
||||
|
||||
void adc_off(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) &= ~ADC_CR2_ADON;
|
||||
}
|
||||
|
||||
void adc_set_conversion_time(u32 adc, u8 channel, u8 time)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
if (channel < 10) {
|
||||
reg32 = ADC_SMPR2(adc);
|
||||
reg32 &= ~(0b111 << (channel * 3));
|
||||
reg32 |= (time << (channel * 3));
|
||||
ADC_SMPR2(adc) = reg32;
|
||||
}
|
||||
else {
|
||||
reg32 = ADC_SMPR1(adc);
|
||||
reg32 &= ~(0b111 << ((channel-10) * 3));
|
||||
reg32 |= (time << ((channel-10) * 3));
|
||||
ADC_SMPR1(adc) = reg32;
|
||||
}
|
||||
}
|
||||
|
||||
void adc_set_conversion_time_on_all_channels(u32 adc, u8 time)
|
||||
{
|
||||
u32 reg32 = 0;
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i <= 9; i++) {
|
||||
reg32 |= (time << (i * 3));
|
||||
}
|
||||
ADC_SMPR2(adc) = reg32;
|
||||
|
||||
for (i = 10; i <= 17; i++) {
|
||||
reg32 |= (time << ((i-10) * 3));
|
||||
}
|
||||
ADC_SMPR1(adc) = reg32;
|
||||
}
|
||||
|
||||
void adc_set_watchdog_high_threshold(u32 adc, u16 threshold)
|
||||
{
|
||||
u32 reg32 = 0;
|
||||
|
||||
reg32 = (u32)threshold;
|
||||
reg32 &= ~0xfffff000; /* clear all bits above 11 */
|
||||
ADC_HTR(adc) = reg32;
|
||||
}
|
||||
|
||||
void adc_set_watchdog_low_threshold(u32 adc, u16 threshold)
|
||||
{
|
||||
u32 reg32 = 0;
|
||||
|
||||
reg32 = (u32)threshold;
|
||||
reg32 &= ~0xfffff000; /* clear all bits above 11 */
|
||||
ADC_LTR(adc) = reg32;
|
||||
}
|
||||
|
||||
void adc_set_regular_sequence(u32 adc, u8 length, u8 channel[])
|
||||
{
|
||||
u32 reg32_1 = 0;
|
||||
u32 reg32_2 = 0;
|
||||
u32 reg32_3 = 0;
|
||||
u8 i = 0;
|
||||
|
||||
/* maximum sequence length is 16 channels */
|
||||
if (length > 16)
|
||||
return;
|
||||
|
||||
for (i=1; i<=length; i++) {
|
||||
if (i <= 6)
|
||||
reg32_3 |= (channel[i-1] << ((i-1) * 5));
|
||||
if ((i > 6) & (i <= 12))
|
||||
reg32_2 |= (channel[i-1] << ((i-6-1) * 5));
|
||||
if ((i > 12) & (i <= 16))
|
||||
reg32_1 |= (channel[i-1] << ((i-12-1) * 5));
|
||||
}
|
||||
reg32_1 |= ((length -1) << ADC_SQR1_L_LSB);
|
||||
|
||||
ADC_SQR1(adc) = reg32_1;
|
||||
ADC_SQR2(adc) = reg32_2;
|
||||
ADC_SQR3(adc) = reg32_3;
|
||||
}
|
||||
|
||||
void adc_set_injected_sequence(u32 adc, u8 length, u8 channel[])
|
||||
{
|
||||
u32 reg32 = 0;
|
||||
u8 i = 0;
|
||||
|
||||
/* maximum sequence length is 4 channels */
|
||||
if (length > 4)
|
||||
return;
|
||||
|
||||
for (i = 1; i <= length; i++) {
|
||||
reg32 |= (channel[i-1] << ((i-1) * 5));
|
||||
}
|
||||
reg32 |= ((length-1) << ADC_JSQR_JL_LSB);
|
||||
|
||||
ADC_JSQR(adc) = reg32;
|
||||
}
|
||||
303
lib/stm32/f1/can.c
Normal file
303
lib/stm32/f1/can.c
Normal file
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/can.h>
|
||||
#include <libopencm3/stm32/f1/rcc.h>
|
||||
|
||||
void can_reset(u32 canport)
|
||||
{
|
||||
if (canport == CAN1) {
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CAN1RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CAN1RST);
|
||||
} else {
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CAN2RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CAN2RST);
|
||||
}
|
||||
}
|
||||
|
||||
int can_init(u32 canport, bool ttcm, bool abom, bool awum, bool nart,
|
||||
bool rflm, bool txfp, u32 sjw, u32 ts1, u32 ts2, u32 brp)
|
||||
{
|
||||
u32 wait_ack = 0x00000000;
|
||||
u32 can_msr_inak_timeout = 0x0000FFFF;
|
||||
int ret = 0;
|
||||
|
||||
/* Exit from sleep mode. */
|
||||
CAN_MCR(canport) &= ~CAN_MCR_SLEEP;
|
||||
|
||||
/* Request initialization "enter". */
|
||||
CAN_MCR(canport) |= CAN_MCR_INRQ;
|
||||
|
||||
/* Wait for acknowledge. */
|
||||
while ((wait_ack != can_msr_inak_timeout) &&
|
||||
((CAN_MSR(canport) & CAN_MSR_INAK) != CAN_MSR_INAK)) {
|
||||
wait_ack++;
|
||||
}
|
||||
|
||||
/* Check the acknowledge. */
|
||||
if ((CAN_MSR(canport) & CAN_MSR_INAK) != CAN_MSR_INAK)
|
||||
return 1;
|
||||
|
||||
/* Set the automatic bus-off management. */
|
||||
if (ttcm)
|
||||
CAN_MCR(canport) |= CAN_MCR_TTCM;
|
||||
else
|
||||
CAN_MCR(canport) &= ~CAN_MCR_TTCM;
|
||||
|
||||
if (abom)
|
||||
CAN_MCR(canport) |= CAN_MCR_ABOM;
|
||||
else
|
||||
CAN_MCR(canport) &= ~CAN_MCR_ABOM;
|
||||
|
||||
if (awum)
|
||||
CAN_MCR(canport) |= CAN_MCR_AWUM;
|
||||
else
|
||||
CAN_MCR(canport) &= ~CAN_MCR_AWUM;
|
||||
|
||||
if (nart)
|
||||
CAN_MCR(canport) |= CAN_MCR_NART;
|
||||
else
|
||||
CAN_MCR(canport) &= ~CAN_MCR_NART;
|
||||
|
||||
if (rflm)
|
||||
CAN_MCR(canport) |= CAN_MCR_RFLM;
|
||||
else
|
||||
CAN_MCR(canport) &= ~CAN_MCR_RFLM;
|
||||
|
||||
if (txfp)
|
||||
CAN_MCR(canport) |= CAN_MCR_TXFP;
|
||||
else
|
||||
CAN_MCR(canport) &= ~CAN_MCR_TXFP;
|
||||
|
||||
/* Set bit timings. */
|
||||
CAN_BTR(canport) = sjw | ts2 | ts1 |
|
||||
(u32)(CAN_BTR_BRP_MASK & (brp - 1));
|
||||
|
||||
/* Request initialization "leave". */
|
||||
CAN_MCR(canport) &= ~CAN_MCR_INRQ;
|
||||
|
||||
/* Wait for acknowledge. */
|
||||
wait_ack = 0x00000000;
|
||||
while ((wait_ack != can_msr_inak_timeout) &&
|
||||
((CAN_MSR(canport) & CAN_MSR_INAK) == CAN_MSR_INAK)) {
|
||||
wait_ack++;
|
||||
}
|
||||
|
||||
if ((CAN_MSR(canport) & CAN_MSR_INAK) == CAN_MSR_INAK)
|
||||
ret = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void can_filter_init(u32 canport, u32 nr, bool scale_32bit, bool id_list_mode,
|
||||
u32 fr1, u32 fr2, u32 fifo, bool enable)
|
||||
{
|
||||
u32 filter_select_bit = 0x00000001 << nr;
|
||||
|
||||
/* Request initialization "enter". */
|
||||
CAN_FMR(canport) |= CAN_FMR_FINIT;
|
||||
|
||||
/* Deactivate the filter. */
|
||||
CAN_FA1R(canport) &= ~filter_select_bit;
|
||||
|
||||
if (scale_32bit) {
|
||||
/* Set 32-bit scale for the filter. */
|
||||
CAN_FS1R(canport) |= filter_select_bit;
|
||||
} else {
|
||||
/* Set 16-bit scale for the filter. */
|
||||
CAN_FS1R(canport) &= ~filter_select_bit;
|
||||
}
|
||||
|
||||
if (id_list_mode) {
|
||||
/* Set filter mode to ID list mode. */
|
||||
CAN_FM1R(canport) |= filter_select_bit;
|
||||
} else {
|
||||
/* Set filter mode to id/mask mode. */
|
||||
CAN_FM1R(canport) &= ~filter_select_bit;
|
||||
}
|
||||
|
||||
/* Set the first filter register. */
|
||||
CAN_FiR1(canport, nr) = fr1;
|
||||
|
||||
/* Set the second filter register. */
|
||||
CAN_FiR2(canport, nr) = fr2;
|
||||
|
||||
/* Select FIFO0 or FIFO1 as filter assignement. */
|
||||
if (fifo)
|
||||
CAN_FFA1R(canport) |= filter_select_bit; /* FIFO1 */
|
||||
else
|
||||
CAN_FFA1R(canport) &= ~filter_select_bit; /* FIFO0 */
|
||||
|
||||
if (enable)
|
||||
CAN_FA1R(canport) |= filter_select_bit; /* Activate filter. */
|
||||
|
||||
/* Request initialization "leave". */
|
||||
CAN_FMR(canport) &= ~CAN_FMR_FINIT;
|
||||
}
|
||||
|
||||
void can_filter_id_mask_16bit_init(u32 canport, u32 nr, u16 id1, u16 mask1,
|
||||
u16 id2, u16 mask2, u32 fifo, bool enable)
|
||||
{
|
||||
can_filter_init(canport, nr, false, false,
|
||||
((u32)id1 << 16) | (u32)mask1,
|
||||
((u32)id2 << 16) | (u32)mask2, fifo, enable);
|
||||
}
|
||||
|
||||
void can_filter_id_mask_32bit_init(u32 canport, u32 nr, u32 id, u32 mask,
|
||||
u32 fifo, bool enable)
|
||||
{
|
||||
can_filter_init(canport, nr, true, false, id, mask, fifo, enable);
|
||||
}
|
||||
|
||||
void can_filter_id_list_16bit_init(u32 canport, u32 nr, u16 id1, u16 id2,
|
||||
u16 id3, u16 id4, u32 fifo, bool enable)
|
||||
{
|
||||
can_filter_init(canport, nr, false, true,
|
||||
((u32)id1 << 16) | (u32)id2,
|
||||
((u32)id3 << 16) | (u32)id4, fifo, enable);
|
||||
}
|
||||
|
||||
void can_filter_id_list_32bit_init(u32 canport, u32 nr, u32 id1, u32 id2,
|
||||
u32 fifo, bool enable)
|
||||
{
|
||||
can_filter_init(canport, nr, true, true, id1, id2, fifo, enable);
|
||||
}
|
||||
|
||||
void can_enable_irq(u32 canport, u32 irq)
|
||||
{
|
||||
CAN_IER(canport) |= irq;
|
||||
}
|
||||
|
||||
void can_disable_irq(u32 canport, u32 irq)
|
||||
{
|
||||
CAN_IER(canport) &= ~irq;
|
||||
}
|
||||
|
||||
int can_transmit(u32 canport, u32 id, bool ext, bool rtr, u8 length, u8 *data)
|
||||
{
|
||||
int ret = 0, i;
|
||||
u32 mailbox = 0;
|
||||
|
||||
if ((CAN_TSR(canport) & CAN_TSR_TME0) == CAN_TSR_TME0) {
|
||||
ret = 0;
|
||||
mailbox = CAN_MBOX0;
|
||||
} else if ((CAN_TSR(canport) & CAN_TSR_TME1) == CAN_TSR_TME1) {
|
||||
ret = 1;
|
||||
mailbox = CAN_MBOX1;
|
||||
} else if ((CAN_TSR(canport) & CAN_TSR_TME2) == CAN_TSR_TME2) {
|
||||
ret = 2;
|
||||
mailbox = CAN_MBOX2;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Check if we have an empty mailbox. */
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
/* Clear stale register bits */
|
||||
CAN_TIxR(canport, mailbox) = 0;
|
||||
if (ext) {
|
||||
/* Set extended ID. */
|
||||
CAN_TIxR(canport, mailbox) |= id << CAN_TIxR_EXID_SHIFT;
|
||||
/* Set extended ID indicator bit. */
|
||||
CAN_TIxR(canport, mailbox) |= CAN_TIxR_IDE;
|
||||
} else {
|
||||
/* Set standard ID. */
|
||||
CAN_TIxR(canport, mailbox) |= id << CAN_TIxR_STID_SHIFT;
|
||||
}
|
||||
|
||||
/* Set/clear remote transmission request bit. */
|
||||
if (rtr)
|
||||
CAN_TIxR(canport, mailbox) |= CAN_TIxR_RTR; /* Set */
|
||||
|
||||
/* Set the DLC. */
|
||||
CAN_TDTxR(canport, mailbox) &= 0xFFFFFFFF0;
|
||||
CAN_TDTxR(canport, mailbox) |= length & CAN_TDTxR_DLC_MASK;
|
||||
|
||||
/* Set the data. */
|
||||
CAN_TDLxR(canport, mailbox) = 0;
|
||||
CAN_TDHxR(canport, mailbox) = 0;
|
||||
for (i = 0; (i < 4) && (i < length); i++)
|
||||
CAN_TDLxR(canport, mailbox) |= (u32)data[i] << (8 * i);
|
||||
for (i = 4; (i < 8) && (i < length); i++)
|
||||
CAN_TDHxR(canport, mailbox) |= (u32)data[i] << (8 * (i - 4));
|
||||
|
||||
/* Request transmission. */
|
||||
CAN_TIxR(canport, mailbox) |= CAN_TIxR_TXRQ;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void can_fifo_release(u32 canport, u8 fifo)
|
||||
{
|
||||
if (fifo == 0)
|
||||
CAN_RF0R(canport) |= CAN_RF1R_RFOM1;
|
||||
else
|
||||
CAN_RF1R(canport) |= CAN_RF1R_RFOM1;
|
||||
}
|
||||
|
||||
void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
|
||||
bool *rtr, u32 *fmi, u8 *length, u8 *data)
|
||||
{
|
||||
u32 fifo_id = 0;
|
||||
int i;
|
||||
|
||||
if (fifo == 0)
|
||||
fifo_id = CAN_FIFO0;
|
||||
else
|
||||
fifo_id = CAN_FIFO1;
|
||||
|
||||
/* Get type of CAN ID and CAN ID. */
|
||||
if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_IDE) {
|
||||
*ext = true;
|
||||
/* Get extended CAN ID. */
|
||||
*id = ((CAN_RIxR(canport, fifo_id) & CAN_RIxR_EXID_MASK) >>
|
||||
CAN_RIxR_EXID_SHIFT);
|
||||
} else {
|
||||
*ext = false;
|
||||
/* Get standard CAN ID. */
|
||||
*id = ((CAN_RIxR(canport, fifo_id) & CAN_RIxR_STID_MASK) >>
|
||||
CAN_RIxR_STID_SHIFT);
|
||||
}
|
||||
|
||||
/* Get request transmit flag. */
|
||||
if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_RTR)
|
||||
*rtr = true;
|
||||
else
|
||||
*rtr = false;
|
||||
|
||||
/* Get filter match ID. */
|
||||
*fmi = ((CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_FMI_MASK) >
|
||||
CAN_RDTxR_FMI_SHIFT);
|
||||
|
||||
/* Get data length. */
|
||||
*length = CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_DLC_MASK;
|
||||
|
||||
/* Get data. */
|
||||
for (i = 0; (i < 4) && (i < *length); i++)
|
||||
data[i] = (CAN_RDLxR(canport, fifo_id) >> (8 * i)) & 0xFF;
|
||||
|
||||
for (i = 4; (i < 8) && (i < *length); i++)
|
||||
data[i] = (CAN_RDHxR(canport, fifo_id) >> (8 * (i - 4))) & 0xFF;
|
||||
|
||||
/* Release the FIFO. */
|
||||
if (release)
|
||||
can_fifo_release(CAN1, 0);
|
||||
}
|
||||
543
lib/stm32/f1/dma.c
Normal file
543
lib/stm32/f1/dma.c
Normal file
@@ -0,0 +1,543 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/f1/dma.h>
|
||||
|
||||
void dma_enable_mem2mem_mode(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) |= DMA_CCR1_MEM2MEM;
|
||||
DMA_CCR1(dma) &= ~DMA_CCR1_CIRC;
|
||||
case 2:
|
||||
DMA_CCR2(dma) |= DMA_CCR2_MEM2MEM;
|
||||
DMA_CCR2(dma) &= ~DMA_CCR2_CIRC;
|
||||
case 3:
|
||||
DMA_CCR3(dma) |= DMA_CCR3_MEM2MEM;
|
||||
DMA_CCR3(dma) &= ~DMA_CCR3_CIRC;
|
||||
case 4:
|
||||
DMA_CCR4(dma) |= DMA_CCR4_MEM2MEM;
|
||||
DMA_CCR4(dma) &= ~DMA_CCR4_CIRC;
|
||||
case 5:
|
||||
DMA_CCR5(dma) |= DMA_CCR5_MEM2MEM;
|
||||
DMA_CCR5(dma) &= ~DMA_CCR5_CIRC;
|
||||
case 6:
|
||||
if (dma == DMA1) {
|
||||
DMA_CCR6(dma) |= DMA_CCR6_MEM2MEM;
|
||||
DMA_CCR6(dma) &= ~DMA_CCR6_CIRC;
|
||||
}
|
||||
case 7:
|
||||
if (dma == DMA1) {
|
||||
DMA_CCR7(dma) |= DMA_CCR7_MEM2MEM;
|
||||
DMA_CCR7(dma) &= ~DMA_CCR7_CIRC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void dma_set_priority(u32 dma, u8 channel, u8 prio)
|
||||
{
|
||||
/* parameter check */
|
||||
if (prio > 3)
|
||||
return;
|
||||
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) &= ~(0x3 << DMA_CCR1_PL_LSB);
|
||||
DMA_CCR1(dma) |= (prio << DMA_CCR1_PL_LSB);
|
||||
case 2:
|
||||
DMA_CCR2(dma) &= ~(0x3 << DMA_CCR2_PL_LSB);
|
||||
DMA_CCR2(dma) |= (prio << DMA_CCR2_PL_LSB);
|
||||
case 3:
|
||||
DMA_CCR3(dma) &= ~(0x3 << DMA_CCR3_PL_LSB);
|
||||
DMA_CCR3(dma) |= (prio << DMA_CCR3_PL_LSB);
|
||||
case 4:
|
||||
DMA_CCR4(dma) &= ~(0x3 << DMA_CCR4_PL_LSB);
|
||||
DMA_CCR4(dma) |= (prio << DMA_CCR4_PL_LSB);
|
||||
case 5:
|
||||
DMA_CCR5(dma) &= ~(0x3 << DMA_CCR5_PL_LSB);
|
||||
DMA_CCR5(dma) |= (prio << DMA_CCR5_PL_LSB);
|
||||
case 6:
|
||||
if (dma == DMA1) {
|
||||
DMA_CCR6(dma) &= ~(0x3 << DMA_CCR6_PL_LSB);
|
||||
DMA_CCR6(dma) |= (prio << DMA_CCR6_PL_LSB);
|
||||
}
|
||||
case 7:
|
||||
if (dma == DMA1) {
|
||||
DMA_CCR7(dma) &= ~(0x3 << DMA_CCR7_PL_LSB);
|
||||
DMA_CCR7(dma) |= (prio << DMA_CCR7_PL_LSB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dma_set_memory_size(u32 dma, u8 channel, u8 mem_size)
|
||||
{
|
||||
/* parameter check */
|
||||
if (mem_size > 2)
|
||||
return;
|
||||
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) &= ~(0x3 << DMA_CCR1_MSIZE_LSB);
|
||||
DMA_CCR1(dma) |= (mem_size << DMA_CCR1_MSIZE_LSB);
|
||||
case 2:
|
||||
DMA_CCR2(dma) &= ~(0x3 << DMA_CCR2_MSIZE_LSB);
|
||||
DMA_CCR2(dma) |= (mem_size << DMA_CCR2_MSIZE_LSB);
|
||||
case 3:
|
||||
DMA_CCR3(dma) &= ~(0x3 << DMA_CCR3_MSIZE_LSB);
|
||||
DMA_CCR3(dma) |= (mem_size << DMA_CCR3_MSIZE_LSB);
|
||||
case 4:
|
||||
DMA_CCR4(dma) &= ~(0x3 << DMA_CCR4_MSIZE_LSB);
|
||||
DMA_CCR4(dma) |= (mem_size << DMA_CCR4_MSIZE_LSB);
|
||||
case 5:
|
||||
DMA_CCR5(dma) &= ~(0x3 << DMA_CCR5_MSIZE_LSB);
|
||||
DMA_CCR5(dma) |= (mem_size << DMA_CCR5_MSIZE_LSB);
|
||||
case 6:
|
||||
if (dma == DMA1) {
|
||||
DMA_CCR6(dma) &= ~(0x3 << DMA_CCR6_MSIZE_LSB);
|
||||
DMA_CCR6(dma) |= (mem_size << DMA_CCR6_MSIZE_LSB);
|
||||
}
|
||||
case 7:
|
||||
if (dma == DMA1) {
|
||||
DMA_CCR7(dma) &= ~(0x3 << DMA_CCR7_MSIZE_LSB);
|
||||
DMA_CCR7(dma) |= (mem_size << DMA_CCR7_MSIZE_LSB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dma_set_peripheral_size(u32 dma, u8 channel, u8 peripheral_size)
|
||||
{
|
||||
/* parameter check */
|
||||
if (peripheral_size > 2)
|
||||
return;
|
||||
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) &= ~(0x3 << DMA_CCR1_PSIZE_LSB);
|
||||
DMA_CCR1(dma) |= (peripheral_size << DMA_CCR1_PSIZE_LSB);
|
||||
case 2:
|
||||
DMA_CCR2(dma) &= ~(0x3 << DMA_CCR2_PSIZE_LSB);
|
||||
DMA_CCR2(dma) |= (peripheral_size << DMA_CCR2_PSIZE_LSB);
|
||||
case 3:
|
||||
DMA_CCR3(dma) &= ~(0x3 << DMA_CCR3_PSIZE_LSB);
|
||||
DMA_CCR3(dma) |= (peripheral_size << DMA_CCR3_PSIZE_LSB);
|
||||
case 4:
|
||||
DMA_CCR4(dma) &= ~(0x3 << DMA_CCR4_PSIZE_LSB);
|
||||
DMA_CCR4(dma) |= (peripheral_size << DMA_CCR4_PSIZE_LSB);
|
||||
case 5:
|
||||
DMA_CCR5(dma) &= ~(0x3 << DMA_CCR5_PSIZE_LSB);
|
||||
DMA_CCR5(dma) |= (peripheral_size << DMA_CCR5_PSIZE_LSB);
|
||||
case 6:
|
||||
if (dma == DMA1) {
|
||||
DMA_CCR6(dma) &= ~(0x3 << DMA_CCR6_PSIZE_LSB);
|
||||
DMA_CCR6(dma) |= (peripheral_size << DMA_CCR6_PSIZE_LSB);
|
||||
}
|
||||
case 7:
|
||||
if (dma == DMA1) {
|
||||
DMA_CCR7(dma) &= ~(0x3 << DMA_CCR7_PSIZE_LSB);
|
||||
DMA_CCR7(dma) |= (peripheral_size << DMA_CCR7_PSIZE_LSB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dma_enable_memory_increment_mode(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) |= DMA_CCR1_MINC;
|
||||
case 2:
|
||||
DMA_CCR2(dma) |= DMA_CCR2_MINC;
|
||||
case 3:
|
||||
DMA_CCR3(dma) |= DMA_CCR3_MINC;
|
||||
case 4:
|
||||
DMA_CCR4(dma) |= DMA_CCR4_MINC;
|
||||
case 5:
|
||||
DMA_CCR5(dma) |= DMA_CCR5_MINC;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR6(dma) |= DMA_CCR6_MINC;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR7(dma) |= DMA_CCR7_MINC;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_enable_peripheral_increment_mode(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) |= DMA_CCR1_PINC;
|
||||
case 2:
|
||||
DMA_CCR2(dma) |= DMA_CCR2_PINC;
|
||||
case 3:
|
||||
DMA_CCR3(dma) |= DMA_CCR3_PINC;
|
||||
case 4:
|
||||
DMA_CCR4(dma) |= DMA_CCR4_PINC;
|
||||
case 5:
|
||||
DMA_CCR5(dma) |= DMA_CCR5_PINC;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR6(dma) |= DMA_CCR6_PINC;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR7(dma) |= DMA_CCR7_PINC;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_enable_circular_mode(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) |= DMA_CCR1_CIRC;
|
||||
DMA_CCR1(dma) &= ~DMA_CCR1_MEM2MEM;
|
||||
case 2:
|
||||
DMA_CCR2(dma) |= DMA_CCR2_CIRC;
|
||||
DMA_CCR2(dma) &= ~DMA_CCR2_MEM2MEM;
|
||||
case 3:
|
||||
DMA_CCR3(dma) |= DMA_CCR3_CIRC;
|
||||
DMA_CCR3(dma) &= ~DMA_CCR3_MEM2MEM;
|
||||
case 4:
|
||||
DMA_CCR4(dma) |= DMA_CCR4_CIRC;
|
||||
DMA_CCR4(dma) &= ~DMA_CCR4_MEM2MEM;
|
||||
case 5:
|
||||
DMA_CCR5(dma) |= DMA_CCR5_CIRC;
|
||||
DMA_CCR5(dma) &= ~DMA_CCR5_MEM2MEM;
|
||||
case 6:
|
||||
if (dma == DMA1) {
|
||||
DMA_CCR6(dma) |= DMA_CCR6_CIRC;
|
||||
DMA_CCR6(dma) &= ~DMA_CCR6_MEM2MEM;
|
||||
}
|
||||
case 7:
|
||||
if (dma == DMA1) {
|
||||
DMA_CCR7(dma) |= DMA_CCR7_CIRC;
|
||||
DMA_CCR7(dma) &= ~DMA_CCR7_MEM2MEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dma_set_read_from_peripheral(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) &= ~DMA_CCR1_DIR;
|
||||
case 2:
|
||||
DMA_CCR2(dma) &= ~DMA_CCR2_DIR;
|
||||
case 3:
|
||||
DMA_CCR3(dma) &= ~DMA_CCR3_DIR;
|
||||
case 4:
|
||||
DMA_CCR4(dma) &= ~DMA_CCR4_DIR;
|
||||
case 5:
|
||||
DMA_CCR5(dma) &= ~DMA_CCR5_DIR;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR6(dma) &= ~DMA_CCR6_DIR;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR7(dma) &= ~DMA_CCR7_DIR;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_set_read_from_memory(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) |= DMA_CCR1_DIR;
|
||||
case 2:
|
||||
DMA_CCR2(dma) |= DMA_CCR2_DIR;
|
||||
case 3:
|
||||
DMA_CCR3(dma) |= DMA_CCR3_DIR;
|
||||
case 4:
|
||||
DMA_CCR4(dma) |= DMA_CCR4_DIR;
|
||||
case 5:
|
||||
DMA_CCR5(dma) |= DMA_CCR5_DIR;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR6(dma) |= DMA_CCR6_DIR;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR7(dma) |= DMA_CCR7_DIR;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_enable_transfer_error_interrupt(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) |= DMA_CCR1_TEIE;
|
||||
case 2:
|
||||
DMA_CCR2(dma) |= DMA_CCR2_TEIE;
|
||||
case 3:
|
||||
DMA_CCR3(dma) |= DMA_CCR3_TEIE;
|
||||
case 4:
|
||||
DMA_CCR4(dma) |= DMA_CCR4_TEIE;
|
||||
case 5:
|
||||
DMA_CCR5(dma) |= DMA_CCR5_TEIE;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR6(dma) |= DMA_CCR6_TEIE;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR7(dma) |= DMA_CCR7_TEIE;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_disable_transfer_error_interrupt(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) &= ~DMA_CCR1_TEIE;
|
||||
case 2:
|
||||
DMA_CCR2(dma) &= ~DMA_CCR2_TEIE;
|
||||
case 3:
|
||||
DMA_CCR3(dma) &= ~DMA_CCR3_TEIE;
|
||||
case 4:
|
||||
DMA_CCR4(dma) &= ~DMA_CCR4_TEIE;
|
||||
case 5:
|
||||
DMA_CCR5(dma) &= ~DMA_CCR5_TEIE;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR6(dma) &= ~DMA_CCR6_TEIE;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR7(dma) &= ~DMA_CCR7_TEIE;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_enable_half_transfer_interrupt(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) |= DMA_CCR1_HTIE;
|
||||
case 2:
|
||||
DMA_CCR2(dma) |= DMA_CCR2_HTIE;
|
||||
case 3:
|
||||
DMA_CCR3(dma) |= DMA_CCR3_HTIE;
|
||||
case 4:
|
||||
DMA_CCR4(dma) |= DMA_CCR4_HTIE;
|
||||
case 5:
|
||||
DMA_CCR5(dma) |= DMA_CCR5_HTIE;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR6(dma) |= DMA_CCR6_HTIE;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR7(dma) |= DMA_CCR7_HTIE;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_disable_half_transfer_interrupt(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) &= ~DMA_CCR1_HTIE;
|
||||
case 2:
|
||||
DMA_CCR2(dma) &= ~DMA_CCR2_HTIE;
|
||||
case 3:
|
||||
DMA_CCR3(dma) &= ~DMA_CCR3_HTIE;
|
||||
case 4:
|
||||
DMA_CCR4(dma) &= ~DMA_CCR4_HTIE;
|
||||
case 5:
|
||||
DMA_CCR5(dma) &= ~DMA_CCR5_HTIE;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR6(dma) &= ~DMA_CCR6_HTIE;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR7(dma) &= ~DMA_CCR7_HTIE;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_enable_transfer_complete_interrupt(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) |= DMA_CCR1_TCIE;
|
||||
case 2:
|
||||
DMA_CCR2(dma) |= DMA_CCR2_TCIE;
|
||||
case 3:
|
||||
DMA_CCR3(dma) |= DMA_CCR3_TCIE;
|
||||
case 4:
|
||||
DMA_CCR4(dma) |= DMA_CCR4_TCIE;
|
||||
case 5:
|
||||
DMA_CCR5(dma) |= DMA_CCR5_TCIE;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR6(dma) |= DMA_CCR6_TCIE;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR7(dma) |= DMA_CCR7_TCIE;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_disable_transfer_complete_interrupt(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) &= ~DMA_CCR1_TCIE;
|
||||
case 2:
|
||||
DMA_CCR2(dma) &= ~DMA_CCR2_TCIE;
|
||||
case 3:
|
||||
DMA_CCR3(dma) &= ~DMA_CCR3_TCIE;
|
||||
case 4:
|
||||
DMA_CCR4(dma) &= ~DMA_CCR4_TCIE;
|
||||
case 5:
|
||||
DMA_CCR5(dma) &= ~DMA_CCR5_TCIE;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR6(dma) &= ~DMA_CCR6_TCIE;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR7(dma) &= ~DMA_CCR7_TCIE;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_enable_channel(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) |= DMA_CCR1_EN;
|
||||
case 2:
|
||||
DMA_CCR2(dma) |= DMA_CCR2_EN;
|
||||
case 3:
|
||||
DMA_CCR3(dma) |= DMA_CCR3_EN;
|
||||
case 4:
|
||||
DMA_CCR4(dma) |= DMA_CCR4_EN;
|
||||
case 5:
|
||||
DMA_CCR5(dma) |= DMA_CCR5_EN;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR6(dma) |= DMA_CCR6_EN;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR7(dma) |= DMA_CCR7_EN;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_disable_channel(u32 dma, u8 channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CCR1(dma) &= ~DMA_CCR1_EN;
|
||||
case 2:
|
||||
DMA_CCR2(dma) &= ~DMA_CCR2_EN;
|
||||
case 3:
|
||||
DMA_CCR3(dma) &= ~DMA_CCR3_EN;
|
||||
case 4:
|
||||
DMA_CCR4(dma) &= ~DMA_CCR4_EN;
|
||||
case 5:
|
||||
DMA_CCR5(dma) &= ~DMA_CCR5_EN;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR6(dma) &= ~DMA_CCR6_EN;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CCR7(dma) &= ~DMA_CCR7_EN;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_set_peripheral_address(u32 dma, u8 channel, u32 address)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CPAR1(dma) = (u32)address;
|
||||
case 2:
|
||||
DMA_CPAR2(dma) = (u32)address;
|
||||
case 3:
|
||||
DMA_CPAR3(dma) = (u32)address;
|
||||
case 4:
|
||||
DMA_CPAR4(dma) = (u32)address;
|
||||
case 5:
|
||||
DMA_CPAR5(dma) = (u32)address;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CPAR6(dma) = (u32)address;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CPAR7(dma) = (u32)address;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_set_memory_address(u32 dma, u8 channel, u32 address)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CMAR1(dma) = (u32)address;
|
||||
case 2:
|
||||
DMA_CMAR2(dma) = (u32)address;
|
||||
case 3:
|
||||
DMA_CMAR3(dma) = (u32)address;
|
||||
case 4:
|
||||
DMA_CMAR4(dma) = (u32)address;
|
||||
case 5:
|
||||
DMA_CMAR5(dma) = (u32)address;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CMAR6(dma) = (u32)address;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CMAR7(dma) = (u32)address;
|
||||
}
|
||||
}
|
||||
|
||||
void dma_set_number_of_data(u32 dma, u8 channel, u16 number)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1:
|
||||
DMA_CNDTR1(dma) = number;
|
||||
case 2:
|
||||
DMA_CNDTR2(dma) = number;
|
||||
case 3:
|
||||
DMA_CNDTR3(dma) = number;
|
||||
case 4:
|
||||
DMA_CNDTR4(dma) = number;
|
||||
case 5:
|
||||
DMA_CNDTR5(dma) = number;
|
||||
case 6:
|
||||
if (dma == DMA1)
|
||||
DMA_CNDTR6(dma) = number;
|
||||
case 7:
|
||||
if (dma == DMA1)
|
||||
DMA_CNDTR7(dma) = number;
|
||||
}
|
||||
}
|
||||
53
lib/stm32/f1/ethernet.c
Normal file
53
lib/stm32/f1/ethernet.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/f1/ethernet.h>
|
||||
|
||||
void eth_smi_write(u8 phy, u8 reg, u16 data)
|
||||
{
|
||||
/* Set PHY and register addresses for write access. */
|
||||
ETH_MACMIIAR &= ~(ETH_MACMIIAR_MR | ETH_MACMIIAR_PA);
|
||||
ETH_MACMIIAR |= (phy << 11) | (reg << 6) | ETH_MACMIIAR_MW;
|
||||
|
||||
/* Set register value. */
|
||||
ETH_MACMIIDR = data;
|
||||
|
||||
/* Begin transaction. */
|
||||
ETH_MACMIIAR |= ETH_MACMIIAR_MB;
|
||||
|
||||
/* Wait for not busy. */
|
||||
while (ETH_MACMIIAR & ETH_MACMIIAR_MB);
|
||||
}
|
||||
|
||||
u16 eth_smi_read(u8 phy, u8 reg)
|
||||
{
|
||||
/* Set PHY and register addresses for write access. */
|
||||
ETH_MACMIIAR &= ~(ETH_MACMIIAR_MR | ETH_MACMIIAR_PA |
|
||||
ETH_MACMIIAR_MW);
|
||||
ETH_MACMIIAR |= (phy << 11) | (reg << 6);
|
||||
|
||||
/* Begin transaction. */
|
||||
ETH_MACMIIAR |= ETH_MACMIIAR_MB;
|
||||
|
||||
/* Wait for not busy. */
|
||||
while (ETH_MACMIIAR & ETH_MACMIIAR_MB);
|
||||
|
||||
/* Set register value. */
|
||||
return (u16)(ETH_MACMIIDR);
|
||||
}
|
||||
145
lib/stm32/f1/exti.c
Normal file
145
lib/stm32/f1/exti.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/exti.h>
|
||||
#include <libopencm3/stm32/f1/gpio.h>
|
||||
|
||||
void exti_set_trigger(u32 extis, exti_trigger_type trig)
|
||||
{
|
||||
switch (trig) {
|
||||
case EXTI_TRIGGER_RISING:
|
||||
EXTI_RTSR |= extis;
|
||||
EXTI_FTSR &= ~extis;
|
||||
break;
|
||||
case EXTI_TRIGGER_FALLING:
|
||||
EXTI_RTSR &= ~extis;
|
||||
EXTI_FTSR |= extis;
|
||||
break;
|
||||
case EXTI_TRIGGER_BOTH:
|
||||
EXTI_RTSR |= extis;
|
||||
EXTI_FTSR |= extis;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void exti_enable_request(u32 extis)
|
||||
{
|
||||
/* Enable interrupts. */
|
||||
EXTI_IMR |= extis;
|
||||
|
||||
/* Enable events. */
|
||||
EXTI_EMR |= extis;
|
||||
}
|
||||
|
||||
void exti_disable_request(u32 extis)
|
||||
{
|
||||
/* Disable interrupts. */
|
||||
EXTI_IMR &= ~extis;
|
||||
|
||||
/* Disable events. */
|
||||
EXTI_EMR &= ~extis;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the interrupt request by writing a 1 to the corresponding
|
||||
* pending bit register.
|
||||
*/
|
||||
void exti_reset_request(u32 extis)
|
||||
{
|
||||
EXTI_PR |= extis;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remap an external interrupt line to the corresponding pin on the
|
||||
* specified GPIO port.
|
||||
*
|
||||
* TODO: This could be rewritten in fewer lines of code.
|
||||
*/
|
||||
void exti_select_source(u32 exti, u32 gpioport)
|
||||
{
|
||||
u8 shift, bits;
|
||||
|
||||
shift = bits = 0;
|
||||
|
||||
switch (exti) {
|
||||
case EXTI0:
|
||||
case EXTI4:
|
||||
case EXTI8:
|
||||
case EXTI12:
|
||||
shift = 0;
|
||||
break;
|
||||
case EXTI1:
|
||||
case EXTI5:
|
||||
case EXTI9:
|
||||
case EXTI13:
|
||||
shift = 4;
|
||||
break;
|
||||
case EXTI2:
|
||||
case EXTI6:
|
||||
case EXTI10:
|
||||
case EXTI14:
|
||||
shift = 8;
|
||||
break;
|
||||
case EXTI3:
|
||||
case EXTI7:
|
||||
case EXTI11:
|
||||
case EXTI15:
|
||||
shift = 12;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (gpioport) {
|
||||
case GPIOA:
|
||||
bits = 0xf;
|
||||
break;
|
||||
case GPIOB:
|
||||
bits = 0xe;
|
||||
break;
|
||||
case GPIOC:
|
||||
bits = 0xd;
|
||||
break;
|
||||
case GPIOD:
|
||||
bits = 0xc;
|
||||
break;
|
||||
case GPIOE:
|
||||
bits = 0xb;
|
||||
break;
|
||||
case GPIOF:
|
||||
bits = 0xa;
|
||||
break;
|
||||
case GPIOG:
|
||||
bits = 0x9;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Ensure that only valid EXTI lines are used. */
|
||||
if (exti < EXTI4) {
|
||||
AFIO_EXTICR1 &= ~(0x000F << shift);
|
||||
AFIO_EXTICR1 |= (~bits << shift);
|
||||
} else if (exti < EXTI8) {
|
||||
AFIO_EXTICR2 &= ~(0x000F << shift);
|
||||
AFIO_EXTICR2 |= (~bits << shift);
|
||||
} else if (exti < EXTI12) {
|
||||
AFIO_EXTICR3 &= ~(0x000F << shift);
|
||||
AFIO_EXTICR3 |= (~bits << shift);
|
||||
} else if (exti < EXTI16) {
|
||||
AFIO_EXTICR4 &= ~(0x000F << shift);
|
||||
AFIO_EXTICR4 |= (~bits << shift);
|
||||
}
|
||||
}
|
||||
189
lib/stm32/f1/flash.c
Normal file
189
lib/stm32/f1/flash.c
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
|
||||
* Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/f1/flash.h>
|
||||
|
||||
void flash_prefetch_buffer_enable(void)
|
||||
{
|
||||
FLASH_ACR |= FLASH_PRFTBE;
|
||||
}
|
||||
|
||||
void flash_prefetch_buffer_disable(void)
|
||||
{
|
||||
FLASH_ACR &= ~FLASH_PRFTBE;
|
||||
}
|
||||
|
||||
void flash_halfcycle_enable(void)
|
||||
{
|
||||
FLASH_ACR |= FLASH_HLFCYA;
|
||||
}
|
||||
|
||||
void flash_halfcycle_disable(void)
|
||||
{
|
||||
FLASH_ACR &= ~FLASH_HLFCYA;
|
||||
}
|
||||
|
||||
void flash_set_ws(u32 ws)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = FLASH_ACR;
|
||||
reg32 &= ~((1 << 0) | (1 << 1) | (1 << 2));
|
||||
reg32 |= ws;
|
||||
FLASH_ACR = reg32;
|
||||
}
|
||||
|
||||
void flash_unlock(void)
|
||||
{
|
||||
/* Authorize the FPEC access. */
|
||||
FLASH_KEYR = FLASH_KEY1;
|
||||
FLASH_KEYR = FLASH_KEY2;
|
||||
}
|
||||
|
||||
void flash_lock(void)
|
||||
{
|
||||
FLASH_CR |= FLASH_LOCK;
|
||||
}
|
||||
|
||||
void flash_clear_pgerr_flag(void)
|
||||
{
|
||||
FLASH_SR |= FLASH_PGERR;
|
||||
}
|
||||
|
||||
void flash_clear_eop_flag(void)
|
||||
{
|
||||
FLASH_SR |= FLASH_EOP;
|
||||
}
|
||||
|
||||
void flash_clear_wrprterr_flag(void)
|
||||
{
|
||||
FLASH_SR |= FLASH_WRPRTERR;
|
||||
}
|
||||
|
||||
void flash_clear_bsy_flag(void)
|
||||
{
|
||||
FLASH_SR &= ~FLASH_BSY;
|
||||
}
|
||||
|
||||
void flash_clear_status_flags(void)
|
||||
{
|
||||
flash_clear_pgerr_flag();
|
||||
flash_clear_eop_flag();
|
||||
flash_clear_wrprterr_flag();
|
||||
flash_clear_bsy_flag();
|
||||
}
|
||||
|
||||
void flash_unlock_option_bytes(void)
|
||||
{
|
||||
FLASH_OPTKEYR = FLASH_KEY1;
|
||||
FLASH_OPTKEYR = FLASH_KEY2;
|
||||
}
|
||||
|
||||
void flash_wait_for_last_operation(void)
|
||||
{
|
||||
while ((FLASH_SR & FLASH_BSY) == FLASH_BSY)
|
||||
;
|
||||
}
|
||||
|
||||
void flash_program_word(u32 address, u32 data)
|
||||
{
|
||||
/* Ensure that all flash operations are complete. */
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
/* Enable writes to flash. */
|
||||
FLASH_CR |= FLASH_PG;
|
||||
|
||||
/* Program the first half of the word. */
|
||||
(*(volatile u16 *)address) = (u16)data;
|
||||
|
||||
/* Wait for the write to complete. */
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
/* Program the second half of the word. */
|
||||
(*(volatile u16 *)(address + 2)) = data >> 16;
|
||||
|
||||
/* Wait for the write to complete. */
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
/* Disable writes to flash. */
|
||||
FLASH_CR &= ~FLASH_PG;
|
||||
}
|
||||
|
||||
void flash_program_half_word(u32 address, u16 data)
|
||||
{
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
FLASH_CR |= FLASH_PG;
|
||||
|
||||
(*(volatile u16 *)address) = data;
|
||||
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
FLASH_CR &= ~FLASH_PG; /* Disable the PG bit. */
|
||||
}
|
||||
|
||||
void flash_erase_page(u32 page_address)
|
||||
{
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
FLASH_CR |= FLASH_PER;
|
||||
FLASH_AR = page_address;
|
||||
FLASH_CR |= FLASH_STRT;
|
||||
|
||||
flash_wait_for_last_operation();
|
||||
FLASH_CR &= ~FLASH_PER;
|
||||
}
|
||||
|
||||
void flash_erase_all_pages(void)
|
||||
{
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
FLASH_CR |= FLASH_MER; /* Enable mass erase. */
|
||||
FLASH_CR |= FLASH_STRT; /* Trigger the erase. */
|
||||
|
||||
flash_wait_for_last_operation();
|
||||
FLASH_CR &= ~FLASH_MER; /* Disable mass erase. */
|
||||
}
|
||||
|
||||
void flash_erase_option_bytes(void)
|
||||
{
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
if ((FLASH_CR & FLASH_OPTWRE) == 0)
|
||||
flash_unlock_option_bytes();
|
||||
|
||||
FLASH_CR |= FLASH_OPTER; /* Enable option byte erase. */
|
||||
FLASH_CR |= FLASH_STRT;
|
||||
flash_wait_for_last_operation();
|
||||
FLASH_CR &= ~FLASH_OPTER; /* Disable option byte erase. */
|
||||
}
|
||||
|
||||
void flash_program_option_bytes(u32 address, u16 data)
|
||||
{
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
if ((FLASH_CR & FLASH_OPTWRE) == 0)
|
||||
flash_unlock_option_bytes();
|
||||
|
||||
FLASH_CR |= FLASH_OPTPG; /* Enable option byte programming. */
|
||||
(*(volatile u16 *)address) = data;
|
||||
flash_wait_for_last_operation();
|
||||
FLASH_CR &= ~FLASH_OPTPG; /* Disable option byte programming. */
|
||||
}
|
||||
118
lib/stm32/f1/gpio.c
Normal file
118
lib/stm32/f1/gpio.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Basic GPIO handling API.
|
||||
*
|
||||
* Examples:
|
||||
* gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
|
||||
* GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
|
||||
* gpio_set(GPIOB, GPIO4);
|
||||
* gpio_clear(GPIOG, GPIO2 | GPIO9);
|
||||
* gpio_get(GPIOC, GPIO1);
|
||||
* gpio_toggle(GPIOA, GPIO7 | GPIO8);
|
||||
* reg16 = gpio_port_read(GPIOD);
|
||||
* gpio_port_write(GPIOF, 0xc8fe);
|
||||
*
|
||||
* TODO:
|
||||
* - GPIO remapping support
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/f1/gpio.h>
|
||||
|
||||
void gpio_set_mode(u32 gpioport, u8 mode, u8 cnf, u16 gpios)
|
||||
{
|
||||
u16 i, offset = 0;
|
||||
u32 crl = 0, crh = 0, tmp32 = 0;
|
||||
|
||||
/*
|
||||
* We want to set the config only for the pins mentioned in gpios,
|
||||
* but keeping the others, so read out the actual config first.
|
||||
*/
|
||||
crl = GPIO_CRL(gpioport);
|
||||
crh = GPIO_CRH(gpioport);
|
||||
|
||||
/* Iterate over all bits, use i as the bitnumber. */
|
||||
for (i = 0; i < 16; i++) {
|
||||
/* Only set the config if the bit is set in gpios. */
|
||||
if (!((1 << i) & gpios))
|
||||
continue;
|
||||
|
||||
/* Calculate bit offset. */
|
||||
offset = (i < 8) ? (i * 4) : ((i - 8) * 4);
|
||||
|
||||
/* Use tmp32 to either modify crl or crh. */
|
||||
tmp32 = (i < 8) ? crl : crh;
|
||||
|
||||
/* Modify bits are needed. */
|
||||
tmp32 &= ~(0b1111 << offset); /* Clear the bits first. */
|
||||
tmp32 |= (mode << offset) | (cnf << (offset + 2));
|
||||
|
||||
/* Write tmp32 into crl or crh, leave the other unchanged. */
|
||||
crl = (i < 8) ? tmp32 : crl;
|
||||
crh = (i >= 8) ? tmp32 : crh;
|
||||
}
|
||||
|
||||
GPIO_CRL(gpioport) = crl;
|
||||
GPIO_CRH(gpioport) = crh;
|
||||
}
|
||||
|
||||
void gpio_set(u32 gpioport, u16 gpios)
|
||||
{
|
||||
GPIO_BSRR(gpioport) = gpios;
|
||||
}
|
||||
|
||||
void gpio_clear(u32 gpioport, u16 gpios)
|
||||
{
|
||||
GPIO_BRR(gpioport) = gpios;
|
||||
}
|
||||
|
||||
u16 gpio_get(u32 gpioport, u16 gpios)
|
||||
{
|
||||
return gpio_port_read(gpioport) & gpios;
|
||||
}
|
||||
|
||||
void gpio_toggle(u32 gpioport, u16 gpios)
|
||||
{
|
||||
GPIO_ODR(gpioport) ^= gpios;
|
||||
}
|
||||
|
||||
u16 gpio_port_read(u32 gpioport)
|
||||
{
|
||||
return (u16)GPIO_IDR(gpioport);
|
||||
}
|
||||
|
||||
void gpio_port_write(u32 gpioport, u16 data)
|
||||
{
|
||||
GPIO_ODR(gpioport) = data;
|
||||
}
|
||||
|
||||
void gpio_port_config_lock(u32 gpioport, u16 gpios)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
/* Special "Lock Key Writing Sequence", see datasheet. */
|
||||
GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
|
||||
GPIO_LCKR(gpioport) = ~GPIO_LCKK & gpios; /* Clear LCKK. */
|
||||
GPIO_LCKR(gpioport) = GPIO_LCKK | gpios; /* Set LCKK. */
|
||||
reg32 = GPIO_LCKR(gpioport); /* Read LCKK. */
|
||||
reg32 = GPIO_LCKR(gpioport); /* Read LCKK again. */
|
||||
|
||||
/* If (reg32 & GPIO_LCKK) is true, the lock is now active. */
|
||||
}
|
||||
63
lib/stm32/f1/libopencm3_stm32f1.ld
Normal file
63
lib/stm32/f1/libopencm3_stm32f1.ld
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Generic linker script for STM32 targets using libopencm3. */
|
||||
|
||||
/* Memory regions must be defined in the ld script which includes this one. */
|
||||
|
||||
/* Enforce emmition of the vector table. */
|
||||
EXTERN (vector_table)
|
||||
|
||||
/* Define sections. */
|
||||
SECTIONS
|
||||
{
|
||||
. = ORIGIN(rom);
|
||||
|
||||
.text : {
|
||||
*(.vectors) /* Vector table */
|
||||
*(.text*) /* Program code */
|
||||
*(.rodata*) /* Read-only data */
|
||||
_etext = .;
|
||||
} >rom
|
||||
|
||||
. = ORIGIN(ram);
|
||||
|
||||
.data : {
|
||||
_data = .;
|
||||
*(.data*) /* Read-write initialized data */
|
||||
_edata = .;
|
||||
} >ram AT >rom
|
||||
|
||||
.bss : {
|
||||
*(.bss*) /* Read-write zero initialized data */
|
||||
*(COMMON)
|
||||
_ebss = .;
|
||||
} >ram AT >rom
|
||||
|
||||
/*
|
||||
* The .eh_frame section appears to be used for C++ exception handling.
|
||||
* You may need to fix this if you're using C++.
|
||||
*/
|
||||
/DISCARD/ : { *(.eh_frame) }
|
||||
|
||||
end = .;
|
||||
}
|
||||
|
||||
PROVIDE(_stack = 0x20000800);
|
||||
|
||||
677
lib/stm32/f1/rcc.c
Normal file
677
lib/stm32/f1/rcc.c
Normal file
@@ -0,0 +1,677 @@
|
||||
/*
|
||||
* 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 program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/f1/rcc.h>
|
||||
#include <libopencm3/stm32/f1/flash.h>
|
||||
|
||||
/* Set the default ppre1 and ppre2 peripheral clock frequencies after reset */
|
||||
u32 rcc_ppre1_frequency = 8000000;
|
||||
u32 rcc_ppre2_frequency = 8000000;
|
||||
|
||||
void rcc_osc_ready_int_clear(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case PLL:
|
||||
RCC_CIR |= RCC_CIR_PLLRDYC;
|
||||
break;
|
||||
case HSE:
|
||||
RCC_CIR |= RCC_CIR_HSERDYC;
|
||||
break;
|
||||
case HSI:
|
||||
RCC_CIR |= RCC_CIR_HSIRDYC;
|
||||
break;
|
||||
case LSE:
|
||||
RCC_CIR |= RCC_CIR_LSERDYC;
|
||||
break;
|
||||
case LSI:
|
||||
RCC_CIR |= RCC_CIR_LSIRDYC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rcc_osc_ready_int_enable(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case PLL:
|
||||
RCC_CIR |= RCC_CIR_PLLRDYIE;
|
||||
break;
|
||||
case HSE:
|
||||
RCC_CIR |= RCC_CIR_HSERDYIE;
|
||||
break;
|
||||
case HSI:
|
||||
RCC_CIR |= RCC_CIR_HSIRDYIE;
|
||||
break;
|
||||
case LSE:
|
||||
RCC_CIR |= RCC_CIR_LSERDYIE;
|
||||
break;
|
||||
case LSI:
|
||||
RCC_CIR |= RCC_CIR_LSIRDYIE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rcc_osc_ready_int_disable(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case PLL:
|
||||
RCC_CIR &= ~RCC_CIR_PLLRDYIE;
|
||||
break;
|
||||
case HSE:
|
||||
RCC_CIR &= ~RCC_CIR_HSERDYIE;
|
||||
break;
|
||||
case HSI:
|
||||
RCC_CIR &= ~RCC_CIR_HSIRDYIE;
|
||||
break;
|
||||
case LSE:
|
||||
RCC_CIR &= ~RCC_CIR_LSERDYIE;
|
||||
break;
|
||||
case LSI:
|
||||
RCC_CIR &= ~RCC_CIR_LSIRDYIE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int rcc_osc_ready_int_flag(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case PLL:
|
||||
return ((RCC_CIR & RCC_CIR_PLLRDYF) != 0);
|
||||
break;
|
||||
case HSE:
|
||||
return ((RCC_CIR & RCC_CIR_HSERDYF) != 0);
|
||||
break;
|
||||
case HSI:
|
||||
return ((RCC_CIR & RCC_CIR_HSIRDYF) != 0);
|
||||
break;
|
||||
case LSE:
|
||||
return ((RCC_CIR & RCC_CIR_LSERDYF) != 0);
|
||||
break;
|
||||
case LSI:
|
||||
return ((RCC_CIR & RCC_CIR_LSIRDYF) != 0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Shouldn't be reached. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
void rcc_css_int_clear(void)
|
||||
{
|
||||
RCC_CIR |= RCC_CIR_CSSC;
|
||||
}
|
||||
|
||||
int rcc_css_int_flag(void)
|
||||
{
|
||||
return ((RCC_CIR & RCC_CIR_CSSF) != 0);
|
||||
}
|
||||
|
||||
void rcc_wait_for_osc_ready(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case PLL:
|
||||
while ((RCC_CR & RCC_CR_PLLRDY) == 0);
|
||||
break;
|
||||
case HSE:
|
||||
while ((RCC_CR & RCC_CR_HSERDY) == 0);
|
||||
break;
|
||||
case HSI:
|
||||
while ((RCC_CR & RCC_CR_HSIRDY) == 0);
|
||||
break;
|
||||
case LSE:
|
||||
while ((RCC_BDCR & RCC_BDCR_LSERDY) == 0);
|
||||
break;
|
||||
case LSI:
|
||||
while ((RCC_CSR & RCC_CSR_LSIRDY) == 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rcc_osc_on(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case PLL:
|
||||
RCC_CR |= RCC_CR_PLLON;
|
||||
break;
|
||||
case HSE:
|
||||
RCC_CR |= RCC_CR_HSEON;
|
||||
break;
|
||||
case HSI:
|
||||
RCC_CR |= RCC_CR_HSION;
|
||||
break;
|
||||
case LSE:
|
||||
RCC_BDCR |= RCC_BDCR_LSEON;
|
||||
break;
|
||||
case LSI:
|
||||
RCC_CSR |= RCC_CSR_LSION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rcc_osc_off(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case PLL:
|
||||
RCC_CR &= ~RCC_CR_PLLON;
|
||||
break;
|
||||
case HSE:
|
||||
RCC_CR &= ~RCC_CR_HSEON;
|
||||
break;
|
||||
case HSI:
|
||||
RCC_CR &= ~RCC_CR_HSION;
|
||||
break;
|
||||
case LSE:
|
||||
RCC_BDCR &= ~RCC_BDCR_LSEON;
|
||||
break;
|
||||
case LSI:
|
||||
RCC_CSR &= ~RCC_CSR_LSION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rcc_css_enable(void)
|
||||
{
|
||||
RCC_CR |= RCC_CR_CSSON;
|
||||
}
|
||||
|
||||
void rcc_css_disable(void)
|
||||
{
|
||||
RCC_CR &= ~RCC_CR_CSSON;
|
||||
}
|
||||
|
||||
void rcc_osc_bypass_enable(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case HSE:
|
||||
RCC_CR |= RCC_CR_HSEBYP;
|
||||
break;
|
||||
case LSE:
|
||||
RCC_BDCR |= RCC_BDCR_LSEBYP;
|
||||
break;
|
||||
case PLL:
|
||||
case HSI:
|
||||
case LSI:
|
||||
/* Do nothing, only HSE/LSE allowed here. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rcc_osc_bypass_disable(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case HSE:
|
||||
RCC_CR &= ~RCC_CR_HSEBYP;
|
||||
break;
|
||||
case LSE:
|
||||
RCC_BDCR &= ~RCC_BDCR_LSEBYP;
|
||||
break;
|
||||
case PLL:
|
||||
case HSI:
|
||||
case LSI:
|
||||
/* Do nothing, only HSE/LSE allowed here. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rcc_peripheral_enable_clock(volatile u32 *reg, u32 en)
|
||||
{
|
||||
*reg |= en;
|
||||
}
|
||||
|
||||
void rcc_peripheral_disable_clock(volatile u32 *reg, u32 en)
|
||||
{
|
||||
*reg &= ~en;
|
||||
}
|
||||
|
||||
void rcc_peripheral_reset(volatile u32 *reg, u32 reset)
|
||||
{
|
||||
*reg |= reset;
|
||||
}
|
||||
|
||||
void rcc_peripheral_clear_reset(volatile u32 *reg, u32 clear_reset)
|
||||
{
|
||||
*reg &= ~clear_reset;
|
||||
}
|
||||
|
||||
void rcc_set_sysclk_source(u32 clk)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~((1 << 1) | (1 << 0));
|
||||
RCC_CFGR = (reg32 | clk);
|
||||
}
|
||||
|
||||
void rcc_set_pll_multiplication_factor(u32 mul)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~((1 << 21) | (1 << 20) | (1 << 19) | (1 << 18));
|
||||
RCC_CFGR = (reg32 | (mul << 18));
|
||||
}
|
||||
|
||||
void rcc_set_pll_source(u32 pllsrc)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~(1 << 16);
|
||||
RCC_CFGR = (reg32 | (pllsrc << 16));
|
||||
}
|
||||
|
||||
void rcc_set_pllxtpre(u32 pllxtpre)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~(1 << 17);
|
||||
RCC_CFGR = (reg32 | (pllxtpre << 17));
|
||||
}
|
||||
|
||||
void rcc_set_adcpre(u32 adcpre)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~((1 << 14) | (1 << 15));
|
||||
RCC_CFGR = (reg32 | (adcpre << 14));
|
||||
}
|
||||
|
||||
void rcc_set_ppre2(u32 ppre2)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~((1 << 11) | (1 << 12) | (1 << 13));
|
||||
RCC_CFGR = (reg32 | (ppre2 << 11));
|
||||
}
|
||||
|
||||
void rcc_set_ppre1(u32 ppre1)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~((1 << 8) | (1 << 9) | (1 << 10));
|
||||
RCC_CFGR = (reg32 | (ppre1 << 8));
|
||||
}
|
||||
|
||||
void rcc_set_hpre(u32 hpre)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7));
|
||||
RCC_CFGR = (reg32 | (hpre << 4));
|
||||
}
|
||||
|
||||
void rcc_set_usbpre(u32 usbpre)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~(1 << 22);
|
||||
RCC_CFGR = (reg32 | (usbpre << 22));
|
||||
}
|
||||
|
||||
u32 rcc_system_clock_source(void)
|
||||
{
|
||||
/* Return the clock source which is used as system clock. */
|
||||
return ((RCC_CFGR & 0x000c) >> 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions are setting up the whole clock system for the most common
|
||||
* input clock and output clock configurations.
|
||||
*/
|
||||
void rcc_clock_setup_in_hsi_out_64mhz(void)
|
||||
{
|
||||
/* Enable internal high-speed oscillator. */
|
||||
rcc_osc_on(HSI);
|
||||
rcc_wait_for_osc_ready(HSI);
|
||||
|
||||
/* Select HSI as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
|
||||
|
||||
/*
|
||||
* Set prescalers for AHB, ADC, ABP1, ABP2.
|
||||
* Do this before touching the PLL (TODO: why?).
|
||||
*/
|
||||
rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 64MHz Max. 72MHz */
|
||||
rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV8); /* Set. 8MHz Max. 14MHz */
|
||||
rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /* Set. 32MHz Max. 36MHz */
|
||||
rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 64MHz Max. 72MHz */
|
||||
|
||||
/*
|
||||
* Sysclk is running with 64MHz -> 2 waitstates.
|
||||
* 0WS from 0-24MHz
|
||||
* 1WS from 24-48MHz
|
||||
* 2WS from 48-72MHz
|
||||
*/
|
||||
flash_set_ws(FLASH_LATENCY_2WS);
|
||||
|
||||
/*
|
||||
* Set the PLL multiplication factor to 16.
|
||||
* 8MHz (internal) * 16 (multiplier) / 2 (PLLSRC_HSI_CLK_DIV2) = 64MHz
|
||||
*/
|
||||
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL16);
|
||||
|
||||
/* Select HSI/2 as PLL source. */
|
||||
rcc_set_pll_source(RCC_CFGR_PLLSRC_HSI_CLK_DIV2);
|
||||
|
||||
/* Enable PLL oscillator and wait for it to stabilize. */
|
||||
rcc_osc_on(PLL);
|
||||
rcc_wait_for_osc_ready(PLL);
|
||||
|
||||
/* Select PLL as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
|
||||
|
||||
/* Set the peripheral clock frequencies used */
|
||||
rcc_ppre1_frequency = 32000000;
|
||||
rcc_ppre2_frequency = 64000000;
|
||||
}
|
||||
|
||||
void rcc_clock_setup_in_hsi_out_48mhz(void)
|
||||
{
|
||||
/* Enable internal high-speed oscillator. */
|
||||
rcc_osc_on(HSI);
|
||||
rcc_wait_for_osc_ready(HSI);
|
||||
|
||||
/* Select HSI as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
|
||||
|
||||
/*
|
||||
* Set prescalers for AHB, ADC, ABP1, ABP2.
|
||||
* Do this before touching the PLL (TODO: why?).
|
||||
*/
|
||||
rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 48MHz Max. 72MHz */
|
||||
rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV8); /* Set. 6MHz Max. 14MHz */
|
||||
rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /* Set. 24MHz Max. 36MHz */
|
||||
rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 48MHz Max. 72MHz */
|
||||
rcc_set_usbpre(RCC_CFGR_USBPRE_PLL_CLK_NODIV); /* Set. 48MHz Max. 48MHz */
|
||||
|
||||
/*
|
||||
* Sysclk runs with 48MHz -> 1 waitstates.
|
||||
* 0WS from 0-24MHz
|
||||
* 1WS from 24-48MHz
|
||||
* 2WS from 48-72MHz
|
||||
*/
|
||||
flash_set_ws(FLASH_LATENCY_1WS);
|
||||
|
||||
/*
|
||||
* Set the PLL multiplication factor to 12.
|
||||
* 8MHz (internal) * 12 (multiplier) / 2 (PLLSRC_HSI_CLK_DIV2) = 48MHz
|
||||
*/
|
||||
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL12);
|
||||
|
||||
/* Select HSI/2 as PLL source. */
|
||||
rcc_set_pll_source(RCC_CFGR_PLLSRC_HSI_CLK_DIV2);
|
||||
|
||||
/* Enable PLL oscillator and wait for it to stabilize. */
|
||||
rcc_osc_on(PLL);
|
||||
rcc_wait_for_osc_ready(PLL);
|
||||
|
||||
/* Select PLL as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
|
||||
|
||||
/* Set the peripheral clock frequencies used */
|
||||
rcc_ppre1_frequency = 24000000;
|
||||
rcc_ppre2_frequency = 48000000;
|
||||
}
|
||||
|
||||
void rcc_clock_setup_in_hse_8mhz_out_24mhz(void)
|
||||
{
|
||||
/* Enable internal high-speed oscillator. */
|
||||
rcc_osc_on(HSI);
|
||||
rcc_wait_for_osc_ready(HSI);
|
||||
|
||||
/* Select HSI as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
|
||||
|
||||
/* Enable external high-speed oscillator 8MHz. */
|
||||
rcc_osc_on(HSE);
|
||||
rcc_wait_for_osc_ready(HSE);
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK);
|
||||
|
||||
/*
|
||||
* Set prescalers for AHB, ADC, ABP1, ABP2.
|
||||
* Do this before touching the PLL (TODO: why?).
|
||||
*/
|
||||
rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 24MHz Max. 72MHz */
|
||||
rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV2); /* Set. 12MHz Max. 14MHz */
|
||||
rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_NODIV); /* Set. 24MHz Max. 36MHz */
|
||||
rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 24MHz Max. 72MHz */
|
||||
|
||||
/*
|
||||
* Sysclk runs with 24MHz -> 0 waitstates.
|
||||
* 0WS from 0-24MHz
|
||||
* 1WS from 24-48MHz
|
||||
* 2WS from 48-72MHz
|
||||
*/
|
||||
flash_set_ws(FLASH_LATENCY_0WS);
|
||||
|
||||
/*
|
||||
* Set the PLL multiplication factor to 3.
|
||||
* 8MHz (external) * 3 (multiplier) = 24MHz
|
||||
*/
|
||||
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL3);
|
||||
|
||||
/* Select HSE as PLL source. */
|
||||
rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_CLK);
|
||||
|
||||
/*
|
||||
* External frequency undivided before entering PLL
|
||||
* (only valid/needed for HSE).
|
||||
*/
|
||||
rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK);
|
||||
|
||||
/* Enable PLL oscillator and wait for it to stabilize. */
|
||||
rcc_osc_on(PLL);
|
||||
rcc_wait_for_osc_ready(PLL);
|
||||
|
||||
/* Select PLL as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
|
||||
|
||||
/* Set the peripheral clock frequencies used */
|
||||
rcc_ppre1_frequency = 24000000;
|
||||
rcc_ppre2_frequency = 24000000;
|
||||
}
|
||||
void rcc_clock_setup_in_hse_8mhz_out_72mhz(void)
|
||||
{
|
||||
/* Enable internal high-speed oscillator. */
|
||||
rcc_osc_on(HSI);
|
||||
rcc_wait_for_osc_ready(HSI);
|
||||
|
||||
/* Select HSI as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
|
||||
|
||||
/* Enable external high-speed oscillator 8MHz. */
|
||||
rcc_osc_on(HSE);
|
||||
rcc_wait_for_osc_ready(HSE);
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK);
|
||||
|
||||
/*
|
||||
* Set prescalers for AHB, ADC, ABP1, ABP2.
|
||||
* Do this before touching the PLL (TODO: why?).
|
||||
*/
|
||||
rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 72MHz Max. 72MHz */
|
||||
rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV8); /* Set. 9MHz Max. 14MHz */
|
||||
rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /* Set. 36MHz Max. 36MHz */
|
||||
rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 72MHz Max. 72MHz */
|
||||
|
||||
/*
|
||||
* Sysclk runs with 72MHz -> 2 waitstates.
|
||||
* 0WS from 0-24MHz
|
||||
* 1WS from 24-48MHz
|
||||
* 2WS from 48-72MHz
|
||||
*/
|
||||
flash_set_ws(FLASH_LATENCY_2WS);
|
||||
|
||||
/*
|
||||
* Set the PLL multiplication factor to 9.
|
||||
* 8MHz (external) * 9 (multiplier) = 72MHz
|
||||
*/
|
||||
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL9);
|
||||
|
||||
/* Select HSE as PLL source. */
|
||||
rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_CLK);
|
||||
|
||||
/*
|
||||
* External frequency undivided before entering PLL
|
||||
* (only valid/needed for HSE).
|
||||
*/
|
||||
rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK);
|
||||
|
||||
/* Enable PLL oscillator and wait for it to stabilize. */
|
||||
rcc_osc_on(PLL);
|
||||
rcc_wait_for_osc_ready(PLL);
|
||||
|
||||
/* Select PLL as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
|
||||
|
||||
/* Set the peripheral clock frequencies used */
|
||||
rcc_ppre1_frequency = 36000000;
|
||||
rcc_ppre2_frequency = 72000000;
|
||||
}
|
||||
|
||||
void rcc_clock_setup_in_hse_12mhz_out_72mhz(void)
|
||||
{
|
||||
/* Enable internal high-speed oscillator. */
|
||||
rcc_osc_on(HSI);
|
||||
rcc_wait_for_osc_ready(HSI);
|
||||
|
||||
/* Select HSI as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
|
||||
|
||||
/* Enable external high-speed oscillator 16MHz. */
|
||||
rcc_osc_on(HSE);
|
||||
rcc_wait_for_osc_ready(HSE);
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK);
|
||||
|
||||
/*
|
||||
* Set prescalers for AHB, ADC, ABP1, ABP2.
|
||||
* Do this before touching the PLL (TODO: why?).
|
||||
*/
|
||||
rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 72MHz Max. 72MHz */
|
||||
rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV6); /* Set. 12MHz Max. 14MHz */
|
||||
rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /* Set. 36MHz Max. 36MHz */
|
||||
rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 72MHz Max. 72MHz */
|
||||
|
||||
/*
|
||||
* Sysclk runs with 72MHz -> 2 waitstates.
|
||||
* 0WS from 0-24MHz
|
||||
* 1WS from 24-48MHz
|
||||
* 2WS from 48-72MHz
|
||||
*/
|
||||
flash_set_ws(FLASH_LATENCY_2WS);
|
||||
|
||||
/*
|
||||
* Set the PLL multiplication factor to 9.
|
||||
* 12MHz (external) * 6 (multiplier) / 1 (PLLXTPRE_HSE_CLK) = 72MHz
|
||||
*/
|
||||
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL6);
|
||||
|
||||
/* Select HSI as PLL source. */
|
||||
rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_CLK);
|
||||
|
||||
/*
|
||||
* Divide external frequency by 2 before entering PLL
|
||||
* (only valid/needed for HSE).
|
||||
*/
|
||||
rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK);
|
||||
|
||||
/* Enable PLL oscillator and wait for it to stabilize. */
|
||||
rcc_osc_on(PLL);
|
||||
rcc_wait_for_osc_ready(PLL);
|
||||
|
||||
/* Select PLL as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
|
||||
|
||||
/* Set the peripheral clock frequencies used */
|
||||
rcc_ppre1_frequency = 36000000;
|
||||
rcc_ppre2_frequency = 72000000;
|
||||
}
|
||||
|
||||
void rcc_clock_setup_in_hse_16mhz_out_72mhz(void)
|
||||
{
|
||||
/* Enable internal high-speed oscillator. */
|
||||
rcc_osc_on(HSI);
|
||||
rcc_wait_for_osc_ready(HSI);
|
||||
|
||||
/* Select HSI as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
|
||||
|
||||
/* Enable external high-speed oscillator 16MHz. */
|
||||
rcc_osc_on(HSE);
|
||||
rcc_wait_for_osc_ready(HSE);
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK);
|
||||
|
||||
/*
|
||||
* Set prescalers for AHB, ADC, ABP1, ABP2.
|
||||
* Do this before touching the PLL (TODO: why?).
|
||||
*/
|
||||
rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 72MHz Max. 72MHz */
|
||||
rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV6); /* Set. 12MHz Max. 14MHz */
|
||||
rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /* Set. 36MHz Max. 36MHz */
|
||||
rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 72MHz Max. 72MHz */
|
||||
|
||||
/*
|
||||
* Sysclk runs with 72MHz -> 2 waitstates.
|
||||
* 0WS from 0-24MHz
|
||||
* 1WS from 24-48MHz
|
||||
* 2WS from 48-72MHz
|
||||
*/
|
||||
flash_set_ws(FLASH_LATENCY_2WS);
|
||||
|
||||
/*
|
||||
* Set the PLL multiplication factor to 9.
|
||||
* 16MHz (external) * 9 (multiplier) / 2 (PLLXTPRE_HSE_CLK_DIV2) = 72MHz
|
||||
*/
|
||||
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL9);
|
||||
|
||||
/* Select HSI as PLL source. */
|
||||
rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_CLK);
|
||||
|
||||
/*
|
||||
* Divide external frequency by 2 before entering PLL
|
||||
* (only valid/needed for HSE).
|
||||
*/
|
||||
rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK_DIV2);
|
||||
|
||||
/* Enable PLL oscillator and wait for it to stabilize. */
|
||||
rcc_osc_on(PLL);
|
||||
rcc_wait_for_osc_ready(PLL);
|
||||
|
||||
/* Select PLL as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
|
||||
|
||||
/* Set the peripheral clock frequencies used */
|
||||
rcc_ppre1_frequency = 36000000;
|
||||
rcc_ppre2_frequency = 72000000;
|
||||
}
|
||||
|
||||
void rcc_backupdomain_reset(void)
|
||||
{
|
||||
/* Set the backup domain software reset. */
|
||||
RCC_BDCR |= RCC_BDCR_BDRST;
|
||||
|
||||
/* Clear the backup domain software reset. */
|
||||
RCC_BDCR &= ~RCC_BDCR_BDRST;
|
||||
}
|
||||
282
lib/stm32/f1/rtc.c
Normal file
282
lib/stm32/f1/rtc.c
Normal file
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
* Copyright (C) 2010 Lord James <lordjames@y7mail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/f1/rcc.h>
|
||||
#include <libopencm3/stm32/f1/rtc.h>
|
||||
#include <libopencm3/stm32/pwr.h>
|
||||
|
||||
void rtc_awake_from_off(osc_t clock_source)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
/* Enable power and backup interface clocks. */
|
||||
RCC_APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN);
|
||||
|
||||
/* Enable access to the backup registers and the RTC. */
|
||||
PWR_CR |= PWR_CR_DBP;
|
||||
|
||||
/*
|
||||
* Reset the backup domain, clears everything RTC related.
|
||||
* If not wanted use the rtc_awake_from_standby() function.
|
||||
*/
|
||||
rcc_backupdomain_reset();
|
||||
|
||||
switch (clock_source) {
|
||||
case LSE:
|
||||
/* Turn the LSE on and wait while it stabilises. */
|
||||
RCC_BDCR |= RCC_BDCR_LSEON;
|
||||
while ((reg32 = (RCC_BDCR & RCC_BDCR_LSERDY)) == 0);
|
||||
|
||||
/* Choose LSE as the RTC clock source. */
|
||||
RCC_BDCR &= ~((1 << 8) | (1 << 9));
|
||||
RCC_BDCR |= (1 << 8);
|
||||
break;
|
||||
case LSI:
|
||||
/* Turn the LSI on and wait while it stabilises. */
|
||||
RCC_CSR |= RCC_CSR_LSION;
|
||||
while ((reg32 = (RCC_CSR & RCC_CSR_LSIRDY)) == 0);
|
||||
|
||||
/* Choose LSI as the RTC clock source. */
|
||||
RCC_BDCR &= ~((1 << 8) | (1 << 9));
|
||||
RCC_BDCR |= (1 << 9);
|
||||
break;
|
||||
case HSE:
|
||||
/* Turn the HSE on and wait while it stabilises. */
|
||||
RCC_CR |= RCC_CR_HSEON;
|
||||
while ((reg32 = (RCC_CR & RCC_CR_HSERDY)) == 0);
|
||||
|
||||
/* Choose HSE as the RTC clock source. */
|
||||
RCC_BDCR &= ~((1 << 8) | (1 << 9));
|
||||
RCC_BDCR |= (1 << 9) | (1 << 8);
|
||||
break;
|
||||
case PLL:
|
||||
case HSI:
|
||||
/* Unusable clock source, here to prevent warnings. */
|
||||
/* Turn off clock sources to RTC. */
|
||||
RCC_BDCR &= ~((1 << 8) | (1 << 9));
|
||||
break;
|
||||
}
|
||||
|
||||
/* Enable the RTC. */
|
||||
RCC_BDCR |= RCC_BDCR_RTCEN;
|
||||
|
||||
/* Wait for the RSF bit in RTC_CRL to be set by hardware. */
|
||||
RTC_CRL &= ~RTC_CRL_RSF;
|
||||
while ((reg32 = (RTC_CRL & RTC_CRL_RSF)) == 0);
|
||||
|
||||
/* Wait for the last write operation to finish. */
|
||||
/* TODO: Necessary? */
|
||||
while ((reg32 = (RTC_CRL & RTC_CRL_RTOFF)) == 0);
|
||||
}
|
||||
|
||||
void rtc_enter_config_mode(void)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
/* Wait until the RTOFF bit is 1 (no RTC register writes ongoing). */
|
||||
while ((reg32 = (RTC_CRL & RTC_CRL_RTOFF)) == 0);
|
||||
|
||||
/* Enter configuration mode. */
|
||||
RTC_CRL |= RTC_CRL_CNF;
|
||||
}
|
||||
|
||||
void rtc_exit_config_mode(void)
|
||||
{
|
||||
/* u32 reg32; */
|
||||
|
||||
/* Exit configuration mode. */
|
||||
RTC_CRL &= ~RTC_CRL_CNF;
|
||||
|
||||
/* Wait until the RTOFF bit is 1 (our RTC register write finished). */
|
||||
/* while ((reg32 = (RTC_CRL & RTC_CRL_RTOFF)) == 0); */
|
||||
/* TODO: Unnecessary since we poll the bit on config entry(?) */
|
||||
}
|
||||
|
||||
void rtc_set_alarm_time(u32 alarm_time)
|
||||
{
|
||||
rtc_enter_config_mode();
|
||||
RTC_ALRL = (alarm_time & 0x0000ffff);
|
||||
RTC_ALRH = (alarm_time & 0xffff0000) >> 16;
|
||||
rtc_exit_config_mode();
|
||||
}
|
||||
|
||||
void rtc_enable_alarm(void)
|
||||
{
|
||||
rtc_enter_config_mode();
|
||||
RTC_CRH |= RTC_CRH_ALRIE;
|
||||
rtc_exit_config_mode();
|
||||
}
|
||||
|
||||
void rtc_disable_alarm(void)
|
||||
{
|
||||
rtc_enter_config_mode();
|
||||
RTC_CRH &= ~RTC_CRH_ALRIE;
|
||||
rtc_exit_config_mode();
|
||||
}
|
||||
|
||||
void rtc_set_prescale_val(u32 prescale_val)
|
||||
{
|
||||
rtc_enter_config_mode();
|
||||
RTC_PRLL = prescale_val & 0x0000ffff; /* PRL[15:0] */
|
||||
RTC_PRLH = (prescale_val & 0x000f0000) >> 16; /* PRL[19:16] */
|
||||
rtc_exit_config_mode();
|
||||
}
|
||||
|
||||
u32 rtc_get_counter_val(void)
|
||||
{
|
||||
return (RTC_CNTH << 16) | RTC_CNTL;
|
||||
}
|
||||
|
||||
u32 rtc_get_prescale_div_val(void)
|
||||
{
|
||||
return (RTC_DIVH << 16) | RTC_DIVL;
|
||||
}
|
||||
|
||||
u32 rtc_get_alarm_val(void)
|
||||
{
|
||||
return (RTC_ALRH << 16) | RTC_ALRL;
|
||||
}
|
||||
|
||||
void rtc_set_counter_val(u32 counter_val)
|
||||
{
|
||||
rtc_enter_config_mode();
|
||||
RTC_CNTH = (counter_val & 0xffff0000) >> 16; /* CNT[31:16] */
|
||||
RTC_CNTL = counter_val & 0x0000ffff; /* CNT[15:0] */
|
||||
rtc_exit_config_mode();
|
||||
}
|
||||
|
||||
void rtc_interrupt_enable(rtcflag_t flag_val)
|
||||
{
|
||||
rtc_enter_config_mode();
|
||||
|
||||
/* Set the correct interrupt enable. */
|
||||
switch(flag_val) {
|
||||
case RTC_SEC:
|
||||
RTC_CRH |= RTC_CRH_SECIE;
|
||||
break;
|
||||
case RTC_ALR:
|
||||
RTC_CRH |= RTC_CRH_ALRIE;
|
||||
break;
|
||||
case RTC_OW:
|
||||
RTC_CRH |= RTC_CRH_OWIE;
|
||||
break;
|
||||
}
|
||||
|
||||
rtc_exit_config_mode();
|
||||
}
|
||||
|
||||
void rtc_interrupt_disable(rtcflag_t flag_val)
|
||||
{
|
||||
rtc_enter_config_mode();
|
||||
|
||||
/* Disable the correct interrupt enable. */
|
||||
switch(flag_val) {
|
||||
case RTC_SEC:
|
||||
RTC_CRH &= ~RTC_CRH_SECIE;
|
||||
break;
|
||||
case RTC_ALR:
|
||||
RTC_CRH &= ~RTC_CRH_ALRIE;
|
||||
break;
|
||||
case RTC_OW:
|
||||
RTC_CRH &= ~RTC_CRH_OWIE;
|
||||
break;
|
||||
}
|
||||
|
||||
rtc_exit_config_mode();
|
||||
}
|
||||
|
||||
void rtc_clear_flag(rtcflag_t flag_val)
|
||||
{
|
||||
/* Configuration mode not needed. */
|
||||
|
||||
/* Clear the correct flag. */
|
||||
switch(flag_val) {
|
||||
case RTC_SEC:
|
||||
RTC_CRL &= ~RTC_CRL_SECF;
|
||||
break;
|
||||
case RTC_ALR:
|
||||
RTC_CRL &= ~RTC_CRL_ALRF;
|
||||
break;
|
||||
case RTC_OW:
|
||||
RTC_CRL &= ~RTC_CRL_OWF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u32 rtc_check_flag(rtcflag_t flag_val)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
/* Read correct flag. */
|
||||
switch(flag_val) {
|
||||
case RTC_SEC:
|
||||
reg32 = RTC_CRL & RTC_CRL_SECF;
|
||||
break;
|
||||
case RTC_ALR:
|
||||
reg32 = RTC_CRL & RTC_CRL_ALRF;
|
||||
break;
|
||||
case RTC_OW:
|
||||
reg32 = RTC_CRL & RTC_CRL_OWF;
|
||||
break;
|
||||
default:
|
||||
reg32 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return reg32;
|
||||
}
|
||||
|
||||
void rtc_awake_from_standby(void)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
/* Enable power and backup interface clocks. */
|
||||
RCC_APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN);
|
||||
|
||||
/* Enable access to the backup registers and the RTC. */
|
||||
PWR_CR |= PWR_CR_DBP;
|
||||
|
||||
/* Wait for the RSF bit in RTC_CRL to be set by hardware. */
|
||||
RTC_CRL &= ~RTC_CRL_RSF;
|
||||
while ((reg32 = (RTC_CRL & RTC_CRL_RSF)) == 0);
|
||||
|
||||
/* Wait for the last write operation to finish. */
|
||||
/* TODO: Necessary? */
|
||||
while ((reg32 = (RTC_CRL & RTC_CRL_RTOFF)) == 0);
|
||||
}
|
||||
|
||||
void rtc_auto_awake(osc_t clock_source, u32 prescale_val)
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
/* Enable power and backup interface clocks. */
|
||||
RCC_APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN);
|
||||
|
||||
/* Enable access to the backup registers and the RTC. */
|
||||
/* TODO: Not sure if this is necessary to just read the flag. */
|
||||
PWR_CR |= PWR_CR_DBP;
|
||||
|
||||
if ((reg32 = RCC_BDCR & RCC_BDCR_RTCEN) != 0) {
|
||||
rtc_awake_from_standby();
|
||||
} else {
|
||||
rtc_awake_from_off(clock_source);
|
||||
rtc_set_prescale_val(prescale_val);
|
||||
}
|
||||
}
|
||||
30
lib/stm32/f1/scb.c
Normal file
30
lib/stm32/f1/scb.c
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/f1/scb.h>
|
||||
|
||||
void scb_reset_core(void)
|
||||
{
|
||||
SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_VECTRESET;
|
||||
}
|
||||
|
||||
void scb_reset_system(void)
|
||||
{
|
||||
SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ;
|
||||
}
|
||||
914
lib/stm32/f1/timer.c
Normal file
914
lib/stm32/f1/timer.c
Normal file
@@ -0,0 +1,914 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Edward Cheeseman <evbuilder@users.sourceforge.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Basic TIMER handling API.
|
||||
*
|
||||
* Examples:
|
||||
* timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT_MUL_2,
|
||||
* TIM_CR1_CMS_CENTRE_3, TIM_CR1_DIR_UP);
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/timer.h>
|
||||
#include <libopencm3/stm32/f1/rcc.h>
|
||||
|
||||
void timer_reset(u32 timer_peripheral)
|
||||
{
|
||||
switch (timer_peripheral) {
|
||||
case TIM1:
|
||||
rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM1RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM1RST);
|
||||
break;
|
||||
case TIM2:
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM2RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM2RST);
|
||||
break;
|
||||
case TIM3:
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM3RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM3RST);
|
||||
break;
|
||||
case TIM4:
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM4RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM4RST);
|
||||
break;
|
||||
case TIM5:
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM5RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM5RST);
|
||||
break;
|
||||
case TIM6:
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM6RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM6RST);
|
||||
break;
|
||||
case TIM7:
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM7RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM7RST);
|
||||
break;
|
||||
case TIM8:
|
||||
rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM8RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM8RST);
|
||||
break;
|
||||
/* These timers are not supported in libopencm3 yet */
|
||||
/*
|
||||
case TIM9:
|
||||
rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM9RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM9RST);
|
||||
break;
|
||||
case TIM10:
|
||||
rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM10RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM10RST);
|
||||
break;
|
||||
case TIM11:
|
||||
rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM11RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_TIM11RST);
|
||||
break;
|
||||
case TIM12:
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM12RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM12RST);
|
||||
break;
|
||||
case TIM13:
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM13RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM13RST);
|
||||
break;
|
||||
case TIM14:
|
||||
rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM14RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_TIM14RST);
|
||||
break;
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
void timer_enable_irq(u32 timer_peripheral, u32 irq)
|
||||
{
|
||||
TIM_DIER(timer_peripheral) |= irq;
|
||||
}
|
||||
|
||||
void timer_disable_irq(u32 timer_peripheral, u32 irq)
|
||||
{
|
||||
TIM_DIER(timer_peripheral) &= ~irq;
|
||||
}
|
||||
|
||||
bool timer_get_flag(u32 timer_peripheral, u32 flag)
|
||||
{
|
||||
if (((TIM_SR(timer_peripheral) & flag) != 0) &&
|
||||
((TIM_DIER(timer_peripheral) & flag) != 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void timer_clear_flag(u32 timer_peripheral, u32 flag)
|
||||
{
|
||||
TIM_SR(timer_peripheral) &= ~flag;
|
||||
}
|
||||
|
||||
void timer_set_mode(u32 timer_peripheral, u8 clock_div,
|
||||
u8 alignment, u8 direction)
|
||||
{
|
||||
u32 cr1;
|
||||
|
||||
cr1 = TIM_CR1(timer_peripheral);
|
||||
|
||||
cr1 &= ~(TIM_CR1_CKD_CK_INT_MASK |
|
||||
TIM_CR1_CMS_MASK |
|
||||
TIM_CR1_DIR_DOWN);
|
||||
|
||||
cr1 |= clock_div | alignment | direction;
|
||||
|
||||
TIM_CR1(timer_peripheral) = cr1;
|
||||
}
|
||||
|
||||
void timer_set_clock_division(u32 timer_peripheral, u32 clock_div)
|
||||
{
|
||||
clock_div &= TIM_CR1_CKD_CK_INT_MASK;
|
||||
TIM_CR1(timer_peripheral) &= ~TIM_CR1_CKD_CK_INT_MASK;
|
||||
TIM_CR1(timer_peripheral) |= clock_div;
|
||||
}
|
||||
|
||||
void timer_enable_preload(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR1(timer_peripheral) |= TIM_CR1_ARPE;
|
||||
}
|
||||
|
||||
void timer_disable_preload(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR1(timer_peripheral) &= ~TIM_CR1_ARPE;
|
||||
}
|
||||
|
||||
void timer_set_alignment(u32 timer_peripheral, u32 alignment)
|
||||
{
|
||||
alignment &= TIM_CR1_CMS_MASK;
|
||||
TIM_CR1(timer_peripheral) &= ~TIM_CR1_CMS_MASK;
|
||||
TIM_CR1(timer_peripheral) |= alignment;
|
||||
}
|
||||
|
||||
void timer_direction_up(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR1(timer_peripheral) &= ~TIM_CR1_DIR_DOWN;
|
||||
}
|
||||
|
||||
void timer_direction_down(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR1(timer_peripheral) |= TIM_CR1_DIR_DOWN;
|
||||
}
|
||||
|
||||
void timer_one_shot_mode(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR1(timer_peripheral) |= TIM_CR1_OPM;
|
||||
}
|
||||
|
||||
void timer_continuous_mode(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR1(timer_peripheral) &= ~TIM_CR1_OPM;
|
||||
}
|
||||
|
||||
void timer_update_on_any(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR1(timer_peripheral) &= ~TIM_CR1_URS;
|
||||
}
|
||||
|
||||
void timer_update_on_overflow(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR1(timer_peripheral) |= TIM_CR1_URS;
|
||||
}
|
||||
|
||||
void timer_enable_update_event(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR1(timer_peripheral) &= ~TIM_CR1_UDIS;
|
||||
}
|
||||
|
||||
void timer_disable_update_event(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR1(timer_peripheral) |= TIM_CR1_UDIS;
|
||||
}
|
||||
|
||||
void timer_enable_counter(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR1(timer_peripheral) |= TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
void timer_disable_counter(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR1(timer_peripheral) &= ~TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
void timer_set_output_idle_state(u32 timer_peripheral, u32 outputs)
|
||||
{
|
||||
TIM_CR2(timer_peripheral) |= outputs & TIM_CR2_OIS_MASK;
|
||||
}
|
||||
|
||||
void timer_reset_output_idle_state(u32 timer_peripheral, u32 outputs)
|
||||
{
|
||||
TIM_CR2(timer_peripheral) &= ~(outputs & TIM_CR2_OIS_MASK);
|
||||
}
|
||||
|
||||
void timer_set_ti1_ch123_xor(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR2(timer_peripheral) |= TIM_CR2_TI1S;
|
||||
}
|
||||
|
||||
void timer_set_ti1_ch1(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR2(timer_peripheral) &= ~TIM_CR2_TI1S;
|
||||
}
|
||||
|
||||
void timer_set_master_mode(u32 timer_peripheral, u32 mode)
|
||||
{
|
||||
TIM_CR2(timer_peripheral) &= ~TIM_CR2_MMS_MASK;
|
||||
TIM_CR2(timer_peripheral) |= mode;
|
||||
}
|
||||
|
||||
void timer_set_dma_on_compare_event(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCDS;
|
||||
}
|
||||
|
||||
void timer_set_dma_on_update_event(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR2(timer_peripheral) |= TIM_CR2_CCDS;
|
||||
}
|
||||
|
||||
void timer_enable_compare_control_update_on_trigger(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR2(timer_peripheral) |= TIM_CR2_CCUS;
|
||||
}
|
||||
|
||||
void timer_disable_compare_control_update_on_trigger(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCUS;
|
||||
}
|
||||
|
||||
void timer_enable_preload_complementry_enable_bits(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR2(timer_peripheral) |= TIM_CR2_CCPC;
|
||||
}
|
||||
|
||||
void timer_disable_preload_complementry_enable_bits(u32 timer_peripheral)
|
||||
{
|
||||
TIM_CR2(timer_peripheral) &= ~TIM_CR2_CCPC;
|
||||
}
|
||||
|
||||
void timer_set_prescaler(u32 timer_peripheral, u32 value)
|
||||
{
|
||||
TIM_PSC(timer_peripheral) = value;
|
||||
}
|
||||
|
||||
void timer_set_repetition_counter(u32 timer_peripheral, u32 value)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_RCR(timer_peripheral) = value;
|
||||
}
|
||||
|
||||
void timer_set_period(u32 timer_peripheral, u32 period)
|
||||
{
|
||||
TIM_ARR(timer_peripheral) = period;
|
||||
}
|
||||
|
||||
void timer_enable_oc_clear(u32 timer_peripheral, enum tim_oc_id oc_id)
|
||||
{
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1CE;
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2CE;
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3CE;
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4CE;
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
case TIM_OC2N:
|
||||
case TIM_OC3N:
|
||||
/* Ignoring as fast enable only applies to the whole channel. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_disable_oc_clear(u32 timer_peripheral, enum tim_oc_id oc_id)
|
||||
{
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1CE;
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2CE;
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3CE;
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4CE;
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
case TIM_OC2N:
|
||||
case TIM_OC3N:
|
||||
/* Ignoring as fast enable only applies to the whole channel. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_set_oc_fast_mode(u32 timer_peripheral, enum tim_oc_id oc_id)
|
||||
{
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1FE;
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2FE;
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3FE;
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4FE;
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
case TIM_OC2N:
|
||||
case TIM_OC3N:
|
||||
/* Ignoring as fast enable only applies to the whole channel. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_set_oc_slow_mode(u32 timer_peripheral, enum tim_oc_id oc_id)
|
||||
{
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1FE;
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2FE;
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3FE;
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4FE;
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
case TIM_OC2N:
|
||||
case TIM_OC3N:
|
||||
/* Ignoring as this option applies to the whole channel. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_set_oc_mode(u32 timer_peripheral, enum tim_oc_id oc_id,
|
||||
enum tim_oc_mode oc_mode)
|
||||
{
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_CC1S_MASK;
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_CC1S_OUT;
|
||||
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1M_MASK;
|
||||
switch (oc_mode) {
|
||||
case TIM_OCM_FROZEN:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_FROZEN;
|
||||
break;
|
||||
case TIM_OCM_ACTIVE:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_ACTIVE;
|
||||
break;
|
||||
case TIM_OCM_INACTIVE:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_INACTIVE;
|
||||
break;
|
||||
case TIM_OCM_TOGGLE:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_TOGGLE;
|
||||
break;
|
||||
case TIM_OCM_FORCE_LOW:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_FORCE_LOW;
|
||||
break;
|
||||
case TIM_OCM_FORCE_HIGH:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_FORCE_HIGH;
|
||||
break;
|
||||
case TIM_OCM_PWM1:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_PWM1;
|
||||
break;
|
||||
case TIM_OCM_PWM2:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1M_PWM2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_CC2S_MASK;
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_CC2S_OUT;
|
||||
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2M_MASK;
|
||||
switch (oc_mode) {
|
||||
case TIM_OCM_FROZEN:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_FROZEN;
|
||||
break;
|
||||
case TIM_OCM_ACTIVE:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_ACTIVE;
|
||||
break;
|
||||
case TIM_OCM_INACTIVE:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_INACTIVE;
|
||||
break;
|
||||
case TIM_OCM_TOGGLE:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_TOGGLE;
|
||||
break;
|
||||
case TIM_OCM_FORCE_LOW:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_FORCE_LOW;
|
||||
break;
|
||||
case TIM_OCM_FORCE_HIGH:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_FORCE_HIGH;
|
||||
break;
|
||||
case TIM_OCM_PWM1:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_PWM1;
|
||||
break;
|
||||
case TIM_OCM_PWM2:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2M_PWM2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR2_CC3S_MASK;
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_CC3S_OUT;
|
||||
TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3M_MASK;
|
||||
switch (oc_mode) {
|
||||
case TIM_OCM_FROZEN:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_FROZEN;
|
||||
break;
|
||||
case TIM_OCM_ACTIVE:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_OC3M_ACTIVE;
|
||||
break;
|
||||
case TIM_OCM_INACTIVE:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_INACTIVE;
|
||||
break;
|
||||
case TIM_OCM_TOGGLE:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_TOGGLE;
|
||||
break;
|
||||
case TIM_OCM_FORCE_LOW:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_FORCE_LOW;
|
||||
break;
|
||||
case TIM_OCM_FORCE_HIGH:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_FORCE_HIGH;
|
||||
break;
|
||||
case TIM_OCM_PWM1:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_PWM1;
|
||||
break;
|
||||
case TIM_OCM_PWM2:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3M_PWM2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR2_CC4S_MASK;
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_CC4S_OUT;
|
||||
TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4M_MASK;
|
||||
switch (oc_mode) {
|
||||
case TIM_OCM_FROZEN:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_FROZEN;
|
||||
break;
|
||||
case TIM_OCM_ACTIVE:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR2_OC4M_ACTIVE;
|
||||
break;
|
||||
case TIM_OCM_INACTIVE:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_INACTIVE;
|
||||
break;
|
||||
case TIM_OCM_TOGGLE:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_TOGGLE;
|
||||
break;
|
||||
case TIM_OCM_FORCE_LOW:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_FORCE_LOW;
|
||||
break;
|
||||
case TIM_OCM_FORCE_HIGH:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_FORCE_HIGH;
|
||||
break;
|
||||
case TIM_OCM_PWM1:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_PWM1;
|
||||
break;
|
||||
case TIM_OCM_PWM2:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4M_PWM2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
case TIM_OC2N:
|
||||
case TIM_OC3N:
|
||||
/* Ignoring as this option applies to the whole channel. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_enable_oc_preload(u32 timer_peripheral, enum tim_oc_id oc_id)
|
||||
{
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC1PE;
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CCMR1(timer_peripheral) |= TIM_CCMR1_OC2PE;
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC3PE;
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CCMR2(timer_peripheral) |= TIM_CCMR2_OC4PE;
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
case TIM_OC2N:
|
||||
case TIM_OC3N:
|
||||
/* Ignoring as this option applies to the whole channel. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_disable_oc_preload(u32 timer_peripheral, enum tim_oc_id oc_id)
|
||||
{
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC1PE;
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CCMR1(timer_peripheral) &= ~TIM_CCMR1_OC2PE;
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC3PE;
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CCMR2(timer_peripheral) &= ~TIM_CCMR2_OC4PE;
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
case TIM_OC2N:
|
||||
case TIM_OC3N:
|
||||
/* Ignoring as this option applies to the whole channel. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_set_oc_polarity_high(u32 timer_peripheral, enum tim_oc_id oc_id)
|
||||
{
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC1P;
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC2P;
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC3P;
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC4P;
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
case TIM_OC2N:
|
||||
case TIM_OC3N:
|
||||
/* Ignoring as this option applies to TIM1 and TIM8 only. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Acting for TIM1 and TIM8 only from here onwards. */
|
||||
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
|
||||
return;
|
||||
|
||||
switch (oc_id) {
|
||||
case TIM_OC1N:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC1NP;
|
||||
break;
|
||||
case TIM_OC2N:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC2NP;
|
||||
break;
|
||||
case TIM_OC3N:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC3NP;
|
||||
break;
|
||||
case TIM_OC1:
|
||||
case TIM_OC2:
|
||||
case TIM_OC3:
|
||||
case TIM_OC4:
|
||||
/* Ignoring as this option was already set above. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_set_oc_polarity_low(u32 timer_peripheral, enum tim_oc_id oc_id)
|
||||
{
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC1P;
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC2P;
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC3P;
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC4P;
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
case TIM_OC2N:
|
||||
case TIM_OC3N:
|
||||
/* Ignoring as this option applies to TIM1 and TIM8 only. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Acting for TIM1 and TIM8 only from here onwards. */
|
||||
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
|
||||
return;
|
||||
|
||||
switch (oc_id) {
|
||||
case TIM_OC1N:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC1NP;
|
||||
break;
|
||||
case TIM_OC2N:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC2NP;
|
||||
break;
|
||||
case TIM_OC3N:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC3NP;
|
||||
break;
|
||||
case TIM_OC1:
|
||||
case TIM_OC2:
|
||||
case TIM_OC3:
|
||||
case TIM_OC4:
|
||||
/* Ignoring as this option was already set above. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_enable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
|
||||
{
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC1E;
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC2E;
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC3E;
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC4E;
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
case TIM_OC2N:
|
||||
case TIM_OC3N:
|
||||
/* Ignoring as this option applies to TIM1 and TIM8 only. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Acting for TIM1 and TIM8 only from here onwards. */
|
||||
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
|
||||
return;
|
||||
|
||||
switch (oc_id) {
|
||||
case TIM_OC1N:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC1NE;
|
||||
break;
|
||||
case TIM_OC2N:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC2NE;
|
||||
break;
|
||||
case TIM_OC3N:
|
||||
TIM_CCER(timer_peripheral) |= TIM_CCER_CC3NE;
|
||||
break;
|
||||
case TIM_OC1:
|
||||
case TIM_OC2:
|
||||
case TIM_OC3:
|
||||
case TIM_OC4:
|
||||
/* Ignoring as this option was already set above. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_disable_oc_output(u32 timer_peripheral, enum tim_oc_id oc_id)
|
||||
{
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC1E;
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC2E;
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC3E;
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC4E;
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
case TIM_OC2N:
|
||||
case TIM_OC3N:
|
||||
/* Ignoring as this option applies to TIM1 and TIM8 only. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Acting for TIM1 and TIM8 only from here onwards. */
|
||||
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
|
||||
return;
|
||||
|
||||
switch (oc_id) {
|
||||
case TIM_OC1N:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC1NE;
|
||||
break;
|
||||
case TIM_OC2N:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC2NE;
|
||||
break;
|
||||
case TIM_OC3N:
|
||||
TIM_CCER(timer_peripheral) &= ~TIM_CCER_CC3NE;
|
||||
break;
|
||||
case TIM_OC1:
|
||||
case TIM_OC2:
|
||||
case TIM_OC3:
|
||||
case TIM_OC4:
|
||||
/* Ignoring as this option was already set above. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_set_oc_idle_state_set(u32 timer_peripheral, enum tim_oc_id oc_id)
|
||||
{
|
||||
/* Acting for TIM1 and TIM8 only. */
|
||||
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
|
||||
return;
|
||||
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CR2(timer_peripheral) |= TIM_CR2_OIS1;
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
TIM_CR2(timer_peripheral) |= TIM_CR2_OIS1N;
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CR2(timer_peripheral) |= TIM_CR2_OIS2;
|
||||
break;
|
||||
case TIM_OC2N:
|
||||
TIM_CR2(timer_peripheral) |= TIM_CR2_OIS2N;
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CR2(timer_peripheral) |= TIM_CR2_OIS3;
|
||||
break;
|
||||
case TIM_OC3N:
|
||||
TIM_CR2(timer_peripheral) |= TIM_CR2_OIS3N;
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CR2(timer_peripheral) |= TIM_CR2_OIS4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_set_oc_idle_state_unset(u32 timer_peripheral, enum tim_oc_id oc_id)
|
||||
{
|
||||
/* Acting for TIM1 and TIM8 only. */
|
||||
if ((timer_peripheral != TIM1) && (timer_peripheral != TIM8))
|
||||
return;
|
||||
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS1;
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS1N;
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS2;
|
||||
break;
|
||||
case TIM_OC2N:
|
||||
TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS2N;
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS3;
|
||||
break;
|
||||
case TIM_OC3N:
|
||||
TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS3N;
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CR2(timer_peripheral) &= ~TIM_CR2_OIS4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_set_oc_value(u32 timer_peripheral, enum tim_oc_id oc_id, u32 value)
|
||||
{
|
||||
switch (oc_id) {
|
||||
case TIM_OC1:
|
||||
TIM_CCR1(timer_peripheral) = value;
|
||||
break;
|
||||
case TIM_OC2:
|
||||
TIM_CCR2(timer_peripheral) = value;
|
||||
break;
|
||||
case TIM_OC3:
|
||||
TIM_CCR3(timer_peripheral) = value;
|
||||
break;
|
||||
case TIM_OC4:
|
||||
TIM_CCR4(timer_peripheral) = value;
|
||||
break;
|
||||
case TIM_OC1N:
|
||||
case TIM_OC2N:
|
||||
case TIM_OC3N:
|
||||
/* Ignoring as this option applies to the whole channel. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_enable_break_main_output(u32 timer_peripheral)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) |= TIM_BDTR_MOE;
|
||||
}
|
||||
|
||||
void timer_disable_break_main_output(u32 timer_peripheral)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_MOE;
|
||||
}
|
||||
|
||||
void timer_enable_break_automatic_output(u32 timer_peripheral)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) |= TIM_BDTR_AOE;
|
||||
}
|
||||
|
||||
void timer_disable_break_automatic_output(u32 timer_peripheral)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_AOE;
|
||||
}
|
||||
|
||||
void timer_set_break_polarity_high(u32 timer_peripheral)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) |= TIM_BDTR_BKP;
|
||||
}
|
||||
|
||||
void timer_set_break_polarity_low(u32 timer_peripheral)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_BKP;
|
||||
}
|
||||
|
||||
void timer_enable_break(u32 timer_peripheral)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) |= TIM_BDTR_BKE;
|
||||
}
|
||||
|
||||
void timer_disable_break(u32 timer_peripheral)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_BKE;
|
||||
}
|
||||
|
||||
void timer_set_enabled_off_state_in_run_mode(u32 timer_peripheral)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) |= TIM_BDTR_OSSR;
|
||||
}
|
||||
|
||||
void timer_set_disabled_off_state_in_run_mode(u32 timer_peripheral)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_OSSR;
|
||||
}
|
||||
|
||||
void timer_set_enabled_off_state_in_idle_mode(u32 timer_peripheral)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) |= TIM_BDTR_OSSI;
|
||||
}
|
||||
|
||||
void timer_set_disabled_off_state_in_idle_mode(u32 timer_peripheral)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) &= ~TIM_BDTR_OSSI;
|
||||
}
|
||||
|
||||
void timer_set_break_lock(u32 timer_peripheral, u32 lock)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) |= lock;
|
||||
}
|
||||
|
||||
void timer_set_deadtime(u32 timer_peripheral, u32 deadtime)
|
||||
{
|
||||
if ((timer_peripheral == TIM1) || (timer_peripheral == TIM8))
|
||||
TIM_BDTR(timer_peripheral) |= deadtime;
|
||||
}
|
||||
|
||||
void timer_generate_event(u32 timer_peripheral, u32 event)
|
||||
{
|
||||
TIM_EGR(timer_peripheral) |= event;
|
||||
}
|
||||
|
||||
u32 timer_get_counter(u32 timer_peripheral)
|
||||
{
|
||||
return TIM_CNT(timer_peripheral);
|
||||
}
|
||||
296
lib/stm32/f1/vector.c
Normal file
296
lib/stm32/f1/vector.c
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define WEAK __attribute__ ((weak))
|
||||
|
||||
/* Symbols exported by linker script */
|
||||
extern unsigned _etext, _data, _edata, _ebss, _stack;
|
||||
|
||||
void main(void);
|
||||
void reset_handler(void);
|
||||
void blocking_handler(void);
|
||||
void null_handler(void);
|
||||
|
||||
void WEAK nmi_handler(void);
|
||||
void WEAK hard_fault_handler(void);
|
||||
void WEAK mem_manage_handler(void);
|
||||
void WEAK bus_fault_handler(void);
|
||||
void WEAK usage_fault_handler(void);
|
||||
void WEAK sv_call_handler(void);
|
||||
void WEAK debug_monitor_handler(void);
|
||||
void WEAK pend_sv_handler(void);
|
||||
void WEAK sys_tick_handler(void);
|
||||
void WEAK wwdg_isr(void);
|
||||
void WEAK pvd_isr(void);
|
||||
void WEAK tamper_isr(void);
|
||||
void WEAK rtc_isr(void);
|
||||
void WEAK flash_isr(void);
|
||||
void WEAK rcc_isr(void);
|
||||
void WEAK exti0_isr(void);
|
||||
void WEAK exti1_isr(void);
|
||||
void WEAK exti2_isr(void);
|
||||
void WEAK exti3_isr(void);
|
||||
void WEAK exti4_isr(void);
|
||||
void WEAK dma1_channel1_isr(void);
|
||||
void WEAK dma1_channel2_isr(void);
|
||||
void WEAK dma1_channel3_isr(void);
|
||||
void WEAK dma1_channel4_isr(void);
|
||||
void WEAK dma1_channel5_isr(void);
|
||||
void WEAK dma1_channel6_isr(void);
|
||||
void WEAK dma1_channel7_isr(void);
|
||||
void WEAK adc1_2_isr(void);
|
||||
void WEAK usb_hp_can_tx_isr(void);
|
||||
void WEAK usb_lp_can_rx0_isr(void);
|
||||
void WEAK can_rx1_isr(void);
|
||||
void WEAK can_sce_isr(void);
|
||||
void WEAK exti9_5_isr(void);
|
||||
void WEAK tim1_brk_isr(void);
|
||||
void WEAK tim1_up_isr(void);
|
||||
void WEAK tim1_trg_com_isr(void);
|
||||
void WEAK tim1_cc_isr(void);
|
||||
void WEAK tim2_isr(void);
|
||||
void WEAK tim3_isr(void);
|
||||
void WEAK tim4_isr(void);
|
||||
void WEAK i2c1_ev_isr(void);
|
||||
void WEAK i2c1_er_isr(void);
|
||||
void WEAK i2c2_ev_isr(void);
|
||||
void WEAK i2c2_er_isr(void);
|
||||
void WEAK spi1_isr(void);
|
||||
void WEAK spi2_isr(void);
|
||||
void WEAK usart1_isr(void);
|
||||
void WEAK usart2_isr(void);
|
||||
void WEAK usart3_isr(void);
|
||||
void WEAK exti15_10_isr(void);
|
||||
void WEAK rtc_alarm_isr(void);
|
||||
void WEAK usb_wakeup_isr(void);
|
||||
void WEAK tim8_brk_isr(void);
|
||||
void WEAK tim8_up_isr(void);
|
||||
void WEAK tim8_trg_com_isr(void);
|
||||
void WEAK tim8_cc_isr(void);
|
||||
void WEAK adc3_isr(void);
|
||||
void WEAK fsmc_isr(void);
|
||||
void WEAK sdio_isr(void);
|
||||
void WEAK tim5_isr(void);
|
||||
void WEAK spi3_isr(void);
|
||||
void WEAK usart4_isr(void);
|
||||
void WEAK usart5_isr(void);
|
||||
void WEAK tim6_isr(void);
|
||||
void WEAK tim7_isr(void);
|
||||
void WEAK dma2_channel1_isr(void);
|
||||
void WEAK dma2_channel2_isr(void);
|
||||
void WEAK dma2_channel3_isr(void);
|
||||
void WEAK dma2_channel4_5_isr(void);
|
||||
void WEAK dma2_channel5_isr(void);
|
||||
void WEAK eth_isr(void);
|
||||
void WEAK eth_wkup_isr(void);
|
||||
void WEAK can2_tx_isr(void);
|
||||
void WEAK can2_rx0_isr(void);
|
||||
void WEAK can2_rx1_isr(void);
|
||||
void WEAK can2_sce_isr(void);
|
||||
void WEAK otg_fs_isr(void);
|
||||
|
||||
|
||||
__attribute__ ((section(".vectors")))
|
||||
void (*const vector_table[]) (void) = {
|
||||
(void*)&_stack,
|
||||
reset_handler,
|
||||
nmi_handler,
|
||||
hard_fault_handler,
|
||||
mem_manage_handler,
|
||||
bus_fault_handler,
|
||||
usage_fault_handler,
|
||||
0, 0, 0, 0, /* Reserved */
|
||||
sv_call_handler,
|
||||
debug_monitor_handler,
|
||||
0, /* Reserved */
|
||||
pend_sv_handler,
|
||||
sys_tick_handler,
|
||||
wwdg_isr,
|
||||
pvd_isr,
|
||||
tamper_isr,
|
||||
rtc_isr,
|
||||
flash_isr,
|
||||
rcc_isr,
|
||||
exti0_isr,
|
||||
exti1_isr,
|
||||
exti2_isr,
|
||||
exti3_isr,
|
||||
exti4_isr,
|
||||
dma1_channel1_isr,
|
||||
dma1_channel2_isr,
|
||||
dma1_channel3_isr,
|
||||
dma1_channel4_isr,
|
||||
dma1_channel5_isr,
|
||||
dma1_channel6_isr,
|
||||
dma1_channel7_isr,
|
||||
adc1_2_isr,
|
||||
usb_hp_can_tx_isr,
|
||||
usb_lp_can_rx0_isr,
|
||||
can_rx1_isr,
|
||||
can_sce_isr,
|
||||
exti9_5_isr,
|
||||
tim1_brk_isr,
|
||||
tim1_up_isr,
|
||||
tim1_trg_com_isr,
|
||||
tim1_cc_isr,
|
||||
tim2_isr,
|
||||
tim3_isr,
|
||||
tim4_isr,
|
||||
i2c1_ev_isr,
|
||||
i2c1_er_isr,
|
||||
i2c2_ev_isr,
|
||||
i2c2_er_isr,
|
||||
spi1_isr,
|
||||
spi2_isr,
|
||||
usart1_isr,
|
||||
usart2_isr,
|
||||
usart3_isr,
|
||||
exti15_10_isr,
|
||||
rtc_alarm_isr,
|
||||
usb_wakeup_isr,
|
||||
tim8_brk_isr,
|
||||
tim8_up_isr,
|
||||
tim8_trg_com_isr,
|
||||
tim8_cc_isr,
|
||||
adc3_isr,
|
||||
fsmc_isr,
|
||||
sdio_isr,
|
||||
tim5_isr,
|
||||
spi3_isr,
|
||||
usart4_isr,
|
||||
usart5_isr,
|
||||
tim6_isr,
|
||||
tim7_isr,
|
||||
dma2_channel1_isr,
|
||||
dma2_channel2_isr,
|
||||
dma2_channel3_isr,
|
||||
dma2_channel4_5_isr,
|
||||
dma2_channel5_isr,
|
||||
eth_isr,
|
||||
eth_wkup_isr,
|
||||
can2_tx_isr,
|
||||
can2_rx0_isr,
|
||||
can2_rx1_isr,
|
||||
can2_sce_isr,
|
||||
otg_fs_isr,
|
||||
};
|
||||
|
||||
void reset_handler(void)
|
||||
{
|
||||
volatile unsigned *src, *dest;
|
||||
asm("MSR msp, %0" : : "r"(&_stack));
|
||||
|
||||
for (src = &_etext, dest = &_data; dest < &_edata; src++, dest++)
|
||||
*dest = *src;
|
||||
|
||||
while (dest < &_ebss)
|
||||
*dest++ = 0;
|
||||
|
||||
/* Call the application's entry point. */
|
||||
main();
|
||||
}
|
||||
|
||||
void blocking_handler(void)
|
||||
{
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
void null_handler(void)
|
||||
{
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
#pragma weak nmi_handler = null_handler
|
||||
#pragma weak hard_fault_handler = blocking_handler
|
||||
#pragma weak mem_manage_handler = blocking_handler
|
||||
#pragma weak bus_fault_handler = blocking_handler
|
||||
#pragma weak usage_fault_handler = blocking_handler
|
||||
#pragma weak sv_call_handler = null_handler
|
||||
#pragma weak debug_monitor_handler = null_handler
|
||||
#pragma weak pend_sv_handler = null_handler
|
||||
#pragma weak sys_tick_handler = null_handler
|
||||
#pragma weak wwdg_isr = null_handler
|
||||
#pragma weak pvd_isr = null_handler
|
||||
#pragma weak tamper_isr = null_handler
|
||||
#pragma weak rtc_isr = null_handler
|
||||
#pragma weak flash_isr = null_handler
|
||||
#pragma weak rcc_isr = null_handler
|
||||
#pragma weak exti0_isr = null_handler
|
||||
#pragma weak exti1_isr = null_handler
|
||||
#pragma weak exti2_isr = null_handler
|
||||
#pragma weak exti3_isr = null_handler
|
||||
#pragma weak exti4_isr = null_handler
|
||||
#pragma weak dma1_channel1_isr = null_handler
|
||||
#pragma weak dma1_channel2_isr = null_handler
|
||||
#pragma weak dma1_channel3_isr = null_handler
|
||||
#pragma weak dma1_channel4_isr = null_handler
|
||||
#pragma weak dma1_channel5_isr = null_handler
|
||||
#pragma weak dma1_channel6_isr = null_handler
|
||||
#pragma weak dma1_channel7_isr = null_handler
|
||||
#pragma weak adc1_2_isr = null_handler
|
||||
#pragma weak usb_hp_can_tx_isr = null_handler
|
||||
#pragma weak usb_lp_can_rx0_isr = null_handler
|
||||
#pragma weak can_rx1_isr = null_handler
|
||||
#pragma weak can_sce_isr = null_handler
|
||||
#pragma weak exti9_5_isr = null_handler
|
||||
#pragma weak tim1_brk_isr = null_handler
|
||||
#pragma weak tim1_up_isr = null_handler
|
||||
#pragma weak tim1_trg_com_isr = null_handler
|
||||
#pragma weak tim1_cc_isr = null_handler
|
||||
#pragma weak tim2_isr = null_handler
|
||||
#pragma weak tim3_isr = null_handler
|
||||
#pragma weak tim4_isr = null_handler
|
||||
#pragma weak i2c1_ev_isr = null_handler
|
||||
#pragma weak i2c1_er_isr = null_handler
|
||||
#pragma weak i2c2_ev_isr = null_handler
|
||||
#pragma weak i2c2_er_isr = null_handler
|
||||
#pragma weak spi1_isr = null_handler
|
||||
#pragma weak spi2_isr = null_handler
|
||||
#pragma weak usart1_isr = null_handler
|
||||
#pragma weak usart2_isr = null_handler
|
||||
#pragma weak usart3_isr = null_handler
|
||||
#pragma weak exti15_10_isr = null_handler
|
||||
#pragma weak rtc_alarm_isr = null_handler
|
||||
#pragma weak usb_wakeup_isr = null_handler
|
||||
#pragma weak tim8_brk_isr = null_handler
|
||||
#pragma weak tim8_up_isr = null_handler
|
||||
#pragma weak tim8_trg_com_isr = null_handler
|
||||
#pragma weak tim8_cc_isr = null_handler
|
||||
#pragma weak adc3_isr = null_handler
|
||||
#pragma weak fsmc_isr = null_handler
|
||||
#pragma weak sdio_isr = null_handler
|
||||
#pragma weak tim5_isr = null_handler
|
||||
#pragma weak spi3_isr = null_handler
|
||||
#pragma weak usart4_isr = null_handler
|
||||
#pragma weak usart5_isr = null_handler
|
||||
#pragma weak tim6_isr = null_handler
|
||||
#pragma weak tim7_isr = null_handler
|
||||
#pragma weak dma2_channel1_isr = null_handler
|
||||
#pragma weak dma2_channel2_isr = null_handler
|
||||
#pragma weak dma2_channel3_isr = null_handler
|
||||
#pragma weak dma2_channel4_5_isr = null_handler
|
||||
#pragma weak dma2_channel5_isr
|
||||
#pragma weak eth_isr = null_handler
|
||||
#pragma weak eth_wkup_isr = null_handler
|
||||
#pragma weak can2_tx_isr = null_handler
|
||||
#pragma weak can2_rx0_isr = null_handler
|
||||
#pragma weak can2_rx1_isr = null_handler
|
||||
#pragma weak can2_sce_isr = null_handler
|
||||
#pragma weak otg_fs_isr = null_handler
|
||||
|
||||
Reference in New Issue
Block a user