2019-09-14 06:24 AM
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;
}
2019-09-14 07:40 AM
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.
2019-09-14 07:46 AM
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.
2019-09-14 07:54 AM
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.
2019-09-14 08:02 AM
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:
2019-09-14 08:15 AM
I have updated my original question with the code that (to some extent) follows your suggestion but to no avail.
2019-09-14 09:45 AM
You don't reset the STM32 anywhere, just setting BOOT0/1 doesn't get it into loader mode, the STM32 inspects these pins only at reset
2019-09-14 10:34 AM
So, I need to reset the STM (by pulling the NRST to ground) and then do the whole pattern 1 followed by handshake? I don't do that in my code because the PCB doesn't have any pin assigned/connected for the needful.
AN2606 does start with system reset in the flowchart of section 34.2 (page 161) but isn't every boot a reset especially given that it inits the sys, USB OTG, I2C and then it goes in the loop which sort of always keeps an ear out for 0x7f. Do we really need to have that pin connection? To drive the NRST to ground sort of defeats the whole purpose of "pattern1" in my opinion.
2019-09-14 10:42 AM
pattern1 defines that the CPU boots into ROM rather than your application in FLASH, at boot time.
The alternative is that the application in the F4 already restarts itself into the ROM
Not sure how many SoC or PCB you've designed to determine how the mechanics of these things should work optimally.