This commit is contained in:
Alexander Heldt
2024-08-11 17:37:17 +02:00
parent a3c1de878a
commit 2fc8ee4f92
23 changed files with 9613 additions and 839 deletions

View File

@@ -13,10 +13,36 @@ struct gpio {
volatile uint32_t ODR; // Port output data register
volatile uint32_t BSRR; // Port bit set/reset register
volatile uint32_t LCKR; // Port configuration lock register
volatile uint32_t AFRL[2]; // Alternative function low register
volatile uint32_t AFRH[2]; // Alternative function high register
volatile uint32_t AFRL; // Alternative function low register
volatile uint32_t AFRH; // Alternative function high register
};
#define GPIOA_BASE_ADDR (0x40020000U)
#define GPIOA ((struct gpio *) GPIOA_BASE_ADDR)
// MODER register
#define GPIO_MODER_MODER3_BIT 7 // Bits [7:6]
#define GPIO_MODER_MODER3_MASK (0b11)
#define GPIO_MODER_MODER3_AF (0b10)
#define GPIO_MODER_MODER2_BIT 4 // Bits [5:4]
#define GPIO_MODER_MODER2_MASK (0b11)
#define GPIO_MODER_MODER2_AF (0b10)
// AFRL register
#define GPIO_AFRL_AFRL3_BIT 12 // Bits [15:12]
#define GPIO_AFRL_AFRL3_MASK (0b1111)
#define GPIO_AFRL_AFRL3_USART2_RX (0b0111) // Alternative function 7
#define GPIO_AFRL_AFRL2_BIT 8 // Bits [11:8]
#define GPIO_AFRL_AFRL2_MASK (0b1111)
#define GPIO_AFRL_AFRL2_USART2_TX (0b0111) // Alternative function 7
#define GPIO_BASE_ADDR (0x40020000U)
#define GPIO_PORT_OFFSET (0x400U)
#define GPIO(port) ((struct gpio*)(uintptr_t)(GPIO_BASE_ADDR + (GPIO_PORT_OFFSET * port)))

View File

@@ -6,6 +6,7 @@
#include "flash.h"
#include "pwr.h"
#include "timer.h"
#include "usart.h"
#define exit 42
@@ -76,7 +77,9 @@ static void system_clock_init(void) {
int main(void) {
(void) system_clock_init();
(void) tim4_init();
(void) usart2_init();
(void) tim4_start();
(void) tim4_start();
uint16_t led = PIN('C', 13); // Blue LED
@@ -90,6 +93,9 @@ int main(void) {
led_on = !led_on;
gpio_write(led, led_on);
while ((USART2->ISR & USART_ISR_TC) != USART_ISR_TC);
USART2->TDR = '#';
counter = TIM4->CNT;
}
};

View File

@@ -114,10 +114,18 @@ struct rcc {
#define RCC_CFGR_SW_MASK (0b11)
#define RCC_CFGR_SW(clock) ((clock & RCC_CFGR_SW_MASK) << RCC_CFGR_SW_BIT)
// AHB1ENR Register
// GPIOA AHB1ENR
#define RCC_AHB1ENR_GPIOAEN_BIT 0
#define RCC_AHB1ENR_GPIOAEN_ENABLE (1 << RCC_AHB1ENR_GPIOAEN_BIT)
// APB1ENR Register
#define RCC_APB1ENR_PWREN_BIT 28
#define RCC_APB1ENR_PWREN_CLOCK_ENABLE (1 << RCC_APB1ENR_PWREN_BIT)
#define RCC_APB1ENR_USART2EN_BIT 17
#define RCC_APB1ENR_USART2EN_ENABLE (1 << RCC_APB1ENR_USART2EN_BIT)
#define RCC_APB1ENR_TIM4_BIT 2
#define RCC_APB1ENR_TIM4_ENABLE (1 << RCC_APB1ENR_TIM4_BIT)

View File

@@ -18,5 +18,5 @@ void tim4_init(void) {
}
void tim4_start(void) {
TIM4->CR1 |= TIM4_ENABLE;
TIM4->CR1 |= TIM_ENABLE;
}

View File

@@ -29,8 +29,8 @@ struct timer {
#define TIM4_BASE_ADDR (0x40000800U)
#define TIM4 ((struct timer *) TIM4_BASE_ADDR)
#define TIM4_CR_CEN_BIT 0
#define TIM4_ENABLE (1 << TIM4_CR_CEN_BIT)
#define TIM_CR1_CEN_BIT 0
#define TIM_ENABLE (1 << TIM_CR1_CEN_BIT)
void tim4_init(void);
void tim4_start(void);

63
src/usart.c Normal file
View File

@@ -0,0 +1,63 @@
#include "rcc.h"
#include "gpio.h"
#include "usart.h"
void usart2_init(void) {
// Enable clock for GPIOA
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN_ENABLE;
// Configure PA2 and PA3 (USART2 pins) to use alternative functions
GPIOA->MODER &= ~(GPIO_MODER_MODER2_MASK << GPIO_MODER_MODER2_BIT);
GPIOA->MODER |= (GPIO_MODER_MODER2_AF << GPIO_MODER_MODER2_BIT);
GPIOA->MODER &= ~(GPIO_MODER_MODER3_MASK << GPIO_MODER_MODER3_BIT);
GPIOA->MODER |= (GPIO_MODER_MODER3_AF << GPIO_MODER_MODER3_BIT);
// Set pin alternative modes to use USART
GPIOA->AFRL &= ~(GPIO_AFRL_AFRL2_MASK << GPIO_AFRL_AFRL2_BIT);
GPIOA->AFRL |= (GPIO_AFRL_AFRL2_USART2_TX << GPIO_AFRL_AFRL2_BIT);
GPIOA->AFRL &= ~(GPIO_AFRL_AFRL3_MASK << GPIO_AFRL_AFRL3_BIT);
GPIOA->AFRL |= (GPIO_AFRL_AFRL3_USART2_RX << GPIO_AFRL_AFRL3_BIT);
// Enable USART
RCC->AHB1ENR |= RCC_APB1ENR_USART2EN_ENABLE;
// Clear control registers
USART2->CR1 = 0;
USART2->CR2 = 0;
USART2->CR3 = 0;
// Calculate Baud rate:
// baud = f_clock / (8 * (2 - OVER8) * USARTDIV); =>
// (8 * (2 - OVER8) * USARTDIV) = f_clock / baud; =>
// USARTDIV = (f_clock / (baud * (8 * (2 - OVER8))); =>
// Target Baud rate = 115200, f_clock = 48MHz
// With OVER8 = 1 (oversampling by 8)
// USARTDIV = (48E6 / (115200 * (8 * (2 - 1))) = 52.083
// mantissa = 52
// fraction = 0.083 * 8 = 0.664 ~= 1
// rounding fraction up: USARTDIV = 53
// baud = 48E6 / (8 * (52 + 1)) = 113207.54716981133
// error of 0.1% (115200 / 113207.54716981133)
// rounding fraction down: USARTDIV = 52
// baud = 48E6 / (8 * 52) = 115384.61538461539
// error of 0.001% (115384.61538461539 / 115200)
USART2->CR1 |= USART_CR1_OVER8_8;
USART2->BRR &= ~(USART_BRR_MANTISSA_MASK << USART_BRR_MANTISSA_BIT);
USART2->BRR |= (52 << USART_BRR_MANTISSA_BIT);
USART2->BRR &= ~(USART_BRR_FRACTION_MASK << USART_BRR_FRACTION_BIT);
USART2->BRR |= (0 << USART_BRR_FRACTION_BIT);
// Enable transmitter and receiver
USART2->CR1 |= USART_CR1_TE_ENABLE;
USART2->CR1 |= USART_CR1_RE_ENABLE;
}
void usart2_start(void) {
USART2->CR1 |= USART_CR1_UE_ENABLE;
}

46
src/usart.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef USART_H_
#define USART_H_
#include <inttypes.h>
struct usart {
volatile uint32_t SR; // Status register
volatile uint32_t DR; // Data register
volatile uint32_t BRR; // Baud rate register
volatile uint32_t CR1; // Control register 1
volatile uint32_t CR2; // Control register 2
volatile uint32_t CR3; // Control register 3
volatile uint32_t GTPR; // Guard time and prescaler registe
};
#define USART2_BASE_ADDR (0x40004400U)
#define USART2 ((struct usart *) USART2_BASE_ADDR)
// CR Register
// Oversampling mode
#define USART_CR1_OVER8_BIT 15
#define USART_CR1_OVER8_8 (1 << USART_CR1_OVER8_BIT)
// USART enable
#define USART_CR1_UE_BIT 13
#define USART_CR1_UE_ENABLE (1 << USART_CR1_UE_BIT)
// Trasmitter enable
#define USART_CR1_TE_BIT 3
#define USART_CR1_TE_ENABLE (1 << USART_CR1_TE_BIT)
// Receiver enable
#define USART_CR1_RE_BIT 2
#define USART_CR1_RE_ENABLE (1 << USART_CR1_RE_BIT)
// BRR Register
#define USART_BRR_MANTISSA_BIT 4 // Bits [15:4]
#define USART_BRR_MANTISSA_MASK (0b111111111111) // Bits [15:4]
#define USART_BRR_FRACTION_BIT 0 // Bits [3:0]
#define USART_BRR_FRACTION_MASK (0b111) // Bits [3:0]
void usart2_init(void);
void usart2_start(void);
#endif