1
1
// Copyright (c) 2022 Cesanta Software Limited
2
2
// 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
3
4
4
5
#pragma once
5
6
6
- #include <inttypes.h>
7
+ #include <stm32f429xx.h>
8
+
7
9
#include <stdbool.h>
10
+ #include <stdint.h>
8
11
#include <stdio.h>
9
- #include <stdlib.h>
10
- #include <sys/stat.h>
11
-
12
- #include "stm32f429xx.h"
12
+ #include <string.h>
13
13
14
14
#define BIT (x ) (1UL << (x))
15
+ #define SETBITS (R , CLEARMASK , SETMASK ) (R) = ((R) & ~(CLEARMASK)) | (SETMASK)
15
16
#define PIN (bank , num ) ((((bank) - 'A') << 8) | (num))
16
17
#define PINNO (pin ) (pin & 255)
17
18
#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
27
28
#define APB1_FREQUENCY (SYS_FREQUENCY / (BIT(APB1_PRE - 3)))
28
29
29
30
static 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 ;
39
32
}
40
33
41
- #define GPIO (bank ) ((GPIO_TypeDef *) (GPIOA_BASE + 0x400U * (bank)))
42
34
enum { 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 );
50
45
}
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 ;
57
48
}
58
-
59
49
static 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 );
62
72
}
63
73
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
67
89
68
- static inline void uart_init (USART_TypeDef * uart , unsigned long baud ) {
90
+ static inline bool uart_init (USART_TypeDef * uart , unsigned long baud ) {
69
91
// https://www.st.com/resource/en/datasheet/stm32f429zi.pdf
70
92
uint8_t af = 7 ; // Alternate function
71
93
uint16_t rx = 0 , tx = 0 ; // pins
72
94
uint32_t freq = 0 ; // Bus frequency. UART1 is on APB2, rest on APB1
73
95
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 );
86
111
uart -> CR1 = 0 ; // Disable this UART
87
112
uart -> BRR = freq / baud ; // Set baud rate
88
113
uart -> CR1 |= BIT (13 ) | BIT (2 ) | BIT (3 ); // Set UE, RE, TE
114
+ return true;
89
115
}
90
-
91
116
static inline void uart_write_byte (USART_TypeDef * uart , uint8_t byte ) {
92
117
uart -> DR = byte ;
93
118
while ((uart -> SR & BIT (7 )) == 0 ) spin (1 );
94
119
}
95
-
96
120
static inline void uart_write_buf (USART_TypeDef * uart , char * buf , size_t len ) {
97
121
while (len -- > 0 ) uart_write_byte (uart , * (uint8_t * ) buf ++ );
98
122
}
99
-
100
123
static inline int uart_read_ready (USART_TypeDef * uart ) {
101
124
return uart -> SR & BIT (5 ); // If RXNE bit is set, data is ready
102
125
}
103
-
104
126
static inline uint8_t uart_read_byte (USART_TypeDef * uart ) {
105
127
return (uint8_t ) (uart -> DR & 255 );
106
128
}
107
129
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 ) {
109
150
if (now + prd < * t ) * t = 0 ; // Time wrapped? Reset timer
110
151
if (* t == 0 ) * t = now + prd ; // Firt poll? Set expiration
111
152
if (* t > now ) return false; // Not expired yet, return
112
153
* t = (now - * t ) > prd ? now + prd : * t + prd ; // Next expiration time
113
154
return true; // Expired, return true
114
155
}
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