summaryrefslogtreecommitdiff
path: root/tests/uart-basic
diff options
context:
space:
mode:
Diffstat (limited to 'tests/uart-basic')
-rw-r--r--tests/uart-basic/Makefile.stm32f3-disco29
-rw-r--r--tests/uart-basic/Makefile.stm32f4-disco29
-rw-r--r--tests/uart-basic/main-stm32f3-disco.c136
-rw-r--r--tests/uart-basic/main-stm32f4-disco.c63
-rw-r--r--tests/uart-basic/uart-basic.c71
-rw-r--r--tests/uart-basic/uart-basic.h44
6 files changed, 372 insertions, 0 deletions
diff --git a/tests/uart-basic/Makefile.stm32f3-disco b/tests/uart-basic/Makefile.stm32f3-disco
new file mode 100644
index 0000000..2320af0
--- /dev/null
+++ b/tests/uart-basic/Makefile.stm32f3-disco
@@ -0,0 +1,29 @@
+# This is just a makefile.
+# Consider it released into the public domain, or, where not available,
+# available under your choice of BSD2clause, MIT, X11, ISC or Apache2 licenses
+# Karl Palsson <karlp@tweak.net.au>
+BOARD = stm32f3-disco
+PROJECT = uart-basic-$(BOARD)
+BUILD_DIR = bin-$(BOARD)
+
+SHARED_DIR = ../../shared
+
+CFILES = main-$(BOARD).c
+CFILES += uart-basic.c
+# No trace, we're using the uart explicitly here, deliberately.
+# Perhaps later we'll use trace differently, or with different files
+#CFILES += trace.c trace_stdio.c
+
+VPATH += $(SHARED_DIR)
+
+INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
+
+OPENCM3_DIR=../../libopencm3/
+
+### This section can go to an arch shared rules eventually...
+DEVICE=stm32f303vct6
+#OOCD_INTERFACE = stlink-v2
+#OOCD_TARGET = stm32f3x
+OOCD_FILE = ../../openocd/openocd.stm32f3-disco.cfg
+
+include ../../rules.mk
diff --git a/tests/uart-basic/Makefile.stm32f4-disco b/tests/uart-basic/Makefile.stm32f4-disco
new file mode 100644
index 0000000..40e2e1c
--- /dev/null
+++ b/tests/uart-basic/Makefile.stm32f4-disco
@@ -0,0 +1,29 @@
+# This is just a makefile.
+# Consider it released into the public domain, or, where not available,
+# available under your choice of BSD2clause, MIT, X11, ISC or Apache2 licenses
+# Karl Palsson <karlp@tweak.net.au>
+BOARD = stm32f4-disco
+PROJECT = uart-basic-$(BOARD)
+BUILD_DIR = bin-$(BOARD)
+
+SHARED_DIR = ../../shared
+
+CFILES = main-$(BOARD).c
+CFILES += uart-basic.c
+# No trace, we're using the uart explicitly here, deliberately.
+# Perhaps later we'll use trace differently, or with different files
+#CFILES += trace.c trace_stdio.c
+
+VPATH += $(SHARED_DIR)
+
+INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
+
+OPENCM3_DIR=../../libopencm3/
+
+### This section can go to an arch shared rules eventually...
+DEVICE=stm32f405xg
+#OOCD_INTERFACE = stlink-v2
+#OOCD_TARGET = stm32f4x
+OOCD_FILE = ../../openocd/openocd.stm32f4-disco.cfg
+
+include ../../rules.mk
diff --git a/tests/uart-basic/main-stm32f3-disco.c b/tests/uart-basic/main-stm32f3-disco.c
new file mode 100644
index 0000000..94c6937
--- /dev/null
+++ b/tests/uart-basic/main-stm32f3-disco.c
@@ -0,0 +1,136 @@
+/*
+ * Oct 2017 Karl Palsson <karlp@tweak.net.au>
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/stm32/flash.h>
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/usart.h>
+
+#include "uart-basic.h"
+
+/* f3 pll setup, based on l1/f4*/
+
+typedef struct {
+ uint8_t pll_mul;
+ uint8_t pll_div;
+ uint8_t pll_source;
+ uint32_t flash_config;
+ uint8_t hpre;
+ uint8_t ppre1;
+ uint8_t ppre2;
+ uint32_t apb1_frequency;
+ uint32_t apb2_frequency;
+ uint32_t ahb_frequency;
+} rcc_clock_scale_t;
+
+static void rcc_clock_setup_pll_f3_special(const rcc_clock_scale_t *clock)
+{
+ /* Turn on the appropriate source for the PLL */
+ // TODO, some f3's have extra bits here
+ enum rcc_osc my_osc;
+ if (clock->pll_source == RCC_CFGR_PLLSRC_HSE_PREDIV) {
+ my_osc = RCC_HSE;
+ } else {
+ my_osc = RCC_HSI;
+ }
+ rcc_osc_on(my_osc);
+ while (!rcc_is_osc_ready(my_osc));
+
+ /* Configure flash settings. */
+ flash_set_ws(clock->flash_config);
+
+ /*
+ * Set prescalers for AHB, ADC, ABP1, ABP2.
+ * Do this before touching the PLL (TODO: why?).
+ */
+ rcc_set_hpre(clock->hpre);
+ rcc_set_ppre1(clock->ppre1);
+ rcc_set_ppre2(clock->ppre2);
+
+ rcc_osc_off(RCC_PLL);
+ while (rcc_is_osc_ready(RCC_PLL));
+ rcc_set_pll_source(clock->pll_source);
+ rcc_set_pll_multiplier(clock->pll_mul);
+ // TODO - iff pll_div != 0, then maybe we're on a target that
+ // has the dividers?
+
+ /* Enable PLL oscillator and wait for it to stabilize. */
+ rcc_osc_on(RCC_PLL);
+ while (!rcc_is_osc_ready(RCC_PLL));
+
+ /* Select PLL as SYSCLK source. */
+ rcc_set_sysclk_source(RCC_CFGR_SW_PLL);
+ rcc_wait_for_sysclk_status(RCC_PLL);
+
+ /* Set the peripheral clock frequencies used. */
+ rcc_ahb_frequency = clock->ahb_frequency;
+ rcc_apb1_frequency = clock->apb1_frequency;
+ rcc_apb2_frequency = clock->apb2_frequency;
+}
+
+static void setup_clocks(void)
+{
+ rcc_clock_scale_t clock_full_hse8mhz ={
+ .pll_mul = RCC_CFGR_PLLMUL_PLL_IN_CLK_X9,
+ .pll_source = RCC_CFGR_PLLSRC_HSE_PREDIV,
+ .hpre = RCC_CFGR_HPRE_DIV_NONE,
+ .ppre1 = RCC_CFGR_PPRE1_DIV_2,
+ .ppre2 = RCC_CFGR_PPRE2_DIV_NONE,
+ .flash_config = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_2WS,
+ .apb1_frequency = 36000000,
+ .apb2_frequency = 72000000,
+ .ahb_frequency = 72000000,
+ };
+
+ rcc_clock_setup_pll_f3_special(&clock_full_hse8mhz);
+}
+
+void usart2_exti26_isr(void)
+{
+ ub_irq_handler();
+}
+
+int main(void)
+{
+ int i;
+ int j = 0;
+ setup_clocks();
+ /* Board led */
+ rcc_periph_clock_enable(RCC_GPIOE);
+ gpio_mode_setup(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO8);
+ gpio_set(GPIOE, GPIO8);
+
+ /* board init for uart2 on pa2/3 */
+ rcc_periph_clock_enable(RCC_GPIOA);
+ gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2|GPIO3);
+ /* usart is AF7 */
+ gpio_set_af(GPIOA, GPIO_AF7, GPIO2|GPIO3);
+
+ struct ub_hw ub = {
+ .uart = USART2,
+ .uart_nvic = NVIC_USART2_EXTI26_IRQ,
+ .uart_rcc = RCC_USART2,
+ };
+ ub_init(&ub);
+ printf("hi guys!\n");
+
+ while (1) {
+ gpio_toggle(GPIOE, GPIO8);
+
+ for (i = 0; i < 0x100000; i++) { /* Wait a bit. */
+ __asm__("NOP");
+ }
+ ub_task();
+ gpio_toggle(GPIOE, GPIO8);
+ for (i = 0; i < 0x100000; i++) { /* Wait a bit. */
+ __asm__("NOP");
+ }
+ }
+
+ return 0;
+}
diff --git a/tests/uart-basic/main-stm32f4-disco.c b/tests/uart-basic/main-stm32f4-disco.c
new file mode 100644
index 0000000..86d9b4a
--- /dev/null
+++ b/tests/uart-basic/main-stm32f4-disco.c
@@ -0,0 +1,63 @@
+/*
+ * Oct 2017 Karl Palsson <karlp@tweak.net.au>
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/usart.h>
+
+#include "uart-basic.h"
+
+#define LED_DISCO_GREEN_PORT GPIOD
+#define LED_DISCO_GREEN_PIN GPIO12
+
+void usart2_isr(void)
+{
+ ub_irq_handler();
+}
+
+static void board_init(void) {
+ rcc_periph_clock_enable(RCC_GPIOA);
+ gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2|GPIO3);
+ /* usart is AF7 */
+ gpio_set_af(GPIOA, GPIO_AF7, GPIO2|GPIO3);
+}
+
+int main(void)
+{
+ int i;
+ int j = 0;
+ rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
+ rcc_periph_clock_enable(RCC_GPIOD);
+ board_init();
+ struct ub_hw ub = {
+ .uart = USART2,
+ .uart_nvic = NVIC_USART2_IRQ,
+ .uart_rcc = RCC_USART2,
+ };
+ ub_init(&ub);
+ printf("hi guys!\n");
+ /* green led for ticking */
+ gpio_mode_setup(LED_DISCO_GREEN_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,
+ LED_DISCO_GREEN_PIN);
+
+
+ while (1) {
+ gpio_toggle(LED_DISCO_GREEN_PORT, LED_DISCO_GREEN_PIN);
+
+ for (i = 0; i < 0x800000; i++) { /* Wait a bit. */
+ __asm__("NOP");
+ }
+ ub_task();
+ gpio_toggle(LED_DISCO_GREEN_PORT, LED_DISCO_GREEN_PIN);
+ for (i = 0; i < 0x800000; i++) { /* Wait a bit. */
+ __asm__("NOP");
+ }
+ }
+
+ return 0;
+}
diff --git a/tests/uart-basic/uart-basic.c b/tests/uart-basic/uart-basic.c
new file mode 100644
index 0000000..4dae0e1
--- /dev/null
+++ b/tests/uart-basic/uart-basic.c
@@ -0,0 +1,71 @@
+/*
+ * Karl Palsson <karlp@tweak.net.au> Oct 2017
+ * Considered to be available under your choice of:
+ * BSD2 clause, Apache2, MIT, X11 or ISC licenses
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/usart.h>
+#include "uart-basic.h"
+
+/* prototype to make linking happy */
+int _write(int file, char *ptr, int len);
+
+static struct ub_hw *ub;
+static uint8_t last_rxb;
+
+/* Implement _write for newlib to use printf */
+int _write(int file, char *ptr, int len)
+{
+ int i;
+
+ if (file == STDOUT_FILENO || file == STDERR_FILENO) {
+ for (i = 0; i < len; i++) {
+ if (ptr[i] == '\n') {
+ usart_send_blocking(ub->uart, '\r');
+ }
+ usart_send_blocking(ub->uart, ptr[i]);
+ }
+ return i;
+ }
+ errno = EIO;
+ return -1;
+}
+
+void ub_init(struct ub_hw *ub_input)
+{
+ ub = ub_input;
+ rcc_periph_clock_enable(ub->uart_rcc);
+
+ usart_set_baudrate(ub->uart, 115200);
+ usart_set_databits(ub->uart, 9);
+ usart_set_stopbits(ub->uart, USART_STOPBITS_1);
+ usart_set_mode(ub->uart, USART_MODE_TX_RX);
+ usart_set_parity(ub->uart, USART_PARITY_EVEN);
+ usart_set_flow_control(ub->uart, USART_FLOWCONTROL_NONE);
+
+ usart_enable_rx_interrupt(ub->uart);
+ nvic_enable_irq(ub->uart_nvic);
+ usart_enable(ub->uart);
+}
+
+void ub_task(void)
+{
+ if (last_rxb) {
+ printf("Last rx char was: <%c>\n", last_rxb);
+ last_rxb = 0;
+ } else {
+ printf("enter a character!\n");
+ }
+}
+
+void ub_irq_handler(void)
+{
+ if (usart_get_flag(ub->uart, USART_SR_RXNE)) {
+ last_rxb = usart_recv(ub->uart);
+ }
+}
diff --git a/tests/uart-basic/uart-basic.h b/tests/uart-basic/uart-basic.h
new file mode 100644
index 0000000..8e3b8f6
--- /dev/null
+++ b/tests/uart-basic/uart-basic.h
@@ -0,0 +1,44 @@
+/*
+ * Karl Palsson <karlp@tweak.net.au> Oct 2017
+ * Considered to be available under your choice of:
+ * BSD2 clause, Apache2, MIT, X11 or ISC licenses
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <libopencm3/stm32/usart.h>
+
+struct ub_hw {
+ /** usart itself, eg USART2 */
+ uint32_t uart;
+ /** RCC_xxx flag for this usart, eg RCC_USART2 */
+ uint32_t uart_rcc;
+ /** eg NVIC_USART2_IRQ */
+ uint32_t uart_nvic;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initialise the uart itself.
+ * gpios are required to have been already configured as needed
+ * @param ub
+ */
+void ub_init(struct ub_hw *ub);
+
+/**
+ * Call this, it will "do stuff"
+ */
+void ub_task(void);
+
+/**
+ * Call this from your board irq handler, it will "do the right thing"
+ */
+void ub_irq_handler(void);
+
+#ifdef __cplusplus
+}
+#endif