Test of ADC (+ lots of unrelated code)
This commit is contained in:
parent
25422326fe
commit
614369f83b
1 changed files with 585 additions and 0 deletions
585
src/analog-test/test.c
Normal file
585
src/analog-test/test.c
Normal file
|
@ -0,0 +1,585 @@
|
|||
/*
|
||||
* USB-RS485 Switch -- Hardware Testing
|
||||
*
|
||||
* (c) 2022 Martin Mareš <mj@ucw.cz>
|
||||
*/
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#include <libopencm3/cm3/cortex.h>
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/cm3/systick.h>
|
||||
#include <libopencm3/cm3/scb.h>
|
||||
#include <libopencm3/stm32/adc.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/spi.h>
|
||||
#include <libopencm3/stm32/timer.h>
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
#include <libopencm3/usb/dfu.h>
|
||||
#include <libopencm3/usb/usbd.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*** Hardware init ***/
|
||||
|
||||
static void clock_init(void)
|
||||
{
|
||||
rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]);
|
||||
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
rcc_periph_clock_enable(RCC_GPIOB);
|
||||
rcc_periph_clock_enable(RCC_GPIOC);
|
||||
rcc_periph_clock_enable(RCC_USART1);
|
||||
rcc_periph_clock_enable(RCC_USART2);
|
||||
rcc_periph_clock_enable(RCC_USART3);
|
||||
rcc_periph_clock_enable(RCC_SPI2);
|
||||
// rcc_periph_clock_enable(RCC_TIM4);
|
||||
rcc_periph_clock_enable(RCC_ADC1);
|
||||
rcc_periph_clock_enable(RCC_AFIO);
|
||||
|
||||
rcc_periph_reset_pulse(RST_GPIOA);
|
||||
rcc_periph_reset_pulse(RST_GPIOB);
|
||||
rcc_periph_reset_pulse(RST_GPIOC);
|
||||
rcc_periph_reset_pulse(RST_USART1);
|
||||
rcc_periph_reset_pulse(RST_USART2);
|
||||
rcc_periph_reset_pulse(RST_USART3);
|
||||
rcc_periph_reset_pulse(RST_SPI2);
|
||||
// rcc_periph_reset_pulse(RST_TIM4);
|
||||
rcc_periph_reset_pulse(RST_ADC1);
|
||||
rcc_periph_reset_pulse(RST_AFIO);
|
||||
}
|
||||
|
||||
static void gpio_init(void)
|
||||
{
|
||||
// PA0 = VCC sense -> ADC12_IN0
|
||||
// PA1 = 5V sense -> ADC12_IN1
|
||||
// PA2 = TXD2 (debug)
|
||||
// PA3 = RXD2
|
||||
// PA4 = SPI1_SS* (jumpers)
|
||||
// PA5 = SPI1_SCK
|
||||
// PA6 = SPI1_MISO
|
||||
// PA7 = SPI1_MOSI
|
||||
// PA8 = SPI2_OE*
|
||||
// PA9 = TXD1
|
||||
// PA10 = RXD1
|
||||
// PA11 = USB_DN
|
||||
// PA12 = USB_DP
|
||||
// PA13 + PA14 = programming interface
|
||||
// PA15 = GPIO3
|
||||
|
||||
// PB0 = GPIO0 = ADuM4160 PIN (USB upstream enable)
|
||||
// PB1 = I_SENSE -> ADC12_IN9
|
||||
// PB2 = unused
|
||||
// PB3 = I_SEN_A
|
||||
// PB4 = I_SEN_B
|
||||
// PB5 = I_SEN_C
|
||||
// PB6 = I2C1_SCL
|
||||
// PB7 = I2C1_SDA
|
||||
// PB8 = GPIO1
|
||||
// PB9 = GPIO2
|
||||
// PB10 = TXD3
|
||||
// PB11 = RXD3
|
||||
// PB12 = SPI2_STROBE
|
||||
// PB13 = SPI2_SCK
|
||||
// PB14 = SPI2_MISO
|
||||
// PB15 = SPI2_MOSI
|
||||
|
||||
// PC13 = debugging LED *
|
||||
// PC14 = unused
|
||||
// PC15 = unused
|
||||
|
||||
// Switch JTAG off to free up pins
|
||||
gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON, 0);
|
||||
}
|
||||
|
||||
static void debug_init(void)
|
||||
{
|
||||
// PC13 = debugging LED à la BluePill
|
||||
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
|
||||
gpio_clear(GPIOC, GPIO13);
|
||||
|
||||
// USART2: Debugging console
|
||||
// PA2 = TXD2
|
||||
// PA3 = RXD2
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO2);
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO3);
|
||||
|
||||
usart_set_baudrate(USART2, 115200);
|
||||
usart_set_databits(USART2, 8);
|
||||
usart_set_stopbits(USART2, USART_STOPBITS_1);
|
||||
usart_set_mode(USART2, USART_MODE_TX_RX);
|
||||
usart_set_parity(USART2, USART_PARITY_NONE);
|
||||
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
|
||||
|
||||
usart_enable(USART2);
|
||||
}
|
||||
|
||||
/*** System ticks ***/
|
||||
|
||||
static volatile u32 ms_ticks;
|
||||
|
||||
void sys_tick_handler(void)
|
||||
{
|
||||
ms_ticks++;
|
||||
}
|
||||
|
||||
static void tick_init(void)
|
||||
{
|
||||
systick_set_frequency(1000, CPU_CLOCK_MHZ * 1000000);
|
||||
systick_counter_enable();
|
||||
systick_interrupt_enable();
|
||||
}
|
||||
|
||||
static void delay_ms(uint ms)
|
||||
{
|
||||
u32 start_ticks = ms_ticks;
|
||||
while (ms_ticks - start_ticks < ms)
|
||||
;
|
||||
}
|
||||
|
||||
/*** Shift registers ***/
|
||||
|
||||
static void reg_init(void)
|
||||
{
|
||||
// Pins: PA8=OE*, PB12=STROBE, PB13=SCK, PB14=MISO, PB15=MOSI
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO8);
|
||||
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
|
||||
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO13 | GPIO15);
|
||||
gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO14);
|
||||
|
||||
gpio_set(GPIOA, GPIO8);
|
||||
gpio_clear(GPIOB, GPIO12);
|
||||
|
||||
spi_reset(SPI2);
|
||||
|
||||
/*
|
||||
* Set up SPI in Master mode with:
|
||||
*
|
||||
* - baud rate: 1/64 of peripheral clock frequency
|
||||
* - clock polarity: idle high
|
||||
* - clock phase: data valid on 2nd clock pulse
|
||||
* - data frame format: 8-bit, MSB first
|
||||
*/
|
||||
spi_init_master(SPI2, SPI_CR1_BAUDRATE_FPCLK_DIV_64, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
|
||||
SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST);
|
||||
|
||||
// NSS will be managed by software and always held high
|
||||
spi_enable_software_slave_management(SPI2);
|
||||
spi_set_nss_high(SPI2);
|
||||
|
||||
spi_enable(SPI2);
|
||||
}
|
||||
|
||||
static byte reg_state[4] = { 0x88, 0x88, 0x88, 0x88 };
|
||||
|
||||
static void reg_send(void)
|
||||
{
|
||||
for (byte i=0; i<4; i++)
|
||||
spi_send(SPI2, reg_state[3-i]);
|
||||
while (SPI_SR(SPI2) & SPI_SR_BSY)
|
||||
;
|
||||
gpio_set(GPIOB, GPIO12); // strobe
|
||||
asm volatile ("nop; nop; nop; nop"); // just to be sure
|
||||
gpio_clear(GPIOB, GPIO12);
|
||||
gpio_clear(GPIOA, GPIO8); // OE*
|
||||
}
|
||||
|
||||
enum reg_flags {
|
||||
SF_RXEN_N = 8,
|
||||
SF_TXEN = 4,
|
||||
SF_PWREN = 2,
|
||||
SF_LED = 1,
|
||||
};
|
||||
|
||||
static void reg_set_flag(uint port, uint flag)
|
||||
{
|
||||
reg_state[port/2] |= (port & 1) ? flag : (flag << 4);
|
||||
}
|
||||
|
||||
static void reg_clear_flag(uint port, uint flag)
|
||||
{
|
||||
reg_state[port/2] &= ~((port & 1) ? flag : (flag << 4));
|
||||
}
|
||||
|
||||
static void reg_toggle_flag(uint port, uint flag)
|
||||
{
|
||||
reg_state[port/2] ^= (port & 1) ? flag : (flag << 4);
|
||||
}
|
||||
|
||||
/*** ADC ***/
|
||||
|
||||
static void adc_init(void)
|
||||
{
|
||||
// PA0, PA1 and PB1 are analog inputs
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0 | GPIO1);
|
||||
gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO1);
|
||||
|
||||
// PB3 to PB5 control the analog multiplexer on PB1
|
||||
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO3 | GPIO4 | GPIO5);
|
||||
|
||||
adc_power_off(ADC1);
|
||||
// ADC prescaler set by rcc_clock_setup_pll(): ADC clock = PCLK2/8 = 9 MHz
|
||||
rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV8);
|
||||
adc_disable_scan_mode(ADC1);
|
||||
adc_set_single_conversion_mode(ADC1);
|
||||
adc_set_sample_time(ADC1, ADC_CHANNEL0, ADC_SMPR_SMP_239DOT5CYC);
|
||||
adc_set_sample_time(ADC1, ADC_CHANNEL1, ADC_SMPR_SMP_239DOT5CYC);
|
||||
adc_set_sample_time(ADC1, ADC_CHANNEL9, ADC_SMPR_SMP_239DOT5CYC);
|
||||
adc_set_sample_time(ADC1, ADC_CHANNEL16, ADC_SMPR_SMP_239DOT5CYC);
|
||||
adc_set_sample_time(ADC1, ADC_CHANNEL17, ADC_SMPR_SMP_239DOT5CYC);
|
||||
adc_enable_external_trigger_regular(ADC1, ADC_CR2_EXTSEL_SWSTART);
|
||||
adc_enable_temperature_sensor();
|
||||
adc_power_on(ADC1);
|
||||
adc_reset_calibration(ADC1);
|
||||
adc_calibrate(ADC1);
|
||||
}
|
||||
|
||||
static void adc_test(void)
|
||||
{
|
||||
for (int i=0; i<4; i++) {
|
||||
uint j=0;
|
||||
switch (i) {
|
||||
case 0:
|
||||
j = ADC_CHANNEL0;
|
||||
break;
|
||||
case 1:
|
||||
j = ADC_CHANNEL1;
|
||||
break;
|
||||
case 2:
|
||||
j = ADC_CHANNEL16;
|
||||
break;
|
||||
case 3:
|
||||
j = ADC_CHANNEL17;
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t channels[] = { j };
|
||||
adc_set_regular_sequence(ADC1, 1, channels);
|
||||
|
||||
adc_start_conversion_regular(ADC1);
|
||||
|
||||
while (! adc_eoc(ADC1));
|
||||
uint reg16 = adc_read_regular(ADC1);
|
||||
debug_printf("ADC %d = %d\n", i, reg16);
|
||||
}
|
||||
|
||||
for (int i=0; i<8; i++) {
|
||||
gpio_clear(GPIOB, GPIO3 | GPIO4 | GPIO5);
|
||||
gpio_set(GPIOB, i << 3);
|
||||
delay_ms(5);
|
||||
|
||||
uint8_t channels[] = { ADC_CHANNEL9 };
|
||||
adc_set_regular_sequence(ADC1, 1, channels);
|
||||
|
||||
adc_start_conversion_regular(ADC1);
|
||||
|
||||
while (! adc_eoc(ADC1));
|
||||
uint reg16 = adc_read_regular(ADC1);
|
||||
debug_printf("SENSE %d = %d\n", i, reg16);
|
||||
}
|
||||
}
|
||||
|
||||
/*** Loopback between ports 1 and 5 ***/
|
||||
|
||||
static void loop_init(void)
|
||||
{
|
||||
// USART1: Ports 1 to 4
|
||||
// PA9 = TXD1
|
||||
// PA10 = RXD1
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO9);
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO10);
|
||||
|
||||
usart_set_baudrate(USART1, 115200);
|
||||
usart_set_databits(USART1, 8);
|
||||
usart_set_stopbits(USART1, USART_STOPBITS_1);
|
||||
usart_set_mode(USART1, USART_MODE_TX_RX);
|
||||
usart_set_parity(USART1, USART_PARITY_NONE);
|
||||
usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);
|
||||
|
||||
usart_enable(USART1);
|
||||
|
||||
// USART3: Ports 5 to 9
|
||||
// PB10 = TXD3
|
||||
// PB11 = RXD3
|
||||
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO10);
|
||||
gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO11);
|
||||
|
||||
usart_set_baudrate(USART3, 115200);
|
||||
usart_set_databits(USART3, 8);
|
||||
usart_set_stopbits(USART3, USART_STOPBITS_1);
|
||||
usart_set_mode(USART3, USART_MODE_TX_RX);
|
||||
usart_set_parity(USART3, USART_PARITY_NONE);
|
||||
usart_set_flow_control(USART3, USART_FLOWCONTROL_NONE);
|
||||
|
||||
usart_enable(USART3);
|
||||
|
||||
// Enable TX on port 1
|
||||
reg_set_flag(0, SF_TXEN);
|
||||
|
||||
// Enable RX on port 5
|
||||
reg_clear_flag(4, SF_RXEN_N);
|
||||
}
|
||||
|
||||
static void loop_recv(void)
|
||||
{
|
||||
if (usart_get_flag(USART3, USART_SR_RXNE)) {
|
||||
uint ch = usart_recv(USART3);
|
||||
debug_putc(ch);
|
||||
}
|
||||
}
|
||||
|
||||
static void loop_send(uint ch)
|
||||
{
|
||||
usart_send_blocking(USART1, ch);
|
||||
}
|
||||
|
||||
/*** USB ***/
|
||||
|
||||
#define USB_RS485_USB_VENDOR 0x4242
|
||||
#define USB_RS485_USB_PRODUCT 0x000b
|
||||
#define USB_RS485_USB_VERSION 1
|
||||
|
||||
static usbd_device *usbd_dev;
|
||||
|
||||
enum usb_string {
|
||||
STR_MANUFACTURER = 1,
|
||||
STR_PRODUCT,
|
||||
STR_SERIAL,
|
||||
};
|
||||
|
||||
static char usb_serial_number[13];
|
||||
|
||||
static const char *usb_strings[] = {
|
||||
"United Computer Wizards",
|
||||
"USB-RS485 Switch",
|
||||
usb_serial_number,
|
||||
};
|
||||
|
||||
static const struct usb_device_descriptor device = {
|
||||
.bLength = USB_DT_DEVICE_SIZE,
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = 0xFF,
|
||||
.bDeviceSubClass = 0,
|
||||
.bDeviceProtocol = 0,
|
||||
.bMaxPacketSize0 = 64,
|
||||
.idVendor = USB_RS485_USB_VENDOR,
|
||||
.idProduct = USB_RS485_USB_PRODUCT,
|
||||
.bcdDevice = USB_RS485_USB_VERSION,
|
||||
.iManufacturer = STR_MANUFACTURER,
|
||||
.iProduct = STR_PRODUCT,
|
||||
.iSerialNumber = STR_SERIAL,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
static const struct usb_endpoint_descriptor endpoints[] = {{
|
||||
// Bulk end-point for sending LED values
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x01,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 1,
|
||||
}};
|
||||
|
||||
static const struct usb_interface_descriptor iface = {
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = 0xFF,
|
||||
.bInterfaceSubClass = 0,
|
||||
.bInterfaceProtocol = 0,
|
||||
.iInterface = 0,
|
||||
.endpoint = endpoints,
|
||||
};
|
||||
|
||||
static const struct usb_dfu_descriptor dfu_function = {
|
||||
.bLength = sizeof(struct usb_dfu_descriptor),
|
||||
.bDescriptorType = DFU_FUNCTIONAL,
|
||||
.bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH,
|
||||
.wDetachTimeout = 255,
|
||||
.wTransferSize = 1024,
|
||||
.bcdDFUVersion = 0x0100,
|
||||
};
|
||||
|
||||
static const struct usb_interface_descriptor dfu_iface = {
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 1,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 0,
|
||||
.bInterfaceClass = 0xFE,
|
||||
.bInterfaceSubClass = 1,
|
||||
.bInterfaceProtocol = 1,
|
||||
.iInterface = 0,
|
||||
|
||||
.extra = &dfu_function,
|
||||
.extralen = sizeof(dfu_function),
|
||||
};
|
||||
|
||||
static const struct usb_interface ifaces[] = {{
|
||||
.num_altsetting = 1,
|
||||
.altsetting = &iface,
|
||||
}, {
|
||||
.num_altsetting = 1,
|
||||
.altsetting = &dfu_iface,
|
||||
}};
|
||||
|
||||
static const struct usb_config_descriptor config = {
|
||||
.bLength = USB_DT_CONFIGURATION_SIZE,
|
||||
.bDescriptorType = USB_DT_CONFIGURATION,
|
||||
.wTotalLength = 0,
|
||||
.bNumInterfaces = 2,
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = 0,
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 100, // multiplied by 2 mA
|
||||
.interface = ifaces,
|
||||
};
|
||||
|
||||
static byte usb_configured;
|
||||
static uint8_t usbd_control_buffer[64];
|
||||
|
||||
static void dfu_detach_complete(usbd_device *dev UNUSED, struct usb_setup_data *req UNUSED)
|
||||
{
|
||||
// Reset to bootloader, which implements the rest of DFU
|
||||
debug_printf("Switching to DFU\n");
|
||||
debug_flush();
|
||||
scb_reset_core();
|
||||
}
|
||||
|
||||
static enum usbd_request_return_codes dfu_control_cb(usbd_device *dev UNUSED,
|
||||
struct usb_setup_data *req,
|
||||
uint8_t **buf UNUSED,
|
||||
uint16_t *len UNUSED,
|
||||
void (**complete)(usbd_device *dev, struct usb_setup_data *req))
|
||||
{
|
||||
if (req->bmRequestType != 0x21 || req->bRequest != DFU_DETACH)
|
||||
return USBD_REQ_NOTSUPP;
|
||||
|
||||
*complete = dfu_detach_complete;
|
||||
return USBD_REQ_HANDLED;
|
||||
}
|
||||
|
||||
static byte usb_rx_buf[64];
|
||||
|
||||
static void ep01_cb(usbd_device *dev, uint8_t ep UNUSED)
|
||||
{
|
||||
// We received a frame from the USB host
|
||||
uint len = usbd_ep_read_packet(dev, 0x01, usb_rx_buf, sizeof(usb_rx_buf));
|
||||
debug_printf("USB: Host sent %u bytes\n", len);
|
||||
}
|
||||
|
||||
static void set_config_cb(usbd_device *dev, uint16_t wValue UNUSED)
|
||||
{
|
||||
usbd_register_control_callback(
|
||||
dev,
|
||||
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
|
||||
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
|
||||
dfu_control_cb);
|
||||
usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, ep01_cb);
|
||||
usb_configured = 1;
|
||||
}
|
||||
|
||||
static void reset_cb(void)
|
||||
{
|
||||
debug_printf("USB: Reset\n");
|
||||
usb_configured = 0;
|
||||
}
|
||||
|
||||
static volatile bool usb_event_pending;
|
||||
|
||||
void usb_lp_can_rx0_isr(void)
|
||||
{
|
||||
/*
|
||||
* We handle USB in the main loop to avoid race conditions between
|
||||
* USB interrupts and other code. However, we need an interrupt to
|
||||
* up the main loop from sleep.
|
||||
*
|
||||
* We set up only the low-priority ISR, because high-priority ISR handles
|
||||
* only double-buffered bulk transfers and isochronous transfers.
|
||||
*/
|
||||
nvic_disable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
|
||||
usb_event_pending = 1;
|
||||
}
|
||||
|
||||
static void usb_init(void)
|
||||
{
|
||||
// Simulate USB disconnect
|
||||
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO0);
|
||||
gpio_clear(GPIOB, GPIO0);
|
||||
delay_ms(100);
|
||||
gpio_set(GPIOB, GPIO0);
|
||||
|
||||
usbd_dev = usbd_init(
|
||||
&st_usbfs_v1_usb_driver,
|
||||
&device,
|
||||
&config,
|
||||
usb_strings,
|
||||
ARRAY_SIZE(usb_strings),
|
||||
usbd_control_buffer,
|
||||
sizeof(usbd_control_buffer)
|
||||
);
|
||||
usbd_register_reset_callback(usbd_dev, reset_cb);
|
||||
usbd_register_set_config_callback(usbd_dev, set_config_cb);
|
||||
usb_event_pending = 1;
|
||||
}
|
||||
|
||||
/*** Main ***/
|
||||
|
||||
int main(void)
|
||||
{
|
||||
clock_init();
|
||||
gpio_init();
|
||||
debug_init();
|
||||
reg_init();
|
||||
tick_init();
|
||||
adc_init();
|
||||
usb_init();
|
||||
loop_init();
|
||||
|
||||
debug_printf("Lisak je lisak...\n");
|
||||
|
||||
byte t = 0;
|
||||
u32 last_blink = 0;
|
||||
|
||||
for (;;) {
|
||||
if (ms_ticks - last_blink >= 250) {
|
||||
debug_led_toggle();
|
||||
reg_clear_flag(t, SF_LED);
|
||||
t = (t+1) & 7;
|
||||
reg_set_flag(t, SF_LED);
|
||||
reg_send();
|
||||
last_blink = ms_ticks;
|
||||
}
|
||||
|
||||
if (usart_get_flag(USART2, USART_SR_RXNE)) {
|
||||
uint ch = usart_recv(USART2);
|
||||
debug_putc(ch);
|
||||
if (ch >= '0' && ch <= '7') {
|
||||
reg_toggle_flag(ch - '0', SF_PWREN);
|
||||
reg_send();
|
||||
} else if (ch == 'a') {
|
||||
adc_test();
|
||||
} else {
|
||||
loop_send(ch);
|
||||
}
|
||||
}
|
||||
|
||||
loop_recv();
|
||||
|
||||
if (usb_event_pending) {
|
||||
usbd_poll(usbd_dev);
|
||||
usb_event_pending = 0;
|
||||
nvic_clear_pending_irq(NVIC_USB_LP_CAN_RX0_IRQ);
|
||||
nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
|
||||
}
|
||||
|
||||
wait_for_interrupt();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue