A include/exti.h => include/exti.h +22 -0
@@ 0,0 1,22 @@
+#include <stdint.h>
+#include <stm32h747xx.h>
+
+#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
A include/pin.h => include/pin.h +65 -0
@@ 0,0 1,65 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stm32h747xx.h>
+
+#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
A include/registers.h => include/registers.h +12 -0
@@ 0,0 1,12 @@
+#include <stdint.h>
+
+#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
A include/usb_device.h => include/usb_device.h +29 -0
@@ 0,0 1,29 @@
+#ifndef USB_DEVICE_H
+#define USB_DEVICE_H
+
+//
+#include <stm32h747xx.h>
+
+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
A src/exti.c => src/exti.c +75 -0
@@ 0,0 1,75 @@
+#include <stdint.h>
+#include <stdlib.h>
+
+#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);
+}
A src/pin.c => src/pin.c +78 -0
@@ 0,0 1,78 @@
+#include "pin.h"
+#include "registers.h"
+#include <stdlib.h>
+
+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);
+}
A src/registers.c => src/registers.c +23 -0
@@ 0,0 1,23 @@
+#include <stdint.h>
+
+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;
+}
A src/usb_device.c => src/usb_device.c +103 -0
@@ 0,0 1,103 @@
+#include "usb_device.h"
+#include <stdlib.h>
+#include <stddef.h>
+#include <stm32h747xx.h>
+
+/* 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) {
+
+}