Skip to main content
Visitor II
September 14, 2019
Question

Serial programming STM32F446 using ESP32-Wroom

  • September 14, 2019
  • 3 replies
  • 4325 views

The question gives away most of what I am trying to accomplish. I got a project for which I need to update the code/firmware and to test what I do. I have a device (PCB with peripherals).

How things are connected?

I have an ESP32-Wroom which is like the main MCU and it talks to most peripherals and an onboard STM32F446RETx MCU. GPIO25 and GPIO26 of the ESP32 connect with PA9 and PA10 forming a serial connection. I have an onboard jumper that I can use to tap into PA9 and PA10 in addition to another pin duo that I can use to hear Serial of the ESP32. I also have another pin duo that I can use to connect ST-Link SWD with STM32 as well. In case you got distracted about what I am trying to do, I only want to serially program the STM32 using ESP32.

What does the code that I have do?

The ESP32 code sets the BOOT0 to high and BOOT1 to low before starting Serial1 connection (using IO25 IO26) using even parity and 1 stop bit as per the ST guidelines. Then comes the part of initiating the handshake Serial1.write(0x7f) with hope of getting 0x79. However, the response I get is neither NACK (0x1f) nor BUSY (0x76), and it not an ACK either in case you wanted to read things explicitly.

What did I do next?

The PCB has a jumper that allows me tap into PA9 and PA10 connections of STM so I just put the BOOT pins in pattern 1 (as per AN2606 or whatever application note has the pattern) and try using stm32flash to get the chip information but nothing comes from the STM.

I would really like to know if there is something that I can do to salvage the situation. Feel free to ask follow up questions for clarity.

Edit 1: Added ESP32 code responsible for the handshake

int STM32BL_Init(void)
{
 bool status = false;
 
 pinMode(STM_BOOT_0, OUTPUT);
 pinMode(STM_BOOT_1, OUTPUT);
 
 // Configure USART
 Serial1.end();
 Serial.println("Restarting UART1");
 delay(100);
 Serial1.begin(9600, SERIAL_8E1, 25, 26); // UART1
 Serial1.setTimeout(1000);
 delay(100);
 
 // Activate pattern 1
 Serial.println("Activating pattern 1");
 digitalWrite(STM_BOOT_0, HIGH);
 digitalWrite(STM_BOOT_1, LOW);
 
 // Send handshake byte and look for ACK 
 int retries = 10;
 if (Serial1.available()) Serial1.write(STM32_CMD_INIT);
 else
 {
 Serial.println("Serial1 not available"); 
 }
 char ack;// = (char)Serial1.read();
 while (((ack = (char) Serial1.read()) != STM32_ACK) && retries > 0)
 {
 Serial.println("Handshake failed!");
 printf("Received %x\n", ack);
 //ack = (char) Serial.read();
 delay(50);
 retries--;
 }
 flash_ptr = 0x08008000;
 return status;
}

    This topic has been closed for replies.

    3 replies

    Graduate II
    September 14, 2019

    Sounds reasonable enough.

    The loader is highly intolerant of noise on the interface, the first thing it needs to hear is the 0x7F pattern at 8E1, you get one shot at this, and then you're in the loader. If you get an ACK/NACK response you can try sending other commands. If you get some other response, look at that with a scope, it is likely 0x79 with an alternate bit-timing, as the 0x7F pattern is measured by a TIM to compute the baud rate.

    FahadAuthor
    Visitor II
    September 14, 2019

    Don't have scope to test but I do know for fact that my usual/routine serial connection between the two MCUs is working reasonably at 115200N1. However, to be on safe side, I Serial1.end() it before Serail1.begin(115200, SERIAL_8E1, 25, 26). I am guessing that it is not the noise because if it were then why other/routine communication on the same pin duo would work? By the way, I have tried 9600 baud rate as well but nothing with that as well.

    Graduate II
    September 14, 2019

    I would send a character at 9600 8E1, reset the STM32 with BOOT0/BOOT1 configured, wait for say 100 ms, then send the 0x7F pattern.

    The AN2606 indicates all the interfaces the loader is listening too, these would need to be silent also. The noise, or glitches, I talk about in this context is any pin transition that can be interpreted as a connection request, on any of the interfaces the loader is watching for.

    I think the F4 methods to jump into the ROM loader for an application would work on the F446.

    FahadAuthor
    Visitor II
    September 14, 2019

    I have updated my original question with the code that (to some extent) follows your suggestion but to no avail.

    FahadAuthor
    Visitor II
    September 14, 2019

    Hmm, actually STM32 is not listening to anything but is merely connected with a circuitry to read data from RFID access cards. However, there is one debug message that it seems to be constantly writing/transmitting (again not listening) on PA9/PA10 serial port. I also don't think that we have means to disable/reset STM32 using ESP32 on our PCB. I can try changing the order of things to Serial1.begin(9600, SERIAL_8E1), activation of pattern 1 on boot pins followed by 0x7f pattern. I doubt that this might make much of a difference but I am getting a wee bit desperate to not ignore it :squinting_face_with_tongue: