~ruther/stm32h747i-disco-usb-image-viewer

f8fd8e9ffbfd742e4c25f499824323766c41bb7d — Rutherther 5 months ago cedafa2
chore: update pin, exti, delay
9 files changed, 107 insertions(+), 115 deletions(-)

M Makefile
M include/exti.h
M include/pin.h
M include/usb_device.h
M src/delay.c
M src/exti.c
M src/main.c
M src/pin.c
M src/usb_device.c
M Makefile => Makefile +1 -1
@@ 27,7 27,7 @@ CFLAGS=-I$(INCDIR) \
				-Ilibs/CMSIS_6/CMSIS/Core/Include \
				-Ilibs/cmsis_device_h7/Include \
				-mthumb -mcpu=$(CPU) --specs=nano.specs -g \
				-DCORE_CM7
				-DCORE_CM7 -DSTM32H747xx
LDFLAGS=-T$(DEVICEDIR)/linker_script.ld

CC=arm-none-eabi-gcc

M include/exti.h => include/exti.h +19 -28
@@ 1,5 1,5 @@
#include <stdint.h>
#include <stm32h747xx.h>
#include <stm32h7xx.h>

#ifndef EXTI_H
#define EXTI_H


@@ 7,38 7,29 @@
typedef struct {
  EXTI_TypeDef* exti;
  SYSCFG_TypeDef* syscfg;
  uint8_t line;
} 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);
typedef enum {
  EXTI_GPIOA = 0,
  EXTI_GPIOB = 1,
  EXTI_GPIOC = 2,
  EXTI_GPIOD = 2,
  /// ... TODO
} EXTI_external_gpio_t;

void exti_init(exti_t* exti, uint8_t line, EXTI_TypeDef* exti_periph, SYSCFG_TypeDef* syscfg);
void exti_external_interrupt(exti_t* exti, uint8_t gpio);

// Only 21 positions are now supported. This is too hard for other ones.
void exti_rising_interrupt(exti_t* exti);
void exti_falling_interrupt(exti_t* exti);
void exti_disable_interrupt(exti_t* exti);
void exti_enable_interrupt(exti_t *exti);

/**
 * @brief Set the exti line to send an interrupt on rising edge.
 * @details Valid for external EXTI interrupts. The interrupt will be triggered on rising interrupt
 * @param[in,out] exti The exti line descriptor
 */
void exti_rising_interrupt(exti_t* exti, uint8_t line);

/**
 * @brief Set the exti line to send an interrupt on falling edge.
 * @details Valid for external EXTI interrupts. The interrupt will be triggered on falling interrupt
 * @param[in,out] exti The exti line descriptor
 */
void exti_falling_interrupt(exti_t* exti, uint8_t line);

/**
 * @brief Mask the interrupt for given exti line.
 * @details Description
 * @param[in,out] exti The exti line descriptor
 */
void exti_disable_interrupt(exti_t* exti, uint8_t line);

/**
 * @brief Enable the nvic interrupt
 * @param[in,out] exti The exti line descriptor
 */
void exti_nvic_setup(exti_t* exti, uint8_t line);

uint32_t exti_is_interrupt(exti_t* exti);
void exti_clear_interrupt(exti_t* exti);

#endif // EXTI_H

M include/pin.h => include/pin.h +2 -8
@@ 1,6 1,6 @@
#include <stdlib.h>
#include <stdint.h>
#include <stm32h747xx.h>
#include <stm32h7xx.h>

#ifndef PIN_H
#define PIN_H


@@ 31,13 31,7 @@ typedef enum {
  VERY_HIGH_SPEED
} pin_speedmode_t;

/**
 * @brief Allocate a pin for given gpio.
 * @param[in,out] gpio The address for the gpio, like GPIOA
 * @param[in] pin Location of the pin, ie. for GPIOA2 use 2
 * @return Description
 */
pin_t* pin_init(GPIO_TypeDef* gpio, uint8_t pin);
void pin_init(pin_t* pin, GPIO_TypeDef* gpio, uint8_t pin_index);

void pin_mode(pin_t* pin, pin_mode_t mode);
void pin_pull(pin_t* pin, pin_pullmode_t mode);

M include/usb_device.h => include/usb_device.h +2 -2
@@ 12,12 12,12 @@ typedef enum {
  // error states first so they are lowest
  CONTROL_ERROR = -4,                                        /**< There was an error on the control interface. The device doesn't know how to proceed. */
  UNKNOWN_CONTROL_COMMAND = -4,                              /**< An unknown control command has been received. The device doesn't know how to proceed. */
  ERROR = -3,                                                /**< An unspecified error. */
  USB_DEV_ERROR = -3,                                                /**< An unspecified error. */
  UNKNOWN_INTERRUPT = -2,                                    /**< There was an unknown interrupt. This should not occur as all interrupts should be handled. */
  OTG_ERROR = -1,                                            /**< There was an interrupt from otg / error from otg. Otg is not used, so this is not supposed to happen. */

  INIT = 0,                                                  /**< The device has just been created. */
  RESET = 1,                                                 /**< Received a reset from the usb host. */
  USB_DEV_RESET = 1,                                                 /**< Received a reset from the usb host. */
  RESET_DONE = 2,                                            /**< The reset from the host is over. */
  SET_ADDRESS_RCVD = 3,                                      /**< Set address has been received and set to the register. */
  ENUMERATED = 4,                                            /**< The device has received SET_CONFIGURATION command, endpoints were configured. */

M src/delay.c => src/delay.c +1 -1
@@ 1,5 1,5 @@
#include "delay.h"
#include <stm32h747xx.h>
#include <stm32h7xx.h>

void systick_configure() {
  SysTick->LOAD = SYSTICK_LOAD;

M src/exti.c => src/exti.c +29 -24
@@ 1,41 1,36 @@
#include <stdint.h>
#include <stdlib.h>

#include <stm32h7xx.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_init(exti_t* exti, uint8_t line, EXTI_TypeDef *exti_periph, SYSCFG_TypeDef *syscfg) {
  exti->exti = exti_periph;
  exti->syscfg = syscfg;
  exti->line = line;
}

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;
void exti_external_interrupt(exti_t *exti, uint8_t gpio) {
  uint8_t index = exti->line >> 2;
  uint8_t pos = (exti->line & 0x3) * 4;
  volatile uint32_t *exticr = exti->syscfg->EXTICR;
  reg_write_bits_pos(exticr + index, gpio, pos, 0x0F);
}

void exti_rising_interrupt(exti_t *exti, uint8_t line) {
  reg_write_bits_pos(&exti->exti->RTSR1, 1, line, 1);
  reg_write_bits_pos(&exti->exti->FTSR1, 0, line, 1);
  reg_write_bits_pos(&exti->exti->IMR1, 1, line, 1);
void exti_rising_interrupt(exti_t *exti) {
  reg_write_bits_pos(&exti->exti->RTSR1, 1, exti->line, 1);
  reg_write_bits_pos(&exti->exti->FTSR1, 0, exti->line, 1);
  reg_write_bits_pos(&exti->exti->IMR1, 1, exti->line, 1);
}

void exti_falling_interrupt(exti_t *exti, uint8_t line) {
  reg_write_bits_pos(&exti->exti->FTSR1, 1, line, 1);
  reg_write_bits_pos(&exti->exti->RTSR1, 0, line, 1);
  reg_write_bits_pos(&exti->exti->IMR1, 1, line, 1);
void exti_falling_interrupt(exti_t *exti) {
  reg_write_bits_pos(&exti->exti->FTSR1, 1, exti->line, 1);
  reg_write_bits_pos(&exti->exti->RTSR1, 0, exti->line, 1);
}

void exti_disable_interrupt(exti_t *exti, uint8_t line) {
  reg_write_bits_pos(&exti->exti->IMR1, 0, line, 1);
void exti_disable_interrupt(exti_t *exti) {
  reg_write_bits_pos(&exti->exti->IMR1, 0, exti->line, 1);
}

IRQn_Type exti_irq_idx(uint8_t line) {


@@ 68,8 63,18 @@ IRQn_Type exti_irq_idx(uint8_t line) {
  }
}

void exti_nvic_setup(exti_t *exti, uint8_t line) {
  IRQn_Type idx = exti_irq_idx(line);
void exti_enable_interrupt(exti_t *exti) {
  reg_write_bits_pos(&exti->exti->IMR1, 1, exti->line, 1);

  IRQn_Type idx = exti_irq_idx(exti->line);
  NVIC_SetPriority(idx, 2);
  NVIC_EnableIRQ(idx);
}

uint32_t exti_is_interrupt(exti_t *exti) {
  return exti->exti->PR1 & (EXTI_PR1_PR0 << exti->line);
}

void exti_clear_interrupt(exti_t *exti) {
  exti->exti->PR1 |= (EXTI_PR1_PR0 << exti->line);
}

M src/main.c => src/main.c +45 -41
@@ 102,21 102,22 @@ void main()
  dummy = RCC->AHB4ENR;

  // Pins init
  pin_t* led1 = pin_init(LED1_GPIO, LED1_PIN);
  pin_into_output_pushpull(led1);
  pin_toggle(led1);
  pin_toggle(led1);
  pin_t led1;
  pin_init(&led1, LED1_GPIO, LED1_PIN);
  pin_into_output_pushpull(&led1);
  pin_toggle(&led1);
  pin_toggle(&led1);

  // pc13 input - wakeup button
  pin_t* wkup = pin_init(GPIOC, 13);
  pin_into_input(wkup);

  exti_t* exti = exti_init(EXTI, SYSCFG);
  //                        exti13  pc
  exti_external_interrupt(exti, 13, 2);
  exti_rising_interrupt(exti, 13);

  exti_nvic_setup(exti, 13);
  pin_t wkup;
  pin_init(&wkup, GPIOC, 13);
  pin_into_input(&wkup);

  exti_t exti_wkup;
  exti_init(&exti_wkup, 13, EXTI, SYSCFG);
  exti_external_interrupt(&exti_wkup, EXTI_GPIOC);
  exti_rising_interrupt(&exti_wkup);
  exti_enable_interrupt(&exti_wkup);
  /* NVIC_SetPriority(EXTI15_10_IRQn, 2); */
  /* NVIC_EnableIRQ(EXTI15_10_IRQn); */



@@ 124,36 125,39 @@ void main()

  // TODO: ULPI inputs to alternate mode...

  pin_t* ulpi_ck = pin_init(GPIOA, 5);
  pin_t* ulpi_stp = pin_init(GPIOC, 0);
  pin_t* ulpi_dir = pin_init(GPIOI, 11);
  pin_t* ulpi_nxt = pin_init(GPIOH, 4);

  pin_t* ulpi_d0 = pin_init(GPIOA, 3);
  pin_t* ulpi_d1 = pin_init(GPIOB, 0);
  pin_t* ulpi_d2 = pin_init(GPIOB, 1);
  pin_t* ulpi_d3 = pin_init(GPIOB, 10);
  pin_t* ulpi_d4 = pin_init(GPIOB, 11);
  pin_t* ulpi_d5 = pin_init(GPIOB, 12);
  pin_t* ulpi_d6 = pin_init(GPIOB, 13);
  pin_t* ulpi_d7 = pin_init(GPIOB, 5);
  pin_t* otg_hs_overcurrent = pin_init(GPIOJ, 1);

  pin_into_alternate_highspeed(ulpi_ck, 10);
  pin_into_alternate_highspeed(ulpi_stp, 10);
  pin_into_alternate_highspeed(ulpi_dir, 10);
  pin_into_alternate_highspeed(ulpi_nxt, 10);
  pin_into_alternate_highspeed(ulpi_d0, 10);
  pin_into_alternate_highspeed(ulpi_d1, 10);
  pin_into_alternate_highspeed(ulpi_d2, 10);
  pin_into_alternate_highspeed(ulpi_d3, 10);
  pin_into_alternate_highspeed(ulpi_d4, 10);
  pin_into_alternate_highspeed(ulpi_d5, 10);
  pin_into_alternate_highspeed(ulpi_d6, 10);
  pin_into_alternate_highspeed(ulpi_d7, 10);
  pin_t ulpi_clk, ulpi_stp, ulpi_dir, ulpi_nxt,
    ulpi_d0, ulpi_d1, ulpi_d2, ulpi_d3, ulpi_d4,
    ulpi_d5, ulpi_d6, ulpi_d7, otg_hs_overcurrent;
  pin_init(&ulpi_clk, GPIOA, 5);
  pin_init(&ulpi_stp, GPIOC, 0);
  pin_init(&ulpi_dir, GPIOI, 11);
  pin_init(&ulpi_nxt, GPIOH, 4);

  pin_init(&ulpi_d0, GPIOA, 3);
  pin_init(&ulpi_d1, GPIOB, 0);
  pin_init(&ulpi_d2, GPIOB, 1);
  pin_init(&ulpi_d3, GPIOB, 10);
  pin_init(&ulpi_d4, GPIOB, 11);
  pin_init(&ulpi_d5, GPIOB, 12);
  pin_init(&ulpi_d6, GPIOB, 13);
  pin_init(&ulpi_d7, GPIOB, 5);
  pin_init(&otg_hs_overcurrent, GPIOJ, 1);

  pin_into_alternate_highspeed(&ulpi_clk, 10);
  pin_into_alternate_highspeed(&ulpi_stp, 10);
  pin_into_alternate_highspeed(&ulpi_dir, 10);
  pin_into_alternate_highspeed(&ulpi_nxt, 10);
  pin_into_alternate_highspeed(&ulpi_d0, 10);
  pin_into_alternate_highspeed(&ulpi_d1, 10);
  pin_into_alternate_highspeed(&ulpi_d2, 10);
  pin_into_alternate_highspeed(&ulpi_d3, 10);
  pin_into_alternate_highspeed(&ulpi_d4, 10);
  pin_into_alternate_highspeed(&ulpi_d5, 10);
  pin_into_alternate_highspeed(&ulpi_d6, 10);
  pin_into_alternate_highspeed(&ulpi_d7, 10);

  // TODO: ?
  pin_into_input_highspeed(otg_hs_overcurrent);
  pin_into_input_highspeed(&otg_hs_overcurrent);

  void *usb_dev = usb_device_init(USB_OTG_HS1, &USB_CLASS_CDC_ACM,
                                  0x1234, 0x1111, "Frantisek Bohacek",

M src/pin.c => src/pin.c +4 -6
@@ 2,13 2,11 @@
#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));
void pin_init(pin_t* pin, GPIO_TypeDef *gpio, uint8_t pin_index) {
  pin->gpio = gpio;
  pin->pin = pin_index;

  pin_periph->gpio = gpio;
  pin_periph->pin = pin;

  return pin_periph;
  return pin;
}

void pin_mode(pin_t *pin, pin_mode_t mode) {

M src/usb_device.c => src/usb_device.c +4 -4
@@ 401,7 401,7 @@ void usb_handle_endpoint_in_int(usb_device_t* device) {
  uint8_t ep_id = usb_daint_get_endpoint_number(reg_read_bits_pos(&device->device->DAINT, USB_OTG_DAINT_IEPINT_Pos, 0xFFFF));

  if (ep_id == 0xFF) {
    device->state = ERROR;
    device->state = USB_DEV_ERROR;
    return;
  }



@@ 432,7 432,7 @@ void usb_handle_endpoint_in_int(usb_device_t* device) {
    // NAK effective. Okay, ack, go on.
    reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_INEPNE);
  } else if (interrupt_reg & USB_OTG_DIEPINT_INEPNM) {
    device->state = ERROR; // data on top of TxFIFO belong to endpoint other
    device->state = USB_DEV_ERROR; // data on top of TxFIFO belong to endpoint other
    // than the one for which in token was received.
    reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_INEPNM);
  } else if (interrupt_reg & USB_OTG_DIEPINT_ITTXFE) {


@@ 475,7 475,7 @@ void usb_handle_endpoint_out_int(usb_device_t* device) {
  uint8_t ep_id = usb_daint_get_endpoint_number(reg_read_bits_pos(&device->device->DAINT, USB_OTG_DAINT_OEPINT_Pos, 0xFFFF));

  if (ep_id == 0xFF) {
    device->state = ERROR;
    device->state = USB_DEV_ERROR;
    return;
  }



@@ 578,7 578,7 @@ void otg_hs_handler(void) {
    // 3 packets to receive as setup
    reg_write_bits_pos(&device->out->DOEPTSIZ, 3, USB_OTG_DOEPTSIZ_STUPCNT_Pos, 3);

    device->state = RESET;
    device->state = USB_DEV_RESET;
    // clear it
    reg_set_bits(&device->core->GINTSTS,  USB_OTG_GINTSTS_USBRST);


Do not follow this link