diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32L1/spi_api.c b/hal/targets/hal/TARGET_STM/TARGET_STM32L1/spi_api.c index a0429ac21d..e312af1e4c 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32L1/spi_api.c +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32L1/spi_api.c @@ -28,6 +28,7 @@ ******************************************************************************* */ #include "mbed_assert.h" +#include "mbed_error.h" #include "spi_api.h" #if DEVICE_SPI @@ -177,46 +178,47 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) init_spi(obj); } +static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2, + SPI_BAUDRATEPRESCALER_4, + SPI_BAUDRATEPRESCALER_8, + SPI_BAUDRATEPRESCALER_16, + SPI_BAUDRATEPRESCALER_32, + SPI_BAUDRATEPRESCALER_64, + SPI_BAUDRATEPRESCALER_128, + SPI_BAUDRATEPRESCALER_256}; + void spi_frequency(spi_t *obj, int hz) { - // Values depend of PCLK1 and PCLK2: 32 MHz if HSI is used, 24 MHz if HSE is used - if (SystemCoreClock == 32000000) { // HSI - if (hz < 250000) { - obj->br_presc = SPI_BAUDRATEPRESCALER_256; // 125 kHz - } else if ((hz >= 250000) && (hz < 500000)) { - obj->br_presc = SPI_BAUDRATEPRESCALER_128; // 250 kHz - } else if ((hz >= 500000) && (hz < 1000000)) { - obj->br_presc = SPI_BAUDRATEPRESCALER_64; // 500 kHz - } else if ((hz >= 1000000) && (hz < 2000000)) { - obj->br_presc = SPI_BAUDRATEPRESCALER_32; // 1 MHz - } else if ((hz >= 2000000) && (hz < 4000000)) { - obj->br_presc = SPI_BAUDRATEPRESCALER_16; // 2 MHz - } else if ((hz >= 4000000) && (hz < 8000000)) { - obj->br_presc = SPI_BAUDRATEPRESCALER_8; // 4 MHz - } else if ((hz >= 8000000) && (hz < 16000000)) { - obj->br_presc = SPI_BAUDRATEPRESCALER_4; // 8 MHz - } else { // >= 16000000 - obj->br_presc = SPI_BAUDRATEPRESCALER_2; // 16 MHz - } - } else { // 24 MHz - HSE - if (hz < 180000) { - obj->br_presc = SPI_BAUDRATEPRESCALER_256; // 94 kHz - } else if ((hz >= 180000) && (hz < 350000)) { - obj->br_presc = SPI_BAUDRATEPRESCALER_128; // 188 kHz - } else if ((hz >= 350000) && (hz < 750000)) { - obj->br_presc = SPI_BAUDRATEPRESCALER_64; // 375 kHz - } else if ((hz >= 750000) && (hz < 1000000)) { - obj->br_presc = SPI_BAUDRATEPRESCALER_32; // 750 kHz - } else if ((hz >= 1000000) && (hz < 3000000)) { - obj->br_presc = SPI_BAUDRATEPRESCALER_16; // 1.5 MHz - } else if ((hz >= 3000000) && (hz < 6000000)) { - obj->br_presc = SPI_BAUDRATEPRESCALER_8; // 3 MHz - } else if ((hz >= 6000000) && (hz < 12000000)) { - obj->br_presc = SPI_BAUDRATEPRESCALER_4; // 6 MHz - } else { // >= 12000000 - obj->br_presc = SPI_BAUDRATEPRESCALER_2; // 12 MHz - } + int spi_hz = 0; + uint8_t prescaler_rank = 0; + + /* Get source clock depending on SPI instance */ + switch ((int)obj->spi) { + case SPI_1: + /* SPI_1. Source CLK is PCKL2 */ + spi_hz = HAL_RCC_GetPCLK2Freq(); + break; + case SPI_2: + case SPI_3: + /* SPI_2, SPI_3. Source CLK is PCKL1 */ + spi_hz = HAL_RCC_GetPCLK1Freq(); + break; + default: + error("SPI instance not set"); } + + /* Define pre-scaler in order to get highest available frequency below requested frequency */ + while ((spi_hz > hz) && (prescaler_rank < sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0]))){ + spi_hz = spi_hz / 2; + prescaler_rank++; + } + + if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) { + obj->br_presc = baudrate_prescaler_table[prescaler_rank-1]; + } else { + error("Couldn't setup requested SPI frequency"); + } + init_spi(obj); }