1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/stm32_common/dist/spi_divtable/spi_divtable.c

106 lines
2.8 KiB
C
Raw Normal View History

/*
* Copyright (C) 2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @brief Compute SPI clock scaler values for STM32x CPUs
*
* This helper tool calculates the needed SPI scaler values for the APBx buses.
* It outputs the values for the possible SPI clock speeds based on the clock
* speeds of the APB1 and the APB2 bus.
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
static int targets[] = { 100000, 400000, 1000000, 5000000, 10000000 };
/**
* @brief Find the best fitting divisor value base on target and APB clock
*
* The SPI bus clock speed is calculated as follows:
*
* clk_bus = clk_apb / 2 ^ (x + 1)
*
* In this function we will try to find the x-value, that brings clk_bus as
* close as possible to the value given in @p target.
*
* @param[in] bus clock speed of the given APB bus
* @param[in] target targeted SPI clock speed
*
* @return the closes divisor value to be used in the clock config register
*/
static int find_best(int bus, int target)
{
int br = -1;
int tmp = bus;
do {
// printf("b: x: %i - tmp: %i\n", br, tmp);
++br;
tmp /= 2;
if (tmp == target) {
return br;
}
// printf("a: x: %i - tmp: %i\n", br, tmp);
// printf(" (tmp - target):%i\n", (tmp - target));
} while ((tmp - target > 0) && (br < 7));
int old = tmp * 2;
// printf("(target - tmp):%i, (old - target): %i\n", (target - tmp), (old - target));
if ((target - tmp) > (old - target)) {
return (br - 1);
}
return br;
}
static int real_clk(int bus, int br)
{
return bus / (2 << br);
}
int main(int argc, char **argv)
{
2019-07-18 15:19:55 +02:00
int tnum = ARRAY_SIZE(targets);
int apb[2];
if (argc != 3) {
printf("usage: %s <APB1 clk> <APB2 clk> (in Hz)\n", argv[0]);
return 1;
}
apb[0] = atoi(argv[1]); /* APB1 */
apb[1] = atoi(argv[2]); /* APB2 */
if ((apb[0] <= 0) || (apb[1] <= 0)) {
puts("error: invalid APB clock speed values");
return 1;
}
printf("static const uint8_t spi_divtable[2][%i] = {\n", tnum);
2019-07-18 15:19:55 +02:00
for (int bus = 0; bus < ARRAY_SIZE(apb); bus ++) {
printf(" { /* for APB%i @ %iHz */\n", (bus + 1), apb[bus]);
for (int t = 0; t < tnum; t++) {
int br = find_best(apb[bus], targets[t]);
printf(" %i%c /* -> %iHz */\n",
br, ((t < (tnum - 1)) ? ',' : ' '), real_clk(apb[bus], br));
}
printf(" }%s\n", ((bus == 0) ? "," : ""));
}
puts("};");
return 0;
}