summaryrefslogtreecommitdiff
path: root/tests/rcc-legal-ranges
diff options
context:
space:
mode:
Diffstat (limited to 'tests/rcc-legal-ranges')
-rw-r--r--tests/rcc-legal-ranges/Makefile.stm32l1-generic1
-rw-r--r--tests/rcc-legal-ranges/README.md5
-rw-r--r--tests/rcc-legal-ranges/main-stm32l1-generic.c143
3 files changed, 119 insertions, 30 deletions
diff --git a/tests/rcc-legal-ranges/Makefile.stm32l1-generic b/tests/rcc-legal-ranges/Makefile.stm32l1-generic
index bdb721e..b9ecc71 100644
--- a/tests/rcc-legal-ranges/Makefile.stm32l1-generic
+++ b/tests/rcc-legal-ranges/Makefile.stm32l1-generic
@@ -2,6 +2,7 @@
BOARD = stm32l1-generic
PROJECT = rcc-legal-ranges-$(BOARD)
BUILD_DIR = bin-$(BOARD)
+OPT=-O0
SHARED_DIR = ../../shared
diff --git a/tests/rcc-legal-ranges/README.md b/tests/rcc-legal-ranges/README.md
index 2720e56..2313ebd 100644
--- a/tests/rcc-legal-ranges/README.md
+++ b/tests/rcc-legal-ranges/README.md
@@ -5,8 +5,9 @@ turning on and selecting different clocks, power ranges and flash
wait state configuration are robust enough.
## PASSING
-The board should issue a series of blinks at various rates before
-settling on a steady rate
+On boot you should get two slow blinks.
+After boot, you should get continuous 5/2 fast/slow blinks as it
+continuously shuffles and resets clock configurations.
## FAILING
The board stops blinking at any point in the sequence
diff --git a/tests/rcc-legal-ranges/main-stm32l1-generic.c b/tests/rcc-legal-ranges/main-stm32l1-generic.c
index 4418827..8c97bad 100644
--- a/tests/rcc-legal-ranges/main-stm32l1-generic.c
+++ b/tests/rcc-legal-ranges/main-stm32l1-generic.c
@@ -2,6 +2,7 @@
* Aug 2016 Karl Palsson <karlp@tweak.net.au>
*/
+#include <stdlib.h>
#include <libopencm3/stm32/flash.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/pwr.h>
@@ -11,6 +12,85 @@
#define LEDPORT GPIOB
#define LEDPIN GPIO6
+#ifndef ARRAY_LENGTH
+#define ARRAY_LENGTH(array) (sizeof((array))/sizeof((array)[0]))
+#endif
+
+/*
+ * A set of valid clock configurations with HSI as the source.
+ * thankfully, L1 allows apb1/apb2 to reach full ahb speed in all cases.
+ */
+struct rcc_clock_scale valid_hsi_clocks[] = {
+ {
+ /* 8Mhz, hsi/div2, max perf for range 2 with 0 ws */
+ .hpre = RCC_CFGR_HPRE_SYSCLK_DIV2,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
+ .voltage_scale = PWR_SCALE2,
+ .flash_config = FLASH_ACR_LATENCY_0WS,
+ .ahb_frequency = 8e6,
+ .apb1_frequency = 8e6,
+ .apb2_frequency = 8e6,
+ },
+ {
+ /* Slowest hsi possible */
+ .hpre = RCC_CFGR_HPRE_SYSCLK_DIV512,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .voltage_scale = PWR_SCALE3,
+ .flash_config = FLASH_ACR_LATENCY_0WS,
+ .ahb_frequency = 31250,
+ .apb1_frequency = 31250,
+ .apb2_frequency = 31250,
+ },
+ {
+ /* Fastest HSI possible, range 1, 0ws */
+ .hpre = RCC_CFGR_HPRE_SYSCLK_NODIV,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .voltage_scale = PWR_SCALE1,
+ .flash_config = FLASH_ACR_LATENCY_0WS,
+ .ahb_frequency = 16e6,
+ .apb1_frequency = 16e6,
+ .apb2_frequency = 16e6,
+ },
+ {
+ /* highest perf for range 3 with 0 wait states */
+ .hpre = RCC_CFGR_HPRE_SYSCLK_DIV8,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .voltage_scale = PWR_SCALE3,
+ .flash_config = FLASH_ACR_LATENCY_0WS,
+ .ahb_frequency = 2e6,
+ .apb1_frequency = 2e6,
+ .apb2_frequency = 2e6,
+ },
+ {
+ /* Fastest HSI for range 2, 0ws */
+ .hpre = RCC_CFGR_HPRE_SYSCLK_NODIV,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .voltage_scale = PWR_SCALE1,
+ .flash_config = FLASH_ACR_LATENCY_0WS,
+ .ahb_frequency = 16e6,
+ .apb1_frequency = 16e6,
+ .apb2_frequency = 16e6,
+ },
+ {
+ /* highest perf for range 3 */
+ .hpre = RCC_CFGR_HPRE_SYSCLK_DIV4,
+ .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .ppre2 = RCC_CFGR_PPRE1_HCLK_NODIV,
+ .voltage_scale = PWR_SCALE3,
+ .flash_config = FLASH_ACR_LATENCY_1WS,
+ .ahb_frequency = 4e6,
+ .apb1_frequency = 4e6,
+ .apb2_frequency = 4e6,
+ },
+};
+
+int shuffled[ARRAY_LENGTH(valid_hsi_clocks)];
+
/**
* blink led count times, with vile hack * 1000 asm nops
*/
@@ -24,43 +104,50 @@ static void hack_blink(int count, int hack)
}
}
+/* Stack overflow, wiki, whathaveyou */
+/* FIXME oh yeah, did I mention that rand() is always zero? */
+static void shuffle_fisher_yates(int *array, size_t n)
+{
+ if (n > 1) {
+ size_t i;
+ for (i = 0; i < n - 1; i++) {
+ size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
+ int t = array[j];
+ array[j] = array[i];
+ array[i] = t;
+ }
+ }
+}
+
+static void run_clock_set(void)
+{
+ shuffle_fisher_yates(shuffled, ARRAY_LENGTH(shuffled));
+
+ struct rcc_clock_scale *clock;
+ for (size_t i = 0; i < ARRAY_LENGTH(shuffled); i++) {
+ clock = &valid_hsi_clocks[i];
+ rcc_clock_setup_hsi(clock);
+ /** blink quickly/slowly as we run through these */
+ hack_blink(10, clock->ahb_frequency / (500 * 1000));
+ hack_blink(4, clock->ahb_frequency / (200 * 1000));
+ }
+}
+
int main(void)
{
- int i;
- int j = 0;
/* Allow leds on any port */
RCC_AHBENR |= 0xff;
gpio_mode_setup(LEDPORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LEDPIN);
/* blink twice with slow msi reset clock */
hack_blink(4, 60);
+
+ /* ok, now, "randomly" sort the list of clocks to try them out */
+ for (size_t i = 0; i < ARRAY_LENGTH(shuffled); i++) {
+ shuffled[i] = i;
+ }
- /* step forward to HSI/2, 8Mhz */
- struct rcc_clock_scale v2_8low = {
- .hpre = RCC_CFGR_HPRE_SYSCLK_DIV2,
- .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
- .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
- .voltage_scale = PWR_SCALE2,
- .flash_config = FLASH_ACR_LATENCY_0WS,
- .ahb_frequency = 8000000,
- .apb1_frequency = 8000000,
- .apb2_frequency = 8000000,
- };
- rcc_clock_setup_hsi(&v2_8low);
- /* blink twice again, different rate */
- hack_blink(4, 60);
-
- /* step forward to HSI->PLL@32Mhz, range 1 */
- rcc_clock_setup_pll(&rcc_clock_config[RCC_CLOCK_VRANGE1_HSI_PLL_32MHZ]);
- /* blink twice again */
- hack_blink(4, 400);
-
- /* back down again */
- rcc_clock_setup_hsi(&v2_8low);
- hack_blink(4, 60);
-
- /* just keep blinking */
while (1) {
- hack_blink(1, 400);
+ run_clock_set();
}
return 0;