STM32G431 use CAN BUS on PB8/BOOT0 pin

Related to the the forum.
Post Reply
trimarco232
Posts: 50
Joined: Wed Jul 12, 2023 11:09 am
Answers: 1

STM32G431 use CAN BUS on PB8/BOOT0 pin

Post by trimarco232 »

probably an old song : sometimes , one can run out of pins or peripherals for a given STM32 ; in my case , I want to use CAN BUS on PB8 & PB9 pins of STM32G431CBU6 , but the problem is : one have to connect PB8 to the CANRx pin of the CAN transceiver ; → the transceiver normally outputs a high value on PB8/BOOT0 pin, which will cause the STM32 to enter in DFU upload mode after reset , and no more resume normal/CAN operation .
I have spoken about this here : https://community.st.com/t5/stm32-mcus- ... d-p/887913
There is an interesting HW solution , but my project is actually prototypal , so I probably (unfortunately) will have to use the reset button , and in the case of this HW solution , the STM32 will resume in DFU upload mode , not that I want .
The SW solution I have adopted works this way :
1) at the setup , one tests the nSWBOOT0 bit in the flash . This bit in set by default (this lead the PB8 pin to enter the DFU upload mode as it is HIGH) . This is not that one need , so in this case , one call a function which clears nSWBOOT0 bit : → the STM32 will start normally , ie. it will boot from user program in flash . If the nSWBOOT0 is already cleared , → one do nothing .
2) at this point , CAN works , the STM32 works , but it is bricked , because one can no more program it through USB DFU . If one want to program it , one have to put PB8 back in BOOT0 mode , by setting again the nSWBOOT0 ; this can be done by several ways , button for example . I my case , I do this after receiving a given code from USB CDC : the function is called that will set the nSWBOOT0 bit ; after cycling the STM32 , it will enter USB DFU mode , and accept one uploading .
In any cases , one have to ensure not to catch the writing to to the flash in an (infinite) loop , this might destroy the STM32

Code: Select all

#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();
}
Post Reply

Return to “Ideas & suggestions”