rcc-legal-ranges: run through a range of clocks

blink fast/slow for each clock configuration tested, then finish by
blinking idly.

As of this commit, this test fails quickly on most L1 boards tested.
An update to libopencm3 is required to fix this.
This commit is contained in:
Karl Palsson 2016-08-18 18:35:00 +00:00
parent 3d72709fda
commit cb945fa671
3 changed files with 119 additions and 30 deletions

View file

@ -2,6 +2,7 @@
BOARD = stm32l1-generic
PROJECT = rcc-legal-ranges-$(BOARD)
BUILD_DIR = bin-$(BOARD)
OPT=-O0
SHARED_DIR = ../../shared

View file

@ -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

View file

@ -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;