summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Schodet2012-12-16 19:20:11 +0100
committerNicolas Schodet2012-12-23 15:32:51 +0100
commit1ae44013703af4e8757abe6adb70745861bf8f9f (patch)
tree0e7ed71eed591579dd0aaf93af289836453451c3
parent57510da98a112699188012b8505136d58594c274 (diff)
digital/ucoolib/ucoolib/utils: add delay functions
-rw-r--r--digital/ucoolib/ucoolib/utils/Module1
-rw-r--r--digital/ucoolib/ucoolib/utils/delay.arm.cc76
-rw-r--r--digital/ucoolib/ucoolib/utils/delay.arm.hh52
-rw-r--r--digital/ucoolib/ucoolib/utils/delay.hh76
-rw-r--r--digital/ucoolib/ucoolib/utils/test/Makefile9
-rw-r--r--digital/ucoolib/ucoolib/utils/test/test_delay.cc64
6 files changed, 278 insertions, 0 deletions
diff --git a/digital/ucoolib/ucoolib/utils/Module b/digital/ucoolib/ucoolib/utils/Module
new file mode 100644
index 00000000..fe3f9fd0
--- /dev/null
+++ b/digital/ucoolib/ucoolib/utils/Module
@@ -0,0 +1 @@
+utils_SOURCES := delay.arm.cc
diff --git a/digital/ucoolib/ucoolib/utils/delay.arm.cc b/digital/ucoolib/ucoolib/utils/delay.arm.cc
new file mode 100644
index 00000000..8410c8d1
--- /dev/null
+++ b/digital/ucoolib/ucoolib/utils/delay.arm.cc
@@ -0,0 +1,76 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// APBTeam:
+// Web: http://apbteam.org/
+// Email: team AT apbteam DOT org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// }}}
+#include "delay.arm.hh"
+
+#include <algorithm>
+
+#include <libopencm3/stm32/systick.h>
+#include <libopencm3/stm32/f4/rcc.h>
+
+namespace ucoo {
+
+void
+delay_us (int us)
+{
+ // Horrible hack: there is no record of the current systick speed, make
+ // guesses based on APB2 clock. Also, suppose that frequency is a multiple
+ // of 1 MHz (to avoid 64 bit division).
+ int systick_mhz = rcc_ppre2_frequency / (4 * 1000000);
+ int cycles = systick_mhz * us;
+ STK_CTRL = 0;
+ // Loop several times if cycles is too big for the systick timer. Some
+ // nanoseconds are lost every second, I can live with that, it simplifies
+ // code.
+ while (cycles)
+ {
+ int loop_cycles = std::min (1 << 24, cycles);
+ STK_LOAD = loop_cycles - 1;
+ STK_VAL = 0;
+ STK_CTRL = STK_CTRL_ENABLE;
+ while (!(STK_CTRL & STK_CTRL_COUNTFLAG))
+ ;
+ STK_CTRL = 0;
+ cycles -= loop_cycles;
+ }
+}
+
+void
+delay_ns (int ns)
+{
+ // Horrible hack: there is no record of the current hclock speed, make
+ // guesses based on APB2 clock. Also, suppose that frequency is a multiple
+ // of 1 MHz (to avoid 64 bit division).
+ int hclock_mhz = rcc_ppre2_frequency / (1000000 / 2);
+ int cycles = (hclock_mhz * ns + 999) / 1000;
+ STK_CTRL = 0;
+ // Loop once, ns is supposed to be small.
+ STK_LOAD = cycles - 1;
+ STK_VAL = 0;
+ STK_CTRL = STK_CTRL_CLKSOURCE_AHB | STK_CTRL_ENABLE;
+ while (!(STK_CTRL & STK_CTRL_COUNTFLAG))
+ ;
+ STK_CTRL = 0;
+}
+
+} // namespace ucoo
diff --git a/digital/ucoolib/ucoolib/utils/delay.arm.hh b/digital/ucoolib/ucoolib/utils/delay.arm.hh
new file mode 100644
index 00000000..ad67002f
--- /dev/null
+++ b/digital/ucoolib/ucoolib/utils/delay.arm.hh
@@ -0,0 +1,52 @@
+#ifndef ucoolib_utils_delay_arm_hh
+#define ucoolib_utils_delay_arm_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// APBTeam:
+// Web: http://apbteam.org/
+// Email: team AT apbteam DOT org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// }}}
+
+namespace ucoo {
+
+/// Wait for an integral number of microseconds, used to implement delay.
+void
+delay_us (int us);
+
+/// Wait for a small integral number of nanoseconds, used to implement short
+/// delay.
+void
+delay_ns (int us);
+
+/// Wait for the specified delay in seconds.
+extern inline void
+delay (double s)
+{
+ if (s < 1e-6)
+ delay_ns (static_cast<int> (s * 1e9));
+ else
+ delay_us (static_cast<int> (s * 1e6));
+}
+extern inline void
+delay (double s) __attribute__ ((always_inline));
+
+} // namespace ucoo
+
+#endif // ucoolib_utils_delay_arm_hh
diff --git a/digital/ucoolib/ucoolib/utils/delay.hh b/digital/ucoolib/ucoolib/utils/delay.hh
new file mode 100644
index 00000000..4affce83
--- /dev/null
+++ b/digital/ucoolib/ucoolib/utils/delay.hh
@@ -0,0 +1,76 @@
+#ifndef ucoolib_utils_delay_hh
+#define ucoolib_utils_delay_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// APBTeam:
+// Web: http://apbteam.org/
+// Email: team AT apbteam DOT org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// }}}
+
+#if defined (TARGET_host)
+
+namespace ucoo {
+
+/// No delay on host.
+extern inline void
+delay (double s)
+{
+}
+
+} // namespace ucoo
+
+#elif defined (TARGET_arm)
+# include "delay.arm.hh"
+#else
+# error "not implemented for this target"
+#endif
+
+namespace ucoo {
+
+/// Shortcut for delay with nanosecond.
+extern inline void
+delay_ns (double ns)
+{
+ delay (ns * 1e-9);
+}
+extern inline void
+delay_ns (double ns) __attribute__ ((always_inline));
+
+/// Shortcut for delay with microsecond.
+extern inline void
+delay_us (double us)
+{
+ delay (us * 1e-6);
+}
+extern inline void
+delay_us (double us) __attribute__ ((always_inline));
+
+/// Shortcut for delay with millisecond.
+extern inline void
+delay_ms (double ms)
+{
+ delay (ms * 1e-3);
+}
+extern inline void
+delay_ms (double ms) __attribute__ ((always_inline));
+
+} // namespace ucoo
+
+#endif // ucoolib_utils_delay_hh
diff --git a/digital/ucoolib/ucoolib/utils/test/Makefile b/digital/ucoolib/ucoolib/utils/test/Makefile
new file mode 100644
index 00000000..2c45dc44
--- /dev/null
+++ b/digital/ucoolib/ucoolib/utils/test/Makefile
@@ -0,0 +1,9 @@
+BASE = ../../..
+
+TARGETS = stm32f4
+stm32f4_PROGS = test_delay
+test_delay_SOURCES = test_delay.cc
+
+MODULES = utils
+
+include $(BASE)/build/top.mk
diff --git a/digital/ucoolib/ucoolib/utils/test/test_delay.cc b/digital/ucoolib/ucoolib/utils/test/test_delay.cc
new file mode 100644
index 00000000..1b645619
--- /dev/null
+++ b/digital/ucoolib/ucoolib/utils/test/test_delay.cc
@@ -0,0 +1,64 @@
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2012 Nicolas Schodet
+//
+// APBTeam:
+// Web: http://apbteam.org/
+// Email: team AT apbteam DOT org
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// }}}
+#include "ucoolib/utils/delay.hh"
+#include "ucoolib/arch/arch.hh"
+
+#include <libopencm3/stm32/f4/rcc.h>
+#include <libopencm3/stm32/f4/gpio.h>
+
+int
+main (int argc, const char **argv)
+{
+ ucoo::arch_init (argc, argv);
+ rcc_peripheral_enable_clock (&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN);
+ gpio_mode_setup (GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,
+ GPIO12 | GPIO13 | GPIO14 | GPIO15);
+ gpio_clear (GPIOD, GPIO12 | GPIO13 | GPIO14 | GPIO15);
+ int i, j;
+ while (1)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ gpio_toggle (GPIOD, GPIO12 << (i % 4));
+ ucoo::delay (1);
+ }
+ for (i = 0; i < 16; i++)
+ {
+ gpio_toggle (GPIOD, GPIO12 << (i % 4));
+ ucoo::delay_ms (250);
+ }
+ for (i = 0; i < 16000; i++)
+ {
+ gpio_toggle (GPIOD, GPIO12 << (i % 4));
+ ucoo::delay_us (250);
+ }
+ for (i = 0; i < 16; i++)
+ {
+ gpio_toggle (GPIOD, GPIO12 << (i % 4));
+ for (j = 0; j < 1000; j++)
+ ucoo::delay_us (250);
+ }
+ }
+ return 0;
+}