Initial commit.

This commit is contained in:
Piotr Esden-Tempski
2013-04-19 17:19:32 -07:00
commit 9d5526f773
324 changed files with 22845 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
##
## 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>
static 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);
}
static 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);
}
static 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
}
static 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,28 @@
##
## 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>
static 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);
}
static 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);
}
static 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);
}
static 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);
}
static 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,28 @@
##
## 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/cm3/nvic.h>
volatile u16 temperature = 0;
static 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);
}
static 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);
}
static 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);
}
static 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);
}
static 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);
}
static 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,28 @@
##
## 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/cm3/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 */
static 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);
}
static 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 );
}
static 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);
}
static 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);
}
static 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
}
static 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

@@ -0,0 +1,28 @@
##
## 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
# 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,9 @@
------------------------------------------------------------------------------
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.
The terminal settings for the receiving device/PC are 115200 8n1.

View File

@@ -0,0 +1,161 @@
/*
* 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 Ken Sarkies <ksarkies@internode.on.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/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>
static 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);
}
static 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);
}
static 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 conversion. */
adc_disable_scan_mode(ADC1);
adc_set_single_conversion_mode(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_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);
adc_calibration(ADC1);
}
static 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; 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 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');
/* Select the channel we want to convert. 16=temperature_sensor. */
channel_array[0] = 16;
adc_set_regular_sequence(ADC1, 1, channel_array);
/* Continously convert and poll the temperature ADC. */
while (1) {
/*
* Start the conversion directly (ie without a trigger).
*/
adc_start_conversion_direct(ADC1);
/* Wait for end of conversion. */
while (!(adc_eoc(ADC1)));
temperature = adc_read_regular(ADC1);
/*
* 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,28 @@
##
## 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 = can
# 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,4 @@
This test sets up the CAN interface on Lisa/M and transmits 8 bites every
100ms. The first byte is being incremented in each cycle. The demo also
receives messages and is displaing the first 4 bits of the first byte on the
board LEDs.

View File

@@ -0,0 +1,237 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Copyright (C) 2010-2011 Piotr Esden-Tempski <piotr@esden.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/flash.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/cm3/systick.h>
#include <libopencm3/stm32/can.h>
struct can_tx_msg {
u32 std_id;
u32 ext_id;
u8 ide;
u8 rtr;
u8 dlc;
u8 data[8];
};
struct can_rx_msg {
u32 std_id;
u32 ext_id;
u8 ide;
u8 rtr;
u8 dlc;
u8 data[8];
u8 fmi;
};
struct can_tx_msg can_tx_msg;
struct can_rx_msg can_rx_msg;
static void gpio_setup(void)
{
/* Enable Alternate Function clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN);
/* Enable GPIOA clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
/* Enable GPIOB clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
/* Enable GPIOC clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
/* Preconfigure LEDs. */
gpio_set(GPIOA, GPIO8); /* LED1 off */
gpio_set(GPIOB, GPIO4); /* LED2 off */
gpio_set(GPIOC, GPIO2); /* LED3 off */
gpio_set(GPIOC, GPIO5); /* LED4 off */
gpio_set(GPIOC, GPIO15); /* LED5 off */
/* Configure LED GPIOOs. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO4);
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO2);
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO5);
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
/* Configure PB4 as GPIO. */
AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_JNTRST;
}
static void systick_setup(void)
{
/* 72MHz / 8 => 9000000 counts per second */
systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8);
/* 9000000/9000 = 1000 overflows per second - every 1ms one interrupt */
/* SysTick interrupt every N clock pulses: set reload to N-1 */
systick_set_reload(8999);
systick_interrupt_enable();
/* Start counting. */
systick_counter_enable();
}
static void can_setup(void)
{
/* Enable peripheral clocks. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_CAN1EN);
AFIO_MAPR |= AFIO_MAPR_CAN1_REMAP_PORTB;
/* Configure CAN pin: RX (input pull-up). */
gpio_set_mode(GPIO_BANK_CAN1_PB_RX, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_PULL_UPDOWN, GPIO_CAN1_PB_RX);
gpio_set(GPIO_BANK_CAN1_PB_RX, GPIO_CAN1_PB_RX);
/* Configure CAN pin: TX. */
gpio_set_mode(GPIO_BANK_CAN1_PB_TX, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_CAN1_PB_TX);
/* NVIC setup. */
nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
nvic_set_priority(NVIC_USB_LP_CAN_RX0_IRQ, 1);
/* Reset CAN. */
can_reset(CAN1);
/* CAN cell init. */
if (can_init(CAN1,
false, /* TTCM: Time triggered comm mode? */
true, /* ABOM: Automatic bus-off management? */
false, /* AWUM: Automatic wakeup mode? */
false, /* NART: No automatic retransmission? */
false, /* RFLM: Receive FIFO locked mode? */
false, /* TXFP: Transmit FIFO priority? */
CAN_BTR_SJW_1TQ,
CAN_BTR_TS1_3TQ,
CAN_BTR_TS2_4TQ,
12,
false,
false)) /* BRP+1: Baud rate prescaler */
{
gpio_set(GPIOA, GPIO8); /* LED1 off */
gpio_set(GPIOB, GPIO4); /* LED2 off */
gpio_set(GPIOC, GPIO2); /* LED3 off */
gpio_clear(GPIOC, GPIO5); /* LED4 on */
gpio_set(GPIOC, GPIO15); /* LED5 off */
/* Die because we failed to initialize. */
while (1)
__asm__("nop");
}
/* CAN filter 0 init. */
can_filter_id_mask_32bit_init(CAN1,
0, /* Filter ID */
0, /* CAN ID */
0, /* CAN ID mask */
0, /* FIFO assignment (here: FIFO0) */
true); /* Enable the filter. */
/* Enable CAN RX interrupt. */
can_enable_irq(CAN1, CAN_IER_FMPIE0);
}
void sys_tick_handler(void)
{
static int temp32 = 0;
static u8 data[8] = {0, 1, 2, 0, 0, 0, 0, 0};
/* We call this handler every 1ms so every 100ms = 0.1s
* resulting in 100Hz message rate.
*/
if (++temp32 != 100)
return;
temp32 = 0;
/* Transmit CAN frame. */
data[0]++;
if (can_transmit(CAN1,
0, /* (EX/ST)ID: CAN ID */
false, /* IDE: CAN ID extended? */
false, /* RTR: Request transmit? */
8, /* DLC: Data length */
data) == -1)
{
gpio_set(GPIOA, GPIO8); /* LED1 off */
gpio_set(GPIOB, GPIO4); /* LED2 off */
gpio_set(GPIOC, GPIO2); /* LED3 off */
gpio_set(GPIOC, GPIO5); /* LED4 off */
gpio_clear(GPIOC, GPIO15); /* LED5 on */
}
}
void usb_lp_can_rx0_isr(void)
{
u32 id, fmi;
bool ext, rtr;
u8 length, data[8];
can_receive(CAN1, 0, false, &id, &ext, &rtr, &fmi, &length, data);
if (data[0] & 1)
gpio_clear(GPIOA, GPIO8);
else
gpio_set(GPIOA, GPIO8);
if (data[0] & 2)
gpio_clear(GPIOB, GPIO4);
else
gpio_set(GPIOB, GPIO4);
if (data[0] & 4)
gpio_clear(GPIOC, GPIO2);
else
gpio_set(GPIOC, GPIO2);
if (data[0] & 8)
gpio_clear(GPIOC, GPIO5);
else
gpio_set(GPIOC, GPIO5);
can_fifo_release(CAN1, 0);
}
int main(void)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz();
gpio_setup();
can_setup();
systick_setup();
while (1); /* Halt. */
return 0;
}

View File

@@ -0,0 +1,232 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/flash.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/cm3/systick.h>
#include <libopencm3/stm32/can.h>
struct can_tx_msg {
u32 std_id;
u32 ext_id;
u8 ide;
u8 rtr;
u8 dlc;
u8 data[8];
};
struct can_rx_msg {
u32 std_id;
u32 ext_id;
u8 ide;
u8 rtr;
u8 dlc;
u8 data[8];
u8 fmi;
};
struct can_tx_msg can_tx_msg;
struct can_rx_msg can_rx_msg;
void gpio_setup(void)
{
/* Enable Alternate Function clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN);
/* Enable GPIOA clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
/* Enable GPIOB clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
/* Enable GPIOC clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
/* Preconfigure LEDs. */
gpio_set(GPIOA, GPIO8); /* LED0 off */
gpio_set(GPIOB, GPIO4); /* LED1 off */
gpio_set(GPIOC, GPIO15); /* LED2 off */
gpio_set(GPIOC, GPIO2); /* LED3 off */
gpio_set(GPIOC, GPIO5); /* LED4 off */
/* Configure LED GPIOOs. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO4);
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO2);
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO5);
/* Configure PB4 as GPIO. */
AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_JNTRST;
}
void systick_setup(void)
{
/* 72MHz / 8 => 9000000 counts per second */
systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8);
/* 9000000/9000 = 1000 overflows per second - every 1ms one interrupt */
systick_set_reload(9000);
systick_interrupt_enable();
/* Start counting. */
systick_counter_enable();
}
void can_setup(void)
{
/* Enable peripheral clocks. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_CANEN);
AFIO_MAPR = AFIO_MAPR_CAN1_REMAP_PORTB;
/* Configure CAN pin: RX (input pull-up). */
gpio_set_mode(GPIOB, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_PULL_UPDOWN, GPIO_CAN1_PB_RX);
gpio_set(GPIOB, GPIO_CAN1_PB_RX);
/* Configure CAN pin: TX. */
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_CAN1_PB_TX);
/* NVIC setup. */
nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
nvic_set_priority(NVIC_USB_LP_CAN_RX0_IRQ, 1);
/* Reset CAN. */
can_reset(CAN1);
/* CAN cell init. */
if (can_init(CAN1,
false, /* TTCM: Time triggered comm mode? */
true, /* ABOM: Automatic bus-off management? */
false, /* AWUM: Automatic wakeup mode? */
false, /* NART: No automatic retransmission? */
false, /* RFLM: Receive FIFO locked mode? */
false, /* TXFP: Transmit FIFO priority? */
CAN_BTR_SJW_1TQ,
CAN_BTR_TS1_3TQ,
CAN_BTR_TS2_4TQ,
12)) /* BRP+1: Baud rate prescaler */
{
gpio_set(GPIOA, GPIO8); /* LED0 off */
gpio_set(GPIOB, GPIO4); /* LED1 off */
gpio_set(GPIOC, GPIO15); /* LED2 off */
gpio_clear(GPIOC, GPIO2); /* LED3 on */
gpio_set(GPIOC, GPIO5); /* LED4 off */
/* Die because we failed to initialize. */
while (1)
__asm__("nop");
}
/* CAN filter 0 init. */
can_filter_id_mask_32bit_init(CAN1,
0, /* Filter ID */
0, /* CAN ID */
0, /* CAN ID mask */
0, /* FIFO assignment (here: FIFO0) */
true); /* Enable the filter. */
/* Enable CAN RX interrupt. */
can_enable_irq(CAN1, CAN_IER_FMPIE0);
}
void sys_tick_handler(void)
{
static int temp32 = 0;
static u8 data[8] = {0, 1, 2, 0, 0, 0, 0, 0};
/* We call this handler every 1ms so 1000ms = 1s on/off. */
if (++temp32 != 1000)
return;
temp32 = 0;
/* Transmit CAN frame. */
data[0]++;
if (can_transmit(CAN1,
0, /* (EX/ST)ID: CAN ID */
false, /* IDE: CAN ID extended? */
false, /* RTR: Request transmit? */
8, /* DLC: Data length */
data) == -1)
{
gpio_set(GPIOA, GPIO8); /* LED0 off */
gpio_set(GPIOB, GPIO4); /* LED1 off */
gpio_set(GPIOC, GPIO15); /* LED2 off */
gpio_set(GPIOC, GPIO2); /* LED3 off */
gpio_clear(GPIOC, GPIO5); /* LED4 on */
}
}
void usb_lp_can_rx0_isr(void)
{
u32 id, fmi;
bool ext, rtr;
u8 length, data[8];
can_receive(CAN1, 0, false, &id, &ext, &rtr, &fmi, &length, data);
if (data[0] & 1)
gpio_clear(GPIOA, GPIO8);
else
gpio_set(GPIOA, GPIO8);
if (data[0] & 2)
gpio_clear(GPIOB, GPIO4);
else
gpio_set(GPIOB, GPIO4);
if (data[0] & 4)
gpio_clear(GPIOC, GPIO15);
else
gpio_set(GPIOC, GPIO15);
if (data[0] & 8)
gpio_clear(GPIOC, GPIO2);
else
gpio_set(GPIOC, GPIO2);
can_fifo_release(CAN1, 0);
}
int main(void)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz();
gpio_setup();
can_setup();
systick_setup();
while (1); /* Halt. */
return 0;
}

View File

@@ -0,0 +1,28 @@
##
## 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 = fancyblink
# 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,148 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2011 Piotr Esden-Tempski <piotr@esden.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/gpio.h>
/* Set STM32 to 72 MHz. */
static void clock_setup(void)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz();
/* Enable GPIOA, GPIOB, GPIOC, and AFIO clocks. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN);
}
static void gpio_setup(void)
{
/* LED1 */
/* Set GPIO8 (in GPIO port A) to 'output push-pull'. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
/* LED2 */
/* Set GPIO15 (in GPIO port C) to 'output push-pull'. */
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
/* JTAG_TRST */
/* Set GPIO4 (in GPIO port B) to 'output push-pull'. */
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO4);
AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_JNTRST;
/* ADC4 */
/* Set GPIO5 (in GPIO port C) to 'output push-pull'. */
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO5);
/* ADC6 */
/* Set GPIO2 (in GPIO port C) to 'output push-pull'. */
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO2);
/* Preconfigure the LEDs. */
gpio_set(GPIOA, GPIO8);
gpio_set(GPIOC, GPIO15);
gpio_set(GPIOB, GPIO4);
gpio_set(GPIOC, GPIO5);
gpio_set(GPIOC, GPIO2);
}
static void led_set(int id, int on)
{
if (on) {
switch (id) {
case 0:
gpio_clear(GPIOA, GPIO8); /* LED1 On */
break;
case 1:
gpio_clear(GPIOB, GPIO4); /* JTAG_TRST On */
break;
case 2:
gpio_clear(GPIOC, GPIO2); /* ADC6 On */
break;
case 3:
gpio_clear(GPIOC, GPIO5); /* ADC4 On */
break;
case 4:
gpio_clear(GPIOC, GPIO15); /* LED2 On */
break;
}
} else {
switch (id) {
case 0:
gpio_set(GPIOA, GPIO8); /* LED1 On */
break;
case 1:
gpio_set(GPIOB, GPIO4); /* JTAG_TRST On */
break;
case 2:
gpio_set(GPIOC, GPIO2); /* ADC6 On */
break;
case 3:
gpio_set(GPIOC, GPIO5); /* ADC4 On */
break;
case 4:
gpio_set(GPIOC, GPIO15); /* LED2 On */
break;
}
}
}
static void led_advance(void)
{
static int state = 0;
if (state < 5) {
led_set(state, 1);
} else if (state < 10) {
led_set(state - 5, 0);
} else if (state < 15) {
led_set(14 - state, 1);
} else if (state < 20) {
led_set(19 - state, 0);
}
state++;
if(state == 20) state = 0;
}
int main(void)
{
int i;
clock_setup();
gpio_setup();
/* Blink the LEDs (PC13 and PB4) on the board. */
while (1) {
led_advance();
for (i = 0; i < 800000; i++) /* Wait a bit. */
__asm__("nop");
}
return 0;
}

View File

@@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for Lisa-M (STM32F103RBT6, 128K flash, 20K RAM). */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

View File

@@ -0,0 +1,28 @@
##
## 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 = spi
# 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,14 @@
------------------------------------------------------------------------------
README
------------------------------------------------------------------------------
This example program demonstrates simple SPI transceive on Lisa/M 2.0 board
(http://paparazzi.enac.fr/wiki/Lisa/M_v20 for details).
The terminal settings for the receiving device/PC are 9600 8n1.
The example expects a loopback connection between the MISO and MOSI pins on
SPI1.
A counter increments and the spi sends this byte out, after which it should
come back in to the rx buffer, and the result is reported on the uart.

View File

@@ -0,0 +1,164 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2013 Stephen Dwyer <scdwyer@ualberta.ca>
*
* 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/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/dma.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/spi.h>
#include <stdio.h>
#include <errno.h>
int _write(int file, char *ptr, int len);
static void clock_setup(void)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz();
/* Enable GPIOA, GPIOB, GPIOC clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR,
RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN |
RCC_APB2ENR_IOPCEN);
/* Enable clocks for GPIO port A (for GPIO_USART2_TX) and USART2. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN |
RCC_APB2ENR_AFIOEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
/* Enable SPI1 Periph and gpio clocks */
rcc_peripheral_enable_clock(&RCC_APB2ENR,
RCC_APB2ENR_SPI1EN);
}
static void spi_setup(void) {
/* Configure GPIOs: SS=PA4, SCK=PA5, MISO=PA6 and MOSI=PA7 */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO4 |
GPIO5 |
GPIO7 );
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT,
GPIO6);
/* Reset SPI, SPI_CR1 register cleared, SPI is disabled */
spi_reset(SPI1);
/* Set up SPI in Master mode with:
* Clock baud rate: 1/64 of peripheral clock frequency
* Clock polarity: Idle High
* Clock phase: Data valid on 2nd clock pulse
* Data frame format: 8-bit
* Frame format: MSB First
*/
spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_64, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST);
/*
* Set NSS management to software.
*
* Note:
* Setting nss high is very important, even if we are controlling the GPIO
* ourselves this bit needs to be at least set to 1, otherwise the spi
* peripheral will not send any data out.
*/
spi_enable_software_slave_management(SPI1);
spi_set_nss_high(SPI1);
/* Enable SPI1 periph. */
spi_enable(SPI1);
}
static void usart_setup(void)
{
/* Setup GPIO pin GPIO_USART2_TX and GPIO_USART2_RX. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_FLOAT, GPIO_USART2_RX);
/* Setup UART parameters. */
usart_set_baudrate(USART2, 9600);
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);
}
int _write(int file, char *ptr, int len)
{
int i;
if (file == 1) {
for (i = 0; i < len; i++)
usart_send_blocking(USART2, ptr[i]);
return i;
}
errno = EIO;
return -1;
}
static void gpio_setup(void)
{
/* Set GPIO8 (in GPIO port A) to 'output push-pull'. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
}
int main(void)
{
int counter = 0;
u16 rx_value = 0x42;
clock_setup();
gpio_setup();
usart_setup();
spi_setup();
/* Blink the LED (PA8) on the board with every transmitted byte. */
while (1) {
/* LED on/off */
gpio_toggle(GPIOA, GPIO8);
/* printf the value that SPI should send */
printf("Counter: %i SPI Sent Byte: %i", counter, (uint8_t) counter);
/* blocking send of the byte out SPI1 */
spi_send(SPI1, (uint8_t) counter);
/* Read the byte that just came in (use a loopback between MISO and MOSI
* to get the same byte back)
*/
rx_value = spi_read(SPI1);
/* printf the byte just received */
printf(" SPI Received Byte: %i\r\n", rx_value);
counter++;
}
return 0;
}

View File

@@ -0,0 +1,28 @@
##
## 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 = spi_dma
# 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,17 @@
------------------------------------------------------------------------------
README
------------------------------------------------------------------------------
This example program demonstrates SPI transceive with DMA on Lisa/M 2.0 board
(http://paparazzi.enac.fr/wiki/Lisa/M_v20 for details).
The terminal settings for the receiving device/PC are 9600 8n1.
The example expects a loopback connection between the MISO and MOSI pins on
SPI1. The DRDY and SS pins (on the Lisa/M v2.0 SPI1 connector) are used as
GPIO to time the tx and rx ISRs, respectively. Use a scope or logic analyzer.
The tx length is incremented, followed by the rx length, after which both tx
and rx lengths are decremented together. The case where rx is longer than tx
requires greater complexity to ensure all rx data is clocked in. See the adv
example for this.

View File

@@ -0,0 +1,439 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2013 Stephen Dwyer <scdwyer@ualberta.ca>
*
* 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/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/dma.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/spi.h>
#include <stdio.h>
#include <errno.h>
#ifndef USE_16BIT_TRANSFERS
#define USE_16BIT_TRANSFERS 1
#endif
/* This is for the counter state flag */
typedef enum {
TX_UP_RX_HOLD = 0,
TX_HOLD_RX_UP,
TX_DOWN_RX_DOWN
} cnt_state;
/* This is a global spi state flag */
typedef enum {
NONE = 0,
ONE,
DONE
} trans_status;
volatile trans_status transceive_status;
int _write(int file, char *ptr, int len);
static void clock_setup(void)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz();
/* Enable GPIOA, GPIOB, GPIOC clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR,
RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN |
RCC_APB2ENR_IOPCEN);
/* Enable clocks for GPIO port A (for GPIO_USART2_TX) and USART2. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN |
RCC_APB2ENR_AFIOEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
/* Enable SPI1 Periph and gpio clocks */
rcc_peripheral_enable_clock(&RCC_APB2ENR,
RCC_APB2ENR_SPI1EN);
/* Enable DMA1 clock */
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_DMA1EN);
}
static void spi_setup(void) {
/* Configure GPIOs: SS=PA4, SCK=PA5, MISO=PA6 and MOSI=PA7
* For now ignore the SS pin so we can use it to time the ISRs
*/
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, /* GPIO4 | */
GPIO5 |
GPIO7 );
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT,
GPIO6);
/* Reset SPI, SPI_CR1 register cleared, SPI is disabled */
spi_reset(SPI1);
/* Explicitly disable I2S in favour of SPI operation */
SPI1_I2SCFGR = 0;
/* Set up SPI in Master mode with:
* Clock baud rate: 1/64 of peripheral clock frequency
* Clock polarity: Idle High
* Clock phase: Data valid on 2nd clock pulse
* Data frame format: 8-bit or 16-bit
* Frame format: MSB First
*/
#if USE_16BIT_TRANSFERS
spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_64, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_16BIT, SPI_CR1_MSBFIRST);
#else
spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_64, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST);
#endif
/*
* Set NSS management to software.
*
* Note:
* Setting nss high is very important, even if we are controlling the GPIO
* ourselves this bit needs to be at least set to 1, otherwise the spi
* peripheral will not send any data out.
*/
spi_enable_software_slave_management(SPI1);
spi_set_nss_high(SPI1);
/* Enable SPI1 periph. */
spi_enable(SPI1);
}
static void dma_int_enable(void) {
/* SPI1 RX on DMA1 Channel 2 */
nvic_set_priority(NVIC_DMA1_CHANNEL2_IRQ, 0);
nvic_enable_irq(NVIC_DMA1_CHANNEL2_IRQ);
/* SPI1 TX on DMA1 Channel 3 */
nvic_set_priority(NVIC_DMA1_CHANNEL3_IRQ, 0);
nvic_enable_irq(NVIC_DMA1_CHANNEL3_IRQ);
}
/* Not used in this example
static void dma_int_disable(void) {
nvic_disable_irq(NVIC_DMA1_CHANNEL2_IRQ);
nvic_disable_irq(NVIC_DMA1_CHANNEL3_IRQ);
}
*/
static void dma_setup(void)
{
dma_int_enable();
}
#if USE_16BIT_TRANSFERS
static int spi_dma_transceive(u16 *tx_buf, int tx_len, u16 *rx_buf, int rx_len)
#else
static int spi_dma_transceive(u8 *tx_buf, int tx_len, u8 *rx_buf, int rx_len)
#endif
{
/* Check for 0 length in both tx and rx */
if ((rx_len < 1) && (tx_len < 1)) {
/* return -1 as error */
return -1;
}
/* Reset DMA channels*/
dma_channel_reset(DMA1, DMA_CHANNEL2);
dma_channel_reset(DMA1, DMA_CHANNEL3);
/* Reset SPI data and status registers.
* Here we assume that the SPI peripheral is NOT
* busy any longer, i.e. the last activity was verified
* complete elsewhere in the program.
*/
volatile u8 temp_data __attribute__ ((unused));
while (SPI_SR(SPI1) & (SPI_SR_RXNE | SPI_SR_OVR)) {
temp_data = SPI_DR(SPI1);
}
/* Reset status flag appropriately (both 0 case caught above) */
transceive_status = NONE;
if (rx_len < 1) {
transceive_status = ONE;
}
if (tx_len < 1) {
transceive_status = ONE;
}
/* Set up rx dma, note it has higher priority to avoid overrun */
if (rx_len > 0) {
dma_set_peripheral_address(DMA1, DMA_CHANNEL2, (u32)&SPI1_DR);
dma_set_memory_address(DMA1, DMA_CHANNEL2, (u32)rx_buf);
dma_set_number_of_data(DMA1, DMA_CHANNEL2, rx_len);
dma_set_read_from_peripheral(DMA1, DMA_CHANNEL2);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL2);
#if USE_16BIT_TRANSFERS
dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_16BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_16BIT);
#else
dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_8BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_8BIT);
#endif
dma_set_priority(DMA1, DMA_CHANNEL2, DMA_CCR_PL_VERY_HIGH);
}
/* Set up tx dma */
if (tx_len > 0) {
dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (u32)&SPI1_DR);
dma_set_memory_address(DMA1, DMA_CHANNEL3, (u32)tx_buf);
dma_set_number_of_data(DMA1, DMA_CHANNEL3, tx_len);
dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL3);
#if USE_16BIT_TRANSFERS
dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_16BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_16BIT);
#else
dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
#endif
dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
}
/* Enable dma transfer complete interrupts */
if (rx_len > 0) {
dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL2);
}
if (tx_len > 0) {
dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL3);
}
/* Activate dma channels */
if (rx_len > 0) {
dma_enable_channel(DMA1, DMA_CHANNEL2);
}
if (tx_len > 0) {
dma_enable_channel(DMA1, DMA_CHANNEL3);
}
/* Enable the spi transfer via dma
* This will immediately start the transmission,
* after which when the receive is complete, the
* receive dma will activate
*/
if (rx_len > 0) {
spi_enable_rx_dma(SPI1);
}
if (tx_len > 0) {
spi_enable_tx_dma(SPI1);
}
return 0;
}
/* SPI receive completed with DMA */
void dma1_channel2_isr(void)
{
gpio_set(GPIOA,GPIO4);
if ((DMA1_ISR &DMA_ISR_TCIF2) != 0) {
DMA1_IFCR |= DMA_IFCR_CTCIF2;
}
dma_disable_transfer_complete_interrupt(DMA1, DMA_CHANNEL2);
spi_disable_rx_dma(SPI1);
dma_disable_channel(DMA1, DMA_CHANNEL2);
/* Increment the status to indicate one of the transfers is complete */
transceive_status++;
gpio_clear(GPIOA,GPIO4);
}
/* SPI transmit completed with DMA */
void dma1_channel3_isr(void)
{
gpio_set(GPIOB,GPIO1);
if ((DMA1_ISR &DMA_ISR_TCIF3) != 0) {
DMA1_IFCR |= DMA_IFCR_CTCIF3;
}
dma_disable_transfer_complete_interrupt(DMA1, DMA_CHANNEL3);
spi_disable_tx_dma(SPI1);
dma_disable_channel(DMA1, DMA_CHANNEL3);
/* Increment the status to indicate one of the transfers is complete */
transceive_status++;
gpio_clear(GPIOB,GPIO1);
}
static void usart_setup(void)
{
/* Setup GPIO pin GPIO_USART2_TX and GPIO_USART2_RX. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_FLOAT, GPIO_USART2_RX);
/* Setup UART parameters. */
usart_set_baudrate(USART2, 9600);
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);
}
int _write(int file, char *ptr, int len)
{
int i;
if (file == 1) {
for (i = 0; i < len; i++)
usart_send_blocking(USART2, ptr[i]);
return i;
}
errno = EIO;
return -1;
}
static void gpio_setup(void)
{
/* Set GPIO8 (in GPIO port A) to 'output push-pull'. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
/* Use the extra pins to signal when the ISRs are running */
/* First, SPI1 - SS pin on Lisa/M v2.0 */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO4);
/* Then, SPI1 - DRDY pin on Lisa/M v2.0 */
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO1);
}
int main(void)
{
int counter_tx = 0;
int counter_rx = 0;
cnt_state counter_state = TX_UP_RX_HOLD;
int i = 0;
/* Transmit and Receive packets, set transmit to index and receive to known unused value to aid in debugging */
#if USE_16BIT_TRANSFERS
u16 tx_packet[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
u16 rx_packet[16] = {0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42};
#else
u8 tx_packet[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
u8 rx_packet[16] = {0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42};
#endif
transceive_status = DONE;
clock_setup();
gpio_setup();
usart_setup();
spi_setup();
dma_setup();
#if USE_16BIT_TRANSFERS
printf("SPI with DMA Transfer Test using 16bit option (Use loopback)\r\n\r\n");
#else
printf("SPI with DMA Transfer Test using 8bit option (Use loopback)\r\n\r\n");
#endif
/* Blink the LED (PA8) on the board with every transmitted byte. */
while (1) {
/* LED on/off */
gpio_toggle(GPIOA, GPIO8);
/* Print what is going to be sent on the SPI bus */
printf("Sending packet (tx len %02i):", counter_tx);
for (i = 0; i < counter_tx; i++)
{
printf(" 0x%02x,", tx_packet[i]);
}
printf("\r\n");
/* Start a transceive */
if (spi_dma_transceive(tx_packet, counter_tx, rx_packet, counter_rx)) {
printf("Attempted 0 length tx and rx packets\r\n");
}
/* Wait until transceive complete.
* This checks the state flag as well as follows the
* procedure on the Reference Manual (RM0008 rev 14
* Section 25.3.9 page 692, the note.)
*/
while (transceive_status != DONE)
;
while (!(SPI_SR(SPI1) & SPI_SR_TXE))
;
while (SPI_SR(SPI1) & SPI_SR_BSY)
;
/* Print what was received on the SPI bus */
printf("Received Packet (rx len %02i):", counter_rx);
for (i = 0; i < 16; i++) {
printf(" 0x%02x,", rx_packet[i]);
}
printf("\r\n\r\n");
/* Update counters
* If we use the loopback method, we can not
* have a rx length longer than the tx length.
* Testing rx lengths longer than tx lengths
* requires an actual slave device that will
* return data.
*/
switch (counter_state) {
case TX_UP_RX_HOLD:
counter_tx++;
if (counter_tx > 15) {
counter_state = TX_HOLD_RX_UP;
}
break;
case TX_HOLD_RX_UP:
counter_rx++;
if (counter_rx > 15) {
counter_state = TX_DOWN_RX_DOWN;
}
break;
case TX_DOWN_RX_DOWN:
counter_tx--;
counter_rx--;
if (counter_tx < 1) {
counter_state = TX_UP_RX_HOLD;
}
break;
default:
;
}
/* Reset receive buffer for consistency */
for (i = 0; i < 16; i++) {
rx_packet[i] = 0x42;
}
}
return 0;
}

View File

@@ -0,0 +1,28 @@
##
## 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 = spi_dma_adv
# 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,17 @@
------------------------------------------------------------------------------
README
------------------------------------------------------------------------------
This example program demonstrates SPI transceive with DMA on Lisa/M 2.0 board
(http://paparazzi.enac.fr/wiki/Lisa/M_v20 for details).
The terminal settings for the receiving device/PC are 9600 8n1.
The example expects a loopback connection between the MISO and MOSI pins on
SPI1. The DRDY and SS pins (on the Lisa/M v2.0 SPI1 connector) are used as
GPIO to time the tx and rx ISRs, respectively. Use a scope or logic analyzer.
The tx length is incremented, followed by the rx length, after which the tx is
decremented, then the rx is decremented. This is repeated in a loop. In this
example, rx lengths longer than tx lengths are handled by using two dma transmits
one after the other, handled inside the tx dma ISR.

View File

@@ -0,0 +1,506 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2013 Stephen Dwyer <scdwyer@ualberta.ca>
*
* 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/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/dma.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/spi.h>
#include <stdio.h>
#include <errno.h>
#ifndef USE_16BIT_TRANSFERS
#define USE_16BIT_TRANSFERS 0
#endif
/* This is for the counter state flag */
typedef enum {
TX_UP_RX_HOLD = 0,
TX_HOLD_RX_UP,
TX_DOWN_RX_HOLD,
TX_HOLD_RX_DOWN
} cnt_state;
/* This is a global spi state flag */
typedef enum {
NONE = 0,
ONE,
DONE
} trans_status;
volatile trans_status transceive_status;
/* Global for dummy tx dma transfer */
int rx_buf_remainder = 0;
#if USE_16BIT_TRANSFERS
u16 dummy_tx_buf = 0xdd;
#else
u8 dummy_tx_buf = 0xdd;
#endif
int _write(int file, char *ptr, int len);
static void clock_setup(void)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz();
/* Enable GPIOA, GPIOB, GPIOC clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR,
RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN |
RCC_APB2ENR_IOPCEN);
/* Enable clocks for GPIO port A (for GPIO_USART2_TX) and USART2. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN |
RCC_APB2ENR_AFIOEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
/* Enable SPI1 Periph and gpio clocks */
rcc_peripheral_enable_clock(&RCC_APB2ENR,
RCC_APB2ENR_SPI1EN);
/* Enable DMA1 clock */
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_DMA1EN);
}
static void spi_setup(void) {
/* Configure GPIOs: SS=PA4, SCK=PA5, MISO=PA6 and MOSI=PA7
* For now ignore the SS pin so we can use it to time the ISRs
*/
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, /* GPIO4 | */
GPIO5 |
GPIO7 );
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT,
GPIO6);
/* Reset SPI, SPI_CR1 register cleared, SPI is disabled */
spi_reset(SPI1);
/* Explicitly disable I2S in favour of SPI operation */
SPI1_I2SCFGR = 0;
/* Set up SPI in Master mode with:
* Clock baud rate: 1/64 of peripheral clock frequency
* Clock polarity: Idle High
* Clock phase: Data valid on 2nd clock pulse
* Data frame format: 8-bit or 16-bit
* Frame format: MSB First
*/
#if USE_16BIT_TRANSFERS
spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_64, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_16BIT, SPI_CR1_MSBFIRST);
#else
spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_64, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST);
#endif
/*
* Set NSS management to software.
*
* Note:
* Setting nss high is very important, even if we are controlling the GPIO
* ourselves this bit needs to be at least set to 1, otherwise the spi
* peripheral will not send any data out.
*/
spi_enable_software_slave_management(SPI1);
spi_set_nss_high(SPI1);
/* Enable SPI1 periph. */
spi_enable(SPI1);
}
static void dma_int_enable(void) {
/* SPI1 RX on DMA1 Channel 2 */
nvic_set_priority(NVIC_DMA1_CHANNEL2_IRQ, 0);
nvic_enable_irq(NVIC_DMA1_CHANNEL2_IRQ);
/* SPI1 TX on DMA1 Channel 3 */
nvic_set_priority(NVIC_DMA1_CHANNEL3_IRQ, 0);
nvic_enable_irq(NVIC_DMA1_CHANNEL3_IRQ);
}
/* Not used in this example
static void dma_int_disable(void) {
nvic_disable_irq(NVIC_DMA1_CHANNEL2_IRQ);
nvic_disable_irq(NVIC_DMA1_CHANNEL3_IRQ);
}
*/
static void dma_setup(void)
{
dma_int_enable();
}
#if USE_16BIT_TRANSFERS
static int spi_dma_transceive(u16 *tx_buf, int tx_len, u16 *rx_buf, int rx_len)
#else
static int spi_dma_transceive(u8 *tx_buf, int tx_len, u8 *rx_buf, int rx_len)
#endif
{
/* Check for 0 length in both tx and rx */
if ((rx_len < 1) && (tx_len < 1)) {
/* return -1 as error */
return -1;
}
/* Reset DMA channels*/
dma_channel_reset(DMA1, DMA_CHANNEL2);
dma_channel_reset(DMA1, DMA_CHANNEL3);
/* Reset SPI data and status registers.
* Here we assume that the SPI peripheral is NOT
* busy any longer, i.e. the last activity was verified
* complete elsewhere in the program.
*/
volatile u8 temp_data __attribute__ ((unused));
while (SPI_SR(SPI1) & (SPI_SR_RXNE | SPI_SR_OVR)) {
temp_data = SPI_DR(SPI1);
}
/* Reset status flag appropriately (both 0 case caught above) */
transceive_status = NONE;
if (rx_len < 1) {
transceive_status = ONE;
}
/* Determine tx length case to change behaviour
* If tx_len >= rx_len, then normal case, run both DMAs with normal settings
* If rx_len == 0, just don't run the rx DMA at all
* If tx_len == 0, use a dummy buf and set the tx dma to transfer the same
* amount as the rx_len, to ensure everything is clocked in
* If 0 < tx_len < rx_len, first do a normal case, then on the tx finished
* interrupt, set up a new dummyy buf tx dma transfer for the remaining
* required clock cycles (handled in tx dma complete interrupt)
*/
if ((tx_len > 0) && (tx_len < rx_len)) {
rx_buf_remainder = rx_len - tx_len;
}
/* Set up rx dma, note it has higher priority to avoid overrun */
if (rx_len > 0) {
dma_set_peripheral_address(DMA1, DMA_CHANNEL2, (u32)&SPI1_DR);
dma_set_memory_address(DMA1, DMA_CHANNEL2, (u32)rx_buf);
dma_set_number_of_data(DMA1, DMA_CHANNEL2, rx_len);
dma_set_read_from_peripheral(DMA1, DMA_CHANNEL2);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL2);
#if USE_16BIT_TRANSFERS
dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_16BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_16BIT);
#else
dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_8BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_8BIT);
#endif
dma_set_priority(DMA1, DMA_CHANNEL2, DMA_CCR_PL_VERY_HIGH);
}
/* Set up tx dma (must always run tx to get clock signal) */
if (tx_len > 0) {
/* Here we have a regular tx transfer */
dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (u32)&SPI1_DR);
dma_set_memory_address(DMA1, DMA_CHANNEL3, (u32)tx_buf);
dma_set_number_of_data(DMA1, DMA_CHANNEL3, tx_len);
dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL3);
#if USE_16BIT_TRANSFERS
dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_16BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_16BIT);
#else
dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
#endif
dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
} else {
/* Here we aren't transmitting any real data, use the dummy buffer
* and set the length to the rx_len to get all rx data in, while
* not incrementing the memory pointer
*/
dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (u32)&SPI1_DR);
dma_set_memory_address(DMA1, DMA_CHANNEL3, (u32)(&dummy_tx_buf)); // Change here
dma_set_number_of_data(DMA1, DMA_CHANNEL3, rx_len); // Change here
dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
dma_disable_memory_increment_mode(DMA1, DMA_CHANNEL3); // Change here
#if USE_16BIT_TRANSFERS
dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_16BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_16BIT);
#else
dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
#endif
dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
}
/* Enable dma transfer complete interrupts */
if (rx_len > 0) {
dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL2);
}
dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL3);
/* Activate dma channels */
if (rx_len > 0) {
dma_enable_channel(DMA1, DMA_CHANNEL2);
}
dma_enable_channel(DMA1, DMA_CHANNEL3);
/* Enable the spi transfer via dma
* This will immediately start the transmission,
* after which when the receive is complete, the
* receive dma will activate
*/
if (rx_len > 0) {
spi_enable_rx_dma(SPI1);
}
spi_enable_tx_dma(SPI1);
return 0;
}
/* SPI receive completed with DMA */
void dma1_channel2_isr(void)
{
gpio_set(GPIOA,GPIO4);
if ((DMA1_ISR &DMA_ISR_TCIF2) != 0) {
DMA1_IFCR |= DMA_IFCR_CTCIF2;
}
dma_disable_transfer_complete_interrupt(DMA1, DMA_CHANNEL2);
spi_disable_rx_dma(SPI1);
dma_disable_channel(DMA1, DMA_CHANNEL2);
/* Increment the status to indicate one of the transfers is complete */
transceive_status++;
gpio_clear(GPIOA,GPIO4);
}
/* SPI transmit completed with DMA */
void dma1_channel3_isr(void)
{
gpio_set(GPIOB,GPIO1);
if ((DMA1_ISR &DMA_ISR_TCIF3) != 0) {
DMA1_IFCR |= DMA_IFCR_CTCIF3;
}
dma_disable_transfer_complete_interrupt(DMA1, DMA_CHANNEL3);
spi_disable_tx_dma(SPI1);
dma_disable_channel(DMA1, DMA_CHANNEL3);
/* If tx_len < rx_len, create a dummy transfer to clock in the remaining
* rx data
*/
if (rx_buf_remainder > 0) {
dma_channel_reset(DMA1, DMA_CHANNEL3);
dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (u32)&SPI1_DR);
dma_set_memory_address(DMA1, DMA_CHANNEL3, (u32)(&dummy_tx_buf)); // Change here
dma_set_number_of_data(DMA1, DMA_CHANNEL3, rx_buf_remainder); // Change here
dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
dma_disable_memory_increment_mode(DMA1, DMA_CHANNEL3); // Change here
#if USE_16BIT_TRANSFERS
dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_16BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_16BIT);
#else
dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
#endif
dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
rx_buf_remainder = 0; // Clear the buffer remainder to disable this section later
dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL3);
dma_enable_channel(DMA1, DMA_CHANNEL3);
spi_enable_tx_dma(SPI1);
} else {
/* Increment the status to indicate one of the transfers is complete */
transceive_status++;
}
gpio_clear(GPIOB,GPIO1);
}
static void usart_setup(void)
{
/* Setup GPIO pin GPIO_USART2_TX and GPIO_USART2_RX. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_FLOAT, GPIO_USART2_RX);
/* Setup UART parameters. */
usart_set_baudrate(USART2, 9600);
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);
}
int _write(int file, char *ptr, int len)
{
int i;
if (file == 1) {
for (i = 0; i < len; i++)
usart_send_blocking(USART2, ptr[i]);
return i;
}
errno = EIO;
return -1;
}
static void gpio_setup(void)
{
/* Set GPIO8 (in GPIO port A) to 'output push-pull'. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
/* Use the extra pins to signal when the ISRs are running */
/* First, SPI1 - SS pin on Lisa/M v2.0 */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO4);
/* Then, SPI1 - DRDY pin on Lisa/M v2.0 */
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO1);
}
int main(void)
{
int counter_tx = 0;
int counter_rx = 0;
cnt_state counter_state = TX_UP_RX_HOLD;
int i = 0;
/* Transmit and Receive packets, set transmit to index and receive to known unused value to aid in debugging */
#if USE_16BIT_TRANSFERS
u16 tx_packet[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
u16 rx_packet[16] = {0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42};
#else
u8 tx_packet[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
u8 rx_packet[16] = {0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42};
#endif
transceive_status = DONE;
clock_setup();
gpio_setup();
usart_setup();
spi_setup();
dma_setup();
printf("SPI with DMA Transfer Test (Use loopback)\r\n\r\n");
/* Blink the LED (PA8) on the board with every transmitted byte. */
while (1) {
/* LED on/off */
gpio_toggle(GPIOA, GPIO8);
/* Print what is going to be sent on the SPI bus */
printf("Sending packet (tx len %02i):", counter_tx);
for (i = 0; i < counter_tx; i++)
{
printf(" 0x%02x,", tx_packet[i]);
}
printf("\r\n");
/* Start a transceive */
if (spi_dma_transceive(tx_packet, counter_tx, rx_packet, counter_rx)) {
printf("Attempted 0 length tx and rx packets\r\n");
}
/* Wait until transceive complete.
* This checks the state flag as well as follows the
* procedure on the Reference Manual (RM0008 rev 14
* Section 25.3.9 page 692, the note.)
*/
while (transceive_status != DONE)
;
while (!(SPI_SR(SPI1) & SPI_SR_TXE))
;
while (SPI_SR(SPI1) & SPI_SR_BSY)
;
/* Print what was received on the SPI bus */
printf("Received Packet (rx len %02i):", counter_rx);
for (i = 0; i < 16; i++) {
printf(" 0x%02x,", rx_packet[i]);
}
printf("\r\n\r\n");
/* Update counters
* If we use the loopback method, we can not
* have a rx length longer than the tx length.
* Testing rx lengths longer than tx lengths
* requires an actual slave device that will
* return data.
*/
switch (counter_state) {
case TX_UP_RX_HOLD:
counter_tx++;
if (counter_tx > 15) {
counter_state = TX_HOLD_RX_UP;
}
break;
case TX_HOLD_RX_UP:
counter_rx++;
if (counter_rx > 15) {
counter_state = TX_DOWN_RX_HOLD;
}
break;
case TX_DOWN_RX_HOLD:
counter_tx--;
if (counter_tx < 1) {
counter_state = TX_HOLD_RX_DOWN;
}
break;
case TX_HOLD_RX_DOWN:
counter_rx--;
if (counter_rx < 1) {
counter_state = TX_UP_RX_HOLD;
}
break;
default:
;
}
/* Reset receive buffer for consistency */
for (i = 0; i < 16; i++) {
#if USE_16BIT_TRANSFERS
tx_packet[i] = (u16)i;
#else
tx_packet[i] = (u8)i;
#endif
rx_packet[i] = 0x42;
}
}
return 0;
}

View File

@@ -0,0 +1,28 @@
##
## 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 = usart
# 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 example program sends some characters on USART2 on Lisa/M 2.0 board
(see http://paparazzi.enac.fr/wiki/LisaM for details).
The terminal settings for the receiving device/PC are 38400 8n1.
The sending is done in a blocking way in the code, see the usart_irq example
for a more elaborate USART example.

View File

@@ -0,0 +1,86 @@
/*
* 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/>.
*/
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/usart.h>
static void clock_setup(void)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz();
/* Enable GPIOA, GPIOB, GPIOC clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR,
RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN |
RCC_APB2ENR_IOPCEN);
/* Enable clocks for GPIO port B (for GPIO_USART3_TX) and USART3. */
rcc_peripheral_enable_clock(&RCC_APB1ENR,
RCC_APB1ENR_USART2EN);
}
static void usart_setup(void)
{
/* Setup GPIO pin GPIO_USART2_TX. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
/* Setup UART 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);
}
static void gpio_setup(void)
{
/* Set GPIO8 (in GPIO port A) to 'output push-pull'. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
}
int main(void)
{
int i, j = 0, c = 0;
clock_setup();
gpio_setup();
usart_setup();
/* Blink the LED (PA8) on the board with every transmitted byte. */
while (1) {
gpio_toggle(GPIOA, GPIO8); /* LED on/off */
usart_send_blocking(USART2, c + '0'); /* USART2: Send byte. */
c = (c == 9) ? 0 : c + 1; /* Increment c. */
if ((j++ % 80) == 0) { /* Newline after line full. */
usart_send_blocking(USART2, '\r');
usart_send_blocking(USART2, '\n');
}
for (i = 0; i < 800000; i++) /* Wait a bit. */
__asm__("nop");
}
return 0;
}

View File

@@ -0,0 +1,28 @@
##
## 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 = usart_dma
# 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,199 @@
/*
* 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/>.
*/
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/f1/dma.h>
#include <libopencm3/cm3/nvic.h>
static void clock_setup(void)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz();
/* Enable GPIOA, GPIOB, GPIOC clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR,
RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN |
RCC_APB2ENR_IOPCEN);
/* Enable clocks for GPIO port B (for GPIO_USART3_TX) and USART3. */
rcc_peripheral_enable_clock(&RCC_APB1ENR,
RCC_APB1ENR_USART2EN);
/* Enable DMA1 clock */
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_DMA1EN);
}
static void usart_setup(void)
{
/* Setup GPIO pin GPIO_USART2_TX and GPIO_USART2_RX. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_FLOAT, GPIO_USART2_RX);
/* Setup UART 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_RX);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
/* Finally enable the USART. */
usart_enable(USART2);
nvic_set_priority(NVIC_DMA1_CHANNEL7_IRQ, 0);
nvic_enable_irq(NVIC_DMA1_CHANNEL7_IRQ);
nvic_set_priority(NVIC_DMA1_CHANNEL6_IRQ, 0);
nvic_enable_irq(NVIC_DMA1_CHANNEL6_IRQ);
}
static void dma_write(char *data, int size)
{
/*
* Using channel 7 for USART2_TX
*/
/* Reset DMA channel*/
dma_channel_reset(DMA1, DMA_CHANNEL7);
dma_set_peripheral_address(DMA1, DMA_CHANNEL7, (u32)&USART2_DR);
dma_set_memory_address(DMA1, DMA_CHANNEL7, (u32)data);
dma_set_number_of_data(DMA1, DMA_CHANNEL7, size);
dma_set_read_from_memory(DMA1, DMA_CHANNEL7);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL7);
dma_set_peripheral_size(DMA1, DMA_CHANNEL7, DMA_CCR_PSIZE_8BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL7, DMA_CCR_MSIZE_8BIT);
dma_set_priority(DMA1, DMA_CHANNEL7, DMA_CCR_PL_VERY_HIGH);
dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL7);
dma_enable_channel(DMA1, DMA_CHANNEL7);
usart_enable_tx_dma(USART2);
}
volatile int transfered = 0;
void dma1_channel7_isr(void)
{
if ((DMA1_ISR &DMA_ISR_TCIF7) != 0) {
DMA1_IFCR |= DMA_IFCR_CTCIF7;
transfered = 1;
}
dma_disable_transfer_complete_interrupt(DMA1, DMA_CHANNEL7);
usart_disable_tx_dma(USART2);
dma_disable_channel(DMA1, DMA_CHANNEL7);
}
static void dma_read(char *data, int size)
{
/*
* Using channel 6 for USART2_RX
*/
/* Reset DMA channel*/
dma_channel_reset(DMA1, DMA_CHANNEL6);
dma_set_peripheral_address(DMA1, DMA_CHANNEL6, (u32)&USART2_DR);
dma_set_memory_address(DMA1, DMA_CHANNEL6, (u32)data);
dma_set_number_of_data(DMA1, DMA_CHANNEL6, size);
dma_set_read_from_peripheral(DMA1, DMA_CHANNEL6);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL6);
dma_set_peripheral_size(DMA1, DMA_CHANNEL6, DMA_CCR_PSIZE_8BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL6, DMA_CCR_MSIZE_8BIT);
dma_set_priority(DMA1, DMA_CHANNEL6, DMA_CCR_PL_HIGH);
dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL6);
dma_enable_channel(DMA1, DMA_CHANNEL6);
usart_enable_rx_dma(USART2);
}
volatile int received = 0;
void dma1_channel6_isr(void)
{
if ((DMA1_ISR &DMA_ISR_TCIF6) != 0) {
DMA1_IFCR |= DMA_IFCR_CTCIF6;
received = 1;
}
dma_disable_transfer_complete_interrupt(DMA1, DMA_CHANNEL6);
usart_disable_rx_dma(USART2);
dma_disable_channel(DMA1, DMA_CHANNEL6);
}
static void gpio_setup(void)
{
/* Set GPIO8 (in GPIO port A) to 'output push-pull'. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
}
int main(void)
{
char tx[10] = "abcdefg\r\n";
int tx_len = 10;
char rx[7] = "bcdefg";
int rx_len = 6;
clock_setup();
gpio_setup();
usart_setup();
transfered = 0;
dma_write(tx, tx_len);
received = 0;
dma_read(rx, rx_len);
/* Blink the LED (PA8) on the board with every transmitted byte. */
while (1) {
gpio_toggle(GPIOA, GPIO8); /* LED on/off */
while ( transfered != 1) {
if (received == 1) {
tx[1] = rx[0];
tx[2] = rx[1];
tx[3] = rx[2];
tx[4] = rx[3];
tx[5] = rx[4];
tx[6] = rx[5];
received = 0;
dma_read(rx, rx_len);
}
}
tx[0]++;
if (tx[0] > 'z') tx[0] = 'a';
transfered = 0;
dma_write(tx, tx_len);
}
return 0;
}

View File

@@ -0,0 +1,86 @@
/*
* 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/>.
*/
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/usart.h>
void clock_setup(void)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz();
/* Enable GPIOA, GPIOB, GPIOC clock. */
rcc_peripheral_enable_clock(&RCC_APB2ENR,
RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN |
RCC_APB2ENR_IOPCEN);
/* Enable clocks for GPIO port B (for GPIO_USART3_TX) and USART3. */
rcc_peripheral_enable_clock(&RCC_APB1ENR,
RCC_APB1ENR_USART2EN);
}
void usart_setup(void)
{
/* Setup GPIO pin GPIO_USART2_TX. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
/* Setup UART 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)
{
/* Set GPIO8 (in GPIO port A) to 'output push-pull'. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
}
int main(void)
{
int i, j = 0, c = 0;
clock_setup();
gpio_setup();
usart_setup();
/* Blink the LED (PA8) on the board with every transmitted byte. */
while (1) {
gpio_toggle(GPIOA, GPIO8); /* LED on/off */
usart_send_blocking(USART2, c + '0'); /* USART2: Send byte. */
c = (c == 9) ? 0 : c + 1; /* Increment c. */
if ((j++ % 80) == 0) { /* Newline after line full. */
usart_send_blocking(USART2, '\r');
usart_send_blocking(USART2, '\n');
}
for (i = 0; i < 800000; i++) /* Wait a bit. */
__asm__("nop");
}
return 0;
}

View File

@@ -0,0 +1,28 @@
##
## 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 = usart_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,126 @@
/*
* 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/>.
*/
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/cm3/nvic.h>
static void clock_setup(void)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz();
/* Enable GPIOA clock (for LED GPIOs). */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN);
/* Enable clocks for GPIO port A (for GPIO_USART2_TX) and USART2. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN |
RCC_APB2ENR_AFIOEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
}
static void usart_setup(void)
{
/* Enable the USART2 interrupt. */
nvic_enable_irq(NVIC_USART2_IRQ);
/* Setup GPIO pin GPIO_USART2_TX on GPIO port A for transmit. */
gpio_set_mode(GPIO_BANK_USART2_TX, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
/* Setup GPIO pin GPIO_USART2_RX on GPIO port A for receive. */
gpio_set_mode(GPIO_BANK_USART2_RX, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_FLOAT, GPIO_USART2_RX);
/* Setup UART parameters. */
usart_set_baudrate(USART2, 230400);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
usart_set_mode(USART2, USART_MODE_TX_RX);
/* Enable USART2 Receive interrupt. */
USART_CR1(USART2) |= USART_CR1_RXNEIE;
/* Finally enable the USART. */
usart_enable(USART2);
}
static void gpio_setup(void)
{
gpio_set(GPIOA, GPIO8);
/* Setup GPIO8 (in GPIO port A) for LED use. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
gpio_set(GPIOC, GPIO15);
/* Setup GPIO15 (in GPIO port C) for LED use. */
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
}
void usart2_isr(void)
{
static u8 data = 'A';
/* Check if we were called because of RXNE. */
if (((USART_CR1(USART2) & USART_CR1_RXNEIE) != 0) &&
((USART_SR(USART2) & USART_SR_RXNE) != 0)) {
/* Indicate that we got data. */
gpio_toggle(GPIOA, GPIO8);
/* Retrieve the data from the peripheral. */
data = usart_recv(USART2);
/* Enable transmit interrupt so it sends back the data. */
USART_CR1(USART2) |= USART_CR1_TXEIE;
}
/* Check if we were called because of TXE. */
if (((USART_CR1(USART2) & USART_CR1_TXEIE) != 0) &&
((USART_SR(USART2) & USART_SR_TXE) != 0)) {
/* Indicate that we are sending out data. */
gpio_toggle(GPIOC, GPIO15);
/* Put data into the transmit register. */
usart_send(USART2, data);
/* Disable the TXE interrupt as we don't need it anymore. */
USART_CR1(USART2) &= ~USART_CR1_TXEIE;
}
}
int main(void)
{
clock_setup();
gpio_setup();
usart_setup();
/* Wait forever and do nothing. */
while (1)
__asm__("nop");
return 0;
}

View File

@@ -0,0 +1,28 @@
##
## 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 = usart_irq_printf
# 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,274 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>,
* Copyright (C) 2011 Piotr Esden-Tempski <piotr@esden.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/cm3/systick.h>
#include <stdio.h>
#include <errno.h>
/******************************************************************************
* Simple ringbuffer implementation from open-bldc's libgovernor that
* you can find at:
* https://github.com/open-bldc/open-bldc/tree/master/source/libgovernor
*****************************************************************************/
typedef s32 ring_size_t;
struct ring {
u8 *data;
ring_size_t size;
u32 begin;
u32 end;
};
#define RING_SIZE(RING) ((RING)->size - 1)
#define RING_DATA(RING) (RING)->data
#define RING_EMPTY(RING) ((RING)->begin == (RING)->end)
int _write(int file, char *ptr, int len);
static void ring_init(struct ring *ring, u8 *buf, ring_size_t size)
{
ring->data = buf;
ring->size = size;
ring->begin = 0;
ring->end = 0;
}
static s32 ring_write_ch(struct ring *ring, u8 ch)
{
if (((ring->end + 1) % ring->size) != ring->begin) {
ring->data[ring->end++] = ch;
ring->end %= ring->size;
return (u32)ch;
}
return -1;
}
static s32 ring_write(struct ring *ring, u8 *data, ring_size_t size)
{
s32 i;
for (i = 0; i < size; i++) {
if (ring_write_ch(ring, data[i]) < 0)
return -i;
}
return i;
}
static s32 ring_read_ch(struct ring *ring, u8 *ch)
{
s32 ret = -1;
if (ring->begin != ring->end) {
ret = ring->data[ring->begin++];
ring->begin %= ring->size;
if (ch)
*ch = ret;
}
return ret;
}
/* Not used!
static s32 ring_read(struct ring *ring, u8 *data, ring_size_t size)
{
s32 i;
for (i = 0; i < size; i++) {
if (ring_read_ch(ring, data + i) < 0)
return i;
}
return -i;
}
*/
/******************************************************************************
* The example implementation
*****************************************************************************/
#define BUFFER_SIZE 1024
struct ring output_ring;
u8 output_ring_buffer[BUFFER_SIZE];
static void clock_setup(void)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz();
/* Enable GPIOA clock (for LED GPIOs). */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
/* Enable clocks for GPIO port A (for GPIO_USART2_TX) and USART2. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN |
RCC_APB2ENR_AFIOEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
}
static void usart_setup(void)
{
/* Initialize output ring buffer. */
ring_init(&output_ring, output_ring_buffer, BUFFER_SIZE);
/* Enable the USART2 interrupt. */
nvic_enable_irq(NVIC_USART2_IRQ);
/* Setup GPIO pin GPIO_USART2_TX on GPIO port A for transmit. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
/* Setup GPIO pin GPIO_USART2_RX on GPIO port A for receive. */
gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_FLOAT, GPIO_USART2_RX);
/* Setup UART parameters. */
usart_set_baudrate(USART2, 230400);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
usart_set_mode(USART2, USART_MODE_TX_RX);
/* Enable USART2 Receive interrupt. */
USART_CR1(USART2) |= USART_CR1_RXNEIE;
/* Finally enable the USART. */
usart_enable(USART2);
}
static void gpio_setup(void)
{
gpio_set(GPIOA, GPIO8);
/* Setup GPIO8 (in GPIO port A) for LED use. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
}
void usart2_isr(void)
{
/* Check if we were called because of RXNE. */
if (((USART_CR1(USART2) & USART_CR1_RXNEIE) != 0) &&
((USART_SR(USART2) & USART_SR_RXNE) != 0)) {
/* Indicate that we got data. */
gpio_toggle(GPIOA, GPIO8);
/* Retrieve the data from the peripheral. */
ring_write_ch(&output_ring, usart_recv(USART2));
/* Enable transmit interrupt so it sends back the data. */
USART_CR1(USART2) |= USART_CR1_TXEIE;
}
/* Check if we were called because of TXE. */
if (((USART_CR1(USART2) & USART_CR1_TXEIE) != 0) &&
((USART_SR(USART2) & USART_SR_TXE) != 0)) {
s32 data;
data = ring_read_ch(&output_ring, NULL);
if (data == -1) {
/* Disable the TXE interrupt, it's no longer needed. */
USART_CR1(USART2) &= ~USART_CR1_TXEIE;
} else {
/* Put data into the transmit register. */
usart_send(USART2, data);
}
}
}
int _write(int file, char *ptr, int len)
{
int ret;
if (file == 1) {
ret = ring_write(&output_ring, (u8 *)ptr, len);
if (ret < 0)
ret = -ret;
USART_CR1(USART2) |= USART_CR1_TXEIE;
return ret;
}
errno = EIO;
return -1;
}
static void systick_setup(void)
{
/* 72MHz / 8 => 9000000 counts per second. */
systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8);
/* 9000000/9000 = 1000 overflows per second - every 1ms one interrupt */
/* SysTick interrupt every N clock pulses: set reload to N-1 */
systick_set_reload(8999);
systick_interrupt_enable();
/* Start counting. */
systick_counter_enable();
}
void sys_tick_handler(void)
{
static int counter = 0;
static float fcounter = 0.0;
static double dcounter = 0.0;
static u32 temp32 = 0;
temp32++;
/*
* We call this handler every 1ms so we are sending hello world
* every 10ms / 100Hz.
*/
if (temp32 == 10) {
printf("Hello World! %i %f %f\r\n", counter, fcounter,
dcounter);
counter++;
fcounter += 0.01;
dcounter += 0.01;
temp32 = 0;
}
}
int main(void)
{
clock_setup();
gpio_setup();
usart_setup();
systick_setup();
while (1)
__asm__("nop");
return 0;
}

View File

@@ -0,0 +1,28 @@
##
## 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 = usart_printf
# 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,108 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>,
* Copyright (C) 2011-2012 Piotr Esden-Tempski <piotr@esden.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/cm3/nvic.h>
#include <stdio.h>
#include <errno.h>
int _write(int file, char *ptr, int len);
static void clock_setup(void)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz();
/* Enable GPIOA clock (for LED GPIOs). */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
/* Enable clocks for GPIO port A (for GPIO_USART2_TX) and USART2. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN |
RCC_APB2ENR_AFIOEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
}
static void usart_setup(void)
{
/* Setup GPIO pin GPIO_USART2_RE_TX on GPIO port B 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, 230400);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
usart_set_mode(USART2, USART_MODE_TX);
/* Finally enable the USART. */
usart_enable(USART2);
}
static void gpio_setup(void)
{
gpio_set(GPIOA, GPIO8);
/* Setup GPIO8 (in GPIO port A) for LED use. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
}
int _write(int file, char *ptr, int len)
{
int i;
if (file == 1) {
for (i = 0; i < len; i++)
usart_send_blocking(USART2, ptr[i]);
return i;
}
errno = EIO;
return -1;
}
int main(void)
{
int counter = 0;
float fcounter = 0.0;
double dcounter = 0.0;
clock_setup();
gpio_setup();
usart_setup();
/*
* Write Hello World, an integer, float and double all over
* again while incrementing the numbers.
*/
while (1) {
gpio_toggle(GPIOA, GPIO8);
printf("Hello World! %i %f %f\r\n", counter, fcounter,
dcounter);
counter++;
fcounter += 0.01;
dcounter += 0.01;
}
return 0;
}