Merge branch 'master' of git://github.com/libopencm3/libopencm3 into upstream-merge

This commit is contained in:
Jeff Ciesielski
2012-11-13 11:06:21 -08:00
188 changed files with 9883 additions and 6293 deletions

View File

@@ -18,7 +18,16 @@
*/
#include <libopencm3/stm32/can.h>
#include <libopencm3/stm32/f1/rcc.h>
#if defined(STM32F1)
# include <libopencm3/stm32/f1/rcc.h>
#elif defined(STM32F2)
# include <libopencm3/stm32/f2/rcc.h>
#elif defined(STM32F4)
# include <libopencm3/stm32/f4/rcc.h>
#else
# error "stm32 family not defined."
#endif
void can_reset(u32 canport)
{
@@ -314,7 +323,7 @@ void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
/* Release the FIFO. */
if (release)
can_fifo_release(CAN1, 0);
can_fifo_release(canport, fifo);
}
bool can_available_mailbox(u32 canport)

View File

@@ -17,7 +17,7 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f1/desig.h>
#include <libopencm3/stm32/desig.h>
u16 desig_get_flash_size(void)
{

View File

@@ -2,6 +2,7 @@
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -15,11 +16,22 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* This provides the code for the "next gen" EXTI block provided in F2/F4/L1
* devices. (differences only in the source selection)
*/
#include <libopencm3/stm32/exti.h>
#include <libopencm3/stm32/f4/syscfg.h>
#include <libopencm3/stm32/syscfg.h>
#if defined(STM32F2)
#include <libopencm3/stm32/f2/gpio.h>
#elif defined(STM32F4)
#include <libopencm3/stm32/f4/gpio.h>
#elif defined(STM32L1)
#include <libopencm3/stm32/l1/gpio.h>
#else
#error "invalid/unknown stm32 family for this code"
#endif
void exti_set_trigger(u32 extis, exti_trigger_type trig)
{
@@ -121,12 +133,24 @@ void exti_select_source(u32 exti, u32 gpioport)
case GPIOE:
bits = 0xb;
break;
#if defined(STM32L1)
#else
case GPIOF:
bits = 0xa;
break;
case GPIOG:
bits = 0x9;
break;
#endif
case GPIOH:
bits = 0x8;
break;
#if defined(STM32L1)
#else
case GPIOI:
bits = 0x7;
break;
#endif
}
/* Ensure that only valid EXTI lines are used. */

View File

@@ -28,10 +28,11 @@ CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
-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 \
OBJS = rcc.o gpio.o usart.o adc.o spi.o flash.o \
rtc.o i2c.o dma.o exti.o ethernet.o \
usb_f103.o usb.o usb_control.o usb_standard.o can.o \
timer.o usb_f107.o desig.o crc.o assert.o dac.o iwdg.o pwr.o
timer.o usb_f107.o desig.o crc.o dac.o iwdg.o pwr.o \
usb_fx07_common.o
VPATH += ../../usb:../:../../cm3

View File

@@ -10,12 +10,18 @@
@date 18 August 2012
This library supports the DMA
Control System in the STM32F1xx series of ARM Cortex Microcontrollers
by ST Microelectronics. It can provide for two DMA controllers,
one with 7 channels and one with 5. Channels are hardware dedicated
and each is shared with a number of different sources (only one can be
used at a time, under the responsibility of the programmer).
This library supports the DMA Control System in the STM32 series of ARM Cortex
Microcontrollers by ST Microelectronics.
Up to two DMA controllers are supported. 12 DMA channels are allocated 7 to
the first DMA controller and 5 to the second. Each channel is connected to
between 3 and 6 hardware peripheral DMA signals in a logical OR arrangement.
DMA transfers can be configured to occur between peripheral and memory in
any combination including memory to memory. Circular mode transfers are
also supported in transfers involving a peripheral. An arbiter is provided
to resolve priority DMA requests. Transfers can be made with 8, 16 or 32 bit
words.
LGPL License Terms @ref lgpl_license
*/
@@ -67,6 +73,42 @@ void dma_channel_reset(u32 dma, u8 channel)
DMA_IFCR(dma) |= DMA_IFCR_CIF(channel);
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Channel Clear Interrupt Flag
The interrupt flag for the channel is cleared. More than one interrupt for the
same channel may be cleared by using the logical OR of the interrupt flags.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: @ref dma_st_number
@param[in] interrupts unsigned int32. Logical OR of interrupt numbers: @ref dma_if_offset
*/
void dma_clear_interrupt_flags(u32 dma, u8 channel, u32 interrupts)
{
/* Get offset to interrupt flag location in channel field */
u32 flags = (interrupts << DMA_FLAG_OFFSET(channel));
DMA_IFCR(dma) = flags;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Channel Read Interrupt Flag
The interrupt flag for the channel is returned.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: @ref dma_st_number
@param[in] interrupt unsigned int32. Interrupt number: @ref dma_st_number
@returns bool interrupt flag is set.
*/
bool dma_get_interrupt_flag(u32 dma, u8 channel, u32 interrupt)
{
/* get offset to interrupt flag location in channel field. */
u32 flag = (interrupt << DMA_FLAG_OFFSET(channel));
return ((DMA_ISR(dma) & flag) > 0);
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Memory to Memory Transfers
@@ -160,11 +202,39 @@ void dma_enable_memory_increment_mode(u32 dma, u8 channel)
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_disable_memory_increment_mode(u32 dma, u8 channel)
{
DMA_CCR(dma, channel) &= ~DMA_CCR_MINC;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Peripheral Increment after Transfer
Following each transfer the current peripheral address is incremented by
1, 2 or 4 depending on the data size set in @ref dma_set_peripheral_size. The
value held by the base peripheral address register is unchanged.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_enable_peripheral_increment_mode(u32 dma, u8 channel)
{
DMA_CCR(dma, channel) |= DMA_CCR_PINC;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Channel Disable Peripheral Increment after Transfer
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
void dma_disable_peripheral_increment_mode(u32 dma, u8 channel)
{
DMA_CCR(dma, channel) &= ~DMA_CCR_PINC;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Memory Circular Mode

View File

@@ -1,316 +0,0 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#define WEAK __attribute__ ((weak))
#define NAKED __attribute__((naked))
#include <stdint.h>
/* Symbols exported by the linker script(s): */
extern unsigned _data_loadaddr, _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 uart4_isr(void);
void WEAK uart5_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, /* Addr: 0x0000_0000 */
reset_handler, /* Addr: 0x0000_0004 */
nmi_handler, /* Addr: 0x0000_0008 */
hard_fault_handler, /* Addr: 0x0000_000C */
mem_manage_handler, /* Addr: 0x0000_0010 */
bus_fault_handler, /* Addr: 0x0000_0014 */
usage_fault_handler, /* Addr: 0x0000_0018 */
0, 0, 0, 0, /* Reserved Addr: 0x0000_001C - 0x0000_002B */
sv_call_handler, /* Addr: 0x0000_002C */
debug_monitor_handler, /* Addr: 0x0000_0030*/
0, /* Reserved Addr: 0x0000_00034 */
pend_sv_handler, /* Addr: 0x0000_0038 */
sys_tick_handler, /* Addr: 0x0000_003C */
wwdg_isr, /* Addr: 0x0000_0040 */
pvd_isr, /* Addr: 0x0000_0044 */
tamper_isr, /* Addr: 0x0000_0048 */
rtc_isr, /* Addr: 0x0000_004C */
flash_isr, /* Addr: 0x0000_0050 */
rcc_isr, /* Addr: 0x0000_0054 */
exti0_isr, /* Addr: 0x0000_0058 */
exti1_isr, /* Addr: 0x0000_005C */
exti2_isr, /* Addr: 0x0000_0060 */
exti3_isr, /* Addr: 0x0000_0064 */
exti4_isr, /* Addr: 0x0000_0068 */
dma1_channel1_isr, /* Addr: 0x0000_006C */
dma1_channel2_isr, /* Addr: 0x0000_0070 */
dma1_channel3_isr, /* Addr: 0x0000_0074 */
dma1_channel4_isr, /* Addr: 0x0000_0078 */
dma1_channel5_isr, /* Addr: 0x0000_007C */
dma1_channel6_isr, /* Addr: 0x0000_0080 */
dma1_channel7_isr, /* Addr: 0x0000_0084 */
adc1_2_isr, /* Addr: 0x0000_0088 */
usb_hp_can_tx_isr, /* Addr: 0x0000_008C */
usb_lp_can_rx0_isr, /* Addr: 0x0000_0090 */
can_rx1_isr, /* Addr: 0x0000_0094 */
can_sce_isr, /* Addr: 0x0000_0098 */
exti9_5_isr, /* Addr: 0x0000_009C */
tim1_brk_isr, /* Addr: 0x0000_00A0 */
tim1_up_isr, /* Addr: 0x0000_00A4 */
tim1_trg_com_isr, /* Addr: 0x0000_00A8 */
tim1_cc_isr, /* Addr: 0x0000_00AC */
tim2_isr, /* Addr: 0x0000_00B0 */
tim3_isr, /* Addr: 0x0000_00B4 */
tim4_isr, /* Addr: 0x0000_00B8 */
i2c1_ev_isr, /* Addr: 0x0000_00BC */
i2c1_er_isr, /* Addr: 0x0000_00C0 */
i2c2_ev_isr, /* Addr: 0x0000_00C4 */
i2c2_er_isr, /* Addr: 0x0000_00C8 */
spi1_isr, /* Addr: 0x0000_00CC */
spi2_isr, /* Addr: 0x0000_00D0 */
usart1_isr, /* Addr: 0x0000_00D4 */
usart2_isr, /* Addr: 0x0000_00D8 */
usart3_isr, /* Addr: 0x0000_00DC */
exti15_10_isr, /* Addr: 0x0000_00E0 */
rtc_alarm_isr, /* Addr: 0x0000_00E4 */
usb_wakeup_isr, /* Addr: 0x0000_00E8 */
tim8_brk_isr, /* Addr: 0x0000_00EC */
tim8_up_isr, /* Addr: 0x0000_00F0 */
tim8_trg_com_isr, /* Addr: 0x0000_00F4 */
tim8_cc_isr, /* Addr: 0x0000_00F8 */
adc3_isr, /* Addr: 0x0000_00FC */
fsmc_isr, /* Addr: 0x0000_0100 */
sdio_isr, /* Addr: 0x0000_0104 */
tim5_isr, /* Addr: 0x0000_0108 */
spi3_isr, /* Addr: 0x0000_010C */
uart4_isr, /* Addr: 0x0000_0110 */
uart5_isr, /* Addr: 0x0000_0114 */
tim6_isr, /* Addr: 0x0000_0118 */
tim7_isr, /* Addr: 0x0000_011C */
dma2_channel1_isr, /* Addr: 0x0000_0120 */
dma2_channel2_isr, /* Addr: 0x0000_0124 */
dma2_channel3_isr, /* Addr: 0x0000_0128 */
dma2_channel4_5_isr, /* Addr: 0x0000_012C */
dma2_channel5_isr, /* Addr: 0x0000_0130 */
eth_isr, /* Addr: 0x0000_0134 */
eth_wkup_isr, /* Addr: 0x0000_0138 */
can2_tx_isr, /* Addr: 0x0000_013C */
can2_rx0_isr, /* Addr: 0x0000_0140 */
can2_rx1_isr, /* Addr: 0x0000_0144 */
can2_sce_isr, /* Addr: 0x0000_0148 */
otg_fs_isr, /* Addr: 0x0000_014C */
};
void WEAK user_reset_hook(void);
void handle_dfu_bootloader(void)
{
uint32_t reset_str = *((uint32_t *)0x2000FFF0);
if (reset_str == 0xDEADBEEF) {
*((uint32_t *)0x2000FFF0) = 0x00;
asm("ldr r0, =0x1fffb000");
asm("ldr sp, [r0, #0]");
asm("ldr r0, [r0, #4]");
asm("bx r0");
}
}
void NAKED reset_handler(void)
{
volatile unsigned *src, *dest;
__asm__("MSR msp, %0" : : "r"(&_stack));
user_reset_hook();
for (src = &_data_loadaddr, 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 user_reset_hook = handle_dfu_bootloader
#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 uart4_isr = null_handler
#pragma weak uart5_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

View File

@@ -28,8 +28,8 @@ CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
-ffunction-sections -fdata-sections -MD -DSTM32F2
# ARFLAGS = rcsv
ARFLAGS = rcs
OBJS = vector.o rcc.o gpio.o usart.o spi.o flash.o nvic.o \
i2c.o systick.o exti.o scb.o timer.o assert.o
OBJS = rcc.o gpio2.o usart.o spi.o flash.o \
i2c.o exti2.o timer.o
VPATH += ../../usb:../:../../cm3

View File

@@ -1,146 +0,0 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Mark Butler <mbutler@physics.otago.ac.nz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/exti.h>
#include <libopencm3/stm32/f2/syscfg.h>
#include <libopencm3/stm32/f2/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) {
SYSCFG_EXTICR1 &= ~(0x000F << shift);
SYSCFG_EXTICR1 |= (~bits << shift);
} else if (exti < EXTI8) {
SYSCFG_EXTICR2 &= ~(0x000F << shift);
SYSCFG_EXTICR2 |= (~bits << shift);
} else if (exti < EXTI12) {
SYSCFG_EXTICR3 &= ~(0x000F << shift);
SYSCFG_EXTICR3 |= (~bits << shift);
} else if (exti < EXTI16) {
SYSCFG_EXTICR4 &= ~(0x000F << shift);
SYSCFG_EXTICR4 |= (~bits << shift);
}
}

View File

@@ -1,928 +0,0 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Edward Cheeseman <evbuilder@users.sourceforge.org>
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* 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/f2/timer.h>
#include <libopencm3/stm32/f2/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, u32 clock_div,
u32 alignment, u32 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);
}
void timer_set_option(u32 timer_peripheral, u32 option)
{
if (timer_peripheral == TIM2) {
TIM_OR(timer_peripheral) &= ~TIM2_OR_ITR1_RMP_MASK;
TIM_OR(timer_peripheral) |= option;
} else if (timer_peripheral == TIM5) {
TIM_OR(timer_peripheral) &= ~TIM5_OR_TI4_RMP_MASK;
TIM_OR(timer_peripheral) |= option;
}
}

View File

@@ -1,336 +0,0 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#define WEAK __attribute__ ((weak))
/* Symbols exported by the linker script(s): */
extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack;
void main(void);
void reset_handler(void);
void blocking_handler(void);
void null_handler(void);
void WEAK reset_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 tamp_stamp_isr(void);
void WEAK rtc_wkup_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_stream0_isr(void);
void WEAK dma1_stream1_isr(void);
void WEAK dma1_stream2_isr(void);
void WEAK dma1_stream3_isr(void);
void WEAK dma1_stream4_isr(void);
void WEAK dma1_stream5_isr(void);
void WEAK dma1_stream6_isr(void);
void WEAK adc_isr(void);
void WEAK can1_tx_isr(void);
void WEAK can1_rx0_isr(void);
void WEAK can1_rx1_isr(void);
void WEAK can1_sce_isr(void);
void WEAK exti9_5_isr(void);
void WEAK tim1_brk_tim9_isr(void);
void WEAK tim1_up_tim10_isr(void);
void WEAK tim1_trg_com_tim11_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_fs_wkup_isr(void);
void WEAK tim8_brk_tim12_isr(void);
void WEAK tim8_up_tim13_isr(void);
void WEAK tim8_trg_com_tim14_isr(void);
void WEAK tim8_cc_isr(void);
void WEAK dma1_stream7_isr(void);
void WEAK fsmc_isr(void);
void WEAK sdio_isr(void);
void WEAK tim5_isr(void);
void WEAK spi3_isr(void);
void WEAK uart4_isr(void);
void WEAK uart5_isr(void);
void WEAK tim6_dac_isr(void);
void WEAK tim7_isr(void);
void WEAK dma2_stream0_isr(void);
void WEAK dma2_stream1_isr(void);
void WEAK dma2_stream2_isr(void);
void WEAK dma2_stream3_isr(void);
void WEAK dma2_stream4_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);
void WEAK dma2_stream5_isr(void);
void WEAK dma2_stream6_isr(void);
void WEAK dma2_stream7_isr(void);
void WEAK usart6_isr(void);
void WEAK i2c3_ev_isr(void);
void WEAK i2c3_er_isr(void);
void WEAK otg_hs_ep1_out_isr(void);
void WEAK otg_hs_ep1_in_isr(void);
void WEAK otg_hs_wkup_isr(void);
void WEAK otg_hs_isr(void);
void WEAK dcmi_isr(void);
void WEAK cryp_isr(void);
void WEAK hash_rng_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,
tamp_stamp_isr,
rtc_wkup_isr,
flash_isr,
rcc_isr,
exti0_isr,
exti1_isr,
exti2_isr,
exti3_isr,
exti4_isr,
dma1_stream0_isr,
dma1_stream1_isr,
dma1_stream2_isr,
dma1_stream3_isr,
dma1_stream4_isr,
dma1_stream5_isr,
dma1_stream6_isr,
adc_isr,
can1_tx_isr,
can1_rx0_isr,
can1_rx1_isr,
can1_sce_isr,
exti9_5_isr,
tim1_brk_tim9_isr,
tim1_up_tim10_isr,
tim1_trg_com_tim11_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_fs_wkup_isr,
tim8_brk_tim12_isr,
tim8_up_tim13_isr,
tim8_trg_com_tim14_isr,
tim8_cc_isr,
dma1_stream7_isr,
fsmc_isr,
sdio_isr,
tim5_isr,
spi3_isr,
uart4_isr,
uart5_isr,
tim6_dac_isr,
tim7_isr,
dma2_stream0_isr,
dma2_stream1_isr,
dma2_stream2_isr,
dma2_stream3_isr,
dma2_stream4_isr,
eth_isr,
eth_wkup_isr,
can2_tx_isr,
can2_rx0_isr,
can2_rx1_isr,
can2_sce_isr,
otg_fs_isr,
dma2_stream5_isr,
dma2_stream6_isr,
dma2_stream7_isr,
usart6_isr,
i2c3_ev_isr,
i2c3_er_isr,
otg_hs_ep1_out_isr,
otg_hs_ep1_in_isr,
otg_hs_wkup_isr,
otg_hs_isr,
dcmi_isr,
cryp_isr,
hash_rng_isr,
};
void reset_handler(void)
{
volatile unsigned *src, *dest;
__asm__("MSR msp, %0" : : "r"(&_stack));
for (src = &_data_loadaddr, 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 tamp_stamp_isr = null_handler
#pragma weak rtc_wkup_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_stream0_isr = null_handler
#pragma weak dma1_stream1_isr = null_handler
#pragma weak dma1_stream2_isr = null_handler
#pragma weak dma1_stream3_isr = null_handler
#pragma weak dma1_stream4_isr = null_handler
#pragma weak dma1_stream5_isr = null_handler
#pragma weak dma1_stream6_isr = null_handler
#pragma weak adc_isr = null_handler
#pragma weak can1_tx_isr = null_handler
#pragma weak can1_rx0_isr = null_handler
#pragma weak can1_rx1_isr = null_handler
#pragma weak can1_sce_isr = null_handler
#pragma weak exti9_5_isr = null_handler
#pragma weak tim1_brk_tim9_isr = null_handler
#pragma weak tim1_up_tim10_isr = null_handler
#pragma weak tim1_trg_com_tim11_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_fs_wkup_isr = null_handler
#pragma weak tim8_brk_tim12_isr = null_handler
#pragma weak tim8_up_tim13_isr = null_handler
#pragma weak tim8_trg_com_tim14_isr = null_handler
#pragma weak tim8_cc_isr = null_handler
#pragma weak dma1_stream7_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 uart4_isr = null_handler
#pragma weak uart5_isr = null_handler
#pragma weak tim6_dac_isr = null_handler
#pragma weak tim7_isr = null_handler
#pragma weak dma2_stream0_isr = null_handler
#pragma weak dma2_stream1_isr = null_handler
#pragma weak dma2_stream2_isr = null_handler
#pragma weak dma2_stream3_isr = null_handler
#pragma weak dma2_stream4_isr = null_handler
#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
#pragma weak dma2_stream5_isr = null_handler
#pragma weak dma2_stream6_isr = null_handler
#pragma weak dma2_stream7_isr = null_handler
#pragma weak usart6_isr = null_handler
#pragma weak i2c3_ev_isr = null_handler
#pragma weak i2c3_er_isr = null_handler
#pragma weak otg_hs_ep1_out_isr = null_handler
#pragma weak otg_hs_ep1_in_isr = null_handler
#pragma weak otg_hs_wkup_isr = null_handler
#pragma weak otg_hs_isr = null_handler
#pragma weak dcmi_isr = null_handler
#pragma weak cryp_isr = null_handler
#pragma weak hash_rng_isr = null_handler

View File

@@ -29,10 +29,10 @@ CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
-ffunction-sections -fdata-sections -MD -DSTM32F4
# ARFLAGS = rcsv
ARFLAGS = rcs
OBJS = vector.o rcc.o gpio.o usart.o spi.o flash.o nvic.o \
i2c.o systick.o exti.o scb.o pwr.o timer.o \
usb.o usb_standard.o usb_control.o usb_f107.o \
assert.o
OBJS = rcc.o gpio2.o usart.o spi.o flash.o \
i2c.o exti2.o pwr.o timer.o \
usb.o usb_standard.o usb_control.o usb_fx07_common.o usb_f107.o \
usb_f207.o adc.o dma.o
VPATH += ../../usb:../:../../cm3

1027
lib/stm32/f4/adc.c Normal file

File diff suppressed because it is too large Load Diff

772
lib/stm32/f4/dma.c Normal file
View File

@@ -0,0 +1,772 @@
/** @defgroup STM32F4xx-dma-file DMA
@ingroup STM32F4xx
@brief <b>libopencm3 STM32F4xx DMA Controller</b>
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
@date 18 October 2012
This library supports the DMA Control System in the STM32F2 and STM32F4
series of ARM Cortex Microcontrollers by ST Microelectronics.
Up to two DMA controllers are supported each with 8 streams, and each stream
having up to 8 channels hardware dedicated to various peripheral DMA signals.
DMA transfers can be configured to occur between peripheral and memory in
either direction, and memory to memory. Peripheral to peripheral transfer
is not supported. Circular mode transfers are also supported in transfers
involving a peripheral. An arbiter is provided to resolve priority DMA
requests. Transfers can be made with 8, 16 or 32 bit words.
Each stream has access to a 4 word deep FIFO and can use double buffering
by means of two memory pointers. When using the FIFO it is possible to
configure transfers to occur in indivisible bursts.
It is also possible to select a peripheral to control the flow of data rather
than the DMA controller. This limits the functionality but is udeful when the
number of transfers is unknown.
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/f4/dma.h>
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Reset
The specified stream is disabled and configuration registers are cleared.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_stream_reset(u32 dma, u8 stream)
{
/* Disable stream (must be done before register is otherwise changed). */
DMA_SCR(dma, stream) &= ~DMA_SCR_EN;
/* Reset all config bits. */
DMA_SCR(dma, stream) = 0;
/* Reset data transfer number. */
DMA_SNDTR(dma, stream) = 0;
/* Reset peripheral and memory addresses. */
DMA_SPAR(dma, stream) = 0;
DMA_SM0AR(dma, stream) = 0;
DMA_SM1AR(dma, stream) = 0;
/* This is the default setting */
DMA_SFCR(dma, stream) = 0x21;
/* Reset all stream interrupt flags using the interrupt flag clear register. */
u32 mask = DMA_ISR_MASK(stream);
if (stream < 4)
{
DMA_LIFCR(dma) |= mask;
}
else
{
DMA_HIFCR(dma) |= mask;
}
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Clear Interrupt Flag
The interrupt flag for the stream is cleared. More than one interrupt for the
same stream may be cleared by using the logical OR of the interrupt flags.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] interrupts unsigned int32. Logical OR of interrupt numbers: @ref dma_if_offset
*/
void dma_clear_interrupt_flags(u32 dma, u8 stream, u32 interrupts)
{
/* Get offset to interrupt flag location in stream field */
u32 flags = (interrupts << DMA_ISR_OFFSET(stream));
/* First four streams are in low register. Flag clear must be set then reset. */
if (stream < 4)
{
DMA_LIFCR(dma) = flags;
}
else
{
DMA_HIFCR(dma) = flags;
}
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Read Interrupt Flag
The interrupt flag for the stream is returned.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] interrupt unsigned int32. Interrupt number: @ref dma_if_offset
@returns bool interrupt flag is set.
*/
bool dma_get_interrupt_flag(u32 dma, u8 stream, u32 interrupt)
{
/* get offset to interrupt flag location in stream field.
Assumes stream and interrupt parameters are integers */
u32 flag = (interrupt << DMA_ISR_OFFSET(stream));
/* First four streams are in low register */
if (stream < 4) return ((DMA_LISR(dma) & flag) > 0);
else return ((DMA_HISR(dma) & flag) > 0);
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Transfer Direction
Set peripheral to memory, memory to peripheral or memory to memory. If memory
to memory mode is selected, circular mode and double buffer modes are disabled.
Ensure that these modes are not enabled at a later time.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] direction unsigned int32. Data transfer direction @ref dma_st_dir
*/
void dma_set_transfer_mode(u32 dma, u8 stream, u32 direction)
{
u32 reg32 = (DMA_SCR(dma, stream) & ~DMA_SCR_DIR_MASK);
/* Disable circular and double buffer modes if memory to memory transfers
are in effect (Direct Mode is automatically disabled by hardware) */
if (direction == DMA_SCR_DIR_MEM2MEM)
{
reg32 &= ~(DMA_SCR_CIRC | DMA_SCR_DBM);
}
DMA_SCR(dma, stream) = (reg32 | direction);
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Set Priority
Stream Priority has four levels: low to very high. This has precedence over the
hardware priority. In the event of equal software priority the lower numbered
stream has priority.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] prio unsigned int32. Priority level @ref dma_st_pri.
*/
void dma_set_priority(u32 dma, u8 stream, u32 prio)
{
DMA_SCR(dma, stream) &= ~(DMA_SCR_PL_MASK);
DMA_SCR(dma, stream) |= prio;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Set Memory Word Width
Set the memory word width 8 bits, 16 bits, or 32 bits. Refer to datasheet for
alignment information if the source and destination widths do not match.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] mem_size unsigned int32. Memory word width @ref dma_st_memwidth.
*/
void dma_set_memory_size(u32 dma, u8 stream, u32 mem_size)
{
DMA_SCR(dma, stream) &= ~(DMA_SCR_MSIZE_MASK);
DMA_SCR(dma, stream) |= mem_size;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Set Peripheral Word Width
Set the peripheral word width 8 bits, 16 bits, or 32 bits. Refer to datasheet for
alignment information if the source and destination widths do not match, or
if the peripheral does not support byte or half-word writes.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] peripheral_size unsigned int32. Peripheral word width @ref dma_st_perwidth.
*/
void dma_set_peripheral_size(u32 dma, u8 stream, u32 peripheral_size)
{
DMA_SCR(dma, stream) &= ~(DMA_SCR_PSIZE_MASK);
DMA_SCR(dma, stream) |= peripheral_size;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Memory Increment after Transfer
Following each transfer the current memory address is incremented by
1, 2 or 4 depending on the data size set in @ref dma_set_memory_size. The
value held by the base memory address register is unchanged.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_memory_increment_mode(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) |= DMA_SCR_MINC;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Channel Disable Memory Increment after Transfer
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_memory_increment_mode(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) &= ~DMA_SCR_MINC;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Variable Sized Peripheral Increment after Transfer
Following each transfer the current peripheral address is incremented by
1, 2 or 4 depending on the data size set in @ref dma_set_peripheral_size. The
value held by the base peripheral address register is unchanged.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_peripheral_increment_mode(u32 dma, u8 stream)
{
u32 reg32 = (DMA_SCR(dma, stream) | DMA_SCR_PINC);
DMA_SCR(dma, stream) = (reg32 & ~DMA_SCR_PINCOS);
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Channel Disable Peripheral Increment after Transfer
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_peripheral_increment_mode(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) &= ~DMA_SCR_PINC;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Fixed Sized Peripheral Increment after Transfer
Following each transfer the current peripheral address is incremented by
4 regardless of the data size. The value held by the base peripheral address
register is unchanged.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_fixed_peripheral_increment_mode(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) |= (DMA_SCR_PINC | DMA_SCR_PINCOS);
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Memory Circular Mode
After the number of bytes/words to be transferred has been completed, the
original transfer block size, memory and peripheral base addresses are
reloaded and the process repeats.
Ensure that the stream is disabled otherwise the setting will not be changed.
@note This cannot be used with memory to memory mode. It is disabled
automatically if the peripheral is selected as the flow controller.
It is enabled automatically if double buffered mode is selected.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_circular_mode(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) |= DMA_SCR_CIRC;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Channel Select
Associate an input channel to the stream. Not every channel is allocated to a
hardware DMA request signal. The allocations for each stream are given in the
STM32F4 Reference Manual.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] channel unsigned int8. Channel selection @ref dma_ch_sel
*/
void dma_channel_select(u32 dma, u8 stream, u32 channel)
{
DMA_SCR(dma, stream) |= channel;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Set Memory Burst Configuration
Set the memory burst type to none, 4 8 or 16 word length. This is forced to none
if direct mode is used.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] burst unsigned int8. Memory Burst selection @ref dma_mburst
*/
void dma_set_memory_burst(u32 dma, u8 stream, u32 burst)
{
u32 reg32 = (DMA_SCR(dma, stream) & ~DMA_SCR_MBURST_MASK);
DMA_SCR(dma, stream) = (reg32 | burst);
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Set Peripheral Burst Configuration
Set the memory burst type to none, 4 8 or 16 word length. This is forced to none
if direct mode is used.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] burst unsigned int8. Peripheral Burst selection @ref dma_pburst
*/
void dma_set_peripheral_burst(u32 dma, u8 stream, u32 burst)
{
u32 reg32 = (DMA_SCR(dma, stream) & ~DMA_SCR_PBURST_MASK);
DMA_SCR(dma, stream) = (reg32 | burst);
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Set Initial Target Memory
In double buffered mode, set the target memory (M0 or M1) to be used for the first
transfer.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] memory unsigned int8. Initial memory pointer to use: 0 or 1
*/
void dma_set_initial_target(u32 dma, u8 stream, u8 memory)
{
u32 reg32 = (DMA_SCR(dma, stream) & ~DMA_SCR_CT);
if (memory == 1) reg32 |= DMA_SCR_CT;
DMA_SCR(dma, stream) = reg32;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Read Current Memory Target
In double buffer mode, return the current memory target (M0 or M1). It is possible
to update the memory pointer in the register that is <b> not </b> currently in
use. An attempt to change the register currently in use will cause the stream
to be disabled and the transfer error flag to be set.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@returns unsigned int8. Memory buffer in use: 0 or 1
*/
u8 dma_get_target(u32 dma, u8 stream)
{
if (DMA_SCR(dma, stream) & DMA_SCR_CT) return 1;
return 0;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Double Buffer Mode
Double buffer mode is used for memory to/from peripheral transfers only, and in
circular mode which is automatically enabled. Two memory buffers must be
established with pointers stored in the memory pointer registers.
Ensure that the stream is disabled otherwise the setting will not be changed.
@note This cannot be used with memory to memory mode.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_double_buffer_mode(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) |= DMA_SCR_DBM;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Set Peripheral Flow Control
Set the peripheral to control DMA flow. Useful when the number of transfers is
unknown. This is forced off when memory to memory mode is selected.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_set_peripheral_flow_control(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) |= DMA_SCR_PFCTRL;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Set DMA Flow Control
Set the DMA controller to control DMA flow. This is the default.
Ensure that the stream is disabled otherwise the setting will not be changed.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_set_dma_flow_control(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) &= ~DMA_SCR_PFCTRL;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Interrupt on Transfer Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_transfer_error_interrupt(u32 dma, u8 stream)
{
dma_clear_interrupt_flags(dma, stream, DMA_ISR_TEIF);
DMA_SCR(dma, stream) |= DMA_SCR_TEIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Disable Interrupt on Transfer Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_transfer_error_interrupt(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) &= ~DMA_SCR_TEIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Interrupt on Transfer Half Complete
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_half_transfer_interrupt(u32 dma, u8 stream)
{
dma_clear_interrupt_flags(dma, stream, DMA_ISR_HTIF);
DMA_SCR(dma, stream) |= DMA_SCR_HTIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Disable Interrupt on Transfer Half Complete
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_half_transfer_interrupt(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) &= ~DMA_SCR_HTIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Interrupt on Transfer Complete
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_transfer_complete_interrupt(u32 dma, u8 stream)
{
dma_clear_interrupt_flags(dma, stream, DMA_ISR_TCIF);
DMA_SCR(dma, stream) |= DMA_SCR_TCIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Disable Interrupt on Transfer Complete
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_transfer_complete_interrupt(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) &= ~DMA_SCR_TCIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Enable Interrupt on Direct Mode Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_direct_mode_error_interrupt(u32 dma, u8 stream)
{
dma_clear_interrupt_flags(dma, stream, DMA_ISR_DMEIF);
DMA_SCR(dma, stream) |= DMA_SCR_DMEIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Disable Interrupt on Direct Mode Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_direct_mode_error_interrupt(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) &= ~DMA_SCR_DMEIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Enable Interrupt on FIFO Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_fifo_error_interrupt(u32 dma, u8 stream)
{
dma_clear_interrupt_flags(dma, stream, DMA_ISR_FEIF);
DMA_SFCR(dma, stream) |= DMA_FCR_FEIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Disable Interrupt on FIFO Error
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_fifo_error_interrupt(u32 dma, u8 stream)
{
DMA_SFCR(dma, stream) &= ~DMA_FCR_FEIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Get FIFO Status
Status of FIFO (empty. full or partial filled states) is returned. This has no
meaning if direct mode is enabled (as the FIFO is not used).
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@returns u32 FIFO Status @ref dma_fifo_status
*/
u32 dma_fifo_status(u32 dma, u8 stream)
{
return (DMA_SFCR(dma, stream) & DMA_FCR_FS_MASK);
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Enable Direct Mode
Direct mode is the default. Data is transferred as soon as a DMA request is
received. The FIFO is not used. This must not be set when memory to memory
mode is selected.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_direct_mode(u32 dma, u8 stream)
{
DMA_SFCR(dma, stream) &= ~DMA_FCR_DMDIS;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Enable FIFO Mode
Data is transferred via a FIFO.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_fifo_mode(u32 dma, u8 stream)
{
DMA_SFCR(dma, stream) |= DMA_FCR_DMDIS;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Set FIFO Threshold
This is the filled level at which data is transferred out of the FIFO to the
destination.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] threshold unsigned int8. Threshold setting @ref dma_fifo_thresh
*/
void dma_set_fifo_threshold(u32 dma, u8 stream, u32 threshold)
{
u32 reg32 = (DMA_SFCR(dma, stream) & ~DMA_FCR_FTH_MASK);
DMA_SFCR(dma, stream) = (reg32 | threshold);
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Enable
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_enable_stream(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) |= DMA_SCR_EN;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Disable
@note The DMA stream registers retain their values when the stream is disabled.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
*/
void dma_disable_stream(u32 dma, u8 stream)
{
DMA_SCR(dma, stream) &= ~DMA_SCR_EN;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Set the Peripheral Address
Set the address of the peripheral register to or from which data is to be transferred.
Refer to the documentation for the specific peripheral.
@note The DMA stream must be disabled before setting this address. This function
has no effect if the stream is enabled.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] address unsigned int32. Peripheral Address.
*/
void dma_set_peripheral_address(u32 dma, u8 stream, u32 address)
{
if (!(DMA_SCR(dma, stream) & DMA_SCR_EN))
DMA_SPAR(dma, stream) = (u32) address;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Set the Base Memory Address 0
Set the address pointer to the memory location for DMA transfers. The DMA stream
must normally be disabled before setting this address, however it is possible
to change this in double buffer mode when the current target is memory area 1
(see @ref dma_get_target).
This is the default base memory address used in direct mode.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] address unsigned int32. Memory Initial Address.
*/
void dma_set_memory_address(u32 dma, u8 stream, u32 address)
{
u32 reg32 = DMA_SCR(dma, stream);
if ( !(reg32 & DMA_SCR_EN) || ((reg32 & DMA_SCR_CT) && (reg32 & DMA_SCR_DBM)) )
DMA_SM0AR(dma, stream) = (u32) address;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Set the Base Memory Address 1
Set the address pointer to the memory location for DMA transfers. The DMA stream
must normally be disabled before setting this address, however it is possible
to change this in double buffer mode when the current target is memory area 0
(see @ref dma_get_target).
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] address unsigned int32. Memory Initial Address.
*/
void dma_set_memory_address_1(u32 dma, u8 stream, u32 address)
{
u32 reg32 = DMA_SCR(dma, stream);
if ( !(reg32 & DMA_SCR_EN) || (!(reg32 & DMA_SCR_CT) && (reg32 & DMA_SCR_DBM)) )
DMA_SM1AR(dma, stream) = (u32) address;
}
/*-----------------------------------------------------------------------------*/
/** @brief DMA Stream Set the Transfer Block Size
@note The DMA stream must be disabled before setting this count value. The count
is not changed if the stream is enabled.
@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
@param[in] stream unsigned int8. Stream number: @ref dma_st_number
@param[in] number unsigned int16. Number of data words to transfer (65535 maximum).
*/
void dma_set_number_of_data(u32 dma, u8 stream, u16 number)
{
DMA_SNDTR(dma, stream) = number;
}
/**@}*/

View File

@@ -1,142 +0,0 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f4/gpio.h>
void gpio_mode_setup(u32 gpioport, u8 mode, u8 pull_up_down, u16 gpios)
{
u16 i;
u32 moder, pupd;
/*
* We want to set the config only for the pins mentioned in gpios,
* but keeping the others, so read out the actual config first.
*/
moder = GPIO_MODER(gpioport);
pupd = GPIO_PUPDR(gpioport);
for (i = 0; i < 16; i++) {
if (!((1 << i) & gpios))
continue;
moder &= ~GPIO_MODE_MASK(i);
moder |= GPIO_MODE(i, mode);
pupd &= ~GPIO_PUPD_MASK(i);
pupd |= GPIO_PUPD(i, pull_up_down);
}
/* Set mode and pull up/down control registers. */
GPIO_MODER(gpioport) = moder;
GPIO_PUPDR(gpioport) = pupd;
}
void gpio_set_output_options(u32 gpioport, u8 otype, u8 speed, u16 gpios)
{
u16 i;
u32 ospeedr;
if (otype == 0x1)
GPIO_OTYPER(gpioport) |= gpios;
else
GPIO_OTYPER(gpioport) &= ~gpios;
ospeedr = GPIO_OSPEEDR(gpioport);
for (i = 0; i < 16; i++) {
if (!((1 << i) & gpios))
continue;
ospeedr &= ~GPIO_OSPEED_MASK(i);
ospeedr |= GPIO_OSPEED(i, speed);
}
GPIO_OSPEEDR(gpioport) = ospeedr;
}
void gpio_set_af(u32 gpioport, u8 alt_func_num, u16 gpios)
{
u16 i;
u32 afrl, afrh;
afrl = GPIO_AFRL(gpioport);
afrh = GPIO_AFRH(gpioport);
for (i = 0; i < 8; i++) {
if (!((1 << i) & gpios))
continue;
afrl &= ~GPIO_AFR_MASK(i);
afrl |= GPIO_AFR(i, alt_func_num);
}
for (i = 8; i < 16; i++) {
if (!((1 << i) & gpios))
continue;
afrl &= ~GPIO_AFR_MASK(i - 8);
afrh |= GPIO_AFR(i - 8, alt_func_num);
}
GPIO_AFRL(gpioport) = afrl;
GPIO_AFRH(gpioport) = afrh;
}
void gpio_set(u32 gpioport, u16 gpios)
{
GPIO_BSRR(gpioport) = gpios;
}
void gpio_clear(u32 gpioport, u16 gpios)
{
GPIO_BSRR(gpioport) = gpios << 16;
}
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. */
/* Tell the compiler the variable is actually used. It will get optimized out anyways. */
reg32 = reg32;
/* If (reg32 & GPIO_LCKK) is true, the lock is now active. */
}

View File

@@ -1,928 +0,0 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Edward Cheeseman <evbuilder@users.sourceforge.org>
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* 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/f4/timer.h>
#include <libopencm3/stm32/f4/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, u32 clock_div,
u32 alignment, u32 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);
}
void timer_set_option(u32 timer_peripheral, u32 option)
{
if (timer_peripheral == TIM2) {
TIM_OR(timer_peripheral) &= ~TIM2_OR_ITR1_RMP_MASK;
TIM_OR(timer_peripheral) |= option;
} else if (timer_peripheral == TIM5) {
TIM_OR(timer_peripheral) &= ~TIM5_OR_TI4_RMP_MASK;
TIM_OR(timer_peripheral) |= option;
}
}

View File

@@ -1,341 +0,0 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f4/scb.h>
#define WEAK __attribute__ ((weak))
/* Symbols exported by the linker script(s): */
extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack;
void main(void);
void reset_handler(void);
void blocking_handler(void);
void null_handler(void);
void WEAK reset_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 tamp_stamp_isr(void);
void WEAK rtc_wkup_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_stream0_isr(void);
void WEAK dma1_stream1_isr(void);
void WEAK dma1_stream2_isr(void);
void WEAK dma1_stream3_isr(void);
void WEAK dma1_stream4_isr(void);
void WEAK dma1_stream5_isr(void);
void WEAK dma1_stream6_isr(void);
void WEAK adc_isr(void);
void WEAK can1_tx_isr(void);
void WEAK can1_rx0_isr(void);
void WEAK can1_rx1_isr(void);
void WEAK can1_sce_isr(void);
void WEAK exti9_5_isr(void);
void WEAK tim1_brk_tim9_isr(void);
void WEAK tim1_up_tim10_isr(void);
void WEAK tim1_trg_com_tim11_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_fs_wkup_isr(void);
void WEAK tim8_brk_tim12_isr(void);
void WEAK tim8_up_tim13_isr(void);
void WEAK tim8_trg_com_tim14_isr(void);
void WEAK tim8_cc_isr(void);
void WEAK dma1_stream7_isr(void);
void WEAK fsmc_isr(void);
void WEAK sdio_isr(void);
void WEAK tim5_isr(void);
void WEAK spi3_isr(void);
void WEAK uart4_isr(void);
void WEAK uart5_isr(void);
void WEAK tim6_dac_isr(void);
void WEAK tim7_isr(void);
void WEAK dma2_stream0_isr(void);
void WEAK dma2_stream1_isr(void);
void WEAK dma2_stream2_isr(void);
void WEAK dma2_stream3_isr(void);
void WEAK dma2_stream4_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);
void WEAK dma2_stream5_isr(void);
void WEAK dma2_stream6_isr(void);
void WEAK dma2_stream7_isr(void);
void WEAK usart6_isr(void);
void WEAK i2c3_ev_isr(void);
void WEAK i2c3_er_isr(void);
void WEAK otg_hs_ep1_out_isr(void);
void WEAK otg_hs_ep1_in_isr(void);
void WEAK otg_hs_wkup_isr(void);
void WEAK otg_hs_isr(void);
void WEAK dcmi_isr(void);
void WEAK cryp_isr(void);
void WEAK hash_rng_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,
tamp_stamp_isr,
rtc_wkup_isr,
flash_isr,
rcc_isr,
exti0_isr,
exti1_isr,
exti2_isr,
exti3_isr,
exti4_isr,
dma1_stream0_isr,
dma1_stream1_isr,
dma1_stream2_isr,
dma1_stream3_isr,
dma1_stream4_isr,
dma1_stream5_isr,
dma1_stream6_isr,
adc_isr,
can1_tx_isr,
can1_rx0_isr,
can1_rx1_isr,
can1_sce_isr,
exti9_5_isr,
tim1_brk_tim9_isr,
tim1_up_tim10_isr,
tim1_trg_com_tim11_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_fs_wkup_isr,
tim8_brk_tim12_isr,
tim8_up_tim13_isr,
tim8_trg_com_tim14_isr,
tim8_cc_isr,
dma1_stream7_isr,
fsmc_isr,
sdio_isr,
tim5_isr,
spi3_isr,
uart4_isr,
uart5_isr,
tim6_dac_isr,
tim7_isr,
dma2_stream0_isr,
dma2_stream1_isr,
dma2_stream2_isr,
dma2_stream3_isr,
dma2_stream4_isr,
eth_isr,
eth_wkup_isr,
can2_tx_isr,
can2_rx0_isr,
can2_rx1_isr,
can2_sce_isr,
otg_fs_isr,
dma2_stream5_isr,
dma2_stream6_isr,
dma2_stream7_isr,
usart6_isr,
i2c3_ev_isr,
i2c3_er_isr,
otg_hs_ep1_out_isr,
otg_hs_ep1_in_isr,
otg_hs_wkup_isr,
otg_hs_isr,
dcmi_isr,
cryp_isr,
hash_rng_isr,
};
void reset_handler(void)
{
volatile unsigned *src, *dest;
__asm__("MSR msp, %0" : : "r"(&_stack));
/* Enable access to Floating-Point coprocessor. */
SCB_CPACR |= SCB_CPACR_FULL * (SCB_CPACR_CP10 | SCB_CPACR_CP11);
for (src = &_data_loadaddr, 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 tamp_stamp_isr = null_handler
#pragma weak rtc_wkup_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_stream0_isr = null_handler
#pragma weak dma1_stream1_isr = null_handler
#pragma weak dma1_stream2_isr = null_handler
#pragma weak dma1_stream3_isr = null_handler
#pragma weak dma1_stream4_isr = null_handler
#pragma weak dma1_stream5_isr = null_handler
#pragma weak dma1_stream6_isr = null_handler
#pragma weak adc_isr = null_handler
#pragma weak can1_tx_isr = null_handler
#pragma weak can1_rx0_isr = null_handler
#pragma weak can1_rx1_isr = null_handler
#pragma weak can1_sce_isr = null_handler
#pragma weak exti9_5_isr = null_handler
#pragma weak tim1_brk_tim9_isr = null_handler
#pragma weak tim1_up_tim10_isr = null_handler
#pragma weak tim1_trg_com_tim11_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_fs_wkup_isr = null_handler
#pragma weak tim8_brk_tim12_isr = null_handler
#pragma weak tim8_up_tim13_isr = null_handler
#pragma weak tim8_trg_com_tim14_isr = null_handler
#pragma weak tim8_cc_isr = null_handler
#pragma weak dma1_stream7_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 uart4_isr = null_handler
#pragma weak uart5_isr = null_handler
#pragma weak tim6_dac_isr = null_handler
#pragma weak tim7_isr = null_handler
#pragma weak dma2_stream0_isr = null_handler
#pragma weak dma2_stream1_isr = null_handler
#pragma weak dma2_stream2_isr = null_handler
#pragma weak dma2_stream3_isr = null_handler
#pragma weak dma2_stream4_isr = null_handler
#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
#pragma weak dma2_stream5_isr = null_handler
#pragma weak dma2_stream6_isr = null_handler
#pragma weak dma2_stream7_isr = null_handler
#pragma weak usart6_isr = null_handler
#pragma weak i2c3_ev_isr = null_handler
#pragma weak i2c3_er_isr = null_handler
#pragma weak otg_hs_ep1_out_isr = null_handler
#pragma weak otg_hs_ep1_in_isr = null_handler
#pragma weak otg_hs_wkup_isr = null_handler
#pragma weak otg_hs_isr = null_handler
#pragma weak dcmi_isr = null_handler
#pragma weak cryp_isr = null_handler
#pragma weak hash_rng_isr = null_handler

View File

@@ -1,7 +1,8 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -17,19 +18,10 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f4/scb.h>
#include <libopencm3/cm3/scb.h>
void scb_reset_core(void)
static void pre_main(void)
{
SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_VECTRESET;
}
void scb_reset_system(void)
{
SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ;
}
void scb_set_priority_grouping(u32 prigroup)
{
SCB_AIRCR = SCB_AIRCR_VECTKEY | prigroup;
/* Enable access to Floating-Point coprocessor. */
SCB_CPACR |= SCB_CPACR_FULL * (SCB_CPACR_CP10 | SCB_CPACR_CP11);
}

View File

@@ -17,7 +17,15 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(STM32F2)
#include <libopencm3/stm32/f2/gpio.h>
#elif defined(STM32F4)
#include <libopencm3/stm32/f4/gpio.h>
#elif defined(STM32L1)
#include <libopencm3/stm32/l1/gpio.h>
#else
#error "invalid/unknown stm32 family for this code"
#endif
void gpio_mode_setup(u32 gpioport, u8 mode, u8 pull_up_down, u16 gpios)
{
@@ -86,7 +94,7 @@ void gpio_set_af(u32 gpioport, u8 alt_func_num, u16 gpios)
for (i = 8; i < 16; i++) {
if (!((1 << i) & gpios))
continue;
afrl &= ~GPIO_AFR_MASK(i - 8);
afrh &= ~GPIO_AFR_MASK(i - 8);
afrh |= GPIO_AFR(i - 8, alt_func_num);
}

36
lib/stm32/l1/Makefile Normal file
View File

@@ -0,0 +1,36 @@
##
## This file is part of the libopencm3 project.
##
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
##
## This library is free software: you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this library. If not, see <http://www.gnu.org/licenses/>.
##
LIBNAME = libopencm3_stm32l1
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 -DSTM32L1
# ARFLAGS = rcsv
ARFLAGS = rcs
OBJS = rcc.o gpio2.o desig.o crc.o usart.o exti2.o
VPATH += ../../usb:../:../../cm3
include ../../Makefile.include

View File

@@ -0,0 +1,83 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Generic linker script for STM32 targets using libopencm3. */
/* Memory regions must be defined in the ld script which includes this one. */
/* Enforce emmition of the vector table. */
EXTERN (vector_table)
/* Define the entry point of the output file. */
ENTRY(reset_handler)
/* Define sections. */
SECTIONS
{
.text : {
*(.vectors) /* Vector table */
*(.text*) /* Program code */
. = ALIGN(4);
*(.rodata*) /* Read-only data */
. = ALIGN(4);
} >rom
/*
* Another section used by C++ stuff, appears when using newlib with
* 64bit (long long) printf support
*/
.ARM.extab : {
*(.ARM.extab*)
} >rom
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >rom
. = ALIGN(4);
_etext = .;
.data : {
_data = .;
*(.data*) /* Read-write initialized data */
. = ALIGN(4);
_edata = .;
} >ram AT >rom
_data_loadaddr = LOADADDR(.data);
.bss : {
*(.bss*) /* Read-write zero initialized data */
*(COMMON)
. = ALIGN(4);
_ebss = .;
} >ram
/*
* The .eh_frame section appears to be used for C++ exception handling.
* You may need to fix this if you're using C++.
*/
/DISCARD/ : { *(.eh_frame) }
. = ALIGN(4);
end = .;
}
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));

357
lib/stm32/l1/rcc.c Normal file
View File

@@ -0,0 +1,357 @@
/*
* 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>
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
* Based on the F4 code...
*/
#include <libopencm3/stm32/l1/rcc.h>
/* Set the default ppre1 and ppre2 peripheral clock frequencies after reset. */
u32 rcc_ppre1_frequency = 2097000;
u32 rcc_ppre2_frequency = 2097000;
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;
case MSI:
RCC_CIR |= RCC_CIR_MSIRDYC;
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;
case MSI:
RCC_CIR |= RCC_CIR_MSIRDYIE;
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;
case MSI:
RCC_CIR &= ~RCC_CIR_MSIRDYIE;
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;
case MSI:
return ((RCC_CIR & RCC_CIR_MSIRDYF) != 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 MSI:
while ((RCC_CR & RCC_CR_MSIRDY) == 0);
break;
case LSE:
while ((RCC_CSR & RCC_CSR_LSERDY) == 0);
break;
case LSI:
while ((RCC_CSR & RCC_CSR_LSIRDY) == 0);
break;
}
}
void rcc_wait_for_sysclk_status(osc_t osc)
{
switch (osc) {
case PLL:
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_SYSCLKSEL_PLLCLK);
break;
case HSE:
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_SYSCLKSEL_HSECLK);
break;
case HSI:
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_SYSCLKSEL_HSICLK);
break;
case MSI:
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SWS_SYSCLKSEL_MSICLK);
break;
default:
/* Shouldn't be reached. */
break;
}
}
void rcc_osc_on(osc_t osc)
{
switch (osc) {
case PLL:
RCC_CR |= RCC_CR_PLLON;
break;
case MSI:
RCC_CR |= RCC_CR_MSION;
break;
case HSE:
RCC_CR |= RCC_CR_HSEON;
break;
case HSI:
RCC_CR |= RCC_CR_HSION;
break;
case LSE:
RCC_CSR |= RCC_CSR_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 MSI:
RCC_CR &= ~RCC_CR_MSION;
break;
case HSE:
RCC_CR &= ~RCC_CR_HSEON;
break;
case HSI:
RCC_CR &= ~RCC_CR_HSION;
break;
case LSE:
RCC_CSR &= ~RCC_CSR_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_CSR |= RCC_CSR_LSEBYP;
break;
case PLL:
case HSI:
case LSI:
case MSI:
/* 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_CSR &= ~RCC_CSR_LSEBYP;
break;
case PLL:
case HSI:
case LSI:
case MSI:
/* 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_source(u32 pllsrc)
{
u32 reg32;
reg32 = RCC_CFGR;
reg32 &= ~(1 << 16);
RCC_CFGR = (reg32 | (pllsrc << 16));
}
void rcc_set_ppre2(u32 ppre2)
{
u32 reg32;
reg32 = RCC_CFGR;
reg32 &= ~((1 << 13) | (1 << 12) | (1 << 11));
RCC_CFGR = (reg32 | (ppre2 << 11));
}
void rcc_set_ppre1(u32 ppre1)
{
u32 reg32;
reg32 = RCC_CFGR;
reg32 &= ~((1 << 10) | (1 << 9) | (1 << 8));
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_rtcpre(u32 rtcpre)
{
u32 reg32;
reg32 = RCC_CR;
reg32 &= ~((1 << 30) | (1 << 29));
RCC_CR = (reg32 | (rtcpre << 29));
}
u32 rcc_system_clock_source(void)
{
/* Return the clock source which is used as system clock. */
return ((RCC_CFGR & 0x000c) >> 2);
}

View File

@@ -1,7 +1,7 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -17,19 +17,15 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f1/scb.h>
/* Linker script for STM32L15xx8, 64K flash, 10K RAM. */
void scb_reset_core(void)
/* Define memory regions. */
MEMORY
{
SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_VECTRESET;
rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 10K
}
void scb_reset_system(void)
{
SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ;
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32l1.ld
void scb_set_priority_grouping(u32 prigroup)
{
SCB_AIRCR = SCB_AIRCR_VECTKEY | prigroup;
}

View File

@@ -1,7 +1,7 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -17,19 +17,15 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f2/scb.h>
/* Linker script for STM32L15xxB, 128K flash, 16K RAM. */
void scb_reset_core(void)
/* Define memory regions. */
MEMORY
{
SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_VECTRESET;
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K
}
void scb_reset_system(void)
{
SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ;
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32l1.ld
void scb_set_priority_grouping(u32 prigroup)
{
SCB_AIRCR = SCB_AIRCR_VECTKEY | prigroup;
}

View File

@@ -1,174 +0,0 @@
/** @defgroup STM32F_nvic_file NVIC
@ingroup STM32F_files
@brief <b>libopencm3 STM32F Nested Vectored Interrupt Controller</b>
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
@author @htmlonly &copy; @endhtmlonly 2012 Fergus Noble <fergusnoble@gmail.com>
@date 18 August 2012
The STM32F series provides up to 68 maskable user interrupts for the STM32F10x
series, and 87 for the STM32F2xx and STM32F4xx series.
The NVIC registers are defined by the ARM standards but the STM32F series have some
additional limitations
@see Cortex-M3 Devices Generic User Guide
@see STM32F10xxx Cortex-M3 programming manual
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/nvic.h>
/*-----------------------------------------------------------------------------*/
/** @brief NVIC Enable Interrupt
Enables a user interrupt.
@param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
*/
void nvic_enable_irq(u8 irqn)
{
NVIC_ISER(irqn / 32) = (1 << (irqn % 32));
}
/*-----------------------------------------------------------------------------*/
/** @brief NVIC Disable Interrupt
Disables a user interrupt.
@param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
*/
void nvic_disable_irq(u8 irqn)
{
NVIC_ICER(irqn / 32) = (1 << (irqn % 32));
}
/*-----------------------------------------------------------------------------*/
/** @brief NVIC Return Pending Interrupt
True if the interrupt has occurred and is waiting for service.
@param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
@return Boolean. Interrupt pending.
*/
u8 nvic_get_pending_irq(u8 irqn)
{
return NVIC_ISPR(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
}
/*-----------------------------------------------------------------------------*/
/** @brief NVIC Set Pending Interrupt
Force a user interrupt to a pending state. This has no effect if the interrupt
is already pending.
@param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
*/
void nvic_set_pending_irq(u8 irqn)
{
NVIC_ISPR(irqn / 32) = (1 << (irqn % 32));
}
/*-----------------------------------------------------------------------------*/
/** @brief NVIC Clear Pending Interrupt
Force remove a user interrupt from a pending state. This has no effect if the
interrupt is actively being serviced.
@param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
*/
void nvic_clear_pending_irq(u8 irqn)
{
NVIC_ICPR(irqn / 32) = (1 << (irqn % 32));
}
/*-----------------------------------------------------------------------------*/
/** @brief NVIC Return Active Interrupt
Interrupt has occurred and is currently being serviced.
@param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
@return Boolean. Interrupt active.
*/
u8 nvic_get_active_irq(u8 irqn)
{
return NVIC_IABR(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
}
/*-----------------------------------------------------------------------------*/
/** @brief NVIC Return Enabled Interrupt
@param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
@return Boolean. Interrupt enabled.
*/
u8 nvic_get_irq_enabled(u8 irqn)
{
return NVIC_ISER(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
}
/*-----------------------------------------------------------------------------*/
/** @brief NVIC Set Interrupt Priority
There are 16 priority levels only, given by the upper four bits of the priority
byte, as required by ARM standards. The priority levels are interpreted according
to the pre-emptive priority grouping set in the SCB Application Interrupt and Reset
Control Register (SCB_AIRCR), as done in @ref scb_set_priority_grouping.
@param[in] irqn Unsigned int8. Interrupt number @ref nvic_stm32f1_userint
@param[in] priority Unsigned int8. Interrupt priority (0 ... 255 in steps of 16)
*/
void nvic_set_priority(u8 irqn, u8 priority)
{
NVIC_IPR(irqn) = priority;
}
/*-----------------------------------------------------------------------------*/
/** @brief NVIC Software Trigger Interrupt
Generate an interrupt from software. This has no effect for unprivileged access
unless the privilege level has been elevated through the System Control Registers.
@param[in] irqn Unsigned int16. Interrupt number (0 ... 239)
*/
void nvic_generate_software_interrupt(u16 irqn)
{
if (irqn <= 239)
NVIC_STIR |= irqn;
}
/**@}*/

View File

@@ -1,139 +0,0 @@
/** @defgroup STM32F_systick_file SysTick
@ingroup STM32F_files
@brief <b>libopencm3 STM32Fxx System Tick Timer</b>
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
@date 19 August 2012
This library supports the System Tick timer in the
STM32F series of ARM Cortex Microcontrollers by ST Microelectronics.
The System Tick timer is part of the ARM Cortex core. It is a 24 bit
down counter that can be configured with an automatical reload value.
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/systick.h>
/*-----------------------------------------------------------------------------*/
/** @brief SysTick Set the Automatic Reload Value.
The counter is set to the reload value when the counter starts and after it
reaches zero.
@param[in] value u32. 24 bit reload value.
*/
void systick_set_reload(u32 value)
{
STK_LOAD = (value & 0x00FFFFFF);
}
/*-----------------------------------------------------------------------------*/
/** @brief SysTick Read the Automatic Reload Value.
@returns 24 bit reload value as u32.
*/
u32 systick_get_value(void)
{
return STK_VAL;
}
/*-----------------------------------------------------------------------------*/
/** @brief Set the SysTick Clock Source.
The clock source can be either the AHB clock or the same clock divided by 8.
@param[in] clocksource u8. Clock source from @ref systick_clksource.
*/
void systick_set_clocksource(u8 clocksource)
{
if (clocksource < 2)
STK_CTRL |= (clocksource << STK_CTRL_CLKSOURCE_LSB);
}
/*-----------------------------------------------------------------------------*/
/** @brief Enable SysTick Interrupt.
*/
void systick_interrupt_enable(void)
{
STK_CTRL |= STK_CTRL_TICKINT;
}
/*-----------------------------------------------------------------------------*/
/** @brief Disable SysTick Interrupt.
*/
void systick_interrupt_disable(void)
{
STK_CTRL &= ~STK_CTRL_TICKINT;
}
/*-----------------------------------------------------------------------------*/
/** @brief Enable SysTick Counter.
*/
void systick_counter_enable(void)
{
STK_CTRL |= STK_CTRL_ENABLE;
}
/*-----------------------------------------------------------------------------*/
/** @brief Disable SysTick Counter.
*/
void systick_counter_disable(void)
{
STK_CTRL &= ~STK_CTRL_ENABLE;
}
/*-----------------------------------------------------------------------------*/
/** @brief SysTick Read the Counter Flag.
The count flag is set when the timer count becomes zero, and is cleared when the
flag is read.
@returns Boolean if flag set.
*/
u8 systick_get_countflag(void)
{
if (STK_CTRL & STK_CTRL_COUNTFLAG)
return 1;
else
return 0;
}
/**@}*/

View File

@@ -2,7 +2,7 @@
@ingroup STM32F1xx
@brief <b>libopencm3 STM32F1xx Timers</b>
@brief <b>libopencm3 STM32 Timers</b>
@version 1.0.0
@@ -11,9 +11,9 @@
@date 18 August 2012
This library supports the General Purpose and Advanced Control Timers for
the STM32F1xx series of ARM Cortex Microcontrollers by ST Microelectronics.
the STM32 series of ARM Cortex Microcontrollers by ST Microelectronics.
The STM32F1xx series have four general purpose timers (2-5), while some have
The STM32 series have four general purpose timers (2-5), while some have
an additional two advanced timers (1,8), and some have two basic timers (6,7).
Some of the larger devices have additional general purpose timers (9-14).
@@ -70,6 +70,7 @@ push-pull outputs where the PWM output will appear.
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Edward Cheeseman <evbuilder@users.sourceforge.org>
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -96,7 +97,18 @@ push-pull outputs where the PWM output will appear.
/**@{*/
#include <libopencm3/stm32/timer.h>
#include <libopencm3/stm32/f1/rcc.h>
#if defined(STM32F1)
# include <libopencm3/stm32/f1/rcc.h>
#elif defined(STM32F2)
# include <libopencm3/stm32/f2/timer.h>
# include <libopencm3/stm32/f2/rcc.h>
#elif defined(STM32F4)
# include <libopencm3/stm32/f4/timer.h>
# include <libopencm3/stm32/f4/rcc.h>
#else
# error "stm32 family not defined."
#endif
/*---------------------------------------------------------------------------*/
/** @brief Reset a Timer.
@@ -1696,6 +1708,29 @@ u32 timer_get_counter(u32 timer_peripheral)
return TIM_CNT(timer_peripheral);
}
/*---------------------------------------------------------------------------*/
/** @brief Set Timer Option
Set timer options register on TIM2 or TIM5, used for oscillator calibration
on TIM5 and trigger remapping on TIM2. Only available on F4 and F2.
@param[in] timer_peripheral Unsigned int32. Timer register address base
@returns Unsigned int32. Option flags.
*/
#if (defined(STM32F4) || defined(STM32F2))
void timer_set_option(u32 timer_peripheral, u32 option)
{
if (timer_peripheral == TIM2) {
TIM_OR(timer_peripheral) &= ~TIM2_OR_ITR1_RMP_MASK;
TIM_OR(timer_peripheral) |= option;
} else if (timer_peripheral == TIM5) {
TIM_OR(timer_peripheral) &= ~TIM5_OR_TI4_RMP_MASK;
TIM_OR(timer_peripheral) |= option;
}
}
#endif
/*---------------------------------------------------------------------------*/
/** @brief Set Counter

View File

@@ -46,6 +46,8 @@ LGPL License Terms @ref lgpl_license
# include <libopencm3/stm32/f2/rcc.h>
#elif defined(STM32F4)
# include <libopencm3/stm32/f4/rcc.h>
#elif defined(STM32L1)
# include <libopencm3/stm32/l1/rcc.h>
#else
# error "stm32 family not defined."
#endif