2 * Boiler System Bus Gateway
4 * (c) 2020 Martin Mareš <mj@ucw.cz>
10 #include <libopencm3/cm3/cortex.h>
11 #include <libopencm3/cm3/nvic.h>
12 #include <libopencm3/cm3/systick.h>
13 #include <libopencm3/cm3/scb.h>
14 #include <libopencm3/stm32/rcc.h>
15 #include <libopencm3/stm32/desig.h>
16 #include <libopencm3/stm32/gpio.h>
17 #include <libopencm3/stm32/timer.h>
18 #include <libopencm3/stm32/usart.h>
19 #include <libopencm3/usb/dfu.h>
20 #include <libopencm3/usb/usbd.h>
24 /*** Hardware init ***/
26 static void clock_init(void)
28 rcc_clock_setup_in_hse_8mhz_out_72mhz();
30 rcc_periph_clock_enable(RCC_GPIOA);
31 rcc_periph_clock_enable(RCC_GPIOB);
32 rcc_periph_clock_enable(RCC_GPIOC);
33 rcc_periph_clock_enable(RCC_USART1);
34 rcc_periph_clock_enable(RCC_USART3);
35 rcc_periph_clock_enable(RCC_USB);
37 rcc_periph_reset_pulse(RST_GPIOA);
38 rcc_periph_reset_pulse(RST_GPIOB);
39 rcc_periph_reset_pulse(RST_GPIOC);
40 rcc_periph_reset_pulse(RST_USART1);
41 rcc_periph_reset_pulse(RST_USART3);
42 rcc_periph_reset_pulse(RST_USB);
45 static void gpio_init(void)
47 // PA9 = TXD1 for debugging console
48 // PA10 = RXD1 for debugging console
49 gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO9);
50 gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO10);
52 // PC13 = BluePill LED
53 gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
54 gpio_clear(GPIOC, GPIO13);
56 // PB0 = yellow LED*, PB1 = green LED*
57 gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO0 | GPIO1);
58 gpio_set(GPIOB, GPIO0 | GPIO1);
60 // PB10 = TXD3 for BSB
61 // PB11 = RXD3 for BSB
62 gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, GPIO10);
63 gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO11);
66 static void usart_init(void)
68 usart_set_baudrate(USART1, 115200);
69 usart_set_databits(USART1, 8);
70 usart_set_stopbits(USART1, USART_STOPBITS_1);
71 usart_set_mode(USART1, USART_MODE_TX);
72 usart_set_parity(USART1, USART_PARITY_NONE);
73 usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);
78 /*** System ticks ***/
80 static volatile u32 ms_ticks;
82 void sys_tick_handler(void)
87 static void tick_init(void)
89 systick_set_frequency(1000, CPU_CLOCK_MHZ * 1000000);
90 systick_counter_enable();
91 systick_interrupt_enable();
94 static void delay_ms(uint ms)
96 u32 start_ticks = ms_ticks;
97 while (ms_ticks - start_ticks < ms)
101 /*** Random generator ***/
103 static u32 rng_state;
105 static u32 random_u32(void)
107 rng_state *= 2654289733;
111 static void random_init(void)
114 desig_get_unique_id(desig);
115 rng_state = desig[0] ^ desig[1] ^ desig[2];
120 #define BSB_MAX_SIZE 32
121 #define BSB_RX_TIMEOUT 10 // If no byte was received for this time, end the current frame [ms]
122 #define BSB_TX_IDLE_LINE 100 // Consider the line idle if no byte was received for this time [ms]
123 #define BSB_TX_MAX_ATTEMPTS 3
124 #define BSB_TX_WAIT_LOG 8 // base 2 log of pre-frame waiting time in ms
125 #define BSB_TX_TIMEOUT 10000 // Total time to transmit a frame including all retries and waiting for reply [ms]
126 #define BSB_REPLY_TIMEOUT 1000 // How long to wait for a reply [ms]
130 #define BSB_DEBUG(x) debug_putc(x)
132 #define BSB_DEBUG(x) do { } while (0)
136 byte rx_len; // Bytes received so far
137 byte rx_led; // Countdown to turning RX LED off
139 volatile u32 rx_timestamp; // Last byte received
141 byte tx_state; // TX_STATE_xxx
146 byte tx_result; // TX_RESULT_xxx
147 u32 tx_start_timestamp;
148 u32 tx_ticks_to_send;
149 u32 tx_end_timestamp;
150 u32 reply_type_mask; // Expected reply types (0=no reply)
152 byte rx_buf[BSB_MAX_SIZE];
153 byte tx_buf[BSB_MAX_SIZE];
156 static struct bsb_state bsb;
158 // Passing received frames and status codes to the main loop
159 static byte bsb_rx_status_and_frame[1 + BSB_MAX_SIZE];
160 static volatile byte bsb_rx_frame_len;
161 static byte bsb_tx_result;
165 TX_STATE_WAITING_FOR_IDLE_LINE,
166 TX_STATE_PRE_PACKET_DELAY,
169 TX_STATE_WAITING_FOR_REPLY,
173 static struct bsb_stats bsb_stats;
175 static void bsb_attempt_tx(void);
177 static u16 bsb_crc_update(u16 crc, byte data)
179 crc = crc ^ (data << 8);
180 for (uint i=0; i<8; i++) {
182 crc = (crc << 1) ^ 0x1021;
189 void usart3_isr(void)
191 u32 status = USART_SR(USART3);
193 if (status & USART_SR_RXNE) {
194 uint ch = ~usart_recv(USART3) & 0xff;
195 bsb.rx_timestamp = ms_ticks;
197 debug_printf(" %02x", ch);
200 if (bsb.tx_state == TX_STATE_SENDING) {
201 // We are hearing the echo of a transmitted packet, check it for collisions
202 if (status & (USART_SR_FE | USART_SR_ORE | USART_SR_NE)) {
204 bsb.tx_state = TX_STATE_COLLISION;
205 } else if (ch == bsb.tx_buf[bsb.tx_check_index++]) {
206 if (bsb.tx_check_index >= bsb.tx_len) {
208 bsb.tx_state = TX_STATE_SENT;
212 bsb.tx_state = TX_STATE_COLLISION;
216 if (status & (USART_SR_FE | USART_SR_ORE | USART_SR_NE)) {
217 bsb_stats.rx_errors++;
219 } else if (!bsb.rx_len) {
222 bsb.rx_buf[bsb.rx_len++] = ch;
223 bsb.rx_crc = bsb_crc_update(0, ch);
226 bsb_stats.rx_noise++;
230 bsb.rx_buf[bsb.rx_len++] = ch;
231 bsb.rx_crc = bsb_crc_update(bsb.rx_crc, ch);
232 if (bsb.rx_len < 4) {
233 // First three bytes: SOF, source addr, destination addr
234 } else if (bsb.rx_len == 4) {
235 // Received length byte
236 if (bsb.rx_buf[BF_LEN] < 7 || bsb.rx_buf[BF_LEN] > BSB_MAX_SIZE) {
237 bsb_stats.rx_invalid++;
241 } else if (bsb.rx_len == bsb.rx_buf[BF_LEN]) {
242 // Received a complete frame: check CRC and pass it to the main loop
244 bsb_stats.rx_bad_crc++;
247 if (bsb_rx_frame_len) {
248 // The previous one was not sent yet
249 bsb_stats.rx_overruns++;
252 bsb_rx_frame_len = bsb.rx_buf[BF_LEN];
253 memcpy(bsb_rx_status_and_frame + 1, bsb.rx_buf, bsb_rx_frame_len);
256 // Will match with expected replies in main loop
258 gpio_clear(GPIOB, GPIO1);
267 if (status & USART_SR_TXE) {
268 if (bsb.tx_state == TX_STATE_SENDING && bsb.tx_send_index < bsb.tx_len) {
270 usart_send(USART3, bsb.tx_buf[bsb.tx_send_index++] ^ 0xff);
272 usart_disable_tx_interrupt(USART3);
273 // Main loop will be notified by receiving the echo of our frame,
274 // so we do not need to wait for the "transmit complete" flag.
279 static void bsb_rx_step(void)
281 cm_disable_interrupts();
283 if (bsb.rx_len && ms_ticks - bsb.rx_timestamp >= BSB_RX_TIMEOUT) {
285 bsb_stats.rx_timeouts++;
290 gpio_set(GPIOB, GPIO1);
292 cm_enable_interrupts();
295 static void bsb_tx_step(void)
297 switch (bsb.tx_state) {
298 case TX_STATE_WAITING_FOR_IDLE_LINE:
299 if (ms_ticks - bsb.rx_timestamp < BSB_TX_IDLE_LINE)
301 bsb.tx_state = TX_STATE_PRE_PACKET_DELAY;
304 case TX_STATE_PRE_PACKET_DELAY:
305 if (ms_ticks - bsb.tx_start_timestamp > BSB_TX_TIMEOUT) {
306 bsb.tx_state = TX_STATE_OFF;
307 bsb_tx_result = TX_RESULT_TIMEOUT;
308 bsb_stats.tx_timeouts++;
311 if (ms_ticks - bsb.rx_timestamp < BSB_TX_IDLE_LINE) {
312 bsb.tx_state = TX_STATE_WAITING_FOR_IDLE_LINE;
316 if (--bsb.tx_ticks_to_send)
319 bsb.rx_timestamp = ms_ticks;
321 bsb.tx_state = TX_STATE_SENDING;
323 usart_enable_tx_interrupt(USART3);
325 case TX_STATE_SENDING:
326 // In this state, we can race with the USART interrupt handler
327 cm_disable_interrupts();
328 if (bsb.tx_state == TX_STATE_SENDING && ms_ticks - bsb.rx_timestamp >= BSB_RX_TIMEOUT) {
329 // The echo of our packet was truncated due to collision
330 bsb.tx_state = TX_STATE_COLLISION;
333 cm_enable_interrupts();
335 case TX_STATE_COLLISION:
336 bsb_stats.tx_collisions++;
340 if (!bsb.reply_type_mask) {
341 // The frame needs no reply => confirm transmission
342 bsb_stats.tx_ok_no_reply++;
343 bsb.tx_state = TX_STATE_OFF;
344 bsb_tx_result = TX_RESULT_OK;
346 bsb.tx_state = TX_STATE_WAITING_FOR_REPLY;
347 bsb.tx_end_timestamp = ms_ticks;
351 case TX_STATE_WAITING_FOR_REPLY:
352 if (ms_ticks - bsb.tx_end_timestamp > BSB_REPLY_TIMEOUT) {
353 // We did not receive a reply. Maybe the request was lost? Re-transmit it.
354 bsb_stats.tx_reply_timeouts++;
364 static void bsb_attempt_tx(void)
366 if (bsb.tx_attempts++ >= BSB_TX_MAX_ATTEMPTS) {
367 bsb.tx_state = TX_STATE_OFF;
368 bsb_tx_result = TX_RESULT_TOO_MANY_RETRIES;
372 bsb.tx_ticks_to_send = (random_u32() | 0x80000000) >> (32 - BSB_TX_WAIT_LOG - (bsb.tx_attempts-1));
374 bsb.tx_state = TX_STATE_WAITING_FOR_IDLE_LINE;
375 bsb.tx_send_index = 0;
376 bsb.tx_check_index = 0;
377 debug_printf("TX: Attempt #%u, wait for %u ms\n", bsb.tx_attempts, (uint) bsb.tx_ticks_to_send);
380 static void bsb_send(byte *buf, uint len)
382 // If a transmit is in progress, declare overrrun
383 if (bsb_tx_result != TX_RESULT_NONE) {
384 bsb_stats.tx_overruns++;
387 if (bsb.tx_state != TX_STATE_OFF) {
388 bsb_stats.tx_overruns++;
389 bsb_tx_result = TX_RESULT_OVERRUN;
393 // Check frame validity
394 if (len < 7 || len > BSB_MAX_SIZE || buf[BF_SOF] != 0xdc || buf[BF_LEN] != len) {
395 bsb_stats.tx_rejects++;
396 bsb_tx_result = TX_RESULT_MALFORMED;
400 // Detect frame type and prepare expected reply types
401 if (buf[BF_OP] == BSB_OP_QUERY) {
402 // So far, we allow only QUERY frames
403 bsb.reply_type_mask = (1 << BSB_OP_ANSWER) | (1 << BSB_OP_ERROR);
405 bsb_stats.tx_rejects++;
406 bsb_tx_result = TX_RESULT_FORBIDDEN;
410 // Fill in source address
411 buf[BF_SRC] = 0x80 + BSB_ADDR_GATEWAY;
415 for (uint i = 0; i < len - 2; i++)
416 crc = bsb_crc_update(crc, buf[i]);
417 buf[len-2] = crc >> 8;
419 debug_printf("TX: Prepared frame: type=%02x dest=%02x len=%u crc=%04x reply=%08x\n", buf[BF_OP], buf[BF_DEST], len, crc, (uint) bsb.reply_type_mask);
421 // Queue frame for transmission
422 memcpy(bsb.tx_buf, buf, len);
424 bsb.tx_start_timestamp = ms_ticks;
429 gpio_clear(GPIOB, GPIO0);
432 static void bsb_check_reply(void)
434 // Match received frame in bsb_rx_status_and_frame to expected replies
435 // and set the status in byte 0.
437 byte *frame = bsb_rx_status_and_frame + 1;
438 // XXX: This might be executed too fast, so we can still be in TX_STATE_SENT
439 if (bsb.tx_state == TX_STATE_WAITING_FOR_REPLY || bsb.tx_state == TX_STATE_SENT) {
440 if (frame[BF_DEST] == BSB_ADDR_GATEWAY &&
441 frame[BF_SRC] == bsb.tx_buf[BF_DEST] ^ 0x80 &&
443 bsb.reply_type_mask & (1 << frame[BF_OP])) {
444 debug_printf("BSB: Matched reply\n");
445 bsb.tx_state = TX_STATE_OFF;
446 bsb_stats.tx_ok_replied++;
447 bsb_rx_status_and_frame[0] = TX_RESULT_OK;
448 gpio_set(GPIOB, GPIO0); // Turn the TX LED off
453 bsb_rx_status_and_frame[0] = TX_RESULT_NONE;
456 static void bsb_init(void)
458 usart_set_baudrate(USART3, 4800);
459 usart_set_databits(USART3, 9);
460 usart_set_stopbits(USART3, USART_STOPBITS_1);
461 usart_set_mode(USART3, USART_MODE_TX_RX);
462 usart_set_parity(USART3, USART_PARITY_ODD);
463 usart_set_flow_control(USART3, USART_FLOWCONTROL_NONE);
465 usart_enable(USART3);
466 nvic_enable_irq(NVIC_USART3_IRQ);
467 usart_enable_rx_interrupt(USART3);
472 static usbd_device *usbd_dev;
475 STR_MANUFACTURER = 1,
480 static char usb_serial_number[13];
482 static const char *usb_strings[] = {
483 "United Computer Wizards",
488 static const struct usb_device_descriptor device = {
489 .bLength = USB_DT_DEVICE_SIZE,
490 .bDescriptorType = USB_DT_DEVICE,
492 .bDeviceClass = 0xFF,
493 .bDeviceSubClass = 0,
494 .bDeviceProtocol = 0,
495 .bMaxPacketSize0 = 64,
496 .idVendor = BSB_USB_VENDOR,
497 .idProduct = BSB_USB_PRODUCT,
498 .bcdDevice = BSB_USB_VERSION,
499 .iManufacturer = STR_MANUFACTURER,
500 .iProduct = STR_PRODUCT,
501 .iSerialNumber = STR_SERIAL,
502 .bNumConfigurations = 1,
505 static const struct usb_endpoint_descriptor endpoints[] = {{
506 // Bulk end-point for sending frames to BSB
507 .bLength = USB_DT_ENDPOINT_SIZE,
508 .bDescriptorType = USB_DT_ENDPOINT,
509 .bEndpointAddress = 0x01,
510 .bmAttributes = USB_ENDPOINT_ATTR_BULK,
511 .wMaxPacketSize = 64,
514 // Interrupt end-point for receiving frames from BSB
515 .bLength = USB_DT_ENDPOINT_SIZE,
516 .bDescriptorType = USB_DT_ENDPOINT,
517 .bEndpointAddress = 0x82,
518 .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
519 .wMaxPacketSize = 64,
523 static const struct usb_interface_descriptor iface = {
524 .bLength = USB_DT_INTERFACE_SIZE,
525 .bDescriptorType = USB_DT_INTERFACE,
526 .bInterfaceNumber = 0,
527 .bAlternateSetting = 0,
529 .bInterfaceClass = 0xFF,
530 .bInterfaceSubClass = 0,
531 .bInterfaceProtocol = 0,
533 .endpoint = endpoints,
536 static const struct usb_dfu_descriptor dfu_function = {
537 .bLength = sizeof(struct usb_dfu_descriptor),
538 .bDescriptorType = DFU_FUNCTIONAL,
539 .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH,
540 .wDetachTimeout = 255,
541 .wTransferSize = 1024,
542 .bcdDFUVersion = 0x0100,
545 static const struct usb_interface_descriptor dfu_iface = {
546 .bLength = USB_DT_INTERFACE_SIZE,
547 .bDescriptorType = USB_DT_INTERFACE,
548 .bInterfaceNumber = 1,
549 .bAlternateSetting = 0,
551 .bInterfaceClass = 0xFE,
552 .bInterfaceSubClass = 1,
553 .bInterfaceProtocol = 1,
556 .extra = &dfu_function,
557 .extralen = sizeof(dfu_function),
560 static const struct usb_interface ifaces[] = {{
562 .altsetting = &iface,
565 .altsetting = &dfu_iface,
568 static const struct usb_config_descriptor config = {
569 .bLength = USB_DT_CONFIGURATION_SIZE,
570 .bDescriptorType = USB_DT_CONFIGURATION,
573 .bConfigurationValue = 1,
575 .bmAttributes = 0x80,
576 .bMaxPower = 50, // multiplied by 2 mA
580 static byte usb_configured;
581 static byte usb_ep82_pending;
582 static uint8_t usbd_control_buffer[64];
584 static enum usbd_request_return_codes control_cb(
585 usbd_device *dev UNUSED,
586 struct usb_setup_data *req,
589 void (**complete)(usbd_device *dev, struct usb_setup_data *req) UNUSED)
591 if (req->bmRequestType != 0xc0 || req->bRequest != 0x00)
592 return USBD_REQ_NOTSUPP;
594 // We support reading of statistics via control requests
595 debug_printf("USB: Reading statistics\n");
596 uint n = MIN(*len, sizeof(bsb_stats));
597 memcpy(*buf, (char *) &bsb_stats, n);
600 return USBD_REQ_HANDLED;
603 static void dfu_detach_complete(usbd_device *dev UNUSED, struct usb_setup_data *req UNUSED)
605 // Reset to bootloader, which implements the rest of DFU
606 debug_printf("Switching to DFU\n");
611 static enum usbd_request_return_codes dfu_control_cb(usbd_device *dev UNUSED,
612 struct usb_setup_data *req,
613 uint8_t **buf UNUSED,
614 uint16_t *len UNUSED,
615 void (**complete)(usbd_device *dev, struct usb_setup_data *req))
617 if (req->bmRequestType != 0x21 || req->bRequest != DFU_DETACH)
618 return USBD_REQ_NOTSUPP;
620 *complete = dfu_detach_complete;
621 return USBD_REQ_HANDLED;
624 static void ep01_cb(usbd_device *dev, uint8_t ep UNUSED)
626 // We received a frame from the USB host
628 uint len = usbd_ep_read_packet(dev, 0x01, buf, sizeof(buf));
629 debug_printf("USB: Host sent %u bytes\n", len);
633 static void ep82_cb(usbd_device *dev UNUSED, uint8_t ep UNUSED)
635 // The frame was accepted by the USB host
636 debug_printf("USB: Interrupt done\n");
637 usb_ep82_pending = 0;
640 static void set_config_cb(usbd_device *dev, uint16_t wValue UNUSED)
642 usbd_register_control_callback(
647 usbd_register_control_callback(
649 USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
650 USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
652 usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, ep01_cb);
653 usbd_ep_setup(dev, 0x82, USB_ENDPOINT_ATTR_INTERRUPT, 64, ep82_cb);
657 static void reset_cb(void)
659 debug_printf("USB: Reset\n");
661 usb_ep82_pending = 0;
664 static volatile bool usb_event_pending;
666 void usb_lp_can_rx0_isr(void)
669 * We handle USB in the main loop to avoid race conditions between
670 * USB interrupts and other code. However, we need an interrupt to
671 * up the main loop from sleep.
673 * We set up only the low-priority ISR, because high-priority ISR handles
674 * only double-buffered bulk transfers and isochronous transfers.
676 nvic_disable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
677 usb_event_pending = 1;
680 static void usb_init(void)
682 // Simulate USB disconnect
683 gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO11 | GPIO12);
684 gpio_clear(GPIOA, GPIO11 | GPIO12);
687 usbd_dev = usbd_init(
688 &st_usbfs_v1_usb_driver,
692 ARRAY_SIZE(usb_strings),
694 sizeof(usbd_control_buffer)
696 usbd_register_reset_callback(usbd_dev, reset_cb);
697 usbd_register_set_config_callback(usbd_dev, set_config_cb);
698 usb_event_pending = 1;
709 desig_get_unique_id_as_dfu(usb_serial_number);
712 debug_printf("Hail, Lord Damian! Thy BSB interface is ready.\n");
721 if (ms_ticks - last_blink >= 100) {
723 last_blink = ms_ticks;
726 if (usb_event_pending) {
728 usb_event_pending = 0;
729 nvic_clear_pending_irq(NVIC_USB_LP_CAN_RX0_IRQ);
730 nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
733 if (usb_configured) {
734 // Passing of received frames to USB
735 if (!usb_ep82_pending) {
736 if (bsb_rx_frame_len) {
737 // Received frame, possibly marked as reply
740 usbd_ep_write_packet(usbd_dev, 0x82, bsb_rx_status_and_frame, 1 + bsb_rx_frame_len);
741 usb_ep82_pending = 1;
743 bsb_rx_frame_len = 0;
744 debug_printf("USB: Sending frame to interrupt EP\n");
745 } else if (bsb_tx_result != TX_RESULT_NONE) {
746 // Only a transmission result
747 usbd_ep_write_packet(usbd_dev, 0x82, &bsb_tx_result, 1);
748 usb_ep82_pending = 1;
749 gpio_set(GPIOB, GPIO0); // Turn the TX LED off
750 debug_printf("USB: Sending status %u to interrupt EP\n", bsb_tx_result);
751 bsb_tx_result = TX_RESULT_NONE;
756 if (ms_ticks != last_step) {
757 last_step = ms_ticks;
762 wait_for_interrupt();