summaryrefslogtreecommitdiff
path: root/ucoo
diff options
context:
space:
mode:
authorNicolas Schodet2015-08-14 17:09:27 +0200
committerNicolas Schodet2019-10-07 00:44:50 +0200
commit6e72fb26efbb45f1244d95d33d459566a8af57fe (patch)
treed9cc9834e18bee80fc21075df3de348ba933c254 /ucoo
parent7b6ad41ea67e10ce9849b5a7ae4411b272c3d43c (diff)
ucoo/{intf,hal/exti,arch}: add EXTI
Diffstat (limited to 'ucoo')
-rw-r--r--ucoo/arch/arch.stm32f1.cc1
-rw-r--r--ucoo/arch/arch.stm32f4.cc1
-rw-r--r--ucoo/hal/exti/Module1
-rw-r--r--ucoo/hal/exti/exti.hh33
-rw-r--r--ucoo/hal/exti/exti.stm32.cc295
-rw-r--r--ucoo/hal/exti/exti.stm32.hh86
-rw-r--r--ucoo/hal/exti/test/Makefile9
-rw-r--r--ucoo/hal/exti/test/test_exti.stm32.cc66
-rw-r--r--ucoo/intf/exti.hh56
9 files changed, 548 insertions, 0 deletions
diff --git a/ucoo/arch/arch.stm32f1.cc b/ucoo/arch/arch.stm32f1.cc
index 090e2c1..a2d659c 100644
--- a/ucoo/arch/arch.stm32f1.cc
+++ b/ucoo/arch/arch.stm32f1.cc
@@ -32,6 +32,7 @@ void
arch_init (int argc, const char **argv)
{
rcc_clock_setup_in_hse_12mhz_out_72mhz ();
+ rcc_periph_clock_enable (RCC_AFIO);
}
} // namespace ucoo
diff --git a/ucoo/arch/arch.stm32f4.cc b/ucoo/arch/arch.stm32f4.cc
index c3e7dc2..74c7306 100644
--- a/ucoo/arch/arch.stm32f4.cc
+++ b/ucoo/arch/arch.stm32f4.cc
@@ -33,6 +33,7 @@ arch_init (int argc, const char **argv)
{
rcc_clock_setup_hse_3v3 (&hse_8mhz_3v3[CLOCK_3V3_120MHZ]);
rcc_ahb_frequency = 120000000;
+ rcc_periph_clock_enable (RCC_SYSCFG);
}
} // namespace ucoo
diff --git a/ucoo/hal/exti/Module b/ucoo/hal/exti/Module
new file mode 100644
index 0000000..c4c8a06
--- /dev/null
+++ b/ucoo/hal/exti/Module
@@ -0,0 +1 @@
+ucoo_hal_exti_SOURCES := exti.stm32.cc
diff --git a/ucoo/hal/exti/exti.hh b/ucoo/hal/exti/exti.hh
new file mode 100644
index 0000000..5aa0c4f
--- /dev/null
+++ b/ucoo/hal/exti/exti.hh
@@ -0,0 +1,33 @@
+#ifndef ucoo_hal_exti_exti_hh
+#define ucoo_hal_exti_exti_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2015 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+
+#if defined TARGET_stm32
+# include "exti.stm32.hh"
+#else
+# error "not implemented for this target"
+#endif
+
+#endif // ucoo_hal_exti_exti_hh
diff --git a/ucoo/hal/exti/exti.stm32.cc b/ucoo/hal/exti/exti.stm32.cc
new file mode 100644
index 0000000..120b25e
--- /dev/null
+++ b/ucoo/hal/exti/exti.stm32.cc
@@ -0,0 +1,295 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2015 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/hal/exti/exti.stm32.hh"
+#include "ucoo/common.hh"
+
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/stm32/gpio.h>
+#if !defined AFIO_BASE
+# include <libopencm3/stm32/syscfg.h>
+#endif
+
+namespace ucoo {
+
+/// Information on EXTI hardware structure.
+struct exti_hardware_t
+{
+ /// Corresponding IRQ.
+ int irq;
+ /// Pointer to number of enabled EXTI for shared vectors, or NULL.
+ int *enabled;
+};
+
+/// Number of enabled EXTI for vector 9 down to 5.
+static int exti_vector_9_5_enabled;
+
+/// Number of enabled EXTI for vector 15 down to 10.
+static int exti_vector_15_10_enabled;
+
+/// Information on EXTI hardware array.
+struct exti_hardware_t exti_hardware[] =
+{
+ { NVIC_EXTI0_IRQ, nullptr },
+ { NVIC_EXTI1_IRQ, nullptr },
+ { NVIC_EXTI2_IRQ, nullptr },
+ { NVIC_EXTI3_IRQ, nullptr },
+ { NVIC_EXTI4_IRQ, nullptr },
+ { NVIC_EXTI9_5_IRQ, &exti_vector_9_5_enabled },
+ { NVIC_EXTI9_5_IRQ, &exti_vector_9_5_enabled },
+ { NVIC_EXTI9_5_IRQ, &exti_vector_9_5_enabled },
+ { NVIC_EXTI9_5_IRQ, &exti_vector_9_5_enabled },
+ { NVIC_EXTI9_5_IRQ, &exti_vector_9_5_enabled },
+ { NVIC_EXTI15_10_IRQ, &exti_vector_15_10_enabled },
+ { NVIC_EXTI15_10_IRQ, &exti_vector_15_10_enabled },
+ { NVIC_EXTI15_10_IRQ, &exti_vector_15_10_enabled },
+ { NVIC_EXTI15_10_IRQ, &exti_vector_15_10_enabled },
+ { NVIC_EXTI15_10_IRQ, &exti_vector_15_10_enabled },
+ { NVIC_EXTI15_10_IRQ, &exti_vector_15_10_enabled },
+};
+
+static ExtiHard *exti_instances[lengthof (exti_hardware)];
+
+} // namespace ucoo
+
+extern "C" {
+
+// If the interrupt is triggered again after being cleared, the interrupt
+// handler will be reentered. There is no need to loop.
+
+void
+exti0_isr ()
+{
+ EXTI_PR = 1u << 0;
+ assert (ucoo::exti_instances[0]);
+ ucoo::exti_instances[0]->isr ();
+}
+
+void
+exti1_isr ()
+{
+ EXTI_PR = 1u << 1;
+ assert (ucoo::exti_instances[1]);
+ ucoo::exti_instances[1]->isr ();
+}
+
+void
+exti2_isr ()
+{
+ EXTI_PR = 1u << 2;
+ assert (ucoo::exti_instances[2]);
+ ucoo::exti_instances[2]->isr ();
+}
+
+void
+exti3_isr ()
+{
+ EXTI_PR = 1u << 3;
+ assert (ucoo::exti_instances[3]);
+ ucoo::exti_instances[3]->isr ();
+}
+
+void
+exti4_isr ()
+{
+ EXTI_PR = 1u << 4;
+ assert (ucoo::exti_instances[4]);
+ ucoo::exti_instances[4]->isr ();
+}
+
+void
+exti9_5_isr ()
+{
+ uint32_t pending = EXTI_PR & 0x3e0;
+ EXTI_PR = pending;
+ for (int i = 5; i <= 9; i++)
+ {
+ if (pending & (1u << i))
+ {
+ assert (ucoo::exti_instances[i]);
+ ucoo::exti_instances[i]->isr ();
+ }
+ }
+}
+
+void
+exti15_10_isr ()
+{
+ uint32_t pending = EXTI_PR & 0xfc00;
+ EXTI_PR = pending;
+ for (int i = 10; i <= 15; i++)
+ {
+ if (pending & (1u << i))
+ {
+ assert (ucoo::exti_instances[i]);
+ ucoo::exti_instances[i]->isr ();
+ }
+ }
+}
+
+}
+
+namespace ucoo {
+
+ExtiHard::ExtiHard (int n)
+ : n_ (n)
+{
+ assert (n < lengthof (exti_instances));
+ assert (!exti_instances[n]);
+ exti_instances[n] = this;
+}
+
+ExtiHard::~ExtiHard ()
+{
+ disable ();
+ exti_instances[n_] = 0;
+}
+
+void
+ExtiHard::enable ()
+{
+ assert (handler_);
+ EXTI_IMR |= 1u << n_;
+ if (exti_hardware[n_].enabled)
+ {
+ if (!(*exti_hardware[n_].enabled)++)
+ nvic_enable_irq (exti_hardware[n_].irq);
+ }
+ else
+ nvic_enable_irq (exti_hardware[n_].irq);
+}
+
+void
+ExtiHard::disable ()
+{
+ if (exti_hardware[n_].enabled)
+ {
+ if (!--*exti_hardware[n_].enabled)
+ nvic_disable_irq (exti_hardware[n_].irq);
+ }
+ else
+ nvic_disable_irq (exti_hardware[n_].irq);
+ EXTI_IMR &= ~(1u << n_);
+ EXTI_PR = 1u << n_;
+}
+
+bool
+ExtiHard::mask ()
+{
+ bool irq_enabled = nvic_get_irq_enabled (exti_hardware[n_].irq);
+ if (irq_enabled)
+ nvic_disable_irq (exti_hardware[n_].irq);
+ return irq_enabled;
+}
+
+void
+ExtiHard::unmask (bool saved_state)
+{
+ if (saved_state)
+ nvic_enable_irq (exti_hardware[n_].irq);
+}
+
+void
+ExtiHard::set_trigger (Edge edge)
+{
+ switch (edge)
+ {
+ case Edge::RISING:
+ EXTI_RTSR |= 1u << n_;
+ EXTI_FTSR &= ~(1u << n_);
+ break;
+ case Edge::FALLING:
+ EXTI_RTSR &= ~(1u << n_);
+ EXTI_FTSR |= 1u << n_;
+ break;
+ case Edge::BOTH:
+ EXTI_RTSR |= (1u << n_);
+ EXTI_FTSR |= (1u << n_);
+ break;
+ }
+}
+
+void
+ExtiHard::set_source (uint32_t gpio_port)
+{
+ int port;
+ switch (gpio_port)
+ {
+ case GPIOA:
+ port = 0;
+ break;
+ case GPIOB:
+ port = 1;
+ break;
+ case GPIOC:
+ port = 2;
+ break;
+ case GPIOD:
+ port = 3;
+ break;
+#if defined GPIOE
+ case GPIOE:
+ port = 4;
+ break;
+#endif
+#if defined GPIOF
+ case GPIOF:
+ port = 5;
+ break;
+#endif
+#if defined GPIOG
+ case GPIOG:
+ port = 6;
+ break;
+#endif
+#if defined GPIOH
+ case GPIOH:
+ port = 7;
+ break;
+#endif
+#if defined GPIOI
+ case GPIOI:
+ port = 8;
+ break;
+#endif
+ default:
+ assert_unreachable ();
+ }
+ int shift = (n_ % 4) * 4;
+ int reg = n_ / 4;
+ uint32_t mask = 0xf << shift;
+ uint32_t bits = port << shift;
+#if defined AFIO_BASE
+ AFIO_EXTICR (reg) = (AFIO_EXTICR (reg) & ~mask) | bits;
+#else
+ SYSCFG_EXTICR (reg) = (SYSCFG_EXTICR (reg) & ~mask) | bits;
+#endif
+}
+
+void
+ExtiHard::isr ()
+{
+ handler_ ();
+}
+
+} // namespace ucoo
diff --git a/ucoo/hal/exti/exti.stm32.hh b/ucoo/hal/exti/exti.stm32.hh
new file mode 100644
index 0000000..90a8098
--- /dev/null
+++ b/ucoo/hal/exti/exti.stm32.hh
@@ -0,0 +1,86 @@
+#ifndef ucoo_hal_exti_exti_stm32_hh
+#define ucoo_hal_exti_exti_stm32_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2015 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/intf/exti.hh"
+
+#include <libopencm3/stm32/exti.h>
+
+namespace ucoo {
+
+/// External interrupt on STM32.
+class ExtiHard : public Exti
+{
+ public:
+ enum class Edge
+ {
+ RISING = 1,
+ FALLING = 2,
+ BOTH = 3
+ };
+ public:
+ /// Constructor, take the EXTI number.
+ ExtiHard (int n);
+ /// Constructor, shortcut to set source.
+ ExtiHard (uint32_t gpio_port, int n);
+ /// Constructor, shortcut to set source and trigger.
+ ExtiHard (uint32_t gpio_port, int n, Edge edge);
+ /// Destructor.
+ ~ExtiHard ();
+ /// See Exti::enable.
+ void enable ();
+ /// See Exti::disable.
+ void disable ();
+ /// See Exti::mask.
+ bool mask ();
+ /// See Exti::unmask.
+ void unmask (bool saved_state);
+ /// Set trigger edge.
+ void set_trigger (Edge edge);
+ /// Select source, take GPIO port address.
+ void set_source (uint32_t gpio_port);
+ /// Handle interrupts.
+ void isr ();
+ private:
+ /// EXTI line number.
+ int n_;
+};
+
+inline
+ExtiHard::ExtiHard (uint32_t gpio_port, int n)
+ : ExtiHard (n)
+{
+ set_source (gpio_port);
+}
+
+inline
+ExtiHard::ExtiHard (uint32_t gpio_port, int n, Edge edge)
+ : ExtiHard (gpio_port, n)
+{
+ set_trigger (edge);
+}
+
+} // namespace ucoo
+
+#endif // ucoo_hal_exti_exti_stm32_hh
diff --git a/ucoo/hal/exti/test/Makefile b/ucoo/hal/exti/test/Makefile
new file mode 100644
index 0000000..c2a7418
--- /dev/null
+++ b/ucoo/hal/exti/test/Makefile
@@ -0,0 +1,9 @@
+BASE = ../../../..
+
+TARGETS = stm32f4 stm32f1
+PROGS = test_exti
+test_exti_SOURCES = test_exti.stm32.cc
+
+MODULES = ucoo/hal/gpio ucoo/hal/exti ucoo/utils
+
+include $(BASE)/build/top.mk
diff --git a/ucoo/hal/exti/test/test_exti.stm32.cc b/ucoo/hal/exti/test/test_exti.stm32.cc
new file mode 100644
index 0000000..57b80a5
--- /dev/null
+++ b/ucoo/hal/exti/test/test_exti.stm32.cc
@@ -0,0 +1,66 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2015 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/arch/arch.hh"
+#include "ucoo/hal/gpio/gpio.hh"
+#include "ucoo/hal/exti/exti.hh"
+#include "ucoo/utils/delay.hh"
+
+#include <libopencm3/stm32/rcc.h>
+
+ucoo::Gpio *led4p;
+
+void
+led4_handler ()
+{
+ led4p->toggle ();
+}
+
+int
+main (int argc, const char **argv)
+{
+ ucoo::arch_init (argc, argv);
+ rcc_periph_clock_enable (RCC_GPIOB);
+ rcc_periph_clock_enable (RCC_GPIOD);
+ // For this test, shorten B6 & B7 to have loopback.
+ ucoo::Gpio loop_out (GPIOB, 6);
+ ucoo::Gpio loop_in (GPIOB, 7);
+ ucoo::Gpio led3 (GPIOD, 13);
+ ucoo::Gpio led4 (GPIOD, 12);
+ led4p = &led4;
+ ucoo::ExtiHard exti (7);
+ exti.set_source (GPIOB);
+ exti.set_trigger (ucoo::ExtiHard::Edge::RISING);
+ exti.register_event (led4_handler);
+ exti.enable ();
+ loop_out.output ();
+ led3.output ();
+ led4.output ();
+ while (1)
+ {
+ loop_out.toggle ();
+ led3.set (loop_in.get ());
+ ucoo::delay (1);
+ }
+ return 0;
+}
diff --git a/ucoo/intf/exti.hh b/ucoo/intf/exti.hh
new file mode 100644
index 0000000..a943a80
--- /dev/null
+++ b/ucoo/intf/exti.hh
@@ -0,0 +1,56 @@
+#ifndef ucoo_intf_exti_hh
+#define ucoo_intf_exti_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2015 Nicolas Schodet
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// }}}
+#include "ucoo/utils/function.hh"
+
+namespace ucoo {
+
+/// External interrupt interface.
+class Exti
+{
+ public:
+ /// Enable.
+ virtual void enable () = 0;
+ /// Disable.
+ virtual void disable () = 0;
+ /// Temporary mask interrupt, return previous state.
+ virtual bool mask () = 0;
+ /// Unmask interrupt.
+ virtual void unmask (bool saved_state) = 0;
+ /// Register a handler called on event.
+ template<typename F>
+ void register_event (F handler)
+ { handler_ = handler; }
+ protected:
+ /// Default constructor.
+ Exti () { }
+ protected:
+ /// Handler called on event.
+ Function<void ()> handler_;
+};
+
+} // namespace ucoo
+
+#endif // ucoo_intf_exti_hh