Skip to main content
mwalt.3
Associate III
March 24, 2026
Solved

STM32G431 USB dfu , CAN bus , PB8 and nSWBOOT0

  • March 24, 2026
  • 4 replies
  • 425 views

The problem is that the transceiver will set the RX pin high at boot , this will put the G431 in boot mode and never start . The question is how to set and reset the nSWBOOT0 bit in the program . I mean , if I am right ::
2) at setup (yes , Arduino) , the nSWBOOT0 bit is set in order to disable BOOT0 pin , thus allow normal (CAN bus) operation after boot  on PB8 .

1) but this will reset the STM32 , so before doing 2) , one need to read the level of nSWBOOT0 , and only set it if it is 0 . (one time action)

3) but this will brick the DFU uploading . To reset this , for exemple by a customer In order to update the firmware , one have to reset the nSWBOOT0 by the program . This could be done by a button , or by a code received trough USB .

Hope this is clear enough (and correct of course) . But doing this is not that simple for me , so I wonder if there is a working code available for this (sure , some people have done the trick successfully ) ?
Thank you !

Edit : correct name = nSWBOOT0 bit

Best answer by mwalt.3

I finally found the right code here : https://github.com/T-K-233/Notes/blob/main/stm32/misc/changing-stm32-default-boot-option.md

I have modified it , in order to allow to clear or to set the nSWBOOT0 bit .

It is Arduino code , I hope it isn't an issue ; 2 things one need to watch out for :

- avoid unwanted call to the function (that modifies the nSWBOOT0 bit , or anything in the flash domain)

- avoid to catch the function in an infinite loop , this may destroy the device

#define LED PC6

String ze_string;

void setup() {
 Serial.begin(115200); // USB CDC
 pinMode(LED, OUTPUT);
 while (!Serial) { // wait for USB CDC → ok
 delay(50);
 }

 // if not cleard , clear the nSWBOOT0 in the setup , in order to allow normal CAN operation
 Serial.print("FLASH->OPTR before setup: ");
 Serial.println(FLASH->OPTR, HEX);
 if (FLASH->OPTR |= FLASH_OPTR_nSWBOOT0) { // is nSWBOOT0 set ?
 set_clear_nSWBOOT0(false); // then clear it
 digitalWrite(LED, HIGH);
 }
 Serial.print("FLASH->OPTR after setup , must be FBEFF8AA : ");
 Serial.println(FLASH->OPTR, HEX);
}

void loop() {
 while (Serial.available()) {
 ze_string = Serial.readString(); // read the incoming data as string
 Serial.print(" Serial: ");
 Serial.println(ze_string);

 if (ze_string.equals("Please dear STM32 , would you be so kind and allow BOOT0 pin to be in use , thank you !")) {
 if ((FLASH->OPTR & FLASH_OPTR_nSWBOOT0) == 0) { // isn't nSWBOOT0 set ?
 set_clear_nSWBOOT0(true); // then set it
 Serial.println(FLASH->OPTR, HEX);
 Serial.println(" : FFEFF8AA → BOOT0 pin in use , please cycle STM32 before uploading in DFU mode");
 digitalWrite(LED, LOW);
 }
 }
 }
 Serial.print("i"); /// debug
 Serial.println(FLASH->OPTR, HEX); /// debug
 delay(500); /// debug
}

// https://github.com/T-K-233/Notes/blob/main/stm32/misc/changing-stm32-default-boot-option.md
void set_clear_nSWBOOT0(bool set_nSWBOOT0) {
 // 1. Unlock the FLASH_CR with the LOCK clearing sequence
 // Check that no Flash memory operation is on going by checking the BSY bit in the Flash status register (FLASH_SR).
 while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {}
 HAL_FLASH_Unlock();

 // 2. Unlock the FLASH Option Byte with the LOCK clearing sequence
 // Check that no Flash memory operation is on going by checking the BSY bit in the Flash status register (FLASH_SR).
 while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {}
 HAL_FLASH_OB_Unlock();

 // 3. program OPTR
 if (set_nSWBOOT0) { // → set nSWBOOT0 bit
 if (FLASH->OPTR | FLASH_OPTR_nSWBOOT0) // is nSWBOOT0 set ?
 FLASH->OPTR |= FLASH_OPTR_nSWBOOT0; // default to boot according BOOT0 pin
 } else { // → clear nSWBOOT0 bit
 if (FLASH->OPTR | FLASH_OPTR_nSWBOOT0 == 0) // isn't nSWBOOT0 set ?
 FLASH->OPTR &= ~FLASH_OPTR_nSWBOOT0; // default to boot from flash
 }

 // 4. Set the Options Start bit OPTSTRT in the Flash control register (FLASH_CR).
 SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);

 // 4.1 clear status register
 SET_BIT(FLASH->SR, FLASH_SR_OPTVERR | FLASH_SR_RDERR);

 // 5. Wait for the BSY bit to be cleared.
 while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {}

 // 6. Lock Flash
 // If LOCK is set by software, OPTLOCK is automatically set too
 HAL_FLASH_Lock();

 // 7. reload the new settings
 // seems this line will cause error when put before FLASH_Lock(), which will then corrupt all Flash settings
 // so putting it here
 // can also comment out this line and just power cycle to update the flash settings
 HAL_FLASH_OB_Launch();
}

4 replies

Technical Moderator
March 24, 2026

Hi @mwalt.3 

You can disable the hardware BOOT0 pin. When nSWBOOT0 = 1, the MCU no longer samples the BOOT0 pin at reset and PB8 is free to be used as CAN RX without affecting the boot mode.

Disabling the BOOT0 pindoes not remove the bootloader, it only removes the BOOT0 pin high at reset entry. You can still implement jump to system memory bootloader from your firmware as documented in AN2606.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.Best regards,FBL
mwalt.3
mwalt.3Author
Associate III
March 24, 2026

Thank you FBL ,

yes , it is what I meant , but my question is more : how can I do  nSWBoot0(bit) = 1 or nSWBoot0(bit) = 0 ?

It is not that obvious , because this bit is in flash , witch has special access . AN2606 doesn't give any indication for how to set or reset this bit ...

Technical Moderator
March 27, 2026

Hi @mwalt.3 

To set nSWBOOT0 bit to 1 or 0, you need to modify the option bytes. This is typically done using STM32CubeProgrammer. Attached screenshot from STM32CubeProgrammer. 

I hope this helps.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.Best regards,FBL
mwalt.3
mwalt.3Author
Associate III
March 29, 2026

yes , but I want to set nSWBoot0 bit , or reset it , through the firmware , and still looking for a beginning of a piece of code for this

MHoll.2
Senior III
March 28, 2026

The placement of the CAN_RX pin on the BOOT0 pin was a very bad design decision by ST on this MCU.

Se how others have worked around the problem:

https://github.com/makerbase-mks/CANable-MKS/blob/main/Hardware/MKS%20CANable%20V2.0/MKS%20CANable%20V2.0_001%20schematic.pdf

This results in:

Running application when powered on, but run bootloader when switched off-on fast. (C7 remains charged)

mwalt.3
mwalt.3Author
Associate III
March 28, 2026
Hi @MHoll.2 , I don't understand the role of C7 , did you mean C3 ?
 
MHoll.2
Senior III
March 28, 2026

Yes C3, sorry

mwalt.3
mwalt.3AuthorBest answer
Associate III
March 30, 2026

I finally found the right code here : https://github.com/T-K-233/Notes/blob/main/stm32/misc/changing-stm32-default-boot-option.md

I have modified it , in order to allow to clear or to set the nSWBOOT0 bit .

It is Arduino code , I hope it isn't an issue ; 2 things one need to watch out for :

- avoid unwanted call to the function (that modifies the nSWBOOT0 bit , or anything in the flash domain)

- avoid to catch the function in an infinite loop , this may destroy the device

#define LED PC6

String ze_string;

void setup() {
 Serial.begin(115200); // USB CDC
 pinMode(LED, OUTPUT);
 while (!Serial) { // wait for USB CDC → ok
 delay(50);
 }

 // if not cleard , clear the nSWBOOT0 in the setup , in order to allow normal CAN operation
 Serial.print("FLASH->OPTR before setup: ");
 Serial.println(FLASH->OPTR, HEX);
 if (FLASH->OPTR |= FLASH_OPTR_nSWBOOT0) { // is nSWBOOT0 set ?
 set_clear_nSWBOOT0(false); // then clear it
 digitalWrite(LED, HIGH);
 }
 Serial.print("FLASH->OPTR after setup , must be FBEFF8AA : ");
 Serial.println(FLASH->OPTR, HEX);
}

void loop() {
 while (Serial.available()) {
 ze_string = Serial.readString(); // read the incoming data as string
 Serial.print(" Serial: ");
 Serial.println(ze_string);

 if (ze_string.equals("Please dear STM32 , would you be so kind and allow BOOT0 pin to be in use , thank you !")) {
 if ((FLASH->OPTR & FLASH_OPTR_nSWBOOT0) == 0) { // isn't nSWBOOT0 set ?
 set_clear_nSWBOOT0(true); // then set it
 Serial.println(FLASH->OPTR, HEX);
 Serial.println(" : FFEFF8AA → BOOT0 pin in use , please cycle STM32 before uploading in DFU mode");
 digitalWrite(LED, LOW);
 }
 }
 }
 Serial.print("i"); /// debug
 Serial.println(FLASH->OPTR, HEX); /// debug
 delay(500); /// debug
}

// https://github.com/T-K-233/Notes/blob/main/stm32/misc/changing-stm32-default-boot-option.md
void set_clear_nSWBOOT0(bool set_nSWBOOT0) {
 // 1. Unlock the FLASH_CR with the LOCK clearing sequence
 // Check that no Flash memory operation is on going by checking the BSY bit in the Flash status register (FLASH_SR).
 while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {}
 HAL_FLASH_Unlock();

 // 2. Unlock the FLASH Option Byte with the LOCK clearing sequence
 // Check that no Flash memory operation is on going by checking the BSY bit in the Flash status register (FLASH_SR).
 while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {}
 HAL_FLASH_OB_Unlock();

 // 3. program OPTR
 if (set_nSWBOOT0) { // → set nSWBOOT0 bit
 if (FLASH->OPTR | FLASH_OPTR_nSWBOOT0) // is nSWBOOT0 set ?
 FLASH->OPTR |= FLASH_OPTR_nSWBOOT0; // default to boot according BOOT0 pin
 } else { // → clear nSWBOOT0 bit
 if (FLASH->OPTR | FLASH_OPTR_nSWBOOT0 == 0) // isn't nSWBOOT0 set ?
 FLASH->OPTR &= ~FLASH_OPTR_nSWBOOT0; // default to boot from flash
 }

 // 4. Set the Options Start bit OPTSTRT in the Flash control register (FLASH_CR).
 SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);

 // 4.1 clear status register
 SET_BIT(FLASH->SR, FLASH_SR_OPTVERR | FLASH_SR_RDERR);

 // 5. Wait for the BSY bit to be cleared.
 while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {}

 // 6. Lock Flash
 // If LOCK is set by software, OPTLOCK is automatically set too
 HAL_FLASH_Lock();

 // 7. reload the new settings
 // seems this line will cause error when put before FLASH_Lock(), which will then corrupt all Flash settings
 // so putting it here
 // can also comment out this line and just power cycle to update the flash settings
 HAL_FLASH_OB_Launch();
}