Failed to reconnect serial monitor after uploading on macOS

Apple Mac OSX
ag123
Posts: 624
Joined: Thu Jul 21, 2016 4:24 pm

Re: Failed to reconnect serial monitor after uploading on macOS

Post by ag123 » Sat May 13, 2017 3:56 pm

there is this post recently about including newlib nano
http://www.stm32duino.com/viewtopic.php ... =10#p27885
Dears, I was playing with the compiler/linker options (latest Maple F1 core) and it happened to me that appending "--specs=nano.specs" to the linker, of course reduced a bit the sketch size but also broke the automatic board reset on a blue pill: since that addition I had to manually reset the board in order to complete the upload..
Removing the option restored the automatic board reset feature.
Couldn't test on other boards..

Best, E.

ps: compiler version: arm-none-eabi-gcc\4.8.3-2014q1
hence you may like to update platforms.txt and exclude that --specs=nano.specs to see if it'd help

i've not reviewed the bootloader code, but i'd think dfu-util -R would set the bits in the bootloader and trigger that usb reset, usb reset is basically just pulling the D+, D- lines low for 10ms - 20ms

User avatar
RogerClark
Posts: 5897
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Failed to reconnect serial monitor after uploading on macOS

Post by RogerClark » Sat May 13, 2017 9:21 pm

Thanks

I dont know why Leaflabs chose to require DFU to send reset.

You could try changing those values reported by the bootloader, and add some code to check for a empty transmission, and seem that works on the mac

hanyazou
Posts: 40
Joined: Fri May 05, 2017 2:38 am

Re: Failed to reconnect serial monitor after uploading on macOS

Post by hanyazou » Sat May 20, 2017 5:33 am

I can't change the bitWillDetach (= 0) because bitWillDetach = 1 means the device (the bootloader in this case) have the detach-attach capability and the bootloader does not have the capability. I think it will be waste of flash memory to add the detach-attach capability. No one does like bloated bootloader.

And I've checked that libusb_reset_device() on Mac does NOT issue reset signal (Both D+ and D- lines are pulled down for 10ms). I'm sure because I've used my logic analyzer to probe USB signal on USB cable. The bootloader has done nothing wrong.

I've made new patch which adds some timeout to exit the MANIFEST_WAIT_RESET status. This works well on Linux and Mac. This mod consume 32 bytes in the binary size. (The size of generic_boot20_pc13.bin increased from 7188 to 7220 bytes.)

I'd like to send PR to the STM32-bootloader repo.

Code: Select all

diff --git a/STM32F1/binaries/generic_boot20_pc13.bin b/STM32F1/binaries/generic_boot20_pc13.bin
index 71bce95..ed49094 100644
Binary files a/STM32F1/binaries/generic_boot20_pc13.bin and b/STM32F1/binaries/generic_boot20_pc13.bin differ
diff --git a/STM32F1/dfu.c b/STM32F1/dfu.c
index 6091fe6..d4fa062 100644
--- a/STM32F1/dfu.c
+++ b/STM32F1/dfu.c
@@ -60,6 +60,7 @@ void dfuInit(void) {
     dfuAppStatus.bwPollTimeout2 = 0x00;
     dfuAppStatus.bState = dfuIDLE;
     dfuAppStatus.iString = 0x00;          /* all strings must be 0x00 until we make them! */
+    dfuAppStatus.bwWaitResetTimeout = 0;
     userFirmwareLen = 0;
     thisBlockLen = 0;;
     userAppAddr = USER_CODE_RAM; /* default RAM user code location */
@@ -275,9 +276,11 @@ bool dfuUpdateByRequest(void) {
         /* device has programmed new firmware but needs external
            usb reset or power on reset to run the new code */

-        /* consider timing out and self-resetting */
         dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;

+        /* set timeout */
+        dfuAppStatus.bwWaitResetTimeout = 500;
+
     } else if (startState == dfuUPLOAD_IDLE)         {
         /* device expecting further dfu_upload requests */

@@ -369,6 +372,9 @@ void dfuUpdateByReset(void) {
 }

 void dfuUpdateByTimeout(void) {
+    if (dfuAppStatus.bState  == dfuMANIFEST_WAIT_RESET && --dfuAppStatus.bwWaitResetTimeout == 0) {
+        systemHardReset();
+    }
 }

 u8 *dfuCopyState(u16 length) {
@@ -464,7 +470,12 @@ bool dfuUploadStarted() {
 void dfuFinishUpload() {
     while (1)
        {
+            u32 c;
+            for (c = 0; c < 9000; c++)
+                {
                __asm("nop");
+            }
+            dfuUpdateByTimeout();

 /* Roger Clark.
        Commented out code associated with upload to RAM
diff --git a/STM32F1/dfu.h b/STM32F1/dfu.h
index d6ad1bc..70d2dc4 100644
--- a/STM32F1/dfu.h
+++ b/STM32F1/dfu.h
@@ -45,6 +45,7 @@ typedef struct _DFUStatus {
     u8 bwPollTimeout2;
     u8 bState;  /* state of device at the time the host receives the message! */
     u8 iString;
+    u32 bwWaitResetTimeout;
 } DFUStatus;

 typedef enum _PLOT {
 
I've uploaded this patch on the github also.
https://github.com/hanyazou/STM32duino- ... et_Timeout

ag123
Posts: 624
Joined: Thu Jul 21, 2016 4:24 pm

Re: Failed to reconnect serial monitor after uploading on macOS

Post by ag123 » Sat May 20, 2017 7:49 pm

it is an interesting if somewhat surprising result as pulling D+/D- pins low for 10ms (usb reset) is intended to tell the usb host controllers to start enumerating again. i'd guess i'm not too familar with these aspects but it may seem that the mac's usb controller could be buggy? well, i'm not sure too :?

User avatar
RogerClark
Posts: 5897
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Failed to reconnect serial monitor after uploading on macOS

Post by RogerClark » Sat May 20, 2017 10:43 pm

ag123 wrote:it is an interesting if somewhat surprising result as pulling D+/D- pins low for 10ms (usb reset) is intended to tell the usb host controllers to start enumerating again. i'd guess i'm not too familar with these aspects but it may seem that the mac's usb controller could be buggy? well, i'm not sure too :?

From what I recall the bootloader pulls USB D+ low to tell the host it wants to reset the USB bus.

I was not aware of a sequence from the host to reset the periheral.

hanyazou
Posts: 40
Joined: Fri May 05, 2017 2:38 am

Re: Failed to reconnect serial monitor after uploading on macOS

Post by hanyazou » Sun May 21, 2017 1:39 am

ag123 wrote:it is an interesting if somewhat surprising result as pulling D+/D- pins low for 10ms (usb reset) is intended to tell the usb host controllers to start enumerating again.
:??

The blue-pill is just waiting for usb reset, which should be issued by Mac's host controller.
dfu-util calls libusb_reset_device() to issue usb reset.

User avatar
RogerClark
Posts: 5897
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Failed to reconnect serial monitor after uploading on macOS

Post by RogerClark » Sun May 21, 2017 6:59 am

I thought the bootloader was waiting for the DFU reset command, rather than some generic USB reset caused by pulling D+ and D- low

hanyazou
Posts: 40
Joined: Fri May 05, 2017 2:38 am

Re: Failed to reconnect serial monitor after uploading on macOS

Post by hanyazou » Sun May 21, 2017 7:59 am

RogerClark wrote:I thought the bootloader was waiting for the DFU reset command, rather than some generic USB reset caused by pulling D+ and D- low
Please refer the state machine which described in STM32duino-bootloader/STM32F1/dfu.c.
I think the final status of downloading is the MANIFEST_WAIT_RESET status. Once the bootloader enter that MANIFEST_WAIT_RESET status, it may not change the status from MANIFEST_WAIT_RESET and wait for USB reset interruption forever. Please see the code of the state machine and dfuUpdateByReset() in dfu.c. The systemHardReset() should be called from dfuUpdateByReset(). But it may not be called if host does not signal usb reset in the MANIFEST_WAIT_RESET status.

Code: Select all

    } else if (startState == dfuMANIFEST_WAIT_RESET) {
        /* device has programmed new firmware but needs external                                                                                                                                                        
           usb reset or power on reset to run the new code */

        dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;

Code: Select all

void dfuUpdateByReset(void) {
    u8 startState = dfuAppStatus.bState;
    userFirmwareLen = 0;

    if (startState == appDETACH) {
        dfuAppStatus.bState = dfuIDLE;
	dfuAppStatus.bStatus = OK;

        nvicDisableInterrupts();
	usbEnbISR();

    } else if (startState == appIDLE || startState == dfuIDLE) {
	/* do nothing...might be normal usb bus activity */
    } else {
        /* we reset from the dfu, reset everything and startover,                                                                                                                                                       
           which is the correct operation if this is an erroneous                                                                                                                                                       
           event or properly following a MANIFEST */
        dfuAppStatus.bState = dfuIDLE;
        dfuAppStatus.bStatus = OK;

        systemHardReset();
    }
}

kamilo
Posts: 1
Joined: Wed May 24, 2017 9:29 pm

Re: Failed to reconnect serial monitor after uploading on macOS

Post by kamilo » Wed May 24, 2017 9:43 pm

I've tried your patch hanyazou, but unfortunately it doesn't seem to work for me. The board won't reset after sketch upload.
hanyazou wrote:I can't change the bitWillDetach (= 0) because bitWillDetach = 1 means the device (the bootloader in this case) have the detach-attach capability and the bootloader does not have the capability. I think it will be waste of flash memory to add the detach-attach capability. No one does like bloated bootloader.

And I've checked that libusb_reset_device() on Mac does NOT issue reset signal (Both D+ and D- lines are pulled down for 10ms). I'm sure because I've used my logic analyzer to probe USB signal on USB cable. The bootloader has done nothing wrong.

I've made new patch which adds some timeout to exit the MANIFEST_WAIT_RESET status. This works well on Linux and Mac. This mod consume 32 bytes in the binary size. (The size of generic_boot20_pc13.bin increased from 7188 to 7220 bytes.)

I'd like to send PR to the STM32-bootloader repo.

Code: Select all

diff --git a/STM32F1/binaries/generic_boot20_pc13.bin b/STM32F1/binaries/generic_boot20_pc13.bin
index 71bce95..ed49094 100644
Binary files a/STM32F1/binaries/generic_boot20_pc13.bin and b/STM32F1/binaries/generic_boot20_pc13.bin differ
diff --git a/STM32F1/dfu.c b/STM32F1/dfu.c
index 6091fe6..d4fa062 100644
--- a/STM32F1/dfu.c
+++ b/STM32F1/dfu.c
@@ -60,6 +60,7 @@ void dfuInit(void) {
     dfuAppStatus.bwPollTimeout2 = 0x00;
     dfuAppStatus.bState = dfuIDLE;
     dfuAppStatus.iString = 0x00;          /* all strings must be 0x00 until we make them! */
+    dfuAppStatus.bwWaitResetTimeout = 0;
     userFirmwareLen = 0;
     thisBlockLen = 0;;
     userAppAddr = USER_CODE_RAM; /* default RAM user code location */
@@ -275,9 +276,11 @@ bool dfuUpdateByRequest(void) {
         /* device has programmed new firmware but needs external
            usb reset or power on reset to run the new code */

-        /* consider timing out and self-resetting */
         dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;

+        /* set timeout */
+        dfuAppStatus.bwWaitResetTimeout = 500;
+
     } else if (startState == dfuUPLOAD_IDLE)         {
         /* device expecting further dfu_upload requests */

@@ -369,6 +372,9 @@ void dfuUpdateByReset(void) {
 }

 void dfuUpdateByTimeout(void) {
+    if (dfuAppStatus.bState  == dfuMANIFEST_WAIT_RESET && --dfuAppStatus.bwWaitResetTimeout == 0) {
+        systemHardReset();
+    }
 }

 u8 *dfuCopyState(u16 length) {
@@ -464,7 +470,12 @@ bool dfuUploadStarted() {
 void dfuFinishUpload() {
     while (1)
        {
+            u32 c;
+            for (c = 0; c < 9000; c++)
+                {
                __asm("nop");
+            }
+            dfuUpdateByTimeout();

 /* Roger Clark.
        Commented out code associated with upload to RAM
diff --git a/STM32F1/dfu.h b/STM32F1/dfu.h
index d6ad1bc..70d2dc4 100644
--- a/STM32F1/dfu.h
+++ b/STM32F1/dfu.h
@@ -45,6 +45,7 @@ typedef struct _DFUStatus {
     u8 bwPollTimeout2;
     u8 bState;  /* state of device at the time the host receives the message! */
     u8 iString;
+    u32 bwWaitResetTimeout;
 } DFUStatus;

 typedef enum _PLOT {
 
I've uploaded this patch on the github also.
https://github.com/hanyazou/STM32duino- ... et_Timeout

User avatar
RogerClark
Posts: 5897
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Failed to reconnect serial monitor after uploading on macOS

Post by RogerClark » Wed May 24, 2017 9:47 pm

Have you tried a variation of @danieleff's suggestion, as posted to the PR by @ag123 ( on github ) ?

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest