diff options
-rw-r--r-- | tests/rcc-legal-ranges/Makefile.stm32l1-generic | 1 | ||||
-rw-r--r-- | tests/rcc-legal-ranges/README.md | 5 | ||||
-rw-r--r-- | tests/rcc-legal-ranges/main-stm32l1-generic.c | 143 |
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; |