From d0823eecd4dee0c7e2f3ee08534b89477526b6ad Mon Sep 17 00:00:00 2001 From: Rutherther Date: Sun, 20 Oct 2024 14:07:04 +0200 Subject: [PATCH] feat: add registers, pin, exti, usb_device skeleton --- include/exti.h | 22 +++++++++ include/pin.h | 65 +++++++++++++++++++++++++++ include/registers.h | 12 +++++ include/usb_device.h | 29 ++++++++++++ src/exti.c | 75 +++++++++++++++++++++++++++++++ src/pin.c | 78 ++++++++++++++++++++++++++++++++ src/registers.c | 23 ++++++++++ src/usb_device.c | 103 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 407 insertions(+) create mode 100644 include/exti.h create mode 100644 include/pin.h create mode 100644 include/registers.h create mode 100644 include/usb_device.h create mode 100644 src/exti.c create mode 100644 src/pin.c create mode 100644 src/registers.c create mode 100644 src/usb_device.c diff --git a/include/exti.h b/include/exti.h new file mode 100644 index 0000000..44322ed --- /dev/null +++ b/include/exti.h @@ -0,0 +1,22 @@ +#include +#include + +#ifndef EXTI_H +#define EXTI_H + +typedef struct { + EXTI_TypeDef* exti; + SYSCFG_TypeDef* syscfg; +} exti_t; + +exti_t* exti_init(EXTI_TypeDef* exti, SYSCFG_TypeDef* syscfg); +void exti_external_interrupt(exti_t* exti, uint8_t line, uint8_t gpio); + +// Only 21 positions are now supported. This is too hard for other ones. +void exti_rising_interrupt(exti_t* exti, uint8_t line); +void exti_falling_interrupt(exti_t* exti, uint8_t line); +void exti_disable_interrupt(exti_t* exti, uint8_t line); + +void exti_nvic_setup(exti_t* exti, uint8_t line); + +#endif // EXTI_H diff --git a/include/pin.h b/include/pin.h new file mode 100644 index 0000000..5d75ff3 --- /dev/null +++ b/include/pin.h @@ -0,0 +1,65 @@ +#include +#include +#include + +#ifndef PIN_H +#define PIN_H + +typedef struct { + GPIO_TypeDef* gpio; + uint8_t pin; +} pin_t; + +typedef enum { + NONE = 0, + PULLUP = 1, + PULLDOWN = 2, + PULL_RESERVED = 3 +} pin_pullmode_t; + +typedef enum { + INPUT, + OUTPUT, + ALTERNATE, + ANALOG +} pin_mode_t; + +typedef enum { + LOW_SPEED, + MEDIUM_SPEED, + HIGH_SPEED, + VERY_HIGH_SPEED +} pin_speedmode_t; + +pin_t* pin_init(GPIO_TypeDef* gpio, uint8_t pin); + +void pin_mode(pin_t* pin, pin_mode_t mode); +void pin_pull(pin_t* pin, pin_pullmode_t mode); +void pin_speed(pin_t* pin, pin_speedmode_t mode); + +// Reads input, not output! +uint8_t pin_read(pin_t* pin); +uint8_t pin_write(pin_t* pin, uint8_t val); +void pin_toggle(pin_t* pin); +void pin_set(pin_t* pin); +void pin_reset(pin_t* pin); + +void pin_into_pulldown(pin_t* pin); +void pin_into_pullup(pin_t* pin); +void pin_into_no_pull(pin_t* pin); + +void pin_into_output(pin_t* pin); +void pin_into_output_pushpull(pin_t* pin); +void pin_into_output_opendrain(pin_t* pin); +void pin_into_pushpull(pin_t* pin); +void pin_into_opendrain(pin_t* pin); + +void pin_into_input(pin_t* pin); +void pin_into_input_highspeed(pin_t* pin); + +void pin_into_alternate(pin_t* pin, uint8_t alternate); +void pin_into_alternate_highspeed(pin_t* pin, uint8_t alternate); + +void pin_into_highspeed(pin_t* pin); + +#endif // PIN_H diff --git a/include/registers.h b/include/registers.h new file mode 100644 index 0000000..e62a884 --- /dev/null +++ b/include/registers.h @@ -0,0 +1,12 @@ +#include + +#ifndef REGISTERS_H +#define REGISTERS_H + +void reg_set_bits_pos(volatile uint32_t *reg, uint32_t data, uint8_t pos, uint8_t mask); +void reg_set_bits(volatile uint32_t *reg, uint32_t data, uint8_t mask); +void reg_toggle_bits_pos(volatile uint32_t *reg, uint8_t pos, uint8_t mask); +void reg_toggle_bits(volatile uint32_t *reg, uint8_t mask); +uint32_t reg_read_bits_pos(volatile uint32_t *reg, uint8_t pos, uint8_t mask); + +#endif // REGISTERS_H diff --git a/include/usb_device.h b/include/usb_device.h new file mode 100644 index 0000000..627ceeb --- /dev/null +++ b/include/usb_device.h @@ -0,0 +1,29 @@ +#ifndef USB_DEVICE_H +#define USB_DEVICE_H + +// +#include + +typedef struct { + volatile USB_OTG_GlobalTypeDef *core; + volatile USB_OTG_DeviceTypeDef *device; +} usb_device_t; + +struct usb_configuration_t; + +typedef struct { + +} usb_class_t; + +// has configuration etc + +#define USB_DEVICE_SIZE sizeof(usb_device_t) + +extern usb_device_t* usb1_device; + +void* usb_device_init(void* peripheral_address, usb_class_t* class, void* buffer); + +void usb_device_setup(void* device); +void* usb_device_wait_for_handshake(void* device); + +#endif // USB_DEVICE_H diff --git a/src/exti.c b/src/exti.c new file mode 100644 index 0000000..1331032 --- /dev/null +++ b/src/exti.c @@ -0,0 +1,75 @@ +#include +#include + +#include "exti.h" +#include "registers.h" +#include "stm32h747xx.h" + +exti_t *exti_init(EXTI_TypeDef *exti, SYSCFG_TypeDef *syscfg) { + exti_t* exti_periph = (exti_t*)malloc(sizeof(exti_t)); + + exti_periph->exti = exti; + exti_periph->syscfg = syscfg; + + return exti_periph; +} + +void exti_external_interrupt(exti_t *exti, uint8_t line, uint8_t gpio) { + // TODOA; general + uint8_t index = line >> 2; + uint8_t pos = (line & 0x3) * 4; + volatile uint32_t *exticr = exti->syscfg->EXTICR; + reg_set_bits_pos(exticr + index, gpio, pos, 0x0F); +} + +void exti_rising_interrupt(exti_t *exti, uint8_t line) { + reg_set_bits_pos(&exti->exti->RTSR1, 1, line, 1); + reg_set_bits_pos(&exti->exti->FTSR1, 0, line, 1); + reg_set_bits_pos(&exti->exti->IMR1, 1, line, 1); +} + +void exti_falling_interrupt(exti_t *exti, uint8_t line) { + reg_set_bits_pos(&exti->exti->FTSR1, 1, line, 1); + reg_set_bits_pos(&exti->exti->RTSR1, 0, line, 1); + reg_set_bits_pos(&exti->exti->IMR1, 1, line, 1); +} + +void exti_disable_interrupt(exti_t *exti, uint8_t line) { + reg_set_bits_pos(&exti->exti->IMR1, 0, line, 1); +} + +IRQn_Type exti_irq_idx(uint8_t line) { + switch (line) { + case 0: + return EXTI0_IRQn; + case 1: + return EXTI1_IRQn; + case 2: + return EXTI2_IRQn; + case 3: + return EXTI3_IRQn; + case 4: + return EXTI4_IRQn; + case 5: + case 6: + case 7: + case 8: + case 9: + return EXTI9_5_IRQn; + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + return EXTI15_10_IRQn; + default: + return -1; + } +} + +void exti_nvic_setup(exti_t *exti, uint8_t line) { + IRQn_Type idx = exti_irq_idx(line); + NVIC_SetPriority(idx, 2); + NVIC_EnableIRQ(idx); +} diff --git a/src/pin.c b/src/pin.c new file mode 100644 index 0000000..bf985e1 --- /dev/null +++ b/src/pin.c @@ -0,0 +1,78 @@ +#include "pin.h" +#include "registers.h" +#include + +pin_t *pin_init(GPIO_TypeDef *gpio, uint8_t pin) { + pin_t* pin_periph = (pin_t*)malloc(sizeof(pin_t)); + + pin_periph->gpio = gpio; + pin_periph->pin = pin; + + return pin_periph; +} + +void pin_mode(pin_t *pin, pin_mode_t mode) { + reg_set_bits_pos(&pin->gpio->MODER, (uint32_t)mode, pin->pin << 1, 0b11); +} +void pin_pull(pin_t *pin, pin_pullmode_t mode) { + reg_set_bits_pos(&pin->gpio->PUPDR, (uint32_t)mode, pin->pin << 1, 0b11); +} +void pin_speed(pin_t *pin, pin_speedmode_t mode) { + reg_set_bits_pos(&pin->gpio->OSPEEDR, (uint32_t)mode, pin->pin << 1, 0b11); +} + +uint8_t pin_read(pin_t *pin) { + reg_read_bits_pos(&pin->gpio->IDR, pin->pin, 1); +} + +uint8_t pin_write(pin_t *pin, uint8_t val) { + reg_set_bits_pos(&pin->gpio->ODR, val, pin->pin, 1); +} +void pin_toggle(pin_t *pin) { + reg_toggle_bits_pos(&pin->gpio->ODR, pin->pin, 1); +} +void pin_set(pin_t *pin) { + pin->gpio->ODR = 1 << pin->pin; +} +void pin_reset(pin_t *pin) { + pin->gpio->ODR = 1 << (pin->pin + 15); +} + +void pin_into_output(pin_t *pin) { + pin_mode(pin, OUTPUT); +} +void pin_into_output_pushpull(pin_t *pin) { + pin_into_output(pin); + pin_into_pushpull(pin); +} +void pin_into_output_opendrain(pin_t *pin) { + pin_into_output(pin); + pin_into_opendrain(pin); +} + +void pin_into_pushpull(pin_t *pin) { + reg_set_bits_pos(&pin->gpio->OTYPER, 0, pin->pin, 1); +} +void pin_into_opendrain(pin_t *pin) { + reg_set_bits_pos(&pin->gpio->OTYPER, 1, pin->pin, 1); +} + +void pin_into_input(pin_t *pin) { + pin_mode(pin, INPUT); +} +void pin_into_input_highspeed(pin_t *pin) { + pin_into_input(pin); + pin_into_highspeed(pin); +} + +void pin_into_alternate(pin_t *pin, uint8_t alternate) { + pin_mode(pin, ALTERNATE); +} +void pin_into_alternate_highspeed(pin_t *pin, uint8_t alternate) { + pin_into_alternate(pin, alternate); + pin_into_highspeed(pin); +} + +void pin_into_highspeed(pin_t *pin) { + pin_speed(pin, HIGH_SPEED); +} diff --git a/src/registers.c b/src/registers.c new file mode 100644 index 0000000..4c76320 --- /dev/null +++ b/src/registers.c @@ -0,0 +1,23 @@ +#include + +void reg_set_bits_pos(volatile uint32_t *reg, uint32_t data, uint8_t pos, uint8_t mask) { + *reg &= ~(mask << pos); + *reg |= (data & mask) << pos; +} + +void reg_set_bits(volatile uint32_t *reg, uint32_t data, uint8_t mask) { + *reg &= ~(mask); + *reg |= (data & mask); +} + +void reg_toggle_bits_pos(volatile uint32_t *reg, uint8_t pos, uint8_t mask) { + *reg ^= (mask << pos); +} + +void reg_toggle_bits(volatile uint32_t *reg, uint8_t mask) { + *reg ^= mask; +} + +uint32_t reg_read_bits_pos(volatile uint32_t *reg, uint8_t pos, uint8_t mask) { + return ((*reg) >> pos) & mask; +} diff --git a/src/usb_device.c b/src/usb_device.c new file mode 100644 index 0000000..307f533 --- /dev/null +++ b/src/usb_device.c @@ -0,0 +1,103 @@ +#include "usb_device.h" +#include +#include +#include + +/* USB_OTG_GlobalTypeDef */ + +usb_device_t* usb1_device; + +void* usb_device_init(void* peripheral_address, usb_class_t* class, void* buffer) +{ + if (buffer == NULL) { + buffer = (void*)malloc(sizeof(usb_device_t)); + } + + usb_device_t* device = (usb_device_t*)buffer; + + device->core = peripheral_address; + device->device = peripheral_address + USB_OTG_DEVICE_BASE; + + usb1_device = device; + + return device; +} + +void usb_device_reset(void* device_ptr) +{ + usb_device_t* device = (usb_device_t*)device_ptr; + while ((device->core->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0); + device->core->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; + while (device->core->GRSTCTL & USB_OTG_GRSTCTL_CSRST); + while ((device->core->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0); +} + +void usb_device_clear_interrupts(void* device_ptr) +{ + usb_device_t* device = (usb_device_t*)device_ptr; + device->core->GINTSTS = 0; // clear interrupts + + // for other interrupts the rx queue has to be read +} + +void usb_device_setup(void* device_ptr) +{ + RCC->AHB1ENR |= RCC_AHB1ENR_USB1OTGHSEN | RCC_AHB1ENR_USB1OTGHSULPIEN; + + volatile uint32_t dummy; + dummy = RCC->AHB1ENR; + dummy = RCC->AHB1ENR; + + NVIC_SetPriority(OTG_FS_IRQn, 2); + NVIC_EnableIRQ(OTG_FS_IRQn); + + // 1. core initialization + usb_device_t* device = (usb_device_t*)device_ptr; + + RCC->AHB1ENR |= RCC_AHB1ENR_USB1OTGHSULPIEN | RCC_AHB1ENR_USB1OTGHSEN; + + /* PWR->CR3 |= PWR_CR3_USBREGEN; */ + /* while ((PWR->CR3 & PWR_CR3_USB33RDY) == 0); */ + + device->core->GCCFG |= USB_OTG_GCCFG_PWRDWN; + + device->core->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + + // global interrupt mask + // rx fifo non empty + // periodic tx fifo empty level + usb_device_clear_interrupts(device_ptr); + device->core->GAHBCFG = USB_OTG_GAHBCFG_GINT | USB_OTG_GAHBCFG_TXFELVL | USB_OTG_GAHBCFG_HBSTLEN_2; + + // hnp capable, srp capable, otg hs timeout, usb turnaround + // TODO: based on enumeration speed set TOCAL - fs timeout calibration + device->core->GUSBCFG = USB_OTG_GUSBCFG_FDMOD | USB_OTG_GUSBCFG_ULPIEVBUSI | USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_TRDT_3 | USB_OTG_GUSBCFG_TRDT_2; + + // unmask otg interrupt mask + device->core->GINTMSK |= USB_OTG_GINTMSK_OTGINT | USB_OTG_GINTMSK_MMISM; + + // device initialization + + // descdma, device speed, non-zero-length status out handshake, periodic frame interval + device->device->DCFG = 0; + + // TODO device threshold control register IF DMA + + usb_device_reset(device_ptr); + + // sdis bit + device->device->DCTL = ~(USB_OTG_DCTL_SDIS); + + // unmask interrupts usb reset, enumeration done, early suspend, usb suspend, sof + device->core->GINTMSK |= USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_RSTDEM | USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ESUSPM | USB_OTG_GINTMSK_SOFM; + + // wait for usbrst interrupt - the reset + while (((device->core->GINTSTS) & USB_OTG_GINTSTS_USBRST) == 0) {} + + // wait for enumdne interrupt - end of reset + while (((device->core->GINTSTS) & USB_OTG_GINTSTS_ENUMDNE) == 0) {} +} + +void otg_hs_handler(void) { + +} -- 2.48.1