diff --git a/src/main.c b/src/main.c index 777596b..35b4909 100644 --- a/src/main.c +++ b/src/main.c @@ -1,30 +1,105 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2024-2025 Matthias Blankertz +#include + #include #include #include +#include +#include +#include #include +static void HALClockConfig(void) +{ + // Two wait states required for sysclk > 48 MHz + LL_FLASH_SetLatency(LL_FLASH_LATENCY_2); + while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2) { + } + + LL_RCC_HSE_Enable(); + /* Wait till HSE is ready */ + while (LL_RCC_HSE_IsReady() != 1) { + } + + // HSE clock = 16 MHz, SysClk = 16 MHz / 2 * 9 = 72 MHz + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE_DIV_2, LL_RCC_PLL_MUL_9); + LL_RCC_PLL_Enable(); + /* Wait till PLL is ready */ + while (LL_RCC_PLL_IsReady() != 1) { + } + + // AHB clock = SysClk = 72 MHz + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + // APB1 clock = AHB clock / 2 = 36 MHz + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2); + // APB2 clock = AHB clock = 72 MHz + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + /* Wait till System clock is ready */ + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { + } + + LL_Init1msTick(72000000); + LL_SetSystemCoreClock(72000000); +} + static void HALInit(void) { - LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO | LL_APB2_GRP1_PERIPH_GPIOA); + LL_FLASH_EnablePrefetch(); + + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO | LL_APB2_GRP1_PERIPH_GPIOA | LL_APB2_GRP1_PERIPH_SPI1); LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); // No JTAG, only SWD LL_GPIO_AF_Remap_SWJ_NOJTAG(); + HALClockConfig(); + + // LED is on PA8 LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_8, LL_GPIO_MODE_OUTPUT); - LL_Init1msTick(8000000); + // SPI1 on PA4 - CS, PA5 - SCK, PA7 - MOSI + LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_4, LL_GPIO_MODE_OUTPUT); + LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_5, LL_GPIO_MODE_ALTERNATE); + LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_7, LL_GPIO_MODE_ALTERNATE); + + // APB2 clock = 72 MHz, SPI rate = 72 MHz / 4 = 18 MHz + LL_SPI_SetBaudRatePrescaler(SPI1, LL_SPI_BAUDRATEPRESCALER_DIV4); + // CPOL = CPHA = 0 is default + // Set 16 bit data width + LL_SPI_SetDataWidth(SPI1, LL_SPI_DATAWIDTH_16BIT); + // MSB transmitted first is default + LL_SPI_SetNSSMode(SPI1, LL_SPI_NSS_SOFT); + LL_SPI_SetMode(SPI1, LL_SPI_MODE_MASTER); + LL_SPI_Enable(SPI1); +} + +static void spi_send(uint8_t data) +{ + LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_4); + // LL_SPI_TransmitData8(SPI1, data); + LL_SPI_TransmitData16(SPI1, (((uint16_t)data) << 8) | data); + // Wait for xfer to start + while (!LL_SPI_IsActiveFlag_TXE(SPI1)) { + } + // Wait for xfer to end + while (LL_SPI_IsActiveFlag_BSY(SPI1)) { + } + LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_4); } int main(void) { HALInit(); + bool spi_led_state = true; while (1) { LL_GPIO_TogglePin(GPIOA, LL_GPIO_PIN_8); + spi_send(spi_led_state ? 0x1 : 0x0); + spi_led_state = !spi_led_state; LL_mDelay(1000); } }