11// Copyright (c) 2022 Cesanta Software Limited
22// All rights reserved
3+ // https://www.st.com/resource/en/reference_manual/dm00031020-stm32f405-415-stm32f407-417-stm32f427-437-and-stm32f429-439-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf
34
45#pragma once
56
6- #include <inttypes.h>
7+ #include <stm32f429xx.h>
8+
79#include <stdbool.h>
10+ #include <stdint.h>
811#include <stdio.h>
9- #include <stdlib.h>
10- #include <sys/stat.h>
11-
12- #include "stm32f429xx.h"
12+ #include <string.h>
1313
1414#define BIT (x ) (1UL << (x))
15+ #define SETBITS (R , CLEARMASK , SETMASK ) (R) = ((R) & ~(CLEARMASK)) | (SETMASK)
1516#define PIN (bank , num ) ((((bank) - 'A') << 8) | (num))
1617#define PINNO (pin ) (pin & 255)
1718#define PINBANK (pin ) (pin >> 8)
@@ -27,101 +28,128 @@ enum { PLL_HSI = 16, PLL_M = 8, PLL_N = 180, PLL_P = 2 }; // Run at 180 Mhz
2728#define APB1_FREQUENCY (SYS_FREQUENCY / (BIT(APB1_PRE - 3)))
2829
2930static inline void spin (volatile uint32_t count ) {
30- while (count -- ) asm("nop" );
31- }
32-
33- static inline void systick_init (uint32_t ticks ) {
34- if ((ticks - 1 ) > 0xffffff ) return ; // Systick timer is 24 bit
35- SysTick -> LOAD = ticks - 1 ;
36- SysTick -> VAL = 0 ;
37- SysTick -> CTRL = BIT (0 ) | BIT (1 ) | BIT (2 ); // Enable systick
38- RCC -> APB2ENR |= BIT (14 ); // Enable SYSCFG
31+ while (count -- ) (void ) 0 ;
3932}
4033
41- #define GPIO (bank ) ((GPIO_TypeDef *) (GPIOA_BASE + 0x400U * (bank)))
4234enum { GPIO_MODE_INPUT , GPIO_MODE_OUTPUT , GPIO_MODE_AF , GPIO_MODE_ANALOG };
43-
44- static inline void gpio_set_mode (uint16_t pin , uint8_t mode ) {
45- GPIO_TypeDef * gpio = GPIO (PINBANK (pin )); // GPIO bank
46- int n = PINNO (pin ); // Pin number
47- RCC -> AHB1ENR |= BIT (PINBANK (pin )); // Enable GPIO clock
48- gpio -> MODER &= ~(3U << (n * 2 )); // Clear existing setting
49- gpio -> MODER |= (mode & 3U ) << (n * 2 ); // Set new mode
35+ enum { GPIO_OTYPE_PUSH_PULL , GPIO_OTYPE_OPEN_DRAIN };
36+ enum { GPIO_SPEED_LOW , GPIO_SPEED_MEDIUM , GPIO_SPEED_HIGH , GPIO_SPEED_INSANE };
37+ enum { GPIO_PULL_NONE , GPIO_PULL_UP , GPIO_PULL_DOWN };
38+ #define GPIO (N ) ((GPIO_TypeDef *) (0x40020000 + 0x400 * (N)))
39+
40+ static GPIO_TypeDef * gpio_bank (uint16_t pin ) { return GPIO (PINBANK (pin )); }
41+ static inline void gpio_toggle (uint16_t pin ) {
42+ GPIO_TypeDef * gpio = gpio_bank (pin );
43+ uint32_t mask = BIT (PINNO (pin ));
44+ gpio -> BSRR = mask << (gpio -> ODR & mask ? 16 : 0 );
5045}
51-
52- static inline void gpio_set_af (uint16_t pin , uint8_t af_num ) {
53- GPIO_TypeDef * gpio = GPIO (PINBANK (pin )); // GPIO bank
54- int n = PINNO (pin ); // Pin number
55- gpio -> AFR [n >> 3 ] &= ~(15UL << ((n & 7 ) * 4 ));
56- gpio -> AFR [n >> 3 ] |= ((uint32_t ) af_num ) << ((n & 7 ) * 4 );
46+ static inline int gpio_read (uint16_t pin ) {
47+ return gpio_bank (pin )-> IDR & BIT (PINNO (pin )) ? 1 : 0 ;
5748}
58-
5949static inline void gpio_write (uint16_t pin , bool val ) {
60- GPIO_TypeDef * gpio = GPIO (PINBANK (pin ));
61- gpio -> BSRR = (1U << PINNO (pin )) << (val ? 0 : 16 );
50+ GPIO_TypeDef * gpio = gpio_bank (pin );
51+ gpio -> BSRR = BIT (PINNO (pin )) << (val ? 0 : 16 );
52+ }
53+ static inline void gpio_init (uint16_t pin , uint8_t mode , uint8_t type ,
54+ uint8_t speed , uint8_t pull , uint8_t af ) {
55+ GPIO_TypeDef * gpio = gpio_bank (pin );
56+ uint8_t n = (uint8_t ) (PINNO (pin ));
57+ RCC -> AHB1ENR |= BIT (PINBANK (pin )); // Enable GPIO clock
58+ SETBITS (gpio -> OTYPER , 1UL << n , ((uint32_t ) type ) << n );
59+ SETBITS (gpio -> OSPEEDR , 3UL << (n * 2 ), ((uint32_t ) speed ) << (n * 2 ));
60+ SETBITS (gpio -> PUPDR , 3UL << (n * 2 ), ((uint32_t ) pull ) << (n * 2 ));
61+ SETBITS (gpio -> AFR [n >> 3 ], 15UL << ((n & 7 ) * 4 ),
62+ ((uint32_t ) af ) << ((n & 7 ) * 4 ));
63+ SETBITS (gpio -> MODER , 3UL << (n * 2 ), ((uint32_t ) mode ) << (n * 2 ));
64+ }
65+ static inline void gpio_input (uint16_t pin ) {
66+ gpio_init (pin , GPIO_MODE_INPUT , GPIO_OTYPE_PUSH_PULL , GPIO_SPEED_HIGH ,
67+ GPIO_PULL_NONE , 0 );
68+ }
69+ static inline void gpio_output (uint16_t pin ) {
70+ gpio_init (pin , GPIO_MODE_OUTPUT , GPIO_OTYPE_PUSH_PULL , GPIO_SPEED_HIGH ,
71+ GPIO_PULL_NONE , 0 );
6272}
6373
64- #define UART1 USART1
65- #define UART2 USART2
66- #define UART3 USART3
74+ static inline void irq_exti_attach (uint16_t pin ) {
75+ uint8_t bank = (uint8_t ) (PINBANK (pin )), n = (uint8_t ) (PINNO (pin ));
76+ SYSCFG -> EXTICR [n / 4 ] &= ~(15UL << ((n % 4 ) * 4 ));
77+ SYSCFG -> EXTICR [n / 4 ] |= (uint32_t ) (bank << ((n % 4 ) * 4 ));
78+ EXTI -> IMR |= BIT (n );
79+ EXTI -> RTSR |= BIT (n );
80+ EXTI -> FTSR |= BIT (n );
81+ int irqvec = n < 5 ? 6 + n : n < 10 ? 23 : 40 ; // IRQ vector index, 10.1.2
82+ NVIC_SetPriority (irqvec , 3 );
83+ NVIC_EnableIRQ (irqvec );
84+ }
85+
86+ #ifndef UART_DEBUG
87+ #define UART_DEBUG USART3
88+ #endif
6789
68- static inline void uart_init (USART_TypeDef * uart , unsigned long baud ) {
90+ static inline bool uart_init (USART_TypeDef * uart , unsigned long baud ) {
6991 // https://www.st.com/resource/en/datasheet/stm32f429zi.pdf
7092 uint8_t af = 7 ; // Alternate function
7193 uint16_t rx = 0 , tx = 0 ; // pins
7294 uint32_t freq = 0 ; // Bus frequency. UART1 is on APB2, rest on APB1
7395
74- if (uart == UART1 ) freq = APB2_FREQUENCY , RCC -> APB2ENR |= BIT (4 );
75- if (uart == UART2 ) freq = APB1_FREQUENCY , RCC -> APB1ENR |= BIT (17 );
76- if (uart == UART3 ) freq = APB1_FREQUENCY , RCC -> APB1ENR |= BIT (18 );
77-
78- if (uart == UART1 ) tx = PIN ('A' , 9 ), rx = PIN ('A' , 10 );
79- if (uart == UART2 ) tx = PIN ('A' , 2 ), rx = PIN ('A' , 3 );
80- if (uart == UART3 ) tx = PIN ('D' , 8 ), rx = PIN ('D' , 9 );
81-
82- gpio_set_mode (tx , GPIO_MODE_AF );
83- gpio_set_af (tx , af );
84- gpio_set_mode (rx , GPIO_MODE_AF );
85- gpio_set_af (rx , af );
96+ if (uart == USART1 ) {
97+ freq = APB2_FREQUENCY , RCC -> APB2ENR |= BIT (4 );
98+ tx = PIN ('A' , 9 ), rx = PIN ('A' , 10 );
99+ } else if (uart == USART2 ) {
100+ freq = APB1_FREQUENCY , RCC -> APB1ENR |= BIT (17 );
101+ tx = PIN ('A' , 2 ), rx = PIN ('A' , 3 );
102+ } else if (uart == USART3 ) {
103+ freq = APB1_FREQUENCY , RCC -> APB1ENR |= BIT (18 );
104+ tx = PIN ('D' , 8 ), rx = PIN ('D' , 9 );
105+ } else {
106+ return false;
107+ }
108+
109+ gpio_init (tx , GPIO_MODE_AF , GPIO_OTYPE_PUSH_PULL , GPIO_SPEED_HIGH , 0 , af );
110+ gpio_init (rx , GPIO_MODE_AF , GPIO_OTYPE_PUSH_PULL , GPIO_SPEED_HIGH , 0 , af );
86111 uart -> CR1 = 0 ; // Disable this UART
87112 uart -> BRR = freq / baud ; // Set baud rate
88113 uart -> CR1 |= BIT (13 ) | BIT (2 ) | BIT (3 ); // Set UE, RE, TE
114+ return true;
89115}
90-
91116static inline void uart_write_byte (USART_TypeDef * uart , uint8_t byte ) {
92117 uart -> DR = byte ;
93118 while ((uart -> SR & BIT (7 )) == 0 ) spin (1 );
94119}
95-
96120static inline void uart_write_buf (USART_TypeDef * uart , char * buf , size_t len ) {
97121 while (len -- > 0 ) uart_write_byte (uart , * (uint8_t * ) buf ++ );
98122}
99-
100123static inline int uart_read_ready (USART_TypeDef * uart ) {
101124 return uart -> SR & BIT (5 ); // If RXNE bit is set, data is ready
102125}
103-
104126static inline uint8_t uart_read_byte (USART_TypeDef * uart ) {
105127 return (uint8_t ) (uart -> DR & 255 );
106128}
107129
108- static inline bool timer_expired (uint32_t * t , uint32_t prd , uint32_t now ) {
130+ static inline void rng_init (void ) {
131+ RCC -> AHB2ENR |= RCC_AHB2ENR_RNGEN ;
132+ RNG -> CR |= RNG_CR_RNGEN ;
133+ }
134+ static inline uint32_t rng_read (void ) {
135+ while ((RNG -> SR & RNG_SR_DRDY ) == 0 ) (void ) 0 ;
136+ return RNG -> DR ;
137+ }
138+
139+ #define UUID ((uint8_t *) UID_BASE) // Unique 96-bit chip ID. TRM 39.1
140+
141+ // Helper macro for MAC generation
142+ #define GENERATE_LOCALLY_ADMINISTERED_MAC () \
143+ { \
144+ 2, UUID[0] ^ UUID[1], UUID[2] ^ UUID[3], UUID[4] ^ UUID[5], \
145+ UUID[6] ^ UUID[7] ^ UUID[8], UUID[9] ^ UUID[10] ^ UUID[11] \
146+ }
147+
148+ static inline bool timer_expired (volatile uint32_t * t , uint32_t prd ,
149+ uint32_t now ) {
109150 if (now + prd < * t ) * t = 0 ; // Time wrapped? Reset timer
110151 if (* t == 0 ) * t = now + prd ; // Firt poll? Set expiration
111152 if (* t > now ) return false; // Not expired yet, return
112153 * t = (now - * t ) > prd ? now + prd : * t + prd ; // Next expiration time
113154 return true; // Expired, return true
114155}
115-
116- static inline void clock_init (void ) { // Set clock frequency
117- SCB -> CPACR |= ((3UL << 10 * 2 ) | (3UL << 11 * 2 )); // Enable FPU
118- FLASH -> ACR |= FLASH_LATENCY | BIT (8 ) | BIT (9 ); // Flash latency, caches
119- RCC -> PLLCFGR &= ~((BIT (17 ) - 1 )); // Clear PLL multipliers
120- RCC -> PLLCFGR |= (((PLL_P - 2 ) / 2 ) & 3 ) << 16 ; // Set PLL_P
121- RCC -> PLLCFGR |= PLL_M | (PLL_N << 6 ); // Set PLL_M and PLL_N
122- RCC -> CR |= BIT (24 ); // Enable PLL
123- while ((RCC -> CR & BIT (25 )) == 0 ) spin (1 ); // Wait until done
124- RCC -> CFGR = (APB1_PRE << 10 ) | (APB2_PRE << 13 ); // Set prescalers
125- RCC -> CFGR |= 2 ; // Set clock source to PLL
126- while ((RCC -> CFGR & 12 ) == 0 ) spin (1 ); // Wait until done
127- }
0 commit comments