Skip to content

Commit

Permalink
Merge pull request #2535 from cesanta/hal
Browse files Browse the repository at this point in the history
Move clock_init() to hal.h
  • Loading branch information
scaprile authored Dec 18, 2023
2 parents 4b7d871 + e9a6bad commit df3c216
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 57 deletions.
56 changes: 53 additions & 3 deletions examples/stm32/nucleo-h743zi-make-baremetal-builtin/hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#define LED2 PIN('E', 1) // On-board LED pin (yellow)
#define LED3 PIN('B', 14) // On-board LED pin (red)

#define LED LED2 // Use yellow LED for blinking
#define LED LED2 // Use yellow LED for blinking

// System clock (2.1, Figure 1; 8.5, Figure 45; 8.5.5, Figure 47; 8.5.6, Figure
// 49) CPU_FREQUENCY <= 480 MHz; hclk = CPU_FREQUENCY / HPRE ; hclk <= 240 MHz;
Expand Down Expand Up @@ -61,7 +61,9 @@ enum { GPIO_PULL_NONE, GPIO_PULL_UP, GPIO_PULL_DOWN };

#define GPIO(N) ((GPIO_TypeDef *) (0x40000000 + 0x18020000UL + 0x400 * (N)))

static GPIO_TypeDef *gpio_bank(uint16_t pin) { return GPIO(PINBANK(pin)); }
static GPIO_TypeDef *gpio_bank(uint16_t pin) {
return GPIO(PINBANK(pin));
}
static inline void gpio_toggle(uint16_t pin) {
GPIO_TypeDef *gpio = gpio_bank(pin);
uint32_t mask = BIT(PINNO(pin));
Expand Down Expand Up @@ -159,6 +161,53 @@ static inline char chiprev(void) {
return '?';
}

static inline unsigned int div2prescval(unsigned int div) {
// 0 --> /1; 8 --> /2 ... 11 --> /16; 12 --> /64 ... 15 --> /512
if (div == 1) return 0;
if (div > 16) div /= 2;
unsigned int val = 7;
while (div >>= 1) ++val;
return val;
}

static inline unsigned int pllrge(unsigned int f) {
unsigned int val = 0;
while (f >>= 1) ++val;
return val - 1;
}

static inline void clock_init(void) {
SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); // Enable FPU
__DSB();
__ISB();
PWR->CR3 |= BIT(1); // select LDO (reset value)
while ((PWR->CSR1 & BIT(13)) == 0) spin(1); // ACTVOSRDY
PWR->D3CR |= BIT(15) | BIT(14); // Select VOS1
uint32_t f = PWR->D3CR; // fake read to wait for bus clocking
while ((PWR->CSR1 & BIT(13)) == 0) spin(1); // ACTVOSRDY
SYSCFG->PWRCR |= BIT(0); // ODEN
f = SYSCFG->PWRCR;
while ((PWR->CSR1 & BIT(13)) == 0) spin(1); // ACTVOSRDY
(void) f;
SETBITS(
RCC->D1CFGR, (0x0F << 8) | (7 << 4) | (0x0F << 0),
(div2prescval(D1CPRE) << 8) | (D1PPRE << 4) | (div2prescval(HPRE) << 0));
RCC->D2CFGR = (D2PPRE2 << 8) | (D2PPRE1 << 4);
RCC->D3CFGR = (D3PPRE << 4);
SETBITS(RCC->PLLCFGR, 3 << 2,
pllrge(PLL1_HSI / PLL1_M)
<< 2); // keep reset config (DIVP1EN, !PLL1VCOSEL), PLL1RGE
SETBITS(RCC->PLL1DIVR, (0x7F << 9) | (0x1FF << 0),
((PLL1_P - 1) << 9) | ((PLL1_N - 1) << 0)); // Set PLL1_P PLL1_N
SETBITS(RCC->PLLCKSELR, 0x3F << 4,
PLL1_M << 4); // Set PLL1_M (source defaults to HSI)
RCC->CR |= BIT(24); // Enable PLL1
while ((RCC->CR & BIT(25)) == 0) spin(1); // Wait until done
RCC->CFGR |= (3 << 0); // Set clock source to PLL1
while ((RCC->CFGR & (7 << 3)) != (3 << 3)) spin(1); // Wait until done
FLASH->ACR = FLASH_LATENCY; // default is larger
}

static inline void ethernet_init(void) {
// Initialise Ethernet. Enable MAC GPIO pins, see
// https://www.st.com/resource/en/user_manual/um2407-stm32h7-nucleo144-boards-mb1364-stmicroelectronics.pdf
Expand All @@ -169,9 +218,10 @@ static inline void ethernet_init(void) {
gpio_init(pins[i], GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_INSANE,
GPIO_PULL_NONE, 11); // 11 is the Ethernet function
}
NVIC_EnableIRQ(ETH_IRQn); // Setup Ethernet IRQ handler
RCC->APB4ENR |= RCC_APB4ENR_SYSCFGEN; // Enable SYSCFG
SETBITS(SYSCFG->PMCR, 7 << 21, 4 << 21); // Use RMII (12.3.1)
RCC->AHB1ENR |= BIT(15) | BIT(16) | BIT(17); // Enable Ethernet clocks
NVIC_EnableIRQ(ETH_IRQn); // Setup Ethernet IRQ handler
}

#define UUID ((uint8_t *) UID_BASE) // Unique 96-bit chip ID. TRM 61.1
Expand Down
2 changes: 2 additions & 0 deletions examples/stm32/nucleo-h743zi-make-baremetal-builtin/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ static void timer_fn(void *arg) {
ifp->ndrop, ifp->nerr));
}

// Device initialisation flow is in startup_XXX.s, provided by device vendor.
// It inits data/bss, IRQ table, then calls SystemInit(), then calls main()
int main(void) {
gpio_output(LED); // Setup green LED
uart_init(UART_DEBUG, 115200); // Initialise debug printf
Expand Down
63 changes: 9 additions & 54 deletions examples/stm32/nucleo-h743zi-make-baremetal-builtin/sysinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,17 @@
// This file contains essentials required by the CMSIS:
// uint32_t SystemCoreClock - holds the system core clock value
// SystemInit() - initialises the system, e.g. sets up clocks
//
// Vendor CMSIS usually contain system_XXXX.c file with SystemInit()
// We don't use it - instead, we provide our own SystemInit().

#include "hal.h"

uint32_t SystemCoreClock = CPU_FREQUENCY;

static inline unsigned int div2prescval(unsigned int div) {
// 0 --> /1; 8 --> /2 ... 11 --> /16; 12 --> /64 ... 15 --> /512
if (div == 1) return 0;
if (div > 16) div /= 2;
unsigned int val = 7;
while (div >>= 1) ++val;
return val;
}

static inline unsigned int pllrge(unsigned int f) {
unsigned int val = 0;
while (f >>= 1) ++val;
return val - 1;
}

void SystemInit(void) { // Called automatically by startup code
SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); // Enable FPU
asm("DSB");
asm("ISB");
PWR->CR3 |= BIT(1); // select LDO (reset value)
while ((PWR->CSR1 & BIT(13)) == 0) spin(1); // ACTVOSRDY
PWR->D3CR |= BIT(15) | BIT(14); // Select VOS1
uint32_t f = PWR->D3CR; // fake read to wait for bus clocking
while ((PWR->CSR1 & BIT(13)) == 0) spin(1); // ACTVOSRDY
SYSCFG->PWRCR |= BIT(0); // ODEN
f = SYSCFG->PWRCR;
while ((PWR->CSR1 & BIT(13)) == 0) spin(1); // ACTVOSRDY
(void) f;
SETBITS(
RCC->D1CFGR, (0x0F << 8) | (7 << 4) | (0x0F << 0),
(div2prescval(D1CPRE) << 8) | (D1PPRE << 4) | (div2prescval(HPRE) << 0));
RCC->D2CFGR = (D2PPRE2 << 8) | (D2PPRE1 << 4);
RCC->D3CFGR = (D3PPRE << 4);
SETBITS(RCC->PLLCFGR, 3 << 2,
pllrge(PLL1_HSI / PLL1_M)
<< 2); // keep reset config (DIVP1EN, !PLL1VCOSEL), PLL1RGE
SETBITS(RCC->PLL1DIVR, (0x7F << 9) | (0x1FF << 0),
((PLL1_P - 1) << 9) | ((PLL1_N - 1) << 0)); // Set PLL1_P PLL1_N
SETBITS(RCC->PLLCKSELR, 0x3F << 4,
PLL1_M << 4); // Set PLL1_M (source defaults to HSI)
RCC->CR |= BIT(24); // Enable PLL1
while ((RCC->CR & BIT(25)) == 0) spin(1); // Wait until done
RCC->CFGR |= (3 << 0); // Set clock source to PLL1
while ((RCC->CFGR & (7 << 3)) != (3 << 3)) spin(1); // Wait until done
FLASH->ACR = FLASH_LATENCY; // default is larger
#if 0
// Enable SRAM block if you want to use it for ETH buffer (needs proper attributes in driver code)
// RCC->AHB2ENR |= BIT(29) | BIT(30) | BIT(31);
#endif
uint32_t SystemCoreClock; // Holds system core clock in Hz. Required by CMSIS

RCC->APB4ENR |= RCC_APB4ENR_SYSCFGEN; // Enable SYSCFG
rng_init(); // Initialise random number generator
SysTick_Config(CPU_FREQUENCY / 1000); // Sys tick every 1ms
void SystemInit(void) { // Called automatically by startup code
clock_init(); // Core clock to 480 MHz
rng_init(); // Initialise random number generator
SystemCoreClock = CPU_FREQUENCY; // defined in hal.h
SysTick_Config(SystemCoreClock / 1000); // Sys tick every 1ms
}

0 comments on commit df3c216

Please sign in to comment.