@rew OK, so let me show you how I'd solve this problem.
Let's assume you are using a STM32F0 MCU and you must ensure the SPI clock speed must be between 0.8 and 1.2 MHz (1.0 MHz nominal!). I'll compute that for my STM32F0 board.
When looking e.g. at section 27.9.1 in the reference manual (
http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031936.pdf), you can see that the SPI clock speed is derived from PCLK.
Let's calculate the clocks (although ChibiOS does this in macros, you usually need to do it to find out if your concepts work at all):
SYSCLK is equal to the PLL output because STM32_SW = STM32_SW_PLL
The PLL gets fed by a 8 MHz HSE oscillator (STM32_PLLSRC = STM32_PLLSRC_HSE) that is first divided by STM32_PREDIV_VALUE = 1 and then multiplied by STM32_PLLMUL_VALUE = 6. This gives us a 48 MHz SYSCLK (max speed for the F030F4).
HCLK is SYSCLK divided by STM32_HPRE_DIV1 = 1, therefore HCLK is 48 MHz.
PCLK is SYSCLK divided by STM32_PPRE_DIV1 = 1, therefore PCLK is 48 MHz.
OK, now we know that PCLK is 48 MHz. Let's do some elementary math: What do we need to divide 48 MHz by to get 1 MHz. Right: 48.
Now we can look at the table in the refman (search for SPIx_CR1, see above for link & section). What is the correct value for BR[2:0]?
Ahem... there is no 48 here. Therefore, it won't work
What can we do?
Unfortunately not too much as long as the CPU clock remains @48MHz. We need to ensure PCLK is 32, 16, 8, 4, 2 or 1 MHz. However, the PCLK can (AFAIK) only be generated by a power-of-2-prescaler from SYSCLK.
This means, we have to set PLLMUL to 4 (instead of 6) to get a 32 MHz sysclock. Then we can use BR[2:0] = 100 (a SPI prescaler of 32 --> 1 MHz).
Of course we could always relax the requirements. But I hope you can see the issue now, it is a complicated process on complicated MCUs. When you have a single, slow clock like on the AVR, it is much easier, but you won't have any of the fancy features like DMA etc.
The F0 family usually can handle up to 18 MBit/s SPI, so you can assume using a 16 MHz SCLK will work (actual limits are listed in the datasheet).
-------------
This was complicated. Welcome to MCUs. However IMO most of the time you can actually avoid doing that calculations
Some practical tips:
a) If possible, use _Static_assert to check the ChibiOS calculated value, e.g.
Code: Select all
_Static_assert (STM32_PCLK < 32000000, "PCLK too large");
b) If you can be sure not to damage the other ICs (or it's cheap to replace), in my experience you can usually waste less time by just trying it out. Start with the maximum prescaler(fPCLK/256) and work your way up until it doesn't work any more (if you care about low power or have EMI issues, try to use a higher prescaler --> lower frequency).
c) In many cases you can just use the default config from the testhal directory. This is my config. As I said, in my experience it wastes less time to change something and measure than to do accurate calculations, assuming you don't have very strict requirements and your equipment is not easily damaged. You can optimize power consumption and EMI later.
Code: Select all
static SPIConfig spi1cfg = {
NULL,
/* HW dependent part.*/
GPIOB,
GPIOB_ADC1_CS,
SPI_CR1_BR_0 | SPI_CR1_CPOL | SPI_CR1_CPHA,
0
};
Best regards, Uli