Merge branch 'master' into generalizations

Conflicts:
	lib/lm3s/vector.c -- split out to lm3s/irq.h
	lib/stm32/f4/vector.c -- put the floating point initialization code into a function like in lpc43xx
This commit is contained in:
chrysn 2012-10-17 18:55:54 +02:00
commit 7c33025c31
51 changed files with 3324 additions and 151 deletions

1
.gitignore vendored
View File

@ -6,6 +6,7 @@
*.srec
*.a
*.elf
lib/*.ld
*.swp
\#*
.\#*

View File

@ -26,7 +26,7 @@ SHAREDIR = $(DESTDIR)/$(PREFIX)/share/libopencm3/scripts
INSTALL = install
SRCLIBDIR = $(shell pwd)/lib
TARGETS = stm32/f1 stm32/f2 stm32/f4 lpc13xx lpc17xx lpc43xx lm3s
TARGETS = stm32/f1 stm32/f2 stm32/f4 lpc13xx lpc17xx lpc43xx lm3s
# Be silent per default, but 'make V=1' will show all compiler calls.
ifneq ($(V),1)

View File

@ -6,7 +6,7 @@
<tab type="user" visible="yes" url="../../html/index.html" title="Back to Top" intro=""/>
<tab type="user" visible="yes" url="../../cm3/html/modules.html" title="CM3 Core" intro=""/>
<tab type="user" visible="yes" url="../../stm32/html/modules.html" title="STM32" intro=""/>
<tab type="modules" visible="yes" title="STMF1" intro=""/>
<tab type="modules" visible="yes" title="STM32F1" intro=""/>
<tab type="user" visible="yes" url="../../stm32f2/html/modules.html" title="STM32F2" intro=""/>
<tab type="user" visible="yes" url="../../stm32f4/html/modules.html" title="STM32F4" intro=""/>
<tab type="user" visible="yes" url="../../lm3s/html/modules.html" title="LM3S" intro=""/>

View File

@ -24,14 +24,18 @@ CC = $(PREFIX)-gcc
LD = $(PREFIX)-gcc
OBJCOPY = $(PREFIX)-objcopy
OBJDUMP = $(PREFIX)-objdump
TOOLCHAIN_DIR ?= ../../../..
ifeq ($(wildcard ../../../../lib/libopencm3_lm3s.a),)
ifneq ($(strip $(shell which $(CC))),)
TOOLCHAIN_DIR := $(shell dirname `which $(CC)`)/../$(PREFIX)
endif
else
ifeq ($(V),1)
$(info We seem to be building the example in the source directory. Using local library!)
endif
TOOLCHAIN_DIR := ../../../..
endif
CFLAGS += -O0 -g3 -Wall -Wextra -I$(TOOLCHAIN_DIR)/include -fno-common \
-mcpu=cortex-m3 -mthumb -MD
LDSCRIPT ?= $(BINARY).ld

View File

@ -24,14 +24,18 @@ CC = $(PREFIX)-gcc
LD = $(PREFIX)-gcc
OBJCOPY = $(PREFIX)-objcopy
OBJDUMP = $(PREFIX)-objdump
TOOLCHAIN_DIR ?= ../../../..
ifeq ($(wildcard ../../../../lib/libopencm3_lpc13xx.a),)
ifneq ($(strip $(shell which $(CC))),)
TOOLCHAIN_DIR := $(shell dirname `which $(CC)`)/../$(PREFIX)
endif
else
ifeq ($(V),1)
$(info We seem to be building the example in the source directory. Using local library!)
endif
TOOLCHAIN_DIR := ../../../..
endif
CFLAGS += -Os -g -Wall -Wextra -I$(TOOLCHAIN_DIR)/include -fno-common \
-mcpu=cortex-m3 -mthumb -MD
LDSCRIPT ?= $(BINARY).ld

View File

@ -24,14 +24,18 @@ CC = $(PREFIX)-gcc
LD = $(PREFIX)-gcc
OBJCOPY = $(PREFIX)-objcopy
OBJDUMP = $(PREFIX)-objdump
TOOLCHAIN_DIR ?= ../../../..
ifeq ($(wildcard ../../../../lib/libopencm3_lpc17xx.a),)
ifneq ($(strip $(shell which $(CC))),)
TOOLCHAIN_DIR := $(shell dirname `which $(CC)`)/../$(PREFIX)
endif
else
ifeq ($(V),1)
$(info We seem to be building the example in the source directory. Using local library!)
endif
TOOLCHAIN_DIR := ../../../..
endif
CFLAGS += -O0 -g -Wall -Wextra -I$(TOOLCHAIN_DIR)/include -fno-common \
-mcpu=cortex-m3 -mthumb -MD
LDSCRIPT ?= $(BINARY).ld

View File

@ -27,14 +27,18 @@ LD = $(PREFIX)-gcc
OBJCOPY = $(PREFIX)-objcopy
OBJDUMP = $(PREFIX)-objdump
GDB = $(PREFIX)-gdb
TOOLCHAIN_DIR ?= ../../../..
ifeq ($(wildcard ../../../../lib/libopencm3_lpc43xx.a),)
ifneq ($(strip $(shell which $(CC))),)
TOOLCHAIN_DIR := $(shell dirname `which $(CC)`)/../$(PREFIX)
endif
else
ifeq ($(V),1)
$(info We seem to be building the example in the source directory. Using local library!)
endif
TOOLCHAIN_DIR := ../../../..
endif
CFLAGS += -O2 -g -Wall -Wextra -I$(TOOLCHAIN_DIR)/include -fno-common \
-mcpu=cortex-m4 -mthumb -MD \
-mfloat-abi=hard -mfpu=fpv4-sp-d16

View File

@ -25,14 +25,18 @@ LD = $(PREFIX)-gcc
OBJCOPY = $(PREFIX)-objcopy
OBJDUMP = $(PREFIX)-objdump
GDB = $(PREFIX)-gdb
TOOLCHAIN_DIR ?= ../../../../..
ifeq ($(wildcard ../../../../../lib/libopencm3_stm32f1.a),)
ifneq ($(strip $(shell which $(CC))),)
TOOLCHAIN_DIR := $(shell dirname `which $(CC)`)/../$(PREFIX)
endif
else
ifeq ($(V),1)
$(info We seem to be building the example in the source directory. Using local library!)
$(info We seem to be building the example in the source directory. Using local library!)
endif
TOOLCHAIN_DIR := ../../../../..
endif
ARCH_FLAGS = -mthumb -mcpu=cortex-m3 -msoft-float
CFLAGS += -Os -g -Wall -Wextra -I$(TOOLCHAIN_DIR)/include \
-fno-common $(ARCH_FLAGS) -MD -DSTM32F1

View File

@ -0,0 +1,27 @@
##
## 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/>.
##
BINARY = adc_injec
# Comment the following line if you _don't_ have luftboot flashed!
LDFLAGS += -Wl,-Ttext=0x8002000
CFLAGS += -std=c99
LDSCRIPT = ../lisa-m.ld
include ../../Makefile.include

View File

@ -0,0 +1,11 @@
------------------------------------------------------------------------------
README
------------------------------------------------------------------------------
This is a simple polling example that sends the value read out from the
temperature sensor ADC channel of the STM32 to the USART2.
This example polls injected channels.
The terminal settings for the receiving device/PC are 115200 8n1.

View File

@ -0,0 +1,174 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Copyright (C) 2012 Piotr Esden-Tempski <piotr@esden.net>
* Copyright (C) 2012 Stephen Dwyer <dwyer.sc@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/flash.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/f1/adc.h>
#include <libopencm3/stm32/usart.h>
void usart_setup(void)
{
/* Enable clocks for GPIO port A (for GPIO_USART1_TX) and USART1. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
/* Setup GPIO pin GPIO_USART1_TX/GPIO9 on GPIO port A for transmit. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
/* Setup UART parameters. */
usart_set_baudrate(USART2, 115200);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_mode(USART2, USART_MODE_TX_RX);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
/* Finally enable the USART. */
usart_enable(USART2);
}
void gpio_setup(void)
{
/* Enable GPIO clocks. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
/* Setup the LEDs. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
}
void adc_setup(void)
{
int i;
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN);
/* Make sure the ADC doesn't run during config. */
adc_off(ADC1);
/* We configure everything for one single injected conversion. */
adc_disable_scan_mode(ADC1);
adc_set_single_conversion_mode(ADC1);
/* We can only use discontinuous mode on either the regular OR injected channels, not both */
adc_disable_discontinuous_mode_regular(ADC1);
adc_enable_discontinuous_mode_injected(ADC1);
/* We want to start the injected conversion in software */
adc_enable_external_trigger_injected(ADC1,ADC_CR2_JEXTSEL_JSWSTART);
adc_set_right_aligned(ADC1);
/* We want to read the temperature sensor, so we have to enable it. */
adc_enable_temperature_sensor(ADC1);
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC);
adc_power_on(ADC1);
/* Wait for ADC starting up. */
for (i = 0; i < 800000; i++) /* Wait a bit. */
__asm__("nop");
adc_reset_calibration(ADC1);
while ((ADC_CR2(ADC1) & ADC_CR2_RSTCAL) != 0); //added this check
adc_calibration(ADC1);
while ((ADC_CR2(ADC1) & ADC_CR2_CAL) != 0); //added this check
}
void my_usart_print_int(u32 usart, int value)
{
s8 i;
u8 nr_digits = 0;
char buffer[25];
if (value < 0) {
usart_send_blocking(usart, '-');
value = value * -1;
}
while (value > 0) {
buffer[nr_digits++] = "0123456789"[value % 10];
value /= 10;
}
for (i = (nr_digits - 1); i >= 0; i--) {
usart_send_blocking(usart, buffer[i]);
}
usart_send_blocking(usart, '\r');
}
int main(void)
{
u8 channel_array[16];
u16 temperature = 0;
rcc_clock_setup_in_hse_12mhz_out_72mhz();
gpio_setup();
usart_setup();
adc_setup();
gpio_set(GPIOA, GPIO8); /* LED1 on */
gpio_set(GPIOC, GPIO15); /* LED2 on */
/* Send a message on USART1. */
usart_send_blocking(USART2, 's');
usart_send_blocking(USART2, 't');
usart_send_blocking(USART2, 'm');
usart_send_blocking(USART2, '\r');
usart_send_blocking(USART2, '\n');
/* Select the channel we want to convert. 16=temperature_sensor. */
channel_array[0] = 16;
/* Set the injected sequence here, with number of channels */
adc_set_injected_sequence(ADC1, 1, channel_array);
/* Continously convert and poll the temperature ADC. */
while (1) {
/*
* If the ADC_CR2_ON bit is already set -> setting it another time
* starts a regular conversion. Injected conversion is started
* explicitly with the JSWSTART bit as an external trigger. It may
* also work by setting no regular channels and setting JAUTO to
* automatically convert the injected channels after the regular
* channels (of which there would be none). (Not tested.)
*/
adc_start_conversion_injected(ADC1);
/* Wait for end of conversion. */
while (!(adc_eoc_injected(ADC1)));
ADC_SR(ADC2) &= ~ADC_SR_JEOC; //clear injected end of conversion
temperature = adc_read_injected(ADC1,1); //get the result from ADC_JDR1 on ADC1 (only bottom 16bits)
/*
* That's actually not the real temperature - you have to compute it
* as described in the datasheet.
*/
my_usart_print_int(USART2, temperature);
gpio_toggle(GPIOA, GPIO8); /* LED2 on */
}
return 0;
}

View File

@ -0,0 +1,27 @@
##
## 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/>.
##
BINARY = adc_injec_timtrig
# Comment the following line if you _don't_ have luftboot flashed!
LDFLAGS += -Wl,-Ttext=0x8002000
CFLAGS += -std=c99
LDSCRIPT = ../lisa-m.ld
include ../../Makefile.include

View File

@ -0,0 +1,11 @@
------------------------------------------------------------------------------
README
------------------------------------------------------------------------------
This is a simple example that sends the value read out from the
temperature sensor ADC channel of the STM32 to the USART2.
This example uses a timer trigger to automatically sample the adc channel.
The terminal settings for the receiving device/PC are 115200 8n1.

View File

@ -0,0 +1,195 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Copyright (C) 2012 Piotr Esden-Tempski <piotr@esden.net>
* Copyright (C) 2012 Stephen Dwyer <dwyer.sc@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/flash.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/f1/adc.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/timer.h>
void usart_setup(void)
{
/* Enable clocks for GPIO port A (for GPIO_USART1_TX) and USART1. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
/* Setup GPIO pin GPIO_USART1_TX/GPIO9 on GPIO port A for transmit. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
/* Setup UART parameters. */
usart_set_baudrate(USART2, 115200);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_mode(USART2, USART_MODE_TX_RX);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
/* Finally enable the USART. */
usart_enable(USART2);
}
void gpio_setup(void)
{
/* Enable GPIO clocks. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
/* Setup the LEDs. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
}
void timer_setup(void)
{
/* Set up the timer TIM2 for injected sampling */
uint32_t timer;
volatile uint32_t *rcc_apbenr;
uint32_t rcc_apb;
timer = TIM2;
rcc_apbenr = &RCC_APB1ENR;
rcc_apb = RCC_APB1ENR_TIM2EN;
rcc_peripheral_enable_clock(rcc_apbenr, rcc_apb);
/* Time Base configuration */
timer_reset(timer);
timer_set_mode(timer, TIM_CR1_CKD_CK_INT,
TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
timer_set_period(timer, 0xFF);
timer_set_prescaler(timer, 0x8);
timer_set_clock_division(timer, 0x0);
/* Generate TRGO on every update. */
timer_set_master_mode(timer, TIM_CR2_MMS_UPDATE);
timer_enable_counter(timer);
}
void adc_setup(void)
{
int i;
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN);
/* Make sure the ADC doesn't run during config. */
adc_off(ADC1);
/* We configure everything for one single timer triggered injected conversion. */
adc_disable_scan_mode(ADC1);
adc_set_single_conversion_mode(ADC1);
/* We can only use discontinuous mode on either the regular OR injected channels, not both */
adc_disable_discontinuous_mode_regular(ADC1);
adc_enable_discontinuous_mode_injected(ADC1);
/* We want to start the injected conversion with the TIM2 TRGO */
adc_enable_external_trigger_injected(ADC1,ADC_CR2_JEXTSEL_TIM2_TRGO);
adc_set_right_aligned(ADC1);
/* We want to read the temperature sensor, so we have to enable it. */
adc_enable_temperature_sensor(ADC1);
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC);
adc_power_on(ADC1);
/* Wait for ADC starting up. */
for (i = 0; i < 800000; i++) /* Wait a bit. */
__asm__("nop");
adc_reset_calibration(ADC1);
while ((ADC_CR2(ADC1) & ADC_CR2_RSTCAL) != 0);
adc_calibration(ADC1);
while ((ADC_CR2(ADC1) & ADC_CR2_CAL) != 0);
}
void my_usart_print_int(u32 usart, int value)
{
s8 i;
u8 nr_digits = 0;
char buffer[25];
if (value < 0) {
usart_send_blocking(usart, '-');
value = value * -1;
}
while (value > 0) {
buffer[nr_digits++] = "0123456789"[value % 10];
value /= 10;
}
for (i = (nr_digits - 1); i >= 0; i--) {
usart_send_blocking(usart, buffer[i]);
}
usart_send_blocking(usart, '\r');
}
int main(void)
{
u8 channel_array[16];
u16 temperature = 0;
rcc_clock_setup_in_hse_12mhz_out_72mhz();
gpio_setup();
usart_setup();
timer_setup();
adc_setup();
gpio_set(GPIOA, GPIO8); /* LED1 on */
gpio_set(GPIOC, GPIO15); /* LED2 on */
/* Send a message on USART1. */
usart_send_blocking(USART2, 's');
usart_send_blocking(USART2, 't');
usart_send_blocking(USART2, 'm');
usart_send_blocking(USART2, '\r');
usart_send_blocking(USART2, '\n');
/* Select the channel we want to convert. 16=temperature_sensor. */
channel_array[0] = 16;
/* Set the injected sequence here, with number of channels */
adc_set_injected_sequence(ADC1, 1, channel_array);
/* Continously convert and poll the temperature ADC. */
while (1) {
/*
* Since the injected sampling is triggered by the timer, it gets
* updated automatically, we just need to periodically read out the value.
* It would be better to check if the JEOC bit is set, and clear it following
* so that you do not read the same value twice, especially for a slower
* sampling rate.
*/
temperature = adc_read_injected(ADC1,1); //get the result from ADC_JDR1 on ADC1 (only bottom 16bits)
/*
* That's actually not the real temperature - you have to compute it
* as described in the datasheet.
*/
my_usart_print_int(USART2, temperature);
gpio_toggle(GPIOA, GPIO8); /* LED2 on */
}
return 0;
}

View File

@ -0,0 +1,27 @@
##
## 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/>.
##
BINARY = adc_injec_timtrig_irq
# Comment the following line if you _don't_ have luftboot flashed!
LDFLAGS += -Wl,-Ttext=0x8002000
CFLAGS += -std=c99
LDSCRIPT = ../lisa-m.ld
include ../../Makefile.include

View File

@ -0,0 +1,12 @@
------------------------------------------------------------------------------
README
------------------------------------------------------------------------------
This is a simple example that sends the value read out from the
temperature sensor ADC channel of the STM32 to the USART2.
This example uses a timer trigger to sample an injected adc channel and
then uses an interrupt routine to retrieve the sample from the data register.
The terminal settings for the receiving device/PC are 115200 8n1.

View File

@ -0,0 +1,211 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Copyright (C) 2012 Piotr Esden-Tempski <piotr@esden.net>
* Copyright (C) 2012 Stephen Dwyer <dwyer.sc@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/flash.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/f1/adc.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/timer.h>
#include <libopencm3/stm32/nvic.h>
volatile u16 temperature = 0;
void usart_setup(void)
{
/* Enable clocks for GPIO port A (for GPIO_USART1_TX) and USART1. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
/* Setup GPIO pin GPIO_USART1_TX/GPIO9 on GPIO port A for transmit. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
/* Setup UART parameters. */
usart_set_baudrate(USART2, 115200);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_mode(USART2, USART_MODE_TX_RX);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
/* Finally enable the USART. */
usart_enable(USART2);
}
void gpio_setup(void)
{
/* Enable GPIO clocks. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
/* Setup the LEDs. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
}
void timer_setup(void)
{
/* Set up the timer TIM2 for injected sampling */
uint32_t timer;
volatile uint32_t *rcc_apbenr;
uint32_t rcc_apb;
timer = TIM2;
rcc_apbenr = &RCC_APB1ENR;
rcc_apb = RCC_APB1ENR_TIM2EN;
rcc_peripheral_enable_clock(rcc_apbenr, rcc_apb);
/* Time Base configuration */
timer_reset(timer);
timer_set_mode(timer, TIM_CR1_CKD_CK_INT,
TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
timer_set_period(timer, 0xFF);
timer_set_prescaler(timer, 0x8);
timer_set_clock_division(timer, 0x0);
/* Generate TRGO on every update. */
timer_set_master_mode(timer, TIM_CR2_MMS_UPDATE);
timer_enable_counter(timer);
}
void irq_setup(void)
{
/* Enable the adc1_2_isr() routine */
nvic_set_priority(NVIC_ADC1_2_IRQ, 0);
nvic_enable_irq(NVIC_ADC1_2_IRQ);
}
void adc_setup(void)
{
int i;
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN);
/* Make sure the ADC doesn't run during config. */
adc_off(ADC1);
/* We configure everything for one single timer triggered injected conversion with interrupt generation. */
/* While not needed for a single channel, try out scan mode which does all channels in one sweep and
* generates the interrupt/EOC/JEOC flags set at the end of all channels, not each one.
*/
adc_enable_scan_mode(ADC1);
adc_set_single_conversion_mode(ADC1);
/* We want to start the injected conversion with the TIM2 TRGO */
adc_enable_external_trigger_injected(ADC1,ADC_CR2_JEXTSEL_TIM2_TRGO);
/* Generate the ADC1_2_IRQ */
adc_enable_eoc_interrupt_injected(ADC1);
adc_set_right_aligned(ADC1);
/* We want to read the temperature sensor, so we have to enable it. */
adc_enable_temperature_sensor(ADC1);
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC);
adc_power_on(ADC1);
/* Wait for ADC starting up. */
for (i = 0; i < 800000; i++) /* Wait a bit. */
__asm__("nop");
adc_reset_calibration(ADC1);
while ((ADC_CR2(ADC1) & ADC_CR2_RSTCAL) != 0);
adc_calibration(ADC1);
while ((ADC_CR2(ADC1) & ADC_CR2_CAL) != 0);
}
void my_usart_print_int(u32 usart, int value)
{
s8 i;
u8 nr_digits = 0;
char buffer[25];
if (value < 0) {
usart_send_blocking(usart, '-');
value = value * -1;
}
while (value > 0) {
buffer[nr_digits++] = "0123456789"[value % 10];
value /= 10;
}
for (i = (nr_digits - 1); i >= 0; i--) {
usart_send_blocking(usart, buffer[i]);
}
usart_send_blocking(usart, '\r');
}
int main(void)
{
u8 channel_array[16];
rcc_clock_setup_in_hse_12mhz_out_72mhz();
gpio_setup();
usart_setup();
timer_setup();
irq_setup();
adc_setup();
gpio_set(GPIOA, GPIO8); /* LED1 on */
gpio_set(GPIOC, GPIO15); /* LED2 on */
/* Send a message on USART1. */
usart_send_blocking(USART2, 's');
usart_send_blocking(USART2, 't');
usart_send_blocking(USART2, 'm');
usart_send_blocking(USART2, '\r');
usart_send_blocking(USART2, '\n');
/* Select the channel we want to convert. 16=temperature_sensor. */
channel_array[0] = 16;
/* Set the injected sequence here, with number of channels */
adc_set_injected_sequence(ADC1, 1, channel_array);
/* Continously convert and poll the temperature ADC. */
while (1) {
/*
* Since sampling is triggered by the timer and copying the value
* out of the data register is handled by the interrupt routine,
* we just need to print the value and toggle the LED. It may be useful
* to buffer the adc values in some cases.
*/
/*
* That's actually not the real temperature - you have to compute it
* as described in the datasheet.
*/
my_usart_print_int(USART2, temperature);
gpio_toggle(GPIOA, GPIO8); /* LED2 on */
}
return 0;
}
void adc1_2_isr(void)
{
/* Clear Injected End Of Conversion (JEOC) */
ADC_SR(ADC1) &= ~ADC_SR_JEOC;
temperature = adc_read_injected(ADC1,1);
}

View File

@ -0,0 +1,27 @@
##
## 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/>.
##
BINARY = adc_injec_timtrig_irq_4ch
# Comment the following line if you _don't_ have luftboot flashed!
LDFLAGS += -Wl,-Ttext=0x8002000
CFLAGS += -std=c99
LDSCRIPT = ../lisa-m.ld
include ../../Makefile.include

View File

@ -0,0 +1,12 @@
------------------------------------------------------------------------------
README
------------------------------------------------------------------------------
This is a simple example that sends the values read out from four ADC
channels of the STM32 to the USART2.
This example uses a timer trigger to sample the injected adc channels and
then uses an interrupt routine to retrieve the samples from the data registers.
The terminal settings for the receiving device/PC are 115200 8n1.

View File

@ -0,0 +1,230 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Copyright (C) 2012 Piotr Esden-Tempski <piotr@esden.net>
* Copyright (C) 2012 Stephen Dwyer <dwyer.sc@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/flash.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/f1/adc.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/timer.h>
#include <libopencm3/stm32/nvic.h>
volatile u16 temperature = 0;
volatile u16 v_refint = 0;
volatile u16 lisam_adc1 = 0;
volatile u16 lisam_adc2 = 0;
u8 channel_array[4]; /* for injected sampling, 4 channels max, for regular, 16 max */
void usart_setup(void)
{
/* Enable clocks for GPIO port A (for GPIO_USART1_TX) and USART1. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
/* Setup GPIO pin GPIO_USART1_TX/GPIO9 on GPIO port A for transmit. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
/* Setup UART parameters. */
usart_set_baudrate(USART2, 115200);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_mode(USART2, USART_MODE_TX_RX);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
/* Finally enable the USART. */
usart_enable(USART2);
}
void gpio_setup(void)
{
/* Enable GPIO clocks. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
/* Setup the LEDs. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
/* Setup Lisa/M v2 ADC1,2 on ANALOG1 connector */
gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, \
GPIO3 | GPIO0 );
}
void timer_setup(void)
{
/* Set up the timer TIM2 for injected sampling */
uint32_t timer;
volatile uint32_t *rcc_apbenr;
uint32_t rcc_apb;
timer = TIM2;
rcc_apbenr = &RCC_APB1ENR;
rcc_apb = RCC_APB1ENR_TIM2EN;
rcc_peripheral_enable_clock(rcc_apbenr, rcc_apb);
/* Time Base configuration */
timer_reset(timer);
timer_set_mode(timer, TIM_CR1_CKD_CK_INT,
TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
timer_set_period(timer, 0xFF);
timer_set_prescaler(timer, 0x8);
timer_set_clock_division(timer, 0x0);
/* Generate TRGO on every update. */
timer_set_master_mode(timer, TIM_CR2_MMS_UPDATE);
timer_enable_counter(timer);
}
void irq_setup(void)
{
/* Enable the adc1_2_isr() routine */
nvic_set_priority(NVIC_ADC1_2_IRQ, 0);
nvic_enable_irq(NVIC_ADC1_2_IRQ);
}
void adc_setup(void)
{
int i;
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN);
/* Make sure the ADC doesn't run during config. */
adc_off(ADC1);
/* We configure everything for one single timer triggered injected conversion with interrupt generation. */
/* While not needed for a single channel, try out scan mode which does all channels in one sweep and
* generates the interrupt/EOC/JEOC flags set at the end of all channels, not each one.
*/
adc_enable_scan_mode(ADC1);
adc_set_single_conversion_mode(ADC1);
/* We want to start the injected conversion with the TIM2 TRGO */
adc_enable_external_trigger_injected(ADC1,ADC_CR2_JEXTSEL_TIM2_TRGO);
/* Generate the ADC1_2_IRQ */
adc_enable_eoc_interrupt_injected(ADC1);
adc_set_right_aligned(ADC1);
/* We want to read the temperature sensor, so we have to enable it. */
adc_enable_temperature_sensor(ADC1);
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC);
/* Select the channels we want to convert.
* 16=temperature_sensor, 17=Vrefint, 13=ADC1, 10=ADC2
*/
channel_array[0] = 16;
channel_array[1] = 17;
channel_array[2] = 13;
channel_array[3] = 10;
adc_set_injected_sequence(ADC1, 4, channel_array);
adc_power_on(ADC1);
/* Wait for ADC starting up. */
for (i = 0; i < 800000; i++) /* Wait a bit. */
__asm__("nop");
adc_reset_calibration(ADC1);
while ((ADC_CR2(ADC1) & ADC_CR2_RSTCAL) != 0); //added this check
adc_calibration(ADC1);
while ((ADC_CR2(ADC1) & ADC_CR2_CAL) != 0); //added this check
}
void my_usart_print_int(u32 usart, int value)
{
s8 i;
u8 nr_digits = 0;
char buffer[25];
if (value < 0) {
usart_send_blocking(usart, '-');
value = value * -1;
}
while (value > 0) {
buffer[nr_digits++] = "0123456789"[value % 10];
value /= 10;
}
for (i = (nr_digits - 1); i >= 0; i--) {
usart_send_blocking(usart, buffer[i]);
}
//usart_send_blocking(usart, '\r');
}
int main(void)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz();
gpio_setup();
usart_setup();
timer_setup();
irq_setup();
adc_setup();
gpio_set(GPIOA, GPIO8); /* LED1 off */
gpio_set(GPIOC, GPIO15); /* LED5 off */
/* Send a message on USART1. */
usart_send_blocking(USART2, 's');
usart_send_blocking(USART2, 't');
usart_send_blocking(USART2, 'm');
usart_send_blocking(USART2, '\r');
usart_send_blocking(USART2, '\n');
/* Moved the channel selection and sequence init to adc_setup() */
/* Continously convert and poll the temperature ADC. */
while (1) {
/*
* Since sampling is triggered by the timer and copying the values
* out of the data registers is handled by the interrupt routine,
* we just need to print the values and toggle the LED. It may be useful
* to buffer the adc values in some cases.
*/
my_usart_print_int(USART2, temperature);
usart_send_blocking(USART2, ' ');
my_usart_print_int(USART2, v_refint);
usart_send_blocking(USART2, ' ');
my_usart_print_int(USART2, lisam_adc1);
usart_send_blocking(USART2, ' ');
my_usart_print_int(USART2, lisam_adc2);
usart_send_blocking(USART2, '\r');
gpio_toggle(GPIOA, GPIO8); /* LED2 on */
}
return 0;
}
void adc1_2_isr(void)
{
/* Clear Injected End Of Conversion (JEOC) */
ADC_SR(ADC1) &= ~ADC_SR_JEOC;
temperature = adc_read_injected(ADC1,1);
v_refint = adc_read_injected(ADC1,2);
lisam_adc1 = adc_read_injected(ADC1,3);
lisam_adc2 = adc_read_injected(ADC1,4);
}

View File

@ -3,6 +3,7 @@
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Copyright (C) 2012 Piotr Esden-Tempski <piotr@esden.net>
* 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
@ -71,14 +72,13 @@ void adc_setup(void)
/* We configure everything for one single conversion. */
adc_disable_scan_mode(ADC1);
adc_set_single_conversion_mode(ADC1);
adc_enable_discontinous_mode_regular(ADC1);
adc_disable_external_trigger_regular(ADC1);
adc_set_right_aligned(ADC1);
/* We want to read the temperature sensor, so we have to enable it. */
adc_enable_temperature_sensor(ADC1);
adc_set_conversion_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC);
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC);
adc_on(ADC1);
adc_power_on(ADC1);
/* Wait for ADC starting up. */
for (i = 0; i < 800000; i++) /* Wait a bit. */
@ -138,15 +138,14 @@ int main(void)
/* Continously convert and poll the temperature ADC. */
while (1) {
/*
* If the ADC_CR2_ON bit is already set -> setting it another time
* starts the conversion.
* Start the conversion directly (ie without a trigger).
*/
adc_on(ADC1);
adc_start_conversion_direct(ADC1);
/* Wait for end of conversion. */
while (!(ADC_SR(ADC1) & ADC_SR_EOC));
while (!(adc_eoc(ADC1)));
temperature = ADC_DR(ADC1);
temperature = adc_read_regular(ADC1);
/*
* That's actually not the real temperature - you have to compute it

View File

@ -69,14 +69,13 @@ void adc_setup(void)
/* We configure everything for one single conversion. */
adc_disable_scan_mode(ADC1);
adc_set_single_conversion_mode(ADC1);
adc_enable_discontinous_mode_regular(ADC1);
adc_disable_external_trigger_regular(ADC1);
adc_set_right_aligned(ADC1);
/* We want to read the temperature sensor, so we have to enable it. */
adc_enable_temperature_sensor(ADC1);
adc_set_conversion_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC);
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC);
adc_on(ADC1);
adc_power_on(ADC1);
/* Wait for ADC starting up. */
for (i = 0; i < 800000; i++) /* Wait a bit. */
@ -131,10 +130,9 @@ int main(void)
adc_set_regular_sequence(ADC1, 1, channel_array);
/*
* If the ADC_CR2_ON bit is already set -> setting it another time
* starts the conversion.
* Start the conversion directly (not trigger mode).
*/
adc_on(ADC1);
adc_start_conversion_direct(ADC1);
/* Wait for end of conversion. */
while (!(ADC_SR(ADC1) & ADC_SR_EOC));

View File

@ -26,14 +26,18 @@ LD = $(PREFIX)-gcc
OBJCOPY = $(PREFIX)-objcopy
OBJDUMP = $(PREFIX)-objdump
GDB = $(PREFIX)-gdb
TOOLCHAIN_DIR ?= ../../../../..
ifeq ($(wildcard ../../../../../lib/libopencm3_stm32f2.a),)
ifneq ($(strip $(shell which $(CC))),)
TOOLCHAIN_DIR := $(shell dirname `which $(CC)`)/../$(PREFIX)
endif
else
ifeq ($(V),1)
$(info We seem to be building the example in the source directory. Using local library!)
endif
TOOLCHAIN_DIR := ../../../../..
endif
CFLAGS += -Os -g -Wall -Wextra -I$(TOOLCHAIN_DIR)/include \
-fno-common -mcpu=cortex-m3 -mthumb -msoft-float -MD -DSTM32F2
LDSCRIPT ?= $(BINARY).ld

View File

@ -27,21 +27,26 @@ OBJCOPY = $(PREFIX)-objcopy
OBJDUMP = $(PREFIX)-objdump
GDB = $(PREFIX)-gdb
FLASH = $(shell which st-flash)
TOOLCHAIN_DIR ?= ../../../../..
ifeq ($(wildcard ../../../../../lib/libopencm3_stm32f4.a),)
ifneq ($(strip $(shell which $(CC))),)
TOOLCHAIN_DIR := $(shell dirname `which $(CC)`)/../$(PREFIX)
endif
else
ifeq ($(V),1)
$(info We seem to be building the example in the source directory. Using local library!)
endif
TOOLCHAIN_DIR := ../../../../..
endif
CFLAGS += -Os -g -Wall -Wextra -I$(TOOLCHAIN_DIR)/include \
-fno-common -mcpu=cortex-m4 -mthumb -msoft-float -MD -DSTM32F4
-fno-common -mcpu=cortex-m4 -mthumb \
-mfloat-abi=hard -mfpu=fpv4-sp-d16 -MD -DSTM32F4
LDSCRIPT ?= $(BINARY).ld
LDFLAGS += --static -lc -lnosys -L$(TOOLCHAIN_DIR)/lib \
-L$(TOOLCHAIN_DIR)/lib/stm32/f4 \
-T$(LDSCRIPT) -nostartfiles -Wl,--gc-sections \
-mthumb -mcpu=cortex-m4 -march=armv7 -mfix-cortex-m3-ldrd -msoft-float
-mthumb -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16
OBJS += $(BINARY).o
OOCD ?= openocd

View File

@ -0,0 +1,25 @@
##
## 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/>.
##
BINARY = mandel
LDSCRIPT = ../stm32f4-discovery.ld
include ../../Makefile.include

View File

@ -0,0 +1,12 @@
------------------------------------------------------------------------------
README
------------------------------------------------------------------------------
This example program demonstrates the floating point coprocessor usage on
the ST STM32F4DISCOVERY eval board.
A mandelbrot fractal is calculated and sent as "ascii-art" image through
the USART2.
The terminal settings for the receiving device/PC are 38400 8n1.

View File

@ -0,0 +1,127 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
* Copyright (C) 2012 Daniel Serpell <daniel.serpell@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f4/rcc.h>
#include <libopencm3/stm32/f4/gpio.h>
#include <libopencm3/stm32/usart.h>
void clock_setup(void)
{
/* Enable high-speed clock at 120MHz */
rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_120MHZ]);
/* Enable GPIOD clock for LED & USARTs. */
rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN);
rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN);
/* Enable clocks for USART2. */
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
}
void usart_setup(void)
{
/* Setup USART2 parameters. */
usart_set_baudrate(USART2, 38400);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_mode(USART2, USART_MODE_TX);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
/* Finally enable the USART. */
usart_enable(USART2);
}
void gpio_setup(void)
{
/* Setup GPIO pin GPIO12 on GPIO port D for LED. */
gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO12);
/* Setup GPIO pins for USART2 transmit. */
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2);
/* Setup USART2 TX pin as alternate function. */
gpio_set_af(GPIOA, GPIO_AF7, GPIO2);
}
/* Maximum number of iterations for the escape-time calculation */
#define maxIter 32
/* This array converts the iteration count to a character representation. */
static char color[maxIter+1] = " .:++xxXXX%%%%%%################";
/* Main mandelbrot calculation */
static int iterate(float px, float py)
{
int it=0;
float x=0,y=0;
while(it<maxIter)
{
float nx = x*x;
float ny = y*y;
if( (nx + ny) > 4 )
return it;
// Zn+1 = Zn^2 + P
y = 2*x*y + py;
x = nx - ny + px;
it++;
}
return 0;
}
static void mandel(float cX, float cY, float scale)
{
int x,y;
for(x=-60;x<60;x++)
{
for(y=-50;y<50;y++)
{
int i = iterate(cX+x*scale, cY+y*scale);
usart_send_blocking(USART2, color[i]);
}
usart_send_blocking(USART2, '\r');
usart_send_blocking(USART2, '\n');
}
}
int main(void)
{
float scale = 0.25f, centerX = -0.5f, centerY = 0.0f;
clock_setup();
gpio_setup();
usart_setup();
while (1) {
/* Blink the LED (PD12) on the board with each fractal drawn. */
gpio_toggle(GPIOD, GPIO12); /* LED on/off */
mandel(centerX,centerY,scale); /* draw mandelbrot */
/* Change scale and center */
centerX += 0.175f * scale;
centerY += 0.522f * scale;
scale *= 0.875f;
usart_send_blocking(USART2, '\r');
usart_send_blocking(USART2, '\n');
}
return 0;
}

View File

@ -0,0 +1,25 @@
##
## 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/>.
##
BINARY = random
LDSCRIPT = ../stm32f4-discovery.ld
include ../../Makefile.include

View File

@ -0,0 +1,5 @@
------------------------------------------------------------------------------
README
------------------------------------------------------------------------------
This example randomly blinks the green LED on the ST STM32F4DISCOVERY eval board.

View File

@ -0,0 +1,88 @@
/*
* 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/cm3/common.h>
#include <libopencm3/stm32/f4/rcc.h>
#include <libopencm3/stm32/f4/gpio.h>
#include <libopencm3/stm32/f4/rng.h>
static void rcc_setup(void)
{
rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_120MHZ]);
/* Enable GPIOD clock for onboard leds. */
rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN);
/* Enable rng clock */
rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_RNGEN);
}
static void rng_setup(void)
{
/* Enable interupt */
/* Set the IE bit in the RNG_CR register. */
RNG_CR |= RNG_CR_IE;
/* Enable the random number generation by setting the RNGEN bit in the RNG_CR
register. This activates the analog part, the RNG_LFSR and the error detector.
*/
RNG_CR |= RNG_CR_EN;
}
static void gpio_setup(void)
{
/* Setup onboard led */
gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO12 | GPIO13);
}
/* Tried to folow the guidelines in the stm32f4 user manual.*/
static u32 random_int(void)
{
static u32 last_value=0;
static u32 new_value=0;
u32 error_bits = 0;
error_bits = RNG_SR_SEIS | RNG_SR_CEIS;
while (new_value==last_value) {
/* Check for error flags and if data is ready. */
if ( ((RNG_SR & error_bits) == 0) && ( (RNG_SR & RNG_SR_DRDY) == 1 ) )
new_value=RNG_DR;
}
last_value=new_value;
return new_value;
}
int main(void)
{
int i,j;
rcc_setup();
gpio_setup();
rng_setup();
while(1){
u32 rnd;
rnd = random_int();
for(i=0;i!=32;++i){
if ( (rnd & (1 << i))!=0 )
gpio_set(GPIOD, GPIO12);
else
gpio_clear(GPIOD, GPIO12);
/* Delay */
for(j=0;j!=5000000;++j)
__asm__("nop");
}
}
}

View File

@ -21,13 +21,485 @@
#ifndef LIBOPENCM3_LM3S_IRQ_H
#define LIBOPENCM3_LM3S_IRQ_H
/* TODO: Interrupt definitions */
#define IRQ_COUNT 0
#define IRQ_GPIOA 0
#define IRQ_GPIOB 1
#define IRQ_GPIOC 2
#define IRQ_GPIOD 3
#define IRQ_GPIOE 4
#define IRQ_UART0 5
#define IRQ_UART1 6
#define IRQ_SSI0 7
#define IRQ_I2C0 8
#define IRQ_PWM0_FAULT 9
#define IRQ_PWM0_0 10
#define IRQ_PWM0_1 11
#define IRQ_PWM0_2 12
#define IRQ_QEI0 13
#define IRQ_ADC0SS0 14
#define IRQ_ADC0SS1 15
#define IRQ_ADC0SS2 16
#define IRQ_ADC0SS3 17
#define IRQ_WATCHDOG 18
#define IRQ_TIMER0A 19
#define IRQ_TIMER0B 20
#define IRQ_TIMER1A 21
#define IRQ_TIMER1B 22
#define IRQ_TIMER2A 23
#define IRQ_TIMER2B 24
#define IRQ_COMP0 25
#define IRQ_COMP1 26
#define IRQ_COMP2 27
#define IRQ_SYSCTL 28
#define IRQ_FLASH 29
#define IRQ_GPIOF 30
#define IRQ_GPIOG 31
#define IRQ_GPIOH 32
#define IRQ_UART2 33
#define IRQ_SSI1 34
#define IRQ_TIMER3A 35
#define IRQ_TIMER3B 36
#define IRQ_I2C1 37
#define IRQ_QEI1 38
#define IRQ_CAN0 39
#define IRQ_CAN1 40
#define IRQ_CAN2 41
#define IRQ_ETH 42
#define IRQ_HIBERNATE 43
#define IRQ_USB0 44
#define IRQ_PWM0_3 45
#define IRQ_UDMA 46
#define IRQ_UDMAERR 47
#define IRQ_ADC1SS0 48
#define IRQ_ADC1SS1 49
#define IRQ_ADC1SS2 50
#define IRQ_ADC1SS3 51
#define IRQ_I2S0 52
#define IRQ_EPI0 53
#define IRQ_GPIOJ 54
#define IRQ_GPIOK 55
#define IRQ_GPIOL 56
#define IRQ_SSI2 57
#define IRQ_SSI3 58
#define IRQ_UART3 59
#define IRQ_UART4 60
#define IRQ_UART5 61
#define IRQ_UART6 62
#define IRQ_UART7 63
/* undefined: slot 64 */
/* undefined: slot 65 */
/* undefined: slot 66 */
/* undefined: slot 67 */
#define IRQ_I2C2 68
#define IRQ_I2C3 69
#define IRQ_TIMER4A 70
#define IRQ_TIMER4B 71
/* undefined: slot 72 */
/* undefined: slot 73 */
/* undefined: slot 74 */
/* undefined: slot 75 */
/* undefined: slot 76 */
/* undefined: slot 77 */
/* undefined: slot 78 */
/* undefined: slot 79 */
/* undefined: slot 80 */
/* undefined: slot 81 */
/* undefined: slot 82 */
/* undefined: slot 83 */
/* undefined: slot 84 */
/* undefined: slot 85 */
/* undefined: slot 86 */
/* undefined: slot 87 */
/* undefined: slot 88 */
/* undefined: slot 89 */
/* undefined: slot 90 */
/* undefined: slot 91 */
#define IRQ_TIMER5A 92
#define IRQ_TIMER5B 93
#define IRQ_WTIMER0A 94
#define IRQ_WTIMER0B 95
#define IRQ_WTIMER1A 96
#define IRQ_WTIMER1B 97
#define IRQ_WTIMER2A 98
#define IRQ_WTIMER2B 99
#define IRQ_WTIMER3A 100
#define IRQ_WTIMER3B 101
#define IRQ_WTIMER4A 102
#define IRQ_WTIMER4B 103
#define IRQ_WTIMER5A 104
#define IRQ_WTIMER5B 105
#define IRQ_SYSEXC 106
#define IRQ_PECI0 107
#define IRQ_LPC0 108
#define IRQ_I2C4 109
#define IRQ_I2C5 110
#define IRQ_GPIOM 111
#define IRQ_GPION 112
/* undefined: slot 113 */
#define IRQ_FAN0 114
/* undefined: slot 115 */
#define IRQ_GPIOP0 116
#define IRQ_GPIOP1 117
#define IRQ_GPIOP2 118
#define IRQ_GPIOP3 119
#define IRQ_GPIOP4 120
#define IRQ_GPIOP5 121
#define IRQ_GPIOP6 122
#define IRQ_GPIOP7 123
#define IRQ_GPIOQ0 124
#define IRQ_GPIOQ1 125
#define IRQ_GPIOQ2 126
#define IRQ_GPIOQ3 127
#define IRQ_GPIOQ4 128
#define IRQ_GPIOQ5 129
#define IRQ_GPIOQ6 130
#define IRQ_GPIOQ7 131
/* undefined: slot 132 */
/* undefined: slot 133 */
#define IRQ_PWM1_0 134
#define IRQ_PWM1_1 135
#define IRQ_PWM1_2 136
#define IRQ_PWM1_3 137
#define IRQ_PWM1_FAULT 138
/* TODO: Interrupt handler prototypes */
#define IRQ_COUNT 139
/* TODO: Interrupt handler weak aliases */
#define WEAK __attribute__ ((weak))
#define IRQ_HANDLERS
void WEAK gpioa_isr(void);
void WEAK gpiob_isr(void);
void WEAK gpioc_isr(void);
void WEAK gpiod_isr(void);
void WEAK gpioe_isr(void);
void WEAK uart0_isr(void);
void WEAK uart1_isr(void);
void WEAK ssi0_isr(void);
void WEAK i2c0_isr(void);
void WEAK pwm0_fault_isr(void);
void WEAK pwm0_0_isr(void);
void WEAK pwm0_1_isr(void);
void WEAK pwm0_2_isr(void);
void WEAK qei0_isr(void);
void WEAK adc0ss0_isr(void);
void WEAK adc0ss1_isr(void);
void WEAK adc0ss2_isr(void);
void WEAK adc0ss3_isr(void);
void WEAK watchdog_isr(void);
void WEAK timer0a_isr(void);
void WEAK timer0b_isr(void);
void WEAK timer1a_isr(void);
void WEAK timer1b_isr(void);
void WEAK timer2a_isr(void);
void WEAK timer2b_isr(void);
void WEAK comp0_isr(void);
void WEAK comp1_isr(void);
void WEAK comp2_isr(void);
void WEAK sysctl_isr(void);
void WEAK flash_isr(void);
void WEAK gpiof_isr(void);
void WEAK gpiog_isr(void);
void WEAK gpioh_isr(void);
void WEAK uart2_isr(void);
void WEAK ssi1_isr(void);
void WEAK timer3a_isr(void);
void WEAK timer3b_isr(void);
void WEAK i2c1_isr(void);
void WEAK qei1_isr(void);
void WEAK can0_isr(void);
void WEAK can1_isr(void);
void WEAK can2_isr(void);
void WEAK eth_isr(void);
void WEAK hibernate_isr(void);
void WEAK usb0_isr(void);
void WEAK pwm0_3_isr(void);
void WEAK udma_isr(void);
void WEAK udmaerr_isr(void);
void WEAK adc1ss0_isr(void);
void WEAK adc1ss1_isr(void);
void WEAK adc1ss2_isr(void);
void WEAK adc1ss3_isr(void);
void WEAK i2s0_isr(void);
void WEAK epi0_isr(void);
void WEAK gpioj_isr(void);
void WEAK gpiok_isr(void);
void WEAK gpiol_isr(void);
void WEAK ssi2_isr(void);
void WEAK ssi3_isr(void);
void WEAK uart3_isr(void);
void WEAK uart4_isr(void);
void WEAK uart5_isr(void);
void WEAK uart6_isr(void);
void WEAK uart7_isr(void);
void WEAK i2c2_isr(void);
void WEAK i2c3_isr(void);
void WEAK timer4a_isr(void);
void WEAK timer4b_isr(void);
void WEAK timer5a_isr(void);
void WEAK timer5b_isr(void);
void WEAK wtimer0a_isr(void);
void WEAK wtimer0b_isr(void);
void WEAK wtimer1a_isr(void);
void WEAK wtimer1b_isr(void);
void WEAK wtimer2a_isr(void);
void WEAK wtimer2b_isr(void);
void WEAK wtimer3a_isr(void);
void WEAK wtimer3b_isr(void);
void WEAK wtimer4a_isr(void);
void WEAK wtimer4b_isr(void);
void WEAK wtimer5a_isr(void);
void WEAK wtimer5b_isr(void);
void WEAK sysexc_isr(void);
void WEAK peci0_isr(void);
void WEAK lpc0_isr(void);
void WEAK i2c4_isr(void);
void WEAK i2c5_isr(void);
void WEAK gpiom_isr(void);
void WEAK gpion_isr(void);
void WEAK fan0_isr(void);
void WEAK gpiop0_isr(void);
void WEAK gpiop1_isr(void);
void WEAK gpiop2_isr(void);
void WEAK gpiop3_isr(void);
void WEAK gpiop4_isr(void);
void WEAK gpiop5_isr(void);
void WEAK gpiop6_isr(void);
void WEAK gpiop7_isr(void);
void WEAK gpioq0_isr(void);
void WEAK gpioq1_isr(void);
void WEAK gpioq2_isr(void);
void WEAK gpioq3_isr(void);
void WEAK gpioq4_isr(void);
void WEAK gpioq5_isr(void);
void WEAK gpioq6_isr(void);
void WEAK gpioq7_isr(void);
void WEAK pwm1_0_isr(void);
void WEAK pwm1_1_isr(void);
void WEAK pwm1_2_isr(void);
void WEAK pwm1_3_isr(void);
void WEAK pwm1_fault_isr(void);
#pragma weak gpioa_isr = blocking_handler
#pragma weak gpiob_isr = blocking_handler
#pragma weak gpioc_isr = blocking_handler
#pragma weak gpiod_isr = blocking_handler
#pragma weak gpioe_isr = blocking_handler
#pragma weak uart0_isr = blocking_handler
#pragma weak uart1_isr = blocking_handler
#pragma weak ssi0_isr = blocking_handler
#pragma weak i2c0_isr = blocking_handler
#pragma weak pwm0_fault_isr = blocking_handler
#pragma weak pwm0_0_isr = blocking_handler
#pragma weak pwm0_1_isr = blocking_handler
#pragma weak pwm0_2_isr = blocking_handler
#pragma weak qei0_isr = blocking_handler
#pragma weak adc0ss0_isr = blocking_handler
#pragma weak adc0ss1_isr = blocking_handler
#pragma weak adc0ss2_isr = blocking_handler
#pragma weak adc0ss3_isr = blocking_handler
#pragma weak watchdog_isr = blocking_handler
#pragma weak timer0a_isr = blocking_handler
#pragma weak timer0b_isr = blocking_handler
#pragma weak timer1a_isr = blocking_handler
#pragma weak timer1b_isr = blocking_handler
#pragma weak timer2a_isr = blocking_handler
#pragma weak timer2b_isr = blocking_handler
#pragma weak comp0_isr = blocking_handler
#pragma weak comp1_isr = blocking_handler
#pragma weak comp2_isr = blocking_handler
#pragma weak sysctl_isr = blocking_handler
#pragma weak flash_isr = blocking_handler
#pragma weak gpiof_isr = blocking_handler
#pragma weak gpiog_isr = blocking_handler
#pragma weak gpioh_isr = blocking_handler
#pragma weak uart2_isr = blocking_handler
#pragma weak ssi1_isr = blocking_handler
#pragma weak timer3a_isr = blocking_handler
#pragma weak timer3b_isr = blocking_handler
#pragma weak i2c1_isr = blocking_handler
#pragma weak qei1_isr = blocking_handler
#pragma weak can0_isr = blocking_handler
#pragma weak can1_isr = blocking_handler
#pragma weak can2_isr = blocking_handler
#pragma weak eth_isr = blocking_handler
#pragma weak hibernate_isr = blocking_handler
#pragma weak usb0_isr = blocking_handler
#pragma weak pwm0_3_isr = blocking_handler
#pragma weak udma_isr = blocking_handler
#pragma weak udmaerr_isr = blocking_handler
#pragma weak adc1ss0_isr = blocking_handler
#pragma weak adc1ss1_isr = blocking_handler
#pragma weak adc1ss2_isr = blocking_handler
#pragma weak adc1ss3_isr = blocking_handler
#pragma weak i2s0_isr = blocking_handler
#pragma weak epi0_isr = blocking_handler
#pragma weak gpioj_isr = blocking_handler
#pragma weak gpiok_isr = blocking_handler
#pragma weak gpiol_isr = blocking_handler
#pragma weak ssi2_isr = blocking_handler
#pragma weak ssi3_isr = blocking_handler
#pragma weak uart3_isr = blocking_handler
#pragma weak uart4_isr = blocking_handler
#pragma weak uart5_isr = blocking_handler
#pragma weak uart6_isr = blocking_handler
#pragma weak uart7_isr = blocking_handler
#pragma weak i2c2_isr = blocking_handler
#pragma weak i2c3_isr = blocking_handler
#pragma weak timer4a_isr = blocking_handler
#pragma weak timer4b_isr = blocking_handler
#pragma weak timer5a_isr = blocking_handler
#pragma weak timer5b_isr = blocking_handler
#pragma weak wtimer0a_isr = blocking_handler
#pragma weak wtimer0b_isr = blocking_handler
#pragma weak wtimer1a_isr = blocking_handler
#pragma weak wtimer1b_isr = blocking_handler
#pragma weak wtimer2a_isr = blocking_handler
#pragma weak wtimer2b_isr = blocking_handler
#pragma weak wtimer3a_isr = blocking_handler
#pragma weak wtimer3b_isr = blocking_handler
#pragma weak wtimer4a_isr = blocking_handler
#pragma weak wtimer4b_isr = blocking_handler
#pragma weak wtimer5a_isr = blocking_handler
#pragma weak wtimer5b_isr = blocking_handler
#pragma weak sysexc_isr = blocking_handler
#pragma weak peci0_isr = blocking_handler
#pragma weak lpc0_isr = blocking_handler
#pragma weak i2c4_isr = blocking_handler
#pragma weak i2c5_isr = blocking_handler
#pragma weak gpiom_isr = blocking_handler
#pragma weak gpion_isr = blocking_handler
#pragma weak fan0_isr = blocking_handler
#pragma weak gpiop0_isr = blocking_handler
#pragma weak gpiop1_isr = blocking_handler
#pragma weak gpiop2_isr = blocking_handler
#pragma weak gpiop3_isr = blocking_handler
#pragma weak gpiop4_isr = blocking_handler
#pragma weak gpiop5_isr = blocking_handler
#pragma weak gpiop6_isr = blocking_handler
#pragma weak gpiop7_isr = blocking_handler
#pragma weak gpioq0_isr = blocking_handler
#pragma weak gpioq1_isr = blocking_handler
#pragma weak gpioq2_isr = blocking_handler
#pragma weak gpioq3_isr = blocking_handler
#pragma weak gpioq4_isr = blocking_handler
#pragma weak gpioq5_isr = blocking_handler
#pragma weak gpioq6_isr = blocking_handler
#pragma weak gpioq7_isr = blocking_handler
#pragma weak pwm1_0_isr = blocking_handler
#pragma weak pwm1_1_isr = blocking_handler
#pragma weak pwm1_2_isr = blocking_handler
#pragma weak pwm1_3_isr = blocking_handler
#pragma weak pwm1_fault_isr = blocking_handler
#define IRQ_HANDLERS \
[IRQ_GPIOA] = gpioa_isr, \
[IRQ_GPIOB] = gpiob_isr, \
[IRQ_GPIOC] = gpioc_isr, \
[IRQ_GPIOD] = gpiod_isr, \
[IRQ_GPIOE] = gpioe_isr, \
[IRQ_UART0] = uart0_isr, \
[IRQ_UART1] = uart1_isr, \
[IRQ_SSI0] = ssi0_isr, \
[IRQ_I2C0] = i2c0_isr, \
[IRQ_PWM0_FAULT] = pwm0_fault_isr, \
[IRQ_PWM0_0] = pwm0_0_isr, \
[IRQ_PWM0_1] = pwm0_1_isr, \
[IRQ_PWM0_2] = pwm0_2_isr, \
[IRQ_QEI0] = qei0_isr, \
[IRQ_ADC0SS0] = adc0ss0_isr, \
[IRQ_ADC0SS1] = adc0ss1_isr, \
[IRQ_ADC0SS2] = adc0ss2_isr, \
[IRQ_ADC0SS3] = adc0ss3_isr, \
[IRQ_WATCHDOG] = watchdog_isr, \
[IRQ_TIMER0A] = timer0a_isr, \
[IRQ_TIMER0B] = timer0b_isr, \
[IRQ_TIMER1A] = timer1a_isr, \
[IRQ_TIMER1B] = timer1b_isr, \
[IRQ_TIMER2A] = timer2a_isr, \
[IRQ_TIMER2B] = timer2b_isr, \
[IRQ_COMP0] = comp0_isr, \
[IRQ_COMP1] = comp1_isr, \
[IRQ_COMP2] = comp2_isr, \
[IRQ_SYSCTL] = sysctl_isr, \
[IRQ_FLASH] = flash_isr, \
[IRQ_GPIOF] = gpiof_isr, \
[IRQ_GPIOG] = gpiog_isr, \
[IRQ_GPIOH] = gpioh_isr, \
[IRQ_UART2] = uart2_isr, \
[IRQ_SSI1] = ssi1_isr, \
[IRQ_TIMER3A] = timer3a_isr, \
[IRQ_TIMER3B] = timer3b_isr, \
[IRQ_I2C1] = i2c1_isr, \
[IRQ_QEI1] = qei1_isr, \
[IRQ_CAN0] = can0_isr, \
[IRQ_CAN1] = can1_isr, \
[IRQ_CAN2] = can2_isr, \
[IRQ_ETH] = eth_isr, \
[IRQ_HIBERNATE] = hibernate_isr, \
[IRQ_USB0] = usb0_isr, \
[IRQ_PWM0_3] = pwm0_3_isr, \
[IRQ_UDMA] = udma_isr, \
[IRQ_UDMAERR] = udmaerr_isr, \
[IRQ_ADC1SS0] = adc1ss0_isr, \
[IRQ_ADC1SS1] = adc1ss1_isr, \
[IRQ_ADC1SS2] = adc1ss2_isr, \
[IRQ_ADC1SS3] = adc1ss3_isr, \
[IRQ_I2S0] = i2s0_isr, \
[IRQ_EPI0] = epi0_isr, \
[IRQ_GPIOJ] = gpioj_isr, \
[IRQ_GPIOK] = gpiok_isr, \
[IRQ_GPIOL] = gpiol_isr, \
[IRQ_SSI2] = ssi2_isr, \
[IRQ_SSI3] = ssi3_isr, \
[IRQ_UART3] = uart3_isr, \
[IRQ_UART4] = uart4_isr, \
[IRQ_UART5] = uart5_isr, \
[IRQ_UART6] = uart6_isr, \
[IRQ_UART7] = uart7_isr, \
[IRQ_I2C2] = i2c2_isr, \
[IRQ_I2C3] = i2c3_isr, \
[IRQ_TIMER4A] = timer4a_isr, \
[IRQ_TIMER4B] = timer4b_isr, \
[IRQ_TIMER5A] = timer5a_isr, \
[IRQ_TIMER5B] = timer5b_isr, \
[IRQ_WTIMER0A] = wtimer0a_isr, \
[IRQ_WTIMER0B] = wtimer0b_isr, \
[IRQ_WTIMER1A] = wtimer1a_isr, \
[IRQ_WTIMER1B] = wtimer1b_isr, \
[IRQ_WTIMER2A] = wtimer2a_isr, \
[IRQ_WTIMER2B] = wtimer2b_isr, \
[IRQ_WTIMER3A] = wtimer3a_isr, \
[IRQ_WTIMER3B] = wtimer3b_isr, \
[IRQ_WTIMER4A] = wtimer4a_isr, \
[IRQ_WTIMER4B] = wtimer4b_isr, \
[IRQ_WTIMER5A] = wtimer5a_isr, \
[IRQ_WTIMER5B] = wtimer5b_isr, \
[IRQ_SYSEXC] = sysexc_isr, \
[IRQ_PECI0] = peci0_isr, \
[IRQ_LPC0] = lpc0_isr, \
[IRQ_I2C4] = i2c4_isr, \
[IRQ_I2C5] = i2c5_isr, \
[IRQ_GPIOM] = gpiom_isr, \
[IRQ_GPION] = gpion_isr, \
[IRQ_FAN0] = fan0_isr, \
[IRQ_GPIOP0] = gpiop0_isr, \
[IRQ_GPIOP1] = gpiop1_isr, \
[IRQ_GPIOP2] = gpiop2_isr, \
[IRQ_GPIOP3] = gpiop3_isr, \
[IRQ_GPIOP4] = gpiop4_isr, \
[IRQ_GPIOP5] = gpiop5_isr, \
[IRQ_GPIOP6] = gpiop6_isr, \
[IRQ_GPIOP7] = gpiop7_isr, \
[IRQ_GPIOQ0] = gpioq0_isr, \
[IRQ_GPIOQ1] = gpioq1_isr, \
[IRQ_GPIOQ2] = gpioq2_isr, \
[IRQ_GPIOQ3] = gpioq3_isr, \
[IRQ_GPIOQ4] = gpioq4_isr, \
[IRQ_GPIOQ5] = gpioq5_isr, \
[IRQ_GPIOQ6] = gpioq6_isr, \
[IRQ_GPIOQ7] = gpioq7_isr, \
[IRQ_PWM1_0] = pwm1_0_isr, \
[IRQ_PWM1_1] = pwm1_1_isr, \
[IRQ_PWM1_2] = pwm1_2_isr, \
[IRQ_PWM1_3] = pwm1_3_isr, \
[IRQ_PWM1_FAULT] = pwm1_fault_isr,
#endif

View File

@ -1,3 +1,17 @@
/** @defgroup crc_defines CRC Defines
@brief <b>libopencm3 Defined Constants and Types for the STM32F CRC Generator </b>
@ingroup STM32F_defines
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
@date 18 August 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*

View File

@ -252,7 +252,7 @@ LGPL License Terms @ref lgpl_license
#define ADC_CR1_DUALMOD_MASK (0xF << 16)
#define ADC_CR1_DUALMOD_SHIFT 16
/* DISCNUM[2:0]: Discontinous mode channel count. */
/* DISCNUM[2:0]: Discontinuous mode channel count. */
/****************************************************************************/
/** @defgroup adc_cr1_discnum ADC Number of channels in discontinuous mode.
@ingroup STM32F1xx_adc_defines
@ -270,10 +270,10 @@ LGPL License Terms @ref lgpl_license
#define ADC_CR1_DISCNUM_MASK (0x7 << 13)
#define ADC_CR1_DISCNUM_SHIFT 13
/* JDISCEN: */ /** Discontinous mode on injected channels. */
/* JDISCEN: */ /** Discontinuous mode on injected channels. */
#define ADC_CR1_JDISCEN (1 << 12)
/* DISCEN: */ /** Discontinous mode on regular channels. */
/* DISCEN: */ /** Discontinuous mode on regular channels. */
#define ADC_CR1_DISCEN (1 << 11)
/* JAUTO: */ /** Automatic Injection Group conversion. */
@ -557,7 +557,7 @@ LGPL License Terms @ref lgpl_license
/* --- ADC_SMPRx generic values -------------------------------------------- */
/****************************************************************************/
/* ADC_SMPRG ADC Sample Time Selection for Channels */
/** @defgroup adc_sample_rg ADC Sample Time Selection Generic
/** @defgroup adc_sample_rg ADC Sample Time Selection for All Channels
@ingroup STM32F1xx_adc_defines
@{*/
@ -587,18 +587,11 @@ LGPL License Terms @ref lgpl_license
#define ADC_SQR1_SQ15_LSB 10
#define ADC_SQR1_SQ14_LSB 5
#define ADC_SQR1_SQ13_LSB 0
#define ADC_SQR1_L_MSK (0xf << ADC_L_LSB)
#define ADC_SQR1_SQ16_MSK (0x1f << ADC_SQ16_LSB)
#define ADC_SQR1_SQ15_MSK (0x1f << ADC_SQ15_LSB)
#define ADC_SQR1_SQ14_MSK (0x1f << ADC_SQ14_LSB)
#define ADC_SQR1_SQ13_MSK (0x1f << ADC_SQ13_LSB)
/* TODO Fix error
#define ADC_SQR1_L_MSK (0xf << ADC_SQR1_L_LSB)
#define ADC_SQR1_SQ16_MSK (0x1f << ADC_SQR1_SQ16_LSB)
#define ADC_SQR1_SQ15_MSK (0x1f << ADC_SQR1_SQ15_LSB)
#define ADC_SQR1_SQ14_MSK (0x1f << ADC_SQR1_SQ14_LSB)
#define ADC_SQR1_SQ13_MSK (0x1f << ADC_SQR1_SQ13_LSB)
*/
/* --- ADC_SQR2 values ----------------------------------------------------- */
@ -608,20 +601,12 @@ LGPL License Terms @ref lgpl_license
#define ADC_SQR2_SQ9_LSB 10
#define ADC_SQR2_SQ8_LSB 5
#define ADC_SQR2_SQ7_LSB 0
#define ADC_SQR2_SQ12_MSK (0x1f << ADC_SQ12_LSB)
#define ADC_SQR2_SQ11_MSK (0x1f << ADC_SQ11_LSB)
#define ADC_SQR2_SQ10_MSK (0x1f << ADC_SQ10_LSB)
#define ADC_SQR2_SQ9_MSK (0x1f << ADC_SQ9_LSB)
#define ADC_SQR2_SQ8_MSK (0x1f << ADC_SQ8_LSB)
#define ADC_SQR2_SQ7_MSK (0x1f << ADC_SQ7_LSB)
/* TODO Fix error
#define ADC_SQR2_SQ12_MSK (0x1f << ADC_SQR2_SQ12_LSB)
#define ADC_SQR2_SQ11_MSK (0x1f << ADC_SQR2_SQ11_LSB)
#define ADC_SQR2_SQ10_MSK (0x1f << ADC_SQR2_SQ10_LSB)
#define ADC_SQR2_SQ9_MSK (0x1f << ADC_SQR2_SQ9_LSB)
#define ADC_SQR2_SQ8_MSK (0x1f << ADC_SQR2_SQ8_LSB)
#define ADC_SQR2_SQ7_MSK (0x1f << ADC_SQR2_SQ7_LSB)
*/
/* --- ADC_SQR3 values ----------------------------------------------------- */
@ -631,20 +616,12 @@ LGPL License Terms @ref lgpl_license
#define ADC_SQR3_SQ3_LSB 10
#define ADC_SQR3_SQ2_LSB 5
#define ADC_SQR3_SQ1_LSB 0
#define ADC_SQR3_SQ6_MSK (0x1f << ADC_SQ6_LSB)
#define ADC_SQR3_SQ5_MSK (0x1f << ADC_SQ5_LSB)
#define ADC_SQR3_SQ4_MSK (0x1f << ADC_SQ4_LSB)
#define ADC_SQR3_SQ3_MSK (0x1f << ADC_SQ3_LSB)
#define ADC_SQR3_SQ2_MSK (0x1f << ADC_SQ2_LSB)
#define ADC_SQR3_SQ1_MSK (0x1f << ADC_SQ1_LSB)
/* TODO Fix error
#define ADC_SQR3_SQ6_MSK (0x1f << ADC_SQR3_SQ6_LSB)
#define ADC_SQR3_SQ5_MSK (0x1f << ADC_SQR3_SQ5_LSB)
#define ADC_SQR3_SQ4_MSK (0x1f << ADC_SQR3_SQ4_LSB)
#define ADC_SQR3_SQ3_MSK (0x1f << ADC_SQR3_SQ3_LSB)
#define ADC_SQR3_SQ2_MSK (0x1f << ADC_SQR3_SQ2_LSB)
#define ADC_SQR3_SQ1_MSK (0x1f << ADC_SQR3_SQ1_LSB)
*/
/* --- ADC_JSQR values ----------------------------------------------------- */
#define ADC_JSQR_JL_LSB 20
@ -652,18 +629,24 @@ LGPL License Terms @ref lgpl_license
#define ADC_JSQR_JSQ3_LSB 10
#define ADC_JSQR_JSQ2_LSB 5
#define ADC_JSQR_JSQ1_LSB 0
#define ADC_JSQR_JL_MSK (0x2 << ADC_JL_LSB)
#define ADC_JSQR_JSQ4_MSK (0x1f << ADC_JSQ4_LSB)
#define ADC_JSQR_JSQ3_MSK (0x1f << ADC_JSQ3_LSB)
#define ADC_JSQR_JSQ2_MSK (0x1f << ADC_JSQ2_LSB)
#define ADC_JSQR_JSQ1_MSK (0x1f << ADC_JSQ1_LSB)
/* TODO Fix error
/* JL[2:0]: Discontinous mode channel count injected channels. */
/****************************************************************************/
/** @defgroup adc_jsqr_jl ADC Number of channels in discontinuous mode fro injected channels.
@ingroup STM32F1xx_adc_defines
@{*/
#define ADC_JSQR_JL_1CHANNELS (0x0 << ADC_JSQR_JL_LSB)
#define ADC_JSQR_JL_2CHANNELS (0x1 << ADC_JSQR_JL_LSB)
#define ADC_JSQR_JL_3CHANNELS (0x2 << ADC_JSQR_JL_LSB)
#define ADC_JSQR_JL_4CHANNELS (0x3 << ADC_JSQR_JL_LSB)
/**@}*/
#define ADC_JSQR_JL_SHIFT 13
#define ADC_JSQR_JL_MSK (0x2 << ADC_JSQR_JL_LSB)
#define ADC_JSQR_JSQ4_MSK (0x1f << ADC_JSQR_JSQ4_LSB)
#define ADC_JSQR_JSQ3_MSK (0x1f << ADC_JSQR_JSQ3_LSB)
#define ADC_JSQR_JSQ2_MSK (0x1f << ADC_JSQR_JSQ2_LSB)
#define ADC_JSQR_JSQ1_MSK (0x1f << ADC_JSQR_JSQ1_LSB)
*/
/* --- ADC_JDRx, ADC_DR values --------------------------------------------- */
@ -679,22 +662,31 @@ LGPL License Terms @ref lgpl_license
BEGIN_DECLS
void adc_power_on(u32 adc);
void adc_start_conversion_direct(u32 adc);
void adc_set_single_channel(u32 adc, u8 channel);
void adc_set_dual_mode(u32 mode);
bool adc_eoc(u32 adc);
bool adc_eoc_injected(u32 adc);
u32 adc_read_regular(u32 adc);
u32 adc_read_injected(u32 adc, u8 reg);
void adc_set_injected_offset(u32 adc, u8 reg, u32 offset);
void adc_enable_analog_watchdog_regular(u32 adc);
void adc_disable_analog_watchdog_regular(u32 adc);
void adc_enable_analog_watchdog_injected(u32 adc);
void adc_disable_analog_watchdog_injected(u32 adc);
void adc_enable_discontinous_mode_regular(u32 adc);
void adc_disable_discontinous_mode_regular(u32 adc);
void adc_enable_discontinous_mode_injected(u32 adc);
void adc_disable_discontinous_mode_injected(u32 adc);
void adc_enable_discontinuous_mode_regular(u32 adc, u8 length);
void adc_disable_discontinuous_mode_regular(u32 adc);
void adc_enable_discontinuous_mode_injected(u32 adc);
void adc_disable_discontinuous_mode_injected(u32 adc);
void adc_enable_automatic_injected_group_conversion(u32 adc);
void adc_disable_automatic_injected_group_conversion(u32 adc);
void adc_enable_analog_watchdog_on_all_channels(u32 adc);
void adc_enable_analog_watchdog_on_selected_channel(u32 adc, u8 channel);
void adc_enable_scan_mode(u32 adc);
void adc_disable_scan_mode(u32 adc);
void adc_enable_jeoc_interrupt(u32 adc);
void adc_disable_jeoc_interrupt(u32 adc);
void adc_enable_eoc_interrupt_injected(u32 adc);
void adc_disable_eoc_interrupt_injected(u32 adc);
void adc_enable_awd_interrupt(u32 adc);
void adc_disable_awd_interrupt(u32 adc);
void adc_enable_eoc_interrupt(u32 adc);
@ -713,17 +705,28 @@ void adc_enable_dma(u32 adc);
void adc_disable_dma(u32 adc);
void adc_reset_calibration(u32 adc);
void adc_calibration(u32 adc);
void adc_set_continous_conversion_mode(u32 adc);
void adc_set_continuous_conversion_mode(u32 adc);
void adc_set_single_conversion_mode(u32 adc);
#ifdef __GNUC__
void adc_on(u32 adc) __attribute__ ((deprecated ("will be removed in the first release")));
#else
void adc_on(u32 adc);
#endif
void adc_off(u32 adc);
void adc_set_conversion_time(u32 adc, u8 channel, u8 time);
void adc_set_conversion_time_on_all_channels(u32 adc, u8 time);
void adc_set_sample_time(u32 adc, u8 channel, u8 time);
void adc_set_sample_time_on_all_channels(u32 adc, u8 time);
void adc_set_watchdog_high_threshold(u32 adc, u16 threshold);
void adc_set_watchdog_low_threshold(u32 adc, u16 threshold);
void adc_set_regular_sequence(u32 adc, u8 length, u8 channel[]);
void adc_set_injected_sequence(u32 adc, u8 length, u8 channel[]);
#ifdef __GNUC__
void adc_set_continous_conversion_mode(u32 adc) __attribute__ ((deprecated ("change to adc_set_continuous_conversion_mode")));
void adc_set_conversion_time(u32 adc, u8 channel, u8 time) __attribute__ ((deprecated ("change to adc_set_sample_time")));
void adc_set_conversion_time_on_all_channels(u32 adc, u8 time) __attribute__ ((deprecated ("change to adc_set_sample_time_on_all_channels")));
void adc_enable_jeoc_interrupt(u32 adc) __attribute__ ((deprecated ("change to adc_enable_eoc_interrupt_injected")));
void adc_disable_jeoc_interrupt(u32 adc) __attribute__ ((deprecated ("change to adc_disable_eoc_interrupt_injected")));
#endif
END_DECLS
#endif

View File

@ -0,0 +1,61 @@
/*
* 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/>.
*/
#ifndef LIBOPENCM3_RNG_H
#define LIBOPENCM3_RNG_H
#include <libopencm3/stm32/memorymap.h>
#include <libopencm3/cm3/common.h>
/* --- Random number generator registers ----------------------------------- */
/* Control register */
#define RNG_CR MMIO32(RNG_BASE + 0x00)
/* Status register */
#define RNG_SR MMIO32(RNG_BASE + 0x04)
/* Data register */
#define RNG_DR MMIO32(RNG_BASE + 0x08)
/* --- RNG_CR values ------------------------------------------------------- */
/* RNG ENABLE */
#define RNG_CR_EN (1 << 2)
/* RNG interupt enable */
#define RNG_CR_IE (1 << 3)
/* --- RNG_SR values ------------------------------------------------------- */
/* Data ready */
#define RNG_SR_DRDY (1 << 0)
/* Clock error current status */
#define RNG_SR_CECS (1 << 1)
/* Seed error current status */
#define RNG_SR_SECS (1 << 2)
/* Clock error interup status */
#define RNG_SR_CEIS (1 << 5)
/* Seed error interup status */
#define RNG_SR_SEIS (1 << 6)
#endif

View File

@ -72,6 +72,63 @@
/* AFSR: Auxiliary Fault Status Register */
#define SCB_AFSR MMIO32(SCB_BASE + 0x3C)
/* ID_PFR0: Processor Feature Register 0 */
#define SCB_ID_PFR0 MMIO32(SCB_BASE + 0x40)
/* ID_PFR1: Processor Feature Register 1 */
#define SCB_ID_PFR1 MMIO32(SCB_BASE + 0x44)
/* ID_DFR0: Debug Features Register 0 */
#define SCB_ID_DFR0 MMIO32(SCB_BASE + 0x48)
/* ID_AFR0: Auxiliary Features Register 0 */
#define SCB_ID_AFR0 MMIO32(SCB_BASE + 0x4C)
/* ID_MMFR0: Memory Model Feature Register 0 */
#define SCB_ID_MMFR0 MMIO32(SCB_BASE + 0x50)
/* ID_MMFR1: Memory Model Feature Register 1 */
#define SCB_ID_MMFR1 MMIO32(SCB_BASE + 0x54)
/* ID_MMFR2: Memory Model Feature Register 2 */
#define SCB_ID_MMFR2 MMIO32(SCB_BASE + 0x58)
/* ID_MMFR3: Memory Model Feature Register 3 */
#define SCB_ID_MMFR3 MMIO32(SCB_BASE + 0x5C)
/* ID_ISAR0: Instruction Set Attributes Register 0 */
#define SCB_ID_ISAR0 MMIO32(SCB_BASE + 0x60)
/* ID_ISAR1: Instruction Set Attributes Register 1 */
#define SCB_ID_ISAR1 MMIO32(SCB_BASE + 0x64)
/* ID_ISAR2: Instruction Set Attributes Register 2 */
#define SCB_ID_ISAR2 MMIO32(SCB_BASE + 0x68)
/* ID_ISAR3: Instruction Set Attributes Register 3 */
#define SCB_ID_ISAR3 MMIO32(SCB_BASE + 0x6C)
/* ID_ISAR4: Instruction Set Attributes Register 4 */
#define SCB_ID_ISAR4 MMIO32(SCB_BASE + 0x70)
/* CPACR: Coprocessor Access Control Register */
#define SCB_CPACR MMIO32(SCB_BASE + 0x88)
/* FPCCR: Floating-Point Context Control Register */
#define SCB_FPCCR MMIO32(SCB_BASE + 0x234)
/* FPCAR: Floating-Point Context Address Register */
#define SCB_FPCAR MMIO32(SCB_BASE + 0x238)
/* FPDSCR: Floating-Point Default Status Control Register */
#define SCB_FPDSCR MMIO32(SCB_BASE + 0x23C)
/* MVFR0: Media and Floating-Point Feature Register 0 */
#define SCB_MVFR0 MMIO32(SCB_BASE + 0x240)
/* MVFR1: Media and Floating-Point Feature Register 1 */
#define SCB_MVFR1 MMIO32(SCB_BASE + 0x244)
/* --- SCB values ---------------------------------------------------------- */
/* --- SCB_CPUID values ---------------------------------------------------- */
@ -292,6 +349,18 @@
/* BFAR [31:0]: Bus fault address */
/* --- SCB_CPACR values ---------------------------------------------------- */
/* CPACR CPn: Access privileges values */
#define SCB_CPACR_NONE 0 /* Access denied */
#define SCB_CPACR_PRIV 1 /* Privileged access only */
#define SCB_CPACR_FULL 3 /* Full access */
/* CPACR [20:21]: Access privileges for coprocessor 10 */
#define SCB_CPACR_CP10 (1 << 20)
/* CPACR [22:23]: Access privileges for coprocessor 11 */
#define SCB_CPACR_CP11 (1 << 22)
/* --- SCB functions ------------------------------------------------------- */
BEGIN_DECLS

View File

@ -1,3 +1,19 @@
/** @defgroup i2c_defines I2C Defines
@ingroup STM32F_defines
@brief <b>libopencm3 Defined Constants and Types for the STM32 I2C </b>
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
@date 12 October 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
@ -23,11 +39,19 @@
#include <libopencm3/stm32/memorymap.h>
#include <libopencm3/cm3/common.h>
/**@{*/
/* --- Convenience macros -------------------------------------------------- */
/* I2C register base adresses (for convenience) */
/****************************************************************************/
/** @defgroup i2c_reg_base I2C register base address
@ingroup i2c_defines
@{*/
#define I2C1 I2C1_BASE
#define I2C2 I2C2_BASE
/**@}*/
/* --- I2C registers ------------------------------------------------------- */
@ -146,6 +170,11 @@
/* Note: Bits [7:6] are reserved, and forced to 0 by hardware. */
/* FREQ[5:0]: Peripheral clock frequency (valid values: 2-36 MHz) */
/****************************************************************************/
/** @defgroup i2c_clock I2C clock frequency settings
@ingroup i2c_defines
@{*/
#define I2C_CR2_FREQ_2MHZ 0x02
#define I2C_CR2_FREQ_3MHZ 0x03
#define I2C_CR2_FREQ_4MHZ 0x04
@ -181,6 +210,7 @@
#define I2C_CR2_FREQ_34MHZ 0x22
#define I2C_CR2_FREQ_35MHZ 0x23
#define I2C_CR2_FREQ_36MHZ 0x24
/**@}*/
/* --- I2Cx_OAR1 values ---------------------------------------------------- */
@ -311,8 +341,14 @@
/* --- I2C const definitions ----------------------------------------------- */
/****************************************************************************/
/** @defgroup i2c_rw I2C Read/Write bit
@ingroup i2c_defines
@{*/
#define I2C_WRITE 0
#define I2C_READ 1
/**@}*/
/* --- I2C funtion prototypes----------------------------------------------- */
@ -336,3 +372,5 @@ void i2c_send_data(u32 i2c, u8 data);
END_DECLS
#endif
/**@}*/

View File

@ -1,3 +1,19 @@
/** @defgroup spi_defines SPI Defines
@ingroup STM32F_defines
@brief <b>libopencm3 Defined Constants and Types for the STM32 SPI </b>
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
@date 12 October 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
@ -23,13 +39,21 @@
#include <libopencm3/stm32/memorymap.h>
#include <libopencm3/cm3/common.h>
/**@{*/
/* Registers can be accessed as 16bit or 32bit values. */
/* --- Convenience macros -------------------------------------------------- */
/****************************************************************************/
/** @defgroup spi_reg_base SPI Register base address
@ingroup spi_defines
@{*/
#define SPI1 SPI1_BASE
#define SPI2 SPI2_I2S_BASE
#define SPI3 SPI3_I2S_BASE
/**@}*/
/* --- SPI registers ------------------------------------------------------- */
@ -110,8 +134,14 @@
#define SPI_CR1_CRCNEXT (1 << 12)
/* DFF: Data frame format */
/****************************************************************************/
/** @defgroup spi_dff SPI data frame format
@ingroup spi_defines
@{*/
#define SPI_CR1_DFF_8BIT (0 << 11)
#define SPI_CR1_DFF_16BIT (1 << 11)
/**@}*/
#define SPI_CR1_DFF (1 << 11)
/* RXONLY: Receive only */
@ -124,13 +154,24 @@
#define SPI_CR1_SSI (1 << 8)
/* LSBFIRST: Frame format */
/****************************************************************************/
/** @defgroup spi_lsbfirst SPI lsb/msb first
@ingroup spi_defines
@{*/
#define SPI_CR1_MSBFIRST (0 << 7)
#define SPI_CR1_LSBFIRST (1 << 7)
/**@}*/
/* SPE: SPI enable */
#define SPI_CR1_SPE (1 << 6)
/* BR[2:0]: Baud rate control */
/****************************************************************************/
/** @defgroup spi_baudrate SPI peripheral baud rates
@ingroup spi_defines
@{*/
#define SPI_CR1_BAUDRATE_FPCLK_DIV_2 (0x00 << 3)
#define SPI_CR1_BAUDRATE_FPCLK_DIV_4 (0x01 << 3)
#define SPI_CR1_BAUDRATE_FPCLK_DIV_8 (0x02 << 3)
@ -139,6 +180,12 @@
#define SPI_CR1_BAUDRATE_FPCLK_DIV_64 (0x05 << 3)
#define SPI_CR1_BAUDRATE_FPCLK_DIV_128 (0x06 << 3)
#define SPI_CR1_BAUDRATE_FPCLK_DIV_256 (0x07 << 3)
/**@}*/
/****************************************************************************/
/** @defgroup spi_br_pre SPI peripheral baud rate prescale values
@ingroup spi_defines
@{*/
#define SPI_CR1_BR_FPCLK_DIV_2 0x0
#define SPI_CR1_BR_FPCLK_DIV_4 0x1
#define SPI_CR1_BR_FPCLK_DIV_8 0x2
@ -147,18 +194,31 @@
#define SPI_CR1_BR_FPCLK_DIV_64 0x5
#define SPI_CR1_BR_FPCLK_DIV_128 0x6
#define SPI_CR1_BR_FPCLK_DIV_256 0x7
/**@}*/
/* MSTR: Master selection */
#define SPI_CR1_MSTR (1 << 2)
/* CPOL: Clock polarity */
/****************************************************************************/
/** @defgroup spi_cpol SPI clock polarity
@ingroup spi_defines
@{*/
#define SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE (0 << 1)
#define SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE (1 << 1)
/**@}*/
#define SPI_CR1_CPOL (1 << 1)
/* CPHA: Clock phase */
/****************************************************************************/
/** @defgroup spi_cpha SPI clock phase
@ingroup spi_defines
@{*/
#define SPI_CR1_CPHA_CLK_TRANSITION_1 (0 << 0)
#define SPI_CR1_CPHA_CLK_TRANSITION_2 (1 << 0)
/**@}*/
#define SPI_CR1_CPHA (1 << 0)
/* --- SPI_CR2 values ------------------------------------------------------ */
@ -347,4 +407,6 @@ void spi_disable_rx_dma(u32 spi);
END_DECLS
/**@}*/
#endif

View File

@ -1,6 +1,6 @@
/** @defgroup STM32F_tim_defines Timers Defines
@brief <b>libopencm3 Defined Constants and Types for the STM32F1xx Timers</b>
@brief <b>libopencm3 Defined Constants and Types for the STM32 Timers</b>
@ingroup STM32F_defines
@ -44,7 +44,7 @@ LGPL License Terms @ref lgpl_license
/* Timer register base adresses (for convenience) */
/****************************************************************************/
/** @defgroup tim_reg_base Timer register base addresses
@ingroup STM32F1xx_tim_defines
@ingroup STM32F_tim_defines
@{*/
#define TIM1 TIM1_BASE
@ -251,7 +251,7 @@ LGPL License Terms @ref lgpl_license
/****************************************************************************/
/** @defgroup tim_x_cr1_cdr TIMx_CR1 CKD[1:0] Clock Division Ratio
@ingroup STM32F1xx_tim_defines
@ingroup STM32F_tim_defines
@{*/
/* CKD[1:0]: Clock division */
@ -267,7 +267,7 @@ LGPL License Terms @ref lgpl_license
/* CMS[1:0]: Center-aligned mode selection */
/****************************************************************************/
/** @defgroup tim_x_cr1_cms TIMx_CR1 CMS[1:0]: Center-aligned Mode Selection
@ingroup STM32F1xx_tim_defines
@ingroup STM32F_tim_defines
@{*/
#define TIM_CR1_CMS_EDGE (0x0 << 5)
@ -280,7 +280,7 @@ LGPL License Terms @ref lgpl_license
/* DIR: Direction */
/****************************************************************************/
/** @defgroup tim_x_cr1_dir TIMx_CR1 DIR: Direction
@ingroup STM32F1xx_tim_defines
@ingroup STM32F_tim_defines
@{*/
#define TIM_CR1_DIR_UP (0 << 4)
@ -303,7 +303,7 @@ LGPL License Terms @ref lgpl_license
/****************************************************************************/
/** @defgroup tim_x_cr2_ois TIMx_CR2_OIS: Force Output Idle State Control Values
@ingroup STM32F1xx_tim_defines
@ingroup STM32F_tim_defines
@{*/
/* OIS4:*//** Output idle state 4 (OC4 output) */
@ -335,7 +335,7 @@ LGPL License Terms @ref lgpl_license
/* MMS[2:0]: Master mode selection */
/****************************************************************************/
/** @defgroup tim_mastermode TIMx_CR2 MMS[6:4]: Master Mode Selection
@ingroup STM32F1xx_tim_defines
@ingroup STM32F_tim_defines
@{*/
#define TIM_CR2_MMS_RESET (0x0 << 4)
@ -397,7 +397,7 @@ LGPL License Terms @ref lgpl_license
/* TS[2:0]: Trigger selection */
/** @defgroup tim_ts TS Trigger selection
@ingroup STM32F1xx_tim_defines
@ingroup STM32F_tim_defines
@{*/
/** Internal Trigger 0 (ITR0) */
@ -421,7 +421,7 @@ LGPL License Terms @ref lgpl_license
/* SMS[2:0]: Slave mode selection */
/** @defgroup tim_sms SMS Slave mode selection
@ingroup STM32F1xx_tim_defines
@ingroup STM32F_tim_defines
@{*/
/** Slave mode disabled */
@ -451,7 +451,7 @@ and generates an update of the registers. */
/****************************************************************************/
/** @defgroup tim_irq_enable TIMx_DIER Timer DMA and Interrupt Enable Values
@ingroup STM32F1xx_tim_defines
@ingroup STM32F_tim_defines
@{*/
/* TDE:*//** Trigger DMA request enable */
@ -503,7 +503,7 @@ and generates an update of the registers. */
/* --- TIMx_SR values ------------------------------------------------------ */
/****************************************************************************/
/** @defgroup tim_sr_values TIMx_SR Timer Status Register Flags
@ingroup STM32F1xx_tim_defines
@ingroup STM32F_tim_defines
@{*/
@ -548,7 +548,7 @@ and generates an update of the registers. */
/****************************************************************************/
/** @defgroup tim_event_gen TIMx_EGR Timer Event Generator Values
@ingroup STM32F1xx_tim_defines
@ingroup STM32F_tim_defines
@{*/
@ -908,7 +908,7 @@ and generates an update of the registers. */
/* LOCK[1:0]: Lock configuration */
/****************************************************************************/
/** @defgroup tim_lock TIM_BDTR_LOCK Timer Lock Values
@ingroup STM32F1xx_tim_defines
@ingroup STM32F_tim_defines
@{*/
#define TIM_BDTR_LOCK_OFF (0x0 << 8)
@ -1028,6 +1028,7 @@ BEGIN_DECLS
void timer_reset(u32 timer_peripheral);
void timer_enable_irq(u32 timer_peripheral, u32 irq);
void timer_disable_irq(u32 timer_peripheral, u32 irq);
bool timer_return_interrupt_source(u32 timer_peripheral, u32 flag);
bool timer_get_flag(u32 timer_peripheral, u32 flag);
void timer_clear_flag(u32 timer_peripheral, u32 flag);
void timer_set_mode(u32 timer_peripheral, u32 clock_div,
@ -1090,6 +1091,7 @@ void timer_set_break_lock(u32 timer_peripheral, u32 lock);
void timer_set_deadtime(u32 timer_peripheral, u32 deadtime);
void timer_generate_event(u32 timer_peripheral, u32 event);
u32 timer_get_counter(u32 timer_peripheral);
void timer_set_counter(u32 timer_peripheral, u32 count);
void timer_ic_set_filter(u32 timer, enum tim_ic_id ic, enum tim_ic_filter flt);
void timer_ic_set_prescaler(u32 timer, enum tim_ic_id ic, enum tim_ic_psc psc);

View File

@ -1,3 +1,18 @@
/** @defgroup STM32F_usart_defines USART Defines
@brief <b>libopencm3 Defined Constants and Types for the STM32F Digital to Analog Converter </b>
@ingroup STM32F_defines
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
@date 1 September 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
@ -17,6 +32,8 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#ifndef LIBOPENCM3_USART_H
#define LIBOPENCM3_USART_H
@ -25,9 +42,15 @@
/* --- Convenience macros -------------------------------------------------- */
/****************************************************************************/
/** @defgroup usart_reg_base USART register base addresses
@ingroup STM32F_usart_defines
@{*/
#define USART1 USART1_BASE
#define USART2 USART2_BASE
#define USART3 USART3_BASE
/**@}*/
#define UART4 UART4_BASE
#define UART5 UART5_BASE
@ -90,37 +113,43 @@
#define UART5_GTPR USART_GTPR(UART5_BASE)
/* --- USART_SR values ----------------------------------------------------- */
/****************************************************************************/
/** @defgroup usart_sr_flags USART Status register Flags
@ingroup STM32F_usart_defines
/* CTS: CTS flag */
/* Note: N/A on UART4/5 */
@{*/
/** CTS: CTS flag */
/** @note: undefined on UART4 and UART5 */
#define USART_SR_CTS (1 << 9)
/* LBD: LIN break detection flag */
/** LBD: LIN break detection flag */
#define USART_SR_LBD (1 << 8)
/* TXE: Transmit data buffer empty */
/** TXE: Transmit data buffer empty */
#define USART_SR_TXE (1 << 7)
/* TC: Transmission complete */
/** TC: Transmission complete */
#define USART_SR_TC (1 << 6)
/* RXNE: Read data register not empty */
/** RXNE: Read data register not empty */
#define USART_SR_RXNE (1 << 5)
/* IDLE: Idle line detected */
/** IDLE: Idle line detected */
#define USART_SR_IDLE (1 << 4)
/* ORE: Overrun error */
/** ORE: Overrun error */
#define USART_SR_ORE (1 << 3)
/* NE: Noise error flag */
/** NE: Noise error flag */
#define USART_SR_NE (1 << 2)
/* FE: Framing error */
/** FE: Framing error */
#define USART_SR_FE (1 << 1)
/* PE: Parity error */
/** PE: Parity error */
#define USART_SR_PE (1 << 0)
/**@}*/
/* --- USART_DR values ----------------------------------------------------- */
@ -269,27 +298,51 @@
/* --- Convenience defines ------------------------------------------------- */
/* CR1_PCE / CR1_PS combined values */
/****************************************************************************/
/** @defgroup usart_cr1_parity USART Parity Selection
@ingroup STM32F_usart_defines
@{*/
#define USART_PARITY_NONE 0x00
#define USART_PARITY_EVEN USART_CR1_PCE
#define USART_PARITY_ODD (USART_CR1_PS | USART_CR1_PCE)
/**@}*/
#define USART_PARITY_MASK (USART_CR1_PS | USART_CR1_PCE)
/* CR1_TE/CR1_RE combined values */
/****************************************************************************/
/** @defgroup usart_cr1_mode USART Tx/Rx Mode Selection
@ingroup STM32F_usart_defines
@{*/
#define USART_MODE_RX USART_CR1_RE
#define USART_MODE_TX USART_CR1_TE
#define USART_MODE_TX_RX (USART_CR1_RE | USART_CR1_TE)
/**@}*/
#define USART_MODE_MASK (USART_CR1_RE | USART_CR1_TE)
/****************************************************************************/
/** @defgroup usart_cr2_stopbits USART Stop Bit Selection
@ingroup STM32F_usart_defines
@{*/
#define USART_STOPBITS_1 USART_CR2_STOPBITS_1 /* 1 stop bit */
#define USART_STOPBITS_0_5 USART_CR2_STOPBITS_0_5 /* 0.5 stop bits */
#define USART_STOPBITS_2 USART_CR2_STOPBITS_2 /* 2 stop bits */
#define USART_STOPBITS_1_5 USART_CR2_STOPBITS_1_5 /* 1.5 stop bits */
/**@}*/
/* CR3_CTSE/CR3_RTSE combined values */
/****************************************************************************/
/** @defgroup usart_cr3_flowcontrol USART Hardware Flow Control Selection
@ingroup STM32F_usart_defines
@{*/
#define USART_FLOWCONTROL_NONE 0x00
#define USART_FLOWCONTROL_RTS USART_CR3_RTSE
#define USART_FLOWCONTROL_CTS USART_CR3_CTSE
#define USART_FLOWCONTROL_RTS_CTS (USART_CR3_RTSE | USART_CR3_CTSE)
/**@}*/
#define USART_FLOWCONTROL_MASK (USART_CR3_RTSE | USART_CR3_CTSE)
/* --- Function prototypes ------------------------------------------------- */
@ -314,7 +367,15 @@ void usart_enable_rx_dma(u32 usart);
void usart_disable_rx_dma(u32 usart);
void usart_enable_tx_dma(u32 usart);
void usart_disable_tx_dma(u32 usart);
void usart_enable_rx_interrupt(u32 usart);
void usart_disable_rx_interrupt(u32 usart);
void usart_enable_tx_interrupt(u32 usart);
void usart_disable_tx_interrupt(u32 usart);
bool usart_get_flag(u32 usart, u32 flag);
bool usart_get_interrupt_source(u32 usart, u32 flag);
END_DECLS
#endif
/**@}*/

View File

@ -40,7 +40,7 @@ $(SRCLIBDIR)/$(LIBNAME).ld: $(LIBNAME).ld
clean:
@printf " CLEAN lib/stm32/f1\n"
$(Q)rm -f *.o *.d
$(Q)rm -f *.o *.d ../*.o ../*.d
$(Q)rm -f $(SRCLIBDIR)/$(LIBNAME).a
$(Q)rm -f $(SRCLIBDIR)/$(LIBNAME).ld
$(Q)rm -f $(SRCLIBDIR)/$(LIBNAME)_rom_to_ram.ld

View File

@ -77,6 +77,8 @@ SECTIONS
. = ALIGN(4);
end = .;
_end = .;
__end = .;
}
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));

View File

@ -1,3 +1,17 @@
/** @defgroup crc_file CRC
@ingroup STM32F_files
@brief <b>libopencm3 STM32Fxxx CRC</b>
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2012 Karl Palsson <karlp@remake.is>
@date 15 October 2012
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
@ -19,11 +33,30 @@
#include <libopencm3/stm32/crc.h>
/**@{*/
/*-----------------------------------------------------------------------------*/
/** @brief CRC Reset.
Reset the CRC unit and forces the data register to all 1s.
*/
void crc_reset(void)
{
CRC_CR |= CRC_CR_RESET;
}
/*-----------------------------------------------------------------------------*/
/** @brief CRC Calculate.
Writes a data word to the register, the write operation stalling until the
computation is complete.
@param[in] data Unsigned int32.
@returns int32 Computed CRC result
*/
u32 crc_calculate(u32 data)
{
CRC_DR = data;
@ -31,6 +64,16 @@ u32 crc_calculate(u32 data)
return CRC_DR;
}
/*-----------------------------------------------------------------------------*/
/** @brief CRC Calculate of a Block of Data.
Writes data words consecutively to the register, the write operation stalling
until the computation of each word is complete.
@param[in] datap Unsigned int32. pointer to an array of 32 bit data words.
@returns int32 Final computed CRC result
*/
u32 crc_calculate_block(u32 *datap, int size)
{
int i;
@ -39,6 +82,5 @@ u32 crc_calculate_block(u32 *datap, int size)
}
return CRC_DR;
}
/**@}*/

View File

@ -31,7 +31,7 @@ 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 desig.o crc.o assert.o
timer.o usb_f107.o desig.o crc.o assert.o dac.o iwdg.o pwr.o
VPATH += ../../usb:../:../../cm3

View File

@ -44,12 +44,12 @@ 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.
and ADC, reset ADC and set the prescaler divider. Set dual mode to independent
(default). Enable triggering for a software trigger.
@code
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN);
adc_power_on(ADC1);
adc_calibration(ADC1);
adc_off(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);
@ -58,6 +58,10 @@ and ADC, reset ADC and set the prescaler divider. Set dual mode to independent.
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_enable_trigger(ADC1, ADC_CR2_EXTSEL_SWSTART);
adc_power_on(ADC1);
adc_reset_calibration(ADC1);
adc_calibration(ADC1);
adc_start_conversion_regular(ADC1);
while (! adc_eoc(ADC1));
reg16 = adc_read_regular(ADC1);
@ -102,38 +106,181 @@ LGPL License Terms @ref lgpl_license
#include <libopencm3/stm32/f1/adc.h>
void rcc_set_adc_clk(u32 prescaler)
/*-----------------------------------------------------------------------------*/
/** @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 has no effect.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_power_on(u32 adc)
{
/* TODO */
/* FIXME: QUICK HACK to prevent compiler warnings. */
prescaler = prescaler;
}
void adc_set_mode(u32 block, /* TODO */ u8 mode)
{
/* TODO */
/* FIXME: QUICK HACK to prevent compiler warnings. */
block = block;
mode = mode;
if (!(ADC_CR2(adc) & ADC_CR2_ADON))
ADC_CR2(adc) |= ADC_CR2_ADON;
}
/*-----------------------------------------------------------------------------*/
/** @brief ADC Read from a Conversion Result Register
/** @brief ADC Start a Conversion Without Trigger
This initiates a conversion by software without a trigger. The ADC needs to be
powered on before this is called, otherwise this function has no effect.
Note that this is not available in other STM32F families. To ensure code compatibility,
enable triggering and use a software trigger source @see adc_start_conversion_regular.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_start_conversion_direct(u32 adc)
{
if (ADC_CR2(adc) & ADC_CR2_ADON)
ADC_CR2(adc) |= ADC_CR2_ADON;
}
/*-----------------------------------------------------------------------------*/
/** @brief ADC Set Dual A/D Mode
The dual mode uses ADC1 as master and ADC2 in a slave arrangement. This setting
is applied to ADC1 only. Start of conversion when triggered can cause simultaneous
conversion with ADC2, or alternate conversion. Regular and injected conversions
can be configured, each one being separately simultaneous or alternate.
Fast interleaved mode starts ADC1 immediately on trigger, and ADC2 seven clock
cycles later.
Slow interleaved mode starts ADC1 immediately on trigger, and ADC2 fourteen clock
cycles later, followed by ADC1 fourteen cycles later again. This can only be used
on a single channel.
Alternate trigger mode must occur on an injected channel group, and alternates
between the ADCs on each trigger.
Note that sampling must not overlap between ADCs on the same channel.
Dual A/D converter modes possible:
@li IND: Independent mode.
@li CRSISM: Combined regular simultaneous + injected simultaneous mode.
@li CRSATM: Combined regular simultaneous + alternate trigger mode.
@li CISFIM: Combined injected simultaneous + fast interleaved mode.
@li CISSIM: Combined injected simultaneous + slow interleaved mode.
@li ISM: Injected simultaneous mode only.
@li RSM: Regular simultaneous mode only.
@li FIM: Fast interleaved mode only.
@li SIM: Slow interleaved mode only.
@li ATM: Alternate trigger mode only.
@param[in] mode Unsigned int32. Dual mode selection from @ref adc_cr1_dualmod
*/
void adc_set_dual_mode(u32 mode)
{
ADC1_CR1 |= mode;
}
/*-----------------------------------------------------------------------------*/
/** @brief ADC Read the End-of-Conversion Flag
This flag is set after all channels of a regular or injected group have been
converted.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
@returns bool. End of conversion flag.
*/
bool adc_eoc(u32 adc)
{
return ((ADC_SR(adc) & ADC_SR_EOC) != 0);
}
/*-----------------------------------------------------------------------------*/
/** @brief ADC Read the End-of-Conversion Flag for Injected Conversion
This flag is set after all channels of an injected group have been converted.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
@returns bool. End of conversion flag.
*/
bool adc_eoc_injected(u32 adc)
{
return ((ADC_SR(adc) & ADC_SR_JEOC) != 0);
}
/*-----------------------------------------------------------------------------*/
/** @brief ADC Read from the Regular Conversion Result Register
The result read back is 12 bits, right or left aligned within the first 16 bits.
For ADC1 only, the higher 16 bits will hold the result from ADC2 if
an appropriate dual mode has been set @see adc_set_dual_mode.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
@returns Unsigned int32 conversion result.
*/
u32 adc_read_regular(u32 adc)
{
return ADC_DR(adc);
}
/*-----------------------------------------------------------------------------*/
/** @brief ADC Read from an Injected Conversion Result Register
The result read back from the selected injected result register (one of four) is
12 bits, right or left aligned within the first 16 bits. The result can have a
negative value if the injected channel offset has been set @see adc_set_injected_offset.
@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)
u32 adc_read_injected(u32 adc, u8 reg)
{
/* TODO */
switch (reg) {
case 1:
return ADC_JDR1(adc);
case 2:
return ADC_JDR2(adc);
case 3:
return ADC_JDR3(adc);
case 4:
return ADC_JDR4(adc);
}
return 0;
}
/* FIXME: QUICK HACK to prevent compiler warnings. */
block = block;
channel = channel;
/*-----------------------------------------------------------------------------*/
/** @brief ADC Set the Injected Channel Data Offset
This value is subtracted from the injected channel results after conversion
is complete, and can result in negative results. A separate value can be specified
for each injected data register.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
@param[in] reg Unsigned int8. Register number (1 ... 4).
@param[in] offset Unsigned int32.
*/
void adc_set_injected_offset(u32 adc, u8 reg, u32 offset)
{
switch (reg) {
case 1:
ADC_JOFR1(adc) = offset;
break;
case 2:
ADC_JOFR2(adc) = offset;
break;
case 3:
ADC_JOFR3(adc) = offset;
break;
case 4:
ADC_JOFR4(adc) = offset;
break;
}
}
/*-----------------------------------------------------------------------------*/
@ -203,9 +350,11 @@ of the subgroup at the beginning of the whole group.
@param[in] length Unsigned int8. Number of channels in the group @ref adc_cr1_discnum
*/
void adc_enable_discontinous_mode_regular(u32 adc)
void adc_enable_discontinuous_mode_regular(u32 adc, u8 length)
{
ADC_CR1(adc) |= ADC_CR1_DISCEN;
if ( (length-1) > 7 ) return;
ADC_CR1(adc) |= ADC_CR1_DISCEN;
ADC_CR2(adc) |= ((length-1) << ADC_CR1_DISCNUM_SHIFT);
}
/*-----------------------------------------------------------------------------*/
@ -214,7 +363,7 @@ void adc_enable_discontinous_mode_regular(u32 adc)
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_disable_discontinous_mode_regular(u32 adc)
void adc_disable_discontinuous_mode_regular(u32 adc)
{
ADC_CR1(adc) &= ~ADC_CR1_DISCEN;
}
@ -229,7 +378,7 @@ 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)
void adc_enable_discontinuous_mode_injected(u32 adc)
{
ADC_CR1(adc) |= ADC_CR1_JDISCEN;
}
@ -240,7 +389,7 @@ void adc_enable_discontinous_mode_injected(u32 adc)
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_disable_discontinous_mode_injected(u32 adc)
void adc_disable_discontinuous_mode_injected(u32 adc)
{
ADC_CR1(adc) &= ~ADC_CR1_JDISCEN;
}
@ -257,6 +406,7 @@ channels is disabled as required.
void adc_enable_automatic_injected_group_conversion(u32 adc)
{
adc_disable_external_trigger_injected(adc);
ADC_CR1(adc) |= ADC_CR1_JAUTO;
}
@ -288,7 +438,7 @@ disabled.
void adc_enable_analog_watchdog_on_all_channels(u32 adc)
{
ADC_CR1(adc) |= ADC_CR1_AWDSGL;
ADC_CR1(adc) &= ~ADC_CR1_AWDSGL;
}
/*-----------------------------------------------------------------------------*/
@ -315,7 +465,7 @@ void adc_enable_analog_watchdog_on_selected_channel(u32 adc, u8 channel)
if (channel < 18)
reg32 |= channel;
ADC_CR1(adc) = reg32;
ADC_CR1(adc) &= ~ADC_CR1_AWDSGL;
ADC_CR1(adc) |= ADC_CR1_AWDSGL;
}
/*-----------------------------------------------------------------------------*/
@ -350,7 +500,7 @@ void adc_disable_scan_mode(u32 adc)
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_enable_jeoc_interrupt(u32 adc)
void adc_enable_eoc_interrupt_injected(u32 adc)
{
ADC_CR1(adc) |= ADC_CR1_JEOCIE;
}
@ -361,7 +511,7 @@ void adc_enable_jeoc_interrupt(u32 adc)
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_disable_jeoc_interrupt(u32 adc)
void adc_disable_eoc_interrupt_injected(u32 adc)
{
ADC_CR1(adc) &= ~ADC_CR1_JEOCIE;
}
@ -519,8 +669,7 @@ void adc_enable_external_trigger_regular(u32 adc, u32 trigger)
u32 reg32;
reg32 = (ADC_CR2(adc) & ~(ADC_CR2_EXTSEL_MASK));
if (trigger < 8)
reg32 |= (trigger);
reg32 |= (trigger);
ADC_CR2(adc) = reg32;
ADC_CR2(adc) |= ADC_CR2_EXTTRIG;
}
@ -565,14 +714,12 @@ For ADC3
@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;
reg32 = (ADC_CR2(adc) & ~(ADC_CR2_JEXTSEL_MASK)); /* Clear bits [12:14]. */
if (trigger < 8)
reg32 |= (trigger);
reg32 |= (trigger);
ADC_CR2(adc) = reg32;
ADC_CR2(adc) |= ADC_CR2_JEXTTRIG;
}
@ -681,7 +828,7 @@ 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)
void adc_set_continuous_conversion_mode(u32 adc)
{
ADC_CR2(adc) |= ADC_CR2_CONT;
}
@ -707,7 +854,7 @@ 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.
@deprecated to be removed in a later release
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
@ -740,7 +887,7 @@ The sampling time can be selected in ADC clock cycles from 1.5 to 239.5.
@param[in] time Unsigned int8. Sampling time selection from @ref adc_sample_rg
*/
void adc_set_conversion_time(u32 adc, u8 channel, u8 time)
void adc_set_sample_time(u32 adc, u8 channel, u8 time)
{
u32 reg32;
@ -767,7 +914,7 @@ all channels.
@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)
void adc_set_sample_time_on_all_channels(u32 adc, u8 time)
{
u8 i;
u32 reg32 = 0;
@ -871,12 +1018,24 @@ void adc_set_injected_sequence(u32 adc, u8 length, u8 channel[])
return;
for (i = 1; i <= length; i++)
reg32 |= (channel[i - 1] << ((i - 1) * 5));
reg32 |= (channel[4 - i] << ((4 - i) * 5));
reg32 |= ((length - 1) << ADC_JSQR_JL_LSB);
ADC_JSQR(adc) = reg32;
}
/*-----------------------------------------------------------------------------*/
/* Aliases */
#ifdef __GNUC__
void adc_set_continous_conversion_mode(u32 adc) __attribute__ ((alias("adc_set_continuous_conversion_mode")));
void adc_set_conversion_time(u32 adc, u8 channel, u8 time) __attribute__ ((alias ("adc_set_sample_time")));
void adc_set_conversion_time_on_all_channels(u32 adc, u8 time) __attribute__ ((alias ("adc_set_sample_time_on_all_channels")));
void adc_enable_jeoc_interrupt(u32 adc) __attribute__ ((alias ("adc_enable_eoc_interrupt_injected")));
void adc_disable_jeoc_interrupt(u32 adc) __attribute__ ((alias ("adc_disable_eoc_interrupt_injected")));
#endif
/**@}*/

View File

@ -157,7 +157,7 @@ The wakeup pin is used for waking the processor from standby mode.
void pwr_enable_wakeup_pin(void)
{
PWR_CSR |= PWR_CR_EWUP;
PWR_CSR |= PWR_CSR_EWUP;
}
/*---------------------------------------------------------------------------*/
@ -168,7 +168,7 @@ The wakeup pin is used for general purpose I/O.
void pwr_disable_wakeup_pin(void)
{
PWR_CSR &= ~PWR_CR_EWUP;
PWR_CSR &= ~PWR_CSR_EWUP;
}
/*---------------------------------------------------------------------------*/
@ -183,7 +183,7 @@ threshold.
bool pwr_voltage_high(void)
{
return (PWR_CSR & PWR_CR_PVDO);
return (PWR_CSR & PWR_CSR_PVDO);
}
/*---------------------------------------------------------------------------*/
@ -197,7 +197,7 @@ cleared by software (see @ref pwr_clear_standby_flag).
bool pwr_get_standby_flag(void)
{
return (PWR_CSR & PWR_CR_SBF);
return (PWR_CSR & PWR_CSR_SBF);
}
/*---------------------------------------------------------------------------*/
@ -211,7 +211,7 @@ cleared by software (see @ref pwr_clear_wakeup_flag).
bool pwr_get_wakeup_flag(void)
{
return (PWR_CSR & PWR_CR_WUF);
return (PWR_CSR & PWR_CSR_WUF);
}
/**@}*/

View File

@ -198,6 +198,31 @@ void timer_disable_irq(u32 timer_peripheral, u32 irq)
TIM_DIER(timer_peripheral) &= ~irq;
}
/*---------------------------------------------------------------------------*/
/** @brief Return Interrupt Source.
Returns true if the specified interrupt flag (UIF, TIF or CCxIF, with BIF or COMIF
for advanced timers) was set and the interrupt was enabled. If the specified flag
is not an interrupt flag, the function returns false.
@todo Timers 6-7, 9-14 have fewer interrupts, but invalid flags are not caught here.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
@param[in] flag Unsigned int32. Status register flag @ref tim_sr_values.
@returns boolean: flag set.
*/
bool timer_interrupt_source(u32 timer_peripheral, u32 flag)
{
/* flag not set or interrupt disabled or not an interrupt source */
if (((TIM_SR(timer_peripheral) & TIM_DIER(timer_peripheral) & flag) == 0) ||
(flag > TIM_SR_BIF)) return false;
/* Only an interrupt source for advanced timers */
if ((flag == TIM_SR_BIF) || (flag == TIM_SR_COMIF))
return ((timer_peripheral == TIM1) || (timer_peripheral == TIM8));
return true;
}
/*---------------------------------------------------------------------------*/
/** @brief Read a Status Flag.
@ -1671,6 +1696,20 @@ u32 timer_get_counter(u32 timer_peripheral)
return TIM_CNT(timer_peripheral);
}
/*---------------------------------------------------------------------------*/
/** @brief Set Counter
Set the value of a timer's counter register contents.
@param[in] timer_peripheral Unsigned int32. Timer register address base
@param[in] Unsigned int32. Counter value.
*/
void timer_set_counter(u32 timer_peripheral, u32 count)
{
TIM_CNT(timer_peripheral) = count;
}
/*---------------------------------------------------------------------------*/
/** @brief Set Input Capture Filter Parameters

View File

@ -24,7 +24,8 @@ PREFIX ?= arm-none-eabi
CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
-mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 \
-Wstrict-prototypes \
-ffunction-sections -fdata-sections -MD -DSTM32F4
# ARFLAGS = rcsv
ARFLAGS = rcs

View File

@ -1,2 +1,33 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f4/irq.h>
#define reset_handler original_reset_handler
#include "../../cm3/vector.c"
#undef reset_handler
#include <libopencm3/stm32/f4/scb.h>
void WEAK reset_handler(void)
{
/* Enable access to Floating-Point coprocessor. */
SCB_CPACR |= SCB_CPACR_FULL * (SCB_CPACR_CP10 | SCB_CPACR_CP11);
original_reset_handler();
}

View File

@ -1,3 +1,28 @@
/** @defgroup i2c_file I2C
@ingroup STM32F_files
@brief <b>libopencm3 STM32Fxxx I2C</b>
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
@date 15 October 2012
Devices can have up to two I2C peripherals. The peripherals support SMBus and
PMBus variants.
A peripheral begins after reset in Slave mode. To become a Master a start
condition must be generated. The peripheral will remain in Master mode unless
a multimaster contention is lost or a stop condition is generated.
@todo all sorts of lovely stuff like DMA, Interrupts, SMBus variant, Status
register access, Error conditions
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
@ -20,6 +45,17 @@
#include <libopencm3/stm32/i2c.h>
#include <libopencm3/stm32/f4/rcc.h>
/**@{*/
/*-----------------------------------------------------------------------------*/
/** @brief I2C Reset.
The I2C peripheral and all its associated configuration registers are placed in the
reset condition. The reset is effected via the RCC peripheral reset system.
@param[in] i2c Unsigned int32. I2C peripheral identifier @ref i2c_reg_base.
*/
void i2c_reset(u32 i2c)
{
switch (i2c) {
@ -34,26 +70,69 @@ void i2c_reset(u32 i2c)
}
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Peripheral Enable.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_peripheral_enable(u32 i2c)
{
I2C_CR1(i2c) |= I2C_CR1_PE;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Peripheral Disable.
This must not be reset while in Master mode until a communication has finished.
In Slave mode, the peripheral is disabled only after communication has ended.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_peripheral_disable(u32 i2c)
{
I2C_CR1(i2c) &= ~I2C_CR1_PE;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Send Start Condition.
If in Master mode this will cause a restart condition to occur at the end of the
current transmission. If in Slave mode, this will initiate a start condition
when the current bus activity is completed.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_send_start(u32 i2c)
{
I2C_CR1(i2c) |= I2C_CR1_START;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Send Stop Condition.
After the current byte transfer this will initiate a stop condition if in Master
mode, or simply release the bus if in Slave mode.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_send_stop(u32 i2c)
{
I2C_CR1(i2c) |= I2C_CR1_STOP;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Set the 7 bit Slave Address for the Peripheral.
This sets an address for Slave mode operation, in 7 bit form.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] slave Unsigned int8. Slave address 0...127.
*/
void i2c_set_own_7bit_slave_address(u32 i2c, u8 slave)
{
I2C_OAR1(i2c) = (u16)(slave << 1);
@ -61,21 +140,61 @@ void i2c_set_own_7bit_slave_address(u32 i2c, u8 slave)
I2C_OAR1(i2c) |= (1 << 14); /* Datasheet: always keep 1 by software. */
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Set the 10 bit Slave Address for the Peripheral.
This sets an address for Slave mode operation, in 10 bit form.
@todo add "I2C_OAR1(i2c) |= (1 << 14);" as above
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] slave Unsigned int16. Slave address 0...1023.
*/
void i2c_set_own_10bit_slave_address(u32 i2c, u16 slave)
{
I2C_OAR1(i2c) = (u16)(I2C_OAR1_ADDMODE | slave);
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Set Fast Mode.
Set the clock frequency to the high clock rate mode (up to 400kHz). The actual
clock frequency must be set with @ref i2c_set_clock_frequency
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_set_fast_mode(u32 i2c)
{
I2C_CCR(i2c) |= I2C_CCR_FS;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Set Standard Mode.
Set the clock frequency to the standard clock rate mode (up to 100kHz). The actual
clock frequency must be set with @ref i2c_set_clock_frequency
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_set_standard_mode(u32 i2c)
{
I2C_CCR(i2c) &= ~I2C_CCR_FS;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Set Peripheral Clock Frequency.
Set the peripheral clock frequency: 2MHz to 36MHz (the APB frequency). Note that
this is <b> not </b> the I2C bus clock. This is set in conjunction with the Clock
Control register to generate the Master bus clock, see @ref i2c_set_ccr
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] freq Unsigned int8. Clock Frequency Setting @ref i2c_clock.
*/
void i2c_set_clock_frequency(u32 i2c, u8 freq)
{
u16 reg16;
@ -84,6 +203,21 @@ void i2c_set_clock_frequency(u32 i2c, u8 freq)
I2C_CR2(i2c) = reg16;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Set Bus Clock Frequency.
Set the bus clock frequency. This is a 12 bit number (0...4095) calculated
from the formulae given in the STM32F1 reference manual in the description
of the CCR field. It is a divisor of the peripheral clock frequency
@ref i2c_set_clock_frequency modified by the fast mode setting
@ref i2c_set_fast_mode
@todo provide additional API assitance to set the clock, eg macros
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] freq Unsigned int16. Bus Clock Frequency Setting 0...4095.
*/
void i2c_set_ccr(u32 i2c, u16 freq)
{
u16 reg16;
@ -92,17 +226,48 @@ void i2c_set_ccr(u32 i2c, u16 freq)
I2C_CCR(i2c) = reg16;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Set the Rise Time.
Set the maximum rise time on the bus according to the I2C specification, as 1
more than the specified rise time in peripheral clock cycles. This is a 6 bit
number.
@todo provide additional APIP assistance.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] trise Unsigned int16. Rise Time Setting 0...63.
*/
void i2c_set_trise(u32 i2c, u16 trise)
{
I2C_TRISE(i2c) = trise;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Send the 7-bit Slave Address.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] slave Unsigned int16. Slave address 0...1023.
@param[in] readwrite Unsigned int8. Single bit to instruct slave to receive or send @ref i2c_rw.
*/
void i2c_send_7bit_address(u32 i2c, u8 slave, u8 readwrite)
{
I2C_DR(i2c) = (u8)((slave << 1) | readwrite);
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Send Data.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] data Unsigned int8. Byte to send.
*/
void i2c_send_data(u32 i2c, u8 data)
{
I2C_DR(i2c) = data;
}
/**@}*/

View File

@ -1,3 +1,43 @@
/** @defgroup spi_file SPI
@ingroup STM32F_files
@brief <b>libopencm3 STM32Fxxx SPI</b>
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies <ksarkies@internode.on.net>
@date 15 October 2012
Devices can have up to three SPI peripherals. The common 4-wire full-duplex
mode of operation is supported, along with 3-wire variants using unidirectional
communication modes or half-duplex bidirectional communication. A variety of
options allows many of the SPI variants to be supported. Multimaster operation
is also supported. A CRC can be generated and checked in hardware.
@note Some JTAG pins need to be remapped if SPI is to be used.
@note The I2S protocol shares the SPI hardware so the two protocols cannot be
used at the same time on the same peripheral.
Example: 1Mbps, positive clock polarity, leading edge trigger, 8-bit words,
LSB first.
@code
spi_init_master(SPI1, 1000000, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,
SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT,
SPI_CR1_LSBFIRST);
spi_write(SPI1, 0x55); // 8-bit write
spi_write(SPI1, 0xaa88); // 16-bit write
reg8 = spi_read(SPI1); // 8-bit read
reg16 = spi_read(SPI1); // 16-bit read
@endcode
@todo need additional functions to aid ISRs in retrieving status
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
@ -41,6 +81,17 @@
* reg16 = spi_read(SPI1); // 16-bit read
*/
/**@{*/
/*-----------------------------------------------------------------------------*/
/** @brief SPI Reset.
The SPI peripheral and all its associated configuration registers are placed in the
reset condition. The reset is effected via the RCC peripheral reset system.
@param[in] spi_peripheral Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_reset(u32 spi_peripheral)
{
switch (spi_peripheral) {
@ -59,6 +110,25 @@ void spi_reset(u32 spi_peripheral)
}
}
/*-----------------------------------------------------------------------------*/
/** @brief Configure the SPI as Master.
The SPI peripheral is configured as a master with communication parameters
baudrate, data format 8/16 bits, frame format lsb/msb first, clock polarity
and phase. The SPI enable, CRC enable and CRC next controls are not affected.
These must be controlled separately.
@todo NSS pin handling.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
@param[in] br Unsigned int32. Baudrate @ref spi_baudrate.
@param[in] cpol Unsigned int32. Clock polarity @ref spi_cpol.
@param[in] cpha Unsigned int32. Clock Phase @ref spi_cpha.
@param[in] dff Unsigned int32. Data frame format 8/16 bits @ref spi_dff.
@param[in] lsbfirst Unsigned int32. Frame format lsb/msb first @ref spi_lsbfirst.
@returns int. Error code.
*/
int spi_init_master(u32 spi, u32 br, u32 cpol, u32 cpha, u32 dff, u32 lsbfirst)
{
u32 reg32 = SPI_CR1(spi);
@ -82,28 +152,66 @@ int spi_init_master(u32 spi, u32 br, u32 cpol, u32 cpha, u32 dff, u32 lsbfirst)
}
/* TODO: Error handling? */
/*-----------------------------------------------------------------------------*/
/** @brief SPI Enable.
The SPI peripheral is enabled.
@todo Error handling?
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_SPE; /* Enable SPI. */
}
/* TODO: Error handling? */
/*-----------------------------------------------------------------------------*/
/** @brief SPI Disable.
The SPI peripheral is disabled.
@todo Follow procedure from section 23.3.8 in the TRM.
(possibly create a "clean disable" function separately)
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable(u32 spi)
{
u32 reg32;
/* TODO: Follow procedure from section 23.3.8 in the TRM. */
reg32 = SPI_CR1(spi);
reg32 &= ~(SPI_CR1_SPE); /* Disable SPI. */
SPI_CR1(spi) = reg32;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Data Write.
Data is written to the SPI interface.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
@param[in] data Unsigned int16. 8 or 16 bit data to be written.
*/
void spi_write(u32 spi, u16 data)
{
/* Write data (8 or 16 bits, depending on DFF) into DR. */
SPI_DR(spi) = data;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Data Write with Blocking.
Data is written to the SPI interface after the previous write transfer has finished.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
@param[in] data Unsigned int16. 8 or 16 bit data to be written.
*/
void spi_send(u32 spi, u16 data)
{
/* Wait for transfer finished. */
@ -114,6 +222,15 @@ void spi_send(u32 spi, u16 data)
SPI_DR(spi) = data;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Data Read.
Data is read from the SPI interface after the incoming transfer has finished.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
@returns data Unsigned int16. 8 or 16 bit data.
*/
u16 spi_read(u32 spi)
{
/* Wait for transfer finished. */
@ -124,6 +241,17 @@ u16 spi_read(u32 spi)
return SPI_DR(spi);
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Data Write and Read Exchange.
Data is written to the SPI interface, then a read is done after the incoming transfer
has finished.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
@param[in] data Unsigned int16. 8 or 16 bit data to be written.
@returns data Unsigned int16. 8 or 16 bit data.
*/
u16 spi_xfer(u32 spi, u16 data)
{
spi_write(spi, data);
@ -136,98 +264,251 @@ u16 spi_xfer(u32 spi, u16 data)
return SPI_DR(spi);
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set Bidirectional Simplex Mode.
The SPI peripheral is set for bidirectional transfers in two-wire simplex mode
(using a clock wire and a bidirectional data wire).
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_bidirectional_mode(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_BIDIMODE;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set Unidirectional Mode.
The SPI peripheral is set for unidirectional transfers. This is used in full duplex
mode or when the SPI is placed in two-wire simplex mode that uses a clock wire and a
unidirectional data wire.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_unidirectional_mode(u32 spi)
{
SPI_CR1(spi) &= ~SPI_CR1_BIDIMODE;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set Bidirectional Simplex Receive Only Mode.
The SPI peripheral is set for bidirectional transfers in two-wire simplex mode
(using a clock wire and a bidirectional data wire), and is placed in a receive state.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_bidirectional_receive_only_mode(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_BIDIMODE;
SPI_CR1(spi) &= ~SPI_CR1_BIDIOE;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set Bidirectional Simplex Receive Only Mode.
The SPI peripheral is set for bidirectional transfers in two-wire simplex mode
(using a clock wire and a bidirectional data wire), and is placed in a transmit state.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_bidirectional_transmit_only_mode(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_BIDIMODE;
SPI_CR1(spi) |= SPI_CR1_BIDIOE;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Enable the CRC.
The SPI peripheral is set to use a CRC field for transmit and receive.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_crc(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_CRCEN;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Disable the CRC.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_crc(u32 spi)
{
SPI_CR1(spi) &= ~SPI_CR1_CRCEN;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Next Transmit is a Data Word
The next transmission to take place is a data word from the transmit buffer.
This must be called before transmission to distinguish between sending
of a data or CRC word.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_next_tx_from_buffer(u32 spi)
{
SPI_CR1(spi) &= ~SPI_CR1_CRCNEXT;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Next Transmit is a CRC Word
The next transmission to take place is a crc word from the hardware crc unit.
This must be called before transmission to distinguish between sending
of a data or CRC word.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_next_tx_from_crc(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_CRCNEXT;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set Data Frame Format to 8 bits
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_dff_8bit(u32 spi)
{
SPI_CR1(spi) &= ~SPI_CR1_DFF;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set Data Frame Format to 16 bits
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_dff_16bit(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_DFF;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set Full Duplex (3-wire) Mode
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_full_duplex_mode(u32 spi)
{
SPI_CR1(spi) &= ~SPI_CR1_RXONLY;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set Receive Only Mode for Simplex (2-wire) Unidirectional Transfers
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_receive_only_mode(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_RXONLY;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Enable Slave Management by Hardware
In slave mode the NSS hardware input is used as a select enable for the slave.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_software_slave_management(u32 spi)
{
SPI_CR1(spi) &= ~SPI_CR1_SSM;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Enable Slave Management by Software
In slave mode the NSS hardware input is replaced by an internal software
enable/disable of the slave (@ref spi_set_nss_high).
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_software_slave_management(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_SSM;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set the Software NSS Signal High
In slave mode, and only when software slave management is used, this replaces
the NSS signal with a slave select enable signal.
@todo these should perhaps be combined with an SSM enable as it is meaningless otherwise
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_nss_high(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_SSI;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set the Software NSS Signal Low
In slave mode, and only when software slave management is used, this replaces
the NSS signal with a slave select disable signal.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_nss_low(u32 spi)
{
SPI_CR1(spi) &= ~SPI_CR1_SSI;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set to Send LSB First
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_send_lsb_first(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_LSBFIRST;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set to Send MSB First
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_send_msb_first(u32 spi)
{
SPI_CR1(spi) &= ~SPI_CR1_LSBFIRST;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set the Baudrate Prescaler
@todo Why is this specification different to the spi_init_master baudrate values?
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
@param[in] baudrate Unsigned int8. Baudrate prescale value @ref spi_br_pre.
*/
void spi_set_baudrate_prescaler(u32 spi, u8 baudrate)
{
u32 reg32;
@ -240,92 +521,217 @@ void spi_set_baudrate_prescaler(u32 spi, u8 baudrate)
SPI_CR1(spi) = reg32;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set to Master Mode
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_master_mode(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_MSTR;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set to Slave Mode
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_slave_mode(u32 spi)
{
SPI_CR1(spi) &= ~SPI_CR1_MSTR;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set the Clock Polarity to High when Idle
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_clock_polarity_1(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_CPOL;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set the Clock Polarity to Low when Idle
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_clock_polarity_0(u32 spi)
{
SPI_CR1(spi) &= ~SPI_CR1_CPOL;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set the Clock Phase to Capture on Trailing Edge
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_clock_phase_1(u32 spi)
{
SPI_CR1(spi) |= SPI_CR1_CPHA;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set the Clock Phase to Capture on Leading Edge
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_set_clock_phase_0(u32 spi)
{
SPI_CR1(spi) &= ~SPI_CR1_CPHA;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Enable the Transmit Buffer Empty Interrupt
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_tx_buffer_empty_interrupt(u32 spi)
{
SPI_CR2(spi) |= SPI_CR2_TXEIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Disable the Transmit Buffer Empty Interrupt
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_tx_buffer_empty_interrupt(u32 spi)
{
SPI_CR2(spi) &= ~SPI_CR2_TXEIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Enable the Receive Buffer Ready Interrupt
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_rx_buffer_not_empty_interrupt(u32 spi)
{
SPI_CR2(spi) |= SPI_CR2_RXNEIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Disable the Receive Buffer Ready Interrupt
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_rx_buffer_not_empty_interrupt(u32 spi)
{
SPI_CR2(spi) &= ~SPI_CR2_RXNEIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Enable the Error Interrupt
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_error_interrupt(u32 spi)
{
SPI_CR2(spi) |= SPI_CR2_ERRIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Disable the Error Interrupt
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_error_interrupt(u32 spi)
{
SPI_CR2(spi) &= ~SPI_CR2_ERRIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set the NSS Pin as an Output
Normally used in master mode to allows the master to place all devices on the
SPI bus into slave mode. Multimaster mode is not possible.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_ss_output(u32 spi)
{
SPI_CR2(spi) |= SPI_CR2_SSOE;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Set the NSS Pin as an Input
In master mode this allows the master to sense the presence of other masters. If
NSS is then pulled low the master is placed into slave mode. In slave mode NSS
becomes a slave enable.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_ss_output(u32 spi)
{
SPI_CR2(spi) &= ~SPI_CR2_SSOE;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Enable Transmit Transfers via DMA
This allows transmissions to proceed unattended using DMA to move data to the
transmit buffer as it becomes available. The DMA channels provided for each
SPI peripheral are given in the Technical Manual DMA section.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_tx_dma(u32 spi)
{
SPI_CR2(spi) |= SPI_CR2_TXDMAEN;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Disable Transmit Transfers via DMA
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_tx_dma(u32 spi)
{
SPI_CR2(spi) &= ~SPI_CR2_TXDMAEN;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Enable Receive Transfers via DMA
This allows received data streams to proceed unattended using DMA to move data from
the receive buffer as data becomes available. The DMA channels provided for each
SPI peripheral are given in the Technical Manual DMA section.
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_enable_rx_dma(u32 spi)
{
SPI_CR2(spi) |= SPI_CR2_RXDMAEN;
}
/*-----------------------------------------------------------------------------*/
/** @brief SPI Disable Receive Transfers via DMA
@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base.
*/
void spi_disable_rx_dma(u32 spi)
{
SPI_CR2(spi) &= ~SPI_CR2_RXDMAEN;
}
/**@}*/

View File

@ -1,3 +1,22 @@
/** @defgroup STM32F1xx_usart_file USART
@ingroup STM32F_files
@brief <b>libopencm3 STM32F USART</b>
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
@date 30 August 2012
This library supports the USART/UART in the STM32F series
of ARM Cortex Microcontrollers by ST Microelectronics.
Devices can have up to 3 USARTs and 2 UARTs.
LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
@ -17,6 +36,8 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/stm32/usart.h>
#if defined(STM32F1)
@ -29,6 +50,20 @@
# error "stm32 family not defined."
#endif
/*-----------------------------------------------------------------------------*/
/** @brief USART Set Baudrate.
The baud rate is computed from the APB high-speed prescaler clock (for USART1)
or the APB low-speed prescaler clock (for other USARTs). These values must
be correctly set before calling this function (refer to the rcc_clock_setup-*
functions in RCC).
@todo Add support for USART6 and oversampling in F2/F4
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
@param[in] baud unsigned 32 bit. Baud rate specified in Hz.
*/
void usart_set_baudrate(u32 usart, u32 baud)
{
u32 clock = rcc_ppre1_frequency;
@ -59,6 +94,16 @@ void usart_set_baudrate(u32 usart, u32 baud)
USART_BRR(usart) = ((2 * clock) + baud) / (2 * baud);
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Set Word Length.
The word length is set to 8 or 9 bits. Note that the last bit will be a parity bit
if parity is enabled, in which case the data length will be 7 or 8 bits respectively.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
@param[in] bits unsigned 32 bit. Word length in bits 8 or 9.
*/
void usart_set_databits(u32 usart, u32 bits)
{
if (bits == 8)
@ -67,6 +112,15 @@ void usart_set_databits(u32 usart, u32 bits)
USART_CR1(usart) |= USART_CR1_M; /* 9 data bits */
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Set Stop Bit(s).
The stop bits are specified as 0.5, 1, 1.5 or 2.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
@param[in] stopbits unsigned 32 bit. Stop bits @ref usart_cr2_stopbits.
*/
void usart_set_stopbits(u32 usart, u32 stopbits)
{
u32 reg32;
@ -76,6 +130,15 @@ void usart_set_stopbits(u32 usart, u32 stopbits)
USART_CR2(usart) = reg32;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Set Parity.
The parity bit can be selected as none, even or odd.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
@param[in] parity unsigned 32 bit. Parity @ref usart_cr1_parity.
*/
void usart_set_parity(u32 usart, u32 parity)
{
u32 reg32;
@ -85,6 +148,15 @@ void usart_set_parity(u32 usart, u32 parity)
USART_CR1(usart) = reg32;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Set Rx/Tx Mode.
The mode can be selected as Rx only, Tx only or Rx+Tx.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
@param[in] mode unsigned 32 bit. Mode @ref usart_cr1_mode.
*/
void usart_set_mode(u32 usart, u32 mode)
{
u32 reg32;
@ -94,6 +166,15 @@ void usart_set_mode(u32 usart, u32 mode)
USART_CR1(usart) = reg32;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Set Hardware Flow Control.
The flow control bit can be selected as none, RTS, CTS or RTS+CTS.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
@param[in] flowcontrol unsigned 32 bit. Flowcontrol @ref usart_cr3_flowcontrol.
*/
void usart_set_flow_control(u32 usart, u32 flowcontrol)
{
u32 reg32;
@ -103,46 +184,112 @@ void usart_set_flow_control(u32 usart, u32 flowcontrol)
USART_CR3(usart) = reg32;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Enable.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
*/
void usart_enable(u32 usart)
{
USART_CR1(usart) |= USART_CR1_UE;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Disable.
At the end of the current frame, the USART is disabled to reduce power.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
*/
void usart_disable(u32 usart)
{
USART_CR1(usart) &= ~USART_CR1_UE;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Send a Data Word.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
@param[in] data unsigned 16 bit.
*/
void usart_send(u32 usart, u16 data)
{
/* Send data. */
USART_DR(usart) = (data & USART_DR_MASK);
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Read a Received Data Word.
If parity is enabled the MSB (bit 7 or 8 depending on the word length) is the parity bit.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
@returns unsigned 16 bit data word.
*/
u16 usart_recv(u32 usart)
{
/* Receive data. */
return USART_DR(usart) & USART_DR_MASK;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Wait for Transmit Data Buffer Empty
Blocks until the transmit data buffer becomes empty and is ready to accept the
next data word.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
*/
void usart_wait_send_ready(u32 usart)
{
/* Wait until the data has been transferred into the shift register. */
while ((USART_SR(usart) & USART_SR_TXE) == 0);
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Wait for Received Data Available
Blocks until the receive data buffer holds a valid received data word.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
*/
void usart_wait_recv_ready(u32 usart)
{
/* Wait until the data is ready to be received. */
while ((USART_SR(usart) & USART_SR_RXNE) == 0);
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Send Data Word with Blocking
Blocks until the transmit data buffer becomes empty then writes the next data word
for transmission.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
@param[in] data unsigned 16 bit.
*/
void usart_send_blocking(u32 usart, u16 data)
{
usart_wait_send_ready(usart);
usart_send(usart, data);
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Read a Received Data Word with Blocking.
Wait until a data word has been received then return the word.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
@returns unsigned 16 bit data word.
*/
u16 usart_recv_blocking(u32 usart)
{
usart_wait_recv_ready(usart);
@ -150,22 +297,148 @@ u16 usart_recv_blocking(u32 usart)
return usart_recv(usart);
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Receiver DMA Enable.
DMA is available on:
@li USART1 Rx DMA1 channel 5.
@li USART2 Rx DMA1 channel 6.
@li USART3 Rx DMA1 channel 3.
@li UART4 Rx DMA2 channel 3.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
*/
void usart_enable_rx_dma(u32 usart)
{
USART_CR3(usart) |= USART_CR3_DMAR;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Receiver DMA Disable.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
*/
void usart_disable_rx_dma(u32 usart)
{
USART_CR3(usart) &= ~USART_CR3_DMAR;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Transmitter DMA Enable.
DMA is available on:
@li USART1 Tx DMA1 channel 4.
@li USART2 Tx DMA1 channel 7.
@li USART3 Tx DMA1 channel 2.
@li UART4 Tx DMA2 channel 5.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
*/
void usart_enable_tx_dma(u32 usart)
{
USART_CR3(usart) |= USART_CR3_DMAT;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Transmitter DMA Disable.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
*/
void usart_disable_tx_dma(u32 usart)
{
USART_CR3(usart) &= ~USART_CR3_DMAT;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Receiver Interrupt Enable.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
*/
void usart_enable_rx_interrupt(u32 usart)
{
USART_CR1(usart) |= USART_CR1_RXNEIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Receiver Interrupt Disable.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
*/
void usart_disable_rx_interrupt(u32 usart)
{
USART_CR1(usart) &= ~USART_CR1_RXNEIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Transmitter Interrupt Enable.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
*/
void usart_enable_tx_interrupt(u32 usart)
{
USART_CR1(usart) |= USART_CR1_TXEIE;
}
/*-----------------------------------------------------------------------------*/
/** @brief USART Transmitter Interrupt Disable.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
*/
void usart_disable_tx_interrupt(u32 usart)
{
USART_CR1(usart) &= ~USART_CR1_TXEIE;
}
/*---------------------------------------------------------------------------*/
/** @brief USART Read a Status Flag.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
@param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags.
@returns boolean: flag set.
*/
bool usart_get_flag(u32 usart, u32 flag)
{
return ((USART_SR(usart) & flag) != 0);
}
/*---------------------------------------------------------------------------*/
/** @brief USART Return Interrupt Source.
Returns true if the specified interrupt flag (IDLE, RXNE, TC, TXE or OE) was
set and the interrupt was enabled. If the specified flag is not an interrupt
flag, the function returns false.
@todo These are the most important interrupts likely to be used. Others
relating to LIN break, and error conditions in multibuffer communication, need
to be added for completeness.
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
@param[in] flag Unsigned int32. Status register flag @ref usart_sr_flags.
@returns boolean: flag and interrupt enable both set.
*/
bool usart_get_interrupt_source(u32 usart, u32 flag)
{
u32 flag_set = (USART_SR(usart) & flag);
/* IDLE, RXNE, TC, TXE interrupts */
if ((flag >= USART_SR_IDLE) && (flag <= USART_SR_TXE))
return ((flag_set & USART_CR1(usart)) != 0);
/* Overrun error */
else if (flag == USART_SR_ORE)
return (flag_set && (USART_CR3(usart) & USART_CR3_CTSIE));
return (false);
}
/**@}*/