diff --git a/stm32f103t8u6/build_number.txt b/stm32f103t8u6/build_number.txt index ec9163d..6fa50e7 100644 --- a/stm32f103t8u6/build_number.txt +++ b/stm32f103t8u6/build_number.txt @@ -1 +1 @@ -352 +353 diff --git a/stm32f103t8u6/src/hpgl.c b/stm32f103t8u6/src/hpgl.c index c198c0e..9c0d593 100644 --- a/stm32f103t8u6/src/hpgl.c +++ b/stm32f103t8u6/src/hpgl.c @@ -2,6 +2,7 @@ #include "usb_cdc.h" #include "pwm_output.h" #include "led.h" +#include "system.h" unsigned int HPGL_ParseErrorCounter = 0; @@ -12,6 +13,7 @@ typedef enum // First byte of instruction has been received, waiting for second one HPGL_Parser_ReceivingInstruction, + HPGL_Parser_ReceivingDeviceControl, // Receiving the pen number (currently ignored) HPGL_Parser_ReceivingPenNumber, @@ -77,6 +79,12 @@ void HPGL_Poll(void) // First character of all supported instructions state = HPGL_Parser_ReceivingInstruction; } + else if(character == 27) + { + // Found a device control instruction, which always starts with + // ESC + state = HPGL_Parser_ReceivingDeviceControl; + } else { // Unsupported command @@ -118,6 +126,25 @@ void HPGL_Poll(void) default: // Unsupported instruction + HPGL_ParseErrorCounter++; + state = HPGL_Parser_Error; + break; + } + break; + + case HPGL_Parser_ReceivingDeviceControl: + switch(character) + { + case 'B': + // Reset into bootloader + LED_On(LED_Orange); + LED_On(LED_Pink); + System_EnterBootloader(); + break; + + default: + // Unsupported instruction + HPGL_ParseErrorCounter++; state = HPGL_Parser_Error; break; } diff --git a/stm32f103t8u6/src/system.c b/stm32f103t8u6/src/system.c new file mode 100644 index 0000000..4adc3a1 --- /dev/null +++ b/stm32f103t8u6/src/system.c @@ -0,0 +1,17 @@ +#include "system.h" +#include "usb.h" +#include "usb_util.h" + +void System_EnterBootloader(void) +{ + USB_Disable(); + USB_Delay(100000); + + // Set bootloader magic value in RTC backup register + RCC->APB1ENR |= RCC_APB1ENR_BKPEN | RCC_APB1ENR_PWREN; + PWR->CR = PWR_CR_DBP; + BKP->DR1 = 0xb007; + + // Initiate software reset + NVIC_SystemReset(); +} diff --git a/stm32f103t8u6/src/system.h b/stm32f103t8u6/src/system.h new file mode 100644 index 0000000..4008be9 --- /dev/null +++ b/stm32f103t8u6/src/system.h @@ -0,0 +1,6 @@ +#pragma once + +#include "stm32f1xx.h" + +// Immediately reset MCU and enter bootloader +void System_EnterBootloader(void); diff --git a/stm32f103t8u6/src/usb.c b/stm32f103t8u6/src/usb.c index e1184f8..fbd2035 100644 --- a/stm32f103t8u6/src/usb.c +++ b/stm32f103t8u6/src/usb.c @@ -62,6 +62,21 @@ void USB_Init(void) } +void USB_Disable(void) +{ + // Disable interrupts, force reset + USB->CNTR = USB_CNTR_FRES; + + // Clear interrupt flags + USB->ISTR = 0x00; + + // Power down + USB->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; + + // Disable D- pull-up + GPIOA->BRR = (1 << PIN_USB_PULLUP); +} + static inline void USB_HandleReset(void) { // Remove reset flag diff --git a/stm32f103t8u6/src/usb.h b/stm32f103t8u6/src/usb.h index f83ddc1..404a547 100644 --- a/stm32f103t8u6/src/usb.h +++ b/stm32f103t8u6/src/usb.h @@ -134,3 +134,4 @@ typedef void (*USB_PacketHandler_t)(int length); extern USB_PacketHandler_t USB_EP0OutPacketHandler; void USB_Init(void); +void USB_Disable(void); diff --git a/stm32f103t8u6/src/usb_vendor.c b/stm32f103t8u6/src/usb_vendor.c index 3d56a64..ef41a90 100644 --- a/stm32f103t8u6/src/usb_vendor.c +++ b/stm32f103t8u6/src/usb_vendor.c @@ -1,4 +1,5 @@ #include "usb_vendor.h" +#include "system.h" void USBVendor_HandleDeviceSetup(USB_SetupPacket_t *sp, const void **reply_data, int *reply_length, uint8_t *reply_response) @@ -14,6 +15,11 @@ void USBVendor_HandleDeviceSetup(USB_SetupPacket_t *sp, *reply_response = USB_EP_TX_VALID; break; + case USB_VENDOR_COMMAND_ENTER_BOOTLOADER: + *reply_response = USB_EP_TX_VALID; + System_EnterBootloader(); + break; + default: *reply_response = USB_EP_TX_STALL; } diff --git a/stm32f103t8u6/src/usb_vendor.h b/stm32f103t8u6/src/usb_vendor.h index 42c3b5d..b7153d4 100644 --- a/stm32f103t8u6/src/usb_vendor.h +++ b/stm32f103t8u6/src/usb_vendor.h @@ -5,6 +5,7 @@ typedef enum { USB_VENDOR_COMMAND_NOP = 0x00, + USB_VENDOR_COMMAND_ENTER_BOOTLOADER = 0xb0, } USBVendor_Command_t; void USBVendor_HandleDeviceSetup(USB_SetupPacket_t *sp,