Merge branch 'master' into efm32
Conflicts: Doxyfile Makefile
This commit is contained in:
50
lib/Makefile.include
Normal file
50
lib/Makefile.include
Normal file
@@ -0,0 +1,50 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2012 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/>.
|
||||
##
|
||||
|
||||
# Be silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1)
|
||||
Q := @
|
||||
endif
|
||||
|
||||
all: $(SRCLIBDIR)/$(LIBNAME).a
|
||||
|
||||
$(SRCLIBDIR)/$(LIBNAME).a: $(SRCLIBDIR)/$(LIBNAME).ld $(OBJS)
|
||||
@printf " AR $(shell basename $(@))\n"
|
||||
$(Q)$(AR) $(ARFLAGS) $(SRCLIBDIR)/$(shell basename $(@)) $(OBJS)
|
||||
|
||||
$(SRCLIBDIR)/$(LIBNAME).ld: $(LIBNAME).ld
|
||||
@printf " CP $(LIBNAME).ld\n"
|
||||
$(Q)cp $^ $@
|
||||
$(Q)if [ -f $(LIBNAME)_rom_to_ram.ld ]; then cp $(LIBNAME)_rom_to_ram.ld $(SRCLIBDIR); fi
|
||||
|
||||
%.o: %.c
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
@printf " CLEAN lib/stm32/f1\n"
|
||||
$(Q)rm -f *.o *.d
|
||||
$(Q)rm -f $(SRCLIBDIR)/$(LIBNAME).a
|
||||
$(Q)rm -f $(SRCLIBDIR)/$(LIBNAME).ld
|
||||
$(Q)rm -f $(SRCLIBDIR)/$(LIBNAME)_rom_to_ram.ld
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
-include $(OBJS:.o=.d)
|
||||
@@ -32,26 +32,4 @@ OBJS = gpio.o vector.o
|
||||
|
||||
# VPATH += ../usb
|
||||
|
||||
# Be silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1)
|
||||
Q := @
|
||||
endif
|
||||
|
||||
all: $(LIBNAME).a
|
||||
|
||||
$(LIBNAME).a: $(OBJS)
|
||||
@printf " AR $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
%.o: %.c
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
@printf " CLEAN lib/lpc13xx\n"
|
||||
$(Q)rm -f *.o *.d
|
||||
$(Q)rm -f $(LIBNAME).a
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
-include $(OBJS:.o=.d)
|
||||
include ../Makefile.include
|
||||
|
||||
@@ -24,31 +24,50 @@
|
||||
/* Enforce emmition of the vector table. */
|
||||
EXTERN (vector_table)
|
||||
|
||||
/* Define the entry point of the output file. */
|
||||
ENTRY(reset_handler)
|
||||
|
||||
/* Define sections. */
|
||||
SECTIONS
|
||||
{
|
||||
. = ORIGIN(rom);
|
||||
|
||||
.text : {
|
||||
*(.vectors) /* Vector table */
|
||||
*(.text*) /* Program code */
|
||||
. = ALIGN(4);
|
||||
*(.rodata*) /* Read-only data */
|
||||
_etext = .;
|
||||
. = ALIGN(4);
|
||||
} >rom
|
||||
|
||||
. = ORIGIN(ram);
|
||||
/*
|
||||
* 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 AT >rom
|
||||
} >ram
|
||||
|
||||
/*
|
||||
* The .eh_frame section appears to be used for C++ exception handling.
|
||||
@@ -56,12 +75,7 @@ SECTIONS
|
||||
*/
|
||||
/DISCARD/ : { *(.eh_frame) }
|
||||
|
||||
/*
|
||||
* Another section used by C++ stuff, appears when using newlib with
|
||||
* 64bit (long long) printf support - discard it for now.
|
||||
*/
|
||||
/DISCARD/ : { *(.ARM.exidx) }
|
||||
|
||||
. = ALIGN(4);
|
||||
end = .;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#define WEAK __attribute__ ((weak))
|
||||
|
||||
/* Symbols exported by the linker script(s): */
|
||||
extern unsigned _etext, _data, _edata, _ebss, _stack;
|
||||
extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack;
|
||||
|
||||
void main(void);
|
||||
void reset_handler(void);
|
||||
@@ -61,9 +61,10 @@ void (*const vector_table[]) (void) = {
|
||||
void reset_handler(void)
|
||||
{
|
||||
volatile unsigned *src, *dest;
|
||||
|
||||
__asm__("MSR msp, %0" : : "r"(&_stack));
|
||||
|
||||
for (src = &_etext, dest = &_data; dest < &_edata; src++, dest++)
|
||||
for (src = &_data_loadaddr, dest = &_data; dest < &_edata; src++, dest++)
|
||||
*dest = *src;
|
||||
|
||||
while (dest < &_ebss)
|
||||
|
||||
@@ -32,27 +32,4 @@ OBJS = gpio.o
|
||||
|
||||
# VPATH += ../usb
|
||||
|
||||
# Be silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1)
|
||||
Q := @
|
||||
endif
|
||||
|
||||
all: $(LIBNAME).a
|
||||
|
||||
$(LIBNAME).a: $(OBJS)
|
||||
@printf " AR $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
%.o: %.c
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
@printf " CLEAN lib/lpc13xx\n"
|
||||
$(Q)rm -f *.o *.d
|
||||
$(Q)rm -f $(LIBNAME).a
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
-include $(OBJS:.o=.d)
|
||||
|
||||
include ../Makefile.include
|
||||
|
||||
@@ -24,31 +24,50 @@
|
||||
/* Enforce emmition of the vector table. */
|
||||
EXTERN (vector_table)
|
||||
|
||||
/* Define the entry point of the output file. */
|
||||
ENTRY(reset_handler)
|
||||
|
||||
/* Define sections. */
|
||||
SECTIONS
|
||||
{
|
||||
. = ORIGIN(rom);
|
||||
|
||||
.text : {
|
||||
*(.vectors) /* Vector table */
|
||||
*(.text*) /* Program code */
|
||||
. = ALIGN(4);
|
||||
*(.rodata*) /* Read-only data */
|
||||
_etext = .;
|
||||
. = ALIGN(4);
|
||||
} >rom
|
||||
|
||||
. = ORIGIN(ram);
|
||||
/*
|
||||
* 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 AT >rom
|
||||
} >ram
|
||||
|
||||
/*
|
||||
* The .eh_frame section appears to be used for C++ exception handling.
|
||||
@@ -56,12 +75,7 @@ SECTIONS
|
||||
*/
|
||||
/DISCARD/ : { *(.eh_frame) }
|
||||
|
||||
/*
|
||||
* Another section used by C++ stuff, appears when using newlib with
|
||||
* 64bit (long long) printf support - discard it for now.
|
||||
*/
|
||||
/DISCARD/ : { *(.ARM.exidx) }
|
||||
|
||||
. = ALIGN(4);
|
||||
end = .;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,27 +32,4 @@ OBJS = gpio.o vector.o
|
||||
|
||||
# VPATH += ../usb
|
||||
|
||||
# Be silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1)
|
||||
Q := @
|
||||
endif
|
||||
|
||||
all: $(LIBNAME).a
|
||||
|
||||
$(LIBNAME).a: $(OBJS)
|
||||
@printf " AR $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
%.o: %.c
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
@printf " CLEAN lib/lpc17xx\n"
|
||||
$(Q)rm -f *.o *.d
|
||||
$(Q)rm -f $(LIBNAME).a
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
-include $(OBJS:.o=.d)
|
||||
|
||||
include ../Makefile.include
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
@@ -31,28 +30,44 @@ ENTRY(reset_handler)
|
||||
/* Define sections. */
|
||||
SECTIONS
|
||||
{
|
||||
. = ORIGIN(rom);
|
||||
|
||||
.text : {
|
||||
*(.vectors) /* Vector table */
|
||||
*(.text*) /* Program code */
|
||||
. = ALIGN(4);
|
||||
*(.rodata*) /* Read-only data */
|
||||
_etext = .;
|
||||
. = ALIGN(4);
|
||||
} >rom
|
||||
|
||||
. = ORIGIN(ram);
|
||||
/*
|
||||
* 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 AT >rom
|
||||
} >ram
|
||||
|
||||
/*
|
||||
* The .eh_frame section appears to be used for C++ exception handling.
|
||||
@@ -60,12 +75,7 @@ SECTIONS
|
||||
*/
|
||||
/DISCARD/ : { *(.eh_frame) }
|
||||
|
||||
/*
|
||||
* Another section used by C++ stuff, appears when using newlib with
|
||||
* 64bit (long long) printf support - discard it for now.
|
||||
*/
|
||||
/DISCARD/ : { *(.ARM.exidx) }
|
||||
|
||||
. = ALIGN(4);
|
||||
end = .;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
#define WEAK __attribute__ ((weak))
|
||||
|
||||
/* Symbols exported by the linker script(s). */
|
||||
extern unsigned _etext, _data, _edata, _ebss, _stack;
|
||||
/* Symbols exported by the linker script(s): */
|
||||
extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack;
|
||||
|
||||
void main(void);
|
||||
void reset_handler(void);
|
||||
@@ -60,9 +60,10 @@ void (*const vector_table[]) (void) = {
|
||||
void reset_handler(void)
|
||||
{
|
||||
volatile unsigned *src, *dest;
|
||||
|
||||
__asm__("MSR msp, %0" : : "r"(&_stack));
|
||||
|
||||
for (src = &_etext, dest = &_data; dest < &_edata; src++, dest++)
|
||||
for (src = &_data_loadaddr, dest = &_data; dest < &_edata; src++, dest++)
|
||||
*dest = *src;
|
||||
|
||||
while (dest < &_ebss)
|
||||
|
||||
38
lib/lpc43xx/Makefile
Normal file
38
lib/lpc43xx/Makefile
Normal file
@@ -0,0 +1,38 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2012 Michael Ossmann <mike@ossmann.com>
|
||||
## Copyright (C) 2012 Benjamin Vernoux <titanmkd@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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_lpc43xx
|
||||
|
||||
PREFIX ?= arm-none-eabi
|
||||
#PREFIX ?= arm-elf
|
||||
CC = $(PREFIX)-gcc
|
||||
AR = $(PREFIX)-ar
|
||||
CFLAGS = -O2 -g3 -Wall -Wextra -I../../include -fno-common \
|
||||
-mcpu=cortex-m4 -mthumb -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD \
|
||||
-mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
OBJS = gpio.o vector.o scu.o i2c.o ssp.o nvic.o systick.o
|
||||
|
||||
# VPATH += ../usb
|
||||
|
||||
include ../Makefile.include
|
||||
35
lib/lpc43xx/gpio.c
Normal file
35
lib/lpc43xx/gpio.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 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/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/lpc43xx/gpio.h>
|
||||
|
||||
void gpio_set(u32 gpioport, u32 gpios)
|
||||
{
|
||||
GPIO_SET(gpioport) = gpios;
|
||||
}
|
||||
|
||||
void gpio_clear(u32 gpioport, u32 gpios)
|
||||
{
|
||||
GPIO_CLR(gpioport) = gpios;
|
||||
}
|
||||
|
||||
void gpio_toggle(u32 gpioport, u32 gpios)
|
||||
{
|
||||
GPIO_NOT(gpioport) = gpios;
|
||||
}
|
||||
93
lib/lpc43xx/i2c.c
Normal file
93
lib/lpc43xx/i2c.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Michael Ossmann <mike@ossmann.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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a very minimal I2C driver just to make sure we can get the
|
||||
* peripheral working.
|
||||
*/
|
||||
|
||||
#include <libopencm3/lpc43xx/i2c.h>
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
#include <libopencm3/lpc43xx/cgu.h>
|
||||
|
||||
void i2c0_init(void)
|
||||
{
|
||||
/* enable input on SCL and SDA pins */
|
||||
SCU_SFSI2C0 = SCU_I2C0_NOMINAL;
|
||||
|
||||
/* use IRC as clock source for APB1 (including I2C0) */
|
||||
CGU_BASE_APB1_CLK = (CGU_SRC_IRC << CGU_BASE_CLK_SEL_SHIFT);
|
||||
|
||||
/* FIXME assuming we're on IRC at 12 MHz */
|
||||
|
||||
/* 400 kHz I2C */
|
||||
I2C0_SCLH = 15;
|
||||
I2C0_SCLL = 15;
|
||||
|
||||
/* 100 kHz I2C */
|
||||
/*
|
||||
I2C0_SCLH = 60;
|
||||
I2C0_SCLL = 60;
|
||||
*/
|
||||
|
||||
/* clear the control bits */
|
||||
I2C0_CONCLR = (I2C_CONCLR_AAC | I2C_CONCLR_SIC
|
||||
| I2C_CONCLR_STAC | I2C_CONCLR_I2ENC);
|
||||
|
||||
/* enable I2C0 */
|
||||
I2C0_CONSET = I2C_CONSET_I2EN;
|
||||
}
|
||||
|
||||
/* transmit start bit */
|
||||
void i2c0_tx_start(void)
|
||||
{
|
||||
I2C0_CONCLR = I2C_CONCLR_SIC;
|
||||
I2C0_CONSET = I2C_CONSET_STA;
|
||||
while (!(I2C0_CONSET & I2C_CONSET_SI));
|
||||
I2C0_CONCLR = I2C_CONCLR_STAC;
|
||||
}
|
||||
|
||||
/* transmit data byte */
|
||||
void i2c0_tx_byte(u8 byte)
|
||||
{
|
||||
if (I2C0_CONSET & I2C_CONSET_STA)
|
||||
I2C0_CONCLR = I2C_CONCLR_STAC;
|
||||
I2C0_DAT = byte;
|
||||
I2C0_CONCLR = I2C_CONCLR_SIC;
|
||||
while (!(I2C0_CONSET & I2C_CONSET_SI));
|
||||
}
|
||||
|
||||
/* receive data byte */
|
||||
u8 i2c0_rx_byte(void)
|
||||
{
|
||||
if (I2C0_CONSET & I2C_CONSET_STA)
|
||||
I2C0_CONCLR = I2C_CONCLR_STAC;
|
||||
I2C0_CONCLR = I2C_CONCLR_SIC;
|
||||
while (!(I2C0_CONSET & I2C_CONSET_SI));
|
||||
return I2C0_DAT;
|
||||
}
|
||||
|
||||
/* transmit stop bit */
|
||||
void i2c0_stop(void)
|
||||
{
|
||||
if (I2C0_CONSET & I2C_CONSET_STA)
|
||||
I2C0_CONCLR = I2C_CONCLR_STAC;
|
||||
I2C0_CONSET = I2C_CONSET_STO;
|
||||
I2C0_CONCLR = I2C_CONCLR_SIC;
|
||||
}
|
||||
90
lib/lpc43xx/libopencm3_lpc43xx.ld
Normal file
90
lib/lpc43xx/libopencm3_lpc43xx.ld
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
* Copyright (C) 2012 Michael Ossmann <mike@ossmann.com>
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@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/>.
|
||||
*/
|
||||
|
||||
/* Generic linker script for LPC43XX 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 : {
|
||||
. = ALIGN(0x400);
|
||||
_text_ram = 0; /* Start of Code in RAM NULL because Copy of Code from ROM to RAM disabled */
|
||||
*(.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 = .;
|
||||
_etext_ram = 0; /* Start of Code in RAM NULL because Copy of Code from ROM to RAM disabled */
|
||||
_etext_rom = 0; /* Start of Code in RAM NULL because Copy of Code from ROM to RAM disabled */
|
||||
|
||||
.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 = .;
|
||||
|
||||
/* Leave room above stack for IAP to run. */
|
||||
__StackTop = ORIGIN(ram) + LENGTH(ram) - 32;
|
||||
PROVIDE(_stack = __StackTop);
|
||||
}
|
||||
91
lib/lpc43xx/libopencm3_lpc43xx_rom_to_ram.ld
Normal file
91
lib/lpc43xx/libopencm3_lpc43xx_rom_to_ram.ld
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
* Copyright (C) 2012 Michael Ossmann <mike@ossmann.com>
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@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/>.
|
||||
*/
|
||||
|
||||
/* Generic linker script for LPC43XX 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 : {
|
||||
. = ALIGN(0x400);
|
||||
_text_ram = (. - ORIGIN(rom)) + ORIGIN(ram); /* Start of Code in RAM */
|
||||
|
||||
*(.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 = .;
|
||||
_etext_ram = (. - ORIGIN(rom)) + ORIGIN(ram);
|
||||
_etext_rom = (. - ORIGIN(rom)) + ORIGIN(rom_flash);
|
||||
|
||||
.data : {
|
||||
_data = .;
|
||||
*(.data*) /* Read-write initialized data */
|
||||
. = ALIGN(4);
|
||||
_edata = .;
|
||||
} >ram_data AT >rom
|
||||
_data_loadaddr = LOADADDR(.data);
|
||||
|
||||
.bss : {
|
||||
*(.bss*) /* Read-write zero initialized data */
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = .;
|
||||
} >ram_data
|
||||
|
||||
/*
|
||||
* 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 = .;
|
||||
|
||||
/* Leave room above stack for IAP to run. */
|
||||
__StackTop = ORIGIN(ram) + LENGTH(ram) - 32;
|
||||
PROVIDE(_stack = __StackTop);
|
||||
}
|
||||
76
lib/lpc43xx/nvic.c
Normal file
76
lib/lpc43xx/nvic.c
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
|
||||
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@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/cm3/scs.h>
|
||||
#include <libopencm3/lpc43xx/nvic.h>
|
||||
|
||||
void nvic_enable_irq(u8 irqn)
|
||||
{
|
||||
NVIC_ISER(irqn / 32) = (1 << (irqn % 32));
|
||||
}
|
||||
|
||||
void nvic_disable_irq(u8 irqn)
|
||||
{
|
||||
NVIC_ICER(irqn / 32) = (1 << (irqn % 32));
|
||||
}
|
||||
|
||||
u8 nvic_get_pending_irq(u8 irqn)
|
||||
{
|
||||
return NVIC_ISPR(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
|
||||
}
|
||||
|
||||
void nvic_set_pending_irq(u8 irqn)
|
||||
{
|
||||
NVIC_ISPR(irqn / 32) = (1 << (irqn % 32));
|
||||
}
|
||||
|
||||
void nvic_clear_pending_irq(u8 irqn)
|
||||
{
|
||||
NVIC_ICPR(irqn / 32) = (1 << (irqn % 32));
|
||||
}
|
||||
|
||||
u8 nvic_get_active_irq(u8 irqn)
|
||||
{
|
||||
return NVIC_IABR(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
|
||||
}
|
||||
|
||||
u8 nvic_get_irq_enabled(u8 irqn)
|
||||
{
|
||||
return NVIC_ISER(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
|
||||
}
|
||||
|
||||
void nvic_set_priority(u8 irqn, u8 priority)
|
||||
{
|
||||
if(irqn>NVIC_M4_QEI_IRQ)
|
||||
{
|
||||
/* Cortex-M system interrupts */
|
||||
SCS_SHPR( (irqn&0xF)-4 ) = priority;
|
||||
}else
|
||||
{
|
||||
/* Device specific interrupts */
|
||||
NVIC_IPR(irqn) = priority;
|
||||
}
|
||||
}
|
||||
|
||||
void nvic_generate_software_interrupt(u8 irqn)
|
||||
{
|
||||
if (irqn <= 239)
|
||||
NVIC_STIR |= irqn;
|
||||
}
|
||||
30
lib/lpc43xx/scu.c
Normal file
30
lib/lpc43xx/scu.c
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@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/lpc43xx/scu.h>
|
||||
|
||||
/* For pin_conf_normal value see scu.h define SCU_CONF_XXX or Configuration for different I/O pins types */
|
||||
void scu_pinmux(scu_grp_pin_t group_pin, u32 scu_conf)
|
||||
{
|
||||
MMIO32(group_pin) = scu_conf;
|
||||
}
|
||||
|
||||
/* For other special SCU register USB1, I2C0, ADC0/1, DAC, EMC clock delay See scu.h */
|
||||
|
||||
/* For Pin interrupt select register see scu.h SCU_PINTSEL0 & SCU_PINTSEL1 */
|
||||
160
lib/lpc43xx/ssp.c
Normal file
160
lib/lpc43xx/ssp.c
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@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/lpc43xx/ssp.h>
|
||||
#include <libopencm3/lpc43xx/cgu.h>
|
||||
|
||||
#define CGU_SRC_32K 0x00
|
||||
#define CGU_SRC_IRC 0x01
|
||||
#define CGU_SRC_ENET_RX 0x02
|
||||
#define CGU_SRC_ENET_TX 0x03
|
||||
#define CGU_SRC_GP_CLKIN 0x04
|
||||
#define CGU_SRC_XTAL 0x06
|
||||
#define CGU_SRC_PLL0USB 0x07
|
||||
#define CGU_SRC_PLL0AUDIO 0x08
|
||||
#define CGU_SRC_PLL1 0x09
|
||||
#define CGU_SRC_IDIVA 0x0C
|
||||
#define CGU_SRC_IDIVB 0x0D
|
||||
#define CGU_SRC_IDIVC 0x0E
|
||||
#define CGU_SRC_IDIVD 0x0F
|
||||
#define CGU_SRC_IDIVE 0x10
|
||||
|
||||
#define CGU_AUTOBLOCK_CLOCK_BIT 11
|
||||
#define CGU_BASE_CLK_SEL_SHIFT 24 /* clock source selection (5 bits) */
|
||||
|
||||
/* Disable SSP */
|
||||
void ssp_disable(ssp_num_t ssp_num)
|
||||
{
|
||||
u32 ssp_port;
|
||||
|
||||
if(ssp_num == SSP0_NUM)
|
||||
{
|
||||
ssp_port = SSP0;
|
||||
}else
|
||||
{
|
||||
ssp_port = SSP1;
|
||||
}
|
||||
/* Disable SSP */
|
||||
SSP_CR1(ssp_port) = 0x0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SSP Init function
|
||||
*/
|
||||
void ssp_init(ssp_num_t ssp_num,
|
||||
ssp_datasize_t data_size,
|
||||
ssp_frame_format_t frame_format,
|
||||
ssp_cpol_cpha_t cpol_cpha_format,
|
||||
u8 serial_clock_rate,
|
||||
u8 clk_prescale,
|
||||
ssp_mode_t mode,
|
||||
ssp_master_slave_t master_slave,
|
||||
ssp_slave_option_t slave_option)
|
||||
{
|
||||
u32 ssp_port;
|
||||
u32 clock;
|
||||
|
||||
if(ssp_num == SSP0_NUM)
|
||||
{
|
||||
ssp_port = SSP0;
|
||||
}else
|
||||
{
|
||||
ssp_port = SSP1;
|
||||
}
|
||||
|
||||
/* use PLL1 as clock source for SSP1 */
|
||||
CGU_BASE_SSP1_CLK = (CGU_SRC_PLL1<<CGU_BASE_CLK_SEL_SHIFT) | (1<<CGU_AUTOBLOCK_CLOCK_BIT);
|
||||
|
||||
/* Disable SSP before to configure it */
|
||||
SSP_CR1(ssp_port) = 0x0;
|
||||
|
||||
/* Configure SSP */
|
||||
clock = serial_clock_rate;
|
||||
SSP_CPSR(ssp_port) = clk_prescale;
|
||||
SSP_CR0(ssp_port) = (data_size | frame_format | cpol_cpha_format | (clock<<8) );
|
||||
|
||||
/* Enable SSP */
|
||||
SSP_CR1(ssp_port) = (SSP_ENABLE | mode | master_slave | slave_option);
|
||||
}
|
||||
|
||||
/*
|
||||
* This Function Wait until Data RX Ready, and return Data Read from SSP.
|
||||
*/
|
||||
u16 ssp_read(ssp_num_t ssp_num)
|
||||
{
|
||||
u32 ssp_port;
|
||||
|
||||
if(ssp_num == SSP0_NUM)
|
||||
{
|
||||
ssp_port = SSP0;
|
||||
}else
|
||||
{
|
||||
ssp_port = SSP1;
|
||||
}
|
||||
/* Wait Until Data Received (Rx FIFO not Empty) */
|
||||
while( (SSP_SR(ssp_port) & SSP_SR_RNE) == 0);
|
||||
|
||||
return SSP_DR(ssp_port);
|
||||
}
|
||||
|
||||
void ssp_wait_until_not_busy(ssp_num_t ssp_num)
|
||||
{
|
||||
u32 ssp_port;
|
||||
|
||||
if(ssp_num == SSP0_NUM)
|
||||
{
|
||||
ssp_port = SSP0;
|
||||
}else
|
||||
{
|
||||
ssp_port = SSP1;
|
||||
}
|
||||
|
||||
while( (SSP_SR(ssp_port) & SSP_SR_BSY) );
|
||||
}
|
||||
|
||||
/* This Function Wait Data TX Ready, and Write Data to SSP */
|
||||
void ssp_write(ssp_num_t ssp_num, u16 data)
|
||||
{
|
||||
u32 ssp_port;
|
||||
|
||||
if(ssp_num == SSP0_NUM)
|
||||
{
|
||||
ssp_port = SSP0;
|
||||
}else
|
||||
{
|
||||
ssp_port = SSP1;
|
||||
}
|
||||
|
||||
/* Wait Until FIFO not full */
|
||||
while( (SSP_SR(ssp_port) & SSP_SR_TNF) == 0);
|
||||
|
||||
SSP_DR(ssp_port) = data;
|
||||
|
||||
/* Wait for not busy, since we're controlling CS# of
|
||||
* devices manually and need to wait for the data to
|
||||
* be sent. It may also be important to wait here
|
||||
* in case we're configuring devices via SPI and also
|
||||
* with GPIO control -- we need to know when SPI
|
||||
* commands are effective before altering a device's
|
||||
* state with GPIO. I'm thinking the MAX2837, for
|
||||
* example...
|
||||
*/
|
||||
ssp_wait_until_not_busy(ssp_num);
|
||||
}
|
||||
|
||||
69
lib/lpc43xx/systick.c
Normal file
69
lib/lpc43xx/systick.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@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/lpc43xx/systick.h>
|
||||
|
||||
void systick_set_reload(u32 value)
|
||||
{
|
||||
STK_LOAD = (value & 0x00FFFFFF);
|
||||
}
|
||||
|
||||
u32 systick_get_value(void)
|
||||
{
|
||||
return STK_VAL;
|
||||
}
|
||||
|
||||
void systick_set_clocksource(u8 clocksource)
|
||||
{
|
||||
STK_CTRL |= clocksource;
|
||||
}
|
||||
|
||||
void systick_interrupt_enable(void)
|
||||
{
|
||||
STK_CTRL |= STK_CTRL_TICKINT;
|
||||
}
|
||||
|
||||
void systick_interrupt_disable(void)
|
||||
{
|
||||
STK_CTRL &= ~STK_CTRL_TICKINT;
|
||||
}
|
||||
|
||||
void systick_counter_enable(void)
|
||||
{
|
||||
STK_CTRL |= STK_CTRL_ENABLE;
|
||||
}
|
||||
|
||||
void systick_counter_disable(void)
|
||||
{
|
||||
STK_CTRL &= ~STK_CTRL_ENABLE;
|
||||
}
|
||||
|
||||
u8 systick_get_countflag(void)
|
||||
{
|
||||
if (STK_CTRL & STK_CTRL_COUNTFLAG)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 systick_get_calib(void)
|
||||
{
|
||||
return (STK_CALIB&0x00FFFFFF);
|
||||
}
|
||||
264
lib/lpc43xx/vector.c
Normal file
264
lib/lpc43xx/vector.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
|
||||
* Copyright (C) 2012 Michael Ossmann <mike@ossmann.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;
|
||||
extern unsigned _etext_ram, _text_ram, _etext_rom;
|
||||
|
||||
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 dac_irqhandler(void);
|
||||
void WEAK m0core_irqhandler(void);
|
||||
void WEAK dma_irqhandler(void);
|
||||
void WEAK ethernet_irqhandler(void);
|
||||
void WEAK sdio_irqhandler(void);
|
||||
void WEAK lcd_irqhandler(void);
|
||||
void WEAK usb0_irqhandler(void);
|
||||
void WEAK usb1_irqhandler(void);
|
||||
void WEAK sct_irqhandler(void);
|
||||
void WEAK ritimer_irqhandler(void);
|
||||
void WEAK timer0_irqhandler(void);
|
||||
void WEAK timer1_irqhandler(void);
|
||||
void WEAK timer2_irqhandler(void);
|
||||
void WEAK timer3_irqhandler(void);
|
||||
void WEAK mcpwm_irqhandler(void);
|
||||
void WEAK adc0_irqhandler(void);
|
||||
void WEAK i2c0_irqhandler(void);
|
||||
void WEAK i2c1_irqhandler(void);
|
||||
void WEAK spi_irqhandler(void);
|
||||
void WEAK adc1_irqhandler(void);
|
||||
void WEAK ssp0_irqhandler(void);
|
||||
void WEAK ssp1_irqhandler(void);
|
||||
void WEAK usart0_irqhandler(void);
|
||||
void WEAK uart1_irqhandler(void);
|
||||
void WEAK usart2_irqhandler(void);
|
||||
void WEAK usart3_irqhandler(void);
|
||||
void WEAK i2s0_irqhandler(void);
|
||||
void WEAK i2s1_irqhandler(void);
|
||||
void WEAK spifi_irqhandler(void);
|
||||
void WEAK sgpio_irqhandler(void);
|
||||
void WEAK pin_int0_irqhandler(void);
|
||||
void WEAK pin_int1_irqhandler(void);
|
||||
void WEAK pin_int2_irqhandler(void);
|
||||
void WEAK pin_int3_irqhandler(void);
|
||||
void WEAK pin_int4_irqhandler(void);
|
||||
void WEAK pin_int5_irqhandler(void);
|
||||
void WEAK pin_int6_irqhandler(void);
|
||||
void WEAK pin_int7_irqhandler(void);
|
||||
void WEAK gint0_irqhandler(void);
|
||||
void WEAK gint1_irqhandler(void);
|
||||
void WEAK eventrouter_irqhandler(void);
|
||||
void WEAK c_can1_irqhandler(void);
|
||||
void WEAK atimer_irqhandler(void);
|
||||
void WEAK rtc_irqhandler(void);
|
||||
void WEAK wwdt_irqhandler(void);
|
||||
void WEAK c_can0_irqhandler(void);
|
||||
void WEAK qei_irqhandler(void);
|
||||
|
||||
__attribute__ ((section(".vectors")))
|
||||
void (*const vector_table[]) (void) = {
|
||||
/* Cortex-M4 interrupts */
|
||||
(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,
|
||||
|
||||
/* LPC43xx interrupts */
|
||||
dac_irqhandler,
|
||||
m0core_irqhandler,
|
||||
dma_irqhandler,
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
ethernet_irqhandler,
|
||||
sdio_irqhandler,
|
||||
lcd_irqhandler,
|
||||
usb0_irqhandler,
|
||||
usb1_irqhandler,
|
||||
sct_irqhandler,
|
||||
ritimer_irqhandler,
|
||||
timer0_irqhandler,
|
||||
timer1_irqhandler,
|
||||
timer2_irqhandler,
|
||||
timer3_irqhandler,
|
||||
mcpwm_irqhandler,
|
||||
adc0_irqhandler,
|
||||
i2c0_irqhandler,
|
||||
i2c1_irqhandler,
|
||||
spi_irqhandler,
|
||||
adc1_irqhandler,
|
||||
ssp0_irqhandler,
|
||||
ssp1_irqhandler,
|
||||
usart0_irqhandler,
|
||||
uart1_irqhandler,
|
||||
usart2_irqhandler,
|
||||
usart3_irqhandler,
|
||||
i2s0_irqhandler,
|
||||
i2s1_irqhandler,
|
||||
spifi_irqhandler,
|
||||
sgpio_irqhandler,
|
||||
pin_int0_irqhandler,
|
||||
pin_int1_irqhandler,
|
||||
pin_int2_irqhandler,
|
||||
pin_int3_irqhandler,
|
||||
pin_int4_irqhandler,
|
||||
pin_int5_irqhandler,
|
||||
pin_int6_irqhandler,
|
||||
pin_int7_irqhandler,
|
||||
gint0_irqhandler,
|
||||
gint1_irqhandler,
|
||||
eventrouter_irqhandler,
|
||||
c_can1_irqhandler,
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
atimer_irqhandler,
|
||||
rtc_irqhandler,
|
||||
0, /* reserved */
|
||||
wwdt_irqhandler,
|
||||
0, /* reserved */
|
||||
c_can0_irqhandler,
|
||||
qei_irqhandler,
|
||||
};
|
||||
|
||||
#define MMIO32(addr) (*(volatile unsigned long*)(addr))
|
||||
#define CREG_M4MEMMAP MMIO32( (0x40043000 + 0x100) )
|
||||
|
||||
void reset_handler(void)
|
||||
{
|
||||
volatile unsigned *src, *dest;
|
||||
|
||||
__asm__("MSR msp, %0" : : "r"(&_stack));
|
||||
|
||||
/* Copy the code from ROM to Real RAM (if enabled) */
|
||||
if( (&_etext_ram-&_text_ram) > 0 )
|
||||
{
|
||||
src = &_etext_rom-(&_etext_ram-&_text_ram);
|
||||
/* Change Shadow memory to ROM (for Debug Purpose in case Boot has not set correctly the M4MEMMAP because of debug) */
|
||||
CREG_M4MEMMAP = (unsigned long)src;
|
||||
|
||||
for(dest = &_text_ram; dest < &_etext_ram; )
|
||||
{
|
||||
*dest++ = *src++;
|
||||
}
|
||||
|
||||
/* Change Shadow memory to Real RAM */
|
||||
CREG_M4MEMMAP = (unsigned long)&_text_ram;
|
||||
|
||||
/* Continue Execution in RAM */
|
||||
}
|
||||
|
||||
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 dac_irqhandler = null_handler
|
||||
#pragma weak m0core_irqhandler = null_handler
|
||||
#pragma weak dma_irqhandler = null_handler
|
||||
#pragma weak ethernet_irqhandler = null_handler
|
||||
#pragma weak sdio_irqhandler = null_handler
|
||||
#pragma weak lcd_irqhandler = null_handler
|
||||
#pragma weak usb0_irqhandler = null_handler
|
||||
#pragma weak usb1_irqhandler = null_handler
|
||||
#pragma weak sct_irqhandler = null_handler
|
||||
#pragma weak ritimer_irqhandler = null_handler
|
||||
#pragma weak timer0_irqhandler = null_handler
|
||||
#pragma weak timer1_irqhandler = null_handler
|
||||
#pragma weak timer2_irqhandler = null_handler
|
||||
#pragma weak timer3_irqhandler = null_handler
|
||||
#pragma weak mcpwm_irqhandler = null_handler
|
||||
#pragma weak adc0_irqhandler = null_handler
|
||||
#pragma weak i2c0_irqhandler = null_handler
|
||||
#pragma weak i2c1_irqhandler = null_handler
|
||||
#pragma weak spi_irqhandler = null_handler
|
||||
#pragma weak adc1_irqhandler = null_handler
|
||||
#pragma weak ssp0_irqhandler = null_handler
|
||||
#pragma weak ssp1_irqhandler = null_handler
|
||||
#pragma weak usart0_irqhandler = null_handler
|
||||
#pragma weak uart1_irqhandler = null_handler
|
||||
#pragma weak usart2_irqhandler = null_handler
|
||||
#pragma weak usart3_irqhandler = null_handler
|
||||
#pragma weak i2s0_irqhandler = null_handler
|
||||
#pragma weak i2s1_irqhandler = null_handler
|
||||
#pragma weak spifi_irqhandler = null_handler
|
||||
#pragma weak sgpio_irqhandler = null_handler
|
||||
#pragma weak pin_int0_irqhandler = null_handler
|
||||
#pragma weak pin_int1_irqhandler = null_handler
|
||||
#pragma weak pin_int2_irqhandler = null_handler
|
||||
#pragma weak pin_int3_irqhandler = null_handler
|
||||
#pragma weak pin_int4_irqhandler = null_handler
|
||||
#pragma weak pin_int5_irqhandler = null_handler
|
||||
#pragma weak pin_int6_irqhandler = null_handler
|
||||
#pragma weak pin_int7_irqhandler = null_handler
|
||||
#pragma weak gint0_irqhandler = null_handler
|
||||
#pragma weak gint1_irqhandler = null_handler
|
||||
#pragma weak eventrouter_irqhandler = null_handler
|
||||
#pragma weak c_can1_irqhandler = null_handler
|
||||
#pragma weak atimer_irqhandler = null_handler
|
||||
#pragma weak rtc_irqhandler = null_handler
|
||||
#pragma weak wwdt_irqhandler = null_handler
|
||||
#pragma weak c_can0_irqhandler = null_handler
|
||||
#pragma weak qei_irqhandler = null_handler
|
||||
44
lib/stm32/crc.c
Normal file
44
lib/stm32/crc.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@remake.is>
|
||||
*
|
||||
* 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/crc.h>
|
||||
|
||||
void crc_reset(void)
|
||||
{
|
||||
CRC_CR |= CRC_CR_RESET;
|
||||
}
|
||||
|
||||
u32 crc_calculate(u32 data)
|
||||
{
|
||||
CRC_DR = data;
|
||||
// Data sheet says this blocks until it's ready....
|
||||
return CRC_DR;
|
||||
}
|
||||
|
||||
u32 crc_calculate_block(u32 *datap, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
CRC_DR = datap[i];
|
||||
}
|
||||
return CRC_DR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
520
lib/stm32/dac.c
Normal file
520
lib/stm32/dac.c
Normal file
@@ -0,0 +1,520 @@
|
||||
/** @defgroup STM32F_dac_file DAC
|
||||
|
||||
@ingroup STM32F_files
|
||||
|
||||
@brief <b>libopencm3 STM32Fxx Digital to Analog Converter</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2012 Ken Sarkies
|
||||
|
||||
@date 18 August 2012
|
||||
|
||||
This library supports the Digital to Analog Conversion System in the
|
||||
STM32F series of ARM Cortex Microcontrollers by ST Microelectronics.
|
||||
|
||||
The DAC is present only in a limited set of devices, notably some
|
||||
of the connection line, high density and XL devices.
|
||||
|
||||
Two DAC channels are available, however unlike the ADC channels these
|
||||
are separate DAC devices controlled by the same register block.
|
||||
|
||||
The DAC is on APB1. Its clock must be enabled in RCC and the GPIO
|
||||
ports set to alternate function output before it can be used.
|
||||
The digital output driver is disabled so the output driver mode
|
||||
(push-pull/open drain) is arbitrary.
|
||||
|
||||
The DAC has a holding (buffer) register and an output register from
|
||||
which the analog output is derived. The holding register must be
|
||||
loaded first. If triggering is enabled the output register is loaded
|
||||
from the holding register after a trigger occurs. If triggering is
|
||||
not enabled the holding register contents are transferred directly
|
||||
to the output register.
|
||||
|
||||
@note To avoid nonlinearities, do not allow outputs to range close
|
||||
to zero or V_analog.
|
||||
|
||||
@section dac_api_dual Dual Channel Conversion
|
||||
|
||||
There are dual modes in which both DACs are used to output data
|
||||
simultaneously or independently on both channels. The data must be
|
||||
presented according to the formats described in the datasheets. A
|
||||
convenience function @ref dac_load_data_buffer_dual is provided
|
||||
for software controlled use.
|
||||
|
||||
A variety of modes are available depending on whether independent
|
||||
or simultaneous output is desired, and whether waveforms are to be
|
||||
superimposed. Refer to the datasheets.
|
||||
|
||||
If DMA is used, only enable it for one of the channels. The DMA
|
||||
requests will then serve data in dual format to the data register
|
||||
dedicated to dual mode. The data will then be split and loaded to the
|
||||
appropriate DAC following the next trigger. There are three registers
|
||||
available, one for each of the formats: 12 bit right-aligned, 12 bit
|
||||
left-aligned and 8 bit right-aligned. The desired format is determined
|
||||
by specifying the appropriate register to the DMA controller.
|
||||
|
||||
@section dac_api_basic_ex Basic DAC handling API.
|
||||
|
||||
Set the DAC's GPIO port to any alternate function output mode. Enable the
|
||||
DAC clock. Enable the DAC, set a trigger source and load the buffer
|
||||
with the first value. After the DAC is triggered, load the buffer with
|
||||
the next value. This example uses software triggering and added noise.
|
||||
The trigger and further buffer load calls are made when data is to be
|
||||
sent out.
|
||||
|
||||
@code
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
|
||||
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO4);
|
||||
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_DACEN);
|
||||
dac_disable(CHANNEL_1);
|
||||
dac_set_waveform_characteristics(DAC_CR_MAMP1_8);
|
||||
dac_set_waveform_generation(DAC_CR_WAVE1_NOISE);
|
||||
dac_enable(CHANNEL_1);
|
||||
dac_set_trigger_source(DAC_CR_TSEL1_SW);
|
||||
dac_load_data_buffer_single(0, RIGHT12, CHANNEL_1);
|
||||
....
|
||||
dac_software_trigger(CHANNEL_1);
|
||||
dac_load_data_buffer_single(value, RIGHT12, CHANNEL_1);
|
||||
@endcode
|
||||
|
||||
@section dac_api_dma_ex Simultaneous Dual DAC with DMA.
|
||||
|
||||
This example in part sets up the DAC channel 1 DMA (DMA2 channel 3) to read
|
||||
16 bit data from memory into the right-aligned 8 bit dual register DAC_DHR8RD.
|
||||
Both DAC channels are enabled, and both triggers are set to the same timer
|
||||
2 input as required for simultaneous operation. DMA is enabled for DAC channel
|
||||
1 only to ensure that only one DMA request is generated.
|
||||
|
||||
@code
|
||||
dma_set_memory_size(DMA2,DMA_CHANNEL3,DMA_CCR_MSIZE_16BIT);
|
||||
dma_set_peripheral_size(DMA2,DMA_CHANNEL3,DMA_CCR_PSIZE_16BIT);
|
||||
dma_set_read_from_memory(DMA2,DMA_CHANNEL3);
|
||||
dma_set_peripheral_address(DMA2,DMA_CHANNEL3,(u32) &DAC_DHR8RD);
|
||||
dma_enable_channel(DMA2,DMA_CHANNEL3);
|
||||
...
|
||||
dac_trigger_enable(CHANNEL_D);
|
||||
dac_set_trigger_source(DAC_CR_TSEL1_T2 | DAC_CR_TSEL2_T2);
|
||||
dac_dma_enable(CHANNEL_1);
|
||||
dac_enable(CHANNEL_D);
|
||||
@endcode
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Ken Sarkies
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
|
||||
#include <libopencm3/stm32/dac.h>
|
||||
|
||||
#define MASK8 0xFF
|
||||
#define MASK12 0xFFF
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel Enable.
|
||||
|
||||
Enable a digital to analog converter channel. After setting this enable, the DAC
|
||||
requires a t<sub>wakeup</sub> time typically around 10 microseconds before it
|
||||
actually wakes up.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_enable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR |= DAC_CR_EN1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR |= DAC_CR_EN2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR |= (DAC_CR_EN1 | DAC_CR_EN2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel Disable.
|
||||
|
||||
Disable a digital to analog converter channel.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_disable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR &= ~DAC_CR_EN1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR &= ~DAC_CR_EN2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR &= ~(DAC_CR_EN1 | DAC_CR_EN2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel Output Buffer Enable.
|
||||
|
||||
Enable a digital to analog converter channel output drive buffer. This is an optional
|
||||
amplifying buffer that provides additional drive for the output signal. The
|
||||
buffer is enabled by default after a reset and needs to be explicitly disabled
|
||||
if required.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_buffer_enable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR |= DAC_CR_BOFF1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR |= DAC_CR_BOFF2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR |= (DAC_CR_BOFF1 | DAC_CR_BOFF2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel Output Buffer Disable.
|
||||
|
||||
Disable a digital to analog converter channel output drive buffer. Disabling this will
|
||||
reduce power consumption slightly and will increase the output impedance of the DAC.
|
||||
The buffers are enabled by default after a reset.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_buffer_disable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR &= ~DAC_CR_BOFF1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR &= ~DAC_CR_BOFF2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR &= ~(DAC_CR_BOFF1 | DAC_CR_BOFF2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel DMA Enable.
|
||||
|
||||
Enable a digital to analog converter channel DMA mode (connected to DMA2 channel
|
||||
3 for DAC channel 1 and DMA2 channel 4 for DAC channel 2). A DMA request is
|
||||
generated following an external trigger.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_dma_enable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR |= DAC_CR_DMAEN1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR |= DAC_CR_DMAEN2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR |= (DAC_CR_DMAEN1 | DAC_CR_DMAEN2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel DMA Disable.
|
||||
|
||||
Disable a digital to analog converter channel DMA mode.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_dma_disable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR &= ~DAC_CR_DMAEN1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR &= ~DAC_CR_DMAEN2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR &= ~(DAC_CR_DMAEN1 | DAC_CR_DMAEN2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel Trigger Enable.
|
||||
|
||||
Enable a digital to analog converter channel external trigger mode. This allows an
|
||||
external trigger to initiate register transfers from the buffer register to the DAC
|
||||
output register, followed by a DMA transfer to the buffer register if DMA is enabled.
|
||||
The trigger source must also be selected.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_trigger_enable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR |= DAC_CR_TEN1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR |= DAC_CR_TEN2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR |= (DAC_CR_TEN1 | DAC_CR_TEN2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DAC Channel Trigger Disable.
|
||||
|
||||
Disable a digital to analog converter channel external trigger.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_trigger_disable(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR &= ~DAC_CR_TEN1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR &= ~DAC_CR_TEN2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR &= ~(DAC_CR_TEN1 | DAC_CR_TEN2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Set DAC Channel Trigger Source.
|
||||
|
||||
Sets the digital to analog converter trigger source, which can be taken from various
|
||||
timers, an external trigger or a software trigger.
|
||||
|
||||
@param[in] dac_trig_src u32. Taken from @ref dac_trig2_sel or @ref dac_trig1_sel or
|
||||
a logical OR of one of each of these to set both channels simultaneously.
|
||||
*/
|
||||
|
||||
void dac_set_trigger_source(u32 dac_trig_src)
|
||||
{
|
||||
DAC_CR |= dac_trig_src;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Enable and Set DAC Channel Waveform Generation.
|
||||
|
||||
Enable the digital to analog converter waveform generation as either pseudo-random
|
||||
noise or triangular wave. These signals are superimposed on existing output values
|
||||
in the DAC output registers.
|
||||
|
||||
@note The DAC trigger must be enabled for this to work.
|
||||
|
||||
@param[in] dac_wave_ens u32. Taken from @ref dac_wave1_en or @ref dac_wave2_en or
|
||||
a logical OR of one of each of these to set both channels simultaneously.
|
||||
*/
|
||||
|
||||
void dac_set_waveform_generation(u32 dac_wave_ens)
|
||||
{
|
||||
DAC_CR |= dac_wave_ens;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Disable DAC Channel Waveform Generation.
|
||||
|
||||
Disable a digital to analog converter channel superimposed waveform generation.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_disable_waveform_generation(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_CR &= ~DAC_CR_WAVE1_DIS;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_CR &= ~DAC_CR_WAVE2_DIS;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_CR &= ~(DAC_CR_WAVE1_DIS | DAC_CR_WAVE2_DIS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Set DAC Channel LFSR Mask or Triangle Wave Amplitude.
|
||||
|
||||
Sets the digital to analog converter superimposed waveform generation characteristics.
|
||||
@li If the noise generation mode is set, this sets the length of the PRBS sequence and
|
||||
hence the amplitude of the output noise signal. Default setting is length 1.
|
||||
@li If the triangle wave generation mode is set, this sets the amplitude of the
|
||||
output signal as 2^(n)-1 where n is the parameter value. Default setting is 1.
|
||||
|
||||
@note High amplitude levels of these waveforms can overload the DAC and distort the
|
||||
signal output.
|
||||
@note This must be called before enabling the DAC as the settings will then become read-only.
|
||||
@note The DAC trigger must be enabled for this to work.
|
||||
|
||||
@param[in] dac_mamp u32. Taken from @ref dac_mamp2 or @ref dac_mamp1 or a logical OR
|
||||
of one of each of these to set both channels simultaneously.
|
||||
*/
|
||||
|
||||
void dac_set_waveform_characteristics(u32 dac_mamp)
|
||||
{
|
||||
DAC_CR |= dac_mamp;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Load DAC Data Register.
|
||||
|
||||
Loads the appropriate digital to analog converter data register with 12 or 8 bit
|
||||
data to be converted on a channel. The data can be aligned as follows:
|
||||
@li right-aligned 8 bit data in bits 0-7
|
||||
@li right-aligned 12 bit data in bits 0-11
|
||||
@li left aligned 12 bit data in bits 4-15
|
||||
|
||||
This function can also be used to load the dual channel registers if the data is
|
||||
formatted according to the datasheets:
|
||||
@li right-aligned 8 bit data in bits 0-7 for channel 1 and 8-15 for channel 2
|
||||
@li right-aligned 12 bit data in bits 0-11 for channel 1 and 16-27 for channel 2
|
||||
@li left aligned 12 bit data in bits 4-15 for channel 1 and 20-31 for channel 2
|
||||
|
||||
@param[in] dac_data u32 with appropriate alignment.
|
||||
@param[in] dac_data_format enum ::data_align. Alignment and size.
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_load_data_buffer_single(u32 dac_data, data_align dac_data_format, data_channel dac_channel)
|
||||
{
|
||||
if (dac_channel == CHANNEL_1)
|
||||
{
|
||||
switch (dac_data_format) {
|
||||
case RIGHT8:
|
||||
DAC_DHR8R1 = dac_data;
|
||||
break;
|
||||
case RIGHT12:
|
||||
DAC_DHR12R1 = dac_data;
|
||||
break;
|
||||
case LEFT12:
|
||||
DAC_DHR12L1 = dac_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (dac_channel == CHANNEL_2)
|
||||
{
|
||||
switch (dac_data_format) {
|
||||
case RIGHT8:
|
||||
DAC_DHR8R2 = dac_data;
|
||||
break;
|
||||
case RIGHT12:
|
||||
DAC_DHR12R2 = dac_data;
|
||||
break;
|
||||
case LEFT12:
|
||||
DAC_DHR12L2 = dac_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
switch (dac_data_format) {
|
||||
case RIGHT8:
|
||||
DAC_DHR8RD = dac_data;
|
||||
break;
|
||||
case RIGHT12:
|
||||
DAC_DHR12RD = dac_data;
|
||||
break;
|
||||
case LEFT12:
|
||||
DAC_DHR12LD = dac_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Load DAC Dual Data Register.
|
||||
|
||||
Loads the appropriate digital to analog converter dual data register with 12 or
|
||||
8 bit data to be converted for both channels. This allows high bandwidth
|
||||
simultaneous or independent analog output. The data in both channels are aligned
|
||||
identically.
|
||||
|
||||
@param[in] dac_data1 u32 for channel 1 with appropriate alignment.
|
||||
@param[in] dac_data2 u32 for channel 2 with appropriate alignment.
|
||||
@param[in] dac_data_format enum ::data_align. Right or left aligned, and 8 or 12 bit.
|
||||
*/
|
||||
|
||||
void dac_load_data_buffer_dual(u32 dac_data1, u32 dac_data2, data_align dac_data_format)
|
||||
{
|
||||
switch (dac_data_format) {
|
||||
case RIGHT8:
|
||||
DAC_DHR8RD = ((dac_data1 & MASK8) | ((dac_data2 & MASK8) << 8));
|
||||
break;
|
||||
case RIGHT12:
|
||||
DAC_DHR12RD = ((dac_data1 & MASK12) | ((dac_data2 & MASK12) << 12));
|
||||
break;
|
||||
case LEFT12:
|
||||
DAC_DHR12LD = ((dac_data1 & MASK12) | ((dac_data2 & MASK12) << 16));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Trigger the DAC by a Software Trigger.
|
||||
|
||||
If the trigger source is set to be a software trigger, cause a trigger to occur.
|
||||
The trigger is cleared by hardware after conversion.
|
||||
|
||||
@param[in] dac_channel enum ::data_channel.
|
||||
*/
|
||||
|
||||
void dac_software_trigger(data_channel dac_channel)
|
||||
{
|
||||
switch (dac_channel) {
|
||||
case CHANNEL_1:
|
||||
DAC_SWTRIGR |= DAC_SWTRIGR_SWTRIG1;
|
||||
break;
|
||||
case CHANNEL_2:
|
||||
DAC_SWTRIGR |= DAC_SWTRIGR_SWTRIG2;
|
||||
break;
|
||||
case CHANNEL_D:
|
||||
DAC_SWTRIGR |= (DAC_SWTRIGR_SWTRIG1 | DAC_SWTRIGR_SWTRIG2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
@@ -31,31 +31,9 @@ ARFLAGS = rcs
|
||||
OBJS = vector.o rcc.o gpio.o usart.o adc.o spi.o flash.o nvic.o \
|
||||
rtc.o i2c.o dma.o systick.o exti.o scb.o ethernet.o \
|
||||
usb_f103.o usb.o usb_control.o usb_standard.o can.o \
|
||||
timer.o usb_f107.o
|
||||
timer.o usb_f107.o desig.o crc.o
|
||||
|
||||
VPATH += ../../usb:../
|
||||
|
||||
# Be silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1)
|
||||
Q := @
|
||||
endif
|
||||
|
||||
all: $(LIBNAME).a
|
||||
|
||||
$(LIBNAME).a: $(OBJS)
|
||||
@printf " AR $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
%.o: %.c
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
@printf " CLEAN lib/stm32/f1\n"
|
||||
$(Q)rm -f *.o *.d
|
||||
$(Q)rm -f $(LIBNAME).a
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
-include $(OBJS:.o=.d)
|
||||
include ../../Makefile.include
|
||||
|
||||
|
||||
@@ -1,3 +1,70 @@
|
||||
/** @defgroup STM32F1xx_adc_file ADC
|
||||
|
||||
@ingroup STM32F1xx
|
||||
|
||||
@brief <b>libopencm3 STM32F1xx Analog to Digital Converters</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2009 Edward Cheeseman <evbuilder@users.sourceforge.net>
|
||||
@author @htmlonly © @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
|
||||
|
||||
@date 18 August 2012
|
||||
|
||||
This library supports the A/D Converter Control System in the STM32F1xx series
|
||||
of ARM Cortex Microcontrollers by ST Microelectronics.
|
||||
|
||||
Devices can have up to three A/D converters each with their own set of registers.
|
||||
However all the A/D converters share a common clock which is prescaled from the APB2
|
||||
clock by default by a minimum factor of 2 to a maximum of 8.
|
||||
|
||||
Each A/D converter has up to 18 channels:
|
||||
@li On ADC1 the analog channels 16 and 17 are internally connected to the temperature
|
||||
sensor and V<sub>REFINT</sub>, respectively.
|
||||
@li On ADC2 the analog channels 16 and 17 are internally connected to V<sub>SS</sub>.
|
||||
@li On ADC3 the analog channels 9, 14, 15, 16 and 17 are internally connected to V<sub>SS</sub>.
|
||||
|
||||
The conversions can occur as a one-off conversion whereby the process stops once
|
||||
conversion is complete. The conversions can also be continuous wherein a new
|
||||
conversion starts immediately the previous conversion has ended.
|
||||
|
||||
Conversion can occur as a single channel conversion or a scan of a group of
|
||||
channels in either continuous or one-off mode. If more than one channel is converted
|
||||
in a scan group, DMA must be used to transfer the data as there is only one
|
||||
result register available. An interrupt can be set to occur at the end of
|
||||
conversion, which occurs after all channels have been scanned.
|
||||
|
||||
A discontinuous mode allows a subgroup of group of a channels to be converted in
|
||||
bursts of a given length.
|
||||
|
||||
Injected conversions allow a second group of channels to be converted separately
|
||||
from the regular group. An interrupt can be set to occur at the end of
|
||||
conversion, which occurs after all channels have been scanned.
|
||||
|
||||
@section adc_api_ex Basic ADC Handling API.
|
||||
|
||||
Example 1: Simple single channel conversion polled. Enable the peripheral clock
|
||||
and ADC, reset ADC and set the prescaler divider. Set dual mode to independent.
|
||||
|
||||
@code
|
||||
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN);
|
||||
adc_power_on(ADC1);
|
||||
adc_calibration(ADC1);
|
||||
rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_ADC1RST);
|
||||
rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_ADC1RST);
|
||||
rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV2);
|
||||
adc_set_dual_mode(ADC_CR1_DUALMOD_IND);
|
||||
adc_disable_scan_mode(ADC1);
|
||||
adc_set_single_conversion_mode(ADC1);
|
||||
adc_set_sample_time(ADC1, ADC_CHANNEL0, ADC_SMPR1_SMP_1DOT5CYC);
|
||||
adc_set_single_channel(ADC1, ADC_CHANNEL0);
|
||||
adc_start_conversion_regular(ADC1);
|
||||
while (! adc_eoc(ADC1));
|
||||
reg16 = adc_read_regular(ADC1);
|
||||
@endcode
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
@@ -27,10 +94,12 @@
|
||||
* rcc_peripheral_clear_reset(&RCC_APB2RSTR, ADC1RST);
|
||||
*
|
||||
* rcc_set_adc_clk(ADC_PRE_PLCK2_DIV2);
|
||||
* adc_set_mode(ADC1, TODO);
|
||||
* adc_set_dual_mode(ADC1, TODO);
|
||||
* reg16 = adc_read(ADC1, ADC_CH_0);
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
|
||||
#include <libopencm3/stm32/f1/adc.h>
|
||||
|
||||
void rcc_set_adc_clk(u32 prescaler)
|
||||
@@ -50,6 +119,14 @@ void adc_set_mode(u32 block, /* TODO */ u8 mode)
|
||||
mode = mode;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Read from a Conversion Result Register
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
@param[in] reg Unsigned int8. Register number (1 ... 4).
|
||||
@returns Unsigned int32 conversion result.
|
||||
*/
|
||||
|
||||
void adc_read(u32 block, u32 channel)
|
||||
{
|
||||
/* TODO */
|
||||
@@ -59,61 +136,177 @@ void adc_read(u32 block, u32 channel)
|
||||
channel = channel;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable Analog Watchdog for Regular Conversions
|
||||
|
||||
The analog watchdog allows the monitoring of an analog signal between two threshold
|
||||
levels. The thresholds must be preset. Comparison is done before data alignment
|
||||
takes place, so the thresholds are left-aligned.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_enable_analog_watchdog_regular(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_AWDEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Disable Analog Watchdog for Regular Conversions
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_disable_analog_watchdog_regular(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_AWDEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable Analog Watchdog for Injected Conversions
|
||||
|
||||
The analog watchdog allows the monitoring of an analog signal between two threshold
|
||||
levels. The thresholds must be preset. Comparison is done before data alignment
|
||||
takes place, so the thresholds are left-aligned.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_enable_analog_watchdog_injected(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_JAWDEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Disable Analog Watchdog for Injected Conversions
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_disable_analog_watchdog_injected(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_JAWDEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable Discontinuous Mode for Regular Conversions
|
||||
|
||||
In this mode the ADC converts, on each trigger, a subgroup of up to 8 of the
|
||||
defined regular channel group. The subgroup is defined by the number of
|
||||
consecutive channels to be converted. After a subgroup has been converted
|
||||
the next trigger will start conversion of the immediately following subgroup
|
||||
of the same length or until the whole group has all been converted. When the
|
||||
the whole group has been converted, the next trigger will restart conversion
|
||||
of the subgroup at the beginning of the whole group.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
@param[in] length Unsigned int8. Number of channels in the group @ref adc_cr1_discnum
|
||||
*/
|
||||
|
||||
void adc_enable_discontinous_mode_regular(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_DISCEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Disable Discontinuous Mode for Regular Conversions
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_disable_discontinous_mode_regular(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_DISCEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable Discontinuous Mode for Injected Conversions
|
||||
|
||||
In this mode the ADC converts sequentially one channel of the defined group of
|
||||
injected channels, cycling back to the first channel in the group once the
|
||||
entire group has been converted.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_enable_discontinous_mode_injected(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_JDISCEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Disable Discontinuous Mode for Injected Conversions
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_disable_discontinous_mode_injected(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_JDISCEN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable Automatic Injected Conversions
|
||||
|
||||
The ADC converts a defined injected group of channels immediately after the
|
||||
regular channels have been converted. The external trigger on the injected
|
||||
channels is disabled as required.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_enable_automatic_injected_group_conversion(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_JAUTO;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Disable Automatic Injected Conversions
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_disable_automatic_injected_group_conversion(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_JAUTO;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable Analog Watchdog for All Regular and/or Injected Channels
|
||||
|
||||
The analog watchdog allows the monitoring of an analog signal between two threshold
|
||||
levels. The thresholds must be preset. Comparison is done before data alignment
|
||||
takes place, so the thresholds are left-aligned.
|
||||
|
||||
@note The analog watchdog must be enabled for either or both of the regular or
|
||||
injected channels. If neither are enabled, the analog watchdog feature will be
|
||||
disabled.
|
||||
@ref adc_enable_analog_watchdog_injected, @ref adc_enable_analog_watchdog_regular.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_enable_analog_watchdog_on_all_channels(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_AWDSGL;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable Analog Watchdog for a Selected Channel
|
||||
|
||||
The analog watchdog allows the monitoring of an analog signal between two threshold
|
||||
levels. The thresholds must be preset. Comparison is done before data alignment
|
||||
takes place, so the thresholds are left-aligned.
|
||||
|
||||
@note The analog watchdog must be enabled for either or both of the regular or
|
||||
injected channels. If neither are enabled, the analog watchdog feature will be
|
||||
disabled. If both are enabled, the same channel number is monitored.
|
||||
@ref adc_enable_analog_watchdog_injected, @ref adc_enable_analog_watchdog_regular.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
@param[in] channel Unsigned int8. ADC channel number @ref adc_watchdog_channel
|
||||
*/
|
||||
|
||||
void adc_enable_analog_watchdog_on_selected_channel(u32 adc, u8 channel)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -125,56 +318,140 @@ void adc_enable_analog_watchdog_on_selected_channel(u32 adc, u8 channel)
|
||||
ADC_CR1(adc) &= ~ADC_CR1_AWDSGL;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Set Scan Mode
|
||||
|
||||
In this mode a conversion consists of a scan of the predefined set of channels,
|
||||
regular and injected, each channel conversion immediately following the
|
||||
previous one. It can use single, continuous or discontinuous mode.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_enable_scan_mode(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_SCAN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Disable Scan Mode
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_disable_scan_mode(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_SCAN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable Injected End-Of-Conversion Interrupt
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_enable_jeoc_interrupt(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_JEOCIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Disable Injected End-Of-Conversion Interrupt
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_disable_jeoc_interrupt(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_JEOCIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable Analog Watchdog Interrupt
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_enable_awd_interrupt(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_AWDIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Disable Analog Watchdog Interrupt
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_disable_awd_interrupt(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_AWDIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable Regular End-Of-Conversion Interrupt
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_enable_eoc_interrupt(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) |= ADC_CR1_EOCIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Disable Regular End-Of-Conversion Interrupt
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_disable_eoc_interrupt(u32 adc)
|
||||
{
|
||||
ADC_CR1(adc) &= ~ADC_CR1_EOCIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable The Temperature Sensor
|
||||
|
||||
This enables both the sensor and the reference voltage measurements on channels
|
||||
16 and 17.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_enable_temperature_sensor(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) |= ADC_CR2_TSVREFE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Disable The Temperature Sensor
|
||||
|
||||
Disabling this will reduce power consumption from the sensor and the reference
|
||||
voltage measurements.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_disable_temperature_sensor(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) &= ~ADC_CR2_TSVREFE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Software Triggered Conversion on Regular Channels
|
||||
|
||||
This starts conversion on a set of defined regular channels if the ADC trigger
|
||||
is set to be a software trigger. It is cleared by hardware once conversion
|
||||
starts.
|
||||
|
||||
Note this is a software trigger and requires triggering to be enabled and the
|
||||
trigger source to be set appropriately otherwise conversion will not start.
|
||||
This is not the same as the ADC start conversion operation.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_start_conversion_regular(u32 adc)
|
||||
{
|
||||
/* Start conversion on regular channels. */
|
||||
@@ -184,6 +461,20 @@ void adc_start_conversion_regular(u32 adc)
|
||||
while (ADC_CR2(adc) & ADC_CR2_SWSTART);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Software Triggered Conversion on Injected Channels
|
||||
|
||||
This starts conversion on a set of defined injected channels if the ADC trigger
|
||||
is set to be a software trigger. It is cleared by hardware once conversion
|
||||
starts.
|
||||
|
||||
Note this is a software trigger and requires triggering to be enabled and the
|
||||
trigger source to be set appropriately otherwise conversion will not start.
|
||||
This is not the same as the ADC start conversion operation.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_start_conversion_injected(u32 adc)
|
||||
{
|
||||
/* Start conversion on injected channels. */
|
||||
@@ -193,6 +484,36 @@ void adc_start_conversion_injected(u32 adc)
|
||||
while (ADC_CR2(adc) & ADC_CR2_JSWSTART);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable an External Trigger for Regular Channels
|
||||
|
||||
This enables an external trigger for set of defined regular channels.
|
||||
|
||||
For ADC1 and ADC2
|
||||
@li Timer 1 CC1 event
|
||||
@li Timer 1 CC2 event
|
||||
@li Timer 1 CC3 event
|
||||
@li Timer 2 CC2 event
|
||||
@li Timer 3 TRGO event
|
||||
@li Timer 4 CC4 event
|
||||
@li EXTI (TIM8_TRGO is also possible on some devices, see datasheet)
|
||||
@li Software Start
|
||||
|
||||
For ADC3
|
||||
@li Timer 3 CC1 event
|
||||
@li Timer 2 CC3 event
|
||||
@li Timer 1 CC3 event
|
||||
@li Timer 8 CC1 event
|
||||
@li Timer 8 TRGO event
|
||||
@li Timer 5 CC1 event
|
||||
@li Timer 5 CC3 event
|
||||
@li Software Start
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
@param[in] trigger Unsigned int8. Trigger identifier @ref adc_trigger_regular_12
|
||||
for ADC1 and ADC2, or @ref adc_trigger_regular_3 for ADC3
|
||||
*/
|
||||
|
||||
void adc_enable_external_trigger_regular(u32 adc, u32 trigger)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -204,11 +525,47 @@ void adc_enable_external_trigger_regular(u32 adc, u32 trigger)
|
||||
ADC_CR2(adc) |= ADC_CR2_EXTTRIG;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Disable an External Trigger for Regular Channels
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_disable_external_trigger_regular(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) &= ~ADC_CR2_EXTTRIG;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable an External Trigger for Injected Channels
|
||||
|
||||
This enables an external trigger for set of defined injected channels.
|
||||
|
||||
For ADC1 and ADC2
|
||||
@li Timer 1 TRGO event
|
||||
@li Timer 1 CC4 event
|
||||
@li Timer 2 TRGO event
|
||||
@li Timer 2 CC1 event
|
||||
@li Timer 3 CC4 event
|
||||
@li Timer 4 TRGO event
|
||||
@li EXTI (TIM8 CC4 is also possible on some devices, see datasheet)
|
||||
@li Software Start
|
||||
|
||||
For ADC3
|
||||
@li Timer 1 TRGO event
|
||||
@li Timer 1 CC4 event
|
||||
@li Timer 4 CC3 event
|
||||
@li Timer 8 CC2 event
|
||||
@li Timer 8 CC4 event
|
||||
@li Timer 5 TRGO event
|
||||
@li Timer 5 CC4 event
|
||||
@li Software Start
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
@param[in] trigger Unsigned int8. Trigger identifier @ref adc_trigger_injected_12
|
||||
for ADC1 and ADC2, or @ref adc_trigger_injected_3 for ADC3
|
||||
*/
|
||||
|
||||
void adc_enable_external_trigger_injected(u32 adc, u32 trigger)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -220,65 +577,169 @@ void adc_enable_external_trigger_injected(u32 adc, u32 trigger)
|
||||
ADC_CR2(adc) |= ADC_CR2_JEXTTRIG;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Disable an External Trigger for Injected Channels
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_disable_external_trigger_injected(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) &= ~ADC_CR2_JEXTTRIG;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Set the Data as Left Aligned
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_set_left_aligned(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) |= ADC_CR2_ALIGN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Set the Data as Right Aligned
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_set_right_aligned(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) &= ~ADC_CR2_ALIGN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable DMA Transfers
|
||||
|
||||
Only available for ADC1 through DMA1 channel1, and ADC3 through DMA2 channel5.
|
||||
ADC2 will use DMA if it is set as slave in dual mode with ADC1 in DMA transfer
|
||||
mode.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_enable_dma(u32 adc)
|
||||
{
|
||||
if ((adc == ADC1) | (adc == ADC3))
|
||||
ADC_CR2(adc) |= ADC_CR2_DMA;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Disable DMA Transfers
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_disable_dma(u32 adc)
|
||||
{
|
||||
if ((adc == ADC1) | (adc == ADC3))
|
||||
ADC_CR2(adc) &= ~ADC_CR2_DMA;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Initialize Calibration Registers
|
||||
|
||||
This resets the calibration registers. It is not clear if this is required to be
|
||||
done before every calibration operation.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_reset_calibration(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) |= ADC_CR2_RSTCAL;
|
||||
while (ADC_CR2(adc) & ADC_CR2_RSTCAL);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Calibration
|
||||
|
||||
The calibration data for the ADC is recomputed. The hardware clears the
|
||||
calibration status flag when calibration is complete. This function does not return
|
||||
until this happens and the ADC is ready for use.
|
||||
|
||||
The ADC must have been powered down for at least 2 ADC clock cycles, then powered on.
|
||||
before calibration starts
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_calibration(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) |= ADC_CR2_CAL;
|
||||
while (ADC_CR2(adc) & ADC_CR2_CAL);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable Continuous Conversion Mode
|
||||
|
||||
In this mode the ADC starts a new conversion of a single channel or a channel
|
||||
group immediately following completion of the previous channel group conversion.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_set_continous_conversion_mode(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) |= ADC_CR2_CONT;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Enable Single Conversion Mode
|
||||
|
||||
In this mode the ADC performs a conversion of one channel or a channel group
|
||||
and stops.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_set_single_conversion_mode(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) &= ~ADC_CR2_CONT;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Power On
|
||||
|
||||
If the ADC is in power-down mode then it is powered up. The application needs
|
||||
to wait a time of about 3 microseconds for stabilization before using the ADC.
|
||||
If the ADC is already on this function call will initiate a conversion.
|
||||
|
||||
@todo fix this.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_on(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) |= ADC_CR2_ADON;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Off
|
||||
|
||||
Turn off the ADC to reduce power consumption to a few microamps.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
*/
|
||||
|
||||
void adc_off(u32 adc)
|
||||
{
|
||||
ADC_CR2(adc) &= ~ADC_CR2_ADON;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Set the Sample Time for a Single Channel
|
||||
|
||||
The sampling time can be selected in ADC clock cycles from 1.5 to 239.5.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
@param[in] channel Unsigned int8. ADC Channel integer 0..18 or from @ref adc_channel
|
||||
@param[in] time Unsigned int8. Sampling time selection from @ref adc_sample_rg
|
||||
*/
|
||||
|
||||
void adc_set_conversion_time(u32 adc, u8 channel, u8 time)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -296,6 +757,16 @@ void adc_set_conversion_time(u32 adc, u8 channel, u8 time)
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Set the Sample Time for All Channels
|
||||
|
||||
The sampling time can be selected in ADC clock cycles from 1.5 to 239.5, same for
|
||||
all channels.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
@param[in] time Unsigned int8. Sampling time selection from @ref adc_sample_rg
|
||||
*/
|
||||
|
||||
void adc_set_conversion_time_on_all_channels(u32 adc, u8 time)
|
||||
{
|
||||
u8 i;
|
||||
@@ -310,6 +781,13 @@ void adc_set_conversion_time_on_all_channels(u32 adc, u8 time)
|
||||
ADC_SMPR1(adc) = reg32;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Set Analog Watchdog Upper Threshold
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
@param[in] threshold Unsigned int8. Upper threshold value
|
||||
*/
|
||||
|
||||
void adc_set_watchdog_high_threshold(u32 adc, u16 threshold)
|
||||
{
|
||||
u32 reg32 = 0;
|
||||
@@ -319,6 +797,13 @@ void adc_set_watchdog_high_threshold(u32 adc, u16 threshold)
|
||||
ADC_HTR(adc) = reg32;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Set Analog Watchdog Lower Threshold
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
@param[in] threshold Unsigned int8. Lower threshold value
|
||||
*/
|
||||
|
||||
void adc_set_watchdog_low_threshold(u32 adc, u16 threshold)
|
||||
{
|
||||
u32 reg32 = 0;
|
||||
@@ -328,6 +813,18 @@ void adc_set_watchdog_low_threshold(u32 adc, u16 threshold)
|
||||
ADC_LTR(adc) = reg32;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Set a Regular Channel Conversion Sequence
|
||||
|
||||
Define a sequence of channels to be converted as a regular group with a length
|
||||
from 1 to 16 channels. If this is called during conversion, the current conversion
|
||||
is reset and conversion begins again with the newly defined group.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
@param[in] length Unsigned int8. Number of channels in the group.
|
||||
@param[in] channel Unsigned int8[]. Set of channels in sequence, integers 0..18.
|
||||
*/
|
||||
|
||||
void adc_set_regular_sequence(u32 adc, u8 length, u8 channel[])
|
||||
{
|
||||
u32 reg32_1 = 0, reg32_2 = 0, reg32_3 = 0;
|
||||
@@ -352,6 +849,18 @@ void adc_set_regular_sequence(u32 adc, u8 length, u8 channel[])
|
||||
ADC_SQR3(adc) = reg32_3;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Set an Injected Channel Conversion Sequence
|
||||
|
||||
Defines a sequence of channels to be converted as an injected group with a length
|
||||
from 1 to 4 channels. If this is called during conversion, the current conversion
|
||||
is reset and conversion begins again with the newly defined group.
|
||||
|
||||
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
|
||||
@param[in] length Unsigned int8. Number of channels in the group.
|
||||
@param[in] channel Unsigned int8[]. Set of channels in sequence, integers 0..18
|
||||
*/
|
||||
|
||||
void adc_set_injected_sequence(u32 adc, u8 length, u8 channel[])
|
||||
{
|
||||
u32 reg32 = 0;
|
||||
@@ -368,3 +877,6 @@ void adc_set_injected_sequence(u32 adc, u8 length, u8 channel[])
|
||||
|
||||
ADC_JSQR(adc) = reg32;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
||||
37
lib/stm32/f1/desig.c
Normal file
37
lib/stm32/f1/desig.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@ŧweak.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/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/f1/desig.h>
|
||||
|
||||
u16 desig_get_flash_size(void)
|
||||
{
|
||||
return DESIG_FLASH_SIZE;
|
||||
}
|
||||
|
||||
void desig_get_unique_id(u32 result[])
|
||||
{
|
||||
// Could also just return a pointer to the start? read it as they wish?
|
||||
u16 bits15_0 = DESIG_UID_15_0;
|
||||
u32 bits31_16 = DESIG_UID_31_16;
|
||||
u32 bits63_32 = DESIG_UID_63_32;
|
||||
u32 bits95_64 = DESIG_UID_95_64;
|
||||
result[0] = bits95_64;
|
||||
result[1] = bits63_32;
|
||||
result[2] = bits31_16 << 16 | bits15_0;
|
||||
}
|
||||
@@ -1,3 +1,24 @@
|
||||
/** @defgroup STM32F1xx-dma-file DMA
|
||||
|
||||
@ingroup STM32F1xx
|
||||
|
||||
@brief <b>libopencm3 STM32F1xx DMA Controller</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
|
||||
|
||||
@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).
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
@@ -17,8 +38,19 @@
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
|
||||
#include <libopencm3/stm32/f1/dma.h>
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Reset
|
||||
|
||||
The channel is disabled and configuration registers are cleared.
|
||||
|
||||
@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_channel_reset(u32 dma, u8 channel)
|
||||
{
|
||||
/* Disable channel. */
|
||||
@@ -35,18 +67,51 @@ void dma_channel_reset(u32 dma, u8 channel)
|
||||
DMA_IFCR(dma) |= DMA_IFCR_CIF(channel);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Enable Memory to Memory Transfers
|
||||
|
||||
Memory to memory transfers do not require a trigger to activate each transfer.
|
||||
Transfers begin immediately the channel has been enabled, and proceed without
|
||||
intervention.
|
||||
|
||||
@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_mem2mem_mode(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) |= DMA_CCR_MEM2MEM;
|
||||
DMA_CCR(dma, channel) &= ~DMA_CCR_CIRC;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Set Priority
|
||||
|
||||
Channel Priority has four levels: low to very high. This has precedence over the
|
||||
hardware priority.
|
||||
|
||||
@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
|
||||
@param[in] prio unsigned int32. Priority level @ref dma_ch_pri.
|
||||
*/
|
||||
|
||||
void dma_set_priority(u32 dma, u8 channel, u32 prio)
|
||||
{
|
||||
DMA_CCR(dma, channel) &= ~(DMA_CCR_PL_MASK);
|
||||
DMA_CCR(dma, channel) |= prio;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel 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.
|
||||
|
||||
@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
|
||||
@param[in] mem_size unsigned int32. Memory word width @ref dma_ch_memwidth.
|
||||
*/
|
||||
|
||||
void dma_set_memory_size(u32 dma, u8 channel, u32 mem_size)
|
||||
{
|
||||
|
||||
@@ -54,89 +119,249 @@ void dma_set_memory_size(u32 dma, u8 channel, u32 mem_size)
|
||||
DMA_CCR(dma, channel) |= mem_size;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel 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.
|
||||
|
||||
@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
|
||||
@param[in] peripheral_size unsigned int32. Peripheral word width @ref dma_ch_perwidth.
|
||||
*/
|
||||
|
||||
void dma_set_peripheral_size(u32 dma, u8 channel, u32 peripheral_size)
|
||||
{
|
||||
DMA_CCR(dma, channel) &= ~(DMA_CCR_PSIZE_MASK);
|
||||
DMA_CCR(dma, channel) |= peripheral_size;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel 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.
|
||||
|
||||
@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_memory_increment_mode(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) |= DMA_CCR_MINC;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Disable Memory 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_enable_peripheral_increment_mode(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) |= DMA_CCR_PINC;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel 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.
|
||||
|
||||
@note This cannot be used with memory to memory mode, which is explictly
|
||||
disabled here.
|
||||
|
||||
@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_circular_mode(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) |= DMA_CCR_CIRC;
|
||||
DMA_CCR(dma, channel) &= ~DMA_CCR_MEM2MEM;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Enable Transfers from a Peripheral
|
||||
|
||||
The data direction is set to read from a peripheral.
|
||||
|
||||
@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_set_read_from_peripheral(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) &= ~DMA_CCR_DIR;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Enable Transfers from Memory
|
||||
|
||||
The data direction is set to read from memory.
|
||||
|
||||
@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_set_read_from_memory(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) |= DMA_CCR_DIR;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Enable Interrupt on Transfer Error
|
||||
|
||||
@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_transfer_error_interrupt(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) |= DMA_CCR_TEIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Disable Interrupt on Transfer Error
|
||||
|
||||
@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_transfer_error_interrupt(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) &= ~DMA_CCR_TEIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Enable Interrupt on Transfer Half Complete
|
||||
|
||||
@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_half_transfer_interrupt(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) |= DMA_CCR_HTIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Disable Interrupt on Transfer Half Complete
|
||||
|
||||
@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_half_transfer_interrupt(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) &= ~DMA_CCR_HTIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Enable Interrupt on Transfer Complete
|
||||
|
||||
@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_transfer_complete_interrupt(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) |= DMA_CCR_TCIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Disable Interrupt on Transfer Complete
|
||||
|
||||
@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_transfer_complete_interrupt(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) &= ~DMA_CCR_TCIE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Enable
|
||||
|
||||
@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_channel(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) |= DMA_CCR_EN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Disable
|
||||
|
||||
@note The DMA channel registers retain their values when the channel is disabled.
|
||||
|
||||
@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_channel(u32 dma, u8 channel)
|
||||
{
|
||||
DMA_CCR(dma, channel) &= ~DMA_CCR_EN;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel 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 channel must be disabled before setting this address. This function
|
||||
has no effect if the channel is enabled.
|
||||
|
||||
@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
|
||||
@param[in] address unsigned int32. Peripheral Address.
|
||||
*/
|
||||
|
||||
void dma_set_peripheral_address(u32 dma, u8 channel, u32 address)
|
||||
{
|
||||
DMA_CPAR(dma, channel) = (u32) address;
|
||||
if (!(DMA_CCR(dma, channel) & DMA_CCR_EN))
|
||||
DMA_CPAR(dma, channel) = (u32) address;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Set the Base Memory Address
|
||||
|
||||
@note The DMA channel must be disabled before setting this address. This function
|
||||
has no effect if the channel is enabled.
|
||||
|
||||
@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
|
||||
@param[in] address unsigned int32. Memory Initial Address.
|
||||
*/
|
||||
|
||||
void dma_set_memory_address(u32 dma, u8 channel, u32 address)
|
||||
{
|
||||
DMA_CMAR(dma, channel) = (u32) address;
|
||||
if (!(DMA_CCR(dma, channel) & DMA_CCR_EN))
|
||||
DMA_CMAR(dma, channel) = (u32) address;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief DMA Channel Set the Transfer Block Size
|
||||
|
||||
@note The DMA channel must be disabled before setting this count value. The count
|
||||
is not changed if the channel is enabled.
|
||||
|
||||
@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
|
||||
@param[in] number unsigned int16. Number of data words to transfer (65535 maximum).
|
||||
*/
|
||||
|
||||
void dma_set_number_of_data(u32 dma, u8 channel, u16 number)
|
||||
{
|
||||
DMA_CNDTR(dma, channel) = number;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
|
||||
@@ -1,3 +1,61 @@
|
||||
/** @defgroup STM32F1xx_gpio_file GPIO
|
||||
|
||||
@ingroup STM32F1xx
|
||||
|
||||
@brief <b>libopencm3 STM32F1xx General Purpose I/O</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
@author @htmlonly © @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
|
||||
|
||||
@date 18 August 2012
|
||||
|
||||
This library supports the General Purpose I/O System in the STM32F1xx series
|
||||
of ARM Cortex Microcontrollers by ST Microelectronics.
|
||||
|
||||
Each I/O port has 16 individually configurable bits. Many I/O pins share GPIO
|
||||
functionality with a number of alternate functions and must be configured to the
|
||||
alternate function mode if these are to be accessed. A feature is available to
|
||||
remap alternative functions to a limited set of alternative pins in the event
|
||||
of a clash of requirements.
|
||||
|
||||
The data registers associated with each port for input and output are 32 bit with
|
||||
the upper 16 bits unused. The output buffer must be written as a 32 bit word, but
|
||||
individual bits may be set or reset separately in atomic operations to avoid race
|
||||
conditions during interrupts. Bits may also be individually locked to prevent
|
||||
accidental configuration changes. Once locked the configuration cannot be changed
|
||||
until after the next reset.
|
||||
|
||||
Each port bit can be configured as analog or digital input, the latter can be
|
||||
floating or pulled up or down. As outputs they can be configured as either
|
||||
push-pull or open drain, digital I/O or alternate function, and with maximum
|
||||
output speeds of 2MHz, 10MHz, or 50MHz.
|
||||
|
||||
On reset all ports are configured as digital floating input.
|
||||
|
||||
@section gpio_api_ex Basic GPIO Handling API.
|
||||
|
||||
Example 1: Push-pull digital output actions on ports C2 and C9
|
||||
|
||||
@code
|
||||
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, GPIO2 | GPIO9);
|
||||
gpio_set(GPIOC, GPIO2 | GPIO9);
|
||||
gpio_clear(GPIOC, GPIO2);
|
||||
gpio_toggle(GPIOC, GPIO2 | GPIO9);
|
||||
gpio_port_write(GPIOC, 0x204);
|
||||
@endcode
|
||||
|
||||
Example 1: Digital input on port C12
|
||||
|
||||
@code
|
||||
gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT, GPIO12);
|
||||
reg16 = gpio_port_read(GPIOC);
|
||||
@endcode
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
@@ -33,9 +91,23 @@
|
||||
* TODO:
|
||||
* - GPIO remapping support
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
#include <libopencm3/stm32/f1/gpio.h>
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Set GPIO Pin Mode
|
||||
|
||||
Sets the mode (input/output) and configuration (analog/digitial and
|
||||
open drain/push pull), for a set of GPIO pins on a given GPIO port.
|
||||
|
||||
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
|
||||
@param[in] mode Unsigned int8. Pin mode @ref gpio_mode
|
||||
@param[in] cnf Unsigned int8. Pin configuration @ref gpio_cnf
|
||||
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
|
||||
If multiple pins are to be set, use logical OR '|' to separate them.
|
||||
*/
|
||||
|
||||
void gpio_set_mode(u32 gpioport, u8 mode, u8 cnf, u16 gpios)
|
||||
{
|
||||
u16 i, offset = 0;
|
||||
@@ -73,69 +145,99 @@ void gpio_set_mode(u32 gpioport, u8 mode, u8 cnf, u16 gpios)
|
||||
GPIO_CRH(gpioport) = crh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set one or more pins of the given GPIO port to 1.
|
||||
*
|
||||
* @param gpioport The GPIO port to use (GPIOA - GPIOG).
|
||||
* @param gpios The GPIO pin(s) to set to 1 (GPIO0 - GPIO15, or GPIO_ALL).
|
||||
* If multiple pins shall be set, use '|' to separate them.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Set a Group of Pins Atomic
|
||||
|
||||
Set one or more pins of the given GPIO port to 1 in an atomic operation.
|
||||
|
||||
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
|
||||
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
|
||||
If multiple pins are to be changed, use logical OR '|' to separate them.
|
||||
*/
|
||||
void gpio_set(u32 gpioport, u16 gpios)
|
||||
{
|
||||
GPIO_BSRR(gpioport) = gpios;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear one or more pins of the given GPIO port to 0.
|
||||
*
|
||||
* @param gpioport The GPIO port to use (GPIOA - GPIOG).
|
||||
* @param gpios The GPIO pin(s) to set to 0 (GPIO0 - GPIO15, or GPIO_ALL).
|
||||
* If multiple pins shall be cleared, use '|' to separate them.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Clear a Group of Pins Atomic
|
||||
|
||||
Clear one or more pins of the given GPIO port to 0 in an atomic operation.
|
||||
|
||||
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
|
||||
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
|
||||
If multiple pins are to be changed, use logical OR '|' to separate them.
|
||||
*/
|
||||
void gpio_clear(u32 gpioport, u16 gpios)
|
||||
{
|
||||
GPIO_BRR(gpioport) = gpios;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Read a Group of Pins.
|
||||
|
||||
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
|
||||
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
|
||||
If multiple pins are to be read, use logical OR '|' to separate them.
|
||||
@return Unsigned int16 value of the pin values. The bit position of the pin value
|
||||
returned corresponds to the pin number.
|
||||
*/
|
||||
u16 gpio_get(u32 gpioport, u16 gpios)
|
||||
{
|
||||
return gpio_port_read(gpioport) & gpios;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle one or more pins of the given GPIO port.
|
||||
*
|
||||
* @param gpioport The GPIO port to use (GPIOA - GPIOG).
|
||||
* @param gpios The GPIO pin(s) to toggle (GPIO0 - GPIO15, or GPIO_ALL).
|
||||
* If multiple pins shall be toggled, use '|' to separate them.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Toggle a Group of Pins
|
||||
|
||||
Toggle one or more pins of the given GPIO port. This is not an atomic operation.
|
||||
|
||||
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
|
||||
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
|
||||
If multiple pins are to be changed, use logical OR '|' to separate them.
|
||||
*/
|
||||
void gpio_toggle(u32 gpioport, u16 gpios)
|
||||
{
|
||||
GPIO_ODR(gpioport) ^= gpios;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the current value of the given GPIO port.
|
||||
*
|
||||
* @param gpioport The GPIO port to read (GPIOA - GPIOG).
|
||||
* @return The value of the current GPIO port.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Read from a Port
|
||||
|
||||
Read the current value of the given GPIO port. Only the lower 16 bits contain
|
||||
valid pin data.
|
||||
|
||||
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
|
||||
@return Unsigned int16. The value held in the specified GPIO port.
|
||||
*/
|
||||
u16 gpio_port_read(u32 gpioport)
|
||||
{
|
||||
return (u16)GPIO_IDR(gpioport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to the given GPIO port.
|
||||
*
|
||||
* @param gpioport The GPIO port to write to (GPIOA - GPIOG).
|
||||
* @param data The data to write to the specified GPIO port.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Write to a Port
|
||||
|
||||
Write a value to the given GPIO port.
|
||||
|
||||
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
|
||||
@param[in] data Unsigned int16. The value to be written to the GPIO port.
|
||||
*/
|
||||
void gpio_port_write(u32 gpioport, u16 data)
|
||||
{
|
||||
GPIO_ODR(gpioport) = data;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Lock the Configuration of a Group of Pins
|
||||
|
||||
The configuration of one or more pins of the given GPIO port is locked. There is
|
||||
no mechanism to unlock these via software. Unlocking occurs at the next reset.
|
||||
|
||||
@param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id
|
||||
@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id
|
||||
If multiple pins are to be locked, use logical OR '|' to separate them.
|
||||
*/
|
||||
void gpio_port_config_lock(u32 gpioport, u16 gpios)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -147,5 +249,69 @@ void gpio_port_config_lock(u32 gpioport, u16 gpios)
|
||||
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. */
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Map the EVENTOUT signal
|
||||
|
||||
Enable the EVENTOUT signal and select the port and pin to be used.
|
||||
|
||||
@param[in] evoutport Unsigned int8. Port for EVENTOUT signal @ref afio_evcr_port
|
||||
@param[in] evoutpin Unsigned int8. Pin for EVENTOUT signal @ref afio_evcr_pin
|
||||
*/
|
||||
void gpio_set_eventout(u8 evoutport, u8 evoutpin)
|
||||
{
|
||||
AFIO_EVCR = AFIO_EVCR_EVOE | evoutport | evoutpin;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Map Alternate Function Port Bits (Main Set)
|
||||
|
||||
A number of alternate function ports can be remapped to defined alternative
|
||||
port bits to avoid clashes in cases where multiple alternate functions are present.
|
||||
Refer to the datasheets for the particular mapping desired. This provides the main
|
||||
set of remap functionality. See @ref gpio_secondary_remap for a number of lesser used
|
||||
remaps.
|
||||
|
||||
The AFIO remapping feature is used only with the STM32F10x series.
|
||||
|
||||
@note The Serial Wire JTAG disable controls allow certain GPIO ports to become available
|
||||
in place of some of the SWJ signals. Full SWJ capability is obtained by setting this to
|
||||
zero. The value of this must be specified for every call to this function as its current
|
||||
value cannot be ascertained from the hardware.
|
||||
|
||||
@param[in] swjdisable Unsigned int8. Disable parts of the SWJ capability @ref afio_swj_disable.
|
||||
@param[in] maps Unsigned int32. Logical OR of map enable controls from @ref afio_remap,
|
||||
@ref afio_remap_can1, @ref afio_remap_tim3, @ref afio_remap_tim2, @ref afio_remap_tim1,
|
||||
@ref afio_remap_usart3. For connectivity line devices only @ref afio_remap_cld are
|
||||
also available.
|
||||
*/
|
||||
void gpio_primary_remap(u8 swjdisable, u32 maps)
|
||||
{
|
||||
AFIO_MAPR = swjdisable | (maps & 0x1FFFFF);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief Map Alternate Function Port Bits (Secondary Set)
|
||||
|
||||
A number of alternate function ports can be remapped to defined alternative
|
||||
port bits to avoid clashes in cases where multiple alternate functions are present.
|
||||
Refer to the datasheets for the particular mapping desired. This provides the second
|
||||
smaller and less used set of remap functionality. See @ref gpio_primary_remap for
|
||||
the main set of remaps.
|
||||
|
||||
The AFIO remapping feature is used only with the STM32F10x series.
|
||||
|
||||
@param[in] maps Unsigned int32. Logical OR of map enable controls from @ref afio_remap2
|
||||
*/
|
||||
void gpio_secondary_remap(u32 maps)
|
||||
{
|
||||
AFIO_MAPR2 = maps;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
||||
@@ -30,21 +30,18 @@ ENTRY(reset_handler)
|
||||
/* Define sections. */
|
||||
SECTIONS
|
||||
{
|
||||
. = ORIGIN(rom);
|
||||
|
||||
.text : {
|
||||
*(.vectors) /* Vector table */
|
||||
*(.text*) /* Program code */
|
||||
. = ALIGN(4);
|
||||
*(.rodata*) /* Read-only data */
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
} >rom
|
||||
|
||||
/*
|
||||
* Another section used by C++ stuff, appears when using newlib with
|
||||
* 64bit (long long) printf support
|
||||
*/
|
||||
* Another section used by C++ stuff, appears when using newlib with
|
||||
* 64bit (long long) printf support
|
||||
*/
|
||||
.ARM.extab : {
|
||||
*(.ARM.extab*)
|
||||
} >rom
|
||||
@@ -54,21 +51,23 @@ SECTIONS
|
||||
__exidx_end = .;
|
||||
} >rom
|
||||
|
||||
. = ORIGIN(ram);
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
|
||||
.data : AT (__exidx_end) {
|
||||
.data : {
|
||||
_data = .;
|
||||
*(.data*) /* Read-write initialized data */
|
||||
. = ALIGN(4);
|
||||
_edata = .;
|
||||
} >ram
|
||||
} >ram AT >rom
|
||||
_data_loadaddr = LOADADDR(.data);
|
||||
|
||||
.bss : {
|
||||
*(.bss*) /* Read-write zero initialized data */
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = .;
|
||||
} >ram AT >rom
|
||||
} >ram
|
||||
|
||||
/*
|
||||
* The .eh_frame section appears to be used for C++ exception handling.
|
||||
|
||||
217
lib/stm32/f1/pwr.c
Normal file
217
lib/stm32/f1/pwr.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/** @defgroup STM32F1xx-pwr-file PWR
|
||||
|
||||
@ingroup STM32F1xx
|
||||
|
||||
@brief <b>libopencm3 STM32F1xx Power Control</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
|
||||
|
||||
@date 18 August 2012
|
||||
|
||||
This library supports the power control system for the
|
||||
STM32F1 series of ARM Cortex Microcontrollers by ST Microelectronics.
|
||||
|
||||
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/pwr.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Disable Backup Domain Write Protection.
|
||||
|
||||
This allows backup domain registers to be changed. These registers are write
|
||||
protected after a reset.
|
||||
*/
|
||||
|
||||
void pwr_disable_backup_domain_write_protect(void)
|
||||
{
|
||||
PWR_CR |= PWR_CR_DBP;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Re-enable Backup Domain Write Protection.
|
||||
|
||||
This protects backup domain registers from inadvertent change.
|
||||
*/
|
||||
|
||||
void pwr_enable_backup_domain_write_protect(void)
|
||||
{
|
||||
PWR_CR &= ~PWR_CR_DBP;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Enable Power Voltage Detector.
|
||||
|
||||
This provides voltage level threshold detection. The result of detection is
|
||||
provided in the power voltage detector output flag (see @ref pwr_voltage_high)
|
||||
or by setting the EXTI16 interrupt (see datasheet for configuration details).
|
||||
|
||||
@param[in] pvd_level u32. Taken from @ref pwr_pls.
|
||||
*/
|
||||
|
||||
void pwr_enable_power_voltage_detect(u32 pvd_level)
|
||||
{
|
||||
PWR_CR &= ~PWR_CR_PLS_MASK;
|
||||
PWR_CR |= (PWR_CR_PVDE | pvd_level);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Disable Power Voltage Detector.
|
||||
|
||||
*/
|
||||
|
||||
void pwr_disable_power_voltage_detect(void)
|
||||
{
|
||||
PWR_CR &= ~PWR_CR_PVDE;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Clear the Standby Flag.
|
||||
|
||||
This is set when the processor returns from a standby mode.
|
||||
*/
|
||||
|
||||
void pwr_clear_standby_flag(void)
|
||||
{
|
||||
PWR_CR |= PWR_CR_CSBF;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Clear the Wakeup Flag.
|
||||
|
||||
This is set when the processor receives a wakeup signal.
|
||||
*/
|
||||
|
||||
void pwr_clear_wakeup_flag(void)
|
||||
{
|
||||
PWR_CR |= PWR_CR_CWUF;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Set Standby Mode in Deep Sleep.
|
||||
|
||||
*/
|
||||
|
||||
void pwr_set_standby_mode(void)
|
||||
{
|
||||
PWR_CR |= PWR_CR_PDDS;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Set Stop Mode in Deep Sleep.
|
||||
|
||||
*/
|
||||
|
||||
void pwr_set_stop_mode(void)
|
||||
{
|
||||
PWR_CR &= ~PWR_CR_PDDS;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Voltage Regulator On in Stop Mode.
|
||||
|
||||
*/
|
||||
|
||||
void pwr_voltage_regulator_on_in_stop(void)
|
||||
{
|
||||
PWR_CR &= ~PWR_CR_LPDS;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Voltage Regulator Low Power in Stop Mode.
|
||||
|
||||
*/
|
||||
|
||||
void pwr_voltage_regulator_low_power_in_stop(void)
|
||||
{
|
||||
PWR_CR |= PWR_CR_LPDS;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Enable Wakeup Pin.
|
||||
|
||||
The wakeup pin is used for waking the processor from standby mode.
|
||||
*/
|
||||
|
||||
void pwr_enable_wakeup_pin(void)
|
||||
{
|
||||
PWR_CSR |= PWR_CR_EWUP;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Release Wakeup Pin.
|
||||
|
||||
The wakeup pin is used for general purpose I/O.
|
||||
*/
|
||||
|
||||
void pwr_disable_wakeup_pin(void)
|
||||
{
|
||||
PWR_CSR &= ~PWR_CR_EWUP;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Get Voltage Detector Output.
|
||||
|
||||
The voltage detector threshold must be set when the power voltage detector is
|
||||
enabled, see @ref pwr_enable_power_voltage_detect.
|
||||
|
||||
@returns boolean: TRUE if the power voltage is above the preset voltage
|
||||
threshold.
|
||||
*/
|
||||
|
||||
bool pwr_voltage_high(void)
|
||||
{
|
||||
return (PWR_CSR & PWR_CR_PVDO);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Get Standby Flag.
|
||||
|
||||
The standby flag is set when the processor returns from a standby state. It is
|
||||
cleared by software (see @ref pwr_clear_standby_flag).
|
||||
|
||||
@returns boolean: TRUE if the processor was in standby state.
|
||||
*/
|
||||
|
||||
bool pwr_get_standby_flag(void)
|
||||
{
|
||||
return (PWR_CSR & PWR_CR_SBF);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Get Wakeup Flag.
|
||||
|
||||
The wakeup flag is set when a wakeup event has been received. It is
|
||||
cleared by software (see @ref pwr_clear_wakeup_flag).
|
||||
|
||||
@returns boolean: TRUE if a wakeup event was received.
|
||||
*/
|
||||
|
||||
bool pwr_get_wakeup_flag(void)
|
||||
{
|
||||
return (PWR_CSR & PWR_CR_WUF);
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
@@ -1,3 +1,30 @@
|
||||
/** @defgroup STM32F1xx-rcc-file RCC
|
||||
|
||||
@ingroup STM32F1xx
|
||||
|
||||
@brief <b>libopencm3 STM32F1xx Reset and Clock Control</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2009 Federico Ruiz-Ugalde \<memeruiz at gmail dot com\>
|
||||
@author @htmlonly © @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
@author @htmlonly © @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
|
||||
|
||||
@date 18 August 2012
|
||||
|
||||
This library supports the Reset and Clock Control System in the STM32F1xx
|
||||
series of ARM Cortex Microcontrollers by ST Microelectronics.
|
||||
|
||||
@note Full support for connection line devices is not yet provided.
|
||||
|
||||
Clock settings and resets for many peripherals are given here rather than in the
|
||||
corresponding peripheral library.
|
||||
|
||||
The library also provides a number of common configurations for the processor
|
||||
system clock. Not all possible configurations are included.
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
@@ -19,13 +46,24 @@
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
|
||||
#include <libopencm3/stm32/f1/rcc.h>
|
||||
#include <libopencm3/stm32/f1/flash.h>
|
||||
|
||||
/* Set the default ppre1 and ppre2 peripheral clock frequencies after reset. */
|
||||
/** Default ppre1 peripheral clock frequency after reset. */
|
||||
u32 rcc_ppre1_frequency = 8000000;
|
||||
/** Default ppre2 peripheral clock frequency after reset. */
|
||||
u32 rcc_ppre2_frequency = 8000000;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Clear the Oscillator Ready Interrupt Flag
|
||||
|
||||
Clear the interrupt flag that was set when a clock oscillator became ready to use.
|
||||
|
||||
@param[in] osc enum ::osc_t. Oscillator ID
|
||||
*/
|
||||
|
||||
void rcc_osc_ready_int_clear(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
@@ -47,6 +85,12 @@ void rcc_osc_ready_int_clear(osc_t osc)
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Enable the Oscillator Ready Interrupt
|
||||
|
||||
@param[in] osc enum ::osc_t. Oscillator ID
|
||||
*/
|
||||
|
||||
void rcc_osc_ready_int_enable(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
@@ -68,6 +112,12 @@ void rcc_osc_ready_int_enable(osc_t osc)
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Disable the Oscillator Ready Interrupt
|
||||
|
||||
@param[in] osc enum ::osc_t. Oscillator ID
|
||||
*/
|
||||
|
||||
void rcc_osc_ready_int_disable(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
@@ -89,6 +139,13 @@ void rcc_osc_ready_int_disable(osc_t osc)
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Read the Oscillator Ready Interrupt Flag
|
||||
|
||||
@param[in] osc enum ::osc_t. Oscillator ID
|
||||
@returns int. Boolean value for flag set.
|
||||
*/
|
||||
|
||||
int rcc_osc_ready_int_flag(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
@@ -113,16 +170,33 @@ int rcc_osc_ready_int_flag(osc_t osc)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Clear the Clock Security System Interrupt Flag
|
||||
|
||||
*/
|
||||
|
||||
void rcc_css_int_clear(void)
|
||||
{
|
||||
RCC_CIR |= RCC_CIR_CSSC;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Read the Clock Security System Interrupt Flag
|
||||
|
||||
@returns int. Boolean value for flag set.
|
||||
*/
|
||||
|
||||
int rcc_css_int_flag(void)
|
||||
{
|
||||
return ((RCC_CIR & RCC_CIR_CSSF) != 0);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Wait for Oscillator Ready.
|
||||
|
||||
@param[in] osc enum ::osc_t. Oscillator ID
|
||||
*/
|
||||
|
||||
void rcc_wait_for_osc_ready(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
@@ -144,6 +218,20 @@ void rcc_wait_for_osc_ready(osc_t osc)
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Turn on an Oscillator.
|
||||
|
||||
Enable an oscillator and power on. Each oscillator requires an amount of time to
|
||||
settle to a usable state. Refer to datasheets for time delay information. A status
|
||||
flag is available to indicate when the oscillator becomes ready (see
|
||||
@ref rcc_osc_ready_int_flag and @ref rcc_wait_for_osc_ready).
|
||||
|
||||
@note The LSE clock is in the backup domain and cannot be enabled until the
|
||||
backup domain write protection has been removed (see @ref pwr_disable_backup_domain_write_protect).
|
||||
|
||||
@param[in] osc enum ::osc_t. Oscillator ID
|
||||
*/
|
||||
|
||||
void rcc_osc_on(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
@@ -165,6 +253,20 @@ void rcc_osc_on(osc_t osc)
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Turn off an Oscillator.
|
||||
|
||||
Disable an oscillator and power off.
|
||||
|
||||
@note An oscillator cannot be turned off if it is selected as the system clock.
|
||||
@note The LSE clock is in the backup domain and cannot be disabled until the
|
||||
backup domain write protection has been removed (see
|
||||
@ref pwr_disable_backup_domain_write_protect) or the backup domain has been
|
||||
(see reset @ref rcc_backupdomain_reset).
|
||||
|
||||
@param[in] osc enum ::osc_t. Oscillator ID
|
||||
*/
|
||||
|
||||
void rcc_osc_off(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
@@ -186,16 +288,39 @@ void rcc_osc_off(osc_t osc)
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Enable the Clock Security System.
|
||||
|
||||
*/
|
||||
|
||||
void rcc_css_enable(void)
|
||||
{
|
||||
RCC_CR |= RCC_CR_CSSON;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Disable the Clock Security System.
|
||||
|
||||
*/
|
||||
|
||||
void rcc_css_disable(void)
|
||||
{
|
||||
RCC_CR &= ~RCC_CR_CSSON;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Enable Bypass.
|
||||
|
||||
Enable an external clock to bypass the internal clock (high speed and low speed
|
||||
clocks only). The external clock must be enabled (see @ref rcc_osc_on)
|
||||
and the internal clock must be disabled (see @ref rcc_osc_off) for this to have effect.
|
||||
|
||||
@note The LSE clock is in the backup domain and cannot be bypassed until the
|
||||
backup domain write protection has been removed (see @ref pwr_disable_backup_domain_write_protect).
|
||||
|
||||
@param[in] osc enum ::osc_t. Oscillator ID. Only HSE and LSE have effect.
|
||||
*/
|
||||
|
||||
void rcc_osc_bypass_enable(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
@@ -213,6 +338,19 @@ void rcc_osc_bypass_enable(osc_t osc)
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Disable Bypass.
|
||||
|
||||
Re-enable the internal clock (high speed and low speed clocks only). The internal
|
||||
clock must be disabled (see @ref rcc_osc_off) for this to have effect.
|
||||
|
||||
@note The LSE clock is in the backup domain and cannot have bypass removed until the
|
||||
backup domain write protection has been removed (see @ref pwr_disable_backup_domain_write_protect)
|
||||
or the backup domain has been reset (see @ref rcc_backupdomain_reset).
|
||||
|
||||
@param[in] osc enum ::osc_t. Oscillator ID. Only HSE and LSE have effect.
|
||||
*/
|
||||
|
||||
void rcc_osc_bypass_disable(osc_t osc)
|
||||
{
|
||||
switch (osc) {
|
||||
@@ -230,26 +368,96 @@ void rcc_osc_bypass_disable(osc_t osc)
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Enable Peripheral Clocks.
|
||||
|
||||
Enable the clock on particular peripherals. There are three registers
|
||||
involved, each one controlling the enabling of clocks associated with the AHB,
|
||||
APB1 and APB2 respectively. Several peripherals could be
|
||||
enabled simultaneously <em>only if they are controlled by the same register</em>.
|
||||
|
||||
@param[in] *reg Unsigned int32. Pointer to a Clock Enable Register
|
||||
(either RCC_AHBENR, RCC_APB1ENR or RCC_APB2ENR)
|
||||
@param[in] en Unsigned int32. Logical OR of all enables to be set
|
||||
@li If register is RCC_AHBER, from @ref rcc_ahbenr_en
|
||||
@li If register is RCC_APB1ENR, from @ref rcc_apb1enr_en
|
||||
@li If register is RCC_APB2ENR, from @ref rcc_apb2enr_en
|
||||
*/
|
||||
|
||||
void rcc_peripheral_enable_clock(volatile u32 *reg, u32 en)
|
||||
{
|
||||
*reg |= en;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Disable Peripheral Clocks.
|
||||
|
||||
Enable the clock on particular peripherals. There are three registers
|
||||
involved, each one controlling the enabling of clocks associated with the AHB,
|
||||
APB1 and APB2 respectively. Several peripherals could be
|
||||
disabled simultaneously <em>only if they are controlled by the same register</em>.
|
||||
|
||||
@param[in] *reg Unsigned int32. Pointer to a Clock Enable Register
|
||||
(either RCC_AHBENR, RCC_APB1ENR or RCC_APB2ENR)
|
||||
@param[in] en Unsigned int32. Logical OR of all enables to be used for disabling.
|
||||
@li If register is RCC_AHBER, from @ref rcc_ahbenr_en
|
||||
@li If register is RCC_APB1ENR, from @ref rcc_apb1enr_en
|
||||
@li If register is RCC_APB2ENR, from @ref rcc_apb2enr_en
|
||||
*/
|
||||
|
||||
void rcc_peripheral_disable_clock(volatile u32 *reg, u32 en)
|
||||
{
|
||||
*reg &= ~en;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Reset Peripherals.
|
||||
|
||||
Reset particular peripherals. There are three registers
|
||||
involved, each one controlling reset of peripherals associated with the AHB,
|
||||
APB1 and APB2 respectively. Several peripherals could be reset simultaneously
|
||||
<em>only if they are controlled by the same register</em>.
|
||||
|
||||
@param[in] *reg Unsigned int32. Pointer to a Reset Register
|
||||
(either RCC_AHBENR, RCC_APB1ENR or RCC_APB2ENR)
|
||||
@param[in] reset Unsigned int32. Logical OR of all resets.
|
||||
@li If register is RCC_AHBRSTR, from @ref rcc_ahbrstr_rst
|
||||
@li If register is RCC_APB1RSTR, from @ref rcc_apb1rstr_rst
|
||||
@li If register is RCC_APB2RSTR, from @ref rcc_apb2rstr_rst
|
||||
*/
|
||||
|
||||
void rcc_peripheral_reset(volatile u32 *reg, u32 reset)
|
||||
{
|
||||
*reg |= reset;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Remove Reset on Peripherals.
|
||||
|
||||
Remove the reset on particular peripherals. There are three registers
|
||||
involved, each one controlling reset of peripherals associated with the AHB,
|
||||
APB1 and APB2 respectively. Several peripherals could have the reset removed
|
||||
simultaneously <em>only if they are controlled by the same register</em>.
|
||||
|
||||
@param[in] *reg Unsigned int32. Pointer to a Reset Register
|
||||
(either RCC_AHBENR, RCC_APB1ENR or RCC_APB2ENR)
|
||||
@param[in] clear_reset Unsigned int32. Logical OR of all resets to be removed:
|
||||
@li If register is RCC_AHBRSTR, from @ref rcc_ahbrstr_rst
|
||||
@li If register is RCC_APB1RSTR, from @ref rcc_apb1rstr_rst
|
||||
@li If register is RCC_APB2RSTR, from @ref rcc_apb2rstr_rst
|
||||
*/
|
||||
|
||||
void rcc_peripheral_clear_reset(volatile u32 *reg, u32 clear_reset)
|
||||
{
|
||||
*reg &= ~clear_reset;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the Source for the System Clock.
|
||||
|
||||
@param[in] clk Unsigned int32. System Clock Selection @ref rcc_cfgr_scs
|
||||
*/
|
||||
|
||||
void rcc_set_sysclk_source(u32 clk)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -259,6 +467,14 @@ void rcc_set_sysclk_source(u32 clk)
|
||||
RCC_CFGR = (reg32 | clk);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the PLL Multiplication Factor.
|
||||
|
||||
@note This only has effect when the PLL is disabled.
|
||||
|
||||
@param[in] mul Unsigned int32. PLL multiplication factor @ref rcc_cfgr_pmf
|
||||
*/
|
||||
|
||||
void rcc_set_pll_multiplication_factor(u32 mul)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -268,6 +484,14 @@ void rcc_set_pll_multiplication_factor(u32 mul)
|
||||
RCC_CFGR = (reg32 | (mul << 18));
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the PLL Clock Source.
|
||||
|
||||
@note This only has effect when the PLL is disabled.
|
||||
|
||||
@param[in] pllsrc Unsigned int32. PLL clock source @ref rcc_cfgr_pcs
|
||||
*/
|
||||
|
||||
void rcc_set_pll_source(u32 pllsrc)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -277,6 +501,14 @@ void rcc_set_pll_source(u32 pllsrc)
|
||||
RCC_CFGR = (reg32 | (pllsrc << 16));
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the HSE Frequency Divider used as PLL Clock Source.
|
||||
|
||||
@note This only has effect when the PLL is disabled.
|
||||
|
||||
@param[in] pllxtpre Unsigned int32. HSE division factor @ref rcc_cfgr_hsepre
|
||||
*/
|
||||
|
||||
void rcc_set_pllxtpre(u32 pllxtpre)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -286,6 +518,14 @@ void rcc_set_pllxtpre(u32 pllxtpre)
|
||||
RCC_CFGR = (reg32 | (pllxtpre << 17));
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief ADC Setup the A/D Clock
|
||||
|
||||
The ADC's have a common clock prescale setting.
|
||||
|
||||
@param[in] adcpre u32. Prescale divider taken from @ref rcc_cfgr_adcpre
|
||||
*/
|
||||
|
||||
void rcc_set_adcpre(u32 adcpre)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -295,6 +535,12 @@ void rcc_set_adcpre(u32 adcpre)
|
||||
RCC_CFGR = (reg32 | (adcpre << 14));
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the APB2 Prescale Factor.
|
||||
|
||||
@param[in] ppre2 Unsigned int32. APB2 prescale factor @ref rcc_cfgr_apb2pre
|
||||
*/
|
||||
|
||||
void rcc_set_ppre2(u32 ppre2)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -304,6 +550,14 @@ void rcc_set_ppre2(u32 ppre2)
|
||||
RCC_CFGR = (reg32 | (ppre2 << 11));
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the APB1 Prescale Factor.
|
||||
|
||||
@note The APB1 clock frequency must not exceed 36MHz.
|
||||
|
||||
@param[in] ppre1 Unsigned int32. APB1 prescale factor @ref rcc_cfgr_apb1pre
|
||||
*/
|
||||
|
||||
void rcc_set_ppre1(u32 ppre1)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -313,6 +567,12 @@ void rcc_set_ppre1(u32 ppre1)
|
||||
RCC_CFGR = (reg32 | (ppre1 << 8));
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the AHB Prescale Factor.
|
||||
|
||||
@param[in] hpre Unsigned int32. AHB prescale factor @ref rcc_cfgr_ahbpre
|
||||
*/
|
||||
|
||||
void rcc_set_hpre(u32 hpre)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -322,6 +582,17 @@ void rcc_set_hpre(u32 hpre)
|
||||
RCC_CFGR = (reg32 | (hpre << 4));
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the USB Prescale Factor.
|
||||
|
||||
The prescale factor can be set to 1 (no prescale) for use when the PLL clock is
|
||||
48MHz, or 1.5 to generate the 48MHz USB clock from a 64MHz PLL clock.
|
||||
|
||||
@note This bit cannot be reset while the USB clock is enabled.
|
||||
|
||||
@param[in] usbpre Unsigned int32. USB prescale factor @ref rcc_cfgr_usbpre
|
||||
*/
|
||||
|
||||
void rcc_set_usbpre(u32 usbpre)
|
||||
{
|
||||
u32 reg32;
|
||||
@@ -331,16 +602,31 @@ void rcc_set_usbpre(u32 usbpre)
|
||||
RCC_CFGR = (reg32 | (usbpre << 22));
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Get the System Clock Source.
|
||||
|
||||
@returns Unsigned int32. System clock source:
|
||||
@li 00 indicates HSE
|
||||
@li 01 indicates LSE
|
||||
@li 02 indicates PLL
|
||||
*/
|
||||
|
||||
u32 rcc_system_clock_source(void)
|
||||
{
|
||||
/* Return the clock source which is used as system clock. */
|
||||
return ((RCC_CFGR & 0x000c) >> 2);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* These functions are setting up the whole clock system for the most common
|
||||
* input clock and output clock configurations.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set System Clock PLL at 64MHz from HSI
|
||||
|
||||
*/
|
||||
|
||||
void rcc_clock_setup_in_hsi_out_64mhz(void)
|
||||
{
|
||||
/* Enable internal high-speed oscillator. */
|
||||
@@ -388,6 +674,11 @@ void rcc_clock_setup_in_hsi_out_64mhz(void)
|
||||
rcc_ppre2_frequency = 64000000;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set System Clock PLL at 48MHz from HSI
|
||||
|
||||
*/
|
||||
|
||||
void rcc_clock_setup_in_hsi_out_48mhz(void)
|
||||
{
|
||||
/* Enable internal high-speed oscillator. */
|
||||
@@ -436,6 +727,62 @@ void rcc_clock_setup_in_hsi_out_48mhz(void)
|
||||
rcc_ppre2_frequency = 48000000;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set System Clock PLL at 24MHz from HSI
|
||||
|
||||
*/
|
||||
|
||||
void rcc_clock_setup_in_hsi_out_24mhz(void) {
|
||||
/* Enable internal high-speed oscillator. */
|
||||
rcc_osc_on(HSI);
|
||||
rcc_wait_for_osc_ready(HSI);
|
||||
|
||||
/* Select HSI as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
|
||||
|
||||
/*
|
||||
* Set prescalers for AHB, ADC, ABP1, ABP2.
|
||||
* Do this before touching the PLL (TODO: why?).
|
||||
*/
|
||||
rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 24MHz Max. 24MHz */
|
||||
rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV2); /* Set. 12MHz Max. 12MHz */
|
||||
rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_NODIV); /* Set. 24MHz Max. 24MHz */
|
||||
rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 24MHz Max. 24MHz */
|
||||
|
||||
/*
|
||||
* Sysclk is (will be) running with 24MHz -> 2 waitstates.
|
||||
* 0WS from 0-24MHz
|
||||
* 1WS from 24-48MHz
|
||||
* 2WS from 48-72MHz
|
||||
*/
|
||||
flash_set_ws(FLASH_LATENCY_0WS);
|
||||
|
||||
/*
|
||||
* Set the PLL multiplication factor to 6.
|
||||
* 8MHz (internal) * 6 (multiplier) / 2 (PLLSRC_HSI_CLK_DIV2) = 24MHz
|
||||
*/
|
||||
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL6);
|
||||
|
||||
/* Select HSI/2 as PLL source. */
|
||||
rcc_set_pll_source(RCC_CFGR_PLLSRC_HSI_CLK_DIV2);
|
||||
|
||||
/* Enable PLL oscillator and wait for it to stabilize. */
|
||||
rcc_osc_on(PLL);
|
||||
rcc_wait_for_osc_ready(PLL);
|
||||
|
||||
/* Select PLL as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
|
||||
|
||||
/* Set the peripheral clock frequencies used */
|
||||
rcc_ppre1_frequency = 24000000;
|
||||
rcc_ppre2_frequency = 24000000;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set System Clock PLL at 24MHz from HSE at 8MHz
|
||||
|
||||
*/
|
||||
|
||||
void rcc_clock_setup_in_hse_8mhz_out_24mhz(void)
|
||||
{
|
||||
/* Enable internal high-speed oscillator. */
|
||||
@@ -494,6 +841,11 @@ void rcc_clock_setup_in_hse_8mhz_out_24mhz(void)
|
||||
rcc_ppre2_frequency = 24000000;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set System Clock PLL at 72MHz from HSE at 8MHz
|
||||
|
||||
*/
|
||||
|
||||
void rcc_clock_setup_in_hse_8mhz_out_72mhz(void)
|
||||
{
|
||||
/* Enable internal high-speed oscillator. */
|
||||
@@ -552,6 +904,11 @@ void rcc_clock_setup_in_hse_8mhz_out_72mhz(void)
|
||||
rcc_ppre2_frequency = 72000000;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set System Clock PLL at 24MHz from HSE at 12MHz
|
||||
|
||||
*/
|
||||
|
||||
void rcc_clock_setup_in_hse_12mhz_out_72mhz(void)
|
||||
{
|
||||
/* Enable internal high-speed oscillator. */
|
||||
@@ -610,6 +967,11 @@ void rcc_clock_setup_in_hse_12mhz_out_72mhz(void)
|
||||
rcc_ppre2_frequency = 72000000;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set System Clock PLL at 24MHz from HSE at 16MHz
|
||||
|
||||
*/
|
||||
|
||||
void rcc_clock_setup_in_hse_16mhz_out_72mhz(void)
|
||||
{
|
||||
/* Enable internal high-speed oscillator. */
|
||||
@@ -668,6 +1030,12 @@ void rcc_clock_setup_in_hse_16mhz_out_72mhz(void)
|
||||
rcc_ppre2_frequency = 72000000;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief RCC Reset the backup domain
|
||||
|
||||
The backup domain register is reset to disable all controls.
|
||||
*/
|
||||
|
||||
void rcc_backupdomain_reset(void)
|
||||
{
|
||||
/* Set the backup domain software reset. */
|
||||
@@ -676,3 +1044,5 @@ void rcc_backupdomain_reset(void)
|
||||
/* Clear the backup domain software reset. */
|
||||
RCC_BDCR &= ~RCC_BDCR_BDRST;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
|
||||
31
lib/stm32/f1/stm32f100x4.ld
Normal file
31
lib/stm32/f1/stm32f100x4.ld
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 16K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
lib/stm32/f1/stm32f100x6.ld
Normal file
31
lib/stm32/f1/stm32f100x6.ld
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x6, 32K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
lib/stm32/f1/stm32f100x8.ld
Normal file
31
lib/stm32/f1/stm32f100x8.ld
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x8, 64K flash, 8K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
lib/stm32/f1/stm32f100xb.ld
Normal file
31
lib/stm32/f1/stm32f100xb.ld
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100xB, 128K flash, 8K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
lib/stm32/f1/stm32f100xc.ld
Normal file
31
lib/stm32/f1/stm32f100xc.ld
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100xC, 256K flash, 24K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 256K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 24K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
lib/stm32/f1/stm32f100xd.ld
Normal file
31
lib/stm32/f1/stm32f100xd.ld
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100xD, 384K flash, 32K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 384K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 32K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
lib/stm32/f1/stm32f100xe.ld
Normal file
31
lib/stm32/f1/stm32f100xe.ld
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100xE, 512K flash, 32K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 32K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,8 +19,8 @@
|
||||
|
||||
#define WEAK __attribute__ ((weak))
|
||||
|
||||
/* Symbols exported by the linker script(s). */
|
||||
extern unsigned __exidx_end, _data, _edata, _ebss, _stack;
|
||||
/* Symbols exported by the linker script(s): */
|
||||
extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack;
|
||||
|
||||
void main(void);
|
||||
void reset_handler(void);
|
||||
@@ -197,7 +197,7 @@ void reset_handler(void)
|
||||
|
||||
__asm__("MSR msp, %0" : : "r"(&_stack));
|
||||
|
||||
for (src = &__exidx_end, dest = &_data; dest < &_edata; src++, dest++)
|
||||
for (src = &_data_loadaddr, dest = &_data; dest < &_edata; src++, dest++)
|
||||
*dest = *src;
|
||||
|
||||
while (dest < &_ebss)
|
||||
|
||||
@@ -33,27 +33,4 @@ OBJS = vector.o rcc.o gpio.o usart.o spi.o flash.o nvic.o \
|
||||
|
||||
VPATH += ../../usb:../
|
||||
|
||||
# Be silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1)
|
||||
Q := @
|
||||
endif
|
||||
|
||||
all: $(LIBNAME).a
|
||||
|
||||
$(LIBNAME).a: $(OBJS)
|
||||
@printf " AR $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
%.o: %.c
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
@printf " CLEAN lib/stm32/f2\n"
|
||||
$(Q)rm -f *.o *.d
|
||||
$(Q)rm -f $(LIBNAME).a
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
-include $(OBJS:.o=.d)
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
@@ -111,7 +111,7 @@ u16 gpio_get(u32 gpioport, u16 gpios)
|
||||
|
||||
void gpio_toggle(u32 gpioport, u16 gpios)
|
||||
{
|
||||
GPIO_ODR(gpioport) = GPIO_IDR(gpioport) ^ gpios;
|
||||
GPIO_ODR(gpioport) ^= gpios;
|
||||
}
|
||||
|
||||
u16 gpio_port_read(u32 gpioport)
|
||||
@@ -135,5 +135,8 @@ void gpio_port_config_lock(u32 gpioport, u16 gpios)
|
||||
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. */
|
||||
}
|
||||
|
||||
@@ -30,21 +30,18 @@ ENTRY(reset_handler)
|
||||
/* Define sections. */
|
||||
SECTIONS
|
||||
{
|
||||
. = ORIGIN(rom);
|
||||
|
||||
.text : {
|
||||
*(.vectors) /* Vector table */
|
||||
*(.text*) /* Program code */
|
||||
. = ALIGN(4);
|
||||
*(.rodata*) /* Read-only data */
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
} >rom
|
||||
|
||||
/*
|
||||
* Another section used by C++ stuff, appears when using newlib with
|
||||
* 64bit (long long) printf support
|
||||
*/
|
||||
* Another section used by C++ stuff, appears when using newlib with
|
||||
* 64bit (long long) printf support
|
||||
*/
|
||||
.ARM.extab : {
|
||||
*(.ARM.extab*)
|
||||
} >rom
|
||||
@@ -54,21 +51,23 @@ SECTIONS
|
||||
__exidx_end = .;
|
||||
} >rom
|
||||
|
||||
. = ORIGIN(ram);
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
|
||||
.data : AT (__exidx_end) {
|
||||
.data : {
|
||||
_data = .;
|
||||
*(.data*) /* Read-write initialized data */
|
||||
. = ALIGN(4);
|
||||
_edata = .;
|
||||
} >ram
|
||||
} >ram AT >rom
|
||||
_data_loadaddr = LOADADDR(.data);
|
||||
|
||||
.bss : {
|
||||
*(.bss*) /* Read-write zero initialized data */
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = .;
|
||||
} >ram AT >rom
|
||||
} >ram
|
||||
|
||||
/*
|
||||
* The .eh_frame section appears to be used for C++ exception handling.
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#define WEAK __attribute__ ((weak))
|
||||
|
||||
/* Symbols exported by the linker script(s): */
|
||||
extern unsigned __exidx_end, _data, _edata, _ebss, _stack;
|
||||
extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack;
|
||||
|
||||
void main(void);
|
||||
void reset_handler(void);
|
||||
@@ -224,7 +224,7 @@ void reset_handler(void)
|
||||
|
||||
__asm__("MSR msp, %0" : : "r"(&_stack));
|
||||
|
||||
for (src = &__exidx_end, dest = &_data; dest < &_edata; src++, dest++)
|
||||
for (src = &_data_loadaddr, dest = &_data; dest < &_edata; src++, dest++)
|
||||
*dest = *src;
|
||||
|
||||
while (dest < &_ebss)
|
||||
|
||||
@@ -34,27 +34,4 @@ OBJS = vector.o rcc.o gpio.o usart.o spi.o flash.o nvic.o \
|
||||
|
||||
VPATH += ../../usb:../
|
||||
|
||||
# Be silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1)
|
||||
Q := @
|
||||
endif
|
||||
|
||||
all: $(LIBNAME).a
|
||||
|
||||
$(LIBNAME).a: $(OBJS)
|
||||
@printf " AR $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
%.o: %.c
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
@printf " CLEAN lib/stm32/f4\n"
|
||||
$(Q)rm -f *.o *.d
|
||||
$(Q)rm -f $(LIBNAME).a
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
-include $(OBJS:.o=.d)
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
@@ -111,7 +111,7 @@ u16 gpio_get(u32 gpioport, u16 gpios)
|
||||
|
||||
void gpio_toggle(u32 gpioport, u16 gpios)
|
||||
{
|
||||
GPIO_ODR(gpioport) = GPIO_IDR(gpioport) ^ gpios;
|
||||
GPIO_ODR(gpioport) ^= gpios;
|
||||
}
|
||||
|
||||
u16 gpio_port_read(u32 gpioport)
|
||||
@@ -135,5 +135,8 @@ void gpio_port_config_lock(u32 gpioport, u16 gpios)
|
||||
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. */
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@ ENTRY(reset_handler)
|
||||
/* Define sections. */
|
||||
SECTIONS
|
||||
{
|
||||
. = ORIGIN(rom);
|
||||
|
||||
.text : {
|
||||
*(.vectors) /* Vector table */
|
||||
*(.text*) /* Program code */
|
||||
@@ -40,14 +38,20 @@ SECTIONS
|
||||
. = ALIGN(4);
|
||||
} >rom
|
||||
|
||||
/* exception index - required due to libgcc.a issuing /0 exceptions */
|
||||
__exidx_start = .;
|
||||
/*
|
||||
* Another section used by C++ stuff, appears when using newlib with
|
||||
* 64bit (long long) printf support
|
||||
*/
|
||||
.ARM.extab : {
|
||||
*(.ARM.extab*)
|
||||
} >rom
|
||||
.ARM.exidx : {
|
||||
*(.ARM.exidx*)
|
||||
} > rom
|
||||
__exidx_end = .;
|
||||
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
__exidx_end = .;
|
||||
} >rom
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
|
||||
.data : {
|
||||
@@ -56,6 +60,7 @@ SECTIONS
|
||||
. = ALIGN(4);
|
||||
_edata = .;
|
||||
} >ram AT >rom
|
||||
_data_loadaddr = LOADADDR(.data);
|
||||
|
||||
.bss : {
|
||||
*(.bss*) /* Read-write zero initialized data */
|
||||
@@ -64,10 +69,11 @@ SECTIONS
|
||||
_ebss = .;
|
||||
} >ram
|
||||
|
||||
/* exception unwind data - required due to libgcc.a issuing /0 exceptions */
|
||||
.ARM.extab : {
|
||||
*(.ARM.extab*)
|
||||
} >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 = .;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#define WEAK __attribute__ ((weak))
|
||||
|
||||
/* Symbols exported by the linker script(s): */
|
||||
extern unsigned _etext, _data, _edata, _ebss, _stack;
|
||||
extern unsigned _data_loadaddr, _data, _edata, _ebss, _stack;
|
||||
|
||||
void main(void);
|
||||
void reset_handler(void);
|
||||
@@ -224,7 +224,7 @@ void reset_handler(void)
|
||||
|
||||
__asm__("MSR msp, %0" : : "r"(&_stack));
|
||||
|
||||
for (src = &_etext, dest = &_data; dest < &_edata; src++, dest++)
|
||||
for (src = &_data_loadaddr, dest = &_data; dest < &_edata; src++, dest++)
|
||||
*dest = *src;
|
||||
|
||||
while (dest < &_ebss)
|
||||
|
||||
144
lib/stm32/iwdg.c
Normal file
144
lib/stm32/iwdg.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/** @defgroup STM32F_iwdg_file IWDG
|
||||
|
||||
@ingroup STM32F_files
|
||||
|
||||
@brief <b>libopencm3 STM32F1xx Independent Watchdog Timer</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2012 Ken Sarkies ksarkies@internode.on.net
|
||||
|
||||
@date 18 August 2012
|
||||
|
||||
This library supports the Independent Watchdog Timer System in the STM32F1xx
|
||||
series of ARM Cortex Microcontrollers by ST Microelectronics.
|
||||
|
||||
The watchdog timer uses the LSI (low speed internal) clock which is low power
|
||||
and continues to operate during stop and standby modes. Its frequency is
|
||||
nominally 32kHz (40kHz for the STM32F1xx series) but can vary from as low
|
||||
as 17kHz up to 60kHz (refer to datasheet electrical characteristics).
|
||||
|
||||
Note that the User Configuration option byte provides a means of automatically
|
||||
enabling the IWDG timer at power on (with counter value 0xFFF). If the
|
||||
relevant bit is not set, the IWDG timer must be enabled by software.
|
||||
|
||||
@note: Tested: CPU STM32F103RET6, Board ET-ARM Stamp STM32
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
|
||||
#include <libopencm3/stm32/iwdg.h>
|
||||
|
||||
#define LSI_FREQUENCY 32000
|
||||
#define COUNT_LENGTH 12
|
||||
#define COUNT_MASK ((1 << COUNT_LENGTH)-1)
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief IWDG Enable Watchdog Timer
|
||||
|
||||
The watchdog timer is started. The timeout period defaults to 512 milliseconds
|
||||
unless it has been previously defined.
|
||||
|
||||
*/
|
||||
|
||||
void iwdg_start(void)
|
||||
{
|
||||
IWDG_KR = IWDG_KR_START;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief IWDG Set Period in Milliseconds
|
||||
|
||||
The countdown period is converted into count and prescale values. The maximum
|
||||
period is 32.76 seconds; values above this are truncated. Periods less than 1ms
|
||||
are not supported by this library.
|
||||
|
||||
A delay of up to 5 clock cycles of the LSI clock (about 156 microseconds)
|
||||
can occasionally occur if the prescale or preload registers are currently busy
|
||||
loading a previous value.
|
||||
|
||||
@param[in] period u32 Period in milliseconds (< 32760) from a watchdog reset until
|
||||
a system reset is issued.
|
||||
*/
|
||||
|
||||
void iwdg_set_period_ms(u32 period)
|
||||
{
|
||||
u32 count, prescale, reload, exponent;
|
||||
/* Set the count to represent ticks of the 32kHz LSI clock */
|
||||
count = (period << 5);
|
||||
/* Strip off the first 12 bits to get the prescale value required */
|
||||
prescale = (count >> 12);
|
||||
if (prescale > 256) {exponent = IWDG_PR_DIV256; reload = COUNT_MASK;}
|
||||
else if (prescale > 128) {exponent = IWDG_PR_DIV256; reload = (count >> 8);}
|
||||
else if (prescale > 64) {exponent = IWDG_PR_DIV128; reload = (count >> 7);}
|
||||
else if (prescale > 32) {exponent = IWDG_PR_DIV64; reload = (count >> 6);}
|
||||
else if (prescale > 16) {exponent = IWDG_PR_DIV32; reload = (count >> 5);}
|
||||
else if (prescale > 8) {exponent = IWDG_PR_DIV16; reload = (count >> 4);}
|
||||
else if (prescale > 4) {exponent = IWDG_PR_DIV8; reload = (count >> 3);}
|
||||
else {exponent = IWDG_PR_DIV4; reload = (count >> 2);}
|
||||
/* Avoid the undefined situation of a zero count */
|
||||
if (count == 0) count = 1;
|
||||
|
||||
while (iwdg_prescaler_busy());
|
||||
IWDG_KR = IWDG_KR_UNLOCK;
|
||||
IWDG_PR = exponent;
|
||||
while (iwdg_reload_busy());
|
||||
IWDG_KR = IWDG_KR_UNLOCK;
|
||||
IWDG_RLR = (reload & COUNT_MASK);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief IWDG Get Reload Register Status
|
||||
|
||||
@returns boolean: TRUE if the reload register is busy and unavailable for loading
|
||||
a new count value.
|
||||
*/
|
||||
|
||||
bool iwdg_reload_busy(void)
|
||||
{
|
||||
return (IWDG_SR & IWDG_SR_RVU);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief IWDG Get Prescaler Register Status
|
||||
|
||||
@returns boolean: TRUE if the prescaler register is busy and unavailable for loading
|
||||
a new period value.
|
||||
*/
|
||||
|
||||
bool iwdg_prescaler_busy(void)
|
||||
{
|
||||
return (IWDG_SR & IWDG_SR_PVU);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @brief IWDG reset Watchdog Timer
|
||||
|
||||
The watchdog timer is reset. The counter restarts from the value in the reload
|
||||
register.
|
||||
*/
|
||||
|
||||
void iwdg_reset(void)
|
||||
{
|
||||
IWDG_KR = IWDG_KR_RESET;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
111
lib/stm32/nvic.c
111
lib/stm32/nvic.c
@@ -1,3 +1,26 @@
|
||||
/** @defgroup STM32F_nvic_file NVIC
|
||||
|
||||
@ingroup STM32F_files
|
||||
|
||||
@brief <b>libopencm3 STM32F Nested Vectored Interrupt Controller</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
|
||||
@author @htmlonly © @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.
|
||||
*
|
||||
@@ -18,50 +41,134 @@
|
||||
* 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 / 4) |= (priority << ((irqn % 4) * 8));
|
||||
NVIC_IPR(irqn) = priority;
|
||||
}
|
||||
|
||||
void nvic_generate_software_interrupt(u8 irqn)
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/** @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;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
/** @defgroup STM32F_systick_file SysTick
|
||||
|
||||
@ingroup STM32F_files
|
||||
|
||||
@brief <b>libopencm3 STM32Fxx System Tick Timer</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @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.
|
||||
*
|
||||
@@ -17,44 +37,97 @@
|
||||
* 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)
|
||||
@@ -62,3 +135,5 @@ u8 systick_get_countflag(void)
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user